Commit b481fea7d9e3461365edaba2d026321acc77e31f

Authored by Nishanth Menon
Committed by Afzal Mohammed
1 parent e8e3da65b1
Exists in master

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>
[vaibhav.bedia@ti.com: Pull in for AM33xx]
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>

Showing 1 changed file with 17 additions and 5 deletions Side-by-side Diff

drivers/cpufreq/omap-cpufreq.c
... ... @@ -47,6 +47,7 @@
47 47 #endif
48 48  
49 49 static struct cpufreq_frequency_table *freq_table;
  50 +static atomic_t freq_table_users = ATOMIC_INIT(0);
50 51 static struct clk *mpu_clk;
51 52 static char *mpu_clk_name;
52 53 static struct device *mpu_dev;
... ... @@ -151,6 +152,12 @@
151 152 return ret;
152 153 }
153 154  
  155 +static inline void freq_table_free(void)
  156 +{
  157 + if (atomic_dec_and_test(&freq_table_users))
  158 + opp_free_cpufreq_table(mpu_dev, &freq_table);
  159 +}
  160 +
154 161 static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
155 162 {
156 163 int result = 0;
157 164  
... ... @@ -165,8 +172,10 @@
165 172 }
166 173  
167 174 policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
168   - result = opp_init_cpufreq_table(mpu_dev, &freq_table);
169 175  
  176 + if (atomic_inc_return(&freq_table_users) == 1)
  177 + result = opp_init_cpufreq_table(mpu_dev, &freq_table);
  178 +
170 179 if (result) {
171 180 dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
172 181 __func__, policy->cpu, result);
173 182  
... ... @@ -174,11 +183,11 @@
174 183 }
175 184  
176 185 result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
177   - if (!result)
178   - cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
179   - else
180   - goto fail_ck;
  186 + if (result)
  187 + goto fail_table;
181 188  
  189 + cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
  190 +
182 191 policy->min = policy->cpuinfo.min_freq;
183 192 policy->max = policy->cpuinfo.max_freq;
184 193 policy->cur = omap_getspeed(policy->cpu);
... ... @@ -200,6 +209,8 @@
200 209  
201 210 return 0;
202 211  
  212 +fail_table:
  213 + freq_table_free();
203 214 fail_ck:
204 215 clk_put(mpu_clk);
205 216 return result;
... ... @@ -207,6 +218,7 @@
207 218  
208 219 static int omap_cpu_exit(struct cpufreq_policy *policy)
209 220 {
  221 + freq_table_free();
210 222 clk_put(mpu_clk);
211 223 return 0;
212 224 }