media: videobuf2: handle V4L2_MEMORY_FLAG_NON_COHERENT flag

This patch lets user-space request a non-coherent 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 byte of a 4 byte ->reserved[1] member of struct
 v4l2_requestbuffers. The struct, thus, now has reserved 3 bytes.

Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Sergey Senozhatsky 2021-09-09 13:24:29 +02:00 коммит произвёл Mauro Carvalho Chehab
Родитель b00a9e59c5
Коммит c0acf9cfee
7 изменённых файлов: 60 добавлений и 15 удалений

Просмотреть файл

@ -113,7 +113,12 @@ than the number requested.
``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.

Просмотреть файл

@ -104,10 +104,13 @@ 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.
* - __u32 * - __u8
- ``reserved``\ [1] - ``flags``
- A place holder for future extensions. Drivers and applications - Specifies additional buffer management attributes.
must set the array to zero. See :ref:`memory-flags`.
* - __u8
- ``reserved``\ [3]
- Reserved for future extensions.
.. _v4l2-buf-capabilities: .. _v4l2-buf-capabilities:
.. _V4L2-BUF-CAP-SUPPORTS-MMAP: .. _V4L2-BUF-CAP-SUPPORTS-MMAP:

Просмотреть файл

@ -761,7 +761,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
{ {
unsigned int num_buffers, allocated_buffers, num_planes = 0; unsigned int num_buffers, allocated_buffers, num_planes = 0;
unsigned plane_sizes[VB2_MAX_PLANES] = { }; unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = false; bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
unsigned int i; unsigned int i;
int ret; int ret;
@ -905,7 +905,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
{ {
unsigned int num_planes = 0, num_buffers, allocated_buffers; unsigned int num_planes = 0, num_buffers, allocated_buffers;
unsigned plane_sizes[VB2_MAX_PLANES] = { }; unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = false; bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
int ret; int ret;
if (q->num_buffers == VB2_MAX_FRAME) { if (q->num_buffers == VB2_MAX_FRAME) {

Просмотреть файл

@ -692,12 +692,32 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
#endif #endif
} }
static void validate_memory_flags(struct vb2_queue *q,
int memory,
u32 *flags)
{
if (!q->allow_cache_hints || memory != V4L2_MEMORY_MMAP) {
/*
* This needs to clear V4L2_MEMORY_FLAG_NON_COHERENT only,
* but in order to avoid bugs we zero out all bits.
*/
*flags = 0;
} else {
/* Clear all unknown flags. */
*flags &= V4L2_MEMORY_FLAG_NON_COHERENT;
}
}
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);
u32 flags = req->flags;
fill_buf_caps(q, &req->capabilities); fill_buf_caps(q, &req->capabilities);
return ret ? ret : vb2_core_reqbufs(q, req->memory, 0, &req->count); validate_memory_flags(q, req->memory, &flags);
req->flags = flags;
return ret ? ret : vb2_core_reqbufs(q, req->memory,
req->flags, &req->count);
} }
EXPORT_SYMBOL_GPL(vb2_reqbufs); EXPORT_SYMBOL_GPL(vb2_reqbufs);
@ -729,6 +749,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);
validate_memory_flags(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;
@ -772,7 +793,7 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
if (requested_sizes[i] == 0) if (requested_sizes[i] == 0)
return -EINVAL; return -EINVAL;
return ret ? ret : vb2_core_create_bufs(q, create->memory, return ret ? ret : vb2_core_create_bufs(q, create->memory,
0, create->flags,
&create->count, &create->count,
requested_planes, requested_planes,
requested_sizes); requested_sizes);
@ -969,13 +990,16 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv,
{ {
struct video_device *vdev = video_devdata(file); struct video_device *vdev = video_devdata(file);
int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type); int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
u32 flags = p->flags;
fill_buf_caps(vdev->queue, &p->capabilities); fill_buf_caps(vdev->queue, &p->capabilities);
validate_memory_flags(vdev->queue, p->memory, &flags);
p->flags = 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)
@ -993,6 +1017,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);
validate_memory_flags(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.

Просмотреть файл

@ -126,6 +126,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 {
@ -134,7 +137,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 get_v4l2_format32(struct v4l2_format *p64, static int get_v4l2_format32(struct v4l2_format *p64,
@ -182,6 +186,8 @@ static int get_v4l2_create32(struct v4l2_create_buffers *p64,
if (copy_from_user(p64, p32, if (copy_from_user(p64, p32,
offsetof(struct v4l2_create_buffers32, format))) offsetof(struct v4l2_create_buffers32, format)))
return -EFAULT; return -EFAULT;
if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
return -EFAULT;
return get_v4l2_format32(&p64->format, &p32->format); return get_v4l2_format32(&p64->format, &p32->format);
} }
@ -227,6 +233,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers *p64,
if (copy_to_user(p32, p64, if (copy_to_user(p32, p64,
offsetof(struct v4l2_create_buffers32, format)) || offsetof(struct v4l2_create_buffers32, format)) ||
put_user(p64->capabilities, &p32->capabilities) || put_user(p64->capabilities, &p32->capabilities) ||
put_user(p64->flags, &p32->flags) ||
copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved))) copy_to_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);

Просмотреть файл

@ -2024,7 +2024,7 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,
if (ret) if (ret)
return ret; return ret;
CLEAR_AFTER_FIELD(p, capabilities); CLEAR_AFTER_FIELD(p, flags);
return ops->vidioc_reqbufs(file, fh, p); return ops->vidioc_reqbufs(file, fh, p);
} }
@ -2065,7 +2065,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);

Просмотреть файл

@ -959,7 +959,8 @@ 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]; __u8 flags;
__u8 reserved[3];
}; };
#define V4L2_MEMORY_FLAG_NON_COHERENT (1 << 0) #define V4L2_MEMORY_FLAG_NON_COHERENT (1 << 0)
@ -2507,6 +2508,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 {
@ -2515,7 +2519,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];
}; };
/* /*