[PATCH] swsusp: debugging
Add a swsusp debugging mode. This does everything that's needed for a suspend except for actually suspending. So we can look in the log messages and work out a) what code is being slow and b) which drivers are misbehaving. (1) # echo testproc > /sys/power/disk # echo disk > /sys/power/state This should turn off the non-boot CPU, freeze all processes, wait for 5 seconds and then thaw the processes and the CPU. (2) # echo test > /sys/power/disk # echo disk > /sys/power/state This should turn off the non-boot CPU, freeze all processes, shrink memory, suspend all devices, wait for 5 seconds, resume the devices etc. Cc: Pavel Machek <pavel@ucw.cz> Cc: Stefan Seyfried <seife@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
90d5390944
commit
b918f6e62c
@ -21,7 +21,7 @@ Description:
|
||||
these states.
|
||||
|
||||
What: /sys/power/disk
|
||||
Date: August 2006
|
||||
Date: September 2006
|
||||
Contact: Rafael J. Wysocki <rjw@sisk.pl>
|
||||
Description:
|
||||
The /sys/power/disk file controls the operating mode of the
|
||||
@ -39,6 +39,19 @@ Description:
|
||||
'reboot' - the memory image will be saved by the kernel and
|
||||
the system will be rebooted.
|
||||
|
||||
Additionally, /sys/power/disk can be used to turn on one of the
|
||||
two testing modes of the suspend-to-disk mechanism: 'testproc'
|
||||
or 'test'. If the suspend-to-disk mechanism is in the
|
||||
'testproc' mode, writing 'disk' to /sys/power/state will cause
|
||||
the kernel to disable nonboot CPUs and freeze tasks, wait for 5
|
||||
seconds, unfreeze tasks and enable nonboot CPUs. If it is in
|
||||
the 'test' mode, writing 'disk' to /sys/power/state will cause
|
||||
the kernel to disable nonboot CPUs and freeze tasks, shrink
|
||||
memory, suspend devices, wait for 5 seconds, resume devices,
|
||||
unfreeze tasks and enable nonboot CPUs. Then, we are able to
|
||||
look in the log messages and work out, for example, which code
|
||||
is being slow and which device drivers are misbehaving.
|
||||
|
||||
The suspend-to-disk method may be chosen by writing to this
|
||||
file one of the accepted strings:
|
||||
|
||||
@ -46,6 +59,8 @@ Description:
|
||||
'platform'
|
||||
'shutdown'
|
||||
'reboot'
|
||||
'testproc'
|
||||
'test'
|
||||
|
||||
It will only change to 'firmware' or 'platform' if the system
|
||||
supports that.
|
||||
|
@ -30,6 +30,17 @@ testing). The system will support either 'firmware' or 'platform', and
|
||||
that is known a priori. But, the user may choose 'shutdown' or
|
||||
'reboot' as alternatives.
|
||||
|
||||
Additionally, /sys/power/disk can be used to turn on one of the two testing
|
||||
modes of the suspend-to-disk mechanism: 'testproc' or 'test'. If the
|
||||
suspend-to-disk mechanism is in the 'testproc' mode, writing 'disk' to
|
||||
/sys/power/state will cause the kernel to disable nonboot CPUs and freeze
|
||||
tasks, wait for 5 seconds, unfreeze tasks and enable nonboot CPUs. If it is
|
||||
in the 'test' mode, writing 'disk' to /sys/power/state will cause the kernel
|
||||
to disable nonboot CPUs and freeze tasks, shrink memory, suspend devices, wait
|
||||
for 5 seconds, resume devices, unfreeze tasks and enable nonboot CPUs. Then,
|
||||
we are able to look in the log messages and work out, for example, which code
|
||||
is being slow and which device drivers are misbehaving.
|
||||
|
||||
Reading from this file will display what the mode is currently set
|
||||
to. Writing to this file will accept one of
|
||||
|
||||
@ -37,6 +48,8 @@ to. Writing to this file will accept one of
|
||||
'platform'
|
||||
'shutdown'
|
||||
'reboot'
|
||||
'testproc'
|
||||
'test'
|
||||
|
||||
It will only change to 'firmware' or 'platform' if the system supports
|
||||
it.
|
||||
|
@ -116,7 +116,9 @@ typedef int __bitwise suspend_disk_method_t;
|
||||
#define PM_DISK_PLATFORM ((__force suspend_disk_method_t) 2)
|
||||
#define PM_DISK_SHUTDOWN ((__force suspend_disk_method_t) 3)
|
||||
#define PM_DISK_REBOOT ((__force suspend_disk_method_t) 4)
|
||||
#define PM_DISK_MAX ((__force suspend_disk_method_t) 5)
|
||||
#define PM_DISK_TEST ((__force suspend_disk_method_t) 5)
|
||||
#define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 6)
|
||||
#define PM_DISK_MAX ((__force suspend_disk_method_t) 7)
|
||||
|
||||
struct pm_ops {
|
||||
suspend_disk_method_t pm_disk_mode;
|
||||
|
@ -71,7 +71,7 @@ static inline void platform_finish(void)
|
||||
|
||||
static int prepare_processes(void)
|
||||
{
|
||||
int error;
|
||||
int error = 0;
|
||||
|
||||
pm_prepare_console();
|
||||
|
||||
@ -84,6 +84,12 @@ static int prepare_processes(void)
|
||||
goto thaw;
|
||||
}
|
||||
|
||||
if (pm_disk_mode == PM_DISK_TESTPROC) {
|
||||
printk("swsusp debug: Waiting for 5 seconds.\n");
|
||||
mdelay(5000);
|
||||
goto thaw;
|
||||
}
|
||||
|
||||
/* Free memory before shutting down devices. */
|
||||
if (!(error = swsusp_shrink_memory()))
|
||||
return 0;
|
||||
@ -120,13 +126,21 @@ int pm_suspend_disk(void)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (pm_disk_mode == PM_DISK_TESTPROC)
|
||||
goto Thaw;
|
||||
|
||||
suspend_console();
|
||||
error = device_suspend(PMSG_FREEZE);
|
||||
if (error) {
|
||||
resume_console();
|
||||
printk("Some devices failed to suspend\n");
|
||||
unprepare_processes();
|
||||
return error;
|
||||
goto Thaw;
|
||||
}
|
||||
|
||||
if (pm_disk_mode == PM_DISK_TEST) {
|
||||
printk("swsusp debug: Waiting for 5 seconds.\n");
|
||||
mdelay(5000);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
pr_debug("PM: snapshotting memory.\n");
|
||||
@ -143,16 +157,17 @@ int pm_suspend_disk(void)
|
||||
power_down(pm_disk_mode);
|
||||
else {
|
||||
swsusp_free();
|
||||
unprepare_processes();
|
||||
return error;
|
||||
goto Thaw;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
pr_debug("PM: Image restored successfully.\n");
|
||||
}
|
||||
|
||||
swsusp_free();
|
||||
Done:
|
||||
device_resume();
|
||||
resume_console();
|
||||
Thaw:
|
||||
unprepare_processes();
|
||||
return error;
|
||||
}
|
||||
@ -249,6 +264,8 @@ static const char * const pm_disk_modes[] = {
|
||||
[PM_DISK_PLATFORM] = "platform",
|
||||
[PM_DISK_SHUTDOWN] = "shutdown",
|
||||
[PM_DISK_REBOOT] = "reboot",
|
||||
[PM_DISK_TEST] = "test",
|
||||
[PM_DISK_TESTPROC] = "testproc",
|
||||
};
|
||||
|
||||
/**
|
||||
@ -303,17 +320,19 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n)
|
||||
}
|
||||
}
|
||||
if (mode) {
|
||||
if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT)
|
||||
if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT ||
|
||||
mode == PM_DISK_TEST || mode == PM_DISK_TESTPROC) {
|
||||
pm_disk_mode = mode;
|
||||
else {
|
||||
} else {
|
||||
if (pm_ops && pm_ops->enter &&
|
||||
(mode == pm_ops->pm_disk_mode))
|
||||
pm_disk_mode = mode;
|
||||
else
|
||||
error = -EINVAL;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
error = -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("PM: suspend-to-disk mode set to '%s'\n",
|
||||
pm_disk_modes[mode]);
|
||||
|
Loading…
Reference in New Issue
Block a user