diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/drm/i915_drm.h | 3 | ||||
-rw-r--r-- | drivers/char/drm/i915_irq.c | 43 |
2 files changed, 40 insertions, 6 deletions
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 8926beb5a61f..4ce3d16cf065 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h | |||
@@ -149,6 +149,7 @@ typedef struct _drm_i915_sarea { | |||
149 | #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) | 149 | #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) |
150 | #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) | 150 | #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) |
151 | #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) | 151 | #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) |
152 | #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) | ||
152 | 153 | ||
153 | /* Allow drivers to submit batchbuffers directly to hardware, relying | 154 | /* Allow drivers to submit batchbuffers directly to hardware, relying |
154 | * on the security mechanisms provided by hardware. | 155 | * on the security mechanisms provided by hardware. |
@@ -248,7 +249,7 @@ typedef struct drm_i915_vblank_pipe { | |||
248 | */ | 249 | */ |
249 | typedef struct drm_i915_vblank_swap { | 250 | typedef struct drm_i915_vblank_swap { |
250 | drm_drawable_t drawable; | 251 | drm_drawable_t drawable; |
251 | unsigned int pipe; | 252 | drm_vblank_seq_type_t seqtype; |
252 | unsigned int sequence; | 253 | unsigned int sequence; |
253 | } drm_i915_vblank_swap_t; | 254 | } drm_i915_vblank_swap_t; |
254 | 255 | ||
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 | ||