This has read_capacity_16 have scsi-ml retry errors instead of driving them itself. Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx> Reviewed-by: Martin Wilck <mwilck@xxxxxxxx> --- drivers/scsi/sd.c | 115 +++++++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 37eafa968116..c94c3cdffa90 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2279,59 +2279,92 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, unsigned char *buffer) { - unsigned char cmd[16]; + static const u8 cmd[16] = { SERVICE_ACTION_IN_16, SAI_READ_CAPACITY_16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RC16_LEN }; struct scsi_sense_hdr sshdr; int sense_valid = 0; int the_result; - int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET; unsigned int alignment; unsigned long long lba; unsigned sector_size; + struct scsi_failure failures[] = { + /* + * Fail immediately for Invalid Command Operation Code or + * Invalid Field in CDB. + */ + { + .sense = ILLEGAL_REQUEST, + .asc = 0x20, + .ascq = 0x0, + .allowed = 0, + .result = SAM_STAT_CHECK_CONDITION, + }, + { + .sense = ILLEGAL_REQUEST, + .asc = 0x24, + .ascq = 0x0, + .allowed = 0, + .result = SAM_STAT_CHECK_CONDITION, + }, + /* Fail immediately for Medium Not Present */ + { + .sense = UNIT_ATTENTION, + .asc = 0x3A, + .ascq = 0x0, + .allowed = 0, + .result = SAM_STAT_CHECK_CONDITION, + }, + { + .sense = NOT_READY, + .asc = 0x3A, + .ascq = 0x0, + .allowed = 0, + .result = SAM_STAT_CHECK_CONDITION, + }, + { + .sense = UNIT_ATTENTION, + .asc = 0x29, + .ascq = 0, + /* Device reset might occur several times */ + .allowed = READ_CAPACITY_RETRIES_ON_RESET, + .result = SAM_STAT_CHECK_CONDITION, + }, + /* Any other error not listed above retry */ + { + .result = SCMD_FAILURE_RESULT_ANY, + .allowed = 3, + }, + {}, + }; if (sdp->no_read_capacity_16) return -EINVAL; - do { - memset(cmd, 0, 16); - cmd[0] = SERVICE_ACTION_IN_16; - cmd[1] = SAI_READ_CAPACITY_16; - cmd[13] = RC16_LEN; - memset(buffer, 0, RC16_LEN); - - the_result = scsi_exec_req(((struct scsi_exec_args) { - .sdev = sdp, - .cmd = cmd, - .data_dir = DMA_FROM_DEVICE, - .buf = buffer, - .buf_len = RC16_LEN, - .sshdr = &sshdr, - .timeout = SD_TIMEOUT, - .retries = sdkp->max_retries })); - - if (media_not_present(sdkp, &sshdr)) - return -ENODEV; + the_result = scsi_exec_req(((struct scsi_exec_args) { + .sdev = sdp, + .cmd = cmd, + .data_dir = DMA_FROM_DEVICE, + .buf = buffer, + .buf_len = RC16_LEN, + .sshdr = &sshdr, + .timeout = SD_TIMEOUT, + .retries = sdkp->max_retries, + .failures = failures })); - if (the_result > 0) { - sense_valid = scsi_sense_valid(&sshdr); - if (sense_valid && - sshdr.sense_key == ILLEGAL_REQUEST && - (sshdr.asc == 0x20 || sshdr.asc == 0x24) && - sshdr.ascq == 0x00) - /* Invalid Command Operation Code or - * Invalid Field in CDB, just retry - * silently with RC10 */ - return -EINVAL; - if (sense_valid && - sshdr.sense_key == UNIT_ATTENTION && - sshdr.asc == 0x29 && sshdr.ascq == 0x00) - /* Device reset might occur several times, - * give it one more chance */ - if (--reset_retries > 0) - continue; - } - retries--; + if (media_not_present(sdkp, &sshdr)) + return -ENODEV; - } while (the_result && retries); + if (the_result > 0) { + sense_valid = scsi_sense_valid(&sshdr); + if (sense_valid && sshdr.sense_key == ILLEGAL_REQUEST && + (sshdr.asc == 0x20 || sshdr.asc == 0x24) && + sshdr.ascq == 0x00) + /* + * Invalid Command Operation Code or Invalid Field in + * CDB, just retry silently with RC10 + */ + return -EINVAL; + } if (the_result) { sd_print_result(sdkp, "Read Capacity(16) failed", the_result); -- 2.25.1