From 7a68ed73f024187bd797f75bbf80cad7c1a6d02d Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Thu, 27 Apr 2023 21:00:11 +0200 Subject: [PATCH 1/5] clk: remove unnecessary freq change notifications Such notification currently is used only in non-zephyr code (ll sched) so it is safe to remove for MTL because of some idc issues Signed-off-by: Adrian Bonislawski --- src/lib/clk.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/lib/clk.c b/src/lib/clk.c index a3439b2a01ae..6a57966b9be5 100644 --- a/src/lib/clk.c +++ b/src/lib/clk.c @@ -28,8 +28,6 @@ DECLARE_TR_CTX(clock_tr, SOF_UUID(clock_uuid), LOG_LEVEL_INFO); SHARED_DATA struct k_spinlock clk_lock; -struct clock_notify_data clk_notify_data; - static inline uint32_t clock_get_nearest_freq_idx(const struct freq_table *tab, uint32_t size, uint32_t hz) { @@ -59,39 +57,21 @@ void clock_set_freq(int clock, uint32_t hz) uint32_t idx; k_spinlock_key_t key; - clk_notify_data.old_freq = - clk_info->freqs[clk_info->current_freq_idx].freq; - clk_notify_data.old_ticks_per_msec = - clk_info->freqs[clk_info->current_freq_idx].ticks_per_msec; - /* atomic context for changing clocks */ key = clock_lock(); /* get nearest frequency that is >= requested Hz */ idx = clock_get_nearest_freq_idx(clk_info->freqs, clk_info->freqs_num, hz); - clk_notify_data.freq = clk_info->freqs[idx].freq; tr_info(&clock_tr, "clock %d set freq %dHz freq_idx %d", clock, hz, idx); - /* tell anyone interested we are about to change freq */ - clk_notify_data.message = CLOCK_NOTIFY_PRE; - notifier_event(clk_info, clk_info->notification_id, - clk_info->notification_mask, &clk_notify_data, - sizeof(clk_notify_data)); - if (!clk_info->set_freq || clk_info->set_freq(clock, idx) == 0) /* update clock frequency */ clk_info->current_freq_idx = idx; - /* tell anyone interested we have now changed freq */ - clk_notify_data.message = CLOCK_NOTIFY_POST; - notifier_event(clk_info, clk_info->notification_id, - clk_info->notification_mask, &clk_notify_data, - sizeof(clk_notify_data)); - clock_unlock(key); } From 4e3bf98d8eb1e8a6e7bbd2ac9c5e4391122b934e Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Sat, 26 Aug 2023 10:58:05 +0200 Subject: [PATCH 2/5] platform: init kcps budged before any kcps adjustments KCPS budged should be initialized before any KCPS adjustments Signed-off-by: Adrian Bonislawski --- src/platform/intel/ace/platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/intel/ace/platform.c b/src/platform/intel/ace/platform.c index 765bc7580236..a70d2db94a5c 100644 --- a/src/platform/intel/ace/platform.c +++ b/src/platform/intel/ace/platform.c @@ -87,6 +87,7 @@ int platform_init(struct sof *sof) trace_point(TRACE_BOOT_PLATFORM_CLOCK); platform_clock_init(sof); + kcps_budget_init(); /* Set DSP clock to MAX using KCPS API. Value should be lowered when KCPS API * for modules is implemented From 1572a1dfafe6acc5f55888657a1d6960c596991b Mon Sep 17 00:00:00 2001 From: Krzysztof Frydryk Date: Fri, 24 Feb 2023 16:48:09 +0100 Subject: [PATCH 3/5] pipeline: Register and unregister pipelines CPS consumption on run/pause Register and unregister pipelines CPS consumption on run/pause Signed-off-by: Adrian Bonislawski Signed-off-by: Krzysztof Frydryk +Squashed commits: 924f0d26db2c pipeline: print warning if 0 KCPS received Signed-off-by: Adrian Bonislawski 7bb6e7ef3ba9 pipeline: register CPS consumption for a proper core Signed-off-by: Adrian Bonislawski 5f0c4e4c3160 pipeline: make CPC data "opt-in" with fallback Signed-off-by: Liam Girdwood Signed-off-by: Peter Ujfalusi --- src/audio/pipeline/pipeline-stream.c | 101 +++++++++++++++++- src/include/sof/audio/pipeline.h | 3 + src/lib/cpu-clk-manager.c | 2 +- src/platform/Kconfig | 8 ++ .../imx93_a55/include/platform/lib/clk.h | 1 + 5 files changed, 112 insertions(+), 3 deletions(-) diff --git a/src/audio/pipeline/pipeline-stream.c b/src/audio/pipeline/pipeline-stream.c index af696810d5c5..51ddbd965ec1 100644 --- a/src/audio/pipeline/pipeline-stream.c +++ b/src/audio/pipeline/pipeline-stream.c @@ -11,12 +11,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include @@ -311,17 +314,80 @@ static void pipeline_trigger_xrun(struct pipeline *p, struct comp_dev **host) } while (true); } +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL +static int pipeline_calc_cps_consumption(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + struct ipc4_base_module_cfg *cd; + int comp_core, kcps; + + pipe_dbg(ppl_data->p, "pipeline_calc_cps_consumption(), current->comp.id = %u, dir = %u", + dev_comp_id(current), dir); + + if (!comp_is_single_pipeline(current, ppl_data->start)) { + pipe_dbg(ppl_data->p, "pipeline_calc_cps_consumption(), current is from another pipeline"); + return 0; + } + comp_core = current->ipc_config.core; + + /* modules created through module adapter have different priv_data */ + if (current->drv->type != SOF_COMP_MODULE_ADAPTER) { + cd = comp_get_drvdata(current); + } else { + struct processing_module *mod = comp_get_drvdata(current); + struct module_data *md = &mod->priv; + + cd = &md->cfg.base_cfg; + } + + if (cd->cpc == 0) { + /* Use maximum clock budget, assume 1ms chunk size */ + ppl_data->kcps[comp_core] = CLK_MAX_CPU_HZ / 1000; + tr_warn(pipe, + "0 CPS requested for module: %#x, core: %d using safe max KCPS: %u", + current->ipc_config.id, comp_core, ppl_data->kcps[comp_core]); + + return PPL_STATUS_PATH_STOP; + } else { + kcps = cd->cpc * 1000 / current->period; + tr_dbg(pipe, "Module: %#x KCPS consumption: %d, core: %d", + current->ipc_config.id, kcps, comp_core); + + ppl_data->kcps[comp_core] += kcps; + } + + return pipeline_for_each_comp(current, ctx, dir); +} +#endif + /* trigger pipeline in IPC context */ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) { int ret; - +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + struct pipeline_data data = { + .start = p->source_comp, + .p = p, + }; + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_calc_cps_consumption, + .comp_data = &data, + }; + bool trigger_first = false; + uint32_t flags = 0; +#endif pipe_info(p, "pipe trigger cmd %d", cmd); p->trigger.aborted = false; switch (cmd) { case COMP_TRIGGER_PAUSE: +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + trigger_first = true; + COMPILER_FALLTHROUGH; +#endif case COMP_TRIGGER_STOP: if (p->status == COMP_STATE_PAUSED || p->xrun_bytes) { /* The task isn't running, trigger inline */ @@ -338,9 +404,40 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) case COMP_TRIGGER_PRE_RELEASE: case COMP_TRIGGER_PRE_START: /* Add all connected pipelines to the list and trigger them all */ +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + flags = irq_lock(); + /* setup walking ctx for removing consumption */ + if (!trigger_first) { + ret = walk_ctx.comp_func(p->source_comp, NULL, &walk_ctx, PPL_DIR_DOWNSTREAM); + + for (int i = 0; i < arch_num_cpus(); i++) { + if (data.kcps[i] > 0) { + core_kcps_adjust(i, data.kcps[i]); + tr_info(pipe, "Sum of KCPS consumption: %d, core: %d", core_kcps_get(i), i); + } + } + } +#endif ret = pipeline_trigger_list(p, host, cmd); - if (ret < 0) + if (ret < 0) { +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + irq_unlock(flags); +#endif return ret; + } +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + if (trigger_first) { + ret = walk_ctx.comp_func(p->source_comp, NULL, &walk_ctx, PPL_DIR_DOWNSTREAM); + + for (int i = 0; i < arch_num_cpus(); i++) { + if (data.kcps[i] > 0) { + core_kcps_adjust(i, -data.kcps[i]); + tr_info(pipe, "Sum of KCPS consumption: %d, core: %d", core_kcps_get(i), i); + } + } + } + irq_unlock(flags); +#endif /* IPC response will be sent from the task, unless it was paused */ return PPL_STATUS_SCHEDULED; } diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index 8dc5ea16d51d..0edb3305680c 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -122,6 +122,9 @@ struct pipeline_data { struct pipeline *p; int cmd; uint32_t delay_ms; /* between PRE_{START,RELEASE} and {START,RELEASE} */ +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + uint32_t kcps[CONFIG_CORE_COUNT]; /**< the max count of KCPS */ +#endif }; /** \brief Task type registered by pipelines. */ diff --git a/src/lib/cpu-clk-manager.c b/src/lib/cpu-clk-manager.c index d23bb6e91cb3..ee92196aea2e 100644 --- a/src/lib/cpu-clk-manager.c +++ b/src/lib/cpu-clk-manager.c @@ -64,7 +64,7 @@ int core_kcps_adjust(int adjusted_core_id, int kcps_delta) for (core_id = 0; core_id < CONFIG_CORE_COUNT; core_id++) { /* Convert kcps to cps */ - ret = request_freq_change(core_id, freq * 1000); + ret = request_freq_change(core_id, MIN(freq * 1000, CLK_MAX_CPU_HZ)); if (ret < 0) goto out; } diff --git a/src/platform/Kconfig b/src/platform/Kconfig index 66dce8ea6f85..462074a028a9 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -377,6 +377,14 @@ config CAVS_USE_LPRO_IN_WAITI After waiti exit clock source will be restored. Choose n if unclear. +config KCPS_DYNAMIC_CLOCK_CONTROL + bool "Use KCPS budget to determine DSP clock" + default n + depends on IPC_MAJOR_4 + help + Select if we want to use compute budget + expressed in Kilo Cycles Per Second (KCPS) to determine DSP clock. + config L3_HEAP bool "Use L3 memory heap" default n diff --git a/src/platform/imx93_a55/include/platform/lib/clk.h b/src/platform/imx93_a55/include/platform/lib/clk.h index 6703c1304a7a..cb834906b485 100644 --- a/src/platform/imx93_a55/include/platform/lib/clk.h +++ b/src/platform/imx93_a55/include/platform/lib/clk.h @@ -12,6 +12,7 @@ #define CPU_DEFAULT_IDX 0 #define NUM_CLOCKS 1 #define NUM_CPU_FREQ 1 +#define CLK_MAX_CPU_HZ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC struct sof; From 577e8aa24886927c034a92e137a3c51c6e17bdc7 Mon Sep 17 00:00:00 2001 From: Krzysztof Frydryk Date: Fri, 24 Feb 2023 16:46:41 +0100 Subject: [PATCH 4/5] platform: register proper basefw CPS consumption on boot On init, register consumption of 10MCPS for base fw if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL enabled Signed-off-by: Adrian Bonislawski Signed-off-by: Krzysztof Frydryk --- src/init/init.c | 6 ++++++ src/platform/intel/ace/platform.c | 8 +++++--- src/platform/meteorlake/include/platform/lib/clk.h | 3 +++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/init/init.c b/src/init/init.c index 86049d8b6be1..a5b219c7ff2e 100644 --- a/src/init/init.c +++ b/src/init/init.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -203,6 +204,11 @@ int secondary_core_init(struct sof *sof) if (err < 0) return err; #endif +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + err = core_kcps_adjust(cpu_get_id(), SECONDARY_CORE_BASE_CPS_USAGE); + if (err < 0) + return err; +#endif trace_point(TRACE_BOOT_PLATFORM); diff --git a/src/platform/intel/ace/platform.c b/src/platform/intel/ace/platform.c index a70d2db94a5c..6959a6572c36 100644 --- a/src/platform/intel/ace/platform.c +++ b/src/platform/intel/ace/platform.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -89,10 +90,11 @@ int platform_init(struct sof *sof) platform_clock_init(sof); kcps_budget_init(); - /* Set DSP clock to MAX using KCPS API. Value should be lowered when KCPS API - * for modules is implemented - */ +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + ret = core_kcps_adjust(cpu_get_id(), PRIMARY_CORE_BASE_CPS_USAGE); +#else ret = core_kcps_adjust(cpu_get_id(), CLK_MAX_CPU_HZ / 1000); +#endif if (ret < 0) return ret; diff --git a/src/platform/meteorlake/include/platform/lib/clk.h b/src/platform/meteorlake/include/platform/lib/clk.h index fec0a582ab7e..e82c3e47fc61 100644 --- a/src/platform/meteorlake/include/platform/lib/clk.h +++ b/src/platform/meteorlake/include/platform/lib/clk.h @@ -30,6 +30,9 @@ #define NUM_SSP_FREQ 3 +#define PRIMARY_CORE_BASE_CPS_USAGE 20000 +#define SECONDARY_CORE_BASE_CPS_USAGE 10000 + #endif /* __PLATFORM_LIB_CLK_H__ */ #else From 2c6483f37d360b86724f290562e7ded1213ef214 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Wed, 9 Aug 2023 09:43:38 +0200 Subject: [PATCH 5/5] boards: mtl: enable KCPS dynamic clock control This will enable dynamic clock control based on KCPS budget Signed-off-by: Adrian Bonislawski --- app/boards/intel_adsp_ace15_mtpm.conf | 2 ++ app/perf_overlay.conf | 1 + 2 files changed, 3 insertions(+) diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index 4c75272de807..6d2b371e9f33 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -95,3 +95,5 @@ CONFIG_LOG_TIMESTAMP_64BIT=y CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=y CONFIG_COMP_STUBS=y + +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=y diff --git a/app/perf_overlay.conf b/app/perf_overlay.conf index 28a3eb83d50c..08edb74ee978 100644 --- a/app/perf_overlay.conf +++ b/app/perf_overlay.conf @@ -2,3 +2,4 @@ CONFIG_PERFORMANCE_COUNTERS=y CONFIG_SYS_HEAP_RUNTIME_STATS=y CONFIG_TIMING_FUNCTIONS=y CONFIG_ADSP_IDLE_CLOCK_GATING=n +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n