diff mbox series

[RFC,1/8] drm/i915: Introduce intel_runtime_pm_disable to pair intel_runtime_pm_enable

Message ID 20180810071138.30138-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show
Series [RFC,1/8] drm/i915: Introduce intel_runtime_pm_disable to pair intel_runtime_pm_enable | expand

Commit Message

Chris Wilson Aug. 10, 2018, 7:11 a.m. UTC
Currently, we cancel the extra wakeref we have for !runtime-pm devices
inside power_wells_fini_hw. However, this is not strictly paired with
the acquisition of that wakeref in runtime_pm_enable (as the fini_hw may
be called on errors paths before we even call runtime_pm_enable). Make
the symmetry more explicit and include a check that we do release all of
our rpm wakerefs.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_drv.c         |  8 ++++++--
 drivers/gpu/drm/i915/intel_drv.h        |  1 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 24 +++++++++++++++---------
 3 files changed, 22 insertions(+), 11 deletions(-)

Comments

Imre Deak Aug. 10, 2018, 12:22 p.m. UTC | #1
On Fri, Aug 10, 2018 at 08:11:31AM +0100, Chris Wilson wrote:
> Currently, we cancel the extra wakeref we have for !runtime-pm devices
> inside power_wells_fini_hw. However, this is not strictly paired with
> the acquisition of that wakeref in runtime_pm_enable (as the fini_hw may
> be called on errors paths before we even call runtime_pm_enable). Make
> the symmetry more explicit and include a check that we do release all of
> our rpm wakerefs.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_drv.c         |  8 ++++++--
>  drivers/gpu/drm/i915/intel_drv.h        |  1 +
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 24 +++++++++++++++---------
>  3 files changed, 22 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 9dce55182c3a..62ef105a241d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1281,6 +1281,8 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
>  	 */
>  	if (INTEL_INFO(dev_priv)->num_pipes)
>  		drm_kms_helper_poll_init(dev);
> +
> +	intel_runtime_pm_enable(dev_priv);
>  }
>  
>  /**
> @@ -1289,6 +1291,8 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
>   */
>  static void i915_driver_unregister(struct drm_i915_private *dev_priv)
>  {
> +	intel_runtime_pm_disable(dev_priv);
> +
>  	intel_fbdev_unregister(dev_priv);
>  	intel_audio_deinit(dev_priv);
>  
> @@ -1408,8 +1412,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  
>  	i915_driver_register(dev_priv);
>  
> -	intel_runtime_pm_enable(dev_priv);
> -
>  	intel_init_ipc(dev_priv);
>  
>  	intel_runtime_pm_put(dev_priv);
> @@ -1474,6 +1476,8 @@ void i915_driver_unload(struct drm_device *dev)
>  	i915_driver_cleanup_mmio(dev_priv);
>  
>  	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +
> +	WARN_ON(atomic_read(&dev_priv->runtime_pm.wakeref_count));

This probably WARNs atm at least due to having a low-level
pm_runtime_put_autosuspend() in intel_runtime_pm_enable(); but a
corresponding intel_runtime_pm_get() in intel_power_domains_fini_hw() (via
intel_display_set_init_power) which is i915 specific. The following
would fix that:

diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index e209edbc561d..1623c0d2cf57 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -3806,6 +3806,10 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
 	 */
 	intel_display_set_init_power(dev_priv, true);
 
+	/* Hand over RPM reference to PM core */
+	pm_runtime_get_noresume(kdev);
+	intel_runtime_pm_put(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);

>  }
>  
>  static void i915_driver_release(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 0601abb8c71f..dc6c0cec9b36 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1956,6 +1956,7 @@ void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
>  void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume);
>  void bxt_display_core_uninit(struct drm_i915_private *dev_priv);
>  void intel_runtime_pm_enable(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_disable(struct drm_i915_private *dev_priv);
>  const char *
>  intel_display_power_domain_str(enum intel_display_power_domain domain);
>  
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index e209edbc561d..b78c3b48aa62 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -3793,8 +3793,6 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
>   */
>  void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
>  {
> -	struct device *kdev = &dev_priv->drm.pdev->dev;
> -
>  	/*
>  	 * The i915.ko module is still not prepared to be loaded when
>  	 * the power well is not enabled, so just enable it in case
> @@ -3809,13 +3807,6 @@ 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);
> -
> -	/*
> -	 * Remove the refcount we took in intel_runtime_pm_enable() in case
> -	 * the platform doesn't support runtime PM.
> -	 */
> -	if (!HAS_RUNTIME_PM(dev_priv))
> -		pm_runtime_put(kdev);
>  }
>  
>  /**
> @@ -4074,3 +4065,18 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
>  	 */
>  	pm_runtime_put_autosuspend(kdev);
>  }
> +
> +void intel_runtime_pm_disable(struct drm_i915_private *dev_priv)
> +{
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
> +	struct device *kdev = &pdev->dev;
> +
> +	pm_runtime_dont_use_autosuspend(kdev);
> +
> +	/*
> +	 * Remove the refcount we took in intel_runtime_pm_enable() in case
> +	 * the platform doesn't support runtime PM.
> +	 */
> +	if (!HAS_RUNTIME_PM(dev_priv))
> +		pm_runtime_put(kdev);
> +}
> -- 
> 2.18.0
>
Chris Wilson Aug. 10, 2018, 12:33 p.m. UTC | #2
Quoting Imre Deak (2018-08-10 13:22:43)
> On Fri, Aug 10, 2018 at 08:11:31AM +0100, Chris Wilson wrote:
> > @@ -1474,6 +1476,8 @@ void i915_driver_unload(struct drm_device *dev)
> >       i915_driver_cleanup_mmio(dev_priv);
> >  
> >       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> > +
> > +     WARN_ON(atomic_read(&dev_priv->runtime_pm.wakeref_count));
> 
> This probably WARNs atm at least due to having a low-level
> pm_runtime_put_autosuspend() in intel_runtime_pm_enable(); but a
> corresponding intel_runtime_pm_get() in intel_power_domains_fini_hw() (via
> intel_display_set_init_power) which is i915 specific. The following
> would fix that:

