> On Jul 12, 2023, at 2:05 AM, Nilesh Javali <njavali@xxxxxxxxxxx> wrote: > > From: Quinn Tran <qutran@xxxxxxxxxxx> > > 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@xxxxxxxxxxxxxxx > Fixes: 6a87679626b5 ("scsi: qla2xxx: Fix task management cmd fail due to unavailable resource") > Signed-off-by: Quinn Tran <qutran@xxxxxxxxxxx> > Signed-off-by: Nilesh Javali <njavali@xxxxxxxxxxx> > --- > drivers/scsi/qla2xxx/qla_def.h | 9 +++--- > drivers/scsi/qla2xxx/qla_init.c | 55 ++++++++++++++++++++------------- > drivers/scsi/qla2xxx/qla_os.c | 2 ++ > 3 files changed, 41 insertions(+), 25 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h > index 95a12b4e0484..03d94e024bdd 100644 > --- a/drivers/scsi/qla2xxx/qla_def.h > +++ b/drivers/scsi/qla2xxx/qla_def.h > @@ -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; > @@ -4656,6 +4653,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; > @@ -4670,6 +4669,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)]; > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c > index 60dd0e415351..5ec6f01ca635 100644 > --- a/drivers/scsi/qla2xxx/qla_init.c > +++ b/drivers/scsi/qla2xxx/qla_init.c > @@ -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); > diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c > index 877e4f446709..47bbc8b321f8 100644 > --- a/drivers/scsi/qla2xxx/qla_os.c > +++ b/drivers/scsi/qla2xxx/qla_os.c > @@ -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)) { > -- > 2.23.1 > Reviewed-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx> -- Himanshu Madhani Oracle Linux Engineering