Skip to content
Merged
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
7 changes: 5 additions & 2 deletions src/audio/component.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,20 @@ int comp_set_state(struct comp_dev *dev, int cmd)
}
break;
case COMP_TRIGGER_STOP:
case COMP_TRIGGER_XRUN:
if (dev->state == COMP_STATE_ACTIVE ||
dev->state == COMP_STATE_PAUSED) {
dev->state = COMP_STATE_PREPARE;
} else {
trace_comp_error("comp_set_state() error: "
"wrong state = %u, "
"COMP_TRIGGER_STOP/XRUN", dev->state);
"COMP_TRIGGER_STOP", dev->state);
ret = -EINVAL;
}
break;
case COMP_TRIGGER_XRUN:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@keyonjie does the state transition diagram need updated in the component header ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct, let me update it.

/* reset component status to ready at xrun */
dev->state = COMP_STATE_READY;
break;
case COMP_TRIGGER_PAUSE:
/* only support pausing for running */
if (dev->state == COMP_STATE_ACTIVE) {
Expand Down
62 changes: 58 additions & 4 deletions src/audio/pipeline.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ static void pipeline_comp_trigger_sched_comp(struct pipeline *p,
switch (cmd) {
case COMP_TRIGGER_PAUSE:
case COMP_TRIGGER_STOP:
case COMP_TRIGGER_XRUN:
pipeline_schedule_cancel(p);
p->status = COMP_STATE_PAUSED;
break;
Expand All @@ -453,7 +454,6 @@ static void pipeline_comp_trigger_sched_comp(struct pipeline *p,
break;
case COMP_TRIGGER_SUSPEND:
case COMP_TRIGGER_RESUME:
case COMP_TRIGGER_XRUN:
default:
break;
}
Expand Down Expand Up @@ -530,6 +530,49 @@ static int pipeline_trigger_on_core(struct pipeline *p, struct comp_dev *host,
return ret;
}

/*
Comment thread
keyonjie marked this conversation as resolved.
Resolved
* trigger handler for pipelines in xrun, used for recovery from host only.
* return values:
* 0 -- success, further trigger in caller needed.
* PPL_STATUS_PATH_STOP -- done, no more further trigger needed.
* minus -- failed, caller should return failure.
*/
static int pipeline_xrun_handle_trigger(struct pipeline *p, int cmd)
{
int ret = 0;

/* it is expected in paused status for xrun pipeline */
if (!p->xrun_bytes || p->status != COMP_STATE_PAUSED)
return 0;

/* in xrun, handle start/stop trigger */
switch (cmd) {
case COMP_TRIGGER_START:
/* in xrun, prepare before trigger start needed */
trace_pipe_with_ids(p, "in xrun, prepare it first");
/* prepare the pipeline */
ret = pipeline_prepare(p, p->source_comp);
if (ret < 0) {
trace_pipe_error_with_ids(p, "prepare error: ret = %d",
ret);
return ret;
}
/* now ready for start, clear xrun_bytes */
p->xrun_bytes = 0;
break;
case COMP_TRIGGER_STOP:
/* in xrun, suppose pipeline is already stopped, ignore it */
trace_pipe_with_ids(p, "already stopped in xrun");
/* no more further trigger stop needed */
ret = PPL_STATUS_PATH_STOP;
break;
default:
break;
}

return ret;
}

/* trigger pipeline */
int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd)
{
Expand All @@ -539,6 +582,18 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd)

trace_pipe_with_ids(p, "pipeline_trigger()");

/* handle pipeline global checks before going into each components */
if (p->xrun_bytes) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already checked inside the function

ret = pipeline_xrun_handle_trigger(p, cmd);
if (ret < 0) {
trace_pipe_error_with_ids(p, "xrun handle error: ret = %d",
ret);
return ret;
} else if (ret == PPL_STATUS_PATH_STOP)
/* no further action needed*/
return 0;
}

/* if current core is different than requested */
if (p->ipc_pipe.core != cpu_get_id())
return pipeline_trigger_on_core(p, host, cmd);
Expand Down Expand Up @@ -854,7 +909,7 @@ static uint64_t pipeline_task(void *arg)
/* try to recover */
err = pipeline_xrun_recover(p);
if (err < 0)
goto sched;/* skip copy if still in xrun */
return 0;/* skip copy if still in xrun */
}

err = pipeline_copy(p);
Expand All @@ -863,11 +918,10 @@ static uint64_t pipeline_task(void *arg)
err = pipeline_xrun_recover(p);
if (err < 0) {
trace_pipe_error_with_ids(p, "pipeline_task(): xrun recover failed! pipeline will be stopped!");
goto sched; /* failed - host will stop this pipeline */
return 0; /* failed - host will stop this pipeline */
}
}

