[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>

authored by Rafael J. Wysocki and committed by Linus Torvalds b918f6e6 90d53909

+60 -11
+16 -1
Documentation/ABI/testing/sysfs-power
··· 21 these states. 22 23 What: /sys/power/disk 24 - Date: August 2006 25 Contact: Rafael J. Wysocki <rjw@sisk.pl> 26 Description: 27 The /sys/power/disk file controls the operating mode of the ··· 39 'reboot' - the memory image will be saved by the kernel and 40 the system will be rebooted. 41 42 The suspend-to-disk method may be chosen by writing to this 43 file one of the accepted strings: 44 ··· 59 'platform' 60 'shutdown' 61 'reboot' 62 63 It will only change to 'firmware' or 'platform' if the system 64 supports that.
··· 21 these states. 22 23 What: /sys/power/disk 24 + Date: September 2006 25 Contact: Rafael J. Wysocki <rjw@sisk.pl> 26 Description: 27 The /sys/power/disk file controls the operating mode of the ··· 39 'reboot' - the memory image will be saved by the kernel and 40 the system will be rebooted. 41 42 + Additionally, /sys/power/disk can be used to turn on one of the 43 + two testing modes of the suspend-to-disk mechanism: 'testproc' 44 + or 'test'. If the suspend-to-disk mechanism is in the 45 + 'testproc' mode, writing 'disk' to /sys/power/state will cause 46 + the kernel to disable nonboot CPUs and freeze tasks, wait for 5 47 + seconds, unfreeze tasks and enable nonboot CPUs. If it is in 48 + the 'test' mode, writing 'disk' to /sys/power/state will cause 49 + the kernel to disable nonboot CPUs and freeze tasks, shrink 50 + memory, suspend devices, wait for 5 seconds, resume devices, 51 + unfreeze tasks and enable nonboot CPUs. Then, we are able to 52 + look in the log messages and work out, for example, which code 53 + is being slow and which device drivers are misbehaving. 54 + 55 The suspend-to-disk method may be chosen by writing to this 56 file one of the accepted strings: 57 ··· 46 'platform' 47 'shutdown' 48 'reboot' 49 + 'testproc' 50 + 'test' 51 52 It will only change to 'firmware' or 'platform' if the system 53 supports that.
+13
Documentation/power/interface.txt
··· 30 that is known a priori. But, the user may choose 'shutdown' or 31 'reboot' as alternatives. 32 33 Reading from this file will display what the mode is currently set 34 to. Writing to this file will accept one of 35 ··· 48 'platform' 49 'shutdown' 50 'reboot' 51 52 It will only change to 'firmware' or 'platform' if the system supports 53 it.
··· 30 that is known a priori. But, the user may choose 'shutdown' or 31 'reboot' as alternatives. 32 33 + Additionally, /sys/power/disk can be used to turn on one of the two testing 34 + modes of the suspend-to-disk mechanism: 'testproc' or 'test'. If the 35 + suspend-to-disk mechanism is in the 'testproc' mode, writing 'disk' to 36 + /sys/power/state will cause the kernel to disable nonboot CPUs and freeze 37 + tasks, wait for 5 seconds, unfreeze tasks and enable nonboot CPUs. If it is 38 + in the 'test' mode, writing 'disk' to /sys/power/state will cause the kernel 39 + to disable nonboot CPUs and freeze tasks, shrink memory, suspend devices, wait 40 + for 5 seconds, resume devices, unfreeze tasks and enable nonboot CPUs. Then, 41 + we are able to look in the log messages and work out, for example, which code 42 + is being slow and which device drivers are misbehaving. 43 + 44 Reading from this file will display what the mode is currently set 45 to. Writing to this file will accept one of 46 ··· 37 'platform' 38 'shutdown' 39 'reboot' 40 + 'testproc' 41 + 'test' 42 43 It will only change to 'firmware' or 'platform' if the system supports 44 it.
+3 -1
include/linux/pm.h
··· 116 #define PM_DISK_PLATFORM ((__force suspend_disk_method_t) 2) 117 #define PM_DISK_SHUTDOWN ((__force suspend_disk_method_t) 3) 118 #define PM_DISK_REBOOT ((__force suspend_disk_method_t) 4) 119 - #define PM_DISK_MAX ((__force suspend_disk_method_t) 5) 120 121 struct pm_ops { 122 suspend_disk_method_t pm_disk_mode;
··· 116 #define PM_DISK_PLATFORM ((__force suspend_disk_method_t) 2) 117 #define PM_DISK_SHUTDOWN ((__force suspend_disk_method_t) 3) 118 #define PM_DISK_REBOOT ((__force suspend_disk_method_t) 4) 119 + #define PM_DISK_TEST ((__force suspend_disk_method_t) 5) 120 + #define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 6) 121 + #define PM_DISK_MAX ((__force suspend_disk_method_t) 7) 122 123 struct pm_ops { 124 suspend_disk_method_t pm_disk_mode;
+28 -9
kernel/power/disk.c
··· 71 72 static int prepare_processes(void) 73 { 74 - int error; 75 76 pm_prepare_console(); 77 ··· 81 82 if (freeze_processes()) { 83 error = -EBUSY; 84 goto thaw; 85 } 86 ··· 126 if (error) 127 return error; 128 129 suspend_console(); 130 error = device_suspend(PMSG_FREEZE); 131 if (error) { 132 resume_console(); 133 printk("Some devices failed to suspend\n"); 134 - unprepare_processes(); 135 - return error; 136 } 137 138 pr_debug("PM: snapshotting memory.\n"); ··· 157 power_down(pm_disk_mode); 158 else { 159 swsusp_free(); 160 - unprepare_processes(); 161 - return error; 162 } 163 - } else 164 pr_debug("PM: Image restored successfully.\n"); 165 166 swsusp_free(); 167 Done: 168 device_resume(); 169 resume_console(); 170 unprepare_processes(); 171 return error; 172 } ··· 264 [PM_DISK_PLATFORM] = "platform", 265 [PM_DISK_SHUTDOWN] = "shutdown", 266 [PM_DISK_REBOOT] = "reboot", 267 }; 268 269 /** ··· 320 } 321 } 322 if (mode) { 323 - if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT) 324 pm_disk_mode = mode; 325 - else { 326 if (pm_ops && pm_ops->enter && 327 (mode == pm_ops->pm_disk_mode)) 328 pm_disk_mode = mode; 329 else 330 error = -EINVAL; 331 } 332 - } else 333 error = -EINVAL; 334 335 pr_debug("PM: suspend-to-disk mode set to '%s'\n", 336 pm_disk_modes[mode]);
··· 71 72 static int prepare_processes(void) 73 { 74 + int error = 0; 75 76 pm_prepare_console(); 77 ··· 81 82 if (freeze_processes()) { 83 error = -EBUSY; 84 + goto thaw; 85 + } 86 + 87 + if (pm_disk_mode == PM_DISK_TESTPROC) { 88 + printk("swsusp debug: Waiting for 5 seconds.\n"); 89 + mdelay(5000); 90 goto thaw; 91 } 92 ··· 120 if (error) 121 return error; 122 123 + if (pm_disk_mode == PM_DISK_TESTPROC) 124 + goto Thaw; 125 + 126 suspend_console(); 127 error = device_suspend(PMSG_FREEZE); 128 if (error) { 129 resume_console(); 130 printk("Some devices failed to suspend\n"); 131 + goto Thaw; 132 + } 133 + 134 + if (pm_disk_mode == PM_DISK_TEST) { 135 + printk("swsusp debug: Waiting for 5 seconds.\n"); 136 + mdelay(5000); 137 + goto Done; 138 } 139 140 pr_debug("PM: snapshotting memory.\n"); ··· 143 power_down(pm_disk_mode); 144 else { 145 swsusp_free(); 146 + goto Thaw; 147 } 148 + } else { 149 pr_debug("PM: Image restored successfully.\n"); 150 + } 151 152 swsusp_free(); 153 Done: 154 device_resume(); 155 resume_console(); 156 + Thaw: 157 unprepare_processes(); 158 return error; 159 } ··· 249 [PM_DISK_PLATFORM] = "platform", 250 [PM_DISK_SHUTDOWN] = "shutdown", 251 [PM_DISK_REBOOT] = "reboot", 252 + [PM_DISK_TEST] = "test", 253 + [PM_DISK_TESTPROC] = "testproc", 254 }; 255 256 /** ··· 303 } 304 } 305 if (mode) { 306 + if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT || 307 + mode == PM_DISK_TEST || mode == PM_DISK_TESTPROC) { 308 pm_disk_mode = mode; 309 + } else { 310 if (pm_ops && pm_ops->enter && 311 (mode == pm_ops->pm_disk_mode)) 312 pm_disk_mode = mode; 313 else 314 error = -EINVAL; 315 } 316 + } else { 317 error = -EINVAL; 318 + } 319 320 pr_debug("PM: suspend-to-disk mode set to '%s'\n", 321 pm_disk_modes[mode]);