1 From 60123966221b74199e4cf0c18d43396b4f00a94a Mon Sep 17 00:00:00 2001
2 From: Yuichi Kusakabe <yuichi.kusakabe@jp.fujitsu.com>
3 Date: Thu, 18 May 2017 16:44:34 +0900
4 Subject: [PATCH 01/15] Add Hibernation kernel base code
6 Signed-off-by: Yuichi Kusakabe <yuichi.kusakabe@jp.fujitsu.com>
8 include/linux/sched.h | 1 +
9 include/linux/suspend.h | 2 +
10 kernel/auditfilter.c | 2 +-
11 kernel/power/console.c | 2 +
12 kernel/power/hibernate.c | 146 +++++++++++++++++++++++++++++++----------------
13 kernel/power/main.c | 4 --
14 kernel/power/power.h | 8 ++-
15 kernel/power/process.c | 35 ++++++++----
16 kernel/power/snapshot.c | 33 +++++++----
17 kernel/power/suspend.c | 4 +-
18 kernel/power/swap.c | 50 ++++++++++++++--
19 11 files changed, 201 insertions(+), 86 deletions(-)
21 diff --git a/include/linux/sched.h b/include/linux/sched.h
22 index f87e9a8..8e3270c 100644
23 --- a/include/linux/sched.h
24 +++ b/include/linux/sched.h
25 @@ -1644,6 +1644,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut,
26 #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */
27 #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */
28 #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */
29 +#define PF_SUSPEND_TASK 0x80000000 /* this thread called freeze_processes and should not be frozen */
32 * Only the _current_ task can read/write to tsk->flags, but other
33 diff --git a/include/linux/suspend.h b/include/linux/suspend.h
34 index d4e3f16..243ff56 100644
35 --- a/include/linux/suspend.h
36 +++ b/include/linux/suspend.h
37 @@ -320,6 +320,8 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
38 extern void hibernation_set_ops(const struct platform_hibernation_ops *ops);
39 extern int hibernate(void);
40 extern bool system_entering_hibernation(void);
41 +asmlinkage int swsusp_save(void);
42 +extern struct pbe *restore_pblist;
43 #else /* CONFIG_HIBERNATION */
44 static inline void register_nosave_region(unsigned long b, unsigned long e) {}
45 static inline void register_nosave_region_late(unsigned long b, unsigned long e) {}
46 diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
47 index 6bd4a90..ac08a9a 100644
48 --- a/kernel/auditfilter.c
49 +++ b/kernel/auditfilter.c
50 @@ -423,7 +423,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
53 /* Support legacy tests for a valid loginuid */
54 - if ((f->type == AUDIT_LOGINUID) && (f->val == 4294967295)) {
55 + if ((f->type == AUDIT_LOGINUID) && (f->val == 0xFFFFFFFF)) {
56 f->type = AUDIT_LOGINUID_SET;
59 diff --git a/kernel/power/console.c b/kernel/power/console.c
60 index 463aa67..aba9c54 100644
61 --- a/kernel/power/console.c
62 +++ b/kernel/power/console.c
64 #include <linux/kbd_kern.h>
66 #include <linux/module.h>
67 +#include <linux/slab.h>
70 #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
71 @@ -81,6 +82,7 @@ void pm_vt_switch_unregister(struct device *dev)
72 list_for_each_entry(tmp, &pm_vt_switch_list, head) {
73 if (tmp->dev == dev) {
79 diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
80 index b26f5f1..524dcf5 100644
81 --- a/kernel/power/hibernate.c
82 +++ b/kernel/power/hibernate.c
85 static int nocompress;
87 +static int nohibernate;
88 static int resume_wait;
89 -static int resume_delay;
90 +static unsigned int resume_delay;
91 static char resume_file[256] = CONFIG_PM_STD_PARTITION;
92 dev_t swsusp_resume_device;
93 sector_t swsusp_resume_block;
94 -int in_suspend __nosavedata;
95 +__visible int in_suspend __nosavedata;
99 @@ -61,6 +62,11 @@ bool freezer_test_done;
101 static const struct platform_hibernation_ops *hibernation_ops;
103 +bool hibernation_available(void)
105 + return (nohibernate == 0);
109 * hibernation_set_ops - Set the global hibernate operations.
110 * @ops: Hibernation operations to use in subsequent hibernation transitions.
111 @@ -82,6 +88,7 @@ void hibernation_set_ops(const struct platform_hibernation_ops *ops)
113 unlock_system_sleep();
115 +EXPORT_SYMBOL_GPL(hibernation_set_ops);
117 static bool entering_platform_hibernation;
119 @@ -227,19 +234,23 @@ static void platform_recover(int platform_mode)
120 void swsusp_show_speed(struct timeval *start, struct timeval *stop,
121 unsigned nr_pages, char *msg)
123 - s64 elapsed_centisecs64;
127 + u64 elapsed_centisecs64;
128 + unsigned int centisecs;
132 elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start);
134 + * If "(s64)elapsed_centisecs64 < 0", it will print long elapsed time,
135 + * it is obvious enough for what went wrong.
137 do_div(elapsed_centisecs64, NSEC_PER_SEC / 100);
138 centisecs = elapsed_centisecs64;
140 centisecs = 1; /* avoid div-by-zero */
141 k = nr_pages * (PAGE_SIZE / 1024);
142 kps = (k * 100) / centisecs;
143 - printk(KERN_INFO "PM: %s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n",
144 + pr_info("PM: %s %u kbytes in %u.%02u seconds (%u.%02u MB/s)\n",
146 centisecs / 100, centisecs % 100,
147 kps / 1000, (kps % 1000) / 10);
148 @@ -293,10 +304,10 @@ static int create_image(int platform_mode)
150 /* Restore control flow magically appears here */
151 restore_processor_state();
154 events_check_enabled = false;
155 - platform_leave(platform_mode);
158 + platform_leave(platform_mode);
162 @@ -594,7 +605,8 @@ static void power_down(void)
163 case HIBERNATION_PLATFORM:
164 hibernation_platform_enter();
165 case HIBERNATION_SHUTDOWN:
166 - kernel_power_off();
168 + kernel_power_off();
170 #ifdef CONFIG_SUSPEND
171 case HIBERNATION_SUSPEND:
172 @@ -622,7 +634,8 @@ static void power_down(void)
173 * corruption after resume.
175 printk(KERN_CRIT "PM: Please power down manually\n");
182 @@ -632,6 +645,11 @@ int hibernate(void)
186 + if (!hibernation_available()) {
187 + pr_debug("PM: Hibernation not available.\n");
192 /* The snapshot device should not be opened while we're running */
193 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
194 @@ -644,22 +662,22 @@ int hibernate(void)
198 - /* Allocate memory management structures */
199 - error = create_basic_memory_bitmaps();
203 printk(KERN_INFO "PM: Syncing filesystems ... ");
207 error = freeze_processes();
212 + /* Allocate memory management structures */
213 + error = create_basic_memory_bitmaps();
217 error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
218 if (error || freezer_test_done)
223 unsigned int flags = 0;
224 @@ -682,14 +700,13 @@ int hibernate(void)
225 pr_debug("PM: Image restored successfully.\n");
229 + free_basic_memory_bitmaps();
233 /* Don't bother checking whether freezer_test_done is true */
234 freezer_test_done = false;
237 - free_basic_memory_bitmaps();
239 pm_notifier_call_chain(PM_POST_HIBERNATION);
240 pm_restore_console();
241 @@ -723,7 +740,7 @@ static int software_resume(void)
243 * If the user said "noresume".. bail out early.
246 + if (noresume || !hibernation_available())
250 @@ -806,21 +823,19 @@ static int software_resume(void)
251 pm_prepare_console();
252 error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
256 - error = create_basic_memory_bitmaps();
261 pr_debug("PM: Preparing processes for restore.\n");
262 error = freeze_processes();
264 - swsusp_close(FMODE_READ);
270 pr_debug("PM: Loading hibernation image.\n");
272 + error = create_basic_memory_bitmaps();
276 error = swsusp_read(&flags);
277 swsusp_close(FMODE_READ);
279 @@ -828,9 +843,9 @@ static int software_resume(void)
281 printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
285 free_basic_memory_bitmaps();
289 pm_notifier_call_chain(PM_POST_RESTORE);
290 pm_restore_console();
291 @@ -840,12 +855,12 @@ static int software_resume(void)
292 mutex_unlock(&pm_mutex);
293 pr_debug("PM: Hibernation image not present or could not be loaded.\n");
297 swsusp_close(FMODE_READ);
301 -late_initcall(software_resume);
302 +late_initcall_sync(software_resume);
305 static const char * const hibernation_modes[] = {
306 @@ -889,6 +904,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
310 + if (!hibernation_available())
311 + return sprintf(buf, "[disabled]\n");
313 for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
314 if (!hibernation_modes[i])
316 @@ -923,6 +941,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
318 int mode = HIBERNATION_INVALID;
320 + if (!hibernation_available())
323 p = memchr(buf, '\n', n);
324 len = p ? p - buf : n;
326 @@ -971,16 +992,20 @@ static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr,
327 static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
328 const char *buf, size_t n)
330 - unsigned int maj, min;
336 - if (sscanf(buf, "%u:%u", &maj, &min) != 2)
338 + if (len && buf[len-1] == '\n')
340 + name = kstrndup(buf, len, GFP_KERNEL);
344 - res = MKDEV(maj,min);
345 - if (maj != MAJOR(res) || min != MINOR(res))
347 + res = name_to_dev_t(name);
353 swsusp_resume_device = res;
354 @@ -988,20 +1013,20 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
355 printk(KERN_INFO "PM: Starting manual resume from disk\n");
366 -static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr,
367 +static ssize_t image_size_show(struct kobject *kobj,
368 + struct kobj_attribute *attr,
371 return sprintf(buf, "%lu\n", image_size);
374 -static ssize_t image_size_store(struct kobject *kobj, struct kobj_attribute *attr,
375 +static ssize_t image_size_store(struct kobject *kobj,
376 + struct kobj_attribute *attr,
377 const char *buf, size_t n)
380 @@ -1065,7 +1090,7 @@ static int __init resume_setup(char *str)
384 - strncpy( resume_file, str, 255 );
385 + strncpy(resume_file, str, 255);
389 @@ -1088,6 +1113,10 @@ static int __init hibernate_setup(char *str)
391 else if (!strncmp(str, "nocompress", 10))
393 + else if (!strncmp(str, "no", 2)) {
400 @@ -1105,13 +1134,30 @@ static int __init resumewait_setup(char *str)
402 static int __init resumedelay_setup(char *str)
404 - resume_delay = simple_strtoul(str, NULL, 0);
405 + int rc = kstrtouint(str, 0, &resume_delay);
412 +static int __init nohibernate_setup(char *str)
419 +static int __init kaslr_nohibernate_setup(char *str)
421 + return nohibernate_setup(str);
424 __setup("noresume", noresume_setup);
425 __setup("resume_offset=", resume_offset_setup);
426 __setup("resume=", resume_setup);
427 __setup("hibernate=", hibernate_setup);
428 __setup("resumewait", resumewait_setup);
429 __setup("resumedelay=", resumedelay_setup);
430 +__setup("nohibernate", nohibernate_setup);
431 +__setup("kaslr", kaslr_nohibernate_setup);
432 diff --git a/kernel/power/main.c b/kernel/power/main.c
433 index d77663b..ac615e4 100644
434 --- a/kernel/power/main.c
435 +++ b/kernel/power/main.c
436 @@ -610,7 +610,6 @@ static struct attribute_group attr_group = {
440 -#ifdef CONFIG_PM_RUNTIME
441 struct workqueue_struct *pm_wq;
442 EXPORT_SYMBOL_GPL(pm_wq);
444 @@ -620,9 +619,6 @@ static int __init pm_start_workqueue(void)
446 return pm_wq ? 0 : -ENOMEM;
449 -static inline int pm_start_workqueue(void) { return 0; }
452 static int __init pm_init(void)
454 diff --git a/kernel/power/power.h b/kernel/power/power.h
455 index 7d4b7ff..c5821ca 100644
456 --- a/kernel/power/power.h
457 +++ b/kernel/power/power.h
459 #include <linux/suspend_ioctls.h>
460 #include <linux/utsname.h>
461 #include <linux/freezer.h>
462 +#include <linux/compiler.h>
465 struct new_utsname uts;
466 @@ -11,7 +12,8 @@ struct swsusp_info {
467 unsigned long image_pages;
470 -} __attribute__((aligned(PAGE_SIZE)));
471 + char archdata[1024];
472 +} __aligned(PAGE_SIZE);
474 #ifdef CONFIG_HIBERNATION
475 /* kernel/power/snapshot.c */
476 @@ -37,6 +39,8 @@ static inline char *check_image_kernel(struct swsusp_info *info)
478 #endif /* CONFIG_ARCH_HIBERNATION_HEADER */
480 +extern void __weak swsusp_arch_add_info(char *archdata);
483 * Keep some memory free so that I/O operations can succeed without paging
484 * [Might this be more than 4 MB?]
485 @@ -49,6 +53,8 @@ static inline char *check_image_kernel(struct swsusp_info *info)
487 #define SPARE_PAGES ((1024 * 1024) >> PAGE_SHIFT)
489 +asmlinkage int swsusp_save(void);
491 /* kernel/power/hibernate.c */
492 extern bool freezer_test_done;
494 diff --git a/kernel/power/process.c b/kernel/power/process.c
495 index 0695319..04559b4 100644
496 --- a/kernel/power/process.c
497 +++ b/kernel/power/process.c
498 @@ -30,9 +30,10 @@ static int try_to_freeze_tasks(bool user_only)
500 bool wq_busy = false;
501 struct timeval start, end;
502 - u64 elapsed_csecs64;
503 - unsigned int elapsed_csecs;
504 + u64 elapsed_msecs64;
505 + unsigned int elapsed_msecs;
507 + int sleep_usecs = USEC_PER_MSEC;
509 do_gettimeofday(&start);
511 @@ -68,22 +69,25 @@ static int try_to_freeze_tasks(bool user_only)
514 * We need to retry, but first give the freezing tasks some
515 - * time to enter the refrigerator.
516 + * time to enter the refrigerator. Start with an initial
517 + * 1 ms sleep followed by exponential backoff until 8 ms.
520 + usleep_range(sleep_usecs / 2, sleep_usecs);
521 + if (sleep_usecs < 8 * USEC_PER_MSEC)
525 do_gettimeofday(&end);
526 - elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
527 - do_div(elapsed_csecs64, NSEC_PER_SEC / 100);
528 - elapsed_csecs = elapsed_csecs64;
529 + elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
530 + do_div(elapsed_msecs64, NSEC_PER_MSEC);
531 + elapsed_msecs = elapsed_msecs64;
535 - printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
536 + printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds "
537 "(%d tasks refusing to freeze, wq_busy=%d):\n",
538 wakeup ? "aborted" : "failed",
539 - elapsed_csecs / 100, elapsed_csecs % 100,
540 + elapsed_msecs / 1000, elapsed_msecs % 1000,
541 todo - wq_busy, wq_busy);
544 @@ -96,8 +100,8 @@ static int try_to_freeze_tasks(bool user_only)
545 read_unlock(&tasklist_lock);
548 - printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
549 - elapsed_csecs % 100);
550 + printk("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000,
551 + elapsed_msecs % 1000);
554 return todo ? -EBUSY : 0;
555 @@ -139,6 +143,9 @@ int freeze_processes(void)
559 + /* Make sure this task doesn't get frozen */
560 + current->flags |= PF_SUSPEND_TASK;
563 atomic_inc(&system_freezing_cnt);
565 @@ -202,6 +209,7 @@ int freeze_kernel_threads(void)
566 void thaw_processes(void)
568 struct task_struct *g, *p;
569 + struct task_struct *curr = current;
572 atomic_dec(&system_freezing_cnt);
573 @@ -217,10 +225,15 @@ void thaw_processes(void)
575 read_lock(&tasklist_lock);
576 do_each_thread(g, p) {
577 + /* No other threads should have PF_SUSPEND_TASK set */
578 + WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK));
580 } while_each_thread(g, p);
581 read_unlock(&tasklist_lock);
583 + WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
584 + curr->flags &= ~PF_SUSPEND_TASK;
586 usermodehelper_enable();
589 diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
590 index 91c04f1..a673f7b 100644
591 --- a/kernel/power/snapshot.c
592 +++ b/kernel/power/snapshot.c
594 #include <linux/highmem.h>
595 #include <linux/list.h>
596 #include <linux/slab.h>
597 +#include <linux/compiler.h>
599 #include <asm/uaccess.h>
600 #include <asm/mmu_context.h>
601 @@ -155,7 +156,7 @@ static inline void free_image_page(void *addr, int clear_nosave_free)
603 struct linked_page *next;
604 char data[LINKED_PAGE_DATA_SIZE];
605 -} __attribute__((packed));
609 free_list_of_pages(struct linked_page *list, int clear_page_nosave)
610 @@ -352,7 +353,7 @@ static int create_mem_extents(struct list_head *list, gfp_t gfp_mask)
611 struct mem_extent *ext, *cur, *aux;
613 zone_start = zone->zone_start_pfn;
614 - zone_end = zone->zone_start_pfn + zone->spanned_pages;
615 + zone_end = zone_end_pfn(zone);
617 list_for_each_entry(ext, list, hook)
618 if (zone_start <= ext->end)
619 @@ -642,8 +643,9 @@ __register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
620 region->end_pfn = end_pfn;
621 list_add_tail(®ion->list, &nosave_regions);
623 - printk(KERN_INFO "PM: Registered nosave memory: %016lx - %016lx\n",
624 - start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
625 + printk(KERN_INFO "PM: Registered nosave memory: [mem %#010llx-%#010llx]\n",
626 + (unsigned long long) start_pfn << PAGE_SHIFT,
627 + ((unsigned long long) end_pfn << PAGE_SHIFT) - 1);
631 @@ -742,7 +744,10 @@ int create_basic_memory_bitmaps(void)
632 struct memory_bitmap *bm1, *bm2;
635 - BUG_ON(forbidden_pages_map || free_pages_map);
636 + if (forbidden_pages_map && free_pages_map)
639 + BUG_ON(forbidden_pages_map || free_pages_map);
641 bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
643 @@ -788,7 +793,8 @@ void free_basic_memory_bitmaps(void)
645 struct memory_bitmap *bm1, *bm2;
647 - BUG_ON(!(forbidden_pages_map && free_pages_map));
648 + if (WARN_ON(!(forbidden_pages_map && free_pages_map)))
651 bm1 = forbidden_pages_map;
652 bm2 = free_pages_map;
653 @@ -883,7 +889,7 @@ static unsigned int count_highmem_pages(void)
656 mark_free_pages(zone);
657 - max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
658 + max_zone_pfn = zone_end_pfn(zone);
659 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
660 if (saveable_highmem_page(zone, pfn))
662 @@ -947,7 +953,7 @@ static unsigned int count_data_pages(void)
665 mark_free_pages(zone);
666 - max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
667 + max_zone_pfn = zone_end_pfn(zone);
668 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
669 if (saveable_page(zone, pfn))
671 @@ -1040,7 +1046,7 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
672 unsigned long max_zone_pfn;
674 mark_free_pages(zone);
675 - max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
676 + max_zone_pfn = zone_end_pfn(zone);
677 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
678 if (page_is_saveable(zone, pfn))
679 memory_bm_set_bit(orig_bm, pfn);
680 @@ -1092,7 +1098,7 @@ void swsusp_free(void)
681 unsigned long pfn, max_zone_pfn;
683 for_each_populated_zone(zone) {
684 - max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
685 + max_zone_pfn = zone_end_pfn(zone);
686 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
687 if (pfn_valid(pfn)) {
688 struct page *page = pfn_to_page(pfn);
689 @@ -1580,7 +1586,7 @@ swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm,
693 -asmlinkage int swsusp_save(void)
694 +asmlinkage __visible int swsusp_save(void)
696 unsigned int nr_pages, nr_highmem;
698 @@ -1628,6 +1634,7 @@ static int init_header_complete(struct swsusp_info *info)
700 memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
701 info->version_code = LINUX_VERSION_CODE;
702 + swsusp_arch_add_info(info->archdata);
706 @@ -1647,6 +1654,8 @@ static char *check_image_kernel(struct swsusp_info *info)
708 #endif /* CONFIG_ARCH_HIBERNATION_HEADER */
710 +void __weak swsusp_arch_add_info(char *archdata) {}
712 unsigned long snapshot_get_image_size(void)
714 return nr_copy_pages + nr_meta_pages + 1;
715 @@ -1758,7 +1767,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm)
717 /* Clear page flags */
718 for_each_populated_zone(zone) {
719 - max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
720 + max_zone_pfn = zone_end_pfn(zone);
721 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
723 swsusp_unset_page_free(pfn_to_page(pfn));
724 diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
725 index bef86d1..deec937 100644
726 --- a/kernel/power/suspend.c
727 +++ b/kernel/power/suspend.c
728 @@ -156,13 +156,13 @@ static int suspend_prepare(suspend_state_t state)
731 /* default implementation */
732 -void __attribute__ ((weak)) arch_suspend_disable_irqs(void)
733 +void __weak arch_suspend_disable_irqs(void)
738 /* default implementation */
739 -void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
740 +void __weak arch_suspend_enable_irqs(void)
744 diff --git a/kernel/power/swap.c b/kernel/power/swap.c
745 index 7c33ed2..a6a1c55 100644
746 --- a/kernel/power/swap.c
747 +++ b/kernel/power/swap.c
748 @@ -91,17 +91,28 @@ struct swap_map_handle {
750 unsigned long reqd_free_pages;
752 +#ifdef CONFIG_ARCH_SHMOBILE
753 + unsigned int img_size; /* add */
757 struct swsusp_header {
758 +#ifdef CONFIG_ARCH_SHMOBILE
759 + char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int) -
760 + sizeof(u32) - (sizeof(unsigned int)*4) - sizeof(u32)];
761 + unsigned int comp_crc32[4];
764 char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int) -
766 + sizeof(u32) - sizeof(u32)];
771 unsigned int flags; /* Flags to pass to the "boot" kernel */
774 -} __attribute__((packed));
777 static struct swsusp_header *swsusp_header;
779 @@ -230,6 +241,11 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
780 swsusp_header->flags = flags;
781 if (flags & SF_CRC32_MODE)
782 swsusp_header->crc32 = handle->crc32;
784 +#ifdef CONFIG_ARCH_SHMOBILE
785 + swsusp_header->img_size = handle->img_size;
788 error = hib_bio_write_page(swsusp_resume_block,
789 swsusp_header, NULL);
791 @@ -587,7 +603,11 @@ static int save_image_lzo(struct swap_map_handle *handle,
792 unsigned char *page = NULL;
793 struct cmp_data *data = NULL;
794 struct crc_data *crc = NULL;
797 +#ifdef CONFIG_ARCH_SHMOBILE
798 + unsigned int comp_imgtotal = 0;
801 * We'll limit the number of threads for compression to limit memory
803 @@ -733,7 +753,12 @@ static int save_image_lzo(struct swap_map_handle *handle,
806 *(size_t *)data[thr].cmp = data[thr].cmp_len;
808 + compr += data[thr].cmp_len;
809 +#ifdef CONFIG_ARCH_SHMOBILE
810 + comp_imgtotal += (data[thr].cmp_len
811 + + LZO_HEADER + (PAGE_SIZE - 1))
812 + & ~(PAGE_SIZE - 1);
815 * Given we are writing one page at a time to disk, we
816 * copy that much from the buffer, although the last
817 @@ -746,7 +771,6 @@ static int save_image_lzo(struct swap_map_handle *handle,
818 off < LZO_HEADER + data[thr].cmp_len;
820 memcpy(page, data[thr].cmp + off, PAGE_SIZE);
822 ret = swap_write_page(handle, page, &bio);
825 @@ -762,8 +786,24 @@ out_finish:
826 do_gettimeofday(&stop);
831 +#ifdef CONFIG_ARCH_SHMOBILE
832 + const unsigned int ds = comp_imgtotal +
834 + / ((2 * 1024 * 1024)
835 + - PAGE_SIZE)) * PAGE_SIZE);
836 + const unsigned int swaped =
837 + (swp_offset(get_swap_page_of_type(root_swap))
840 + handle->img_size = swaped;
842 + handle->img_size = ds;
844 printk(KERN_INFO "PM: Image saving done.\n");
845 + printk(KERN_INFO "PM: Compressed output size: %d [%d] (imgsize=%d/swaped size=%d)\n",
846 + compr, handle->img_size, ds, swaped);
848 swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");