diff --git a/kernel/sched/core.c b/kernel/sched/core.c index fa71c7c5119641fbd162e0564e85059deb4e8027..77dc6e0e3f8bab1ecc6d55d915c1caf574a3b202 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -9690,6 +9690,15 @@ static int cpu_affinity_stat_show(struct seq_file *sf, void *v) return 0; } + +static int cpu_rebuild_affinity_domain_u64(struct cgroup_subsys_state *css, + struct cftype *cftype, + u64 cpu) +{ + struct task_group *tg = css_tg(css); + + return tg_rebuild_affinity_domains(cpu, tg->auto_affinity); +} #endif /* CONFIG_QOS_SCHED_SMART_GRID */ #ifdef CONFIG_QOS_SCHED @@ -9873,6 +9882,10 @@ static struct cftype cpu_legacy_files[] = { .name = "affinity_stat", .seq_show = cpu_affinity_stat_show, }, + { + .name = "rebuild_affinity_domain", + .write_u64 = cpu_rebuild_affinity_domain_u64, + }, #endif #ifdef CONFIG_CFS_BANDWIDTH { diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index f39e7547523c78bda1af34d28df053b1670296d3..1458878f5464f206c951614bfe81406a723e02f1 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6242,6 +6242,49 @@ static void destroy_auto_affinity(struct task_group *tg) kfree(tg->auto_affinity); tg->auto_affinity = NULL; } + +int tg_rebuild_affinity_domains(int cpu, struct auto_affinity *auto_affi) +{ + int ret = 0; + int level = 0; + struct sched_domain *tmp; + + if (unlikely(!auto_affi)) + return -EPERM; + + mutex_lock(&smart_grid_used_mutex); + raw_spin_lock_irq(&auto_affi->lock); + /* Only build domain while auto mode disabled */ + if (auto_affi->mode) { + ret = -EPERM; + goto unlock_all; + } + + /* Only build on active and housekeeping cpu */ + if (!cpu_active(cpu) || !housekeeping_cpu(cpu, HK_FLAG_DOMAIN)) { + ret = -EINVAL; + goto unlock_all; + } + + for_each_domain(cpu, tmp) { + if (!auto_affi->ad.domains[level] || !auto_affi->ad.domains_orig[level]) + continue; + + /* rebuild domain[,_orig] and reset schedstat counter */ + cpumask_copy(auto_affi->ad.domains[level], sched_domain_span(tmp)); + cpumask_copy(auto_affi->ad.domains_orig[level], auto_affi->ad.domains[level]); + __schedstat_set(auto_affi->ad.stay_cnt[level], 0); + level++; + } + + /* trigger to update smart grid zone */ + sched_grid_zone_update(false); + +unlock_all: + raw_spin_unlock_irq(&auto_affi->lock); + mutex_unlock(&smart_grid_used_mutex); + return ret; +} #else static void destroy_auto_affinity(struct task_group *tg) {} diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index e6f934af7062f938c5a67f9b10a77d034e91868d..e10f65a7f87f4bbce383f84ebd74c936f0eceb2e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -580,6 +580,7 @@ extern void start_auto_affinity(struct auto_affinity *auto_affi); extern void stop_auto_affinity(struct auto_affinity *auto_affi); extern int init_auto_affinity(struct task_group *tg); extern void tg_update_affinity_domains(int cpu, int online); +extern int tg_rebuild_affinity_domains(int cpu, struct auto_affinity *auto_affi); #else static inline int init_auto_affinity(struct task_group *tg)