drm/radeon: add error handling to fence_wait_empty_locked
authorChristian König <deathsimple@vodafone.de>
Fri, 29 Jun 2012 09:33:12 +0000 (11:33 +0200)
committerChristian König <deathsimple@vodafone.de>
Tue, 17 Jul 2012 08:31:39 +0000 (10:31 +0200)
Instead of returning the error handle it directly
and while at it fix the comments about the ring lock.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_fence.c

index 77b4519b19b8379b451c4deb3954386e73e758b4..5861ec86725f7f703342cea3a4f7f80e9a0edebb 100644 (file)
@@ -239,7 +239,7 @@ void radeon_fence_process(struct radeon_device *rdev, int ring);
 bool radeon_fence_signaled(struct radeon_fence *fence);
 int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
 int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring);
-int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
+void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
 int radeon_fence_wait_any(struct radeon_device *rdev,
                          struct radeon_fence **fences,
                          bool intr);
index 7b55625a5e1826dbfb5fcf49546d26e7d48a72ce..be4e4f390e898fd1952c3850b5bf4d0aa135f3ab 100644 (file)
@@ -440,14 +440,11 @@ int radeon_fence_wait_any(struct radeon_device *rdev,
        return 0;
 }
 
+/* caller must hold ring lock */
 int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring)
 {
        uint64_t seq;
 
-       /* We are not protected by ring lock when reading current seq but
-        * it's ok as worst case is we return to early while we could have
-        * wait.
-        */
        seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL;
        if (seq >= rdev->fence_drv[ring].sync_seq[ring]) {
                /* nothing to wait for, last_seq is
@@ -457,15 +454,27 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring)
        return radeon_fence_wait_seq(rdev, seq, ring, false, false);
 }
 
-int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
+/* caller must hold ring lock */
+void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
 {
-       /* We are not protected by ring lock when reading current seq
-        * but it's ok as wait empty is call from place where no more
-        * activity can be scheduled so there won't be concurrent access
-        * to seq value.
-        */
-       return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].sync_seq[ring],
-                                    ring, false, false);
+       uint64_t seq = rdev->fence_drv[ring].sync_seq[ring];
+
+       while(1) {
+               int r;
+               r = radeon_fence_wait_seq(rdev, seq, ring, false, false);
+               if (r == -EDEADLK) {
+                       mutex_unlock(&rdev->ring_lock);
+                       r = radeon_gpu_reset(rdev);
+                       mutex_lock(&rdev->ring_lock);
+                       if (!r)
+                               continue;
+               }
+               if (r) {
+                       dev_err(rdev->dev, "error waiting for ring to become"
+                               " idle (%d)\n", r);
+               }
+               return;
+       }
 }
 
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence)