Trigger cpufreq updates any time the number of soft_affined task changes. -ck --- kernel/sched/bfs.c | 31 ++++++++++++++++++++++--------- kernel/sched/bfs_sched.h | 12 ++++++++++++ 2 files changed, 34 insertions(+), 9 deletions(-) Index: linux-4.7-ck4/kernel/sched/bfs.c =================================================================== --- linux-4.7-ck4.orig/kernel/sched/bfs.c 2016-09-13 17:21:52.354247208 +1000 +++ linux-4.7-ck4/kernel/sched/bfs.c 2016-09-13 17:21:52.352247253 +1000 @@ -1025,7 +1025,6 @@ static void update_load_avg(struct rq *r load = 0; load += rq->soft_affined * rq_load_avg(rq) * us_interval * 80 / 32768 / 128; rq->load_avg = load; - cpufreq_trigger(grq.niffies, rq->load_avg); } rq->load_update = rq->clock; } @@ -1057,6 +1056,7 @@ static void activate_task(struct task_st grq.nr_running++; inc_qnr(); update_load_avg(rq); + cpufreq_trigger(grq.niffies, rq->load_avg); } static inline void clear_sticky(struct task_struct *p); @@ -1074,18 +1074,21 @@ static inline void deactivate_task(struc grq.nr_running--; clear_sticky(p); update_load_avg(rq); + cpufreq_trigger(grq.niffies, rq->load_avg); } #ifdef CONFIG_SMP void set_task_cpu(struct task_struct *p, unsigned int cpu) { + unsigned int tcpu; + #ifdef CONFIG_LOCKDEP /* * The caller should hold grq lock. */ WARN_ON_ONCE(debug_locks && !lockdep_is_held(&grq.lock)); #endif - if (task_cpu(p) == cpu) + if ((tcpu = task_cpu(p)) == cpu) return; trace_sched_migrate_task(p, cpu); perf_event_task_migrate(p); @@ -1097,8 +1100,21 @@ void set_task_cpu(struct task_struct *p, */ smp_wmb(); if (p->on_rq) { - task_rq(p)->soft_affined--; - cpu_rq(cpu)->soft_affined++; + struct rq *rq; + + /* + * set_task_cpu can be set on other CPUs so call cpufreq_trigger + * explicitly telling it what CPU is being updated as the value + * of soft_affined has changed. + */ + rq = task_rq(p); + rq->soft_affined--; + update_load_avg(rq); + other_cpufreq_trigger(tcpu, grq.niffies, rq->load_avg); + rq = cpu_rq(cpu); + rq->soft_affined++; + update_load_avg(rq); + other_cpufreq_trigger(cpu, grq.niffies, rq->load_avg); } task_thread_info(p)->cpu = cpu; } @@ -3153,11 +3169,8 @@ void scheduler_tick(void) if (!rq_idle(rq)) task_running_tick(rq); else { - /* - * Trigger cpufreq update while we're idle. Soft affined will - * be zero unless we have uninterruptible tasks. - */ - cpufreq_trigger(grq.niffies, rq->soft_affined); + update_load_avg(rq); + cpufreq_trigger(grq.niffies, rq->load_avg); no_iso_tick(); } rq->last_tick = rq->clock; Index: linux-4.7-ck4/kernel/sched/bfs_sched.h =================================================================== --- linux-4.7-ck4.orig/kernel/sched/bfs_sched.h 2016-09-13 17:21:52.354247208 +1000 +++ linux-4.7-ck4/kernel/sched/bfs_sched.h 2016-09-13 17:21:52.352247253 +1000 @@ -210,10 +210,22 @@ static inline void cpufreq_trigger(u64 t data->func(data, time, util, SCHED_CAPACITY_SCALE); } +static inline void other_cpufreq_trigger(int cpu, u64 time, unsigned long util) +{ + struct update_util_data *data; + + data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data, cpu)); + if (data) + data->func(data, time, util, SCHED_CAPACITY_SCALE); +} #else static inline void cpufreq_trigger(u64 time, unsigned long util) { } + +static inline void other_cpufreq_trigger(int cpu, u64 time, unsigned long util) +{ +} #endif /* CONFIG_CPU_FREQ */ #ifdef arch_scale_freq_capacity