fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / ppc / kernel / idle.c
index 5adb6be..1be3ca5 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/cpu.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -30,6 +32,7 @@
 #include <asm/cache.h>
 #include <asm/cputable.h>
 #include <asm/machdep.h>
+#include <asm/smp.h>
 
 void default_idle(void)
 {
@@ -43,25 +46,67 @@ void default_idle(void)
 #ifdef CONFIG_SMP
                else {
                        set_thread_flag(TIF_POLLING_NRFLAG);
-                       while (!need_resched())
+                       while (!need_resched() &&
+                                       !cpu_is_offline(smp_processor_id()))
                                barrier();
                        clear_thread_flag(TIF_POLLING_NRFLAG);
                }
 #endif
        }
-       if (need_resched())
-               schedule();
 }
 
 /*
  * The body of the idle task.
  */
-int cpu_idle(void)
+void cpu_idle(void)
+{
+       int cpu = smp_processor_id();
+
+       for (;;) {
+               while (!need_resched()) {
+                       if (ppc_md.idle != NULL)
+                               ppc_md.idle();
+                       else
+                               default_idle();
+               }
+
+               if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+                       cpu_die();
+               preempt_enable_no_resched();
+               schedule();
+               preempt_disable();
+       }
+}
+
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
+/*
+ * Register the sysctl to set/clear powersave_nap.
+ */
+extern int powersave_nap;
+
+static 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,
+       },
+       { 0, },
+};
+static ctl_table powersave_nap_sysctl_root[] = {
+       { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
+       { 0,},
+};
+
+static int __init
+register_powersave_nap_sysctl(void)
 {
-       for (;;)
-               if (ppc_md.idle != NULL)
-                       ppc_md.idle();
-               else
-                       default_idle();
+       register_sysctl_table(powersave_nap_sysctl_root, 0);
+
        return 0;
 }
+
+__initcall(register_powersave_nap_sysctl);
+#endif