diff options
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r-- | kernel/power/swsusp.c | 75 |
1 files changed, 45 insertions, 30 deletions
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) |