Chris Wilson <ch...@chris-wilson.co.uk> writes:

> The majority of runtime-pm operations are bounded and scoped within a
> function; these are easy to verify that the wakeref are handled
> correctly. We can employ the compiler to help us, and reduce the number
> of wakerefs tracked when debugging, by passing around cookies provided
> by the various rpm_get functions to their rpm_put counterpart. This
> makes the pairing explicit, and given the required wakeref cookie the
> compiler can verify that we pass an initialised value to the rpm_put
> (quite handy for double checking error paths).
>
> Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nik...@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c     | 35 ++++++------
>  drivers/gpu/drm/i915/i915_drv.h         |  2 +
>  drivers/gpu/drm/i915/i915_gem.c         |  4 +-
>  drivers/gpu/drm/i915/icl_dsi.c          | 36 ++++++++-----
>  drivers/gpu/drm/i915/intel_audio.c      |  3 +-
>  drivers/gpu/drm/i915/intel_cdclk.c      | 10 ++--
>  drivers/gpu/drm/i915/intel_crt.c        | 25 +++++----
>  drivers/gpu/drm/i915/intel_csr.c        | 25 +++++++--
>  drivers/gpu/drm/i915/intel_ddi.c        | 36 ++++++++-----
>  drivers/gpu/drm/i915/intel_display.c    | 68 ++++++++++++++---------
>  drivers/gpu/drm/i915/intel_dp.c         | 38 +++++++------
>  drivers/gpu/drm/i915/intel_dpll_mgr.c   | 66 +++++++++++++++--------
>  drivers/gpu/drm/i915/intel_drv.h        | 17 ++++--
>  drivers/gpu/drm/i915/intel_dsi.h        |  1 +
>  drivers/gpu/drm/i915/intel_hdmi.c       | 18 ++++---
>  drivers/gpu/drm/i915/intel_i2c.c        | 20 +++----
>  drivers/gpu/drm/i915/intel_lvds.c       |  8 +--
>  drivers/gpu/drm/i915/intel_pipe_crc.c   |  6 ++-
>  drivers/gpu/drm/i915/intel_pm.c         |  6 ++-
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 71 ++++++++++++++++---------
>  drivers/gpu/drm/i915/intel_sprite.c     | 24 ++++++---
>  drivers/gpu/drm/i915/intel_vdsc.c       |  4 +-
>  drivers/gpu/drm/i915/vlv_dsi.c          | 14 +++--
>  23 files changed, 347 insertions(+), 190 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index 34cbd9a20583..b7dcacf2a5d3 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -626,10 +626,12 @@ static void gen8_display_interrupt_info(struct seq_file 
> *m)
>  
>       for_each_pipe(dev_priv, pipe) {
>               enum intel_display_power_domain power_domain;
> +             intel_wakeref_t wakeref;
>  
>               power_domain = POWER_DOMAIN_PIPE(pipe);
> -             if (!intel_display_power_get_if_enabled(dev_priv,
> -                                                     power_domain)) {
> +             wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                          power_domain);
> +             if (!wakeref) {
>                       seq_printf(m, "Pipe %c power disabled\n",
>                                  pipe_name(pipe));
>                       continue;
> @@ -644,7 +646,7 @@ static void gen8_display_interrupt_info(struct seq_file 
> *m)
>                          pipe_name(pipe),
>                          I915_READ(GEN8_DE_PIPE_IER(pipe)));
>  
> -             intel_display_power_put(dev_priv, power_domain);
> +             intel_display_power_put(dev_priv, power_domain, wakeref);
>       }
>  
>       seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
> @@ -680,6 +682,8 @@ static int i915_interrupt_info(struct seq_file *m, void 
> *data)
>       wakeref = intel_runtime_pm_get(dev_priv);
>  
>       if (IS_CHERRYVIEW(dev_priv)) {
> +             intel_wakeref_t pref;
> +

In here you are introducing a new, descriptive, power reference for display.
But then you drop it after using it twice. And can't seem to find
reason for inconsistency.

>               seq_printf(m, "Master Interrupt Control:\t%08x\n",
>                          I915_READ(GEN8_MASTER_IRQ));
>  
> @@ -695,8 +699,9 @@ static int i915_interrupt_info(struct seq_file *m, void 
> *data)
>                       enum intel_display_power_domain power_domain;
>  
>                       power_domain = POWER_DOMAIN_PIPE(pipe);
> -                     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                                             power_domain)) {
> +                     pref = intel_display_power_get_if_enabled(dev_priv,
> +                                                               power_domain);
> +                     if (!pref) {
>                               seq_printf(m, "Pipe %c power disabled\n",
>                                          pipe_name(pipe));
>                               continue;
> @@ -706,17 +711,17 @@ static int i915_interrupt_info(struct seq_file *m, void 
> *data)
>                                  pipe_name(pipe),
>                                  I915_READ(PIPESTAT(pipe)));
>  
> -                     intel_display_power_put(dev_priv, power_domain);
> +                     intel_display_power_put(dev_priv, power_domain, pref);
>               }
>  
> -             intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +             pref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
>               seq_printf(m, "Port hotplug:\t%08x\n",
>                          I915_READ(PORT_HOTPLUG_EN));
>               seq_printf(m, "DPFLIPSTAT:\t%08x\n",
>                          I915_READ(VLV_DPFLIPSTAT));
>               seq_printf(m, "DPINVGTT:\t%08x\n",
>                          I915_READ(DPINVGTT));
> -             intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +             intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, pref);
>  
>               for (i = 0; i < 4; i++) {
>                       seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
> @@ -779,10 +784,12 @@ static int i915_interrupt_info(struct seq_file *m, void 
> *data)
>                          I915_READ(VLV_IMR));
>               for_each_pipe(dev_priv, pipe) {
>                       enum intel_display_power_domain power_domain;
> +                     intel_wakeref_t pref;
>  
>                       power_domain = POWER_DOMAIN_PIPE(pipe);
> -                     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                                             power_domain)) {
> +                     pref = intel_display_power_get_if_enabled(dev_priv,
> +                                                               power_domain);
> +                     if (!pref) {
>                               seq_printf(m, "Pipe %c power disabled\n",
>                                          pipe_name(pipe));
>                               continue;
> @@ -791,7 +798,7 @@ static int i915_interrupt_info(struct seq_file *m, void 
> *data)
>                       seq_printf(m, "Pipe %c stat:\t%08x\n",
>                                  pipe_name(pipe),
>                                  I915_READ(PIPESTAT(pipe)));
> -                     intel_display_power_put(dev_priv, power_domain);
> +                     intel_display_power_put(dev_priv, power_domain, pref);
>               }
>  
>               seq_printf(m, "Master IER:\t%08x\n",
> @@ -1709,8 +1716,7 @@ static int i915_sr_status(struct seq_file *m, void 
> *unused)
>       intel_wakeref_t wakeref;
>       bool sr_enabled = false;
>  
> -     wakeref = intel_runtime_pm_get(dev_priv);
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +     wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
>  
>       if (INTEL_GEN(dev_priv) >= 9)
>               /* no global SR status; inspect per-plane WM */;
> @@ -1726,8 +1732,7 @@ static int i915_sr_status(struct seq_file *m, void 
> *unused)
>       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>               sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> -     intel_runtime_pm_put(dev_priv, wakeref);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
>  
>       seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index f0a405604b75..44c1b21febba 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -344,6 +344,7 @@ struct intel_csr {
>       uint32_t mmiodata[8];
>       uint32_t dc_state;
>       uint32_t allowed_dc_mask;
> +     intel_wakeref_t wakeref;
>  };
>  
>  enum i915_cache_level {
> @@ -1982,6 +1983,7 @@ struct drm_i915_private {
>                * is a slight delay before we do so.
>                */
>               intel_wakeref_t awake;
> +             intel_wakeref_t power;

This prolly explains the prefs above :)

>  
>               /**
>                * The number of times we have woken up.
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 67fd119bdad8..5ed1c8576525 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -176,7 +176,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
>       if (INTEL_GEN(i915) >= 6)
>               gen6_rps_idle(i915);
>  
> -     intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
> +     intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, i915->gt.power);
>  
>       intel_runtime_pm_put(i915, wakeref);
>  
> @@ -221,7 +221,7 @@ void i915_gem_unpark(struct drm_i915_private *i915)
>        * Work around it by grabbing a GT IRQ power domain whilst there is any
>        * GT activity, preventing any DC state transitions.
>        */
> -     intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
> +     i915->gt.power = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
>  
>       if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
>               i915->gt.epoch = 1;
> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
> index 4dd793b78996..f3a5f03646ce 100644
> --- a/drivers/gpu/drm/i915/icl_dsi.c
> +++ b/drivers/gpu/drm/i915/icl_dsi.c
> @@ -337,9 +337,11 @@ static void gen11_dsi_enable_io_power(struct 
> intel_encoder *encoder)
>       }
>  
>       for_each_dsi_port(port, intel_dsi->ports) {
> -             intel_display_power_get(dev_priv, port == PORT_A ?
> -                                     POWER_DOMAIN_PORT_DDI_A_IO :
> -                                     POWER_DOMAIN_PORT_DDI_B_IO);
> +             intel_dsi->io_wakeref[port] =
> +                     intel_display_power_get(dev_priv,
> +                                             port == PORT_A ?
> +                                             POWER_DOMAIN_PORT_DDI_A_IO :
> +                                             POWER_DOMAIN_PORT_DDI_B_IO);
>       }
>  }
>  
> @@ -1125,10 +1127,18 @@ static void gen11_dsi_disable_io_power(struct 
> intel_encoder *encoder)
>       enum port port;
>       u32 tmp;
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_A_IO);
> -
> -     if (intel_dsi->dual_link)
> -             intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_B_IO);
> +     for_each_dsi_port(port, intel_dsi->ports) {
> +             intel_wakeref_t wakeref;
> +
> +             wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
> +             if (wakeref) {
> +                     intel_display_power_put(dev_priv,
> +                                             port == PORT_A ?
> +                                             POWER_DOMAIN_PORT_DDI_A_IO :
> +                                             POWER_DOMAIN_PORT_DDI_B_IO,
> +                                             wakeref);
> +             }
> +     }

