From: Ram Pai <linuxram@xxxxxxxxxx> Currently pci_dev structure holds an array of 17 PCI resources; six base BARs, one ROM BAR, four BRIDGE BARs, six sriov BARs. This is wasteful. A bridge device just needs the 4 bridge resources. A non-bridge device just needs the six base resources and one ROM resource. The sriov resources are needed only if the device has SRIOV capability. The pci_dev structure needs to be re-organized to avoid unnecessary bloating. However too much code outside the pci-bus driver, assumes the internal details of the pci_dev structure, thus making it hard to re-organize the datastructure. As a first step this patch provides generic methods to access the resource structure of the pci_dev. Finally we can re-organize the resource structure in the pci_dev structure and correspondingly update the methods. -v2: Consolidated iterator interface as per Bjorn's suggestion. -v3: Add the idx back - Yinghai Lu -v7: Change to use bitmap for searching - Yinghai Lu -v8: Fix acpiphp module compiling error that is found by Steven Newbury <steve@xxxxxxxxxxxxxxx> - Yinghai Lu -v9: According to Bjorn, remove PCI_NO_... that is too confusing - Yinghai Lu Signed-off-by: Ram Pai <linuxram@xxxxxxxxxx> Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> --- drivers/pci/probe.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 24 ++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 1df75f7..ac751a6 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -123,6 +123,54 @@ int pci_dev_resource_idx(struct pci_dev *dev, struct resource *res) return -1; } +static void __init_res_idx_mask(unsigned long *mask, int flag) +{ + bitmap_zero(mask, PCI_NUM_RESOURCES); + if (flag & PCI_STD_RES) + bitmap_set(mask, PCI_STD_RESOURCES, + PCI_STD_RESOURCE_END - PCI_STD_RESOURCES + 1); + if (flag & PCI_ROM_RES) + bitmap_set(mask, PCI_ROM_RESOURCE, 1); +#ifdef CONFIG_PCI_IOV + if (flag & PCI_IOV_RES) + bitmap_set(mask, PCI_IOV_RESOURCES, + PCI_IOV_RESOURCE_END - PCI_IOV_RESOURCES + 1); +#endif + if (flag & PCI_BRIDGE_RES) + bitmap_set(mask, PCI_BRIDGE_RESOURCES, + PCI_BRIDGE_RESOURCE_END - PCI_BRIDGE_RESOURCES + 1); +} + +static DECLARE_BITMAP(res_idx_mask[1 << PCI_RES_BLOCK_NUM], PCI_NUM_RESOURCES); +static int __init pci_res_idx_mask_init(void) +{ + int i; + + for (i = 0; i < (1 << PCI_RES_BLOCK_NUM); i++) + __init_res_idx_mask(res_idx_mask[i], i); + + return 0; +} +postcore_initcall(pci_res_idx_mask_init); + +static inline unsigned long *get_res_idx_mask(int flag) +{ + return res_idx_mask[flag & ((1 << PCI_RES_BLOCK_NUM) - 1)]; +} + +int pci_next_resource_idx(int i, int flag) +{ + i++; + if (i < PCI_NUM_RESOURCES) + i = find_next_bit(get_res_idx_mask(flag), PCI_NUM_RESOURCES, i); + + if (i < PCI_NUM_RESOURCES) + return i; + + return -1; +} +EXPORT_SYMBOL(pci_next_resource_idx); + static u64 pci_size(u64 base, u64 maxbase, u64 mask) { u64 size = mask & maxbase; /* Find the significant bits */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 14b7de4..044c474 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -379,6 +379,30 @@ struct pci_dev { struct resource *pci_dev_resource_n(struct pci_dev *dev, int n); int pci_dev_resource_idx(struct pci_dev *dev, struct resource *res); +#define PCI_STD_RES (1<<0) +#define PCI_ROM_RES (1<<1) +#define PCI_IOV_RES (1<<2) +#define PCI_BRIDGE_RES (1<<3) +#define PCI_RES_BLOCK_NUM 4 + +#define PCI_ALL_RES (PCI_STD_RES | PCI_ROM_RES | PCI_BRIDGE_RES | PCI_IOV_RES) +#define PCI_ROM_IOV_BRIDGE_RES (PCI_ROM_RES | PCI_BRIDGE_RES | PCI_IOV_RES) +#define PCI_STD_ROM_BRIDGE_RES (PCI_STD_RES | PCI_ROM_RES | PCI_BRIDGE_RES) +#define PCI_STD_IOV_BRIDGE_RES (PCI_STD_RES | PCI_IOV_RES | PCI_BRIDGE_RES) +#define PCI_STD_ROM_IOV_RES (PCI_STD_RES | PCI_ROM_RES | PCI_IOV_RES) +#define PCI_STD_ROM_RES (PCI_STD_RES | PCI_ROM_RES) +#define PCI_STD_IOV_RES (PCI_STD_RES | PCI_IOV_RES) +#define PCI_STD_ROM_IOV_RES (PCI_STD_RES | PCI_ROM_RES | PCI_IOV_RES) + +int pci_next_resource_idx(int i, int flag); + +#define for_each_pci_resource(dev, res, i, flag) \ + for (i = pci_next_resource_idx(-1, flag), \ + res = pci_dev_resource_n(dev, i); \ + res; \ + i = pci_next_resource_idx(i, flag), \ + res = pci_dev_resource_n(dev, i)) + static inline struct pci_dev *pci_physfn(struct pci_dev *dev) { #ifdef CONFIG_PCI_IOV -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html