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

scsi: qla2xxx: 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: default avatarkernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/oe-kbuild-all/202304271952.NKNmoFzv-lkp@intel.com/
Cc: stable@vger.kernel.org
Signed-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230428075339.32551-4-njavali@marvell.comReviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 9803fb5d
...@@ -2542,6 +2542,7 @@ enum rscn_addr_format { ...@@ -2542,6 +2542,7 @@ 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,6 +2563,8 @@ typedef struct fc_port { ...@@ -2562,6 +2563,8 @@ 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];
......
...@@ -2149,6 +2149,54 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) ...@@ -2149,6 +2149,54 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
return rval; 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 int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
uint32_t tag) uint32_t tag)
...@@ -2156,18 +2204,19 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, ...@@ -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 scsi_qla_host *vha = fcport->vha;
struct qla_qpair *qpair; struct qla_qpair *qpair;
struct tmf_arg a; struct tmf_arg a;
struct completion comp;
int i, rval; int i, rval;
init_completion(&comp);
a.vha = fcport->vha; a.vha = fcport->vha;
a.fcport = fcport; a.fcport = fcport;
a.lun = lun; 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; a.modifier = MK_SYNC_ID_LUN;
else
if (qla_get_tmf(fcport))
return QLA_FUNCTION_FAILED;
} else {
a.modifier = MK_SYNC_ID; a.modifier = MK_SYNC_ID;
}
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++) {
...@@ -2186,6 +2235,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, ...@@ -2186,6 +2235,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
a.flags = flags; a.flags = flags;
rval = __qla2x00_async_tm_cmd(&a); rval = __qla2x00_async_tm_cmd(&a);
if (a.modifier == MK_SYNC_ID_LUN)
qla_put_tmf(fcport);
return rval; return rval;
} }
...@@ -5400,6 +5452,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) ...@@ -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_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);
......
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