It gets caught out by the very last display_set_init_power indeed. I
mean to have a word with you about that function ;)

The issue we have with intel_display_set_init_power() at the moment is
that we don't always clean up it correctly as it not obvious who is
responsible for it at any time. Would it be possible to make that into
local POWER_DOMAIN_INIT grabs so the onion is always clear? (It wasn't
obvious to me why ownership was being transferred fairly arbitrary.)

> 
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index e209edbc561d..1623c0d2cf57 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -3806,6 +3806,10 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
>          */
>         intel_display_set_init_power(dev_priv, true);

In this case this would be much clearer as a raw
	intel_power_domain_get(POWER_DOMAIN_INIT)
I think.
-Chris
Imre Deak Aug. 10, 2018, 2:01 p.m. UTC | #3
On Fri, Aug 10, 2018 at 01:33:19PM +0100, Chris Wilson wrote:
> Quoting Imre Deak (2018-08-10 13:22:43)
> > On Fri, Aug 10, 2018 at 08:11:31AM +0100, Chris Wilson wrote:
> > > @@ -1474,6 +1476,8 @@ void i915_driver_unload(struct drm_device *dev)
> > >       i915_driver_cleanup_mmio(dev_priv);
> > >  
> > >       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> > > +
> > > +     WARN_ON(atomic_read(&dev_priv->runtime_pm.wakeref_count));
> > 
> > This probably WARNs atm at least due to having a low-level
> > pm_runtime_put_autosuspend() in intel_runtime_pm_enable(); but a
> > corresponding intel_runtime_pm_get() in intel_power_domains_fini_hw() (via
> > intel_display_set_init_power) which is i915 specific. The following
> > would fix that:
> 
> It gets caught out by the very last display_set_init_power indeed. I
> mean to have a word with you about that function ;)
> 
> The issue we have with intel_display_set_init_power() at the moment is
> that we don't always clean up it correctly as it not obvious who is
> responsible for it at any time. Would it be possible to make that into
> local POWER_DOMAIN_INIT grabs so the onion is always clear? (It wasn't
> obvious to me why ownership was being transferred fairly arbitrary.)

