Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: Separate invocations of _GTS and _BFS from _PTS and _WAK

The execution of ACPI global control methods _GTS and _BFS is
currently tied to the preparation to enter a sleep state and to the
leaving of the sleep state, respectively. However, these functions
are called before disabling the nonboot CPUs and after enabling
them, respectively (in fact, on ACPI 1.0x systems the first of them
ought to be called before suspending devices), while according to the
ACPI specification, _GTS is to be executed right prior to entering
the system sleep state and _BFS is to be executed right after the
platfor firmware has returned control to the OS on wake up.

Move the execution of _GTS and _BFS to the right places.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by

Rafael J. Wysocki and committed by
Len Brown
c95d47a8 c697eece

+66 -18
+57 -18
drivers/acpi/hardware/hwsleep.c
··· 192 arg.type = ACPI_TYPE_INTEGER; 193 arg.integer.value = sleep_state; 194 195 - /* Run the _PTS and _GTS methods */ 196 197 status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); 198 - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 199 - return_ACPI_STATUS(status); 200 - } 201 - 202 - status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); 203 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 204 return_ACPI_STATUS(status); 205 } ··· 257 struct acpi_bit_register_info *sleep_type_reg_info; 258 struct acpi_bit_register_info *sleep_enable_reg_info; 259 u32 in_value; 260 acpi_status status; 261 262 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); ··· 301 302 status = acpi_hw_enable_all_wakeup_gpes(); 303 if (ACPI_FAILURE(status)) { 304 return_ACPI_STATUS(status); 305 } 306 ··· 482 483 /******************************************************************************* 484 * 485 - * FUNCTION: acpi_leave_sleep_state 486 * 487 - * PARAMETERS: sleep_state - Which sleep state we just exited 488 * 489 * RETURN: Status 490 * 491 - * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep 492 - * Called with interrupts ENABLED. 493 * 494 ******************************************************************************/ 495 - acpi_status acpi_leave_sleep_state(u8 sleep_state) 496 { 497 struct acpi_object_list arg_list; 498 union acpi_object arg; ··· 503 u32 PM1Acontrol; 504 u32 PM1Bcontrol; 505 506 - ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); 507 508 /* 509 * Set SLP_TYPE and SLP_EN to state S0. ··· 550 } 551 } 552 553 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ 554 555 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; ··· 601 status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); 602 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 603 ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); 604 - } 605 - 606 - arg.integer.value = sleep_state; 607 - status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); 608 - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 609 - ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); 610 } 611 612 /*
··· 192 arg.type = ACPI_TYPE_INTEGER; 193 arg.integer.value = sleep_state; 194 195 + /* Run the _PTS method */ 196 197 status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); 198 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 199 return_ACPI_STATUS(status); 200 } ··· 262 struct acpi_bit_register_info *sleep_type_reg_info; 263 struct acpi_bit_register_info *sleep_enable_reg_info; 264 u32 in_value; 265 + struct acpi_object_list arg_list; 266 + union acpi_object arg; 267 acpi_status status; 268 269 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); ··· 304 305 status = acpi_hw_enable_all_wakeup_gpes(); 306 if (ACPI_FAILURE(status)) { 307 + return_ACPI_STATUS(status); 308 + } 309 + 310 + /* Execute the _GTS method */ 311 + 312 + arg_list.count = 1; 313 + arg_list.pointer = &arg; 314 + arg.type = ACPI_TYPE_INTEGER; 315 + arg.integer.value = sleep_state; 316 + 317 + status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); 318 + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 319 return_ACPI_STATUS(status); 320 } 321 ··· 473 474 /******************************************************************************* 475 * 476 + * FUNCTION: acpi_leave_sleep_state_prep 477 * 478 + * PARAMETERS: sleep_state - Which sleep state we are exiting 479 * 480 * RETURN: Status 481 * 482 + * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a 483 + * sleep. 484 + * Called with interrupts DISABLED. 485 * 486 ******************************************************************************/ 487 + acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) 488 { 489 struct acpi_object_list arg_list; 490 union acpi_object arg; ··· 493 u32 PM1Acontrol; 494 u32 PM1Bcontrol; 495 496 + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); 497 498 /* 499 * Set SLP_TYPE and SLP_EN to state S0. ··· 540 } 541 } 542 543 + /* Execute the _BFS method */ 544 + 545 + arg_list.count = 1; 546 + arg_list.pointer = &arg; 547 + arg.type = ACPI_TYPE_INTEGER; 548 + arg.integer.value = sleep_state; 549 + 550 + status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); 551 + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 552 + ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); 553 + } 554 + 555 + return_ACPI_STATUS(status); 556 + } 557 + 558 + /******************************************************************************* 559 + * 560 + * FUNCTION: acpi_leave_sleep_state 561 + * 562 + * PARAMETERS: sleep_state - Which sleep state we just exited 563 + * 564 + * RETURN: Status 565 + * 566 + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep 567 + * Called with interrupts ENABLED. 568 + * 569 + ******************************************************************************/ 570 + acpi_status acpi_leave_sleep_state(u8 sleep_state) 571 + { 572 + struct acpi_object_list arg_list; 573 + union acpi_object arg; 574 + acpi_status status; 575 + 576 + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); 577 + 578 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ 579 580 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; ··· 556 status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); 557 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 558 ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); 559 } 560 561 /*
+7
drivers/acpi/sleep/main.c
··· 139 break; 140 } 141 142 /* ACPI 3.0 specs (P62) says that it's the responsabilty 143 * of the OSPM to clear the status bit [ implying that the 144 * POWER_BUTTON event should not reach userspace ] ··· 275 acpi_enable_wakeup_device(ACPI_STATE_S4); 276 /* This shouldn't return. If it returns, we have a problem */ 277 status = acpi_enter_sleep_state(ACPI_STATE_S4); 278 local_irq_restore(flags); 279 280 return ACPI_SUCCESS(status) ? 0 : -EFAULT; ··· 289 * enable it here. 290 */ 291 acpi_enable(); 292 } 293 294 static void acpi_hibernation_finish(void)
··· 139 break; 140 } 141 142 + /* Reprogram control registers and execute _BFS */ 143 + acpi_leave_sleep_state_prep(acpi_state); 144 + 145 /* ACPI 3.0 specs (P62) says that it's the responsabilty 146 * of the OSPM to clear the status bit [ implying that the 147 * POWER_BUTTON event should not reach userspace ] ··· 272 acpi_enable_wakeup_device(ACPI_STATE_S4); 273 /* This shouldn't return. If it returns, we have a problem */ 274 status = acpi_enter_sleep_state(ACPI_STATE_S4); 275 + /* Reprogram control registers and execute _BFS */ 276 + acpi_leave_sleep_state_prep(ACPI_STATE_S4); 277 local_irq_restore(flags); 278 279 return ACPI_SUCCESS(status) ? 0 : -EFAULT; ··· 284 * enable it here. 285 */ 286 acpi_enable(); 287 + /* Reprogram control registers and execute _BFS */ 288 + acpi_leave_sleep_state_prep(ACPI_STATE_S4); 289 } 290 291 static void acpi_hibernation_finish(void)
+2
include/acpi/acpixf.h
··· 335 336 acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void); 337 338 acpi_status acpi_leave_sleep_state(u8 sleep_state); 339 340 #endif /* __ACXFACE_H__ */
··· 335 336 acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void); 337 338 + acpi_status acpi_leave_sleep_state_prep(u8 sleep_state); 339 + 340 acpi_status acpi_leave_sleep_state(u8 sleep_state); 341 342 #endif /* __ACXFACE_H__ */