summaryrefslogtreecommitdiff
path: root/drivers/scsi/qla2xxx/qla_iocb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c95
1 files changed, 83 insertions, 12 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 42ce4e1fe744..6b91dcfd994d 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -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;
@@ -3813,6 +3817,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 +3890,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 +3996,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;
}