@@ -59,14 +59,19 @@ i915_context_lookup_id(struct drm_device *dev,
return idr_find(&dev_priv->i915_ctx_idr, id);
}
-static void
-i915_context_del_id(struct drm_device *dev,
- struct drm_i915_gem_context *ctx)
+static void i915_context_del_id(struct drm_device *dev,
+ struct drm_i915_gem_context *ctx)
{
struct drm_i915_private *dev_priv = dev->dev_private;
idr_remove(&dev_priv->i915_ctx_idr, ctx->ctx_id);
}
+int i915_context_validate(struct drm_device *dev, struct drm_file *file,
+ uint32_t ctx_id,
+ struct drm_i915_context_flag *ctx_flag, int count)
+{
+ return 0;
+}
/**
* i915_context_alloc_backing_obj - Allocate and pin space in the global GTT for
* use by the HW to save, and restore context information.
@@ -1323,6 +1323,11 @@ extern void intel_display_print_error_state(struct seq_file *m,
extern void i915_context_init(struct drm_device *dev);
extern void i915_context_deinit(struct drm_device *dev);
extern void i915_context_close(struct drm_device *dev, struct drm_file *file);
+struct drm_i915_context_flag;
+extern int i915_context_validate(struct drm_device *dev,
+ struct drm_file *file, uint32_t ctx_id,
+ struct drm_i915_context_flag *ctx_flag,
+ int count);
#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
@@ -979,7 +979,9 @@ static int
i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file,
struct drm_i915_gem_execbuffer2 *args,
- struct drm_i915_gem_exec_object2 *exec)
+ struct drm_i915_gem_exec_object2 *exec,
+ struct drm_i915_context_flag *ctx_flags,
+ int flag_count)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct list_head objects;
@@ -999,7 +1001,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
ret = validate_exec_list(exec, args->buffer_count);
if (ret)
return ret;
-
+ if (ctx_flags) {
+ ret = i915_context_validate(dev, file, EXECBUFFER2_CTX_ID(args),
+ ctx_flags, flag_count);
+ if (ret) {
+ if (ret == -EAGAIN)
+ DRM_DEBUG_DRIVER("Context resubmission required\n");
+ return ret;
+ }
+ }
#if WATCH_EXEC
DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
(int) args->buffers_ptr, args->buffer_count, args->batch_len);
@@ -1299,7 +1309,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
exec2.cliprects_ptr = args->cliprects_ptr;
exec2.flags = I915_EXEC_RENDER;
- ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
+ ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list,
+ NULL, 0);
if (!ret) {
/* Copy the new buffer offsets back to the user's exec list. */
for (i = 0; i < args->buffer_count; i++)
@@ -1328,6 +1339,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
{
struct drm_i915_gem_execbuffer2 *args = data;
struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+ struct drm_i915_context_flag *flags = NULL;
+ uint32_t flag_count = 0;
int ret;
#if WATCH_EXEC
@@ -1356,8 +1369,32 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
drm_free_large(exec2_list);
return -EFAULT;
}
+ if (EXECBUFFER2_FLAGS_PTR(args) && EXECBUFFER2_FLAGS_COUNT(argc)) {
+ flag_count = EXECBUFFER2_FLAGS_COUNT(argc);
+ flags = drm_malloc_ab(sizeof(*flags), flag_count);
+ if (flags == NULL) {
+ DRM_ERROR("allocation of flags failed\n");
+ drm_free_large(exec2_list);
+ /* return -EAGAIN; */
+ return -ENOMEM;
+ }
- ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
+ ret = copy_from_user(flags,
+ (struct drm_context_flags __user *)
+ (uintptr_t)EXECBUFFER2_FLAGS_PTR(args),
+ sizeof(*flags) * flag_count);
+ if (ret != 0) {
+ DRM_ERROR("copy %d flags failed %d\n",
+ flag_count, ret);
+ drm_free_large(flags);
+ drm_free_large(exec2_list);
+ return -EFAULT;
+ }
+ ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list,
+ flags, flag_count);
+ } else
+ ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list,
+ NULL, 0);
if (!ret) {
/* Copy the new buffer offsets back to the user's exec list. */
ret = copy_to_user((struct drm_i915_relocation_entry __user *)
@@ -659,6 +659,21 @@ struct drm_i915_gem_execbuffer2 {
__u64 rsvd2;
};
+#define EXECBUFFER2_FLAGS_PTR(exec2) (exec2->rsvd1)
+#define EXECBUFFER2_FLAGS_COUNT(exec2) ((uint32_t)(args->rsvd2>>32))
+#define EXECBUFFER2_CTX_ID(exec2) ((uint32_t)args->rsvd2 )
+
+struct drm_i915_context_flag {
+ __u8 slot;
+ __u32 handle;
+ __u64 offset;
+ __u32 read_domain;
+ __u32 write_domain;
+#define I915_CTX_ASSOC_BUF (1 << 0)
+#define I915_CTX_DISASSOC_BUF (1 << 1)
+ __u32 command;
+};
+
struct drm_i915_gem_pin {
/** Handle of the buffer to be pinned. */
__u32 handle;