mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-25 20:10:23 +09:00
scsi: qla2xxx: Fix command flush during TMF
commitda7c21b72aupstream. For each TMF request, driver iterates through each qpair and flushes commands associated to the TMF. At the end of the qpair flush, a Marker is used to complete the flush transaction. This process was repeated for each qpair. The multiple flush and marker for this TMF request seems to cause confusion for FW. Instead, 1 flush is sent to FW. Driver would wait for FW to go through all the I/Os on each qpair to be read then return. Driver then closes out the transaction with a Marker. Cc: stable@vger.kernel.org Fixes:d90171dd0d("scsi: qla2xxx: Multi-que support for TMF") Signed-off-by: Quinn Tran <qutran@marvell.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> Link: https://lore.kernel.org/r/20230714070104.40052-5-njavali@marvell.com Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
4a16a46c84
commit
5934b2125f
@@ -2004,12 +2004,11 @@ qla2x00_tmf_iocb_timeout(void *data)
|
||||
int rc, h;
|
||||
unsigned long flags;
|
||||
|
||||
if (sp->type == SRB_MARKER) {
|
||||
complete(&tmf->u.tmf.comp);
|
||||
return;
|
||||
}
|
||||
if (sp->type == SRB_MARKER)
|
||||
rc = QLA_FUNCTION_FAILED;
|
||||
else
|
||||
rc = qla24xx_async_abort_cmd(sp, false);
|
||||
|
||||
rc = qla24xx_async_abort_cmd(sp, false);
|
||||
if (rc) {
|
||||
spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags);
|
||||
for (h = 1; h < sp->qpair->req->num_outstanding_cmds; h++) {
|
||||
@@ -2131,6 +2130,17 @@ static void qla2x00_tmf_sp_done(srb_t *sp, int res)
|
||||
complete(&tmf->u.tmf.comp);
|
||||
}
|
||||
|
||||
static int qla_tmf_wait(struct tmf_arg *arg)
|
||||
{
|
||||
/* there are only 2 types of error handling that reaches here, lun or target reset */
|
||||
if (arg->flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET | TCF_CLEAR_TASK_SET))
|
||||
return qla2x00_eh_wait_for_pending_commands(arg->vha,
|
||||
arg->fcport->d_id.b24, arg->lun, WAIT_LUN);
|
||||
else
|
||||
return qla2x00_eh_wait_for_pending_commands(arg->vha,
|
||||
arg->fcport->d_id.b24, arg->lun, WAIT_TARGET);
|
||||
}
|
||||
|
||||
static int
|
||||
__qla2x00_async_tm_cmd(struct tmf_arg *arg)
|
||||
{
|
||||
@@ -2138,8 +2148,9 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
|
||||
struct srb_iocb *tm_iocb;
|
||||
srb_t *sp;
|
||||
int rval = QLA_FUNCTION_FAILED;
|
||||
|
||||
fc_port_t *fcport = arg->fcport;
|
||||
u32 chip_gen, login_gen;
|
||||
u64 jif;
|
||||
|
||||
if (TMF_NOT_READY(arg->fcport)) {
|
||||
ql_dbg(ql_dbg_taskm, vha, 0x8032,
|
||||
@@ -2184,8 +2195,27 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
|
||||
"TM IOCB failed (%x).\n", rval);
|
||||
}
|
||||
|
||||
if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw))
|
||||
rval = qla26xx_marker(arg);
|
||||
if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
|
||||
chip_gen = vha->hw->chip_reset;
|
||||
login_gen = fcport->login_gen;
|
||||
|
||||
jif = jiffies;
|
||||
if (qla_tmf_wait(arg)) {
|
||||
ql_log(ql_log_info, vha, 0x803e,
|
||||
"Waited %u ms Nexus=%ld:%06x:%llu.\n",
|
||||
jiffies_to_msecs(jiffies - jif), vha->host_no,
|
||||
fcport->d_id.b24, arg->lun);
|
||||
}
|
||||
|
||||
if (chip_gen == vha->hw->chip_reset && login_gen == fcport->login_gen) {
|
||||
rval = qla26xx_marker(arg);
|
||||
} else {
|
||||
ql_log(ql_log_info, vha, 0x803e,
|
||||
"Skip Marker due to disruption. Nexus=%ld:%06x:%llu.\n",
|
||||
vha->host_no, fcport->d_id.b24, arg->lun);
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
done_free_sp:
|
||||
/* ref: INIT */
|
||||
@@ -2263,9 +2293,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
|
||||
uint32_t tag)
|
||||
{
|
||||
struct scsi_qla_host *vha = fcport->vha;
|
||||
struct qla_qpair *qpair;
|
||||
struct tmf_arg a;
|
||||
int i, rval = QLA_SUCCESS;
|
||||
int rval = QLA_SUCCESS;
|
||||
|
||||
if (TMF_NOT_READY(fcport))
|
||||
return QLA_SUSPENDED;
|
||||
@@ -2285,34 +2314,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
|
||||
if (qla_get_tmf(&a))
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
if (vha->hw->mqenable) {
|
||||
for (i = 0; i < vha->hw->num_qpairs; i++) {
|
||||
qpair = vha->hw->queue_pair_map[i];
|
||||
if (!qpair)
|
||||
continue;
|
||||
|
||||
if (TMF_NOT_READY(fcport)) {
|
||||
ql_log(ql_log_warn, vha, 0x8026,
|
||||
"Unable to send TM due to disruption.\n");
|
||||
rval = QLA_SUSPENDED;
|
||||
break;
|
||||
}
|
||||
|
||||
a.qpair = qpair;
|
||||
a.flags = flags|TCF_NOTMCMD_TO_TARGET;
|
||||
rval = __qla2x00_async_tm_cmd(&a);
|
||||
if (rval)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rval)
|
||||
goto bailout;
|
||||
|
||||
a.qpair = vha->hw->base_qpair;
|
||||
rval = __qla2x00_async_tm_cmd(&a);
|
||||
|
||||
bailout:
|
||||
qla_put_tmf(&a);
|
||||
return rval;
|
||||
}
|
||||
|
||||
@@ -3887,6 +3887,7 @@ qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk)
|
||||
{
|
||||
mrk->entry_type = MARKER_TYPE;
|
||||
mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier;
|
||||
mrk->handle = make_handle(sp->qpair->req->id, sp->handle);
|
||||
if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) {
|
||||
mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id);
|
||||
int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun);
|
||||
|
||||
@@ -1470,8 +1470,9 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
||||
goto eh_reset_failed;
|
||||
}
|
||||
err = 3;
|
||||
if (qla2x00_eh_wait_for_pending_commands(vha, sdev->id,
|
||||
sdev->lun, WAIT_LUN) != QLA_SUCCESS) {
|
||||
if (qla2x00_eh_wait_for_pending_commands(vha, fcport->d_id.b24,
|
||||
cmd->device->lun,
|
||||
WAIT_LUN) != QLA_SUCCESS) {
|
||||
ql_log(ql_log_warn, vha, 0x800d,
|
||||
"wait for pending cmds failed for cmd=%p.\n", cmd);
|
||||
goto eh_reset_failed;
|
||||
@@ -1537,8 +1538,8 @@ qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
|
||||
goto eh_reset_failed;
|
||||
}
|
||||
err = 3;
|
||||
if (qla2x00_eh_wait_for_pending_commands(vha, sdev->id,
|
||||
0, WAIT_TARGET) != QLA_SUCCESS) {
|
||||
if (qla2x00_eh_wait_for_pending_commands(vha, fcport->d_id.b24, 0,
|
||||
WAIT_TARGET) != QLA_SUCCESS) {
|
||||
ql_log(ql_log_warn, vha, 0x800d,
|
||||
"wait for pending cmds failed for cmd=%p.\n", cmd);
|
||||
goto eh_reset_failed;
|
||||
|
||||
Reference in New Issue
Block a user