scsi: qla2xxx: Fix race condition between iocb timeout and initialisation
authorBen Hutchings <ben.hutchings@codethink.co.uk>
Tue, 20 Mar 2018 21:36:14 +0000 (21:36 +0000)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 10 Apr 2018 01:04:36 +0000 (21:04 -0400)
qla2x00_init_timer() calls add_timer() on the iocb timeout timer, which
means the timeout function pointer and any data that the function depends on
must be initialised beforehand.

Move this initialisation before each call to qla2x00_init_timer().  In some
cases qla2x00_init_timer() initialises a completion structure needed by the
timeout function, so move the call to add_timer() after that.

Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Acked-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_mr.c
drivers/scsi/qla2xxx/qla_target.c

index 2288757b5c9e6ba118b3e7360b7094fceea135eb..9e914f9c3ffb375b2a2fbba2cc9d8c38f8544c85 100644 (file)
@@ -3794,6 +3794,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
        sp->gen1 = fcport->rscn_gen;
        sp->gen2 = fcport->login_gen;
 
+       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        /* CT_IU preamble  */
@@ -3812,7 +3813,6 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
        sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;
        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        sp->done = qla24xx_async_gffid_sp_done;
 
        rval = qla2x00_start_sp(sp);
@@ -4230,6 +4230,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
        sp->name = "gnnft";
        sp->gen1 = vha->hw->base_qpair->chip_reset;
        sp->gen2 = fc4_type;
+
+       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
@@ -4246,7 +4248,6 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
        sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        sp->done = qla2x00_async_gpnft_gnnft_sp_done;
 
        rval = qla2x00_start_sp(sp);
@@ -4370,6 +4371,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
        sp->name = "gpnft";
        sp->gen1 = vha->hw->base_qpair->chip_reset;
        sp->gen2 = fc4_type;
+
+       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        rspsz = sizeof(struct ct_sns_gpnft_rsp) +
@@ -4385,7 +4388,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
 
        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        sp->done = qla2x00_async_gpnft_gnnft_sp_done;
 
        rval = qla2x00_start_sp(sp);
@@ -4495,6 +4497,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
        sp->gen1 = fcport->rscn_gen;
        sp->gen2 = fcport->login_gen;
 
+       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        /* CT_IU preamble  */
@@ -4516,7 +4519,6 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
        sp->u.iocb_cmd.u.ctarg.rsp_size = GNN_ID_RSP_SIZE;
        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        sp->done = qla2x00_async_gnnid_sp_done;
 
        rval = qla2x00_start_sp(sp);
@@ -4632,6 +4634,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
        sp->gen1 = fcport->rscn_gen;
        sp->gen2 = fcport->login_gen;
 
+       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        /* CT_IU preamble  */
@@ -4653,7 +4656,6 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
        sp->u.iocb_cmd.u.ctarg.rsp_size = GFPN_ID_RSP_SIZE;
        sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 
-       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        sp->done = qla2x00_async_gfpnid_sp_done;
 
        rval = qla2x00_start_sp(sp);
index a568266a44bfb650f042fe908456cd41942d0534..8f55dd44adaef43386399fc767b7de94b7ef2465 100644 (file)
@@ -183,10 +183,11 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
        sp->name = "login";
        sp->gen1 = fcport->rscn_gen;
        sp->gen2 = fcport->login_gen;
-       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        lio = &sp->u.iocb_cmd;
        lio->timeout = qla2x00_async_iocb_timeout;
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
        sp->done = qla2x00_async_login_sp_done;
        lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
 
@@ -245,10 +246,11 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
 
        sp->type = SRB_LOGOUT_CMD;
        sp->name = "logout";
-       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        lio = &sp->u.iocb_cmd;
        lio->timeout = qla2x00_async_iocb_timeout;
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
        sp->done = qla2x00_async_logout_sp_done;
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS)
@@ -307,10 +309,11 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
 
        sp->type = SRB_PRLO_CMD;
        sp->name = "prlo";
-       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        lio = &sp->u.iocb_cmd;
        lio->timeout = qla2x00_async_iocb_timeout;
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
        sp->done = qla2x00_async_prlo_sp_done;
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS)
@@ -412,10 +415,11 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 
        sp->type = SRB_ADISC_CMD;
        sp->name = "adisc";
