aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r--drivers/cpufreq/cpufreq.c61
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 */
55static struct notifier_block *cpufreq_policy_notifier_list; 55static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
56static struct notifier_block *cpufreq_transition_notifier_list; 56static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list);
57static DECLARE_RWSEM (cpufreq_notifier_rwsem);
58 57
59 58
60static LIST_HEAD(cpufreq_governor_list); 59static 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}
284EXPORT_SYMBOL_GPL(cpufreq_notify_transition); 280EXPORT_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 */
1130int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) 1127int 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 */
1162int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) 1159int 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;