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
7 changes: 7 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ config INTERRUPT_LEVEL_5

rsource "src/Kconfig"

config IDC_TASK_BUDGET
int "Cycles budget for IDC task"
depends on SMP
default 8000
help
Cycles budget for IDC task per systick (see config SYSTICK).

choice
prompt "Optimization"
default OPTIMIZE_FOR_PERFORMANCE
Expand Down
7 changes: 7 additions & 0 deletions src/drivers/intel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ config INTEL_DMIC
Select this to enable Intel DMIC driver. The DMIC driver provides
as DAI the SoC direct attach digital microphones interface.

config INTEL_CAVS_IPC_TASK_BUDGET
int "Intel cycles budget for IPC task"
depends on CAVS
default 8000
help
Cycles budget for IPC task per systick (see config SYSTICK).

if INTEL_DMIC

choice
Expand Down
6 changes: 4 additions & 2 deletions src/drivers/intel/cavs/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,10 @@ int platform_ipc_init(struct ipc *ipc)
ipc_set_drvdata(ipc, NULL);

/* schedule */
schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_uuid),
&ipc_task_ops, ipc, 0, 0);
schedule_task_init_edf_with_budget(&ipc->ipc_task,
SOF_UUID(ipc_task_uuid),
&ipc_task_ops, ipc, 0, 0,
CONFIG_INTEL_CAVS_IPC_TASK_BUDGET);

/* configure interrupt */
irq = interrupt_get_irq(PLATFORM_IPC_INTERRUPT,
Expand Down
6 changes: 4 additions & 2 deletions src/idc/idc.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,10 @@ int idc_init(void)
(*idc)->payload = cache_to_uncache((struct idc_payload *)payload);

/* process task */
schedule_task_init_edf(&(*idc)->idc_task, SOF_UUID(idc_cmd_task_uuid),
&ops, *idc, cpu_get_id(), 0);
schedule_task_init_edf_with_budget(&(*idc)->idc_task,
SOF_UUID(idc_cmd_task_uuid),
&ops, *idc, cpu_get_id(), 0,
CONFIG_IDC_TASK_BUDGET);

return platform_idc_init();
}
3 changes: 2 additions & 1 deletion src/include/sof/drivers/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define __SOF_DRIVERS_TIMER_H__

#include <arch/drivers/timer.h>
#include <sof/lib/cpu.h>
#include <sof/sof.h>
#include <stdint.h>

Expand All @@ -33,7 +34,7 @@ static inline struct timer *timer_get(void)

static inline struct timer *cpu_timer_get(void)
{
return sof_get()->cpu_timer;
return &(sof_get()->cpu_timers[cpu_get_id()]);
}

static inline int64_t timer_set(struct timer *timer, uint64_t ticks)
Expand Down
10 changes: 10 additions & 0 deletions src/include/sof/schedule/edf_schedule.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <sof/trace/trace.h>
#include <user/trace.h>
#include <stdint.h>
#include <stdbool.h>

#define edf_sch_set_pdata(task, data) \
(task->priv_data = data)
Expand All @@ -20,6 +21,10 @@

struct edf_task_pdata {
void *ctx;
uint32_t budget; /**< cycles per systick */
uint64_t last_systick; /**< last systick in which budget
* was granted to task
*/
};

int scheduler_init_edf(void);
Expand All @@ -28,4 +33,9 @@ int schedule_task_init_edf(struct task *task, uint32_t uid,
const struct task_ops *ops,
void *data, uint16_t core, uint32_t flags);

int schedule_task_init_edf_with_budget(struct task *task, uint32_t uid,
Comment thread
lgirdwood marked this conversation as resolved.
const struct task_ops *ops,
void *data, uint16_t core,
uint32_t flags, uint32_t cycles_budget);

#endif /* __SOF_SCHEDULE_EDF_SCHEDULE_H__ */
4 changes: 2 additions & 2 deletions src/include/sof/sof.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ struct sof {
/* default platform timer */
struct timer *platform_timer;

/* cpu (arch) timer */
struct timer *cpu_timer;
/* cpu (arch) timers - 1 per core */
struct timer *cpu_timers;

/* timer domain for driving timer LL scheduler */
struct ll_schedule_domain *platform_timer_domain;
Expand Down
2 changes: 1 addition & 1 deletion src/platform/baytrail/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ int platform_init(struct sof *sof)
int ret;

sof->platform_timer = &timer;
sof->cpu_timer = &timer;
sof->cpu_timers = &timer;

/* clear mailbox for early trace and debug */
trace_point(TRACE_BOOT_PLATFORM_MBOX);
Expand Down
2 changes: 1 addition & 1 deletion src/platform/haswell/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ int platform_init(struct sof *sof)
int ret;

sof->platform_timer = &timer;
sof->cpu_timer = &timer;
sof->cpu_timers = &timer;

/* clear mailbox for early trace and debug */
trace_point(TRACE_BOOT_PLATFORM_MBOX);
Expand Down
2 changes: 1 addition & 1 deletion src/platform/imx8/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ int platform_init(struct sof *sof)
int ret;

sof->platform_timer = &timer;
sof->cpu_timer = &timer;
sof->cpu_timers = &timer;

platform_interrupt_init();
platform_clock_init(sof);
Expand Down
2 changes: 1 addition & 1 deletion src/platform/imx8m/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ int platform_init(struct sof *sof)
int ret;

sof->platform_timer = &timer;
sof->cpu_timer = &timer;
sof->cpu_timers = &timer;

platform_interrupt_init();
platform_clock_init(sof);
Expand Down
13 changes: 8 additions & 5 deletions src/platform/intel/cavs/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,7 @@ SHARED_DATA struct timer timer = {
.irq_name = irq_name_level2,
};

SHARED_DATA struct timer arch_timer = {
.id = TIMER1, /* internal timer */
.irq = IRQ_NUM_TIMER2,
};
SHARED_DATA struct timer arch_timers[PLATFORM_CORE_COUNT];

#if CONFIG_DW_SPI

Expand Down Expand Up @@ -363,7 +360,13 @@ int platform_init(struct sof *sof)
int i;

sof->platform_timer = cache_to_uncache(&timer);
sof->cpu_timer = cache_to_uncache(&arch_timer);
sof->cpu_timers = (struct timer *)cache_to_uncache(&arch_timers);

for (i = 0; i < PLATFORM_CORE_COUNT; i++)
sof->cpu_timers[i] = (struct timer) {
.id = TIMER1, /* internal timer */
.irq = IRQ_NUM_TIMER2,
};

/* Turn off memory for all unused cores */
for (i = 0; i < PLATFORM_CORE_COUNT; i++)
Expand Down
56 changes: 55 additions & 1 deletion src/schedule/edf_schedule.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,26 @@ static void schedule_edf_task_run(struct task *task, void *data)
}
}

