From b26b2d494b659f988b4d75eb394dfa0ddac415c9 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Fri, 1 Jan 2010 17:40:49 +0100 Subject: resource/PCI: align functions now return start of resource As suggested by Linus, align functions should return the start of a resource, not void. An update of "res->start" is no longer necessary. Cc: Bjorn Helgaas Cc: Yinghai Lu Signed-off-by: Dominik Brodowski Signed-off-by: Jesse Barnes --- arch/ia64/pci/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/ia64/pci/pci.c') diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index df639db779f..ef574cd311d 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -547,10 +547,11 @@ pcibios_disable_device (struct pci_dev *dev) acpi_pci_irq_disable(dev); } -void +resource_size_t pcibios_align_resource (void *data, struct resource *res, resource_size_t size, resource_size_t align) { + return res->start; } /* -- cgit v1.2.3-70-g09d2 From 3b7a17fcdae532d29dffab9d564a28be08960988 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Fri, 1 Jan 2010 17:40:50 +0100 Subject: resource/PCI: mark struct resource as const Now that we return the new resource start position, there is no need to update "struct resource" inside the align function. Therefore, mark the struct resource as const. Cc: Bjorn Helgaas Cc: Yinghai Lu Signed-off-by: Dominik Brodowski Signed-off-by: Jesse Barnes --- arch/alpha/kernel/pci.c | 2 +- arch/arm/kernel/bios32.c | 2 +- arch/cris/arch-v32/drivers/pci/bios.c | 2 +- arch/frv/mb93090-mb00/pci-frv.c | 2 +- arch/ia64/pci/pci.c | 2 +- arch/mips/pci/pci.c | 2 +- arch/mips/pmc-sierra/yosemite/ht.c | 2 +- arch/mn10300/unit-asb2305/pci-asb2305.c | 2 +- arch/parisc/kernel/pci.c | 2 +- arch/powerpc/kernel/pci-common.c | 2 +- arch/sh/drivers/pci/pci.c | 2 +- arch/sparc/kernel/pci.c | 2 +- arch/sparc/kernel/pcic.c | 2 +- arch/x86/pci/i386.c | 2 +- arch/xtensa/kernel/pci.c | 4 ++-- drivers/pci/bus.c | 2 +- drivers/pcmcia/rsrc_mgr.c | 3 ++- drivers/pcmcia/rsrc_nonstatic.c | 6 +++--- include/linux/ioport.h | 2 +- include/linux/pci.h | 5 +++-- kernel/resource.c | 4 ++-- 21 files changed, 28 insertions(+), 26 deletions(-) (limited to 'arch/ia64/pci/pci.c') diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 5cf111ed851..c9ab94ee1ca 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -127,7 +127,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final); #define GB (1024*MB) resource_size_t -pcibios_align_resource(void *data, struct resource *res, +pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index a7c85f84f06..bd397e0b663 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -616,7 +616,7 @@ char * __init pcibios_setup(char *str) * but we want to try to avoid allocating at 0x2900-0x2bff * which might be mirrored at 0x0100-0x03ff.. */ -resource_size_t pcibios_align_resource(void *data, struct resource *res, +resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { resource_size_t start = res->start; diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c index 5811e2f8945..d4b9c36ddc0 100644 --- a/arch/cris/arch-v32/drivers/pci/bios.c +++ b/arch/cris/arch-v32/drivers/pci/bios.c @@ -42,7 +42,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, } resource_size_t -pcibios_align_resource(void *data, struct resource *res, +pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { resource_size_t start = res->start; diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c index c947aa43f2a..1ed15d7fea2 100644 --- a/arch/frv/mb93090-mb00/pci-frv.c +++ b/arch/frv/mb93090-mb00/pci-frv.c @@ -33,7 +33,7 @@ * which might have be mirrored at 0x0100-0x03ff.. */ resource_size_t -pcibios_align_resource(void *data, struct resource *res, +pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { resource_size_t start = res->start; diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index ef574cd311d..783c83bb2b4 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -548,7 +548,7 @@ pcibios_disable_device (struct pci_dev *dev) } resource_size_t -pcibios_align_resource (void *data, struct resource *res, +pcibios_align_resource (void *data, const struct resource *res, resource_size_t size, resource_size_t align) { return res->start; diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 9085988f7cf..f87f5e188fa 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -50,7 +50,7 @@ static int pci_initialized; * which might have be mirrored at 0x0100-0x03ff.. */ resource_size_t -pcibios_align_resource(void *data, struct resource *res, +pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c index 5e410087b62..fd22597edb6 100644 --- a/arch/mips/pmc-sierra/yosemite/ht.c +++ b/arch/mips/pmc-sierra/yosemite/ht.c @@ -345,7 +345,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return pcibios_enable_resources(dev); } -resource_size_t pcibios_align_resource(void *data, struct resource *res, +resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c index b0b3758fba0..d6119b879a9 100644 --- a/arch/mn10300/unit-asb2305/pci-asb2305.c +++ b/arch/mn10300/unit-asb2305/pci-asb2305.c @@ -31,7 +31,7 @@ * but we want to try to avoid allocating at 0x2900-0x2bff * which might have be mirrored at 0x0100-0x03ff.. */ -resource_size_t pcibios_align_resource(void *data, struct resource *res, +resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { resource_size_t start = res->start; diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 4463a31973b..5179e5e6f8f 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -254,7 +254,7 @@ EXPORT_SYMBOL(pcibios_bus_to_resource); * Since we are just checking candidates, don't use any fields other * than res->start. */ -resource_size_t pcibios_align_resource(void *data, struct resource *res, +resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t alignment) { resource_size_t mask, align, start = res->start; diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index d7eebbaf01f..e640810e813 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1181,7 +1181,7 @@ static int skip_isa_ioresource_align(struct pci_dev *dev) * but we want to try to avoid allocating at 0x2900-0x2bff * which might have be mirrored at 0x0100-0x03ff.. */ -resource_size_t pcibios_align_resource(void *data, struct resource *res, +resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index b36ca825b3d..96213fd172c 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -148,7 +148,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) * addresses to be allocated in the 0x000-0x0ff region * modulo 0x400. */ -resource_size_t pcibios_align_resource(void *data, struct resource *res, +resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index d56c1f34689..37b66c60abe 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -722,7 +722,7 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq) { } -resource_size_t pcibios_align_resource(void *data, struct resource *res, +resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { return res->start; diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 46fda64ff16..75e88c00bca 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -768,7 +768,7 @@ char * __devinit pcibios_setup(char *str) return str; } -resource_size_t pcibios_align_resource(void *data, struct resource *res, +resource_size_t pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { return res->start; diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 924e40c916d..5a8fbf8d4ca 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -61,7 +61,7 @@ skip_isa_ioresource_align(struct pci_dev *dev) { * which might have be mirrored at 0x0100-0x03ff.. */ resource_size_t -pcibios_align_resource(void *data, struct resource *res, +pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index d7efab03164..cd102693120 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -70,8 +70,8 @@ static int pci_bus_count; * which might have be mirrored at 0x0100-0x03ff.. */ resource_size_t -pcibios_align_resource(void *data, struct resource *res, resource_size_t size, - resource_size_t align) +pcibios_align_resource(void *data, const struct resource *res, + resource_size_t size, resource_size_t align) { struct pci_dev *dev = data; resource_size_t start = res->start; diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index d29d69a3794..a26135bb0ff 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -37,7 +37,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, resource_size_t min, unsigned int type_mask, resource_size_t (*alignf)(void *, - struct resource *, + const struct resource *, resource_size_t, resource_size_t), void *alignf_data) diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index f92a2dac13a..f8401a0ef89 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -114,7 +114,8 @@ struct pcmcia_align_data { unsigned long offset; }; -static resource_size_t pcmcia_align(void *align_data, struct resource *res, +static resource_size_t pcmcia_align(void *align_data, + const struct resource *res, resource_size_t size, resource_size_t align) { struct pcmcia_align_data *data = align_data; diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index b65902870e4..45d75dc452f 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -534,7 +534,7 @@ struct pcmcia_align_data { }; static resource_size_t -pcmcia_common_align(void *align_data, struct resource *res, +pcmcia_common_align(void *align_data, const struct resource *res, resource_size_t size, resource_size_t align) { struct pcmcia_align_data *data = align_data; @@ -549,8 +549,8 @@ pcmcia_common_align(void *align_data, struct resource *res, } static resource_size_t -pcmcia_align(void *align_data, struct resource *res, resource_size_t size, - resource_size_t align) +pcmcia_align(void *align_data, const struct resource *res, + resource_size_t size, resource_size_t align) { struct pcmcia_align_data *data = align_data; struct resource_map *m; diff --git a/include/linux/ioport.h b/include/linux/ioport.h index f4195de4eb9..4a811891dbe 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -121,7 +121,7 @@ extern int allocate_resource(struct resource *root, struct resource *new, resource_size_t size, resource_size_t min, resource_size_t max, resource_size_t align, resource_size_t (*alignf)(void *, - struct resource *, + const struct resource *, resource_size_t, resource_size_t), void *alignf_data); diff --git a/include/linux/pci.h b/include/linux/pci.h index 1bd9f52b24b..449d51560fc 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -592,7 +592,7 @@ int __must_check pcibios_enable_device(struct pci_dev *, int mask); char *pcibios_setup(char *str); /* Used only when drivers/pci/setup.c is used */ -resource_size_t pcibios_align_resource(void *, struct resource *, +resource_size_t pcibios_align_resource(void *, const struct resource *, resource_size_t, resource_size_t); void pcibios_update_irq(struct pci_dev *, int irq); @@ -828,7 +828,8 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, resource_size_t min, unsigned int type_mask, - resource_size_t (*alignf)(void *, struct resource *, + resource_size_t (*alignf)(void *, + const struct resource *, resource_size_t, resource_size_t), void *alignf_data); diff --git a/kernel/resource.c b/kernel/resource.c index e697f20e228..7fd123ad00a 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -304,7 +304,7 @@ static int find_resource(struct resource *root, struct resource *new, resource_size_t size, resource_size_t min, resource_size_t max, resource_size_t align, resource_size_t (*alignf)(void *, - struct resource *, + const struct resource *, resource_size_t, resource_size_t), void *alignf_data) @@ -361,7 +361,7 @@ int allocate_resource(struct resource *root, struct resource *new, resource_size_t size, resource_size_t min, resource_size_t max, resource_size_t align, resource_size_t (*alignf)(void *, - struct resource *, + const struct resource *, resource_size_t, resource_size_t), void *alignf_data) -- cgit v1.2.3-70-g09d2 From 89a74ecccd1f78e51faf6287e5c0e93a92ac096e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 23 Feb 2010 10:24:31 -0700 Subject: PCI: add pci_bus_for_each_resource(), remove direct bus->resource[] refs No functional change; this converts loops that iterate from 0 to PCI_BUS_NUM_RESOURCES through pci_bus resource[] table to use the pci_bus_for_each_resource() iterator instead. This doesn't change the way resources are stored; it merely removes dependencies on the fact that they're in a table. Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/ia64/pci/pci.c | 5 ++--- arch/mn10300/unit-asb2305/pci.c | 6 ++---- arch/powerpc/kernel/pci-common.c | 11 ++++------- arch/powerpc/platforms/fsl_uli1575.c | 12 ++++++------ drivers/pci/bus.c | 4 ++-- drivers/pci/hotplug/shpchp_sysfs.c | 9 +++------ drivers/pci/pci.c | 5 ++--- drivers/pci/setup-bus.c | 10 ++++------ drivers/pcmcia/rsrc_nonstatic.c | 3 +-- drivers/pcmcia/yenta_socket.c | 5 +++-- include/linux/pci.h | 3 +++ 11 files changed, 32 insertions(+), 41 deletions(-) (limited to 'arch/ia64/pci/pci.c') diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 783c83bb2b4..89f957ca3eb 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -452,13 +452,12 @@ EXPORT_SYMBOL(pcibios_bus_to_resource); static int __devinit is_valid_resource(struct pci_dev *dev, int idx) { unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; - struct resource *devr = &dev->resource[idx]; + struct resource *devr = &dev->resource[idx], *busr; if (!dev->bus) return 0; - for (i=0; ibus->resource[i]; + pci_bus_for_each_resource(dev->bus, busr, i) { if (!busr || ((busr->flags ^ devr->flags) & type_mask)) continue; if ((devr->start) && (devr->start >= busr->start) && diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 2cb7e75ba1c..6d8720a0a59 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c @@ -331,12 +331,10 @@ static int __init pci_check_direct(void) static int __devinit is_valid_resource(struct pci_dev *dev, int idx) { unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; - struct resource *devr = &dev->resource[idx]; + struct resource *devr = &dev->resource[idx], *busr; if (dev->bus) { - for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - struct resource *busr = dev->bus->resource[i]; - + pci_bus_for_each_resource(dev->bus, busr, i) { if (!busr || (busr->flags ^ devr->flags) & type_mask) continue; diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index e640810e813..2597f9545d8 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1047,10 +1047,8 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus) struct pci_dev *dev = bus->self; - for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { - if ((res = bus->resource[i]) == NULL) - continue; - if (!res->flags) + pci_bus_for_each_resource(bus, res, i) { + if (!res || !res->flags) continue; if (i >= 3 && bus->self->transparent) continue; @@ -1277,9 +1275,8 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus) pr_debug("PCI: Allocating bus resources for %04x:%02x...\n", pci_domain_nr(bus), bus->number); - for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { - if ((res = bus->resource[i]) == NULL || !res->flags - || res->start > res->end || res->parent) + pci_bus_for_each_resource(bus, res, i) { + if (!res || !res->flags || res->start > res->end || res->parent) continue; if (bus->parent == NULL) pr = (res->flags & IORESOURCE_IO) ? diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c index fd23a1d4b39..8b0c2082a78 100644 --- a/arch/powerpc/platforms/fsl_uli1575.c +++ b/arch/powerpc/platforms/fsl_uli1575.c @@ -222,6 +222,7 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev) int i; u8 *dummy; struct pci_bus *bus = dev->bus; + struct resource *res; resource_size_t end = 0; for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) { @@ -230,13 +231,12 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev) end = pci_resource_end(dev, i); } - for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - if ((bus->resource[i]) && - (bus->resource[i]->flags & IORESOURCE_MEM)) { - if (bus->resource[i]->end == end) - dummy = ioremap(bus->resource[i]->start, 0x4); + pci_bus_for_each_resource(bus, res, i) { + if (res && res->flags & IORESOURCE_MEM) { + if (res->end == end) + dummy = ioremap(res->start, 0x4); else - dummy = ioremap(bus->resource[i]->end - 3, 0x4); + dummy = ioremap(res->end - 3, 0x4); if (dummy) { in_8(dummy); iounmap(dummy); diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index a26135bb0ff..e75d219fd10 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -43,6 +43,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, void *alignf_data) { int i, ret = -ENOMEM; + struct resource *r; resource_size_t max = -1; type_mask |= IORESOURCE_IO | IORESOURCE_MEM; @@ -51,8 +52,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, if (!(res->flags & IORESOURCE_MEM_64)) max = PCIBIOS_MAX_MEM_32; - for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - struct resource *r = bus->resource[i]; + pci_bus_for_each_resource(bus, r, i) { if (!r) continue; diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index 29fa9d26ada..071b7dc0094 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -47,8 +47,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha bus = pdev->subordinate; out += sprintf(buf, "Free resources: memory\n"); - for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { - res = bus->resource[index]; + pci_bus_for_each_resource(bus, res, index) { if (res && (res->flags & IORESOURCE_MEM) && !(res->flags & IORESOURCE_PREFETCH)) { out += sprintf(out, "start = %8.8llx, " @@ -58,8 +57,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha } } out += sprintf(out, "Free resources: prefetchable memory\n"); - for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { - res = bus->resource[index]; + pci_bus_for_each_resource(bus, res, index) { if (res && (res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PREFETCH)) { out += sprintf(out, "start = %8.8llx, " @@ -69,8 +67,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha } } out += sprintf(out, "Free resources: IO\n"); - for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) { - res = bus->resource[index]; + pci_bus_for_each_resource(bus, res, index) { if (res && (res->flags & IORESOURCE_IO)) { out += sprintf(out, "start = %8.8llx, " "length = %8.8llx\n", diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d62a5de8167..f4a2738bf0b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -386,10 +386,9 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) { const struct pci_bus *bus = dev->bus; int i; - struct resource *best = NULL; + struct resource *best = NULL, *r; - for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - struct resource *r = bus->resource[i]; + pci_bus_for_each_resource(bus, r, i) { if (!r) continue; if (res->start && !(res->start >= r->start && res->end <= r->end)) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 743ed8c48b9..bf32f07c4ef 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -387,8 +387,7 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; - for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - r = bus->resource[i]; + pci_bus_for_each_resource(bus, r, i) { if (r == &ioport_resource || r == &iomem_resource) continue; if (r && (r->flags & type_mask) == type && !r->parent) @@ -803,11 +802,10 @@ static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus, static void pci_bus_dump_res(struct pci_bus *bus) { - int i; - - for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - struct resource *res = bus->resource[i]; + struct resource *res; + int i; + pci_bus_for_each_resource(bus, res, i) { if (!res || !res->end || !res->flags) continue; diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 45d75dc452f..c67638fe691 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -803,8 +803,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) return -EINVAL; #endif - for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - res = s->cb_dev->bus->resource[i]; + pci_bus_for_each_resource(s->cb_dev->bus, res, i) { if (!res) continue; diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index e4d12acdd52..1f2039d5e96 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -649,9 +649,10 @@ static int yenta_search_one_res(struct resource *root, struct resource *res, static int yenta_search_res(struct yenta_socket *socket, struct resource *res, u32 min) { + struct resource *root; int i; - for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - struct resource *root = socket->dev->bus->resource[i]; + + pci_bus_for_each_resource(socket->dev->bus, root, i) { if (!root) continue; diff --git a/include/linux/pci.h b/include/linux/pci.h index 1a29f9f6b2d..2ff9d26a078 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -829,6 +829,9 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *); void pci_release_selected_regions(struct pci_dev *, int); /* drivers/pci/bus.c */ +#define pci_bus_for_each_resource(bus, res, i) \ + for (i = 0; res = bus->resource[i], i < PCI_BUS_NUM_RESOURCES; i++) + int __must_check pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, resource_size_t min, -- cgit v1.2.3-70-g09d2 From 2fe2abf896c1e7a0ee65faaf3ef0ce654848abbd Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 23 Feb 2010 10:24:36 -0700 Subject: PCI: augment bus resource table with a list Previously we used a table of size PCI_BUS_NUM_RESOURCES (16) for resources forwarded to a bus by its upstream bridge. We've increased this size several times when the table overflowed. But there's no good limit on the number of resources because host bridges and subtractive decode bridges can forward any number of ranges to their secondary buses. This patch reduces the table to only PCI_BRIDGE_RESOURCE_NUM (4) entries, which corresponds to the number of windows a PCI-to-PCI (3) or CardBus (4) bridge can positively decode. Any additional resources, e.g., PCI host bridge windows or subtractively-decoded regions, are kept in a list. I'd prefer a single list rather than this split table/list approach, but that requires simultaneous changes to every architecture. This approach only requires immediate changes where we set up (a) host bridges with more than four windows and (b) subtractive-decode P2P bridges, and we can incrementally change other architectures to use the list. Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/ia64/pci/pci.c | 12 +++--------- arch/x86/pci/acpi.c | 33 ++++----------------------------- arch/x86/pci/bus_numa.c | 3 ++- arch/x86/pci/bus_numa.h | 3 +-- drivers/pci/bus.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/probe.c | 17 +++++++++++++---- include/linux/pci.h | 35 +++++++++++++++++++++++++++++------ 7 files changed, 98 insertions(+), 51 deletions(-) (limited to 'arch/ia64/pci/pci.c') diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 89f957ca3eb..64aff520b89 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -320,9 +320,9 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) static void __devinit pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) { - int i, j; + int i; - j = 0; + pci_bus_remove_resources(bus); for (i = 0; i < ctrl->windows; i++) { struct resource *res = &ctrl->window[i].resource; /* HP's firmware has a hack to work around a Windows bug. @@ -330,13 +330,7 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) if ((res->flags & IORESOURCE_MEM) && (res->end - res->start < 16)) continue; - if (j >= PCI_BUS_NUM_RESOURCES) { - dev_warn(&bus->dev, - "ignoring host bridge window %pR (no space)\n", - res); - continue; - } - bus->resource[j++] = res; + pci_bus_add_resource(bus, res, 0); } } diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 959e548a703..a2f8cdb8c1d 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -45,20 +45,6 @@ count_resource(struct acpi_resource *acpi_res, void *data) return AE_OK; } -static int -bus_has_transparent_bridge(struct pci_bus *bus) -{ - struct pci_dev *dev; - - list_for_each_entry(dev, &bus->devices, bus_list) { - u16 class = dev->class >> 8; - - if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) - return true; - } - return false; -} - static void align_resource(struct acpi_device *bridge, struct resource *res) { @@ -92,12 +78,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data) acpi_status status; unsigned long flags; struct resource *root; - int max_root_bus_resources = PCI_BUS_NUM_RESOURCES; u64 start, end; - if (bus_has_transparent_bridge(info->bus)) - max_root_bus_resources -= 3; - status = resource_to_addr(acpi_res, &addr); if (!ACPI_SUCCESS(status)) return AE_OK; @@ -115,15 +97,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data) start = addr.minimum + addr.translation_offset; end = start + addr.address_length - 1; - if (info->res_num >= max_root_bus_resources) { - if (pci_probe & PCI_USE__CRS) - printk(KERN_WARNING "PCI: Failed to allocate " - "0x%lx-0x%lx from %s for %s due to _CRS " - "returning more than %d resource descriptors\n", - (unsigned long) start, (unsigned long) end, - root->name, info->name, max_root_bus_resources); - return AE_OK; - } res = &info->res[info->res_num]; res->name = info->name; @@ -143,7 +116,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) dev_err(&info->bridge->dev, "can't allocate host bridge window %pR\n", res); } else { - info->bus->resource[info->res_num] = res; + pci_bus_add_resource(info->bus, res, 0); info->res_num++; if (addr.translation_offset) dev_info(&info->bridge->dev, "host bridge window %pR " @@ -164,7 +137,9 @@ get_current_resources(struct acpi_device *device, int busnum, struct pci_root_info info; size_t size; - if (!(pci_probe & PCI_USE__CRS)) + if (pci_probe & PCI_USE__CRS) + pci_bus_remove_resources(bus); + else dev_info(&device->dev, "ignoring host bridge windows from ACPI; " "boot with \"pci=use_crs\" to use them\n"); diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c index f939d603adf..12d54ff3654 100644 --- a/arch/x86/pci/bus_numa.c +++ b/arch/x86/pci/bus_numa.c @@ -36,13 +36,14 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", b->number); + pci_bus_remove_resources(b); info = &pci_root_info[i]; for (j = 0; j < info->res_num; j++) { struct resource *res; struct resource *root; res = &info->res[j]; - b->resource[j] = res; + pci_bus_add_resource(b, res, 0); if (res->flags & IORESOURCE_IO) root = &ioport_resource; else diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h index adbc23fe82a..731b64ee8d8 100644 --- a/arch/x86/pci/bus_numa.h +++ b/arch/x86/pci/bus_numa.h @@ -2,8 +2,7 @@ /* * sub bus (transparent) will use entres from 3 to store extra from - * root, so need to make sure we have enough slot there, Should we - * increase PCI_BUS_NUM_RESOURCES? + * root, so need to make sure we have enough slot there. */ #define RES_NUM 16 struct pci_root_info { diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index e75d219fd10..712250f5874 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -17,6 +17,52 @@ #include "pci.h" +void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, + unsigned int flags) +{ + struct pci_bus_resource *bus_res; + + bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL); + if (!bus_res) { + dev_err(&bus->dev, "can't add %pR resource\n", res); + return; + } + + bus_res->res = res; + bus_res->flags = flags; + list_add_tail(&bus_res->list, &bus->resources); +} + +struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n) +{ + struct pci_bus_resource *bus_res; + + if (n < PCI_BRIDGE_RESOURCE_NUM) + return bus->resource[n]; + + n -= PCI_BRIDGE_RESOURCE_NUM; + list_for_each_entry(bus_res, &bus->resources, list) { + if (n-- == 0) + return bus_res->res; + } + return NULL; +} +EXPORT_SYMBOL_GPL(pci_bus_resource_n); + +void pci_bus_remove_resources(struct pci_bus *bus) +{ + struct pci_bus_resource *bus_res, *tmp; + int i; + + for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) + bus->resource[i] = 0; + + list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { + list_del(&bus_res->list); + kfree(bus_res); + } +} + /** * pci_bus_alloc_resource - allocate a resource from a parent bus * @bus: PCI bus diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 70c4ed2e67c..270d069819f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -89,6 +89,7 @@ static void release_pcibus_dev(struct device *dev) if (pci_bus->bridge) put_device(pci_bus->bridge); + pci_bus_remove_resources(pci_bus); kfree(pci_bus); } @@ -394,6 +395,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) void __devinit pci_read_bridge_bases(struct pci_bus *child) { struct pci_dev *dev = child->self; + struct resource *res; int i; if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ @@ -403,17 +405,23 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) child->secondary, child->subordinate, dev->transparent ? " (subtractive decode)" : ""); + pci_bus_remove_resources(child); + for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) + child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; + pci_read_bridge_io(child); pci_read_bridge_mmio(child); pci_read_bridge_mmio_pref(child); if (dev->transparent) { - for (i = 3; i < PCI_BUS_NUM_RESOURCES; i++) { - child->resource[i] = child->parent->resource[i - 3]; - if (child->resource[i]) + pci_bus_for_each_resource(child->parent, res, i) { + if (res) { + pci_bus_add_resource(child, res, + PCI_SUBTRACTIVE_DECODE); dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR (subtractive decode)\n", - child->resource[i]); + res); + } } } } @@ -428,6 +436,7 @@ static struct pci_bus * pci_alloc_bus(void) INIT_LIST_HEAD(&b->children); INIT_LIST_HEAD(&b->devices); INIT_LIST_HEAD(&b->slots); + INIT_LIST_HEAD(&b->resources); b->max_bus_speed = PCI_SPEED_UNKNOWN; b->cur_bus_speed = PCI_SPEED_UNKNOWN; } diff --git a/include/linux/pci.h b/include/linux/pci.h index 2ff9d26a078..e19a69613d8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -364,9 +364,26 @@ static inline void pci_add_saved_cap(struct pci_dev *pci_dev, hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space); } -#ifndef PCI_BUS_NUM_RESOURCES -#define PCI_BUS_NUM_RESOURCES 16 -#endif +/* + * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond + * to P2P or CardBus bridge windows) go in a table. Additional ones (for + * buses below host bridges or subtractive decode bridges) go in the list. + * Use pci_bus_for_each_resource() to iterate through all the resources. + */ + +/* + * PCI_SUBTRACTIVE_DECODE means the bridge forwards the window implicitly + * and there's no way to program the bridge with the details of the window. + * This does not apply to ACPI _CRS windows, even with the _DEC subtractive- + * decode bit set, because they are explicit and can be programmed with _SRS. + */ +#define PCI_SUBTRACTIVE_DECODE 0x1 + +struct pci_bus_resource { + struct list_head list; + struct resource *res; + unsigned int flags; +}; #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */ @@ -377,8 +394,8 @@ struct pci_bus { struct list_head devices; /* list of devices on this bus */ struct pci_dev *self; /* bridge device as seen by parent */ struct list_head slots; /* list of slots on this bus */ - struct resource *resource[PCI_BUS_NUM_RESOURCES]; - /* address space routed to this bus */ + struct resource *resource[PCI_BRIDGE_RESOURCE_NUM]; + struct list_head resources; /* address space routed to this bus */ struct pci_ops *ops; /* configuration access functions */ void *sysdata; /* hook for sys-specific extension */ @@ -829,8 +846,14 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *); void pci_release_selected_regions(struct pci_dev *, int); /* drivers/pci/bus.c */ +void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags); +struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n); +void pci_bus_remove_resources(struct pci_bus *bus); + #define pci_bus_for_each_resource(bus, res, i) \ - for (i = 0; res = bus->resource[i], i < PCI_BUS_NUM_RESOURCES; i++) + for (i = 0; \ + (res = pci_bus_resource_n(bus, i)) || i < PCI_BRIDGE_RESOURCE_NUM; \ + i++) int __must_check pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t size, -- cgit v1.2.3-70-g09d2