diff mbox

drm/i915: Only write watermark registers if a pipe is active

Message ID 1457044041-13978-1-git-send-email-matthew.d.roper@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Matt Roper March 3, 2016, 10:27 p.m. UTC
If all pipes are off, then we may have entered runtime suspend and
writing these registers will have no effect anyway.  When a pipe is
re-enabled, it's crtc_enable will take care of programming appropriate
watermark values.

Cc: arun.siluvery@linux.intel.com
Cc: ville.syrjala@linux.intel.com
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94349
Fixes: ed4a6a7ca853 ("drm/i915: Add two-stage ILK-style watermark programming (v11)")
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
I've still been unable to reproduce this defect on my SNB system; none of the
suggested tests people have noted in Bugzilla have triggered it for me.  But
based on the stack trace I'm guessing that the problem happens because we've
disabled the last pipe and gone into runtime suspend before we get around to
optimizing the watermarks.

I'm not super familiar with the details of runtime PM, so if there's a better
way this should be handled, I'm open to suggestions.

 drivers/gpu/drm/i915/intel_pm.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Comments

Ville Syrjälä March 4, 2016, 10:52 a.m. UTC | #1
On Thu, Mar 03, 2016 at 02:27:21PM -0800, Matt Roper wrote:
> If all pipes are off, then we may have entered runtime suspend and
> writing these registers will have no effect anyway.  When a pipe is
> re-enabled, it's crtc_enable will take care of programming appropriate
> watermark values.
> 
> Cc: arun.siluvery@linux.intel.com
> Cc: ville.syrjala@linux.intel.com
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94349
> Fixes: ed4a6a7ca853 ("drm/i915: Add two-stage ILK-style watermark programming (v11)")
> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> ---
> I've still been unable to reproduce this defect on my SNB system; none of the
> suggested tests people have noted in Bugzilla have triggered it for me.  But
> based on the stack trace I'm guessing that the problem happens because we've
> disabled the last pipe and gone into runtime suspend before we get around to
> optimizing the watermarks.
> 
> I'm not super familiar with the details of runtime PM, so if there's a better
> way this should be handled, I'm open to suggestions.

This definitely feels like papering over the problem. Why is the modeset
code still calling watermark updates at the wrong time?

With my original two stage wm code most wm updates got kicked off from
the plane commits stage, and the only manual calls were in plaform
specific code just before a new pipe is enabled, or just after one is
disabled. Very little room for these sorts of errors in that scheme.
What we have currently isn't done like that and instead it seems to
me we've somehow sprinkled stuff all over some common codepaths which
apparently leads to these problems.

> 
>  drivers/gpu/drm/i915/intel_pm.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index f65e841..8c7fddf 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2802,8 +2802,6 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
>  		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
>  	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2])
>  		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
> -
> -	dev_priv->wm.hw = *results;
>  }
>  
>  bool ilk_disable_lp_wm(struct drm_device *dev)
> @@ -3731,7 +3729,10 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
>  
>  	ilk_compute_wm_results(dev, best_lp_wm, partitioning, &results);
>  
> -	ilk_write_wm_values(dev_priv, &results);
> +	if (config.num_pipes_active > 0)
> +		ilk_write_wm_values(dev_priv, &results);
> +
> +	dev_priv->wm.hw = results;
>  }
>  
>  static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
> -- 
> 2.1.4
Matt Roper March 4, 2016, 11:49 p.m. UTC | #2
On Fri, Mar 04, 2016 at 12:52:41PM +0200, Ville Syrjälä wrote:
> On Thu, Mar 03, 2016 at 02:27:21PM -0800, Matt Roper wrote:
> > If all pipes are off, then we may have entered runtime suspend and
> > writing these registers will have no effect anyway.  When a pipe is
> > re-enabled, it's crtc_enable will take care of programming appropriate
> > watermark values.
> > 
> > Cc: arun.siluvery@linux.intel.com
> > Cc: ville.syrjala@linux.intel.com
> > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94349
> > Fixes: ed4a6a7ca853 ("drm/i915: Add two-stage ILK-style watermark programming (v11)")
> > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> > ---
> > I've still been unable to reproduce this defect on my SNB system; none of the
> > suggested tests people have noted in Bugzilla have triggered it for me.  But
> > based on the stack trace I'm guessing that the problem happens because we've
> > disabled the last pipe and gone into runtime suspend before we get around to
> > optimizing the watermarks.
> > 
> > I'm not super familiar with the details of runtime PM, so if there's a better
> > way this should be handled, I'm open to suggestions.
> 
> This definitely feels like papering over the problem. Why is the modeset
> code still calling watermark updates at the wrong time?
> 
> With my original two stage wm code most wm updates got kicked off from
> the plane commits stage, and the only manual calls were in plaform
> specific code just before a new pipe is enabled, or just after one is
> disabled. Very little room for these sorts of errors in that scheme.
> What we have currently isn't done like that and instead it seems to
> me we've somehow sprinkled stuff all over some common codepaths which
> apparently leads to these problems.

