From d8a7926cd478388b3a07568a189d01e342193a7f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 14 Sep 2026 14:07:12 +0200 Subject: [PATCH 1/6] ipc: (cosmetic) make a function static Make ipc4_process_large_config_get() static, it's only called once in the same file where it's defined. Signed-off-by: Guennadi Liakhovetski --- src/include/ipc4/handler.h | 13 ------------- src/ipc/ipc4/handler-user.c | 10 ++++++---- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/include/ipc4/handler.h b/src/include/ipc4/handler.h index cb54ecc08db0..8f624a3c5c70 100644 --- a/src/include/ipc4/handler.h +++ b/src/include/ipc4/handler.h @@ -34,19 +34,6 @@ int ipc4_user_module_load(const struct comp_driver *drv, int ipc4_process_module_config(struct ipc4_message_request *ipc4, bool set, uint32_t *reply_ext); -/** - * @brief Process MOD_LARGE_CONFIG_GET in any execution context. - * @param[in] ipc4 IPC4 message request. - * @param[out] reply_ext Receives extension value for reply. - * @param[out] reply_tx_size Receives TX data size for reply. - * @param[out] reply_tx_data Receives TX data pointer for reply. - * @return IPC4 status code (0 on success). - */ -int ipc4_process_large_config_get(struct ipc4_message_request *ipc4, - uint32_t *reply_ext, - uint32_t *reply_tx_size, - void **reply_tx_data); - /** * @brief Process MOD_LARGE_CONFIG_SET in any execution context. * @param[in] ipc4 IPC4 message request. diff --git a/src/ipc/ipc4/handler-user.c b/src/ipc/ipc4/handler-user.c index 5cea1bf7dbe4..72b00bc32496 100644 --- a/src/ipc/ipc4/handler-user.c +++ b/src/ipc/ipc4/handler-user.c @@ -1091,10 +1091,11 @@ __cold static int ipc4_get_vendor_config_module_instance(struct comp_dev *dev, return IPC4_SUCCESS; } -__cold int ipc4_process_large_config_get(struct ipc4_message_request *ipc4, - uint32_t *reply_ext, - uint32_t *reply_tx_size, - void **reply_tx_data) +#ifdef CONFIG_SOF_USERSPACE_LL +__cold static int ipc4_process_large_config_get(struct ipc4_message_request *ipc4, + uint32_t *reply_ext, + uint32_t *reply_tx_size, + void **reply_tx_data) { struct ipc4_module_large_config_reply reply; const struct ipc4_module_large_config *config = @@ -1189,6 +1190,7 @@ __cold int ipc4_process_large_config_get(struct ipc4_message_request *ipc4, *reply_tx_data = data; return ret; } +#endif __cold static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ipc4) { From eab9059af9a6b1d14dfac6dfb3ae513493c98e55 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 14 Sep 2026 14:14:42 +0200 Subject: [PATCH 2/6] schedule: dp: remove the "const" qualifiew from a function Remove "const" from the "param" argument of scheduler_dp_thread_ipc() - some of the wrapped methods have to modify it. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/generic.c | 8 ++++---- src/audio/module_adapter/module_adapter.c | 2 +- src/include/sof/schedule/dp_schedule.h | 4 ++-- src/schedule/zephyr_dp_schedule_application.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 639dbc954dbb..889b5fdaec08 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -580,7 +580,7 @@ int module_prepare(struct processing_module *mod, #if CONFIG_SOF_USERSPACE_APPLICATION if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { - const union scheduler_dp_thread_ipc_param param = { + union scheduler_dp_thread_ipc_param param = { .pipeline_state = { .trigger_cmd = COMP_TRIGGER_PREPARE, .state = SOF_IPC4_PIPELINE_STATE_RUNNING, @@ -722,7 +722,7 @@ int module_reset(struct processing_module *mod) if (ops->reset) { #if CONFIG_SOF_USERSPACE_APPLICATION if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { - const union scheduler_dp_thread_ipc_param param = { + union scheduler_dp_thread_ipc_param param = { .pipeline_state.trigger_cmd = COMP_TRIGGER_STOP, }; ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_GLB_SET_PIPELINE_STATE, ¶m); @@ -939,7 +939,7 @@ int module_bind(struct processing_module *mod, const struct bind_info *bind_data if (ops->bind) { #if CONFIG_SOF_USERSPACE_APPLICATION if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { - const union scheduler_dp_thread_ipc_param param = { + union scheduler_dp_thread_ipc_param param = { .bind_data = bind_data, }; ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_BIND, ¶m); @@ -972,7 +972,7 @@ int module_unbind(struct processing_module *mod, const struct bind_info *unbind_ if (ops->unbind) { #if CONFIG_SOF_USERSPACE_APPLICATION if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { - const union scheduler_dp_thread_ipc_param param = { + union scheduler_dp_thread_ipc_param param = { .bind_data = unbind_data, }; ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_UNBIND, ¶m); diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 98234daa082c..e42b0e0fc66c 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1413,7 +1413,7 @@ int module_adapter_trigger(struct comp_dev *dev, int cmd) #if CONFIG_SOF_USERSPACE_APPLICATION if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { /* Process DP module's trigger */ - const union scheduler_dp_thread_ipc_param param = { + union scheduler_dp_thread_ipc_param param = { .pipeline_state.trigger_cmd = cmd, }; return scheduler_dp_thread_ipc(mod, SOF_IPC4_GLB_SET_PIPELINE_STATE, diff --git a/src/include/sof/schedule/dp_schedule.h b/src/include/sof/schedule/dp_schedule.h index 2c72178cd766..182df29301bb 100644 --- a/src/include/sof/schedule/dp_schedule.h +++ b/src/include/sof/schedule/dp_schedule.h @@ -133,11 +133,11 @@ union scheduler_dp_thread_ipc_param { #if CONFIG_ZEPHYR_DP_SCHEDULER int scheduler_dp_thread_ipc(struct processing_module *pmod, unsigned int cmd, - const union scheduler_dp_thread_ipc_param *param); + union scheduler_dp_thread_ipc_param *param); #else static inline int scheduler_dp_thread_ipc(struct processing_module *pmod, unsigned int cmd, - const union scheduler_dp_thread_ipc_param *param) + union scheduler_dp_thread_ipc_param *param) { return 0; } diff --git a/src/schedule/zephyr_dp_schedule_application.c b/src/schedule/zephyr_dp_schedule_application.c index 0cf8c457b9b8..75356d990b4c 100644 --- a/src/schedule/zephyr_dp_schedule_application.c +++ b/src/schedule/zephyr_dp_schedule_application.c @@ -174,7 +174,7 @@ static void ipc_thread_unflatten_run(struct processing_module *pmod, struct ipc4 /* Signal an IPC and wait for processing completion */ int scheduler_dp_thread_ipc(struct processing_module *pmod, unsigned int cmd, - const union scheduler_dp_thread_ipc_param *param) + union scheduler_dp_thread_ipc_param *param) { if (!pmod) { tr_err(&dp_tr, "no thread module"); From d592bff980af9a4c2c4397242d41756e0c03cb5b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 14 Sep 2026 14:19:31 +0200 Subject: [PATCH 3/6] audio: module-adapter: (cosmetic) consolidate module freeing code No need to split module freeing code between module_free() and module_adapter_free(), merge it back together. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/generic.c | 22 +++++++++++++++++----- src/audio/module_adapter/module_adapter.c | 11 ----------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 889b5fdaec08..48906bada70f 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -781,11 +781,23 @@ int module_free(struct processing_module *mod) struct module_data *md = &mod->priv; int ret = 0; - if (ops->free && (mod->dev->ipc_config.proc_domain != COMP_PROCESSING_DOMAIN_DP || - !IS_ENABLED(CONFIG_SOF_USERSPACE_APPLICATION))) { - ret = ops->free(mod); - if (ret) - comp_warn(mod->dev, "error: %d", ret); + if (ops->free) { + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL || + !IS_ENABLED(CONFIG_SOF_USERSPACE_APPLICATION)) { + ret = ops->free(mod); + if (ret) + comp_warn(mod->dev, "error: %d", ret); +#if CONFIG_SOF_USERSPACE_APPLICATION + } else { + /* + * Run DP module's .free() method in its thread context. + * Unlike with other IPCs we first run module's .free() + * in thread context, then cancel the thread, and then + * execute final clean up + */ + scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_DELETE_INSTANCE, NULL); +#endif + } } /* Free all memory shared by module_adapter & module */ diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index e42b0e0fc66c..2da09b17f5a3 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1483,17 +1483,6 @@ void module_adapter_free(struct comp_dev *dev) comp_dbg(dev, "start"); -#if CONFIG_SOF_USERSPACE_APPLICATION - if (dev->task) - /* - * Run DP module's .free() method in its thread context. - * Unlike with other IPCs we first run module's .free() in - * thread context, then cancel the thread, and then execute - * final clean up - */ - scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_DELETE_INSTANCE, NULL); -#endif - ret = module_free(mod); if (ret) comp_err(dev, "failed with error: %d", ret); From 89df374b131b17af15352276aeac47e78964366c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 14 Sep 2026 14:24:39 +0200 Subject: [PATCH 4/6] schedule: dp: use a macro instead of hard-coded mailbox size Use MAILBOX_HOSTBOX_SIZE to map the mailbox. Signed-off-by: Guennadi Liakhovetski --- src/schedule/zephyr_dp_schedule_application.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/schedule/zephyr_dp_schedule_application.c b/src/schedule/zephyr_dp_schedule_application.c index 75356d990b4c..0c058bc30004 100644 --- a/src/schedule/zephyr_dp_schedule_application.c +++ b/src/schedule/zephyr_dp_schedule_application.c @@ -592,12 +592,12 @@ int scheduler_dp_task_init(struct task **task, const struct sof_uuid_entry *uid, /* Host mailbox partition for additional IPC parameters: read-only */ pdata->mpart[SOF_DP_PART_CFG] = (struct k_mem_partition){ .start = (uintptr_t)sys_cache_uncached_ptr_get((void *)MAILBOX_HOSTBOX_BASE), - .size = 4096, + .size = MAILBOX_HOSTBOX_SIZE, .attr = K_MEM_PARTITION_P_RO_U_RO, }; pdata->mpart[SOF_DP_PART_CFG_CACHE] = (struct k_mem_partition){ .start = (uintptr_t)MAILBOX_HOSTBOX_BASE, - .size = 4096, + .size = MAILBOX_HOSTBOX_SIZE, .attr = K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB, }; From 05288debcf51f224ff2898f2a31282f701d07b18 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 14 Sep 2026 14:43:00 +0200 Subject: [PATCH 5/6] schedule: dp: add support for get/set_configuration With the "application" version of the DP scheduler individual module adapter methods are offloaded to the userspace thread context. Add two more methods to the offloaded set: get_configuration() and set_configuration(). Note, thet get_configuration() also requires copying data back to the coller, which until now wasn't done. Signed-off-by: Guennadi Liakhovetski --- .../module_adapter/module_adapter_ipc4.c | 52 +++++++-- src/include/sof/schedule/dp_schedule.h | 14 +++ src/schedule/zephyr_dp_schedule.h | 1 + src/schedule/zephyr_dp_schedule_application.c | 104 ++++++++++++++---- 4 files changed, 144 insertions(+), 27 deletions(-) diff --git a/src/audio/module_adapter/module_adapter_ipc4.c b/src/audio/module_adapter/module_adapter_ipc4.c index 7fa224a06d6c..a70eb77eff38 100644 --- a/src/audio/module_adapter/module_adapter_ipc4.c +++ b/src/audio/module_adapter/module_adapter_ipc4.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -263,10 +265,27 @@ int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_ return -EINVAL; } - if (interface->set_configuration) - return interface->set_configuration(mod, param_id, pos, data_offset_size, - (const uint8_t *)data, fragment_size, - NULL, 0); + if (interface->set_configuration) { +#if CONFIG_SOF_USERSPACE_APPLICATION + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + union scheduler_dp_thread_ipc_param param = { + .set_config = { + .param_id = param_id, + .position = pos, + .data_offset_size = data_offset_size, + .data = data, + .fragment_size = fragment_size, + }, + }; + + return scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_LARGE_CONFIG_SET, ¶m); + } else +#endif + return interface->set_configuration(mod, param_id, pos, data_offset_size, + (const uint8_t *)data, fragment_size, + NULL, 0); + } + return 0; } @@ -297,9 +316,28 @@ int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_ } } - if (interface->get_configuration) - return interface->get_configuration(mod, param_id, data_offset_size, - (uint8_t *)data, fragment_size); + if (interface->get_configuration) { +#if CONFIG_SOF_USERSPACE_APPLICATION + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + union scheduler_dp_thread_ipc_param param = { + .get_config = { + .param_id = param_id, + .data_offset_size = *data_offset_size, + .data = data, + .fragment_size = fragment_size, + }, + }; + + int ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_LARGE_CONFIG_SET, + ¶m); + if (!ret) + *data_offset_size = param.get_config.data_offset_size; + } else +#endif + return interface->get_configuration(mod, param_id, data_offset_size, + (uint8_t *)data, fragment_size); + } + /* * Return error if getter is not implemented. Otherwise, the host will suppose * the GET_VALUE command is successful, but the received cdata is not filled. diff --git a/src/include/sof/schedule/dp_schedule.h b/src/include/sof/schedule/dp_schedule.h index 182df29301bb..a2260febb2fc 100644 --- a/src/include/sof/schedule/dp_schedule.h +++ b/src/include/sof/schedule/dp_schedule.h @@ -15,6 +15,7 @@ #include #include #include +#include struct processing_module; struct module_ext_init_data; @@ -129,6 +130,19 @@ union scheduler_dp_thread_ipc_param { int n_sinks; struct sof_sink **sinks; } pipeline_state; + struct { + uint32_t param_id; + enum module_cfg_fragment_position position; + uint32_t data_offset_size; + size_t fragment_size; + const char *data; + } set_config; + struct { + uint32_t param_id; + uint32_t data_offset_size; + size_t fragment_size; + char *data; + } get_config; }; #if CONFIG_ZEPHYR_DP_SCHEDULER diff --git a/src/schedule/zephyr_dp_schedule.h b/src/schedule/zephyr_dp_schedule.h index 2119e44c9dfc..d33e6895507c 100644 --- a/src/schedule/zephyr_dp_schedule.h +++ b/src/schedule/zephyr_dp_schedule.h @@ -42,6 +42,7 @@ struct task_dp_pdata { struct processing_module *mod; /* the module to be scheduled */ uint32_t ll_cycles_to_start; /* current number of LL cycles till delayed start */ #if CONFIG_SOF_USERSPACE_APPLICATION + uint8_t *ipc_config_data; struct ipc4_flat *flat; struct k_mem_partition mpart[SOF_DP_PART_TYPE_COUNT]; #endif diff --git a/src/schedule/zephyr_dp_schedule_application.c b/src/schedule/zephyr_dp_schedule_application.c index 0c058bc30004..02bd00da5bbc 100644 --- a/src/schedule/zephyr_dp_schedule_application.c +++ b/src/schedule/zephyr_dp_schedule_application.c @@ -62,6 +62,19 @@ struct ipc4_flat { * valid and is covered by the DP thread's SOF_DP_PART_CFG partition. */ struct module_ext_init_data init_instance; + struct { + uint32_t param_id; + enum module_cfg_fragment_position position; + uint32_t data_offset_size; + size_t fragment_size; + const char *data; + } set_config; + struct { + uint32_t param_id; + uint32_t data_offset_size; + size_t fragment_size; + char *data; + } get_config; }; }; @@ -108,15 +121,39 @@ static int ipc_thread_flatten(unsigned int cmd, const union scheduler_dp_thread_ flat->pipeline_state.n_sinks * sizeof(flat->pipeline_state.sink[0])); } + break; + case SOF_IPC4_MOD_LARGE_CONFIG_SET: + flat->set_config.param_id = param->set_config.param_id; + flat->set_config.position = param->set_config.position; + flat->set_config.data_offset_size = param->set_config.data_offset_size; + flat->set_config.fragment_size = param->set_config.fragment_size; + flat->set_config.data = param->set_config.data; + break; + case SOF_IPC4_MOD_LARGE_CONFIG_GET: + flat->get_config.param_id = param->get_config.param_id; + flat->get_config.data_offset_size = param->get_config.data_offset_size; + flat->get_config.fragment_size = param->get_config.fragment_size; + flat->get_config.data = NULL/*param->get_config.data*/; } return 0; } +/* memory allocation helper structure */ +struct scheduler_dp_task_memory { + struct task task; + struct task_dp_pdata pdata; + struct comp_driver drv; + struct ipc4_flat flat; +}; + /* Unpack IPC data and execute a callback */ static void ipc_thread_unflatten_run(struct processing_module *pmod, struct ipc4_flat *flat) { const struct module_interface *const ops = pmod->dev->drv->adapter_ops; + struct scheduler_dp_task_memory *task_mem = container_of(flat, + struct scheduler_dp_task_memory, + flat); switch (flat->cmd) { case SOF_IPC4_MOD_BIND: @@ -167,6 +204,21 @@ static void ipc_thread_unflatten_run(struct processing_module *pmod, struct ipc4 flat->pipeline_state.sink, flat->pipeline_state.n_sinks); } + break; + case SOF_IPC4_MOD_LARGE_CONFIG_SET: + flat->ret = ops->set_configuration(pmod, flat->set_config.param_id, + flat->set_config.position, + flat->set_config.data_offset_size, + flat->set_config.data, + flat->set_config.fragment_size, NULL, 0); + break; + case SOF_IPC4_MOD_LARGE_CONFIG_GET: + flat->ret = ops->get_configuration(pmod, flat->get_config.param_id, + &flat->get_config.data_offset_size, + task_mem->pdata.ipc_config_data, + flat->get_config.fragment_size); + if (!flat->ret) + flat->get_config.data = task_mem->pdata.ipc_config_data; } } @@ -205,16 +257,24 @@ int scheduler_dp_thread_ipc(struct processing_module *pmod, unsigned int cmd, scheduler_dp_unlock(lock_key); - if (!ret) { - /* Wait for completion */ - ret = k_sem_take(&dp_sync[core], DP_THREAD_IPC_TIMEOUT); - if (ret < 0) - tr_err(&dp_tr, "Failed waiting for DP thread: %d", ret); - else - ret = pdata->flat->ret; + if (ret < 0) + return ret; + + /* Wait for completion */ + ret = k_sem_take(&dp_sync[core], DP_THREAD_IPC_TIMEOUT); + if (ret < 0) { + tr_err(&dp_tr, "Failed waiting for DP thread: %d", ret); + return ret; } - return ret; + if (!pdata->flat->ret && cmd == SOF_IPC4_MOD_LARGE_CONFIG_GET) { + /* A single case of returning data */ + param->get_config.data_offset_size = pdata->flat->get_config.data_offset_size; + return memcpy_s(param->get_config.data, SOF_IPC_MSG_MAX_SIZE, + pdata->flat->get_config.data, param->get_config.fragment_size); + } + + return pdata->flat->ret; } /* Go through all DP tasks and recalculate their readiness and deadlines @@ -415,14 +475,6 @@ static void scheduler_dp_domain_free(struct task_dp_pdata *pdata) objpool_free(&dp_mdom_head, mdom); } -/* memory allocation helper structure */ -struct scheduler_dp_task_memory { - struct task task; - struct task_dp_pdata pdata; - struct comp_driver drv; - struct ipc4_flat flat; -}; - void z_impl_scheduler_dp_internal_free(struct task *task) { struct task_dp_pdata *pdata = task->priv_data; @@ -500,20 +552,31 @@ int scheduler_dp_task_init(struct task **task, const struct sof_uuid_entry *uid, struct task_dp_pdata *pdata = &task_memory->pdata; + if (mod->dev->drv->adapter_ops->get_configuration) { + pdata->ipc_config_data = mod_alloc_ext(mod, SOF_MEM_FLAG_USER, SOF_IPC_MSG_MAX_SIZE, + 0); + if (!pdata->ipc_config_data) { + tr_err(&dp_tr, "Failed to allocate memory for get-config"); + goto e_stack; + } + } else { + pdata->ipc_config_data = NULL; + } + pdata->flat = &task_memory->flat; pdata->event = k_object_alloc(K_OBJ_EVENT); if (!pdata->event) { tr_err(&dp_tr, "Event object allocation failed"); ret = -ENOMEM; - goto e_stack; + goto e_config; } pdata->thread = k_object_alloc(K_OBJ_THREAD); if (!pdata->thread) { tr_err(&dp_tr, "Thread object allocation failed"); ret = -ENOMEM; - goto e_kobj; + goto e_event; } memset(&pdata->thread->arch, 0, sizeof(pdata->thread->arch)); @@ -636,10 +699,11 @@ int scheduler_dp_task_init(struct task **task, const struct sof_uuid_entry *uid, if (on_pool) objpool_free(&dp_mdom_head, mdom); k_thread_abort(pdata->thread_id); -e_kobj: - /* k_object_free looks for a pointer in the list, any invalid value can be passed */ k_object_free(pdata->thread); +e_event: k_object_free(pdata->event); +e_config: + mod_free(mod, pdata->ipc_config_data); e_stack: user_stack_free(p_stack); e_tmem: From ba3abba6a363f5dc5f0450b6eb66a58ca1d7dc51 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 14 Sep 2026 14:51:12 +0200 Subject: [PATCH 6/6] ipc: (cosmetic) add comments for buffer binding It is unclear in which context buffer binding should be executed when an LL and a DP modules are being bound with both running in userspace context. Since DP modules have limited visibility into the system and the userspace LL context on the other hand has access to most DP assets, perform binding and unbinding in LL thread context. Add comments to explain that. Signed-off-by: Guennadi Liakhovetski --- src/ipc/ipc4/handler-user.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ipc/ipc4/handler-user.c b/src/ipc/ipc4/handler-user.c index 72b00bc32496..94360942934b 100644 --- a/src/ipc/ipc4/handler-user.c +++ b/src/ipc/ipc4/handler-user.c @@ -1685,6 +1685,13 @@ __cold int ipc4_user_process_module_message(struct ipc4_message_request *ipc4, break; case SOF_IPC4_MOD_BIND: #ifdef CONFIG_SOF_USERSPACE_LL + /* + * bind and unbind can connect LL with DP. In that case it isn't + * immediately clear whether the handler should run in the DP + * thread context or in the LL IPC thread context. The LL IPC + * thread has access to DP modules, so we have to perform + * binding in the LL IPC thread context + */ ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat, ipc4_user_target_core_module(ipc4)); #else @@ -1693,6 +1700,7 @@ __cold int ipc4_user_process_module_message(struct ipc4_message_request *ipc4, break; case SOF_IPC4_MOD_UNBIND: #ifdef CONFIG_SOF_USERSPACE_LL + /* DP / LL: see comment above */ ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat, ipc4_user_target_core_module(ipc4)); #else