Will add addon_resources list in pci_dev, it will be used for resources other than standard, rom, sriov, bridges. Some could be same as std reg, but using different register. Some could have own way to read/write to them. Kernel using different way to hack those resources like abusing pci bridge resource spot on non bridge pci device. With this patch, will treat addon-resource like standard resource with special ops. Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> --- drivers/pci/probe.c | 18 ++++++++++++++++++ include/linux/pci.h | 16 ++++++++++++++++ 2 files changed, 34 insertions(+), 0 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index dfa56fb..6dbad5b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -82,6 +82,12 @@ struct resource *pci_dev_resource_n(struct pci_dev *dev, int n) if (n < PCI_NUM_RESOURCES) return &dev->resource[n]; + n -= PCI_NUM_RESOURCES; + list_for_each_entry(addon_res, &dev->addon_resources, list) { + if (n-- == 0) + return &addon_res->res; + } + return NULL; } @@ -97,6 +103,16 @@ int pci_dev_resource_idx(struct pci_dev *dev, struct resource *res) return -1; } +static void pci_release_dev_addon_res(struct pci_dev *dev) +{ + struct pci_dev_addon_resource *addon_res, *tmp; + + list_for_each_entry_safe(addon_res, tmp, &dev->addon_resources, list) { + list_del(&addon_res->list); + kfree(addon_res); + } +} + static u64 pci_size(u64 base, u64 maxbase, u64 mask) { u64 size = mask & maxbase; /* Find the significant bits */ @@ -1288,6 +1304,7 @@ static void pci_release_dev(struct device *dev) pci_dev = to_pci_dev(dev); pci_release_capabilities(pci_dev); pci_release_of_node(pci_dev); + pci_release_dev_addon_res(pci_dev); kfree(pci_dev); } @@ -1367,6 +1384,7 @@ struct pci_dev *alloc_pci_dev(void) return NULL; INIT_LIST_HEAD(&dev->bus_list); + INIT_LIST_HEAD(&dev->addon_resources); return dev; } diff --git a/include/linux/pci.h b/include/linux/pci.h index c7a2806..2c8b1a4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -299,6 +299,7 @@ struct pci_dev { */ unsigned int irq; struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */ + struct list_head addon_resources; /* addon I/O and memory resource */ /* These fields are used by common fixups */ unsigned int transparent:1; /* Transparent PCI bridge */ @@ -347,6 +348,21 @@ struct pci_dev { #endif }; +struct resource_ops { + int (*read)(struct pci_dev *dev, struct resource *res, int addr); + int (*write)(struct pci_dev *dev, struct resource *res, int addr); +}; + +struct pci_dev_addon_resource { + struct list_head list; + int reg_addr; + int size; + struct resource res; + struct resource_ops *ops; +}; +#define to_pci_dev_addon_resource(n) \ + container_of(n, struct pci_dev_addon_resource, res) + struct resource *pci_dev_resource_n(struct pci_dev *dev, int n); int pci_dev_resource_idx(struct pci_dev *dev, struct resource *res); -- 1.7.7 -- 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