--- /dev/null
+From 0ba0b018f94525a6b32f5930f980ce9b62b72e6f Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Mon, 21 Aug 2023 18:30:41 +0530
+Subject: scsi: qla2xxx: Error code did not return to upper layer
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 0ba0b018f94525a6b32f5930f980ce9b62b72e6f upstream.
+
+TMF was returned with an error code. The error code was not preserved to be
+returned to upper layer. Instead, the error code from the Marker was
+returned.
+
+Preserve error code from TMF and return it to upper layer.
+
+Cc: stable@vger.kernel.org
+Fixes: da7c21b72aa8 ("scsi: qla2xxx: Fix command flush during TMF")
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230821130045.34850-6-njavali@marvell.com
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qla2xxx/qla_init.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -2224,6 +2224,8 @@ __qla2x00_async_tm_cmd(struct tmf_arg *a
+ rval = QLA_FUNCTION_FAILED;
+ }
+ }
++ if (tm_iocb->u.tmf.data)
++ rval = tm_iocb->u.tmf.data;
+
+ done_free_sp:
+ /* ref: INIT */
--- /dev/null
+From e370b64c7db96384a0886a09a9d80406e4c663d7 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Mon, 21 Aug 2023 18:30:39 +0530
+Subject: scsi: qla2xxx: Fix firmware resource tracking
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit e370b64c7db96384a0886a09a9d80406e4c663d7 upstream.
+
+The storage was not draining I/Os and the work load was not spread out
+across different CPUs evenly. This led to firmware resource counters
+getting overrun on the busy CPU. This overrun prevented error recovery from
+happening in a timely manner.
+
+By switching the counter to atomic, it allows the count to be little more
+accurate to prevent the overrun.
+
+Cc: stable@vger.kernel.org
+Fixes: da7c21b72aa8 ("scsi: qla2xxx: Fix command flush during TMF")
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230821130045.34850-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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h | 11 +++++++
+ drivers/scsi/qla2xxx/qla_dfs.c | 10 ++++++
+ drivers/scsi/qla2xxx/qla_init.c | 8 +++++
+ drivers/scsi/qla2xxx/qla_inline.h | 57 +++++++++++++++++++++++++++++++++++++-
+ drivers/scsi/qla2xxx/qla_os.c | 5 ++-
+ 5 files changed, 88 insertions(+), 3 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -3740,6 +3740,16 @@ struct qla_fw_resources {
+ u16 pad;
+ };
+
++struct qla_fw_res {
++ u16 iocb_total;
++ u16 iocb_limit;
++ atomic_t iocb_used;
++
++ u16 exch_total;
++ u16 exch_limit;
++ atomic_t exch_used;
++};
++
+ #define QLA_IOCB_PCT_LIMIT 95
+
+ /*Queue pair data structure */
+@@ -4782,6 +4792,7 @@ struct qla_hw_data {
+ spinlock_t sadb_lock; /* protects list */
+ struct els_reject elsrej;
+ u8 edif_post_stop_cnt_down;
++ struct qla_fw_res fwres ____cacheline_aligned;
+ };
+
+ #define RX_ELS_SIZE (roundup(sizeof(struct enode) + ELS_MAX_PAYLOAD, SMP_CACHE_BYTES))
+--- a/drivers/scsi/qla2xxx/qla_dfs.c
++++ b/drivers/scsi/qla2xxx/qla_dfs.c
+@@ -276,6 +276,16 @@ qla_dfs_fw_resource_cnt_show(struct seq_
+
+ seq_printf(s, "estimate exchange used[%d] high water limit [%d] n",
+ exch_used, ha->base_qpair->fwres.exch_limit);
++
++ if (ql2xenforce_iocb_limit == 2) {
++ iocbs_used = atomic_read(&ha->fwres.iocb_used);
++ exch_used = atomic_read(&ha->fwres.exch_used);
++ seq_printf(s, " estimate iocb2 used [%d] high water limit [%d]\n",
++ iocbs_used, ha->fwres.iocb_limit);
++
++ seq_printf(s, " estimate exchange2 used[%d] high water limit [%d] \n",
++ exch_used, ha->fwres.exch_limit);
++ }
+ }
+
+ return 0;
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -4217,6 +4217,14 @@ void qla_init_iocb_limit(scsi_qla_host_t
+ ha->queue_pair_map[i]->fwres.exch_used = 0;
+ }
+ }
++
++ ha->fwres.iocb_total = ha->orig_fw_iocb_count;
++ ha->fwres.iocb_limit = (ha->orig_fw_iocb_count * QLA_IOCB_PCT_LIMIT) / 100;
++ ha->fwres.exch_total = ha->orig_fw_xcb_count;
++ ha->fwres.exch_limit = (ha->orig_fw_xcb_count * QLA_IOCB_PCT_LIMIT) / 100;
++
++ atomic_set(&ha->fwres.iocb_used, 0);
++ atomic_set(&ha->fwres.exch_used, 0);
+ }
+
+ void qla_adjust_iocb_limit(scsi_qla_host_t *vha)
+--- a/drivers/scsi/qla2xxx/qla_inline.h
++++ b/drivers/scsi/qla2xxx/qla_inline.h
+@@ -386,6 +386,7 @@ enum {
+ RESOURCE_IOCB = BIT_0,
+ RESOURCE_EXCH = BIT_1, /* exchange */
+ RESOURCE_FORCE = BIT_2,
++ RESOURCE_HA = BIT_3,
+ };
+
+ static inline int
+@@ -393,7 +394,7 @@ qla_get_fw_resources(struct qla_qpair *q
+ {
+ u16 iocbs_used, i;
+ u16 exch_used;
+- struct qla_hw_data *ha = qp->vha->hw;
++ struct qla_hw_data *ha = qp->hw;
+
+ if (!ql2xenforce_iocb_limit) {
+ iores->res_type = RESOURCE_NONE;
+@@ -428,15 +429,69 @@ qla_get_fw_resources(struct qla_qpair *q
+ return -ENOSPC;
+ }
+ }
++
++ if (ql2xenforce_iocb_limit == 2) {
++ if ((iores->iocb_cnt + atomic_read(&ha->fwres.iocb_used)) >=
++ ha->fwres.iocb_limit) {
++ iores->res_type = RESOURCE_NONE;
++ return -ENOSPC;
++ }
++
++ if (iores->res_type & RESOURCE_EXCH) {
++ if ((iores->exch_cnt + atomic_read(&ha->fwres.exch_used)) >=
++ ha->fwres.exch_limit) {
++ iores->res_type = RESOURCE_NONE;
++ return -ENOSPC;
++ }
++ }
++ }
++
+ force:
+ qp->fwres.iocbs_used += iores->iocb_cnt;
+ qp->fwres.exch_used += iores->exch_cnt;
++ if (ql2xenforce_iocb_limit == 2) {
++ atomic_add(iores->iocb_cnt, &ha->fwres.iocb_used);
++ atomic_add(iores->exch_cnt, &ha->fwres.exch_used);
++ iores->res_type |= RESOURCE_HA;
++ }
+ return 0;
+ }
+
++/*
++ * decrement to zero. This routine will not decrement below zero
++ * @v: pointer of type atomic_t
++ * @amount: amount to decrement from v
++ */
++static void qla_atomic_dtz(atomic_t *v, int amount)
++{
++ int c, old, dec;
++
++ c = atomic_read(v);
++ for (;;) {
++ dec = c - amount;
++ if (unlikely(dec < 0))
++ dec = 0;
++
++ old = atomic_cmpxchg((v), c, dec);
++ if (likely(old == c))
++ break;
++ c = old;
++ }
++}
++
+ static inline void
+ qla_put_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores)
+ {
++ struct qla_hw_data *ha = qp->hw;
++
++ if (iores->res_type & RESOURCE_HA) {
++ if (iores->res_type & RESOURCE_IOCB)
++ qla_atomic_dtz(&ha->fwres.iocb_used, iores->iocb_cnt);
++
++ if (iores->res_type & RESOURCE_EXCH)
++ qla_atomic_dtz(&ha->fwres.exch_used, iores->exch_cnt);
++ }
++
+ if (iores->res_type & RESOURCE_IOCB) {
+ if (qp->fwres.iocbs_used >= iores->iocb_cnt) {
+ qp->fwres.iocbs_used -= iores->iocb_cnt;
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -44,10 +44,11 @@ module_param(ql2xfulldump_on_mpifail, in
+ MODULE_PARM_DESC(ql2xfulldump_on_mpifail,
+ "Set this to take full dump on MPI hang.");
+
+-int ql2xenforce_iocb_limit = 1;
++int ql2xenforce_iocb_limit = 2;
+ module_param(ql2xenforce_iocb_limit, int, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(ql2xenforce_iocb_limit,
+- "Enforce IOCB throttling, to avoid FW congestion. (default: 1)");
++ "Enforce IOCB throttling, to avoid FW congestion. (default: 2) "
++ "1: track usage per queue, 2: track usage per adapter");
+
+ /*
+ * CT6 CTX allocation cache
--- /dev/null
+From b496953dd0444001b12f425ea07d78c1f47e3193 Mon Sep 17 00:00:00 2001
+From: Nilesh Javali <njavali@marvell.com>
+Date: Mon, 21 Aug 2023 18:30:43 +0530
+Subject: scsi: qla2xxx: Fix smatch warn for qla_init_iocb_limit()
+
+From: Nilesh Javali <njavali@marvell.com>
+
+commit b496953dd0444001b12f425ea07d78c1f47e3193 upstream.
+
+Fix indentation for warning reported by smatch:
+
+drivers/scsi/qla2xxx/qla_init.c:4199 qla_init_iocb_limit() warn: inconsistent indenting
+
+Fixes: efa74a62aaa2 ("scsi: qla2xxx: Adjust IOCB resource on qpair create")
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230821130045.34850-8-njavali@marvell.com
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qla2xxx/qla_init.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -4204,7 +4204,7 @@ void qla_init_iocb_limit(scsi_qla_host_t
+ u8 i;
+ struct qla_hw_data *ha = vha->hw;
+
+- __qla_adjust_iocb_limit(ha->base_qpair);
++ __qla_adjust_iocb_limit(ha->base_qpair);
+ ha->base_qpair->fwres.iocbs_used = 0;
+ ha->base_qpair->fwres.exch_used = 0;
+