diff options
| author | Joonwoo Park <joonwoop@codeaurora.org> | 2016-05-02 16:53:21 -0700 |
|---|---|---|
| committer | Kyle Yan <kyan@codeaurora.org> | 2016-06-09 15:09:45 -0700 |
| commit | 8c8a1a12e8396f8c122f2b195acf05131a18e1bd (patch) | |
| tree | d145216a20402c2abe355a8b7a6e9767e0cf0f53 /kernel | |
| parent | b33996c5b44ac1f0cf52421112965f2e48271e1f (diff) | |
sched: avoid potential race between governor and thermal driver
It's possible thermal driver and governor notify that fmax is being
changed at the same time. In such case we can potentially skip updating
of CPU's capacity. Fix this by updating capacity always when limited
fmax is changed by same entity.
Meanwhile serialize sched_update_cpu_freq_min_max() with spinlock since
this function can be called by multiple drivers at the same time.
Change-Id: I3608cb09c30797bf858f434579fd07555546fb60
Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched/core.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index ab519d8d3422..6736e2d7cbaf 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4038,23 +4038,24 @@ static void update_cpu_cluster_capacity(const cpumask_t *cpus) post_big_task_count_change(cpu_possible_mask); } +static DEFINE_SPINLOCK(cpu_freq_min_max_lock); void sched_update_cpu_freq_min_max(const cpumask_t *cpus, u32 fmin, u32 fmax) { struct cpumask cpumask; struct sched_cluster *cluster; - unsigned int orig_max_freq; int i, update_capacity = 0; + unsigned long flags; + spin_lock_irqsave(&cpu_freq_min_max_lock, flags); cpumask_copy(&cpumask, cpus); for_each_cpu(i, &cpumask) { cluster = cpu_rq(i)->cluster; cpumask_andnot(&cpumask, &cpumask, &cluster->cpus); - orig_max_freq = cpu_max_freq(i); + update_capacity += (cluster->max_mitigated_freq != fmax); cluster->max_mitigated_freq = fmax; - - update_capacity += (orig_max_freq != cpu_max_freq(i)); } + spin_unlock_irqrestore(&cpu_freq_min_max_lock, flags); if (update_capacity) update_cpu_cluster_capacity(cpus); @@ -4090,7 +4091,7 @@ static int cpufreq_notifier_policy(struct notifier_block *nb, cpumask_andnot(&policy_cluster, &policy_cluster, &cluster->cpus); - orig_max_freq = cpu_max_freq(i); + orig_max_freq = cluster->max_freq; cluster->min_freq = policy->min; cluster->max_freq = policy->max; cluster->cur_freq = policy->cur; @@ -4111,7 +4112,7 @@ static int cpufreq_notifier_policy(struct notifier_block *nb, continue; } - update_capacity += (orig_max_freq != cpu_max_freq(i)); + update_capacity += (orig_max_freq != cluster->max_freq); } if (update_capacity) |
