Commit 30424e38 authored by Sam Bobroff's avatar Sam Bobroff Committed by Michael Ellerman

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: default avatarSam Bobroff <sbobroff@linux.ibm.com>
[mpe: Minor formatting (clang-format)]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 2eae39f2
...@@ -39,6 +39,35 @@ struct eeh_rmv_data { ...@@ -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) ...@@ -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 */ *res = pci_ers_merge_result(*res, rc);
if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
if (*res == PCI_ERS_RESULT_NONE) *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) ...@@ -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 */ *res = pci_ers_merge_result(*res, rc);
if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
if (*res == PCI_ERS_RESULT_NONE) *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) ...@@ -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_merge_result(*res, rc);
(*res == PCI_ERS_RESULT_RECOVERED)) *res = rc;
if (*res == PCI_ERS_RESULT_DISCONNECT &&
rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
out: out:
eeh_pcid_put(dev); eeh_pcid_put(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment