[POWERPC] EEH: restructure multi-function support
authorLinas Vepstas <linas@austin.ibm.com>
Mon, 19 Mar 2007 20:01:31 +0000 (15:01 -0500)
committerPaul Mackerras <paulus@samba.org>
Thu, 22 Mar 2007 11:52:57 +0000 (22:52 +1100)
Rework how multi-function PCI devices are identified and traversed.
This fixes a bug with multi-function recovery on Power4 that was
introduced by a recent Power4 EEH patch.

Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_driver.c

index eac2a631c5a1f6f85545f4b69694a447afaf8a1c..a56be71d1ede29fd91655aa924ab45c89d141d35 100644 (file)
@@ -282,7 +282,7 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag)
        dn = find_device_pe (dn);
 
        /* Back up one, since config addrs might be shared */
-       if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+       if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
                dn = dn->parent;
 
        PCI_DN(dn)->eeh_mode |= mode_flag;
@@ -316,7 +316,7 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
        dn = find_device_pe (dn);
        
        /* Back up one, since config addrs might be shared */
-       if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+       if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
                dn = dn->parent;
 
        PCI_DN(dn)->eeh_mode &= ~mode_flag;
index f5b4f7c20d7ae6ede9d8c94f37eca29b7ae9418c..8cc331eecc9d5975b0fd63ab4ac00ad699ed41dd 100644 (file)
@@ -249,6 +249,7 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata)
 
 static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
 {
+       struct device_node *dn;
        int cnt, rc;
 
        /* pcibios will clear the counter; save the value */
@@ -264,23 +265,20 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
        if (rc)
                return rc;
 
-       /* New-style config addrs might be shared across multiple devices,
-        * Walk over all functions on this device */
-       if (pe_dn->eeh_pe_config_addr) {
-               struct device_node *pe = pe_dn->node;
-               pe = pe->parent->child;
-               while (pe) {
-                       struct pci_dn *ppe = PCI_DN(pe);
-                       if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
-                               rtas_configure_bridge(ppe);
-                               eeh_restore_bars(ppe);
-                       }
-                       pe = pe->sibling;
+       /* Walk over all functions on this device.  */
+       dn = pe_dn->node;
+       if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
+               dn = dn->parent->child;
+
+       while (dn) {
+               struct pci_dn *ppe = PCI_DN(dn);
+               /* On Power4, always true because eeh_pe_config_addr=0 */
+               if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
+                       rtas_configure_bridge(ppe);
+                       eeh_restore_bars(ppe);
                }
-       } else {
-               rtas_configure_bridge(pe_dn);
-               eeh_restore_bars(pe_dn);
-       }
+               dn = dn->sibling;
+       }
 
        /* Give the system 5 seconds to finish running the user-space
         * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,