Ok, well. I have been trying to figure out what really is going on here.

First it seems that you fix a bug. We take refs for each dsi port but
only release once special casing 'dual_link' without this patch.

Second, all the hw access is before getting the refs, looking
suspicious.

>  
>       /* set mode to DDI */
>       for_each_dsi_port(port, intel_dsi->ports) {
> @@ -1229,13 +1239,15 @@ static bool gen11_dsi_get_hw_state(struct 
> intel_encoder *encoder,
>  {
>       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> -     u32 tmp;
> -     enum port port;
>       enum transcoder dsi_trans;
> +     intel_wakeref_t wakeref;
> +     enum port port;
>       bool ret = false;
> +     u32 tmp;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                             encoder->power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  encoder->power_domain);
> +     if (!wakeref)
>               return false;
>  
>       for_each_dsi_port(port, intel_dsi->ports) {
> @@ -1260,7 +1272,7 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder 
> *encoder,
>               ret = tmp & PIPECONF_ENABLE;
>       }
>  out:
> -     intel_display_power_put(dev_priv, encoder->power_domain);
> +     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>       return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_audio.c 
> b/drivers/gpu/drm/i915/intel_audio.c
> index 202a58cf2d9f..de26cd0a5497 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -748,7 +748,8 @@ static void i915_audio_component_get_power(struct device 
> *kdev)
>  
>  static void i915_audio_component_put_power(struct device *kdev)
>  {
> -     intel_display_power_put(kdev_to_i915(kdev), POWER_DOMAIN_AUDIO);
> +     intel_display_power_put_unchecked(kdev_to_i915(kdev),
> +                                       POWER_DOMAIN_AUDIO);
>  }
>  
>  static void i915_audio_component_codec_wake_override(struct device *kdev,
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c 
> b/drivers/gpu/drm/i915/intel_cdclk.c
> index 2021e484a287..73cb7250118e 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -520,6 +520,7 @@ static void vlv_set_cdclk(struct drm_i915_private 
> *dev_priv,
>  {
>       int cdclk = cdclk_state->cdclk;
>       u32 val, cmd = cdclk_state->voltage_level;
> +     intel_wakeref_t wakeref;
>  
>       switch (cdclk) {
>       case 400000:
> @@ -539,7 +540,7 @@ static void vlv_set_cdclk(struct drm_i915_private 
> *dev_priv,
>        * a system suspend.  So grab the PIPE-A domain, which covers
>        * the HW blocks needed for the following programming.
>        */
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> +     wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
>  
>       mutex_lock(&dev_priv->pcu_lock);
>       val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> @@ -593,7 +594,7 @@ static void vlv_set_cdclk(struct drm_i915_private 
> *dev_priv,
>  
>       vlv_program_pfi_credits(dev_priv);
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A, wakeref);
>  }
>  
>  static void chv_set_cdclk(struct drm_i915_private *dev_priv,
> @@ -601,6 +602,7 @@ static void chv_set_cdclk(struct drm_i915_private 
> *dev_priv,
>  {
>       int cdclk = cdclk_state->cdclk;
>       u32 val, cmd = cdclk_state->voltage_level;
> +     intel_wakeref_t wakeref;
>  
>       switch (cdclk) {
>       case 333333:
> @@ -619,7 +621,7 @@ static void chv_set_cdclk(struct drm_i915_private 
> *dev_priv,
>        * a system suspend.  So grab the PIPE-A domain, which covers
>        * the HW blocks needed for the following programming.
>        */
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> +     wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
>  
>       mutex_lock(&dev_priv->pcu_lock);
>       val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> @@ -637,7 +639,7 @@ static void chv_set_cdclk(struct drm_i915_private 
> *dev_priv,
>  
>       vlv_program_pfi_credits(dev_priv);
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A, wakeref);
>  }
>  
>  static int bdw_calc_cdclk(int min_cdclk)
> diff --git a/drivers/gpu/drm/i915/intel_crt.c 
> b/drivers/gpu/drm/i915/intel_crt.c
> index 951e9bae6921..33bd2addcbdd 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -83,15 +83,17 @@ static bool intel_crt_get_hw_state(struct intel_encoder 
> *encoder,
>  {
>       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>       struct intel_crt *crt = intel_encoder_to_crt(encoder);
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                             encoder->power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  encoder->power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret = intel_crt_port_enabled(dev_priv, crt->adpa_reg, pipe);
>  
> -     intel_display_power_put(dev_priv, encoder->power_domain);
> +     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -776,6 +778,7 @@ intel_crt_detect(struct drm_connector *connector,
>       struct drm_i915_private *dev_priv = to_i915(connector->dev);
>       struct intel_crt *crt = intel_attached_crt(connector);
>       struct intel_encoder *intel_encoder = &crt->base;
> +     intel_wakeref_t wakeref;
>       int status, ret;
>       struct intel_load_detect_pipe tmp;
>  
> @@ -784,7 +787,8 @@ intel_crt_detect(struct drm_connector *connector,
>                     force);
>  
>       if (i915_modparams.load_detect_test) {
> -             intel_display_power_get(dev_priv, intel_encoder->power_domain);
> +             wakeref = intel_display_power_get(dev_priv,
> +                                               intel_encoder->power_domain);
>               goto load_detect;
>       }
>  
> @@ -792,7 +796,8 @@ intel_crt_detect(struct drm_connector *connector,
>       if (dmi_check_system(intel_spurious_crt_detect))
>               return connector_status_disconnected;
>  
> -     intel_display_power_get(dev_priv, intel_encoder->power_domain);
> +     wakeref = intel_display_power_get(dev_priv,
> +                                       intel_encoder->power_domain);
>  
>       if (I915_HAS_HOTPLUG(dev_priv)) {
>               /* We can not rely on the HPD pin always being correctly wired
> @@ -847,7 +852,7 @@ intel_crt_detect(struct drm_connector *connector,
>       }
>  
>  out:
> -     intel_display_power_put(dev_priv, intel_encoder->power_domain);
> +     intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
>       return status;
>  }
>  
> @@ -857,10 +862,12 @@ static int intel_crt_get_modes(struct drm_connector 
> *connector)
>       struct drm_i915_private *dev_priv = to_i915(dev);
>       struct intel_crt *crt = intel_attached_crt(connector);
>       struct intel_encoder *intel_encoder = &crt->base;
> -     int ret;
> +     intel_wakeref_t wakeref;
>       struct i2c_adapter *i2c;
> +     int ret;
>  
> -     intel_display_power_get(dev_priv, intel_encoder->power_domain);
> +     wakeref = intel_display_power_get(dev_priv,
> +                                       intel_encoder->power_domain);
>  
>       i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
>       ret = intel_crt_ddc_get_modes(connector, i2c);
> @@ -872,7 +879,7 @@ static int intel_crt_get_modes(struct drm_connector 
> *connector)
>       ret = intel_crt_ddc_get_modes(connector, i2c);
>  
>  out:
> -     intel_display_power_put(dev_priv, intel_encoder->power_domain);
> +     intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
>  
>       return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_csr.c 
> b/drivers/gpu/drm/i915/intel_csr.c
> index a516697bf57d..ea5fb64d33dd 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -409,6 +409,21 @@ static uint32_t *parse_csr_fw(struct drm_i915_private 
> *dev_priv,
>       return memcpy(dmc_payload, &fw->data[readcount], nbytes);
>  }
>  
> +static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
> +{
> +     WARN_ON(dev_priv->csr.wakeref);
> +     dev_priv->csr.wakeref =
> +             intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +}
> +
> +static void intel_csr_runtime_pm_put(struct drm_i915_private *dev_priv)
> +{
> +     intel_wakeref_t wakeref __maybe_unused =
> +             fetch_and_zero(&dev_priv->csr.wakeref);
> +
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
> +}
> +
>  static void csr_load_work_fn(struct work_struct *work)
>  {
>       struct drm_i915_private *dev_priv;
> @@ -424,8 +439,7 @@ static void csr_load_work_fn(struct work_struct *work)
>  
>       if (dev_priv->csr.dmc_payload) {
>               intel_csr_load_program(dev_priv);
> -
> -             intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +             intel_csr_runtime_pm_put(dev_priv);
>  
>               DRM_INFO("Finished loading DMC firmware %s (v%u.%u)\n",
>                        dev_priv->csr.fw_path,
> @@ -467,7 +481,7 @@ void intel_csr_ucode_init(struct drm_i915_private 
> *dev_priv)
>        * suspend as runtime suspend *requires* a working CSR for whatever
>        * reason.
>        */
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +     intel_csr_runtime_pm_get(dev_priv);
>  
>       if (INTEL_GEN(dev_priv) >= 12) {
>               /* Allow to load fw via parameter using the last known size */
> @@ -538,7 +552,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private 
> *dev_priv)
>  
>       /* Drop the reference held in case DMC isn't loaded. */
>       if (!dev_priv->csr.dmc_payload)
> -             intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +             intel_csr_runtime_pm_put(dev_priv);
>  }
>  
>  /**
> @@ -558,7 +572,7 @@ void intel_csr_ucode_resume(struct drm_i915_private 
> *dev_priv)
>        * loaded.
>        */
>       if (!dev_priv->csr.dmc_payload)
> -             intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +             intel_csr_runtime_pm_get(dev_priv);
>  }
>  
>  /**
> @@ -574,6 +588,7 @@ void intel_csr_ucode_fini(struct drm_i915_private 
> *dev_priv)
>               return;
>  
>       intel_csr_ucode_suspend(dev_priv);
> +     WARN_ON(dev_priv->csr.wakeref);
>  
>       kfree(dev_priv->csr.dmc_payload);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c 
> b/drivers/gpu/drm/i915/intel_ddi.c
> index 2d6ed990a232..7f3cd055de50 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1860,12 +1860,14 @@ int intel_ddi_toggle_hdcp_signalling(struct 
> intel_encoder *intel_encoder,
>  {
>       struct drm_device *dev = intel_encoder->base.dev;
>       struct drm_i915_private *dev_priv = to_i915(dev);
> +     intel_wakeref_t wakeref;
>       enum pipe pipe = 0;
>       int ret = 0;
>       uint32_t tmp;
>  
> -     if (WARN_ON(!intel_display_power_get_if_enabled(dev_priv,
> -                                             intel_encoder->power_domain)))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  
> intel_encoder->power_domain);
> +     if (WARN_ON(!wakeref))
>               return -ENXIO;
>  
>       if (WARN_ON(!intel_encoder->get_hw_state(intel_encoder, &pipe))) {
> @@ -1880,7 +1882,7 @@ int intel_ddi_toggle_hdcp_signalling(struct 
> intel_encoder *intel_encoder,
>               tmp &= ~TRANS_DDI_HDCP_SIGNALLING;
>       I915_WRITE(TRANS_DDI_FUNC_CTL(pipe), tmp);
>  out:
> -     intel_display_power_put(dev_priv, intel_encoder->power_domain);
> +     intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
>       return ret;
>  }
>  
> @@ -1891,13 +1893,15 @@ bool intel_ddi_connector_get_hw_state(struct 
> intel_connector *intel_connector)
>       struct intel_encoder *encoder = intel_connector->encoder;
>       int type = intel_connector->base.connector_type;
>       enum port port = encoder->port;
> -     enum pipe pipe = 0;
>       enum transcoder cpu_transcoder;
> +     intel_wakeref_t wakeref;
> +     enum pipe pipe = 0;
>       uint32_t tmp;
>       bool ret;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                             encoder->power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  encoder->power_domain);
> +     if (!wakeref)
>               return false;
>  
>       if (!encoder->get_hw_state(encoder, &pipe)) {
> @@ -1939,7 +1943,7 @@ bool intel_ddi_connector_get_hw_state(struct 
> intel_connector *intel_connector)
>       }
>  
>  out:
> -     intel_display_power_put(dev_priv, encoder->power_domain);
> +     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -1950,6 +1954,7 @@ static void intel_ddi_get_encoder_pipes(struct 
> intel_encoder *encoder,
>       struct drm_device *dev = encoder->base.dev;
>       struct drm_i915_private *dev_priv = to_i915(dev);
>       enum port port = encoder->port;
> +     intel_wakeref_t wakeref;
>       enum pipe p;
>       u32 tmp;
>       u8 mst_pipe_mask;
> @@ -1957,8 +1962,9 @@ static void intel_ddi_get_encoder_pipes(struct 
> intel_encoder *encoder,
>       *pipe_mask = 0;
>       *is_dp_mst = false;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                             encoder->power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  encoder->power_domain);
> +     if (!wakeref)
>               return;
>  
>       tmp = I915_READ(DDI_BUF_CTL(port));
> @@ -2029,7 +2035,7 @@ static void intel_ddi_get_encoder_pipes(struct 
> intel_encoder *encoder,
>                                 "(PHY_CTL %08x)\n", port_name(port), tmp);
>       }
>  
> -     intel_display_power_put(dev_priv, encoder->power_domain);
> +     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  }
>  
>  bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
> @@ -3286,7 +3292,8 @@ static void intel_ddi_post_disable_dp(struct 
> intel_encoder *encoder,
>       intel_edp_panel_vdd_on(intel_dp);
>       intel_edp_panel_off(intel_dp);
>  
> -     intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
> +     intel_display_power_put_unchecked(dev_priv,
> +                                       dig_port->ddi_io_power_domain);
>  
>       intel_ddi_clk_disable(encoder);
>  }
> @@ -3306,7 +3313,8 @@ static void intel_ddi_post_disable_hdmi(struct 
> intel_encoder *encoder,
>  
>       intel_disable_ddi_buf(encoder, old_crtc_state);
>  
> -     intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
> +     intel_display_power_put_unchecked(dev_priv,
> +                                       dig_port->ddi_io_power_domain);
>  
>       intel_ddi_clk_disable(encoder);
>  
> @@ -3626,8 +3634,8 @@ intel_ddi_post_pll_disable(struct intel_encoder 
> *encoder,
>  
>       if (intel_crtc_has_dp_encoder(crtc_state) ||
>           intel_port_is_tc(dev_priv, encoder->port))
> -             intel_display_power_put(dev_priv,
> -                                     
> intel_ddi_main_link_aux_domain(dig_port));
> +             intel_display_power_put_unchecked(dev_priv,
> +                                               
> intel_ddi_main_link_aux_domain(dig_port));
>  }
>  
>  void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> diff --git a/drivers/gpu/drm/i915/intel_display.c 
> b/drivers/gpu/drm/i915/intel_display.c
> index b0b8f9ffd873..36c56d1637b8 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1197,17 +1197,19 @@ void assert_pipe(struct drm_i915_private *dev_priv,
>       enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
>                                                                     pipe);
>       enum intel_display_power_domain power_domain;
> +     intel_wakeref_t wakeref;
>  
>       /* we keep both pipes enabled on 830 */
>       if (IS_I830(dev_priv))
>               state = true;
>  
>       power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
> -     if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (wakeref) {
>               u32 val = I915_READ(PIPECONF(cpu_transcoder));
>               cur_state = !!(val & PIPECONF_ENABLE);
>  
> -             intel_display_power_put(dev_priv, power_domain);
> +             intel_display_power_put(dev_priv, power_domain, wakeref);
>       } else {
>               cur_state = false;
>       }
> @@ -3412,6 +3414,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane 
> *plane,
>       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>       enum intel_display_power_domain power_domain;
>       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +     intel_wakeref_t wakeref;
>       bool ret;
>       u32 val;
>  
> @@ -3421,7 +3424,8 @@ static bool i9xx_plane_get_hw_state(struct intel_plane 
> *plane,
>        * display power wells.
>        */
>       power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       val = I915_READ(DSPCNTR(i9xx_plane));
> @@ -3434,7 +3438,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane 
> *plane,
>               *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
>                       DISPPLANE_SEL_PIPE_SHIFT;
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -6107,7 +6111,7 @@ static void modeset_put_power_domains(struct 
> drm_i915_private *dev_priv,
>       enum intel_display_power_domain domain;
>  
>       for_each_power_domain(domain, domains)
> -             intel_display_power_put(dev_priv, domain);
> +             intel_display_power_put_unchecked(dev_priv, domain);
>  }
>  
>  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> @@ -6354,7 +6358,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc 
> *crtc,
>  
>       domains = intel_crtc->enabled_power_domains;
>       for_each_power_domain(domain, domains)
> -             intel_display_power_put(dev_priv, domain);
> +             intel_display_power_put_unchecked(dev_priv, domain);
>       intel_crtc->enabled_power_domains = 0;
>  
>       dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
> @@ -7966,11 +7970,13 @@ static bool i9xx_get_pipe_config(struct intel_crtc 
> *crtc,
>  {
>       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>       enum intel_display_power_domain power_domain;
> +     intel_wakeref_t wakeref;
>       uint32_t tmp;
>       bool ret;
>  
>       power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> @@ -8071,7 +8077,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc 
> *crtc,
>       ret = true;
>  
>  out:
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -9038,11 +9044,13 @@ static bool ironlake_get_pipe_config(struct 
> intel_crtc *crtc,
>       struct drm_device *dev = crtc->base.dev;
>       struct drm_i915_private *dev_priv = to_i915(dev);
>       enum intel_display_power_domain power_domain;
> +     intel_wakeref_t wakeref;
>       uint32_t tmp;
>       bool ret;
>  
>       power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> @@ -9125,7 +9133,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc 
> *crtc,
>       ret = true;
>  
>  out:
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -9734,7 +9742,7 @@ static bool haswell_get_pipe_config(struct intel_crtc 
> *crtc,
>  
>  out:
>       for_each_power_domain(power_domain, power_domain_mask)
> -             intel_display_power_put(dev_priv, power_domain);
> +             intel_display_power_put_unchecked(dev_priv, power_domain);
>  
>       return active;
>  }
> @@ -9984,17 +9992,19 @@ static bool i845_cursor_get_hw_state(struct 
> intel_plane *plane,
>  {
>       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>       enum intel_display_power_domain power_domain;
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
>       power_domain = POWER_DOMAIN_PIPE(PIPE_A);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
>  
>       *pipe = PIPE_A;
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -10217,6 +10227,7 @@ static bool i9xx_cursor_get_hw_state(struct 
> intel_plane *plane,
>  {
>       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>       enum intel_display_power_domain power_domain;
> +     intel_wakeref_t wakeref;
>       bool ret;
>       u32 val;
>  
> @@ -10226,7 +10237,8 @@ static bool i9xx_cursor_get_hw_state(struct 
> intel_plane *plane,
>        * display power wells.
>        */
>       power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       val = I915_READ(CURCNTR(plane->pipe));
> @@ -10239,7 +10251,7 @@ static bool i9xx_cursor_get_hw_state(struct 
> intel_plane *plane,
>               *pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
>                       MCURSOR_PIPE_SELECT_SHIFT;
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -12950,6 +12962,7 @@ static void intel_atomic_commit_tail(struct 
> drm_atomic_state *state)
>       struct drm_crtc *crtc;
>       struct intel_crtc *intel_crtc;
>       u64 put_domains[I915_MAX_PIPES] = {};
> +     intel_wakeref_t wakeref = 0;
>       int i;
>  
>       intel_atomic_commit_fence_wait(intel_state);
> @@ -12957,7 +12970,7 @@ static void intel_atomic_commit_tail(struct 
> drm_atomic_state *state)
>       drm_atomic_helper_wait_for_dependencies(state);
>  
>       if (intel_state->modeset)
> -             intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
> +             wakeref = intel_display_power_get(dev_priv, 
> POWER_DOMAIN_MODESET);
>  
>       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
> new_crtc_state, i) {
>               old_intel_crtc_state = to_intel_crtc_state(old_crtc_state);
> @@ -13094,7 +13107,7 @@ static void intel_atomic_commit_tail(struct 
> drm_atomic_state *state)
>                * the culprit.
>                */
>               intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
> -             intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
> +             intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, 
> wakeref);
>       }
>  
>       /*
> @@ -15496,19 +15509,25 @@ void i915_redisable_vga_power_on(struct 
> drm_i915_private *dev_priv)
>  
>  void i915_redisable_vga(struct drm_i915_private *dev_priv)
>  {
> -     /* This function can be called both from intel_modeset_setup_hw_state or
> +     intel_wakeref_t wakeref;
> +
> +     /*
> +      * This function can be called both from intel_modeset_setup_hw_state or
>        * at a very early point in our resume sequence, where the power well
>        * structures are not yet restored. Since this function is at a very
>        * paranoid "someone might have enabled VGA while we were not looking"
>        * level, just check if the power well is enabled instead of trying to
>        * follow the "don't touch the power well if we don't need it" policy
> -      * the rest of the driver uses. */
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
> +      * the rest of the driver uses.
> +      */
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_VGA);
> +     if (!wakeref)
>               return;
>  
>       i915_redisable_vga_power_on(dev_priv);
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_VGA, wakeref);
>  }
>  
>  /* FIXME read out full plane state for all planes */
> @@ -15808,12 +15827,13 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
>                            struct drm_modeset_acquire_ctx *ctx)
>  {
>       struct drm_i915_private *dev_priv = to_i915(dev);
> -     struct intel_crtc *crtc;
>       struct intel_crtc_state *crtc_state;
>       struct intel_encoder *encoder;
> +     struct intel_crtc *crtc;

Not that I mind but I don't understand the reasoning
behind the change of order on this and on few other places in this
patch.


> +     intel_wakeref_t wakeref;
>       int i;
>  
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +     wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
>  
>       intel_early_display_was(dev_priv);
>       intel_modeset_readout_hw_state(dev);
> @@ -15883,7 +15903,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
>                       modeset_put_power_domains(dev_priv, put_domains);
>       }
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
>  
>       intel_fbc_init_pipe_state(dev_priv);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index d3cd40e656fe..fc85fd77a661 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -621,8 +621,8 @@ static void pps_unlock(struct intel_dp *intel_dp)
>  
>       mutex_unlock(&dev_priv->pps_mutex);
>  
> -     intel_display_power_put(dev_priv,
> -                             
> intel_aux_power_domain(dp_to_dig_port(intel_dp)));
> +     intel_display_power_put_unchecked(dev_priv,
> +                                       
> intel_aux_power_domain(dp_to_dig_port(intel_dp)));
>  }
>  
>  static void
> @@ -2511,8 +2511,8 @@ static void edp_panel_vdd_off_sync(struct intel_dp 
> *intel_dp)
>       if ((pp & PANEL_POWER_ON) == 0)
>               intel_dp->panel_power_off_time = ktime_get_boottime();
>  
> -     intel_display_power_put(dev_priv,
> -                             intel_aux_power_domain(intel_dig_port));
> +     intel_display_power_put_unchecked(dev_priv,
> +                                       
> intel_aux_power_domain(intel_dig_port));
>  }
>  
>  static void edp_panel_vdd_work(struct work_struct *__work)
> @@ -2657,7 +2657,7 @@ static void edp_panel_off(struct intel_dp *intel_dp)
>       intel_dp->panel_power_off_time = ktime_get_boottime();
>  
>       /* We got a reference when we enabled the VDD. */
> -     intel_display_power_put(dev_priv, intel_aux_power_domain(dig_port));
> +     intel_display_power_put_unchecked(dev_priv, 
> intel_aux_power_domain(dig_port));
>  }
>  
>  void intel_edp_panel_off(struct intel_dp *intel_dp)
> @@ -2983,16 +2983,18 @@ static bool intel_dp_get_hw_state(struct 
> intel_encoder *encoder,
>  {
>       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                             encoder->power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  encoder->power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret = intel_dp_port_enabled(dev_priv, intel_dp->output_reg,
>                                   encoder->port, pipe);
>  
> -     intel_display_power_put(dev_priv, encoder->power_domain);
> +     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -5365,12 +5367,13 @@ intel_dp_detect(struct drm_connector *connector,
>       enum drm_connector_status status;
>       enum intel_display_power_domain aux_domain =
>               intel_aux_power_domain(dig_port);
> +     intel_wakeref_t wakeref;
>  
>       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>                     connector->base.id, connector->name);
>       
> WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
>  
> -     intel_display_power_get(dev_priv, aux_domain);
> +     wakeref = intel_display_power_get(dev_priv, aux_domain);
>  
>       /* Can't disconnect eDP */
>       if (intel_dp_is_edp(intel_dp))
> @@ -5436,7 +5439,7 @@ intel_dp_detect(struct drm_connector *connector,
>  
>               ret = intel_dp_retrain_link(encoder, ctx);
>               if (ret) {
> -                     intel_display_power_put(dev_priv, aux_domain);
> +                     intel_display_power_put(dev_priv, aux_domain, wakeref);
>                       return ret;
>               }
>       }
> @@ -5460,7 +5463,7 @@ intel_dp_detect(struct drm_connector *connector,
>       if (status != connector_status_connected && !intel_dp->is_mst)
>               intel_dp_unset_edid(intel_dp);
>  
> -     intel_display_power_put(dev_priv, aux_domain);
> +     intel_display_power_put(dev_priv, aux_domain, wakeref);
>       return status;
>  }
>  
> @@ -5473,6 +5476,7 @@ intel_dp_force(struct drm_connector *connector)
>       struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
>       enum intel_display_power_domain aux_domain =
>               intel_aux_power_domain(dig_port);
> +     intel_wakeref_t wakeref;
>  
>       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>                     connector->base.id, connector->name);
> @@ -5481,11 +5485,11 @@ intel_dp_force(struct drm_connector *connector)
>       if (connector->status != connector_status_connected)
>               return;
>  
> -     intel_display_power_get(dev_priv, aux_domain);
> +     wakeref = intel_display_power_get(dev_priv, aux_domain);
>  
>       intel_dp_set_edid(intel_dp);
>  
> -     intel_display_power_put(dev_priv, aux_domain);
> +     intel_display_power_put(dev_priv, aux_domain, wakeref);
>  }
>  
>  static int intel_dp_get_modes(struct drm_connector *connector)
> @@ -5931,6 +5935,7 @@ intel_dp_hpd_pulse(struct intel_digital_port 
> *intel_dig_port, bool long_hpd)
>       struct intel_dp *intel_dp = &intel_dig_port->dp;
>       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>       enum irqreturn ret = IRQ_NONE;
> +     intel_wakeref_t wakeref;
>  
>       if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {
>               /*
> @@ -5953,8 +5958,8 @@ intel_dp_hpd_pulse(struct intel_digital_port 
> *intel_dig_port, bool long_hpd)
>               return IRQ_NONE;
>       }
>  
> -     intel_display_power_get(dev_priv,
> -                             intel_aux_power_domain(intel_dig_port));
> +     wakeref = intel_display_power_get(dev_priv,
> +                                       
> intel_aux_power_domain(intel_dig_port));
>  
>       if (intel_dp->is_mst) {
>               if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> @@ -5984,7 +5989,8 @@ intel_dp_hpd_pulse(struct intel_digital_port 
> *intel_dig_port, bool long_hpd)
>  
>  put_power:
>       intel_display_power_put(dev_priv,
> -                             intel_aux_power_domain(intel_dig_port));
> +                             intel_aux_power_domain(intel_dig_port),
> +                             wakeref);
>  
>       return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c 
> b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index d513ca875c67..04870e960537 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> @@ -345,9 +345,12 @@ static bool ibx_pch_dpll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>                                     struct intel_dpll_hw_state *hw_state)
>  {
>       const enum intel_dpll_id id = pll->info->id;
> +     intel_wakeref_t wakeref;
>       uint32_t val;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_PLLS);
> +     if (!wakeref)
>               return false;
>  
>       val = I915_READ(PCH_DPLL(id));
> @@ -355,7 +358,7 @@ static bool ibx_pch_dpll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>       hw_state->fp0 = I915_READ(PCH_FP0(id));
>       hw_state->fp1 = I915_READ(PCH_FP1(id));
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>       return val & DPLL_VCO_ENABLE;
>  }
> @@ -509,15 +512,18 @@ static bool hsw_ddi_wrpll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>                                      struct intel_dpll_hw_state *hw_state)
>  {
>       const enum intel_dpll_id id = pll->info->id;
> +     intel_wakeref_t wakeref;
>       uint32_t val;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_PLLS);
> +     if (!wakeref)
>               return false;
>  
>       val = I915_READ(WRPLL_CTL(id));
>       hw_state->wrpll = val;
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>       return val & WRPLL_PLL_ENABLE;
>  }
> @@ -526,15 +532,18 @@ static bool hsw_ddi_spll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>                                     struct intel_shared_dpll *pll,
>                                     struct intel_dpll_hw_state *hw_state)
>  {
> +     intel_wakeref_t wakeref;
>       uint32_t val;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_PLLS);
> +     if (!wakeref)
>               return false;
>  
>       val = I915_READ(SPLL_CTL);
>       hw_state->spll = val;
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>       return val & SPLL_PLL_ENABLE;
>  }
> @@ -989,9 +998,12 @@ static bool skl_ddi_pll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>       uint32_t val;
>       const struct skl_dpll_regs *regs = skl_dpll_regs;
>       const enum intel_dpll_id id = pll->info->id;
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_PLLS);
> +     if (!wakeref)
>               return false;
>  
>       ret = false;
> @@ -1011,7 +1023,7 @@ static bool skl_ddi_pll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>       ret = true;
>  
>  out:
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>       return ret;
>  }
> @@ -1020,12 +1032,15 @@ static bool skl_ddi_dpll0_get_hw_state(struct 
> drm_i915_private *dev_priv,
>                                      struct intel_shared_dpll *pll,
>                                      struct intel_dpll_hw_state *hw_state)
>  {
> -     uint32_t val;
>       const struct skl_dpll_regs *regs = skl_dpll_regs;
>       const enum intel_dpll_id id = pll->info->id;
> +     intel_wakeref_t wakeref;
> +     uint32_t val;
>       bool ret;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_PLLS);
> +     if (!wakeref)
>               return false;
>  
>       ret = false;
> @@ -1041,7 +1056,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct 
> drm_i915_private *dev_priv,
>       ret = true;
>  
>  out:
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>       return ret;
>  }
> @@ -1579,14 +1594,17 @@ static bool bxt_ddi_pll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>                                       struct intel_dpll_hw_state *hw_state)
>  {
>       enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
> -     uint32_t val;
> -     bool ret;
> +     intel_wakeref_t wakeref;
>       enum dpio_phy phy;
>       enum dpio_channel ch;
> +     uint32_t val;
> +     bool ret;
>  
>       bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_PLLS);
> +     if (!wakeref)
>               return false;
>  
>       ret = false;
> @@ -1643,7 +1661,7 @@ static bool bxt_ddi_pll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>       ret = true;
>  
>  out:
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>       return ret;
>  }
> @@ -2091,10 +2109,13 @@ static bool cnl_ddi_pll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>                                    struct intel_dpll_hw_state *hw_state)
>  {
>       const enum intel_dpll_id id = pll->info->id;
> +     intel_wakeref_t wakeref;
>       uint32_t val;
>       bool ret;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_PLLS);
> +     if (!wakeref)
>               return false;
>  
>       ret = false;
> @@ -2113,7 +2134,7 @@ static bool cnl_ddi_pll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>       ret = true;
>  
>  out:
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>       return ret;
>  }
> @@ -2950,11 +2971,14 @@ static bool icl_pll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>                                struct intel_dpll_hw_state *hw_state)
>  {
>       const enum intel_dpll_id id = pll->info->id;
> -     uint32_t val;
> -     enum port port;
> +     intel_wakeref_t wakeref;
>       bool ret = false;
> +     enum port port;
> +     uint32_t val;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  POWER_DOMAIN_PLLS);
> +     if (!wakeref)
>               return false;
>  
>       val = I915_READ(icl_pll_id_to_enable_reg(id));
> @@ -3007,7 +3031,7 @@ static bool icl_pll_get_hw_state(struct 
> drm_i915_private *dev_priv,
>  
>       ret = true;
>  out:
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>       return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index 93c86b19700e..6fa1e6ff0e28 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -2118,12 +2118,21 @@ bool intel_display_power_is_enabled(struct 
> drm_i915_private *dev_priv,
>                                   enum intel_display_power_domain domain);
>  bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
>                                     enum intel_display_power_domain domain);
> -void intel_display_power_get(struct drm_i915_private *dev_priv,
> -                          enum intel_display_power_domain domain);
> -bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
> +intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
>                                       enum intel_display_power_domain domain);
> +intel_wakeref_t
> +intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
> +                                enum intel_display_power_domain domain);
> +void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
> +                                    enum intel_display_power_domain domain);
> +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
>  void intel_display_power_put(struct drm_i915_private *dev_priv,
> -                          enum intel_display_power_domain domain);
> +                          enum intel_display_power_domain domain,
> +                          intel_wakeref_t wakeref);
> +#else
> +#define intel_display_power_put(i915, domain, wakeref) \
> +     intel_display_power_put_unchecked(i915, domain)
> +#endif
>  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>                           u8 req_slices);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dsi.h 
> b/drivers/gpu/drm/i915/intel_dsi.h
> index fc7a09049f81..df3d390e25fe 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.h
> +++ b/drivers/gpu/drm/i915/intel_dsi.h
> @@ -39,6 +39,7 @@ struct intel_dsi {
>       struct intel_encoder base;
>  
>       struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS];
> +     intel_wakeref_t io_wakeref[I915_MAX_PORTS];
>  
>       /* GPIO Desc for CRC based Panel control */
>       struct gpio_desc *gpio_panel;
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
> b/drivers/gpu/drm/i915/intel_hdmi.c
> index 14a0c28fe7c1..14727ac06f67 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1190,15 +1190,17 @@ static bool intel_hdmi_get_hw_state(struct 
> intel_encoder *encoder,
>  {
>       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                             encoder->power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  encoder->power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret = intel_sdvo_port_enabled(dev_priv, intel_hdmi->hdmi_reg, pipe);
>  
> -     intel_display_power_put(dev_priv, encoder->power_domain);
> +     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -1895,11 +1897,12 @@ intel_hdmi_set_edid(struct drm_connector *connector)
>  {
>       struct drm_i915_private *dev_priv = to_i915(connector->dev);
>       struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
> +     intel_wakeref_t wakeref;
>       struct edid *edid;
>       bool connected = false;
>       struct i2c_adapter *i2c;
>  
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +     wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>  
>       i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
>  
> @@ -1914,7 +1917,7 @@ intel_hdmi_set_edid(struct drm_connector *connector)
>  
>       intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
>  
>       to_intel_connector(connector)->detect_edid = edid;
>       if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
> @@ -1939,11 +1942,12 @@ intel_hdmi_detect(struct drm_connector *connector, 
> bool force)
>       struct drm_i915_private *dev_priv = to_i915(connector->dev);
>       struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
>       struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
> +     intel_wakeref_t wakeref;
>  
>       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>                     connector->base.id, connector->name);
>  
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +     wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>  
>       if (IS_ICELAKE(dev_priv) &&
>           !intel_digital_port_connected(encoder))
> @@ -1955,7 +1959,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool 
> force)
>               status = connector_status_connected;
>  
>  out:
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
>  
>       if (status != connector_status_connected)
>               cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
> diff --git a/drivers/gpu/drm/i915/intel_i2c.c 
> b/drivers/gpu/drm/i915/intel_i2c.c
> index c6159aff9dc8..4f6dc8c94634 100644
> --- a/drivers/gpu/drm/i915/intel_i2c.c
> +++ b/drivers/gpu/drm/i915/intel_i2c.c
> @@ -697,12 +697,13 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct 
> i2c_msg *msgs, int num,
>  static int
>  gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
>  {
> -     struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
> -                                            adapter);
> +     struct intel_gmbus *bus =
> +             container_of(adapter, struct intel_gmbus, adapter);
>       struct drm_i915_private *dev_priv = bus->dev_priv;
> +     intel_wakeref_t wakeref;
>       int ret;
>  
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +     wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>  
>       if (bus->force_bit) {
>               ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
> @@ -714,17 +715,16 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg 
> *msgs, int num)
>                       bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
>       }
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
>  
>       return ret;
>  }
>  
>  int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
>  {
> -     struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
> -                                            adapter);
> +     struct intel_gmbus *bus =
> +             container_of(adapter, struct intel_gmbus, adapter);
>       struct drm_i915_private *dev_priv = bus->dev_priv;
> -     int ret;
>       u8 cmd = DRM_HDCP_DDC_AKSV;
>       u8 buf[DRM_HDCP_KSV_LEN] = { 0 };
>       struct i2c_msg msgs[] = {
> @@ -741,8 +741,10 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
>                       .buf = buf,
>               }
>       };
> +     intel_wakeref_t wakeref;
> +     int ret;
>  
> -     intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +     wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>       mutex_lock(&dev_priv->gmbus_mutex);
>  
>       /*
> @@ -753,7 +755,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
>       ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
>  
>       mutex_unlock(&dev_priv->gmbus_mutex);
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +     intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
>  
>       return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c 
> b/drivers/gpu/drm/i915/intel_lvds.c
> index 6adcc8d037bf..b01aacb5d73d 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -94,15 +94,17 @@ static bool intel_lvds_get_hw_state(struct intel_encoder 
> *encoder,
>  {
>       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>       struct intel_lvds_encoder *lvds_encoder = 
> to_lvds_encoder(&encoder->base);
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                             encoder->power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  encoder->power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret = intel_lvds_port_enabled(dev_priv, lvds_encoder->reg, pipe);
>  
> -     intel_display_power_put(dev_priv, encoder->power_domain);
> +     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>       return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c 
> b/drivers/gpu/drm/i915/intel_pipe_crc.c
> index bdabcfab8090..56d614b02302 100644
> --- a/drivers/gpu/drm/i915/intel_pipe_crc.c
> +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c
> @@ -589,6 +589,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, 
> const char *source_name)
>       struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
>       enum intel_display_power_domain power_domain;
>       enum intel_pipe_crc_source source;
> +     intel_wakeref_t wakeref;
>       u32 val = 0; /* shut up gcc */
>       int ret = 0;
>  
> @@ -598,7 +599,8 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, 
> const char *source_name)
>       }
>  
>       power_domain = POWER_DOMAIN_PIPE(crtc->index);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref) {
>               DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
>               return -EIO;
>       }
> @@ -624,7 +626,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, 
> const char *source_name)
>       pipe_crc->skipped = 0;
>  
>  out:
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 83b01cde8113..ab7257720c7e 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3989,10 +3989,12 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc 
> *crtc,
>       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>       enum intel_display_power_domain power_domain;
>       enum pipe pipe = crtc->pipe;
> +     intel_wakeref_t wakeref;
>       enum plane_id plane_id;
>  
>       power_domain = POWER_DOMAIN_PIPE(pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return;
>  
>       for_each_plane_id_on_crtc(crtc, plane_id)
> @@ -4001,7 +4003,7 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>                                          &ddb_y[plane_id],
>                                          &ddb_uv[plane_id]);
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  }
>  
>  void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c 
> b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index f585ef742efe..fd2fc10dd1e4 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -1867,18 +1867,19 @@ __intel_display_power_get_domain(struct 
> drm_i915_private *dev_priv,
>   * Any power domain reference obtained by this function must have a symmetric
>   * call to intel_display_power_put() to release the reference again.
>   */
> -void intel_display_power_get(struct drm_i915_private *dev_priv,
> -                          enum intel_display_power_domain domain)
> +intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
> +                                     enum intel_display_power_domain domain)
>  {
>       struct i915_power_domains *power_domains = &dev_priv->power_domains;
> -
> -     intel_runtime_pm_get(dev_priv);
> +     intel_wakeref_t wakeref = intel_runtime_pm_get(dev_priv);
>  
>       mutex_lock(&power_domains->lock);
>  
>       __intel_display_power_get_domain(dev_priv, domain);
>  
>       mutex_unlock(&power_domains->lock);
> +
> +     return wakeref;
>  }
>  
>  /**
> @@ -1893,13 +1894,16 @@ void intel_display_power_get(struct drm_i915_private 
> *dev_priv,
>   * Any power domain reference obtained by this function must have a symmetric
>   * call to intel_display_power_put() to release the reference again.
>   */
> -bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
> -                                     enum intel_display_power_domain domain)
> +intel_wakeref_t
> +intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
> +                                enum intel_display_power_domain domain)
>  {
>       struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +     intel_wakeref_t wakeref;
>       bool is_enabled;
>  
> -     if (!intel_runtime_pm_get_if_in_use(dev_priv))
> +     wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
> +     if (!wakeref)
>               return false;
>  
>       mutex_lock(&power_domains->lock);
> @@ -1913,23 +1917,16 @@ bool intel_display_power_get_if_enabled(struct 
> drm_i915_private *dev_priv,
>  
>       mutex_unlock(&power_domains->lock);
>  
> -     if (!is_enabled)
> -             intel_runtime_pm_put_unchecked(dev_priv);
> +     if (!is_enabled) {
> +             intel_runtime_pm_put(dev_priv, wakeref);
> +             wakeref = 0;
> +     }
>  
> -     return is_enabled;
> +     return wakeref;
>  }
>  
> -/**
> - * intel_display_power_put - release a power domain reference
> - * @dev_priv: i915 device instance
> - * @domain: power domain to reference
> - *
> - * This function drops the power domain reference obtained by
> - * intel_display_power_get() and might power down the corresponding hardware
> - * block right away if this is the last reference.
> - */
> -void intel_display_power_put(struct drm_i915_private *dev_priv,
> -                          enum intel_display_power_domain domain)
> +static void __intel_display_power_put(struct drm_i915_private *dev_priv,
> +                                   enum intel_display_power_domain domain)
>  {
>       struct i915_power_domains *power_domains;
>       struct i915_power_well *power_well;
> @@ -1947,10 +1944,34 @@ void intel_display_power_put(struct drm_i915_private 
> *dev_priv,
>               intel_power_well_put(dev_priv, power_well);
>  
>       mutex_unlock(&power_domains->lock);
> +}
>  
> +/**
> + * intel_display_power_put - release a power domain reference

+unchecked? or is this in wrong place.

And the perf oa_config unrelated changes are gone. Good.
-Mika

> + * @dev_priv: i915 device instance
> + * @domain: power domain to reference
> + *
> + * This function drops the power domain reference obtained by
> + * intel_display_power_get() and might power down the corresponding hardware
> + * block right away if this is the last reference.
> + */
> +void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
> +                                    enum intel_display_power_domain domain)
> +{
> +     __intel_display_power_put(dev_priv, domain);
>       intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
> +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
> +void intel_display_power_put(struct drm_i915_private *dev_priv,
> +                          enum intel_display_power_domain domain,
> +                          intel_wakeref_t wakeref)
> +{
> +     __intel_display_power_put(dev_priv, domain);
> +     intel_runtime_pm_put(dev_priv, wakeref);
> +}
> +#endif
> +
>  #define I830_PIPES_POWER_DOMAINS (           \
>       BIT_ULL(POWER_DOMAIN_PIPE_A) |          \
>       BIT_ULL(POWER_DOMAIN_PIPE_B) |          \
> @@ -4060,7 +4081,7 @@ void intel_power_domains_fini_hw(struct 
> drm_i915_private *dev_priv)
>  
>       /* Remove the refcount we took to keep power well support disabled. */
>       if (!i915_modparams.disable_power_well)
> -             intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +             intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
>  
>       intel_power_domains_verify_state(dev_priv);
>  }
> @@ -4079,7 +4100,7 @@ void intel_power_domains_fini_hw(struct 
> drm_i915_private *dev_priv)
>   */
>  void intel_power_domains_enable(struct drm_i915_private *dev_priv)
>  {
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +     intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
>  
>       intel_power_domains_verify_state(dev_priv);
>  }
> @@ -4114,7 +4135,7 @@ void intel_power_domains_suspend(struct 
> drm_i915_private *dev_priv,
>  {
>       struct i915_power_domains *power_domains = &dev_priv->power_domains;
>  
> -     intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +     intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
>  
>       /*
>        * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
> @@ -4135,7 +4156,7 @@ 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(dev_priv, POWER_DOMAIN_INIT);
> +             intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
>               intel_power_domains_verify_state(dev_priv);
>       }
>  
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
> b/drivers/gpu/drm/i915/intel_sprite.c
> index 8f3982c03925..87a06fcca284 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -618,17 +618,19 @@ skl_plane_get_hw_state(struct intel_plane *plane,
>       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>       enum intel_display_power_domain power_domain;
>       enum plane_id plane_id = plane->id;
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
>       power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
>  
>       *pipe = plane->pipe;
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -882,17 +884,19 @@ vlv_plane_get_hw_state(struct intel_plane *plane,
>       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>       enum intel_display_power_domain power_domain;
>       enum plane_id plane_id = plane->id;
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
>       power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
>  
>       *pipe = plane->pipe;
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -1051,17 +1055,19 @@ ivb_plane_get_hw_state(struct intel_plane *plane,
>  {
>       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>       enum intel_display_power_domain power_domain;
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
>       power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
>  
>       *pipe = plane->pipe;
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> @@ -1217,17 +1223,19 @@ g4x_plane_get_hw_state(struct intel_plane *plane,
>  {
>       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>       enum intel_display_power_domain power_domain;
> +     intel_wakeref_t wakeref;
>       bool ret;
>  
>       power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return false;
>  
>       ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
>  
>       *pipe = plane->pipe;
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_vdsc.c 
> b/drivers/gpu/drm/i915/intel_vdsc.c
> index 48537827616f..23abf03736e7 100644
> --- a/drivers/gpu/drm/i915/intel_vdsc.c
> +++ b/drivers/gpu/drm/i915/intel_vdsc.c
> @@ -1082,6 +1082,6 @@ void intel_dsc_disable(const struct intel_crtc_state 
> *old_crtc_state)
>       I915_WRITE(dss_ctl2_reg, dss_ctl2_val);
>  
>       /* Disable Power wells for VDSC/joining */
> -     intel_display_power_put(dev_priv,
> -                             intel_dsc_power_domain(old_crtc_state));
> +     intel_display_power_put_unchecked(dev_priv,
> +                                       
> intel_dsc_power_domain(old_crtc_state));
>  }
> diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c
> index bb1287020f80..d116fead8514 100644
> --- a/drivers/gpu/drm/i915/vlv_dsi.c
> +++ b/drivers/gpu/drm/i915/vlv_dsi.c
> @@ -959,13 +959,15 @@ static bool intel_dsi_get_hw_state(struct intel_encoder 
> *encoder,
>  {
>       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> +     intel_wakeref_t wakeref;
>       enum port port;
>       bool active = false;
>  
>       DRM_DEBUG_KMS("\n");
>  
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> -                                             encoder->power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv,
> +                                                  encoder->power_domain);
> +     if (!wakeref)
>               return false;
>  
>       /*
> @@ -1021,7 +1023,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder 
> *encoder,
>       }
>  
>  out_put_power:
> -     intel_display_power_put(dev_priv, encoder->power_domain);
> +     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>       return active;
>  }
> @@ -1574,6 +1576,7 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector 
> *connector)
>       enum drm_panel_orientation orientation;
>       struct intel_plane *plane;
>       struct intel_crtc *crtc;
> +     intel_wakeref_t wakeref;
>       enum pipe pipe;
>       u32 val;
>  
> @@ -1584,7 +1587,8 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector 
> *connector)
>       plane = to_intel_plane(crtc->base.primary);
>  
>       power_domain = POWER_DOMAIN_PIPE(pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +     if (!wakeref)
>               return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
>  
>       val = I915_READ(DSPCNTR(plane->i9xx_plane));
> @@ -1596,7 +1600,7 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector 
> *connector)
>       else
>               orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
>  
> -     intel_display_power_put(dev_priv, power_domain);
> +     intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>       return orientation;
>  }
> -- 
> 2.20.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to