Yes, would be much clearer. One thing that depends on it is driver
loading / resume expecting any power wells enabled by BIOS to stay enabled
until the end of display HW readout. I can take a look at the exact
dependencies there and remove the use of intel_display_set_init_power().

> > 
> > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > index e209edbc561d..1623c0d2cf57 100644
> > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > @@ -3806,6 +3806,10 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
> >          */
> >         intel_display_set_init_power(dev_priv, true);
> 
> In this case this would be much clearer as a raw
> 	intel_power_domain_get(POWER_DOMAIN_INIT)
> I think.

Yes, but would have to change it in sync with the
intel_display_set_init_power() in intel_power_domains_init_hw(). An
error somewhere after that and before the end of HW readout would make
the above intel_display_set_init_power() a nop.

--Imre
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 9dce55182c3a..62ef105a241d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1281,6 +1281,8 @@  static void i915_driver_register(struct drm_i915_private *dev_priv)
 	 */
 	if (INTEL_INFO(dev_priv)->num_pipes)
 		drm_kms_helper_poll_init(dev);
+
+	intel_runtime_pm_enable(dev_priv);
 }
 
 /**
@@ -1289,6 +1291,8 @@  static void i915_driver_register(struct drm_i915_private *dev_priv)
  */
 static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 {
+	intel_runtime_pm_disable(dev_priv);
+
 	intel_fbdev_unregister(dev_priv);
 	intel_audio_deinit(dev_priv);
 
@@ -1408,8 +1412,6 @@  int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	i915_driver_register(dev_priv);
 
-	intel_runtime_pm_enable(dev_priv);
-
 	intel_init_ipc(dev_priv);
 
 	intel_runtime_pm_put(dev_priv);
@@ -1474,6 +1476,8 @@  void i915_driver_unload(struct drm_device *dev)
 	i915_driver_cleanup_mmio(dev_priv);
 
 	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+
+	WARN_ON(atomic_read(&dev_priv->runtime_pm.wakeref_count));
 }
 
 static void i915_driver_release(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0601abb8c71f..dc6c0cec9b36 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1956,6 +1956,7 @@  void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
 void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume);
 void bxt_display_core_uninit(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_enable(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_disable(struct drm_i915_private *dev_priv);
 const char *
 intel_display_power_domain_str(enum intel_display_power_domain domain);
 
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index e209edbc561d..b78c3b48aa62 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -3793,8 +3793,6 @@  void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
  */
 void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
 {
-	struct device *kdev = &dev_priv->drm.pdev->dev;
-
 	/*
 	 * The i915.ko module is still not prepared to be loaded when
 	 * the power well is not enabled, so just enable it in case
@@ -3809,13 +3807,6 @@  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);
-
-	/*
-	 * Remove the refcount we took in intel_runtime_pm_enable() in case
-	 * the platform doesn't support runtime PM.
-	 */
-	if (!HAS_RUNTIME_PM(dev_priv))
-		pm_runtime_put(kdev);
 }
 
 /**
@@ -4074,3 +4065,18 @@  void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
 	 */
 	pm_runtime_put_autosuspend(kdev);
 }
+
+void intel_runtime_pm_disable(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	struct device *kdev = &pdev->dev;
+
+	pm_runtime_dont_use_autosuspend(kdev);
+
+	/*
+	 * Remove the refcount we took in intel_runtime_pm_enable() in case
+	 * the platform doesn't support runtime PM.
+	 */
+	if (!HAS_RUNTIME_PM(dev_priv))
+		pm_runtime_put(kdev);
+}