scsi: qla2xxx: Prevent command send on chip reset
commit 4895009c4bb72f71f2e682f1e7d2c2d96e482087 upstream. Currently IOCBs are allowed to push through while chip reset could be in progress. During chip reset the outstanding_cmds array is cleared twice. Once when any command on this array is returned as failed and secondly when the array is initialize to zero. If a command is inserted on to the array between these intervals, then the command will be lost. Check for chip reset before sending IOCB. 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/20240227164127.36465-2-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:
parent
f18f5fcdaa
commit
7861213201
@ -1188,8 +1188,12 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
return rval;
|
||||
|
||||
done_free_sp:
|
||||
/* ref: INIT */
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
/*
|
||||
* use qla24xx_async_gnl_sp_done to purge all pending gnl request.
|
||||
* kref_put is call behind the scene.
|
||||
*/
|
||||
sp->u.iocb_cmd.u.mbx.in_mb[0] = MBS_COMMAND_ERROR;
|
||||
qla24xx_async_gnl_sp_done(sp, QLA_COMMAND_ERROR);
|
||||
fcport->flags &= ~(FCF_ASYNC_SENT);
|
||||
done:
|
||||
fcport->flags &= ~(FCF_ASYNC_ACTIVE);
|
||||
|
@ -2588,6 +2588,33 @@ void
|
||||
qla2x00_sp_release(struct kref *kref)
|
||||
{
|
||||
struct srb *sp = container_of(kref, struct srb, cmd_kref);
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
|
||||
switch (sp->type) {
|
||||
case SRB_CT_PTHRU_CMD:
|
||||
/* GPSC & GFPNID use fcport->ct_desc.ct_sns for both req & rsp */
|
||||
if (sp->u.iocb_cmd.u.ctarg.req &&
|
||||
(!sp->fcport ||
|
||||
sp->u.iocb_cmd.u.ctarg.req != sp->fcport->ct_desc.ct_sns)) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sp->u.iocb_cmd.u.ctarg.req_allocated_size,
|
||||
sp->u.iocb_cmd.u.ctarg.req,
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.req = NULL;
|
||||
}
|
||||
if (sp->u.iocb_cmd.u.ctarg.rsp &&
|
||||
(!sp->fcport ||
|
||||
sp->u.iocb_cmd.u.ctarg.rsp != sp->fcport->ct_desc.ct_sns)) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sp->free(sp);
|
||||
}
|
||||
@ -2693,7 +2720,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
|
||||
*/
|
||||
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
|
||||
if (!sp) {
|
||||
kfree(fcport);
|
||||
qla2x00_free_fcport(fcport);
|
||||
ql_log(ql_log_info, vha, 0x70e6,
|
||||
"SRB allocation failed\n");
|
||||
return -ENOMEM;
|
||||
@ -2748,6 +2775,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
|
||||
if (rval != QLA_SUCCESS) {
|
||||
/* ref: INIT */
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
qla2x00_free_fcport(fcport);
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
@ -2757,6 +2785,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
|
||||
fcport->d_id.b.area, fcport->d_id.b.al_pa);
|
||||
|
||||
wait_for_completion(&elsio->u.els_logo.comp);
|
||||
qla2x00_free_fcport(fcport);
|
||||
|
||||
/* ref: INIT */
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
@ -3916,7 +3945,7 @@ qla2x00_start_sp(srb_t *sp)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
|
||||
pkt = qla2x00_alloc_iocbs_ready(sp->qpair, sp);
|
||||
if (!pkt) {
|
||||
rval = -EAGAIN;
|
||||
ql_log(ql_log_warn, vha, 0x700c,
|
||||
|
Loading…
x
Reference in New Issue
Block a user