drm/amd/display: Fix divide-by-zero in DPPCLK and DISPCLK calculation
authorGeorge Shen <george.shen@amd.com>
Fri, 20 May 2022 15:55:10 +0000 (11:55 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 21 Jun 2022 22:17:24 +0000 (18:17 -0400)
[Why]
Certain use cases will pass in zero in the new_clocks parameter for all
clocks. This results in a divide-by-zero error when attempting to round
up the new clock.

When new_clocks are zero, no rounding is required, so we can skip it.

[How]
Guard the division calculation with a check to make sure clocks are not
zero.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: George Shen <george.shen@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c

index bab85f3..8ece88d 100644 (file)
@@ -335,14 +335,16 @@ static void dcn32_update_dppclk_dispclk_freq(struct clk_mgr_internal *clk_mgr, s
        int dpp_divider = 0;
        int disp_divider = 0;
 
-       dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
-                       * clk_mgr->base.dentist_vco_freq_khz / new_clocks->dppclk_khz;
-       disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
-                       * clk_mgr->base.dentist_vco_freq_khz / new_clocks->dispclk_khz;
-
-       // Divide back the previous result to round up to the actual clock value that will be set from divider
-       new_clocks->dppclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / dpp_divider;
-       new_clocks->dispclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider;
+       if (new_clocks->dppclk_khz) {
+               dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
+                               * clk_mgr->base.dentist_vco_freq_khz / new_clocks->dppclk_khz;
+               new_clocks->dppclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / dpp_divider;
+       }
+       if (new_clocks->dispclk_khz > 0) {
+               disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
+                               * clk_mgr->base.dentist_vco_freq_khz / new_clocks->dispclk_khz;
+               new_clocks->dispclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider;
+       }
 }
 
 static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,