diff options
author | Vaibhav Jain <vaibhav@linux.vnet.ibm.com> | 2017-04-27 01:28:22 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-25 09:44:37 -0400 |
commit | 168b2bfaa235e91c2f7a76ac693435e530f486b3 (patch) | |
tree | c7644be65fa3d624977a84a899c3769059cc3cf0 /drivers/misc | |
parent | 3935312995473ce0abc40582d5cda31da3594294 (diff) |
cxl: Route eeh events to all drivers in cxl_pci_error_detected()
commit 4f58f0bf155e87dda31a3088b1e107fa9dd79f0e upstream.
Fix a boundary condition where in some cases an eeh event that results
in card reset isn't passed on to a driver attached to the virtual PCI
device associated with a slice. This will happen in case when a slice
attached device driver returns a value other than
PCI_ERS_RESULT_NEED_RESET from the eeh error_detected() callback. This
would result in an early return from cxl_pci_error_detected() and
other drivers attached to other AFUs on the card wont be notified.
The patch fixes this by making sure that all slice attached
device-drivers are notified and the return values from
error_detected() callback are aggregated in a scheme where request for
'disconnect' trumps all and 'none' trumps 'need_reset'.
Fixes: 9e8df8a21963 ("cxl: EEH support")
Signed-off-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
Acked-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/cxl/pci.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 80b1a7e87888..fa4fe02cfef4 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
@@ -1779,7 +1779,7 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev, | |||
1779 | { | 1779 | { |
1780 | struct cxl *adapter = pci_get_drvdata(pdev); | 1780 | struct cxl *adapter = pci_get_drvdata(pdev); |
1781 | struct cxl_afu *afu; | 1781 | struct cxl_afu *afu; |
1782 | pci_ers_result_t result = PCI_ERS_RESULT_NEED_RESET; | 1782 | pci_ers_result_t result = PCI_ERS_RESULT_NEED_RESET, afu_result; |
1783 | int i; | 1783 | int i; |
1784 | 1784 | ||
1785 | /* At this point, we could still have an interrupt pending. | 1785 | /* At this point, we could still have an interrupt pending. |
@@ -1884,15 +1884,18 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev, | |||
1884 | for (i = 0; i < adapter->slices; i++) { | 1884 | for (i = 0; i < adapter->slices; i++) { |
1885 | afu = adapter->afu[i]; | 1885 | afu = adapter->afu[i]; |
1886 | 1886 | ||
1887 | result = cxl_vphb_error_detected(afu, state); | 1887 | afu_result = cxl_vphb_error_detected(afu, state); |
1888 | |||
1889 | /* Only continue if everyone agrees on NEED_RESET */ | ||
1890 | if (result != PCI_ERS_RESULT_NEED_RESET) | ||
1891 | return result; | ||
1892 | 1888 | ||
1893 | cxl_context_detach_all(afu); | 1889 | cxl_context_detach_all(afu); |
1894 | cxl_ops->afu_deactivate_mode(afu, afu->current_mode); | 1890 | cxl_ops->afu_deactivate_mode(afu, afu->current_mode); |
1895 | pci_deconfigure_afu(afu); | 1891 | pci_deconfigure_afu(afu); |
1892 | |||
1893 | /* Disconnect trumps all, NONE trumps NEED_RESET */ | ||
1894 | if (afu_result == PCI_ERS_RESULT_DISCONNECT) | ||
1895 | result = PCI_ERS_RESULT_DISCONNECT; | ||
1896 | else if ((afu_result == PCI_ERS_RESULT_NONE) && | ||
1897 | (result == PCI_ERS_RESULT_NEED_RESET)) | ||
1898 | result = PCI_ERS_RESULT_NONE; | ||
1896 | } | 1899 | } |
1897 | 1900 | ||
1898 | /* should take the context lock here */ | 1901 | /* should take the context lock here */ |