]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees master
authorSasha Levin <sashal@kernel.org>
Fri, 5 Jun 2026 19:37:14 +0000 (15:37 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 5 Jun 2026 19:37:14 +0000 (15:37 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
38 files changed:
queue-5.10/bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch [new file with mode: 0644]
queue-5.10/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch [new file with mode: 0644]
queue-5.10/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch [new file with mode: 0644]
queue-5.15/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch [new file with mode: 0644]
queue-5.15/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch [new file with mode: 0644]
queue-5.15/hid-pass-the-buffer-size-to-hid_report_raw_event.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch [new file with mode: 0644]
queue-5.15/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch [new file with mode: 0644]
queue-5.15/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch [new file with mode: 0644]
queue-6.1/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch [new file with mode: 0644]
queue-6.1/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch [new file with mode: 0644]
queue-6.1/hid-pass-the-buffer-size-to-hid_report_raw_event.patch [new file with mode: 0644]
queue-6.1/netfilter-nf_tables-restore-set-elements-when-delete.patch [new file with mode: 0644]
queue-6.1/rdma-rxe-complete-the-rxe_cleanup_task-backport.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch [new file with mode: 0644]
queue-6.1/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch [new file with mode: 0644]
queue-6.1/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch [new file with mode: 0644]
queue-6.12/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch [new file with mode: 0644]
queue-6.12/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch [new file with mode: 0644]
queue-6.18/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch [new file with mode: 0644]
queue-6.18/series
queue-6.18/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch [new file with mode: 0644]
queue-6.6/bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch [new file with mode: 0644]
queue-6.6/landlock-fix-handling-of-disconnected-directories.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch [new file with mode: 0644]
queue-6.6/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch [new file with mode: 0644]
queue-6.6/x86-kexec-disable-kcov-instrumentation-after-load_se.patch [new file with mode: 0644]
queue-6.6/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch [new file with mode: 0644]
queue-7.0/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch [new file with mode: 0644]
queue-7.0/series
queue-7.0/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch [new file with mode: 0644]

diff --git a/queue-5.10/bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch b/queue-5.10/bluetooth-hci_core-fix-use-after-free-in-vhci_flush.patch
new file mode 100644 (file)
index 0000000..aa17e5d
--- /dev/null
@@ -0,0 +1,253 @@
+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
+
index c2ae51e021507ab32aa58dd8971a890893818725..fba3779f740d45facb11b1865466072e0bee1c9c 100644 (file)
@@ -113,3 +113,7 @@ serial-fsl_lpuart-fix-rx-buffer-and-dma-map-leaks-in-start_rx_dma.patch
 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
diff --git a/queue-5.10/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-5.10/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
new file mode 100644 (file)
index 0000000..3b47f07
--- /dev/null
@@ -0,0 +1,46 @@
+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
+
diff --git a/queue-5.10/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-5.10/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
new file mode 100644 (file)
index 0000000..e21a402
--- /dev/null
@@ -0,0 +1,67 @@
+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
+
diff --git a/queue-5.10/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-5.10/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
new file mode 100644 (file)
index 0000000..c4a34bd
--- /dev/null
@@ -0,0 +1,188 @@
+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
+
diff --git a/queue-5.15/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch b/queue-5.15/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch
new file mode 100644 (file)
index 0000000..32f26f7
--- /dev/null
@@ -0,0 +1,43 @@
+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
+
diff --git a/queue-5.15/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch b/queue-5.15/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch
new file mode 100644 (file)
index 0000000..332dad6
--- /dev/null
@@ -0,0 +1,67 @@
+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
+
diff --git a/queue-5.15/hid-pass-the-buffer-size-to-hid_report_raw_event.patch b/queue-5.15/hid-pass-the-buffer-size-to-hid_report_raw_event.patch
new file mode 100644 (file)
index 0000000..06f5522
--- /dev/null
@@ -0,0 +1,269 @@
+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
+
index ca649ea2220dc6b0f718ab601e7b92d9b26d52bf..5bc0113b3d58f97203dd81636e7f5493fda8e497 100644 (file)
@@ -133,3 +133,9 @@ serial-fsl_lpuart-fix-rx-buffer-and-dma-map-leaks-in-start_rx_dma.patch
 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
diff --git a/queue-5.15/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-5.15/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
new file mode 100644 (file)
index 0000000..7d33456
--- /dev/null
@@ -0,0 +1,46 @@
+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
+
diff --git a/queue-5.15/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-5.15/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
new file mode 100644 (file)
index 0000000..8149b0d
--- /dev/null
@@ -0,0 +1,67 @@
+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
+
diff --git a/queue-5.15/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-5.15/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
new file mode 100644 (file)
index 0000000..3baf88b
--- /dev/null
@@ -0,0 +1,188 @@
+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
+
diff --git a/queue-6.1/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch b/queue-6.1/hid-core-add-printk_ratelimited-variants-to-hid_warn.patch
new file mode 100644 (file)
index 0000000..dc665d0
--- /dev/null
@@ -0,0 +1,42 @@
+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
+
diff --git a/queue-6.1/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch b/queue-6.1/hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch
new file mode 100644 (file)
index 0000000..2c1c211
--- /dev/null
@@ -0,0 +1,66 @@
+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
+
diff --git a/queue-6.1/hid-pass-the-buffer-size-to-hid_report_raw_event.patch b/queue-6.1/hid-pass-the-buffer-size-to-hid_report_raw_event.patch
new file mode 100644 (file)
index 0000000..63179d6
--- /dev/null
@@ -0,0 +1,276 @@
+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
+
diff --git a/queue-6.1/netfilter-nf_tables-restore-set-elements-when-delete.patch b/queue-6.1/netfilter-nf_tables-restore-set-elements-when-delete.patch
new file mode 100644 (file)
index 0000000..1370232
--- /dev/null
@@ -0,0 +1,324 @@
+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
+
diff --git a/queue-6.1/rdma-rxe-complete-the-rxe_cleanup_task-backport.patch b/queue-6.1/rdma-rxe-complete-the-rxe_cleanup_task-backport.patch
new file mode 100644 (file)
index 0000000..acc7ab8
--- /dev/null
@@ -0,0 +1,62 @@
+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
+
index 6687d865a182ec46c5fd8c9c3968e81c415f5407..8a3815650bc78d76fdc108188b66041df9110b28 100644 (file)
@@ -177,3 +177,11 @@ drm-amdkfd-check-for-pdd-drm-file-first-in-criu-restore-path.patch
 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
diff --git a/queue-6.1/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-6.1/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
new file mode 100644 (file)
index 0000000..fc95322
--- /dev/null
@@ -0,0 +1,46 @@
+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
+
diff --git a/queue-6.1/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-6.1/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
new file mode 100644 (file)
index 0000000..86bf4a6
--- /dev/null
@@ -0,0 +1,67 @@
+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
+
diff --git a/queue-6.1/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-6.1/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
new file mode 100644 (file)
index 0000000..3a057fb
--- /dev/null
@@ -0,0 +1,188 @@
+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
+
index d7cf1d2ab67a60de7dbb4dfdcb2a5d904c250743..223bcd70f9f1f634db046496ca4de4ab7bbbfca6 100644 (file)
@@ -259,3 +259,6 @@ serial-dz-convert-to-use-a-platform-device.patch
 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
diff --git a/queue-6.12/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-6.12/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
new file mode 100644 (file)
index 0000000..4ac4628
--- /dev/null
@@ -0,0 +1,46 @@
+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
+
diff --git a/queue-6.12/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-6.12/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
new file mode 100644 (file)
index 0000000..70640c9
--- /dev/null
@@ -0,0 +1,67 @@
+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
+
diff --git a/queue-6.12/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-6.12/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
new file mode 100644 (file)
index 0000000..e928e4f
--- /dev/null
@@ -0,0 +1,197 @@
+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
+
diff --git a/queue-6.18/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch b/queue-6.18/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch
new file mode 100644 (file)
index 0000000..f6b7935
--- /dev/null
@@ -0,0 +1,68 @@
+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
+
index 5c4bf834c900aada0b0267649f7e5319fbf99f1d..dd2be7c583502c34bed0c811bb4a1b77ad05b572 100644 (file)
@@ -308,3 +308,5 @@ 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
 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
diff --git a/queue-6.18/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-6.18/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
new file mode 100644 (file)
index 0000000..522c428
--- /dev/null
@@ -0,0 +1,197 @@
+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
+
diff --git a/queue-6.6/bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch b/queue-6.6/bluetooth-hci_sync-fix-uaf-in-hci_le_create_cis_sync.patch
new file mode 100644 (file)
index 0000000..06dafea
--- /dev/null
@@ -0,0 +1,84 @@
+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
+
diff --git a/queue-6.6/landlock-fix-handling-of-disconnected-directories.patch b/queue-6.6/landlock-fix-handling-of-disconnected-directories.patch
new file mode 100644 (file)
index 0000000..e82b741
--- /dev/null
@@ -0,0 +1,172 @@
+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
+
index c84d96a748fc97ed5a1de148fd4b553485a5fdce..726695120e82d8ac80bad6bfb756f588ed21b4c9 100644 (file)
@@ -189,3 +189,9 @@ drm-amdkfd-check-for-pdd-drm-file-first-in-criu-restore-path.patch
 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
diff --git a/queue-6.6/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch b/queue-6.6/usb-serial-cypress_m8-fix-memory-corruption-with-sma.patch
new file mode 100644 (file)
index 0000000..ed656e6
--- /dev/null
@@ -0,0 +1,46 @@
+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
+
diff --git a/queue-6.6/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch b/queue-6.6/usb-serial-digi_acceleport-fix-memory-corruption-wit.patch
new file mode 100644 (file)
index 0000000..6d8037c
--- /dev/null
@@ -0,0 +1,67 @@
+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
+
diff --git a/queue-6.6/x86-kexec-disable-kcov-instrumentation-after-load_se.patch b/queue-6.6/x86-kexec-disable-kcov-instrumentation-after-load_se.patch
new file mode 100644 (file)
index 0000000..d0abc25
--- /dev/null
@@ -0,0 +1,92 @@
+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
+
diff --git a/queue-6.6/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-6.6/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
new file mode 100644 (file)
index 0000000..dd6aa49
--- /dev/null
@@ -0,0 +1,197 @@
+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
+
diff --git a/queue-7.0/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch b/queue-7.0/net-phy-micrel-fix-lan8814-qsgmii-soft-reset.patch
new file mode 100644 (file)
index 0000000..ee25483
--- /dev/null
@@ -0,0 +1,68 @@
+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
+
index c3783d96f08136b1f55ce50f650bb9f8d17c870b..13f68c95ad854d9be8202ae61bfddc7e4689db1b 100644 (file)
@@ -327,3 +327,5 @@ i2c-tegra-make-tegra_i2c_mutex_unlock-return-void.patch
 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
diff --git a/queue-7.0/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch b/queue-7.0/xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch
new file mode 100644 (file)
index 0000000..ee92181
--- /dev/null
@@ -0,0 +1,194 @@
+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
+