aboutsummaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch100
1 files changed, 100 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch
new file mode 100644
index 00000000..0cb4c91f
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch
@@ -0,0 +1,100 @@
+From 42a384af80e07534913d9002ec8d9caf5d4d305c Mon Sep 17 00:00:00 2001
+From: Nishanth Menon <nm@ti.com>
+Date: Wed, 18 May 2011 01:48:23 -0500
+Subject: [PATCH 6/6] OMAP2+: cpufreq: fix freq_table leak
+
+Since we have two cpus the cpuinit call for cpu1 causes
+freq_table of cpu0 to be overwritten. instead, we maintain
+a counter to keep track of cpus who use the cpufreq table
+allocate it once(one freq table for all CPUs) and free them
+once the last user is done with it.
+
+Signed-off-by: Nishanth Menon <nm@ti.com>
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/mach-omap2/omap2plus-cpufreq.c | 33 ++++++++++++++++++++++++------
+ 1 files changed, 26 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
+index d0b4f97..fc3d0fb 100644
+--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
++++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
+@@ -42,6 +42,9 @@
+ #define VERY_HI_RATE 900000000
+
+ static struct cpufreq_frequency_table *freq_table;
++static int freq_table_users;
++static DEFINE_MUTEX(freq_table_lock);
++
+ static struct clk *mpu_clk;
+
+ static int omap_verify_speed(struct cpufreq_policy *policy)
+@@ -172,6 +175,18 @@ skip_lpj:
+ return ret;
+ }
+
++static void freq_table_free(void)
++{
++ if (!freq_table_users)
++ return;
++ freq_table_users--;
++ if (freq_table_users)
++ return;
++ clk_exit_cpufreq_table(&freq_table);
++ kfree(freq_table);
++ freq_table = NULL;
++}
++
+ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
+ {
+ int result = 0;
+@@ -199,14 +214,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
+ return -EINVAL;
+ }
+
++ mutex_lock(&freq_table_lock);
+ /*
+ * if we dont get cpufreq table using opp, use traditional omap2 lookup
+ * as a fallback
+ */
+- if (opp_init_cpufreq_table(mpu_dev, &freq_table))
+- clk_init_cpufreq_table(&freq_table);
++ if (!freq_table) {
++ if (opp_init_cpufreq_table(mpu_dev, &freq_table))
++ clk_init_cpufreq_table(&freq_table);
++ }
+
+ if (freq_table) {
++ freq_table_users++;
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ if (!result) {
+ cpufreq_frequency_table_get_attr(freq_table,
+@@ -215,10 +234,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
+ clk_exit_cpufreq_table(&freq_table);
+ WARN(true, "%s: fallback to clk_round(freq_table=%d)\n",
+ __func__, result);
+- kfree(freq_table);
+- freq_table = NULL;
++ freq_table_free();
+ }
+ }
++ mutex_unlock(&freq_table_lock);
+
+ if (!freq_table) {
+ policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
+@@ -251,9 +270,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
+
+ static int omap_cpu_exit(struct cpufreq_policy *policy)
+ {
+- clk_exit_cpufreq_table(&freq_table);
+- kfree(freq_table);
+- freq_table = NULL;
++ mutex_lock(&freq_table_lock);
++ freq_table_free();
++ mutex_unlock(&freq_table_lock);
+ clk_put(mpu_clk);
+ return 0;
+ }
+--
+1.6.6.1
+