Commit 9803fb5d authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: Fix task management cmd failure

Task management cmd failed with status 30h which means
FW is not able to finish processing one task management
before another task management for the same lun.
Hence add wait for completion of marker to space it out.
Reported-by: default avatarkernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/oe-kbuild-all/202304271802.uCZfwQC1-lkp@intel.com/
Cc: stable@vger.kernel.org
Signed-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230428075339.32551-3-njavali@marvell.comReviewed-by: default avatarHimanshu Madhani &lt;himanshu.madhani@oracle.com <mailto:himanshu.madhani@oracle.com&gt;>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent d90171dd
...@@ -471,6 +471,7 @@ struct tmf_arg { ...@@ -471,6 +471,7 @@ struct tmf_arg {
struct scsi_qla_host *vha; struct scsi_qla_host *vha;
u64 lun; u64 lun;
u32 flags; u32 flags;
uint8_t modifier;
}; };
struct els_logo_payload { struct els_logo_payload {
...@@ -552,6 +553,10 @@ struct srb_iocb { ...@@ -552,6 +553,10 @@ struct srb_iocb {
uint32_t data; uint32_t data;
struct completion comp; struct completion comp;
__le16 comp_status; __le16 comp_status;
uint8_t modifier;
uint8_t vp_index;
uint16_t loop_id;
} tmf; } tmf;
struct { struct {
#define SRB_FXDISC_REQ_DMA_VALID BIT_0 #define SRB_FXDISC_REQ_DMA_VALID BIT_0
...@@ -655,6 +660,7 @@ struct srb_iocb { ...@@ -655,6 +660,7 @@ struct srb_iocb {
#define SRB_SA_UPDATE 25 #define SRB_SA_UPDATE 25
#define SRB_ELS_CMD_HST_NOLOGIN 26 #define SRB_ELS_CMD_HST_NOLOGIN 26
#define SRB_SA_REPLACE 27 #define SRB_SA_REPLACE 27
#define SRB_MARKER 28
struct qla_els_pt_arg { struct qla_els_pt_arg {
u8 els_opcode; u8 els_opcode;
......
...@@ -2013,6 +2013,80 @@ qla2x00_tmf_iocb_timeout(void *data) ...@@ -2013,6 +2013,80 @@ qla2x00_tmf_iocb_timeout(void *data)
} }
} }
static void qla_marker_sp_done(srb_t *sp, int res)
{
struct srb_iocb *tmf = &sp->u.iocb_cmd;
if (res != QLA_SUCCESS)
ql_dbg(ql_dbg_taskm, sp->vha, 0x8004,
"Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n",
sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags,
sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id);
complete(&tmf->u.tmf.comp);
}
#define START_SP_W_RETRIES(_sp, _rval) \
{\
int cnt = 5; \
do { \
_rval = qla2x00_start_sp(_sp); \
if (_rval == EAGAIN) \
msleep(1); \
else \
break; \
cnt--; \
} while (cnt); \
}
static int
qla26xx_marker(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;
/* ref: INIT */
sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
if (!sp)
goto done;
sp->type = SRB_MARKER;
sp->name = "marker";
qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done);
sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout;
tm_iocb = &sp->u.iocb_cmd;
init_completion(&tm_iocb->u.tmf.comp);
tm_iocb->u.tmf.modifier = arg->modifier;
tm_iocb->u.tmf.lun = arg->lun;
tm_iocb->u.tmf.loop_id = fcport->loop_id;
tm_iocb->u.tmf.vp_index = vha->vp_idx;
START_SP_W_RETRIES(sp, rval);
ql_dbg(ql_dbg_taskm, vha, 0x8006,
"Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
sp->handle, fcport->loop_id, fcport->d_id.b24,
arg->modifier, arg->lun, sp->qpair->id, rval);
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x8031,
"Marker IOCB failed (%x).\n", rval);
goto done_free_sp;
}
wait_for_completion(&tm_iocb->u.tmf.comp);
done_free_sp:
/* ref: INIT */
kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
static void qla2x00_tmf_sp_done(srb_t *sp, int res) static void qla2x00_tmf_sp_done(srb_t *sp, int res)
{ {
struct srb_iocb *tmf = &sp->u.iocb_cmd; struct srb_iocb *tmf = &sp->u.iocb_cmd;
...@@ -2026,7 +2100,6 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) ...@@ -2026,7 +2100,6 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
struct scsi_qla_host *vha = arg->vha; struct scsi_qla_host *vha = arg->vha;
struct srb_iocb *tm_iocb; struct srb_iocb *tm_iocb;
srb_t *sp; srb_t *sp;
unsigned long flags;
int rval = QLA_FUNCTION_FAILED; int rval = QLA_FUNCTION_FAILED;
fc_port_t *fcport = arg->fcport; fc_port_t *fcport = arg->fcport;
...@@ -2048,11 +2121,12 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) ...@@ -2048,11 +2121,12 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
tm_iocb->u.tmf.flags = arg->flags; tm_iocb->u.tmf.flags = arg->flags;
tm_iocb->u.tmf.lun = arg->lun; tm_iocb->u.tmf.lun = arg->lun;
rval = qla2x00_start_sp(sp); START_SP_W_RETRIES(sp, rval);
ql_dbg(ql_dbg_taskm, vha, 0x802f, ql_dbg(ql_dbg_taskm, vha, 0x802f,
"Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x ctrl=%x.\n", "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain, sp->handle, fcport->loop_id, fcport->d_id.b24,
fcport->d_id.b.area, fcport->d_id.b.al_pa, arg->flags); arg->flags, arg->lun, sp->qpair->id, rval);
if (rval != QLA_SUCCESS) if (rval != QLA_SUCCESS)
goto done_free_sp; goto done_free_sp;
...@@ -2065,17 +2139,8 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) ...@@ -2065,17 +2139,8 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
"TM IOCB failed (%x).\n", rval); "TM IOCB failed (%x).\n", rval);
} }
if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw))
flags = tm_iocb->u.tmf.flags; rval = qla26xx_marker(arg);
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;
qla2x00_marker(vha, sp->qpair,
sp->fcport->loop_id, arg->lun, flags);
}
done_free_sp: done_free_sp:
/* ref: INIT */ /* ref: INIT */
...@@ -2099,6 +2164,11 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, ...@@ -2099,6 +2164,11 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
a.fcport = fcport; a.fcport = fcport;
a.lun = lun; a.lun = lun;
if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA))
a.modifier = MK_SYNC_ID_LUN;
else
a.modifier = MK_SYNC_ID;
if (vha->hw->mqenable) { if (vha->hw->mqenable) {
for (i = 0; i < vha->hw->num_qpairs; i++) { for (i = 0; i < vha->hw->num_qpairs; i++) {
qpair = vha->hw->queue_pair_map[i]; qpair = vha->hw->queue_pair_map[i];
......
...@@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, ...@@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair,
return (QLA_FUNCTION_FAILED); return (QLA_FUNCTION_FAILED);
} }
mrk24 = (struct mrk_entry_24xx *)mrk;
mrk->entry_type = MARKER_TYPE; mrk->entry_type = MARKER_TYPE;
mrk->modifier = type; mrk->modifier = type;
if (type != MK_SYNC_ALL) { if (type != MK_SYNC_ALL) {
if (IS_FWI2_CAPABLE(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mrk24 = (struct mrk_entry_24xx *) mrk;
mrk24->nport_handle = cpu_to_le16(loop_id); mrk24->nport_handle = cpu_to_le16(loop_id);
int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun);
host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
mrk24->vp_index = vha->vp_idx; mrk24->vp_index = vha->vp_idx;
mrk24->handle = make_handle(req->id, mrk24->handle);
} else { } else {
SET_TARGET_ID(ha, mrk->target, loop_id); SET_TARGET_ID(ha, mrk->target, loop_id);
mrk->lun = cpu_to_le16((uint16_t)lun); mrk->lun = cpu_to_le16((uint16_t)lun);
} }
} }
if (IS_FWI2_CAPABLE(ha))
mrk24->handle = QLA_SKIP_HANDLE;
wmb(); wmb();
qla2x00_start_iocbs(vha, req); qla2x00_start_iocbs(vha, req);
...@@ -3853,9 +3857,9 @@ static int qla_get_iocbs_resource(struct srb *sp) ...@@ -3853,9 +3857,9 @@ static int qla_get_iocbs_resource(struct srb *sp)
case SRB_NACK_LOGO: case SRB_NACK_LOGO:
case SRB_LOGOUT_CMD: case SRB_LOGOUT_CMD:
case SRB_CTRL_VP: case SRB_CTRL_VP:
push_it_through = true; case SRB_MARKER:
fallthrough;
default: default:
push_it_through = true;
get_exch = false; get_exch = false;
} }
...@@ -3871,6 +3875,19 @@ static int qla_get_iocbs_resource(struct srb *sp) ...@@ -3871,6 +3875,19 @@ static int qla_get_iocbs_resource(struct srb *sp)
return qla_get_fw_resources(sp->qpair, &sp->iores); return qla_get_fw_resources(sp->qpair, &sp->iores);
} }
static void
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;
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);
host_to_fcp_swap(mrk->lun, sizeof(mrk->lun));
mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index;
}
}
int int
qla2x00_start_sp(srb_t *sp) qla2x00_start_sp(srb_t *sp)
{ {
...@@ -3974,6 +3991,9 @@ qla2x00_start_sp(srb_t *sp) ...@@ -3974,6 +3991,9 @@ qla2x00_start_sp(srb_t *sp)
case SRB_SA_REPLACE: case SRB_SA_REPLACE:
qla24xx_sa_replace_iocb(sp, pkt); qla24xx_sa_replace_iocb(sp, pkt);
break; break;
case SRB_MARKER:
qla_marker_iocb(sp, pkt);
break;
default: default:
break; break;
} }
......
...@@ -3750,6 +3750,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha, ...@@ -3750,6 +3750,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
return rc; return rc;
} }
static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
struct mrk_entry_24xx *pkt)
{
const char func[] = "MRK-IOCB";
srb_t *sp;
int res = QLA_SUCCESS;
if (!IS_FWI2_CAPABLE(vha->hw))
return;
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (!sp)
return;
if (pkt->entry_status) {
ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n");
res = QLA_COMMAND_ERROR;
}
sp->u.iocb_cmd.u.tmf.data = res;
sp->done(sp, res);
}
/** /**
* qla24xx_process_response_queue() - Process response queue entries. * qla24xx_process_response_queue() - Process response queue entries.
* @vha: SCSI driver HA context * @vha: SCSI driver HA context
...@@ -3863,9 +3885,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, ...@@ -3863,9 +3885,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
(struct nack_to_isp *)pkt); (struct nack_to_isp *)pkt);
break; break;
case MARKER_TYPE: case MARKER_TYPE:
/* Do nothing in this case, this check is to prevent it qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt);
* from falling into default case
*/
break; break;
case ABORT_IOCB_TYPE: case ABORT_IOCB_TYPE:
qla24xx_abort_iocb_entry(vha, rsp->req, qla24xx_abort_iocb_entry(vha, rsp->req,
......
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