Skip to content

Commit

Permalink
scsi: qla2xxx: Fix command flush during TMF
Browse files Browse the repository at this point in the history
commit da7c21b upstream.

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: d90171d ("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>
  • Loading branch information
Quinn Tran authored and gregkh committed Sep 19, 2023
1 parent 6e44a7e commit ddb8fa0
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 39 deletions.
74 changes: 39 additions & 35 deletions drivers/scsi/qla2xxx/qla_init.c
Expand Up @@ -2003,12 +2003,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++) {
Expand Down Expand Up @@ -2130,15 +2129,27 @@ 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)
{
struct scsi_qla_host *vha = arg->vha;
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,
Expand Down Expand Up @@ -2183,8 +2194,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 */
Expand Down Expand Up @@ -2262,9 +2292,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;
Expand All @@ -2284,34 +2313,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;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/qla2xxx/qla_iocb.c
Expand Up @@ -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);
Expand Down
9 changes: 5 additions & 4 deletions drivers/scsi/qla2xxx/qla_os.c
Expand Up @@ -1478,8 +1478,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;
Expand Down Expand Up @@ -1545,8 +1546,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;
Expand Down

0 comments on commit ddb8fa0

Please sign in to comment.