drm: Core vsync: Add flag DRM_VBLANK_NEXTONMISS.

When this flag is set and the target sequence is missed, wait for the next
vertical blank instead of returning immediately.

Signed-off-by: Dave Airlie <airlied@linux.ie>
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index b08608a..78aae5b 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -250,8 +250,7 @@
 	drm_wait_vblank_t vblwait;
 	struct timeval now;
 	int ret = 0;
-	unsigned int flags;
-	atomic_t *seq;
+	unsigned int flags, seq;
 
 	if (!dev->irq)
 		return -EINVAL;
@@ -273,12 +272,12 @@
 				    DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
 		return -EINVAL;
 
-	seq = (flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 :
-	      &dev->vbl_received;
+	seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
+			  : &dev->vbl_received);
 
 	switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {
 	case _DRM_VBLANK_RELATIVE:
-		vblwait.request.sequence += atomic_read(seq);
+		vblwait.request.sequence += seq;
 		vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
 	case _DRM_VBLANK_ABSOLUTE:
 		break;
@@ -286,13 +285,18 @@
 		return -EINVAL;
 	}
 
+	if ((flags & _DRM_VBLANK_NEXTONMISS) &&
+	    (seq - vblwait.request.sequence) <= (1<<23)) {
+		vblwait.request.sequence = seq + 1;
+	}
+
 	if (flags & _DRM_VBLANK_SIGNAL) {
 		unsigned long irqflags;
 		drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
 				      ? &dev->vbl_sigs2 : &dev->vbl_sigs;
 		drm_vbl_sig_t *vbl_sig;
 
-		vblwait.reply.sequence = atomic_read(seq);
+		vblwait.reply.sequence = seq;
 
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);