]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: qla2xxx: Fix task management cmd fail due to unavailable resource
authorQuinn Tran <qutran@marvell.com>
Fri, 28 Apr 2023 07:53:35 +0000 (00:53 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2023 08:22:31 +0000 (10:22 +0200)
[ Upstream commit 6a87679626b51b53fbb6be417ad8eb083030b617 ]

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@intel.com>
Link: https://lore.kernel.org/oe-kbuild-all/202304271952.NKNmoFzv-lkp@intel.com/
Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230428075339.32551-4-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c

index ca63aa8f33b5d48de7e8ea75343eaae3ac57083e..bbeb116c16cc34a1f13cdce10df75b94d0d0082b 100644 (file)
@@ -2523,6 +2523,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;
@@ -2543,6 +2544,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];
index 9d9b16f7f34a664ab7230665fab8ea2879072a60..2c42ecb2a64a5d813e7cc11c15e78b87bed0bb33 100644 (file)
@@ -2151,6 +2151,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)
@@ -2158,18 +2206,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++) {
@@ -2188,6 +2237,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;
 }
 
@@ -5423,6 +5475,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);