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); |