During suspend we want to flush out all active contexts and their rendering. To do so we queue a request from the kernel's context, once we know that request is done, we know the GPU is completely idle. To speed up that switch bump the GPU clocks. Switching to the kernel context prior to idling is also used to enforce a barrier before changing OA properties, and when evicting active rendering from the global GTT. All cases where we do want to race-to-idle. v2: Limit the boosting to only the switch before suspend. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: David Weinehall <david.weinehall@xxxxxxxxxxxxxxx> Cc: Mika Kuoppala <mika.kuoppala@xxxxxxxxx> Reviewed-by: Mika Kuoppala <mika.kuoppala@xxxxxxxxx> #v1 Tested-by: David Weinehall <david.weinehall@xxxxxxxxxxxxxxx> #v1 --- drivers/gpu/drm/i915/i915_gem.c | 11 ++++++----- drivers/gpu/drm/i915/i915_gem_context.c | 15 ++++++++++++++- drivers/gpu/drm/i915/i915_gem_context.h | 4 +++- drivers/gpu/drm/i915/i915_gem_evict.c | 2 +- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a81aa124af26..37a6c9ec5d60 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3513,7 +3513,7 @@ i915_gem_idle_work_handler(struct work_struct *work) * idle that implies a round trip through the retire worker). */ mutex_lock(&dev_priv->drm.struct_mutex); - i915_gem_switch_to_kernel_context(dev_priv); + i915_gem_switch_to_kernel_context(dev_priv, 0); mutex_unlock(&dev_priv->drm.struct_mutex); /* @@ -4958,7 +4958,8 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) * not rely on its state. */ if (!i915_terminally_wedged(&dev_priv->gpu_error)) { - ret = i915_gem_switch_to_kernel_context(dev_priv); + ret = i915_gem_switch_to_kernel_context(dev_priv, + I915_SWITCH_BOOST); if (ret) goto err_unlock; @@ -5043,7 +5044,7 @@ void i915_gem_resume(struct drm_i915_private *i915) intel_uc_resume(i915); /* Always reload a context for powersaving. */ - if (i915_gem_switch_to_kernel_context(i915)) + if (i915_gem_switch_to_kernel_context(i915, 0)) goto err_wedged; out_unlock: @@ -5238,7 +5239,7 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) goto err_active; } - err = i915_gem_switch_to_kernel_context(i915); + err = i915_gem_switch_to_kernel_context(i915, 0); if (err) goto err_active; @@ -5304,7 +5305,7 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) * request, ensure we are pointing at the kernel context and * then remove it. */ - if (WARN_ON(i915_gem_switch_to_kernel_context(i915))) + if (WARN_ON(i915_gem_switch_to_kernel_context(i915, 0))) goto out_ctx; if (WARN_ON(i915_gem_wait_for_idle(i915, I915_WAIT_LOCKED))) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 3fe1212b0f7e..dce1a3d9f5e6 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -605,7 +605,8 @@ static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine) return intel_engine_has_kernel_context(engine); } -int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915) +int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915, + unsigned int flags) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -636,6 +637,18 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915) I915_FENCE_GFP); } + /* + * "Race-to-idle". + * + * Switching to the kernel context is often used a synchronous + * step prior to idling, e.g. in suspend for flushing all + * current operations to memory before sleeping. These we + * want to complete as quickly as possible to avoid prolonged + * stalls, so allow the gpu to boost to maximum clocks. + */ + if (flags & I915_SWITCH_BOOST) + gen6_rps_boost(rq, NULL); + /* * Force a flush after the switch to ensure that all rendering * and operations prior to switching to the kernel context hits diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index c3262b4dd2ee..9d9140fa91ac 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -303,7 +303,9 @@ int i915_gem_context_open(struct drm_i915_private *i915, void i915_gem_context_close(struct drm_file *file); int i915_switch_context(struct i915_request *rq); -int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv); +int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915, + unsigned int flags); +#define I915_SWITCH_BOOST BIT(0) void i915_gem_context_release(struct kref *ctx_ref); struct i915_gem_context * diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 54814a196ee4..7d0f34b587ab 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -63,7 +63,7 @@ static int ggtt_flush(struct drm_i915_private *i915) * the hopes that we can then remove contexts and the like only * bound by their active reference. */ - err = i915_gem_switch_to_kernel_context(i915); + err = i915_gem_switch_to_kernel_context(i915, 0); if (err) return err; -- 2.17.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx