From: Lukas Splavec <lukas.splavec@puresig.cz>
To: detlev.casanova@collabora.com, ezequiel@vanguardiasur.com.ar,
mchehab@kernel.org
Cc: heiko@sntech.de, linux-media@vger.kernel.org,
linux-rockchip@lists.infradead.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org,
Lukas Splavec <lukas.splavec@puresig.cz>
Subject: [PATCH] media: rkvdec: Use dma_map_resource() to map RCB SRAM buffers
Date: Sat, 14 Nov 2026 09:49:16 +0000 [thread overview]
Message-ID: <20261114094916.28744-1-lukas.splavec@puresig.cz> (raw)
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
next reply other threads:[~2026-11-14 9:49 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 9:49 Lukas Splavec [this message]
2026-11-15 8:01 ` Arun Iyengar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261114094916.28744-1-lukas.splavec@puresig.cz \
--to=lukas.splavec@puresig.cz \
--cc=detlev.casanova@collabora.com \
--cc=ezequiel@vanguardiasur.com.ar \
--cc=heiko@sntech.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=mchehab@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®