aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Widawsky <ben@bwidawsk.net>2012-06-04 17:42:50 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-06-14 11:36:19 -0400
commit12b0286f49947a6cdc9285032d918466a8c3f5f9 (patch)
tree7fa02ef380f2260b2c5eae769b6ac8c40e7d92b2 /drivers/gpu/drm
parentcc0f6398225ffd2b890ff83eafe212b1ae863cad (diff)
drm/i915: possibly invalidate TLB before context switch
From http://intellinuxgraphics.org/documentation/SNB/IHD_OS_Vol1_Part3.pdf [DevSNB] If Flush TLB invalidation Mode is enabled it's the driver's responsibility to invalidate the TLBs at least once after the previous context switch after any GTT mappings changed (including new GTT entries). This can be done by a pipelined PIPE_CONTROL with TLB inv bit set immediately before MI_SET_CONTEXT. On GEN7 the invalidation mode is explicitly set, but this appears to be lacking for GEN6. Since I don't know the history on this, I've decided to dynamically read the value at ring init time, and use that value throughout. v2: better comment (daniel) Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c11
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c7
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h4
3 files changed, 22 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index d49d5fc0a592..fb1e1d22572c 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -324,6 +324,17 @@ mi_set_context(struct intel_ring_buffer *ring,
324{ 324{
325 int ret; 325 int ret;
326 326
327 /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB
328 * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value
329 * explicitly, so we rely on the value at ring init, stored in
330 * itlb_before_ctx_switch.
331 */
332 if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) {
333 ret = ring->flush(ring, 0, 0);
334 if (ret)
335 return ret;
336 }
337
327 ret = intel_ring_begin(ring, 6); 338 ret = intel_ring_begin(ring, 6);
328 if (ret) 339 if (ret)
329 return ret; 340 return ret;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index a041492fdd46..7a16f16371e6 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -423,6 +423,13 @@ static int init_render_ring(struct intel_ring_buffer *ring)
423 */ 423 */
424 I915_WRITE(CACHE_MODE_0, 424 I915_WRITE(CACHE_MODE_0,
425 _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 425 _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
426
427 /* This is not explicitly set for GEN6, so read the register.
428 * see intel_ring_mi_set_context() for why we care.
429 * TODO: consider explicitly setting the bit for GEN5
430 */
431 ring->itlb_before_ctx_switch =
432 !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS);
426 } 433 }
427 434
428 if (INTEL_INFO(dev)->gen >= 6) 435 if (INTEL_INFO(dev)->gen >= 6)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index b7884b90474a..594c9c4ad396 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -116,6 +116,10 @@ struct intel_ring_buffer {
116 116
117 wait_queue_head_t irq_queue; 117 wait_queue_head_t irq_queue;
118 118
119 /**
120 * Do an explicit TLB flush before MI_SET_CONTEXT
121 */
122 bool itlb_before_ctx_switch;
119 struct i915_hw_context *default_context; 123 struct i915_hw_context *default_context;
120 struct drm_i915_gem_object *last_context_obj; 124 struct drm_i915_gem_object *last_context_obj;
121 125