[PATCH 9/9] drm/i915: Split rc6 enabling
Chris Wilson
chris at chris-wilson.co.uk
Mon Nov 27 21:53:27 UTC 2017
Before we enable RC6, we should ensure that the HW state is valid. In
particular, that we have loaded a render context onto the HW. To be safe,
we need to defer the enabling from inside the i915_add_request to after
we have sync'ed with the initial context switch.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_gem.c | 17 ++-
drivers/gpu/drm/i915/i915_gem_request.c | 1 -
drivers/gpu/drm/i915/intel_display.c | 2 -
drivers/gpu/drm/i915/intel_gt_pm.c | 196 ++++++++++++++------------------
drivers/gpu/drm/i915/intel_gt_pm.h | 6 +-
5 files changed, 105 insertions(+), 117 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ce7a2ed7f980..de1e0d77d3e4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3121,9 +3121,12 @@ void i915_gem_reset(struct drm_i915_private *dev_priv)
i915_gem_restore_fences(dev_priv);
+ if (dev_priv->gt_pm.rc6.enabled) {
+ dev_priv->gt_pm.rc6.enabled = false;
+ intel_enable_rc6(dev_priv);
+ }
+
if (dev_priv->gt.awake) {
- intel_sanitize_gt_powersave(dev_priv);
- intel_enable_gt_powersave(dev_priv);
if (INTEL_GEN(dev_priv) >= 6)
gen6_rps_busy(dev_priv);
}
@@ -4765,7 +4768,6 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv)
int ret;
intel_runtime_pm_get(dev_priv);
- intel_suspend_gt_powersave(dev_priv);
mutex_lock(&dev->struct_mutex);
@@ -4829,6 +4831,7 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv)
*/
i915_gem_sanitize(dev_priv);
+ intel_disable_rc6(dev_priv);
intel_runtime_pm_put(dev_priv);
return 0;
@@ -4863,6 +4866,11 @@ void i915_gem_resume(struct drm_i915_private *i915)
if (i915_gem_switch_to_kernel_context(i915))
goto err_wedged;
+ if (i915_gem_wait_for_idle(i915, I915_WAIT_LOCKED))
+ goto err_wedged;
+
+ intel_enable_rc6(i915);
+
out_unlock:
intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
mutex_unlock(&i915->drm.struct_mutex);
@@ -5094,6 +5102,9 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915)
}
}
+ /* Once we have a render context loaded, we can allow the HW to sleep */
+ intel_enable_rc6(i915);
+
out_ctx:
i915_gem_context_set_closed(ctx);
i915_gem_context_put(ctx);
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index dc47233f629c..ebf4a9107ccf 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -255,7 +255,6 @@ static void mark_busy(struct drm_i915_private *i915)
intel_runtime_pm_get_noresume(i915);
i915->gt.awake = true;
- intel_enable_gt_powersave(i915);
i915_update_gfx_val(i915);
if (INTEL_GEN(i915) >= 6)
gen6_rps_busy(i915);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 11d259052a72..41af8aa5cf00 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15298,8 +15298,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
flush_work(&dev_priv->atomic_helper.free_work);
WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list));
- intel_disable_gt_powersave(dev_priv);
-
/*
* Interrupts and polling as the first thing to avoid creating havoc.
* Too much stuff here (turning of connectors, ...) would
diff --git a/drivers/gpu/drm/i915/intel_gt_pm.c b/drivers/gpu/drm/i915/intel_gt_pm.c
index 11e2c0dd7237..708de67cc452 100644
--- a/drivers/gpu/drm/i915/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/intel_gt_pm.c
@@ -2035,96 +2035,6 @@ static void intel_init_emon(struct drm_i915_private *dev_priv)
dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK);
}
-void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
-{
- struct intel_rps *rps = &dev_priv->gt_pm.rps;
-
- /*
- * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
- * requirement.
- */
- if (!sanitize_rc6(dev_priv)) {
- DRM_INFO("RC6 disabled, disabling runtime PM support\n");
- intel_runtime_pm_get(dev_priv);
- }
-
- mutex_lock(&dev_priv->pcu_lock);
-
- /* Initialize RPS limits (for userspace) */
- if (IS_CHERRYVIEW(dev_priv))
- cherryview_init_gt_powersave(dev_priv);
- else if (IS_VALLEYVIEW(dev_priv))
- valleyview_init_gt_powersave(dev_priv);
- else if (INTEL_GEN(dev_priv) >= 6)
- gen6_init_rps_frequencies(dev_priv);
-
- /* Derive initial user preferences/limits from the hardware limits */
- rps->idle_freq = rps->min_freq;
- rps->cur_freq = rps->idle_freq;
-
- rps->max_freq_softlimit = rps->max_freq;
- rps->min_freq_softlimit = rps->min_freq;
-
- if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
- rps->min_freq_softlimit =
- max_t(int,
- rps->efficient_freq,
- intel_freq_opcode(dev_priv, 450));
-
- /* After setting max-softlimit, find the overclock max freq */
- if (IS_GEN6(dev_priv) ||
- IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) {
- u32 params = 0;
-
- sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, ¶ms);
- if (params & BIT(31)) { /* OC supported */
- DRM_DEBUG_DRIVER("Overclocking supported, max: %dMHz, overclock: %dMHz\n",
- (rps->max_freq & 0xff) * 50,
- (params & 0xff) * 50);
- rps->max_freq = params & 0xff;
- }
- }
-
- /* Finally allow us to boost to max by default */
- rps->boost_freq = rps->max_freq;
-
- mutex_unlock(&dev_priv->pcu_lock);
-}
-
-void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
-{
- if (IS_VALLEYVIEW(dev_priv))
- valleyview_cleanup_gt_powersave(dev_priv);
-
- if (!HAS_RC6(dev_priv))
- intel_runtime_pm_put(dev_priv);
-}
-
-/**
- * intel_suspend_gt_powersave - suspend PM work and helper threads
- * @dev_priv: i915 device
- *
- * We don't want to disable RC6 or other features here, we just want
- * to make sure any work we've queued has finished and won't bother
- * us while we're suspended.
- */
-void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv)
-{
- if (INTEL_GEN(dev_priv) < 6)
- return;
-
- /* gen6_rps_idle() will be called later to disable interrupts */
-}
-
-void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv)
-{
- dev_priv->gt_pm.rps.enabled = true; /* force RPS disabling */
- dev_priv->gt_pm.rc6.enabled = true; /* force RC6 disabling */
- intel_disable_gt_powersave(dev_priv);
-
- gen6_reset_rps_interrupts(dev_priv);
-}
-
static inline void intel_disable_llc_pstate(struct drm_i915_private *i915)
{
lockdep_assert_held(&i915->pcu_lock);
@@ -2137,12 +2047,11 @@ static inline void intel_disable_llc_pstate(struct drm_i915_private *i915)
i915->gt_pm.llc_pstate.enabled = false;
}
-static void intel_disable_rc6(struct drm_i915_private *dev_priv)
+void intel_disable_rc6(struct drm_i915_private *dev_priv)
{
- lockdep_assert_held(&dev_priv->pcu_lock);
-
+ mutex_lock(&dev_priv->pcu_lock);
if (!dev_priv->gt_pm.rc6.enabled)
- return;
+ goto unlock;
if (INTEL_GEN(dev_priv) >= 9)
gen9_disable_rc6(dev_priv);
@@ -2154,6 +2063,8 @@ static void intel_disable_rc6(struct drm_i915_private *dev_priv)
gen6_disable_rc6(dev_priv);
dev_priv->gt_pm.rc6.enabled = false;
+unlock:
+ mutex_unlock(&dev_priv->pcu_lock);
}
static void intel_disable_rps(struct drm_i915_private *dev_priv)
@@ -2177,11 +2088,10 @@ static void intel_disable_rps(struct drm_i915_private *dev_priv)
dev_priv->gt_pm.rps.enabled = false;
}
-void intel_disable_gt_powersave(struct drm_i915_private *dev_priv)
+static void intel_disable_gt_powersave(struct drm_i915_private *dev_priv)
{
mutex_lock(&dev_priv->pcu_lock);
- intel_disable_rc6(dev_priv);
intel_disable_rps(dev_priv);
if (HAS_LLC(dev_priv))
intel_disable_llc_pstate(dev_priv);
@@ -2201,12 +2111,14 @@ static inline void intel_enable_llc_pstate(struct drm_i915_private *i915)
i915->gt_pm.llc_pstate.enabled = true;
}
-static void intel_enable_rc6(struct drm_i915_private *dev_priv)
+void intel_enable_rc6(struct drm_i915_private *dev_priv)
{
- lockdep_assert_held(&dev_priv->pcu_lock);
+ if (!HAS_RC6(dev_priv))
+ return;
+ mutex_lock(&dev_priv->pcu_lock);
if (dev_priv->gt_pm.rc6.enabled)
- return;
+ goto unlock;
if (IS_CHERRYVIEW(dev_priv))
cherryview_enable_rc6(dev_priv);
@@ -2220,6 +2132,8 @@ static void intel_enable_rc6(struct drm_i915_private *dev_priv)
gen6_enable_rc6(dev_priv);
dev_priv->gt_pm.rc6.enabled = true;
+unlock:
+ mutex_unlock(&dev_priv->pcu_lock);
}
static void intel_enable_rps(struct drm_i915_private *dev_priv)
@@ -2255,20 +2169,86 @@ static void intel_enable_rps(struct drm_i915_private *dev_priv)
rps->enabled = true;
}
-void intel_enable_gt_powersave(struct drm_i915_private *dev_priv)
+void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
{
- /* Powersaving is controlled by the host when inside a VM */
- if (intel_vgpu_active(dev_priv))
- return;
+ struct intel_rps *rps = &dev_priv->gt_pm.rps;
+
+ /*
+ * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
+ * requirement.
+ */
+ if (!sanitize_rc6(dev_priv)) {
+ DRM_INFO("RC6 disabled, disabling runtime PM support\n");
+ intel_runtime_pm_get(dev_priv);
+ }
mutex_lock(&dev_priv->pcu_lock);
- if (HAS_RC6(dev_priv))
- intel_enable_rc6(dev_priv);
- intel_enable_rps(dev_priv);
- if (HAS_LLC(dev_priv))
- intel_enable_llc_pstate(dev_priv);
+ /* Initialize RPS limits (for userspace) */
+ if (IS_CHERRYVIEW(dev_priv))
+ cherryview_init_gt_powersave(dev_priv);
+ else if (IS_VALLEYVIEW(dev_priv))
+ valleyview_init_gt_powersave(dev_priv);
+ else if (INTEL_GEN(dev_priv) >= 6)
+ gen6_init_rps_frequencies(dev_priv);
+
+ /* Derive initial user preferences/limits from the hardware limits */
+ rps->idle_freq = rps->min_freq;
+ rps->cur_freq = rps->idle_freq;
+
+ rps->max_freq_softlimit = rps->max_freq;
+ rps->min_freq_softlimit = rps->min_freq;
+
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+ rps->min_freq_softlimit =
+ max_t(int,
+ rps->efficient_freq,
+ intel_freq_opcode(dev_priv, 450));
+
+ /* After setting max-softlimit, find the overclock max freq */
+ if (IS_GEN6(dev_priv) ||
+ IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) {
+ u32 params = 0;
+
+ sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, ¶ms);
+ if (params & BIT(31)) { /* OC supported */
+ DRM_DEBUG_DRIVER("Overclocking supported, max: %dMHz, overclock: %dMHz\n",
+ (rps->max_freq & 0xff) * 50,
+ (params & 0xff) * 50);
+ rps->max_freq = params & 0xff;
+ }
+ }
+
+ /* Finally allow us to boost to max by default */
+ rps->boost_freq = rps->max_freq;
+
+
+ /* Powersaving is controlled by the host when inside a VM */
+ if (!intel_vgpu_active(dev_priv)) {
+ intel_enable_rps(dev_priv);
+ if (HAS_LLC(dev_priv))
+ intel_enable_llc_pstate(dev_priv);
+ }
mutex_unlock(&dev_priv->pcu_lock);
}
+void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
+{
+ if (IS_VALLEYVIEW(dev_priv))
+ valleyview_cleanup_gt_powersave(dev_priv);
+
+ if (!HAS_RC6(dev_priv))
+ intel_runtime_pm_put(dev_priv);
+}
+
+void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv)
+{
+ dev_priv->gt_pm.rc6.enabled = true; /* force RC6 disabling */
+ intel_disable_rc6(dev_priv);
+
+ dev_priv->gt_pm.rps.enabled = true; /* force RPS disabling */
+ intel_disable_gt_powersave(dev_priv);
+
+ gen6_reset_rps_interrupts(dev_priv);
+}
diff --git a/drivers/gpu/drm/i915/intel_gt_pm.h b/drivers/gpu/drm/i915/intel_gt_pm.h
index 5f027466b710..0ce0ec347cd9 100644
--- a/drivers/gpu/drm/i915/intel_gt_pm.h
+++ b/drivers/gpu/drm/i915/intel_gt_pm.h
@@ -30,9 +30,9 @@ void intel_gpu_ips_teardown(void);
void intel_init_gt_powersave(struct drm_i915_private *dev_priv);
void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv);
void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv);
-void intel_enable_gt_powersave(struct drm_i915_private *dev_priv);
-void intel_disable_gt_powersave(struct drm_i915_private *dev_priv);
-void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv);
+
+void intel_enable_rc6(struct drm_i915_private *dev_priv);
+void intel_disable_rc6(struct drm_i915_private *dev_priv);
void gen6_rps_busy(struct drm_i915_private *dev_priv);
void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
--
2.15.0
More information about the Intel-gfx-trybot
mailing list