-       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        lio = &sp->u.iocb_cmd;
        lio->timeout = qla2x00_async_iocb_timeout;
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
        sp->done = qla2x00_async_adisc_sp_done;
        if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
                lio->u.logio.flags |= SRB_LOGIN_RETRIED;
@@ -745,6 +749,8 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
        sp->gen1 = fcport->rscn_gen;
        sp->gen2 = fcport->login_gen;
 
+       mbx = &sp->u.iocb_cmd;
+       mbx->timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
 
        mb = sp->u.iocb_cmd.u.mbx.out_mb;
@@ -757,9 +763,6 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
        mb[8] = vha->gnl.size;
        mb[9] = vha->vp_idx;
 
-       mbx = &sp->u.iocb_cmd;
-       mbx->timeout = qla2x00_async_iocb_timeout;
-
        sp->done = qla24xx_async_gnl_sp_done;
 
        rval = qla2x00_start_sp(sp);
@@ -887,10 +890,11 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
 
        sp->type = SRB_PRLI_CMD;
        sp->name = "prli";
-       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        lio = &sp->u.iocb_cmd;
        lio->timeout = qla2x00_async_iocb_timeout;
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
        sp->done = qla2x00_async_prli_sp_done;
        lio->u.logio.flags = 0;
 
@@ -955,6 +959,9 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
        sp->name = "gpdb";
        sp->gen1 = fcport->rscn_gen;
        sp->gen2 = fcport->login_gen;
+
+       mbx = &sp->u.iocb_cmd;
+       mbx->timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
@@ -974,8 +981,6 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
        mb[9] = vha->vp_idx;
        mb[10] = opt;
 
-       mbx = &sp->u.iocb_cmd;
-       mbx->timeout = qla2x00_async_iocb_timeout;
        mbx->u.mbx.in = (void *)pd;
        mbx->u.mbx.in_dma = pd_dma;
 
@@ -1490,13 +1495,15 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
        tm_iocb = &sp->u.iocb_cmd;
        sp->type = SRB_TM_CMD;
        sp->name = "tmf";
+
+       tm_iocb->timeout = qla2x00_tmf_iocb_timeout;
+       init_completion(&tm_iocb->u.tmf.comp);
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
+
        tm_iocb->u.tmf.flags = flags;
        tm_iocb->u.tmf.lun = lun;
        tm_iocb->u.tmf.data = tag;
        sp->done = qla2x00_tmf_sp_done;
-       tm_iocb->timeout = qla2x00_tmf_iocb_timeout;
-       init_completion(&tm_iocb->u.tmf.comp);
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS)
@@ -1570,7 +1577,11 @@ qla24xx_async_abort_cmd(srb_t *cmd_sp)
        abt_iocb = &sp->u.iocb_cmd;
        sp->type = SRB_ABT_CMD;
        sp->name = "abort";
+
+       abt_iocb->timeout = qla24xx_abort_iocb_timeout;
+       init_completion(&abt_iocb->u.abt.comp);
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
+
        abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
 
        if (vha->flags.qpairs_available && cmd_sp->qpair)
@@ -1580,8 +1591,6 @@ qla24xx_async_abort_cmd(srb_t *cmd_sp)
                abt_iocb->u.abt.req_que_no = cpu_to_le16(vha->req->id);
 
        sp->done = qla24xx_abort_sp_done;
-       abt_iocb->timeout = qla24xx_abort_iocb_timeout;
-       init_completion(&abt_iocb->u.abt.comp);
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS)
index b7a05aebf06593f69346218b285898932cb130ef..37ae0f6d8ae5743a182cc9fb963cbc868ddd925b 100644 (file)
@@ -272,13 +272,13 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo)
 {
        timer_setup(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, 0);
        sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
-       add_timer(&sp->u.iocb_cmd.timer);
        sp->free = qla2x00_sp_free;
        init_completion(&sp->comp);
        if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD))
                init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
        if (sp->type == SRB_ELS_DCMD)
                init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
