static u32 acpi_target_sleep_state = ACPI_STATE_S0;
#endif
-int acpi_sleep_prepare(u32 acpi_state)
+static int acpi_sleep_prepare(u32 acpi_state)
{
#ifdef CONFIG_ACPI_SLEEP
/* do we have a wakeup address for S2 and S3? */
ACPI_FLUSH_CPU_CACHE();
acpi_enable_wakeup_device_prep(acpi_state);
#endif
+ printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n",
+ acpi_state);
acpi_enter_sleep_state_prep(acpi_state);
return 0;
}
{
int error = acpi_sleep_prepare(acpi_target_sleep_state);
- if (error)
+ if (error) {
acpi_target_sleep_state = ACPI_STATE_S0;
+ return error;
+ }
- return error;
+ return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
}
/**
if (acpi_state == ACPI_STATE_S3) {
int error = acpi_save_state_mem();
- if (error) {
- acpi_target_sleep_state = ACPI_STATE_S0;
+ if (error)
return error;
- }
}
local_irq_save(flags);
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(acpi_state);
- /* ACPI 3.0 specs (P62) says that it's the responsabilty
+ /* ACPI 3.0 specs (P62) says that it's the responsibility
* of the OSPM to clear the status bit [ implying that the
* POWER_BUTTON event should not reach userspace ]
*/
#endif /* CONFIG_SUSPEND */
#ifdef CONFIG_HIBERNATION
-static int acpi_hibernation_start(void)
+static int acpi_hibernation_begin(void)
{
acpi_target_sleep_state = ACPI_STATE_S4;
+
return 0;
}
static int acpi_hibernation_prepare(void)
{
- return acpi_sleep_prepare(ACPI_STATE_S4);
+ int error = acpi_sleep_prepare(ACPI_STATE_S4);
+
+ if (error) {
+ acpi_target_sleep_state = ACPI_STATE_S0;
+ return error;
+ }
+
+ return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
}
static int acpi_hibernation_enter(void)
acpi_target_sleep_state = ACPI_STATE_S0;
}
+static void acpi_hibernation_end(void)
+{
+ /*
+ * This is necessary in case acpi_hibernation_finish() is not called
+ * during a failing transition to the sleep state.
+ */
+ acpi_target_sleep_state = ACPI_STATE_S0;
+}
+
static int acpi_hibernation_pre_restore(void)
{
acpi_status status;
}
static struct platform_hibernation_ops acpi_hibernation_ops = {
- .start = acpi_hibernation_start,
+ .begin = acpi_hibernation_begin,
+ .end = acpi_hibernation_end,
.pre_snapshot = acpi_hibernation_prepare,
.finish = acpi_hibernation_finish,
.prepare = acpi_hibernation_prepare,
if (acpi_target_sleep_state == ACPI_STATE_S0 ||
(wake && adev->wakeup.state.enabled &&
adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
+ acpi_status status;
+
acpi_method[3] = 'W';
- acpi_evaluate_integer(handle, acpi_method, NULL, &d_max);
- /* Sanity check */
- if (d_max < d_min)
+ status = acpi_evaluate_integer(handle, acpi_method, NULL,
+ &d_max);
+ if (ACPI_FAILURE(status)) {
+ d_max = d_min;
+ } else if (d_max < d_min) {
+ /* Warn the user of the broken DSDT */
+ printk(KERN_WARNING "ACPI: Wrong value from %s\n",
+ acpi_method);
+ /* Sanitize it */
d_min = d_max;
+ }
}
if (d_min_p)
{
/* Prepare to power off the system */
acpi_sleep_prepare(ACPI_STATE_S5);
+ acpi_hw_disable_all_gpes();
}
static void acpi_power_off(void)
{
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
- printk("%s called\n", __FUNCTION__);
+ printk("%s called\n", __func__);
local_irq_disable();
acpi_enable_wakeup_device(ACPI_STATE_S5);
acpi_enter_sleep_state(ACPI_STATE_S5);