[PATCH i-g-t] i915: Add gem_cancel

Chris Wilson chris at chris-wilson.co.uk
Thu Dec 10 16:06:31 UTC 2020


Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 lib/igt_dummyload.c              |   5 +
 lib/igt_dummyload.h              |  17 +--
 tests/Makefile.sources           |   3 +
 tests/i915/gem_cancel.c          | 177 +++++++++++++++++++++++++++++++
 tests/i915/gem_ctx_persistence.c |   2 +-
 tests/meson.build                |   1 +
 6 files changed, 196 insertions(+), 9 deletions(-)
 create mode 100644 tests/i915/gem_cancel.c

diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
index 31cfb0697..28bbd3622 100644
--- a/lib/igt_dummyload.c
+++ b/lib/igt_dummyload.c
@@ -333,6 +333,11 @@ emit_recursive_batch(igt_spin_t *spin,
 		execbuf->rsvd2 = opts->fence;
 	}
 
+	if (opts->flags & IGT_SPIN_FENCE_SUBMIT) {
+		execbuf->flags |= I915_EXEC_FENCE_SUBMIT;
+		execbuf->rsvd2 = opts->fence;
+	}
+
 	for (i = 0; i < nengine; i++) {
 		execbuf->flags &= ~ENGINE_MASK;
 		execbuf->flags |= flags[i];
diff --git a/lib/igt_dummyload.h b/lib/igt_dummyload.h
index 232f3238e..c38f9efd8 100644
--- a/lib/igt_dummyload.h
+++ b/lib/igt_dummyload.h
@@ -65,14 +65,15 @@ struct igt_spin_factory {
 };
 
 #define IGT_SPIN_FENCE_IN      (1 << 0)
-#define IGT_SPIN_FENCE_OUT     (1 << 1)
-#define IGT_SPIN_POLL_RUN      (1 << 2)
-#define IGT_SPIN_WAKE_RUN      (1 << 3)
-#define IGT_SPIN_FAST          (1 << 4)
-#define IGT_SPIN_NO_PREEMPTION (1 << 5)
-#define IGT_SPIN_INVALID_CS    (1 << 6)
-#define IGT_SPIN_USERPTR       (1 << 7)
-#define IGT_SPIN_SOFTDEP       (1 << 8)
+#define IGT_SPIN_FENCE_SUBMIT  (1 << 1)
+#define IGT_SPIN_FENCE_OUT     (1 << 2)
+#define IGT_SPIN_POLL_RUN      (1 << 3)
+#define IGT_SPIN_WAKE_RUN      (1 << 4)
+#define IGT_SPIN_FAST          (1 << 5)
+#define IGT_SPIN_NO_PREEMPTION (1 << 6)
+#define IGT_SPIN_INVALID_CS    (1 << 7)
+#define IGT_SPIN_USERPTR       (1 << 8)
+#define IGT_SPIN_SOFTDEP       (1 << 9)
 
 igt_spin_t *
 __igt_spin_factory(int fd, const struct igt_spin_factory *opts);
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index b4a472623..8b23237ae 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -461,6 +461,9 @@ gem_unref_active_buffers_SOURCES = i915/gem_unref_active_buffers.c
 TESTS_progs += gem_userptr_blits
 gem_userptr_blits_SOURCES = i915/gem_userptr_blits.c
 
+TESTS_progs += gem_cancel
+gem_cancel_SOURCES = i915/gem_cancel.c
+
 TESTS_progs += gem_wait
 gem_wait_SOURCES = i915/gem_wait.c
 
diff --git a/tests/i915/gem_cancel.c b/tests/i915/gem_cancel.c
new file mode 100644
index 000000000..0060eb953
--- /dev/null
+++ b/tests/i915/gem_cancel.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <unistd.h>
+
+#include "drmtest.h"
+#include "i915/gem.h"
+#include "i915/gem_engine_topology.h"
+#include "igt_core.h"
+#include "igt_dummyload.h"
+#include "ioctl_wrappers.h"
+#include "sw_sync.h"
+
+#define DRM_I915_GEM_CANCEL             0x3c
+#define DRM_IOCTL_I915_GEM_CANCEL       DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CANCEL, struct drm_i915_gem_cancel)
+struct drm_i915_gem_cancel {
+        __u32 handle;
+        __u32 flags;
+#define CANCEL_SYNCOBJ (1 << 0)
+};
+
+static int __gem_cancel(int i915, uint32_t handle, uint32_t flags)
+{
+	struct drm_i915_gem_cancel arg = {
+		.handle = handle,
+		.flags = flags,
+	};
+	int err;
+
+	err = 0;
+	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_CANCEL, &arg)) {
+		err = -errno;
+		igt_assume(err);
+	}
+
+	errno = 0;
+	return err;
+}
+
+static void gem_cancel(int i915, uint32_t handle, uint32_t flags)
+{
+	igt_assert_eq(__gem_cancel(i915, handle, flags), 0);
+}
+
+static bool has_cancel(int i915)
+{
+	return __gem_cancel(i915, -1, 0) == -ENOENT;
+}
+
+static void test_active(int i915, unsigned int engine)
+{
+	igt_spin_t *spin;
+
+	spin = igt_spin_new(i915,
+			    .engine = engine,
+			    .flags = IGT_SPIN_POLL_RUN | IGT_SPIN_FENCE_OUT);
+	igt_spin_busywait_until_started(spin);
+
+	gem_cancel(i915, spin->out_fence, 0);
+	igt_assert_eq(sync_fence_wait(spin->out_fence, 50), 0);
+	igt_assert_eq(sync_fence_status(spin->out_fence), -EINTR);
+
+	igt_spin_free(i915, spin);
+}
+
+static void test_signaled(int i915, unsigned int engine)
+{
+	igt_spin_t *spin;
+
+	spin = igt_spin_new(i915,
+			    .engine = engine,
+			    .flags = IGT_SPIN_POLL_RUN | IGT_SPIN_FENCE_OUT);
+	igt_spin_busywait_until_started(spin);
+	igt_spin_end(spin);
+	igt_assert_eq(sync_fence_wait(spin->out_fence, 50), 0);
+
+	gem_cancel(i915, spin->out_fence, 0);
+	igt_assert_eq(sync_fence_status(spin->out_fence), 1);
+
+	igt_spin_free(i915, spin);
+}
+
+static void test_unready(int i915, unsigned int engine)
+{
+	igt_spin_t *spin[2];
+
+	spin[0] = igt_spin_new(i915,
+			       .engine = engine,
+			       .flags = IGT_SPIN_POLL_RUN);
+	igt_spin_busywait_until_started(spin[0]);
+
+	spin[1] = igt_spin_new(i915,
+			       .engine = engine,
+			       .flags = IGT_SPIN_FENCE_OUT);
+
+	gem_cancel(i915, spin[1]->out_fence, 0);
+	igt_spin_end(spin[0]);
+
+	igt_assert_eq(sync_fence_wait(spin[1]->out_fence, 50), 0);
+	igt_assert_eq(sync_fence_status(spin[1]->out_fence), -EINTR);
+
+	igt_spin_free(i915, spin[1]);
+	igt_spin_free(i915, spin[0]);
+}
+
+static void test_parallel(int i915)
+{
+	struct intel_execution_engine2 *e;
+	int first = -1;
+	int last = -1;
+
+	__for_each_physical_engine(i915, e) {
+		igt_spin_t *spin;
+
+		spin = igt_spin_new(i915,
+				    .engine = e->flags,
+				    .fence = last,
+				    .flags = (IGT_SPIN_POLL_RUN |
+					      IGT_SPIN_FENCE_OUT |
+					      (last != -1 ? IGT_SPIN_FENCE_SUBMIT : 0)));
+		igt_spin_busywait_until_started(spin);
+
+		last = spin->out_fence;
+		if (first == -1)
+			first = last;
+	}
+	igt_require(first != -1);
+
+	gem_cancel(i915, first, 0);
+	igt_assert_eq(sync_fence_wait(last, 50), 0);
+	igt_assert_eq(sync_fence_status(last), -EINTR);
+
+	gem_quiescent_gpu(i915);
+}
+
+igt_main
+{
+	struct intel_execution_engine2 *e;
+	int i915;
+
+	igt_fixture {
+		i915 = drm_open_driver(DRIVER_INTEL);
+		igt_require_gem(i915);
+
+		igt_require(has_cancel(i915));
+	}
+
+	igt_subtest_with_dynamic("active") {
+		__for_each_physical_engine(i915, e) {
+			igt_dynamic_f("%s", e->name)
+				test_active(i915, e->flags);
+		}
+	}
+
+	igt_subtest_with_dynamic("signaled") {
+		__for_each_physical_engine(i915, e) {
+			igt_dynamic_f("%s", e->name)
+				test_signaled(i915, e->flags);
+		}
+	}
+
+	igt_subtest_with_dynamic("unready") {
+		__for_each_physical_engine(i915, e) {
+			igt_dynamic_f("%s", e->name)
+				test_unready(i915, e->flags);
+		}
+	}
+
+	igt_subtest("parallel")
+		test_parallel(i915);
+
+	igt_fixture {
+		close(i915);
+	}
+}
diff --git a/tests/i915/gem_ctx_persistence.c b/tests/i915/gem_ctx_persistence.c
index 97b38e780..ebbf33308 100644
--- a/tests/i915/gem_ctx_persistence.c
+++ b/tests/i915/gem_ctx_persistence.c
@@ -783,7 +783,7 @@ static void test_userptr(int i915)
 	fence = recvfd(sv[1]);
 	close(sv[1]);
 
-	igt_assert_eq(wait_for_status(fence, reset_timeout_ms), -EIO);
+	igt_assert_eq(wait_for_status(i915, fence, reset_timeout_ms), -EIO);
 	close(fence);
 
 	/* We have to manually clean up the orphaned spinner */
diff --git a/tests/meson.build b/tests/meson.build
index 86dbae950..b77627e86 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -121,6 +121,7 @@ i915_progs = [
 	'gem_blits',
 	'gem_busy',
 	'gem_caching',
+	'gem_cancel',
 	'gem_close',
 	'gem_close_race',
 	'gem_concurrent_blit',
-- 
2.29.2



More information about the Intel-gfx-trybot mailing list