[PATCH 1/3] drm/radeon/kms: add some loop timeouts in pageflip code

Mario Kleiner mario.kleiner at tuebingen.mpg.de
Mon Nov 28 13:12:21 PST 2011


On Nov 28, 2011, at 8:49 PM, alexdeucher at gmail.com wrote:

> From: Alex Deucher <alexander.deucher at amd.com>
>
> Avoid infinite loops waiting for surface updates if a GPU
> reset happens while waiting for a page flip.
>
> See:
> https://bugs.freedesktop.org/show_bug.cgi?id=43191
>
> Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
> Cc: stable at kernel.org
> Cc: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>
> ---
>  drivers/gpu/drm/radeon/evergreen.c |    7 ++++++-
>  drivers/gpu/drm/radeon/r100.c      |    7 ++++++-
>  drivers/gpu/drm/radeon/rs600.c     |    7 ++++++-
>  drivers/gpu/drm/radeon/rv770.c     |    7 ++++++-
>  4 files changed, 24 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/ 
> radeon/evergreen.c
> index 99cdc5d..e78feab 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -84,6 +84,7 @@ u32 evergreen_page_flip(struct radeon_device  
> *rdev, int crtc_id, u64 crtc_base)
>  {
>  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>  	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
> +	int i;
>
>  	/* Lock the graphics update lock */
>  	tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
> @@ -101,7 +102,11 @@ u32 evergreen_page_flip(struct radeon_device  
> *rdev, int crtc_id, u64 crtc_base)
>  	       (u32)crtc_base);
>
>  	/* Wait for update_pending to go high. */
> -	while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset)  
> & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING));
> +	for (i = 0; i < rdev->usec_timeout; i++) {
> +		if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) &  
> EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
> +			break;
> +		udelay(1);
> +	}
>  	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
>
>  	/* Unlock the lock, so double-buffering can take place inside  
> vblank */
> diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/ 
> r100.c
> index 4e71da0..d7fd5aa 100644
> --- a/drivers/gpu/drm/radeon/r100.c
> +++ b/drivers/gpu/drm/radeon/r100.c
> @@ -187,13 +187,18 @@ u32 r100_page_flip(struct radeon_device  
> *rdev, int crtc_id, u64 crtc_base)
>  {
>  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>  	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
> +	int i;
>
>  	/* Lock the graphics update lock */
>  	/* update the scanout addresses */
>  	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
>
>  	/* Wait for update_pending to go high. */
> -	while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) &  
> RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET));
> +	for (i = 0; i < rdev->usec_timeout; i++) {
> +		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) &  
> RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
> +			break;
> +		udelay(1);
> +	}
>  	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
>
>  	/* Unlock the lock, so double-buffering can take place inside  
> vblank */
> diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/ 
> radeon/rs600.c
> index 8ce17ed..8a52cf0 100644
> --- a/drivers/gpu/drm/radeon/rs600.c
> +++ b/drivers/gpu/drm/radeon/rs600.c
> @@ -62,6 +62,7 @@ u32 rs600_page_flip(struct radeon_device *rdev,  
> int crtc_id, u64 crtc_base)
>  {
>  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>  	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
> +	int i;
>
>  	/* Lock the graphics update lock */
>  	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
> @@ -74,7 +75,11 @@ u32 rs600_page_flip(struct radeon_device *rdev,  
> int crtc_id, u64 crtc_base)
>  	       (u32)crtc_base);
>
>  	/* Wait for update_pending to go high. */
> -	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &  
> AVIVO_D1GRPH_SURFACE_UPDATE_PENDING));
> +	for (i = 0; i < rdev->usec_timeout; i++) {
> +		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &  
> AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
> +			break;
> +		udelay(1);
> +	}
>  	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
>
>  	/* Unlock the lock, so double-buffering can take place inside  
> vblank */
> diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/ 
> radeon/rv770.c
> index a9242e6..7bec3f4 100644
> --- a/drivers/gpu/drm/radeon/rv770.c
> +++ b/drivers/gpu/drm/radeon/rv770.c
> @@ -47,6 +47,7 @@ u32 rv770_page_flip(struct radeon_device *rdev,  
> int crtc_id, u64 crtc_base)
>  {
>  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>  	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
> +	int i;
>
>  	/* Lock the graphics update lock */
>  	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
> @@ -66,7 +67,11 @@ u32 rv770_page_flip(struct radeon_device *rdev,  
> int crtc_id, u64 crtc_base)
>  	       (u32)crtc_base);
>
>  	/* Wait for update_pending to go high. */
> -	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &  
> AVIVO_D1GRPH_SURFACE_UPDATE_PENDING));
> +	for (i = 0; i < rdev->usec_timeout; i++) {
> +		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &  
> AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
> +			break;
> +		udelay(1);
> +	}
>  	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
>
>  	/* Unlock the lock, so double-buffering can take place inside  
> vblank */
> -- 
> 1.7.3.4
>



Reviewed-by: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>


*********************************************************************
Mario Kleiner
Max Planck Institute for Biological Cybernetics
Spemannstr. 38
72076 Tuebingen
Germany

e-mail: mario.kleiner at tuebingen.mpg.de
office: +49 (0)7071/601-1623
fax:    +49 (0)7071/601-616
www:    http://www.kyb.tuebingen.mpg.de/~kleinerm
*********************************************************************
"For a successful technology, reality must take precedence
over public relations, for Nature cannot be fooled."
(Richard Feynman)



More information about the dri-devel mailing list