aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/power.h2
-rw-r--r--kernel/power/snapshot.c78
-rw-r--r--kernel/power/swsusp.c6
3 files changed, 43 insertions, 43 deletions
diff --git a/kernel/power/power.h b/kernel/power/power.h
index e54dd8435de7..28afcb090149 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -69,4 +69,4 @@ extern int restore_highmem(void);
69extern void free_pagedir(struct pbe *pblist); 69extern void free_pagedir(struct pbe *pblist);
70extern struct pbe * alloc_pagedir(unsigned nr_pages); 70extern struct pbe * alloc_pagedir(unsigned nr_pages);
71extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); 71extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages);
72extern int enough_swap(void); 72extern int enough_swap(unsigned nr_pages);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 0f0a7f306b0d..03916cf3ff02 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -187,37 +187,38 @@ static int saveable(struct zone * zone, unsigned long * zone_pfn)
187 return 1; 187 return 1;
188} 188}
189 189
190static void count_data_pages(void) 190static unsigned count_data_pages(void)
191{ 191{
192 struct zone *zone; 192 struct zone *zone;
193 unsigned long zone_pfn; 193 unsigned long zone_pfn;
194 unsigned n;
194 195
195 nr_copy_pages = 0; 196 n = 0;
196
197 for_each_zone (zone) { 197 for_each_zone (zone) {
198 if (is_highmem(zone)) 198 if (is_highmem(zone))
199 continue; 199 continue;
200 mark_free_pages(zone); 200 mark_free_pages(zone);
201 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) 201 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
202 nr_copy_pages += saveable(zone, &zone_pfn); 202 n += saveable(zone, &zone_pfn);
203 } 203 }
204 return n;
204} 205}
205 206
206static void copy_data_pages(void) 207static void copy_data_pages(struct pbe *pblist)
207{ 208{
208 struct zone *zone; 209 struct zone *zone;
209 unsigned long zone_pfn; 210 unsigned long zone_pfn;
210 struct pbe *pbe = pagedir_nosave, *p; 211 struct pbe *pbe, *p;
211 212
212 pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages); 213 pbe = pblist;
213 for_each_zone (zone) { 214 for_each_zone (zone) {
214 if (is_highmem(zone)) 215 if (is_highmem(zone))
215 continue; 216 continue;
216 mark_free_pages(zone); 217 mark_free_pages(zone);
217 /* This is necessary for swsusp_free() */ 218 /* This is necessary for swsusp_free() */
218 for_each_pb_page (p, pagedir_nosave) 219 for_each_pb_page (p, pblist)
219 SetPageNosaveFree(virt_to_page(p)); 220 SetPageNosaveFree(virt_to_page(p));
220 for_each_pbe(p, pagedir_nosave) 221 for_each_pbe (p, pblist)
221 SetPageNosaveFree(virt_to_page(p->address)); 222 SetPageNosaveFree(virt_to_page(p->address));
222 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { 223 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
223 if (saveable(zone, &zone_pfn)) { 224 if (saveable(zone, &zone_pfn)) {
@@ -370,46 +371,39 @@ void swsusp_free(void)
370 * free pages. 371 * free pages.
371 */ 372 */
372 373
373static int enough_free_mem(void) 374static int enough_free_mem(unsigned nr_pages)
374{ 375{
375 pr_debug("swsusp: available memory: %u pages\n", nr_free_pages()); 376 pr_debug("swsusp: available memory: %u pages\n", nr_free_pages());
376 return nr_free_pages() > (nr_copy_pages + PAGES_FOR_IO + 377 return nr_free_pages() > (nr_pages + PAGES_FOR_IO +
377 nr_copy_pages/PBES_PER_PAGE + !!(nr_copy_pages%PBES_PER_PAGE)); 378 (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
378} 379}
379 380
380 381
381static int swsusp_alloc(void) 382static struct pbe *swsusp_alloc(unsigned nr_pages)
382{ 383{
383 struct pbe * p; 384 struct pbe *pblist, *p;
384
385 pagedir_nosave = NULL;
386
387 if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE +
388 !!(nr_copy_pages % PBES_PER_PAGE))
389 return -ENOSPC;
390 385
391 if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) { 386 if (!(pblist = alloc_pagedir(nr_pages))) {
392 printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); 387 printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
393 return -ENOMEM; 388 return NULL;
394 } 389 }
395 create_pbe_list(pagedir_save, nr_copy_pages); 390 create_pbe_list(pblist, nr_pages);
396 pagedir_nosave = pagedir_save;
397 391
398 for_each_pbe (p, pagedir_save) { 392 for_each_pbe (p, pblist) {
399 p->address = (unsigned long)alloc_image_page(); 393 p->address = (unsigned long)alloc_image_page();
400 if (!p->address) { 394 if (!p->address) {
401 printk(KERN_ERR "suspend: Allocating image pages failed.\n"); 395 printk(KERN_ERR "suspend: Allocating image pages failed.\n");
402 swsusp_free(); 396 swsusp_free();
403 return -ENOMEM; 397 return NULL;
404 } 398 }
405 } 399 }
406 400
407 return 0; 401 return pblist;
408} 402}
409 403
410static int suspend_prepare_image(void) 404static int suspend_prepare_image(void)
411{ 405{
412 int error; 406 unsigned nr_pages;
413 407
414 pr_debug("swsusp: critical section: \n"); 408 pr_debug("swsusp: critical section: \n");
415 if (save_highmem()) { 409 if (save_highmem()) {
@@ -419,33 +413,37 @@ static int suspend_prepare_image(void)
419 } 413 }
420 414
421 drain_local_pages(); 415 drain_local_pages();
422 count_data_pages(); 416 nr_pages = count_data_pages();
423 printk("swsusp: Need to copy %u pages\n", nr_copy_pages); 417 printk("swsusp: Need to copy %u pages\n", nr_pages);
424 418
425 pr_debug("swsusp: pages needed: %u + %lu + %u, free: %u\n", 419 pr_debug("swsusp: pages needed: %u + %lu + %u, free: %u\n",
426 nr_copy_pages, 420 nr_pages,
427 nr_copy_pages/PBES_PER_PAGE + !!(nr_copy_pages%PBES_PER_PAGE), 421 (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE,
428 PAGES_FOR_IO, nr_free_pages()); 422 PAGES_FOR_IO, nr_free_pages());
429 423
430 if (!enough_free_mem()) { 424 /* This is needed because of the fixed size of swsusp_info */
425 if (MAX_PBES < (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE)
426 return -ENOSPC;
427
428 if (!enough_free_mem(nr_pages)) {
431 printk(KERN_ERR "swsusp: Not enough free memory\n"); 429 printk(KERN_ERR "swsusp: Not enough free memory\n");
432 return -ENOMEM; 430 return -ENOMEM;
433 } 431 }
434 432
435 if (!enough_swap()) { 433 if (!enough_swap(nr_pages)) {
436 printk(KERN_ERR "swsusp: Not enough free swap\n"); 434 printk(KERN_ERR "swsusp: Not enough free swap\n");
437 return -ENOSPC; 435 return -ENOSPC;
438 } 436 }
439 437
440 error = swsusp_alloc(); 438 pagedir_nosave = swsusp_alloc(nr_pages);
441 if (error) 439 if (!pagedir_nosave)
442 return error; 440 return -ENOMEM;
443 441
444 /* During allocating of suspend pagedir, new cold pages may appear. 442 /* During allocating of suspend pagedir, new cold pages may appear.
445 * Kill them. 443 * Kill them.
446 */ 444 */
447 drain_local_pages(); 445 drain_local_pages();
448 copy_data_pages(); 446 copy_data_pages(pagedir_nosave);
449 447
450 /* 448 /*
451 * End of critical section. From now on, we can write to memory, 449 * End of critical section. From now on, we can write to memory,
@@ -453,7 +451,9 @@ static int suspend_prepare_image(void)
453 * touch swap space! Except we must write out our image of course. 451 * touch swap space! Except we must write out our image of course.
454 */ 452 */
455 453
456 printk("swsusp: critical section/: done (%d pages copied)\n", nr_copy_pages ); 454 nr_copy_pages = nr_pages;
455
456 printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages);
457 return 0; 457 return 0;
458} 458}
459 459
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index fc50b5d2dd26..f6abfdb0a02a 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -550,14 +550,14 @@ static int write_suspend_image(void)
550 * We should only consider resume_device. 550 * We should only consider resume_device.
551 */ 551 */
552 552
553int enough_swap(void) 553int enough_swap(unsigned nr_pages)
554{ 554{
555 struct sysinfo i; 555 struct sysinfo i;
556 556
557 si_swapinfo(&i); 557 si_swapinfo(&i);
558 pr_debug("swsusp: available swap: %lu pages\n", i.freeswap); 558 pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
559 return i.freeswap > (nr_copy_pages + PAGES_FOR_IO + 559 return i.freeswap > (nr_pages + PAGES_FOR_IO +
560 nr_copy_pages/PBES_PER_PAGE + !!(nr_copy_pages%PBES_PER_PAGE)); 560 (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
561} 561}
562 562
563 563