diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-27 15:48:37 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-11-05 17:22:37 -0500 |
commit | 8b8da35804bb89eee23f9bcd5638e1f754bd4c91 (patch) | |
tree | 8ec1ba6ef03c88da5c37eec4825fff6524358b37 /arch/powerpc/kernel/pci_64.c | |
parent | ab56ced9c57b66862c687f3158045d15133f02d6 (diff) |
powerpc/pci: Split pcibios_fixup_bus() into bus setup and device setup
Currently, our PCI code uses the pcibios_fixup_bus() callback, which
is called by the generic code when probing PCI buses, for two
different things.
One is to set up things related to the bus itself, such as reading
bridge resources for P2P bridges, fixing them up, or setting up the
iommu's associated with bridges on some platforms.
The other is some setup for each individual device under that bridge,
mostly setting up DMA mappings and interrupts.
The problem is that this approach doesn't work well with PCI hotplug
when an existing bus is re-probed for new children. We fix this
problem by splitting pcibios_fixup_bus into two routines:
pcibios_setup_bus_self() is now called to setup the bus itself
pcibios_setup_bus_devices() is now called to setup devices
pcibios_fixup_bus() is then modified to call these two after reading the
bridge bases, and the OF based PCI probe is modified to avoid calling
into the first one when rescanning an existing bridge.
[paulus@samba.org - fixed eeh.h for 32-bit compile now that pci-common.c
is including it unconditionally.]
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/pci_64.c')
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index e6e8813c364a..39fadc6e1492 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, | |||
189 | } | 189 | } |
190 | EXPORT_SYMBOL(of_create_pci_dev); | 190 | EXPORT_SYMBOL(of_create_pci_dev); |
191 | 191 | ||
192 | void __devinit of_scan_bus(struct device_node *node, | 192 | static void __devinit __of_scan_bus(struct device_node *node, |
193 | struct pci_bus *bus) | 193 | struct pci_bus *bus, int rescan_existing) |
194 | { | 194 | { |
195 | struct device_node *child; | 195 | struct device_node *child; |
196 | const u32 *reg; | 196 | const u32 *reg; |
@@ -215,8 +215,12 @@ void __devinit of_scan_bus(struct device_node *node, | |||
215 | pr_debug(" dev header type: %x\n", dev->hdr_type); | 215 | pr_debug(" dev header type: %x\n", dev->hdr_type); |
216 | } | 216 | } |
217 | 217 | ||
218 | /* Ally all fixups */ | 218 | /* Apply all fixups necessary. We don't fixup the bus "self" |
219 | pcibios_fixup_of_probed_bus(bus); | 219 | * for an existing bridge that is being rescanned |
220 | */ | ||
221 | if (!rescan_existing) | ||
222 | pcibios_setup_bus_self(bus); | ||
223 | pcibios_setup_bus_devices(bus); | ||
220 | 224 | ||
221 | /* Now scan child busses */ | 225 | /* Now scan child busses */ |
222 | list_for_each_entry(dev, &bus->devices, bus_list) { | 226 | list_for_each_entry(dev, &bus->devices, bus_list) { |
@@ -228,7 +232,20 @@ void __devinit of_scan_bus(struct device_node *node, | |||
228 | } | 232 | } |
229 | } | 233 | } |
230 | } | 234 | } |
231 | EXPORT_SYMBOL(of_scan_bus); | 235 | |
236 | void __devinit of_scan_bus(struct device_node *node, | ||
237 | struct pci_bus *bus) | ||
238 | { | ||
239 | __of_scan_bus(node, bus, 0); | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(of_scan_bus); | ||
242 | |||
243 | void __devinit of_rescan_bus(struct device_node *node, | ||
244 | struct pci_bus *bus) | ||
245 | { | ||
246 | __of_scan_bus(node, bus, 1); | ||
247 | } | ||
248 | EXPORT_SYMBOL_GPL(of_rescan_bus); | ||
232 | 249 | ||
233 | void __devinit of_scan_pci_bridge(struct device_node *node, | 250 | void __devinit of_scan_pci_bridge(struct device_node *node, |
234 | struct pci_dev *dev) | 251 | struct pci_dev *dev) |