[PATCH 1/2] scsi: smartpqi: add pci_error_handlers for bus reset recovery
From: Mateusz Nowicki
Date: Wed May 06 2026 - 10:02:43 EST
The smartpqi driver does not register pci_error_handlers. When the PCI
subsystem performs a bus reset (e.g. "echo 1 > /sys/bus/pci/devices/
<bdf>/reset") on a controller without FLR support, the driver is not
notified. Firmware reverts to SIS mode and drops admin and operational
queue mappings while the driver still believes PQI is active; SCSI I/O
hangs until reboot.
Add .reset_prepare and .reset_done callbacks reusing the existing
SIS -> PQI recovery helpers.
reset_prepare:
- pqi_wait_until_ofa_finished()
- pqi_ofa_ctrl_quiesce()
- clear controller_online and pqi_mode_enabled
reset_done:
- ssleep(PQI_POST_RESET_DELAY_SECS)
- pqi_ofa_ctrl_unquiesce()
- pqi_ctrl_init_resume() to drive SIS -> PQI, recreate queues,
re-enable events and rescan
- pqi_take_ctrl_offline() on failure
No new helpers or exports. Tested on HPE SR932i-p Gen10+.
Signed-off-by: Mateusz Nowicki <mateusz.nowicki@xxxxxxxxxxxxx>
---
drivers/scsi/smartpqi/smartpqi_init.c | 47 +++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index 2026ac645d6a..c4003d3cda7e 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -10677,12 +10677,59 @@ static const struct pci_device_id pqi_pci_id_table[] = {
MODULE_DEVICE_TABLE(pci, pqi_pci_id_table);
+static void pqi_reset_prepare(struct pci_dev *pci_dev)
+{
+ struct pqi_ctrl_info *ctrl_info = pci_get_drvdata(pci_dev);
+
+ if (!ctrl_info)
+ return;
+
+ dev_info(&pci_dev->dev, "PCI reset prepare\n");
+
+ pqi_wait_until_ofa_finished(ctrl_info);
+
+ pqi_ofa_ctrl_quiesce(ctrl_info);
+
+ ctrl_info->controller_online = false;
+ ctrl_info->pqi_mode_enabled = false;
+}
+
+static void pqi_reset_done(struct pci_dev *pci_dev)
+{
+ int rc;
+ struct pqi_ctrl_info *ctrl_info = pci_get_drvdata(pci_dev);
+
+ if (!ctrl_info)
+ return;
+
+ dev_info(&pci_dev->dev, "PCI reset done - reinitializing\n");
+
+ ssleep(PQI_POST_RESET_DELAY_SECS);
+
+ pqi_ofa_ctrl_unquiesce(ctrl_info);
+
+ rc = pqi_ctrl_init_resume(ctrl_info);
+ if (rc) {
+ dev_err(&pci_dev->dev, "reset recovery failed: %d\n", rc);
+ pqi_take_ctrl_offline(ctrl_info, PQI_FIRMWARE_KERNEL_NOT_UP);
+ return;
+ }
+
+ dev_info(&pci_dev->dev, "reset recovery complete\n");
+}
+
+static const struct pci_error_handlers pqi_pci_error_handlers = {
+ .reset_prepare = pqi_reset_prepare,
+ .reset_done = pqi_reset_done,
+};
+
static struct pci_driver pqi_pci_driver = {
.name = DRIVER_NAME_SHORT,
.id_table = pqi_pci_id_table,
.probe = pqi_pci_probe,
.remove = pqi_pci_remove,
.shutdown = pqi_shutdown,
+ .err_handler = &pqi_pci_error_handlers,
#if defined(CONFIG_PM)
.driver = {
.pm = &pqi_pm_ops
--
2.43.0