diff mbox

[igt] vgem: Add basic dma-buf fence interop

Message ID 1466582546-28083-1-git-send-email-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson June 22, 2016, 8:02 a.m. UTC
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 lib/igt_vgem.c     | 70 ++++++++++++++++++++++++++++++++++++++
 lib/igt_vgem.h     |  4 +++
 tests/prime_vgem.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 tests/vgem_basic.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 259 insertions(+), 5 deletions(-)
diff mbox

Patch

diff --git a/lib/igt_vgem.c b/lib/igt_vgem.c
index 4fe166a..95731d9 100644
--- a/lib/igt_vgem.c
+++ b/lib/igt_vgem.c
@@ -80,3 +80,73 @@  void *vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot)
 	return ptr;
 }
 
+#define LOCAL_VGEM_FENCE_ATTACH   0x1
+#define LOCAL_VGEM_FENCE_SIGNAL   0x2
+
+#define LOCAL_IOCTL_VGEM_FENCE_ATTACH     DRM_IOWR( DRM_COMMAND_BASE + LOCAL_VGEM_FENCE_ATTACH, struct local_vgem_fence_attach)
+#define LOCAL_IOCTL_VGEM_FENCE_SIGNAL     DRM_IOW( DRM_COMMAND_BASE + LOCAL_VGEM_FENCE_SIGNAL, struct local_vgem_fence_signal)
+
+struct local_vgem_fence_attach {
+	uint32_t handle;
+	uint32_t flags;
+#define VGEM_FENCE_WRITE 0x1
+	uint32_t out_fence;
+	uint32_t pad;
+};
+
+struct local_vgem_fence_signal {
+	uint32_t fence;
+	uint32_t flags;
+};
+
+bool vgem_has_fences(int fd)
+{
+	struct local_vgem_fence_signal arg;
+	int err;
+
+	err = 0;
+	memset(&arg, 0, sizeof(arg));
+	if (drmIoctl(fd, LOCAL_IOCTL_VGEM_FENCE_SIGNAL, &arg))
+		err = -errno;
+	errno = 0;
+	return err == -ENOENT;
+}
+
+static int __vgem_fence_attach(int fd, struct local_vgem_fence_attach *arg)
+{
+	int err = 0;
+	if (igt_ioctl(fd, LOCAL_IOCTL_VGEM_FENCE_ATTACH, arg))
+		err = -errno;
+	errno = 0;
+	return err;
+}
+
+uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, bool write)
+{
+	struct local_vgem_fence_attach arg;
+
+	memset(&arg, 0, sizeof(arg));
+	arg.handle = bo->handle;
+	if (write)
+		arg.flags |= VGEM_FENCE_WRITE;
+	igt_assert_eq(__vgem_fence_attach(fd, &arg), 0);
+	return arg.out_fence;
+}
+
+static int __vgem_fence_signal(int fd, struct local_vgem_fence_signal *arg)
+{
+	int err = 0;
+	if (igt_ioctl(fd, LOCAL_IOCTL_VGEM_FENCE_SIGNAL, arg))
+		err = -errno;
+	errno = 0;
+	return err;
+}
+
+void vgem_fence_signal(int fd, uint32_t fence)
+{
+	struct local_vgem_fence_signal arg;
+
+	memset(&arg, 0, sizeof(arg));
+	arg.fence = fence;
+	igt_assert_eq(__vgem_fence_signal(fd, &arg), 0);
+}
diff --git a/lib/igt_vgem.h b/lib/igt_vgem.h
index 9e4a55e..91c77ba 100644
--- a/lib/igt_vgem.h
+++ b/lib/igt_vgem.h
@@ -39,4 +39,8 @@  void vgem_create(int fd, struct vgem_bo *bo);
 void *__vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot);
 void *vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot);
 
+bool vgem_has_fences(int fd);
+uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, bool write);
+void vgem_fence_signal(int fd, uint32_t fence);
+
 #endif /* IGT_VGEM_H */
diff --git a/tests/prime_vgem.c b/tests/prime_vgem.c
index 6bdd567..be4a43c 100644
--- a/tests/prime_vgem.c
+++ b/tests/prime_vgem.c
@@ -309,21 +309,88 @@  static void test_sync(int i915, int vgem, unsigned ring, uint32_t flags)
 	vgem_create(vgem, &scratch);
 	dmabuf = prime_handle_to_fd(vgem, scratch.handle);
 
