Browse Source

powerpc/eeh: Clean up pci_ers_result handling

As EEH event handling progresses, a cumulative result of type
pci_ers_result is built up by (some of) the eeh_report_*() functions
using either:
	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
or:
	if ((*res == PCI_ERS_RESULT_NONE) ||
	    (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc;
	if (*res == PCI_ERS_RESULT_DISCONNECT &&
	    rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
(Where *res is the accumulator.)

However, the intent is not immediately clear and the result in some
situations is order dependent.

Address this by assigning a priority to each result value, and always
merging to the highest priority. This renders the intent clear, and
provides a stable value for all orderings.

Signed-off-by: Sam Bobroff <sbobroff@linux.ibm.com>
[mpe: Minor formatting (clang-format)]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Sam Bobroff 7 years ago
parent
commit
30424e386a
1 changed files with 32 additions and 10 deletions
  1. 32 10
      arch/powerpc/kernel/eeh_driver.c

+ 32 - 10
arch/powerpc/kernel/eeh_driver.c

@@ -39,6 +39,35 @@ struct eeh_rmv_data {
 	int removed;
 	int removed;
 };
 };
 
 
+static int eeh_result_priority(enum pci_ers_result result)
+{
+	switch (result) {
+	case PCI_ERS_RESULT_NONE:
+		return 1;
+	case PCI_ERS_RESULT_NO_AER_DRIVER:
+		return 2;
+	case PCI_ERS_RESULT_RECOVERED:
+		return 3;
+	case PCI_ERS_RESULT_CAN_RECOVER:
+		return 4;
+	case PCI_ERS_RESULT_DISCONNECT:
+		return 5;
+	case PCI_ERS_RESULT_NEED_RESET:
+		return 6;
+	default:
+		WARN_ONCE(1, "Unknown pci_ers_result value: %d\n", (int)result);
+		return 0;
+	}
+};
+
+static enum pci_ers_result pci_ers_merge_result(enum pci_ers_result old,
+						enum pci_ers_result new)
+{
+	if (eeh_result_priority(new) > eeh_result_priority(old))
+		return new;
+	return old;
+}
+
 /**
 /**
  * eeh_pcid_get - Get the PCI device driver
  * eeh_pcid_get - Get the PCI device driver
  * @pdev: PCI device
  * @pdev: PCI device
@@ -206,9 +235,7 @@ static void *eeh_report_error(struct eeh_dev *edev, void *userdata)
 
 
 	rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
 	rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
 
 
-	/* A driver that needs a reset trumps all others */
-	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
-	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+	*res = pci_ers_merge_result(*res, rc);
 
 
 	edev->in_error = true;
 	edev->in_error = true;
 	pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
 	pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
@@ -249,9 +276,7 @@ static void *eeh_report_mmio_enabled(struct eeh_dev *edev, void *userdata)
 
 
 	rc = driver->err_handler->mmio_enabled(dev);
 	rc = driver->err_handler->mmio_enabled(dev);
 
 
-	/* A driver that needs a reset trumps all others */
-	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
-	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+	*res = pci_ers_merge_result(*res, rc);
 
 
 out:
 out:
 	eeh_pcid_put(dev);
 	eeh_pcid_put(dev);
@@ -294,10 +319,7 @@ static void *eeh_report_reset(struct eeh_dev *edev, void *userdata)
 		goto out;
 		goto out;
 
 
 	rc = driver->err_handler->slot_reset(dev);
 	rc = driver->err_handler->slot_reset(dev);
-	if ((*res == PCI_ERS_RESULT_NONE) ||
-	    (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc;
-	if (*res == PCI_ERS_RESULT_DISCONNECT &&
-	     rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
+	*res = pci_ers_merge_result(*res, rc);
 
 
 out:
 out:
 	eeh_pcid_put(dev);
 	eeh_pcid_put(dev);