diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 54 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 27 |
2 files changed, 50 insertions, 31 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 780db386c1f..0eaabd41474 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -37,6 +37,7 @@ #include <asm/machdep.h> #include <asm/ppc-pci.h> #include <asm/firmware.h> +#include <asm/eeh.h> static DEFINE_SPINLOCK(hose_spinlock); @@ -1074,31 +1075,17 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus) } } -static void __devinit __pcibios_fixup_bus(struct pci_bus *bus) +void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) { struct pci_dev *dev; pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, bus->self ? pci_name(bus->self) : "PHB"); - /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for - * now differently between 32 and 64 bits. - */ - if (bus->self != NULL) - pcibios_fixup_bridge(bus); - - /* Setup bus DMA mappings */ - if (ppc_md.pci_dma_bus_setup) - ppc_md.pci_dma_bus_setup(bus); - /* Setup DMA for all PCI devices on that bus */ list_for_each_entry(dev, &bus->devices, bus_list) pcibios_setup_new_device(dev); - /* Platform specific bus fixups */ - if (ppc_md.pcibios_fixup_bus) - ppc_md.pcibios_fixup_bus(bus); - /* Read default IRQs and fixup if necessary */ list_for_each_entry(dev, &bus->devices, bus_list) { pci_read_irq_line(dev); @@ -1107,25 +1094,39 @@ static void __devinit __pcibios_fixup_bus(struct pci_bus *bus) } } +void __devinit pcibios_setup_bus_self(struct pci_bus *bus) +{ + /* Fix up the bus resources */ + if (bus->self != NULL) + pcibios_fixup_bridge(bus); + + /* Platform specific bus fixups. This is currently only used + * by fsl_pci and I'm hoping getting rid of it at some point + */ + if (ppc_md.pcibios_fixup_bus) + ppc_md.pcibios_fixup_bus(bus); + + /* Setup bus DMA mappings */ + if (ppc_md.pci_dma_bus_setup) + ppc_md.pci_dma_bus_setup(bus); +} + void __devinit pcibios_fixup_bus(struct pci_bus *bus) { /* When called from the generic PCI probe, read PCI<->PCI bridge - * bases before proceeding + * bases. This isn't called when generating the PCI tree from + * the OF device-tree. */ if (bus->self != NULL) pci_read_bridge_bases(bus); - __pcibios_fixup_bus(bus); -} -EXPORT_SYMBOL(pcibios_fixup_bus); -/* When building a bus from the OF tree rather than probing, we need a - * slightly different version of the fixup which doesn't read the - * bridge bases using config space accesses - */ -void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus) -{ - __pcibios_fixup_bus(bus); + /* Now fixup the bus bus */ + pcibios_setup_bus_self(bus); + + /* Now fixup devices on that bus */ + pcibios_setup_bus_devices(bus); } +EXPORT_SYMBOL(pcibios_fixup_bus); static int skip_isa_ioresource_align(struct pci_dev *dev) { @@ -1392,6 +1393,7 @@ void __init pcibios_resource_survey(void) } #ifdef CONFIG_HOTPLUG + /* This is used by the pSeries hotplug driver to allocate resource * of newly plugged busses. We can try to consolidate with the * rest of the code later, for now, keep it as-is diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index e6e8813c364..39fadc6e149 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -189,8 +189,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, } EXPORT_SYMBOL(of_create_pci_dev); -void __devinit of_scan_bus(struct device_node *node, - struct pci_bus *bus) +static void __devinit __of_scan_bus(struct device_node *node, + struct pci_bus *bus, int rescan_existing) { struct device_node *child; const u32 *reg; @@ -215,8 +215,12 @@ void __devinit of_scan_bus(struct device_node *node, pr_debug(" dev header type: %x\n", dev->hdr_type); } - /* Ally all fixups */ - pcibios_fixup_of_probed_bus(bus); + /* Apply all fixups necessary. We don't fixup the bus "self" + * for an existing bridge that is being rescanned + */ + if (!rescan_existing) + pcibios_setup_bus_self(bus); + pcibios_setup_bus_devices(bus); /* Now scan child busses */ list_for_each_entry(dev, &bus->devices, bus_list) { @@ -228,7 +232,20 @@ void __devinit of_scan_bus(struct device_node *node, } } } -EXPORT_SYMBOL(of_scan_bus); + +void __devinit of_scan_bus(struct device_node *node, + struct pci_bus *bus) +{ + __of_scan_bus(node, bus, 0); +} +EXPORT_SYMBOL_GPL(of_scan_bus); + +void __devinit of_rescan_bus(struct device_node *node, + struct pci_bus *bus) +{ + __of_scan_bus(node, bus, 1); +} +EXPORT_SYMBOL_GPL(of_rescan_bus); void __devinit of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev) |