[Intel-gfx] [RFC v4 1/2] drm/i915: Engine discovery uAPI
Tvrtko Ursulin
tursulin at ursulin.net
Mon Jun 26 15:47:41 UTC 2017
From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Engine discovery uAPI allows userspace to probe for engine
configuration and features without needing to maintain the
internal PCI id based database.
This enables removal of code duplications across userspace
components.
Probing is done via the new DRM_IOCTL_I915_GEM_ENGINE_INFO ioctl
which returns the number and information on the specified engine
class.
Currently only general engine configuration and HEVC feature of
the VCS engine can be probed but the uAPI is designed to be
generic and extensible.
Code is based almost exactly on the earlier proposal on the
topic by Jon Bloomfield. Engine class and instance refactoring
made recently by Daniele Ceraolo Spurio enabled this to be
implemented in an elegant fashion.
To probe configuration userspace sets the engine class it wants
to query (struct drm_i915_gem_engine_info) and provides an array
of drm_i915_engine_info structs which will be filled in by the
driver. Userspace also has to tell i915 how many elements are in
the array, and the driver will report back the total number of
engine instances in any case.
v2:
* Add a version field and consolidate to one engine count.
(Chris Wilson)
* Rename uAPI flags for VCS engines to DRM_I915_ENGINE_CLASS_VIDEO.
(Gong Zhipeng)
v3:
* Drop the DRM_ prefix from uAPI enums. (Chris Wilson)
* Only reserve 8-bits for the engine info for time being.
v4:
* Made user_class_map static.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Cc: Ben Widawsky <ben at bwidawsk.net>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter at intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
Cc: Jon Bloomfield <jon.bloomfield at intel.com>
Cc: "Rogozhkin, Dmitry V" <dmitry.v.rogozhkin at intel.com>
Cc: Oscar Mateo <oscar.mateo at intel.com>
Cc: "Gong, Zhipeng" <zhipeng.gong at intel.com>
---
drivers/gpu/drm/i915/i915_drv.c | 1 +
drivers/gpu/drm/i915/i915_drv.h | 3 ++
drivers/gpu/drm/i915/intel_engine_cs.c | 64 ++++++++++++++++++++++++++++++++++
include/uapi/drm/i915_drm.h | 41 ++++++++++++++++++++++
4 files changed, 109 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e9d8e9ee51b2..44dd2f37937f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -2724,6 +2724,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_ENGINE_INFO, i915_gem_engine_info_ioctl, DRM_RENDER_ALLOW),
};
static struct drm_driver driver = {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 427d10c7eca5..496565e1753f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3598,6 +3598,9 @@ void i915_oa_init_reg_state(struct intel_engine_cs *engine,
struct i915_gem_context *ctx,
uint32_t *reg_state);
+int i915_gem_engine_info_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file);
+
/* i915_gem_evict.c */
int __must_check i915_gem_evict_something(struct i915_address_space *vm,
u64 min_size, u64 alignment,
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 3b46c1f7b88b..a98669f6ad85 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -25,6 +25,7 @@
#include "i915_drv.h"
#include "intel_ringbuffer.h"
#include "intel_lrc.h"
+#include <uapi/drm/i915_drm.h>
/* Haswell does have the CXT_SIZE register however it does not appear to be
* valid. Now, docs explain in dwords what is in the context object. The full
@@ -1332,6 +1333,69 @@ void intel_engines_mark_idle(struct drm_i915_private *i915)
}
}
+static u8 user_class_map[I915_ENGINE_CLASS_MAX] = {
+ [I915_ENGINE_CLASS_OTHER] = OTHER_CLASS,
+ [I915_ENGINE_CLASS_RENDER] = RENDER_CLASS,
+ [I915_ENGINE_CLASS_COPY] = COPY_ENGINE_CLASS,
+ [I915_ENGINE_CLASS_VIDEO] = VIDEO_DECODE_CLASS,
+ [I915_ENGINE_CLASS_VIDEO_ENHANCE] = VIDEO_ENHANCEMENT_CLASS,
+};
+
+int i915_gem_engine_info_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_private *i915 = to_i915(dev);
+ struct drm_i915_gem_engine_info *args = data;
+ struct drm_i915_engine_info __user *user_info =
+ u64_to_user_ptr(args->info_ptr);
+ unsigned int info_size = args->num_engines;
+ struct drm_i915_engine_info info;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+ u8 class;
+
+ if (args->rsvd)
+ return -EINVAL;
+
+ switch (args->engine_class) {
+ case I915_ENGINE_CLASS_OTHER:
+ case I915_ENGINE_CLASS_RENDER:
+ case I915_ENGINE_CLASS_COPY:
+ case I915_ENGINE_CLASS_VIDEO:
+ case I915_ENGINE_CLASS_VIDEO_ENHANCE:
+ class = user_class_map[args->engine_class];
+ break;
+ case I915_ENGINE_CLASS_MAX:
+ default:
+ return -EINVAL;
+ };
+
+ args->num_engines = 0;
+
+ if (args->version != 1) {
+ args->version = 1;
+ return 0;
+ }
+
+ for_each_engine(engine, i915, id) {
+ if (class != engine->class)
+ continue;
+
+ if (++args->num_engines > info_size)
+ continue;
+
+ memset(&info, 0, sizeof(info));
+ info.instance = engine->instance;
+ if (INTEL_GEN(i915) >= 8 && id == VCS)
+ info.info = I915_VCS_HAS_HEVC;
+
+ if (copy_to_user(user_info++, &info, sizeof(info)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_engine.c"
#endif
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 7ccbd6a2bbe0..fbb1f6b99959 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -260,6 +260,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
#define DRM_I915_PERF_OPEN 0x36
+#define DRM_I915_GEM_ENGINE_INFO 0x37
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -315,6 +316,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
+#define DRM_IOCTL_I915_GEM_ENGINE_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_ENGINE_INFO, struct drm_i915_gem_engine_info)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -1467,6 +1469,45 @@ enum drm_i915_perf_record_type {
DRM_I915_PERF_RECORD_MAX /* non-ABI */
};
+enum drm_i915_gem_engine_class {
+ I915_ENGINE_CLASS_OTHER = 0,
+ I915_ENGINE_CLASS_RENDER = 1,
+ I915_ENGINE_CLASS_COPY = 2,
+ I915_ENGINE_CLASS_VIDEO = 3,
+ I915_ENGINE_CLASS_VIDEO_ENHANCE = 4,
+ I915_ENGINE_CLASS_MAX /* non-ABI */
+};
+
+struct drm_i915_engine_info {
+ /** Engine instance number. */
+ __u8 instance;
+
+ /** Engine specific info. */
+#define I915_VCS_HAS_HEVC BIT(0)
+ __u8 info;
+
+ __u8 rsvd2[6];
+};
+
+struct drm_i915_gem_engine_info {
+ /** in/out: Protocol version requested/supported. */
+ __u32 version;
+
+ /** in: Engine class to probe (enum drm_i915_gem_engine_class). */
+ __u32 engine_class;
+
+ /**
+ * in/out: Number of struct drm_i915_engine_info entries in the provided
+ * @info_ptr array and actual number of supported hardware engines.
+ */
+ __u32 num_engines;
+ __u32 rsvd;
+
+ /** in/out: Pointer to array of struct i915_engine_info elements. */
+ __u64 info_ptr;
+
+};
+
#if defined(__cplusplus)
}
#endif
--
2.9.4
More information about the Intel-gfx
mailing list