powerpc/powernv: Drop PHB operation post_init()
authorGavin Shan <gwshan@linux.vnet.ibm.com>
Mon, 16 Feb 2015 03:45:41 +0000 (14:45 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 16 Mar 2015 23:31:18 +0000 (10:31 +1100)
The patch drops PHB EEH operation post_init() and merge its logic
to eeh_ops::post_init().

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

index dd154cf..bd509ad 100644 (file)
 #include "powernv.h"
 #include "pci.h"
 
-static int ioda_eeh_nb_init = 0;
-
-static int ioda_eeh_event(struct notifier_block *nb,
-                         unsigned long events, void *change)
-{
-       uint64_t changed_evts = (uint64_t)change;
-
-       /*
-        * We simply send special EEH event if EEH has
-        * been enabled, or clear pending events in
-        * case that we enable EEH soon
-        */
-       if (!(changed_evts & OPAL_EVENT_PCI_ERROR) ||
-           !(events & OPAL_EVENT_PCI_ERROR))
-               return 0;
-
-       if (eeh_enabled())
-               eeh_send_failure_event(NULL);
-       else
-               opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul);
-
-       return 0;
-}
-
-static struct notifier_block ioda_eeh_nb = {
-       .notifier_call  = ioda_eeh_event,
-       .next           = NULL,
-       .priority       = 0
-};
-
-#ifdef CONFIG_DEBUG_FS
-static ssize_t ioda_eeh_ei_write(struct file *filp,
-                                const char __user *user_buf,
-                                size_t count, loff_t *ppos)
-{
-       struct pci_controller *hose = filp->private_data;
-       struct eeh_dev *edev;
-       struct eeh_pe *pe;
-       int pe_no, type, func;
-       unsigned long addr, mask;
-       char buf[50];
-       int ret;
-
-       if (!eeh_ops || !eeh_ops->err_inject)
-               return -ENXIO;
-
-       ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count);
-       if (!ret)
-               return -EFAULT;
-
-       /* Retrieve parameters */
-       ret = sscanf(buf, "%x:%x:%x:%lx:%lx",
-                    &pe_no, &type, &func, &addr, &mask);
-       if (ret != 5)
-               return -EINVAL;
-
-       /* Retrieve PE */
-       edev = kzalloc(sizeof(*edev), GFP_KERNEL);
-       if (!edev)
-               return -ENOMEM;
-       edev->phb = hose;
-       edev->pe_config_addr = pe_no;
-       pe = eeh_pe_get(edev);
-       kfree(edev);
-       if (!pe)
-               return -ENODEV;
-
-       /* Do error injection */
-       ret = eeh_ops->err_inject(pe, type, func, addr, mask);
-       return ret < 0 ? ret : count;
-}
-
-static const struct file_operations ioda_eeh_ei_fops = {
-       .open   = simple_open,
-       .llseek = no_llseek,
-       .write  = ioda_eeh_ei_write,
-};
-
-static int ioda_eeh_dbgfs_set(void *data, int offset, u64 val)
-{
-       struct pci_controller *hose = data;
-       struct pnv_phb *phb = hose->private_data;
-
-       out_be64(phb->regs + offset, val);
-       return 0;
-}
-
-static int ioda_eeh_dbgfs_get(void *data, int offset, u64 *val)
-{
-       struct pci_controller *hose = data;
-       struct pnv_phb *phb = hose->private_data;
-
-       *val = in_be64(phb->regs + offset);
-       return 0;
-}
-
-static int ioda_eeh_outb_dbgfs_set(void *data, u64 val)
-{
-       return ioda_eeh_dbgfs_set(data, 0xD10, val);
-}
-
-static int ioda_eeh_outb_dbgfs_get(void *data, u64 *val)
-{
-       return ioda_eeh_dbgfs_get(data, 0xD10, val);
-}
-
-static int ioda_eeh_inbA_dbgfs_set(void *data, u64 val)
-{
-       return ioda_eeh_dbgfs_set(data, 0xD90, val);
-}
-
-static int ioda_eeh_inbA_dbgfs_get(void *data, u64 *val)
-{
-       return ioda_eeh_dbgfs_get(data, 0xD90, val);
-}
-
-static int ioda_eeh_inbB_dbgfs_set(void *data, u64 val)
-{
-       return ioda_eeh_dbgfs_set(data, 0xE10, val);
-}
-
-static int ioda_eeh_inbB_dbgfs_get(void *data, u64 *val)
-{
-       return ioda_eeh_dbgfs_get(data, 0xE10, val);
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_outb_dbgfs_ops, ioda_eeh_outb_dbgfs_get,
-                       ioda_eeh_outb_dbgfs_set, "0x%llx\n");
-DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbA_dbgfs_ops, ioda_eeh_inbA_dbgfs_get,
-                       ioda_eeh_inbA_dbgfs_set, "0x%llx\n");
-DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbB_dbgfs_ops, ioda_eeh_inbB_dbgfs_get,
-                       ioda_eeh_inbB_dbgfs_set, "0x%llx\n");
-#endif /* CONFIG_DEBUG_FS */
-
-
-/**
- * ioda_eeh_post_init - Chip dependent post initialization
- * @hose: PCI controller
- *
- * The function will be called after eeh PEs and devices
- * have been built. That means the EEH is ready to supply
- * service with I/O cache.
- */
-static int ioda_eeh_post_init(struct pci_controller *hose)
-{
-       struct pnv_phb *phb = hose->private_data;
-       int ret;
-
-       /* Register OPAL event notifier */
-       if (!ioda_eeh_nb_init) {
-               ret = opal_notifier_register(&ioda_eeh_nb);
-               if (ret) {
-                       pr_err("%s: Can't register OPAL event notifier (%d)\n",
-                              __func__, ret);
-                       return ret;
-               }
-
-               ioda_eeh_nb_init = 1;
-       }
-
-#ifdef CONFIG_DEBUG_FS
-       if (!phb->has_dbgfs && phb->dbgfs) {
-               phb->has_dbgfs = 1;
-
-               debugfs_create_file("err_injct", 0200,
-                                   phb->dbgfs, hose,
-                                   &ioda_eeh_ei_fops);
-
-               debugfs_create_file("err_injct_outbound", 0600,
-                                   phb->dbgfs, hose,
-                                   &ioda_eeh_outb_dbgfs_ops);
-               debugfs_create_file("err_injct_inboundA", 0600,
-                                   phb->dbgfs, hose,
-                                   &ioda_eeh_inbA_dbgfs_ops);
-               debugfs_create_file("err_injct_inboundB", 0600,
-                                   phb->dbgfs, hose,
-                                   &ioda_eeh_inbB_dbgfs_ops);
-       }
-#endif
-
-       /* If EEH is enabled, we're going to rely on that.
-        * Otherwise, we restore to conventional mechanism
-        * to clear frozen PE during PCI config access.
-        */
-       if (eeh_enabled())
-               phb->flags |= PNV_PHB_FLAG_EEH;
-       else
-               phb->flags &= ~PNV_PHB_FLAG_EEH;
-
-       return 0;
-}
-
 /**
  * ioda_eeh_set_option - Set EEH operation or I/O setting
  * @pe: EEH PE
@@ -1094,7 +902,6 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
 }
 
 struct pnv_eeh_ops ioda_eeh_ops = {
-       .post_init              = ioda_eeh_post_init,
        .set_option             = ioda_eeh_set_option,
        .get_state              = ioda_eeh_get_state,
        .reset                  = ioda_eeh_reset,
index df33daa..641ba33 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/atomic.h>
+#include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/init.h>
@@ -38,6 +39,8 @@
 #include "powernv.h"
 #include "pci.h"
 
+static bool pnv_eeh_nb_init = false;
+
 /**
  * pnv_eeh_init - EEH platform dependent initialization
  *
@@ -85,6 +88,139 @@ static int pnv_eeh_init(void)
        return 0;
 }
 
+static int pnv_eeh_event(struct notifier_block *nb,
+                        unsigned long events, void *change)
+{
+       uint64_t changed_evts = (uint64_t)change;
+
+       /*
+        * We simply send special EEH event if EEH has
+        * been enabled, or clear pending events in
+        * case that we enable EEH soon
+        */
+       if (!(changed_evts & OPAL_EVENT_PCI_ERROR) ||
+           !(events & OPAL_EVENT_PCI_ERROR))
+               return 0;
+
+       if (eeh_enabled())
+               eeh_send_failure_event(NULL);
+       else
+               opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul);
+
+       return 0;
+}
+
+static struct notifier_block pnv_eeh_nb = {
+       .notifier_call  = pnv_eeh_event,
+       .next           = NULL,
+       .priority       = 0
+};
+
+#ifdef CONFIG_DEBUG_FS
+static ssize_t pnv_eeh_ei_write(struct file *filp,
+                               const char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       struct pci_controller *hose = filp->private_data;
+       struct eeh_dev *edev;
+       struct eeh_pe *pe;
+       int pe_no, type, func;
+       unsigned long addr, mask;
+       char buf[50];
+       int ret;
+
+       if (!eeh_ops || !eeh_ops->err_inject)
+               return -ENXIO;
+
+       /* Copy over argument buffer */
+       ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count);
+       if (!ret)
+               return -EFAULT;
+
+       /* Retrieve parameters */
+       ret = sscanf(buf, "%x:%x:%x:%lx:%lx",
+                    &pe_no, &type, &func, &addr, &mask);
+       if (ret != 5)
+               return -EINVAL;
+
+       /* Retrieve PE */
+       edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+       if (!edev)
+               return -ENOMEM;
+       edev->phb = hose;
+       edev->pe_config_addr = pe_no;
+       pe = eeh_pe_get(edev);
+       kfree(edev);
+       if (!pe)
+               return -ENODEV;
+
+       /* Do error injection */
+       ret = eeh_ops->err_inject(pe, type, func, addr, mask);
+       return ret < 0 ? ret : count;
+}
+
+static const struct file_operations pnv_eeh_ei_fops = {
+       .open   = simple_open,
+       .llseek = no_llseek,
+       .write  = pnv_eeh_ei_write,
+};
+
+static int pnv_eeh_dbgfs_set(void *data, int offset, u64 val)
+{
+       struct pci_controller *hose = data;
+       struct pnv_phb *phb = hose->private_data;
+
+       out_be64(phb->regs + offset, val);
+       return 0;
+}
+
+static int pnv_eeh_dbgfs_get(void *data, int offset, u64 *val)
+{
+       struct pci_controller *hose = data;
+       struct pnv_phb *phb = hose->private_data;
+
+       *val = in_be64(phb->regs + offset);
+       return 0;
+}
+
+static int pnv_eeh_outb_dbgfs_set(void *data, u64 val)
+{
+       return pnv_eeh_dbgfs_set(data, 0xD10, val);
+}
+
+static int pnv_eeh_outb_dbgfs_get(void *data, u64 *val)
+{
+       return pnv_eeh_dbgfs_get(data, 0xD10, val);
+}
+
+static int pnv_eeh_inbA_dbgfs_set(void *data, u64 val)
+{
+       return pnv_eeh_dbgfs_set(data, 0xD90, val);
+}
+
+static int pnv_eeh_inbA_dbgfs_get(void *data, u64 *val)
+{
+       return pnv_eeh_dbgfs_get(data, 0xD90, val);
+}
+
+static int pnv_eeh_inbB_dbgfs_set(void *data, u64 val)
+{
+       return pnv_eeh_dbgfs_set(data, 0xE10, val);
+}
+
+static int pnv_eeh_inbB_dbgfs_get(void *data, u64 *val)
+{
+       return pnv_eeh_dbgfs_get(data, 0xE10, val);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_outb_dbgfs_ops, pnv_eeh_outb_dbgfs_get,
+                       pnv_eeh_outb_dbgfs_set, "0x%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_inbA_dbgfs_ops, pnv_eeh_inbA_dbgfs_get,
+                       pnv_eeh_inbA_dbgfs_set, "0x%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_inbB_dbgfs_ops, pnv_eeh_inbB_dbgfs_get,
+                       pnv_eeh_inbB_dbgfs_set, "0x%llx\n");
+#endif /* CONFIG_DEBUG_FS */
+
 /**
  * pnv_eeh_post_init - EEH platform dependent post initialization
  *
@@ -99,16 +235,54 @@ static int pnv_eeh_post_init(void)
        struct pnv_phb *phb;
        int ret = 0;
 
+       /* Register OPAL event notifier */
+       if (!pnv_eeh_nb_init) {
+               ret = opal_notifier_register(&pnv_eeh_nb);
+               if (ret) {
+                       pr_warn("%s: Can't register OPAL event notifier (%d)\n",
+                               __func__, ret);
+                       return ret;
+               }
+
+               pnv_eeh_nb_init = true;
+       }
+
        list_for_each_entry(hose, &hose_list, list_node) {
                phb = hose->private_data;
 
-               if (phb->eeh_ops && phb->eeh_ops->post_init) {
-                       ret = phb->eeh_ops->post_init(hose);
-                       if (ret)
-                               break;
-               }
+               /*
+                * If EEH is enabled, we're going to rely on that.
+                * Otherwise, we restore to conventional mechanism
+                * to clear frozen PE during PCI config access.
+                */
+               if (eeh_enabled())
+                       phb->flags |= PNV_PHB_FLAG_EEH;
+               else
+                       phb->flags &= ~PNV_PHB_FLAG_EEH;
+
+               /* Create debugfs entries */
+#ifdef CONFIG_DEBUG_FS
+               if (phb->has_dbgfs || !phb->dbgfs)
+                       continue;
+
+               phb->has_dbgfs = 1;
+               debugfs_create_file("err_injct", 0200,
+                                   phb->dbgfs, hose,
+                                   &pnv_eeh_ei_fops);
+
+               debugfs_create_file("err_injct_outbound", 0600,
+                                   phb->dbgfs, hose,
+                                   &pnv_eeh_outb_dbgfs_ops);
+               debugfs_create_file("err_injct_inboundA", 0600,
+                                   phb->dbgfs, hose,
+                                   &pnv_eeh_inbA_dbgfs_ops);
+               debugfs_create_file("err_injct_inboundB", 0600,
+                                   phb->dbgfs, hose,
+                                   &pnv_eeh_inbB_dbgfs_ops);
+#endif /* CONFIG_DEBUG_FS */
        }
 
+
        return ret;
 }
 
index a9f2362..c7e047f 100644 (file)
@@ -78,7 +78,6 @@ struct pnv_ioda_pe {
 /* IOC dependent EEH operations */
 #ifdef CONFIG_EEH
 struct pnv_eeh_ops {
-       int (*post_init)(struct pci_controller *hose);
        int (*set_option)(struct eeh_pe *pe, int option);
        int (*get_state)(struct eeh_pe *pe);
        int (*reset)(struct eeh_pe *pe, int option);