Commit e5c86b5d authored by Len Brown's avatar Len Brown

Pull suspend.now into release branch

parents 19adc6ba 5a50fe70
obj-y := poweroff.o wakeup.o obj-y := wakeup.o
obj-$(CONFIG_ACPI_SLEEP) += main.o obj-$(CONFIG_ACPI_SLEEP) += main.o
obj-$(CONFIG_ACPI_SLEEP) += proc.o obj-$(CONFIG_ACPI_SLEEP) += proc.o
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <asm/io.h>
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h> #include <acpi/acpi_drivers.h>
#include "sleep.h" #include "sleep.h"
...@@ -57,6 +60,27 @@ static int acpi_pm_set_target(suspend_state_t pm_state) ...@@ -57,6 +60,27 @@ static int acpi_pm_set_target(suspend_state_t pm_state)
return error; return error;
} }
int acpi_sleep_prepare(u32 acpi_state)
{
#ifdef CONFIG_ACPI_SLEEP
/* do we have a wakeup address for S2 and S3? */
if (acpi_state == ACPI_STATE_S3) {
if (!acpi_wakeup_address) {
return -EFAULT;
}
acpi_set_firmware_waking_vector((acpi_physical_address)
virt_to_phys((void *)
acpi_wakeup_address));
}
ACPI_FLUSH_CPU_CACHE();
acpi_enable_wakeup_device_prep(acpi_state);
#endif
acpi_gpe_sleep_prepare(acpi_state);
acpi_enter_sleep_state_prep(acpi_state);
return 0;
}
/** /**
* acpi_pm_prepare - Do preliminary suspend work. * acpi_pm_prepare - Do preliminary suspend work.
* @pm_state: ignored * @pm_state: ignored
...@@ -350,6 +374,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) ...@@ -350,6 +374,20 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
return d_max; return d_max;
} }
static void acpi_power_off_prepare(void)
{
/* Prepare to power off the system */
acpi_sleep_prepare(ACPI_STATE_S5);
}
static void acpi_power_off(void)
{
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
printk("%s called\n", __FUNCTION__);
local_irq_disable();
acpi_enter_sleep_state(ACPI_STATE_S5);
}
int __init acpi_sleep_init(void) int __init acpi_sleep_init(void)
{ {
acpi_status status; acpi_status status;
...@@ -363,16 +401,17 @@ int __init acpi_sleep_init(void) ...@@ -363,16 +401,17 @@ int __init acpi_sleep_init(void)
if (acpi_disabled) if (acpi_disabled)
return 0; return 0;
sleep_states[ACPI_STATE_S0] = 1;
printk(KERN_INFO PREFIX "(supports S0");
#ifdef CONFIG_SUSPEND #ifdef CONFIG_SUSPEND
printk(KERN_INFO PREFIX "(supports"); for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) {
for (i = ACPI_STATE_S0; i < ACPI_STATE_S4; i++) {
status = acpi_get_sleep_type_data(i, &type_a, &type_b); status = acpi_get_sleep_type_data(i, &type_a, &type_b);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
sleep_states[i] = 1; sleep_states[i] = 1;
printk(" S%d", i); printk(" S%d", i);
} }
} }
printk(")\n");
pm_set_ops(&acpi_pm_ops); pm_set_ops(&acpi_pm_ops);
#endif #endif
...@@ -382,10 +421,16 @@ int __init acpi_sleep_init(void) ...@@ -382,10 +421,16 @@ int __init acpi_sleep_init(void)
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
hibernation_set_ops(&acpi_hibernation_ops); hibernation_set_ops(&acpi_hibernation_ops);
sleep_states[ACPI_STATE_S4] = 1; sleep_states[ACPI_STATE_S4] = 1;
printk(" S4");
} }
#else
sleep_states[ACPI_STATE_S4] = 0;
#endif #endif
status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
if (ACPI_SUCCESS(status)) {
sleep_states[ACPI_STATE_S5] = 1;
printk(" S5");
pm_power_off_prepare = acpi_power_off_prepare;
pm_power_off = acpi_power_off;
}
printk(")\n");
return 0; return 0;
} }
/*
* poweroff.c - ACPI handler for powering off the system.
*
* AKA S5, but it is independent of whether or not the kernel supports
* any other sleep support in the system.
*
* Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
*
* This file is released under the GPLv2.
*/
#include <linux/pm.h>
#include <linux/init.h>
#include <acpi/acpi_bus.h>
#include <linux/sysdev.h>
#include <asm/io.h>
#include "sleep.h"
int acpi_sleep_prepare(u32 acpi_state)
{
#ifdef CONFIG_ACPI_SLEEP
/* do we have a wakeup address for S2 and S3? */
if (acpi_state == ACPI_STATE_S3) {
if (!acpi_wakeup_address) {
return -EFAULT;
}
acpi_set_firmware_waking_vector((acpi_physical_address)
virt_to_phys((void *)
acpi_wakeup_address));
}
ACPI_FLUSH_CPU_CACHE();
acpi_enable_wakeup_device_prep(acpi_state);
#endif
acpi_gpe_sleep_prepare(acpi_state);
acpi_enter_sleep_state_prep(acpi_state);
return 0;
}
#ifdef CONFIG_PM
static void acpi_power_off_prepare(void)
{
/* Prepare to power off the system */
acpi_sleep_prepare(ACPI_STATE_S5);
}
static void acpi_power_off(void)
{
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
printk("%s called\n", __FUNCTION__);
local_irq_disable();
/* Some SMP machines only can poweroff in boot CPU */
acpi_enter_sleep_state(ACPI_STATE_S5);
}
static int acpi_poweroff_init(void)
{
if (!acpi_disabled) {
u8 type_a, type_b;
acpi_status status;
status =
acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
if (ACPI_SUCCESS(status)) {
pm_power_off_prepare = acpi_power_off_prepare;
pm_power_off = acpi_power_off;
}
}
return 0;
}
late_initcall(acpi_poweroff_init);
#endif /* CONFIG_PM */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment