diff mbox

[2/2] drm: Peek at the current counter/timestamp for vblank queries

Message ID 20170316234749.1297-2-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson March 16, 2017, 11:47 p.m. UTC
Bypass all the spinlocks and return the last timestamp and counter from
the last vblank if the driver delcares that it is accurate (and stable
across on/off), and the vblank is currently enabled.

This is dependent upon the both the hardware and driver to provide the
proper barriers to facilitate reading our bookkeeping outside of the
vblank interrupt and outside of the explicit vblank locks.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: Michel Dänzer <michel@daenzer.net>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Dave Airlie <airlied@redhat.com>,
Cc: Mario Kleiner <mario.kleiner.de@gmail.com>
---
 drivers/gpu/drm/drm_irq.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

Comments

Ville Syrjala March 17, 2017, 9:49 a.m. UTC | #1
On Thu, Mar 16, 2017 at 11:47:49PM +0000, Chris Wilson wrote:
> Bypass all the spinlocks and return the last timestamp and counter from
> the last vblank if the driver delcares that it is accurate (and stable
> across on/off), and the vblank is currently enabled.
> 
> This is dependent upon the both the hardware and driver to provide the
> proper barriers to facilitate reading our bookkeeping outside of the
> vblank interrupt and outside of the explicit vblank locks.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel@ffwll.ch>
> Cc: Michel Dänzer <michel@daenzer.net>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Cc: Dave Airlie <airlied@redhat.com>,
> Cc: Mario Kleiner <mario.kleiner.de@gmail.com>
> ---
>  drivers/gpu/drm/drm_irq.c | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
> index 4cc9352ab6a8..b4bd361a2bcc 100644
> --- a/drivers/gpu/drm/drm_irq.c
> +++ b/drivers/gpu/drm/drm_irq.c
> @@ -1562,6 +1562,17 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
>  	return ret;
>  }
>  
> +static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
> +{
> +	if (vblwait->request.sequence)
> +		return false;
> +
> +	return _DRM_VBLANK_RELATIVE ==
> +		(vblwait->request.type & (_DRM_VBLANK_TYPES_MASK |
> +					  _DRM_VBLANK_EVENT |
> +					  _DRM_VBLANK_NEXTONMISS));
> +}
> +
>  /*
>   * Wait for VBLANK.
>   *
> @@ -1611,6 +1622,21 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
>  
>  	vblank = &dev->vblank[pipe];
>  
> +	/* If the counter is currently enabled and accurate, short-circuit queries
> +	 * to return the cached timestamp of the last vblank.
> +	 */
> +	if (dev->vblank_disable_immediate &&
> +	    drm_wait_vblank_is_query(vblwait) &&
> +	    vblank->enabled) {
> +		struct timeval now;
> +

Do we want a comment here as well stating that the seqlock
already has the rmb?

> +		vblwait->reply.sequence =
> +			drm_vblank_count_and_time(dev, pipe, &now);
> +		vblwait->reply.tval_sec = now.tv_sec;
> +		vblwait->reply.tval_usec = now.tv_usec;
> +		return 0;
> +	}
> +
>  	ret = drm_vblank_get(dev, pipe);
>  	if (ret) {
>  		DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);
> -- 
> 2.11.0
Chris Wilson March 17, 2017, 7:59 p.m. UTC | #2
On Fri, Mar 17, 2017 at 11:49:32AM +0200, Ville Syrjälä wrote:
> On Thu, Mar 16, 2017 at 11:47:49PM +0000, Chris Wilson wrote:
> > Bypass all the spinlocks and return the last timestamp and counter from
> > the last vblank if the driver delcares that it is accurate (and stable
> > across on/off), and the vblank is currently enabled.
> > 
> > This is dependent upon the both the hardware and driver to provide the
> > proper barriers to facilitate reading our bookkeeping outside of the
> > vblank interrupt and outside of the explicit vblank locks.
> > 
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Daniel Vetter <daniel@ffwll.ch>
> > Cc: Michel Dänzer <michel@daenzer.net>
> > Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Cc: Dave Airlie <airlied@redhat.com>,
> > Cc: Mario Kleiner <mario.kleiner.de@gmail.com>
> > ---
> >  drivers/gpu/drm/drm_irq.c | 26 ++++++++++++++++++++++++++
> >  1 file changed, 26 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
> > index 4cc9352ab6a8..b4bd361a2bcc 100644
> > --- a/drivers/gpu/drm/drm_irq.c
> > +++ b/drivers/gpu/drm/drm_irq.c
> > @@ -1562,6 +1562,17 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
> >  	return ret;
> >  }
> >  
> > +static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
> > +{
> > +	if (vblwait->request.sequence)
> > +		return false;
> > +
> > +	return _DRM_VBLANK_RELATIVE ==
> > +		(vblwait->request.type & (_DRM_VBLANK_TYPES_MASK |
> > +					  _DRM_VBLANK_EVENT |
> > +					  _DRM_VBLANK_NEXTONMISS));
> > +}
> > +
> >  /*
> >   * Wait for VBLANK.
> >   *
> > @@ -1611,6 +1622,21 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
> >  
> >  	vblank = &dev->vblank[pipe];
> >  
> > +	/* If the counter is currently enabled and accurate, short-circuit queries
> > +	 * to return the cached timestamp of the last vblank.
> > +	 */
> > +	if (dev->vblank_disable_immediate &&
> > +	    drm_wait_vblank_is_query(vblwait) &&
> > +	    vblank->enabled) {
> > +		struct timeval now;
> > +
> 
> Do we want a comment here as well stating that the seqlock
> already has the rmb?

I didn't find it enlightening. Added READ_ONCE(vblank->enabled).
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 4cc9352ab6a8..b4bd361a2bcc 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -1562,6 +1562,17 @@  static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
 	return ret;
 }
 
+static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
+{
+	if (vblwait->request.sequence)
+		return false;
+
+	return _DRM_VBLANK_RELATIVE ==
+		(vblwait->request.type & (_DRM_VBLANK_TYPES_MASK |
+					  _DRM_VBLANK_EVENT |
+					  _DRM_VBLANK_NEXTONMISS));
+}
+
 /*
  * Wait for VBLANK.
  *
@@ -1611,6 +1622,21 @@  int drm_wait_vblank(struct drm_device *dev, void *data,
 
 	vblank = &dev->vblank[pipe];
 
+	/* If the counter is currently enabled and accurate, short-circuit queries
+	 * to return the cached timestamp of the last vblank.
+	 */
+	if (dev->vblank_disable_immediate &&
+	    drm_wait_vblank_is_query(vblwait) &&
+	    vblank->enabled) {
+		struct timeval now;
+
+		vblwait->reply.sequence =
+			drm_vblank_count_and_time(dev, pipe, &now);
+		vblwait->reply.tval_sec = now.tv_sec;
+		vblwait->reply.tval_usec = now.tv_usec;
+		return 0;
+	}
+
 	ret = drm_vblank_get(dev, pipe);
 	if (ret) {
 		DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);