Commit 6b0431d6 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: Fix out of order Termination and ABTS response

Following changes are added by this patch

- Prevent ABTS Response from getting in front of Termination of exchange.
  Firmware requires driver to cleanup exchanges before ABTS response can be
  sent. This reduces ABTS response error which triggers extra command
  re-termination and re-sending of ABTS response.

- Add bits in driver and tracks CTIO/ATIO attribute bits for proper command
  Termination. A copy of the ATTR bits will be kept in the ABTS task
  management command as a back up copy, if an ABTS response encounters an
  error.
Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 0691094f
...@@ -519,6 +519,7 @@ struct srb_iocb { ...@@ -519,6 +519,7 @@ struct srb_iocb {
enum { enum {
TYPE_SRB, TYPE_SRB,
TYPE_TGT_CMD, TYPE_TGT_CMD,
TYPE_TGT_TMCMD, /* task management */
}; };
typedef struct srb { typedef struct srb {
......
...@@ -1732,64 +1732,84 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) ...@@ -1732,64 +1732,84 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
sp = req->outstanding_cmds[cnt]; sp = req->outstanding_cmds[cnt];
if (sp) { if (sp) {
req->outstanding_cmds[cnt] = NULL; req->outstanding_cmds[cnt] = NULL;
if (sp->cmd_type == TYPE_SRB) { switch (sp->cmd_type) {
if (sp->type == SRB_NVME_CMD || case TYPE_SRB:
sp->type == SRB_NVME_LS) { if (sp->cmd_type == TYPE_SRB) {
sp_get(sp); if (sp->type == SRB_NVME_CMD ||
spin_unlock_irqrestore(qp->qp_lock_ptr, sp->type == SRB_NVME_LS) {
flags); sp_get(sp);
qla_nvme_abort(ha, sp, res); spin_unlock_irqrestore
spin_lock_irqsave(qp->qp_lock_ptr, (qp->qp_lock_ptr,
flags); flags);
} else if (GET_CMD_SP(sp) && qla_nvme_abort(ha, sp, res);
!ha->flags.eeh_busy && spin_lock_irqsave
(!test_bit(ABORT_ISP_ACTIVE, (qp->qp_lock_ptr,
&vha->dpc_flags)) && flags);
(sp->type == SRB_SCSI_CMD)) { } else if (GET_CMD_SP(sp) &&
/* !ha->flags.eeh_busy &&
* Don't abort commands in (!test_bit(ABORT_ISP_ACTIVE,
* adapter during EEH &vha->dpc_flags)) &&
* recovery as it's not (sp->type == SRB_SCSI_CMD)) {
* accessible/responding. /*
* * Don't abort commands in
* Get a reference to the sp * adapter during EEH
* and drop the lock. The * recovery as it's not
* reference ensures this * accessible/responding.
* sp->done() call and not the *
* call in qla2xxx_eh_abort() * Get a reference to the sp
* ends the SCSI command (with * and drop the lock. The
* result 'res'). * reference ensures this
*/ * sp->done() call and not the
sp_get(sp); * call in qla2xxx_eh_abort()
spin_unlock_irqrestore(qp->qp_lock_ptr, * ends the SCSI command (with
flags); * result 'res').
status = qla2xxx_eh_abort( */
GET_CMD_SP(sp)); sp_get(sp);
spin_lock_irqsave(qp->qp_lock_ptr, spin_unlock_irqrestore
flags); (qp->qp_lock_ptr,
flags);
status = qla2xxx_eh_abort(
GET_CMD_SP(sp));
spin_lock_irqsave
(qp->qp_lock_ptr,
flags);
/*
* Get rid of extra reference
* if immediate exit from
* ql2xxx_eh_abort
*/
if (status == FAILED &&
(qla2x00_isp_reg_stat(ha)))
atomic_dec(
&sp->ref_count);
}
sp->done(sp, res);
break;
case TYPE_TGT_CMD:
if (!vha->hw->tgt.tgt_ops ||
!tgt || qla_ini_mode_enabled(vha)) {
if (!trace)
ql_dbg(ql_dbg_tgt_mgt,
vha, 0xf003,
"HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n",
vha->dpc_flags);
continue;
}
cmd = (struct qla_tgt_cmd *)sp;
qlt_abort_cmd_on_host_reset(cmd->vha,
cmd);
break;
case TYPE_TGT_TMCMD:
/* /*
* Get rid of extra reference * Currently, only ABTS response gets on
* if immediate exit from * the outstanding_cmds[]
* ql2xxx_eh_abort
*/ */
if (status == FAILED && ha->tgt.tgt_ops->free_mcmd(
(qla2x00_isp_reg_stat(ha))) (struct qla_tgt_mgmt_cmd *)sp);
atomic_dec( break;
&sp->ref_count); default:
} break;
sp->done(sp, res);
} else {
if (!vha->hw->tgt.tgt_ops || !tgt ||
qla_ini_mode_enabled(vha)) {
if (!trace)
ql_dbg(ql_dbg_tgt_mgt,
vha, 0xf003,
"HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n",
vha->dpc_flags);
continue;
} }
cmd = (struct qla_tgt_cmd *)sp;
qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
} }
} }
} }
......
This diff is collapsed.
...@@ -957,16 +957,20 @@ struct qla_tgt_sess_work_param { ...@@ -957,16 +957,20 @@ struct qla_tgt_sess_work_param {
}; };
struct qla_tgt_mgmt_cmd { struct qla_tgt_mgmt_cmd {
uint8_t cmd_type;
uint8_t pad[3];
uint16_t tmr_func; uint16_t tmr_func;
uint8_t fc_tm_rsp; uint8_t fc_tm_rsp;
uint8_t abort_io_attr;
struct fc_port *sess; struct fc_port *sess;
struct qla_qpair *qpair; struct qla_qpair *qpair;
struct scsi_qla_host *vha; struct scsi_qla_host *vha;
struct se_cmd se_cmd; struct se_cmd se_cmd;
struct work_struct free_work; struct work_struct free_work;
unsigned int flags; unsigned int flags;
#define QLA24XX_MGMT_SEND_NACK BIT_0
#define QLA24XX_MGMT_ABORT_IO_ATTR_VALID BIT_1
uint32_t reset_count; uint32_t reset_count;
#define QLA24XX_MGMT_SEND_NACK 1
struct work_struct work; struct work_struct work;
uint64_t unpacked_lun; uint64_t unpacked_lun;
union { union {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment