summaryrefslogtreecommitdiff
path: root/drivers/cpufreq
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 03ac6ce54042..089ca6a6ca02 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -252,20 +252,39 @@ static void update_sampling_rate(struct dbs_data *dbs_data,
od_tuners->sampling_rate = new_rate = max(new_rate,
dbs_data->min_sampling_rate);
+ /*
+ * Lock governor so that governor start/stop can't execute in parallel.
+ */
+ mutex_lock(&od_dbs_cdata.mutex);
+
for_each_online_cpu(cpu) {
struct cpufreq_policy *policy;
struct od_cpu_dbs_info_s *dbs_info;
+ struct cpu_dbs_info *cdbs;
+ struct cpu_common_dbs_info *shared;
unsigned long next_sampling, appointed_at;
- policy = cpufreq_cpu_get(cpu);
- if (!policy)
+ dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+ cdbs = &dbs_info->cdbs;
+ shared = cdbs->shared;
+
+ /*
+ * A valid shared and shared->policy means governor hasn't
+ * stopped or exited yet.
+ */
+ if (!shared || !shared->policy)
continue;
- if (policy->governor != &cpufreq_gov_ondemand) {
- cpufreq_cpu_put(policy);
+
+ policy = shared->policy;
+
+ /*
+ * Update sampling rate for CPUs whose policy is governed by
+ * dbs_data. In case of governor_per_policy, only a single
+ * policy will be governed by dbs_data, otherwise there can be
+ * multiple policies that are governed by the same dbs_data.
+ */
+ if (dbs_data != policy->governor_data)
continue;
- }
- dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
- cpufreq_cpu_put(policy);
if (!delayed_work_pending(&dbs_info->cdbs.dwork))
continue;
@@ -281,6 +300,8 @@ static void update_sampling_rate(struct dbs_data *dbs_data,
}
}
+
+ mutex_unlock(&od_dbs_cdata.mutex);
}
static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,