Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- 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 --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") -- 2.8.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx