scsi: smartpqi: improve error checking for sync requests
authorKevin Barnett <kevin.barnett@microsemi.com>
Mon, 18 Jun 2018 18:22:48 +0000 (13:22 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 20 Jun 2018 02:02:25 +0000 (22:02 -0400)
Detect rare error cases for synchronous requests down the RAID path.

Also retry INQUIRY of VPD page 0 sent to an HBA drive if the command failed
due to an abort.

Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/smartpqi/smartpqi.h
drivers/scsi/smartpqi/smartpqi_init.c

index dc3a0542a2e83b161bd3ea44b41f450d9e48c7a9..a8e7c4d48061162bd96852cd775131db7d3f09b0 100644 (file)
@@ -483,6 +483,8 @@ struct pqi_raid_error_info {
 #define CISS_CMD_STATUS_TMF                    0xd
 #define CISS_CMD_STATUS_AIO_DISABLED           0xe
 
+#define PQI_CMD_STATUS_ABORTED CISS_CMD_STATUS_ABORTED
+
 #define PQI_NUM_EVENT_QUEUE_ELEMENTS   32
 #define PQI_EVENT_OQ_ELEMENT_LENGTH    sizeof(struct pqi_event_response)
 
index 4036f65cbb72df0239120ff421e58a0d2478554c..1593ee343a2b264d31a2d34cb45be2786f4e2061 100644 (file)
@@ -1197,20 +1197,30 @@ no_buffer:
        device->volume_offline = volume_offline;
 }
 
+#define PQI_INQUIRY_PAGE0_RETRIES      3
+
 static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info,
        struct pqi_scsi_dev *device)
 {
        int rc;
        u8 *buffer;
+       unsigned int retries;
 
        buffer = kmalloc(64, GFP_KERNEL);
        if (!buffer)
                return -ENOMEM;
 
        /* Send an inquiry to the device to see what it is. */
-       rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0, buffer, 64);
-       if (rc)
-               goto out;
+       for (retries = 0;;) {
+               rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0,
+                       buffer, 64);
+               if (rc == 0)
+                       break;
+               if (pqi_is_logical_device(device) ||
+                       rc != PQI_CMD_STATUS_ABORTED ||
+                       ++retries > PQI_INQUIRY_PAGE0_RETRIES)
+                       goto out;
+       }
 
        scsi_sanitize_inquiry_string(&buffer[8], 8);
        scsi_sanitize_inquiry_string(&buffer[16], 16);
@@ -3621,6 +3631,29 @@ static void pqi_raid_synchronous_complete(struct pqi_io_request *io_request,
        complete(waiting);
 }
 
+static int pqi_process_raid_io_error_synchronous(struct pqi_raid_error_info
+                                               *error_info)
+{
+       int rc = -EIO;
+
+       switch (error_info->data_out_result) {
+       case PQI_DATA_IN_OUT_GOOD:
+               if (error_info->status == SAM_STAT_GOOD)
+                       rc = 0;
+               break;
+       case PQI_DATA_IN_OUT_UNDERFLOW:
+               if (error_info->status == SAM_STAT_GOOD ||
+                       error_info->status == SAM_STAT_CHECK_CONDITION)
+                       rc = 0;
+               break;
+       case PQI_DATA_IN_OUT_ABORTED:
+               rc = PQI_CMD_STATUS_ABORTED;
+               break;
+       }
+
+       return rc;
+}
+
 static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
        struct pqi_iu_header *request, unsigned int flags,
        struct pqi_raid_error_info *error_info, unsigned long timeout_msecs)
@@ -3710,19 +3743,8 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
                else
                        memset(error_info, 0, sizeof(*error_info));
        } else if (rc == 0 && io_request->error_info) {
-               u8 scsi_status;
-               struct pqi_raid_error_info *raid_error_info;
-
-               raid_error_info = io_request->error_info;
-               scsi_status = raid_error_info->status;
-
-               if (scsi_status == SAM_STAT_CHECK_CONDITION &&
-                       raid_error_info->data_out_result ==
-                       PQI_DATA_IN_OUT_UNDERFLOW)
-                       scsi_status = SAM_STAT_GOOD;
-
-               if (scsi_status != SAM_STAT_GOOD)
-                       rc = -EIO;
+               rc = pqi_process_raid_io_error_synchronous(
+                       io_request->error_info);
        }
 
        pqi_free_io_request(io_request);