Commit c1e3b377ad48febba6f91b8ae42c44ee4d4ab45e
Committed by
Andi Kleen
1 parent
5b53496a5a
Exists in
master
and in
20 other branches
ACPI: Create "idle=halt" bootparam
"idle=halt" limits the idle loop to using the halt instruction. No MWAIT, no IO accesses, no C-states deeper than C1. If something is broken in the idle code, "idle=halt" is a less severe workaround than "idle=poll" which disables all power savings. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
Showing 6 changed files with 45 additions and 2 deletions Side-by-side Diff
Documentation/kernel-parameters.txt
... | ... | @@ -818,7 +818,7 @@ |
818 | 818 | See Documentation/ide/ide.txt. |
819 | 819 | |
820 | 820 | idle= [X86] |
821 | - Format: idle=poll or idle=mwait | |
821 | + Format: idle=poll or idle=mwait, idle=halt | |
822 | 822 | Poll forces a polling idle loop that can slightly improves the performance |
823 | 823 | of waking up a idle CPU, but will use a lot of power and make the system |
824 | 824 | run hot. Not recommended. |
... | ... | @@ -826,6 +826,8 @@ |
826 | 826 | to not use it because it doesn't save as much power as a normal idle |
827 | 827 | loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same |
828 | 828 | as idle=poll. |
829 | + idle=halt. Halt is forced to be used for CPU idle. | |
830 | + In such case C2/C3 won't be used again. | |
829 | 831 | |
830 | 832 | ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem |
831 | 833 | Claim all unknown PCI IDE storage controllers. |
arch/ia64/kernel/process.c
arch/x86/kernel/process.c
... | ... | @@ -7,7 +7,11 @@ |
7 | 7 | #include <linux/module.h> |
8 | 8 | #include <linux/pm.h> |
9 | 9 | #include <linux/clockchips.h> |
10 | +#include <asm/system.h> | |
10 | 11 | |
12 | +unsigned long idle_halt; | |
13 | +EXPORT_SYMBOL(idle_halt); | |
14 | + | |
11 | 15 | struct kmem_cache *task_xstate_cachep; |
12 | 16 | |
13 | 17 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
... | ... | @@ -325,7 +329,18 @@ |
325 | 329 | pm_idle = poll_idle; |
326 | 330 | } else if (!strcmp(str, "mwait")) |
327 | 331 | force_mwait = 1; |
328 | - else | |
332 | + else if (!strcmp(str, "halt")) { | |
333 | + /* | |
334 | + * When the boot option of idle=halt is added, halt is | |
335 | + * forced to be used for CPU idle. In such case CPU C2/C3 | |
336 | + * won't be used again. | |
337 | + * To continue to load the CPU idle driver, don't touch | |
338 | + * the boot_option_idle_override. | |
339 | + */ | |
340 | + pm_idle = default_idle; | |
341 | + idle_halt = 1; | |
342 | + return 0; | |
343 | + } else | |
329 | 344 | return -1; |
330 | 345 | |
331 | 346 | boot_option_idle_override = 1; |
drivers/acpi/processor_idle.c
... | ... | @@ -41,6 +41,7 @@ |
41 | 41 | #include <linux/pm_qos_params.h> |
42 | 42 | #include <linux/clockchips.h> |
43 | 43 | #include <linux/cpuidle.h> |
44 | +#include <linux/cpuidle.h> | |
44 | 45 | |
45 | 46 | /* |
46 | 47 | * Include the apic definitions for x86 to have the APIC timer related defines |
... | ... | @@ -57,6 +58,7 @@ |
57 | 58 | |
58 | 59 | #include <acpi/acpi_bus.h> |
59 | 60 | #include <acpi/processor.h> |
61 | +#include <asm/processor.h> | |
60 | 62 | |
61 | 63 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 |
62 | 64 | #define ACPI_PROCESSOR_CLASS "processor" |
... | ... | @@ -955,6 +957,17 @@ |
955 | 957 | } else { |
956 | 958 | continue; |
957 | 959 | } |
960 | + if (cx.type == ACPI_STATE_C1 && idle_halt) { | |
961 | + /* | |
962 | + * In most cases the C1 space_id obtained from | |
963 | + * _CST object is FIXED_HARDWARE access mode. | |
964 | + * But when the option of idle=halt is added, | |
965 | + * the entry_method type should be changed from | |
966 | + * CSTATE_FFH to CSTATE_HALT. | |
967 | + */ | |
968 | + cx.entry_method = ACPI_CSTATE_HALT; | |
969 | + snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); | |
970 | + } | |
958 | 971 | } else { |
959 | 972 | snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x", |
960 | 973 | cx.address); |
... | ... | @@ -1780,6 +1793,15 @@ |
1780 | 1793 | return 0; |
1781 | 1794 | |
1782 | 1795 | if (!first_run) { |
1796 | + if (idle_halt) { | |
1797 | + /* | |
1798 | + * When the boot option of "idle=halt" is added, halt | |
1799 | + * is used for CPU IDLE. | |
1800 | + * In such case C2/C3 is meaningless. So the max_cstate | |
1801 | + * is set to one. | |
1802 | + */ | |
1803 | + max_cstate = 1; | |
1804 | + } | |
1783 | 1805 | dmi_check_system(processor_power_dmi_table); |
1784 | 1806 | max_cstate = acpi_processor_cstate_check(max_cstate); |
1785 | 1807 | if (max_cstate < ACPI_C_STATES_MAX) |
include/asm-ia64/processor.h
include/asm-x86/processor.h