From 8c64701a307df392383d42015757743482f310a7 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 5 Aug 2011 10:46:06 +1000 Subject: [PATCH] Revert "cpuidle: stop depending on pm_idle" This reverts commit a0bfa1373859e9d11dc92561a8667588803e42d8. --- arch/arm/kernel/process.c | 4 +--- arch/sh/kernel/idle.c | 6 ++---- arch/x86/kernel/process_32.c | 4 +--- arch/x86/kernel/process_64.c | 4 +--- drivers/cpuidle/cpuidle.c | 38 +++++++++++++++++++----------------- include/linux/cpuidle.h | 2 -- 6 files changed, 25 insertions(+), 33 deletions(-) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index d7ee0d4c072d..5e1e54197227 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -197,8 +196,7 @@ void cpu_idle(void) cpu_relax(); } else { stop_critical_timings(); - if (cpuidle_call_idle()) - pm_idle(); + pm_idle(); start_critical_timings(); /* * This will eventually be removed - pm_idle diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 3c45de1db716..84db0d6ccd0d 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -16,13 +16,12 @@ #include #include #include -#include #include #include #include #include -static void (*pm_idle)(void); +void (*pm_idle)(void) = NULL; static int hlt_counter; @@ -101,8 +100,7 @@ void cpu_idle(void) local_irq_disable(); /* Don't trace irqs off for idle */ stop_critical_timings(); - if (cpuidle_call_idle()) - pm_idle(); + pm_idle(); /* * Sanity check to ensure that pm_idle() returns * with IRQs enabled diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 7a3b65107a27..a3d0dc59067b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -110,8 +109,7 @@ void cpu_idle(void) local_irq_disable(); /* Don't trace irqs off for idle */ stop_critical_timings(); - if (cpuidle_idle_call()) - pm_idle(); + pm_idle(); start_critical_timings(); } tick_nohz_restart_sched_tick(); diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index f693e44e1bf6..ca6f7ab8df33 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -137,8 +136,7 @@ void cpu_idle(void) enter_idle(); /* Don't trace irqs off for idle */ stop_critical_timings(); - if (cpuidle_idle_call()) - pm_idle(); + pm_idle(); start_critical_timings(); /* In many cases the interrupt that ended idle diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d4c542372886..041df0b056b2 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,23 +56,25 @@ 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 */ -int cpuidle_idle_call(void) +static void 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) - return -EBUSY; + 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 0 /* shows regressions, re-enable for 2.6.29 */ @@ -97,7 +99,7 @@ int cpuidle_idle_call(void) next_state = cpuidle_curr_governor->select(dev); if (need_resched()) { local_irq_enable(); - return 0; + return; } target_state = &dev->states[next_state]; @@ -122,8 +124,6 @@ int 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 @@ int cpuidle_idle_call(void) */ void cpuidle_install_idle_handler(void) { - if (enabled_devices) { + if (enabled_devices && (pm_idle != cpuidle_idle_call)) { /* Make sure all changes finished before we switch to new idle */ smp_wmb(); - initialized = 1; + pm_idle = cpuidle_idle_call; } } @@ -143,8 +143,8 @@ void cpuidle_install_idle_handler(void) */ void cpuidle_uninstall_idle_handler(void) { - if (enabled_devices) { - initialized = 0; + if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) { + pm_idle = pm_idle_old; cpuidle_kick_cpus(); } } @@ -440,6 +440,8 @@ 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; diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index b51629e15cfc..b89f67da919e 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -123,7 +123,6 @@ struct cpuidle_driver { #ifdef CONFIG_CPU_IDLE extern void disable_cpuidle(void); -extern int cpuidle_idle_call(void); extern int cpuidle_register_driver(struct cpuidle_driver *drv); struct cpuidle_driver *cpuidle_get_driver(void); @@ -138,7 +137,6 @@ extern void cpuidle_disable_device(struct cpuidle_device *dev); #else static inline void disable_cpuidle(void) { } -static inline int cpuidle_idle_call(void) { return -ENODEV; } static inline int cpuidle_register_driver(struct cpuidle_driver *drv) {return -ENODEV; } -- 2.39.5