On Wed, Mar 19, 2014 at 05:07:53PM +0200, Imre Deak wrote:
> On Fri, 2014-03-07 at 20:08 -0300, Paulo Zanoni wrote:
> > From: Paulo Zanoni <paulo.r.zan...@intel.com>
> > 
> > Currently, when our driver becomes idle for i915.pc8_timeout (default:
> > 5s) we enable PC8, so we save some power, but not everything we can.
> > Then, while PC8 is enabled, if we stay idle for more
> > autosuspend_delay_ms (default: 10s) we'll enter runtime PM and put the
> > graphics device in D3 state, saving even more power. The two features
> > are separate things with increasing levels of power savings, but if we
> > disable PC8 we'll never get into D3.
> > 
> > While from the modularity point of view it would be nice to keep these
> > features as separate, we have reasons to merge them:
> >  - We are not aware of anybody wanting a "PC8 without D3" environment.
> >  - If we keep both features as separate, we'll have to to test both
> >    PC8 and PC8+D3 code paths. We're already having a major pain to
> >    make QA do automated testing of just one thing, testing both paths
> >    will cost even more.
> >  - Only Haswell+ supports PC8, so if we want to add runtime PM support
> >    to, for example, IVB, we'll have to copy some code from the PC8
> >    feature to runtime PM, so merging both features as a single thing
> >    will make it easier for enabling runtime PM on other platforms.
> > 
> > This patch only does the very basic steps required to have PC8 and
> > runtime PM merged on a single feature: the next patches will take care
> > of cleaning up everything.
> > 
> > v2: - Rebase.
> > v3: - Rebase.
> >     - Fully remove the deprecated i915 params since Daniel doesn't
> >       consider them as part of the ABI.
> > v4: - Rebase.
> >     - Fix typo in the commit message.
> > v5: - Rebase, again.
> >     - Add a huge comment explaining the different forcewake usage
> >       (Chris, Daniel).
> >     - Use open-coded forcewake functions (Daniel).
> > 
> > Signed-off-by: Paulo Zanoni <paulo.r.zan...@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_dma.c      |  2 --
> >  drivers/gpu/drm/i915/i915_drv.c      |  8 +++++
> >  drivers/gpu/drm/i915/i915_drv.h      |  7 ++--
> >  drivers/gpu/drm/i915/i915_params.c   | 10 ------
> >  drivers/gpu/drm/i915/intel_display.c | 65 
> > ++++++++++++++++--------------------
> >  drivers/gpu/drm/i915/intel_drv.h     |  3 +-
> >  drivers/gpu/drm/i915/intel_pm.c      |  1 -
> >  7 files changed, 43 insertions(+), 53 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_dma.c 
> > b/drivers/gpu/drm/i915/i915_dma.c
> > index e4d2b9f..6aa23af 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -1822,8 +1822,6 @@ int i915_driver_unload(struct drm_device *dev)
> >     cancel_work_sync(&dev_priv->gpu_error.work);
> >     i915_destroy_error_state(dev);
> >  
> > -   cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
> > -
> >     if (dev->pdev->msi_enabled)
> >             pci_disable_msi(dev->pdev);
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c 
> > b/drivers/gpu/drm/i915/i915_drv.c
> > index 658fe24..6178c95 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -848,6 +848,9 @@ static int i915_runtime_suspend(struct device *device)
> >  
> >     DRM_DEBUG_KMS("Suspending device\n");
> >  
> > +   if (HAS_PC8(dev))
> > +           __hsw_do_enable_pc8(dev_priv);
> > +
> >     i915_gem_release_all_mmaps(dev_priv);
> >  
> >     del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
> > @@ -862,6 +865,7 @@ static int i915_runtime_suspend(struct device *device)
> >      */
> >     intel_opregion_notify_adapter(dev, PCI_D1);
> >  
> > +   DRM_DEBUG_KMS("Device suspended\n");
> >     return 0;
> >  }
> >  
> > @@ -878,6 +882,10 @@ static int i915_runtime_resume(struct device *device)
> >     intel_opregion_notify_adapter(dev, PCI_D0);
> >     dev_priv->pm.suspended = false;
> >  
> > +   if (HAS_PC8(dev))
> > +           __hsw_do_disable_pc8(dev_priv);
> > +
> > +   DRM_DEBUG_KMS("Device resumed\n");
> >     return 0;
> >  }
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h 
> > b/drivers/gpu/drm/i915/i915_drv.h
> > index 2a319ba..a5f1780 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1335,6 +1335,10 @@ struct ilk_wm_values {
> >  /*
> >   * This struct tracks the state needed for the Package C8+ feature.
> >   *
> > + * TODO: we're merging the Package C8+ feature with the runtime PM 
> > support. To
> > + * avoid having to update the documentation at each patch of the series, 
> > we'll
> > + * do a final update at the end.
> > + *
> >   * Package states C8 and deeper are really deep PC states that can only be
> >   * reached when all the devices on the system allow it, so even if the 
> > graphics
> >   * device allows PC8+, it doesn't mean the system will actually get to 
> > these
> > @@ -1388,7 +1392,6 @@ struct i915_package_c8 {
> >     bool enabled;
> >     int disable_count;
> >     struct mutex lock;
> > -   struct delayed_work enable_work;
> >  
> >     struct {
> >             uint32_t deimr;
> > @@ -2092,8 +2095,6 @@ struct i915_params {
> >     unsigned int preliminary_hw_support;
> >     int disable_power_well;
> >     int enable_ips;
> > -   int enable_pc8;
> > -   int pc8_timeout;
> >     int invert_brightness;
> >     int enable_cmd_parser;
> >     /* leave bools at the end to not create holes */
> > diff --git a/drivers/gpu/drm/i915/i915_params.c 
> > b/drivers/gpu/drm/i915/i915_params.c
> > index a66ffb6..d1d7980 100644
> > --- a/drivers/gpu/drm/i915/i915_params.c
> > +++ b/drivers/gpu/drm/i915/i915_params.c
> > @@ -42,8 +42,6 @@ struct i915_params i915 __read_mostly = {
> >     .disable_power_well = 1,
> >     .enable_ips = 1,
> >     .fastboot = 0,
> > -   .enable_pc8 = 1,
> > -   .pc8_timeout = 5000,
> >     .prefault_disable = 0,
> >     .reset = true,
> >     .invert_brightness = 0,
> > @@ -135,14 +133,6 @@ module_param_named(fastboot, i915.fastboot, bool, 
> > 0600);
> >  MODULE_PARM_DESC(fastboot,
> >     "Try to skip unnecessary mode sets at boot time (default: false)");
> >  
> > -module_param_named(enable_pc8, i915.enable_pc8, int, 0600);
> > -MODULE_PARM_DESC(enable_pc8,
> > -   "Enable support for low power package C states (PC8+) (default: true)");
> > -
> > -module_param_named(pc8_timeout, i915.pc8_timeout, int, 0600);
> > -MODULE_PARM_DESC(pc8_timeout,
> > -   "Number of msecs of idleness required to enter PC8+ (default: 5000)");
> > -
> >  module_param_named(prefault_disable, i915.prefault_disable, bool, 0600);
> >  MODULE_PARM_DESC(prefault_disable,
> >     "Disable page prefaulting for pread/pwrite/reloc (default:false). "
> > diff --git a/drivers/gpu/drm/i915/intel_display.c 
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 9c3e2c5..ab02848 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -6726,6 +6726,7 @@ static void hsw_disable_lcpll(struct drm_i915_private 
> > *dev_priv,
> >  static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
> >  {
> >     uint32_t val;
> > +   unsigned long irqflags;
> >  
> >     val = I915_READ(LCPLL_CTL);
> >  
> > @@ -6733,9 +6734,22 @@ static void hsw_restore_lcpll(struct 
> > drm_i915_private *dev_priv)
> >                 LCPLL_POWER_DOWN_ALLOW)) == LCPLL_PLL_LOCK)
> >             return;
> >  
> > -   /* Make sure we're not on PC8 state before disabling PC8, otherwise
> > -    * we'll hang the machine! */
> > -   gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
> > +   /*
> > +    * Make sure we're not on PC8 state before disabling PC8, otherwise
> 
> While at it the above comment could be clarified. For me 'before
> enabling PLL, which also disables PC8' would be clearer, if that's what
> was meant.

I think we can do this comment polishing later on.

> > +    * we'll hang the machine. To prevent PC8 state, just enable force_wake.
> > +    *
> > +    * The other problem is that hsw_restore_lcpll() is called as part of
> > +    * the runtime PM resume sequence, so we can't just call
> > +    * gen6_gt_force_wake_get() because that function calls
> > +    * intel_runtime_pm_get(), and we can't change the runtime PM refcount
> > +    * while we are on the resume sequence. So to solve this problem we have
> > +    * to call special forcewake code that doesn't touch runtime PM and
> > +    * doesn't enable the forcewake delayed work.
> > +    */
> > +   spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> > +   if (dev_priv->uncore.forcewake_count++ == 0)
> > +           dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
> > +   spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> >  
> >     if (val & LCPLL_POWER_DOWN_ALLOW) {
> >             val &= ~LCPLL_POWER_DOWN_ALLOW;
> > @@ -6769,14 +6783,20 @@ static void hsw_restore_lcpll(struct 
> > drm_i915_private *dev_priv)
> >                     DRM_ERROR("Switching back to LCPLL failed\n");
> >     }
> >  
> > -   gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
> > +   /* See the big comment above. */
> > +   spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> > +   if (--dev_priv->uncore.forcewake_count == 0)
> > +           dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
> > +   spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> 
> For clarity I would group these in separate functions with the rest of
> force wake helpers in intel_uncore.c.

tbh we currently have a rather big mess with all our forcewake functions
and the setup/init code. Before we encapsulate things like crazy I think
we should work out all the existing little bugs and races we have :(
> 
> Otherwise looks good, so with the above fixed:
> Reviewed-by: Imre Deak <imre.d...@intel.com>

Thanks for patches&review, merged it all to dinq.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to