aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c43
2 files changed, 28 insertions, 16 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 588e86c7c5cc..fc995b45fa8f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -761,6 +761,7 @@ struct amdgpu_flip_work {
761 struct fence *excl; 761 struct fence *excl;
762 unsigned shared_count; 762 unsigned shared_count;
763 struct fence **shared; 763 struct fence **shared;
764 struct fence_cb cb;
764}; 765};
765 766
766 767
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 1d6ef1a95e74..edf91593ac87 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -35,24 +35,32 @@
35#include <drm/drm_crtc_helper.h> 35#include <drm/drm_crtc_helper.h>
36#include <drm/drm_edid.h> 36#include <drm/drm_edid.h>
37 37
38static void amdgpu_flip_wait_fence(struct amdgpu_device *adev, 38static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb)
39 struct fence **f)
40{ 39{
41 long r; 40 struct amdgpu_flip_work *work =
41 container_of(cb, struct amdgpu_flip_work, cb);
42 struct amdgpu_device *adev = work->adev;
43 struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[work->crtc_id];
42 44
43 if (*f == NULL) 45 fence_put(f);
44 return; 46 queue_work(amdgpu_crtc->pflip_queue, &work->flip_work);
47}
45 48
46 r = fence_wait(*f, false); 49static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work,
47 if (r) 50 struct fence **f)
48 DRM_ERROR("failed to wait on page flip fence (%ld)!\n", r); 51{
52 struct fence *fence= *f;
53
54 if (fence == NULL)
55 return false;
49 56
50 /* We continue with the page flip even if we failed to wait on
51 * the fence, otherwise the DRM core and userspace will be
52 * confused about which BO the CRTC is scanning out
53 */
54 fence_put(*f);
55 *f = NULL; 57 *f = NULL;
58
59 if (!fence_add_callback(fence, &work->cb, amdgpu_flip_callback))
60 return true;
61
62 fence_put(*f);
63 return false;
56} 64}
57 65
58static void amdgpu_flip_work_func(struct work_struct *__work) 66static void amdgpu_flip_work_func(struct work_struct *__work)
@@ -68,9 +76,12 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
68 int vpos, hpos, stat, min_udelay; 76 int vpos, hpos, stat, min_udelay;
69 struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; 77 struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
70 78
71 amdgpu_flip_wait_fence(adev, &work->excl); 79 if (amdgpu_flip_handle_fence(work, &work->excl))
80 return;
81
72 for (i = 0; i < work->shared_count; ++i) 82 for (i = 0; i < work->shared_count; ++i)
73 amdgpu_flip_wait_fence(adev, &work->shared[i]); 83 if (amdgpu_flip_handle_fence(work, &work->shared[i]))
84 return;
74 85
75 /* We borrow the event spin lock for protecting flip_status */ 86 /* We borrow the event spin lock for protecting flip_status */
76 spin_lock_irqsave(&crtc->dev->event_lock, flags); 87 spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -234,7 +245,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
234 /* update crtc fb */ 245 /* update crtc fb */
235 crtc->primary->fb = fb; 246 crtc->primary->fb = fb;
236 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); 247 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
237 queue_work(amdgpu_crtc->pflip_queue, &work->flip_work); 248 amdgpu_flip_work_func(&work->flip_work);
238 return 0; 249 return 0;
239 250
240vblank_cleanup: 251vblank_cleanup: