Message ID | 1438291229-7541-4-git-send-email-paulo.r.zanoni@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Jul 30, 2015 at 06:20:28PM -0300, Paulo Zanoni wrote: > From: Damien Lespiau <damien.lespiau@intel.com> > > Before this patch, we used the intel_display_power_{get,put} functions > to make sure the PW1 and Misc I/O power wells were enabled all the > time while LCPLL was enabled. We called a get() at > intel_ddi_pll_init() when we discovered that LCPLL was enabled, then > we would call put/get at skl_{un,}init_cdclk(). > > The problem is that skl_uninit_cdclk() is indirectly called by > intel_runtime_suspend(). So it will only release its power well > _after_ we already decided to runtime suspend. But since we only > decide to runtime suspend after all power wells and refcounts are > released, that basically means we will never decide to runtime > suspend. > > So what this patch does to fix that problem is move the PW1 + Misc I/O > power well handling out of the runtime PM mechanism: instead of > calling intel_display_power_{get_put} - functions that touch the > refcount -, we'll call the low level intel_power_well_{en,dis}able, > which don't change the refcount. This way, it is now possible for the > refcount to actually reach zero, and we'll now start runtime > suspending/resuming. > > v2 (from Paulo): > - Write a commit message since the original patch left it empty. > - Rebase after the intel_power_well_{en,dis}able rename. > - Use lookup_power_well() instead of hardcoded indexes. > > Testcase: igt/pm_rpm/rte (and every other rpm test) > Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> > Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> This is imo too much of a hack. If we go with this then we should either completely remove the pw1 and misc pw from the power well code and just directly call the relevant functions. Or we fix up the ordering and stop lcpll before dropping pw1, which probably means that skl dp aux and gmbus need to adjust their divisors for every transaction since those change when lcpll changes. I don't really have clue about which is the right option, but it seems like dmc will take control of pw1&pw-misc anyway, so probably we don't need to manage them explicitly on skl anyway. -Daniel > --- > drivers/gpu/drm/i915/intel_ddi.c | 2 -- > drivers/gpu/drm/i915/intel_display.c | 5 +++-- > drivers/gpu/drm/i915/intel_drv.h | 2 ++ > drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++++++++++++ > 4 files changed, 34 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c > index 9a40bfb..e629ad3 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -2931,8 +2931,6 @@ void intel_ddi_pll_init(struct drm_device *dev) > dev_priv->skl_boot_cdclk = cdclk_freq; > if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) > DRM_ERROR("LCPLL1 is disabled\n"); > - else > - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); > } else if (IS_BROXTON(dev)) { > broxton_init_cdclk(dev); > broxton_ddi_phy_init(dev); > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 43b0f17..34cbe4a 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -5680,7 +5680,8 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv) > if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1)) > DRM_ERROR("Couldn't disable DPLL0\n"); > > - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); > + /* disable PG1 and Misc I/O */ > + skl_pw1_misc_io_fini(dev_priv); > } > > void skl_init_cdclk(struct drm_i915_private *dev_priv) > @@ -5693,7 +5694,7 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) > I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE); > > /* enable PG1 and Misc I/O */ > - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); > + skl_pw1_misc_io_init(dev_priv); > > /* DPLL0 already enabed !? */ > if (I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE) { > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 320c9e6..10e8a2f 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -1325,6 +1325,8 @@ void intel_psr_single_frame_update(struct drm_device *dev, > int intel_power_domains_init(struct drm_i915_private *); > void intel_power_domains_fini(struct drm_i915_private *); > void intel_power_domains_init_hw(struct drm_i915_private *dev_priv); > +void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv); > +void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv); > void intel_runtime_pm_enable(struct drm_i915_private *dev_priv); > > bool intel_display_power_is_enabled(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 821644d..d62b030 100644 > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c > @@ -1505,6 +1505,35 @@ static struct i915_power_well skl_power_wells[] = { > }, > }; > > +void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv) > +{ > + struct i915_power_well *well; > + > + if (!IS_SKYLAKE(dev_priv)) > + return; > + > + well = lookup_power_well(dev_priv, SKL_DISP_PW_1); > + intel_power_well_enable(dev_priv, well); > + > + well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); > + intel_power_well_enable(dev_priv, well); > +} > + > +void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv) > +{ > + struct i915_power_well *well; > + > + if (!IS_SKYLAKE(dev_priv)) > + return; > + > + well = lookup_power_well(dev_priv, SKL_DISP_PW_1); > + intel_power_well_disable(dev_priv, well); > + > + well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); > + intel_power_well_disable(dev_priv, well); > + > +} > + > static struct i915_power_well bxt_power_wells[] = { > { > .name = "always-on", > -- > 2.4.6 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
2015-08-05 5:30 GMT-03:00 Daniel Vetter <daniel@ffwll.ch>: > On Thu, Jul 30, 2015 at 06:20:28PM -0300, Paulo Zanoni wrote: >> From: Damien Lespiau <damien.lespiau@intel.com> >> >> Before this patch, we used the intel_display_power_{get,put} functions >> to make sure the PW1 and Misc I/O power wells were enabled all the >> time while LCPLL was enabled. We called a get() at >> intel_ddi_pll_init() when we discovered that LCPLL was enabled, then >> we would call put/get at skl_{un,}init_cdclk(). >> >> The problem is that skl_uninit_cdclk() is indirectly called by >> intel_runtime_suspend(). So it will only release its power well >> _after_ we already decided to runtime suspend. But since we only >> decide to runtime suspend after all power wells and refcounts are >> released, that basically means we will never decide to runtime >> suspend. >> >> So what this patch does to fix that problem is move the PW1 + Misc I/O >> power well handling out of the runtime PM mechanism: instead of >> calling intel_display_power_{get_put} - functions that touch the >> refcount -, we'll call the low level intel_power_well_{en,dis}able, >> which don't change the refcount. This way, it is now possible for the >> refcount to actually reach zero, and we'll now start runtime >> suspending/resuming. >> >> v2 (from Paulo): >> - Write a commit message since the original patch left it empty. >> - Rebase after the intel_power_well_{en,dis}able rename. >> - Use lookup_power_well() instead of hardcoded indexes. >> >> Testcase: igt/pm_rpm/rte (and every other rpm test) >> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> >> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> >> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > > This is imo too much of a hack. If we go with this then we should either > completely remove the pw1 and misc pw from the power well code and just > directly call the relevant functions. What do you mean by "the relevant functions"? Notice that the patch already moved us outside of the "power domains" framework, but not the "power wells" framework, since those are actual power wells. I'm still trying to fully understand what you wanted here. > > Or we fix up the ordering and stop lcpll before dropping pw1, which > probably means that skl dp aux and gmbus need to adjust their divisors for > every transaction since those change when lcpll changes. > > I don't really have clue about which is the right option, but it seems > like dmc will take control of pw1&pw-misc anyway, so probably we don't > need to manage them explicitly on skl anyway. > -Daniel > >> --- >> drivers/gpu/drm/i915/intel_ddi.c | 2 -- >> drivers/gpu/drm/i915/intel_display.c | 5 +++-- >> drivers/gpu/drm/i915/intel_drv.h | 2 ++ >> drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++++++++++++ >> 4 files changed, 34 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c >> index 9a40bfb..e629ad3 100644 >> --- a/drivers/gpu/drm/i915/intel_ddi.c >> +++ b/drivers/gpu/drm/i915/intel_ddi.c >> @@ -2931,8 +2931,6 @@ void intel_ddi_pll_init(struct drm_device *dev) >> dev_priv->skl_boot_cdclk = cdclk_freq; >> if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) >> DRM_ERROR("LCPLL1 is disabled\n"); >> - else >> - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); >> } else if (IS_BROXTON(dev)) { >> broxton_init_cdclk(dev); >> broxton_ddi_phy_init(dev); >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c >> index 43b0f17..34cbe4a 100644 >> --- a/drivers/gpu/drm/i915/intel_display.c >> +++ b/drivers/gpu/drm/i915/intel_display.c >> @@ -5680,7 +5680,8 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv) >> if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1)) >> DRM_ERROR("Couldn't disable DPLL0\n"); >> >> - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); >> + /* disable PG1 and Misc I/O */ >> + skl_pw1_misc_io_fini(dev_priv); >> } >> >> void skl_init_cdclk(struct drm_i915_private *dev_priv) >> @@ -5693,7 +5694,7 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) >> I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE); >> >> /* enable PG1 and Misc I/O */ >> - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); >> + skl_pw1_misc_io_init(dev_priv); >> >> /* DPLL0 already enabed !? */ >> if (I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE) { >> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h >> index 320c9e6..10e8a2f 100644 >> --- a/drivers/gpu/drm/i915/intel_drv.h >> +++ b/drivers/gpu/drm/i915/intel_drv.h >> @@ -1325,6 +1325,8 @@ void intel_psr_single_frame_update(struct drm_device *dev, >> int intel_power_domains_init(struct drm_i915_private *); >> void intel_power_domains_fini(struct drm_i915_private *); >> void intel_power_domains_init_hw(struct drm_i915_private *dev_priv); >> +void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv); >> +void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv); >> void intel_runtime_pm_enable(struct drm_i915_private *dev_priv); >> >> bool intel_display_power_is_enabled(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 821644d..d62b030 100644 >> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c >> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c >> @@ -1505,6 +1505,35 @@ static struct i915_power_well skl_power_wells[] = { >> }, >> }; >> >> +void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv) >> +{ >> + struct i915_power_well *well; >> + >> + if (!IS_SKYLAKE(dev_priv)) >> + return; >> + >> + well = lookup_power_well(dev_priv, SKL_DISP_PW_1); >> + intel_power_well_enable(dev_priv, well); >> + >> + well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); >> + intel_power_well_enable(dev_priv, well); >> +} >> + >> +void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv) >> +{ >> + struct i915_power_well *well; >> + >> + if (!IS_SKYLAKE(dev_priv)) >> + return; >> + >> + well = lookup_power_well(dev_priv, SKL_DISP_PW_1); >> + intel_power_well_disable(dev_priv, well); >> + >> + well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); >> + intel_power_well_disable(dev_priv, well); >> + >> +} >> + >> static struct i915_power_well bxt_power_wells[] = { >> { >> .name = "always-on", >> -- >> 2.4.6 >> >> _______________________________________________ >> Intel-gfx mailing list >> Intel-gfx@lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Wed, Aug 05, 2015 at 03:28:54PM -0300, Paulo Zanoni wrote: > 2015-08-05 5:30 GMT-03:00 Daniel Vetter <daniel@ffwll.ch>: > > On Thu, Jul 30, 2015 at 06:20:28PM -0300, Paulo Zanoni wrote: > >> From: Damien Lespiau <damien.lespiau@intel.com> > >> > >> Before this patch, we used the intel_display_power_{get,put} functions > >> to make sure the PW1 and Misc I/O power wells were enabled all the > >> time while LCPLL was enabled. We called a get() at > >> intel_ddi_pll_init() when we discovered that LCPLL was enabled, then > >> we would call put/get at skl_{un,}init_cdclk(). > >> > >> The problem is that skl_uninit_cdclk() is indirectly called by > >> intel_runtime_suspend(). So it will only release its power well > >> _after_ we already decided to runtime suspend. But since we only > >> decide to runtime suspend after all power wells and refcounts are > >> released, that basically means we will never decide to runtime > >> suspend. > >> > >> So what this patch does to fix that problem is move the PW1 + Misc I/O > >> power well handling out of the runtime PM mechanism: instead of > >> calling intel_display_power_{get_put} - functions that touch the > >> refcount -, we'll call the low level intel_power_well_{en,dis}able, > >> which don't change the refcount. This way, it is now possible for the > >> refcount to actually reach zero, and we'll now start runtime > >> suspending/resuming. > >> > >> v2 (from Paulo): > >> - Write a commit message since the original patch left it empty. > >> - Rebase after the intel_power_well_{en,dis}able rename. > >> - Use lookup_power_well() instead of hardcoded indexes. > >> > >> Testcase: igt/pm_rpm/rte (and every other rpm test) > >> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> > >> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > >> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > > > > This is imo too much of a hack. If we go with this then we should either > > completely remove the pw1 and misc pw from the power well code and just > > directly call the relevant functions. > > What do you mean by "the relevant functions"? Notice that the patch > already moved us outside of the "power domains" framework, but not the > "power wells" framework, since those are actual power wells. I'm still > trying to fully understand what you wanted here. The power wells abstraction doesn't buy anything here if we have a power well that we always enable/disable with something else (device rpm here). So instead of the lookup_power_well + enable call just remove pw1 and pw-misc from the list of power wells and call the enable code directly. Otherwise we just have a bit of abstraction that gets in the way. Also note that dmc has similar requirements of enable pw1 and lcpll together to avoid upsetting the firmware. The overall idea is that abstraction should only be used when it actually makes sense for a given platform. And I think using power wells abstraction for pw1 and pw-misc on skl doesn't make sense since we can't actually use it as an independent power well from the software pov - the hw itself is different, but that's all managed by dmc firmware for us. -Daniel
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 9a40bfb..e629ad3 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2931,8 +2931,6 @@ void intel_ddi_pll_init(struct drm_device *dev) dev_priv->skl_boot_cdclk = cdclk_freq; if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) DRM_ERROR("LCPLL1 is disabled\n"); - else - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); } else if (IS_BROXTON(dev)) { broxton_init_cdclk(dev); broxton_ddi_phy_init(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 43b0f17..34cbe4a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5680,7 +5680,8 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv) if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1)) DRM_ERROR("Couldn't disable DPLL0\n"); - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + /* disable PG1 and Misc I/O */ + skl_pw1_misc_io_fini(dev_priv); } void skl_init_cdclk(struct drm_i915_private *dev_priv) @@ -5693,7 +5694,7 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE); /* enable PG1 and Misc I/O */ - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + skl_pw1_misc_io_init(dev_priv); /* DPLL0 already enabed !? */ if (I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 320c9e6..10e8a2f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1325,6 +1325,8 @@ void intel_psr_single_frame_update(struct drm_device *dev, int intel_power_domains_init(struct drm_i915_private *); void intel_power_domains_fini(struct drm_i915_private *); void intel_power_domains_init_hw(struct drm_i915_private *dev_priv); +void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv); +void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv); void intel_runtime_pm_enable(struct drm_i915_private *dev_priv); bool intel_display_power_is_enabled(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 821644d..d62b030 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1505,6 +1505,35 @@ static struct i915_power_well skl_power_wells[] = { }, }; +void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv) +{ + struct i915_power_well *well; + + if (!IS_SKYLAKE(dev_priv)) + return; + + well = lookup_power_well(dev_priv, SKL_DISP_PW_1); + intel_power_well_enable(dev_priv, well); + + well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); + intel_power_well_enable(dev_priv, well); +} + +void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv) +{ + struct i915_power_well *well; + + if (!IS_SKYLAKE(dev_priv)) + return; + + well = lookup_power_well(dev_priv, SKL_DISP_PW_1); + intel_power_well_disable(dev_priv, well); + + well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); + intel_power_well_disable(dev_priv, well); + +} + static struct i915_power_well bxt_power_wells[] = { { .name = "always-on",