From: Quinn Tran Date: Fri, 26 Jul 2019 16:07:28 +0000 (-0700) Subject: scsi: qla2xxx: Fix abort timeout race condition. X-Git-Tag: v5.3.17~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d863b40cc143e348ac5aa6489d3292eaa9073c01;p=thirdparty%2Fkernel%2Fstable.git scsi: qla2xxx: Fix abort timeout race condition. [ Upstream commit 0c6df59061b23c7a951836d23977be34e896d3da ] If an abort times out, the Abort IOCB completion and Abort timer can race against each other. This patch provides unique error code for timer path to allow proper cleanup. [mkp: typo] Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a2922b17b55b0..bb1c7b2d0ac1f 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -4629,6 +4629,7 @@ struct secure_flash_update_block_pk { #define QLA_SUSPENDED 0x106 #define QLA_BUSY 0x107 #define QLA_ALREADY_REGISTERED 0x109 +#define QLA_OS_TIMER_EXPIRED 0x10a #define NVRAM_DELAY() udelay(10) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index afc890bc50e4f..5df604fae7593 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -99,9 +99,22 @@ static void qla24xx_abort_iocb_timeout(void *data) { srb_t *sp = data; struct srb_iocb *abt = &sp->u.iocb_cmd; + struct qla_qpair *qpair = sp->qpair; + u32 handle; + unsigned long flags; + + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) { + /* removing the abort */ + if (qpair->req->outstanding_cmds[handle] == sp) { + qpair->req->outstanding_cmds[handle] = NULL; + break; + } + } + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); abt->u.abt.comp_status = CS_TIMEOUT; - sp->done(sp, QLA_FUNCTION_TIMEOUT); + sp->done(sp, QLA_OS_TIMER_EXPIRED); } static void qla24xx_abort_sp_done(void *ptr, int res) @@ -109,7 +122,8 @@ static void qla24xx_abort_sp_done(void *ptr, int res) srb_t *sp = ptr; struct srb_iocb *abt = &sp->u.iocb_cmd; - if (del_timer(&sp->u.iocb_cmd.timer)) { + if ((res == QLA_OS_TIMER_EXPIRED) || + del_timer(&sp->u.iocb_cmd.timer)) { if (sp->flags & SRB_WAKEUP_ON_COMP) complete(&abt->u.abt.comp); else