[Intel-gfx] [RFC] [PATCH 8/8] drm/i915/context: create and destroy ioctls

Ben Widawsky bwidawsk at gmail.com
Sat Feb 26 19:30:18 CET 2011


The create and destroy ioctls are quite simple but depend on a lot of
other infrastructure, including:
	file open handling
	file close handling - cleanup stray contexts
	context_fini - possible switch back to default context
	get_context - object lookup is needed by destroy ioctl

There are two things lacking from the previous set of patches:
* no mention of gtt size in create ioctl
* no handling of the "slots"

gtt size and everything else related to ppgtt will be deferred as much as
possible. I think my dream of getting the API right, and not having a
long term topic branch is quickly becoming unattainable.

slots, I'm still undecided on whether or not to use slots to manage the
buffers associated with the context. It remains in the ioctl semantics
for now as I feel the API doesn't really suffer by having it there...
---
 drivers/gpu/drm/i915/i915_context.c |  110 +++++++++++++++++++++++++++++++++--
 1 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
index 3719a87..da4a0ff 100644
--- a/drivers/gpu/drm/i915/i915_context.c
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -33,6 +33,8 @@
 #define CONTEXT_SIZE dev_priv->context_size
 #define CONTEXT_ALIGN 4096
 
+static int context_idr_cleanup(int id, void *p, void *data);
+
 static int context_generate_id(struct drm_i915_gem_context *ctx)
 {
 	struct drm_i915_file_private *file_priv = ctx->file->driver_priv;
@@ -268,7 +270,50 @@ id_out:
 
 static void logical_context_fini(struct drm_i915_gem_context *ctx)
 {
+	struct drm_device *dev = ctx->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_context *last;
+	int i;
+	int ret = 0;
+
+	if (WARN_ON(!mutex_is_locked(&dev->struct_mutex)))
+		return;
+
+	if (ctx == dev_priv->default_context)
+		return;
+
+	for (i = 0; i < I915_NUM_RINGS; i++) {
+		struct intel_ring_buffer *ring = &dev_priv->ring[i];
+		if (!ring->context_switch)
+			continue;
+
+		if (!(ctx->ring_enable & (1 << i)))
+			continue;
+
+		if (ring->last_context != ctx)
+			continue;
 
+		/*
+		 * XXX We can prevent restoring contexts, but not saving them
+		 * so if we're going to take away our backing context object
+		 * of the last context, we have to switch now.
+		 */
+
+		DRM_DEBUG_DRIVER("Switching to default context\n");
+		last = ring->context_switch(ring, dev_priv->default_context,
+					    0, I915_CONTEXT_NORMAL_SWITCH);
+		if (!last) {
+			DRM_ERROR("Couldn't switch back to default context\n");
+			continue;
+		}
+
+		BUG_ON(last != ctx);
+		ret = wait_for_context_switch(ring);
+		if (ret)
+			DRM_ERROR("Wait for default context switch failed "
+				  "ring = %d (%d)", i, ret);
+		i915_release_context(last);
+	}
 }
 
 static int logical_context_free(struct drm_file *file, uint32_t id)
@@ -304,24 +349,40 @@ static int logical_context_free(struct drm_file *file, uint32_t id)
 }
 
 /**
- * i915_context_create_ioctl() - not yet supported
+ * i915_context_create_ioctl()
  */
 int i915_context_create_ioctl(struct drm_device *dev, void *data,
 			      struct drm_file *file)
 {
 	struct drm_i915_gem_context_create *args = data;
-	args->ctx_id = 0;
-	return -EIO;
+	struct drm_i915_gem_context *out_ctx = NULL;
+	int ret = 0;
+
+	mutex_lock(&dev->struct_mutex);
+	ret = logical_context_alloc(dev, file, args->ring_mask, &out_ctx);
+	mutex_unlock(&dev->struct_mutex);
+	if (ret == 0) {
+		args->ctx_id = out_ctx->id;
+		if (WARN_ON(args->ctx_id == DEFAULT_CONTEXT_ID))
+			return -ENXIO;
+		args->ring_enable = out_ctx->ring_enable;
+	}
+
+	return ret;
 }
 
 /**
- * i915_context_destroy_ioctl() - not yet supported
+ * i915_context_destroy_ioctl()
  */
 int i915_context_destroy_ioctl(struct drm_device *dev, void *data,
 			       struct drm_file *file)
 {
 	struct drm_i915_gem_context_destroy *args = data;
-	return -EINVAL;
+
+	if (args->ctx_id == DEFAULT_CONTEXT_ID)
+		return -EINVAL;
+
+	return logical_context_free(file, args->ctx_id);
 }
 
 /**
@@ -370,18 +431,55 @@ void i915_context_unload(struct drm_device *dev)
 
 void i915_context_open(struct drm_device *dev, struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_file_private *file_priv = file->driver_priv;
+
+	if (dev_priv->contexts_disabled)
+		return;
 
+	idr_init(&file_priv->context_idr);
+	spin_lock_init(&file_priv->context_idr_lock);
 }
 
 void i915_context_close(struct drm_device *dev, struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_file_private *file_priv = file->driver_priv;
+
+	if (dev_priv->contexts_disabled)
+		return;
 
+	idr_for_each(&file_priv->context_idr, context_idr_cleanup, file);
+	idr_destroy(&file_priv->context_idr);
+}
+
+static int context_idr_cleanup(int id, void *p, void *data)
+{
+	struct drm_file *file = (struct drm_file *) data;
+	logical_context_free(file, id);
+	return 0;
 }
 
 struct drm_i915_gem_context *i915_get_context(struct drm_file *file,
 					      uint32_t id)
 {
-	return NULL;
+	struct drm_i915_file_private *file_priv = file->driver_priv;
+	struct drm_i915_gem_context *ctx = NULL;
+	int ret;
+
+	spin_lock(&file_priv->context_idr_lock);
+	ctx = idr_find(&file_priv->context_idr, id);
+	if (ctx) {
+		drm_gem_object_reference(&ctx->obj->base);
+		ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false);
+		if (ret) {
+			drm_gem_object_unreference(&ctx->obj->base);
+			ctx = NULL;
+		}
+	}
+	spin_unlock(&file_priv->context_idr_lock);
+
+	return ctx;
 }
 
 void i915_release_context(struct drm_i915_gem_context *ctx)
-- 
1.7.3.4




More information about the Intel-gfx mailing list