[PATCH] powerpc: fix dynamic PCI probe regression
authorJohn Rose <johnrose@austin.ibm.com>
Fri, 24 Feb 2006 17:34:23 +0000 (11:34 -0600)
committerPaul Mackerras <paulus@samba.org>
Tue, 28 Feb 2006 05:25:54 +0000 (16:25 +1100)
Some hotplug driver functions were migrated to the kernel for use by EEH
in commit 2bf6a8fa21570f37fd1789610da30f70a05ac5e3.

Previously, the PCI Hotplug module had been changed to use the new
OFDT-based PCI probe when appropriate:
5fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6

When rpaphp_pci_config_slot() was moved from the rpaphp driver to the
new kernel function pcibios_add_pci_devices(), the OFDT-based probe
stuff was dropped.  This patch restores it.

Signed-off-by: John Rose <johnrose@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/pci_dlpar.c
include/asm-powerpc/eeh.h

index 83578313ee7e7e635fb07663df1e64ab080dff94..2ab9dcdfb41579704c55d8c1a4ddc918e832d6ee 100644 (file)
@@ -893,6 +893,20 @@ void eeh_add_device_tree_early(struct device_node *dn)
 }
 EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
 
+void eeh_add_device_tree_late(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               eeh_add_device_late(dev);
+               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+                       struct pci_bus *subbus = dev->subordinate;
+                       if (subbus)
+                               eeh_add_device_tree_late(subbus);
+               }
+       }
+}
+
 /**
  * eeh_add_device_late - perform EEH initialization for the indicated pci device
  * @dev: pci device for which to set up EEH
index bdaa8aabdaa64c4388c5ca4d933464a0293aa6f0..f3bad900bbcf81a236b3f9c7f081ef97477bc16e 100644 (file)
@@ -106,6 +106,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
                        }
                }
        }
+
+       eeh_add_device_tree_late(bus);
 }
 EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
 
@@ -114,7 +116,6 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
 {
        u8 sec_busno;
        struct pci_bus *child_bus;
-       struct pci_dev *child_dev;
 
        /* Get busno of downstream bus */
        pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
@@ -129,10 +130,6 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
 
        pci_scan_child_bus(child_bus);
 
-       list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
-               eeh_add_device_late(child_dev);
-       }
-
        /* Fixup new pci devices without touching bus struct */
        pcibios_fixup_new_pci_devices(child_bus, 0);
 
@@ -160,18 +157,25 @@ pcibios_add_pci_devices(struct pci_bus * bus)
 
        eeh_add_device_tree_early(dn);
 
-       /* pci_scan_slot should find all children */
-       slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
-       num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
-       if (num) {
-               pcibios_fixup_new_pci_devices(bus, 1);
-               pci_bus_add_devices(bus);
-       }
+       if (_machine == PLATFORM_PSERIES_LPAR) {
+               /* use ofdt-based probe */
+               of_scan_bus(dn, bus);
+               if (!list_empty(&bus->devices)) {
+                       pcibios_fixup_new_pci_devices(bus, 0);
+                       pci_bus_add_devices(bus);
+               }
+       } else {
+               /* use legacy probe */
+               slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
+               num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
+               if (num) {
+                       pcibios_fixup_new_pci_devices(bus, 1);
+                       pci_bus_add_devices(bus);
+               }
 
-       list_for_each_entry(dev, &bus->devices, bus_list) {
-               eeh_add_device_late (dev);
-               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
-                       pcibios_pci_config_bridge(dev);
+               list_for_each_entry(dev, &bus->devices, bus_list)
+                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+                               pcibios_pci_config_bridge(dev);
        }
 }
 EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
index b263fb2fa6e4376312677746cc00a10911f676df..7dfb408fe2cac07830c3ed552aeeee3a8cafd8e2 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/string.h>
 
 struct pci_dev;
+struct pci_bus;
 struct device_node;
 
 #ifdef CONFIG_EEH
@@ -61,7 +62,7 @@ void __init pci_addr_cache_build(void);
  */
 void eeh_add_device_early(struct device_node *);
 void eeh_add_device_tree_early(struct device_node *);
-void eeh_add_device_late(struct pci_dev *);
+void eeh_add_device_tree_late(struct pci_bus *);
 
 /**
  * eeh_remove_device - undo EEH setup for the indicated pci device
@@ -116,12 +117,12 @@ static inline void pci_addr_cache_build(void) { }
 
 static inline void eeh_add_device_early(struct device_node *dn) { }
 
-static inline void eeh_add_device_late(struct pci_dev *dev) { }
-
 static inline void eeh_remove_device(struct pci_dev *dev) { }
 
 static inline void eeh_add_device_tree_early(struct device_node *dn) { }
 
+static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
+
 static inline void eeh_remove_bus_device(struct pci_dev *dev) { }
 #define EEH_POSSIBLE_ERROR(val, type) (0)
 #define EEH_IO_ERROR_VALUE(size) (-1UL)