Skip to content

Commit

Permalink
[PATCH] swsusp: debugging
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rafael J. Wysocki authored and Linus Torvalds committed Nov 3, 2006
1 parent 90d5390 commit b918f6e
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 11 deletions.
17 changes: 16 additions & 1 deletion Documentation/ABI/testing/sysfs-power
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -39,13 +39,28 @@ 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:

'firmware'
'platform'
'shutdown'
'reboot'
'testproc'
'test'

It will only change to 'firmware' or 'platform' if the system
supports that.
Expand Down
13 changes: 13 additions & 0 deletions Documentation/power/interface.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,26 @@ 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

'firmware'
'platform'
'shutdown'
'reboot'
'testproc'
'test'

It will only change to 'firmware' or 'platform' if the system supports
it.
Expand Down
4 changes: 3 additions & 1 deletion include/linux/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
37 changes: 28 additions & 9 deletions kernel/power/disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static inline void platform_finish(void)

static int prepare_processes(void)
{
int error;
int error = 0;

pm_prepare_console();

Expand All @@ -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;
Expand Down Expand Up @@ -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");
Expand All @@ -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;
}
Expand Down Expand Up @@ -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",
};

/**
Expand Down Expand Up @@ -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]);
Expand Down

0 comments on commit b918f6e

Please sign in to comment.