scsi: smartpqi: Take drives offline when controller is offline
authorDavid Strahan <david.strahan@microchip.com>
Wed, 23 Apr 2025 18:32:25 +0000 (13:32 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 29 Apr 2025 01:43:26 +0000 (21:43 -0400)
During a controller lockup, the physical and logical drives under the
locked up controller are still listed at the OS level. I.e. the
controller is offline but the status of each drive is 'running'.

When the controller is unexpectedly taken offline, show its drives as
offline.

Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
Reviewed-by: Mike McGowen <mike.mcgowen@microchip.com>
Signed-off-by: David Strahan <david.strahan@microchip.com>
Co-developed-by: Don Brace <don.brace@microchip.com>
Signed-off-by: Don Brace <don.brace@microchip.com>
Link: https://lore.kernel.org/r/20250423183229.538572-2-don.brace@microchip.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/smartpqi/smartpqi_init.c

index 88135fdb8bd14b4ebf0418f5decc83a1d4d7008d..73f576ccf511055d51166659eefa9b005c58d679 100644 (file)
@@ -67,6 +67,7 @@ static struct pqi_cmd_priv *pqi_cmd_priv(struct scsi_cmnd *cmd)
 static void pqi_verify_structures(void);
 static void pqi_take_ctrl_offline(struct pqi_ctrl_info *ctrl_info,
        enum pqi_ctrl_shutdown_reason ctrl_shutdown_reason);
+static void pqi_take_ctrl_devices_offline(struct pqi_ctrl_info *ctrl_info);
 static void pqi_ctrl_offline_worker(struct work_struct *work);
 static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info);
 static void pqi_scan_start(struct Scsi_Host *shost);
@@ -9128,6 +9129,7 @@ static void pqi_take_ctrl_offline_deferred(struct pqi_ctrl_info *ctrl_info)
        pqi_ctrl_wait_until_quiesced(ctrl_info);
        pqi_fail_all_outstanding_requests(ctrl_info);
        pqi_ctrl_unblock_requests(ctrl_info);
+       pqi_take_ctrl_devices_offline(ctrl_info);
 }
 
 static void pqi_ctrl_offline_worker(struct work_struct *work)
@@ -9202,6 +9204,27 @@ static void pqi_take_ctrl_offline(struct pqi_ctrl_info *ctrl_info,
        schedule_work(&ctrl_info->ctrl_offline_work);
 }
 
+static void pqi_take_ctrl_devices_offline(struct pqi_ctrl_info *ctrl_info)
+{
+       int rc;
+       unsigned long flags;
+       struct pqi_scsi_dev *device;
+
+       spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
+       list_for_each_entry(device, &ctrl_info->scsi_device_list, scsi_device_list_entry) {
+               rc = list_is_last(&device->scsi_device_list_entry, &ctrl_info->scsi_device_list);
+               if (rc)
+                       continue;
+
+               /*
+                * Is the sdev pointer NULL?
+                */
+               if (device->sdev)
+                       scsi_device_set_state(device->sdev, SDEV_OFFLINE);
+       }
+       spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
+}
+
 static void pqi_print_ctrl_info(struct pci_dev *pci_dev,
        const struct pci_device_id *id)
 {