From 2f1b7560258ee0c3923112272cf2547e68b9b407 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 3 Sep 2026 20:28:24 +0300 Subject: [PATCH 1/4] pipeline: replace heap member with alloc context Replace the bare k_heap pointer in struct pipeline with a mod_alloc_ctx object. The context is created in pipeline_new() and freed symmetrically in pipeline_free(). No vregion is associated with this context yet, so allocation behavior is unchanged: sof_ctx_alloc()/sof_ctx_zalloc()/sof_ctx_free() fall back to the plain heap when the context has no vregion. Update all remaining pipeline->heap consumers, including the pipeline and trigger task allocations in pipeline-schedule.c, to go through the alloc context instead of the heap pointer directly. Signed-off-by: Jyri Sarha --- src/audio/pipeline/pipeline-graph.c | 27 +++++++++++++++++++------- src/audio/pipeline/pipeline-schedule.c | 14 ++++++------- src/include/sof/audio/pipeline.h | 3 ++- zephyr/test/userspace/test_ll_task.c | 2 +- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index e6f56eaf7096..e8fbb6333c14 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -174,6 +174,7 @@ void pipeline_posn_grant_access(struct k_thread *thread) 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 mod_alloc_ctx *alloc; struct sof_ipc_stream_posn posn; struct pipeline *p; int ret; @@ -184,17 +185,24 @@ struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_ /* show heap status */ heap_trace_all(0); + alloc = sof_heap_alloc(heap, SOF_MEM_FLAG_USER, sizeof(*alloc), 0); + if (!alloc) { + pipe_cl_err("Failed to allocate pipeline alloc context"); + return NULL; + } + + memset(alloc, 0, sizeof(*alloc)); + alloc->heap = heap; + /* allocate new pipeline */ - p = sof_heap_alloc(heap, SOF_MEM_FLAG_USER, sizeof(*p), 0); + p = sof_ctx_zalloc(alloc, SOF_MEM_FLAG_USER, sizeof(*p), 0); if (!p) { pipe_cl_err("Out of Memory"); - return NULL; + goto free_alloc; } - memset(p, 0, sizeof(*p)); - /* init pipeline */ - p->heap = heap; + p->alloc = alloc; p->comp_id = comp_id; p->priority = priority; p->pipeline_id = pipeline_id; @@ -236,7 +244,9 @@ struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_ return p; free: - sof_heap_free(heap, p); + sof_ctx_free(alloc, p); +free_alloc: + sof_heap_free(heap, alloc); return NULL; } @@ -321,6 +331,8 @@ void pipeline_disconnect(struct comp_dev *comp, struct comp_buffer *buffer, int /* pipelines must be inactive */ int pipeline_free(struct pipeline *p) { + struct mod_alloc_ctx *alloc = p->alloc; + pipe_dbg(p, "entry"); /* @@ -336,7 +348,8 @@ int pipeline_free(struct pipeline *p) pipeline_posn_offset_put(p->posn_offset); /* now free the pipeline */ - sof_heap_free(p->heap, p); + sof_ctx_free(alloc, p); + sof_heap_free(alloc->heap, alloc); /* show heap status */ heap_trace_all(0); diff --git a/src/audio/pipeline/pipeline-schedule.c b/src/audio/pipeline/pipeline-schedule.c index 0f00dcf1701c..fc8daad6e378 100644 --- a/src/audio/pipeline/pipeline-schedule.c +++ b/src/audio/pipeline/pipeline-schedule.c @@ -349,7 +349,7 @@ static struct task *ipc4_pipeline_trigger_task_init(struct pipeline *p, uint32_t { struct task *task; - task = sof_heap_alloc(p->heap, SOF_MEM_FLAG_USER, sizeof(*task), 0); + task = sof_ctx_alloc(p->alloc, SOF_MEM_FLAG_USER, sizeof(*task), 0); if (!task) return NULL; @@ -358,7 +358,7 @@ static struct task *ipc4_pipeline_trigger_task_init(struct pipeline *p, uint32_t /* All trigger tasks use the highest priority, regardless of pipeline priority. */ if (schedule_task_init_ll(task, SOF_UUID(pipe_trigger_task_uuid), type, -1, ipc4_pipeline_trigger_task, p, p->core, 0) < 0) { - sof_heap_free(p->heap, task); + sof_ctx_free(p->alloc, task); return NULL; } @@ -370,8 +370,8 @@ static struct task *pipeline_task_init(struct pipeline *p, uint32_t type) { struct pipeline_task *task = NULL; - task = sof_heap_alloc(p->heap, SOF_MEM_FLAG_USER, - sizeof(*task), 0); + task = sof_ctx_alloc(p->alloc, SOF_MEM_FLAG_USER, + sizeof(*task), 0); if (!task) return NULL; @@ -385,7 +385,7 @@ static struct task *pipeline_task_init(struct pipeline *p, uint32_t type) ipc3_pipeline_task, #endif p, p->core, 0) < 0) { - sof_heap_free(p->heap, task); + sof_ctx_free(p->alloc, task); return NULL; } @@ -562,14 +562,14 @@ void pipeline_comp_ll_task_free(struct pipeline *p) delayed_trigger_owner[p->core] = NULL; if (p->trigger_task) - sof_heap_free(p->heap, p->trigger_task); + sof_ctx_free(p->alloc, p->trigger_task); #endif if (p->pipe_task) { #if !CONFIG_LIBRARY || UNIT_TEST schedule_task_free(p->pipe_task); #endif - sof_heap_free(p->heap, p->pipe_task); + sof_ctx_free(p->alloc, p->pipe_task); } } diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index 858c81d98a2f..688fa6fc12dc 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -26,6 +26,7 @@ struct comp_dev; struct ipc; struct ipc_msg; struct k_heap; +struct mod_alloc_ctx; /* * Pipeline status to stop execution of current path, but to keep the @@ -53,7 +54,7 @@ struct k_heap; * Audio pipeline. */ struct pipeline { - struct k_heap *heap; /**< heap used for allocating this pipeline */ + struct mod_alloc_ctx *alloc; /**< alloc context 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 */ diff --git a/zephyr/test/userspace/test_ll_task.c b/zephyr/test/userspace/test_ll_task.c index 1e31e01538b7..f6a63b7194bd 100644 --- a/zephyr/test/userspace/test_ll_task.c +++ b/zephyr/test/userspace/test_ll_task.c @@ -113,7 +113,7 @@ static void pipeline_check(void) zassert_not_null(p, "pipeline creation failed"); /* Verify heap assignment */ - zassert_equal(p->heap, heap, "pipeline heap not equal to user heap"); + zassert_equal(p->alloc->heap, heap, "pipeline heap not equal to user heap"); /* Verify pipeline properties */ zassert_equal(p->pipeline_id, pipeline_id, "pipeline id mismatch"); From a73b7d66f379442d78134fe5df0bba632303157c Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 3 Sep 2026 20:36:33 +0300 Subject: [PATCH 2/4] pipeline: allocate shared vregion for LL modules in the pipeline Create a per-pipeline vregion in pipeline_new() when the IPC4 pipeline extension payload specifies the required heap size, and attach it to the pipeline's alloc context. LL modules on a pipeline with a vregion use it as their allocation backend, instead of the driver's default heap, and share the pipeline's mod_alloc_ctx. A use_ppl_alloc flag gates the sharing to LL modules only, so DP modules continue to create their own vregion and alloc context as before. Also the behaviour in the case where ppl_alloc is not available remains unchanged. module_adapter_mem_free() detects whether a module's alloc belongs to its pipeline and either just releases the vregion reference (ppl_alloc case) or tears down the module's own alloc. Setting of dev->pipeline is moved earlier in module_adapter_new_ext() so that we can still use module_adapter_mem_free() in its error handling. Call vregion_set_interim() for the pipeline vregion in pipeline_complete() to switch the allocator to interim mode after all lifetime allocations are done, and release it in pipeline_free(), warning if the refcount does not reach zero. module_adapter_mem_alloc() itself is only extended with the use_ppl_alloc branch here, keeping its existing DP allocation code path and conditional structure otherwise unchanged; the follow-up commit extracts and reworks that DP allocation path. Signed-off-by: Jyri Sarha --- src/audio/module_adapter/module_adapter.c | 100 ++++++++++++++-------- src/audio/pipeline/pipeline-graph.c | 22 +++++ 2 files changed, 87 insertions(+), 35 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 9e6720424bcf..dbfe4c9ad6a7 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -77,12 +77,15 @@ static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config * static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv, const struct comp_ipc_config *config, - const struct module_ext_init_data *ext_init) + const struct module_ext_init_data *ext_init, + struct mod_alloc_ctx *ppl_alloc) { struct k_heap *mod_heap; struct vregion *mod_vreg; struct processing_module *mod; + struct mod_alloc_ctx *alloc; struct comp_dev *dev; + bool use_ppl_alloc = ppl_alloc && config->proc_domain == COMP_PROCESSING_DOMAIN_LL; /* * For DP shared modules the struct processing_module object must be * accessible from all cores. Unfortunately at this point there's no @@ -93,7 +96,12 @@ struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv uint32_t flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ? SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER; - if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_SOF_VREGIONS) && + if (use_ppl_alloc) { + /* LL modules share the pipeline's alloc context */ + mod_heap = ppl_alloc->heap; + mod_vreg = ppl_alloc->vreg; + vregion_get(mod_vreg); + } else if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_SOF_VREGIONS) && IS_ENABLED(CONFIG_USERSPACE) && !IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) { mod_vreg = module_adapter_dp_heap_new(config, ext_init); if (!mod_vreg) { @@ -127,14 +135,18 @@ struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv goto emod; } - struct mod_alloc_ctx *alloc = sof_heap_alloc(mod_heap, flags, sizeof(*alloc), 0); + if (use_ppl_alloc) { + alloc = ppl_alloc; + } else { + alloc = sof_heap_alloc(mod_heap, flags, sizeof(*alloc), 0); + if (!alloc) + goto ealloc; - if (!alloc) - goto ealloc; + alloc->heap = mod_heap; + alloc->vreg = mod_vreg; + } memset(mod, 0, sizeof(*mod)); - alloc->heap = mod_heap; - alloc->vreg = mod_vreg; mod->priv.resources.alloc = alloc; mod_resource_init(mod); @@ -163,7 +175,8 @@ struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv return mod; edev: - sof_heap_free(mod_heap, alloc); + if (!use_ppl_alloc) + sof_heap_free(mod_heap, alloc); ealloc: if (mod_vreg) vregion_free(mod_vreg, mod); @@ -178,26 +191,33 @@ struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv static void module_adapter_mem_free(struct processing_module *mod) { struct mod_alloc_ctx *alloc = mod->priv.resources.alloc; - struct k_heap *mod_heap = alloc->heap; + bool ppl_alloc = mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL && + mod->dev->pipeline && mod->dev->pipeline->alloc == alloc; /* * In principle it shouldn't even be needed to free individual objects * on the module heap since we're freeing the heap itself too */ #if CONFIG_IPC_MAJOR_4 - sof_heap_free(mod_heap, mod->priv.cfg.input_pins); + sof_heap_free(alloc->heap, mod->priv.cfg.input_pins); #endif - if (alloc->vreg) { - struct vregion *mod_vreg = alloc->vreg; + sof_ctx_free(alloc, mod->dev); + sof_ctx_free(alloc, mod); - vregion_free(mod_vreg, mod->dev); - vregion_free(mod_vreg, mod); - if (!vregion_put(mod_vreg)) + if (ppl_alloc) { + /* alloc belongs to pipeline, just release vregion reference */ + vregion_put(alloc->vreg); + } else if (alloc->vreg) { + /* + * This is DP userpsace case + * Only remove the alloc ctx, if vreg was freed. If it was not + * the DP userspace thread is still holding a reference to it, + * and will free alloc ctx eventually. + */ + if (!vregion_put(alloc->vreg)) sof_heap_free(alloc->heap, alloc); } else { - sof_heap_free(mod_heap, mod->dev); - sof_heap_free(mod_heap, mod); - sof_heap_free(mod_heap, alloc); + sof_heap_free(alloc->heap, alloc); } } @@ -248,8 +268,19 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, NULL; #endif - struct processing_module *mod = module_adapter_mem_alloc(drv, config, ext_init); + struct mod_alloc_ctx *ppl_alloc = NULL; +#if CONFIG_IPC_MAJOR_4 + struct ipc_comp_dev *ipc_pipe; + struct ipc *ipc = ipc_get(); + /* resolve the pipeline pointer early to pass its alloc to mem_alloc */ + ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, config->pipeline_id, + IPC_COMP_IGNORE_REMOTE); + if (ipc_pipe && ipc_pipe->pipeline) + ppl_alloc = ipc_pipe->pipeline->alloc; +#endif + + struct processing_module *mod = module_adapter_mem_alloc(drv, config, ext_init, ppl_alloc); if (!mod) return NULL; @@ -273,6 +304,21 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, dst->ext_data = &ext_data; #endif +#if CONFIG_IPC_MAJOR_4 + /* + * Set the pipeline pointer if ipc_pipe is valid. Do this + * early so that we can use module_adapter_mem_free() in error + * handling. + */ + if (ipc_pipe) { + dev->pipeline = ipc_pipe->pipeline; + + /* LL modules have the same period as the pipeline */ + if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) + dev->period = ipc_pipe->pipeline->period; + } +#endif + #if CONFIG_ZEPHYR_DP_SCHEDULER /* create a task for DP processing */ if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP) { @@ -306,22 +352,6 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, else goto err; -#if CONFIG_IPC_MAJOR_4 - struct ipc_comp_dev *ipc_pipe; - struct ipc *ipc = ipc_get(); - - /* set the pipeline pointer if ipc_pipe is valid */ - ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, config->pipeline_id, - IPC_COMP_IGNORE_REMOTE); - if (ipc_pipe) { - dev->pipeline = ipc_pipe->pipeline; - - /* LL modules have the same period as the pipeline */ - if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) - dev->period = ipc_pipe->pipeline->period; - } -#endif - /* Init processing module */ ret = module_init(mod); if (ret) { diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index e8fbb6333c14..d7404359c0b5 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -194,6 +195,18 @@ struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_ memset(alloc, 0, sizeof(*alloc)); alloc->heap = heap; + /* Create vregion for pipeline and its modules if size info is available */ + if (IS_ENABLED(CONFIG_SOF_VREGIONS) && + pparams && pparams->mem_data && pparams->mem_data->heap_bytes) { + size_t buf_size = pparams->mem_data->heap_bytes; + uintptr_t vreg_start; + + alloc->vreg = vregion_create_map(&vreg_start, &buf_size); + if (!alloc->vreg) + pipe_cl_err("Failed to create pipeline vregion of %zu bytes, using heap", + pparams->mem_data->heap_bytes); + } + /* allocate new pipeline */ p = sof_ctx_zalloc(alloc, SOF_MEM_FLAG_USER, sizeof(*p), 0); if (!p) { @@ -246,6 +259,7 @@ struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_ free: sof_ctx_free(alloc, p); free_alloc: + vregion_put(alloc->vreg); sof_heap_free(heap, alloc); return NULL; } @@ -349,6 +363,10 @@ int pipeline_free(struct pipeline *p) /* now free the pipeline */ sof_ctx_free(alloc, p); + + /* free alloc context and vregion */ + if (vregion_put(alloc->vreg)) + pipe_cl_warn("pipeline vregion still in use"); sof_heap_free(alloc->heap, alloc); /* show heap status */ @@ -426,6 +444,10 @@ int pipeline_complete(struct pipeline *p, struct comp_dev *source, p->source_comp = source; p->sink_comp = sink; + + if (p->alloc->vreg) + vregion_set_interim(p->alloc->vreg); + p->status = COMP_STATE_READY; /* show heap status */ From 4380b32738f9bf4450596043767b7c10bcf5ab71 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 3 Sep 2026 20:36:33 +0300 Subject: [PATCH 3/4] module_adapter: extract DP alloc context creation from module_adapter_mem_alloc() Extract the DP-specific vregion/heap and mod_alloc_ctx creation out of module_adapter_mem_alloc() into a new helper, module_adapter_dp_alloc_ctx_new(). module_adapter_mem_alloc() now simply picks between the shared pipeline alloc context (LL modules) and a freshly created one (DP modules) with a plain if/else-if/else on proc_domain, and then uses sof_ctx_alloc()/sof_ctx_free() for the struct processing_module and struct comp_dev allocations instead of choosing between vregion_alloc()/sof_heap_alloc() by hand. This is a refactor only, allocation backend selection and error handling behaviour are unchanged. Signed-off-by: Jyri Sarha --- src/audio/module_adapter/module_adapter.c | 107 +++++++++++----------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index dbfe4c9ad6a7..1b9f775f719c 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -75,34 +75,17 @@ static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config * } static -struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const struct module_ext_init_data *ext_init, - struct mod_alloc_ctx *ppl_alloc) +struct mod_alloc_ctx *module_adapter_dp_alloc_ctx_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const struct module_ext_init_data *ext_init, + uint32_t flags) { struct k_heap *mod_heap; struct vregion *mod_vreg; - struct processing_module *mod; struct mod_alloc_ctx *alloc; - struct comp_dev *dev; - bool use_ppl_alloc = ppl_alloc && config->proc_domain == COMP_PROCESSING_DOMAIN_LL; - /* - * For DP shared modules the struct processing_module object must be - * accessible from all cores. Unfortunately at this point there's no - * information of components the module will be bound to. So we need to - * allocate shared memory for each DP module. - * To be removed when pipeline 2.0 is ready. - */ - uint32_t flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ? - SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER; - if (use_ppl_alloc) { - /* LL modules share the pipeline's alloc context */ - mod_heap = ppl_alloc->heap; - mod_vreg = ppl_alloc->vreg; - vregion_get(mod_vreg); - } else if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_SOF_VREGIONS) && - IS_ENABLED(CONFIG_USERSPACE) && !IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) { + if (IS_ENABLED(CONFIG_SOF_VREGIONS) && IS_ENABLED(CONFIG_USERSPACE) && + !IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) { mod_vreg = module_adapter_dp_heap_new(config, ext_init); if (!mod_vreg) { comp_cl_err(drv, "Failed to allocate DP module heap / vregion"); @@ -122,28 +105,56 @@ struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv #endif mod_vreg = NULL; } + alloc = sof_heap_alloc(mod_heap, flags, sizeof(*alloc), 0); + if (!alloc) { + comp_cl_err(drv, "sof_alloc_ctx allocation failed"); + vregion_put(mod_vreg); + return NULL; + } - if (!mod_vreg) - mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0); - else if (flags & SOF_MEM_FLAG_COHERENT) - mod = vregion_alloc_coherent(mod_vreg, sizeof(*mod)); - else - mod = vregion_alloc(mod_vreg, sizeof(*mod)); + memset(alloc, 0, sizeof(*alloc)); + alloc->heap = mod_heap; + alloc->vreg = mod_vreg; - if (!mod) { - comp_cl_err(drv, "failed to allocate memory for module"); - goto emod; - } + return alloc; +} - if (use_ppl_alloc) { +static +struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const struct module_ext_init_data *ext_init, + struct mod_alloc_ctx *ppl_alloc) +{ + struct processing_module *mod; + struct mod_alloc_ctx *alloc; + struct comp_dev *dev; + /* + * For DP shared modules the struct processing_module object must be + * accessible from all cores. Unfortunately at this point there's no + * information of components the module will be bound to. So we need to + * allocate shared memory for each DP module. + * To be removed when pipeline 2.0 is ready. + */ + uint32_t flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ? + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER; + + if (config->proc_domain == COMP_PROCESSING_DOMAIN_LL) { + /* LL modules share the pipeline's alloc context */ alloc = ppl_alloc; - } else { - alloc = sof_heap_alloc(mod_heap, flags, sizeof(*alloc), 0); + vregion_get(alloc->vreg); + } else if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP) { + alloc = module_adapter_dp_alloc_ctx_new(drv, config, ext_init, flags); if (!alloc) - goto ealloc; + return NULL; + } else { + comp_cl_err(drv, "bad proc_domain %d", config->proc_domain); + return NULL; + } - alloc->heap = mod_heap; - alloc->vreg = mod_vreg; + mod = sof_ctx_alloc(alloc, flags, sizeof(*mod), 0); + if (!mod) { + comp_cl_err(drv, "failed to allocate memory for module"); + goto emod; } memset(mod, 0, sizeof(*mod)); @@ -156,11 +167,7 @@ struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv * then it can be cached. Effectively it can be only cached in * single-core configurations. */ - if (mod_vreg) - dev = vregion_alloc_coherent(mod_vreg, sizeof(*dev)); - else - dev = sof_heap_alloc(mod_heap, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0); - + dev = sof_ctx_alloc(alloc, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0); if (!dev) { comp_cl_err(drv, "failed to allocate memory for comp_dev"); goto edev; @@ -175,15 +182,11 @@ struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv return mod; edev: - if (!use_ppl_alloc) - sof_heap_free(mod_heap, alloc); -ealloc: - if (mod_vreg) - vregion_free(mod_vreg, mod); - else - sof_heap_free(mod_heap, mod); + sof_ctx_free(alloc, mod); emod: - vregion_put(mod_vreg); + vregion_put(alloc->vreg); + if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP) + sof_heap_free(alloc->heap, alloc); return NULL; } From 2874e33c317e17651b4906967344c94555fa3fb9 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 10 Sep 2026 12:21:41 +0300 Subject: [PATCH 4/4] cmocka: initialize pipeline allocation context Pipeline cmocka tests need the struct mod_alloc_ctx too, like the real thing does at the moment. Signed-off-by: Jyri Sarha --- test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c index 7315ce387562..db8b1e79cbf2 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c +++ b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c @@ -5,6 +5,7 @@ // Author: Jakub Dabek #include +#include #include "pipeline_connection_mocks.h" extern struct schedulers *schedulers; @@ -32,6 +33,7 @@ struct pipeline_connect_data *get_standard_connect_objects(void) struct pipeline *pipe = &pipeline_connect_data->p; + pipe->alloc = calloc(sizeof(*pipe->alloc), 1); pipe->frames_per_sched = 5; pipe->pipeline_id = PIPELINE_ID_SAME; pipe->status = COMP_STATE_INIT; @@ -91,6 +93,7 @@ struct pipeline_connect_data *get_standard_connect_objects(void) void free_standard_connect_objects(struct pipeline_connect_data *data) { + free(data->p.alloc); free(data->p.pipe_task); free(data->p.sched_comp); free(data->second);