I don't think moving the second stage of watermark programming into
device-specific code is the direction we want to go.  You're still under
vblank evasion at that point, so you can't wait for vblanks, but even if
you could you'd be adding a lot of unnecessary/redundant wait time.  The
model we have now is to call the 'optimize' helper as soon as we're done
with the post-update vblank waiting.  In simplified pseudo-code, the
logic is:

    for each crtc in state {
        drm_atomic_helper_commit_planes_on_crtc()  // does vbl evade
    }

    if (!legacy cursor hack)
        intel_atomic_wait_for_vblanks();

    for each crtc in state {
        intel_post_plane_update();
    }

    if (modeset)
        intel_display_power_put()

    for each crtc in state
        optimize watermarks

For our code today, I guess the proper fix is to move the optimize step
up above the display power put; looks like that PM code changed around a
bit while this series was being rebased, so I think the power put was
located elsewhere before.  It could even be moved into the
post_plane_update function if we wanted, but I had kept it separate
since ultimately it's going to move out of the atomic_commit altogether.

Longer term, we'll actually be doing the optimize asynchronously via a
workqueue task or something (so at an arbitrary future time after the
commit is complete); at that point it's even more likely that things
have powered down, so I imagine we'll either need to grab the power
reference before optimizing watermarks or else just not bother
programming them at all in cases where everything is off (which is the
approach this patch took).

Anyway, I'll post another patch to move the optimize call up before we
drop the power reference; that should also fix the problem as I
understand it.


Matt

> 
> > 
> >  drivers/gpu/drm/i915/intel_pm.c | 7 ++++---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index f65e841..8c7fddf 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2802,8 +2802,6 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
> >  		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
> >  	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2])
> >  		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
> > -
> > -	dev_priv->wm.hw = *results;
> >  }
> >  
> >  bool ilk_disable_lp_wm(struct drm_device *dev)
> > @@ -3731,7 +3729,10 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
> >  
> >  	ilk_compute_wm_results(dev, best_lp_wm, partitioning, &results);
> >  
> > -	ilk_write_wm_values(dev_priv, &results);
> > +	if (config.num_pipes_active > 0)
> > +		ilk_write_wm_values(dev_priv, &results);
> > +
> > +	dev_priv->wm.hw = results;
> >  }
> >  
> >  static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
> > -- 
> > 2.1.4
> 
> -- 
> Ville Syrjälä
> ntel OTC
Ville Syrjälä March 7, 2016, 2:29 p.m. UTC | #3
On Fri, Mar 04, 2016 at 03:49:02PM -0800, Matt Roper wrote:
> On Fri, Mar 04, 2016 at 12:52:41PM +0200, Ville Syrjälä wrote:
> > On Thu, Mar 03, 2016 at 02:27:21PM -0800, Matt Roper wrote:
> > > If all pipes are off, then we may have entered runtime suspend and
> > > writing these registers will have no effect anyway.  When a pipe is
> > > re-enabled, it's crtc_enable will take care of programming appropriate
> > > watermark values.
> > > 
> > > Cc: arun.siluvery@linux.intel.com
> > > Cc: ville.syrjala@linux.intel.com
> > > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94349
> > > Fixes: ed4a6a7ca853 ("drm/i915: Add two-stage ILK-style watermark programming (v11)")
> > > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> > > ---
> > > I've still been unable to reproduce this defect on my SNB system; none of the
> > > suggested tests people have noted in Bugzilla have triggered it for me.  But
> > > based on the stack trace I'm guessing that the problem happens because we've
> > > disabled the last pipe and gone into runtime suspend before we get around to
> > > optimizing the watermarks.
> > > 
> > > I'm not super familiar with the details of runtime PM, so if there's a better
> > > way this should be handled, I'm open to suggestions.
> > 
> > This definitely feels like papering over the problem. Why is the modeset
> > code still calling watermark updates at the wrong time?
> > 
> > With my original two stage wm code most wm updates got kicked off from
> > the plane commits stage, and the only manual calls were in plaform
> > specific code just before a new pipe is enabled, or just after one is
> > disabled. Very little room for these sorts of errors in that scheme.
> > What we have currently isn't done like that and instead it seems to
> > me we've somehow sprinkled stuff all over some common codepaths which
> > apparently leads to these problems.
> 
> I don't think moving the second stage of watermark programming into
> device-specific code is the direction we want to go.

In my book the second stage shouldn't even be part of the modeset
sequence, and instead if should just be done from a vblank work/etc.
which is how I did it.

