[0/11] drm: add drm_send_vblank_event() helper (v4)

Message ID 1350086233-12426-1-git-send-email-rob.clark@linaro.org
State New
Headers show

Commit Message

Rob Clark Oct. 12, 2012, 11:57 p.m.
From: Rob Clark <rob@ti.com>

A helper that drivers can use to send vblank event after a pageflip.
If the driver doesn't support proper vblank irq based time/seqn then
just pass -1 for the pipe # to get do_gettimestamp() behavior (since
there are a lot of drivers that don't use drm_vblank_count_and_time())

Also an internal send_vblank_event() helper for the various other code
paths within drm_irq that also need to send vblank events.

v1: original
v2: add back 'vblwait->reply.sequence = seq' which should not have
    been deleted
v3: add WARN_ON() in case lock is not held and comments
v4: use WARN_ON_SMP() instead to fix issue with !SMP && !DEBUG_SPINLOCK
    as pointed out by Marcin Slusarz

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/gpu/drm/drm_irq.c |   74 +++++++++++++++++++++++++++++++--------------
 include/drm/drmP.h        |    2 ++
 2 files changed, 54 insertions(+), 22 deletions(-)

Comments

Laurent Pinchart Oct. 16, 2012, 2:14 p.m. | #1
Hi Rob,

Thanks for the patch (0/11 looks a bit weird BTW).

On Friday 12 October 2012 18:57:12 Rob Clark wrote:
> From: Rob Clark <rob@ti.com>
> 
> A helper that drivers can use to send vblank event after a pageflip.
> If the driver doesn't support proper vblank irq based time/seqn then
> just pass -1 for the pipe # to get do_gettimestamp() behavior (since
> there are a lot of drivers that don't use drm_vblank_count_and_time())
> 
> Also an internal send_vblank_event() helper for the various other code
> paths within drm_irq that also need to send vblank events.
> 
> v1: original
> v2: add back 'vblwait->reply.sequence = seq' which should not have
>     been deleted
> v3: add WARN_ON() in case lock is not held and comments
> v4: use WARN_ON_SMP() instead to fix issue with !SMP && !DEBUG_SPINLOCK
>     as pointed out by Marcin Slusarz
> 
> Signed-off-by: Rob Clark <rob@ti.com>
> ---
>  drivers/gpu/drm/drm_irq.c |   74 ++++++++++++++++++++++++++++--------------
>  include/drm/drmP.h        |    2 ++

Documentation/DocBook/drm.tmpl is missing ;-)

>  2 files changed, 54 insertions(+), 22 deletions(-)

I still wish we could have found a way to call drm_vblank_count_and_time() and 
do_gettimeofday() outside of the spinlock-protected region, but I won't 
complain. Apart from the missing documentation update the patch looks OK to 
me.
Rob Clark Oct. 16, 2012, 3:27 p.m. | #2
On Tue, Oct 16, 2012 at 9:14 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi Rob,
>
> Thanks for the patch (0/11 looks a bit weird BTW).

opps, that was *supposed* to be 01/11 :-P

>
> On Friday 12 October 2012 18:57:12 Rob Clark wrote:
>> From: Rob Clark <rob@ti.com>
>>
>> A helper that drivers can use to send vblank event after a pageflip.
>> If the driver doesn't support proper vblank irq based time/seqn then
>> just pass -1 for the pipe # to get do_gettimestamp() behavior (since
>> there are a lot of drivers that don't use drm_vblank_count_and_time())
>>
>> Also an internal send_vblank_event() helper for the various other code
>> paths within drm_irq that also need to send vblank events.
>>
>> v1: original
>> v2: add back 'vblwait->reply.sequence = seq' which should not have
>>     been deleted
>> v3: add WARN_ON() in case lock is not held and comments
>> v4: use WARN_ON_SMP() instead to fix issue with !SMP && !DEBUG_SPINLOCK
>>     as pointed out by Marcin Slusarz
>>
>> Signed-off-by: Rob Clark <rob@ti.com>
>> ---
>>  drivers/gpu/drm/drm_irq.c |   74 ++++++++++++++++++++++++++++--------------
>>  include/drm/drmP.h        |    2 ++
>
> Documentation/DocBook/drm.tmpl is missing ;-)

yeah, I just noticed that the docbook already has a section on
pageflip.. I'll send a separate patch for this.

BR,
-R

>
>>  2 files changed, 54 insertions(+), 22 deletions(-)
>
> I still wish we could have found a way to call drm_vblank_count_and_time() and
> do_gettimeofday() outside of the spinlock-protected region, but I won't
> complain. Apart from the missing documentation update the patch looks OK to
> me.
>
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

Patch

diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 076c4a8..9bdcfd5 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -802,6 +802,46 @@  u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
 }
 EXPORT_SYMBOL(drm_vblank_count_and_time);
 
+static void send_vblank_event(struct drm_device *dev,
+		struct drm_pending_vblank_event *e,
+		unsigned long seq, struct timeval *now)
+{
+	WARN_ON_SMP(!spin_is_locked(&dev->event_lock));
+	e->event.sequence = seq;
+	e->event.tv_sec = now->tv_sec;
+	e->event.tv_usec = now->tv_usec;
+
+	list_add_tail(&e->base.link,
+		      &e->base.file_priv->event_list);
+	wake_up_interruptible(&e->base.file_priv->event_wait);
+	trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
+					 e->event.sequence);
+}
+
+/**
+ * drm_send_vblank_event - helper to send vblank event after pageflip
+ * @dev: DRM device
+ * @crtc: CRTC in question
+ * @e: the event to send
+ *
+ * Updates sequence # and timestamp on event, and sends it to userspace.
+ * Caller must hold event lock.
+ */
+void drm_send_vblank_event(struct drm_device *dev, int crtc,
+		struct drm_pending_vblank_event *e)
+{
+	struct timeval now;
+	unsigned int seq;
+	if (crtc >= 0) {
+		seq = drm_vblank_count_and_time(dev, crtc, &now);
+	} else {
+		seq = 0;
+		do_gettimeofday(&now);
+	}
+	send_vblank_event(dev, e, seq, &now);
+}
+EXPORT_SYMBOL(drm_send_vblank_event);
+
 /**
  * drm_update_vblank_count - update the master vblank counter
  * @dev: DRM device
@@ -936,6 +976,13 @@  void drm_vblank_put(struct drm_device *dev, int crtc)
 }
 EXPORT_SYMBOL(drm_vblank_put);
 
+/**
+ * drm_vblank_off - disable vblank events on a CRTC
+ * @dev: DRM device
+ * @crtc: CRTC in question
+ *
+ * Caller must hold event lock.
+ */
 void drm_vblank_off(struct drm_device *dev, int crtc)
 {
 	struct drm_pending_vblank_event *e, *t;
@@ -955,15 +1002,9 @@  void drm_vblank_off(struct drm_device *dev, int crtc)
 		DRM_DEBUG("Sending premature vblank event on disable: \
 			  wanted %d, current %d\n",
 			  e->event.sequence, seq);
-
-		e->event.sequence = seq;
-		e->event.tv_sec = now.tv_sec;
-		e->event.tv_usec = now.tv_usec;
+		list_del(&e->base.link);
 		drm_vblank_put(dev, e->pipe);
-		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-		wake_up_interruptible(&e->base.file_priv->event_wait);
-		trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
-						 e->event.sequence);
+		send_vblank_event(dev, e, seq, &now);
 	}
 
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -1107,15 +1148,9 @@  static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
 
 	e->event.sequence = vblwait->request.sequence;
 	if ((seq - vblwait->request.sequence) <= (1 << 23)) {
-		e->event.sequence = seq;
-		e->event.tv_sec = now.tv_sec;
-		e->event.tv_usec = now.tv_usec;
 		drm_vblank_put(dev, pipe);
-		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
-		wake_up_interruptible(&e->base.file_priv->event_wait);
+		send_vblank_event(dev, e, seq, &now);
 		vblwait->reply.sequence = seq;
-		trace_drm_vblank_event_delivered(current->pid, pipe,
-						 vblwait->request.sequence);
 	} else {
 		/* drm_handle_vblank_events will call drm_vblank_put */
 		list_add_tail(&e->base.link, &dev->vblank_event_list);
@@ -1256,14 +1291,9 @@  static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
 		DRM_DEBUG("vblank event on %d, current %d\n",
 			  e->event.sequence, seq);
 
-		e->event.sequence = seq;
-		e->event.tv_sec = now.tv_sec;
-		e->event.tv_usec = now.tv_usec;
+		list_del(&e->base.link);
 		drm_vblank_put(dev, e->pipe);
-		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-		wake_up_interruptible(&e->base.file_priv->event_wait);
-		trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
-						 e->event.sequence);
+		send_vblank_event(dev, e, seq, &now);
 	}
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 05af0e7..ee8f927 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1437,6 +1437,8 @@  extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
 extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
 extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
 				     struct timeval *vblanktime);
+extern void drm_send_vblank_event(struct drm_device *dev, int crtc,
+				     struct drm_pending_vblank_event *e);
 extern bool drm_handle_vblank(struct drm_device *dev, int crtc);
 extern int drm_vblank_get(struct drm_device *dev, int crtc);
 extern void drm_vblank_put(struct drm_device *dev, int crtc);