+	ptr = mmap(NULL, scratch.size, PROT_READ, MAP_SHARED, dmabuf, 0);
+	igt_assert(ptr != MAP_FAILED);
+	gem_close(vgem, scratch.handle);
+
 	work(i915, dmabuf, ring, flags);
 
 	prime_sync_start(dmabuf, false);
-
-	ptr = vgem_mmap(vgem, &scratch, PROT_READ);
 	for (i = 0; i < 1024; i++)
 		igt_assert_eq_u32(ptr[i], i);
-	munmap(ptr, 4096);
 
 	prime_sync_end(dmabuf, false);
+	close(dmabuf);
+
+	munmap(ptr, scratch.size);
+}
+
+static void test_fence_wait(int i915, int vgem, unsigned ring, unsigned flags)
+{
+	struct vgem_bo scratch;
+	uint32_t fence;
+	uint32_t *ptr;
+	int dmabuf;
+
+	scratch.width = 1024;
+	scratch.height = 1;
+	scratch.bpp = 32;
+	vgem_create(vgem, &scratch);
 
+	dmabuf = prime_handle_to_fd(vgem, scratch.handle);
+	fence = vgem_fence_attach(vgem, &scratch, true);
 	gem_close(vgem, scratch.handle);
+
+	igt_fork(child, 1)
+		work(i915, dmabuf, ring, flags);
+
+	sleep(1);
+	vgem_fence_signal(vgem, fence);
+	igt_waitchildren();
+
+	ptr = mmap(NULL, scratch.size, PROT_READ, MAP_SHARED, dmabuf, 0);
+	igt_assert(ptr != MAP_FAILED);
+
+	prime_sync_start(dmabuf, false);
+	for (int i = 0; i < 1024; i++)
+		igt_assert_eq_u32(ptr[i], i);
+	prime_sync_end(dmabuf, false);
+	munmap(ptr, scratch.size);
+
 	close(dmabuf);
 }
 
+static void test_fence_hang(int i915, int vgem, bool write)
+{
+	struct vgem_bo scratch;
+	uint32_t *ptr;
+	int dmabuf;
+	int i;
+
+	scratch.width = 1024;
+	scratch.height = 1;
+	scratch.bpp = 32;
+	vgem_create(vgem, &scratch);
+	dmabuf = prime_handle_to_fd(vgem, scratch.handle);
+	vgem_fence_attach(vgem, &scratch, write);
+
+	ptr = mmap(NULL, scratch.size, PROT_READ, MAP_SHARED, dmabuf, 0);
+	igt_assert(ptr != MAP_FAILED);
+	gem_close(vgem, scratch.handle);
+
+	work(i915, dmabuf, I915_EXEC_DEFAULT, 0);
+
+	/* The work should have been cancelled */
+
+	prime_sync_start(dmabuf, false);
+	for (i = 0; i < 1024; i++)
+		igt_assert_eq_u32(ptr[i], 0);
+	prime_sync_end(dmabuf, false);
+	close(dmabuf);
+
+	munmap(ptr, scratch.size);
+}
+
 static bool has_prime_export(int fd)
 {
 	uint64_t value;
@@ -411,6 +478,31 @@  igt_main
 		}
 	}
 
+	/* Fence testing */
+	igt_subtest_group {
+		igt_fixture {
+			igt_require(vgem_has_fences(vgem));
+		}
+
+		for (e = intel_execution_engines; e->name; e++) {
+			igt_subtest_f("%sfence-wait-%s",
+					e->exec_id == 0 ? "basic-" : "",
+					e->name) {
+				gem_require_ring(i915, e->exec_id | e->flags);
+				igt_skip_on_f(gen == 6 &&
+						e->exec_id == I915_EXEC_BSD,
+						"MI_STORE_DATA broken on gen6 bsd\n");
+				gem_quiescent_gpu(i915);
+				test_fence_wait(i915, vgem, e->exec_id, e->flags);
+			}
+		}
+
+		igt_subtest("fence-read-hang")
+			test_fence_hang(i915, vgem, false);
+		igt_subtest("fence-write-hang")
+			test_fence_hang(i915, vgem, true);
+	}
+
 	igt_fixture {
 		close(i915);
 		close(vgem);
diff --git a/tests/vgem_basic.c b/tests/vgem_basic.c
index b4337ee..9feabf7 100644
--- a/tests/vgem_basic.c
+++ b/tests/vgem_basic.c
@@ -27,6 +27,7 @@ 
 #include "igt_sysfs.h"
 
 #include <sys/mman.h>
+#include <sys/poll.h>
 #include <sys/stat.h>
 #include <dirent.h>
 
@@ -144,6 +145,82 @@  static void test_dmabuf_mmap(int fd)
 	munmap(ptr, bo.size);
 }
 