+       add_timer(&sp->u.iocb_cmd.timer);
 }
 
 static inline int
index f74ff7b550b64348d511c930d474bffd991a9081..a91cca52b5d5be5a262270ae6b0cbefe5a72a8bf 100644 (file)
@@ -2460,8 +2460,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
        sp->type = SRB_ELS_DCMD;
        sp->name = "ELS_DCMD";
        sp->fcport = fcport;
-       qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
        elsio->timeout = qla2x00_els_dcmd_iocb_timeout;
+       qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
        sp->done = qla2x00_els_dcmd_sp_done;
        sp->free = qla2x00_els_dcmd_sp_free;
 
@@ -2658,8 +2658,11 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
        sp->type = SRB_ELS_DCMD;
        sp->name = "ELS_DCMD";
        sp->fcport = fcport;
-       qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
+
        elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
+       init_completion(&elsio->u.els_plogi.comp);
+       qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
+
        sp->done = qla2x00_els_dcmd2_sp_done;
        sp->free = qla2x00_els_dcmd2_sp_free;
 
@@ -2696,7 +2699,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
        ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x0109,
            (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70);
 
-       init_completion(&elsio->u.els_plogi.comp);
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
index 5db0262d5c94690c46f1fc2d11bdbffc780f08b4..d8a36c13aedaf8606a4931287bb2879aee23dcae 100644 (file)
@@ -6023,14 +6023,14 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
        sp->type = SRB_MB_IOCB;
        sp->name = mb_to_str(mcp->mb[0]);
 
-       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
-
-       memcpy(sp->u.iocb_cmd.u.mbx.out_mb, mcp->mb, SIZEOF_IOCB_MB_REG);
-
        c = &sp->u.iocb_cmd;
        c->timeout = qla2x00_async_iocb_timeout;
        init_completion(&c->u.mbx.comp);
 
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+       memcpy(sp->u.iocb_cmd.u.mbx.out_mb, mcp->mb, SIZEOF_IOCB_MB_REG);
+
        sp->done = qla2x00_async_mb_sp_done;
 
        rval = qla2x00_start_sp(sp);
index da85cd89639ff20d572f76866dc8e331aeb12ccd..f6f0a759a7c248eb403873c01fc9d4d912cced60 100644 (file)
@@ -929,8 +929,8 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
        sp->type = SRB_CTRL_VP;
        sp->name = "ctrl_vp";
        sp->done = qla_ctrlvp_sp_done;
-       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
        sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
        sp->u.iocb_cmd.u.ctrlvp.cmd = cmd;
        sp->u.iocb_cmd.u.ctrlvp.vp_index = vp_index;
 
index 7113acf42ff3907df68fda00b8336c782e58bfa6..521a513705549a9b263566c5bd9ea7b568bf4029 100644 (file)
@@ -1821,9 +1821,11 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
 
        sp->type = SRB_FXIOCB_DCMD;
        sp->name = "fxdisc";
-       qla2x00_init_timer(sp, FXDISC_TIMEOUT);
 
        fdisc = &sp->u.iocb_cmd;
+       fdisc->timeout = qla2x00_fxdisc_iocb_timeout;
+       qla2x00_init_timer(sp, FXDISC_TIMEOUT);
+
        switch (fx_type) {
        case FXDISC_GET_CONFIG_INFO:
        fdisc->u.fxiocb.flags =
@@ -1924,7 +1926,6 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
                        goto done_unmap_req;
        }
 
-       fdisc->timeout = qla2x00_fxdisc_iocb_timeout;
        fdisc->u.fxiocb.req_func_type = cpu_to_le16(fx_type);
        sp->done = qla2x00_fxdisc_sp_done;
 
index 5546ac9c3d9dd6028a45742740a4fa337420426c..025dc2d3f3de53a4e816486d8bdee12ee2011638 100644 (file)
@@ -664,10 +664,10 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
        sp->type = type;
        sp->name = "nack";
 
+       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
 
        sp->u.iocb_cmd.u.nack.ntfy = ntfy;
-       sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
        sp->done = qla2x00_async_nack_sp_done;
 
        rval = qla2x00_start_sp(sp);