* [PATCH] media: rkvdec: Use dma_map_resource() to map RCB SRAM buffers
@ 2026-11-14 9:49 Lukas Splavec
2026-11-15 8:01 ` Arun Iyengar
0 siblings, 1 reply; 2+ messages in thread
From: Lukas Splavec @ 2026-11-14 9:49 UTC (permalink / raw)
To: detlev.casanova, ezequiel, mchehab
Cc: heiko, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, Lukas Splavec
rkvdec_allocate_rcb() uses the CPU virtual address of the SRAM buffer
as the decoder's IOVA and writes it into the IOMMU page table directly
with iommu_map(), bypassing the DMA API. Only the low 32 bits of that
address are used, which falls inside the IOVA range managed by the
allocator. The IOVA allocator does not know about this range and
considers it free. Under load it hands out the same IOVA to another
buffer, e.g. a capture buffer, whose mapping then fails:
[ 66.930512] iova: 0x0000000082100000 already mapped to 0x00000000ff001000 cannot remap to phys: 0x0000000168231000 prot: 0x3
[ 66.930674] rkvdec fdc38100.video-codec: dma alloc of size 16588800 failed
and decoding cannot start.
Map the SRAM buffer with dma_map_resource() instead, so the IOVA is
allocated by the IOVA allocator and the mapping is created by the DMA
API, and release it with dma_unmap_resource(). Without an IOMMU,
dma_map_resource() returns the physical address, so the separate
no-IOMMU path is no longer needed.
Fixes: e5640dbb991c ("media: rkvdec: Add RCB and SRAM support")
Signed-off-by: Lukas Splavec <lukas.splavec@puresig.cz>
---
Tested on a Giada D77 (RK3588) with GStreamer 1.28 (v4l2slh264dec/
v4l2slh265dec, H.264 and HEVC up to 4K) using a rolling load of 4
pipelines where each new set starts before the previous one is stopped:
kernel rounds already mapped dma alloc failed faults
v7.1 150/150 163 93 0
v7.1 + this patch 150/150 0 0 0
v7.1-rc1 + rkvdec
multicore v2 + fix 150/150 7 7 0
... + this patch 150/150 0 0 0
dma:dma_map_phys tracing confirms the RCB buffers stay in SRAM
(phys 0xff00xxxx) with IOVAs handed out by dma-iommu; on the
single-core path every map is matched by an unmap (767/767 over 60
rounds). With the IOMMU disabled in DT, dma_map_resource() returns the
SRAM physical address and decoding works. Also tested: SIGKILL
teardown, 6/8/12 concurrent streams, forced dma_map_resource()
failures (RAM fallback), WebKit page reloads with a corrupted stream
(IOMMU restore path), and a 600-round soak on the multicore series.
Tested on v7.1; applies cleanly to media-committers next.
.../platform/rockchip/rkvdec/rkvdec-rcb.c | 30 ++++++++-----------
1 file changed, 12 insertions(+), 18 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c
index fdcf1f1773..3492b78cc6 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-rcb.c
@@ -9,7 +9,7 @@
#include "rkvdec.h"
#include "rkvdec-rcb.h"
-#include <linux/iommu.h>
+#include <linux/dma-mapping.h>
#include <linux/genalloc.h>
#include <linux/sizes.h>
#include <linux/types.h>
@@ -44,7 +44,6 @@ void rkvdec_free_rcb(struct rkvdec_ctx *ctx)
{
struct rkvdec_dev *dev = ctx->dev;
struct rkvdec_rcb_config *cfg = ctx->rcb_config;
- unsigned long virt_addr;
int i;
if (!cfg)
@@ -58,11 +57,10 @@ void rkvdec_free_rcb(struct rkvdec_ctx *ctx)
switch (cfg->rcb_bufs[i].type) {
case RKVDEC_ALLOC_SRAM:
- virt_addr = (unsigned long)cfg->rcb_bufs[i].cpu;
-
- if (dev->iommu_domain)
- iommu_unmap(dev->iommu_domain, virt_addr, rcb_size);
- gen_pool_free(dev->sram_pool, virt_addr, rcb_size);
+ dma_unmap_resource(dev->dev, cfg->rcb_bufs[i].dma, rcb_size,
+ DMA_BIDIRECTIONAL, 0);
+ gen_pool_free(dev->sram_pool,
+ (unsigned long)cfg->rcb_bufs[i].cpu, rcb_size);
break;
case RKVDEC_ALLOC_DMA:
dma_free_coherent(dev->dev,
@@ -125,14 +123,14 @@ int rkvdec_allocate_rcb(struct rkvdec_ctx *ctx,
SZ_4K);
}
- /* If an IOMMU is used, map the SRAM address through it */
- if (cpu && rkvdec->iommu_domain) {
- unsigned long virt_addr = (unsigned long)cpu;
+ /* Map the SRAM through the DMA API so the IOVA is properly allocated */
+ if (cpu) {
phys_addr_t phys_addr = dma;
+ dma_addr_t iova;
- ret = iommu_map(rkvdec->iommu_domain, virt_addr, phys_addr,
- rcb_size, IOMMU_READ | IOMMU_WRITE, 0);
- if (ret) {
+ iova = dma_map_resource(ctx->dev->dev, phys_addr, rcb_size,
+ DMA_BIDIRECTIONAL, 0);
+ if (dma_mapping_error(ctx->dev->dev, iova)) {
gen_pool_free(ctx->dev->sram_pool,
(unsigned long)cpu,
rcb_size);
@@ -140,11 +138,7 @@ int rkvdec_allocate_rcb(struct rkvdec_ctx *ctx,
goto ram_fallback;
}
- /*
- * The registers will be configured with the virtual
- * address so that it goes through the IOMMU
- */
- dma = virt_addr;
+ dma = iova;
}
ram_fallback:
--
2.51.2
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] media: rkvdec: Use dma_map_resource() to map RCB SRAM buffers
2026-11-14 9:49 [PATCH] media: rkvdec: Use dma_map_resource() to map RCB SRAM buffers Lukas Splavec
@ 2026-11-15 8:01 ` Arun Iyengar
0 siblings, 0 replies; 2+ messages in thread
From: Arun Iyengar @ 2026-11-15 8:01 UTC (permalink / raw)
To: Lukas Splavec
Cc: detlev.casanova, ezequiel, mchehab, heiko, linux-media,
linux-rockchip, linux-arm-kernel, linux-kernel
Tested on an Orange Pi 5 (RK3588S), rkvdec from media next with this
patch, KASAN and lockdep on: all RCBs in SRAM now use IOVAs, no IOMMU
fault or splat, fluster HEVC and H.264 results unchanged.
Tested-by: Arun Iyengar <aiyengar1990@gmail.com>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-15 8:01 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-14 9:49 [PATCH] media: rkvdec: Use dma_map_resource() to map RCB SRAM buffers Lukas Splavec
2026-11-15 8:01 ` Arun Iyengar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox