From 6ab72405fa26f426854cdb37f2085fea08c90ba6 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Wed, 23 Jul 2014 02:49:50 +0000 Subject: [PATCH] Review of host_status handling (pass-through mode) Inspired by Dave Butler and Bart Van Assche git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5703 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst_const.h | 23 +++++++++++++++++++++++ scst/src/scst_targ.c | 37 +++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/scst/include/scst_const.h b/scst/include/scst_const.h index ca17ec628..0250c4a1c 100644 --- a/scst/include/scst_const.h +++ b/scst/include/scst_const.h @@ -577,6 +577,29 @@ enum scst_tg_sup { #define POSITION_LEN_SHORT 20 #define POSITION_LEN_LONG 32 +/************************************************************* + ** Compatibility constants + *************************************************************/ +#ifndef DID_TRANSPORT_DISRUPTED +#define DID_TRANSPORT_DISRUPTED 0xe +#endif + +#ifndef DID_TRANSPORT_FAILFAST +#define DID_TRANSPORT_FAILFAST 0xf +#endif + +#ifndef DID_NEXUS_FAILURE +#define DID_NEXUS_FAILURE 0x11 +#endif + +#ifndef DID_ALLOC_FAILURE +#define DID_ALLOC_FAILURE 0x12 +#endif + +#ifndef DID_MEDIUM_ERROR +#define DID_MEDIUM_ERROR 0x13 +#endif + /************************************************************* ** Various timeouts *************************************************************/ diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index d1b5cd079..a82921e1d 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -3380,11 +3380,21 @@ static int scst_check_sense(struct scst_cmd *cmd) /* If we had internal bus reset behind us, set the command error UA */ if ((dev->scsi_dev != NULL) && - unlikely(cmd->host_status == DID_RESET) && - ((cmd->op_flags & SCST_SKIP_UA) == 0)) { - TRACE(TRACE_MGMT, "DID_RESET: was_reset=%d host_status=%x", - dev->scsi_dev->was_reset, cmd->host_status); - scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_reset_UA)); + unlikely(cmd->host_status == DID_RESET)) { + if ((cmd->op_flags & SCST_SKIP_UA) == 0) { + TRACE(TRACE_MGMT, "DID_RESET: was_reset=%d host_status=%x", + dev->scsi_dev->was_reset, cmd->host_status); + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_reset_UA)); + } else { + int sl; + uint8_t sense[SCST_STANDARD_SENSE_LEN]; + TRACE(TRACE_MGMT, "DID_RESET received for device %s, " + "triggering reset UA", dev->virt_name); + sl = scst_set_sense(sense, sizeof(sense), dev->d_sense, + SCST_LOAD_SENSE(scst_sense_reset_UA)); + scst_dev_check_set_UA(dev, NULL, sense, sl); + scst_abort_cmd(cmd, NULL, false, false); + } /* It looks like it is safe to clear was_reset here */ dev->scsi_dev->was_reset = 0; } @@ -3479,8 +3489,23 @@ static bool scst_check_auto_sense(struct scst_cmd *cmd) if ((cmd->host_status == DID_REQUEUE) || (cmd->host_status == DID_IMM_RETRY) || (cmd->host_status == DID_SOFT_ERROR) || - (cmd->host_status == DID_ABORT)) { + (cmd->host_status == DID_BUS_BUSY) || + (cmd->host_status == DID_TRANSPORT_DISRUPTED) || + (cmd->host_status == DID_TRANSPORT_FAILFAST) || + (cmd->host_status == DID_ALLOC_FAILURE)) { scst_set_busy(cmd); + } else if (cmd->host_status == DID_RESET) { + /* Postpone handling to scst_check_sense() */ + } else if ((cmd->host_status == DID_ABORT) || + (cmd->host_status == DID_NO_CONNECT) || + (cmd->host_status == DID_TIME_OUT) || + (cmd->host_status == DID_NEXUS_FAILURE)) { + scst_abort_cmd(cmd, NULL, false, false); + } else if (cmd->host_status == DID_MEDIUM_ERROR) { + if (cmd->data_direction & SCST_DATA_WRITE) + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_write_error)); + else + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_read_error)); } else { TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "Host " "status 0x%x received, returning HARDWARE ERROR "