diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lrc.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_lrc.c | 72 |
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 */ |