drm/radeon: improve radeon_test_syncing function
authorChristian König <deathsimple@vodafone.de>
Thu, 17 Nov 2011 14:22:44 +0000 (15:22 +0100)
committerDave Airlie <airlied@redhat.com>
Tue, 20 Dec 2011 19:51:37 +0000 (19:51 +0000)
Also test multiple waits on the same semaphore.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/radeon_test.c

index 3ab4be9e63d4dfa9abbb9e8888c2e0d5c2250442..210d99f9193290d9b02d8b3981b7cf61baa03134 100644 (file)
@@ -239,15 +239,20 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
                           struct radeon_ring *ringA,
                           struct radeon_ring *ringB)
 {
-       struct radeon_fence *fence = NULL;
+       struct radeon_fence *fence1 = NULL, *fence2 = NULL;
        struct radeon_semaphore *semaphore = NULL;
        int ridxA = radeon_ring_index(rdev, ringA);
        int ridxB = radeon_ring_index(rdev, ringB);
        int r;
 
-       r = radeon_fence_create(rdev, &fence, ridxA);
+       r = radeon_fence_create(rdev, &fence1, ridxA);
+       if (r) {
+               DRM_ERROR("Failed to create sync fence 1\n");
+               goto out_cleanup;
+       }
+       r = radeon_fence_create(rdev, &fence2, ridxA);
        if (r) {
-               DRM_ERROR("Failed to create sync fence\n");
+               DRM_ERROR("Failed to create sync fence 2\n");
                goto out_cleanup;
        }
 
@@ -263,13 +268,15 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
                goto out_cleanup;
        }
        radeon_semaphore_emit_wait(rdev, ridxA, semaphore);
-       radeon_fence_emit(rdev, fence);
+       radeon_fence_emit(rdev, fence1);
+       radeon_semaphore_emit_wait(rdev, ridxA, semaphore);
+       radeon_fence_emit(rdev, fence2);
        radeon_ring_unlock_commit(rdev, ringA);
 
        mdelay(1000);
 