sched:
tracev_pipe("pipeline_task() sched");
return p->ipc_pipe.period;
}
52 changes: 28 additions & 24 deletions src/include/sof/audio/component.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,29 +68,33 @@
/**
* States may transform as below:-
* \verbatim
*
* -------------
* pause | | stop/xrun
* +-------------| ACTIVITY |---------------+
* | | | | prepare
* | ------------- | +-----------+
* | ^ ^ | | |
* | | | | | |
* v | | v | |
* ------------- | | ------------- |
* | | release | | start | | |
* | PAUSED |-----------+ +-------------| PREPARE |<-------+
* | | | |
* ------------- -------------
* | ^ ^
* | stop/xrun | |
* +--------------------------------------+ |
* | prepare
* ------------- |
* | | |
* ----------->| READY |------------------+
* reset | |
* -------------
* +---------------------------------------+
* | |
* ------------- |
* pause | | stop |
* +-------------| ACTIVITY |---------------+ |
* | | | | prepare |
* | ------------- | +---------+ |
* | ^ ^ | | | |
* | | | | | | |
* v | | v | | |
* ------------- | | ------------- | |
* | | release | | start | | | |
* | PAUSED |-----------+ +-------------| PREPARE |<-----+ |
* | | | | |
* ------------- ------------- |
* | ^ ^ |
* | stop | | |
* +--------------------------------------+ | |
* | prepare |
* ------------- | |
* | | | |
* ----------->| READY |------------------+ |
* reset | | |
* ------------- |
* ^ |
* | xrun |
* +---------------------------------------+
*
* \endverbatim
*/
Expand Down Expand Up @@ -662,12 +666,12 @@ static inline int comp_get_requested_state(int cmd)
break;
case COMP_TRIGGER_PREPARE:
case COMP_TRIGGER_STOP:
case COMP_TRIGGER_XRUN:
state = COMP_STATE_PREPARE;
break;
case COMP_TRIGGER_PAUSE:
state = COMP_STATE_PAUSED;
break;
case COMP_TRIGGER_XRUN:
case COMP_TRIGGER_RESET:
state = COMP_STATE_READY;
break;
Expand Down
22 changes: 9 additions & 13 deletions test/cmocka/src/audio/component/comp_set_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ struct test_case test_cases[] = {
COMP_TRIGGER_STOP, NULL_STATE),
TEST_CASE(SUCCEED, COMP_STATE_PAUSED,
COMP_TRIGGER_STOP, NULL_STATE),
TEST_CASE(SUCCEED, COMP_STATE_ACTIVE,
COMP_TRIGGER_XRUN, NULL_STATE),
TEST_CASE(SUCCEED, COMP_STATE_PAUSED,
COMP_TRIGGER_XRUN, NULL_STATE),
TEST_CASE(SUCCEED, COMP_STATE_ACTIVE,
COMP_TRIGGER_PAUSE, NULL_STATE),
TEST_CASE(SUCCEED, COMP_STATE_INIT,
Expand Down Expand Up @@ -120,12 +116,6 @@ struct test_case test_cases[] = {
NULL_STATE),
TEST_CASE(FAIL, COMP_STATE_SUSPEND, COMP_TRIGGER_STOP,
NULL_STATE),
TEST_CASE(FAIL, COMP_STATE_INIT, COMP_TRIGGER_XRUN,
NULL_STATE),
TEST_CASE(FAIL, COMP_STATE_READY, COMP_TRIGGER_XRUN,
NULL_STATE),
TEST_CASE(FAIL, COMP_STATE_SUSPEND, COMP_TRIGGER_XRUN,
NULL_STATE),
TEST_CASE(FAIL, COMP_STATE_INIT, COMP_TRIGGER_PAUSE,
NULL_STATE),
TEST_CASE(FAIL, COMP_STATE_READY, COMP_TRIGGER_PAUSE,
Expand All @@ -152,10 +142,16 @@ struct test_case test_cases[] = {
COMP_TRIGGER_STOP, COMP_STATE_PREPARE),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PAUSED,
COMP_TRIGGER_STOP, COMP_STATE_PREPARE),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_ACTIVE,
COMP_TRIGGER_XRUN, COMP_STATE_PREPARE),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_INIT,
COMP_TRIGGER_XRUN, COMP_STATE_READY),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_SUSPEND,
COMP_TRIGGER_XRUN, COMP_STATE_READY),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PREPARE,
COMP_TRIGGER_XRUN, COMP_STATE_READY),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PAUSED,
COMP_TRIGGER_XRUN, COMP_STATE_PREPARE),
COMP_TRIGGER_XRUN, COMP_STATE_READY),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_ACTIVE,
COMP_TRIGGER_XRUN, COMP_STATE_READY),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_ACTIVE,
COMP_TRIGGER_PAUSE, COMP_STATE_PAUSED),
TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_INIT,
Expand Down