diff --git a/src/audio/host.c b/src/audio/host.c index a620c8697686..53fdf47b64ab 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -399,7 +399,7 @@ static int host_copy_normal(struct comp_dev *dev) struct host_data *hd = comp_get_drvdata(dev); uint32_t copy_bytes = 0; uint32_t flags = 0; - int ret = 0; + int ret; comp_dbg(dev, "host_copy_normal()"); @@ -408,13 +408,11 @@ static int host_copy_normal(struct comp_dev *dev) copy_bytes = host_get_copy_bytes_normal(dev); if (!copy_bytes) - return ret; + return 0; ret = dma_copy(hd->chan, copy_bytes, flags); - if (ret < 0) { + if (ret < 0) comp_err(dev, "host_copy_normal(): dma_copy() failed, ret = %u", ret); - return ret; - } return ret; } diff --git a/src/audio/pipeline/pipeline-schedule.c b/src/audio/pipeline/pipeline-schedule.c index d374effc736e..60c0ea753f14 100644 --- a/src/audio/pipeline/pipeline-schedule.c +++ b/src/audio/pipeline/pipeline-schedule.c @@ -192,6 +192,17 @@ void pipeline_schedule_triggered(struct pipeline_walk_context *ctx, } pipeline_schedule_copy(p, 0); } + break; + case COMP_TRIGGER_XRUN: + list_for_item(tlist, &ctx->pipelines) { + p = container_of(tlist, struct pipeline, list); + if (!p->xrun_bytes) + /* + * the exact number of xrun bytes is unused, + * just make it non-0 + */ + p->xrun_bytes = 1; + } } irq_local_enable(flags); diff --git a/src/audio/pipeline/pipeline-stream.c b/src/audio/pipeline/pipeline-stream.c index 18081bd7a26c..974fb0578a19 100644 --- a/src/audio/pipeline/pipeline-stream.c +++ b/src/audio/pipeline/pipeline-stream.c @@ -255,6 +255,53 @@ static int pipeline_trigger_list(struct pipeline *p, struct comp_dev *host, int return ret; } +static void pipeline_trigger_xrun(struct pipeline *p, struct comp_dev **host) +{ + /* + * XRUN can happen on a pipeline, not directly attached to the host, + * find the original one + */ + do { + /* Check the opposite direction */ + int dir = (*host)->direction == PPL_DIR_DOWNSTREAM ? PPL_DIR_UPSTREAM : + PPL_DIR_DOWNSTREAM; + struct list_item *buffer_list = comp_buffer_list(*host, dir); + struct list_item *clist; + bool found = false; + + if (list_is_empty(buffer_list)) + /* Reached the original host */ + break; + + list_for_item(clist, buffer_list) { + struct comp_buffer *buffer = buffer_from_list(clist, + struct comp_buffer, dir); + struct comp_dev *buffer_comp = buffer_get_comp(buffer, dir); + + switch (buffer_comp->pipeline->status) { + case COMP_STATE_ACTIVE: + case COMP_STATE_PREPARE: + found = true; + break; + } + + if (found) { + *host = (*host)->direction == PPL_DIR_DOWNSTREAM ? + buffer_comp->pipeline->source_comp : + buffer_comp->pipeline->sink_comp; + break; + } + } + + if (!found) { + /* No active pipeline found! Should never occur. */ + pipe_err(p, "No active pipeline found to link to pipeline %u!", + (*host)->pipeline->pipeline_id); + break; + } + } while (true); +} + /* trigger pipeline in IPC context */ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) { @@ -268,9 +315,12 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) /* Execute immediately */ ret = pipeline_trigger_run(p, host, cmd); return ret == PPL_STATUS_PATH_STOP ? 0 : ret; + case COMP_TRIGGER_XRUN: + pipeline_trigger_xrun(p, &host); + COMPILER_FALLTHROUGH; case COMP_TRIGGER_PRE_RELEASE: case COMP_TRIGGER_PRE_START: - /* Add all connected pipelines to the list and schedule them all */ + /* Add all connected pipelines to the list and trigger them all */ ret = pipeline_trigger_list(p, host, cmd); if (ret < 0) return ret; diff --git a/src/audio/pipeline/pipeline-xrun.c b/src/audio/pipeline/pipeline-xrun.c index 04b85f3abfab..1f22fbb93b51 100644 --- a/src/audio/pipeline/pipeline-xrun.c +++ b/src/audio/pipeline/pipeline-xrun.c @@ -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); diff --git a/src/include/sof/audio/component_ext.h b/src/include/sof/audio/component_ext.h index 5c646908afb9..f63b72a8cd07 100644 --- a/src/include/sof/audio/component_ext.h +++ b/src/include/sof/audio/component_ext.h @@ -35,8 +35,8 @@ struct comp_driver_list { /** \brief Retrieves the component device buffer list. */ #define comp_buffer_list(comp, dir) \ - ((dir) == PPL_DIR_DOWNSTREAM ? &comp->bsink_list : \ - &comp->bsource_list) + ((dir) == PPL_DIR_DOWNSTREAM ? &(comp)->bsink_list : \ + &(comp)->bsource_list) /** See comp_ops::new */ struct comp_dev *comp_new(struct sof_ipc_comp *comp); diff --git a/zephyr/edf_schedule.c b/zephyr/edf_schedule.c index 519efba0121e..4abecc1dd3f6 100644 --- a/zephyr/edf_schedule.c +++ b/zephyr/edf_schedule.c @@ -41,8 +41,8 @@ static int schedule_edf_task(void *data, struct task *task, uint64_t start, k_timeout_t start_time = K_USEC(start + EDF_SCHEDULE_DELAY); k_work_reschedule_for_queue(&edf_workq, - &task->z_delayed_work, - start_time); + &task->z_delayed_work, + start_time); task->state = SOF_TASK_STATE_QUEUED; return 0;