powerpc/eeh: Make eeh_init() public
authorGavin Shan <shangw@linux.vnet.ibm.com>
Thu, 20 Jun 2013 05:20:56 +0000 (13:20 +0800)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Thu, 20 Jun 2013 07:05:48 +0000 (17:05 +1000)
For EEH on PowerNV platform, we will do EEH probe based on the
real PCI devices. The PCI devices are available after PCI probe.
So we have to call eeh_init() explicitly on PowerNV platform
after PCI probe. The patch also does EEH probe for PowerNV platform
in eeh_init().

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/eeh.h
arch/powerpc/kernel/eeh.c

index f3b49d6d5259ab67b4d22476d88a6a78c3b25a3a..beb3cbcb76f8677b8cf7b58430ff58eaceb18cbc 100644 (file)
@@ -132,7 +132,7 @@ struct eeh_ops {
        char *name;
        int (*init)(void);
        void* (*of_probe)(struct device_node *dn, void *flag);
-       void* (*dev_probe)(struct pci_dev *dev, void *flag);
+       int (*dev_probe)(struct pci_dev *dev, void *flag);
        int (*set_option)(struct eeh_pe *pe, int option);
        int (*get_pe_addr)(struct eeh_pe *pe);
        int (*get_state)(struct eeh_pe *pe, int *state);
@@ -196,6 +196,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
 
 void *eeh_dev_init(struct device_node *dn, void *data);
 void eeh_dev_phb_init_dynamic(struct pci_controller *phb);
+int __init eeh_init(void);
 int __init eeh_ops_register(struct eeh_ops *ops);
 int __exit eeh_ops_unregister(const char *name);
 unsigned long eeh_check_failure(const volatile void __iomem *token,
@@ -224,6 +225,11 @@ void eeh_remove_bus_device(struct pci_dev *, int);
 
 #else /* !CONFIG_EEH */
 
+static inline int eeh_init(void)
+{
+       return 0;
+}
+
 static inline void *eeh_dev_init(struct device_node *dn, void *data)
 {
        return NULL;
index 8a834519308309dad352409f762fdd6c2930e357..c865c5f54b1855650e8d458e50589501dc32d95d 100644 (file)
@@ -674,11 +674,21 @@ int __exit eeh_ops_unregister(const char *name)
  * Even if force-off is set, the EEH hardware is still enabled, so that
  * newer systems can boot.
  */
-static int __init eeh_init(void)
+int __init eeh_init(void)
 {
        struct pci_controller *hose, *tmp;
        struct device_node *phb;
-       int ret;
+       static int cnt = 0;
+       int ret = 0;
+
+       /*
+        * We have to delay the initialization on PowerNV after
+        * the PCI hierarchy tree has been built because the PEs
+        * are figured out based on PCI devices instead of device
+        * tree nodes
+        */
+       if (machine_is(powernv) && cnt++ <= 0)
+               return ret;
 
        /* call platform initialization function */
        if (!eeh_ops) {
@@ -700,6 +710,14 @@ static int __init eeh_init(void)
                        phb = hose->dn;
                        traverse_pci_devices(phb, eeh_ops->of_probe, NULL);
                }
+       } else if (eeh_probe_mode_dev()) {
+               list_for_each_entry_safe(hose, tmp,
+                       &hose_list, list_node)
+                       pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL);
+       } else {
+               pr_warning("%s: Invalid probe mode %d\n",
+                          __func__, eeh_probe_mode);
+               return -EINVAL;
        }
 
        if (eeh_subsystem_enabled)