diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-10-04 05:17:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:30 -0400 |
commit | b4dfdbb3c707474a2254c5b4d7e62be31a4b7da9 (patch) | |
tree | 20558266428cb904c4ffc660647cfdb7e7abeae5 /drivers/cpufreq | |
parent | e6a92013ba458804161c0c5b6d134d82204dc233 (diff) |
[PATCH] cpufreq: make the transition_notifier chain use SRCU
This patch (as762) changes the cpufreq_transition_notifier_list from a
blocking_notifier_head to an srcu_notifier_head. This will prevent errors
caused attempting to call down_read() to access the notifier chain at a
time when interrupts must remain disabled, during system suspend.
It's not clear to me whether this is really necessary; perhaps the chain
could be made into an atomic_notifier. However a couple of the callout
routines do use blocking operations, so this approach seems safer.
The head of the notifier chain needs to be initialized before use; this is
done by an __init routine at core_initcall time. If this turns out not to
be a good choice, it can easily be changed.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: "Paul E. McKenney" <paulmck@us.ibm.com>
Cc: Jesse Brandeburg <jesse.brandeburg@gmail.com>
Cc: Dave Jones <davej@codemonkey.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 2caaf71d80c8..86e69b7f9122 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -52,8 +52,14 @@ static void handle_update(void *data); | |||
52 | * The mutex locks both lists. | 52 | * The mutex locks both lists. |
53 | */ | 53 | */ |
54 | static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); | 54 | static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); |
55 | static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list); | 55 | static struct srcu_notifier_head cpufreq_transition_notifier_list; |
56 | 56 | ||
57 | static int __init init_cpufreq_transition_notifier_list(void) | ||
58 | { | ||
59 | srcu_init_notifier_head(&cpufreq_transition_notifier_list); | ||
60 | return 0; | ||
61 | } | ||
62 | core_initcall(init_cpufreq_transition_notifier_list); | ||
57 | 63 | ||
58 | static LIST_HEAD(cpufreq_governor_list); | 64 | static LIST_HEAD(cpufreq_governor_list); |
59 | static DEFINE_MUTEX (cpufreq_governor_mutex); | 65 | static DEFINE_MUTEX (cpufreq_governor_mutex); |
@@ -262,14 +268,14 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) | |||
262 | freqs->old = policy->cur; | 268 | freqs->old = policy->cur; |
263 | } | 269 | } |
264 | } | 270 | } |
265 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, | 271 | srcu_notifier_call_chain(&cpufreq_transition_notifier_list, |
266 | CPUFREQ_PRECHANGE, freqs); | 272 | CPUFREQ_PRECHANGE, freqs); |
267 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); | 273 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); |
268 | break; | 274 | break; |
269 | 275 | ||
270 | case CPUFREQ_POSTCHANGE: | 276 | case CPUFREQ_POSTCHANGE: |
271 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); | 277 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); |
272 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, | 278 | srcu_notifier_call_chain(&cpufreq_transition_notifier_list, |
273 | CPUFREQ_POSTCHANGE, freqs); | 279 | CPUFREQ_POSTCHANGE, freqs); |
274 | if (likely(policy) && likely(policy->cpu == freqs->cpu)) | 280 | if (likely(policy) && likely(policy->cpu == freqs->cpu)) |
275 | policy->cur = freqs->new; | 281 | policy->cur = freqs->new; |
@@ -1049,7 +1055,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) | |||
1049 | freqs.old = cpu_policy->cur; | 1055 | freqs.old = cpu_policy->cur; |
1050 | freqs.new = cur_freq; | 1056 | freqs.new = cur_freq; |
1051 | 1057 | ||
1052 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, | 1058 | srcu_notifier_call_chain(&cpufreq_transition_notifier_list, |
1053 | CPUFREQ_SUSPENDCHANGE, &freqs); | 1059 | CPUFREQ_SUSPENDCHANGE, &freqs); |
1054 | adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); | 1060 | adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); |
1055 | 1061 | ||
@@ -1130,7 +1136,7 @@ static int cpufreq_resume(struct sys_device * sysdev) | |||
1130 | freqs.old = cpu_policy->cur; | 1136 | freqs.old = cpu_policy->cur; |
1131 | freqs.new = cur_freq; | 1137 | freqs.new = cur_freq; |
1132 | 1138 | ||
1133 | blocking_notifier_call_chain( | 1139 | srcu_notifier_call_chain( |
1134 | &cpufreq_transition_notifier_list, | 1140 | &cpufreq_transition_notifier_list, |
1135 | CPUFREQ_RESUMECHANGE, &freqs); | 1141 | CPUFREQ_RESUMECHANGE, &freqs); |
1136 | adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); | 1142 | adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); |
@@ -1176,7 +1182,7 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) | |||
1176 | 1182 | ||
1177 | switch (list) { | 1183 | switch (list) { |
1178 | case CPUFREQ_TRANSITION_NOTIFIER: | 1184 | case CPUFREQ_TRANSITION_NOTIFIER: |
1179 | ret = blocking_notifier_chain_register( | 1185 | ret = srcu_notifier_chain_register( |
1180 | &cpufreq_transition_notifier_list, nb); | 1186 | &cpufreq_transition_notifier_list, nb); |
1181 | break; | 1187 | break; |
1182 | case CPUFREQ_POLICY_NOTIFIER: | 1188 | case CPUFREQ_POLICY_NOTIFIER: |
@@ -1208,7 +1214,7 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) | |||
1208 | 1214 | ||
1209 | switch (list) { | 1215 | switch (list) { |
1210 | case CPUFREQ_TRANSITION_NOTIFIER: | 1216 | case CPUFREQ_TRANSITION_NOTIFIER: |
1211 | ret = blocking_notifier_chain_unregister( | 1217 | ret = srcu_notifier_chain_unregister( |
1212 | &cpufreq_transition_notifier_list, nb); | 1218 | &cpufreq_transition_notifier_list, nb); |
1213 | break; | 1219 | break; |
1214 | case CPUFREQ_POLICY_NOTIFIER: | 1220 | case CPUFREQ_POLICY_NOTIFIER: |