* [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs
@ 2026-10-19 7:14 Karl Mehltretter
2026-10-19 7:14 ` [PATCH 1/4] media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS Karl Mehltretter
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Karl Mehltretter @ 2026-10-19 7:14 UTC (permalink / raw)
To: linux-media
Cc: Tomasz Figa, Marek Szyprowski, Mauro Carvalho Chehab,
Laurent Pinchart, Hans de Goede, Hans Verkuil, Benjamin Gaignard,
Tomasz Stanislawski, Sumit Semwal, Christian König,
dri-devel, linaro-mm-sig, linux-kernel, Karl Mehltretter
UVC and vivid access imported DMA-BUFs with the CPU without cache
synchronization. On a Pi 400, captured data remained in the CPU cache
while physical RAM was stale.
Add an opt-in queue flag to bracket CPU access from buf_prepare() through
buf_finish(). The allocator cannot imply CPU use because some vb2-vmalloc
drivers pass buffers to hardware. Patch 1 balances finish operations in
VIDIOC_REMOVE_BUFS so removing prepared buffers closes this interval.
This follows the per-queue flag proposed here:
https://lists.openwall.net/linux-kernel/2024/06/20/236
Based on Linux 7.3. Tests cover the same code on these earlier bases:
- Pi 400, 7.3-rc4, all four patches: eight 640x480 YUYV frames per run,
imported CMA DMA-BUFs with a DRM device mapping:
Path Runs Stale frames
UVC, vb2-vmalloc 12 0/96
vivid, vb2-vmalloc 12 0/96
vivid, vb2-dma-contig 12 0/96
All six lifecycle cases passed with both vivid allocators. Read-only
output USERPTR passed. The test added no warnings or failed CPU-access
callbacks. A control without the DRM mapping found 4/16 stale frames.
- SAM9X75 (ARMv5), 6.18 backport of all four patches: the baseline
PREPARE_BUF/REMOVE_BUFS imbalance was fixed. USERPTR and six lifecycle
cases passed. All 128 vivid and 96 UVC frames matched RAM, with 100/100
begin/end calls. The baseline was already coherent.
- BeagleV Ahead (RISC-V), 7.3-rc7, patches 1, 2 and 4: read-only USERPTR,
six traced lifecycle cases and 60 repeats passed with balanced callbacks
and no kernel diagnostics. A vendor 5.10 backport of patches 2 and 3
captured 96 UVC frames without stale data, with 100/100 begin/end calls.
Its baseline was already coherent.
Karl Mehltretter (4):
media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS
media: videobuf2: add opt-in DMA-BUF CPU access
media: uvcvideo: synchronize imported DMA-BUFs for CPU access
media: vivid: synchronize imported DMA-BUFs for CPU access
.../media/common/videobuf2/videobuf2-core.c | 96 ++++++++++++++++++-
.../common/videobuf2/videobuf2-dma-contig.c | 5 +-
.../media/common/videobuf2/videobuf2-dma-sg.c | 5 +-
.../common/videobuf2/videobuf2-vmalloc.c | 5 +-
drivers/media/test-drivers/vivid/vivid-core.c | 1 +
drivers/media/usb/uvc/uvc_queue.c | 1 +
include/media/videobuf2-core.h | 12 ++-
7 files changed, 116 insertions(+), 9 deletions(-)
base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS
2026-10-19 7:14 [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Karl Mehltretter
@ 2026-10-19 7:14 ` Karl Mehltretter
2026-10-19 7:14 ` [PATCH 2/4] media: videobuf2: add opt-in DMA-BUF CPU access Karl Mehltretter
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Karl Mehltretter @ 2026-10-19 7:14 UTC (permalink / raw)
To: linux-media
Cc: Tomasz Figa, Marek Szyprowski, Mauro Carvalho Chehab,
Laurent Pinchart, Hans de Goede, Hans Verkuil, Benjamin Gaignard,
Tomasz Stanislawski, Sumit Semwal, Christian König,
dri-devel, linaro-mm-sig, linux-kernel, Karl Mehltretter
VIDIOC_PREPARE_BUF leaves a buffer DEQUEUED after calling buf_prepare()
and the prepare() memory operation. VIDIOC_REMOVE_BUFS accepts that state
but frees the buffer without calling the matching finish operations.
With VIDEO_ADV_DEBUG, vivid reports:
unbalanced counters for queue 000000009fa716f8, buffer 0:
buf_prepare: 1 buf_finish: 0
prepare: 1 finish: 0
Finish prepared buffers before freeing them, as queue cancellation does.
Fixes: a3293a85381e ("media: v4l2: Add REMOVE_BUFS ioctl")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
drivers/media/common/videobuf2/videobuf2-core.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index b0a6084f17573..460eaf4e82f78 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1746,6 +1746,19 @@ int vb2_core_remove_bufs(struct vb2_queue *q, unsigned int start, unsigned int c
goto unlock;
}
}
+
+ /* A buffer can be prepared without being queued. Finish it first. */
+ for (i = start; i < start + count; i++) {
+ struct vb2_buffer *vb = vb2_get_buffer(q, i);
+
+ if (!vb->prepared)
+ continue;
+
+ __vb2_buf_mem_finish(vb);
+ call_void_vb_qop(vb, buf_finish, vb);
+ vb->prepared = 0;
+ }
+
__vb2_queue_free(q, start, count);
dprintk(q, 2, "%u buffers removed\n", count);
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/4] media: videobuf2: add opt-in DMA-BUF CPU access
2026-10-19 7:14 [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Karl Mehltretter
2026-10-19 7:14 ` [PATCH 1/4] media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS Karl Mehltretter
@ 2026-10-19 7:14 ` Karl Mehltretter
2026-10-19 7:14 ` [PATCH 3/4] media: uvcvideo: synchronize imported DMA-BUFs for " Karl Mehltretter
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Karl Mehltretter @ 2026-10-19 7:14 UTC (permalink / raw)
To: linux-media
Cc: Tomasz Figa, Marek Szyprowski, Mauro Carvalho Chehab,
Laurent Pinchart, Hans de Goede, Hans Verkuil, Benjamin Gaignard,
Tomasz Stanislawski, Sumit Semwal, Christian König,
dri-devel, linaro-mm-sig, linux-kernel, Karl Mehltretter
Drivers must bracket CPU access to imported DMA-BUFs with
dma_buf_begin_cpu_access() and dma_buf_end_cpu_access().
Add a queue flag to do so from buf_prepare() through buf_finish(). Use
read access for output and write access for capture. Map imports
bidirectionally because CPU and device access directions are opposite.
Pass the mapping direction to attach_dmabuf() so USERPTR and MMAP keep
the queue's normal direction.
Keep this opt-in because some vb2-vmalloc drivers pass buffers to
hardware. End access in process context because DMA-BUF callbacks may
sleep.
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
.../media/common/videobuf2/videobuf2-core.c | 83 ++++++++++++++++++-
.../common/videobuf2/videobuf2-dma-contig.c | 5 +-
.../media/common/videobuf2/videobuf2-dma-sg.c | 5 +-
.../common/videobuf2/videobuf2-vmalloc.c | 5 +-
include/media/videobuf2-core.h | 12 ++-
5 files changed, 101 insertions(+), 9 deletions(-)
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 460eaf4e82f78..d2a78cd0a86bb 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -371,6 +371,65 @@ static void __vb2_buf_mem_finish(struct vb2_buffer *vb)
call_void_memop(vb, finish, vb->planes[plane].mem_priv);
}
+/* Output buffers are read by the driver; capture buffers are written. */
+static enum dma_data_direction vb2_cpu_access_dir(const struct vb2_queue *q)
+{
+ return q->is_output ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+}
+
+static bool __vb2_dmabuf_is_duplicate(const struct vb2_buffer *vb,
+ unsigned int plane)
+{
+ unsigned int i;
+
+ for (i = 0; i < plane; i++)
+ if (vb->planes[i].dbuf == vb->planes[plane].dbuf)
+ return true;
+
+ return false;
+}
+
+static void __vb2_buf_end_cpu_access(struct vb2_buffer *vb,
+ unsigned int num_planes)
+{
+ struct vb2_queue *q = vb->vb2_queue;
+ enum dma_data_direction dir = vb2_cpu_access_dir(q);
+ unsigned int plane;
+
+ for (plane = 0; plane < num_planes; plane++) {
+ int ret;
+
+ if (__vb2_dmabuf_is_duplicate(vb, plane))
+ continue;
+
+ ret = dma_buf_end_cpu_access(vb->planes[plane].dbuf, dir);
+ if (ret)
+ pr_warn_ratelimited("[%s] failed to end CPU access to dmabuf plane %u: %d\n",
+ q->name, plane, ret);
+ }
+}
+
+static int __vb2_buf_begin_cpu_access(struct vb2_buffer *vb)
+{
+ struct vb2_queue *q = vb->vb2_queue;
+ enum dma_data_direction dir = vb2_cpu_access_dir(q);
+ unsigned int plane;
+ int ret;
+
+ for (plane = 0; plane < vb->num_planes; plane++) {
+ if (__vb2_dmabuf_is_duplicate(vb, plane))
+ continue;
+
+ ret = dma_buf_begin_cpu_access(vb->planes[plane].dbuf, dir);
+ if (ret) {
+ __vb2_buf_end_cpu_access(vb, plane);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
/*
* __setup_offsets() - setup unique offsets ("cookies") for every plane in
* the buffer.
@@ -1423,6 +1482,9 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
}
if (reacquired) {
+ enum dma_data_direction attach_dir = q->uses_cpu_access ?
+ DMA_BIDIRECTIONAL : q->dma_dir;
+
if (vb->planes[0].mem_priv) {
vb->copied_timestamp = 0;
call_void_vb_qop(vb, buf_cleanup, vb);
@@ -1453,7 +1515,8 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
vb,
q->alloc_devs[plane] ? : q->dev,
planes[plane].dbuf,
- planes[plane].length);
+ planes[plane].length,
+ attach_dir);
if (IS_ERR(mem_priv)) {
dprintk(q, 1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
@@ -1504,9 +1567,21 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
}
}
+ if (q->uses_cpu_access) {
+ ret = __vb2_buf_begin_cpu_access(vb);
+ if (ret) {
+ dprintk(q, 1, "failed to begin CPU access to dmabuf: %d\n",
+ ret);
+ call_void_vb_qop(vb, buf_cleanup, vb);
+ goto err_put_vb2_buf;
+ }
+ }
+
ret = call_vb_qop(vb, buf_prepare, vb);
if (ret) {
dprintk(q, 1, "buffer preparation failed\n");
+ if (q->uses_cpu_access)
+ __vb2_buf_end_cpu_access(vb, vb->num_planes);
call_void_vb_qop(vb, buf_cleanup, vb);
goto err_put_vb2_buf;
}
@@ -1756,6 +1831,8 @@ int vb2_core_remove_bufs(struct vb2_queue *q, unsigned int start, unsigned int c
__vb2_buf_mem_finish(vb);
call_void_vb_qop(vb, buf_finish, vb);
+ if (q->memory == VB2_MEMORY_DMABUF && q->uses_cpu_access)
+ __vb2_buf_end_cpu_access(vb, vb->num_planes);
vb->prepared = 0;
}
@@ -2160,6 +2237,8 @@ int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
}
call_void_vb_qop(vb, buf_finish, vb);
+ if (q->memory == VB2_MEMORY_DMABUF && q->uses_cpu_access)
+ __vb2_buf_end_cpu_access(vb, vb->num_planes);
vb->prepared = 0;
if (pindex)
@@ -2296,6 +2375,8 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
if (vb->prepared) {
call_void_vb_qop(vb, buf_finish, vb);
+ if (q->memory == VB2_MEMORY_DMABUF && q->uses_cpu_access)
+ __vb2_buf_end_cpu_access(vb, vb->num_planes);
vb->prepared = 0;
}
__vb2_dqbuf(vb);
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index 9ce6284cd5f26..68c146c043fb1 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -768,7 +768,8 @@ static void vb2_dc_detach_dmabuf(void *mem_priv)
}
static void *vb2_dc_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
- struct dma_buf *dbuf, unsigned long size)
+ struct dma_buf *dbuf, unsigned long size,
+ enum dma_data_direction dma_dir)
{
struct vb2_dc_buf *buf;
struct dma_buf_attachment *dba;
@@ -794,7 +795,7 @@ static void *vb2_dc_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
return dba;
}
- buf->dma_dir = vb->vb2_queue->dma_dir;
+ buf->dma_dir = dma_dir;
buf->size = size;
buf->db_attach = dba;
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index b1d0695cda260..ab03f9d31391a 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -616,7 +616,8 @@ static void vb2_dma_sg_detach_dmabuf(void *mem_priv)
}
static void *vb2_dma_sg_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
- struct dma_buf *dbuf, unsigned long size)
+ struct dma_buf *dbuf, unsigned long size,
+ enum dma_data_direction dma_dir)
{
struct vb2_dma_sg_buf *buf;
struct dma_buf_attachment *dba;
@@ -640,7 +641,7 @@ static void *vb2_dma_sg_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
return dba;
}
- buf->dma_dir = vb->vb2_queue->dma_dir;
+ buf->dma_dir = dma_dir;
buf->size = size;
buf->db_attach = dba;
buf->vb = vb;
diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c
index 63f023696f3ee..c38faa0188bc9 100644
--- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c
+++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c
@@ -402,7 +402,8 @@ static void vb2_vmalloc_detach_dmabuf(void *mem_priv)
static void *vb2_vmalloc_attach_dmabuf(struct vb2_buffer *vb,
struct device *dev,
struct dma_buf *dbuf,
- unsigned long size)
+ unsigned long size,
+ enum dma_data_direction dma_dir)
{
struct vb2_vmalloc_buf *buf;
@@ -414,7 +415,7 @@ static void *vb2_vmalloc_attach_dmabuf(struct vb2_buffer *vb,
return ERR_PTR(-ENOMEM);
buf->dbuf = dbuf;
- buf->dma_dir = vb->vb2_queue->dma_dir;
+ buf->dma_dir = dma_dir;
buf->size = size;
return buf;
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4b4f4c15c53a7..8dfe22fa4423c 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -78,7 +78,8 @@ struct vb2_buffer;
* to the userspace, also optional.
* @attach_dmabuf: attach a shared &struct dma_buf for a hardware operation;
* used for DMABUF memory types; dev is the alloc device
- * dbuf is the shared dma_buf; returns ERR_PTR() on failure;
+ * dbuf is the shared dma_buf; dma_dir is the DMA mapping
+ * direction; returns ERR_PTR() on failure;
* allocator private per-buffer structure on success;
* this needs to be used for further accesses to the buffer.
* @detach_dmabuf: inform the exporter of the buffer that the current DMABUF
@@ -136,7 +137,8 @@ struct vb2_mem_ops {
void *(*attach_dmabuf)(struct vb2_buffer *vb,
struct device *dev,
struct dma_buf *dbuf,
- unsigned long size);
+ unsigned long size,
+ enum dma_data_direction dma_dir);
void (*detach_dmabuf)(void *buf_priv);
int (*map_dmabuf)(void *buf_priv);
void (*unmap_dmabuf)(void *buf_priv);
@@ -510,6 +512,11 @@ struct vb2_buf_ops {
* ->finish().
* @non_coherent_mem: when set queue will attempt to allocate buffers using
* non-coherent memory.
+ * @uses_cpu_access: the driver transfers buffer data with the CPU instead of
+ * DMA. For imported dma-bufs, videobuf2 brackets the interval from
+ * buf_prepare through buf_finish with dma_buf_begin_cpu_access()
+ * and dma_buf_end_cpu_access(). Imported attachments use
+ * bidirectional DMA mappings.
* @lock: pointer to a mutex that protects the &struct vb2_queue. The
* driver must set this to a mutex to let the v4l2 core serialize
* the queuing ioctls. This lock is used when waiting for a new
@@ -614,6 +621,7 @@ struct vb2_queue {
unsigned int uses_requests:1;
unsigned int allow_cache_hints:1;
unsigned int non_coherent_mem:1;
+ unsigned int uses_cpu_access:1;
struct mutex *lock;
void *owner;
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/4] media: uvcvideo: synchronize imported DMA-BUFs for CPU access
2026-10-19 7:14 [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Karl Mehltretter
2026-10-19 7:14 ` [PATCH 1/4] media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS Karl Mehltretter
2026-10-19 7:14 ` [PATCH 2/4] media: videobuf2: add opt-in DMA-BUF CPU access Karl Mehltretter
@ 2026-10-19 7:14 ` Karl Mehltretter
2026-10-19 7:14 ` [PATCH 4/4] media: vivid: " Karl Mehltretter
2026-10-19 12:44 ` [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Laurent Pinchart
4 siblings, 0 replies; 8+ messages in thread
From: Karl Mehltretter @ 2026-10-19 7:14 UTC (permalink / raw)
To: linux-media
Cc: Tomasz Figa, Marek Szyprowski, Mauro Carvalho Chehab,
Laurent Pinchart, Hans de Goede, Hans Verkuil, Benjamin Gaignard,
Tomasz Stanislawski, Sumit Semwal, Christian König,
dri-devel, linaro-mm-sig, linux-kernel, Karl Mehltretter
uvcvideo writes USB payloads into imported DMA-BUFs with the CPU without
cache synchronization, leaving physical RAM stale.
Set uses_cpu_access to bracket the driver's CPU access.
On a Pi 400, 12 eight-frame captures each had stale data before this
change. All 96 frames matched RAM with it.
Fixes: ccc4c539c05f ("[media] v4l: uvc: add support for DMABUF importing")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
drivers/media/usb/uvc/uvc_queue.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 3c002c8f442fb..1f92ee96e0710 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -247,6 +247,7 @@ int uvc_queue_init(struct uvc_streaming *stream, struct uvc_video_queue *queue,
queue->queue.drv_priv = queue;
queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
queue->queue.mem_ops = &vb2_vmalloc_memops;
+ queue->queue.uses_cpu_access = true;
queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
| V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
queue->queue.lock = &queue->mutex;
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/4] media: vivid: synchronize imported DMA-BUFs for CPU access
2026-10-19 7:14 [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Karl Mehltretter
` (2 preceding siblings ...)
2026-10-19 7:14 ` [PATCH 3/4] media: uvcvideo: synchronize imported DMA-BUFs for " Karl Mehltretter
@ 2026-10-19 7:14 ` Karl Mehltretter
2026-10-19 12:44 ` [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Laurent Pinchart
4 siblings, 0 replies; 8+ messages in thread
From: Karl Mehltretter @ 2026-10-19 7:14 UTC (permalink / raw)
To: linux-media
Cc: Tomasz Figa, Marek Szyprowski, Mauro Carvalho Chehab,
Laurent Pinchart, Hans de Goede, Hans Verkuil, Benjamin Gaignard,
Tomasz Stanislawski, Sumit Semwal, Christian König,
dri-devel, linaro-mm-sig, linux-kernel, Karl Mehltretter
vivid accesses imported DMA-BUFs with the CPU without cache
synchronization, leaving physical RAM stale after capture.
Set uses_cpu_access to bracket the driver's CPU access.
On a Pi 400, stale frames fell from 25/96 to 0/96 with this change.
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
drivers/media/test-drivers/vivid/vivid-core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/test-drivers/vivid/vivid-core.c b/drivers/media/test-drivers/vivid/vivid-core.c
index 62cfb5feb2cf5..e3aa1fc3bcf75 100644
--- a/drivers/media/test-drivers/vivid/vivid-core.c
+++ b/drivers/media/test-drivers/vivid/vivid-core.c
@@ -925,6 +925,7 @@ static int vivid_create_queue(struct vivid_dev *dev,
q->ops = ops;
q->mem_ops = allocators[dev->inst] == 1 ? &vb2_dma_contig_memops :
&vb2_vmalloc_memops;
+ q->uses_cpu_access = true;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->min_reqbufs_allocation = min_reqbufs_allocation;
q->lock = &dev->mutex;
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs
2026-10-19 7:14 [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Karl Mehltretter
` (3 preceding siblings ...)
2026-10-19 7:14 ` [PATCH 4/4] media: vivid: " Karl Mehltretter
@ 2026-10-19 12:44 ` Laurent Pinchart
2026-10-19 14:48 ` Christian König
4 siblings, 1 reply; 8+ messages in thread
From: Laurent Pinchart @ 2026-10-19 12:44 UTC (permalink / raw)
To: Karl Mehltretter
Cc: linux-media, Tomasz Figa, Marek Szyprowski,
Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil,
Benjamin Gaignard, Tomasz Stanislawski, Sumit Semwal,
Christian König, dri-devel, linaro-mm-sig, linux-kernel
On Mon, Oct 19, 2026 at 09:14:07AM +0200, Karl Mehltretter wrote:
> UVC and vivid access imported DMA-BUFs with the CPU without cache
> synchronization. On a Pi 400, captured data remained in the CPU cache
> while physical RAM was stale.
>
> Add an opt-in queue flag to bracket CPU access from buf_prepare() through
> buf_finish(). The allocator cannot imply CPU use because some vb2-vmalloc
> drivers pass buffers to hardware. Patch 1 balances finish operations in
> VIDIOC_REMOVE_BUFS so removing prepared buffers closes this interval.
This seems completely wrong.
> This follows the per-queue flag proposed here:
> https://lists.openwall.net/linux-kernel/2024/06/20/236
>
> Based on Linux 7.3. Tests cover the same code on these earlier bases:
>
> - Pi 400, 7.3-rc4, all four patches: eight 640x480 YUYV frames per run,
> imported CMA DMA-BUFs with a DRM device mapping:
>
> Path Runs Stale frames
> UVC, vb2-vmalloc 12 0/96
> vivid, vb2-vmalloc 12 0/96
> vivid, vb2-dma-contig 12 0/96
>
> All six lifecycle cases passed with both vivid allocators. Read-only
> output USERPTR passed. The test added no warnings or failed CPU-access
> callbacks. A control without the DRM mapping found 4/16 stale frames.
>
> - SAM9X75 (ARMv5), 6.18 backport of all four patches: the baseline
> PREPARE_BUF/REMOVE_BUFS imbalance was fixed. USERPTR and six lifecycle
> cases passed. All 128 vivid and 96 UVC frames matched RAM, with 100/100
> begin/end calls. The baseline was already coherent.
>
> - BeagleV Ahead (RISC-V), 7.3-rc7, patches 1, 2 and 4: read-only USERPTR,
> six traced lifecycle cases and 60 repeats passed with balanced callbacks
> and no kernel diagnostics. A vendor 5.10 backport of patches 2 and 3
> captured 96 UVC frames without stale data, with 100/100 begin/end calls.
> Its baseline was already coherent.
>
> Karl Mehltretter (4):
> media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS
> media: videobuf2: add opt-in DMA-BUF CPU access
> media: uvcvideo: synchronize imported DMA-BUFs for CPU access
> media: vivid: synchronize imported DMA-BUFs for CPU access
>
> .../media/common/videobuf2/videobuf2-core.c | 96 ++++++++++++++++++-
> .../common/videobuf2/videobuf2-dma-contig.c | 5 +-
> .../media/common/videobuf2/videobuf2-dma-sg.c | 5 +-
> .../common/videobuf2/videobuf2-vmalloc.c | 5 +-
> drivers/media/test-drivers/vivid/vivid-core.c | 1 +
> drivers/media/usb/uvc/uvc_queue.c | 1 +
> include/media/videobuf2-core.h | 12 ++-
> 7 files changed, 116 insertions(+), 9 deletions(-)
>
>
> base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs
2026-10-19 12:44 ` [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Laurent Pinchart
@ 2026-10-19 14:48 ` Christian König
2026-10-19 15:01 ` Laurent Pinchart
0 siblings, 1 reply; 8+ messages in thread
From: Christian König @ 2026-10-19 14:48 UTC (permalink / raw)
To: Laurent Pinchart, Karl Mehltretter
Cc: linux-media, Tomasz Figa, Marek Szyprowski,
Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil,
Benjamin Gaignard, Tomasz Stanislawski, Sumit Semwal, dri-devel,
linaro-mm-sig, linux-kernel
On 10/19/26 14:44, Laurent Pinchart wrote:
> On Mon, Oct 19, 2026 at 09:14:07AM +0200, Karl Mehltretter wrote:
>> UVC and vivid access imported DMA-BUFs with the CPU without cache
>> synchronization. On a Pi 400, captured data remained in the CPU cache
>> while physical RAM was stale.
>>
>> Add an opt-in queue flag to bracket CPU access from buf_prepare() through
>> buf_finish(). The allocator cannot imply CPU use because some vb2-vmalloc
>> drivers pass buffers to hardware. Patch 1 balances finish operations in
>> VIDIOC_REMOVE_BUFS so removing prepared buffers closes this interval.
>
> This seems completely wrong.
It looks a bit questionable from 1000 miles above, but I might be wrong.
Let me iterate the rules here:
Accessing imported DMA-buf with the CPU from userspace should only be possible by using the dma_buf_mmap() interface and that includes the DMA_BUF_IOCTL_SYNC IOCTL to flush buffers dirtied by the CPU. If that is not done this way then that would be a *major* security issue, but I guess that this isn't the issue here.
What the drivers do more likely is that they use the vmap interface to access the DMA-buf with the CPU inside the kernel. Correct?
In this case dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() should be called to properly frame that access.
That seems to be added in patch #2, but I absolutely can't judge if that is correct or not since at the same time you speak about userptr access and the code really looks a bit like spaghetti.
Regards,
Christian.
>
>> This follows the per-queue flag proposed here:
>> https://lists.openwall.net/linux-kernel/2024/06/20/236
>>
>> Based on Linux 7.3. Tests cover the same code on these earlier bases:
>>
>> - Pi 400, 7.3-rc4, all four patches: eight 640x480 YUYV frames per run,
>> imported CMA DMA-BUFs with a DRM device mapping:
>>
>> Path Runs Stale frames
>> UVC, vb2-vmalloc 12 0/96
>> vivid, vb2-vmalloc 12 0/96
>> vivid, vb2-dma-contig 12 0/96
>>
>> All six lifecycle cases passed with both vivid allocators. Read-only
>> output USERPTR passed. The test added no warnings or failed CPU-access
>> callbacks. A control without the DRM mapping found 4/16 stale frames.
>>
>> - SAM9X75 (ARMv5), 6.18 backport of all four patches: the baseline
>> PREPARE_BUF/REMOVE_BUFS imbalance was fixed. USERPTR and six lifecycle
>> cases passed. All 128 vivid and 96 UVC frames matched RAM, with 100/100
>> begin/end calls. The baseline was already coherent.
>>
>> - BeagleV Ahead (RISC-V), 7.3-rc7, patches 1, 2 and 4: read-only USERPTR,
>> six traced lifecycle cases and 60 repeats passed with balanced callbacks
>> and no kernel diagnostics. A vendor 5.10 backport of patches 2 and 3
>> captured 96 UVC frames without stale data, with 100/100 begin/end calls.
>> Its baseline was already coherent.
>>
>> Karl Mehltretter (4):
>> media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS
>> media: videobuf2: add opt-in DMA-BUF CPU access
>> media: uvcvideo: synchronize imported DMA-BUFs for CPU access
>> media: vivid: synchronize imported DMA-BUFs for CPU access
>>
>> .../media/common/videobuf2/videobuf2-core.c | 96 ++++++++++++++++++-
>> .../common/videobuf2/videobuf2-dma-contig.c | 5 +-
>> .../media/common/videobuf2/videobuf2-dma-sg.c | 5 +-
>> .../common/videobuf2/videobuf2-vmalloc.c | 5 +-
>> drivers/media/test-drivers/vivid/vivid-core.c | 1 +
>> drivers/media/usb/uvc/uvc_queue.c | 1 +
>> include/media/videobuf2-core.h | 12 ++-
>> 7 files changed, 116 insertions(+), 9 deletions(-)
>>
>>
>> base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs
2026-10-19 14:48 ` Christian König
@ 2026-10-19 15:01 ` Laurent Pinchart
0 siblings, 0 replies; 8+ messages in thread
From: Laurent Pinchart @ 2026-10-19 15:01 UTC (permalink / raw)
To: Christian König
Cc: Karl Mehltretter, linux-media, Tomasz Figa, Marek Szyprowski,
Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil,
Benjamin Gaignard, Tomasz Stanislawski, Sumit Semwal, dri-devel,
linaro-mm-sig, linux-kernel
On Mon, Oct 19, 2026 at 04:48:13PM +0200, Christian König wrote:
> On 10/19/26 14:44, Laurent Pinchart wrote:
> > On Mon, Oct 19, 2026 at 09:14:07AM +0200, Karl Mehltretter wrote:
> >> UVC and vivid access imported DMA-BUFs with the CPU without cache
> >> synchronization. On a Pi 400, captured data remained in the CPU cache
> >> while physical RAM was stale.
> >>
> >> Add an opt-in queue flag to bracket CPU access from buf_prepare() through
> >> buf_finish(). The allocator cannot imply CPU use because some vb2-vmalloc
> >> drivers pass buffers to hardware. Patch 1 balances finish operations in
> >> VIDIOC_REMOVE_BUFS so removing prepared buffers closes this interval.
> >
> > This seems completely wrong.
>
> It looks a bit questionable from 1000 miles above, but I might be wrong.
>
> Let me iterate the rules here:
>
> Accessing imported DMA-buf with the CPU from userspace should only be
> possible by using the dma_buf_mmap() interface and that includes the
> DMA_BUF_IOCTL_SYNC IOCTL to flush buffers dirtied by the CPU. If that
> is not done this way then that would be a *major* security issue, but
> I guess that this isn't the issue here.
>
> What the drivers do more likely is that they use the vmap interface to
> access the DMA-buf with the CPU inside the kernel. Correct?
This patch series introduces a big penalty in the common case where a
userspace application consumes the frame with the CPU. There should be
no cache invalidation in that case.
> In this case dma_buf_begin_cpu_access() and dma_buf_end_cpu_access()
> should be called to properly frame that access.
>
> That seems to be added in patch #2, but I absolutely can't judge if
> that is correct or not since at the same time you speak about userptr
> access and the code really looks a bit like spaghetti.
>
> >> This follows the per-queue flag proposed here:
> >> https://lists.openwall.net/linux-kernel/2024/06/20/236
> >>
> >> Based on Linux 7.3. Tests cover the same code on these earlier bases:
> >>
> >> - Pi 400, 7.3-rc4, all four patches: eight 640x480 YUYV frames per run,
> >> imported CMA DMA-BUFs with a DRM device mapping:
> >>
> >> Path Runs Stale frames
> >> UVC, vb2-vmalloc 12 0/96
> >> vivid, vb2-vmalloc 12 0/96
> >> vivid, vb2-dma-contig 12 0/96
> >>
> >> All six lifecycle cases passed with both vivid allocators. Read-only
> >> output USERPTR passed. The test added no warnings or failed CPU-access
> >> callbacks. A control without the DRM mapping found 4/16 stale frames.
> >>
> >> - SAM9X75 (ARMv5), 6.18 backport of all four patches: the baseline
> >> PREPARE_BUF/REMOVE_BUFS imbalance was fixed. USERPTR and six lifecycle
> >> cases passed. All 128 vivid and 96 UVC frames matched RAM, with 100/100
> >> begin/end calls. The baseline was already coherent.
> >>
> >> - BeagleV Ahead (RISC-V), 7.3-rc7, patches 1, 2 and 4: read-only USERPTR,
> >> six traced lifecycle cases and 60 repeats passed with balanced callbacks
> >> and no kernel diagnostics. A vendor 5.10 backport of patches 2 and 3
> >> captured 96 UVC frames without stale data, with 100/100 begin/end calls.
> >> Its baseline was already coherent.
> >>
> >> Karl Mehltretter (4):
> >> media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS
> >> media: videobuf2: add opt-in DMA-BUF CPU access
> >> media: uvcvideo: synchronize imported DMA-BUFs for CPU access
> >> media: vivid: synchronize imported DMA-BUFs for CPU access
> >>
> >> .../media/common/videobuf2/videobuf2-core.c | 96 ++++++++++++++++++-
> >> .../common/videobuf2/videobuf2-dma-contig.c | 5 +-
> >> .../media/common/videobuf2/videobuf2-dma-sg.c | 5 +-
> >> .../common/videobuf2/videobuf2-vmalloc.c | 5 +-
> >> drivers/media/test-drivers/vivid/vivid-core.c | 1 +
> >> drivers/media/usb/uvc/uvc_queue.c | 1 +
> >> include/media/videobuf2-core.h | 12 ++-
> >> 7 files changed, 116 insertions(+), 9 deletions(-)
> >>
> >>
> >> base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-19 15:01 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-19 7:14 [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Karl Mehltretter
2026-10-19 7:14 ` [PATCH 1/4] media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS Karl Mehltretter
2026-10-19 7:14 ` [PATCH 2/4] media: videobuf2: add opt-in DMA-BUF CPU access Karl Mehltretter
2026-10-19 7:14 ` [PATCH 3/4] media: uvcvideo: synchronize imported DMA-BUFs for " Karl Mehltretter
2026-10-19 7:14 ` [PATCH 4/4] media: vivid: " Karl Mehltretter
2026-10-19 12:44 ` [PATCH 0/4] media: synchronize CPU access to imported DMA-BUFs Laurent Pinchart
2026-10-19 14:48 ` Christian König
2026-10-19 15:01 ` Laurent Pinchart
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®