diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2010-07-23 16:59:09 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-07-24 23:26:09 -0400 |
commit | 72ad5d77fb981963edae15eee8196c80238f5ed0 (patch) | |
tree | a6fa9a0b9ba924fd2dd91debf3e8ab04e8084338 | |
parent | b37fa16e78d6f9790462b3181602a26b5af36260 (diff) |
ACPI / Sleep: Allow the NVS saving to be skipped during suspend to RAM
Commit 2a6b69765ad794389f2fc3e14a0afa1a995221c2
(ACPI: Store NVS state even when entering suspend to RAM) caused the
ACPI suspend code save the NVS area during suspend and restore it
during resume unconditionally, although it is known that some systems
need to use acpi_sleep=s4_nonvs for hibernation to work. To allow
the affected systems to avoid saving and restoring the NVS area
during suspend to RAM and resume, introduce kernel command line
option acpi_sleep=nonvs and make acpi_sleep=s4_nonvs work as its
alias temporarily (add acpi_sleep=s4_nonvs to the feature removal
file).
Addresses https://bugzilla.kernel.org/show_bug.cgi?id=16396 .
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Reported-and-tested-by: tomas m <tmezzadra@gmail.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | Documentation/feature-removal-schedule.txt | 7 | ||||
-rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 9 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 35 | ||||
-rw-r--r-- | include/linux/acpi.h | 2 |
5 files changed, 34 insertions, 23 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index c268783bc4e7..1571c0c83dba 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -647,3 +647,10 @@ Who: Stefan Richter <stefanr@s5r6.in-berlin.de> | |||
647 | 647 | ||
648 | ---------------------------- | 648 | ---------------------------- |
649 | 649 | ||
650 | What: The acpi_sleep=s4_nonvs command line option | ||
651 | When: 2.6.37 | ||
652 | Files: arch/x86/kernel/acpi/sleep.c | ||
653 | Why: superseded by acpi_sleep=nonvs | ||
654 | Who: Rafael J. Wysocki <rjw@sisk.pl> | ||
655 | |||
656 | ---------------------------- | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4ddb58df081e..2b2407d9a6d0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -254,8 +254,8 @@ and is between 256 and 4096 characters. It is defined in the file | |||
254 | control method, with respect to putting devices into | 254 | control method, with respect to putting devices into |
255 | low power states, to be enforced (the ACPI 2.0 ordering | 255 | low power states, to be enforced (the ACPI 2.0 ordering |
256 | of _PTS is used by default). | 256 | of _PTS is used by default). |
257 | s4_nonvs prevents the kernel from saving/restoring the | 257 | nonvs prevents the kernel from saving/restoring the |
258 | ACPI NVS memory during hibernation. | 258 | ACPI NVS memory during suspend/hibernation and resume. |
259 | sci_force_enable causes the kernel to set SCI_EN directly | 259 | sci_force_enable causes the kernel to set SCI_EN directly |
260 | on resume from S1/S3 (which is against the ACPI spec, | 260 | on resume from S1/S3 (which is against the ACPI spec, |
261 | but some broken systems don't work without it). | 261 | but some broken systems don't work without it). |
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 82e508677b91..fcc3c61fdecc 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
@@ -157,9 +157,14 @@ static int __init acpi_sleep_setup(char *str) | |||
157 | #ifdef CONFIG_HIBERNATION | 157 | #ifdef CONFIG_HIBERNATION |
158 | if (strncmp(str, "s4_nohwsig", 10) == 0) | 158 | if (strncmp(str, "s4_nohwsig", 10) == 0) |
159 | acpi_no_s4_hw_signature(); | 159 | acpi_no_s4_hw_signature(); |
160 | if (strncmp(str, "s4_nonvs", 8) == 0) | 160 | if (strncmp(str, "s4_nonvs", 8) == 0) { |
161 | acpi_s4_no_nvs(); | 161 | pr_warning("ACPI: acpi_sleep=s4_nonvs is deprecated, " |
162 | "please use acpi_sleep=nonvs instead"); | ||
163 | acpi_nvs_nosave(); | ||
164 | } | ||
162 | #endif | 165 | #endif |
166 | if (strncmp(str, "nonvs", 5) == 0) | ||
167 | acpi_nvs_nosave(); | ||
163 | if (strncmp(str, "old_ordering", 12) == 0) | 168 | if (strncmp(str, "old_ordering", 12) == 0) |
164 | acpi_old_suspend_ordering(); | 169 | acpi_old_suspend_ordering(); |
165 | str = strchr(str, ','); | 170 | str = strchr(str, ','); |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 5b7c52e4a00f..2862c781b372 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -82,6 +82,20 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * The ACPI specification wants us to save NVS memory regions during hibernation | ||
86 | * and to restore them during the subsequent resume. Windows does that also for | ||
87 | * suspend to RAM. However, it is known that this mechanism does not work on | ||
88 | * all machines, so we allow the user to disable it with the help of the | ||
89 | * 'acpi_sleep=nonvs' kernel command line option. | ||
90 | */ | ||
91 | static bool nvs_nosave; | ||
92 | |||
93 | void __init acpi_nvs_nosave(void) | ||
94 | { | ||
95 | nvs_nosave = true; | ||
96 | } | ||
97 | |||
98 | /* | ||
85 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the | 99 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the |
86 | * user to request that behavior by using the 'acpi_old_suspend_ordering' | 100 | * user to request that behavior by using the 'acpi_old_suspend_ordering' |
87 | * kernel command line option that causes the following variable to be set. | 101 | * kernel command line option that causes the following variable to be set. |
@@ -197,8 +211,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state) | |||
197 | u32 acpi_state = acpi_suspend_states[pm_state]; | 211 | u32 acpi_state = acpi_suspend_states[pm_state]; |
198 | int error = 0; | 212 | int error = 0; |
199 | 213 | ||
200 | error = suspend_nvs_alloc(); | 214 | error = nvs_nosave ? 0 : suspend_nvs_alloc(); |
201 | |||
202 | if (error) | 215 | if (error) |
203 | return error; | 216 | return error; |
204 | 217 | ||
@@ -388,20 +401,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
388 | #endif /* CONFIG_SUSPEND */ | 401 | #endif /* CONFIG_SUSPEND */ |
389 | 402 | ||
390 | #ifdef CONFIG_HIBERNATION | 403 | #ifdef CONFIG_HIBERNATION |
391 | /* | ||
392 | * The ACPI specification wants us to save NVS memory regions during hibernation | ||
393 | * and to restore them during the subsequent resume. However, it is not certain | ||
394 | * if this mechanism is going to work on all machines, so we allow the user to | ||
395 | * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line | ||
396 | * option. | ||
397 | */ | ||
398 | static bool s4_no_nvs; | ||
399 | |||
400 | void __init acpi_s4_no_nvs(void) | ||
401 | { | ||
402 | s4_no_nvs = true; | ||
403 | } | ||
404 | |||
405 | static unsigned long s4_hardware_signature; | 404 | static unsigned long s4_hardware_signature; |
406 | static struct acpi_table_facs *facs; | 405 | static struct acpi_table_facs *facs; |
407 | static bool nosigcheck; | 406 | static bool nosigcheck; |
@@ -415,7 +414,7 @@ static int acpi_hibernation_begin(void) | |||
415 | { | 414 | { |
416 | int error; | 415 | int error; |
417 | 416 | ||
418 | error = s4_no_nvs ? 0 : suspend_nvs_alloc(); | 417 | error = nvs_nosave ? 0 : suspend_nvs_alloc(); |
419 | if (!error) { | 418 | if (!error) { |
420 | acpi_target_sleep_state = ACPI_STATE_S4; | 419 | acpi_target_sleep_state = ACPI_STATE_S4; |
421 | acpi_sleep_tts_switch(acpi_target_sleep_state); | 420 | acpi_sleep_tts_switch(acpi_target_sleep_state); |
@@ -510,7 +509,7 @@ static int acpi_hibernation_begin_old(void) | |||
510 | error = acpi_sleep_prepare(ACPI_STATE_S4); | 509 | error = acpi_sleep_prepare(ACPI_STATE_S4); |
511 | 510 | ||
512 | if (!error) { | 511 | if (!error) { |
513 | if (!s4_no_nvs) | 512 | if (!nvs_nosave) |
514 | error = suspend_nvs_alloc(); | 513 | error = suspend_nvs_alloc(); |
515 | if (!error) | 514 | if (!error) |
516 | acpi_target_sleep_state = ACPI_STATE_S4; | 515 | acpi_target_sleep_state = ACPI_STATE_S4; |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 224a38c960d4..ccf94dc5acdf 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -253,7 +253,7 @@ int acpi_resources_are_enforced(void); | |||
253 | #ifdef CONFIG_PM_SLEEP | 253 | #ifdef CONFIG_PM_SLEEP |
254 | void __init acpi_no_s4_hw_signature(void); | 254 | void __init acpi_no_s4_hw_signature(void); |
255 | void __init acpi_old_suspend_ordering(void); | 255 | void __init acpi_old_suspend_ordering(void); |
256 | void __init acpi_s4_no_nvs(void); | 256 | void __init acpi_nvs_nosave(void); |
257 | #endif /* CONFIG_PM_SLEEP */ | 257 | #endif /* CONFIG_PM_SLEEP */ |
258 | 258 | ||
259 | struct acpi_osc_context { | 259 | struct acpi_osc_context { |