aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/power.h2
-rw-r--r--kernel/power/snapshot.c19
-rw-r--r--kernel/power/swsusp.c75
3 files changed, 47 insertions, 49 deletions
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 893ee655085c..6c042b5ee14b 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -65,10 +65,8 @@ extern suspend_pagedir_t *pagedir_save;
65extern asmlinkage int swsusp_arch_suspend(void); 65extern asmlinkage int swsusp_arch_suspend(void);
66extern asmlinkage int swsusp_arch_resume(void); 66extern asmlinkage int swsusp_arch_resume(void);
67 67
68extern int restore_highmem(void);
69extern void free_pagedir(struct pbe *pblist); 68extern void free_pagedir(struct pbe *pblist);
70extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); 69extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed);
71extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); 70extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages);
72extern void swsusp_free(void); 71extern void swsusp_free(void);
73extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed); 72extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed);
74extern int enough_swap(unsigned nr_pages);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index b8a2e9a63206..4a6dbcefd378 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -88,8 +88,7 @@ static int save_highmem_zone(struct zone *zone)
88 return 0; 88 return 0;
89} 89}
90 90
91 91int save_highmem(void)
92static int save_highmem(void)
93{ 92{
94 struct zone *zone; 93 struct zone *zone;
95 int res = 0; 94 int res = 0;
@@ -120,11 +119,7 @@ int restore_highmem(void)
120 } 119 }
121 return 0; 120 return 0;
122} 121}
123#else 122#endif
124static int save_highmem(void) { return 0; }
125int restore_highmem(void) { return 0; }
126#endif /* CONFIG_HIGHMEM */
127
128 123
129static int pfn_is_nosave(unsigned long pfn) 124static int pfn_is_nosave(unsigned long pfn)
130{ 125{
@@ -416,11 +411,6 @@ asmlinkage int swsusp_save(void)
416 unsigned int nr_pages; 411 unsigned int nr_pages;
417 412
418 pr_debug("swsusp: critical section: \n"); 413 pr_debug("swsusp: critical section: \n");
419 if (save_highmem()) {
420 printk(KERN_CRIT "swsusp: Not enough free pages for highmem\n");
421 restore_highmem();
422 return -ENOMEM;
423 }
424 414
425 drain_local_pages(); 415 drain_local_pages();
426 nr_pages = count_data_pages(); 416 nr_pages = count_data_pages();
@@ -440,11 +430,6 @@ asmlinkage int swsusp_save(void)
440 return -ENOMEM; 430 return -ENOMEM;
441 } 431 }
442 432
443 if (!enough_swap(nr_pages)) {
444 printk(KERN_ERR "swsusp: Not enough free swap\n");
445 return -ENOSPC;
446 }
447
448 pagedir_nosave = swsusp_alloc(nr_pages); 433 pagedir_nosave = swsusp_alloc(nr_pages);
449 if (!pagedir_nosave) 434 if (!pagedir_nosave)
450 return -ENOMEM; 435 return -ENOMEM;
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 8511c7f3386a..c05f46e7348f 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -73,6 +73,14 @@
73 73
74#include "power.h" 74#include "power.h"
75 75
76#ifdef CONFIG_HIGHMEM
77int save_highmem(void);
78int restore_highmem(void);
79#else
80static int save_highmem(void) { return 0; }
81static int restore_highmem(void) { return 0; }
82#endif
83
76#define CIPHER "aes" 84#define CIPHER "aes"
77#define MAXKEY 32 85#define MAXKEY 32
78#define MAXIV 32 86#define MAXIV 32
@@ -500,6 +508,26 @@ static int write_pagedir(void)
500} 508}
501 509
502/** 510/**
511 * enough_swap - Make sure we have enough swap to save the image.
512 *
513 * Returns TRUE or FALSE after checking the total amount of swap
514 * space avaiable.
515 *
516 * FIXME: si_swapinfo(&i) returns all swap devices information.
517 * We should only consider resume_device.
518 */
519
520static int enough_swap(unsigned int nr_pages)
521{
522 struct sysinfo i;
523
524 si_swapinfo(&i);
525 pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
526 return i.freeswap > (nr_pages + PAGES_FOR_IO +
527 (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
528}
529
530/**
503 * write_suspend_image - Write entire image and metadata. 531 * write_suspend_image - Write entire image and metadata.
504 * 532 *
505 */ 533 */
@@ -507,6 +535,11 @@ static int write_suspend_image(void)
507{ 535{
508 int error; 536 int error;
509 537
538 if (!enough_swap(nr_copy_pages)) {
539 printk(KERN_ERR "swsusp: Not enough free swap\n");
540 return -ENOSPC;
541 }
542
510 init_header(); 543 init_header();
511 if ((error = data_write())) 544 if ((error = data_write()))
512 goto FreeData; 545 goto FreeData;
@@ -526,27 +559,6 @@ static int write_suspend_image(void)
526 goto Done; 559 goto Done;
527} 560}
528 561
529/**
530 * enough_swap - Make sure we have enough swap to save the image.
531 *
532 * Returns TRUE or FALSE after checking the total amount of swap
533 * space avaiable.
534 *
535 * FIXME: si_swapinfo(&i) returns all swap devices information.
536 * We should only consider resume_device.
537 */
538
539int enough_swap(unsigned int nr_pages)
540{
541 struct sysinfo i;
542
543 si_swapinfo(&i);
544 pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
545 return i.freeswap > (nr_pages + PAGES_FOR_IO +
546 (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
547}
548
549
550/* It is important _NOT_ to umount filesystems at this point. We want 562/* It is important _NOT_ to umount filesystems at this point. We want
551 * them synced (in case something goes wrong) but we DO not want to mark 563 * them synced (in case something goes wrong) but we DO not want to mark
552 * filesystem clean: it is not. (And it does not matter, if we resume 564 * filesystem clean: it is not. (And it does not matter, if we resume
@@ -556,12 +568,15 @@ int swsusp_write(void)
556{ 568{
557 int error; 569 int error;
558 570
571 if ((error = swsusp_swap_check())) {
572 printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n");
573 return error;
574 }
559 lock_swapdevices(); 575 lock_swapdevices();
560 error = write_suspend_image(); 576 error = write_suspend_image();
561 /* This will unlock ignored swap devices since writing is finished */ 577 /* This will unlock ignored swap devices since writing is finished */
562 lock_swapdevices(); 578 lock_swapdevices();
563 return error; 579 return error;
564
565} 580}
566 581
567 582
@@ -569,6 +584,7 @@ int swsusp_write(void)
569int swsusp_suspend(void) 584int swsusp_suspend(void)
570{ 585{
571 int error; 586 int error;
587
572 if ((error = arch_prepare_suspend())) 588 if ((error = arch_prepare_suspend()))
573 return error; 589 return error;
574 local_irq_disable(); 590 local_irq_disable();
@@ -580,15 +596,12 @@ int swsusp_suspend(void)
580 */ 596 */
581 if ((error = device_power_down(PMSG_FREEZE))) { 597 if ((error = device_power_down(PMSG_FREEZE))) {
582 printk(KERN_ERR "Some devices failed to power down, aborting suspend\n"); 598 printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
583 local_irq_enable(); 599 goto Enable_irqs;
584 return error;
585 } 600 }
586 601
587 if ((error = swsusp_swap_check())) { 602 if ((error = save_highmem())) {
588 printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n"); 603 printk(KERN_ERR "swsusp: Not enough free pages for highmem\n");
589 device_power_up(); 604 goto Restore_highmem;
590 local_irq_enable();
591 return error;
592 } 605 }
593 606
594 save_processor_state(); 607 save_processor_state();
@@ -596,8 +609,10 @@ int swsusp_suspend(void)
596 printk(KERN_ERR "Error %d suspending\n", error); 609 printk(KERN_ERR "Error %d suspending\n", error);
597 /* Restore control flow magically appears here */ 610 /* Restore control flow magically appears here */
598 restore_processor_state(); 611 restore_processor_state();
612Restore_highmem:
599 restore_highmem(); 613 restore_highmem();
600 device_power_up(); 614 device_power_up();
615Enable_irqs:
601 local_irq_enable(); 616 local_irq_enable();
602 return error; 617 return error;
603} 618}
@@ -804,7 +819,7 @@ static int check_sig(void)
804 * Reset swap signature now. 819 * Reset swap signature now.
805 */ 820 */
806 error = bio_write_page(0, &swsusp_header); 821 error = bio_write_page(0, &swsusp_header);
807 } else { 822 } else {
808 return -EINVAL; 823 return -EINVAL;
809 } 824 }
810 if (!error) 825 if (!error)