[Intel-gfx] [PATCH] drm/i915/gen9: Probe power well 1 status on dc status query

Chris Wilson chris at chris-wilson.co.uk
Tue Jan 26 09:07:24 PST 2016


On Tue, Jan 26, 2016 at 05:45:31PM +0200, Mika Kuoppala wrote:
> There has been cases where we read DC_STATE and get something that we
> did not write there. As DMC owns power well 1, this could be that DMC
> snoops DC_STATE accesses and needs to wake up power well 1 up to serve
> the access. But the waking up power well 1 takes time and we might end up
> reading during unfinished well wakeup.
> 
> When we want the dc status, wake up DMC and make sure that DMC has
> properly woken up well 1 before we read for the final value.
> 
> References: https://bugs.freedesktop.org/show_bug.cgi?id=93768
> Suggested-by: Patrik Jakobsson <patrik.jakobsson at linux.intel.com>
> Cc: Patrik Jakobsson <patrik.jakobsson at linux.intel.com>
> Cc: Imre Deak <imre.deak at intel.com>
> Cc: Chris Wilson <chris at chris-wilson.co.uk>
> Signed-off-by: Mika Kuoppala <mika.kuoppala at intel.com>
> ---
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 86 ++++++++++++++++++++++++++-------
>  1 file changed, 69 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index bbca527184d0..83c24e73cb88 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -418,15 +418,62 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  	BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS)) |	\
>  	BIT(POWER_DOMAIN_INIT))
>  
> +
> +static bool __gen9_power_well_enabled(struct drm_i915_private *dev_priv,
> +				      const enum skl_disp_power_wells pw,
> +				      const bool req)
> +{
> +	uint32_t mask = SKL_POWER_WELL_STATE(pw);
> +
> +	if (req)
> +		mask |= SKL_POWER_WELL_REQ(pw);
> +
> +	return (I915_READ(HSW_PWR_WELL_DRIVER) & mask) == mask;
> +}
> +
> +static bool gen9_power_well_enabled(struct drm_i915_private *dev_priv,
> +				    const enum skl_disp_power_wells pw)
> +{
> +	return __gen9_power_well_enabled(dev_priv, pw, true);
> +}
> +
> +static bool gen9_power_well_enabled_noreq(struct drm_i915_private *dev_priv,
> +					  const enum skl_disp_power_wells pw)
> +{
> +	return __gen9_power_well_enabled(dev_priv, pw, false);
> +}
> +

> +static bool gen9_pw1_enabled(struct drm_i915_private *dev_priv)

Jumping around between conventions for function names?

> +{
> +	/* DMC owns the pw1. Don't check for request */
> +	return gen9_power_well_enabled_noreq(dev_priv, SKL_DISP_PW_1);
> +}
> +
> +static u32 gen9_get_dc_state(struct drm_i915_private *dev_priv)
> +{
> +	if (gen9_pw1_enabled(dev_priv))
> +		return I915_READ(DC_STATE_EN);
> +
> +	/* DMC should snoop this and wakeup */
> +	I915_READ(DC_STATE_EN);
> +
> +	if (wait_for(gen9_pw1_enabled(dev_priv), 1))
> +		DRM_ERROR("pw1 enabling timeout 0x%x\n",
> +			  I915_READ(HSW_PWR_WELL_DRIVER));

	if (!gen9_powerwell_1_enabled(dev_priv)) {
		/* DMC should snoop this and wakeup */
		I915_READ(DC_STATE_EN);

		/* And wait for it to wakeup */
		if (wait_for(gen9_pw1_enabled(dev_priv), 1))
			DRM_ERROR("pw1 enabling timeout 0x%x\n",
				  I915_READ(HSW_PWR_WELL_DRIVER));
	}

> +	return I915_READ(DC_STATE_EN);
> +}

Reads a bit better

> @@ -762,7 +810,11 @@ static void skl_power_well_disable(struct drm_i915_private *dev_priv,
>  static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
>  					   struct i915_power_well *power_well)
>  {
> -	return (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0;
> +	if (gen9_pw1_enabled(dev_priv))
> +		return (I915_READ(DC_STATE_EN) &
> +			DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0;
> +
> +	return true;

/* Please explain this!
if (!gen9_powerwell_1_enabled(dev_priv))
	return true;

return (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0;

Again looks a little easier on the eyes.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the Intel-gfx mailing list