diff options
Diffstat (limited to 'arch/powerpc/kernel/idle.c')
| -rw-r--r-- | arch/powerpc/kernel/idle.c | 95 | 
1 files changed, 36 insertions, 59 deletions
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 39a2baa6ad5..d7216c9abda 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -26,80 +26,57 @@  #include <linux/sysctl.h>  #include <linux/tick.h> -#include <asm/system.h>  #include <asm/processor.h>  #include <asm/cputable.h>  #include <asm/time.h>  #include <asm/machdep.h> +#include <asm/runlatch.h>  #include <asm/smp.h> -#ifdef CONFIG_HOTPLUG_CPU -#define cpu_should_die()	cpu_is_offline(smp_processor_id()) -#else -#define cpu_should_die()	0 -#endif + +unsigned long cpuidle_disable = IDLE_NO_OVERRIDE; +EXPORT_SYMBOL(cpuidle_disable);  static int __init powersave_off(char *arg)  {  	ppc_md.power_save = NULL; +	cpuidle_disable = IDLE_POWERSAVE_OFF;  	return 0;  }  __setup("powersave=off", powersave_off); -/* - * The body of the idle task. - */ -void cpu_idle(void) +#ifdef CONFIG_HOTPLUG_CPU +void arch_cpu_idle_dead(void)  { -	if (ppc_md.idle_loop) -		ppc_md.idle_loop();	/* doesn't return */ - -	set_thread_flag(TIF_POLLING_NRFLAG); -	while (1) { -		tick_nohz_stop_sched_tick(1); -		while (!need_resched() && !cpu_should_die()) { -			ppc64_runlatch_off(); - -			if (ppc_md.power_save) { -				clear_thread_flag(TIF_POLLING_NRFLAG); -				/* -				 * smp_mb is so clearing of TIF_POLLING_NRFLAG -				 * is ordered w.r.t. need_resched() test. -				 */ -				smp_mb(); -				local_irq_disable(); - -				/* Don't trace irqs off for idle */ -				stop_critical_timings(); - -				/* check again after disabling irqs */ -				if (!need_resched() && !cpu_should_die()) -					ppc_md.power_save(); - -				start_critical_timings(); - -				local_irq_enable(); -				set_thread_flag(TIF_POLLING_NRFLAG); - -			} else { -				/* -				 * Go into low thread priority and possibly -				 * low power mode. -				 */ -				HMT_low(); -				HMT_very_low(); -			} -		} +	sched_preempt_enable_no_resched(); +	cpu_die(); +} +#endif -		HMT_medium(); -		ppc64_runlatch_on(); -		tick_nohz_restart_sched_tick(); -		preempt_enable_no_resched(); -		if (cpu_should_die()) -			cpu_die(); -		schedule(); -		preempt_disable(); +void arch_cpu_idle(void) +{ +	ppc64_runlatch_off(); + +	if (ppc_md.power_save) { +		ppc_md.power_save(); +		/* +		 * Some power_save functions return with +		 * interrupts enabled, some don't. +		 */ +		if (irqs_disabled()) +			local_irq_enable(); +	} else { +		local_irq_enable(); +		/* +		 * Go into low thread priority and possibly +		 * low power mode. +		 */ +		HMT_low(); +		HMT_very_low();  	} + +	HMT_medium(); +	ppc64_runlatch_on();  }  int powersave_nap; @@ -108,7 +85,7 @@ int powersave_nap;  /*   * Register the sysctl to set/clear powersave_nap.   */ -static ctl_table powersave_nap_ctl_table[]={ +static struct ctl_table powersave_nap_ctl_table[] = {  	{  		.procname	= "powersave-nap",  		.data		= &powersave_nap, @@ -118,7 +95,7 @@ static ctl_table powersave_nap_ctl_table[]={  	},  	{}  }; -static ctl_table powersave_nap_sysctl_root[] = { +static struct ctl_table powersave_nap_sysctl_root[] = {  	{  		.procname	= "kernel",  		.mode		= 0555,  | 
