aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/i915_irq.c
diff options
context:
space:
mode:
author=?utf-8?q?Michel_D=C3=A4nzer?= <michel@tungstengraphics.com>2006-10-24 09:38:54 -0400
committerairlied <airlied@linux.ie>2006-12-06 23:53:30 -0500
commit541f29aad766b6c7b911a7d900d952744369bf53 (patch)
tree5ce5aa51d47c518146b0f13c2a58d643b58d58ba /drivers/char/drm/i915_irq.c
parenta6b54f3f5050c0cbc0c35dd48064846c6302706b (diff)
drm: DRM_I915_VBLANK_SWAP ioctl: Take drm_vblank_seq_type_t instead
of pipe number. Handle relative as well as absolute target sequence numbers. Return error if target sequence has already passed, so userspace can deal with this situation as it sees fit. On success, return the sequence number of the vertical blank when the buffer swap is expected to take place. Also add DRM_IOCTL_I915_VBLANK_SWAP definition for userspace code that may want to use ioctl() instead of drmCommandWriteRead(). Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/i915_irq.c')
-rw-r--r--drivers/char/drm/i915_irq.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index a93f1f37ec6a..d56455666312 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -375,7 +375,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
375 drm_i915_private_t *dev_priv = dev->dev_private; 375 drm_i915_private_t *dev_priv = dev->dev_private;
376 drm_i915_vblank_swap_t swap; 376 drm_i915_vblank_swap_t swap;
377 drm_i915_vbl_swap_t *vbl_swap; 377 drm_i915_vbl_swap_t *vbl_swap;
378 unsigned int irqflags; 378 unsigned int pipe, seqtype, irqflags, curseq;
379 struct list_head *list; 379 struct list_head *list;
380 380
381 if (!dev_priv) { 381 if (!dev_priv) {
@@ -396,8 +396,23 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
396 DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data, 396 DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data,
397 sizeof(swap)); 397 sizeof(swap));
398 398
399 if (swap.pipe > 1 || !(dev_priv->vblank_pipe & (1 << swap.pipe))) { 399 if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
400 DRM_ERROR("Invalid pipe %d\n", swap.pipe); 400 _DRM_VBLANK_SECONDARY)) {
401 DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
402 return DRM_ERR(EINVAL);
403 }
404
405 pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
406
407 seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
408
409 if (seqtype == _DRM_VBLANK_RELATIVE && swap.sequence == 0) {
410 DRM_DEBUG("Not scheduling swap for current sequence\n");
411 return DRM_ERR(EINVAL);
412 }
413
414 if (!(dev_priv->vblank_pipe & (1 << pipe))) {
415 DRM_ERROR("Invalid pipe %d\n", pipe);
401 return DRM_ERR(EINVAL); 416 return DRM_ERR(EINVAL);
402 } 417 }
403 418
@@ -411,13 +426,28 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
411 426
412 spin_unlock_irqrestore(&dev->drw_lock, irqflags); 427 spin_unlock_irqrestore(&dev->drw_lock, irqflags);
413 428
429 curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
430
414 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); 431 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
415 432
433 switch (seqtype) {
434 case _DRM_VBLANK_RELATIVE:
435 swap.sequence += curseq;
436 break;
437 case _DRM_VBLANK_ABSOLUTE:
438 if ((curseq - swap.sequence) > (1<<23)) {
439 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
440 DRM_DEBUG("Missed target sequence\n");
441 return DRM_ERR(EINVAL);
442 }
443 break;
444 }
445
416 list_for_each(list, &dev_priv->vbl_swaps.head) { 446 list_for_each(list, &dev_priv->vbl_swaps.head) {
417 vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); 447 vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
418 448
419 if (vbl_swap->drw_id == swap.drawable && 449 if (vbl_swap->drw_id == swap.drawable &&
420 vbl_swap->pipe == swap.pipe && 450 vbl_swap->pipe == pipe &&
421 vbl_swap->sequence == swap.sequence) { 451 vbl_swap->sequence == swap.sequence) {
422 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); 452 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
423 DRM_DEBUG("Already scheduled\n"); 453 DRM_DEBUG("Already scheduled\n");
@@ -437,7 +467,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
437 DRM_DEBUG("\n"); 467 DRM_DEBUG("\n");
438 468
439 vbl_swap->drw_id = swap.drawable; 469 vbl_swap->drw_id = swap.drawable;
440 vbl_swap->pipe = swap.pipe; 470 vbl_swap->pipe = pipe;
441 vbl_swap->sequence = swap.sequence; 471 vbl_swap->sequence = swap.sequence;
442 472
443 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); 473 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
@@ -447,6 +477,9 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
447 477
448 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); 478 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
449 479
480 DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap,
481 sizeof(swap));
482
450 return 0; 483 return 0;
451} 484}
452 485