Whenever a sense code is set it would need to be evaluated to
update the error mask.

Signed-off-by: Hannes Reinecke <h...@suse.de>
---
 drivers/ata/libata-eh.c   | 28 +++++++++++++++++++---------
 drivers/scsi/scsi_error.c |  3 ++-
 include/scsi/scsi_eh.h    |  1 +
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index d33e7b8..99bb9f9 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1919,20 +1919,30 @@ 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 984ddcb..a8b610e 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 dbb8c64..98d366b 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)
 {
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to