scsi: aacraid: Process Error for response I/O

Make sure that the driver processes error conditions even in the fast
response path for response from the adapter.

Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: Dave Carroll <David.Carroll@microsemi.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Raghava Aditya Renukunta 2017-02-02 15:53:21 -08:00 committed by Martin K. Petersen
parent c4e2fbca37
commit 4ec57fb4ed

View File

@ -3068,16 +3068,11 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
return; return;
BUG_ON(fibptr == NULL); BUG_ON(fibptr == NULL);
dev = fibptr->dev; dev = fibptr->dev;
scsi_dma_unmap(scsicmd);
/* expose physical device if expose_physicald flag is on */
if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
&& expose_physicals > 0)
aac_expose_phy_device(scsicmd);
srbreply = (struct aac_srb_reply *) fib_data(fibptr); srbreply = (struct aac_srb_reply *) fib_data(fibptr);
scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */ scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */
if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) { if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) {
@ -3090,158 +3085,176 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
*/ */
scsi_set_resid(scsicmd, scsi_bufflen(scsicmd) scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
- le32_to_cpu(srbreply->data_xfer_length)); - le32_to_cpu(srbreply->data_xfer_length));
/* }
* First check the fib status
*/
if (le32_to_cpu(srbreply->status) != ST_OK) {
int len;
printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status)); scsi_dma_unmap(scsicmd);
len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
SCSI_SENSE_BUFFERSIZE); /* expose physical device if expose_physicald flag is on */
if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
&& expose_physicals > 0)
aac_expose_phy_device(scsicmd);
/*
* First check the fib status
*/
if (le32_to_cpu(srbreply->status) != ST_OK) {
int len;
pr_warn("aac_srb_callback: srb failed, status = %d\n",
le32_to_cpu(srbreply->status));
len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
SCSI_SENSE_BUFFERSIZE);
scsicmd->result = DID_ERROR << 16
| COMMAND_COMPLETE << 8
| SAM_STAT_CHECK_CONDITION;
memcpy(scsicmd->sense_buffer,
srbreply->sense_data, len);
}
/*
* Next check the srb status
*/
switch ((le32_to_cpu(srbreply->srb_status))&0x3f) {
case SRB_STATUS_ERROR_RECOVERY:
case SRB_STATUS_PENDING:
case SRB_STATUS_SUCCESS:
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
break;
case SRB_STATUS_DATA_OVERRUN:
switch (scsicmd->cmnd[0]) {
case READ_6:
case WRITE_6:
case READ_10:
case WRITE_10:
case READ_12:
case WRITE_12:
case READ_16:
case WRITE_16:
if (le32_to_cpu(srbreply->data_xfer_length)
< scsicmd->underflow)
pr_warn("aacraid: SCSI CMD underflow\n");
else
pr_warn("aacraid: SCSI CMD Data Overrun\n");
scsicmd->result = DID_ERROR << 16 scsicmd->result = DID_ERROR << 16
| COMMAND_COMPLETE << 8 | COMMAND_COMPLETE << 8;
| SAM_STAT_CHECK_CONDITION; break;
memcpy(scsicmd->sense_buffer, case INQUIRY:
srbreply->sense_data, len); scsicmd->result = DID_OK << 16
} | COMMAND_COMPLETE << 8;
break;
/* default:
* Next check the srb status
*/
switch ((le32_to_cpu(srbreply->srb_status))&0x3f) {
case SRB_STATUS_ERROR_RECOVERY:
case SRB_STATUS_PENDING:
case SRB_STATUS_SUCCESS:
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
break; break;
case SRB_STATUS_DATA_OVERRUN: }
switch (scsicmd->cmnd[0]) { break;
case READ_6: case SRB_STATUS_ABORTED:
case WRITE_6: scsicmd->result = DID_ABORT << 16 | ABORT << 8;
case READ_10: break;
case WRITE_10: case SRB_STATUS_ABORT_FAILED:
case READ_12: /*
case WRITE_12: * Not sure about this one - but assuming the
case READ_16: * hba was trying to abort for some reason
case WRITE_16: */
if (le32_to_cpu(srbreply->data_xfer_length) scsicmd->result = DID_ERROR << 16 | ABORT << 8;
< scsicmd->underflow) break;
printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); case SRB_STATUS_PARITY_ERROR:
else scsicmd->result = DID_PARITY << 16
printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n"); | MSG_PARITY_ERROR << 8;
scsicmd->result = DID_ERROR << 16 break;
| COMMAND_COMPLETE << 8; case SRB_STATUS_NO_DEVICE:
break; case SRB_STATUS_INVALID_PATH_ID:
case INQUIRY: { case SRB_STATUS_INVALID_TARGET_ID:
scsicmd->result = DID_OK << 16 case SRB_STATUS_INVALID_LUN:
| COMMAND_COMPLETE << 8; case SRB_STATUS_SELECTION_TIMEOUT:
break; scsicmd->result = DID_NO_CONNECT << 16
} | COMMAND_COMPLETE << 8;
default: break;
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
break;
}
break;
case SRB_STATUS_ABORTED:
scsicmd->result = DID_ABORT << 16 | ABORT << 8;
break;
case SRB_STATUS_ABORT_FAILED:
/*
* Not sure about this one - but assuming the
* hba was trying to abort for some reason
*/
scsicmd->result = DID_ERROR << 16 | ABORT << 8;
break;
case SRB_STATUS_PARITY_ERROR:
scsicmd->result = DID_PARITY << 16
| MSG_PARITY_ERROR << 8;
break;
case SRB_STATUS_NO_DEVICE:
case SRB_STATUS_INVALID_PATH_ID:
case SRB_STATUS_INVALID_TARGET_ID:
case SRB_STATUS_INVALID_LUN:
case SRB_STATUS_SELECTION_TIMEOUT:
scsicmd->result = DID_NO_CONNECT << 16
| COMMAND_COMPLETE << 8;
break;
case SRB_STATUS_COMMAND_TIMEOUT: case SRB_STATUS_COMMAND_TIMEOUT:
case SRB_STATUS_TIMEOUT: case SRB_STATUS_TIMEOUT:
scsicmd->result = DID_TIME_OUT << 16 scsicmd->result = DID_TIME_OUT << 16
| COMMAND_COMPLETE << 8; | COMMAND_COMPLETE << 8;
break; break;
case SRB_STATUS_BUSY: case SRB_STATUS_BUSY:
scsicmd->result = DID_BUS_BUSY << 16 scsicmd->result = DID_BUS_BUSY << 16
| COMMAND_COMPLETE << 8; | COMMAND_COMPLETE << 8;
break; break;
case SRB_STATUS_BUS_RESET: case SRB_STATUS_BUS_RESET:
scsicmd->result = DID_RESET << 16 scsicmd->result = DID_RESET << 16
| COMMAND_COMPLETE << 8; | COMMAND_COMPLETE << 8;
break; break;
case SRB_STATUS_MESSAGE_REJECTED: case SRB_STATUS_MESSAGE_REJECTED:
scsicmd->result = DID_ERROR << 16 scsicmd->result = DID_ERROR << 16
| MESSAGE_REJECT << 8; | MESSAGE_REJECT << 8;
break; break;
case SRB_STATUS_REQUEST_FLUSHED: case SRB_STATUS_REQUEST_FLUSHED:
case SRB_STATUS_ERROR: case SRB_STATUS_ERROR:
case SRB_STATUS_INVALID_REQUEST: case SRB_STATUS_INVALID_REQUEST:
case SRB_STATUS_REQUEST_SENSE_FAILED: case SRB_STATUS_REQUEST_SENSE_FAILED:
case SRB_STATUS_NO_HBA: case SRB_STATUS_NO_HBA:
case SRB_STATUS_UNEXPECTED_BUS_FREE: case SRB_STATUS_UNEXPECTED_BUS_FREE:
case SRB_STATUS_PHASE_SEQUENCE_FAILURE: case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
case SRB_STATUS_DELAYED_RETRY: case SRB_STATUS_DELAYED_RETRY:
case SRB_STATUS_BAD_FUNCTION: case SRB_STATUS_BAD_FUNCTION:
case SRB_STATUS_NOT_STARTED: case SRB_STATUS_NOT_STARTED:
case SRB_STATUS_NOT_IN_USE: case SRB_STATUS_NOT_IN_USE:
case SRB_STATUS_FORCE_ABORT: case SRB_STATUS_FORCE_ABORT:
case SRB_STATUS_DOMAIN_VALIDATION_FAIL: case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
default: default:
#ifdef AAC_DETAILED_STATUS_INFO #ifdef AAC_DETAILED_STATUS_INFO
printk(KERN_INFO "aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n", pr_info("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x -scsi status 0x%x\n",
le32_to_cpu(srbreply->srb_status) & 0x3F, le32_to_cpu(srbreply->srb_status) & 0x3F,
aac_get_status_string( aac_get_status_string(
le32_to_cpu(srbreply->srb_status) & 0x3F), le32_to_cpu(srbreply->srb_status) & 0x3F),
scsicmd->cmnd[0], scsicmd->cmnd[0],
le32_to_cpu(srbreply->scsi_status)); le32_to_cpu(srbreply->scsi_status));
#endif #endif
if ((scsicmd->cmnd[0] == ATA_12) /*
|| (scsicmd->cmnd[0] == ATA_16)) { * When the CC bit is SET by the host in ATA pass thru CDB,
if (scsicmd->cmnd[2] & (0x01 << 5)) { * driver is supposed to return DID_OK
scsicmd->result = DID_OK << 16 *
| COMMAND_COMPLETE << 8; * When the CC bit is RESET by the host, driver should
break; * return DID_ERROR
} else { */
scsicmd->result = DID_ERROR << 16 if ((scsicmd->cmnd[0] == ATA_12)
| COMMAND_COMPLETE << 8; || (scsicmd->cmnd[0] == ATA_16)) {
break;
} if (scsicmd->cmnd[2] & (0x01 << 5)) {
scsicmd->result = DID_OK << 16
| COMMAND_COMPLETE << 8;
break;
} else { } else {
scsicmd->result = DID_ERROR << 16 scsicmd->result = DID_ERROR << 16
| COMMAND_COMPLETE << 8; | COMMAND_COMPLETE << 8;
break; break;
} }
} } else {
if (le32_to_cpu(srbreply->scsi_status) scsicmd->result = DID_ERROR << 16
== SAM_STAT_CHECK_CONDITION) { | COMMAND_COMPLETE << 8;
int len; break;
scsicmd->result |= SAM_STAT_CHECK_CONDITION;
len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
SCSI_SENSE_BUFFERSIZE);
#ifdef AAC_DETAILED_STATUS_INFO
printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
le32_to_cpu(srbreply->status), len);
#endif
memcpy(scsicmd->sense_buffer,
srbreply->sense_data, len);
} }
} }
if (le32_to_cpu(srbreply->scsi_status)
== SAM_STAT_CHECK_CONDITION) {
int len;
scsicmd->result |= SAM_STAT_CHECK_CONDITION;
len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
SCSI_SENSE_BUFFERSIZE);
#ifdef AAC_DETAILED_STATUS_INFO
pr_warn("aac_srb_callback: check condition, status = %d len=%d\n",
le32_to_cpu(srbreply->status), len);
#endif
memcpy(scsicmd->sense_buffer,
srbreply->sense_data, len);
}
/* /*
* OR in the scsi status (already shifted up a bit) * OR in the scsi status (already shifted up a bit)
*/ */