diff --git a/kernel/sched/walt/walt.c b/kernel/sched/walt/walt.c index 23f9a01f9a26..4507cb2d02a2 100644 --- a/kernel/sched/walt/walt.c +++ b/kernel/sched/walt/walt.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -3808,11 +3809,6 @@ static void walt_irq_work(struct irq_work *irq_work) level++; } - if (!is_migration) { - for_each_cpu(cpu, &lock_cpus) - update_cpu_capacity_helper(cpu); - } - __walt_irq_work_locked(is_migration, &lock_cpus); for_each_cpu(cpu, &lock_cpus) @@ -4440,6 +4436,46 @@ static void android_rvh_build_perf_domains(void *unused, bool *eas_check) *eas_check = true; } +static void android_rvh_update_thermal_stats(void *unused, int cpu) +{ + if (unlikely(walt_disabled)) + return; + update_cpu_capacity_helper(cpu); +} + +static DECLARE_COMPLETION(rebuild_domains_completion); +static void rebuild_sd_workfn(struct work_struct *work); +static DECLARE_WORK(rebuild_sd_work, rebuild_sd_workfn); + +/** rebuild_sd_workfn + * + * rebuild the sched domains (and therefore the perf + * domains). It is absolutely necessary that the + * em_pds are created for each cpu device before + * proceeding, and this must complete for walt to + * function properly. + */ +static void rebuild_sd_workfn(struct work_struct *work) +{ + int cpu; + struct device *cpu_dev; + + for_each_possible_cpu(cpu) { + cpu_dev = get_cpu_device(cpu); + if (cpu_dev->em_pd) + continue; + + WARN_ONCE(true, "must wait for perf domains to be created"); + schedule_work(&rebuild_sd_work); + + /* do not rebuild domains yet, and do not complete this action */ + return; + } + + rebuild_sched_domains(); + complete(&rebuild_domains_completion); +} + static void walt_do_sched_yield(void *unused, struct rq *rq) { struct task_struct *curr = rq->curr; @@ -4484,6 +4520,7 @@ static void register_walt_hooks(void) register_trace_android_rvh_build_perf_domains(android_rvh_build_perf_domains, NULL); register_trace_cpu_frequency_limits(walt_cpu_frequency_limits, NULL); register_trace_android_rvh_do_sched_yield(walt_do_sched_yield, NULL); + register_trace_android_rvh_update_thermal_stats(android_rvh_update_thermal_stats, NULL); } atomic64_t walt_irq_work_lastq_ws; @@ -4551,6 +4588,7 @@ static void walt_init(struct work_struct *work) { struct ctl_table_header *hdr; static atomic_t already_inited = ATOMIC_INIT(0); + struct root_domain *rd = cpu_rq(cpumask_first(cpu_active_mask))->rd; int i; might_sleep(); @@ -4573,6 +4611,22 @@ static void walt_init(struct work_struct *work) walt_cfs_init(); walt_halt_init(); wait_for_completion_interruptible(&tick_sched_clock_completion); + + if (!rcu_dereference(rd->pd)) { + /* + * perf domains not properly configured. this is a must as + * create_util_to_cost depends on rd->pd being properly + * initialized. + */ + schedule_work(&rebuild_sd_work); + wait_for_completion_interruptible(&rebuild_domains_completion); + } + + if (!rcu_dereference(rd->pd)) + WALT_BUG(WALT_BUG_WALT, NULL, + "root domain's perf-domain values not initialized rd->pd=%d.", + rd->pd); + stop_machine(walt_init_stop_handler, NULL, NULL); hdr = register_sysctl_table(walt_base_table); diff --git a/kernel/sched/walt/walt.h b/kernel/sched/walt/walt.h index c72e68120ee5..6274f7a49071 100644 --- a/kernel/sched/walt/walt.h +++ b/kernel/sched/walt/walt.h @@ -189,6 +189,7 @@ extern void walt_init_foreground_tg(struct task_group *tg); extern int register_walt_callback(void); extern int input_boost_init(void); extern int core_ctl_init(void); +extern void rebuild_sched_domains(void); extern atomic64_t walt_irq_work_lastq_ws; extern unsigned int __read_mostly sched_ravg_window;