aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm')
-rw-r--r--drivers/char/drm/drm.h4
-rw-r--r--drivers/char/drm/drm_irq.c16
2 files changed, 13 insertions, 7 deletions
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 07a699029c3e..3f28a1551621 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -487,12 +487,14 @@ typedef struct drm_irq_busid {
487typedef enum { 487typedef enum {
488 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ 488 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
489 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ 489 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
490 _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
490 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ 491 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
491 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ 492 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
492} drm_vblank_seq_type_t; 493} drm_vblank_seq_type_t;
493 494
494#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) 495#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
495#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY) 496#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
497 _DRM_VBLANK_NEXTONMISS)
496 498
497struct drm_wait_vblank_request { 499struct drm_wait_vblank_request {
498 drm_vblank_seq_type_t type; 500 drm_vblank_seq_type_t type;
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index b08608a9f026..78aae5b35c62 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -250,8 +250,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
250 drm_wait_vblank_t vblwait; 250 drm_wait_vblank_t vblwait;
251 struct timeval now; 251 struct timeval now;
252 int ret = 0; 252 int ret = 0;
253 unsigned int flags; 253 unsigned int flags, seq;
254 atomic_t *seq;
255 254
256 if (!dev->irq) 255 if (!dev->irq)
257 return -EINVAL; 256 return -EINVAL;
@@ -273,12 +272,12 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
273 DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL)) 272 DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
274 return -EINVAL; 273 return -EINVAL;
275 274
276 seq = (flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 : 275 seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
277 &dev->vbl_received; 276 : &dev->vbl_received);
278 277
279 switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) { 278 switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {
280 case _DRM_VBLANK_RELATIVE: 279 case _DRM_VBLANK_RELATIVE:
281 vblwait.request.sequence += atomic_read(seq); 280 vblwait.request.sequence += seq;
282 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; 281 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
283 case _DRM_VBLANK_ABSOLUTE: 282 case _DRM_VBLANK_ABSOLUTE:
284 break; 283 break;
@@ -286,13 +285,18 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
286 return -EINVAL; 285 return -EINVAL;
287 } 286 }
288 287
288 if ((flags & _DRM_VBLANK_NEXTONMISS) &&
289 (seq - vblwait.request.sequence) <= (1<<23)) {
290 vblwait.request.sequence = seq + 1;
291 }
292
289 if (flags & _DRM_VBLANK_SIGNAL) { 293 if (flags & _DRM_VBLANK_SIGNAL) {
290 unsigned long irqflags; 294 unsigned long irqflags;
291 drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY) 295 drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
292 ? &dev->vbl_sigs2 : &dev->vbl_sigs; 296 ? &dev->vbl_sigs2 : &dev->vbl_sigs;
293 drm_vbl_sig_t *vbl_sig; 297 drm_vbl_sig_t *vbl_sig;
294 298
295 vblwait.reply.sequence = atomic_read(seq); 299 vblwait.reply.sequence = seq;
296 300
297 spin_lock_irqsave(&dev->vbl_lock, irqflags); 301 spin_lock_irqsave(&dev->vbl_lock, irqflags);
298 302