From f48db1e562b6d63acf4bccd6e97e9c3af9ebc204 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 18 Oct 2021 16:31:48 +0800 Subject: [PATCH 1/2] ll_schedule: keep the task in the list for finished task Keep the task in the list and the subsequent call to schedule_ll_task_cancel() will clean it up. Remove the operation in schedule_ll_task_done() to avoid double cleaning, and unregistering from the interrupt handler itself won't happen anymore. Signed-off-by: Keyon Jie --- src/schedule/ll_schedule.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/schedule/ll_schedule.c b/src/schedule/ll_schedule.c index a650cd065cea..d06d8b15c811 100644 --- a/src/schedule/ll_schedule.c +++ b/src/schedule/ll_schedule.c @@ -107,11 +107,6 @@ static void schedule_ll_task_update_start(struct ll_schedule_data *sch, static void schedule_ll_task_done(struct ll_schedule_data *sch, struct task *task) { - /* Remove from the task list, schedule_task_cancel() won't handle it again */ - list_item_del(&task->list); - - domain_unregister(sch->domain, task, atomic_sub(&sch->num_tasks, 1) - 1); - tr_info(&ll_tr, "task complete %p %pU", task, task->uid); tr_info(&ll_tr, "num_tasks %d total_num_tasks %d", atomic_read(&sch->num_tasks), @@ -142,6 +137,10 @@ static void schedule_ll_tasks_execute(struct ll_schedule_data *sch) /* do we need to reschedule this task */ if (task->state == SOF_TASK_STATE_COMPLETED) { + /* + * keep the task in the list and the subsequent call to + * schedule_ll_task_cancel() will clean it up. + */ schedule_ll_task_done(sch, task); } else { /* update task's start time */ From edf7c2bd69e958817ea8e9e02b9c9aed8fccdc08 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 18 Oct 2021 16:39:41 +0800 Subject: [PATCH 2/2] timer_domain: bring the timer_domain_unregister() back This partially revert the below commit, to bring the regitser/unregister symmetry back with restore the timer_domain_unregister() implementation: commit d4fd1b3eb696 ("timer_domain: don't unregister interrupt handler from itself") Signed-off-by: Keyon Jie --- src/schedule/timer_domain.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/schedule/timer_domain.c b/src/schedule/timer_domain.c index 8d30dc26f321..6d5cc125547b 100644 --- a/src/schedule/timer_domain.c +++ b/src/schedule/timer_domain.c @@ -67,12 +67,21 @@ static int timer_domain_register(struct ll_schedule_domain *domain, static int timer_domain_unregister(struct ll_schedule_domain *domain, struct task *task, uint32_t num_tasks) { - /* - * domain_unregister() can be called from the domain handler itself, - * and we cannot unregister the timer interrupt handler from the handler - * itself. Keep the interrupt registered but disabled. This assumes that - * the handler is at least not unloaded. - */ + struct timer_domain *timer_domain = ll_sch_domain_get_pdata(domain); + int core = cpu_get_id(); + + tr_dbg(&ll_tr, "timer_domain_unregister()"); + + /* tasks still registered on this core */ + if (!timer_domain->arg[core] || num_tasks) + return 0; + + tr_info(&ll_tr, "timer_domain_unregister domain->type %d domain->clk %d", + domain->type, domain->clk); + + timer_unregister(timer_domain->timer, timer_domain->arg[core]); + + timer_domain->arg[core] = NULL; return 0; }