@@ -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;
+}
@@ -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,
@@ -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)
{
@@ -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.
@@ -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;
@@ -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_ */