Repository navigation
Conversation
The DP lock is taken by the LL thread on every tick in scheduler_dp_ll_tick() and by each DP thread after every run. It was a k_sem, which has no priority inheritance: when a DP thread holding it was preempted by other DP threads, the cooperative high priority LL thread blocked until the holder got CPU time again. With several busy DP modules (3 MFCC + 3 MWW on cAVS 2.5) single LL ticks took up to ~40 ms, overrunning the DMIC DMAs of unrelated streams. With a k_mutex the holder inherits the LL priority: LL max drops from ~1.5M to <30k timer cycles, with no LL overruns or DMA xruns. Co-developed-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
CONFIG_ZEPHYR_DP_SCHEDULER can be enabled on cAVS, but only the ACE platform_init() registered the DP scheduler. Creating a DP module on cAVS then failed with "unable to bind scheduler to task (type 3)" and module init returned -ENODEV. Call scheduler_dp_init() after the LL scheduler is set up, as ACE does. Co-developed-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
| DECLARE_TR_CTX(dp_tr, SOF_UUID(dp_sched_uuid), LOG_LEVEL_INFO); | ||
|
|
||
| #define DP_LOCK_INIT(i, _) Z_SEM_INITIALIZER(dp_lock[i], 1, 1) | ||
| /* k_mutex, not k_sem: priority inheritance keeps a preempted DP holder from stalling LL */ |
| default y | ||
| help | ||
| Select for KPB component | ||
|
|
| if (buffer->secondary_buffer_sink && buffer->secondary_buffer_sink->ops->reset) | ||
| buffer->secondary_buffer_sink->ops->reset(buffer->secondary_buffer_sink); | ||
|
|
||
| #ifdef CONFIG_DP_TO_DP_BIND |
There was a problem hiding this comment.
this looks like it belongs in another patch.
| assert(!ret); | ||
| } | ||
| #else /* CONFIG_LIBRARY */ | ||
| #else |
There was a problem hiding this comment.
this looks like a completely separate patch too.
|
|
||
| [[maybe_unused]] void *sof_operator_new(size_t size) | ||
| { | ||
| return malloc(size); |
There was a problem hiding this comment.
how can we map this to mod_alloc ? We could use current thread context here to get metadata in order to alloc.
| default 0x40000 if VIRTUAL_HEAP | ||
| default 0xF0000 if SOC_ACE15_MTPM || SOC_ACE20_LNL | ||
| default 0x100000 if SOC_ACE30 || SOC_ACE40 | ||
| default 0xD0000 if SOC_ACE30 || SOC_ACE40 |
There was a problem hiding this comment.
is this needed for the C++ new ?
| ext_init payload. If the stack size requested in the IPC is | ||
| smaller than this, then the value defined here takes over. | ||
|
|
||
| config DP_TO_DP_BIND |
There was a problem hiding this comment.
seems unrelated, this should be form DP to DP patch.
|
|
||
| err = comp_prepare(current); | ||
| if (err < 0 || err == PPL_STATUS_PATH_STOP) | ||
| if (err < 0 || err == PPL_STATUS_PATH_STOP) { |
There was a problem hiding this comment.
this looks like a separate patch
| dai_common_free(cd->dd[i]); | ||
| mod_free(mod, cd->dd[i]->gain_data); | ||
| mod_free(mod, cd->dd[i]); | ||
| if (cd->dd[i]) { |
There was a problem hiding this comment.
this should be its own patch.
| { | ||
| assert_can_be_cold(); | ||
|
|
||
| if (!dd) |
There was a problem hiding this comment.
I suspect a lot of these are really not needed
When freeing an EDF scheduled task, ensure any pending delayed work associated with the task is cancelled before marking the task free and clearing callbacks. This prevents delayed work from triggering on freed task data during pipeline resets or teardown. Co-developed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
In copier_dai_free(), guard cd->dd[i] against NULL before accessing cd->dd[i]->gain_data and calling dai_common_free(). This prevents a NULL pointer dereference if endpoint allocation failed during initialization or during teardown of partially configured copier instances. Also reset pointers to NULL after freeing. Co-developed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
When comp_prepare() returns a negative error code in pipeline_comp_prepare(), emit a pipe_err message including the component ID and error code. This greatly accelerates diagnosing topology and IPC parameter configuration failures during pipeline setup. Co-developed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
91ea041 to
610f318
Compare
There was a problem hiding this comment.
🟡 Changes recommended
EDF task cleanup can race with an already-running delayed-work callback.
1 open finding
What changed in this PR
Addresses scheduling and cleanup regressions affecting WoV targets.
Changes:
- Improves DP scheduler initialization and priority inheritance.
- Adds preparation failure diagnostics.
- Hardens EDF and DAI resource cleanup.
| File | Description |
|---|---|
zephyr/edf_schedule.c |
Cancels delayed work during task cleanup. |
src/schedule/zephyr_dp_schedule.c |
Replaces DP semaphores with priority-inheriting mutexes. |
src/platform/intel/cavs/platform.c |
Initializes the DP scheduler on cAVS. |
src/audio/pipeline/pipeline-params.c |
Logs component preparation failures. |
src/audio/copier/copier_dai.c |
Adds guarded, idempotent DAI cleanup. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| static int schedule_edf_task_free(void *data, struct task *task) | ||
| { | ||
| k_work_cancel_delayable(&task->z_delayed_work); |

Testing, expect some patches/changes not required.