drm/radeon: cope with foreign fences inside display
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>
Wed, 17 Sep 2014 12:35:02 +0000 (14:35 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 3 Oct 2014 13:19:15 +0000 (09:19 -0400)
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_display.c

index 510fe9677e849396d5aecb317e923a809a6539da..06d24b85003e270c4f8cde9dbd46ca1532558aff 100644 (file)
@@ -712,7 +712,7 @@ struct radeon_flip_work {
        uint64_t                        base;
        struct drm_pending_vblank_event *event;
        struct radeon_bo                *old_rbo;
-       struct radeon_fence             *fence;
+       struct fence                    *fence;
 };
 
 struct r500_irq_stat_regs {
index 4eb37976f8799070c72565eab59b7e6e1f9338fe..00ead8c2758a972debddf97234e206d211db5d7a 100644 (file)
@@ -402,14 +402,21 @@ static void radeon_flip_work_func(struct work_struct *__work)
 
         down_read(&rdev->exclusive_lock);
        if (work->fence) {
-               r = radeon_fence_wait(work->fence, false);
-               if (r == -EDEADLK) {
-                       up_read(&rdev->exclusive_lock);
-                       do {
-                               r = radeon_gpu_reset(rdev);
-                       } while (r == -EAGAIN);
-                       down_read(&rdev->exclusive_lock);
-               }
+               struct radeon_fence *fence;
+
+               fence = to_radeon_fence(work->fence);
+               if (fence && fence->rdev == rdev) {
+                       r = radeon_fence_wait(fence, false);
+                       if (r == -EDEADLK) {
+                               up_read(&rdev->exclusive_lock);
+                               do {
+                                       r = radeon_gpu_reset(rdev);
+                               } while (r == -EAGAIN);
+                               down_read(&rdev->exclusive_lock);
+                       }
+               } else
+                       r = fence_wait(work->fence, false);
+
                if (r)
                        DRM_ERROR("failed to wait on page flip fence (%d)!\n", r);
 
@@ -418,7 +425,8 @@ static void radeon_flip_work_func(struct work_struct *__work)
                 * confused about which BO the CRTC is scanning out
                 */
 
-               radeon_fence_unref(&work->fence);
+               fence_put(work->fence);
+               work->fence = NULL;
        }
 
        /* We borrow the event spin lock for protecting flip_status */
@@ -494,7 +502,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
                DRM_ERROR("failed to pin new rbo buffer before flip\n");
                goto cleanup;
        }
-       work->fence = (struct radeon_fence *)fence_get(reservation_object_get_excl(new_rbo->tbo.resv));
+       work->fence = fence_get(reservation_object_get_excl(new_rbo->tbo.resv));
        radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL);
        radeon_bo_unreserve(new_rbo);
 
@@ -576,7 +584,7 @@ pflip_cleanup:
 
 cleanup:
        drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
-       radeon_fence_unref(&work->fence);
+       fence_put(work->fence);
        kfree(work);
        return r;
 }