--- /dev/null
+From efa74a62aaa2429c04fe6cb277b3bf6739747d86 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:30:56 +0530
+Subject: scsi: qla2xxx: Adjust IOCB resource on qpair create
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit efa74a62aaa2429c04fe6cb277b3bf6739747d86 upstream.
+
+During NVMe queue creation, a new qpair is created. FW resource limit needs
+to be re-adjusted to take into account the new qpair. Otherwise, NVMe
+command can not go through. This issue was discovered while
+testing/forcing FW execution to fail at load time.
+
+Add call to readjust IOCB and exchange limit.
+
+In addition, get FW state command and require FW to be running. Otherwise,
+error is generated.
+
+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/20230714070104.40052-3-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_gbl.h | 1
+ drivers/scsi/qla2xxx/qla_init.c | 52 +++++++++++++++++++++++++---------------
+ drivers/scsi/qla2xxx/qla_mbx.c | 3 ++
+ drivers/scsi/qla2xxx/qla_nvme.c | 1
+ 4 files changed, 38 insertions(+), 19 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -143,6 +143,7 @@ void qla_edif_sess_down(struct scsi_qla_
+ void qla_edif_clear_appdata(struct scsi_qla_host *vha,
+ struct fc_port *fcport);
+ const char *sc_to_str(uint16_t cmd);
++void qla_adjust_iocb_limit(scsi_qla_host_t *vha);
+
+ /*
+ * Global Data in qla_os.c source file.
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -4147,41 +4147,55 @@ out:
+ return ha->flags.lr_detected;
+ }
+
+-void qla_init_iocb_limit(scsi_qla_host_t *vha)
++static void __qla_adjust_iocb_limit(struct qla_qpair *qpair)
+ {
+- u16 i, num_qps;
+- u32 limit;
+- struct qla_hw_data *ha = vha->hw;
++ u8 num_qps;
++ u16 limit;
++ struct qla_hw_data *ha = qpair->vha->hw;
+
+ num_qps = ha->num_qpairs + 1;
+ limit = (ha->orig_fw_iocb_count * QLA_IOCB_PCT_LIMIT) / 100;
+
+- ha->base_qpair->fwres.iocbs_total = ha->orig_fw_iocb_count;
+- ha->base_qpair->fwres.iocbs_limit = limit;
+- ha->base_qpair->fwres.iocbs_qp_limit = limit / num_qps;
+- ha->base_qpair->fwres.iocbs_used = 0;
++ qpair->fwres.iocbs_total = ha->orig_fw_iocb_count;
++ qpair->fwres.iocbs_limit = limit;
++ qpair->fwres.iocbs_qp_limit = limit / num_qps;
++
++ qpair->fwres.exch_total = ha->orig_fw_xcb_count;
++ qpair->fwres.exch_limit = (ha->orig_fw_xcb_count *
++ QLA_IOCB_PCT_LIMIT) / 100;
++}
+
+- ha->base_qpair->fwres.exch_total = ha->orig_fw_xcb_count;
+- ha->base_qpair->fwres.exch_limit = (ha->orig_fw_xcb_count *
+- QLA_IOCB_PCT_LIMIT) / 100;
++void qla_init_iocb_limit(scsi_qla_host_t *vha)
++{
++ u8 i;
++ struct qla_hw_data *ha = vha->hw;
++
++ __qla_adjust_iocb_limit(ha->base_qpair);
++ ha->base_qpair->fwres.iocbs_used = 0;
+ ha->base_qpair->fwres.exch_used = 0;
+
+ for (i = 0; i < ha->max_qpairs; i++) {
+ if (ha->queue_pair_map[i]) {
+- ha->queue_pair_map[i]->fwres.iocbs_total =
+- ha->orig_fw_iocb_count;
+- ha->queue_pair_map[i]->fwres.iocbs_limit = limit;
+- ha->queue_pair_map[i]->fwres.iocbs_qp_limit =
+- limit / num_qps;
++ __qla_adjust_iocb_limit(ha->queue_pair_map[i]);
+ ha->queue_pair_map[i]->fwres.iocbs_used = 0;
+- ha->queue_pair_map[i]->fwres.exch_total = ha->orig_fw_xcb_count;
+- ha->queue_pair_map[i]->fwres.exch_limit =
+- (ha->orig_fw_xcb_count * QLA_IOCB_PCT_LIMIT) / 100;
+ ha->queue_pair_map[i]->fwres.exch_used = 0;
+ }
+ }
+ }
+
++void qla_adjust_iocb_limit(scsi_qla_host_t *vha)
++{
++ u8 i;
++ struct qla_hw_data *ha = vha->hw;
++
++ __qla_adjust_iocb_limit(ha->base_qpair);
++
++ for (i = 0; i < ha->max_qpairs; i++) {
++ if (ha->queue_pair_map[i])
++ __qla_adjust_iocb_limit(ha->queue_pair_map[i]);
++ }
++}
++
+ /**
+ * qla2x00_setup_chip() - Load and start RISC firmware.
+ * @vha: HA context
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -2213,6 +2213,9 @@ qla2x00_get_firmware_state(scsi_qla_host
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054,
+ "Entered %s.\n", __func__);
+
++ if (!ha->flags.fw_started)
++ return QLA_FUNCTION_FAILED;
++
+ mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
+ mcp->out_mb = MBX_0;
+ if (IS_FWI2_CAPABLE(vha->hw))
+--- a/drivers/scsi/qla2xxx/qla_nvme.c
++++ b/drivers/scsi/qla2xxx/qla_nvme.c
+@@ -132,6 +132,7 @@ static int qla_nvme_alloc_queue(struct n
+ "Failed to allocate qpair\n");
+ return -EINVAL;
+ }
++ qla_adjust_iocb_limit(vha);
+ }
+ *handle = qpair;
+
--- /dev/null
+From da7c21b72aa86e990af5f73bce6590b8d8d148d0 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:30:58 +0530
+Subject: scsi: qla2xxx: Fix command flush during TMF
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit da7c21b72aa86e990af5f73bce6590b8d8d148d0 upstream.
+
+For each TMF request, driver iterates through each qpair and flushes
+commands associated to the TMF. At the end of the qpair flush, a Marker is
+used to complete the flush transaction. This process was repeated for each
+qpair. The multiple flush and marker for this TMF request seems to cause
+confusion for FW.
+
+Instead, 1 flush is sent to FW. Driver would wait for FW to go through all
+the I/Os on each qpair to be read then return. Driver then closes out the
+transaction with a Marker.
+
+Cc: stable@vger.kernel.org
+Fixes: d90171dd0da5 ("scsi: qla2xxx: Multi-que support for TMF")
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230714070104.40052-5-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 | 74 +++++++++++++++++++++-------------------
+ drivers/scsi/qla2xxx/qla_iocb.c | 1
+ drivers/scsi/qla2xxx/qla_os.c | 9 ++--
+ 3 files changed, 45 insertions(+), 39 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -2002,12 +2002,11 @@ qla2x00_tmf_iocb_timeout(void *data)
+ int rc, h;
+ unsigned long flags;
+
+- if (sp->type == SRB_MARKER) {
+- complete(&tmf->u.tmf.comp);
+- return;
+- }
++ if (sp->type == SRB_MARKER)
++ rc = QLA_FUNCTION_FAILED;
++ else
++ rc = qla24xx_async_abort_cmd(sp, false);
+
+- rc = qla24xx_async_abort_cmd(sp, false);
+ if (rc) {
+ spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags);
+ for (h = 1; h < sp->qpair->req->num_outstanding_cmds; h++) {
+@@ -2129,6 +2128,17 @@ static void qla2x00_tmf_sp_done(srb_t *s
+ complete(&tmf->u.tmf.comp);
+ }
+
++static int qla_tmf_wait(struct tmf_arg *arg)
++{
++ /* there are only 2 types of error handling that reaches here, lun or target reset */
++ if (arg->flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET | TCF_CLEAR_TASK_SET))
++ return qla2x00_eh_wait_for_pending_commands(arg->vha,
++ arg->fcport->d_id.b24, arg->lun, WAIT_LUN);
++ else
++ return qla2x00_eh_wait_for_pending_commands(arg->vha,
++ arg->fcport->d_id.b24, arg->lun, WAIT_TARGET);
++}
++
+ static int
+ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
+ {
+@@ -2136,8 +2146,9 @@ __qla2x00_async_tm_cmd(struct tmf_arg *a
+ struct srb_iocb *tm_iocb;
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
+-
+ fc_port_t *fcport = arg->fcport;
++ u32 chip_gen, login_gen;
++ u64 jif;
+
+ if (TMF_NOT_READY(arg->fcport)) {
+ ql_dbg(ql_dbg_taskm, vha, 0x8032,
+@@ -2182,8 +2193,27 @@ __qla2x00_async_tm_cmd(struct tmf_arg *a
+ "TM IOCB failed (%x).\n", rval);
+ }
+
+- if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw))
+- rval = qla26xx_marker(arg);
++ if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
++ chip_gen = vha->hw->chip_reset;
++ login_gen = fcport->login_gen;
++
++ jif = jiffies;
++ if (qla_tmf_wait(arg)) {
++ ql_log(ql_log_info, vha, 0x803e,
++ "Waited %u ms Nexus=%ld:%06x:%llu.\n",
++ jiffies_to_msecs(jiffies - jif), vha->host_no,
++ fcport->d_id.b24, arg->lun);
++ }
++
++ if (chip_gen == vha->hw->chip_reset && login_gen == fcport->login_gen) {
++ rval = qla26xx_marker(arg);
++ } else {
++ ql_log(ql_log_info, vha, 0x803e,
++ "Skip Marker due to disruption. Nexus=%ld:%06x:%llu.\n",
++ vha->host_no, fcport->d_id.b24, arg->lun);
++ rval = QLA_FUNCTION_FAILED;
++ }
++ }
+
+ done_free_sp:
+ /* ref: INIT */
+@@ -2261,9 +2291,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
+ uint32_t tag)
+ {
+ struct scsi_qla_host *vha = fcport->vha;
+- struct qla_qpair *qpair;
+ struct tmf_arg a;
+- int i, rval = QLA_SUCCESS;
++ int rval = QLA_SUCCESS;
+
+ if (TMF_NOT_READY(fcport))
+ return QLA_SUSPENDED;
+@@ -2283,34 +2312,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
+ if (qla_get_tmf(&a))
+ return QLA_FUNCTION_FAILED;
+
+- if (vha->hw->mqenable) {
+- for (i = 0; i < vha->hw->num_qpairs; i++) {
+- qpair = vha->hw->queue_pair_map[i];
+- if (!qpair)
+- continue;
+-
+- if (TMF_NOT_READY(fcport)) {
+- ql_log(ql_log_warn, vha, 0x8026,
+- "Unable to send TM due to disruption.\n");
+- rval = QLA_SUSPENDED;
+- break;
+- }
+-
+- a.qpair = qpair;
+- a.flags = flags|TCF_NOTMCMD_TO_TARGET;
+- rval = __qla2x00_async_tm_cmd(&a);
+- if (rval)
+- break;
+- }
+- }
+-
+- if (rval)
+- goto bailout;
+-
+ a.qpair = vha->hw->base_qpair;
+ rval = __qla2x00_async_tm_cmd(&a);
+
+-bailout:
+ qla_put_tmf(&a);
+ return rval;
+ }
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -3882,6 +3882,7 @@ qla_marker_iocb(srb_t *sp, struct mrk_en
+ {
+ mrk->entry_type = MARKER_TYPE;
+ mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier;
++ mrk->handle = make_handle(sp->qpair->req->id, sp->handle);
+ if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) {
+ mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id);
+ int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun);
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -1488,8 +1488,9 @@ qla2xxx_eh_device_reset(struct scsi_cmnd
+ goto eh_reset_failed;
+ }
+ err = 3;
+- if (qla2x00_eh_wait_for_pending_commands(vha, sdev->id,
+- sdev->lun, WAIT_LUN) != QLA_SUCCESS) {
++ if (qla2x00_eh_wait_for_pending_commands(vha, fcport->d_id.b24,
++ cmd->device->lun,
++ WAIT_LUN) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x800d,
+ "wait for pending cmds failed for cmd=%p.\n", cmd);
+ goto eh_reset_failed;
+@@ -1555,8 +1556,8 @@ qla2xxx_eh_target_reset(struct scsi_cmnd
+ goto eh_reset_failed;
+ }
+ err = 3;
+- if (qla2x00_eh_wait_for_pending_commands(vha, sdev->id,
+- 0, WAIT_TARGET) != QLA_SUCCESS) {
++ if (qla2x00_eh_wait_for_pending_commands(vha, fcport->d_id.b24, 0,
++ WAIT_TARGET) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x800d,
+ "wait for pending cmds failed for cmd=%p.\n", cmd);
+ goto eh_reset_failed;
--- /dev/null
+From 6dfe4344c168c6ca20fe7640649aacfcefcccb26 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:30:55 +0530
+Subject: scsi: qla2xxx: Fix deletion race condition
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 6dfe4344c168c6ca20fe7640649aacfcefcccb26 upstream.
+
+System crash when using debug kernel due to link list corruption. The cause
+of the link list corruption is due to session deletion was allowed to queue
+up twice. Here's the internal trace that show the same port was allowed to
+double queue for deletion on different cpu.
+
+20808683956 015 qla2xxx [0000:13:00.1]-e801:4: Scheduling sess ffff93ebf9306800 for deletion 50:06:0e:80:12:48:ff:50 fc4_type 1
+20808683957 027 qla2xxx [0000:13:00.1]-e801:4: Scheduling sess ffff93ebf9306800 for deletion 50:06:0e:80:12:48:ff:50 fc4_type 1
+
+Move the clearing/setting of deleted flag lock.
+
+Cc: stable@vger.kernel.org
+Fixes: 726b85487067 ("qla2xxx: Add framework for async fabric discovery")
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230714070104.40052-2-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 | 16 ++++++++++++++--
+ drivers/scsi/qla2xxx/qla_target.c | 14 +++++++-------
+ 2 files changed, 21 insertions(+), 9 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -508,6 +508,7 @@ static
+ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
+ {
+ struct fc_port *fcport = ea->fcport;
++ unsigned long flags;
+
+ ql_dbg(ql_dbg_disc, vha, 0x20d2,
+ "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
+@@ -522,9 +523,15 @@ void qla24xx_handle_adisc_event(scsi_qla
+ ql_dbg(ql_dbg_disc, vha, 0x2066,
+ "%s %8phC: adisc fail: post delete\n",
+ __func__, ea->fcport->port_name);
++
++ spin_lock_irqsave(&vha->work_lock, flags);
+ /* deleted = 0 & logout_on_delete = force fw cleanup */
+- fcport->deleted = 0;
++ if (fcport->deleted == QLA_SESS_DELETED)
++ fcport->deleted = 0;
++
+ fcport->logout_on_delete = 1;
++ spin_unlock_irqrestore(&vha->work_lock, flags);
++
+ qlt_schedule_sess_for_deletion(ea->fcport);
+ return;
+ }
+@@ -1446,7 +1453,6 @@ void __qla24xx_handle_gpdb_event(scsi_ql
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ ea->fcport->login_gen++;
+- ea->fcport->deleted = 0;
+ ea->fcport->logout_on_delete = 1;
+
+ if (!ea->fcport->login_succ && !IS_SW_RESV_ADDR(ea->fcport->d_id)) {
+@@ -6117,6 +6123,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t
+ void
+ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
+ {
++ unsigned long flags;
++
+ if (IS_SW_RESV_ADDR(fcport->d_id))
+ return;
+
+@@ -6126,7 +6134,11 @@ qla2x00_update_fcport(scsi_qla_host_t *v
+ qla2x00_set_fcport_disc_state(fcport, DSC_UPD_FCPORT);
+ fcport->login_retry = vha->hw->login_retry_count;
+ fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
++
++ spin_lock_irqsave(&vha->work_lock, flags);
+ fcport->deleted = 0;
++ spin_unlock_irqrestore(&vha->work_lock, flags);
++
+ if (vha->hw->current_topology == ISP_CFG_NL)
+ fcport->logout_on_delete = 0;
+ else
+--- a/drivers/scsi/qla2xxx/qla_target.c
++++ b/drivers/scsi/qla2xxx/qla_target.c
+@@ -1068,10 +1068,6 @@ void qlt_free_session_done(struct work_s
+ (struct imm_ntfy_from_isp *)sess->iocb, SRB_NACK_LOGO);
+ }
+
+- spin_lock_irqsave(&vha->work_lock, flags);
+- sess->flags &= ~FCF_ASYNC_SENT;
+- spin_unlock_irqrestore(&vha->work_lock, flags);
+-
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ if (sess->se_sess) {
+ sess->se_sess = NULL;
+@@ -1081,7 +1077,6 @@ void qlt_free_session_done(struct work_s
+
+ qla2x00_set_fcport_disc_state(sess, DSC_DELETED);
+ sess->fw_login_state = DSC_LS_PORT_UNAVAIL;
+- sess->deleted = QLA_SESS_DELETED;
+
+ if (sess->login_succ && !IS_SW_RESV_ADDR(sess->d_id)) {
+ vha->fcport_count--;
+@@ -1133,10 +1128,15 @@ void qlt_free_session_done(struct work_s
+
+ sess->explicit_logout = 0;
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+- sess->free_pending = 0;
+
+ qla2x00_dfs_remove_rport(vha, sess);
+
++ spin_lock_irqsave(&vha->work_lock, flags);
++ sess->flags &= ~FCF_ASYNC_SENT;
++ sess->deleted = QLA_SESS_DELETED;
++ sess->free_pending = 0;
++ spin_unlock_irqrestore(&vha->work_lock, flags);
++
+ ql_dbg(ql_dbg_disc, vha, 0xf001,
+ "Unregistration of sess %p %8phC finished fcp_cnt %d\n",
+ sess, sess->port_name, vha->fcport_count);
+@@ -1185,12 +1185,12 @@ void qlt_unreg_sess(struct fc_port *sess
+ * management from being sent.
+ */
+ sess->flags |= FCF_ASYNC_SENT;
++ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+ spin_unlock_irqrestore(&sess->vha->work_lock, flags);
+
+ if (sess->se_sess)
+ vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
+
+- sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+ qla2x00_set_fcport_disc_state(sess, DSC_DELETE_PEND);
+ sess->last_rscn_gen = sess->rscn_gen;
+ sess->last_login_gen = sess->login_gen;
--- /dev/null
+From 5b51f35d127e7bef55fa869d2465e2bca4636454 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:30:59 +0530
+Subject: scsi: qla2xxx: Fix erroneous link up failure
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 5b51f35d127e7bef55fa869d2465e2bca4636454 upstream.
+
+Link up failure occurred where driver failed to see certain events from FW
+indicating link up (AEN 8011) and fabric login completion (AEN 8014).
+Without these 2 events, driver would not proceed forward to scan the
+fabric. The cause of this is due to delay in the receive of interrupt for
+Mailbox 60 that causes qla to set the fw_started flag late. The late
+setting of this flag causes other interrupts to be dropped. These dropped
+interrupts happen to be the link up (AEN 8011) and fabric login completion
+(AEN 8014).
+
+Set fw_started flag early to prevent interrupts being dropped.
+
+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/20230714070104.40052-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 | 3 ++-
+ drivers/scsi/qla2xxx/qla_isr.c | 6 +++++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -4815,15 +4815,16 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
+ if (ha->flags.edif_enabled)
+ mid_init_cb->init_cb.frame_payload_size = cpu_to_le16(ELS_MAX_PAYLOAD);
+
++ QLA_FW_STARTED(ha);
+ rval = qla2x00_init_firmware(vha, ha->init_cb_size);
+ next_check:
+ if (rval) {
++ QLA_FW_STOPPED(ha);
+ ql_log(ql_log_fatal, vha, 0x00d2,
+ "Init Firmware **** FAILED ****.\n");
+ } else {
+ ql_dbg(ql_dbg_init, vha, 0x00d3,
+ "Init Firmware -- success.\n");
+- QLA_FW_STARTED(ha);
+ vha->u_ql2xexchoffld = vha->u_ql2xiniexchg = 0;
+ }
+
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -1121,8 +1121,12 @@ qla2x00_async_event(scsi_qla_host_t *vha
+ unsigned long flags;
+ fc_port_t *fcport = NULL;
+
+- if (!vha->hw->flags.fw_started)
++ if (!vha->hw->flags.fw_started) {
++ ql_log(ql_log_warn, vha, 0x50ff,
++ "Dropping AEN - %04x %04x %04x %04x.\n",
++ mb[0], mb[1], mb[2], mb[3]);
+ return;
++ }
+
+ /* Setup to process RIO completion. */
+ handle_cnt = 0;
--- /dev/null
+From 009e7fe4a1ed52276b332842a6b6e23b07200f2d Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:31:03 +0530
+Subject: scsi: qla2xxx: fix inconsistent TMF timeout
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 009e7fe4a1ed52276b332842a6b6e23b07200f2d upstream.
+
+Different behavior were experienced of session being torn down vs not when
+TMF is timed out. When FW detects the time out, the session is torn down.
+When driver detects the time out, the session is not torn down.
+
+Allow TMF error to return to upper layer without session tear down.
+
+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/20230714070104.40052-10-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_isr.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -2539,7 +2539,6 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *v
+ case CS_PORT_BUSY:
+ case CS_INCOMPLETE:
+ case CS_PORT_UNAVAILABLE:
+- case CS_TIMEOUT:
+ case CS_RESET:
+ if (atomic_read(&fcport->state) == FCS_ONLINE) {
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
--- /dev/null
+From 39d22740712c7563a2e18c08f033deeacdaf66e7 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:31:00 +0530
+Subject: scsi: qla2xxx: Fix session hang in gnl
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 39d22740712c7563a2e18c08f033deeacdaf66e7 upstream.
+
+Connection does not resume after a host reset / chip reset. The cause of
+the blockage is due to the FCF_ASYNC_ACTIVE left on. The gnl command was
+interrupted by the chip reset. On exiting the command, this flag should be
+turn off to allow relogin to reoccur. Clear this flag to prevent blockage.
+
+Cc: stable@vger.kernel.org
+Fixes: 17e64648aa47 ("scsi: qla2xxx: Correct fcport flags handling")
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230714070104.40052-7-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 | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1141,7 +1141,7 @@ int qla24xx_async_gnl(struct scsi_qla_ho
+ u16 *mb;
+
+ if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+- return rval;
++ goto done;
+
+ ql_dbg(ql_dbg_disc, vha, 0x20d9,
+ "Async-gnlist WWPN %8phC \n", fcport->port_name);
+@@ -1195,8 +1195,9 @@ int qla24xx_async_gnl(struct scsi_qla_ho
+ done_free_sp:
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
++ fcport->flags &= ~(FCF_ASYNC_SENT);
+ done:
+- fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
++ fcport->flags &= ~(FCF_ASYNC_ACTIVE);
+ return rval;
+ }
+
--- /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
+@@ -4203,7 +4203,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;
+
--- /dev/null
+From 5d3148d8e8b05f084e607ac3bd55a4c317a9f934 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:31:02 +0530
+Subject: scsi: qla2xxx: Fix TMF leak through
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 5d3148d8e8b05f084e607ac3bd55a4c317a9f934 upstream.
+
+Task management can retry up to 5 times when FW resource becomes bottle
+neck. Between the retries, there is a short sleep. Current code assumes
+the chip has not reset or session has not changed.
+
+Check for chip reset or session change before sending Task management.
+
+Cc: stable@vger.kernel.org
+Fixes: 9803fb5d2759 ("scsi: qla2xxx: Fix task management cmd failure")
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230714070104.40052-9-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 | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -2038,10 +2038,14 @@ static void qla_marker_sp_done(srb_t *sp
+ complete(&tmf->u.tmf.comp);
+ }
+
+-#define START_SP_W_RETRIES(_sp, _rval) \
++#define START_SP_W_RETRIES(_sp, _rval, _chip_gen, _login_gen) \
+ {\
+ int cnt = 5; \
+ do { \
++ if (_chip_gen != sp->vha->hw->chip_reset || _login_gen != sp->fcport->login_gen) {\
++ _rval = EINVAL; \
++ break; \
++ } \
+ _rval = qla2x00_start_sp(_sp); \
+ if (_rval == EAGAIN) \
+ msleep(1); \
+@@ -2064,6 +2068,7 @@ qla26xx_marker(struct tmf_arg *arg)
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
+ fc_port_t *fcport = arg->fcport;
++ u32 chip_gen, login_gen;
+
+ if (TMF_NOT_READY(arg->fcport)) {
+ ql_dbg(ql_dbg_taskm, vha, 0x8039,
+@@ -2073,6 +2078,9 @@ qla26xx_marker(struct tmf_arg *arg)
+ return QLA_SUSPENDED;
+ }
+
++ chip_gen = vha->hw->chip_reset;
++ login_gen = fcport->login_gen;
++
+ /* ref: INIT */
+ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
+ if (!sp)
+@@ -2090,7 +2098,7 @@ qla26xx_marker(struct tmf_arg *arg)
+ tm_iocb->u.tmf.loop_id = fcport->loop_id;
+ tm_iocb->u.tmf.vp_index = vha->vp_idx;
+
+- START_SP_W_RETRIES(sp, rval);
++ START_SP_W_RETRIES(sp, rval, chip_gen, login_gen);
+
+ ql_dbg(ql_dbg_taskm, vha, 0x8006,
+ "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
+@@ -2159,6 +2167,9 @@ __qla2x00_async_tm_cmd(struct tmf_arg *a
+ return QLA_SUSPENDED;
+ }
+
++ chip_gen = vha->hw->chip_reset;
++ login_gen = fcport->login_gen;
++
+ /* ref: INIT */
+ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
+ if (!sp)
+@@ -2176,7 +2187,7 @@ __qla2x00_async_tm_cmd(struct tmf_arg *a
+ tm_iocb->u.tmf.flags = arg->flags;
+ tm_iocb->u.tmf.lun = arg->lun;
+
+- START_SP_W_RETRIES(sp, rval);
++ START_SP_W_RETRIES(sp, rval, chip_gen, login_gen);
+
+ ql_dbg(ql_dbg_taskm, vha, 0x802f,
+ "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n",
+@@ -2195,9 +2206,6 @@ __qla2x00_async_tm_cmd(struct tmf_arg *a
+ }
+
+ if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
+- chip_gen = vha->hw->chip_reset;
+- login_gen = fcport->login_gen;
+-
+ jif = jiffies;
+ if (qla_tmf_wait(arg)) {
+ ql_log(ql_log_info, vha, 0x803e,
--- /dev/null
+From 6d0b65569c0a10b27c49bacd8d25bcd406003533 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Mon, 21 Aug 2023 18:30:38 +0530
+Subject: scsi: qla2xxx: Flush mailbox commands on chip reset
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 6d0b65569c0a10b27c49bacd8d25bcd406003533 upstream.
+
+Fix race condition between Interrupt thread and Chip reset thread in trying
+to flush the same mailbox. With the race condition, the "ha->mbx_intr_comp"
+will get an extra complete() call. The extra complete call create erroneous
+mailbox timeout condition when the next mailbox is sent where the mailbox
+call does not wait for interrupt to arrive. Instead, it advances without
+waiting.
+
+Add lock protection around the check for mailbox completion.
+
+Cc: stable@vger.kernel.org
+Fixes: b2000805a975 ("scsi: qla2xxx: Flush mailbox commands on chip reset")
+Signed-off-by: Quinn Tran <quinn.tran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230821130045.34850-3-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 | 1 -
+ drivers/scsi/qla2xxx/qla_init.c | 7 ++++---
+ drivers/scsi/qla2xxx/qla_mbx.c | 4 ----
+ drivers/scsi/qla2xxx/qla_os.c | 1 -
+ 4 files changed, 4 insertions(+), 9 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -4384,7 +4384,6 @@ struct qla_hw_data {
+ uint8_t aen_mbx_count;
+ atomic_t num_pend_mbx_stage1;
+ atomic_t num_pend_mbx_stage2;
+- atomic_t num_pend_mbx_stage3;
+ uint16_t frame_payload_size;
+
+ uint32_t login_retry_count;
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -7390,14 +7390,15 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_
+ }
+
+ /* purge MBox commands */
+- if (atomic_read(&ha->num_pend_mbx_stage3)) {
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) {
+ clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
+ complete(&ha->mbx_intr_comp);
+ }
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ i = 0;
+- while (atomic_read(&ha->num_pend_mbx_stage3) ||
+- atomic_read(&ha->num_pend_mbx_stage2) ||
++ while (atomic_read(&ha->num_pend_mbx_stage2) ||
+ atomic_read(&ha->num_pend_mbx_stage1)) {
+ msleep(20);
+ i++;
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -273,7 +273,6 @@ qla2x00_mailbox_command(scsi_qla_host_t
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ wait_time = jiffies;
+- atomic_inc(&ha->num_pend_mbx_stage3);
+ if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
+ mcp->tov * HZ)) {
+ ql_dbg(ql_dbg_mbx, vha, 0x117a,
+@@ -290,7 +289,6 @@ qla2x00_mailbox_command(scsi_qla_host_t
+ spin_unlock_irqrestore(&ha->hardware_lock,
+ flags);
+ atomic_dec(&ha->num_pend_mbx_stage2);
+- atomic_dec(&ha->num_pend_mbx_stage3);
+ rval = QLA_ABORTED;
+ goto premature_exit;
+ }
+@@ -302,11 +300,9 @@ qla2x00_mailbox_command(scsi_qla_host_t
+ ha->flags.mbox_busy = 0;
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ atomic_dec(&ha->num_pend_mbx_stage2);
+- atomic_dec(&ha->num_pend_mbx_stage3);
+ rval = QLA_ABORTED;
+ goto premature_exit;
+ }
+- atomic_dec(&ha->num_pend_mbx_stage3);
+
+ if (time_after(jiffies, wait_time + 5 * HZ))
+ ql_log(ql_log_warn, vha, 0x1015, "cmd=0x%x, waited %d msecs\n",
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -3007,7 +3007,6 @@ qla2x00_probe_one(struct pci_dev *pdev,
+ ha->max_exchg = FW_MAX_EXCHANGES_CNT;
+ atomic_set(&ha->num_pend_mbx_stage1, 0);
+ atomic_set(&ha->num_pend_mbx_stage2, 0);
+- atomic_set(&ha->num_pend_mbx_stage3, 0);
+ atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD);
+ ha->last_zio_threshold = DEFAULT_ZIO_THRESHOLD;
+ INIT_LIST_HEAD(&ha->tmf_pending);
--- /dev/null
+From a8ec192427e0516436e61f9ca9eb49c54eadfe0a Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:30:57 +0530
+Subject: scsi: qla2xxx: Limit TMF to 8 per function
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit a8ec192427e0516436e61f9ca9eb49c54eadfe0a upstream.
+
+Per FW recommendation, 8 TMF's can be outstanding for each
+function. Previously, it allowed 8 per target.
+
+Limit TMF to 8 per function.
+
+Cc: stable@vger.kernel.org
+Fixes: 6a87679626b5 ("scsi: qla2xxx: Fix task management cmd fail due to unavailable resource")
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230714070104.40052-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 | 9 +++---
+ drivers/scsi/qla2xxx/qla_init.c | 55 ++++++++++++++++++++++++----------------
+ drivers/scsi/qla2xxx/qla_os.c | 2 +
+ 3 files changed, 41 insertions(+), 25 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -466,6 +466,7 @@ static inline be_id_t port_id_to_be_id(p
+ }
+
+ struct tmf_arg {
++ struct list_head tmf_elem;
+ struct qla_qpair *qpair;
+ struct fc_port *fcport;
+ struct scsi_qla_host *vha;
+@@ -2541,7 +2542,6 @@ 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;
+@@ -2562,9 +2562,6 @@ 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];
+ port_id_t d_id;
+@@ -4656,6 +4653,8 @@ struct qla_hw_data {
+ uint32_t flt_region_aux_img_status_sec;
+ };
+ uint8_t active_image;
++ uint8_t active_tmf;
++#define MAX_ACTIVE_TMF 8
+
+ /* Needed for BEACON */
+ uint16_t beacon_blink_led;
+@@ -4670,6 +4669,8 @@ struct qla_hw_data {
+
+ struct qla_msix_entry *msix_entries;
+
++ struct list_head tmf_pending;
++ struct list_head tmf_active;
+ struct list_head vp_list; /* list of VP */
+ unsigned long vp_idx_map[(MAX_MULTI_ID_FABRIC / 8) /
+ sizeof(unsigned long)];
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -2186,30 +2186,42 @@ done:
+ return rval;
+ }
+
+-static void qla_put_tmf(fc_port_t *fcport)
++static void qla_put_tmf(struct tmf_arg *arg)
+ {
+- struct scsi_qla_host *vha = fcport->vha;
++ struct scsi_qla_host *vha = arg->vha;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+- fcport->active_tmf--;
++ ha->active_tmf--;
++ list_del(&arg->tmf_elem);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ }
+
+ static
+-int qla_get_tmf(fc_port_t *fcport)
++int qla_get_tmf(struct tmf_arg *arg)
+ {
+- struct scsi_qla_host *vha = fcport->vha;
++ struct scsi_qla_host *vha = arg->vha;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
++ fc_port_t *fcport = arg->fcport;
+ int rc = 0;
+- LIST_HEAD(tmf_elem);
++ struct tmf_arg *t;
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+- list_add_tail(&tmf_elem, &fcport->tmf_pending);
++ list_for_each_entry(t, &ha->tmf_active, tmf_elem) {
++ if (t->fcport == arg->fcport && t->lun == arg->lun) {
++ /* reject duplicate TMF */
++ ql_log(ql_log_warn, vha, 0x802c,
++ "found duplicate TMF. Nexus=%ld:%06x:%llu.\n",
++ vha->host_no, fcport->d_id.b24, arg->lun);
++ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
++ return -EINVAL;
++ }
++ }
+
+- while (fcport->active_tmf >= MAX_ACTIVE_TMF) {
++ list_add_tail(&arg->tmf_elem, &ha->tmf_pending);
++ while (ha->active_tmf >= MAX_ACTIVE_TMF) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+ msleep(1);
+@@ -2221,15 +2233,17 @@ int qla_get_tmf(fc_port_t *fcport)
+ rc = EIO;
+ break;
+ }
+- if (fcport->active_tmf < MAX_ACTIVE_TMF &&
+- list_is_first(&tmf_elem, &fcport->tmf_pending))
++ if (ha->active_tmf < MAX_ACTIVE_TMF &&
++ list_is_first(&arg->tmf_elem, &ha->tmf_pending))
+ break;
+ }
+
+- list_del(&tmf_elem);
++ list_del(&arg->tmf_elem);
+
+- if (!rc)
+- fcport->active_tmf++;
++ if (!rc) {
++ ha->active_tmf++;
++ list_add_tail(&arg->tmf_elem, &ha->tmf_active);
++ }
+
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+@@ -2251,15 +2265,18 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
+ a.vha = fcport->vha;
+ a.fcport = fcport;
+ a.lun = lun;
++ a.flags = flags;
++ INIT_LIST_HEAD(&a.tmf_elem);
++
+ if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
+ a.modifier = MK_SYNC_ID_LUN;
+-
+- if (qla_get_tmf(fcport))
+- return QLA_FUNCTION_FAILED;
+ } else {
+ a.modifier = MK_SYNC_ID;
+ }
+
++ if (qla_get_tmf(&a))
++ return QLA_FUNCTION_FAILED;
++
+ if (vha->hw->mqenable) {
+ for (i = 0; i < vha->hw->num_qpairs; i++) {
+ qpair = vha->hw->queue_pair_map[i];
+@@ -2285,13 +2302,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,
+ goto bailout;
+
+ a.qpair = vha->hw->base_qpair;
+- a.flags = flags;
+ rval = __qla2x00_async_tm_cmd(&a);
+
+ bailout:
+- if (a.modifier == MK_SYNC_ID_LUN)
+- qla_put_tmf(fcport);
+-
++ qla_put_tmf(&a);
+ return rval;
+ }
+
+@@ -5520,7 +5534,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vh
+ 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);
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -3009,6 +3009,8 @@ qla2x00_probe_one(struct pci_dev *pdev,
+ atomic_set(&ha->num_pend_mbx_stage3, 0);
+ atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD);
+ ha->last_zio_threshold = DEFAULT_ZIO_THRESHOLD;
++ INIT_LIST_HEAD(&ha->tmf_pending);
++ INIT_LIST_HEAD(&ha->tmf_active);
+
+ /* Assign ISP specific operations. */
+ if (IS_QLA2100(ha)) {
--- /dev/null
+From e9105c4b7a9208a21a9bda133707624f12ddabc2 Mon Sep 17 00:00:00 2001
+From: Manish Rangankar <mrangankar@marvell.com>
+Date: Mon, 21 Aug 2023 18:30:42 +0530
+Subject: scsi: qla2xxx: Remove unsupported ql2xenabledif option
+
+From: Manish Rangankar <mrangankar@marvell.com>
+
+commit e9105c4b7a9208a21a9bda133707624f12ddabc2 upstream.
+
+User accidently passed module parameter ql2xenabledif=1 which is
+unsupported. However, driver still initialized which lead to guard tag
+errors during device discovery.
+
+Remove unsupported ql2xenabledif=1 option and validate the user input.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Manish Rangankar <mrangankar@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230821130045.34850-7-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_attr.c | 2 --
+ drivers/scsi/qla2xxx/qla_dbg.c | 2 +-
+ drivers/scsi/qla2xxx/qla_os.c | 9 +++++++--
+ 3 files changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -3093,8 +3093,6 @@ qla24xx_vport_create(struct fc_vport *fc
+ vha->flags.difdix_supported = 1;
+ ql_dbg(ql_dbg_user, vha, 0x7082,
+ "Registered for DIF/DIX type 1 and 3 protection.\n");
+- if (ql2xenabledif == 1)
+- prot = SHOST_DIX_TYPE0_PROTECTION;
+ scsi_host_set_prot(vha->host,
+ prot | SHOST_DIF_TYPE1_PROTECTION
+ | SHOST_DIF_TYPE2_PROTECTION
+--- a/drivers/scsi/qla2xxx/qla_dbg.c
++++ b/drivers/scsi/qla2xxx/qla_dbg.c
+@@ -18,7 +18,7 @@
+ * | Queue Command and IO tracing | 0x3074 | 0x300b |
+ * | | | 0x3027-0x3028 |
+ * | | | 0x303d-0x3041 |
+- * | | | 0x302d,0x3033 |
++ * | | | 0x302e,0x3033 |
+ * | | | 0x3036,0x3038 |
+ * | | | 0x303a |
+ * | DPC Thread | 0x4023 | 0x4002,0x4013 |
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -3288,6 +3288,13 @@ qla2x00_probe_one(struct pci_dev *pdev,
+ host->max_id = ha->max_fibre_devices;
+ host->cmd_per_lun = 3;
+ host->unique_id = host->host_no;
++
++ if (ql2xenabledif && ql2xenabledif != 2) {
++ ql_log(ql_log_warn, base_vha, 0x302d,
++ "Invalid value for ql2xenabledif, resetting it to default (2)\n");
++ ql2xenabledif = 2;
++ }
++
+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif)
+ host->max_cmd_len = 32;
+ else
+@@ -3524,8 +3531,6 @@ skip_dpc:
+ base_vha->flags.difdix_supported = 1;
+ ql_dbg(ql_dbg_init, base_vha, 0x00f1,
+ "Registering for DIF/DIX type 1 and 3 protection.\n");
+- if (ql2xenabledif == 1)
+- prot = SHOST_DIX_TYPE0_PROTECTION;
+ if (ql2xprotmask)
+ scsi_host_set_prot(host, ql2xprotmask);
+ else
--- /dev/null
+From 8ebaa45163a3fedc885c1dc7d43ea987a2f00a06 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Fri, 14 Jul 2023 12:31:01 +0530
+Subject: scsi: qla2xxx: Turn off noisy message log
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 8ebaa45163a3fedc885c1dc7d43ea987a2f00a06 upstream.
+
+Some consider noisy log as test failure. Turn off noisy message log.
+
+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/20230714070104.40052-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_nvme.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/scsi/qla2xxx/qla_nvme.c
++++ b/drivers/scsi/qla2xxx/qla_nvme.c
+@@ -668,7 +668,7 @@ static int qla_nvme_post_cmd(struct nvme
+
+ rval = qla2x00_start_nvme_mq(sp);
+ if (rval != QLA_SUCCESS) {
+- ql_log(ql_log_warn, vha, 0x212d,
++ ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x212d,
+ "qla2x00_start_nvme_mq failed = %d\n", rval);
+ sp->priv = NULL;
+ priv->sp = NULL;
--- /dev/null
+From c91e585cfb3dd7d076e9ba0967908fc504d32def Mon Sep 17 00:00:00 2001
+From: Bean Huo <beanhuo@micron.com>
+Date: Wed, 9 Aug 2023 20:18:46 +0200
+Subject: scsi: ufs: core: Add advanced RPMB support where UFSHCI 4.0 does not support EHS length in UTRD
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bean Huo <beanhuo@micron.com>
+
+commit c91e585cfb3dd7d076e9ba0967908fc504d32def upstream.
+
+According to UFSHCI 4.0 specification:
+
+5.2 Host Controller Capabilities Registers
+5.2.1 Offset 00h: CAP – Controller Capabilities:
+
+ "EHS Length in UTRD Supported (EHSLUTRDS): Indicates whether the host
+ controller supports EHS Length field in UTRD.
+
+ 0 – Host controller takes EHS length from CMD UPIU, and SW driver use EHS
+ Length field in CMD UPIU.
+
+ 1 – HW controller takes EHS length from UTRD, and SW driver use EHS
+ Length field in UTRD.
+
+ NOTE Recommend Host controllers move to taking EHS length from UTRD, and
+ in UFS-5, it will be mandatory."
+
+So, when UFSHCI 4.0 doesn't support EHS Length field in UTRD, we could use
+EHS Length field in CMD UPIU. Remove the limitation that advanced RPMB only
+works when EHS length is supported in UTRD.
+
+Fixes: 6ff265fc5ef6 ("scsi: ufs: core: bsg: Add advanced RPMB support in ufs_bsg")
+Co-developed-by: "jonghwi.rha" <jonghwi.rha@samsung.com>
+Signed-off-by: "jonghwi.rha" <jonghwi.rha@samsung.com>
+Signed-off-by: Bean Huo <beanhuo@micron.com>
+Link: https://lore.kernel.org/r/20230809181847.102123-2-beanhuo@iokpp.de
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ufs/core/ufs_bsg.c | 3 +--
+ drivers/ufs/core/ufshcd.c | 10 +++++++++-
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+--- a/drivers/ufs/core/ufs_bsg.c
++++ b/drivers/ufs/core/ufs_bsg.c
+@@ -76,8 +76,7 @@ static int ufs_bsg_exec_advanced_rpmb_re
+ int ret;
+ int data_len;
+
+- if (hba->ufs_version < ufshci_version(4, 0) || !hba->dev_info.b_advanced_rpmb_en ||
+- !(hba->capabilities & MASK_EHSLUTRD_SUPPORTED))
++ if (hba->ufs_version < ufshci_version(4, 0) || !hba->dev_info.b_advanced_rpmb_en)
+ return -EINVAL;
+
+ if (rpmb_request->ehs_req.length != 2 || rpmb_request->ehs_req.ehs_type != 1)
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -7296,7 +7296,15 @@ int ufshcd_advanced_rpmb_req_handler(str
+ /* Advanced RPMB starts from UFS 4.0, so its command type is UTP_CMD_TYPE_UFS_STORAGE */
+ lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
+
+- ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, dir, 2);
++ /*
++ * According to UFSHCI 4.0 specification page 24, if EHSLUTRDS is 0, host controller takes
++ * EHS length from CMD UPIU, and SW driver use EHS Length field in CMD UPIU. if it is 1,
++ * HW controller takes EHS length from UTRD.
++ */
++ if (hba->capabilities & MASK_EHSLUTRD_SUPPORTED)
++ ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, dir, 2);
++ else
++ ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, dir, 0);
+
+ /* update the task tag and LUN in the request upiu */
+ req_upiu->header.dword_0 |= cpu_to_be32(upiu_flags << 16 | UFS_UPIU_RPMB_WLUN << 8 | tag);
net-ipv6-skb-symmetric-hash-should-incorporate-transport-ports.patch
drm-virtio-conditionally-allocate-virtio_gpu_fence.patch
+scsi-ufs-core-add-advanced-rpmb-support-where-ufshci-4.0-does-not-support-ehs-length-in-utrd.patch
+scsi-qla2xxx-adjust-iocb-resource-on-qpair-create.patch
+scsi-qla2xxx-limit-tmf-to-8-per-function.patch
+scsi-qla2xxx-fix-deletion-race-condition.patch
+scsi-qla2xxx-fix-inconsistent-tmf-timeout.patch
+scsi-qla2xxx-fix-command-flush-during-tmf.patch
+scsi-qla2xxx-fix-erroneous-link-up-failure.patch
+scsi-qla2xxx-turn-off-noisy-message-log.patch
+scsi-qla2xxx-fix-session-hang-in-gnl.patch
+scsi-qla2xxx-fix-tmf-leak-through.patch
+scsi-qla2xxx-remove-unsupported-ql2xenabledif-option.patch
+scsi-qla2xxx-flush-mailbox-commands-on-chip-reset.patch
+scsi-qla2xxx-fix-smatch-warn-for-qla_init_iocb_limit.patch