On Tue, Jun 10, 2014 at 11:04:02AM +0100, Chris Wilson wrote: > If we hit a vblank and see that have a pageflip queue but not yet > processed, ensure that the GPU is running at maximum in order to clear > the backlog. Pageflips are only queued for the following vblank, if we > miss it, there will be a visible stutter. Boosting the GPU frequency > doesn't prevent us from missing the target vblank, but it should help > the subsequent frames hitting theirs. > > v2: Reorder vblank vs flip-complete so that we only check for a missed > flip after processing the completion events, and avoid spurious boosts. > > v3: Rename missed_vblank > > Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> > Cc: Daniel Vetter <daniel.vetter@xxxxxxxx> > Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_drv.h | 1 + > drivers/gpu/drm/i915/intel_display.c | 6 ++++++ > drivers/gpu/drm/i915/intel_drv.h | 1 + > drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++++ > 4 files changed, 23 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 10dd80a..33ed0c6 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -910,6 +910,7 @@ struct intel_gen6_power_mgmt { > > bool enabled; > struct delayed_work delayed_resume_work; > + struct work_struct boost_work; > > /* > * Protects RPS/RC6 register access and PCU communication. > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 9ecc6bf..aeb58fa 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -9339,6 +9339,7 @@ void intel_check_page_flip(struct drm_device *dev, int pipe) > struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; > struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > unsigned long flags; > + bool missed_vblank; > > if (crtc == NULL) > return; > @@ -9349,7 +9350,12 @@ void intel_check_page_flip(struct drm_device *dev, int pipe) > intel_crtc->unpin_work->sbc, crtc_sbc(intel_crtc)); > page_flip_completed(intel_crtc); > } > + missed_vblank = (intel_crtc->unpin_work != NULL && > + crtc_sbc(intel_crtc) - intel_crtc->unpin_work->sbc > 1); So this will boost when we notice that we've crossed into the second vblank since the flip was queued. I was wondering if we should try to boost already after the first vblank. But doing that is a bit more problematic since we process the "flip done" interrupt after the vblank interrupt. So simply changing the check to >0 would end up boosting every time even if the flip already happened and we're just about to complete it when we get to processing the "flip done" interrupt. > spin_unlock_irqrestore(&dev->event_lock, flags); > + > + if (missed_vblank) > + intel_queue_rps_boost(dev); > } > > static int intel_crtc_page_flip(struct drm_crtc *crtc, > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index ac902ad..75fba0d 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -966,6 +966,7 @@ void ironlake_teardown_rc6(struct drm_device *dev); > void gen6_update_ring_freq(struct drm_device *dev); > void gen6_rps_idle(struct drm_i915_private *dev_priv); > void gen6_rps_boost(struct drm_i915_private *dev_priv); > +void intel_queue_rps_boost(struct drm_device *dev); > void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); > void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); > void intel_runtime_pm_get(struct drm_i915_private *dev_priv); > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c > index b06f896..ab760e5 100644 > --- a/drivers/gpu/drm/i915/intel_pm.c > +++ b/drivers/gpu/drm/i915/intel_pm.c > @@ -6722,6 +6722,19 @@ int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val) > return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6; > } > > +static void __intel_rps_boost_work(struct work_struct *work) > +{ > + gen6_rps_boost(container_of(work, struct drm_i915_private, rps.boost_work)); > +} > + > +void intel_queue_rps_boost(struct drm_device *dev) > +{ > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + if (INTEL_INFO(dev)->gen >= 6) > + queue_work(dev_priv->wq, &dev_priv->rps.boost_work); > +} > + > void intel_pm_setup(struct drm_device *dev) > { > struct drm_i915_private *dev_priv = dev->dev_private; > @@ -6730,6 +6743,8 @@ void intel_pm_setup(struct drm_device *dev) > > INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, > intel_gen6_powersave_work); > + INIT_WORK(&dev_priv->rps.boost_work, > + __intel_rps_boost_work); > > dev_priv->pm.suspended = false; > dev_priv->pm.irqs_disabled = false; > -- > 1.7.9.5 -- Ville Syrjälä Intel OTC _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx