scsi: smartpqi: Avoid failing I/Os for offline devices
authorMahesh Rajashekhara <mahesh.rajashekhara@microchip.com>
Tue, 28 Sep 2021 23:54:37 +0000 (18:54 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 5 Oct 2021 04:13:15 +0000 (00:13 -0400)
Prevent kernel crash by failing outstanding I/O request when the OS takes
device offline.

When posted I/Os to the controller's inbound queue are not picked by the
controller, the driver will halt the controller and take the controller
offline.

When the driver takes the controller offline, the driver will fail all the
outstanding requests which can sometimes lead to an OS crash.

Link: https://lore.kernel.org/r/20210928235442.201875-7-don.brace@microchip.com
Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
Reviewed-by: Scott Teel <scott.teel@microchip.com>
Acked-by: John Donnelly <john.p.donnelly@oracle.com>
Signed-off-by: Mahesh Rajashekhara <mahesh.rajashekhara@microchip.com>
Signed-off-by: Don Brace <don.brace@microchip.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/smartpqi/smartpqi_init.c

index 838274d8fadfd3141381e1066360e131f544a961..c9f2a3d54663070e2fc394f7091e30a07daf4f5a 100644 (file)
@@ -8544,6 +8544,7 @@ static void pqi_fail_all_outstanding_requests(struct pqi_ctrl_info *ctrl_info)
        unsigned int i;
        struct pqi_io_request *io_request;
        struct scsi_cmnd *scmd;
+       struct scsi_device *sdev;
 
        for (i = 0; i < ctrl_info->max_io_slots; i++) {
                io_request = &ctrl_info->io_request_pool[i];
@@ -8552,7 +8553,13 @@ static void pqi_fail_all_outstanding_requests(struct pqi_ctrl_info *ctrl_info)
 
                scmd = io_request->scmd;
                if (scmd) {
-                       set_host_byte(scmd, DID_NO_CONNECT);
+                       sdev = scmd->device;
+                       if (!sdev || !scsi_device_online(sdev)) {
+                               pqi_free_io_request(io_request);
+                               continue;
+                       } else {
+                               set_host_byte(scmd, DID_NO_CONNECT);
+                       }
                } else {
                        io_request->status = -ENXIO;
                        io_request->error_info =