[PATCH 01/11] drm: add drm_send_vblank_event() helper (v5)

2012-10-16 Thread Rob Clark
From: Rob Clark 

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
v5: update docbook

Signed-off-by: Rob Clark 
---
 Documentation/DocBook/drm.tmpl |   20 +++
 drivers/gpu/drm/drm_irq.c  |   74 
 include/drm/drmP.h |2 ++
 3 files changed, 59 insertions(+), 37 deletions(-)

diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index b030052..c9cbb3f 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -1141,23 +1141,13 @@ int max_width, max_height;
 the page_flip operation will be called 
with a
 non-NULL event argument pointing to a
 drm_pending_vblank_event instance. Upon 
page
-flip completion the driver must fill the
-event::event
-sequence, 
tv_sec
-and tv_usec fields with the associated
-vertical blanking count and timestamp, add the event to the
-drm_file list of events to be signaled, and 
wake
-up any waiting process. This can be performed with
+flip completion the driver must call 
drm_send_vblank_event
+to fill in the event and send to wake up any waiting processes.
+This can be performed with
 
   
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(>event_lock));
+   e->event.sequence = seq;
+   e->event.tv_sec = now->tv_sec;
+   e->event.tv_usec = now->tv_usec;
+
+   list_add_tail(>base.link,
+ >base.file_priv->event_list);
+   wake_up_interruptible(>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, );
+   } else {
+   seq = 0;
+   do_gettimeofday();
+   }
+   send_vblank_event(dev, e, seq, );
+}
+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(>base.link);
drm_vblank_put(dev, e->pipe);
-   list_move_tail(>base.link, >base.file_priv->event_list);
-   wake_up_interruptible(>base.file_priv->event_wait);
-   trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
-e->event.sequence);
+   send_vblank_event(dev, e, seq, );
}

spin_unlock_irqrestore(>vbl_lock, irqflags);
@@ -1107,15 +1148,9 @@ static int drm_queue_vblank_event(struct drm_device 
*dev, int pipe,


[PATCH 01/11] drm: add drm_send_vblank_event() helper (v5)

2012-10-16 Thread Rob Clark
From: Rob Clark r...@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
v5: update docbook

Signed-off-by: Rob Clark r...@ti.com
---
 Documentation/DocBook/drm.tmpl |   20 +++
 drivers/gpu/drm/drm_irq.c  |   74 
 include/drm/drmP.h |2 ++
 3 files changed, 59 insertions(+), 37 deletions(-)

diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index b030052..c9cbb3f 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -1141,23 +1141,13 @@ int max_width, max_height;/synopsis
 the methodnamepage_flip/methodname operation will be called 
with a
 non-NULL parameterevent/parameter argument pointing to a
 structnamedrm_pending_vblank_event/structname instance. Upon 
page
-flip completion the driver must fill the
-parameterevent/parameter::structfieldevent/structfield
-structfieldsequence/structfield, 
structfieldtv_sec/structfield
-and structfieldtv_usec/structfield fields with the associated
-vertical blanking count and timestamp, add the event to the
-parameterdrm_file/parameter list of events to be signaled, and 
wake
-up any waiting process. This can be performed with
+flip completion the driver must call 
methodnamedrm_send_vblank_event/methodname
+to fill in the event and send to wake up any waiting processes.
+This can be performed with
 programlisting![CDATA[
-struct timeval now;
-
-event-event.sequence = drm_vblank_count_and_time(..., now);
-event-event.tv_sec = now.tv_sec;
-event-event.tv_usec = now.tv_usec;
-
 spin_lock_irqsave(dev-event_lock, flags);
-list_add_tail(event-base.link, 
event-base.file_priv-event_list);
-wake_up_interruptible(event-base.file_priv-event_wait);
+...
+drm_send_vblank_event(dev, pipe, event);
 spin_unlock_irqrestore(dev-event_lock, flags);
 ]]/programlisting
   /para
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: \