Skip to content

Commit

Permalink
Merge branch 'suspend' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
lenb committed Jan 9, 2009
2 parents d0302bc + ada9cfd commit 3cc8a5f
Show file tree
Hide file tree
Showing 9 changed files with 446 additions and 201 deletions.
45 changes: 26 additions & 19 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,20 @@ and is between 256 and 4096 characters. It is defined in the file
default: 0

acpi_sleep= [HW,ACPI] Sleep options
Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, old_ordering }
See Documentation/power/video.txt for s3_bios and s3_mode.
Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
old_ordering, s4_nonvs }
See Documentation/power/video.txt for information on
s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep
as soon as the kernel's real-mode entry point is called.
s4_nohwsig prevents ACPI hardware signature from being
used during resume from hibernation.
old_ordering causes the ACPI 1.0 ordering of the _PTS
control method, wrt putting devices into low power
states, to be enforced (the ACPI 2.0 ordering of _PTS is
used by default).
control method, with respect to putting devices into
low power states, to be enforced (the ACPI 2.0 ordering
of _PTS is used by default).
s4_nonvs prevents the kernel from saving/restoring the
ACPI NVS memory during hibernation.

acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
Format: { level | edge | high | low }
Expand Down Expand Up @@ -194,7 +198,7 @@ and is between 256 and 4096 characters. It is defined in the file
acpi_skip_timer_override [HW,ACPI]
Recognize and ignore IRQ0/pin2 Interrupt Override.
For broken nForce2 BIOS resulting in XT-PIC timer.
acpi_use_timer_override [HW,ACPI}
acpi_use_timer_override [HW,ACPI]
Use timer override. For some broken Nvidia NF5 boards
that require a timer override, but don't have
HPET
Expand Down Expand Up @@ -861,17 +865,19 @@ and is between 256 and 4096 characters. It is defined in the file
See Documentation/ide/ide.txt.

idle= [X86]
Format: idle=poll or idle=mwait, idle=halt, idle=nomwait
Poll forces a polling idle loop that can slightly improves the performance
of waking up a idle CPU, but will use a lot of power and make the system
run hot. Not recommended.
idle=mwait. On systems which support MONITOR/MWAIT but the kernel chose
to not use it because it doesn't save as much power as a normal idle
loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
as idle=poll.
idle=halt. Halt is forced to be used for CPU idle.
Format: idle=poll, idle=mwait, idle=halt, idle=nomwait
Poll forces a polling idle loop that can slightly
improve the performance of waking up a idle CPU, but
will use a lot of power and make the system run hot.
Not recommended.
idle=mwait: On systems which support MONITOR/MWAIT but
the kernel chose to not use it because it doesn't save
as much power as a normal idle loop, use the
MONITOR/MWAIT idle loop anyways. Performance should be
the same as idle=poll.
idle=halt: Halt is forced to be used for CPU idle.
In such case C2/C3 won't be used again.
idle=nomwait. Disable mwait for CPU C-states
idle=nomwait: Disable mwait for CPU C-states

ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
Claim all unknown PCI IDE storage controllers.
Expand Down Expand Up @@ -1053,8 +1059,8 @@ and is between 256 and 4096 characters. It is defined in the file
lapic [X86-32,APIC] Enable the local APIC even if BIOS
disabled it.

lapic_timer_c2_ok [X86-32,x86-64,APIC] trust the local apic timer in
C2 power state.
lapic_timer_c2_ok [X86-32,x86-64,APIC] trust the local apic timer
in C2 power state.

libata.dma= [LIBATA] DMA control
libata.dma=0 Disable all PATA and SATA DMA
Expand Down Expand Up @@ -2242,7 +2248,8 @@ and is between 256 and 4096 characters. It is defined in the file

thermal.psv= [HW,ACPI]
-1: disable all passive trip points
<degrees C>: override all passive trip points to this value
<degrees C>: override all passive trip points to this
value

thermal.tzp= [HW,ACPI]
Specify global default ACPI thermal zone polling rate
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/kernel/acpi/sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ static int __init acpi_sleep_setup(char *str)
#endif
if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering();
if (strncmp(str, "s4_nonvs", 8) == 0)
acpi_s4_no_nvs();
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
Expand Down
21 changes: 21 additions & 0 deletions arch/x86/kernel/e820.c
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,27 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)
}
#endif

#ifdef CONFIG_HIBERNATION
/**
* Mark ACPI NVS memory region, so that we can save/restore it during
* hibernation and the subsequent resume.
*/
static int __init e820_mark_nvs_memory(void)
{
int i;

for (i = 0; i < e820.nr_map; i++) {
struct e820entry *ei = &e820.map[i];

if (ei->type == E820_NVS)
hibernate_nvs_register(ei->addr, ei->size);
}

return 0;
}
core_initcall(e820_mark_nvs_memory);
#endif

/*
* Early reserved memory areas.
*/
Expand Down
67 changes: 59 additions & 8 deletions drivers/acpi/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,19 @@ void __init acpi_old_suspend_ordering(void)
* cases.
*/
static bool set_sci_en_on_resume;
/*
* The ACPI specification wants us to save NVS memory regions during hibernation
* and to restore them during the subsequent resume. However, it is not certain
* if this mechanism is going to work on all machines, so we allow the user to
* disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
* option.
*/
static bool s4_no_nvs;

