diff --git a/src/arch/xtensa/init.c b/src/arch/xtensa/init.c index 8a06252f2a4b..96c823cb8258 100644 --- a/src/arch/xtensa/init.c +++ b/src/arch/xtensa/init.c @@ -140,7 +140,7 @@ int slave_core_init(struct sof *sof) platform_interrupt_init(); trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init_edf(sof); + scheduler_init_edf(); scheduler_init_ll(platform_timer_domain); scheduler_init_ll(platform_dma_domain); diff --git a/src/audio/kpb.c b/src/audio/kpb.c index c7229087bf42..8044f2a52143 100644 --- a/src/audio/kpb.c +++ b/src/audio/kpb.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -987,9 +986,6 @@ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli) /* Pause selector copy. */ kpb->sel_sink->sink->state = COMP_STATE_PAUSED; - /* Disable system agent during draining */ - sa_disable(); - /* Schedule draining task */ schedule_task(&kpb->draining_task, 0, 0); } @@ -1129,9 +1125,6 @@ static enum task_state kpb_draining_task(void *arg) */ (void)(draining_time_end - draining_time_start); - /* Enable system agent back */ - sa_enable(); - return SOF_TASK_STATE_COMPLETED; } diff --git a/src/include/sof/lib/agent.h b/src/include/sof/lib/agent.h index a7a81820383d..b8b785ca9b3c 100644 --- a/src/include/sof/lib/agent.h +++ b/src/include/sof/lib/agent.h @@ -16,15 +16,12 @@ struct sof; /* simple agent */ struct sa { - uint64_t last_idle; /* time of last idle */ - uint64_t ticks; + uint64_t last_check; /* time of last activity checking */ + uint64_t panic_timeout; /* threshold of panic */ + uint64_t warn_timeout; /* threshold of warning */ struct task work; - bool is_active; }; -void sa_enter_idle(struct sof *sof); -void sa_init(struct sof *sof); -void sa_disable(void); -void sa_enable(void); +void sa_init(struct sof *sof, uint64_t timeout); #endif /* __SOF_LIB_AGENT_H__ */ diff --git a/src/include/sof/schedule/edf_schedule.h b/src/include/sof/schedule/edf_schedule.h index 625ab0eae4d8..b3d9d974d11e 100644 --- a/src/include/sof/schedule/edf_schedule.h +++ b/src/include/sof/schedule/edf_schedule.h @@ -13,8 +13,6 @@ #include #include -struct sof; - /* schedule tracing */ #define trace_edf_sch(format, ...) \ trace_event(TRACE_CLASS_EDF, format, ##__VA_ARGS__) @@ -35,6 +33,6 @@ struct edf_task_pdata { void *ctx; }; -int scheduler_init_edf(struct sof *sof); +int scheduler_init_edf(void); #endif /* __SOF_SCHEDULE_EDF_SCHEDULE_H__ */ diff --git a/src/include/sof/schedule/task.h b/src/include/sof/schedule/task.h index 07861053c93b..a43ad1c5d11a 100644 --- a/src/include/sof/schedule/task.h +++ b/src/include/sof/schedule/task.h @@ -57,7 +57,7 @@ enum task_state task_main_master_core(void *data); enum task_state task_main_slave_core(void *data); -void task_main_init(struct sof *sof); +void task_main_init(void); void task_main_free(void); diff --git a/src/lib/agent.c b/src/lib/agent.c index 7e2d9b337f80..b009c9bc17ee 100644 --- a/src/lib/agent.c +++ b/src/lib/agent.c @@ -6,10 +6,11 @@ /* * System Agent - Simple FW Monitor that can notify host drivers in the event - * of any FW errors. The SA assumes that each core will enter the idle state - * from time to time (within a period of PLATFORM_IDLE_TIME). If the core does - * not enter the idle loop through looping forever or scheduling some work - * continuously then the SA will emit trace and panic(). + * of any FW errors. The SA checks if the DSP is still responsive and verifies + * the stability of the system by checking time elapsed between every timer + * tick. If the core exceeds the threshold by over 5% then the SA will emit + * error trace. However if it will be exceeded by over 100% the panic will be + * called. */ #include @@ -32,19 +33,11 @@ trace_event_atomic(TRACE_CLASS_SA, __e, ##__VA_ARGS__) #define trace_sa_value(__e, ...) \ trace_value_atomic(__e, ##__VA_ARGS__) +#define trace_sa_error(__e, ...) \ + trace_error(TRACE_CLASS_SA, __e, ##__VA_ARGS__) struct sa *sa; -/* - * Notify the SA that we are about to enter idle state (WFI). - */ -void sa_enter_idle(struct sof *sof) -{ - struct sa *sa = sof->sa; - - sa->last_idle = platform_timer_get(platform_timer); -} - static enum task_state validate(void *data) { struct sa *sa = data; @@ -52,50 +45,48 @@ static enum task_state validate(void *data) uint64_t delta; current = platform_timer_get(platform_timer); - delta = current - sa->last_idle; - - /* were we last idle longer than timeout */ + delta = current - sa->last_check; - if (delta > sa->ticks && sa->is_active) { - trace_sa("validate(), idle longer than timeout, delta = %u", - delta); + /* panic timeout */ + if (delta > sa->panic_timeout) panic(SOF_IPC_PANIC_IDLE); - } + + /* warning timeout */ + if (delta > sa->warn_timeout) + trace_sa_error("validate(), ll drift detected, delta = " + "%u", delta); + + /* update last_check to current */ + sa->last_check = current; return SOF_TASK_STATE_RESCHEDULE; } -void sa_init(struct sof *sof) +void sa_init(struct sof *sof, uint64_t timeout) { + uint64_t ticks; - trace_sa("sa_init()"); + trace_sa("sa_init(), timeout = %u", timeout); sa = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(*sa)); sof->sa = sa; - /* set default tick timeout */ - sa->ticks = clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * - PLATFORM_IDLE_TIME / 1000; + /* set default timeouts */ + ticks = clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * timeout / 1000; - trace_sa("sa_init(), sa->ticks = %u", sa->ticks); + /* TODO: change values after minimal drifts will be assured */ + sa->panic_timeout = 2 * ticks; /* 100% delay */ + sa->warn_timeout = ticks + ticks / 20; /* 5% delay */ - /* set lst idle time to now to give time for boot completion */ - sa->last_idle = platform_timer_get(platform_timer) + sa->ticks; - sa->is_active = true; + trace_sa("sa_init(), ticks = %u, sa->warn_timeout = %u, " + "sa->panic_timeout = %u", ticks, sa->warn_timeout, + sa->panic_timeout); schedule_task_init(&sa->work, SOF_SCHEDULE_LL_TIMER, SOF_TASK_PRI_HIGH, validate, NULL, sa, 0, 0); - schedule_task(&sa->work, PLATFORM_IDLE_TIME, PLATFORM_IDLE_TIME); -} + schedule_task(&sa->work, 0, timeout); -void sa_disable(void) -{ - sa->is_active = false; -} - -void sa_enable(void) -{ - sa->is_active = true; - sa->last_idle = platform_timer_get(platform_timer); + /* set last check time to now to give time for boot completion */ + sa->last_check = platform_timer_get(platform_timer); } diff --git a/src/platform/Kconfig b/src/platform/Kconfig index 06a511349054..1a3b0e54369a 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -236,4 +236,13 @@ config FIRMWARE_SHORT_NAME 3-characters long firmware identifer used by rimage to decide how to build final binary +config SYSTICK_PERIOD + int "System tick period in microseconds" + default 1000 + help + Defines platform system tick period. It is used to + drive timer based low latency scheduler and also + as a timeout check value for system agent. + Value should be provided in microseconds. + endmenu diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index acea8a9e0b69..66fbd919b92e 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -56,11 +56,6 @@ struct timer; #define PLATFORM_MAX_CHANNELS 8 #define PLATFORM_MAX_STREAMS 16 -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - /* local buffer size of DMA tracing */ #define DMA_TRACE_LOCAL_SIZE (HOST_PAGE_SIZE * 2) @@ -76,9 +71,6 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 500 -/* DSP should be idle in this time frame */ -#define PLATFORM_IDLE_TIME 750000 - /* platform has DMA memory type */ #define PLATFORM_MEM_HAS_DMA diff --git a/src/platform/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h index ddfd614d7813..4eb11a82514e 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/include/platform/platform.h @@ -40,11 +40,6 @@ struct timer; */ #define PLATFORM_DEFAULT_CLOCK CLK_SSP -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - /* IPC Interrupt */ #define PLATFORM_IPC_INTERRUPT IRQ_NUM_EXT_IA #define PLATFORM_IPC_INTERRUPT_NAME NULL @@ -76,9 +71,6 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 100 -/* DSP should be idle in this time frame */ -#define PLATFORM_IDLE_TIME 750000 - /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c index ee6ab0642e46..e6bf2bbebe26 100644 --- a/src/platform/baytrail/platform.c +++ b/src/platform/baytrail/platform.c @@ -190,12 +190,12 @@ int platform_init(struct sof *sof) clock_init(); trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init_edf(sof); + scheduler_init_edf(); /* init low latency timer domain and scheduler */ platform_timer_domain = timer_domain_init(platform_timer, PLATFORM_DEFAULT_CLOCK, - PLATFORM_LL_DEFAULT_TIMEOUT); + CONFIG_SYSTICK_PERIOD); scheduler_init_ll(platform_timer_domain); /* init low latency multi channel DW-DMA domain and scheduler */ @@ -208,7 +208,7 @@ int platform_init(struct sof *sof) /* init the system agent */ trace_point(TRACE_BOOT_PLATFORM_AGENT); - sa_init(sof); + sa_init(sof, CONFIG_SYSTICK_PERIOD); /* Set CPU to default frequency for booting */ trace_point(TRACE_BOOT_PLATFORM_CPU_FREQ); diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h index 428ba88704e2..177e26fc06a0 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -37,11 +37,6 @@ struct timer; */ #define PLATFORM_DEFAULT_CLOCK CLK_SSP -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - #define MAX_GPDMA_COUNT 2 /* Host page size */ @@ -79,9 +74,6 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 500 -/* DSP should be idle in this time frame */ -#define PLATFORM_IDLE_TIME 750000 - /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 diff --git a/src/platform/haswell/include/platform/platform.h b/src/platform/haswell/include/platform/platform.h index a94ed53045bc..c9b3dbda7886 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -36,11 +36,6 @@ struct timer; */ #define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - /* IPC Interrupt */ #define PLATFORM_IPC_INTERRUPT IRQ_NUM_EXT_IA #define PLATFORM_IPC_INTERRUPT_NAME NULL @@ -72,9 +67,6 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 100 -/* DSP should be idle in this time frame */ -#define PLATFORM_IDLE_TIME 750000 - /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c index 0aeae47284f0..1faab99ac9bd 100644 --- a/src/platform/haswell/platform.c +++ b/src/platform/haswell/platform.c @@ -178,12 +178,12 @@ int platform_init(struct sof *sof) clock_init(); trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init_edf(sof); + scheduler_init_edf(); /* init low latency timer domain and scheduler */ platform_timer_domain = timer_domain_init(platform_timer, PLATFORM_DEFAULT_CLOCK, - PLATFORM_LL_DEFAULT_TIMEOUT); + CONFIG_SYSTICK_PERIOD); scheduler_init_ll(platform_timer_domain); /* init low latency multi channel DW-DMA domain and scheduler */ @@ -196,7 +196,7 @@ int platform_init(struct sof *sof) /* init the system agent */ trace_point(TRACE_BOOT_PLATFORM_AGENT); - sa_init(sof); + sa_init(sof, CONFIG_SYSTICK_PERIOD); /* Set CPU to default frequency for booting */ trace_point(TRACE_BOOT_PLATFORM_CPU_FREQ); diff --git a/src/platform/icelake/include/platform/platform.h b/src/platform/icelake/include/platform/platform.h index c65d6b8cb1ba..606b44071235 100644 --- a/src/platform/icelake/include/platform/platform.h +++ b/src/platform/icelake/include/platform/platform.h @@ -37,11 +37,6 @@ struct timer; */ #define PLATFORM_DEFAULT_CLOCK CLK_SSP -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - #define MAX_GPDMA_COUNT 2 /* Host page size */ @@ -79,9 +74,6 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 500 -/* DSP should be idle in this time frame */ -#define PLATFORM_IDLE_TIME 750000 - /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 diff --git a/src/platform/imx8/include/platform/platform.h b/src/platform/imx8/include/platform/platform.h index c44d77860e67..334745d1c92a 100644 --- a/src/platform/imx8/include/platform/platform.h +++ b/src/platform/imx8/include/platform/platform.h @@ -25,11 +25,6 @@ struct timer; #define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) #define LPSRAM_SIZE 16384 -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - /* IPC Interrupt */ #define PLATFORM_IPC_INTERRUPT IRQ_NUM_MU #define PLATFORM_IPC_INTERRUPT_NAME NULL @@ -61,9 +56,6 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 100 -/* DSP should be idle in this time frame */ -#define PLATFORM_IDLE_TIME 750000 - /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 diff --git a/src/platform/imx8/platform.c b/src/platform/imx8/platform.c index aeecf4ca9a3a..ae59a53f67cb 100644 --- a/src/platform/imx8/platform.c +++ b/src/platform/imx8/platform.c @@ -145,12 +145,12 @@ int platform_init(struct sof *sof) platform_interrupt_init(); clock_init(); - scheduler_init_edf(sof); + scheduler_init_edf(); /* init low latency domains and schedulers */ platform_timer_domain = timer_domain_init(platform_timer, PLATFORM_DEFAULT_CLOCK, - PLATFORM_LL_DEFAULT_TIMEOUT); + CONFIG_SYSTICK_PERIOD); scheduler_init_ll(platform_timer_domain); /* Init EDMA platform domain */ @@ -163,7 +163,7 @@ int platform_init(struct sof *sof) scheduler_init_ll(platform_dma_domain); platform_timer_start(platform_timer); - sa_init(sof); + sa_init(sof, CONFIG_SYSTICK_PERIOD); clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index 59aa2e5ce91c..3ab6bed7562d 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -378,12 +378,12 @@ int platform_init(struct sof *sof) clock_init(); trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init_edf(sof); + scheduler_init_edf(); /* init low latency timer domain and scheduler */ platform_timer_domain = timer_domain_init(platform_timer, PLATFORM_DEFAULT_CLOCK, - PLATFORM_LL_DEFAULT_TIMEOUT); + CONFIG_SYSTICK_PERIOD); scheduler_init_ll(platform_timer_domain); /* init low latency single channel DW-DMA domain and scheduler */ @@ -396,7 +396,7 @@ int platform_init(struct sof *sof) /* init the system agent */ trace_point(TRACE_BOOT_PLATFORM_AGENT); - sa_init(sof); + sa_init(sof, CONFIG_SYSTICK_PERIOD); /* Set CPU to max frequency for booting (single shim_write below) */ trace_point(TRACE_BOOT_PLATFORM_CPU_FREQ); diff --git a/src/platform/library/include/platform/platform.h b/src/platform/library/include/platform/platform.h index 5a1de02b784d..9fae05253e2a 100644 --- a/src/platform/library/include/platform/platform.h +++ b/src/platform/library/include/platform/platform.h @@ -26,11 +26,6 @@ struct timer; */ #define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - /* Host page size */ #define HOST_PAGE_SIZE 4096 diff --git a/src/platform/suecreek/include/platform/platform.h b/src/platform/suecreek/include/platform/platform.h index a33aba4f2f4c..4e9662dfc7d0 100644 --- a/src/platform/suecreek/include/platform/platform.h +++ b/src/platform/suecreek/include/platform/platform.h @@ -37,11 +37,6 @@ struct timer; */ #define PLATFORM_DEFAULT_CLOCK CLK_SSP -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - #define MAX_GPDMA_COUNT 2 /* Host page size */ @@ -75,9 +70,6 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 500 -/* DSP should be idle in this time frame */ -#define PLATFORM_IDLE_TIME 750000 - /* baud-rate used for uart port trace log */ #define PATFORM_TRACE_UART_BAUDRATE 115200 diff --git a/src/platform/tigerlake/include/platform/platform.h b/src/platform/tigerlake/include/platform/platform.h index c65d6b8cb1ba..606b44071235 100644 --- a/src/platform/tigerlake/include/platform/platform.h +++ b/src/platform/tigerlake/include/platform/platform.h @@ -37,11 +37,6 @@ struct timer; */ #define PLATFORM_DEFAULT_CLOCK CLK_SSP -/*! \def PLATFORM_LL_DEFAULT_TIMEOUT - * \brief low latency scheduler default timeout in microseconds - */ -#define PLATFORM_LL_DEFAULT_TIMEOUT 1000 - #define MAX_GPDMA_COUNT 2 /* Host page size */ @@ -79,9 +74,6 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 500 -/* DSP should be idle in this time frame */ -#define PLATFORM_IDLE_TIME 750000 - /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 diff --git a/src/schedule/edf_schedule.c b/src/schedule/edf_schedule.c index 2d4360f896f1..91f0032558cf 100644 --- a/src/schedule/edf_schedule.c +++ b/src/schedule/edf_schedule.c @@ -259,7 +259,7 @@ static void schedule_edf_task_free(void *data, struct task *task) irq_local_enable(flags); } -int scheduler_init_edf(struct sof *sof) +int scheduler_init_edf(void) { struct edf_schedule_data *edf_sch; @@ -272,7 +272,7 @@ int scheduler_init_edf(struct sof *sof) scheduler_init(SOF_SCHEDULE_EDF, &schedule_edf_ops, edf_sch); /* initialize main task context before enabling interrupt */ - task_main_init(sof); + task_main_init(); /* configure EDF scheduler interrupt */ edf_sch->irq = interrupt_get_irq(PLATFORM_SCHEDULE_IRQ, diff --git a/src/schedule/task.c b/src/schedule/task.c index 71ffca9e48a9..7e74c60a44be 100644 --- a/src/schedule/task.c +++ b/src/schedule/task.c @@ -41,12 +41,9 @@ static void sys_module_init(void) enum task_state task_main_master_core(void *data) { - struct sof *sof = data; - /* main audio processing loop */ while (1) { /* sleep until next IPC or DMA */ - sa_enter_idle(sof); wait_for_interrupt(0); /* now process any IPC messages to host */ @@ -56,7 +53,7 @@ enum task_state task_main_master_core(void *data) return SOF_TASK_STATE_COMPLETED; } -void task_main_init(struct sof *sof) +void task_main_init(void) { struct task **main_task = task_main_get(); int cpu = cpu_get_id(); @@ -66,8 +63,8 @@ void task_main_init(struct sof *sof) *main_task = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(**main_task)); assert(!schedule_task_init(*main_task, SOF_SCHEDULE_EDF, - SOF_TASK_PRI_IDLE, main_main, NULL, sof, cpu, - SOF_SCHEDULE_FLAG_IDLE)); + SOF_TASK_PRI_IDLE, main_main, NULL, NULL, + cpu, SOF_SCHEDULE_FLAG_IDLE)); } void task_main_free(void) diff --git a/tools/testbench/common_test.c b/tools/testbench/common_test.c index 253cf4f04b66..e820a651aca2 100644 --- a/tools/testbench/common_test.c +++ b/tools/testbench/common_test.c @@ -36,7 +36,7 @@ int tb_pipeline_setup(struct sof *sof) } /* init scheduler */ - if (scheduler_init_edf(sof) < 0) { + if (scheduler_init_edf() < 0) { fprintf(stderr, "error: edf scheduler init\n"); return -EINVAL; } diff --git a/tools/testbench/edf_schedule.c b/tools/testbench/edf_schedule.c index 44f63529fb3f..1f8969ad473d 100644 --- a/tools/testbench/edf_schedule.c +++ b/tools/testbench/edf_schedule.c @@ -54,7 +54,7 @@ static int schedule_edf_task_init(void *data, struct task *task) } /* initialize scheduler */ -int scheduler_init_edf(struct sof *sof) +int scheduler_init_edf(void) { trace_edf_sch("edf_scheduler_init()"); sch = malloc(sizeof(*sch));