aboutsummaryrefslogtreecommitdiff
path: root/drivers/acpi/sleep
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2007-07-29 23:27:18 +0200
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-29 16:45:38 -0700
commit296699de6bdc717189a331ab6bbe90e05c94db06 (patch)
tree53c847ecc8cce11952502921844052e44ca60d5e /drivers/acpi/sleep
parentb0cb1a19d05b8ea8611a9ef48a17fe417f1832e6 (diff)
Introduce CONFIG_SUSPEND for suspend-to-Ram and standby
Introduce CONFIG_SUSPEND representing the ability to enter system sleep states, such as the ACPI S3 state, and allow the user to choose SUSPEND and HIBERNATION independently of each other. Make HOTPLUG_CPU be selected automatically if SUSPEND or HIBERNATION has been chosen and the kernel is intended for SMP systems. Also, introduce CONFIG_PM_SLEEP which is automatically selected if CONFIG_SUSPEND or CONFIG_HIBERNATION is set and use it to select the code needed for both suspend and hibernation. The top-level power management headers and the ACPI code related to suspend and hibernation are modified to use the new definitions (the changes in drivers/acpi/sleep/main.c are, mostly, moving code to reduce the number of ifdefs). There are many other files in which CONFIG_PM can be replaced with CONFIG_PM_SLEEP or even with CONFIG_SUSPEND, but they can be updated in the future. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/acpi/sleep')
-rw-r--r--drivers/acpi/sleep/Makefile2
-rw-r--r--drivers/acpi/sleep/main.c94
-rw-r--r--drivers/acpi/sleep/proc.c10
-rw-r--r--drivers/acpi/sleep/sleep.h2
4 files changed, 58 insertions, 50 deletions
diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile
index 01a993a1d08..2bec897ab1e 100644
--- a/drivers/acpi/sleep/Makefile
+++ b/drivers/acpi/sleep/Makefile
@@ -1,5 +1,5 @@
obj-y := poweroff.o wakeup.o
-obj-y += main.o
+obj-$(CONFIG_PM_SLEEP) += main.o
obj-$(CONFIG_X86) += proc.o
EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index b4e94c893c8..e8cff5dd4cb 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -21,6 +21,9 @@
u8 sleep_states[ACPI_S_STATE_COUNT];
+static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
+#ifdef CONFIG_SUSPEND
static struct pm_ops acpi_pm_ops;
extern void do_suspend_lowlevel(void);
@@ -34,11 +37,6 @@ static u32 acpi_suspend_states[] = {
static int init_8259A_after_S1;
-extern int acpi_sleep_prepare(u32 acpi_state);
-extern void acpi_power_off(void);
-
-static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-
/**
* acpi_pm_set_target - Set the target system sleep state to the state
* associated with given @pm_state, if supported.
@@ -163,21 +161,6 @@ static int acpi_pm_finish(suspend_state_t pm_state)
return 0;
}
-int acpi_suspend(u32 acpi_state)
-{
- suspend_state_t states[] = {
- [1] = PM_SUSPEND_STANDBY,
- [3] = PM_SUSPEND_MEM,
- [5] = PM_SUSPEND_MAX
- };
-
- if (acpi_state < 6 && states[acpi_state])
- return pm_suspend(states[acpi_state]);
- if (acpi_state == 4)
- return hibernate();
- return -EINVAL;
-}
-
static int acpi_pm_state_valid(suspend_state_t pm_state)
{
u32 acpi_state;
@@ -202,6 +185,27 @@ static struct pm_ops acpi_pm_ops = {
.finish = acpi_pm_finish,
};
+/*
+ * Toshiba fails to preserve interrupts over S1, reinitialization
+ * of 8259 is needed after S1 resume.
+ */
+static int __init init_ints_after_s1(struct dmi_system_id *d)
+{
+ printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident);
+ init_8259A_after_S1 = 1;
+ return 0;
+}
+
+static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+ {
+ .callback = init_ints_after_s1,
+ .ident = "Toshiba Satellite 4030cdt",
+ .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),},
+ },
+ {},
+};
+#endif /* CONFIG_SUSPEND */
+
#ifdef CONFIG_HIBERNATION
static int acpi_hibernation_prepare(void)
{
@@ -256,6 +260,21 @@ static struct hibernation_ops acpi_hibernation_ops = {
};
#endif /* CONFIG_HIBERNATION */
+int acpi_suspend(u32 acpi_state)
+{
+ suspend_state_t states[] = {
+ [1] = PM_SUSPEND_STANDBY,
+ [3] = PM_SUSPEND_MEM,
+ [5] = PM_SUSPEND_MAX
+ };
+
+ if (acpi_state < 6 && states[acpi_state])
+ return pm_suspend(states[acpi_state]);
+ if (acpi_state == 4)
+ return hibernate();
+ return -EINVAL;
+}
+
/**
* acpi_pm_device_sleep_state - return preferred power state of ACPI device
* in the system sleep state given by %acpi_target_sleep_state
@@ -331,39 +350,22 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
return d_max;
}
-/*
- * Toshiba fails to preserve interrupts over S1, reinitialization
- * of 8259 is needed after S1 resume.
- */
-static int __init init_ints_after_s1(struct dmi_system_id *d)
-{
- printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident);
- init_8259A_after_S1 = 1;
- return 0;
-}
-
-static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
- {
- .callback = init_ints_after_s1,
- .ident = "Toshiba Satellite 4030cdt",
- .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),},
- },
- {},
-};
-
int __init acpi_sleep_init(void)
{
+ acpi_status status;
+ u8 type_a, type_b;
+#ifdef CONFIG_SUSPEND
int i = 0;
dmi_check_system(acpisleep_dmi_table);
+#endif
if (acpi_disabled)
return 0;
+#ifdef CONFIG_SUSPEND
printk(KERN_INFO PREFIX "(supports");
- for (i = 0; i < ACPI_S_STATE_COUNT; i++) {
- acpi_status status;
- u8 type_a, type_b;
+ for (i = ACPI_STATE_S0; i < ACPI_STATE_S4; i++) {
status = acpi_get_sleep_type_data(i, &type_a, &type_b);
if (ACPI_SUCCESS(status)) {
sleep_states[i] = 1;
@@ -373,10 +375,14 @@ int __init acpi_sleep_init(void)
printk(")\n");
pm_set_ops(&acpi_pm_ops);
+#endif
#ifdef CONFIG_HIBERNATION
- if (sleep_states[ACPI_STATE_S4])
+ status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b);
+ if (ACPI_SUCCESS(status)) {
hibernation_set_ops(&acpi_hibernation_ops);
+ sleep_states[ACPI_STATE_S4] = 1;
+ }
#else
sleep_states[ACPI_STATE_S4] = 0;
#endif
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 1b7bbb5ba62..5dfe8b78963 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -23,7 +23,7 @@
*/
ACPI_MODULE_NAME("sleep")
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_SLEEP
static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
{
int i;
@@ -76,7 +76,7 @@ acpi_system_write_sleep(struct file *file,
Done:
return error ? error : count;
}
-#endif /* CONFIG_ACPI_PROCFS */
+#endif /* CONFIG_ACPI_PROCFS_SLEEP */
#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */
@@ -471,7 +471,7 @@ static const struct file_operations acpi_system_wakeup_device_fops = {
.release = single_release,
};
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_SLEEP
static const struct file_operations acpi_system_sleep_fops = {
.open = acpi_system_sleep_open_fs,
.read = seq_read,
@@ -479,7 +479,7 @@ static const struct file_operations acpi_system_sleep_fops = {
.llseek = seq_lseek,
.release = single_release,
};
-#endif /* CONFIG_ACPI_PROCFS */
+#endif /* CONFIG_ACPI_PROCFS_SLEEP */
#ifdef HAVE_ACPI_LEGACY_ALARM
static const struct file_operations acpi_system_alarm_fops = {
@@ -506,7 +506,7 @@ static int __init acpi_sleep_proc_init(void)
if (acpi_disabled)
return 0;
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_SLEEP
/* 'sleep' [R/W] */
entry =
create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR,
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
index f3e70397a7d..ff1f8504f49 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep/sleep.h
@@ -6,3 +6,5 @@ extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
extern void acpi_enable_wakeup_device(u8 sleep_state);
extern void acpi_disable_wakeup_device(u8 sleep_state);
extern void acpi_gpe_sleep_prepare(u32 sleep_state);
+
+extern int acpi_sleep_prepare(u32 acpi_state);