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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to