--- /dev/null
+From stable+bounces-223166-greg=kroah.com@vger.kernel.org Thu Mar 5 03:35:55 2026
+From: Robert Garcia <rob_garcia@163.com>
+Date: Thu, 5 Mar 2026 10:35:01 +0800
+Subject: binfmt_misc: restore write access before closing files opened by open_exec()
+To: stable@vger.kernel.org, Zilin Guan <zilin@seu.edu.cn>
+Cc: Christian Brauner <brauner@kernel.org>, Alexander Viro <viro@zeniv.linux.org.uk>, Robert Garcia <rob_garcia@163.com>, Jan Kara <jack@suse.cz>, Eric Biederman <ebiederm@xmission.com>, Kees Cook <kees@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Helge Deller <deller@gmx.de>, Lior Ribak <liorribak@gmail.com>, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org
+Message-ID: <20260305023501.4003943-1-rob_garcia@163.com>
+
+From: Zilin Guan <zilin@seu.edu.cn>
+
+[ Upstream commit 90f601b497d76f40fa66795c3ecf625b6aced9fd ]
+
+bm_register_write() opens an executable file using open_exec(), which
+internally calls do_open_execat() and denies write access on the file to
+avoid modification while it is being executed.
+
+However, when an error occurs, bm_register_write() closes the file using
+filp_close() directly. This does not restore the write permission, which
+may cause subsequent write operations on the same file to fail.
+
+Fix this by calling exe_file_allow_write_access() before filp_close() to
+restore the write permission properly.
+
+Fixes: e7850f4d844e ("binfmt_misc: fix possible deadlock in bm_register_write")
+Signed-off-by: Zilin Guan <zilin@seu.edu.cn>
+Link: https://patch.msgid.link/20251105022923.1813587-1-zilin@seu.edu.cn
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+[ Use allow_write_access() instead of exe_file_allow_write_access()
+according to commit 0357ef03c94ef
+("fs: don't block write during exec on pre-content watched files"). ]
+Signed-off-by: Robert Garcia <rob_garcia@163.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/binfmt_misc.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -815,8 +815,10 @@ out:
+ inode_unlock(d_inode(root));
+
+ if (err) {
+- if (f)
++ if (f) {
++ allow_write_access(f);
+ filp_close(f, NULL);
++ }
+ kfree(e);
+ return err;
+ }
--- /dev/null
+From 6279846b9b2532e1b04559ef8bd0dec049f29383 Mon Sep 17 00:00:00 2001
+From: Paul Chaignon <paul.chaignon@gmail.com>
+Date: Thu, 10 Jul 2025 20:20:53 +0200
+Subject: bpf: Forget ranges when refining tnum after JSET
+
+From: Paul Chaignon <paul.chaignon@gmail.com>
+
+commit 6279846b9b2532e1b04559ef8bd0dec049f29383 upstream.
+
+Syzbot reported a kernel warning due to a range invariant violation on
+the following BPF program.
+
+ 0: call bpf_get_netns_cookie
+ 1: if r0 == 0 goto <exit>
+ 2: if r0 & Oxffffffff goto <exit>
+
+The issue is on the path where we fall through both jumps.
+
+That path is unreachable at runtime: after insn 1, we know r0 != 0, but
+with the sign extension on the jset, we would only fallthrough insn 2
+if r0 == 0. Unfortunately, is_branch_taken() isn't currently able to
+figure this out, so the verifier walks all branches. The verifier then
+refines the register bounds using the second condition and we end
+up with inconsistent bounds on this unreachable path:
+
+ 1: if r0 == 0 goto <exit>
+ r0: u64=[0x1, 0xffffffffffffffff] var_off=(0, 0xffffffffffffffff)
+ 2: if r0 & 0xffffffff goto <exit>
+ r0 before reg_bounds_sync: u64=[0x1, 0xffffffffffffffff] var_off=(0, 0)
+ r0 after reg_bounds_sync: u64=[0x1, 0] var_off=(0, 0)
+
+Improving the range refinement for JSET to cover all cases is tricky. We
+also don't expect many users to rely on JSET given LLVM doesn't generate
+those instructions. So instead of improving the range refinement for
+JSETs, Eduard suggested we forget the ranges whenever we're narrowing
+tnums after a JSET. This patch implements that approach.
+
+Reported-by: syzbot+c711ce17dd78e5d4fdcf@syzkaller.appspotmail.com
+Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
+Acked-by: Yonghong Song <yonghong.song@linux.dev>
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Link: https://lore.kernel.org/r/9d4fd6432a095d281f815770608fdcd16028ce0b.1752171365.git.paul.chaignon@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ shung-hsi.yu: no detection or kernel warning for invariant violation before
+ 6.8, but the same umin=1,umax=0 state can occur when jset is preceed by r0 < 1.
+ Changes were made to adapt to older range refinement logic before commit
+ 67420501e868 ("bpf: generalize reg_set_min_max() to handle non-const register
+ comparisons"). ]
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -14158,6 +14158,10 @@ static void reg_set_min_max(struct bpf_r
+ }
+ break;
+ case BPF_JSET:
++ /* Forget the ranges before narrowing tnums, to avoid invariant
++ * violations if we're on a dead branch.
++ */
++ __mark_reg_unbounded(false_reg);
+ if (is_jmp32) {
+ false_32off = tnum_and(false_32off, tnum_const(~val32));
+ if (is_power_of_2(val32))
--- /dev/null
+From b515dcb0dc4e85d8254f5459cfb32fce88dacbfb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timur=20Krist=C3=B3f?= <timur.kristof@gmail.com>
+Date: Tue, 9 Sep 2025 16:17:50 +0200
+Subject: drm/amd/display: Add pixel_clock to amd_pp_display_configuration
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+commit b515dcb0dc4e85d8254f5459cfb32fce88dacbfb upstream.
+
+This commit adds the pixel_clock field to the display config
+struct so that power management (DPM) can use it.
+
+We currently don't have a proper bandwidth calculation on old
+GPUs with DCE 6-10 because dce_calcs only supports DCE 11+.
+So the power management (DPM) on these GPUs may need to make
+ad-hoc decisions for display based on the pixel clock.
+
+Also rename sym_clock to pixel_clock in dm_pp_single_disp_config
+to avoid confusion with other code where the sym_clock refers to
+the DisplayPort symbol clock.
+
+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/amdgpu_dm/amdgpu_dm_pp_smu.c | 1 +
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c | 2 +-
+ drivers/gpu/drm/amd/display/dc/dm_services_types.h | 2 +-
+ drivers/gpu/drm/amd/include/dm_pp_interface.h | 1 +
+ 4 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+@@ -97,6 +97,7 @@ bool dm_pp_apply_display_requirements(
+ const struct dm_pp_single_disp_config *dc_cfg =
+ &pp_display_cfg->disp_configs[i];
+ adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1;
++ adev->pm.pm_display_cfg.displays[i].pixel_clock = dc_cfg->pixel_clock;
+ }
+
+ amdgpu_dpm_display_configuration_change(adev, &adev->pm.pm_display_cfg);
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
+@@ -164,7 +164,7 @@ void dce110_fill_display_configs(
+ stream->link->cur_link_settings.link_rate;
+ cfg->link_settings.link_spread =
+ stream->link->cur_link_settings.link_spread;
+- cfg->sym_clock = stream->phy_pix_clk;
++ cfg->pixel_clock = stream->phy_pix_clk;
+ /* Round v_refresh*/
+ cfg->v_refresh = stream->timing.pix_clk_100hz * 100;
+ cfg->v_refresh /= stream->timing.h_total;
+--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+@@ -127,7 +127,7 @@ struct dm_pp_single_disp_config {
+ uint32_t src_height;
+ uint32_t src_width;
+ uint32_t v_refresh;
+- uint32_t sym_clock; /* HDMI only */
++ uint32_t pixel_clock; /* Pixel clock in KHz (for HDMI only: normalized) */
+ struct dc_link_settings link_settings; /* DP only */
+ };
+
+--- a/drivers/gpu/drm/amd/include/dm_pp_interface.h
++++ b/drivers/gpu/drm/amd/include/dm_pp_interface.h
+@@ -66,6 +66,7 @@ struct single_display_configuration
+ uint32_t view_resolution_cy;
+ enum amd_pp_display_config_type displayconfigtype;
+ uint32_t vertical_refresh; /* for active display */
++ uint32_t pixel_clock; /* Pixel clock in KHz (for HDMI only: normalized) */
+ };
+
+ #define MAX_NUM_DISPLAY 32
--- /dev/null
+From 9d73b107a61b73e7101d4b728ddac3d2c77db111 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timur=20Krist=C3=B3f?= <timur.kristof@gmail.com>
+Date: Tue, 9 Sep 2025 16:17:51 +0200
+Subject: drm/amd/pm: Use pm_display_cfg in legacy DPM (v2)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+commit 9d73b107a61b73e7101d4b728ddac3d2c77db111 upstream.
+
+This commit is necessary for DC to function well with chips
+that use the legacy power management code, ie. SI and KV.
+Communicate display information from DC to the legacy PM code.
+
+Currently DC uses pm_display_cfg to communicate power management
+requirements from the display code to the DPM code.
+However, the legacy (non-DC) code path used different fields
+and therefore could not take into account anything from DC.
+
+Change the legacy display code to fill the same pm_display_cfg
+struct as DC and use the same in the legacy DPM code.
+
+To ease review and reduce churn, this commit does not yet
+delete the now unneeded code, that is done in the next commit.
+
+v2:
+Rebase.
+Fix single_display in amdgpu_dpm_pick_power_state.
+
+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/pm/amdgpu_dpm_internal.c | 67 +++++++++++++++++++++++
+ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h | 2
+ drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c | 4 -
+ drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c | 6 +-
+ drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 65 +++++++---------------
+ drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 11 ---
+ 6 files changed, 97 insertions(+), 58 deletions(-)
+
+--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c
++++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c
+@@ -100,3 +100,70 @@ u32 amdgpu_dpm_get_vrefresh(struct amdgp
+
+ return vrefresh;
+ }
++
++void amdgpu_dpm_get_display_cfg(struct amdgpu_device *adev)
++{
++ struct drm_device *ddev = adev_to_drm(adev);
++ struct amd_pp_display_configuration *cfg = &adev->pm.pm_display_cfg;
++ struct single_display_configuration *display_cfg;
++ struct drm_crtc *crtc;
++ struct amdgpu_crtc *amdgpu_crtc;
++ struct amdgpu_connector *conn;
++ int num_crtcs = 0;
++ int vrefresh;
++ u32 vblank_in_pixels, vblank_time_us;
++
++ cfg->min_vblank_time = 0xffffffff; /* if the displays are off, vblank time is max */
++
++ if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
++ list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
++ amdgpu_crtc = to_amdgpu_crtc(crtc);
++
++ /* The array should only contain active displays. */
++ if (!amdgpu_crtc->enabled)
++ continue;
++
++ conn = to_amdgpu_connector(amdgpu_crtc->connector);
++ display_cfg = &adev->pm.pm_display_cfg.displays[num_crtcs++];
++
++ if (amdgpu_crtc->hw_mode.clock) {
++ vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
++
++ vblank_in_pixels =
++ amdgpu_crtc->hw_mode.crtc_htotal *
++ (amdgpu_crtc->hw_mode.crtc_vblank_end -
++ amdgpu_crtc->hw_mode.crtc_vdisplay +
++ (amdgpu_crtc->v_border * 2));
++
++ vblank_time_us =
++ vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
++
++ /* The legacy (non-DC) code has issues with mclk switching
++ * with refresh rates over 120 Hz. Disable mclk switching.
++ */
++ if (vrefresh > 120)
++ vblank_time_us = 0;
++
++ /* Find minimum vblank time. */
++ if (vblank_time_us < cfg->min_vblank_time)
++ cfg->min_vblank_time = vblank_time_us;
++
++ /* Find vertical refresh rate of first active display. */
++ if (!cfg->vrefresh)
++ cfg->vrefresh = vrefresh;
++ }
++
++ if (amdgpu_crtc->crtc_id < cfg->crtc_index) {
++ /* Find first active CRTC and its line time. */
++ cfg->crtc_index = amdgpu_crtc->crtc_id;
++ cfg->line_time_in_us = amdgpu_crtc->line_time;
++ }
++
++ display_cfg->controller_id = amdgpu_crtc->crtc_id;
++ display_cfg->pixel_clock = conn->pixelclock_for_modeset;
++ }
++ }
++
++ cfg->display_clk = adev->clock.default_dispclk;
++ cfg->num_display = num_crtcs;
++}
+--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h
++++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h
+@@ -29,4 +29,6 @@ u32 amdgpu_dpm_get_vblank_time(struct am
+
+ u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev);
+
++void amdgpu_dpm_get_display_cfg(struct amdgpu_device *adev);
++
+ #endif
+--- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
++++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
+@@ -2299,7 +2299,7 @@ static void kv_apply_state_adjust_rules(
+
+ if (pi->sys_info.nb_dpm_enable) {
+ force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) ||
+- pi->video_start || (adev->pm.dpm.new_active_crtc_count >= 3) ||
++ pi->video_start || (adev->pm.pm_display_cfg.num_display >= 3) ||
+ pi->disable_nb_ps3_in_battery;
+ ps->dpm0_pg_nb_ps_lo = force_high ? 0x2 : 0x3;
+ ps->dpm0_pg_nb_ps_hi = 0x2;
+@@ -2358,7 +2358,7 @@ static int kv_calculate_nbps_level_setti
+ return 0;
+
+ force_high = ((mclk >= pi->sys_info.nbp_memory_clock[3]) ||
+- (adev->pm.dpm.new_active_crtc_count >= 3) || pi->video_start);
++ (adev->pm.pm_display_cfg.num_display >= 3) || pi->video_start);
+
+ if (force_high) {
+ for (i = pi->lowest_valid; i <= pi->highest_valid; i++)
+--- a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c
++++ b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c
+@@ -797,8 +797,7 @@ static struct amdgpu_ps *amdgpu_dpm_pick
+ int i;
+ struct amdgpu_ps *ps;
+ u32 ui_class;
+- bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ?
+- true : false;
++ bool single_display = adev->pm.pm_display_cfg.num_display < 2;
+
+ /* check if the vblank period is too short to adjust the mclk */
+ if (single_display && adev->powerplay.pp_funcs->vblank_too_short) {
+@@ -1003,7 +1002,8 @@ void amdgpu_legacy_dpm_compute_clocks(vo
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+- amdgpu_dpm_get_active_displays(adev);
++ if (!adev->dc_enabled)
++ amdgpu_dpm_get_display_cfg(adev);
+
+ amdgpu_dpm_change_power_state_locked(adev);
+ }
+--- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
++++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
+@@ -3058,7 +3058,7 @@ static int si_get_vce_clock_voltage(stru
+ static bool si_dpm_vblank_too_short(void *handle)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+- u32 vblank_time = amdgpu_dpm_get_vblank_time(adev);
++ u32 vblank_time = adev->pm.pm_display_cfg.min_vblank_time;
+ /* we never hit the non-gddr5 limit so disable it */
+ u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0;
+
+@@ -3424,9 +3424,10 @@ static void rv770_get_engine_memory_ss(s
+ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
+ struct amdgpu_ps *rps)
+ {
++ const struct amd_pp_display_configuration *display_cfg =
++ &adev->pm.pm_display_cfg;
+ struct si_ps *ps = si_get_ps(rps);
+ struct amdgpu_clock_and_voltage_limits *max_limits;
+- struct amdgpu_connector *conn;
+ bool disable_mclk_switching = false;
+ bool disable_sclk_switching = false;
+ u32 mclk, sclk;
+@@ -3475,14 +3476,9 @@ static void si_apply_state_adjust_rules(
+ * For example, 4K 60Hz and 1080p 144Hz fall into this category.
+ * Find number of such displays connected.
+ */
+- for (i = 0; i < adev->mode_info.num_crtc; i++) {
+- if (!(adev->pm.dpm.new_active_crtcs & (1 << i)) ||
+- !adev->mode_info.crtcs[i]->enabled)
+- continue;
+-
+- conn = to_amdgpu_connector(adev->mode_info.crtcs[i]->connector);
+-
+- if (conn->pixelclock_for_modeset > 297000)
++ for (i = 0; i < display_cfg->num_display; i++) {
++ /* The array only contains active displays. */
++ if (display_cfg->displays[i].pixel_clock > 297000)
+ high_pixelclock_count++;
+ }
+
+@@ -3515,7 +3511,7 @@ static void si_apply_state_adjust_rules(
+ rps->ecclk = 0;
+ }
+
+- if ((adev->pm.dpm.new_active_crtc_count > 1) ||
++ if ((adev->pm.pm_display_cfg.num_display > 1) ||
+ si_dpm_vblank_too_short(adev))
+ disable_mclk_switching = true;
+
+@@ -3663,7 +3659,7 @@ static void si_apply_state_adjust_rules(
+ ps->performance_levels[i].mclk,
+ max_limits->vddc, &ps->performance_levels[i].vddc);
+ btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
+- adev->clock.current_dispclk,
++ display_cfg->display_clk,
+ max_limits->vddc, &ps->performance_levels[i].vddc);
+ }
+
+@@ -4188,16 +4184,16 @@ static void si_program_ds_registers(stru
+
+ static void si_program_display_gap(struct amdgpu_device *adev)
+ {
++ const struct amd_pp_display_configuration *cfg = &adev->pm.pm_display_cfg;
+ u32 tmp, pipe;
+- int i;
+
+ tmp = RREG32(CG_DISPLAY_GAP_CNTL) & ~(DISP1_GAP_MASK | DISP2_GAP_MASK);
+- if (adev->pm.dpm.new_active_crtc_count > 0)
++ if (cfg->num_display > 0)
+ tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM);
+ else
+ tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE);
+
+- if (adev->pm.dpm.new_active_crtc_count > 1)
++ if (cfg->num_display > 1)
+ tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM);
+ else
+ tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE);
+@@ -4207,17 +4203,8 @@ static void si_program_display_gap(struc
+ tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG);
+ pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> DCCG_DISP1_SLOW_SELECT_SHIFT;
+
+- if ((adev->pm.dpm.new_active_crtc_count > 0) &&
+- (!(adev->pm.dpm.new_active_crtcs & (1 << pipe)))) {
+- /* find the first active crtc */
+- for (i = 0; i < adev->mode_info.num_crtc; i++) {
+- if (adev->pm.dpm.new_active_crtcs & (1 << i))
+- break;
+- }
+- if (i == adev->mode_info.num_crtc)
+- pipe = 0;
+- else
+- pipe = i;
++ if (cfg->num_display > 0 && pipe != cfg->crtc_index) {
++ pipe = cfg->crtc_index;
+
+ tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK;
+ tmp |= DCCG_DISP1_SLOW_SELECT(pipe);
+@@ -4228,7 +4215,7 @@ static void si_program_display_gap(struc
+ * This can be a problem on PowerXpress systems or if you want to use the card
+ * for offscreen rendering or compute if there are no crtcs enabled.
+ */
+- si_notify_smc_display_change(adev, adev->pm.dpm.new_active_crtc_count > 0);
++ si_notify_smc_display_change(adev, cfg->num_display > 0);
+ }
+
+ static void si_enable_spread_spectrum(struct amdgpu_device *adev, bool enable)
+@@ -5533,7 +5520,7 @@ static int si_convert_power_level_to_smc
+ (pl->mclk <= pi->mclk_stutter_mode_threshold) &&
+ !eg_pi->uvd_enabled &&
+ (RREG32(DPG_PIPE_STUTTER_CONTROL) & STUTTER_ENABLE) &&
+- (adev->pm.dpm.new_active_crtc_count <= 2)) {
++ (adev->pm.pm_display_cfg.num_display <= 2)) {
+ level->mcFlags |= SISLANDS_SMC_MC_STUTTER_EN;
+
+ if (gmc_pg)
+@@ -5685,7 +5672,7 @@ static bool si_is_state_ulv_compatible(s
+ /* XXX validate against display requirements! */
+
+ for (i = 0; i < adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count; i++) {
+- if (adev->clock.current_dispclk <=
++ if (adev->pm.pm_display_cfg.display_clk <=
+ adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].clk) {
+ if (ulv->pl.vddc <
+ adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].v)
+@@ -5839,30 +5826,22 @@ static int si_upload_ulv_state(struct am
+
+ static int si_upload_smc_data(struct amdgpu_device *adev)
+ {
+- struct amdgpu_crtc *amdgpu_crtc = NULL;
+- int i;
++ const struct amd_pp_display_configuration *cfg = &adev->pm.pm_display_cfg;
+ u32 crtc_index = 0;
+ u32 mclk_change_block_cp_min = 0;
+ u32 mclk_change_block_cp_max = 0;
+
+- for (i = 0; i < adev->mode_info.num_crtc; i++) {
+- if (adev->pm.dpm.new_active_crtcs & (1 << i)) {
+- amdgpu_crtc = adev->mode_info.crtcs[i];
+- break;
+- }
+- }
+-
+ /* When a display is plugged in, program these so that the SMC
+ * performs MCLK switching when it doesn't cause flickering.
+ * When no display is plugged in, there is no need to restrict
+ * MCLK switching, so program them to zero.
+ */
+- if (adev->pm.dpm.new_active_crtc_count && amdgpu_crtc) {
+- crtc_index = amdgpu_crtc->crtc_id;
++ if (cfg->num_display) {
++ crtc_index = cfg->crtc_index;
+
+- if (amdgpu_crtc->line_time) {
+- mclk_change_block_cp_min = 200 / amdgpu_crtc->line_time;
+- mclk_change_block_cp_max = 100 / amdgpu_crtc->line_time;
++ if (cfg->line_time_in_us) {
++ mclk_change_block_cp_min = 200 / cfg->line_time_in_us;
++ mclk_change_block_cp_max = 100 / cfg->line_time_in_us;
+ }
+ }
+
+--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+@@ -1567,16 +1567,7 @@ static void pp_pm_compute_clocks(void *h
+ struct amdgpu_device *adev = hwmgr->adev;
+
+ if (!adev->dc_enabled) {
+- amdgpu_dpm_get_active_displays(adev);
+- adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count;
+- adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev);
+- adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev);
+- /* we have issues with mclk switching with
+- * refresh rates over 120 hz on the non-DC code.
+- */
+- if (adev->pm.pm_display_cfg.vrefresh > 120)
+- adev->pm.pm_display_cfg.min_vblank_time = 0;
+-
++ amdgpu_dpm_get_display_cfg(adev);
+ pp_display_configuration_change(handle,
+ &adev->pm.pm_display_cfg);
+ }
--- /dev/null
+From 5df0d6addb7e9b6f71f7162d1253762a5be9138e Mon Sep 17 00:00:00 2001
+From: Lijo Lazar <lijo.lazar@amd.com>
+Date: Wed, 26 Mar 2025 13:28:38 +0530
+Subject: drm/amdgpu: Add basic validation for RAS header
+
+From: Lijo Lazar <lijo.lazar@amd.com>
+
+commit 5df0d6addb7e9b6f71f7162d1253762a5be9138e upstream.
+
+If RAS header read from EEPROM is corrupted, it could result in trying
+to allocate huge memory for reading the records. Add some validation to
+header fields.
+
+Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
+Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[ RAS_TABLE_VER_V3 is not supported in v6.6.y. ]
+Signed-off-by: Alva Lan <alvalan9@foxmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+@@ -1338,15 +1338,31 @@ int amdgpu_ras_eeprom_init(struct amdgpu
+
+ __decode_table_header_from_buf(hdr, buf);
+
+- if (hdr->version == RAS_TABLE_VER_V2_1) {
++ switch (hdr->version) {
++ case RAS_TABLE_VER_V2_1:
+ control->ras_num_recs = RAS_NUM_RECS_V2_1(hdr);
+ control->ras_record_offset = RAS_RECORD_START_V2_1;
+ control->ras_max_record_count = RAS_MAX_RECORD_COUNT_V2_1;
+- } else {
++ break;
++ case RAS_TABLE_VER_V1:
+ control->ras_num_recs = RAS_NUM_RECS(hdr);
+ control->ras_record_offset = RAS_RECORD_START;
+ control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
++ break;
++ default:
++ dev_err(adev->dev,
++ "RAS header invalid, unsupported version: %u",
++ hdr->version);
++ return -EINVAL;
+ }
++
++ if (control->ras_num_recs > control->ras_max_record_count) {
++ dev_err(adev->dev,
++ "RAS header invalid, records in header: %u max allowed :%u",
++ control->ras_num_recs, control->ras_max_record_count);
++ return -EINVAL;
++ }
++
+ control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset);
+
+ if (hdr->header == RAS_TABLE_HDR_VAL) {
--- /dev/null
+From stable+bounces-219910-greg=kroah.com@vger.kernel.org Fri Feb 27 06:00:25 2026
+From: Jeongjun Park <aha310510@gmail.com>
+Date: Fri, 27 Feb 2026 13:59:52 +0900
+Subject: drm/exynos: vidi: fix to avoid directly dereferencing user pointer
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Inki Dae <inki.dae@samsung.com>, Seung-Woo Kim <sw0312.kim@samsung.com>, Kyungmin Park <kyungmin.park@samsung.com>, David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>, Krzysztof Kozlowski <krzk@kernel.org>, Alim Akhtar <alim.akhtar@samsung.com>, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Jeongjun Park <aha310510@gmail.com>
+Message-ID: <20260227045953.165751-3-aha310510@gmail.com>
+
+From: Jeongjun Park <aha310510@gmail.com>
+
+[ Upstream commit d4c98c077c7fb2dfdece7d605e694b5ea2665085 ]
+
+In vidi_connection_ioctl(), vidi->edid(user pointer) is directly
+dereferenced in the kernel.
+
+This allows arbitrary kernel memory access from the user space, so instead
+of directly accessing the user pointer in the kernel, we should modify it
+to copy edid to kernel memory using copy_from_user() and use it.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Jeongjun Park <aha310510@gmail.com>
+Signed-off-by: Inki Dae <inki.dae@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/exynos/exynos_drm_vidi.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+@@ -252,19 +252,26 @@ int vidi_connection_ioctl(struct drm_dev
+
+ if (vidi->connection) {
+ struct edid *raw_edid;
++ struct edid edid_buf;
++ void *edid_userptr = u64_to_user_ptr(vidi->edid);
+
+- raw_edid = (struct edid *)(unsigned long)vidi->edid;
+- if (!drm_edid_is_valid(raw_edid)) {
++ if (copy_from_user(&edid_buf, edid_userptr, sizeof(struct edid)))
++ return -EFAULT;
++
++ if (!drm_edid_is_valid(&edid_buf)) {
+ DRM_DEV_DEBUG_KMS(ctx->dev,
+ "edid data is invalid.\n");
+ return -EINVAL;
+ }
+- ctx->raw_edid = drm_edid_duplicate(raw_edid);
+- if (!ctx->raw_edid) {
++
++ raw_edid = drm_edid_duplicate(&edid_buf);
++
++ if (!raw_edid) {
+ DRM_DEV_DEBUG_KMS(ctx->dev,
+ "failed to allocate raw_edid.\n");
+ return -ENOMEM;
+ }
++ ctx->raw_edid = raw_edid;
+ } else {
+ /*
+ * with connection = 0, free raw_edid
--- /dev/null
+From stable+bounces-219911-greg=kroah.com@vger.kernel.org Fri Feb 27 06:01:30 2026
+From: Jeongjun Park <aha310510@gmail.com>
+Date: Fri, 27 Feb 2026 13:59:53 +0900
+Subject: drm/exynos: vidi: use ctx->lock to protect struct vidi_context member variables related to memory alloc/free
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Inki Dae <inki.dae@samsung.com>, Seung-Woo Kim <sw0312.kim@samsung.com>, Kyungmin Park <kyungmin.park@samsung.com>, David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>, Krzysztof Kozlowski <krzk@kernel.org>, Alim Akhtar <alim.akhtar@samsung.com>, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Jeongjun Park <aha310510@gmail.com>
+Message-ID: <20260227045953.165751-4-aha310510@gmail.com>
+
+From: Jeongjun Park <aha310510@gmail.com>
+
+[ Upstream commit 52b330799e2d6f825ae2bb74662ec1b10eb954bb ]
+
+Exynos Virtual Display driver performs memory alloc/free operations
+without lock protection, which easily causes concurrency problem.
+
+For example, use-after-free can occur in race scenario like this:
+```
+ CPU0 CPU1 CPU2
+ ---- ---- ----
+ vidi_connection_ioctl()
+ if (vidi->connection) // true
+ drm_edid = drm_edid_alloc(); // alloc drm_edid
+ ...
+ ctx->raw_edid = drm_edid;
+ ...
+ drm_mode_getconnector()
+ drm_helper_probe_single_connector_modes()
+ vidi_get_modes()
+ if (ctx->raw_edid) // true
+ drm_edid_dup(ctx->raw_edid);
+ if (!drm_edid) // false
+ ...
+ vidi_connection_ioctl()
+ if (vidi->connection) // false
+ drm_edid_free(ctx->raw_edid); // free drm_edid
+ ...
+ drm_edid_alloc(drm_edid->edid)
+ kmemdup(edid); // UAF!!
+ ...
+```
+
+To prevent these vulns, at least in vidi_context, member variables related
+to memory alloc/free should be protected with ctx->lock.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Jeongjun Park <aha310510@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/exynos/exynos_drm_vidi.c | 43 +++++++++++++++++++++++++------
+ 1 file changed, 35 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+@@ -186,15 +186,17 @@ static ssize_t vidi_store_connection(str
+ const char *buf, size_t len)
+ {
+ struct vidi_context *ctx = dev_get_drvdata(dev);
+- int ret;
++ int ret, new_connected;
+
+- ret = kstrtoint(buf, 0, &ctx->connected);
++ ret = kstrtoint(buf, 0, &new_connected);
+ if (ret)
+ return ret;
+
+- if (ctx->connected > 1)
++ if (new_connected > 1)
+ return -EINVAL;
+
++ mutex_lock(&ctx->lock);
++
+ /* use fake edid data for test. */
+ if (!ctx->raw_edid)
+ ctx->raw_edid = (struct edid *)fake_edid_info;
+@@ -202,14 +204,21 @@ static ssize_t vidi_store_connection(str
+ /* if raw_edid isn't same as fake data then it can't be tested. */
+ if (ctx->raw_edid != (struct edid *)fake_edid_info) {
+ DRM_DEV_DEBUG_KMS(dev, "edid data is not fake data.\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto fail;
+ }
+
++ ctx->connected = new_connected;
++ mutex_unlock(&ctx->lock);
++
+ DRM_DEV_DEBUG_KMS(dev, "requested connection.\n");
+
+ drm_helper_hpd_irq_event(ctx->drm_dev);
+
+ return len;
++fail:
++ mutex_unlock(&ctx->lock);
++ return ret;
+ }
+
+ static DEVICE_ATTR(connection, 0644, vidi_show_connection,
+@@ -244,11 +253,14 @@ int vidi_connection_ioctl(struct drm_dev
+ return -EINVAL;
+ }
+
++ mutex_lock(&ctx->lock);
+ if (ctx->connected == vidi->connection) {
++ mutex_unlock(&ctx->lock);
+ DRM_DEV_DEBUG_KMS(ctx->dev,
+ "same connection request.\n");
+ return -EINVAL;
+ }
++ mutex_unlock(&ctx->lock);
+
+ if (vidi->connection) {
+ struct edid *raw_edid;
+@@ -271,20 +283,27 @@ int vidi_connection_ioctl(struct drm_dev
+ "failed to allocate raw_edid.\n");
+ return -ENOMEM;
+ }
++ mutex_lock(&ctx->lock);
+ ctx->raw_edid = raw_edid;
++ mutex_unlock(&ctx->lock);
+ } else {
+ /*
+ * with connection = 0, free raw_edid
+ * only if raw edid data isn't same as fake data.
+ */
++ mutex_lock(&ctx->lock);
+ if (ctx->raw_edid && ctx->raw_edid !=
+ (struct edid *)fake_edid_info) {
+ kfree(ctx->raw_edid);
+ ctx->raw_edid = NULL;
+ }
++ mutex_unlock(&ctx->lock);
+ }
+
++ mutex_lock(&ctx->lock);
+ ctx->connected = vidi->connection;
++ mutex_unlock(&ctx->lock);
++
+ drm_helper_hpd_irq_event(ctx->drm_dev);
+
+ return 0;
+@@ -299,7 +318,7 @@ static enum drm_connector_status vidi_de
+ * connection request would come from user side
+ * to do hotplug through specific ioctl.
+ */
+- return ctx->connected ? connector_status_connected :
++ return READ_ONCE(ctx->connected) ? connector_status_connected :
+ connector_status_disconnected;
+ }
+
+@@ -321,22 +340,24 @@ static int vidi_get_modes(struct drm_con
+ struct vidi_context *ctx = ctx_from_connector(connector);
+ struct edid *edid;
+ int edid_len;
+- int count;
++ int count = 0;
+
+ /*
+ * the edid data comes from user side and it would be set
+ * to ctx->raw_edid through specific ioctl.
+ */
++
++ mutex_lock(&ctx->lock);
+ if (!ctx->raw_edid) {
+ DRM_DEV_DEBUG_KMS(ctx->dev, "raw_edid is null.\n");
+- return 0;
++ goto fail;
+ }
+
+ edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
+ edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
+ if (!edid) {
+ DRM_DEV_DEBUG_KMS(ctx->dev, "failed to allocate edid\n");
+- return 0;
++ goto fail;
+ }
+
+ drm_connector_update_edid_property(connector, edid);
+@@ -345,6 +366,8 @@ static int vidi_get_modes(struct drm_con
+
+ kfree(edid);
+
++fail:
++ mutex_unlock(&ctx->lock);
+ return count;
+ }
+
+@@ -490,11 +513,15 @@ static int vidi_remove(struct platform_d
+ {
+ struct vidi_context *ctx = platform_get_drvdata(pdev);
+
++ mutex_lock(&ctx->lock);
++
+ if (ctx->raw_edid != (struct edid *)fake_edid_info) {
+ kfree(ctx->raw_edid);
+ ctx->raw_edid = NULL;
+ }
+
++ mutex_unlock(&ctx->lock);
++
+ component_del(&pdev->dev, &vidi_component_ops);
+
+ return 0;
--- /dev/null
+From stable+bounces-219909-greg=kroah.com@vger.kernel.org Fri Feb 27 06:00:30 2026
+From: Jeongjun Park <aha310510@gmail.com>
+Date: Fri, 27 Feb 2026 13:59:51 +0900
+Subject: drm/exynos: vidi: use priv->vidi_dev for ctx lookup in vidi_connection_ioctl()
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Inki Dae <inki.dae@samsung.com>, Seung-Woo Kim <sw0312.kim@samsung.com>, Kyungmin Park <kyungmin.park@samsung.com>, David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>, Krzysztof Kozlowski <krzk@kernel.org>, Alim Akhtar <alim.akhtar@samsung.com>, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Jeongjun Park <aha310510@gmail.com>
+Message-ID: <20260227045953.165751-2-aha310510@gmail.com>
+
+From: Jeongjun Park <aha310510@gmail.com>
+
+[ Upstream commit d3968a0d85b211e197f2f4f06268a7031079e0d0 ]
+
+vidi_connection_ioctl() retrieves the driver_data from drm_dev->dev to
+obtain a struct vidi_context pointer. However, drm_dev->dev is the
+exynos-drm master device, and the driver_data contained therein is not
+the vidi component device, but a completely different device.
+
+This can lead to various bugs, ranging from null pointer dereferences and
+garbage value accesses to, in unlucky cases, out-of-bounds errors,
+use-after-free errors, and more.
+
+To resolve this issue, we need to store/delete the vidi device pointer in
+exynos_drm_private->vidi_dev during bind/unbind, and then read this
+exynos_drm_private->vidi_dev within ioctl() to obtain the correct
+struct vidi_context pointer.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Jeongjun Park <aha310510@gmail.com>
+Signed-off-by: Inki Dae <inki.dae@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 +
+ drivers/gpu/drm/exynos/exynos_drm_vidi.c | 14 +++++++++++++-
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
++++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
+@@ -199,6 +199,7 @@ struct drm_exynos_file_private {
+ struct exynos_drm_private {
+ struct device *g2d_dev;
+ struct device *dma_dev;
++ struct device *vidi_dev;
+ void *mapping;
+
+ /* for atomic commit */
+--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+@@ -224,9 +224,14 @@ ATTRIBUTE_GROUPS(vidi);
+ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
+ struct drm_file *file_priv)
+ {
+- struct vidi_context *ctx = dev_get_drvdata(drm_dev->dev);
++ struct exynos_drm_private *priv = drm_dev->dev_private;
++ struct device *dev = priv ? priv->vidi_dev : NULL;
++ struct vidi_context *ctx = dev ? dev_get_drvdata(dev) : NULL;
+ struct drm_exynos_vidi_connection *vidi = data;
+
++ if (!ctx)
++ return -ENODEV;
++
+ if (!vidi) {
+ DRM_DEV_DEBUG_KMS(ctx->dev,
+ "user data for vidi is null.\n");
+@@ -386,6 +391,7 @@ static int vidi_bind(struct device *dev,
+ {
+ struct vidi_context *ctx = dev_get_drvdata(dev);
+ struct drm_device *drm_dev = data;
++ struct exynos_drm_private *priv = drm_dev->dev_private;
+ struct drm_encoder *encoder = &ctx->encoder;
+ struct exynos_drm_plane *exynos_plane;
+ struct exynos_drm_plane_config plane_config = { 0 };
+@@ -393,6 +399,8 @@ static int vidi_bind(struct device *dev,
+ int ret;
+
+ ctx->drm_dev = drm_dev;
++ if (priv)
++ priv->vidi_dev = dev;
+
+ plane_config.pixel_formats = formats;
+ plane_config.num_pixel_formats = ARRAY_SIZE(formats);
+@@ -438,8 +446,12 @@ static int vidi_bind(struct device *dev,
+ static void vidi_unbind(struct device *dev, struct device *master, void *data)
+ {
+ struct vidi_context *ctx = dev_get_drvdata(dev);
++ struct drm_device *drm_dev = data;
++ struct exynos_drm_private *priv = drm_dev->dev_private;
+
+ del_timer_sync(&ctx->timer);
++ if (priv)
++ priv->vidi_dev = NULL;
+ }
+
+ static const struct component_ops vidi_component_ops = {
--- /dev/null
+From stable+bounces-222982-greg=kroah.com@vger.kernel.org Wed Mar 4 06:56:20 2026
+From: Li hongliang <1468888505@139.com>
+Date: Wed, 4 Mar 2026 13:55:56 +0800
+Subject: f2fs: zone: fix to avoid inconsistence in between SIT and SSA
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org, chao@kernel.org
+Cc: patches@lists.linux.dev, linux-kernel@vger.kernel.org, jaegeuk@kernel.org, daehojeong@google.com, linux-f2fs-devel@lists.sourceforge.net
+Message-ID: <20260304055556.2595295-1-1468888505@139.com>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 773704c1ef96a8b70d0d186ab725f50548de82c4 ]
+
+w/ below testcase, it will cause inconsistence in between SIT and SSA.
+
+create_null_blk 512 2 1024 1024
+mkfs.f2fs -m /dev/nullb0
+mount /dev/nullb0 /mnt/f2fs/
+touch /mnt/f2fs/file
+f2fs_io pinfile set /mnt/f2fs/file
+fallocate -l 4GiB /mnt/f2fs/file
+
+F2FS-fs (nullb0): Inconsistent segment (0) type [1, 0] in SSA and SIT
+CPU: 5 UID: 0 PID: 2398 Comm: fallocate Tainted: G O 6.13.0-rc1 #84
+Tainted: [O]=OOT_MODULE
+Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xb3/0xd0
+ dump_stack+0x14/0x20
+ f2fs_handle_critical_error+0x18c/0x220 [f2fs]
+ f2fs_stop_checkpoint+0x38/0x50 [f2fs]
+ do_garbage_collect+0x674/0x6e0 [f2fs]
+ f2fs_gc_range+0x12b/0x230 [f2fs]
+ f2fs_allocate_pinning_section+0x5c/0x150 [f2fs]
+ f2fs_expand_inode_data+0x1cc/0x3c0 [f2fs]
+ f2fs_fallocate+0x3c3/0x410 [f2fs]
+ vfs_fallocate+0x15f/0x4b0
+ __x64_sys_fallocate+0x4a/0x80
+ x64_sys_call+0x15e8/0x1b80
+ do_syscall_64+0x68/0x130
+ entry_SYSCALL_64_after_hwframe+0x67/0x6f
+RIP: 0033:0x7f9dba5197ca
+F2FS-fs (nullb0): Stopped filesystem due to reason: 4
+
+The reason is f2fs_gc_range() may try to migrate block in curseg, however,
+its SSA block is not uptodate due to the last summary block data is still
+in cache of curseg.
+
+In this patch, we add a condition in f2fs_gc_range() to check whether
+section is opened or not, and skip block migration for opened section.
+
+Fixes: 9703d69d9d15 ("f2fs: support file pinning for zoned devices")
+Reviewed-by: Daeho Jeong <daehojeong@google.com>
+Cc: Daeho Jeong <daehojeong@google.com>
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ Minor conflict resolved. ]
+Signed-off-by: Li hongliang <1468888505@139.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/gc.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -2019,6 +2019,9 @@ int f2fs_gc_range(struct f2fs_sb_info *s
+ if (!get_valid_blocks(sbi, segno, true))
+ continue;
+
++ if (IS_CURSEC(sbi, GET_SEC_FROM_SEG(sbi, segno)))
++ continue;
++
+ do_garbage_collect(sbi, segno, &gc_list, FG_GC,
+ dry_run_sections == 0);
+ put_gc_inode(&gc_list);
--- /dev/null
+From 9b8c88f875c04d4cb9111bd5dd9291c7e9691bf5 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 26 Aug 2025 13:44:35 +0000
+Subject: l2tp: do not use sock_hold() in pppol2tp_session_get_sock()
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 9b8c88f875c04d4cb9111bd5dd9291c7e9691bf5 upstream.
+
+pppol2tp_session_get_sock() is using RCU, it must be ready
+for sk_refcnt being zero.
+
+Commit ee40fb2e1eb5 ("l2tp: protect sock pointer of
+struct pppol2tp_session with RCU") was correct because it
+had a call_rcu(..., pppol2tp_put_sk) which was later removed in blamed commit.
+
+pppol2tp_recv() can use pppol2tp_session_get_sock() as well.
+
+Fixes: c5cbaef992d6 ("l2tp: refactor ppp socket/session relationship")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: James Chapman <jchapman@katalix.com>
+Reviewed-by: Guillaume Nault <gnault@redhat.com>
+Link: https://patch.msgid.link/20250826134435.1683435-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Qingfang Deng <dqfext@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_ppp.c | 25 ++++++++-----------------
+ 1 file changed, 8 insertions(+), 17 deletions(-)
+
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -130,22 +130,12 @@ static const struct ppp_channel_ops pppo
+
+ static const struct proto_ops pppol2tp_ops;
+
+-/* Retrieves the pppol2tp socket associated to a session.
+- * A reference is held on the returned socket, so this function must be paired
+- * with sock_put().
+- */
++/* Retrieves the pppol2tp socket associated to a session. */
+ static struct sock *pppol2tp_session_get_sock(struct l2tp_session *session)
+ {
+ struct pppol2tp_session *ps = l2tp_session_priv(session);
+- struct sock *sk;
+
+- rcu_read_lock();
+- sk = rcu_dereference(ps->sk);
+- if (sk)
+- sock_hold(sk);
+- rcu_read_unlock();
+-
+- return sk;
++ return rcu_dereference(ps->sk);
+ }
+
+ /* Helpers to obtain tunnel/session contexts from sockets.
+@@ -211,14 +201,13 @@ end:
+
+ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len)
+ {
+- struct pppol2tp_session *ps = l2tp_session_priv(session);
+- struct sock *sk = NULL;
++ struct sock *sk;
+
+ /* If the socket is bound, send it in to PPP's input queue. Otherwise
+ * queue it on the session socket.
+ */
+ rcu_read_lock();
+- sk = rcu_dereference(ps->sk);
++ sk = pppol2tp_session_get_sock(session);
+ if (!sk)
+ goto no_sock;
+
+@@ -528,13 +517,14 @@ static void pppol2tp_show(struct seq_fil
+ struct l2tp_session *session = arg;
+ struct sock *sk;
+
++ rcu_read_lock();
+ sk = pppol2tp_session_get_sock(session);
+ if (sk) {
+ struct pppox_sock *po = pppox_sk(sk);
+
+ seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan));
+- sock_put(sk);
+ }
++ rcu_read_unlock();
+ }
+
+ static void pppol2tp_session_init(struct l2tp_session *session)
+@@ -1540,6 +1530,7 @@ static void pppol2tp_seq_session_show(st
+ port = ntohs(inet->inet_sport);
+ }
+
++ rcu_read_lock();
+ sk = pppol2tp_session_get_sock(session);
+ if (sk) {
+ state = sk->sk_state;
+@@ -1575,8 +1566,8 @@ static void pppol2tp_seq_session_show(st
+ struct pppox_sock *po = pppox_sk(sk);
+
+ seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan));
+- sock_put(sk);
+ }
++ rcu_read_unlock();
+ }
+
+ static int pppol2tp_seq_show(struct seq_file *m, void *v)
--- /dev/null
+From matttbe@kernel.org Fri Mar 6 18:49:49 2026
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Fri, 6 Mar 2026 18:49:08 +0100
+Subject: mptcp: pm: in-kernel: always set ID as avail when rm endp
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: MPTCP Upstream <mptcp@lists.linux.dev>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, syzbot+f56f7d56e2c6e11a01b6@syzkaller.appspotmail.com, Mat Martineau <martineau@kernel.org>, Jakub Kicinski <kuba@kernel.org>
+Message-ID: <20260306174907.2519153-2-matttbe@kernel.org>
+
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+
+commit d191101dee25567c2af3b28565f45346c33d65f5 upstream.
+
+Syzkaller managed to find a combination of actions that was generating
+this warning:
+
+ WARNING: net/mptcp/pm_kernel.c:1074 at __mark_subflow_endp_available net/mptcp/pm_kernel.c:1074 [inline], CPU#1: syz.7.48/2535
+ WARNING: net/mptcp/pm_kernel.c:1074 at mptcp_pm_nl_fullmesh net/mptcp/pm_kernel.c:1446 [inline], CPU#1: syz.7.48/2535
+ WARNING: net/mptcp/pm_kernel.c:1074 at mptcp_pm_nl_set_flags_all net/mptcp/pm_kernel.c:1474 [inline], CPU#1: syz.7.48/2535
+ WARNING: net/mptcp/pm_kernel.c:1074 at mptcp_pm_nl_set_flags+0x5de/0x640 net/mptcp/pm_kernel.c:1538, CPU#1: syz.7.48/2535
+ Modules linked in:
+ CPU: 1 UID: 0 PID: 2535 Comm: syz.7.48 Not tainted 6.18.0-03987-gea5f5e676cf5 #17 PREEMPT(voluntary)
+ Hardware name: QEMU Ubuntu 25.10 PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
+ RIP: 0010:__mark_subflow_endp_available net/mptcp/pm_kernel.c:1074 [inline]
+ RIP: 0010:mptcp_pm_nl_fullmesh net/mptcp/pm_kernel.c:1446 [inline]
+ RIP: 0010:mptcp_pm_nl_set_flags_all net/mptcp/pm_kernel.c:1474 [inline]
+ RIP: 0010:mptcp_pm_nl_set_flags+0x5de/0x640 net/mptcp/pm_kernel.c:1538
+ Code: 89 c7 e8 c5 8c 73 fe e9 f7 fd ff ff 49 83 ef 80 e8 b7 8c 73 fe 4c 89 ff be 03 00 00 00 e8 4a 29 e3 fe eb ac e8 a3 8c 73 fe 90 <0f> 0b 90 e9 3d ff ff ff e8 95 8c 73 fe b8 a1 ff ff ff eb 1a e8 89
+ RSP: 0018:ffffc9001535b820 EFLAGS: 00010287
+ netdevsim0: tun_chr_ioctl cmd 1074025677
+ RAX: ffffffff82da294d RBX: 0000000000000001 RCX: 0000000000080000
+ RDX: ffffc900096d0000 RSI: 00000000000006d6 RDI: 00000000000006d7
+ netdevsim0: linktype set to 823
+ RBP: ffff88802cdb2240 R08: 00000000000104ae R09: ffffffffffffffff
+ R10: ffffffff82da27d4 R11: 0000000000000000 R12: 0000000000000000
+ R13: ffff88801246d8c0 R14: ffffc9001535b8b8 R15: ffff88802cdb1800
+ FS: 00007fc6ac5a76c0(0000) GS:ffff8880f90c8000(0000) knlGS:0000000000000000
+ netlink: 'syz.3.50': attribute type 5 has an invalid length.
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ netlink: 1232 bytes leftover after parsing attributes in process `syz.3.50'.
+ CR2: 0000200000010000 CR3: 0000000025b1a000 CR4: 0000000000350ef0
+ Call Trace:
+ <TASK>
+ mptcp_pm_set_flags net/mptcp/pm_netlink.c:277 [inline]
+ mptcp_pm_nl_set_flags_doit+0x1d7/0x210 net/mptcp/pm_netlink.c:282
+ genl_family_rcv_msg_doit+0x117/0x180 net/netlink/genetlink.c:1115
+ genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline]
+ genl_rcv_msg+0x3a8/0x3f0 net/netlink/genetlink.c:1210
+ netlink_rcv_skb+0x16d/0x240 net/netlink/af_netlink.c:2550
+ genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219
+ netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
+ netlink_unicast+0x3e9/0x4c0 net/netlink/af_netlink.c:1344
+ netlink_sendmsg+0x4ab/0x5b0 net/netlink/af_netlink.c:1894
+ sock_sendmsg_nosec net/socket.c:718 [inline]
+ __sock_sendmsg+0xc9/0xf0 net/socket.c:733
+ ____sys_sendmsg+0x272/0x3b0 net/socket.c:2608
+ ___sys_sendmsg+0x2de/0x320 net/socket.c:2662
+ __sys_sendmsg net/socket.c:2694 [inline]
+ __do_sys_sendmsg net/socket.c:2699 [inline]
+ __se_sys_sendmsg net/socket.c:2697 [inline]
+ __x64_sys_sendmsg+0x110/0x1a0 net/socket.c:2697
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xed/0x360 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ RIP: 0033:0x7fc6adb66f6d
+ Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
+ RSP: 002b:00007fc6ac5a6ff8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+ RAX: ffffffffffffffda RBX: 00007fc6addf5fa0 RCX: 00007fc6adb66f6d
+ RDX: 0000000000048084 RSI: 00002000000002c0 RDI: 000000000000000e
+ RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
+ R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+ netlink: 'syz.5.51': attribute type 2 has an invalid length.
+ R13: 00007fff25e91fe0 R14: 00007fc6ac5a7ce4 R15: 00007fff25e920d7
+ </TASK>
+
+The actions that caused that seem to be:
+
+ - Create an MPTCP endpoint for address A without any flags
+ - Create a new MPTCP connection from address A
+ - Remove the MPTCP endpoint: the corresponding subflows will be removed
+ - Recreate the endpoint with the same ID, but with the subflow flag
+ - Change the same endpoint to add the fullmesh flag
+
+In this case, msk->pm.local_addr_used has been kept to 0 as expected,
+but the corresponding bit in msk->pm.id_avail_bitmap was still unset
+after having removed the endpoint, causing the splat later on.
+
+When removing an endpoint, the corresponding endpoint ID was only marked
+as available for "signal" types with an announced address, plus all
+"subflow" types, but not the other types like an endpoint corresponding
+to the initial subflow. In these cases, re-creating an endpoint with the
+same ID didn't signal/create anything. Here, adding the fullmesh flag
+was creating the splat when calling __mark_subflow_endp_available() from
+mptcp_pm_nl_fullmesh(), because msk->pm.local_addr_used was set to 0
+while the ID was marked as used.
+
+To fix this issue, the corresponding bit in msk->pm.id_avail_bitmap can
+always be set as available when removing an MPTCP in-kernel endpoint. In
+other words, moving the call to __set_bit() to do it in all cases,
+except for "subflow" types where this bit is handled in a dedicated
+helper.
+
+Note: instead of adding a new spin_(un)lock_bh that would be taken in
+all cases, do all the actions requiring the spin lock under the same
+block.
+
+This modification potentially fixes another issue reported by syzbot,
+see [1]. But without a reproducer or more details about what exactly
+happened before, it is hard to confirm.
+
+Fixes: e255683c06df ("mptcp: pm: re-using ID of unused removed ADD_ADDR")
+Cc: stable@vger.kernel.org
+Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/606
+Reported-by: syzbot+f56f7d56e2c6e11a01b6@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/68fcfc4a.050a0220.346f24.02fb.GAE@google.com [1]
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20260205-net-mptcp-misc-fixes-6-19-rc8-v2-1-c2720ce75c34@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Conflict in pm_netlink.c, because commit 8617e85e04bd ("mptcp: pm:
+ split in-kernel PM specific code") is not in this version, and move
+ code from pm_netlink.c to pm_kernel.c. Also, commit 636113918508
+ ("mptcp: pm: remove '_nl' from mptcp_pm_nl_rm_addr_received") renamed
+ mptcp_pm_nl_rm_subflow_received() to mptcp_pm_rm_subflow(). Apart from
+ that, the same patch can be applied in pm_netlink.c. ]
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/pm_netlink.c | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1647,10 +1647,8 @@ static bool mptcp_pm_remove_anno_addr(st
+ ret = remove_anno_list_by_saddr(msk, addr);
+ if (ret || force) {
+ spin_lock_bh(&msk->pm.lock);
+- if (ret) {
+- __set_bit(addr->id, msk->pm.id_avail_bitmap);
++ if (ret)
+ msk->pm.add_addr_signaled--;
+- }
+ mptcp_pm_remove_addr(msk, &list);
+ spin_unlock_bh(&msk->pm.lock);
+ }
+@@ -1688,17 +1686,15 @@ static int mptcp_nl_remove_subflow_and_s
+ !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
+
+ list.ids[0] = mptcp_endp_get_local_id(msk, addr);
+- if (remove_subflow) {
+- spin_lock_bh(&msk->pm.lock);
+- mptcp_pm_nl_rm_subflow_received(msk, &list);
+- spin_unlock_bh(&msk->pm.lock);
+- }
+
+- if (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
+- spin_lock_bh(&msk->pm.lock);
++ spin_lock_bh(&msk->pm.lock);
++ if (remove_subflow)
++ mptcp_pm_nl_rm_subflow_received(msk, &list);
++ if (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW)
+ __mark_subflow_endp_available(msk, list.ids[0]);
+- spin_unlock_bh(&msk->pm.lock);
+- }
++ else /* mark endp ID as available, e.g. Signal or MPC endp */
++ __set_bit(addr->id, msk->pm.id_avail_bitmap);
++ spin_unlock_bh(&msk->pm.lock);
+
+ if (msk->mpc_endpoint_id == entry->addr.id)
+ msk->mpc_endpoint_id = 0;
--- /dev/null
+From 06e219f6a706c367c93051f408ac61417643d2f9 Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+Date: Mon, 15 Dec 2025 17:02:35 +0200
+Subject: net: dsa: properly keep track of conduit reference
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+commit 06e219f6a706c367c93051f408ac61417643d2f9 upstream.
+
+Problem description
+-------------------
+
+DSA has a mumbo-jumbo of reference handling of the conduit net device
+and its kobject which, sadly, is just wrong and doesn't make sense.
+
+There are two distinct problems.
+
+1. The OF path, which uses of_find_net_device_by_node(), never releases
+ the elevated refcount on the conduit's kobject. Nominally, the OF and
+ non-OF paths should result in objects having identical reference
+ counts taken, and it is already suspicious that
+ dsa_dev_to_net_device() has a put_device() call which is missing in
+ dsa_port_parse_of(), but we can actually even verify that an issue
+ exists. With CONFIG_DEBUG_KOBJECT_RELEASE=y, if we run this command
+ "before" and "after" applying this patch:
+
+(unbind the conduit driver for net device eno2)
+echo 0000:00:00.2 > /sys/bus/pci/drivers/fsl_enetc/unbind
+
+we see these lines in the output diff which appear only with the patch
+applied:
+
+kobject: 'eno2' (ffff002009a3a6b8): kobject_release, parent 0000000000000000 (delayed 1000)
+kobject: '109' (ffff0020099d59a0): kobject_release, parent 0000000000000000 (delayed 1000)
+
+2. After we find the conduit interface one way (OF) or another (non-OF),
+ it can get unregistered at any time, and DSA remains with a long-lived,
+ but in this case stale, cpu_dp->conduit pointer. Holding the net
+ device's underlying kobject isn't actually of much help, it just
+ prevents it from being freed (but we never need that kobject
+ directly). What helps us to prevent the net device from being
+ unregistered is the parallel netdev reference mechanism (dev_hold()
+ and dev_put()).
+
+Actually we actually use that netdev tracker mechanism implicitly on
+user ports since commit 2f1e8ea726e9 ("net: dsa: link interfaces with
+the DSA master to get rid of lockdep warnings"), via netdev_upper_dev_link().
+But time still passes at DSA switch probe time between the initial
+of_find_net_device_by_node() code and the user port creation time, time
+during which the conduit could unregister itself and DSA wouldn't know
+about it.
+
+So we have to run of_find_net_device_by_node() under rtnl_lock() to
+prevent that from happening, and release the lock only with the netdev
+tracker having acquired the reference.
+
+Do we need to keep the reference until dsa_unregister_switch() /
+dsa_switch_shutdown()?
+1: Maybe yes. A switch device will still be registered even if all user
+ ports failed to probe, see commit 86f8b1c01a0a ("net: dsa: Do not
+ make user port errors fatal"), and the cpu_dp->conduit pointers
+ remain valid. I haven't audited all call paths to see whether they
+ will actually use the conduit in lack of any user port, but if they
+ do, it seems safer to not rely on user ports for that reference.
+2. Definitely yes. We support changing the conduit which a user port is
+ associated to, and we can get into a situation where we've moved all
+ user ports away from a conduit, thus no longer hold any reference to
+ it via the net device tracker. But we shouldn't let it go nonetheless
+ - see the next change in relation to dsa_tree_find_first_conduit()
+ and LAG conduits which disappear.
+ We have to be prepared to return to the physical conduit, so the CPU
+ port must explicitly keep another reference to it. This is also to
+ say: the user ports and their CPU ports may not always keep a
+ reference to the same conduit net device, and both are needed.
+
+As for the conduit's kobject for the /sys/class/net/ entry, we don't
+care about it, we can release it as soon as we hold the net device
+object itself.
+
+History and blame attribution
+-----------------------------
+
+The code has been refactored so many times, it is very difficult to
+follow and properly attribute a blame, but I'll try to make a short
+history which I hope to be correct.
+
+We have two distinct probing paths:
+- one for OF, introduced in 2016 in commit 83c0afaec7b7 ("net: dsa: Add
+ new binding implementation")
+- one for non-OF, introduced in 2017 in commit 71e0bbde0d88 ("net: dsa:
+ Add support for platform data")
+
+These are both complete rewrites of the original probing paths (which
+used struct dsa_switch_driver and other weird stuff, instead of regular
+devices on their respective buses for register access, like MDIO, SPI,
+I2C etc):
+- one for OF, introduced in 2013 in commit 5e95329b701c ("dsa: add
+ device tree bindings to register DSA switches")
+- one for non-OF, introduced in 2008 in commit 91da11f870f0 ("net:
+ Distributed Switch Architecture protocol support")
+
+except for tiny bits and pieces like dsa_dev_to_net_device() which were
+seemingly carried over since the original commit, and used to this day.
+
+The point is that the original probing paths received a fix in 2015 in
+the form of commit 679fb46c5785 ("net: dsa: Add missing master netdev
+dev_put() calls"), but the fix never made it into the "new" (dsa2)
+probing paths that can still be traced to today, and the fixed probing
+path was later deleted in 2019 in commit 93e86b3bc842 ("net: dsa: Remove
+legacy probing support").
+
+That is to say, the new probing paths were never quite correct in this
+area.
+
+The existence of the legacy probing support which was deleted in 2019
+explains why dsa_dev_to_net_device() returns a conduit with elevated
+refcount (because it was supposed to be released during
+dsa_remove_dst()). After the removal of the legacy code, the only user
+of dsa_dev_to_net_device() calls dev_put(conduit) immediately after this
+function returns. This pattern makes no sense today, and can only be
+interpreted historically to understand why dev_hold() was there in the
+first place.
+
+Change details
+--------------
+
+Today we have a better netdev tracking infrastructure which we should
+use. Logically netdev_hold() belongs in common code
+(dsa_port_parse_cpu(), where dp->conduit is assigned), but there is a
+tradeoff to be made with the rtnl_lock() section which would become a
+bit too long if we did that - dsa_port_parse_cpu() also calls
+request_module(). So we duplicate a bit of logic in order for the
+callers of dsa_port_parse_cpu() to be the ones responsible of holding
+the conduit reference and releasing it on error. This shortens the
+rtnl_lock() section significantly.
+
+In the dsa_switch_probe() error path, dsa_switch_release_ports() will be
+called in a number of situations, one being where dsa_port_parse_cpu()
+maybe didn't get the chance to run at all (a different port failed
+earlier, etc). So we have to test for the conduit being NULL prior to
+calling netdev_put().
+
+There have still been so many transformations to the code since the
+blamed commits (rename master -> conduit, commit 0650bf52b31f ("net:
+dsa: be compatible with masters which unregister on shutdown")), that it
+only makes sense to fix the code using the best methods available today
+and see how it can be backported to stable later. I suspect the fix
+cannot even be backported to kernels which lack dsa_switch_shutdown(),
+and I suspect this is also maybe why the long-lived conduit reference
+didn't make it into the new DSA probing paths at the time (problems
+during shutdown).
+
+Because dsa_dev_to_net_device() has a single call site and has to be
+changed anyway, the logic was just absorbed into the non-OF
+dsa_port_parse().
+
+Tested on the ocelot/felix switch and on dsa_loop, both on the NXP
+LS1028A with CONFIG_DEBUG_KOBJECT_RELEASE=y.
+
+Reported-by: Ma Ke <make24@iscas.ac.cn>
+Closes: https://lore.kernel.org/netdev/20251214131204.4684-1-make24@iscas.ac.cn/
+Fixes: 83c0afaec7b7 ("net: dsa: Add new binding implementation")
+Fixes: 71e0bbde0d88 ("net: dsa: Add support for platform data")
+Reviewed-by: Jonas Gorski <jonas.gorski@gmail.com>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://patch.msgid.link/20251215150236.3931670-1-vladimir.oltean@nxp.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ backport: "conduit" -> "master" in code, kept original commit message ]
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/dsa.h | 1
+ net/dsa/dsa.c | 59 +++++++++++++++++++++++++++++++-----------------------
+ 2 files changed, 35 insertions(+), 25 deletions(-)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -297,6 +297,7 @@ struct dsa_port {
+ struct devlink_port devlink_port;
+ struct phylink *pl;
+ struct phylink_config pl_config;
++ netdevice_tracker master_tracker;
+ struct dsa_lag *lag;
+ struct net_device *hsr_dev;
+
+--- a/net/dsa/dsa.c
++++ b/net/dsa/dsa.c
+@@ -1257,14 +1257,25 @@ static int dsa_port_parse_of(struct dsa_
+ if (ethernet) {
+ struct net_device *master;
+ const char *user_protocol;
++ int err;
+
++ rtnl_lock();
+ master = of_find_net_device_by_node(ethernet);
+ of_node_put(ethernet);
+- if (!master)
++ if (!master) {
++ rtnl_unlock();
+ return -EPROBE_DEFER;
++ }
++
++ netdev_hold(master, &dp->master_tracker, GFP_KERNEL);
++ put_device(&master->dev);
++ rtnl_unlock();
+
+ user_protocol = of_get_property(dn, "dsa-tag-protocol", NULL);
+- return dsa_port_parse_cpu(dp, master, user_protocol);
++ err = dsa_port_parse_cpu(dp, master, user_protocol);
++ if (err)
++ netdev_put(master, &dp->master_tracker);
++ return err;
+ }
+
+ if (link)
+@@ -1397,37 +1408,30 @@ static struct device *dev_find_class(str
+ return device_find_child(parent, class, dev_is_class);
+ }
+
+-static struct net_device *dsa_dev_to_net_device(struct device *dev)
+-{
+- struct device *d;
+-
+- d = dev_find_class(dev, "net");
+- if (d != NULL) {
+- struct net_device *nd;
+-
+- nd = to_net_dev(d);
+- dev_hold(nd);
+- put_device(d);
+-
+- return nd;
+- }
+-
+- return NULL;
+-}
+-
+ static int dsa_port_parse(struct dsa_port *dp, const char *name,
+ struct device *dev)
+ {
+ if (!strcmp(name, "cpu")) {
+ struct net_device *master;
++ struct device *d;
++ int err;
+
+- master = dsa_dev_to_net_device(dev);
+- if (!master)
++ rtnl_lock();
++ d = dev_find_class(dev, "net");
++ if (!d) {
++ rtnl_unlock();
+ return -EPROBE_DEFER;
++ }
+
+- dev_put(master);
++ master = to_net_dev(d);
++ netdev_hold(master, &dp->master_tracker, GFP_KERNEL);
++ put_device(d);
++ rtnl_unlock();
+
+- return dsa_port_parse_cpu(dp, master, NULL);
++ err = dsa_port_parse_cpu(dp, master, NULL);
++ if (err)
++ netdev_put(master, &dp->master_tracker);
++ return err;
+ }
+
+ if (!strcmp(name, "dsa"))
+@@ -1495,6 +1499,9 @@ static void dsa_switch_release_ports(str
+ struct dsa_vlan *v, *n;
+
+ dsa_switch_for_each_port_safe(dp, next, ds) {
++ if (dsa_port_is_cpu(dp) && dp->master)
++ netdev_put(dp->master, &dp->master_tracker);
++
+ /* These are either entries that upper layers lost track of
+ * (probably due to bugs), or installed through interfaces
+ * where one does not necessarily have to remove them, like
+@@ -1639,8 +1646,10 @@ void dsa_switch_shutdown(struct dsa_swit
+ /* Disconnect from further netdevice notifiers on the master,
+ * since netdev_uses_dsa() will now return false.
+ */
+- dsa_switch_for_each_cpu_port(dp, ds)
++ dsa_switch_for_each_cpu_port(dp, ds) {
+ dp->master->dsa_ptr = NULL;
++ netdev_put(dp->master, &dp->master_tracker);
++ }
+
+ rtnl_unlock();
+ out:
--- /dev/null
+From ruohanlan@aliyun.com Mon Mar 2 08:37:18 2026
+From: Ruohan Lan <ruohanlan@aliyun.com>
+Date: Mon, 2 Mar 2026 15:36:28 +0800
+Subject: net: dst: add four helpers to annotate data-races around dst->dev
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: edumazet@google.com, kuniyu@google.com, kuba@kernel.org, dsahern@kernel.org, netdev@vger.kernel.org, Ruohan Lan <ruohanlan@aliyun.com>
+Message-ID: <20260302073630.988982-2-ruohanlan@aliyun.com>
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 88fe14253e181878c2ddb51a298ae8c468a63010 ]
+
+dst->dev is read locklessly in many contexts,
+and written in dst_dev_put().
+
+Fixing all the races is going to need many changes.
+
+We probably will have to add full RCU protection.
+
+Add three helpers to ease this painful process.
+
+static inline struct net_device *dst_dev(const struct dst_entry *dst)
+{
+ return READ_ONCE(dst->dev);
+}
+
+static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
+{
+ return dst_dev(skb_dst(skb));
+}
+
+static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
+{
+ return dev_net(skb_dst_dev(skb));
+}
+
+static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
+{
+ return dev_net_rcu(skb_dst_dev(skb));
+}
+
+Fixes: 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20250630121934.3399505-7-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Minor context conflict resolved. ]
+Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/dst.h | 20 ++++++++++++++++++++
+ net/core/dst.c | 4 ++--
+ net/core/sock.c | 8 ++++----
+ 3 files changed, 26 insertions(+), 6 deletions(-)
+
+--- a/include/net/dst.h
++++ b/include/net/dst.h
+@@ -581,6 +581,26 @@ static inline struct net_device *skb_dst
+ return dst_dev_rcu(skb_dst(skb));
+ }
+
++static inline struct net_device *dst_dev(const struct dst_entry *dst)
++{
++ return READ_ONCE(dst->dev);
++}
++
++static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
++{
++ return dst_dev(skb_dst(skb));
++}
++
++static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
++{
++ return dev_net(skb_dst_dev(skb));
++}
++
++static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
++{
++ return dev_net_rcu(skb_dst_dev(skb));
++}
++
+ struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
+ void dst_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
+ struct sk_buff *skb, u32 mtu, bool confirm_neigh);
+--- a/net/core/dst.c
++++ b/net/core/dst.c
+@@ -153,7 +153,7 @@ void dst_dev_put(struct dst_entry *dst)
+ dst->ops->ifdown(dst, dev);
+ WRITE_ONCE(dst->input, dst_discard);
+ WRITE_ONCE(dst->output, dst_discard_out);
+- dst->dev = blackhole_netdev;
++ WRITE_ONCE(dst->dev, blackhole_netdev);
+ netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker,
+ GFP_ATOMIC);
+ }
+@@ -266,7 +266,7 @@ unsigned int dst_blackhole_mtu(const str
+ {
+ unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
+
+- return mtu ? : dst->dev->mtu;
++ return mtu ? : dst_dev(dst)->mtu;
+ }
+ EXPORT_SYMBOL_GPL(dst_blackhole_mtu);
+
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2450,8 +2450,8 @@ static u32 sk_dst_gso_max_size(struct so
+ !ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr));
+ #endif
+ /* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */
+- max_size = is_ipv6 ? READ_ONCE(dst->dev->gso_max_size) :
+- READ_ONCE(dst->dev->gso_ipv4_max_size);
++ max_size = is_ipv6 ? READ_ONCE(dst_dev(dst)->gso_max_size) :
++ READ_ONCE(dst_dev(dst)->gso_ipv4_max_size);
+ if (max_size > GSO_LEGACY_MAX_SIZE && !sk_is_tcp(sk))
+ max_size = GSO_LEGACY_MAX_SIZE;
+
+@@ -2462,7 +2462,7 @@ void sk_setup_caps(struct sock *sk, stru
+ {
+ u32 max_segs = 1;
+
+- sk->sk_route_caps = dst->dev->features;
++ sk->sk_route_caps = dst_dev(dst)->features;
+ if (sk_is_tcp(sk))
+ sk->sk_route_caps |= NETIF_F_GSO;
+ if (sk->sk_route_caps & NETIF_F_GSO)
+@@ -2476,7 +2476,7 @@ void sk_setup_caps(struct sock *sk, stru
+ sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
+ sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dst);
+ /* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */
+- max_segs = max_t(u32, READ_ONCE(dst->dev->gso_max_segs), 1);
++ max_segs = max_t(u32, READ_ONCE(dst_dev(dst)->gso_max_segs), 1);
+ }
+ }
+ sk->sk_gso_max_segs = max_segs;
--- /dev/null
+From ruohanlan@aliyun.com Mon Mar 2 08:37:19 2026
+From: Ruohan Lan <ruohanlan@aliyun.com>
+Date: Mon, 2 Mar 2026 15:36:29 +0800
+Subject: net: dst: introduce dst->dev_rcu
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: edumazet@google.com, kuniyu@google.com, kuba@kernel.org, dsahern@kernel.org, netdev@vger.kernel.org, Ruohan Lan <ruohanlan@aliyun.com>
+Message-ID: <20260302073630.988982-3-ruohanlan@aliyun.com>
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit caedcc5b6df1b2e2b5f39079e3369c1d4d5c5f50 ]
+
+Followup of commit 88fe14253e18 ("net: dst: add four helpers
+to annotate data-races around dst->dev").
+
+We want to gradually add explicit RCU protection to dst->dev,
+including lockdep support.
+
+Add an union to alias dst->dev_rcu and dst->dev.
+
+Add dst_dev_net_rcu() helper.
+
+Fixes: 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://patch.msgid.link/20250828195823.3958522-2-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Minor context conflict resolved. ]
+Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/dst.h | 16 +++++++++++-----
+ net/core/dst.c | 2 +-
+ net/ipv4/route.c | 4 ++--
+ 3 files changed, 14 insertions(+), 8 deletions(-)
+
+--- a/include/net/dst.h
++++ b/include/net/dst.h
+@@ -24,7 +24,10 @@
+ struct sk_buff;
+
+ struct dst_entry {
+- struct net_device *dev;
++ union {
++ struct net_device *dev;
++ struct net_device __rcu *dev_rcu;
++ };
+ struct dst_ops *ops;
+ unsigned long _metrics;
+ unsigned long expires;
+@@ -571,9 +574,12 @@ static inline void skb_dst_update_pmtu_n
+
+ static inline struct net_device *dst_dev_rcu(const struct dst_entry *dst)
+ {
+- /* In the future, use rcu_dereference(dst->dev) */
+- WARN_ON_ONCE(!rcu_read_lock_held());
+- return READ_ONCE(dst->dev);
++ return rcu_dereference(dst->dev_rcu);
++}
++
++static inline struct net *dst_dev_net_rcu(const struct dst_entry *dst)
++{
++ return dev_net_rcu(dst_dev_rcu(dst));
+ }
+
+ static inline struct net_device *skb_dst_dev_rcu(const struct sk_buff *skb)
+@@ -598,7 +604,7 @@ static inline struct net *skb_dst_dev_ne
+
+ static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
+ {
+- return dev_net_rcu(skb_dst_dev(skb));
++ return dev_net_rcu(skb_dst_dev_rcu(skb));
+ }
+
+ struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
+--- a/net/core/dst.c
++++ b/net/core/dst.c
+@@ -153,7 +153,7 @@ void dst_dev_put(struct dst_entry *dst)
+ dst->ops->ifdown(dst, dev);
+ WRITE_ONCE(dst->input, dst_discard);
+ WRITE_ONCE(dst->output, dst_discard_out);
+- WRITE_ONCE(dst->dev, blackhole_netdev);
++ rcu_assign_pointer(dst->dev_rcu, blackhole_netdev);
+ netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker,
+ GFP_ATOMIC);
+ }
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -1042,7 +1042,7 @@ static void __ip_rt_update_pmtu(struct r
+ return;
+
+ rcu_read_lock();
+- net = dev_net_rcu(dst->dev);
++ net = dst_dev_net_rcu(dst);
+ if (mtu < net->ipv4.ip_rt_min_pmtu) {
+ lock = true;
+ mtu = min(old_mtu, net->ipv4.ip_rt_min_pmtu);
+@@ -1340,7 +1340,7 @@ static unsigned int ipv4_default_advmss(
+ struct net *net;
+
+ rcu_read_lock();
+- net = dev_net_rcu(dst->dev);
++ net = dst_dev_net_rcu(dst);
+ advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size,
+ net->ipv4.ip_rt_min_advmss);
+ rcu_read_unlock();
--- /dev/null
+From stable+bounces-223355-greg=kroah.com@vger.kernel.org Fri Mar 6 16:12:28 2026
+From: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
+Date: Fri, 6 Mar 2026 15:06:56 +0000
+Subject: net: stmmac: remove support for lpi_intr_o
+To: stable@vger.kernel.org
+Cc: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>, Ovidiu Panait <ovidiu.panait.rb@renesas.com>, Jakub Kicinski <kuba@kernel.org>
+Message-ID: <20260306150656.23781-2-ovidiu.panait.rb@renesas.com>
+
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+
+commit 14eb64db8ff07b58a35b98375f446d9e20765674 upstream.
+
+The dwmac databook for v3.74a states that lpi_intr_o is a sideband
+signal which should be used to ungate the application clock, and this
+signal is synchronous to the receive clock. The receive clock can run
+at 2.5, 25 or 125MHz depending on the media speed, and can stop under
+the control of the link partner. This means that the time it takes to
+clear is dependent on the negotiated media speed, and thus can be 8,
+40, or 400ns after reading the LPI control and status register.
+
+It has been observed with some aggressive link partners, this clock
+can stop while lpi_intr_o is still asserted, meaning that the signal
+remains asserted for an indefinite period that the local system has
+no direct control over.
+
+The LPI interrupts will still be signalled through the main interrupt
+path in any case, and this path is not dependent on the receive clock.
+
+This, since we do not gate the application clock, and the chances of
+adding clock gating in the future are slim due to the clocks being
+ill-defined, lpi_intr_o serves no useful purpose. Remove the code which
+requests the interrupt, and all associated code.
+
+Reported-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
+Tested-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com> # Renesas RZ/V2H board
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/E1vnJbt-00000007YYN-28nm@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/common.h | 1
+ drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 4 --
+ drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 7 ---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 -
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 36 ------------------
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 8 ----
+ include/linux/stmmac.h | 1
+ 7 files changed, 59 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/common.h
++++ b/drivers/net/ethernet/stmicro/stmmac/common.h
+@@ -371,7 +371,6 @@ enum request_irq_err {
+ REQ_IRQ_ERR_RX,
+ REQ_IRQ_ERR_SFTY_UE,
+ REQ_IRQ_ERR_SFTY_CE,
+- REQ_IRQ_ERR_LPI,
+ REQ_IRQ_ERR_WOL,
+ REQ_IRQ_ERR_MAC,
+ REQ_IRQ_ERR_NO,
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+@@ -612,7 +612,6 @@ static int intel_mgbe_common_data(struct
+
+ /* Setup MSI vector offset specific to Intel mGbE controller */
+ plat->msi_mac_vec = 29;
+- plat->msi_lpi_vec = 28;
+ plat->msi_sfty_ce_vec = 27;
+ plat->msi_sfty_ue_vec = 26;
+ plat->msi_rx_base_vec = 0;
+@@ -998,8 +997,6 @@ static int stmmac_config_multi_msi(struc
+ res->irq = pci_irq_vector(pdev, plat->msi_mac_vec);
+ if (plat->msi_wol_vec < STMMAC_MSI_VEC_MAX)
+ res->wol_irq = pci_irq_vector(pdev, plat->msi_wol_vec);
+- if (plat->msi_lpi_vec < STMMAC_MSI_VEC_MAX)
+- res->lpi_irq = pci_irq_vector(pdev, plat->msi_lpi_vec);
+ if (plat->msi_sfty_ce_vec < STMMAC_MSI_VEC_MAX)
+ res->sfty_ce_irq = pci_irq_vector(pdev, plat->msi_sfty_ce_vec);
+ if (plat->msi_sfty_ue_vec < STMMAC_MSI_VEC_MAX)
+@@ -1081,7 +1078,6 @@ static int intel_eth_pci_probe(struct pc
+ */
+ plat->msi_mac_vec = STMMAC_MSI_VEC_MAX;
+ plat->msi_wol_vec = STMMAC_MSI_VEC_MAX;
+- plat->msi_lpi_vec = STMMAC_MSI_VEC_MAX;
+ plat->msi_sfty_ce_vec = STMMAC_MSI_VEC_MAX;
+ plat->msi_sfty_ue_vec = STMMAC_MSI_VEC_MAX;
+ plat->msi_rx_base_vec = STMMAC_MSI_VEC_MAX;
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+@@ -138,13 +138,6 @@ static int loongson_dwmac_probe(struct p
+ res.wol_irq = res.irq;
+ }
+
+- res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
+- if (res.lpi_irq < 0) {
+- dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
+- ret = -ENODEV;
+- goto err_disable_msi;
+- }
+-
+ ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
+ if (ret)
+ goto err_disable_msi;
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -29,7 +29,6 @@ struct stmmac_resources {
+ void __iomem *addr;
+ u8 mac[ETH_ALEN];
+ int wol_irq;
+- int lpi_irq;
+ int irq;
+ int sfty_ce_irq;
+ int sfty_ue_irq;
+@@ -260,7 +259,6 @@ struct stmmac_priv {
+ bool wol_irq_disabled;
+ int clk_csr;
+ struct timer_list eee_ctrl_timer;
+- int lpi_irq;
+ int eee_enabled;
+ int eee_active;
+ int tx_lpi_timer;
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -3496,10 +3496,6 @@ static void stmmac_free_irq(struct net_d
+ free_irq(priv->sfty_ce_irq, dev);
+ fallthrough;
+ case REQ_IRQ_ERR_SFTY_CE:
+- if (priv->lpi_irq > 0 && priv->lpi_irq != dev->irq)
+- free_irq(priv->lpi_irq, dev);
+- fallthrough;
+- case REQ_IRQ_ERR_LPI:
+ if (priv->wol_irq > 0 && priv->wol_irq != dev->irq)
+ free_irq(priv->wol_irq, dev);
+ fallthrough;
+@@ -3554,24 +3550,6 @@ static int stmmac_request_irq_multi_msi(
+ }
+ }
+
+- /* Request the LPI IRQ in case of another line
+- * is used for LPI
+- */
+- if (priv->lpi_irq > 0 && priv->lpi_irq != dev->irq) {
+- int_name = priv->int_name_lpi;
+- sprintf(int_name, "%s:%s", dev->name, "lpi");
+- ret = request_irq(priv->lpi_irq,
+- stmmac_mac_interrupt,
+- 0, int_name, dev);
+- if (unlikely(ret < 0)) {
+- netdev_err(priv->dev,
+- "%s: alloc lpi MSI %d (error: %d)\n",
+- __func__, priv->lpi_irq, ret);
+- irq_err = REQ_IRQ_ERR_LPI;
+- goto irq_error;
+- }
+- }
+-
+ /* Request the Safety Feature Correctible Error line in
+ * case of another line is used
+ */
+@@ -3695,19 +3673,6 @@ static int stmmac_request_irq_single(str
+ }
+ }
+
+- /* Request the IRQ lines */
+- if (priv->lpi_irq > 0 && priv->lpi_irq != dev->irq) {
+- ret = request_irq(priv->lpi_irq, stmmac_interrupt,
+- IRQF_SHARED, dev->name, dev);
+- if (unlikely(ret < 0)) {
+- netdev_err(priv->dev,
+- "%s: ERROR: allocating the LPI IRQ %d (%d)\n",
+- __func__, priv->lpi_irq, ret);
+- irq_err = REQ_IRQ_ERR_LPI;
+- goto irq_error;
+- }
+- }
+-
+ return 0;
+
+ irq_error:
+@@ -7436,7 +7401,6 @@ int stmmac_dvr_probe(struct device *devi
+
+ priv->dev->irq = res->irq;
+ priv->wol_irq = res->wol_irq;
+- priv->lpi_irq = res->lpi_irq;
+ priv->sfty_ce_irq = res->sfty_ce_irq;
+ priv->sfty_ue_irq = res->sfty_ue_irq;
+ for (i = 0; i < MTL_MAX_RX_QUEUES; i++)
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -762,14 +762,6 @@ int stmmac_get_platform_resources(struct
+ stmmac_res->wol_irq = stmmac_res->irq;
+ }
+
+- stmmac_res->lpi_irq =
+- platform_get_irq_byname_optional(pdev, "eth_lpi");
+- if (stmmac_res->lpi_irq < 0) {
+- if (stmmac_res->lpi_irq == -EPROBE_DEFER)
+- return -EPROBE_DEFER;
+- dev_info(&pdev->dev, "IRQ eth_lpi not found\n");
+- }
+-
+ stmmac_res->addr = devm_platform_ioremap_resource(pdev, 0);
+
+ return PTR_ERR_OR_ZERO(stmmac_res->addr);
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -306,7 +306,6 @@ struct plat_stmmacenet_data {
+ int ext_snapshot_num;
+ int msi_mac_vec;
+ int msi_wol_vec;
+- int msi_lpi_vec;
+ int msi_sfty_ce_vec;
+ int msi_sfty_ue_vec;
+ int msi_rx_base_vec;
--- /dev/null
+From ruohanlan@aliyun.com Mon Mar 2 08:37:21 2026
+From: Ruohan Lan <ruohanlan@aliyun.com>
+Date: Mon, 2 Mar 2026 15:36:30 +0800
+Subject: net: use dst_dev_rcu() in sk_setup_caps()
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: edumazet@google.com, kuniyu@google.com, kuba@kernel.org, dsahern@kernel.org, netdev@vger.kernel.org, Ruohan Lan <ruohanlan@aliyun.com>
+Message-ID: <20260302073630.988982-4-ruohanlan@aliyun.com>
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 99a2ace61b211b0be861b07fbaa062fca4b58879 ]
+
+Use RCU to protect accesses to dst->dev from sk_setup_caps()
+and sk_dst_gso_max_size().
+
+Also use dst_dev_rcu() in ip6_dst_mtu_maybe_forward(),
+and ip_dst_mtu_maybe_forward().
+
+ip4_dst_hoplimit() can use dst_dev_net_rcu().
+
+Fixes: 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://patch.msgid.link/20250828195823.3958522-6-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Adjust context ]
+Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/ip.h | 7 +++++--
+ include/net/ip6_route.h | 2 +-
+ include/net/route.h | 2 +-
+ net/core/sock.c | 16 ++++++++++------
+ 4 files changed, 17 insertions(+), 10 deletions(-)
+
+--- a/include/net/ip.h
++++ b/include/net/ip.h
+@@ -458,9 +458,12 @@ static inline unsigned int ip_dst_mtu_ma
+ bool forwarding)
+ {
+ const struct rtable *rt = container_of(dst, struct rtable, dst);
+- struct net *net = dev_net(dst->dev);
++ struct net *net;
++ const struct net_device *dev;
+ unsigned int mtu;
+
++ dev = dst_dev_rcu(dst);
++ net = dev_net_rcu(dev);
+ if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
+ ip_mtu_locked(dst) ||
+ !forwarding) {
+@@ -474,7 +477,7 @@ static inline unsigned int ip_dst_mtu_ma
+ if (mtu)
+ goto out;
+
+- mtu = READ_ONCE(dst->dev->mtu);
++ mtu = READ_ONCE(dev->mtu);
+
+ if (unlikely(ip_mtu_locked(dst))) {
+ if (rt->rt_uses_gateway && mtu > 576)
+--- a/include/net/ip6_route.h
++++ b/include/net/ip6_route.h
+@@ -333,7 +333,7 @@ static inline unsigned int ip6_dst_mtu_m
+
+ mtu = IPV6_MIN_MTU;
+ rcu_read_lock();
+- idev = __in6_dev_get(dst->dev);
++ idev = __in6_dev_get(dst_dev_rcu(dst));
+ if (idev)
+ mtu = idev->cnf.mtu6;
+ rcu_read_unlock();
+--- a/include/net/route.h
++++ b/include/net/route.h
+@@ -363,7 +363,7 @@ static inline int ip4_dst_hoplimit(const
+ const struct net *net;
+
+ rcu_read_lock();
+- net = dev_net_rcu(dst->dev);
++ net = dst_dev_net_rcu(dst);
+ hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl);
+ rcu_read_unlock();
+ }
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2440,7 +2440,7 @@ void sk_free_unlock_clone(struct sock *s
+ }
+ EXPORT_SYMBOL_GPL(sk_free_unlock_clone);
+
+-static u32 sk_dst_gso_max_size(struct sock *sk, struct dst_entry *dst)
++static u32 sk_dst_gso_max_size(struct sock *sk, const struct net_device *dev)
+ {
+ bool is_ipv6 = false;
+ u32 max_size;
+@@ -2450,8 +2450,8 @@ static u32 sk_dst_gso_max_size(struct so
+ !ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr));
+ #endif
+ /* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */
+- max_size = is_ipv6 ? READ_ONCE(dst_dev(dst)->gso_max_size) :
+- READ_ONCE(dst_dev(dst)->gso_ipv4_max_size);
++ max_size = is_ipv6 ? READ_ONCE(dev->gso_max_size) :
++ READ_ONCE(dev->gso_ipv4_max_size);
+ if (max_size > GSO_LEGACY_MAX_SIZE && !sk_is_tcp(sk))
+ max_size = GSO_LEGACY_MAX_SIZE;
+
+@@ -2460,9 +2460,12 @@ static u32 sk_dst_gso_max_size(struct so
+
+ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
+ {
++ const struct net_device *dev;
+ u32 max_segs = 1;
+
+- sk->sk_route_caps = dst_dev(dst)->features;
++ rcu_read_lock();
++ dev = dst_dev_rcu(dst);
++ sk->sk_route_caps = dev->features;
+ if (sk_is_tcp(sk))
+ sk->sk_route_caps |= NETIF_F_GSO;
+ if (sk->sk_route_caps & NETIF_F_GSO)
+@@ -2474,13 +2477,14 @@ void sk_setup_caps(struct sock *sk, stru
+ sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+ } else {
+ sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
+- sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dst);
++ sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dev);
+ /* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */
+- max_segs = max_t(u32, READ_ONCE(dst_dev(dst)->gso_max_segs), 1);
++ max_segs = max_t(u32, READ_ONCE(dev->gso_max_segs), 1);
+ }
+ }
+ sk->sk_gso_max_segs = max_segs;
+ sk_dst_set(sk, dst);
++ rcu_read_unlock();
+ }
+ EXPORT_SYMBOL_GPL(sk_setup_caps);
+
--- /dev/null
+From stable+bounces-222799-greg=kroah.com@vger.kernel.org Tue Mar 3 07:32:46 2026
+From: Alva Lan <alvalan9@foxmail.com>
+Date: Tue, 3 Mar 2026 14:31:51 +0800
+Subject: platform/x86/amd/pmc: Add support for Van Gogh SoC
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: platform-driver-x86@vger.kernel.org, "Antheas Kapenekakis" <lkml@antheas.dev>, "Mario Limonciello" <superm1@kernel.org>, "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>, "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>, "Alva Lan" <alvalan9@foxmail.com>
+Message-ID: <tencent_9AB419354F1F619209D63A382030610D4208@qq.com>
+
+From: Antheas Kapenekakis <lkml@antheas.dev>
+
+[ Upstream commit db4a3f0fbedb0398f77b9047e8b8bb2b49f355bb ]
+
+The ROG Xbox Ally (non-X) SoC features a similar architecture to the
+Steam Deck. While the Steam Deck supports S3 (s2idle causes a crash),
+this support was dropped by the Xbox Ally which only S0ix suspend.
+
+Since the handler is missing here, this causes the device to not suspend
+and the AMD GPU driver to crash while trying to resume afterwards due to
+a power hang.
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4659
+Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
+Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
+Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+Link: https://patch.msgid.link/20251024152152.3981721-2-lkml@antheas.dev
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+[ Adjust context ]
+Signed-off-by: Alva Lan <alvalan9@foxmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/amd/pmc/pmc.c | 3 +++
+ drivers/platform/x86/amd/pmc/pmc.h | 1 +
+ 2 files changed, 4 insertions(+)
+
+--- a/drivers/platform/x86/amd/pmc/pmc.c
++++ b/drivers/platform/x86/amd/pmc/pmc.c
+@@ -294,6 +294,7 @@ static void amd_pmc_get_ip_info(struct a
+ switch (dev->cpu_id) {
+ case AMD_CPU_ID_PCO:
+ case AMD_CPU_ID_RN:
++ case AMD_CPU_ID_VG:
+ case AMD_CPU_ID_YC:
+ case AMD_CPU_ID_CB:
+ dev->num_ips = 12;
+@@ -698,6 +699,7 @@ static int amd_pmc_get_os_hint(struct am
+ case AMD_CPU_ID_PCO:
+ return MSG_OS_HINT_PCO;
+ case AMD_CPU_ID_RN:
++ case AMD_CPU_ID_VG:
+ case AMD_CPU_ID_YC:
+ case AMD_CPU_ID_CB:
+ case AMD_CPU_ID_PS:
+@@ -908,6 +910,7 @@ static const struct pci_device_id pmc_pc
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) },
++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_VG) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
+ { }
+ };
+--- a/drivers/platform/x86/amd/pmc/pmc.h
++++ b/drivers/platform/x86/amd/pmc/pmc.h
+@@ -47,6 +47,7 @@ void amd_pmc_quirks_init(struct amd_pmc_
+ #define AMD_CPU_ID_RN 0x1630
+ #define AMD_CPU_ID_PCO AMD_CPU_ID_RV
+ #define AMD_CPU_ID_CZN AMD_CPU_ID_RN
++#define AMD_CPU_ID_VG 0x1645
+ #define AMD_CPU_ID_YC 0x14B5
+ #define AMD_CPU_ID_CB 0x14D8
+ #define AMD_CPU_ID_PS 0x14E8
--- /dev/null
+From stable+bounces-222973-greg=kroah.com@vger.kernel.org Wed Mar 4 03:59:38 2026
+From: Jianqiang kang <jianqkang@sina.cn>
+Date: Wed, 4 Mar 2026 10:57:24 +0800
+Subject: rcu/nocb: Fix possible invalid rdp's->nocb_cb_kthread pointer access
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org, qiang.zhang1211@gmail.com
+Cc: patches@lists.linux.dev, linux-kernel@vger.kernel.org, paulmck@kernel.org, frederic@kernel.org, quic_neeraju@quicinc.com, josh@joshtriplett.org, rostedt@goodmis.org, mathieu.desnoyers@efficios.com, jiangshanlai@gmail.com, joel@joelfernandes.org, rcu@vger.kernel.org, neeraj.upadhyay@kernel.org
+Message-ID: <20260304025724.2365669-1-jianqkang@sina.cn>
+
+From: Zqiang <qiang.zhang1211@gmail.com>
+
+[ Upstream commit 1bba3900ca18bdae28d1b9fa10f16a8f8cb2ada1 ]
+
+In the preparation stage of CPU online, if the corresponding
+the rdp's->nocb_cb_kthread does not exist, will be created,
+there is a situation where the rdp's rcuop kthreads creation fails,
+and then de-offload this CPU's rdp, does not assign this CPU's
+rdp->nocb_cb_kthread pointer, but this rdp's->nocb_gp_rdp and
+rdp's->rdp_gp->nocb_gp_kthread is still valid.
+
+This will cause the subsequent re-offload operation of this offline
+CPU, which will pass the conditional check and the kthread_unpark()
+will access invalid rdp's->nocb_cb_kthread pointer.
+
+This commit therefore use rdp's->nocb_gp_kthread instead of
+rdp_gp's->nocb_gp_kthread for safety check.
+
+Signed-off-by: Zqiang <qiang.zhang1211@gmail.com>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
+[ Minor conflict resolved. ]
+Signed-off-by: Jianqiang kang <jianqkang@sina.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/rcu/tree_nocb.h | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/kernel/rcu/tree_nocb.h
++++ b/kernel/rcu/tree_nocb.h
+@@ -1221,7 +1221,6 @@ static long rcu_nocb_rdp_offload(void *a
+ struct rcu_segcblist *cblist = &rdp->cblist;
+ unsigned long flags;
+ int wake_gp;
+- struct rcu_data *rdp_gp = rdp->nocb_gp_rdp;
+
+ WARN_ON_ONCE(rdp->cpu != raw_smp_processor_id());
+ /*
+@@ -1231,7 +1230,7 @@ static long rcu_nocb_rdp_offload(void *a
+ if (!rdp->nocb_gp_rdp)
+ return -EINVAL;
+
+- if (WARN_ON_ONCE(!rdp_gp->nocb_gp_kthread))
++ if (WARN_ON_ONCE(!rdp->nocb_gp_kthread))
+ return -EINVAL;
+
+ pr_info("Offloading %d\n", rdp->cpu);
+@@ -1260,7 +1259,7 @@ static long rcu_nocb_rdp_offload(void *a
+ */
+ wake_gp = rdp_offload_toggle(rdp, true, flags);
+ if (wake_gp)
+- wake_up_process(rdp_gp->nocb_gp_kthread);
++ wake_up_process(rdp->nocb_gp_kthread);
+ swait_event_exclusive(rdp->nocb_state_wq,
+ rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_CB) &&
+ rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_GP));
--- /dev/null
+From stable+bounces-223134-greg=kroah.com@vger.kernel.org Wed Mar 4 21:26:05 2026
+From: Samuel Wu <wusamuel@google.com>
+Date: Wed, 4 Mar 2026 12:25:52 -0800
+Subject: sched/fair: Fix pelt clock sync when entering idle
+To: stable@vger.kernel.org
+Cc: gregkh@linuxfoundation.org, sashal@kernel.org, jstultz@google.com, qyousef@google.com, vincent.guittot@linaro.com, Vincent Guittot <vincent.guittot@linaro.org>, Samuel Wu <wusamuel@google.com>, Alex Hoh <Alex.Hoh@mediatek.com>, "Peter Zijlstra (Intel)" <peterz@infradead.org>
+Message-ID: <20260304202553.422006-1-wusamuel@google.com>
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+[ Upstream commit 98c88dc8a1ace642d9021b103b28cba7b51e3abc ]
+
+Samuel and Alex reported regressions of the util_avg of RT rq with
+commit 17e3e88ed0b6 ("sched/fair: Fix pelt lost idle time detection").
+It happens that fair is updating and syncing the pelt clock with task one
+when pick_next_task_fair() fails to pick a task but before the prev
+scheduling class got a chance to update its pelt signals.
+
+Move update_idle_rq_clock_pelt() in set_next_task_idle() which is called
+after prev class has been called.
+
+Fixes: 17e3e88ed0b6 ("sched/fair: Fix pelt lost idle time detection")
+Reported-by: Samuel Wu <wusamuel@google.com>
+Closes: https://lore.kernel.org/all/CAG2KctpO6VKS6GN4QWDji0t92_gNBJ7HjjXrE+6H+RwRXt=iLg@mail.gmail.com/
+Reported-by: Alex Hoh <Alex.Hoh@mediatek.com>
+Closes: https://lore.kernel.org/all/8cf19bf0e0054dcfed70e9935029201694f1bb5a.camel@mediatek.com/
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Tested-by: Samuel Wu <wusamuel@google.com>
+Tested-by: Alex Hoh <Alex.Hoh@mediatek.com>
+Link: https://patch.msgid.link/20260121163317.505635-1-vincent.guittot@linaro.org
+(cherry picked from commit 98c88dc8a1ace642d9021b103b28cba7b51e3abc)
+[ wusamuel: Did not include line 'exec_start = rq_clock_task()', which
+is not present in 6.6.y but found in mainline ]
+Signed-off-by: Samuel Wu <wusamuel@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/fair.c | 6 ------
+ kernel/sched/idle.c | 6 ++++++
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -8557,12 +8557,6 @@ idle:
+ goto again;
+ }
+
+- /*
+- * rq is about to be idle, check if we need to update the
+- * lost_idle_time of clock_pelt
+- */
+- update_idle_rq_clock_pelt(rq);
+-
+ return NULL;
+ }
+
+--- a/kernel/sched/idle.c
++++ b/kernel/sched/idle.c
+@@ -423,6 +423,12 @@ static void set_next_task_idle(struct rq
+ {
+ update_idle_core(rq);
+ schedstat_inc(rq->sched_goidle);
++
++ /*
++ * rq is about to be idle, check if we need to update the
++ * lost_idle_time of clock_pelt
++ */
++ update_idle_rq_clock_pelt(rq);
+ }
+
+ #ifdef CONFIG_SMP
net-add-support-for-segmenting-tcp-fraglist-gso-packets.patch
net-gso-fix-tcp-fraglist-segmentation-after-pull-from-frag_list.patch
net-fix-segmentation-of-forwarding-fraglist-gro.patch
+bpf-forget-ranges-when-refining-tnum-after-jset.patch
+net-dsa-properly-keep-track-of-conduit-reference.patch
+drm-amd-display-add-pixel_clock-to-amd_pp_display_configuration.patch
+drm-amd-pm-use-pm_display_cfg-in-legacy-dpm-v2.patch
+l2tp-do-not-use-sock_hold-in-pppol2tp_session_get_sock.patch
+drm-amdgpu-add-basic-validation-for-ras-header.patch
+drm-exynos-vidi-use-priv-vidi_dev-for-ctx-lookup-in-vidi_connection_ioctl.patch
+drm-exynos-vidi-fix-to-avoid-directly-dereferencing-user-pointer.patch
+drm-exynos-vidi-use-ctx-lock-to-protect-struct-vidi_context-member-variables-related-to-memory-alloc-free.patch
+net-dst-add-four-helpers-to-annotate-data-races-around-dst-dev.patch
+net-dst-introduce-dst-dev_rcu.patch
+net-use-dst_dev_rcu-in-sk_setup_caps.patch
+x86-uprobes-fix-xol-allocation-failure-for-32-bit-tasks.patch
+platform-x86-amd-pmc-add-support-for-van-gogh-soc.patch
+rcu-nocb-fix-possible-invalid-rdp-s-nocb_cb_kthread-pointer-access.patch
+f2fs-zone-fix-to-avoid-inconsistence-in-between-sit-and-ssa.patch
+sched-fair-fix-pelt-clock-sync-when-entering-idle.patch
+binfmt_misc-restore-write-access-before-closing-files-opened-by-open_exec.patch
+net-stmmac-remove-support-for-lpi_intr_o.patch
+mptcp-pm-in-kernel-always-set-id-as-avail-when-rm-endp.patch
--- /dev/null
+From stable+bounces-222629-greg=kroah.com@vger.kernel.org Mon Mar 2 16:45:15 2026
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Mon, 2 Mar 2026 16:29:27 +0100
+Subject: x86/uprobes: Fix XOL allocation failure for 32-bit tasks
+To: Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, Paulo Andrade <pandrade@redhat.com>, "Peter Zijlstra (Intel)" <peterz@infradead.org>, linux-trace-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org
+Message-ID: <aaWs1z8mExRodXo6@redhat.com>
+Content-Disposition: inline
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[ Upstream commit d55c571e4333fac71826e8db3b9753fadfbead6a ]
+
+This script
+
+ #!/usr/bin/bash
+
+ echo 0 > /proc/sys/kernel/randomize_va_space
+
+ echo 'void main(void) {}' > TEST.c
+
+ # -fcf-protection to ensure that the 1st endbr32 insn can't be emulated
+ gcc -m32 -fcf-protection=branch TEST.c -o test
+
+ bpftrace -e 'uprobe:./test:main {}' -c ./test
+
+"hangs", the probed ./test task enters an endless loop.
+
+The problem is that with randomize_va_space == 0
+get_unmapped_area(TASK_SIZE - PAGE_SIZE) called by xol_add_vma() can not
+just return the "addr == TASK_SIZE - PAGE_SIZE" hint, this addr is used
+by the stack vma.
+
+arch_get_unmapped_area_topdown() doesn't take TIF_ADDR32 into account and
+in_32bit_syscall() is false, this leads to info.high_limit > TASK_SIZE.
+vm_unmapped_area() happily returns the high address > TASK_SIZE and then
+get_unmapped_area() returns -ENOMEM after the "if (addr > TASK_SIZE - len)"
+check.
+
+handle_swbp() doesn't report this failure (probably it should) and silently
+restarts the probed insn. Endless loop.
+
+I think that the right fix should change the x86 get_unmapped_area() paths
+to rely on TIF_ADDR32 rather than in_32bit_syscall(). Note also that if
+CONFIG_X86_X32_ABI=y, in_x32_syscall() falsely returns true in this case
+because ->orig_ax = -1.
+
+But we need a simple fix for -stable, so this patch just sets TS_COMPAT if
+the probed task is 32-bit to make in_ia32_syscall() true.
+
+Fixes: 1b028f784e8c ("x86/mm: Introduce mmap_compat_base() for 32-bit mmap()")
+Reported-by: Paulo Andrade <pandrade@redhat.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/all/aV5uldEvV7pb4RA8@redhat.com/
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/aWO7Fdxn39piQnxu@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/uprobes.c | 24 ++++++++++++++++++++++++
+ include/linux/uprobes.h | 1 +
+ kernel/events/uprobes.c | 10 +++++++---
+ 3 files changed, 32 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kernel/uprobes.c
++++ b/arch/x86/kernel/uprobes.c
+@@ -1102,3 +1102,27 @@ bool arch_uretprobe_is_alive(struct retu
+ else
+ return regs->sp <= ret->stack;
+ }
++
++#ifdef CONFIG_IA32_EMULATION
++unsigned long arch_uprobe_get_xol_area(void)
++{
++ struct thread_info *ti = current_thread_info();
++ unsigned long vaddr;
++
++ /*
++ * HACK: we are not in a syscall, but x86 get_unmapped_area() paths
++ * ignore TIF_ADDR32 and rely on in_32bit_syscall() to calculate
++ * vm_unmapped_area_info.high_limit.
++ *
++ * The #ifdef above doesn't cover the CONFIG_X86_X32_ABI=y case,
++ * but in this case in_32bit_syscall() -> in_x32_syscall() always
++ * (falsely) returns true because ->orig_ax == -1.
++ */
++ if (test_thread_flag(TIF_ADDR32))
++ ti->status |= TS_COMPAT;
++ vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0);
++ ti->status &= ~TS_COMPAT;
++
++ return vaddr;
++}
++#endif
+--- a/include/linux/uprobes.h
++++ b/include/linux/uprobes.h
+@@ -140,6 +140,7 @@ extern bool arch_uretprobe_is_alive(stru
+ extern bool arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs);
+ extern void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
+ void *src, unsigned long len);
++extern unsigned long arch_uprobe_get_xol_area(void);
+ #else /* !CONFIG_UPROBES */
+ struct uprobes_state {
+ };
+--- a/kernel/events/uprobes.c
++++ b/kernel/events/uprobes.c
+@@ -1449,6 +1449,12 @@ void uprobe_munmap(struct vm_area_struct
+ set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags);
+ }
+
++unsigned long __weak arch_uprobe_get_xol_area(void)
++{
++ /* Try to map as high as possible, this is only a hint. */
++ return get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0);
++}
++
+ /* Slot allocation for XOL */
+ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
+ {
+@@ -1464,9 +1470,7 @@ static int xol_add_vma(struct mm_struct
+ }
+
+ if (!area->vaddr) {
+- /* Try to map as high as possible, this is only a hint. */
+- area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE,
+- PAGE_SIZE, 0, 0);
++ area->vaddr = arch_uprobe_get_xol_area();
+ if (IS_ERR_VALUE(area->vaddr)) {
+ ret = area->vaddr;
+ goto fail;