diff options
Diffstat (limited to 'arch/sh/kernel/idle.c')
| -rw-r--r-- | arch/sh/kernel/idle.c | 78 |
1 files changed, 29 insertions, 49 deletions
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index fe59ccfc115..be616ee0cf8 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -1,7 +1,7 @@ /* * The idle loop for all SuperH platforms. * - * Copyright (C) 2002 - 2008 Paul Mundt + * Copyright (C) 2002 - 2009 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -15,67 +15,47 @@ #include <linux/preempt.h> #include <linux/thread_info.h> #include <linux/irqflags.h> +#include <linux/smp.h> +#include <linux/atomic.h> #include <asm/pgalloc.h> -#include <asm/system.h> -#include <asm/atomic.h> +#include <asm/smp.h> +#include <asm/bl_bit.h> -static int hlt_counter; -void (*pm_idle)(void); -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); +static void (*sh_idle)(void); -static int __init nohlt_setup(char *__unused) +void default_idle(void) { - hlt_counter = 1; - return 1; + set_bl_bit(); + local_irq_enable(); + /* Isn't this racy ? */ + cpu_sleep(); + clear_bl_bit(); } -__setup("nohlt", nohlt_setup); -static int __init hlt_setup(char *__unused) +void arch_cpu_idle_dead(void) { - hlt_counter = 0; - return 1; + play_dead(); } -__setup("hlt", hlt_setup); -static void default_idle(void) +void arch_cpu_idle(void) { - if (!hlt_counter) { - clear_thread_flag(TIF_POLLING_NRFLAG); - smp_mb__after_clear_bit(); - set_bl_bit(); - stop_critical_timings(); - - while (!need_resched()) - cpu_sleep(); - - start_critical_timings(); - clear_bl_bit(); - set_thread_flag(TIF_POLLING_NRFLAG); - } else - while (!need_resched()) - cpu_relax(); + sh_idle(); } -void cpu_idle(void) +void __init select_idle_routine(void) { - set_thread_flag(TIF_POLLING_NRFLAG); - - /* endless idle loop with no priority at all */ - while (1) { - void (*idle)(void) = pm_idle; - - if (!idle) - idle = default_idle; + /* + * If a platform has set its own idle routine, leave it alone. + */ + if (!sh_idle) + sh_idle = default_idle; +} - tick_nohz_stop_sched_tick(1); - while (!need_resched()) - idle(); - tick_nohz_restart_sched_tick(); +void stop_this_cpu(void *unused) +{ + local_irq_disable(); + set_cpu_online(smp_processor_id(), false); - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - check_pgt_cache(); - } + for (;;) + cpu_sleep(); } |