+static bool prime_busy(int fd, bool excl)
+{
+	struct pollfd pfd = { .fd = fd, .events = excl ? POLLOUT : POLLIN };
+	return poll(&pfd, 1, 0) == 0;
+}
+
+static void test_dmabuf_fence(int fd)
+{
+	struct vgem_bo bo;
+	int dmabuf;
+	uint32_t fence;
+
+	bo.width = 1024;
+	bo.height = 1;
+	bo.bpp = 32;
+	vgem_create(fd, &bo);
+
+	/* export, then fence */
+
+	dmabuf = prime_handle_to_fd(fd, bo.handle);
+
+	fence = vgem_fence_attach(fd, &bo, false);
+	igt_assert(!prime_busy(dmabuf, false));
+	igt_assert(prime_busy(dmabuf, true));
+
+	vgem_fence_signal(fd, fence);
+	igt_assert(!prime_busy(dmabuf, false));
+	igt_assert(!prime_busy(dmabuf, true));
+
+	fence = vgem_fence_attach(fd, &bo, true);
+	igt_assert(prime_busy(dmabuf, false));
+	igt_assert(prime_busy(dmabuf, true));
+
+	vgem_fence_signal(fd, fence);
+	igt_assert(!prime_busy(dmabuf, false));
+	igt_assert(!prime_busy(dmabuf, true));
+
+	gem_close(fd, bo.handle);
+}
+
+static void test_dmabuf_fence_before(int fd)
+{
+	struct vgem_bo bo;
+	int dmabuf;
+	uint32_t fence;
+
+	bo.width = 1024;
+	bo.height = 1;
+	bo.bpp = 32;
+	vgem_create(fd, &bo);
+
+	fence = vgem_fence_attach(fd, &bo, false);
+	dmabuf = prime_handle_to_fd(fd, bo.handle);
+
+	igt_assert(!prime_busy(dmabuf, false));
+	igt_assert(prime_busy(dmabuf, true));
+
+	vgem_fence_signal(fd, fence);
+	igt_assert(!prime_busy(dmabuf, false));
+	igt_assert(!prime_busy(dmabuf, true));
+
+	gem_close(fd, bo.handle);
+	vgem_create(fd, &bo);
+
+	fence = vgem_fence_attach(fd, &bo, true);
+	dmabuf = prime_handle_to_fd(fd, bo.handle);
+	igt_assert(prime_busy(dmabuf, false));
+	igt_assert(prime_busy(dmabuf, true));
+
+	vgem_fence_signal(fd, fence);
+	igt_assert(!prime_busy(dmabuf, false));
+	igt_assert(!prime_busy(dmabuf, true));
+
+	gem_close(fd, bo.handle);
+}
+
 static void test_sysfs_read(int fd)
 {
 	int dir = igt_sysfs_open(fd, NULL);
@@ -229,11 +306,22 @@  igt_main
 			igt_require(has_prime_export(fd));
 		}
 
-		igt_subtest_f("dmabuf-export")
+		igt_subtest("dmabuf-export")
 			test_dmabuf_export(fd);
 
-		igt_subtest_f("dmabuf-mmap")
+		igt_subtest("dmabuf-mmap")
 			test_dmabuf_mmap(fd);
+
+		igt_subtest_group {
+			igt_fixture {
+				igt_require(vgem_has_fences(fd));
+			}
+
+			igt_subtest("dmabuf-fence")
+				test_dmabuf_fence(fd);
+			igt_subtest("dmabuf-fence-before")
+				test_dmabuf_fence_before(fd);
+		}
 	}
 
 	igt_subtest("sysfs")