Skip to content

Commit 1d7ff41

Browse files
author
Mete Durlu
committed
s390/pci: Allow automatic recovery with minimal driver support
JIRA: https://issues.redhat.com/browse/RHEL-110239 commit 62355f1 Author: Niklas Schnelle <schnelle@linux.ibm.com> Date: Wed Jun 25 11:28:30 2025 +0200 s390/pci: Allow automatic recovery with minimal driver support According to Documentation/PCI/pci-error-recovery.rst only the error_detected() callback in the err_handler struct is mandatory for a driver to support error recovery. So far s390's error recovery chose a stricter approach also requiring slot_reset() and resume(). Relax this requirement and only require error_detected(). If a callback is not implemented EEH and AER treat this as PCI_ERS_RESULT_NONE. This return value is otherwise used by drivers abstaining from their vote on how to proceed with recovery and currently also not supported by s390's recovery code. So to support missing callbacks in-line with other implementors of the recovery flow, also handle PCI_ERS_RESULT_NONE. Since s390 only does per PCI function recovery and does not do voting, treat PCI_ERS_RESULT_NONE optimistically and proceed through recovery unless other failures prevent this. Reviewed-by: Farhan Ali <alifm@linux.ibm.com> Reviewed-by: Julian Ruess <julianr@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Mete Durlu <mdurlu@redhat.com>
1 parent 5787e90 commit 1d7ff41

File tree

1 file changed

+29
-15
lines changed

1 file changed

+29
-15
lines changed

arch/s390/pci/pci_event.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static inline bool ers_result_indicates_abort(pci_ers_result_t ers_res)
5454
case PCI_ERS_RESULT_CAN_RECOVER:
5555
case PCI_ERS_RESULT_RECOVERED:
5656
case PCI_ERS_RESULT_NEED_RESET:
57+
case PCI_ERS_RESULT_NONE:
5758
return false;
5859
default:
5960
return true;
@@ -78,10 +79,6 @@ static bool is_driver_supported(struct pci_driver *driver)
7879
return false;
7980
if (!driver->err_handler->error_detected)
8081
return false;
81-
if (!driver->err_handler->slot_reset)
82-
return false;
83-
if (!driver->err_handler->resume)
84-
return false;
8582
return true;
8683
}
8784

@@ -114,16 +111,18 @@ static pci_ers_result_t zpci_event_do_error_state_clear(struct pci_dev *pdev,
114111
return PCI_ERS_RESULT_NEED_RESET;
115112
}
116113

117-
if (driver->err_handler->mmio_enabled) {
114+
if (driver->err_handler->mmio_enabled)
118115
ers_res = driver->err_handler->mmio_enabled(pdev);
119-
if (ers_result_indicates_abort(ers_res)) {
120-
pr_info("%s: Automatic recovery failed after MMIO re-enable\n",
121-
pci_name(pdev));
122-
return ers_res;
123-
} else if (ers_res == PCI_ERS_RESULT_NEED_RESET) {
124-
pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev));
125-
return ers_res;
126-
}
116+
else
117+
ers_res = PCI_ERS_RESULT_NONE;
118+
119+
if (ers_result_indicates_abort(ers_res)) {
120+
pr_info("%s: Automatic recovery failed after MMIO re-enable\n",
121+
pci_name(pdev));
122+
return ers_res;
123+
} else if (ers_res == PCI_ERS_RESULT_NEED_RESET) {
124+
pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev));
125+
return ers_res;
127126
}
128127

129128
pr_debug("%s: Unblocking DMA\n", pci_name(pdev));
@@ -150,7 +149,12 @@ static pci_ers_result_t zpci_event_do_reset(struct pci_dev *pdev,
150149
return ers_res;
151150
}
152151
pdev->error_state = pci_channel_io_normal;
153-
ers_res = driver->err_handler->slot_reset(pdev);
152+
153+
if (driver->err_handler->slot_reset)
154+
ers_res = driver->err_handler->slot_reset(pdev);
155+
else
156+
ers_res = PCI_ERS_RESULT_NONE;
157+
154158
if (ers_result_indicates_abort(ers_res)) {
155159
pr_info("%s: Automatic recovery failed after slot reset\n", pci_name(pdev));
156160
return ers_res;
@@ -214,7 +218,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
214218
goto out_unlock;
215219
}
216220

217-
if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) {
221+
if (ers_res != PCI_ERS_RESULT_NEED_RESET) {
218222
ers_res = zpci_event_do_error_state_clear(pdev, driver);
219223
if (ers_result_indicates_abort(ers_res)) {
220224
status_str = "failed (abort on MMIO enable)";
@@ -225,6 +229,16 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
225229
if (ers_res == PCI_ERS_RESULT_NEED_RESET)
226230
ers_res = zpci_event_do_reset(pdev, driver);
227231

232+
/*
233+
* ers_res can be PCI_ERS_RESULT_NONE either because the driver
234+
* decided to return it, indicating that it abstains from voting
235+
* on how to recover, or because it didn't implement the callback.
236+
* Both cases assume, that if there is nothing else causing a
237+
* disconnect, we recovered successfully.
238+
*/
239+
if (ers_res == PCI_ERS_RESULT_NONE)
240+
ers_res = PCI_ERS_RESULT_RECOVERED;
241+
228242
if (ers_res != PCI_ERS_RESULT_RECOVERED) {
229243
pr_err("%s: Automatic recovery failed; operator intervention is required\n",
230244
pci_name(pdev));

0 commit comments

Comments
 (0)