]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Fix NULL pointer dereference in dcn401_init_hw()
authorSrinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Sat, 21 Mar 2026 11:55:14 +0000 (17:25 +0530)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 30 Mar 2026 20:18:47 +0000 (16:18 -0400)
dcn401_init_hw() assumes that update_bw_bounding_box() is valid when
entering the update path. However, the existing condition:

  ((!fams2_enable && update_bw_bounding_box) || freq_changed)

does not guarantee this, as the freq_changed branch can evaluate to true
independently of the callback pointer.

This can result in calling update_bw_bounding_box() when it is NULL.

Fix this by separating the update condition from the pointer checks and
ensuring the callback, dc->clk_mgr, and bw_params are validated before
use.

Fixes the below:
../dc/hwss/dcn401/dcn401_hwseq.c:367 dcn401_init_hw() error: we previously assumed 'dc->res_pool->funcs->update_bw_bounding_box' could be null (see line 362)

Fixes: ca0fb243c3bb ("drm/amd/display: Underflow Seen on DCN401 eGPU")
Cc: Daniel Sa <Daniel.Sa@amd.com>
Cc: Alvin Lee <alvin.lee2@amd.com>
Cc: Roman Li <roman.li@amd.com>
Cc: Alex Hung <alex.hung@amd.com>
Cc: Tom Chung <chiahsuan.chung@amd.com>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 86117c5ab42f21562fedb0a64bffea3ee5fcd477)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c

index eb198d52a1155c72f80ec1e728c6fba0a0cfcfdd..4dfb6c8658312da67fcd5e5e4cd401ae220e351e 100644 (file)
@@ -147,6 +147,7 @@ void dcn401_init_hw(struct dc *dc)
        int edp_num;
        uint32_t backlight = MAX_BACKLIGHT_LEVEL;
        uint32_t user_level = MAX_BACKLIGHT_LEVEL;
+       bool dchub_ref_freq_changed;
        int current_dchub_ref_freq = 0;
 
        if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
@@ -360,14 +361,18 @@ void dcn401_init_hw(struct dc *dc)
                dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
                dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
                dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
+
+               /* sw and fw FAMS versions must match for support */
                dc->debug.fams2_config.bits.enable &=
-                               dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver; // sw & fw fams versions must match for support
-               if ((!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box)
-                       || res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq) {
+                       dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver;
+               dchub_ref_freq_changed =
+                       res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq;
+               if ((!dc->debug.fams2_config.bits.enable || dchub_ref_freq_changed) &&
+                   dc->res_pool->funcs->update_bw_bounding_box &&
+                   dc->clk_mgr && dc->clk_mgr->bw_params) {
                        /* update bounding box if FAMS2 disabled, or if dchub clk has changed */
-                       if (dc->clk_mgr)
-                               dc->res_pool->funcs->update_bw_bounding_box(dc,
-                                                                           dc->clk_mgr->bw_params);
+                       dc->res_pool->funcs->update_bw_bounding_box(dc,
+                                                                   dc->clk_mgr->bw_params);
                }
        }
 }