libata: evaluate SCSI sense code
authorHannes Reinecke <hare@suse.de>
Mon, 4 Apr 2016 09:44:01 +0000 (11:44 +0200)
committerTejun Heo <tj@kernel.org>
Mon, 4 Apr 2016 16:07:41 +0000 (12:07 -0400)
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 <hare@suse.de>
Signed-off-by: Tejun Heo <tj@kernel.org>
drivers/ata/libata-eh.c
drivers/scsi/scsi_error.c
include/scsi/scsi_eh.h

index e4e0e2e..e37258b 100644 (file)
@@ -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;
 
index 984ddcb..a8b610e 100644 (file)
@@ -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)
 {
index dbb8c64..98d366b 100644 (file)
@@ -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)
 {