> On Apr 28, 2023, at 12:53 AM, Nilesh Javali <njavali@xxxxxxxxxxx> wrote: > > From: Quinn Tran <qutran@xxxxxxxxxxx> > > 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: kernel test robot <lkp@xxxxxxxxx> > Link: https://lore.kernel.org/oe-kbuild-all/202304271952.NKNmoFzv-lkp@xxxxxxxxx/ > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Quinn Tran <qutran@xxxxxxxxxxx> > Signed-off-by: Nilesh Javali <njavali@xxxxxxxxxxx> > --- > v2: > - Fix warning reported by kernel robot. > > drivers/scsi/qla2xxx/qla_def.h | 3 ++ > drivers/scsi/qla2xxx/qla_init.c | 63 ++++++++++++++++++++++++++++++--- > 2 files changed, 61 insertions(+), 5 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h > index 0437e0150a50..0971150953a9 100644 > --- a/drivers/scsi/qla2xxx/qla_def.h > +++ b/drivers/scsi/qla2xxx/qla_def.h > @@ -2543,6 +2543,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; > @@ -2563,6 +2564,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]; > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c > index 2402b1402e0d..17649cf9c39d 100644 > --- a/drivers/scsi/qla2xxx/qla_init.c > +++ b/drivers/scsi/qla2xxx/qla_init.c > @@ -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); > -- > 2.23.1 > Reviewed-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx> -- Himanshu Madhani Oracle Linux Engineering