[PATCH 01/19] drm/core: Add drm_accurate_vblank_count, v4.
Ville Syrjälä
ville.syrjala at linux.intel.com
Mon Apr 25 12:26:02 UTC 2016
On Mon, Apr 25, 2016 at 06:35:48AM +0200, Mario Kleiner wrote:
> Sorry for the late review, but see below...
>
> On 04/19/2016 09:52 AM, Maarten Lankhorst wrote:
> > This function is useful for gen2 intel devices which have no frame
> > counter, but need a way to determine the current vblank count without
> > racing with the vblank interrupt handler.
> >
> > intel_pipe_update_start checks if no vblank interrupt will occur
> > during vblank evasion, but cannot check whether the vblank handler has
> > run to completion. This function uses the timestamps to determine
> > when the last vblank has happened, and interpolates from there.
> >
> > Changes since v1:
> > - Take vblank_time_lock and don't use drm_vblank_count_and_time.
> > Changes since v2:
> > - Don't return time of last vblank.
> > Changes since v3:
> > - Change pipe to unsigned int. (Ville)
> > - Remove unused documentation for tv_ret. (kbuild)
> >
> > Cc: Mario Kleiner <mario.kleiner.de at gmail.com>
> > Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> > Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> > Reviewed-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> > Acked-by: David Airlie <airlied at linux.ie> #irc
> > ---
> > drivers/gpu/drm/drm_irq.c | 26 ++++++++++++++++++++++++++
> > include/drm/drmP.h | 1 +
> > 2 files changed, 27 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
> > index 3c1a6f18e71c..f1bda13562da 100644
> > --- a/drivers/gpu/drm/drm_irq.c
> > +++ b/drivers/gpu/drm/drm_irq.c
> > @@ -303,6 +303,32 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
> > store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);
> > }
> >
> > +/**
> > + * drm_accurate_vblank_count - retrieve the master vblank counter
> > + * @crtc: which counter to retrieve
> > + *
> > + * This function is similar to @drm_crtc_vblank_count but this
> > + * function interpolates to handle a race with vblank irq's.
> > + */
> > +
> > +u32 drm_accurate_vblank_count(struct drm_crtc *crtc)
> > +{
> > + struct drm_device *dev = crtc->dev;
> > + unsigned int pipe = drm_crtc_index(crtc);
> > + u32 vblank;
> > + unsigned long flags;
> > +
>
> This function is rather dangerous to use on any driver that doesn't have
> precise vblank timestamping, or doesn't have the guarantee that hw
> vblank counters (if there are any) and timestamps update exactly at
> leading edge of vblank, so i think we need some WARN() here and maybe
> much less encouraging docs to avoid this being called from incapable kms
> drivers or in general code.
>
> - If the driver doesn't have precise scanoutpos based timestamping each
> call into drm_update_vblank_count from non-irq context will reset the
> vblank timestamps to zero, so clients will only receive invalid
> timestamps if this is frequently used. Also bogus vblank counts
>
> Atm. only i915 Intel, AMD, NVidia desktop for >= NV-50, maybe nouveau
> driven Tegra parts, and some modern Adrenos (msm/mdp-5 - i assume from
> the code?) support this reliably.
>
> - If the drivers scanoutpos timestamps and/or vblank counter don't
> increment at leading edge we will get funny off-by-one problems with
> vblank counters. That's why we normally only call
> drm_update_vblank_count() from vblank irq on such parts - the only safe
> place to avoid off-by-one problems, and limit vblank disable/enable to
> only at most once every 5 seconds to reduce the problems caused by
> off-by-one errors.
>
> Which restricts the list to only the above parts, maybe minus Adreno
> where i don't know if it obeys the "leading edge" rule or not.
>
> So on most SoC's one must not use this function.
>
> WARN_ON(!dev->vblank_disable_immediate, "This function is unsafe on this
> driver.");
>
> would probably prevent the worst abuse, unless drivers lie about
> vblank_disable_immediate. Not sure how much this was checked for msm /
> Adreno? At least drm_vblank_init() only allows vblank_disable_immediate
> if the driver at least implements proper timestamping.
>
> Not sure how much general use this function will have outside Intel
> gen-2 with the restrictions on safe use?
This (or something like it) needs to be used also in generic vblank
wait functions. Currently those are racy.
>
> > + spin_lock_irqsave(&dev->vblank_time_lock, flags);
> > +
> > + drm_update_vblank_count(dev, pipe, 0);
> > + vblank = dev->vblank[pipe].count;
>
> Could do vblank = drm_vblank_count(dev, pipe); instead, given that we
> avoid open coding this in most places.
>
> -mario
>
> > +
> > + spin_unlock_irqrestore(&dev->vblank_time_lock, flags);
> > +
> > + return vblank;
> > +}
> > +EXPORT_SYMBOL(drm_accurate_vblank_count);
> > +
> > /*
> > * Disable vblank irq's on crtc, make sure that last vblank count
> > * of hardware and corresponding consistent software vblank counter
> > diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> > index 005202ea5900..90527c41cd5a 100644
> > --- a/include/drm/drmP.h
> > +++ b/include/drm/drmP.h
> > @@ -995,6 +995,7 @@ extern void drm_crtc_vblank_off(struct drm_crtc *crtc);
> > extern void drm_crtc_vblank_reset(struct drm_crtc *crtc);
> > extern void drm_crtc_vblank_on(struct drm_crtc *crtc);
> > extern void drm_vblank_cleanup(struct drm_device *dev);
> > +extern u32 drm_accurate_vblank_count(struct drm_crtc *crtc);
> > extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
> >
> > extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
> >
--
Ville Syrjälä
Intel OTC
More information about the dri-devel
mailing list