Skip to content

Commit f15dc5b

Browse files
abonislawskilgirdwood
authored andcommitted
ipc: clear dangling pipeline comp refs on instance free
ipc_comp_free() freed a component that a completed pipeline still referenced via source_comp/sink_comp/sched_comp, so a later SET_PIPELINE_STATE dereferenced the freed comp_dev. Clear those references on free and bail out of pipeline_get_host_dev() when an endpoint is gone. Signed-off-by: Adrian Bonislawski <adrian.bonislawski@intel.com>
1 parent edd1f93 commit f15dc5b

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

src/ipc/ipc-helper.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ __cold int ipc_comp_free(struct ipc *ipc, uint32_t comp_id)
291291
struct ipc_comp_dev *icd;
292292
struct comp_buffer *buffer;
293293
struct comp_buffer *safe;
294+
struct list_item *clist;
294295
uint32_t flags;
295296

296297
assert_can_be_cold();
@@ -348,6 +349,24 @@ __cold int ipc_comp_free(struct ipc *ipc, uint32_t comp_id)
348349

349350
irq_local_enable(flags);
350351

352+
/*
353+
* A completed pipeline stores raw comp_dev pointers in its
354+
* source_comp/sink_comp/sched_comp fields.
355+
*/
356+
list_for_item(clist, &ipc->comp_list) {
357+
struct ipc_comp_dev *ppl_icd = container_of(clist, struct ipc_comp_dev, list);
358+
359+
if (ppl_icd->type != COMP_TYPE_PIPELINE)
360+
continue;
361+
362+
if (ppl_icd->pipeline->source_comp == icd->cd)
363+
ppl_icd->pipeline->source_comp = NULL;
364+
if (ppl_icd->pipeline->sink_comp == icd->cd)
365+
ppl_icd->pipeline->sink_comp = NULL;
366+
if (ppl_icd->pipeline->sched_comp == icd->cd)
367+
ppl_icd->pipeline->sched_comp = NULL;
368+
}
369+
351370
/* free component and remove from list */
352371
comp_free(icd->cd);
353372

src/ipc/ipc4/handler-user.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ static struct ipc_comp_dev *pipeline_get_host_dev(struct ipc_comp_dev *ppl_icd)
149149
struct ipc *ipc = ipc_get();
150150
int host_id;
151151

152+
if (!ppl_icd->pipeline->source_comp || !ppl_icd->pipeline->sink_comp) {
153+
ipc_cmd_err(&ipc_tr, "pipeline %d: source/sink comp freed", ppl_icd->id);
154+
return NULL;
155+
}
156+
152157
/* If the source component's direction is not set but the sink's direction is,
153158
* this block will copy the direction from the sink to the source component and
154159
* mark the source's direction as set.

0 commit comments

Comments
 (0)