[Intel-gfx] [RESEND] drm/i915: Interactive RPS mode
Chris Wilson
chris at chris-wilson.co.uk
Fri Jul 20 13:02:34 UTC 2018
Quoting Tvrtko Ursulin (2018-07-20 13:49:09)
>
> On 12/07/2018 18:38, Chris Wilson wrote:
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 7998e70a3174..5809366ff9f0 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -13104,6 +13104,19 @@ intel_prepare_plane_fb(struct drm_plane *plane,
> > add_rps_boost_after_vblank(new_state->crtc, new_state->fence);
> > }
> >
> > + /*
> > + * We declare pageflips to be interactive and so merit a small bias
> > + * towards upclocking to deliver the frame on time. By only changing
> > + * the RPS thresholds to sample more regularly and aim for higher
> > + * clocks we can hopefully deliver low power workloads (like kodi)
> > + * that are not quite steady state without resorting to forcing
> > + * maximum clocks following a vblank miss (see do_rps_boost()).
> > + */
> > + if (!intel_state->rps_interactive) {
> > + intel_rps_set_interactive(dev_priv, true);
> > + intel_state->rps_interactive = true;
> > + }
> > +
> > return 0;
> > }
> >
> > @@ -13120,8 +13133,15 @@ void
> > intel_cleanup_plane_fb(struct drm_plane *plane,
> > struct drm_plane_state *old_state)
> > {
> > + struct intel_atomic_state *intel_state =
> > + to_intel_atomic_state(old_state->state);
> > struct drm_i915_private *dev_priv = to_i915(plane->dev);
> >
> > + if (intel_state->rps_interactive) {
> > + intel_rps_set_interactive(dev_priv, false);
> > + intel_state->rps_interactive = false;
> > + }
>
> Why is the rps_intearctive flag needed in plane state? I wanted to
> assume prepare & cleanup hooks are fully symmetric, but this flags makes
> me unsure. A reviewer with more display knowledge will be needed here I
> think.
It's so that when we call intel_cleanup_plane_fb() on something that
wasn't first prepared, we don't decrement the counter. There's a little
bit of asymmetry at the start where we inherit the plane state.
> > +
> > /* Should only be called after a successful intel_prepare_plane_fb()! */
> > mutex_lock(&dev_priv->drm.struct_mutex);
> > intel_plane_unpin_fb(to_intel_plane_state(old_state));
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 61e715ddd0d5..544812488821 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -482,6 +482,8 @@ struct intel_atomic_state {
> > */
> > bool skip_intermediate_wm;
> >
> > + bool rps_interactive;
>
> Should the name at this level be something more tied to the subsystem
> and not implying wider relationships? Like page flip pending? fb_prepared?
But we are in the plane state so anything plane/flip is implied. I think
saying whether or not we've called out to rps is a reasonable name for
the state.
> > + /* Max/min bins are special */
> > + if (val <= rps->min_freq_softlimit)
> > + new_power = LOW_POWER;
> > + if (val >= rps->max_freq_softlimit)
> > + new_power = HIGH_POWER;
> > +
> > + mutex_lock(&rps->power_lock);
>
> Is it worth avoiding the atomic here when GEN < 6?
We don't get here when not !RPS. You mean GEN < 5 ;)
> > + if (rps->interactive)
> > + new_power = HIGH_POWER;
> > + rps_set_power(dev_priv, new_power);
> > + mutex_unlock(&rps->power_lock);
> >
> > rps->last_adj = 0;
>
> This block should go up to the beginning of the function since when
> rps->interactive all preceding calculations are for nothing. And can
> immediately return then.
We have to lock around rps_set_power, so you're not going to avoid
taking the lock here, so I don't think it makes any difference.
Certainly neater than locking everything.
> > +void intel_rps_set_interactive(struct drm_i915_private *dev_priv, bool state)
>
> s/state/interactive/ for more self-documenting function body?
>
> And not s/dev_priv/i915/ ?!? :)
>
> > +{
> > + struct intel_rps *rps = &dev_priv->gt_pm.rps;
> > +
> > + if (INTEL_GEN(dev_priv) < 6)
> > + return;
> > +
> > + mutex_lock(&rps->power_lock);
> > + if (state) {
> > + if (!rps->interactive++ && READ_ONCE(dev_priv->gt.awake))
> > + rps_set_power(dev_priv, HIGH_POWER);
> > + } else {
> > + GEM_BUG_ON(!rps->interactive);
> > + rps->interactive--;
>
> Hm maybe protect this in production code so some missed code flows in
> the atomic paths do not cause underflow and so permanent interactive mode.
Are you suggesting testing is inadequate? ;) Underflow here isn't a big
deal, it just locks in the HIGH_POWER (faster sampling, bias towards
upclocking). Or worse not allow HIGH_POWER, status quo returned.
-Chris
More information about the Intel-gfx
mailing list