[PATCH v2 17/17] media: rockchip: rga: schedule jobs to multiple cores
From: Sven Püschel
Date: Wed Sep 16 2026 - 11:40:15 EST
Schedule jobs to multiple cores to utilize all RGA cores. To avoid race
conditions when selecting the next free core a dedicated spinlock is added.
Note that this doesn't increase the max frame rate of a single
stream, as a context will wait for the job to finish before starting
the next device_run call.
Signed-off-by: Sven Püschel <s.pueschel@xxxxxxxxxxxxxx>
---
v2
- Set core->curr to null first in pm_runtime_resume_and_get error path
(https://sashiko.dev/#/patchset/20260606-spu-rga3multicore-v1-0-3ec2b15675f7%40pengutronix.de?part=15)
- Also protect adding/removing cores with the spinlock in bind/unbind
---
drivers/media/platform/rockchip/rga/rga.c | 30 +++++++++++++++++++++++++++---
drivers/media/platform/rockchip/rga/rga.h | 1 +
2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index b2eeae0a61771..6294825eaacfd 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -38,13 +38,29 @@ static void device_run(void *prv)
{
struct rga_ctx *ctx = prv;
struct rockchip_rga *rga = ctx->rga;
- struct rga_core *core = rga->cores[0];
+ struct rga_core *core = NULL;
struct vb2_v4l2_buffer *src, *dst;
unsigned long flags;
int ret;
+ unsigned int i;
+
+ spin_lock_irqsave(&rga->cores_lock, flags);
+ for (i = 0; i < rga->num_cores; i++) {
+ if (!rga->cores[i]->curr) {
+ core = rga->cores[i];
+ core->curr = ctx;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&rga->cores_lock, flags);
+
+ WARN_ONCE(!core, "No free core although max parallel jobs matches the core count!\n");
+ if (!core)
+ return;
ret = pm_runtime_resume_and_get(core->dev);
if (ret < 0) {
+ core->curr = NULL;
v4l2_m2m_buf_done_and_job_finish(rga->m2m_dev, ctx->fh.m2m_ctx,
VB2_BUF_STATE_ERROR);
return;
@@ -58,8 +74,6 @@ static void device_run(void *prv)
}
spin_unlock_irqrestore(&rga->ctrl_lock, flags);
- core->curr = ctx;
-
src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
src->sequence = ctx->osequence++;
@@ -748,6 +762,7 @@ static int rga_core_bind(struct device *dev, struct device *master, void *data)
struct rockchip_rga *rga = data;
struct rga_core *core = dev_get_drvdata(dev);
struct rockchip_rga_version version;
+ unsigned long flags;
int ret = 0;
core->rga = rga;
@@ -785,7 +800,9 @@ static int rga_core_bind(struct device *dev, struct device *master, void *data)
pm_runtime_put(core->dev);
+ spin_lock_irqsave(&rga->cores_lock, flags);
rga->cores[rga->num_cores++] = core;
+ spin_unlock_irqrestore(&rga->cores_lock, flags);
return 0;
}
@@ -796,6 +813,7 @@ static void rga_core_unbind(struct device *dev, struct device *master,
struct rga_core *core = dev_get_drvdata(dev);
struct rockchip_rga *rga = core->rga;
u8 i;
+ unsigned long flags;
/* Remove our core from the list */
for (i = 0; i < rga->num_cores; i++) {
@@ -810,8 +828,10 @@ static void rga_core_unbind(struct device *dev, struct device *master,
iommu_detach_device(domain, core->dev);
}
+ spin_lock_irqsave(&rga->cores_lock, flags);
rga->cores[i] = rga->cores[rga->num_cores - 1];
rga->num_cores--;
+ spin_unlock_irqrestore(&rga->cores_lock, flags);
break;
}
@@ -977,6 +997,9 @@ static int rga_bind(struct device *dev)
goto rel_m2m;
}
+ /* after binding all cores num_cores has the proper number of cores */
+ v4l2_m2m_set_max_parallel_jobs(rga->m2m_dev, rga->num_cores);
+
v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n",
vfd->name, video_device_node_name(vfd));
@@ -1047,6 +1070,7 @@ static int rga_probe(struct platform_device *pdev)
return dev_err_probe(dev, -ENODEV, "failed to get match data\n");
spin_lock_init(&rga->ctrl_lock);
+ spin_lock_init(&rga->cores_lock);
mutex_init(&rga->mutex);
dev_set_drvdata(dev, rga);
diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
index 522021c3e0249..b046083244bf6 100644
--- a/drivers/media/platform/rockchip/rga/rga.h
+++ b/drivers/media/platform/rockchip/rga/rga.h
@@ -86,6 +86,7 @@ struct rockchip_rga {
struct mutex mutex;
/* ctrl parm lock */
spinlock_t ctrl_lock;
+ spinlock_t cores_lock;
const struct rga_hw *hw;
--
2.55.0