[PATCH 3/3] drm/radeon: Hide the HW cursor while it's out of bounds
Deucher, Alexander
Alexander.Deucher at amd.com
Thu Oct 27 14:21:10 UTC 2016
> -----Original Message-----
> From: amd-gfx [mailto:amd-gfx-bounces at lists.freedesktop.org] On Behalf
> Of Michel Dänzer
> Sent: Thursday, October 27, 2016 4:00 AM
> To: amd-gfx at lists.freedesktop.org
> Cc: Takashi Iwai; Tomáš Chvátal
> Subject: [PATCH 3/3] drm/radeon: Hide the HW cursor while it's out of
> bounds
>
> From: Michel Dänzer <michel.daenzer at amd.com>
>
> Fixes hangs in that case under some circumstances.
>
> Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1000433
> Cc: stable at vger.kernel.org
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
For the series:
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
> ---
> drivers/gpu/drm/radeon/radeon_cursor.c | 66 +++++++++++++++++++++--
> -----------
> drivers/gpu/drm/radeon/radeon_mode.h | 1 +
> 2 files changed, 42 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c
> b/drivers/gpu/drm/radeon/radeon_cursor.c
> index a3405fc..baf632a 100644
> --- a/drivers/gpu/drm/radeon/radeon_cursor.c
> +++ b/drivers/gpu/drm/radeon/radeon_cursor.c
> @@ -90,6 +90,9 @@ static void radeon_show_cursor(struct drm_crtc *crtc)
> struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
> struct radeon_device *rdev = crtc->dev->dev_private;
>
> + if (radeon_crtc->cursor_out_of_bounds)
> + return;
> +
> if (ASIC_IS_DCE4(rdev)) {
> WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH +
> radeon_crtc->crtc_offset,
> upper_32_bits(radeon_crtc->cursor_addr));
> @@ -146,21 +149,14 @@ static int radeon_cursor_move_locked(struct
> drm_crtc *crtc, int x, int y)
> radeon_crtc->cursor_x = x;
> radeon_crtc->cursor_y = y;
>
> - if (ASIC_IS_AVIVO(rdev)) {
> - /* avivo cursor are offset into the total surface */
> - x += crtc->x;
> - y += crtc->y;
> - }
> - DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
> -
> - if (x < 0) {
> + if (x < 0)
> xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
> - x = 0;
> - }
> - if (y < 0) {
> + if (y < 0)
> yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
> - y = 0;
> - }
> +
> + x += crtc->x;
> + y += crtc->y;
> + DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
>
> /* fixed on DCE6 and newer */
> if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
> @@ -183,27 +179,31 @@ static int radeon_cursor_move_locked(struct
> drm_crtc *crtc, int x, int y)
> if (i > 1) {
> int cursor_end, frame_end;
>
> - cursor_end = x - xorigin + w;
> + cursor_end = x + w;
> frame_end = crtc->x + crtc->mode.crtc_hdisplay;
> if (cursor_end >= frame_end) {
> w = w - (cursor_end - frame_end);
> if (!(frame_end & 0x7f))
> w--;
> - } else {
> - if (!(cursor_end & 0x7f))
> - w--;
> + } else if (cursor_end <= 0) {
> + goto out_of_bounds;
> + } else if (!(cursor_end & 0x7f)) {
> + w--;
> }
> if (w <= 0) {
> - w = 1;
> - cursor_end = x - xorigin + w;
> - if (!(cursor_end & 0x7f)) {
> - x--;
> - WARN_ON_ONCE(x < 0);
> - }
> + goto out_of_bounds;
> }
> }
> }
>
> + if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
> + x >= (crtc->x + crtc->mode.crtc_hdisplay) ||
> + y >= (crtc->y + crtc->mode.crtc_vdisplay))
> + goto out_of_bounds;
> +
> + x += xorigin;
> + y += yorigin;
> +
> if (ASIC_IS_DCE4(rdev)) {
> WREG32(EVERGREEN_CUR_POSITION + radeon_crtc-
> >crtc_offset, (x << 16) | y);
> WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc-
> >crtc_offset, (xorigin << 16) | yorigin);
> @@ -215,6 +215,9 @@ static int radeon_cursor_move_locked(struct
> drm_crtc *crtc, int x, int y)
> WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
> ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
> } else {
> + x -= crtc->x;
> + y -= crtc->y;
> +
> if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
> y *= 2;
>
> @@ -232,6 +235,19 @@ static int radeon_cursor_move_locked(struct
> drm_crtc *crtc, int x, int y)
> yorigin * 256);
> }
>
> + if (radeon_crtc->cursor_out_of_bounds) {
> + radeon_crtc->cursor_out_of_bounds = false;
> + if (radeon_crtc->cursor_bo)
> + radeon_show_cursor(crtc);
> + }
> +
> + return 0;
> +
> + out_of_bounds:
> + if (!radeon_crtc->cursor_out_of_bounds) {
> + radeon_hide_cursor(crtc);
> + radeon_crtc->cursor_out_of_bounds = true;
> + }
> return 0;
> }
>
> @@ -308,12 +324,12 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
> x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x -
> hot_x;
> y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y -
> hot_y;
>
> - radeon_cursor_move_locked(crtc, x, y);
> -
> radeon_crtc->cursor_width = width;
> radeon_crtc->cursor_height = height;
> radeon_crtc->cursor_hot_x = hot_x;
> radeon_crtc->cursor_hot_y = hot_y;
> +
> + radeon_cursor_move_locked(crtc, x, y);
> }
>
> radeon_show_cursor(crtc);
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h
> b/drivers/gpu/drm/radeon/radeon_mode.h
> index bb75201a..f1da484 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -330,6 +330,7 @@ struct radeon_crtc {
> u16 lut_r[256], lut_g[256], lut_b[256];
> bool enabled;
> bool can_tile;
> + bool cursor_out_of_bounds;
> uint32_t crtc_offset;
> struct drm_gem_object *cursor_bo;
> uint64_t cursor_addr;
> --
> 2.10.1
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
More information about the amd-gfx
mailing list