[PATCH 2/2] drm/i915/gem: Allow cancelling an individual fence

Chris Wilson chris at chris-wilson.co.uk
Tue Jan 12 14:05:13 UTC 2021


Primarily as a thought experiment, construct an ioctl that allows the
user to cancel the associated fence, causing immediate completion if
currently executing.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/Makefile              |  1 +
 drivers/gpu/drm/i915/gem/i915_gem_cancel.c | 57 ++++++++++++++++++++++
 drivers/gpu/drm/i915/gem/i915_gem_ioctls.h |  2 +
 drivers/gpu/drm/i915/i915_drv.c            |  1 +
 include/uapi/drm/i915_drm.h                |  8 +++
 5 files changed, 69 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_cancel.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 48f82c354611..ebf170664c29 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -132,6 +132,7 @@ i915-y += $(gt-y)
 # GEM (Graphics Execution Management) code
 gem-y += \
 	gem/i915_gem_busy.o \
+	gem/i915_gem_cancel.o \
 	gem/i915_gem_clflush.o \
 	gem/i915_gem_client_blt.o \
 	gem/i915_gem_context.o \
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_cancel.c b/drivers/gpu/drm/i915/gem/i915_gem_cancel.c
new file mode 100644
index 000000000000..c85dc22fb96d
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/i915_gem_cancel.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <linux/sync_file.h>
+
+#include <drm/drm_print.h>
+#include <drm/drm_syncobj.h>
+
+#include "i915_drv.h"
+#include "i915_gem_ioctls.h"
+
+int
+i915_gem_cancel_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+	struct drm_i915_gem_cancel *args = data;
+	struct dma_fence *fence;
+	int err;
+
+	/* Only supported if we can gracefully cancel a request */
+	if (!(to_i915(dev)->caps.scheduler & I915_SCHEDULER_CAP_PREEMPTION))
+		return -ENODEV;
+
+	if (args->flags & ~(I915_GEM_CANCEL_SYNCOBJ))
+		return -EINVAL;
+
+	if (args->flags & I915_GEM_CANCEL_SYNCOBJ) {
+		struct drm_syncobj *syncobj;
+
+		syncobj = drm_syncobj_find(file, args->handle);
+		if (!syncobj) {
+			DRM_DEBUG("Invalid syncobj handle:%d provided\n",
+				  args->handle);
+			return -ENOENT;
+		}
+
+		fence = drm_syncobj_fence_get(syncobj);
+		drm_syncobj_put(syncobj);
+	} else {
+		fence = sync_file_get_fence(args->handle);
+		if (!fence) {
+			DRM_DEBUG("Invalid fence fd:%d provided\n",
+				  args->handle);
+			return -ENOENT;
+		}
+	}
+
+	err = -EINVAL;
+	if (dma_fence_is_i915(fence)) {
+		i915_request_cancel(to_request(fence), -EINTR);
+		err = 0;
+	}
+
+	dma_fence_put(fence);
+	return err;
+}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ioctls.h b/drivers/gpu/drm/i915/gem/i915_gem_ioctls.h
index 87d8b27f426d..6487f9a652e6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ioctls.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ioctls.h
@@ -12,6 +12,8 @@ struct drm_file;
 
 int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file);
+int i915_gem_cancel_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file);
 int i915_gem_create_ioctl(struct drm_device *dev, void *data,
 			  struct drm_file *file);
 int i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f5666b44ea9d..61827c447568 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1756,6 +1756,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_VM_CREATE, i915_gem_vm_create_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_VM_DESTROY, i915_gem_vm_destroy_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(I915_GEM_CANCEL, i915_gem_cancel_ioctl, DRM_RENDER_ALLOW),
 };
 
 static const struct drm_driver driver = {
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 1987e2ea79a3..91f41dfe4af1 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -360,6 +360,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_QUERY			0x39
 #define DRM_I915_GEM_VM_CREATE		0x3a
 #define DRM_I915_GEM_VM_DESTROY		0x3b
+#define DRM_I915_GEM_CANCEL		0x3c
 /* Must be kept compact -- no holes */
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
@@ -423,6 +424,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_QUERY			DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
 #define DRM_IOCTL_I915_GEM_VM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
 #define DRM_IOCTL_I915_GEM_VM_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
+#define DRM_IOCTL_I915_GEM_CANCEL	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CANCEL, struct drm_i915_gem_cancel)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -1570,6 +1572,12 @@ struct drm_i915_gem_wait {
 	__s64 timeout_ns;
 };
 
+struct drm_i915_gem_cancel {
+	__u32 handle;
+	__u32 flags;
+#define I915_GEM_CANCEL_SYNCOBJ (1 << 0)
+};
+
 struct drm_i915_gem_context_create {
 	__u32 ctx_id; /* output: id of new context*/
 	__u32 pad;
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list