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

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
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -121,7 +121,12 @@ than the number requested.
	other changes, then set ``count`` to 0, ``memory`` to
	``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type.
    * - __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
	must set the array to zero.

+9 −2
Original line number Diff line number Diff line
@@ -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
	free any previously allocated buffers, so this is typically something
	that will be done at the start of the application.
    * - union {
      - (anonymous)
    * - __u32
      - ``flags``
      - Specifies additional buffer management attributes.
	See :ref:`memory-flags`.
    * - __u32
      - ``reserved``\ [1]
      - A place holder for future extensions. Drivers and applications
	must set the array to zero.
      - Kept for backwards compatibility. Use ``flags`` instead.
    * - }
      -

.. tabularcolumns:: |p{6.1cm}|p{2.2cm}|p{8.7cm}|

+6 −0
Original line number Diff line number Diff line
@@ -694,6 +694,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
	unsigned int i;
	int ret;

	if (flags & V4L2_FLAG_MEMORY_NON_CONSISTENT)
		consistent_mem = false;

	if (q->streaming) {
		dprintk(1, "streaming active\n");
		return -EBUSY;
@@ -837,6 +840,9 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
	bool consistent_mem = true;
	int ret;

	if (flags & V4L2_FLAG_MEMORY_NON_CONSISTENT)
		consistent_mem = false;

	if (q->num_buffers == VB2_MAX_FRAME) {
		dprintk(1, "maximum number of buffers already allocated\n");
		return -ENOBUFS;
+20 −4
Original line number Diff line number Diff line
@@ -718,12 +718,22 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
#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 ret = vb2_verify_memory_type(q, req->memory, req->type);

	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);

@@ -755,6 +765,7 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
	unsigned i;

	fill_buf_caps(q, &create->capabilities);
	clear_consistency_attr(q, create->memory, &create->flags);
	create->index = q->num_buffers;
	if (create->count == 0)
		return ret != -EBUSY ? ret : 0;
@@ -797,8 +808,11 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
	for (i = 0; i < requested_planes; i++)
		if (requested_sizes[i] == 0)
			return -EINVAL;
	return ret ? ret : vb2_core_create_bufs(q, create->memory, 0,
		&create->count, requested_planes, requested_sizes);
	return ret ? ret : vb2_core_create_bufs(q, create->memory,
						create->flags,
						&create->count,
						requested_planes,
						requested_sizes);
}
EXPORT_SYMBOL_GPL(vb2_create_bufs);

@@ -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);

	fill_buf_caps(vdev->queue, &p->capabilities);
	clear_consistency_attr(vdev->queue, p->memory, &p->flags);
	if (res)
		return res;
	if (vb2_queue_is_busy(vdev, file))
		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
	   is no longer owner of the queue. Otherwise we have a new owner. */
	if (res == 0)
@@ -991,6 +1006,7 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv,

	p->index = vdev->queue->num_buffers;
	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.
	 * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
+8 −2
Original line number Diff line number Diff line
@@ -246,6 +246,9 @@ struct v4l2_format32 {
 * @memory:	buffer memory type
 * @format:	frame format, for which buffers are requested
 * @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
 */
struct v4l2_create_buffers32 {
@@ -254,7 +257,8 @@ struct v4l2_create_buffers32 {
	__u32			memory;	/* enum v4l2_memory */
	struct v4l2_format32	format;
	__u32			capabilities;
	__u32			reserved[7];
	__u32			flags;
	__u32			reserved[6];
};

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,
{
	if (!access_ok(p32, sizeof(*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 __get_v4l2_format32(&p64->format, &p32->format,
				   aux_buf, aux_space);
@@ -417,6 +422,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers __user *p64,
	    copy_in_user(p32, p64,
			 offsetof(struct v4l2_create_buffers32, format)) ||
	    assign_in_user(&p32->capabilities, &p64->capabilities) ||
	    assign_in_user(&p32->flags, &p64->flags) ||
	    copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
		return -EFAULT;
	return __put_v4l2_format32(&p64->format, &p32->format);
Loading