[Intel-gfx] [PATCH 9/9] drm/i915: add bufferless execbuf ioctl
Jesse Barnes
jbarnes at virtuousgeek.org
Fri Sep 4 09:59:03 PDT 2015
We just need to pass in an address to execute and some flags, since we
don't have to worry about buffer relocation or any of the other usual
stuff. Returns a fence to be used for synchronization.
---
drivers/gpu/drm/i915/i915_dma.c | 140 ++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/i915_drv.h | 7 ++
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +-
drivers/gpu/drm/i915/i915_svm.c | 10 ---
drivers/gpu/drm/i915/i915_sync.c | 4 +-
include/uapi/drm/i915_drm.h | 24 +++++
6 files changed, 173 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index b868084..19b463a 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -50,7 +50,8 @@
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/oom.h>
-
+#include <linux/dma-buf.h>
+#include "../../../staging/android/sync.h"
static int i915_getparam(struct drm_device *dev, void *data,
struct drm_file *file_priv)
@@ -1247,6 +1248,132 @@ i915_gem_reject_pin_ioctl(struct drm_device *dev, void *data,
return -ENODEV;
}
+int intel_exec_mm_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_exec_mm *exec_mm = data;
+ struct intel_ringbuffer *ringbuf;
+ struct intel_engine_cs *ring;
+ struct intel_context *ctx;
+ struct drm_i915_gem_request *request;
+ struct fence *fence;
+ struct sync_fence *sfence;
+ u32 ctx_id = exec_mm->ctx_id;
+ int fd = get_unused_fd_flags(O_CLOEXEC);
+ int ret = 0;
+
+ if (exec_mm->batch_ptr & 3) {
+ DRM_ERROR("misaligned batch ptr\n");
+ ret = -ENOEXEC;
+ goto out;
+ }
+
+ if (!dev_priv->svm.svm_available) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ret = i915_mutex_lock_interruptible(dev);
+ if (ret) {
+ DRM_ERROR("mutex interrupted\n");
+ goto out;
+ }
+
+ if (file == NULL) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ctx = i915_gem_validate_context(dev, file, &dev_priv->ring[RCS],
+ ctx_id);
+ if (ctx == NULL) {
+ ret = -ENOENT;
+ DRM_ERROR("couldn't get context\n");
+ goto out_unlock;
+ }
+
+ if (!ctx->is_svm) {
+ ret = -EINVAL;
+ DRM_ERROR("context is not SVM enabled\n");
+ goto out_unlock;
+ }
+
+ i915_gem_context_reference(ctx);
+
+ ringbuf = ctx->engine[RCS].ringbuf;
+ ring = ringbuf->ring;
+ if (!ring) {
+ DRM_ERROR("context has no last ring\n");
+ ret = -EIO;
+ goto out_unref;
+ }
+
+ if (!ctx->rcs_initialized) {
+ DRM_DEBUG("ring not ready\n");
+ ret = -EIO;
+ goto out_unref;
+ }
+
+ ret = i915_gem_request_alloc(ring, ctx, &request);
+ if (ret) {
+ DRM_ERROR("request alloc failed\n");
+ goto out_unref;
+ }
+
+ ret = i915_gem_request_add_to_client(request, file);
+ if (ret) {
+ DRM_ERROR("failed to add request to client\n");
+ goto out_free_req;
+ }
+
+ fence = i915_fence_create_ring(ring, ctx);
+ if (!fence) {
+ ret = -ENOMEM;
+ DRM_ERROR("fence creation failed\n");
+ goto out_free_req;
+ }
+
+ sfence = sync_fence_create_dma("svm-execbuf", fence);
+ if (!sfence) {
+ ret = -ENOMEM;
+ DRM_ERROR("sfence creation failed\n");
+ goto out_free_req;
+ }
+
+ exec_mm->fence = fd;
+ sync_fence_install(sfence, fd);
+
+ ret = ring->emit_flush(request, 0, I915_GEM_GPU_DOMAINS);
+ if (ret) {
+ DRM_ERROR("ring flush failed: %d\n", ret);
+ goto out_free_req;
+ }
+
+ ret = ring->emit_bb_start(request, exec_mm->batch_ptr, 0);
+ if (ret) {
+ DRM_ERROR("ring dispatch execbuf failed: %d\n", ret);
+ goto out_free_req;
+ }
+
+ i915_gem_context_unreference(ctx);
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+
+out_free_req:
+ i915_gem_request_cancel(request);
+
+out_unref:
+ i915_gem_context_unreference(ctx);
+out_unlock:
+ mutex_unlock(&dev->struct_mutex);
+ put_unused_fd(fd);
+
+out:
+ return ret;
+}
+
const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_FLUSH, drm_noop, DRM_AUTH),
@@ -1301,6 +1428,17 @@ const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE2, i915_gem_context_create2_ioctl, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(I915_EXEC_MM, intel_exec_mm_ioctl, DRM_UNLOCKED),
};
int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
+
+/*
+ * This is really ugly: Because old userspace abused the linux agp interface to
+ * manage the gtt, we need to claim that all intel devices are agp. For
+ * otherwise the drm core refuses to initialize the agp support code.
+ */
+int i915_driver_device_is_agp(struct drm_device *dev)
+{
+ return 1;
+}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0c3047b..d89955c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2860,6 +2860,8 @@ void i915_gem_vma_destroy(struct i915_vma *vma);
#ifdef CONFIG_DRM_I915_SYNC
int i915_sync_init(struct drm_i915_private *dev_priv);
void i915_sync_fini(struct drm_i915_private *dev_priv);
+struct fence *i915_fence_create_ring(struct intel_engine_cs *ring,
+ struct intel_context *ctx);
int i915_sync_create_fence_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
#else
@@ -3178,6 +3180,9 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
void i915_gem_context_free(struct kref *ctx_ref);
struct drm_i915_gem_object *
i915_gem_alloc_context_obj(struct drm_device *dev, size_t size);
+struct intel_context *
+i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
+ struct intel_engine_cs *ring, const u32 ctx_id);
static inline void i915_gem_context_reference(struct intel_context *ctx)
{
kref_get(&ctx->ref);
@@ -3402,6 +3407,8 @@ int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
extern struct intel_mm_struct *intel_bind_mm(struct drm_device *dev,
struct intel_context *ctx);
extern void intel_unbind_mm(struct intel_context *ctx);
+extern int intel_exec_mm_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file);
extern int intel_alloc_pasid(struct drm_device *dev,
struct intel_context *ctx);
extern void intel_free_pasid(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a953d49..b1f8819 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -988,7 +988,7 @@ validate_exec_list(struct drm_device *dev,
return 0;
}
-static struct intel_context *
+struct intel_context *
i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
struct intel_engine_cs *ring, const u32 ctx_id)
{
diff --git a/drivers/gpu/drm/i915/i915_svm.c b/drivers/gpu/drm/i915/i915_svm.c
index 1d05318..fdb45d6 100644
--- a/drivers/gpu/drm/i915/i915_svm.c
+++ b/drivers/gpu/drm/i915/i915_svm.c
@@ -757,16 +757,6 @@ void intel_unbind_mm(struct intel_context *ctx)
return;
}
-int intel_exec_mm_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
-// struct drm_i915_exec_mm *exec_mm = data;
-// struct drm_i915_private *dev_priv = dev->dev_private;
-
- /* Load new context into context reg */
- return 0;
-}
-
/*
* The PASID table has 32 entries in the current config, rotate through
* them as needed.
diff --git a/drivers/gpu/drm/i915/i915_sync.c b/drivers/gpu/drm/i915/i915_sync.c
index 46cea44..085f1f9 100644
--- a/drivers/gpu/drm/i915/i915_sync.c
+++ b/drivers/gpu/drm/i915/i915_sync.c
@@ -187,8 +187,8 @@ static struct fence_ops i915_fence_ring_ops = {
.timeline_value_str = i915_fence_ring_timeline_value_str,
};
-static struct fence *i915_fence_create_ring(struct intel_engine_cs *ring,
- struct intel_context *ctx)
+struct fence *i915_fence_create_ring(struct intel_engine_cs *ring,
+ struct intel_context *ctx)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
struct drm_i915_gem_request *request;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index bac2fb2..9683e8c 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -231,6 +231,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
#define DRM_I915_GEM_CONTEXT_CREATE2 0x36
+#define DRM_I915_EXEC_MM 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)
@@ -285,6 +286,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_GEM_CONTEXT_CREATE2 DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE2, struct drm_i915_gem_context_create2)
+#define DRM_IOCTL_I915_EXEC_MM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_EXEC_MM, struct drm_i915_exec_mm)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -1147,4 +1149,26 @@ struct drm_i915_gem_context_param {
__u64 value;
};
+/**
+ * drm_i915_exec_mm - shared address space execbuf
+ * @batch_ptr: address of batch buffer (in context's CPU address space)
+ * @ctx_id: context to use for execution
+ * @flags: see flags
+ * @fence: returned fence handle
+ * @pad: unused
+ *
+ * This simlified execbuf just executes an MI_BATCH_BUFFER_START at
+ * @batch_ptr using @ctx_id as the context. The context will indicate
+ * which address space the @batch_ptr will use.
+ *
+ * Note @batch_ptr must be dword aligned.
+ */
+struct drm_i915_exec_mm {
+ __u64 batch_ptr;
+ __u32 ctx_id;
+ __u32 flags;
+ __u32 fence;
+ __u32 pad;
+};
+
#endif /* _UAPI_I915_DRM_H_ */
--
1.9.1
More information about the Intel-gfx
mailing list