[Intel-gfx] [PATCH 1/1] drm/i915: Adding Gfx Clock, Wake and Gunit save/restore logic in PM suspend/resume paths.

Sagar Arun Kamble sagar.a.kamble at intel.com
Fri Aug 8 08:52:44 CEST 2014


Hi Daniel,
On Mon, 2014-08-04 at 10:07 +0200, Daniel Vetter wrote:
> On Fri, Aug 01, 2014 at 12:34:56PM +0530, sagar.a.kamble at intel.com wrote:
> > From: Sagar Kamble <sagar.a.kamble at intel.com>
> > 
> > Sequence to get gfx clocks on/off, allow/disallow wake and save/restore of gunit registers need to be followed in
> > PM suspend and resume path similar to runtime suspend and resume.
> > 
> > v2:
> > 1. Keeping GT access, wake, gunit save/restore related helpers static.
> > 2. Moved GT access check, Wake Control, Gunit state save to end of i915_drm_freeze.
> > 3. Reusing the sequence in runtime_suspend/resume path at macro level.
> > 
> > Cc: Imre Deak <imre.deak at intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni at intel.com>
> > Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
> > Cc: Jani Nikula <jani.nikula at linux.intel.com>
> > Cc: Goel, Akash <akash.goel at intel.com>
> > Change-Id: I15cfdeeec9c976d9839bb281f809664f4a0c78a2
> > Signed-off-by: Sagar Kamble <sagar.a.kamble at intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c | 39 +++++++++++++++++++++++++++++++++------
> >  drivers/gpu/drm/i915/i915_drv.h |  1 +
> >  2 files changed, 34 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 6c4b25c..385dc74 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -490,11 +490,16 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
> >  	return true;
> >  }
> >  
> > +static int vlv_runtime_suspend(struct drm_i915_private *dev_priv);
> > +static int vlv_runtime_resume(struct drm_i915_private *dev_priv,
> > +				bool resume_from_s0ix);
> > +
> >  static int i915_drm_freeze(struct drm_device *dev)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	struct drm_crtc *crtc;
> >  	pci_power_t opregion_target_state;
> > +	int ret = 0;
> >  
> >  	/* ignore lid events during suspend */
> >  	mutex_lock(&dev_priv->modeset_restore_lock);
> > @@ -562,7 +567,12 @@ static int i915_drm_freeze(struct drm_device *dev)
> >  
> >  	intel_display_set_init_power(dev_priv, false);
> >  
> > -	return 0;
> > +	/* Save Gunit State and clear wake - Need to make sure
> > +	 * changes in vlv_runtime_suspend path don't impact this path */
> > +	if (IS_VALLEYVIEW(dev))
> > +		ret = vlv_runtime_suspend(dev_priv);
> 
> Maybe I wasn't clear, but I absolutely don't want any IS_VLV additions to
> core resume/thaw code. This should be shovelled into the runtime pm
> handling code, which should be reused in the suspend/resume code.
This piece of code does not fit into any of the power well get/put path.
Its specific sequence that need to be followed in VLV when Gunit gets
power gated. So we have to keep this IS_VLV related functionality in
both runtime and pm suspend/resume.
> 
> > +
> > +	return ret;
> >  }
> >  
> >  int i915_suspend(struct drm_device *dev, pm_message_t state)
> > @@ -610,6 +620,12 @@ void intel_console_resume(struct work_struct *work)
> >  static int i915_drm_thaw_early(struct drm_device *dev)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	int ret = 0;
> > +
> > +	/* Restore Gunit State and allow wake - Need to make sure
> > +	 * changes in vlv_runtime_resume path don't impact this path */
> > +	if (IS_VALLEYVIEW(dev))
> > +		ret = vlv_runtime_resume(dev_priv, true);
> >  
> >  	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> >  		hsw_disable_pc8(dev_priv);
> > @@ -618,7 +634,7 @@ static int i915_drm_thaw_early(struct drm_device *dev)
> >  	intel_uncore_sanitize(dev);
> >  	intel_power_domains_init_hw(dev_priv);
> >  
> > -	return 0;
> > +	return ret;
> >  }
> >  
> >  static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
> > @@ -1098,6 +1114,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> >  	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
> >  	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
> >  	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
> > +	s->dpio_cfg_data	= I915_READ(DPIO_CTL);
> >  
> >  	/*
> >  	 * Not saving any of:
> > @@ -1192,6 +1209,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> >  	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
> >  	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
> >  	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
> > +	I915_WRITE(DPIO_CTL,			s->dpio_cfg_data);
> >  }
> >  
> >  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> > @@ -1291,6 +1309,8 @@ static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
> >  	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
> >  }
> >  
> > +/* This function is used in system suspend path as well to utilize
> > + * Gfx clock, Wake control, Gunit state save related functionaility */
> >  static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
> >  {
> >  	u32 mask;
> > @@ -1331,7 +1351,12 @@ err1:
> >  	return err;
> >  }
> >  
> > -static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
> > +/* This function is used in system resume path as well to utilize
> > + * Gfx clock, Wake control, Gunit state restore related functionaility.
> > + * GEM and other initialization will differ which will be controlled by
> > + * resume_from_s0ix variable */
> > +static int vlv_runtime_resume(struct drm_i915_private *dev_priv,
> > +				bool resume_from_s0ix)
> >  {
> >  	struct drm_device *dev = dev_priv->dev;
> >  	int err;
> > @@ -1356,8 +1381,10 @@ static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
> >  
> >  	vlv_check_no_gt_access(dev_priv);
> >  
> > -	intel_init_clock_gating(dev);
> > -	i915_gem_restore_fences(dev);
> > +	if (!resume_from_s0ix) {
> > +		intel_init_clock_gating(dev);
> > +		i915_gem_restore_fences(dev);
> > +	}
> 
> This essentially amounts to another IS_VLV block. I might be able to live
> with a generic "supports runtime pm check".
> 
> >  
> >  	return ret;
> >  }
> > @@ -1462,7 +1489,7 @@ static int intel_runtime_resume(struct device *device)
> >  	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> >  		ret = hsw_runtime_resume(dev_priv);
> >  	} else if (IS_VALLEYVIEW(dev)) {
> > -		ret = vlv_runtime_resume(dev_priv);
> > +		ret = vlv_runtime_resume(dev_priv, false);
> >  	} else {
> >  		WARN_ON(1);
> >  		ret = -ENODEV;
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index d604f4f..3a836c9 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -910,6 +910,7 @@ struct vlv_s0ix_state {
> >  	u32 gu_ctl0;
> >  	u32 gu_ctl1;
> >  	u32 clock_gate_dis2;
> > +	u32 dpio_cfg_data;
> 
> Register save/restore files considered evil. I've let vlv slip through,
> but I really want people to try harder to avoid these. The correct fix is
> to pimp the clock_gating_init functions and similar places to make sure we
> don't just keep the right value around, but also reinit in all places
> correctly.
> -Daniel





More information about the Intel-gfx mailing list