From 4240ce27ec8ad43d580ccd049a9fc7d90d501e72 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 16 Feb 2022 11:10:14 +0100 Subject: [PATCH] pipeline: fix aborting STOP or PAUSE propagation When trigger.aborted is set, pipeline_trigger_run() also returns PPL_STATUS_PATH_STOP. So the current test for trigger.aborted in pipeline_task_cmd() after pipeline_trigger_run() is a left-over from an earlier implementation and is never entered with the current flow. In the current implementation, a typical playback topology like [pipeline A] PCM -> ... - [pipeline B] mixer -> ... -> DAI when a pause is triggered mixer will stop its propagation, set trigger.aborted on pipeline B to true and return PPL_STATUS_PATH_STOP. pipeline_task_cmd() is still running in the context of pipeline A, so it will detect PPL_STATUS_PATH_STOP, check that trigger.aborted is not set and terminate the task. Then the scheduler will run the task for pipeline B, that one will verify, that trigger.host == NULL, then find the trigger.aborted to be true and will keep the task running. In a topology, where the PCM, the mixer and the DAI all belong to the same pipeline, when PAUSE is triggered, the whole pipeline should be left running which is what this patch achieves by checkint trigger.aborted when PPL_STATUS_PATH_STOP is returned by pipeline_trigger_run(). BugLink: https://github.com/thesofproject/sof/issues/5257 Signed-off-by: Guennadi Liakhovetski --- src/audio/pipeline/pipeline-schedule.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/audio/pipeline/pipeline-schedule.c b/src/audio/pipeline/pipeline-schedule.c index 7b6e7bd1013e..19d6843aaf89 100644 --- a/src/audio/pipeline/pipeline-schedule.c +++ b/src/audio/pipeline/pipeline-schedule.c @@ -81,15 +81,7 @@ static enum task_state pipeline_task_cmd(struct pipeline *p, if (err == PPL_STATUS_PATH_STOP) { /* comp_trigger() interrupted trigger propagation or an xrun occurred */ - err = SOF_TASK_STATE_COMPLETED; - } else if (p->trigger.cmd != cmd) { - /* PRE stage completed */ - if (p->trigger.delay) - return SOF_TASK_STATE_RESCHEDULE; - /* No delay: the final stage has already run too */ - err = SOF_TASK_STATE_RESCHEDULE; - } else if (p->status == COMP_STATE_PAUSED) { - if (p->trigger.aborted) { + if (p->trigger.aborted && p->status == COMP_STATE_PAUSED) { p->status = COMP_STATE_ACTIVE; /* * the pipeline aborted a STOP or a PAUSE @@ -99,6 +91,14 @@ static enum task_state pipeline_task_cmd(struct pipeline *p, } else { err = SOF_TASK_STATE_COMPLETED; } + } else if (p->trigger.cmd != cmd) { + /* PRE stage completed */ + if (p->trigger.delay) + return SOF_TASK_STATE_RESCHEDULE; + /* No delay: the final stage has already run too */ + err = SOF_TASK_STATE_RESCHEDULE; + } else if (p->status == COMP_STATE_PAUSED) { + err = SOF_TASK_STATE_COMPLETED; } else { p->status = COMP_STATE_ACTIVE; err = SOF_TASK_STATE_RESCHEDULE;