aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/disk.c')
-rw-r--r--kernel/power/disk.c101
1 files changed, 44 insertions, 57 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 027322a564f4..e03d85e55291 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -24,10 +24,11 @@
24 24
25extern suspend_disk_method_t pm_disk_mode; 25extern suspend_disk_method_t pm_disk_mode;
26 26
27extern int swsusp_shrink_memory(void);
27extern int swsusp_suspend(void); 28extern int swsusp_suspend(void);
28extern int swsusp_write(void); 29extern int swsusp_write(struct pbe *pblist, unsigned int nr_pages);
29extern int swsusp_check(void); 30extern int swsusp_check(void);
30extern int swsusp_read(void); 31extern int swsusp_read(struct pbe **pblist_ptr);
31extern void swsusp_close(void); 32extern void swsusp_close(void);
32extern int swsusp_resume(void); 33extern int swsusp_resume(void);
33 34
@@ -52,7 +53,7 @@ static void power_down(suspend_disk_method_t mode)
52 53
53 switch(mode) { 54 switch(mode) {
54 case PM_DISK_PLATFORM: 55 case PM_DISK_PLATFORM:
55 kernel_power_off_prepare(); 56 kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
56 error = pm_ops->enter(PM_SUSPEND_DISK); 57 error = pm_ops->enter(PM_SUSPEND_DISK);
57 break; 58 break;
58 case PM_DISK_SHUTDOWN: 59 case PM_DISK_SHUTDOWN:
@@ -73,31 +74,6 @@ static void power_down(suspend_disk_method_t mode)
73static int in_suspend __nosavedata = 0; 74static int in_suspend __nosavedata = 0;
74 75
75 76
76/**
77 * free_some_memory - Try to free as much memory as possible
78 *
79 * ... but do not OOM-kill anyone
80 *
81 * Notice: all userland should be stopped at this point, or
82 * livelock is possible.
83 */
84
85static void free_some_memory(void)
86{
87 unsigned int i = 0;
88 unsigned int tmp;
89 unsigned long pages = 0;
90 char *p = "-\\|/";
91
92 printk("Freeing memory... ");
93 while ((tmp = shrink_all_memory(10000))) {
94 pages += tmp;
95 printk("\b%c", p[i++ % 4]);
96 }
97 printk("\bdone (%li pages freed)\n", pages);
98}
99
100
101static inline void platform_finish(void) 77static inline void platform_finish(void)
102{ 78{
103 if (pm_disk_mode == PM_DISK_PLATFORM) { 79 if (pm_disk_mode == PM_DISK_PLATFORM) {
@@ -119,16 +95,9 @@ static int prepare_processes(void)
119 goto thaw; 95 goto thaw;
120 } 96 }
121 97
122 if (pm_disk_mode == PM_DISK_PLATFORM) {
123 if (pm_ops && pm_ops->prepare) {
124 if ((error = pm_ops->prepare(PM_SUSPEND_DISK)))
125 goto thaw;
126 }
127 }
128
129 /* Free memory before shutting down devices. */ 98 /* Free memory before shutting down devices. */
130 free_some_memory(); 99 if (!(error = swsusp_shrink_memory()))
131 return 0; 100 return 0;
132thaw: 101thaw:
133 thaw_processes(); 102 thaw_processes();
134 enable_nonboot_cpus(); 103 enable_nonboot_cpus();
@@ -176,7 +145,7 @@ int pm_suspend_disk(void)
176 if (in_suspend) { 145 if (in_suspend) {
177 device_resume(); 146 device_resume();
178 pr_debug("PM: writing image.\n"); 147 pr_debug("PM: writing image.\n");
179 error = swsusp_write(); 148 error = swsusp_write(pagedir_nosave, nr_copy_pages);
180 if (!error) 149 if (!error)
181 power_down(pm_disk_mode); 150 power_down(pm_disk_mode);
182 else { 151 else {
@@ -247,7 +216,7 @@ static int software_resume(void)
247 216
248 pr_debug("PM: Reading swsusp image.\n"); 217 pr_debug("PM: Reading swsusp image.\n");
249 218
250 if ((error = swsusp_read())) { 219 if ((error = swsusp_read(&pagedir_nosave))) {
251 swsusp_free(); 220 swsusp_free();
252 goto Thaw; 221 goto Thaw;
253 } 222 }
@@ -363,37 +332,55 @@ static ssize_t resume_show(struct subsystem * subsys, char *buf)
363 MINOR(swsusp_resume_device)); 332 MINOR(swsusp_resume_device));
364} 333}
365 334
366static ssize_t resume_store(struct subsystem * subsys, const char * buf, size_t n) 335static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n)
367{ 336{
368 int len;
369 char *p;
370 unsigned int maj, min; 337 unsigned int maj, min;
371 int error = -EINVAL;
372 dev_t res; 338 dev_t res;
339 int ret = -EINVAL;
373 340
374 p = memchr(buf, '\n', n); 341 if (sscanf(buf, "%u:%u", &maj, &min) != 2)
375 len = p ? p - buf : n; 342 goto out;
376 343
377 if (sscanf(buf, "%u:%u", &maj, &min) == 2) { 344 res = MKDEV(maj,min);
378 res = MKDEV(maj,min); 345 if (maj != MAJOR(res) || min != MINOR(res))
379 if (maj == MAJOR(res) && min == MINOR(res)) { 346 goto out;
380 down(&pm_sem);
381 swsusp_resume_device = res;
382 up(&pm_sem);
383 printk("Attempting manual resume\n");
384 noresume = 0;
385 software_resume();
386 }
387 }
388 347
389 return error >= 0 ? n : error; 348 down(&pm_sem);
349 swsusp_resume_device = res;
350 up(&pm_sem);
351 printk("Attempting manual resume\n");
352 noresume = 0;
353 software_resume();
354 ret = n;
355out:
356 return ret;
390} 357}
391 358
392power_attr(resume); 359power_attr(resume);
393 360
361static ssize_t image_size_show(struct subsystem * subsys, char *buf)
362{
363 return sprintf(buf, "%u\n", image_size);
364}
365
366static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n)
367{
368 unsigned int size;
369
370 if (sscanf(buf, "%u", &size) == 1) {
371 image_size = size;
372 return n;
373 }
374
375 return -EINVAL;
376}
377
378power_attr(image_size);
379
394static struct attribute * g[] = { 380static struct attribute * g[] = {
395 &disk_attr.attr, 381 &disk_attr.attr,
396 &resume_attr.attr, 382 &resume_attr.attr,
383 &image_size_attr.attr,
397 NULL, 384 NULL,
398}; 385};
399 386