mirror of https://github.com/thesofproject/sof.git
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:
parent
ec15c0ac38
commit
de0a0b85c5
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
|
|
|
@ -36,3 +36,8 @@ struct sof *sof_get(void)
|
|||
{
|
||||
return &sof;
|
||||
}
|
||||
|
||||
struct schedulers **arch_schedulers_get(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue