From patchwork Tue Nov 12 09:22:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 842806 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4323720DD7B for ; Tue, 12 Nov 2024 09:33:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731404005; cv=none; b=IYVqVVh1hLHuKp4LN8EnATKq/30BaKXcycPN9Vm6rl0pImxT72zVCw7W8SgFJ8U0UxzT0lEzx6k0Tn20ffiYWXmubtC/n5Ats/wHL1x68OiQvFLsn5VKkiIzK3u/rdzrf/O96mgbkVQ93E3DSxM5jh/0UcEbwxCORXdtIeEP5Yo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731404005; c=relaxed/simple; bh=fB2PomdAzt/DzHHPe6DJp4oV43MOnlpIo/E9fNbMbak=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=clyW4Vpk6GWsIT3l7wzLNkfBIbxmB9Yz6ChSbMJZCpo1pIzVcgOvjb4FPO30gvt7F9ILoH4c0Nb00SzXzPxm34vbncJMU3lawK2sXM0y/+scoM1IAkLHE1chLgh+OXWe0obbhskpCUQae2I3sZMusczQbcDX62MgpV1a5M5rSFE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0AB22C4CECD; Tue, 12 Nov 2024 09:33:23 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Laurent Pinchart , Hans Verkuil Subject: [RFC PATCHv2 2/5] Documentation: media: document min/rec_num_buffers Date: Tue, 12 Nov 2024 10:22:13 +0100 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Document the new min_num_buffers and rec_num_buffers fields and the corresponding V4L2_BUF_CAP_SUPPORTS_MIN_REC_NUM_BUFFERS capability flag. Signed-off-by: Hans Verkuil --- .../media/v4l/vidioc-create-bufs.rst | 34 +++++++++++++++---- .../media/v4l/vidioc-reqbufs.rst | 6 ++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/vidioc-create-bufs.rst b/Documentation/userspace-api/media/v4l/vidioc-create-bufs.rst index 49232c9006c2..a400d464cc9f 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-create-bufs.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-create-bufs.rst @@ -68,7 +68,12 @@ When the ioctl is called with a pointer to this structure the driver will attempt to allocate up to the requested number of buffers and store the actual number allocated and the starting index in the ``count`` and the ``index`` fields respectively. On return ``count`` can be smaller -than the number requested. +than the number requested, but never larger. If no buffers could be +allocated, then -1 is returned and errno is set to the ``ENOMEM`` error code. + +If ``count`` was set to 0, then no buffers are allocated, and instead +it just sets the various informative fields, e.g. ``capabilities``, +``max_num_buffers``, etc. .. c:type:: v4l2_create_buffers @@ -88,9 +93,9 @@ than the number requested. :ref:`VIDIOC_CREATE_BUFS` will set ``index`` to the current number of created buffers, and it will check the validity of ``memory`` and ``format.type``. If those are invalid -1 is returned and errno is - set to ``EINVAL`` error code, otherwise :ref:`VIDIOC_CREATE_BUFS` returns - 0. It will never set errno to ``EBUSY`` error code in this particular - case. + set to the ``EINVAL`` error code, otherwise :ref:`VIDIOC_CREATE_BUFS` + returns 0. It will never set errno to the ``EBUSY`` error code in this + particular case. * - __u32 - ``memory`` - Applications set this field to ``V4L2_MEMORY_MMAP``, @@ -118,11 +123,26 @@ than the number requested. See :ref:`memory-flags`. * - __u32 - ``max_num_buffers`` - - If the V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS capability flag is set - this field indicates the maximum possible number of buffers + - If the ``V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS`` capability flag is + set this field indicates the maximum possible number of buffers for this queue. + * - __u16 + - ``min_num_buffers`` + - If the ``V4L2_BUF_CAP_SUPPORTS_MIN_REC_NUM_BUFFERS`` capability flag is + set this field indicates the minimum number of buffers for this queue. + Allocating this number of buffers will allow video streaming, but frame + drops might happen. + * - __u16 + - ``rec_num_buffers`` + - If the ``V4L2_BUF_CAP_SUPPORTS_MIN_REC_NUM_BUFFERS`` capability flag is + set this field indicates the recommended number of buffers for this + queue. + The :ref:`VIDIOC_REQBUFS` will use this value if the requested number of + buffers is less than this value. This value ensures reliable video + streaming without frame drops, provided the application can process + a dequeued buffer within a single frame period. * - __u32 - - ``reserved``\ [5] + - ``reserved``\ [4] - A place holder for future extensions. Drivers and applications must set the array to zero. diff --git a/Documentation/userspace-api/media/v4l/vidioc-reqbufs.rst b/Documentation/userspace-api/media/v4l/vidioc-reqbufs.rst index daf9a6621b50..4c5bb303b5a2 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-reqbufs.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-reqbufs.rst @@ -124,6 +124,7 @@ aborting or finishing any DMA in progress, an implicit .. _V4L2-BUF-CAP-SUPPORTS-MMAP-CACHE-HINTS: .. _V4L2-BUF-CAP-SUPPORTS-MAX-NUM-BUFFERS: .. _V4L2-BUF-CAP-SUPPORTS-REMOVE-BUFS: +.. _V4L2-BUF-CAP-SUPPORTS-MIN-REC-NUM-BUFFERS: .. flat-table:: V4L2 Buffer Capabilities Flags :header-rows: 0 @@ -167,6 +168,11 @@ aborting or finishing any DMA in progress, an implicit * - ``V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS`` - 0x00000100 - If set, then ``VIDIOC_REMOVE_BUFS`` is supported. + * - ``V4L2_BUF_CAP_SUPPORTS_MIN_REC_NUM_BUFFERS`` + - 0x00000200 + - If set, then the ``min_num_buffers`` and ``rec_num_buffers`` fields in + ``struct v4l2_create_buffers`` are valid. If not set, then these fields + are 0. .. _memory-flags: .. _V4L2-MEMORY-FLAG-NON-COHERENT: From patchwork Tue Nov 12 09:22:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 842805 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 08F7D1ABEC2 for ; Tue, 12 Nov 2024 09:33:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731404008; cv=none; b=UTDYOltmGFokLqpSyTMeSqDISIgbCOLAoiYGYB9ryKxiEdfOvKlLPxxH8qr5X8vE/Lk6bM9FsNlUHbpCklUvjqrp/7zAvznBvF9Rq0wv5v6w+/1ZCsgtw41t/MrU9rbbuRa4ULWVHB/ZDqz52nWLGtgIXf1hfuAW08DzvpyBoz0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731404008; c=relaxed/simple; bh=bu3D/oQ1wnWfvuqBcAQoBX0km+bNjnKlHL0MK9ZD6Wo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OAOm34DNksbSOvb2BSMBYcNwZn7doaN2pbWM5hPCN9vZTW2vMs8DARhtBiFtW5XCaRadIefkKTcXBqXmr/nY8qLcmIbcmaIQc4KQE5xeo9CaireXSuNOQkJwxUfsGgzRNlQRyFdA0wxjsnCv9MUuTjap6p/VdcttsanWqvlMtDI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id AA488C4CED4; Tue, 12 Nov 2024 09:33:26 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Laurent Pinchart , Hans Verkuil Subject: [RFC PATCHv2 4/5] media: vb2: introduce queue_info to replace queue_setup Date: Tue, 12 Nov 2024 10:22:15 +0100 Message-ID: <541c146568fa67a7acc3aca87001f056751c638c.1731403336.git.hverkuil@xs4all.nl> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The new queue_info op just returns the number of planes and plane sizes for the currently configured format. Signed-off-by: Hans Verkuil --- .../media/common/videobuf2/videobuf2-core.c | 82 ++++++++++++++----- include/media/videobuf2-core.h | 10 +++ 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 4b55280dc8b8..bd241fe9474b 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -611,9 +611,9 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int start, unsigned i if (unbalanced) { pr_info("unbalanced counters for queue %p:\n", q); if (q->cnt_start_streaming != q->cnt_stop_streaming) - pr_info(" setup: %u start_streaming: %u stop_streaming: %u\n", - q->cnt_queue_setup, q->cnt_start_streaming, - q->cnt_stop_streaming); + pr_info(" setup: %u info: %u start_streaming: %u stop_streaming: %u\n", + q->cnt_queue_setup, q->cnt_queue_info, + q->cnt_start_streaming, q->cnt_stop_streaming); if (q->cnt_prepare_streaming != q->cnt_unprepare_streaming) pr_info(" prepare_streaming: %u unprepare_streaming: %u\n", q->cnt_prepare_streaming, q->cnt_unprepare_streaming); @@ -622,6 +622,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int start, unsigned i q->cnt_wait_prepare, q->cnt_wait_finish); } q->cnt_queue_setup = 0; + q->cnt_queue_info = 0; q->cnt_wait_prepare = 0; q->cnt_wait_finish = 0; q->cnt_prepare_streaming = 0; @@ -914,7 +915,8 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, q->is_busy = 0; /* * In case of REQBUFS(0) return immediately without calling - * driver's queue_setup() callback and allocating resources. + * driver's queue_setup() or queue_info() callback and + * allocating resources. */ if (*count == 0) return 0; @@ -928,7 +930,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, memset(q->alloc_devs, 0, sizeof(q->alloc_devs)); /* * Set this now to ensure that drivers see the correct q->memory value - * in the queue_setup op. + * in the queue_setup/info op. */ mutex_lock(&q->mmap_lock); ret = vb2_core_allocated_buffers_storage(q); @@ -938,12 +940,18 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, return ret; set_queue_coherency(q, non_coherent_mem); - /* - * Ask the driver how many buffers and planes per buffer it requires. - * Driver also sets the size and allocator context for each plane. - */ - ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, - plane_sizes, q->alloc_devs); + if (q->ops->queue_info) { + ret = call_qop(q, queue_info, q, &num_planes, + plane_sizes, q->alloc_devs); + } else { + /* + * Ask the driver how many buffers and planes per buffer it + * requires. The driver also sets the size and (optionally) + * the allocator context for each plane. + */ + ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, + plane_sizes, q->alloc_devs); + } if (ret) goto error; @@ -980,7 +988,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, /* * Check if driver can handle the allocated number of buffers. */ - if (!ret && allocated_buffers < num_buffers) { + if (!ret && allocated_buffers < num_buffers && q->ops->queue_setup) { num_buffers = allocated_buffers; /* * num_planes is set by the previous queue_setup(), but since it @@ -1082,17 +1090,44 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, num_buffers = min(*count, q->max_num_buffers - q_num_bufs); - if (requested_planes && requested_sizes) { + if (q->ops->queue_info) { + ret = call_qop(q, queue_info, q, &num_planes, + plane_sizes, q->alloc_devs); + + if (ret) + goto error; + + /* Check that driver has set sane values */ + if (WARN_ON(!num_planes)) { + ret = -EINVAL; + goto error; + } + if (num_planes != requested_planes) { + ret = -EINVAL; + goto error; + } + + for (unsigned int i = 0; i < num_planes; i++) { + if (WARN_ON(!plane_sizes[i])) { + ret = -EINVAL; + goto error; + } + if (plane_sizes[i] > requested_sizes[i]) { + ret = -EINVAL; + goto error; + } + plane_sizes[i] = requested_sizes[i]; + } + } else { num_planes = requested_planes; memcpy(plane_sizes, requested_sizes, sizeof(plane_sizes)); + /* + * Ask the driver, whether the requested number of buffers, planes per + * buffer and their sizes are acceptable + */ + ret = call_qop(q, queue_setup, q, &num_buffers, + &num_planes, plane_sizes, q->alloc_devs); } - - /* - * Ask the driver, whether the requested number of buffers, planes per - * buffer and their sizes are acceptable - */ - ret = call_qop(q, queue_setup, q, &num_buffers, - &num_planes, plane_sizes, q->alloc_devs); if (ret) goto error; @@ -1108,7 +1143,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, /* * Check if driver can handle the so far allocated number of buffers. */ - if (allocated_buffers < num_buffers) { + if (allocated_buffers < num_buffers && q->ops->queue_setup) { num_buffers = allocated_buffers; /* @@ -2619,10 +2654,13 @@ int vb2_core_queue_init(struct vb2_queue *q) WARN_ON(!q->mem_ops) || WARN_ON(!q->type) || WARN_ON(!q->io_modes) || - WARN_ON(!q->ops->queue_setup) || WARN_ON(!q->ops->buf_queue)) return -EINVAL; + if (WARN_ON(!q->ops->queue_setup && !q->ops->queue_info) || + WARN_ON(q->ops->queue_setup && q->ops->queue_info)) + return -EINVAL; + if (WARN_ON(q->max_num_buffers < VB2_MAX_FRAME) || WARN_ON(q->min_queued_buffers > q->max_num_buffers)) return -EINVAL; diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 3282b55179a5..89b7600e4cf6 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -351,6 +351,13 @@ struct vb2_buffer { * \*num_buffers are being allocated additionally to * the buffers already allocated. If either \*num_planes * or the requested sizes are invalid callback must return %-EINVAL. + * @queue_info: called from VIDIOC_REQBUFS() and VIDIOC_CREATE_BUFS() + * handlers before memory allocation. + * The driver must return the required number of planes + * per buffer in \*num_planes, and the size of each plane + * must be set in the sizes\[\] array. Optionally set the + * per-plane allocator specific device in the + * alloc_devs\[\] array. * @wait_prepare: release any locks taken while calling vb2 functions; * it is called before an ioctl needs to wait for a new * buffer to arrive; required to avoid a deadlock in @@ -435,6 +442,8 @@ struct vb2_ops { int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], struct device *alloc_devs[]); + int (*queue_info)(struct vb2_queue *q, unsigned int *num_planes, + unsigned int sizes[], struct device *alloc_devs[]); void (*wait_prepare)(struct vb2_queue *q); void (*wait_finish)(struct vb2_queue *q); @@ -682,6 +691,7 @@ struct vb2_queue { * called. Used to check for unbalanced ops. */ u32 cnt_queue_setup; + u32 cnt_queue_info; u32 cnt_wait_prepare; u32 cnt_wait_finish; u32 cnt_prepare_streaming;