From f6c65099e9f3cd8c48553d4c537b81d7e5d44449 Mon Sep 17 00:00:00 2001 From: Stephen Dickey Date: Fri, 29 Jul 2022 12:23:41 -0700 Subject: [PATCH] kernel/sched/walt/halt: drain needs __balance_callbacks drain_rq_cpu_stop as written, can and will add a call to the balance_callbacks queue. This is possible with the below calling sequence drain_rq_cpu_stop migrate_tasks pick_migrate_task pick_next_task pick_next_task-rt (first==true) set_next_task_rt rt_queue_push_tasks queue_balance_calllback (if rq has pushable tasks) --> entry added to balance_callbacks queue. drain_rq_cpu_stop will release the rq lock and enable interrupts without performing a balance callback. If an interrupt which will attempt to acquire the rq lock happens before this context switches out, the balance callback will not have happened, and an attempt to reaquire the rq lock will WARN. Correct the warn by handling the callbacks prior to releasing the locks and re-enabling interrupts. Change-Id: I36f7b20cfaedac556a5a2418a299551bc2c34eb3 Signed-off-by: Stephen Dickey --- kernel/sched/walt/walt_halt.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel/sched/walt/walt_halt.c b/kernel/sched/walt/walt_halt.c index f61528ef7cb2..c5f4acf04691 100644 --- a/kernel/sched/walt/walt_halt.c +++ b/kernel/sched/walt/walt_halt.c @@ -176,6 +176,8 @@ static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf) rq->stop = stop; } +void __balance_callbacks(struct rq *rq); + static int drain_rq_cpu_stop(void *data) { struct rq *rq = this_rq(); @@ -183,6 +185,14 @@ static int drain_rq_cpu_stop(void *data) rq_lock_irqsave(rq, &rf); migrate_tasks(rq, &rf); + + /* + * service any callbacks that were accumulated, prior to unlocking. such that + * any subsequent calls to rq_lock... will see an rq->balance_callback set to + * the default (0 or balance_push_callback); + */ + __balance_callbacks(rq); + rq_unlock_irqrestore(rq, &rf); return 0;