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

scsi: qla2xxx: Limit TMF to 8 per function



Per FW recommendation, 8 TMF's can be outstanding for each
function. Previously, it allowed 8 per target.

Limit TMF to 8 per function.

Cc: stable@vger.kernel.org
Fixes: 6a876796 ("scsi: qla2xxx: Fix task management cmd fail due to unavailable resource")
Signed-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230714070104.40052-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 efa74a62
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -466,6 +466,7 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id)
}

struct tmf_arg {
	struct list_head tmf_elem;
	struct qla_qpair *qpair;
	struct fc_port *fcport;
	struct scsi_qla_host *vha;
@@ -2541,7 +2542,6 @@ 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,9 +2562,6 @@ 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];
	port_id_t d_id;
@@ -4657,6 +4654,8 @@ struct qla_hw_data {
		uint32_t	flt_region_aux_img_status_sec;
	};
	uint8_t         active_image;
	uint8_t active_tmf;
#define MAX_ACTIVE_TMF 8

	/* Needed for BEACON */
	uint16_t        beacon_blink_led;
@@ -4671,6 +4670,8 @@ struct qla_hw_data {

	struct qla_msix_entry *msix_entries;

	struct list_head tmf_pending;
	struct list_head tmf_active;
	struct list_head        vp_list;        /* list of VP */
	unsigned long   vp_idx_map[(MAX_MULTI_ID_FABRIC / 8) /
			sizeof(unsigned long)];
+34 −21
Original line number Diff line number Diff line
@@ -2192,30 +2192,42 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
	return rval;
}

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

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

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

	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
	list_add_tail(&tmf_elem, &fcport->tmf_pending);
	list_for_each_entry(t, &ha->tmf_active, tmf_elem) {
		if (t->fcport == arg->fcport && t->lun == arg->lun) {
			/* reject duplicate TMF */
			ql_log(ql_log_warn, vha, 0x802c,
			       "found duplicate TMF.  Nexus=%ld:%06x:%llu.\n",
			       vha->host_no, fcport->d_id.b24, arg->lun);
			spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
			return -EINVAL;
		}
	}

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

		msleep(1);
@@ -2227,15 +2239,17 @@ int qla_get_tmf(fc_port_t *fcport)
			rc = EIO;
			break;
		}
		if (fcport->active_tmf < MAX_ACTIVE_TMF &&
		    list_is_first(&tmf_elem, &fcport->tmf_pending))
		if (ha->active_tmf < MAX_ACTIVE_TMF &&
		    list_is_first(&arg->tmf_elem, &ha->tmf_pending))
			break;
	}

	list_del(&tmf_elem);
	list_del(&arg->tmf_elem);

	if (!rc)
		fcport->active_tmf++;
	if (!rc) {
		ha->active_tmf++;
		list_add_tail(&arg->tmf_elem, &ha->tmf_active);
	}

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

@@ -2257,15 +2271,18 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
	a.vha = fcport->vha;
	a.fcport = fcport;
	a.lun = lun;
	a.flags = flags;
	INIT_LIST_HEAD(&a.tmf_elem);

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

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

	if (qla_get_tmf(&a))
		return QLA_FUNCTION_FAILED;

	if (vha->hw->mqenable) {
		for (i = 0; i < vha->hw->num_qpairs; i++) {
			qpair = vha->hw->queue_pair_map[i];
@@ -2291,13 +2308,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
		goto bailout;

	a.qpair = vha->hw->base_qpair;
	a.flags = flags;
	rval = __qla2x00_async_tm_cmd(&a);

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

	qla_put_tmf(&a);
	return rval;
}

@@ -5526,7 +5540,6 @@ 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);
+2 −0
Original line number Diff line number Diff line
@@ -3009,6 +3009,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
	atomic_set(&ha->num_pend_mbx_stage3, 0);
	atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD);
	ha->last_zio_threshold = DEFAULT_ZIO_THRESHOLD;
	INIT_LIST_HEAD(&ha->tmf_pending);
	INIT_LIST_HEAD(&ha->tmf_active);

	/* Assign ISP specific operations. */
	if (IS_QLA2100(ha)) {