Using aliasing ppgtt in some cases like playing video the GPU might hang because HW context was not in a reliable state. When we resume we switch to default context and when we resume we can force a restore if default is really there and object is bound. Cc: Ben Widawsky <ben@xxxxxxxxxxxx> Cc: U. Artie Eoff <ullysses.a.eoff@xxxxxxxxx> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_gem_context.c | 180 +++++++++++++++++--------------- 1 file changed, 94 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index e4c57a3..0a8a07a 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -97,6 +97,91 @@ #define GEN6_CONTEXT_ALIGN (64<<10) #define GEN7_CONTEXT_ALIGN 4096 +static inline int +mi_set_context(struct intel_engine_cs *ring, + struct intel_context *new_context, + u32 hw_flags) +{ + u32 flags = hw_flags | MI_MM_SPACE_GTT; + const int num_rings = + /* Use an extended w/a on ivb+ if signalling from other rings */ + i915_semaphore_is_enabled(ring->dev) ? + hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 : + 0; + int len, i, ret; + + /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB + * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value + * explicitly, so we rely on the value at ring init, stored in + * itlb_before_ctx_switch. + */ + if (IS_GEN6(ring->dev)) { + ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0); + if (ret) + return ret; + } + + /* These flags are for resource streamer on HSW+ */ + if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8) + flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); + + + len = 4; + if (INTEL_INFO(ring->dev)->gen >= 7) + len += 2 + (num_rings ? 4*num_rings + 2 : 0); + + ret = intel_ring_begin(ring, len); + if (ret) + return ret; + + /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ + if (INTEL_INFO(ring->dev)->gen >= 7) { + intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); + if (num_rings) { + struct intel_engine_cs *signaller; + + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); + for_each_ring(signaller, to_i915(ring->dev), i) { + if (signaller == ring) + continue; + + intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); + intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); + } + } + } + + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_SET_CONTEXT); + intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->legacy_hw_ctx.rcs_state) | + flags); + /* + * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP + * WaMiSetContext_Hang:snb,ivb,vlv + */ + intel_ring_emit(ring, MI_NOOP); + + if (INTEL_INFO(ring->dev)->gen >= 7) { + if (num_rings) { + struct intel_engine_cs *signaller; + + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); + for_each_ring(signaller, to_i915(ring->dev), i) { + if (signaller == ring) + continue; + + intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); + intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); + } + } + intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); + } + + intel_ring_advance(ring); + + return ret; +} + static size_t get_context_alignment(struct drm_device *dev) { if (IS_GEN6(dev)) @@ -412,6 +497,7 @@ void i915_gem_context_fini(struct drm_device *dev) int i915_gem_context_enable(struct drm_i915_private *dev_priv) { struct intel_engine_cs *ring; + struct intel_context *lctx = dev_priv->ring[RCS].last_context; int ret, i; BUG_ON(!dev_priv->ring[RCS].default_context); @@ -429,12 +515,19 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) } } - } else + } else { for_each_ring(ring, dev_priv, i) { ret = i915_switch_context(ring, ring->default_context); if (ret) return ret; } + /* Force default HW Context restore on Resume */ + if (lctx == dev_priv->ring[RCS].default_context && + i915_gem_obj_ggtt_bound(lctx->legacy_hw_ctx.rcs_state)) { + mi_set_context(&dev_priv->ring[RCS], lctx, + MI_FORCE_RESTORE | MI_SAVE_EXT_STATE_EN); + } + } return 0; } @@ -486,91 +579,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) return ctx; } -static inline int -mi_set_context(struct intel_engine_cs *ring, - struct intel_context *new_context, - u32 hw_flags) -{ - u32 flags = hw_flags | MI_MM_SPACE_GTT; - const int num_rings = - /* Use an extended w/a on ivb+ if signalling from other rings */ - i915_semaphore_is_enabled(ring->dev) ? - hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 : - 0; - int len, i, ret; - - /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB - * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value - * explicitly, so we rely on the value at ring init, stored in - * itlb_before_ctx_switch. - */ - if (IS_GEN6(ring->dev)) { - ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0); - if (ret) - return ret; - } - - /* These flags are for resource streamer on HSW+ */ - if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8) - flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); - - - len = 4; - if (INTEL_INFO(ring->dev)->gen >= 7) - len += 2 + (num_rings ? 4*num_rings + 2 : 0); - - ret = intel_ring_begin(ring, len); - if (ret) - return ret; - - /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ - if (INTEL_INFO(ring->dev)->gen >= 7) { - intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); - if (num_rings) { - struct intel_engine_cs *signaller; - - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_ring(signaller, to_i915(ring->dev), i) { - if (signaller == ring) - continue; - - intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); - intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); - } - } - } - - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_SET_CONTEXT); - intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->legacy_hw_ctx.rcs_state) | - flags); - /* - * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP - * WaMiSetContext_Hang:snb,ivb,vlv - */ - intel_ring_emit(ring, MI_NOOP); - - if (INTEL_INFO(ring->dev)->gen >= 7) { - if (num_rings) { - struct intel_engine_cs *signaller; - - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_ring(signaller, to_i915(ring->dev), i) { - if (signaller == ring) - continue; - - intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); - intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); - } - } - intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); - } - - intel_ring_advance(ring); - - return ret; -} - static inline bool should_skip_switch(struct intel_engine_cs *ring, struct intel_context *from, struct intel_context *to) -- 2.1.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx