--- /dev/null
+From 860fa1e6ed52a6a96da778319b84d7d917664094 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 02:43:39 +0300
+Subject: Bluetooth: hci_core: Fix use-after-free in vhci_flush()
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+commit 1d6123102e9fbedc8d25bf4731da6d513173e49e upstream.
+
+syzbot reported use-after-free in vhci_flush() without repro. [0]
+
+>From the splat, a thread close()d a vhci file descriptor while
+its device was being used by iotcl() on another thread.
+
+Once the last fd refcnt is released, vhci_release() calls
+hci_unregister_dev(), hci_free_dev(), and kfree() for struct
+vhci_data, which is set to hci_dev->dev->driver_data.
+
+The problem is that there is no synchronisation after unlinking
+hdev from hci_dev_list in hci_unregister_dev(). There might be
+another thread still accessing the hdev which was fetched before
+the unlink operation.
+
+We can use SRCU for such synchronisation.
+
+Let's run hci_dev_reset() under SRCU and wait for its completion
+in hci_unregister_dev().
+
+Another option would be to restore hci_dev->destruct(), which was
+removed in commit 587ae086f6e4 ("Bluetooth: Remove unused
+hci-destruct cb"). However, this would not be a good solution, as
+we should not run hci_unregister_dev() while there are in-flight
+ioctl() requests, which could lead to another data-race KCSAN splat.
+
+Note that other drivers seem to have the same problem, for exmaple,
+virtbt_remove().
+
+[0]:
+BUG: KASAN: slab-use-after-free in skb_queue_empty_lockless include/linux/skbuff.h:1891 [inline]
+BUG: KASAN: slab-use-after-free in skb_queue_purge_reason+0x99/0x360 net/core/skbuff.c:3937
+Read of size 8 at addr ffff88807cb8d858 by task syz.1.219/6718
+
+CPU: 1 UID: 0 PID: 6718 Comm: syz.1.219 Not tainted 6.16.0-rc1-syzkaller-00196-g08207f42d3ff #0 PREEMPT(full)
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
+ print_address_description mm/kasan/report.c:408 [inline]
+ print_report+0xd2/0x2b0 mm/kasan/report.c:521
+ kasan_report+0x118/0x150 mm/kasan/report.c:634
+ skb_queue_empty_lockless include/linux/skbuff.h:1891 [inline]
+ skb_queue_purge_reason+0x99/0x360 net/core/skbuff.c:3937
+ skb_queue_purge include/linux/skbuff.h:3368 [inline]
+ vhci_flush+0x44/0x50 drivers/bluetooth/hci_vhci.c:69
+ hci_dev_do_reset net/bluetooth/hci_core.c:552 [inline]
+ hci_dev_reset+0x420/0x5c0 net/bluetooth/hci_core.c:592
+ sock_do_ioctl+0xd9/0x300 net/socket.c:1190
+ sock_ioctl+0x576/0x790 net/socket.c:1311
+ vfs_ioctl fs/ioctl.c:51 [inline]
+ __do_sys_ioctl fs/ioctl.c:907 [inline]
+ __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:893
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7fcf5b98e929
+Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007fcf5c7b9038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+RAX: ffffffffffffffda RBX: 00007fcf5bbb6160 RCX: 00007fcf5b98e929
+RDX: 0000000000000000 RSI: 00000000400448cb RDI: 0000000000000009
+RBP: 00007fcf5ba10b39 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 0000000000000000 R14: 00007fcf5bbb6160 R15: 00007ffd6353d528
+ </TASK>
+
+Allocated by task 6535:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3e/0x80 mm/kasan/common.c:68
+ poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
+ __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:394
+ kasan_kmalloc include/linux/kasan.h:260 [inline]
+ __kmalloc_cache_noprof+0x230/0x3d0 mm/slub.c:4359
+ kmalloc_noprof include/linux/slab.h:905 [inline]
+ kzalloc_noprof include/linux/slab.h:1039 [inline]
+ vhci_open+0x57/0x360 drivers/bluetooth/hci_vhci.c:635
+ misc_open+0x2bc/0x330 drivers/char/misc.c:161
+ chrdev_open+0x4c9/0x5e0 fs/char_dev.c:414
+ do_dentry_open+0xdf0/0x1970 fs/open.c:964
+ vfs_open+0x3b/0x340 fs/open.c:1094
+ do_open fs/namei.c:3887 [inline]
+ path_openat+0x2ee5/0x3830 fs/namei.c:4046
+ do_filp_open+0x1fa/0x410 fs/namei.c:4073
+ do_sys_openat2+0x121/0x1c0 fs/open.c:1437
+ do_sys_open fs/open.c:1452 [inline]
+ __do_sys_openat fs/open.c:1468 [inline]
+ __se_sys_openat fs/open.c:1463 [inline]
+ __x64_sys_openat+0x138/0x170 fs/open.c:1463
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Freed by task 6535:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3e/0x80 mm/kasan/common.c:68
+ kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576
+ poison_slab_object mm/kasan/common.c:247 [inline]
+ __kasan_slab_free+0x62/0x70 mm/kasan/common.c:264
+ kasan_slab_free include/linux/kasan.h:233 [inline]
+ slab_free_hook mm/slub.c:2381 [inline]
+ slab_free mm/slub.c:4643 [inline]
+ kfree+0x18e/0x440 mm/slub.c:4842
+ vhci_release+0xbc/0xd0 drivers/bluetooth/hci_vhci.c:671
+ __fput+0x44c/0xa70 fs/file_table.c:465
+ task_work_run+0x1d1/0x260 kernel/task_work.c:227
+ exit_task_work include/linux/task_work.h:40 [inline]
+ do_exit+0x6ad/0x22e0 kernel/exit.c:955
+ do_group_exit+0x21c/0x2d0 kernel/exit.c:1104
+ __do_sys_exit_group kernel/exit.c:1115 [inline]
+ __se_sys_exit_group kernel/exit.c:1113 [inline]
+ __x64_sys_exit_group+0x3f/0x40 kernel/exit.c:1113
+ x64_sys_call+0x21ba/0x21c0 arch/x86/include/generated/asm/syscalls_64.h:232
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+The buggy address belongs to the object at ffff88807cb8d800
+ which belongs to the cache kmalloc-1k of size 1024
+The buggy address is located 88 bytes inside of
+ freed 1024-byte region [ffff88807cb8d800, ffff88807cb8dc00)
+
+Fixes: bf18c7118cf8 ("Bluetooth: vhci: Free driver_data on file release")
+Reported-by: syzbot+2faa4825e556199361f9@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=f62d64848fc4c7c30cd6
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Acked-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Vladislav Nikolaev <vlad102nikolaev@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/hci_core.h | 2 ++
+ net/bluetooth/hci_core.c | 34 ++++++++++++++++++++++++++++----
+ 2 files changed, 32 insertions(+), 4 deletions(-)
+
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index fe62943a35ddc9..bc4e2856f23567 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -28,6 +28,7 @@
+ #include <linux/idr.h>
+ #include <linux/leds.h>
+ #include <linux/rculist.h>
++#include <linux/srcu.h>
+
+ #include <net/bluetooth/hci.h>
+ #include <net/bluetooth/hci_sock.h>
+@@ -285,6 +286,7 @@ struct amp_assoc {
+
+ struct hci_dev {
+ struct list_head list;
++ struct srcu_struct srcu;
+ struct mutex lock;
+
+ const char *name;
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 9787a4c551138d..a718e38f3da31a 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -1040,7 +1040,7 @@ static int hci_linkpol_req(struct hci_request *req, unsigned long opt)
+
+ /* Get HCI device by index.
+ * Device is held on return. */
+-struct hci_dev *hci_dev_get(int index)
++static struct hci_dev *__hci_dev_get(int index, int *srcu_index)
+ {
+ struct hci_dev *hdev = NULL, *d;
+
+@@ -1053,6 +1053,8 @@ struct hci_dev *hci_dev_get(int index)
+ list_for_each_entry(d, &hci_dev_list, list) {
+ if (d->id == index) {
+ hdev = hci_dev_hold(d);
++ if (srcu_index)
++ *srcu_index = srcu_read_lock(&d->srcu);
+ break;
+ }
+ }
+@@ -1060,6 +1062,22 @@ struct hci_dev *hci_dev_get(int index)
+ return hdev;
+ }
+
++struct hci_dev *hci_dev_get(int index)
++{
++ return __hci_dev_get(index, NULL);
++}
++
++static struct hci_dev *hci_dev_get_srcu(int index, int *srcu_index)
++{
++ return __hci_dev_get(index, srcu_index);
++}
++
++static void hci_dev_put_srcu(struct hci_dev *hdev, int srcu_index)
++{
++ srcu_read_unlock(&hdev->srcu, srcu_index);
++ hci_dev_put(hdev);
++}
++
+ /* ---- Inquiry support ---- */
+
+ bool hci_discovery_active(struct hci_dev *hdev)
+@@ -1906,9 +1924,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev)
+ int hci_dev_reset(__u16 dev)
+ {
+ struct hci_dev *hdev;
+- int err;
++ int err, srcu_index;
+
+- hdev = hci_dev_get(dev);
++ hdev = hci_dev_get_srcu(dev, &srcu_index);
+ if (!hdev)
+ return -ENODEV;
+
+@@ -1930,7 +1948,7 @@ int hci_dev_reset(__u16 dev)
+ err = hci_dev_do_reset(hdev);
+
+ done:
+- hci_dev_put(hdev);
++ hci_dev_put_srcu(hdev, srcu_index);
+ return err;
+ }
+
+@@ -3596,6 +3614,11 @@ struct hci_dev *hci_alloc_dev(void)
+ if (!hdev)
+ return NULL;
+
++ if (init_srcu_struct(&hdev->srcu)) {
++ kfree(hdev);
++ return NULL;
++ }
++
+ hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
+ hdev->esco_type = (ESCO_HV1);
+ hdev->link_mode = (HCI_LM_ACCEPT);
+@@ -3839,6 +3862,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
+ list_del(&hdev->list);
+ write_unlock(&hci_dev_list_lock);
+
++ synchronize_srcu(&hdev->srcu);
++ cleanup_srcu_struct(&hdev->srcu);
++
+ cancel_work_sync(&hdev->rx_work);
+ cancel_work_sync(&hdev->cmd_work);
+ cancel_work_sync(&hdev->tx_work);
+--
+2.53.0
+
serial-dz-fix-bootconsole-message-clobbering-at-chip-reset.patch
serial-zs-fix-bootconsole-handover-lockup.patch
serial-zs-switch-to-using-channel-reset.patch
+bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch
+usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
+usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
+xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
--- /dev/null
+From 0b0395e2c8c678a2ebba1acd157be548eb6bdad6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 10:36:36 +0200
+Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint
+
+From: Johan Hovold <johan@kernel.org>
+
+commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream.
+
+Make sure that the interrupt-out endpoint max packet size is at least
+eight bytes to avoid user-controlled slab corruption or NULL-pointer
+dereference should a malicious device report a smaller size.
+
+Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size")
+Cc: stable@vger.kernel.org # 2.6.26
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+[ johan: adjust context for 6.18 ]
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/cypress_m8.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 82d2e076ea9a09..e924fb212f5b24 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -447,6 +447,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
+ return -ENODEV;
+ }
+
++ /*
++ * The buffer must be large enough for the one or two-byte header (and
++ * following data), but assume anything smaller than eight bytes is
++ * broken.
++ */
++ if (port->interrupt_out_size < 8)
++ return -EINVAL;
++
+ priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+--
+2.53.0
+
--- /dev/null
+From e85c58daa923c1c46806d3f58a9f584b0d16196a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:07:58 +0200
+Subject: USB: serial: digi_acceleport: fix memory corruption with small
+ endpoints
+
+From: Johan Hovold <johan@kernel.org>
+
+commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream.
+
+Add the missing bulk-out buffer size sanity checks to avoid
+out-of-bounds memory accesses or slab corruption should a malicious
+device report smaller buffers than expected.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index 0d606fa9fdca1a..d03bba38d802d2 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -1229,15 +1229,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
+ static int digi_startup(struct usb_serial *serial)
+ {
+ struct digi_serial *serial_priv;
++ int oob_port_num;
+ int ret;
++ int i;
++
++ /*
++ * The port bulk-out buffers must be large enough for header and
++ * buffered data.
++ */
++ for (i = 0; i < serial->type->num_ports; i++) {
++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2)
++ return -EINVAL;
++ }
++
++ /*
++ * The OOB port bulk-out buffer must be large enough for the two
++ * commands in digi_set_modem_signals().
++ */
++ oob_port_num = serial->type->num_ports;
++ if (serial->port[oob_port_num]->bulk_out_size < 8)
++ return -EINVAL;
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv)
+ return -ENOMEM;
+
+ spin_lock_init(&serial_priv->ds_serial_lock);
+- serial_priv->ds_oob_port_num = serial->type->num_ports;
+- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
++ serial_priv->ds_oob_port_num = oob_port_num;
++ serial_priv->ds_oob_port = serial->port[oob_port_num];
+
+ ret = digi_port_init(serial_priv->ds_oob_port,
+ serial_priv->ds_oob_port_num);
+--
+2.53.0
+
--- /dev/null
+From 05777def7e2d578f109046104d883053f1fd0fbf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:19:18 +0800
+Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug
+
+From: Wei-Cheng Chen <weichengc@nvidia.com>
+
+[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ]
+
+When a USB device is unplugged from the dual-role port, the device-mode
+path in tegra_xhci_id_work() explicitly clears both SS and HS port power
+via direct hub_control ClearPortFeature(POWER) calls. This preempts the
+xHCI controller's normal disconnect processing -- PORT_CSC is never
+generated, the USB core never sees the disconnect, and the device remains
+in its internal tree as a ghost visible in lsusb.
+
+Add an otg_set_port_power flag to control whether the dual-role switch
+path performs explicit port power management. SoCs that need it
+(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and
+beyond) rely on the PHY mode change to handle disconnect naturally and
+skip all port power calls.
+
+Within the port power path, otg_reset_sspi additionally gates the SSPI
+reset sequence on host-mode entry for SoCs that require it.
+
+Flags set per SoC:
+ Tegra124, Tegra186 -> otg_set_port_power
+ Tegra210 -> otg_set_port_power, otg_reset_sspi
+ Tegra194 and later -> (none)
+
+[ Backport to 5.10.y: keep the host-mode snapshot in the existing
+ tegra->lock section, retain pm_runtime_mark_last_busy() in the host
+ port-power path, and omit the newer Tegra234 entry. ]
+
+Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wei-Cheng Chen <weichengc@nvidia.com>
+Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-tegra.c | 78 ++++++++++++++++++++---------------
+ 1 file changed, 44 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
+index e2cd145ed495a1..8b4a6eb8f0b11f 100644
+--- a/drivers/usb/host/xhci-tegra.c
++++ b/drivers/usb/host/xhci-tegra.c
+@@ -208,6 +208,7 @@ struct tegra_xusb_soc {
+ bool has_ipfs;
+ bool lpm_support;
+ bool otg_reset_sspi;
++ bool otg_set_port_power;
+ };
+
+ struct tegra_xusb_context {
+@@ -1161,14 +1162,17 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ struct tegra_xusb_mbox_msg msg;
+ struct phy *phy = tegra_xusb_get_phy(tegra, "usb2",
+ tegra->otg_usb2_port);
++ bool host_mode;
+ u32 status;
+ int ret;
+
+- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off");
+-
+ mutex_lock(&tegra->lock);
+
+- if (tegra->host_mode)
++ host_mode = tegra->host_mode;
++
++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off");
++
++ if (host_mode)
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST);
+ else
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+@@ -1179,42 +1183,44 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ tegra->otg_usb2_port);
+
+ pm_runtime_get_sync(tegra->dev);
+- if (tegra->host_mode) {
+- /* switch to host mode */
+- if (tegra->otg_usb3_port >= 0) {
+- if (tegra->soc->otg_reset_sspi) {
+- /* set PP=0 */
+- tegra_xhci_hc_driver.hub_control(
+- xhci->shared_hcd, GetPortStatus,
+- 0, tegra->otg_usb3_port+1,
+- (char *) &status, sizeof(status));
+- if (status & USB_SS_PORT_STAT_POWER)
+- tegra_xhci_set_port_power(tegra, false,
+- false);
+-
+- /* reset OTG port SSPI */
+- msg.cmd = MBOX_CMD_RESET_SSPI;
+- msg.data = tegra->otg_usb3_port+1;
+-
+- ret = tegra_xusb_mbox_send(tegra, &msg);
+- if (ret < 0) {
+- dev_info(tegra->dev,
+- "failed to RESET_SSPI %d\n",
+- ret);
++ if (tegra->soc->otg_set_port_power) {
++ if (host_mode) {
++ /* switch to host mode */
++ if (tegra->otg_usb3_port >= 0) {
++ if (tegra->soc->otg_reset_sspi) {
++ /* set PP=0 */
++ tegra_xhci_hc_driver.hub_control(
++ xhci->shared_hcd, GetPortStatus,
++ 0, tegra->otg_usb3_port+1,
++ (char *) &status, sizeof(status));
++ if (status & USB_SS_PORT_STAT_POWER)
++ tegra_xhci_set_port_power(tegra, false,
++ false);
++
++ /* reset OTG port SSPI */
++ msg.cmd = MBOX_CMD_RESET_SSPI;
++ msg.data = tegra->otg_usb3_port+1;
++
++ ret = tegra_xusb_mbox_send(tegra, &msg);
++ if (ret < 0) {
++ dev_info(tegra->dev,
++ "failed to RESET_SSPI %d\n",
++ ret);
++ }
+ }
+- }
+
+- tegra_xhci_set_port_power(tegra, false, true);
+- }
++ tegra_xhci_set_port_power(tegra, false, true);
++ }
+
+- tegra_xhci_set_port_power(tegra, true, true);
+- pm_runtime_mark_last_busy(tegra->dev);
++ tegra_xhci_set_port_power(tegra, true, true);
++ pm_runtime_mark_last_busy(tegra->dev);
+
+- } else {
+- if (tegra->otg_usb3_port >= 0)
+- tegra_xhci_set_port_power(tegra, false, false);
++ } else {
++ if (tegra->otg_usb3_port >= 0)
++ tegra_xhci_set_port_power(tegra, false, false);
+
+- tegra_xhci_set_port_power(tegra, true, false);
++ tegra_xhci_set_port_power(tegra, true, false);
++ }
+ }
+ pm_runtime_put_autosuspend(tegra->dev);
+ }
+@@ -1925,6 +1931,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
+ .scale_ss_clock = true,
+ .has_ipfs = true,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -1961,6 +1968,7 @@ static const struct tegra_xusb_soc tegra210_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = true,
+ .otg_reset_sspi = true,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -2002,6 +2010,7 @@ static const struct tegra_xusb_soc tegra186_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -2033,6 +2042,7 @@ static const struct tegra_xusb_soc tegra194_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .mbox = {
+ .cmd = 0x68,
+ .data_in = 0x6c,
+--
+2.53.0
+
--- /dev/null
+From 20edc38963a0a2e5ba72028747b2f11bab44b3a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 10:26:50 +0100
+Subject: HID: core: Add printk_ratelimited variants to hid_warn() etc
+
+From: Vicki Pfau <vi@endrift.com>
+
+[ Upstream commit 1d64624243af8329b4b219d8c39e28ea448f9929 ]
+
+hid_warn_ratelimited() is needed. Add the others as part of the block.
+
+Signed-off-by: Vicki Pfau <vi@endrift.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/hid.h | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 671403f208c91d..3968fa039c260b 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1248,4 +1248,15 @@ do { \
+ #define hid_dbg_once(hid, fmt, ...) \
+ dev_dbg_once(&(hid)->dev, fmt, ##__VA_ARGS__)
+
++#define hid_err_ratelimited(hid, fmt, ...) \
++ dev_err_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++#define hid_notice_ratelimited(hid, fmt, ...) \
++ dev_notice_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++#define hid_warn_ratelimited(hid, fmt, ...) \
++ dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++#define hid_info_ratelimited(hid, fmt, ...) \
++ dev_info_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++#define hid_dbg_ratelimited(hid, fmt, ...) \
++ dev_dbg_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++
+ #endif
+--
+2.53.0
+
--- /dev/null
+From e43275056059158360d4d476ce4bc7e3974d0c53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 10:26:52 +0100
+Subject: HID: core: Fix size_t specifier in hid_report_raw_event()
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit 4d3a2a466b8d68d852a1f3bbf11204b718428dc4 ]
+
+When building for 32-bit platforms, for which 'size_t' is
+'unsigned int', there are warnings around using the incorrect format
+specifier to print bsize in hid_report_raw_event():
+
+ drivers/hid/hid-core.c:2054:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
+ 2053 | hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
+ | ~~~
+ | %zu
+ 2054 | report->id, csize, bsize);
+ | ^~~~~
+ drivers/hid/hid-core.c:2076:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
+ 2075 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
+ | ~~~
+ | %zu
+ 2076 | report->id, rsize, bsize);
+ | ^~~~~
+
+Use the proper 'size_t' format specifier, '%zu', to clear up the
+warnings.
+
+Cc: stable@vger.kernel.org
+Fixes: 2c85c61d1332 ("HID: pass the buffer size to hid_report_raw_event")
+Reported-by: Miguel Ojeda <ojeda@kernel.org>
+Closes: https://lore.kernel.org/20260516020430.110135-1-ojeda@kernel.org/
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index a8d4673c7b8e13..e106b59b55da2d 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1793,7 +1793,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data,
+ return 0;
+
+ if (unlikely(bsize < csize)) {
+- hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
++ hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %zu)\n",
+ report->id, csize, bsize);
+ return -EINVAL;
+ }
+@@ -1815,7 +1815,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data,
+ rsize = max_buffer_size;
+
+ if (bsize < rsize) {
+- hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
++ hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %zu)\n",
+ report->id, rsize, bsize);
+ return -EINVAL;
+ }
+--
+2.53.0
+
--- /dev/null
+From 51914eb2df20b1114553d7bd48ea305f58b867ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 10:26:51 +0100
+Subject: HID: pass the buffer size to hid_report_raw_event
+
+From: Benjamin Tissoires <bentiss@kernel.org>
+
+[ Upstream commit 2c85c61d1332e1e16f020d76951baf167dcb6f7a ]
+
+commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing
+bogus memset()") enforced the provided data to be at least the size of
+the declared buffer in the report descriptor to prevent a buffer
+overflow. However, we can try to be smarter by providing both the buffer
+size and the data size, meaning that hid_report_raw_event() can make
+better decision whether we should plaining reject the buffer (buffer
+overflow attempt) or if we can safely memset it to 0 and pass it to the
+rest of the stack.
+
+Fixes: 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Acked-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Stable-dep-of: 206342541fc8 ("HID: core: introduce hid_safe_input_report()")
+[Lee: Backported to linux-6.12.y and beyond]
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-core.c | 29 ++++++++++++++++++++++-------
+ drivers/hid/hid-gfrm.c | 4 ++--
+ drivers/hid/hid-logitech-hidpp.c | 2 +-
+ drivers/hid/hid-multitouch.c | 2 +-
+ drivers/hid/hid-primax.c | 2 +-
+ drivers/hid/hid-vivaldi.c | 2 +-
+ drivers/hid/wacom_sys.c | 6 +++---
+ drivers/staging/greybus/hid.c | 2 +-
+ include/linux/hid.h | 4 ++--
+ 9 files changed, 34 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 4fb573ee31b2ca..a8d4673c7b8e13 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1775,8 +1775,8 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
+ }
+ EXPORT_SYMBOL_GPL(__hid_request);
+
+-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
+- int interrupt)
++int hid_report_raw_event(struct hid_device *hid, int type, u8 *data,
++ size_t bufsize, u32 size, int interrupt)
+ {
+ struct hid_report_enum *report_enum = hid->report_enum + type;
+ struct hid_report *report;
+@@ -1784,16 +1784,24 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
+ int max_buffer_size = HID_MAX_BUFFER_SIZE;
+ unsigned int a;
+ u32 rsize, csize = size;
++ size_t bsize = bufsize;
+ u8 *cdata = data;
+ int ret = 0;
+
+ report = hid_get_report(report_enum, data);
+ if (!report)
+- goto out;
++ return 0;
++
++ if (unlikely(bsize < csize)) {
++ hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
++ report->id, csize, bsize);
++ return -EINVAL;
++ }
+
+ if (report_enum->numbered) {
+ cdata++;
+ csize--;
++ bsize--;
+ }
+
+ rsize = hid_compute_report_size(report);
+@@ -1806,9 +1814,15 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
+ else if (rsize > max_buffer_size)
+ rsize = max_buffer_size;
+
++ if (bsize < rsize) {
++ hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
++ report->id, rsize, bsize);
++ return -EINVAL;
++ }
++
+ if (csize < rsize) {
+ dbg_hid("report %d is too short, (%d < %d)\n", report->id,
+- csize, rsize);
++ csize, rsize);
+ memset(cdata + csize, 0, rsize - csize);
+ }
+
+@@ -1817,7 +1831,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
+ if (hid->claimed & HID_CLAIMED_HIDRAW) {
+ ret = hidraw_report_event(hid, data, size);
+ if (ret)
+- goto out;
++ return ret;
+ }
+
+ if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) {
+@@ -1830,7 +1844,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
+
+ if (hid->claimed & HID_CLAIMED_INPUT)
+ hidinput_report_event(hid, report);
+-out:
++
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(hid_report_raw_event);
+@@ -1851,6 +1865,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int i
+ struct hid_report_enum *report_enum;
+ struct hid_driver *hdrv;
+ struct hid_report *report;
++ size_t bufsize = size;
+ int ret = 0;
+
+ if (!hid)
+@@ -1889,7 +1904,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int i
+ goto unlock;
+ }
+
+- ret = hid_report_raw_event(hid, type, data, size, interrupt);
++ ret = hid_report_raw_event(hid, type, data, bufsize, size, interrupt);
+
+ unlock:
+ up(&hid->driver_input_lock);
+diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
+index 699186ff2349e9..d2a56bf92b416e 100644
+--- a/drivers/hid/hid-gfrm.c
++++ b/drivers/hid/hid-gfrm.c
+@@ -66,7 +66,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+ switch (data[1]) {
+ case GFRM100_SEARCH_KEY_DOWN:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
+- sizeof(search_key_dn), 1);
++ sizeof(search_key_dn), sizeof(search_key_dn), 1);
+ break;
+
+ case GFRM100_SEARCH_KEY_AUDIO_DATA:
+@@ -74,7 +74,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+
+ case GFRM100_SEARCH_KEY_UP:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
+- sizeof(search_key_up), 1);
++ sizeof(search_key_up), sizeof(search_key_up), 1);
+ break;
+
+ default:
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index 7ed851bf5bc81f..812ed660c55575 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -3440,7 +3440,7 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp,
+ memcpy(&consumer_report[1], &data[3], 4);
+ /* We are called from atomic context */
+ hid_report_raw_event(hidpp->hid_dev, HID_INPUT_REPORT,
+- consumer_report, 5, 1);
++ consumer_report, sizeof(consumer_report), 5, 1);
+
+ return 1;
+ }
+diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
+index 7a092a2a1bf004..df87d7ae94c462 100644
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -479,7 +479,7 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
+ }
+
+ ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
+- size, 0);
++ size, size, 0);
+ if (ret)
+ dev_warn(&hdev->dev, "failed to report feature\n");
+ }
+diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c
+index 1e6413d07cae21..16e2a811eda9f0 100644
+--- a/drivers/hid/hid-primax.c
++++ b/drivers/hid/hid-primax.c
+@@ -44,7 +44,7 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report,
+ data[0] |= (1 << (data[idx] - 0xE0));
+ data[idx] = 0;
+ }
+- hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0);
++ hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, size, 0);
+ return 1;
+
+ default: /* unknown report */
+diff --git a/drivers/hid/hid-vivaldi.c b/drivers/hid/hid-vivaldi.c
+index d57ec17670379c..fdfea1355ee782 100644
+--- a/drivers/hid/hid-vivaldi.c
++++ b/drivers/hid/hid-vivaldi.c
+@@ -126,7 +126,7 @@ static void vivaldi_feature_mapping(struct hid_device *hdev,
+ }
+
+ ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, report_data,
+- report_len, 0);
++ report_len, report_len, 0);
+ if (ret) {
+ dev_warn(&hdev->dev, "failed to report feature %d\n",
+ field->report->id);
+diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
+index 9065a41336f9ba..07de763a4ee330 100644
+--- a/drivers/hid/wacom_sys.c
++++ b/drivers/hid/wacom_sys.c
+@@ -79,7 +79,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev,
+ int err;
+
+ size = kfifo_out(fifo, buf, sizeof(buf));
+- err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false);
++ err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, size, false);
+ if (err) {
+ hid_warn(hdev, "%s: unable to flush event due to error %d\n",
+ __func__, err);
+@@ -324,7 +324,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
+ data, n, WAC_CMD_RETRIES);
+ if (ret == n && features->type == HID_GENERIC) {
+ ret = hid_report_raw_event(hdev,
+- HID_FEATURE_REPORT, data, n, 0);
++ HID_FEATURE_REPORT, data, n, n, 0);
+ } else if (ret == 2 && features->type != HID_GENERIC) {
+ features->touch_max = data[1];
+ } else {
+@@ -386,7 +386,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
+ data, n, WAC_CMD_RETRIES);
+ if (ret == n) {
+ ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT,
+- data, n, 0);
++ data, n, n, 0);
+ } else {
+ hid_warn(hdev, "%s: could not retrieve sensor offsets\n",
+ __func__);
+diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c
+index adb91286803a91..49b42c0ab078ec 100644
+--- a/drivers/staging/greybus/hid.c
++++ b/drivers/staging/greybus/hid.c
+@@ -201,7 +201,7 @@ static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report)
+ * we just need to setup the input fields, so using
+ * hid_report_raw_event is safe.
+ */
+- hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1);
++ hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, ghid->bufsize, size, 1);
+ }
+
+ static void gb_hid_init_reports(struct gb_hid *ghid)
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 3968fa039c260b..c92c5e2ae24f3b 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1206,8 +1206,8 @@ static inline u32 hid_report_len(struct hid_report *report)
+ return DIV_ROUND_UP(report->size, 8) + (report->id > 0);
+ }
+
+-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
+- int interrupt);
++int hid_report_raw_event(struct hid_device *hid, int type, u8 *data,
++ size_t bufsize, u32 size, int interrupt);
+
+ /* HID quirks API */
+ unsigned long hid_lookup_quirk(const struct hid_device *hdev);
+--
+2.53.0
+
serial-dz-fix-bootconsole-message-clobbering-at-chip-reset.patch
serial-zs-fix-bootconsole-handover-lockup.patch
serial-zs-switch-to-using-channel-reset.patch
+usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
+hid-core-add-printk_ratelimited-variants-to-hid_warn.patch
+hid-pass-the-buffer-size-to-hid_report_raw_event.patch
+hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch
+usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
+xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
--- /dev/null
+From 76d74666c3bccf6fae8dd8783b37b09194c37b73 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 10:36:36 +0200
+Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint
+
+From: Johan Hovold <johan@kernel.org>
+
+commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream.
+
+Make sure that the interrupt-out endpoint max packet size is at least
+eight bytes to avoid user-controlled slab corruption or NULL-pointer
+dereference should a malicious device report a smaller size.
+
+Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size")
+Cc: stable@vger.kernel.org # 2.6.26
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+[ johan: adjust context for 6.18 ]
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/cypress_m8.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 115e2df92132d3..2ca7e7af714fdb 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -447,6 +447,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
+ return -ENODEV;
+ }
+
++ /*
++ * The buffer must be large enough for the one or two-byte header (and
++ * following data), but assume anything smaller than eight bytes is
++ * broken.
++ */
++ if (port->interrupt_out_size < 8)
++ return -EINVAL;
++
+ priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+--
+2.53.0
+
--- /dev/null
+From 8127d1b7d83a94d840b7e94feb60d2788f816eaa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:07:58 +0200
+Subject: USB: serial: digi_acceleport: fix memory corruption with small
+ endpoints
+
+From: Johan Hovold <johan@kernel.org>
+
+commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream.
+
+Add the missing bulk-out buffer size sanity checks to avoid
+out-of-bounds memory accesses or slab corruption should a malicious
+device report smaller buffers than expected.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index af65eb863d70d4..6edc1b50a364f1 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -1228,15 +1228,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
+ static int digi_startup(struct usb_serial *serial)
+ {
+ struct digi_serial *serial_priv;
++ int oob_port_num;
+ int ret;
++ int i;
++
++ /*
++ * The port bulk-out buffers must be large enough for header and
++ * buffered data.
++ */
++ for (i = 0; i < serial->type->num_ports; i++) {
++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2)
++ return -EINVAL;
++ }
++
++ /*
++ * The OOB port bulk-out buffer must be large enough for the two
++ * commands in digi_set_modem_signals().
++ */
++ oob_port_num = serial->type->num_ports;
++ if (serial->port[oob_port_num]->bulk_out_size < 8)
++ return -EINVAL;
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv)
+ return -ENOMEM;
+
+ spin_lock_init(&serial_priv->ds_serial_lock);
+- serial_priv->ds_oob_port_num = serial->type->num_ports;
+- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
++ serial_priv->ds_oob_port_num = oob_port_num;
++ serial_priv->ds_oob_port = serial->port[oob_port_num];
+
+ ret = digi_port_init(serial_priv->ds_oob_port,
+ serial_priv->ds_oob_port_num);
+--
+2.53.0
+
--- /dev/null
+From 85b22d504abe5ef887c2e5e20679e8a3a0950b56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:19:16 +0800
+Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug
+
+From: Wei-Cheng Chen <weichengc@nvidia.com>
+
+[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ]
+
+When a USB device is unplugged from the dual-role port, the device-mode
+path in tegra_xhci_id_work() explicitly clears both SS and HS port power
+via direct hub_control ClearPortFeature(POWER) calls. This preempts the
+xHCI controller's normal disconnect processing -- PORT_CSC is never
+generated, the USB core never sees the disconnect, and the device remains
+in its internal tree as a ghost visible in lsusb.
+
+Add an otg_set_port_power flag to control whether the dual-role switch
+path performs explicit port power management. SoCs that need it
+(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and
+beyond) rely on the PHY mode change to handle disconnect naturally and
+skip all port power calls.
+
+Within the port power path, otg_reset_sspi additionally gates the SSPI
+reset sequence on host-mode entry for SoCs that require it.
+
+Flags set per SoC:
+ Tegra124, Tegra186 -> otg_set_port_power
+ Tegra210 -> otg_set_port_power, otg_reset_sspi
+ Tegra194 and later -> (none)
+
+[ Backport to 5.15.y: keep the host-mode snapshot in the existing
+ tegra->lock section, retain pm_runtime_mark_last_busy() in the host
+ port-power path, and omit the newer Tegra234 entry. ]
+
+Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wei-Cheng Chen <weichengc@nvidia.com>
+Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-tegra.c | 78 ++++++++++++++++++++---------------
+ 1 file changed, 44 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
+index 14a772feab7946..0f936aeb88d064 100644
+--- a/drivers/usb/host/xhci-tegra.c
++++ b/drivers/usb/host/xhci-tegra.c
+@@ -210,6 +210,7 @@ struct tegra_xusb_soc {
+ bool has_ipfs;
+ bool lpm_support;
+ bool otg_reset_sspi;
++ bool otg_set_port_power;
+ };
+
+ struct tegra_xusb_context {
+@@ -1211,14 +1212,17 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ struct tegra_xusb_mbox_msg msg;
+ struct phy *phy = tegra_xusb_get_phy(tegra, "usb2",
+ tegra->otg_usb2_port);
++ bool host_mode;
+ u32 status;
+ int ret;
+
+- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off");
+-
+ mutex_lock(&tegra->lock);
+
+- if (tegra->host_mode)
++ host_mode = tegra->host_mode;
++
++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off");
++
++ if (host_mode)
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST);
+ else
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+@@ -1229,42 +1233,44 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ tegra->otg_usb2_port);
+
+ pm_runtime_get_sync(tegra->dev);
+- if (tegra->host_mode) {
+- /* switch to host mode */
+- if (tegra->otg_usb3_port >= 0) {
+- if (tegra->soc->otg_reset_sspi) {
+- /* set PP=0 */
+- tegra_xhci_hc_driver.hub_control(
+- xhci->shared_hcd, GetPortStatus,
+- 0, tegra->otg_usb3_port+1,
+- (char *) &status, sizeof(status));
+- if (status & USB_SS_PORT_STAT_POWER)
+- tegra_xhci_set_port_power(tegra, false,
+- false);
+-
+- /* reset OTG port SSPI */
+- msg.cmd = MBOX_CMD_RESET_SSPI;
+- msg.data = tegra->otg_usb3_port+1;
+-
+- ret = tegra_xusb_mbox_send(tegra, &msg);
+- if (ret < 0) {
+- dev_info(tegra->dev,
+- "failed to RESET_SSPI %d\n",
+- ret);
++ if (tegra->soc->otg_set_port_power) {
++ if (host_mode) {
++ /* switch to host mode */
++ if (tegra->otg_usb3_port >= 0) {
++ if (tegra->soc->otg_reset_sspi) {
++ /* set PP=0 */
++ tegra_xhci_hc_driver.hub_control(
++ xhci->shared_hcd, GetPortStatus,
++ 0, tegra->otg_usb3_port+1,
++ (char *) &status, sizeof(status));
++ if (status & USB_SS_PORT_STAT_POWER)
++ tegra_xhci_set_port_power(tegra, false,
++ false);
++
++ /* reset OTG port SSPI */
++ msg.cmd = MBOX_CMD_RESET_SSPI;
++ msg.data = tegra->otg_usb3_port+1;
++
++ ret = tegra_xusb_mbox_send(tegra, &msg);
++ if (ret < 0) {
++ dev_info(tegra->dev,
++ "failed to RESET_SSPI %d\n",
++ ret);
++ }
+ }
+- }
+
+- tegra_xhci_set_port_power(tegra, false, true);
+- }
++ tegra_xhci_set_port_power(tegra, false, true);
++ }
+
+- tegra_xhci_set_port_power(tegra, true, true);
+- pm_runtime_mark_last_busy(tegra->dev);
++ tegra_xhci_set_port_power(tegra, true, true);
++ pm_runtime_mark_last_busy(tegra->dev);
+
+- } else {
+- if (tegra->otg_usb3_port >= 0)
+- tegra_xhci_set_port_power(tegra, false, false);
++ } else {
++ if (tegra->otg_usb3_port >= 0)
++ tegra_xhci_set_port_power(tegra, false, false);
+
+- tegra_xhci_set_port_power(tegra, true, false);
++ tegra_xhci_set_port_power(tegra, true, false);
++ }
+ }
+ pm_runtime_put_autosuspend(tegra->dev);
+ }
+@@ -2289,6 +2295,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
+ .scale_ss_clock = true,
+ .has_ipfs = true,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -2325,6 +2332,7 @@ static const struct tegra_xusb_soc tegra210_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = true,
+ .otg_reset_sspi = true,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -2366,6 +2374,7 @@ static const struct tegra_xusb_soc tegra186_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -2397,6 +2406,7 @@ static const struct tegra_xusb_soc tegra194_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .mbox = {
+ .cmd = 0x68,
+ .data_in = 0x6c,
+--
+2.53.0
+
--- /dev/null
+From c91ad06cc5fe268b524276f59ad6df47b5d050d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 17:30:12 +0100
+Subject: HID: core: Add printk_ratelimited variants to hid_warn() etc
+
+From: Vicki Pfau <vi@endrift.com>
+
+[ Upstream commit 1d64624243af8329b4b219d8c39e28ea448f9929 ]
+
+hid_warn_ratelimited() is needed. Add the others as part of the block.
+
+Signed-off-by: Vicki Pfau <vi@endrift.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/hid.h | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 6c3dc24acefc2d..058ba486fdcf87 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1230,4 +1230,15 @@ do { \
+ #define hid_dbg_once(hid, fmt, ...) \
+ dev_dbg_once(&(hid)->dev, fmt, ##__VA_ARGS__)
+
++#define hid_err_ratelimited(hid, fmt, ...) \
++ dev_err_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++#define hid_notice_ratelimited(hid, fmt, ...) \
++ dev_notice_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++#define hid_warn_ratelimited(hid, fmt, ...) \
++ dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++#define hid_info_ratelimited(hid, fmt, ...) \
++ dev_info_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++#define hid_dbg_ratelimited(hid, fmt, ...) \
++ dev_dbg_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
++
+ #endif
+--
+2.53.0
+
--- /dev/null
+From 22eabda3a3fc2045c46ba27e3da5d3703305fef8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 17:30:14 +0100
+Subject: HID: core: Fix size_t specifier in hid_report_raw_event()
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit 4d3a2a466b8d68d852a1f3bbf11204b718428dc4 ]
+
+When building for 32-bit platforms, for which 'size_t' is
+'unsigned int', there are warnings around using the incorrect format
+specifier to print bsize in hid_report_raw_event():
+
+ drivers/hid/hid-core.c:2054:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
+ 2053 | hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
+ | ~~~
+ | %zu
+ 2054 | report->id, csize, bsize);
+ | ^~~~~
+ drivers/hid/hid-core.c:2076:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
+ 2075 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
+ | ~~~
+ | %zu
+ 2076 | report->id, rsize, bsize);
+ | ^~~~~
+
+Use the proper 'size_t' format specifier, '%zu', to clear up the
+warnings.
+
+Cc: stable@vger.kernel.org
+Fixes: 2c85c61d1332 ("HID: pass the buffer size to hid_report_raw_event")
+Reported-by: Miguel Ojeda <ojeda@kernel.org>
+Closes: https://lore.kernel.org/20260516020430.110135-1-ojeda@kernel.org/
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 2be5823002a3a4..2191205ce5b0bf 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -2006,7 +2006,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+ return 0;
+
+ if (unlikely(bsize < csize)) {
+- hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
++ hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %zu)\n",
+ report->id, csize, bsize);
+ return -EINVAL;
+ }
+@@ -2028,7 +2028,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+ rsize = max_buffer_size;
+
+ if (bsize < rsize) {
+- hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
++ hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %zu)\n",
+ report->id, rsize, bsize);
+ return -EINVAL;
+ }
+--
+2.53.0
+
--- /dev/null
+From c63ea6201204fccc17441da6a08a9321360368e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 17:30:13 +0100
+Subject: HID: pass the buffer size to hid_report_raw_event
+
+From: Benjamin Tissoires <bentiss@kernel.org>
+
+[ Upstream commit 2c85c61d1332e1e16f020d76951baf167dcb6f7a ]
+
+commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing
+bogus memset()") enforced the provided data to be at least the size of
+the declared buffer in the report descriptor to prevent a buffer
+overflow. However, we can try to be smarter by providing both the buffer
+size and the data size, meaning that hid_report_raw_event() can make
+better decision whether we should plaining reject the buffer (buffer
+overflow attempt) or if we can safely memset it to 0 and pass it to the
+rest of the stack.
+
+Fixes: 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Acked-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Stable-dep-of: 206342541fc8 ("HID: core: introduce hid_safe_input_report()")
+[Lee: Backported to linux-6.12.y and beyond]
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-core.c | 33 +++++++++++++++++++++++---------
+ drivers/hid/hid-gfrm.c | 4 ++--
+ drivers/hid/hid-logitech-hidpp.c | 2 +-
+ drivers/hid/hid-multitouch.c | 2 +-
+ drivers/hid/hid-primax.c | 2 +-
+ drivers/hid/hid-vivaldi-common.c | 2 +-
+ drivers/hid/wacom_sys.c | 6 +++---
+ drivers/staging/greybus/hid.c | 2 +-
+ include/linux/hid.h | 4 ++--
+ 9 files changed, 36 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 3f3de08969b55c..2be5823002a3a4 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1989,24 +1989,32 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
+ }
+ EXPORT_SYMBOL_GPL(__hid_request);
+
+-int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+- int interrupt)
++int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
++ size_t bufsize, u32 size, int interrupt)
+ {
+ struct hid_report_enum *report_enum = hid->report_enum + type;
+ struct hid_report *report;
+ struct hid_driver *hdrv;
+ int max_buffer_size = HID_MAX_BUFFER_SIZE;
+ u32 rsize, csize = size;
++ size_t bsize = bufsize;
+ u8 *cdata = data;
+ int ret = 0;
+
+ report = hid_get_report(report_enum, data);
+ if (!report)
+- goto out;
++ return 0;
++
++ if (unlikely(bsize < csize)) {
++ hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
++ report->id, csize, bsize);
++ return -EINVAL;
++ }
+
+ if (report_enum->numbered) {
+ cdata++;
+ csize--;
++ bsize--;
+ }
+
+ rsize = hid_compute_report_size(report);
+@@ -2019,9 +2027,15 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+ else if (rsize > max_buffer_size)
+ rsize = max_buffer_size;
+
++ if (bsize < rsize) {
++ hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
++ report->id, rsize, bsize);
++ return -EINVAL;
++ }
++
+ if (csize < rsize) {
+ dbg_hid("report %d is too short, (%d < %d)\n", report->id,
+- csize, rsize);
++ csize, rsize);
+ memset(cdata + csize, 0, rsize - csize);
+ }
+
+@@ -2030,7 +2044,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+ if (hid->claimed & HID_CLAIMED_HIDRAW) {
+ ret = hidraw_report_event(hid, data, size);
+ if (ret)
+- goto out;
++ return ret;
+ }
+
+ if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) {
+@@ -2042,7 +2056,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+
+ if (hid->claimed & HID_CLAIMED_INPUT)
+ hidinput_report_event(hid, report);
+-out:
++
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(hid_report_raw_event);
+@@ -2058,12 +2072,13 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
+ *
+ * This is data entry for lower layers.
+ */
+-int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+- int interrupt)
++int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data,
++ u32 size, int interrupt)
+ {
+ struct hid_report_enum *report_enum;
+ struct hid_driver *hdrv;
+ struct hid_report *report;
++ size_t bufsize = size;
+ int ret = 0;
+
+ if (!hid)
+@@ -2102,7 +2117,7 @@ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data
+ goto unlock;
+ }
+
+- ret = hid_report_raw_event(hid, type, data, size, interrupt);
++ ret = hid_report_raw_event(hid, type, data, bufsize, size, interrupt);
+
+ unlock:
+ up(&hid->driver_input_lock);
+diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
+index 699186ff2349e9..d2a56bf92b416e 100644
+--- a/drivers/hid/hid-gfrm.c
++++ b/drivers/hid/hid-gfrm.c
+@@ -66,7 +66,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+ switch (data[1]) {
+ case GFRM100_SEARCH_KEY_DOWN:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
+- sizeof(search_key_dn), 1);
++ sizeof(search_key_dn), sizeof(search_key_dn), 1);
+ break;
+
+ case GFRM100_SEARCH_KEY_AUDIO_DATA:
+@@ -74,7 +74,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+
+ case GFRM100_SEARCH_KEY_UP:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
+- sizeof(search_key_up), 1);
++ sizeof(search_key_up), sizeof(search_key_up), 1);
+ break;
+
+ default:
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index c65b5f004bac57..89b0374bb9a851 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -3451,7 +3451,7 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp,
+ memcpy(&consumer_report[1], &data[3], 4);
+ /* We are called from atomic context */
+ hid_report_raw_event(hidpp->hid_dev, HID_INPUT_REPORT,
+- consumer_report, 5, 1);
++ consumer_report, sizeof(consumer_report), 5, 1);
+
+ return 1;
+ }
+diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
+index 0039508943626d..6c04eed0a46464 100644
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -479,7 +479,7 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
+ }
+
+ ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
+- size, 0);
++ size, size, 0);
+ if (ret)
+ dev_warn(&hdev->dev, "failed to report feature\n");
+ }
+diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c
+index 1e6413d07cae21..16e2a811eda9f0 100644
+--- a/drivers/hid/hid-primax.c
++++ b/drivers/hid/hid-primax.c
+@@ -44,7 +44,7 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report,
+ data[0] |= (1 << (data[idx] - 0xE0));
+ data[idx] = 0;
+ }
+- hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0);
++ hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, size, 0);
+ return 1;
+
+ default: /* unknown report */
+diff --git a/drivers/hid/hid-vivaldi-common.c b/drivers/hid/hid-vivaldi-common.c
+index b0af2be948952c..7fb986615768f7 100644
+--- a/drivers/hid/hid-vivaldi-common.c
++++ b/drivers/hid/hid-vivaldi-common.c
+@@ -85,7 +85,7 @@ void vivaldi_feature_mapping(struct hid_device *hdev,
+ }
+
+ ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, report_data,
+- report_len, 0);
++ report_len, report_len, 0);
+ if (ret) {
+ dev_warn(&hdev->dev, "failed to report feature %d\n",
+ field->report->id);
+diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
+index 9106f16e42df23..9d2a54451b0b5f 100644
+--- a/drivers/hid/wacom_sys.c
++++ b/drivers/hid/wacom_sys.c
+@@ -74,7 +74,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev,
+ int err;
+
+ size = kfifo_out(fifo, buf, sizeof(buf));
+- err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false);
++ err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, size, false);
+ if (err) {
+ hid_warn(hdev, "%s: unable to flush event due to error %d\n",
+ __func__, err);
+@@ -319,7 +319,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
+ data, n, WAC_CMD_RETRIES);
+ if (ret == n && features->type == HID_GENERIC) {
+ ret = hid_report_raw_event(hdev,
+- HID_FEATURE_REPORT, data, n, 0);
++ HID_FEATURE_REPORT, data, n, n, 0);
+ } else if (ret == 2 && features->type != HID_GENERIC) {
+ features->touch_max = data[1];
+ } else {
+@@ -381,7 +381,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
+ data, n, WAC_CMD_RETRIES);
+ if (ret == n) {
+ ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT,
+- data, n, 0);
++ data, n, n, 0);
+ } else {
+ hid_warn(hdev, "%s: could not retrieve sensor offsets\n",
+ __func__);
+diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c
+index adb91286803a91..49b42c0ab078ec 100644
+--- a/drivers/staging/greybus/hid.c
++++ b/drivers/staging/greybus/hid.c
+@@ -201,7 +201,7 @@ static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report)
+ * we just need to setup the input fields, so using
+ * hid_report_raw_event is safe.
+ */
+- hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1);
++ hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, ghid->bufsize, size, 1);
+ }
+
+ static void gb_hid_init_reports(struct gb_hid *ghid)
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 058ba486fdcf87..c57fc6a918c030 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1188,8 +1188,8 @@ static inline u32 hid_report_len(struct hid_report *report)
+ return DIV_ROUND_UP(report->size, 8) + (report->id > 0);
+ }
+
+-int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+- int interrupt);
++int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
++ size_t bufsize, u32 size, int interrupt);
+
+ /* HID quirks API */
+ unsigned long hid_lookup_quirk(const struct hid_device *hdev);
+--
+2.53.0
+
--- /dev/null
+From 0c2113155aab5f8b42a34c4826eb5ba91fdd139a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 08:32:45 +0000
+Subject: netfilter: nf_tables: restore set elements when delete set fails
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit e79b47a8615d42c68aaeb68971593333667382ed ]
+
+>From abort path, nft_mapelem_activate() needs to restore refcounters to
+the original state. Currently, it uses the set->ops->walk() to iterate
+over these set elements. The existing set iterator skips inactive
+elements in the next generation, this does not work from the abort path
+to restore the original state since it has to skip active elements
+instead (not inactive ones).
+
+This patch moves the check for inactive elements to the set iterator
+callback, then it reverses the logic for the .activate case which
+needs to skip active elements.
+
+Toggle next generation bit for elements when delete set command is
+invoked and call nft_clear() from .activate (abort) path to restore the
+next generation bit.
+
+The splat below shows an object in mappings memleak:
+
+[43929.457523] ------------[ cut here ]------------
+[43929.457532] WARNING: CPU: 0 PID: 1139 at include/net/netfilter/nf_tables.h:1237 nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables]
+[...]
+[43929.458014] RIP: 0010:nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables]
+[43929.458076] Code: 83 f8 01 77 ab 49 8d 7c 24 08 e8 37 5e d0 de 49 8b 6c 24 08 48 8d 7d 50 e8 e9 5c d0 de 8b 45 50 8d 50 ff 89 55 50 85 c0 75 86 <0f> 0b eb 82 0f 0b eb b3 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90
+[43929.458081] RSP: 0018:ffff888140f9f4b0 EFLAGS: 00010246
+[43929.458086] RAX: 0000000000000000 RBX: ffff8881434f5288 RCX: dffffc0000000000
+[43929.458090] RDX: 00000000ffffffff RSI: ffffffffa26d28a7 RDI: ffff88810ecc9550
+[43929.458093] RBP: ffff88810ecc9500 R08: 0000000000000001 R09: ffffed10281f3e8f
+[43929.458096] R10: 0000000000000003 R11: ffff0000ffff0000 R12: ffff8881434f52a0
+[43929.458100] R13: ffff888140f9f5f4 R14: ffff888151c7a800 R15: 0000000000000002
+[43929.458103] FS: 00007f0c687c4740(0000) GS:ffff888390800000(0000) knlGS:0000000000000000
+[43929.458107] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[43929.458111] CR2: 00007f58dbe5b008 CR3: 0000000123602005 CR4: 00000000001706f0
+[43929.458114] Call Trace:
+[43929.458118] <TASK>
+[43929.458121] ? __warn+0x9f/0x1a0
+[43929.458127] ? nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables]
+[43929.458188] ? report_bug+0x1b1/0x1e0
+[43929.458196] ? handle_bug+0x3c/0x70
+[43929.458200] ? exc_invalid_op+0x17/0x40
+[43929.458211] ? nft_setelem_data_deactivate+0xd7/0xf0 [nf_tables]
+[43929.458271] ? nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables]
+[43929.458332] nft_mapelem_deactivate+0x24/0x30 [nf_tables]
+[43929.458392] nft_rhash_walk+0xdd/0x180 [nf_tables]
+[43929.458453] ? __pfx_nft_rhash_walk+0x10/0x10 [nf_tables]
+[43929.458512] ? rb_insert_color+0x2e/0x280
+[43929.458520] nft_map_deactivate+0xdc/0x1e0 [nf_tables]
+[43929.458582] ? __pfx_nft_map_deactivate+0x10/0x10 [nf_tables]
+[43929.458642] ? __pfx_nft_mapelem_deactivate+0x10/0x10 [nf_tables]
+[43929.458701] ? __rcu_read_unlock+0x46/0x70
+[43929.458709] nft_delset+0xff/0x110 [nf_tables]
+[43929.458769] nft_flush_table+0x16f/0x460 [nf_tables]
+[43929.458830] nf_tables_deltable+0x501/0x580 [nf_tables]
+
+Fixes: 628bd3e49cba ("netfilter: nf_tables: drop map element references from preparation phase")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+(cherry picked from commit e79b47a8615d42c68aaeb68971593333667382ed)
+[Vegard: CVE-2024-27012; fixed conflicts due to missing commits
+ 0e1ea651c9717ddcd8e0648d8468477a31867b0a ("netfilter: nf_tables: shrink
+ memory consumption of set elements") and
+ 9dad402b89e81a0516bad5e0ac009b7a0a80898f ("netfilter: nf_tables: expose
+ opaque set element as struct nft_elem_priv") so we pass the correct types
+ and values to nft_setelem_data_deactivate(), nft_setelem_validate(),
+ nft_set_elem_ext(), etc.]
+Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[acsjakub: clean cherry-pick of the commit 164936b2fc88
+ ("netfilter: nf_tables: restore set elements when delete set fails")
+ from 6.6.y. Plus, add "[ Upstream commit .." header to the message]
+Signed-off-by: Jakub Acs <acsjakub@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 41 ++++++++++++++++++++++++++++++----
+ net/netfilter/nft_set_bitmap.c | 4 +---
+ net/netfilter/nft_set_hash.c | 8 ++-----
+ net/netfilter/nft_set_pipapo.c | 5 +----
+ net/netfilter/nft_set_rbtree.c | 4 +---
+ 5 files changed, 42 insertions(+), 20 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 0c422428263873..201e2cc0453992 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -594,6 +594,12 @@ static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
+ const struct nft_set_iter *iter,
+ struct nft_set_elem *elem)
+ {
++ struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
++
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
++ nft_set_elem_change_active(ctx->net, set, ext);
+ nft_setelem_data_deactivate(ctx->net, set, elem);
+
+ return 0;
+@@ -619,6 +625,7 @@ static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
+ continue;
+
+ elem.priv = catchall->elem;
++ nft_set_elem_change_active(ctx->net, set, ext);
+ nft_setelem_data_deactivate(ctx->net, set, &elem);
+ break;
+ }
+@@ -3593,6 +3600,9 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
+ const struct nft_data *data;
+ int err;
+
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
+ *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
+ return 0;
+@@ -3616,19 +3626,22 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
+
+ int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
+ {
+- u8 genmask = nft_genmask_next(ctx->net);
++ struct nft_set_iter dummy_iter = {
++ .genmask = nft_genmask_next(ctx->net),
++ };
+ struct nft_set_elem_catchall *catchall;
+ struct nft_set_elem elem;
++
+ struct nft_set_ext *ext;
+ int ret = 0;
+
+ list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
+ ext = nft_set_elem_ext(set, catchall->elem);
+- if (!nft_set_elem_active(ext, genmask))
++ if (!nft_set_elem_active(ext, dummy_iter.genmask))
+ continue;
+
+ elem.priv = catchall->elem;
+- ret = nft_setelem_validate(ctx, set, NULL, &elem);
++ ret = nft_setelem_validate(ctx, set, &dummy_iter, &elem);
+ if (ret < 0)
+ return ret;
+ }
+@@ -5103,6 +5116,11 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
+ const struct nft_set_iter *iter,
+ struct nft_set_elem *elem)
+ {
++ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
++
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ return nft_setelem_data_validate(ctx, set, elem);
+ }
+
+@@ -5197,6 +5215,13 @@ static int nft_mapelem_activate(const struct nft_ctx *ctx,
+ const struct nft_set_iter *iter,
+ struct nft_set_elem *elem)
+ {
++ struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
++
++ /* called from abort path, reverse check to undo changes. */
++ if (nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
++ nft_clear(ctx->net, ext);
+ nft_setelem_data_activate(ctx->net, set, elem);
+
+ return 0;
+@@ -5215,6 +5240,7 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx,
+ if (nft_set_elem_active(ext, genmask))
+ continue;
+
++ nft_clear(ctx->net, ext);
+ elem.priv = catchall->elem;
+ nft_setelem_data_activate(ctx->net, set, &elem);
+ break;
+@@ -5488,6 +5514,9 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
+ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
+ struct nft_set_dump_args *args;
+
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ if (nft_set_elem_expired(ext) || nft_set_elem_is_dead(ext))
+ return 0;
+
+@@ -6220,7 +6249,7 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set,
+ struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
+
+ if (nft_setelem_is_catchall(set, elem)) {
+- nft_set_elem_change_active(net, set, ext);
++ nft_clear(net, ext);
+ } else {
+ set->ops->activate(net, set, elem);
+ }
+@@ -6902,9 +6931,13 @@ static int nft_setelem_flush(const struct nft_ctx *ctx,
+ const struct nft_set_iter *iter,
+ struct nft_set_elem *elem)
+ {
++ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
+ struct nft_trans *trans;
+ int err;
+
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM,
+ sizeof(struct nft_trans_elem), GFP_ATOMIC);
+ if (!trans)
+diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c
+index 1e5e7a181e0bc2..cbf7f7825f1b88 100644
+--- a/net/netfilter/nft_set_bitmap.c
++++ b/net/netfilter/nft_set_bitmap.c
+@@ -171,7 +171,7 @@ static void nft_bitmap_activate(const struct net *net,
+ nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off);
+ /* Enter 11 state. */
+ priv->bitmap[idx] |= (genmask << off);
+- nft_set_elem_change_active(net, set, &be->ext);
++ nft_clear(net, &be->ext);
+ }
+
+ static bool nft_bitmap_flush(const struct net *net,
+@@ -223,8 +223,6 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx,
+ list_for_each_entry_rcu(be, &priv->list, head) {
+ if (iter->count < iter->skip)
+ goto cont;
+- if (!nft_set_elem_active(&be->ext, iter->genmask))
+- goto cont;
+
+ elem.priv = be;
+
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index 9ea4a09903186d..5a74ee4b7dfb35 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -196,7 +196,7 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set,
+ {
+ struct nft_rhash_elem *he = elem->priv;
+
+- nft_set_elem_change_active(net, set, &he->ext);
++ nft_clear(net, &he->ext);
+ }
+
+ static bool nft_rhash_flush(const struct net *net,
+@@ -285,8 +285,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
+
+ if (iter->count < iter->skip)
+ goto cont;
+- if (!nft_set_elem_active(&he->ext, iter->genmask))
+- goto cont;
+
+ elem.priv = he;
+
+@@ -615,7 +613,7 @@ static void nft_hash_activate(const struct net *net, const struct nft_set *set,
+ {
+ struct nft_hash_elem *he = elem->priv;
+
+- nft_set_elem_change_active(net, set, &he->ext);
++ nft_clear(net, &he->ext);
+ }
+
+ static bool nft_hash_flush(const struct net *net,
+@@ -669,8 +667,6 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
+ hlist_for_each_entry_rcu(he, &priv->table[i], node) {
+ if (iter->count < iter->skip)
+ goto cont;
+- if (!nft_set_elem_active(&he->ext, iter->genmask))
+- goto cont;
+
+ elem.priv = he;
+
+diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
+index cfd0d020f3382b..11473275c6e263 100644
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -1849,7 +1849,7 @@ static void nft_pipapo_activate(const struct net *net,
+ {
+ struct nft_pipapo_elem *e = elem->priv;
+
+- nft_set_elem_change_active(net, set, &e->ext);
++ nft_clear(net, &e->ext);
+ }
+
+ /**
+@@ -2151,9 +2151,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
+
+ e = f->mt[r].e;
+
+- if (!nft_set_elem_active(&e->ext, iter->genmask))
+- goto cont;
+-
+ elem.priv = e;
+
+ iter->err = iter->fn(ctx, set, iter, &elem);
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index 426becaad1b94f..23e4e656f7f0cb 100644
+--- a/net/netfilter/nft_set_rbtree.c
++++ b/net/netfilter/nft_set_rbtree.c
+@@ -548,7 +548,7 @@ static void nft_rbtree_activate(const struct net *net,
+ {
+ struct nft_rbtree_elem *rbe = elem->priv;
+
+- nft_set_elem_change_active(net, set, &rbe->ext);
++ nft_clear(net, &rbe->ext);
+ }
+
+ static bool nft_rbtree_flush(const struct net *net,
+@@ -618,8 +618,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
+
+ if (iter->count < iter->skip)
+ goto cont;
+- if (!nft_set_elem_active(&rbe->ext, iter->genmask))
+- goto cont;
+
+ elem.priv = rbe;
+
+--
+2.53.0
+
--- /dev/null
+From f5a021ea66314b5bed31babffaf56d5c1df1570b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2026 16:27:15 +0300
+Subject: RDMA/rxe: Complete the rxe_cleanup_task backport
+
+From: Vladislav Nikolaev <vlad102nikolaev@gmail.com>
+
+No upstream commit exists for this patch.
+
+The issue was introduced with backporting upstream commit b2b1ddc45745
+("RDMA/rxe: Fix the error "trying to register non-static key in
+rxe_cleanup_task"") to the 6.1 stable tree as commit 3236221bb8e4
+("RDMA/rxe: Fix the error "trying to register non-static key in
+rxe_cleanup_task"").
+
+The 6.1 backport guarded qp->req.task and qp->comp.task before calling
+rxe_cleanup_task(), but left qp->resp.task unguarded. It also kept the
+responder task cleanup before deleting the RC timers, while upstream had
+already moved it after the timer shutdown by commit 960ebe97e523
+("RDMA/rxe: Remove __rxe_do_task()").
+
+In the 6.1 tree, rxe_qp_from_init() calls rxe_qp_init_req() before
+rxe_qp_init_resp(). Therefore, if rxe_qp_init_req() fails, cleanup can
+run before qp->resp.task has been initialized by rxe_init_task(), and the
+unconditional rxe_cleanup_task(&qp->resp.task) can still hit the same
+uninitialized task lock problem that upstream commit b2b1ddc45745 fixed.
+
+Move responder task cleanup after deleting the RC timers, matching the
+upstream cleanup order, and guard it with qp->resp.task.func like the
+requester and completer tasks.
+
+Fixes: 3236221bb8e4 ("RDMA/rxe: Fix the error "trying to register non-static key in rxe_cleanup_task"")
+Signed-off-by: Vladislav Nikolaev <vlad102nikolaev@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/sw/rxe/rxe_qp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c
+index 709c63e9773c5f..171c0f4dcbecfc 100644
+--- a/drivers/infiniband/sw/rxe/rxe_qp.c
++++ b/drivers/infiniband/sw/rxe/rxe_qp.c
+@@ -781,13 +781,15 @@ static void rxe_qp_do_cleanup(struct work_struct *work)
+
+ qp->valid = 0;
+ qp->qp_timeout_jiffies = 0;
+- rxe_cleanup_task(&qp->resp.task);
+
+ if (qp_type(qp) == IB_QPT_RC) {
+ del_timer_sync(&qp->retrans_timer);
+ del_timer_sync(&qp->rnr_nak_timer);
+ }
+
++ if (qp->resp.task.func)
++ rxe_cleanup_task(&qp->resp.task);
++
+ if (qp->req.task.func)
+ rxe_cleanup_task(&qp->req.task);
+
+--
+2.53.0
+
serial-dz-fix-bootconsole-message-clobbering-at-chip-reset.patch
serial-zs-fix-bootconsole-handover-lockup.patch
serial-zs-switch-to-using-channel-reset.patch
+hid-core-add-printk_ratelimited-variants-to-hid_warn.patch
+hid-pass-the-buffer-size-to-hid_report_raw_event.patch
+hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch
+rdma-rxe-complete-the-rxe_cleanup_task-backport.patch
+usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
+xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
+netfilter-nf_tables-restore-set-elements-when-delete.patch
+usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
--- /dev/null
+From b8614b05f2dfc9139fc9ee77073ef49541fe7aae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 10:36:36 +0200
+Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint
+
+From: Johan Hovold <johan@kernel.org>
+
+commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream.
+
+Make sure that the interrupt-out endpoint max packet size is at least
+eight bytes to avoid user-controlled slab corruption or NULL-pointer
+dereference should a malicious device report a smaller size.
+
+Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size")
+Cc: stable@vger.kernel.org # 2.6.26
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+[ johan: adjust context for 6.18 ]
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/cypress_m8.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 4c625e77da3a8f..f567617c8f2314 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -448,6 +448,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
+ return -ENODEV;
+ }
+
++ /*
++ * The buffer must be large enough for the one or two-byte header (and
++ * following data), but assume anything smaller than eight bytes is
++ * broken.
++ */
++ if (port->interrupt_out_size < 8)
++ return -EINVAL;
++
+ priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+--
+2.53.0
+
--- /dev/null
+From a00cc119bbd9e7377e959199a8b97226e4145d56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:07:58 +0200
+Subject: USB: serial: digi_acceleport: fix memory corruption with small
+ endpoints
+
+From: Johan Hovold <johan@kernel.org>
+
+commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream.
+
+Add the missing bulk-out buffer size sanity checks to avoid
+out-of-bounds memory accesses or slab corruption should a malicious
+device report smaller buffers than expected.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index 45d688e9b93f68..eb23f7bb41e728 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -1230,15 +1230,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
+ static int digi_startup(struct usb_serial *serial)
+ {
+ struct digi_serial *serial_priv;
++ int oob_port_num;
+ int ret;
++ int i;
++
++ /*
++ * The port bulk-out buffers must be large enough for header and
++ * buffered data.
++ */
++ for (i = 0; i < serial->type->num_ports; i++) {
++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2)
++ return -EINVAL;
++ }
++
++ /*
++ * The OOB port bulk-out buffer must be large enough for the two
++ * commands in digi_set_modem_signals().
++ */
++ oob_port_num = serial->type->num_ports;
++ if (serial->port[oob_port_num]->bulk_out_size < 8)
++ return -EINVAL;
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv)
+ return -ENOMEM;
+
+ spin_lock_init(&serial_priv->ds_serial_lock);
+- serial_priv->ds_oob_port_num = serial->type->num_ports;
+- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
++ serial_priv->ds_oob_port_num = oob_port_num;
++ serial_priv->ds_oob_port = serial->port[oob_port_num];
+
+ ret = digi_port_init(serial_priv->ds_oob_port,
+ serial_priv->ds_oob_port_num);
+--
+2.53.0
+
--- /dev/null
+From 1bf08213d392dc0615d0d32a248e4550a39ad722 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:19:13 +0800
+Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug
+
+From: Wei-Cheng Chen <weichengc@nvidia.com>
+
+[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ]
+
+When a USB device is unplugged from the dual-role port, the device-mode
+path in tegra_xhci_id_work() explicitly clears both SS and HS port power
+via direct hub_control ClearPortFeature(POWER) calls. This preempts the
+xHCI controller's normal disconnect processing -- PORT_CSC is never
+generated, the USB core never sees the disconnect, and the device remains
+in its internal tree as a ghost visible in lsusb.
+
+Add an otg_set_port_power flag to control whether the dual-role switch
+path performs explicit port power management. SoCs that need it
+(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and
+beyond) rely on the PHY mode change to handle disconnect naturally and
+skip all port power calls.
+
+Within the port power path, otg_reset_sspi additionally gates the SSPI
+reset sequence on host-mode entry for SoCs that require it.
+
+Flags set per SoC:
+ Tegra124, Tegra186 -> otg_set_port_power
+ Tegra210 -> otg_set_port_power, otg_reset_sspi
+ Tegra194 and later -> (none)
+
+[ Backport to 6.1.y: keep the host-mode snapshot in the existing
+ tegra->lock section, retain pm_runtime_mark_last_busy() in the host
+ port-power path, and omit the newer Tegra234 entry. ]
+
+Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wei-Cheng Chen <weichengc@nvidia.com>
+Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-tegra.c | 78 ++++++++++++++++++++---------------
+ 1 file changed, 44 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
+index 14a772feab7946..0f936aeb88d064 100644
+--- a/drivers/usb/host/xhci-tegra.c
++++ b/drivers/usb/host/xhci-tegra.c
+@@ -210,6 +210,7 @@ struct tegra_xusb_soc {
+ bool has_ipfs;
+ bool lpm_support;
+ bool otg_reset_sspi;
++ bool otg_set_port_power;
+ };
+
+ struct tegra_xusb_context {
+@@ -1211,14 +1212,17 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ struct tegra_xusb_mbox_msg msg;
+ struct phy *phy = tegra_xusb_get_phy(tegra, "usb2",
+ tegra->otg_usb2_port);
++ bool host_mode;
+ u32 status;
+ int ret;
+
+- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off");
+-
+ mutex_lock(&tegra->lock);
+
+- if (tegra->host_mode)
++ host_mode = tegra->host_mode;
++
++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off");
++
++ if (host_mode)
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST);
+ else
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+@@ -1229,42 +1233,44 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ tegra->otg_usb2_port);
+
+ pm_runtime_get_sync(tegra->dev);
+- if (tegra->host_mode) {
+- /* switch to host mode */
+- if (tegra->otg_usb3_port >= 0) {
+- if (tegra->soc->otg_reset_sspi) {
+- /* set PP=0 */
+- tegra_xhci_hc_driver.hub_control(
+- xhci->shared_hcd, GetPortStatus,
+- 0, tegra->otg_usb3_port+1,
+- (char *) &status, sizeof(status));
+- if (status & USB_SS_PORT_STAT_POWER)
+- tegra_xhci_set_port_power(tegra, false,
+- false);
+-
+- /* reset OTG port SSPI */
+- msg.cmd = MBOX_CMD_RESET_SSPI;
+- msg.data = tegra->otg_usb3_port+1;
+-
+- ret = tegra_xusb_mbox_send(tegra, &msg);
+- if (ret < 0) {
+- dev_info(tegra->dev,
+- "failed to RESET_SSPI %d\n",
+- ret);
++ if (tegra->soc->otg_set_port_power) {
++ if (host_mode) {
++ /* switch to host mode */
++ if (tegra->otg_usb3_port >= 0) {
++ if (tegra->soc->otg_reset_sspi) {
++ /* set PP=0 */
++ tegra_xhci_hc_driver.hub_control(
++ xhci->shared_hcd, GetPortStatus,
++ 0, tegra->otg_usb3_port+1,
++ (char *) &status, sizeof(status));
++ if (status & USB_SS_PORT_STAT_POWER)
++ tegra_xhci_set_port_power(tegra, false,
++ false);
++
++ /* reset OTG port SSPI */
++ msg.cmd = MBOX_CMD_RESET_SSPI;
++ msg.data = tegra->otg_usb3_port+1;
++
++ ret = tegra_xusb_mbox_send(tegra, &msg);
++ if (ret < 0) {
++ dev_info(tegra->dev,
++ "failed to RESET_SSPI %d\n",
++ ret);
++ }
+ }
+- }
+
+- tegra_xhci_set_port_power(tegra, false, true);
+- }
++ tegra_xhci_set_port_power(tegra, false, true);
++ }
+
+- tegra_xhci_set_port_power(tegra, true, true);
+- pm_runtime_mark_last_busy(tegra->dev);
++ tegra_xhci_set_port_power(tegra, true, true);
++ pm_runtime_mark_last_busy(tegra->dev);
+
+- } else {
+- if (tegra->otg_usb3_port >= 0)
+- tegra_xhci_set_port_power(tegra, false, false);
++ } else {
++ if (tegra->otg_usb3_port >= 0)
++ tegra_xhci_set_port_power(tegra, false, false);
+
+- tegra_xhci_set_port_power(tegra, true, false);
++ tegra_xhci_set_port_power(tegra, true, false);
++ }
+ }
+ pm_runtime_put_autosuspend(tegra->dev);
+ }
+@@ -2289,6 +2295,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
+ .scale_ss_clock = true,
+ .has_ipfs = true,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -2325,6 +2332,7 @@ static const struct tegra_xusb_soc tegra210_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = true,
+ .otg_reset_sspi = true,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -2366,6 +2374,7 @@ static const struct tegra_xusb_soc tegra186_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .mbox = {
+ .cmd = 0xe4,
+ .data_in = 0xe8,
+@@ -2397,6 +2406,7 @@ static const struct tegra_xusb_soc tegra194_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .mbox = {
+ .cmd = 0x68,
+ .data_in = 0x6c,
+--
+2.53.0
+
serial-zs-fix-bootconsole-handover-lockup.patch
serial-zs-switch-to-using-channel-reset.patch
serial-zs-convert-to-use-a-platform-device.patch
+usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
+usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
+xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
--- /dev/null
+From d9ba47331e8a007280c5aa74ae6614463406ca7e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 10:36:36 +0200
+Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint
+
+From: Johan Hovold <johan@kernel.org>
+
+commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream.
+
+Make sure that the interrupt-out endpoint max packet size is at least
+eight bytes to avoid user-controlled slab corruption or NULL-pointer
+dereference should a malicious device report a smaller size.
+
+Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size")
+Cc: stable@vger.kernel.org # 2.6.26
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+[ johan: adjust context for 6.18 ]
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/cypress_m8.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index eb47f35aab0ced..905f6a560e0455 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -445,6 +445,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
+ return -ENODEV;
+ }
+
++ /*
++ * The buffer must be large enough for the one or two-byte header (and
++ * following data), but assume anything smaller than eight bytes is
++ * broken.
++ */
++ if (port->interrupt_out_size < 8)
++ return -EINVAL;
++
+ priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+--
+2.53.0
+
--- /dev/null
+From 92801d79c243b81292c22855b7bd31a9965db8f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:07:58 +0200
+Subject: USB: serial: digi_acceleport: fix memory corruption with small
+ endpoints
+
+From: Johan Hovold <johan@kernel.org>
+
+commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream.
+
+Add the missing bulk-out buffer size sanity checks to avoid
+out-of-bounds memory accesses or slab corruption should a malicious
+device report smaller buffers than expected.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index a064859654121d..a876d6629b65d1 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -1229,15 +1229,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
+ static int digi_startup(struct usb_serial *serial)
+ {
+ struct digi_serial *serial_priv;
++ int oob_port_num;
+ int ret;
++ int i;
++
++ /*
++ * The port bulk-out buffers must be large enough for header and
++ * buffered data.
++ */
++ for (i = 0; i < serial->type->num_ports; i++) {
++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2)
++ return -EINVAL;
++ }
++
++ /*
++ * The OOB port bulk-out buffer must be large enough for the two
++ * commands in digi_set_modem_signals().
++ */
++ oob_port_num = serial->type->num_ports;
++ if (serial->port[oob_port_num]->bulk_out_size < 8)
++ return -EINVAL;
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv)
+ return -ENOMEM;
+
+ spin_lock_init(&serial_priv->ds_serial_lock);
+- serial_priv->ds_oob_port_num = serial->type->num_ports;
+- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
++ serial_priv->ds_oob_port_num = oob_port_num;
++ serial_priv->ds_oob_port = serial->port[oob_port_num];
+
+ ret = digi_port_init(serial_priv->ds_oob_port,
+ serial_priv->ds_oob_port_num);
+--
+2.53.0
+
--- /dev/null
+From 78fd31285a78754d419d92a743c92caed3759571 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:19:09 +0800
+Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug
+
+From: Wei-Cheng Chen <weichengc@nvidia.com>
+
+[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ]
+
+When a USB device is unplugged from the dual-role port, the device-mode
+path in tegra_xhci_id_work() explicitly clears both SS and HS port power
+via direct hub_control ClearPortFeature(POWER) calls. This preempts the
+xHCI controller's normal disconnect processing -- PORT_CSC is never
+generated, the USB core never sees the disconnect, and the device remains
+in its internal tree as a ghost visible in lsusb.
+
+Add an otg_set_port_power flag to control whether the dual-role switch
+path performs explicit port power management. SoCs that need it
+(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and
+beyond) rely on the PHY mode change to handle disconnect naturally and
+skip all port power calls.
+
+Within the port power path, otg_reset_sspi additionally gates the SSPI
+reset sequence on host-mode entry for SoCs that require it.
+
+Flags set per SoC:
+ Tegra124, Tegra186 -> otg_set_port_power
+ Tegra210 -> otg_set_port_power, otg_reset_sspi
+ Tegra194 and later -> (none)
+
+[ Backport to 6.12.y: keep the host-mode snapshot in the existing
+ tegra->lock section, retain pm_runtime_mark_last_busy() in the host
+ port-power path, and resolve context around the SoC ops/Tegra234
+ entries. ]
+
+Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wei-Cheng Chen <weichengc@nvidia.com>
+Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-tegra.c | 79 ++++++++++++++++++++---------------
+ 1 file changed, 45 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
+index 89b3079194d7b3..2eb1aa25be1d37 100644
+--- a/drivers/usb/host/xhci-tegra.c
++++ b/drivers/usb/host/xhci-tegra.c
+@@ -243,6 +243,7 @@ struct tegra_xusb_soc {
+ bool has_ipfs;
+ bool lpm_support;
+ bool otg_reset_sspi;
++ bool otg_set_port_power;
+
+ bool has_bar2;
+ };
+@@ -1346,14 +1347,17 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ struct tegra_xusb_mbox_msg msg;
+ struct phy *phy = tegra_xusb_get_phy(tegra, "usb2",
+ tegra->otg_usb2_port);
++ bool host_mode;
+ u32 status;
+ int ret;
+
+- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off");
+-
+ mutex_lock(&tegra->lock);
+
+- if (tegra->host_mode)
++ host_mode = tegra->host_mode;
++
++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off");
++
++ if (host_mode)
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST);
+ else
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+@@ -1364,42 +1368,44 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ tegra->otg_usb2_port);
+
+ pm_runtime_get_sync(tegra->dev);
+- if (tegra->host_mode) {
+- /* switch to host mode */
+- if (tegra->otg_usb3_port >= 0) {
+- if (tegra->soc->otg_reset_sspi) {
+- /* set PP=0 */
+- tegra_xhci_hc_driver.hub_control(
+- xhci->shared_hcd, GetPortStatus,
+- 0, tegra->otg_usb3_port+1,
+- (char *) &status, sizeof(status));
+- if (status & USB_SS_PORT_STAT_POWER)
+- tegra_xhci_set_port_power(tegra, false,
+- false);
+-
+- /* reset OTG port SSPI */
+- msg.cmd = MBOX_CMD_RESET_SSPI;
+- msg.data = tegra->otg_usb3_port+1;
+-
+- ret = tegra_xusb_mbox_send(tegra, &msg);
+- if (ret < 0) {
+- dev_info(tegra->dev,
+- "failed to RESET_SSPI %d\n",
+- ret);
++ if (tegra->soc->otg_set_port_power) {
++ if (host_mode) {
++ /* switch to host mode */
++ if (tegra->otg_usb3_port >= 0) {
++ if (tegra->soc->otg_reset_sspi) {
++ /* set PP=0 */
++ tegra_xhci_hc_driver.hub_control(
++ xhci->shared_hcd, GetPortStatus,
++ 0, tegra->otg_usb3_port+1,
++ (char *) &status, sizeof(status));
++ if (status & USB_SS_PORT_STAT_POWER)
++ tegra_xhci_set_port_power(tegra, false,
++ false);
++
++ /* reset OTG port SSPI */
++ msg.cmd = MBOX_CMD_RESET_SSPI;
++ msg.data = tegra->otg_usb3_port+1;
++
++ ret = tegra_xusb_mbox_send(tegra, &msg);
++ if (ret < 0) {
++ dev_info(tegra->dev,
++ "failed to RESET_SSPI %d\n",
++ ret);
++ }
+ }
+- }
+
+- tegra_xhci_set_port_power(tegra, false, true);
+- }
++ tegra_xhci_set_port_power(tegra, false, true);
++ }
+
+- tegra_xhci_set_port_power(tegra, true, true);
+- pm_runtime_mark_last_busy(tegra->dev);
++ tegra_xhci_set_port_power(tegra, true, true);
++ pm_runtime_mark_last_busy(tegra->dev);
+
+- } else {
+- if (tegra->otg_usb3_port >= 0)
+- tegra_xhci_set_port_power(tegra, false, false);
++ } else {
++ if (tegra->otg_usb3_port >= 0)
++ tegra_xhci_set_port_power(tegra, false, false);
+
+- tegra_xhci_set_port_power(tegra, true, false);
++ tegra_xhci_set_port_power(tegra, true, false);
++ }
+ }
+ pm_runtime_put_autosuspend(tegra->dev);
+ }
+@@ -2497,6 +2503,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
+ .scale_ss_clock = true,
+ .has_ipfs = true,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2535,6 +2542,7 @@ static const struct tegra_xusb_soc tegra210_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = true,
+ .otg_reset_sspi = true,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2578,6 +2586,7 @@ static const struct tegra_xusb_soc tegra186_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2611,6 +2620,7 @@ static const struct tegra_xusb_soc tegra194_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0x68,
+@@ -2643,6 +2653,7 @@ static const struct tegra_xusb_soc tegra234_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .ops = &tegra234_ops,
+ .mbox = {
+ .cmd = XUSB_BAR2_ARU_MBOX_CMD,
+--
+2.53.0
+
--- /dev/null
+From e54bf04a6ae276230f5364a9a2437c5b4696dabe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Apr 2026 15:41:01 +0200
+Subject: net: phy: micrel: fix LAN8814 QSGMII soft reset
+
+From: Robert Marko <robert.marko@sartura.hr>
+
+[ Upstream commit e027c218c482c6a0ae1948129ccda3b0a2033368 ]
+
+LAN8814 QSGMII soft reset was moved into the probe function to avoid
+triggering it for each of 4 PHY-s in the package.
+
+However, that broke QSGMII link between the MAC and PHY on most LAN8814
+PHY-s, specificaly for us on the Microchip LAN969x switch.
+Reading the QSGMII status registers it was visible that lanes were only
+partially synced.
+
+It looks like the reset timing is crucial, so lets move the reset back
+into the .config_init function but guard it with phy_package_init_once()
+to avoid it being triggered on each of 4 PHY-s in the package.
+Change the probe function to use phy_package_probe_once() for coma and PtP
+setup.
+
+Fixes: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface")
+Signed-off-by: Robert Marko <robert.marko@sartura.hr>
+Link: https://patch.msgid.link/20260428134138.1741253-1-robert.marko@sartura.hr
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/micrel.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
+index bc19880107ae42..e6f00aa9a99010 100644
+--- a/drivers/net/phy/micrel.c
++++ b/drivers/net/phy/micrel.c
+@@ -4389,6 +4389,13 @@ static int lan8814_config_init(struct phy_device *phydev)
+ {
+ struct kszphy_priv *lan8814 = phydev->priv;
+
++ if (phy_package_init_once(phydev))
++ /* Reset the PHY */
++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
++ LAN8814_QSGMII_SOFT_RESET,
++ LAN8814_QSGMII_SOFT_RESET_BIT,
++ LAN8814_QSGMII_SOFT_RESET_BIT);
++
+ /* Disable ANEG with QSGMII PCS Host side */
+ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS,
+ LAN8814_QSGMII_PCS1G_ANEG_CONFIG,
+@@ -4473,13 +4480,7 @@ static int lan8814_probe(struct phy_device *phydev)
+ devm_phy_package_join(&phydev->mdio.dev, phydev,
+ addr, sizeof(struct lan8814_shared_priv));
+
+- if (phy_package_init_once(phydev)) {
+- /* Reset the PHY */
+- lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
+- LAN8814_QSGMII_SOFT_RESET,
+- LAN8814_QSGMII_SOFT_RESET_BIT,
+- LAN8814_QSGMII_SOFT_RESET_BIT);
+-
++ if (phy_package_probe_once(phydev)) {
+ err = lan8814_release_coma_mode(phydev);
+ if (err)
+ return err;
+--
+2.53.0
+
hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch
hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch
mm-slub-hold-cpus_read_lock-around-flush_rcu_sheaves_on_cache.patch
+net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch
+xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
--- /dev/null
+From addb52fab7c2e7217a5fd8707d34e42eccd4c165 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:19:07 +0800
+Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug
+
+From: Wei-Cheng Chen <weichengc@nvidia.com>
+
+[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ]
+
+When a USB device is unplugged from the dual-role port, the device-mode
+path in tegra_xhci_id_work() explicitly clears both SS and HS port power
+via direct hub_control ClearPortFeature(POWER) calls. This preempts the
+xHCI controller's normal disconnect processing -- PORT_CSC is never
+generated, the USB core never sees the disconnect, and the device remains
+in its internal tree as a ghost visible in lsusb.
+
+Add an otg_set_port_power flag to control whether the dual-role switch
+path performs explicit port power management. SoCs that need it
+(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and
+beyond) rely on the PHY mode change to handle disconnect naturally and
+skip all port power calls.
+
+Within the port power path, otg_reset_sspi additionally gates the SSPI
+reset sequence on host-mode entry for SoCs that require it.
+
+Flags set per SoC:
+ Tegra124, Tegra186 -> otg_set_port_power
+ Tegra210 -> otg_set_port_power, otg_reset_sspi
+ Tegra194 and later -> (none)
+
+[ Backport to 6.18.y: keep the host-mode snapshot in the existing
+ tegra->lock section, retain pm_runtime_mark_last_busy() in the host
+ port-power path, preserve str_on_off(), and resolve context around the
+ SoC ops/Tegra234 entries. ]
+
+Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wei-Cheng Chen <weichengc@nvidia.com>
+Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-tegra.c | 79 ++++++++++++++++++++---------------
+ 1 file changed, 45 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
+index 83b1766ff1521b..b0dcdede1fc8e6 100644
+--- a/drivers/usb/host/xhci-tegra.c
++++ b/drivers/usb/host/xhci-tegra.c
+@@ -247,6 +247,7 @@ struct tegra_xusb_soc {
+ bool has_ipfs;
+ bool lpm_support;
+ bool otg_reset_sspi;
++ bool otg_set_port_power;
+
+ bool has_bar2;
+ };
+@@ -1352,14 +1353,17 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ struct tegra_xusb_mbox_msg msg;
+ struct phy *phy = tegra_xusb_get_phy(tegra, "usb2",
+ tegra->otg_usb2_port);
++ bool host_mode;
+ u32 status;
+ int ret;
+
+- dev_dbg(tegra->dev, "host mode %s\n", str_on_off(tegra->host_mode));
+-
+ mutex_lock(&tegra->lock);
+
+- if (tegra->host_mode)
++ host_mode = tegra->host_mode;
++
++ dev_dbg(tegra->dev, "host mode %s\n", str_on_off(host_mode));
++
++ if (host_mode)
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST);
+ else
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+@@ -1370,42 +1374,44 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ tegra->otg_usb2_port);
+
+ pm_runtime_get_sync(tegra->dev);
+- if (tegra->host_mode) {
+- /* switch to host mode */
+- if (tegra->otg_usb3_port >= 0) {
+- if (tegra->soc->otg_reset_sspi) {
+- /* set PP=0 */
+- tegra_xhci_hc_driver.hub_control(
+- xhci->shared_hcd, GetPortStatus,
+- 0, tegra->otg_usb3_port+1,
+- (char *) &status, sizeof(status));
+- if (status & USB_SS_PORT_STAT_POWER)
+- tegra_xhci_set_port_power(tegra, false,
+- false);
+-
+- /* reset OTG port SSPI */
+- msg.cmd = MBOX_CMD_RESET_SSPI;
+- msg.data = tegra->otg_usb3_port+1;
+-
+- ret = tegra_xusb_mbox_send(tegra, &msg);
+- if (ret < 0) {
+- dev_info(tegra->dev,
+- "failed to RESET_SSPI %d\n",
+- ret);
++ if (tegra->soc->otg_set_port_power) {
++ if (host_mode) {
++ /* switch to host mode */
++ if (tegra->otg_usb3_port >= 0) {
++ if (tegra->soc->otg_reset_sspi) {
++ /* set PP=0 */
++ tegra_xhci_hc_driver.hub_control(
++ xhci->shared_hcd, GetPortStatus,
++ 0, tegra->otg_usb3_port+1,
++ (char *) &status, sizeof(status));
++ if (status & USB_SS_PORT_STAT_POWER)
++ tegra_xhci_set_port_power(tegra, false,
++ false);
++
++ /* reset OTG port SSPI */
++ msg.cmd = MBOX_CMD_RESET_SSPI;
++ msg.data = tegra->otg_usb3_port+1;
++
++ ret = tegra_xusb_mbox_send(tegra, &msg);
++ if (ret < 0) {
++ dev_info(tegra->dev,
++ "failed to RESET_SSPI %d\n",
++ ret);
++ }
+ }
+- }
+
+- tegra_xhci_set_port_power(tegra, false, true);
+- }
++ tegra_xhci_set_port_power(tegra, false, true);
++ }
+
+- tegra_xhci_set_port_power(tegra, true, true);
+- pm_runtime_mark_last_busy(tegra->dev);
++ tegra_xhci_set_port_power(tegra, true, true);
++ pm_runtime_mark_last_busy(tegra->dev);
+
+- } else {
+- if (tegra->otg_usb3_port >= 0)
+- tegra_xhci_set_port_power(tegra, false, false);
++ } else {
++ if (tegra->otg_usb3_port >= 0)
++ tegra_xhci_set_port_power(tegra, false, false);
+
+- tegra_xhci_set_port_power(tegra, true, false);
++ tegra_xhci_set_port_power(tegra, true, false);
++ }
+ }
+ pm_runtime_put_autosuspend(tegra->dev);
+ }
+@@ -2558,6 +2564,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
+ .scale_ss_clock = true,
+ .has_ipfs = true,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2596,6 +2603,7 @@ static const struct tegra_xusb_soc tegra210_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = true,
+ .otg_reset_sspi = true,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2639,6 +2647,7 @@ static const struct tegra_xusb_soc tegra186_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2672,6 +2681,7 @@ static const struct tegra_xusb_soc tegra194_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0x68,
+@@ -2705,6 +2715,7 @@ static const struct tegra_xusb_soc tegra234_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .ops = &tegra234_ops,
+ .mbox = {
+ .cmd = XUSB_BAR2_ARU_MBOX_CMD,
+--
+2.53.0
+
--- /dev/null
+From ca8a35121e0f51f8d597f6e6abdbc5dd719851d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 11:52:29 +0200
+Subject: Bluetooth: hci_sync: fix UAF in hci_le_create_cis_sync
+
+From: Doruk Tan Ozturk <doruk@0sec.ai>
+
+[ Upstream commit bfea6091e0fffb270c20e74384b660910277eb6c ]
+
+hci_le_create_cis_sync() dereferences conn->conn_timeout after releasing
+both rcu_read_lock() and hci_dev_lock(hdev). The conn pointer was
+obtained from an RCU-protected iteration over hdev->conn_hash.list and
+is not valid once these locks are dropped. A concurrent disconnect can
+free the hci_conn between the unlock and the dereference, causing a
+use-after-free read.
+
+The cancellation mechanism in hci_conn_del() cannot prevent this because
+hci_le_create_cis_pending() queues hci_create_cis_sync with data=NULL:
+
+ hci_cmd_sync_queue(hdev, hci_create_cis_sync, NULL, NULL);
+
+While hci_conn_del() dequeues with data=conn:
+
+ hci_cmd_sync_dequeue(hdev, NULL, conn, NULL);
+
+Since NULL != conn, the lookup in _hci_cmd_sync_lookup_entry() never
+matches, and the pending work item is not cancelled.
+
+Fix this by saving conn->conn_timeout into a local variable while the
+locks are still held, so the stale conn pointer is never dereferenced
+after unlock.
+
+This is the same class of bug as the one fixed by commit 035c25007c9e
+("Bluetooth: hci_sync: Fix UAF on le_read_features_complete") which
+addressed the identical pattern in a different function.
+
+This vulnerability was identified using 0sec.ai, an open-source
+automated security auditing platform (https://github.com/0sec-labs).
+
+Fixes: c09b80be6ffc ("Bluetooth: hci_conn: Fix not waiting for HCI_EVT_LE_CIS_ESTABLISHED")
+Cc: stable@vger.kernel.org
+Reported-by: Doruk Tan Ozturk <doruk@0sec.ai>
+Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+[doruk: adjust context for 6.6 \u2014 open-coded cmd struct instead of
+ DEFINE_FLEX, num_cis tracked via cmd.cp.num_cis]
+Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index a41cfc76e98bf1..7cba461b21de4f 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -6631,6 +6631,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
+ struct hci_cis cis[0x1f];
+ } cmd;
+ struct hci_conn *conn;
++ u16 timeout = 0;
+ u8 cig = BT_ISO_QOS_CIG_UNSET;
+
+ /* The spec allows only one pending LE Create CIS command at a time. If
+@@ -6703,6 +6704,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
+ set_bit(HCI_CONN_CREATE_CIS, &conn->flags);
+ cis->acl_handle = cpu_to_le16(conn->parent->handle);
+ cis->cis_handle = cpu_to_le16(conn->handle);
++ timeout = conn->conn_timeout;
+ cmd.cp.num_cis++;
+
+ if (cmd.cp.num_cis >= ARRAY_SIZE(cmd.cis))
+@@ -6722,7 +6724,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
+ sizeof(cmd.cp) + sizeof(cmd.cis[0]) *
+ cmd.cp.num_cis, &cmd,
+ HCI_EVT_LE_CIS_ESTABLISHED,
+- conn->conn_timeout, NULL);
++ timeout, NULL);
+ }
+
+ int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle)
+--
+2.53.0
+
--- /dev/null
+From 151919186817d3f00316eafd37a81b7e2f21db03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 18:16:18 +0800
+Subject: landlock: Fix handling of disconnected directories
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+[ Upstream commit 49c9e09d961025b22e61ef9ad56aa1c21b6ce2f1 ]
+
+Disconnected files or directories can appear when they are visible and
+opened from a bind mount, but have been renamed or moved from the source
+of the bind mount in a way that makes them inaccessible from the mount
+point (i.e. out of scope).
+
+Previously, access rights tied to files or directories opened through a
+disconnected directory were collected by walking the related hierarchy
+down to the root of the filesystem, without taking into account the
+mount point because it couldn't be found. This could lead to
+inconsistent access results, potential access right widening, and
+hard-to-debug renames, especially since such paths cannot be printed.
+
+For a sandboxed task to create a disconnected directory, it needs to
+have write access (i.e. FS_MAKE_REG, FS_REMOVE_FILE, and FS_REFER) to
+the underlying source of the bind mount, and read access to the related
+mount point. Because a sandboxed task cannot acquire more access
+rights than those defined by its Landlock domain, this could lead to
+inconsistent access rights due to missing permissions that should be
+inherited from the mount point hierarchy, while inheriting permissions
+from the filesystem hierarchy hidden by this mount point instead.
+
+Landlock now handles files and directories opened from disconnected
+directories by taking into account the filesystem hierarchy when the
+mount point is not found in the hierarchy walk, and also always taking
+into account the mount point from which these disconnected directories
+were opened. This ensures that a rename is not allowed if it would
+widen access rights [1].
+
+The rationale is that, even if disconnected hierarchies might not be
+visible or accessible to a sandboxed task, relying on the collected
+access rights from them improves the guarantee that access rights will
+not be widened during a rename because of the access right comparison
+between the source and the destination (see LANDLOCK_ACCESS_FS_REFER).
+It may look like this would grant more access on disconnected files and
+directories, but the security policies are always enforced for all the
+evaluated hierarchies. This new behavior should be less surprising to
+users and safer from an access control perspective.
+
+Remove a wrong WARN_ON_ONCE() canary in collect_domain_accesses() and
+fix the related comment.
+
+Because opened files have their access rights stored in the related file
+security properties, there is no impact for disconnected or unlinked
+files.
+
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Günther Noack <gnoack@google.com>
+Cc: Song Liu <song@kernel.org>
+Reported-by: Tingmao Wang <m@maowtm.org>
+Closes: https://lore.kernel.org/r/027d5190-b37a-40a8-84e9-4ccbc352bcdf@maowtm.org
+Closes: https://lore.kernel.org/r/09b24128f86973a6022e6aa8338945fcfb9a33e4.1749925391.git.m@maowtm.org
+Fixes: b91c3e4ea756 ("landlock: Add support for file reparenting with LANDLOCK_ACCESS_FS_REFER")
+Fixes: cb2c7d1a1776 ("landlock: Support filesystem access-control")
+Link: https://lore.kernel.org/r/b0f46246-f2c5-42ca-93ce-0d629702a987@maowtm.org [1]
+Reviewed-by: Tingmao Wang <m@maowtm.org>
+Link: https://lore.kernel.org/r/20251128172200.760753-2-mic@digikod.net
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+[ Adjust context ]
+Signed-off-by: Bin Lan <bin.lan.cn@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ security/landlock/errata/abi-1.h | 16 +++++++++++++
+ security/landlock/fs.c | 40 +++++++++++++++++++++++---------
+ 2 files changed, 45 insertions(+), 11 deletions(-)
+ create mode 100644 security/landlock/errata/abi-1.h
+
+diff --git a/security/landlock/errata/abi-1.h b/security/landlock/errata/abi-1.h
+new file mode 100644
+index 00000000000000..e8a2bff2e5b6a8
+--- /dev/null
++++ b/security/landlock/errata/abi-1.h
+@@ -0,0 +1,16 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++
++/**
++ * DOC: erratum_3
++ *
++ * Erratum 3: Disconnected directory handling
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ * This fix addresses an issue with disconnected directories that occur when a
++ * directory is moved outside the scope of a bind mount. The change ensures
++ * that evaluated access rights include both those from the disconnected file
++ * hierarchy down to its filesystem root and those from the related mount point
++ * hierarchy. This prevents access right widening through rename or link
++ * actions.
++ */
++LANDLOCK_ERRATUM(3)
+diff --git a/security/landlock/fs.c b/security/landlock/fs.c
+index fe4622d88eb15e..7145162f1e5971 100644
+--- a/security/landlock/fs.c
++++ b/security/landlock/fs.c
+@@ -616,19 +616,31 @@ static bool is_access_to_paths_allowed(
+ break;
+ }
+ }
++
+ if (unlikely(IS_ROOT(walker_path.dentry))) {
++ if (likely(walker_path.mnt->mnt_flags & MNT_INTERNAL)) {
++ /*
++ * Stops and allows access when reaching disconnected root
++ * directories that are part of internal filesystems (e.g. nsfs,
++ * which is reachable through /proc/<pid>/ns/<namespace>).
++ */
++ allowed_parent1 = true;
++ allowed_parent2 = true;
++ break;
++ }
++
+ /*
+- * Stops at disconnected root directories. Only allows
+- * access to internal filesystems (e.g. nsfs, which is
+- * reachable through /proc/<pid>/ns/<namespace>).
++ * We reached a disconnected root directory from a bind mount.
++ * Let's continue the walk with the mount point we missed.
+ */
+- allowed_parent1 = allowed_parent2 =
+- !!(walker_path.mnt->mnt_flags & MNT_INTERNAL);
+- break;
++ dput(walker_path.dentry);
++ walker_path.dentry = walker_path.mnt->mnt_root;
++ dget(walker_path.dentry);
++ } else {
++ parent_dentry = dget_parent(walker_path.dentry);
++ dput(walker_path.dentry);
++ walker_path.dentry = parent_dentry;
+ }
+- parent_dentry = dget_parent(walker_path.dentry);
+- dput(walker_path.dentry);
+- walker_path.dentry = parent_dentry;
+ }
+ path_put(&walker_path);
+
+@@ -705,6 +717,9 @@ static inline access_mask_t maybe_remove(const struct dentry *const dentry)
+ * file. While walking from @dir to @mnt_root, we record all the domain's
+ * allowed accesses in @layer_masks_dom.
+ *
++ * Because of disconnected directories, this walk may not reach @mnt_dir. In
++ * this case, the walk will continue to @mnt_dir after this call.
++ *
+ * This is similar to is_access_to_paths_allowed() but much simpler because it
+ * only handles walking on the same mount point and only checks one set of
+ * accesses.
+@@ -744,8 +759,11 @@ static bool collect_domain_accesses(
+ break;
+ }
+
+- /* We should not reach a root other than @mnt_root. */
+- if (dir == mnt_root || WARN_ON_ONCE(IS_ROOT(dir)))
++ /*
++ * Stops at the mount point or the filesystem root for a disconnected
++ * directory.
++ */
++ if (dir == mnt_root || unlikely(IS_ROOT(dir)))
+ break;
+
+ parent_dentry = dget_parent(dir);
+--
+2.53.0
+
serial-dz-fix-bootconsole-message-clobbering-at-chip-reset.patch
serial-zs-fix-bootconsole-handover-lockup.patch
serial-zs-switch-to-using-channel-reset.patch
+usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
+bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch
+x86-kexec-disable-kcov-instrumentation-after-load_se.patch
+landlock-fix-handling-of-disconnected-directories.patch
+usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
+xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
--- /dev/null
+From 3816ad8c11165edeaf9e5e5c43e4029529cd1cf4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 10:36:36 +0200
+Subject: USB: serial: cypress_m8: fix memory corruption with small endpoint
+
+From: Johan Hovold <johan@kernel.org>
+
+commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream.
+
+Make sure that the interrupt-out endpoint max packet size is at least
+eight bytes to avoid user-controlled slab corruption or NULL-pointer
+dereference should a malicious device report a smaller size.
+
+Fixes: 3416eaa1f8f8 ("USB: cypress_m8: Packet format is separate from characteristic size")
+Cc: stable@vger.kernel.org # 2.6.26
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+[ johan: adjust context for 6.18 ]
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/cypress_m8.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 4c625e77da3a8f..f567617c8f2314 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -448,6 +448,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
+ return -ENODEV;
+ }
+
++ /*
++ * The buffer must be large enough for the one or two-byte header (and
++ * following data), but assume anything smaller than eight bytes is
++ * broken.
++ */
++ if (port->interrupt_out_size < 8)
++ return -EINVAL;
++
+ priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+--
+2.53.0
+
--- /dev/null
+From a860946615a082d8fe3cd3bf70b740766b1147d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:07:58 +0200
+Subject: USB: serial: digi_acceleport: fix memory corruption with small
+ endpoints
+
+From: Johan Hovold <johan@kernel.org>
+
+commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream.
+
+Add the missing bulk-out buffer size sanity checks to avoid
+out-of-bounds memory accesses or slab corruption should a malicious
+device report smaller buffers than expected.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index d1dea38505762c..5eac99407c1611 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -1231,15 +1231,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
+ static int digi_startup(struct usb_serial *serial)
+ {
+ struct digi_serial *serial_priv;
++ int oob_port_num;
+ int ret;
++ int i;
++
++ /*
++ * The port bulk-out buffers must be large enough for header and
++ * buffered data.
++ */
++ for (i = 0; i < serial->type->num_ports; i++) {
++ if (serial->port[i]->bulk_out_size < DIGI_OUT_BUF_SIZE + 2)
++ return -EINVAL;
++ }
++
++ /*
++ * The OOB port bulk-out buffer must be large enough for the two
++ * commands in digi_set_modem_signals().
++ */
++ oob_port_num = serial->type->num_ports;
++ if (serial->port[oob_port_num]->bulk_out_size < 8)
++ return -EINVAL;
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv)
+ return -ENOMEM;
+
+ spin_lock_init(&serial_priv->ds_serial_lock);
+- serial_priv->ds_oob_port_num = serial->type->num_ports;
+- serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
++ serial_priv->ds_oob_port_num = oob_port_num;
++ serial_priv->ds_oob_port = serial->port[oob_port_num];
+
+ ret = digi_port_init(serial_priv->ds_oob_port,
+ serial_priv->ds_oob_port_num);
+--
+2.53.0
+
--- /dev/null
+From 0dbde02c2ae38a48c3fe38c4031ed099484e86bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 08:30:31 +0800
+Subject: x86/kexec: Disable KCOV instrumentation after load_segments()
+
+From: Aleksandr Nogikh <nogikh@google.com>
+
+[ Upstream commit 917e3ad3321e75ca0223d5ccf26ceda116aa51e1 ]
+
+The load_segments() function changes segment registers, invalidating GS base
+(which KCOV relies on for per-cpu data). When CONFIG_KCOV is enabled, any
+subsequent instrumented C code call (e.g. native_gdt_invalidate()) begins
+crashing the kernel in an endless loop.
+
+To reproduce the problem, it's sufficient to do kexec on a KCOV-instrumented
+kernel:
+
+ $ kexec -l /boot/otherKernel
+ $ kexec -e
+
+The real-world context for this problem is enabling crash dump collection in
+syzkaller. For this, the tool loads a panic kernel before fuzzing and then
+calls makedumpfile after the panic. This workflow requires both CONFIG_KEXEC
+and CONFIG_KCOV to be enabled simultaneously.
+
+Adding safeguards directly to the KCOV fast-path (__sanitizer_cov_trace_pc())
+is also undesirable as it would introduce an extra performance overhead.
+
+Disabling instrumentation for the individual functions would be too fragile,
+so disable KCOV instrumentation for the entire machine_kexec_64.c and
+physaddr.c. If coverage-guided fuzzing ever needs these components in the
+future, other approaches should be considered.
+
+The problem is not relevant for 32 bit kernels as CONFIG_KCOV is not supported
+there.
+
+ [ bp: Space out comment for better readability. ]
+
+Fixes: 0d345996e4cb ("x86/kernel: increase kcov coverage under arch/x86/kernel folder")
+Signed-off-by: Aleksandr Nogikh <nogikh@google.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260325154825.551191-1-nogikh@google.com
+Signed-off-by: Miles Wang <13621186580@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/Makefile | 14 ++++++++++++++
+ arch/x86/mm/Makefile | 2 ++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
+index 0000325ab98f4d..c1fe6c98d3f6e0 100644
+--- a/arch/x86/kernel/Makefile
++++ b/arch/x86/kernel/Makefile
+@@ -39,6 +39,20 @@ KMSAN_SANITIZE_nmi.o := n
+ KCOV_INSTRUMENT_head$(BITS).o := n
+ KCOV_INSTRUMENT_sev.o := n
+
++# Disable KCOV to prevent crashes during kexec: load_segments() invalidates
++# the GS base, which KCOV relies on for per-CPU data.
++#
++# As KCOV and KEXEC compatibility should be preserved (e.g. syzkaller is
++# using it to collect crash dumps during kernel fuzzing), disabling
++# KCOV for KEXEC kernels is not an option. Selectively disabling KCOV
++# instrumentation for individual affected functions can be fragile, while
++# adding more checks to KCOV would slow it down.
++#
++# As a compromise solution, disable KCOV instrumentation for the whole
++# source code file. If its coverage is ever needed, other approaches
++# should be considered.
++KCOV_INSTRUMENT_machine_kexec_64.o := n
++
+ CFLAGS_irq.o := -I $(srctree)/$(src)/../include/asm/trace
+
+ obj-y += head_$(BITS).o
+diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
+index c80febc44cd2fe..dd78ec8758f17e 100644
+--- a/arch/x86/mm/Makefile
++++ b/arch/x86/mm/Makefile
+@@ -5,6 +5,8 @@ KCOV_INSTRUMENT_mem_encrypt.o := n
+ KCOV_INSTRUMENT_mem_encrypt_amd.o := n
+ KCOV_INSTRUMENT_mem_encrypt_identity.o := n
+ KCOV_INSTRUMENT_pgprot.o := n
++# See the "Disable KCOV" comment in arch/x86/kernel/Makefile.
++KCOV_INSTRUMENT_physaddr.o := n
+
+ KASAN_SANITIZE_mem_encrypt.o := n
+ KASAN_SANITIZE_mem_encrypt_amd.o := n
+--
+2.53.0
+
--- /dev/null
+From d2d8ae5eaf9546e76d9dd8119511eb3b6e081ade Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:19:11 +0800
+Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug
+
+From: Wei-Cheng Chen <weichengc@nvidia.com>
+
+[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ]
+
+When a USB device is unplugged from the dual-role port, the device-mode
+path in tegra_xhci_id_work() explicitly clears both SS and HS port power
+via direct hub_control ClearPortFeature(POWER) calls. This preempts the
+xHCI controller's normal disconnect processing -- PORT_CSC is never
+generated, the USB core never sees the disconnect, and the device remains
+in its internal tree as a ghost visible in lsusb.
+
+Add an otg_set_port_power flag to control whether the dual-role switch
+path performs explicit port power management. SoCs that need it
+(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and
+beyond) rely on the PHY mode change to handle disconnect naturally and
+skip all port power calls.
+
+Within the port power path, otg_reset_sspi additionally gates the SSPI
+reset sequence on host-mode entry for SoCs that require it.
+
+Flags set per SoC:
+ Tegra124, Tegra186 -> otg_set_port_power
+ Tegra210 -> otg_set_port_power, otg_reset_sspi
+ Tegra194 and later -> (none)
+
+[ Backport to 6.6.y: keep the host-mode snapshot in the existing
+ tegra->lock section, retain pm_runtime_mark_last_busy() in the host
+ port-power path, and resolve context around the SoC ops/Tegra234
+ entries. ]
+
+Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wei-Cheng Chen <weichengc@nvidia.com>
+Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-tegra.c | 79 ++++++++++++++++++++---------------
+ 1 file changed, 45 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
+index 89b3079194d7b3..2eb1aa25be1d37 100644
+--- a/drivers/usb/host/xhci-tegra.c
++++ b/drivers/usb/host/xhci-tegra.c
+@@ -243,6 +243,7 @@ struct tegra_xusb_soc {
+ bool has_ipfs;
+ bool lpm_support;
+ bool otg_reset_sspi;
++ bool otg_set_port_power;
+
+ bool has_bar2;
+ };
+@@ -1346,14 +1347,17 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ struct tegra_xusb_mbox_msg msg;
+ struct phy *phy = tegra_xusb_get_phy(tegra, "usb2",
+ tegra->otg_usb2_port);
++ bool host_mode;
+ u32 status;
+ int ret;
+
+- dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off");
+-
+ mutex_lock(&tegra->lock);
+
+- if (tegra->host_mode)
++ host_mode = tegra->host_mode;
++
++ dev_dbg(tegra->dev, "host mode %s\n", host_mode ? "on" : "off");
++
++ if (host_mode)
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST);
+ else
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+@@ -1364,42 +1368,44 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ tegra->otg_usb2_port);
+
+ pm_runtime_get_sync(tegra->dev);
+- if (tegra->host_mode) {
+- /* switch to host mode */
+- if (tegra->otg_usb3_port >= 0) {
+- if (tegra->soc->otg_reset_sspi) {
+- /* set PP=0 */
+- tegra_xhci_hc_driver.hub_control(
+- xhci->shared_hcd, GetPortStatus,
+- 0, tegra->otg_usb3_port+1,
+- (char *) &status, sizeof(status));
+- if (status & USB_SS_PORT_STAT_POWER)
+- tegra_xhci_set_port_power(tegra, false,
+- false);
+-
+- /* reset OTG port SSPI */
+- msg.cmd = MBOX_CMD_RESET_SSPI;
+- msg.data = tegra->otg_usb3_port+1;
+-
+- ret = tegra_xusb_mbox_send(tegra, &msg);
+- if (ret < 0) {
+- dev_info(tegra->dev,
+- "failed to RESET_SSPI %d\n",
+- ret);
++ if (tegra->soc->otg_set_port_power) {
++ if (host_mode) {
++ /* switch to host mode */
++ if (tegra->otg_usb3_port >= 0) {
++ if (tegra->soc->otg_reset_sspi) {
++ /* set PP=0 */
++ tegra_xhci_hc_driver.hub_control(
++ xhci->shared_hcd, GetPortStatus,
++ 0, tegra->otg_usb3_port+1,
++ (char *) &status, sizeof(status));
++ if (status & USB_SS_PORT_STAT_POWER)
++ tegra_xhci_set_port_power(tegra, false,
++ false);
++
++ /* reset OTG port SSPI */
++ msg.cmd = MBOX_CMD_RESET_SSPI;
++ msg.data = tegra->otg_usb3_port+1;
++
++ ret = tegra_xusb_mbox_send(tegra, &msg);
++ if (ret < 0) {
++ dev_info(tegra->dev,
++ "failed to RESET_SSPI %d\n",
++ ret);
++ }
+ }
+- }
+
+- tegra_xhci_set_port_power(tegra, false, true);
+- }
++ tegra_xhci_set_port_power(tegra, false, true);
++ }
+
+- tegra_xhci_set_port_power(tegra, true, true);
+- pm_runtime_mark_last_busy(tegra->dev);
++ tegra_xhci_set_port_power(tegra, true, true);
++ pm_runtime_mark_last_busy(tegra->dev);
+
+- } else {
+- if (tegra->otg_usb3_port >= 0)
+- tegra_xhci_set_port_power(tegra, false, false);
++ } else {
++ if (tegra->otg_usb3_port >= 0)
++ tegra_xhci_set_port_power(tegra, false, false);
+
+- tegra_xhci_set_port_power(tegra, true, false);
++ tegra_xhci_set_port_power(tegra, true, false);
++ }
+ }
+ pm_runtime_put_autosuspend(tegra->dev);
+ }
+@@ -2497,6 +2503,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
+ .scale_ss_clock = true,
+ .has_ipfs = true,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2535,6 +2542,7 @@ static const struct tegra_xusb_soc tegra210_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = true,
+ .otg_reset_sspi = true,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2578,6 +2586,7 @@ static const struct tegra_xusb_soc tegra186_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2611,6 +2620,7 @@ static const struct tegra_xusb_soc tegra194_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0x68,
+@@ -2643,6 +2653,7 @@ static const struct tegra_xusb_soc tegra234_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .ops = &tegra234_ops,
+ .mbox = {
+ .cmd = XUSB_BAR2_ARU_MBOX_CMD,
+--
+2.53.0
+
--- /dev/null
+From 053fa58cc11c8f2a0fda1c48d4f3a410d6aa49db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Apr 2026 15:41:01 +0200
+Subject: net: phy: micrel: fix LAN8814 QSGMII soft reset
+
+From: Robert Marko <robert.marko@sartura.hr>
+
+[ Upstream commit e027c218c482c6a0ae1948129ccda3b0a2033368 ]
+
+LAN8814 QSGMII soft reset was moved into the probe function to avoid
+triggering it for each of 4 PHY-s in the package.
+
+However, that broke QSGMII link between the MAC and PHY on most LAN8814
+PHY-s, specificaly for us on the Microchip LAN969x switch.
+Reading the QSGMII status registers it was visible that lanes were only
+partially synced.
+
+It looks like the reset timing is crucial, so lets move the reset back
+into the .config_init function but guard it with phy_package_init_once()
+to avoid it being triggered on each of 4 PHY-s in the package.
+Change the probe function to use phy_package_probe_once() for coma and PtP
+setup.
+
+Fixes: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface")
+Signed-off-by: Robert Marko <robert.marko@sartura.hr>
+Link: https://patch.msgid.link/20260428134138.1741253-1-robert.marko@sartura.hr
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/micrel.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
+index c6b011a9d63698..23305be8c7fac7 100644
+--- a/drivers/net/phy/micrel.c
++++ b/drivers/net/phy/micrel.c
+@@ -4548,6 +4548,13 @@ static int lan8814_config_init(struct phy_device *phydev)
+ struct kszphy_priv *lan8814 = phydev->priv;
+ int ret;
+
++ if (phy_package_init_once(phydev))
++ /* Reset the PHY */
++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
++ LAN8814_QSGMII_SOFT_RESET,
++ LAN8814_QSGMII_SOFT_RESET_BIT,
++ LAN8814_QSGMII_SOFT_RESET_BIT);
++
+ /* Based on the interface type select how the advertise ability is
+ * encoded, to set as SGMII or as USGMII.
+ */
+@@ -4655,13 +4662,7 @@ static int lan8814_probe(struct phy_device *phydev)
+ priv->is_ptp_available = err == LAN8814_REV_LAN8814 ||
+ err == LAN8814_REV_LAN8818;
+
+- if (phy_package_init_once(phydev)) {
+- /* Reset the PHY */
+- lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
+- LAN8814_QSGMII_SOFT_RESET,
+- LAN8814_QSGMII_SOFT_RESET_BIT,
+- LAN8814_QSGMII_SOFT_RESET_BIT);
+-
++ if (phy_package_probe_once(phydev)) {
+ err = lan8814_release_coma_mode(phydev);
+ if (err)
+ return err;
+--
+2.53.0
+
hwmon-pmbus-add-support-for-guarded-pmbus-lock.patch
hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch
hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch
+net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch
+xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
--- /dev/null
+From c760846a5e78bb06fd99efcbefd1293903a9c821 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:09:14 +0800
+Subject: xhci: tegra: Fix ghost USB device on dual-role port unplug
+
+From: Wei-Cheng Chen <weichengc@nvidia.com>
+
+[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ]
+
+When a USB device is unplugged from the dual-role port, the device-mode
+path in tegra_xhci_id_work() explicitly clears both SS and HS port power
+via direct hub_control ClearPortFeature(POWER) calls. This preempts the
+xHCI controller's normal disconnect processing -- PORT_CSC is never
+generated, the USB core never sees the disconnect, and the device remains
+in its internal tree as a ghost visible in lsusb.
+
+Add an otg_set_port_power flag to control whether the dual-role switch
+path performs explicit port power management. SoCs that need it
+(Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and
+beyond) rely on the PHY mode change to handle disconnect naturally and
+skip all port power calls.
+
+Within the port power path, otg_reset_sspi additionally gates the SSPI
+reset sequence on host-mode entry for SoCs that require it.
+
+Flags set per SoC:
+ Tegra124, Tegra186 -> otg_set_port_power
+ Tegra210 -> otg_set_port_power, otg_reset_sspi
+ Tegra194 and later -> (none)
+
+[ Backport to 7.0.y: keep the host-mode snapshot in the existing
+ tegra->lock section, preserve str_on_off(), and resolve context around
+ the SoC ops/Tegra234 entries. ]
+
+Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wei-Cheng Chen <weichengc@nvidia.com>
+Link: https://patch.msgid.link/20260505112630.217704-1-weichengc@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-tegra.c | 77 ++++++++++++++++++++---------------
+ 1 file changed, 44 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
+index 3f6aa2440b05b9..ddc52d1e0edaf7 100644
+--- a/drivers/usb/host/xhci-tegra.c
++++ b/drivers/usb/host/xhci-tegra.c
+@@ -247,6 +247,7 @@ struct tegra_xusb_soc {
+ bool has_ipfs;
+ bool lpm_support;
+ bool otg_reset_sspi;
++ bool otg_set_port_power;
+
+ bool has_bar2;
+ };
+@@ -1352,14 +1353,17 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ struct tegra_xusb_mbox_msg msg;
+ struct phy *phy = tegra_xusb_get_phy(tegra, "usb2",
+ tegra->otg_usb2_port);
++ bool host_mode;
+ u32 status;
+ int ret;
+
+- dev_dbg(tegra->dev, "host mode %s\n", str_on_off(tegra->host_mode));
+-
+ mutex_lock(&tegra->lock);
+
+- if (tegra->host_mode)
++ host_mode = tegra->host_mode;
++
++ dev_dbg(tegra->dev, "host mode %s\n", str_on_off(host_mode));
++
++ if (host_mode)
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST);
+ else
+ phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+@@ -1370,41 +1374,43 @@ static void tegra_xhci_id_work(struct work_struct *work)
+ tegra->otg_usb2_port);
+
+ pm_runtime_get_sync(tegra->dev);
+- if (tegra->host_mode) {
+- /* switch to host mode */
+- if (tegra->otg_usb3_port >= 0) {
+- if (tegra->soc->otg_reset_sspi) {
+- /* set PP=0 */
+- tegra_xhci_hc_driver.hub_control(
+- xhci->shared_hcd, GetPortStatus,
+- 0, tegra->otg_usb3_port+1,
+- (char *) &status, sizeof(status));
+- if (status & USB_SS_PORT_STAT_POWER)
+- tegra_xhci_set_port_power(tegra, false,
+- false);
+-
+- /* reset OTG port SSPI */
+- msg.cmd = MBOX_CMD_RESET_SSPI;
+- msg.data = tegra->otg_usb3_port+1;
+-
+- ret = tegra_xusb_mbox_send(tegra, &msg);
+- if (ret < 0) {
+- dev_info(tegra->dev,
+- "failed to RESET_SSPI %d\n",
+- ret);
++ if (tegra->soc->otg_set_port_power) {
++ if (host_mode) {
++ /* switch to host mode */
++ if (tegra->otg_usb3_port >= 0) {
++ if (tegra->soc->otg_reset_sspi) {
++ /* set PP=0 */
++ tegra_xhci_hc_driver.hub_control(
++ xhci->shared_hcd, GetPortStatus,
++ 0, tegra->otg_usb3_port+1,
++ (char *) &status, sizeof(status));
++ if (status & USB_SS_PORT_STAT_POWER)
++ tegra_xhci_set_port_power(tegra, false,
++ false);
++
++ /* reset OTG port SSPI */
++ msg.cmd = MBOX_CMD_RESET_SSPI;
++ msg.data = tegra->otg_usb3_port+1;
++
++ ret = tegra_xusb_mbox_send(tegra, &msg);
++ if (ret < 0) {
++ dev_info(tegra->dev,
++ "failed to RESET_SSPI %d\n",
++ ret);
++ }
+ }
+- }
+
+- tegra_xhci_set_port_power(tegra, false, true);
+- }
++ tegra_xhci_set_port_power(tegra, false, true);
++ }
+
+- tegra_xhci_set_port_power(tegra, true, true);
++ tegra_xhci_set_port_power(tegra, true, true);
+
+- } else {
+- if (tegra->otg_usb3_port >= 0)
+- tegra_xhci_set_port_power(tegra, false, false);
++ } else {
++ if (tegra->otg_usb3_port >= 0)
++ tegra_xhci_set_port_power(tegra, false, false);
+
+- tegra_xhci_set_port_power(tegra, true, false);
++ tegra_xhci_set_port_power(tegra, true, false);
++ }
+ }
+ pm_runtime_put_autosuspend(tegra->dev);
+ }
+@@ -2557,6 +2563,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
+ .scale_ss_clock = true,
+ .has_ipfs = true,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2595,6 +2602,7 @@ static const struct tegra_xusb_soc tegra210_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = true,
+ .otg_reset_sspi = true,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2638,6 +2646,7 @@ static const struct tegra_xusb_soc tegra186_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = true,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0xe4,
+@@ -2671,6 +2680,7 @@ static const struct tegra_xusb_soc tegra194_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .ops = &tegra124_ops,
+ .mbox = {
+ .cmd = 0x68,
+@@ -2704,6 +2714,7 @@ static const struct tegra_xusb_soc tegra234_soc = {
+ .scale_ss_clock = false,
+ .has_ipfs = false,
+ .otg_reset_sspi = false,
++ .otg_set_port_power = false,
+ .ops = &tegra234_ops,
+ .mbox = {
+ .cmd = XUSB_BAR2_ARU_MBOX_CMD,
+--
+2.53.0
+