All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Widawsky <bwidawsk@gmail.com>
To: intel-gfx@lists.freedesktop.org
Subject: [RFC] [PATCH 7/8] drm/i915/context: context switch implementation
Date: Sat, 26 Feb 2011 10:30:17 -0800	[thread overview]
Message-ID: <1298745018-5937-8-git-send-email-bwidawsk@gmail.com> (raw)
In-Reply-To: <1298745018-5937-1-git-send-email-bwidawsk@gmail.com>

Once again, split out mostly for review...

Implementation of the context switch code (MI_SET_CONTEXT), which is
supposed to be per ringbuffer. There is a bit of ugliness for the
initial default context load, for which I had no better solution.

Slightly modified the default context creation code to check for the
previously mentioned ugliness.
---
 drivers/gpu/drm/i915/i915_context.c     |   28 ++++++---
 drivers/gpu/drm/i915/i915_drv.h         |    1 +
 drivers/gpu/drm/i915/intel_ringbuffer.c |   97 +++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c
index 2e38fa8..3719a87 100644
--- a/drivers/gpu/drm/i915/i915_context.c
+++ b/drivers/gpu/drm/i915/i915_context.c
@@ -123,28 +123,34 @@ static int context_init(struct drm_i915_gem_context *ctx,
 		 */
 		last = ring->context_switch(ring, ctx, 0,
 					    I915_CONTEXT_SAVE_ONLY);
-		if (!last) {
-			ret = EIO;
+		if (last != ctx) {
+			DRM_ERROR("Context switch state invalid");
+			ret = -EIO;
 			goto err_out;
 		}
 		last = ring->context_switch(ring, ctx, 0,
 					    I915_CONTEXT_SAVE_ONLY |
 					    I915_CONTEXT_FORCED_SWITCH);
-		if (!last) {
-			ret = EIO;
+		if (last != ctx) {
+			DRM_ERROR("First context switch fail");
+			ret = -EIO;
 			goto err_out;
 		}
 		last = ring->context_switch(ring, ctx, 0,
 					    I915_CONTEXT_NORMAL_SWITCH |
 					    I915_CONTEXT_FORCED_SWITCH);
+		if (last != ctx) {
+			DRM_ERROR("Final context switch fail");
+			ret = -EIO;
+			goto err_out;
+		}
 	} else {
 		last = ring->context_switch(ring, ctx, 0,
 					    I915_CONTEXT_SAVE_ONLY);
-	}
-
-	if (!last) {
-		ret = EIO;
-		goto err_out;
+		if (!last) {
+			ret = -EIO;
+			goto err_out;
+		}
 	}
 
 	if (!last->is_default)
@@ -346,7 +352,11 @@ void i915_context_load(struct drm_device *dev)
 	ret = logical_context_alloc(dev, NULL, 0, &dev_priv->default_context);
 	if (ret)
 		dev_priv->contexts_disabled = true;
+	else {
+		DRM_DEBUG_DRIVER("HW context support initialized\n");
+	}
 	mutex_unlock(&dev->struct_mutex);
+
 }
 
 void i915_context_unload(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 98ccbd9..39669ff 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -909,6 +909,7 @@ struct drm_i915_gem_context {
 	uint8_t ring_enable;
 	struct drm_i915_gem_object *obj;
 	bool is_default;
+	bool is_initialized;
 
 	struct drm_gem_object **bufs;
 	int slot_count;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 789c478..7d18c07 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -734,6 +734,102 @@ render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
 	return 0;
 }
 
+static int do_ring_switch(struct intel_ring_buffer *ring,
+			  struct drm_i915_gem_context *new_context,
+			  u32 hw_flags)
+{
+	struct drm_device *dev = ring->dev;
+	int ret = 0;
+
+	if (!new_context->is_initialized) {
+		ret = intel_ring_begin(ring, 6);
+		if (ret)
+			return ret;
+		intel_ring_emit(ring, MI_NOOP | (1 << 22) | new_context->id);
+		intel_ring_emit(ring, MI_FLUSH);
+	} else {
+		ret = intel_ring_begin(ring, 4);
+		if (ret)
+			return ret;
+	}
+
+	DRM_DEBUG_DRIVER("Context switch %d -> %d\n",
+			 ring->last_context ? ring->last_context->id : -1,
+			 new_context->id);
+
+	if (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev))
+		intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
+	else
+		intel_ring_emit(ring, MI_NOOP);
+
+	intel_ring_emit(ring, MI_SET_CONTEXT);
+	intel_ring_emit(ring, new_context->obj->gtt_offset |
+			MI_MM_SPACE_GTT |
+			MI_SAVE_EXT_STATE_EN |
+			MI_RESTORE_EXT_STATE_EN |
+			hw_flags);
+
+	if (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev))
+		intel_ring_emit(ring, MI_SUSPEND_FLUSH);
+		/* TODO: we may need a NOOP here */
+	else
+		intel_ring_emit(ring, MI_NOOP);
+
+	intel_ring_advance(ring);
+
+	return ret;
+
+}
+
+static struct drm_i915_gem_context *
+render_ring_context_switch(struct intel_ring_buffer *ring,
+			   struct drm_i915_gem_context *new_context,
+			   u32 seqno, u32 flags)
+{
+	struct drm_device *dev = ring->dev;
+	bool force = (flags & I915_CONTEXT_FORCED_SWITCH) ? true : false;
+	struct drm_i915_gem_context *last = NULL;
+	uint32_t hw_flags = 0;
+
+	if (WARN_ON(new_context->obj->gtt_offset == 0))
+		return NULL;
+
+	/* last_context is only protected by struct_mutex */
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	if (!force && (ring->last_context == new_context))  {
+		if (WARN_ON(seqno == 0))
+			seqno = ring->get_seqno(ring);
+
+		if (!new_context->is_default)
+			i915_gem_object_move_to_active(new_context->obj,
+						       ring, seqno);
+		return new_context;
+	}
+
+	if (flags & I915_CONTEXT_SAVE_ONLY)
+		hw_flags = MI_RESTORE_INHIBIT;
+
+	if (do_ring_switch(ring, new_context, hw_flags))
+		return NULL;
+
+	last = ring->last_context;
+	ring->last_context = new_context;
+
+	if (last && !last->is_default)
+		i915_gem_object_move_to_active(last->obj, ring, seqno);
+
+	/* XXX The first call to this default and last are NULL. Unfortunately
+	 * the only mechanism we have to determine failure is */
+	if (!new_context->is_initialized && !last) {
+		WARN_ON(!new_context->is_default);
+		last = new_context;
+	} else
+		new_context->is_initialized = true;
+
+	return last;
+}
+
 static void cleanup_status_page(struct intel_ring_buffer *ring)
 {
 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
@@ -1008,6 +1104,7 @@ static const struct intel_ring_buffer render_ring = {
 	.irq_put		= render_ring_put_irq,
 	.dispatch_execbuffer	= render_ring_dispatch_execbuffer,
        .cleanup			= render_ring_cleanup,
+	.context_switch		= render_ring_context_switch,
 };
 
 /* ring buffer for bit-stream decoder */
-- 
1.7.3.4

  parent reply	other threads:[~2011-02-26 18:30 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-26 18:30 [RFC] [PATCH 0/8] drm/i915/context Ben Widawsky
2011-02-26 18:30 ` [RFC] [PATCH 1/8] drm/i915/context: CXT_SIZE register offset added Ben Widawsky
2011-02-26 18:30 ` [RFC] [PATCH 2/8] drm/i915/context: Preliminary context support Ben Widawsky
2011-02-26 18:30 ` [RFC] [PATCH 3/8] drm/i915/context: implement load and unload Ben Widawsky
2011-02-26 18:30 ` [RFC] [PATCH 4/8] drm/i915/context: logical context free Ben Widawsky
2011-02-26 18:30 ` [RFC] [PATCH 5/8] drm/i915/context: implement context switch wait Ben Widawsky
2011-02-26 18:30 ` [RFC] [PATCH 6/8] drm/i915/context: context init implementation Ben Widawsky
2011-02-26 18:30 ` Ben Widawsky [this message]
2011-02-26 18:30 ` [RFC] [PATCH 8/8] drm/i915/context: create and destroy ioctls Ben Widawsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1298745018-5937-8-git-send-email-bwidawsk@gmail.com \
    --to=bwidawsk@gmail.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.