ACPI : Create "idle=nomwait" bootparam
[deliverable/linux.git] / arch / x86 / kernel / process.c
index 68ad3539b143a57051d2b8b8f5939a474dac9917..4d629c62f4f8fbb993a49c0d5f12d7e88bbd94b5 100644 (file)
@@ -7,6 +7,12 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 #include <linux/clockchips.h>
+#include <asm/system.h>
+
+unsigned long idle_halt;
+EXPORT_SYMBOL(idle_halt);
+unsigned long idle_nomwait;
+EXPORT_SYMBOL(idle_nomwait);
 
 struct kmem_cache *task_xstate_cachep;
 
@@ -132,7 +138,7 @@ void cpu_idle_wait(void)
 {
        smp_mb();
        /* kick all the CPUs so that they exit out of pm_idle */
-       smp_call_function(do_nothing, NULL, 0, 1);
+       smp_call_function(do_nothing, NULL, 1);
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
@@ -267,17 +273,29 @@ static void c1e_idle(void)
 
                if (!cpu_isset(cpu, c1e_mask)) {
                        cpu_set(cpu, c1e_mask);
-                       /* Force broadcast so ACPI can not interfere */
+                       /*
+                        * Force broadcast so ACPI can not interfere. Needs
+                        * to run with interrupts enabled as it uses
+                        * smp_function_call.
+                        */
+                       local_irq_enable();
                        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
                                           &cpu);
                        printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
                               cpu);
+                       local_irq_disable();
                }
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+
                default_idle();
-               local_irq_disable();
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
-               local_irq_enable();
+
+               /*
+                * The switch back from broadcast mode needs to be
+                * called with interrupts disabled.
+                */
+                local_irq_disable();
+                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+                local_irq_enable();
        } else
                default_idle();
 }
@@ -313,7 +331,27 @@ static int __init idle_setup(char *str)
                pm_idle = poll_idle;
        } else if (!strcmp(str, "mwait"))
                force_mwait = 1;
-       else
+       else if (!strcmp(str, "halt")) {
+               /*
+                * When the boot option of idle=halt is added, halt is
+                * forced to be used for CPU idle. In such case CPU C2/C3
+                * won't be used again.
+                * To continue to load the CPU idle driver, don't touch
+                * the boot_option_idle_override.
+                */
+               pm_idle = default_idle;
+               idle_halt = 1;
+               return 0;
+       } else if (!strcmp(str, "nomwait")) {
+               /*
+                * If the boot option of "idle=nomwait" is added,
+                * it means that mwait will be disabled for CPU C2/C3
+                * states. In such case it won't touch the variable
+                * of boot_option_idle_override.
+                */
+               idle_nomwait = 1;
+               return 0;
+       } else
                return -1;
 
        boot_option_idle_override = 1;
This page took 0.038093 seconds and 5 git commands to generate.