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)
