summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_lrc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lrc.c')
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c72
1 files changed, 53 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 0160bec1e7ba..a499f16db194 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1092,6 +1092,56 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
batch[index++] = (cmd); \
} while (0)
+
+/*
+ * In this WA we need to set GEN8_L3SQCREG4[21:21] and reset it after
+ * PIPE_CONTROL instruction. This is required for the flush to happen correctly
+ * but there is a slight complication as this is applied in WA batch where the
+ * values are only initialized once so we cannot take register value at the
+ * beginning and reuse it further; hence we save its value to memory, upload a
+ * constant value with bit21 set and then we restore it back with the saved value.
+ * To simplify the WA, a constant value is formed by using the default value
+ * of this register. This shouldn't be a problem because we are only modifying
+ * it for a short period and this batch in non-premptible. We can ofcourse
+ * use additional instructions that read the actual value of the register
+ * at that time and set our bit of interest but it makes the WA complicated.
+ *
+ * This WA is also required for Gen9 so extracting as a function avoids
+ * code duplication.
+ */
+static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
+ uint32_t *const batch,
+ uint32_t index)
+{
+ uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES);
+
+ wa_ctx_emit(batch, (MI_STORE_REGISTER_MEM_GEN8(1) |
+ MI_SRM_LRM_GLOBAL_GTT));
+ wa_ctx_emit(batch, GEN8_L3SQCREG4);
+ wa_ctx_emit(batch, ring->scratch.gtt_offset + 256);
+ wa_ctx_emit(batch, 0);
+
+ wa_ctx_emit(batch, MI_LOAD_REGISTER_IMM(1));
+ wa_ctx_emit(batch, GEN8_L3SQCREG4);
+ wa_ctx_emit(batch, l3sqc4_flush);
+
+ wa_ctx_emit(batch, GFX_OP_PIPE_CONTROL(6));
+ wa_ctx_emit(batch, (PIPE_CONTROL_CS_STALL |
+ PIPE_CONTROL_DC_FLUSH_ENABLE));
+ wa_ctx_emit(batch, 0);
+ wa_ctx_emit(batch, 0);
+ wa_ctx_emit(batch, 0);
+ wa_ctx_emit(batch, 0);
+
+ wa_ctx_emit(batch, (MI_LOAD_REGISTER_MEM_GEN8(1) |
+ MI_SRM_LRM_GLOBAL_GTT));
+ wa_ctx_emit(batch, GEN8_L3SQCREG4);
+ wa_ctx_emit(batch, ring->scratch.gtt_offset + 256);
+ wa_ctx_emit(batch, 0);
+
+ return index;
+}
+
static inline uint32_t wa_ctx_start(struct i915_wa_ctx_bb *wa_ctx,
uint32_t offset,
uint32_t start_alignment)
@@ -1152,25 +1202,9 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring,
/* WaFlushCoherentL3CacheLinesAtContextSwitch:bdw */
if (IS_BROADWELL(ring->dev)) {
- struct drm_i915_private *dev_priv = to_i915(ring->dev);
- uint32_t l3sqc4_flush = (I915_READ(GEN8_L3SQCREG4) |
- GEN8_LQSC_FLUSH_COHERENT_LINES);
-
- wa_ctx_emit(batch, MI_LOAD_REGISTER_IMM(1));
- wa_ctx_emit(batch, GEN8_L3SQCREG4);
- wa_ctx_emit(batch, l3sqc4_flush);
-
- wa_ctx_emit(batch, GFX_OP_PIPE_CONTROL(6));
- wa_ctx_emit(batch, (PIPE_CONTROL_CS_STALL |
- PIPE_CONTROL_DC_FLUSH_ENABLE));
- wa_ctx_emit(batch, 0);
- wa_ctx_emit(batch, 0);
- wa_ctx_emit(batch, 0);
- wa_ctx_emit(batch, 0);
-
- wa_ctx_emit(batch, MI_LOAD_REGISTER_IMM(1));
- wa_ctx_emit(batch, GEN8_L3SQCREG4);
- wa_ctx_emit(batch, l3sqc4_flush & ~GEN8_LQSC_FLUSH_COHERENT_LINES);
+ index = gen8_emit_flush_coherentl3_wa(ring, batch, index);
+ if (index < 0)
+ return index;
}
/* WaClearSlmSpaceAtContextSwitch:bdw,chv */