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@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx