--- /dev/null
+From f28beb69c51517aec7067dfb2074e7c751542384 Mon Sep 17 00:00:00 2001
+From: Benjamin Tissoires <bentiss@kernel.org>
+Date: Mon, 15 Dec 2025 12:57:21 +0100
+Subject: HID: usbhid: paper over wrong bNumDescriptor field
+
+From: Benjamin Tissoires <bentiss@kernel.org>
+
+commit f28beb69c51517aec7067dfb2074e7c751542384 upstream.
+
+Some faulty devices (ZWO EFWmini) have a wrong optional HID class
+descriptor count compared to the provided length.
+
+Given that we plainly ignore those optional descriptor, we can attempt
+to fix the provided number so we do not lock out those devices.
+
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Cc: Salvatore Bonaccorso <carnil@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/usbhid/hid-core.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -985,6 +985,7 @@ static int usbhid_parse(struct hid_devic
+ struct usb_device *dev = interface_to_usbdev (intf);
+ struct hid_descriptor *hdesc;
+ struct hid_class_descriptor *hcdesc;
++ __u8 fixed_opt_descriptors_size;
+ u32 quirks = 0;
+ unsigned int rsize = 0;
+ char *rdesc;
+@@ -1015,7 +1016,21 @@ static int usbhid_parse(struct hid_devic
+ (hdesc->bNumDescriptors - 1) * sizeof(*hcdesc)) {
+ dbg_hid("hid descriptor invalid, bLen=%hhu bNum=%hhu\n",
+ hdesc->bLength, hdesc->bNumDescriptors);
+- return -EINVAL;
++
++ /*
++ * Some devices may expose a wrong number of descriptors compared
++ * to the provided length.
++ * However, we ignore the optional hid class descriptors entirely
++ * so we can safely recompute the proper field.
++ */
++ if (hdesc->bLength >= sizeof(*hdesc)) {
++ fixed_opt_descriptors_size = hdesc->bLength - sizeof(*hdesc);
++
++ hid_warn(intf, "fixing wrong optional hid class descriptors count\n");
++ hdesc->bNumDescriptors = fixed_opt_descriptors_size / sizeof(*hcdesc) + 1;
++ } else {
++ return -EINVAL;
++ }
+ }
+
+ hid->version = le16_to_cpu(hdesc->bcdHID);
--- /dev/null
+From 4f8543b5f20f851cedbb23f8eade159871d84e2a Mon Sep 17 00:00:00 2001
+From: Yonghong Song <yonghong.song@linux.dev>
+Date: Mon, 13 Oct 2025 22:16:39 -0700
+Subject: selftests/bpf: Fix selftest verif_scale_strobemeta failure with llvm22
+
+From: Yonghong Song <yonghong.song@linux.dev>
+
+commit 4f8543b5f20f851cedbb23f8eade159871d84e2a upstream.
+
+With latest llvm22, I hit the verif_scale_strobemeta selftest failure
+below:
+ $ ./test_progs -n 618
+ libbpf: prog 'on_event': BPF program load failed: -E2BIG
+ libbpf: prog 'on_event': -- BEGIN PROG LOAD LOG --
+ BPF program is too large. Processed 1000001 insn
+ verification time 7019091 usec
+ stack depth 488
+ processed 1000001 insns (limit 1000000) max_states_per_insn 28 total_states 33927 peak_states 12813 mark_read 0
+ -- END PROG LOAD LOG --
+ libbpf: prog 'on_event': failed to load: -E2BIG
+ libbpf: failed to load object 'strobemeta.bpf.o'
+ scale_test:FAIL:expect_success unexpected error: -7 (errno 7)
+ #618 verif_scale_strobemeta:FAIL
+
+But if I increase the verificaiton insn limit from 1M to 10M, the above
+test_progs run actually will succeed. The below is the result from veristat:
+ $ ./veristat strobemeta.bpf.o
+ Processing 'strobemeta.bpf.o'...
+ File Program Verdict Duration (us) Insns States Program size Jited size
+ ---------------- -------- ------- ------------- ------- ------ ------------ ----------
+ strobemeta.bpf.o on_event success 90250893 9777685 358230 15954 80794
+ ---------------- -------- ------- ------------- ------- ------ ------------ ----------
+ Done. Processed 1 files, 0 programs. Skipped 1 files, 0 programs.
+
+Further debugging shows the llvm commit [1] is responsible for the verificaiton
+failure as it tries to convert certain switch statement to if-condition. Such
+change may cause different transformation compared to original switch statement.
+
+In bpf program strobemeta.c case, the initial llvm ir for read_int_var() function is
+ define internal void @read_int_var(ptr noundef %0, i64 noundef %1, ptr noundef %2,
+ ptr noundef %3, ptr noundef %4) #2 !dbg !535 {
+ %6 = alloca ptr, align 8
+ %7 = alloca i64, align 8
+ %8 = alloca ptr, align 8
+ %9 = alloca ptr, align 8
+ %10 = alloca ptr, align 8
+ %11 = alloca ptr, align 8
+ %12 = alloca i32, align 4
+ ...
+ %20 = icmp ne ptr %19, null, !dbg !561
+ br i1 %20, label %22, label %21, !dbg !562
+
+ 21: ; preds = %5
+ store i32 1, ptr %12, align 4
+ br label %48, !dbg !563
+
+ 22:
+ %23 = load ptr, ptr %9, align 8, !dbg !564
+ ...
+
+ 47: ; preds = %38, %22
+ store i32 0, ptr %12, align 4, !dbg !588
+ br label %48, !dbg !588
+
+ 48: ; preds = %47, %21
+ call void @llvm.lifetime.end.p0(ptr %11) #4, !dbg !588
+ %49 = load i32, ptr %12, align 4
+ switch i32 %49, label %51 [
+ i32 0, label %50
+ i32 1, label %50
+ ]
+
+ 50: ; preds = %48, %48
+ ret void, !dbg !589
+
+ 51: ; preds = %48
+ unreachable
+ }
+
+Note that the above 'switch' statement is added by clang frontend.
+Without [1], the switch statement will survive until SelectionDag,
+so the switch statement acts like a 'barrier' and prevents some
+transformation involved with both 'before' and 'after' the switch statement.
+
+But with [1], the switch statement will be removed during middle end
+optimization and later middle end passes (esp. after inlining) have more
+freedom to reorder the code.
+
+The following is the related source code:
+
+ static void *calc_location(struct strobe_value_loc *loc, void *tls_base):
+ bpf_probe_read_user(&tls_ptr, sizeof(void *), dtv);
+ /* if pointer has (void *)-1 value, then TLS wasn't initialized yet */
+ return tls_ptr && tls_ptr != (void *)-1
+ ? tls_ptr + tls_index.offset
+ : NULL;
+
+ In read_int_var() func, we have:
+ void *location = calc_location(&cfg->int_locs[idx], tls_base);
+ if (!location)
+ return;
+
+ bpf_probe_read_user(value, sizeof(struct strobe_value_generic), location);
+ ...
+
+The static func calc_location() is called inside read_int_var(). The asm code
+without [1]:
+ 77: .123....89 (85) call bpf_probe_read_user#112
+ 78: ........89 (79) r1 = *(u64 *)(r10 -368)
+ 79: .1......89 (79) r2 = *(u64 *)(r10 -8)
+ 80: .12.....89 (bf) r3 = r2
+ 81: .123....89 (0f) r3 += r1
+ 82: ..23....89 (07) r2 += 1
+ 83: ..23....89 (79) r4 = *(u64 *)(r10 -464)
+ 84: ..234...89 (a5) if r2 < 0x2 goto pc+13
+ 85: ...34...89 (15) if r3 == 0x0 goto pc+12
+ 86: ...3....89 (bf) r1 = r10
+ 87: .1.3....89 (07) r1 += -400
+ 88: .1.3....89 (b4) w2 = 16
+In this case, 'r2 < 0x2' and 'r3 == 0x0' go to null 'locaiton' place,
+so the verifier actually prefers to do verification first at 'r1 = r10' etc.
+
+The asm code with [1]:
+ 119: .123....89 (85) call bpf_probe_read_user#112
+ 120: ........89 (79) r1 = *(u64 *)(r10 -368)
+ 121: .1......89 (79) r2 = *(u64 *)(r10 -8)
+ 122: .12.....89 (bf) r3 = r2
+ 123: .123....89 (0f) r3 += r1
+ 124: ..23....89 (07) r2 += -1
+ 125: ..23....89 (a5) if r2 < 0xfffffffe goto pc+6
+ 126: ........89 (05) goto pc+17
+ ...
+ 144: ........89 (b4) w1 = 0
+ 145: .1......89 (6b) *(u16 *)(r8 +80) = r1
+In this case, if 'r2 < 0xfffffffe' is true, the control will go to
+non-null 'location' branch, so 'goto pc+17' will actually go to
+null 'location' branch. This seems causing tremendous amount of
+verificaiton state.
+
+To fix the issue, rewrite the following code
+ return tls_ptr && tls_ptr != (void *)-1
+ ? tls_ptr + tls_index.offset
+ : NULL;
+to if/then statement and hopefully these explicit if/then statements
+are sticky during middle-end optimizations.
+
+Test with llvm20 and llvm21 as well and all strobemeta related selftests
+are passed.
+
+ [1] https://github.com/llvm/llvm-project/pull/161000
+
+Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
+Link: https://lore.kernel.org/r/20251014051639.1996331-1-yonghong.song@linux.dev
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/bpf/progs/strobemeta.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/tools/testing/selftests/bpf/progs/strobemeta.h
++++ b/tools/testing/selftests/bpf/progs/strobemeta.h
+@@ -330,9 +330,9 @@ static void *calc_location(struct strobe
+ }
+ bpf_probe_read_user(&tls_ptr, sizeof(void *), dtv);
+ /* if pointer has (void *)-1 value, then TLS wasn't initialized yet */
+- return tls_ptr && tls_ptr != (void *)-1
+- ? tls_ptr + tls_index.offset
+- : NULL;
++ if (!tls_ptr || tls_ptr == (void *)-1)
++ return NULL;
++ return tls_ptr + tls_index.offset;
+ }
+
+ #ifdef SUBPROGS