]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Mar 2026 15:49:34 +0000 (16:49 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Mar 2026 15:49:34 +0000 (16:49 +0100)
added patches:
asoc-amd-yc-add-dmi-quirk-for-asus-expertbook-pm1503cda.patch
ata-libata-core-add-bridge_ok-quirk-for-qemu-drives.patch
kvm-arm64-fix-protected-mode-handling-of-pages-larger-than-4kb.patch
kvm-arm64-pkvm-don-t-reprobe-for-ich_vtr_el2.tds-on-cpu-hotplug.patch
kvm-arm64-pkvm-fallback-to-level-3-mapping-on-host-stage-2-fault.patch
kvm-arm64-vgic-pick-eoicount-deactivations-from-ap-list-tail.patch
kvm-svm-initialize-avic-vmcb-fields-if-avic-is-enabled-with-in-kernel-apic.patch
kvm-svm-set-clear-cr8-write-interception-when-avic-is-de-activated.patch
kvm-x86-introduce-kvm_x86_quirk_vmcs12_allow_freeze_in_smm.patch
revert-usb-gadget-f_ncm-align-net_device-lifecycle-with-bind-unbind.patch
revert-usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch
revert-usb-gadget-u_ether-add-auto-cleanup-helper-for-freeing-net_device.patch
revert-usb-gadget-u_ether-add-gether_opts-for-config-caching.patch
revert-usb-legacy-ncm-fix-npe-in-gncm_bind.patch
usb-add-quirk_no_bos-for-video-capture-several-devices.patch
usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch
usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch
usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch
usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch
usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch
usb-dwc3-pci-add-support-for-the-intel-nova-lake-h.patch
usb-ezcap401-needs-usb_quirk_no_bos-to-function-on-10gbs-usb-speed.patch
usb-gadget-f_hid-fix-superspeed-descriptors.patch
usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch
usb-gadget-f_tcm-fix-null-pointer-dereferences-in-nexus-handling.patch
usb-gadget-uvc-fix-interval_duration-calculation.patch
usb-image-mdc800-kill-download-urb-on-timeout.patch
usb-legacy-ncm-fix-npe-in-gncm_bind.patch
usb-mdc800-handle-signal-and-read-racing.patch
usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch
usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch
usb-roles-get-usb-role-switch-from-parent-only-for-usb-b-connector.patch
usb-typec-altmode-displayport-set-displayport-signaling-rate-in-configure-message.patch
usb-usbcore-introduce-usb_bulk_msg_killable.patch
usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch
usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch
usb-xhci-prevent-interrupt-storm-on-host-controller-error-hce.patch
usb-yurex-fix-race-in-probe.patch
xhci-fix-null-pointer-dereference-when-reading-portli-debugfs-files.patch

40 files changed:
queue-6.19/asoc-amd-yc-add-dmi-quirk-for-asus-expertbook-pm1503cda.patch [new file with mode: 0644]
queue-6.19/ata-libata-core-add-bridge_ok-quirk-for-qemu-drives.patch [new file with mode: 0644]
queue-6.19/kvm-arm64-fix-protected-mode-handling-of-pages-larger-than-4kb.patch [new file with mode: 0644]
queue-6.19/kvm-arm64-pkvm-don-t-reprobe-for-ich_vtr_el2.tds-on-cpu-hotplug.patch [new file with mode: 0644]
queue-6.19/kvm-arm64-pkvm-fallback-to-level-3-mapping-on-host-stage-2-fault.patch [new file with mode: 0644]
queue-6.19/kvm-arm64-vgic-pick-eoicount-deactivations-from-ap-list-tail.patch [new file with mode: 0644]
queue-6.19/kvm-svm-initialize-avic-vmcb-fields-if-avic-is-enabled-with-in-kernel-apic.patch [new file with mode: 0644]
queue-6.19/kvm-svm-set-clear-cr8-write-interception-when-avic-is-de-activated.patch [new file with mode: 0644]
queue-6.19/kvm-x86-introduce-kvm_x86_quirk_vmcs12_allow_freeze_in_smm.patch [new file with mode: 0644]
queue-6.19/revert-usb-gadget-f_ncm-align-net_device-lifecycle-with-bind-unbind.patch [new file with mode: 0644]
queue-6.19/revert-usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch [new file with mode: 0644]
queue-6.19/revert-usb-gadget-u_ether-add-auto-cleanup-helper-for-freeing-net_device.patch [new file with mode: 0644]
queue-6.19/revert-usb-gadget-u_ether-add-gether_opts-for-config-caching.patch [new file with mode: 0644]
queue-6.19/revert-usb-legacy-ncm-fix-npe-in-gncm_bind.patch [new file with mode: 0644]
queue-6.19/series
queue-6.19/usb-add-quirk_no_bos-for-video-capture-several-devices.patch [new file with mode: 0644]
queue-6.19/usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch [new file with mode: 0644]
queue-6.19/usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch [new file with mode: 0644]
queue-6.19/usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch [new file with mode: 0644]
queue-6.19/usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch [new file with mode: 0644]
queue-6.19/usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch [new file with mode: 0644]
queue-6.19/usb-dwc3-pci-add-support-for-the-intel-nova-lake-h.patch [new file with mode: 0644]
queue-6.19/usb-ezcap401-needs-usb_quirk_no_bos-to-function-on-10gbs-usb-speed.patch [new file with mode: 0644]
queue-6.19/usb-gadget-f_hid-fix-superspeed-descriptors.patch [new file with mode: 0644]
queue-6.19/usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch [new file with mode: 0644]
queue-6.19/usb-gadget-f_tcm-fix-null-pointer-dereferences-in-nexus-handling.patch [new file with mode: 0644]
queue-6.19/usb-gadget-uvc-fix-interval_duration-calculation.patch [new file with mode: 0644]
queue-6.19/usb-image-mdc800-kill-download-urb-on-timeout.patch [new file with mode: 0644]
queue-6.19/usb-legacy-ncm-fix-npe-in-gncm_bind.patch [new file with mode: 0644]
queue-6.19/usb-mdc800-handle-signal-and-read-racing.patch [new file with mode: 0644]
queue-6.19/usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch [new file with mode: 0644]
queue-6.19/usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch [new file with mode: 0644]
queue-6.19/usb-roles-get-usb-role-switch-from-parent-only-for-usb-b-connector.patch [new file with mode: 0644]
queue-6.19/usb-typec-altmode-displayport-set-displayport-signaling-rate-in-configure-message.patch [new file with mode: 0644]
queue-6.19/usb-usbcore-introduce-usb_bulk_msg_killable.patch [new file with mode: 0644]
queue-6.19/usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch [new file with mode: 0644]
queue-6.19/usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch [new file with mode: 0644]
queue-6.19/usb-xhci-prevent-interrupt-storm-on-host-controller-error-hce.patch [new file with mode: 0644]
queue-6.19/usb-yurex-fix-race-in-probe.patch [new file with mode: 0644]
queue-6.19/xhci-fix-null-pointer-dereference-when-reading-portli-debugfs-files.patch [new file with mode: 0644]

diff --git a/queue-6.19/asoc-amd-yc-add-dmi-quirk-for-asus-expertbook-pm1503cda.patch b/queue-6.19/asoc-amd-yc-add-dmi-quirk-for-asus-expertbook-pm1503cda.patch
new file mode 100644 (file)
index 0000000..b798e38
--- /dev/null
@@ -0,0 +1,38 @@
+From 325291b20f8a6f14b9c82edbf5d12e4e71f6adaa Mon Sep 17 00:00:00 2001
+From: Zhang Heng <zhangheng@kylinos.cn>
+Date: Wed, 4 Mar 2026 14:32:55 +0800
+Subject: ASoC: amd: yc: Add DMI quirk for ASUS EXPERTBOOK PM1503CDA
+
+From: Zhang Heng <zhangheng@kylinos.cn>
+
+commit 325291b20f8a6f14b9c82edbf5d12e4e71f6adaa upstream.
+
+Add a DMI quirk for the ASUS EXPERTBOOK PM1503CDA fixing the
+issue where the internal microphone was not detected.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=221070
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
+Link: https://patch.msgid.link/20260304063255.139331-1-zhangheng@kylinos.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/amd/yc/acp6x-mach.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -710,6 +710,13 @@ static const struct dmi_system_id yc_acp
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK BM1503CDA"),
+               }
+       },
++      {
++              .driver_data = &acp6x_card,
++              .matches = {
++                      DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_BOARD_NAME, "PM1503CDA"),
++              }
++      },
+       {}
+ };
diff --git a/queue-6.19/ata-libata-core-add-bridge_ok-quirk-for-qemu-drives.patch b/queue-6.19/ata-libata-core-add-bridge_ok-quirk-for-qemu-drives.patch
new file mode 100644 (file)
index 0000000..9c1da68
--- /dev/null
@@ -0,0 +1,48 @@
+From b92b0075ee1870f78f59ab1f7da7dbfdd718ad7a Mon Sep 17 00:00:00 2001
+From: Pedro Falcato <pfalcato@suse.de>
+Date: Thu, 5 Mar 2026 14:53:12 +0000
+Subject: ata: libata-core: Add BRIDGE_OK quirk for QEMU drives
+
+From: Pedro Falcato <pfalcato@suse.de>
+
+commit b92b0075ee1870f78f59ab1f7da7dbfdd718ad7a upstream.
+
+Currently, whenever you boot with a QEMU drive over an AHCI interface,
+you get:
+[    1.632121] ata1.00: applying bridge limits
+
+This happens due to the kernel not believing the given drive is SATA,
+since word 93 of IDENTIFY (ATA_ID_HW_CONFIG) is non-zero. The result is
+a pretty severe limit in max_hw_sectors_kb, which limits our IO sizes.
+
+QEMU has set word 93 erroneously for SATA drives but does not, in any
+way, emulate any of these real hardware details. There is no PATA
+drive and no SATA cable.
+
+As such, add a BRIDGE_OK quirk for QEMU HARDDISK. Special care is taken
+to limit this quirk to "2.5+", to allow for fixed future versions.
+
+This results in the max_hw_sectors being limited solely by the
+controller interface's limits. Which, for AHCI controllers, takes it
+from 128KB to 32767KB.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Pedro Falcato <pfalcato@suse.de>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ata/libata-core.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -4228,6 +4228,7 @@ static const struct ata_dev_quirks_entry
+       /* Devices that do not need bridging limits applied */
+       { "MTRON MSP-SATA*",            NULL,   ATA_QUIRK_BRIDGE_OK },
+       { "BUFFALO HD-QSU2/R5",         NULL,   ATA_QUIRK_BRIDGE_OK },
++      { "QEMU HARDDISK",              "2.5+", ATA_QUIRK_BRIDGE_OK },
+       /* Devices which aren't very happy with higher link speeds */
+       { "WD My Book",                 NULL,   ATA_QUIRK_1_5_GBPS },
diff --git a/queue-6.19/kvm-arm64-fix-protected-mode-handling-of-pages-larger-than-4kb.patch b/queue-6.19/kvm-arm64-fix-protected-mode-handling-of-pages-larger-than-4kb.patch
new file mode 100644 (file)
index 0000000..448e1be
--- /dev/null
@@ -0,0 +1,81 @@
+From 08f97454b7fa39bfcf82524955c771d2d693d6fe Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Sun, 22 Feb 2026 13:35:13 +0000
+Subject: KVM: arm64: Fix protected mode handling of pages larger than 4kB
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 08f97454b7fa39bfcf82524955c771d2d693d6fe upstream.
+
+Since 3669ddd8fa8b5 ("KVM: arm64: Add a range to pkvm_mappings"),
+pKVM tracks the memory that has been mapped into a guest in a
+side data structure. Crucially, it uses it to find out whether
+a page has already been mapped, and therefore refuses to map it
+twice. So far, so good.
+
+However, this very patch completely breaks non-4kB page support,
+with guests being unable to boot. The most obvious symptom is that
+we take the same fault repeatedly, and not making forward progress.
+A quick investigation shows that this is because of the above
+rejection code.
+
+As it turns out, there are multiple issues at play:
+
+- while the HPFAR_EL2 register gives you the faulting IPA minus
+  the bottom 12 bits, it will still give you the extra bits that
+  are part of the page offset for anything larger than 4kB,
+  even for a level-3 mapping
+
+- pkvm_pgtable_stage2_map() assumes that the address passed as
+  a parameter is aligned to the size of the intended mapping
+
+- the faulting address is only aligned for a non-page mapping
+
+When the planets are suitably aligned (pun intended), the guest
+faults on a page by accessing it past the bottom 4kB, and extra bits
+get set in the HPFAR_EL2 register. If this results in a page mapping
+(which is likely with large granule sizes), nothing aligns it further
+down, and pkvm_mapping_iter_first() finds an intersection that
+doesn't really exist. We assume this is a spurious fault and return
+-EAGAIN. And again...
+
+This doesn't hit outside of the protected code, as the page table
+code always aligns the IPA down to a page boundary, hiding the issue
+for everyone else.
+
+Fix it by always forcing the alignment on vma_pagesize, irrespective
+of the value of vma_pagesize.
+
+Fixes: 3669ddd8fa8b5 ("KVM: arm64: Add a range to pkvm_mappings")
+Reviewed-by: Fuad Tabba <tabba@google.com>
+Tested-by: Fuad Tabba <tabba@google.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://https://patch.msgid.link/20260222141000.3084258-1-maz@kernel.org
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/mmu.c |   12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/arch/arm64/kvm/mmu.c
++++ b/arch/arm64/kvm/mmu.c
+@@ -1753,14 +1753,12 @@ static int user_mem_abort(struct kvm_vcp
+       }
+       /*
+-       * Both the canonical IPA and fault IPA must be hugepage-aligned to
+-       * ensure we find the right PFN and lay down the mapping in the right
+-       * place.
++       * Both the canonical IPA and fault IPA must be aligned to the
++       * mapping size to ensure we find the right PFN and lay down the
++       * mapping in the right place.
+        */
+-      if (vma_pagesize == PMD_SIZE || vma_pagesize == PUD_SIZE) {
+-              fault_ipa &= ~(vma_pagesize - 1);
+-              ipa &= ~(vma_pagesize - 1);
+-      }
++      fault_ipa = ALIGN_DOWN(fault_ipa, vma_pagesize);
++      ipa = ALIGN_DOWN(ipa, vma_pagesize);
+       gfn = ipa >> PAGE_SHIFT;
+       mte_allowed = kvm_vma_mte_allowed(vma);
diff --git a/queue-6.19/kvm-arm64-pkvm-don-t-reprobe-for-ich_vtr_el2.tds-on-cpu-hotplug.patch b/queue-6.19/kvm-arm64-pkvm-don-t-reprobe-for-ich_vtr_el2.tds-on-cpu-hotplug.patch
new file mode 100644 (file)
index 0000000..b287e5e
--- /dev/null
@@ -0,0 +1,48 @@
+From a79f7b4aeb8e7562cd6dbf9c223e2c2a04b1a85f Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Tue, 10 Mar 2026 08:54:33 +0000
+Subject: KVM: arm64: pkvm: Don't reprobe for ICH_VTR_EL2.TDS on CPU hotplug
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit a79f7b4aeb8e7562cd6dbf9c223e2c2a04b1a85f upstream.
+
+Hotplugging a CPU off and back on fails with pKVM, as we try to
+probe for ICH_VTR_EL2.TDS. In a non-VHE setup, this is achieved
+by using an EL2 stub helper. However, the stubs are out of reach
+once pKVM has deprivileged the kernel. The CPU never boots.
+
+Since pKVM doesn't allow late onlining of CPUs, we can detect
+that protected mode is enforced early on, and return the current
+state of the capability.
+
+Fixes: 2a28810cbb8b2 ("KVM: arm64: GICv3: Detect and work around the lack of ICV_DIR_EL1 trapping")
+Reported-by: Vincent Donnefort <vdonnefort@google.com>
+Tested-by: Vincent Donnefort <vdonnefort@google.com>
+Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://patch.msgid.link/20260310085433.3936742-1-maz@kernel.org
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/cpufeature.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/arch/arm64/kernel/cpufeature.c
++++ b/arch/arm64/kernel/cpufeature.c
+@@ -2336,6 +2336,15 @@ static bool can_trap_icv_dir_el1(const s
+       if (this_cpu_has_cap(ARM64_HAS_GICV5_LEGACY))
+               return true;
++      /*
++       * pKVM prevents late onlining of CPUs. This means that whatever
++       * state the capability is in after deprivilege cannot be affected
++       * by a new CPU booting -- this is garanteed to be a CPU we have
++       * already seen, and the cap is therefore unchanged.
++       */
++      if (system_capabilities_finalized() && is_protected_kvm_enabled())
++              return cpus_have_final_cap(ARM64_HAS_ICH_HCR_EL2_TDIR);
++
+       if (is_kernel_in_hyp_mode())
+               res.a1 = read_sysreg_s(SYS_ICH_VTR_EL2);
+       else
diff --git a/queue-6.19/kvm-arm64-pkvm-fallback-to-level-3-mapping-on-host-stage-2-fault.patch b/queue-6.19/kvm-arm64-pkvm-fallback-to-level-3-mapping-on-host-stage-2-fault.patch
new file mode 100644 (file)
index 0000000..9e2a2ba
--- /dev/null
@@ -0,0 +1,43 @@
+From 8531d5a83d8eb8affb5c0249b466c28d94192603 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Thu, 5 Mar 2026 13:27:51 +0000
+Subject: KVM: arm64: pkvm: Fallback to level-3 mapping on host stage-2 fault
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 8531d5a83d8eb8affb5c0249b466c28d94192603 upstream.
+
+If, for any odd reason, we cannot converge to mapping size that is
+completely contained in a memblock region, we fail to install a S2
+mapping and go back to the faulting instruction. Rince, repeat.
+
+This happens when faulting in regions that are smaller than a page
+or that do not have PAGE_SIZE-aligned boundaries (as witnessed on
+an O6 board that refuses to boot in protected mode).
+
+In this situation, fallback to using a PAGE_SIZE mapping anyway --
+it isn't like we can go any lower.
+
+Fixes: e728e705802fe ("KVM: arm64: Adjust range correctly during host stage-2 faults")
+Link: https://lore.kernel.org/r/86wlzr77cn.wl-maz@kernel.org
+Cc: stable@vger.kernel.org
+Cc: Quentin Perret <qperret@google.com>
+Reviewed-by: Quentin Perret <qperret@google.com>
+Link: https://patch.msgid.link/20260305132751.2928138-1-maz@kernel.org
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/hyp/nvhe/mem_protect.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
++++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+@@ -516,7 +516,7 @@ static int host_stage2_adjust_range(u64
+               granule = kvm_granule_size(level);
+               cur.start = ALIGN_DOWN(addr, granule);
+               cur.end = cur.start + granule;
+-              if (!range_included(&cur, range))
++              if (!range_included(&cur, range) && level < KVM_PGTABLE_LAST_LEVEL)
+                       continue;
+               *range = cur;
+               return 0;
diff --git a/queue-6.19/kvm-arm64-vgic-pick-eoicount-deactivations-from-ap-list-tail.patch b/queue-6.19/kvm-arm64-vgic-pick-eoicount-deactivations-from-ap-list-tail.patch
new file mode 100644 (file)
index 0000000..f92cbc2
--- /dev/null
@@ -0,0 +1,131 @@
+From 6da5e537f5afe091658e846da1949d7e557d2ade Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Sat, 7 Mar 2026 19:11:51 +0000
+Subject: KVM: arm64: vgic: Pick EOIcount deactivations from AP-list tail
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 6da5e537f5afe091658e846da1949d7e557d2ade upstream.
+
+Valentine reports that their guests fail to boot correctly, losing
+interrupts, and indicates that the wrong interrupt gets deactivated.
+
+What happens here is that if the maintenance interrupt is slow enough
+to kick us out of the guest, extra interrupts can be activated from
+the LRs. We then exit and proceed to handle EOIcount deactivations,
+picking active interrupts from the AP list. But we start from the
+top of the list, potentially deactivating interrupts that were in
+the LRs, while EOIcount only denotes deactivation of interrupts that
+are not present in an LR.
+
+Solve this by tracking the last interrupt that made it in the LRs,
+and start the EOIcount deactivation walk *after* that interrupt.
+Since this only makes sense while the vcpu is loaded, stash this
+in the per-CPU host state.
+
+Huge thanks to Valentine for doing all the detective work and
+providing an initial patch.
+
+Fixes: 3cfd59f81e0f3 ("KVM: arm64: GICv3: Handle LR overflow when EOImode==0")
+Fixes: 281c6c06e2a7b ("KVM: arm64: GICv2: Handle LR overflow when EOImode==0")
+Reported-by: Valentine Burley <valentine.burley@collabora.com>
+Tested-by: Valentine Burley <valentine.burley@collabora.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20260307115955.369455-1-valentine.burley@collabora.com
+Link: https://patch.msgid.link/20260307191151.3781182-1-maz@kernel.org
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/include/asm/kvm_host.h |    3 +++
+ arch/arm64/kvm/vgic/vgic-v2.c     |    4 ++--
+ arch/arm64/kvm/vgic/vgic-v3.c     |   12 ++++++------
+ arch/arm64/kvm/vgic/vgic.c        |    6 ++++++
+ 4 files changed, 17 insertions(+), 8 deletions(-)
+
+--- a/arch/arm64/include/asm/kvm_host.h
++++ b/arch/arm64/include/asm/kvm_host.h
+@@ -760,6 +760,9 @@ struct kvm_host_data {
+       /* Number of debug breakpoints/watchpoints for this CPU (minus 1) */
+       unsigned int debug_brps;
+       unsigned int debug_wrps;
++
++      /* Last vgic_irq part of the AP list recorded in an LR */
++      struct vgic_irq *last_lr_irq;
+ };
+ struct kvm_host_psci_config {
+--- a/arch/arm64/kvm/vgic/vgic-v2.c
++++ b/arch/arm64/kvm/vgic/vgic-v2.c
+@@ -115,7 +115,7 @@ void vgic_v2_fold_lr_state(struct kvm_vc
+       struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+       struct vgic_v2_cpu_if *cpuif = &vgic_cpu->vgic_v2;
+       u32 eoicount = FIELD_GET(GICH_HCR_EOICOUNT, cpuif->vgic_hcr);
+-      struct vgic_irq *irq;
++      struct vgic_irq *irq = *host_data_ptr(last_lr_irq);
+       DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
+@@ -123,7 +123,7 @@ void vgic_v2_fold_lr_state(struct kvm_vc
+               vgic_v2_fold_lr(vcpu, cpuif->vgic_lr[lr]);
+       /* See the GICv3 equivalent for the EOIcount handling rationale */
+-      list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
++      list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) {
+               u32 lr;
+               if (!eoicount) {
+--- a/arch/arm64/kvm/vgic/vgic-v3.c
++++ b/arch/arm64/kvm/vgic/vgic-v3.c
+@@ -148,7 +148,7 @@ void vgic_v3_fold_lr_state(struct kvm_vc
+       struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+       struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3;
+       u32 eoicount = FIELD_GET(ICH_HCR_EL2_EOIcount, cpuif->vgic_hcr);
+-      struct vgic_irq *irq;
++      struct vgic_irq *irq = *host_data_ptr(last_lr_irq);
+       DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
+@@ -158,12 +158,12 @@ void vgic_v3_fold_lr_state(struct kvm_vc
+       /*
+        * EOIMode=0: use EOIcount to emulate deactivation. We are
+        * guaranteed to deactivate in reverse order of the activation, so
+-       * just pick one active interrupt after the other in the ap_list,
+-       * and replay the deactivation as if the CPU was doing it. We also
+-       * rely on priority drop to have taken place, and the list to be
+-       * sorted by priority.
++       * just pick one active interrupt after the other in the tail part
++       * of the ap_list, past the LRs, and replay the deactivation as if
++       * the CPU was doing it. We also rely on priority drop to have taken
++       * place, and the list to be sorted by priority.
+        */
+-      list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
++      list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) {
+               u64 lr;
+               /*
+--- a/arch/arm64/kvm/vgic/vgic.c
++++ b/arch/arm64/kvm/vgic/vgic.c
+@@ -814,6 +814,9 @@ retry:
+ static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
+ {
++      if (!*host_data_ptr(last_lr_irq))
++              return;
++
+       if (kvm_vgic_global_state.type == VGIC_V2)
+               vgic_v2_fold_lr_state(vcpu);
+       else
+@@ -960,10 +963,13 @@ static void vgic_flush_lr_state(struct k
+       if (irqs_outside_lrs(&als))
+               vgic_sort_ap_list(vcpu);
++      *host_data_ptr(last_lr_irq) = NULL;
++
+       list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+               scoped_guard(raw_spinlock,  &irq->irq_lock) {
+                       if (likely(vgic_target_oracle(irq) == vcpu)) {
+                               vgic_populate_lr(vcpu, irq, count++);
++                              *host_data_ptr(last_lr_irq) = irq;
+                       }
+               }
diff --git a/queue-6.19/kvm-svm-initialize-avic-vmcb-fields-if-avic-is-enabled-with-in-kernel-apic.patch b/queue-6.19/kvm-svm-initialize-avic-vmcb-fields-if-avic-is-enabled-with-in-kernel-apic.patch
new file mode 100644 (file)
index 0000000..6cabc7e
--- /dev/null
@@ -0,0 +1,61 @@
+From 3989a6d036c8ec82c0de3614bed23a1dacd45de5 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Tue, 3 Feb 2026 11:07:09 -0800
+Subject: KVM: SVM: Initialize AVIC VMCB fields if AVIC is enabled with in-kernel APIC
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 3989a6d036c8ec82c0de3614bed23a1dacd45de5 upstream.
+
+Initialize all per-vCPU AVIC control fields in the VMCB if AVIC is enabled
+in KVM and the VM has an in-kernel local APIC, i.e. if it's _possible_ the
+vCPU could activate AVIC at any point in its lifecycle.  Configuring the
+VMCB if and only if AVIC is active "works" purely because of optimizations
+in kvm_create_lapic() to speculatively set apicv_active if AVIC is enabled
+*and* to defer updates until the first KVM_RUN.  In quotes because KVM
+likely won't do the right thing if kvm_apicv_activated() is false, i.e. if
+a vCPU is created while APICv is inhibited at the VM level for whatever
+reason.  E.g. if the inhibit is *removed* before KVM_REQ_APICV_UPDATE is
+handled in KVM_RUN, then __kvm_vcpu_update_apicv() will elide calls to
+vendor code due to seeing "apicv_active == activate".
+
+Cleaning up the initialization code will also allow fixing a bug where KVM
+incorrectly leaves CR8 interception enabled when AVIC is activated without
+creating a mess with respect to whether AVIC is activated or not.
+
+Cc: stable@vger.kernel.org
+Fixes: 67034bb9dd5e ("KVM: SVM: Add irqchip_split() checks before enabling AVIC")
+Fixes: 6c3e4422dd20 ("svm: Add support for dynamic APICv")
+Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>
+Reviewed-by: Jim Mattson <jmattson@google.com>
+Link: https://patch.msgid.link/20260203190711.458413-2-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/svm/avic.c |    2 +-
+ arch/x86/kvm/svm/svm.c  |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/svm/avic.c
++++ b/arch/x86/kvm/svm/avic.c
+@@ -368,7 +368,7 @@ void avic_init_vmcb(struct vcpu_svm *svm
+       vmcb->control.avic_physical_id = __sme_set(__pa(kvm_svm->avic_physical_id_table));
+       vmcb->control.avic_vapic_bar = APIC_DEFAULT_PHYS_BASE;
+-      if (kvm_apicv_activated(svm->vcpu.kvm))
++      if (kvm_vcpu_apicv_active(&svm->vcpu))
+               avic_activate_vmcb(svm);
+       else
+               avic_deactivate_vmcb(svm);
+--- a/arch/x86/kvm/svm/svm.c
++++ b/arch/x86/kvm/svm/svm.c
+@@ -1141,7 +1141,7 @@ static void init_vmcb(struct kvm_vcpu *v
+               svm_clr_intercept(svm, INTERCEPT_PAUSE);
+       }
+-      if (kvm_vcpu_apicv_active(vcpu))
++      if (enable_apicv && irqchip_in_kernel(vcpu->kvm))
+               avic_init_vmcb(svm, vmcb);
+       if (vnmi)
diff --git a/queue-6.19/kvm-svm-set-clear-cr8-write-interception-when-avic-is-de-activated.patch b/queue-6.19/kvm-svm-set-clear-cr8-write-interception-when-avic-is-de-activated.patch
new file mode 100644 (file)
index 0000000..b6e32d3
--- /dev/null
@@ -0,0 +1,97 @@
+From 87d0f901a9bd8ae6be57249c737f20ac0cace93d Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Tue, 3 Feb 2026 11:07:10 -0800
+Subject: KVM: SVM: Set/clear CR8 write interception when AVIC is (de)activated
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 87d0f901a9bd8ae6be57249c737f20ac0cace93d upstream.
+
+Explicitly set/clear CR8 write interception when AVIC is (de)activated to
+fix a bug where KVM leaves the interception enabled after AVIC is
+activated.  E.g. if KVM emulates INIT=>WFS while AVIC is deactivated, CR8
+will remain intercepted in perpetuity.
+
+On its own, the dangling CR8 intercept is "just" a performance issue, but
+combined with the TPR sync bug fixed by commit d02e48830e3f ("KVM: SVM:
+Sync TPR from LAPIC into VMCB::V_TPR even if AVIC is active"), the danging
+intercept is fatal to Windows guests as the TPR seen by hardware gets
+wildly out of sync with reality.
+
+Note, VMX isn't affected by the bug as TPR_THRESHOLD is explicitly ignored
+when Virtual Interrupt Delivery is enabled, i.e. when APICv is active in
+KVM's world.  I.e. there's no need to trigger update_cr8_intercept(), this
+is firmly an SVM implementation flaw/detail.
+
+WARN if KVM gets a CR8 write #VMEXIT while AVIC is active, as KVM should
+never enter the guest with AVIC enabled and CR8 writes intercepted.
+
+Fixes: 3bbf3565f48c ("svm: Do not intercept CR8 when enable AVIC")
+Cc: stable@vger.kernel.org
+Cc: Jim Mattson <jmattson@google.com>
+Cc: Naveen N Rao (AMD) <naveen@kernel.org>
+Cc: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
+Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>
+Reviewed-by: Jim Mattson <jmattson@google.com>
+Link: https://patch.msgid.link/20260203190711.458413-3-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[Squash fix to avic_deactivate_vmcb. - Paolo]
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/svm/avic.c |    7 +++++--
+ arch/x86/kvm/svm/svm.c  |    7 ++++---
+ 2 files changed, 9 insertions(+), 5 deletions(-)
+
+--- a/arch/x86/kvm/svm/avic.c
++++ b/arch/x86/kvm/svm/avic.c
+@@ -189,12 +189,12 @@ static void avic_activate_vmcb(struct vc
+       struct kvm_vcpu *vcpu = &svm->vcpu;
+       vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK);
+-
+       vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK;
+       vmcb->control.avic_physical_id |= avic_get_max_physical_id(vcpu);
+-
+       vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
++      svm_clr_intercept(svm, INTERCEPT_CR8_WRITE);
++
+       /*
+        * Note: KVM supports hybrid-AVIC mode, where KVM emulates x2APIC MSR
+        * accesses, while interrupt injection to a running vCPU can be
+@@ -226,6 +226,9 @@ static void avic_deactivate_vmcb(struct
+       vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK);
+       vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK;
++      if (!sev_es_guest(svm->vcpu.kvm))
++              svm_set_intercept(svm, INTERCEPT_CR8_WRITE);
++
+       /*
+        * If running nested and the guest uses its own MSR bitmap, there
+        * is no need to update L0's msr bitmap
+--- a/arch/x86/kvm/svm/svm.c
++++ b/arch/x86/kvm/svm/svm.c
+@@ -1032,8 +1032,7 @@ static void init_vmcb(struct kvm_vcpu *v
+       svm_set_intercept(svm, INTERCEPT_CR0_WRITE);
+       svm_set_intercept(svm, INTERCEPT_CR3_WRITE);
+       svm_set_intercept(svm, INTERCEPT_CR4_WRITE);
+-      if (!kvm_vcpu_apicv_active(vcpu))
+-              svm_set_intercept(svm, INTERCEPT_CR8_WRITE);
++      svm_set_intercept(svm, INTERCEPT_CR8_WRITE);
+       set_dr_intercepts(svm);
+@@ -2603,9 +2602,11 @@ static int dr_interception(struct kvm_vc
+ static int cr8_write_interception(struct kvm_vcpu *vcpu)
+ {
++      u8 cr8_prev = kvm_get_cr8(vcpu);
+       int r;
+-      u8 cr8_prev = kvm_get_cr8(vcpu);
++      WARN_ON_ONCE(kvm_vcpu_apicv_active(vcpu));
++
+       /* instruction emulation calls kvm_set_cr8() */
+       r = cr_interception(vcpu);
+       if (lapic_in_kernel(vcpu))
diff --git a/queue-6.19/kvm-x86-introduce-kvm_x86_quirk_vmcs12_allow_freeze_in_smm.patch b/queue-6.19/kvm-x86-introduce-kvm_x86_quirk_vmcs12_allow_freeze_in_smm.patch
new file mode 100644 (file)
index 0000000..8ea60f9
--- /dev/null
@@ -0,0 +1,108 @@
+From e2ffe85b6d2bb7780174b87aa4468a39be17eb81 Mon Sep 17 00:00:00 2001
+From: Jim Mattson <jmattson@google.com>
+Date: Thu, 5 Feb 2026 15:15:26 -0800
+Subject: KVM: x86: Introduce KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM
+
+From: Jim Mattson <jmattson@google.com>
+
+commit e2ffe85b6d2bb7780174b87aa4468a39be17eb81 upstream.
+
+Add KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM to allow L1 to set
+FREEZE_IN_SMM in vmcs12's GUEST_IA32_DEBUGCTL field, as permitted
+prior to commit 6b1dd26544d0 ("KVM: VMX: Preserve host's
+DEBUGCTLMSR_FREEZE_IN_SMM while running the guest").  Enable the quirk
+by default for backwards compatibility (like all quirks); userspace
+can disable it via KVM_CAP_DISABLE_QUIRKS2 for consistency with the
+constraints on WRMSR(IA32_DEBUGCTL).
+
+Note that the quirk only bypasses the consistency check.  The vmcs02 bit is
+still owned by the host, and PMCs are not frozen during virtualized SMM.
+In particular, if a host administrator decides that PMCs should not be
+frozen during physical SMM, then L1 has no say in the matter.
+
+Fixes: 095686e6fcb4 ("KVM: nVMX: Check vmcs12->guest_ia32_debugctl on nested VM-Enter")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jim Mattson <jmattson@google.com>
+Link: https://patch.msgid.link/20260205231537.1278753-1-jmattson@google.com
+[sean: tag for stable@, clean-up and fix goofs in the comment and docs]
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[Rename quirk. - Paolo]
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/virt/kvm/api.rst  |    8 ++++++++
+ arch/x86/include/asm/kvm_host.h |    3 ++-
+ arch/x86/include/uapi/asm/kvm.h |    1 +
+ arch/x86/kvm/vmx/nested.c       |   22 ++++++++++++++++++----
+ 4 files changed, 29 insertions(+), 5 deletions(-)
+
+--- a/Documentation/virt/kvm/api.rst
++++ b/Documentation/virt/kvm/api.rst
+@@ -8438,6 +8438,14 @@ KVM_X86_QUIRK_IGNORE_GUEST_PAT      By d
+                                     guest software, for example if it does not
+                                     expose a bochs graphics device (which is
+                                     known to have had a buggy driver).
++
++KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM   By default, KVM relaxes the consistency
++                                      check for GUEST_IA32_DEBUGCTL in vmcs12
++                                      to allow FREEZE_IN_SMM to be set.  When
++                                      this quirk is disabled, KVM requires this
++                                      bit to be cleared.  Note that the vmcs02
++                                      bit is still completely controlled by the
++                                      host, regardless of the quirk setting.
+ =================================== ============================================
+ 7.32 KVM_CAP_MAX_VCPU_ID
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -2470,7 +2470,8 @@ int memslot_rmap_alloc(struct kvm_memory
+        KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS |  \
+        KVM_X86_QUIRK_SLOT_ZAP_ALL |           \
+        KVM_X86_QUIRK_STUFF_FEATURE_MSRS |     \
+-       KVM_X86_QUIRK_IGNORE_GUEST_PAT)
++       KVM_X86_QUIRK_IGNORE_GUEST_PAT |       \
++       KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM)
+ #define KVM_X86_CONDITIONAL_QUIRKS            \
+       (KVM_X86_QUIRK_CD_NW_CLEARED |          \
+--- a/arch/x86/include/uapi/asm/kvm.h
++++ b/arch/x86/include/uapi/asm/kvm.h
+@@ -476,6 +476,7 @@ struct kvm_sync_regs {
+ #define KVM_X86_QUIRK_SLOT_ZAP_ALL            (1 << 7)
+ #define KVM_X86_QUIRK_STUFF_FEATURE_MSRS      (1 << 8)
+ #define KVM_X86_QUIRK_IGNORE_GUEST_PAT                (1 << 9)
++#define KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM (1 << 10)
+ #define KVM_STATE_NESTED_FORMAT_VMX   0
+ #define KVM_STATE_NESTED_FORMAT_SVM   1
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -3292,10 +3292,24 @@ static int nested_vmx_check_guest_state(
+       if (CC(vmcs12->guest_cr4 & X86_CR4_CET && !(vmcs12->guest_cr0 & X86_CR0_WP)))
+               return -EINVAL;
+-      if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) &&
+-          (CC(!kvm_dr7_valid(vmcs12->guest_dr7)) ||
+-           CC(!vmx_is_valid_debugctl(vcpu, vmcs12->guest_ia32_debugctl, false))))
+-              return -EINVAL;
++      if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) {
++              u64 debugctl = vmcs12->guest_ia32_debugctl;
++
++              /*
++               * FREEZE_IN_SMM is not virtualized, but allow L1 to set it in
++               * vmcs12's DEBUGCTL under a quirk for backwards compatibility.
++               * Note that the quirk only relaxes the consistency check.  The
++               * vmcc02 bit is still under the control of the host.  In
++               * particular, if a host administrator decides to clear the bit,
++               * then L1 has no say in the matter.
++               */
++              if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM))
++                      debugctl &= ~DEBUGCTLMSR_FREEZE_IN_SMM;
++
++              if (CC(!kvm_dr7_valid(vmcs12->guest_dr7)) ||
++                  CC(!vmx_is_valid_debugctl(vcpu, debugctl, false)))
++                      return -EINVAL;
++      }
+       if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT) &&
+           CC(!kvm_pat_valid(vmcs12->guest_ia32_pat)))
diff --git a/queue-6.19/revert-usb-gadget-f_ncm-align-net_device-lifecycle-with-bind-unbind.patch b/queue-6.19/revert-usb-gadget-f_ncm-align-net_device-lifecycle-with-bind-unbind.patch
new file mode 100644 (file)
index 0000000..60d5b65
--- /dev/null
@@ -0,0 +1,343 @@
+From 37893bc5de2460c543ec1aa8250c37a305234054 Mon Sep 17 00:00:00 2001
+From: Kuen-Han Tsai <khtsai@google.com>
+Date: Mon, 9 Mar 2026 20:04:48 +0800
+Subject: Revert "usb: gadget: f_ncm: align net_device lifecycle with bind/unbind"
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+commit 37893bc5de2460c543ec1aa8250c37a305234054 upstream.
+
+This reverts commit 56a512a9b4107079f68701e7d55da8507eb963d9.
+
+This commit is being reverted as part of a series-wide revert.
+
+By deferring the net_device allocation to the bind() phase, a single
+function instance will spawn multiple network devices if it is symlinked
+to multiple USB configurations.
+
+This causes regressions for userspace tools (like the postmarketOS DHCP
+daemon) that rely on reading the interface name (e.g., "usb0") from
+configfs. Currently, configfs returns the template "usb%d", causing the
+userspace network setup to fail.
+
+Crucially, because this patch breaks the 1:1 mapping between the
+function instance and the network device, this naming issue cannot
+simply be patched. Configfs only exposes a single 'ifname' attribute per
+instance, making it impossible to accurately report the actual interface
+name when multiple underlying network devices can exist for that single
+instance.
+
+All configurations tied to the same function instance are meant to share
+a single network device. Revert this change to restore the 1:1 mapping
+by allocating the network device at the instance level (alloc_inst).
+
+Reported-by: David Heidelberg <david@ixit.cz>
+Closes: https://lore.kernel.org/linux-usb/70b558ea-a12e-4170-9b8e-c951131249af@ixit.cz/
+Fixes: 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle with bind/unbind")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://patch.msgid.link/20260309-f-ncm-revert-v2-3-ea2afbc7d9b2@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_ncm.c |  128 ++++++++++++++++++------------------
+ drivers/usb/gadget/function/u_ncm.h |    4 -
+ 2 files changed, 66 insertions(+), 66 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_ncm.c
++++ b/drivers/usb/gadget/function/f_ncm.c
+@@ -83,11 +83,6 @@ static inline struct f_ncm *func_to_ncm(
+       return container_of(f, struct f_ncm, port.func);
+ }
+-static inline struct f_ncm_opts *func_to_ncm_opts(struct usb_function *f)
+-{
+-      return container_of(f->fi, struct f_ncm_opts, func_inst);
+-}
+-
+ /*-------------------------------------------------------------------------*/
+ /*
+@@ -864,7 +859,6 @@ invalid:
+ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+ {
+       struct f_ncm            *ncm = func_to_ncm(f);
+-      struct f_ncm_opts       *opts = func_to_ncm_opts(f);
+       struct usb_composite_dev *cdev = f->config->cdev;
+       /* Control interface has only altsetting 0 */
+@@ -887,13 +881,12 @@ static int ncm_set_alt(struct usb_functi
+               if (alt > 1)
+                       goto fail;
+-              scoped_guard(mutex, &opts->lock)
+-                      if (opts->net) {
+-                              DBG(cdev, "reset ncm\n");
+-                              opts->net = NULL;
+-                              gether_disconnect(&ncm->port);
+-                              ncm_reset_values(ncm);
+-                      }
++              if (ncm->netdev) {
++                      DBG(cdev, "reset ncm\n");
++                      ncm->netdev = NULL;
++                      gether_disconnect(&ncm->port);
++                      ncm_reset_values(ncm);
++              }
+               /*
+                * CDC Network only sends data in non-default altsettings.
+@@ -926,8 +919,7 @@ static int ncm_set_alt(struct usb_functi
+                       net = gether_connect(&ncm->port);
+                       if (IS_ERR(net))
+                               return PTR_ERR(net);
+-                      scoped_guard(mutex, &opts->lock)
+-                              opts->net = net;
++                      ncm->netdev = net;
+               }
+               spin_lock(&ncm->lock);
+@@ -1374,16 +1366,14 @@ err:
+ static void ncm_disable(struct usb_function *f)
+ {
+       struct f_ncm            *ncm = func_to_ncm(f);
+-      struct f_ncm_opts       *opts = func_to_ncm_opts(f);
+       struct usb_composite_dev *cdev = f->config->cdev;
+       DBG(cdev, "ncm deactivated\n");
+-      scoped_guard(mutex, &opts->lock)
+-              if (opts->net) {
+-                      opts->net = NULL;
+-                      gether_disconnect(&ncm->port);
+-              }
++      if (ncm->netdev) {
++              ncm->netdev = NULL;
++              gether_disconnect(&ncm->port);
++      }
+       if (ncm->notify->enabled) {
+               usb_ep_disable(ncm->notify);
+@@ -1443,44 +1433,39 @@ static int ncm_bind(struct usb_configura
+ {
+       struct usb_composite_dev *cdev = c->cdev;
+       struct f_ncm            *ncm = func_to_ncm(f);
+-      struct f_ncm_opts       *ncm_opts = func_to_ncm_opts(f);
+       struct usb_string       *us;
+       int                     status = 0;
+       struct usb_ep           *ep;
++      struct f_ncm_opts       *ncm_opts;
+       struct usb_os_desc_table        *os_desc_table __free(kfree) = NULL;
+-      struct net_device               *netdev __free(free_gether_netdev) = NULL;
+       struct usb_request              *request __free(free_usb_request) = NULL;
+       if (!can_support_ecm(cdev->gadget))
+               return -EINVAL;
++      ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst);
++
+       if (cdev->use_os_string) {
+               os_desc_table = kzalloc(sizeof(*os_desc_table), GFP_KERNEL);
+               if (!os_desc_table)
+                       return -ENOMEM;
+       }
+-      netdev = gether_setup_default();
+-      if (IS_ERR(netdev))
+-              return -ENOMEM;
+-
+-      scoped_guard(mutex, &ncm_opts->lock) {
+-              gether_apply_opts(netdev, &ncm_opts->net_opts);
+-              netdev->mtu = ncm_opts->max_segment_size - ETH_HLEN;
++      mutex_lock(&ncm_opts->lock);
++      gether_set_gadget(ncm_opts->net, cdev->gadget);
++      if (!ncm_opts->bound) {
++              ncm_opts->net->mtu = (ncm_opts->max_segment_size - ETH_HLEN);
++              status = gether_register_netdev(ncm_opts->net);
+       }
++      mutex_unlock(&ncm_opts->lock);
+-      gether_set_gadget(netdev, cdev->gadget);
+-      status = gether_register_netdev(netdev);
+       if (status)
+               return status;
+-      /* export host's Ethernet address in CDC format */
+-      status = gether_get_host_addr_cdc(netdev, ncm->ethaddr,
+-                                        sizeof(ncm->ethaddr));
+-      if (status < 12)
+-              return -EINVAL;
+-      ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr;
++      ncm_opts->bound = true;
++
++      ncm_string_defs[1].s = ncm->ethaddr;
+       us = usb_gstrings_attach(cdev, ncm_strings,
+                                ARRAY_SIZE(ncm_string_defs));
+@@ -1578,8 +1563,6 @@ static int ncm_bind(struct usb_configura
+               f->os_desc_n = 1;
+       }
+       ncm->notify_req = no_free_ptr(request);
+-      ncm->netdev = no_free_ptr(netdev);
+-      ncm->port.ioport = netdev_priv(ncm->netdev);
+       DBG(cdev, "CDC Network: IN/%s OUT/%s NOTIFY/%s\n",
+                       ncm->port.in_ep->name, ncm->port.out_ep->name,
+@@ -1594,19 +1577,19 @@ static inline struct f_ncm_opts *to_f_nc
+ }
+ /* f_ncm_item_ops */
+-USB_ETHER_OPTS_ITEM(ncm);
++USB_ETHERNET_CONFIGFS_ITEM(ncm);
+ /* f_ncm_opts_dev_addr */
+-USB_ETHER_OPTS_ATTR_DEV_ADDR(ncm);
++USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(ncm);
+ /* f_ncm_opts_host_addr */
+-USB_ETHER_OPTS_ATTR_HOST_ADDR(ncm);
++USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(ncm);
+ /* f_ncm_opts_qmult */
+-USB_ETHER_OPTS_ATTR_QMULT(ncm);
++USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ncm);
+ /* f_ncm_opts_ifname */
+-USB_ETHER_OPTS_ATTR_IFNAME(ncm);
++USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ncm);
+ static ssize_t ncm_opts_max_segment_size_show(struct config_item *item,
+                                             char *page)
+@@ -1672,27 +1655,34 @@ static void ncm_free_inst(struct usb_fun
+       struct f_ncm_opts *opts;
+       opts = container_of(f, struct f_ncm_opts, func_inst);
++      if (opts->bound)
++              gether_cleanup(netdev_priv(opts->net));
++      else
++              free_netdev(opts->net);
+       kfree(opts->ncm_interf_group);
+       kfree(opts);
+ }
+ static struct usb_function_instance *ncm_alloc_inst(void)
+ {
+-      struct usb_function_instance *ret;
++      struct f_ncm_opts *opts;
+       struct usb_os_desc *descs[1];
+       char *names[1];
+       struct config_group *ncm_interf_group;
+-      struct f_ncm_opts *opts __free(kfree) = kzalloc(sizeof(*opts), GFP_KERNEL);
++      opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+       if (!opts)
+               return ERR_PTR(-ENOMEM);
+-
+-      opts->net = NULL;
+       opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id;
+-      gether_setup_opts_default(&opts->net_opts, "usb");
+       mutex_init(&opts->lock);
+       opts->func_inst.free_func_inst = ncm_free_inst;
++      opts->net = gether_setup_default();
++      if (IS_ERR(opts->net)) {
++              struct net_device *net = opts->net;
++              kfree(opts);
++              return ERR_CAST(net);
++      }
+       opts->max_segment_size = ETH_FRAME_LEN;
+       INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop);
+@@ -1703,22 +1693,26 @@ static struct usb_function_instance *ncm
+       ncm_interf_group =
+               usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
+                                              names, THIS_MODULE);
+-      if (IS_ERR(ncm_interf_group))
++      if (IS_ERR(ncm_interf_group)) {
++              ncm_free_inst(&opts->func_inst);
+               return ERR_CAST(ncm_interf_group);
++      }
+       opts->ncm_interf_group = ncm_interf_group;
+-      ret = &opts->func_inst;
+-      retain_and_null_ptr(opts);
+-      return ret;
++      return &opts->func_inst;
+ }
+ static void ncm_free(struct usb_function *f)
+ {
+-      struct f_ncm_opts *opts = func_to_ncm_opts(f);
++      struct f_ncm *ncm;
++      struct f_ncm_opts *opts;
+-      scoped_guard(mutex, &opts->lock)
+-              opts->refcnt--;
+-      kfree(func_to_ncm(f));
++      ncm = func_to_ncm(f);
++      opts = container_of(f->fi, struct f_ncm_opts, func_inst);
++      kfree(ncm);
++      mutex_lock(&opts->lock);
++      opts->refcnt--;
++      mutex_unlock(&opts->lock);
+ }
+ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
+@@ -1742,15 +1736,13 @@ static void ncm_unbind(struct usb_config
+       kfree(ncm->notify_req->buf);
+       usb_ep_free_request(ncm->notify, ncm->notify_req);
+-
+-      ncm->port.ioport = NULL;
+-      gether_cleanup(netdev_priv(ncm->netdev));
+ }
+ static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
+ {
+       struct f_ncm            *ncm;
+       struct f_ncm_opts       *opts;
++      int status;
+       /* allocate and initialize one new instance */
+       ncm = kzalloc(sizeof(*ncm), GFP_KERNEL);
+@@ -1758,12 +1750,22 @@ static struct usb_function *ncm_alloc(st
+               return ERR_PTR(-ENOMEM);
+       opts = container_of(fi, struct f_ncm_opts, func_inst);
++      mutex_lock(&opts->lock);
++      opts->refcnt++;
+-      scoped_guard(mutex, &opts->lock)
+-              opts->refcnt++;
++      /* export host's Ethernet address in CDC format */
++      status = gether_get_host_addr_cdc(opts->net, ncm->ethaddr,
++                                    sizeof(ncm->ethaddr));
++      if (status < 12) { /* strlen("01234567890a") */
++              kfree(ncm);
++              mutex_unlock(&opts->lock);
++              return ERR_PTR(-EINVAL);
++      }
+       spin_lock_init(&ncm->lock);
+       ncm_reset_values(ncm);
++      ncm->port.ioport = netdev_priv(opts->net);
++      mutex_unlock(&opts->lock);
+       ncm->port.is_fixed = true;
+       ncm->port.supports_multi_frame = true;
+--- a/drivers/usb/gadget/function/u_ncm.h
++++ b/drivers/usb/gadget/function/u_ncm.h
+@@ -15,13 +15,11 @@
+ #include <linux/usb/composite.h>
+-#include "u_ether.h"
+-
+ struct f_ncm_opts {
+       struct usb_function_instance    func_inst;
+       struct net_device               *net;
++      bool                            bound;
+-      struct gether_opts              net_opts;
+       struct config_group             *ncm_interf_group;
+       struct usb_os_desc              ncm_os_desc;
+       char                            ncm_ext_compat_id[16];
diff --git a/queue-6.19/revert-usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch b/queue-6.19/revert-usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch
new file mode 100644 (file)
index 0000000..5a002a7
--- /dev/null
@@ -0,0 +1,155 @@
+From 11199720fac2debbe718aec11e026ab3330dc80d Mon Sep 17 00:00:00 2001
+From: Kuen-Han Tsai <khtsai@google.com>
+Date: Mon, 9 Mar 2026 20:04:46 +0800
+Subject: Revert "usb: gadget: f_ncm: Fix atomic context locking issue"
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+commit 11199720fac2debbe718aec11e026ab3330dc80d upstream.
+
+This reverts commit 0d6c8144ca4d93253de952a5ea0028c19ed7ab68.
+
+This commit is being reverted as part of a series-wide revert.
+
+By deferring the net_device allocation to the bind() phase, a single
+function instance will spawn multiple network devices if it is symlinked
+to multiple USB configurations.
+
+This causes regressions for userspace tools (like the postmarketOS DHCP
+daemon) that rely on reading the interface name (e.g., "usb0") from
+configfs. Currently, configfs returns the template "usb%d", causing the
+userspace network setup to fail.
+
+Crucially, because this patch breaks the 1:1 mapping between the
+function instance and the network device, this naming issue cannot
+simply be patched. Configfs only exposes a single 'ifname' attribute per
+instance, making it impossible to accurately report the actual interface
+name when multiple underlying network devices can exist for that single
+instance.
+
+All configurations tied to the same function instance are meant to share
+a single network device. Revert this change to restore the 1:1 mapping
+by allocating the network device at the instance level (alloc_inst).
+
+Reported-by: David Heidelberg <david@ixit.cz>
+Closes: https://lore.kernel.org/linux-usb/70b558ea-a12e-4170-9b8e-c951131249af@ixit.cz/
+Fixes: 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle with bind/unbind")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://patch.msgid.link/20260309-f-ncm-revert-v2-1-ea2afbc7d9b2@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_ncm.c            |   29 ++++++++++++++-----------
+ drivers/usb/gadget/function/u_ether_configfs.h |   11 ++++++++-
+ drivers/usb/gadget/function/u_ncm.h            |    1 
+ 3 files changed, 28 insertions(+), 13 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_ncm.c
++++ b/drivers/usb/gadget/function/f_ncm.c
+@@ -58,7 +58,6 @@ struct f_ncm {
+       u8                              notify_state;
+       atomic_t                        notify_count;
+       bool                            is_open;
+-      bool                            is_connected;
+       const struct ndp_parser_opts    *parser_opts;
+       bool                            is_crc;
+@@ -865,6 +864,7 @@ invalid:
+ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+ {
+       struct f_ncm            *ncm = func_to_ncm(f);
++      struct f_ncm_opts       *opts = func_to_ncm_opts(f);
+       struct usb_composite_dev *cdev = f->config->cdev;
+       /* Control interface has only altsetting 0 */
+@@ -887,12 +887,13 @@ static int ncm_set_alt(struct usb_functi
+               if (alt > 1)
+                       goto fail;
+-              if (ncm->is_connected) {
+-                      DBG(cdev, "reset ncm\n");
+-                      ncm->is_connected = false;
+-                      gether_disconnect(&ncm->port);
+-                      ncm_reset_values(ncm);
+-              }
++              scoped_guard(mutex, &opts->lock)
++                      if (opts->net) {
++                              DBG(cdev, "reset ncm\n");
++                              opts->net = NULL;
++                              gether_disconnect(&ncm->port);
++                              ncm_reset_values(ncm);
++                      }
+               /*
+                * CDC Network only sends data in non-default altsettings.
+@@ -925,7 +926,8 @@ static int ncm_set_alt(struct usb_functi
+                       net = gether_connect(&ncm->port);
+                       if (IS_ERR(net))
+                               return PTR_ERR(net);
+-                      ncm->is_connected = true;
++                      scoped_guard(mutex, &opts->lock)
++                              opts->net = net;
+               }
+               spin_lock(&ncm->lock);
+@@ -1372,14 +1374,16 @@ err:
+ static void ncm_disable(struct usb_function *f)
+ {
+       struct f_ncm            *ncm = func_to_ncm(f);
++      struct f_ncm_opts       *opts = func_to_ncm_opts(f);
+       struct usb_composite_dev *cdev = f->config->cdev;
+       DBG(cdev, "ncm deactivated\n");
+-      if (ncm->is_connected) {
+-              ncm->is_connected = false;
+-              gether_disconnect(&ncm->port);
+-      }
++      scoped_guard(mutex, &opts->lock)
++              if (opts->net) {
++                      opts->net = NULL;
++                      gether_disconnect(&ncm->port);
++              }
+       if (ncm->notify->enabled) {
+               usb_ep_disable(ncm->notify);
+@@ -1683,6 +1687,7 @@ static struct usb_function_instance *ncm
+       if (!opts)
+               return ERR_PTR(-ENOMEM);
++      opts->net = NULL;
+       opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id;
+       gether_setup_opts_default(&opts->net_opts, "usb");
+--- a/drivers/usb/gadget/function/u_ether_configfs.h
++++ b/drivers/usb/gadget/function/u_ether_configfs.h
+@@ -326,9 +326,18 @@ out:                                                                      \
+                                             char *page)                       \
+       {                                                                       \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
++              const char *name;                                               \
+                                                                               \
+               guard(mutex)(&opts->lock);                                      \
+-              return sysfs_emit(page, "%s\n", opts->net_opts.name);           \
++              rtnl_lock();                                                    \
++              if (opts->net_opts.ifname_set)                                  \
++                      name = opts->net_opts.name;                             \
++              else if (opts->net)                                             \
++                      name = netdev_name(opts->net);                          \
++              else                                                            \
++                      name = "(inactive net_device)";                         \
++              rtnl_unlock();                                                  \
++              return sysfs_emit(page, "%s\n", name);                          \
+       }                                                                       \
+                                                                               \
+       static ssize_t _f_##_opts_ifname_store(struct config_item *item,        \
+--- a/drivers/usb/gadget/function/u_ncm.h
++++ b/drivers/usb/gadget/function/u_ncm.h
+@@ -19,6 +19,7 @@
+ struct f_ncm_opts {
+       struct usb_function_instance    func_inst;
++      struct net_device               *net;
+       struct gether_opts              net_opts;
+       struct config_group             *ncm_interf_group;
diff --git a/queue-6.19/revert-usb-gadget-u_ether-add-auto-cleanup-helper-for-freeing-net_device.patch b/queue-6.19/revert-usb-gadget-u_ether-add-auto-cleanup-helper-for-freeing-net_device.patch
new file mode 100644 (file)
index 0000000..103b542
--- /dev/null
@@ -0,0 +1,80 @@
+From 46662d3a1ad40282ba9f753cccc6f909ec4468cc Mon Sep 17 00:00:00 2001
+From: Kuen-Han Tsai <khtsai@google.com>
+Date: Mon, 9 Mar 2026 20:04:49 +0800
+Subject: Revert "usb: gadget: u_ether: Add auto-cleanup helper for freeing net_device"
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+commit 46662d3a1ad40282ba9f753cccc6f909ec4468cc upstream.
+
+This reverts commit 0c0981126b99288ed354d3d414c8a5fd42ac9e25.
+
+This commit is being reverted as part of a series-wide revert.
+
+By deferring the net_device allocation to the bind() phase, a single
+function instance will spawn multiple network devices if it is symlinked
+to multiple USB configurations.
+
+This causes regressions for userspace tools (like the postmarketOS DHCP
+daemon) that rely on reading the interface name (e.g., "usb0") from
+configfs. Currently, configfs returns the template "usb%d", causing the
+userspace network setup to fail.
+
+Crucially, because this patch breaks the 1:1 mapping between the
+function instance and the network device, this naming issue cannot
+simply be patched. Configfs only exposes a single 'ifname' attribute per
+instance, making it impossible to accurately report the actual interface
+name when multiple underlying network devices can exist for that single
+instance.
+
+All configurations tied to the same function instance are meant to share
+a single network device. Revert this change to restore the 1:1 mapping
+by allocating the network device at the instance level (alloc_inst).
+
+Reported-by: David Heidelberg <david@ixit.cz>
+Closes: https://lore.kernel.org/linux-usb/70b558ea-a12e-4170-9b8e-c951131249af@ixit.cz/
+Fixes: 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle with bind/unbind")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://patch.msgid.link/20260309-f-ncm-revert-v2-4-ea2afbc7d9b2@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/u_ether.c |   15 ---------------
+ drivers/usb/gadget/function/u_ether.h |    2 --
+ 2 files changed, 17 deletions(-)
+
+--- a/drivers/usb/gadget/function/u_ether.c
++++ b/drivers/usb/gadget/function/u_ether.c
+@@ -1125,21 +1125,6 @@ void gether_cleanup(struct eth_dev *dev)
+ }
+ EXPORT_SYMBOL_GPL(gether_cleanup);
+-void gether_unregister_free_netdev(struct net_device *net)
+-{
+-      if (!net)
+-              return;
+-
+-      struct eth_dev *dev = netdev_priv(net);
+-
+-      if (net->reg_state == NETREG_REGISTERED) {
+-              unregister_netdev(net);
+-              flush_work(&dev->work);
+-      }
+-      free_netdev(net);
+-}
+-EXPORT_SYMBOL_GPL(gether_unregister_free_netdev);
+-
+ /**
+  * gether_connect - notify network layer that USB link is active
+  * @link: the USB link, set up with endpoints, descriptors matching
+--- a/drivers/usb/gadget/function/u_ether.h
++++ b/drivers/usb/gadget/function/u_ether.h
+@@ -283,8 +283,6 @@ int gether_get_ifname(struct net_device
+ int gether_set_ifname(struct net_device *net, const char *name, int len);
+ void gether_cleanup(struct eth_dev *dev);
+-void gether_unregister_free_netdev(struct net_device *net);
+-DEFINE_FREE(free_gether_netdev, struct net_device *, gether_unregister_free_netdev(_T));
+ void gether_setup_opts_default(struct gether_opts *opts, const char *name);
+ void gether_apply_opts(struct net_device *net, struct gether_opts *opts);
diff --git a/queue-6.19/revert-usb-gadget-u_ether-add-gether_opts-for-config-caching.patch b/queue-6.19/revert-usb-gadget-u_ether-add-gether_opts-for-config-caching.patch
new file mode 100644 (file)
index 0000000..8249c2a
--- /dev/null
@@ -0,0 +1,319 @@
+From 3131c1aff7cdffb96239f06f98e16188cbc2083f Mon Sep 17 00:00:00 2001
+From: Kuen-Han Tsai <khtsai@google.com>
+Date: Mon, 9 Mar 2026 20:04:51 +0800
+Subject: Revert "usb: gadget: u_ether: add gether_opts for config caching"
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+commit 3131c1aff7cdffb96239f06f98e16188cbc2083f upstream.
+
+This reverts commit e065c6a7e46c2ee9c677fdbf50035323d2de1215.
+
+This commit is being reverted as part of a series-wide revert.
+
+By deferring the net_device allocation to the bind() phase, a single
+function instance will spawn multiple network devices if it is symlinked
+to multiple USB configurations.
+
+This causes regressions for userspace tools (like the postmarketOS DHCP
+daemon) that rely on reading the interface name (e.g., "usb0") from
+configfs. Currently, configfs returns the template "usb%d", causing the
+userspace network setup to fail.
+
+Crucially, because this patch breaks the 1:1 mapping between the
+function instance and the network device, this naming issue cannot
+simply be patched. Configfs only exposes a single 'ifname' attribute per
+instance, making it impossible to accurately report the actual interface
+name when multiple underlying network devices can exist for that single
+instance.
+
+All configurations tied to the same function instance are meant to share
+a single network device. Revert this change to restore the 1:1 mapping
+by allocating the network device at the instance level (alloc_inst).
+
+Reported-by: David Heidelberg <david@ixit.cz>
+Closes: https://lore.kernel.org/linux-usb/70b558ea-a12e-4170-9b8e-c951131249af@ixit.cz/
+Fixes: 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle with bind/unbind")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://patch.msgid.link/20260309-f-ncm-revert-v2-6-ea2afbc7d9b2@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/u_ether.c          |   30 ----
+ drivers/usb/gadget/function/u_ether.h          |   28 ---
+ drivers/usb/gadget/function/u_ether_configfs.h |  176 -------------------------
+ 3 files changed, 234 deletions(-)
+
+--- a/drivers/usb/gadget/function/u_ether.c
++++ b/drivers/usb/gadget/function/u_ether.c
+@@ -1039,36 +1039,6 @@ int gether_set_ifname(struct net_device
+ }
+ EXPORT_SYMBOL_GPL(gether_set_ifname);
+-void gether_setup_opts_default(struct gether_opts *opts, const char *name)
+-{
+-      opts->qmult = QMULT_DEFAULT;
+-      snprintf(opts->name, sizeof(opts->name), "%s%%d", name);
+-      eth_random_addr(opts->dev_mac);
+-      opts->addr_assign_type = NET_ADDR_RANDOM;
+-      eth_random_addr(opts->host_mac);
+-}
+-EXPORT_SYMBOL_GPL(gether_setup_opts_default);
+-
+-void gether_apply_opts(struct net_device *net, struct gether_opts *opts)
+-{
+-      struct eth_dev *dev = netdev_priv(net);
+-
+-      dev->qmult = opts->qmult;
+-
+-      if (opts->ifname_set) {
+-              strscpy(net->name, opts->name, sizeof(net->name));
+-              dev->ifname_set = true;
+-      }
+-
+-      memcpy(dev->host_mac, opts->host_mac, sizeof(dev->host_mac));
+-
+-      if (opts->addr_assign_type == NET_ADDR_SET) {
+-              memcpy(dev->dev_mac, opts->dev_mac, sizeof(dev->dev_mac));
+-              net->addr_assign_type = opts->addr_assign_type;
+-      }
+-}
+-EXPORT_SYMBOL_GPL(gether_apply_opts);
+-
+ void gether_suspend(struct gether *link)
+ {
+       struct eth_dev *dev = link->ioport;
+--- a/drivers/usb/gadget/function/u_ether.h
++++ b/drivers/usb/gadget/function/u_ether.h
+@@ -38,31 +38,6 @@
+ struct eth_dev;
+-/**
+- * struct gether_opts - Options for Ethernet gadget function instances
+- * @name: Pattern for the network interface name (e.g., "usb%d").
+- *        Used to generate the net device name.
+- * @qmult: Queue length multiplier for high/super speed.
+- * @host_mac: The MAC address to be used by the host side.
+- * @dev_mac: The MAC address to be used by the device side.
+- * @ifname_set: True if the interface name pattern has been set by userspace.
+- * @addr_assign_type: The method used for assigning the device MAC address
+- *                    (e.g., NET_ADDR_RANDOM, NET_ADDR_SET).
+- *
+- * This structure caches network-related settings provided through configfs
+- * before the net_device is fully instantiated. This allows for early
+- * configuration while deferring net_device allocation until the function
+- * is bound.
+- */
+-struct gether_opts {
+-      char                    name[IFNAMSIZ];
+-      unsigned int            qmult;
+-      u8                      host_mac[ETH_ALEN];
+-      u8                      dev_mac[ETH_ALEN];
+-      bool                    ifname_set;
+-      unsigned char           addr_assign_type;
+-};
+-
+ /*
+  * This represents the USB side of an "ethernet" link, managed by a USB
+  * function which provides control and (maybe) framing.  Two functions
+@@ -284,9 +259,6 @@ int gether_set_ifname(struct net_device
+ void gether_cleanup(struct eth_dev *dev);
+-void gether_setup_opts_default(struct gether_opts *opts, const char *name);
+-void gether_apply_opts(struct net_device *net, struct gether_opts *opts);
+-
+ void gether_suspend(struct gether *link);
+ void gether_resume(struct gether *link);
+--- a/drivers/usb/gadget/function/u_ether_configfs.h
++++ b/drivers/usb/gadget/function/u_ether_configfs.h
+@@ -13,12 +13,6 @@
+ #ifndef __U_ETHER_CONFIGFS_H
+ #define __U_ETHER_CONFIGFS_H
+-#include <linux/cleanup.h>
+-#include <linux/if_ether.h>
+-#include <linux/mutex.h>
+-#include <linux/netdevice.h>
+-#include <linux/rtnetlink.h>
+-
+ #define USB_ETHERNET_CONFIGFS_ITEM(_f_)                                       \
+       static void _f_##_attr_release(struct config_item *item)        \
+       {                                                               \
+@@ -203,174 +197,4 @@ out:                                                                     \
+                                                                       \
+       CONFIGFS_ATTR(_f_##_opts_, _n_)
+-#define USB_ETHER_OPTS_ITEM(_f_)                                              \
+-      static void _f_##_attr_release(struct config_item *item)                \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-                                                                              \
+-              usb_put_function_instance(&opts->func_inst);                    \
+-      }                                                                       \
+-                                                                              \
+-      static struct configfs_item_operations _f_##_item_ops = {               \
+-              .release        = _f_##_attr_release,                           \
+-      }
+-
+-#define USB_ETHER_OPTS_ATTR_DEV_ADDR(_f_)                                     \
+-      static ssize_t _f_##_opts_dev_addr_show(struct config_item *item,       \
+-                                              char *page)                     \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-                                                                              \
+-              guard(mutex)(&opts->lock);                                      \
+-              return sysfs_emit(page, "%pM\n", opts->net_opts.dev_mac);       \
+-      }                                                                       \
+-                                                                              \
+-      static ssize_t _f_##_opts_dev_addr_store(struct config_item *item,      \
+-                                               const char *page, size_t len)  \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-              u8 new_addr[ETH_ALEN];                                          \
+-              const char *p = page;                                           \
+-                                                                              \
+-              guard(mutex)(&opts->lock);                                      \
+-              if (opts->refcnt)                                               \
+-                      return -EBUSY;                                          \
+-                                                                              \
+-              for (int i = 0; i < ETH_ALEN; i++) {                            \
+-                      unsigned char num;                                      \
+-                      if ((*p == '.') || (*p == ':'))                         \
+-                              p++;                                            \
+-                      num = hex_to_bin(*p++) << 4;                            \
+-                      num |= hex_to_bin(*p++);                                \
+-                      new_addr[i] = num;                                      \
+-              }                                                               \
+-              if (!is_valid_ether_addr(new_addr))                             \
+-                      return -EINVAL;                                         \
+-              memcpy(opts->net_opts.dev_mac, new_addr, ETH_ALEN);             \
+-              opts->net_opts.addr_assign_type = NET_ADDR_SET;                 \
+-              return len;                                                     \
+-      }                                                                       \
+-                                                                              \
+-      CONFIGFS_ATTR(_f_##_opts_, dev_addr)
+-
+-#define USB_ETHER_OPTS_ATTR_HOST_ADDR(_f_)                                    \
+-      static ssize_t _f_##_opts_host_addr_show(struct config_item *item,      \
+-                                               char *page)                    \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-                                                                              \
+-              guard(mutex)(&opts->lock);                                      \
+-              return sysfs_emit(page, "%pM\n", opts->net_opts.host_mac);      \
+-      }                                                                       \
+-                                                                              \
+-      static ssize_t _f_##_opts_host_addr_store(struct config_item *item,     \
+-                                                const char *page, size_t len) \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-              u8 new_addr[ETH_ALEN];                                          \
+-              const char *p = page;                                           \
+-                                                                              \
+-              guard(mutex)(&opts->lock);                                      \
+-              if (opts->refcnt)                                               \
+-                      return -EBUSY;                                          \
+-                                                                              \
+-              for (int i = 0; i < ETH_ALEN; i++) {                            \
+-                      unsigned char num;                                      \
+-                      if ((*p == '.') || (*p == ':'))                         \
+-                              p++;                                            \
+-                      num = hex_to_bin(*p++) << 4;                            \
+-                      num |= hex_to_bin(*p++);                                \
+-                      new_addr[i] = num;                                      \
+-              }                                                               \
+-              if (!is_valid_ether_addr(new_addr))                             \
+-                      return -EINVAL;                                         \
+-              memcpy(opts->net_opts.host_mac, new_addr, ETH_ALEN);            \
+-              return len;                                                     \
+-      }                                                                       \
+-                                                                              \
+-      CONFIGFS_ATTR(_f_##_opts_, host_addr)
+-
+-#define USB_ETHER_OPTS_ATTR_QMULT(_f_)                                                \
+-      static ssize_t _f_##_opts_qmult_show(struct config_item *item,          \
+-                                           char *page)                        \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-                                                                              \
+-              guard(mutex)(&opts->lock);                                      \
+-              return sysfs_emit(page, "%u\n", opts->net_opts.qmult);          \
+-      }                                                                       \
+-                                                                              \
+-      static ssize_t _f_##_opts_qmult_store(struct config_item *item,         \
+-                                            const char *page, size_t len)     \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-              u32 val;                                                        \
+-              int ret;                                                        \
+-                                                                              \
+-              guard(mutex)(&opts->lock);                                      \
+-              if (opts->refcnt)                                               \
+-                      return -EBUSY;                                          \
+-                                                                              \
+-              ret = kstrtou32(page, 0, &val);                                 \
+-              if (ret)                                                        \
+-                      return ret;                                             \
+-                                                                              \
+-              opts->net_opts.qmult = val;                                     \
+-              return len;                                                     \
+-      }                                                                       \
+-                                                                              \
+-      CONFIGFS_ATTR(_f_##_opts_, qmult)
+-
+-#define USB_ETHER_OPTS_ATTR_IFNAME(_f_)                                               \
+-      static ssize_t _f_##_opts_ifname_show(struct config_item *item,         \
+-                                            char *page)                       \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-              const char *name;                                               \
+-                                                                              \
+-              guard(mutex)(&opts->lock);                                      \
+-              rtnl_lock();                                                    \
+-              if (opts->net_opts.ifname_set)                                  \
+-                      name = opts->net_opts.name;                             \
+-              else if (opts->net)                                             \
+-                      name = netdev_name(opts->net);                          \
+-              else                                                            \
+-                      name = "(inactive net_device)";                         \
+-              rtnl_unlock();                                                  \
+-              return sysfs_emit(page, "%s\n", name);                          \
+-      }                                                                       \
+-                                                                              \
+-      static ssize_t _f_##_opts_ifname_store(struct config_item *item,        \
+-                                             const char *page, size_t len)    \
+-      {                                                                       \
+-              struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-              char tmp[IFNAMSIZ];                                             \
+-              const char *p;                                                  \
+-              size_t c_len = len;                                             \
+-                                                                              \
+-              if (c_len > 0 && page[c_len - 1] == '\n')                       \
+-                      c_len--;                                                \
+-                                                                              \
+-              if (c_len >= sizeof(tmp))                                       \
+-                      return -E2BIG;                                          \
+-                                                                              \
+-              strscpy(tmp, page, c_len + 1);                                  \
+-              if (!dev_valid_name(tmp))                                       \
+-                      return -EINVAL;                                         \
+-                                                                              \
+-              /* Require exactly one %d */                                    \
+-              p = strchr(tmp, '%');                                           \
+-              if (!p || p[1] != 'd' || strchr(p + 2, '%'))                    \
+-                      return -EINVAL;                                         \
+-                                                                              \
+-              guard(mutex)(&opts->lock);                                      \
+-              if (opts->refcnt)                                               \
+-                      return -EBUSY;                                          \
+-              strscpy(opts->net_opts.name, tmp, sizeof(opts->net_opts.name)); \
+-              opts->net_opts.ifname_set = true;                               \
+-              return len;                                                     \
+-      }                                                                       \
+-                                                                              \
+-      CONFIGFS_ATTR(_f_##_opts_, ifname)
+-
+ #endif /* __U_ETHER_CONFIGFS_H */
diff --git a/queue-6.19/revert-usb-legacy-ncm-fix-npe-in-gncm_bind.patch b/queue-6.19/revert-usb-legacy-ncm-fix-npe-in-gncm_bind.patch
new file mode 100644 (file)
index 0000000..d7f94b2
--- /dev/null
@@ -0,0 +1,84 @@
+From f2524c0e6ff0a5f72f1e1a32441c69d3b56430c4 Mon Sep 17 00:00:00 2001
+From: Kuen-Han Tsai <khtsai@google.com>
+Date: Mon, 9 Mar 2026 20:04:47 +0800
+Subject: Revert "usb: legacy: ncm: Fix NPE in gncm_bind"
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+commit f2524c0e6ff0a5f72f1e1a32441c69d3b56430c4 upstream.
+
+This reverts commit fde0634ad9856b3943a2d1a8cc8de174a63ac840.
+
+This commit is being reverted as part of a series-wide revert.
+
+By deferring the net_device allocation to the bind() phase, a single
+function instance will spawn multiple network devices if it is symlinked
+to multiple USB configurations.
+
+This causes regressions for userspace tools (like the postmarketOS DHCP
+daemon) that rely on reading the interface name (e.g., "usb0") from
+configfs. Currently, configfs returns the template "usb%d", causing the
+userspace network setup to fail.
+
+Crucially, because this patch breaks the 1:1 mapping between the
+function instance and the network device, this naming issue cannot
+simply be patched. Configfs only exposes a single 'ifname' attribute per
+instance, making it impossible to accurately report the actual interface
+name when multiple underlying network devices can exist for that single
+instance.
+
+All configurations tied to the same function instance are meant to share
+a single network device. Revert this change to restore the 1:1 mapping
+by allocating the network device at the instance level (alloc_inst).
+
+Reported-by: David Heidelberg <david@ixit.cz>
+Closes: https://lore.kernel.org/linux-usb/70b558ea-a12e-4170-9b8e-c951131249af@ixit.cz/
+Fixes: 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle with bind/unbind")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://patch.msgid.link/20260309-f-ncm-revert-v2-2-ea2afbc7d9b2@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/legacy/ncm.c |   13 +++----------
+ 1 file changed, 3 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/gadget/legacy/ncm.c
++++ b/drivers/usb/gadget/legacy/ncm.c
+@@ -15,10 +15,8 @@
+ /* #define DEBUG */
+ /* #define VERBOSE_DEBUG */
+-#include <linux/hex.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+-#include <linux/string.h>
+ #include <linux/usb/composite.h>
+ #include "u_ether.h"
+@@ -131,7 +129,6 @@ static int gncm_bind(struct usb_composit
+       struct usb_gadget       *gadget = cdev->gadget;
+       struct f_ncm_opts       *ncm_opts;
+       int                     status;
+-      u8                      mac[ETH_ALEN];
+       f_ncm_inst = usb_get_function_instance("ncm");
+       if (IS_ERR(f_ncm_inst))
+@@ -139,15 +136,11 @@ static int gncm_bind(struct usb_composit
+       ncm_opts = container_of(f_ncm_inst, struct f_ncm_opts, func_inst);
+-      ncm_opts->net_opts.qmult = qmult;
+-      if (host_addr && mac_pton(host_addr, mac)) {
+-              memcpy(&ncm_opts->net_opts.host_mac, mac, ETH_ALEN);
++      gether_set_qmult(ncm_opts->net, qmult);
++      if (!gether_set_host_addr(ncm_opts->net, host_addr))
+               pr_info("using host ethernet address: %s", host_addr);
+-      }
+-      if (dev_addr && mac_pton(dev_addr, mac)) {
+-              memcpy(&ncm_opts->net_opts.dev_mac, mac, ETH_ALEN);
++      if (!gether_set_dev_addr(ncm_opts->net, dev_addr))
+               pr_info("using self ethernet address: %s", dev_addr);
+-      }
+       /* Allocate string descriptor numbers ... note that string
+        * contents can be overridden by the composite_dev glue.
index cd7bd52c945ba0973183d2c9e6f33d4926af2ba1..7e5369c46f3a45afa6f66eb4e743d8f5cb248069 100644 (file)
@@ -130,3 +130,42 @@ rust_binder-call-set_notification_done-without-proc-lock.patch
 rust-kbuild-allow-unused_features.patch
 rust-kbuild-emit-dep-info-into-depfile-directly.patch
 rust-str-make-nullterminatedformatter-public.patch
+ata-libata-core-add-bridge_ok-quirk-for-qemu-drives.patch
+asoc-amd-yc-add-dmi-quirk-for-asus-expertbook-pm1503cda.patch
+kvm-arm64-fix-protected-mode-handling-of-pages-larger-than-4kb.patch
+kvm-x86-introduce-kvm_x86_quirk_vmcs12_allow_freeze_in_smm.patch
+kvm-svm-initialize-avic-vmcb-fields-if-avic-is-enabled-with-in-kernel-apic.patch
+kvm-svm-set-clear-cr8-write-interception-when-avic-is-de-activated.patch
+kvm-arm64-pkvm-fallback-to-level-3-mapping-on-host-stage-2-fault.patch
+kvm-arm64-vgic-pick-eoicount-deactivations-from-ap-list-tail.patch
+kvm-arm64-pkvm-don-t-reprobe-for-ich_vtr_el2.tds-on-cpu-hotplug.patch
+usb-add-quirk_no_bos-for-video-capture-several-devices.patch
+usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch
+usb-ezcap401-needs-usb_quirk_no_bos-to-function-on-10gbs-usb-speed.patch
+usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch
+usb-xhci-prevent-interrupt-storm-on-host-controller-error-hce.patch
+xhci-fix-null-pointer-dereference-when-reading-portli-debugfs-files.patch
+usb-yurex-fix-race-in-probe.patch
+usb-dwc3-pci-add-support-for-the-intel-nova-lake-h.patch
+usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch
+usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch
+usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch
+usb-roles-get-usb-role-switch-from-parent-only-for-usb-b-connector.patch
+usb-typec-altmode-displayport-set-displayport-signaling-rate-in-configure-message.patch
+usb-usbcore-introduce-usb_bulk_msg_killable.patch
+usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch
+usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch
+usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch
+usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch
+usb-gadget-f_hid-fix-superspeed-descriptors.patch
+usb-mdc800-handle-signal-and-read-racing.patch
+usb-gadget-uvc-fix-interval_duration-calculation.patch
+usb-image-mdc800-kill-download-urb-on-timeout.patch
+usb-gadget-f_tcm-fix-null-pointer-dereferences-in-nexus-handling.patch
+usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch
+usb-legacy-ncm-fix-npe-in-gncm_bind.patch
+revert-usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch
+revert-usb-legacy-ncm-fix-npe-in-gncm_bind.patch
+revert-usb-gadget-u_ether-add-auto-cleanup-helper-for-freeing-net_device.patch
+revert-usb-gadget-f_ncm-align-net_device-lifecycle-with-bind-unbind.patch
+revert-usb-gadget-u_ether-add-gether_opts-for-config-caching.patch
diff --git a/queue-6.19/usb-add-quirk_no_bos-for-video-capture-several-devices.patch b/queue-6.19/usb-add-quirk_no_bos-for-video-capture-several-devices.patch
new file mode 100644 (file)
index 0000000..3293ff9
--- /dev/null
@@ -0,0 +1,59 @@
+From 93cd0d664661f58f7e7bed7373714ab2ace41734 Mon Sep 17 00:00:00 2001
+From: A1RM4X <dev@a1rm4x.com>
+Date: Wed, 4 Feb 2026 14:26:48 -0500
+Subject: USB: add QUIRK_NO_BOS for video capture several devices
+
+From: A1RM4X <dev@a1rm4x.com>
+
+commit 93cd0d664661f58f7e7bed7373714ab2ace41734 upstream.
+
+Several USB capture devices also need the USB_QUIRK_NO_BOS set for them
+to work properly, odds are they are all the same chip inside, just
+different vendor/product ids.
+
+This fixes up:
+  - ASUS TUF 4K PRO
+  - Avermedia Live Gamer Ultra 2.1 (GC553G2)
+  - UGREEN 35871
+to now run at full speed (10 Gbps/4K 60 fps mode.)
+
+Link: https://lore.kernel.org/r/CACy+XB-f-51xGpNQFCSm5pE_momTQLu=BaZggHYU1DiDmFX=ug@mail.gmail.com
+Cc: stable <stable@kernel.org>
+Signed-off-by: A1RM4X <dev@a1rm4x.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/quirks.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -377,6 +377,9 @@ static const struct usb_device_id usb_qu
+       /* SanDisk Extreme 55AE */
+       { USB_DEVICE(0x0781, 0x55ae), .driver_info = USB_QUIRK_NO_LPM },
++      /* Avermedia Live Gamer Ultra 2.1 (GC553G2) - BOS descriptor fetch hangs at SuperSpeed Plus */
++      { USB_DEVICE(0x07ca, 0x2553), .driver_info = USB_QUIRK_NO_BOS },
++
+       /* Realforce 87U Keyboard */
+       { USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM },
+@@ -437,6 +440,9 @@ static const struct usb_device_id usb_qu
+       { USB_DEVICE(0x0b05, 0x17e0), .driver_info =
+                       USB_QUIRK_IGNORE_REMOTE_WAKEUP },
++      /* ASUS TUF 4K PRO - BOS descriptor fetch hangs at SuperSpeed Plus */
++      { USB_DEVICE(0x0b05, 0x1ab9), .driver_info = USB_QUIRK_NO_BOS },
++
+       /* Realtek Semiconductor Corp. Mass Storage Device (Multicard Reader)*/
+       { USB_DEVICE(0x0bda, 0x0151), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },
+@@ -565,6 +571,9 @@ static const struct usb_device_id usb_qu
+       { USB_DEVICE(0x2386, 0x350e), .driver_info = USB_QUIRK_NO_LPM },
++      /* UGREEN 35871 - BOS descriptor fetch hangs at SuperSpeed Plus */
++      { USB_DEVICE(0x2b89, 0x5871), .driver_info = USB_QUIRK_NO_BOS },
++
+       /* APTIV AUTOMOTIVE HUB */
+       { USB_DEVICE(0x2c48, 0x0132), .driver_info =
+                       USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT },
diff --git a/queue-6.19/usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch b/queue-6.19/usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch
new file mode 100644 (file)
index 0000000..ce76733
--- /dev/null
@@ -0,0 +1,62 @@
+From 14ae24cba291bddfdc296bbcbfd00cd09d0498ef Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Sun, 1 Mar 2026 12:44:40 +0000
+Subject: usb: cdc-acm: Restore CAP_BRK functionnality to CH343
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 14ae24cba291bddfdc296bbcbfd00cd09d0498ef upstream.
+
+The CH343 USB/serial adapter is as buggy as it is popular (very).
+One of its quirks is that despite being capable of signalling a
+BREAK condition, it doesn't advertise it.
+
+This used to work nonetheless until 66aad7d8d3ec5 ("usb: cdc-acm:
+return correct error code on unsupported break") applied some
+reasonable restrictions, preventing breaks from being emitted on
+devices that do not advertise CAP_BRK.
+
+Add a quirk for this particular device, so that breaks can still
+be produced on some of my machines attached to my console server.
+
+Fixes: 66aad7d8d3ec5 ("usb: cdc-acm: return correct error code on unsupported break")
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Cc: stable <stable@kernel.org>
+Cc: Oliver Neukum <oneukum@suse.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Link: https://patch.msgid.link/20260301124440.1192752-1-maz@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/class/cdc-acm.c |    5 +++++
+ drivers/usb/class/cdc-acm.h |    1 +
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1379,6 +1379,8 @@ made_compressed_probe:
+               acm->ctrl_caps = h.usb_cdc_acm_descriptor->bmCapabilities;
+       if (quirks & NO_CAP_LINE)
+               acm->ctrl_caps &= ~USB_CDC_CAP_LINE;
++      if (quirks & MISSING_CAP_BRK)
++              acm->ctrl_caps |= USB_CDC_CAP_BRK;
+       acm->ctrlsize = ctrlsize;
+       acm->readsize = readsize;
+       acm->rx_buflimit = num_rx_buf;
+@@ -2002,6 +2004,9 @@ static const struct usb_device_id acm_id
+       .driver_info = IGNORE_DEVICE,
+       },
++      /* CH343 supports CAP_BRK, but doesn't advertise it */
++      { USB_DEVICE(0x1a86, 0x55d3), .driver_info = MISSING_CAP_BRK, },
++
+       /* control interfaces without any protocol set */
+       { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+               USB_CDC_PROTO_NONE) },
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -113,3 +113,4 @@ struct acm {
+ #define CLEAR_HALT_CONDITIONS         BIT(5)
+ #define SEND_ZERO_PACKET              BIT(6)
+ #define DISABLE_ECHO                  BIT(7)
++#define MISSING_CAP_BRK                       BIT(8)
diff --git a/queue-6.19/usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch b/queue-6.19/usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch
new file mode 100644 (file)
index 0000000..63c6ae2
--- /dev/null
@@ -0,0 +1,50 @@
+From 8df672bfe3ec2268c2636584202755898e547173 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Wed, 4 Mar 2026 14:01:12 +0100
+Subject: usb: class: cdc-wdm: fix reordering issue in read code path
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit 8df672bfe3ec2268c2636584202755898e547173 upstream.
+
+Quoting the bug report:
+
+Due to compiler optimization or CPU out-of-order execution, the
+desc->length update can be reordered before the memmove. If this
+happens, wdm_read() can see the new length and call copy_to_user() on
+uninitialized memory. This also violates LKMM data race rules [1].
+
+Fix it by using WRITE_ONCE and memory barriers.
+
+Fixes: afba937e540c9 ("USB: CDC WDM driver")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Closes: https://lore.kernel.org/linux-usb/CALbr=LbrUZn_cfp7CfR-7Z5wDTHF96qeuM=3fO2m-q4cDrnC4A@mail.gmail.com/
+Reported-by: Gui-Dong Han <hanguidong02@gmail.com>
+Reviewed-by: Gui-Dong Han <hanguidong02@gmail.com>
+Link: https://patch.msgid.link/20260304130116.1721682-1-oneukum@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/class/cdc-wdm.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -225,7 +225,8 @@ static void wdm_in_callback(struct urb *
+               /* we may already be in overflow */
+               if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
+                       memmove(desc->ubuf + desc->length, desc->inbuf, length);
+-                      desc->length += length;
++                      smp_wmb(); /* against wdm_read() */
++                      WRITE_ONCE(desc->length, desc->length + length);
+               }
+       }
+ skip_error:
+@@ -533,6 +534,7 @@ static ssize_t wdm_read
+               return -ERESTARTSYS;
+       cntr = READ_ONCE(desc->length);
++      smp_rmb(); /* against wdm_in_callback() */
+       if (cntr == 0) {
+               desc->read = 0;
+ retry:
diff --git a/queue-6.19/usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch b/queue-6.19/usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch
new file mode 100644 (file)
index 0000000..c2d62fb
--- /dev/null
@@ -0,0 +1,50 @@
+From e293015ba76eb96ce4ebed7e3b2cb1a7d319f3e9 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Wed, 18 Feb 2026 21:21:07 +0100
+Subject: usb: core: don't power off roothub PHYs if phy_set_mode() fails
+
+From: Gabor Juhos <j4g8y7@gmail.com>
+
+commit e293015ba76eb96ce4ebed7e3b2cb1a7d319f3e9 upstream.
+
+Remove the error path from the usb_phy_roothub_set_mode() function.
+The code is clearly wrong, because phy_set_mode() calls can't be
+balanced with phy_power_off() calls.
+
+Additionally, the usb_phy_roothub_set_mode() function is called only
+from usb_add_hcd() before it powers on the PHYs, so powering off those
+makes no sense anyway.
+
+Presumably, the code is copy-pasted from the phy_power_on() function
+without adjusting the error handling.
+
+Cc: stable@vger.kernel.org # v5.1+
+Fixes: b97a31348379 ("usb: core: comply to PHY framework")
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://patch.msgid.link/20260218-usb-phy-poweroff-fix-v1-1-66e6831e860e@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/phy.c |    8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+--- a/drivers/usb/core/phy.c
++++ b/drivers/usb/core/phy.c
+@@ -200,16 +200,10 @@ int usb_phy_roothub_set_mode(struct usb_
+       list_for_each_entry(roothub_entry, head, list) {
+               err = phy_set_mode(roothub_entry->phy, mode);
+               if (err)
+-                      goto err_out;
++                      return err;
+       }
+       return 0;
+-
+-err_out:
+-      list_for_each_entry_continue_reverse(roothub_entry, head, list)
+-              phy_power_off(roothub_entry->phy);
+-
+-      return err;
+ }
+ EXPORT_SYMBOL_GPL(usb_phy_roothub_set_mode);
diff --git a/queue-6.19/usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch b/queue-6.19/usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch
new file mode 100644 (file)
index 0000000..d382a47
--- /dev/null
@@ -0,0 +1,134 @@
+From 1015c27a5e1a63efae2b18a9901494474b4d1dc3 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Tue, 17 Feb 2026 22:10:32 -0500
+Subject: USB: core: Limit the length of unkillable synchronous timeouts
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 1015c27a5e1a63efae2b18a9901494474b4d1dc3 upstream.
+
+The usb_control_msg(), usb_bulk_msg(), and usb_interrupt_msg() APIs in
+usbcore allow unlimited timeout durations.  And since they use
+uninterruptible waits, this leaves open the possibility of hanging a
+task for an indefinitely long time, with no way to kill it short of
+unplugging the target device.
+
+To prevent this sort of problem, enforce a maximum limit on the length
+of these unkillable timeouts.  The limit chosen here, somewhat
+arbitrarily, is 60 seconds.  On many systems (although not all) this
+is short enough to avoid triggering the kernel's hung-task detector.
+
+In addition, clear up the ambiguity of negative timeout values by
+treating them the same as 0, i.e., using the maximum allowed timeout.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/linux-usb/3acfe838-6334-4f6d-be7c-4bb01704b33d@rowland.harvard.edu/
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+CC: stable@vger.kernel.org
+Link: https://patch.msgid.link/15fc9773-a007-47b0-a703-df89a8cf83dd@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/message.c |   27 +++++++++++++--------------
+ include/linux/usb.h        |    3 +++
+ 2 files changed, 16 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -45,6 +45,8 @@ static void usb_api_blocking_completion(
+  * Starts urb and waits for completion or timeout.
+  * Whether or not the wait is killable depends on the flag passed in.
+  * For example, compare usb_bulk_msg() and usb_bulk_msg_killable().
++ *
++ * For non-killable waits, we enforce a maximum limit on the timeout value.
+  */
+ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length,
+               bool killable)
+@@ -61,7 +63,9 @@ static int usb_start_wait_urb(struct urb
+       if (unlikely(retval))
+               goto out;
+-      expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
++      if (!killable && (timeout <= 0 || timeout > USB_MAX_SYNCHRONOUS_TIMEOUT))
++              timeout = USB_MAX_SYNCHRONOUS_TIMEOUT;
++      expire = (timeout > 0) ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
+       if (killable)
+               rc = wait_for_completion_killable_timeout(&ctx.done, expire);
+       else
+@@ -127,8 +131,7 @@ static int usb_internal_control_msg(stru
+  * @index: USB message index value
+  * @data: pointer to the data to send
+  * @size: length in bytes of the data to send
+- * @timeout: time in msecs to wait for the message to complete before timing
+- *    out (if 0 the wait is forever)
++ * @timeout: time in msecs to wait for the message to complete before timing out
+  *
+  * Context: task context, might sleep.
+  *
+@@ -183,8 +186,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg);
+  * @index: USB message index value
+  * @driver_data: pointer to the data to send
+  * @size: length in bytes of the data to send
+- * @timeout: time in msecs to wait for the message to complete before timing
+- *    out (if 0 the wait is forever)
++ * @timeout: time in msecs to wait for the message to complete before timing out
+  * @memflags: the flags for memory allocation for buffers
+  *
+  * Context: !in_interrupt ()
+@@ -242,8 +244,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg_send);
+  * @index: USB message index value
+  * @driver_data: pointer to the data to be filled in by the message
+  * @size: length in bytes of the data to be received
+- * @timeout: time in msecs to wait for the message to complete before timing
+- *    out (if 0 the wait is forever)
++ * @timeout: time in msecs to wait for the message to complete before timing out
+  * @memflags: the flags for memory allocation for buffers
+  *
+  * Context: !in_interrupt ()
+@@ -314,8 +315,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg_recv);
+  * @len: length in bytes of the data to send
+  * @actual_length: pointer to a location to put the actual length transferred
+  *    in bytes
+- * @timeout: time in msecs to wait for the message to complete before
+- *    timing out (if 0 the wait is forever)
++ * @timeout: time in msecs to wait for the message to complete before timing out
+  *
+  * Context: task context, might sleep.
+  *
+@@ -347,8 +347,7 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);
+  * @len: length in bytes of the data to send
+  * @actual_length: pointer to a location to put the actual length transferred
+  *    in bytes
+- * @timeout: time in msecs to wait for the message to complete before
+- *    timing out (if 0 the wait is forever)
++ * @timeout: time in msecs to wait for the message to complete before timing out
+  *
+  * Context: task context, might sleep.
+  *
+@@ -408,12 +407,12 @@ EXPORT_SYMBOL_GPL(usb_bulk_msg);
+  * @actual_length: pointer to a location to put the actual length transferred
+  *    in bytes
+  * @timeout: time in msecs to wait for the message to complete before
+- *    timing out (if 0 the wait is forever)
++ *    timing out (if <= 0, the wait is as long as possible)
+  *
+  * Context: task context, might sleep.
+  *
+- * This function is just like usb_blk_msg() except that it waits in a
+- * killable state.
++ * This function is just like usb_blk_msg(), except that it waits in a
++ * killable state and there is no limit on the timeout length.
+  *
+  * Return:
+  * If successful, 0. Otherwise a negative error number. The number of actual
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1863,6 +1863,9 @@ void usb_free_noncoherent(struct usb_dev
+  *                         SYNCHRONOUS CALL SUPPORT                  *
+  *-------------------------------------------------------------------*/
++/* Maximum value allowed for timeout in synchronous routines below */
++#define USB_MAX_SYNCHRONOUS_TIMEOUT           60000   /* ms */
++
+ extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
+       __u8 request, __u8 requesttype, __u16 value, __u16 index,
+       void *data, __u16 size, int timeout);
diff --git a/queue-6.19/usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch b/queue-6.19/usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch
new file mode 100644 (file)
index 0000000..cefd8c6
--- /dev/null
@@ -0,0 +1,36 @@
+From 0326ff28d56b4fa202de36ffc8462a354f383a64 Mon Sep 17 00:00:00 2001
+From: Christoffer Sandberg <cs@tuxedo.de>
+Date: Fri, 6 Mar 2026 18:28:14 +0100
+Subject: usb/core/quirks: Add Huawei ME906S-device to wakeup quirk
+
+From: Christoffer Sandberg <cs@tuxedo.de>
+
+commit 0326ff28d56b4fa202de36ffc8462a354f383a64 upstream.
+
+Similar to other Huawei LTE modules using this quirk, this version with
+another vid/pid suffers from spurious wakeups.
+
+Setting the quirk fixes the issue for this device as well.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Christoffer Sandberg <cs@tuxedo.de>
+Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
+Link: https://patch.msgid.link/20260306172817.2098898-1-wse@tuxedocomputers.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/quirks.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -208,6 +208,10 @@ static const struct usb_device_id usb_qu
+       /* HP v222w 16GB Mini USB Drive */
+       { USB_DEVICE(0x03f0, 0x3f40), .driver_info = USB_QUIRK_DELAY_INIT },
++      /* Huawei 4G LTE module ME906S  */
++      { USB_DEVICE(0x03f0, 0xa31d), .driver_info =
++                      USB_QUIRK_DISCONNECT_SUSPEND },
++
+       /* Creative SB Audigy 2 NX */
+       { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
diff --git a/queue-6.19/usb-dwc3-pci-add-support-for-the-intel-nova-lake-h.patch b/queue-6.19/usb-dwc3-pci-add-support-for-the-intel-nova-lake-h.patch
new file mode 100644 (file)
index 0000000..9f6239a
--- /dev/null
@@ -0,0 +1,39 @@
+From 17ab4d4078e22be7fd8fd6fc710c15c085a4cb1b Mon Sep 17 00:00:00 2001
+From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Date: Mon, 9 Mar 2026 14:02:04 +0100
+Subject: usb: dwc3: pci: add support for the Intel Nova Lake -H
+
+From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+
+commit 17ab4d4078e22be7fd8fd6fc710c15c085a4cb1b upstream.
+
+This patch adds the necessary PCI ID for Intel Nova Lake -H
+devices.
+
+Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://patch.msgid.link/20260309130204.208661-1-heikki.krogerus@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/dwc3-pci.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -56,6 +56,7 @@
+ #define PCI_DEVICE_ID_INTEL_CNPH              0xa36e
+ #define PCI_DEVICE_ID_INTEL_CNPV              0xa3b0
+ #define PCI_DEVICE_ID_INTEL_RPL                       0xa70e
++#define PCI_DEVICE_ID_INTEL_NVLH              0xd37f
+ #define PCI_DEVICE_ID_INTEL_PTLH              0xe332
+ #define PCI_DEVICE_ID_INTEL_PTLH_PCH          0xe37e
+ #define PCI_DEVICE_ID_INTEL_PTLU              0xe432
+@@ -447,6 +448,7 @@ static const struct pci_device_id dwc3_p
+       { PCI_DEVICE_DATA(INTEL, CNPH, &dwc3_pci_intel_swnode) },
+       { PCI_DEVICE_DATA(INTEL, CNPV, &dwc3_pci_intel_swnode) },
+       { PCI_DEVICE_DATA(INTEL, RPL, &dwc3_pci_intel_swnode) },
++      { PCI_DEVICE_DATA(INTEL, NVLH, &dwc3_pci_intel_swnode) },
+       { PCI_DEVICE_DATA(INTEL, PTLH, &dwc3_pci_intel_swnode) },
+       { PCI_DEVICE_DATA(INTEL, PTLH_PCH, &dwc3_pci_intel_swnode) },
+       { PCI_DEVICE_DATA(INTEL, PTLU, &dwc3_pci_intel_swnode) },
diff --git a/queue-6.19/usb-ezcap401-needs-usb_quirk_no_bos-to-function-on-10gbs-usb-speed.patch b/queue-6.19/usb-ezcap401-needs-usb_quirk_no_bos-to-function-on-10gbs-usb-speed.patch
new file mode 100644 (file)
index 0000000..080f24a
--- /dev/null
@@ -0,0 +1,34 @@
+From d0d9b1f4f5391e6a00cee81d73ed2e8f98446d5f Mon Sep 17 00:00:00 2001
+From: Vyacheslav Vahnenko <vahnenko2003@gmail.com>
+Date: Fri, 13 Mar 2026 15:36:38 +0300
+Subject: USB: ezcap401 needs USB_QUIRK_NO_BOS to function on 10gbs usb speed
+
+From: Vyacheslav Vahnenko <vahnenko2003@gmail.com>
+
+commit d0d9b1f4f5391e6a00cee81d73ed2e8f98446d5f upstream.
+
+Add USB_QUIRK_NO_BOS for ezcap401 capture card, without it dmesg will show
+"unable to get BOS descriptor or descriptor too short" and "unable to
+read config index 0 descriptor/start: -71" errors and device will not
+able to work at full speed at 10gbs
+
+Signed-off-by: Vyacheslav Vahnenko <vahnenko2003@gmail.com>
+Cc: stable <stable@kernel.org>
+Link: https://patch.msgid.link/20260313123638.20481-1-vahnenko2003@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/quirks.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -588,6 +588,9 @@ static const struct usb_device_id usb_qu
+       /* Alcor Link AK9563 SC Reader used in 2022 Lenovo ThinkPads */
+       { USB_DEVICE(0x2ce3, 0x9563), .driver_info = USB_QUIRK_NO_LPM },
++      /* ezcap401 - BOS descriptor fetch hangs at SuperSpeed Plus */
++      { USB_DEVICE(0x32ed, 0x0401), .driver_info = USB_QUIRK_NO_BOS },
++
+       /* DELL USB GEN2 */
+       { USB_DEVICE(0x413c, 0xb062), .driver_info = USB_QUIRK_NO_LPM | USB_QUIRK_RESET_RESUME },
diff --git a/queue-6.19/usb-gadget-f_hid-fix-superspeed-descriptors.patch b/queue-6.19/usb-gadget-f_hid-fix-superspeed-descriptors.patch
new file mode 100644 (file)
index 0000000..c1b781a
--- /dev/null
@@ -0,0 +1,53 @@
+From 7f58b4148ef5d8ee0fb7d8113dcc38ff5374babc Mon Sep 17 00:00:00 2001
+From: John Keeping <jkeeping@inmusicbrands.com>
+Date: Fri, 27 Feb 2026 11:15:39 +0000
+Subject: usb: gadget: f_hid: fix SuperSpeed descriptors
+
+From: John Keeping <jkeeping@inmusicbrands.com>
+
+commit 7f58b4148ef5d8ee0fb7d8113dcc38ff5374babc upstream.
+
+When adding dynamic configuration for bInterval, the value was removed
+from the static SuperSpeed endpoint descriptors but was not set from the
+configured value in hidg_bind().  Thus at SuperSpeed the interrupt
+endpoints have bInterval as zero which is not valid per the USB
+specification.
+
+Add the missing setting for SuperSpeed endpoints.
+
+Fixes: ea34925f5b2ee ("usb: gadget: hid: allow dynamic interval configuration via configfs")
+Cc: stable <stable@kernel.org>
+Signed-off-by: John Keeping <jkeeping@inmusicbrands.com>
+Acked-by: Peter Korsgaard <peter@korsgaard.com>
+Link: https://patch.msgid.link/20260227111540.431521-1-jkeeping@inmusicbrands.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_hid.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -1207,9 +1207,11 @@ static int hidg_bind(struct usb_configur
+       if (!hidg->interval_user_set) {
+               hidg_fs_in_ep_desc.bInterval = 10;
+               hidg_hs_in_ep_desc.bInterval = 4;
++              hidg_ss_in_ep_desc.bInterval = 4;
+       } else {
+               hidg_fs_in_ep_desc.bInterval = hidg->interval;
+               hidg_hs_in_ep_desc.bInterval = hidg->interval;
++              hidg_ss_in_ep_desc.bInterval = hidg->interval;
+       }
+       hidg_ss_out_comp_desc.wBytesPerInterval =
+@@ -1239,9 +1241,11 @@ static int hidg_bind(struct usb_configur
+               if (!hidg->interval_user_set) {
+                       hidg_fs_out_ep_desc.bInterval = 10;
+                       hidg_hs_out_ep_desc.bInterval = 4;
++                      hidg_ss_out_ep_desc.bInterval = 4;
+               } else {
+                       hidg_fs_out_ep_desc.bInterval = hidg->interval;
+                       hidg_hs_out_ep_desc.bInterval = hidg->interval;
++                      hidg_ss_out_ep_desc.bInterval = hidg->interval;
+               }
+               status = usb_assign_descriptors(f,
+                           hidg_fs_descriptors_intout,
diff --git a/queue-6.19/usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch b/queue-6.19/usb-gadget-f_ncm-fix-atomic-context-locking-issue.patch
new file mode 100644 (file)
index 0000000..6998c60
--- /dev/null
@@ -0,0 +1,153 @@
+From 0d6c8144ca4d93253de952a5ea0028c19ed7ab68 Mon Sep 17 00:00:00 2001
+From: Kuen-Han Tsai <khtsai@google.com>
+Date: Sat, 21 Feb 2026 22:48:16 +0800
+Subject: usb: gadget: f_ncm: Fix atomic context locking issue
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+commit 0d6c8144ca4d93253de952a5ea0028c19ed7ab68 upstream.
+
+The ncm_set_alt function was holding a mutex to protect against races
+with configfs, which invokes the might-sleep function inside an atomic
+context.
+
+Remove the struct net_device pointer from the f_ncm_opts structure to
+eliminate the contention. The connection state is now managed by a new
+boolean flag to preserve the use-after-free fix from
+commit 6334b8e4553c ("usb: gadget: f_ncm: Fix UAF ncm object at re-bind
+after usb ep transport error").
+
+BUG: sleeping function called from invalid context
+Call Trace:
+ dump_stack_lvl+0x83/0xc0
+ dump_stack+0x14/0x16
+ __might_resched+0x389/0x4c0
+ __might_sleep+0x8e/0x100
+ ...
+ __mutex_lock+0x6f/0x1740
+ ...
+ ncm_set_alt+0x209/0xa40
+ set_config+0x6b6/0xb40
+ composite_setup+0x734/0x2b40
+ ...
+
+Fixes: 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle with bind/unbind")
+Cc: stable@kernel.org
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://patch.msgid.link/20260221-legacy-ncm-v2-2-dfb891d76507@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_ncm.c            |   29 ++++++++++---------------
+ drivers/usb/gadget/function/u_ether_configfs.h |   11 ---------
+ drivers/usb/gadget/function/u_ncm.h            |    1 
+ 3 files changed, 13 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_ncm.c
++++ b/drivers/usb/gadget/function/f_ncm.c
+@@ -58,6 +58,7 @@ struct f_ncm {
+       u8                              notify_state;
+       atomic_t                        notify_count;
+       bool                            is_open;
++      bool                            is_connected;
+       const struct ndp_parser_opts    *parser_opts;
+       bool                            is_crc;
+@@ -864,7 +865,6 @@ invalid:
+ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+ {
+       struct f_ncm            *ncm = func_to_ncm(f);
+-      struct f_ncm_opts       *opts = func_to_ncm_opts(f);
+       struct usb_composite_dev *cdev = f->config->cdev;
+       /* Control interface has only altsetting 0 */
+@@ -887,13 +887,12 @@ static int ncm_set_alt(struct usb_functi
+               if (alt > 1)
+                       goto fail;
+-              scoped_guard(mutex, &opts->lock)
+-                      if (opts->net) {
+-                              DBG(cdev, "reset ncm\n");
+-                              opts->net = NULL;
+-                              gether_disconnect(&ncm->port);
+-                              ncm_reset_values(ncm);
+-                      }
++              if (ncm->is_connected) {
++                      DBG(cdev, "reset ncm\n");
++                      ncm->is_connected = false;
++                      gether_disconnect(&ncm->port);
++                      ncm_reset_values(ncm);
++              }
+               /*
+                * CDC Network only sends data in non-default altsettings.
+@@ -926,8 +925,7 @@ static int ncm_set_alt(struct usb_functi
+                       net = gether_connect(&ncm->port);
+                       if (IS_ERR(net))
+                               return PTR_ERR(net);
+-                      scoped_guard(mutex, &opts->lock)
+-                              opts->net = net;
++                      ncm->is_connected = true;
+               }
+               spin_lock(&ncm->lock);
+@@ -1374,16 +1372,14 @@ err:
+ static void ncm_disable(struct usb_function *f)
+ {
+       struct f_ncm            *ncm = func_to_ncm(f);
+-      struct f_ncm_opts       *opts = func_to_ncm_opts(f);
+       struct usb_composite_dev *cdev = f->config->cdev;
+       DBG(cdev, "ncm deactivated\n");
+-      scoped_guard(mutex, &opts->lock)
+-              if (opts->net) {
+-                      opts->net = NULL;
+-                      gether_disconnect(&ncm->port);
+-              }
++      if (ncm->is_connected) {
++              ncm->is_connected = false;
++              gether_disconnect(&ncm->port);
++      }
+       if (ncm->notify->enabled) {
+               usb_ep_disable(ncm->notify);
+@@ -1687,7 +1683,6 @@ static struct usb_function_instance *ncm
+       if (!opts)
+               return ERR_PTR(-ENOMEM);
+-      opts->net = NULL;
+       opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id;
+       gether_setup_opts_default(&opts->net_opts, "usb");
+--- a/drivers/usb/gadget/function/u_ether_configfs.h
++++ b/drivers/usb/gadget/function/u_ether_configfs.h
+@@ -326,18 +326,9 @@ out:                                                                      \
+                                             char *page)                       \
+       {                                                                       \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);          \
+-              const char *name;                                               \
+                                                                               \
+               guard(mutex)(&opts->lock);                                      \
+-              rtnl_lock();                                                    \
+-              if (opts->net_opts.ifname_set)                                  \
+-                      name = opts->net_opts.name;                             \
+-              else if (opts->net)                                             \
+-                      name = netdev_name(opts->net);                          \
+-              else                                                            \
+-                      name = "(inactive net_device)";                         \
+-              rtnl_unlock();                                                  \
+-              return sysfs_emit(page, "%s\n", name);                          \
++              return sysfs_emit(page, "%s\n", opts->net_opts.name);           \
+       }                                                                       \
+                                                                               \
+       static ssize_t _f_##_opts_ifname_store(struct config_item *item,        \
+--- a/drivers/usb/gadget/function/u_ncm.h
++++ b/drivers/usb/gadget/function/u_ncm.h
+@@ -19,7 +19,6 @@
+ struct f_ncm_opts {
+       struct usb_function_instance    func_inst;
+-      struct net_device               *net;
+       struct gether_opts              net_opts;
+       struct config_group             *ncm_interf_group;
diff --git a/queue-6.19/usb-gadget-f_tcm-fix-null-pointer-dereferences-in-nexus-handling.patch b/queue-6.19/usb-gadget-f_tcm-fix-null-pointer-dereferences-in-nexus-handling.patch
new file mode 100644 (file)
index 0000000..8bc8433
--- /dev/null
@@ -0,0 +1,70 @@
+From b9fde507355342a2d64225d582dc8b98ff5ecb19 Mon Sep 17 00:00:00 2001
+From: Jiasheng Jiang <jiashengjiangcool@gmail.com>
+Date: Thu, 19 Feb 2026 02:38:34 +0000
+Subject: usb: gadget: f_tcm: Fix NULL pointer dereferences in nexus handling
+
+From: Jiasheng Jiang <jiashengjiangcool@gmail.com>
+
+commit b9fde507355342a2d64225d582dc8b98ff5ecb19 upstream.
+
+The `tpg->tpg_nexus` pointer in the USB Target driver is dynamically
+managed and tied to userspace configuration via ConfigFS. It can be
+NULL if the USB host sends requests before the nexus is fully
+established or immediately after it is dropped.
+
+Currently, functions like `bot_submit_command()` and the data
+transfer paths retrieve `tv_nexus = tpg->tpg_nexus` and immediately
+dereference `tv_nexus->tvn_se_sess` without any validation. If a
+malicious or misconfigured USB host sends a BOT (Bulk-Only Transport)
+command during this race window, it triggers a NULL pointer
+dereference, leading to a kernel panic (local DoS).
+
+This exposes an inconsistent API usage within the module, as peer
+functions like `usbg_submit_command()` and `bot_send_bad_response()`
+correctly implement a NULL check for `tv_nexus` before proceeding.
+
+Fix this by bringing consistency to the nexus handling. Add the
+missing `if (!tv_nexus)` checks to the vulnerable BOT command and
+request processing paths, aborting the command gracefully with an
+error instead of crashing the system.
+
+Fixes: c52661d60f63 ("usb-gadget: Initial merge of target module for UASP + BOT")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
+Reviewed-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://patch.msgid.link/20260219023834.17976-1-jiashengjiangcool@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_tcm.c |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/usb/gadget/function/f_tcm.c
++++ b/drivers/usb/gadget/function/f_tcm.c
+@@ -1222,6 +1222,13 @@ static void usbg_submit_cmd(struct usbg_
+       se_cmd = &cmd->se_cmd;
+       tpg = cmd->fu->tpg;
+       tv_nexus = tpg->tpg_nexus;
++      if (!tv_nexus) {
++              struct usb_gadget *gadget = fuas_to_gadget(cmd->fu);
++
++              dev_err(&gadget->dev, "Missing nexus, ignoring command\n");
++              return;
++      }
++
+       dir = get_cmd_dir(cmd->cmd_buf);
+       if (dir < 0)
+               goto out;
+@@ -1482,6 +1489,13 @@ static void bot_cmd_work(struct work_str
+       se_cmd = &cmd->se_cmd;
+       tpg = cmd->fu->tpg;
+       tv_nexus = tpg->tpg_nexus;
++      if (!tv_nexus) {
++              struct usb_gadget *gadget = fuas_to_gadget(cmd->fu);
++
++              dev_err(&gadget->dev, "Missing nexus, ignoring command\n");
++              return;
++      }
++
+       dir = get_cmd_dir(cmd->cmd_buf);
+       if (dir < 0)
+               goto out;
diff --git a/queue-6.19/usb-gadget-uvc-fix-interval_duration-calculation.patch b/queue-6.19/usb-gadget-uvc-fix-interval_duration-calculation.patch
new file mode 100644 (file)
index 0000000..27c4dd4
--- /dev/null
@@ -0,0 +1,36 @@
+From 56135c0c60b07729401af9d329fa9c0eded845a6 Mon Sep 17 00:00:00 2001
+From: Junzhong Pan <panjunzhong@linux.spacemit.com>
+Date: Fri, 6 Mar 2026 11:30:09 +0800
+Subject: usb: gadget: uvc: fix interval_duration calculation
+
+From: Junzhong Pan <panjunzhong@linux.spacemit.com>
+
+commit 56135c0c60b07729401af9d329fa9c0eded845a6 upstream.
+
+To correctly convert bInterval as interval_duration:
+  interval_duration = 2^(bInterval-1) * frame_interval
+
+Current code uses a wrong left shift operand, computing 2^bInterval
+instead of 2^(bInterval-1).
+
+Fixes: 010dc57cb516 ("usb: gadget: uvc: fix interval_duration calculation")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Junzhong Pan <panjunzhong@linux.spacemit.com>
+Reviewed-by: Xu Yang <xu.yang_2@nxp.com>
+Link: https://patch.msgid.link/20260306-fix-uvc-interval-v1-1-9a2df6859859@linux.spacemit.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/uvc_video.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/uvc_video.c
++++ b/drivers/usb/gadget/function/uvc_video.c
+@@ -513,7 +513,7 @@ uvc_video_prep_requests(struct uvc_video
+               return;
+       }
+-      interval_duration = 2 << (video->ep->desc->bInterval - 1);
++      interval_duration = 1 << (video->ep->desc->bInterval - 1);
+       if (cdev->gadget->speed < USB_SPEED_HIGH)
+               interval_duration *= 10000;
+       else
diff --git a/queue-6.19/usb-image-mdc800-kill-download-urb-on-timeout.patch b/queue-6.19/usb-image-mdc800-kill-download-urb-on-timeout.patch
new file mode 100644 (file)
index 0000000..9fe27bc
--- /dev/null
@@ -0,0 +1,49 @@
+From 1be3b77de4eb89af8ae2fd6610546be778e25589 Mon Sep 17 00:00:00 2001
+From: Ziyi Guo <n7l8m4@u.northwestern.edu>
+Date: Mon, 9 Feb 2026 15:19:37 +0000
+Subject: usb: image: mdc800: kill download URB on timeout
+
+From: Ziyi Guo <n7l8m4@u.northwestern.edu>
+
+commit 1be3b77de4eb89af8ae2fd6610546be778e25589 upstream.
+
+mdc800_device_read() submits download_urb and waits for completion.
+If the timeout fires and the device has not responded, the function
+returns without killing the URB, leaving it active.
+
+A subsequent read() resubmits the same URB while it is still
+in-flight, triggering the WARN in usb_submit_urb():
+
+  "URB submitted while active"
+
+Check the return value of wait_event_timeout() and kill the URB if
+it indicates timeout, ensuring the URB is complete before its status
+is inspected or the URB is resubmitted.
+
+Similar to
+- commit 372c93131998 ("USB: yurex: fix control-URB timeout handling")
+- commit b98d5000c505 ("media: rc: iguanair: handle timeouts")
+
+Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
+Cc: stable <stable@kernel.org>
+Link: https://patch.msgid.link/20260209151937.2247202-1-n7l8m4@u.northwestern.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/image/mdc800.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/image/mdc800.c
++++ b/drivers/usb/image/mdc800.c
+@@ -730,9 +730,11 @@ static ssize_t mdc800_device_read (struc
+                                       mutex_unlock(&mdc800->io_lock);
+                                       return len-left;
+                               }
+-                              wait_event_timeout(mdc800->download_wait,
++                              retval = wait_event_timeout(mdc800->download_wait,
+                                    mdc800->downloaded,
+                                    msecs_to_jiffies(TO_DOWNLOAD_GET_READY));
++                              if (!retval)
++                                      usb_kill_urb(mdc800->download_urb);
+                               mdc800->downloaded = 0;
+                               if (mdc800->download_urb->status != 0)
+                               {
diff --git a/queue-6.19/usb-legacy-ncm-fix-npe-in-gncm_bind.patch b/queue-6.19/usb-legacy-ncm-fix-npe-in-gncm_bind.patch
new file mode 100644 (file)
index 0000000..45c2643
--- /dev/null
@@ -0,0 +1,70 @@
+From fde0634ad9856b3943a2d1a8cc8de174a63ac840 Mon Sep 17 00:00:00 2001
+From: Kuen-Han Tsai <khtsai@google.com>
+Date: Sat, 21 Feb 2026 22:48:15 +0800
+Subject: usb: legacy: ncm: Fix NPE in gncm_bind
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+commit fde0634ad9856b3943a2d1a8cc8de174a63ac840 upstream.
+
+Commit 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle
+with bind/unbind") deferred the allocation of the net_device. This
+change leads to a NULL pointer dereference in the legacy NCM driver as
+it attempts to access the net_device before it's fully instantiated.
+
+Store the provided qmult, host_addr, and dev_addr into the struct
+ncm_opts->net_opts during gncm_bind(). These values will be properly
+applied to the net_device when it is allocated and configured later in
+the binding process by the NCM function driver.
+
+Fixes: 56a512a9b410 ("usb: gadget: f_ncm: align net_device lifecycle with bind/unbind")
+Cc: stable@kernel.org
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202602181727.fd76c561-lkp@intel.com
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://patch.msgid.link/20260221-legacy-ncm-v2-1-dfb891d76507@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/legacy/ncm.c |   13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/gadget/legacy/ncm.c
++++ b/drivers/usb/gadget/legacy/ncm.c
+@@ -15,8 +15,10 @@
+ /* #define DEBUG */
+ /* #define VERBOSE_DEBUG */
++#include <linux/hex.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/string.h>
+ #include <linux/usb/composite.h>
+ #include "u_ether.h"
+@@ -129,6 +131,7 @@ static int gncm_bind(struct usb_composit
+       struct usb_gadget       *gadget = cdev->gadget;
+       struct f_ncm_opts       *ncm_opts;
+       int                     status;
++      u8                      mac[ETH_ALEN];
+       f_ncm_inst = usb_get_function_instance("ncm");
+       if (IS_ERR(f_ncm_inst))
+@@ -136,11 +139,15 @@ static int gncm_bind(struct usb_composit
+       ncm_opts = container_of(f_ncm_inst, struct f_ncm_opts, func_inst);
+-      gether_set_qmult(ncm_opts->net, qmult);
+-      if (!gether_set_host_addr(ncm_opts->net, host_addr))
++      ncm_opts->net_opts.qmult = qmult;
++      if (host_addr && mac_pton(host_addr, mac)) {
++              memcpy(&ncm_opts->net_opts.host_mac, mac, ETH_ALEN);
+               pr_info("using host ethernet address: %s", host_addr);
+-      if (!gether_set_dev_addr(ncm_opts->net, dev_addr))
++      }
++      if (dev_addr && mac_pton(dev_addr, mac)) {
++              memcpy(&ncm_opts->net_opts.dev_mac, mac, ETH_ALEN);
+               pr_info("using self ethernet address: %s", dev_addr);
++      }
+       /* Allocate string descriptor numbers ... note that string
+        * contents can be overridden by the composite_dev glue.
diff --git a/queue-6.19/usb-mdc800-handle-signal-and-read-racing.patch b/queue-6.19/usb-mdc800-handle-signal-and-read-racing.patch
new file mode 100644 (file)
index 0000000..2c2bcd4
--- /dev/null
@@ -0,0 +1,32 @@
+From 2d6d260e9a3576256fe9ef6d1f7930c9ec348723 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Mon, 9 Feb 2026 15:20:48 +0100
+Subject: usb: mdc800: handle signal and read racing
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit 2d6d260e9a3576256fe9ef6d1f7930c9ec348723 upstream.
+
+If a signal arrives after a read has partially completed,
+we need to return the number of bytes read. -EINTR is correct
+only if that number is zero.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Cc: stable <stable@kernel.org>
+Link: https://patch.msgid.link/20260209142048.1503791-1-oneukum@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/image/mdc800.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/image/mdc800.c
++++ b/drivers/usb/image/mdc800.c
+@@ -707,7 +707,7 @@ static ssize_t mdc800_device_read (struc
+               if (signal_pending (current)) 
+               {
+                       mutex_unlock(&mdc800->io_lock);
+-                      return -EINTR;
++                      return len == left ? -EINTR : len-left;
+               }
+               sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left;
diff --git a/queue-6.19/usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch b/queue-6.19/usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch
new file mode 100644 (file)
index 0000000..8d99815
--- /dev/null
@@ -0,0 +1,33 @@
+From 45dba8011efac11a2f360383221b541f5ea53ce5 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 23 Feb 2026 13:19:43 +0100
+Subject: usb: misc: uss720: properly clean up reference in uss720_probe()
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 45dba8011efac11a2f360383221b541f5ea53ce5 upstream.
+
+If get_1284_register() fails, the usb device reference count is
+incorrect and needs to be properly dropped before returning.  That will
+happen when the kref is dropped in the call to destroy_priv(), so jump
+to that error path instead of returning directly.
+
+Cc: stable <stable@kernel.org>
+Assisted-by: gkh_clanker_2000
+Link: https://patch.msgid.link/2026022342-smokiness-stove-d792@gregkh
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/uss720.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/misc/uss720.c
++++ b/drivers/usb/misc/uss720.c
+@@ -736,7 +736,7 @@ static int uss720_probe(struct usb_inter
+       ret = get_1284_register(pp, 0, &reg, GFP_KERNEL);
+       dev_dbg(&intf->dev, "reg: %7ph\n", priv->reg);
+       if (ret < 0)
+-              return ret;
++              goto probe_abort;
+       ret = usb_find_last_int_in_endpoint(interface, &epd);
+       if (!ret) {
diff --git a/queue-6.19/usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch b/queue-6.19/usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch
new file mode 100644 (file)
index 0000000..fd18a2c
--- /dev/null
@@ -0,0 +1,46 @@
+From 3cbc242b88c607f55da3d0d0d336b49bf1e20412 Mon Sep 17 00:00:00 2001
+From: Fan Wu <fanwu01@zju.edu.cn>
+Date: Tue, 3 Mar 2026 07:33:44 +0000
+Subject: usb: renesas_usbhs: fix use-after-free in ISR during device removal
+
+From: Fan Wu <fanwu01@zju.edu.cn>
+
+commit 3cbc242b88c607f55da3d0d0d336b49bf1e20412 upstream.
+
+In usbhs_remove(), the driver frees resources (including the pipe array)
+while the interrupt handler (usbhs_interrupt) is still registered. If an
+interrupt fires after usbhs_pipe_remove() but before the driver is fully
+unbound, the ISR may access freed memory, causing a use-after-free.
+
+Fix this by calling devm_free_irq() before freeing resources. This ensures
+the interrupt handler is both disabled and synchronized (waits for any
+running ISR to complete) before usbhs_pipe_remove() is called.
+
+Fixes: f1407d5c6624 ("usb: renesas_usbhs: Add Renesas USBHS common code")
+Cc: stable <stable@kernel.org>
+Suggested-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
+Link: https://patch.msgid.link/20260303073344.34577-1-fanwu01@zju.edu.cn
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/renesas_usbhs/common.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/usb/renesas_usbhs/common.c
++++ b/drivers/usb/renesas_usbhs/common.c
+@@ -815,6 +815,15 @@ static void usbhs_remove(struct platform
+       usbhs_platform_call(priv, hardware_exit, pdev);
+       reset_control_assert(priv->rsts);
++
++      /*
++       * Explicitly free the IRQ to ensure the interrupt handler is
++       * disabled and synchronized before freeing resources.
++       * devm_free_irq() calls free_irq() which waits for any running
++       * ISR to complete, preventing UAF.
++       */
++      devm_free_irq(&pdev->dev, priv->irq, priv);
++
+       usbhs_mod_remove(priv);
+       usbhs_fifo_remove(priv);
+       usbhs_pipe_remove(priv);
diff --git a/queue-6.19/usb-roles-get-usb-role-switch-from-parent-only-for-usb-b-connector.patch b/queue-6.19/usb-roles-get-usb-role-switch-from-parent-only-for-usb-b-connector.patch
new file mode 100644 (file)
index 0000000..f4caae9
--- /dev/null
@@ -0,0 +1,54 @@
+From 8345b1539faa49fcf9c9439c3cbd97dac6eca171 Mon Sep 17 00:00:00 2001
+From: Xu Yang <xu.yang_2@nxp.com>
+Date: Mon, 9 Mar 2026 15:43:13 +0800
+Subject: usb: roles: get usb role switch from parent only for usb-b-connector
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+commit 8345b1539faa49fcf9c9439c3cbd97dac6eca171 upstream.
+
+usb_role_switch_is_parent() was walking up to the parent node and checking
+for the "usb-role-switch" property regardless of the type of the passed
+fwnode. This could cause unrelated device nodes to be probed as potential
+role switch parent, leading to spurious matches and "-EPROBE_DEFER" being
+returned infinitely.
+
+Till now only Type-B connector node will have a parent node which may
+present "usb-role-switch" property and register the role switch device.
+For Type-C connector node, its parent node will always be a Type-C chip
+device which will never register the role switch device. However, it may
+still present a non-boolean "usb-role-switch = <&usb_controller>" property
+for historical compatibility.
+
+So restrict the helper to only operate on Type-B connector when attempting
+to get the role switch from parent node.
+
+Fixes: 6fadd72943b8 ("usb: roles: get usb-role-switch from parent")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Tested-by: Arnaud Ferraris <arnaud.ferraris@collabora.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://patch.msgid.link/20260309074313.2809867-3-xu.yang_2@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/roles/class.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/roles/class.c
++++ b/drivers/usb/roles/class.c
+@@ -139,9 +139,14 @@ static void *usb_role_switch_match(const
+ static struct usb_role_switch *
+ usb_role_switch_is_parent(struct fwnode_handle *fwnode)
+ {
+-      struct fwnode_handle *parent = fwnode_get_parent(fwnode);
++      struct fwnode_handle *parent;
+       struct device *dev;
++      if (!fwnode_device_is_compatible(fwnode, "usb-b-connector"))
++              return NULL;
++
++      parent = fwnode_get_parent(fwnode);
++
+       if (!fwnode_property_present(parent, "usb-role-switch")) {
+               fwnode_handle_put(parent);
+               return NULL;
diff --git a/queue-6.19/usb-typec-altmode-displayport-set-displayport-signaling-rate-in-configure-message.patch b/queue-6.19/usb-typec-altmode-displayport-set-displayport-signaling-rate-in-configure-message.patch
new file mode 100644 (file)
index 0000000..93ecb08
--- /dev/null
@@ -0,0 +1,48 @@
+From e8557acfa079a54b59a21f447c82a31aec7717df Mon Sep 17 00:00:00 2001
+From: RD Babiera <rdbabiera@google.com>
+Date: Tue, 10 Mar 2026 20:41:05 +0000
+Subject: usb: typec: altmode/displayport: set displayport signaling rate in configure message
+
+From: RD Babiera <rdbabiera@google.com>
+
+commit e8557acfa079a54b59a21f447c82a31aec7717df upstream.
+
+dp_altmode_configure sets the signaling rate to the current
+configuration's rate and then shifts the value to the Select
+Configuration bitfield. On the initial configuration, dp->data.conf
+is 0 to begin with, so the signaling rate field is never set, which
+leads to some DisplayPort Alt Mode partners sending NAK to the
+Configure message.
+
+Set the signaling rate to the capabilities supported by both the
+port and the port partner. If the cable supports DisplayPort Alt Mode,
+then include its capabilities as well.
+
+Fixes: a17fae8fc38e ("usb: typec: Add Displayport Alternate Mode 2.1 Support")
+Cc: stable <stable@kernel.org>
+Signed-off-by: RD Babiera <rdbabiera@google.com>
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://patch.msgid.link/20260310204106.3939862-2-rdbabiera@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/altmodes/displayport.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/typec/altmodes/displayport.c
++++ b/drivers/usb/typec/altmodes/displayport.c
+@@ -100,9 +100,14 @@ static int dp_altmode_configure(struct d
+ {
+       u8 pin_assign = 0;
+       u32 conf;
++      u32 signal;
+       /* DP Signalling */
+-      conf = (dp->data.conf & DP_CONF_SIGNALLING_MASK) >> DP_CONF_SIGNALLING_SHIFT;
++      signal = DP_CAP_DP_SIGNALLING(dp->port->vdo) & DP_CAP_DP_SIGNALLING(dp->alt->vdo);
++      if (dp->plug_prime)
++              signal &= DP_CAP_DP_SIGNALLING(dp->plug_prime->vdo);
++
++      conf = signal << DP_CONF_SIGNALLING_SHIFT;
+       switch (con) {
+       case DP_STATUS_CON_DISABLED:
diff --git a/queue-6.19/usb-usbcore-introduce-usb_bulk_msg_killable.patch b/queue-6.19/usb-usbcore-introduce-usb_bulk_msg_killable.patch
new file mode 100644 (file)
index 0000000..370c584
--- /dev/null
@@ -0,0 +1,166 @@
+From 416909962e7cdf29fd01ac523c953f37708df93d Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Tue, 17 Feb 2026 22:07:47 -0500
+Subject: USB: usbcore: Introduce usb_bulk_msg_killable()
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 416909962e7cdf29fd01ac523c953f37708df93d upstream.
+
+The synchronous message API in usbcore (usb_control_msg(),
+usb_bulk_msg(), and so on) uses uninterruptible waits.  However,
+drivers may call these routines in the context of a user thread, which
+means it ought to be possible to at least kill them.
+
+For this reason, introduce a new usb_bulk_msg_killable() function
+which behaves the same as usb_bulk_msg() except for using
+wait_for_completion_killable_timeout() instead of
+wait_for_completion_timeout().  The same can be done later for
+usb_control_msg() later on, if it turns out to be needed.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Suggested-by: Oliver Neukum <oneukum@suse.com>
+Link: https://lore.kernel.org/linux-usb/3acfe838-6334-4f6d-be7c-4bb01704b33d@rowland.harvard.edu/
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+CC: stable@vger.kernel.org
+Link: https://patch.msgid.link/248628b4-cc83-4e81-a620-3ce4e0376d41@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/message.c |   79 +++++++++++++++++++++++++++++++++++++++------
+ include/linux/usb.h        |    5 +-
+ 2 files changed, 72 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -42,16 +42,17 @@ static void usb_api_blocking_completion(
+ /*
+- * Starts urb and waits for completion or timeout. Note that this call
+- * is NOT interruptible. Many device driver i/o requests should be
+- * interruptible and therefore these drivers should implement their
+- * own interruptible routines.
++ * Starts urb and waits for completion or timeout.
++ * Whether or not the wait is killable depends on the flag passed in.
++ * For example, compare usb_bulk_msg() and usb_bulk_msg_killable().
+  */
+-static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
++static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length,
++              bool killable)
+ {
+       struct api_context ctx;
+       unsigned long expire;
+       int retval;
++      long rc;
+       init_completion(&ctx.done);
+       urb->context = &ctx;
+@@ -61,12 +62,21 @@ static int usb_start_wait_urb(struct urb
+               goto out;
+       expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
+-      if (!wait_for_completion_timeout(&ctx.done, expire)) {
++      if (killable)
++              rc = wait_for_completion_killable_timeout(&ctx.done, expire);
++      else
++              rc = wait_for_completion_timeout(&ctx.done, expire);
++      if (rc <= 0) {
+               usb_kill_urb(urb);
+-              retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
++              if (ctx.status != -ENOENT)
++                      retval = ctx.status;
++              else if (rc == 0)
++                      retval = -ETIMEDOUT;
++              else
++                      retval = rc;
+               dev_dbg(&urb->dev->dev,
+-                      "%s timed out on ep%d%s len=%u/%u\n",
++                      "%s timed out or killed on ep%d%s len=%u/%u\n",
+                       current->comm,
+                       usb_endpoint_num(&urb->ep->desc),
+                       usb_urb_dir_in(urb) ? "in" : "out",
+@@ -100,7 +110,7 @@ static int usb_internal_control_msg(stru
+       usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
+                            len, usb_api_blocking_completion, NULL);
+-      retv = usb_start_wait_urb(urb, timeout, &length);
++      retv = usb_start_wait_urb(urb, timeout, &length, false);
+       if (retv < 0)
+               return retv;
+       else
+@@ -385,10 +395,59 @@ int usb_bulk_msg(struct usb_device *usb_
+               usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+                               usb_api_blocking_completion, NULL);
+-      return usb_start_wait_urb(urb, timeout, actual_length);
++      return usb_start_wait_urb(urb, timeout, actual_length, false);
+ }
+ EXPORT_SYMBOL_GPL(usb_bulk_msg);
++/**
++ * usb_bulk_msg_killable - Builds a bulk urb, sends it off and waits for completion in a killable state
++ * @usb_dev: pointer to the usb device to send the message to
++ * @pipe: endpoint "pipe" to send the message to
++ * @data: pointer to the data to send
++ * @len: length in bytes of the data to send
++ * @actual_length: pointer to a location to put the actual length transferred
++ *    in bytes
++ * @timeout: time in msecs to wait for the message to complete before
++ *    timing out (if 0 the wait is forever)
++ *
++ * Context: task context, might sleep.
++ *
++ * This function is just like usb_blk_msg() except that it waits in a
++ * killable state.
++ *
++ * Return:
++ * If successful, 0. Otherwise a negative error number. The number of actual
++ * bytes transferred will be stored in the @actual_length parameter.
++ *
++ */
++int usb_bulk_msg_killable(struct usb_device *usb_dev, unsigned int pipe,
++               void *data, int len, int *actual_length, int timeout)
++{
++      struct urb *urb;
++      struct usb_host_endpoint *ep;
++
++      ep = usb_pipe_endpoint(usb_dev, pipe);
++      if (!ep || len < 0)
++              return -EINVAL;
++
++      urb = usb_alloc_urb(0, GFP_KERNEL);
++      if (!urb)
++              return -ENOMEM;
++
++      if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
++                      USB_ENDPOINT_XFER_INT) {
++              pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
++              usb_fill_int_urb(urb, usb_dev, pipe, data, len,
++                              usb_api_blocking_completion, NULL,
++                              ep->desc.bInterval);
++      } else
++              usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
++                              usb_api_blocking_completion, NULL);
++
++      return usb_start_wait_urb(urb, timeout, actual_length, true);
++}
++EXPORT_SYMBOL_GPL(usb_bulk_msg_killable);
++
+ /*-------------------------------------------------------------------*/
+ static void sg_clean(struct usb_sg_request *io)
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1869,8 +1869,9 @@ extern int usb_control_msg(struct usb_de
+ extern int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
+       void *data, int len, int *actual_length, int timeout);
+ extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+-      void *data, int len, int *actual_length,
+-      int timeout);
++      void *data, int len, int *actual_length, int timeout);
++extern int usb_bulk_msg_killable(struct usb_device *usb_dev, unsigned int pipe,
++      void *data, int len, int *actual_length, int timeout);
+ /* wrappers around usb_control_msg() for the most common standard requests */
+ int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request,
diff --git a/queue-6.19/usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch b/queue-6.19/usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch
new file mode 100644 (file)
index 0000000..a113a1b
--- /dev/null
@@ -0,0 +1,57 @@
+From 7784caa413a89487dd14dd5c41db8753483b2acb Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Tue, 17 Feb 2026 22:09:22 -0500
+Subject: USB: usbtmc: Use usb_bulk_msg_killable() with user-specified timeouts
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 7784caa413a89487dd14dd5c41db8753483b2acb upstream.
+
+The usbtmc driver accepts timeout values specified by the user in an
+ioctl command, and uses these timeouts for some usb_bulk_msg() calls.
+Since the user can specify arbitrarily long timeouts and
+usb_bulk_msg() uses unkillable waits, call usb_bulk_msg_killable()
+instead to avoid the possibility of the user hanging a kernel thread
+indefinitely.
+
+Reported-by: syzbot+25ba18e2c5040447585d@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-usb/8e1c7ac5-e076-44b0-84b8-1b34b20f0ae1@suse.com/T/#t
+Tested-by: syzbot+25ba18e2c5040447585d@syzkaller.appspotmail.com
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Fixes: 048c6d88a021 ("usb: usbtmc: Add ioctls to set/get usb timeout")
+CC: stable@vger.kernel.org
+Link: https://patch.msgid.link/81c6fc24-0607-40f1-8c20-5270dab2fad5@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/class/usbtmc.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/class/usbtmc.c
++++ b/drivers/usb/class/usbtmc.c
+@@ -727,7 +727,7 @@ static int usbtmc488_ioctl_trigger(struc
+       buffer[1] = data->bTag;
+       buffer[2] = ~data->bTag;
+-      retval = usb_bulk_msg(data->usb_dev,
++      retval = usb_bulk_msg_killable(data->usb_dev,
+                             usb_sndbulkpipe(data->usb_dev,
+                                             data->bulk_out),
+                             buffer, USBTMC_HEADER_SIZE,
+@@ -1347,7 +1347,7 @@ static int send_request_dev_dep_msg_in(s
+       buffer[11] = 0; /* Reserved */
+       /* Send bulk URB */
+-      retval = usb_bulk_msg(data->usb_dev,
++      retval = usb_bulk_msg_killable(data->usb_dev,
+                             usb_sndbulkpipe(data->usb_dev,
+                                             data->bulk_out),
+                             buffer, USBTMC_HEADER_SIZE,
+@@ -1419,7 +1419,7 @@ static ssize_t usbtmc_read(struct file *
+       actual = 0;
+       /* Send bulk URB */
+-      retval = usb_bulk_msg(data->usb_dev,
++      retval = usb_bulk_msg_killable(data->usb_dev,
+                             usb_rcvbulkpipe(data->usb_dev,
+                                             data->bulk_in),
+                             buffer, bufsize, &actual,
diff --git a/queue-6.19/usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch b/queue-6.19/usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch
new file mode 100644 (file)
index 0000000..5ea2d31
--- /dev/null
@@ -0,0 +1,66 @@
+From c1c8550e70401159184130a1afc6261db01fc0ce Mon Sep 17 00:00:00 2001
+From: Zilin Guan <zilin@seu.edu.cn>
+Date: Thu, 5 Mar 2026 00:36:37 +0200
+Subject: usb: xhci: Fix memory leak in xhci_disable_slot()
+
+From: Zilin Guan <zilin@seu.edu.cn>
+
+commit c1c8550e70401159184130a1afc6261db01fc0ce upstream.
+
+xhci_alloc_command() allocates a command structure and, when the
+second argument is true, also allocates a completion structure.
+Currently, the error handling path in xhci_disable_slot() only frees
+the command structure using kfree(), causing the completion structure
+to leak.
+
+Use xhci_free_command() instead of kfree(). xhci_free_command() correctly
+frees both the command structure and the associated completion structure.
+Since the command structure is allocated with zero-initialization,
+command->in_ctx is NULL and will not be erroneously freed by
+xhci_free_command().
+
+This bug was found using an experimental static analysis tool we are
+developing. The tool is based on the LLVM framework and is specifically
+designed to detect memory management issues. It is currently under
+active development and not yet publicly available, but we plan to
+open-source it after our research is published.
+
+The bug was originally detected on v6.13-rc1 using our static analysis
+tool, and we have verified that the issue persists in the latest mainline
+kernel.
+
+We performed build testing on x86_64 with allyesconfig using GCC=11.4.0.
+Since triggering these error paths in xhci_disable_slot() requires specific
+hardware conditions or abnormal state, we were unable to construct a test
+case to reliably trigger these specific error paths at runtime.
+
+Fixes: 7faac1953ed1 ("xhci: avoid race between disable slot command and host runtime suspend")
+CC: stable@vger.kernel.org
+Signed-off-by: Zilin Guan <zilin@seu.edu.cn>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://patch.msgid.link/20260304223639.3882398-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -4146,7 +4146,7 @@ int xhci_disable_slot(struct xhci_hcd *x
+       if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) ||
+                       (xhci->xhc_state & XHCI_STATE_HALTED)) {
+               spin_unlock_irqrestore(&xhci->lock, flags);
+-              kfree(command);
++              xhci_free_command(xhci, command);
+               return -ENODEV;
+       }
+@@ -4154,7 +4154,7 @@ int xhci_disable_slot(struct xhci_hcd *x
+                               slot_id);
+       if (ret) {
+               spin_unlock_irqrestore(&xhci->lock, flags);
+-              kfree(command);
++              xhci_free_command(xhci, command);
+               return ret;
+       }
+       xhci_ring_cmd_db(xhci);
diff --git a/queue-6.19/usb-xhci-prevent-interrupt-storm-on-host-controller-error-hce.patch b/queue-6.19/usb-xhci-prevent-interrupt-storm-on-host-controller-error-hce.patch
new file mode 100644 (file)
index 0000000..b2aa05b
--- /dev/null
@@ -0,0 +1,48 @@
+From d6d5febd12452b7fd951fdd15c3ec262f01901a4 Mon Sep 17 00:00:00 2001
+From: Dayu Jiang <jiangdayu@xiaomi.com>
+Date: Thu, 5 Mar 2026 00:36:38 +0200
+Subject: usb: xhci: Prevent interrupt storm on host controller error (HCE)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dayu Jiang <jiangdayu@xiaomi.com>
+
+commit d6d5febd12452b7fd951fdd15c3ec262f01901a4 upstream.
+
+The xHCI controller reports a Host Controller Error (HCE) in UAS Storage
+Device plug/unplug scenarios on Android devices. HCE is checked in
+xhci_irq() function and causes an interrupt storm (since the interrupt
+isn’t cleared), leading to severe system-level faults.
+
+When the xHC controller reports HCE in the interrupt handler, the driver
+only logs a warning and assumes xHC activity will stop as stated in xHCI
+specification. An interrupt storm does however continue on some hosts
+even after HCE, and only ceases after manually disabling xHC interrupt
+and stopping the controller by calling xhci_halt().
+
+Add xhci_halt() to xhci_irq() function where STS_HCE status is checked,
+mirroring the existing error handling pattern used for STS_FATAL errors.
+
+This only fixes the interrupt storm. Proper HCE recovery requires resetting
+and re-initializing the xHC.
+
+CC: stable@vger.kernel.org
+Signed-off-by: Dayu Jiang <jiangdayu@xiaomi.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://patch.msgid.link/20260304223639.3882398-3-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-ring.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -3195,6 +3195,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd
+       if (status & STS_HCE) {
+               xhci_warn(xhci, "WARNING: Host Controller Error\n");
++              xhci_halt(xhci);
+               goto out;
+       }
diff --git a/queue-6.19/usb-yurex-fix-race-in-probe.patch b/queue-6.19/usb-yurex-fix-race-in-probe.patch
new file mode 100644 (file)
index 0000000..150a704
--- /dev/null
@@ -0,0 +1,41 @@
+From 7a875c09899ba0404844abfd8f0d54cdc481c151 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Mon, 9 Feb 2026 15:37:20 +0100
+Subject: usb: yurex: fix race in probe
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit 7a875c09899ba0404844abfd8f0d54cdc481c151 upstream.
+
+The bbu member of the descriptor must be set to the value
+standing for uninitialized values before the URB whose
+completion handler sets bbu is submitted. Otherwise there is
+a window during which probing can overwrite already retrieved
+data.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Link: https://patch.msgid.link/20260209143720.1507500-1-oneukum@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/yurex.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/misc/yurex.c
++++ b/drivers/usb/misc/yurex.c
+@@ -272,6 +272,7 @@ static int yurex_probe(struct usb_interf
+                        dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt,
+                        dev, 1);
+       dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++      dev->bbu = -1;
+       if (usb_submit_urb(dev->urb, GFP_KERNEL)) {
+               retval = -EIO;
+               dev_err(&interface->dev, "Could not submitting URB\n");
+@@ -280,7 +281,6 @@ static int yurex_probe(struct usb_interf
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+-      dev->bbu = -1;
+       /* we can register the device now, as it is ready */
+       retval = usb_register_dev(interface, &yurex_class);
diff --git a/queue-6.19/xhci-fix-null-pointer-dereference-when-reading-portli-debugfs-files.patch b/queue-6.19/xhci-fix-null-pointer-dereference-when-reading-portli-debugfs-files.patch
new file mode 100644 (file)
index 0000000..9f6139d
--- /dev/null
@@ -0,0 +1,62 @@
+From ae4ff9dead5efa2025eddfcdb29411432bf40a7c Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 5 Mar 2026 00:36:39 +0200
+Subject: xhci: Fix NULL pointer dereference when reading portli debugfs files
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit ae4ff9dead5efa2025eddfcdb29411432bf40a7c upstream.
+
+Michal reported and debgged a NULL pointer dereference bug in the
+recently added portli debugfs files
+
+Oops is caused when there are more port registers counted in
+xhci->max_ports than ports reported by Supported Protocol capabilities.
+This is possible if max_ports is more than maximum port number, or
+if there are gaps between ports of different speeds the 'Supported
+Protocol' capabilities.
+
+In such cases port->rhub will be NULL so we can't reach xhci behind it.
+Add an explicit NULL check for this case, and print portli in hex
+without dereferencing port->rhub.
+
+Reported-by: Michal Pecio <michal.pecio@gmail.com>
+Closes: https://lore.kernel.org/linux-usb/20260304103856.48b785fd.michal.pecio@gmail.com
+Fixes: 384c57ec7205 ("usb: xhci: Add debugfs support for xHCI Port Link Info (PORTLI) register.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://patch.msgid.link/20260304223639.3882398-4-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-debugfs.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c
+index 890fc5e892f1..ade178ab34a7 100644
+--- a/drivers/usb/host/xhci-debugfs.c
++++ b/drivers/usb/host/xhci-debugfs.c
+@@ -386,11 +386,19 @@ static const struct file_operations port_fops = {
+ static int xhci_portli_show(struct seq_file *s, void *unused)
+ {
+       struct xhci_port        *port = s->private;
+-      struct xhci_hcd         *xhci = hcd_to_xhci(port->rhub->hcd);
++      struct xhci_hcd         *xhci;
+       u32                     portli;
+       portli = readl(&port->port_reg->portli);
++      /* port without protocol capability isn't added to a roothub */
++      if (!port->rhub) {
++              seq_printf(s, "0x%08x\n", portli);
++              return 0;
++      }
++
++      xhci = hcd_to_xhci(port->rhub->hcd);
++
+       /* PORTLI fields are valid if port is a USB3 or eUSB2V2 port */
+       if (port->rhub == &xhci->usb3_rhub)
+               seq_printf(s, "0x%08x LEC=%u RLC=%u TLC=%u\n", portli,
+-- 
+2.53.0
+