|
@@ -105,7 +105,7 @@ static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt);
|
|
|
static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
|
|
|
int fn, void *iocb, int flags);
|
|
|
static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd
|
|
|
- *cmd, struct atio_from_isp *atio, int ha_locked);
|
|
|
+ *cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort);
|
|
|
static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha,
|
|
|
struct qla_tgt_srr_imm *imm, int ha_lock);
|
|
|
static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
|
|
@@ -2665,7 +2665,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
|
|
|
/* no need to terminate. FW already freed exchange. */
|
|
|
qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
|
|
|
else
|
|
|
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
|
|
|
+ qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
|
|
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
|
|
return 0;
|
|
|
}
|
|
@@ -3173,7 +3173,8 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
|
|
|
}
|
|
|
|
|
|
static void qlt_send_term_exchange(struct scsi_qla_host *vha,
|
|
|
- struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked)
|
|
|
+ struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked,
|
|
|
+ int ul_abort)
|
|
|
{
|
|
|
unsigned long flags = 0;
|
|
|
int rc;
|
|
@@ -3193,8 +3194,7 @@ static void qlt_send_term_exchange(struct scsi_qla_host *vha,
|
|
|
qlt_alloc_qfull_cmd(vha, atio, 0, 0);
|
|
|
|
|
|
done:
|
|
|
- if (cmd && (!cmd->aborted ||
|
|
|
- !cmd->cmd_sent_to_fw)) {
|
|
|
+ if (cmd && !ul_abort && !cmd->aborted) {
|
|
|
if (cmd->sg_mapped)
|
|
|
qlt_unmap_sg(vha, cmd);
|
|
|
vha->hw->tgt.tgt_ops->free_cmd(cmd);
|
|
@@ -3253,21 +3253,38 @@ static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha)
|
|
|
|
|
|
}
|
|
|
|
|
|
-void qlt_abort_cmd(struct qla_tgt_cmd *cmd)
|
|
|
+int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
|
|
|
{
|
|
|
struct qla_tgt *tgt = cmd->tgt;
|
|
|
struct scsi_qla_host *vha = tgt->vha;
|
|
|
struct se_cmd *se_cmd = &cmd->se_cmd;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
|
|
|
"qla_target(%d): terminating exchange for aborted cmd=%p "
|
|
|
"(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd,
|
|
|
se_cmd->tag);
|
|
|
|
|
|
+ spin_lock_irqsave(&cmd->cmd_lock, flags);
|
|
|
+ if (cmd->aborted) {
|
|
|
+ spin_unlock_irqrestore(&cmd->cmd_lock, flags);
|
|
|
+ /*
|
|
|
+ * It's normal to see 2 calls in this path:
|
|
|
+ * 1) XFER Rdy completion + CMD_T_ABORT
|
|
|
+ * 2) TCM TMR - drain_state_list
|
|
|
+ */
|
|
|
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
|
|
|
+ "multiple abort. %p transport_state %x, t_state %x,"
|
|
|
+ " se_cmd_flags %x \n", cmd, cmd->se_cmd.transport_state,
|
|
|
+ cmd->se_cmd.t_state,cmd->se_cmd.se_cmd_flags);
|
|
|
+ return EIO;
|
|
|
+ }
|
|
|
cmd->aborted = 1;
|
|
|
cmd->cmd_flags |= BIT_6;
|
|
|
+ spin_unlock_irqrestore(&cmd->cmd_lock, flags);
|
|
|
|
|
|
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
|
|
|
+ qlt_send_term_exchange(vha, cmd, &cmd->atio, 0, 1);
|
|
|
+ return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL(qlt_abort_cmd);
|
|
|
|
|
@@ -3282,6 +3299,9 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd)
|
|
|
|
|
|
BUG_ON(cmd->cmd_in_wq);
|
|
|
|
|
|
+ if (cmd->sg_mapped)
|
|
|
+ qlt_unmap_sg(cmd->vha, cmd);
|
|
|
+
|
|
|
if (!cmd->q_full)
|
|
|
qlt_decr_num_pend_cmds(cmd->vha);
|
|
|
|
|
@@ -3399,7 +3419,7 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio,
|
|
|
term = 1;
|
|
|
|
|
|
if (term)
|
|
|
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
|
|
|
+ qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
|
|
|
|
|
|
return term;
|
|
|
}
|
|
@@ -3755,6 +3775,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
|
|
|
goto out_term;
|
|
|
}
|
|
|
|
|
|
+ spin_lock_init(&cmd->cmd_lock);
|
|
|
cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
|
|
|
cmd->se_cmd.tag = atio->u.isp24.exchange_addr;
|
|
|
cmd->unpacked_lun = scsilun_to_int(
|
|
@@ -3797,7 +3818,7 @@ out_term:
|
|
|
*/
|
|
|
cmd->cmd_flags |= BIT_2;
|
|
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
|
|
- qlt_send_term_exchange(vha, NULL, &cmd->atio, 1);
|
|
|
+ qlt_send_term_exchange(vha, NULL, &cmd->atio, 1, 0);
|
|
|
|
|
|
qlt_decr_num_pend_cmds(vha);
|
|
|
percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
|
|
@@ -3919,7 +3940,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
|
|
|
|
|
|
out_term:
|
|
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
|
|
- qlt_send_term_exchange(vha, NULL, &op->atio, 1);
|
|
|
+ qlt_send_term_exchange(vha, NULL, &op->atio, 1, 0);
|
|
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
|
|
kfree(op);
|
|
|
|
|
@@ -4772,7 +4793,7 @@ out_reject:
|
|
|
dump_stack();
|
|
|
} else {
|
|
|
cmd->cmd_flags |= BIT_9;
|
|
|
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
|
|
|
+ qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
|
|
|
}
|
|
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
|
|
}
|
|
@@ -4951,7 +4972,7 @@ static void qlt_prepare_srr_imm(struct scsi_qla_host *vha,
|
|
|
sctio, sctio->srr_id);
|
|
|
list_del(&sctio->srr_list_entry);
|
|
|
qlt_send_term_exchange(vha, sctio->cmd,
|
|
|
- &sctio->cmd->atio, 1);
|
|
|
+ &sctio->cmd->atio, 1, 0);
|
|
|
kfree(sctio);
|
|
|
}
|
|
|
}
|
|
@@ -5124,7 +5145,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
|
|
|
atio->u.isp24.fcp_hdr.s_id);
|
|
|
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
|
|
if (!sess) {
|
|
|
- qlt_send_term_exchange(vha, NULL, atio, 1);
|
|
|
+ qlt_send_term_exchange(vha, NULL, atio, 1, 0);
|
|
|
return 0;
|
|
|
}
|
|
|
/* Sending marker isn't necessary, since we called from ISR */
|
|
@@ -5407,7 +5428,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
|
|
|
#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
|
|
|
qlt_send_busy(vha, atio, SAM_STAT_BUSY);
|
|
|
#else
|
|
|
- qlt_send_term_exchange(vha, NULL, atio, 1);
|
|
|
+ qlt_send_term_exchange(vha, NULL, atio, 1, 0);
|
|
|
#endif
|
|
|
|
|
|
if (!ha_locked)
|
|
@@ -5524,7 +5545,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
|
|
|
#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
|
|
|
qlt_send_busy(vha, atio, 0);
|
|
|
#else
|
|
|
- qlt_send_term_exchange(vha, NULL, atio, 1);
|
|
|
+ qlt_send_term_exchange(vha, NULL, atio, 1, 0);
|
|
|
#endif
|
|
|
} else {
|
|
|
if (tgt->tgt_stop) {
|
|
@@ -5533,7 +5554,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
|
|
|
"command to target, sending TERM "
|
|
|
"EXCHANGE for rsp\n");
|
|
|
qlt_send_term_exchange(vha, NULL,
|
|
|
- atio, 1);
|
|
|
+ atio, 1, 0);
|
|
|
} else {
|
|
|
ql_dbg(ql_dbg_tgt, vha, 0xe060,
|
|
|
"qla_target(%d): Unable to send "
|
|
@@ -5961,7 +5982,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
|
|
|
return;
|
|
|
|
|
|
out_term:
|
|
|
- qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 0);
|
|
|
+ qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0);
|
|
|
if (sess)
|
|
|
ha->tgt.tgt_ops->put_sess(sess);
|
|
|
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|