scsi: qla2xxx: Multi-que support for TMF

Add queue flush for task management command, before
placing it on the wire.
Do IO flush for all Request Q's.

Reported-by: kernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/oe-kbuild-all/202304271702.GpIL391S-lkp@intel.com/
Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230428075339.32551-2-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com <mailto:himanshu.madhani@oracle.com>>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Quinn Tran 2023-04-28 00:53:33 -07:00 committed by Martin K. Petersen
parent ac9a78681b
commit d90171dd0d
4 changed files with 68 additions and 20 deletions

View File

@ -465,6 +465,14 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id)
return res;
}
struct tmf_arg {
struct qla_qpair *qpair;
struct fc_port *fcport;
struct scsi_qla_host *vha;
u64 lun;
u32 flags;
};
struct els_logo_payload {
uint8_t opcode;
uint8_t rsvd[3];

View File

@ -69,7 +69,7 @@ extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint64_t, uint32_t);
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);

View File

@ -2020,17 +2020,19 @@ static void qla2x00_tmf_sp_done(srb_t *sp, int res)
complete(&tmf->u.tmf.comp);
}
int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
uint32_t tag)
static int
__qla2x00_async_tm_cmd(struct tmf_arg *arg)
{
struct scsi_qla_host *vha = fcport->vha;
struct scsi_qla_host *vha = arg->vha;
struct srb_iocb *tm_iocb;
srb_t *sp;
unsigned long flags;
int rval = QLA_FUNCTION_FAILED;
fc_port_t *fcport = arg->fcport;
/* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
if (!sp)
goto done;
@ -2043,15 +2045,15 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
tm_iocb = &sp->u.iocb_cmd;
init_completion(&tm_iocb->u.tmf.comp);
tm_iocb->u.tmf.flags = flags;
tm_iocb->u.tmf.lun = lun;
ql_dbg(ql_dbg_taskm, vha, 0x802f,
"Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
tm_iocb->u.tmf.flags = arg->flags;
tm_iocb->u.tmf.lun = arg->lun;
rval = qla2x00_start_sp(sp);
ql_dbg(ql_dbg_taskm, vha, 0x802f,
"Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x ctrl=%x.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa, arg->flags);
if (rval != QLA_SUCCESS)
goto done_free_sp;
wait_for_completion(&tm_iocb->u.tmf.comp);
@ -2065,12 +2067,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
flags = tm_iocb->u.tmf.flags;
lun = (uint16_t)tm_iocb->u.tmf.lun;
if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|
TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA))
flags = MK_SYNC_ID_LUN;
else
flags = MK_SYNC_ID;
/* Issue Marker IOCB */
qla2x00_marker(vha, vha->hw->base_qpair,
fcport->loop_id, lun,
flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
qla2x00_marker(vha, sp->qpair,
sp->fcport->loop_id, arg->lun, flags);
}
done_free_sp:
@ -2080,6 +2084,41 @@ done:
return rval;
}
int
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;
struct completion comp;
int i, rval;
init_completion(&comp);
a.vha = fcport->vha;
a.fcport = fcport;
a.lun = lun;
if (vha->hw->mqenable) {
for (i = 0; i < vha->hw->num_qpairs; i++) {
qpair = vha->hw->queue_pair_map[i];
if (!qpair)
continue;
a.qpair = qpair;
a.flags = flags|TCF_NOTMCMD_TO_TARGET;
rval = __qla2x00_async_tm_cmd(&a);
if (rval)
break;
}
}
a.qpair = vha->hw->base_qpair;
a.flags = flags;
rval = __qla2x00_async_tm_cmd(&a);
return rval;
}
int
qla24xx_async_abort_command(srb_t *sp)
{

View File

@ -2541,7 +2541,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
scsi_qla_host_t *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw;
struct srb_iocb *iocb = &sp->u.iocb_cmd;
struct req_que *req = vha->req;
struct req_que *req = sp->qpair->req;
flags = iocb->u.tmf.flags;
lun = iocb->u.tmf.lun;
@ -2557,7 +2557,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
tsk->port_id[2] = fcport->d_id.b.domain;
tsk->vp_index = fcport->vha->vp_idx;
if (flags == TCF_LUN_RESET) {
if (flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET|
TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
int_to_scsilun(lun, &tsk->lun);
host_to_fcp_swap((uint8_t *)&tsk->lun,
sizeof(tsk->lun));