X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Facpi%2Fhardware%2Fhwsleep.c;h=dba3cfbe8cba9e3235970e7b972e7f54da24c4af;hb=26fd10517e810dd59ea050b052de24a75ee6dc07;hp=685debafbb72f5bddaaddf7ed1bf9892ecc10620;hpb=8313524a0d466f451a62709aaedf988d8257b21c;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 685deba..dba3cfb 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2006, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,6 +43,7 @@ */ #include +#include #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwsleep") @@ -62,17 +63,33 @@ ACPI_MODULE_NAME("hwsleep") acpi_status acpi_set_firmware_waking_vector(acpi_physical_address physical_address) { + struct acpi_table_facs *facs; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); - ACPI_FUNCTION_TRACE("acpi_set_firmware_waking_vector"); + /* Get the FACS */ + + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } /* Set the vector */ - if (acpi_gbl_common_fACS.vector_width == 32) { - *(ACPI_CAST_PTR - (u32, acpi_gbl_common_fACS.firmware_waking_vector)) - = (u32) physical_address; + if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { + /* + * ACPI 1.0 FACS or short table or optional X_ field is zero + */ + facs->firmware_waking_vector = (u32) physical_address; } else { - *acpi_gbl_common_fACS.firmware_waking_vector = physical_address; + /* + * ACPI 2.0 FACS with valid X_ field + */ + facs->xfirmware_waking_vector = physical_address; } return_ACPI_STATUS(AE_OK); @@ -97,23 +114,39 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) acpi_status acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) { + struct acpi_table_facs *facs; + acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_firmware_waking_vector"); + ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector); if (!physical_address) { return_ACPI_STATUS(AE_BAD_PARAMETER); } + /* Get the FACS */ + + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + /* Get the vector */ - if (acpi_gbl_common_fACS.vector_width == 32) { - *physical_address = (acpi_physical_address) - * - (ACPI_CAST_PTR - (u32, acpi_gbl_common_fACS.firmware_waking_vector)); + if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { + /* + * ACPI 1.0 FACS or short table or optional X_ field is zero + */ + *physical_address = + (acpi_physical_address) facs->firmware_waking_vector; } else { + /* + * ACPI 2.0 FACS with valid X_ field + */ *physical_address = - *acpi_gbl_common_fACS.firmware_waking_vector; + (acpi_physical_address) facs->xfirmware_waking_vector; } return_ACPI_STATUS(AE_OK); @@ -121,7 +154,6 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector) #endif - /******************************************************************************* * * FUNCTION: acpi_enter_sleep_state_prep @@ -142,7 +174,7 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) struct acpi_object_list arg_list; union acpi_object arg; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_prep"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); /* * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. @@ -162,18 +194,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) arg.type = ACPI_TYPE_INTEGER; arg.integer.value = sleep_state; - /* Run the _PTS and _GTS methods */ + /* Run the _PTS method */ status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { return_ACPI_STATUS(status); } - status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - return_ACPI_STATUS(status); - } - /* Setup the argument to _SST */ switch (sleep_state) { @@ -196,8 +223,10 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) break; } - /* Set the system indicators to show the desired sleep state. */ - + /* + * Set the system indicators to show the desired sleep state. + * _SST is an optional method (return no error if not found) + */ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, @@ -228,9 +257,11 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 in_value; + struct acpi_object_list arg_list; + union acpi_object arg; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { @@ -246,15 +277,14 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Clear wake status */ - status = - acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); + status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Clear all fixed and general purpose status bits */ - status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); + status = acpi_hw_clear_acpi_status(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -274,10 +304,21 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) return_ACPI_STATUS(status); } + /* Execute the _GTS method */ + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS(status); + } + /* Get current value of PM1A control */ - status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); + status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -304,15 +345,13 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Write #1: fill in SLP_TYP data */ - status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1A_CONTROL, + status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1B_CONTROL, + status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -327,15 +366,13 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) ACPI_FLUSH_CPU_CACHE(); - status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1A_CONTROL, + status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1B_CONTROL, + status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -355,8 +392,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) */ acpi_os_stall(10000000); - status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1_CONTROL, + status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, sleep_enable_reg_info-> access_bit_mask); if (ACPI_FAILURE(status)) { @@ -367,8 +403,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Wait until we enter sleep state */ do { - status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value, - ACPI_MTX_DO_NOT_LOCK); + status = acpi_get_register_unlocked(ACPI_BITREG_WAKE_STATUS, + &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -399,15 +435,14 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) u32 in_value; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_s4bios"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); - status = - acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); + status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); + status = acpi_hw_clear_acpi_status(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -429,13 +464,12 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ACPI_FLUSH_CPU_CACHE(); - status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, - (u32) acpi_gbl_FADT->S4bios_req, 8); + status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + (u32) acpi_gbl_FADT.S4bios_request, 8); do { acpi_os_stall(1000); - status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value, - ACPI_MTX_DO_NOT_LOCK); + status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -448,17 +482,18 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) /******************************************************************************* * - * FUNCTION: acpi_leave_sleep_state + * FUNCTION: acpi_leave_sleep_state_prep * - * PARAMETERS: sleep_state - Which sleep state we just exited + * PARAMETERS: sleep_state - Which sleep state we are exiting * * RETURN: Status * - * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep - * Called with interrupts ENABLED. + * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a + * sleep. + * Called with interrupts DISABLED. * ******************************************************************************/ -acpi_status acpi_leave_sleep_state(u8 sleep_state) +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) { struct acpi_object_list arg_list; union acpi_object arg; @@ -468,7 +503,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) u32 PM1Acontrol; u32 PM1Bcontrol; - ACPI_FUNCTION_TRACE("acpi_leave_sleep_state"); + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); /* * Set SLP_TYPE and SLP_EN to state S0. @@ -486,8 +521,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) /* Get current value of PM1A control */ - status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1_CONTROL, + status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); if (ACPI_SUCCESS(status)) { @@ -509,15 +543,48 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) /* Just ignore any errors */ - (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1A_CONTROL, + (void)acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); - (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1B_CONTROL, + (void)acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); } } + /* Execute the _BFS method */ + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_leave_sleep_state + * + * PARAMETERS: sleep_state - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ +acpi_status acpi_leave_sleep_state(u8 sleep_state) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); + /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; @@ -536,19 +603,10 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); } - arg.integer.value = sleep_state; - status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); - } - - status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); - } - /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ - /* + * GPEs must be enabled before _WAK is called as GPEs + * might get fired there + * * Restore the GPEs: * 1) Disable/Clear all GPEs * 2) Enable all runtime GPEs @@ -557,24 +615,29 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - acpi_gbl_system_awake_and_running = TRUE; - status = acpi_hw_enable_all_runtime_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + arg.integer.value = sleep_state; + status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); + } + /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ + + acpi_gbl_system_awake_and_running = TRUE; + /* Enable power button */ (void) acpi_set_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1, - ACPI_MTX_DO_NOT_LOCK); + [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1); (void) acpi_set_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].status_register_id, 1, - ACPI_MTX_DO_NOT_LOCK); + [ACPI_EVENT_POWER_BUTTON].status_register_id, 1); arg.integer.value = ACPI_SST_WORKING; status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);