]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 8 Apr 2026 13:07:33 +0000 (15:07 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 8 Apr 2026 13:07:33 +0000 (15:07 +0200)
added patches:
bpf-add-third-round-of-bounds-deduction.patch
bpf-fix-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch
bpf-improve-bounds-when-s64-crosses-sign-boundary.patch
drm-amd-amdgpu-decouple-aspm-with-pcie-dpm.patch
drm-amd-amdgpu-disable-aspm-in-some-situations.patch
drm-amd-disable-aspm-on-si.patch
drm-amd-display-adjust-dce-8-10-clock-don-t-overclock-by-15.patch
drm-amd-display-correct-logic-check-error-for-fastboot.patch
drm-amd-display-disable-fastboot-on-dce-6-too.patch
drm-amd-display-disable-scaling-on-dce6-for-now.patch
drm-amd-display-fix-dce-6.0-and-6.4-pll-programming.patch
drm-amd-display-keep-pll0-running-on-dce-6.0-and-6.4.patch
drm-amd-display-reject-modes-with-too-high-pixel-clock-on-dce6-10.patch
drm-amd-pm-disable-od_fan_curve-if-temp-or-pwm-range-invalid-for-smu-v13.patch
ext4-publish-jinode-after-initialization.patch
mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch
mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch
mm-replace-read_once-with-standard-page-table-accessors.patch
mptcp-fix-lock-class-name-family-in-pm_nl_create_listen_socket.patch
net-correctly-handle-tunneled-traffic-on-ipv6_csum-gso-fallback.patch
net-mana-fix-use-after-free-in-add_adev-error-path.patch
s390-cpum_sf-cap-sampling-rate-to-prevent-lsctl-exception.patch
s390-perf_cpum_sf-convert-to-use-try_cmpxchg128.patch
scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch
selftests-bpf-test-cross-sign-64bits-range-refinement.patch
selftests-bpf-test-invariants-on-jslt-crossing-sign.patch
selftests-bpf-test-refining-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch
spi-cadence-qspi-fix-exec_mem_op-error-handling.patch
wifi-virt_wifi-remove-set_netdev_dev-to-avoid-use-after-free.patch
x86-cpu-amd-add-additional-fixed-rdseed-microcode-revisions.patch
x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch

32 files changed:
queue-6.12/bpf-add-third-round-of-bounds-deduction.patch [new file with mode: 0644]
queue-6.12/bpf-fix-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch [new file with mode: 0644]
queue-6.12/bpf-improve-bounds-when-s64-crosses-sign-boundary.patch [new file with mode: 0644]
queue-6.12/drm-amd-amdgpu-decouple-aspm-with-pcie-dpm.patch [new file with mode: 0644]
queue-6.12/drm-amd-amdgpu-disable-aspm-in-some-situations.patch [new file with mode: 0644]
queue-6.12/drm-amd-disable-aspm-on-si.patch [new file with mode: 0644]
queue-6.12/drm-amd-display-adjust-dce-8-10-clock-don-t-overclock-by-15.patch [new file with mode: 0644]
queue-6.12/drm-amd-display-correct-logic-check-error-for-fastboot.patch [new file with mode: 0644]
queue-6.12/drm-amd-display-disable-fastboot-on-dce-6-too.patch [new file with mode: 0644]
queue-6.12/drm-amd-display-disable-scaling-on-dce6-for-now.patch [new file with mode: 0644]
queue-6.12/drm-amd-display-fix-dce-6.0-and-6.4-pll-programming.patch [new file with mode: 0644]
queue-6.12/drm-amd-display-keep-pll0-running-on-dce-6.0-and-6.4.patch [new file with mode: 0644]
queue-6.12/drm-amd-display-reject-modes-with-too-high-pixel-clock-on-dce6-10.patch [new file with mode: 0644]
queue-6.12/drm-amd-pm-disable-od_fan_curve-if-temp-or-pwm-range-invalid-for-smu-v13.patch [new file with mode: 0644]
queue-6.12/ext4-publish-jinode-after-initialization.patch [new file with mode: 0644]
queue-6.12/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch [new file with mode: 0644]
queue-6.12/mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch [new file with mode: 0644]
queue-6.12/mm-replace-read_once-with-standard-page-table-accessors.patch [new file with mode: 0644]
queue-6.12/mptcp-fix-lock-class-name-family-in-pm_nl_create_listen_socket.patch [new file with mode: 0644]
queue-6.12/net-correctly-handle-tunneled-traffic-on-ipv6_csum-gso-fallback.patch [new file with mode: 0644]
queue-6.12/net-mana-fix-use-after-free-in-add_adev-error-path.patch [new file with mode: 0644]
queue-6.12/s390-cpum_sf-cap-sampling-rate-to-prevent-lsctl-exception.patch [new file with mode: 0644]
queue-6.12/s390-perf_cpum_sf-convert-to-use-try_cmpxchg128.patch [new file with mode: 0644]
queue-6.12/scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch [new file with mode: 0644]
queue-6.12/selftests-bpf-test-cross-sign-64bits-range-refinement.patch [new file with mode: 0644]
queue-6.12/selftests-bpf-test-invariants-on-jslt-crossing-sign.patch [new file with mode: 0644]
queue-6.12/selftests-bpf-test-refining-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/spi-cadence-qspi-fix-exec_mem_op-error-handling.patch [new file with mode: 0644]
queue-6.12/wifi-virt_wifi-remove-set_netdev_dev-to-avoid-use-after-free.patch [new file with mode: 0644]
queue-6.12/x86-cpu-amd-add-additional-fixed-rdseed-microcode-revisions.patch [new file with mode: 0644]
queue-6.12/x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch [new file with mode: 0644]

diff --git a/queue-6.12/bpf-add-third-round-of-bounds-deduction.patch b/queue-6.12/bpf-add-third-round-of-bounds-deduction.patch
new file mode 100644 (file)
index 0000000..04a3b4d
--- /dev/null
@@ -0,0 +1,93 @@
+From paul.chaignon@gmail.com Sat Apr  4 10:13:19 2026
+From: Paul Chaignon <paul.chaignon@gmail.com>
+Date: Sat, 4 Apr 2026 10:13:16 +0200
+Subject: bpf: Add third round of bounds deduction
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Eduard Zingerman <eddyz87@gmail.com>, Shung-Hsi Yu <shung-hsi.yu@suse.com>, Alexei Starovoitov <ast@kernel.org>
+Message-ID: <c3ad9d44dbf14a110f85902bdc6e119a762e932a.1775289842.git.paul.chaignon@gmail.com>
+Content-Disposition: inline
+
+From: Paul Chaignon <paul.chaignon@gmail.com>
+
+[ Upstream commit 5dbb19b16ac498b0b7f3a8a85f9d25d6d8af397d ]
+
+Commit d7f008738171 ("bpf: try harder to deduce register bounds from
+different numeric domains") added a second call to __reg_deduce_bounds
+in reg_bounds_sync because a single call wasn't enough to converge to a
+fixed point in terms of register bounds.
+
+With patch "bpf: Improve bounds when s64 crosses sign boundary" from
+this series, Eduard noticed that calling __reg_deduce_bounds twice isn't
+enough anymore to converge. The first selftest added in "selftests/bpf:
+Test cross-sign 64bits range refinement" highlights the need for a third
+call to __reg_deduce_bounds. After instruction 7, reg_bounds_sync
+performs the following bounds deduction:
+
+  reg_bounds_sync entry:          scalar(smin=-655,smax=0xeffffeee,smin32=-783,smax32=-146)
+  __update_reg_bounds:            scalar(smin=-655,smax=0xeffffeee,smin32=-783,smax32=-146)
+  __reg_deduce_bounds:
+      __reg32_deduce_bounds:      scalar(smin=-655,smax=0xeffffeee,smin32=-783,smax32=-146,umin32=0xfffffcf1,umax32=0xffffff6e)
+      __reg64_deduce_bounds:      scalar(smin=-655,smax=0xeffffeee,smin32=-783,smax32=-146,umin32=0xfffffcf1,umax32=0xffffff6e)
+      __reg_deduce_mixed_bounds:  scalar(smin=-655,smax=0xeffffeee,umin=umin32=0xfffffcf1,umax=0xffffffffffffff6e,smin32=-783,smax32=-146,umax32=0xffffff6e)
+  __reg_deduce_bounds:
+      __reg32_deduce_bounds:      scalar(smin=-655,smax=0xeffffeee,umin=umin32=0xfffffcf1,umax=0xffffffffffffff6e,smin32=-783,smax32=-146,umax32=0xffffff6e)
+      __reg64_deduce_bounds:      scalar(smin=-655,smax=smax32=-146,umin=0xfffffffffffffd71,umax=0xffffffffffffff6e,smin32=-783,umin32=0xfffffcf1,umax32=0xffffff6e)
+      __reg_deduce_mixed_bounds:  scalar(smin=-655,smax=smax32=-146,umin=0xfffffffffffffd71,umax=0xffffffffffffff6e,smin32=-783,umin32=0xfffffcf1,umax32=0xffffff6e)
+  __reg_bound_offset:             scalar(smin=-655,smax=smax32=-146,umin=0xfffffffffffffd71,umax=0xffffffffffffff6e,smin32=-783,umin32=0xfffffcf1,umax32=0xffffff6e,var_off=(0xfffffffffffffc00; 0x3ff))
+  __update_reg_bounds:            scalar(smin=-655,smax=smax32=-146,umin=0xfffffffffffffd71,umax=0xffffffffffffff6e,smin32=-783,umin32=0xfffffcf1,umax32=0xffffff6e,var_off=(0xfffffffffffffc00; 0x3ff))
+
+In particular, notice how:
+1. In the first call to __reg_deduce_bounds, __reg32_deduce_bounds
+   learns new u32 bounds.
+2. __reg64_deduce_bounds is unable to improve bounds at this point.
+3. __reg_deduce_mixed_bounds derives new u64 bounds from the u32 bounds.
+4. In the second call to __reg_deduce_bounds, __reg64_deduce_bounds
+   improves the smax and umin bounds thanks to patch "bpf: Improve
+   bounds when s64 crosses sign boundary" from this series.
+5. Subsequent functions are unable to improve the ranges further (only
+   tnums). Yet, a better smin32 bound could be learned from the smin
+   bound.
+
+__reg32_deduce_bounds is able to improve smin32 from smin, but for that
+we need a third call to __reg_deduce_bounds.
+
+As discussed in [1], there may be a better way to organize the deduction
+rules to learn the same information with less calls to the same
+functions. Such an optimization requires further analysis and is
+orthogonal to the present patchset.
+
+Link: https://lore.kernel.org/bpf/aIKtSK9LjQXB8FLY@mail.gmail.com/ [1]
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Co-developed-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Link: https://lore.kernel.org/r/79619d3b42e5525e0e174ed534b75879a5ba15de.1753695655.git.paul.chaignon@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c                               |    1 +
+ tools/testing/selftests/bpf/progs/verifier_bounds.c |    2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -2292,6 +2292,7 @@ static void reg_bounds_sync(struct bpf_r
+       /* We might have learned something about the sign bit. */
+       __reg_deduce_bounds(reg);
+       __reg_deduce_bounds(reg);
++      __reg_deduce_bounds(reg);
+       /* We might have learned some bits from the bounds. */
+       __reg_bound_offset(reg);
+       /* Intersecting with the old var_off might have improved our bounds
+--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
++++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
+@@ -1223,7 +1223,7 @@ l0_%=:   r0 = 0;                                         \
+ SEC("socket")
+ __description("bounds deduction cross sign boundary, negative overlap")
+ __success __log_level(2) __flag(BPF_F_TEST_REG_INVARIANTS)
+-__msg("7: (1f) r0 -= r6 {{.*}} R0=scalar(smin=-655,smax=smax32=-146,umin=0xfffffffffffffd71,umax=0xffffffffffffff6e,smin32=-783,umin32=0xfffffcf1,umax32=0xffffff6e,var_off=(0xfffffffffffffc00; 0x3ff))")
++__msg("7: (1f) r0 -= r6 {{.*}} R0=scalar(smin=smin32=-655,smax=smax32=-146,umin=0xfffffffffffffd71,umax=0xffffffffffffff6e,umin32=0xfffffd71,umax32=0xffffff6e,var_off=(0xfffffffffffffc00; 0x3ff))")
+ __retval(0)
+ __naked void bounds_deduct_negative_overlap(void)
+ {
diff --git a/queue-6.12/bpf-fix-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch b/queue-6.12/bpf-fix-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch
new file mode 100644 (file)
index 0000000..6bf9456
--- /dev/null
@@ -0,0 +1,196 @@
+From paul.chaignon@gmail.com Sat Apr  4 10:14:24 2026
+From: Paul Chaignon <paul.chaignon@gmail.com>
+Date: Sat, 4 Apr 2026 10:14:20 +0200
+Subject: bpf: Fix u32/s32 bounds when ranges cross min/max boundary
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Eduard Zingerman <eddyz87@gmail.com>, Shung-Hsi Yu <shung-hsi.yu@suse.com>, Alexei Starovoitov <ast@kernel.org>, Emil Tsalapatis <emil@etsalapatis.com>, Andrea Righi <arighi@nvidia.com>
+Message-ID: <b9a0f1832723f3881833a1c466af998749292d05.1775289842.git.paul.chaignon@gmail.com>
+Content-Disposition: inline
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit fbc7aef517d8765e4c425d2792409bb9bf2e1f13 ]
+
+Same as in __reg64_deduce_bounds(), refine s32/u32 ranges
+in __reg32_deduce_bounds() in the following situations:
+
+- s32 range crosses U32_MAX/0 boundary, positive part of the s32 range
+  overlaps with u32 range:
+
+  0                                                   U32_MAX
+  |  [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx]              |
+  |----------------------------|----------------------------|
+  |xxxxx s32 range xxxxxxxxx]                       [xxxxxxx|
+  0                     S32_MAX S32_MIN                    -1
+
+- s32 range crosses U32_MAX/0 boundary, negative part of the s32 range
+  overlaps with u32 range:
+
+  0                                                   U32_MAX
+  |              [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx]  |
+  |----------------------------|----------------------------|
+  |xxxxxxxxx]                       [xxxxxxxxxxxx s32 range |
+  0                     S32_MAX S32_MIN                    -1
+
+- No refinement if ranges overlap in two intervals.
+
+This helps for e.g. consider the following program:
+
+   call %[bpf_get_prandom_u32];
+   w0 &= 0xffffffff;
+   if w0 < 0x3 goto 1f;    // on fall-through u32 range [3..U32_MAX]
+   if w0 s> 0x1 goto 1f;   // on fall-through s32 range [S32_MIN..1]
+   if w0 s< 0x0 goto 1f;   // range can be narrowed to  [S32_MIN..-1]
+   r10 = 0;
+1: ...;
+
+The reg_bounds.c selftest is updated to incorporate identical logic,
+refinement based on non-overflowing range halves:
+
+  ((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
+  ((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
+
+Reported-by: Andrea Righi <arighi@nvidia.com>
+Reported-by: Emil Tsalapatis <emil@etsalapatis.com>
+Closes: https://lore.kernel.org/bpf/aakqucg4vcujVwif@gpd4/T/
+Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20260306-bpf-32-bit-range-overflow-v3-1-f7f67e060a6b@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c                               |   24 +++++++
+ tools/testing/selftests/bpf/prog_tests/reg_bounds.c |   62 ++++++++++++++++++--
+ 2 files changed, 82 insertions(+), 4 deletions(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -2046,6 +2046,30 @@ static void __reg32_deduce_bounds(struct
+       if ((u32)reg->s32_min_value <= (u32)reg->s32_max_value) {
+               reg->u32_min_value = max_t(u32, reg->s32_min_value, reg->u32_min_value);
+               reg->u32_max_value = min_t(u32, reg->s32_max_value, reg->u32_max_value);
++      } else {
++              if (reg->u32_max_value < (u32)reg->s32_min_value) {
++                      /* See __reg64_deduce_bounds() for detailed explanation.
++                       * Refine ranges in the following situation:
++                       *
++                       * 0                                                   U32_MAX
++                       * |  [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx]              |
++                       * |----------------------------|----------------------------|
++                       * |xxxxx s32 range xxxxxxxxx]                       [xxxxxxx|
++                       * 0                     S32_MAX S32_MIN                    -1
++                       */
++                      reg->s32_min_value = (s32)reg->u32_min_value;
++                      reg->u32_max_value = min_t(u32, reg->u32_max_value, reg->s32_max_value);
++              } else if ((u32)reg->s32_max_value < reg->u32_min_value) {
++                      /*
++                       * 0                                                   U32_MAX
++                       * |              [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx]  |
++                       * |----------------------------|----------------------------|
++                       * |xxxxxxxxx]                       [xxxxxxxxxxxx s32 range |
++                       * 0                     S32_MAX S32_MIN                    -1
++                       */
++                      reg->s32_max_value = (s32)reg->u32_max_value;
++                      reg->u32_min_value = max_t(u32, reg->u32_min_value, reg->s32_min_value);
++              }
+       }
+ }
+--- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
++++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
+@@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t,
+       }
+ }
+-static struct range range_improve(enum num_t t, struct range old, struct range new)
++static struct range range_intersection(enum num_t t, struct range old, struct range new)
+ {
+       return range(t, max_t(t, old.a, new.a), min_t(t, old.b, new.b));
+ }
++/*
++ * Result is precise when 'x' and 'y' overlap or form a continuous range,
++ * result is an over-approximation if 'x' and 'y' do not overlap.
++ */
++static struct range range_union(enum num_t t, struct range x, struct range y)
++{
++      if (!is_valid_range(t, x))
++              return y;
++      if (!is_valid_range(t, y))
++              return x;
++      return range(t, min_t(t, x.a, y.a), max_t(t, x.b, y.b));
++}
++
++/*
++ * This function attempts to improve x range intersecting it with y.
++ * range_cast(... to_t ...) looses precision for ranges that pass to_t
++ * min/max boundaries. To avoid such precision loses this function
++ * splits both x and y into halves corresponding to non-overflowing
++ * sub-ranges: [0, smin] and [smax, -1].
++ * Final result is computed as follows:
++ *
++ *   ((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
++ *   ((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
++ *
++ * Precision might still be lost if final union is not a continuous range.
++ */
++static struct range range_refine_in_halves(enum num_t x_t, struct range x,
++                                         enum num_t y_t, struct range y)
++{
++      struct range x_pos, x_neg, y_pos, y_neg, r_pos, r_neg;
++      u64 smax, smin, neg_one;
++
++      if (t_is_32(x_t)) {
++              smax = (u64)(u32)S32_MAX;
++              smin = (u64)(u32)S32_MIN;
++              neg_one = (u64)(u32)(s32)(-1);
++      } else {
++              smax = (u64)S64_MAX;
++              smin = (u64)S64_MIN;
++              neg_one = U64_MAX;
++      }
++      x_pos = range_intersection(x_t, x, range(x_t, 0, smax));
++      x_neg = range_intersection(x_t, x, range(x_t, smin, neg_one));
++      y_pos = range_intersection(y_t, y, range(x_t, 0, smax));
++      y_neg = range_intersection(y_t, y, range(y_t, smin, neg_one));
++      r_pos = range_intersection(x_t, x_pos, range_cast(y_t, x_t, y_pos));
++      r_neg = range_intersection(x_t, x_neg, range_cast(y_t, x_t, y_neg));
++      return range_union(x_t, r_pos, r_neg);
++
++}
++
+ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t, struct range y)
+ {
+       struct range y_cast;
++      if (t_is_32(x_t) == t_is_32(y_t))
++              x = range_refine_in_halves(x_t, x, y_t, y);
++
+       y_cast = range_cast(y_t, x_t, y);
+       /* If we know that
+@@ -444,7 +498,7 @@ static struct range range_refine(enum nu
+        */
+       if (x_t == S64 && y_t == S32 && y_cast.a <= S32_MAX  && y_cast.b <= S32_MAX &&
+           (s64)x.a >= S32_MIN && (s64)x.b <= S32_MAX)
+-              return range_improve(x_t, x, y_cast);
++              return range_intersection(x_t, x, y_cast);
+       /* the case when new range knowledge, *y*, is a 32-bit subregister
+        * range, while previous range knowledge, *x*, is a full register
+@@ -462,11 +516,11 @@ static struct range range_refine(enum nu
+               x_swap = range(x_t, swap_low32(x.a, y_cast.a), swap_low32(x.b, y_cast.b));
+               if (!is_valid_range(x_t, x_swap))
+                       return x;
+-              return range_improve(x_t, x, x_swap);
++              return range_intersection(x_t, x, x_swap);
+       }
+       /* otherwise, plain range cast and intersection works */
+-      return range_improve(x_t, x, y_cast);
++      return range_intersection(x_t, x, y_cast);
+ }
+ /* =======================
diff --git a/queue-6.12/bpf-improve-bounds-when-s64-crosses-sign-boundary.patch b/queue-6.12/bpf-improve-bounds-when-s64-crosses-sign-boundary.patch
new file mode 100644 (file)
index 0000000..9f0baa8
--- /dev/null
@@ -0,0 +1,116 @@
+From paul.chaignon@gmail.com Sat Apr  4 10:10:56 2026
+From: Paul Chaignon <paul.chaignon@gmail.com>
+Date: Sat, 4 Apr 2026 10:10:52 +0200
+Subject: bpf: Improve bounds when s64 crosses sign boundary
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Eduard Zingerman <eddyz87@gmail.com>, Shung-Hsi Yu <shung-hsi.yu@suse.com>, Alexei Starovoitov <ast@kernel.org>
+Message-ID: <0f6da4f74ebc491dd651dfcf3ba984bbd3dc566f.1775289842.git.paul.chaignon@gmail.com>
+Content-Disposition: inline
+
+From: Paul Chaignon <paul.chaignon@gmail.com>
+
+[ Upstream commit 00bf8d0c6c9be0c481fc45a3f7d87c7f8812f229 ]
+
+__reg64_deduce_bounds currently improves the s64 range using the u64
+range and vice versa, but only if it doesn't cross the sign boundary.
+
+This patch improves __reg64_deduce_bounds to cover the case where the
+s64 range crosses the sign boundary but overlaps with the u64 range on
+only one end. In that case, we can improve both ranges. Consider the
+following example, with the s64 range crossing the sign boundary:
+
+    0                                                   U64_MAX
+    |  [xxxxxxxxxxxxxx u64 range xxxxxxxxxxxxxx]              |
+    |----------------------------|----------------------------|
+    |xxxxx s64 range xxxxxxxxx]                       [xxxxxxx|
+    0                     S64_MAX S64_MIN                    -1
+
+The u64 range overlaps only with positive portion of the s64 range. We
+can thus derive the following new s64 and u64 ranges.
+
+    0                                                   U64_MAX
+    |  [xxxxxx u64 range xxxxx]                               |
+    |----------------------------|----------------------------|
+    |  [xxxxxx s64 range xxxxx]                               |
+    0                     S64_MAX S64_MIN                    -1
+
+The same logic can probably apply to the s32/u32 ranges, but this patch
+doesn't implement that change.
+
+In addition to the selftests, the __reg64_deduce_bounds change was
+also tested with Agni, the formal verification tool for the range
+analysis [1].
+
+Link: https://github.com/bpfverif/agni [1]
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Link: https://lore.kernel.org/r/933bd9ce1f36ded5559f92fdc09e5dbc823fa245.1753695655.git.paul.chaignon@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -2129,6 +2129,58 @@ static void __reg64_deduce_bounds(struct
+       if ((u64)reg->smin_value <= (u64)reg->smax_value) {
+               reg->umin_value = max_t(u64, reg->smin_value, reg->umin_value);
+               reg->umax_value = min_t(u64, reg->smax_value, reg->umax_value);
++      } else {
++              /* If the s64 range crosses the sign boundary, then it's split
++               * between the beginning and end of the U64 domain. In that
++               * case, we can derive new bounds if the u64 range overlaps
++               * with only one end of the s64 range.
++               *
++               * In the following example, the u64 range overlaps only with
++               * positive portion of the s64 range.
++               *
++               * 0                                                   U64_MAX
++               * |  [xxxxxxxxxxxxxx u64 range xxxxxxxxxxxxxx]              |
++               * |----------------------------|----------------------------|
++               * |xxxxx s64 range xxxxxxxxx]                       [xxxxxxx|
++               * 0                     S64_MAX S64_MIN                    -1
++               *
++               * We can thus derive the following new s64 and u64 ranges.
++               *
++               * 0                                                   U64_MAX
++               * |  [xxxxxx u64 range xxxxx]                               |
++               * |----------------------------|----------------------------|
++               * |  [xxxxxx s64 range xxxxx]                               |
++               * 0                     S64_MAX S64_MIN                    -1
++               *
++               * If they overlap in two places, we can't derive anything
++               * because reg_state can't represent two ranges per numeric
++               * domain.
++               *
++               * 0                                                   U64_MAX
++               * |  [xxxxxxxxxxxxxxxxx u64 range xxxxxxxxxxxxxxxxx]        |
++               * |----------------------------|----------------------------|
++               * |xxxxx s64 range xxxxxxxxx]                    [xxxxxxxxxx|
++               * 0                     S64_MAX S64_MIN                    -1
++               *
++               * The first condition below corresponds to the first diagram
++               * above.
++               */
++              if (reg->umax_value < (u64)reg->smin_value) {
++                      reg->smin_value = (s64)reg->umin_value;
++                      reg->umax_value = min_t(u64, reg->umax_value, reg->smax_value);
++              } else if ((u64)reg->smax_value < reg->umin_value) {
++                      /* This second condition considers the case where the u64 range
++                       * overlaps with the negative portion of the s64 range:
++                       *
++                       * 0                                                   U64_MAX
++                       * |              [xxxxxxxxxxxxxx u64 range xxxxxxxxxxxxxx]  |
++                       * |----------------------------|----------------------------|
++                       * |xxxxxxxxx]                       [xxxxxxxxxxxx s64 range |
++                       * 0                     S64_MAX S64_MIN                    -1
++                       */
++                      reg->smax_value = (s64)reg->umax_value;
++                      reg->umin_value = max_t(u64, reg->umin_value, reg->smin_value);
++              }
+       }
+ }
diff --git a/queue-6.12/drm-amd-amdgpu-decouple-aspm-with-pcie-dpm.patch b/queue-6.12/drm-amd-amdgpu-decouple-aspm-with-pcie-dpm.patch
new file mode 100644 (file)
index 0000000..255086d
--- /dev/null
@@ -0,0 +1,35 @@
+From stable+bounces-232620-greg=kroah.com@vger.kernel.org Wed Apr  1 02:41:51 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:38:59 -0700
+Subject: drm/amd/amdgpu: decouple ASPM with pcie dpm
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-2-rosenp@gmail.com>
+
+From: Kenneth Feng <kenneth.feng@amd.com>
+
+[ Upstream commit df0e722fbdbedb6f2b682dc2fad9e0c221e3622d ]
+
+ASPM doesn't need to be disabled if pcie dpm is disabled.
+So ASPM can be independantly enabled.
+
+Signed-off-by: Kenneth Feng <kenneth.feng@amd.com>
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -1782,8 +1782,6 @@ bool amdgpu_device_should_use_aspm(struc
+       }
+       if (adev->flags & AMD_IS_APU)
+               return false;
+-      if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK))
+-              return false;
+       return pcie_aspm_enabled(adev->pdev);
+ }
diff --git a/queue-6.12/drm-amd-amdgpu-disable-aspm-in-some-situations.patch b/queue-6.12/drm-amd-amdgpu-disable-aspm-in-some-situations.patch
new file mode 100644 (file)
index 0000000..62a779c
--- /dev/null
@@ -0,0 +1,79 @@
+From stable+bounces-232621-greg=kroah.com@vger.kernel.org Wed Apr  1 02:42:32 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:00 -0700
+Subject: drm/amd/amdgpu: disable ASPM in some situations
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-3-rosenp@gmail.com>
+
+From: Kenneth Feng <kenneth.feng@amd.com>
+
+[ Upstream commit c770ef19673fb1defcbde2ee2b91c3c89bfcf164 ]
+
+disable ASPM with some ASICs on some specific platforms.
+required from PCIe controller owner.
+
+Signed-off-by: Kenneth Feng <kenneth.feng@amd.com>
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |   32 +++++++++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -84,6 +84,7 @@
+ #if IS_ENABLED(CONFIG_X86)
+ #include <asm/intel-family.h>
++#include <asm/cpu_device_id.h>
+ #endif
+ MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
+@@ -1758,6 +1759,35 @@ static bool amdgpu_device_pcie_dynamic_s
+       return true;
+ }
++static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
++{
++#if IS_ENABLED(CONFIG_X86)
++      struct cpuinfo_x86 *c = &cpu_data(0);
++
++      if (!(amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 0) ||
++                amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 1)))
++              return false;
++
++      if (c->x86 == 6 &&
++              adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5) {
++              switch (c->x86_model) {
++              case VFM_MODEL(INTEL_ALDERLAKE):
++              case VFM_MODEL(INTEL_ALDERLAKE_L):
++              case VFM_MODEL(INTEL_RAPTORLAKE):
++              case VFM_MODEL(INTEL_RAPTORLAKE_P):
++              case VFM_MODEL(INTEL_RAPTORLAKE_S):
++                      return true;
++              default:
++                      return false;
++              }
++      } else {
++              return false;
++      }
++#else
++      return false;
++#endif
++}
++
+ /**
+  * amdgpu_device_should_use_aspm - check if the device should program ASPM
+  *
+@@ -1782,6 +1812,8 @@ bool amdgpu_device_should_use_aspm(struc
+       }
+       if (adev->flags & AMD_IS_APU)
+               return false;
++      if (amdgpu_device_aspm_support_quirk(adev))
++              return false;
+       return pcie_aspm_enabled(adev->pdev);
+ }
diff --git a/queue-6.12/drm-amd-disable-aspm-on-si.patch b/queue-6.12/drm-amd-disable-aspm-on-si.patch
new file mode 100644 (file)
index 0000000..bfdca20
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-232629-greg=kroah.com@vger.kernel.org Wed Apr  1 02:40:16 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:07 -0700
+Subject: drm/amd: Disable ASPM on SI
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-10-rosenp@gmail.com>
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+[ Upstream commit 7bdd91abf0cb3ea78160e2e78fb58b12f6a38d55 ]
+
+Enabling ASPM causes randoms hangs on Tahiti and Oland on Zen4.
+It's unclear if this is a platform-specific or GPU-specific issue.
+Disable ASPM on SI for the time being.
+
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -1761,6 +1761,13 @@ static bool amdgpu_device_pcie_dynamic_s
+ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
+ {
++      /* Enabling ASPM causes randoms hangs on Tahiti and Oland on Zen4.
++       * It's unclear if this is a platform-specific or GPU-specific issue.
++       * Disable ASPM on SI for the time being.
++       */
++      if (adev->family == AMDGPU_FAMILY_SI)
++              return true;
++
+ #if IS_ENABLED(CONFIG_X86)
+       struct cpuinfo_x86 *c = &cpu_data(0);
diff --git a/queue-6.12/drm-amd-display-adjust-dce-8-10-clock-don-t-overclock-by-15.patch b/queue-6.12/drm-amd-display-adjust-dce-8-10-clock-don-t-overclock-by-15.patch
new file mode 100644 (file)
index 0000000..20f8fa6
--- /dev/null
@@ -0,0 +1,70 @@
+From stable+bounces-232627-greg=kroah.com@vger.kernel.org Wed Apr  1 02:45:17 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:05 -0700
+Subject: drm/amd/display: Adjust DCE 8-10 clock, don't overclock by 15%
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-8-rosenp@gmail.com>
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+[ Upstream commit 1ae45b5d4f371af8ae51a3827d0ec9fe27eeb867 ]
+
+Adjust the nominal (and performance) clocks for DCE 8-10,
+and set them to 625 MHz, which is the value used by the legacy
+display code in amdgpu_atombios_get_clock_info.
+
+This was tested with Hawaii, Tonga and Fiji.
+These GPUs can output 4K 60Hz (10-bit depth) at 625 MHz.
+
+The extra 15% clock was added as a workaround for a Polaris issue
+which uses DCE 11, and should not have been used on DCE 8-10 which
+are already hardcoded to the highest possible display clock.
+Unfortunately, the extra 15% was mistakenly copied and kept
+even on code paths which don't affect Polaris.
+
+This commit fixes that and also        adds a check to make sure
+not to exceed the maximum DCE 8-10 display clock.
+
+Fixes: 8cd61c313d8b ("drm/amd/display: Raise dispclk value for Polaris")
+Fixes: dc88b4a684d2 ("drm/amd/display: make clk mgr soc specific")
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Rodrigo Siqueira <siqueira@igalia.com>
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c |   12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
+@@ -72,9 +72,9 @@ static const struct state_dependent_cloc
+ /* ClocksStateLow */
+ { .display_clk_khz = 352000, .pixel_clk_khz = 330000},
+ /* ClocksStateNominal */
+-{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 },
++{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 },
+ /* ClocksStatePerformance */
+-{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } };
++{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 } };
+ int dentist_get_divider_from_did(int did)
+ {
+@@ -403,11 +403,9 @@ static void dce_update_clocks(struct clk
+ {
+       struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       struct dm_pp_power_level_change_request level_change_req;
+-      int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz;
+-
+-      /*TODO: W/A for dal3 linux, investigate why this works */
+-      if (!clk_mgr_dce->dfs_bypass_active)
+-              patched_disp_clk = patched_disp_clk * 115 / 100;
++      const int max_disp_clk =
++              clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
++      int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz);
+       level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context);
+       /* get max clock state from PPLIB */
diff --git a/queue-6.12/drm-amd-display-correct-logic-check-error-for-fastboot.patch b/queue-6.12/drm-amd-display-correct-logic-check-error-for-fastboot.patch
new file mode 100644 (file)
index 0000000..c8fe91e
--- /dev/null
@@ -0,0 +1,51 @@
+From stable+bounces-232628-greg=kroah.com@vger.kernel.org Wed Apr  1 02:45:51 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:08 -0700
+Subject: drm/amd/display: Correct logic check error for fastboot
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-11-rosenp@gmail.com>
+
+From: Charlene Liu <Charlene.Liu@amd.com>
+
+[ Upstream commit b6a65009e7ce3f0cc72da18f186adb60717b51a0 ]
+
+[Why]
+Fix fastboot broken in driver.
+This is caused by an open source backport change 7495962c.
+
+from the comment, the intended check is to disable fastboot
+for pre-DCN10. but the logic check is reversed, and causes
+fastboot to be disabled on all DCN10 and after.
+
+fastboot is for driver trying to pick up bios used hw setting
+and bypass reprogramming the hw if dc_validate_boot_timing()
+condition meets.
+
+Fixes: 7495962cbceb ("drm/amd/display: Disable fastboot on DCE 6 too")
+Cc: stable@vger.kernel.org
+Reviewed-by: Mario Limonciello <Mario.Limonciello@amd.com>
+Reviewed-by: Ovidiu Bunea <ovidiu.bunea@amd.com>
+Signed-off-by: Charlene Liu <Charlene.Liu@amd.com>
+Signed-off-by: Ray Wu <ray.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+@@ -1910,8 +1910,8 @@ void dce110_enable_accelerated_mode(stru
+       get_edp_streams(context, edp_streams, &edp_stream_num);
+-      /* Check fastboot support, disable on DCE 6-8 because of blank screens */
+-      if (edp_num && edp_stream_num && dc->ctx->dce_version < DCE_VERSION_10_0) {
++      /* Check fastboot support, disable on DCE 6-8-10 because of blank screens */
++      if (edp_num && edp_stream_num && dc->ctx->dce_version > DCE_VERSION_10_0) {
+               for (i = 0; i < edp_num; i++) {
+                       edp_link = edp_links[i];
+                       if (edp_link != edp_streams[0]->link)
diff --git a/queue-6.12/drm-amd-display-disable-fastboot-on-dce-6-too.patch b/queue-6.12/drm-amd-display-disable-fastboot-on-dce-6-too.patch
new file mode 100644 (file)
index 0000000..df5ddfe
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-232622-greg=kroah.com@vger.kernel.org Wed Apr  1 02:43:13 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:01 -0700
+Subject: drm/amd/display: Disable fastboot on DCE 6 too
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-4-rosenp@gmail.com>
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+[ Upstream commit 7495962cbceb967e095233a5673ea71f3bcdee7e ]
+
+It already didn't work on DCE 8,
+so there is no reason to assume it would on DCE 6.
+
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Reviewed-by: Rodrigo Siqueira <siqueira@igalia.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+@@ -1910,10 +1910,8 @@ void dce110_enable_accelerated_mode(stru
+       get_edp_streams(context, edp_streams, &edp_stream_num);
+-      // Check fastboot support, disable on DCE8 because of blank screens
+-      if (edp_num && edp_stream_num && dc->ctx->dce_version != DCE_VERSION_8_0 &&
+-                  dc->ctx->dce_version != DCE_VERSION_8_1 &&
+-                  dc->ctx->dce_version != DCE_VERSION_8_3) {
++      /* Check fastboot support, disable on DCE 6-8 because of blank screens */
++      if (edp_num && edp_stream_num && dc->ctx->dce_version < DCE_VERSION_10_0) {
+               for (i = 0; i < edp_num; i++) {
+                       edp_link = edp_links[i];
+                       if (edp_link != edp_streams[0]->link)
diff --git a/queue-6.12/drm-amd-display-disable-scaling-on-dce6-for-now.patch b/queue-6.12/drm-amd-display-disable-scaling-on-dce6-for-now.patch
new file mode 100644 (file)
index 0000000..5d17d70
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-232626-greg=kroah.com@vger.kernel.org Wed Apr  1 02:45:16 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:06 -0700
+Subject: drm/amd/display: Disable scaling on DCE6 for now
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-9-rosenp@gmail.com>
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+[ Upstream commit 0e190a0446ec517666dab4691b296a9b758e590f ]
+
+Scaling doesn't work on DCE6 at the moment, the current
+register programming produces incorrect output when using
+fractional scaling (between 100-200%) on resolutions higher
+than 1080p.
+
+Disable it until we figure out how to program it properly.
+
+Fixes: 7c15fd86aaec ("drm/amd/display: dc/dce: add initial DCE6 support (v10)")
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
+@@ -404,13 +404,13 @@ static const struct dc_plane_cap plane_c
+       },
+       .max_upscale_factor = {
+-                      .argb8888 = 16000,
++                      .argb8888 = 1,
+                       .nv12 = 1,
+                       .fp16 = 1
+       },
+       .max_downscale_factor = {
+-                      .argb8888 = 250,
++                      .argb8888 = 1,
+                       .nv12 = 1,
+                       .fp16 = 1
+       }
diff --git a/queue-6.12/drm-amd-display-fix-dce-6.0-and-6.4-pll-programming.patch b/queue-6.12/drm-amd-display-fix-dce-6.0-and-6.4-pll-programming.patch
new file mode 100644 (file)
index 0000000..3132cfa
--- /dev/null
@@ -0,0 +1,132 @@
+From stable+bounces-232625-greg=kroah.com@vger.kernel.org Wed Apr  1 02:44:20 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:04 -0700
+Subject: drm/amd/display: Fix DCE 6.0 and 6.4 PLL programming.
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-7-rosenp@gmail.com>
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+[ Upstream commit 35222b5934ec8d762473592ece98659baf6bc48e ]
+
+Apparently, both DCE 6.0 and 6.4 have 3 PLLs, but PLL0 can only
+be used for DP. Make sure to initialize the correct amount of PLLs
+in DC for these DCE versions and use PLL0 only for DP.
+
+Also, on DCE 6.0 and 6.4, the PLL0 needs to be powered on at
+initialization as opposed to DCE 6.1 and 7.x which use a different
+clock source for DFS.
+
+The following functions were used as reference from the        old
+radeon driver implementation of        DCE 6.x:
+- radeon_atom_pick_pll
+- atombios_crtc_set_disp_eng_pll
+
+Reviewed-by: Rodrigo Siqueira <siqueira@igalia.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c |    5 +
+ drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c       |   34 +++++++-----
+ 2 files changed, 25 insertions(+), 14 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
+@@ -245,6 +245,11 @@ int dce_set_clock(
+       pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10;
+       pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
++      /* DCE 6.0, DCE 6.4: engine clock is the same as PLL0 */
++      if (clk_mgr_base->ctx->dce_version == DCE_VERSION_6_0 ||
++          clk_mgr_base->ctx->dce_version == DCE_VERSION_6_4)
++              pxl_clk_params.pll_id = CLOCK_SOURCE_ID_PLL0;
++
+       if (clk_mgr_dce->dfs_bypass_active)
+               pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true;
+--- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
+@@ -374,7 +374,7 @@ static const struct resource_caps res_ca
+               .num_timing_generator = 6,
+               .num_audio = 6,
+               .num_stream_encoder = 6,
+-              .num_pll = 2,
++              .num_pll = 3,
+               .num_ddc = 6,
+ };
+@@ -390,7 +390,7 @@ static const struct resource_caps res_ca
+               .num_timing_generator = 2,
+               .num_audio = 2,
+               .num_stream_encoder = 2,
+-              .num_pll = 2,
++              .num_pll = 3,
+               .num_ddc = 2,
+ };
+@@ -990,21 +990,24 @@ static bool dce60_construct(
+       if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) {
+               pool->base.dp_clock_source =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
++              /* DCE 6.0 and 6.4: PLL0 can only be used with DP. Don't initialize it here. */
+               pool->base.clock_sources[0] =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false);
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
+               pool->base.clock_sources[1] =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
+               pool->base.clk_src_count = 2;
+       } else {
+               pool->base.dp_clock_source =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
+               pool->base.clock_sources[0] =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
+-              pool->base.clk_src_count = 1;
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
++              pool->base.clock_sources[1] =
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
++              pool->base.clk_src_count = 2;
+       }
+       if (pool->base.dp_clock_source == NULL) {
+@@ -1382,21 +1385,24 @@ static bool dce64_construct(
+       if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) {
+               pool->base.dp_clock_source =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
++              /* DCE 6.0 and 6.4: PLL0 can only be used with DP. Don't initialize it here. */
+               pool->base.clock_sources[0] =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false);
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
+               pool->base.clock_sources[1] =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false);
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
+               pool->base.clk_src_count = 2;
+       } else {
+               pool->base.dp_clock_source =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true);
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
+               pool->base.clock_sources[0] =
+-                              dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false);
+-              pool->base.clk_src_count = 1;
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
++              pool->base.clock_sources[1] =
++                      dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
++              pool->base.clk_src_count = 2;
+       }
+       if (pool->base.dp_clock_source == NULL) {
diff --git a/queue-6.12/drm-amd-display-keep-pll0-running-on-dce-6.0-and-6.4.patch b/queue-6.12/drm-amd-display-keep-pll0-running-on-dce-6.0-and-6.4.patch
new file mode 100644 (file)
index 0000000..8454019
--- /dev/null
@@ -0,0 +1,63 @@
+From stable+bounces-232624-greg=kroah.com@vger.kernel.org Wed Apr  1 02:44:15 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:03 -0700
+Subject: drm/amd/display: Keep PLL0 running on DCE 6.0 and 6.4
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-6-rosenp@gmail.com>
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+[ Upstream commit 0449726b58ea64ec96b95f95944f0a3650204059 ]
+
+DC can turn off the display clock when no displays are connected
+or when all displays are off, for reference see:
+- dce*_validate_bandwidth
+
+DC also assumes that the DP clock is always on and never powers
+it down, for reference see:
+- dce110_clock_source_power_down
+
+In case of DCE 6.0 and 6.4, PLL0 is the clock source for both
+the engine clock and DP clock, for reference see:
+- radeon_atom_pick_pll
+- atombios_crtc_set_disp_eng_pll
+
+Therefore, PLL0 should be always kept running on DCE 6.0 and 6.4.
+This commit achieves that by ensuring that by setting the display
+clock to the corresponding value in low power state instead of
+zero.
+
+This fixes a page flip timeout on SI with DC which happens when
+all connected displays are blanked.
+
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c |   11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
+@@ -889,7 +889,16 @@ static bool dce60_validate_bandwidth(
+               context->bw_ctx.bw.dce.dispclk_khz = 681000;
+               context->bw_ctx.bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ;
+       } else {
+-              context->bw_ctx.bw.dce.dispclk_khz = 0;
++              /* On DCE 6.0 and 6.4 the PLL0 is both the display engine clock and
++               * the DP clock, and shouldn't be turned off. Just select the display
++               * clock value from its low power mode.
++               */
++              if (dc->ctx->dce_version == DCE_VERSION_6_0 ||
++                      dc->ctx->dce_version == DCE_VERSION_6_4)
++                      context->bw_ctx.bw.dce.dispclk_khz = 352000;
++              else
++                      context->bw_ctx.bw.dce.dispclk_khz = 0;
++
+               context->bw_ctx.bw.dce.yclk_khz = 0;
+       }
diff --git a/queue-6.12/drm-amd-display-reject-modes-with-too-high-pixel-clock-on-dce6-10.patch b/queue-6.12/drm-amd-display-reject-modes-with-too-high-pixel-clock-on-dce6-10.patch
new file mode 100644 (file)
index 0000000..acfdc9c
--- /dev/null
@@ -0,0 +1,158 @@
+From stable+bounces-232623-greg=kroah.com@vger.kernel.org Wed Apr  1 02:43:45 2026
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 31 Mar 2026 17:39:02 -0700
+Subject: drm/amd/display: Reject modes with too high pixel clock on DCE6-10
+To: stable@vger.kernel.org
+Cc: "Alex Deucher" <alexander.deucher@amd.com>, "Christian König" <christian.koenig@amd.com>, "Xinhui Pan" <Xinhui.Pan@amd.com>, "David Airlie" <airlied@gmail.com>, "Simona Vetter" <simona@ffwll.ch>, "Harry Wentland" <harry.wentland@amd.com>, "Leo Li" <sunpeng.li@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "Ray Wu" <ray.wu@amd.com>, "Wayne Lin" <wayne.lin@amd.com>, "Mario Limonciello" <Mario.Limonciello@amd.com>, "Roman Li" <Roman.Li@amd.com>, "Eric Yang" <Eric.Yang2@amd.com>, "Tony Cheng" <Tony.Cheng@amd.com>, "Mauro Rossi" <issor.oruam@gmail.com>, "Timur Kristóf" <timur.kristof@gmail.com>, "Alex Hung" <alex.hung@amd.com>, amd-gfx@lists.freedesktop.org (open list:RADEON and AMDGPU DRM DRIVERS), dri-devel@lists.freedesktop.org (open list:DRM DRIVERS), linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260401003908.3438-5-rosenp@gmail.com>
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+[ Upstream commit 118800b0797a046adaa2a8e9dee9b971b78802a7 ]
+
+Reject modes with a pixel clock higher than the maximum display
+clock. Use 400 MHz as a fallback value when the maximum display
+clock is not known. Pixel clocks that are higher than the display
+clock just won't work and are not supported.
+
+With the addition of the YUV422        fallback, DC can now accidentally
+select a mode requiring higher pixel clock than actually supported
+when the DP version supports the required bandwidth but the clock
+is otherwise too high for the display engine. DCE 6-10 don't
+support these modes but they don't have a bandwidth calculation
+to reject them properly.
+
+Fixes: db291ed1732e ("drm/amd/display: Add fallback path for YCBCR422")
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c      |    3 +++
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c     |    5 +++++
+ drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c            |   10 +++++++++-
+ drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c |   10 +++++++++-
+ drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c   |   10 +++++++++-
+ 5 files changed, 35 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
+@@ -460,6 +460,9 @@ void dce_clk_mgr_construct(
+               clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
+       clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID;
++      base->clks.max_supported_dispclk_khz =
++              clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
++
+       dce_clock_read_integrated_info(clk_mgr);
+       dce_clock_read_ss_info(clk_mgr);
+ }
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c
+@@ -147,6 +147,8 @@ void dce60_clk_mgr_construct(
+               struct dc_context *ctx,
+               struct clk_mgr_internal *clk_mgr)
+ {
++      struct clk_mgr *base = &clk_mgr->base;
++
+       dce_clk_mgr_construct(ctx, clk_mgr);
+       memcpy(clk_mgr->max_clks_by_state,
+@@ -157,5 +159,8 @@ void dce60_clk_mgr_construct(
+       clk_mgr->clk_mgr_shift = &disp_clk_shift;
+       clk_mgr->clk_mgr_mask = &disp_clk_mask;
+       clk_mgr->base.funcs = &dce60_funcs;
++
++      base->clks.max_supported_dispclk_khz =
++              clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
+ }
+--- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
+@@ -34,6 +34,7 @@
+ #include "stream_encoder.h"
+ #include "resource.h"
++#include "clk_mgr.h"
+ #include "include/irq_service_interface.h"
+ #include "irq/dce60/irq_service_dce60.h"
+ #include "dce110/dce110_timing_generator.h"
+@@ -870,10 +871,17 @@ static bool dce60_validate_bandwidth(
+ {
+       int i;
+       bool at_least_one_pipe = false;
++      struct dc_stream_state *stream = NULL;
++      const uint32_t max_pix_clk_khz = max(dc->clk_mgr->clks.max_supported_dispclk_khz, 400000);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+-              if (context->res_ctx.pipe_ctx[i].stream)
++              stream = context->res_ctx.pipe_ctx[i].stream;
++              if (stream) {
+                       at_least_one_pipe = true;
++
++                      if (stream->timing.pix_clk_100hz >= max_pix_clk_khz * 10)
++                              return DC_FAIL_BANDWIDTH_VALIDATE;
++              }
+       }
+       if (at_least_one_pipe) {
+--- a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
+@@ -29,6 +29,7 @@
+ #include "stream_encoder.h"
+ #include "resource.h"
++#include "clk_mgr.h"
+ #include "include/irq_service_interface.h"
+ #include "virtual/virtual_stream_encoder.h"
+ #include "dce110/dce110_resource.h"
+@@ -843,10 +844,17 @@ static bool dce100_validate_bandwidth(
+ {
+       int i;
+       bool at_least_one_pipe = false;
++      struct dc_stream_state *stream = NULL;
++      const uint32_t max_pix_clk_khz = max(dc->clk_mgr->clks.max_supported_dispclk_khz, 400000);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+-              if (context->res_ctx.pipe_ctx[i].stream)
++              stream = context->res_ctx.pipe_ctx[i].stream;
++              if (stream) {
+                       at_least_one_pipe = true;
++
++                      if (stream->timing.pix_clk_100hz >= max_pix_clk_khz * 10)
++                              return DC_FAIL_BANDWIDTH_VALIDATE;
++              }
+       }
+       if (at_least_one_pipe) {
+--- a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
+@@ -32,6 +32,7 @@
+ #include "stream_encoder.h"
+ #include "resource.h"
++#include "clk_mgr.h"
+ #include "include/irq_service_interface.h"
+ #include "irq/dce80/irq_service_dce80.h"
+ #include "dce110/dce110_timing_generator.h"
+@@ -876,10 +877,17 @@ static bool dce80_validate_bandwidth(
+ {
+       int i;
+       bool at_least_one_pipe = false;
++      struct dc_stream_state *stream = NULL;
++      const uint32_t max_pix_clk_khz = max(dc->clk_mgr->clks.max_supported_dispclk_khz, 400000);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+-              if (context->res_ctx.pipe_ctx[i].stream)
++              stream = context->res_ctx.pipe_ctx[i].stream;
++              if (stream) {
+                       at_least_one_pipe = true;
++
++                      if (stream->timing.pix_clk_100hz >= max_pix_clk_khz * 10)
++                              return DC_FAIL_BANDWIDTH_VALIDATE;
++              }
+       }
+       if (at_least_one_pipe) {
diff --git a/queue-6.12/drm-amd-pm-disable-od_fan_curve-if-temp-or-pwm-range-invalid-for-smu-v13.patch b/queue-6.12/drm-amd-pm-disable-od_fan_curve-if-temp-or-pwm-range-invalid-for-smu-v13.patch
new file mode 100644 (file)
index 0000000..e02825c
--- /dev/null
@@ -0,0 +1,148 @@
+From stable+bounces-232829-greg=kroah.com@vger.kernel.org Wed Apr  1 19:17:47 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  1 Apr 2026 13:06:47 -0400
+Subject: drm/amd/pm: disable OD_FAN_CURVE if temp or pwm range invalid for smu v13
+To: stable@vger.kernel.org
+Cc: Yang Wang <kevinyang.wang@amd.com>, Alex Deucher <alexander.deucher@amd.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260401170647.151337-1-sashal@kernel.org>
+
+From: Yang Wang <kevinyang.wang@amd.com>
+
+[ Upstream commit 3e6dd28a11083e83e11a284d99fcc9eb748c321c ]
+
+Forcibly disable the OD_FAN_CURVE feature when temperature or PWM range is invalid,
+otherwise PMFW will reject this configuration on smu v13.0.x
+
+example:
+$ sudo cat /sys/bus/pci/devices/<BDF>/gpu_od/fan_ctrl/fan_curve
+
+OD_FAN_CURVE:
+0: 0C 0%
+1: 0C 0%
+2: 0C 0%
+3: 0C 0%
+4: 0C 0%
+OD_RANGE:
+FAN_CURVE(hotspot temp): 0C 0C
+FAN_CURVE(fan speed): 0% 0%
+
+$ echo "0 50 40" | sudo tee fan_curve
+
+kernel log:
+[  756.442527] amdgpu 0000:03:00.0: amdgpu: Fan curve temp setting(50) must be within [0, 0]!
+[  777.345800] amdgpu 0000:03:00.0: amdgpu: Fan curve temp setting(50) must be within [0, 0]!
+
+Closes: https://github.com/ROCm/amdgpu/issues/208
+Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 470891606c5a97b1d0d937e0aa67a3bed9fcb056)
+Cc: stable@vger.kernel.org
+[ adapted forward declaration placement to existing FEATURE_MASK macro ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c |   33 ++++++++++++++++++-
+ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c |   33 ++++++++++++++++++-
+ 2 files changed, 64 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+@@ -59,6 +59,10 @@
+ #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
++static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
++                                            int od_feature_bit,
++                                            int32_t *min, int32_t *max);
++
+ #define FEATURE_MASK(feature) (1ULL << feature)
+ #define SMC_DPM_FEATURE ( \
+       FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)     | \
+@@ -1082,8 +1086,35 @@ static bool smu_v13_0_0_is_od_feature_su
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
+       const OverDriveLimits_t * const overdrive_upperlimits =
+                               &pptable->SkuTable.OverDriveLimitsBasicMax;
++      int32_t min_value, max_value;
++      bool feature_enabled;
++
++      switch (od_feature_bit) {
++      case PP_OD_FEATURE_FAN_CURVE_BIT:
++              feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
++              if (feature_enabled) {
++                      smu_v13_0_0_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
++                                                        &min_value, &max_value);
++                      if (!min_value && !max_value) {
++                              feature_enabled = false;
++                              goto out;
++                      }
++
++                      smu_v13_0_0_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
++                                                        &min_value, &max_value);
++                      if (!min_value && !max_value) {
++                              feature_enabled = false;
++                              goto out;
++                      }
++              }
++              break;
++      default:
++              feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
++              break;
++      }
+-      return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
++out:
++      return feature_enabled;
+ }
+ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+@@ -59,6 +59,10 @@
+ #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
++static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
++                                            int od_feature_bit,
++                                            int32_t *min, int32_t *max);
++
+ #define FEATURE_MASK(feature) (1ULL << feature)
+ #define SMC_DPM_FEATURE ( \
+       FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)     | \
+@@ -1071,8 +1075,35 @@ static bool smu_v13_0_7_is_od_feature_su
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
+       const OverDriveLimits_t * const overdrive_upperlimits =
+                               &pptable->SkuTable.OverDriveLimitsBasicMax;
++      int32_t min_value, max_value;
++      bool feature_enabled;
++
++      switch (od_feature_bit) {
++      case PP_OD_FEATURE_FAN_CURVE_BIT:
++              feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
++              if (feature_enabled) {
++                      smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
++                                                        &min_value, &max_value);
++                      if (!min_value && !max_value) {
++                              feature_enabled = false;
++                              goto out;
++                      }
++
++                      smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
++                                                        &min_value, &max_value);
++                      if (!min_value && !max_value) {
++                              feature_enabled = false;
++                              goto out;
++                      }
++              }
++              break;
++      default:
++              feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
++              break;
++      }
+-      return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
++out:
++      return feature_enabled;
+ }
+ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
diff --git a/queue-6.12/ext4-publish-jinode-after-initialization.patch b/queue-6.12/ext4-publish-jinode-after-initialization.patch
new file mode 100644 (file)
index 0000000..8a8441b
--- /dev/null
@@ -0,0 +1,152 @@
+From stable+bounces-233071-greg=kroah.com@vger.kernel.org Thu Apr  2 18:56:36 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Apr 2026 12:51:19 -0400
+Subject: ext4: publish jinode after initialization
+To: stable@vger.kernel.org
+Cc: Li Chen <me@linux.beauty>, Jan Kara <jack@suse.cz>, Theodore Ts'o <tytso@mit.edu>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260402165119.1482773-1-sashal@kernel.org>
+
+From: Li Chen <me@linux.beauty>
+
+[ Upstream commit 1aec30021edd410b986c156f195f3d23959a9d11 ]
+
+ext4_inode_attach_jinode() publishes ei->jinode to concurrent users.
+It used to set ei->jinode before jbd2_journal_init_jbd_inode(),
+allowing a reader to observe a non-NULL jinode with i_vfs_inode
+still unset.
+
+The fast commit flush path can then pass this jinode to
+jbd2_wait_inode_data(), which dereferences i_vfs_inode->i_mapping and
+may crash.
+
+Below is the crash I observe:
+```
+BUG: unable to handle page fault for address: 000000010beb47f4
+PGD 110e51067 P4D 110e51067 PUD 0
+Oops: Oops: 0000 [#1] SMP NOPTI
+CPU: 1 UID: 0 PID: 4850 Comm: fc_fsync_bench_ Not tainted 6.18.0-00764-g795a690c06a5 #1 PREEMPT(voluntary)
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.17.0-2-2 04/01/2014
+RIP: 0010:xas_find_marked+0x3d/0x2e0
+Code: e0 03 48 83 f8 02 0f 84 f0 01 00 00 48 8b 47 08 48 89 c3 48 39 c6 0f 82 fd 01 00 00 48 85 c9 74 3d 48 83 f9 03 77 63 4c 8b 0f <49> 8b 71 08 48 c7 47 18 00 00 00 00 48 89 f1 83 e1 03 48 83 f9 02
+RSP: 0018:ffffbbee806e7bf0 EFLAGS: 00010246
+RAX: 000000000010beb4 RBX: 000000000010beb4 RCX: 0000000000000003
+RDX: 0000000000000001 RSI: 0000002000300000 RDI: ffffbbee806e7c10
+RBP: 0000000000000001 R08: 0000002000300000 R09: 000000010beb47ec
+R10: ffff9ea494590090 R11: 0000000000000000 R12: 0000002000300000
+R13: ffffbbee806e7c90 R14: ffff9ea494513788 R15: ffffbbee806e7c88
+FS: 00007fc2f9e3e6c0(0000) GS:ffff9ea6b1444000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 000000010beb47f4 CR3: 0000000119ac5000 CR4: 0000000000750ef0
+PKRU: 55555554
+Call Trace:
+<TASK>
+filemap_get_folios_tag+0x87/0x2a0
+__filemap_fdatawait_range+0x5f/0xd0
+? srso_alias_return_thunk+0x5/0xfbef5
+? __schedule+0x3e7/0x10c0
+? srso_alias_return_thunk+0x5/0xfbef5
+? srso_alias_return_thunk+0x5/0xfbef5
+? srso_alias_return_thunk+0x5/0xfbef5
+? preempt_count_sub+0x5f/0x80
+? srso_alias_return_thunk+0x5/0xfbef5
+? cap_safe_nice+0x37/0x70
+? srso_alias_return_thunk+0x5/0xfbef5
+? preempt_count_sub+0x5f/0x80
+? srso_alias_return_thunk+0x5/0xfbef5
+filemap_fdatawait_range_keep_errors+0x12/0x40
+ext4_fc_commit+0x697/0x8b0
+? ext4_file_write_iter+0x64b/0x950
+? srso_alias_return_thunk+0x5/0xfbef5
+? preempt_count_sub+0x5f/0x80
+? srso_alias_return_thunk+0x5/0xfbef5
+? vfs_write+0x356/0x480
+? srso_alias_return_thunk+0x5/0xfbef5
+? preempt_count_sub+0x5f/0x80
+ext4_sync_file+0xf7/0x370
+do_fsync+0x3b/0x80
+? syscall_trace_enter+0x108/0x1d0
+__x64_sys_fdatasync+0x16/0x20
+do_syscall_64+0x62/0x2c0
+entry_SYSCALL_64_after_hwframe+0x76/0x7e
+...
+```
+
+Fix this by initializing the jbd2_inode first.
+Use smp_wmb() and WRITE_ONCE() to publish ei->jinode after
+initialization. Readers use READ_ONCE() to fetch the pointer.
+
+Fixes: a361293f5fede ("jbd2: Fix oops in jbd2_journal_file_inode()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Li Chen <me@linux.beauty>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20260225082617.147957-1-me@linux.beauty
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+[ adapted READ_ONCE(ei->jinode) to use pos->jinode ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c |    4 ++--
+ fs/ext4/inode.c       |   15 +++++++++++----
+ 2 files changed, 13 insertions(+), 6 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -997,7 +997,7 @@ static int ext4_fc_submit_inode_data_all
+                       finish_wait(&ei->i_fc_wait, &wait);
+               }
+               spin_unlock(&sbi->s_fc_lock);
+-              ret = jbd2_submit_inode_data(journal, ei->jinode);
++              ret = jbd2_submit_inode_data(journal, READ_ONCE(ei->jinode));
+               if (ret)
+                       return ret;
+               spin_lock(&sbi->s_fc_lock);
+@@ -1022,7 +1022,7 @@ static int ext4_fc_wait_inode_data_all(j
+                       continue;
+               spin_unlock(&sbi->s_fc_lock);
+-              ret = jbd2_wait_inode_data(journal, pos->jinode);
++              ret = jbd2_wait_inode_data(journal, READ_ONCE(pos->jinode));
+               if (ret)
+                       return ret;
+               spin_lock(&sbi->s_fc_lock);
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -128,6 +128,8 @@ void ext4_inode_csum_set(struct inode *i
+ static inline int ext4_begin_ordered_truncate(struct inode *inode,
+                                             loff_t new_size)
+ {
++      struct jbd2_inode *jinode = READ_ONCE(EXT4_I(inode)->jinode);
++
+       trace_ext4_begin_ordered_truncate(inode, new_size);
+       /*
+        * If jinode is zero, then we never opened the file for
+@@ -135,10 +137,10 @@ static inline int ext4_begin_ordered_tru
+        * jbd2_journal_begin_ordered_truncate() since there's no
+        * outstanding writes we need to flush.
+        */
+-      if (!EXT4_I(inode)->jinode)
++      if (!jinode)
+               return 0;
+       return jbd2_journal_begin_ordered_truncate(EXT4_JOURNAL(inode),
+-                                                 EXT4_I(inode)->jinode,
++                                                 jinode,
+                                                  new_size);
+ }
+@@ -4120,8 +4122,13 @@ int ext4_inode_attach_jinode(struct inod
+                       spin_unlock(&inode->i_lock);
+                       return -ENOMEM;
+               }
+-              ei->jinode = jinode;
+-              jbd2_journal_init_jbd_inode(ei->jinode, inode);
++              jbd2_journal_init_jbd_inode(jinode, inode);
++              /*
++               * Publish ->jinode only after it is fully initialized so that
++               * readers never observe a partially initialized jbd2_inode.
++               */
++              smp_wmb();
++              WRITE_ONCE(ei->jinode, jinode);
+               jinode = NULL;
+       }
+       spin_unlock(&inode->i_lock);
diff --git a/queue-6.12/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch b/queue-6.12/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch
new file mode 100644 (file)
index 0000000..319dae5
--- /dev/null
@@ -0,0 +1,121 @@
+From stable+bounces-231405-greg=kroah.com@vger.kernel.org Tue Mar 31 13:42:48 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Mar 2026 07:39:06 -0400
+Subject: mm/huge_memory: fix folio isn't locked in softleaf_to_folio()
+To: stable@vger.kernel.org
+Cc: Jinjiang Tu <tujinjiang@huawei.com>, "David Hildenbrand (Arm)" <david@kernel.org>, "Lorenzo Stoakes (Oracle)" <ljs@kernel.org>, Barry Song <baohua@kernel.org>, Kefeng Wang <wangkefeng.wang@huawei.com>, Liam Howlett <liam.howlett@oracle.com>, Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>, Nanyong Sun <sunnanyong@huawei.com>, Ryan Roberts <ryan.roberts@arm.com>, Suren Baghdasaryan <surenb@google.com>, Vlastimil Babka <vbabka@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260331113906.2080339-1-sashal@kernel.org>
+
+From: Jinjiang Tu <tujinjiang@huawei.com>
+
+[ Upstream commit 4c5e7f0fcd592801c9cc18f29f80fbee84eb8669 ]
+
+On arm64 server, we found folio that get from migration entry isn't locked
+in softleaf_to_folio().  This issue triggers when mTHP splitting and
+zap_nonpresent_ptes() races, and the root cause is lack of memory barrier
+in softleaf_to_folio().  The race is as follows:
+
+       CPU0                                             CPU1
+
+deferred_split_scan()                              zap_nonpresent_ptes()
+  lock folio
+  split_folio()
+    unmap_folio()
+      change ptes to migration entries
+    __split_folio_to_order()                         softleaf_to_folio()
+      set flags(including PG_locked) for tail pages    folio = pfn_folio(softleaf_to_pfn(entry))
+      smp_wmb()                                        VM_WARN_ON_ONCE(!folio_test_locked(folio))
+      prep_compound_page() for tail pages
+
+In __split_folio_to_order(), smp_wmb() guarantees page flags of tail pages
+are visible before the tail page becomes non-compound.  smp_wmb() should
+be paired with smp_rmb() in softleaf_to_folio(), which is missed.  As a
+result, if zap_nonpresent_ptes() accesses migration entry that stores tail
+pfn, softleaf_to_folio() may see the updated compound_head of tail page
+before page->flags.
+
+This issue will trigger VM_WARN_ON_ONCE() in pfn_swap_entry_folio()
+because of the race between folio split and zap_nonpresent_ptes()
+leading to a folio incorrectly undergoing modification without a folio
+lock being held.
+
+This is a BUG_ON() before commit 93976a20345b ("mm: eliminate further
+swapops predicates"), which in merged in v6.19-rc1.
+
+To fix it, add missing smp_rmb() if the softleaf entry is migration entry
+in softleaf_to_folio() and softleaf_to_page().
+
+[tujinjiang@huawei.com: update function name and comments]
+  Link: https://lkml.kernel.org/r/20260321075214.3305564-1-tujinjiang@huawei.com
+Link: https://lkml.kernel.org/r/20260319012541.4158561-1-tujinjiang@huawei.com
+Fixes: e9b61f19858a ("thp: reintroduce split_huge_page()")
+Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Barry Song <baohua@kernel.org>
+Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Nanyong Sun <sunnanyong@huawei.com>
+Cc: Ryan Roberts <ryan.roberts@arm.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ applied fix to swapops.h using old pfn_swap_entry/swp_entry_t naming ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/swapops.h |   27 +++++++++++++++++++--------
+ 1 file changed, 19 insertions(+), 8 deletions(-)
+
+--- a/include/linux/swapops.h
++++ b/include/linux/swapops.h
+@@ -484,15 +484,29 @@ static inline int pte_none_mostly(pte_t
+       return pte_none(pte) || is_pte_marker(pte);
+ }
+-static inline struct page *pfn_swap_entry_to_page(swp_entry_t entry)
++static inline void swap_entry_migration_sync(swp_entry_t entry,
++              struct folio *folio)
+ {
+-      struct page *p = pfn_to_page(swp_offset_pfn(entry));
++      /*
++       * Ensure we do not race with split, which might alter tail pages into new
++       * folios and thus result in observing an unlocked folio.
++       * This matches the write barrier in __split_folio_to_order().
++       */
++      smp_rmb();
+       /*
+        * Any use of migration entries may only occur while the
+        * corresponding page is locked
+        */
+-      BUG_ON(is_migration_entry(entry) && !PageLocked(p));
++      BUG_ON(!folio_test_locked(folio));
++}
++
++static inline struct page *pfn_swap_entry_to_page(swp_entry_t entry)
++{
++      struct page *p = pfn_to_page(swp_offset_pfn(entry));
++
++      if (is_migration_entry(entry))
++              swap_entry_migration_sync(entry, page_folio(p));
+       return p;
+ }
+@@ -501,11 +515,8 @@ static inline struct folio *pfn_swap_ent
+ {
+       struct folio *folio = pfn_folio(swp_offset_pfn(entry));
+-      /*
+-       * Any use of migration entries may only occur while the
+-       * corresponding folio is locked
+-       */
+-      BUG_ON(is_migration_entry(entry) && !folio_test_locked(folio));
++      if (is_migration_entry(entry))
++              swap_entry_migration_sync(entry, folio);
+       return folio;
+ }
diff --git a/queue-6.12/mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch b/queue-6.12/mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch
new file mode 100644 (file)
index 0000000..bbecca6
--- /dev/null
@@ -0,0 +1,103 @@
+From stable+bounces-232830-greg=kroah.com@vger.kernel.org Wed Apr  1 19:17:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  1 Apr 2026 13:06:43 -0400
+Subject: mm/memory: fix PMD/PUD checks in follow_pfnmap_start()
+To: stable@vger.kernel.org
+Cc: "David Hildenbrand (Arm)" <david@kernel.org>, "Mike Rapoport (Microsoft)" <rppt@kernel.org>, "Lorenzo Stoakes (Oracle)" <ljs@kernel.org>, Liam Howlett <liam.howlett@oracle.com>, Michal Hocko <mhocko@suse.com>, Peter Xu <peterx@redhat.com>, Suren Baghdasaryan <surenb@google.com>, Vlastimil Babka <vbabka@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260401170643.151278-2-sashal@kernel.org>
+
+From: "David Hildenbrand (Arm)" <david@kernel.org>
+
+[ Upstream commit ffef67b93aa352b34e6aeba3d52c19a63885409a ]
+
+follow_pfnmap_start() suffers from two problems:
+
+(1) We are not re-fetching the pmd/pud after taking the PTL
+
+Therefore, we are not properly stabilizing what the lock actually
+protects.  If there is concurrent zapping, we would indicate to the
+caller that we found an entry, however, that entry might already have
+been invalidated, or contain a different PFN after taking the lock.
+
+Properly use pmdp_get() / pudp_get() after taking the lock.
+
+(2) pmd_leaf() / pud_leaf() are not well defined on non-present entries
+
+pmd_leaf()/pud_leaf() could wrongly trigger on non-present entries.
+
+There is no real guarantee that pmd_leaf()/pud_leaf() returns something
+reasonable on non-present entries.  Most architectures indeed either
+perform a present check or make it work by smart use of flags.
+
+However, for example loongarch checks the _PAGE_HUGE flag in pmd_leaf(),
+and always sets the _PAGE_HUGE flag in __swp_entry_to_pmd().  Whereby
+pmd_trans_huge() explicitly checks pmd_present(), pmd_leaf() does not do
+that.
+
+Let's check pmd_present()/pud_present() before assuming "the is a present
+PMD leaf" when spotting pmd_leaf()/pud_leaf(), like other page table
+handling code that traverses user page tables does.
+
+Given that non-present PMD entries are likely rare in VM_IO|VM_PFNMAP, (1)
+is likely more relevant than (2).  It is questionable how often (1) would
+actually trigger, but let's CC stable to be sure.
+
+This was found by code inspection.
+
+Link: https://lkml.kernel.org/r/20260323-follow_pfnmap_fix-v1-1-5b0ec10872b3@kernel.org
+Fixes: 6da8e9634bb7 ("mm: new follow_pfnmap API")
+Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
+Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memory.c |   18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -6457,11 +6457,16 @@ retry:
+       pudp = pud_offset(p4dp, address);
+       pud = pudp_get(pudp);
+-      if (pud_none(pud))
++      if (!pud_present(pud))
+               goto out;
+       if (pud_leaf(pud)) {
+               lock = pud_lock(mm, pudp);
+-              if (!unlikely(pud_leaf(pud))) {
++              pud = pudp_get(pudp);
++
++              if (unlikely(!pud_present(pud))) {
++                      spin_unlock(lock);
++                      goto out;
++              } else if (unlikely(!pud_leaf(pud))) {
+                       spin_unlock(lock);
+                       goto retry;
+               }
+@@ -6473,9 +6478,16 @@ retry:
+       pmdp = pmd_offset(pudp, address);
+       pmd = pmdp_get_lockless(pmdp);
++      if (!pmd_present(pmd))
++              goto out;
+       if (pmd_leaf(pmd)) {
+               lock = pmd_lock(mm, pmdp);
+-              if (!unlikely(pmd_leaf(pmd))) {
++              pmd = pmdp_get(pmdp);
++
++              if (unlikely(!pmd_present(pmd))) {
++                      spin_unlock(lock);
++                      goto out;
++              } else if (unlikely(!pmd_leaf(pmd))) {
+                       spin_unlock(lock);
+                       goto retry;
+               }
diff --git a/queue-6.12/mm-replace-read_once-with-standard-page-table-accessors.patch b/queue-6.12/mm-replace-read_once-with-standard-page-table-accessors.patch
new file mode 100644 (file)
index 0000000..0797988
--- /dev/null
@@ -0,0 +1,143 @@
+From stable+bounces-232828-greg=kroah.com@vger.kernel.org Wed Apr  1 19:17:48 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  1 Apr 2026 13:06:42 -0400
+Subject: mm: replace READ_ONCE() with standard page table accessors
+To: stable@vger.kernel.org
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>, David Hildenbrand <david@redhat.com>, Lance Yang <lance.yang@linux.dev>, Wei Yang <richard.weiyang@gmail.com>, Dev Jain <dev.jain@arm.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260401170643.151278-1-sashal@kernel.org>
+
+From: Anshuman Khandual <anshuman.khandual@arm.com>
+
+[ Upstream commit c0efdb373c3aaacb32db59cadb0710cac13e44ae ]
+
+Replace all READ_ONCE() with a standard page table accessors i.e
+pxdp_get() that defaults into READ_ONCE() in cases where platform does not
+override.
+
+Link: https://lkml.kernel.org/r/20251007063100.2396936-1-anshuman.khandual@arm.com
+Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Acked-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Lance Yang <lance.yang@linux.dev>
+Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
+Reviewed-by: Dev Jain <dev.jain@arm.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: ffef67b93aa3 ("mm/memory: fix PMD/PUD checks in follow_pfnmap_start()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/gup.c            |   10 +++++-----
+ mm/hmm.c            |    2 +-
+ mm/memory.c         |    4 ++--
+ mm/mprotect.c       |    2 +-
+ mm/sparse-vmemmap.c |    2 +-
+ mm/vmscan.c         |    2 +-
+ 6 files changed, 11 insertions(+), 11 deletions(-)
+
+--- a/mm/gup.c
++++ b/mm/gup.c
+@@ -1013,7 +1013,7 @@ static struct page *follow_pud_mask(stru
+       struct mm_struct *mm = vma->vm_mm;
+       pudp = pud_offset(p4dp, address);
+-      pud = READ_ONCE(*pudp);
++      pud = pudp_get(pudp);
+       if (!pud_present(pud))
+               return no_page_table(vma, flags, address);
+       if (pud_leaf(pud)) {
+@@ -1038,7 +1038,7 @@ static struct page *follow_p4d_mask(stru
+       p4d_t *p4dp, p4d;
+       p4dp = p4d_offset(pgdp, address);
+-      p4d = READ_ONCE(*p4dp);
++      p4d = p4dp_get(p4dp);
+       BUILD_BUG_ON(p4d_leaf(p4d));
+       if (!p4d_present(p4d) || p4d_bad(p4d))
+@@ -3301,7 +3301,7 @@ static int gup_fast_pud_range(p4d_t *p4d
+       pudp = pud_offset_lockless(p4dp, p4d, addr);
+       do {
+-              pud_t pud = READ_ONCE(*pudp);
++              pud_t pud = pudp_get(pudp);
+               next = pud_addr_end(addr, end);
+               if (unlikely(!pud_present(pud)))
+@@ -3327,7 +3327,7 @@ static int gup_fast_p4d_range(pgd_t *pgd
+       p4dp = p4d_offset_lockless(pgdp, pgd, addr);
+       do {
+-              p4d_t p4d = READ_ONCE(*p4dp);
++              p4d_t p4d = p4dp_get(p4dp);
+               next = p4d_addr_end(addr, end);
+               if (!p4d_present(p4d))
+@@ -3349,7 +3349,7 @@ static void gup_fast_pgd_range(unsigned
+       pgdp = pgd_offset(current->mm, addr);
+       do {
+-              pgd_t pgd = READ_ONCE(*pgdp);
++              pgd_t pgd = pgdp_get(pgdp);
+               next = pgd_addr_end(addr, end);
+               if (pgd_none(pgd))
+--- a/mm/hmm.c
++++ b/mm/hmm.c
+@@ -423,7 +423,7 @@ static int hmm_vma_walk_pud(pud_t *pudp,
+       /* Normally we don't want to split the huge page */
+       walk->action = ACTION_CONTINUE;
+-      pud = READ_ONCE(*pudp);
++      pud = pudp_get(pudp);
+       if (!pud_present(pud)) {
+               spin_unlock(ptl);
+               return hmm_vma_walk_hole(start, end, -1, walk);
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -6451,12 +6451,12 @@ retry:
+               goto out;
+       p4dp = p4d_offset(pgdp, address);
+-      p4d = READ_ONCE(*p4dp);
++      p4d = p4dp_get(p4dp);
+       if (p4d_none(p4d) || unlikely(p4d_bad(p4d)))
+               goto out;
+       pudp = pud_offset(p4dp, address);
+-      pud = READ_ONCE(*pudp);
++      pud = pudp_get(pudp);
+       if (pud_none(pud))
+               goto out;
+       if (pud_leaf(pud)) {
+--- a/mm/mprotect.c
++++ b/mm/mprotect.c
+@@ -447,7 +447,7 @@ again:
+                       break;
+               }
+-              pud = READ_ONCE(*pudp);
++              pud = pudp_get(pudp);
+               if (pud_none(pud))
+                       continue;
+--- a/mm/sparse-vmemmap.c
++++ b/mm/sparse-vmemmap.c
+@@ -337,7 +337,7 @@ int __meminit vmemmap_populate_hugepages
+                       return -ENOMEM;
+               pmd = pmd_offset(pud, addr);
+-              if (pmd_none(READ_ONCE(*pmd))) {
++              if (pmd_none(pmdp_get(pmd))) {
+                       void *p;
+                       p = vmemmap_alloc_block_buf(PMD_SIZE, node, altmap);
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -3631,7 +3631,7 @@ static int walk_pud_range(p4d_t *p4d, un
+       pud = pud_offset(p4d, start & P4D_MASK);
+ restart:
+       for (i = pud_index(start), addr = start; addr != end; i++, addr = next) {
+-              pud_t val = READ_ONCE(pud[i]);
++              pud_t val = pudp_get(pud + i);
+               next = pud_addr_end(addr, end);
diff --git a/queue-6.12/mptcp-fix-lock-class-name-family-in-pm_nl_create_listen_socket.patch b/queue-6.12/mptcp-fix-lock-class-name-family-in-pm_nl_create_listen_socket.patch
new file mode 100644 (file)
index 0000000..bbbafe6
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-233080-greg=kroah.com@vger.kernel.org Thu Apr  2 19:35:28 2026
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Thu,  2 Apr 2026 19:33:10 +0200
+Subject: MPTCP: fix lock class name family in pm_nl_create_listen_socket
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: MPTCP Upstream <mptcp@lists.linux.dev>, Li Xiasong <lixiasong1@huawei.com>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Jakub Kicinski <kuba@kernel.org>
+Message-ID: <20260402173309.3282169-2-matttbe@kernel.org>
+
+From: Li Xiasong <lixiasong1@huawei.com>
+
+commit 7ab4a7c5d969642782b8a5b608da0dd02aa9f229 upstream.
+
+In mptcp_pm_nl_create_listen_socket(), use entry->addr.family
+instead of sk->sk_family for lock class setup. The 'sk' parameter
+is a netlink socket, not the MPTCP subflow socket being created.
+
+Fixes: cee4034a3db1 ("mptcp: fix lockdep false positive in mptcp_pm_nl_create_listen_socket()")
+Signed-off-by: Li Xiasong <lixiasong1@huawei.com>
+Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20260319112159.3118874-1-lixiasong1@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Conflict in pm_kernel.c, because commit 8617e85e04bd ("mptcp: pm:
+  split in-kernel PM specific code") is not in this version, and moves
+  code from pm_netlink.c to pm_kernel.c. ]
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/pm_netlink.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1186,7 +1186,7 @@ static struct lock_class_key mptcp_keys[
+ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
+                                           struct mptcp_pm_addr_entry *entry)
+ {
+-      bool is_ipv6 = sk->sk_family == AF_INET6;
++      bool is_ipv6 = entry->addr.family == AF_INET6;
+       int addrlen = sizeof(struct sockaddr_in);
+       struct sockaddr_storage addr;
+       struct sock *newsk, *ssk;
diff --git a/queue-6.12/net-correctly-handle-tunneled-traffic-on-ipv6_csum-gso-fallback.patch b/queue-6.12/net-correctly-handle-tunneled-traffic-on-ipv6_csum-gso-fallback.patch
new file mode 100644 (file)
index 0000000..5097779
--- /dev/null
@@ -0,0 +1,77 @@
+From stable+bounces-232529-greg=kroah.com@vger.kernel.org Tue Mar 31 19:48:09 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Mar 2026 13:09:35 -0400
+Subject: net: correctly handle tunneled traffic on IPV6_CSUM GSO fallback
+To: stable@vger.kernel.org
+Cc: Willem de Bruijn <willemb@google.com>, Tangxin Xie <xietangxin@yeah.net>, Paolo Abeni <pabeni@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260331170935.2813592-1-sashal@kernel.org>
+
+From: Willem de Bruijn <willemb@google.com>
+
+[ Upstream commit c4336a07eb6b2526dc2b62928b5104b41a7f81f5 ]
+
+NETIF_F_IPV6_CSUM only advertises support for checksum offload of
+packets without IPv6 extension headers. Packets with extension
+headers must fall back onto software checksumming. Since TSO
+depends on checksum offload, those must revert to GSO.
+
+The below commit introduces that fallback. It always checks
+network header length. For tunneled packets, the inner header length
+must be checked instead. Extend the check accordingly.
+
+A special case is tunneled packets without inner IP protocol. Such as
+RFC 6951 SCTP in UDP. Those are not standard IPv6 followed by
+transport header either, so also must revert to the software GSO path.
+
+Cc: stable@vger.kernel.org
+Fixes: 864e3396976e ("net: gso: Forbid IPv6 TSO with extensions on devices with only IPV6_CSUM")
+Reported-by: Tangxin Xie <xietangxin@yeah.net>
+Closes: https://lore.kernel.org/netdev/0414e7e2-9a1c-4d7c-a99d-b9039cf68f40@yeah.net/
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260320190148.2409107-1-willemdebruijn.kernel@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/dev.c |   22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -3579,6 +3579,22 @@ static netdev_features_t dflt_features_c
+       return vlan_features_check(skb, features);
+ }
++static bool skb_gso_has_extension_hdr(const struct sk_buff *skb)
++{
++      if (!skb->encapsulation)
++              return ((skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6 ||
++                       (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
++                        vlan_get_protocol(skb) == htons(ETH_P_IPV6))) &&
++                      skb_transport_header_was_set(skb) &&
++                      skb_network_header_len(skb) != sizeof(struct ipv6hdr));
++      else
++              return (!skb_inner_network_header_was_set(skb) ||
++                      ((skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6 ||
++                        (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
++                         inner_ip_hdr(skb)->version == 6)) &&
++                       skb_inner_network_header_len(skb) != sizeof(struct ipv6hdr)));
++}
++
+ static netdev_features_t gso_features_check(const struct sk_buff *skb,
+                                           struct net_device *dev,
+                                           netdev_features_t features)
+@@ -3625,11 +3641,7 @@ static netdev_features_t gso_features_ch
+        * so neither does TSO that depends on it.
+        */
+       if (features & NETIF_F_IPV6_CSUM &&
+-          (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6 ||
+-           (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
+-            vlan_get_protocol(skb) == htons(ETH_P_IPV6))) &&
+-          skb_transport_header_was_set(skb) &&
+-          skb_network_header_len(skb) != sizeof(struct ipv6hdr) &&
++          skb_gso_has_extension_hdr(skb) &&
+           !ipv6_has_hopopt_jumbo(skb))
+               features &= ~(NETIF_F_IPV6_CSUM | NETIF_F_TSO6 | NETIF_F_GSO_UDP_L4);
diff --git a/queue-6.12/net-mana-fix-use-after-free-in-add_adev-error-path.patch b/queue-6.12/net-mana-fix-use-after-free-in-add_adev-error-path.patch
new file mode 100644 (file)
index 0000000..ad94ce7
--- /dev/null
@@ -0,0 +1,65 @@
+From stable+bounces-232527-greg=kroah.com@vger.kernel.org Tue Mar 31 19:43:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Mar 2026 13:09:32 -0400
+Subject: net: mana: fix use-after-free in add_adev() error path
+To: stable@vger.kernel.org
+Cc: Guangshuo Li <lgs201920130244@gmail.com>, Long Li <longli@microsoft.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260331170932.2813528-1-sashal@kernel.org>
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit c4ea7d8907cf72b259bf70bd8c2e791e1c4ff70f ]
+
+If auxiliary_device_add() fails, add_adev() jumps to add_fail and calls
+auxiliary_device_uninit(adev).
+
+The auxiliary device has its release callback set to adev_release(),
+which frees the containing struct mana_adev. Since adev is embedded in
+struct mana_adev, the subsequent fall-through to init_fail and access
+to adev->id may result in a use-after-free.
+
+Fix this by saving the allocated auxiliary device id in a local
+variable before calling auxiliary_device_add(), and use that saved id
+in the cleanup path after auxiliary_device_uninit().
+
+Fixes: a69839d4327d ("net: mana: Add support for auxiliary device")
+Cc: stable@vger.kernel.org
+Reviewed-by: Long Li <longli@microsoft.com>
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Link: https://patch.msgid.link/20260323165730.945365-1-lgs201920130244@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -2823,6 +2823,7 @@ static int add_adev(struct gdma_dev *gd)
+       struct auxiliary_device *adev;
+       struct mana_adev *madev;
+       int ret;
++      int id;
+       madev = kzalloc(sizeof(*madev), GFP_KERNEL);
+       if (!madev)
+@@ -2832,7 +2833,8 @@ static int add_adev(struct gdma_dev *gd)
+       ret = mana_adev_idx_alloc();
+       if (ret < 0)
+               goto idx_fail;
+-      adev->id = ret;
++      id = ret;
++      adev->id = id;
+       adev->name = "rdma";
+       adev->dev.parent = gd->gdma_context->dev;
+@@ -2856,7 +2858,7 @@ add_fail:
+       auxiliary_device_uninit(adev);
+ init_fail:
+-      mana_adev_idx_free(adev->id);
++      mana_adev_idx_free(id);
+ idx_fail:
+       kfree(madev);
diff --git a/queue-6.12/s390-cpum_sf-cap-sampling-rate-to-prevent-lsctl-exception.patch b/queue-6.12/s390-cpum_sf-cap-sampling-rate-to-prevent-lsctl-exception.patch
new file mode 100644 (file)
index 0000000..13d03b5
--- /dev/null
@@ -0,0 +1,61 @@
+From stable+bounces-233842-greg=kroah.com@vger.kernel.org Wed Apr  8 13:06:45 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  8 Apr 2026 07:06:37 -0400
+Subject: s390/cpum_sf: Cap sampling rate to prevent lsctl exception
+To: stable@vger.kernel.org
+Cc: Thomas Richter <tmricht@linux.ibm.com>, Sumanth Korikkar <sumanthk@linux.ibm.com>, Hendrik Brueckner <brueckner@linux.ibm.com>, Vasily Gorbik <gor@linux.ibm.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260408110637.978601-2-sashal@kernel.org>
+
+From: Thomas Richter <tmricht@linux.ibm.com>
+
+[ Upstream commit 57ad0d4a00f5d3e80f33ba2da8d560c73d83dc22 ]
+
+commit fcc43a7e294f ("s390/configs: Set HZ=1000") changed the interrupt
+frequency of the system. On machines with heavy load and many perf event
+overflows, this might lead to an exception. Dmesg displays these entries:
+  [112.242542] cpum_sf: Loading sampling controls failed: op 1 err -22
+One line per CPU online.
+
+The root cause is the CPU Measurement sampling facility overflow
+adjustment. Whenever an overflow (too much samples per tick) occurs, the
+sampling rate is adjusted and increased. This was done without observing
+the maximum sampling rate limit. When the current sampling interval is
+higher than the maximum sampling rate limit, the lsctl instruction raises
+an exception. The error messages is the result of such an exception.
+Observe the upper limit when the new sampling rate is recalculated.
+
+Cc: stable@vger.kernel.org
+Fixes: 39d4a501a9ef ("s390/cpum_sf: Adjust sampling interval to avoid hitting sample limits")
+Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
+Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
+Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/perf_cpum_sf.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/arch/s390/kernel/perf_cpum_sf.c
++++ b/arch/s390/kernel/perf_cpum_sf.c
+@@ -1188,6 +1188,7 @@ static void hw_collect_samples(struct pe
+ static void hw_perf_event_update(struct perf_event *event, int flush_all)
+ {
+       unsigned long long event_overflow, sampl_overflow, num_sdb;
++      struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf);
+       struct hw_perf_event *hwc = &event->hw;
+       union hws_trailer_header prev, new;
+       struct hws_trailer_entry *te;
+@@ -1267,8 +1268,11 @@ static void hw_perf_event_update(struct
+        * are dropped.
+        * Slightly increase the interval to avoid hitting this limit.
+        */
+-      if (event_overflow)
++      if (event_overflow) {
+               SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10);
++              if (SAMPL_RATE(hwc) > cpuhw->qsi.max_sampl_rate)
++                      SAMPL_RATE(hwc) = cpuhw->qsi.max_sampl_rate;
++      }
+ }
+ static inline unsigned long aux_sdb_index(struct aux_buffer *aux,
diff --git a/queue-6.12/s390-perf_cpum_sf-convert-to-use-try_cmpxchg128.patch b/queue-6.12/s390-perf_cpum_sf-convert-to-use-try_cmpxchg128.patch
new file mode 100644 (file)
index 0000000..f643a81
--- /dev/null
@@ -0,0 +1,110 @@
+From stable+bounces-233841-greg=kroah.com@vger.kernel.org Wed Apr  8 13:06:44 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  8 Apr 2026 07:06:36 -0400
+Subject: s390/perf_cpum_sf: Convert to use try_cmpxchg128()
+To: stable@vger.kernel.org
+Cc: Heiko Carstens <hca@linux.ibm.com>, Juergen Christ <jchrist@linux.ibm.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260408110637.978601-1-sashal@kernel.org>
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+[ Upstream commit e449399ffd295a1202b74a258227193454ef333f ]
+
+Convert cmpxchg128() usages to try_cmpxchg128() in order to generate
+slightly better code.
+
+Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Stable-dep-of: 57ad0d4a00f5 ("s390/cpum_sf: Cap sampling rate to prevent lsctl exception")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/perf_cpum_sf.c |   24 +++++++++---------------
+ 1 file changed, 9 insertions(+), 15 deletions(-)
+
+--- a/arch/s390/kernel/perf_cpum_sf.c
++++ b/arch/s390/kernel/perf_cpum_sf.c
+@@ -1188,8 +1188,8 @@ static void hw_collect_samples(struct pe
+ static void hw_perf_event_update(struct perf_event *event, int flush_all)
+ {
+       unsigned long long event_overflow, sampl_overflow, num_sdb;
+-      union hws_trailer_header old, prev, new;
+       struct hw_perf_event *hwc = &event->hw;
++      union hws_trailer_header prev, new;
+       struct hws_trailer_entry *te;
+       unsigned long *sdbt, sdb;
+       int done;
+@@ -1233,13 +1233,11 @@ static void hw_perf_event_update(struct
+               /* Reset trailer (using compare-double-and-swap) */
+               prev.val = READ_ONCE_ALIGNED_128(te->header.val);
+               do {
+-                      old.val = prev.val;
+                       new.val = prev.val;
+                       new.f = 0;
+                       new.a = 1;
+                       new.overflow = 0;
+-                      prev.val = cmpxchg128(&te->header.val, old.val, new.val);
+-              } while (prev.val != old.val);
++              } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val));
+               /* Advance to next sample-data-block */
+               sdbt++;
+@@ -1405,16 +1403,15 @@ static int aux_output_begin(struct perf_
+ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
+                         unsigned long long *overflow)
+ {
+-      union hws_trailer_header old, prev, new;
++      union hws_trailer_header prev, new;
+       struct hws_trailer_entry *te;
+       te = aux_sdb_trailer(aux, alert_index);
+       prev.val = READ_ONCE_ALIGNED_128(te->header.val);
+       do {
+-              old.val = prev.val;
+               new.val = prev.val;
+-              *overflow = old.overflow;
+-              if (old.f) {
++              *overflow = prev.overflow;
++              if (prev.f) {
+                       /*
+                        * SDB is already set by hardware.
+                        * Abort and try to set somewhere
+@@ -1424,8 +1421,7 @@ static bool aux_set_alert(struct aux_buf
+               }
+               new.a = 1;
+               new.overflow = 0;
+-              prev.val = cmpxchg128(&te->header.val, old.val, new.val);
+-      } while (prev.val != old.val);
++      } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val));
+       return true;
+ }
+@@ -1454,7 +1450,7 @@ static bool aux_set_alert(struct aux_buf
+ static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range,
+                            unsigned long long *overflow)
+ {
+-      union hws_trailer_header old, prev, new;
++      union hws_trailer_header prev, new;
+       unsigned long i, range_scan, idx;
+       unsigned long long orig_overflow;
+       struct hws_trailer_entry *te;
+@@ -1486,17 +1482,15 @@ static bool aux_reset_buffer(struct aux_
+               te = aux_sdb_trailer(aux, idx);
+               prev.val = READ_ONCE_ALIGNED_128(te->header.val);
+               do {
+-                      old.val = prev.val;
+                       new.val = prev.val;
+-                      orig_overflow = old.overflow;
++                      orig_overflow = prev.overflow;
+                       new.f = 0;
+                       new.overflow = 0;
+                       if (idx == aux->alert_mark)
+                               new.a = 1;
+                       else
+                               new.a = 0;
+-                      prev.val = cmpxchg128(&te->header.val, old.val, new.val);
+-              } while (prev.val != old.val);
++              } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val));
+               *overflow += orig_overflow;
+       }
diff --git a/queue-6.12/scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch b/queue-6.12/scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch
new file mode 100644 (file)
index 0000000..bce0a49
--- /dev/null
@@ -0,0 +1,147 @@
+From stable+bounces-231442-greg=kroah.com@vger.kernel.org Tue Mar 31 16:55:48 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Mar 2026 10:53:49 -0400
+Subject: scsi: target: tcm_loop: Drain commands in target_reset handler
+To: stable@vger.kernel.org
+Cc: Josef Bacik <josef@toxicpanda.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260331145349.2557768-1-sashal@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 1333eee56cdf3f0cf67c6ab4114c2c9e0a952026 ]
+
+tcm_loop_target_reset() violates the SCSI EH contract: it returns SUCCESS
+without draining any in-flight commands.  The SCSI EH documentation
+(scsi_eh.rst) requires that when a reset handler returns SUCCESS the driver
+has made lower layers "forget about timed out scmds" and is ready for new
+commands.  Every other SCSI LLD (virtio_scsi, mpt3sas, ipr, scsi_debug,
+mpi3mr) enforces this by draining or completing outstanding commands before
+returning SUCCESS.
+
+Because tcm_loop_target_reset() doesn't drain, the SCSI EH reuses in-flight
+scsi_cmnd structures for recovery commands (e.g. TUR) while the target core
+still has async completion work queued for the old se_cmd.  The memset in
+queuecommand zeroes se_lun and lun_ref_active, causing
+transport_lun_remove_cmd() to skip its percpu_ref_put().  The leaked LUN
+reference prevents transport_clear_lun_ref() from completing, hanging
+configfs LUN unlink forever in D-state:
+
+  INFO: task rm:264 blocked for more than 122 seconds.
+  rm              D    0   264    258 0x00004000
+  Call Trace:
+   __schedule+0x3d0/0x8e0
+   schedule+0x36/0xf0
+   transport_clear_lun_ref+0x78/0x90 [target_core_mod]
+   core_tpg_remove_lun+0x28/0xb0 [target_core_mod]
+   target_fabric_port_unlink+0x50/0x60 [target_core_mod]
+   configfs_unlink+0x156/0x1f0 [configfs]
+   vfs_unlink+0x109/0x290
+   do_unlinkat+0x1d5/0x2d0
+
+Fix this by making tcm_loop_target_reset() actually drain commands:
+
+ 1. Issue TMR_LUN_RESET via tcm_loop_issue_tmr() to drain all commands that
+    the target core knows about (those not yet CMD_T_COMPLETE).
+
+ 2. Use blk_mq_tagset_busy_iter() to iterate all started requests and
+    flush_work() on each se_cmd — this drains any deferred completion work
+    for commands that already had CMD_T_COMPLETE set before the TMR (which
+    the TMR skips via __target_check_io_state()).  This is the same pattern
+    used by mpi3mr, scsi_debug, and libsas to drain outstanding commands
+    during reset.
+
+Fixes: e0eb5d38b732 ("scsi: target: tcm_loop: Use block cmd allocator for se_cmds")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-6
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Link: https://patch.msgid.link/27011aa34c8f6b1b94d2e3cf5655b6d037f53428.1773706803.git.josef@toxicpanda.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/target/loopback/tcm_loop.c |   52 ++++++++++++++++++++++++++++++++-----
+ 1 file changed, 46 insertions(+), 6 deletions(-)
+
+--- a/drivers/target/loopback/tcm_loop.c
++++ b/drivers/target/loopback/tcm_loop.c
+@@ -26,6 +26,7 @@
+ #include <linux/slab.h>
+ #include <linux/types.h>
+ #include <linux/configfs.h>
++#include <linux/blk-mq.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_host.h>
+@@ -267,15 +268,27 @@ static int tcm_loop_device_reset(struct
+       return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
+ }
++static bool tcm_loop_flush_work_iter(struct request *rq, void *data)
++{
++      struct scsi_cmnd *sc = blk_mq_rq_to_pdu(rq);
++      struct tcm_loop_cmd *tl_cmd = scsi_cmd_priv(sc);
++      struct se_cmd *se_cmd = &tl_cmd->tl_se_cmd;
++
++      flush_work(&se_cmd->work);
++      return true;
++}
++
+ static int tcm_loop_target_reset(struct scsi_cmnd *sc)
+ {
+       struct tcm_loop_hba *tl_hba;
+       struct tcm_loop_tpg *tl_tpg;
++      struct Scsi_Host *sh = sc->device->host;
++      int ret;
+       /*
+        * Locate the tcm_loop_hba_t pointer
+        */
+-      tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
++      tl_hba = *(struct tcm_loop_hba **)shost_priv(sh);
+       if (!tl_hba) {
+               pr_err("Unable to perform device reset without active I_T Nexus\n");
+               return FAILED;
+@@ -284,11 +297,38 @@ static int tcm_loop_target_reset(struct
+        * Locate the tl_tpg pointer from TargetID in sc->device->id
+        */
+       tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
+-      if (tl_tpg) {
+-              tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
+-              return SUCCESS;
+-      }
+-      return FAILED;
++      if (!tl_tpg)
++              return FAILED;
++
++      /*
++       * Issue a LUN_RESET to drain all commands that the target core
++       * knows about.  This handles commands not yet marked CMD_T_COMPLETE.
++       */
++      ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, 0, TMR_LUN_RESET);
++      if (ret != TMR_FUNCTION_COMPLETE)
++              return FAILED;
++
++      /*
++       * Flush any deferred target core completion work that may still be
++       * queued.  Commands that already had CMD_T_COMPLETE set before the TMR
++       * are skipped by the TMR drain, but their async completion work
++       * (transport_lun_remove_cmd → percpu_ref_put, release_cmd → scsi_done)
++       * may still be pending in target_completion_wq.
++       *
++       * The SCSI EH will reuse in-flight scsi_cmnd structures for recovery
++       * commands (e.g. TUR) immediately after this handler returns SUCCESS —
++       * if deferred work is still pending, the memset in queuecommand would
++       * zero the se_cmd while the work accesses it, leaking the LUN
++       * percpu_ref and hanging configfs unlink forever.
++       *
++       * Use blk_mq_tagset_busy_iter() to find all started requests and
++       * flush_work() on each — the same pattern used by mpi3mr, scsi_debug,
++       * and other SCSI drivers to drain outstanding commands during reset.
++       */
++      blk_mq_tagset_busy_iter(&sh->tag_set, tcm_loop_flush_work_iter, NULL);
++
++      tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
++      return SUCCESS;
+ }
+ static const struct scsi_host_template tcm_loop_driver_template = {
diff --git a/queue-6.12/selftests-bpf-test-cross-sign-64bits-range-refinement.patch b/queue-6.12/selftests-bpf-test-cross-sign-64bits-range-refinement.patch
new file mode 100644 (file)
index 0000000..3873edc
--- /dev/null
@@ -0,0 +1,173 @@
+From stable+bounces-233270-greg=kroah.com@vger.kernel.org Sat Apr  4 10:15:44 2026
+From: Paul Chaignon <paul.chaignon@gmail.com>
+Date: Sat, 4 Apr 2026 10:11:42 +0200
+Subject: selftests/bpf: Test cross-sign 64bits range refinement
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Eduard Zingerman <eddyz87@gmail.com>, Shung-Hsi Yu <shung-hsi.yu@suse.com>, Alexei Starovoitov <ast@kernel.org>
+Message-ID: <bbf0c6cf0ed051619927d76a5344736e664c9929.1775289842.git.paul.chaignon@gmail.com>
+Content-Disposition: inline
+
+From: Paul Chaignon <paul.chaignon@gmail.com>
+
+[ Upstream commit 26e5e346a52c796190e63af1c2a80a417fda261a ]
+
+This patch adds coverage for the new cross-sign 64bits range refinement
+logic. The three tests cover the cases when the u64 and s64 ranges
+overlap (1) in the negative portion of s64, (2) in the positive portion
+of s64, and (3) in both portions.
+
+The first test is a simplified version of a BPF program generated by
+syzkaller that caused an invariant violation [1]. It looks like
+syzkaller could not extract the reproducer itself (and therefore didn't
+report it to the mailing list), but I was able to extract it from the
+console logs of a crash.
+
+The principle is similar to the invariant violation described in
+commit 6279846b9b25 ("bpf: Forget ranges when refining tnum after
+JSET"): the verifier walks a dead branch, uses the condition to refine
+ranges, and ends up with inconsistent ranges. In this case, the dead
+branch is when we fallthrough on both jumps. The new refinement logic
+improves the bounds such that the second jump is properly detected as
+always-taken and the verifier doesn't end up walking a dead branch.
+
+The second and third tests are inspired by the first, but rely on
+condition jumps to prepare the bounds instead of ALU instructions. An
+R10 write is used to trigger a verifier error when the bounds can't be
+refined.
+
+Link: https://syzkaller.appspot.com/bug?extid=c711ce17dd78e5d4fdcf [1]
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Link: https://lore.kernel.org/r/a0e17b00dab8dabcfa6f8384e7e151186efedfdd.1753695655.git.paul.chaignon@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/bpf/progs/verifier_bounds.c |  118 ++++++++++++++++++++
+ 1 file changed, 118 insertions(+)
+
+--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
++++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
+@@ -1200,4 +1200,122 @@ l0_%=: r0 = 0;                                         \
+       : __clobber_all);
+ }
++/* This test covers the bounds deduction on 64bits when the s64 and u64 ranges
++ * overlap on the negative side. At instruction 7, the ranges look as follows:
++ *
++ * 0          umin=0xfffffcf1                 umax=0xff..ff6e  U64_MAX
++ * |                [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]        |
++ * |----------------------------|------------------------------|
++ * |xxxxxxxxxx]                                   [xxxxxxxxxxxx|
++ * 0    smax=0xeffffeee                       smin=-655        -1
++ *
++ * We should therefore deduce the following new bounds:
++ *
++ * 0                             u64=[0xff..ffd71;0xff..ff6e]  U64_MAX
++ * |                                              [xxx]        |
++ * |----------------------------|------------------------------|
++ * |                                              [xxx]        |
++ * 0                                        s64=[-655;-146]    -1
++ *
++ * Without the deduction cross sign boundary, we end up with an invariant
++ * violation error.
++ */
++SEC("socket")
++__description("bounds deduction cross sign boundary, negative overlap")
++__success __log_level(2) __flag(BPF_F_TEST_REG_INVARIANTS)
++__msg("7: (1f) r0 -= r6 {{.*}} R0=scalar(smin=-655,smax=smax32=-146,umin=0xfffffffffffffd71,umax=0xffffffffffffff6e,smin32=-783,umin32=0xfffffcf1,umax32=0xffffff6e,var_off=(0xfffffffffffffc00; 0x3ff))")
++__retval(0)
++__naked void bounds_deduct_negative_overlap(void)
++{
++      asm volatile("                  \
++      call %[bpf_get_prandom_u32];    \
++      w3 = w0;                        \
++      w6 = (s8)w0;                    \
++      r0 = (s8)r0;                    \
++      if w6 >= 0xf0000000 goto l0_%=; \
++      r0 += r6;                       \
++      r6 += 400;                      \
++      r0 -= r6;                       \
++      if r3 < r0 goto l0_%=;          \
++l0_%=:        r0 = 0;                         \
++      exit;                           \
++"     :
++      : __imm(bpf_get_prandom_u32)
++      : __clobber_all);
++}
++
++/* This test covers the bounds deduction on 64bits when the s64 and u64 ranges
++ * overlap on the positive side. At instruction 3, the ranges look as follows:
++ *
++ * 0 umin=0                      umax=0xffffffffffffff00       U64_MAX
++ * [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]            |
++ * |----------------------------|------------------------------|
++ * |xxxxxxxx]                                         [xxxxxxxx|
++ * 0      smax=127                                smin=-128    -1
++ *
++ * We should therefore deduce the following new bounds:
++ *
++ * 0  u64=[0;127]                                              U64_MAX
++ * [xxxxxxxx]                                                  |
++ * |----------------------------|------------------------------|
++ * [xxxxxxxx]                                                  |
++ * 0  s64=[0;127]                                              -1
++ *
++ * Without the deduction cross sign boundary, the program is rejected due to
++ * the frame pointer write.
++ */
++SEC("socket")
++__description("bounds deduction cross sign boundary, positive overlap")
++__success __log_level(2) __flag(BPF_F_TEST_REG_INVARIANTS)
++__msg("3: (2d) if r0 > r1 {{.*}} R0_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=127,var_off=(0x0; 0x7f))")
++__retval(0)
++__naked void bounds_deduct_positive_overlap(void)
++{
++      asm volatile("                  \
++      call %[bpf_get_prandom_u32];    \
++      r0 = (s8)r0;                    \
++      r1 = 0xffffffffffffff00;        \
++      if r0 > r1 goto l0_%=;          \
++      if r0 < 128 goto l0_%=;         \
++      r10 = 0;                        \
++l0_%=:        r0 = 0;                         \
++      exit;                           \
++"     :
++      : __imm(bpf_get_prandom_u32)
++      : __clobber_all);
++}
++
++/* This test is the same as above, but the s64 and u64 ranges overlap in two
++ * places. At instruction 3, the ranges look as follows:
++ *
++ * 0 umin=0                           umax=0xffffffffffffff80  U64_MAX
++ * [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]        |
++ * |----------------------------|------------------------------|
++ * |xxxxxxxx]                                         [xxxxxxxx|
++ * 0      smax=127                                smin=-128    -1
++ *
++ * 0xffffffffffffff80 = (u64)-128. We therefore can't deduce anything new and
++ * the program should fail due to the frame pointer write.
++ */
++SEC("socket")
++__description("bounds deduction cross sign boundary, two overlaps")
++__failure __flag(BPF_F_TEST_REG_INVARIANTS)
++__msg("3: (2d) if r0 > r1 {{.*}} R0_w=scalar(smin=smin32=-128,smax=smax32=127,umax=0xffffffffffffff80)")
++__msg("frame pointer is read only")
++__naked void bounds_deduct_two_overlaps(void)
++{
++      asm volatile("                  \
++      call %[bpf_get_prandom_u32];    \
++      r0 = (s8)r0;                    \
++      r1 = 0xffffffffffffff80;        \
++      if r0 > r1 goto l0_%=;          \
++      if r0 < 128 goto l0_%=;         \
++      r10 = 0;                        \
++l0_%=:        r0 = 0;                         \
++      exit;                           \
++"     :
++      : __imm(bpf_get_prandom_u32)
++      : __clobber_all);
++}
++
+ char _license[] SEC("license") = "GPL";
diff --git a/queue-6.12/selftests-bpf-test-invariants-on-jslt-crossing-sign.patch b/queue-6.12/selftests-bpf-test-invariants-on-jslt-crossing-sign.patch
new file mode 100644 (file)
index 0000000..1a2ac6a
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-233271-greg=kroah.com@vger.kernel.org Sat Apr  4 10:15:48 2026
+From: Paul Chaignon <paul.chaignon@gmail.com>
+Date: Sat, 4 Apr 2026 10:12:32 +0200
+Subject: selftests/bpf: Test invariants on JSLT crossing sign
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Eduard Zingerman <eddyz87@gmail.com>, Shung-Hsi Yu <shung-hsi.yu@suse.com>, Alexei Starovoitov <ast@kernel.org>
+Message-ID: <8391b533f7f9876aadc8ae1bf9915516db575cd9.1775289842.git.paul.chaignon@gmail.com>
+Content-Disposition: inline
+
+From: Paul Chaignon <paul.chaignon@gmail.com>
+
+[ Upstream commit f96841bbf4a1ee4ed0336ba192a01278fdea6383 ]
+
+The improvement of the u64/s64 range refinement fixed the invariant
+violation that was happening on this test for BPF_JSLT when crossing the
+sign boundary.
+
+After this patch, we have one test remaining with a known invariant
+violation. It's the same test as fixed here but for 32 bits ranges.
+
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Link: https://lore.kernel.org/r/ad046fb0016428f1a33c3b81617aabf31b51183f.1753695655.git.paul.chaignon@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/bpf/progs/verifier_bounds.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
++++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
+@@ -1028,7 +1028,7 @@ l0_%=:   r0 = 0;                                         \
+ SEC("xdp")
+ __description("bound check with JMP_JSLT for crossing 64-bit signed boundary")
+ __success __retval(0)
+-__flag(!BPF_F_TEST_REG_INVARIANTS) /* known invariants violation */
++__flag(BPF_F_TEST_REG_INVARIANTS)
+ __naked void crossing_64_bit_signed_boundary_2(void)
+ {
+       asm volatile ("                                 \
diff --git a/queue-6.12/selftests-bpf-test-refining-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch b/queue-6.12/selftests-bpf-test-refining-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch
new file mode 100644 (file)
index 0000000..fb13c95
--- /dev/null
@@ -0,0 +1,92 @@
+From stable+bounces-233274-greg=kroah.com@vger.kernel.org Sat Apr  4 10:15:39 2026
+From: Paul Chaignon <paul.chaignon@gmail.com>
+Date: Sat, 4 Apr 2026 10:15:26 +0200
+Subject: selftests/bpf: test refining u32/s32 bounds when ranges cross min/max boundary
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Eduard Zingerman <eddyz87@gmail.com>, Shung-Hsi Yu <shung-hsi.yu@suse.com>, Alexei Starovoitov <ast@kernel.org>, Emil Tsalapatis <emil@etsalapatis.com>
+Message-ID: <ba33eedcb64f447d5ea0025606c76fd4f00b22bd.1775289842.git.paul.chaignon@gmail.com>
+Content-Disposition: inline
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ Upstream commit f81fdfd16771e266753146bd83f6dd23515ebee9 ]
+
+Two test cases for signed/unsigned 32-bit bounds refinement
+when s32 range crosses the sign boundary:
+- s32 range [S32_MIN..1] overlapping with u32 range [3..U32_MAX],
+  s32 range tail before sign boundary overlaps with u32 range.
+- s32 range [-3..5] overlapping with u32 range [0..S32_MIN+3],
+  s32 range head after the sign boundary overlaps with u32 range.
+
+This covers both branches added in the __reg32_deduce_bounds().
+
+Also, crossing_32_bit_signed_boundary_2() no longer triggers invariant
+violations.
+
+Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
+Reviewed-by: Paul Chaignon <paul.chaignon@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20260306-bpf-32-bit-range-overflow-v3-2-f7f67e060a6b@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/bpf/progs/verifier_bounds.c |   39 +++++++++++++++++++-
+ 1 file changed, 38 insertions(+), 1 deletion(-)
+
+--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
++++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
+@@ -1110,7 +1110,7 @@ l0_%=:   r0 = 0;                                         \
+ SEC("xdp")
+ __description("bound check with JMP32_JSLT for crossing 32-bit signed boundary")
+ __success __retval(0)
+-__flag(!BPF_F_TEST_REG_INVARIANTS) /* known invariants violation */
++__flag(BPF_F_TEST_REG_INVARIANTS)
+ __naked void crossing_32_bit_signed_boundary_2(void)
+ {
+       asm volatile ("                                 \
+@@ -1316,6 +1316,43 @@ l0_%=:  r0 = 0;                         \
+ "     :
+       : __imm(bpf_get_prandom_u32)
+       : __clobber_all);
++}
++
++SEC("socket")
++__success
++__flag(BPF_F_TEST_REG_INVARIANTS)
++__naked void signed_unsigned_intersection32_case1(void *ctx)
++{
++      asm volatile("                                                                  \
++      call %[bpf_get_prandom_u32];                                                    \
++      w0 &= 0xffffffff;                                                               \
++      if w0 < 0x3 goto 1f;            /* on fall-through u32 range [3..U32_MAX]  */   \
++      if w0 s> 0x1 goto 1f;           /* on fall-through s32 range [S32_MIN..1]  */   \
++      if w0 s< 0x0 goto 1f;           /* range can be narrowed to  [S32_MIN..-1] */   \
++      r10 = 0;                        /* thus predicting the jump. */                 \
++1:    exit;                                                                           \
++"     :
++      : __imm(bpf_get_prandom_u32)
++      : __clobber_all);
++}
++
++SEC("socket")
++__success
++__flag(BPF_F_TEST_REG_INVARIANTS)
++__naked void signed_unsigned_intersection32_case2(void *ctx)
++{
++      asm volatile("                                                                  \
++      call %[bpf_get_prandom_u32];                                                    \
++      w0 &= 0xffffffff;                                                               \
++      if w0 > 0x80000003 goto 1f;     /* on fall-through u32 range [0..S32_MIN+3] */  \
++      if w0 s< -3 goto 1f;            /* on fall-through s32 range [-3..S32_MAX] */   \
++      if w0 s> 5 goto 1f;             /* on fall-through s32 range [-3..5] */         \
++      if w0 <= 5 goto 1f;             /* range can be narrowed to  [0..5] */          \
++      r10 = 0;                        /* thus predicting the jump */                  \
++1:    exit;                                                                           \
++"     :
++      : __imm(bpf_get_prandom_u32)
++      : __clobber_all);
+ }
+ char _license[] SEC("license") = "GPL";
index 7990d2c0892b2295c9f916f211c8c69cd024775e..3f771ace74c451fdf2805179208dd125581e3635 100644 (file)
@@ -214,3 +214,34 @@ usb-gadget-f_subset-fix-net_device-lifecycle-with-device_move.patch
 usb-gadget-f_rndis-fix-net_device-lifecycle-with-device_move.patch
 usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch
 usb-gadget-f_uac1_legacy-validate-control-request-size.patch
+wifi-virt_wifi-remove-set_netdev_dev-to-avoid-use-after-free.patch
+spi-cadence-qspi-fix-exec_mem_op-error-handling.patch
+net-correctly-handle-tunneled-traffic-on-ipv6_csum-gso-fallback.patch
+net-mana-fix-use-after-free-in-add_adev-error-path.patch
+scsi-target-tcm_loop-drain-commands-in-target_reset-handler.patch
+x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch
+mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch
+mm-replace-read_once-with-standard-page-table-accessors.patch
+mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch
+drm-amd-pm-disable-od_fan_curve-if-temp-or-pwm-range-invalid-for-smu-v13.patch
+ext4-publish-jinode-after-initialization.patch
+s390-perf_cpum_sf-convert-to-use-try_cmpxchg128.patch
+s390-cpum_sf-cap-sampling-rate-to-prevent-lsctl-exception.patch
+mptcp-fix-lock-class-name-family-in-pm_nl_create_listen_socket.patch
+x86-cpu-amd-add-additional-fixed-rdseed-microcode-revisions.patch
+drm-amd-amdgpu-decouple-aspm-with-pcie-dpm.patch
+drm-amd-amdgpu-disable-aspm-in-some-situations.patch
+drm-amd-display-disable-fastboot-on-dce-6-too.patch
+drm-amd-display-reject-modes-with-too-high-pixel-clock-on-dce6-10.patch
+drm-amd-display-keep-pll0-running-on-dce-6.0-and-6.4.patch
+drm-amd-display-fix-dce-6.0-and-6.4-pll-programming.patch
+drm-amd-display-adjust-dce-8-10-clock-don-t-overclock-by-15.patch
+drm-amd-display-disable-scaling-on-dce6-for-now.patch
+drm-amd-disable-aspm-on-si.patch
+drm-amd-display-correct-logic-check-error-for-fastboot.patch
+bpf-improve-bounds-when-s64-crosses-sign-boundary.patch
+selftests-bpf-test-cross-sign-64bits-range-refinement.patch
+selftests-bpf-test-invariants-on-jslt-crossing-sign.patch
+bpf-add-third-round-of-bounds-deduction.patch
+bpf-fix-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch
+selftests-bpf-test-refining-u32-s32-bounds-when-ranges-cross-min-max-boundary.patch
diff --git a/queue-6.12/spi-cadence-qspi-fix-exec_mem_op-error-handling.patch b/queue-6.12/spi-cadence-qspi-fix-exec_mem_op-error-handling.patch
new file mode 100644 (file)
index 0000000..2826e31
--- /dev/null
@@ -0,0 +1,64 @@
+From 59e1be1278f064d7172b00473b7e0c453cb1ec52 Mon Sep 17 00:00:00 2001
+From: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
+Date: Fri, 13 Mar 2026 14:52:31 +0100
+Subject: spi: cadence-qspi: Fix exec_mem_op error handling
+
+From: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
+
+commit 59e1be1278f064d7172b00473b7e0c453cb1ec52 upstream.
+
+cqspi_exec_mem_op() increments the runtime PM usage counter before all
+refcount checks are performed. If one of these checks fails, the function
+returns without dropping the PM reference.
+
+Move the pm_runtime_resume_and_get() call after the refcount checks so
+that runtime PM is only acquired when the operation can proceed and
+drop the inflight_ops refcount if the PM resume fails.
+
+Cc: stable@vger.kernel.org
+Fixes: 7446284023e8 ("spi: cadence-quadspi: Implement refcount to handle unbind during busy")
+Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
+Link: https://patch.msgid.link/20260313135236.46642-1-ghidoliemanuele@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-cadence-quadspi.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/spi/spi-cadence-quadspi.c
++++ b/drivers/spi/spi-cadence-quadspi.c
+@@ -1461,12 +1461,6 @@ static int cqspi_exec_mem_op(struct spi_
+       if (refcount_read(&cqspi->inflight_ops) == 0)
+               return -ENODEV;
+-      ret = pm_runtime_resume_and_get(dev);
+-      if (ret) {
+-              dev_err(&mem->spi->dev, "resume failed with %d\n", ret);
+-              return ret;
+-      }
+-
+       if (!refcount_read(&cqspi->refcount))
+               return -EBUSY;
+@@ -1478,6 +1472,12 @@ static int cqspi_exec_mem_op(struct spi_
+               return -EBUSY;
+       }
++      ret = pm_runtime_resume_and_get(dev);
++      if (ret) {
++              dev_err(&mem->spi->dev, "resume failed with %d\n", ret);
++              goto dec_inflight_refcount;
++      }
++
+       ret = cqspi_mem_process(mem, op);
+       pm_runtime_mark_last_busy(dev);
+@@ -1486,6 +1486,7 @@ static int cqspi_exec_mem_op(struct spi_
+       if (ret)
+               dev_err(&mem->spi->dev, "operation failed with %d\n", ret);
++dec_inflight_refcount:
+       if (refcount_read(&cqspi->inflight_ops) > 1)
+               refcount_dec(&cqspi->inflight_ops);
diff --git a/queue-6.12/wifi-virt_wifi-remove-set_netdev_dev-to-avoid-use-after-free.patch b/queue-6.12/wifi-virt_wifi-remove-set_netdev_dev-to-avoid-use-after-free.patch
new file mode 100644 (file)
index 0000000..9eab462
--- /dev/null
@@ -0,0 +1,101 @@
+From 789b06f9f39cdc7e895bdab2c034e39c41c8f8d6 Mon Sep 17 00:00:00 2001
+From: Alexander Popov <alex.popov@linux.com>
+Date: Wed, 25 Mar 2026 01:46:02 +0300
+Subject: wifi: virt_wifi: remove SET_NETDEV_DEV to avoid use-after-free
+
+From: Alexander Popov <alex.popov@linux.com>
+
+commit 789b06f9f39cdc7e895bdab2c034e39c41c8f8d6 upstream.
+
+Currently we execute `SET_NETDEV_DEV(dev, &priv->lowerdev->dev)` for
+the virt_wifi net devices. However, unregistering a virt_wifi device in
+netdev_run_todo() can happen together with the device referenced by
+SET_NETDEV_DEV().
+
+It can result in use-after-free during the ethtool operations performed
+on a virt_wifi device that is currently being unregistered. Such a net
+device can have the `dev.parent` field pointing to the freed memory,
+but ethnl_ops_begin() calls `pm_runtime_get_sync(dev->dev.parent)`.
+
+Let's remove SET_NETDEV_DEV for virt_wifi to avoid bugs like this:
+
+ ==================================================================
+ BUG: KASAN: slab-use-after-free in __pm_runtime_resume+0xe2/0xf0
+ Read of size 2 at addr ffff88810cfc46f8 by task pm/606
+
+ Call Trace:
+  <TASK>
+  dump_stack_lvl+0x4d/0x70
+  print_report+0x170/0x4f3
+  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
+  kasan_report+0xda/0x110
+  ? __pm_runtime_resume+0xe2/0xf0
+  ? __pm_runtime_resume+0xe2/0xf0
+  __pm_runtime_resume+0xe2/0xf0
+  ethnl_ops_begin+0x49/0x270
+  ethnl_set_features+0x23c/0xab0
+  ? __pfx_ethnl_set_features+0x10/0x10
+  ? kvm_sched_clock_read+0x11/0x20
+  ? local_clock_noinstr+0xf/0xf0
+  ? local_clock+0x10/0x30
+  ? kasan_save_track+0x25/0x60
+  ? __kasan_kmalloc+0x7f/0x90
+  ? genl_family_rcv_msg_attrs_parse.isra.0+0x150/0x2c0
+  genl_family_rcv_msg_doit+0x1e7/0x2c0
+  ? __pfx_genl_family_rcv_msg_doit+0x10/0x10
+  ? __pfx_cred_has_capability.isra.0+0x10/0x10
+  ? stack_trace_save+0x8e/0xc0
+  genl_rcv_msg+0x411/0x660
+  ? __pfx_genl_rcv_msg+0x10/0x10
+  ? __pfx_ethnl_set_features+0x10/0x10
+  netlink_rcv_skb+0x121/0x380
+  ? __pfx_genl_rcv_msg+0x10/0x10
+  ? __pfx_netlink_rcv_skb+0x10/0x10
+  ? __pfx_down_read+0x10/0x10
+  genl_rcv+0x23/0x30
+  netlink_unicast+0x60f/0x830
+  ? __pfx_netlink_unicast+0x10/0x10
+  ? __pfx___alloc_skb+0x10/0x10
+  netlink_sendmsg+0x6ea/0xbc0
+  ? __pfx_netlink_sendmsg+0x10/0x10
+  ? __futex_queue+0x10b/0x1f0
+  ____sys_sendmsg+0x7a2/0x950
+  ? copy_msghdr_from_user+0x26b/0x430
+  ? __pfx_____sys_sendmsg+0x10/0x10
+  ? __pfx_copy_msghdr_from_user+0x10/0x10
+  ___sys_sendmsg+0xf8/0x180
+  ? __pfx____sys_sendmsg+0x10/0x10
+  ? __pfx_futex_wait+0x10/0x10
+  ? fdget+0x2e4/0x4a0
+  __sys_sendmsg+0x11f/0x1c0
+  ? __pfx___sys_sendmsg+0x10/0x10
+  do_syscall_64+0xe2/0x570
+  ? exc_page_fault+0x66/0xb0
+  entry_SYSCALL_64_after_hwframe+0x77/0x7f
+  </TASK>
+
+This fix may be combined with another one in the ethtool subsystem:
+https://lore.kernel.org/all/20260322075917.254874-1-alex.popov@linux.com/T/#u
+
+Fixes: d43c65b05b848e0b ("ethtool: runtime-resume netdev parent in ethnl_ops_begin")
+Cc: stable@vger.kernel.org
+Signed-off-by: Alexander Popov <alex.popov@linux.com>
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20260324224607.374327-1-alex.popov@linux.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/virtual/virt_wifi.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/net/wireless/virtual/virt_wifi.c
++++ b/drivers/net/wireless/virtual/virt_wifi.c
+@@ -555,7 +555,6 @@ static int virt_wifi_newlink(struct net
+       eth_hw_addr_inherit(dev, priv->lowerdev);
+       netif_stacked_transfer_operstate(priv->lowerdev, dev);
+-      SET_NETDEV_DEV(dev, &priv->lowerdev->dev);
+       dev->ieee80211_ptr = kzalloc(sizeof(*dev->ieee80211_ptr), GFP_KERNEL);
+       if (!dev->ieee80211_ptr) {
diff --git a/queue-6.12/x86-cpu-amd-add-additional-fixed-rdseed-microcode-revisions.patch b/queue-6.12/x86-cpu-amd-add-additional-fixed-rdseed-microcode-revisions.patch
new file mode 100644 (file)
index 0000000..d682999
--- /dev/null
@@ -0,0 +1,48 @@
+From dan.g.tob@gmail.com Thu Apr  2 05:15:35 2026
+From: Daniel Tobias <dan.g.tob@gmail.com>
+Date: Thu,  2 Apr 2026 14:14:45 +1100
+Subject: x86/CPU/AMD: Add additional fixed RDSEED microcode revisions
+To: stable@vger.kernel.org
+Cc: gregkh@linuxfoundation.org, x86@kernel.org, Mario Limonciello <mario.limonciello@amd.com>, "Borislav Petkov (AMD)" <bp@alien8.de>, Daniel Tobias <dan.g.tob@gmail.com>
+Message-ID: <20260402031445.48620-1-dan.g.tob@gmail.com>
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit e1a97a627cd01d73fac5dd054d8f3de601ef2781 ]
+
+Microcode that resolves the RDSEED failure (SB-7055 [1]) has been released for
+additional Zen5 models to linux-firmware [2]. Update the zen5_rdseed_microcode
+array to cover these new models.
+
+Fixes: e980de2ff109 ("x86/CPU/AMD: Add RDSEED fix for Zen5")
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7055.html [1]
+Link: https://gitlab.com/kernel-firmware/linux-firmware/-/commit/6167e5566900cf236f7a69704e8f4c441bc7212a [2]
+Link: https://patch.msgid.link/20251113223608.1495655-1-mario.limonciello@amd.com
+[ backport: 6.12.y uses a custom check_rdseed_microcode() function with
+  a switch statement. Updated the switch cases to include the new
+  models and revisions from the upstream patch. ]
+Signed-off-by: Daniel Tobias <dan.g.tob@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/amd.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -1034,7 +1034,14 @@ static bool check_rdseed_microcode(void)
+       if (cpu_has(c, X86_FEATURE_ZEN5)) {
+               switch (p.ucode_rev >> 8) {
+               case 0xb0021:   min_rev = 0xb00215a; break;
++              case 0xb0081:   min_rev = 0xb008121; break;
+               case 0xb1010:   min_rev = 0xb101054; break;
++              case 0xb2040:   min_rev = 0xb204037; break;
++              case 0xb4040:   min_rev = 0xb404035; break;
++              case 0xb4041:   min_rev = 0xb404108; break;
++              case 0xb6000:   min_rev = 0xb600037; break;
++              case 0xb6080:   min_rev = 0xb608038; break;
++              case 0xb7000:   min_rev = 0xb700037; break;
+               default:
+                       pr_debug("%s: ucode_rev: 0x%x, current revision: 0x%x\n",
+                                __func__, p.ucode_rev, c->microcode);
diff --git a/queue-6.12/x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch b/queue-6.12/x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch
new file mode 100644 (file)
index 0000000..aeab25e
--- /dev/null
@@ -0,0 +1,94 @@
+From stable+bounces-231415-greg=kroah.com@vger.kernel.org Tue Mar 31 14:17:13 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Mar 2026 08:17:06 -0400
+Subject: x86/fred: Fix early boot failures on SEV-ES/SNP guests
+To: stable@vger.kernel.org
+Cc: Nikunj A Dadhania <nikunj@amd.com>, "Borislav Petkov (AMD)" <bp@alien8.de>, Tom Lendacky <thomas.lendacky@amd.com>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260331121706.2197458-1-sashal@kernel.org>
+
+From: Nikunj A Dadhania <nikunj@amd.com>
+
+[ Upstream commit 3645eb7e3915990a149460c151a00894cb586253 ]
+
+FRED-enabled SEV-(ES,SNP) guests fail to boot due to the following issues
+in the early boot sequence:
+
+* FRED does not have a #VC exception handler in the dispatch logic
+
+* Early FRED #VC exceptions attempt to use uninitialized per-CPU GHCBs
+  instead of boot_ghcb
+
+Add X86_TRAP_VC case to fred_hwexc() with a new exc_vmm_communication()
+function that provides the unified entry point FRED requires, dispatching
+to existing user/kernel handlers based on privilege level. The function is
+already declared via DECLARE_IDTENTRY_VC().
+
+Fix early GHCB access by falling back to boot_ghcb in
+__sev_{get,put}_ghcb() when per-CPU GHCBs are not yet initialized.
+
+Fixes: 14619d912b65 ("x86/fred: FRED entry/exit and dispatch code")
+Signed-off-by: Nikunj A Dadhania <nikunj@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: <stable@kernel.org>  # 6.12+
+Link: https://patch.msgid.link/20260318075654.1792916-4-nikunj@amd.com
+[ applied GHCB early-return changes to core.c instead of noinstr.c ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/coco/sev/core.c    |    6 ++++++
+ arch/x86/entry/entry_fred.c |   14 ++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+--- a/arch/x86/coco/sev/core.c
++++ b/arch/x86/coco/sev/core.c
+@@ -253,6 +253,9 @@ static noinstr struct ghcb *__sev_get_gh
+       WARN_ON(!irqs_disabled());
++      if (!sev_cfg.ghcbs_initialized)
++              return boot_ghcb;
++
+       data = this_cpu_read(runtime_data);
+       ghcb = &data->ghcb_page;
+@@ -649,6 +652,9 @@ static noinstr void __sev_put_ghcb(struc
+       WARN_ON(!irqs_disabled());
++      if (!sev_cfg.ghcbs_initialized)
++              return;
++
+       data = this_cpu_read(runtime_data);
+       ghcb = &data->ghcb_page;
+--- a/arch/x86/entry/entry_fred.c
++++ b/arch/x86/entry/entry_fred.c
+@@ -176,6 +176,16 @@ static noinstr void fred_extint(struct p
+       }
+ }
++#ifdef CONFIG_AMD_MEM_ENCRYPT
++noinstr void exc_vmm_communication(struct pt_regs *regs, unsigned long error_code)
++{
++      if (user_mode(regs))
++              return user_exc_vmm_communication(regs, error_code);
++      else
++              return kernel_exc_vmm_communication(regs, error_code);
++}
++#endif
++
+ static noinstr void fred_hwexc(struct pt_regs *regs, unsigned long error_code)
+ {
+       /* Optimize for #PF. That's the only exception which matters performance wise */
+@@ -206,6 +216,10 @@ static noinstr void fred_hwexc(struct pt
+ #ifdef CONFIG_X86_CET
+       case X86_TRAP_CP: return exc_control_protection(regs, error_code);
+ #endif
++#ifdef CONFIG_AMD_MEM_ENCRYPT
++      case X86_TRAP_VC: return exc_vmm_communication(regs, error_code);
++#endif
++
+       default: return fred_bad_type(regs, error_code);
+       }