[PATCH] drm/i915/gem: Allow cancelling an individual fence
Chris Wilson
chris at chris-wilson.co.uk
Thu Dec 10 13:35:01 UTC 2020
Primarily as a thought experiment, construct an ioctl that allow 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 | 87 ++++++++++++++++++++++
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, 99 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 f9ef5199b124..86ff6142d2fe 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -129,6 +129,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..6c8d5e09a636
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/i915_gem_cancel.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <linux/sync_file.h>
+
+#include <drm/drm_print.h>
+#include <drm/drm_syncobj.h>
+
+#include "gt/intel_engine.h"
+#include "gt/intel_engine_heartbeat.h"
+#include "gt/intel_reset.h"
+
+#include "i915_gem_ioctls.h"
+
+static struct intel_engine_cs *active_engine(struct i915_request *rq)
+{
+ struct intel_engine_cs *engine, *locked;
+
+ locked = READ_ONCE(rq->engine);
+ spin_lock_irq(&locked->active.lock);
+ while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) {
+ spin_unlock(&locked->active.lock);
+ locked = engine;
+ spin_lock(&locked->active.lock);
+ }
+
+ engine = NULL;
+ if (i915_request_is_active(rq) && !i915_request_completed(rq))
+ engine = locked;
+
+ spin_unlock_irq(&locked->active.lock);
+
+ return engine;
+}
+
+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;
+
+ if (args->flags & ~(CANCEL_SYNCOBJ))
+ return -EINVAL;
+
+ if (args->flags & 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)) {
+ struct i915_request *rq = to_request(fence);
+ struct intel_engine_cs *engine;
+
+ i915_request_set_error_once(rq, -EINTR);
+
+ engine = active_engine(rq);
+ if (engine && intel_engine_pulse(engine))
+ intel_gt_handle_error(engine->gt, engine->mask, 0,
+ "request cancellation by %s",
+ current->comm);
+
+ 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 5708e11d917b..de80fbf47b73 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1758,6 +1758,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 6edcb2b6c708..e3369b4942e0 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -359,6 +359,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)
@@ -422,6 +423,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.
@@ -1569,6 +1571,12 @@ struct drm_i915_gem_wait {
__s64 timeout_ns;
};
+struct drm_i915_gem_cancel {
+ __u32 handle;
+ __u32 flags;
+#define 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