-       if (radeon_fence_signaled(fence)) {
-               DRM_ERROR("Fence signaled without waiting for semaphore.\n");
+       if (radeon_fence_signaled(fence1)) {
+               DRM_ERROR("Fence signaled without waiting for semaphore.\n");
                goto out_cleanup;
        }
 
@@ -281,20 +288,162 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
        radeon_semaphore_emit_signal(rdev, ridxB, semaphore);
        radeon_ring_unlock_commit(rdev, ringB);
 
-       r = radeon_fence_wait(fence, false);
+       r = radeon_fence_wait(fence1, false);
+       if (r) {
+               DRM_ERROR("Failed to wait for sync fence 1\n");
+               goto out_cleanup;
+       }
+
+       mdelay(1000);
+
+       if (radeon_fence_signaled(fence2)) {
+               DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n");
+               goto out_cleanup;
+       }
+
+       r = radeon_ring_lock(rdev, ringB, 64);
        if (r) {
-               DRM_ERROR("Failed to wait for sync fence\n");
+               DRM_ERROR("Failed to lock ring B %p\n", ringB);
                goto out_cleanup;
        }
+       radeon_semaphore_emit_signal(rdev, ridxB, semaphore);
+       radeon_ring_unlock_commit(rdev, ringB);
 
-       DRM_INFO("Syncing between rings %d and %d seems to work.\n", ridxA, ridxB);
+       r = radeon_fence_wait(fence2, false);
+       if (r) {
+               DRM_ERROR("Failed to wait for sync fence 1\n");
+               goto out_cleanup;
+       }
 
 out_cleanup:
        if (semaphore)
                radeon_semaphore_free(rdev, semaphore);
 
-       if (fence)
-               radeon_fence_unref(&fence);
+       if (fence1)
+               radeon_fence_unref(&fence1);
+
+       if (fence2)
+               radeon_fence_unref(&fence2);
+
+       if (r)
+               printk(KERN_WARNING "Error while testing ring sync (%d).\n", r);
+}
+
+void radeon_test_ring_sync2(struct radeon_device *rdev,
+                           struct radeon_ring *ringA,
+                           struct radeon_ring *ringB,
+                           struct radeon_ring *ringC)
+{
+       struct radeon_fence *fenceA = NULL, *fenceB = NULL;
+       struct radeon_semaphore *semaphore = NULL;
+       int ridxA = radeon_ring_index(rdev, ringA);
+       int ridxB = radeon_ring_index(rdev, ringB);
+       int ridxC = radeon_ring_index(rdev, ringC);
+       bool sigA, sigB;
+       int i, r;
+
+       r = radeon_fence_create(rdev, &fenceA, ridxA);
+       if (r) {
+               DRM_ERROR("Failed to create sync fence 1\n");
+               goto out_cleanup;
+       }
+       r = radeon_fence_create(rdev, &fenceB, ridxB);
+       if (r) {
+               DRM_ERROR("Failed to create sync fence 2\n");
+               goto out_cleanup;
+       }
+
+       r = radeon_semaphore_create(rdev, &semaphore);
+       if (r) {
+               DRM_ERROR("Failed to create semaphore\n");
+               goto out_cleanup;
+       }
+
+       r = radeon_ring_lock(rdev, ringA, 64);
+       if (r) {
+               DRM_ERROR("Failed to lock ring A %d\n", ridxA);
+               goto out_cleanup;
+       }
+       radeon_semaphore_emit_wait(rdev, ridxA, semaphore);
+       radeon_fence_emit(rdev, fenceA);
+       radeon_ring_unlock_commit(rdev, ringA);
+
+       r = radeon_ring_lock(rdev, ringB, 64);
+       if (r) {
+               DRM_ERROR("Failed to lock ring B %d\n", ridxB);
+               goto out_cleanup;
+       }
+       radeon_semaphore_emit_wait(rdev, ridxB, semaphore);
+       radeon_fence_emit(rdev, fenceB);
+       radeon_ring_unlock_commit(rdev, ringB);
+
+       mdelay(1000);
+
+       if (radeon_fence_signaled(fenceA)) {
+               DRM_ERROR("Fence A signaled without waiting for semaphore.\n");
+               goto out_cleanup;
+       }
+       if (radeon_fence_signaled(fenceB)) {
+               DRM_ERROR("Fence A signaled without waiting for semaphore.\n");
+               goto out_cleanup;
+       }
+
+       r = radeon_ring_lock(rdev, ringC, 64);
+       if (r) {
+               DRM_ERROR("Failed to lock ring B %p\n", ringC);
+               goto out_cleanup;
+       }
+       radeon_semaphore_emit_signal(rdev, ridxC, semaphore);
+       radeon_ring_unlock_commit(rdev, ringC);
+
+       for (i = 0; i < 30; ++i) {
+               mdelay(100);
+               sigA = radeon_fence_signaled(fenceA);
+               sigB = radeon_fence_signaled(fenceB);
+               if (sigA || sigB)
+                       break;
+       }
+
+       if (!sigA && !sigB) {
+               DRM_ERROR("Neither fence A nor B has been signaled\n");
+               goto out_cleanup;
+       } else if (sigA && sigB) {
+               DRM_ERROR("Both fence A and B has been signaled\n");
+               goto out_cleanup;
+       }
+
+       DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B');
+
+       r = radeon_ring_lock(rdev, ringC, 64);
+       if (r) {
+               DRM_ERROR("Failed to lock ring B %p\n", ringC);
+               goto out_cleanup;
+       }
+       radeon_semaphore_emit_signal(rdev, ridxC, semaphore);
+       radeon_ring_unlock_commit(rdev, ringC);
+
+       mdelay(1000);
+
+       r = radeon_fence_wait(fenceA, false);
+       if (r) {
+               DRM_ERROR("Failed to wait for sync fence A\n");
+               goto out_cleanup;
+       }
+       r = radeon_fence_wait(fenceB, false);
+       if (r) {
+               DRM_ERROR("Failed to wait for sync fence B\n");
+               goto out_cleanup;
+       }
+
+out_cleanup:
+       if (semaphore)
+               radeon_semaphore_free(rdev, semaphore);
+
+       if (fenceA)
+               radeon_fence_unref(&fenceA);
+
+       if (fenceB)
+               radeon_fence_unref(&fenceB);
 
        if (r)
                printk(KERN_WARNING "Error while testing ring sync (%d).\n", r);
@@ -302,7 +451,7 @@ out_cleanup:
 
 void radeon_test_syncing(struct radeon_device *rdev)
 {
-       int i, j;
+       int i, j, k;
 
        for (i = 1; i < RADEON_NUM_RINGS; ++i) {
                struct radeon_ring *ringA = &rdev->ring[i];
@@ -314,11 +463,33 @@ void radeon_test_syncing(struct radeon_device *rdev)
                        if (!ringB->ready)
                                continue;
 
-                       DRM_INFO("Testing syncing between rings %d and %d\n", i, j);
+                       DRM_INFO("Testing syncing between rings %d and %d...\n", i, j);
                        radeon_test_ring_sync(rdev, ringA, ringB);
 
-                       DRM_INFO("Testing syncing between rings %d and %d\n", j, i);
+                       DRM_INFO("Testing syncing between rings %d and %d...\n", j, i);
                        radeon_test_ring_sync(rdev, ringB, ringA);
+
+                       for (k = 0; k < j; ++k) {
+                               struct radeon_ring *ringC = &rdev->ring[k];
+
+                               DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k);
+                               radeon_test_ring_sync2(rdev, ringA, ringB, ringC);
+
+                               DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j);
+                               radeon_test_ring_sync2(rdev, ringA, ringC, ringB);
+
+                               DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k);
+                               radeon_test_ring_sync2(rdev, ringB, ringA, ringC);
+
+                               DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i);
+                               radeon_test_ring_sync2(rdev, ringB, ringC, ringA);
+
+                               DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j);
+                               radeon_test_ring_sync2(rdev, ringC, ringA, ringB);
+
+                               DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i);
+                               radeon_test_ring_sync2(rdev, ringC, ringB, ringA);
+                       }
                }
        }
 }