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
1 change: 0 additions & 1 deletion src/audio/pipeline/pipeline-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ 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;
ret = memcpy_s(&p->tctx, sizeof(struct tr_ctx), &pipe_tr,
sizeof(struct tr_ctx));
assert(!ret);
Expand Down
74 changes: 17 additions & 57 deletions src/audio/pipeline/pipeline-schedule.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,44 +55,12 @@ static enum task_state pipeline_task(void *arg)
return SOF_TASK_STATE_COMPLETED;
}

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

err = pipeline_trigger_run(p, p->trigger.host, p->trigger.cmd);
p->trigger.cmd = -EINVAL;

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 {
p->status = COMP_STATE_ACTIVE;
err = SOF_TASK_STATE_RESCHEDULE;
}

ipc_msg_reply(&reply);

return err;
}

/*
* The first execution of the pipeline task above has triggered all
* pipeline components. Subsequent iterations actually perform data
* copying below.
*/
err = pipeline_copy(p);
if (err < 0) {
/* try to recover */
err = pipeline_xrun_recover(p);
if (err < 0) {
pipe_err(p, "pipeline_task(): xrun recovery failed! pipeline is stopped.");
pipe_err(p, "pipeline_task(): xrun recover failed! pipeline will be stopped!");
/* failed - host will stop this pipeline */
return SOF_TASK_STATE_COMPLETED;
}
Expand Down Expand Up @@ -139,11 +107,9 @@ int pipeline_schedule_config(struct pipeline *p, uint32_t sched_id,
return 0;
}

/* trigger connected pipelines: either immediately or schedule them */
void pipeline_schedule_triggered(struct pipeline_walk_context *ctx,
int cmd)
{
struct pipeline_data *ppl_data = ctx->comp_data;
struct list_item *tlist;
struct pipeline *p;
uint32_t flags;
Expand All @@ -155,31 +121,25 @@ void pipeline_schedule_triggered(struct pipeline_walk_context *ctx,
*/
irq_local_disable(flags);

switch (cmd) {
case COMP_TRIGGER_PAUSE:
case COMP_TRIGGER_STOP:
list_for_item(tlist, &ctx->pipelines) {
p = container_of(tlist, struct pipeline, list);
list_for_item(tlist, &ctx->pipelines) {
p = container_of(tlist, struct pipeline, list);

switch (cmd) {
case COMP_TRIGGER_PAUSE:
case COMP_TRIGGER_STOP:
pipeline_schedule_cancel(p);
p->status = COMP_STATE_PAUSED;
}
break;
case COMP_TRIGGER_RELEASE:
case COMP_TRIGGER_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 (cmd >= 0) {
p->trigger.cmd = cmd;
p->trigger.host = ppl_data->start;
cmd = -EINVAL;
}
} else {
p->xrun_bytes = 0;
p->status = COMP_STATE_ACTIVE;
}
break;
case COMP_TRIGGER_RELEASE:
case COMP_TRIGGER_START:
pipeline_schedule_copy(p, 0);
p->xrun_bytes = 0;
p->status = COMP_STATE_ACTIVE;
break;
case COMP_TRIGGER_SUSPEND:
case COMP_TRIGGER_RESUME:
default:
break;
}
}

Expand Down
134 changes: 15 additions & 119 deletions src/audio/pipeline/pipeline-stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,40 +59,21 @@ pipeline_should_report_enodata_on_trigger(struct comp_dev *rsrc,
return false;
}

/* Runs in IPC or in pipeline task context */
static int pipeline_comp_trigger(struct comp_dev *current,
struct comp_buffer *calling_buf,
struct pipeline_walk_context *ctx, int dir)
{
struct pipeline_data *ppl_data = ctx->comp_data;
bool is_single_ppl = comp_is_single_pipeline(current, ppl_data->start);
bool is_same_sched, async;
bool is_same_sched =
pipeline_is_same_sched_comp(current->pipeline,
ppl_data->start->pipeline);
int err;

pipe_dbg(current->pipeline,
"pipeline_comp_trigger(), current->comp.id = %u, dir = %u",
dev_comp_id(current), dir);

switch (ppl_data->cmd) {
case COMP_TRIGGER_PAUSE:
case COMP_TRIGGER_STOP:
/*
* PAUSE and STOP are triggered in IPC context, not from the
* pipeline task
*/
async = true;
break;
case COMP_TRIGGER_RELEASE:
case COMP_TRIGGER_START:
async = !pipeline_is_timer_driven(current->pipeline);
break;
default:
return -EINVAL;
}

is_same_sched = pipeline_is_same_sched_comp(current->pipeline,
ppl_data->start->pipeline);

/* trigger should propagate to the connected pipelines,
* which need to be scheduled together
*/
Expand All @@ -111,12 +92,7 @@ static int pipeline_comp_trigger(struct comp_dev *current,
if (err < 0 || err == PPL_STATUS_PATH_STOP)
return err;

/*
* Add scheduling components to the list. This is only needed for the
* stopping flow.
*/
if (async)
pipeline_comp_trigger_sched_comp(current->pipeline, current, ctx);
pipeline_comp_trigger_sched_comp(current->pipeline, current, ctx);

return pipeline_for_each_comp(current, ctx, dir);
}
Expand Down Expand Up @@ -196,95 +172,18 @@ int pipeline_copy(struct pipeline *p)
return ret;
}

/* only collect scheduling components */
static int pipeline_comp_list(struct comp_dev *current,
struct comp_buffer *calling_buf,
struct pipeline_walk_context *ctx, int dir)
{
struct pipeline_data *ppl_data = ctx->comp_data;
bool is_single_ppl = comp_is_single_pipeline(current, ppl_data->start);
bool is_same_sched = pipeline_is_same_sched_comp(current->pipeline,
ppl_data->start->pipeline);

if (!is_single_ppl && !is_same_sched) {
pipe_dbg(current->pipeline,
"pipeline_comp_list(), current is from another pipeline");
return 0;
}

/* Add scheduling components to the list */
pipeline_comp_trigger_sched_comp(current->pipeline, current, ctx);

return pipeline_for_each_comp(current, ctx, dir);
}

/* build a list of connected pipelines' scheduling components and trigger them */
static int pipeline_trigger_list(struct pipeline *p, struct comp_dev *host, int cmd)
{
struct pipeline_data data = {
.start = host,
.cmd = cmd,
};
struct pipeline_walk_context walk_ctx = {
.comp_func = pipeline_comp_list,
.comp_data = &data,
.skip_incomplete = true,
};
int ret;

list_init(&walk_ctx.pipelines);

ret = walk_ctx.comp_func(host, NULL, &walk_ctx, host->direction);
if (ret < 0)
pipe_err(p, "pipeline_trigger_list(): ret = %d, host->comp.id = %u, cmd = %d",
ret, dev_comp_id(host), cmd);
else
pipeline_schedule_triggered(&walk_ctx, cmd);

return ret;
}

/* trigger pipeline in IPC context */
/* trigger pipeline */
int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd)
{
int ret;

pipe_info(p, "pipe trigger cmd %d", cmd);

switch (cmd) {
case COMP_TRIGGER_PAUSE:
case COMP_TRIGGER_STOP:
/* Execute immediately */
ret = pipeline_trigger_run(p, host, cmd);
return ret == PPL_STATUS_PATH_STOP ? 0 : ret;
case COMP_TRIGGER_RELEASE:
case COMP_TRIGGER_START:
/* Add all connected pipelines to the list and schedule them all */
ret = pipeline_trigger_list(p, host, cmd);
if (ret < 0)
return ret;
/* IPC response will be sent from the task */
return 1;
}

return 0;
}

/* actually execute pipeline trigger, including components: either in IPC or in task context */
int pipeline_trigger_run(struct pipeline *p, struct comp_dev *host, int cmd)
{
struct pipeline_data data = {
.start = host,
.cmd = cmd,
};
struct pipeline_data data;
struct pipeline_walk_context walk_ctx = {
.comp_func = pipeline_comp_trigger,
.comp_data = &data,
.skip_incomplete = true,
};
int ret;

pipe_dbg(p, "execute trigger cmd %d on pipe %u", cmd, p->pipeline_id);
pipe_info(p, "pipe trigger cmd %d", cmd);

list_init(&walk_ctx.pipelines);

Expand All @@ -294,23 +193,20 @@ int pipeline_trigger_run(struct pipeline *p, struct comp_dev *host, int cmd)
if (ret < 0) {
pipe_err(p, "xrun handle: ret = %d", ret);
return ret;
}

if (ret == PPL_STATUS_PATH_STOP)
} else if (ret == PPL_STATUS_PATH_STOP)
/* no further action needed*/
return pipeline_is_timer_driven(p);
return 0;
}

data.start = host;
data.cmd = cmd;

ret = walk_ctx.comp_func(host, NULL, &walk_ctx, host->direction);
if (ret < 0)
pipe_err(p, "pipeline_trigger_run(): ret = %d, host->comp.id = %u, cmd = %d",
if (ret < 0) {
pipe_err(p, "pipeline_trigger(): ret = %d, host->comp.id = %u, cmd = %d",
ret, dev_comp_id(host), cmd);
}

/*
* When called from the pipeline task, pipeline_comp_trigger() will not
* add pipelines to the list, so pipeline_schedule_triggered() will have
* no effect.
*/
pipeline_schedule_triggered(&walk_ctx, cmd);

return ret;
Expand Down
2 changes: 1 addition & 1 deletion src/audio/pipeline/pipeline-xrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void pipeline_xrun(struct pipeline *p, struct comp_dev *dev,
return;

/* notify all pipeline comps we are in XRUN, and stop copying */
ret = pipeline_trigger_run(p, p->source_comp, COMP_TRIGGER_XRUN);
ret = pipeline_trigger(p, p->source_comp, COMP_TRIGGER_XRUN);
if (ret < 0)
pipe_err(p, "pipeline_xrun(): Pipelines notification about XRUN failed, ret = %d",
ret);
Expand Down
7 changes: 1 addition & 6 deletions src/drivers/intel/cavs/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,10 @@ enum task_state ipc_platform_do_cmd(void *data)
void ipc_platform_complete_cmd(void *data)
{
struct ipc *ipc = data;
uint32_t flags;

if (!cpu_is_me(ipc->core) || ipc->delayed_response)
if (!cpu_is_me(ipc->core))
return;

spin_lock_irq(&ipc->lock, flags);

/* write 1 to clear busy, and trigger interrupt to host*/
#if CAVS_VERSION == CAVS_VERSION_1_5
ipc_write(IPC_DIPCT, ipc_read(IPC_DIPCT) | IPC_DIPCT_BUSY);
Expand All @@ -232,8 +229,6 @@ void ipc_platform_complete_cmd(void *data)
}

#endif

spin_unlock_irq(&ipc->lock, flags);
}

int ipc_platform_send_msg(struct ipc_msg *msg)
Expand Down
20 changes: 4 additions & 16 deletions src/include/sof/audio/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,6 @@ struct pipeline {
/* position update */
uint32_t posn_offset; /* position update array offset*/
struct ipc_msg *msg;
struct {
int cmd;
struct comp_dev *host;
} trigger;
};

struct pipeline_walk_context {
Expand Down Expand Up @@ -222,22 +218,14 @@ int pipeline_prepare(struct pipeline *p, struct comp_dev *cd);
*/

/**
* \brief Trigger pipeline - IPC context
* \brief Trigger pipeline - atomic
* \param[in] p pipeline.
* \param[in] host Host DMA component.
* \param[in] host_cd Host DMA component.
* \param[in] cmd Pipeline trigger command.
* \return 0 on success.
*/
int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd);

/**
* \brief Trigger pipeline - either IPC or pipeline task context
* \param[in] p pipeline.
* \param[in] host Host DMA component.
* \param[in] cmd Pipeline trigger command.
* \return 0 on success.
*/
int pipeline_trigger_run(struct pipeline *p, struct comp_dev *host, int cmd);
/* */
int pipeline_trigger(struct pipeline *p, struct comp_dev *host_cd, int cmd);

/**
* \brief Copy data along a pipeline.
Expand Down
7 changes: 0 additions & 7 deletions src/include/sof/ipc/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ struct ipc {

struct list_item msg_list; /* queue of messages to be sent */
bool is_notification_pending; /* notification is being sent to host */
bool delayed_response; /* response will be sent from a different context */
unsigned int core; /* core, processing the IPC */

struct list_item comp_list; /* list of component devices */
Expand Down Expand Up @@ -197,10 +196,4 @@ void ipc_cmd(ipc_cmd_hdr *hdr);
*/
int ipc_process_on_core(uint32_t core, bool blocking);

/**
* \brief reply to an IPC message.
* @param[in] reply pointer to the reply structure.
*/
void ipc_msg_reply(struct sof_ipc_reply *reply);

#endif /* __SOF_DRIVERS_IPC_H__ */
Loading