mirror of https://gitee.com/openkylin/linux.git
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 <alexander.deucher@amd.com> Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
d63c277dc6
commit
e190ed1ea7
|
@ -1090,23 +1090,10 @@ static u32 dce_v10_0_latency_watermark(struct dce10_wm_params *wm)
|
||||||
a.full = dfixed_const(available_bandwidth);
|
a.full = dfixed_const(available_bandwidth);
|
||||||
b.full = dfixed_const(wm->num_heads);
|
b.full = dfixed_const(wm->num_heads);
|
||||||
a.full = dfixed_div(a, b);
|
a.full = dfixed_div(a, b);
|
||||||
|
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
|
||||||
|
tmp = min(dfixed_trunc(a), tmp);
|
||||||
|
|
||||||
b.full = dfixed_const(mc_latency + 512);
|
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
|
||||||
c.full = dfixed_const(wm->disp_clk);
|
|
||||||
b.full = dfixed_div(b, c);
|
|
||||||
|
|
||||||
c.full = dfixed_const(dmif_size);
|
|
||||||
b.full = dfixed_div(c, b);
|
|
||||||
|
|
||||||
tmp = min(dfixed_trunc(a), dfixed_trunc(b));
|
|
||||||
|
|
||||||
b.full = dfixed_const(1000);
|
|
||||||
c.full = dfixed_const(wm->disp_clk);
|
|
||||||
b.full = dfixed_div(c, b);
|
|
||||||
c.full = dfixed_const(wm->bytes_per_pixel);
|
|
||||||
b.full = dfixed_mul(b, c);
|
|
||||||
|
|
||||||
lb_fill_bw = min(tmp, dfixed_trunc(b));
|
|
||||||
|
|
||||||
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
|
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
|
||||||
b.full = dfixed_const(1000);
|
b.full = dfixed_const(1000);
|
||||||
|
|
|
@ -1059,23 +1059,10 @@ static u32 dce_v11_0_latency_watermark(struct dce10_wm_params *wm)
|
||||||
a.full = dfixed_const(available_bandwidth);
|
a.full = dfixed_const(available_bandwidth);
|
||||||
b.full = dfixed_const(wm->num_heads);
|
b.full = dfixed_const(wm->num_heads);
|
||||||
a.full = dfixed_div(a, b);
|
a.full = dfixed_div(a, b);
|
||||||
|
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
|
||||||
|
tmp = min(dfixed_trunc(a), tmp);
|
||||||
|
|
||||||
b.full = dfixed_const(mc_latency + 512);
|
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
|
||||||
c.full = dfixed_const(wm->disp_clk);
|
|
||||||
b.full = dfixed_div(b, c);
|
|
||||||
|
|
||||||
c.full = dfixed_const(dmif_size);
|
|
||||||
b.full = dfixed_div(c, b);
|
|
||||||
|
|
||||||
tmp = min(dfixed_trunc(a), dfixed_trunc(b));
|
|
||||||
|
|
||||||
b.full = dfixed_const(1000);
|
|
||||||
c.full = dfixed_const(wm->disp_clk);
|
|
||||||
b.full = dfixed_div(c, b);
|
|
||||||
c.full = dfixed_const(wm->bytes_per_pixel);
|
|
||||||
b.full = dfixed_mul(b, c);
|
|
||||||
|
|
||||||
lb_fill_bw = min(tmp, dfixed_trunc(b));
|
|
||||||
|
|
||||||
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
|
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
|
||||||
b.full = dfixed_const(1000);
|
b.full = dfixed_const(1000);
|
||||||
|
|
|
@ -861,23 +861,10 @@ static u32 dce_v6_0_latency_watermark(struct dce6_wm_params *wm)
|
||||||
a.full = dfixed_const(available_bandwidth);
|
a.full = dfixed_const(available_bandwidth);
|
||||||
b.full = dfixed_const(wm->num_heads);
|
b.full = dfixed_const(wm->num_heads);
|
||||||
a.full = dfixed_div(a, b);
|
a.full = dfixed_div(a, b);
|
||||||
|
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
|
||||||
|
tmp = min(dfixed_trunc(a), tmp);
|
||||||
|
|
||||||
b.full = dfixed_const(mc_latency + 512);
|
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
|
||||||
c.full = dfixed_const(wm->disp_clk);
|
|
||||||
b.full = dfixed_div(b, c);
|
|
||||||
|
|
||||||
c.full = dfixed_const(dmif_size);
|
|
||||||
b.full = dfixed_div(c, b);
|
|
||||||
|
|
||||||
tmp = min(dfixed_trunc(a), dfixed_trunc(b));
|
|
||||||
|
|
||||||
b.full = dfixed_const(1000);
|
|
||||||
c.full = dfixed_const(wm->disp_clk);
|
|
||||||
b.full = dfixed_div(c, b);
|
|
||||||
c.full = dfixed_const(wm->bytes_per_pixel);
|
|
||||||
b.full = dfixed_mul(b, c);
|
|
||||||
|
|
||||||
lb_fill_bw = min(tmp, dfixed_trunc(b));
|
|
||||||
|
|
||||||
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
|
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
|
||||||
b.full = dfixed_const(1000);
|
b.full = dfixed_const(1000);
|
||||||
|
|
|
@ -974,23 +974,10 @@ static u32 dce_v8_0_latency_watermark(struct dce8_wm_params *wm)
|
||||||
a.full = dfixed_const(available_bandwidth);
|
a.full = dfixed_const(available_bandwidth);
|
||||||
b.full = dfixed_const(wm->num_heads);
|
b.full = dfixed_const(wm->num_heads);
|
||||||
a.full = dfixed_div(a, b);
|
a.full = dfixed_div(a, b);
|
||||||
|
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
|
||||||
|
tmp = min(dfixed_trunc(a), tmp);
|
||||||
|
|
||||||
b.full = dfixed_const(mc_latency + 512);
|
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
|
||||||
c.full = dfixed_const(wm->disp_clk);
|
|
||||||
b.full = dfixed_div(b, c);
|
|
||||||
|
|
||||||
c.full = dfixed_const(dmif_size);
|
|
||||||
b.full = dfixed_div(c, b);
|
|
||||||
|
|
||||||
tmp = min(dfixed_trunc(a), dfixed_trunc(b));
|
|
||||||
|
|
||||||
b.full = dfixed_const(1000);
|
|
||||||
c.full = dfixed_const(wm->disp_clk);
|
|
||||||
b.full = dfixed_div(c, b);
|
|
||||||
c.full = dfixed_const(wm->bytes_per_pixel);
|
|
||||||
b.full = dfixed_mul(b, c);
|
|
||||||
|
|
||||||
lb_fill_bw = min(tmp, dfixed_trunc(b));
|
|
||||||
|
|
||||||
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
|
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
|
||||||
b.full = dfixed_const(1000);
|
b.full = dfixed_const(1000);
|
||||||
|
|
Loading…
Reference in New Issue