diff options
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/power.h | 2 | ||||
-rw-r--r-- | kernel/power/snapshot.c | 19 | ||||
-rw-r--r-- | kernel/power/swsusp.c | 75 |
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; | |||
65 | extern asmlinkage int swsusp_arch_suspend(void); | 65 | extern asmlinkage int swsusp_arch_suspend(void); |
66 | extern asmlinkage int swsusp_arch_resume(void); | 66 | extern asmlinkage int swsusp_arch_resume(void); |
67 | 67 | ||
68 | extern int restore_highmem(void); | ||
69 | extern void free_pagedir(struct pbe *pblist); | 68 | extern void free_pagedir(struct pbe *pblist); |
70 | extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); | 69 | extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); |
71 | extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); | 70 | extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); |
72 | extern void swsusp_free(void); | 71 | extern void swsusp_free(void); |
73 | extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed); | 72 | extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed); |
74 | extern 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 | 91 | int save_highmem(void) | |
92 | static 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 |
124 | static int save_highmem(void) { return 0; } | ||
125 | int restore_highmem(void) { return 0; } | ||
126 | #endif /* CONFIG_HIGHMEM */ | ||
127 | |||
128 | 123 | ||
129 | static int pfn_is_nosave(unsigned long pfn) | 124 | static 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 | ||
77 | int save_highmem(void); | ||
78 | int restore_highmem(void); | ||
79 | #else | ||
80 | static int save_highmem(void) { return 0; } | ||
81 | static 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 | |||
520 | static 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 | |||
539 | int 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) | |||
569 | int swsusp_suspend(void) | 584 | int 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(); |
612 | Restore_highmem: | ||
599 | restore_highmem(); | 613 | restore_highmem(); |
600 | device_power_up(); | 614 | device_power_up(); |
615 | Enable_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) |