Skip to content

Commit fc57e8d

Browse files
committed
pipeline: stop all connected pipelines on xrun
When an xrun occurs we currently stop the affected pipelines, which also leads to stopping the pipeline task. However, the stream can be using several pipelines, all of which have to be stopped. If not stopped, tasks belonging to those pipelines will continue to be scheduled. This patch collects all connected pipelines and stops them all. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 9e30120 commit fc57e8d

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

src/audio/pipeline/pipeline-schedule.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,17 @@ void pipeline_schedule_triggered(struct pipeline_walk_context *ctx,
192192
}
193193
pipeline_schedule_copy(p, 0);
194194
}
195+
break;
196+
case COMP_TRIGGER_XRUN:
197+
list_for_item(tlist, &ctx->pipelines) {
198+
p = container_of(tlist, struct pipeline, list);
199+
if (!p->xrun_bytes)
200+
/*
201+
* the exact number of xrun bytes is unused,
202+
* just make it non-0
203+
*/
204+
p->xrun_bytes = 1;
205+
}
195206
}
196207

197208
irq_local_enable(flags);

src/audio/pipeline/pipeline-stream.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,53 @@ static int pipeline_trigger_list(struct pipeline *p, struct comp_dev *host, int
255255
return ret;
256256
}
257257

258+
static void pipeline_trigger_xrun(struct pipeline *p, struct comp_dev **host)
259+
{
260+
/*
261+
* XRUN can happen on a pipeline, not directly attached to the host,
262+
* find the original one
263+
*/
264+
do {
265+
/* Check the opposite direction */
266+
int dir = (*host)->direction == PPL_DIR_DOWNSTREAM ? PPL_DIR_UPSTREAM :
267+
PPL_DIR_DOWNSTREAM;
268+
struct list_item *buffer_list = comp_buffer_list(*host, dir);
269+
struct list_item *clist;
270+
bool found = false;
271+
272+
if (list_is_empty(buffer_list))
273+
/* Reached the original host */
274+
break;
275+
276+
list_for_item(clist, buffer_list) {
277+
struct comp_buffer *buffer = buffer_from_list(clist,
278+
struct comp_buffer, dir);
279+
struct comp_dev *buffer_comp = buffer_get_comp(buffer, dir);
280+
281+
switch (buffer_comp->pipeline->status) {
282+
case COMP_STATE_ACTIVE:
283+
case COMP_STATE_PREPARE:
284+
found = true;
285+
break;
286+
}
287+
288+
if (found) {
289+
*host = (*host)->direction == PPL_DIR_DOWNSTREAM ?
290+
buffer_comp->pipeline->source_comp :
291+
buffer_comp->pipeline->sink_comp;
292+
break;
293+
}
294+
}
295+
296+
if (!found) {
297+
/* No active pipeline found! Should never occur. */
298+
pipe_err(p, "No active pipeline found to link to pipeline %u!",
299+
(*host)->pipeline->pipeline_id);
300+
break;
301+
}
302+
} while (true);
303+
}
304+
258305
/* trigger pipeline in IPC context */
259306
int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd)
260307
{
@@ -268,9 +315,12 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd)
268315
/* Execute immediately */
269316
ret = pipeline_trigger_run(p, host, cmd);
270317
return ret == PPL_STATUS_PATH_STOP ? 0 : ret;
318+
case COMP_TRIGGER_XRUN:
319+
pipeline_trigger_xrun(p, &host);
320+
COMPILER_FALLTHROUGH;
271321
case COMP_TRIGGER_PRE_RELEASE:
272322
case COMP_TRIGGER_PRE_START:
273-
/* Add all connected pipelines to the list and schedule them all */
323+
/* Add all connected pipelines to the list and trigger them all */
274324
ret = pipeline_trigger_list(p, host, cmd);
275325
if (ret < 0)
276326
return ret;

src/audio/pipeline/pipeline-xrun.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ void pipeline_xrun(struct pipeline *p, struct comp_dev *dev,
153153
return;
154154

155155
/* notify all pipeline comps we are in XRUN, and stop copying */
156-
ret = pipeline_trigger_run(p, p->source_comp, COMP_TRIGGER_XRUN);
156+
ret = pipeline_trigger(p, p->source_comp, COMP_TRIGGER_XRUN);
157157
if (ret < 0)
158158
pipe_err(p, "pipeline_xrun(): Pipelines notification about XRUN failed, ret = %d",
159159
ret);

src/include/sof/audio/component_ext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ struct comp_driver_list {
3535

3636
/** \brief Retrieves the component device buffer list. */
3737
#define comp_buffer_list(comp, dir) \
38-
((dir) == PPL_DIR_DOWNSTREAM ? &comp->bsink_list : \
39-
&comp->bsource_list)
38+
((dir) == PPL_DIR_DOWNSTREAM ? &(comp)->bsink_list : \
39+
&(comp)->bsource_list)
4040

4141
/** See comp_ops::new */
4242
struct comp_dev *comp_new(struct sof_ipc_comp *comp);

0 commit comments

Comments
 (0)