aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRanjani Vaidyanathan <ra5478@freescale.com>2011-09-02 12:04:48 -0500
committerRanjani Vaidyanathan <ra5478@freescale.com>2011-09-02 19:38:05 -0500
commitd33eb697d0b97eea8cd02ecaebbb6d2f7684a9ff (patch)
tree9ed78fa126d3b8a20a00e47cfbd14a44bc1335d6
parentb337f54a44761f5760eb495c29969ba38a801ec6 (diff)
ENGR00155981: MX6: Fix crash caused by cpufreq during suspend/resume
Random crashes occur in CPUFREQ code when resuming from suspend. The root cause is due to freeing and allocating of common data structure (frequency table) shared among all the CPUs. Fix the code by ensuring that the common data structure is only created and deleted once. Signed-off-by: Ranjani Vaidyanathan <ra5478@freescale.com>
-rw-r--r--arch/arm/plat-mxc/cpufreq.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index e8a42434eec..f64b2312961 100644
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -207,28 +207,29 @@ static int __devinit mxc_cpufreq_init(struct cpufreq_policy *policy)
cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000;
cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000;
- imx_freq_table = kmalloc(
- sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1),
- GFP_KERNEL);
- if (!imx_freq_table) {
- ret = -ENOMEM;
- goto err1;
- }
-
- for (i = 0; i < cpu_op_nr; i++) {
- imx_freq_table[i].index = i;
- imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000;
+ if (imx_freq_table == NULL) {
+ imx_freq_table = kmalloc(
+ sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1),
+ GFP_KERNEL);
+ if (!imx_freq_table) {
+ ret = -ENOMEM;
+ goto err1;
+ }
- if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min)
- cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000;
+ for (i = 0; i < cpu_op_nr; i++) {
+ imx_freq_table[i].index = i;
+ imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000;
- if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max)
- cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000;
- }
+ if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min)
+ cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000;
- imx_freq_table[i].index = i;
- imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
+ if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max)
+ cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000;
+ }
+ imx_freq_table[i].index = i;
+ imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
+ }
policy->cur = clk_get_rate(cpu_clk) / 1000;
policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
@@ -265,9 +266,11 @@ static int mxc_cpufreq_exit(struct cpufreq_policy *policy)
{
cpufreq_frequency_table_put_attr(policy->cpu);
- set_cpu_freq(cpu_freq_khz_max * 1000);
- clk_put(cpu_clk);
- kfree(imx_freq_table);
+ if (policy->cpu == 0) {
+ set_cpu_freq(cpu_freq_khz_max * 1000);
+ clk_put(cpu_clk);
+ kfree(imx_freq_table);
+ }
return 0;
}