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

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.comReviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent efa74a62
...@@ -466,6 +466,7 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id) ...@@ -466,6 +466,7 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id)
} }
struct tmf_arg { struct tmf_arg {
struct list_head tmf_elem;
struct qla_qpair *qpair; struct qla_qpair *qpair;
struct fc_port *fcport; struct fc_port *fcport;
struct scsi_qla_host *vha; struct scsi_qla_host *vha;
...@@ -2541,7 +2542,6 @@ enum rscn_addr_format { ...@@ -2541,7 +2542,6 @@ enum rscn_addr_format {
typedef struct fc_port { typedef struct fc_port {
struct list_head list; struct list_head list;
struct scsi_qla_host *vha; struct scsi_qla_host *vha;
struct list_head tmf_pending;
unsigned int conf_compl_supported:1; unsigned int conf_compl_supported:1;
unsigned int deleted:2; unsigned int deleted:2;
...@@ -2562,9 +2562,6 @@ typedef struct fc_port { ...@@ -2562,9 +2562,6 @@ typedef struct fc_port {
unsigned int do_prli_nvme:1; unsigned int do_prli_nvme:1;
uint8_t nvme_flag; uint8_t nvme_flag;
uint8_t active_tmf;
#define MAX_ACTIVE_TMF 8
uint8_t node_name[WWN_SIZE]; uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE];
port_id_t d_id; port_id_t d_id;
...@@ -4657,6 +4654,8 @@ struct qla_hw_data { ...@@ -4657,6 +4654,8 @@ struct qla_hw_data {
uint32_t flt_region_aux_img_status_sec; uint32_t flt_region_aux_img_status_sec;
}; };
uint8_t active_image; uint8_t active_image;
uint8_t active_tmf;
#define MAX_ACTIVE_TMF 8
/* Needed for BEACON */ /* Needed for BEACON */
uint16_t beacon_blink_led; uint16_t beacon_blink_led;
...@@ -4671,6 +4670,8 @@ struct qla_hw_data { ...@@ -4671,6 +4670,8 @@ struct qla_hw_data {
struct qla_msix_entry *msix_entries; struct qla_msix_entry *msix_entries;
struct list_head tmf_pending;
struct list_head tmf_active;
struct list_head vp_list; /* list of VP */ struct list_head vp_list; /* list of VP */
unsigned long vp_idx_map[(MAX_MULTI_ID_FABRIC / 8) / unsigned long vp_idx_map[(MAX_MULTI_ID_FABRIC / 8) /
sizeof(unsigned long)]; sizeof(unsigned long)];
......
...@@ -2192,30 +2192,42 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) ...@@ -2192,30 +2192,42 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
return rval; 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; struct qla_hw_data *ha = vha->hw;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ha->tgt.sess_lock, 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); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
} }
static 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; struct qla_hw_data *ha = vha->hw;
unsigned long flags; unsigned long flags;
fc_port_t *fcport = arg->fcport;
int rc = 0; int rc = 0;
LIST_HEAD(tmf_elem); struct tmf_arg *t;
spin_lock_irqsave(&ha->tgt.sess_lock, flags); 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); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
msleep(1); msleep(1);
...@@ -2227,15 +2239,17 @@ int qla_get_tmf(fc_port_t *fcport) ...@@ -2227,15 +2239,17 @@ int qla_get_tmf(fc_port_t *fcport)
rc = EIO; rc = EIO;
break; break;
} }
if (fcport->active_tmf < MAX_ACTIVE_TMF && if (ha->active_tmf < MAX_ACTIVE_TMF &&
list_is_first(&tmf_elem, &fcport->tmf_pending)) list_is_first(&arg->tmf_elem, &ha->tmf_pending))
break; break;
} }
list_del(&tmf_elem); list_del(&arg->tmf_elem);
if (!rc) if (!rc) {
fcport->active_tmf++; ha->active_tmf++;
list_add_tail(&arg->tmf_elem, &ha->tmf_active);
}
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); 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, ...@@ -2257,15 +2271,18 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
a.vha = fcport->vha; a.vha = fcport->vha;
a.fcport = fcport; a.fcport = fcport;
a.lun = lun; 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)) { if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
a.modifier = MK_SYNC_ID_LUN; a.modifier = MK_SYNC_ID_LUN;
if (qla_get_tmf(fcport))
return QLA_FUNCTION_FAILED;
} else { } else {
a.modifier = MK_SYNC_ID; a.modifier = MK_SYNC_ID;
} }
if (qla_get_tmf(&a))
return QLA_FUNCTION_FAILED;
if (vha->hw->mqenable) { if (vha->hw->mqenable) {
for (i = 0; i < vha->hw->num_qpairs; i++) { for (i = 0; i < vha->hw->num_qpairs; i++) {
qpair = vha->hw->queue_pair_map[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, ...@@ -2291,13 +2308,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
goto bailout; goto bailout;
a.qpair = vha->hw->base_qpair; a.qpair = vha->hw->base_qpair;
a.flags = flags;
rval = __qla2x00_async_tm_cmd(&a); rval = __qla2x00_async_tm_cmd(&a);
bailout: bailout:
if (a.modifier == MK_SYNC_ID_LUN) qla_put_tmf(&a);
qla_put_tmf(fcport);
return rval; return rval;
} }
...@@ -5526,7 +5540,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) ...@@ -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_WORK(&fcport->reg_work, qla_register_fcport_fn);
INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->gnl_entry);
INIT_LIST_HEAD(&fcport->list); INIT_LIST_HEAD(&fcport->list);
INIT_LIST_HEAD(&fcport->tmf_pending);
INIT_LIST_HEAD(&fcport->sess_cmd_list); INIT_LIST_HEAD(&fcport->sess_cmd_list);
spin_lock_init(&fcport->sess_cmd_lock); spin_lock_init(&fcport->sess_cmd_lock);
......
...@@ -3009,6 +3009,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -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->num_pend_mbx_stage3, 0);
atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD); atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD);
ha->last_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. */ /* Assign ISP specific operations. */
if (IS_QLA2100(ha)) { if (IS_QLA2100(ha)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment