diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci-hotplug.c | 14 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_of_scan.c | 56 |
3 files changed, 51 insertions, 21 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index f46914a0f33e..7d22a675fe1a 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -1462,6 +1462,8 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus) | |||
1462 | /* Allocate bus and devices resources */ | 1462 | /* Allocate bus and devices resources */ |
1463 | pcibios_allocate_bus_resources(bus); | 1463 | pcibios_allocate_bus_resources(bus); |
1464 | pcibios_claim_one_bus(bus); | 1464 | pcibios_claim_one_bus(bus); |
1465 | if (!pci_has_flag(PCI_PROBE_ONLY)) | ||
1466 | pci_assign_unassigned_bus_resources(bus); | ||
1465 | 1467 | ||
1466 | /* Fixup EEH */ | 1468 | /* Fixup EEH */ |
1467 | eeh_add_device_tree_late(bus); | 1469 | eeh_add_device_tree_late(bus); |
diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index fc0831d4971f..c1e17ae68a08 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c | |||
@@ -71,7 +71,7 @@ EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices); | |||
71 | */ | 71 | */ |
72 | void pcibios_add_pci_devices(struct pci_bus * bus) | 72 | void pcibios_add_pci_devices(struct pci_bus * bus) |
73 | { | 73 | { |
74 | int slotno, num, mode, pass, max; | 74 | int slotno, mode, pass, max; |
75 | struct pci_dev *dev; | 75 | struct pci_dev *dev; |
76 | struct device_node *dn = pci_bus_to_OF_node(bus); | 76 | struct device_node *dn = pci_bus_to_OF_node(bus); |
77 | 77 | ||
@@ -85,11 +85,15 @@ void pcibios_add_pci_devices(struct pci_bus * bus) | |||
85 | /* use ofdt-based probe */ | 85 | /* use ofdt-based probe */ |
86 | of_rescan_bus(dn, bus); | 86 | of_rescan_bus(dn, bus); |
87 | } else if (mode == PCI_PROBE_NORMAL) { | 87 | } else if (mode == PCI_PROBE_NORMAL) { |
88 | /* use legacy probe */ | 88 | /* |
89 | * Use legacy probe. In the partial hotplug case, we | ||
90 | * probably have grandchildren devices unplugged. So | ||
91 | * we don't check the return value from pci_scan_slot() in | ||
92 | * order for fully rescan all the way down to pick them up. | ||
93 | * They can have been removed during partial hotplug. | ||
94 | */ | ||
89 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); | 95 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); |
90 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); | 96 | pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); |
91 | if (!num) | ||
92 | return; | ||
93 | pcibios_setup_bus_devices(bus); | 97 | pcibios_setup_bus_devices(bus); |
94 | max = bus->busn_res.start; | 98 | max = bus->busn_res.start; |
95 | for (pass = 0; pass < 2; pass++) { | 99 | for (pass = 0; pass < 2; pass++) { |
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 6b0ba5854d99..15d9105323bf 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c | |||
@@ -230,11 +230,14 @@ void of_scan_pci_bridge(struct pci_dev *dev) | |||
230 | return; | 230 | return; |
231 | } | 231 | } |
232 | 232 | ||
233 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); | 233 | bus = pci_find_bus(pci_domain_nr(dev->bus), busrange[0]); |
234 | if (!bus) { | 234 | if (!bus) { |
235 | printk(KERN_ERR "Failed to create pci bus for %s\n", | 235 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); |
236 | node->full_name); | 236 | if (!bus) { |
237 | return; | 237 | printk(KERN_ERR "Failed to create pci bus for %s\n", |
238 | node->full_name); | ||
239 | return; | ||
240 | } | ||
238 | } | 241 | } |
239 | 242 | ||
240 | bus->primary = dev->bus->number; | 243 | bus->primary = dev->bus->number; |
@@ -292,6 +295,38 @@ void of_scan_pci_bridge(struct pci_dev *dev) | |||
292 | } | 295 | } |
293 | EXPORT_SYMBOL(of_scan_pci_bridge); | 296 | EXPORT_SYMBOL(of_scan_pci_bridge); |
294 | 297 | ||
298 | static struct pci_dev *of_scan_pci_dev(struct pci_bus *bus, | ||
299 | struct device_node *dn) | ||
300 | { | ||
301 | struct pci_dev *dev = NULL; | ||
302 | const u32 *reg; | ||
303 | int reglen, devfn; | ||
304 | |||
305 | pr_debug(" * %s\n", dn->full_name); | ||
306 | if (!of_device_is_available(dn)) | ||
307 | return NULL; | ||
308 | |||
309 | reg = of_get_property(dn, "reg", ®len); | ||
310 | if (reg == NULL || reglen < 20) | ||
311 | return NULL; | ||
312 | devfn = (reg[0] >> 8) & 0xff; | ||
313 | |||
314 | /* Check if the PCI device is already there */ | ||
315 | dev = pci_get_slot(bus, devfn); | ||
316 | if (dev) { | ||
317 | pci_dev_put(dev); | ||
318 | return dev; | ||
319 | } | ||
320 | |||
321 | /* create a new pci_dev for this device */ | ||
322 | dev = of_create_pci_dev(dn, bus, devfn); | ||
323 | if (!dev) | ||
324 | return NULL; | ||
325 | |||
326 | pr_debug(" dev header type: %x\n", dev->hdr_type); | ||
327 | return dev; | ||
328 | } | ||
329 | |||
295 | /** | 330 | /** |
296 | * __of_scan_bus - given a PCI bus node, setup bus and scan for child devices | 331 | * __of_scan_bus - given a PCI bus node, setup bus and scan for child devices |
297 | * @node: device tree node for the PCI bus | 332 | * @node: device tree node for the PCI bus |
@@ -302,8 +337,6 @@ static void __of_scan_bus(struct device_node *node, struct pci_bus *bus, | |||
302 | int rescan_existing) | 337 | int rescan_existing) |
303 | { | 338 | { |
304 | struct device_node *child; | 339 | struct device_node *child; |
305 | const u32 *reg; | ||
306 | int reglen, devfn; | ||
307 | struct pci_dev *dev; | 340 | struct pci_dev *dev; |
308 | 341 | ||
309 | pr_debug("of_scan_bus(%s) bus no %d...\n", | 342 | pr_debug("of_scan_bus(%s) bus no %d...\n", |
@@ -311,16 +344,7 @@ static void __of_scan_bus(struct device_node *node, struct pci_bus *bus, | |||
311 | 344 | ||
312 | /* Scan direct children */ | 345 | /* Scan direct children */ |
313 | for_each_child_of_node(node, child) { | 346 | for_each_child_of_node(node, child) { |
314 | pr_debug(" * %s\n", child->full_name); | 347 | dev = of_scan_pci_dev(bus, child); |
315 | if (!of_device_is_available(child)) | ||
316 | continue; | ||
317 | reg = of_get_property(child, "reg", ®len); | ||
318 | if (reg == NULL || reglen < 20) | ||
319 | continue; | ||
320 | devfn = (reg[0] >> 8) & 0xff; | ||
321 | |||
322 | /* create a new pci_dev for this device */ | ||
323 | dev = of_create_pci_dev(child, bus, devfn); | ||
324 | if (!dev) | 348 | if (!dev) |
325 | continue; | 349 | continue; |
326 | pr_debug(" dev header type: %x\n", dev->hdr_type); | 350 | pr_debug(" dev header type: %x\n", dev->hdr_type); |