]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Mar 2026 12:01:48 +0000 (13:01 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Mar 2026 12:01:48 +0000 (13:01 +0100)
added patches:
drm-amd-display-add-pixel_clock-to-amd_pp_display_configuration.patch
drm-amd-pm-use-pm_display_cfg-in-legacy-dpm-v2.patch
drm-amdgpu-add-basic-validation-for-ras-header.patch

queue-6.12/drm-amd-display-add-pixel_clock-to-amd_pp_display_configuration.patch [new file with mode: 0644]
queue-6.12/drm-amd-pm-use-pm_display_cfg-in-legacy-dpm-v2.patch [new file with mode: 0644]
queue-6.12/drm-amdgpu-add-basic-validation-for-ras-header.patch [new file with mode: 0644]
queue-6.12/series

diff --git a/queue-6.12/drm-amd-display-add-pixel_clock-to-amd_pp_display_configuration.patch b/queue-6.12/drm-amd-display-add-pixel_clock-to-amd_pp_display_configuration.patch
new file mode 100644 (file)
index 0000000..b784040
--- /dev/null
@@ -0,0 +1,77 @@
+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
+@@ -65,6 +65,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
diff --git a/queue-6.12/drm-amd-pm-use-pm_display_cfg-in-legacy-dpm-v2.patch b/queue-6.12/drm-amd-pm-use-pm_display_cfg-in-legacy-dpm-v2.patch
new file mode 100644 (file)
index 0000000..2120bd1
--- /dev/null
@@ -0,0 +1,351 @@
+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) {
+@@ -994,7 +993,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)
+@@ -5532,7 +5519,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;
+       }
+@@ -5681,7 +5668,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)
+@@ -5835,30 +5822,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
+@@ -1569,16 +1569,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);
+       }
diff --git a/queue-6.12/drm-amdgpu-add-basic-validation-for-ras-header.patch b/queue-6.12/drm-amdgpu-add-basic-validation-for-ras-header.patch
new file mode 100644 (file)
index 0000000..7edc254
--- /dev/null
@@ -0,0 +1,59 @@
+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
+@@ -1362,15 +1362,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) {
index 8c78f94185a5830e018a94f1c391d04ba4f82a59..f46c1291733cefa44a291d05eb4cd99d107ff402 100644 (file)
@@ -301,3 +301,6 @@ s390-stackleak-fix-__stackleak_poison-inline-assembly-constraint.patch
 s390-xor-fix-xor_xc_2-inline-assembly-constraints.patch
 drm-i915-alpm-alpm-disable-fixes.patch
 drm-i915-psr-repeat-selective-update-area-alignment.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
+drm-amdgpu-add-basic-validation-for-ras-header.patch