diff options
author | Len Brown <len.brown@intel.com> | 2011-04-02 01:34:59 +0200 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-08-04 01:06:37 +0200 |
commit | a0bfa1373859e9d11dc92561a8667588803e42d8 (patch) | |
tree | ef5768a313ac16a211830efc3edb9ca95487cb6a /drivers/cpuidle | |
parent | x86 idle: move mwait_idle_with_hints() to where it is used (diff) | |
download | linux-a0bfa1373859e9d11dc92561a8667588803e42d8.tar.xz linux-a0bfa1373859e9d11dc92561a8667588803e42d8.zip |
cpuidle: stop depending on pm_idle
cpuidle users should call cpuidle_call_idle() directly
rather than via (pm_idle)() function pointer.
Architecture may choose to continue using (pm_idle)(),
but cpuidle need not depend on it:
my_arch_cpu_idle()
...
if(cpuidle_call_idle())
pm_idle();
cc: Kevin Hilman <khilman@deeprootsystems.com>
cc: Paul Mundt <lethal@linux-sh.org>
cc: x86@kernel.org
Acked-by: H. Peter Anvin <hpa@linux.intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 041df0b056b2..d4c542372886 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -25,10 +25,10 @@ DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices); DEFINE_MUTEX(cpuidle_lock); LIST_HEAD(cpuidle_detected_devices); -static void (*pm_idle_old)(void); static int enabled_devices; static int off __read_mostly; +static int initialized __read_mostly; int cpuidle_disabled(void) { @@ -56,25 +56,23 @@ static int __cpuidle_register_device(struct cpuidle_device *dev); * cpuidle_idle_call - the main idle loop * * NOTE: no locks or semaphores should be used here + * return non-zero on failure */ -static void cpuidle_idle_call(void) +int cpuidle_idle_call(void) { struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_state *target_state; int next_state; + if (off) + return -ENODEV; + + if (!initialized) + return -ENODEV; + /* check if the device is ready */ - if (!dev || !dev->enabled) { - if (pm_idle_old) - pm_idle_old(); - else -#if defined(CONFIG_ARCH_HAS_DEFAULT_IDLE) - default_idle(); -#else - local_irq_enable(); -#endif - return; - } + if (!dev || !dev->enabled) + return -EBUSY; #if 0 /* shows regressions, re-enable for 2.6.29 */ @@ -99,7 +97,7 @@ static void cpuidle_idle_call(void) next_state = cpuidle_curr_governor->select(dev); if (need_resched()) { local_irq_enable(); - return; + return 0; } target_state = &dev->states[next_state]; @@ -124,6 +122,8 @@ static void cpuidle_idle_call(void) /* give the governor an opportunity to reflect on the outcome */ if (cpuidle_curr_governor->reflect) cpuidle_curr_governor->reflect(dev); + + return 0; } /** @@ -131,10 +131,10 @@ static void cpuidle_idle_call(void) */ void cpuidle_install_idle_handler(void) { - if (enabled_devices && (pm_idle != cpuidle_idle_call)) { + if (enabled_devices) { /* Make sure all changes finished before we switch to new idle */ smp_wmb(); - pm_idle = cpuidle_idle_call; + initialized = 1; } } @@ -143,8 +143,8 @@ void cpuidle_install_idle_handler(void) */ void cpuidle_uninstall_idle_handler(void) { - if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) { - pm_idle = pm_idle_old; + if (enabled_devices) { + initialized = 0; cpuidle_kick_cpus(); } } @@ -440,8 +440,6 @@ static int __init cpuidle_init(void) if (cpuidle_disabled()) return -ENODEV; - pm_idle_old = pm_idle; - ret = cpuidle_add_class_sysfs(&cpu_sysdev_class); if (ret) return ret; |