static inline uint64_t edf_eval_task_deadline(struct task *task,
uint64_t systick)
{
struct edf_task_pdata *edf_pdata = edf_sch_get_pdata(task);

if (!edf_pdata->budget)
return task_get_deadline(task);

/* check if task was already executed in current systick */
if (edf_pdata->last_systick != systick) {
Comment thread
lgirdwood marked this conversation as resolved.
edf_pdata->last_systick = systick;
return task_get_deadline(task);
}

/* when there are no other tasks to run,
* task can be executed even if it used systick's budget,
*/
return SOF_TASK_DEADLINE_ALMOST_IDLE;
}

static void edf_scheduler_run(void *data)
{
struct edf_schedule_data *edf_sch = data;
Expand All @@ -64,9 +84,20 @@ static void edf_scheduler_run(void *data)
struct task *task;
uint64_t deadline;
uint32_t flags;
uint64_t systick;

tr_dbg(&edf_tr, "edf_scheduler_run()");

timer_disable(cpu_timer_get(), edf_sch, cpu_get_id());

/* budget is given per systick, for example if systick is configured
* as 1ms and budget is 8000 cycles, then task will be able to use
* up to 8MCPS (or more if there are no other tasks)
*/
systick = platform_timer_get(timer_get()) /
Comment thread
lgirdwood marked this conversation as resolved.
(clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1)
* (CONFIG_SYSTICK_PERIOD / 1000));

irq_local_disable(flags);

/* find next task to run */
Expand All @@ -77,7 +108,7 @@ static void edf_scheduler_run(void *data)
task->state != SOF_TASK_STATE_RUNNING)
continue;

deadline = task_get_deadline(task);
deadline = edf_eval_task_deadline(task, systick);

if (deadline == SOF_TASK_DEADLINE_NOW) {
/* task needs to be scheduled ASAP */
Expand Down Expand Up @@ -143,6 +174,15 @@ static int schedule_edf_task(void *data, struct task *task, uint64_t start,
int schedule_task_init_edf(struct task *task, uint32_t uid,
const struct task_ops *ops,
void *data, uint16_t core, uint32_t flags)
{
return schedule_task_init_edf_with_budget(task, uid, ops, data,
core, flags, 0);
}

int schedule_task_init_edf_with_budget(struct task *task, uint32_t uid,
const struct task_ops *ops,
void *data, uint16_t core,
uint32_t flags, uint32_t cycles_budget)
{
struct edf_task_pdata *edf_pdata = NULL;
int ret = 0;
Expand Down Expand Up @@ -174,6 +214,8 @@ int schedule_task_init_edf(struct task *task, uint32_t uid,
task->core, NULL, 0) < 0)
goto error;

edf_pdata->budget = cycles_budget;

/* flush for slave core */
if (cpu_is_slave(task->core))
dcache_writeback_invalidate_region(edf_pdata,
Expand All @@ -191,6 +233,7 @@ int schedule_task_init_edf(struct task *task, uint32_t uid,

static int schedule_edf_task_running(void *data, struct task *task)
{
struct edf_schedule_data *edf_sch = data;
struct edf_task_pdata *edf_pdata = edf_sch_get_pdata(task);
uint32_t flags;

Expand All @@ -201,6 +244,13 @@ static int schedule_edf_task_running(void *data, struct task *task)
task_context_set(edf_pdata->ctx);
task->state = SOF_TASK_STATE_RUNNING;

/* if budget is not set then it's not budgeted task */
if (edf_pdata->budget) {
Comment thread
lgirdwood marked this conversation as resolved.
timer_set(cpu_timer_get(), timer_get_system(cpu_timer_get())
+ edf_pdata->budget);
timer_enable(cpu_timer_get(), edf_sch, cpu_get_id());
}

irq_local_enable(flags);

return 0;
Expand Down Expand Up @@ -287,6 +337,8 @@ int scheduler_init_edf(void)
interrupt_register(edf_sch->irq, edf_scheduler_run, edf_sch);
interrupt_enable(edf_sch->irq, edf_sch);

timer_register(cpu_timer_get(), edf_scheduler_run, edf_sch);

return 0;
}

Expand All @@ -297,6 +349,8 @@ static void scheduler_free_edf(void *data)

irq_local_disable(flags);

timer_unregister(cpu_timer_get(), edf_sch);

/* disable and unregister EDF scheduler interrupt */
interrupt_disable(edf_sch->irq, edf_sch);
interrupt_unregister(edf_sch->irq, edf_sch);
Expand Down