Skip to content

Commit e190ed1

Browse files
kleinermalexdeucher
authored andcommitted
drm/amdgpu: Avoid overflows/divide-by-zero in latency_watermark calculations.
At dot clocks > approx. 250 Mhz, some of these calcs will overflow and cause miscalculation of latency watermarks, and for some overflows also divide-by-zero driver crash ("divide error: 0000 [#1] PREEMPT SMP" in "dce_v10_0_latency_watermark+0x12d/0x190"). This zero-divide happened, e.g., on AMD Tonga Pro under DCE-10, on a Displayport panel when trying to set a video mode of 2560x1440 at 165 Hz vrefresh with a dot clock of 635.540 Mhz. Refine calculations to avoid the overflows. Tested for DCE-10 with R9 380 Tonga + ASUS ROG PG279 panel. Reviewed-by: Alex Deucher <[email protected]> Signed-off-by: Mario Kleiner <[email protected]> Signed-off-by: Alex Deucher <[email protected]> Cc: [email protected]
1 parent d63c277 commit e190ed1

File tree

4 files changed

+12
-64
lines changed

4 files changed

+12
-64
lines changed

drivers/gpu/drm/amd/amdgpu/dce_v10_0.c

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,23 +1090,10 @@ static u32 dce_v10_0_latency_watermark(struct dce10_wm_params *wm)
10901090
a.full = dfixed_const(available_bandwidth);
10911091
b.full = dfixed_const(wm->num_heads);
10921092
a.full = dfixed_div(a, b);
1093+
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
1094+
tmp = min(dfixed_trunc(a), tmp);
10931095

1094-
b.full = dfixed_const(mc_latency + 512);
1095-
c.full = dfixed_const(wm->disp_clk);
1096-
b.full = dfixed_div(b, c);
1097-
1098-
c.full = dfixed_const(dmif_size);
1099-
b.full = dfixed_div(c, b);
1100-
1101-
tmp = min(dfixed_trunc(a), dfixed_trunc(b));
1102-
1103-
b.full = dfixed_const(1000);
1104-
c.full = dfixed_const(wm->disp_clk);
1105-
b.full = dfixed_div(c, b);
1106-
c.full = dfixed_const(wm->bytes_per_pixel);
1107-
b.full = dfixed_mul(b, c);
1108-
1109-
lb_fill_bw = min(tmp, dfixed_trunc(b));
1096+
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
11101097

11111098
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
11121099
b.full = dfixed_const(1000);

drivers/gpu/drm/amd/amdgpu/dce_v11_0.c

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,23 +1059,10 @@ static u32 dce_v11_0_latency_watermark(struct dce10_wm_params *wm)
10591059
a.full = dfixed_const(available_bandwidth);
10601060
b.full = dfixed_const(wm->num_heads);
10611061
a.full = dfixed_div(a, b);
1062+
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
1063+
tmp = min(dfixed_trunc(a), tmp);
10621064

1063-
b.full = dfixed_const(mc_latency + 512);
1064-
c.full = dfixed_const(wm->disp_clk);
1065-
b.full = dfixed_div(b, c);
1066-
1067-
c.full = dfixed_const(dmif_size);
1068-
b.full = dfixed_div(c, b);
1069-
1070-
tmp = min(dfixed_trunc(a), dfixed_trunc(b));
1071-
1072-
b.full = dfixed_const(1000);
1073-
c.full = dfixed_const(wm->disp_clk);
1074-
b.full = dfixed_div(c, b);
1075-
c.full = dfixed_const(wm->bytes_per_pixel);
1076-
b.full = dfixed_mul(b, c);
1077-
1078-
lb_fill_bw = min(tmp, dfixed_trunc(b));
1065+
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
10791066

10801067
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
10811068
b.full = dfixed_const(1000);

drivers/gpu/drm/amd/amdgpu/dce_v6_0.c

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -861,23 +861,10 @@ static u32 dce_v6_0_latency_watermark(struct dce6_wm_params *wm)
861861
a.full = dfixed_const(available_bandwidth);
862862
b.full = dfixed_const(wm->num_heads);
863863
a.full = dfixed_div(a, b);
864+
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
865+
tmp = min(dfixed_trunc(a), tmp);
864866

865-
b.full = dfixed_const(mc_latency + 512);
866-
c.full = dfixed_const(wm->disp_clk);
867-
b.full = dfixed_div(b, c);
868-
869-
c.full = dfixed_const(dmif_size);
870-
b.full = dfixed_div(c, b);
871-
872-
tmp = min(dfixed_trunc(a), dfixed_trunc(b));
873-
874-
b.full = dfixed_const(1000);
875-
c.full = dfixed_const(wm->disp_clk);
876-
b.full = dfixed_div(c, b);
877-
c.full = dfixed_const(wm->bytes_per_pixel);
878-
b.full = dfixed_mul(b, c);
879-
880-
lb_fill_bw = min(tmp, dfixed_trunc(b));
867+
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
881868

882869
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
883870
b.full = dfixed_const(1000);

drivers/gpu/drm/amd/amdgpu/dce_v8_0.c

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -974,23 +974,10 @@ static u32 dce_v8_0_latency_watermark(struct dce8_wm_params *wm)
974974
a.full = dfixed_const(available_bandwidth);
975975
b.full = dfixed_const(wm->num_heads);
976976
a.full = dfixed_div(a, b);
977+
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
978+
tmp = min(dfixed_trunc(a), tmp);
977979

978-
b.full = dfixed_const(mc_latency + 512);
979-
c.full = dfixed_const(wm->disp_clk);
980-
b.full = dfixed_div(b, c);
981-
982-
c.full = dfixed_const(dmif_size);
983-
b.full = dfixed_div(c, b);
984-
985-
tmp = min(dfixed_trunc(a), dfixed_trunc(b));
986-
987-
b.full = dfixed_const(1000);
988-
c.full = dfixed_const(wm->disp_clk);
989-
b.full = dfixed_div(c, b);
990-
c.full = dfixed_const(wm->bytes_per_pixel);
991-
b.full = dfixed_mul(b, c);
992-
993-
lb_fill_bw = min(tmp, dfixed_trunc(b));
980+
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
994981

995982
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
996983
b.full = dfixed_const(1000);

0 commit comments

Comments
 (0)