Commit 296699de authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds

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: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b0cb1a19
...@@ -63,6 +63,14 @@ config ACPI_PROCFS ...@@ -63,6 +63,14 @@ config ACPI_PROCFS
Say N to delete /proc/acpi/ files that have moved to /sys/ Say N to delete /proc/acpi/ files that have moved to /sys/
config ACPI_PROCFS_SLEEP
bool "/proc/acpi/sleep (deprecated)"
depends on PM_SLEEP && ACPI_PROCFS
default n
---help---
Create /proc/acpi/sleep
Deprecated by /sys/power/state
config ACPI_AC config ACPI_AC
tristate "AC Adapter" tristate "AC Adapter"
depends on X86 depends on X86
......
obj-y := poweroff.o wakeup.o obj-y := poweroff.o wakeup.o
obj-y += main.o obj-$(CONFIG_PM_SLEEP) += main.o
obj-$(CONFIG_X86) += proc.o obj-$(CONFIG_X86) += proc.o
EXTRA_CFLAGS += $(ACPI_CFLAGS) EXTRA_CFLAGS += $(ACPI_CFLAGS)
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
u8 sleep_states[ACPI_S_STATE_COUNT]; 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; static struct pm_ops acpi_pm_ops;
extern void do_suspend_lowlevel(void); extern void do_suspend_lowlevel(void);
...@@ -34,11 +37,6 @@ static u32 acpi_suspend_states[] = { ...@@ -34,11 +37,6 @@ static u32 acpi_suspend_states[] = {
static int init_8259A_after_S1; 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 * acpi_pm_set_target - Set the target system sleep state to the state
* associated with given @pm_state, if supported. * associated with given @pm_state, if supported.
...@@ -163,21 +161,6 @@ static int acpi_pm_finish(suspend_state_t pm_state) ...@@ -163,21 +161,6 @@ static int acpi_pm_finish(suspend_state_t pm_state)
return 0; 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) static int acpi_pm_state_valid(suspend_state_t pm_state)
{ {
u32 acpi_state; u32 acpi_state;
...@@ -202,6 +185,27 @@ static struct pm_ops acpi_pm_ops = { ...@@ -202,6 +185,27 @@ static struct pm_ops acpi_pm_ops = {
.finish = acpi_pm_finish, .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 #ifdef CONFIG_HIBERNATION
static int acpi_hibernation_prepare(void) static int acpi_hibernation_prepare(void)
{ {
...@@ -256,6 +260,21 @@ static struct hibernation_ops acpi_hibernation_ops = { ...@@ -256,6 +260,21 @@ static struct hibernation_ops acpi_hibernation_ops = {
}; };
#endif /* CONFIG_HIBERNATION */ #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 * acpi_pm_device_sleep_state - return preferred power state of ACPI device
* in the system sleep state given by %acpi_target_sleep_state * 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) ...@@ -331,39 +350,22 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
return d_max; 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) int __init acpi_sleep_init(void)
{ {
acpi_status status;
u8 type_a, type_b;
#ifdef CONFIG_SUSPEND
int i = 0; int i = 0;
dmi_check_system(acpisleep_dmi_table); dmi_check_system(acpisleep_dmi_table);
#endif
if (acpi_disabled) if (acpi_disabled)
return 0; return 0;
#ifdef CONFIG_SUSPEND
printk(KERN_INFO PREFIX "(supports"); printk(KERN_INFO PREFIX "(supports");
for (i = 0; i < ACPI_S_STATE_COUNT; i++) { for (i = ACPI_STATE_S0; i < ACPI_STATE_S4; i++) {
acpi_status status;
u8 type_a, type_b;
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;
...@@ -373,10 +375,14 @@ int __init acpi_sleep_init(void) ...@@ -373,10 +375,14 @@ int __init acpi_sleep_init(void)
printk(")\n"); printk(")\n");
pm_set_ops(&acpi_pm_ops); pm_set_ops(&acpi_pm_ops);
#endif
#ifdef CONFIG_HIBERNATION #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); hibernation_set_ops(&acpi_hibernation_ops);
sleep_states[ACPI_STATE_S4] = 1;
}
#else #else
sleep_states[ACPI_STATE_S4] = 0; sleep_states[ACPI_STATE_S4] = 0;
#endif #endif
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
*/ */
ACPI_MODULE_NAME("sleep") 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) static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
{ {
int i; int i;
...@@ -76,7 +76,7 @@ acpi_system_write_sleep(struct file *file, ...@@ -76,7 +76,7 @@ acpi_system_write_sleep(struct file *file,
Done: Done:
return error ? error : count; 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) #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ /* 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 = { ...@@ -471,7 +471,7 @@ static const struct file_operations acpi_system_wakeup_device_fops = {
.release = single_release, .release = single_release,
}; };
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_SLEEP
static const struct file_operations acpi_system_sleep_fops = { static const struct file_operations acpi_system_sleep_fops = {
.open = acpi_system_sleep_open_fs, .open = acpi_system_sleep_open_fs,
.read = seq_read, .read = seq_read,
...@@ -479,7 +479,7 @@ static const struct file_operations acpi_system_sleep_fops = { ...@@ -479,7 +479,7 @@ static const struct file_operations acpi_system_sleep_fops = {
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = single_release,
}; };
#endif /* CONFIG_ACPI_PROCFS */ #endif /* CONFIG_ACPI_PROCFS_SLEEP */
#ifdef HAVE_ACPI_LEGACY_ALARM #ifdef HAVE_ACPI_LEGACY_ALARM
static const struct file_operations acpi_system_alarm_fops = { static const struct file_operations acpi_system_alarm_fops = {
...@@ -506,7 +506,7 @@ static int __init acpi_sleep_proc_init(void) ...@@ -506,7 +506,7 @@ static int __init acpi_sleep_proc_init(void)
if (acpi_disabled) if (acpi_disabled)
return 0; return 0;
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_SLEEP
/* 'sleep' [R/W] */ /* 'sleep' [R/W] */
entry = entry =
create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR, create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR,
......
...@@ -6,3 +6,5 @@ extern void acpi_enable_wakeup_device_prep(u8 sleep_state); ...@@ -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_enable_wakeup_device(u8 sleep_state);
extern void acpi_disable_wakeup_device(u8 sleep_state); extern void acpi_disable_wakeup_device(u8 sleep_state);
extern void acpi_gpe_sleep_prepare(u32 sleep_state); extern void acpi_gpe_sleep_prepare(u32 sleep_state);
extern int acpi_sleep_prepare(u32 acpi_state);
obj-y := shutdown.o obj-y := shutdown.o
obj-$(CONFIG_PM) += main.o suspend.o resume.o sysfs.o obj-$(CONFIG_PM_SLEEP) += main.o suspend.o resume.o sysfs.o
obj-$(CONFIG_PM_TRACE) += trace.o obj-$(CONFIG_PM_TRACE) += trace.o
ifeq ($(CONFIG_DEBUG_DRIVER),y) ifeq ($(CONFIG_DEBUG_DRIVER),y)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
extern void device_shutdown(void); extern void device_shutdown(void);
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
/* /*
* main.c * main.c
...@@ -62,7 +62,7 @@ extern int resume_device(struct device *); ...@@ -62,7 +62,7 @@ extern int resume_device(struct device *);
*/ */
extern int suspend_device(struct device *, pm_message_t); extern int suspend_device(struct device *, pm_message_t);
#else /* CONFIG_PM */ #else /* CONFIG_PM_SLEEP */
static inline int device_pm_add(struct device * dev) static inline int device_pm_add(struct device * dev)
......
...@@ -366,7 +366,16 @@ acpi_handle acpi_get_child(acpi_handle, acpi_integer); ...@@ -366,7 +366,16 @@ acpi_handle acpi_get_child(acpi_handle, acpi_integer);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
#ifdef CONFIG_PM_SLEEP
int acpi_pm_device_sleep_state(struct device *, int, int *); int acpi_pm_device_sleep_state(struct device *, int, int *);
#else /* !CONFIG_PM_SLEEP */
static inline int acpi_pm_device_sleep_state(struct device *d, int w, int *p)
{
if (p)
*p = ACPI_STATE_D0;
return ACPI_STATE_D3;
}
#endif /* !CONFIG_PM_SLEEP */
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
......
...@@ -147,6 +147,10 @@ static inline void unregister_hotplug_dock_device(acpi_handle handle) ...@@ -147,6 +147,10 @@ static inline void unregister_hotplug_dock_device(acpi_handle handle)
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
Suspend/Resume Suspend/Resume
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
#ifdef CONFIG_PM_SLEEP
extern int acpi_sleep_init(void); extern int acpi_sleep_init(void);
#else
static inline int acpi_sleep_init(void) { return 0; }
#endif
#endif /*__ACPI_DRIVERS_H__*/ #endif /*__ACPI_DRIVERS_H__*/
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
/* /*
* Check if a process has been frozen * Check if a process has been frozen
*/ */
...@@ -126,7 +126,7 @@ static inline void set_freezable(void) ...@@ -126,7 +126,7 @@ static inline void set_freezable(void)
current->flags &= ~PF_NOFREEZE; current->flags &= ~PF_NOFREEZE;
} }
#else #else /* !CONFIG_PM_SLEEP */
static inline int frozen(struct task_struct *p) { return 0; } static inline int frozen(struct task_struct *p) { return 0; }
static inline int freezing(struct task_struct *p) { return 0; } static inline int freezing(struct task_struct *p) { return 0; }
static inline void set_freeze_flag(struct task_struct *p) {} static inline void set_freeze_flag(struct task_struct *p) {}
...@@ -143,6 +143,6 @@ static inline void freezer_do_not_count(void) {} ...@@ -143,6 +143,6 @@ static inline void freezer_do_not_count(void) {}
static inline void freezer_count(void) {} static inline void freezer_count(void) {}
static inline int freezer_should_skip(struct task_struct *p) { return 0; } static inline int freezer_should_skip(struct task_struct *p) { return 0; }
static inline void set_freezable(void) {} static inline void set_freezable(void) {}
#endif #endif /* !CONFIG_PM_SLEEP */
#endif /* FREEZER_H_INCLUDED */ #endif /* FREEZER_H_INCLUDED */
...@@ -165,6 +165,7 @@ struct pm_ops { ...@@ -165,6 +165,7 @@ struct pm_ops {
int (*finish)(suspend_state_t state); int (*finish)(suspend_state_t state);
}; };
#ifdef CONFIG_SUSPEND
extern struct pm_ops *pm_ops; extern struct pm_ops *pm_ops;
/** /**
...@@ -193,6 +194,12 @@ extern void arch_suspend_disable_irqs(void); ...@@ -193,6 +194,12 @@ extern void arch_suspend_disable_irqs(void);
extern void arch_suspend_enable_irqs(void); extern void arch_suspend_enable_irqs(void);
extern int pm_suspend(suspend_state_t state); extern int pm_suspend(suspend_state_t state);
#else /* !CONFIG_SUSPEND */
#define suspend_valid_only_mem NULL
static inline void pm_set_ops(struct pm_ops *pm_ops) {}
static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; }
#endif /* !CONFIG_SUSPEND */
/* /*
* Device power management * Device power management
...@@ -266,7 +273,7 @@ typedef struct pm_message { ...@@ -266,7 +273,7 @@ typedef struct pm_message {
struct dev_pm_info { struct dev_pm_info {
pm_message_t power_state; pm_message_t power_state;
unsigned can_wakeup:1; unsigned can_wakeup:1;
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
unsigned should_wakeup:1; unsigned should_wakeup:1;
struct list_head entry; struct list_head entry;
#endif #endif
...@@ -276,7 +283,7 @@ extern int device_power_down(pm_message_t state); ...@@ -276,7 +283,7 @@ extern int device_power_down(pm_message_t state);
extern void device_power_up(void); extern void device_power_up(void);
extern void device_resume(void); extern void device_resume(void);
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
extern int device_suspend(pm_message_t state); extern int device_suspend(pm_message_t state);
extern int device_prepare_suspend(pm_message_t state); extern int device_prepare_suspend(pm_message_t state);
...@@ -306,7 +313,7 @@ static inline int call_platform_enable_wakeup(struct device *dev, int is_on) ...@@ -306,7 +313,7 @@ static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
return 0; return 0;
} }
#else /* !CONFIG_PM */ #else /* !CONFIG_PM_SLEEP */
static inline int device_suspend(pm_message_t state) static inline int device_suspend(pm_message_t state)
{ {
...@@ -323,7 +330,7 @@ static inline int call_platform_enable_wakeup(struct device *dev, int is_on) ...@@ -323,7 +330,7 @@ static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
return 0; return 0;
} }
#endif #endif /* !CONFIG_PM_SLEEP */
/* changes to device_may_wakeup take effect on the next pm state change. /* changes to device_may_wakeup take effect on the next pm state change.
* by default, devices should wakeup if they can. * by default, devices should wakeup if they can.
......
...@@ -24,7 +24,7 @@ struct pbe { ...@@ -24,7 +24,7 @@ struct pbe {
extern void drain_local_pages(void); extern void drain_local_pages(void);
extern void mark_free_pages(struct zone *zone); extern void mark_free_pages(struct zone *zone);
#if defined(CONFIG_PM) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
extern int pm_prepare_console(void); extern int pm_prepare_console(void);
extern void pm_restore_console(void); extern void pm_restore_console(void);
#else #else
...@@ -54,7 +54,6 @@ struct hibernation_ops { ...@@ -54,7 +54,6 @@ struct hibernation_ops {
void (*restore_cleanup)(void); void (*restore_cleanup)(void);
}; };
#ifdef CONFIG_PM
#ifdef CONFIG_HIBERNATION #ifdef CONFIG_HIBERNATION
/* kernel/power/snapshot.c */ /* kernel/power/snapshot.c */
extern void __register_nosave_region(unsigned long b, unsigned long e, int km); extern void __register_nosave_region(unsigned long b, unsigned long e, int km);
...@@ -82,6 +81,7 @@ static inline void hibernation_set_ops(struct hibernation_ops *ops) {} ...@@ -82,6 +81,7 @@ static inline void hibernation_set_ops(struct hibernation_ops *ops) {}
static inline int hibernate(void) { return -ENOSYS; } static inline int hibernate(void) { return -ENOSYS; }
#endif /* CONFIG_HIBERNATION */ #endif /* CONFIG_HIBERNATION */
#ifdef CONFIG_PM_SLEEP
void save_processor_state(void); void save_processor_state(void);
void restore_processor_state(void); void restore_processor_state(void);
struct saved_context; struct saved_context;
...@@ -106,7 +106,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) ...@@ -106,7 +106,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
{ .notifier_call = fn, .priority = pri }; \ { .notifier_call = fn, .priority = pri }; \
register_pm_notifier(&fn##_nb); \ register_pm_notifier(&fn##_nb); \
} }
#else /* CONFIG_PM */ #else /* !CONFIG_PM_SLEEP */
static inline int register_pm_notifier(struct notifier_block *nb) static inline int register_pm_notifier(struct notifier_block *nb)
{ {
...@@ -119,9 +119,9 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) ...@@ -119,9 +119,9 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
} }
#define pm_notifier(fn, pri) do { (void)(fn); } while (0) #define pm_notifier(fn, pri) do { (void)(fn); } while (0)
#endif /* CONFIG_PM */ #endif /* !CONFIG_PM_SLEEP */
#if !defined CONFIG_HIBERNATION || !defined(CONFIG_PM) #ifndef CONFIG_HIBERNATION
static inline void register_nosave_region(unsigned long b, unsigned long e) static inline void register_nosave_region(unsigned long b, unsigned long e)
{ {
} }
......
...@@ -46,7 +46,7 @@ config PM_VERBOSE ...@@ -46,7 +46,7 @@ config PM_VERBOSE
config DISABLE_CONSOLE_SUSPEND config DISABLE_CONSOLE_SUSPEND
bool "Keep console(s) enabled during suspend/resume (DANGEROUS)" bool "Keep console(s) enabled during suspend/resume (DANGEROUS)"
depends on PM_DEBUG depends on PM_DEBUG && PM_SLEEP
default n default n
---help--- ---help---
This option turns off the console suspend mechanism that prevents This option turns off the console suspend mechanism that prevents
...@@ -57,7 +57,7 @@ config DISABLE_CONSOLE_SUSPEND ...@@ -57,7 +57,7 @@ config DISABLE_CONSOLE_SUSPEND
config PM_TRACE config PM_TRACE
bool "Suspend/resume event tracing" bool "Suspend/resume event tracing"
depends on PM_DEBUG && X86 && EXPERIMENTAL depends on PM_DEBUG && X86 && PM_SLEEP && EXPERIMENTAL
default n default n
---help--- ---help---
This enables some cheesy code to save the last PM event point in the This enables some cheesy code to save the last PM event point in the
...@@ -72,9 +72,37 @@ config PM_TRACE ...@@ -72,9 +72,37 @@ config PM_TRACE
CAUTION: this option will cause your machine's real-time clock to be CAUTION: this option will cause your machine's real-time clock to be
set to an invalid time after a resume. set to an invalid time after a resume.
config SUSPEND_SMP_POSSIBLE
bool
depends on (X86 && !X86_VOYAGER) || (PPC64 && (PPC_PSERIES || PPC_PMAC))
depends on SMP
default y
config SUSPEND_SMP
bool
depends on SUSPEND_SMP_POSSIBLE && PM_SLEEP
select HOTPLUG_CPU
default y
config PM_SLEEP
bool
depends on SUSPEND || HIBERNATION
default y
config SUSPEND
bool "Suspend to RAM and standby"
depends on PM
depends on !SMP || SUSPEND_SMP_POSSIBLE
default y
---help---
Allow the system to enter sleep states in which main memory is
powered and thus its contents are preserved, such as the
suspend-to-RAM state (i.e. the ACPI S3 state).
config HIBERNATION config HIBERNATION
bool "Hibernation" bool "Hibernation (aka 'suspend to disk')"
depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)) depends on PM && SWAP
depends on ((X86 || PPC64_SWSUSP || FRV || PPC32) && !SMP) || SUSPEND_SMP_POSSIBLE
---help--- ---help---
Enable the suspend to disk (STD) functionality, which is usually Enable the suspend to disk (STD) functionality, which is usually
called "hibernation" in user interfaces. STD checkpoints the called "hibernation" in user interfaces. STD checkpoints the
...@@ -132,11 +160,6 @@ config PM_STD_PARTITION ...@@ -132,11 +160,6 @@ config PM_STD_PARTITION
suspended image to. It will simply pick the first available swap suspended image to. It will simply pick the first available swap
device. device.
config SUSPEND_SMP
bool
depends on HOTPLUG_CPU && (X86 || PPC64) && PM
default y
config APM_EMULATION config APM_EMULATION
tristate "Advanced Power Management Emulation" tristate "Advanced Power Management Emulation"
depends on PM && SYS_SUPPORTS_APM_EMULATION depends on PM && SYS_SUPPORTS_APM_EMULATION
......
...@@ -3,8 +3,9 @@ ifeq ($(CONFIG_PM_DEBUG),y) ...@@ -3,8 +3,9 @@ ifeq ($(CONFIG_PM_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
endif endif
obj-y := main.o process.o console.o obj-y := main.o
obj-$(CONFIG_PM_LEGACY) += pm.o obj-$(CONFIG_PM_LEGACY) += pm.o
obj-$(CONFIG_PM_SLEEP) += process.o console.o
obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o
obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
...@@ -25,11 +25,13 @@ ...@@ -25,11 +25,13 @@
BLOCKING_NOTIFIER_HEAD(pm_chain_head); BLOCKING_NOTIFIER_HEAD(pm_chain_head);
/*This is just an arbitrary number */
#define FREE_PAGE_NUMBER (100)
DEFINE_MUTEX(pm_mutex); DEFINE_MUTEX(pm_mutex);
#ifdef CONFIG_SUSPEND
/* This is just an arbitrary number */
#define FREE_PAGE_NUMBER (100)
struct pm_ops *pm_ops; struct pm_ops *pm_ops;
/** /**
...@@ -269,6 +271,8 @@ int pm_suspend(suspend_state_t state) ...@@ -269,6 +271,8 @@ int pm_suspend(suspend_state_t state)
EXPORT_SYMBOL(pm_suspend); EXPORT_SYMBOL(pm_suspend);
#endif /* CONFIG_SUSPEND */
decl_subsys(power,NULL,NULL); decl_subsys(power,NULL,NULL);
...@@ -285,13 +289,15 @@ decl_subsys(power,NULL,NULL); ...@@ -285,13 +289,15 @@ decl_subsys(power,NULL,NULL);
static ssize_t state_show(struct kset *kset, char *buf) static ssize_t state_show(struct kset *kset, char *buf)
{ {
char *s = buf;
#ifdef CONFIG_SUSPEND
int i; int i;
char * s = buf;
for (i = 0; i < PM_SUSPEND_MAX; i++) { for (i = 0; i < PM_SUSPEND_MAX; i++) {
if (pm_states[i] && valid_state(i)) if (pm_states[i] && valid_state(i))
s += sprintf(s,"%s ", pm_states[i]); s += sprintf(s,"%s ", pm_states[i]);
} }
#endif
#ifdef CONFIG_HIBERNATION #ifdef CONFIG_HIBERNATION
s += sprintf(s, "%s\n", "disk"); s += sprintf(s, "%s\n", "disk");
#else #else
...@@ -304,11 +310,13 @@ static ssize_t state_show(struct kset *kset, char *buf) ...@@ -304,11 +310,13 @@ static ssize_t state_show(struct kset *kset, char *buf)
static ssize_t state_store(struct kset *kset, const char *buf, size_t n) static ssize_t state_store(struct kset *kset, const char *buf, size_t n)
{ {
#ifdef CONFIG_SUSPEND
suspend_state_t state = PM_SUSPEND_STANDBY; suspend_state_t state = PM_SUSPEND_STANDBY;
const char * const *s; const char * const *s;
#endif
char *p; char *p;
int error;
int len; int len;
int error = -EINVAL;
p = memchr(buf, '\n', n); p = memchr(buf, '\n', n);
len = p ? p - buf : n; len = p ? p - buf : n;
...@@ -316,17 +324,19 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n) ...@@ -316,17 +324,19 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n)
/* First, check if we are requested to hibernate */ /* First, check if we are requested to hibernate */
if (len == 4 && !strncmp(buf, "disk", len)) { if (len == 4 && !strncmp(buf, "disk", len)) {
error = hibernate(); error = hibernate();
return error ? error : n; goto Exit;
} }
#ifdef CONFIG_SUSPEND
for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
break; break;
} }
if (state < PM_SUSPEND_MAX && *s) if (state < PM_SUSPEND_MAX && *s)
error = enter_state(state); error = enter_state(state);
else #endif
error = -EINVAL;
Exit:
return error ? error : n; return error ? error : n;
} }
......
...@@ -176,9 +176,17 @@ struct timeval; ...@@ -176,9 +176,17 @@ struct timeval;
extern void swsusp_show_speed(struct timeval *, struct timeval *, extern void swsusp_show_speed(struct timeval *, struct timeval *,
unsigned int, char *); unsigned int, char *);
#ifdef CONFIG_SUSPEND
/* kernel/power/main.c */ /* kernel/power/main.c */
extern int suspend_enter(suspend_state_t state);
extern int suspend_devices_and_enter(suspend_state_t state); extern int suspend_devices_and_enter(suspend_state_t state);
#else /* !CONFIG_SUSPEND */
static inline int suspend_devices_and_enter(suspend_state_t state)
{
return -ENOSYS;
}
#endif /* !CONFIG_SUSPEND */
/* kernel/power/common.c */
extern struct blocking_notifier_head pm_chain_head; extern struct blocking_notifier_head pm_chain_head;
static inline int pm_notifier_call_chain(unsigned long val) static inline int pm_notifier_call_chain(unsigned long val)
......
...@@ -726,7 +726,7 @@ static void __drain_pages(unsigned int cpu) ...@@ -726,7 +726,7 @@ static void __drain_pages(unsigned int cpu)
} }
} }
#ifdef CONFIG_PM #ifdef CONFIG_HIBERNATION
void mark_free_pages(struct zone *zone) void mark_free_pages(struct zone *zone)
{ {
...@@ -772,7 +772,7 @@ void drain_local_pages(void) ...@@ -772,7 +772,7 @@ void drain_local_pages(void)
__drain_pages(smp_processor_id()); __drain_pages(smp_processor_id());
local_irq_restore(flags); local_irq_restore(flags);
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_HIBERNATION */
/* /*
* Free a 0-order page * Free a 0-order page
......
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