component: add task when scheduled on different core

Adds separate task to components, which are supposed to be scheduled
on different core than the rest of the pipeline. These are so called
shared components. This way components requiring huge processing power
can be offloaded to slave cores.

Signed-off-by: Tomasz Lauda <tomasz.lauda@linux.intel.com>
This commit is contained in:
Tomasz Lauda 2020-02-04 10:45:14 +01:00 committed by Liam Girdwood
parent ec15c0ac38
commit de0a0b85c5
4 changed files with 72 additions and 5 deletions

View File

@ -143,6 +143,8 @@ static int pipeline_comp_complete(struct comp_dev *current,
/* complete component init */
current->pipeline = ppl_data->p;
current->period = ppl_data->p->ipc_pipe.period;
current->priority = ppl_data->p->ipc_pipe.priority;
pipeline_for_each_comp(current, &pipeline_comp_complete, data,
NULL, NULL, dir);

View File

@ -20,6 +20,7 @@
#include <sof/lib/shim.h>
#include <sof/platform.h>
#include <sof/schedule/edf_schedule.h>
#include <sof/schedule/ll_schedule.h>
#include <sof/schedule/schedule.h>
#include <sof/schedule/task.h>
#include <ipc/control.h>
@ -245,6 +246,14 @@ static int idc_params(uint32_t comp_id)
return ret;
}
static enum task_state comp_task(void *data)
{
if (comp_copy(data) < 0)
return SOF_TASK_STATE_COMPLETED;
return SOF_TASK_STATE_RESCHEDULE;
}
/**
* \brief Executes IDC component prepare message.
* \param[in] comp_id Component id to be prepared.
@ -254,14 +263,38 @@ static int idc_prepare(uint32_t comp_id)
{
struct ipc *ipc = ipc_get();
struct ipc_comp_dev *ipc_dev;
struct comp_dev *dev;
int ret;
ipc_dev = ipc_get_comp_by_id(ipc, comp_id);
if (!ipc_dev)
return -ENODEV;
dev = ipc_dev->cd;
/* we're running on different core, so allocate our own task */
if (!dev->task) {
/* allocate task for shared component */
dev->task = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
sizeof(*dev->task));
if (!dev->task) {
ret = -ENOMEM;
goto out;
}
ret = schedule_task_init_ll(dev->task, SOF_SCHEDULE_LL_TIMER,
dev->priority, comp_task, dev,
dev->comp.core, 0);
if (ret < 0) {
rfree(dev->task);
goto out;
}
}
ret = comp_prepare(ipc_dev->cd);
out:
platform_shared_commit(dev, sizeof(*dev));
platform_shared_commit(ipc_dev, sizeof(*ipc_dev));
platform_shared_commit(ipc, sizeof(*ipc));
@ -287,8 +320,25 @@ static int idc_trigger(uint32_t comp_id)
return -ENODEV;
ret = comp_trigger(ipc_dev->cd, cmd);
if (ret < 0)
goto out;
/* schedule or cancel task */
switch (cmd) {
case COMP_TRIGGER_START:
case COMP_TRIGGER_RELEASE:
schedule_task(ipc_dev->cd->task, 0, ipc_dev->cd->period);
break;
case COMP_TRIGGER_XRUN:
case COMP_TRIGGER_PAUSE:
case COMP_TRIGGER_STOP:
schedule_task_cancel(ipc_dev->cd->task);
break;
}
out:
platform_shared_commit(payload, sizeof(*payload));
platform_shared_commit(ipc_dev->cd, sizeof(*ipc_dev->cd));
platform_shared_commit(ipc_dev, sizeof(*ipc_dev));
platform_shared_commit(ipc, sizeof(*ipc));

View File

@ -21,9 +21,11 @@
#include <sof/audio/pipeline.h>
#include <sof/debug/panic.h>
#include <sof/list.h>
#include <sof/lib/alloc.h>
#include <sof/lib/dai.h>
#include <sof/lib/memory.h>
#include <sof/math/numbers.h>
#include <sof/schedule/schedule.h>
#include <sof/sof.h>
#include <sof/trace/trace.h>
#include <ipc/control.h>
@ -299,7 +301,13 @@ struct comp_dev {
* to run component's processing
*/
struct task *task; /**< component's processing task used only
* for components running on different core
* than the rest of the pipeline
*/
uint32_t size; /**< component's allocated size */
uint32_t period; /**< component's processing period */
uint32_t priority; /**< component's processing priority */
bool is_shared; /**< indicates whether component is shared
* across cores
*/
@ -480,6 +488,12 @@ static inline void comp_free(struct comp_dev *dev)
{
assert(dev->drv->ops.free);
/* free task if shared component */
if (dev->is_shared && dev->task) {
schedule_task_free(dev->task);
rfree(dev->task);
}
dev->drv->ops.free(dev);
}
@ -795,15 +809,11 @@ static inline int comp_get_endpoint_type(struct comp_dev *dev)
static inline void component_set_period_frames(struct comp_dev *current,
uint32_t rate)
{
int period;
period = current->pipeline->ipc_pipe.period;
/* Samplerate is in Hz and period in microseconds.
* As we don't have floats use scale divider 1000000.
* Also integer round up the result.
*/
current->frames = ceil_divide(rate * period, 1000000);
current->frames = ceil_divide(rate * current->period, 1000000);
}
/** @}*/

View File

@ -36,3 +36,8 @@ struct sof *sof_get(void)
{
return &sof;
}
struct schedulers **arch_schedulers_get(void)
{
return NULL;
}