diff options
Diffstat (limited to 'arch/powerpc/kernel/idle.c')
| -rw-r--r-- | arch/powerpc/kernel/idle.c | 103 |
1 files changed, 45 insertions, 58 deletions
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 8994af327b4..d7216c9abda 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -24,75 +24,59 @@ #include <linux/smp.h> #include <linux/cpu.h> #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()) && \ - system_state == SYSTEM_RUNNING) -#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) { - 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(); - - /* check again after disabling irqs */ - if (!need_resched() && !cpu_should_die()) - ppc_md.power_save(); - - local_irq_enable(); - set_thread_flag(TIF_POLLING_NRFLAG); + sched_preempt_enable_no_resched(); + cpu_die(); +} +#endif - } else { - /* - * Go into low thread priority and possibly - * low power mode. - */ - HMT_low(); - HMT_very_low(); - } - } +void arch_cpu_idle(void) +{ + ppc64_runlatch_off(); - HMT_medium(); - ppc64_runlatch_on(); - if (cpu_should_die()) - cpu_die(); - preempt_enable_no_resched(); - schedule(); - preempt_disable(); + 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; @@ -101,26 +85,29 @@ 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[] = { { - .ctl_name = KERN_PPC_POWERSAVE_NAP, .procname = "powersave-nap", .data = &powersave_nap, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = proc_dointvec, }, - { 0, }, + {} }; -static ctl_table powersave_nap_sysctl_root[] = { - { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, }, - { 0,}, +static struct ctl_table powersave_nap_sysctl_root[] = { + { + .procname = "kernel", + .mode = 0555, + .child = powersave_nap_ctl_table, + }, + {} }; static int __init register_powersave_nap_sysctl(void) { - register_sysctl_table(powersave_nap_sysctl_root, 0); + register_sysctl_table(powersave_nap_sysctl_root); return 0; } |
