[PATCH 3/3] drm/radeon: Hide the HW cursor while it's out of bounds

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----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


[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux