Commit 5f63a163 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Fix exchange oversubscription for management commands



Add resource checking for management (non-I/O) commands.

Fixes: 89c72f42 ("scsi: qla2xxx: Add IOCB resource tracking")
Signed-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 41e5afe5
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -235,7 +235,7 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
	uint16_t mb[MAX_IOCB_MB_REG];
	int rc;
	struct qla_hw_data *ha = vha->hw;
	u16 iocbs_used, i;
	u16 iocbs_used, i, exch_used;

	rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG);
	if (rc != QLA_SUCCESS) {
@@ -263,13 +263,19 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
	if (ql2xenforce_iocb_limit) {
		/* lock is not require. It's an estimate. */
		iocbs_used = ha->base_qpair->fwres.iocbs_used;
		exch_used = ha->base_qpair->fwres.exch_used;
		for (i = 0; i < ha->max_qpairs; i++) {
			if (ha->queue_pair_map[i])
			if (ha->queue_pair_map[i]) {
				iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used;
				exch_used += ha->queue_pair_map[i]->fwres.exch_used;
			}
		}

		seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n",
			   iocbs_used, ha->base_qpair->fwres.iocbs_limit);

		seq_printf(s, "estimate exchange used[%d] high water limit [%d] n",
			   exch_used, ha->base_qpair->fwres.exch_limit);
	}

	return 0;
+4 −1
Original line number Diff line number Diff line
@@ -396,6 +396,8 @@ qla_get_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores)
		iores->res_type = RESOURCE_NONE;
		return 0;
	}
	if (iores->res_type & RESOURCE_FORCE)
		goto force;

	if ((iores->iocb_cnt + qp->fwres.iocbs_used) >= qp->fwres.iocbs_qp_limit) {
		/* no need to acquire qpair lock. It's just rough calculation */
@@ -423,6 +425,7 @@ qla_get_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores)
			return -ENOSPC;
		}
	}
force:
	qp->fwres.iocbs_used += iores->iocb_cnt;
	qp->fwres.exch_used += iores->exch_cnt;
	return 0;
+67 −0
Original line number Diff line number Diff line
@@ -3817,6 +3817,65 @@ qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio)
	logio->vp_index = sp->fcport->vha->vp_idx;
}

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)
{
@@ -3831,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;
@@ -3931,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;
}
+1 −0
Original line number Diff line number Diff line
@@ -3112,6 +3112,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
	}
	bsg_reply->reply_payload_rcv_len = 0;

	qla_put_fw_resources(sp->qpair, &sp->iores);
done:
	/* Return the vendor specific reply to API */
	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;