Commit a3293a85 authored by Benjamin Gaignard's avatar Benjamin Gaignard Committed by Hans Verkuil
Browse files

media: v4l2: Add REMOVE_BUFS ioctl



VIDIOC_REMOVE_BUFS ioctl allows to remove buffers from a queue.
The number of buffers to remove in given by count field of
struct v4l2_remove_buffers and the range start at the index
specified in the same structure.

Signed-off-by: default avatarBenjamin Gaignard <benjamin.gaignard@collabora.com>
Reviewed-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
[hverkuil: vidioc-remove-bufs.rst: mention no bufs are freed on error]
parent 5fb19f20
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ Function Reference
    vidioc-query-dv-timings
    vidioc-querystd
    vidioc-reqbufs
    vidioc-remove-bufs
    vidioc-s-hw-freq-seek
    vidioc-streamon
    vidioc-subdev-enum-frame-interval
+86 −0
Original line number Diff line number Diff line
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
.. c:namespace:: V4L

.. _VIDIOC_REMOVE_BUFS:

************************
ioctl VIDIOC_REMOVE_BUFS
************************

Name
====

VIDIOC_REMOVE_BUFS - Removes buffers from a queue

Synopsis
========

.. c:macro:: VIDIOC_REMOVE_BUFS

``int ioctl(int fd, VIDIOC_REMOVE_BUFS, struct v4l2_remove_buffers *argp)``

Arguments
=========

``fd``
    File descriptor returned by :c:func:`open()`.

``argp``
    Pointer to struct :c:type:`v4l2_remove_buffers`.

Description
===========

Applications can optionally call the :ref:`VIDIOC_REMOVE_BUFS` ioctl to
remove buffers from a queue.
:ref:`VIDIOC_CREATE_BUFS` ioctl support is mandatory to enable :ref:`VIDIOC_REMOVE_BUFS`.
This ioctl is available if the ``V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS`` capability
is set on the queue when :c:func:`VIDIOC_REQBUFS` or :c:func:`VIDIOC_CREATE_BUFS`
are invoked.

.. c:type:: v4l2_remove_buffers

.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.5cm}|

.. flat-table:: struct v4l2_remove_buffers
    :header-rows:  0
    :stub-columns: 0
    :widths:       1 1 2

    * - __u32
      - ``index``
      - The starting buffer index to remove. This field is ignored if count == 0.
    * - __u32
      - ``count``
      - The number of buffers to be removed with indices 'index' until 'index + count - 1'.
        All buffers in this range must be valid and in DEQUEUED state.
        :ref:`VIDIOC_REMOVE_BUFS` will always check the validity of ``type`, if it is
        invalid it returns ``EINVAL`` error code.
        If count is set to 0 :ref:`VIDIOC_REMOVE_BUFS` will do nothing and return 0.
    * - __u32
      - ``type``
      - Type of the stream or buffers, this is the same as the struct
	:c:type:`v4l2_format` ``type`` field. See
	:c:type:`v4l2_buf_type` for valid values.
    * - __u32
      - ``reserved``\ [13]
      - A place holder for future extensions. Drivers and applications
	must set the array to zero.

Return Value
============

On success 0 is returned, on error -1 and the ``errno`` variable is set
appropriately. The generic error codes are described at the
:ref:`Generic Error Codes <gen-errors>` chapter. If an error occurs, no
buffers will be freed and one of the error codes below will be returned:

EBUSY
    File I/O is in progress.
    One or more of the buffers in the range ``index`` to ``index + count - 1`` are not
    in DEQUEUED state.

EINVAL
    One or more of the buffers in the range ``index`` to ``index + count - 1`` do not
    exist in the queue.
    The buffer type (``type`` field) is not valid.
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ aborting or finishing any DMA in progress, an implicit
.. _V4L2-BUF-CAP-SUPPORTS-M2M-HOLD-CAPTURE-BUF:
.. _V4L2-BUF-CAP-SUPPORTS-MMAP-CACHE-HINTS:
.. _V4L2-BUF-CAP-SUPPORTS-MAX-NUM-BUFFERS:
.. _V4L2-BUF-CAP-SUPPORTS-REMOVE-BUFS:

.. raw:: latex

+38 −0
Original line number Diff line number Diff line
@@ -1691,6 +1691,44 @@ int vb2_core_prepare_buf(struct vb2_queue *q, struct vb2_buffer *vb, void *pb)
}
EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);

int vb2_core_remove_bufs(struct vb2_queue *q, unsigned int start, unsigned int count)
{
	unsigned int i, ret = 0;
	unsigned int q_num_bufs = vb2_get_num_buffers(q);

	if (count == 0)
		return 0;

	if (count > q_num_bufs)
		return -EINVAL;

	if (start > q->max_num_buffers - count)
		return -EINVAL;

	mutex_lock(&q->mmap_lock);

	/* Check that all buffers in the range exist */
	for (i = start; i < start + count; i++) {
		struct vb2_buffer *vb = vb2_get_buffer(q, i);

		if (!vb) {
			ret = -EINVAL;
			goto unlock;
		}
		if (vb->state != VB2_BUF_STATE_DEQUEUED) {
			ret = -EBUSY;
			goto unlock;
		}
	}
	__vb2_queue_free(q, start, count);
	dprintk(q, 2, "%u buffers removed\n", count);

unlock:
	mutex_unlock(&q->mmap_lock);
	return ret;
}
EXPORT_SYMBOL_GPL(vb2_core_remove_bufs);

/*
 * vb2_start_streaming() - Attempt to start streaming.
 * @q:		videobuf2 queue
+19 −1
Original line number Diff line number Diff line
@@ -685,7 +685,7 @@ static void vb2_set_flags_and_caps(struct vb2_queue *q, u32 memory,
		*flags &= V4L2_MEMORY_FLAG_NON_COHERENT;
	}

	*caps = V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS;
	*caps |= V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS;
	if (q->io_modes & VB2_MMAP)
		*caps |= V4L2_BUF_CAP_SUPPORTS_MMAP;
	if (q->io_modes & VB2_USERPTR)
@@ -1001,6 +1001,24 @@ EXPORT_SYMBOL_GPL(vb2_poll);

/* vb2 ioctl helpers */

int vb2_ioctl_remove_bufs(struct file *file, void *priv,
			  struct v4l2_remove_buffers *d)
{
	struct video_device *vdev = video_devdata(file);

	if (vdev->queue->type != d->type)
		return -EINVAL;

	if (d->count == 0)
		return 0;

	if (vb2_queue_is_busy(vdev->queue, file))
		return -EBUSY;

	return vb2_core_remove_bufs(vdev->queue, d->index, d->count);
}
EXPORT_SYMBOL_GPL(vb2_ioctl_remove_bufs);

int vb2_ioctl_reqbufs(struct file *file, void *priv,
			  struct v4l2_requestbuffers *p)
{
Loading