diff options
author | Arve Hjønnevåg <arve@android.com> | 2011-06-24 03:04:16 -0400 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2011-07-13 18:29:58 -0400 |
commit | 5b02b7794b555e299c5e9298c6b223b538888ec8 (patch) | |
tree | ae2abbea1e4fc0ac98a544d058c3d0689b01cef0 /drivers/cpufreq/s5pv210-cpufreq.c | |
parent | 405e6d6df739a27a267b381213aa9e86c4929543 (diff) |
[CPUFREQ] S5PV210: Lock a mutex while changing the cpu frequency
Without this lock the call to change the frequency for suspend could
switch to a new frequency while another thread was still changing the
cpu voltage.
Signed-off-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'drivers/cpufreq/s5pv210-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/s5pv210-cpufreq.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 79b1b4ec8e3c..7fba356d2729 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c | |||
@@ -26,6 +26,7 @@ static struct clk *cpu_clk; | |||
26 | static struct clk *dmc0_clk; | 26 | static struct clk *dmc0_clk; |
27 | static struct clk *dmc1_clk; | 27 | static struct clk *dmc1_clk; |
28 | static struct cpufreq_freqs freqs; | 28 | static struct cpufreq_freqs freqs; |
29 | static DEFINE_MUTEX(set_freq_lock); | ||
29 | 30 | ||
30 | /* APLL M,P,S values for 1G/800Mhz */ | 31 | /* APLL M,P,S values for 1G/800Mhz */ |
31 | #define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1) | 32 | #define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1) |
@@ -199,6 +200,8 @@ static int s5pv210_target(struct cpufreq_policy *policy, | |||
199 | int arm_volt, int_volt; | 200 | int arm_volt, int_volt; |
200 | int ret = 0; | 201 | int ret = 0; |
201 | 202 | ||
203 | mutex_lock(&set_freq_lock); | ||
204 | |||
202 | if (relation & ENABLE_FURTHER_CPUFREQ) | 205 | if (relation & ENABLE_FURTHER_CPUFREQ) |
203 | no_cpufreq_access = false; | 206 | no_cpufreq_access = false; |
204 | 207 | ||
@@ -207,7 +210,8 @@ static int s5pv210_target(struct cpufreq_policy *policy, | |||
207 | pr_err("%s:%d denied access to %s as it is disabled" | 210 | pr_err("%s:%d denied access to %s as it is disabled" |
208 | "temporarily\n", __FILE__, __LINE__, __func__); | 211 | "temporarily\n", __FILE__, __LINE__, __func__); |
209 | #endif | 212 | #endif |
210 | return -EINVAL; | 213 | ret = -EINVAL; |
214 | goto exit; | ||
211 | } | 215 | } |
212 | 216 | ||
213 | if (relation & DISABLE_FURTHER_CPUFREQ) | 217 | if (relation & DISABLE_FURTHER_CPUFREQ) |
@@ -218,19 +222,23 @@ static int s5pv210_target(struct cpufreq_policy *policy, | |||
218 | freqs.old = s5pv210_getspeed(0); | 222 | freqs.old = s5pv210_getspeed(0); |
219 | 223 | ||
220 | if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, | 224 | if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, |
221 | target_freq, relation, &index)) | 225 | target_freq, relation, &index)) { |
222 | return -EINVAL; | 226 | ret = -EINVAL; |
227 | goto exit; | ||
228 | } | ||
223 | 229 | ||
224 | freqs.new = s5pv210_freq_table[index].frequency; | 230 | freqs.new = s5pv210_freq_table[index].frequency; |
225 | freqs.cpu = 0; | 231 | freqs.cpu = 0; |
226 | 232 | ||
227 | if (freqs.new == freqs.old) | 233 | if (freqs.new == freqs.old) |
228 | return 0; | 234 | goto exit; |
229 | 235 | ||
230 | /* Finding current running level index */ | 236 | /* Finding current running level index */ |
231 | if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, | 237 | if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, |
232 | freqs.old, relation, &priv_index)) | 238 | freqs.old, relation, &priv_index)) { |
233 | return -EINVAL; | 239 | ret = -EINVAL; |
240 | goto exit; | ||
241 | } | ||
234 | 242 | ||
235 | arm_volt = dvs_conf[index].arm_volt; | 243 | arm_volt = dvs_conf[index].arm_volt; |
236 | int_volt = dvs_conf[index].int_volt; | 244 | int_volt = dvs_conf[index].int_volt; |
@@ -239,12 +247,12 @@ static int s5pv210_target(struct cpufreq_policy *policy, | |||
239 | ret = regulator_set_voltage(arm_regulator, | 247 | ret = regulator_set_voltage(arm_regulator, |
240 | arm_volt, arm_volt_max); | 248 | arm_volt, arm_volt_max); |
241 | if (ret) | 249 | if (ret) |
242 | return ret; | 250 | goto exit; |
243 | 251 | ||
244 | ret = regulator_set_voltage(int_regulator, | 252 | ret = regulator_set_voltage(int_regulator, |
245 | int_volt, int_volt_max); | 253 | int_volt, int_volt_max); |
246 | if (ret) | 254 | if (ret) |
247 | return ret; | 255 | goto exit; |
248 | } | 256 | } |
249 | 257 | ||
250 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 258 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); |
@@ -471,7 +479,9 @@ static int s5pv210_target(struct cpufreq_policy *policy, | |||
471 | 479 | ||
472 | printk(KERN_DEBUG "Perf changed[L%d]\n", index); | 480 | printk(KERN_DEBUG "Perf changed[L%d]\n", index); |
473 | 481 | ||
474 | return 0; | 482 | exit: |
483 | mutex_unlock(&set_freq_lock); | ||
484 | return ret; | ||
475 | } | 485 | } |
476 | 486 | ||
477 | #ifdef CONFIG_PM | 487 | #ifdef CONFIG_PM |