diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 61 |
1 files changed, 26 insertions, 35 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index aed80e6aec6d..9b6ae7dc8b8a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -52,9 +52,8 @@ static void handle_update(void *data); | |||
52 | * changes to devices when the CPU clock speed changes. | 52 | * changes to devices when the CPU clock speed changes. |
53 | * The mutex locks both lists. | 53 | * The mutex locks both lists. |
54 | */ | 54 | */ |
55 | static struct notifier_block *cpufreq_policy_notifier_list; | 55 | static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); |
56 | static struct notifier_block *cpufreq_transition_notifier_list; | 56 | static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list); |
57 | static DECLARE_RWSEM (cpufreq_notifier_rwsem); | ||
58 | 57 | ||
59 | 58 | ||
60 | static LIST_HEAD(cpufreq_governor_list); | 59 | static LIST_HEAD(cpufreq_governor_list); |
@@ -247,8 +246,6 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) | |||
247 | dprintk("notification %u of frequency transition to %u kHz\n", | 246 | dprintk("notification %u of frequency transition to %u kHz\n", |
248 | state, freqs->new); | 247 | state, freqs->new); |
249 | 248 | ||
250 | down_read(&cpufreq_notifier_rwsem); | ||
251 | |||
252 | policy = cpufreq_cpu_data[freqs->cpu]; | 249 | policy = cpufreq_cpu_data[freqs->cpu]; |
253 | switch (state) { | 250 | switch (state) { |
254 | 251 | ||
@@ -266,20 +263,19 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) | |||
266 | freqs->old = policy->cur; | 263 | freqs->old = policy->cur; |
267 | } | 264 | } |
268 | } | 265 | } |
269 | notifier_call_chain(&cpufreq_transition_notifier_list, | 266 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, |
270 | CPUFREQ_PRECHANGE, freqs); | 267 | CPUFREQ_PRECHANGE, freqs); |
271 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); | 268 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); |
272 | break; | 269 | break; |
273 | 270 | ||
274 | case CPUFREQ_POSTCHANGE: | 271 | case CPUFREQ_POSTCHANGE: |
275 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); | 272 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); |
276 | notifier_call_chain(&cpufreq_transition_notifier_list, | 273 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, |
277 | CPUFREQ_POSTCHANGE, freqs); | 274 | CPUFREQ_POSTCHANGE, freqs); |
278 | if (likely(policy) && likely(policy->cpu == freqs->cpu)) | 275 | if (likely(policy) && likely(policy->cpu == freqs->cpu)) |
279 | policy->cur = freqs->new; | 276 | policy->cur = freqs->new; |
280 | break; | 277 | break; |
281 | } | 278 | } |
282 | up_read(&cpufreq_notifier_rwsem); | ||
283 | } | 279 | } |
284 | EXPORT_SYMBOL_GPL(cpufreq_notify_transition); | 280 | EXPORT_SYMBOL_GPL(cpufreq_notify_transition); |
285 | 281 | ||
@@ -1007,7 +1003,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) | |||
1007 | freqs.old = cpu_policy->cur; | 1003 | freqs.old = cpu_policy->cur; |
1008 | freqs.new = cur_freq; | 1004 | freqs.new = cur_freq; |
1009 | 1005 | ||
1010 | notifier_call_chain(&cpufreq_transition_notifier_list, | 1006 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, |
1011 | CPUFREQ_SUSPENDCHANGE, &freqs); | 1007 | CPUFREQ_SUSPENDCHANGE, &freqs); |
1012 | adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); | 1008 | adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); |
1013 | 1009 | ||
@@ -1088,7 +1084,8 @@ static int cpufreq_resume(struct sys_device * sysdev) | |||
1088 | freqs.old = cpu_policy->cur; | 1084 | freqs.old = cpu_policy->cur; |
1089 | freqs.new = cur_freq; | 1085 | freqs.new = cur_freq; |
1090 | 1086 | ||
1091 | notifier_call_chain(&cpufreq_transition_notifier_list, | 1087 | blocking_notifier_call_chain( |
1088 | &cpufreq_transition_notifier_list, | ||
1092 | CPUFREQ_RESUMECHANGE, &freqs); | 1089 | CPUFREQ_RESUMECHANGE, &freqs); |
1093 | adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); | 1090 | adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); |
1094 | 1091 | ||
@@ -1125,24 +1122,24 @@ static struct sysdev_driver cpufreq_sysdev_driver = { | |||
1125 | * changes in cpufreq policy. | 1122 | * changes in cpufreq policy. |
1126 | * | 1123 | * |
1127 | * This function may sleep, and has the same return conditions as | 1124 | * This function may sleep, and has the same return conditions as |
1128 | * notifier_chain_register. | 1125 | * blocking_notifier_chain_register. |
1129 | */ | 1126 | */ |
1130 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) | 1127 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) |
1131 | { | 1128 | { |
1132 | int ret; | 1129 | int ret; |
1133 | 1130 | ||
1134 | down_write(&cpufreq_notifier_rwsem); | ||
1135 | switch (list) { | 1131 | switch (list) { |
1136 | case CPUFREQ_TRANSITION_NOTIFIER: | 1132 | case CPUFREQ_TRANSITION_NOTIFIER: |
1137 | ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb); | 1133 | ret = blocking_notifier_chain_register( |
1134 | &cpufreq_transition_notifier_list, nb); | ||
1138 | break; | 1135 | break; |
1139 | case CPUFREQ_POLICY_NOTIFIER: | 1136 | case CPUFREQ_POLICY_NOTIFIER: |
1140 | ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb); | 1137 | ret = blocking_notifier_chain_register( |
1138 | &cpufreq_policy_notifier_list, nb); | ||
1141 | break; | 1139 | break; |
1142 | default: | 1140 | default: |
1143 | ret = -EINVAL; | 1141 | ret = -EINVAL; |
1144 | } | 1142 | } |
1145 | up_write(&cpufreq_notifier_rwsem); | ||
1146 | 1143 | ||
1147 | return ret; | 1144 | return ret; |
1148 | } | 1145 | } |
@@ -1157,24 +1154,24 @@ EXPORT_SYMBOL(cpufreq_register_notifier); | |||
1157 | * Remove a driver from the CPU frequency notifier list. | 1154 | * Remove a driver from the CPU frequency notifier list. |
1158 | * | 1155 | * |
1159 | * This function may sleep, and has the same return conditions as | 1156 | * This function may sleep, and has the same return conditions as |
1160 | * notifier_chain_unregister. | 1157 | * blocking_notifier_chain_unregister. |
1161 | */ | 1158 | */ |
1162 | int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) | 1159 | int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) |
1163 | { | 1160 | { |
1164 | int ret; | 1161 | int ret; |
1165 | 1162 | ||
1166 | down_write(&cpufreq_notifier_rwsem); | ||
1167 | switch (list) { | 1163 | switch (list) { |
1168 | case CPUFREQ_TRANSITION_NOTIFIER: | 1164 | case CPUFREQ_TRANSITION_NOTIFIER: |
1169 | ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb); | 1165 | ret = blocking_notifier_chain_unregister( |
1166 | &cpufreq_transition_notifier_list, nb); | ||
1170 | break; | 1167 | break; |
1171 | case CPUFREQ_POLICY_NOTIFIER: | 1168 | case CPUFREQ_POLICY_NOTIFIER: |
1172 | ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb); | 1169 | ret = blocking_notifier_chain_unregister( |
1170 | &cpufreq_policy_notifier_list, nb); | ||
1173 | break; | 1171 | break; |
1174 | default: | 1172 | default: |
1175 | ret = -EINVAL; | 1173 | ret = -EINVAL; |
1176 | } | 1174 | } |
1177 | up_write(&cpufreq_notifier_rwsem); | ||
1178 | 1175 | ||
1179 | return ret; | 1176 | return ret; |
1180 | } | 1177 | } |
@@ -1346,29 +1343,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
1346 | if (ret) | 1343 | if (ret) |
1347 | goto error_out; | 1344 | goto error_out; |
1348 | 1345 | ||
1349 | down_read(&cpufreq_notifier_rwsem); | ||
1350 | |||
1351 | /* adjust if necessary - all reasons */ | 1346 | /* adjust if necessary - all reasons */ |
1352 | notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, | 1347 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
1353 | policy); | 1348 | CPUFREQ_ADJUST, policy); |
1354 | 1349 | ||
1355 | /* adjust if necessary - hardware incompatibility*/ | 1350 | /* adjust if necessary - hardware incompatibility*/ |
1356 | notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE, | 1351 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
1357 | policy); | 1352 | CPUFREQ_INCOMPATIBLE, policy); |
1358 | 1353 | ||
1359 | /* verify the cpu speed can be set within this limit, | 1354 | /* verify the cpu speed can be set within this limit, |
1360 | which might be different to the first one */ | 1355 | which might be different to the first one */ |
1361 | ret = cpufreq_driver->verify(policy); | 1356 | ret = cpufreq_driver->verify(policy); |
1362 | if (ret) { | 1357 | if (ret) |
1363 | up_read(&cpufreq_notifier_rwsem); | ||
1364 | goto error_out; | 1358 | goto error_out; |
1365 | } | ||
1366 | 1359 | ||
1367 | /* notification of the new policy */ | 1360 | /* notification of the new policy */ |
1368 | notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, | 1361 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
1369 | policy); | 1362 | CPUFREQ_NOTIFY, policy); |
1370 | |||
1371 | up_read(&cpufreq_notifier_rwsem); | ||
1372 | 1363 | ||
1373 | data->min = policy->min; | 1364 | data->min = policy->min; |
1374 | data->max = policy->max; | 1365 | data->max = policy->max; |