diff options
Diffstat (limited to 'arch/powerpc/kernel/pci_of_scan.c')
-rw-r--r-- | arch/powerpc/kernel/pci_of_scan.c | 56 |
1 files changed, 40 insertions, 16 deletions
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); |