Upgrade wayland-ivi-extension
[AGL/meta-agl.git] / meta-agl-bsp / meta-renesas / recipes-kernel / linux / linux / hibernation / 0001-Add-Hibernation-kernel-base-code.patch
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
5
6 Signed-off-by: Yuichi Kusakabe <yuichi.kusakabe@jp.fujitsu.com>
7 ---
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(-)
20
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 */
30  
31  /*
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,
51                 f->lsm_rule = NULL;
52  
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;
57                         f->val = 0;
58                 }
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
63 @@ -9,6 +9,7 @@
64  #include <linux/kbd_kern.h>
65  #include <linux/vt.h>
66  #include <linux/module.h>
67 +#include <linux/slab.h>
68  #include "power.h"
69  
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) {
74                         list_del(&tmp->head);
75 +                       kfree(tmp);
76                         break;
77                 }
78         }
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
83 @@ -34,12 +34,13 @@
84  
85  static int nocompress;
86  static int noresume;
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;
96  
97  enum {
98         HIBERNATION_INVALID,
99 @@ -61,6 +62,11 @@ bool freezer_test_done;
100  
101  static const struct platform_hibernation_ops *hibernation_ops;
102  
103 +bool hibernation_available(void)
104 +{
105 +       return (nohibernate == 0);
106 +}
107 +
108  /**
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)
112  
113         unlock_system_sleep();
114  }
115 +EXPORT_SYMBOL_GPL(hibernation_set_ops);
116  
117  static bool entering_platform_hibernation;
118  
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)
122  {
123 -       s64 elapsed_centisecs64;
124 -       int centisecs;
125 -       int k;
126 -       int kps;
127 +       u64 elapsed_centisecs64;
128 +       unsigned int centisecs;
129 +       unsigned int k;
130 +       unsigned int kps;
131  
132         elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start);
133 +       /*
134 +        * If "(s64)elapsed_centisecs64 < 0", it will print long elapsed time,
135 +        * it is obvious enough for what went wrong.
136 +        */
137         do_div(elapsed_centisecs64, NSEC_PER_SEC / 100);
138         centisecs = elapsed_centisecs64;
139         if (centisecs == 0)
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",
145                         msg, k,
146                         centisecs / 100, centisecs % 100,
147                         kps / 1000, (kps % 1000) / 10);
148 @@ -293,10 +304,10 @@ static int create_image(int platform_mode)
149                         error);
150         /* Restore control flow magically appears here */
151         restore_processor_state();
152 -       if (!in_suspend) {
153 +       if (!in_suspend)
154                 events_check_enabled = false;
155 -               platform_leave(platform_mode);
156 -       }
157 +
158 +       platform_leave(platform_mode);
159  
160   Power_up:
161         syscore_resume();
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();
167 +               if (pm_power_off)
168 +                       kernel_power_off();
169                 break;
170  #ifdef CONFIG_SUSPEND
171         case HIBERNATION_SUSPEND:
172 @@ -622,7 +634,8 @@ static void power_down(void)
173          * corruption after resume.
174          */
175         printk(KERN_CRIT "PM: Please power down manually\n");
176 -       while(1);
177 +       while (1)
178 +               cpu_relax();
179  }
180  
181  /**
182 @@ -632,6 +645,11 @@ int hibernate(void)
183  {
184         int error;
185  
186 +       if (!hibernation_available()) {
187 +               pr_debug("PM: Hibernation not available.\n");
188 +               return -EPERM;
189 +       }
190 +
191         lock_system_sleep();
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)
195         if (error)
196                 goto Exit;
197  
198 -       /* Allocate memory management structures */
199 -       error = create_basic_memory_bitmaps();
200 -       if (error)
201 -               goto Exit;
202 -
203         printk(KERN_INFO "PM: Syncing filesystems ... ");
204         sys_sync();
205         printk("done.\n");
206  
207         error = freeze_processes();
208         if (error)
209 -               goto Free_bitmaps;
210 +               goto Exit;
211 +
212 +       /* Allocate memory management structures */
213 +       error = create_basic_memory_bitmaps();
214 +       if (error)
215 +               goto Thaw;
216  
217         error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
218         if (error || freezer_test_done)
219 -               goto Thaw;
220 +               goto Free_bitmaps;
221  
222         if (in_suspend) {
223                 unsigned int flags = 0;
224 @@ -682,14 +700,13 @@ int hibernate(void)
225                 pr_debug("PM: Image restored successfully.\n");
226         }
227  
228 + Free_bitmaps:
229 +       free_basic_memory_bitmaps();
230   Thaw:
231         thaw_processes();
232  
233         /* Don't bother checking whether freezer_test_done is true */
234         freezer_test_done = false;
235 -
236 - Free_bitmaps:
237 -       free_basic_memory_bitmaps();
238   Exit:
239         pm_notifier_call_chain(PM_POST_HIBERNATION);
240         pm_restore_console();
241 @@ -723,7 +740,7 @@ static int software_resume(void)
242         /*
243          * If the user said "noresume".. bail out early.
244          */
245 -       if (noresume)
246 +       if (noresume || !hibernation_available())
247                 return 0;
248  
249         /*
250 @@ -806,21 +823,19 @@ static int software_resume(void)
251         pm_prepare_console();
252         error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
253         if (error)
254 -               goto close_finish;
255 -
256 -       error = create_basic_memory_bitmaps();
257 -       if (error)
258 -               goto close_finish;
259 +               goto Close_Finish;
260  
261         pr_debug("PM: Preparing processes for restore.\n");
262         error = freeze_processes();
263 -       if (error) {
264 -               swsusp_close(FMODE_READ);
265 -               goto Done;
266 -       }
267 +       if (error)
268 +               goto Close_Finish;
269  
270         pr_debug("PM: Loading hibernation image.\n");
271  
272 +       error = create_basic_memory_bitmaps();
273 +       if (error)
274 +               goto Thaw;
275 +
276         error = swsusp_read(&flags);
277         swsusp_close(FMODE_READ);
278         if (!error)
279 @@ -828,9 +843,9 @@ static int software_resume(void)
280  
281         printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
282         swsusp_free();
283 -       thaw_processes();
284 - Done:
285         free_basic_memory_bitmaps();
286 + Thaw:
287 +       thaw_processes();
288   Finish:
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");
294         return error;
295 -close_finish:
296 + Close_Finish:
297         swsusp_close(FMODE_READ);
298         goto Finish;
299  }
300  
301 -late_initcall(software_resume);
302 +late_initcall_sync(software_resume);
303  
304  
305  static const char * const hibernation_modes[] = {
306 @@ -889,6 +904,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
307         int i;
308         char *start = buf;
309  
310 +       if (!hibernation_available())
311 +               return sprintf(buf, "[disabled]\n");
312 +
313         for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
314                 if (!hibernation_modes[i])
315                         continue;
316 @@ -923,6 +941,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
317         char *p;
318         int mode = HIBERNATION_INVALID;
319  
320 +       if (!hibernation_available())
321 +               return -EPERM;
322 +
323         p = memchr(buf, '\n', n);
324         len = p ? p - buf : n;
325  
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)
329  {
330 -       unsigned int maj, min;
331         dev_t res;
332 -       int ret = -EINVAL;
333 +       int len = n;
334 +       char *name;
335  
336 -       if (sscanf(buf, "%u:%u", &maj, &min) != 2)
337 -               goto out;
338 +       if (len && buf[len-1] == '\n')
339 +               len--;
340 +       name = kstrndup(buf, len, GFP_KERNEL);
341 +       if (!name)
342 +               return -ENOMEM;
343  
344 -       res = MKDEV(maj,min);
345 -       if (maj != MAJOR(res) || min != MINOR(res))
346 -               goto out;
347 +       res = name_to_dev_t(name);
348 +       kfree(name);
349 +       if (!res)
350 +               return -EINVAL;
351  
352         lock_system_sleep();
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");
356         noresume = 0;
357         software_resume();
358 -       ret = n;
359 - out:
360 -       return ret;
361 +       return n;
362  }
363  
364  power_attr(resume);
365  
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,
369                                char *buf)
370  {
371         return sprintf(buf, "%lu\n", image_size);
372  }
373  
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)
378  {
379         unsigned long size;
380 @@ -1065,7 +1090,7 @@ static int __init resume_setup(char *str)
381         if (noresume)
382                 return 1;
383  
384 -       strncpy( resume_file, str, 255 );
385 +       strncpy(resume_file, str, 255);
386         return 1;
387  }
388  
389 @@ -1088,6 +1113,10 @@ static int __init hibernate_setup(char *str)
390                 noresume = 1;
391         else if (!strncmp(str, "nocompress", 10))
392                 nocompress = 1;
393 +       else if (!strncmp(str, "no", 2)) {
394 +               noresume = 1;
395 +               nohibernate = 1;
396 +       }
397         return 1;
398  }
399  
400 @@ -1105,13 +1134,30 @@ static int __init resumewait_setup(char *str)
401  
402  static int __init resumedelay_setup(char *str)
403  {
404 -       resume_delay = simple_strtoul(str, NULL, 0);
405 +       int rc = kstrtouint(str, 0, &resume_delay);
406 +
407 +       if (rc)
408 +               return rc;
409 +       return 1;
410 +}
411 +
412 +static int __init nohibernate_setup(char *str)
413 +{
414 +       noresume = 1;
415 +       nohibernate = 1;
416         return 1;
417  }
418  
419 +static int __init kaslr_nohibernate_setup(char *str)
420 +{
421 +       return nohibernate_setup(str);
422 +}
423 +
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 = {
437         .attrs = g,
438  };
439  
440 -#ifdef CONFIG_PM_RUNTIME
441  struct workqueue_struct *pm_wq;
442  EXPORT_SYMBOL_GPL(pm_wq);
443  
444 @@ -620,9 +619,6 @@ static int __init pm_start_workqueue(void)
445  
446         return pm_wq ? 0 : -ENOMEM;
447  }
448 -#else
449 -static inline int pm_start_workqueue(void) { return 0; }
450 -#endif
451  
452  static int __init pm_init(void)
453  {
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
458 @@ -2,6 +2,7 @@
459  #include <linux/suspend_ioctls.h>
460  #include <linux/utsname.h>
461  #include <linux/freezer.h>
462 +#include <linux/compiler.h>
463  
464  struct swsusp_info {
465         struct new_utsname      uts;
466 @@ -11,7 +12,8 @@ struct swsusp_info {
467         unsigned long           image_pages;
468         unsigned long           pages;
469         unsigned long           size;
470 -} __attribute__((aligned(PAGE_SIZE)));
471 +       char                    archdata[1024];
472 +} __aligned(PAGE_SIZE);
473  
474  #ifdef CONFIG_HIBERNATION
475  /* kernel/power/snapshot.c */
476 @@ -37,6 +39,8 @@ static inline char *check_image_kernel(struct swsusp_info *info)
477  }
478  #endif /* CONFIG_ARCH_HIBERNATION_HEADER */
479  
480 +extern void __weak swsusp_arch_add_info(char *archdata);
481 +
482  /*
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)
486   */
487  #define SPARE_PAGES    ((1024 * 1024) >> PAGE_SHIFT)
488  
489 +asmlinkage int swsusp_save(void);
490 +
491  /* kernel/power/hibernate.c */
492  extern bool freezer_test_done;
493  
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)
499         unsigned int todo;
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;
506         bool wakeup = false;
507 +       int sleep_usecs = USEC_PER_MSEC;
508  
509         do_gettimeofday(&start);
510  
511 @@ -68,22 +69,25 @@ static int try_to_freeze_tasks(bool user_only)
512  
513                 /*
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.
518                  */
519 -               msleep(10);
520 +               usleep_range(sleep_usecs / 2, sleep_usecs);
521 +               if (sleep_usecs < 8 * USEC_PER_MSEC)
522 +                       sleep_usecs *= 2;
523         }
524  
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;
532  
533         if (todo) {
534                 printk("\n");
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);
542  
543                 if (!wakeup) {
544 @@ -96,8 +100,8 @@ static int try_to_freeze_tasks(bool user_only)
545                         read_unlock(&tasklist_lock);
546                 }
547         } else {
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);
552         }
553  
554         return todo ? -EBUSY : 0;
555 @@ -139,6 +143,9 @@ int freeze_processes(void)
556         if (error)
557                 return error;
558  
559 +       /* Make sure this task doesn't get frozen */
560 +       current->flags |= PF_SUSPEND_TASK;
561 +
562         if (!pm_freezing)
563                 atomic_inc(&system_freezing_cnt);
564  
565 @@ -202,6 +209,7 @@ int freeze_kernel_threads(void)
566  void thaw_processes(void)
567  {
568         struct task_struct *g, *p;
569 +       struct task_struct *curr = current;
570  
571         if (pm_freezing)
572                 atomic_dec(&system_freezing_cnt);
573 @@ -217,10 +225,15 @@ void thaw_processes(void)
574  
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));
579                 __thaw_task(p);
580         } while_each_thread(g, p);
581         read_unlock(&tasklist_lock);
582  
583 +       WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
584 +       curr->flags &= ~PF_SUSPEND_TASK;
585 +
586         usermodehelper_enable();
587  
588         schedule();
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
593 @@ -27,6 +27,7 @@
594  #include <linux/highmem.h>
595  #include <linux/list.h>
596  #include <linux/slab.h>
597 +#include <linux/compiler.h>
598  
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)
602  struct linked_page {
603         struct linked_page *next;
604         char data[LINKED_PAGE_DATA_SIZE];
605 -} __attribute__((packed));
606 +} __packed;
607  
608  static inline void
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;
612  
613                 zone_start = zone->zone_start_pfn;
614 -               zone_end = zone->zone_start_pfn + zone->spanned_pages;
615 +               zone_end = zone_end_pfn(zone);
616  
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(&region->list, &nosave_regions);
622   Report:
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);
628  }
629  
630  /*
631 @@ -742,7 +744,10 @@ int create_basic_memory_bitmaps(void)
632         struct memory_bitmap *bm1, *bm2;
633         int error = 0;
634  
635 -       BUG_ON(forbidden_pages_map || free_pages_map);
636 +       if (forbidden_pages_map && free_pages_map)
637 +               return 0;
638 +       else
639 +               BUG_ON(forbidden_pages_map || free_pages_map);
640  
641         bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
642         if (!bm1)
643 @@ -788,7 +793,8 @@ void free_basic_memory_bitmaps(void)
644  {
645         struct memory_bitmap *bm1, *bm2;
646  
647 -       BUG_ON(!(forbidden_pages_map && free_pages_map));
648 +       if (WARN_ON(!(forbidden_pages_map && free_pages_map)))
649 +               return;
650  
651         bm1 = forbidden_pages_map;
652         bm2 = free_pages_map;
653 @@ -883,7 +889,7 @@ static unsigned int count_highmem_pages(void)
654                         continue;
655  
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))
661                                 n++;
662 @@ -947,7 +953,7 @@ static unsigned int count_data_pages(void)
663                         continue;
664  
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))
670                                 n++;
671 @@ -1040,7 +1046,7 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
672                 unsigned long max_zone_pfn;
673  
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;
682  
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,
690         return -ENOMEM;
691  }
692  
693 -asmlinkage int swsusp_save(void)
694 +asmlinkage __visible int swsusp_save(void)
695  {
696         unsigned int nr_pages, nr_highmem;
697  
698 @@ -1628,6 +1634,7 @@ static int init_header_complete(struct swsusp_info *info)
699  {
700         memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
701         info->version_code = LINUX_VERSION_CODE;
702 +       swsusp_arch_add_info(info->archdata);
703         return 0;
704  }
705  
706 @@ -1647,6 +1654,8 @@ static char *check_image_kernel(struct swsusp_info *info)
707  }
708  #endif /* CONFIG_ARCH_HIBERNATION_HEADER */
709  
710 +void __weak swsusp_arch_add_info(char *archdata) {}
711 +
712  unsigned long snapshot_get_image_size(void)
713  {
714         return nr_copy_pages + nr_meta_pages + 1;
715 @@ -1758,7 +1767,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm)
716  
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++)
722                         if (pfn_valid(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)
729  }
730  
731  /* default implementation */
732 -void __attribute__ ((weak)) arch_suspend_disable_irqs(void)
733 +void __weak arch_suspend_disable_irqs(void)
734  {
735         local_irq_disable();
736  }
737  
738  /* default implementation */
739 -void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
740 +void __weak arch_suspend_enable_irqs(void)
741  {
742         local_irq_enable();
743  }
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 {
749         unsigned int k;
750         unsigned long reqd_free_pages;
751         u32 crc32;
752 +#ifdef CONFIG_ARCH_SHMOBILE
753 +       unsigned int img_size; /* add */
754 +#endif
755  };
756  
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];
762 +       u32 img_size;
763 +#else
764         char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int) -
765 -                     sizeof(u32)];
766 +                     sizeof(u32) - sizeof(u32)];
767 +       u32     comp_crc32;
768 +#endif
769         u32     crc32;
770         sector_t image;
771         unsigned int flags;     /* Flags to pass to the "boot" kernel */
772         char    orig_sig[10];
773         char    sig[10];
774 -} __attribute__((packed));
775 +} __packed;
776  
777  static struct swsusp_header *swsusp_header;
778  
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;
783 +
784 +#ifdef CONFIG_ARCH_SHMOBILE
785 +               swsusp_header->img_size = handle->img_size;
786 +#endif
787 +
788                 error = hib_bio_write_page(swsusp_resume_block,
789                                         swsusp_header, NULL);
790         } else {
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;
795 +       int compr = 0;
796  
797 +#ifdef CONFIG_ARCH_SHMOBILE
798 +       unsigned int comp_imgtotal = 0;
799 +#endif
800         /*
801          * We'll limit the number of threads for compression to limit memory
802          * footprint.
803 @@ -733,7 +753,12 @@ static int save_image_lzo(struct swap_map_handle *handle,
804                         }
805  
806                         *(size_t *)data[thr].cmp = data[thr].cmp_len;
807 -
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);
813 +#endif
814                         /*
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;
819                              off += PAGE_SIZE) {
820                                 memcpy(page, data[thr].cmp + off, PAGE_SIZE);
821 -
822                                 ret = swap_write_page(handle, page, &bio);
823                                 if (ret)
824                                         goto out_finish;
825 @@ -762,8 +786,24 @@ out_finish:
826         do_gettimeofday(&stop);
827         if (!ret)
828                 ret = err2;
829 -       if (!ret)
830 +       if (!ret) {
831 +#ifdef CONFIG_ARCH_SHMOBILE
832 +               const unsigned int ds = comp_imgtotal +
833 +                       ((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))
838 +                        - 2) * PAGE_SIZE;
839 +               if (ds < swaped)
840 +                       handle->img_size = swaped;
841 +               else
842 +                       handle->img_size = ds;
843 +#endif
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);
847 +       }
848         swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
849  out_clean:
850         if (crc) {
851 -- 
852 1.8.3.1
853