Commit 26b390ab authored by Kevin Barnett's avatar Kevin Barnett Committed by Martin K. Petersen

scsi: smartpqi: improve error checking for sync requests

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: default avatarScott Benesh <scott.benesh@microsemi.com>
Reviewed-by: default avatarScott Teel <scott.teel@microsemi.com>
Signed-off-by: default avatarKevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: default avatarDon Brace <don.brace@microsemi.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 957c5ab1
...@@ -483,6 +483,8 @@ struct pqi_raid_error_info { ...@@ -483,6 +483,8 @@ struct pqi_raid_error_info {
#define CISS_CMD_STATUS_TMF 0xd #define CISS_CMD_STATUS_TMF 0xd
#define CISS_CMD_STATUS_AIO_DISABLED 0xe #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_NUM_EVENT_QUEUE_ELEMENTS 32
#define PQI_EVENT_OQ_ELEMENT_LENGTH sizeof(struct pqi_event_response) #define PQI_EVENT_OQ_ELEMENT_LENGTH sizeof(struct pqi_event_response)
......
...@@ -1197,20 +1197,30 @@ static void pqi_get_volume_status(struct pqi_ctrl_info *ctrl_info, ...@@ -1197,20 +1197,30 @@ static void pqi_get_volume_status(struct pqi_ctrl_info *ctrl_info,
device->volume_offline = volume_offline; device->volume_offline = volume_offline;
} }
#define PQI_INQUIRY_PAGE0_RETRIES 3
static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info, static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device) struct pqi_scsi_dev *device)
{ {
int rc; int rc;
u8 *buffer; u8 *buffer;
unsigned int retries;
buffer = kmalloc(64, GFP_KERNEL); buffer = kmalloc(64, GFP_KERNEL);
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
/* Send an inquiry to the device to see what it is. */ /* Send an inquiry to the device to see what it is. */
rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0, buffer, 64); for (retries = 0;;) {
if (rc) rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0,
goto out; 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[8], 8);
scsi_sanitize_inquiry_string(&buffer[16], 16); scsi_sanitize_inquiry_string(&buffer[16], 16);
...@@ -3621,6 +3631,29 @@ static void pqi_raid_synchronous_complete(struct pqi_io_request *io_request, ...@@ -3621,6 +3631,29 @@ static void pqi_raid_synchronous_complete(struct pqi_io_request *io_request,
complete(waiting); 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, static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
struct pqi_iu_header *request, unsigned int flags, struct pqi_iu_header *request, unsigned int flags,
struct pqi_raid_error_info *error_info, unsigned long timeout_msecs) 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, ...@@ -3710,19 +3743,8 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info,
else else
memset(error_info, 0, sizeof(*error_info)); memset(error_info, 0, sizeof(*error_info));
} else if (rc == 0 && io_request->error_info) { } else if (rc == 0 && io_request->error_info) {
u8 scsi_status; rc = pqi_process_raid_io_error_synchronous(
struct pqi_raid_error_info *raid_error_info; io_request->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;
} }
pqi_free_io_request(io_request); pqi_free_io_request(io_request);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment