diff options
author | Nishanth Menon <nm@ti.com> | 2011-05-26 22:39:20 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@ti.com> | 2011-11-08 14:42:17 -0500 |
commit | 1c78217fc8c0983f5768a2d1c17c022f1079751e (patch) | |
tree | 4573ab5b78a0722f399cc599a6ae83ccd7099ee2 /drivers/cpufreq/omap-cpufreq.c | |
parent | 11e04fdd98f0fd6edf1ad6eccb0db4d2f965c392 (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.c | 22 |
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 | ||
48 | static struct cpufreq_frequency_table *freq_table; | 48 | static struct cpufreq_frequency_table *freq_table; |
49 | static atomic_t freq_table_users = ATOMIC_INIT(0); | ||
49 | static struct clk *mpu_clk; | 50 | static struct clk *mpu_clk; |
50 | static char *mpu_clk_name; | 51 | static char *mpu_clk_name; |
51 | static struct device *mpu_dev; | 52 | static 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 | ||
154 | static 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 | |||
153 | static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | 160 | static 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 | ||
211 | fail_table: | ||
212 | freq_table_free(); | ||
202 | fail_ck: | 213 | fail_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 | ||
207 | static int omap_cpu_exit(struct cpufreq_policy *policy) | 218 | static 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 | } |