]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Fix divide-by-zero in calculate_mcache_setting on zero viewport
authorGeorge Zhang <george.zhang@amd.com>
Thu, 16 Jul 2026 21:00:01 +0000 (17:00 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 29 Jul 2026 00:00:20 +0000 (20:00 -0400)
If a plane reaches calculate_mcache_setting with a zero-area viewport,
calculate_mcache_setting exits early with num_mcaches == 0 and
mvmpg_width/height == 0. This will cause a divide-by-zero panic and can
also cause an underflow on num_mcaches.

Fix this by changing calculate_mcache_setting to bool and adding guards
after each calculate_mcache_row_bytes call. If num_mcaches or
mvmpg_width/height is zero, return a false. Callers will propagate the
failure as a rejected mode, which prevents the panic.

Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/5302
Reviewed-by: Sun peng (Leo) Li <sunpeng.li@amd.com>
Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: George Zhang <george.zhang@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 29c0f7c655f47bcbd575ff75e58480df6ec3c9da)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c

index f338e733318e1afe7a4c35ac956b8645f5e42ca1..b4e2264ef408fff6df424c9e04af3512559c53e2 100644 (file)
@@ -2452,7 +2452,7 @@ static void calculate_mcache_row_bytes(
        DML_ASSERT(*p->num_mcaches > 0);
 }
 
-static void calculate_mcache_setting(
+static bool calculate_mcache_setting(
        struct dml2_core_internal_scratch *scratch,
        struct dml2_core_calcs_calculate_mcache_setting_params *p)
 {
@@ -2478,7 +2478,7 @@ static void calculate_mcache_setting(
        *p->lc_comb_mcache = 0;
 
        if (!p->dcc_enable)
-               return;
+               return true;
 
        l->is_dual_plane = dml_is_420(p->source_format) || p->source_format == dml2_rgbe_alpha;
 
@@ -2515,7 +2515,14 @@ static void calculate_mcache_setting(
        l->l_p.mvmpg_per_mcache_lb = &l->mvmpg_per_mcache_lb_l;
 
        calculate_mcache_row_bytes(scratch, &l->l_p);
-       DML_ASSERT(*p->num_mcaches_l > 0);
+       if (*p->num_mcaches_l == 0 ||
+           (p->surf_vert ? l->mvmpg_height_l : l->mvmpg_width_l) == 0) {
+               DML_LOG_VERBOSE("DML::%s: degenerate luma viewport (num_mcaches_l=%u mvmpg_%s_l=%u) — mode not supported\n",
+                       __func__, *p->num_mcaches_l,
+                       p->surf_vert ? "height" : "width",
+                       p->surf_vert ? l->mvmpg_height_l : l->mvmpg_width_l);
+               return false;
+       }
 
        if (l->is_dual_plane) {
                l->c_p.num_chans = p->num_chans;
@@ -2551,7 +2558,14 @@ static void calculate_mcache_setting(
                l->c_p.mvmpg_per_mcache_lb = &l->mvmpg_per_mcache_lb_c;
 
                calculate_mcache_row_bytes(scratch, &l->c_p);
-               DML_ASSERT(*p->num_mcaches_c > 0);
+               if (*p->num_mcaches_c == 0 ||
+                   (p->surf_vert ? l->mvmpg_height_c : l->mvmpg_width_c) == 0) {
+                       DML_LOG_VERBOSE("DML::%s: degenerate chroma viewport (num_mcaches_c=%u mvmpg_%s_c=%u) — mode not supported\n",
+                               __func__, *p->num_mcaches_c,
+                               p->surf_vert ? "height" : "width",
+                               p->surf_vert ? l->mvmpg_height_c : l->mvmpg_width_c);
+                       return false;
+               }
        }
 
        // Sharing for iMALL access
@@ -2661,6 +2675,7 @@ static void calculate_mcache_setting(
 
        *p->mcache_shift_granularity_l = l->mvmpg_access_width_l;
        *p->mcache_shift_granularity_c = l->mvmpg_access_width_c;
+       return true;
 }
 
 static void calculate_mall_bw_overhead_factor(
@@ -9457,7 +9472,10 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
                        calculate_mcache_setting_params->mall_comb_mcache_c = &mode_lib->ms.mall_comb_mcache_c[k];
                        calculate_mcache_setting_params->lc_comb_mcache = &mode_lib->ms.lc_comb_mcache[k];
 
-                       calculate_mcache_setting(&mode_lib->scratch, calculate_mcache_setting_params);
+                       if (!calculate_mcache_setting(&mode_lib->scratch, calculate_mcache_setting_params)) {
+                               mode_lib->ms.support.ModeSupport = false;
+                               return false;
+                       }
                }
 
                calculate_mall_bw_overhead_factor(
@@ -10933,7 +10951,8 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex
                        calculate_mcache_setting_params->mall_comb_mcache_l = &mode_lib->mp.mall_comb_mcache_l[k];
                        calculate_mcache_setting_params->mall_comb_mcache_c = &mode_lib->mp.mall_comb_mcache_c[k];
                        calculate_mcache_setting_params->lc_comb_mcache = &mode_lib->mp.lc_comb_mcache[k];
-                       calculate_mcache_setting(&mode_lib->scratch, calculate_mcache_setting_params);
+                       if (!calculate_mcache_setting(&mode_lib->scratch, calculate_mcache_setting_params))
+                               return false;
                }
 
                calculate_mall_bw_overhead_factor(