ipc: fix buffer cache handling during freeing

Both IPC3 and IPC4 stream termination paths use uncached buffer
addresses, which can contain stale data with core-local buffers. Fix
both to use cached buffer aliases.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
Guennadi Liakhovetski 2022-08-01 10:33:08 +02:00 committed by Liam Girdwood
parent 9ead82e1b8
commit 566415e642
2 changed files with 17 additions and 9 deletions

View File

@ -472,6 +472,7 @@ int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id)
unsigned int core;
bool sink_active = false;
bool source_active = false;
struct comp_buffer __sparse_cache *buffer_c;
/* check whether buffer exists */
ibd = ipc_get_comp_by_id(ipc, buffer_id);
@ -489,6 +490,8 @@ int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id)
if (!cpu_is_me(ibd->core))
return ipc_process_on_core(ibd->core, false);
buffer_c = buffer_acquire(ibd->cb);
/* try to find sink/source components to check if they still exists */
list_for_item(clist, &ipc->comp_list) {
icd = container_of(clist, struct ipc_comp_dev, list);
@ -496,19 +499,21 @@ int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id)
continue;
/* check comp state if sink and source are valid */
if (ibd->cb->sink == icd->cd &&
ibd->cb->sink->state != COMP_STATE_READY) {
sink = ibd->cb->sink;
if (buffer_c->sink == icd->cd &&
buffer_c->sink->state != COMP_STATE_READY) {
sink = buffer_c->sink;
sink_active = true;
}
if (ibd->cb->source == icd->cd &&
ibd->cb->source->state != COMP_STATE_READY) {
source = ibd->cb->source;
if (buffer_c->source == icd->cd &&
buffer_c->source->state != COMP_STATE_READY) {
source = buffer_c->source;
source_active = true;
}
}
buffer_release(buffer_c);
/*
* A buffer could be connected to 2 different pipelines. When one pipeline is freed, the
* buffer comp that belongs in this pipeline will need to be freed even when the other

View File

@ -349,10 +349,13 @@ int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect)
buffer_id = IPC4_COMP_ID(bu->extension.r.src_queue, bu->extension.r.dst_queue);
list_for_item(sink_list, &src->bsink_list) {
struct comp_buffer *buf;
struct comp_buffer *buf = container_of(sink_list, struct comp_buffer, source_list);
struct comp_buffer __sparse_cache *buf_c = buffer_acquire(buf);
bool found = buf_c->id == buffer_id;
buf = container_of(sink_list, struct comp_buffer, source_list);
if (buf->id == buffer_id) {
buffer_release(buf_c);
if (found) {
buffer = buf;
break;
}