diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index cde176f2fadb..61d098c2e12f 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1338,10 +1338,6 @@ int module_adapter_reset(struct comp_dev *dev) rfree(mod->stream_params); mod->stream_params = NULL; -#if CONFIG_IPC_MAJOR_4 - rfree(mod->priv.cfg.input_pins); -#endif - comp_dbg(dev, "module_adapter_reset(): done"); return comp_set_state(dev, COMP_TRIGGER_RESET); @@ -1371,6 +1367,10 @@ void module_adapter_free(struct comp_dev *dev) buffer_free(buffer); } +#if CONFIG_IPC_MAJOR_4 + rfree(mod->priv.cfg.input_pins); +#endif + rfree(mod); rfree(dev); } diff --git a/src/idc/zephyr_idc.c b/src/idc/zephyr_idc.c index 887cff0eb375..5d73016958bf 100644 --- a/src/idc/zephyr_idc.c +++ b/src/idc/zephyr_idc.c @@ -121,6 +121,32 @@ int idc_send_msg(struct idc_msg *msg, uint32_t mode) int ret; int idc_send_memcpy_err __unused; + if (!cpu_is_core_enabled(target_cpu)) { + tr_err(&zephyr_idc_tr, "Core %u is down, cannot sent IDC message", target_cpu); + return -EACCES; + } + + /* + * Handler is NULL when work object has never been submitted. + * In all other cases, we must use k_p4wq_wait() before reuse + * of the object. + */ + if (work->handler) { + /* + * If new request is in blocking mode, we must call + * k_p4wq in blocking mode. This is workaround for + * k_p4wq_wait() interface. + */ + work->sync = (mode == IDC_BLOCKING); + + ret = k_p4wq_wait(work, K_USEC(IDC_TIMEOUT)); + if (ret < 0) { + tr_err(&zephyr_idc_tr, "idc_send_msg error %d, target core %u", + ret, target_cpu); + return ret; + } + } + idc_send_memcpy_err = memcpy_s(msg_cp, sizeof(*msg_cp), msg, sizeof(*msg)); assert(!idc_send_memcpy_err); /* Same priority as the IPC thread which is an EDF task and under Zephyr */ @@ -129,10 +155,6 @@ int idc_send_msg(struct idc_msg *msg, uint32_t mode) work->handler = idc_handler; work->sync = mode == IDC_BLOCKING; - if (!cpu_is_core_enabled(target_cpu)) { - tr_err(&zephyr_idc_tr, "Core %u is down, cannot sent IDC message", target_cpu); - return -EACCES; - } if (msg->payload) { idc_send_memcpy_err = memcpy_s(payload->data, sizeof(payload->data), msg->payload, msg->size); diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index e70fd4e278d0..f36504989e69 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -510,13 +510,12 @@ static void ipc_compound_msg_done(uint32_t msg_id, int error) } } -/* wait for IPCs to complete on other cores and be nice to any LL work */ static int ipc_wait_for_compound_msg(void) { - int try_count = 30; /* timeout out is 30 x 10ms so 300ms for IPC */ + int try_count = 30; while (atomic_read(&msg_data.delayed_reply)) { - k_sleep(Z_TIMEOUT_MS(10)); + k_sleep(Z_TIMEOUT_US(250)); if (!try_count--) { atomic_set(&msg_data.delayed_reply, 0); diff --git a/west.yml b/west.yml index 610f7d3f1c7b..7f935f23a948 100644 --- a/west.yml +++ b/west.yml @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: d7af6f371034f31b9440b27c694b0be3c87491d3 + revision: pull/68110/head remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision diff --git a/zephyr/lib/cpu.c b/zephyr/lib/cpu.c index 3dde19dc38bc..6a896255795a 100644 --- a/zephyr/lib/cpu.c +++ b/zephyr/lib/cpu.c @@ -19,6 +19,7 @@ /* Zephyr includes */ #include #include +#include #include #include @@ -27,37 +28,9 @@ extern K_KERNEL_STACK_ARRAY_DEFINE(z_interrupt_stacks, CONFIG_MP_MAX_NUM_CPUS, CONFIG_ISR_STACK_SIZE); -static atomic_t start_flag; -static atomic_t ready_flag; - -/* Zephyr kernel_internal.h interface */ -extern void smp_timer_init(void); - -static FUNC_NORETURN void secondary_init(void *arg) +static void secondary_init(void *arg) { - struct k_thread dummy_thread; - - /* - * This is an open-coded version of zephyr/kernel/smp.c - * smp_init_top(). We do this so that we can call SOF - * secondary_core_init() for each core. - */ - - atomic_set(&ready_flag, 1); - z_smp_thread_init(arg, &dummy_thread); - smp_timer_init(); - secondary_core_init(sof_get()); - -#ifdef CONFIG_THREAD_STACK_INFO - dummy_thread.stack_info.start = (uintptr_t)z_interrupt_stacks + - arch_curr_cpu()->id * Z_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE); - dummy_thread.stack_info.size = Z_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE); -#endif - - z_smp_thread_swap(); - - CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } #if CONFIG_ZEPHYR_NATIVE_DRIVERS @@ -113,7 +86,6 @@ void cpu_notify_state_exit(enum pm_state state) /* Notifying primary core that secondary core successfully exit the D3 * state and is back in the Idle thread. */ - atomic_set(&ready_flag, 1); return; } #endif @@ -142,26 +114,17 @@ int cpu_enable_core(int id) if (arch_cpu_active(id)) return 0; -#if ZEPHYR_VERSION(3, 0, 99) <= ZEPHYR_VERSION_CODE /* During kernel initialization, the next pm state is set to ACTIVE. By checking this * value, we determine if this is the first core boot, if not, we need to skip idle thread * initialization. By reinitializing the idle thread, we would overwrite the kernel structs * and the idle thread stack. */ - if (pm_state_next_get(id)->state == PM_STATE_ACTIVE) - z_init_cpu(id); -#endif - - atomic_clear(&start_flag); - atomic_clear(&ready_flag); - - arch_start_cpu(id, z_interrupt_stacks[id], CONFIG_ISR_STACK_SIZE, - secondary_init, &start_flag); - - while (!atomic_get(&ready_flag)) - k_busy_wait(100); + if (pm_state_next_get(id)->state == PM_STATE_ACTIVE) { + k_smp_cpu_start(id, secondary_init, NULL); + return 0; + } - atomic_set(&start_flag, 1); + k_smp_cpu_resume(id, secondary_init, NULL, true, false); return 0; } @@ -239,29 +202,20 @@ int cpu_enable_core(int id) int cpu_enable_secondary_core(int id) { - /* - * This is an open-coded version of zephyr/kernel/smp.c - * z_smp_start_cpu(). We do this, so we can use a customized - * secondary_init() for SOF. - */ - if (arch_cpu_active(id)) return 0; -#if ZEPHYR_VERSION(3, 0, 99) <= ZEPHYR_VERSION_CODE - z_init_cpu(id); -#endif - - atomic_clear(&start_flag); - atomic_clear(&ready_flag); - - arch_start_cpu(id, z_interrupt_stacks[id], CONFIG_ISR_STACK_SIZE, - secondary_init, &start_flag); - - while (!atomic_get(&ready_flag)) - k_busy_wait(100); + /* During kernel initialization, the next pm state is set to ACTIVE. By checking this + * value, we determine if this is the first core boot, if not, we need to skip idle thread + * initialization. By reinitializing the idle thread, we would overwrite the kernel structs + * and the idle thread stack. + */ + if (pm_state_next_get(id)->state == PM_STATE_ACTIVE) { + k_smp_cpu_start(id, secondary_init, NULL); + return 0; + } - atomic_set(&start_flag, 1); + k_smp_cpu_resume(id, secondary_init, NULL, true, false); return 0; }