void __init acpi_s4_no_nvs(void)
{
s4_no_nvs = true;
}

/**
* acpi_pm_disable_gpes - Disable the GPEs.
Expand Down Expand Up @@ -394,9 +407,25 @@ void __init acpi_no_s4_hw_signature(void)

static int acpi_hibernation_begin(void)
{
acpi_target_sleep_state = ACPI_STATE_S4;
acpi_sleep_tts_switch(acpi_target_sleep_state);
return 0;
int error;

error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
if (!error) {
acpi_target_sleep_state = ACPI_STATE_S4;
acpi_sleep_tts_switch(acpi_target_sleep_state);
}

return error;
}

static int acpi_hibernation_pre_snapshot(void)
{
int error = acpi_pm_prepare();

if (!error)
hibernate_nvs_save();

return error;
}

static int acpi_hibernation_enter(void)
Expand All @@ -417,6 +446,12 @@ static int acpi_hibernation_enter(void)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}

static void acpi_hibernation_finish(void)
{
hibernate_nvs_free();
acpi_pm_finish();
}

static void acpi_hibernation_leave(void)
{
/*
Expand All @@ -432,6 +467,8 @@ static void acpi_hibernation_leave(void)
"cannot resume!\n");
panic("ACPI S4 hardware signature mismatch");
}
/* Restore the NVS memory area */
hibernate_nvs_restore();
}

static void acpi_pm_enable_gpes(void)
Expand All @@ -442,8 +479,8 @@ static void acpi_pm_enable_gpes(void)
static struct platform_hibernation_ops acpi_hibernation_ops = {
.begin = acpi_hibernation_begin,
.end = acpi_pm_end,
.pre_snapshot = acpi_pm_prepare,
.finish = acpi_pm_finish,
.pre_snapshot = acpi_hibernation_pre_snapshot,
.finish = acpi_hibernation_finish,
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
Expand All @@ -469,8 +506,22 @@ static int acpi_hibernation_begin_old(void)

error = acpi_sleep_prepare(ACPI_STATE_S4);

if (!error) {
if (!s4_no_nvs)
error = hibernate_nvs_alloc();
if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
}
return error;
}

static int acpi_hibernation_pre_snapshot_old(void)
{
int error = acpi_pm_disable_gpes();

if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
hibernate_nvs_save();

return error;
}

Expand All @@ -481,8 +532,8 @@ static int acpi_hibernation_begin_old(void)
static struct platform_hibernation_ops acpi_hibernation_ops_old = {
.begin = acpi_hibernation_begin_old,
.end = acpi_pm_end,
.pre_snapshot = acpi_pm_disable_gpes,
.finish = acpi_pm_finish,
.pre_snapshot = acpi_hibernation_pre_snapshot_old,
.finish = acpi_hibernation_finish,
.prepare = acpi_pm_disable_gpes,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
Expand Down
1 change: 1 addition & 0 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
#ifdef CONFIG_PM_SLEEP
void __init acpi_no_s4_hw_signature(void);
void __init acpi_old_suspend_ordering(void);
void __init acpi_s4_no_nvs(void);
#endif /* CONFIG_PM_SLEEP */
#else /* CONFIG_ACPI */

Expand Down
13 changes: 13 additions & 0 deletions include/linux/suspend.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,26 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);

extern void hibernation_set_ops(struct platform_hibernation_ops *ops);
extern int hibernate(void);
extern int hibernate_nvs_register(unsigned long start, unsigned long size);
extern int hibernate_nvs_alloc(void);
extern void hibernate_nvs_free(void);
extern void hibernate_nvs_save(void);
extern void hibernate_nvs_restore(void);
#else /* CONFIG_HIBERNATION */
static inline int swsusp_page_is_forbidden(struct page *p) { return 0; }
static inline void swsusp_set_page_free(struct page *p) {}
static inline void swsusp_unset_page_free(struct page *p) {}

static inline void hibernation_set_ops(struct platform_hibernation_ops *ops) {}
static inline int hibernate(void) { return -ENOSYS; }
static inline int hibernate_nvs_register(unsigned long a, unsigned long b)
{
return 0;
}
static inline int hibernate_nvs_alloc(void) { return 0; }
static inline void hibernate_nvs_free(void) {}
static inline void hibernate_nvs_save(void) {}
static inline void hibernate_nvs_restore(void) {}
#endif /* CONFIG_HIBERNATION */

#ifdef CONFIG_PM_SLEEP
Expand Down
6 changes: 3 additions & 3 deletions kernel/power/disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,12 @@ int hibernation_snapshot(int platform_mode)
{
int error, ftrace_save;

/* Free memory before shutting down devices. */
error = swsusp_shrink_memory();
error = platform_begin(platform_mode);
if (error)
return error;

error = platform_begin(platform_mode);
/* Free memory before shutting down devices. */
error = swsusp_shrink_memory();
if (error)
goto Close;

Expand Down
Loading

0 comments on commit 3cc8a5f

Please sign in to comment.