| From 90e94b160c7f647ddffda707f5e3c0c66c170df8 Mon Sep 17 00:00:00 2001 |
| From: Mario Kleiner <mario.kleiner.de@gmail.com> |
| Date: Tue, 1 Mar 2016 21:31:16 +0100 |
| Subject: drm/amdgpu: Fix error handling in amdgpu_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 90e94b160c7f647ddffda707f5e3c0c66c170df8 upstream. |
| |
| 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/amd/amdgpu/amdgpu_display.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c |
| +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c |
| @@ -96,7 +96,7 @@ static void amdgpu_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 (amdgpuCrtc->enabled && repcnt--) { |
| + while (amdgpuCrtc->enabled && --repcnt) { |
| /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank |
| * start in hpos, and to the "fudged earlier" vblank start in |
| * vpos. |
| @@ -112,13 +112,13 @@ static void amdgpu_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); |
| }; |