diff options
| author | Yijing Wang <wangyijing@huawei.com> | 2015-03-15 23:18:56 -0400 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-03-19 11:17:13 -0400 |
| commit | b97ea289cf6aff8d4cbcefe2b707bb9b00a73c73 (patch) | |
| tree | efa328fedf08e394912322783660d27c33257610 | |
| parent | c90570d9511d42421c85709b46bffd366185d835 (diff) | |
PCI: Assign resources before drivers claim devices (pci_scan_root_bus())
Previously, pci_scan_root_bus() created a root PCI bus, enumerated the
devices on it, and called pci_bus_add_devices(), which made the devices
available for drivers to claim them.
Most callers assigned resources to devices after pci_scan_root_bus()
returns, which may be after drivers have claimed the devices. This is
incorrect; the PCI core should not change device resources while a driver
is managing the device.
Remove pci_bus_add_devices() from pci_scan_root_bus() and do it after any
resource assignment in the callers.
Note that ARM's pci_common_init_dev() already called pci_bus_add_devices()
after pci_scan_root_bus(), so we only need to remove the first call:
pci_common_init_dev
pcibios_init_hw
pci_scan_root_bus
pci_bus_add_devices # first call
pci_bus_assign_resources
pci_bus_add_devices # second call
[bhelgaas: changelog, drop "root_bus" var in alpha common_init_pci(),
return failure earlier in mn10300, add "return" in x86 pcibios_scan_root(),
return early if xtensa platform_pcibios_fixup() fails]
Signed-off-by: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
CC: Matt Turner <mattst88@gmail.com>
CC: David Howells <dhowells@redhat.com>
CC: Tony Luck <tony.luck@intel.com>
CC: Michal Simek <monstr@monstr.eu>
CC: Ralf Baechle <ralf@linux-mips.org>
CC: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
CC: Sebastian Ott <sebott@linux.vnet.ibm.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: Chris Metcalf <cmetcalf@ezchip.com>
CC: Chris Zankel <chris@zankel.net>
CC: Max Filippov <jcmvbkbc@gmail.com>
CC: Thomas Gleixner <tglx@linutronix.de>
| -rw-r--r-- | arch/alpha/kernel/pci.c | 7 | ||||
| -rw-r--r-- | arch/frv/mb93090-mb00/pci-vdk.c | 6 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 2 | ||||
| -rw-r--r-- | arch/microblaze/pci/pci-common.c | 4 | ||||
| -rw-r--r-- | arch/mips/pci/pci.c | 1 | ||||
| -rw-r--r-- | arch/mn10300/unit-asb2305/pci.c | 6 | ||||
| -rw-r--r-- | arch/s390/pci/pci.c | 2 | ||||
| -rw-r--r-- | arch/sh/drivers/pci/pci.c | 1 | ||||
| -rw-r--r-- | arch/sparc/kernel/leon_pci.c | 1 | ||||
| -rw-r--r-- | arch/tile/kernel/pci.c | 2 | ||||
| -rw-r--r-- | arch/tile/kernel/pci_gx.c | 2 | ||||
| -rw-r--r-- | arch/x86/pci/common.c | 2 | ||||
| -rw-r--r-- | arch/xtensa/kernel/pci.c | 15 | ||||
| -rw-r--r-- | drivers/pci/host/pci-versatile.c | 1 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 1 |
15 files changed, 47 insertions, 6 deletions
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 98a1525fa164..82f738e5d54c 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c | |||
| @@ -338,6 +338,8 @@ common_init_pci(void) | |||
| 338 | 338 | ||
| 339 | bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops, | 339 | bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops, |
| 340 | hose, &resources); | 340 | hose, &resources); |
| 341 | if (!bus) | ||
| 342 | continue; | ||
| 341 | hose->bus = bus; | 343 | hose->bus = bus; |
| 342 | hose->need_domain_info = need_domain_info; | 344 | hose->need_domain_info = need_domain_info; |
| 343 | next_busno = bus->busn_res.end + 1; | 345 | next_busno = bus->busn_res.end + 1; |
| @@ -353,6 +355,11 @@ common_init_pci(void) | |||
| 353 | 355 | ||
| 354 | pci_assign_unassigned_resources(); | 356 | pci_assign_unassigned_resources(); |
| 355 | pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); | 357 | pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); |
| 358 | for (hose = hose_head; hose; hose = hose->next) { | ||
| 359 | bus = hose->bus; | ||
| 360 | if (bus) | ||
| 361 | pci_bus_add_devices(bus); | ||
| 362 | } | ||
| 356 | } | 363 | } |
| 357 | 364 | ||
| 358 | 365 | ||
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index b073f4d771a5..f211839e2cae 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c | |||
| @@ -316,6 +316,7 @@ void pcibios_fixup_bus(struct pci_bus *bus) | |||
| 316 | 316 | ||
| 317 | int __init pcibios_init(void) | 317 | int __init pcibios_init(void) |
| 318 | { | 318 | { |
| 319 | struct pci_bus *bus; | ||
| 319 | struct pci_ops *dir = NULL; | 320 | struct pci_ops *dir = NULL; |
| 320 | LIST_HEAD(resources); | 321 | LIST_HEAD(resources); |
| 321 | 322 | ||
| @@ -383,12 +384,15 @@ int __init pcibios_init(void) | |||
| 383 | printk("PCI: Probing PCI hardware\n"); | 384 | printk("PCI: Probing PCI hardware\n"); |
| 384 | pci_add_resource(&resources, &pci_ioport_resource); | 385 | pci_add_resource(&resources, &pci_ioport_resource); |
| 385 | pci_add_resource(&resources, &pci_iomem_resource); | 386 | pci_add_resource(&resources, &pci_iomem_resource); |
| 386 | pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); | 387 | bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); |
| 387 | 388 | ||
| 388 | pcibios_irq_init(); | 389 | pcibios_irq_init(); |
| 389 | pcibios_fixup_irqs(); | 390 | pcibios_fixup_irqs(); |
| 390 | pcibios_resource_survey(); | 391 | pcibios_resource_survey(); |
| 392 | if (!bus) | ||
| 393 | return 0; | ||
| 391 | 394 | ||
| 395 | pci_bus_add_devices(bus); | ||
| 392 | return 0; | 396 | return 0; |
| 393 | } | 397 | } |
| 394 | 398 | ||
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 0b5ce82d203d..1be65eb074ec 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
| @@ -271,7 +271,9 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
| 271 | if (bus == NULL) { | 271 | if (bus == NULL) { |
| 272 | kfree(res); | 272 | kfree(res); |
| 273 | kfree(controller); | 273 | kfree(controller); |
| 274 | return; | ||
| 274 | } | 275 | } |
| 276 | pci_bus_add_devices(bus); | ||
| 275 | } | 277 | } |
| 276 | 278 | ||
| 277 | /* | 279 | /* |
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 48528fb81eff..ae838ed5fcf2 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c | |||
| @@ -1382,6 +1382,10 @@ static int __init pcibios_init(void) | |||
| 1382 | 1382 | ||
| 1383 | /* Call common code to handle resource allocation */ | 1383 | /* Call common code to handle resource allocation */ |
| 1384 | pcibios_resource_survey(); | 1384 | pcibios_resource_survey(); |
| 1385 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
| 1386 | if (hose->bus) | ||
| 1387 | pci_bus_add_devices(hose->bus); | ||
| 1388 | } | ||
| 1385 | 1389 | ||
| 1386 | return 0; | 1390 | return 0; |
| 1387 | } | 1391 | } |
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 1bf60b127377..9eb54b557c9f 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c | |||
| @@ -114,6 +114,7 @@ static void pcibios_scanbus(struct pci_controller *hose) | |||
| 114 | pci_bus_size_bridges(bus); | 114 | pci_bus_size_bridges(bus); |
| 115 | pci_bus_assign_resources(bus); | 115 | pci_bus_assign_resources(bus); |
| 116 | } | 116 | } |
| 117 | pci_bus_add_devices(bus); | ||
| 117 | } | 118 | } |
| 118 | } | 119 | } |
| 119 | 120 | ||
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 613ca1e55b4b..3dfe2d31c67b 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c | |||
| @@ -342,6 +342,7 @@ static int __init pcibios_init(void) | |||
| 342 | { | 342 | { |
| 343 | resource_size_t io_offset, mem_offset; | 343 | resource_size_t io_offset, mem_offset; |
| 344 | LIST_HEAD(resources); | 344 | LIST_HEAD(resources); |
| 345 | struct pci_bus *bus; | ||
| 345 | 346 | ||
| 346 | ioport_resource.start = 0xA0000000; | 347 | ioport_resource.start = 0xA0000000; |
| 347 | ioport_resource.end = 0xDFFFFFFF; | 348 | ioport_resource.end = 0xDFFFFFFF; |
| @@ -371,11 +372,14 @@ static int __init pcibios_init(void) | |||
| 371 | 372 | ||
| 372 | pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset); | 373 | pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset); |
| 373 | pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset); | 374 | pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset); |
| 374 | pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources); | 375 | bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources); |
| 376 | if (!bus) | ||
| 377 | return 0; | ||
| 375 | 378 | ||
| 376 | pcibios_irq_init(); | 379 | pcibios_irq_init(); |
| 377 | pcibios_fixup_irqs(); | 380 | pcibios_fixup_irqs(); |
| 378 | pcibios_resource_survey(); | 381 | pcibios_resource_survey(); |
| 382 | pci_bus_add_devices(bus); | ||
| 379 | return 0; | 383 | return 0; |
| 380 | } | 384 | } |
| 381 | 385 | ||
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 753a56731951..a2a7391c0b9a 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
| @@ -776,8 +776,8 @@ static int zpci_scan_bus(struct zpci_dev *zdev) | |||
| 776 | zpci_cleanup_bus_resources(zdev); | 776 | zpci_cleanup_bus_resources(zdev); |
| 777 | return -EIO; | 777 | return -EIO; |
| 778 | } | 778 | } |
| 779 | |||
| 780 | zdev->bus->max_bus_speed = zdev->max_bus_speed; | 779 | zdev->bus->max_bus_speed = zdev->max_bus_speed; |
| 780 | pci_bus_add_devices(zdev->bus); | ||
| 781 | return 0; | 781 | return 0; |
| 782 | } | 782 | } |
| 783 | 783 | ||
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 1bc09ee7948f..efc10519916a 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c | |||
| @@ -69,6 +69,7 @@ static void pcibios_scanbus(struct pci_channel *hose) | |||
| 69 | 69 | ||
| 70 | pci_bus_size_bridges(bus); | 70 | pci_bus_size_bridges(bus); |
| 71 | pci_bus_assign_resources(bus); | 71 | pci_bus_assign_resources(bus); |
| 72 | pci_bus_add_devices(bus); | ||
| 72 | } else { | 73 | } else { |
| 73 | pci_free_resource_list(&resources); | 74 | pci_free_resource_list(&resources); |
| 74 | } | 75 | } |
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c index 899b7203a4e4..297107679fdf 100644 --- a/arch/sparc/kernel/leon_pci.c +++ b/arch/sparc/kernel/leon_pci.c | |||
| @@ -40,6 +40,7 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info) | |||
| 40 | 40 | ||
| 41 | /* Assign devices with resources */ | 41 | /* Assign devices with resources */ |
| 42 | pci_assign_unassigned_resources(); | 42 | pci_assign_unassigned_resources(); |
| 43 | pci_bus_add_devices(root_bus); | ||
| 43 | } else { | 44 | } else { |
| 44 | pci_free_resource_list(&resources); | 45 | pci_free_resource_list(&resources); |
| 45 | } | 46 | } |
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index 325df47f114d..9475a74cd53a 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c | |||
| @@ -339,6 +339,8 @@ int __init pcibios_init(void) | |||
| 339 | struct pci_bus *next_bus; | 339 | struct pci_bus *next_bus; |
| 340 | struct pci_dev *dev; | 340 | struct pci_dev *dev; |
| 341 | 341 | ||
| 342 | pci_bus_add_devices(root_bus); | ||
| 343 | |||
| 342 | list_for_each_entry(dev, &root_bus->devices, bus_list) { | 344 | list_for_each_entry(dev, &root_bus->devices, bus_list) { |
| 343 | /* | 345 | /* |
| 344 | * Find the PCI host controller, ie. the 1st | 346 | * Find the PCI host controller, ie. the 1st |
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c index 2c95f37ebbed..b1df847d0686 100644 --- a/arch/tile/kernel/pci_gx.c +++ b/arch/tile/kernel/pci_gx.c | |||
| @@ -1030,6 +1030,8 @@ int __init pcibios_init(void) | |||
| 1030 | alloc_mem_map_failed: | 1030 | alloc_mem_map_failed: |
| 1031 | break; | 1031 | break; |
| 1032 | } | 1032 | } |
| 1033 | |||
| 1034 | pci_bus_add_devices(root_bus); | ||
| 1033 | } | 1035 | } |
| 1034 | 1036 | ||
| 1035 | return 0; | 1037 | return 0; |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 3d2612b68694..95a0ba70376b 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
| @@ -490,7 +490,9 @@ void pcibios_scan_root(int busnum) | |||
| 490 | if (!bus) { | 490 | if (!bus) { |
| 491 | pci_free_resource_list(&resources); | 491 | pci_free_resource_list(&resources); |
| 492 | kfree(sd); | 492 | kfree(sd); |
| 493 | return; | ||
| 493 | } | 494 | } |
| 495 | pci_bus_add_devices(bus); | ||
| 494 | } | 496 | } |
| 495 | 497 | ||
| 496 | void __init pcibios_set_cache_line_size(void) | 498 | void __init pcibios_set_cache_line_size(void) |
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index 5b3403388d7f..b848cc3dc913 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c | |||
| @@ -174,7 +174,7 @@ static int __init pcibios_init(void) | |||
| 174 | struct pci_controller *pci_ctrl; | 174 | struct pci_controller *pci_ctrl; |
| 175 | struct list_head resources; | 175 | struct list_head resources; |
| 176 | struct pci_bus *bus; | 176 | struct pci_bus *bus; |
| 177 | int next_busno = 0; | 177 | int next_busno = 0, ret; |
| 178 | 178 | ||
| 179 | printk("PCI: Probing PCI hardware\n"); | 179 | printk("PCI: Probing PCI hardware\n"); |
| 180 | 180 | ||
| @@ -185,14 +185,25 @@ static int __init pcibios_init(void) | |||
| 185 | pci_controller_apertures(pci_ctrl, &resources); | 185 | pci_controller_apertures(pci_ctrl, &resources); |
| 186 | bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno, | 186 | bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno, |
| 187 | pci_ctrl->ops, pci_ctrl, &resources); | 187 | pci_ctrl->ops, pci_ctrl, &resources); |
| 188 | if (!bus) | ||
| 189 | continue; | ||
| 190 | |||
| 188 | pci_ctrl->bus = bus; | 191 | pci_ctrl->bus = bus; |
| 189 | pci_ctrl->last_busno = bus->busn_res.end; | 192 | pci_ctrl->last_busno = bus->busn_res.end; |
| 190 | if (next_busno <= pci_ctrl->last_busno) | 193 | if (next_busno <= pci_ctrl->last_busno) |
| 191 | next_busno = pci_ctrl->last_busno+1; | 194 | next_busno = pci_ctrl->last_busno+1; |
| 192 | } | 195 | } |
| 193 | pci_bus_count = next_busno; | 196 | pci_bus_count = next_busno; |
| 197 | ret = platform_pcibios_fixup(); | ||
| 198 | if (ret) | ||
| 199 | return ret; | ||
| 194 | 200 | ||
| 195 | return platform_pcibios_fixup(); | 201 | for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) { |
| 202 | if (pci_ctrl->bus) | ||
| 203 | pci_bus_add_devices(pci_ctrl->bus); | ||
| 204 | } | ||
| 205 | |||
| 206 | return 0; | ||
| 196 | } | 207 | } |
| 197 | 208 | ||
| 198 | subsys_initcall(pcibios_init); | 209 | subsys_initcall(pcibios_init); |
diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c index 1ec694a52379..e3a2450db2b8 100644 --- a/drivers/pci/host/pci-versatile.c +++ b/drivers/pci/host/pci-versatile.c | |||
| @@ -214,6 +214,7 @@ static int versatile_pci_probe(struct platform_device *pdev) | |||
| 214 | 214 | ||
| 215 | pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); | 215 | pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); |
| 216 | pci_assign_unassigned_bus_resources(bus); | 216 | pci_assign_unassigned_bus_resources(bus); |
| 217 | pci_bus_add_devices(bus); | ||
| 217 | 218 | ||
| 218 | return 0; | 219 | return 0; |
| 219 | } | 220 | } |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 88604f29d140..8ef0375ea314 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -2087,7 +2087,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, | |||
| 2087 | if (!found) | 2087 | if (!found) |
| 2088 | pci_bus_update_busn_res_end(b, max); | 2088 | pci_bus_update_busn_res_end(b, max); |
| 2089 | 2089 | ||
| 2090 | pci_bus_add_devices(b); | ||
| 2091 | return b; | 2090 | return b; |
| 2092 | } | 2091 | } |
| 2093 | EXPORT_SYMBOL(pci_scan_root_bus); | 2092 | EXPORT_SYMBOL(pci_scan_root_bus); |
