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
2 changes: 1 addition & 1 deletion src/audio/pipeline/pipeline-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t
p->priority = priority;
p->pipeline_id = pipeline_id;
p->status = COMP_STATE_INIT;
p->trigger.cmd = -EINVAL;
p->trigger.cmd = COMP_TRIGGER_NO_ACTION;
ret = memcpy_s(&p->tctx, sizeof(struct tr_ctx), &pipe_tr,
sizeof(struct tr_ctx));
assert(!ret);
Expand Down
139 changes: 94 additions & 45 deletions src/audio/pipeline/pipeline-schedule.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,69 @@ static void pipeline_schedule_cancel(struct pipeline *p)
/* enable system agent panic, when there are no longer
* DMA driven pipelines
*/
if (!pipeline_is_timer_driven(p))
sa_set_panic_on_delay(true);
sa_set_panic_on_delay(true);
}

static enum task_state pipeline_task_cmd(struct pipeline *p,
struct sof_ipc_reply *reply)
{
int err, cmd = p->trigger.cmd;

if (!p->trigger.host) {
p->trigger.cmd = COMP_TRIGGER_NO_ACTION;
return p->status == COMP_STATE_PAUSED ? SOF_TASK_STATE_COMPLETED :
SOF_TASK_STATE_RESCHEDULE;
}

err = pipeline_trigger_run(p, p->trigger.host, cmd);
if (err < 0) {
pipe_err(p, "pipeline_task_cmd(): failed to trigger components: %d", err);
reply->error = err;
err = SOF_TASK_STATE_COMPLETED;
} else {
switch (cmd) {
case COMP_TRIGGER_START:
case COMP_TRIGGER_RELEASE:
p->status = COMP_STATE_ACTIVE;
break;
case COMP_TRIGGER_PRE_START:
case COMP_TRIGGER_PRE_RELEASE:
p->status = COMP_STATE_PRE_ACTIVE;
break;
case COMP_TRIGGER_STOP:
case COMP_TRIGGER_PAUSE:
p->status = COMP_STATE_PAUSED;
}

if (err == PPL_STATUS_PATH_STOP) {
pipe_warn(p, "pipeline_task_cmd(): stopping for xrun");
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 */
} else if (p->status == COMP_STATE_PAUSED && !p->trigger.aborted) {
err = SOF_TASK_STATE_COMPLETED;
} else {
p->status = COMP_STATE_ACTIVE;
err = SOF_TASK_STATE_RESCHEDULE;
}
}

p->trigger.cmd = COMP_TRIGGER_NO_ACTION;

ipc_msg_reply(reply);

return err;
}

static enum task_state pipeline_task(void *arg)
{
struct sof_ipc_reply reply = {
.hdr.cmd = SOF_IPC_GLB_REPLY,
.hdr.size = sizeof(reply),
};
struct pipeline *p = arg;
int err;

Expand All @@ -55,14 +112,14 @@ static enum task_state pipeline_task(void *arg)
* timed out. No point triggering the pipeline in this case. It will be stopped
* anyway by the host.
*/
if (p->trigger.cmd >= 0) {
if (p->trigger.cmd != COMP_TRIGGER_NO_ACTION) {
struct sof_ipc_reply reply = {
.hdr.cmd = SOF_IPC_GLB_REPLY,
.hdr.size = sizeof(reply),
.error = -EPIPE,
};

p->trigger.cmd = -EINVAL;
p->trigger.cmd = COMP_TRIGGER_NO_ACTION;

ipc_msg_reply(&reply);
}
Expand All @@ -79,38 +136,16 @@ static enum task_state pipeline_task(void *arg)
return SOF_TASK_STATE_RESCHEDULE;
}

if (p->trigger.cmd >= 0) {
/* First pipeline task run for either START or RELEASE: PRE stage */
struct sof_ipc_reply reply = {
.hdr.cmd = SOF_IPC_GLB_REPLY,
.hdr.size = sizeof(reply),
};
int cmd = p->trigger.cmd;

err = pipeline_trigger_run(p, p->trigger.host, cmd);
if (err < 0) {
pipe_err(p, "pipeline_task(): failed to trigger components: %d", err);
reply.error = err;
err = SOF_TASK_STATE_COMPLETED;
} else if (err == PPL_STATUS_PATH_STOP) {
pipe_warn(p, "pipeline_task(): stopping for xrun");
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 */
} else {
p->status = COMP_STATE_ACTIVE;
err = SOF_TASK_STATE_RESCHEDULE;
}

p->trigger.cmd = -EINVAL;
if (p->trigger.cmd != COMP_TRIGGER_NO_ACTION)
/* Process an offloaded command */
return pipeline_task_cmd(p, &reply);

ipc_msg_reply(&reply);

return err;
}
if (p->status == COMP_STATE_PAUSED)
/*
* One of pipelines, being stopped, but not the one, that
* triggers all components
*/
return SOF_TASK_STATE_COMPLETED;

/*
* The first execution of the pipeline task above has triggered all
Expand Down Expand Up @@ -190,23 +225,37 @@ void pipeline_schedule_triggered(struct pipeline_walk_context *ctx,
case COMP_TRIGGER_STOP:
list_for_item(tlist, &ctx->pipelines) {
p = container_of(tlist, struct pipeline, list);
pipeline_schedule_cancel(p);
p->status = COMP_STATE_PAUSED;
if (pipeline_is_timer_driven(p) &&
p->status != COMP_STATE_PAUSED) {
/*
* Paused pipelines have their tasks stopped
* already, use a running pipeline to trigger
* components.
*/
p->trigger.cmd = cmd;
p->trigger.host = ppl_data->start;
ppl_data->start = NULL;
} else {
pipeline_schedule_cancel(p);
p->status = COMP_STATE_PAUSED;
}
}
break;
case COMP_TRIGGER_PRE_RELEASE:
case COMP_TRIGGER_PRE_START:
list_for_item(tlist, &ctx->pipelines) {
p = container_of(tlist, struct pipeline, list);
if (pipeline_is_timer_driven(p)) {
/* Use the first of connected pipelines to trigger */
if (first_pipe) {
p->trigger.cmd = cmd;
p->trigger.host = ppl_data->start;
first_pipe = false;
}
p->xrun_bytes = 0;
if (pipeline_is_timer_driven(p) && first_pipe) {
/*
* Use the first of connected pipelines to
* trigger, mark all other connected pipelines
* active immediately.
*/
p->trigger.cmd = cmd;
p->trigger.host = ppl_data->start;
first_pipe = false;
} else {
p->xrun_bytes = 0;
p->status = COMP_STATE_ACTIVE;
}
pipeline_schedule_copy(p, 0);
Expand Down
Loading