All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/10]  Add DELETE_BUF ioctl
@ 2023-07-05 12:10 ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Unlike when resolution change on keyframes, dynamic resolution change
on inter frames doesn't allow to do a stream off/on sequence because
it is need to keep all previous references alive to decode inter frames.
This constraint have two main problems:
- more memory consumption.
- more buffers in use.
To solve these issue this series introduce DELETE_BUFS ioctl and remove
the 32 buffers limit per queue.

VP9 conformance tests using fluster give a score of 210/305.
The 24 resize inter tests (vp90-2-21-resize_inter_* files) are ok
but require to use postprocessor.

Kernel branch is available here:
https://gitlab.collabora.com/benjamin.gaignard/for-upstream/-/commits/remove_vb2_queue_limit_v4

GStreamer branch to use DELETE_BUF ioctl and testing dynamic resolution
change is here:
https://gitlab.freedesktop.org/benjamin.gaignard1/gstreamer/-/commits/VP9_drc

changes in version 4:
- Stop using Xarray, instead let queues decide about their own maximum
  number of buffer and allocate bufs array given that value.
- Rework offset cookie encoding pattern.
- Change DELETE_BUF to DELETE_BUFS because it now usable for
  range of buffer to be symetrical of CREATE_BUFS.
- Add fixes tags on couple of Verisilicon related patches.
- Be smarter in Verisilicon postprocessor buffers management.
- Rebase on top of v6.4

changes in version 3:
- Use Xarray API to store allocated video buffers.
- No module parameter to limit the number of buffer per queue.
- Use Xarray inside Verisilicon driver to store postprocessor buffers
  and remove VB2_MAX_FRAME limit.
- Allow Versilicon driver to change of resolution while streaming
- Various fixes the Verisilicon VP9 code to improve fluster score.
 
changes in version 2:
- Use a dynamic array and not a list to keep trace of allocated buffers.
  Not use IDR interface because it is marked as deprecated in kernel
  documentation.
- Add a module parameter to limit the number of buffer per queue.
- Add DELETE_BUF ioctl and m2m helpers.
 
Benjamin Gaignard (10):
  media: videobuf2: Access vb2_queue bufs array through helper functions
  media: videobuf2: Be more flexible on the number of queue stored
    buffers
  media: videobuf2: Rework offset 'cookie' encoding pattern
  media: verisilicon: Refactor postprocessor to store more buffers
  media: verisilicon: Store chroma and motion vectors offset
  media: verisilicon: vp9: Use destination buffer height to compute
    chroma offset
  media: verisilicon: postproc: Fix down scale test
  media: verisilicon: vp9: Allow to change resolution while streaming
  media: v4l2: Add DELETE_BUFS ioctl
  media: v4l2: Add mem2mem helpers for DELETE_BUFS ioctl

 .../userspace-api/media/v4l/user-func.rst     |   1 +
 .../media/v4l/vidioc-delete-bufs.rst          |  73 +++++
 .../media/common/videobuf2/videobuf2-core.c   | 304 +++++++++++++-----
 .../media/common/videobuf2/videobuf2-v4l2.c   |  44 ++-
 drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
 .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
 drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
 drivers/media/platform/verisilicon/hantro.h   |   9 +-
 .../media/platform/verisilicon/hantro_drv.c   |   4 +-
 .../platform/verisilicon/hantro_g2_vp9_dec.c  |  10 +-
 .../media/platform/verisilicon/hantro_hw.h    |   2 +-
 .../platform/verisilicon/hantro_postproc.c    | 105 ++++--
 .../media/platform/verisilicon/hantro_v4l2.c  |  27 +-
 drivers/media/test-drivers/vim2m.c            |   1 +
 drivers/media/test-drivers/visl/visl-dec.c    |  28 +-
 drivers/media/v4l2-core/v4l2-dev.c            |   1 +
 drivers/media/v4l2-core/v4l2-ioctl.c          |  17 +
 drivers/media/v4l2-core/v4l2-mem2mem.c        |  20 ++
 .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
 include/media/v4l2-ioctl.h                    |   4 +
 include/media/v4l2-mem2mem.h                  |  12 +
 include/media/videobuf2-core.h                |  13 +-
 include/media/videobuf2-v4l2.h                |  11 +
 include/uapi/linux/videodev2.h                |  17 +
 25 files changed, 592 insertions(+), 147 deletions(-)
 create mode 100644 Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst

-- 
2.39.2


^ permalink raw reply	[flat|nested] 51+ messages in thread

* [PATCH v4 00/10]  Add DELETE_BUF ioctl
@ 2023-07-05 12:10 ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Unlike when resolution change on keyframes, dynamic resolution change
on inter frames doesn't allow to do a stream off/on sequence because
it is need to keep all previous references alive to decode inter frames.
This constraint have two main problems:
- more memory consumption.
- more buffers in use.
To solve these issue this series introduce DELETE_BUFS ioctl and remove
the 32 buffers limit per queue.

VP9 conformance tests using fluster give a score of 210/305.
The 24 resize inter tests (vp90-2-21-resize_inter_* files) are ok
but require to use postprocessor.

Kernel branch is available here:
https://gitlab.collabora.com/benjamin.gaignard/for-upstream/-/commits/remove_vb2_queue_limit_v4

GStreamer branch to use DELETE_BUF ioctl and testing dynamic resolution
change is here:
https://gitlab.freedesktop.org/benjamin.gaignard1/gstreamer/-/commits/VP9_drc

changes in version 4:
- Stop using Xarray, instead let queues decide about their own maximum
  number of buffer and allocate bufs array given that value.
- Rework offset cookie encoding pattern.
- Change DELETE_BUF to DELETE_BUFS because it now usable for
  range of buffer to be symetrical of CREATE_BUFS.
- Add fixes tags on couple of Verisilicon related patches.
- Be smarter in Verisilicon postprocessor buffers management.
- Rebase on top of v6.4

changes in version 3:
- Use Xarray API to store allocated video buffers.
- No module parameter to limit the number of buffer per queue.
- Use Xarray inside Verisilicon driver to store postprocessor buffers
  and remove VB2_MAX_FRAME limit.
- Allow Versilicon driver to change of resolution while streaming
- Various fixes the Verisilicon VP9 code to improve fluster score.
 
changes in version 2:
- Use a dynamic array and not a list to keep trace of allocated buffers.
  Not use IDR interface because it is marked as deprecated in kernel
  documentation.
- Add a module parameter to limit the number of buffer per queue.
- Add DELETE_BUF ioctl and m2m helpers.
 
Benjamin Gaignard (10):
  media: videobuf2: Access vb2_queue bufs array through helper functions
  media: videobuf2: Be more flexible on the number of queue stored
    buffers
  media: videobuf2: Rework offset 'cookie' encoding pattern
  media: verisilicon: Refactor postprocessor to store more buffers
  media: verisilicon: Store chroma and motion vectors offset
  media: verisilicon: vp9: Use destination buffer height to compute
    chroma offset
  media: verisilicon: postproc: Fix down scale test
  media: verisilicon: vp9: Allow to change resolution while streaming
  media: v4l2: Add DELETE_BUFS ioctl
  media: v4l2: Add mem2mem helpers for DELETE_BUFS ioctl

 .../userspace-api/media/v4l/user-func.rst     |   1 +
 .../media/v4l/vidioc-delete-bufs.rst          |  73 +++++
 .../media/common/videobuf2/videobuf2-core.c   | 304 +++++++++++++-----
 .../media/common/videobuf2/videobuf2-v4l2.c   |  44 ++-
 drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
 .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
 drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
 drivers/media/platform/verisilicon/hantro.h   |   9 +-
 .../media/platform/verisilicon/hantro_drv.c   |   4 +-
 .../platform/verisilicon/hantro_g2_vp9_dec.c  |  10 +-
 .../media/platform/verisilicon/hantro_hw.h    |   2 +-
 .../platform/verisilicon/hantro_postproc.c    | 105 ++++--
 .../media/platform/verisilicon/hantro_v4l2.c  |  27 +-
 drivers/media/test-drivers/vim2m.c            |   1 +
 drivers/media/test-drivers/visl/visl-dec.c    |  28 +-
 drivers/media/v4l2-core/v4l2-dev.c            |   1 +
 drivers/media/v4l2-core/v4l2-ioctl.c          |  17 +
 drivers/media/v4l2-core/v4l2-mem2mem.c        |  20 ++
 .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
 include/media/v4l2-ioctl.h                    |   4 +
 include/media/v4l2-mem2mem.h                  |  12 +
 include/media/videobuf2-core.h                |  13 +-
 include/media/videobuf2-v4l2.h                |  11 +
 include/uapi/linux/videodev2.h                |  17 +
 25 files changed, 592 insertions(+), 147 deletions(-)
 create mode 100644 Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst

-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [PATCH v4 00/10]  Add DELETE_BUF ioctl
@ 2023-07-05 12:10 ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Unlike when resolution change on keyframes, dynamic resolution change
on inter frames doesn't allow to do a stream off/on sequence because
it is need to keep all previous references alive to decode inter frames.
This constraint have two main problems:
- more memory consumption.
- more buffers in use.
To solve these issue this series introduce DELETE_BUFS ioctl and remove
the 32 buffers limit per queue.

VP9 conformance tests using fluster give a score of 210/305.
The 24 resize inter tests (vp90-2-21-resize_inter_* files) are ok
but require to use postprocessor.

Kernel branch is available here:
https://gitlab.collabora.com/benjamin.gaignard/for-upstream/-/commits/remove_vb2_queue_limit_v4

GStreamer branch to use DELETE_BUF ioctl and testing dynamic resolution
change is here:
https://gitlab.freedesktop.org/benjamin.gaignard1/gstreamer/-/commits/VP9_drc

changes in version 4:
- Stop using Xarray, instead let queues decide about their own maximum
  number of buffer and allocate bufs array given that value.
- Rework offset cookie encoding pattern.
- Change DELETE_BUF to DELETE_BUFS because it now usable for
  range of buffer to be symetrical of CREATE_BUFS.
- Add fixes tags on couple of Verisilicon related patches.
- Be smarter in Verisilicon postprocessor buffers management.
- Rebase on top of v6.4

changes in version 3:
- Use Xarray API to store allocated video buffers.
- No module parameter to limit the number of buffer per queue.
- Use Xarray inside Verisilicon driver to store postprocessor buffers
  and remove VB2_MAX_FRAME limit.
- Allow Versilicon driver to change of resolution while streaming
- Various fixes the Verisilicon VP9 code to improve fluster score.
 
changes in version 2:
- Use a dynamic array and not a list to keep trace of allocated buffers.
  Not use IDR interface because it is marked as deprecated in kernel
  documentation.
- Add a module parameter to limit the number of buffer per queue.
- Add DELETE_BUF ioctl and m2m helpers.
 
Benjamin Gaignard (10):
  media: videobuf2: Access vb2_queue bufs array through helper functions
  media: videobuf2: Be more flexible on the number of queue stored
    buffers
  media: videobuf2: Rework offset 'cookie' encoding pattern
  media: verisilicon: Refactor postprocessor to store more buffers
  media: verisilicon: Store chroma and motion vectors offset
  media: verisilicon: vp9: Use destination buffer height to compute
    chroma offset
  media: verisilicon: postproc: Fix down scale test
  media: verisilicon: vp9: Allow to change resolution while streaming
  media: v4l2: Add DELETE_BUFS ioctl
  media: v4l2: Add mem2mem helpers for DELETE_BUFS ioctl

 .../userspace-api/media/v4l/user-func.rst     |   1 +
 .../media/v4l/vidioc-delete-bufs.rst          |  73 +++++
 .../media/common/videobuf2/videobuf2-core.c   | 304 +++++++++++++-----
 .../media/common/videobuf2/videobuf2-v4l2.c   |  44 ++-
 drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
 .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
 drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
 drivers/media/platform/verisilicon/hantro.h   |   9 +-
 .../media/platform/verisilicon/hantro_drv.c   |   4 +-
 .../platform/verisilicon/hantro_g2_vp9_dec.c  |  10 +-
 .../media/platform/verisilicon/hantro_hw.h    |   2 +-
 .../platform/verisilicon/hantro_postproc.c    | 105 ++++--
 .../media/platform/verisilicon/hantro_v4l2.c  |  27 +-
 drivers/media/test-drivers/vim2m.c            |   1 +
 drivers/media/test-drivers/visl/visl-dec.c    |  28 +-
 drivers/media/v4l2-core/v4l2-dev.c            |   1 +
 drivers/media/v4l2-core/v4l2-ioctl.c          |  17 +
 drivers/media/v4l2-core/v4l2-mem2mem.c        |  20 ++
 .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
 include/media/v4l2-ioctl.h                    |   4 +
 include/media/v4l2-mem2mem.h                  |  12 +
 include/media/videobuf2-core.h                |  13 +-
 include/media/videobuf2-v4l2.h                |  11 +
 include/uapi/linux/videodev2.h                |  17 +
 25 files changed, 592 insertions(+), 147 deletions(-)
 create mode 100644 Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst

-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

The first step before changing how vb2 buffers are stored into queue
is to avoid direct access to bufs arrays.

This patch adds 2 helpers functions to add and remove vb2 buffers
from a queue. With these 2 and vb2_get_buffer(), bufs field of
struct vb2_queue becomes like a private member of the structure.

After each call to vb2_get_buffer() we need to be sure that we get
a valid pointer so check the return value of all of them.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
 .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
 drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
 .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
 drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
 drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
 .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
 8 files changed, 240 insertions(+), 67 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index cf6727d9c81f..42fd3984c2bc 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
 	unsigned long off = 0;
 
 	if (vb->index) {
-		struct vb2_buffer *prev = q->bufs[vb->index - 1];
-		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
+		struct vb2_buffer *prev;
+		struct vb2_plane *p;
+
+		prev = vb2_get_buffer(q, vb->index - 1);
+		if (!prev) {
+			dprintk(q, 1, "can't find the requested buffer\n");
+			return;
+		}
+
+		p = &prev->planes[prev->num_planes - 1];
 
 		off = PAGE_ALIGN(p->m.offset + p->length);
 	}
@@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
 		vb->skip_cache_sync_on_finish = 1;
 }
 
+/**
+ * vb2_queue_add_buffer() - add a buffer to a queue
+ * @q:	pointer to &struct vb2_queue with videobuf2 queue.
+ * @vb:	pointer to &struct vb2_buffer to be added to the queue.
+ * @index: index where add vb2_buffer in the queue
+ */
+static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
+{
+	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
+		q->bufs[index] = vb;
+		vb->index = index;
+		vb->vb2_queue = q;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * vb2_queue_remove_buffer() - remove a buffer from a queue
+ * @q:	pointer to &struct vb2_queue with videobuf2 queue.
+ * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
+ */
+static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
+{
+	if (vb->index < VB2_MAX_FRAME) {
+		q->bufs[vb->index] = NULL;
+		vb->vb2_queue = NULL;
+	}
+}
+
 /*
  * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
  * video buffer memory for all buffers/planes on the queue and initializes the
@@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 		}
 
 		vb->state = VB2_BUF_STATE_DEQUEUED;
-		vb->vb2_queue = q;
 		vb->num_planes = num_planes;
-		vb->index = q->num_buffers + buffer;
 		vb->type = q->type;
 		vb->memory = memory;
 		init_buffer_cache_hints(q, vb);
@@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 		}
 		call_void_bufop(q, init_buffer, vb);
 
-		q->bufs[vb->index] = vb;
+		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
+			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
+			kfree(vb);
+			break;
+		}
 
 		/* Allocate video buffer memory for the MMAP type */
 		if (memory == VB2_MEMORY_MMAP) {
@@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 			if (ret) {
 				dprintk(q, 1, "failed allocating memory for buffer %d\n",
 					buffer);
-				q->bufs[vb->index] = NULL;
+				vb2_queue_remove_buffer(q, vb);
 				kfree(vb);
 				break;
 			}
@@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 				dprintk(q, 1, "buffer %d %p initialization failed\n",
 					buffer, vb);
 				__vb2_buf_mem_free(vb);
-				q->bufs[vb->index] = NULL;
+				vb2_queue_remove_buffer(q, vb);
 				kfree(vb);
 				break;
 			}
@@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		vb = q->bufs[buffer];
+		vb = vb2_get_buffer(q, buffer);
 		if (!vb)
 			continue;
 
@@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 	/* Call driver-provided cleanup function for each buffer, if provided */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		struct vb2_buffer *vb = q->bufs[buffer];
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
 
 		if (vb && vb->planes[0].mem_priv)
 			call_void_vb_qop(vb, buf_cleanup, vb);
@@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 		q->cnt_unprepare_streaming = 0;
 	}
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		struct vb2_buffer *vb = q->bufs[buffer];
-		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
-				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
-				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
-				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
-				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
-				  vb->cnt_buf_queue != vb->cnt_buf_done ||
-				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
-				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+		bool unbalanced;
+
+		if (!vb)
+			continue;
+
+		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
+			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
+			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
+			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
+			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
+			     vb->cnt_buf_queue != vb->cnt_buf_done ||
+			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
+			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
 
 		if (unbalanced || debug) {
 			pr_info("   counters for queue %p, buffer %d:%s\n",
@@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 	/* Free vb2 buffers */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		kfree(q->bufs[buffer]);
-		q->bufs[buffer] = NULL;
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
+
+		vb2_queue_remove_buffer(q, vb);
+		kfree(vb);
 	}
 
 	q->num_buffers -= buffers;
@@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
 {
 	unsigned int buffer;
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		if (vb2_buffer_in_use(q, q->bufs[buffer]))
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
+
+		if (vb2_buffer_in_use(q, vb))
 			return true;
 	}
 	return false;
@@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
 
 void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
 {
-	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
+	struct vb2_buffer *vb = vb2_get_buffer(q, index);
+
+	if (vb)
+		call_void_bufop(q, fill_user_buffer, vb, pb);
 }
 EXPORT_SYMBOL_GPL(vb2_core_querybuf);
 
@@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 	struct vb2_buffer *vb;
 	int ret;
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
+
 	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
 		dprintk(q, 1, "invalid buffer state %s\n",
 			vb2_state_name(vb->state));
@@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
 		 * correctly return them to vb2.
 		 */
 		for (i = 0; i < q->num_buffers; ++i) {
-			vb = q->bufs[i];
+			vb = vb2_get_buffer(q, i);
+
+			if (!vb)
+				continue;
+
 			if (vb->state == VB2_BUF_STATE_ACTIVE)
 				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
 		}
@@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 		return -EIO;
 	}
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
 
 	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
 	    q->requires_requests) {
@@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * to vb2 in stop_streaming().
 	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
-		for (i = 0; i < q->num_buffers; ++i)
-			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
+		for (i = 0; i < q->num_buffers; ++i) {
+			struct vb2_buffer *vb = vb2_get_buffer(q, i);
+
+			if (!vb)
+				continue;
+
+			if (vb->state == VB2_BUF_STATE_ACTIVE) {
 				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
-					q->bufs[i]);
-				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
+					vb);
+				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 			}
+		}
 		/* Must be zero now */
 		WARN_ON(atomic_read(&q->owned_by_drv_count));
 	}
@@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
 	 */
 	for (i = 0; i < q->num_buffers; ++i) {
-		struct vb2_buffer *vb = q->bufs[i];
-		struct media_request *req = vb->req_obj.req;
+		struct vb2_buffer *vb;
+		struct media_request *req;
 
+		vb = vb2_get_buffer(q, i);
+		if (!vb)
+			continue;
+
+		req = vb->req_obj.req;
 		/*
 		 * If a request is associated with this buffer, then
 		 * call buf_request_cancel() to give the driver to complete()
@@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 	 * return its buffer and plane numbers.
 	 */
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		vb = q->bufs[buffer];
+		vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
 
 		for (plane = 0; plane < vb->num_planes; ++plane) {
 			if (vb->planes[plane].m.offset == off) {
@@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
 		return -EINVAL;
 	}
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
 
 	if (plane >= vb->num_planes) {
 		dprintk(q, 1, "buffer plane out of range\n");
@@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 	if (ret)
 		goto unlock;
 
-	vb = q->bufs[buffer];
+	vb = vb2_get_buffer(q, buffer);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		ret = -EINVAL;
+		goto unlock;
+	}
 
 	/*
 	 * MMAP requires page_aligned buffers.
@@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 	if (ret)
 		goto unlock;
 
-	vb = q->bufs[buffer];
+	vb = vb2_get_buffer(q, buffer);
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		ret = -EINVAL;
+		goto unlock;
+	}
 
 	vaddr = vb2_plane_vaddr(vb, plane);
 	mutex_unlock(&q->mmap_lock);
@@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
 static int __vb2_init_fileio(struct vb2_queue *q, int read)
 {
 	struct vb2_fileio_data *fileio;
+	struct vb2_buffer *vb;
 	int i, ret;
 	unsigned int count = 0;
 
@@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	 * Check if plane_count is correct
 	 * (multiplane buffers are not supported).
 	 */
-	if (q->bufs[0]->num_planes != 1) {
+	vb = vb2_get_buffer(q, 0);
+	if (!vb) {
+		ret = -EBUSY;
+		goto err_reqbufs;
+	}
+
+	if (vb->num_planes != 1) {
 		ret = -EBUSY;
 		goto err_reqbufs;
 	}
@@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	 * Get kernel address of each buffer.
 	 */
 	for (i = 0; i < q->num_buffers; i++) {
-		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+		vb = vb2_get_buffer(q, i);
+
+		if (!vb)
+			continue;
+
+		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
 		if (fileio->bufs[i].vaddr == NULL) {
 			ret = -EINVAL;
 			goto err_reqbufs;
 		}
-		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
+		fileio->bufs[i].size = vb2_plane_size(vb, 0);
 	}
 
 	/*
@@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 
 		fileio->cur_index = index;
 		buf = &fileio->bufs[index];
-		b = q->bufs[index];
+		b = vb2_get_buffer(q, index);
+
+		if (!b)
+			return -EINVAL;
 
 		/*
 		 * Get number of bytes filled by the driver
 		 */
 		buf->pos = 0;
 		buf->queued = 0;
-		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
-				 : vb2_plane_size(q->bufs[index], 0);
+		buf->size = read ? vb2_get_plane_payload(b, 0)
+				 : vb2_plane_size(b, 0);
 		/* Compensate for data_offset on read in the multiplanar case. */
 		if (is_multiplanar && read &&
 				b->planes[0].data_offset < buf->size) {
@@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 	 * Queue next buffer if required.
 	 */
 	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
-		struct vb2_buffer *b = q->bufs[index];
+		struct vb2_buffer *b = vb2_get_buffer(q, index);
 
+		if (!b) {
+			dprintk(q, 1, "can't find the requested buffer\n");
+			return -EINVAL;
+		}
 		/*
 		 * Check if this is the last buffer to read.
 		 */
@@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 		 */
 		buf->pos = 0;
 		buf->queued = 1;
-		buf->size = vb2_plane_size(q->bufs[index], 0);
+		buf->size = vb2_plane_size(b, 0);
 		fileio->q_count += 1;
 		/*
 		 * If we are queuing up buffers for the first time, then
@@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
 		 * Call vb2_dqbuf to get buffer back.
 		 */
 		if (prequeue) {
-			vb = q->bufs[index++];
+			vb = vb2_get_buffer(q, index++);
+			if (!vb)
+				continue;
 			prequeue--;
 		} else {
 			call_void_qop(q, wait_finish, q);
@@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
 			call_void_qop(q, wait_prepare, q);
 			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
 			if (!ret)
-				vb = q->bufs[index];
+				vb = vb2_get_buffer(q, index);
 		}
 		if (ret || threadio->stop)
 			break;
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index c7a54d82a55e..724135d41f7f 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 		return -EINVAL;
 	}
 
-	if (q->bufs[b->index] == NULL) {
-		/* Should never happen */
+	if (!vb2_get_buffer(q, b->index)) {
 		dprintk(q, 1, "%s: buffer is NULL\n", opname);
 		return -EINVAL;
 	}
@@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 		return -EINVAL;
 	}
 
-	vb = q->bufs[b->index];
+	vb = vb2_get_buffer(q, b->index);
 	vbuf = to_vb2_v4l2_buffer(vb);
 	ret = __verify_planes_array(vb, b);
 	if (ret)
@@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
 struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
 {
 	unsigned int i;
+	struct vb2_buffer *vb2;
 
-	for (i = 0; i < q->num_buffers; i++)
-		if (q->bufs[i]->copied_timestamp &&
-		    q->bufs[i]->timestamp == timestamp)
-			return vb2_get_buffer(q, i);
+	for (i = 0; i < q->num_buffers; i++) {
+		vb2 = vb2_get_buffer(q, i);
+
+		if (!vb2)
+			continue;
+
+		if (vb2->copied_timestamp &&
+		    vb2->timestamp == timestamp)
+			return vb2;
+	}
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(vb2_find_buffer);
@@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
 		dprintk(q, 1, "buffer index out of range\n");
 		return -EINVAL;
 	}
-	vb = q->bufs[b->index];
+	vb = vb2_get_buffer(q, b->index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
+
 	ret = __verify_planes_array(vb, b);
 	if (!ret)
 		vb2_core_querybuf(q, b->index, b);
diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
index 44b830ae01d8..e2c371c2fde5 100644
--- a/drivers/media/platform/amphion/vpu_dbg.c
+++ b/drivers/media/platform/amphion/vpu_dbg.c
@@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
 
 	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
 	for (i = 0; i < vq->num_buffers; i++) {
-		struct vb2_buffer *vb = vq->bufs[i];
-		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+		struct vb2_buffer *vb;
+		struct vb2_v4l2_buffer *vbuf;
+
+		vb = vb2_get_buffer(vq, i);
+		if (!vb)
+			continue;
 
 		if (vb->state == VB2_BUF_STATE_DEQUEUED)
 			continue;
+
+		vbuf = to_vb2_v4l2_buffer(vb);
+
 		num = scnprintf(str, sizeof(str),
 				"output [%2d] state = %10s, %8s\n",
 				i, vb2_stat_name[vb->state],
@@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
 
 	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
 	for (i = 0; i < vq->num_buffers; i++) {
-		struct vb2_buffer *vb = vq->bufs[i];
-		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+		struct vb2_buffer *vb;
+		struct vb2_v4l2_buffer *vbuf;
+
+		vb = vb2_get_buffer(vq, i);
+		if (!vb)
+			continue;
 
 		if (vb->state == VB2_BUF_STATE_DEQUEUED)
 			continue;
+
+		vbuf = to_vb2_v4l2_buffer(vb);
+
 		num = scnprintf(str, sizeof(str),
 				"capture[%2d] state = %10s, %8s\n",
 				i, vb2_stat_name[vb->state],
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index 0051f372a66c..ea37069ba355 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 		return -EINVAL;
 	}
 
-	vb = vq->bufs[buf->index];
+	vb = vb2_get_buffer(vq, buf->index);
+	if (!vb) {
+		dev_err(ctx->jpeg->dev, "buffer not found\n");
+		return -EINVAL;
+	}
 	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
 	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
 
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
index cf16cf2807f0..6532a69f1fa8 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
@@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
 
 	/* update internal buffer's width/height */
 	for (i = 0; i < vq->num_buffers; i++) {
-		if (vb == vq->bufs[i]) {
+		if (vb == vb2_get_buffer(vq, i)) {
 			instance->dpb[i].width = w;
 			instance->dpb[i].height = h;
 			break;
diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
index 3a848ca32a0e..326be09bdb55 100644
--- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
+++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
@@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 		}
 
 		vb2_buf = vb2_get_buffer(vq, buf->index);
+		if (!vb2_buf) {
+			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
+			return -EINVAL;
+		}
 		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
 		stream->bytesused = buf->bytesused;
 	}
diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
index 318d675e5668..ba20ea998d19 100644
--- a/drivers/media/test-drivers/visl/visl-dec.c
+++ b/drivers/media/test-drivers/visl/visl-dec.c
@@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
 	for (i = 0; i < out_q->num_buffers; i++) {
 		char entry[] = "index: %u, state: %s, request_fd: %d, ";
 		u32 old_len = len;
-		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
+		struct vb2_buffer *vb2;
+		char *q_status;
+
+		vb2 = vb2_get_buffer(out_q, i);
+		if (!vb2)
+			continue;
+
+		q_status = visl_get_vb2_state(vb2->state);
 
 		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
 				 entry, i, q_status,
-				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
+				 to_vb2_v4l2_buffer(vb2)->request_fd);
 
-		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
+		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
 					   &buf[len],
 					   TPG_STR_BUF_SZ - len);
 
@@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
 	len = 0;
 	for (i = 0; i < cap_q->num_buffers; i++) {
 		u32 old_len = len;
-		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
+		struct vb2_buffer *vb2;
+		char *q_status;
+
+		vb2 = vb2_get_buffer(cap_q, i);
+		if (!vb2)
+			continue;
+
+		q_status = visl_get_vb2_state(vb2->state);
 
 		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
 				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
-				 cap_q->bufs[i]->index, q_status,
-				 cap_q->bufs[i]->timestamp,
-				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
+				 vb2->index, q_status,
+				 vb2->timestamp,
+				 to_vb2_v4l2_buffer(vb2)->is_held);
 
 		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
 		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 384f31fc66c5..8df301ab41ad 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
 	if (ret)
 		return ret;
 
-	vb = pipe->vb_queue.bufs[buf->index];
+	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
 	frame = vb_to_frame(vb);
 
 	buf->reserved = asd->frame_status[buf->index];
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

The first step before changing how vb2 buffers are stored into queue
is to avoid direct access to bufs arrays.

This patch adds 2 helpers functions to add and remove vb2 buffers
from a queue. With these 2 and vb2_get_buffer(), bufs field of
struct vb2_queue becomes like a private member of the structure.

After each call to vb2_get_buffer() we need to be sure that we get
a valid pointer so check the return value of all of them.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
 .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
 drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
 .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
 drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
 drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
 .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
 8 files changed, 240 insertions(+), 67 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index cf6727d9c81f..42fd3984c2bc 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
 	unsigned long off = 0;
 
 	if (vb->index) {
-		struct vb2_buffer *prev = q->bufs[vb->index - 1];
-		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
+		struct vb2_buffer *prev;
+		struct vb2_plane *p;
+
+		prev = vb2_get_buffer(q, vb->index - 1);
+		if (!prev) {
+			dprintk(q, 1, "can't find the requested buffer\n");
+			return;
+		}
+
+		p = &prev->planes[prev->num_planes - 1];
 
 		off = PAGE_ALIGN(p->m.offset + p->length);
 	}
@@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
 		vb->skip_cache_sync_on_finish = 1;
 }
 
+/**
+ * vb2_queue_add_buffer() - add a buffer to a queue
+ * @q:	pointer to &struct vb2_queue with videobuf2 queue.
+ * @vb:	pointer to &struct vb2_buffer to be added to the queue.
+ * @index: index where add vb2_buffer in the queue
+ */
+static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
+{
+	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
+		q->bufs[index] = vb;
+		vb->index = index;
+		vb->vb2_queue = q;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * vb2_queue_remove_buffer() - remove a buffer from a queue
+ * @q:	pointer to &struct vb2_queue with videobuf2 queue.
+ * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
+ */
+static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
+{
+	if (vb->index < VB2_MAX_FRAME) {
+		q->bufs[vb->index] = NULL;
+		vb->vb2_queue = NULL;
+	}
+}
+
 /*
  * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
  * video buffer memory for all buffers/planes on the queue and initializes the
@@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 		}
 
 		vb->state = VB2_BUF_STATE_DEQUEUED;
-		vb->vb2_queue = q;
 		vb->num_planes = num_planes;
-		vb->index = q->num_buffers + buffer;
 		vb->type = q->type;
 		vb->memory = memory;
 		init_buffer_cache_hints(q, vb);
@@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 		}
 		call_void_bufop(q, init_buffer, vb);
 
-		q->bufs[vb->index] = vb;
+		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
+			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
+			kfree(vb);
+			break;
+		}
 
 		/* Allocate video buffer memory for the MMAP type */
 		if (memory == VB2_MEMORY_MMAP) {
@@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 			if (ret) {
 				dprintk(q, 1, "failed allocating memory for buffer %d\n",
 					buffer);
-				q->bufs[vb->index] = NULL;
+				vb2_queue_remove_buffer(q, vb);
 				kfree(vb);
 				break;
 			}
@@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 				dprintk(q, 1, "buffer %d %p initialization failed\n",
 					buffer, vb);
 				__vb2_buf_mem_free(vb);
-				q->bufs[vb->index] = NULL;
+				vb2_queue_remove_buffer(q, vb);
 				kfree(vb);
 				break;
 			}
@@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		vb = q->bufs[buffer];
+		vb = vb2_get_buffer(q, buffer);
 		if (!vb)
 			continue;
 
@@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 	/* Call driver-provided cleanup function for each buffer, if provided */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		struct vb2_buffer *vb = q->bufs[buffer];
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
 
 		if (vb && vb->planes[0].mem_priv)
 			call_void_vb_qop(vb, buf_cleanup, vb);
@@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 		q->cnt_unprepare_streaming = 0;
 	}
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		struct vb2_buffer *vb = q->bufs[buffer];
-		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
-				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
-				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
-				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
-				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
-				  vb->cnt_buf_queue != vb->cnt_buf_done ||
-				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
-				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+		bool unbalanced;
+
+		if (!vb)
+			continue;
+
+		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
+			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
+			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
+			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
+			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
+			     vb->cnt_buf_queue != vb->cnt_buf_done ||
+			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
+			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
 
 		if (unbalanced || debug) {
 			pr_info("   counters for queue %p, buffer %d:%s\n",
@@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 	/* Free vb2 buffers */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		kfree(q->bufs[buffer]);
-		q->bufs[buffer] = NULL;
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
+
+		vb2_queue_remove_buffer(q, vb);
+		kfree(vb);
 	}
 
 	q->num_buffers -= buffers;
@@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
 {
 	unsigned int buffer;
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		if (vb2_buffer_in_use(q, q->bufs[buffer]))
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
+
+		if (vb2_buffer_in_use(q, vb))
 			return true;
 	}
 	return false;
@@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
 
 void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
 {
-	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
+	struct vb2_buffer *vb = vb2_get_buffer(q, index);
+
+	if (vb)
+		call_void_bufop(q, fill_user_buffer, vb, pb);
 }
 EXPORT_SYMBOL_GPL(vb2_core_querybuf);
 
@@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 	struct vb2_buffer *vb;
 	int ret;
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
+
 	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
 		dprintk(q, 1, "invalid buffer state %s\n",
 			vb2_state_name(vb->state));
@@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
 		 * correctly return them to vb2.
 		 */
 		for (i = 0; i < q->num_buffers; ++i) {
-			vb = q->bufs[i];
+			vb = vb2_get_buffer(q, i);
+
+			if (!vb)
+				continue;
+
 			if (vb->state == VB2_BUF_STATE_ACTIVE)
 				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
 		}
@@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 		return -EIO;
 	}
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
 
 	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
 	    q->requires_requests) {
@@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * to vb2 in stop_streaming().
 	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
-		for (i = 0; i < q->num_buffers; ++i)
-			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
+		for (i = 0; i < q->num_buffers; ++i) {
+			struct vb2_buffer *vb = vb2_get_buffer(q, i);
+
+			if (!vb)
+				continue;
+
+			if (vb->state == VB2_BUF_STATE_ACTIVE) {
 				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
-					q->bufs[i]);
-				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
+					vb);
+				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 			}
+		}
 		/* Must be zero now */
 		WARN_ON(atomic_read(&q->owned_by_drv_count));
 	}
@@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
 	 */
 	for (i = 0; i < q->num_buffers; ++i) {
-		struct vb2_buffer *vb = q->bufs[i];
-		struct media_request *req = vb->req_obj.req;
+		struct vb2_buffer *vb;
+		struct media_request *req;
 
+		vb = vb2_get_buffer(q, i);
+		if (!vb)
+			continue;
+
+		req = vb->req_obj.req;
 		/*
 		 * If a request is associated with this buffer, then
 		 * call buf_request_cancel() to give the driver to complete()
@@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 	 * return its buffer and plane numbers.
 	 */
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		vb = q->bufs[buffer];
+		vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
 
 		for (plane = 0; plane < vb->num_planes; ++plane) {
 			if (vb->planes[plane].m.offset == off) {
@@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
 		return -EINVAL;
 	}
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
 
 	if (plane >= vb->num_planes) {
 		dprintk(q, 1, "buffer plane out of range\n");
@@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 	if (ret)
 		goto unlock;
 
-	vb = q->bufs[buffer];
+	vb = vb2_get_buffer(q, buffer);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		ret = -EINVAL;
+		goto unlock;
+	}
 
 	/*
 	 * MMAP requires page_aligned buffers.
@@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 	if (ret)
 		goto unlock;
 
-	vb = q->bufs[buffer];
+	vb = vb2_get_buffer(q, buffer);
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		ret = -EINVAL;
+		goto unlock;
+	}
 
 	vaddr = vb2_plane_vaddr(vb, plane);
 	mutex_unlock(&q->mmap_lock);
@@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
 static int __vb2_init_fileio(struct vb2_queue *q, int read)
 {
 	struct vb2_fileio_data *fileio;
+	struct vb2_buffer *vb;
 	int i, ret;
 	unsigned int count = 0;
 
@@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	 * Check if plane_count is correct
 	 * (multiplane buffers are not supported).
 	 */
-	if (q->bufs[0]->num_planes != 1) {
+	vb = vb2_get_buffer(q, 0);
+	if (!vb) {
+		ret = -EBUSY;
+		goto err_reqbufs;
+	}
+
+	if (vb->num_planes != 1) {
 		ret = -EBUSY;
 		goto err_reqbufs;
 	}
@@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	 * Get kernel address of each buffer.
 	 */
 	for (i = 0; i < q->num_buffers; i++) {
-		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+		vb = vb2_get_buffer(q, i);
+
+		if (!vb)
+			continue;
+
+		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
 		if (fileio->bufs[i].vaddr == NULL) {
 			ret = -EINVAL;
 			goto err_reqbufs;
 		}
-		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
+		fileio->bufs[i].size = vb2_plane_size(vb, 0);
 	}
 
 	/*
@@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 
 		fileio->cur_index = index;
 		buf = &fileio->bufs[index];
-		b = q->bufs[index];
+		b = vb2_get_buffer(q, index);
+
+		if (!b)
+			return -EINVAL;
 
 		/*
 		 * Get number of bytes filled by the driver
 		 */
 		buf->pos = 0;
 		buf->queued = 0;
-		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
-				 : vb2_plane_size(q->bufs[index], 0);
+		buf->size = read ? vb2_get_plane_payload(b, 0)
+				 : vb2_plane_size(b, 0);
 		/* Compensate for data_offset on read in the multiplanar case. */
 		if (is_multiplanar && read &&
 				b->planes[0].data_offset < buf->size) {
@@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 	 * Queue next buffer if required.
 	 */
 	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
-		struct vb2_buffer *b = q->bufs[index];
+		struct vb2_buffer *b = vb2_get_buffer(q, index);
 
+		if (!b) {
+			dprintk(q, 1, "can't find the requested buffer\n");
+			return -EINVAL;
+		}
 		/*
 		 * Check if this is the last buffer to read.
 		 */
@@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 		 */
 		buf->pos = 0;
 		buf->queued = 1;
-		buf->size = vb2_plane_size(q->bufs[index], 0);
+		buf->size = vb2_plane_size(b, 0);
 		fileio->q_count += 1;
 		/*
 		 * If we are queuing up buffers for the first time, then
@@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
 		 * Call vb2_dqbuf to get buffer back.
 		 */
 		if (prequeue) {
-			vb = q->bufs[index++];
+			vb = vb2_get_buffer(q, index++);
+			if (!vb)
+				continue;
 			prequeue--;
 		} else {
 			call_void_qop(q, wait_finish, q);
@@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
 			call_void_qop(q, wait_prepare, q);
 			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
 			if (!ret)
-				vb = q->bufs[index];
+				vb = vb2_get_buffer(q, index);
 		}
 		if (ret || threadio->stop)
 			break;
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index c7a54d82a55e..724135d41f7f 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 		return -EINVAL;
 	}
 
-	if (q->bufs[b->index] == NULL) {
-		/* Should never happen */
+	if (!vb2_get_buffer(q, b->index)) {
 		dprintk(q, 1, "%s: buffer is NULL\n", opname);
 		return -EINVAL;
 	}
@@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 		return -EINVAL;
 	}
 
-	vb = q->bufs[b->index];
+	vb = vb2_get_buffer(q, b->index);
 	vbuf = to_vb2_v4l2_buffer(vb);
 	ret = __verify_planes_array(vb, b);
 	if (ret)
@@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
 struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
 {
 	unsigned int i;
+	struct vb2_buffer *vb2;
 
-	for (i = 0; i < q->num_buffers; i++)
-		if (q->bufs[i]->copied_timestamp &&
-		    q->bufs[i]->timestamp == timestamp)
-			return vb2_get_buffer(q, i);
+	for (i = 0; i < q->num_buffers; i++) {
+		vb2 = vb2_get_buffer(q, i);
+
+		if (!vb2)
+			continue;
+
+		if (vb2->copied_timestamp &&
+		    vb2->timestamp == timestamp)
+			return vb2;
+	}
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(vb2_find_buffer);
@@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
 		dprintk(q, 1, "buffer index out of range\n");
 		return -EINVAL;
 	}
-	vb = q->bufs[b->index];
+	vb = vb2_get_buffer(q, b->index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
+
 	ret = __verify_planes_array(vb, b);
 	if (!ret)
 		vb2_core_querybuf(q, b->index, b);
diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
index 44b830ae01d8..e2c371c2fde5 100644
--- a/drivers/media/platform/amphion/vpu_dbg.c
+++ b/drivers/media/platform/amphion/vpu_dbg.c
@@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
 
 	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
 	for (i = 0; i < vq->num_buffers; i++) {
-		struct vb2_buffer *vb = vq->bufs[i];
-		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+		struct vb2_buffer *vb;
+		struct vb2_v4l2_buffer *vbuf;
+
+		vb = vb2_get_buffer(vq, i);
+		if (!vb)
+			continue;
 
 		if (vb->state == VB2_BUF_STATE_DEQUEUED)
 			continue;
+
+		vbuf = to_vb2_v4l2_buffer(vb);
+
 		num = scnprintf(str, sizeof(str),
 				"output [%2d] state = %10s, %8s\n",
 				i, vb2_stat_name[vb->state],
@@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
 
 	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
 	for (i = 0; i < vq->num_buffers; i++) {
-		struct vb2_buffer *vb = vq->bufs[i];
-		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+		struct vb2_buffer *vb;
+		struct vb2_v4l2_buffer *vbuf;
+
+		vb = vb2_get_buffer(vq, i);
+		if (!vb)
+			continue;
 
 		if (vb->state == VB2_BUF_STATE_DEQUEUED)
 			continue;
+
+		vbuf = to_vb2_v4l2_buffer(vb);
+
 		num = scnprintf(str, sizeof(str),
 				"capture[%2d] state = %10s, %8s\n",
 				i, vb2_stat_name[vb->state],
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index 0051f372a66c..ea37069ba355 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 		return -EINVAL;
 	}
 
-	vb = vq->bufs[buf->index];
+	vb = vb2_get_buffer(vq, buf->index);
+	if (!vb) {
+		dev_err(ctx->jpeg->dev, "buffer not found\n");
+		return -EINVAL;
+	}
 	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
 	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
 
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
index cf16cf2807f0..6532a69f1fa8 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
@@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
 
 	/* update internal buffer's width/height */
 	for (i = 0; i < vq->num_buffers; i++) {
-		if (vb == vq->bufs[i]) {
+		if (vb == vb2_get_buffer(vq, i)) {
 			instance->dpb[i].width = w;
 			instance->dpb[i].height = h;
 			break;
diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
index 3a848ca32a0e..326be09bdb55 100644
--- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
+++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
@@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 		}
 
 		vb2_buf = vb2_get_buffer(vq, buf->index);
+		if (!vb2_buf) {
+			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
+			return -EINVAL;
+		}
 		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
 		stream->bytesused = buf->bytesused;
 	}
diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
index 318d675e5668..ba20ea998d19 100644
--- a/drivers/media/test-drivers/visl/visl-dec.c
+++ b/drivers/media/test-drivers/visl/visl-dec.c
@@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
 	for (i = 0; i < out_q->num_buffers; i++) {
 		char entry[] = "index: %u, state: %s, request_fd: %d, ";
 		u32 old_len = len;
-		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
+		struct vb2_buffer *vb2;
+		char *q_status;
+
+		vb2 = vb2_get_buffer(out_q, i);
+		if (!vb2)
+			continue;
+
+		q_status = visl_get_vb2_state(vb2->state);
 
 		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
 				 entry, i, q_status,
-				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
+				 to_vb2_v4l2_buffer(vb2)->request_fd);
 
-		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
+		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
 					   &buf[len],
 					   TPG_STR_BUF_SZ - len);
 
@@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
 	len = 0;
 	for (i = 0; i < cap_q->num_buffers; i++) {
 		u32 old_len = len;
-		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
+		struct vb2_buffer *vb2;
+		char *q_status;
+
+		vb2 = vb2_get_buffer(cap_q, i);
+		if (!vb2)
+			continue;
+
+		q_status = visl_get_vb2_state(vb2->state);
 
 		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
 				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
-				 cap_q->bufs[i]->index, q_status,
-				 cap_q->bufs[i]->timestamp,
-				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
+				 vb2->index, q_status,
+				 vb2->timestamp,
+				 to_vb2_v4l2_buffer(vb2)->is_held);
 
 		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
 		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 384f31fc66c5..8df301ab41ad 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
 	if (ret)
 		return ret;
 
-	vb = pipe->vb_queue.bufs[buf->index];
+	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
 	frame = vb_to_frame(vb);
 
 	buf->reserved = asd->frame_status[buf->index];
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

The first step before changing how vb2 buffers are stored into queue
is to avoid direct access to bufs arrays.

This patch adds 2 helpers functions to add and remove vb2 buffers
from a queue. With these 2 and vb2_get_buffer(), bufs field of
struct vb2_queue becomes like a private member of the structure.

After each call to vb2_get_buffer() we need to be sure that we get
a valid pointer so check the return value of all of them.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
 .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
 drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
 .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
 drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
 drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
 .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
 8 files changed, 240 insertions(+), 67 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index cf6727d9c81f..42fd3984c2bc 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
 	unsigned long off = 0;
 
 	if (vb->index) {
-		struct vb2_buffer *prev = q->bufs[vb->index - 1];
-		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
+		struct vb2_buffer *prev;
+		struct vb2_plane *p;
+
+		prev = vb2_get_buffer(q, vb->index - 1);
+		if (!prev) {
+			dprintk(q, 1, "can't find the requested buffer\n");
+			return;
+		}
+
+		p = &prev->planes[prev->num_planes - 1];
 
 		off = PAGE_ALIGN(p->m.offset + p->length);
 	}
@@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
 		vb->skip_cache_sync_on_finish = 1;
 }
 
+/**
+ * vb2_queue_add_buffer() - add a buffer to a queue
+ * @q:	pointer to &struct vb2_queue with videobuf2 queue.
+ * @vb:	pointer to &struct vb2_buffer to be added to the queue.
+ * @index: index where add vb2_buffer in the queue
+ */
+static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
+{
+	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
+		q->bufs[index] = vb;
+		vb->index = index;
+		vb->vb2_queue = q;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * vb2_queue_remove_buffer() - remove a buffer from a queue
+ * @q:	pointer to &struct vb2_queue with videobuf2 queue.
+ * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
+ */
+static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
+{
+	if (vb->index < VB2_MAX_FRAME) {
+		q->bufs[vb->index] = NULL;
+		vb->vb2_queue = NULL;
+	}
+}
+
 /*
  * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
  * video buffer memory for all buffers/planes on the queue and initializes the
@@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 		}
 
 		vb->state = VB2_BUF_STATE_DEQUEUED;
-		vb->vb2_queue = q;
 		vb->num_planes = num_planes;
-		vb->index = q->num_buffers + buffer;
 		vb->type = q->type;
 		vb->memory = memory;
 		init_buffer_cache_hints(q, vb);
@@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 		}
 		call_void_bufop(q, init_buffer, vb);
 
-		q->bufs[vb->index] = vb;
+		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
+			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
+			kfree(vb);
+			break;
+		}
 
 		/* Allocate video buffer memory for the MMAP type */
 		if (memory == VB2_MEMORY_MMAP) {
@@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 			if (ret) {
 				dprintk(q, 1, "failed allocating memory for buffer %d\n",
 					buffer);
-				q->bufs[vb->index] = NULL;
+				vb2_queue_remove_buffer(q, vb);
 				kfree(vb);
 				break;
 			}
@@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 				dprintk(q, 1, "buffer %d %p initialization failed\n",
 					buffer, vb);
 				__vb2_buf_mem_free(vb);
-				q->bufs[vb->index] = NULL;
+				vb2_queue_remove_buffer(q, vb);
 				kfree(vb);
 				break;
 			}
@@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		vb = q->bufs[buffer];
+		vb = vb2_get_buffer(q, buffer);
 		if (!vb)
 			continue;
 
@@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 	/* Call driver-provided cleanup function for each buffer, if provided */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		struct vb2_buffer *vb = q->bufs[buffer];
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
 
 		if (vb && vb->planes[0].mem_priv)
 			call_void_vb_qop(vb, buf_cleanup, vb);
@@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 		q->cnt_unprepare_streaming = 0;
 	}
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		struct vb2_buffer *vb = q->bufs[buffer];
-		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
-				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
-				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
-				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
-				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
-				  vb->cnt_buf_queue != vb->cnt_buf_done ||
-				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
-				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+		bool unbalanced;
+
+		if (!vb)
+			continue;
+
+		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
+			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
+			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
+			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
+			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
+			     vb->cnt_buf_queue != vb->cnt_buf_done ||
+			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
+			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
 
 		if (unbalanced || debug) {
 			pr_info("   counters for queue %p, buffer %d:%s\n",
@@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 	/* Free vb2 buffers */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 	     ++buffer) {
-		kfree(q->bufs[buffer]);
-		q->bufs[buffer] = NULL;
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
+
+		vb2_queue_remove_buffer(q, vb);
+		kfree(vb);
 	}
 
 	q->num_buffers -= buffers;
@@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
 {
 	unsigned int buffer;
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		if (vb2_buffer_in_use(q, q->bufs[buffer]))
+		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
+
+		if (vb2_buffer_in_use(q, vb))
 			return true;
 	}
 	return false;
@@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
 
 void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
 {
-	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
+	struct vb2_buffer *vb = vb2_get_buffer(q, index);
+
+	if (vb)
+		call_void_bufop(q, fill_user_buffer, vb, pb);
 }
 EXPORT_SYMBOL_GPL(vb2_core_querybuf);
 
@@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 	struct vb2_buffer *vb;
 	int ret;
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
+
 	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
 		dprintk(q, 1, "invalid buffer state %s\n",
 			vb2_state_name(vb->state));
@@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
 		 * correctly return them to vb2.
 		 */
 		for (i = 0; i < q->num_buffers; ++i) {
-			vb = q->bufs[i];
+			vb = vb2_get_buffer(q, i);
+
+			if (!vb)
+				continue;
+
 			if (vb->state == VB2_BUF_STATE_ACTIVE)
 				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
 		}
@@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 		return -EIO;
 	}
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
 
 	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
 	    q->requires_requests) {
@@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * to vb2 in stop_streaming().
 	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
-		for (i = 0; i < q->num_buffers; ++i)
-			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
+		for (i = 0; i < q->num_buffers; ++i) {
+			struct vb2_buffer *vb = vb2_get_buffer(q, i);
+
+			if (!vb)
+				continue;
+
+			if (vb->state == VB2_BUF_STATE_ACTIVE) {
 				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
-					q->bufs[i]);
-				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
+					vb);
+				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 			}
+		}
 		/* Must be zero now */
 		WARN_ON(atomic_read(&q->owned_by_drv_count));
 	}
@@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
 	 */
 	for (i = 0; i < q->num_buffers; ++i) {
-		struct vb2_buffer *vb = q->bufs[i];
-		struct media_request *req = vb->req_obj.req;
+		struct vb2_buffer *vb;
+		struct media_request *req;
 
+		vb = vb2_get_buffer(q, i);
+		if (!vb)
+			continue;
+
+		req = vb->req_obj.req;
 		/*
 		 * If a request is associated with this buffer, then
 		 * call buf_request_cancel() to give the driver to complete()
@@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 	 * return its buffer and plane numbers.
 	 */
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		vb = q->bufs[buffer];
+		vb = vb2_get_buffer(q, buffer);
+
+		if (!vb)
+			continue;
 
 		for (plane = 0; plane < vb->num_planes; ++plane) {
 			if (vb->planes[plane].m.offset == off) {
@@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
 		return -EINVAL;
 	}
 
-	vb = q->bufs[index];
+	vb = vb2_get_buffer(q, index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
 
 	if (plane >= vb->num_planes) {
 		dprintk(q, 1, "buffer plane out of range\n");
@@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 	if (ret)
 		goto unlock;
 
-	vb = q->bufs[buffer];
+	vb = vb2_get_buffer(q, buffer);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		ret = -EINVAL;
+		goto unlock;
+	}
 
 	/*
 	 * MMAP requires page_aligned buffers.
@@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 	if (ret)
 		goto unlock;
 
-	vb = q->bufs[buffer];
+	vb = vb2_get_buffer(q, buffer);
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		ret = -EINVAL;
+		goto unlock;
+	}
 
 	vaddr = vb2_plane_vaddr(vb, plane);
 	mutex_unlock(&q->mmap_lock);
@@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
 static int __vb2_init_fileio(struct vb2_queue *q, int read)
 {
 	struct vb2_fileio_data *fileio;
+	struct vb2_buffer *vb;
 	int i, ret;
 	unsigned int count = 0;
 
@@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	 * Check if plane_count is correct
 	 * (multiplane buffers are not supported).
 	 */
-	if (q->bufs[0]->num_planes != 1) {
+	vb = vb2_get_buffer(q, 0);
+	if (!vb) {
+		ret = -EBUSY;
+		goto err_reqbufs;
+	}
+
+	if (vb->num_planes != 1) {
 		ret = -EBUSY;
 		goto err_reqbufs;
 	}
@@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	 * Get kernel address of each buffer.
 	 */
 	for (i = 0; i < q->num_buffers; i++) {
-		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+		vb = vb2_get_buffer(q, i);
+
+		if (!vb)
+			continue;
+
+		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
 		if (fileio->bufs[i].vaddr == NULL) {
 			ret = -EINVAL;
 			goto err_reqbufs;
 		}
-		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
+		fileio->bufs[i].size = vb2_plane_size(vb, 0);
 	}
 
 	/*
@@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 
 		fileio->cur_index = index;
 		buf = &fileio->bufs[index];
-		b = q->bufs[index];
+		b = vb2_get_buffer(q, index);
+
+		if (!b)
+			return -EINVAL;
 
 		/*
 		 * Get number of bytes filled by the driver
 		 */
 		buf->pos = 0;
 		buf->queued = 0;
-		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
-				 : vb2_plane_size(q->bufs[index], 0);
+		buf->size = read ? vb2_get_plane_payload(b, 0)
+				 : vb2_plane_size(b, 0);
 		/* Compensate for data_offset on read in the multiplanar case. */
 		if (is_multiplanar && read &&
 				b->planes[0].data_offset < buf->size) {
@@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 	 * Queue next buffer if required.
 	 */
 	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
-		struct vb2_buffer *b = q->bufs[index];
+		struct vb2_buffer *b = vb2_get_buffer(q, index);
 
+		if (!b) {
+			dprintk(q, 1, "can't find the requested buffer\n");
+			return -EINVAL;
+		}
 		/*
 		 * Check if this is the last buffer to read.
 		 */
@@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 		 */
 		buf->pos = 0;
 		buf->queued = 1;
-		buf->size = vb2_plane_size(q->bufs[index], 0);
+		buf->size = vb2_plane_size(b, 0);
 		fileio->q_count += 1;
 		/*
 		 * If we are queuing up buffers for the first time, then
@@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
 		 * Call vb2_dqbuf to get buffer back.
 		 */
 		if (prequeue) {
-			vb = q->bufs[index++];
+			vb = vb2_get_buffer(q, index++);
+			if (!vb)
+				continue;
 			prequeue--;
 		} else {
 			call_void_qop(q, wait_finish, q);
@@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
 			call_void_qop(q, wait_prepare, q);
 			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
 			if (!ret)
-				vb = q->bufs[index];
+				vb = vb2_get_buffer(q, index);
 		}
 		if (ret || threadio->stop)
 			break;
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index c7a54d82a55e..724135d41f7f 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 		return -EINVAL;
 	}
 
-	if (q->bufs[b->index] == NULL) {
-		/* Should never happen */
+	if (!vb2_get_buffer(q, b->index)) {
 		dprintk(q, 1, "%s: buffer is NULL\n", opname);
 		return -EINVAL;
 	}
@@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 		return -EINVAL;
 	}
 
-	vb = q->bufs[b->index];
+	vb = vb2_get_buffer(q, b->index);
 	vbuf = to_vb2_v4l2_buffer(vb);
 	ret = __verify_planes_array(vb, b);
 	if (ret)
@@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
 struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
 {
 	unsigned int i;
+	struct vb2_buffer *vb2;
 
-	for (i = 0; i < q->num_buffers; i++)
-		if (q->bufs[i]->copied_timestamp &&
-		    q->bufs[i]->timestamp == timestamp)
-			return vb2_get_buffer(q, i);
+	for (i = 0; i < q->num_buffers; i++) {
+		vb2 = vb2_get_buffer(q, i);
+
+		if (!vb2)
+			continue;
+
+		if (vb2->copied_timestamp &&
+		    vb2->timestamp == timestamp)
+			return vb2;
+	}
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(vb2_find_buffer);
@@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
 		dprintk(q, 1, "buffer index out of range\n");
 		return -EINVAL;
 	}
-	vb = q->bufs[b->index];
+	vb = vb2_get_buffer(q, b->index);
+
+	if (!vb) {
+		dprintk(q, 1, "can't find the requested buffer\n");
+		return -EINVAL;
+	}
+
 	ret = __verify_planes_array(vb, b);
 	if (!ret)
 		vb2_core_querybuf(q, b->index, b);
diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
index 44b830ae01d8..e2c371c2fde5 100644
--- a/drivers/media/platform/amphion/vpu_dbg.c
+++ b/drivers/media/platform/amphion/vpu_dbg.c
@@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
 
 	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
 	for (i = 0; i < vq->num_buffers; i++) {
-		struct vb2_buffer *vb = vq->bufs[i];
-		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+		struct vb2_buffer *vb;
+		struct vb2_v4l2_buffer *vbuf;
+
+		vb = vb2_get_buffer(vq, i);
+		if (!vb)
+			continue;
 
 		if (vb->state == VB2_BUF_STATE_DEQUEUED)
 			continue;
+
+		vbuf = to_vb2_v4l2_buffer(vb);
+
 		num = scnprintf(str, sizeof(str),
 				"output [%2d] state = %10s, %8s\n",
 				i, vb2_stat_name[vb->state],
@@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
 
 	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
 	for (i = 0; i < vq->num_buffers; i++) {
-		struct vb2_buffer *vb = vq->bufs[i];
-		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+		struct vb2_buffer *vb;
+		struct vb2_v4l2_buffer *vbuf;
+
+		vb = vb2_get_buffer(vq, i);
+		if (!vb)
+			continue;
 
 		if (vb->state == VB2_BUF_STATE_DEQUEUED)
 			continue;
+
+		vbuf = to_vb2_v4l2_buffer(vb);
+
 		num = scnprintf(str, sizeof(str),
 				"capture[%2d] state = %10s, %8s\n",
 				i, vb2_stat_name[vb->state],
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index 0051f372a66c..ea37069ba355 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 		return -EINVAL;
 	}
 
-	vb = vq->bufs[buf->index];
+	vb = vb2_get_buffer(vq, buf->index);
+	if (!vb) {
+		dev_err(ctx->jpeg->dev, "buffer not found\n");
+		return -EINVAL;
+	}
 	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
 	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
 
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
index cf16cf2807f0..6532a69f1fa8 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
@@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
 
 	/* update internal buffer's width/height */
 	for (i = 0; i < vq->num_buffers; i++) {
-		if (vb == vq->bufs[i]) {
+		if (vb == vb2_get_buffer(vq, i)) {
 			instance->dpb[i].width = w;
 			instance->dpb[i].height = h;
 			break;
diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
index 3a848ca32a0e..326be09bdb55 100644
--- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
+++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
@@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 		}
 
 		vb2_buf = vb2_get_buffer(vq, buf->index);
+		if (!vb2_buf) {
+			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
+			return -EINVAL;
+		}
 		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
 		stream->bytesused = buf->bytesused;
 	}
diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
index 318d675e5668..ba20ea998d19 100644
--- a/drivers/media/test-drivers/visl/visl-dec.c
+++ b/drivers/media/test-drivers/visl/visl-dec.c
@@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
 	for (i = 0; i < out_q->num_buffers; i++) {
 		char entry[] = "index: %u, state: %s, request_fd: %d, ";
 		u32 old_len = len;
-		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
+		struct vb2_buffer *vb2;
+		char *q_status;
+
+		vb2 = vb2_get_buffer(out_q, i);
+		if (!vb2)
+			continue;
+
+		q_status = visl_get_vb2_state(vb2->state);
 
 		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
 				 entry, i, q_status,
-				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
+				 to_vb2_v4l2_buffer(vb2)->request_fd);
 
-		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
+		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
 					   &buf[len],
 					   TPG_STR_BUF_SZ - len);
 
@@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
 	len = 0;
 	for (i = 0; i < cap_q->num_buffers; i++) {
 		u32 old_len = len;
-		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
+		struct vb2_buffer *vb2;
+		char *q_status;
+
+		vb2 = vb2_get_buffer(cap_q, i);
+		if (!vb2)
+			continue;
+
+		q_status = visl_get_vb2_state(vb2->state);
 
 		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
 				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
-				 cap_q->bufs[i]->index, q_status,
-				 cap_q->bufs[i]->timestamp,
-				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
+				 vb2->index, q_status,
+				 vb2->timestamp,
+				 to_vb2_v4l2_buffer(vb2)->is_held);
 
 		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
 		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 384f31fc66c5..8df301ab41ad 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
 	if (ret)
 		return ret;
 
-	vb = pipe->vb_queue.bufs[buf->index];
+	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
 	frame = vb_to_frame(vb);
 
 	buf->reserved = asd->frame_status[buf->index];
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 02/10] media: videobuf2: Be more flexible on the number of queue stored buffers
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Add 'max_allowed_buffers' field in vb2_queue struct to let drivers decide
how many buffers could be stored in a queue.
This request 'bufs' array to be allocated at queue init time and freed
when releasing the queue.
By default VB2_MAX_FRAME remains the limit.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
version 4:
- no Xarray here but instead a new field to let queues decide
  of their own maximum.
 .../media/common/videobuf2/videobuf2-core.c   | 22 ++++++++++++-------
 include/media/videobuf2-core.h                |  4 +++-
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 42fd3984c2bc..77e69b01d88d 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -413,7 +413,7 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
  */
 static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
 {
-	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
+	if (index < q->max_allowed_buffers && !q->bufs[index]) {
 		q->bufs[index] = vb;
 		vb->index = index;
 		vb->vb2_queue = q;
@@ -430,7 +430,7 @@ static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int
  */
 static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
 {
-	if (vb->index < VB2_MAX_FRAME) {
+	if (vb->index < q->max_allowed_buffers) {
 		q->bufs[vb->index] = NULL;
 		vb->vb2_queue = NULL;
 	}
@@ -451,9 +451,9 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 	struct vb2_buffer *vb;
 	int ret;
 
-	/* Ensure that q->num_buffers+num_buffers is below VB2_MAX_FRAME */
+	/* Ensure that q->num_buffers+num_buffers is below q->max_allowed_buffers */
 	num_buffers = min_t(unsigned int, num_buffers,
-			    VB2_MAX_FRAME - q->num_buffers);
+			    q->max_allowed_buffers - q->num_buffers);
 
 	for (buffer = 0; buffer < num_buffers; ++buffer) {
 		/* Allocate vb2 buffer structures */
@@ -854,9 +854,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
 	/*
 	 * Make sure the requested values and current defaults are sane.
 	 */
-	WARN_ON(q->min_buffers_needed > VB2_MAX_FRAME);
+	WARN_ON(q->min_buffers_needed > q->max_allowed_buffers);
 	num_buffers = max_t(unsigned int, *count, q->min_buffers_needed);
-	num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME);
+	num_buffers = min_t(unsigned int, num_buffers, q->max_allowed_buffers);
 	memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
 	/*
 	 * Set this now to ensure that drivers see the correct q->memory value
@@ -972,7 +972,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
 	bool no_previous_buffers = !q->num_buffers;
 	int ret;
 
-	if (q->num_buffers == VB2_MAX_FRAME) {
+	if (q->num_buffers == q->max_allowed_buffers) {
 		dprintk(q, 1, "maximum number of buffers already allocated\n");
 		return -ENOBUFS;
 	}
@@ -1001,7 +1001,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
 			return -EINVAL;
 	}
 
-	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
+	num_buffers = min(*count, q->max_allowed_buffers - q->num_buffers);
 
 	if (requested_planes && requested_sizes) {
 		num_planes = requested_planes;
@@ -2549,6 +2549,11 @@ int vb2_core_queue_init(struct vb2_queue *q)
 
 	q->memory = VB2_MEMORY_UNKNOWN;
 
+	if (!q->max_allowed_buffers)
+		q->max_allowed_buffers = VB2_MAX_FRAME;
+
+	q->bufs = kcalloc(q->max_allowed_buffers, sizeof(*q->bufs), GFP_KERNEL);
+
 	if (q->buf_struct_size == 0)
 		q->buf_struct_size = sizeof(struct vb2_buffer);
 
@@ -2573,6 +2578,7 @@ void vb2_core_queue_release(struct vb2_queue *q)
 	__vb2_queue_cancel(q);
 	mutex_lock(&q->mmap_lock);
 	__vb2_queue_free(q, q->num_buffers);
+	kfree(q->bufs);
 	mutex_unlock(&q->mmap_lock);
 }
 EXPORT_SYMBOL_GPL(vb2_core_queue_release);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4b6a9d2ea372..ee9161b9fd64 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -558,6 +558,7 @@ struct vb2_buf_ops {
  * @dma_dir:	DMA mapping direction.
  * @bufs:	videobuf2 buffer structures
  * @num_buffers: number of allocated/used buffers
+ * @max_allowed_buffers: upper limit of number of allocated/used buffers
  * @queued_list: list of buffers currently queued from userspace
  * @queued_count: number of buffers queued and ready for streaming.
  * @owned_by_drv_count: number of buffers owned by the driver
@@ -619,8 +620,9 @@ struct vb2_queue {
 	struct mutex			mmap_lock;
 	unsigned int			memory;
 	enum dma_data_direction		dma_dir;
-	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
+	struct vb2_buffer		**bufs;
 	unsigned int			num_buffers;
+	unsigned int			max_allowed_buffers;
 
 	struct list_head		queued_list;
 	unsigned int			queued_count;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 02/10] media: videobuf2: Be more flexible on the number of queue stored buffers
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Add 'max_allowed_buffers' field in vb2_queue struct to let drivers decide
how many buffers could be stored in a queue.
This request 'bufs' array to be allocated at queue init time and freed
when releasing the queue.
By default VB2_MAX_FRAME remains the limit.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
version 4:
- no Xarray here but instead a new field to let queues decide
  of their own maximum.
 .../media/common/videobuf2/videobuf2-core.c   | 22 ++++++++++++-------
 include/media/videobuf2-core.h                |  4 +++-
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 42fd3984c2bc..77e69b01d88d 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -413,7 +413,7 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
  */
 static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
 {
-	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
+	if (index < q->max_allowed_buffers && !q->bufs[index]) {
 		q->bufs[index] = vb;
 		vb->index = index;
 		vb->vb2_queue = q;
@@ -430,7 +430,7 @@ static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int
  */
 static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
 {
-	if (vb->index < VB2_MAX_FRAME) {
+	if (vb->index < q->max_allowed_buffers) {
 		q->bufs[vb->index] = NULL;
 		vb->vb2_queue = NULL;
 	}
@@ -451,9 +451,9 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 	struct vb2_buffer *vb;
 	int ret;
 
-	/* Ensure that q->num_buffers+num_buffers is below VB2_MAX_FRAME */
+	/* Ensure that q->num_buffers+num_buffers is below q->max_allowed_buffers */
 	num_buffers = min_t(unsigned int, num_buffers,
-			    VB2_MAX_FRAME - q->num_buffers);
+			    q->max_allowed_buffers - q->num_buffers);
 
 	for (buffer = 0; buffer < num_buffers; ++buffer) {
 		/* Allocate vb2 buffer structures */
@@ -854,9 +854,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
 	/*
 	 * Make sure the requested values and current defaults are sane.
 	 */
-	WARN_ON(q->min_buffers_needed > VB2_MAX_FRAME);
+	WARN_ON(q->min_buffers_needed > q->max_allowed_buffers);
 	num_buffers = max_t(unsigned int, *count, q->min_buffers_needed);
-	num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME);
+	num_buffers = min_t(unsigned int, num_buffers, q->max_allowed_buffers);
 	memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
 	/*
 	 * Set this now to ensure that drivers see the correct q->memory value
@@ -972,7 +972,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
 	bool no_previous_buffers = !q->num_buffers;
 	int ret;
 
-	if (q->num_buffers == VB2_MAX_FRAME) {
+	if (q->num_buffers == q->max_allowed_buffers) {
 		dprintk(q, 1, "maximum number of buffers already allocated\n");
 		return -ENOBUFS;
 	}
@@ -1001,7 +1001,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
 			return -EINVAL;
 	}
 
-	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
+	num_buffers = min(*count, q->max_allowed_buffers - q->num_buffers);
 
 	if (requested_planes && requested_sizes) {
 		num_planes = requested_planes;
@@ -2549,6 +2549,11 @@ int vb2_core_queue_init(struct vb2_queue *q)
 
 	q->memory = VB2_MEMORY_UNKNOWN;
 
+	if (!q->max_allowed_buffers)
+		q->max_allowed_buffers = VB2_MAX_FRAME;
+
+	q->bufs = kcalloc(q->max_allowed_buffers, sizeof(*q->bufs), GFP_KERNEL);
+
 	if (q->buf_struct_size == 0)
 		q->buf_struct_size = sizeof(struct vb2_buffer);
 
@@ -2573,6 +2578,7 @@ void vb2_core_queue_release(struct vb2_queue *q)
 	__vb2_queue_cancel(q);
 	mutex_lock(&q->mmap_lock);
 	__vb2_queue_free(q, q->num_buffers);
+	kfree(q->bufs);
 	mutex_unlock(&q->mmap_lock);
 }
 EXPORT_SYMBOL_GPL(vb2_core_queue_release);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4b6a9d2ea372..ee9161b9fd64 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -558,6 +558,7 @@ struct vb2_buf_ops {
  * @dma_dir:	DMA mapping direction.
  * @bufs:	videobuf2 buffer structures
  * @num_buffers: number of allocated/used buffers
+ * @max_allowed_buffers: upper limit of number of allocated/used buffers
  * @queued_list: list of buffers currently queued from userspace
  * @queued_count: number of buffers queued and ready for streaming.
  * @owned_by_drv_count: number of buffers owned by the driver
@@ -619,8 +620,9 @@ struct vb2_queue {
 	struct mutex			mmap_lock;
 	unsigned int			memory;
 	enum dma_data_direction		dma_dir;
-	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
+	struct vb2_buffer		**bufs;
 	unsigned int			num_buffers;
+	unsigned int			max_allowed_buffers;
 
 	struct list_head		queued_list;
 	unsigned int			queued_count;
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 02/10] media: videobuf2: Be more flexible on the number of queue stored buffers
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Add 'max_allowed_buffers' field in vb2_queue struct to let drivers decide
how many buffers could be stored in a queue.
This request 'bufs' array to be allocated at queue init time and freed
when releasing the queue.
By default VB2_MAX_FRAME remains the limit.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
version 4:
- no Xarray here but instead a new field to let queues decide
  of their own maximum.
 .../media/common/videobuf2/videobuf2-core.c   | 22 ++++++++++++-------
 include/media/videobuf2-core.h                |  4 +++-
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 42fd3984c2bc..77e69b01d88d 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -413,7 +413,7 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
  */
 static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
 {
-	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
+	if (index < q->max_allowed_buffers && !q->bufs[index]) {
 		q->bufs[index] = vb;
 		vb->index = index;
 		vb->vb2_queue = q;
@@ -430,7 +430,7 @@ static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int
  */
 static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
 {
-	if (vb->index < VB2_MAX_FRAME) {
+	if (vb->index < q->max_allowed_buffers) {
 		q->bufs[vb->index] = NULL;
 		vb->vb2_queue = NULL;
 	}
@@ -451,9 +451,9 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 	struct vb2_buffer *vb;
 	int ret;
 
-	/* Ensure that q->num_buffers+num_buffers is below VB2_MAX_FRAME */
+	/* Ensure that q->num_buffers+num_buffers is below q->max_allowed_buffers */
 	num_buffers = min_t(unsigned int, num_buffers,
-			    VB2_MAX_FRAME - q->num_buffers);
+			    q->max_allowed_buffers - q->num_buffers);
 
 	for (buffer = 0; buffer < num_buffers; ++buffer) {
 		/* Allocate vb2 buffer structures */
@@ -854,9 +854,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
 	/*
 	 * Make sure the requested values and current defaults are sane.
 	 */
-	WARN_ON(q->min_buffers_needed > VB2_MAX_FRAME);
+	WARN_ON(q->min_buffers_needed > q->max_allowed_buffers);
 	num_buffers = max_t(unsigned int, *count, q->min_buffers_needed);
-	num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME);
+	num_buffers = min_t(unsigned int, num_buffers, q->max_allowed_buffers);
 	memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
 	/*
 	 * Set this now to ensure that drivers see the correct q->memory value
@@ -972,7 +972,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
 	bool no_previous_buffers = !q->num_buffers;
 	int ret;
 
-	if (q->num_buffers == VB2_MAX_FRAME) {
+	if (q->num_buffers == q->max_allowed_buffers) {
 		dprintk(q, 1, "maximum number of buffers already allocated\n");
 		return -ENOBUFS;
 	}
@@ -1001,7 +1001,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
 			return -EINVAL;
 	}
 
-	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
+	num_buffers = min(*count, q->max_allowed_buffers - q->num_buffers);
 
 	if (requested_planes && requested_sizes) {
 		num_planes = requested_planes;
@@ -2549,6 +2549,11 @@ int vb2_core_queue_init(struct vb2_queue *q)
 
 	q->memory = VB2_MEMORY_UNKNOWN;
 
+	if (!q->max_allowed_buffers)
+		q->max_allowed_buffers = VB2_MAX_FRAME;
+
+	q->bufs = kcalloc(q->max_allowed_buffers, sizeof(*q->bufs), GFP_KERNEL);
+
 	if (q->buf_struct_size == 0)
 		q->buf_struct_size = sizeof(struct vb2_buffer);
 
@@ -2573,6 +2578,7 @@ void vb2_core_queue_release(struct vb2_queue *q)
 	__vb2_queue_cancel(q);
 	mutex_lock(&q->mmap_lock);
 	__vb2_queue_free(q, q->num_buffers);
+	kfree(q->bufs);
 	mutex_unlock(&q->mmap_lock);
 }
 EXPORT_SYMBOL_GPL(vb2_core_queue_release);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4b6a9d2ea372..ee9161b9fd64 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -558,6 +558,7 @@ struct vb2_buf_ops {
  * @dma_dir:	DMA mapping direction.
  * @bufs:	videobuf2 buffer structures
  * @num_buffers: number of allocated/used buffers
+ * @max_allowed_buffers: upper limit of number of allocated/used buffers
  * @queued_list: list of buffers currently queued from userspace
  * @queued_count: number of buffers queued and ready for streaming.
  * @owned_by_drv_count: number of buffers owned by the driver
@@ -619,8 +620,9 @@ struct vb2_queue {
 	struct mutex			mmap_lock;
 	unsigned int			memory;
 	enum dma_data_direction		dma_dir;
-	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
+	struct vb2_buffer		**bufs;
 	unsigned int			num_buffers;
+	unsigned int			max_allowed_buffers;
 
 	struct list_head		queued_list;
 	unsigned int			queued_count;
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 03/10] media: videobuf2: Rework offset 'cookie' encoding pattern
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Change how offset 'cookie' field value is computed to make possible
to use more buffers.
With this encoding pattern we know the maximum number that a queue
could store so we can check ing at queue init time.
It also make easier and faster to find buffer and plane from using
the offset field.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/common/videobuf2/videobuf2-core.c   | 63 +++++++++----------
 1 file changed, 29 insertions(+), 34 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 77e69b01d88d..70e36389b704 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -31,6 +31,10 @@
 
 #include <trace/events/vb2.h>
 
+#define PLANE_INDEX_SHIFT	3
+#define PLANE_INDEX_MASK	0x7
+#define MAX_BUFFERS		0xffff
+
 static int debug;
 module_param(debug, int, 0644);
 
@@ -358,29 +362,23 @@ static void __setup_offsets(struct vb2_buffer *vb)
 	unsigned int plane;
 	unsigned long off = 0;
 
-	if (vb->index) {
-		struct vb2_buffer *prev;
-		struct vb2_plane *p;
-
-		prev = vb2_get_buffer(q, vb->index - 1);
-		if (!prev) {
-			dprintk(q, 1, "can't find the requested buffer\n");
-			return;
-		}
-
-		p = &prev->planes[prev->num_planes - 1];
-
-		off = PAGE_ALIGN(p->m.offset + p->length);
-	}
+	/*
+	 * Offsets cookies value have the following constraints:
+	 * - a buffer could have up to 8 planes.
+	 * - v4l2 mem2mem use bit 30 to distinguish between source and destination buffers.
+	 * - must be page aligned
+	 * That led to this bit mapping:
+	 * |30                |29        15|14       12|11 0|
+	 * |DST_QUEUE_OFF_BASE|buffer index|plane index| 0  |
+	 * where there is 16 bits to store buffer index.
+	 */
+	off = vb->index << (PLANE_INDEX_SHIFT + PAGE_SHIFT);
 
 	for (plane = 0; plane < vb->num_planes; ++plane) {
-		vb->planes[plane].m.offset = off;
+		vb->planes[plane].m.offset = off + (plane << PAGE_SHIFT);
 
 		dprintk(q, 3, "buffer %d, plane %d offset 0x%08lx\n",
 				vb->index, plane, off);
-
-		off += vb->planes[plane].length;
-		off = PAGE_ALIGN(off);
 	}
 }
 
@@ -2294,24 +2292,18 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 		return -EBUSY;
 	}
 
-	/*
-	 * Go over all buffers and their planes, comparing the given offset
-	 * with an offset assigned to each plane. If a match is found,
-	 * return its buffer and plane numbers.
-	 */
-	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		vb = vb2_get_buffer(q, buffer);
+	/* Get buffer and plane from the offset */
+	buffer = (off >> (PLANE_INDEX_SHIFT + PAGE_SHIFT)) & MAX_BUFFERS;
+	plane = (off >> PAGE_SHIFT) & PLANE_INDEX_MASK;
 
-		if (!vb)
-			continue;
+	vb = vb2_get_buffer(q, buffer);
+	if (!vb)
+		return -EINVAL;
 
-		for (plane = 0; plane < vb->num_planes; ++plane) {
-			if (vb->planes[plane].m.offset == off) {
-				*_buffer = buffer;
-				*_plane = plane;
-				return 0;
-			}
-		}
+	if (vb->planes[plane].m.offset == off) {
+		*_buffer = buffer;
+		*_plane = plane;
+		return 0;
 	}
 
 	return -EINVAL;
@@ -2552,6 +2544,9 @@ int vb2_core_queue_init(struct vb2_queue *q)
 	if (!q->max_allowed_buffers)
 		q->max_allowed_buffers = VB2_MAX_FRAME;
 
+	/* The maximum is limited by offset cookie encoding pattern */
+	q->max_allowed_buffers = min_t(unsigned int, q->max_allowed_buffers, MAX_BUFFERS);
+
 	q->bufs = kcalloc(q->max_allowed_buffers, sizeof(*q->bufs), GFP_KERNEL);
 
 	if (q->buf_struct_size == 0)
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 03/10] media: videobuf2: Rework offset 'cookie' encoding pattern
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Change how offset 'cookie' field value is computed to make possible
to use more buffers.
With this encoding pattern we know the maximum number that a queue
could store so we can check ing at queue init time.
It also make easier and faster to find buffer and plane from using
the offset field.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/common/videobuf2/videobuf2-core.c   | 63 +++++++++----------
 1 file changed, 29 insertions(+), 34 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 77e69b01d88d..70e36389b704 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -31,6 +31,10 @@
 
 #include <trace/events/vb2.h>
 
+#define PLANE_INDEX_SHIFT	3
+#define PLANE_INDEX_MASK	0x7
+#define MAX_BUFFERS		0xffff
+
 static int debug;
 module_param(debug, int, 0644);
 
@@ -358,29 +362,23 @@ static void __setup_offsets(struct vb2_buffer *vb)
 	unsigned int plane;
 	unsigned long off = 0;
 
-	if (vb->index) {
-		struct vb2_buffer *prev;
-		struct vb2_plane *p;
-
-		prev = vb2_get_buffer(q, vb->index - 1);
-		if (!prev) {
-			dprintk(q, 1, "can't find the requested buffer\n");
-			return;
-		}
-
-		p = &prev->planes[prev->num_planes - 1];
-
-		off = PAGE_ALIGN(p->m.offset + p->length);
-	}
+	/*
+	 * Offsets cookies value have the following constraints:
+	 * - a buffer could have up to 8 planes.
+	 * - v4l2 mem2mem use bit 30 to distinguish between source and destination buffers.
+	 * - must be page aligned
+	 * That led to this bit mapping:
+	 * |30                |29        15|14       12|11 0|
+	 * |DST_QUEUE_OFF_BASE|buffer index|plane index| 0  |
+	 * where there is 16 bits to store buffer index.
+	 */
+	off = vb->index << (PLANE_INDEX_SHIFT + PAGE_SHIFT);
 
 	for (plane = 0; plane < vb->num_planes; ++plane) {
-		vb->planes[plane].m.offset = off;
+		vb->planes[plane].m.offset = off + (plane << PAGE_SHIFT);
 
 		dprintk(q, 3, "buffer %d, plane %d offset 0x%08lx\n",
 				vb->index, plane, off);
-
-		off += vb->planes[plane].length;
-		off = PAGE_ALIGN(off);
 	}
 }
 
@@ -2294,24 +2292,18 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 		return -EBUSY;
 	}
 
-	/*
-	 * Go over all buffers and their planes, comparing the given offset
-	 * with an offset assigned to each plane. If a match is found,
-	 * return its buffer and plane numbers.
-	 */
-	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		vb = vb2_get_buffer(q, buffer);
+	/* Get buffer and plane from the offset */
+	buffer = (off >> (PLANE_INDEX_SHIFT + PAGE_SHIFT)) & MAX_BUFFERS;
+	plane = (off >> PAGE_SHIFT) & PLANE_INDEX_MASK;
 
-		if (!vb)
-			continue;
+	vb = vb2_get_buffer(q, buffer);
+	if (!vb)
+		return -EINVAL;
 
-		for (plane = 0; plane < vb->num_planes; ++plane) {
-			if (vb->planes[plane].m.offset == off) {
-				*_buffer = buffer;
-				*_plane = plane;
-				return 0;
-			}
-		}
+	if (vb->planes[plane].m.offset == off) {
+		*_buffer = buffer;
+		*_plane = plane;
+		return 0;
 	}
 
 	return -EINVAL;
@@ -2552,6 +2544,9 @@ int vb2_core_queue_init(struct vb2_queue *q)
 	if (!q->max_allowed_buffers)
 		q->max_allowed_buffers = VB2_MAX_FRAME;
 
+	/* The maximum is limited by offset cookie encoding pattern */
+	q->max_allowed_buffers = min_t(unsigned int, q->max_allowed_buffers, MAX_BUFFERS);
+
 	q->bufs = kcalloc(q->max_allowed_buffers, sizeof(*q->bufs), GFP_KERNEL);
 
 	if (q->buf_struct_size == 0)
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 03/10] media: videobuf2: Rework offset 'cookie' encoding pattern
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Change how offset 'cookie' field value is computed to make possible
to use more buffers.
With this encoding pattern we know the maximum number that a queue
could store so we can check ing at queue init time.
It also make easier and faster to find buffer and plane from using
the offset field.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/common/videobuf2/videobuf2-core.c   | 63 +++++++++----------
 1 file changed, 29 insertions(+), 34 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 77e69b01d88d..70e36389b704 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -31,6 +31,10 @@
 
 #include <trace/events/vb2.h>
 
+#define PLANE_INDEX_SHIFT	3
+#define PLANE_INDEX_MASK	0x7
+#define MAX_BUFFERS		0xffff
+
 static int debug;
 module_param(debug, int, 0644);
 
@@ -358,29 +362,23 @@ static void __setup_offsets(struct vb2_buffer *vb)
 	unsigned int plane;
 	unsigned long off = 0;
 
-	if (vb->index) {
-		struct vb2_buffer *prev;
-		struct vb2_plane *p;
-
-		prev = vb2_get_buffer(q, vb->index - 1);
-		if (!prev) {
-			dprintk(q, 1, "can't find the requested buffer\n");
-			return;
-		}
-
-		p = &prev->planes[prev->num_planes - 1];
-
-		off = PAGE_ALIGN(p->m.offset + p->length);
-	}
+	/*
+	 * Offsets cookies value have the following constraints:
+	 * - a buffer could have up to 8 planes.
+	 * - v4l2 mem2mem use bit 30 to distinguish between source and destination buffers.
+	 * - must be page aligned
+	 * That led to this bit mapping:
+	 * |30                |29        15|14       12|11 0|
+	 * |DST_QUEUE_OFF_BASE|buffer index|plane index| 0  |
+	 * where there is 16 bits to store buffer index.
+	 */
+	off = vb->index << (PLANE_INDEX_SHIFT + PAGE_SHIFT);
 
 	for (plane = 0; plane < vb->num_planes; ++plane) {
-		vb->planes[plane].m.offset = off;
+		vb->planes[plane].m.offset = off + (plane << PAGE_SHIFT);
 
 		dprintk(q, 3, "buffer %d, plane %d offset 0x%08lx\n",
 				vb->index, plane, off);
-
-		off += vb->planes[plane].length;
-		off = PAGE_ALIGN(off);
 	}
 }
 
@@ -2294,24 +2292,18 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 		return -EBUSY;
 	}
 
-	/*
-	 * Go over all buffers and their planes, comparing the given offset
-	 * with an offset assigned to each plane. If a match is found,
-	 * return its buffer and plane numbers.
-	 */
-	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		vb = vb2_get_buffer(q, buffer);
+	/* Get buffer and plane from the offset */
+	buffer = (off >> (PLANE_INDEX_SHIFT + PAGE_SHIFT)) & MAX_BUFFERS;
+	plane = (off >> PAGE_SHIFT) & PLANE_INDEX_MASK;
 
-		if (!vb)
-			continue;
+	vb = vb2_get_buffer(q, buffer);
+	if (!vb)
+		return -EINVAL;
 
-		for (plane = 0; plane < vb->num_planes; ++plane) {
-			if (vb->planes[plane].m.offset == off) {
-				*_buffer = buffer;
-				*_plane = plane;
-				return 0;
-			}
-		}
+	if (vb->planes[plane].m.offset == off) {
+		*_buffer = buffer;
+		*_plane = plane;
+		return 0;
 	}
 
 	return -EINVAL;
@@ -2552,6 +2544,9 @@ int vb2_core_queue_init(struct vb2_queue *q)
 	if (!q->max_allowed_buffers)
 		q->max_allowed_buffers = VB2_MAX_FRAME;
 
+	/* The maximum is limited by offset cookie encoding pattern */
+	q->max_allowed_buffers = min_t(unsigned int, q->max_allowed_buffers, MAX_BUFFERS);
+
 	q->bufs = kcalloc(q->max_allowed_buffers, sizeof(*q->bufs), GFP_KERNEL);
 
 	if (q->buf_struct_size == 0)
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 04/10] media: verisilicon: Refactor postprocessor to store more buffers
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Since vb2 queue can store than VB2_MAX_FRAME buffers postprocessor
buffer storage must be capable to store more buffers too.
Change static dec_q array to allocated array to be capable to store
up to queue 'max_allowed_buffers'.
Keep allocating queue 'num_buffers' at queue setup time but also allows
to allocate postprocessors buffers on the fly.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 drivers/media/platform/verisilicon/hantro.h   |   7 +-
 .../media/platform/verisilicon/hantro_drv.c   |   4 +-
 .../media/platform/verisilicon/hantro_hw.h    |   2 +-
 .../platform/verisilicon/hantro_postproc.c    | 103 ++++++++++++++----
 .../media/platform/verisilicon/hantro_v4l2.c  |   2 +-
 5 files changed, 93 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
index 2989ebc631cc..c8a3cf10cc64 100644
--- a/drivers/media/platform/verisilicon/hantro.h
+++ b/drivers/media/platform/verisilicon/hantro.h
@@ -461,11 +461,14 @@ hantro_get_dst_buf(struct hantro_ctx *ctx)
 bool hantro_needs_postproc(const struct hantro_ctx *ctx,
 			   const struct hantro_fmt *fmt);
 
+dma_addr_t
+hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index);
+
 static inline dma_addr_t
 hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
 {
 	if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
-		return ctx->postproc.dec_q[vb->index].dma;
+		return hantro_postproc_get_dec_buf_addr(ctx, vb->index);
 	return vb2_dma_contig_plane_dma_addr(vb, 0);
 }
 
@@ -477,8 +480,8 @@ vb2_to_hantro_decoded_buf(struct vb2_buffer *buf)
 
 void hantro_postproc_disable(struct hantro_ctx *ctx);
 void hantro_postproc_enable(struct hantro_ctx *ctx);
+int hantro_postproc_init(struct hantro_ctx *ctx);
 void hantro_postproc_free(struct hantro_ctx *ctx);
-int hantro_postproc_alloc(struct hantro_ctx *ctx);
 int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
 				   struct v4l2_frmsizeenum *fsize);
 
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 09c74a573ddb..d908559817ce 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -234,8 +234,10 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
 	 * The Kernel needs access to the JPEG destination buffer for the
 	 * JPEG encoder to fill in the JPEG headers.
 	 */
-	if (!ctx->is_encoder)
+	if (!ctx->is_encoder) {
 		dst_vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
+		dst_vq->max_allowed_buffers = 64;
+	}
 
 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
index e83f0c523a30..6fd6c9d53cec 100644
--- a/drivers/media/platform/verisilicon/hantro_hw.h
+++ b/drivers/media/platform/verisilicon/hantro_hw.h
@@ -253,7 +253,7 @@ struct hantro_vp9_dec_hw_ctx {
  * @dec_q:		References buffers, in decoder format.
  */
 struct hantro_postproc_ctx {
-	struct hantro_aux_buf dec_q[VB2_MAX_FRAME];
+	struct hantro_aux_buf *dec_q;
 };
 
 /**
diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
index 6437423ccf3a..9dfe3141a398 100644
--- a/drivers/media/platform/verisilicon/hantro_postproc.c
+++ b/drivers/media/platform/verisilicon/hantro_postproc.c
@@ -173,9 +173,11 @@ static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx,
 void hantro_postproc_free(struct hantro_ctx *ctx)
 {
 	struct hantro_dev *vpu = ctx->dev;
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_queue *queue = &m2m_ctx->cap_q_ctx.q;
 	unsigned int i;
 
-	for (i = 0; i < VB2_MAX_FRAME; ++i) {
+	for (i = 0; i < queue->max_allowed_buffers; ++i) {
 		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
 
 		if (priv->cpu) {
@@ -184,22 +186,21 @@ void hantro_postproc_free(struct hantro_ctx *ctx)
 			priv->cpu = NULL;
 		}
 	}
+	kfree(ctx->postproc.dec_q);
+	ctx->postproc.dec_q = NULL;
 }
 
-int hantro_postproc_alloc(struct hantro_ctx *ctx)
+static unsigned int hantro_postproc_buffer_size(struct hantro_ctx *ctx)
 {
-	struct hantro_dev *vpu = ctx->dev;
-	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
-	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
-	unsigned int num_buffers = cap_queue->num_buffers;
 	struct v4l2_pix_format_mplane pix_mp;
 	const struct hantro_fmt *fmt;
-	unsigned int i, buf_size;
+	unsigned int buf_size;
 
 	/* this should always pick native format */
 	fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth);
 	if (!fmt)
-		return -EINVAL;
+		return 0;
+
 	v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width,
 			    ctx->src_fmt.height);
 
@@ -214,23 +215,85 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
 		buf_size += hantro_hevc_mv_size(pix_mp.width,
 						pix_mp.height);
 
-	for (i = 0; i < num_buffers; ++i) {
-		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
+	return buf_size;
+}
+
+static int hantro_postproc_alloc(struct hantro_ctx *ctx, int index)
+{
+	struct hantro_dev *vpu = ctx->dev;
+	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
+	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
+
+	if (!buf_size)
+		return -EINVAL;
+
+	/*
+	 * The buffers on this queue are meant as intermediate
+	 * buffers for the decoder, so no mapping is needed.
+	 */
+	priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
+	priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
+				    GFP_KERNEL, priv->attrs);
+	if (!priv->cpu)
+		return -ENOMEM;
+	priv->size = buf_size;
+
+	return 0;
+}
+
+int hantro_postproc_init(struct hantro_ctx *ctx)
+{
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
+	unsigned int num_buffers = cap_queue->num_buffers;
+	unsigned int i;
+	int ret;
 
-		/*
-		 * The buffers on this queue are meant as intermediate
-		 * buffers for the decoder, so no mapping is needed.
-		 */
-		priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
-		priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
-					    GFP_KERNEL, priv->attrs);
-		if (!priv->cpu)
-			return -ENOMEM;
-		priv->size = buf_size;
+	if (!ctx->postproc.dec_q)
+		ctx->postproc.dec_q = kcalloc(cap_queue->max_allowed_buffers,
+					      sizeof(*ctx->postproc.dec_q),
+					      GFP_KERNEL);
+
+	if (!ctx->postproc.dec_q)
+		return -EINVAL;
+
+	for (i = 0; i < num_buffers; i++) {
+		ret = hantro_postproc_alloc(ctx, i);
+		if (ret)
+			return ret;
 	}
+
 	return 0;
 }
 
+dma_addr_t
+hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index)
+{
+	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
+	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
+	struct hantro_dev *vpu = ctx->dev;
+	int ret;
+
+	if (priv->size < buf_size && priv->cpu) {
+		/* buffer is too small, release it */
+		dma_free_attrs(vpu->dev, priv->size, priv->cpu,
+			       priv->dma, priv->attrs);
+		priv->cpu = NULL;
+	}
+
+	if (!priv->cpu) {
+		/* buffer not already allocated, try getting a new one */
+		ret = hantro_postproc_alloc(ctx, index);
+		if (ret)
+			return 0;
+	}
+
+	if (!priv->cpu)
+		return 0;
+
+	return priv->dma;
+}
+
 static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
 {
 	struct hantro_dev *vpu = ctx->dev;
diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 61cfaaf4e927..898e8763d63a 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -897,7 +897,7 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
 		}
 
 		if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) {
-			ret = hantro_postproc_alloc(ctx);
+			ret = hantro_postproc_init(ctx);
 			if (ret)
 				goto err_codec_exit;
 		}
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 04/10] media: verisilicon: Refactor postprocessor to store more buffers
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Since vb2 queue can store than VB2_MAX_FRAME buffers postprocessor
buffer storage must be capable to store more buffers too.
Change static dec_q array to allocated array to be capable to store
up to queue 'max_allowed_buffers'.
Keep allocating queue 'num_buffers' at queue setup time but also allows
to allocate postprocessors buffers on the fly.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 drivers/media/platform/verisilicon/hantro.h   |   7 +-
 .../media/platform/verisilicon/hantro_drv.c   |   4 +-
 .../media/platform/verisilicon/hantro_hw.h    |   2 +-
 .../platform/verisilicon/hantro_postproc.c    | 103 ++++++++++++++----
 .../media/platform/verisilicon/hantro_v4l2.c  |   2 +-
 5 files changed, 93 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
index 2989ebc631cc..c8a3cf10cc64 100644
--- a/drivers/media/platform/verisilicon/hantro.h
+++ b/drivers/media/platform/verisilicon/hantro.h
@@ -461,11 +461,14 @@ hantro_get_dst_buf(struct hantro_ctx *ctx)
 bool hantro_needs_postproc(const struct hantro_ctx *ctx,
 			   const struct hantro_fmt *fmt);
 
+dma_addr_t
+hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index);
+
 static inline dma_addr_t
 hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
 {
 	if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
-		return ctx->postproc.dec_q[vb->index].dma;
+		return hantro_postproc_get_dec_buf_addr(ctx, vb->index);
 	return vb2_dma_contig_plane_dma_addr(vb, 0);
 }
 
@@ -477,8 +480,8 @@ vb2_to_hantro_decoded_buf(struct vb2_buffer *buf)
 
 void hantro_postproc_disable(struct hantro_ctx *ctx);
 void hantro_postproc_enable(struct hantro_ctx *ctx);
+int hantro_postproc_init(struct hantro_ctx *ctx);
 void hantro_postproc_free(struct hantro_ctx *ctx);
-int hantro_postproc_alloc(struct hantro_ctx *ctx);
 int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
 				   struct v4l2_frmsizeenum *fsize);
 
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 09c74a573ddb..d908559817ce 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -234,8 +234,10 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
 	 * The Kernel needs access to the JPEG destination buffer for the
 	 * JPEG encoder to fill in the JPEG headers.
 	 */
-	if (!ctx->is_encoder)
+	if (!ctx->is_encoder) {
 		dst_vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
+		dst_vq->max_allowed_buffers = 64;
+	}
 
 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
index e83f0c523a30..6fd6c9d53cec 100644
--- a/drivers/media/platform/verisilicon/hantro_hw.h
+++ b/drivers/media/platform/verisilicon/hantro_hw.h
@@ -253,7 +253,7 @@ struct hantro_vp9_dec_hw_ctx {
  * @dec_q:		References buffers, in decoder format.
  */
 struct hantro_postproc_ctx {
-	struct hantro_aux_buf dec_q[VB2_MAX_FRAME];
+	struct hantro_aux_buf *dec_q;
 };
 
 /**
diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
index 6437423ccf3a..9dfe3141a398 100644
--- a/drivers/media/platform/verisilicon/hantro_postproc.c
+++ b/drivers/media/platform/verisilicon/hantro_postproc.c
@@ -173,9 +173,11 @@ static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx,
 void hantro_postproc_free(struct hantro_ctx *ctx)
 {
 	struct hantro_dev *vpu = ctx->dev;
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_queue *queue = &m2m_ctx->cap_q_ctx.q;
 	unsigned int i;
 
-	for (i = 0; i < VB2_MAX_FRAME; ++i) {
+	for (i = 0; i < queue->max_allowed_buffers; ++i) {
 		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
 
 		if (priv->cpu) {
@@ -184,22 +186,21 @@ void hantro_postproc_free(struct hantro_ctx *ctx)
 			priv->cpu = NULL;
 		}
 	}
+	kfree(ctx->postproc.dec_q);
+	ctx->postproc.dec_q = NULL;
 }
 
-int hantro_postproc_alloc(struct hantro_ctx *ctx)
+static unsigned int hantro_postproc_buffer_size(struct hantro_ctx *ctx)
 {
-	struct hantro_dev *vpu = ctx->dev;
-	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
-	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
-	unsigned int num_buffers = cap_queue->num_buffers;
 	struct v4l2_pix_format_mplane pix_mp;
 	const struct hantro_fmt *fmt;
-	unsigned int i, buf_size;
+	unsigned int buf_size;
 
 	/* this should always pick native format */
 	fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth);
 	if (!fmt)
-		return -EINVAL;
+		return 0;
+
 	v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width,
 			    ctx->src_fmt.height);
 
@@ -214,23 +215,85 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
 		buf_size += hantro_hevc_mv_size(pix_mp.width,
 						pix_mp.height);
 
-	for (i = 0; i < num_buffers; ++i) {
-		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
+	return buf_size;
+}
+
+static int hantro_postproc_alloc(struct hantro_ctx *ctx, int index)
+{
+	struct hantro_dev *vpu = ctx->dev;
+	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
+	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
+
+	if (!buf_size)
+		return -EINVAL;
+
+	/*
+	 * The buffers on this queue are meant as intermediate
+	 * buffers for the decoder, so no mapping is needed.
+	 */
+	priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
+	priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
+				    GFP_KERNEL, priv->attrs);
+	if (!priv->cpu)
+		return -ENOMEM;
+	priv->size = buf_size;
+
+	return 0;
+}
+
+int hantro_postproc_init(struct hantro_ctx *ctx)
+{
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
+	unsigned int num_buffers = cap_queue->num_buffers;
+	unsigned int i;
+	int ret;
 
-		/*
-		 * The buffers on this queue are meant as intermediate
-		 * buffers for the decoder, so no mapping is needed.
-		 */
-		priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
-		priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
-					    GFP_KERNEL, priv->attrs);
-		if (!priv->cpu)
-			return -ENOMEM;
-		priv->size = buf_size;
+	if (!ctx->postproc.dec_q)
+		ctx->postproc.dec_q = kcalloc(cap_queue->max_allowed_buffers,
+					      sizeof(*ctx->postproc.dec_q),
+					      GFP_KERNEL);
+
+	if (!ctx->postproc.dec_q)
+		return -EINVAL;
+
+	for (i = 0; i < num_buffers; i++) {
+		ret = hantro_postproc_alloc(ctx, i);
+		if (ret)
+			return ret;
 	}
+
 	return 0;
 }
 
+dma_addr_t
+hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index)
+{
+	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
+	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
+	struct hantro_dev *vpu = ctx->dev;
+	int ret;
+
+	if (priv->size < buf_size && priv->cpu) {
+		/* buffer is too small, release it */
+		dma_free_attrs(vpu->dev, priv->size, priv->cpu,
+			       priv->dma, priv->attrs);
+		priv->cpu = NULL;
+	}
+
+	if (!priv->cpu) {
+		/* buffer not already allocated, try getting a new one */
+		ret = hantro_postproc_alloc(ctx, index);
+		if (ret)
+			return 0;
+	}
+
+	if (!priv->cpu)
+		return 0;
+
+	return priv->dma;
+}
+
 static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
 {
 	struct hantro_dev *vpu = ctx->dev;
diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 61cfaaf4e927..898e8763d63a 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -897,7 +897,7 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
 		}
 
 		if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) {
-			ret = hantro_postproc_alloc(ctx);
+			ret = hantro_postproc_init(ctx);
 			if (ret)
 				goto err_codec_exit;
 		}
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 04/10] media: verisilicon: Refactor postprocessor to store more buffers
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Since vb2 queue can store than VB2_MAX_FRAME buffers postprocessor
buffer storage must be capable to store more buffers too.
Change static dec_q array to allocated array to be capable to store
up to queue 'max_allowed_buffers'.
Keep allocating queue 'num_buffers' at queue setup time but also allows
to allocate postprocessors buffers on the fly.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 drivers/media/platform/verisilicon/hantro.h   |   7 +-
 .../media/platform/verisilicon/hantro_drv.c   |   4 +-
 .../media/platform/verisilicon/hantro_hw.h    |   2 +-
 .../platform/verisilicon/hantro_postproc.c    | 103 ++++++++++++++----
 .../media/platform/verisilicon/hantro_v4l2.c  |   2 +-
 5 files changed, 93 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
index 2989ebc631cc..c8a3cf10cc64 100644
--- a/drivers/media/platform/verisilicon/hantro.h
+++ b/drivers/media/platform/verisilicon/hantro.h
@@ -461,11 +461,14 @@ hantro_get_dst_buf(struct hantro_ctx *ctx)
 bool hantro_needs_postproc(const struct hantro_ctx *ctx,
 			   const struct hantro_fmt *fmt);
 
+dma_addr_t
+hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index);
+
 static inline dma_addr_t
 hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
 {
 	if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
-		return ctx->postproc.dec_q[vb->index].dma;
+		return hantro_postproc_get_dec_buf_addr(ctx, vb->index);
 	return vb2_dma_contig_plane_dma_addr(vb, 0);
 }
 
@@ -477,8 +480,8 @@ vb2_to_hantro_decoded_buf(struct vb2_buffer *buf)
 
 void hantro_postproc_disable(struct hantro_ctx *ctx);
 void hantro_postproc_enable(struct hantro_ctx *ctx);
+int hantro_postproc_init(struct hantro_ctx *ctx);
 void hantro_postproc_free(struct hantro_ctx *ctx);
-int hantro_postproc_alloc(struct hantro_ctx *ctx);
 int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
 				   struct v4l2_frmsizeenum *fsize);
 
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 09c74a573ddb..d908559817ce 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -234,8 +234,10 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
 	 * The Kernel needs access to the JPEG destination buffer for the
 	 * JPEG encoder to fill in the JPEG headers.
 	 */
-	if (!ctx->is_encoder)
+	if (!ctx->is_encoder) {
 		dst_vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
+		dst_vq->max_allowed_buffers = 64;
+	}
 
 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
index e83f0c523a30..6fd6c9d53cec 100644
--- a/drivers/media/platform/verisilicon/hantro_hw.h
+++ b/drivers/media/platform/verisilicon/hantro_hw.h
@@ -253,7 +253,7 @@ struct hantro_vp9_dec_hw_ctx {
  * @dec_q:		References buffers, in decoder format.
  */
 struct hantro_postproc_ctx {
-	struct hantro_aux_buf dec_q[VB2_MAX_FRAME];
+	struct hantro_aux_buf *dec_q;
 };
 
 /**
diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
index 6437423ccf3a..9dfe3141a398 100644
--- a/drivers/media/platform/verisilicon/hantro_postproc.c
+++ b/drivers/media/platform/verisilicon/hantro_postproc.c
@@ -173,9 +173,11 @@ static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx,
 void hantro_postproc_free(struct hantro_ctx *ctx)
 {
 	struct hantro_dev *vpu = ctx->dev;
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_queue *queue = &m2m_ctx->cap_q_ctx.q;
 	unsigned int i;
 
-	for (i = 0; i < VB2_MAX_FRAME; ++i) {
+	for (i = 0; i < queue->max_allowed_buffers; ++i) {
 		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
 
 		if (priv->cpu) {
@@ -184,22 +186,21 @@ void hantro_postproc_free(struct hantro_ctx *ctx)
 			priv->cpu = NULL;
 		}
 	}
+	kfree(ctx->postproc.dec_q);
+	ctx->postproc.dec_q = NULL;
 }
 
-int hantro_postproc_alloc(struct hantro_ctx *ctx)
+static unsigned int hantro_postproc_buffer_size(struct hantro_ctx *ctx)
 {
-	struct hantro_dev *vpu = ctx->dev;
-	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
-	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
-	unsigned int num_buffers = cap_queue->num_buffers;
 	struct v4l2_pix_format_mplane pix_mp;
 	const struct hantro_fmt *fmt;
-	unsigned int i, buf_size;
+	unsigned int buf_size;
 
 	/* this should always pick native format */
 	fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth);
 	if (!fmt)
-		return -EINVAL;
+		return 0;
+
 	v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width,
 			    ctx->src_fmt.height);
 
@@ -214,23 +215,85 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
 		buf_size += hantro_hevc_mv_size(pix_mp.width,
 						pix_mp.height);
 
-	for (i = 0; i < num_buffers; ++i) {
-		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
+	return buf_size;
+}
+
+static int hantro_postproc_alloc(struct hantro_ctx *ctx, int index)
+{
+	struct hantro_dev *vpu = ctx->dev;
+	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
+	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
+
+	if (!buf_size)
+		return -EINVAL;
+
+	/*
+	 * The buffers on this queue are meant as intermediate
+	 * buffers for the decoder, so no mapping is needed.
+	 */
+	priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
+	priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
+				    GFP_KERNEL, priv->attrs);
+	if (!priv->cpu)
+		return -ENOMEM;
+	priv->size = buf_size;
+
+	return 0;
+}
+
+int hantro_postproc_init(struct hantro_ctx *ctx)
+{
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
+	unsigned int num_buffers = cap_queue->num_buffers;
+	unsigned int i;
+	int ret;
 
-		/*
-		 * The buffers on this queue are meant as intermediate
-		 * buffers for the decoder, so no mapping is needed.
-		 */
-		priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
-		priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
-					    GFP_KERNEL, priv->attrs);
-		if (!priv->cpu)
-			return -ENOMEM;
-		priv->size = buf_size;
+	if (!ctx->postproc.dec_q)
+		ctx->postproc.dec_q = kcalloc(cap_queue->max_allowed_buffers,
+					      sizeof(*ctx->postproc.dec_q),
+					      GFP_KERNEL);
+
+	if (!ctx->postproc.dec_q)
+		return -EINVAL;
+
+	for (i = 0; i < num_buffers; i++) {
+		ret = hantro_postproc_alloc(ctx, i);
+		if (ret)
+			return ret;
 	}
+
 	return 0;
 }
 
+dma_addr_t
+hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index)
+{
+	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
+	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
+	struct hantro_dev *vpu = ctx->dev;
+	int ret;
+
+	if (priv->size < buf_size && priv->cpu) {
+		/* buffer is too small, release it */
+		dma_free_attrs(vpu->dev, priv->size, priv->cpu,
+			       priv->dma, priv->attrs);
+		priv->cpu = NULL;
+	}
+
+	if (!priv->cpu) {
+		/* buffer not already allocated, try getting a new one */
+		ret = hantro_postproc_alloc(ctx, index);
+		if (ret)
+			return 0;
+	}
+
+	if (!priv->cpu)
+		return 0;
+
+	return priv->dma;
+}
+
 static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
 {
 	struct hantro_dev *vpu = ctx->dev;
diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 61cfaaf4e927..898e8763d63a 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -897,7 +897,7 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
 		}
 
 		if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) {
-			ret = hantro_postproc_alloc(ctx);
+			ret = hantro_postproc_init(ctx);
 			if (ret)
 				goto err_codec_exit;
 		}
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Store computed values of chroma and motion vectors offset because
they depends on width and height values which change if the resolution
change.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 drivers/media/platform/verisilicon/hantro.h            | 2 ++
 drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
index c8a3cf10cc64..53be00142473 100644
--- a/drivers/media/platform/verisilicon/hantro.h
+++ b/drivers/media/platform/verisilicon/hantro.h
@@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
 	/* Info needed when the decoded frame serves as a reference frame. */
 	unsigned short width;
 	unsigned short height;
+	size_t chroma_offset;
+	size_t mv_offset;
 	u32 bit_depth : 4;
 };
 
diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
index 6fc4b555517f..6db1c32fce4d 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
@@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
 
 	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
 	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
+	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
 
 	mv_addr = luma_addr + mv_offset(ctx, dec_params);
 	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
+	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
 }
 
 struct hantro_vp9_ref_reg {
@@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
 	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
 	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
 
-	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
+	chroma_addr = luma_addr + buf->vp9.chroma_offset;
 	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
 }
 
@@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
 	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
 
 	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
-		  mv_offset(ctx, dec_params);
+		  mv_ref->vp9.mv_offset;
 	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
 
 	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Store computed values of chroma and motion vectors offset because
they depends on width and height values which change if the resolution
change.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 drivers/media/platform/verisilicon/hantro.h            | 2 ++
 drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
index c8a3cf10cc64..53be00142473 100644
--- a/drivers/media/platform/verisilicon/hantro.h
+++ b/drivers/media/platform/verisilicon/hantro.h
@@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
 	/* Info needed when the decoded frame serves as a reference frame. */
 	unsigned short width;
 	unsigned short height;
+	size_t chroma_offset;
+	size_t mv_offset;
 	u32 bit_depth : 4;
 };
 
diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
index 6fc4b555517f..6db1c32fce4d 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
@@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
 
 	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
 	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
+	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
 
 	mv_addr = luma_addr + mv_offset(ctx, dec_params);
 	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
+	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
 }
 
 struct hantro_vp9_ref_reg {
@@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
 	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
 	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
 
-	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
+	chroma_addr = luma_addr + buf->vp9.chroma_offset;
 	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
 }
 
@@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
 	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
 
 	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
-		  mv_offset(ctx, dec_params);
+		  mv_ref->vp9.mv_offset;
 	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
 
 	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Store computed values of chroma and motion vectors offset because
they depends on width and height values which change if the resolution
change.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 drivers/media/platform/verisilicon/hantro.h            | 2 ++
 drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
index c8a3cf10cc64..53be00142473 100644
--- a/drivers/media/platform/verisilicon/hantro.h
+++ b/drivers/media/platform/verisilicon/hantro.h
@@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
 	/* Info needed when the decoded frame serves as a reference frame. */
 	unsigned short width;
 	unsigned short height;
+	size_t chroma_offset;
+	size_t mv_offset;
 	u32 bit_depth : 4;
 };
 
diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
index 6fc4b555517f..6db1c32fce4d 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
@@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
 
 	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
 	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
+	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
 
 	mv_addr = luma_addr + mv_offset(ctx, dec_params);
 	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
+	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
 }
 
 struct hantro_vp9_ref_reg {
@@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
 	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
 	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
 
-	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
+	chroma_addr = luma_addr + buf->vp9.chroma_offset;
 	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
 }
 
@@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
 	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
 
 	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
-		  mv_offset(ctx, dec_params);
+		  mv_ref->vp9.mv_offset;
 	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
 
 	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 06/10] media: verisilicon: vp9: Use destination buffer height to compute chroma offset
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Source and destination buffer height may not be the same because
alignment constraint are different.
Use destination height to compute chroma offset because we target
this buffer as hardware output.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Fixes: e2da465455ce ("media: hantro: Support VP9 on the G2 core")
---
version 4:
- Add Fixes tag
 drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
index 6db1c32fce4d..1f3f5e7ce978 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
@@ -93,9 +93,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_
 static size_t chroma_offset(const struct hantro_ctx *ctx,
 			    const struct v4l2_ctrl_vp9_frame *dec_params)
 {
-	int bytes_per_pixel = dec_params->bit_depth == 8 ? 1 : 2;
-
-	return ctx->src_fmt.width * ctx->src_fmt.height * bytes_per_pixel;
+	return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth / 8;
 }
 
 static size_t mv_offset(const struct hantro_ctx *ctx,
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 06/10] media: verisilicon: vp9: Use destination buffer height to compute chroma offset
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Source and destination buffer height may not be the same because
alignment constraint are different.
Use destination height to compute chroma offset because we target
this buffer as hardware output.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Fixes: e2da465455ce ("media: hantro: Support VP9 on the G2 core")
---
version 4:
- Add Fixes tag
 drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
index 6db1c32fce4d..1f3f5e7ce978 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
@@ -93,9 +93,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_
 static size_t chroma_offset(const struct hantro_ctx *ctx,
 			    const struct v4l2_ctrl_vp9_frame *dec_params)
 {
-	int bytes_per_pixel = dec_params->bit_depth == 8 ? 1 : 2;
-
-	return ctx->src_fmt.width * ctx->src_fmt.height * bytes_per_pixel;
+	return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth / 8;
 }
 
 static size_t mv_offset(const struct hantro_ctx *ctx,
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 06/10] media: verisilicon: vp9: Use destination buffer height to compute chroma offset
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Source and destination buffer height may not be the same because
alignment constraint are different.
Use destination height to compute chroma offset because we target
this buffer as hardware output.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Fixes: e2da465455ce ("media: hantro: Support VP9 on the G2 core")
---
version 4:
- Add Fixes tag
 drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
index 6db1c32fce4d..1f3f5e7ce978 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
@@ -93,9 +93,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_
 static size_t chroma_offset(const struct hantro_ctx *ctx,
 			    const struct v4l2_ctrl_vp9_frame *dec_params)
 {
-	int bytes_per_pixel = dec_params->bit_depth == 8 ? 1 : 2;
-
-	return ctx->src_fmt.width * ctx->src_fmt.height * bytes_per_pixel;
+	return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth / 8;
 }
 
 static size_t mv_offset(const struct hantro_ctx *ctx,
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 07/10] media: verisilicon: postproc: Fix down scale test
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Do not allow down scaling if the source buffer resolution is
smaller  than destination one.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Fixes: fbb6c848dd89 ("media: destage Hantro VPU driver")
---
version 4:
- Add Fixes tag

 drivers/media/platform/verisilicon/hantro_postproc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
index 9dfe3141a398..38e812089514 100644
--- a/drivers/media/platform/verisilicon/hantro_postproc.c
+++ b/drivers/media/platform/verisilicon/hantro_postproc.c
@@ -103,7 +103,7 @@ static void hantro_postproc_g1_enable(struct hantro_ctx *ctx)
 
 static int down_scale_factor(struct hantro_ctx *ctx)
 {
-	if (ctx->src_fmt.width == ctx->dst_fmt.width)
+	if (ctx->src_fmt.width <= ctx->dst_fmt.width)
 		return 0;
 
 	return DIV_ROUND_CLOSEST(ctx->src_fmt.width, ctx->dst_fmt.width);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 07/10] media: verisilicon: postproc: Fix down scale test
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Do not allow down scaling if the source buffer resolution is
smaller  than destination one.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Fixes: fbb6c848dd89 ("media: destage Hantro VPU driver")
---
version 4:
- Add Fixes tag

 drivers/media/platform/verisilicon/hantro_postproc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
index 9dfe3141a398..38e812089514 100644
--- a/drivers/media/platform/verisilicon/hantro_postproc.c
+++ b/drivers/media/platform/verisilicon/hantro_postproc.c
@@ -103,7 +103,7 @@ static void hantro_postproc_g1_enable(struct hantro_ctx *ctx)
 
 static int down_scale_factor(struct hantro_ctx *ctx)
 {
-	if (ctx->src_fmt.width == ctx->dst_fmt.width)
+	if (ctx->src_fmt.width <= ctx->dst_fmt.width)
 		return 0;
 
 	return DIV_ROUND_CLOSEST(ctx->src_fmt.width, ctx->dst_fmt.width);
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 07/10] media: verisilicon: postproc: Fix down scale test
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Do not allow down scaling if the source buffer resolution is
smaller  than destination one.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Fixes: fbb6c848dd89 ("media: destage Hantro VPU driver")
---
version 4:
- Add Fixes tag

 drivers/media/platform/verisilicon/hantro_postproc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
index 9dfe3141a398..38e812089514 100644
--- a/drivers/media/platform/verisilicon/hantro_postproc.c
+++ b/drivers/media/platform/verisilicon/hantro_postproc.c
@@ -103,7 +103,7 @@ static void hantro_postproc_g1_enable(struct hantro_ctx *ctx)
 
 static int down_scale_factor(struct hantro_ctx *ctx)
 {
-	if (ctx->src_fmt.width == ctx->dst_fmt.width)
+	if (ctx->src_fmt.width <= ctx->dst_fmt.width)
 		return 0;
 
 	return DIV_ROUND_CLOSEST(ctx->src_fmt.width, ctx->dst_fmt.width);
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 08/10] media: verisilicon: vp9: Allow to change resolution while streaming
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Remove all checks that prohibit to set a new format while streaming.
This allow to change dynamically the resolution if the pixel format
remains the same.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/platform/verisilicon/hantro_v4l2.c  | 24 +++----------------
 1 file changed, 3 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 898e8763d63a..08ec5e9cc739 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -480,25 +480,14 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
 		return ret;
 
 	if (!ctx->is_encoder) {
-		struct vb2_queue *peer_vq;
-
 		/*
 		 * In order to support dynamic resolution change,
 		 * the decoder admits a resolution change, as long
-		 * as the pixelformat remains. Can't be done if streaming.
-		 */
-		if (vb2_is_streaming(vq) || (vb2_is_busy(vq) &&
-		    pix_mp->pixelformat != ctx->src_fmt.pixelformat))
-			return -EBUSY;
-		/*
-		 * Since format change on the OUTPUT queue will reset
-		 * the CAPTURE queue, we can't allow doing so
-		 * when the CAPTURE queue has buffers allocated.
+		 * as the pixelformat remains.
 		 */
-		peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-					  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-		if (vb2_is_busy(peer_vq))
+		if (vb2_is_streaming(vq) && pix_mp->pixelformat != ctx->src_fmt.pixelformat) {
 			return -EBUSY;
+		}
 	} else {
 		/*
 		 * The encoder doesn't admit a format change if
@@ -541,15 +530,8 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
 static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
 			      struct v4l2_pix_format_mplane *pix_mp)
 {
-	struct vb2_queue *vq;
 	int ret;
 
-	/* Change not allowed if queue is busy. */
-	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-			     V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-	if (vb2_is_busy(vq))
-		return -EBUSY;
-
 	if (ctx->is_encoder) {
 		struct vb2_queue *peer_vq;
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 08/10] media: verisilicon: vp9: Allow to change resolution while streaming
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Remove all checks that prohibit to set a new format while streaming.
This allow to change dynamically the resolution if the pixel format
remains the same.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/platform/verisilicon/hantro_v4l2.c  | 24 +++----------------
 1 file changed, 3 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 898e8763d63a..08ec5e9cc739 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -480,25 +480,14 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
 		return ret;
 
 	if (!ctx->is_encoder) {
-		struct vb2_queue *peer_vq;
-
 		/*
 		 * In order to support dynamic resolution change,
 		 * the decoder admits a resolution change, as long
-		 * as the pixelformat remains. Can't be done if streaming.
-		 */
-		if (vb2_is_streaming(vq) || (vb2_is_busy(vq) &&
-		    pix_mp->pixelformat != ctx->src_fmt.pixelformat))
-			return -EBUSY;
-		/*
-		 * Since format change on the OUTPUT queue will reset
-		 * the CAPTURE queue, we can't allow doing so
-		 * when the CAPTURE queue has buffers allocated.
+		 * as the pixelformat remains.
 		 */
-		peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-					  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-		if (vb2_is_busy(peer_vq))
+		if (vb2_is_streaming(vq) && pix_mp->pixelformat != ctx->src_fmt.pixelformat) {
 			return -EBUSY;
+		}
 	} else {
 		/*
 		 * The encoder doesn't admit a format change if
@@ -541,15 +530,8 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
 static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
 			      struct v4l2_pix_format_mplane *pix_mp)
 {
-	struct vb2_queue *vq;
 	int ret;
 
-	/* Change not allowed if queue is busy. */
-	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-			     V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-	if (vb2_is_busy(vq))
-		return -EBUSY;
-
 	if (ctx->is_encoder) {
 		struct vb2_queue *peer_vq;
 
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 08/10] media: verisilicon: vp9: Allow to change resolution while streaming
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Remove all checks that prohibit to set a new format while streaming.
This allow to change dynamically the resolution if the pixel format
remains the same.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/platform/verisilicon/hantro_v4l2.c  | 24 +++----------------
 1 file changed, 3 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 898e8763d63a..08ec5e9cc739 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -480,25 +480,14 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
 		return ret;
 
 	if (!ctx->is_encoder) {
-		struct vb2_queue *peer_vq;
-
 		/*
 		 * In order to support dynamic resolution change,
 		 * the decoder admits a resolution change, as long
-		 * as the pixelformat remains. Can't be done if streaming.
-		 */
-		if (vb2_is_streaming(vq) || (vb2_is_busy(vq) &&
-		    pix_mp->pixelformat != ctx->src_fmt.pixelformat))
-			return -EBUSY;
-		/*
-		 * Since format change on the OUTPUT queue will reset
-		 * the CAPTURE queue, we can't allow doing so
-		 * when the CAPTURE queue has buffers allocated.
+		 * as the pixelformat remains.
 		 */
-		peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-					  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-		if (vb2_is_busy(peer_vq))
+		if (vb2_is_streaming(vq) && pix_mp->pixelformat != ctx->src_fmt.pixelformat) {
 			return -EBUSY;
+		}
 	} else {
 		/*
 		 * The encoder doesn't admit a format change if
@@ -541,15 +530,8 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
 static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
 			      struct v4l2_pix_format_mplane *pix_mp)
 {
-	struct vb2_queue *vq;
 	int ret;
 
-	/* Change not allowed if queue is busy. */
-	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-			     V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
-	if (vb2_is_busy(vq))
-		return -EBUSY;
-
 	if (ctx->is_encoder) {
 		struct vb2_queue *peer_vq;
 
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 09/10] media: v4l2: Add DELETE_BUFS ioctl
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

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

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
version 4:
- Change ioctl to support range of buffers to be delete.
  Add a new structure for this ioctl.
 .../userspace-api/media/v4l/user-func.rst     |  1 +
 .../media/v4l/vidioc-delete-bufs.rst          | 73 +++++++++++++++++++
 .../media/common/videobuf2/videobuf2-core.c   | 34 +++++++++
 .../media/common/videobuf2/videobuf2-v4l2.c   | 16 ++++
 drivers/media/v4l2-core/v4l2-dev.c            |  1 +
 drivers/media/v4l2-core/v4l2-ioctl.c          | 17 +++++
 include/media/v4l2-ioctl.h                    |  4 +
 include/media/videobuf2-core.h                |  9 +++
 include/media/videobuf2-v4l2.h                | 11 +++
 include/uapi/linux/videodev2.h                | 17 +++++
 10 files changed, 183 insertions(+)
 create mode 100644 Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst

diff --git a/Documentation/userspace-api/media/v4l/user-func.rst b/Documentation/userspace-api/media/v4l/user-func.rst
index 15ff0bf7bbe6..3fd567695477 100644
--- a/Documentation/userspace-api/media/v4l/user-func.rst
+++ b/Documentation/userspace-api/media/v4l/user-func.rst
@@ -17,6 +17,7 @@ Function Reference
     vidioc-dbg-g-chip-info
     vidioc-dbg-g-register
     vidioc-decoder-cmd
+    vidioc-delete-bufs
     vidioc-dqevent
     vidioc-dv-timings-cap
     vidioc-encoder-cmd
diff --git a/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst b/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst
new file mode 100644
index 000000000000..a55fe6331fc8
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst
@@ -0,0 +1,73 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: V4L
+
+.. _VIDIOC_DELETE_BUFS:
+
+************************
+ioctl VIDIOC_DELETE_BUFS
+************************
+
+Name
+====
+
+VIDIOC_DELETE_BUFS - Deletes buffers from a queue
+
+Synopsis
+========
+
+.. c:macro:: VIDIOC_DELETE_BUFs
+
+``int ioctl(int fd, VIDIOC_DELETE_BUFs, struct v4l2_delete_buffers *argp)``
+
+Arguments
+=========
+
+``fd``
+    File descriptor returned by :c:func:`open()`.
+
+``argp``
+    Pointer to struct :c:type:`v4l2_delete_buffers`.
+
+Description
+===========
+
+Applications can optionally call the :ref:`VIDIOC_DELETE_BUFS` ioctl to
+delete buffers from a queue.
+
+.. c:type:: v4l2_delete_buffers
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.5cm}|
+
+.. flat-table:: struct v4l2_delete_buffers
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``index``
+      - The starting buffer index to delete.
+    * - __u32
+      - ``count``
+      - The number of buffers to be deleted.
+    * - __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.
+
+EBUSY
+    File I/O is in progress.
+
+EINVAL
+    The buffer ``index`` doesn't exist in the queue.
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 70e36389b704..3d915b4c33b2 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1634,6 +1634,40 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 }
 EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
+int vb2_core_delete_buf(struct vb2_queue *q, unsigned int index)
+{
+	struct vb2_buffer *vb;
+
+	vb = vb2_get_buffer(q, index);
+	if (!vb) {
+		dprintk(q, 1, "invalid buffer index %d\n", index);
+		return -EINVAL;
+	}
+
+	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+		dprintk(q, 1, "can't delete non dequeued buffer index %d\n", index);
+		return -EINVAL;
+	}
+
+	if (vb->planes[0].mem_priv)
+		call_void_vb_qop(vb, buf_cleanup, vb);
+
+	/* Free MMAP buffers or release USERPTR buffers */
+	if (q->memory == VB2_MEMORY_MMAP)
+		__vb2_buf_mem_free(vb);
+	else if (q->memory == VB2_MEMORY_DMABUF)
+		__vb2_buf_dmabuf_put(vb);
+	else
+		__vb2_buf_userptr_put(vb);
+
+	vb2_queue_remove_buffer(q, vb);
+	kfree(vb);
+
+	dprintk(q, 2, "buffer %d deleted\n", index);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_core_delete_buf);
+
 /*
  * vb2_start_streaming() - Attempt to start streaming.
  * @q:		videobuf2 queue
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 724135d41f7f..ffe6b66a27f1 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -751,6 +751,22 @@ int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
 }
 EXPORT_SYMBOL_GPL(vb2_prepare_buf);
 
+int vb2_delete_bufs(struct vb2_queue *q, struct v4l2_delete_buffers *d)
+{
+	unsigned int index;
+	int ret = 0;
+
+	for (index = d->index; index < d->index + d->count; index++) {
+		ret = vb2_core_delete_buf(q, index);
+		if (ret)
+			break;
+	}
+
+	d->index = index;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_delete_bufs);
+
 int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
 {
 	unsigned requested_planes = 1;
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index f81279492682..215654fd6581 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -720,6 +720,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
 		SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
 		SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
 		SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
+		SET_VALID_IOCTL(ops, VIDIOC_DELETE_BUFS, vidioc_delete_bufs);
 	}
 
 	if (is_vid || is_vbi || is_meta) {
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index a858acea6547..8246922dff6d 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -489,6 +489,13 @@ static void v4l_print_create_buffers(const void *arg, bool write_only)
 	v4l_print_format(&p->format, write_only);
 }
 
+static void v4l_print_delete_buffers(const void *arg, bool write_only)
+{
+	const struct v4l2_delete_buffers *p = arg;
+
+	pr_cont("index=%d, count=%d\n", p->index, p->count);
+}
+
 static void v4l_print_streamparm(const void *arg, bool write_only)
 {
 	const struct v4l2_streamparm *p = arg;
@@ -2156,6 +2163,15 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
 	return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
 }
 
+static int v4l_delete_bufs(const struct v4l2_ioctl_ops *ops,
+			   struct file *file, void *fh, void *arg)
+{
+	struct v4l2_delete_buffers *delete = arg;
+	int ret = check_fmt(file, delete->type);
+
+	return ret ? ret : ops->vidioc_delete_bufs(file, fh, delete);
+}
+
 static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -2905,6 +2921,7 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
 	IOCTL_INFO(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
 	IOCTL_INFO(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
+	IOCTL_INFO(VIDIOC_DELETE_BUFS, v4l_delete_bufs, v4l_print_delete_buffers, INFO_FL_QUEUE),
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index edb733f21604..55afbde54211 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -163,6 +163,8 @@ struct v4l2_fh;
  *	:ref:`VIDIOC_CREATE_BUFS <vidioc_create_bufs>` ioctl
  * @vidioc_prepare_buf: pointer to the function that implements
  *	:ref:`VIDIOC_PREPARE_BUF <vidioc_prepare_buf>` ioctl
+ * @vidioc_delete_bufs: pointer to the function that implements
+ *	:ref:`VIDIOC_DELETE_BUFS <vidioc_delete_bufs>` ioctl
  * @vidioc_overlay: pointer to the function that implements
  *	:ref:`VIDIOC_OVERLAY <vidioc_overlay>` ioctl
  * @vidioc_g_fbuf: pointer to the function that implements
@@ -422,6 +424,8 @@ struct v4l2_ioctl_ops {
 				  struct v4l2_create_buffers *b);
 	int (*vidioc_prepare_buf)(struct file *file, void *fh,
 				  struct v4l2_buffer *b);
+	int (*vidioc_delete_bufs)(struct file *file, void *fh,
+				  struct v4l2_delete_buffers *d);
 
 	int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i);
 	int (*vidioc_g_fbuf)(struct file *file, void *fh,
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ee9161b9fd64..c9ecc4214982 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -843,6 +843,15 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
  */
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
 
+/**
+ * vb2_core_delete_buf() -
+ * @q: pointer to &struct vb2_queue with videobuf2 queue.
+ * @index:	id number of the buffer.
+ *
+ *  Return: returns zero on success; an error code otherwise.
+ */
+int vb2_core_delete_buf(struct vb2_queue *q, unsigned int index);
+
 /**
  * vb2_core_qbuf() - Queue a buffer from userspace
  *
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 5a845887850b..2ef68fdf388f 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -118,6 +118,17 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
  */
 int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
 		    struct v4l2_buffer *b);
+/**
+ * vb2_delete_bufs() - Delete buffers from the queue
+ *
+ * @q:		pointer to &struct vb2_queue with videobuf2 queue.
+ * @d:		delete parameter, passed from userspace to
+ *		&v4l2_ioctl_ops->vidioc_delete_bufs handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from &v4l2_ioctl_ops->vidioc_delete_bufs handler in driver.
+ */
+int vb2_delete_bufs(struct vb2_queue *q, struct v4l2_delete_buffers *d);
 
 /**
  * vb2_qbuf() - Queue a buffer from userspace
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index aee75eb9e686..d32f54fdebc2 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -2603,6 +2603,21 @@ struct v4l2_create_buffers {
 	__u32			reserved[6];
 };
 
+/**
+ * struct v4l2_delete_buffers - VIDIOC_DELETE_BUFS argument
+ * @index:	the first buffer to be deleted
+ * @count:	number of buffers to delete
+ * @type:	enum v4l2_buf_type; buffer type (type == *_MPLANE for
+ *		multiplanar buffers);
+ * @reserved:	futur extensions
+ */
+struct v4l2_delete_buffers {
+	__u32			index;
+	__u32			count;
+	__u32			type;
+	__u32			reserved[13];
+};
+
 /*
  *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -2702,6 +2717,8 @@ struct v4l2_create_buffers {
 #define VIDIOC_DBG_G_CHIP_INFO  _IOWR('V', 102, struct v4l2_dbg_chip_info)
 
 #define VIDIOC_QUERY_EXT_CTRL	_IOWR('V', 103, struct v4l2_query_ext_ctrl)
+#define VIDIOC_DELETE_BUFS	_IOWR('V', 104, struct v4l2_delete_buffers)
+
 
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 09/10] media: v4l2: Add DELETE_BUFS ioctl
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

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

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
version 4:
- Change ioctl to support range of buffers to be delete.
  Add a new structure for this ioctl.
 .../userspace-api/media/v4l/user-func.rst     |  1 +
 .../media/v4l/vidioc-delete-bufs.rst          | 73 +++++++++++++++++++
 .../media/common/videobuf2/videobuf2-core.c   | 34 +++++++++
 .../media/common/videobuf2/videobuf2-v4l2.c   | 16 ++++
 drivers/media/v4l2-core/v4l2-dev.c            |  1 +
 drivers/media/v4l2-core/v4l2-ioctl.c          | 17 +++++
 include/media/v4l2-ioctl.h                    |  4 +
 include/media/videobuf2-core.h                |  9 +++
 include/media/videobuf2-v4l2.h                | 11 +++
 include/uapi/linux/videodev2.h                | 17 +++++
 10 files changed, 183 insertions(+)
 create mode 100644 Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst

diff --git a/Documentation/userspace-api/media/v4l/user-func.rst b/Documentation/userspace-api/media/v4l/user-func.rst
index 15ff0bf7bbe6..3fd567695477 100644
--- a/Documentation/userspace-api/media/v4l/user-func.rst
+++ b/Documentation/userspace-api/media/v4l/user-func.rst
@@ -17,6 +17,7 @@ Function Reference
     vidioc-dbg-g-chip-info
     vidioc-dbg-g-register
     vidioc-decoder-cmd
+    vidioc-delete-bufs
     vidioc-dqevent
     vidioc-dv-timings-cap
     vidioc-encoder-cmd
diff --git a/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst b/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst
new file mode 100644
index 000000000000..a55fe6331fc8
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst
@@ -0,0 +1,73 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: V4L
+
+.. _VIDIOC_DELETE_BUFS:
+
+************************
+ioctl VIDIOC_DELETE_BUFS
+************************
+
+Name
+====
+
+VIDIOC_DELETE_BUFS - Deletes buffers from a queue
+
+Synopsis
+========
+
+.. c:macro:: VIDIOC_DELETE_BUFs
+
+``int ioctl(int fd, VIDIOC_DELETE_BUFs, struct v4l2_delete_buffers *argp)``
+
+Arguments
+=========
+
+``fd``
+    File descriptor returned by :c:func:`open()`.
+
+``argp``
+    Pointer to struct :c:type:`v4l2_delete_buffers`.
+
+Description
+===========
+
+Applications can optionally call the :ref:`VIDIOC_DELETE_BUFS` ioctl to
+delete buffers from a queue.
+
+.. c:type:: v4l2_delete_buffers
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.5cm}|
+
+.. flat-table:: struct v4l2_delete_buffers
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``index``
+      - The starting buffer index to delete.
+    * - __u32
+      - ``count``
+      - The number of buffers to be deleted.
+    * - __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.
+
+EBUSY
+    File I/O is in progress.
+
+EINVAL
+    The buffer ``index`` doesn't exist in the queue.
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 70e36389b704..3d915b4c33b2 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1634,6 +1634,40 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 }
 EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
+int vb2_core_delete_buf(struct vb2_queue *q, unsigned int index)
+{
+	struct vb2_buffer *vb;
+
+	vb = vb2_get_buffer(q, index);
+	if (!vb) {
+		dprintk(q, 1, "invalid buffer index %d\n", index);
+		return -EINVAL;
+	}
+
+	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+		dprintk(q, 1, "can't delete non dequeued buffer index %d\n", index);
+		return -EINVAL;
+	}
+
+	if (vb->planes[0].mem_priv)
+		call_void_vb_qop(vb, buf_cleanup, vb);
+
+	/* Free MMAP buffers or release USERPTR buffers */
+	if (q->memory == VB2_MEMORY_MMAP)
+		__vb2_buf_mem_free(vb);
+	else if (q->memory == VB2_MEMORY_DMABUF)
+		__vb2_buf_dmabuf_put(vb);
+	else
+		__vb2_buf_userptr_put(vb);
+
+	vb2_queue_remove_buffer(q, vb);
+	kfree(vb);
+
+	dprintk(q, 2, "buffer %d deleted\n", index);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_core_delete_buf);
+
 /*
  * vb2_start_streaming() - Attempt to start streaming.
  * @q:		videobuf2 queue
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 724135d41f7f..ffe6b66a27f1 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -751,6 +751,22 @@ int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
 }
 EXPORT_SYMBOL_GPL(vb2_prepare_buf);
 
+int vb2_delete_bufs(struct vb2_queue *q, struct v4l2_delete_buffers *d)
+{
+	unsigned int index;
+	int ret = 0;
+
+	for (index = d->index; index < d->index + d->count; index++) {
+		ret = vb2_core_delete_buf(q, index);
+		if (ret)
+			break;
+	}
+
+	d->index = index;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_delete_bufs);
+
 int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
 {
 	unsigned requested_planes = 1;
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index f81279492682..215654fd6581 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -720,6 +720,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
 		SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
 		SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
 		SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
+		SET_VALID_IOCTL(ops, VIDIOC_DELETE_BUFS, vidioc_delete_bufs);
 	}
 
 	if (is_vid || is_vbi || is_meta) {
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index a858acea6547..8246922dff6d 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -489,6 +489,13 @@ static void v4l_print_create_buffers(const void *arg, bool write_only)
 	v4l_print_format(&p->format, write_only);
 }
 
+static void v4l_print_delete_buffers(const void *arg, bool write_only)
+{
+	const struct v4l2_delete_buffers *p = arg;
+
+	pr_cont("index=%d, count=%d\n", p->index, p->count);
+}
+
 static void v4l_print_streamparm(const void *arg, bool write_only)
 {
 	const struct v4l2_streamparm *p = arg;
@@ -2156,6 +2163,15 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
 	return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
 }
 
+static int v4l_delete_bufs(const struct v4l2_ioctl_ops *ops,
+			   struct file *file, void *fh, void *arg)
+{
+	struct v4l2_delete_buffers *delete = arg;
+	int ret = check_fmt(file, delete->type);
+
+	return ret ? ret : ops->vidioc_delete_bufs(file, fh, delete);
+}
+
 static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -2905,6 +2921,7 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
 	IOCTL_INFO(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
 	IOCTL_INFO(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
+	IOCTL_INFO(VIDIOC_DELETE_BUFS, v4l_delete_bufs, v4l_print_delete_buffers, INFO_FL_QUEUE),
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index edb733f21604..55afbde54211 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -163,6 +163,8 @@ struct v4l2_fh;
  *	:ref:`VIDIOC_CREATE_BUFS <vidioc_create_bufs>` ioctl
  * @vidioc_prepare_buf: pointer to the function that implements
  *	:ref:`VIDIOC_PREPARE_BUF <vidioc_prepare_buf>` ioctl
+ * @vidioc_delete_bufs: pointer to the function that implements
+ *	:ref:`VIDIOC_DELETE_BUFS <vidioc_delete_bufs>` ioctl
  * @vidioc_overlay: pointer to the function that implements
  *	:ref:`VIDIOC_OVERLAY <vidioc_overlay>` ioctl
  * @vidioc_g_fbuf: pointer to the function that implements
@@ -422,6 +424,8 @@ struct v4l2_ioctl_ops {
 				  struct v4l2_create_buffers *b);
 	int (*vidioc_prepare_buf)(struct file *file, void *fh,
 				  struct v4l2_buffer *b);
+	int (*vidioc_delete_bufs)(struct file *file, void *fh,
+				  struct v4l2_delete_buffers *d);
 
 	int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i);
 	int (*vidioc_g_fbuf)(struct file *file, void *fh,
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ee9161b9fd64..c9ecc4214982 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -843,6 +843,15 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
  */
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
 
+/**
+ * vb2_core_delete_buf() -
+ * @q: pointer to &struct vb2_queue with videobuf2 queue.
+ * @index:	id number of the buffer.
+ *
+ *  Return: returns zero on success; an error code otherwise.
+ */
+int vb2_core_delete_buf(struct vb2_queue *q, unsigned int index);
+
 /**
  * vb2_core_qbuf() - Queue a buffer from userspace
  *
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 5a845887850b..2ef68fdf388f 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -118,6 +118,17 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
  */
 int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
 		    struct v4l2_buffer *b);
+/**
+ * vb2_delete_bufs() - Delete buffers from the queue
+ *
+ * @q:		pointer to &struct vb2_queue with videobuf2 queue.
+ * @d:		delete parameter, passed from userspace to
+ *		&v4l2_ioctl_ops->vidioc_delete_bufs handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from &v4l2_ioctl_ops->vidioc_delete_bufs handler in driver.
+ */
+int vb2_delete_bufs(struct vb2_queue *q, struct v4l2_delete_buffers *d);
 
 /**
  * vb2_qbuf() - Queue a buffer from userspace
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index aee75eb9e686..d32f54fdebc2 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -2603,6 +2603,21 @@ struct v4l2_create_buffers {
 	__u32			reserved[6];
 };
 
+/**
+ * struct v4l2_delete_buffers - VIDIOC_DELETE_BUFS argument
+ * @index:	the first buffer to be deleted
+ * @count:	number of buffers to delete
+ * @type:	enum v4l2_buf_type; buffer type (type == *_MPLANE for
+ *		multiplanar buffers);
+ * @reserved:	futur extensions
+ */
+struct v4l2_delete_buffers {
+	__u32			index;
+	__u32			count;
+	__u32			type;
+	__u32			reserved[13];
+};
+
 /*
  *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -2702,6 +2717,8 @@ struct v4l2_create_buffers {
 #define VIDIOC_DBG_G_CHIP_INFO  _IOWR('V', 102, struct v4l2_dbg_chip_info)
 
 #define VIDIOC_QUERY_EXT_CTRL	_IOWR('V', 103, struct v4l2_query_ext_ctrl)
+#define VIDIOC_DELETE_BUFS	_IOWR('V', 104, struct v4l2_delete_buffers)
+
 
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 09/10] media: v4l2: Add DELETE_BUFS ioctl
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

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

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
version 4:
- Change ioctl to support range of buffers to be delete.
  Add a new structure for this ioctl.
 .../userspace-api/media/v4l/user-func.rst     |  1 +
 .../media/v4l/vidioc-delete-bufs.rst          | 73 +++++++++++++++++++
 .../media/common/videobuf2/videobuf2-core.c   | 34 +++++++++
 .../media/common/videobuf2/videobuf2-v4l2.c   | 16 ++++
 drivers/media/v4l2-core/v4l2-dev.c            |  1 +
 drivers/media/v4l2-core/v4l2-ioctl.c          | 17 +++++
 include/media/v4l2-ioctl.h                    |  4 +
 include/media/videobuf2-core.h                |  9 +++
 include/media/videobuf2-v4l2.h                | 11 +++
 include/uapi/linux/videodev2.h                | 17 +++++
 10 files changed, 183 insertions(+)
 create mode 100644 Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst

diff --git a/Documentation/userspace-api/media/v4l/user-func.rst b/Documentation/userspace-api/media/v4l/user-func.rst
index 15ff0bf7bbe6..3fd567695477 100644
--- a/Documentation/userspace-api/media/v4l/user-func.rst
+++ b/Documentation/userspace-api/media/v4l/user-func.rst
@@ -17,6 +17,7 @@ Function Reference
     vidioc-dbg-g-chip-info
     vidioc-dbg-g-register
     vidioc-decoder-cmd
+    vidioc-delete-bufs
     vidioc-dqevent
     vidioc-dv-timings-cap
     vidioc-encoder-cmd
diff --git a/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst b/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst
new file mode 100644
index 000000000000..a55fe6331fc8
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/vidioc-delete-bufs.rst
@@ -0,0 +1,73 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: V4L
+
+.. _VIDIOC_DELETE_BUFS:
+
+************************
+ioctl VIDIOC_DELETE_BUFS
+************************
+
+Name
+====
+
+VIDIOC_DELETE_BUFS - Deletes buffers from a queue
+
+Synopsis
+========
+
+.. c:macro:: VIDIOC_DELETE_BUFs
+
+``int ioctl(int fd, VIDIOC_DELETE_BUFs, struct v4l2_delete_buffers *argp)``
+
+Arguments
+=========
+
+``fd``
+    File descriptor returned by :c:func:`open()`.
+
+``argp``
+    Pointer to struct :c:type:`v4l2_delete_buffers`.
+
+Description
+===========
+
+Applications can optionally call the :ref:`VIDIOC_DELETE_BUFS` ioctl to
+delete buffers from a queue.
+
+.. c:type:: v4l2_delete_buffers
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.5cm}|
+
+.. flat-table:: struct v4l2_delete_buffers
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``index``
+      - The starting buffer index to delete.
+    * - __u32
+      - ``count``
+      - The number of buffers to be deleted.
+    * - __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.
+
+EBUSY
+    File I/O is in progress.
+
+EINVAL
+    The buffer ``index`` doesn't exist in the queue.
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 70e36389b704..3d915b4c33b2 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1634,6 +1634,40 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 }
 EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
+int vb2_core_delete_buf(struct vb2_queue *q, unsigned int index)
+{
+	struct vb2_buffer *vb;
+
+	vb = vb2_get_buffer(q, index);
+	if (!vb) {
+		dprintk(q, 1, "invalid buffer index %d\n", index);
+		return -EINVAL;
+	}
+
+	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+		dprintk(q, 1, "can't delete non dequeued buffer index %d\n", index);
+		return -EINVAL;
+	}
+
+	if (vb->planes[0].mem_priv)
+		call_void_vb_qop(vb, buf_cleanup, vb);
+
+	/* Free MMAP buffers or release USERPTR buffers */
+	if (q->memory == VB2_MEMORY_MMAP)
+		__vb2_buf_mem_free(vb);
+	else if (q->memory == VB2_MEMORY_DMABUF)
+		__vb2_buf_dmabuf_put(vb);
+	else
+		__vb2_buf_userptr_put(vb);
+
+	vb2_queue_remove_buffer(q, vb);
+	kfree(vb);
+
+	dprintk(q, 2, "buffer %d deleted\n", index);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_core_delete_buf);
+
 /*
  * vb2_start_streaming() - Attempt to start streaming.
  * @q:		videobuf2 queue
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 724135d41f7f..ffe6b66a27f1 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -751,6 +751,22 @@ int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
 }
 EXPORT_SYMBOL_GPL(vb2_prepare_buf);
 
+int vb2_delete_bufs(struct vb2_queue *q, struct v4l2_delete_buffers *d)
+{
+	unsigned int index;
+	int ret = 0;
+
+	for (index = d->index; index < d->index + d->count; index++) {
+		ret = vb2_core_delete_buf(q, index);
+		if (ret)
+			break;
+	}
+
+	d->index = index;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_delete_bufs);
+
 int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
 {
 	unsigned requested_planes = 1;
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index f81279492682..215654fd6581 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -720,6 +720,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
 		SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
 		SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
 		SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
+		SET_VALID_IOCTL(ops, VIDIOC_DELETE_BUFS, vidioc_delete_bufs);
 	}
 
 	if (is_vid || is_vbi || is_meta) {
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index a858acea6547..8246922dff6d 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -489,6 +489,13 @@ static void v4l_print_create_buffers(const void *arg, bool write_only)
 	v4l_print_format(&p->format, write_only);
 }
 
+static void v4l_print_delete_buffers(const void *arg, bool write_only)
+{
+	const struct v4l2_delete_buffers *p = arg;
+
+	pr_cont("index=%d, count=%d\n", p->index, p->count);
+}
+
 static void v4l_print_streamparm(const void *arg, bool write_only)
 {
 	const struct v4l2_streamparm *p = arg;
@@ -2156,6 +2163,15 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
 	return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
 }
 
+static int v4l_delete_bufs(const struct v4l2_ioctl_ops *ops,
+			   struct file *file, void *fh, void *arg)
+{
+	struct v4l2_delete_buffers *delete = arg;
+	int ret = check_fmt(file, delete->type);
+
+	return ret ? ret : ops->vidioc_delete_bufs(file, fh, delete);
+}
+
 static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -2905,6 +2921,7 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
 	IOCTL_INFO(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
 	IOCTL_INFO(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
+	IOCTL_INFO(VIDIOC_DELETE_BUFS, v4l_delete_bufs, v4l_print_delete_buffers, INFO_FL_QUEUE),
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index edb733f21604..55afbde54211 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -163,6 +163,8 @@ struct v4l2_fh;
  *	:ref:`VIDIOC_CREATE_BUFS <vidioc_create_bufs>` ioctl
  * @vidioc_prepare_buf: pointer to the function that implements
  *	:ref:`VIDIOC_PREPARE_BUF <vidioc_prepare_buf>` ioctl
+ * @vidioc_delete_bufs: pointer to the function that implements
+ *	:ref:`VIDIOC_DELETE_BUFS <vidioc_delete_bufs>` ioctl
  * @vidioc_overlay: pointer to the function that implements
  *	:ref:`VIDIOC_OVERLAY <vidioc_overlay>` ioctl
  * @vidioc_g_fbuf: pointer to the function that implements
@@ -422,6 +424,8 @@ struct v4l2_ioctl_ops {
 				  struct v4l2_create_buffers *b);
 	int (*vidioc_prepare_buf)(struct file *file, void *fh,
 				  struct v4l2_buffer *b);
+	int (*vidioc_delete_bufs)(struct file *file, void *fh,
+				  struct v4l2_delete_buffers *d);
 
 	int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i);
 	int (*vidioc_g_fbuf)(struct file *file, void *fh,
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ee9161b9fd64..c9ecc4214982 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -843,6 +843,15 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
  */
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
 
+/**
+ * vb2_core_delete_buf() -
+ * @q: pointer to &struct vb2_queue with videobuf2 queue.
+ * @index:	id number of the buffer.
+ *
+ *  Return: returns zero on success; an error code otherwise.
+ */
+int vb2_core_delete_buf(struct vb2_queue *q, unsigned int index);
+
 /**
  * vb2_core_qbuf() - Queue a buffer from userspace
  *
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 5a845887850b..2ef68fdf388f 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -118,6 +118,17 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
  */
 int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
 		    struct v4l2_buffer *b);
+/**
+ * vb2_delete_bufs() - Delete buffers from the queue
+ *
+ * @q:		pointer to &struct vb2_queue with videobuf2 queue.
+ * @d:		delete parameter, passed from userspace to
+ *		&v4l2_ioctl_ops->vidioc_delete_bufs handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from &v4l2_ioctl_ops->vidioc_delete_bufs handler in driver.
+ */
+int vb2_delete_bufs(struct vb2_queue *q, struct v4l2_delete_buffers *d);
 
 /**
  * vb2_qbuf() - Queue a buffer from userspace
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index aee75eb9e686..d32f54fdebc2 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -2603,6 +2603,21 @@ struct v4l2_create_buffers {
 	__u32			reserved[6];
 };
 
+/**
+ * struct v4l2_delete_buffers - VIDIOC_DELETE_BUFS argument
+ * @index:	the first buffer to be deleted
+ * @count:	number of buffers to delete
+ * @type:	enum v4l2_buf_type; buffer type (type == *_MPLANE for
+ *		multiplanar buffers);
+ * @reserved:	futur extensions
+ */
+struct v4l2_delete_buffers {
+	__u32			index;
+	__u32			count;
+	__u32			type;
+	__u32			reserved[13];
+};
+
 /*
  *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -2702,6 +2717,8 @@ struct v4l2_create_buffers {
 #define VIDIOC_DBG_G_CHIP_INFO  _IOWR('V', 102, struct v4l2_dbg_chip_info)
 
 #define VIDIOC_QUERY_EXT_CTRL	_IOWR('V', 103, struct v4l2_query_ext_ctrl)
+#define VIDIOC_DELETE_BUFS	_IOWR('V', 104, struct v4l2_delete_buffers)
+
 
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 10/10] media: v4l2: Add mem2mem helpers for DELETE_BUFS ioctl
  2023-07-05 12:10 ` Benjamin Gaignard
  (?)
@ 2023-07-05 12:10   ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Create v4l2-mem2mem helpers for VIDIOC_DELETE_BUFS ioctl.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/platform/verisilicon/hantro_v4l2.c  |  1 +
 drivers/media/test-drivers/vim2m.c            |  1 +
 drivers/media/v4l2-core/v4l2-mem2mem.c        | 20 +++++++++++++++++++
 include/media/v4l2-mem2mem.h                  | 12 +++++++++++
 4 files changed, 34 insertions(+)

diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 08ec5e9cc739..6b8d3908a4f7 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -720,6 +720,7 @@ const struct v4l2_ioctl_ops hantro_ioctl_ops = {
 	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
 	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
 	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+	.vidioc_delete_bufs = v4l2_m2m_ioctl_delete_bufs,
 	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
 
 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
diff --git a/drivers/media/test-drivers/vim2m.c b/drivers/media/test-drivers/vim2m.c
index 3e3b424b4860..3014b8ee13d0 100644
--- a/drivers/media/test-drivers/vim2m.c
+++ b/drivers/media/test-drivers/vim2m.c
@@ -960,6 +960,7 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
 	.vidioc_dqbuf		= v4l2_m2m_ioctl_dqbuf,
 	.vidioc_prepare_buf	= v4l2_m2m_ioctl_prepare_buf,
 	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_delete_buf	= v4l2_m2m_ioctl_delete_buf,
 	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
 
 	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 0cc30397fbad..d1d59943680f 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -831,6 +831,17 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
 
+int v4l2_m2m_delete_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+			 struct v4l2_delete_buffers *d)
+{
+	struct vb2_queue *vq;
+
+	vq = v4l2_m2m_get_vq(m2m_ctx, d->type);
+
+	return vb2_delete_bufs(vq, d);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_delete_bufs);
+
 int v4l2_m2m_create_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 			 struct v4l2_create_buffers *create)
 {
@@ -1377,6 +1388,15 @@ int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_create_bufs);
 
+int v4l2_m2m_ioctl_delete_bufs(struct file *file, void *priv,
+			       struct v4l2_delete_buffers *d)
+{
+	struct v4l2_fh *fh = file->private_data;
+
+	return v4l2_m2m_delete_bufs(file, fh->m2m_ctx, d);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_delete_bufs);
+
 int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv,
 				struct v4l2_buffer *buf)
 {
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index bb9de6a899e0..95b9e1be09f8 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -381,6 +381,16 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 			 struct v4l2_buffer *buf);
 
+/**
+ * v4l2_m2m_delete_bufs() - delete buffers from the queue
+ *
+ * @file: pointer to struct &file
+ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx
+ * @d: pointer to struct &v4l2_delete_buffers
+ */
+int v4l2_m2m_delete_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+			 struct v4l2_delete_buffers *d);
+
 /**
  * v4l2_m2m_create_bufs() - create a source or destination buffer, depending
  * on the type
@@ -846,6 +856,8 @@ int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
 				struct v4l2_requestbuffers *rb);
 int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh,
 				struct v4l2_create_buffers *create);
+int v4l2_m2m_ioctl_delete_bufs(struct file *file, void *priv,
+			       struct v4l2_delete_buffers *d);
 int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh,
 				struct v4l2_buffer *buf);
 int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh,
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 10/10] media: v4l2: Add mem2mem helpers for DELETE_BUFS ioctl
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Create v4l2-mem2mem helpers for VIDIOC_DELETE_BUFS ioctl.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/platform/verisilicon/hantro_v4l2.c  |  1 +
 drivers/media/test-drivers/vim2m.c            |  1 +
 drivers/media/v4l2-core/v4l2-mem2mem.c        | 20 +++++++++++++++++++
 include/media/v4l2-mem2mem.h                  | 12 +++++++++++
 4 files changed, 34 insertions(+)

diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 08ec5e9cc739..6b8d3908a4f7 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -720,6 +720,7 @@ const struct v4l2_ioctl_ops hantro_ioctl_ops = {
 	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
 	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
 	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+	.vidioc_delete_bufs = v4l2_m2m_ioctl_delete_bufs,
 	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
 
 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
diff --git a/drivers/media/test-drivers/vim2m.c b/drivers/media/test-drivers/vim2m.c
index 3e3b424b4860..3014b8ee13d0 100644
--- a/drivers/media/test-drivers/vim2m.c
+++ b/drivers/media/test-drivers/vim2m.c
@@ -960,6 +960,7 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
 	.vidioc_dqbuf		= v4l2_m2m_ioctl_dqbuf,
 	.vidioc_prepare_buf	= v4l2_m2m_ioctl_prepare_buf,
 	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_delete_buf	= v4l2_m2m_ioctl_delete_buf,
 	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
 
 	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 0cc30397fbad..d1d59943680f 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -831,6 +831,17 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
 
+int v4l2_m2m_delete_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+			 struct v4l2_delete_buffers *d)
+{
+	struct vb2_queue *vq;
+
+	vq = v4l2_m2m_get_vq(m2m_ctx, d->type);
+
+	return vb2_delete_bufs(vq, d);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_delete_bufs);
+
 int v4l2_m2m_create_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 			 struct v4l2_create_buffers *create)
 {
@@ -1377,6 +1388,15 @@ int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_create_bufs);
 
+int v4l2_m2m_ioctl_delete_bufs(struct file *file, void *priv,
+			       struct v4l2_delete_buffers *d)
+{
+	struct v4l2_fh *fh = file->private_data;
+
+	return v4l2_m2m_delete_bufs(file, fh->m2m_ctx, d);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_delete_bufs);
+
 int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv,
 				struct v4l2_buffer *buf)
 {
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index bb9de6a899e0..95b9e1be09f8 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -381,6 +381,16 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 			 struct v4l2_buffer *buf);
 
+/**
+ * v4l2_m2m_delete_bufs() - delete buffers from the queue
+ *
+ * @file: pointer to struct &file
+ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx
+ * @d: pointer to struct &v4l2_delete_buffers
+ */
+int v4l2_m2m_delete_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+			 struct v4l2_delete_buffers *d);
+
 /**
  * v4l2_m2m_create_bufs() - create a source or destination buffer, depending
  * on the type
@@ -846,6 +856,8 @@ int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
 				struct v4l2_requestbuffers *rb);
 int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh,
 				struct v4l2_create_buffers *create);
+int v4l2_m2m_ioctl_delete_bufs(struct file *file, void *priv,
+			       struct v4l2_delete_buffers *d);
 int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh,
 				struct v4l2_buffer *buf);
 int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh,
-- 
2.39.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v4 10/10] media: v4l2: Add mem2mem helpers for DELETE_BUFS ioctl
@ 2023-07-05 12:10   ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-07-05 12:10 UTC (permalink / raw)
  To: mchehab, tfiga, m.szyprowski, ming.qian, ezequiel, p.zabel,
	gregkh, hverkuil-cisco, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel,
	Benjamin Gaignard

Create v4l2-mem2mem helpers for VIDIOC_DELETE_BUFS ioctl.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 .../media/platform/verisilicon/hantro_v4l2.c  |  1 +
 drivers/media/test-drivers/vim2m.c            |  1 +
 drivers/media/v4l2-core/v4l2-mem2mem.c        | 20 +++++++++++++++++++
 include/media/v4l2-mem2mem.h                  | 12 +++++++++++
 4 files changed, 34 insertions(+)

diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 08ec5e9cc739..6b8d3908a4f7 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -720,6 +720,7 @@ const struct v4l2_ioctl_ops hantro_ioctl_ops = {
 	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
 	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
 	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+	.vidioc_delete_bufs = v4l2_m2m_ioctl_delete_bufs,
 	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
 
 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
diff --git a/drivers/media/test-drivers/vim2m.c b/drivers/media/test-drivers/vim2m.c
index 3e3b424b4860..3014b8ee13d0 100644
--- a/drivers/media/test-drivers/vim2m.c
+++ b/drivers/media/test-drivers/vim2m.c
@@ -960,6 +960,7 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
 	.vidioc_dqbuf		= v4l2_m2m_ioctl_dqbuf,
 	.vidioc_prepare_buf	= v4l2_m2m_ioctl_prepare_buf,
 	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_delete_buf	= v4l2_m2m_ioctl_delete_buf,
 	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
 
 	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 0cc30397fbad..d1d59943680f 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -831,6 +831,17 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
 
+int v4l2_m2m_delete_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+			 struct v4l2_delete_buffers *d)
+{
+	struct vb2_queue *vq;
+
+	vq = v4l2_m2m_get_vq(m2m_ctx, d->type);
+
+	return vb2_delete_bufs(vq, d);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_delete_bufs);
+
 int v4l2_m2m_create_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 			 struct v4l2_create_buffers *create)
 {
@@ -1377,6 +1388,15 @@ int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_create_bufs);
 
+int v4l2_m2m_ioctl_delete_bufs(struct file *file, void *priv,
+			       struct v4l2_delete_buffers *d)
+{
+	struct v4l2_fh *fh = file->private_data;
+
+	return v4l2_m2m_delete_bufs(file, fh->m2m_ctx, d);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_delete_bufs);
+
 int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv,
 				struct v4l2_buffer *buf)
 {
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index bb9de6a899e0..95b9e1be09f8 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -381,6 +381,16 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 			 struct v4l2_buffer *buf);
 
+/**
+ * v4l2_m2m_delete_bufs() - delete buffers from the queue
+ *
+ * @file: pointer to struct &file
+ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx
+ * @d: pointer to struct &v4l2_delete_buffers
+ */
+int v4l2_m2m_delete_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+			 struct v4l2_delete_buffers *d);
+
 /**
  * v4l2_m2m_create_bufs() - create a source or destination buffer, depending
  * on the type
@@ -846,6 +856,8 @@ int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
 				struct v4l2_requestbuffers *rb);
 int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh,
 				struct v4l2_create_buffers *create);
+int v4l2_m2m_ioctl_delete_bufs(struct file *file, void *priv,
+			       struct v4l2_delete_buffers *d);
 int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh,
 				struct v4l2_buffer *buf);
 int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh,
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
  2023-07-05 12:10   ` Benjamin Gaignard
  (?)
@ 2023-08-21 14:24     ` Hans Verkuil
  -1 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:24 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

Hi Benjamin,

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> The first step before changing how vb2 buffers are stored into queue
> is to avoid direct access to bufs arrays.
> 
> This patch adds 2 helpers functions to add and remove vb2 buffers
> from a queue. With these 2 and vb2_get_buffer(), bufs field of
> struct vb2_queue becomes like a private member of the structure.
> 
> After each call to vb2_get_buffer() we need to be sure that we get
> a valid pointer so check the return value of all of them.
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>  .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>  drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>  .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>  .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>  drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>  drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>  .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>  8 files changed, 240 insertions(+), 67 deletions(-)
> 
> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
> index cf6727d9c81f..42fd3984c2bc 100644
> --- a/drivers/media/common/videobuf2/videobuf2-core.c
> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>  	unsigned long off = 0;
>  
>  	if (vb->index) {
> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
> +		struct vb2_buffer *prev;
> +		struct vb2_plane *p;
> +
> +		prev = vb2_get_buffer(q, vb->index - 1);
> +		if (!prev) {
> +			dprintk(q, 1, "can't find the requested buffer\n");
> +			return;
> +		}
> +
> +		p = &prev->planes[prev->num_planes - 1];
>  
>  		off = PAGE_ALIGN(p->m.offset + p->length);

This does not work. Before this patch there should be a patch that changes
the way the offset is determined since it affects this functionality.

__setup_offsets() fills in the m.offset field for each plane in the buffer.
In the current code it starts with 0 for the first buffer, adds the length
for each plane to it, and for the next buffer it continues doing that. So
the offset for a plane is the total length of all preceding buffers and planes.

In addition, bit 30 of the offset field is used to signal if it is a capture
or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
define).

In addition, the offset has to be page aligned, so the lower 12 bits are 0.
That leaves only 32-1-12 = 19 bits for the offset.

Since we allow 8 planes per buffer, that means that we can't have more than
65536 buffers given a 32 bit offset.

I think the way m.offset is calculated should change drastically: it should
instead be something like this:

m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;

and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.

Parsing the offset would be much simpler as well, since you can just decode
the index and plane numbers directly rather than using the cumbersome
__find_plane_by_offset() function.

The currently mechanism will fail completely once you can delete buffers,
and this proposal will simplify and improve the code, so I think it should
be done first.

Regards,

	Hans

>  	}
> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>  		vb->skip_cache_sync_on_finish = 1;
>  }
>  
> +/**
> + * vb2_queue_add_buffer() - add a buffer to a queue
> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
> + * @index: index where add vb2_buffer in the queue
> + */
> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
> +{
> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
> +		q->bufs[index] = vb;
> +		vb->index = index;
> +		vb->vb2_queue = q;
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * vb2_queue_remove_buffer() - remove a buffer from a queue
> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
> + */
> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
> +{
> +	if (vb->index < VB2_MAX_FRAME) {
> +		q->bufs[vb->index] = NULL;
> +		vb->vb2_queue = NULL;
> +	}
> +}
> +
>  /*
>   * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>   * video buffer memory for all buffers/planes on the queue and initializes the
> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  		}
>  
>  		vb->state = VB2_BUF_STATE_DEQUEUED;
> -		vb->vb2_queue = q;
>  		vb->num_planes = num_planes;
> -		vb->index = q->num_buffers + buffer;
>  		vb->type = q->type;
>  		vb->memory = memory;
>  		init_buffer_cache_hints(q, vb);
> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  		}
>  		call_void_bufop(q, init_buffer, vb);
>  
> -		q->bufs[vb->index] = vb;
> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
> +			kfree(vb);
> +			break;
> +		}
>  
>  		/* Allocate video buffer memory for the MMAP type */
>  		if (memory == VB2_MEMORY_MMAP) {
> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  			if (ret) {
>  				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>  					buffer);
> -				q->bufs[vb->index] = NULL;
> +				vb2_queue_remove_buffer(q, vb);
>  				kfree(vb);
>  				break;
>  			}
> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  				dprintk(q, 1, "buffer %d %p initialization failed\n",
>  					buffer, vb);
>  				__vb2_buf_mem_free(vb);
> -				q->bufs[vb->index] = NULL;
> +				vb2_queue_remove_buffer(q, vb);
>  				kfree(vb);
>  				break;
>  			}
> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>  
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		vb = q->bufs[buffer];
> +		vb = vb2_get_buffer(q, buffer);
>  		if (!vb)
>  			continue;
>  
> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  	/* Call driver-provided cleanup function for each buffer, if provided */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		struct vb2_buffer *vb = q->bufs[buffer];
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>  
>  		if (vb && vb->planes[0].mem_priv)
>  			call_void_vb_qop(vb, buf_cleanup, vb);
> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  		q->cnt_unprepare_streaming = 0;
>  	}
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		struct vb2_buffer *vb = q->bufs[buffer];
> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +		bool unbalanced;
> +
> +		if (!vb)
> +			continue;
> +
> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>  
>  		if (unbalanced || debug) {
>  			pr_info("   counters for queue %p, buffer %d:%s\n",
> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  	/* Free vb2 buffers */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		kfree(q->bufs[buffer]);
> -		q->bufs[buffer] = NULL;
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
> +
> +		vb2_queue_remove_buffer(q, vb);
> +		kfree(vb);
>  	}
>  
>  	q->num_buffers -= buffers;
> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>  {
>  	unsigned int buffer;
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
> +
> +		if (vb2_buffer_in_use(q, vb))
>  			return true;
>  	}
>  	return false;
> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>  
>  void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
> +
> +	if (vb)
> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>  }
>  EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>  
> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>  	struct vb2_buffer *vb;
>  	int ret;
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
> +
>  	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>  		dprintk(q, 1, "invalid buffer state %s\n",
>  			vb2_state_name(vb->state));
> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>  		 * correctly return them to vb2.
>  		 */
>  		for (i = 0; i < q->num_buffers; ++i) {
> -			vb = q->bufs[i];
> +			vb = vb2_get_buffer(q, i);
> +
> +			if (!vb)
> +				continue;
> +
>  			if (vb->state == VB2_BUF_STATE_ACTIVE)
>  				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>  		}
> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>  		return -EIO;
>  	}
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
>  
>  	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>  	    q->requires_requests) {
> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	 * to vb2 in stop_streaming().
>  	 */
>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> -		for (i = 0; i < q->num_buffers; ++i)
> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
> +		for (i = 0; i < q->num_buffers; ++i) {
> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
> +
> +			if (!vb)
> +				continue;
> +
> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>  				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
> -					q->bufs[i]);
> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
> +					vb);
> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>  			}
> +		}
>  		/* Must be zero now */
>  		WARN_ON(atomic_read(&q->owned_by_drv_count));
>  	}
> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>  	 */
>  	for (i = 0; i < q->num_buffers; ++i) {
> -		struct vb2_buffer *vb = q->bufs[i];
> -		struct media_request *req = vb->req_obj.req;
> +		struct vb2_buffer *vb;
> +		struct media_request *req;
>  
> +		vb = vb2_get_buffer(q, i);
> +		if (!vb)
> +			continue;
> +
> +		req = vb->req_obj.req;
>  		/*
>  		 * If a request is associated with this buffer, then
>  		 * call buf_request_cancel() to give the driver to complete()
> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>  	 * return its buffer and plane numbers.
>  	 */
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		vb = q->bufs[buffer];
> +		vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
>  
>  		for (plane = 0; plane < vb->num_planes; ++plane) {
>  			if (vb->planes[plane].m.offset == off) {
> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>  		return -EINVAL;
>  	}
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
>  
>  	if (plane >= vb->num_planes) {
>  		dprintk(q, 1, "buffer plane out of range\n");
> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  	if (ret)
>  		goto unlock;
>  
> -	vb = q->bufs[buffer];
> +	vb = vb2_get_buffer(q, buffer);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
>  
>  	/*
>  	 * MMAP requires page_aligned buffers.
> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  	if (ret)
>  		goto unlock;
>  
> -	vb = q->bufs[buffer];
> +	vb = vb2_get_buffer(q, buffer);
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
>  
>  	vaddr = vb2_plane_vaddr(vb, plane);
>  	mutex_unlock(&q->mmap_lock);
> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>  static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  {
>  	struct vb2_fileio_data *fileio;
> +	struct vb2_buffer *vb;
>  	int i, ret;
>  	unsigned int count = 0;
>  
> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  	 * Check if plane_count is correct
>  	 * (multiplane buffers are not supported).
>  	 */
> -	if (q->bufs[0]->num_planes != 1) {
> +	vb = vb2_get_buffer(q, 0);
> +	if (!vb) {
> +		ret = -EBUSY;
> +		goto err_reqbufs;
> +	}
> +
> +	if (vb->num_planes != 1) {
>  		ret = -EBUSY;
>  		goto err_reqbufs;
>  	}
> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  	 * Get kernel address of each buffer.
>  	 */
>  	for (i = 0; i < q->num_buffers; i++) {
> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> +		vb = vb2_get_buffer(q, i);
> +
> +		if (!vb)
> +			continue;
> +
> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>  		if (fileio->bufs[i].vaddr == NULL) {
>  			ret = -EINVAL;
>  			goto err_reqbufs;
>  		}
> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>  	}
>  
>  	/*
> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  
>  		fileio->cur_index = index;
>  		buf = &fileio->bufs[index];
> -		b = q->bufs[index];
> +		b = vb2_get_buffer(q, index);
> +
> +		if (!b)
> +			return -EINVAL;
>  
>  		/*
>  		 * Get number of bytes filled by the driver
>  		 */
>  		buf->pos = 0;
>  		buf->queued = 0;
> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> -				 : vb2_plane_size(q->bufs[index], 0);
> +		buf->size = read ? vb2_get_plane_payload(b, 0)
> +				 : vb2_plane_size(b, 0);
>  		/* Compensate for data_offset on read in the multiplanar case. */
>  		if (is_multiplanar && read &&
>  				b->planes[0].data_offset < buf->size) {
> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  	 * Queue next buffer if required.
>  	 */
>  	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> -		struct vb2_buffer *b = q->bufs[index];
> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>  
> +		if (!b) {
> +			dprintk(q, 1, "can't find the requested buffer\n");
> +			return -EINVAL;
> +		}
>  		/*
>  		 * Check if this is the last buffer to read.
>  		 */
> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  		 */
>  		buf->pos = 0;
>  		buf->queued = 1;
> -		buf->size = vb2_plane_size(q->bufs[index], 0);
> +		buf->size = vb2_plane_size(b, 0);
>  		fileio->q_count += 1;
>  		/*
>  		 * If we are queuing up buffers for the first time, then
> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>  		 * Call vb2_dqbuf to get buffer back.
>  		 */
>  		if (prequeue) {
> -			vb = q->bufs[index++];
> +			vb = vb2_get_buffer(q, index++);
> +			if (!vb)
> +				continue;
>  			prequeue--;
>  		} else {
>  			call_void_qop(q, wait_finish, q);
> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>  			call_void_qop(q, wait_prepare, q);
>  			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>  			if (!ret)
> -				vb = q->bufs[index];
> +				vb = vb2_get_buffer(q, index);
>  		}
>  		if (ret || threadio->stop)
>  			break;
> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> index c7a54d82a55e..724135d41f7f 100644
> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>  		return -EINVAL;
>  	}
>  
> -	if (q->bufs[b->index] == NULL) {
> -		/* Should never happen */
> +	if (!vb2_get_buffer(q, b->index)) {
>  		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>  		return -EINVAL;
>  	}
> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>  		return -EINVAL;
>  	}
>  
> -	vb = q->bufs[b->index];
> +	vb = vb2_get_buffer(q, b->index);
>  	vbuf = to_vb2_v4l2_buffer(vb);
>  	ret = __verify_planes_array(vb, b);
>  	if (ret)
> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>  struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>  {
>  	unsigned int i;
> +	struct vb2_buffer *vb2;
>  
> -	for (i = 0; i < q->num_buffers; i++)
> -		if (q->bufs[i]->copied_timestamp &&
> -		    q->bufs[i]->timestamp == timestamp)
> -			return vb2_get_buffer(q, i);
> +	for (i = 0; i < q->num_buffers; i++) {
> +		vb2 = vb2_get_buffer(q, i);
> +
> +		if (!vb2)
> +			continue;
> +
> +		if (vb2->copied_timestamp &&
> +		    vb2->timestamp == timestamp)
> +			return vb2;
> +	}
>  	return NULL;
>  }
>  EXPORT_SYMBOL_GPL(vb2_find_buffer);
> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  		dprintk(q, 1, "buffer index out of range\n");
>  		return -EINVAL;
>  	}
> -	vb = q->bufs[b->index];
> +	vb = vb2_get_buffer(q, b->index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
> +
>  	ret = __verify_planes_array(vb, b);
>  	if (!ret)
>  		vb2_core_querybuf(q, b->index, b);
> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
> index 44b830ae01d8..e2c371c2fde5 100644
> --- a/drivers/media/platform/amphion/vpu_dbg.c
> +++ b/drivers/media/platform/amphion/vpu_dbg.c
> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>  
>  	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		struct vb2_buffer *vb = vq->bufs[i];
> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +		struct vb2_buffer *vb;
> +		struct vb2_v4l2_buffer *vbuf;
> +
> +		vb = vb2_get_buffer(vq, i);
> +		if (!vb)
> +			continue;
>  
>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>  			continue;
> +
> +		vbuf = to_vb2_v4l2_buffer(vb);
> +
>  		num = scnprintf(str, sizeof(str),
>  				"output [%2d] state = %10s, %8s\n",
>  				i, vb2_stat_name[vb->state],
> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>  
>  	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		struct vb2_buffer *vb = vq->bufs[i];
> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +		struct vb2_buffer *vb;
> +		struct vb2_v4l2_buffer *vbuf;
> +
> +		vb = vb2_get_buffer(vq, i);
> +		if (!vb)
> +			continue;
>  
>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>  			continue;
> +
> +		vbuf = to_vb2_v4l2_buffer(vb);
> +
>  		num = scnprintf(str, sizeof(str),
>  				"capture[%2d] state = %10s, %8s\n",
>  				i, vb2_stat_name[vb->state],
> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> index 0051f372a66c..ea37069ba355 100644
> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>  		return -EINVAL;
>  	}
>  
> -	vb = vq->bufs[buf->index];
> +	vb = vb2_get_buffer(vq, buf->index);
> +	if (!vb) {
> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
> +		return -EINVAL;
> +	}
>  	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>  	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>  
> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> index cf16cf2807f0..6532a69f1fa8 100644
> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>  
>  	/* update internal buffer's width/height */
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		if (vb == vq->bufs[i]) {
> +		if (vb == vb2_get_buffer(vq, i)) {
>  			instance->dpb[i].width = w;
>  			instance->dpb[i].height = h;
>  			break;
> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
> index 3a848ca32a0e..326be09bdb55 100644
> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>  		}
>  
>  		vb2_buf = vb2_get_buffer(vq, buf->index);
> +		if (!vb2_buf) {
> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
> +			return -EINVAL;
> +		}
>  		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>  		stream->bytesused = buf->bytesused;
>  	}
> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
> index 318d675e5668..ba20ea998d19 100644
> --- a/drivers/media/test-drivers/visl/visl-dec.c
> +++ b/drivers/media/test-drivers/visl/visl-dec.c
> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>  	for (i = 0; i < out_q->num_buffers; i++) {
>  		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>  		u32 old_len = len;
> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
> +		struct vb2_buffer *vb2;
> +		char *q_status;
> +
> +		vb2 = vb2_get_buffer(out_q, i);
> +		if (!vb2)
> +			continue;
> +
> +		q_status = visl_get_vb2_state(vb2->state);
>  
>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>  				 entry, i, q_status,
> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>  
> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>  					   &buf[len],
>  					   TPG_STR_BUF_SZ - len);
>  
> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>  	len = 0;
>  	for (i = 0; i < cap_q->num_buffers; i++) {
>  		u32 old_len = len;
> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
> +		struct vb2_buffer *vb2;
> +		char *q_status;
> +
> +		vb2 = vb2_get_buffer(cap_q, i);
> +		if (!vb2)
> +			continue;
> +
> +		q_status = visl_get_vb2_state(vb2->state);
>  
>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>  				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
> -				 cap_q->bufs[i]->index, q_status,
> -				 cap_q->bufs[i]->timestamp,
> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
> +				 vb2->index, q_status,
> +				 vb2->timestamp,
> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>  
>  		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>  		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> index 384f31fc66c5..8df301ab41ad 100644
> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>  	if (ret)
>  		return ret;
>  
> -	vb = pipe->vb_queue.bufs[buf->index];
> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>  	frame = vb_to_frame(vb);
>  
>  	buf->reserved = asd->frame_status[buf->index];


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
@ 2023-08-21 14:24     ` Hans Verkuil
  0 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:24 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

Hi Benjamin,

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> The first step before changing how vb2 buffers are stored into queue
> is to avoid direct access to bufs arrays.
> 
> This patch adds 2 helpers functions to add and remove vb2 buffers
> from a queue. With these 2 and vb2_get_buffer(), bufs field of
> struct vb2_queue becomes like a private member of the structure.
> 
> After each call to vb2_get_buffer() we need to be sure that we get
> a valid pointer so check the return value of all of them.
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>  .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>  drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>  .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>  .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>  drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>  drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>  .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>  8 files changed, 240 insertions(+), 67 deletions(-)
> 
> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
> index cf6727d9c81f..42fd3984c2bc 100644
> --- a/drivers/media/common/videobuf2/videobuf2-core.c
> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>  	unsigned long off = 0;
>  
>  	if (vb->index) {
> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
> +		struct vb2_buffer *prev;
> +		struct vb2_plane *p;
> +
> +		prev = vb2_get_buffer(q, vb->index - 1);
> +		if (!prev) {
> +			dprintk(q, 1, "can't find the requested buffer\n");
> +			return;
> +		}
> +
> +		p = &prev->planes[prev->num_planes - 1];
>  
>  		off = PAGE_ALIGN(p->m.offset + p->length);

This does not work. Before this patch there should be a patch that changes
the way the offset is determined since it affects this functionality.

__setup_offsets() fills in the m.offset field for each plane in the buffer.
In the current code it starts with 0 for the first buffer, adds the length
for each plane to it, and for the next buffer it continues doing that. So
the offset for a plane is the total length of all preceding buffers and planes.

In addition, bit 30 of the offset field is used to signal if it is a capture
or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
define).

In addition, the offset has to be page aligned, so the lower 12 bits are 0.
That leaves only 32-1-12 = 19 bits for the offset.

Since we allow 8 planes per buffer, that means that we can't have more than
65536 buffers given a 32 bit offset.

I think the way m.offset is calculated should change drastically: it should
instead be something like this:

m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;

and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.

Parsing the offset would be much simpler as well, since you can just decode
the index and plane numbers directly rather than using the cumbersome
__find_plane_by_offset() function.

The currently mechanism will fail completely once you can delete buffers,
and this proposal will simplify and improve the code, so I think it should
be done first.

Regards,

	Hans

>  	}
> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>  		vb->skip_cache_sync_on_finish = 1;
>  }
>  
> +/**
> + * vb2_queue_add_buffer() - add a buffer to a queue
> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
> + * @index: index where add vb2_buffer in the queue
> + */
> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
> +{
> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
> +		q->bufs[index] = vb;
> +		vb->index = index;
> +		vb->vb2_queue = q;
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * vb2_queue_remove_buffer() - remove a buffer from a queue
> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
> + */
> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
> +{
> +	if (vb->index < VB2_MAX_FRAME) {
> +		q->bufs[vb->index] = NULL;
> +		vb->vb2_queue = NULL;
> +	}
> +}
> +
>  /*
>   * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>   * video buffer memory for all buffers/planes on the queue and initializes the
> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  		}
>  
>  		vb->state = VB2_BUF_STATE_DEQUEUED;
> -		vb->vb2_queue = q;
>  		vb->num_planes = num_planes;
> -		vb->index = q->num_buffers + buffer;
>  		vb->type = q->type;
>  		vb->memory = memory;
>  		init_buffer_cache_hints(q, vb);
> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  		}
>  		call_void_bufop(q, init_buffer, vb);
>  
> -		q->bufs[vb->index] = vb;
> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
> +			kfree(vb);
> +			break;
> +		}
>  
>  		/* Allocate video buffer memory for the MMAP type */
>  		if (memory == VB2_MEMORY_MMAP) {
> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  			if (ret) {
>  				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>  					buffer);
> -				q->bufs[vb->index] = NULL;
> +				vb2_queue_remove_buffer(q, vb);
>  				kfree(vb);
>  				break;
>  			}
> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  				dprintk(q, 1, "buffer %d %p initialization failed\n",
>  					buffer, vb);
>  				__vb2_buf_mem_free(vb);
> -				q->bufs[vb->index] = NULL;
> +				vb2_queue_remove_buffer(q, vb);
>  				kfree(vb);
>  				break;
>  			}
> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>  
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		vb = q->bufs[buffer];
> +		vb = vb2_get_buffer(q, buffer);
>  		if (!vb)
>  			continue;
>  
> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  	/* Call driver-provided cleanup function for each buffer, if provided */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		struct vb2_buffer *vb = q->bufs[buffer];
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>  
>  		if (vb && vb->planes[0].mem_priv)
>  			call_void_vb_qop(vb, buf_cleanup, vb);
> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  		q->cnt_unprepare_streaming = 0;
>  	}
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		struct vb2_buffer *vb = q->bufs[buffer];
> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +		bool unbalanced;
> +
> +		if (!vb)
> +			continue;
> +
> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>  
>  		if (unbalanced || debug) {
>  			pr_info("   counters for queue %p, buffer %d:%s\n",
> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  	/* Free vb2 buffers */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		kfree(q->bufs[buffer]);
> -		q->bufs[buffer] = NULL;
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
> +
> +		vb2_queue_remove_buffer(q, vb);
> +		kfree(vb);
>  	}
>  
>  	q->num_buffers -= buffers;
> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>  {
>  	unsigned int buffer;
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
> +
> +		if (vb2_buffer_in_use(q, vb))
>  			return true;
>  	}
>  	return false;
> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>  
>  void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
> +
> +	if (vb)
> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>  }
>  EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>  
> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>  	struct vb2_buffer *vb;
>  	int ret;
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
> +
>  	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>  		dprintk(q, 1, "invalid buffer state %s\n",
>  			vb2_state_name(vb->state));
> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>  		 * correctly return them to vb2.
>  		 */
>  		for (i = 0; i < q->num_buffers; ++i) {
> -			vb = q->bufs[i];
> +			vb = vb2_get_buffer(q, i);
> +
> +			if (!vb)
> +				continue;
> +
>  			if (vb->state == VB2_BUF_STATE_ACTIVE)
>  				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>  		}
> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>  		return -EIO;
>  	}
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
>  
>  	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>  	    q->requires_requests) {
> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	 * to vb2 in stop_streaming().
>  	 */
>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> -		for (i = 0; i < q->num_buffers; ++i)
> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
> +		for (i = 0; i < q->num_buffers; ++i) {
> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
> +
> +			if (!vb)
> +				continue;
> +
> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>  				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
> -					q->bufs[i]);
> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
> +					vb);
> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>  			}
> +		}
>  		/* Must be zero now */
>  		WARN_ON(atomic_read(&q->owned_by_drv_count));
>  	}
> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>  	 */
>  	for (i = 0; i < q->num_buffers; ++i) {
> -		struct vb2_buffer *vb = q->bufs[i];
> -		struct media_request *req = vb->req_obj.req;
> +		struct vb2_buffer *vb;
> +		struct media_request *req;
>  
> +		vb = vb2_get_buffer(q, i);
> +		if (!vb)
> +			continue;
> +
> +		req = vb->req_obj.req;
>  		/*
>  		 * If a request is associated with this buffer, then
>  		 * call buf_request_cancel() to give the driver to complete()
> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>  	 * return its buffer and plane numbers.
>  	 */
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		vb = q->bufs[buffer];
> +		vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
>  
>  		for (plane = 0; plane < vb->num_planes; ++plane) {
>  			if (vb->planes[plane].m.offset == off) {
> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>  		return -EINVAL;
>  	}
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
>  
>  	if (plane >= vb->num_planes) {
>  		dprintk(q, 1, "buffer plane out of range\n");
> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  	if (ret)
>  		goto unlock;
>  
> -	vb = q->bufs[buffer];
> +	vb = vb2_get_buffer(q, buffer);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
>  
>  	/*
>  	 * MMAP requires page_aligned buffers.
> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  	if (ret)
>  		goto unlock;
>  
> -	vb = q->bufs[buffer];
> +	vb = vb2_get_buffer(q, buffer);
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
>  
>  	vaddr = vb2_plane_vaddr(vb, plane);
>  	mutex_unlock(&q->mmap_lock);
> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>  static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  {
>  	struct vb2_fileio_data *fileio;
> +	struct vb2_buffer *vb;
>  	int i, ret;
>  	unsigned int count = 0;
>  
> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  	 * Check if plane_count is correct
>  	 * (multiplane buffers are not supported).
>  	 */
> -	if (q->bufs[0]->num_planes != 1) {
> +	vb = vb2_get_buffer(q, 0);
> +	if (!vb) {
> +		ret = -EBUSY;
> +		goto err_reqbufs;
> +	}
> +
> +	if (vb->num_planes != 1) {
>  		ret = -EBUSY;
>  		goto err_reqbufs;
>  	}
> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  	 * Get kernel address of each buffer.
>  	 */
>  	for (i = 0; i < q->num_buffers; i++) {
> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> +		vb = vb2_get_buffer(q, i);
> +
> +		if (!vb)
> +			continue;
> +
> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>  		if (fileio->bufs[i].vaddr == NULL) {
>  			ret = -EINVAL;
>  			goto err_reqbufs;
>  		}
> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>  	}
>  
>  	/*
> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  
>  		fileio->cur_index = index;
>  		buf = &fileio->bufs[index];
> -		b = q->bufs[index];
> +		b = vb2_get_buffer(q, index);
> +
> +		if (!b)
> +			return -EINVAL;
>  
>  		/*
>  		 * Get number of bytes filled by the driver
>  		 */
>  		buf->pos = 0;
>  		buf->queued = 0;
> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> -				 : vb2_plane_size(q->bufs[index], 0);
> +		buf->size = read ? vb2_get_plane_payload(b, 0)
> +				 : vb2_plane_size(b, 0);
>  		/* Compensate for data_offset on read in the multiplanar case. */
>  		if (is_multiplanar && read &&
>  				b->planes[0].data_offset < buf->size) {
> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  	 * Queue next buffer if required.
>  	 */
>  	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> -		struct vb2_buffer *b = q->bufs[index];
> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>  
> +		if (!b) {
> +			dprintk(q, 1, "can't find the requested buffer\n");
> +			return -EINVAL;
> +		}
>  		/*
>  		 * Check if this is the last buffer to read.
>  		 */
> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  		 */
>  		buf->pos = 0;
>  		buf->queued = 1;
> -		buf->size = vb2_plane_size(q->bufs[index], 0);
> +		buf->size = vb2_plane_size(b, 0);
>  		fileio->q_count += 1;
>  		/*
>  		 * If we are queuing up buffers for the first time, then
> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>  		 * Call vb2_dqbuf to get buffer back.
>  		 */
>  		if (prequeue) {
> -			vb = q->bufs[index++];
> +			vb = vb2_get_buffer(q, index++);
> +			if (!vb)
> +				continue;
>  			prequeue--;
>  		} else {
>  			call_void_qop(q, wait_finish, q);
> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>  			call_void_qop(q, wait_prepare, q);
>  			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>  			if (!ret)
> -				vb = q->bufs[index];
> +				vb = vb2_get_buffer(q, index);
>  		}
>  		if (ret || threadio->stop)
>  			break;
> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> index c7a54d82a55e..724135d41f7f 100644
> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>  		return -EINVAL;
>  	}
>  
> -	if (q->bufs[b->index] == NULL) {
> -		/* Should never happen */
> +	if (!vb2_get_buffer(q, b->index)) {
>  		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>  		return -EINVAL;
>  	}
> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>  		return -EINVAL;
>  	}
>  
> -	vb = q->bufs[b->index];
> +	vb = vb2_get_buffer(q, b->index);
>  	vbuf = to_vb2_v4l2_buffer(vb);
>  	ret = __verify_planes_array(vb, b);
>  	if (ret)
> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>  struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>  {
>  	unsigned int i;
> +	struct vb2_buffer *vb2;
>  
> -	for (i = 0; i < q->num_buffers; i++)
> -		if (q->bufs[i]->copied_timestamp &&
> -		    q->bufs[i]->timestamp == timestamp)
> -			return vb2_get_buffer(q, i);
> +	for (i = 0; i < q->num_buffers; i++) {
> +		vb2 = vb2_get_buffer(q, i);
> +
> +		if (!vb2)
> +			continue;
> +
> +		if (vb2->copied_timestamp &&
> +		    vb2->timestamp == timestamp)
> +			return vb2;
> +	}
>  	return NULL;
>  }
>  EXPORT_SYMBOL_GPL(vb2_find_buffer);
> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  		dprintk(q, 1, "buffer index out of range\n");
>  		return -EINVAL;
>  	}
> -	vb = q->bufs[b->index];
> +	vb = vb2_get_buffer(q, b->index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
> +
>  	ret = __verify_planes_array(vb, b);
>  	if (!ret)
>  		vb2_core_querybuf(q, b->index, b);
> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
> index 44b830ae01d8..e2c371c2fde5 100644
> --- a/drivers/media/platform/amphion/vpu_dbg.c
> +++ b/drivers/media/platform/amphion/vpu_dbg.c
> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>  
>  	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		struct vb2_buffer *vb = vq->bufs[i];
> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +		struct vb2_buffer *vb;
> +		struct vb2_v4l2_buffer *vbuf;
> +
> +		vb = vb2_get_buffer(vq, i);
> +		if (!vb)
> +			continue;
>  
>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>  			continue;
> +
> +		vbuf = to_vb2_v4l2_buffer(vb);
> +
>  		num = scnprintf(str, sizeof(str),
>  				"output [%2d] state = %10s, %8s\n",
>  				i, vb2_stat_name[vb->state],
> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>  
>  	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		struct vb2_buffer *vb = vq->bufs[i];
> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +		struct vb2_buffer *vb;
> +		struct vb2_v4l2_buffer *vbuf;
> +
> +		vb = vb2_get_buffer(vq, i);
> +		if (!vb)
> +			continue;
>  
>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>  			continue;
> +
> +		vbuf = to_vb2_v4l2_buffer(vb);
> +
>  		num = scnprintf(str, sizeof(str),
>  				"capture[%2d] state = %10s, %8s\n",
>  				i, vb2_stat_name[vb->state],
> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> index 0051f372a66c..ea37069ba355 100644
> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>  		return -EINVAL;
>  	}
>  
> -	vb = vq->bufs[buf->index];
> +	vb = vb2_get_buffer(vq, buf->index);
> +	if (!vb) {
> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
> +		return -EINVAL;
> +	}
>  	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>  	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>  
> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> index cf16cf2807f0..6532a69f1fa8 100644
> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>  
>  	/* update internal buffer's width/height */
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		if (vb == vq->bufs[i]) {
> +		if (vb == vb2_get_buffer(vq, i)) {
>  			instance->dpb[i].width = w;
>  			instance->dpb[i].height = h;
>  			break;
> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
> index 3a848ca32a0e..326be09bdb55 100644
> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>  		}
>  
>  		vb2_buf = vb2_get_buffer(vq, buf->index);
> +		if (!vb2_buf) {
> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
> +			return -EINVAL;
> +		}
>  		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>  		stream->bytesused = buf->bytesused;
>  	}
> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
> index 318d675e5668..ba20ea998d19 100644
> --- a/drivers/media/test-drivers/visl/visl-dec.c
> +++ b/drivers/media/test-drivers/visl/visl-dec.c
> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>  	for (i = 0; i < out_q->num_buffers; i++) {
>  		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>  		u32 old_len = len;
> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
> +		struct vb2_buffer *vb2;
> +		char *q_status;
> +
> +		vb2 = vb2_get_buffer(out_q, i);
> +		if (!vb2)
> +			continue;
> +
> +		q_status = visl_get_vb2_state(vb2->state);
>  
>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>  				 entry, i, q_status,
> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>  
> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>  					   &buf[len],
>  					   TPG_STR_BUF_SZ - len);
>  
> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>  	len = 0;
>  	for (i = 0; i < cap_q->num_buffers; i++) {
>  		u32 old_len = len;
> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
> +		struct vb2_buffer *vb2;
> +		char *q_status;
> +
> +		vb2 = vb2_get_buffer(cap_q, i);
> +		if (!vb2)
> +			continue;
> +
> +		q_status = visl_get_vb2_state(vb2->state);
>  
>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>  				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
> -				 cap_q->bufs[i]->index, q_status,
> -				 cap_q->bufs[i]->timestamp,
> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
> +				 vb2->index, q_status,
> +				 vb2->timestamp,
> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>  
>  		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>  		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> index 384f31fc66c5..8df301ab41ad 100644
> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>  	if (ret)
>  		return ret;
>  
> -	vb = pipe->vb_queue.bufs[buf->index];
> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>  	frame = vb_to_frame(vb);
>  
>  	buf->reserved = asd->frame_status[buf->index];


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
@ 2023-08-21 14:24     ` Hans Verkuil
  0 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:24 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

Hi Benjamin,

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> The first step before changing how vb2 buffers are stored into queue
> is to avoid direct access to bufs arrays.
> 
> This patch adds 2 helpers functions to add and remove vb2 buffers
> from a queue. With these 2 and vb2_get_buffer(), bufs field of
> struct vb2_queue becomes like a private member of the structure.
> 
> After each call to vb2_get_buffer() we need to be sure that we get
> a valid pointer so check the return value of all of them.
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>  .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>  drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>  .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>  .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>  drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>  drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>  .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>  8 files changed, 240 insertions(+), 67 deletions(-)
> 
> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
> index cf6727d9c81f..42fd3984c2bc 100644
> --- a/drivers/media/common/videobuf2/videobuf2-core.c
> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>  	unsigned long off = 0;
>  
>  	if (vb->index) {
> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
> +		struct vb2_buffer *prev;
> +		struct vb2_plane *p;
> +
> +		prev = vb2_get_buffer(q, vb->index - 1);
> +		if (!prev) {
> +			dprintk(q, 1, "can't find the requested buffer\n");
> +			return;
> +		}
> +
> +		p = &prev->planes[prev->num_planes - 1];
>  
>  		off = PAGE_ALIGN(p->m.offset + p->length);

This does not work. Before this patch there should be a patch that changes
the way the offset is determined since it affects this functionality.

__setup_offsets() fills in the m.offset field for each plane in the buffer.
In the current code it starts with 0 for the first buffer, adds the length
for each plane to it, and for the next buffer it continues doing that. So
the offset for a plane is the total length of all preceding buffers and planes.

In addition, bit 30 of the offset field is used to signal if it is a capture
or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
define).

In addition, the offset has to be page aligned, so the lower 12 bits are 0.
That leaves only 32-1-12 = 19 bits for the offset.

Since we allow 8 planes per buffer, that means that we can't have more than
65536 buffers given a 32 bit offset.

I think the way m.offset is calculated should change drastically: it should
instead be something like this:

m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;

and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.

Parsing the offset would be much simpler as well, since you can just decode
the index and plane numbers directly rather than using the cumbersome
__find_plane_by_offset() function.

The currently mechanism will fail completely once you can delete buffers,
and this proposal will simplify and improve the code, so I think it should
be done first.

Regards,

	Hans

>  	}
> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>  		vb->skip_cache_sync_on_finish = 1;
>  }
>  
> +/**
> + * vb2_queue_add_buffer() - add a buffer to a queue
> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
> + * @index: index where add vb2_buffer in the queue
> + */
> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
> +{
> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
> +		q->bufs[index] = vb;
> +		vb->index = index;
> +		vb->vb2_queue = q;
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * vb2_queue_remove_buffer() - remove a buffer from a queue
> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
> + */
> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
> +{
> +	if (vb->index < VB2_MAX_FRAME) {
> +		q->bufs[vb->index] = NULL;
> +		vb->vb2_queue = NULL;
> +	}
> +}
> +
>  /*
>   * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>   * video buffer memory for all buffers/planes on the queue and initializes the
> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  		}
>  
>  		vb->state = VB2_BUF_STATE_DEQUEUED;
> -		vb->vb2_queue = q;
>  		vb->num_planes = num_planes;
> -		vb->index = q->num_buffers + buffer;
>  		vb->type = q->type;
>  		vb->memory = memory;
>  		init_buffer_cache_hints(q, vb);
> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  		}
>  		call_void_bufop(q, init_buffer, vb);
>  
> -		q->bufs[vb->index] = vb;
> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
> +			kfree(vb);
> +			break;
> +		}
>  
>  		/* Allocate video buffer memory for the MMAP type */
>  		if (memory == VB2_MEMORY_MMAP) {
> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  			if (ret) {
>  				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>  					buffer);
> -				q->bufs[vb->index] = NULL;
> +				vb2_queue_remove_buffer(q, vb);
>  				kfree(vb);
>  				break;
>  			}
> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>  				dprintk(q, 1, "buffer %d %p initialization failed\n",
>  					buffer, vb);
>  				__vb2_buf_mem_free(vb);
> -				q->bufs[vb->index] = NULL;
> +				vb2_queue_remove_buffer(q, vb);
>  				kfree(vb);
>  				break;
>  			}
> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>  
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		vb = q->bufs[buffer];
> +		vb = vb2_get_buffer(q, buffer);
>  		if (!vb)
>  			continue;
>  
> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  	/* Call driver-provided cleanup function for each buffer, if provided */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		struct vb2_buffer *vb = q->bufs[buffer];
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>  
>  		if (vb && vb->planes[0].mem_priv)
>  			call_void_vb_qop(vb, buf_cleanup, vb);
> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  		q->cnt_unprepare_streaming = 0;
>  	}
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		struct vb2_buffer *vb = q->bufs[buffer];
> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +		bool unbalanced;
> +
> +		if (!vb)
> +			continue;
> +
> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>  
>  		if (unbalanced || debug) {
>  			pr_info("   counters for queue %p, buffer %d:%s\n",
> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  	/* Free vb2 buffers */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>  	     ++buffer) {
> -		kfree(q->bufs[buffer]);
> -		q->bufs[buffer] = NULL;
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
> +
> +		vb2_queue_remove_buffer(q, vb);
> +		kfree(vb);
>  	}
>  
>  	q->num_buffers -= buffers;
> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>  {
>  	unsigned int buffer;
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
> +
> +		if (vb2_buffer_in_use(q, vb))
>  			return true;
>  	}
>  	return false;
> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>  
>  void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
> +
> +	if (vb)
> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>  }
>  EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>  
> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>  	struct vb2_buffer *vb;
>  	int ret;
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
> +
>  	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>  		dprintk(q, 1, "invalid buffer state %s\n",
>  			vb2_state_name(vb->state));
> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>  		 * correctly return them to vb2.
>  		 */
>  		for (i = 0; i < q->num_buffers; ++i) {
> -			vb = q->bufs[i];
> +			vb = vb2_get_buffer(q, i);
> +
> +			if (!vb)
> +				continue;
> +
>  			if (vb->state == VB2_BUF_STATE_ACTIVE)
>  				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>  		}
> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>  		return -EIO;
>  	}
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
>  
>  	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>  	    q->requires_requests) {
> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	 * to vb2 in stop_streaming().
>  	 */
>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> -		for (i = 0; i < q->num_buffers; ++i)
> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
> +		for (i = 0; i < q->num_buffers; ++i) {
> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
> +
> +			if (!vb)
> +				continue;
> +
> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>  				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
> -					q->bufs[i]);
> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
> +					vb);
> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>  			}
> +		}
>  		/* Must be zero now */
>  		WARN_ON(atomic_read(&q->owned_by_drv_count));
>  	}
> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>  	 */
>  	for (i = 0; i < q->num_buffers; ++i) {
> -		struct vb2_buffer *vb = q->bufs[i];
> -		struct media_request *req = vb->req_obj.req;
> +		struct vb2_buffer *vb;
> +		struct media_request *req;
>  
> +		vb = vb2_get_buffer(q, i);
> +		if (!vb)
> +			continue;
> +
> +		req = vb->req_obj.req;
>  		/*
>  		 * If a request is associated with this buffer, then
>  		 * call buf_request_cancel() to give the driver to complete()
> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>  	 * return its buffer and plane numbers.
>  	 */
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		vb = q->bufs[buffer];
> +		vb = vb2_get_buffer(q, buffer);
> +
> +		if (!vb)
> +			continue;
>  
>  		for (plane = 0; plane < vb->num_planes; ++plane) {
>  			if (vb->planes[plane].m.offset == off) {
> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>  		return -EINVAL;
>  	}
>  
> -	vb = q->bufs[index];
> +	vb = vb2_get_buffer(q, index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
>  
>  	if (plane >= vb->num_planes) {
>  		dprintk(q, 1, "buffer plane out of range\n");
> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  	if (ret)
>  		goto unlock;
>  
> -	vb = q->bufs[buffer];
> +	vb = vb2_get_buffer(q, buffer);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
>  
>  	/*
>  	 * MMAP requires page_aligned buffers.
> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  	if (ret)
>  		goto unlock;
>  
> -	vb = q->bufs[buffer];
> +	vb = vb2_get_buffer(q, buffer);
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
>  
>  	vaddr = vb2_plane_vaddr(vb, plane);
>  	mutex_unlock(&q->mmap_lock);
> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>  static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  {
>  	struct vb2_fileio_data *fileio;
> +	struct vb2_buffer *vb;
>  	int i, ret;
>  	unsigned int count = 0;
>  
> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  	 * Check if plane_count is correct
>  	 * (multiplane buffers are not supported).
>  	 */
> -	if (q->bufs[0]->num_planes != 1) {
> +	vb = vb2_get_buffer(q, 0);
> +	if (!vb) {
> +		ret = -EBUSY;
> +		goto err_reqbufs;
> +	}
> +
> +	if (vb->num_planes != 1) {
>  		ret = -EBUSY;
>  		goto err_reqbufs;
>  	}
> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  	 * Get kernel address of each buffer.
>  	 */
>  	for (i = 0; i < q->num_buffers; i++) {
> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> +		vb = vb2_get_buffer(q, i);
> +
> +		if (!vb)
> +			continue;
> +
> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>  		if (fileio->bufs[i].vaddr == NULL) {
>  			ret = -EINVAL;
>  			goto err_reqbufs;
>  		}
> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>  	}
>  
>  	/*
> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  
>  		fileio->cur_index = index;
>  		buf = &fileio->bufs[index];
> -		b = q->bufs[index];
> +		b = vb2_get_buffer(q, index);
> +
> +		if (!b)
> +			return -EINVAL;
>  
>  		/*
>  		 * Get number of bytes filled by the driver
>  		 */
>  		buf->pos = 0;
>  		buf->queued = 0;
> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> -				 : vb2_plane_size(q->bufs[index], 0);
> +		buf->size = read ? vb2_get_plane_payload(b, 0)
> +				 : vb2_plane_size(b, 0);
>  		/* Compensate for data_offset on read in the multiplanar case. */
>  		if (is_multiplanar && read &&
>  				b->planes[0].data_offset < buf->size) {
> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  	 * Queue next buffer if required.
>  	 */
>  	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> -		struct vb2_buffer *b = q->bufs[index];
> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>  
> +		if (!b) {
> +			dprintk(q, 1, "can't find the requested buffer\n");
> +			return -EINVAL;
> +		}
>  		/*
>  		 * Check if this is the last buffer to read.
>  		 */
> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  		 */
>  		buf->pos = 0;
>  		buf->queued = 1;
> -		buf->size = vb2_plane_size(q->bufs[index], 0);
> +		buf->size = vb2_plane_size(b, 0);
>  		fileio->q_count += 1;
>  		/*
>  		 * If we are queuing up buffers for the first time, then
> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>  		 * Call vb2_dqbuf to get buffer back.
>  		 */
>  		if (prequeue) {
> -			vb = q->bufs[index++];
> +			vb = vb2_get_buffer(q, index++);
> +			if (!vb)
> +				continue;
>  			prequeue--;
>  		} else {
>  			call_void_qop(q, wait_finish, q);
> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>  			call_void_qop(q, wait_prepare, q);
>  			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>  			if (!ret)
> -				vb = q->bufs[index];
> +				vb = vb2_get_buffer(q, index);
>  		}
>  		if (ret || threadio->stop)
>  			break;
> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> index c7a54d82a55e..724135d41f7f 100644
> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>  		return -EINVAL;
>  	}
>  
> -	if (q->bufs[b->index] == NULL) {
> -		/* Should never happen */
> +	if (!vb2_get_buffer(q, b->index)) {
>  		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>  		return -EINVAL;
>  	}
> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>  		return -EINVAL;
>  	}
>  
> -	vb = q->bufs[b->index];
> +	vb = vb2_get_buffer(q, b->index);
>  	vbuf = to_vb2_v4l2_buffer(vb);
>  	ret = __verify_planes_array(vb, b);
>  	if (ret)
> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>  struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>  {
>  	unsigned int i;
> +	struct vb2_buffer *vb2;
>  
> -	for (i = 0; i < q->num_buffers; i++)
> -		if (q->bufs[i]->copied_timestamp &&
> -		    q->bufs[i]->timestamp == timestamp)
> -			return vb2_get_buffer(q, i);
> +	for (i = 0; i < q->num_buffers; i++) {
> +		vb2 = vb2_get_buffer(q, i);
> +
> +		if (!vb2)
> +			continue;
> +
> +		if (vb2->copied_timestamp &&
> +		    vb2->timestamp == timestamp)
> +			return vb2;
> +	}
>  	return NULL;
>  }
>  EXPORT_SYMBOL_GPL(vb2_find_buffer);
> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  		dprintk(q, 1, "buffer index out of range\n");
>  		return -EINVAL;
>  	}
> -	vb = q->bufs[b->index];
> +	vb = vb2_get_buffer(q, b->index);
> +
> +	if (!vb) {
> +		dprintk(q, 1, "can't find the requested buffer\n");
> +		return -EINVAL;
> +	}
> +
>  	ret = __verify_planes_array(vb, b);
>  	if (!ret)
>  		vb2_core_querybuf(q, b->index, b);
> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
> index 44b830ae01d8..e2c371c2fde5 100644
> --- a/drivers/media/platform/amphion/vpu_dbg.c
> +++ b/drivers/media/platform/amphion/vpu_dbg.c
> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>  
>  	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		struct vb2_buffer *vb = vq->bufs[i];
> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +		struct vb2_buffer *vb;
> +		struct vb2_v4l2_buffer *vbuf;
> +
> +		vb = vb2_get_buffer(vq, i);
> +		if (!vb)
> +			continue;
>  
>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>  			continue;
> +
> +		vbuf = to_vb2_v4l2_buffer(vb);
> +
>  		num = scnprintf(str, sizeof(str),
>  				"output [%2d] state = %10s, %8s\n",
>  				i, vb2_stat_name[vb->state],
> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>  
>  	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		struct vb2_buffer *vb = vq->bufs[i];
> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +		struct vb2_buffer *vb;
> +		struct vb2_v4l2_buffer *vbuf;
> +
> +		vb = vb2_get_buffer(vq, i);
> +		if (!vb)
> +			continue;
>  
>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>  			continue;
> +
> +		vbuf = to_vb2_v4l2_buffer(vb);
> +
>  		num = scnprintf(str, sizeof(str),
>  				"capture[%2d] state = %10s, %8s\n",
>  				i, vb2_stat_name[vb->state],
> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> index 0051f372a66c..ea37069ba355 100644
> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>  		return -EINVAL;
>  	}
>  
> -	vb = vq->bufs[buf->index];
> +	vb = vb2_get_buffer(vq, buf->index);
> +	if (!vb) {
> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
> +		return -EINVAL;
> +	}
>  	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>  	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>  
> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> index cf16cf2807f0..6532a69f1fa8 100644
> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>  
>  	/* update internal buffer's width/height */
>  	for (i = 0; i < vq->num_buffers; i++) {
> -		if (vb == vq->bufs[i]) {
> +		if (vb == vb2_get_buffer(vq, i)) {
>  			instance->dpb[i].width = w;
>  			instance->dpb[i].height = h;
>  			break;
> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
> index 3a848ca32a0e..326be09bdb55 100644
> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>  		}
>  
>  		vb2_buf = vb2_get_buffer(vq, buf->index);
> +		if (!vb2_buf) {
> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
> +			return -EINVAL;
> +		}
>  		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>  		stream->bytesused = buf->bytesused;
>  	}
> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
> index 318d675e5668..ba20ea998d19 100644
> --- a/drivers/media/test-drivers/visl/visl-dec.c
> +++ b/drivers/media/test-drivers/visl/visl-dec.c
> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>  	for (i = 0; i < out_q->num_buffers; i++) {
>  		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>  		u32 old_len = len;
> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
> +		struct vb2_buffer *vb2;
> +		char *q_status;
> +
> +		vb2 = vb2_get_buffer(out_q, i);
> +		if (!vb2)
> +			continue;
> +
> +		q_status = visl_get_vb2_state(vb2->state);
>  
>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>  				 entry, i, q_status,
> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>  
> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>  					   &buf[len],
>  					   TPG_STR_BUF_SZ - len);
>  
> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>  	len = 0;
>  	for (i = 0; i < cap_q->num_buffers; i++) {
>  		u32 old_len = len;
> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
> +		struct vb2_buffer *vb2;
> +		char *q_status;
> +
> +		vb2 = vb2_get_buffer(cap_q, i);
> +		if (!vb2)
> +			continue;
> +
> +		q_status = visl_get_vb2_state(vb2->state);
>  
>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>  				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
> -				 cap_q->bufs[i]->index, q_status,
> -				 cap_q->bufs[i]->timestamp,
> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
> +				 vb2->index, q_status,
> +				 vb2->timestamp,
> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>  
>  		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>  		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> index 384f31fc66c5..8df301ab41ad 100644
> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>  	if (ret)
>  		return ret;
>  
> -	vb = pipe->vb_queue.bufs[buf->index];
> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>  	frame = vb_to_frame(vb);
>  
>  	buf->reserved = asd->frame_status[buf->index];


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
  2023-08-21 14:24     ` Hans Verkuil
  (?)
@ 2023-08-21 14:31       ` Hans Verkuil
  -1 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:31 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 21/08/2023 16:24, Hans Verkuil wrote:
> Hi Benjamin,
> 
> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>> The first step before changing how vb2 buffers are stored into queue
>> is to avoid direct access to bufs arrays.
>>
>> This patch adds 2 helpers functions to add and remove vb2 buffers
>> from a queue. With these 2 and vb2_get_buffer(), bufs field of
>> struct vb2_queue becomes like a private member of the structure.
>>
>> After each call to vb2_get_buffer() we need to be sure that we get
>> a valid pointer so check the return value of all of them.
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>> ---
>>  .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>>  .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>>  drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>>  .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>>  .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>>  drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>>  drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>>  .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>>  8 files changed, 240 insertions(+), 67 deletions(-)
>>
>> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
>> index cf6727d9c81f..42fd3984c2bc 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-core.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
>> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>>  	unsigned long off = 0;
>>  
>>  	if (vb->index) {
>> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
>> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
>> +		struct vb2_buffer *prev;
>> +		struct vb2_plane *p;
>> +
>> +		prev = vb2_get_buffer(q, vb->index - 1);
>> +		if (!prev) {
>> +			dprintk(q, 1, "can't find the requested buffer\n");
>> +			return;
>> +		}
>> +
>> +		p = &prev->planes[prev->num_planes - 1];
>>  
>>  		off = PAGE_ALIGN(p->m.offset + p->length);
> 
> This does not work. Before this patch there should be a patch that changes
> the way the offset is determined since it affects this functionality.
> 
> __setup_offsets() fills in the m.offset field for each plane in the buffer.
> In the current code it starts with 0 for the first buffer, adds the length
> for each plane to it, and for the next buffer it continues doing that. So
> the offset for a plane is the total length of all preceding buffers and planes.
> 
> In addition, bit 30 of the offset field is used to signal if it is a capture
> or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
> define).
> 
> In addition, the offset has to be page aligned, so the lower 12 bits are 0.
> That leaves only 32-1-12 = 19 bits for the offset.
> 
> Since we allow 8 planes per buffer, that means that we can't have more than
> 65536 buffers given a 32 bit offset.
> 
> I think the way m.offset is calculated should change drastically: it should
> instead be something like this:
> 
> m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;
> 
> and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.
> 
> Parsing the offset would be much simpler as well, since you can just decode
> the index and plane numbers directly rather than using the cumbersome
> __find_plane_by_offset() function.
> 
> The currently mechanism will fail completely once you can delete buffers,
> and this proposal will simplify and improve the code, so I think it should
> be done first.

I could have saved myself some work if I read the other patches first.

I see that patch 3/10 addresses this. But for the v5, just move that patch
to the beginning of the series.

I would also suggest changing DST_QUEUE_OFF_BASE to use bit 31 to allow for
16 bits instead of 15 for the buffer index.

Regards,

	Hans

> 
> Regards,
> 
> 	Hans
> 
>>  	}
>> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>>  		vb->skip_cache_sync_on_finish = 1;
>>  }
>>  
>> +/**
>> + * vb2_queue_add_buffer() - add a buffer to a queue
>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
>> + * @index: index where add vb2_buffer in the queue
>> + */
>> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
>> +{
>> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
>> +		q->bufs[index] = vb;
>> +		vb->index = index;
>> +		vb->vb2_queue = q;
>> +		return true;
>> +	}
>> +
>> +	return false;
>> +}
>> +
>> +/**
>> + * vb2_queue_remove_buffer() - remove a buffer from a queue
>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
>> + */
>> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
>> +{
>> +	if (vb->index < VB2_MAX_FRAME) {
>> +		q->bufs[vb->index] = NULL;
>> +		vb->vb2_queue = NULL;
>> +	}
>> +}
>> +
>>  /*
>>   * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>>   * video buffer memory for all buffers/planes on the queue and initializes the
>> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  		}
>>  
>>  		vb->state = VB2_BUF_STATE_DEQUEUED;
>> -		vb->vb2_queue = q;
>>  		vb->num_planes = num_planes;
>> -		vb->index = q->num_buffers + buffer;
>>  		vb->type = q->type;
>>  		vb->memory = memory;
>>  		init_buffer_cache_hints(q, vb);
>> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  		}
>>  		call_void_bufop(q, init_buffer, vb);
>>  
>> -		q->bufs[vb->index] = vb;
>> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
>> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
>> +			kfree(vb);
>> +			break;
>> +		}
>>  
>>  		/* Allocate video buffer memory for the MMAP type */
>>  		if (memory == VB2_MEMORY_MMAP) {
>> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  			if (ret) {
>>  				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>>  					buffer);
>> -				q->bufs[vb->index] = NULL;
>> +				vb2_queue_remove_buffer(q, vb);
>>  				kfree(vb);
>>  				break;
>>  			}
>> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  				dprintk(q, 1, "buffer %d %p initialization failed\n",
>>  					buffer, vb);
>>  				__vb2_buf_mem_free(vb);
>> -				q->bufs[vb->index] = NULL;
>> +				vb2_queue_remove_buffer(q, vb);
>>  				kfree(vb);
>>  				break;
>>  			}
>> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>  
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		vb = q->bufs[buffer];
>> +		vb = vb2_get_buffer(q, buffer);
>>  		if (!vb)
>>  			continue;
>>  
>> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  	/* Call driver-provided cleanup function for each buffer, if provided */
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		struct vb2_buffer *vb = q->bufs[buffer];
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>  
>>  		if (vb && vb->planes[0].mem_priv)
>>  			call_void_vb_qop(vb, buf_cleanup, vb);
>> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  		q->cnt_unprepare_streaming = 0;
>>  	}
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		struct vb2_buffer *vb = q->bufs[buffer];
>> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
>> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +		bool unbalanced;
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
>> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>  
>>  		if (unbalanced || debug) {
>>  			pr_info("   counters for queue %p, buffer %d:%s\n",
>> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  	/* Free vb2 buffers */
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		kfree(q->bufs[buffer]);
>> -		q->bufs[buffer] = NULL;
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		vb2_queue_remove_buffer(q, vb);
>> +		kfree(vb);
>>  	}
>>  
>>  	q->num_buffers -= buffers;
>> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>  {
>>  	unsigned int buffer;
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		if (vb2_buffer_in_use(q, vb))
>>  			return true;
>>  	}
>>  	return false;
>> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>  
>>  void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>>  {
>> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
>> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
>> +
>> +	if (vb)
>> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>>  }
>>  EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>>  
>> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>>  	struct vb2_buffer *vb;
>>  	int ret;
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>>  	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>>  		dprintk(q, 1, "invalid buffer state %s\n",
>>  			vb2_state_name(vb->state));
>> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>  		 * correctly return them to vb2.
>>  		 */
>>  		for (i = 0; i < q->num_buffers; ++i) {
>> -			vb = q->bufs[i];
>> +			vb = vb2_get_buffer(q, i);
>> +
>> +			if (!vb)
>> +				continue;
>> +
>>  			if (vb->state == VB2_BUF_STATE_ACTIVE)
>>  				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>>  		}
>> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>>  		return -EIO;
>>  	}
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>>  
>>  	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>>  	    q->requires_requests) {
>> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>  	 * to vb2 in stop_streaming().
>>  	 */
>>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
>> -		for (i = 0; i < q->num_buffers; ++i)
>> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
>> +		for (i = 0; i < q->num_buffers; ++i) {
>> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
>> +
>> +			if (!vb)
>> +				continue;
>> +
>> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>>  				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
>> -					q->bufs[i]);
>> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
>> +					vb);
>> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>>  			}
>> +		}
>>  		/* Must be zero now */
>>  		WARN_ON(atomic_read(&q->owned_by_drv_count));
>>  	}
>> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>  	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>>  	 */
>>  	for (i = 0; i < q->num_buffers; ++i) {
>> -		struct vb2_buffer *vb = q->bufs[i];
>> -		struct media_request *req = vb->req_obj.req;
>> +		struct vb2_buffer *vb;
>> +		struct media_request *req;
>>  
>> +		vb = vb2_get_buffer(q, i);
>> +		if (!vb)
>> +			continue;
>> +
>> +		req = vb->req_obj.req;
>>  		/*
>>  		 * If a request is associated with this buffer, then
>>  		 * call buf_request_cancel() to give the driver to complete()
>> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>  	 * return its buffer and plane numbers.
>>  	 */
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		vb = q->bufs[buffer];
>> +		vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>>  
>>  		for (plane = 0; plane < vb->num_planes; ++plane) {
>>  			if (vb->planes[plane].m.offset == off) {
>> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>>  
>>  	if (plane >= vb->num_planes) {
>>  		dprintk(q, 1, "buffer plane out of range\n");
>> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>  	if (ret)
>>  		goto unlock;
>>  
>> -	vb = q->bufs[buffer];
>> +	vb = vb2_get_buffer(q, buffer);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		ret = -EINVAL;
>> +		goto unlock;
>> +	}
>>  
>>  	/*
>>  	 * MMAP requires page_aligned buffers.
>> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>  	if (ret)
>>  		goto unlock;
>>  
>> -	vb = q->bufs[buffer];
>> +	vb = vb2_get_buffer(q, buffer);
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		ret = -EINVAL;
>> +		goto unlock;
>> +	}
>>  
>>  	vaddr = vb2_plane_vaddr(vb, plane);
>>  	mutex_unlock(&q->mmap_lock);
>> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>>  static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  {
>>  	struct vb2_fileio_data *fileio;
>> +	struct vb2_buffer *vb;
>>  	int i, ret;
>>  	unsigned int count = 0;
>>  
>> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  	 * Check if plane_count is correct
>>  	 * (multiplane buffers are not supported).
>>  	 */
>> -	if (q->bufs[0]->num_planes != 1) {
>> +	vb = vb2_get_buffer(q, 0);
>> +	if (!vb) {
>> +		ret = -EBUSY;
>> +		goto err_reqbufs;
>> +	}
>> +
>> +	if (vb->num_planes != 1) {
>>  		ret = -EBUSY;
>>  		goto err_reqbufs;
>>  	}
>> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  	 * Get kernel address of each buffer.
>>  	 */
>>  	for (i = 0; i < q->num_buffers; i++) {
>> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>> +		vb = vb2_get_buffer(q, i);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>>  		if (fileio->bufs[i].vaddr == NULL) {
>>  			ret = -EINVAL;
>>  			goto err_reqbufs;
>>  		}
>> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>>  	}
>>  
>>  	/*
>> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  
>>  		fileio->cur_index = index;
>>  		buf = &fileio->bufs[index];
>> -		b = q->bufs[index];
>> +		b = vb2_get_buffer(q, index);
>> +
>> +		if (!b)
>> +			return -EINVAL;
>>  
>>  		/*
>>  		 * Get number of bytes filled by the driver
>>  		 */
>>  		buf->pos = 0;
>>  		buf->queued = 0;
>> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>> -				 : vb2_plane_size(q->bufs[index], 0);
>> +		buf->size = read ? vb2_get_plane_payload(b, 0)
>> +				 : vb2_plane_size(b, 0);
>>  		/* Compensate for data_offset on read in the multiplanar case. */
>>  		if (is_multiplanar && read &&
>>  				b->planes[0].data_offset < buf->size) {
>> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  	 * Queue next buffer if required.
>>  	 */
>>  	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>> -		struct vb2_buffer *b = q->bufs[index];
>> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>>  
>> +		if (!b) {
>> +			dprintk(q, 1, "can't find the requested buffer\n");
>> +			return -EINVAL;
>> +		}
>>  		/*
>>  		 * Check if this is the last buffer to read.
>>  		 */
>> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  		 */
>>  		buf->pos = 0;
>>  		buf->queued = 1;
>> -		buf->size = vb2_plane_size(q->bufs[index], 0);
>> +		buf->size = vb2_plane_size(b, 0);
>>  		fileio->q_count += 1;
>>  		/*
>>  		 * If we are queuing up buffers for the first time, then
>> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>>  		 * Call vb2_dqbuf to get buffer back.
>>  		 */
>>  		if (prequeue) {
>> -			vb = q->bufs[index++];
>> +			vb = vb2_get_buffer(q, index++);
>> +			if (!vb)
>> +				continue;
>>  			prequeue--;
>>  		} else {
>>  			call_void_qop(q, wait_finish, q);
>> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>>  			call_void_qop(q, wait_prepare, q);
>>  			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>>  			if (!ret)
>> -				vb = q->bufs[index];
>> +				vb = vb2_get_buffer(q, index);
>>  		}
>>  		if (ret || threadio->stop)
>>  			break;
>> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> index c7a54d82a55e..724135d41f7f 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>  		return -EINVAL;
>>  	}
>>  
>> -	if (q->bufs[b->index] == NULL) {
>> -		/* Should never happen */
>> +	if (!vb2_get_buffer(q, b->index)) {
>>  		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>>  		return -EINVAL;
>>  	}
>> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = q->bufs[b->index];
>> +	vb = vb2_get_buffer(q, b->index);
>>  	vbuf = to_vb2_v4l2_buffer(vb);
>>  	ret = __verify_planes_array(vb, b);
>>  	if (ret)
>> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>>  struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>>  {
>>  	unsigned int i;
>> +	struct vb2_buffer *vb2;
>>  
>> -	for (i = 0; i < q->num_buffers; i++)
>> -		if (q->bufs[i]->copied_timestamp &&
>> -		    q->bufs[i]->timestamp == timestamp)
>> -			return vb2_get_buffer(q, i);
>> +	for (i = 0; i < q->num_buffers; i++) {
>> +		vb2 = vb2_get_buffer(q, i);
>> +
>> +		if (!vb2)
>> +			continue;
>> +
>> +		if (vb2->copied_timestamp &&
>> +		    vb2->timestamp == timestamp)
>> +			return vb2;
>> +	}
>>  	return NULL;
>>  }
>>  EXPORT_SYMBOL_GPL(vb2_find_buffer);
>> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>  		dprintk(q, 1, "buffer index out of range\n");
>>  		return -EINVAL;
>>  	}
>> -	vb = q->bufs[b->index];
>> +	vb = vb2_get_buffer(q, b->index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>>  	ret = __verify_planes_array(vb, b);
>>  	if (!ret)
>>  		vb2_core_querybuf(q, b->index, b);
>> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
>> index 44b830ae01d8..e2c371c2fde5 100644
>> --- a/drivers/media/platform/amphion/vpu_dbg.c
>> +++ b/drivers/media/platform/amphion/vpu_dbg.c
>> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>  
>>  	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		struct vb2_buffer *vb = vq->bufs[i];
>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +		struct vb2_buffer *vb;
>> +		struct vb2_v4l2_buffer *vbuf;
>> +
>> +		vb = vb2_get_buffer(vq, i);
>> +		if (!vb)
>> +			continue;
>>  
>>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>  			continue;
>> +
>> +		vbuf = to_vb2_v4l2_buffer(vb);
>> +
>>  		num = scnprintf(str, sizeof(str),
>>  				"output [%2d] state = %10s, %8s\n",
>>  				i, vb2_stat_name[vb->state],
>> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>  
>>  	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		struct vb2_buffer *vb = vq->bufs[i];
>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +		struct vb2_buffer *vb;
>> +		struct vb2_v4l2_buffer *vbuf;
>> +
>> +		vb = vb2_get_buffer(vq, i);
>> +		if (!vb)
>> +			continue;
>>  
>>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>  			continue;
>> +
>> +		vbuf = to_vb2_v4l2_buffer(vb);
>> +
>>  		num = scnprintf(str, sizeof(str),
>>  				"capture[%2d] state = %10s, %8s\n",
>>  				i, vb2_stat_name[vb->state],
>> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> index 0051f372a66c..ea37069ba355 100644
>> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = vq->bufs[buf->index];
>> +	vb = vb2_get_buffer(vq, buf->index);
>> +	if (!vb) {
>> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
>> +		return -EINVAL;
>> +	}
>>  	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>>  	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>>  
>> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> index cf16cf2807f0..6532a69f1fa8 100644
>> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>>  
>>  	/* update internal buffer's width/height */
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		if (vb == vq->bufs[i]) {
>> +		if (vb == vb2_get_buffer(vq, i)) {
>>  			instance->dpb[i].width = w;
>>  			instance->dpb[i].height = h;
>>  			break;
>> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> index 3a848ca32a0e..326be09bdb55 100644
>> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>  		}
>>  
>>  		vb2_buf = vb2_get_buffer(vq, buf->index);
>> +		if (!vb2_buf) {
>> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
>> +			return -EINVAL;
>> +		}
>>  		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>>  		stream->bytesused = buf->bytesused;
>>  	}
>> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
>> index 318d675e5668..ba20ea998d19 100644
>> --- a/drivers/media/test-drivers/visl/visl-dec.c
>> +++ b/drivers/media/test-drivers/visl/visl-dec.c
>> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>  	for (i = 0; i < out_q->num_buffers; i++) {
>>  		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>>  		u32 old_len = len;
>> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
>> +		struct vb2_buffer *vb2;
>> +		char *q_status;
>> +
>> +		vb2 = vb2_get_buffer(out_q, i);
>> +		if (!vb2)
>> +			continue;
>> +
>> +		q_status = visl_get_vb2_state(vb2->state);
>>  
>>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>  				 entry, i, q_status,
>> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
>> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>>  
>> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
>> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>>  					   &buf[len],
>>  					   TPG_STR_BUF_SZ - len);
>>  
>> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>  	len = 0;
>>  	for (i = 0; i < cap_q->num_buffers; i++) {
>>  		u32 old_len = len;
>> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
>> +		struct vb2_buffer *vb2;
>> +		char *q_status;
>> +
>> +		vb2 = vb2_get_buffer(cap_q, i);
>> +		if (!vb2)
>> +			continue;
>> +
>> +		q_status = visl_get_vb2_state(vb2->state);
>>  
>>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>  				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
>> -				 cap_q->bufs[i]->index, q_status,
>> -				 cap_q->bufs[i]->timestamp,
>> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
>> +				 vb2->index, q_status,
>> +				 vb2->timestamp,
>> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>>  
>>  		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>>  		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
>> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> index 384f31fc66c5..8df301ab41ad 100644
>> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>>  	if (ret)
>>  		return ret;
>>  
>> -	vb = pipe->vb_queue.bufs[buf->index];
>> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>>  	frame = vb_to_frame(vb);
>>  
>>  	buf->reserved = asd->frame_status[buf->index];
> 


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
@ 2023-08-21 14:31       ` Hans Verkuil
  0 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:31 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 21/08/2023 16:24, Hans Verkuil wrote:
> Hi Benjamin,
> 
> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>> The first step before changing how vb2 buffers are stored into queue
>> is to avoid direct access to bufs arrays.
>>
>> This patch adds 2 helpers functions to add and remove vb2 buffers
>> from a queue. With these 2 and vb2_get_buffer(), bufs field of
>> struct vb2_queue becomes like a private member of the structure.
>>
>> After each call to vb2_get_buffer() we need to be sure that we get
>> a valid pointer so check the return value of all of them.
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>> ---
>>  .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>>  .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>>  drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>>  .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>>  .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>>  drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>>  drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>>  .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>>  8 files changed, 240 insertions(+), 67 deletions(-)
>>
>> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
>> index cf6727d9c81f..42fd3984c2bc 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-core.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
>> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>>  	unsigned long off = 0;
>>  
>>  	if (vb->index) {
>> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
>> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
>> +		struct vb2_buffer *prev;
>> +		struct vb2_plane *p;
>> +
>> +		prev = vb2_get_buffer(q, vb->index - 1);
>> +		if (!prev) {
>> +			dprintk(q, 1, "can't find the requested buffer\n");
>> +			return;
>> +		}
>> +
>> +		p = &prev->planes[prev->num_planes - 1];
>>  
>>  		off = PAGE_ALIGN(p->m.offset + p->length);
> 
> This does not work. Before this patch there should be a patch that changes
> the way the offset is determined since it affects this functionality.
> 
> __setup_offsets() fills in the m.offset field for each plane in the buffer.
> In the current code it starts with 0 for the first buffer, adds the length
> for each plane to it, and for the next buffer it continues doing that. So
> the offset for a plane is the total length of all preceding buffers and planes.
> 
> In addition, bit 30 of the offset field is used to signal if it is a capture
> or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
> define).
> 
> In addition, the offset has to be page aligned, so the lower 12 bits are 0.
> That leaves only 32-1-12 = 19 bits for the offset.
> 
> Since we allow 8 planes per buffer, that means that we can't have more than
> 65536 buffers given a 32 bit offset.
> 
> I think the way m.offset is calculated should change drastically: it should
> instead be something like this:
> 
> m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;
> 
> and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.
> 
> Parsing the offset would be much simpler as well, since you can just decode
> the index and plane numbers directly rather than using the cumbersome
> __find_plane_by_offset() function.
> 
> The currently mechanism will fail completely once you can delete buffers,
> and this proposal will simplify and improve the code, so I think it should
> be done first.

I could have saved myself some work if I read the other patches first.

I see that patch 3/10 addresses this. But for the v5, just move that patch
to the beginning of the series.

I would also suggest changing DST_QUEUE_OFF_BASE to use bit 31 to allow for
16 bits instead of 15 for the buffer index.

Regards,

	Hans

> 
> Regards,
> 
> 	Hans
> 
>>  	}
>> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>>  		vb->skip_cache_sync_on_finish = 1;
>>  }
>>  
>> +/**
>> + * vb2_queue_add_buffer() - add a buffer to a queue
>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
>> + * @index: index where add vb2_buffer in the queue
>> + */
>> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
>> +{
>> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
>> +		q->bufs[index] = vb;
>> +		vb->index = index;
>> +		vb->vb2_queue = q;
>> +		return true;
>> +	}
>> +
>> +	return false;
>> +}
>> +
>> +/**
>> + * vb2_queue_remove_buffer() - remove a buffer from a queue
>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
>> + */
>> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
>> +{
>> +	if (vb->index < VB2_MAX_FRAME) {
>> +		q->bufs[vb->index] = NULL;
>> +		vb->vb2_queue = NULL;
>> +	}
>> +}
>> +
>>  /*
>>   * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>>   * video buffer memory for all buffers/planes on the queue and initializes the
>> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  		}
>>  
>>  		vb->state = VB2_BUF_STATE_DEQUEUED;
>> -		vb->vb2_queue = q;
>>  		vb->num_planes = num_planes;
>> -		vb->index = q->num_buffers + buffer;
>>  		vb->type = q->type;
>>  		vb->memory = memory;
>>  		init_buffer_cache_hints(q, vb);
>> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  		}
>>  		call_void_bufop(q, init_buffer, vb);
>>  
>> -		q->bufs[vb->index] = vb;
>> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
>> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
>> +			kfree(vb);
>> +			break;
>> +		}
>>  
>>  		/* Allocate video buffer memory for the MMAP type */
>>  		if (memory == VB2_MEMORY_MMAP) {
>> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  			if (ret) {
>>  				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>>  					buffer);
>> -				q->bufs[vb->index] = NULL;
>> +				vb2_queue_remove_buffer(q, vb);
>>  				kfree(vb);
>>  				break;
>>  			}
>> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  				dprintk(q, 1, "buffer %d %p initialization failed\n",
>>  					buffer, vb);
>>  				__vb2_buf_mem_free(vb);
>> -				q->bufs[vb->index] = NULL;
>> +				vb2_queue_remove_buffer(q, vb);
>>  				kfree(vb);
>>  				break;
>>  			}
>> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>  
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		vb = q->bufs[buffer];
>> +		vb = vb2_get_buffer(q, buffer);
>>  		if (!vb)
>>  			continue;
>>  
>> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  	/* Call driver-provided cleanup function for each buffer, if provided */
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		struct vb2_buffer *vb = q->bufs[buffer];
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>  
>>  		if (vb && vb->planes[0].mem_priv)
>>  			call_void_vb_qop(vb, buf_cleanup, vb);
>> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  		q->cnt_unprepare_streaming = 0;
>>  	}
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		struct vb2_buffer *vb = q->bufs[buffer];
>> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
>> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +		bool unbalanced;
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
>> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>  
>>  		if (unbalanced || debug) {
>>  			pr_info("   counters for queue %p, buffer %d:%s\n",
>> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  	/* Free vb2 buffers */
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		kfree(q->bufs[buffer]);
>> -		q->bufs[buffer] = NULL;
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		vb2_queue_remove_buffer(q, vb);
>> +		kfree(vb);
>>  	}
>>  
>>  	q->num_buffers -= buffers;
>> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>  {
>>  	unsigned int buffer;
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		if (vb2_buffer_in_use(q, vb))
>>  			return true;
>>  	}
>>  	return false;
>> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>  
>>  void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>>  {
>> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
>> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
>> +
>> +	if (vb)
>> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>>  }
>>  EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>>  
>> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>>  	struct vb2_buffer *vb;
>>  	int ret;
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>>  	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>>  		dprintk(q, 1, "invalid buffer state %s\n",
>>  			vb2_state_name(vb->state));
>> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>  		 * correctly return them to vb2.
>>  		 */
>>  		for (i = 0; i < q->num_buffers; ++i) {
>> -			vb = q->bufs[i];
>> +			vb = vb2_get_buffer(q, i);
>> +
>> +			if (!vb)
>> +				continue;
>> +
>>  			if (vb->state == VB2_BUF_STATE_ACTIVE)
>>  				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>>  		}
>> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>>  		return -EIO;
>>  	}
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>>  
>>  	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>>  	    q->requires_requests) {
>> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>  	 * to vb2 in stop_streaming().
>>  	 */
>>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
>> -		for (i = 0; i < q->num_buffers; ++i)
>> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
>> +		for (i = 0; i < q->num_buffers; ++i) {
>> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
>> +
>> +			if (!vb)
>> +				continue;
>> +
>> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>>  				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
>> -					q->bufs[i]);
>> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
>> +					vb);
>> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>>  			}
>> +		}
>>  		/* Must be zero now */
>>  		WARN_ON(atomic_read(&q->owned_by_drv_count));
>>  	}
>> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>  	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>>  	 */
>>  	for (i = 0; i < q->num_buffers; ++i) {
>> -		struct vb2_buffer *vb = q->bufs[i];
>> -		struct media_request *req = vb->req_obj.req;
>> +		struct vb2_buffer *vb;
>> +		struct media_request *req;
>>  
>> +		vb = vb2_get_buffer(q, i);
>> +		if (!vb)
>> +			continue;
>> +
>> +		req = vb->req_obj.req;
>>  		/*
>>  		 * If a request is associated with this buffer, then
>>  		 * call buf_request_cancel() to give the driver to complete()
>> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>  	 * return its buffer and plane numbers.
>>  	 */
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		vb = q->bufs[buffer];
>> +		vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>>  
>>  		for (plane = 0; plane < vb->num_planes; ++plane) {
>>  			if (vb->planes[plane].m.offset == off) {
>> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>>  
>>  	if (plane >= vb->num_planes) {
>>  		dprintk(q, 1, "buffer plane out of range\n");
>> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>  	if (ret)
>>  		goto unlock;
>>  
>> -	vb = q->bufs[buffer];
>> +	vb = vb2_get_buffer(q, buffer);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		ret = -EINVAL;
>> +		goto unlock;
>> +	}
>>  
>>  	/*
>>  	 * MMAP requires page_aligned buffers.
>> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>  	if (ret)
>>  		goto unlock;
>>  
>> -	vb = q->bufs[buffer];
>> +	vb = vb2_get_buffer(q, buffer);
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		ret = -EINVAL;
>> +		goto unlock;
>> +	}
>>  
>>  	vaddr = vb2_plane_vaddr(vb, plane);
>>  	mutex_unlock(&q->mmap_lock);
>> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>>  static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  {
>>  	struct vb2_fileio_data *fileio;
>> +	struct vb2_buffer *vb;
>>  	int i, ret;
>>  	unsigned int count = 0;
>>  
>> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  	 * Check if plane_count is correct
>>  	 * (multiplane buffers are not supported).
>>  	 */
>> -	if (q->bufs[0]->num_planes != 1) {
>> +	vb = vb2_get_buffer(q, 0);
>> +	if (!vb) {
>> +		ret = -EBUSY;
>> +		goto err_reqbufs;
>> +	}
>> +
>> +	if (vb->num_planes != 1) {
>>  		ret = -EBUSY;
>>  		goto err_reqbufs;
>>  	}
>> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  	 * Get kernel address of each buffer.
>>  	 */
>>  	for (i = 0; i < q->num_buffers; i++) {
>> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>> +		vb = vb2_get_buffer(q, i);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>>  		if (fileio->bufs[i].vaddr == NULL) {
>>  			ret = -EINVAL;
>>  			goto err_reqbufs;
>>  		}
>> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>>  	}
>>  
>>  	/*
>> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  
>>  		fileio->cur_index = index;
>>  		buf = &fileio->bufs[index];
>> -		b = q->bufs[index];
>> +		b = vb2_get_buffer(q, index);
>> +
>> +		if (!b)
>> +			return -EINVAL;
>>  
>>  		/*
>>  		 * Get number of bytes filled by the driver
>>  		 */
>>  		buf->pos = 0;
>>  		buf->queued = 0;
>> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>> -				 : vb2_plane_size(q->bufs[index], 0);
>> +		buf->size = read ? vb2_get_plane_payload(b, 0)
>> +				 : vb2_plane_size(b, 0);
>>  		/* Compensate for data_offset on read in the multiplanar case. */
>>  		if (is_multiplanar && read &&
>>  				b->planes[0].data_offset < buf->size) {
>> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  	 * Queue next buffer if required.
>>  	 */
>>  	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>> -		struct vb2_buffer *b = q->bufs[index];
>> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>>  
>> +		if (!b) {
>> +			dprintk(q, 1, "can't find the requested buffer\n");
>> +			return -EINVAL;
>> +		}
>>  		/*
>>  		 * Check if this is the last buffer to read.
>>  		 */
>> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  		 */
>>  		buf->pos = 0;
>>  		buf->queued = 1;
>> -		buf->size = vb2_plane_size(q->bufs[index], 0);
>> +		buf->size = vb2_plane_size(b, 0);
>>  		fileio->q_count += 1;
>>  		/*
>>  		 * If we are queuing up buffers for the first time, then
>> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>>  		 * Call vb2_dqbuf to get buffer back.
>>  		 */
>>  		if (prequeue) {
>> -			vb = q->bufs[index++];
>> +			vb = vb2_get_buffer(q, index++);
>> +			if (!vb)
>> +				continue;
>>  			prequeue--;
>>  		} else {
>>  			call_void_qop(q, wait_finish, q);
>> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>>  			call_void_qop(q, wait_prepare, q);
>>  			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>>  			if (!ret)
>> -				vb = q->bufs[index];
>> +				vb = vb2_get_buffer(q, index);
>>  		}
>>  		if (ret || threadio->stop)
>>  			break;
>> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> index c7a54d82a55e..724135d41f7f 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>  		return -EINVAL;
>>  	}
>>  
>> -	if (q->bufs[b->index] == NULL) {
>> -		/* Should never happen */
>> +	if (!vb2_get_buffer(q, b->index)) {
>>  		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>>  		return -EINVAL;
>>  	}
>> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = q->bufs[b->index];
>> +	vb = vb2_get_buffer(q, b->index);
>>  	vbuf = to_vb2_v4l2_buffer(vb);
>>  	ret = __verify_planes_array(vb, b);
>>  	if (ret)
>> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>>  struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>>  {
>>  	unsigned int i;
>> +	struct vb2_buffer *vb2;
>>  
>> -	for (i = 0; i < q->num_buffers; i++)
>> -		if (q->bufs[i]->copied_timestamp &&
>> -		    q->bufs[i]->timestamp == timestamp)
>> -			return vb2_get_buffer(q, i);
>> +	for (i = 0; i < q->num_buffers; i++) {
>> +		vb2 = vb2_get_buffer(q, i);
>> +
>> +		if (!vb2)
>> +			continue;
>> +
>> +		if (vb2->copied_timestamp &&
>> +		    vb2->timestamp == timestamp)
>> +			return vb2;
>> +	}
>>  	return NULL;
>>  }
>>  EXPORT_SYMBOL_GPL(vb2_find_buffer);
>> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>  		dprintk(q, 1, "buffer index out of range\n");
>>  		return -EINVAL;
>>  	}
>> -	vb = q->bufs[b->index];
>> +	vb = vb2_get_buffer(q, b->index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>>  	ret = __verify_planes_array(vb, b);
>>  	if (!ret)
>>  		vb2_core_querybuf(q, b->index, b);
>> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
>> index 44b830ae01d8..e2c371c2fde5 100644
>> --- a/drivers/media/platform/amphion/vpu_dbg.c
>> +++ b/drivers/media/platform/amphion/vpu_dbg.c
>> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>  
>>  	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		struct vb2_buffer *vb = vq->bufs[i];
>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +		struct vb2_buffer *vb;
>> +		struct vb2_v4l2_buffer *vbuf;
>> +
>> +		vb = vb2_get_buffer(vq, i);
>> +		if (!vb)
>> +			continue;
>>  
>>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>  			continue;
>> +
>> +		vbuf = to_vb2_v4l2_buffer(vb);
>> +
>>  		num = scnprintf(str, sizeof(str),
>>  				"output [%2d] state = %10s, %8s\n",
>>  				i, vb2_stat_name[vb->state],
>> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>  
>>  	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		struct vb2_buffer *vb = vq->bufs[i];
>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +		struct vb2_buffer *vb;
>> +		struct vb2_v4l2_buffer *vbuf;
>> +
>> +		vb = vb2_get_buffer(vq, i);
>> +		if (!vb)
>> +			continue;
>>  
>>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>  			continue;
>> +
>> +		vbuf = to_vb2_v4l2_buffer(vb);
>> +
>>  		num = scnprintf(str, sizeof(str),
>>  				"capture[%2d] state = %10s, %8s\n",
>>  				i, vb2_stat_name[vb->state],
>> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> index 0051f372a66c..ea37069ba355 100644
>> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = vq->bufs[buf->index];
>> +	vb = vb2_get_buffer(vq, buf->index);
>> +	if (!vb) {
>> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
>> +		return -EINVAL;
>> +	}
>>  	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>>  	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>>  
>> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> index cf16cf2807f0..6532a69f1fa8 100644
>> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>>  
>>  	/* update internal buffer's width/height */
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		if (vb == vq->bufs[i]) {
>> +		if (vb == vb2_get_buffer(vq, i)) {
>>  			instance->dpb[i].width = w;
>>  			instance->dpb[i].height = h;
>>  			break;
>> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> index 3a848ca32a0e..326be09bdb55 100644
>> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>  		}
>>  
>>  		vb2_buf = vb2_get_buffer(vq, buf->index);
>> +		if (!vb2_buf) {
>> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
>> +			return -EINVAL;
>> +		}
>>  		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>>  		stream->bytesused = buf->bytesused;
>>  	}
>> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
>> index 318d675e5668..ba20ea998d19 100644
>> --- a/drivers/media/test-drivers/visl/visl-dec.c
>> +++ b/drivers/media/test-drivers/visl/visl-dec.c
>> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>  	for (i = 0; i < out_q->num_buffers; i++) {
>>  		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>>  		u32 old_len = len;
>> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
>> +		struct vb2_buffer *vb2;
>> +		char *q_status;
>> +
>> +		vb2 = vb2_get_buffer(out_q, i);
>> +		if (!vb2)
>> +			continue;
>> +
>> +		q_status = visl_get_vb2_state(vb2->state);
>>  
>>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>  				 entry, i, q_status,
>> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
>> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>>  
>> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
>> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>>  					   &buf[len],
>>  					   TPG_STR_BUF_SZ - len);
>>  
>> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>  	len = 0;
>>  	for (i = 0; i < cap_q->num_buffers; i++) {
>>  		u32 old_len = len;
>> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
>> +		struct vb2_buffer *vb2;
>> +		char *q_status;
>> +
>> +		vb2 = vb2_get_buffer(cap_q, i);
>> +		if (!vb2)
>> +			continue;
>> +
>> +		q_status = visl_get_vb2_state(vb2->state);
>>  
>>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>  				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
>> -				 cap_q->bufs[i]->index, q_status,
>> -				 cap_q->bufs[i]->timestamp,
>> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
>> +				 vb2->index, q_status,
>> +				 vb2->timestamp,
>> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>>  
>>  		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>>  		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
>> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> index 384f31fc66c5..8df301ab41ad 100644
>> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>>  	if (ret)
>>  		return ret;
>>  
>> -	vb = pipe->vb_queue.bufs[buf->index];
>> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>>  	frame = vb_to_frame(vb);
>>  
>>  	buf->reserved = asd->frame_status[buf->index];
> 


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
@ 2023-08-21 14:31       ` Hans Verkuil
  0 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:31 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 21/08/2023 16:24, Hans Verkuil wrote:
> Hi Benjamin,
> 
> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>> The first step before changing how vb2 buffers are stored into queue
>> is to avoid direct access to bufs arrays.
>>
>> This patch adds 2 helpers functions to add and remove vb2 buffers
>> from a queue. With these 2 and vb2_get_buffer(), bufs field of
>> struct vb2_queue becomes like a private member of the structure.
>>
>> After each call to vb2_get_buffer() we need to be sure that we get
>> a valid pointer so check the return value of all of them.
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>> ---
>>  .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>>  .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>>  drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>>  .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>>  .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>>  drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>>  drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>>  .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>>  8 files changed, 240 insertions(+), 67 deletions(-)
>>
>> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
>> index cf6727d9c81f..42fd3984c2bc 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-core.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
>> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>>  	unsigned long off = 0;
>>  
>>  	if (vb->index) {
>> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
>> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
>> +		struct vb2_buffer *prev;
>> +		struct vb2_plane *p;
>> +
>> +		prev = vb2_get_buffer(q, vb->index - 1);
>> +		if (!prev) {
>> +			dprintk(q, 1, "can't find the requested buffer\n");
>> +			return;
>> +		}
>> +
>> +		p = &prev->planes[prev->num_planes - 1];
>>  
>>  		off = PAGE_ALIGN(p->m.offset + p->length);
> 
> This does not work. Before this patch there should be a patch that changes
> the way the offset is determined since it affects this functionality.
> 
> __setup_offsets() fills in the m.offset field for each plane in the buffer.
> In the current code it starts with 0 for the first buffer, adds the length
> for each plane to it, and for the next buffer it continues doing that. So
> the offset for a plane is the total length of all preceding buffers and planes.
> 
> In addition, bit 30 of the offset field is used to signal if it is a capture
> or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
> define).
> 
> In addition, the offset has to be page aligned, so the lower 12 bits are 0.
> That leaves only 32-1-12 = 19 bits for the offset.
> 
> Since we allow 8 planes per buffer, that means that we can't have more than
> 65536 buffers given a 32 bit offset.
> 
> I think the way m.offset is calculated should change drastically: it should
> instead be something like this:
> 
> m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;
> 
> and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.
> 
> Parsing the offset would be much simpler as well, since you can just decode
> the index and plane numbers directly rather than using the cumbersome
> __find_plane_by_offset() function.
> 
> The currently mechanism will fail completely once you can delete buffers,
> and this proposal will simplify and improve the code, so I think it should
> be done first.

I could have saved myself some work if I read the other patches first.

I see that patch 3/10 addresses this. But for the v5, just move that patch
to the beginning of the series.

I would also suggest changing DST_QUEUE_OFF_BASE to use bit 31 to allow for
16 bits instead of 15 for the buffer index.

Regards,

	Hans

> 
> Regards,
> 
> 	Hans
> 
>>  	}
>> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>>  		vb->skip_cache_sync_on_finish = 1;
>>  }
>>  
>> +/**
>> + * vb2_queue_add_buffer() - add a buffer to a queue
>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
>> + * @index: index where add vb2_buffer in the queue
>> + */
>> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
>> +{
>> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
>> +		q->bufs[index] = vb;
>> +		vb->index = index;
>> +		vb->vb2_queue = q;
>> +		return true;
>> +	}
>> +
>> +	return false;
>> +}
>> +
>> +/**
>> + * vb2_queue_remove_buffer() - remove a buffer from a queue
>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
>> + */
>> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
>> +{
>> +	if (vb->index < VB2_MAX_FRAME) {
>> +		q->bufs[vb->index] = NULL;
>> +		vb->vb2_queue = NULL;
>> +	}
>> +}
>> +
>>  /*
>>   * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>>   * video buffer memory for all buffers/planes on the queue and initializes the
>> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  		}
>>  
>>  		vb->state = VB2_BUF_STATE_DEQUEUED;
>> -		vb->vb2_queue = q;
>>  		vb->num_planes = num_planes;
>> -		vb->index = q->num_buffers + buffer;
>>  		vb->type = q->type;
>>  		vb->memory = memory;
>>  		init_buffer_cache_hints(q, vb);
>> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  		}
>>  		call_void_bufop(q, init_buffer, vb);
>>  
>> -		q->bufs[vb->index] = vb;
>> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
>> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
>> +			kfree(vb);
>> +			break;
>> +		}
>>  
>>  		/* Allocate video buffer memory for the MMAP type */
>>  		if (memory == VB2_MEMORY_MMAP) {
>> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  			if (ret) {
>>  				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>>  					buffer);
>> -				q->bufs[vb->index] = NULL;
>> +				vb2_queue_remove_buffer(q, vb);
>>  				kfree(vb);
>>  				break;
>>  			}
>> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>  				dprintk(q, 1, "buffer %d %p initialization failed\n",
>>  					buffer, vb);
>>  				__vb2_buf_mem_free(vb);
>> -				q->bufs[vb->index] = NULL;
>> +				vb2_queue_remove_buffer(q, vb);
>>  				kfree(vb);
>>  				break;
>>  			}
>> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>  
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		vb = q->bufs[buffer];
>> +		vb = vb2_get_buffer(q, buffer);
>>  		if (!vb)
>>  			continue;
>>  
>> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  	/* Call driver-provided cleanup function for each buffer, if provided */
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		struct vb2_buffer *vb = q->bufs[buffer];
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>  
>>  		if (vb && vb->planes[0].mem_priv)
>>  			call_void_vb_qop(vb, buf_cleanup, vb);
>> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  		q->cnt_unprepare_streaming = 0;
>>  	}
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		struct vb2_buffer *vb = q->bufs[buffer];
>> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
>> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +		bool unbalanced;
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
>> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>  
>>  		if (unbalanced || debug) {
>>  			pr_info("   counters for queue %p, buffer %d:%s\n",
>> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>  	/* Free vb2 buffers */
>>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>  	     ++buffer) {
>> -		kfree(q->bufs[buffer]);
>> -		q->bufs[buffer] = NULL;
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		vb2_queue_remove_buffer(q, vb);
>> +		kfree(vb);
>>  	}
>>  
>>  	q->num_buffers -= buffers;
>> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>  {
>>  	unsigned int buffer;
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		if (vb2_buffer_in_use(q, vb))
>>  			return true;
>>  	}
>>  	return false;
>> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>  
>>  void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>>  {
>> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
>> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
>> +
>> +	if (vb)
>> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>>  }
>>  EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>>  
>> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>>  	struct vb2_buffer *vb;
>>  	int ret;
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>>  	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>>  		dprintk(q, 1, "invalid buffer state %s\n",
>>  			vb2_state_name(vb->state));
>> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>  		 * correctly return them to vb2.
>>  		 */
>>  		for (i = 0; i < q->num_buffers; ++i) {
>> -			vb = q->bufs[i];
>> +			vb = vb2_get_buffer(q, i);
>> +
>> +			if (!vb)
>> +				continue;
>> +
>>  			if (vb->state == VB2_BUF_STATE_ACTIVE)
>>  				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>>  		}
>> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>>  		return -EIO;
>>  	}
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>>  
>>  	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>>  	    q->requires_requests) {
>> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>  	 * to vb2 in stop_streaming().
>>  	 */
>>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
>> -		for (i = 0; i < q->num_buffers; ++i)
>> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
>> +		for (i = 0; i < q->num_buffers; ++i) {
>> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
>> +
>> +			if (!vb)
>> +				continue;
>> +
>> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>>  				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
>> -					q->bufs[i]);
>> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
>> +					vb);
>> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>>  			}
>> +		}
>>  		/* Must be zero now */
>>  		WARN_ON(atomic_read(&q->owned_by_drv_count));
>>  	}
>> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>  	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>>  	 */
>>  	for (i = 0; i < q->num_buffers; ++i) {
>> -		struct vb2_buffer *vb = q->bufs[i];
>> -		struct media_request *req = vb->req_obj.req;
>> +		struct vb2_buffer *vb;
>> +		struct media_request *req;
>>  
>> +		vb = vb2_get_buffer(q, i);
>> +		if (!vb)
>> +			continue;
>> +
>> +		req = vb->req_obj.req;
>>  		/*
>>  		 * If a request is associated with this buffer, then
>>  		 * call buf_request_cancel() to give the driver to complete()
>> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>  	 * return its buffer and plane numbers.
>>  	 */
>>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		vb = q->bufs[buffer];
>> +		vb = vb2_get_buffer(q, buffer);
>> +
>> +		if (!vb)
>> +			continue;
>>  
>>  		for (plane = 0; plane < vb->num_planes; ++plane) {
>>  			if (vb->planes[plane].m.offset == off) {
>> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = q->bufs[index];
>> +	vb = vb2_get_buffer(q, index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>>  
>>  	if (plane >= vb->num_planes) {
>>  		dprintk(q, 1, "buffer plane out of range\n");
>> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>  	if (ret)
>>  		goto unlock;
>>  
>> -	vb = q->bufs[buffer];
>> +	vb = vb2_get_buffer(q, buffer);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		ret = -EINVAL;
>> +		goto unlock;
>> +	}
>>  
>>  	/*
>>  	 * MMAP requires page_aligned buffers.
>> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>  	if (ret)
>>  		goto unlock;
>>  
>> -	vb = q->bufs[buffer];
>> +	vb = vb2_get_buffer(q, buffer);
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		ret = -EINVAL;
>> +		goto unlock;
>> +	}
>>  
>>  	vaddr = vb2_plane_vaddr(vb, plane);
>>  	mutex_unlock(&q->mmap_lock);
>> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>>  static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  {
>>  	struct vb2_fileio_data *fileio;
>> +	struct vb2_buffer *vb;
>>  	int i, ret;
>>  	unsigned int count = 0;
>>  
>> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  	 * Check if plane_count is correct
>>  	 * (multiplane buffers are not supported).
>>  	 */
>> -	if (q->bufs[0]->num_planes != 1) {
>> +	vb = vb2_get_buffer(q, 0);
>> +	if (!vb) {
>> +		ret = -EBUSY;
>> +		goto err_reqbufs;
>> +	}
>> +
>> +	if (vb->num_planes != 1) {
>>  		ret = -EBUSY;
>>  		goto err_reqbufs;
>>  	}
>> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>  	 * Get kernel address of each buffer.
>>  	 */
>>  	for (i = 0; i < q->num_buffers; i++) {
>> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>> +		vb = vb2_get_buffer(q, i);
>> +
>> +		if (!vb)
>> +			continue;
>> +
>> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>>  		if (fileio->bufs[i].vaddr == NULL) {
>>  			ret = -EINVAL;
>>  			goto err_reqbufs;
>>  		}
>> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>>  	}
>>  
>>  	/*
>> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  
>>  		fileio->cur_index = index;
>>  		buf = &fileio->bufs[index];
>> -		b = q->bufs[index];
>> +		b = vb2_get_buffer(q, index);
>> +
>> +		if (!b)
>> +			return -EINVAL;
>>  
>>  		/*
>>  		 * Get number of bytes filled by the driver
>>  		 */
>>  		buf->pos = 0;
>>  		buf->queued = 0;
>> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>> -				 : vb2_plane_size(q->bufs[index], 0);
>> +		buf->size = read ? vb2_get_plane_payload(b, 0)
>> +				 : vb2_plane_size(b, 0);
>>  		/* Compensate for data_offset on read in the multiplanar case. */
>>  		if (is_multiplanar && read &&
>>  				b->planes[0].data_offset < buf->size) {
>> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  	 * Queue next buffer if required.
>>  	 */
>>  	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>> -		struct vb2_buffer *b = q->bufs[index];
>> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>>  
>> +		if (!b) {
>> +			dprintk(q, 1, "can't find the requested buffer\n");
>> +			return -EINVAL;
>> +		}
>>  		/*
>>  		 * Check if this is the last buffer to read.
>>  		 */
>> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>  		 */
>>  		buf->pos = 0;
>>  		buf->queued = 1;
>> -		buf->size = vb2_plane_size(q->bufs[index], 0);
>> +		buf->size = vb2_plane_size(b, 0);
>>  		fileio->q_count += 1;
>>  		/*
>>  		 * If we are queuing up buffers for the first time, then
>> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>>  		 * Call vb2_dqbuf to get buffer back.
>>  		 */
>>  		if (prequeue) {
>> -			vb = q->bufs[index++];
>> +			vb = vb2_get_buffer(q, index++);
>> +			if (!vb)
>> +				continue;
>>  			prequeue--;
>>  		} else {
>>  			call_void_qop(q, wait_finish, q);
>> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>>  			call_void_qop(q, wait_prepare, q);
>>  			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>>  			if (!ret)
>> -				vb = q->bufs[index];
>> +				vb = vb2_get_buffer(q, index);
>>  		}
>>  		if (ret || threadio->stop)
>>  			break;
>> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> index c7a54d82a55e..724135d41f7f 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>  		return -EINVAL;
>>  	}
>>  
>> -	if (q->bufs[b->index] == NULL) {
>> -		/* Should never happen */
>> +	if (!vb2_get_buffer(q, b->index)) {
>>  		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>>  		return -EINVAL;
>>  	}
>> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = q->bufs[b->index];
>> +	vb = vb2_get_buffer(q, b->index);
>>  	vbuf = to_vb2_v4l2_buffer(vb);
>>  	ret = __verify_planes_array(vb, b);
>>  	if (ret)
>> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>>  struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>>  {
>>  	unsigned int i;
>> +	struct vb2_buffer *vb2;
>>  
>> -	for (i = 0; i < q->num_buffers; i++)
>> -		if (q->bufs[i]->copied_timestamp &&
>> -		    q->bufs[i]->timestamp == timestamp)
>> -			return vb2_get_buffer(q, i);
>> +	for (i = 0; i < q->num_buffers; i++) {
>> +		vb2 = vb2_get_buffer(q, i);
>> +
>> +		if (!vb2)
>> +			continue;
>> +
>> +		if (vb2->copied_timestamp &&
>> +		    vb2->timestamp == timestamp)
>> +			return vb2;
>> +	}
>>  	return NULL;
>>  }
>>  EXPORT_SYMBOL_GPL(vb2_find_buffer);
>> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>  		dprintk(q, 1, "buffer index out of range\n");
>>  		return -EINVAL;
>>  	}
>> -	vb = q->bufs[b->index];
>> +	vb = vb2_get_buffer(q, b->index);
>> +
>> +	if (!vb) {
>> +		dprintk(q, 1, "can't find the requested buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>>  	ret = __verify_planes_array(vb, b);
>>  	if (!ret)
>>  		vb2_core_querybuf(q, b->index, b);
>> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
>> index 44b830ae01d8..e2c371c2fde5 100644
>> --- a/drivers/media/platform/amphion/vpu_dbg.c
>> +++ b/drivers/media/platform/amphion/vpu_dbg.c
>> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>  
>>  	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		struct vb2_buffer *vb = vq->bufs[i];
>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +		struct vb2_buffer *vb;
>> +		struct vb2_v4l2_buffer *vbuf;
>> +
>> +		vb = vb2_get_buffer(vq, i);
>> +		if (!vb)
>> +			continue;
>>  
>>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>  			continue;
>> +
>> +		vbuf = to_vb2_v4l2_buffer(vb);
>> +
>>  		num = scnprintf(str, sizeof(str),
>>  				"output [%2d] state = %10s, %8s\n",
>>  				i, vb2_stat_name[vb->state],
>> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>  
>>  	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		struct vb2_buffer *vb = vq->bufs[i];
>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +		struct vb2_buffer *vb;
>> +		struct vb2_v4l2_buffer *vbuf;
>> +
>> +		vb = vb2_get_buffer(vq, i);
>> +		if (!vb)
>> +			continue;
>>  
>>  		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>  			continue;
>> +
>> +		vbuf = to_vb2_v4l2_buffer(vb);
>> +
>>  		num = scnprintf(str, sizeof(str),
>>  				"capture[%2d] state = %10s, %8s\n",
>>  				i, vb2_stat_name[vb->state],
>> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> index 0051f372a66c..ea37069ba355 100644
>> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>  		return -EINVAL;
>>  	}
>>  
>> -	vb = vq->bufs[buf->index];
>> +	vb = vb2_get_buffer(vq, buf->index);
>> +	if (!vb) {
>> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
>> +		return -EINVAL;
>> +	}
>>  	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>>  	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>>  
>> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> index cf16cf2807f0..6532a69f1fa8 100644
>> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>>  
>>  	/* update internal buffer's width/height */
>>  	for (i = 0; i < vq->num_buffers; i++) {
>> -		if (vb == vq->bufs[i]) {
>> +		if (vb == vb2_get_buffer(vq, i)) {
>>  			instance->dpb[i].width = w;
>>  			instance->dpb[i].height = h;
>>  			break;
>> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> index 3a848ca32a0e..326be09bdb55 100644
>> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>  		}
>>  
>>  		vb2_buf = vb2_get_buffer(vq, buf->index);
>> +		if (!vb2_buf) {
>> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
>> +			return -EINVAL;
>> +		}
>>  		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>>  		stream->bytesused = buf->bytesused;
>>  	}
>> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
>> index 318d675e5668..ba20ea998d19 100644
>> --- a/drivers/media/test-drivers/visl/visl-dec.c
>> +++ b/drivers/media/test-drivers/visl/visl-dec.c
>> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>  	for (i = 0; i < out_q->num_buffers; i++) {
>>  		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>>  		u32 old_len = len;
>> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
>> +		struct vb2_buffer *vb2;
>> +		char *q_status;
>> +
>> +		vb2 = vb2_get_buffer(out_q, i);
>> +		if (!vb2)
>> +			continue;
>> +
>> +		q_status = visl_get_vb2_state(vb2->state);
>>  
>>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>  				 entry, i, q_status,
>> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
>> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>>  
>> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
>> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>>  					   &buf[len],
>>  					   TPG_STR_BUF_SZ - len);
>>  
>> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>  	len = 0;
>>  	for (i = 0; i < cap_q->num_buffers; i++) {
>>  		u32 old_len = len;
>> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
>> +		struct vb2_buffer *vb2;
>> +		char *q_status;
>> +
>> +		vb2 = vb2_get_buffer(cap_q, i);
>> +		if (!vb2)
>> +			continue;
>> +
>> +		q_status = visl_get_vb2_state(vb2->state);
>>  
>>  		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>  				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
>> -				 cap_q->bufs[i]->index, q_status,
>> -				 cap_q->bufs[i]->timestamp,
>> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
>> +				 vb2->index, q_status,
>> +				 vb2->timestamp,
>> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>>  
>>  		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>>  		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
>> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> index 384f31fc66c5..8df301ab41ad 100644
>> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>>  	if (ret)
>>  		return ret;
>>  
>> -	vb = pipe->vb_queue.bufs[buf->index];
>> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>>  	frame = vb_to_frame(vb);
>>  
>>  	buf->reserved = asd->frame_status[buf->index];
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 04/10] media: verisilicon: Refactor postprocessor to store more buffers
  2023-07-05 12:10   ` Benjamin Gaignard
  (?)
@ 2023-08-21 14:38     ` Hans Verkuil
  -1 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:38 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> Since vb2 queue can store than VB2_MAX_FRAME buffers postprocessor
> buffer storage must be capable to store more buffers too.
> Change static dec_q array to allocated array to be capable to store
> up to queue 'max_allowed_buffers'.

Is there are reason to allocate this dynamically instead of keeping it
as an array of 64 elements? It takes a bit more memory, but it avoids
having to allocate extra memory as well.

And how was the new value of max 64 buffers calculated? What is the
reasoning behind it?

Regards,

	Hans

> Keep allocating queue 'num_buffers' at queue setup time but also allows
> to allocate postprocessors buffers on the fly.
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  drivers/media/platform/verisilicon/hantro.h   |   7 +-
>  .../media/platform/verisilicon/hantro_drv.c   |   4 +-
>  .../media/platform/verisilicon/hantro_hw.h    |   2 +-
>  .../platform/verisilicon/hantro_postproc.c    | 103 ++++++++++++++----
>  .../media/platform/verisilicon/hantro_v4l2.c  |   2 +-
>  5 files changed, 93 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
> index 2989ebc631cc..c8a3cf10cc64 100644
> --- a/drivers/media/platform/verisilicon/hantro.h
> +++ b/drivers/media/platform/verisilicon/hantro.h
> @@ -461,11 +461,14 @@ hantro_get_dst_buf(struct hantro_ctx *ctx)
>  bool hantro_needs_postproc(const struct hantro_ctx *ctx,
>  			   const struct hantro_fmt *fmt);
>  
> +dma_addr_t
> +hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index);
> +
>  static inline dma_addr_t
>  hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
>  {
>  	if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
> -		return ctx->postproc.dec_q[vb->index].dma;
> +		return hantro_postproc_get_dec_buf_addr(ctx, vb->index);
>  	return vb2_dma_contig_plane_dma_addr(vb, 0);
>  }
>  
> @@ -477,8 +480,8 @@ vb2_to_hantro_decoded_buf(struct vb2_buffer *buf)
>  
>  void hantro_postproc_disable(struct hantro_ctx *ctx);
>  void hantro_postproc_enable(struct hantro_ctx *ctx);
> +int hantro_postproc_init(struct hantro_ctx *ctx);
>  void hantro_postproc_free(struct hantro_ctx *ctx);
> -int hantro_postproc_alloc(struct hantro_ctx *ctx);
>  int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
>  				   struct v4l2_frmsizeenum *fsize);
>  
> diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
> index 09c74a573ddb..d908559817ce 100644
> --- a/drivers/media/platform/verisilicon/hantro_drv.c
> +++ b/drivers/media/platform/verisilicon/hantro_drv.c
> @@ -234,8 +234,10 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
>  	 * The Kernel needs access to the JPEG destination buffer for the
>  	 * JPEG encoder to fill in the JPEG headers.
>  	 */
> -	if (!ctx->is_encoder)
> +	if (!ctx->is_encoder) {
>  		dst_vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
> +		dst_vq->max_allowed_buffers = 64;
> +	}
>  
>  	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
>  	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
> diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
> index e83f0c523a30..6fd6c9d53cec 100644
> --- a/drivers/media/platform/verisilicon/hantro_hw.h
> +++ b/drivers/media/platform/verisilicon/hantro_hw.h
> @@ -253,7 +253,7 @@ struct hantro_vp9_dec_hw_ctx {
>   * @dec_q:		References buffers, in decoder format.
>   */
>  struct hantro_postproc_ctx {
> -	struct hantro_aux_buf dec_q[VB2_MAX_FRAME];
> +	struct hantro_aux_buf *dec_q;
>  };
>  
>  /**
> diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
> index 6437423ccf3a..9dfe3141a398 100644
> --- a/drivers/media/platform/verisilicon/hantro_postproc.c
> +++ b/drivers/media/platform/verisilicon/hantro_postproc.c
> @@ -173,9 +173,11 @@ static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx,
>  void hantro_postproc_free(struct hantro_ctx *ctx)
>  {
>  	struct hantro_dev *vpu = ctx->dev;
> +	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> +	struct vb2_queue *queue = &m2m_ctx->cap_q_ctx.q;
>  	unsigned int i;
>  
> -	for (i = 0; i < VB2_MAX_FRAME; ++i) {
> +	for (i = 0; i < queue->max_allowed_buffers; ++i) {
>  		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
>  
>  		if (priv->cpu) {
> @@ -184,22 +186,21 @@ void hantro_postproc_free(struct hantro_ctx *ctx)
>  			priv->cpu = NULL;
>  		}
>  	}
> +	kfree(ctx->postproc.dec_q);
> +	ctx->postproc.dec_q = NULL;
>  }
>  
> -int hantro_postproc_alloc(struct hantro_ctx *ctx)
> +static unsigned int hantro_postproc_buffer_size(struct hantro_ctx *ctx)
>  {
> -	struct hantro_dev *vpu = ctx->dev;
> -	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> -	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
> -	unsigned int num_buffers = cap_queue->num_buffers;
>  	struct v4l2_pix_format_mplane pix_mp;
>  	const struct hantro_fmt *fmt;
> -	unsigned int i, buf_size;
> +	unsigned int buf_size;
>  
>  	/* this should always pick native format */
>  	fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth);
>  	if (!fmt)
> -		return -EINVAL;
> +		return 0;
> +
>  	v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width,
>  			    ctx->src_fmt.height);
>  
> @@ -214,23 +215,85 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
>  		buf_size += hantro_hevc_mv_size(pix_mp.width,
>  						pix_mp.height);
>  
> -	for (i = 0; i < num_buffers; ++i) {
> -		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
> +	return buf_size;
> +}
> +
> +static int hantro_postproc_alloc(struct hantro_ctx *ctx, int index)
> +{
> +	struct hantro_dev *vpu = ctx->dev;
> +	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
> +	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
> +
> +	if (!buf_size)
> +		return -EINVAL;
> +
> +	/*
> +	 * The buffers on this queue are meant as intermediate
> +	 * buffers for the decoder, so no mapping is needed.
> +	 */
> +	priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
> +	priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
> +				    GFP_KERNEL, priv->attrs);
> +	if (!priv->cpu)
> +		return -ENOMEM;
> +	priv->size = buf_size;
> +
> +	return 0;
> +}
> +
> +int hantro_postproc_init(struct hantro_ctx *ctx)
> +{
> +	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> +	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
> +	unsigned int num_buffers = cap_queue->num_buffers;
> +	unsigned int i;
> +	int ret;
>  
> -		/*
> -		 * The buffers on this queue are meant as intermediate
> -		 * buffers for the decoder, so no mapping is needed.
> -		 */
> -		priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
> -		priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
> -					    GFP_KERNEL, priv->attrs);
> -		if (!priv->cpu)
> -			return -ENOMEM;
> -		priv->size = buf_size;
> +	if (!ctx->postproc.dec_q)
> +		ctx->postproc.dec_q = kcalloc(cap_queue->max_allowed_buffers,
> +					      sizeof(*ctx->postproc.dec_q),
> +					      GFP_KERNEL);
> +
> +	if (!ctx->postproc.dec_q)
> +		return -EINVAL;
> +
> +	for (i = 0; i < num_buffers; i++) {
> +		ret = hantro_postproc_alloc(ctx, i);
> +		if (ret)
> +			return ret;
>  	}
> +
>  	return 0;
>  }
>  
> +dma_addr_t
> +hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index)
> +{
> +	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
> +	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
> +	struct hantro_dev *vpu = ctx->dev;
> +	int ret;
> +
> +	if (priv->size < buf_size && priv->cpu) {
> +		/* buffer is too small, release it */
> +		dma_free_attrs(vpu->dev, priv->size, priv->cpu,
> +			       priv->dma, priv->attrs);
> +		priv->cpu = NULL;
> +	}
> +
> +	if (!priv->cpu) {
> +		/* buffer not already allocated, try getting a new one */
> +		ret = hantro_postproc_alloc(ctx, index);
> +		if (ret)
> +			return 0;
> +	}
> +
> +	if (!priv->cpu)
> +		return 0;
> +
> +	return priv->dma;
> +}
> +
>  static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
>  {
>  	struct hantro_dev *vpu = ctx->dev;
> diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
> index 61cfaaf4e927..898e8763d63a 100644
> --- a/drivers/media/platform/verisilicon/hantro_v4l2.c
> +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
> @@ -897,7 +897,7 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
>  		}
>  
>  		if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) {
> -			ret = hantro_postproc_alloc(ctx);
> +			ret = hantro_postproc_init(ctx);
>  			if (ret)
>  				goto err_codec_exit;
>  		}


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 04/10] media: verisilicon: Refactor postprocessor to store more buffers
@ 2023-08-21 14:38     ` Hans Verkuil
  0 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:38 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> Since vb2 queue can store than VB2_MAX_FRAME buffers postprocessor
> buffer storage must be capable to store more buffers too.
> Change static dec_q array to allocated array to be capable to store
> up to queue 'max_allowed_buffers'.

Is there are reason to allocate this dynamically instead of keeping it
as an array of 64 elements? It takes a bit more memory, but it avoids
having to allocate extra memory as well.

And how was the new value of max 64 buffers calculated? What is the
reasoning behind it?

Regards,

	Hans

> Keep allocating queue 'num_buffers' at queue setup time but also allows
> to allocate postprocessors buffers on the fly.
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  drivers/media/platform/verisilicon/hantro.h   |   7 +-
>  .../media/platform/verisilicon/hantro_drv.c   |   4 +-
>  .../media/platform/verisilicon/hantro_hw.h    |   2 +-
>  .../platform/verisilicon/hantro_postproc.c    | 103 ++++++++++++++----
>  .../media/platform/verisilicon/hantro_v4l2.c  |   2 +-
>  5 files changed, 93 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
> index 2989ebc631cc..c8a3cf10cc64 100644
> --- a/drivers/media/platform/verisilicon/hantro.h
> +++ b/drivers/media/platform/verisilicon/hantro.h
> @@ -461,11 +461,14 @@ hantro_get_dst_buf(struct hantro_ctx *ctx)
>  bool hantro_needs_postproc(const struct hantro_ctx *ctx,
>  			   const struct hantro_fmt *fmt);
>  
> +dma_addr_t
> +hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index);
> +
>  static inline dma_addr_t
>  hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
>  {
>  	if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
> -		return ctx->postproc.dec_q[vb->index].dma;
> +		return hantro_postproc_get_dec_buf_addr(ctx, vb->index);
>  	return vb2_dma_contig_plane_dma_addr(vb, 0);
>  }
>  
> @@ -477,8 +480,8 @@ vb2_to_hantro_decoded_buf(struct vb2_buffer *buf)
>  
>  void hantro_postproc_disable(struct hantro_ctx *ctx);
>  void hantro_postproc_enable(struct hantro_ctx *ctx);
> +int hantro_postproc_init(struct hantro_ctx *ctx);
>  void hantro_postproc_free(struct hantro_ctx *ctx);
> -int hantro_postproc_alloc(struct hantro_ctx *ctx);
>  int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
>  				   struct v4l2_frmsizeenum *fsize);
>  
> diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
> index 09c74a573ddb..d908559817ce 100644
> --- a/drivers/media/platform/verisilicon/hantro_drv.c
> +++ b/drivers/media/platform/verisilicon/hantro_drv.c
> @@ -234,8 +234,10 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
>  	 * The Kernel needs access to the JPEG destination buffer for the
>  	 * JPEG encoder to fill in the JPEG headers.
>  	 */
> -	if (!ctx->is_encoder)
> +	if (!ctx->is_encoder) {
>  		dst_vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
> +		dst_vq->max_allowed_buffers = 64;
> +	}
>  
>  	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
>  	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
> diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
> index e83f0c523a30..6fd6c9d53cec 100644
> --- a/drivers/media/platform/verisilicon/hantro_hw.h
> +++ b/drivers/media/platform/verisilicon/hantro_hw.h
> @@ -253,7 +253,7 @@ struct hantro_vp9_dec_hw_ctx {
>   * @dec_q:		References buffers, in decoder format.
>   */
>  struct hantro_postproc_ctx {
> -	struct hantro_aux_buf dec_q[VB2_MAX_FRAME];
> +	struct hantro_aux_buf *dec_q;
>  };
>  
>  /**
> diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
> index 6437423ccf3a..9dfe3141a398 100644
> --- a/drivers/media/platform/verisilicon/hantro_postproc.c
> +++ b/drivers/media/platform/verisilicon/hantro_postproc.c
> @@ -173,9 +173,11 @@ static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx,
>  void hantro_postproc_free(struct hantro_ctx *ctx)
>  {
>  	struct hantro_dev *vpu = ctx->dev;
> +	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> +	struct vb2_queue *queue = &m2m_ctx->cap_q_ctx.q;
>  	unsigned int i;
>  
> -	for (i = 0; i < VB2_MAX_FRAME; ++i) {
> +	for (i = 0; i < queue->max_allowed_buffers; ++i) {
>  		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
>  
>  		if (priv->cpu) {
> @@ -184,22 +186,21 @@ void hantro_postproc_free(struct hantro_ctx *ctx)
>  			priv->cpu = NULL;
>  		}
>  	}
> +	kfree(ctx->postproc.dec_q);
> +	ctx->postproc.dec_q = NULL;
>  }
>  
> -int hantro_postproc_alloc(struct hantro_ctx *ctx)
> +static unsigned int hantro_postproc_buffer_size(struct hantro_ctx *ctx)
>  {
> -	struct hantro_dev *vpu = ctx->dev;
> -	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> -	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
> -	unsigned int num_buffers = cap_queue->num_buffers;
>  	struct v4l2_pix_format_mplane pix_mp;
>  	const struct hantro_fmt *fmt;
> -	unsigned int i, buf_size;
> +	unsigned int buf_size;
>  
>  	/* this should always pick native format */
>  	fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth);
>  	if (!fmt)
> -		return -EINVAL;
> +		return 0;
> +
>  	v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width,
>  			    ctx->src_fmt.height);
>  
> @@ -214,23 +215,85 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
>  		buf_size += hantro_hevc_mv_size(pix_mp.width,
>  						pix_mp.height);
>  
> -	for (i = 0; i < num_buffers; ++i) {
> -		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
> +	return buf_size;
> +}
> +
> +static int hantro_postproc_alloc(struct hantro_ctx *ctx, int index)
> +{
> +	struct hantro_dev *vpu = ctx->dev;
> +	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
> +	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
> +
> +	if (!buf_size)
> +		return -EINVAL;
> +
> +	/*
> +	 * The buffers on this queue are meant as intermediate
> +	 * buffers for the decoder, so no mapping is needed.
> +	 */
> +	priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
> +	priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
> +				    GFP_KERNEL, priv->attrs);
> +	if (!priv->cpu)
> +		return -ENOMEM;
> +	priv->size = buf_size;
> +
> +	return 0;
> +}
> +
> +int hantro_postproc_init(struct hantro_ctx *ctx)
> +{
> +	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> +	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
> +	unsigned int num_buffers = cap_queue->num_buffers;
> +	unsigned int i;
> +	int ret;
>  
> -		/*
> -		 * The buffers on this queue are meant as intermediate
> -		 * buffers for the decoder, so no mapping is needed.
> -		 */
> -		priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
> -		priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
> -					    GFP_KERNEL, priv->attrs);
> -		if (!priv->cpu)
> -			return -ENOMEM;
> -		priv->size = buf_size;
> +	if (!ctx->postproc.dec_q)
> +		ctx->postproc.dec_q = kcalloc(cap_queue->max_allowed_buffers,
> +					      sizeof(*ctx->postproc.dec_q),
> +					      GFP_KERNEL);
> +
> +	if (!ctx->postproc.dec_q)
> +		return -EINVAL;
> +
> +	for (i = 0; i < num_buffers; i++) {
> +		ret = hantro_postproc_alloc(ctx, i);
> +		if (ret)
> +			return ret;
>  	}
> +
>  	return 0;
>  }
>  
> +dma_addr_t
> +hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index)
> +{
> +	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
> +	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
> +	struct hantro_dev *vpu = ctx->dev;
> +	int ret;
> +
> +	if (priv->size < buf_size && priv->cpu) {
> +		/* buffer is too small, release it */
> +		dma_free_attrs(vpu->dev, priv->size, priv->cpu,
> +			       priv->dma, priv->attrs);
> +		priv->cpu = NULL;
> +	}
> +
> +	if (!priv->cpu) {
> +		/* buffer not already allocated, try getting a new one */
> +		ret = hantro_postproc_alloc(ctx, index);
> +		if (ret)
> +			return 0;
> +	}
> +
> +	if (!priv->cpu)
> +		return 0;
> +
> +	return priv->dma;
> +}
> +
>  static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
>  {
>  	struct hantro_dev *vpu = ctx->dev;
> diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
> index 61cfaaf4e927..898e8763d63a 100644
> --- a/drivers/media/platform/verisilicon/hantro_v4l2.c
> +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
> @@ -897,7 +897,7 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
>  		}
>  
>  		if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) {
> -			ret = hantro_postproc_alloc(ctx);
> +			ret = hantro_postproc_init(ctx);
>  			if (ret)
>  				goto err_codec_exit;
>  		}


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 04/10] media: verisilicon: Refactor postprocessor to store more buffers
@ 2023-08-21 14:38     ` Hans Verkuil
  0 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:38 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> Since vb2 queue can store than VB2_MAX_FRAME buffers postprocessor
> buffer storage must be capable to store more buffers too.
> Change static dec_q array to allocated array to be capable to store
> up to queue 'max_allowed_buffers'.

Is there are reason to allocate this dynamically instead of keeping it
as an array of 64 elements? It takes a bit more memory, but it avoids
having to allocate extra memory as well.

And how was the new value of max 64 buffers calculated? What is the
reasoning behind it?

Regards,

	Hans

> Keep allocating queue 'num_buffers' at queue setup time but also allows
> to allocate postprocessors buffers on the fly.
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  drivers/media/platform/verisilicon/hantro.h   |   7 +-
>  .../media/platform/verisilicon/hantro_drv.c   |   4 +-
>  .../media/platform/verisilicon/hantro_hw.h    |   2 +-
>  .../platform/verisilicon/hantro_postproc.c    | 103 ++++++++++++++----
>  .../media/platform/verisilicon/hantro_v4l2.c  |   2 +-
>  5 files changed, 93 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
> index 2989ebc631cc..c8a3cf10cc64 100644
> --- a/drivers/media/platform/verisilicon/hantro.h
> +++ b/drivers/media/platform/verisilicon/hantro.h
> @@ -461,11 +461,14 @@ hantro_get_dst_buf(struct hantro_ctx *ctx)
>  bool hantro_needs_postproc(const struct hantro_ctx *ctx,
>  			   const struct hantro_fmt *fmt);
>  
> +dma_addr_t
> +hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index);
> +
>  static inline dma_addr_t
>  hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
>  {
>  	if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
> -		return ctx->postproc.dec_q[vb->index].dma;
> +		return hantro_postproc_get_dec_buf_addr(ctx, vb->index);
>  	return vb2_dma_contig_plane_dma_addr(vb, 0);
>  }
>  
> @@ -477,8 +480,8 @@ vb2_to_hantro_decoded_buf(struct vb2_buffer *buf)
>  
>  void hantro_postproc_disable(struct hantro_ctx *ctx);
>  void hantro_postproc_enable(struct hantro_ctx *ctx);
> +int hantro_postproc_init(struct hantro_ctx *ctx);
>  void hantro_postproc_free(struct hantro_ctx *ctx);
> -int hantro_postproc_alloc(struct hantro_ctx *ctx);
>  int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
>  				   struct v4l2_frmsizeenum *fsize);
>  
> diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
> index 09c74a573ddb..d908559817ce 100644
> --- a/drivers/media/platform/verisilicon/hantro_drv.c
> +++ b/drivers/media/platform/verisilicon/hantro_drv.c
> @@ -234,8 +234,10 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
>  	 * The Kernel needs access to the JPEG destination buffer for the
>  	 * JPEG encoder to fill in the JPEG headers.
>  	 */
> -	if (!ctx->is_encoder)
> +	if (!ctx->is_encoder) {
>  		dst_vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
> +		dst_vq->max_allowed_buffers = 64;
> +	}
>  
>  	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
>  	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
> diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
> index e83f0c523a30..6fd6c9d53cec 100644
> --- a/drivers/media/platform/verisilicon/hantro_hw.h
> +++ b/drivers/media/platform/verisilicon/hantro_hw.h
> @@ -253,7 +253,7 @@ struct hantro_vp9_dec_hw_ctx {
>   * @dec_q:		References buffers, in decoder format.
>   */
>  struct hantro_postproc_ctx {
> -	struct hantro_aux_buf dec_q[VB2_MAX_FRAME];
> +	struct hantro_aux_buf *dec_q;
>  };
>  
>  /**
> diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
> index 6437423ccf3a..9dfe3141a398 100644
> --- a/drivers/media/platform/verisilicon/hantro_postproc.c
> +++ b/drivers/media/platform/verisilicon/hantro_postproc.c
> @@ -173,9 +173,11 @@ static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx,
>  void hantro_postproc_free(struct hantro_ctx *ctx)
>  {
>  	struct hantro_dev *vpu = ctx->dev;
> +	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> +	struct vb2_queue *queue = &m2m_ctx->cap_q_ctx.q;
>  	unsigned int i;
>  
> -	for (i = 0; i < VB2_MAX_FRAME; ++i) {
> +	for (i = 0; i < queue->max_allowed_buffers; ++i) {
>  		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
>  
>  		if (priv->cpu) {
> @@ -184,22 +186,21 @@ void hantro_postproc_free(struct hantro_ctx *ctx)
>  			priv->cpu = NULL;
>  		}
>  	}
> +	kfree(ctx->postproc.dec_q);
> +	ctx->postproc.dec_q = NULL;
>  }
>  
> -int hantro_postproc_alloc(struct hantro_ctx *ctx)
> +static unsigned int hantro_postproc_buffer_size(struct hantro_ctx *ctx)
>  {
> -	struct hantro_dev *vpu = ctx->dev;
> -	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> -	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
> -	unsigned int num_buffers = cap_queue->num_buffers;
>  	struct v4l2_pix_format_mplane pix_mp;
>  	const struct hantro_fmt *fmt;
> -	unsigned int i, buf_size;
> +	unsigned int buf_size;
>  
>  	/* this should always pick native format */
>  	fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth);
>  	if (!fmt)
> -		return -EINVAL;
> +		return 0;
> +
>  	v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width,
>  			    ctx->src_fmt.height);
>  
> @@ -214,23 +215,85 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
>  		buf_size += hantro_hevc_mv_size(pix_mp.width,
>  						pix_mp.height);
>  
> -	for (i = 0; i < num_buffers; ++i) {
> -		struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
> +	return buf_size;
> +}
> +
> +static int hantro_postproc_alloc(struct hantro_ctx *ctx, int index)
> +{
> +	struct hantro_dev *vpu = ctx->dev;
> +	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
> +	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
> +
> +	if (!buf_size)
> +		return -EINVAL;
> +
> +	/*
> +	 * The buffers on this queue are meant as intermediate
> +	 * buffers for the decoder, so no mapping is needed.
> +	 */
> +	priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
> +	priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
> +				    GFP_KERNEL, priv->attrs);
> +	if (!priv->cpu)
> +		return -ENOMEM;
> +	priv->size = buf_size;
> +
> +	return 0;
> +}
> +
> +int hantro_postproc_init(struct hantro_ctx *ctx)
> +{
> +	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
> +	struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q;
> +	unsigned int num_buffers = cap_queue->num_buffers;
> +	unsigned int i;
> +	int ret;
>  
> -		/*
> -		 * The buffers on this queue are meant as intermediate
> -		 * buffers for the decoder, so no mapping is needed.
> -		 */
> -		priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING;
> -		priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma,
> -					    GFP_KERNEL, priv->attrs);
> -		if (!priv->cpu)
> -			return -ENOMEM;
> -		priv->size = buf_size;
> +	if (!ctx->postproc.dec_q)
> +		ctx->postproc.dec_q = kcalloc(cap_queue->max_allowed_buffers,
> +					      sizeof(*ctx->postproc.dec_q),
> +					      GFP_KERNEL);
> +
> +	if (!ctx->postproc.dec_q)
> +		return -EINVAL;
> +
> +	for (i = 0; i < num_buffers; i++) {
> +		ret = hantro_postproc_alloc(ctx, i);
> +		if (ret)
> +			return ret;
>  	}
> +
>  	return 0;
>  }
>  
> +dma_addr_t
> +hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index)
> +{
> +	struct hantro_aux_buf *priv = &ctx->postproc.dec_q[index];
> +	unsigned int buf_size = hantro_postproc_buffer_size(ctx);
> +	struct hantro_dev *vpu = ctx->dev;
> +	int ret;
> +
> +	if (priv->size < buf_size && priv->cpu) {
> +		/* buffer is too small, release it */
> +		dma_free_attrs(vpu->dev, priv->size, priv->cpu,
> +			       priv->dma, priv->attrs);
> +		priv->cpu = NULL;
> +	}
> +
> +	if (!priv->cpu) {
> +		/* buffer not already allocated, try getting a new one */
> +		ret = hantro_postproc_alloc(ctx, index);
> +		if (ret)
> +			return 0;
> +	}
> +
> +	if (!priv->cpu)
> +		return 0;
> +
> +	return priv->dma;
> +}
> +
>  static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
>  {
>  	struct hantro_dev *vpu = ctx->dev;
> diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
> index 61cfaaf4e927..898e8763d63a 100644
> --- a/drivers/media/platform/verisilicon/hantro_v4l2.c
> +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
> @@ -897,7 +897,7 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
>  		}
>  
>  		if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) {
> -			ret = hantro_postproc_alloc(ctx);
> +			ret = hantro_postproc_init(ctx);
>  			if (ret)
>  				goto err_codec_exit;
>  		}


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
  2023-07-05 12:10   ` Benjamin Gaignard
  (?)
@ 2023-08-21 14:41     ` Hans Verkuil
  -1 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:41 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> Store computed values of chroma and motion vectors offset because
> they depends on width and height values which change if the resolution
> change.

Is this a bug fix? Does this patch belong in this series?

Same actually for the next few verisilicon patches. Shouldn't they be
part of a separate 'fixes' patch series? It's confusing to see them
in this series.

Regards,

	Hans

> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  drivers/media/platform/verisilicon/hantro.h            | 2 ++
>  drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
> index c8a3cf10cc64..53be00142473 100644
> --- a/drivers/media/platform/verisilicon/hantro.h
> +++ b/drivers/media/platform/verisilicon/hantro.h
> @@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
>  	/* Info needed when the decoded frame serves as a reference frame. */
>  	unsigned short width;
>  	unsigned short height;
> +	size_t chroma_offset;
> +	size_t mv_offset;
>  	u32 bit_depth : 4;
>  };
>  
> diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> index 6fc4b555517f..6db1c32fce4d 100644
> --- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> +++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> @@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
>  
>  	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>  	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
> +	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
>  
>  	mv_addr = luma_addr + mv_offset(ctx, dec_params);
>  	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
> +	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
>  }
>  
>  struct hantro_vp9_ref_reg {
> @@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
>  	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
>  	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
>  
> -	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
> +	chroma_addr = luma_addr + buf->vp9.chroma_offset;
>  	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
>  }
>  
> @@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
>  	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
>  
>  	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
> -		  mv_offset(ctx, dec_params);
> +		  mv_ref->vp9.mv_offset;
>  	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
>  
>  	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
@ 2023-08-21 14:41     ` Hans Verkuil
  0 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:41 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> Store computed values of chroma and motion vectors offset because
> they depends on width and height values which change if the resolution
> change.

Is this a bug fix? Does this patch belong in this series?

Same actually for the next few verisilicon patches. Shouldn't they be
part of a separate 'fixes' patch series? It's confusing to see them
in this series.

Regards,

	Hans

> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  drivers/media/platform/verisilicon/hantro.h            | 2 ++
>  drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
> index c8a3cf10cc64..53be00142473 100644
> --- a/drivers/media/platform/verisilicon/hantro.h
> +++ b/drivers/media/platform/verisilicon/hantro.h
> @@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
>  	/* Info needed when the decoded frame serves as a reference frame. */
>  	unsigned short width;
>  	unsigned short height;
> +	size_t chroma_offset;
> +	size_t mv_offset;
>  	u32 bit_depth : 4;
>  };
>  
> diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> index 6fc4b555517f..6db1c32fce4d 100644
> --- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> +++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> @@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
>  
>  	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>  	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
> +	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
>  
>  	mv_addr = luma_addr + mv_offset(ctx, dec_params);
>  	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
> +	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
>  }
>  
>  struct hantro_vp9_ref_reg {
> @@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
>  	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
>  	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
>  
> -	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
> +	chroma_addr = luma_addr + buf->vp9.chroma_offset;
>  	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
>  }
>  
> @@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
>  	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
>  
>  	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
> -		  mv_offset(ctx, dec_params);
> +		  mv_ref->vp9.mv_offset;
>  	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
>  
>  	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
@ 2023-08-21 14:41     ` Hans Verkuil
  0 siblings, 0 replies; 51+ messages in thread
From: Hans Verkuil @ 2023-08-21 14:41 UTC (permalink / raw)
  To: Benjamin Gaignard, mchehab, tfiga, m.szyprowski, ming.qian,
	ezequiel, p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel

On 05/07/2023 14:10, Benjamin Gaignard wrote:
> Store computed values of chroma and motion vectors offset because
> they depends on width and height values which change if the resolution
> change.

Is this a bug fix? Does this patch belong in this series?

Same actually for the next few verisilicon patches. Shouldn't they be
part of a separate 'fixes' patch series? It's confusing to see them
in this series.

Regards,

	Hans

> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  drivers/media/platform/verisilicon/hantro.h            | 2 ++
>  drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
> index c8a3cf10cc64..53be00142473 100644
> --- a/drivers/media/platform/verisilicon/hantro.h
> +++ b/drivers/media/platform/verisilicon/hantro.h
> @@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
>  	/* Info needed when the decoded frame serves as a reference frame. */
>  	unsigned short width;
>  	unsigned short height;
> +	size_t chroma_offset;
> +	size_t mv_offset;
>  	u32 bit_depth : 4;
>  };
>  
> diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> index 6fc4b555517f..6db1c32fce4d 100644
> --- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> +++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
> @@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
>  
>  	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>  	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
> +	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
>  
>  	mv_addr = luma_addr + mv_offset(ctx, dec_params);
>  	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
> +	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
>  }
>  
>  struct hantro_vp9_ref_reg {
> @@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
>  	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
>  	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
>  
> -	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
> +	chroma_addr = luma_addr + buf->vp9.chroma_offset;
>  	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
>  }
>  
> @@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
>  	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
>  
>  	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
> -		  mv_offset(ctx, dec_params);
> +		  mv_ref->vp9.mv_offset;
>  	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
>  
>  	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
  2023-08-21 14:31       ` Hans Verkuil
  (?)
@ 2023-08-22 12:49         ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-08-22 12:49 UTC (permalink / raw)
  To: Hans Verkuil, mchehab, tfiga, m.szyprowski, ming.qian, ezequiel,
	p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel


Le 21/08/2023 à 16:31, Hans Verkuil a écrit :
> On 21/08/2023 16:24, Hans Verkuil wrote:
>> Hi Benjamin,
>>
>> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>>> The first step before changing how vb2 buffers are stored into queue
>>> is to avoid direct access to bufs arrays.
>>>
>>> This patch adds 2 helpers functions to add and remove vb2 buffers
>>> from a queue. With these 2 and vb2_get_buffer(), bufs field of
>>> struct vb2_queue becomes like a private member of the structure.
>>>
>>> After each call to vb2_get_buffer() we need to be sure that we get
>>> a valid pointer so check the return value of all of them.
>>>
>>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>>> ---
>>>   .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>>>   .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>>>   drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>>>   .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>>>   .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>>>   drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>>>   drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>>>   .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>>>   8 files changed, 240 insertions(+), 67 deletions(-)
>>>
>>> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
>>> index cf6727d9c81f..42fd3984c2bc 100644
>>> --- a/drivers/media/common/videobuf2/videobuf2-core.c
>>> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
>>> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>>>   	unsigned long off = 0;
>>>   
>>>   	if (vb->index) {
>>> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
>>> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
>>> +		struct vb2_buffer *prev;
>>> +		struct vb2_plane *p;
>>> +
>>> +		prev = vb2_get_buffer(q, vb->index - 1);
>>> +		if (!prev) {
>>> +			dprintk(q, 1, "can't find the requested buffer\n");
>>> +			return;
>>> +		}
>>> +
>>> +		p = &prev->planes[prev->num_planes - 1];
>>>   
>>>   		off = PAGE_ALIGN(p->m.offset + p->length);
>> This does not work. Before this patch there should be a patch that changes
>> the way the offset is determined since it affects this functionality.
>>
>> __setup_offsets() fills in the m.offset field for each plane in the buffer.
>> In the current code it starts with 0 for the first buffer, adds the length
>> for each plane to it, and for the next buffer it continues doing that. So
>> the offset for a plane is the total length of all preceding buffers and planes.
>>
>> In addition, bit 30 of the offset field is used to signal if it is a capture
>> or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
>> define).
>>
>> In addition, the offset has to be page aligned, so the lower 12 bits are 0.
>> That leaves only 32-1-12 = 19 bits for the offset.
>>
>> Since we allow 8 planes per buffer, that means that we can't have more than
>> 65536 buffers given a 32 bit offset.
>>
>> I think the way m.offset is calculated should change drastically: it should
>> instead be something like this:
>>
>> m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;
>>
>> and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.
>>
>> Parsing the offset would be much simpler as well, since you can just decode
>> the index and plane numbers directly rather than using the cumbersome
>> __find_plane_by_offset() function.
>>
>> The currently mechanism will fail completely once you can delete buffers,
>> and this proposal will simplify and improve the code, so I think it should
>> be done first.
> I could have saved myself some work if I read the other patches first.
>
> I see that patch 3/10 addresses this. But for the v5, just move that patch
> to the beginning of the series.

I will try to do that but these patches hit the same pieces of code so changing the order isn't that simple.

>
> I would also suggest changing DST_QUEUE_OFF_BASE to use bit 31 to allow for
> 16 bits instead of 15 for the buffer index.

DST_QUEUE_OFF_BASE is used with PAGE_SHIFT in v4l2-mem2mem and s5p_mfc in mmap/unmap functions.
I'm bit afraid to change that.
With my change each queue can store up to 0xffff (65535) buffers.
Sound large enough for me ;-)

Benjamin

>
> Regards,
>
> 	Hans
>
>> Regards,
>>
>> 	Hans
>>
>>>   	}
>>> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>>>   		vb->skip_cache_sync_on_finish = 1;
>>>   }
>>>   
>>> +/**
>>> + * vb2_queue_add_buffer() - add a buffer to a queue
>>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>>> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
>>> + * @index: index where add vb2_buffer in the queue
>>> + */
>>> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
>>> +{
>>> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
>>> +		q->bufs[index] = vb;
>>> +		vb->index = index;
>>> +		vb->vb2_queue = q;
>>> +		return true;
>>> +	}
>>> +
>>> +	return false;
>>> +}
>>> +
>>> +/**
>>> + * vb2_queue_remove_buffer() - remove a buffer from a queue
>>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>>> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
>>> + */
>>> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
>>> +{
>>> +	if (vb->index < VB2_MAX_FRAME) {
>>> +		q->bufs[vb->index] = NULL;
>>> +		vb->vb2_queue = NULL;
>>> +	}
>>> +}
>>> +
>>>   /*
>>>    * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>>>    * video buffer memory for all buffers/planes on the queue and initializes the
>>> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   		}
>>>   
>>>   		vb->state = VB2_BUF_STATE_DEQUEUED;
>>> -		vb->vb2_queue = q;
>>>   		vb->num_planes = num_planes;
>>> -		vb->index = q->num_buffers + buffer;
>>>   		vb->type = q->type;
>>>   		vb->memory = memory;
>>>   		init_buffer_cache_hints(q, vb);
>>> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   		}
>>>   		call_void_bufop(q, init_buffer, vb);
>>>   
>>> -		q->bufs[vb->index] = vb;
>>> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
>>> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
>>> +			kfree(vb);
>>> +			break;
>>> +		}
>>>   
>>>   		/* Allocate video buffer memory for the MMAP type */
>>>   		if (memory == VB2_MEMORY_MMAP) {
>>> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   			if (ret) {
>>>   				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>>>   					buffer);
>>> -				q->bufs[vb->index] = NULL;
>>> +				vb2_queue_remove_buffer(q, vb);
>>>   				kfree(vb);
>>>   				break;
>>>   			}
>>> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   				dprintk(q, 1, "buffer %d %p initialization failed\n",
>>>   					buffer, vb);
>>>   				__vb2_buf_mem_free(vb);
>>> -				q->bufs[vb->index] = NULL;
>>> +				vb2_queue_remove_buffer(q, vb);
>>>   				kfree(vb);
>>>   				break;
>>>   			}
>>> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>>   
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		vb = q->bufs[buffer];
>>> +		vb = vb2_get_buffer(q, buffer);
>>>   		if (!vb)
>>>   			continue;
>>>   
>>> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   	/* Call driver-provided cleanup function for each buffer, if provided */
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		struct vb2_buffer *vb = q->bufs[buffer];
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>>   
>>>   		if (vb && vb->planes[0].mem_priv)
>>>   			call_void_vb_qop(vb, buf_cleanup, vb);
>>> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   		q->cnt_unprepare_streaming = 0;
>>>   	}
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		struct vb2_buffer *vb = q->bufs[buffer];
>>> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>>> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>>> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>>> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>>> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>>> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
>>> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>>> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +		bool unbalanced;
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>>> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>>> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>>> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>>> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>>> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
>>> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>>> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>>   
>>>   		if (unbalanced || debug) {
>>>   			pr_info("   counters for queue %p, buffer %d:%s\n",
>>> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   	/* Free vb2 buffers */
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		kfree(q->bufs[buffer]);
>>> -		q->bufs[buffer] = NULL;
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		vb2_queue_remove_buffer(q, vb);
>>> +		kfree(vb);
>>>   	}
>>>   
>>>   	q->num_buffers -= buffers;
>>> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>>   {
>>>   	unsigned int buffer;
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		if (vb2_buffer_in_use(q, vb))
>>>   			return true;
>>>   	}
>>>   	return false;
>>> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>>   
>>>   void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>>>   {
>>> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
>>> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (vb)
>>> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>>>   }
>>>   EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>>>   
>>> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>>>   	struct vb2_buffer *vb;
>>>   	int ret;
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>>   	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>>>   		dprintk(q, 1, "invalid buffer state %s\n",
>>>   			vb2_state_name(vb->state));
>>> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>>   		 * correctly return them to vb2.
>>>   		 */
>>>   		for (i = 0; i < q->num_buffers; ++i) {
>>> -			vb = q->bufs[i];
>>> +			vb = vb2_get_buffer(q, i);
>>> +
>>> +			if (!vb)
>>> +				continue;
>>> +
>>>   			if (vb->state == VB2_BUF_STATE_ACTIVE)
>>>   				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>>>   		}
>>> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>>>   		return -EIO;
>>>   	}
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>>   
>>>   	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>>>   	    q->requires_requests) {
>>> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>>   	 * to vb2 in stop_streaming().
>>>   	 */
>>>   	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
>>> -		for (i = 0; i < q->num_buffers; ++i)
>>> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
>>> +		for (i = 0; i < q->num_buffers; ++i) {
>>> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
>>> +
>>> +			if (!vb)
>>> +				continue;
>>> +
>>> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>>>   				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
>>> -					q->bufs[i]);
>>> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
>>> +					vb);
>>> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>>>   			}
>>> +		}
>>>   		/* Must be zero now */
>>>   		WARN_ON(atomic_read(&q->owned_by_drv_count));
>>>   	}
>>> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>>   	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>>>   	 */
>>>   	for (i = 0; i < q->num_buffers; ++i) {
>>> -		struct vb2_buffer *vb = q->bufs[i];
>>> -		struct media_request *req = vb->req_obj.req;
>>> +		struct vb2_buffer *vb;
>>> +		struct media_request *req;
>>>   
>>> +		vb = vb2_get_buffer(q, i);
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		req = vb->req_obj.req;
>>>   		/*
>>>   		 * If a request is associated with this buffer, then
>>>   		 * call buf_request_cancel() to give the driver to complete()
>>> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>>   	 * return its buffer and plane numbers.
>>>   	 */
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		vb = q->bufs[buffer];
>>> +		vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		for (plane = 0; plane < vb->num_planes; ++plane) {
>>>   			if (vb->planes[plane].m.offset == off) {
>>> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>>   
>>>   	if (plane >= vb->num_planes) {
>>>   		dprintk(q, 1, "buffer plane out of range\n");
>>> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>>   	if (ret)
>>>   		goto unlock;
>>>   
>>> -	vb = q->bufs[buffer];
>>> +	vb = vb2_get_buffer(q, buffer);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		ret = -EINVAL;
>>> +		goto unlock;
>>> +	}
>>>   
>>>   	/*
>>>   	 * MMAP requires page_aligned buffers.
>>> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>>   	if (ret)
>>>   		goto unlock;
>>>   
>>> -	vb = q->bufs[buffer];
>>> +	vb = vb2_get_buffer(q, buffer);
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		ret = -EINVAL;
>>> +		goto unlock;
>>> +	}
>>>   
>>>   	vaddr = vb2_plane_vaddr(vb, plane);
>>>   	mutex_unlock(&q->mmap_lock);
>>> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>>>   static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   {
>>>   	struct vb2_fileio_data *fileio;
>>> +	struct vb2_buffer *vb;
>>>   	int i, ret;
>>>   	unsigned int count = 0;
>>>   
>>> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   	 * Check if plane_count is correct
>>>   	 * (multiplane buffers are not supported).
>>>   	 */
>>> -	if (q->bufs[0]->num_planes != 1) {
>>> +	vb = vb2_get_buffer(q, 0);
>>> +	if (!vb) {
>>> +		ret = -EBUSY;
>>> +		goto err_reqbufs;
>>> +	}
>>> +
>>> +	if (vb->num_planes != 1) {
>>>   		ret = -EBUSY;
>>>   		goto err_reqbufs;
>>>   	}
>>> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   	 * Get kernel address of each buffer.
>>>   	 */
>>>   	for (i = 0; i < q->num_buffers; i++) {
>>> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>>> +		vb = vb2_get_buffer(q, i);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>>>   		if (fileio->bufs[i].vaddr == NULL) {
>>>   			ret = -EINVAL;
>>>   			goto err_reqbufs;
>>>   		}
>>> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>>> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>>>   	}
>>>   
>>>   	/*
>>> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   
>>>   		fileio->cur_index = index;
>>>   		buf = &fileio->bufs[index];
>>> -		b = q->bufs[index];
>>> +		b = vb2_get_buffer(q, index);
>>> +
>>> +		if (!b)
>>> +			return -EINVAL;
>>>   
>>>   		/*
>>>   		 * Get number of bytes filled by the driver
>>>   		 */
>>>   		buf->pos = 0;
>>>   		buf->queued = 0;
>>> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>>> -				 : vb2_plane_size(q->bufs[index], 0);
>>> +		buf->size = read ? vb2_get_plane_payload(b, 0)
>>> +				 : vb2_plane_size(b, 0);
>>>   		/* Compensate for data_offset on read in the multiplanar case. */
>>>   		if (is_multiplanar && read &&
>>>   				b->planes[0].data_offset < buf->size) {
>>> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   	 * Queue next buffer if required.
>>>   	 */
>>>   	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>>> -		struct vb2_buffer *b = q->bufs[index];
>>> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>>>   
>>> +		if (!b) {
>>> +			dprintk(q, 1, "can't find the requested buffer\n");
>>> +			return -EINVAL;
>>> +		}
>>>   		/*
>>>   		 * Check if this is the last buffer to read.
>>>   		 */
>>> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   		 */
>>>   		buf->pos = 0;
>>>   		buf->queued = 1;
>>> -		buf->size = vb2_plane_size(q->bufs[index], 0);
>>> +		buf->size = vb2_plane_size(b, 0);
>>>   		fileio->q_count += 1;
>>>   		/*
>>>   		 * If we are queuing up buffers for the first time, then
>>> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>>>   		 * Call vb2_dqbuf to get buffer back.
>>>   		 */
>>>   		if (prequeue) {
>>> -			vb = q->bufs[index++];
>>> +			vb = vb2_get_buffer(q, index++);
>>> +			if (!vb)
>>> +				continue;
>>>   			prequeue--;
>>>   		} else {
>>>   			call_void_qop(q, wait_finish, q);
>>> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>>>   			call_void_qop(q, wait_prepare, q);
>>>   			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>>>   			if (!ret)
>>> -				vb = q->bufs[index];
>>> +				vb = vb2_get_buffer(q, index);
>>>   		}
>>>   		if (ret || threadio->stop)
>>>   			break;
>>> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> index c7a54d82a55e..724135d41f7f 100644
>>> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	if (q->bufs[b->index] == NULL) {
>>> -		/* Should never happen */
>>> +	if (!vb2_get_buffer(q, b->index)) {
>>>   		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>>>   		return -EINVAL;
>>>   	}
>>> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = q->bufs[b->index];
>>> +	vb = vb2_get_buffer(q, b->index);
>>>   	vbuf = to_vb2_v4l2_buffer(vb);
>>>   	ret = __verify_planes_array(vb, b);
>>>   	if (ret)
>>> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>>>   struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>>>   {
>>>   	unsigned int i;
>>> +	struct vb2_buffer *vb2;
>>>   
>>> -	for (i = 0; i < q->num_buffers; i++)
>>> -		if (q->bufs[i]->copied_timestamp &&
>>> -		    q->bufs[i]->timestamp == timestamp)
>>> -			return vb2_get_buffer(q, i);
>>> +	for (i = 0; i < q->num_buffers; i++) {
>>> +		vb2 = vb2_get_buffer(q, i);
>>> +
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		if (vb2->copied_timestamp &&
>>> +		    vb2->timestamp == timestamp)
>>> +			return vb2;
>>> +	}
>>>   	return NULL;
>>>   }
>>>   EXPORT_SYMBOL_GPL(vb2_find_buffer);
>>> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>>   		dprintk(q, 1, "buffer index out of range\n");
>>>   		return -EINVAL;
>>>   	}
>>> -	vb = q->bufs[b->index];
>>> +	vb = vb2_get_buffer(q, b->index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>>   	ret = __verify_planes_array(vb, b);
>>>   	if (!ret)
>>>   		vb2_core_querybuf(q, b->index, b);
>>> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
>>> index 44b830ae01d8..e2c371c2fde5 100644
>>> --- a/drivers/media/platform/amphion/vpu_dbg.c
>>> +++ b/drivers/media/platform/amphion/vpu_dbg.c
>>> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>>   
>>>   	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		struct vb2_buffer *vb = vq->bufs[i];
>>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>> +		struct vb2_buffer *vb;
>>> +		struct vb2_v4l2_buffer *vbuf;
>>> +
>>> +		vb = vb2_get_buffer(vq, i);
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>>   			continue;
>>> +
>>> +		vbuf = to_vb2_v4l2_buffer(vb);
>>> +
>>>   		num = scnprintf(str, sizeof(str),
>>>   				"output [%2d] state = %10s, %8s\n",
>>>   				i, vb2_stat_name[vb->state],
>>> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>>   
>>>   	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		struct vb2_buffer *vb = vq->bufs[i];
>>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>> +		struct vb2_buffer *vb;
>>> +		struct vb2_v4l2_buffer *vbuf;
>>> +
>>> +		vb = vb2_get_buffer(vq, i);
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>>   			continue;
>>> +
>>> +		vbuf = to_vb2_v4l2_buffer(vb);
>>> +
>>>   		num = scnprintf(str, sizeof(str),
>>>   				"capture[%2d] state = %10s, %8s\n",
>>>   				i, vb2_stat_name[vb->state],
>>> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> index 0051f372a66c..ea37069ba355 100644
>>> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = vq->bufs[buf->index];
>>> +	vb = vb2_get_buffer(vq, buf->index);
>>> +	if (!vb) {
>>> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
>>> +		return -EINVAL;
>>> +	}
>>>   	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>>>   	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>>>   
>>> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> index cf16cf2807f0..6532a69f1fa8 100644
>>> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>>>   
>>>   	/* update internal buffer's width/height */
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		if (vb == vq->bufs[i]) {
>>> +		if (vb == vb2_get_buffer(vq, i)) {
>>>   			instance->dpb[i].width = w;
>>>   			instance->dpb[i].height = h;
>>>   			break;
>>> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> index 3a848ca32a0e..326be09bdb55 100644
>>> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>>   		}
>>>   
>>>   		vb2_buf = vb2_get_buffer(vq, buf->index);
>>> +		if (!vb2_buf) {
>>> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
>>> +			return -EINVAL;
>>> +		}
>>>   		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>>>   		stream->bytesused = buf->bytesused;
>>>   	}
>>> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
>>> index 318d675e5668..ba20ea998d19 100644
>>> --- a/drivers/media/test-drivers/visl/visl-dec.c
>>> +++ b/drivers/media/test-drivers/visl/visl-dec.c
>>> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>>   	for (i = 0; i < out_q->num_buffers; i++) {
>>>   		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>>>   		u32 old_len = len;
>>> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
>>> +		struct vb2_buffer *vb2;
>>> +		char *q_status;
>>> +
>>> +		vb2 = vb2_get_buffer(out_q, i);
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		q_status = visl_get_vb2_state(vb2->state);
>>>   
>>>   		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>>   				 entry, i, q_status,
>>> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
>>> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>>>   
>>> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
>>> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>>>   					   &buf[len],
>>>   					   TPG_STR_BUF_SZ - len);
>>>   
>>> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>>   	len = 0;
>>>   	for (i = 0; i < cap_q->num_buffers; i++) {
>>>   		u32 old_len = len;
>>> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
>>> +		struct vb2_buffer *vb2;
>>> +		char *q_status;
>>> +
>>> +		vb2 = vb2_get_buffer(cap_q, i);
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		q_status = visl_get_vb2_state(vb2->state);
>>>   
>>>   		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>>   				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
>>> -				 cap_q->bufs[i]->index, q_status,
>>> -				 cap_q->bufs[i]->timestamp,
>>> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
>>> +				 vb2->index, q_status,
>>> +				 vb2->timestamp,
>>> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>>>   
>>>   		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>>>   		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
>>> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> index 384f31fc66c5..8df301ab41ad 100644
>>> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>>>   	if (ret)
>>>   		return ret;
>>>   
>>> -	vb = pipe->vb_queue.bufs[buf->index];
>>> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>>>   	frame = vb_to_frame(vb);
>>>   
>>>   	buf->reserved = asd->frame_status[buf->index];
>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
@ 2023-08-22 12:49         ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-08-22 12:49 UTC (permalink / raw)
  To: Hans Verkuil, mchehab, tfiga, m.szyprowski, ming.qian, ezequiel,
	p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel


Le 21/08/2023 à 16:31, Hans Verkuil a écrit :
> On 21/08/2023 16:24, Hans Verkuil wrote:
>> Hi Benjamin,
>>
>> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>>> The first step before changing how vb2 buffers are stored into queue
>>> is to avoid direct access to bufs arrays.
>>>
>>> This patch adds 2 helpers functions to add and remove vb2 buffers
>>> from a queue. With these 2 and vb2_get_buffer(), bufs field of
>>> struct vb2_queue becomes like a private member of the structure.
>>>
>>> After each call to vb2_get_buffer() we need to be sure that we get
>>> a valid pointer so check the return value of all of them.
>>>
>>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>>> ---
>>>   .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>>>   .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>>>   drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>>>   .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>>>   .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>>>   drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>>>   drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>>>   .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>>>   8 files changed, 240 insertions(+), 67 deletions(-)
>>>
>>> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
>>> index cf6727d9c81f..42fd3984c2bc 100644
>>> --- a/drivers/media/common/videobuf2/videobuf2-core.c
>>> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
>>> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>>>   	unsigned long off = 0;
>>>   
>>>   	if (vb->index) {
>>> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
>>> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
>>> +		struct vb2_buffer *prev;
>>> +		struct vb2_plane *p;
>>> +
>>> +		prev = vb2_get_buffer(q, vb->index - 1);
>>> +		if (!prev) {
>>> +			dprintk(q, 1, "can't find the requested buffer\n");
>>> +			return;
>>> +		}
>>> +
>>> +		p = &prev->planes[prev->num_planes - 1];
>>>   
>>>   		off = PAGE_ALIGN(p->m.offset + p->length);
>> This does not work. Before this patch there should be a patch that changes
>> the way the offset is determined since it affects this functionality.
>>
>> __setup_offsets() fills in the m.offset field for each plane in the buffer.
>> In the current code it starts with 0 for the first buffer, adds the length
>> for each plane to it, and for the next buffer it continues doing that. So
>> the offset for a plane is the total length of all preceding buffers and planes.
>>
>> In addition, bit 30 of the offset field is used to signal if it is a capture
>> or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
>> define).
>>
>> In addition, the offset has to be page aligned, so the lower 12 bits are 0.
>> That leaves only 32-1-12 = 19 bits for the offset.
>>
>> Since we allow 8 planes per buffer, that means that we can't have more than
>> 65536 buffers given a 32 bit offset.
>>
>> I think the way m.offset is calculated should change drastically: it should
>> instead be something like this:
>>
>> m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;
>>
>> and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.
>>
>> Parsing the offset would be much simpler as well, since you can just decode
>> the index and plane numbers directly rather than using the cumbersome
>> __find_plane_by_offset() function.
>>
>> The currently mechanism will fail completely once you can delete buffers,
>> and this proposal will simplify and improve the code, so I think it should
>> be done first.
> I could have saved myself some work if I read the other patches first.
>
> I see that patch 3/10 addresses this. But for the v5, just move that patch
> to the beginning of the series.

I will try to do that but these patches hit the same pieces of code so changing the order isn't that simple.

>
> I would also suggest changing DST_QUEUE_OFF_BASE to use bit 31 to allow for
> 16 bits instead of 15 for the buffer index.

DST_QUEUE_OFF_BASE is used with PAGE_SHIFT in v4l2-mem2mem and s5p_mfc in mmap/unmap functions.
I'm bit afraid to change that.
With my change each queue can store up to 0xffff (65535) buffers.
Sound large enough for me ;-)

Benjamin

>
> Regards,
>
> 	Hans
>
>> Regards,
>>
>> 	Hans
>>
>>>   	}
>>> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>>>   		vb->skip_cache_sync_on_finish = 1;
>>>   }
>>>   
>>> +/**
>>> + * vb2_queue_add_buffer() - add a buffer to a queue
>>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>>> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
>>> + * @index: index where add vb2_buffer in the queue
>>> + */
>>> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
>>> +{
>>> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
>>> +		q->bufs[index] = vb;
>>> +		vb->index = index;
>>> +		vb->vb2_queue = q;
>>> +		return true;
>>> +	}
>>> +
>>> +	return false;
>>> +}
>>> +
>>> +/**
>>> + * vb2_queue_remove_buffer() - remove a buffer from a queue
>>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>>> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
>>> + */
>>> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
>>> +{
>>> +	if (vb->index < VB2_MAX_FRAME) {
>>> +		q->bufs[vb->index] = NULL;
>>> +		vb->vb2_queue = NULL;
>>> +	}
>>> +}
>>> +
>>>   /*
>>>    * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>>>    * video buffer memory for all buffers/planes on the queue and initializes the
>>> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   		}
>>>   
>>>   		vb->state = VB2_BUF_STATE_DEQUEUED;
>>> -		vb->vb2_queue = q;
>>>   		vb->num_planes = num_planes;
>>> -		vb->index = q->num_buffers + buffer;
>>>   		vb->type = q->type;
>>>   		vb->memory = memory;
>>>   		init_buffer_cache_hints(q, vb);
>>> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   		}
>>>   		call_void_bufop(q, init_buffer, vb);
>>>   
>>> -		q->bufs[vb->index] = vb;
>>> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
>>> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
>>> +			kfree(vb);
>>> +			break;
>>> +		}
>>>   
>>>   		/* Allocate video buffer memory for the MMAP type */
>>>   		if (memory == VB2_MEMORY_MMAP) {
>>> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   			if (ret) {
>>>   				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>>>   					buffer);
>>> -				q->bufs[vb->index] = NULL;
>>> +				vb2_queue_remove_buffer(q, vb);
>>>   				kfree(vb);
>>>   				break;
>>>   			}
>>> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   				dprintk(q, 1, "buffer %d %p initialization failed\n",
>>>   					buffer, vb);
>>>   				__vb2_buf_mem_free(vb);
>>> -				q->bufs[vb->index] = NULL;
>>> +				vb2_queue_remove_buffer(q, vb);
>>>   				kfree(vb);
>>>   				break;
>>>   			}
>>> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>>   
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		vb = q->bufs[buffer];
>>> +		vb = vb2_get_buffer(q, buffer);
>>>   		if (!vb)
>>>   			continue;
>>>   
>>> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   	/* Call driver-provided cleanup function for each buffer, if provided */
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		struct vb2_buffer *vb = q->bufs[buffer];
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>>   
>>>   		if (vb && vb->planes[0].mem_priv)
>>>   			call_void_vb_qop(vb, buf_cleanup, vb);
>>> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   		q->cnt_unprepare_streaming = 0;
>>>   	}
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		struct vb2_buffer *vb = q->bufs[buffer];
>>> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>>> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>>> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>>> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>>> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>>> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
>>> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>>> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +		bool unbalanced;
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>>> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>>> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>>> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>>> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>>> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
>>> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>>> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>>   
>>>   		if (unbalanced || debug) {
>>>   			pr_info("   counters for queue %p, buffer %d:%s\n",
>>> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   	/* Free vb2 buffers */
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		kfree(q->bufs[buffer]);
>>> -		q->bufs[buffer] = NULL;
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		vb2_queue_remove_buffer(q, vb);
>>> +		kfree(vb);
>>>   	}
>>>   
>>>   	q->num_buffers -= buffers;
>>> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>>   {
>>>   	unsigned int buffer;
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		if (vb2_buffer_in_use(q, vb))
>>>   			return true;
>>>   	}
>>>   	return false;
>>> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>>   
>>>   void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>>>   {
>>> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
>>> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (vb)
>>> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>>>   }
>>>   EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>>>   
>>> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>>>   	struct vb2_buffer *vb;
>>>   	int ret;
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>>   	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>>>   		dprintk(q, 1, "invalid buffer state %s\n",
>>>   			vb2_state_name(vb->state));
>>> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>>   		 * correctly return them to vb2.
>>>   		 */
>>>   		for (i = 0; i < q->num_buffers; ++i) {
>>> -			vb = q->bufs[i];
>>> +			vb = vb2_get_buffer(q, i);
>>> +
>>> +			if (!vb)
>>> +				continue;
>>> +
>>>   			if (vb->state == VB2_BUF_STATE_ACTIVE)
>>>   				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>>>   		}
>>> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>>>   		return -EIO;
>>>   	}
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>>   
>>>   	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>>>   	    q->requires_requests) {
>>> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>>   	 * to vb2 in stop_streaming().
>>>   	 */
>>>   	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
>>> -		for (i = 0; i < q->num_buffers; ++i)
>>> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
>>> +		for (i = 0; i < q->num_buffers; ++i) {
>>> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
>>> +
>>> +			if (!vb)
>>> +				continue;
>>> +
>>> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>>>   				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
>>> -					q->bufs[i]);
>>> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
>>> +					vb);
>>> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>>>   			}
>>> +		}
>>>   		/* Must be zero now */
>>>   		WARN_ON(atomic_read(&q->owned_by_drv_count));
>>>   	}
>>> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>>   	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>>>   	 */
>>>   	for (i = 0; i < q->num_buffers; ++i) {
>>> -		struct vb2_buffer *vb = q->bufs[i];
>>> -		struct media_request *req = vb->req_obj.req;
>>> +		struct vb2_buffer *vb;
>>> +		struct media_request *req;
>>>   
>>> +		vb = vb2_get_buffer(q, i);
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		req = vb->req_obj.req;
>>>   		/*
>>>   		 * If a request is associated with this buffer, then
>>>   		 * call buf_request_cancel() to give the driver to complete()
>>> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>>   	 * return its buffer and plane numbers.
>>>   	 */
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		vb = q->bufs[buffer];
>>> +		vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		for (plane = 0; plane < vb->num_planes; ++plane) {
>>>   			if (vb->planes[plane].m.offset == off) {
>>> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>>   
>>>   	if (plane >= vb->num_planes) {
>>>   		dprintk(q, 1, "buffer plane out of range\n");
>>> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>>   	if (ret)
>>>   		goto unlock;
>>>   
>>> -	vb = q->bufs[buffer];
>>> +	vb = vb2_get_buffer(q, buffer);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		ret = -EINVAL;
>>> +		goto unlock;
>>> +	}
>>>   
>>>   	/*
>>>   	 * MMAP requires page_aligned buffers.
>>> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>>   	if (ret)
>>>   		goto unlock;
>>>   
>>> -	vb = q->bufs[buffer];
>>> +	vb = vb2_get_buffer(q, buffer);
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		ret = -EINVAL;
>>> +		goto unlock;
>>> +	}
>>>   
>>>   	vaddr = vb2_plane_vaddr(vb, plane);
>>>   	mutex_unlock(&q->mmap_lock);
>>> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>>>   static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   {
>>>   	struct vb2_fileio_data *fileio;
>>> +	struct vb2_buffer *vb;
>>>   	int i, ret;
>>>   	unsigned int count = 0;
>>>   
>>> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   	 * Check if plane_count is correct
>>>   	 * (multiplane buffers are not supported).
>>>   	 */
>>> -	if (q->bufs[0]->num_planes != 1) {
>>> +	vb = vb2_get_buffer(q, 0);
>>> +	if (!vb) {
>>> +		ret = -EBUSY;
>>> +		goto err_reqbufs;
>>> +	}
>>> +
>>> +	if (vb->num_planes != 1) {
>>>   		ret = -EBUSY;
>>>   		goto err_reqbufs;
>>>   	}
>>> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   	 * Get kernel address of each buffer.
>>>   	 */
>>>   	for (i = 0; i < q->num_buffers; i++) {
>>> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>>> +		vb = vb2_get_buffer(q, i);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>>>   		if (fileio->bufs[i].vaddr == NULL) {
>>>   			ret = -EINVAL;
>>>   			goto err_reqbufs;
>>>   		}
>>> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>>> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>>>   	}
>>>   
>>>   	/*
>>> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   
>>>   		fileio->cur_index = index;
>>>   		buf = &fileio->bufs[index];
>>> -		b = q->bufs[index];
>>> +		b = vb2_get_buffer(q, index);
>>> +
>>> +		if (!b)
>>> +			return -EINVAL;
>>>   
>>>   		/*
>>>   		 * Get number of bytes filled by the driver
>>>   		 */
>>>   		buf->pos = 0;
>>>   		buf->queued = 0;
>>> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>>> -				 : vb2_plane_size(q->bufs[index], 0);
>>> +		buf->size = read ? vb2_get_plane_payload(b, 0)
>>> +				 : vb2_plane_size(b, 0);
>>>   		/* Compensate for data_offset on read in the multiplanar case. */
>>>   		if (is_multiplanar && read &&
>>>   				b->planes[0].data_offset < buf->size) {
>>> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   	 * Queue next buffer if required.
>>>   	 */
>>>   	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>>> -		struct vb2_buffer *b = q->bufs[index];
>>> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>>>   
>>> +		if (!b) {
>>> +			dprintk(q, 1, "can't find the requested buffer\n");
>>> +			return -EINVAL;
>>> +		}
>>>   		/*
>>>   		 * Check if this is the last buffer to read.
>>>   		 */
>>> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   		 */
>>>   		buf->pos = 0;
>>>   		buf->queued = 1;
>>> -		buf->size = vb2_plane_size(q->bufs[index], 0);
>>> +		buf->size = vb2_plane_size(b, 0);
>>>   		fileio->q_count += 1;
>>>   		/*
>>>   		 * If we are queuing up buffers for the first time, then
>>> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>>>   		 * Call vb2_dqbuf to get buffer back.
>>>   		 */
>>>   		if (prequeue) {
>>> -			vb = q->bufs[index++];
>>> +			vb = vb2_get_buffer(q, index++);
>>> +			if (!vb)
>>> +				continue;
>>>   			prequeue--;
>>>   		} else {
>>>   			call_void_qop(q, wait_finish, q);
>>> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>>>   			call_void_qop(q, wait_prepare, q);
>>>   			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>>>   			if (!ret)
>>> -				vb = q->bufs[index];
>>> +				vb = vb2_get_buffer(q, index);
>>>   		}
>>>   		if (ret || threadio->stop)
>>>   			break;
>>> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> index c7a54d82a55e..724135d41f7f 100644
>>> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	if (q->bufs[b->index] == NULL) {
>>> -		/* Should never happen */
>>> +	if (!vb2_get_buffer(q, b->index)) {
>>>   		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>>>   		return -EINVAL;
>>>   	}
>>> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = q->bufs[b->index];
>>> +	vb = vb2_get_buffer(q, b->index);
>>>   	vbuf = to_vb2_v4l2_buffer(vb);
>>>   	ret = __verify_planes_array(vb, b);
>>>   	if (ret)
>>> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>>>   struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>>>   {
>>>   	unsigned int i;
>>> +	struct vb2_buffer *vb2;
>>>   
>>> -	for (i = 0; i < q->num_buffers; i++)
>>> -		if (q->bufs[i]->copied_timestamp &&
>>> -		    q->bufs[i]->timestamp == timestamp)
>>> -			return vb2_get_buffer(q, i);
>>> +	for (i = 0; i < q->num_buffers; i++) {
>>> +		vb2 = vb2_get_buffer(q, i);
>>> +
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		if (vb2->copied_timestamp &&
>>> +		    vb2->timestamp == timestamp)
>>> +			return vb2;
>>> +	}
>>>   	return NULL;
>>>   }
>>>   EXPORT_SYMBOL_GPL(vb2_find_buffer);
>>> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>>   		dprintk(q, 1, "buffer index out of range\n");
>>>   		return -EINVAL;
>>>   	}
>>> -	vb = q->bufs[b->index];
>>> +	vb = vb2_get_buffer(q, b->index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>>   	ret = __verify_planes_array(vb, b);
>>>   	if (!ret)
>>>   		vb2_core_querybuf(q, b->index, b);
>>> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
>>> index 44b830ae01d8..e2c371c2fde5 100644
>>> --- a/drivers/media/platform/amphion/vpu_dbg.c
>>> +++ b/drivers/media/platform/amphion/vpu_dbg.c
>>> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>>   
>>>   	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		struct vb2_buffer *vb = vq->bufs[i];
>>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>> +		struct vb2_buffer *vb;
>>> +		struct vb2_v4l2_buffer *vbuf;
>>> +
>>> +		vb = vb2_get_buffer(vq, i);
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>>   			continue;
>>> +
>>> +		vbuf = to_vb2_v4l2_buffer(vb);
>>> +
>>>   		num = scnprintf(str, sizeof(str),
>>>   				"output [%2d] state = %10s, %8s\n",
>>>   				i, vb2_stat_name[vb->state],
>>> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>>   
>>>   	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		struct vb2_buffer *vb = vq->bufs[i];
>>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>> +		struct vb2_buffer *vb;
>>> +		struct vb2_v4l2_buffer *vbuf;
>>> +
>>> +		vb = vb2_get_buffer(vq, i);
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>>   			continue;
>>> +
>>> +		vbuf = to_vb2_v4l2_buffer(vb);
>>> +
>>>   		num = scnprintf(str, sizeof(str),
>>>   				"capture[%2d] state = %10s, %8s\n",
>>>   				i, vb2_stat_name[vb->state],
>>> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> index 0051f372a66c..ea37069ba355 100644
>>> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = vq->bufs[buf->index];
>>> +	vb = vb2_get_buffer(vq, buf->index);
>>> +	if (!vb) {
>>> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
>>> +		return -EINVAL;
>>> +	}
>>>   	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>>>   	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>>>   
>>> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> index cf16cf2807f0..6532a69f1fa8 100644
>>> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>>>   
>>>   	/* update internal buffer's width/height */
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		if (vb == vq->bufs[i]) {
>>> +		if (vb == vb2_get_buffer(vq, i)) {
>>>   			instance->dpb[i].width = w;
>>>   			instance->dpb[i].height = h;
>>>   			break;
>>> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> index 3a848ca32a0e..326be09bdb55 100644
>>> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>>   		}
>>>   
>>>   		vb2_buf = vb2_get_buffer(vq, buf->index);
>>> +		if (!vb2_buf) {
>>> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
>>> +			return -EINVAL;
>>> +		}
>>>   		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>>>   		stream->bytesused = buf->bytesused;
>>>   	}
>>> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
>>> index 318d675e5668..ba20ea998d19 100644
>>> --- a/drivers/media/test-drivers/visl/visl-dec.c
>>> +++ b/drivers/media/test-drivers/visl/visl-dec.c
>>> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>>   	for (i = 0; i < out_q->num_buffers; i++) {
>>>   		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>>>   		u32 old_len = len;
>>> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
>>> +		struct vb2_buffer *vb2;
>>> +		char *q_status;
>>> +
>>> +		vb2 = vb2_get_buffer(out_q, i);
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		q_status = visl_get_vb2_state(vb2->state);
>>>   
>>>   		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>>   				 entry, i, q_status,
>>> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
>>> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>>>   
>>> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
>>> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>>>   					   &buf[len],
>>>   					   TPG_STR_BUF_SZ - len);
>>>   
>>> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>>   	len = 0;
>>>   	for (i = 0; i < cap_q->num_buffers; i++) {
>>>   		u32 old_len = len;
>>> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
>>> +		struct vb2_buffer *vb2;
>>> +		char *q_status;
>>> +
>>> +		vb2 = vb2_get_buffer(cap_q, i);
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		q_status = visl_get_vb2_state(vb2->state);
>>>   
>>>   		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>>   				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
>>> -				 cap_q->bufs[i]->index, q_status,
>>> -				 cap_q->bufs[i]->timestamp,
>>> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
>>> +				 vb2->index, q_status,
>>> +				 vb2->timestamp,
>>> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>>>   
>>>   		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>>>   		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
>>> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> index 384f31fc66c5..8df301ab41ad 100644
>>> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>>>   	if (ret)
>>>   		return ret;
>>>   
>>> -	vb = pipe->vb_queue.bufs[buf->index];
>>> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>>>   	frame = vb_to_frame(vb);
>>>   
>>>   	buf->reserved = asd->frame_status[buf->index];
>

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions
@ 2023-08-22 12:49         ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-08-22 12:49 UTC (permalink / raw)
  To: Hans Verkuil, mchehab, tfiga, m.szyprowski, ming.qian, ezequiel,
	p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel


Le 21/08/2023 à 16:31, Hans Verkuil a écrit :
> On 21/08/2023 16:24, Hans Verkuil wrote:
>> Hi Benjamin,
>>
>> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>>> The first step before changing how vb2 buffers are stored into queue
>>> is to avoid direct access to bufs arrays.
>>>
>>> This patch adds 2 helpers functions to add and remove vb2 buffers
>>> from a queue. With these 2 and vb2_get_buffer(), bufs field of
>>> struct vb2_queue becomes like a private member of the structure.
>>>
>>> After each call to vb2_get_buffer() we need to be sure that we get
>>> a valid pointer so check the return value of all of them.
>>>
>>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>>> ---
>>>   .../media/common/videobuf2/videobuf2-core.c   | 215 ++++++++++++++----
>>>   .../media/common/videobuf2/videobuf2-v4l2.c   |  28 ++-
>>>   drivers/media/platform/amphion/vpu_dbg.c      |  22 +-
>>>   .../platform/mediatek/jpeg/mtk_jpeg_core.c    |   6 +-
>>>   .../vcodec/vdec/vdec_vp9_req_lat_if.c         |   2 +-
>>>   drivers/media/platform/st/sti/hva/hva-v4l2.c  |   4 +
>>>   drivers/media/test-drivers/visl/visl-dec.c    |  28 ++-
>>>   .../staging/media/atomisp/pci/atomisp_ioctl.c |   2 +-
>>>   8 files changed, 240 insertions(+), 67 deletions(-)
>>>
>>> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
>>> index cf6727d9c81f..42fd3984c2bc 100644
>>> --- a/drivers/media/common/videobuf2/videobuf2-core.c
>>> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
>>> @@ -359,8 +359,16 @@ static void __setup_offsets(struct vb2_buffer *vb)
>>>   	unsigned long off = 0;
>>>   
>>>   	if (vb->index) {
>>> -		struct vb2_buffer *prev = q->bufs[vb->index - 1];
>>> -		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
>>> +		struct vb2_buffer *prev;
>>> +		struct vb2_plane *p;
>>> +
>>> +		prev = vb2_get_buffer(q, vb->index - 1);
>>> +		if (!prev) {
>>> +			dprintk(q, 1, "can't find the requested buffer\n");
>>> +			return;
>>> +		}
>>> +
>>> +		p = &prev->planes[prev->num_planes - 1];
>>>   
>>>   		off = PAGE_ALIGN(p->m.offset + p->length);
>> This does not work. Before this patch there should be a patch that changes
>> the way the offset is determined since it affects this functionality.
>>
>> __setup_offsets() fills in the m.offset field for each plane in the buffer.
>> In the current code it starts with 0 for the first buffer, adds the length
>> for each plane to it, and for the next buffer it continues doing that. So
>> the offset for a plane is the total length of all preceding buffers and planes.
>>
>> In addition, bit 30 of the offset field is used to signal if it is a capture
>> or output buffer in the v4l2-mem2mem framework (see the DST_QUEUE_OFF_BASE
>> define).
>>
>> In addition, the offset has to be page aligned, so the lower 12 bits are 0.
>> That leaves only 32-1-12 = 19 bits for the offset.
>>
>> Since we allow 8 planes per buffer, that means that we can't have more than
>> 65536 buffers given a 32 bit offset.
>>
>> I think the way m.offset is calculated should change drastically: it should
>> instead be something like this:
>>
>> m.offset = ((vb->index << 3) | plane) << PAGE_SHIFT;
>>
>> and DST_QUEUE_OFF_BASE should use bit 31 instead of 30.
>>
>> Parsing the offset would be much simpler as well, since you can just decode
>> the index and plane numbers directly rather than using the cumbersome
>> __find_plane_by_offset() function.
>>
>> The currently mechanism will fail completely once you can delete buffers,
>> and this proposal will simplify and improve the code, so I think it should
>> be done first.
> I could have saved myself some work if I read the other patches first.
>
> I see that patch 3/10 addresses this. But for the v5, just move that patch
> to the beginning of the series.

I will try to do that but these patches hit the same pieces of code so changing the order isn't that simple.

>
> I would also suggest changing DST_QUEUE_OFF_BASE to use bit 31 to allow for
> 16 bits instead of 15 for the buffer index.

DST_QUEUE_OFF_BASE is used with PAGE_SHIFT in v4l2-mem2mem and s5p_mfc in mmap/unmap functions.
I'm bit afraid to change that.
With my change each queue can store up to 0xffff (65535) buffers.
Sound large enough for me ;-)

Benjamin

>
> Regards,
>
> 	Hans
>
>> Regards,
>>
>> 	Hans
>>
>>>   	}
>>> @@ -397,6 +405,37 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
>>>   		vb->skip_cache_sync_on_finish = 1;
>>>   }
>>>   
>>> +/**
>>> + * vb2_queue_add_buffer() - add a buffer to a queue
>>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>>> + * @vb:	pointer to &struct vb2_buffer to be added to the queue.
>>> + * @index: index where add vb2_buffer in the queue
>>> + */
>>> +static bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, int index)
>>> +{
>>> +	if (index < VB2_MAX_FRAME && !q->bufs[index]) {
>>> +		q->bufs[index] = vb;
>>> +		vb->index = index;
>>> +		vb->vb2_queue = q;
>>> +		return true;
>>> +	}
>>> +
>>> +	return false;
>>> +}
>>> +
>>> +/**
>>> + * vb2_queue_remove_buffer() - remove a buffer from a queue
>>> + * @q:	pointer to &struct vb2_queue with videobuf2 queue.
>>> + * @vb:	pointer to &struct vb2_buffer to be removed from the queue.
>>> + */
>>> +static void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb)
>>> +{
>>> +	if (vb->index < VB2_MAX_FRAME) {
>>> +		q->bufs[vb->index] = NULL;
>>> +		vb->vb2_queue = NULL;
>>> +	}
>>> +}
>>> +
>>>   /*
>>>    * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
>>>    * video buffer memory for all buffers/planes on the queue and initializes the
>>> @@ -425,9 +464,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   		}
>>>   
>>>   		vb->state = VB2_BUF_STATE_DEQUEUED;
>>> -		vb->vb2_queue = q;
>>>   		vb->num_planes = num_planes;
>>> -		vb->index = q->num_buffers + buffer;
>>>   		vb->type = q->type;
>>>   		vb->memory = memory;
>>>   		init_buffer_cache_hints(q, vb);
>>> @@ -437,7 +474,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   		}
>>>   		call_void_bufop(q, init_buffer, vb);
>>>   
>>> -		q->bufs[vb->index] = vb;
>>> +		if (!vb2_queue_add_buffer(q, vb, q->num_buffers + buffer)) {
>>> +			dprintk(q, 1, "failed adding buffer %d to queue\n", buffer);
>>> +			kfree(vb);
>>> +			break;
>>> +		}
>>>   
>>>   		/* Allocate video buffer memory for the MMAP type */
>>>   		if (memory == VB2_MEMORY_MMAP) {
>>> @@ -445,7 +486,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   			if (ret) {
>>>   				dprintk(q, 1, "failed allocating memory for buffer %d\n",
>>>   					buffer);
>>> -				q->bufs[vb->index] = NULL;
>>> +				vb2_queue_remove_buffer(q, vb);
>>>   				kfree(vb);
>>>   				break;
>>>   			}
>>> @@ -460,7 +501,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
>>>   				dprintk(q, 1, "buffer %d %p initialization failed\n",
>>>   					buffer, vb);
>>>   				__vb2_buf_mem_free(vb);
>>> -				q->bufs[vb->index] = NULL;
>>> +				vb2_queue_remove_buffer(q, vb);
>>>   				kfree(vb);
>>>   				break;
>>>   			}
>>> @@ -483,7 +524,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>>   
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		vb = q->bufs[buffer];
>>> +		vb = vb2_get_buffer(q, buffer);
>>>   		if (!vb)
>>>   			continue;
>>>   
>>> @@ -511,7 +552,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   	/* Call driver-provided cleanup function for each buffer, if provided */
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		struct vb2_buffer *vb = q->bufs[buffer];
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>>   
>>>   		if (vb && vb->planes[0].mem_priv)
>>>   			call_void_vb_qop(vb, buf_cleanup, vb);
>>> @@ -551,15 +592,20 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   		q->cnt_unprepare_streaming = 0;
>>>   	}
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		struct vb2_buffer *vb = q->bufs[buffer];
>>> -		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>>> -				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>>> -				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>>> -				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>>> -				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>>> -				  vb->cnt_buf_queue != vb->cnt_buf_done ||
>>> -				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>>> -				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +		bool unbalanced;
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
>>> +			     vb->cnt_mem_prepare != vb->cnt_mem_finish ||
>>> +			     vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
>>> +			     vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
>>> +			     vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
>>> +			     vb->cnt_buf_queue != vb->cnt_buf_done ||
>>> +			     vb->cnt_buf_prepare != vb->cnt_buf_finish ||
>>> +			     vb->cnt_buf_init != vb->cnt_buf_cleanup;
>>>   
>>>   		if (unbalanced || debug) {
>>>   			pr_info("   counters for queue %p, buffer %d:%s\n",
>>> @@ -591,8 +637,13 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>>   	/* Free vb2 buffers */
>>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>>>   	     ++buffer) {
>>> -		kfree(q->bufs[buffer]);
>>> -		q->bufs[buffer] = NULL;
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		vb2_queue_remove_buffer(q, vb);
>>> +		kfree(vb);
>>>   	}
>>>   
>>>   	q->num_buffers -= buffers;
>>> @@ -628,7 +679,12 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>>   {
>>>   	unsigned int buffer;
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>>> +		struct vb2_buffer *vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		if (vb2_buffer_in_use(q, vb))
>>>   			return true;
>>>   	}
>>>   	return false;
>>> @@ -636,7 +692,10 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>>   
>>>   void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>>>   {
>>> -	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
>>> +	struct vb2_buffer *vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (vb)
>>> +		call_void_bufop(q, fill_user_buffer, vb, pb);
>>>   }
>>>   EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>>>   
>>> @@ -1547,7 +1606,13 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>>>   	struct vb2_buffer *vb;
>>>   	int ret;
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>>   	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>>>   		dprintk(q, 1, "invalid buffer state %s\n",
>>>   			vb2_state_name(vb->state));
>>> @@ -1618,7 +1683,11 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>>   		 * correctly return them to vb2.
>>>   		 */
>>>   		for (i = 0; i < q->num_buffers; ++i) {
>>> -			vb = q->bufs[i];
>>> +			vb = vb2_get_buffer(q, i);
>>> +
>>> +			if (!vb)
>>> +				continue;
>>> +
>>>   			if (vb->state == VB2_BUF_STATE_ACTIVE)
>>>   				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
>>>   		}
>>> @@ -1646,7 +1715,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
>>>   		return -EIO;
>>>   	}
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>>   
>>>   	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
>>>   	    q->requires_requests) {
>>> @@ -2022,12 +2096,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>>   	 * to vb2 in stop_streaming().
>>>   	 */
>>>   	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
>>> -		for (i = 0; i < q->num_buffers; ++i)
>>> -			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
>>> +		for (i = 0; i < q->num_buffers; ++i) {
>>> +			struct vb2_buffer *vb = vb2_get_buffer(q, i);
>>> +
>>> +			if (!vb)
>>> +				continue;
>>> +
>>> +			if (vb->state == VB2_BUF_STATE_ACTIVE) {
>>>   				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
>>> -					q->bufs[i]);
>>> -				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
>>> +					vb);
>>> +				vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
>>>   			}
>>> +		}
>>>   		/* Must be zero now */
>>>   		WARN_ON(atomic_read(&q->owned_by_drv_count));
>>>   	}
>>> @@ -2061,9 +2141,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>>   	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
>>>   	 */
>>>   	for (i = 0; i < q->num_buffers; ++i) {
>>> -		struct vb2_buffer *vb = q->bufs[i];
>>> -		struct media_request *req = vb->req_obj.req;
>>> +		struct vb2_buffer *vb;
>>> +		struct media_request *req;
>>>   
>>> +		vb = vb2_get_buffer(q, i);
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		req = vb->req_obj.req;
>>>   		/*
>>>   		 * If a request is associated with this buffer, then
>>>   		 * call buf_request_cancel() to give the driver to complete()
>>> @@ -2215,7 +2300,10 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>>   	 * return its buffer and plane numbers.
>>>   	 */
>>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>>> -		vb = q->bufs[buffer];
>>> +		vb = vb2_get_buffer(q, buffer);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		for (plane = 0; plane < vb->num_planes; ++plane) {
>>>   			if (vb->planes[plane].m.offset == off) {
>>> @@ -2262,7 +2350,12 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = q->bufs[index];
>>> +	vb = vb2_get_buffer(q, index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>>   
>>>   	if (plane >= vb->num_planes) {
>>>   		dprintk(q, 1, "buffer plane out of range\n");
>>> @@ -2339,7 +2432,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>>   	if (ret)
>>>   		goto unlock;
>>>   
>>> -	vb = q->bufs[buffer];
>>> +	vb = vb2_get_buffer(q, buffer);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		ret = -EINVAL;
>>> +		goto unlock;
>>> +	}
>>>   
>>>   	/*
>>>   	 * MMAP requires page_aligned buffers.
>>> @@ -2396,7 +2495,12 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>>   	if (ret)
>>>   		goto unlock;
>>>   
>>> -	vb = q->bufs[buffer];
>>> +	vb = vb2_get_buffer(q, buffer);
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		ret = -EINVAL;
>>> +		goto unlock;
>>> +	}
>>>   
>>>   	vaddr = vb2_plane_vaddr(vb, plane);
>>>   	mutex_unlock(&q->mmap_lock);
>>> @@ -2625,6 +2729,7 @@ struct vb2_fileio_data {
>>>   static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   {
>>>   	struct vb2_fileio_data *fileio;
>>> +	struct vb2_buffer *vb;
>>>   	int i, ret;
>>>   	unsigned int count = 0;
>>>   
>>> @@ -2679,7 +2784,13 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   	 * Check if plane_count is correct
>>>   	 * (multiplane buffers are not supported).
>>>   	 */
>>> -	if (q->bufs[0]->num_planes != 1) {
>>> +	vb = vb2_get_buffer(q, 0);
>>> +	if (!vb) {
>>> +		ret = -EBUSY;
>>> +		goto err_reqbufs;
>>> +	}
>>> +
>>> +	if (vb->num_planes != 1) {
>>>   		ret = -EBUSY;
>>>   		goto err_reqbufs;
>>>   	}
>>> @@ -2688,12 +2799,17 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>>   	 * Get kernel address of each buffer.
>>>   	 */
>>>   	for (i = 0; i < q->num_buffers; i++) {
>>> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>>> +		vb = vb2_get_buffer(q, i);
>>> +
>>> +		if (!vb)
>>> +			continue;
>>> +
>>> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(vb, 0);
>>>   		if (fileio->bufs[i].vaddr == NULL) {
>>>   			ret = -EINVAL;
>>>   			goto err_reqbufs;
>>>   		}
>>> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>>> +		fileio->bufs[i].size = vb2_plane_size(vb, 0);
>>>   	}
>>>   
>>>   	/*
>>> @@ -2821,15 +2937,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   
>>>   		fileio->cur_index = index;
>>>   		buf = &fileio->bufs[index];
>>> -		b = q->bufs[index];
>>> +		b = vb2_get_buffer(q, index);
>>> +
>>> +		if (!b)
>>> +			return -EINVAL;
>>>   
>>>   		/*
>>>   		 * Get number of bytes filled by the driver
>>>   		 */
>>>   		buf->pos = 0;
>>>   		buf->queued = 0;
>>> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>>> -				 : vb2_plane_size(q->bufs[index], 0);
>>> +		buf->size = read ? vb2_get_plane_payload(b, 0)
>>> +				 : vb2_plane_size(b, 0);
>>>   		/* Compensate for data_offset on read in the multiplanar case. */
>>>   		if (is_multiplanar && read &&
>>>   				b->planes[0].data_offset < buf->size) {
>>> @@ -2872,8 +2991,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   	 * Queue next buffer if required.
>>>   	 */
>>>   	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>>> -		struct vb2_buffer *b = q->bufs[index];
>>> +		struct vb2_buffer *b = vb2_get_buffer(q, index);
>>>   
>>> +		if (!b) {
>>> +			dprintk(q, 1, "can't find the requested buffer\n");
>>> +			return -EINVAL;
>>> +		}
>>>   		/*
>>>   		 * Check if this is the last buffer to read.
>>>   		 */
>>> @@ -2899,7 +3022,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>>   		 */
>>>   		buf->pos = 0;
>>>   		buf->queued = 1;
>>> -		buf->size = vb2_plane_size(q->bufs[index], 0);
>>> +		buf->size = vb2_plane_size(b, 0);
>>>   		fileio->q_count += 1;
>>>   		/*
>>>   		 * If we are queuing up buffers for the first time, then
>>> @@ -2970,7 +3093,9 @@ static int vb2_thread(void *data)
>>>   		 * Call vb2_dqbuf to get buffer back.
>>>   		 */
>>>   		if (prequeue) {
>>> -			vb = q->bufs[index++];
>>> +			vb = vb2_get_buffer(q, index++);
>>> +			if (!vb)
>>> +				continue;
>>>   			prequeue--;
>>>   		} else {
>>>   			call_void_qop(q, wait_finish, q);
>>> @@ -2979,7 +3104,7 @@ static int vb2_thread(void *data)
>>>   			call_void_qop(q, wait_prepare, q);
>>>   			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
>>>   			if (!ret)
>>> -				vb = q->bufs[index];
>>> +				vb = vb2_get_buffer(q, index);
>>>   		}
>>>   		if (ret || threadio->stop)
>>>   			break;
>>> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> index c7a54d82a55e..724135d41f7f 100644
>>> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
>>> @@ -383,8 +383,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	if (q->bufs[b->index] == NULL) {
>>> -		/* Should never happen */
>>> +	if (!vb2_get_buffer(q, b->index)) {
>>>   		dprintk(q, 1, "%s: buffer is NULL\n", opname);
>>>   		return -EINVAL;
>>>   	}
>>> @@ -394,7 +393,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = q->bufs[b->index];
>>> +	vb = vb2_get_buffer(q, b->index);
>>>   	vbuf = to_vb2_v4l2_buffer(vb);
>>>   	ret = __verify_planes_array(vb, b);
>>>   	if (ret)
>>> @@ -628,11 +627,18 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>>>   struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp)
>>>   {
>>>   	unsigned int i;
>>> +	struct vb2_buffer *vb2;
>>>   
>>> -	for (i = 0; i < q->num_buffers; i++)
>>> -		if (q->bufs[i]->copied_timestamp &&
>>> -		    q->bufs[i]->timestamp == timestamp)
>>> -			return vb2_get_buffer(q, i);
>>> +	for (i = 0; i < q->num_buffers; i++) {
>>> +		vb2 = vb2_get_buffer(q, i);
>>> +
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		if (vb2->copied_timestamp &&
>>> +		    vb2->timestamp == timestamp)
>>> +			return vb2;
>>> +	}
>>>   	return NULL;
>>>   }
>>>   EXPORT_SYMBOL_GPL(vb2_find_buffer);
>>> @@ -664,7 +670,13 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>>   		dprintk(q, 1, "buffer index out of range\n");
>>>   		return -EINVAL;
>>>   	}
>>> -	vb = q->bufs[b->index];
>>> +	vb = vb2_get_buffer(q, b->index);
>>> +
>>> +	if (!vb) {
>>> +		dprintk(q, 1, "can't find the requested buffer\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>>   	ret = __verify_planes_array(vb, b);
>>>   	if (!ret)
>>>   		vb2_core_querybuf(q, b->index, b);
>>> diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
>>> index 44b830ae01d8..e2c371c2fde5 100644
>>> --- a/drivers/media/platform/amphion/vpu_dbg.c
>>> +++ b/drivers/media/platform/amphion/vpu_dbg.c
>>> @@ -133,11 +133,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>>   
>>>   	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		struct vb2_buffer *vb = vq->bufs[i];
>>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>> +		struct vb2_buffer *vb;
>>> +		struct vb2_v4l2_buffer *vbuf;
>>> +
>>> +		vb = vb2_get_buffer(vq, i);
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>>   			continue;
>>> +
>>> +		vbuf = to_vb2_v4l2_buffer(vb);
>>> +
>>>   		num = scnprintf(str, sizeof(str),
>>>   				"output [%2d] state = %10s, %8s\n",
>>>   				i, vb2_stat_name[vb->state],
>>> @@ -148,11 +155,18 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
>>>   
>>>   	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		struct vb2_buffer *vb = vq->bufs[i];
>>> -		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>> +		struct vb2_buffer *vb;
>>> +		struct vb2_v4l2_buffer *vbuf;
>>> +
>>> +		vb = vb2_get_buffer(vq, i);
>>> +		if (!vb)
>>> +			continue;
>>>   
>>>   		if (vb->state == VB2_BUF_STATE_DEQUEUED)
>>>   			continue;
>>> +
>>> +		vbuf = to_vb2_v4l2_buffer(vb);
>>> +
>>>   		num = scnprintf(str, sizeof(str),
>>>   				"capture[%2d] state = %10s, %8s\n",
>>>   				i, vb2_stat_name[vb->state],
>>> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> index 0051f372a66c..ea37069ba355 100644
>>> --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
>>> @@ -603,7 +603,11 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>>   		return -EINVAL;
>>>   	}
>>>   
>>> -	vb = vq->bufs[buf->index];
>>> +	vb = vb2_get_buffer(vq, buf->index);
>>> +	if (!vb) {
>>> +		dev_err(ctx->jpeg->dev, "buffer not found\n");
>>> +		return -EINVAL;
>>> +	}
>>>   	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
>>>   	jpeg_src_buf->bs_size = buf->m.planes[0].bytesused;
>>>   
>>> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> index cf16cf2807f0..6532a69f1fa8 100644
>>> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
>>> @@ -1701,7 +1701,7 @@ static int vdec_vp9_slice_setup_core_buffer(struct vdec_vp9_slice_instance *inst
>>>   
>>>   	/* update internal buffer's width/height */
>>>   	for (i = 0; i < vq->num_buffers; i++) {
>>> -		if (vb == vq->bufs[i]) {
>>> +		if (vb == vb2_get_buffer(vq, i)) {
>>>   			instance->dpb[i].width = w;
>>>   			instance->dpb[i].height = h;
>>>   			break;
>>> diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> index 3a848ca32a0e..326be09bdb55 100644
>>> --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
>>> @@ -577,6 +577,10 @@ static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
>>>   		}
>>>   
>>>   		vb2_buf = vb2_get_buffer(vq, buf->index);
>>> +		if (!vb2_buf) {
>>> +			dev_dbg(dev, "%s buffer index %d not found\n", ctx->name, buf->index);
>>> +			return -EINVAL;
>>> +		}
>>>   		stream = to_hva_stream(to_vb2_v4l2_buffer(vb2_buf));
>>>   		stream->bytesused = buf->bytesused;
>>>   	}
>>> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
>>> index 318d675e5668..ba20ea998d19 100644
>>> --- a/drivers/media/test-drivers/visl/visl-dec.c
>>> +++ b/drivers/media/test-drivers/visl/visl-dec.c
>>> @@ -290,13 +290,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>>   	for (i = 0; i < out_q->num_buffers; i++) {
>>>   		char entry[] = "index: %u, state: %s, request_fd: %d, ";
>>>   		u32 old_len = len;
>>> -		char *q_status = visl_get_vb2_state(out_q->bufs[i]->state);
>>> +		struct vb2_buffer *vb2;
>>> +		char *q_status;
>>> +
>>> +		vb2 = vb2_get_buffer(out_q, i);
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		q_status = visl_get_vb2_state(vb2->state);
>>>   
>>>   		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>>   				 entry, i, q_status,
>>> -				 to_vb2_v4l2_buffer(out_q->bufs[i])->request_fd);
>>> +				 to_vb2_v4l2_buffer(vb2)->request_fd);
>>>   
>>> -		len += visl_fill_bytesused(to_vb2_v4l2_buffer(out_q->bufs[i]),
>>> +		len += visl_fill_bytesused(to_vb2_v4l2_buffer(vb2),
>>>   					   &buf[len],
>>>   					   TPG_STR_BUF_SZ - len);
>>>   
>>> @@ -342,13 +349,20 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
>>>   	len = 0;
>>>   	for (i = 0; i < cap_q->num_buffers; i++) {
>>>   		u32 old_len = len;
>>> -		char *q_status = visl_get_vb2_state(cap_q->bufs[i]->state);
>>> +		struct vb2_buffer *vb2;
>>> +		char *q_status;
>>> +
>>> +		vb2 = vb2_get_buffer(cap_q, i);
>>> +		if (!vb2)
>>> +			continue;
>>> +
>>> +		q_status = visl_get_vb2_state(vb2->state);
>>>   
>>>   		len += scnprintf(&buf[len], TPG_STR_BUF_SZ - len,
>>>   				 "index: %u, status: %s, timestamp: %llu, is_held: %d",
>>> -				 cap_q->bufs[i]->index, q_status,
>>> -				 cap_q->bufs[i]->timestamp,
>>> -				 to_vb2_v4l2_buffer(cap_q->bufs[i])->is_held);
>>> +				 vb2->index, q_status,
>>> +				 vb2->timestamp,
>>> +				 to_vb2_v4l2_buffer(vb2)->is_held);
>>>   
>>>   		tpg_gen_text(&ctx->tpg, basep, line++ * line_height, 16, &buf[old_len]);
>>>   		frame_dprintk(ctx->dev, run->dst->sequence, "%s", &buf[old_len]);
>>> diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> index 384f31fc66c5..8df301ab41ad 100644
>>> --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
>>> @@ -1077,7 +1077,7 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
>>>   	if (ret)
>>>   		return ret;
>>>   
>>> -	vb = pipe->vb_queue.bufs[buf->index];
>>> +	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
>>>   	frame = vb_to_frame(vb);
>>>   
>>>   	buf->reserved = asd->frame_status[buf->index];
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
  2023-08-21 14:41     ` Hans Verkuil
  (?)
@ 2023-08-22 12:55       ` Benjamin Gaignard
  -1 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-08-22 12:55 UTC (permalink / raw)
  To: Hans Verkuil, mchehab, tfiga, m.szyprowski, ming.qian, ezequiel,
	p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel


Le 21/08/2023 à 16:41, Hans Verkuil a écrit :
> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>> Store computed values of chroma and motion vectors offset because
>> they depends on width and height values which change if the resolution
>> change.
> Is this a bug fix? Does this patch belong in this series?
>
> Same actually for the next few verisilicon patches. Shouldn't they be
> part of a separate 'fixes' patch series? It's confusing to see them
> in this series.

They fix bugs that happens only when VP9 resolution change without doing stream off/on
that why they are in this series.

This one, for example, is useless if the resolution change on a keyframe because the
frame will have the same resolution than the current one but is need to store resolution
of each frames if the resize happens between keyframes.

Benjamin

>
> Regards,
>
> 	Hans
>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>> ---
>>   drivers/media/platform/verisilicon/hantro.h            | 2 ++
>>   drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
>>   2 files changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
>> index c8a3cf10cc64..53be00142473 100644
>> --- a/drivers/media/platform/verisilicon/hantro.h
>> +++ b/drivers/media/platform/verisilicon/hantro.h
>> @@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
>>   	/* Info needed when the decoded frame serves as a reference frame. */
>>   	unsigned short width;
>>   	unsigned short height;
>> +	size_t chroma_offset;
>> +	size_t mv_offset;
>>   	u32 bit_depth : 4;
>>   };
>>   
>> diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> index 6fc4b555517f..6db1c32fce4d 100644
>> --- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> +++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> @@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
>>   
>>   	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>>   	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
>> +	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
>>   
>>   	mv_addr = luma_addr + mv_offset(ctx, dec_params);
>>   	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
>> +	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
>>   }
>>   
>>   struct hantro_vp9_ref_reg {
>> @@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
>>   	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
>>   	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
>>   
>> -	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>> +	chroma_addr = luma_addr + buf->vp9.chroma_offset;
>>   	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
>>   }
>>   
>> @@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
>>   	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
>>   
>>   	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
>> -		  mv_offset(ctx, dec_params);
>> +		  mv_ref->vp9.mv_offset;
>>   	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
>>   
>>   	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
@ 2023-08-22 12:55       ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-08-22 12:55 UTC (permalink / raw)
  To: Hans Verkuil, mchehab, tfiga, m.szyprowski, ming.qian, ezequiel,
	p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel


Le 21/08/2023 à 16:41, Hans Verkuil a écrit :
> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>> Store computed values of chroma and motion vectors offset because
>> they depends on width and height values which change if the resolution
>> change.
> Is this a bug fix? Does this patch belong in this series?
>
> Same actually for the next few verisilicon patches. Shouldn't they be
> part of a separate 'fixes' patch series? It's confusing to see them
> in this series.

They fix bugs that happens only when VP9 resolution change without doing stream off/on
that why they are in this series.

This one, for example, is useless if the resolution change on a keyframe because the
frame will have the same resolution than the current one but is need to store resolution
of each frames if the resize happens between keyframes.

Benjamin

>
> Regards,
>
> 	Hans
>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>> ---
>>   drivers/media/platform/verisilicon/hantro.h            | 2 ++
>>   drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
>>   2 files changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
>> index c8a3cf10cc64..53be00142473 100644
>> --- a/drivers/media/platform/verisilicon/hantro.h
>> +++ b/drivers/media/platform/verisilicon/hantro.h
>> @@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
>>   	/* Info needed when the decoded frame serves as a reference frame. */
>>   	unsigned short width;
>>   	unsigned short height;
>> +	size_t chroma_offset;
>> +	size_t mv_offset;
>>   	u32 bit_depth : 4;
>>   };
>>   
>> diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> index 6fc4b555517f..6db1c32fce4d 100644
>> --- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> +++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> @@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
>>   
>>   	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>>   	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
>> +	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
>>   
>>   	mv_addr = luma_addr + mv_offset(ctx, dec_params);
>>   	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
>> +	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
>>   }
>>   
>>   struct hantro_vp9_ref_reg {
>> @@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
>>   	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
>>   	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
>>   
>> -	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>> +	chroma_addr = luma_addr + buf->vp9.chroma_offset;
>>   	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
>>   }
>>   
>> @@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
>>   	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
>>   
>>   	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
>> -		  mv_offset(ctx, dec_params);
>> +		  mv_ref->vp9.mv_offset;
>>   	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
>>   
>>   	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset
@ 2023-08-22 12:55       ` Benjamin Gaignard
  0 siblings, 0 replies; 51+ messages in thread
From: Benjamin Gaignard @ 2023-08-22 12:55 UTC (permalink / raw)
  To: Hans Verkuil, mchehab, tfiga, m.szyprowski, ming.qian, ezequiel,
	p.zabel, gregkh, nicolas.dufresne
  Cc: linux-media, linux-kernel, linux-arm-kernel, linux-mediatek,
	linux-arm-msm, linux-rockchip, linux-staging, kernel


Le 21/08/2023 à 16:41, Hans Verkuil a écrit :
> On 05/07/2023 14:10, Benjamin Gaignard wrote:
>> Store computed values of chroma and motion vectors offset because
>> they depends on width and height values which change if the resolution
>> change.
> Is this a bug fix? Does this patch belong in this series?
>
> Same actually for the next few verisilicon patches. Shouldn't they be
> part of a separate 'fixes' patch series? It's confusing to see them
> in this series.

They fix bugs that happens only when VP9 resolution change without doing stream off/on
that why they are in this series.

This one, for example, is useless if the resolution change on a keyframe because the
frame will have the same resolution than the current one but is need to store resolution
of each frames if the resize happens between keyframes.

Benjamin

>
> Regards,
>
> 	Hans
>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>> ---
>>   drivers/media/platform/verisilicon/hantro.h            | 2 ++
>>   drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++--
>>   2 files changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
>> index c8a3cf10cc64..53be00142473 100644
>> --- a/drivers/media/platform/verisilicon/hantro.h
>> +++ b/drivers/media/platform/verisilicon/hantro.h
>> @@ -320,6 +320,8 @@ struct hantro_vp9_decoded_buffer_info {
>>   	/* Info needed when the decoded frame serves as a reference frame. */
>>   	unsigned short width;
>>   	unsigned short height;
>> +	size_t chroma_offset;
>> +	size_t mv_offset;
>>   	u32 bit_depth : 4;
>>   };
>>   
>> diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> index 6fc4b555517f..6db1c32fce4d 100644
>> --- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> +++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
>> @@ -158,9 +158,11 @@ static void config_output(struct hantro_ctx *ctx,
>>   
>>   	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>>   	hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr);
>> +	dst->vp9.chroma_offset = chroma_offset(ctx, dec_params);
>>   
>>   	mv_addr = luma_addr + mv_offset(ctx, dec_params);
>>   	hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr);
>> +	dst->vp9.mv_offset = mv_offset(ctx, dec_params);
>>   }
>>   
>>   struct hantro_vp9_ref_reg {
>> @@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx *ctx,
>>   	luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf);
>>   	hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr);
>>   
>> -	chroma_addr = luma_addr + chroma_offset(ctx, dec_params);
>> +	chroma_addr = luma_addr + buf->vp9.chroma_offset;
>>   	hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr);
>>   }
>>   
>> @@ -238,7 +240,7 @@ static void config_ref_registers(struct hantro_ctx *ctx,
>>   	config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts);
>>   
>>   	mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) +
>> -		  mv_offset(ctx, dec_params);
>> +		  mv_ref->vp9.mv_offset;
>>   	hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr);
>>   
>>   	hantro_reg_write(ctx->dev, &vp9_last_sign_bias,

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2023-08-22 12:56 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-05 12:10 [PATCH v4 00/10] Add DELETE_BUF ioctl Benjamin Gaignard
2023-07-05 12:10 ` Benjamin Gaignard
2023-07-05 12:10 ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 01/10] media: videobuf2: Access vb2_queue bufs array through helper functions Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-08-21 14:24   ` Hans Verkuil
2023-08-21 14:24     ` Hans Verkuil
2023-08-21 14:24     ` Hans Verkuil
2023-08-21 14:31     ` Hans Verkuil
2023-08-21 14:31       ` Hans Verkuil
2023-08-21 14:31       ` Hans Verkuil
2023-08-22 12:49       ` Benjamin Gaignard
2023-08-22 12:49         ` Benjamin Gaignard
2023-08-22 12:49         ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 02/10] media: videobuf2: Be more flexible on the number of queue stored buffers Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 03/10] media: videobuf2: Rework offset 'cookie' encoding pattern Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 04/10] media: verisilicon: Refactor postprocessor to store more buffers Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-08-21 14:38   ` Hans Verkuil
2023-08-21 14:38     ` Hans Verkuil
2023-08-21 14:38     ` Hans Verkuil
2023-07-05 12:10 ` [PATCH v4 05/10] media: verisilicon: Store chroma and motion vectors offset Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-08-21 14:41   ` Hans Verkuil
2023-08-21 14:41     ` Hans Verkuil
2023-08-21 14:41     ` Hans Verkuil
2023-08-22 12:55     ` Benjamin Gaignard
2023-08-22 12:55       ` Benjamin Gaignard
2023-08-22 12:55       ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 06/10] media: verisilicon: vp9: Use destination buffer height to compute chroma offset Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 07/10] media: verisilicon: postproc: Fix down scale test Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 08/10] media: verisilicon: vp9: Allow to change resolution while streaming Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 09/10] media: v4l2: Add DELETE_BUFS ioctl Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10 ` [PATCH v4 10/10] media: v4l2: Add mem2mem helpers for " Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard
2023-07-05 12:10   ` Benjamin Gaignard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.