Always account for both the ext_server and fair_server bandwidth,
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 <[email protected]>
---
 kernel/sched/deadline.c | 54 +++++++++++++++++++++++++++++++----------
 kernel/sched/topology.c |  5 ++++
 2 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 6ecfaaa1f912d..f786174a126c8 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -2994,6 +2994,36 @@ void dl_add_task_root_domain(struct task_struct *p)
        task_rq_unlock(rq, p, &rf);
 }
 
+static void dl_server_add_bw(struct root_domain *rd, int cpu)
+{
+       struct sched_dl_entity *dl_se;
+
+       dl_se = &cpu_rq(cpu)->fair_server;
+       if (dl_server(dl_se))
+               __dl_add(&rd->dl_bw, dl_se->dl_bw, dl_bw_cpus(cpu));
+
+#ifdef CONFIG_SCHED_CLASS_EXT
+       dl_se = &cpu_rq(cpu)->ext_server;
+       if (dl_server(dl_se))
+               __dl_add(&rd->dl_bw, dl_se->dl_bw, dl_bw_cpus(cpu));
+#endif
+}
+
+static u64 dl_server_read_bw(int cpu)
+{
+       u64 dl_bw = 0;
+
+       if (cpu_rq(cpu)->fair_server.dl_server)
+               dl_bw += cpu_rq(cpu)->fair_server.dl_bw;
+
+#ifdef CONFIG_SCHED_CLASS_EXT
+       if (cpu_rq(cpu)->ext_server.dl_server)
+               dl_bw += cpu_rq(cpu)->ext_server.dl_bw;
+#endif
+
+       return dl_bw;
+}
+
 void dl_clear_root_domain(struct root_domain *rd)
 {
        int i;
@@ -3013,10 +3043,9 @@ 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;
-
-               if (dl_server(dl_se) && cpu_active(i))
-                       __dl_add(&rd->dl_bw, dl_se->dl_bw, dl_bw_cpus(i));
+               if (!cpu_active(i))
+                       continue;
+               dl_server_add_bw(rd, i);
        }
 }
 
@@ -3513,7 +3542,7 @@ static int dl_bw_manage(enum dl_bw_request req, int cpu, 
u64 dl_bw)
        unsigned long flags, cap;
        struct dl_bw *dl_b;
        bool overflow = 0;
-       u64 fair_server_bw = 0;
+       u64 dl_server_bw = 0;
 
        rcu_read_lock_sched();
        dl_b = dl_bw_of(cpu);
@@ -3546,27 +3575,26 @@ 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;
+               dl_server_bw = dl_server_read_bw(cpu);
 
                /*
                 * 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 - dl_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, 
dl_server_bw, 0);
                        else
                                overflow = 1;
                }
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index 711076aa49801..1ec8e74b80219 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.2


Reply via email to