|
From: Gleb C. <lna...@ya...> - 2023-07-19 08:37:06
|
Commit: 4b813bf GitHub URL: https://github.com/SCST-project/scst/commit/4b813bf125242b6da4e67620fc871e3a449cd8b2 Author: Gleb Chesnokov Date: 2023-07-19T11:35:51+03:00 Log Message: ----------- qla2x00t-32gbit: 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: kernel test robot <lk...@in...> Link: https://lore.kernel.org/oe-kbuild-all/202...@in.../ Cc: st...@vg... Signed-off-by: Quinn Tran <qu...@ma...> Signed-off-by: Nilesh Javali <nj...@ma...> Link: https://lore.kernel.org/r/202...@ma... Reviewed-by: Himanshu Madhani <him...@or...> Signed-off-by: Martin K. Petersen <mar...@or...> [ commit 6a87679626b5 upstream ] Modified Paths: -------------- qla2x00t-32gbit/qla_def.h | 3 + qla2x00t-32gbit/qla_init.c | 63 +++++++++++++-- 2 files changed, 61 insertions(+), 5 deletions(-) =================================================================== diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 2717f6f..01c84e2 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -2593,6 +2593,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; @@ -2613,6 +2614,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/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 1339077..dc17acd 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2149,6 +2149,54 @@ done: 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; } @@ -5403,6 +5455,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); |