]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2024 10:34:05 +0000 (12:34 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2024 10:34:05 +0000 (12:34 +0200)
added patches:
scsi-qla2xxx-change-debug-message-during-driver-unload.patch
scsi-qla2xxx-delay-i-o-abort-on-pci-error.patch
scsi-qla2xxx-fix-command-flush-on-cable-pull.patch
scsi-qla2xxx-fix-double-free-of-fcport.patch
scsi-qla2xxx-fix-double-free-of-the-ha-vp_map-pointer.patch
scsi-qla2xxx-fix-n2n-stuck-connection.patch
scsi-qla2xxx-nvme-fcp-prefer-flag-not-being-honored.patch
scsi-qla2xxx-prevent-command-send-on-chip-reset.patch
scsi-qla2xxx-split-fce-eft-trace-control.patch
scsi-qla2xxx-update-manufacturer-detail.patch
usb-core-add-hub_get-and-hub_put-routines.patch
usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch
usb-core-fix-deadlock-in-usb_deauthorize_interface.patch
usb-dwc2-gadget-fix-exiting-from-clock-gating.patch
usb-dwc2-gadget-lpm-flow-fix.patch
usb-dwc2-host-fix-hibernation-flow.patch
usb-dwc2-host-fix-isoc-flow-in-ddma-mode.patch
usb-dwc2-host-fix-remote-wakeup-from-hibernation.patch
usb-dwc3-properly-set-system-wakeup.patch
usb-typec-return-size-of-buffer-if-pd_set-operation-succeeds.patch
usb-typec-ucsi-ack-unsupported-commands.patch
usb-typec-ucsi-check-for-notifications-after-init.patch
usb-typec-ucsi-clear-event_pending-under-ppm-lock.patch
usb-typec-ucsi-clear-ucsi_cci_reset_complete-before-reset.patch
usb-typec-ucsi_acpi-refactor-and-fix-dell-quirk.patch
usb-udc-remove-warning-when-queue-disabled-ep.patch

27 files changed:
queue-6.6/scsi-qla2xxx-change-debug-message-during-driver-unload.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-delay-i-o-abort-on-pci-error.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-fix-command-flush-on-cable-pull.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-fix-double-free-of-fcport.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-fix-double-free-of-the-ha-vp_map-pointer.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-fix-n2n-stuck-connection.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-nvme-fcp-prefer-flag-not-being-honored.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-prevent-command-send-on-chip-reset.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-split-fce-eft-trace-control.patch [new file with mode: 0644]
queue-6.6/scsi-qla2xxx-update-manufacturer-detail.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/usb-core-add-hub_get-and-hub_put-routines.patch [new file with mode: 0644]
queue-6.6/usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch [new file with mode: 0644]
queue-6.6/usb-core-fix-deadlock-in-usb_deauthorize_interface.patch [new file with mode: 0644]
queue-6.6/usb-dwc2-gadget-fix-exiting-from-clock-gating.patch [new file with mode: 0644]
queue-6.6/usb-dwc2-gadget-lpm-flow-fix.patch [new file with mode: 0644]
queue-6.6/usb-dwc2-host-fix-hibernation-flow.patch [new file with mode: 0644]
queue-6.6/usb-dwc2-host-fix-isoc-flow-in-ddma-mode.patch [new file with mode: 0644]
queue-6.6/usb-dwc2-host-fix-remote-wakeup-from-hibernation.patch [new file with mode: 0644]
queue-6.6/usb-dwc3-properly-set-system-wakeup.patch [new file with mode: 0644]
queue-6.6/usb-typec-return-size-of-buffer-if-pd_set-operation-succeeds.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-ack-unsupported-commands.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-check-for-notifications-after-init.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-clear-event_pending-under-ppm-lock.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-clear-ucsi_cci_reset_complete-before-reset.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi_acpi-refactor-and-fix-dell-quirk.patch [new file with mode: 0644]
queue-6.6/usb-udc-remove-warning-when-queue-disabled-ep.patch [new file with mode: 0644]

diff --git a/queue-6.6/scsi-qla2xxx-change-debug-message-during-driver-unload.patch b/queue-6.6/scsi-qla2xxx-change-debug-message-during-driver-unload.patch
new file mode 100644 (file)
index 0000000..0ba0da8
--- /dev/null
@@ -0,0 +1,36 @@
+From b5a30840727a3e41d12a336d19f6c0716b299161 Mon Sep 17 00:00:00 2001
+From: Saurav Kashyap <skashyap@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:25 +0530
+Subject: scsi: qla2xxx: Change debug message during driver unload
+
+From: Saurav Kashyap <skashyap@marvell.com>
+
+commit b5a30840727a3e41d12a336d19f6c0716b299161 upstream.
+
+Upon driver unload, purge_mbox flag is set and the heartbeat monitor thread
+detects this flag and does not send the mailbox command down to FW with a
+debug message "Error detected: purge[1] eeh[0] cmd=0x0, Exiting".  This
+being not a real error, change the debug message.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20240227164127.36465-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_mbx.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -194,7 +194,7 @@ qla2x00_mailbox_command(scsi_qla_host_t
+       if (ha->flags.purge_mbox || chip_reset != ha->chip_reset ||
+           ha->flags.eeh_busy) {
+               ql_log(ql_log_warn, vha, 0xd035,
+-                     "Error detected: purge[%d] eeh[%d] cmd=0x%x, Exiting.\n",
++                     "Purge mbox: purge[%d] eeh[%d] cmd=0x%x, Exiting.\n",
+                      ha->flags.purge_mbox, ha->flags.eeh_busy, mcp->mb[0]);
+               rval = QLA_ABORTED;
+               goto premature_exit;
diff --git a/queue-6.6/scsi-qla2xxx-delay-i-o-abort-on-pci-error.patch b/queue-6.6/scsi-qla2xxx-delay-i-o-abort-on-pci-error.patch
new file mode 100644 (file)
index 0000000..2eef9de
--- /dev/null
@@ -0,0 +1,57 @@
+From 591c1fdf2016d118b8fbde427b796fac13f3f070 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:26 +0530
+Subject: scsi: qla2xxx: Delay I/O Abort on PCI error
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 591c1fdf2016d118b8fbde427b796fac13f3f070 upstream.
+
+Currently when PCI error is detected, I/O is aborted manually through the
+ABORT IOCB mechanism which is not guaranteed to succeed.
+
+Instead, wait for the OS or system to notify driver to wind down I/O
+through the pci_error_handlers api.  Set eeh_busy flag to pause all traffic
+and wait for I/O to drain.
+
+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/20240227164127.36465-11-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 |   14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -2741,7 +2741,13 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rp
+               return;
+       if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
+-              qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
++              /* Will wait for wind down of adapter */
++              ql_dbg(ql_dbg_aer, fcport->vha, 0x900c,
++                  "%s pci offline detected (id %06x)\n", __func__,
++                  fcport->d_id.b24);
++              qla_pci_set_eeh_busy(fcport->vha);
++              qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
++                  0, WAIT_TARGET);
+               return;
+       }
+ }
+@@ -2763,7 +2769,11 @@ qla2x00_terminate_rport_io(struct fc_rpo
+       vha = fcport->vha;
+       if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
+-              qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
++              /* Will wait for wind down of adapter */
++              ql_dbg(ql_dbg_aer, fcport->vha, 0x900b,
++                  "%s pci offline detected (id %06x)\n", __func__,
++                  fcport->d_id.b24);
++              qla_pci_set_eeh_busy(vha);
+               qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
+                       0, WAIT_TARGET);
+               return;
diff --git a/queue-6.6/scsi-qla2xxx-fix-command-flush-on-cable-pull.patch b/queue-6.6/scsi-qla2xxx-fix-command-flush-on-cable-pull.patch
new file mode 100644 (file)
index 0000000..40686b3
--- /dev/null
@@ -0,0 +1,94 @@
+From a27d4d0e7de305def8a5098a614053be208d1aa1 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:22 +0530
+Subject: scsi: qla2xxx: Fix command flush on cable pull
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit a27d4d0e7de305def8a5098a614053be208d1aa1 upstream.
+
+System crash due to command failed to flush back to SCSI layer.
+
+ BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
+ PGD 0 P4D 0
+ Oops: 0000 [#1] SMP NOPTI
+ CPU: 27 PID: 793455 Comm: kworker/u130:6 Kdump: loaded Tainted: G           OE    --------- -  - 4.18.0-372.9.1.el8.x86_64 #1
+ Hardware name: HPE ProLiant DL360 Gen10/ProLiant DL360 Gen10, BIOS U32 09/03/2021
+ Workqueue: nvme-wq nvme_fc_connect_ctrl_work [nvme_fc]
+ RIP: 0010:__wake_up_common+0x4c/0x190
+ Code: 24 10 4d 85 c9 74 0a 41 f6 01 04 0f 85 9d 00 00 00 48 8b 43 08 48 83 c3 08 4c 8d 48 e8 49 8d 41 18 48 39 c3 0f 84 f0 00 00 00 <49> 8b 41 18 89 54 24 08 31 ed 4c 8d 70 e8 45 8b 29 41 f6 c5 04 75
+ RSP: 0018:ffff95f3e0cb7cd0 EFLAGS: 00010086
+ RAX: 0000000000000000 RBX: ffff8b08d3b26328 RCX: 0000000000000000
+ RDX: 0000000000000001 RSI: 0000000000000003 RDI: ffff8b08d3b26320
+ RBP: 0000000000000001 R08: 0000000000000000 R09: ffffffffffffffe8
+ R10: 0000000000000000 R11: ffff95f3e0cb7a60 R12: ffff95f3e0cb7d20
+ R13: 0000000000000003 R14: 0000000000000000 R15: 0000000000000000
+ FS:  0000000000000000(0000) GS:ffff8b2fdf6c0000(0000) knlGS:0000000000000000
+ CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 0000000000000000 CR3: 0000002f1e410002 CR4: 00000000007706e0
+ DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+ DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+ PKRU: 55555554
+ Call Trace:
+  __wake_up_common_lock+0x7c/0xc0
+  qla_nvme_ls_req+0x355/0x4c0 [qla2xxx]
+ qla2xxx [0000:12:00.1]-f084:3: qlt_free_session_done: se_sess 0000000000000000 / sess ffff8ae1407ca000 from port 21:32:00:02:ac:07:ee:b8 loop_id 0x02 s_id 01:02:00 logout 1 keep 0 els_logo 0
+ ? __nvme_fc_send_ls_req+0x260/0x380 [nvme_fc]
+ qla2xxx [0000:12:00.1]-207d:3: FCPort 21:32:00:02:ac:07:ee:b8 state transitioned from ONLINE to LOST - portid=010200.
+  ? nvme_fc_send_ls_req.constprop.42+0x1a/0x45 [nvme_fc]
+ qla2xxx [0000:12:00.1]-2109:3: qla2x00_schedule_rport_del 21320002ac07eeb8. rport ffff8ae598122000 roles 1
+ ? nvme_fc_connect_ctrl_work.cold.63+0x1e3/0xa7d [nvme_fc]
+ qla2xxx [0000:12:00.1]-f084:3: qlt_free_session_done: se_sess 0000000000000000 / sess ffff8ae14801e000 from port 21:32:01:02:ad:f7:ee:b8 loop_id 0x04 s_id 01:02:01 logout 1 keep 0 els_logo 0
+  ? __switch_to+0x10c/0x450
+ ? process_one_work+0x1a7/0x360
+ qla2xxx [0000:12:00.1]-207d:3: FCPort 21:32:01:02:ad:f7:ee:b8 state transitioned from ONLINE to LOST - portid=010201.
+  ? worker_thread+0x1ce/0x390
+  ? create_worker+0x1a0/0x1a0
+ qla2xxx [0000:12:00.1]-2109:3: qla2x00_schedule_rport_del 21320102adf7eeb8. rport ffff8ae3b2312800 roles 70
+  ? kthread+0x10a/0x120
+ qla2xxx [0000:12:00.1]-2112:3: qla_nvme_unregister_remote_port: unregister remoteport on ffff8ae14801e000 21320102adf7eeb8
+  ? set_kthread_struct+0x40/0x40
+ qla2xxx [0000:12:00.1]-2110:3: remoteport_delete of ffff8ae14801e000 21320102adf7eeb8 completed.
+  ? ret_from_fork+0x1f/0x40
+ qla2xxx [0000:12:00.1]-f086:3: qlt_free_session_done: waiting for sess ffff8ae14801e000 logout
+
+The system was under memory stress where driver was not able to allocate an
+SRB to carry out error recovery of cable pull.  The failure to flush causes
+upper layer to start modifying scsi_cmnd.  When the system frees up some
+memory, the subsequent cable pull trigger another command flush. At this
+point the driver access a null pointer when attempting to DMA unmap the
+SGL.
+
+Add a check to make sure commands are flush back on session tear down to
+prevent the null pointer access.
+
+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/20240227164127.36465-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_target.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/scsi/qla2xxx/qla_target.c
++++ b/drivers/scsi/qla2xxx/qla_target.c
+@@ -1062,6 +1062,16 @@ void qlt_free_session_done(struct work_s
+                   "%s: sess %p logout completed\n", __func__, sess);
+       }
++      /* check for any straggling io left behind */
++      if (!(sess->flags & FCF_FCP2_DEVICE) &&
++          qla2x00_eh_wait_for_pending_commands(sess->vha, sess->d_id.b24, 0, WAIT_TARGET)) {
++              ql_log(ql_log_warn, vha, 0x3027,
++                  "IO not return. Resetting.\n");
++              set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
++              qla2xxx_wake_dpc(vha);
++              qla2x00_wait_for_chip_reset(vha);
++      }
++
+       if (sess->logo_ack_needed) {
+               sess->logo_ack_needed = 0;
+               qla24xx_async_notify_ack(vha, sess,
diff --git a/queue-6.6/scsi-qla2xxx-fix-double-free-of-fcport.patch b/queue-6.6/scsi-qla2xxx-fix-double-free-of-fcport.patch
new file mode 100644 (file)
index 0000000..5de63e5
--- /dev/null
@@ -0,0 +1,79 @@
+From 82f522ae0d97119a43da53e0f729275691b9c525 Mon Sep 17 00:00:00 2001
+From: Saurav Kashyap <skashyap@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:24 +0530
+Subject: scsi: qla2xxx: Fix double free of fcport
+
+From: Saurav Kashyap <skashyap@marvell.com>
+
+commit 82f522ae0d97119a43da53e0f729275691b9c525 upstream.
+
+The server was crashing after LOGO because fcport was getting freed twice.
+
+ -----------[ cut here ]-----------
+ kernel BUG at mm/slub.c:371!
+ invalid opcode: 0000 1 SMP PTI
+ CPU: 35 PID: 4610 Comm: bash Kdump: loaded Tainted: G OE --------- - - 4.18.0-425.3.1.el8.x86_64 #1
+ Hardware name: HPE ProLiant DL360 Gen10/ProLiant DL360 Gen10, BIOS U32 09/03/2021
+ RIP: 0010:set_freepointer.part.57+0x0/0x10
+ RSP: 0018:ffffb07107027d90 EFLAGS: 00010246
+ RAX: ffff9cb7e3150000 RBX: ffff9cb7e332b9c0 RCX: ffff9cb7e3150400
+ RDX: 0000000000001f37 RSI: 0000000000000000 RDI: ffff9cb7c0005500
+ RBP: fffff693448c5400 R08: 0000000080000000 R09: 0000000000000009
+ R10: 0000000000000000 R11: 0000000000132af0 R12: ffff9cb7c0005500
+ R13: ffff9cb7e3150000 R14: ffffffffc06990e0 R15: ffff9cb7ea85ea58
+ FS: 00007ff6b79c2740(0000) GS:ffff9cb8f7ec0000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 000055b426b7d700 CR3: 0000000169c18002 CR4: 00000000007706e0
+ DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+ DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+ PKRU: 55555554
+ Call Trace:
+ kfree+0x238/0x250
+ qla2x00_els_dcmd_sp_free+0x20/0x230 [qla2xxx]
+ ? qla24xx_els_dcmd_iocb+0x607/0x690 [qla2xxx]
+ qla2x00_issue_logo+0x28c/0x2a0 [qla2xxx]
+ ? qla2x00_issue_logo+0x28c/0x2a0 [qla2xxx]
+ ? kernfs_fop_write+0x11e/0x1a0
+
+Remove one of the free calls and add check for valid fcport. Also use
+function qla2x00_free_fcport() instead of kfree().
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20240227164127.36465-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_iocb.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -2637,7 +2637,8 @@ static void qla2x00_els_dcmd_sp_free(srb
+ {
+       struct srb_iocb *elsio = &sp->u.iocb_cmd;
+-      kfree(sp->fcport);
++      if (sp->fcport)
++              qla2x00_free_fcport(sp->fcport);
+       if (elsio->u.els_logo.els_logo_pyld)
+               dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
+@@ -2750,6 +2751,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *v
+       if (!elsio->u.els_logo.els_logo_pyld) {
+               /* ref: INIT */
+               kref_put(&sp->cmd_kref, qla2x00_sp_release);
++              qla2x00_free_fcport(fcport);
+               return QLA_FUNCTION_FAILED;
+       }
+@@ -2784,7 +2786,6 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *v
+           fcport->d_id.b.area, fcport->d_id.b.al_pa);
+       wait_for_completion(&elsio->u.els_logo.comp);
+-      qla2x00_free_fcport(fcport);
+       /* ref: INIT */
+       kref_put(&sp->cmd_kref, qla2x00_sp_release);
diff --git a/queue-6.6/scsi-qla2xxx-fix-double-free-of-the-ha-vp_map-pointer.patch b/queue-6.6/scsi-qla2xxx-fix-double-free-of-the-ha-vp_map-pointer.patch
new file mode 100644 (file)
index 0000000..c3cc47b
--- /dev/null
@@ -0,0 +1,36 @@
+From e288285d47784fdcf7c81be56df7d65c6f10c58b Mon Sep 17 00:00:00 2001
+From: Saurav Kashyap <skashyap@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:23 +0530
+Subject: scsi: qla2xxx: Fix double free of the ha->vp_map pointer
+
+From: Saurav Kashyap <skashyap@marvell.com>
+
+commit e288285d47784fdcf7c81be56df7d65c6f10c58b upstream.
+
+Coverity scan reported potential risk of double free of the pointer
+ha->vp_map.  ha->vp_map was freed in qla2x00_mem_alloc(), and again freed
+in function qla2x00_mem_free(ha).
+
+Assign NULL to vp_map and kfree take care of NULL.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20240227164127.36465-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_os.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -4601,6 +4601,7 @@ fail_free_init_cb:
+       ha->init_cb_dma = 0;
+ fail_free_vp_map:
+       kfree(ha->vp_map);
++      ha->vp_map = NULL;
+ fail:
+       ql_log(ql_log_fatal, NULL, 0x0030,
+           "Memory allocation failure.\n");
diff --git a/queue-6.6/scsi-qla2xxx-fix-n2n-stuck-connection.patch b/queue-6.6/scsi-qla2xxx-fix-n2n-stuck-connection.patch
new file mode 100644 (file)
index 0000000..227627a
--- /dev/null
@@ -0,0 +1,145 @@
+From 881eb861ca3877300570db10abbf11494e48548d Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:18 +0530
+Subject: scsi: qla2xxx: Fix N2N stuck connection
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 881eb861ca3877300570db10abbf11494e48548d upstream.
+
+Disk failed to rediscover after chip reset error injection. The chip reset
+happens at the time when a PLOGI is being sent. This causes a flag to be
+left on which blocks the retry. Clear the blocking flag.
+
+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/20240227164127.36465-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  |    2 +-
+ drivers/scsi/qla2xxx/qla_iocb.c |   32 +++++++++++---------------------
+ drivers/scsi/qla2xxx/qla_os.c   |    2 +-
+ 3 files changed, 13 insertions(+), 23 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -44,7 +44,7 @@ extern int qla2x00_fabric_login(scsi_qla
+ extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
+ extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t);
+-extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *, bool);
++extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *);
+ extern void qla2x00_els_dcmd2_free(scsi_qla_host_t *vha,
+                                  struct els_plogi *els_plogi);
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -3041,7 +3041,7 @@ static void qla2x00_els_dcmd2_sp_done(sr
+ int
+ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+-    fc_port_t *fcport, bool wait)
++                      fc_port_t *fcport)
+ {
+       srb_t *sp;
+       struct srb_iocb *elsio = NULL;
+@@ -3056,8 +3056,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *
+       if (!sp) {
+               ql_log(ql_log_info, vha, 0x70e6,
+                "SRB allocation failed\n");
+-              fcport->flags &= ~FCF_ASYNC_ACTIVE;
+-              return -ENOMEM;
++              goto done;
+       }
+       fcport->flags |= FCF_ASYNC_SENT;
+@@ -3066,9 +3065,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *
+       ql_dbg(ql_dbg_io, vha, 0x3073,
+              "%s Enter: PLOGI portid=%06x\n", __func__, fcport->d_id.b24);
+-      if (wait)
+-              sp->flags = SRB_WAKEUP_ON_COMP;
+-
+       sp->type = SRB_ELS_DCMD;
+       sp->name = "ELS_DCMD";
+       sp->fcport = fcport;
+@@ -3084,7 +3080,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *
+       if (!elsio->u.els_plogi.els_plogi_pyld) {
+               rval = QLA_FUNCTION_FAILED;
+-              goto out;
++              goto done_free_sp;
+       }
+       resp_ptr = elsio->u.els_plogi.els_resp_pyld =
+@@ -3093,7 +3089,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *
+       if (!elsio->u.els_plogi.els_resp_pyld) {
+               rval = QLA_FUNCTION_FAILED;
+-              goto out;
++              goto done_free_sp;
+       }
+       ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr);
+@@ -3109,7 +3105,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *
+       if (els_opcode == ELS_DCMD_PLOGI && DBELL_ACTIVE(vha)) {
+               struct fc_els_flogi *p = ptr;
+-
+               p->fl_csp.sp_features |= cpu_to_be16(FC_SP_FT_SEC);
+       }
+@@ -3118,10 +3113,11 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *
+           (uint8_t *)elsio->u.els_plogi.els_plogi_pyld,
+           sizeof(*elsio->u.els_plogi.els_plogi_pyld));
+-      init_completion(&elsio->u.els_plogi.comp);
+       rval = qla2x00_start_sp(sp);
+       if (rval != QLA_SUCCESS) {
+-              rval = QLA_FUNCTION_FAILED;
++              fcport->flags |= FCF_LOGIN_NEEDED;
++              set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
++              goto done_free_sp;
+       } else {
+               ql_dbg(ql_dbg_disc, vha, 0x3074,
+                   "%s PLOGI sent, hdl=%x, loopid=%x, to port_id %06x from port_id %06x\n",
+@@ -3129,21 +3125,15 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *
+                   fcport->d_id.b24, vha->d_id.b24);
+       }
+-      if (wait) {
+-              wait_for_completion(&elsio->u.els_plogi.comp);
+-
+-              if (elsio->u.els_plogi.comp_status != CS_COMPLETE)
+-                      rval = QLA_FUNCTION_FAILED;
+-      } else {
+-              goto done;
+-      }
++      return rval;
+-out:
+-      fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
++done_free_sp:
+       qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
+       /* ref: INIT */
+       kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
++      fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
++      qla2x00_set_fcport_disc_state(fcport, DSC_DELETED);
+       return rval;
+ }
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -5582,7 +5582,7 @@ qla2x00_do_work(struct scsi_qla_host *vh
+                       break;
+               case QLA_EVT_ELS_PLOGI:
+                       qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
+-                          e->u.fcport.fcport, false);
++                          e->u.fcport.fcport);
+                       break;
+               case QLA_EVT_SA_REPLACE:
+                       rc = qla24xx_issue_sa_replace_iocb(vha, e);
diff --git a/queue-6.6/scsi-qla2xxx-nvme-fcp-prefer-flag-not-being-honored.patch b/queue-6.6/scsi-qla2xxx-nvme-fcp-prefer-flag-not-being-honored.patch
new file mode 100644 (file)
index 0000000..2ed8e08
--- /dev/null
@@ -0,0 +1,69 @@
+From 69aecdd410106dc3a8f543a4f7ec6379b995b8d0 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:21 +0530
+Subject: scsi: qla2xxx: NVME|FCP prefer flag not being honored
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 69aecdd410106dc3a8f543a4f7ec6379b995b8d0 upstream.
+
+Changing of [FCP|NVME] prefer flag in flash has no effect on driver. For
+device that supports both FCP + NVMe over the same connection, driver
+continues to connect to this device using the previous successful login
+mode.
+
+On completion of flash update, adapter will be reset. Driver will
+reset the prefer flag based on setting from flash.
+
+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/20240227164127.36465-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 |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -7501,6 +7501,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
+       struct scsi_qla_host *vp, *tvp;
+       struct req_que *req = ha->req_q_map[0];
+       unsigned long flags;
++      fc_port_t *fcport;
+       if (vha->flags.online) {
+               qla2x00_abort_isp_cleanup(vha);
+@@ -7569,6 +7570,15 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
+                              "ISP Abort - ISP reg disconnect post nvmram config, exiting.\n");
+                       return status;
+               }
++
++              /* User may have updated [fcp|nvme] prefer in flash */
++              list_for_each_entry(fcport, &vha->vp_fcports, list) {
++                      if (NVME_PRIORITY(ha, fcport))
++                              fcport->do_prli_nvme = 1;
++                      else
++                              fcport->do_prli_nvme = 0;
++              }
++
+               if (!qla2x00_restart_isp(vha)) {
+                       clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
+@@ -7639,6 +7649,14 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
+                               atomic_inc(&vp->vref_count);
+                               spin_unlock_irqrestore(&ha->vport_slock, flags);
++                              /* User may have updated [fcp|nvme] prefer in flash */
++                              list_for_each_entry(fcport, &vp->vp_fcports, list) {
++                                      if (NVME_PRIORITY(ha, fcport))
++                                              fcport->do_prli_nvme = 1;
++                                      else
++                                              fcport->do_prli_nvme = 0;
++                              }
++
+                               qla2x00_vp_abort_isp(vp);
+                               spin_lock_irqsave(&ha->vport_slock, flags);
diff --git a/queue-6.6/scsi-qla2xxx-prevent-command-send-on-chip-reset.patch b/queue-6.6/scsi-qla2xxx-prevent-command-send-on-chip-reset.patch
new file mode 100644 (file)
index 0000000..268bf32
--- /dev/null
@@ -0,0 +1,115 @@
+From 4895009c4bb72f71f2e682f1e7d2c2d96e482087 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:17 +0530
+Subject: scsi: qla2xxx: Prevent command send on chip reset
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 4895009c4bb72f71f2e682f1e7d2c2d96e482087 upstream.
+
+Currently IOCBs are allowed to push through while chip reset could be in
+progress. During chip reset the outstanding_cmds array is cleared
+twice. Once when any command on this array is returned as failed and
+secondly when the array is initialize to zero. If a command is inserted on
+to the array between these intervals, then the command will be lost.  Check
+for chip reset before sending IOCB.
+
+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/20240227164127.36465-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 |    8 ++++++--
+ drivers/scsi/qla2xxx/qla_iocb.c |   33 +++++++++++++++++++++++++++++++--
+ 2 files changed, 37 insertions(+), 4 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1193,8 +1193,12 @@ int qla24xx_async_gnl(struct scsi_qla_ho
+       return rval;
+ done_free_sp:
+-      /* ref: INIT */
+-      kref_put(&sp->cmd_kref, qla2x00_sp_release);
++      /*
++       * use qla24xx_async_gnl_sp_done to purge all pending gnl request.
++       * kref_put is call behind the scene.
++       */
++      sp->u.iocb_cmd.u.mbx.in_mb[0] = MBS_COMMAND_ERROR;
++      qla24xx_async_gnl_sp_done(sp, QLA_COMMAND_ERROR);
+       fcport->flags &= ~(FCF_ASYNC_SENT);
+ done:
+       fcport->flags &= ~(FCF_ASYNC_ACTIVE);
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -2587,6 +2587,33 @@ void
+ qla2x00_sp_release(struct kref *kref)
+ {
+       struct srb *sp = container_of(kref, struct srb, cmd_kref);
++      struct scsi_qla_host *vha = sp->vha;
++
++      switch (sp->type) {
++      case SRB_CT_PTHRU_CMD:
++              /* GPSC & GFPNID use fcport->ct_desc.ct_sns for both req & rsp */
++              if (sp->u.iocb_cmd.u.ctarg.req &&
++                      (!sp->fcport ||
++                       sp->u.iocb_cmd.u.ctarg.req != sp->fcport->ct_desc.ct_sns)) {
++                      dma_free_coherent(&vha->hw->pdev->dev,
++                          sp->u.iocb_cmd.u.ctarg.req_allocated_size,
++                          sp->u.iocb_cmd.u.ctarg.req,
++                          sp->u.iocb_cmd.u.ctarg.req_dma);
++                      sp->u.iocb_cmd.u.ctarg.req = NULL;
++              }
++              if (sp->u.iocb_cmd.u.ctarg.rsp &&
++                      (!sp->fcport ||
++                       sp->u.iocb_cmd.u.ctarg.rsp != sp->fcport->ct_desc.ct_sns)) {
++                      dma_free_coherent(&vha->hw->pdev->dev,
++                          sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
++                          sp->u.iocb_cmd.u.ctarg.rsp,
++                          sp->u.iocb_cmd.u.ctarg.rsp_dma);
++                      sp->u.iocb_cmd.u.ctarg.rsp = NULL;
++              }
++              break;
++      default:
++              break;
++      }
+       sp->free(sp);
+ }
+@@ -2692,7 +2719,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *v
+        */
+       sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+       if (!sp) {
+-              kfree(fcport);
++              qla2x00_free_fcport(fcport);
+               ql_log(ql_log_info, vha, 0x70e6,
+                "SRB allocation failed\n");
+               return -ENOMEM;
+@@ -2747,6 +2774,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *v
+       if (rval != QLA_SUCCESS) {
+               /* ref: INIT */
+               kref_put(&sp->cmd_kref, qla2x00_sp_release);
++              qla2x00_free_fcport(fcport);
+               return QLA_FUNCTION_FAILED;
+       }
+@@ -2756,6 +2784,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *v
+           fcport->d_id.b.area, fcport->d_id.b.al_pa);
+       wait_for_completion(&elsio->u.els_logo.comp);
++      qla2x00_free_fcport(fcport);
+       /* ref: INIT */
+       kref_put(&sp->cmd_kref, qla2x00_sp_release);
+@@ -3918,7 +3947,7 @@ qla2x00_start_sp(srb_t *sp)
+               return -EAGAIN;
+       }
+-      pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
++      pkt = qla2x00_alloc_iocbs_ready(sp->qpair, sp);
+       if (!pkt) {
+               rval = -EAGAIN;
+               ql_log(ql_log_warn, vha, 0x700c,
diff --git a/queue-6.6/scsi-qla2xxx-split-fce-eft-trace-control.patch b/queue-6.6/scsi-qla2xxx-split-fce-eft-trace-control.patch
new file mode 100644 (file)
index 0000000..91ae3ba
--- /dev/null
@@ -0,0 +1,224 @@
+From 76a192e1a566e15365704b9f8fb3b70825f85064 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:19 +0530
+Subject: scsi: qla2xxx: Split FCE|EFT trace control
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 76a192e1a566e15365704b9f8fb3b70825f85064 upstream.
+
+Current code combines the allocation of FCE|EFT trace buffers and enables
+the features all in 1 step.
+
+Split this step into separate steps in preparation for follow-on patch to
+allow user to have a choice to enable / disable FCE trace feature.
+
+Cc: stable@vger.kernel.org
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20240227164127.36465-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_init.c |  102 ++++++++++++++++------------------------
+ 1 file changed, 41 insertions(+), 61 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -2669,6 +2669,40 @@ exit:
+       return rval;
+ }
++static void qla_enable_fce_trace(scsi_qla_host_t *vha)
++{
++      int rval;
++      struct qla_hw_data *ha = vha->hw;
++
++      if (ha->fce) {
++              ha->flags.fce_enabled = 1;
++              memset(ha->fce, 0, fce_calc_size(ha->fce_bufs));
++              rval = qla2x00_enable_fce_trace(vha,
++                  ha->fce_dma, ha->fce_bufs, ha->fce_mb, &ha->fce_bufs);
++
++              if (rval) {
++                      ql_log(ql_log_warn, vha, 0x8033,
++                          "Unable to reinitialize FCE (%d).\n", rval);
++                      ha->flags.fce_enabled = 0;
++              }
++      }
++}
++
++static void qla_enable_eft_trace(scsi_qla_host_t *vha)
++{
++      int rval;
++      struct qla_hw_data *ha = vha->hw;
++
++      if (ha->eft) {
++              memset(ha->eft, 0, EFT_SIZE);
++              rval = qla2x00_enable_eft_trace(vha, ha->eft_dma, EFT_NUM_BUFFERS);
++
++              if (rval) {
++                      ql_log(ql_log_warn, vha, 0x8034,
++                          "Unable to reinitialize EFT (%d).\n", rval);
++              }
++      }
++}
+ /*
+ * qla2x00_initialize_adapter
+ *      Initialize board.
+@@ -3672,9 +3706,8 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
+ }
+ static void
+-qla2x00_init_fce_trace(scsi_qla_host_t *vha)
++qla2x00_alloc_fce_trace(scsi_qla_host_t *vha)
+ {
+-      int rval;
+       dma_addr_t tc_dma;
+       void *tc;
+       struct qla_hw_data *ha = vha->hw;
+@@ -3703,27 +3736,17 @@ qla2x00_init_fce_trace(scsi_qla_host_t *
+               return;
+       }
+-      rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
+-                                      ha->fce_mb, &ha->fce_bufs);
+-      if (rval) {
+-              ql_log(ql_log_warn, vha, 0x00bf,
+-                     "Unable to initialize FCE (%d).\n", rval);
+-              dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, tc_dma);
+-              return;
+-      }
+-
+       ql_dbg(ql_dbg_init, vha, 0x00c0,
+              "Allocated (%d KB) for FCE...\n", FCE_SIZE / 1024);
+-      ha->flags.fce_enabled = 1;
+       ha->fce_dma = tc_dma;
+       ha->fce = tc;
++      ha->fce_bufs = FCE_NUM_BUFFERS;
+ }
+ static void
+-qla2x00_init_eft_trace(scsi_qla_host_t *vha)
++qla2x00_alloc_eft_trace(scsi_qla_host_t *vha)
+ {
+-      int rval;
+       dma_addr_t tc_dma;
+       void *tc;
+       struct qla_hw_data *ha = vha->hw;
+@@ -3748,14 +3771,6 @@ qla2x00_init_eft_trace(scsi_qla_host_t *
+               return;
+       }
+-      rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
+-      if (rval) {
+-              ql_log(ql_log_warn, vha, 0x00c2,
+-                     "Unable to initialize EFT (%d).\n", rval);
+-              dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, tc_dma);
+-              return;
+-      }
+-
+       ql_dbg(ql_dbg_init, vha, 0x00c3,
+              "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
+@@ -3763,13 +3778,6 @@ qla2x00_init_eft_trace(scsi_qla_host_t *
+       ha->eft = tc;
+ }
+-static void
+-qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
+-{
+-      qla2x00_init_fce_trace(vha);
+-      qla2x00_init_eft_trace(vha);
+-}
+-
+ void
+ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+ {
+@@ -3824,10 +3832,10 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *v
+               if (ha->tgt.atio_ring)
+                       mq_size += ha->tgt.atio_q_length * sizeof(request_t);
+-              qla2x00_init_fce_trace(vha);
++              qla2x00_alloc_fce_trace(vha);
+               if (ha->fce)
+                       fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
+-              qla2x00_init_eft_trace(vha);
++              qla2x00_alloc_eft_trace(vha);
+               if (ha->eft)
+                       eft_size = EFT_SIZE;
+       }
+@@ -4257,7 +4265,6 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
+       struct qla_hw_data *ha = vha->hw;
+       struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+       unsigned long flags;
+-      uint16_t fw_major_version;
+       int done_once = 0;
+       if (IS_P3P_TYPE(ha)) {
+@@ -4324,7 +4331,6 @@ execute_fw_with_lr:
+                                       goto failed;
+ enable_82xx_npiv:
+-                              fw_major_version = ha->fw_major_version;
+                               if (IS_P3P_TYPE(ha))
+                                       qla82xx_check_md_needed(vha);
+                               else
+@@ -4353,12 +4359,11 @@ enable_82xx_npiv:
+                               if (rval != QLA_SUCCESS)
+                                       goto failed;
+-                              if (!fw_major_version && !(IS_P3P_TYPE(ha)))
+-                                      qla2x00_alloc_offload_mem(vha);
+-
+                               if (ql2xallocfwdump && !(IS_P3P_TYPE(ha)))
+                                       qla2x00_alloc_fw_dump(vha);
++                              qla_enable_fce_trace(vha);
++                              qla_enable_eft_trace(vha);
+                       } else {
+                               goto failed;
+                       }
+@@ -7491,7 +7496,6 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_
+ int
+ qla2x00_abort_isp(scsi_qla_host_t *vha)
+ {
+-      int rval;
+       uint8_t        status = 0;
+       struct qla_hw_data *ha = vha->hw;
+       struct scsi_qla_host *vp, *tvp;
+@@ -7585,31 +7589,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
+                       if (IS_QLA81XX(ha) || IS_QLA8031(ha))
+                               qla2x00_get_fw_version(vha);
+-                      if (ha->fce) {
+-                              ha->flags.fce_enabled = 1;
+-                              memset(ha->fce, 0,
+-                                  fce_calc_size(ha->fce_bufs));
+-                              rval = qla2x00_enable_fce_trace(vha,
+-                                  ha->fce_dma, ha->fce_bufs, ha->fce_mb,
+-                                  &ha->fce_bufs);
+-                              if (rval) {
+-                                      ql_log(ql_log_warn, vha, 0x8033,
+-                                          "Unable to reinitialize FCE "
+-                                          "(%d).\n", rval);
+-                                      ha->flags.fce_enabled = 0;
+-                              }
+-                      }
+-                      if (ha->eft) {
+-                              memset(ha->eft, 0, EFT_SIZE);
+-                              rval = qla2x00_enable_eft_trace(vha,
+-                                  ha->eft_dma, EFT_NUM_BUFFERS);
+-                              if (rval) {
+-                                      ql_log(ql_log_warn, vha, 0x8034,
+-                                          "Unable to reinitialize EFT "
+-                                          "(%d).\n", rval);
+-                              }
+-                      }
+               } else {        /* failed the ISP abort */
+                       vha->flags.online = 1;
+                       if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
diff --git a/queue-6.6/scsi-qla2xxx-update-manufacturer-detail.patch b/queue-6.6/scsi-qla2xxx-update-manufacturer-detail.patch
new file mode 100644 (file)
index 0000000..811bad7
--- /dev/null
@@ -0,0 +1,34 @@
+From 688fa069fda6fce24d243cddfe0c7024428acb74 Mon Sep 17 00:00:00 2001
+From: Bikash Hazarika <bhazarika@marvell.com>
+Date: Tue, 27 Feb 2024 22:11:20 +0530
+Subject: scsi: qla2xxx: Update manufacturer detail
+
+From: Bikash Hazarika <bhazarika@marvell.com>
+
+commit 688fa069fda6fce24d243cddfe0c7024428acb74 upstream.
+
+Update manufacturer detail from "Marvell Semiconductor, Inc." to
+"Marvell".
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Bikash Hazarika <bhazarika@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20240227164127.36465-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_def.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -82,7 +82,7 @@ typedef union {
+ #include "qla_nvme.h"
+ #define QLA2XXX_DRIVER_NAME   "qla2xxx"
+ #define QLA2XXX_APIDEV                "ql2xapidev"
+-#define QLA2XXX_MANUFACTURER  "Marvell Semiconductor, Inc."
++#define QLA2XXX_MANUFACTURER  "Marvell"
+ /*
+  * We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
index b363799b5811f15f41fd08711e50b8bb09782e9a..a6012a7c996696e31cca73f3fc46bd83f964aa9a 100644 (file)
@@ -359,3 +359,29 @@ scsi-sg-avoid-sg-device-teardown-race.patch
 scsi-core-fix-unremoved-procfs-host-directory-regression.patch
 staging-vc04_services-changen-strncpy-to-strscpy_pad.patch
 staging-vc04_services-fix-information-leak-in-create_component.patch
+usb-dwc3-properly-set-system-wakeup.patch
+usb-core-fix-deadlock-in-usb_deauthorize_interface.patch
+usb-core-add-hub_get-and-hub_put-routines.patch
+usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch
+usb-dwc2-host-fix-remote-wakeup-from-hibernation.patch
+usb-dwc2-host-fix-hibernation-flow.patch
+usb-dwc2-host-fix-isoc-flow-in-ddma-mode.patch
+usb-dwc2-gadget-fix-exiting-from-clock-gating.patch
+usb-dwc2-gadget-lpm-flow-fix.patch
+usb-udc-remove-warning-when-queue-disabled-ep.patch
+usb-typec-return-size-of-buffer-if-pd_set-operation-succeeds.patch
+usb-typec-ucsi-clear-event_pending-under-ppm-lock.patch
+usb-typec-ucsi-check-for-notifications-after-init.patch
+usb-typec-ucsi-ack-unsupported-commands.patch
+usb-typec-ucsi_acpi-refactor-and-fix-dell-quirk.patch
+usb-typec-ucsi-clear-ucsi_cci_reset_complete-before-reset.patch
+scsi-qla2xxx-prevent-command-send-on-chip-reset.patch
+scsi-qla2xxx-fix-n2n-stuck-connection.patch
+scsi-qla2xxx-split-fce-eft-trace-control.patch
+scsi-qla2xxx-update-manufacturer-detail.patch
+scsi-qla2xxx-nvme-fcp-prefer-flag-not-being-honored.patch
+scsi-qla2xxx-fix-command-flush-on-cable-pull.patch
+scsi-qla2xxx-fix-double-free-of-the-ha-vp_map-pointer.patch
+scsi-qla2xxx-fix-double-free-of-fcport.patch
+scsi-qla2xxx-change-debug-message-during-driver-unload.patch
+scsi-qla2xxx-delay-i-o-abort-on-pci-error.patch
diff --git a/queue-6.6/usb-core-add-hub_get-and-hub_put-routines.patch b/queue-6.6/usb-core-add-hub_get-and-hub_put-routines.patch
new file mode 100644 (file)
index 0000000..7dec5e8
--- /dev/null
@@ -0,0 +1,113 @@
+From ee113b860aa169e9a4d2c167c95d0f1961c6e1b8 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 15 Mar 2024 13:04:50 -0400
+Subject: USB: core: Add hub_get() and hub_put() routines
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit ee113b860aa169e9a4d2c167c95d0f1961c6e1b8 upstream.
+
+Create hub_get() and hub_put() routines to encapsulate the kref_get()
+and kref_put() calls in hub.c.  The new routines will be used by the
+next patch in this series.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/604da420-ae8a-4a9e-91a4-2d511ff404fb@rowland.harvard.edu
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/hub.c |   23 ++++++++++++++++-------
+ drivers/usb/core/hub.h |    2 ++
+ 2 files changed, 18 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -123,7 +123,6 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rws
+ #define HUB_DEBOUNCE_STEP       25
+ #define HUB_DEBOUNCE_STABLE    100
+-static void hub_release(struct kref *kref);
+ static int usb_reset_and_verify_device(struct usb_device *udev);
+ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state);
+ static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1,
+@@ -685,14 +684,14 @@ static void kick_hub_wq(struct usb_hub *
+        */
+       intf = to_usb_interface(hub->intfdev);
+       usb_autopm_get_interface_no_resume(intf);
+-      kref_get(&hub->kref);
++      hub_get(hub);
+       if (queue_work(hub_wq, &hub->events))
+               return;
+       /* the work has already been scheduled */
+       usb_autopm_put_interface_async(intf);
+-      kref_put(&hub->kref, hub_release);
++      hub_put(hub);
+ }
+ void usb_kick_hub_wq(struct usb_device *hdev)
+@@ -1060,7 +1059,7 @@ static void hub_activate(struct usb_hub
+                       goto init2;
+               goto init3;
+       }
+-      kref_get(&hub->kref);
++      hub_get(hub);
+       /* The superspeed hub except for root hub has to use Hub Depth
+        * value as an offset into the route string to locate the bits
+@@ -1308,7 +1307,7 @@ static void hub_activate(struct usb_hub
+               device_unlock(&hdev->dev);
+       }
+-      kref_put(&hub->kref, hub_release);
++      hub_put(hub);
+ }
+ /* Implement the continuations for the delays above */
+@@ -1724,6 +1723,16 @@ static void hub_release(struct kref *kre
+       kfree(hub);
+ }
++void hub_get(struct usb_hub *hub)
++{
++      kref_get(&hub->kref);
++}
++
++void hub_put(struct usb_hub *hub)
++{
++      kref_put(&hub->kref, hub_release);
++}
++
+ static unsigned highspeed_hubs;
+ static void hub_disconnect(struct usb_interface *intf)
+@@ -1772,7 +1781,7 @@ static void hub_disconnect(struct usb_in
+       onboard_hub_destroy_pdevs(&hub->onboard_hub_devs);
+-      kref_put(&hub->kref, hub_release);
++      hub_put(hub);
+ }
+ static bool hub_descriptor_is_sane(struct usb_host_interface *desc)
+@@ -5890,7 +5899,7 @@ out_hdev_lock:
+       /* Balance the stuff in kick_hub_wq() and allow autosuspend */
+       usb_autopm_put_interface(intf);
+-      kref_put(&hub->kref, hub_release);
++      hub_put(hub);
+       kcov_remote_stop();
+ }
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -126,6 +126,8 @@ extern void usb_hub_remove_port_device(s
+ extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
+               int port1, bool set);
+ extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);
++extern void hub_get(struct usb_hub *hub);
++extern void hub_put(struct usb_hub *hub);
+ extern int hub_port_debounce(struct usb_hub *hub, int port1,
+               bool must_be_connected);
+ extern int usb_clear_port_feature(struct usb_device *hdev,
diff --git a/queue-6.6/usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch b/queue-6.6/usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch
new file mode 100644 (file)
index 0000000..1551443
--- /dev/null
@@ -0,0 +1,123 @@
+From f4d1960764d8a70318b02f15203a1be2b2554ca1 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 15 Mar 2024 13:06:33 -0400
+Subject: USB: core: Fix deadlock in port "disable" sysfs attribute
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit f4d1960764d8a70318b02f15203a1be2b2554ca1 upstream.
+
+The show and store callback routines for the "disable" sysfs attribute
+file in port.c acquire the device lock for the port's parent hub
+device.  This can cause problems if another process has locked the hub
+to remove it or change its configuration:
+
+       Removing the hub or changing its configuration requires the
+       hub interface to be removed, which requires the port device
+       to be removed, and device_del() waits until all outstanding
+       sysfs attribute callbacks for the ports have returned.  The
+       lock can't be released until then.
+
+       But the disable_show() or disable_store() routine can't return
+       until after it has acquired the lock.
+
+The resulting deadlock can be avoided by calling
+sysfs_break_active_protection().  This will cause the sysfs core not
+to wait for the attribute's callback routine to return, allowing the
+removal to proceed.  The disadvantage is that after making this call,
+there is no guarantee that the hub structure won't be deallocated at
+any moment.  To prevent this, we have to acquire a reference to it
+first by calling hub_get().
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Cc: stable <stable@kernel.org>
+Link: https://lore.kernel.org/r/f7a8c135-a495-4ce6-bd49-405a45e7ea9a@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/port.c |   38 ++++++++++++++++++++++++++++++++++----
+ 1 file changed, 34 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/core/port.c
++++ b/drivers/usb/core/port.c
+@@ -55,11 +55,22 @@ static ssize_t disable_show(struct devic
+       u16 portstatus, unused;
+       bool disabled;
+       int rc;
++      struct kernfs_node *kn;
++      hub_get(hub);
+       rc = usb_autopm_get_interface(intf);
+       if (rc < 0)
+-              return rc;
++              goto out_hub_get;
++      /*
++       * Prevent deadlock if another process is concurrently
++       * trying to unregister hdev.
++       */
++      kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
++      if (!kn) {
++              rc = -ENODEV;
++              goto out_autopm;
++      }
+       usb_lock_device(hdev);
+       if (hub->disconnected) {
+               rc = -ENODEV;
+@@ -69,9 +80,13 @@ static ssize_t disable_show(struct devic
+       usb_hub_port_status(hub, port1, &portstatus, &unused);
+       disabled = !usb_port_is_power_on(hub, portstatus);
+-out_hdev_lock:
++ out_hdev_lock:
+       usb_unlock_device(hdev);
++      sysfs_unbreak_active_protection(kn);
++ out_autopm:
+       usb_autopm_put_interface(intf);
++ out_hub_get:
++      hub_put(hub);
+       if (rc)
+               return rc;
+@@ -89,15 +104,26 @@ static ssize_t disable_store(struct devi
+       int port1 = port_dev->portnum;
+       bool disabled;
+       int rc;
++      struct kernfs_node *kn;
+       rc = kstrtobool(buf, &disabled);
+       if (rc)
+               return rc;
++      hub_get(hub);
+       rc = usb_autopm_get_interface(intf);
+       if (rc < 0)
+-              return rc;
++              goto out_hub_get;
++      /*
++       * Prevent deadlock if another process is concurrently
++       * trying to unregister hdev.
++       */
++      kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
++      if (!kn) {
++              rc = -ENODEV;
++              goto out_autopm;
++      }
+       usb_lock_device(hdev);
+       if (hub->disconnected) {
+               rc = -ENODEV;
+@@ -118,9 +144,13 @@ static ssize_t disable_store(struct devi
+       if (!rc)
+               rc = count;
+-out_hdev_lock:
++ out_hdev_lock:
+       usb_unlock_device(hdev);
++      sysfs_unbreak_active_protection(kn);
++ out_autopm:
+       usb_autopm_put_interface(intf);
++ out_hub_get:
++      hub_put(hub);
+       return rc;
+ }
diff --git a/queue-6.6/usb-core-fix-deadlock-in-usb_deauthorize_interface.patch b/queue-6.6/usb-core-fix-deadlock-in-usb_deauthorize_interface.patch
new file mode 100644 (file)
index 0000000..62aa8e3
--- /dev/null
@@ -0,0 +1,70 @@
+From 80ba43e9f799cbdd83842fc27db667289b3150f5 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Tue, 12 Mar 2024 11:48:23 -0400
+Subject: USB: core: Fix deadlock in usb_deauthorize_interface()
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 80ba43e9f799cbdd83842fc27db667289b3150f5 upstream.
+
+Among the attribute file callback routines in
+drivers/usb/core/sysfs.c, the interface_authorized_store() function is
+the only one which acquires a device lock on an ancestor device: It
+calls usb_deauthorize_interface(), which locks the interface's parent
+USB device.
+
+The will lead to deadlock if another process already owns that lock
+and tries to remove the interface, whether through a configuration
+change or because the device has been disconnected.  As part of the
+removal procedure, device_del() waits for all ongoing sysfs attribute
+callbacks to complete.  But usb_deauthorize_interface() can't complete
+until the device lock has been released, and the lock won't be
+released until the removal has finished.
+
+The mechanism provided by sysfs to prevent this kind of deadlock is
+to use the sysfs_break_active_protection() function, which tells sysfs
+not to wait for the attribute callback.
+
+Reported-and-tested by: Yue Sun <samsun1006219@gmail.com>
+Reported by: xingwei lee <xrivendell7@gmail.com>
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/linux-usb/CAEkJfYO6jRVC8Tfrd_R=cjO0hguhrV31fDPrLrNOOHocDkPoAA@mail.gmail.com/#r
+Fixes: 310d2b4124c0 ("usb: interface authorization: SysFS part of USB interface authorization")
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/1c37eea1-9f56-4534-b9d8-b443438dc869@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/sysfs.c |   16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -1168,14 +1168,24 @@ static ssize_t interface_authorized_stor
+ {
+       struct usb_interface *intf = to_usb_interface(dev);
+       bool val;
++      struct kernfs_node *kn;
+       if (kstrtobool(buf, &val) != 0)
+               return -EINVAL;
+-      if (val)
++      if (val) {
+               usb_authorize_interface(intf);
+-      else
+-              usb_deauthorize_interface(intf);
++      } else {
++              /*
++               * Prevent deadlock if another process is concurrently
++               * trying to unregister intf.
++               */
++              kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
++              if (kn) {
++                      usb_deauthorize_interface(intf);
++                      sysfs_unbreak_active_protection(kn);
++              }
++      }
+       return count;
+ }
diff --git a/queue-6.6/usb-dwc2-gadget-fix-exiting-from-clock-gating.patch b/queue-6.6/usb-dwc2-gadget-fix-exiting-from-clock-gating.patch
new file mode 100644 (file)
index 0000000..d0762b3
--- /dev/null
@@ -0,0 +1,97 @@
+From 31f42da31417bec88158f3cf62d19db836217f1e Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Wed, 13 Mar 2024 09:22:01 +0000
+Subject: usb: dwc2: gadget: Fix exiting from clock gating
+
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+
+commit 31f42da31417bec88158f3cf62d19db836217f1e upstream.
+
+Added exiting from the clock gating mode on USB Reset Detect interrupt
+if core in the clock gating mode.
+Added new condition to check core in clock gating mode or no.
+
+Fixes: 9b4965d77e11 ("usb: dwc2: Add exit clock gating from session request interrupt")
+Fixes: 5d240efddc7f ("usb: dwc2: Add exit clock gating from wakeup interrupt")
+Fixes: 16c729f90bdf ("usb: dwc2: Allow exit clock gating in urb enqueue")
+Fixes: 401411bbc4e6 ("usb: dwc2: Add exit clock gating before removing driver")
+CC: stable@vger.kernel.org
+Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Link: https://lore.kernel.org/r/cbcc2ccd37e89e339130797ed68ae4597db773ac.1708938774.git.Minas.Harutyunyan@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/core_intr.c |    9 ++++++---
+ drivers/usb/dwc2/gadget.c    |    6 ++++++
+ drivers/usb/dwc2/hcd.c       |    2 +-
+ drivers/usb/dwc2/platform.c  |    2 +-
+ 4 files changed, 14 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/dwc2/core_intr.c
++++ b/drivers/usb/dwc2/core_intr.c
+@@ -297,7 +297,8 @@ static void dwc2_handle_session_req_intr
+                       /* Exit gadget mode clock gating. */
+                       if (hsotg->params.power_down ==
+-                          DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
++                          DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended &&
++                          !hsotg->params.no_clock_gating)
+                               dwc2_gadget_exit_clock_gating(hsotg, 0);
+               }
+@@ -408,7 +409,8 @@ static void dwc2_handle_wakeup_detected_
+                       /* Exit gadget mode clock gating. */
+                       if (hsotg->params.power_down ==
+-                          DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
++                          DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended &&
++                          !hsotg->params.no_clock_gating)
+                               dwc2_gadget_exit_clock_gating(hsotg, 0);
+               } else {
+                       /* Change to L0 state */
+@@ -425,7 +427,8 @@ static void dwc2_handle_wakeup_detected_
+                       }
+                       if (hsotg->params.power_down ==
+-                          DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
++                          DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended &&
++                          !hsotg->params.no_clock_gating)
+                               dwc2_host_exit_clock_gating(hsotg, 1);
+                       /*
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -3727,6 +3727,12 @@ irq_retry:
+               if (hsotg->in_ppd && hsotg->lx_state == DWC2_L2)
+                       dwc2_exit_partial_power_down(hsotg, 0, true);
++              /* Exit gadget mode clock gating. */
++              if (hsotg->params.power_down ==
++                  DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended &&
++                  !hsotg->params.no_clock_gating)
++                      dwc2_gadget_exit_clock_gating(hsotg, 0);
++
+               hsotg->lx_state = DWC2_L0;
+       }
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -4657,7 +4657,7 @@ static int _dwc2_hcd_urb_enqueue(struct
+       }
+       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE &&
+-          hsotg->bus_suspended) {
++          hsotg->bus_suspended && !hsotg->params.no_clock_gating) {
+               if (dwc2_is_device_mode(hsotg))
+                       dwc2_gadget_exit_clock_gating(hsotg, 0);
+               else
+--- a/drivers/usb/dwc2/platform.c
++++ b/drivers/usb/dwc2/platform.c
+@@ -331,7 +331,7 @@ static void dwc2_driver_remove(struct pl
+       /* Exit clock gating when driver is removed. */
+       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE &&
+-          hsotg->bus_suspended) {
++          hsotg->bus_suspended && !hsotg->params.no_clock_gating) {
+               if (dwc2_is_device_mode(hsotg))
+                       dwc2_gadget_exit_clock_gating(hsotg, 0);
+               else
diff --git a/queue-6.6/usb-dwc2-gadget-lpm-flow-fix.patch b/queue-6.6/usb-dwc2-gadget-lpm-flow-fix.patch
new file mode 100644 (file)
index 0000000..140619d
--- /dev/null
@@ -0,0 +1,150 @@
+From 5d69a3b54e5a630c90d82a4c2bdce3d53dc78710 Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Wed, 13 Mar 2024 09:22:13 +0000
+Subject: usb: dwc2: gadget: LPM flow fix
+
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+
+commit 5d69a3b54e5a630c90d82a4c2bdce3d53dc78710 upstream.
+
+Added functionality to exit from L1 state by device initiation
+using remote wakeup signaling, in case when function driver queuing
+request while core in L1 state.
+
+Fixes: 273d576c4d41 ("usb: dwc2: gadget: Add functionality to exit from LPM L1 state")
+Fixes: 88b02f2cb1e1 ("usb: dwc2: Add core state checking")
+CC: stable@vger.kernel.org
+Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Link: https://lore.kernel.org/r/b4d9de5382375dddbf7ef6049d9a82066ad87d5d.1710166393.git.Minas.Harutyunyan@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/core.h      |    1 
+ drivers/usb/dwc2/core_intr.c |   65 ++++++++++++++++++++++++++++---------------
+ drivers/usb/dwc2/gadget.c    |    4 ++
+ 3 files changed, 48 insertions(+), 22 deletions(-)
+
+--- a/drivers/usb/dwc2/core.h
++++ b/drivers/usb/dwc2/core.h
+@@ -1336,6 +1336,7 @@ int dwc2_backup_global_registers(struct
+ int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg);
+ void dwc2_enable_acg(struct dwc2_hsotg *hsotg);
++void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg, bool remotewakeup);
+ /* This function should be called on every hardware interrupt. */
+ irqreturn_t dwc2_handle_common_intr(int irq, void *dev);
+--- a/drivers/usb/dwc2/core_intr.c
++++ b/drivers/usb/dwc2/core_intr.c
+@@ -323,10 +323,11 @@ static void dwc2_handle_session_req_intr
+  * @hsotg: Programming view of DWC_otg controller
+  *
+  */
+-static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
++void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg, bool remotewakeup)
+ {
+       u32 glpmcfg;
+-      u32 i = 0;
++      u32 pcgctl;
++      u32 dctl;
+       if (hsotg->lx_state != DWC2_L1) {
+               dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n");
+@@ -335,37 +336,57 @@ static void dwc2_wakeup_from_lpm_l1(stru
+       glpmcfg = dwc2_readl(hsotg, GLPMCFG);
+       if (dwc2_is_device_mode(hsotg)) {
+-              dev_dbg(hsotg->dev, "Exit from L1 state\n");
++              dev_dbg(hsotg->dev, "Exit from L1 state, remotewakeup=%d\n", remotewakeup);
+               glpmcfg &= ~GLPMCFG_ENBLSLPM;
+-              glpmcfg &= ~GLPMCFG_HIRD_THRES_EN;
++              glpmcfg &= ~GLPMCFG_HIRD_THRES_MASK;
+               dwc2_writel(hsotg, glpmcfg, GLPMCFG);
+-              do {
+-                      glpmcfg = dwc2_readl(hsotg, GLPMCFG);
+-
+-                      if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK |
+-                                       GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS)))
+-                              break;
++              pcgctl = dwc2_readl(hsotg, PCGCTL);
++              pcgctl &= ~PCGCTL_ENBL_SLEEP_GATING;
++              dwc2_writel(hsotg, pcgctl, PCGCTL);
++
++              glpmcfg = dwc2_readl(hsotg, GLPMCFG);
++              if (glpmcfg & GLPMCFG_ENBESL) {
++                      glpmcfg |= GLPMCFG_RSTRSLPSTS;
++                      dwc2_writel(hsotg, glpmcfg, GLPMCFG);
++              }
+-                      udelay(1);
+-              } while (++i < 200);
++              if (remotewakeup) {
++                      if (dwc2_hsotg_wait_bit_set(hsotg, GLPMCFG, GLPMCFG_L1RESUMEOK, 1000)) {
++                              dev_warn(hsotg->dev, "%s: timeout GLPMCFG_L1RESUMEOK\n", __func__);
++                              goto fail;
++                              return;
++                      }
++
++                      dctl = dwc2_readl(hsotg, DCTL);
++                      dctl |= DCTL_RMTWKUPSIG;
++                      dwc2_writel(hsotg, dctl, DCTL);
++
++                      if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS, GINTSTS_WKUPINT, 1000)) {
++                              dev_warn(hsotg->dev, "%s: timeout GINTSTS_WKUPINT\n", __func__);
++                              goto fail;
++                              return;
++                      }
++              }
+-              if (i == 200) {
+-                      dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n");
++              glpmcfg = dwc2_readl(hsotg, GLPMCFG);
++              if (glpmcfg & GLPMCFG_COREL1RES_MASK || glpmcfg & GLPMCFG_SLPSTS ||
++                  glpmcfg & GLPMCFG_L1RESUMEOK) {
++                      goto fail;
+                       return;
+               }
+-              dwc2_gadget_init_lpm(hsotg);
++
++              /* Inform gadget to exit from L1 */
++              call_gadget(hsotg, resume);
++              /* Change to L0 state */
++              hsotg->lx_state = DWC2_L0;
++              hsotg->bus_suspended = false;
++fail:         dwc2_gadget_init_lpm(hsotg);
+       } else {
+               /* TODO */
+               dev_err(hsotg->dev, "Host side LPM is not supported.\n");
+               return;
+       }
+-
+-      /* Change to L0 state */
+-      hsotg->lx_state = DWC2_L0;
+-
+-      /* Inform gadget to exit from L1 */
+-      call_gadget(hsotg, resume);
+ }
+ /*
+@@ -386,7 +407,7 @@ static void dwc2_handle_wakeup_detected_
+       dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
+       if (hsotg->lx_state == DWC2_L1) {
+-              dwc2_wakeup_from_lpm_l1(hsotg);
++              dwc2_wakeup_from_lpm_l1(hsotg, false);
+               return;
+       }
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -1415,6 +1415,10 @@ static int dwc2_hsotg_ep_queue(struct us
+               ep->name, req, req->length, req->buf, req->no_interrupt,
+               req->zero, req->short_not_ok);
++      if (hs->lx_state == DWC2_L1) {
++              dwc2_wakeup_from_lpm_l1(hs, true);
++      }
++
+       /* Prevent new request submission when controller is suspended */
+       if (hs->lx_state != DWC2_L0) {
+               dev_dbg(hs->dev, "%s: submit request only in active state\n",
diff --git a/queue-6.6/usb-dwc2-host-fix-hibernation-flow.patch b/queue-6.6/usb-dwc2-host-fix-hibernation-flow.patch
new file mode 100644 (file)
index 0000000..b7ebbf5
--- /dev/null
@@ -0,0 +1,94 @@
+From 3c7b9856a82227db01a20171d2e24c7ce305d59b Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Wed, 13 Mar 2024 09:21:11 +0000
+Subject: usb: dwc2: host: Fix hibernation flow
+
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+
+commit 3c7b9856a82227db01a20171d2e24c7ce305d59b upstream.
+
+Added to backup/restore registers HFLBADDR, HCCHARi, HCSPLTi,
+HCTSIZi, HCDMAi and HCDMABi.
+
+Fixes: 58e52ff6a6c3 ("usb: dwc2: Move register save and restore functions")
+Fixes: d17ee77b3044 ("usb: dwc2: add controller hibernation support")
+CC: stable@vger.kernel.org
+Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Link: https://lore.kernel.org/r/c2d10ee6098b9b009a8e94191e046004747d3bdd.1708945444.git.Minas.Harutyunyan@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/core.h |   12 ++++++++++++
+ drivers/usb/dwc2/hcd.c  |   18 ++++++++++++++++--
+ 2 files changed, 28 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc2/core.h
++++ b/drivers/usb/dwc2/core.h
+@@ -729,8 +729,14 @@ struct dwc2_dregs_backup {
+  * struct dwc2_hregs_backup - Holds host registers state before
+  * entering partial power down
+  * @hcfg:             Backup of HCFG register
++ * @hflbaddr:         Backup of HFLBADDR register
+  * @haintmsk:         Backup of HAINTMSK register
++ * @hcchar:           Backup of HCCHAR register
++ * @hcsplt:           Backup of HCSPLT register
+  * @hcintmsk:         Backup of HCINTMSK register
++ * @hctsiz:           Backup of HCTSIZ register
++ * @hdma:             Backup of HCDMA register
++ * @hcdmab:           Backup of HCDMAB register
+  * @hprt0:            Backup of HPTR0 register
+  * @hfir:             Backup of HFIR register
+  * @hptxfsiz:         Backup of HPTXFSIZ register
+@@ -738,8 +744,14 @@ struct dwc2_dregs_backup {
+  */
+ struct dwc2_hregs_backup {
+       u32 hcfg;
++      u32 hflbaddr;
+       u32 haintmsk;
++      u32 hcchar[MAX_EPS_CHANNELS];
++      u32 hcsplt[MAX_EPS_CHANNELS];
+       u32 hcintmsk[MAX_EPS_CHANNELS];
++      u32 hctsiz[MAX_EPS_CHANNELS];
++      u32 hcidma[MAX_EPS_CHANNELS];
++      u32 hcidmab[MAX_EPS_CHANNELS];
+       u32 hprt0;
+       u32 hfir;
+       u32 hptxfsiz;
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -5406,9 +5406,16 @@ int dwc2_backup_host_registers(struct dw
+       /* Backup Host regs */
+       hr = &hsotg->hr_backup;
+       hr->hcfg = dwc2_readl(hsotg, HCFG);
++      hr->hflbaddr = dwc2_readl(hsotg, HFLBADDR);
+       hr->haintmsk = dwc2_readl(hsotg, HAINTMSK);
+-      for (i = 0; i < hsotg->params.host_channels; ++i)
++      for (i = 0; i < hsotg->params.host_channels; ++i) {
++              hr->hcchar[i] = dwc2_readl(hsotg, HCCHAR(i));
++              hr->hcsplt[i] = dwc2_readl(hsotg, HCSPLT(i));
+               hr->hcintmsk[i] = dwc2_readl(hsotg, HCINTMSK(i));
++              hr->hctsiz[i] = dwc2_readl(hsotg, HCTSIZ(i));
++              hr->hcidma[i] = dwc2_readl(hsotg, HCDMA(i));
++              hr->hcidmab[i] = dwc2_readl(hsotg, HCDMAB(i));
++      }
+       hr->hprt0 = dwc2_read_hprt0(hsotg);
+       hr->hfir = dwc2_readl(hsotg, HFIR);
+@@ -5442,10 +5449,17 @@ int dwc2_restore_host_registers(struct d
+       hr->valid = false;
+       dwc2_writel(hsotg, hr->hcfg, HCFG);
++      dwc2_writel(hsotg, hr->hflbaddr, HFLBADDR);
+       dwc2_writel(hsotg, hr->haintmsk, HAINTMSK);
+-      for (i = 0; i < hsotg->params.host_channels; ++i)
++      for (i = 0; i < hsotg->params.host_channels; ++i) {
++              dwc2_writel(hsotg, hr->hcchar[i], HCCHAR(i));
++              dwc2_writel(hsotg, hr->hcsplt[i], HCSPLT(i));
+               dwc2_writel(hsotg, hr->hcintmsk[i], HCINTMSK(i));
++              dwc2_writel(hsotg, hr->hctsiz[i], HCTSIZ(i));
++              dwc2_writel(hsotg, hr->hcidma[i], HCDMA(i));
++              dwc2_writel(hsotg, hr->hcidmab[i], HCDMAB(i));
++      }
+       dwc2_writel(hsotg, hr->hprt0, HPRT0);
+       dwc2_writel(hsotg, hr->hfir, HFIR);
diff --git a/queue-6.6/usb-dwc2-host-fix-isoc-flow-in-ddma-mode.patch b/queue-6.6/usb-dwc2-host-fix-isoc-flow-in-ddma-mode.patch
new file mode 100644 (file)
index 0000000..cc27819
--- /dev/null
@@ -0,0 +1,134 @@
+From b258e42688501cadb1a6dd658d6f015df9f32d8f Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Wed, 13 Mar 2024 09:21:32 +0000
+Subject: usb: dwc2: host: Fix ISOC flow in DDMA mode
+
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+
+commit b258e42688501cadb1a6dd658d6f015df9f32d8f upstream.
+
+Fixed ISOC completion flow in DDMA mode. Added isoc
+descriptor actual length value and update urb's start_frame
+value.
+Fixed initialization of ISOC DMA descriptors flow.
+
+Fixes: 56f5b1cff22a ("staging: Core files for the DWC2 driver")
+Fixes: 20f2eb9c4cf8 ("staging: dwc2: add microframe scheduler from downstream Pi kernel")
+Fixes: c17b337c1ea4 ("usb: dwc2: host: program descriptor for next frame")
+Fixes: dc4c76e7b22c ("staging: HCD descriptor DMA support for the DWC2 driver")
+Fixes: 762d3a1a9cd7 ("usb: dwc2: host: process all completed urbs")
+CC: stable@vger.kernel.org
+Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Link: https://lore.kernel.org/r/a8b1e1711cc6cabfb45d92ede12e35445c66f06c.1708944698.git.Minas.Harutyunyan@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/hcd.c      |   12 ++++++++++--
+ drivers/usb/dwc2/hcd_ddma.c |   17 +++++++++++------
+ drivers/usb/dwc2/hw.h       |    2 +-
+ 3 files changed, 22 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -2701,8 +2701,11 @@ enum dwc2_transaction_type dwc2_hcd_sele
+                       hsotg->available_host_channels--;
+               }
+               qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
+-              if (dwc2_assign_and_init_hc(hsotg, qh))
++              if (dwc2_assign_and_init_hc(hsotg, qh)) {
++                      if (hsotg->params.uframe_sched)
++                              hsotg->available_host_channels++;
+                       break;
++              }
+               /*
+                * Move the QH from the periodic ready schedule to the
+@@ -2735,8 +2738,11 @@ enum dwc2_transaction_type dwc2_hcd_sele
+                       hsotg->available_host_channels--;
+               }
+-              if (dwc2_assign_and_init_hc(hsotg, qh))
++              if (dwc2_assign_and_init_hc(hsotg, qh)) {
++                      if (hsotg->params.uframe_sched)
++                              hsotg->available_host_channels++;
+                       break;
++              }
+               /*
+                * Move the QH from the non-periodic inactive schedule to the
+@@ -4143,6 +4149,8 @@ void dwc2_host_complete(struct dwc2_hsot
+                        urb->actual_length);
+       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
++              if (!hsotg->params.dma_desc_enable)
++                      urb->start_frame = qtd->qh->start_active_frame;
+               urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
+               for (i = 0; i < urb->number_of_packets; ++i) {
+                       urb->iso_frame_desc[i].actual_length =
+--- a/drivers/usb/dwc2/hcd_ddma.c
++++ b/drivers/usb/dwc2/hcd_ddma.c
+@@ -559,7 +559,7 @@ static void dwc2_init_isoc_dma_desc(stru
+       idx = qh->td_last;
+       inc = qh->host_interval;
+       hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
+-      cur_idx = dwc2_frame_list_idx(hsotg->frame_number);
++      cur_idx = idx;
+       next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed);
+       /*
+@@ -866,6 +866,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(
+ {
+       struct dwc2_dma_desc *dma_desc;
+       struct dwc2_hcd_iso_packet_desc *frame_desc;
++      u16 frame_desc_idx;
++      struct urb *usb_urb = qtd->urb->priv;
+       u16 remain = 0;
+       int rc = 0;
+@@ -878,8 +880,11 @@ static int dwc2_cmpl_host_isoc_dma_desc(
+                               DMA_FROM_DEVICE);
+       dma_desc = &qh->desc_list[idx];
++      frame_desc_idx = (idx - qtd->isoc_td_first) & (usb_urb->number_of_packets - 1);
+-      frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
++      frame_desc = &qtd->urb->iso_descs[frame_desc_idx];
++      if (idx == qtd->isoc_td_first)
++              usb_urb->start_frame = dwc2_hcd_get_frame_number(hsotg);
+       dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
+       if (chan->ep_is_in)
+               remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >>
+@@ -900,7 +905,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(
+               frame_desc->status = 0;
+       }
+-      if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
++      if (++qtd->isoc_frame_index == usb_urb->number_of_packets) {
+               /*
+                * urb->status is not used for isoc transfers here. The
+                * individual frame_desc status are used instead.
+@@ -1005,11 +1010,11 @@ static void dwc2_complete_isoc_xfer_ddma
+                               return;
+                       idx = dwc2_desclist_idx_inc(idx, qh->host_interval,
+                                                   chan->speed);
+-                      if (!rc)
++                      if (rc == 0)
+                               continue;
+-                      if (rc == DWC2_CMPL_DONE)
+-                              break;
++                      if (rc == DWC2_CMPL_DONE || rc == DWC2_CMPL_STOP)
++                              goto stop_scan;
+                       /* rc == DWC2_CMPL_STOP */
+--- a/drivers/usb/dwc2/hw.h
++++ b/drivers/usb/dwc2/hw.h
+@@ -698,7 +698,7 @@
+ #define TXSTS_QTOP_TOKEN_MASK         (0x3 << 25)
+ #define TXSTS_QTOP_TOKEN_SHIFT                25
+ #define TXSTS_QTOP_TERMINATE          BIT(24)
+-#define TXSTS_QSPCAVAIL_MASK          (0xff << 16)
++#define TXSTS_QSPCAVAIL_MASK          (0x7f << 16)
+ #define TXSTS_QSPCAVAIL_SHIFT         16
+ #define TXSTS_FSPCAVAIL_MASK          (0xffff << 0)
+ #define TXSTS_FSPCAVAIL_SHIFT         0
diff --git a/queue-6.6/usb-dwc2-host-fix-remote-wakeup-from-hibernation.patch b/queue-6.6/usb-dwc2-host-fix-remote-wakeup-from-hibernation.patch
new file mode 100644 (file)
index 0000000..cc2cf8a
--- /dev/null
@@ -0,0 +1,66 @@
+From bae2bc73a59c200db53b6c15fb26bb758e2c6108 Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Wed, 13 Mar 2024 09:21:21 +0000
+Subject: usb: dwc2: host: Fix remote wakeup from hibernation
+
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+
+commit bae2bc73a59c200db53b6c15fb26bb758e2c6108 upstream.
+
+Starting from core v4.30a changed order of programming
+GPWRDN_PMUACTV to 0 in case of exit from hibernation on
+remote wakeup signaling from device.
+
+Fixes: c5c403dc4336 ("usb: dwc2: Add host/device hibernation functions")
+CC: stable@vger.kernel.org
+Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Link: https://lore.kernel.org/r/99385ec55ce73445b6fbd0f471c9bd40eb1c9b9e.1708939799.git.Minas.Harutyunyan@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/core.h |    1 +
+ drivers/usb/dwc2/hcd.c  |   17 +++++++++++++----
+ 2 files changed, 14 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/dwc2/core.h
++++ b/drivers/usb/dwc2/core.h
+@@ -1086,6 +1086,7 @@ struct dwc2_hsotg {
+       bool needs_byte_swap;
+       /* DWC OTG HW Release versions */
++#define DWC2_CORE_REV_4_30a   0x4f54430a
+ #define DWC2_CORE_REV_2_71a   0x4f54271a
+ #define DWC2_CORE_REV_2_72a     0x4f54272a
+ #define DWC2_CORE_REV_2_80a   0x4f54280a
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -5610,10 +5610,12 @@ int dwc2_host_exit_hibernation(struct dw
+       dwc2_writel(hsotg, hr->hcfg, HCFG);
+       /* De-assert Wakeup Logic */
+-      gpwrdn = dwc2_readl(hsotg, GPWRDN);
+-      gpwrdn &= ~GPWRDN_PMUACTV;
+-      dwc2_writel(hsotg, gpwrdn, GPWRDN);
+-      udelay(10);
++      if (!(rem_wakeup && hsotg->hw_params.snpsid >= DWC2_CORE_REV_4_30a)) {
++              gpwrdn = dwc2_readl(hsotg, GPWRDN);
++              gpwrdn &= ~GPWRDN_PMUACTV;
++              dwc2_writel(hsotg, gpwrdn, GPWRDN);
++              udelay(10);
++      }
+       hprt0 = hr->hprt0;
+       hprt0 |= HPRT0_PWR;
+@@ -5638,6 +5640,13 @@ int dwc2_host_exit_hibernation(struct dw
+               hprt0 |= HPRT0_RES;
+               dwc2_writel(hsotg, hprt0, HPRT0);
++              /* De-assert Wakeup Logic */
++              if ((rem_wakeup && hsotg->hw_params.snpsid >= DWC2_CORE_REV_4_30a)) {
++                      gpwrdn = dwc2_readl(hsotg, GPWRDN);
++                      gpwrdn &= ~GPWRDN_PMUACTV;
++                      dwc2_writel(hsotg, gpwrdn, GPWRDN);
++                      udelay(10);
++              }
+               /* Wait for Resume time and then program HPRT again */
+               mdelay(100);
+               hprt0 &= ~HPRT0_RES;
diff --git a/queue-6.6/usb-dwc3-properly-set-system-wakeup.patch b/queue-6.6/usb-dwc3-properly-set-system-wakeup.patch
new file mode 100644 (file)
index 0000000..ce68488
--- /dev/null
@@ -0,0 +1,128 @@
+From f9aa41130ac69d13a53ce2a153ca79c70d43f39c Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Fri, 8 Mar 2024 02:40:25 +0000
+Subject: usb: dwc3: Properly set system wakeup
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit f9aa41130ac69d13a53ce2a153ca79c70d43f39c upstream.
+
+If the device is configured for system wakeup, then make sure that the
+xHCI driver knows about it and make sure to permit wakeup only at the
+appropriate time.
+
+For host mode, if the controller goes through the dwc3 code path, then a
+child xHCI platform device is created. Make sure the platform device
+also inherits the wakeup setting for xHCI to enable remote wakeup.
+
+For device mode, make sure to disable system wakeup if no gadget driver
+is bound. We may experience unwanted system wakeup due to the wakeup
+signal from the controller PMU detecting connection/disconnection when
+in low power (D3). E.g. In the case of Steam Deck, the PCI PME prevents
+the system staying in suspend.
+
+Cc: stable@vger.kernel.org
+Reported-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
+Closes: https://lore.kernel.org/linux-usb/70a7692d-647c-9be7-00a6-06fc60f77294@igalia.com/T/#mf00d6669c2eff7b308d1162acd1d66c09f0853c7
+Fixes: d07e8819a03d ("usb: dwc3: add xHCI Host support")
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Tested-by: Sanath S <Sanath.S@amd.com>
+Tested-by: Guilherme G. Piccoli <gpiccoli@igalia.com> # Steam Deck
+Link: https://lore.kernel.org/r/667cfda7009b502e08462c8fb3f65841d103cc0a.1709865476.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/core.c   |    2 ++
+ drivers/usb/dwc3/core.h   |    2 ++
+ drivers/usb/dwc3/gadget.c |   10 ++++++++++
+ drivers/usb/dwc3/host.c   |   11 +++++++++++
+ 4 files changed, 25 insertions(+)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1493,6 +1493,8 @@ static void dwc3_get_properties(struct d
+       else
+               dwc->sysdev = dwc->dev;
++      dwc->sys_wakeup = device_may_wakeup(dwc->sysdev);
++
+       ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name);
+       if (ret >= 0) {
+               dwc->usb_psy = power_supply_get_by_name(usb_psy_name);
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -1123,6 +1123,7 @@ struct dwc3_scratchpad_array {
+  *    3       - Reserved
+  * @dis_metastability_quirk: set to disable metastability quirk.
+  * @dis_split_quirk: set to disable split boundary.
++ * @sys_wakeup: set if the device may do system wakeup.
+  * @wakeup_configured: set if the device is configured for remote wakeup.
+  * @suspended: set to track suspend event due to U3/L2.
+  * @imod_interval: set the interrupt moderation interval in 250ns
+@@ -1344,6 +1345,7 @@ struct dwc3 {
+       unsigned                dis_split_quirk:1;
+       unsigned                async_callbacks:1;
++      unsigned                sys_wakeup:1;
+       unsigned                wakeup_configured:1;
+       unsigned                suspended:1;
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2968,6 +2968,9 @@ static int dwc3_gadget_start(struct usb_
+       dwc->gadget_driver      = driver;
+       spin_unlock_irqrestore(&dwc->lock, flags);
++      if (dwc->sys_wakeup)
++              device_wakeup_enable(dwc->sysdev);
++
+       return 0;
+ }
+@@ -2983,6 +2986,9 @@ static int dwc3_gadget_stop(struct usb_g
+       struct dwc3             *dwc = gadget_to_dwc(g);
+       unsigned long           flags;
++      if (dwc->sys_wakeup)
++              device_wakeup_disable(dwc->sysdev);
++
+       spin_lock_irqsave(&dwc->lock, flags);
+       dwc->gadget_driver      = NULL;
+       dwc->max_cfg_eps = 0;
+@@ -4664,6 +4670,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
+       else
+               dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
++      /* No system wakeup if no gadget driver bound */
++      if (dwc->sys_wakeup)
++              device_wakeup_disable(dwc->sysdev);
++
+       return 0;
+ err5:
+--- a/drivers/usb/dwc3/host.c
++++ b/drivers/usb/dwc3/host.c
+@@ -123,6 +123,14 @@ int dwc3_host_init(struct dwc3 *dwc)
+               goto err;
+       }
++      if (dwc->sys_wakeup) {
++              /* Restore wakeup setting if switched from device */
++              device_wakeup_enable(dwc->sysdev);
++
++              /* Pass on wakeup setting to the new xhci platform device */
++              device_init_wakeup(&xhci->dev, true);
++      }
++
+       return 0;
+ err:
+       platform_device_put(xhci);
+@@ -131,6 +139,9 @@ err:
+ void dwc3_host_exit(struct dwc3 *dwc)
+ {
++      if (dwc->sys_wakeup)
++              device_init_wakeup(&dwc->xhci->dev, false);
++
+       platform_device_unregister(dwc->xhci);
+       dwc->xhci = NULL;
+ }
diff --git a/queue-6.6/usb-typec-return-size-of-buffer-if-pd_set-operation-succeeds.patch b/queue-6.6/usb-typec-return-size-of-buffer-if-pd_set-operation-succeeds.patch
new file mode 100644 (file)
index 0000000..3f62e8c
--- /dev/null
@@ -0,0 +1,46 @@
+From 53f5094fdf5deacd99b8655df692e9278506724d Mon Sep 17 00:00:00 2001
+From: Kyle Tso <kyletso@google.com>
+Date: Tue, 19 Mar 2024 15:43:09 +0800
+Subject: usb: typec: Return size of buffer if pd_set operation succeeds
+
+From: Kyle Tso <kyletso@google.com>
+
+commit 53f5094fdf5deacd99b8655df692e9278506724d upstream.
+
+The attribute writing should return the number of bytes used from the
+buffer on success.
+
+Fixes: a7cff92f0635 ("usb: typec: USB Power Delivery helpers for ports and partners")
+Cc: stable@vger.kernel.org
+Signed-off-by: Kyle Tso <kyletso@google.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20240319074309.3306579-1-kyletso@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/class.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/typec/class.c
++++ b/drivers/usb/typec/class.c
+@@ -1264,6 +1264,7 @@ static ssize_t select_usb_power_delivery
+ {
+       struct typec_port *port = to_typec_port(dev);
+       struct usb_power_delivery *pd;
++      int ret;
+       if (!port->ops || !port->ops->pd_set)
+               return -EOPNOTSUPP;
+@@ -1272,7 +1273,11 @@ static ssize_t select_usb_power_delivery
+       if (!pd)
+               return -EINVAL;
+-      return port->ops->pd_set(port, pd);
++      ret = port->ops->pd_set(port, pd);
++      if (ret)
++              return ret;
++
++      return size;
+ }
+ static ssize_t select_usb_power_delivery_show(struct device *dev,
diff --git a/queue-6.6/usb-typec-ucsi-ack-unsupported-commands.patch b/queue-6.6/usb-typec-ucsi-ack-unsupported-commands.patch
new file mode 100644 (file)
index 0000000..68ecbb1
--- /dev/null
@@ -0,0 +1,40 @@
+From 6b5c85ddeea77d18c4b69e3bda60e9374a20c304 Mon Sep 17 00:00:00 2001
+From: "Christian A. Ehrhardt" <lk@c--e.de>
+Date: Wed, 20 Mar 2024 08:39:24 +0100
+Subject: usb: typec: ucsi: Ack unsupported commands
+
+From: Christian A. Ehrhardt <lk@c--e.de>
+
+commit 6b5c85ddeea77d18c4b69e3bda60e9374a20c304 upstream.
+
+If a command completes the OPM must send an ack. This applies
+to unsupported commands, too.
+
+Send the required ACK for unsupported commands.
+
+Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
+Cc: stable <stable@kernel.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Link: https://lore.kernel.org/r/20240320073927.1641788-4-lk@c--e.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -138,8 +138,12 @@ static int ucsi_exec_command(struct ucsi
+       if (!(cci & UCSI_CCI_COMMAND_COMPLETE))
+               return -EIO;
+-      if (cci & UCSI_CCI_NOT_SUPPORTED)
++      if (cci & UCSI_CCI_NOT_SUPPORTED) {
++              if (ucsi_acknowledge_command(ucsi) < 0)
++                      dev_err(ucsi->dev,
++                              "ACK of unsupported command failed\n");
+               return -EOPNOTSUPP;
++      }
+       if (cci & UCSI_CCI_ERROR) {
+               if (cmd == UCSI_GET_ERROR_STATUS)
diff --git a/queue-6.6/usb-typec-ucsi-check-for-notifications-after-init.patch b/queue-6.6/usb-typec-ucsi-check-for-notifications-after-init.patch
new file mode 100644 (file)
index 0000000..b3056f2
--- /dev/null
@@ -0,0 +1,64 @@
+From 808a8b9e0b87bbc72bcc1f7ddfe5d04746e7ce56 Mon Sep 17 00:00:00 2001
+From: "Christian A. Ehrhardt" <lk@c--e.de>
+Date: Wed, 20 Mar 2024 08:39:23 +0100
+Subject: usb: typec: ucsi: Check for notifications after init
+
+From: Christian A. Ehrhardt <lk@c--e.de>
+
+commit 808a8b9e0b87bbc72bcc1f7ddfe5d04746e7ce56 upstream.
+
+The completion notification for the final SET_NOTIFICATION_ENABLE
+command during initialization can include a connector change
+notification.  However, at the time this completion notification is
+processed, the ucsi struct is not ready to handle this notification.
+As a result the notification is ignored and the controller
+never sends an interrupt again.
+
+Re-check CCI for a pending connector state change after
+initialization is complete. Adjust the corresponding debug
+message accordingly.
+
+Fixes: 71a1fa0df2a3 ("usb: typec: ucsi: Store the notification mask")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Link: https://lore.kernel.org/r/20240320073927.1641788-3-lk@c--e.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |   10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -955,7 +955,7 @@ void ucsi_connector_change(struct ucsi *
+       struct ucsi_connector *con = &ucsi->connector[num - 1];
+       if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) {
+-              dev_dbg(ucsi->dev, "Bogus connector change event\n");
++              dev_dbg(ucsi->dev, "Early connector change event\n");
+               return;
+       }
+@@ -1352,6 +1352,7 @@ static int ucsi_init(struct ucsi *ucsi)
+ {
+       struct ucsi_connector *con, *connector;
+       u64 command, ntfy;
++      u32 cci;
+       int ret;
+       int i;
+@@ -1404,6 +1405,13 @@ static int ucsi_init(struct ucsi *ucsi)
+       ucsi->connector = connector;
+       ucsi->ntfy = ntfy;
++
++      ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci));
++      if (ret)
++              return ret;
++      if (UCSI_CCI_CONNECTOR(READ_ONCE(cci)))
++              ucsi_connector_change(ucsi, cci);
++
+       return 0;
+ err_unregister:
diff --git a/queue-6.6/usb-typec-ucsi-clear-event_pending-under-ppm-lock.patch b/queue-6.6/usb-typec-ucsi-clear-event_pending-under-ppm-lock.patch
new file mode 100644 (file)
index 0000000..3b45d35
--- /dev/null
@@ -0,0 +1,44 @@
+From 15b2e71b4653b3e13df34695a29ebeee237c5af2 Mon Sep 17 00:00:00 2001
+From: "Christian A. Ehrhardt" <lk@c--e.de>
+Date: Wed, 20 Mar 2024 08:39:22 +0100
+Subject: usb: typec: ucsi: Clear EVENT_PENDING under PPM lock
+
+From: Christian A. Ehrhardt <lk@c--e.de>
+
+commit 15b2e71b4653b3e13df34695a29ebeee237c5af2 upstream.
+
+Suppose we sleep on the PPM lock after clearing the EVENT_PENDING
+bit because the thread for another connector is executing a command.
+In this case the command completion of the other command will still
+report the connector change for our connector.
+
+Clear the EVENT_PENDING bit under the PPM lock to avoid another
+useless call to ucsi_handle_connector_change() in this case.
+
+Fixes: c9aed03a0a68 ("usb: ucsi: Add missing ppm_lock")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Link: https://lore.kernel.org/r/20240320073927.1641788-2-lk@c--e.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -933,11 +933,11 @@ static void ucsi_handle_connector_change
+       if (con->status.change & UCSI_CONSTAT_CAM_CHANGE)
+               ucsi_partner_task(con, ucsi_check_altmodes, 1, 0);
+-      clear_bit(EVENT_PENDING, &con->ucsi->flags);
+-
+       mutex_lock(&ucsi->ppm_lock);
++      clear_bit(EVENT_PENDING, &con->ucsi->flags);
+       ret = ucsi_acknowledge_connector_change(ucsi);
+       mutex_unlock(&ucsi->ppm_lock);
++
+       if (ret)
+               dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret);
diff --git a/queue-6.6/usb-typec-ucsi-clear-ucsi_cci_reset_complete-before-reset.patch b/queue-6.6/usb-typec-ucsi-clear-ucsi_cci_reset_complete-before-reset.patch
new file mode 100644 (file)
index 0000000..8adbc15
--- /dev/null
@@ -0,0 +1,74 @@
+From 3de4f996a0b5412aa451729008130a488f71563e Mon Sep 17 00:00:00 2001
+From: "Christian A. Ehrhardt" <lk@c--e.de>
+Date: Wed, 20 Mar 2024 08:39:26 +0100
+Subject: usb: typec: ucsi: Clear UCSI_CCI_RESET_COMPLETE before reset
+
+From: Christian A. Ehrhardt <lk@c--e.de>
+
+commit 3de4f996a0b5412aa451729008130a488f71563e upstream.
+
+Check the UCSI_CCI_RESET_COMPLETE complete flag before starting
+another reset. Use a UCSI_SET_NOTIFICATION_ENABLE command to clear
+the flag if it is set.
+
+Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
+Cc: stable <stable@kernel.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Link: https://lore.kernel.org/r/20240320073927.1641788-6-lk@c--e.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |   36 +++++++++++++++++++++++++++++++++++-
+ 1 file changed, 35 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -982,13 +982,47 @@ static int ucsi_reset_connector(struct u
+ static int ucsi_reset_ppm(struct ucsi *ucsi)
+ {
+-      u64 command = UCSI_PPM_RESET;
++      u64 command;
+       unsigned long tmo;
+       u32 cci;
+       int ret;
+       mutex_lock(&ucsi->ppm_lock);
++      ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci));
++      if (ret < 0)
++              goto out;
++
++      /*
++       * If UCSI_CCI_RESET_COMPLETE is already set we must clear
++       * the flag before we start another reset. Send a
++       * UCSI_SET_NOTIFICATION_ENABLE command to achieve this.
++       * Ignore a timeout and try the reset anyway if this fails.
++       */
++      if (cci & UCSI_CCI_RESET_COMPLETE) {
++              command = UCSI_SET_NOTIFICATION_ENABLE;
++              ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
++                                           sizeof(command));
++              if (ret < 0)
++                      goto out;
++
++              tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS);
++              do {
++                      ret = ucsi->ops->read(ucsi, UCSI_CCI,
++                                            &cci, sizeof(cci));
++                      if (ret < 0)
++                              goto out;
++                      if (cci & UCSI_CCI_COMMAND_COMPLETE)
++                              break;
++                      if (time_is_before_jiffies(tmo))
++                              break;
++                      msleep(20);
++              } while (1);
++
++              WARN_ON(cci & UCSI_CCI_RESET_COMPLETE);
++      }
++
++      command = UCSI_PPM_RESET;
+       ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
+                                    sizeof(command));
+       if (ret < 0)
diff --git a/queue-6.6/usb-typec-ucsi_acpi-refactor-and-fix-dell-quirk.patch b/queue-6.6/usb-typec-ucsi_acpi-refactor-and-fix-dell-quirk.patch
new file mode 100644 (file)
index 0000000..89f8586
--- /dev/null
@@ -0,0 +1,163 @@
+From 6aaceb7d9cd00f3e065dc4b054ecfe52c5253b03 Mon Sep 17 00:00:00 2001
+From: "Christian A. Ehrhardt" <lk@c--e.de>
+Date: Wed, 20 Mar 2024 08:39:25 +0100
+Subject: usb: typec: ucsi_acpi: Refactor and fix DELL quirk
+
+From: Christian A. Ehrhardt <lk@c--e.de>
+
+commit 6aaceb7d9cd00f3e065dc4b054ecfe52c5253b03 upstream.
+
+Some DELL systems don't like UCSI_ACK_CC_CI commands with the
+UCSI_ACK_CONNECTOR_CHANGE but not the UCSI_ACK_COMMAND_COMPLETE
+bit set. The current quirk still leaves room for races because
+it requires two consecutive ACK commands to be sent.
+
+Refactor and significantly simplify the quirk to fix this:
+Send a dummy command and bundle the connector change ack with the
+command completion ack in a single UCSI_ACK_CC_CI command.
+This removes the need to probe for the quirk.
+
+While there define flag bits for struct ucsi_acpi->flags in ucsi_acpi.c
+and don't re-use definitions from ucsi.h for struct ucsi->flags.
+
+Fixes: f3be347ea42d ("usb: ucsi_acpi: Quirk to ack a connector change ack cmd")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Link: https://lore.kernel.org/r/20240320073927.1641788-5-lk@c--e.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi_acpi.c |   71 ++++++++++++++++---------------------
+ 1 file changed, 31 insertions(+), 40 deletions(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
++++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
+@@ -23,10 +23,11 @@ struct ucsi_acpi {
+       void *base;
+       struct completion complete;
+       unsigned long flags;
++#define UCSI_ACPI_SUPPRESS_EVENT      0
++#define UCSI_ACPI_COMMAND_PENDING     1
++#define UCSI_ACPI_ACK_PENDING         2
+       guid_t guid;
+       u64 cmd;
+-      bool dell_quirk_probed;
+-      bool dell_quirk_active;
+ };
+ static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func)
+@@ -79,9 +80,9 @@ static int ucsi_acpi_sync_write(struct u
+       int ret;
+       if (ack)
+-              set_bit(ACK_PENDING, &ua->flags);
++              set_bit(UCSI_ACPI_ACK_PENDING, &ua->flags);
+       else
+-              set_bit(COMMAND_PENDING, &ua->flags);
++              set_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags);
+       ret = ucsi_acpi_async_write(ucsi, offset, val, val_len);
+       if (ret)
+@@ -92,9 +93,9 @@ static int ucsi_acpi_sync_write(struct u
+ out_clear_bit:
+       if (ack)
+-              clear_bit(ACK_PENDING, &ua->flags);
++              clear_bit(UCSI_ACPI_ACK_PENDING, &ua->flags);
+       else
+-              clear_bit(COMMAND_PENDING, &ua->flags);
++              clear_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags);
+       return ret;
+ }
+@@ -129,51 +130,40 @@ static const struct ucsi_operations ucsi
+ };
+ /*
+- * Some Dell laptops expect that an ACK command with the
+- * UCSI_ACK_CONNECTOR_CHANGE bit set is followed by a (separate)
+- * ACK command that only has the UCSI_ACK_COMMAND_COMPLETE bit set.
+- * If this is not done events are not delivered to OSPM and
+- * subsequent commands will timeout.
++ * Some Dell laptops don't like ACK commands with the
++ * UCSI_ACK_CONNECTOR_CHANGE but not the UCSI_ACK_COMMAND_COMPLETE
++ * bit set. To work around this send a dummy command and bundle the
++ * UCSI_ACK_CONNECTOR_CHANGE with the UCSI_ACK_COMMAND_COMPLETE
++ * for the dummy command.
+  */
+ static int
+ ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset,
+                    const void *val, size_t val_len)
+ {
+       struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
+-      u64 cmd = *(u64 *)val, ack = 0;
++      u64 cmd = *(u64 *)val;
++      u64 dummycmd = UCSI_GET_CAPABILITY;
+       int ret;
+-      if (UCSI_COMMAND(cmd) == UCSI_ACK_CC_CI &&
+-          cmd & UCSI_ACK_CONNECTOR_CHANGE)
+-              ack = UCSI_ACK_CC_CI | UCSI_ACK_COMMAND_COMPLETE;
++      if (cmd == (UCSI_ACK_CC_CI | UCSI_ACK_CONNECTOR_CHANGE)) {
++              cmd |= UCSI_ACK_COMMAND_COMPLETE;
+-      ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len);
+-      if (ret != 0)
+-              return ret;
+-      if (ack == 0)
+-              return ret;
+-
+-      if (!ua->dell_quirk_probed) {
+-              ua->dell_quirk_probed = true;
++              /*
++               * The UCSI core thinks it is sending a connector change ack
++               * and will accept new connector change events. We don't want
++               * this to happen for the dummy command as its response will
++               * still report the very event that the core is trying to clear.
++               */
++              set_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags);
++              ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &dummycmd,
++                                         sizeof(dummycmd));
++              clear_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags);
+-              cmd = UCSI_GET_CAPABILITY;
+-              ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd,
+-                                         sizeof(cmd));
+-              if (ret == 0)
+-                      return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL,
+-                                                  &ack, sizeof(ack));
+-              if (ret != -ETIMEDOUT)
++              if (ret < 0)
+                       return ret;
+-
+-              ua->dell_quirk_active = true;
+-              dev_err(ua->dev, "Firmware bug: Additional ACK required after ACKing a connector change.\n");
+-              dev_err(ua->dev, "Firmware bug: Enabling workaround\n");
+       }
+-      if (!ua->dell_quirk_active)
+-              return ret;
+-
+-      return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack));
++      return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
+ }
+ static const struct ucsi_operations ucsi_dell_ops = {
+@@ -209,13 +199,14 @@ static void ucsi_acpi_notify(acpi_handle
+       if (ret)
+               return;
+-      if (UCSI_CCI_CONNECTOR(cci))
++      if (UCSI_CCI_CONNECTOR(cci) &&
++          !test_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags))
+               ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci));
+       if (cci & UCSI_CCI_ACK_COMPLETE && test_bit(ACK_PENDING, &ua->flags))
+               complete(&ua->complete);
+       if (cci & UCSI_CCI_COMMAND_COMPLETE &&
+-          test_bit(COMMAND_PENDING, &ua->flags))
++          test_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags))
+               complete(&ua->complete);
+ }
diff --git a/queue-6.6/usb-udc-remove-warning-when-queue-disabled-ep.patch b/queue-6.6/usb-udc-remove-warning-when-queue-disabled-ep.patch
new file mode 100644 (file)
index 0000000..1028f20
--- /dev/null
@@ -0,0 +1,44 @@
+From 2a587a035214fa1b5ef598aea0b81848c5b72e5e Mon Sep 17 00:00:00 2001
+From: yuan linyu <yuanlinyu@hihonor.com>
+Date: Fri, 15 Mar 2024 10:01:44 +0800
+Subject: usb: udc: remove warning when queue disabled ep
+
+From: yuan linyu <yuanlinyu@hihonor.com>
+
+commit 2a587a035214fa1b5ef598aea0b81848c5b72e5e upstream.
+
+It is possible trigger below warning message from mass storage function,
+
+WARNING: CPU: 6 PID: 3839 at drivers/usb/gadget/udc/core.c:294 usb_ep_queue+0x7c/0x104
+pc : usb_ep_queue+0x7c/0x104
+lr : fsg_main_thread+0x494/0x1b3c
+
+Root cause is mass storage function try to queue request from main thread,
+but other thread may already disable ep when function disable.
+
+As there is no function failure in the driver, in order to avoid effort
+to fix warning, change WARN_ON_ONCE() in usb_ep_queue() to pr_debug().
+
+Suggested-by: Alan Stern <stern@rowland.harvard.edu>
+Cc: stable@vger.kernel.org
+Signed-off-by: yuan linyu <yuanlinyu@hihonor.com>
+Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20240315020144.2715575-1-yuanlinyu@hihonor.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/udc/core.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -292,7 +292,9 @@ int usb_ep_queue(struct usb_ep *ep,
+ {
+       int ret = 0;
+-      if (WARN_ON_ONCE(!ep->enabled && ep->address)) {
++      if (!ep->enabled && ep->address) {
++              pr_debug("USB gadget: queue request to disabled ep 0x%x (%s)\n",
++                               ep->address, ep->name);
+               ret = -ESHUTDOWN;
+               goto out;
+       }