--- /dev/null
+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)
+ {
--- /dev/null
+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);
+ }
+
+ /* =======================
--- /dev/null
+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);
++ }
+ }
+ }
+
--- /dev/null
+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);
+ }
+
--- /dev/null
+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);
+ }
+
--- /dev/null
+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);
+
--- /dev/null
+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 */
--- /dev/null
+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)
--- /dev/null
+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)
--- /dev/null
+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
+ }
--- /dev/null
+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) {
--- /dev/null
+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;
+ }
+
--- /dev/null
+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) {
--- /dev/null
+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,
--- /dev/null
+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);
--- /dev/null
+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;
+ }
--- /dev/null
+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;
+ }
--- /dev/null
+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);
+
--- /dev/null
+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;
--- /dev/null
+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);
+
--- /dev/null
+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);
--- /dev/null
+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,
--- /dev/null
+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;
+ }
+
--- /dev/null
+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 = {
--- /dev/null
+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";
--- /dev/null
+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 (" \
--- /dev/null
+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";
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
--- /dev/null
+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);
+
--- /dev/null
+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) {
--- /dev/null
+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);
--- /dev/null
+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);
+ }
+