From: Ben Hutchings Date: Tue, 20 Mar 2018 21:36:14 +0000 (+0000) Subject: scsi: qla2xxx: Fix race condition between iocb timeout and initialisation X-Git-Tag: v4.1.12-124.31.3~441 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ee20ff651d2ce57932933f363a83ce0c1bfcf480;p=users%2Fjedix%2Flinux-maple.git scsi: qla2xxx: Fix race condition between iocb timeout and initialisation 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 Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen (cherry picked from commit e74e7d95878d7993cf56c801d55d78f16ea58d1d) Orabug: 28013813 Signed-off-by: Somasundaram Krishnasamy Reviewed-by: Chuck Anderson Signed-off-by: Brian Maly Conflicts: 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_mid.c drivers/scsi/qla2xxx/qla_mr.c Signed-off-by: Brian Maly --- diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index c9233211824d..f5a85b49e03d 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -2949,6 +2949,7 @@ int qla24xx_async_gidpn(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 */ @@ -2968,7 +2969,6 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport) sp->u.iocb_cmd.u.ctarg.rsp_size = GID_PN_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_gidpn_sp_done; rval = qla2x00_start_sp(sp); @@ -3109,6 +3109,7 @@ int qla24xx_async_gpsc(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 */ @@ -3127,7 +3128,6 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport) sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE; sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id; - sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout; sp->done = qla24xx_async_gpsc_sp_done; rval = qla2x00_start_sp(sp); @@ -3411,6 +3411,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id) sp->name = sp_to_str(SPCN_GPNID); sp->u.iocb_cmd.u.ctarg.id = *id; sp->gen1 = 0; + sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout; qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); @@ -3459,7 +3460,6 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id) sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_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_gpnid_sp_done; rval = qla2x00_start_sp(sp); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index fd9e9343d519..e865c811c349 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -184,10 +184,11 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, sp->type = SRB_LOGIN_CMD; sp->name = sp_to_str(SPCN_LOGIN); - 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; if (data[1] & QLA_LOGIO_LOGIN_RETRIED) @@ -242,10 +243,11 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) sp->type = SRB_LOGOUT_CMD; sp->name = sp_to_str(SPCN_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) @@ -294,10 +296,11 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport, sp->type = SRB_ADISC_CMD; sp->name = sp_to_str(SPCN_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; @@ -576,6 +579,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; @@ -588,9 +593,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); @@ -709,6 +711,9 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt) sp->name = sp_to_str(SPCN_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); mb = sp->u.iocb_cmd.u.mbx.out_mb; @@ -721,8 +726,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; @@ -1184,13 +1187,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 = sp_to_str(SPCN_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) @@ -1262,11 +1267,12 @@ qla24xx_async_abort_cmd(srb_t *cmd_sp) abt_iocb = &sp->u.iocb_cmd; sp->type = SRB_ABT_CMD; sp->name = sp_to_str(SPCN_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; 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) diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 66df6cec59da..571188942992 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -284,12 +284,12 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo) sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ; sp->u.iocb_cmd.timer.data = (unsigned long)sp; sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout; - add_timer(&sp->u.iocb_cmd.timer); sp->free = qla2x00_sp_free; 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 diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index b8dcd33afb3e..d11101aa6012 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2639,8 +2639,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, sp->type = SRB_ELS_DCMD; sp->name = sp_to_str(SPCN_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; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 7934db629fb1..6a1833eb7c07 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -5594,14 +5594,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); diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index be91550b8c72..6aa42762f989 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -1818,7 +1818,13 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) if (!sp) goto done; + sp->type = SRB_FXIOCB_DCMD; + sp->name = sp_to_str(SPCN_FXDISC); + 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 = @@ -1920,10 +1926,6 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) goto done_unmap_req; } - sp->type = SRB_FXIOCB_DCMD; - sp->name = sp_to_str(SPCN_FXDISC); - qla2x00_init_timer(sp, FXDISC_TIMEOUT); - fdisc->timeout = qla2x00_fxdisc_iocb_timeout; fdisc->u.fxiocb.req_func_type = cpu_to_le16(fx_type); sp->done = qla2x00_fxdisc_sp_done; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 68282a006026..228c8cdf85e2 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -623,10 +623,10 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport, sp->type = type; sp->name = sp_to_str(SPCN_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);