]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - arch/powerpc/kernel/eeh.c
Merge tag 'docs-4.10-2' of git://git.lwn.net/linux
[mirror_ubuntu-bionic-kernel.git] / arch / powerpc / kernel / eeh.c
index f25731627d7f472a44e25bf48e61cffcc2c51055..8180bfd7ab931c5b6d16a1c1b7cb73689206571b 100644 (file)
@@ -372,7 +372,7 @@ static int eeh_phb_check_failure(struct eeh_pe *pe)
        /* Find the PHB PE */
        phb_pe = eeh_phb_pe_get(pe->phb);
        if (!phb_pe) {
-               pr_warn("%s Can't find PE for PHB#%d\n",
+               pr_warn("%s Can't find PE for PHB#%x\n",
                        __func__, pe->phb->global_number);
                return -EEXIST;
        }
@@ -664,7 +664,7 @@ int eeh_pci_enable(struct eeh_pe *pe, int function)
        rc = eeh_ops->set_option(pe, function);
        if (rc)
                pr_warn("%s: Unexpected state change %d on "
-                       "PHB#%d-PE#%x, err=%d\n",
+                       "PHB#%x-PE#%x, err=%d\n",
                        __func__, function, pe->phb->global_number,
                        pe->addr, rc);
 
@@ -808,76 +808,67 @@ static void *eeh_set_dev_freset(void *data, void *flag)
 }
 
 /**
- * eeh_reset_pe_once - Assert the pci #RST line for 1/4 second
+ * eeh_pe_reset_full - Complete a full reset process on the indicated PE
  * @pe: EEH PE
  *
- * Assert the PCI #RST line for 1/4 second.
+ * This function executes a full reset procedure on a PE, including setting
+ * the appropriate flags, performing a fundamental or hot reset, and then
+ * deactivating the reset status.  It is designed to be used within the EEH
+ * subsystem, as opposed to eeh_pe_reset which is exported to drivers and
+ * only performs a single operation at a time.
+ *
+ * This function will attempt to reset a PE three times before failing.
  */
-static void eeh_reset_pe_once(struct eeh_pe *pe)
+int eeh_pe_reset_full(struct eeh_pe *pe)
 {
+       int active_flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
+       int reset_state = (EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
+       int type = EEH_RESET_HOT;
        unsigned int freset = 0;
+       int i, state, ret;
 
-       /* Determine type of EEH reset required for
-        * Partitionable Endpoint, a hot-reset (1)
-        * or a fundamental reset (3).
-        * A fundamental reset required by any device under
-        * Partitionable Endpoint trumps hot-reset.
+       /*
+        * Determine the type of reset to perform - hot or fundamental.
+        * Hot reset is the default operation, unless any device under the
+        * PE requires a fundamental reset.
         */
        eeh_pe_dev_traverse(pe, eeh_set_dev_freset, &freset);
 
        if (freset)
-               eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
-       else
-               eeh_ops->reset(pe, EEH_RESET_HOT);
-
-       eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
-}
-
-/**
- * eeh_reset_pe - Reset the indicated PE
- * @pe: EEH PE
- *
- * This routine should be called to reset indicated device, including
- * PE. A PE might include multiple PCI devices and sometimes PCI bridges
- * might be involved as well.
- */
-int eeh_reset_pe(struct eeh_pe *pe)
-{
-       int flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
-       int i, state, ret;
+               type = EEH_RESET_FUNDAMENTAL;
 
-       /* Mark as reset and block config space */
-       eeh_pe_state_mark(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
+       /* Mark the PE as in reset state and block config space accesses */
+       eeh_pe_state_mark(pe, reset_state);
 
-       /* Take three shots at resetting the bus */
+       /* Make three attempts at resetting the bus */
        for (i = 0; i < 3; i++) {
-               eeh_reset_pe_once(pe);
+               ret = eeh_pe_reset(pe, type);
+               if (ret)
+                       break;
 
-               /*
-                * EEH_PE_ISOLATED is expected to be removed after
-                * BAR restore.
-                */
+               ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE);
+               if (ret)
+                       break;
+
+               /* Wait until the PE is in a functioning state */
                state = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
-               if ((state & flags) == flags) {
-                       ret = 0;
-                       goto out;
-               }
+               if ((state & active_flags) == active_flags)
+                       break;
 
                if (state < 0) {
-                       pr_warn("%s: Unrecoverable slot failure on PHB#%d-PE#%x",
+                       pr_warn("%s: Unrecoverable slot failure on PHB#%x-PE#%x",
                                __func__, pe->phb->global_number, pe->addr);
                        ret = -ENOTRECOVERABLE;
-                       goto out;
+                       break;
                }
 
-               /* We might run out of credits */
+               /* Set error in case this is our last attempt */
                ret = -EIO;
                pr_warn("%s: Failure %d resetting PHB#%x-PE#%x\n (%d)\n",
                        __func__, state, pe->phb->global_number, pe->addr, (i + 1));
        }
 
-out:
-       eeh_pe_state_clear(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
+       eeh_pe_state_clear(pe, reset_state);
        return ret;
 }
 
@@ -1601,6 +1592,7 @@ static int eeh_pe_reenable_devices(struct eeh_pe *pe)
        return eeh_unfreeze_pe(pe, true);
 }
 
+
 /**
  * eeh_pe_reset - Issue PE reset according to specified type
  * @pe: EEH PE