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>
This commit is contained in:
Saravana Kannan 2014-07-22 15:42:51 -07:00 committed by David Keitel
parent 249a58c4a5
commit 9993217296

View file

@ -1155,19 +1155,27 @@ static void save_tunables(struct cpufreq_policy *policy,
{ {
int cpu; int cpu;
if (have_governor_per_policy()) { if (have_governor_per_policy())
for_each_cpu(cpu, policy->related_cpus) { cpu = cpumask_first(policy->related_cpus);
WARN_ON(per_cpu(cached_tunables, cpu) && else
per_cpu(cached_tunables, cpu) != tunables); cpu = 0;
per_cpu(cached_tunables, cpu) = tunables;
} WARN_ON(per_cpu(cached_tunables, cpu) &&
} else { per_cpu(cached_tunables, cpu) != tunables);
for_each_possible_cpu(cpu) { per_cpu(cached_tunables, cpu) = tunables;
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, static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
@ -1197,7 +1205,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
return 0; return 0;
} }
tunables = per_cpu(cached_tunables, policy->cpu); tunables = restore_tunables(policy);
if (!tunables) { if (!tunables) {
tunables = alloc_tunable(policy); tunables = alloc_tunable(policy);
if (IS_ERR(tunables)) if (IS_ERR(tunables))