And the first stage stuff is clearly hardware specific since the
behavhoir of the wm registers is hardware specific, so trying to
shoehorn it all into the common code is IMO a mistake.

> You're still under
> vblank evasion at that point, so you can't wait for vblanks, but even if
> you could you'd be adding a lot of unnecessary/redundant wait time.  The
> model we have now is to call the 'optimize' helper as soon as we're done
> with the post-update vblank waiting.  In simplified pseudo-code, the
> logic is:
> 
>     for each crtc in state {
>         drm_atomic_helper_commit_planes_on_crtc()  // does vbl evade
>     }
> 
>     if (!legacy cursor hack)
>         intel_atomic_wait_for_vblanks();
> 
>     for each crtc in state {
>         intel_post_plane_update();
>     }
> 
>     if (modeset)
>         intel_display_power_put()
> 
>     for each crtc in state
>         optimize watermarks
> 
> For our code today, I guess the proper fix is to move the optimize step
> up above the display power put; looks like that PM code changed around a
> bit while this series was being rebased, so I think the power put was
> located elsewhere before.  It could even be moved into the
> post_plane_update function if we wanted, but I had kept it separate
> since ultimately it's going to move out of the atomic_commit altogether.
> 
> Longer term, we'll actually be doing the optimize asynchronously via a
> workqueue task or something (so at an arbitrary future time after the
> commit is complete); at that point it's even more likely that things
> have powered down, so I imagine we'll either need to grab the power
> reference before optimizing watermarks or else just not bother
> programming them at all in cases where everything is off (which is the
> approach this patch took).
> 
> Anyway, I'll post another patch to move the optimize call up before we
> drop the power reference; that should also fix the problem as I
> understand it.
> 
> 
> Matt
> 
> > 
> > > 
> > >  drivers/gpu/drm/i915/intel_pm.c | 7 ++++---
> > >  1 file changed, 4 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > index f65e841..8c7fddf 100644
> > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > @@ -2802,8 +2802,6 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
> > >  		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
> > >  	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2])
> > >  		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
> > > -
> > > -	dev_priv->wm.hw = *results;
> > >  }
> > >  
> > >  bool ilk_disable_lp_wm(struct drm_device *dev)
> > > @@ -3731,7 +3729,10 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
> > >  
> > >  	ilk_compute_wm_results(dev, best_lp_wm, partitioning, &results);
> > >  
> > > -	ilk_write_wm_values(dev_priv, &results);
> > > +	if (config.num_pipes_active > 0)
> > > +		ilk_write_wm_values(dev_priv, &results);
> > > +
> > > +	dev_priv->wm.hw = results;
> > >  }
> > >  
> > >  static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
> > > -- 
> > > 2.1.4
> > 
> > -- 
> > Ville Syrjälä
> > ntel OTC
> 
> -- 
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
Matt Roper March 7, 2016, 7:09 p.m. UTC | #4
On Mon, Mar 07, 2016 at 04:29:04PM +0200, Ville Syrjälä wrote:
> On Fri, Mar 04, 2016 at 03:49:02PM -0800, Matt Roper wrote:
> > On Fri, Mar 04, 2016 at 12:52:41PM +0200, Ville Syrjälä wrote:
> > > On Thu, Mar 03, 2016 at 02:27:21PM -0800, Matt Roper wrote:
> > > > If all pipes are off, then we may have entered runtime suspend and
> > > > writing these registers will have no effect anyway.  When a pipe is
> > > > re-enabled, it's crtc_enable will take care of programming appropriate
> > > > watermark values.
> > > > 
> > > > Cc: arun.siluvery@linux.intel.com
> > > > Cc: ville.syrjala@linux.intel.com
> > > > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94349
> > > > Fixes: ed4a6a7ca853 ("drm/i915: Add two-stage ILK-style watermark programming (v11)")
> > > > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> > > > ---
> > > > I've still been unable to reproduce this defect on my SNB system; none of the
> > > > suggested tests people have noted in Bugzilla have triggered it for me.  But
> > > > based on the stack trace I'm guessing that the problem happens because we've
> > > > disabled the last pipe and gone into runtime suspend before we get around to
> > > > optimizing the watermarks.
> > > > 
> > > > I'm not super familiar with the details of runtime PM, so if there's a better
> > > > way this should be handled, I'm open to suggestions.
> > > 
> > > This definitely feels like papering over the problem. Why is the modeset
> > > code still calling watermark updates at the wrong time?
> > > 
> > > With my original two stage wm code most wm updates got kicked off from
> > > the plane commits stage, and the only manual calls were in plaform
> > > specific code just before a new pipe is enabled, or just after one is
> > > disabled. Very little room for these sorts of errors in that scheme.
> > > What we have currently isn't done like that and instead it seems to
> > > me we've somehow sprinkled stuff all over some common codepaths which
> > > apparently leads to these problems.
> > 
> > I don't think moving the second stage of watermark programming into
> > device-specific code is the direction we want to go.
> 
> In my book the second stage shouldn't even be part of the modeset
> sequence, and instead if should just be done from a vblank work/etc.
> which is how I did it.

