diff options
| author | Takashi Iwai <tiwai@suse.de> | 2011-08-08 14:30:29 +0200 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2011-08-08 14:30:29 +0200 | 
| commit | 0a2d31b62dba9b5b92a38c67c9cc42630513662a (patch) | |
| tree | f755d74ec85248de645e10c45ed1a2ed467530f6 /drivers/cpuidle/cpuidle.c | |
| parent | 8039290a91c5dc4414093c086987a5d7738fe2fd (diff) | |
| parent | df944f66784e6d4f2f50739263a4947885d8b6ae (diff) | |
Merge branch 'fix/kconfig' into for-linus
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
| -rw-r--r-- | drivers/cpuidle/cpuidle.c | 50 | 
1 files changed, 31 insertions, 19 deletions
| diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index bf5092455a8f..d4c542372886 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -25,9 +25,19 @@ 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) +{ +	return off; +} +void disable_cpuidle(void) +{ +	off = 1; +}  #if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)  static void cpuidle_kick_cpus(void) @@ -46,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 */ @@ -89,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]; @@ -114,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;  }  /** @@ -121,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;  	}  } @@ -133,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();  	}  } @@ -427,7 +437,8 @@ static int __init cpuidle_init(void)  {  	int ret; -	pm_idle_old = pm_idle; +	if (cpuidle_disabled()) +		return -ENODEV;  	ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);  	if (ret) @@ -438,4 +449,5 @@ static int __init cpuidle_init(void)  	return 0;  } +module_param(off, int, 0444);  core_initcall(cpuidle_init); | 
