From: Arun Easi <aeasi@xxxxxxxxxxx> While performing CPU hotplug, a crash with the following stack was seen: Call Trace: qla24xx_process_response_queue+0x42a/0x970 [qla2xxx] qla2x00_start_nvme_mq+0x3a2/0x4b0 [qla2xxx] qla_nvme_post_cmd+0x166/0x240 [qla2xxx] nvme_fc_start_fcp_op.part.0+0x119/0x2e0 [nvme_fc] blk_mq_dispatch_rq_list+0x17b/0x610 __blk_mq_sched_dispatch_requests+0xb0/0x140 blk_mq_sched_dispatch_requests+0x30/0x60 __blk_mq_run_hw_queue+0x35/0x90 __blk_mq_delay_run_hw_queue+0x161/0x180 blk_execute_rq+0xbe/0x160 __nvme_submit_sync_cmd+0x16f/0x220 [nvme_core] nvmf_connect_admin_queue+0x11a/0x170 [nvme_fabrics] nvme_fc_create_association.cold+0x50/0x3dc [nvme_fc] nvme_fc_connect_ctrl_work+0x19/0x30 [nvme_fc] process_one_work+0x1e8/0x3c0 On abort timeout, an IO completion was called without checking if that was already completed or not leading up to a crash. Verify IO and abort request are indeed outstanding before attempting completion. Fixes: ca66aa0949a0 ("scsi: qla2xxx: Do command completion on abort timeout") Reported-by: Marco Patalano <mpatalan@xxxxxxxxxx> Tested-by: Marco Patalano <mpatalan@xxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Arun Easi <aeasi@xxxxxxxxxxx> Signed-off-by: Nilesh Javali <njavali@xxxxxxxxxxx> --- drivers/scsi/qla2xxx/qla_init.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 29ce6a55ce5e..ee5927cb51ca 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -110,6 +110,7 @@ static void qla24xx_abort_iocb_timeout(void *data) struct qla_qpair *qpair = sp->qpair; u32 handle; unsigned long flags; + int sp_found = 0, cmdsp_found = 0; if (sp->cmd_sp) ql_dbg(ql_dbg_async, sp->vha, 0x507c, @@ -124,18 +125,21 @@ static void qla24xx_abort_iocb_timeout(void *data) spin_lock_irqsave(qpair->qp_lock_ptr, flags); for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) { if (sp->cmd_sp && (qpair->req->outstanding_cmds[handle] == - sp->cmd_sp)) + sp->cmd_sp)) { qpair->req->outstanding_cmds[handle] = NULL; + cmdsp_found = 1; + } /* removing the abort */ if (qpair->req->outstanding_cmds[handle] == sp) { qpair->req->outstanding_cmds[handle] = NULL; + sp_found = 1; break; } } spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - if (sp->cmd_sp) { + if (cmdsp_found && sp->cmd_sp) { /* * This done function should take care of * original command ref: INIT @@ -143,8 +147,10 @@ static void qla24xx_abort_iocb_timeout(void *data) sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED); } - abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT); - sp->done(sp, QLA_OS_TIMER_EXPIRED); + if (sp_found) { + abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT); + sp->done(sp, QLA_OS_TIMER_EXPIRED); + } } static void qla24xx_abort_sp_done(srb_t *sp, int res) -- 2.19.0.rc0