[Intel-gfx] [PATCH 4/5] drm/vblank: Restoring vblank counts after device PM events.

Pandiyan, Dhinakaran dhinakaran.pandiyan at intel.com
Fri Jan 19 22:02:12 UTC 2018




On Fri, 2018-01-19 at 00:01 -0800, Rodrigo Vivi wrote:
> On Fri, Jan 12, 2018 at 09:57:06PM +0000, Dhinakaran Pandiyan wrote:
> > The HW frame counter can get reset if device enters a low power state after
> > vblank interrupts were disabled. This messes up any following vblank count
> > update as a negative diff (huge unsigned diff) is calculated from the HW
> > frame counter change. We cannot ignore negative diffs altogther as there
> > could be legitimate wrap arounds. So, allow drivers to update vblank->count
> > with missed vblanks for the time interrupts were disabled. This is similar
> > to _crtc_vblank_on() except that vblanks interrupts are not enabled at the
> > end as this function is expected to be called from the driver
> > _enable_vblank() vfunc.
> > 
> > v2: drm_crtc_vblank_restore should take crtc as arg. (Chris)
> >     Add docs and sprinkle some asserts.
> > 
> > Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
> > Cc: Chris Wilson <chris at chris-wilson.co.uk>
> > Cc: Michel Dänzer <michel at daenzer.net>
> > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan at intel.com>
> > ---
> >  drivers/gpu/drm/drm_vblank.c | 59 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/drm/drm_vblank.h     |  2 ++
> >  2 files changed, 61 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
> > index 2559d2d7b907..2690966694f0 100644
> > --- a/drivers/gpu/drm/drm_vblank.c
> > +++ b/drivers/gpu/drm/drm_vblank.c
> > @@ -1237,6 +1237,65 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc)
> >  }
> >  EXPORT_SYMBOL(drm_crtc_vblank_on);
> >  
> > +/**
> > + * drm_vblank_restore - estimated vblanks using timestamps and update it.
> > + *
> > + * Power manamement features can cause frame counter resets between vblank
> > + * disable and enable. Drivers can then use this function in their
> > + * &drm_crtc_funcs.enable_vblank implementation to estimate the vblanks since
> > + * the last &drm_crtc_funcs.disable_vblank.
> > + *
> > + * This function is the legacy version of drm_crtc_vblank_restore().
> > + */
> > +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
> > +{
> > +	ktime_t t_vblank;
> > +	struct drm_vblank_crtc *vblank;
> > +	int framedur_ns;
> > +	u64 diff_ns;
> > +	u32 cur_vblank, diff = 1;
> > +	int count = DRM_TIMESTAMP_MAXRETRIES;
> > +
> > +	if (WARN_ON(pipe >= dev->num_crtcs))
> > +		return;
> > +
> > +	assert_spin_locked(&dev->vbl_lock);
> > +	assert_spin_locked(&dev->vblank_time_lock);
> > +
> > +	vblank = &dev->vblank[pipe];
> > +	WARN_ONCE((drm_debug & DRM_UT_VBL) && !vblank->framedur_ns,
> 
> do we really only need this warn on debug vlb?
> 
> > +		  "Cannot compute missed vblanks without frame duration\n");
> 
> The message seems hard... if we *cannot* why do we move fwd?

We assume the diff is 1 and make an update, some kind of a default
similar to what is implemented in drm_update_vblank_count()

> 
> > +	framedur_ns = vblank->framedur_ns;
> > +
> > +	do {
> > +		cur_vblank = __get_vblank_counter(dev, pipe);
> > +		drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
> > +	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
> 
> Based on the commend of drm_update_vblank_count I don't feel that we have to


This one? -
"* We repeat the hardware vblank counter & timestamp query until
 * we get consistent results. This to prevent races between gpu
 * updating its hardware counter while we are retrieving the
 * corresponding vblank timestamp." 


I added the loop based on that comment. If the register if partially
updated, we want to discard that and loop until it is stable.


> do the loop here... And if we have maybe we should re-org things to avoid
> duplication?
> 

I considered that, we need to pass at least four args for three lines of
code. Felt it was too small to warrant a separate function.


> > +
> > +	diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
> > +	if (framedur_ns)
> > +		diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
> > +
> > +
> > +	DRM_DEBUG_VBL("missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n",
> > +		      diff, diff_ns, framedur_ns, cur_vblank - vblank->last);
> > +	store_vblank(dev, pipe, diff, t_vblank, cur_vblank);
> 
> hm... I wonder if the simple store_vblank(... __get_vblank_counter(dev, pipe));
> wouldn't work here...

We have to store a stable count.

> 
> > +}
> > +EXPORT_SYMBOL(drm_vblank_restore);
> > +
> > +/**
> > + * drm_crtc_vblank_restore - estimate vblanks using timestamps and update it.
> > + * Power manamement features can cause frame counter resets between vblank
> > + * disable and enable. Drivers can then use this function in their
> > + * &drm_crtc_funcs.enable_vblank implementation to estimate the vblanks since
> > + * the last &drm_crtc_funcs.disable_vblank.
> > + */
> > +void drm_crtc_vblank_restore(struct drm_crtc *crtc)
> > +{
> > +	drm_vblank_restore(crtc->dev, drm_crtc_index(crtc));
> > +}
> > +EXPORT_SYMBOL(drm_crtc_vblank_restore);
> > +
> >  static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
> >  					  unsigned int pipe)
> >  {
> > diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
> > index a4c3b0a0a197..16d46e2a6854 100644
> > --- a/include/drm/drm_vblank.h
> > +++ b/include/drm/drm_vblank.h
> > @@ -180,6 +180,8 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc);
> >  void drm_crtc_vblank_reset(struct drm_crtc *crtc);
> >  void drm_crtc_vblank_on(struct drm_crtc *crtc);
> >  u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc);
> > +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe);
> > +void drm_crtc_vblank_restore(struct drm_crtc *crtc);
> >  
> >  bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
> >  					   unsigned int pipe, int *max_error,
> > -- 
> > 2.11.0
> > 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx


More information about the Intel-gfx mailing list