summaryrefslogtreecommitdiff
path: root/sound/soc/sof
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-07-31 15:44:40 +0100
committerMark Brown <broonie@kernel.org>2026-07-31 15:44:40 +0100
commit5ce2195c087493f5a42cef026d3bdc2b1ea01f11 (patch)
tree67054056800faa566d1d9b3fd2cab9162ba2c1c4 /sound/soc/sof
parent74a66323e1489cfccecf6dfcfa1df4a914676bc2 (diff)
parent221f3b29366ec9f8579a8366ba438726c596ff61 (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.c179
-rw-r--r--sound/soc/sof/sof-audio.h8
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 */