From b7869ba17cfb5553a33e11f18c7c45d988e4c455 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 3 Jan 2013 15:28:34 -0700 Subject: x86/PCI: Remove unused pci_root_bus pci_root_bus is unused, so remove all references to it. Signed-off-by: Bjorn Helgaas --- arch/x86/include/asm/pci_x86.h | 1 - arch/x86/pci/common.c | 1 - arch/x86/pci/legacy.c | 2 +- arch/x86/pci/numaq_32.c | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index 73e8eeff22ee..0126f104f0a5 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -54,7 +54,6 @@ void pcibios_set_cache_line_size(void); /* pci-pc.c */ extern int pcibios_last_bus; -extern struct pci_bus *pci_root_bus; extern struct pci_ops pci_root_ops; void pcibios_scan_specific_bus(int busn); diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 412e1286d1fc..505731b139f4 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -34,7 +34,6 @@ int noioapicreroute = 1; #endif int pcibios_last_bus = -1; unsigned long pirq_table_addr; -struct pci_bus *pci_root_bus; const struct pci_raw_ops *__read_mostly raw_pci_ops; const struct pci_raw_ops *__read_mostly raw_pci_ext_ops; diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c index a1df191129d3..a9e83083fb85 100644 --- a/arch/x86/pci/legacy.c +++ b/arch/x86/pci/legacy.c @@ -30,7 +30,7 @@ int __init pci_legacy_init(void) } printk("PCI: Probing PCI hardware\n"); - pci_root_bus = pcibios_scan_root(0); + pcibios_scan_root(0); return 0; } diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c index 83e125b95ca6..00edfe652b72 100644 --- a/arch/x86/pci/numaq_32.c +++ b/arch/x86/pci/numaq_32.c @@ -152,7 +152,7 @@ int __init pci_numaq_init(void) raw_pci_ops = &pci_direct_conf1_mq; - pci_root_bus = pcibios_scan_root(0); + pcibios_scan_root(0); if (num_online_nodes() > 1) for_each_online_node(quad) { if (quad == 0) -- cgit v1.2.3 From ca75e032a51013b5b9de16b7aec3674ce29b544f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 3 Jan 2013 15:30:09 -0700 Subject: frv/PCI: Remove unused pci_root_bus pci_root_bus is unused, so remove all references to it. Signed-off-by: Bjorn Helgaas --- arch/frv/mb93090-mb00/pci-frv.h | 1 - arch/frv/mb93090-mb00/pci-vdk.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h index 089eeba4f3bc..76c4e73d643d 100644 --- a/arch/frv/mb93090-mb00/pci-frv.h +++ b/arch/frv/mb93090-mb00/pci-frv.h @@ -31,7 +31,6 @@ void pcibios_resource_survey(void); /* pci-vdk.c */ extern int __nongpreldata pcibios_last_bus; -extern struct pci_bus *__nongpreldata pci_root_bus; extern struct pci_ops *__nongpreldata pci_root_ops; /* pci-irq.c */ diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index 71e9bcf58105..1152a1e3cabb 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -26,7 +26,6 @@ unsigned int __nongpreldata pci_probe = 1; int __nongpreldata pcibios_last_bus = -1; -struct pci_bus *__nongpreldata pci_root_bus; struct pci_ops *__nongpreldata pci_root_ops; /* @@ -416,8 +415,7 @@ int __init pcibios_init(void) printk("PCI: Probing PCI hardware\n"); pci_add_resource(&resources, &pci_ioport_resource); pci_add_resource(&resources, &pci_iomem_resource); - pci_root_bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, - &resources); + pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); pcibios_irq_init(); pcibios_fixup_peer_bridges(); -- cgit v1.2.3 From 7f0d21f937939d05649b95c2ff34c53f6726d11e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 3 Jan 2013 15:30:21 -0700 Subject: mn10300/PCI: Remove unused pci_root_bus pci_root_bus is unused, so remove all references to it. Signed-off-by: Bjorn Helgaas --- arch/mn10300/unit-asb2305/pci-asb2305.h | 1 - arch/mn10300/unit-asb2305/pci.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h index 1194fe486b01..7fa66a0e4624 100644 --- a/arch/mn10300/unit-asb2305/pci-asb2305.h +++ b/arch/mn10300/unit-asb2305/pci-asb2305.h @@ -36,7 +36,6 @@ extern void pcibios_resource_survey(void); /* pci.c */ extern int pcibios_last_bus; -extern struct pci_bus *pci_root_bus; extern struct pci_ops *pci_root_ops; extern struct irq_routing_table *pcibios_get_irq_routing_table(void); diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index e2059486d3f8..426bf51605f3 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c @@ -24,7 +24,6 @@ unsigned int pci_probe = 1; int pcibios_last_bus = -1; -struct pci_bus *pci_root_bus; struct pci_ops *pci_root_ops; /* @@ -377,8 +376,7 @@ static int __init pcibios_init(void) pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset); pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset); - pci_root_bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, - &resources); + pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources); pcibios_irq_init(); pcibios_fixup_irqs(); -- cgit v1.2.3 From f7ac356dc3da1f69dc52cb6273e08e53b85b4884 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 3 Nov 2012 21:39:24 -0700 Subject: x86/PCI: Factor out pcibios_allocate_bridge_resources() Thus pcibios_allocate_bus_resources() could more simple and clean. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/i386.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index dd8ca6f7223b..980036286909 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -193,34 +193,36 @@ EXPORT_SYMBOL(pcibios_align_resource); * as well. */ -static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) +static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev) { - struct pci_bus *bus; - struct pci_dev *dev; int idx; struct resource *r; + for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { + r = &dev->resource[idx]; + if (!r->flags) + continue; + if (!r->start || pci_claim_resource(dev, idx) < 0) { + /* + * Something is wrong with the region. + * Invalidate the resource to prevent + * child resource allocations in this + * range. + */ + r->start = r->end = 0; + r->flags = 0; + } + } +} + +static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) +{ + struct pci_bus *bus; + /* Depth-First Search on bus tree */ list_for_each_entry(bus, bus_list, node) { - if ((dev = bus->self)) { - for (idx = PCI_BRIDGE_RESOURCES; - idx < PCI_NUM_RESOURCES; idx++) { - r = &dev->resource[idx]; - if (!r->flags) - continue; - if (!r->start || - pci_claim_resource(dev, idx) < 0) { - /* - * Something is wrong with the region. - * Invalidate the resource to prevent - * child resource allocations in this - * range. - */ - r->start = r->end = 0; - r->flags = 0; - } - } - } + if (bus->self) + pcibios_allocate_bridge_resources(bus->self); pcibios_allocate_bus_resources(&bus->children); } } -- cgit v1.2.3 From c7f4bbc92feee2986212ef3b42c806e2257197dc Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 3 Nov 2012 21:39:25 -0700 Subject: x86/PCI: Factor out pcibios_allocate_dev_resources() Factor pcibios_allocate_dev_resources() out of pcibios_allocate_resources(). Currently we only allocate these resources at boot-time with a for_each_pci_dev() loop. Eventually we'll use pcibios_allocate_dev_resources() for hot-added devices, too. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/i386.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 980036286909..5817cf235d9a 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -232,9 +232,8 @@ struct pci_check_idx_range { int end; }; -static void __init pcibios_allocate_resources(int pass) +static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) { - struct pci_dev *dev = NULL; int idx, disabled, i; u16 command; struct resource *r; @@ -246,14 +245,13 @@ static void __init pcibios_allocate_resources(int pass) #endif }; - for_each_pci_dev(dev) { - pci_read_config_word(dev, PCI_COMMAND, &command); - for (i = 0; i < ARRAY_SIZE(idx_range); i++) + pci_read_config_word(dev, PCI_COMMAND, &command); + for (i = 0; i < ARRAY_SIZE(idx_range); i++) for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) { r = &dev->resource[idx]; - if (r->parent) /* Already allocated */ + if (r->parent) /* Already allocated */ continue; - if (!r->start) /* Address not assigned at all */ + if (!r->start) /* Address not assigned at all */ continue; if (r->flags & IORESOURCE_IO) disabled = !(command & PCI_COMMAND_IO); @@ -272,23 +270,29 @@ static void __init pcibios_allocate_resources(int pass) } } } - if (!pass) { - r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & IORESOURCE_ROM_ENABLE) { - /* Turn the ROM off, leave the resource region, - * but keep it unregistered. */ - u32 reg; - dev_dbg(&dev->dev, "disabling ROM %pR\n", r); - r->flags &= ~IORESOURCE_ROM_ENABLE; - pci_read_config_dword(dev, - dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, + if (!pass) { + r = &dev->resource[PCI_ROM_RESOURCE]; + if (r->flags & IORESOURCE_ROM_ENABLE) { + /* Turn the ROM off, leave the resource region, + * but keep it unregistered. */ + u32 reg; + dev_dbg(&dev->dev, "disabling ROM %pR\n", r); + r->flags &= ~IORESOURCE_ROM_ENABLE; + pci_read_config_dword(dev, dev->rom_base_reg, ®); + pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); - } } } } +static void __init pcibios_allocate_resources(int pass) +{ + struct pci_dev *dev = NULL; + + for_each_pci_dev(dev) + pcibios_allocate_dev_resources(dev, pass); +} + static int __init pcibios_assign_resources(void) { struct pci_dev *dev = NULL; -- cgit v1.2.3 From 83edc87ce8b284a3d60ab8072e55041c76a68277 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 3 Nov 2012 21:39:26 -0700 Subject: x86/PCI: Allocate resources on a per-bus basis for hot-adding root buses Previously pcibios_allocate_resources() allocated resources at boot-time for all PCI devices using for_each_pci_dev(). This patch changes pcibios_allocate_resources() so we can specify a bus, so we can do similar allocation when hot-adding a root bus. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/i386.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 5817cf235d9a..84696ed1f0e9 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -215,16 +215,15 @@ static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev) } } -static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) +static void __init pcibios_allocate_bus_resources(struct pci_bus *bus) { - struct pci_bus *bus; + struct pci_bus *child; /* Depth-First Search on bus tree */ - list_for_each_entry(bus, bus_list, node) { - if (bus->self) - pcibios_allocate_bridge_resources(bus->self); - pcibios_allocate_bus_resources(&bus->children); - } + if (bus->self) + pcibios_allocate_bridge_resources(bus->self); + list_for_each_entry(child, &bus->children, node) + pcibios_allocate_bus_resources(child); } struct pci_check_idx_range { @@ -285,12 +284,18 @@ static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) } } -static void __init pcibios_allocate_resources(int pass) +static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass) { - struct pci_dev *dev = NULL; + struct pci_dev *dev; + struct pci_bus *child; - for_each_pci_dev(dev) + list_for_each_entry(dev, &bus->devices, bus_list) { pcibios_allocate_dev_resources(dev, pass); + + child = dev->subordinate; + if (child) + pcibios_allocate_resources(child, pass); + } } static int __init pcibios_assign_resources(void) @@ -323,10 +328,17 @@ static int __init pcibios_assign_resources(void) void __init pcibios_resource_survey(void) { + struct pci_bus *bus; + DBG("PCI: Allocating resources\n"); - pcibios_allocate_bus_resources(&pci_root_buses); - pcibios_allocate_resources(0); - pcibios_allocate_resources(1); + + list_for_each_entry(bus, &pci_root_buses, node) + pcibios_allocate_bus_resources(bus); + + list_for_each_entry(bus, &pci_root_buses, node) + pcibios_allocate_resources(bus, 0); + list_for_each_entry(bus, &pci_root_buses, node) + pcibios_allocate_resources(bus, 1); e820_reserve_resources_late(); /* -- cgit v1.2.3 From dc2f56fa8400677ef4852d5128f03b795cf57e7b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 3 Nov 2012 21:39:27 -0700 Subject: x86/PCI: Factor out pcibios_allocate_dev_rom_resource() Factor pcibios_allocate_rom_resources() and pcibios_allocate_dev_rom_resource() out of pcibios_assign_resources(). This will allow us to allocate ROM resources for hot-added root buses. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/i386.c | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 84696ed1f0e9..42dd75552351 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -298,27 +298,45 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass) } } -static int __init pcibios_assign_resources(void) +static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev) { - struct pci_dev *dev = NULL; struct resource *r; - if (!(pci_probe & PCI_ASSIGN_ROMS)) { - /* - * Try to use BIOS settings for ROMs, otherwise let - * pci_assign_unassigned_resources() allocate the new - * addresses. - */ - for_each_pci_dev(dev) { - r = &dev->resource[PCI_ROM_RESOURCE]; - if (!r->flags || !r->start) - continue; - if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) { - r->end -= r->start; - r->start = 0; - } - } + /* + * Try to use BIOS settings for ROMs, otherwise let + * pci_assign_unassigned_resources() allocate the new + * addresses. + */ + r = &dev->resource[PCI_ROM_RESOURCE]; + if (!r->flags || !r->start) + return; + + if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) { + r->end -= r->start; + r->start = 0; } +} +static void __init pcibios_allocate_rom_resources(struct pci_bus *bus) +{ + struct pci_dev *dev; + struct pci_bus *child; + + list_for_each_entry(dev, &bus->devices, bus_list) { + pcibios_allocate_dev_rom_resource(dev); + + child = dev->subordinate; + if (child) + pcibios_allocate_rom_resources(child); + } +} + +static int __init pcibios_assign_resources(void) +{ + struct pci_bus *bus; + + if (!(pci_probe & PCI_ASSIGN_ROMS)) + list_for_each_entry(bus, &pci_root_buses, node) + pcibios_allocate_rom_resources(bus); pci_assign_unassigned_resources(); pcibios_fw_addr_list_del(); -- cgit v1.2.3 From 745216025de0354eea23493d994e3fc0ab7369fc Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 3 Nov 2012 21:39:28 -0700 Subject: x86/PCI: Don't track firmware-assigned BAR values for hot-added devices The BIOS doesn't assign BAR values for hot-added devices, so don't bother saving the original values when we enumerate these devices. [bhelgaas: changelog, return constant 0 in pcibios_retrieve_fw_addr] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/i386.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 42dd75552351..1bd672ab0084 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -51,6 +51,7 @@ struct pcibios_fwaddrmap { static LIST_HEAD(pcibios_fwaddrmappings); static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock); +static bool pcibios_fw_addr_done; /* Must be called with 'pcibios_fwaddrmap_lock' lock held. */ static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev) @@ -72,6 +73,9 @@ pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr) unsigned long flags; struct pcibios_fwaddrmap *map; + if (pcibios_fw_addr_done) + return; + spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); map = pcibios_fwaddrmap_lookup(dev); if (!map) { @@ -97,6 +101,9 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx) struct pcibios_fwaddrmap *map; resource_size_t fw_addr = 0; + if (pcibios_fw_addr_done) + return 0; + spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); map = pcibios_fwaddrmap_lookup(dev); if (map) @@ -106,7 +113,7 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx) return fw_addr; } -static void pcibios_fw_addr_list_del(void) +static void __init pcibios_fw_addr_list_del(void) { unsigned long flags; struct pcibios_fwaddrmap *entry, *next; @@ -118,6 +125,7 @@ static void pcibios_fw_addr_list_del(void) kfree(entry); } spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags); + pcibios_fw_addr_done = true; } static int -- cgit v1.2.3 From b95168e010a405add13aa010d7c45b55dc4026c7 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 3 Nov 2012 21:39:29 -0700 Subject: x86/PCI: Keep resource allocation functions after boot The PCI resource allocation functions will be used for hot-added devices, so keep them around. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/i386.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 1bd672ab0084..8656ea88cf66 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -201,7 +201,7 @@ EXPORT_SYMBOL(pcibios_align_resource); * as well. */ -static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev) +static void pcibios_allocate_bridge_resources(struct pci_dev *dev) { int idx; struct resource *r; @@ -223,7 +223,7 @@ static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev) } } -static void __init pcibios_allocate_bus_resources(struct pci_bus *bus) +static void pcibios_allocate_bus_resources(struct pci_bus *bus) { struct pci_bus *child; @@ -239,7 +239,7 @@ struct pci_check_idx_range { int end; }; -static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) +static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) { int idx, disabled, i; u16 command; @@ -292,7 +292,7 @@ static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) } } -static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass) +static void pcibios_allocate_resources(struct pci_bus *bus, int pass) { struct pci_dev *dev; struct pci_bus *child; @@ -306,7 +306,7 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass) } } -static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev) +static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev) { struct resource *r; @@ -324,7 +324,7 @@ static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev) r->start = 0; } } -static void __init pcibios_allocate_rom_resources(struct pci_bus *bus) +static void pcibios_allocate_rom_resources(struct pci_bus *bus) { struct pci_dev *dev; struct pci_bus *child; -- cgit v1.2.3 From b3e65e1f9185a2eb034defe4270ba178ba70b9a9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 3 Nov 2012 21:39:30 -0700 Subject: x86/PCI: Implement pcibios_resource_survey_bus() During testing remove/rescan root bus 00, found [ 338.142574] bus: 'pci': really_probe: probing driver ata_piix with device 0000:00:01.1 [ 338.146788] ata_piix 0000:00:01.1: device not available (can't reserve [io 0x01f0-0x01f7]) [ 338.150565] ata_piix: probe of 0000:00:01.1 failed with error -22 because that fixed resource is not claimed. For bootint path it is claimed in from arch/x86/pci/i386.c::pcibios_allocate_resources() Claim those resources, so on the remove/rescan will still use old resources. It is some kind honoring FW setting in the registers during hot add. esp root-bus hot add is through acpi, BIOS has chance to set some registers before handing over. [bhelgaas: move weak definition to patch that uses it] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/x86/pci/i386.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 8656ea88cf66..94919e307f8e 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -352,6 +352,19 @@ static int __init pcibios_assign_resources(void) return 0; } +void pcibios_resource_survey_bus(struct pci_bus *bus) +{ + dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n"); + + pcibios_allocate_bus_resources(bus); + + pcibios_allocate_resources(bus, 0); + pcibios_allocate_resources(bus, 1); + + if (!(pci_probe & PCI_ASSIGN_ROMS)) + pcibios_allocate_rom_resources(bus); +} + void __init pcibios_resource_survey(void) { struct pci_bus *bus; -- cgit v1.2.3 From 6c0cc950ae670403a362bdcbf3cde0df33744928 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 9 Jan 2013 22:33:37 +0100 Subject: ACPI / PCI: Set root bridge ACPI handle in advance The ACPI handles of PCI root bridges need to be known to acpi_bind_one(), so that it can create the appropriate "firmware_node" and "physical_node" files for them, but currently the way it gets to know those handles is not exactly straightforward (to put it lightly). This is how it works, roughly: 1. acpi_bus_scan() finds the handle of a PCI root bridge, creates a struct acpi_device object for it and passes that object to acpi_pci_root_add(). 2. acpi_pci_root_add() creates a struct acpi_pci_root object, populates its "device" field with its argument's address (device->handle is the ACPI handle found in step 1). 3. The struct acpi_pci_root object created in step 2 is passed to pci_acpi_scan_root() and used to get resources that are passed to pci_create_root_bus(). 4. pci_create_root_bus() creates a struct pci_host_bridge object and passes its "dev" member to device_register(). 5. platform_notify(), which for systems with ACPI is set to acpi_platform_notify(), is called. So far, so good. Now it starts to be "interesting". 6. acpi_find_bridge_device() is used to find the ACPI handle of the given device (which is the PCI root bridge) and executes acpi_pci_find_root_bridge(), among other things, for the given device object. 7. acpi_pci_find_root_bridge() uses the name (sic!) of the given device object to extract the segment and bus numbers of the PCI root bridge and passes them to acpi_get_pci_rootbridge_handle(). 8. acpi_get_pci_rootbridge_handle() browses the list of ACPI PCI root bridges and finds the one that matches the given segment and bus numbers. Its handle is then used to initialize the ACPI handle of the PCI root bridge's device object by acpi_bind_one(). However, this is *exactly* the ACPI handle we started with in step 1. Needless to say, this is quite embarassing, but it may be avoided thanks to commit f3fd0c8 (ACPI: Allow ACPI handles of devices to be initialized in advance), which makes it possible to initialize the ACPI handle of a device before passing it to device_register(). Accordingly, add a new __weak routine, pcibios_root_bridge_prepare(), defaulting to an empty implementation that can be replaced by the interested architecutres (x86 and ia64 at the moment) with functions that will set the root bridge's ACPI handle before its dev member is passed to device_register(). Make both x86 and ia64 provide such implementations of pcibios_root_bridge_prepare() and remove acpi_pci_find_root_bridge() and acpi_get_pci_rootbridge_handle() that aren't necessary any more. Included is a fix for breakage on systems with non-ACPI PCI host bridges from Bjorn Helgaas. Signed-off-by: Rafael J. Wysocki Signed-off-by: Bjorn Helgaas --- arch/ia64/pci/pci.c | 8 ++++++++ arch/x86/include/asm/pci.h | 3 +++ arch/x86/pci/acpi.c | 9 +++++++++ 3 files changed, 20 insertions(+) (limited to 'arch') diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 5faa66c5c2a8..00e59c7ad3c0 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -396,6 +396,14 @@ out1: return NULL; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct pci_controller *controller = bridge->bus->sysdata; + + ACPI_HANDLE_SET(&bridge->dev, controller->acpi_handle); + return 0; +} + static int __devinit is_valid_resource(struct pci_dev *dev, int idx) { unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index dba7805176bf..9f437e97e9e8 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -14,6 +14,9 @@ struct pci_sysdata { int domain; /* PCI domain */ int node; /* NUMA node */ +#ifdef CONFIG_ACPI + void *acpi; /* ACPI-specific data */ +#endif #ifdef CONFIG_X86_64 void *iommu; /* IOMMU private data */ #endif diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 0c01261fe5a8..3d49094ed3e8 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -522,6 +522,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) sd = &info->sd; sd->domain = domain; sd->node = node; + sd->acpi = device->handle; /* * Maybe the desired pci bus has been already scanned. In such case * it is unnecessary to scan the pci bus with the given domain,busnum. @@ -593,6 +594,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) return bus; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct pci_sysdata *sd = bridge->bus->sysdata; + + ACPI_HANDLE_SET(&bridge->dev, sd->acpi); + return 0; +} + int __init pci_acpi_init(void) { struct pci_dev *dev = NULL; -- cgit v1.2.3