diff options
| author | Mark Brown <broonie@kernel.org> | 2026-07-31 15:44:40 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-07-31 15:44:40 +0100 |
| commit | 5ce2195c087493f5a42cef026d3bdc2b1ea01f11 (patch) | |
| tree | 67054056800faa566d1d9b3fd2cab9162ba2c1c4 /sound/soc/sof | |
| parent | 74a66323e1489cfccecf6dfcfa1df4a914676bc2 (diff) | |
| parent | 221f3b29366ec9f8579a8366ba438726c596ff61 (diff) | |
ASoC: SOF: ipc4-topology: Update the memory data building
Peter Ujfalusi <peter.ujfalusi@linux.intel.com> says:
This series fixes some issues left to the first version
sof_ipc4_mod_init_ext_dp_memory_data payload building code. The
payload to specify memory requirements of Data Processing components,
running as independent processes in SOF firmware.
But more importantly it adds a payload of similar purpose to the
pipeline create message, e.g. sof_ipc4_glb_pipe_payload. It sums up
the memory requirements of individual Low Latency components in the
pipeline and sends the summed up values in pipeline create message.
Link: https://patch.msgid.link/20260730104141.14817-1-peter.ujfalusi@linux.intel.com
Diffstat (limited to 'sound/soc/sof')
| -rw-r--r-- | sound/soc/sof/ipc4-topology.c | 179 | ||||
| -rw-r--r-- | sound/soc/sof/sof-audio.h | 8 |
2 files changed, 150 insertions, 37 deletions
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 8ac7dde32f77..45f434c86cf9 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -163,11 +163,11 @@ static const struct sof_topology_token comp_ext_tokens[] = { {SOF_TKN_COMP_SCHED_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_domain, offsetof(struct snd_sof_widget, comp_domain)}, {SOF_TKN_COMP_DOMAIN_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct snd_sof_widget, dp_domain_id)}, + offsetof(struct snd_sof_widget, domain_id)}, {SOF_TKN_COMP_HEAP_BYTES_REQUIREMENT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct snd_sof_widget, dp_heap_bytes)}, + offsetof(struct snd_sof_widget, heap_bytes)}, {SOF_TKN_COMP_STACK_BYTES_REQUIREMENT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct snd_sof_widget, dp_stack_bytes)}, + offsetof(struct snd_sof_widget, stack_bytes)}, }; static const struct sof_topology_token gain_tokens[] = { @@ -1371,6 +1371,22 @@ sof_ipc4_update_resource_usage(struct snd_sof_dev *sdev, struct snd_sof_widget * pipeline = pipe_widget->private; pipeline->mem_usage += total; + /* + * If this is not a Data Processing module instance, add the + * required heap sizes to the sum of all module instances belonging + * to the same pipeline, and find the maximum stack requirement + * among all module instances belonging to the same pipeline. + */ + if (swidget->comp_domain != SOF_COMP_DOMAIN_DP) { + pipe_widget->heap_bytes += swidget->heap_bytes; + if (pipe_widget->stack_bytes < swidget->stack_bytes) + pipe_widget->stack_bytes = swidget->stack_bytes; + + dev_dbg(sdev->dev, "%s mem reqs to %s heap %u stack %u", + swidget->widget->name, pipe_widget->widget->name, + pipe_widget->heap_bytes, pipe_widget->stack_bytes); + } + /* Update base_config->cpc from the module manifest */ sof_ipc4_update_cpc_from_manifest(sdev, fw_module, base_config); @@ -1688,6 +1704,8 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) pipe_widget = swidget->spipe->pipe_widget; pipeline = pipe_widget->private; pipeline->mem_usage = 0; + pipe_widget->heap_bytes = 0; + pipe_widget->stack_bytes = 0; if (WIDGET_IS_AIF(swidget->id) || swidget->id == snd_soc_dapm_buffer) { if (pipeline->use_chain_dma) { @@ -3085,27 +3103,47 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr return 0; } -static int sof_ipc4_widget_setup_msg_payload(struct snd_sof_dev *sdev, - struct snd_sof_widget *swidget, - struct sof_ipc4_msg *msg, - void *ipc_data, u32 ipc_size, - void **new_data) +static void sof_ipc4_add_init_ext_dp_memory_data(struct snd_sof_dev *sdev, + struct snd_sof_widget *swidget, + u32 *payload, u32 *ext_pos, + struct sof_ipc4_module_init_ext_object **hdr) +{ + /* Add memory_data if comp_domain indicates DP */ + if (swidget->comp_domain == SOF_COMP_DOMAIN_DP) { + struct sof_ipc4_mod_init_ext_dp_memory_data *dp_mem_data; + + *hdr = (struct sof_ipc4_module_init_ext_object *)&payload[*ext_pos]; + (*hdr)->header = + SOF_IPC4_MOD_INIT_EXT_OBJ_ID(SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA) | + SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS(DIV_ROUND_UP(sizeof(*dp_mem_data), + sizeof(u32))); + *ext_pos += DIV_ROUND_UP(sizeof(**hdr), sizeof(u32)); + dp_mem_data = (struct sof_ipc4_mod_init_ext_dp_memory_data *)&payload[*ext_pos]; + dp_mem_data->domain_id = swidget->domain_id; + dp_mem_data->stack_bytes = swidget->stack_bytes; + dp_mem_data->heap_bytes = swidget->heap_bytes; + *ext_pos += DIV_ROUND_UP(sizeof(*dp_mem_data), sizeof(u32)); + } +} + +static int sof_ipc4_widget_mod_init_msg_payload(struct snd_sof_dev *sdev, + struct snd_sof_widget *swidget, + struct sof_ipc4_msg *msg, + void *ipc_data, u32 ipc_size, + void **new_data) { - struct sof_ipc4_mod_init_ext_dp_memory_data *dp_mem_data; struct sof_ipc4_module_init_ext_init *ext_init; - struct sof_ipc4_module_init_ext_object *hdr; + struct sof_ipc4_module_init_ext_object *hdr = NULL; int new_size; u32 *payload; u32 ext_pos; - /* For the moment the only reason for adding init_ext_init payload is DP - * memory data. If both stack and heap size are 0 (= use default), then - * there is no need for init_ext_init payload. + /* + * Only DP widgets currently add init-ext objects here. Avoid allocating + * a max-sized payload buffer for widgets that will immediately return 0. */ - if (swidget->comp_domain != SOF_COMP_DOMAIN_DP) { - msg->extension &= ~SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK; + if (swidget->comp_domain != SOF_COMP_DOMAIN_DP) return 0; - } payload = kzalloc(sdev->ipc->max_payload_size, GFP_KERNEL); if (!payload) @@ -3113,27 +3151,26 @@ static int sof_ipc4_widget_setup_msg_payload(struct snd_sof_dev *sdev, /* Add ext_init first and set objects array flag to 1 */ ext_init = (struct sof_ipc4_module_init_ext_init *)payload; - ext_init->word0 |= SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK; ext_pos = DIV_ROUND_UP(sizeof(*ext_init), sizeof(u32)); /* Add object array objects after ext_init */ - /* Add dp_memory_data if comp_domain indicates DP */ - if (swidget->comp_domain == SOF_COMP_DOMAIN_DP) { - hdr = (struct sof_ipc4_module_init_ext_object *)&payload[ext_pos]; - hdr->header = SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_MASK | - SOF_IPC4_MOD_INIT_EXT_OBJ_ID(SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA) | - SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS(DIV_ROUND_UP(sizeof(*dp_mem_data), - sizeof(u32))); - ext_pos += DIV_ROUND_UP(sizeof(*hdr), sizeof(u32)); - dp_mem_data = (struct sof_ipc4_mod_init_ext_dp_memory_data *)&payload[ext_pos]; - dp_mem_data->domain_id = swidget->dp_domain_id; - dp_mem_data->stack_bytes = swidget->dp_stack_bytes; - dp_mem_data->heap_bytes = swidget->dp_heap_bytes; - ext_pos += DIV_ROUND_UP(sizeof(*dp_mem_data), sizeof(u32)); + sof_ipc4_add_init_ext_dp_memory_data(sdev, swidget, payload, &ext_pos, &hdr); + + /* Add following object array items here */ + + if (!hdr) { + /* + * NOTE: Remove this early bail out, when struct + * sof_ipc4_module_init_ext_init alone has some + * function. + */ + kfree(payload); + return 0; } - /* If another array object is added, remember clear previous OBJ_LAST bit */ + ext_init->word0 |= SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK; + hdr->header |= SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_MASK; /* Calculate final size and check that it fits to max payload size */ new_size = ext_pos * sizeof(u32) + ipc_size; @@ -3156,6 +3193,69 @@ static int sof_ipc4_widget_setup_msg_payload(struct snd_sof_dev *sdev, return new_size; } +static void sof_ipc4_widget_pipe_ext_obj_memory_data(struct snd_sof_dev *sdev, + struct snd_sof_widget *swidget, + u32 *payload, u32 *ext_pos, + struct sof_ipc4_glb_pipe_ext_object **hdr) +{ + struct sof_ipc4_glb_pipe_ext_obj_memory_data *mem_data; + + *hdr = (struct sof_ipc4_glb_pipe_ext_object *)&payload[*ext_pos]; + (*hdr)->header = + SOF_IPC4_GLB_PIPE_EXT_OBJ_ID(SOF_IPC4_GLB_PIPE_DATA_ID_MEM_DATA) | + SOF_IPC4_GLB_PIPE_EXT_OBJ_WORDS(DIV_ROUND_UP(sizeof(*mem_data), + sizeof(u32))); + *ext_pos += DIV_ROUND_UP(sizeof(**hdr), sizeof(u32)); + mem_data = (struct sof_ipc4_glb_pipe_ext_obj_memory_data *)&payload[*ext_pos]; + mem_data->domain_id = swidget->domain_id; + mem_data->stack_bytes = swidget->stack_bytes; + mem_data->heap_bytes = swidget->heap_bytes; + *ext_pos += DIV_ROUND_UP(sizeof(*mem_data), sizeof(u32)); + + dev_dbg(sdev->dev, + "%s; domain_id %u stack %u heap %u bytes", + swidget->widget->name, mem_data->domain_id, mem_data->stack_bytes, + mem_data->heap_bytes); +} + +static int sof_ipc4_widget_pipe_create_msg_payload(struct snd_sof_dev *sdev, + struct snd_sof_widget *swidget, + struct sof_ipc4_msg *msg, + void **new_data) +{ + struct sof_ipc4_glb_pipe_payload *payload_hdr; + struct sof_ipc4_glb_pipe_ext_object *hdr = NULL; + u32 *payload; + u32 ext_pos; + + payload = kzalloc(sdev->ipc->max_payload_size, GFP_KERNEL); + if (!payload) + return -ENOMEM; + + /* Add sof_ipc4_glb_pipe_payload and set array bit to 1 */ + payload_hdr = (struct sof_ipc4_glb_pipe_payload *)payload; + payload_hdr->word0 |= SOF_IPC4_GLB_PIPE_EXT_OBJ_ARRAY_MASK; + ext_pos = DIV_ROUND_UP(sizeof(*payload_hdr), sizeof(u32)); + + sof_ipc4_widget_pipe_ext_obj_memory_data(sdev, swidget, payload, &ext_pos, &hdr); + /* Add following array objects here */ + + /* Mark end of object array */ + hdr->header |= SOF_IPC4_GLB_PIPE_EXT_OBJ_LAST_MASK; + + /* Put total payload size in words to the payload header */ + payload_hdr->word0 |= SOF_IPC4_GLB_PIPE_PAYLOAD_WORDS(ext_pos); + *new_data = payload; + + /* Update msg extension bits according to the payload changes */ + msg->extension |= SOF_IPC4_GLB_PIPE_PAYLOAD_MASK; + + dev_dbg(sdev->dev, "%s: payload word0 %#x", swidget->widget->name, + payload_hdr->word0); + + return ext_pos * sizeof(int32_t); +} + static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; @@ -3309,8 +3409,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget swidget->widget->name, swidget->pipeline_id, module_id, swidget->instance_id, swidget->core); - ret = sof_ipc4_widget_setup_msg_payload(sdev, swidget, msg, ipc_data, ipc_size, - &ext_data); + ret = sof_ipc4_widget_mod_init_msg_payload(sdev, swidget, msg, ipc_data, ipc_size, + &ext_data); if (ret < 0) goto fail; @@ -3322,6 +3422,17 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget dev_dbg(sdev->dev, "Create pipeline %s (pipe %d) - instance %d, core %d\n", swidget->widget->name, swidget->pipeline_id, swidget->instance_id, swidget->core); + + msg->extension &= ~SOF_IPC4_GLB_PIPE_PAYLOAD_MASK; + ret = sof_ipc4_widget_pipe_create_msg_payload(sdev, swidget, msg, + &ext_data); + if (ret < 0) + goto fail; + + if (ret > 0) { + ipc_size = ret; + ipc_data = ext_data; + } } msg->data_size = ipc_size; @@ -3379,6 +3490,8 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget swidget->widget->name); pipeline->mem_usage = 0; + swidget->heap_bytes = 0; + swidget->stack_bytes = 0; pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED; ida_free(&pipeline_ida, swidget->instance_id); swidget->instance_id = -EINVAL; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 138e5fcc2dd0..ae95efc9be1c 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -459,10 +459,10 @@ struct snd_sof_widget { /* Scheduling domain (enum sof_comp_domain), unset, Low Latency, or Data Processing */ u32 comp_domain; - /* The values below are added to mod_init pay load if comp_domain indicates DP component */ - u32 dp_domain_id; /* DP process userspace domain ID */ - u32 dp_stack_bytes; /* DP process stack size requirement in bytes */ - u32 dp_heap_bytes; /* DP process heap size requirement in bytes */ + /* Module instance's memory configuration. */ + u32 domain_id; /* Module instance's userspace domain ID */ + u32 stack_bytes; /* Module instance's stack size requirement */ + u32 heap_bytes; /* Module instance's heap size requirement */ struct snd_soc_dapm_widget *widget; struct list_head list; /* list in sdev widget list */ |
