powerpc/eeh: sysfs entries lost
authorMike Qiu <qiudayu@linux.vnet.ibm.com>
Thu, 26 Jun 2014 06:58:47 +0000 (02:58 -0400)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 5 Aug 2014 05:28:49 +0000 (15:28 +1000)
The sysfs entries are lost because of commit 2213fb1 ("powerpc/eeh:
Skip eeh sysfs when eeh is disabled"). That commit added condition
to create sysfs entries with EEH_ENABLED, which isn't populated
when trying to create sysfs entries on PowerNV platform during system
boot time. The patch fixes the issue by:

   * Reoder EEH initialization functions so that they're same on
     PowerNV/pSeries.
   * Cache PE's primary bus by PowerNV platform instead of EEH core
     to avoid kernel crash caused by the function reorder. Another
     benefit with this is to avoid one eeh_probe_mode_dev() in EEH
     core.

Signed-off-by: Mike Qiu <qiudayu@linux.vnet.ibm.com>
Acked-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/eeh_pe.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/pci-ioda.c

index fbd01eb..1dce071 100644 (file)
@@ -351,17 +351,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
        pe->config_addr = edev->config_addr;
 
        /*
-        * While doing PE reset, we probably hot-reset the
-        * upstream bridge. However, the PCI devices including
-        * the associated EEH devices might be removed when EEH
-        * core is doing recovery. So that won't safe to retrieve
-        * the bridge through downstream EEH device. We have to
-        * trace the parent PCI bus, then the upstream bridge.
-        */
-       if (eeh_probe_mode_dev())
-               pe->bus = eeh_dev_to_pci_dev(edev)->bus;
-
-       /*
         * Put the new EEH PE into hierarchy tree. If the parent
         * can't be found, the newly created PE will be attached
         * to PHB directly. Otherwise, we have to associate the
index 998bcc1..c3a5c2f 100644 (file)
@@ -107,6 +107,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
        struct pnv_phb *phb = hose->private_data;
        struct device_node *dn = pci_device_to_OF_node(dev);
        struct eeh_dev *edev = of_node_to_eeh_dev(dn);
+       int ret;
 
        /*
         * When probing the root bridge, which doesn't have any
@@ -143,7 +144,21 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
        edev->pe_config_addr    = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff);
 
        /* Create PE */
-       eeh_add_to_parent_pe(edev);
+       ret = eeh_add_to_parent_pe(edev);
+       if (ret) {
+               pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n",
+                       __func__, pci_name(dev), ret);
+               return ret;
+       }
+
+       /*
+        * Cache the PE primary bus, which can't be fetched when
+        * full hotplug is in progress. In that case, all child
+        * PCI devices of the PE are expected to be removed prior
+        * to PE reset.
+        */
+       if (!edev->pe->bus)
+               edev->pe->bus = dev->bus;
 
        /*
         * Enable EEH explicitly so that we will do EEH check
index 9f28e18..fa3029a 100644 (file)
@@ -1145,8 +1145,8 @@ static void pnv_pci_ioda_fixup(void)
 
 #ifdef CONFIG_EEH
        eeh_probe_mode_set(EEH_PROBE_MODE_DEV);
-       eeh_addr_cache_build();
        eeh_init();
+       eeh_addr_cache_build();
 #endif
 }