diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 78a57ec98..012d249e8 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -559,7 +559,7 @@ typedef struct srb { u32 gen2; /* scratch */ int rc; int retry_count; - struct completion comp; + struct completion *comp; union { struct srb_iocb iocb_cmd; #ifndef NEW_LIBFC_API diff --git a/qla2x00t-32gbit/qla_inline.h b/qla2x00t-32gbit/qla_inline.h index 0bdf090ba..507d177a4 100644 --- a/qla2x00t-32gbit/qla_inline.h +++ b/qla2x00t-32gbit/qla_inline.h @@ -302,7 +302,6 @@ 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; 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); add_timer(&sp->u.iocb_cmd.timer); diff --git a/qla2x00t-32gbit/qla_mid.c b/qla2x00t-32gbit/qla_mid.c index 099d8e985..b2977e493 100644 --- a/qla2x00t-32gbit/qla_mid.c +++ b/qla2x00t-32gbit/qla_mid.c @@ -905,7 +905,8 @@ static void qla_ctrlvp_sp_done(void *s, int res) { struct srb *sp = s; - complete(&sp->comp); + if (sp->comp) + complete(sp->comp); /* don't free sp here. Let the caller do the free */ } @@ -922,6 +923,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) struct qla_hw_data *ha = vha->hw; int vp_index = vha->vp_idx; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + DECLARE_COMPLETION_ONSTACK(comp); srb_t *sp; ql_dbg(ql_dbg_vport, vha, 0x10c1, @@ -936,6 +938,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) sp->type = SRB_CTRL_VP; sp->name = "ctrl_vp"; + sp->comp = ∁ sp->done = qla_ctrlvp_sp_done; sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout; qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); @@ -953,7 +956,9 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) ql_dbg(ql_dbg_vport, vha, 0x113f, "%s hndl %x submitted\n", sp->name, sp->handle); - wait_for_completion(&sp->comp); + wait_for_completion(&comp); + sp->comp = NULL; + rval = sp->rc; switch (rval) { case QLA_FUNCTION_TIMEOUT: diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 4dba38916..764a5b1ce 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -145,8 +145,7 @@ static void qla_nvme_sp_ls_done(void *ptr, int res) if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; - if (!atomic_dec_and_test(&sp->ref_count)) - return; + atomic_dec(&sp->ref_count); if (res) res = -EINVAL; @@ -169,9 +168,11 @@ static void qla_nvme_sp_done(void *ptr, int res) nvme = &sp->u.iocb_cmd; fd = nvme->u.nvme.desc; - if (!atomic_dec_and_test(&sp->ref_count)) + if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; + atomic_dec(&sp->ref_count); + if (res == QLA_SUCCESS) { fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; } else { diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 22f76f1a4..3e0e01646 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -804,16 +804,18 @@ qla2x00_sp_compl(void *ptr, int res) { srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); + struct completion *comp = sp->comp; if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; - if (!atomic_dec_and_test(&sp->ref_count)) - return; + atomic_dec(&sp->ref_count); sp->free(sp); cmd->result = res; cmd->scsi_done(cmd); + if (comp) + complete(comp); } void @@ -907,17 +909,17 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) { srb_t *sp = ptr; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - - cmd->result = res; + struct completion *comp = sp->comp; if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; - if (!atomic_dec_and_test(&sp->ref_count)) - return; + atomic_dec(&sp->ref_count); sp->free(sp); cmd->scsi_done(cmd); + if (comp) + complete(comp); } #if defined(RHEL_MAJOR) && RHEL_MAJOR -0 == 6 && RHEL_MINOR -0 >= 2 @@ -1378,12 +1380,13 @@ static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { scsi_qla_host_t *vha = shost_priv(cmd->device->host); + DECLARE_COMPLETION_ONSTACK(comp); srb_t *sp; int ret; unsigned int id; uint64_t lun; unsigned long flags; - int rval, wait = 0; + int rval; struct qla_hw_data *ha = vha->hw; struct qla_qpair *qpair; @@ -1407,9 +1410,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return SUCCESS; spin_lock_irqsave(qpair->qp_lock_ptr, flags); - if (!CMD_SP(cmd)) { - /* there's a chance an interrupt could clear - the ptr as part of done & free */ + if (sp->type != SRB_SCSI_CMD || GET_CMD_SP(sp) != cmd) { spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return SUCCESS; } @@ -1430,56 +1431,39 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) /* Get a reference to the sp and drop the lock.*/ + ret = SUCCESS; rval = ha->isp_ops->abort_command(sp); - if (rval) { - if (rval == QLA_FUNCTION_PARAMETER_ERROR) - ret = SUCCESS; - else - ret = FAILED; + ql_dbg(ql_dbg_taskm, vha, 0x8003, + "Abort command mbx cmd=%p, rval=%x.\n", cmd, rval); - ql_dbg(ql_dbg_taskm, vha, 0x8003, - "Abort command mbx failed cmd=%p, rval=%x.\n", cmd, rval); - } else { - ql_dbg(ql_dbg_taskm, vha, 0x8004, - "Abort command mbx success cmd=%p.\n", cmd); - wait = 1; - } + switch (rval) { + case QLA_SUCCESS: + /* The command has been aborted. */ + sp->done(sp, DID_ABORT << 16); + break; + case QLA_FUNCTION_PARAMETER_ERROR: + default: { + /* Wait for the command completion. */ + uint32_t ratov = ha->r_a_tov/10; + uint32_t ratov_j = msecs_to_jiffies(4 * ratov * 1000); - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - /* - * Clear the slot in the oustanding_cmds array if we can't find the - * command to reclaim the resources. - */ - if (rval == QLA_FUNCTION_PARAMETER_ERROR) - vha->req->outstanding_cmds[sp->handle] = NULL; - - /* - * sp->done will do ref_count-- - * sp_get() took an extra count above - */ - sp->done(sp, DID_RESET << 16); - - /* Did the command return during mailbox execution? */ - if (ret == FAILED && !CMD_SP(cmd)) - ret = SUCCESS; - - if (!CMD_SP(cmd)) - wait = 0; - - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - - /* Wait for the command to be returned. */ - if (wait) { - if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x8006, - "Abort handler timed out cmd=%p.\n", cmd); + sp->comp = ∁ + if (!wait_for_completion_timeout(&comp, ratov_j)) { + ql_dbg(ql_dbg_taskm, vha, 0xffff, + "%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n", + __func__, ha->r_a_tov); ret = FAILED; + break; } + break; + } } + sp->comp = NULL; + atomic_dec(&sp->ref_count); ql_log(ql_log_info, vha, 0x801c, - "Abort command issued nexus=%ld:%d:%llu -- %d %x.\n", - vha->host_no, id, lun, wait, ret); + "Abort command issued nexus=%ld:%d:%llu -- %x.\n", + vha->host_no, id, lun, ret); return ret; }