diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 107 |
1 files changed, 86 insertions, 21 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 42ce4e1fe744..b9b3e6f80ea9 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -623,7 +623,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, } cur_seg = scsi_sglist(cmd); - ctx = sp->u.scmd.ct6_ctx; + ctx = &sp->u.scmd.ct6_ctx; while (tot_dsds) { avail_dsds = (tot_dsds > QLA_DSDS_PER_IOCB) ? @@ -1589,9 +1589,10 @@ qla24xx_start_scsi(srb_t *sp) tot_dsds = nseg; req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); - sp->iores.res_type = RESOURCE_INI; + sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH; + sp->iores.exch_cnt = 1; sp->iores.iocb_cnt = req_cnt; - if (qla_get_iocbs(sp->qpair, &sp->iores)) + if (qla_get_fw_resources(sp->qpair, &sp->iores)) goto queuing_error; if (req->cnt < (req_cnt + 2)) { @@ -1678,7 +1679,7 @@ queuing_error: if (tot_dsds) scsi_dma_unmap(cmd); - qla_put_iocbs(sp->qpair, &sp->iores); + qla_put_fw_resources(sp->qpair, &sp->iores); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_FUNCTION_FAILED; @@ -1793,9 +1794,10 @@ qla24xx_dif_start_scsi(srb_t *sp) tot_prot_dsds = nseg; tot_dsds += nseg; - sp->iores.res_type = RESOURCE_INI; + sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH; + sp->iores.exch_cnt = 1; sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); - if (qla_get_iocbs(sp->qpair, &sp->iores)) + if (qla_get_fw_resources(sp->qpair, &sp->iores)) goto queuing_error; if (req->cnt < (req_cnt + 2)) { @@ -1883,7 +1885,7 @@ queuing_error: } /* Cleanup will be performed by the caller (queuecommand) */ - qla_put_iocbs(sp->qpair, &sp->iores); + qla_put_fw_resources(sp->qpair, &sp->iores); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_FUNCTION_FAILED; @@ -1952,9 +1954,10 @@ qla2xxx_start_scsi_mq(srb_t *sp) tot_dsds = nseg; req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); - sp->iores.res_type = RESOURCE_INI; + sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH; + sp->iores.exch_cnt = 1; sp->iores.iocb_cnt = req_cnt; - if (qla_get_iocbs(sp->qpair, &sp->iores)) + if (qla_get_fw_resources(sp->qpair, &sp->iores)) goto queuing_error; if (req->cnt < (req_cnt + 2)) { @@ -2041,7 +2044,7 @@ queuing_error: if (tot_dsds) scsi_dma_unmap(cmd); - qla_put_iocbs(sp->qpair, &sp->iores); + qla_put_fw_resources(sp->qpair, &sp->iores); spin_unlock_irqrestore(&qpair->qp_lock, flags); return QLA_FUNCTION_FAILED; @@ -2171,9 +2174,10 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) tot_prot_dsds = nseg; tot_dsds += nseg; - sp->iores.res_type = RESOURCE_INI; + sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH; + sp->iores.exch_cnt = 1; sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); - if (qla_get_iocbs(sp->qpair, &sp->iores)) + if (qla_get_fw_resources(sp->qpair, &sp->iores)) goto queuing_error; if (req->cnt < (req_cnt + 2)) { @@ -2260,7 +2264,7 @@ queuing_error: } /* Cleanup will be performed by the caller (queuecommand) */ - qla_put_iocbs(sp->qpair, &sp->iores); + qla_put_fw_resources(sp->qpair, &sp->iores); spin_unlock_irqrestore(&qpair->qp_lock, flags); return QLA_FUNCTION_FAILED; @@ -2916,7 +2920,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) conflict_fcport->conflict = fcport; fcport->login_pause = 1; ql_dbg(ql_dbg_disc, vha, 0x20ed, - "%s %d %8phC pid %06x inuse with lid %#x post gidpn\n", + "%s %d %8phC pid %06x inuse with lid %#x.\n", __func__, __LINE__, fcport->port_name, fcport->d_id.b24, lid); @@ -3455,13 +3459,7 @@ sufficient_dsds: goto queuing_error; } - ctx = sp->u.scmd.ct6_ctx = - mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); - if (!ctx) { - ql_log(ql_log_fatal, vha, 0x3010, - "Failed to allocate ctx for cmd=%p.\n", cmd); - goto queuing_error; - } + ctx = &sp->u.scmd.ct6_ctx; memset(ctx, 0, sizeof(struct ct6_dsd)); ctx->fcp_cmnd = dma_pool_zalloc(ha->fcp_cmnd_dma_pool, @@ -3813,6 +3811,65 @@ qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio) logio->vp_index = sp->fcport->vha->vp_idx; } +static int qla_get_iocbs_resource(struct srb *sp) +{ + bool get_exch; + bool push_it_through = false; + + if (!ql2xenforce_iocb_limit) { + sp->iores.res_type = RESOURCE_NONE; + return 0; + } + sp->iores.res_type = RESOURCE_NONE; + + switch (sp->type) { + case SRB_TM_CMD: + case SRB_PRLI_CMD: + case SRB_ADISC_CMD: + push_it_through = true; + fallthrough; + case SRB_LOGIN_CMD: + case SRB_ELS_CMD_RPT: + case SRB_ELS_CMD_HST: + case SRB_ELS_CMD_HST_NOLOGIN: + case SRB_CT_CMD: + case SRB_NVME_LS: + case SRB_ELS_DCMD: + get_exch = true; + break; + + case SRB_FXIOCB_DCMD: + case SRB_FXIOCB_BCMD: + sp->iores.res_type = RESOURCE_NONE; + return 0; + + case SRB_SA_UPDATE: + case SRB_SA_REPLACE: + case SRB_MB_IOCB: + case SRB_ABT_CMD: + case SRB_NACK_PLOGI: + case SRB_NACK_PRLI: + case SRB_NACK_LOGO: + case SRB_LOGOUT_CMD: + case SRB_CTRL_VP: + push_it_through = true; + fallthrough; + default: + get_exch = false; + } + + sp->iores.res_type |= RESOURCE_IOCB; + sp->iores.iocb_cnt = 1; + if (get_exch) { + sp->iores.res_type |= RESOURCE_EXCH; + sp->iores.exch_cnt = 1; + } + if (push_it_through) + sp->iores.res_type |= RESOURCE_FORCE; + + return qla_get_fw_resources(sp->qpair, &sp->iores); +} + int qla2x00_start_sp(srb_t *sp) { @@ -3827,6 +3884,12 @@ qla2x00_start_sp(srb_t *sp) return -EIO; spin_lock_irqsave(qp->qp_lock_ptr, flags); + rval = qla_get_iocbs_resource(sp); + if (rval) { + spin_unlock_irqrestore(qp->qp_lock_ptr, flags); + return -EAGAIN; + } + pkt = __qla2x00_alloc_iocbs(sp->qpair, sp); if (!pkt) { rval = EAGAIN; @@ -3927,6 +3990,8 @@ qla2x00_start_sp(srb_t *sp) wmb(); qla2x00_start_iocbs(vha, qp->req); done: + if (rval) + qla_put_fw_resources(sp->qpair, &sp->iores); spin_unlock_irqrestore(qp->qp_lock_ptr, flags); return rval; } |