cpufreq: interactive: Fix freeing of cached tunabled during module_exit()
To avoid multiple frees of an allocated tunables struct during
module_exit(), the pointer to the allocated tunables should be stored in
only one of the per-CPU cached_tunables pointer.
So, in the case of per policy governor configuration, store the cached
values in the pointer of first CPU in a policy. In the case of one governor
across all policies, store it in the CPU0 pointer.
Change-Id: Id4334246491519ac91ab725a8758b2748f743bb0
Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 7989bd6..d904682 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -1153,19 +1153,27 @@
{
int cpu;
- if (have_governor_per_policy()) {
- for_each_cpu(cpu, policy->related_cpus) {
- WARN_ON(per_cpu(cached_tunables, cpu) &&
- per_cpu(cached_tunables, cpu) != tunables);
- per_cpu(cached_tunables, cpu) = tunables;
- }
- } else {
- for_each_possible_cpu(cpu) {
- WARN_ON(per_cpu(cached_tunables, cpu) &&
- per_cpu(cached_tunables, cpu) != tunables);
- per_cpu(cached_tunables, cpu) = tunables;
- }
- }
+ if (have_governor_per_policy())
+ cpu = cpumask_first(policy->related_cpus);
+ else
+ cpu = 0;
+
+ WARN_ON(per_cpu(cached_tunables, cpu) &&
+ per_cpu(cached_tunables, cpu) != tunables);
+ per_cpu(cached_tunables, cpu) = tunables;
+}
+
+static struct cpufreq_interactive_tunables *restore_tunables(
+ struct cpufreq_policy *policy)
+{
+ int cpu;
+
+ if (have_governor_per_policy())
+ cpu = cpumask_first(policy->related_cpus);
+ else
+ cpu = 0;
+
+ return per_cpu(cached_tunables, cpu);
}
static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
@@ -1195,7 +1203,7 @@
return 0;
}
- tunables = per_cpu(cached_tunables, policy->cpu);
+ tunables = restore_tunables(policy);
if (!tunables) {
tunables = alloc_tunable(policy);
if (IS_ERR(tunables))