diff options
Diffstat (limited to 'drivers/pci/pci.h')
-rw-r--r-- | drivers/pci/pci.h | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 34f65d69662e..4492b809094b 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -2,12 +2,15 @@ #ifndef DRIVERS_PCI_H #define DRIVERS_PCI_H +#include <linux/align.h> +#include <linux/bitfield.h> #include <linux/pci.h> struct pcie_tlp_log; /* Number of possible devfns: 0.0 to 1f.7 inclusive */ #define MAX_NR_DEVFNS 256 +#define PCI_MAX_NR_DEVS 32 #define MAX_NR_LANES 16 @@ -81,13 +84,102 @@ struct pcie_tlp_log; #define PCIE_MSG_CODE_DEASSERT_INTC 0x26 #define PCIE_MSG_CODE_DEASSERT_INTD 0x27 +#define PCI_BUS_BRIDGE_IO_WINDOW 0 +#define PCI_BUS_BRIDGE_MEM_WINDOW 1 +#define PCI_BUS_BRIDGE_PREF_MEM_WINDOW 2 + extern const unsigned char pcie_link_speed[]; extern bool pci_early_dump; +extern struct mutex pci_rescan_remove_lock; + bool pcie_cap_has_lnkctl(const struct pci_dev *dev); bool pcie_cap_has_lnkctl2(const struct pci_dev *dev); bool pcie_cap_has_rtctl(const struct pci_dev *dev); +/* Standard Capability finder */ +/** + * PCI_FIND_NEXT_CAP - Find a PCI standard capability + * @read_cfg: Function pointer for reading PCI config space + * @start: Starting position to begin search + * @cap: Capability ID to find + * @args: Arguments to pass to read_cfg function + * + * Search the capability list in PCI config space to find @cap. + * Implements TTL (time-to-live) protection against infinite loops. + * + * Return: Position of the capability if found, 0 otherwise. + */ +#define PCI_FIND_NEXT_CAP(read_cfg, start, cap, args...) \ +({ \ + int __ttl = PCI_FIND_CAP_TTL; \ + u8 __id, __found_pos = 0; \ + u8 __pos = (start); \ + u16 __ent; \ + \ + read_cfg##_byte(args, __pos, &__pos); \ + \ + while (__ttl--) { \ + if (__pos < PCI_STD_HEADER_SIZEOF) \ + break; \ + \ + __pos = ALIGN_DOWN(__pos, 4); \ + read_cfg##_word(args, __pos, &__ent); \ + \ + __id = FIELD_GET(PCI_CAP_ID_MASK, __ent); \ + if (__id == 0xff) \ + break; \ + \ + if (__id == (cap)) { \ + __found_pos = __pos; \ + break; \ + } \ + \ + __pos = FIELD_GET(PCI_CAP_LIST_NEXT_MASK, __ent); \ + } \ + __found_pos; \ +}) + +/* Extended Capability finder */ +/** + * PCI_FIND_NEXT_EXT_CAP - Find a PCI extended capability + * @read_cfg: Function pointer for reading PCI config space + * @start: Starting position to begin search (0 for initial search) + * @cap: Extended capability ID to find + * @args: Arguments to pass to read_cfg function + * + * Search the extended capability list in PCI config space to find @cap. + * Implements TTL protection against infinite loops using a calculated + * maximum search count. + * + * Return: Position of the capability if found, 0 otherwise. + */ +#define PCI_FIND_NEXT_EXT_CAP(read_cfg, start, cap, args...) \ +({ \ + u16 __pos = (start) ?: PCI_CFG_SPACE_SIZE; \ + u16 __found_pos = 0; \ + int __ttl, __ret; \ + u32 __header; \ + \ + __ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; \ + while (__ttl-- > 0 && __pos >= PCI_CFG_SPACE_SIZE) { \ + __ret = read_cfg##_dword(args, __pos, &__header); \ + if (__ret != PCIBIOS_SUCCESSFUL) \ + break; \ + \ + if (__header == 0) \ + break; \ + \ + if (PCI_EXT_CAP_ID(__header) == (cap) && __pos != start) {\ + __found_pos = __pos; \ + break; \ + } \ + \ + __pos = PCI_EXT_CAP_NEXT(__header); \ + } \ + __found_pos; \ +}) + /* Functions internal to the PCI core code */ #ifdef CONFIG_DMI @@ -330,7 +422,7 @@ struct device *pci_get_host_bridge_device(struct pci_dev *dev); void pci_put_host_bridge_device(struct device *dev); unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge); -int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type); +int pbus_reassign_bridge_resources(struct pci_bus *bus, struct resource *res); int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align); int pci_configure_extended_tags(struct pci_dev *dev, void *ign); @@ -381,6 +473,8 @@ static inline int pci_resource_num(const struct pci_dev *dev, return resno; } +struct resource *pbus_select_window(struct pci_bus *bus, + const struct resource *res); void pci_reassigndev_resource_alignment(struct pci_dev *dev); void pci_disable_bridge_window(struct pci_dev *dev); struct pci_bus *pci_bus_get(struct pci_bus *bus); |