aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/swsusp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r--kernel/power/swsusp.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index f0ee4e7780d6..0b66659dc516 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -62,6 +62,16 @@ unsigned long image_size = 500 * 1024 * 1024;
62 62
63int in_suspend __nosavedata = 0; 63int in_suspend __nosavedata = 0;
64 64
65#ifdef CONFIG_HIGHMEM
66unsigned int count_highmem_pages(void);
67int save_highmem(void);
68int restore_highmem(void);
69#else
70static inline int save_highmem(void) { return 0; }
71static inline int restore_highmem(void) { return 0; }
72static inline unsigned int count_highmem_pages(void) { return 0; }
73#endif
74
65/** 75/**
66 * The following functions are used for tracing the allocated 76 * The following functions are used for tracing the allocated
67 * swap pages, so that they can be freed in case of an error. 77 * swap pages, so that they can be freed in case of an error.
@@ -182,15 +192,14 @@ int swsusp_shrink_memory(void)
182 192
183 printk("Shrinking memory... "); 193 printk("Shrinking memory... ");
184 do { 194 do {
185 size = 2 * count_special_pages(); 195 size = 2 * count_highmem_pages();
186 size += size / 50 + count_data_pages(); 196 size += size / 50 + count_data_pages() + PAGES_FOR_IO;
187 size += (size + PBES_PER_PAGE - 1) / PBES_PER_PAGE +
188 PAGES_FOR_IO;
189 tmp = size; 197 tmp = size;
190 for_each_zone (zone) 198 for_each_zone (zone)
191 if (!is_highmem(zone) && populated_zone(zone)) { 199 if (!is_highmem(zone) && populated_zone(zone)) {
192 tmp -= zone->free_pages; 200 tmp -= zone->free_pages;
193 tmp += zone->lowmem_reserve[ZONE_NORMAL]; 201 tmp += zone->lowmem_reserve[ZONE_NORMAL];
202 tmp += snapshot_additional_pages(zone);
194 } 203 }
195 if (tmp > 0) { 204 if (tmp > 0) {
196 tmp = __shrink_memory(tmp); 205 tmp = __shrink_memory(tmp);
@@ -226,7 +235,7 @@ int swsusp_suspend(void)
226 goto Enable_irqs; 235 goto Enable_irqs;
227 } 236 }
228 237
229 if ((error = save_special_mem())) { 238 if ((error = save_highmem())) {
230 printk(KERN_ERR "swsusp: Not enough free pages for highmem\n"); 239 printk(KERN_ERR "swsusp: Not enough free pages for highmem\n");
231 goto Restore_highmem; 240 goto Restore_highmem;
232 } 241 }
@@ -237,7 +246,10 @@ int swsusp_suspend(void)
237 /* Restore control flow magically appears here */ 246 /* Restore control flow magically appears here */
238 restore_processor_state(); 247 restore_processor_state();
239Restore_highmem: 248Restore_highmem:
240 restore_special_mem(); 249 restore_highmem();
250 /* NOTE: device_power_up() is just a resume() for devices
251 * that suspended with irqs off ... no overall powerup.
252 */
241 device_power_up(); 253 device_power_up();
242Enable_irqs: 254Enable_irqs:
243 local_irq_enable(); 255 local_irq_enable();
@@ -247,8 +259,12 @@ Enable_irqs:
247int swsusp_resume(void) 259int swsusp_resume(void)
248{ 260{
249 int error; 261 int error;
262
250 local_irq_disable(); 263 local_irq_disable();
251 if (device_power_down(PMSG_FREEZE)) 264 /* NOTE: device_power_down() is just a suspend() with irqs off;
265 * it has no special "power things down" semantics
266 */
267 if (device_power_down(PMSG_PRETHAW))
252 printk(KERN_ERR "Some devices failed to power down, very bad\n"); 268 printk(KERN_ERR "Some devices failed to power down, very bad\n");
253 /* We'll ignore saved state, but this gets preempt count (etc) right */ 269 /* We'll ignore saved state, but this gets preempt count (etc) right */
254 save_processor_state(); 270 save_processor_state();
@@ -263,7 +279,7 @@ int swsusp_resume(void)
263 */ 279 */
264 swsusp_free(); 280 swsusp_free();
265 restore_processor_state(); 281 restore_processor_state();
266 restore_special_mem(); 282 restore_highmem();
267 touch_softlockup_watchdog(); 283 touch_softlockup_watchdog();
268 device_power_up(); 284 device_power_up();
269 local_irq_enable(); 285 local_irq_enable();