Merge branches 'pm-sleep' and 'pm-tools'
* pm-sleep: PM / hibernate: Introduce test_resume mode for hibernation x86 / hibernate: Use hlt_play_dead() when resuming from hibernation PM / hibernate: Image data protection during restoration PM / hibernate: Add missing braces in __register_nosave_region() PM / hibernate: Clean up comments in snapshot.c PM / hibernate: Clean up function headers in snapshot.c PM / hibernate: Add missing braces in hibernate_setup() PM / hibernate: Recycle safe pages after image restoration PM / hibernate: Simplify mark_unsafe_pages() PM / hibernate: Do not free preallocated safe pages during image restore PM / suspend: show workqueue state in suspend flow PM / sleep: make PM notifiers called symmetrically PM / sleep: Make pm_prepare_console() return void PM / Hibernate: Don't let kasan instrument snapshot.c * pm-tools: PM / tools: scripts: AnalyzeSuspend v4.2 tools/turbostat: allow user to alter DESTDIR and PREFIX
This commit is contained in:
commit
7f234a4d8a
|
@ -3594,6 +3594,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||||
present during boot.
|
present during boot.
|
||||||
nocompress Don't compress/decompress hibernation images.
|
nocompress Don't compress/decompress hibernation images.
|
||||||
no Disable hibernation and resume.
|
no Disable hibernation and resume.
|
||||||
|
protect_image Turn on image protection during restoration
|
||||||
|
(that will set all pages holding image data
|
||||||
|
during restoration read-only).
|
||||||
|
|
||||||
retain_initrd [RAM] Keep initrd memory after extraction
|
retain_initrd [RAM] Keep initrd memory after extraction
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
|
||||||
int native_cpu_disable(void);
|
int native_cpu_disable(void);
|
||||||
int common_cpu_die(unsigned int cpu);
|
int common_cpu_die(unsigned int cpu);
|
||||||
void native_cpu_die(unsigned int cpu);
|
void native_cpu_die(unsigned int cpu);
|
||||||
|
void hlt_play_dead(void);
|
||||||
void native_play_dead(void);
|
void native_play_dead(void);
|
||||||
void play_dead_common(void);
|
void play_dead_common(void);
|
||||||
void wbinvd_on_cpu(int cpu);
|
void wbinvd_on_cpu(int cpu);
|
||||||
|
|
|
@ -1622,7 +1622,7 @@ static inline void mwait_play_dead(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void hlt_play_dead(void)
|
void hlt_play_dead(void)
|
||||||
{
|
{
|
||||||
if (__this_cpu_read(cpu_info.x86) >= 4)
|
if (__this_cpu_read(cpu_info.x86) >= 4)
|
||||||
wbinvd();
|
wbinvd();
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/perf_event.h>
|
#include <linux/perf_event.h>
|
||||||
|
#include <linux/tboot.h>
|
||||||
|
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/proto.h>
|
#include <asm/proto.h>
|
||||||
|
@ -266,6 +267,35 @@ void notrace restore_processor_state(void)
|
||||||
EXPORT_SYMBOL(restore_processor_state);
|
EXPORT_SYMBOL(restore_processor_state);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_HIBERNATION) && defined(CONFIG_HOTPLUG_CPU)
|
||||||
|
static void resume_play_dead(void)
|
||||||
|
{
|
||||||
|
play_dead_common();
|
||||||
|
tboot_shutdown(TB_SHUTDOWN_WFS);
|
||||||
|
hlt_play_dead();
|
||||||
|
}
|
||||||
|
|
||||||
|
int hibernate_resume_nonboot_cpu_disable(void)
|
||||||
|
{
|
||||||
|
void (*play_dead)(void) = smp_ops.play_dead;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that MONITOR/MWAIT will not be used in the "play dead" loop
|
||||||
|
* during hibernate image restoration, because it is likely that the
|
||||||
|
* monitored address will be actually written to at that time and then
|
||||||
|
* the "dead" CPU will attempt to execute instructions again, but the
|
||||||
|
* address in its instruction pointer may not be possible to resolve
|
||||||
|
* any more at that point (the page tables used by it previously may
|
||||||
|
* have been overwritten by hibernate image data).
|
||||||
|
*/
|
||||||
|
smp_ops.play_dead = resume_play_dead;
|
||||||
|
ret = disable_nonboot_cpus();
|
||||||
|
smp_ops.play_dead = play_dead;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When bsp_check() is called in hibernate and suspend, cpu hotplug
|
* When bsp_check() is called in hibernate and suspend, cpu hotplug
|
||||||
* is disabled already. So it's unnessary to handle race condition between
|
* is disabled already. So it's unnessary to handle race condition between
|
||||||
|
|
|
@ -18,12 +18,11 @@ static inline void pm_set_vt_switch(int do_switch)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_VT_CONSOLE_SLEEP
|
#ifdef CONFIG_VT_CONSOLE_SLEEP
|
||||||
extern int pm_prepare_console(void);
|
extern void pm_prepare_console(void);
|
||||||
extern void pm_restore_console(void);
|
extern void pm_restore_console(void);
|
||||||
#else
|
#else
|
||||||
static inline int pm_prepare_console(void)
|
static inline void pm_prepare_console(void)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pm_restore_console(void)
|
static inline void pm_restore_console(void)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG
|
ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG
|
||||||
|
|
||||||
|
KASAN_SANITIZE_snapshot.o := n
|
||||||
|
|
||||||
obj-y += qos.o
|
obj-y += qos.o
|
||||||
obj-$(CONFIG_PM) += main.o
|
obj-$(CONFIG_PM) += main.o
|
||||||
obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o
|
obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o
|
||||||
|
|
|
@ -126,17 +126,17 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pm_prepare_console(void)
|
void pm_prepare_console(void)
|
||||||
{
|
{
|
||||||
if (!pm_vt_switch())
|
if (!pm_vt_switch())
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
orig_fgconsole = vt_move_to_console(SUSPEND_CONSOLE, 1);
|
orig_fgconsole = vt_move_to_console(SUSPEND_CONSOLE, 1);
|
||||||
if (orig_fgconsole < 0)
|
if (orig_fgconsole < 0)
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
orig_kmsg = vt_kmsg_redirect(SUSPEND_CONSOLE);
|
orig_kmsg = vt_kmsg_redirect(SUSPEND_CONSOLE);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pm_restore_console(void)
|
void pm_restore_console(void)
|
||||||
|
|
|
@ -52,6 +52,7 @@ enum {
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
HIBERNATION_SUSPEND,
|
HIBERNATION_SUSPEND,
|
||||||
#endif
|
#endif
|
||||||
|
HIBERNATION_TEST_RESUME,
|
||||||
/* keep last */
|
/* keep last */
|
||||||
__HIBERNATION_AFTER_LAST
|
__HIBERNATION_AFTER_LAST
|
||||||
};
|
};
|
||||||
|
@ -409,6 +410,11 @@ int hibernation_snapshot(int platform_mode)
|
||||||
goto Close;
|
goto Close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __weak hibernate_resume_nonboot_cpu_disable(void)
|
||||||
|
{
|
||||||
|
return disable_nonboot_cpus();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* resume_target_kernel - Restore system state from a hibernation image.
|
* resume_target_kernel - Restore system state from a hibernation image.
|
||||||
* @platform_mode: Whether or not to use the platform driver.
|
* @platform_mode: Whether or not to use the platform driver.
|
||||||
|
@ -433,7 +439,7 @@ static int resume_target_kernel(bool platform_mode)
|
||||||
if (error)
|
if (error)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
error = disable_nonboot_cpus();
|
error = hibernate_resume_nonboot_cpu_disable();
|
||||||
if (error)
|
if (error)
|
||||||
goto Enable_cpus;
|
goto Enable_cpus;
|
||||||
|
|
||||||
|
@ -642,12 +648,39 @@ static void power_down(void)
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int load_image_and_restore(void)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
unsigned int flags;
|
||||||
|
|
||||||
|
pr_debug("PM: Loading hibernation image.\n");
|
||||||
|
|
||||||
|
lock_device_hotplug();
|
||||||
|
error = create_basic_memory_bitmaps();
|
||||||
|
if (error)
|
||||||
|
goto Unlock;
|
||||||
|
|
||||||
|
error = swsusp_read(&flags);
|
||||||
|
swsusp_close(FMODE_READ);
|
||||||
|
if (!error)
|
||||||
|
hibernation_restore(flags & SF_PLATFORM_MODE);
|
||||||
|
|
||||||
|
printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
|
||||||
|
swsusp_free();
|
||||||
|
free_basic_memory_bitmaps();
|
||||||
|
Unlock:
|
||||||
|
unlock_device_hotplug();
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hibernate - Carry out system hibernation, including saving the image.
|
* hibernate - Carry out system hibernation, including saving the image.
|
||||||
*/
|
*/
|
||||||
int hibernate(void)
|
int hibernate(void)
|
||||||
{
|
{
|
||||||
int error;
|
int error, nr_calls = 0;
|
||||||
|
bool snapshot_test = false;
|
||||||
|
|
||||||
if (!hibernation_available()) {
|
if (!hibernation_available()) {
|
||||||
pr_debug("PM: Hibernation not available.\n");
|
pr_debug("PM: Hibernation not available.\n");
|
||||||
|
@ -662,9 +695,11 @@ int hibernate(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_prepare_console();
|
pm_prepare_console();
|
||||||
error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
|
error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
|
||||||
if (error)
|
if (error) {
|
||||||
|
nr_calls--;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "PM: Syncing filesystems ... ");
|
printk(KERN_INFO "PM: Syncing filesystems ... ");
|
||||||
sys_sync();
|
sys_sync();
|
||||||
|
@ -697,8 +732,12 @@ int hibernate(void)
|
||||||
pr_debug("PM: writing image.\n");
|
pr_debug("PM: writing image.\n");
|
||||||
error = swsusp_write(flags);
|
error = swsusp_write(flags);
|
||||||
swsusp_free();
|
swsusp_free();
|
||||||
if (!error)
|
if (!error) {
|
||||||
power_down();
|
if (hibernation_mode == HIBERNATION_TEST_RESUME)
|
||||||
|
snapshot_test = true;
|
||||||
|
else
|
||||||
|
power_down();
|
||||||
|
}
|
||||||
in_suspend = 0;
|
in_suspend = 0;
|
||||||
pm_restore_gfp_mask();
|
pm_restore_gfp_mask();
|
||||||
} else {
|
} else {
|
||||||
|
@ -709,12 +748,18 @@ int hibernate(void)
|
||||||
free_basic_memory_bitmaps();
|
free_basic_memory_bitmaps();
|
||||||
Thaw:
|
Thaw:
|
||||||
unlock_device_hotplug();
|
unlock_device_hotplug();
|
||||||
|
if (snapshot_test) {
|
||||||
|
pr_debug("PM: Checking hibernation image\n");
|
||||||
|
error = swsusp_check();
|
||||||
|
if (!error)
|
||||||
|
error = load_image_and_restore();
|
||||||
|
}
|
||||||
thaw_processes();
|
thaw_processes();
|
||||||
|
|
||||||
/* Don't bother checking whether freezer_test_done is true */
|
/* Don't bother checking whether freezer_test_done is true */
|
||||||
freezer_test_done = false;
|
freezer_test_done = false;
|
||||||
Exit:
|
Exit:
|
||||||
pm_notifier_call_chain(PM_POST_HIBERNATION);
|
__pm_notifier_call_chain(PM_POST_HIBERNATION, nr_calls, NULL);
|
||||||
pm_restore_console();
|
pm_restore_console();
|
||||||
atomic_inc(&snapshot_device_available);
|
atomic_inc(&snapshot_device_available);
|
||||||
Unlock:
|
Unlock:
|
||||||
|
@ -740,8 +785,7 @@ int hibernate(void)
|
||||||
*/
|
*/
|
||||||
static int software_resume(void)
|
static int software_resume(void)
|
||||||
{
|
{
|
||||||
int error;
|
int error, nr_calls = 0;
|
||||||
unsigned int flags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the user said "noresume".. bail out early.
|
* If the user said "noresume".. bail out early.
|
||||||
|
@ -827,35 +871,20 @@ static int software_resume(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_prepare_console();
|
pm_prepare_console();
|
||||||
error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
|
error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
|
||||||
if (error)
|
if (error) {
|
||||||
|
nr_calls--;
|
||||||
goto Close_Finish;
|
goto Close_Finish;
|
||||||
|
}
|
||||||
|
|
||||||
pr_debug("PM: Preparing processes for restore.\n");
|
pr_debug("PM: Preparing processes for restore.\n");
|
||||||
error = freeze_processes();
|
error = freeze_processes();
|
||||||
if (error)
|
if (error)
|
||||||
goto Close_Finish;
|
goto Close_Finish;
|
||||||
|
error = load_image_and_restore();
|
||||||
pr_debug("PM: Loading hibernation image.\n");
|
|
||||||
|
|
||||||
lock_device_hotplug();
|
|
||||||
error = create_basic_memory_bitmaps();
|
|
||||||
if (error)
|
|
||||||
goto Thaw;
|
|
||||||
|
|
||||||
error = swsusp_read(&flags);
|
|
||||||
swsusp_close(FMODE_READ);
|
|
||||||
if (!error)
|
|
||||||
hibernation_restore(flags & SF_PLATFORM_MODE);
|
|
||||||
|
|
||||||
printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
|
|
||||||
swsusp_free();
|
|
||||||
free_basic_memory_bitmaps();
|
|
||||||
Thaw:
|
|
||||||
unlock_device_hotplug();
|
|
||||||
thaw_processes();
|
thaw_processes();
|
||||||
Finish:
|
Finish:
|
||||||
pm_notifier_call_chain(PM_POST_RESTORE);
|
__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
|
||||||
pm_restore_console();
|
pm_restore_console();
|
||||||
atomic_inc(&snapshot_device_available);
|
atomic_inc(&snapshot_device_available);
|
||||||
/* For success case, the suspend path will release the lock */
|
/* For success case, the suspend path will release the lock */
|
||||||
|
@ -878,6 +907,7 @@ static const char * const hibernation_modes[] = {
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
[HIBERNATION_SUSPEND] = "suspend",
|
[HIBERNATION_SUSPEND] = "suspend",
|
||||||
#endif
|
#endif
|
||||||
|
[HIBERNATION_TEST_RESUME] = "test_resume",
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -924,6 +954,7 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
case HIBERNATION_SUSPEND:
|
case HIBERNATION_SUSPEND:
|
||||||
#endif
|
#endif
|
||||||
|
case HIBERNATION_TEST_RESUME:
|
||||||
break;
|
break;
|
||||||
case HIBERNATION_PLATFORM:
|
case HIBERNATION_PLATFORM:
|
||||||
if (hibernation_ops)
|
if (hibernation_ops)
|
||||||
|
@ -970,6 +1001,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
case HIBERNATION_SUSPEND:
|
case HIBERNATION_SUSPEND:
|
||||||
#endif
|
#endif
|
||||||
|
case HIBERNATION_TEST_RESUME:
|
||||||
hibernation_mode = mode;
|
hibernation_mode = mode;
|
||||||
break;
|
break;
|
||||||
case HIBERNATION_PLATFORM:
|
case HIBERNATION_PLATFORM:
|
||||||
|
@ -1115,13 +1147,16 @@ static int __init resume_offset_setup(char *str)
|
||||||
|
|
||||||
static int __init hibernate_setup(char *str)
|
static int __init hibernate_setup(char *str)
|
||||||
{
|
{
|
||||||
if (!strncmp(str, "noresume", 8))
|
if (!strncmp(str, "noresume", 8)) {
|
||||||
noresume = 1;
|
noresume = 1;
|
||||||
else if (!strncmp(str, "nocompress", 10))
|
} else if (!strncmp(str, "nocompress", 10)) {
|
||||||
nocompress = 1;
|
nocompress = 1;
|
||||||
else if (!strncmp(str, "no", 2)) {
|
} else if (!strncmp(str, "no", 2)) {
|
||||||
noresume = 1;
|
noresume = 1;
|
||||||
nohibernate = 1;
|
nohibernate = 1;
|
||||||
|
} else if (IS_ENABLED(CONFIG_DEBUG_RODATA)
|
||||||
|
&& !strncmp(str, "protect_image", 13)) {
|
||||||
|
enable_restore_image_protection();
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,19 @@ int unregister_pm_notifier(struct notifier_block *nb)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(unregister_pm_notifier);
|
EXPORT_SYMBOL_GPL(unregister_pm_notifier);
|
||||||
|
|
||||||
int pm_notifier_call_chain(unsigned long val)
|
int __pm_notifier_call_chain(unsigned long val, int nr_to_call, int *nr_calls)
|
||||||
{
|
{
|
||||||
int ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL);
|
int ret;
|
||||||
|
|
||||||
|
ret = __blocking_notifier_call_chain(&pm_chain_head, val, NULL,
|
||||||
|
nr_to_call, nr_calls);
|
||||||
|
|
||||||
return notifier_to_errno(ret);
|
return notifier_to_errno(ret);
|
||||||
}
|
}
|
||||||
|
int pm_notifier_call_chain(unsigned long val)
|
||||||
|
{
|
||||||
|
return __pm_notifier_call_chain(val, -1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* If set, devices may be suspended and resumed asynchronously. */
|
/* If set, devices may be suspended and resumed asynchronously. */
|
||||||
int pm_async_enabled = 1;
|
int pm_async_enabled = 1;
|
||||||
|
|
|
@ -38,6 +38,8 @@ static inline char *check_image_kernel(struct swsusp_info *info)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
|
#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
|
||||||
|
|
||||||
|
extern int hibernate_resume_nonboot_cpu_disable(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep some memory free so that I/O operations can succeed without paging
|
* Keep some memory free so that I/O operations can succeed without paging
|
||||||
* [Might this be more than 4 MB?]
|
* [Might this be more than 4 MB?]
|
||||||
|
@ -59,6 +61,13 @@ extern int hibernation_snapshot(int platform_mode);
|
||||||
extern int hibernation_restore(int platform_mode);
|
extern int hibernation_restore(int platform_mode);
|
||||||
extern int hibernation_platform_enter(void);
|
extern int hibernation_platform_enter(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_RODATA
|
||||||
|
/* kernel/power/snapshot.c */
|
||||||
|
extern void enable_restore_image_protection(void);
|
||||||
|
#else
|
||||||
|
static inline void enable_restore_image_protection(void) {}
|
||||||
|
#endif /* CONFIG_DEBUG_RODATA */
|
||||||
|
|
||||||
#else /* !CONFIG_HIBERNATION */
|
#else /* !CONFIG_HIBERNATION */
|
||||||
|
|
||||||
static inline void hibernate_reserved_size_init(void) {}
|
static inline void hibernate_reserved_size_init(void) {}
|
||||||
|
@ -200,6 +209,8 @@ static inline void suspend_test_finish(const char *label) {}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
/* kernel/power/main.c */
|
/* kernel/power/main.c */
|
||||||
|
extern int __pm_notifier_call_chain(unsigned long val, int nr_to_call,
|
||||||
|
int *nr_calls);
|
||||||
extern int pm_notifier_call_chain(unsigned long val);
|
extern int pm_notifier_call_chain(unsigned long val);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,9 @@ static int try_to_freeze_tasks(bool user_only)
|
||||||
elapsed_msecs / 1000, elapsed_msecs % 1000,
|
elapsed_msecs / 1000, elapsed_msecs % 1000,
|
||||||
todo - wq_busy, wq_busy);
|
todo - wq_busy, wq_busy);
|
||||||
|
|
||||||
|
if (wq_busy)
|
||||||
|
show_workqueue_state();
|
||||||
|
|
||||||
if (!wakeup) {
|
if (!wakeup) {
|
||||||
read_lock(&tasklist_lock);
|
read_lock(&tasklist_lock);
|
||||||
for_each_process_thread(g, p) {
|
for_each_process_thread(g, p) {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -266,16 +266,18 @@ static int suspend_test(int level)
|
||||||
*/
|
*/
|
||||||
static int suspend_prepare(suspend_state_t state)
|
static int suspend_prepare(suspend_state_t state)
|
||||||
{
|
{
|
||||||
int error;
|
int error, nr_calls = 0;
|
||||||
|
|
||||||
if (!sleep_state_supported(state))
|
if (!sleep_state_supported(state))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
pm_prepare_console();
|
pm_prepare_console();
|
||||||
|
|
||||||
error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
|
error = __pm_notifier_call_chain(PM_SUSPEND_PREPARE, -1, &nr_calls);
|
||||||
if (error)
|
if (error) {
|
||||||
|
nr_calls--;
|
||||||
goto Finish;
|
goto Finish;
|
||||||
|
}
|
||||||
|
|
||||||
trace_suspend_resume(TPS("freeze_processes"), 0, true);
|
trace_suspend_resume(TPS("freeze_processes"), 0, true);
|
||||||
error = suspend_freeze_processes();
|
error = suspend_freeze_processes();
|
||||||
|
@ -286,7 +288,7 @@ static int suspend_prepare(suspend_state_t state)
|
||||||
suspend_stats.failed_freeze++;
|
suspend_stats.failed_freeze++;
|
||||||
dpm_save_failed_step(SUSPEND_FREEZE);
|
dpm_save_failed_step(SUSPEND_FREEZE);
|
||||||
Finish:
|
Finish:
|
||||||
pm_notifier_call_chain(PM_POST_SUSPEND);
|
__pm_notifier_call_chain(PM_POST_SUSPEND, nr_calls, NULL);
|
||||||
pm_restore_console();
|
pm_restore_console();
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,6 +348,12 @@ static int swsusp_swap_check(void)
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
blkdev_put(hib_resume_bdev, FMODE_WRITE);
|
blkdev_put(hib_resume_bdev, FMODE_WRITE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the resume device to the one actually used,
|
||||||
|
* so the test_resume mode can use it in case it is
|
||||||
|
* invoked from hibernate() to test the snapshot.
|
||||||
|
*/
|
||||||
|
swsusp_resume_device = hib_resume_bdev->bd_dev;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ atomic_t snapshot_device_available = ATOMIC_INIT(1);
|
||||||
static int snapshot_open(struct inode *inode, struct file *filp)
|
static int snapshot_open(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
struct snapshot_data *data;
|
struct snapshot_data *data;
|
||||||
int error;
|
int error, nr_calls = 0;
|
||||||
|
|
||||||
if (!hibernation_available())
|
if (!hibernation_available())
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
@ -74,9 +74,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
|
||||||
swap_type_of(swsusp_resume_device, 0, NULL) : -1;
|
swap_type_of(swsusp_resume_device, 0, NULL) : -1;
|
||||||
data->mode = O_RDONLY;
|
data->mode = O_RDONLY;
|
||||||
data->free_bitmaps = false;
|
data->free_bitmaps = false;
|
||||||
error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
|
error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
|
||||||
if (error)
|
if (error)
|
||||||
pm_notifier_call_chain(PM_POST_HIBERNATION);
|
__pm_notifier_call_chain(PM_POST_HIBERNATION, --nr_calls, NULL);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Resuming. We may need to wait for the image device to
|
* Resuming. We may need to wait for the image device to
|
||||||
|
@ -86,13 +86,15 @@ static int snapshot_open(struct inode *inode, struct file *filp)
|
||||||
|
|
||||||
data->swap = -1;
|
data->swap = -1;
|
||||||
data->mode = O_WRONLY;
|
data->mode = O_WRONLY;
|
||||||
error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
|
error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
error = create_basic_memory_bitmaps();
|
error = create_basic_memory_bitmaps();
|
||||||
data->free_bitmaps = !error;
|
data->free_bitmaps = !error;
|
||||||
}
|
} else
|
||||||
|
nr_calls--;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
pm_notifier_call_chain(PM_POST_RESTORE);
|
__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
|
||||||
}
|
}
|
||||||
if (error)
|
if (error)
|
||||||
atomic_inc(&snapshot_device_available);
|
atomic_inc(&snapshot_device_available);
|
||||||
|
|
|
@ -4369,8 +4369,8 @@ static void show_pwq(struct pool_workqueue *pwq)
|
||||||
/**
|
/**
|
||||||
* show_workqueue_state - dump workqueue state
|
* show_workqueue_state - dump workqueue state
|
||||||
*
|
*
|
||||||
* Called from a sysrq handler and prints out all busy workqueues and
|
* Called from a sysrq handler or try_to_freeze_tasks() and prints out
|
||||||
* pools.
|
* all busy workqueues and pools.
|
||||||
*/
|
*/
|
||||||
void show_workqueue_state(void)
|
void show_workqueue_state(void)
|
||||||
{
|
{
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC = $(CROSS_COMPILE)gcc
|
||||||
BUILD_OUTPUT := $(CURDIR)
|
BUILD_OUTPUT := $(CURDIR)
|
||||||
PREFIX := /usr
|
PREFIX ?= /usr
|
||||||
DESTDIR :=
|
DESTDIR ?=
|
||||||
|
|
||||||
ifeq ("$(origin O)", "command line")
|
ifeq ("$(origin O)", "command line")
|
||||||
BUILD_OUTPUT := $(O)
|
BUILD_OUTPUT := $(O)
|
||||||
|
|
Loading…
Reference in New Issue