Commit 6a876796 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Fix task management cmd fail due to unavailable resource



Task management command failed with status 2Ch which is
a result of too many task management commands sent
to the same target. Hence limit task management commands
to 8 per target.

Reported-by: default avatarkernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/oe-kbuild-all/202304271952.NKNmoFzv-lkp@intel.com/


Cc: stable@vger.kernel.org
Signed-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230428075339.32551-4-njavali@marvell.com


Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 9803fb5d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2542,6 +2542,7 @@ enum rscn_addr_format {
typedef struct fc_port {
	struct list_head list;
	struct scsi_qla_host *vha;
	struct list_head tmf_pending;

	unsigned int conf_compl_supported:1;
	unsigned int deleted:2;
@@ -2562,6 +2563,8 @@ typedef struct fc_port {
	unsigned int do_prli_nvme:1;

	uint8_t nvme_flag;
	uint8_t active_tmf;
#define MAX_ACTIVE_TMF 8

	uint8_t node_name[WWN_SIZE];
	uint8_t port_name[WWN_SIZE];
+58 −5
Original line number Diff line number Diff line
@@ -2149,6 +2149,54 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
	return rval;
}

static void qla_put_tmf(fc_port_t *fcport)
{
	struct scsi_qla_host *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
	unsigned long flags;

	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
	fcport->active_tmf--;
	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}

static
int qla_get_tmf(fc_port_t *fcport)
{
	struct scsi_qla_host *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
	unsigned long flags;
	int rc = 0;
	LIST_HEAD(tmf_elem);

	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
	list_add_tail(&tmf_elem, &fcport->tmf_pending);

	while (fcport->active_tmf >= MAX_ACTIVE_TMF) {
		spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);

		msleep(1);

		spin_lock_irqsave(&ha->tgt.sess_lock, flags);
		if (fcport->deleted) {
			rc = EIO;
			break;
		}
		if (fcport->active_tmf < MAX_ACTIVE_TMF &&
		    list_is_first(&tmf_elem, &fcport->tmf_pending))
			break;
	}

	list_del(&tmf_elem);

	if (!rc)
		fcport->active_tmf++;

	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);

	return rc;
}

int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
		     uint32_t tag)
@@ -2156,18 +2204,19 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
	struct scsi_qla_host *vha = fcport->vha;
	struct qla_qpair *qpair;
	struct tmf_arg a;
	struct completion comp;
	int i, rval;

	init_completion(&comp);
	a.vha = fcport->vha;
	a.fcport = fcport;
	a.lun = lun;

	if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA))
	if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
		a.modifier = MK_SYNC_ID_LUN;
	else

		if (qla_get_tmf(fcport))
			return QLA_FUNCTION_FAILED;
	} else {
		a.modifier = MK_SYNC_ID;
	}

	if (vha->hw->mqenable) {
		for (i = 0; i < vha->hw->num_qpairs; i++) {
@@ -2186,6 +2235,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
	a.flags = flags;
	rval = __qla2x00_async_tm_cmd(&a);

	if (a.modifier == MK_SYNC_ID_LUN)
		qla_put_tmf(fcport);

	return rval;
}

@@ -5400,6 +5452,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
	INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
	INIT_LIST_HEAD(&fcport->gnl_entry);
	INIT_LIST_HEAD(&fcport->list);
	INIT_LIST_HEAD(&fcport->tmf_pending);

	INIT_LIST_HEAD(&fcport->sess_cmd_list);
	spin_lock_init(&fcport->sess_cmd_lock);