diff options
| author | Alex Deucher <alexander.deucher@amd.com> | 2011-11-28 14:49:26 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2011-12-01 04:56:31 -0500 |
| commit | f64964796dedca340608fb1075ab6baad5625851 (patch) | |
| tree | 60812ba63cd0ffe4da61d5cbdf5b97c27a3eb474 | |
| parent | 4f3e0b1d33bfeb1e05e53073c6f277176ff9e368 (diff) | |
drm/radeon/kms: add some loop timeouts in pageflip code
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@amd.com>
Cc: stable@kernel.org
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Tested-by: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/rs600.c | 7 | ||||
| -rw-r--r-- | 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 1d603a3335db..5e00d1670aa9 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -82,6 +82,7 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | |||
| 82 | { | 82 | { |
| 83 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 83 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
| 84 | u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); | 84 | u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); |
| 85 | int i; | ||
| 85 | 86 | ||
| 86 | /* Lock the graphics update lock */ | 87 | /* Lock the graphics update lock */ |
| 87 | tmp |= EVERGREEN_GRPH_UPDATE_LOCK; | 88 | tmp |= EVERGREEN_GRPH_UPDATE_LOCK; |
| @@ -99,7 +100,11 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | |||
| 99 | (u32)crtc_base); | 100 | (u32)crtc_base); |
| 100 | 101 | ||
| 101 | /* Wait for update_pending to go high. */ | 102 | /* Wait for update_pending to go high. */ |
| 102 | while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)); | 103 | for (i = 0; i < rdev->usec_timeout; i++) { |
| 104 | if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) | ||
| 105 | break; | ||
| 106 | udelay(1); | ||
| 107 | } | ||
| 103 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); | 108 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); |
| 104 | 109 | ||
| 105 | /* Unlock the lock, so double-buffering can take place inside vblank */ | 110 | /* 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 ad158ea49901..bfc08f6320f8 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) | |||
| 187 | { | 187 | { |
| 188 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 188 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
| 189 | u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; | 189 | u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; |
| 190 | int i; | ||
| 190 | 191 | ||
| 191 | /* Lock the graphics update lock */ | 192 | /* Lock the graphics update lock */ |
| 192 | /* update the scanout addresses */ | 193 | /* update the scanout addresses */ |
| 193 | WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); | 194 | WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); |
| 194 | 195 | ||
| 195 | /* Wait for update_pending to go high. */ | 196 | /* Wait for update_pending to go high. */ |
| 196 | while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)); | 197 | for (i = 0; i < rdev->usec_timeout; i++) { |
| 198 | if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) | ||
| 199 | break; | ||
| 200 | udelay(1); | ||
| 201 | } | ||
| 197 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); | 202 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); |
| 198 | 203 | ||
| 199 | /* Unlock the lock, so double-buffering can take place inside vblank */ | 204 | /* 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 481b99e89f65..b1053d640423 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) | |||
| 62 | { | 62 | { |
| 63 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 63 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
| 64 | u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); | 64 | u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); |
| 65 | int i; | ||
| 65 | 66 | ||
| 66 | /* Lock the graphics update lock */ | 67 | /* Lock the graphics update lock */ |
| 67 | tmp |= AVIVO_D1GRPH_UPDATE_LOCK; | 68 | tmp |= AVIVO_D1GRPH_UPDATE_LOCK; |
| @@ -74,7 +75,11 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | |||
| 74 | (u32)crtc_base); | 75 | (u32)crtc_base); |
| 75 | 76 | ||
| 76 | /* Wait for update_pending to go high. */ | 77 | /* Wait for update_pending to go high. */ |
| 77 | while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); | 78 | for (i = 0; i < rdev->usec_timeout; i++) { |
| 79 | if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) | ||
| 80 | break; | ||
| 81 | udelay(1); | ||
| 82 | } | ||
| 78 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); | 83 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); |
| 79 | 84 | ||
| 80 | /* Unlock the lock, so double-buffering can take place inside vblank */ | 85 | /* 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 a983f410ab89..23ae1c60ab3d 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) | |||
| 47 | { | 47 | { |
| 48 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 48 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
| 49 | u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); | 49 | u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); |
| 50 | int i; | ||
| 50 | 51 | ||
| 51 | /* Lock the graphics update lock */ | 52 | /* Lock the graphics update lock */ |
| 52 | tmp |= AVIVO_D1GRPH_UPDATE_LOCK; | 53 | tmp |= AVIVO_D1GRPH_UPDATE_LOCK; |
| @@ -66,7 +67,11 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | |||
| 66 | (u32)crtc_base); | 67 | (u32)crtc_base); |
| 67 | 68 | ||
| 68 | /* Wait for update_pending to go high. */ | 69 | /* Wait for update_pending to go high. */ |
| 69 | while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); | 70 | for (i = 0; i < rdev->usec_timeout; i++) { |
| 71 | if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) | ||
| 72 | break; | ||
| 73 | udelay(1); | ||
| 74 | } | ||
| 70 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); | 75 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); |
| 71 | 76 | ||
| 72 | /* Unlock the lock, so double-buffering can take place inside vblank */ | 77 | /* Unlock the lock, so double-buffering can take place inside vblank */ |
