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/main.c | |
parent | b0cb1a19d05b8ea8611a9ef48a17fe417f1832e6 (diff) | |
download | lwn-296699de6bdc717189a331ab6bbe90e05c94db06.tar.gz lwn-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/main.c')
-rw-r--r-- | drivers/acpi/sleep/main.c | 94 |
1 files changed, 50 insertions, 44 deletions
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 |