drm/amdgpu: stop blocking for page filp fences
authorChristian König <christian.koenig@amd.com>
Thu, 11 Feb 2016 14:48:30 +0000 (15:48 +0100)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 16 Feb 2016 22:24:07 +0000 (17:24 -0500)
Just register an callback and reschedule the work item if necessary.

Signed-off-by: Christian König <christian.koenig@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c

index 588e86c7c5cc244bf2aa92cd0e21b8bf06503103..fc995b45fa8f87210bbb5890f3d3b2a5527f12c0 100644 (file)
@@ -761,6 +761,7 @@ struct amdgpu_flip_work {
        struct fence                    *excl;
        unsigned                        shared_count;
        struct fence                    **shared;
+       struct fence_cb                 cb;
 };
 
 
index 1d6ef1a95e747026f9eb08bcd0a8d312dfb388b5..edf91593ac87d07bc79ad89c8ba3f232c3ed794e 100644 (file)
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 
-static void amdgpu_flip_wait_fence(struct amdgpu_device *adev,
-                                  struct fence **f)
+static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb)
 {
-       long r;
+       struct amdgpu_flip_work *work =
+               container_of(cb, struct amdgpu_flip_work, cb);
+       struct amdgpu_device *adev = work->adev;
+       struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[work->crtc_id];
 
-       if (*f == NULL)
-               return;
+       fence_put(f);
+       queue_work(amdgpu_crtc->pflip_queue, &work->flip_work);
+}
 
-       r = fence_wait(*f, false);
-       if (r)
-               DRM_ERROR("failed to wait on page flip fence (%ld)!\n", r);
+static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work,
+                                    struct fence **f)
+{
+       struct fence *fence= *f;
+
+       if (fence == NULL)
+               return false;
 
-       /* We continue with the page flip even if we failed to wait on
-        * the fence, otherwise the DRM core and userspace will be
-        * confused about which BO the CRTC is scanning out
-        */
-       fence_put(*f);
        *f = NULL;
+
+       if (!fence_add_callback(fence, &work->cb, amdgpu_flip_callback))
+               return true;
+
+       fence_put(*f);
+       return false;
 }
 
 static void amdgpu_flip_work_func(struct work_struct *__work)
@@ -68,9 +76,12 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
        int vpos, hpos, stat, min_udelay;
        struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
 
-       amdgpu_flip_wait_fence(adev, &work->excl);
+       if (amdgpu_flip_handle_fence(work, &work->excl))
+               return;
+
        for (i = 0; i < work->shared_count; ++i)
-               amdgpu_flip_wait_fence(adev, &work->shared[i]);
+               if (amdgpu_flip_handle_fence(work, &work->shared[i]))
+                       return;
 
        /* We borrow the event spin lock for protecting flip_status */
        spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -234,7 +245,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
        /* update crtc fb */
        crtc->primary->fb = fb;
        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-       queue_work(amdgpu_crtc->pflip_queue, &work->flip_work);
+       amdgpu_flip_work_func(&work->flip_work);
        return 0;
 
 vblank_cleanup: