diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2007-07-29 23:27:18 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-29 16:45:38 -0700 |
commit | 296699de6bdc717189a331ab6bbe90e05c94db06 (patch) | |
tree | 53c847ecc8cce11952502921844052e44ca60d5e /drivers/acpi/sleep | |
parent | b0cb1a19d05b8ea8611a9ef48a17fe417f1832e6 (diff) | |
download | talos-obmc-linux-296699de6bdc717189a331ab6bbe90e05c94db06.tar.gz talos-obmc-linux-296699de6bdc717189a331ab6bbe90e05c94db06.zip |
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/Makefile | 2 | ||||
-rw-r--r-- | drivers/acpi/sleep/main.c | 94 | ||||
-rw-r--r-- | drivers/acpi/sleep/proc.c | 10 | ||||
-rw-r--r-- | drivers/acpi/sleep/sleep.h | 2 |
4 files changed, 58 insertions, 50 deletions
diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile index 01a993a1d086..2bec897ab1eb 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 b4e94c893c81..e8cff5dd4cbc 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 1b7bbb5ba623..5dfe8b789633 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 f3e70397a7d6..ff1f8504f497 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); |