From e7311aa47a6ac355558bc65512aa7c381f8506ec Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Mon, 5 Aug 2024 07:59:43 +0000 Subject: media: siano: Simplify smscore_load_firmware_from_file The function is never called with a loadfirmware_handler, so we can remove some dead code. We can also use this as a excuse to remove some unused type definitions. This fixes the following smatch warning: drivers/media/common/siano/smscoreapi.c:1172 smscore_load_firmware_from_file() error: we previously assumed 'loadfirmware_handler' could be null (see line 1150) Signed-off-by: Ricardo Ribalda Reported-by: Hans Verkuil Closes: https://lore.kernel.org/linux-media/99bd75a0-a6f3-4c47-bc89-70ffd87da756@xs4all.nl/T/#t Signed-off-by: Hans Verkuil --- drivers/media/common/siano/smscoreapi.c | 15 +++++---------- drivers/media/common/siano/smscoreapi.h | 4 ---- 2 files changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index b6f1eb5dbbdf..3732367e0c62 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -1132,8 +1132,7 @@ static char *smscore_get_fw_filename(struct smscore_device_t *coredev, * return: 0 on success, <0 on error. */ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, - int mode, - loadfirmware_t loadfirmware_handler) + int mode) { int rc = -ENOENT; u8 *fw_buf; @@ -1147,8 +1146,7 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, } pr_debug("Firmware name: %s\n", fw_filename); - if (!loadfirmware_handler && - !(coredev->device_flags & SMS_DEVICE_FAMILY2)) + if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) return -EINVAL; rc = request_firmware(&fw, fw_filename, coredev->device); @@ -1166,10 +1164,8 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, memcpy(fw_buf, fw->data, fw->size); fw_buf_size = fw->size; - rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? - smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size) - : loadfirmware_handler(coredev->context, fw_buf, - fw_buf_size); + rc = smscore_load_firmware_family2(coredev, fw_buf, + fw_buf_size); } kfree(fw_buf); @@ -1353,8 +1349,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) } if (!(coredev->modes_supported & (1 << mode))) { - rc = smscore_load_firmware_from_file(coredev, - mode, NULL); + rc = smscore_load_firmware_from_file(coredev, mode); if (rc >= 0) pr_debug("firmware download success\n"); } else { diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h index 82d9f8a64d99..3c15082ce0e3 100644 --- a/drivers/media/common/siano/smscoreapi.h +++ b/drivers/media/common/siano/smscoreapi.h @@ -97,7 +97,6 @@ typedef int (*hotplug_t)(struct smscore_device_t *coredev, typedef int (*setmode_t)(void *context, int mode); typedef void (*detectmode_t)(void *context, int *mode); typedef int (*sendrequest_t)(void *context, void *buffer, size_t size); -typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size); typedef int (*preload_t)(void *context); typedef int (*postload_t)(void *context); @@ -1102,9 +1101,6 @@ extern int smscore_register_device(struct smsdevice_params_t *params, extern void smscore_unregister_device(struct smscore_device_t *coredev); extern int smscore_start_device(struct smscore_device_t *coredev); -extern int smscore_load_firmware(struct smscore_device_t *coredev, - char *filename, - loadfirmware_t loadfirmware_handler); extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode); extern int smscore_get_device_mode(struct smscore_device_t *coredev); -- cgit v1.3.1 From 6a9c97ab6b7e85697e0b74e86062192a5ffffd99 Mon Sep 17 00:00:00 2001 From: Yunke Cao Date: Wed, 14 Aug 2024 11:06:40 +0900 Subject: media: videobuf2-core: clear memory related fields in __vb2_plane_dmabuf_put() Clear vb2_plane's memory related fields in __vb2_plane_dmabuf_put(), including bytesused, length, fd and data_offset. Remove the duplicated code in __prepare_dmabuf(). Signed-off-by: Yunke Cao Acked-by: Tomasz Figa Signed-off-by: Hans Verkuil --- drivers/media/common/videobuf2/videobuf2-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 0217392fcc0d..4d232b08f950 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -311,6 +311,10 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p) p->mem_priv = NULL; p->dbuf = NULL; p->dbuf_mapped = 0; + p->bytesused = 0; + p->length = 0; + p->m.fd = 0; + p->data_offset = 0; } /* @@ -1420,10 +1424,6 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) /* Release previously acquired memory if present */ __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); - vb->planes[plane].bytesused = 0; - vb->planes[plane].length = 0; - vb->planes[plane].m.fd = 0; - vb->planes[plane].data_offset = 0; /* Acquire each plane's memory */ mem_priv = call_ptr_memop(attach_dmabuf, -- cgit v1.3.1 From 95af7c00f35b9cb0873afb8f191f42e04714ed2a Mon Sep 17 00:00:00 2001 From: Yunke Cao Date: Wed, 14 Aug 2024 11:06:41 +0900 Subject: media: videobuf2-core: release all planes first in __prepare_dmabuf() In the existing implementation, validating planes, checking if the planes changed, releasing previous planes and reaquiring new planes all happens in the same for loop. Split the for loop into 3 parts 1. In the first for loop, validate planes and check if planes changed. 2. Call __vb2_buf_dmabuf_put() to release all planes. 3. In the second for loop, reaquire new planes. Signed-off-by: Yunke Cao Acked-by: Tomasz Figa Signed-off-by: Hans Verkuil --- drivers/media/common/videobuf2/videobuf2-core.c | 115 ++++++++++++------------ 1 file changed, 59 insertions(+), 56 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 4d232b08f950..b53d94659e30 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -1387,11 +1387,13 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) for (plane = 0; plane < vb->num_planes; ++plane) { struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd); + planes[plane].dbuf = dbuf; + if (IS_ERR_OR_NULL(dbuf)) { dprintk(q, 1, "invalid dmabuf fd for plane %d\n", plane); ret = -EINVAL; - goto err; + goto err_put_planes; } /* use DMABUF size if length is not provided */ @@ -1402,76 +1404,68 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) dprintk(q, 1, "invalid dmabuf length %u for plane %d, minimum length %u\n", planes[plane].length, plane, vb->planes[plane].min_length); - dma_buf_put(dbuf); ret = -EINVAL; - goto err; + goto err_put_planes; } /* Skip the plane if already verified */ if (dbuf == vb->planes[plane].dbuf && - vb->planes[plane].length == planes[plane].length) { - dma_buf_put(dbuf); + vb->planes[plane].length == planes[plane].length) continue; - } dprintk(q, 3, "buffer for plane %d changed\n", plane); - if (!reacquired) { - reacquired = true; + reacquired = true; + } + + if (reacquired) { + if (vb->planes[0].mem_priv) { vb->copied_timestamp = 0; call_void_vb_qop(vb, buf_cleanup, vb); + __vb2_buf_dmabuf_put(vb); } - /* Release previously acquired memory if present */ - __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); - - /* Acquire each plane's memory */ - mem_priv = call_ptr_memop(attach_dmabuf, - vb, - q->alloc_devs[plane] ? : q->dev, - dbuf, - planes[plane].length); - if (IS_ERR(mem_priv)) { - dprintk(q, 1, "failed to attach dmabuf\n"); - ret = PTR_ERR(mem_priv); - dma_buf_put(dbuf); - goto err; - } - - vb->planes[plane].dbuf = dbuf; - vb->planes[plane].mem_priv = mem_priv; - } + for (plane = 0; plane < vb->num_planes; ++plane) { + /* Acquire each plane's memory */ + mem_priv = call_ptr_memop(attach_dmabuf, + vb, + q->alloc_devs[plane] ? : q->dev, + planes[plane].dbuf, + planes[plane].length); + if (IS_ERR(mem_priv)) { + dprintk(q, 1, "failed to attach dmabuf\n"); + ret = PTR_ERR(mem_priv); + goto err_put_vb2_buf; + } - /* - * This pins the buffer(s) with dma_buf_map_attachment()). It's done - * here instead just before the DMA, while queueing the buffer(s) so - * userspace knows sooner rather than later if the dma-buf map fails. - */ - for (plane = 0; plane < vb->num_planes; ++plane) { - if (vb->planes[plane].dbuf_mapped) - continue; + vb->planes[plane].dbuf = planes[plane].dbuf; + vb->planes[plane].mem_priv = mem_priv; - ret = call_memop(vb, map_dmabuf, vb->planes[plane].mem_priv); - if (ret) { - dprintk(q, 1, "failed to map dmabuf for plane %d\n", - plane); - goto err; + /* + * This pins the buffer(s) with dma_buf_map_attachment()). It's done + * here instead just before the DMA, while queueing the buffer(s) so + * userspace knows sooner rather than later if the dma-buf map fails. + */ + ret = call_memop(vb, map_dmabuf, vb->planes[plane].mem_priv); + if (ret) { + dprintk(q, 1, "failed to map dmabuf for plane %d\n", + plane); + goto err_put_vb2_buf; + } + vb->planes[plane].dbuf_mapped = 1; } - vb->planes[plane].dbuf_mapped = 1; - } - /* - * Now that everything is in order, copy relevant information - * provided by userspace. - */ - for (plane = 0; plane < vb->num_planes; ++plane) { - vb->planes[plane].bytesused = planes[plane].bytesused; - vb->planes[plane].length = planes[plane].length; - vb->planes[plane].m.fd = planes[plane].m.fd; - vb->planes[plane].data_offset = planes[plane].data_offset; - } + /* + * Now that everything is in order, copy relevant information + * provided by userspace. + */ + for (plane = 0; plane < vb->num_planes; ++plane) { + vb->planes[plane].bytesused = planes[plane].bytesused; + vb->planes[plane].length = planes[plane].length; + vb->planes[plane].m.fd = planes[plane].m.fd; + vb->planes[plane].data_offset = planes[plane].data_offset; + } - if (reacquired) { /* * Call driver-specific initialization on the newly acquired buffer, * if provided. @@ -1479,19 +1473,28 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) ret = call_vb_qop(vb, buf_init, vb); if (ret) { dprintk(q, 1, "buffer initialization failed\n"); - goto err; + goto err_put_vb2_buf; } + } else { + for (plane = 0; plane < vb->num_planes; ++plane) + dma_buf_put(planes[plane].dbuf); } ret = call_vb_qop(vb, buf_prepare, vb); if (ret) { dprintk(q, 1, "buffer preparation failed\n"); call_void_vb_qop(vb, buf_cleanup, vb); - goto err; + goto err_put_vb2_buf; } return 0; -err: + +err_put_planes: + for (plane = 0; plane < vb->num_planes; ++plane) { + if (!IS_ERR_OR_NULL(planes[plane].dbuf)) + dma_buf_put(planes[plane].dbuf); + } +err_put_vb2_buf: /* In case of errors, release planes that were already acquired */ __vb2_buf_dmabuf_put(vb); -- cgit v1.3.1 From 1da4e16130d36c712e00bf045f09f194aac964b8 Mon Sep 17 00:00:00 2001 From: Yunke Cao Date: Wed, 14 Aug 2024 11:06:42 +0900 Subject: media: videobuf2-core: reverse the iteration order in __vb2_buf_dmabuf_put This patch prepares for allowing multiple planes to share the same DMA buffer attachment. Release the planes from num_planes - 1 to 0 so that we don't leave invalid mem_priv pointers behind. Signed-off-by: Yunke Cao Acked-by: Tomasz Figa Signed-off-by: Hans Verkuil --- drivers/media/common/videobuf2/videobuf2-core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index b53d94659e30..e6af963307e3 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -323,9 +323,15 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p) */ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb) { - unsigned int plane; + int plane; - for (plane = 0; plane < vb->num_planes; ++plane) + /* + * When multiple planes share the same DMA buffer attachment, the plane + * with the lowest index owns the mem_priv. + * Put planes in the reversed order so that we don't leave invalid + * mem_priv behind. + */ + for (plane = vb->num_planes - 1; plane >= 0; --plane) __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); } -- cgit v1.3.1 From 03a979b74dc1ad5aeed8026a84d8771842cb1631 Mon Sep 17 00:00:00 2001 From: Yunke Cao Date: Wed, 14 Aug 2024 11:06:43 +0900 Subject: media: videobuf2-core: attach once if multiple planes share the same dbuf When multiple planes use the same dma buf, each plane will have its own dma buf attachment and mapping. It is a waste of IOVA space. This patch adds a dbuf_duplicated boolean in vb2_plane. If a plane's dbuf is the same as an existing plane, do not create another attachment and mapping. Signed-off-by: Yunke Cao Acked-by: Tomasz Figa Signed-off-by: Hans Verkuil --- drivers/media/common/videobuf2/videobuf2-core.c | 30 +++++++++++++++++++++---- include/media/videobuf2-core.h | 3 +++ 2 files changed, 29 insertions(+), 4 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index e6af963307e3..500a4e0c84ab 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -303,10 +303,13 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p) if (!p->mem_priv) return; - if (p->dbuf_mapped) - call_void_memop(vb, unmap_dmabuf, p->mem_priv); + if (!p->dbuf_duplicated) { + if (p->dbuf_mapped) + call_void_memop(vb, unmap_dmabuf, p->mem_priv); + + call_void_memop(vb, detach_dmabuf, p->mem_priv); + } - call_void_memop(vb, detach_dmabuf, p->mem_priv); dma_buf_put(p->dbuf); p->mem_priv = NULL; p->dbuf = NULL; @@ -315,6 +318,7 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p) p->length = 0; p->m.fd = 0; p->data_offset = 0; + p->dbuf_duplicated = false; } /* @@ -1379,7 +1383,7 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) struct vb2_plane planes[VB2_MAX_PLANES]; struct vb2_queue *q = vb->vb2_queue; void *mem_priv; - unsigned int plane; + unsigned int plane, i; int ret = 0; bool reacquired = vb->planes[0].mem_priv == NULL; @@ -1432,6 +1436,24 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) } for (plane = 0; plane < vb->num_planes; ++plane) { + /* + * This is an optimization to reduce dma_buf attachment/mapping. + * When the same dma_buf is used for multiple planes, there is no need + * to create duplicated attachments. + */ + for (i = 0; i < plane; ++i) { + if (planes[plane].dbuf == vb->planes[i].dbuf && + q->alloc_devs[plane] == q->alloc_devs[i]) { + vb->planes[plane].dbuf_duplicated = true; + vb->planes[plane].dbuf = vb->planes[i].dbuf; + vb->planes[plane].mem_priv = vb->planes[i].mem_priv; + break; + } + } + + if (vb->planes[plane].dbuf_duplicated) + continue; + /* Acquire each plane's memory */ mem_priv = call_ptr_memop(attach_dmabuf, vb, diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 955237ac503d..9b02aeba4108 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -154,6 +154,8 @@ struct vb2_mem_ops { * @mem_priv: private data with this plane. * @dbuf: dma_buf - shared buffer object. * @dbuf_mapped: flag to show whether dbuf is mapped or not + * @dbuf_duplicated: boolean to show whether dbuf is duplicated with a + * previous plane of the buffer. * @bytesused: number of bytes occupied by data in the plane (payload). * @length: size of this plane (NOT the payload) in bytes. The maximum * valid size is MAX_UINT - PAGE_SIZE. @@ -179,6 +181,7 @@ struct vb2_plane { void *mem_priv; struct dma_buf *dbuf; unsigned int dbuf_mapped; + bool dbuf_duplicated; unsigned int bytesused; unsigned int length; unsigned int min_length; -- cgit v1.3.1 From e5700c9037727d5a69a677d6dba25010b485d65b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 26 Aug 2024 02:24:49 +0300 Subject: media: videobuf2: Drop minimum allocation requirement of 2 buffers When introducing the ability for drivers to indicate the minimum number of buffers they require an application to allocate, commit 6662edcd32cc ("media: videobuf2: Add min_reqbufs_allocation field to vb2_queue structure") also introduced a global minimum of 2 buffers. It turns out this breaks the Renesas R-Car VSP test suite, where a test that allocates a single buffer fails when two buffers are used. One may consider debatable whether test suite failures without failures in production use cases should be considered as a regression, but operation with a single buffer is a valid use case. While full frame rate can't be maintained, memory-to-memory devices can still be used with a decent efficiency, and requiring applications to allocate multiple buffers for single-shot use cases with capture devices would just waste memory. For those reasons, fix the regression by dropping the global minimum of buffers. Individual drivers can still set their own minimum. Fixes: 6662edcd32cc ("media: videobuf2: Add min_reqbufs_allocation field to vb2_queue structure") Cc: stable@vger.kernel.org Signed-off-by: Laurent Pinchart Reviewed-by: Hans Verkuil Acked-by: Tomasz Figa Link: https://lore.kernel.org/r/20240825232449.25905-1-laurent.pinchart+renesas@ideasonboard.com Signed-off-by: Laurent Pinchart --- drivers/media/common/videobuf2/videobuf2-core.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 500a4e0c84ab..29a8d876e6c2 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -2632,13 +2632,6 @@ int vb2_core_queue_init(struct vb2_queue *q) if (WARN_ON(q->supports_requests && q->min_queued_buffers)) return -EINVAL; - /* - * The minimum requirement is 2: one buffer is used - * by the hardware while the other is being processed by userspace. - */ - if (q->min_reqbufs_allocation < 2) - q->min_reqbufs_allocation = 2; - /* * If the driver needs 'min_queued_buffers' in the queue before * calling start_streaming() then the minimum requirement is -- cgit v1.3.1 From e7a9c987381a991f7ac54372ea45cfd4b160edcb Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Fri, 23 Aug 2024 17:48:39 +0800 Subject: media: siano: Remove unused declarations There is no caller and implementation in tree, so can remove them. Signed-off-by: Yue Haibing Reviewed-by: Ricardo Ribalda Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/common/siano/smscoreapi.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h index 3c15082ce0e3..d945a2d6d624 100644 --- a/drivers/media/common/siano/smscoreapi.h +++ b/drivers/media/common/siano/smscoreapi.h @@ -1115,12 +1115,6 @@ extern int smsclient_sendrequest(struct smscore_client_t *client, extern void smscore_onresponse(struct smscore_device_t *coredev, struct smscore_buffer_t *cb); -extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev); -extern int smscore_map_common_buffer(struct smscore_device_t *coredev, - struct vm_area_struct *vma); -extern int smscore_send_fw_file(struct smscore_device_t *coredev, - u8 *ufwbuf, int size); - extern struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev); extern void smscore_putbuffer(struct smscore_device_t *coredev, -- cgit v1.3.1