Skip to content

Commit d385c16

Browse files
coxuintelzhenyw
authored andcommitted
drm/i915/gvt: Prevent divided by zero when calculating refresh rate
To get refresh rate as vblank timer period and keep the precision, the calculation of rate is multiplied by 1000. However old logic was using: rate = pixel clock / (h * v / 1000). When the h/v total is invalid, like all 0, h * v / 1000 will be rounded to 0, which leads to a divided by 0 fault. 0 H/V are already checked above. Instead of divide after divide, refine the calculation to divide after multiply: "pixel clock * 1000 / (h * v)" Guest driver should guarantee the correctness of the timing regs' value. Fixes: 6a4500c ("drm/i915/gvt: Get accurate vGPU virtual display refresh rate from vreg") Reported-by: Zhenyu Wang <[email protected]> Signed-off-by: Colin Xu <[email protected]> Signed-off-by: Zhenyu Wang <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected] Reviewed-by: Zhenyu Wang <[email protected]>
1 parent e65a4d3 commit d385c16

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

drivers/gpu/drm/i915/gvt/handlers.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -669,8 +669,8 @@ static void vgpu_update_refresh_rate(struct intel_vgpu *vgpu)
669669
link_n = vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A));
670670

671671
/* Get H/V total from transcoder timing */
672-
htotal = (vgpu_vreg_t(vgpu, HTOTAL(TRANSCODER_A)) >> TRANS_HTOTAL_SHIFT) + 1;
673-
vtotal = (vgpu_vreg_t(vgpu, VTOTAL(TRANSCODER_A)) >> TRANS_VTOTAL_SHIFT) + 1;
672+
htotal = (vgpu_vreg_t(vgpu, HTOTAL(TRANSCODER_A)) >> TRANS_HTOTAL_SHIFT);
673+
vtotal = (vgpu_vreg_t(vgpu, VTOTAL(TRANSCODER_A)) >> TRANS_VTOTAL_SHIFT);
674674

675675
if (dp_br && link_n && htotal && vtotal) {
676676
u64 pixel_clk = 0;
@@ -682,7 +682,7 @@ static void vgpu_update_refresh_rate(struct intel_vgpu *vgpu)
682682
pixel_clk *= MSEC_PER_SEC;
683683

684684
/* Calcuate refresh rate by (pixel_clk / (h_total * v_total)) */
685-
new_rate = DIV64_U64_ROUND_CLOSEST(pixel_clk, div64_u64(mul_u32_u32(htotal, vtotal), MSEC_PER_SEC));
685+
new_rate = DIV64_U64_ROUND_CLOSEST(mul_u64_u32_shr(pixel_clk, MSEC_PER_SEC, 0), mul_u32_u32(htotal + 1, vtotal + 1));
686686

687687
if (*old_rate != new_rate)
688688
*old_rate = new_rate;

0 commit comments

Comments
 (0)