From 3852e37382664a06cd006bb389a8223e32cedf45 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:01 +0200 Subject: [PATCH] libata: evaluate SCSI sense code Whenever a sense code is set it would need to be evaluated to update the error mask. tj: Cosmetic formatting updates. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-eh.c | 29 ++++++++++++++++++++--------- drivers/scsi/scsi_error.c | 3 ++- include/scsi/scsi_eh.h | 1 + 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index e4e0e2e80c20..e37258b78e01 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1920,20 +1920,31 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, tmp = atapi_eh_request_sense(qc->dev, qc->scsicmd->sense_buffer, qc->result_tf.feature >> 4); - if (!tmp) { - /* ATA_QCFLAG_SENSE_VALID is used to - * tell atapi_qc_complete() that sense - * data is already valid. - * - * TODO: interpret sense data and set - * appropriate err_mask. - */ + if (!tmp) qc->flags |= ATA_QCFLAG_SENSE_VALID; - } else + else qc->err_mask |= tmp; } } + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + int ret = scsi_check_sense(qc->scsicmd); + /* + * SUCCESS here means that the sense code could + * evaluated and should be passed to the upper layers + * for correct evaluation. + * FAILED means the sense code could not interpreted + * and the device would need to be reset. + * NEEDS_RETRY and ADD_TO_MLQUEUE means that the + * command would need to be retried. + */ + if (ret == NEEDS_RETRY || ret == ADD_TO_MLQUEUE) { + qc->flags |= ATA_QCFLAG_RETRY; + qc->err_mask |= AC_ERR_OTHER; + } else if (ret != SUCCESS) { + qc->err_mask |= AC_ERR_HSM; + } + } if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS)) action |= ATA_EH_RESET; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 984ddcb4786d..a8b610eaa0ca 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -452,7 +452,7 @@ static void scsi_report_sense(struct scsi_device *sdev, * When a deferred error is detected the current command has * not been executed and needs retrying. */ -static int scsi_check_sense(struct scsi_cmnd *scmd) +int scsi_check_sense(struct scsi_cmnd *scmd) { struct scsi_device *sdev = scmd->device; struct scsi_sense_hdr sshdr; @@ -602,6 +602,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) return SUCCESS; } } +EXPORT_SYMBOL_GPL(scsi_check_sense); static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) { diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index dbb8c640e26f..98d366b55770 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -16,6 +16,7 @@ extern void scsi_report_device_reset(struct Scsi_Host *, int, int); extern int scsi_block_when_processing_errors(struct scsi_device *); extern bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd, struct scsi_sense_hdr *sshdr); +extern int scsi_check_sense(struct scsi_cmnd *); static inline bool scsi_sense_is_deferred(const struct scsi_sense_hdr *sshdr) {