diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/power/hibernate.c | 36 | ||||
-rw-r--r-- | kernel/power/power.h | 3 | ||||
-rw-r--r-- | kernel/power/swap.c | 28 |
3 files changed, 67 insertions, 0 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 8b53db38a279..21ad3fe3164f 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Copyright (c) 2003 Open Source Development Lab | 5 | * Copyright (c) 2003 Open Source Development Lab |
6 | * Copyright (c) 2004 Pavel Machek <pavel@ucw.cz> | 6 | * Copyright (c) 2004 Pavel Machek <pavel@ucw.cz> |
7 | * Copyright (c) 2009 Rafael J. Wysocki, Novell Inc. | 7 | * Copyright (c) 2009 Rafael J. Wysocki, Novell Inc. |
8 | * Copyright (C) 2012 Bojan Smojver <bojan@rexursive.com> | ||
8 | * | 9 | * |
9 | * This file is released under the GPLv2. | 10 | * This file is released under the GPLv2. |
10 | */ | 11 | */ |
@@ -46,6 +47,9 @@ enum { | |||
46 | HIBERNATION_PLATFORM, | 47 | HIBERNATION_PLATFORM, |
47 | HIBERNATION_SHUTDOWN, | 48 | HIBERNATION_SHUTDOWN, |
48 | HIBERNATION_REBOOT, | 49 | HIBERNATION_REBOOT, |
50 | #ifdef CONFIG_SUSPEND | ||
51 | HIBERNATION_SUSPEND, | ||
52 | #endif | ||
49 | /* keep last */ | 53 | /* keep last */ |
50 | __HIBERNATION_AFTER_LAST | 54 | __HIBERNATION_AFTER_LAST |
51 | }; | 55 | }; |
@@ -574,6 +578,10 @@ int hibernation_platform_enter(void) | |||
574 | */ | 578 | */ |
575 | static void power_down(void) | 579 | static void power_down(void) |
576 | { | 580 | { |
581 | #ifdef CONFIG_SUSPEND | ||
582 | int error; | ||
583 | #endif | ||
584 | |||
577 | switch (hibernation_mode) { | 585 | switch (hibernation_mode) { |
578 | case HIBERNATION_REBOOT: | 586 | case HIBERNATION_REBOOT: |
579 | kernel_restart(NULL); | 587 | kernel_restart(NULL); |
@@ -583,6 +591,25 @@ static void power_down(void) | |||
583 | case HIBERNATION_SHUTDOWN: | 591 | case HIBERNATION_SHUTDOWN: |
584 | kernel_power_off(); | 592 | kernel_power_off(); |
585 | break; | 593 | break; |
594 | #ifdef CONFIG_SUSPEND | ||
595 | case HIBERNATION_SUSPEND: | ||
596 | error = suspend_devices_and_enter(PM_SUSPEND_MEM); | ||
597 | if (error) { | ||
598 | if (hibernation_ops) | ||
599 | hibernation_mode = HIBERNATION_PLATFORM; | ||
600 | else | ||
601 | hibernation_mode = HIBERNATION_SHUTDOWN; | ||
602 | power_down(); | ||
603 | } | ||
604 | /* | ||
605 | * Restore swap signature. | ||
606 | */ | ||
607 | error = swsusp_unmark(); | ||
608 | if (error) | ||
609 | printk(KERN_ERR "PM: Swap will be unusable! " | ||
610 | "Try swapon -a.\n"); | ||
611 | return; | ||
612 | #endif | ||
586 | } | 613 | } |
587 | kernel_halt(); | 614 | kernel_halt(); |
588 | /* | 615 | /* |
@@ -827,6 +854,9 @@ static const char * const hibernation_modes[] = { | |||
827 | [HIBERNATION_PLATFORM] = "platform", | 854 | [HIBERNATION_PLATFORM] = "platform", |
828 | [HIBERNATION_SHUTDOWN] = "shutdown", | 855 | [HIBERNATION_SHUTDOWN] = "shutdown", |
829 | [HIBERNATION_REBOOT] = "reboot", | 856 | [HIBERNATION_REBOOT] = "reboot", |
857 | #ifdef CONFIG_SUSPEND | ||
858 | [HIBERNATION_SUSPEND] = "suspend", | ||
859 | #endif | ||
830 | }; | 860 | }; |
831 | 861 | ||
832 | /* | 862 | /* |
@@ -867,6 +897,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, | |||
867 | switch (i) { | 897 | switch (i) { |
868 | case HIBERNATION_SHUTDOWN: | 898 | case HIBERNATION_SHUTDOWN: |
869 | case HIBERNATION_REBOOT: | 899 | case HIBERNATION_REBOOT: |
900 | #ifdef CONFIG_SUSPEND | ||
901 | case HIBERNATION_SUSPEND: | ||
902 | #endif | ||
870 | break; | 903 | break; |
871 | case HIBERNATION_PLATFORM: | 904 | case HIBERNATION_PLATFORM: |
872 | if (hibernation_ops) | 905 | if (hibernation_ops) |
@@ -907,6 +940,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, | |||
907 | switch (mode) { | 940 | switch (mode) { |
908 | case HIBERNATION_SHUTDOWN: | 941 | case HIBERNATION_SHUTDOWN: |
909 | case HIBERNATION_REBOOT: | 942 | case HIBERNATION_REBOOT: |
943 | #ifdef CONFIG_SUSPEND | ||
944 | case HIBERNATION_SUSPEND: | ||
945 | #endif | ||
910 | hibernation_mode = mode; | 946 | hibernation_mode = mode; |
911 | break; | 947 | break; |
912 | case HIBERNATION_PLATFORM: | 948 | case HIBERNATION_PLATFORM: |
diff --git a/kernel/power/power.h b/kernel/power/power.h index b0bd4beaebfe..7d4b7ffb3c1d 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -156,6 +156,9 @@ extern void swsusp_free(void); | |||
156 | extern int swsusp_read(unsigned int *flags_p); | 156 | extern int swsusp_read(unsigned int *flags_p); |
157 | extern int swsusp_write(unsigned int flags); | 157 | extern int swsusp_write(unsigned int flags); |
158 | extern void swsusp_close(fmode_t); | 158 | extern void swsusp_close(fmode_t); |
159 | #ifdef CONFIG_SUSPEND | ||
160 | extern int swsusp_unmark(void); | ||
161 | #endif | ||
159 | 162 | ||
160 | /* kernel/power/block_io.c */ | 163 | /* kernel/power/block_io.c */ |
161 | extern struct block_device *hib_resume_bdev; | 164 | extern struct block_device *hib_resume_bdev; |
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 11e22c068e8b..83d505142b00 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -1472,6 +1472,34 @@ void swsusp_close(fmode_t mode) | |||
1472 | blkdev_put(hib_resume_bdev, mode); | 1472 | blkdev_put(hib_resume_bdev, mode); |
1473 | } | 1473 | } |
1474 | 1474 | ||
1475 | /** | ||
1476 | * swsusp_unmark - Unmark swsusp signature in the resume device | ||
1477 | */ | ||
1478 | |||
1479 | #ifdef CONFIG_SUSPEND | ||
1480 | int swsusp_unmark(void) | ||
1481 | { | ||
1482 | int error; | ||
1483 | |||
1484 | hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL); | ||
1485 | if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) { | ||
1486 | memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10); | ||
1487 | error = hib_bio_write_page(swsusp_resume_block, | ||
1488 | swsusp_header, NULL); | ||
1489 | } else { | ||
1490 | printk(KERN_ERR "PM: Cannot find swsusp signature!\n"); | ||
1491 | error = -ENODEV; | ||
1492 | } | ||
1493 | |||
1494 | /* | ||
1495 | * We just returned from suspend, we don't need the image any more. | ||
1496 | */ | ||
1497 | free_all_swap_pages(root_swap); | ||
1498 | |||
1499 | return error; | ||
1500 | } | ||
1501 | #endif | ||
1502 | |||
1475 | static int swsusp_header_init(void) | 1503 | static int swsusp_header_init(void) |
1476 | { | 1504 | { |
1477 | swsusp_header = (struct swsusp_header*) __get_free_page(GFP_KERNEL); | 1505 | swsusp_header = (struct swsusp_header*) __get_free_page(GFP_KERNEL); |