summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorJoonwoo Park <joonwoop@codeaurora.org>2016-05-02 16:53:21 -0700
committerKyle Yan <kyan@codeaurora.org>2016-06-09 15:09:45 -0700
commit8c8a1a12e8396f8c122f2b195acf05131a18e1bd (patch)
treed145216a20402c2abe355a8b7a6e9767e0cf0f53 /kernel
parentb33996c5b44ac1f0cf52421112965f2e48271e1f (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.c13
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)