sh: sr.bl toggling around idle sleep.
authorPaul Mundt <lethal@linux-sh.org>
Mon, 14 May 2007 10:39:48 +0000 (19:39 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 21 May 2007 05:34:25 +0000 (14:34 +0900)
As pointed out by Saito-san, without the sr.bl manipulation we can
occasionally hit delays in the idle loop due to interrupt handling, so
ensure that interrupts are blocked before going to sleep.

At the same time, we throw in TIF_POLLING_NRFLAG for the !hlt_counter
case (primarily used by the ST-40 parts).

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/kernel/process.c

index 6b4f5748d0be682a2b6334ca7d6f5ccc406be271..a11e2aa73cbc0888aeafb1bb74193d98a4293ad3 100644 (file)
@@ -26,8 +26,6 @@
 static int hlt_counter;
 int ubc_usercnt = 0;
 
-#define HARD_IDLE_TIMEOUT (HZ / 3)
-
 void (*pm_idle)(void);
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
@@ -44,16 +42,39 @@ void enable_hlt(void)
 }
 EXPORT_SYMBOL(enable_hlt);
 
+static int __init nohlt_setup(char *__unused)
+{
+       hlt_counter = 1;
+       return 1;
+}
+__setup("nohlt", nohlt_setup);
+
+static int __init hlt_setup(char *__unused)
+{
+       hlt_counter = 0;
+       return 1;
+}
+__setup("hlt", hlt_setup);
+
 void default_idle(void)
 {
-       if (!hlt_counter)
-               cpu_sleep();
-       else
-               cpu_relax();
+       if (!hlt_counter) {
+               clear_thread_flag(TIF_POLLING_NRFLAG);
+               smp_mb__after_clear_bit();
+               set_bl_bit();
+               while (!need_resched())
+                       cpu_sleep();
+               clear_bl_bit();
+               set_thread_flag(TIF_POLLING_NRFLAG);
+       } else
+               while (!need_resched())
+                       cpu_relax();
 }
 
 void cpu_idle(void)
 {
+       set_thread_flag(TIF_POLLING_NRFLAG);
+
        /* endless idle loop with no priority at all */
        while (1) {
                void (*idle)(void) = pm_idle;