Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -63,6 +63,14 @@ config ACPI_PROCFS

	  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
	tristate "AC Adapter"
	depends on X86
+1 −1
Original line number Diff line number Diff line
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)
+50 −44
Original line number Diff line number Diff line
@@ -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
+5 −5
Original line number Diff line number Diff line
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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);
Loading