ACPI hibernation: Call _PTS before suspending devices

The ACPI 1.0 specification wants us to put devices into low power
states after executing the _PTS global control method, while ACPI
2.0 and later want us to do that in the reverse order. The current
hibernation code follows ACPI 2.0 in that respect which may cause some
ACPI 1.0x systems to hang during hibernation (ref.
http://bugzilla.kernel.org/show_bug.cgi?id=9528).

Make the hibernation code execute _PTS before putting devices into
low power states (ie. in accordance with ACPI 1.0x) with the
possibility to override that using the 'acpi_new_pts_ordering' kernel
command line option.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by Rafael J. Wysocki and committed by Len Brown 7258ec5d caea99ef

+25 -11
+25 -11
drivers/acpi/sleep/main.c
··· 283 283 #ifdef CONFIG_HIBERNATION 284 284 static int acpi_hibernation_begin(void) 285 285 { 286 + int error; 287 + 286 288 acpi_target_sleep_state = ACPI_STATE_S4; 287 - return 0; 289 + if (new_pts_ordering) 290 + return 0; 291 + 292 + error = acpi_sleep_prepare(ACPI_STATE_S4); 293 + if (error) 294 + acpi_target_sleep_state = ACPI_STATE_S0; 295 + else 296 + acpi_sleep_finish_wake_up = true; 297 + 298 + return error; 288 299 } 289 300 290 301 static int acpi_hibernation_prepare(void) 291 302 { 292 - int error; 303 + if (new_pts_ordering) { 304 + int error = acpi_sleep_prepare(ACPI_STATE_S4); 293 305 294 - error = acpi_sleep_prepare(ACPI_STATE_S4); 295 - if (error) 296 - return error; 306 + if (error) { 307 + acpi_target_sleep_state = ACPI_STATE_S0; 308 + return error; 309 + } 310 + acpi_sleep_finish_wake_up = true; 311 + } 297 312 298 - if (!ACPI_SUCCESS(acpi_hw_disable_all_gpes())) 299 - error = -EFAULT; 300 - 301 - return error; 313 + return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT; 302 314 } 303 315 304 316 static int acpi_hibernation_enter(void) ··· 351 339 acpi_set_firmware_waking_vector((acpi_physical_address) 0); 352 340 353 341 acpi_target_sleep_state = ACPI_STATE_S0; 342 + acpi_sleep_finish_wake_up = false; 354 343 } 355 344 356 345 static void acpi_hibernation_end(void) 357 346 { 358 347 /* 359 348 * This is necessary in case acpi_hibernation_finish() is not called 360 - * during a failing transition to the sleep state. 349 + * directly during a failing transition to the sleep state. 361 350 */ 362 - acpi_target_sleep_state = ACPI_STATE_S0; 351 + if (acpi_sleep_finish_wake_up) 352 + acpi_hibernation_finish(); 363 353 } 364 354 365 355 static int acpi_hibernation_pre_restore(void)