[PATCH 1/2] drm/radeon: Avoid overflows/divide-by-zero in latency_watermark calculations.

Alex Deucher alexdeucher at gmail.com
Wed Apr 26 21:08:22 UTC 2017


On Sun, Apr 23, 2017 at 7:33 PM, Mario Kleiner
<mario.kleiner.de at gmail.com> wrote:
> 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. Make calcs more overflow resistant.
>
> This is a direct port of the corresponding patch from amdgpu-kms,
> copy-paste for cik from dce-8 and si from dce-6, with a slightly
> simpler variant for evergreen dce-4/5.
>
> Only tested on DCE-4 evergreen with a Radeon HD-5770.
>
> Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
> Cc: Alex Deucher <alexander.deucher at amd.com>

Applied the series.  thanks!

Alex

> ---
>  drivers/gpu/drm/radeon/cik.c       | 19 +++----------------
>  drivers/gpu/drm/radeon/evergreen.c |  8 +-------
>  drivers/gpu/drm/radeon/si.c        | 19 +++----------------
>  3 files changed, 7 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
> index 53710dd..4f034cb 100644
> --- a/drivers/gpu/drm/radeon/cik.c
> +++ b/drivers/gpu/drm/radeon/cik.c
> @@ -9150,23 +9150,10 @@ static u32 dce8_latency_watermark(struct dce8_wm_params *wm)
>         a.full = dfixed_const(available_bandwidth);
>         b.full = dfixed_const(wm->num_heads);
>         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);
> -       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));
> +       lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
>
>         a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
>         b.full = dfixed_const(1000);
> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
> index d1b1e0c..3c9c133 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -2188,13 +2188,7 @@ static u32 evergreen_latency_watermark(struct evergreen_wm_params *wm)
>         b.full = dfixed_const(wm->num_heads);
>         a.full = dfixed_div(a, 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(dfixed_trunc(a), dfixed_trunc(b));
> +       lb_fill_bw = min(dfixed_trunc(a), wm->disp_clk * wm->bytes_per_pixel / 1000);
>
>         a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
>         b.full = dfixed_const(1000);
> diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
> index 528e5a4..3efdfd0 100644
> --- a/drivers/gpu/drm/radeon/si.c
> +++ b/drivers/gpu/drm/radeon/si.c
> @@ -2204,23 +2204,10 @@ static u32 dce6_latency_watermark(struct dce6_wm_params *wm)
>         a.full = dfixed_const(available_bandwidth);
>         b.full = dfixed_const(wm->num_heads);
>         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);
> -       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));
> +       lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
>
>         a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
>         b.full = dfixed_const(1000);
> --
> 2.7.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list