diff options
author | Ashok Raj <ashok.raj@intel.com> | 2005-10-30 17:59:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 20:37:14 -0500 |
commit | c32b6b8e524d2c337767d312814484d9289550cf (patch) | |
tree | 02e634b0b48db6eccc8774369366daa1893921ea /drivers/cpufreq/cpufreq_stats.c | |
parent | d434fca737bee0862625c2377b987a7713b6b487 (diff) |
[PATCH] create and destroy cpufreq sysfs entries based on cpu notifiers
cpufreq entries in sysfs should only be populated when CPU is online state.
When we either boot with maxcpus=x and then boot the other cpus by echoing
to sysfs online file, these entries should be created and destroyed when
CPU_DEAD is notified. Same treatement as cache entries under sysfs.
We place the processor in the lowest frequency, so hw managed P-State
transitions can still work on the other threads to save power.
Primary goal was to just make these directories appear/disapper dynamically.
There is one in this patch i had to do, which i really dont like myself but
probably best if someone handling the cpufreq infrastructure could give
this code right treatment if this is not acceptable. I guess its probably
good for the first cut.
- Converting lock_cpu_hotplug()/unlock_cpu_hotplug() to disable/enable preempt.
The locking was smack in the middle of the notification path, when the
hotplug is already holding the lock. I tried another solution to avoid this
so avoid taking locks if we know we are from notification path. The solution
was getting very ugly and i decided this was probably good for this iteration
until someone who understands cpufreq could do a better job than me.
(akpm: export cpucontrol to GPL modules: drivers/cpufreq/cpufreq_stats.c now
does lock_cpu_hotplug())
Signed-off-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: Dave Jones <davej@codemonkey.org.uk>
Cc: Zwane Mwaikambo <zwane@holomorphy.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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>"); |