aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/omap-cpufreq.c
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2011-05-26 22:39:20 -0400
committerKevin Hilman <khilman@ti.com>2011-11-08 14:42:17 -0500
commit1c78217fc8c0983f5768a2d1c17c022f1079751e (patch)
tree4573ab5b78a0722f399cc599a6ae83ccd7099ee2 /drivers/cpufreq/omap-cpufreq.c
parent11e04fdd98f0fd6edf1ad6eccb0db4d2f965c392 (diff)
cpufreq: OMAP: fix freq_table leak
We use a single frequency table for multiple CPUs. But, with OMAP4, since we have multiple CPUs, the cpu_init call for CPU1 causes freq_table previously allocated for CPU0 to be overwritten. In addition, we dont free the table on exit path. We solve this by maintaining an atomic type counter to ensure just a single table exists at a given time. Signed-off-by: Nishanth Menon <nm@ti.com> Signed-off-by: Kevin Hilman <khilman@ti.com>
Diffstat (limited to 'drivers/cpufreq/omap-cpufreq.c')
-rw-r--r--drivers/cpufreq/omap-cpufreq.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 8c5419201ac5..ad94b4f2892c 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -46,6 +46,7 @@ static struct lpj_info global_lpj_ref;
46#endif 46#endif
47 47
48static struct cpufreq_frequency_table *freq_table; 48static struct cpufreq_frequency_table *freq_table;
49static atomic_t freq_table_users = ATOMIC_INIT(0);
49static struct clk *mpu_clk; 50static struct clk *mpu_clk;
50static char *mpu_clk_name; 51static char *mpu_clk_name;
51static struct device *mpu_dev; 52static struct device *mpu_dev;
@@ -150,6 +151,12 @@ static int omap_target(struct cpufreq_policy *policy,
150 return ret; 151 return ret;
151} 152}
152 153
154static inline void freq_table_free(void)
155{
156 if (atomic_dec_and_test(&freq_table_users))
157 opp_free_cpufreq_table(mpu_dev, &freq_table);
158}
159
153static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) 160static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
154{ 161{
155 int result = 0; 162 int result = 0;
@@ -164,7 +171,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
164 } 171 }
165 172
166 policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); 173 policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
167 result = opp_init_cpufreq_table(mpu_dev, &freq_table); 174
175 if (atomic_inc_return(&freq_table_users) == 1)
176 result = opp_init_cpufreq_table(mpu_dev, &freq_table);
168 177
169 if (result) { 178 if (result) {
170 dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n", 179 dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
@@ -173,10 +182,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
173 } 182 }
174 183
175 result = cpufreq_frequency_table_cpuinfo(policy, freq_table); 184 result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
176 if (!result) 185 if (result)
177 cpufreq_frequency_table_get_attr(freq_table, policy->cpu); 186 goto fail_table;
178 else 187
179 goto fail_ck; 188 cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
180 189
181 policy->min = policy->cpuinfo.min_freq; 190 policy->min = policy->cpuinfo.min_freq;
182 policy->max = policy->cpuinfo.max_freq; 191 policy->max = policy->cpuinfo.max_freq;
@@ -199,6 +208,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
199 208
200 return 0; 209 return 0;
201 210
211fail_table:
212 freq_table_free();
202fail_ck: 213fail_ck:
203 clk_put(mpu_clk); 214 clk_put(mpu_clk);
204 return result; 215 return result;
@@ -206,6 +217,7 @@ fail_ck:
206 217
207static int omap_cpu_exit(struct cpufreq_policy *policy) 218static int omap_cpu_exit(struct cpufreq_policy *policy)
208{ 219{
220 freq_table_free();
209 clk_put(mpu_clk); 221 clk_put(mpu_clk);
210 return 0; 222 return 0;
211} 223}