From 402a8759e504dfd0f07cc04f9d073ef15d84fd6c Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 9 Feb 2026 13:25:29 +0200 Subject: [PATCH 1/3] pipeline: allocate on specific heap Add a heap parameter to pipeline allocation functions. This makes it possible to control how allocations are done with pipeline granularity and makes it possible to move pipelines to user-space. Signed-off-by: Kai Vehmanen --- src/audio/pipeline/pipeline-graph.c | 16 ++++++++++------ src/audio/pipeline/pipeline-schedule.c | 9 ++++++--- src/include/sof/audio/pipeline.h | 7 +++++-- src/ipc/ipc3/helper.c | 2 +- src/ipc/ipc4/helper.c | 4 ++-- test/cmocka/src/audio/pipeline/pipeline_new.c | 3 ++- 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index a89b9a6ece4b..89bb3574289b 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -108,8 +109,8 @@ void pipeline_posn_init(struct sof *sof) } /* create new pipeline - returns pipeline id or negative error */ -struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t comp_id, - struct create_pipeline_params *pparams) +struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_t priority, + uint32_t comp_id, struct create_pipeline_params *pparams) { struct sof_ipc_stream_posn posn; struct pipeline *p; @@ -122,13 +123,16 @@ struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t heap_trace_all(0); /* allocate new pipeline */ - p = rzalloc(SOF_MEM_FLAG_USER, sizeof(*p)); + p = sof_heap_alloc(heap, SOF_MEM_FLAG_USER, sizeof(*p), 0); if (!p) { pipe_cl_err("Out of Memory"); return NULL; } + memset(p, 0, sizeof(*p)); + /* init pipeline */ + p->heap = heap; p->comp_id = comp_id; p->priority = priority; p->pipeline_id = pipeline_id; @@ -161,7 +165,7 @@ struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t return p; free: - rfree(p); + sof_heap_free(heap, p); return NULL; } @@ -230,7 +234,7 @@ int pipeline_free(struct pipeline *p) #if !CONFIG_LIBRARY || UNIT_TEST schedule_task_free(p->pipe_task); #endif - rfree(p->pipe_task); + sof_heap_free(p->heap, p->pipe_task); } ipc_msg_free(p->msg); @@ -238,7 +242,7 @@ int pipeline_free(struct pipeline *p) pipeline_posn_offset_put(p->posn_offset); /* now free the pipeline */ - rfree(p); + sof_heap_free(p->heap, p); /* show heap status */ heap_trace_all(0); diff --git a/src/audio/pipeline/pipeline-schedule.c b/src/audio/pipeline/pipeline-schedule.c index f422e73e5392..45fd1eed639c 100644 --- a/src/audio/pipeline/pipeline-schedule.c +++ b/src/audio/pipeline/pipeline-schedule.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -241,15 +242,17 @@ static struct task *pipeline_task_init(struct pipeline *p, uint32_t type) { struct pipeline_task *task = NULL; - task = rzalloc(SOF_MEM_FLAG_USER, - sizeof(*task)); + task = sof_heap_alloc(p->heap, SOF_MEM_FLAG_USER, + sizeof(*task), 0); if (!task) return NULL; + memset(task, 0, sizeof(*task)); + if (schedule_task_init_ll(&task->task, SOF_UUID(pipe_task_uuid), type, p->priority, pipeline_task, p, p->core, 0) < 0) { - rfree(task); + sof_heap_free(p->heap, task); return NULL; } diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index c242865a7cf3..8f81c1a28a45 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -25,6 +25,7 @@ struct comp_buffer; struct comp_dev; struct ipc; struct ipc_msg; +struct k_heap; /* * Pipeline status to stop execution of current path, but to keep the @@ -52,6 +53,7 @@ struct ipc_msg; * Audio pipeline. */ struct pipeline { + struct k_heap *heap; /**< heap used for allocating this pipeline */ uint32_t comp_id; /**< component id for pipeline */ uint32_t pipeline_id; /**< pipeline id */ uint32_t sched_id; /**< Scheduling component id */ @@ -152,14 +154,15 @@ struct create_pipeline_params { /** * \brief Creates a new pipeline. + * \param[in] heap Heap to allocate the pipeline on, or NULL for default. * \param[in] pipeline_id Pipeline ID number. * \param[in] priority Pipeline scheduling priority. * \param[in] comp_id Pipeline component ID number. * \param[in] pparams Pipeline parameters from IPC payload, maybe NULL. * \return New pipeline pointer or NULL. */ -struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t comp_id, - struct create_pipeline_params *pparams); +struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_t priority, + uint32_t comp_id, struct create_pipeline_params *pparams); /** * \brief Free's a pipeline. diff --git a/src/ipc/ipc3/helper.c b/src/ipc/ipc3/helper.c index 4a5b85b055b6..4d87f042dd1d 100644 --- a/src/ipc/ipc3/helper.c +++ b/src/ipc/ipc3/helper.c @@ -395,7 +395,7 @@ int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) } /* create the pipeline */ - pipe = pipeline_new(pipe_desc->pipeline_id, pipe_desc->priority, + pipe = pipeline_new(NULL, pipe_desc->pipeline_id, pipe_desc->priority, pipe_desc->comp_id, NULL); if (!pipe) { tr_err(&ipc_tr, "pipeline_new() failed"); diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 75175b377347..a06d3dc7bc59 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -352,8 +352,8 @@ __cold static int ipc4_create_pipeline(struct ipc4_pipeline_create *pipe_desc, } /* create the pipeline */ - pipe = pipeline_new(pipe_desc->primary.r.instance_id, pipe_desc->primary.r.ppl_priority, 0, - pparams); + pipe = pipeline_new(NULL, pipe_desc->primary.r.instance_id, + pipe_desc->primary.r.ppl_priority, 0, pparams); if (!pipe) { tr_err(&ipc_tr, "ipc: pipeline_new() failed"); return IPC4_OUT_OF_MEMORY; diff --git a/test/cmocka/src/audio/pipeline/pipeline_new.c b/test/cmocka/src/audio/pipeline/pipeline_new.c index fd5145ef6d99..a68afe49e4be 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_new.c +++ b/test/cmocka/src/audio/pipeline/pipeline_new.c @@ -49,7 +49,8 @@ static void test_audio_pipeline_pipeline_new_creation(void **state) struct pipeline_new_setup_data *test_data = *state; /*Testing component*/ - struct pipeline *result = pipeline_new(test_data->pipe_id, + struct pipeline *result = pipeline_new(NULL, + test_data->pipe_id, test_data->priority, test_data->comp_id, NULL); From 9b0bf526e2f5ae2eeaf10453b7b13e381cc0c0e1 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 9 Feb 2026 13:57:48 +0200 Subject: [PATCH 2/3] zephyr: test: userspace: add a test for pipeline_new() Add a simple test to allocate a pipeline using a user-space memory heap and verify creation is successful. Signed-off-by: Kai Vehmanen --- zephyr/test/userspace/test_ll_task.c | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/zephyr/test/userspace/test_ll_task.c b/zephyr/test/userspace/test_ll_task.c index ec4439cfea6c..542f81b47359 100644 --- a/zephyr/test/userspace/test_ll_task.c +++ b/zephyr/test/userspace/test_ll_task.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,40 @@ ZTEST(userspace_ll, ll_task_test) ll_task_test(); } +static void pipeline_check(void) +{ + struct pipeline *p; + struct k_heap *heap; + uint32_t pipeline_id = 1; + uint32_t priority = 5; + uint32_t comp_id = 10; + int ret; + + heap = zephyr_ll_user_heap(); + zassert_not_null(heap, "user heap not found"); + + /* Create pipeline on user heap */ + p = pipeline_new(heap, pipeline_id, priority, comp_id, NULL); + zassert_not_null(p, "pipeline creation failed"); + + /* Verify heap assignment */ + zassert_equal(p->heap, heap, "pipeline heap not equal to user heap"); + + /* Verify pipeline properties */ + zassert_equal(p->pipeline_id, pipeline_id, "pipeline id mismatch"); + zassert_equal(p->priority, priority, "priority mismatch"); + zassert_equal(p->comp_id, comp_id, "comp id mismatch"); + + /* Free pipeline */ + ret = pipeline_free(p); + zassert_equal(ret, 0, "pipeline free failed"); +} + +ZTEST(userspace_ll, pipeline_check) +{ + pipeline_check(); +} + ZTEST_SUITE(userspace_ll, NULL, NULL, NULL, NULL, NULL); /** From 3e60e0abb6e37fbc3cb3370480c9713352b38f2f Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 10 Feb 2026 18:45:07 +0200 Subject: [PATCH 3/3] pipeline: fix documentation for pipeline_prepare() Fix copy and paste error in documentation for pipeline_prepare(). Signed-off-by: Kai Vehmanen --- src/include/sof/audio/pipeline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index 8f81c1a28a45..71568f232625 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -269,7 +269,7 @@ int pipeline_params(struct pipeline *p, struct comp_dev *cd, struct sof_ipc_pcm_params *params); /** - * \brief Creates a new pipeline. + * \brief Prepares pipeline for processing. * \param[in] p pipeline. * \param[in,out] cd Pipeline component device. * \return 0 on success.