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