[Intel-gfx] [PATCH 16/21] drm/i915: Markup paired operations on display power domains

Mika Kuoppala mika.kuoppala at linux.intel.com
Thu Jan 10 15:51:33 UTC 2019


Chris Wilson <chris at 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 <chris at chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula at 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


More information about the Intel-gfx mailing list