Always account for both the ext_server and fair_server bandwidths, especially during CPU hotplug operations. Ignoring either can lead to imbalances in total_bw when sched_ext schedulers are active and CPUs are brought online / offline. Signed-off-by: Andrea Righi <arighi@xxxxxxxxxx> --- kernel/sched/deadline.c | 29 +++++++++++++++++++++-------- kernel/sched/topology.c | 5 +++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 31d397aa777b9..165b12553e10d 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -2981,9 +2981,17 @@ void dl_clear_root_domain(struct root_domain *rd) * them, we need to account for them here explicitly. */ for_each_cpu(i, rd->span) { - struct sched_dl_entity *dl_se = &cpu_rq(i)->fair_server; + struct sched_dl_entity *dl_se; - if (dl_server(dl_se) && cpu_active(i)) + if (!cpu_active(i)) + continue; + + dl_se = &cpu_rq(i)->fair_server; + if (dl_server(dl_se)) + __dl_add(&rd->dl_bw, dl_se->dl_bw, dl_bw_cpus(i)); + + dl_se = &cpu_rq(i)->ext_server; + if (dl_server(dl_se)) __dl_add(&rd->dl_bw, dl_se->dl_bw, dl_bw_cpus(i)); } } @@ -3478,6 +3486,7 @@ static int dl_bw_manage(enum dl_bw_request req, int cpu, u64 dl_bw) struct dl_bw *dl_b; bool overflow = 0; u64 fair_server_bw = 0; + u64 ext_server_bw = 0; rcu_read_lock_sched(); dl_b = dl_bw_of(cpu); @@ -3510,27 +3519,31 @@ static int dl_bw_manage(enum dl_bw_request req, int cpu, u64 dl_bw) cap -= arch_scale_cpu_capacity(cpu); /* - * cpu is going offline and NORMAL tasks will be moved away - * from it. We can thus discount dl_server bandwidth - * contribution as it won't need to be servicing tasks after - * the cpu is off. + * cpu is going offline and NORMAL and EXT tasks will be + * moved away from it. We can thus discount dl_server + * bandwidth contribution as it won't need to be servicing + * tasks after the cpu is off. */ if (cpu_rq(cpu)->fair_server.dl_server) fair_server_bw = cpu_rq(cpu)->fair_server.dl_bw; + if (cpu_rq(cpu)->ext_server.dl_server) + ext_server_bw = cpu_rq(cpu)->ext_server.dl_bw; + /* * Not much to check if no DEADLINE bandwidth is present. * dl_servers we can discount, as tasks will be moved out the * offlined CPUs anyway. */ - if (dl_b->total_bw - fair_server_bw > 0) { + if (dl_b->total_bw - fair_server_bw - ext_server_bw > 0) { /* * Leaving at least one CPU for DEADLINE tasks seems a * wise thing to do. As said above, cpu is not offline * yet, so account for that. */ if (dl_bw_cpus(cpu) - 1) - overflow = __dl_overflow(dl_b, cap, fair_server_bw, 0); + overflow = __dl_overflow(dl_b, cap, + fair_server_bw + ext_server_bw, 0); else overflow = 1; } diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 977e133bb8a44..f4574b0cf8ebc 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -508,6 +508,11 @@ void rq_attach_root(struct rq *rq, struct root_domain *rd) if (rq->fair_server.dl_server) __dl_server_attach_root(&rq->fair_server, rq); +#ifdef CONFIG_SCHED_CLASS_EXT + if (rq->ext_server.dl_server) + __dl_server_attach_root(&rq->ext_server, rq); +#endif + rq_unlock_irqrestore(rq, &rf); if (old_rd) -- 2.51.0