Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/audio/module_adapter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ sequenceDiagram

Connection establishes buffer relationships (`comp_buffer`) connecting the component sources and sinks to the rest of the generic pipeline graph.

Each connected buffer takes a slot in `mod->sinks[]` or `mod->sources[]`, which hold `CONFIG_MODULE_MAX_CONNECTIONS` entries each. A bind (IPC4) or prepare (IPC3) that would need more slots fails with `-EINVAL`.

```mermaid
sequenceDiagram
participant Pipe as Pipeline
Expand Down
10 changes: 10 additions & 0 deletions src/audio/module_adapter/module_adapter_ipc3.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,23 @@ int module_adapter_sink_src_prepare(struct comp_dev *dev)
/* acquire all sink and source buffers, get handlers to sink/source API */
i = 0;
comp_dev_for_each_consumer(dev, sink_buffer) {
if (i == CONFIG_MODULE_MAX_CONNECTIONS) {
comp_err(dev, "more than %d sinks connected",
CONFIG_MODULE_MAX_CONNECTIONS);
return -EINVAL;
}
mod->sinks[i] = audio_buffer_get_sink(&sink_buffer->audio_buffer);
i++;
}
mod->num_of_sinks = i;

i = 0;
comp_dev_for_each_producer(dev, source_buffer) {
if (i == CONFIG_MODULE_MAX_CONNECTIONS) {
comp_err(dev, "more than %d sources connected",
CONFIG_MODULE_MAX_CONNECTIONS);
return -EINVAL;
}
mod->sources[i] = audio_buffer_get_source(&source_buffer->audio_buffer);
i++;
}
Expand Down
19 changes: 19 additions & 0 deletions src/audio/module_adapter/module_adapter_ipc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,29 @@ __cold static int module_update_source_buffer_params(struct processing_module *m
__cold int module_adapter_bind(struct comp_dev *dev, const struct bind_info *bind_data)
{
struct processing_module *mod = comp_mod(dev);
struct comp_buffer *buffer;
unsigned int count = 0;
int ret;

assert_can_be_cold();

/*
* The buffer is already connected here and every connected buffer
* takes a slot in mod->sinks[] or mod->sources[].
*/
if (bind_data->bind_type == COMP_BIND_TYPE_SINK) {
comp_dev_for_each_consumer(dev, buffer)
count++;
} else {
comp_dev_for_each_producer(dev, buffer)
count++;
}

if (count > CONFIG_MODULE_MAX_CONNECTIONS) {
comp_err(dev, "%u connections exceed max %d", count, CONFIG_MODULE_MAX_CONNECTIONS);
return -EINVAL;
}

ret = module_update_source_buffer_params(mod, bind_data);
if (ret < 0)
return ret;
Expand Down
9 changes: 8 additions & 1 deletion src/ipc/ipc4/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1058,10 +1058,17 @@ __cold int ipc4_comp_connect(struct ipc *ipc, const struct ipc4_module_bind_unbi
return IPC4_SUCCESS;

e_sink_bind:
/* sink bind was already called */
/*
* The source is already bound. Disconnect first, as
* ipc4_comp_disconnect() does, so its unbind does not keep the
* buffer in the source's sinks[].
*/
pipeline_disconnect(sink, buffer, PPL_CONN_DIR_BUFFER_TO_COMP);
pipeline_disconnect(source, buffer, PPL_CONN_DIR_COMP_TO_BUFFER);
bind_data.bind_type = COMP_BIND_TYPE_SINK;
bind_data.sink = audio_buffer_get_sink(&buffer->audio_buffer);
comp_unbind(source, &bind_data);
goto free;
e_src_bind:
pipeline_disconnect(sink, buffer, PPL_CONN_DIR_BUFFER_TO_COMP);
e_sink_connect:
Expand Down
Loading