From a6270011ecb746759bde77664e9bea80ac46fbe3 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Wed, 28 Apr 2010 16:54:22 +0000 Subject: [PATCH] - Fixing case when during SRRs ping-pong between initiator and target HW pending timeout gets triggered and the corresponding command deleted => oops on the next ping-pong turn - Minor cleanups and fixes git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1662 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t/qla2x00-target/qla2x00t.c | 7 +++++ scst/include/scst.h | 2 ++ scst/src/scst_lib.c | 45 ++++++++++++++++++++++++------ scst/src/scst_targ.c | 13 ++++++--- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index c40b19a73..143db1435 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -2604,6 +2604,9 @@ static int q2t_prepare_srr_ctio(scsi_qla_host_t *ha, struct q2t_cmd *cmd, goto out; } + if (cmd->scst_cmd != NULL) + scst_update_hw_pending_start(cmd->scst_cmd); + sc = kzalloc(sizeof(*sc), GFP_ATOMIC); if (sc != NULL) { sc->cmd = cmd; @@ -3604,6 +3607,8 @@ static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio, TRACE_ENTRY(); + TRACE_MGMT_DBG("SRR cmd %p, srr_ui %x", cmd, ntfy->srr_ui); + switch (ntfy->srr_ui) { case SRR_IU_STATUS: spin_lock_irq(&ha->hardware_lock); @@ -3702,6 +3707,8 @@ static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio, TRACE_ENTRY(); + TRACE_MGMT_DBG("SRR cmd %p, srr_ui %x", cmd, ntfy->srr_ui); + switch (ntfy->srr_ui) { case SRR_IU_STATUS: spin_lock_irq(&ha->hardware_lock); diff --git a/scst/include/scst.h b/scst/include/scst.h index ed10dcdda..73cd2cab7 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -2451,6 +2451,8 @@ static inline void scst_tgt_set_tgt_priv(struct scst_tgt *tgt, void *val) tgt->tgt_priv = val; } +void scst_update_hw_pending_start(struct scst_cmd *cmd); + /* * Get/Set functions for session's target private data */ diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index e534e43fd..47ae0373e 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -1891,7 +1891,35 @@ out_unlock_tgt: return res; } -/* Returns 0 to continue, >0 to restart, <0 to break */ +/** + * scst_update_hw_pending_start() - update commands pending start + * + * Updates the command's hw_pending_start as if it's just started hw pending. + * Target drivers should call it if they received reply from this pending + * command, but SCST core won't see it. + */ +void scst_update_hw_pending_start(struct scst_cmd *cmd) +{ + unsigned long flags; + + TRACE_ENTRY(); + + /* To sync with scst_check_hw_pending_cmd() */ + spin_lock_irqsave(&cmd->sess->sess_list_lock, flags); + cmd->hw_pending_start = jiffies; + TRACE_MGMT_DBG("Updated hw_pending_start to %ld (cmd %p)", + cmd->hw_pending_start, cmd); + spin_unlock_irqrestore(&cmd->sess->sess_list_lock, flags); + + TRACE_EXIT(); + return; +} +EXPORT_SYMBOL(scst_update_hw_pending_start); + +/* + * Supposed to be called under sess_list_lock, but can release/reaquire it. + * Returns 0 to continue, >0 to restart, <0 to break. + */ static int scst_check_hw_pending_cmd(struct scst_cmd *cmd, unsigned long cur_time, unsigned long max_time, struct scst_session *sess, unsigned long *flags, @@ -1904,7 +1932,7 @@ static int scst_check_hw_pending_cmd(struct scst_cmd *cmd, (long)(cur_time - cmd->start_time) / HZ, (long)(cur_time - cmd->hw_pending_start) / HZ); - if (time_before_eq(cur_time, cmd->start_time + max_time)) { + if (time_before(cur_time, cmd->start_time + max_time)) { /* Cmds are ordered, so no need to check more */ goto out; } @@ -1915,7 +1943,7 @@ static int scst_check_hw_pending_cmd(struct scst_cmd *cmd, } if (time_before(cur_time, cmd->hw_pending_start + max_time)) { - /* Cmds are ordered, so no need to check more */ + res = 0; /* continue */ goto out; } @@ -5412,9 +5440,8 @@ int scst_obtain_device_parameters(struct scst_device *dev) if (scsi_status_is_good(rc)) { int q; - PRINT_BUFF_FLAG(TRACE_SCSI, - "Returned control mode page data", - buffer, sizeof(buffer)); + PRINT_BUFF_FLAG(TRACE_SCSI, "Returned control mode " + "page data", buffer, sizeof(buffer)); dev->tst = buffer[4+2] >> 5; q = buffer[4+3] >> 4; @@ -5455,9 +5482,9 @@ int scst_obtain_device_parameters(struct scst_device *dev) */ if (SCST_SENSE_VALID(sense_buffer)) { #endif - PRINT_BUFF_FLAG(TRACE_SCSI, - "Returned sense data", - sense_buffer, sizeof(sense_buffer)); + PRINT_BUFF_FLAG(TRACE_SCSI, "Returned sense " + "data", sense_buffer, + sizeof(sense_buffer)); if (scst_analyze_sense(sense_buffer, sizeof(sense_buffer), SCST_SENSE_KEY_VALID, diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 87354e546..78dc583e2 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -1395,10 +1395,10 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result, scst_alloc_set_sense(cmd, 1, rq_sense, rq_sense_len); } - TRACE(TRACE_SCSI, "cmd %p, result=%x, cmd->status=%x, resid=%d, " - "cmd->msg_status=%x, cmd->host_status=%x, " - "cmd->driver_status=%x (cmd %p)", cmd, result, cmd->status, resid, - cmd->msg_status, cmd->host_status, cmd->driver_status, cmd); + TRACE(TRACE_SCSI, "cmd %p, result %x, cmd->status %x, resid %d, " + "cmd->msg_status %x, cmd->host_status %x, " + "cmd->driver_status %x", cmd, result, cmd->status, resid, + cmd->msg_status, cmd->host_status, cmd->driver_status); cmd->completed = 1; @@ -1506,6 +1506,11 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state, scst_set_exec_time(cmd); + TRACE(TRACE_SCSI, "cmd %p, status %x, msg_status %x, host_status %x, " + "driver_status %x, resp_data_len %d", cmd, cmd->status, + cmd->msg_status, cmd->host_status, cmd->driver_status, + cmd->resp_data_len); + if (next_state == SCST_CMD_STATE_DEFAULT) next_state = SCST_CMD_STATE_PRE_DEV_DONE;