diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq_stats.c')
-rw-r--r-- | drivers/cpufreq/cpufreq_stats.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 741b6b191e6a..3597f25d5efa 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/percpu.h> | 19 | #include <linux/percpu.h> |
20 | #include <linux/kobject.h> | 20 | #include <linux/kobject.h> |
21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include <linux/notifier.h> | ||
22 | #include <asm/cputime.h> | 23 | #include <asm/cputime.h> |
23 | 24 | ||
24 | static spinlock_t cpufreq_stats_lock; | 25 | static spinlock_t cpufreq_stats_lock; |
@@ -298,6 +299,27 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, | |||
298 | return 0; | 299 | return 0; |
299 | } | 300 | } |
300 | 301 | ||
302 | static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, | ||
303 | unsigned long action, void *hcpu) | ||
304 | { | ||
305 | unsigned int cpu = (unsigned long)hcpu; | ||
306 | |||
307 | switch (action) { | ||
308 | case CPU_ONLINE: | ||
309 | cpufreq_update_policy(cpu); | ||
310 | break; | ||
311 | case CPU_DEAD: | ||
312 | cpufreq_stats_free_table(cpu); | ||
313 | break; | ||
314 | } | ||
315 | return NOTIFY_OK; | ||
316 | } | ||
317 | |||
318 | static struct notifier_block cpufreq_stat_cpu_notifier = | ||
319 | { | ||
320 | .notifier_call = cpufreq_stat_cpu_callback, | ||
321 | }; | ||
322 | |||
301 | static struct notifier_block notifier_policy_block = { | 323 | static struct notifier_block notifier_policy_block = { |
302 | .notifier_call = cpufreq_stat_notifier_policy | 324 | .notifier_call = cpufreq_stat_notifier_policy |
303 | }; | 325 | }; |
@@ -311,6 +333,7 @@ __init cpufreq_stats_init(void) | |||
311 | { | 333 | { |
312 | int ret; | 334 | int ret; |
313 | unsigned int cpu; | 335 | unsigned int cpu; |
336 | |||
314 | spin_lock_init(&cpufreq_stats_lock); | 337 | spin_lock_init(&cpufreq_stats_lock); |
315 | if ((ret = cpufreq_register_notifier(¬ifier_policy_block, | 338 | if ((ret = cpufreq_register_notifier(¬ifier_policy_block, |
316 | CPUFREQ_POLICY_NOTIFIER))) | 339 | CPUFREQ_POLICY_NOTIFIER))) |
@@ -323,20 +346,31 @@ __init cpufreq_stats_init(void) | |||
323 | return ret; | 346 | return ret; |
324 | } | 347 | } |
325 | 348 | ||
326 | for_each_cpu(cpu) | 349 | register_cpu_notifier(&cpufreq_stat_cpu_notifier); |
327 | cpufreq_update_policy(cpu); | 350 | lock_cpu_hotplug(); |
351 | for_each_online_cpu(cpu) { | ||
352 | cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, | ||
353 | (void *)(long)cpu); | ||
354 | } | ||
355 | unlock_cpu_hotplug(); | ||
328 | return 0; | 356 | return 0; |
329 | } | 357 | } |
330 | static void | 358 | static void |
331 | __exit cpufreq_stats_exit(void) | 359 | __exit cpufreq_stats_exit(void) |
332 | { | 360 | { |
333 | unsigned int cpu; | 361 | unsigned int cpu; |
362 | |||
334 | cpufreq_unregister_notifier(¬ifier_policy_block, | 363 | cpufreq_unregister_notifier(¬ifier_policy_block, |
335 | CPUFREQ_POLICY_NOTIFIER); | 364 | CPUFREQ_POLICY_NOTIFIER); |
336 | cpufreq_unregister_notifier(¬ifier_trans_block, | 365 | cpufreq_unregister_notifier(¬ifier_trans_block, |
337 | CPUFREQ_TRANSITION_NOTIFIER); | 366 | CPUFREQ_TRANSITION_NOTIFIER); |
338 | for_each_cpu(cpu) | 367 | unregister_cpu_notifier(&cpufreq_stat_cpu_notifier); |
339 | cpufreq_stats_free_table(cpu); | 368 | lock_cpu_hotplug(); |
369 | for_each_online_cpu(cpu) { | ||
370 | cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD, | ||
371 | (void *)(long)cpu); | ||
372 | } | ||
373 | unlock_cpu_hotplug(); | ||
340 | } | 374 | } |
341 | 375 | ||
342 | MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>"); | 376 | MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>"); |