[PATCH v6 2/2] drm/rocket: Keep scheduler allocation in rocket_file_priv

From: Triet Hoang

Date: Mon Sep 14 2026 - 00:57:21 EST


The scheduler array passed to drm_sched_entity_init() is retained by the
entity when the device has multiple cores. drm_sched_entity_init() stores
the list conditionally:

entity->sched_list = num_sched_list > 1 ? sched_list : NULL;

With one scheduler, it keeps only entity->rq and drops the array pointer
while rocket_job_open() allows its local copy to go out of scope. So
for num_cores == 1 the kfree() in rocket_job_close() is a kfree(NULL)
and the array leaks unreachably. For num_cores > 1 there is no leak,
which is why this is invisible in normal use on RK3588.

Keep the allocation in rocket_file_priv so rocket_job_close() can destroy
the entity before freeing the array. Free the array directly if entity
initialization fails, since rocket_job_open() does not call
rocket_job_close() on that error path.

Fixes: 0810d5ad88a1 ("accel/rocket: Add job submission IOCTL")

Suggested-by: Igor Paunovic <royalnet026@xxxxxxxxx>
Link: https://lore.kernel.org/all/20260817093009.22359-1-royalnet026@xxxxxxxxx/
Signed-off-by: Triet Hoang <triet.hoang.dev@xxxxxxxxx>
Tested-by: Igor Paunovic <royalnet026@xxxxxxxxx>
Tested-by: Sidong Yang <sidong.yang@xxxxxxxxxx>
---
Changes in v5:
- Free rocket_priv->scheds instead of entity->sched_list in rocket_job_close().

Changes in v6:
- Add Tested-by and Fixes tags.
- Move kfree() below the drm_sched_entity_destroy() call in rocket_job_close().
- Update commit message to explain why the scheduler array must outlive the scheduler entity.
---
drivers/accel/rocket/rocket_drv.h | 1 +
drivers/accel/rocket/rocket_job.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/accel/rocket/rocket_drv.h b/drivers/accel/rocket/rocket_drv.h
index 2c673bb99ccc..9421e48ec5d8 100644
--- a/drivers/accel/rocket/rocket_drv.h
+++ b/drivers/accel/rocket/rocket_drv.h
@@ -23,6 +23,7 @@ struct rocket_file_priv {
struct drm_mm mm;
struct mutex mm_lock;

+ struct drm_gpu_scheduler **scheds;
struct drm_sched_entity sched_entity;
};

diff --git a/drivers/accel/rocket/rocket_job.c b/drivers/accel/rocket/rocket_job.c
index 704a15513179..f27e6264f91d 100644
--- a/drivers/accel/rocket/rocket_job.c
+++ b/drivers/accel/rocket/rocket_job.c
@@ -528,6 +528,8 @@ int rocket_job_open(struct rocket_file_priv *rocket_priv)
rdev->num_cores, NULL);
if (ret)
kfree(scheds);
+ else
+ rocket_priv->scheds = scheds;

return ret;
}
@@ -536,8 +538,8 @@ void rocket_job_close(struct rocket_file_priv *rocket_priv)
{
struct drm_sched_entity *entity = &rocket_priv->sched_entity;

- kfree(entity->sched_list);
drm_sched_entity_destroy(entity);
+ kfree(rocket_priv->scheds);
}

int rocket_job_is_idle(struct rocket_core *core)
--
2.53.0