I agree on this; that's the eventual goal.  My earlier iterations of
atomic watermarks took this step, but we decided to defer it until later
since it clashed with other work Maarten was doing and also added too
many moving pieces to the already-complicated watermark series.

> And the first stage stuff is clearly hardware specific since the
> behavhoir of the wm registers is hardware specific, so trying to
> shoehorn it all into the common code is IMO a mistake.

Nothing really changed with the first stage except that the computation
part has been done earlier (during atomic check phase) and the vfunc
that gets called is named differently (initial_watermarks vs update_wm
to clarify how it fits into the two-step model).


Matt

> 
> > You're still under
> > vblank evasion at that point, so you can't wait for vblanks, but even if
> > you could you'd be adding a lot of unnecessary/redundant wait time.  The
> > model we have now is to call the 'optimize' helper as soon as we're done
> > with the post-update vblank waiting.  In simplified pseudo-code, the
> > logic is:
> > 
> >     for each crtc in state {
> >         drm_atomic_helper_commit_planes_on_crtc()  // does vbl evade
> >     }
> > 
> >     if (!legacy cursor hack)
> >         intel_atomic_wait_for_vblanks();
> > 
> >     for each crtc in state {
> >         intel_post_plane_update();
> >     }
> > 
> >     if (modeset)
> >         intel_display_power_put()
> > 
> >     for each crtc in state
> >         optimize watermarks
> > 
> > For our code today, I guess the proper fix is to move the optimize step
> > up above the display power put; looks like that PM code changed around a
> > bit while this series was being rebased, so I think the power put was
> > located elsewhere before.  It could even be moved into the
> > post_plane_update function if we wanted, but I had kept it separate
> > since ultimately it's going to move out of the atomic_commit altogether.
> > 
> > Longer term, we'll actually be doing the optimize asynchronously via a
> > workqueue task or something (so at an arbitrary future time after the
> > commit is complete); at that point it's even more likely that things
> > have powered down, so I imagine we'll either need to grab the power
> > reference before optimizing watermarks or else just not bother
> > programming them at all in cases where everything is off (which is the
> > approach this patch took).
> > 
> > Anyway, I'll post another patch to move the optimize call up before we
> > drop the power reference; that should also fix the problem as I
> > understand it.
> > 
> > 
> > Matt
> > 
> > > 
> > > > 
> > > >  drivers/gpu/drm/i915/intel_pm.c | 7 ++++---
> > > >  1 file changed, 4 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > > index f65e841..8c7fddf 100644
> > > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > > @@ -2802,8 +2802,6 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
> > > >  		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
> > > >  	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2])
> > > >  		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
> > > > -
> > > > -	dev_priv->wm.hw = *results;
> > > >  }
> > > >  
> > > >  bool ilk_disable_lp_wm(struct drm_device *dev)
> > > > @@ -3731,7 +3729,10 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
> > > >  
> > > >  	ilk_compute_wm_results(dev, best_lp_wm, partitioning, &results);
> > > >  
> > > > -	ilk_write_wm_values(dev_priv, &results);
> > > > +	if (config.num_pipes_active > 0)
> > > > +		ilk_write_wm_values(dev_priv, &results);
> > > > +
> > > > +	dev_priv->wm.hw = results;
> > > >  }
> > > >  
> > > >  static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
> > > > -- 
> > > > 2.1.4
> > > 
> > > -- 
> > > Ville Syrjälä
> > > ntel OTC
> > 
> > -- 
> > Matt Roper
> > Graphics Software Engineer
> > IoTG Platform Enabling & Development
> > Intel Corporation
> > (916) 356-2795
> 
> -- 
> Ville Syrjälä
> Intel OTC
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f65e841..8c7fddf 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2802,8 +2802,6 @@  static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
 	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2])
 		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
-
-	dev_priv->wm.hw = *results;
 }
 
 bool ilk_disable_lp_wm(struct drm_device *dev)
@@ -3731,7 +3729,10 @@  static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
 
 	ilk_compute_wm_results(dev, best_lp_wm, partitioning, &results);
 
-	ilk_write_wm_values(dev_priv, &results);
+	if (config.num_pipes_active > 0)
+		ilk_write_wm_values(dev_priv, &results);
+
+	dev_priv->wm.hw = results;
 }
 
 static void ilk_initial_watermarks(struct intel_crtc_state *cstate)