Commit 541f29aa authored by =?utf-8?q?Michel_D=C3=A4nzer?='s avatar =?utf-8?q?Michel_D=C3=A4nzer?= Committed by airlied

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: default avatarDave Airlie <airlied@linux.ie>
parent a6b54f3f
...@@ -149,6 +149,7 @@ typedef struct _drm_i915_sarea { ...@@ -149,6 +149,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
/* Allow drivers to submit batchbuffers directly to hardware, relying /* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware. * on the security mechanisms provided by hardware.
...@@ -248,7 +249,7 @@ typedef struct drm_i915_vblank_pipe { ...@@ -248,7 +249,7 @@ typedef struct drm_i915_vblank_pipe {
*/ */
typedef struct drm_i915_vblank_swap { typedef struct drm_i915_vblank_swap {
drm_drawable_t drawable; drm_drawable_t drawable;
unsigned int pipe; drm_vblank_seq_type_t seqtype;
unsigned int sequence; unsigned int sequence;
} drm_i915_vblank_swap_t; } drm_i915_vblank_swap_t;
......
...@@ -375,7 +375,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) ...@@ -375,7 +375,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_vblank_swap_t swap; drm_i915_vblank_swap_t swap;
drm_i915_vbl_swap_t *vbl_swap; drm_i915_vbl_swap_t *vbl_swap;
unsigned int irqflags; unsigned int pipe, seqtype, irqflags, curseq;
struct list_head *list; struct list_head *list;
if (!dev_priv) { if (!dev_priv) {
...@@ -396,8 +396,23 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) ...@@ -396,8 +396,23 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data, DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data,
sizeof(swap)); sizeof(swap));
if (swap.pipe > 1 || !(dev_priv->vblank_pipe & (1 << swap.pipe))) { if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
DRM_ERROR("Invalid pipe %d\n", swap.pipe); _DRM_VBLANK_SECONDARY)) {
DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
return DRM_ERR(EINVAL);
}
pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
if (seqtype == _DRM_VBLANK_RELATIVE && swap.sequence == 0) {
DRM_DEBUG("Not scheduling swap for current sequence\n");
return DRM_ERR(EINVAL);
}
if (!(dev_priv->vblank_pipe & (1 << pipe))) {
DRM_ERROR("Invalid pipe %d\n", pipe);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
...@@ -411,13 +426,28 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) ...@@ -411,13 +426,28 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
spin_unlock_irqrestore(&dev->drw_lock, irqflags); spin_unlock_irqrestore(&dev->drw_lock, irqflags);
curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
switch (seqtype) {
case _DRM_VBLANK_RELATIVE:
swap.sequence += curseq;
break;
case _DRM_VBLANK_ABSOLUTE:
if ((curseq - swap.sequence) > (1<<23)) {
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
DRM_DEBUG("Missed target sequence\n");
return DRM_ERR(EINVAL);
}
break;
}
list_for_each(list, &dev_priv->vbl_swaps.head) { list_for_each(list, &dev_priv->vbl_swaps.head) {
vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
if (vbl_swap->drw_id == swap.drawable && if (vbl_swap->drw_id == swap.drawable &&
vbl_swap->pipe == swap.pipe && vbl_swap->pipe == pipe &&
vbl_swap->sequence == swap.sequence) { vbl_swap->sequence == swap.sequence) {
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
DRM_DEBUG("Already scheduled\n"); DRM_DEBUG("Already scheduled\n");
...@@ -437,7 +467,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) ...@@ -437,7 +467,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
DRM_DEBUG("\n"); DRM_DEBUG("\n");
vbl_swap->drw_id = swap.drawable; vbl_swap->drw_id = swap.drawable;
vbl_swap->pipe = swap.pipe; vbl_swap->pipe = pipe;
vbl_swap->sequence = swap.sequence; vbl_swap->sequence = swap.sequence;
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
...@@ -447,6 +477,9 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) ...@@ -447,6 +477,9 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap,
sizeof(swap));
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment