Commit 1e0b2318 authored by Sergey Senozhatsky's avatar Sergey Senozhatsky Committed by Mauro Carvalho Chehab

media: videobuf2: handle V4L2_FLAG_MEMORY_NON_CONSISTENT flag

This patch lets user-space to request a non-consistent memory
allocation during CREATE_BUFS and REQBUFS ioctl calls.

= CREATE_BUFS

  struct v4l2_create_buffers has seven 4-byte reserved areas,
  so reserved[0] is renamed to ->flags. The struct, thus, now
  has six reserved 4-byte regions.

= CREATE_BUFS32

  struct v4l2_create_buffers32 has seven 4-byte reserved areas,
  so reserved[0] is renamed to ->flags. The struct, thus, now
  has six reserved 4-byte regions.

= REQBUFS

 We use one bit of a ->reserved[1] member of struct v4l2_requestbuffers,
 which is now renamed to ->flags. Unlike v4l2_create_buffers, struct
 v4l2_requestbuffers does not have enough reserved room. Therefore for
 backward compatibility  ->reserved and ->flags were put into anonymous
 union.
Signed-off-by: default avatarSergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 7b4b4555
...@@ -121,7 +121,12 @@ than the number requested. ...@@ -121,7 +121,12 @@ than the number requested.
other changes, then set ``count`` to 0, ``memory`` to other changes, then set ``count`` to 0, ``memory`` to
``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type. ``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type.
* - __u32 * - __u32
- ``reserved``\ [7] - ``flags``
- Specifies additional buffer management attributes.
See :ref:`memory-flags`.
* - __u32
- ``reserved``\ [6]
- A place holder for future extensions. Drivers and applications - A place holder for future extensions. Drivers and applications
must set the array to zero. must set the array to zero.
......
...@@ -112,10 +112,17 @@ aborting or finishing any DMA in progress, an implicit ...@@ -112,10 +112,17 @@ aborting or finishing any DMA in progress, an implicit
``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will ``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will
free any previously allocated buffers, so this is typically something free any previously allocated buffers, so this is typically something
that will be done at the start of the application. that will be done at the start of the application.
* - union {
- (anonymous)
* - __u32
- ``flags``
- Specifies additional buffer management attributes.
See :ref:`memory-flags`.
* - __u32 * - __u32
- ``reserved``\ [1] - ``reserved``\ [1]
- A place holder for future extensions. Drivers and applications - Kept for backwards compatibility. Use ``flags`` instead.
must set the array to zero. * - }
-
.. tabularcolumns:: |p{6.1cm}|p{2.2cm}|p{8.7cm}| .. tabularcolumns:: |p{6.1cm}|p{2.2cm}|p{8.7cm}|
......
...@@ -694,6 +694,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, ...@@ -694,6 +694,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
unsigned int i; unsigned int i;
int ret; int ret;
if (flags & V4L2_FLAG_MEMORY_NON_CONSISTENT)
consistent_mem = false;
if (q->streaming) { if (q->streaming) {
dprintk(1, "streaming active\n"); dprintk(1, "streaming active\n");
return -EBUSY; return -EBUSY;
...@@ -837,6 +840,9 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, ...@@ -837,6 +840,9 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
bool consistent_mem = true; bool consistent_mem = true;
int ret; int ret;
if (flags & V4L2_FLAG_MEMORY_NON_CONSISTENT)
consistent_mem = false;
if (q->num_buffers == VB2_MAX_FRAME) { if (q->num_buffers == VB2_MAX_FRAME) {
dprintk(1, "maximum number of buffers already allocated\n"); dprintk(1, "maximum number of buffers already allocated\n");
return -ENOBUFS; return -ENOBUFS;
......
...@@ -718,12 +718,22 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps) ...@@ -718,12 +718,22 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
#endif #endif
} }
static void clear_consistency_attr(struct vb2_queue *q,
int memory,
unsigned int *flags)
{
if (!q->allow_cache_hints || memory != V4L2_MEMORY_MMAP)
*flags &= ~V4L2_FLAG_MEMORY_NON_CONSISTENT;
}
int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
{ {
int ret = vb2_verify_memory_type(q, req->memory, req->type); int ret = vb2_verify_memory_type(q, req->memory, req->type);
fill_buf_caps(q, &req->capabilities); fill_buf_caps(q, &req->capabilities);
return ret ? ret : vb2_core_reqbufs(q, req->memory, 0, &req->count); clear_consistency_attr(q, req->memory, &req->flags);
return ret ? ret : vb2_core_reqbufs(q, req->memory,
req->flags, &req->count);
} }
EXPORT_SYMBOL_GPL(vb2_reqbufs); EXPORT_SYMBOL_GPL(vb2_reqbufs);
...@@ -755,6 +765,7 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) ...@@ -755,6 +765,7 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
unsigned i; unsigned i;
fill_buf_caps(q, &create->capabilities); fill_buf_caps(q, &create->capabilities);
clear_consistency_attr(q, create->memory, &create->flags);
create->index = q->num_buffers; create->index = q->num_buffers;
if (create->count == 0) if (create->count == 0)
return ret != -EBUSY ? ret : 0; return ret != -EBUSY ? ret : 0;
...@@ -797,8 +808,11 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) ...@@ -797,8 +808,11 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
for (i = 0; i < requested_planes; i++) for (i = 0; i < requested_planes; i++)
if (requested_sizes[i] == 0) if (requested_sizes[i] == 0)
return -EINVAL; return -EINVAL;
return ret ? ret : vb2_core_create_bufs(q, create->memory, 0, return ret ? ret : vb2_core_create_bufs(q, create->memory,
&create->count, requested_planes, requested_sizes); create->flags,
&create->count,
requested_planes,
requested_sizes);
} }
EXPORT_SYMBOL_GPL(vb2_create_bufs); EXPORT_SYMBOL_GPL(vb2_create_bufs);
...@@ -969,11 +983,12 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv, ...@@ -969,11 +983,12 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv,
int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type); int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
fill_buf_caps(vdev->queue, &p->capabilities); fill_buf_caps(vdev->queue, &p->capabilities);
clear_consistency_attr(vdev->queue, p->memory, &p->flags);
if (res) if (res)
return res; return res;
if (vb2_queue_is_busy(vdev, file)) if (vb2_queue_is_busy(vdev, file))
return -EBUSY; return -EBUSY;
res = vb2_core_reqbufs(vdev->queue, p->memory, 0, &p->count); res = vb2_core_reqbufs(vdev->queue, p->memory, p->flags, &p->count);
/* If count == 0, then the owner has released all buffers and he /* If count == 0, then the owner has released all buffers and he
is no longer owner of the queue. Otherwise we have a new owner. */ is no longer owner of the queue. Otherwise we have a new owner. */
if (res == 0) if (res == 0)
...@@ -991,6 +1006,7 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv, ...@@ -991,6 +1006,7 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv,
p->index = vdev->queue->num_buffers; p->index = vdev->queue->num_buffers;
fill_buf_caps(vdev->queue, &p->capabilities); fill_buf_caps(vdev->queue, &p->capabilities);
clear_consistency_attr(vdev->queue, p->memory, &p->flags);
/* /*
* If count == 0, then just check if memory and type are valid. * If count == 0, then just check if memory and type are valid.
* Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
......
...@@ -246,6 +246,9 @@ struct v4l2_format32 { ...@@ -246,6 +246,9 @@ struct v4l2_format32 {
* @memory: buffer memory type * @memory: buffer memory type
* @format: frame format, for which buffers are requested * @format: frame format, for which buffers are requested
* @capabilities: capabilities of this buffer type. * @capabilities: capabilities of this buffer type.
* @flags: additional buffer management attributes (ignored unless the
* queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
* configured for MMAP streaming I/O).
* @reserved: future extensions * @reserved: future extensions
*/ */
struct v4l2_create_buffers32 { struct v4l2_create_buffers32 {
...@@ -254,7 +257,8 @@ struct v4l2_create_buffers32 { ...@@ -254,7 +257,8 @@ struct v4l2_create_buffers32 {
__u32 memory; /* enum v4l2_memory */ __u32 memory; /* enum v4l2_memory */
struct v4l2_format32 format; struct v4l2_format32 format;
__u32 capabilities; __u32 capabilities;
__u32 reserved[7]; __u32 flags;
__u32 reserved[6];
}; };
static int __bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size) static int __bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size)
...@@ -355,7 +359,8 @@ static int get_v4l2_create32(struct v4l2_create_buffers __user *p64, ...@@ -355,7 +359,8 @@ static int get_v4l2_create32(struct v4l2_create_buffers __user *p64,
{ {
if (!access_ok(p32, sizeof(*p32)) || if (!access_ok(p32, sizeof(*p32)) ||
copy_in_user(p64, p32, copy_in_user(p64, p32,
offsetof(struct v4l2_create_buffers32, format))) offsetof(struct v4l2_create_buffers32, format)) ||
assign_in_user(&p64->flags, &p32->flags))
return -EFAULT; return -EFAULT;
return __get_v4l2_format32(&p64->format, &p32->format, return __get_v4l2_format32(&p64->format, &p32->format,
aux_buf, aux_space); aux_buf, aux_space);
...@@ -417,6 +422,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers __user *p64, ...@@ -417,6 +422,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers __user *p64,
copy_in_user(p32, p64, copy_in_user(p32, p64,
offsetof(struct v4l2_create_buffers32, format)) || offsetof(struct v4l2_create_buffers32, format)) ||
assign_in_user(&p32->capabilities, &p64->capabilities) || assign_in_user(&p32->capabilities, &p64->capabilities) ||
assign_in_user(&p32->flags, &p64->flags) ||
copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved))) copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
return -EFAULT; return -EFAULT;
return __put_v4l2_format32(&p64->format, &p32->format); return __put_v4l2_format32(&p64->format, &p32->format);
......
...@@ -2038,9 +2038,6 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, ...@@ -2038,9 +2038,6 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,
if (ret) if (ret)
return ret; return ret;
CLEAR_AFTER_FIELD(p, capabilities);
return ops->vidioc_reqbufs(file, fh, p); return ops->vidioc_reqbufs(file, fh, p);
} }
...@@ -2080,7 +2077,7 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, ...@@ -2080,7 +2077,7 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
if (ret) if (ret)
return ret; return ret;
CLEAR_AFTER_FIELD(create, capabilities); CLEAR_AFTER_FIELD(create, flags);
v4l_sanitize_format(&create->format); v4l_sanitize_format(&create->format);
......
...@@ -946,7 +946,10 @@ struct v4l2_requestbuffers { ...@@ -946,7 +946,10 @@ struct v4l2_requestbuffers {
__u32 type; /* enum v4l2_buf_type */ __u32 type; /* enum v4l2_buf_type */
__u32 memory; /* enum v4l2_memory */ __u32 memory; /* enum v4l2_memory */
__u32 capabilities; __u32 capabilities;
__u32 reserved[1]; union {
__u32 flags;
__u32 reserved[1];
};
}; };
/* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */ /* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
...@@ -2450,6 +2453,9 @@ struct v4l2_dbg_chip_info { ...@@ -2450,6 +2453,9 @@ struct v4l2_dbg_chip_info {
* @memory: enum v4l2_memory; buffer memory type * @memory: enum v4l2_memory; buffer memory type
* @format: frame format, for which buffers are requested * @format: frame format, for which buffers are requested
* @capabilities: capabilities of this buffer type. * @capabilities: capabilities of this buffer type.
* @flags: additional buffer management attributes (ignored unless the
* queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability
* and configured for MMAP streaming I/O).
* @reserved: future extensions * @reserved: future extensions
*/ */
struct v4l2_create_buffers { struct v4l2_create_buffers {
...@@ -2458,7 +2464,8 @@ struct v4l2_create_buffers { ...@@ -2458,7 +2464,8 @@ struct v4l2_create_buffers {
__u32 memory; __u32 memory;
struct v4l2_format format; struct v4l2_format format;
__u32 capabilities; __u32 capabilities;
__u32 reserved[7]; __u32 flags;
__u32 reserved[6];
}; };
/* /*
......
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