| From 1e1490a38504419e349caa1b7d55d5c141a9bccb Mon Sep 17 00:00:00 2001 |
| From: Mario Kleiner <mario.kleiner.de@gmail.com> |
| Date: Tue, 1 Mar 2016 21:31:17 +0100 |
| Subject: drm/radeon: Fix error handling in radeon_flip_work_func. |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Mario Kleiner <mario.kleiner.de@gmail.com> |
| |
| commit 1e1490a38504419e349caa1b7d55d5c141a9bccb upstream. |
| |
| This is a port of the patch "drm/amdgpu: Fix error handling in amdgpu_flip_work_func." |
| to fix the following problem for radeon as well which was |
| reported against amdgpu: |
| |
| The patch e1d09dc0ccc6: "drm/amdgpu: Don't hang in |
| amdgpu_flip_work_func on disabled crtc." from Feb 19, 2016, leads to |
| the following static checker warning, as reported by Dan Carpenter in |
| https://lists.freedesktop.org/archives/dri-devel/2016-February/101987.html |
| |
| drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:127 amdgpu_flip_work_func() warn: should this be 'repcnt == -1' |
| drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:136 amdgpu_flip_work_func() error: double unlock 'spin_lock:&crtc->dev->event_lock' |
| drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:136 amdgpu_flip_work_func() error: double unlock 'irqsave:flags' |
| |
| This patch fixes both reported problems: |
| |
| Change post-decrement of repcnt to pre-decrement, so |
| it can't underflow anymore, but still performs up to |
| three repetitions - three is the maximum one could |
| expect in practice. |
| |
| Move the spin_unlock_irqrestore to where it actually |
| belongs. |
| |
| Reviewed-by: Michel Dänzer <michel.daenzer@amd.com> |
| Reported-by: Dan Carpenter <dan.carpenter@oracle.com> |
| Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com> |
| Cc: Michel Dänzer <michel.daenzer@amd.com> |
| Cc: Alex Deucher <alexander.deucher@amd.com> |
| Signed-off-by: Alex Deucher <alexander.deucher@amd.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/radeon/radeon_display.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/gpu/drm/radeon/radeon_display.c |
| +++ b/drivers/gpu/drm/radeon/radeon_display.c |
| @@ -455,7 +455,7 @@ static void radeon_flip_work_func(struct |
| * In practice this won't execute very often unless on very fast |
| * machines because the time window for this to happen is very small. |
| */ |
| - while (radeon_crtc->enabled && repcnt--) { |
| + while (radeon_crtc->enabled && --repcnt) { |
| /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank |
| * start in hpos, and to the "fudged earlier" vblank start in |
| * vpos. |
| @@ -471,13 +471,13 @@ static void radeon_flip_work_func(struct |
| break; |
| |
| /* Sleep at least until estimated real start of hw vblank */ |
| - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
| min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); |
| if (min_udelay > vblank->framedur_ns / 2000) { |
| /* Don't wait ridiculously long - something is wrong */ |
| repcnt = 0; |
| break; |
| } |
| + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
| usleep_range(min_udelay, 2 * min_udelay); |
| spin_lock_irqsave(&crtc->dev->event_lock, flags); |
| }; |