diff options
author | Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | 2007-08-30 05:46:39 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2008-03-05 03:23:19 -0500 |
commit | b8488fbe6d2f32ff4ad2f8f348a50e42389fc727 (patch) | |
tree | f3b58df85c57e60bf999a25336c99faf2bc7ae21 | |
parent | 538528de0cb256f65716ab2e9613d9e920f97fe2 (diff) |
ARM: OMAP: Fix sleep under spinlock for cpufreq
[ 10.523437] BUG: sleeping function called from invalid context at kernel/mut6
[ 10.523437] in_atomic():0, irqs_disabled():128
[ 10.523437] [<c002c168>] (dump_stack+0x0/0x14) from [<c005374c>] (__might_sl)
[ 10.523437] [<c0053698>] (__might_sleep+0x0/0xd4) from [<c024fdf4>] (mutex_l)
[ 10.523437] r5 = C02F0DE8 r4 = C02F0DF0
[ 10.523437] [<c024fdd4>] (mutex_lock+0x0/0x44) from [<c0041df4>] (clk_get+0x)
[ 10.523437] r4 = 00000000
[ 10.523437] [<c0041da4>] (clk_get+0x0/0x128) from [<c0046520>] (omap_getspee)
[ 10.523437] r8 = 00000002 r7 = 00000000 r6 = C031DAF8 r5 = C0473980
[ 10.523437] r4 = 00000000
[ 10.523437] [<c00464fc>] (omap_getspeed+0x0/0x5c) from [<c01b8518>] (cpufreq)
[ 10.523437] r5 = C0473980 r4 = 00000002
Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r-- | arch/arm/plat-omap/cpu-omap.c | 32 |
1 files changed, 10 insertions, 22 deletions
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c index c0d63b0c61c9..d719c15daa55 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/plat-omap/cpu-omap.c | |||
@@ -33,43 +33,33 @@ | |||
33 | #define MPU_CLK "virt_prcm_set" | 33 | #define MPU_CLK "virt_prcm_set" |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | static struct clk *mpu_clk; | ||
37 | |||
36 | /* TODO: Add support for SDRAM timing changes */ | 38 | /* TODO: Add support for SDRAM timing changes */ |
37 | 39 | ||
38 | int omap_verify_speed(struct cpufreq_policy *policy) | 40 | int omap_verify_speed(struct cpufreq_policy *policy) |
39 | { | 41 | { |
40 | struct clk * mpu_clk; | ||
41 | |||
42 | if (policy->cpu) | 42 | if (policy->cpu) |
43 | return -EINVAL; | 43 | return -EINVAL; |
44 | 44 | ||
45 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | 45 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, |
46 | policy->cpuinfo.max_freq); | 46 | policy->cpuinfo.max_freq); |
47 | mpu_clk = clk_get(NULL, MPU_CLK); | 47 | |
48 | if (IS_ERR(mpu_clk)) | ||
49 | return PTR_ERR(mpu_clk); | ||
50 | policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | 48 | policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; |
51 | policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | 49 | policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; |
52 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | 50 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, |
53 | policy->cpuinfo.max_freq); | 51 | policy->cpuinfo.max_freq); |
54 | clk_put(mpu_clk); | ||
55 | |||
56 | return 0; | 52 | return 0; |
57 | } | 53 | } |
58 | 54 | ||
59 | unsigned int omap_getspeed(unsigned int cpu) | 55 | unsigned int omap_getspeed(unsigned int cpu) |
60 | { | 56 | { |
61 | struct clk * mpu_clk; | ||
62 | unsigned long rate; | 57 | unsigned long rate; |
63 | 58 | ||
64 | if (cpu) | 59 | if (cpu) |
65 | return 0; | 60 | return 0; |
66 | 61 | ||
67 | mpu_clk = clk_get(NULL, MPU_CLK); | ||
68 | if (IS_ERR(mpu_clk)) | ||
69 | return 0; | ||
70 | rate = clk_get_rate(mpu_clk) / 1000; | 62 | rate = clk_get_rate(mpu_clk) / 1000; |
71 | clk_put(mpu_clk); | ||
72 | |||
73 | return rate; | 63 | return rate; |
74 | } | 64 | } |
75 | 65 | ||
@@ -77,14 +67,9 @@ static int omap_target(struct cpufreq_policy *policy, | |||
77 | unsigned int target_freq, | 67 | unsigned int target_freq, |
78 | unsigned int relation) | 68 | unsigned int relation) |
79 | { | 69 | { |
80 | struct clk * mpu_clk; | ||
81 | struct cpufreq_freqs freqs; | 70 | struct cpufreq_freqs freqs; |
82 | int ret = 0; | 71 | int ret = 0; |
83 | 72 | ||
84 | mpu_clk = clk_get(NULL, MPU_CLK); | ||
85 | if (IS_ERR(mpu_clk)) | ||
86 | return PTR_ERR(mpu_clk); | ||
87 | |||
88 | freqs.old = omap_getspeed(0); | 73 | freqs.old = omap_getspeed(0); |
89 | freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | 74 | freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; |
90 | freqs.cpu = 0; | 75 | freqs.cpu = 0; |
@@ -92,15 +77,12 @@ static int omap_target(struct cpufreq_policy *policy, | |||
92 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 77 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); |
93 | ret = clk_set_rate(mpu_clk, target_freq * 1000); | 78 | ret = clk_set_rate(mpu_clk, target_freq * 1000); |
94 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 79 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
95 | clk_put(mpu_clk); | ||
96 | 80 | ||
97 | return ret; | 81 | return ret; |
98 | } | 82 | } |
99 | 83 | ||
100 | static int __init omap_cpu_init(struct cpufreq_policy *policy) | 84 | static int __init omap_cpu_init(struct cpufreq_policy *policy) |
101 | { | 85 | { |
102 | struct clk * mpu_clk; | ||
103 | |||
104 | mpu_clk = clk_get(NULL, MPU_CLK); | 86 | mpu_clk = clk_get(NULL, MPU_CLK); |
105 | if (IS_ERR(mpu_clk)) | 87 | if (IS_ERR(mpu_clk)) |
106 | return PTR_ERR(mpu_clk); | 88 | return PTR_ERR(mpu_clk); |
@@ -111,17 +93,23 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy) | |||
111 | policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | 93 | policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; |
112 | policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000; | 94 | policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000; |
113 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 95 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
114 | clk_put(mpu_clk); | ||
115 | 96 | ||
116 | return 0; | 97 | return 0; |
117 | } | 98 | } |
118 | 99 | ||
100 | static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
101 | { | ||
102 | clk_put(mpu_clk); | ||
103 | return 0; | ||
104 | } | ||
105 | |||
119 | static struct cpufreq_driver omap_driver = { | 106 | static struct cpufreq_driver omap_driver = { |
120 | .flags = CPUFREQ_STICKY, | 107 | .flags = CPUFREQ_STICKY, |
121 | .verify = omap_verify_speed, | 108 | .verify = omap_verify_speed, |
122 | .target = omap_target, | 109 | .target = omap_target, |
123 | .get = omap_getspeed, | 110 | .get = omap_getspeed, |
124 | .init = omap_cpu_init, | 111 | .init = omap_cpu_init, |
112 | .exit = omap_cpu_exit, | ||
125 | .name = "omap", | 113 | .name = "omap", |
126 | }; | 114 | }; |
127 | 115 | ||