On module load and unload, we grab the POWER_DOMAIN_INIT powerwells and
transfer them to the runtime-pm code. We can use our wakeref tracking to
verify that the wakeref is indeed passed from init to enable, and
disable to fini; and across suspend.

Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_debugfs.c     |   3 +
 drivers/gpu/drm/i915/i915_drv.h         |   2 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 146 +++++++++++++-----------
 3 files changed, 85 insertions(+), 66 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index b1fdaa8875cb..a6d2e3496a09 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2695,6 +2695,9 @@ static int i915_runtime_pm_status(struct seq_file *m, 
void *unused)
        if (!HAS_RUNTIME_PM(dev_priv))
                seq_puts(m, "Runtime power management not supported\n");
 
+       seq_printf(m, "Runtime power management: %s\n",
+                  enableddisabled(!dev_priv->power_domains.wakeref));
+
        seq_printf(m, "GPU idle: %s (epoch %u)\n",
                   yesno(!dev_priv->gt.awake), dev_priv->gt.epoch);
        seq_printf(m, "IRQs disabled: %s\n",
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c497c781f936..34cd9e189cfb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -943,6 +943,8 @@ struct i915_power_domains {
        bool display_core_suspended;
        int power_well_count;
 
+       intel_wakeref_t wakeref;
+
        struct mutex lock;
        int domain_use_count[POWER_DOMAIN_NUM];
        struct i915_power_well *power_wells;
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c 
b/drivers/gpu/drm/i915/intel_runtime_pm.c
index f0debe757840..20f546dc2490 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -3974,7 +3974,7 @@ static void intel_power_domains_verify_state(struct 
drm_i915_private *dev_priv);
 
 /**
  * intel_power_domains_init_hw - initialize hardware power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  * @resume: Called from resume code paths or not
  *
  * This function initializes the hardware power domain state and enables all
@@ -3988,27 +3988,27 @@ static void intel_power_domains_verify_state(struct 
drm_i915_private *dev_priv);
  * intel_power_domains_enable()) and must be paired with
  * intel_power_domains_fini_hw().
  */
-void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool 
resume)
+void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
 
        power_domains->initializing = true;
 
-       if (IS_ICELAKE(dev_priv)) {
-               icl_display_core_init(dev_priv, resume);
-       } else if (IS_CANNONLAKE(dev_priv)) {
-               cnl_display_core_init(dev_priv, resume);
-       } else if (IS_GEN9_BC(dev_priv)) {
-               skl_display_core_init(dev_priv, resume);
-       } else if (IS_GEN9_LP(dev_priv)) {
-               bxt_display_core_init(dev_priv, resume);
-       } else if (IS_CHERRYVIEW(dev_priv)) {
+       if (IS_ICELAKE(i915)) {
+               icl_display_core_init(i915, resume);
+       } else if (IS_CANNONLAKE(i915)) {
+               cnl_display_core_init(i915, resume);
+       } else if (IS_GEN9_BC(i915)) {
+               skl_display_core_init(i915, resume);
+       } else if (IS_GEN9_LP(i915)) {
+               bxt_display_core_init(i915, resume);
+       } else if (IS_CHERRYVIEW(i915)) {
                mutex_lock(&power_domains->lock);
-               chv_phy_control_init(dev_priv);
+               chv_phy_control_init(i915);
                mutex_unlock(&power_domains->lock);
-       } else if (IS_VALLEYVIEW(dev_priv)) {
+       } else if (IS_VALLEYVIEW(i915)) {
                mutex_lock(&power_domains->lock);
-               vlv_cmnlane_wa(dev_priv);
+               vlv_cmnlane_wa(i915);
                mutex_unlock(&power_domains->lock);
        }
 
@@ -4018,18 +4018,20 @@ void intel_power_domains_init_hw(struct 
drm_i915_private *dev_priv, bool resume)
         * resources powered until display HW readout is complete. We drop
         * this reference in intel_power_domains_enable().
         */
-       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+       power_domains->wakeref =
+               intel_display_power_get(i915, POWER_DOMAIN_INIT);
+
        /* Disable power support if the user asked so. */
        if (!i915_modparams.disable_power_well)
-               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
-       intel_power_domains_sync_hw(dev_priv);
+               intel_display_power_get(i915, POWER_DOMAIN_INIT);
+       intel_power_domains_sync_hw(i915);
 
        power_domains->initializing = false;
 }
 
 /**
  * intel_power_domains_fini_hw - deinitialize hw power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * De-initializes the display power domain HW state. It also ensures that the
  * device stays powered up so that the driver can be reloaded.
@@ -4038,21 +4040,24 @@ void intel_power_domains_init_hw(struct 
drm_i915_private *dev_priv, bool resume)
  * intel_power_domains_disable()) and must be paired with
  * intel_power_domains_init_hw().
  */
-void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
+void intel_power_domains_fini_hw(struct drm_i915_private *i915)
 {
-       /* Keep the power well enabled, but cancel its rpm wakeref. */
-       intel_runtime_pm_put_unchecked(dev_priv);
+       intel_wakeref_t wakeref __maybe_unused =
+               fetch_and_zero(&i915->power_domains.wakeref);
 
        /* Remove the refcount we took to keep power well support disabled. */
        if (!i915_modparams.disable_power_well)
-               intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
+               intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
+
+       intel_power_domains_verify_state(i915);
 
-       intel_power_domains_verify_state(dev_priv);
+       /* Keep the power well enabled, but cancel its rpm wakeref. */
+       intel_runtime_pm_put(i915, wakeref);
 }
 
 /**
  * intel_power_domains_enable - enable toggling of display power wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Enable the ondemand enabling/disabling of the display power wells. Note that
  * power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled
@@ -4062,30 +4067,36 @@ void intel_power_domains_fini_hw(struct 
drm_i915_private *dev_priv)
  * of display HW readout (which will acquire the power references reflecting
  * the current HW state).
  */
-void intel_power_domains_enable(struct drm_i915_private *dev_priv)
+void intel_power_domains_enable(struct drm_i915_private *i915)
 {
-       intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
+       intel_wakeref_t wakeref __maybe_unused =
+               fetch_and_zero(&i915->power_domains.wakeref);
 
-       intel_power_domains_verify_state(dev_priv);
+       intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
+       intel_power_domains_verify_state(i915);
 }
 
 /**
  * intel_power_domains_disable - disable toggling of display power wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Disable the ondemand enabling/disabling of the display power wells. See
  * intel_power_domains_enable() for which power wells this call controls.
  */
-void intel_power_domains_disable(struct drm_i915_private *dev_priv)
+void intel_power_domains_disable(struct drm_i915_private *i915)
 {
-       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+       struct i915_power_domains *power_domains = &i915->power_domains;
+
+       WARN_ON(power_domains->wakeref);
+       power_domains->wakeref =
+               intel_display_power_get(i915, POWER_DOMAIN_INIT);
 
-       intel_power_domains_verify_state(dev_priv);
+       intel_power_domains_verify_state(i915);
 }
 
 /**
  * intel_power_domains_suspend - suspend power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  * @suspend_mode: specifies the target suspend state (idle, mem, hibernation)
  *
  * This function prepares the hardware power domain state before entering
@@ -4094,12 +4105,14 @@ void intel_power_domains_disable(struct 
drm_i915_private *dev_priv)
  * It must be called with power domains already disabled (after a call to
  * intel_power_domains_disable()) and paired with intel_power_domains_resume().
  */
-void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
+void intel_power_domains_suspend(struct drm_i915_private *i915,
                                 enum i915_drm_suspend_mode suspend_mode)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
+       intel_wakeref_t wakeref __maybe_unused =
+               fetch_and_zero(&power_domains->wakeref);
 
-       intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
+       intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
 
        /*
         * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
@@ -4108,10 +4121,10 @@ void intel_power_domains_suspend(struct 
drm_i915_private *dev_priv,
         * resources as required and also enable deeper system power states
         * that would be blocked if the firmware was inactive.
         */
-       if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
+       if (!(i915->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
            suspend_mode == I915_DRM_SUSPEND_IDLE &&
-           dev_priv->csr.dmc_payload != NULL) {
-               intel_power_domains_verify_state(dev_priv);
+           i915->csr.dmc_payload != NULL) {
+               intel_power_domains_verify_state(i915);
                return;
        }
 
@@ -4120,25 +4133,25 @@ void intel_power_domains_suspend(struct 
drm_i915_private *dev_priv,
         * power wells if power domains must be deinitialized for suspend.
         */
        if (!i915_modparams.disable_power_well) {
-               intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
-               intel_power_domains_verify_state(dev_priv);
+               intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
+               intel_power_domains_verify_state(i915);
        }
 
-       if (IS_ICELAKE(dev_priv))
-               icl_display_core_uninit(dev_priv);
-       else if (IS_CANNONLAKE(dev_priv))
-               cnl_display_core_uninit(dev_priv);
-       else if (IS_GEN9_BC(dev_priv))
-               skl_display_core_uninit(dev_priv);
-       else if (IS_GEN9_LP(dev_priv))
-               bxt_display_core_uninit(dev_priv);
+       if (IS_ICELAKE(i915))
+               icl_display_core_uninit(i915);
+       else if (IS_CANNONLAKE(i915))
+               cnl_display_core_uninit(i915);
+       else if (IS_GEN9_BC(i915))
+               skl_display_core_uninit(i915);
+       else if (IS_GEN9_LP(i915))
+               bxt_display_core_uninit(i915);
 
        power_domains->display_core_suspended = true;
 }
 
 /**
  * intel_power_domains_resume - resume power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function resume the hardware power domain state during system resume.
  *
@@ -4146,28 +4159,30 @@ void intel_power_domains_suspend(struct 
drm_i915_private *dev_priv,
  * intel_power_domains_enable()) and must be paired with
  * intel_power_domains_suspend().
  */
-void intel_power_domains_resume(struct drm_i915_private *dev_priv)
+void intel_power_domains_resume(struct drm_i915_private *i915)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
 
        if (power_domains->display_core_suspended) {
-               intel_power_domains_init_hw(dev_priv, true);
+               intel_power_domains_init_hw(i915, true);
                power_domains->display_core_suspended = false;
        } else {
-               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+               WARN_ON(power_domains->wakeref);
+               power_domains->wakeref =
+                       intel_display_power_get(i915, POWER_DOMAIN_INIT);
        }
 
-       intel_power_domains_verify_state(dev_priv);
+       intel_power_domains_verify_state(i915);
 }
 
 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 
-static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
+static void intel_power_domains_dump_info(struct drm_i915_private *i915)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
        struct i915_power_well *power_well;
 
-       for_each_power_well(dev_priv, power_well) {
+       for_each_power_well(i915, power_well) {
                enum intel_display_power_domain domain;
 
                DRM_DEBUG_DRIVER("%-25s %d\n",
@@ -4182,7 +4197,7 @@ static void intel_power_domains_dump_info(struct 
drm_i915_private *dev_priv)
 
 /**
  * intel_power_domains_verify_state - verify the HW/SW state for all power 
wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Verify if the reference count of each power well matches its HW enabled
  * state and the total refcount of the domains it belongs to. This must be
@@ -4190,16 +4205,16 @@ static void intel_power_domains_dump_info(struct 
drm_i915_private *dev_priv)
  * acquiring reference counts for any power wells in use and disabling the
  * ones left on by BIOS but not required by any active output.
  */
-static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
+static void intel_power_domains_verify_state(struct drm_i915_private *i915)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
        struct i915_power_well *power_well;
        bool dump_domain_info;
 
        mutex_lock(&power_domains->lock);
 
        dump_domain_info = false;
-       for_each_power_well(dev_priv, power_well) {
+       for_each_power_well(i915, power_well) {
                enum intel_display_power_domain domain;
                int domains_count;
                bool enabled;
@@ -4212,8 +4227,7 @@ static void intel_power_domains_verify_state(struct 
drm_i915_private *dev_priv)
                if (!power_well->desc->domains)
                        continue;
 
-               enabled = power_well->desc->ops->is_enabled(dev_priv,
-                                                           power_well);
+               enabled = power_well->desc->ops->is_enabled(i915, power_well);
                if ((power_well->count || power_well->desc->always_on) !=
                    enabled)
                        DRM_ERROR("power well %s state mismatch (refcount 
%d/enabled %d)",
@@ -4237,7 +4251,7 @@ static void intel_power_domains_verify_state(struct 
drm_i915_private *dev_priv)
                static bool dumped;
 
                if (!dumped) {
-                       intel_power_domains_dump_info(dev_priv);
+                       intel_power_domains_dump_info(i915);
                        dumped = true;
                }
        }
@@ -4247,7 +4261,7 @@ static void intel_power_domains_verify_state(struct 
drm_i915_private *dev_priv)
 
 #else
 
-static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
+static void intel_power_domains_verify_state(struct drm_i915_private *i915)
 {
 }
 
-- 
2.19.0.rc1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to