drm/nouveau: always queue flips relative to kernel channel activity
authorBen Skeggs <bskeggs@redhat.com>
Wed, 13 Nov 2013 00:17:17 +0000 (10:17 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 14 Nov 2013 04:55:15 +0000 (14:55 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_display.c

index 547c42b4a35d4a3d22909af35c4f28a4b4e7ccbf..4b124a67fc043a096d822d47758cedb0f53ba1bb 100644 (file)
@@ -591,7 +591,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
        struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
        struct nouveau_page_flip_state *s;
-       struct nouveau_channel *chan = NULL;
+       struct nouveau_channel *chan = drm->channel;
        struct nouveau_fence *fence;
        int ret;
 
@@ -602,14 +602,13 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        if (!s)
                return -ENOMEM;
 
-       /* Choose the channel the flip will be handled in */
-       spin_lock(&old_bo->bo.bdev->fence_lock);
-       fence = new_bo->bo.sync_obj;
-       if (fence)
-               chan = fence->channel;
-       if (!chan)
-               chan = drm->channel;
-       spin_unlock(&old_bo->bo.bdev->fence_lock);
+       /* synchronise rendering channel with the kernel's channel */
+       spin_lock(&new_bo->bo.bdev->fence_lock);
+       fence = nouveau_fence_ref(new_bo->bo.sync_obj);
+       spin_unlock(&new_bo->bo.bdev->fence_lock);
+       ret = nouveau_fence_sync(fence, chan);
+       if (ret)
+               return ret;
 
        if (new_bo != old_bo) {
                ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);