|
@@ -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;
|