[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