[Intel-gfx] [PATCH 06/11] drm/i915/context: ringbuffer context switch code
Ben Widawsky
ben at bwidawsk.net
Tue Feb 14 22:09:13 CET 2012
This is the HW dependent context switch code.
Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
drivers/gpu/drm/i915/i915_drv.h | 3 +
drivers/gpu/drm/i915/intel_ringbuffer.c | 117 +++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_ringbuffer.h | 6 ++-
3 files changed, 125 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 34e6f4f..4175929 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -965,6 +965,9 @@ struct drm_i915_gem_context {
bool is_initialized;
};
+#define I915_CONTEXT_NORMAL_SWITCH (1 << 0)
+#define I915_CONTEXT_SAVE_ONLY (1 << 1)
+#define I915_CONTEXT_FORCED_SWITCH (1 << 2)
#define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info)
#define IS_I830(dev) ((dev)->pci_device == 0x3577)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index e71e7fc..dcdc80e 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -942,6 +942,122 @@ 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 = ring->flush(ring, 0, 0);
+ if (ret)
+ return ret;
+
+ ret = intel_ring_begin(ring, 2);
+ if (ret)
+ return ret;
+
+ intel_ring_emit(ring, MI_NOOP | (1 << 22) | new_context->id);
+ intel_ring_emit(ring, MI_NOOP);
+ intel_ring_advance(ring);
+ }
+
+ if (IS_GEN6(dev) && new_context->is_initialized &&
+ ring->itlb_before_ctx_switch) {
+ /* w/a: If Flush TLB Invalidation Mode is enabled, driver must
+ * do a TLB invalidation prior to MI_SET_CONTEXT
+ */
+ gen6_render_ring_flush(ring, 0, 0);
+ }
+
+ ret = intel_ring_begin(ring, 6);
+ if (ret)
+ return ret;
+
+ intel_ring_emit(ring, MI_NOOP);
+
+ switch (INTEL_INFO(dev)->gen) {
+ case 5:
+ intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
+ break;
+ case 6:
+ intel_ring_emit(ring, MI_NOOP);
+ break;
+ case 7:
+ intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
+ break;
+ case 4:
+ default:
+ BUG();
+ }
+
+ DRM_DEBUG_DRIVER("Context switch %d-%d -> %d-%d\n",
+ (ring->last_context && ring->last_context->file) ?
+ ring->last_context->file->pid : 0,
+ ring->last_context ? ring->last_context->id : -1,
+ new_context->file ? new_context->file->pid : 0,
+ new_context->id);
+
+
+ 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);
+
+ /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */
+ intel_ring_emit(ring, MI_NOOP);
+
+ if (IS_GEN5(dev))
+ intel_ring_emit(ring, MI_SUSPEND_FLUSH);
+ else if (IS_GEN7(dev))
+ intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
+ 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 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;
+
+ /* last_context is only protected by struct_mutex */
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+ BUG_ON(new_context->obj == NULL || new_context->obj->gtt_offset == 0);
+
+ if (!force && (ring->last_context == new_context))
+ 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;
+
+ /* The first context switch with default context is special */
+ if (last == NULL && new_context->is_default)
+ return new_context;
+
+ return last;
+}
+
static void cleanup_status_page(struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = ring->dev->dev_private;
@@ -1232,6 +1348,7 @@ static const struct intel_ring_buffer render_ring = {
MI_SEMAPHORE_SYNC_RV,
MI_SEMAPHORE_SYNC_RB},
.signal_mbox = {GEN6_VRSYNC, GEN6_BRSYNC},
+ .context_switch = render_ring_context_switch,
};
/* ring buffer for bit-stream decoder */
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index fad4251..1988728 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -69,10 +69,14 @@ struct intel_ring_buffer {
int (*dispatch_execbuffer)(struct intel_ring_buffer *ring,
u32 offset, u32 length);
void (*cleanup)(struct intel_ring_buffer *ring);
+ struct drm_i915_gem_context *last_context;
+ struct drm_i915_gem_context *(*context_switch) (
+ struct intel_ring_buffer *ring,
+ struct drm_i915_gem_context *ctx,
+ u32 flags);
int (*sync_to)(struct intel_ring_buffer *ring,
struct intel_ring_buffer *to,
u32 seqno);
-
u32 semaphore_register[3]; /*our mbox written by others */
u32 signal_mbox[2]; /* mboxes this ring signals to */
/**
--
1.7.9
More information about the Intel-gfx
mailing list