summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian König <deathsimple@vodafone.de>2011-09-27 12:31:00 +0200
committerJerome Glisse <jglisse@redhat.com>2011-12-05 18:25:05 -0500
commitba4da430f82fc79ee990901c62bf32b6f8b9c90e (patch)
tree2cc86fe39815722fe7ae09b2e294d5e3cee3955b
parent09a3f1153d2648ab6f636b3ccc998100ee6b2cc5 (diff)
drm/radeon: Add radeon_test_syncing function v2
Tests syncing between all rings by using semaphores and fences. v2: use radeon_testing as a bit flag rather than on/off switch this allow to test for one thing at a time (bo_move or semaphore test). It kind of break the usage if user wheren't using 1 for bo move test but as it's a test feature i believe it's ok. Signed-off-by: Christian König <deathsimple@vodafone.de> Reviewed-by: Jerome Glisse <jglisse@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_test.c88
3 files changed, 96 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 3abcdc7a117e..d6af618605d3 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -914,6 +914,10 @@ void radeon_benchmark(struct radeon_device *rdev, int test_number);
* Testing
*/
void radeon_test_moves(struct radeon_device *rdev);
+void radeon_test_ring_sync(struct radeon_device *rdev,
+ struct radeon_cp *cpA,
+ struct radeon_cp *cpB);
+void radeon_test_syncing(struct radeon_device *rdev);
/*
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index c6e2cac2479e..d96300da3c5a 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -817,9 +817,12 @@ int radeon_device_init(struct radeon_device *rdev,
if (r)
return r;
}
- if (radeon_testing) {
+ if ((radeon_testing & 1)) {
radeon_test_moves(rdev);
}
+ if ((radeon_testing & 2)) {
+ radeon_test_syncing(rdev);
+ }
if (radeon_benchmarking) {
radeon_benchmark(rdev, radeon_benchmarking);
}
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
index 160e7df77551..5f4d31ef3933 100644
--- a/drivers/gpu/drm/radeon/radeon_test.c
+++ b/drivers/gpu/drm/radeon/radeon_test.c
@@ -234,3 +234,91 @@ out_cleanup:
printk(KERN_WARNING "Error while testing BO move.\n");
}
}
+
+void radeon_test_ring_sync(struct radeon_device *rdev,
+ struct radeon_cp *cpA,
+ struct radeon_cp *cpB)
+{
+ struct radeon_fence *fence = NULL;
+ struct radeon_semaphore *semaphore = NULL;
+ int ringA = radeon_ring_index(rdev, cpA);
+ int ringB = radeon_ring_index(rdev, cpB);
+ int r;
+
+ r = radeon_fence_create(rdev, &fence, ringA);
+ if (r) {
+ DRM_ERROR("Failed to create sync fence\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, cpA, 64);
+ if (r) {
+ DRM_ERROR("Failed to lock ring %d\n", ringA);
+ goto out_cleanup;
+ }
+ radeon_semaphore_emit_wait(rdev, ringA, semaphore);
+ radeon_fence_emit(rdev, fence);
+ radeon_ring_unlock_commit(rdev, cpA);
+
+ mdelay(1000);
+
+ if (radeon_fence_signaled(fence)) {
+ DRM_ERROR("Fence signaled without waiting for semaphore.\n");
+ goto out_cleanup;
+ }
+
+ r = radeon_ring_lock(rdev, cpB, 64);
+ if (r) {
+ DRM_ERROR("Failed to lock ring %d\n", ringB);
+ goto out_cleanup;
+ }
+ radeon_semaphore_emit_signal(rdev, ringB, semaphore);
+ radeon_ring_unlock_commit(rdev, cpB);
+
+ r = radeon_fence_wait(fence, false);
+ if (r) {
+ DRM_ERROR("Failed to wait for sync fence\n");
+ goto out_cleanup;
+ }
+
+ DRM_INFO("Syncing between rings %d and %d seems to work.\n", ringA, ringB);
+
+out_cleanup:
+ if (semaphore)
+ radeon_semaphore_free(rdev, semaphore);
+
+ if (fence)
+ radeon_fence_unref(&fence);
+
+ if (r)
+ printk(KERN_WARNING "Error while testing ring sync (%d).\n", r);
+}
+
+void radeon_test_syncing(struct radeon_device *rdev)
+{
+ int i, j;
+
+ for (i = 1; i < RADEON_NUM_RINGS; ++i) {
+ struct radeon_cp *cpA = &rdev->cp[i];
+ if (!cpA->ready)
+ continue;
+
+ for (j = 0; j < i; ++j) {
+ struct radeon_cp *cpB = &rdev->cp[j];
+ if (!cpB->ready)
+ continue;
+
+ DRM_INFO("Testing syncing between rings %d and %d\n", i, j);
+ radeon_test_ring_sync(rdev, cpA, cpB);
+
+ DRM_INFO("Testing syncing between rings %d and %d\n", j, i);
+ radeon_test_ring_sync(rdev, cpB, cpA);
+ }
+ }
+}