summaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/Kconfig9
-rw-r--r--kernel/power/Makefile3
-rw-r--r--kernel/power/main.c2
-rw-r--r--kernel/power/pm.c1
-rw-r--r--kernel/power/power.h6
-rw-r--r--kernel/power/snapshot.c100
-rw-r--r--kernel/power/swsusp.c251
7 files changed, 165 insertions, 207 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 46a5e5acff9..5ec248cb7f4 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -19,6 +19,15 @@ config PM
will issue the hlt instruction if nothing is to be done, thereby
sending the processor to sleep and saving power.
+config PM_LEGACY
+ bool "Legacy Power Management API"
+ depends on PM
+ default y
+ ---help---
+ Support for pm_register() and friends.
+
+ If unsure, say Y.
+
config PM_DEBUG
bool "Power Management Debug Support"
depends on PM
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index c71eb4579c0..04be7d0d96a 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -3,7 +3,8 @@ ifeq ($(CONFIG_PM_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
-obj-y := main.o process.o console.o pm.o
+obj-y := main.o process.o console.o
+obj-$(CONFIG_PM_LEGACY) += pm.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o
obj-$(CONFIG_SUSPEND_SMP) += smp.o
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 18d7d693fbb..6ee2cad530e 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -167,7 +167,7 @@ static int enter_state(suspend_state_t state)
{
int error;
- if (pm_ops->valid && !pm_ops->valid(state))
+ if (pm_ops && pm_ops->valid && !pm_ops->valid(state))
return -ENODEV;
if (down_trylock(&pm_sem))
return -EBUSY;
diff --git a/kernel/power/pm.c b/kernel/power/pm.c
index 159149321b3..33c508e857d 100644
--- a/kernel/power/pm.c
+++ b/kernel/power/pm.c
@@ -23,6 +23,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/pm.h>
+#include <linux/pm_legacy.h>
#include <linux/interrupt.h>
int pm_active;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index d4fd96a135a..6c042b5ee14 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -65,8 +65,8 @@ extern suspend_pagedir_t *pagedir_save;
extern asmlinkage int swsusp_arch_suspend(void);
extern asmlinkage int swsusp_arch_resume(void);
-extern int restore_highmem(void);
-extern struct pbe * alloc_pagedir(unsigned nr_pages);
+extern void free_pagedir(struct pbe *pblist);
+extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed);
extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages);
extern void swsusp_free(void);
-extern int enough_swap(unsigned nr_pages);
+extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 42a62870439..4a6dbcefd37 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -88,8 +88,7 @@ static int save_highmem_zone(struct zone *zone)
return 0;
}
-
-static int save_highmem(void)
+int save_highmem(void)
{
struct zone *zone;
int res = 0;
@@ -120,11 +119,7 @@ int restore_highmem(void)
}
return 0;
}
-#else
-static int save_highmem(void) { return 0; }
-int restore_highmem(void) { return 0; }
-#endif /* CONFIG_HIGHMEM */
-
+#endif
static int pfn_is_nosave(unsigned long pfn)
{
@@ -168,9 +163,8 @@ static unsigned count_data_pages(void)
{
struct zone *zone;
unsigned long zone_pfn;
- unsigned n;
+ unsigned int n = 0;
- n = 0;
for_each_zone (zone) {
if (is_highmem(zone))
continue;
@@ -217,7 +211,7 @@ static void copy_data_pages(struct pbe *pblist)
* free_pagedir - free pages allocated with alloc_pagedir()
*/
-static void free_pagedir(struct pbe *pblist)
+void free_pagedir(struct pbe *pblist)
{
struct pbe *pbe;
@@ -250,10 +244,10 @@ static inline void fill_pb_page(struct pbe *pbpage)
* of memory pages allocated with alloc_pagedir()
*/
-void create_pbe_list(struct pbe *pblist, unsigned nr_pages)
+void create_pbe_list(struct pbe *pblist, unsigned int nr_pages)
{
struct pbe *pbpage, *p;
- unsigned num = PBES_PER_PAGE;
+ unsigned int num = PBES_PER_PAGE;
for_each_pb_page (pbpage, pblist) {
if (num >= nr_pages)
@@ -270,9 +264,30 @@ void create_pbe_list(struct pbe *pblist, unsigned nr_pages)
pr_debug("create_pbe_list(): initialized %d PBEs\n", num);
}
-static void *alloc_image_page(void)
+/**
+ * @safe_needed - on resume, for storing the PBE list and the image,
+ * we can only use memory pages that do not conflict with the pages
+ * which had been used before suspend.
+ *
+ * The unsafe pages are marked with the PG_nosave_free flag
+ *
+ * Allocated but unusable (ie eaten) memory pages should be marked
+ * so that swsusp_free() can release them
+ */
+
+static inline void *alloc_image_page(gfp_t gfp_mask, int safe_needed)
{
- void *res = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
+ void *res;
+
+ if (safe_needed)
+ do {
+ res = (void *)get_zeroed_page(gfp_mask);
+ if (res && PageNosaveFree(virt_to_page(res)))
+ /* This is for swsusp_free() */
+ SetPageNosave(virt_to_page(res));
+ } while (res && PageNosaveFree(virt_to_page(res)));
+ else
+ res = (void *)get_zeroed_page(gfp_mask);
if (res) {
SetPageNosave(virt_to_page(res));
SetPageNosaveFree(virt_to_page(res));
@@ -280,6 +295,11 @@ static void *alloc_image_page(void)
return res;
}
+unsigned long get_safe_page(gfp_t gfp_mask)
+{
+ return (unsigned long)alloc_image_page(gfp_mask, 1);
+}
+
/**
* alloc_pagedir - Allocate the page directory.
*
@@ -293,21 +313,21 @@ static void *alloc_image_page(void)
* On each page we set up a list of struct_pbe elements.
*/
-struct pbe *alloc_pagedir(unsigned nr_pages)
+struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed)
{
- unsigned num;
+ unsigned int num;
struct pbe *pblist, *pbe;
if (!nr_pages)
return NULL;
pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages);
- pblist = alloc_image_page();
+ pblist = alloc_image_page(gfp_mask, safe_needed);
/* FIXME: rewrite this ugly loop */
for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages;
pbe = pbe->next, num += PBES_PER_PAGE) {
pbe += PB_PAGE_SKIP;
- pbe->next = alloc_image_page();
+ pbe->next = alloc_image_page(gfp_mask, safe_needed);
}
if (!pbe) { /* get_zeroed_page() failed */
free_pagedir(pblist);
@@ -329,7 +349,7 @@ void swsusp_free(void)
for_each_zone(zone) {
for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
if (pfn_valid(zone_pfn + zone->zone_start_pfn)) {
- struct page * page;
+ struct page *page;
page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
if (PageNosave(page) && PageNosaveFree(page)) {
ClearPageNosave(page);
@@ -348,31 +368,39 @@ void swsusp_free(void)
* free pages.
*/
-static int enough_free_mem(unsigned nr_pages)
+static int enough_free_mem(unsigned int nr_pages)
{
pr_debug("swsusp: available memory: %u pages\n", nr_free_pages());
return nr_free_pages() > (nr_pages + PAGES_FOR_IO +
(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
}
+int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed)
+{
+ struct pbe *p;
-static struct pbe *swsusp_alloc(unsigned nr_pages)
+ for_each_pbe (p, pblist) {
+ p->address = (unsigned long)alloc_image_page(gfp_mask, safe_needed);
+ if (!p->address)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static struct pbe *swsusp_alloc(unsigned int nr_pages)
{
- struct pbe *pblist, *p;
+ struct pbe *pblist;
- if (!(pblist = alloc_pagedir(nr_pages))) {
+ if (!(pblist = alloc_pagedir(nr_pages, GFP_ATOMIC | __GFP_COLD, 0))) {
printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
return NULL;
}
create_pbe_list(pblist, nr_pages);
- for_each_pbe (p, pblist) {
- p->address = (unsigned long)alloc_image_page();
- if (!p->address) {
- printk(KERN_ERR "suspend: Allocating image pages failed.\n");
- swsusp_free();
- return NULL;
- }
+ if (alloc_data_pages(pblist, GFP_ATOMIC | __GFP_COLD, 0)) {
+ printk(KERN_ERR "suspend: Allocating image pages failed.\n");
+ swsusp_free();
+ return NULL;
}
return pblist;
@@ -380,14 +408,9 @@ static struct pbe *swsusp_alloc(unsigned nr_pages)
asmlinkage int swsusp_save(void)
{
- unsigned nr_pages;
+ unsigned int nr_pages;
pr_debug("swsusp: critical section: \n");
- if (save_highmem()) {
- printk(KERN_CRIT "swsusp: Not enough free pages for highmem\n");
- restore_highmem();
- return -ENOMEM;
- }
drain_local_pages();
nr_pages = count_data_pages();
@@ -407,11 +430,6 @@ asmlinkage int swsusp_save(void)
return -ENOMEM;
}
- if (!enough_swap(nr_pages)) {
- printk(KERN_ERR "swsusp: Not enough free swap\n");
- return -ENOSPC;
- }
-
pagedir_nosave = swsusp_alloc(nr_pages);
if (!pagedir_nosave)
return -ENOMEM;
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 12db1d2ad61..c05f46e7348 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -73,6 +73,14 @@
#include "power.h"
+#ifdef CONFIG_HIGHMEM
+int save_highmem(void);
+int restore_highmem(void);
+#else
+static int save_highmem(void) { return 0; }
+static int restore_highmem(void) { return 0; }
+#endif
+
#define CIPHER "aes"
#define MAXKEY 32
#define MAXIV 32
@@ -85,18 +93,11 @@ unsigned int nr_copy_pages __nosavedata = 0;
/* Suspend pagedir is allocated before final copy, therefore it
must be freed after resume
- Warning: this is evil. There are actually two pagedirs at time of
- resume. One is "pagedir_save", which is empty frame allocated at
- time of suspend, that must be freed. Second is "pagedir_nosave",
- allocated at time of resume, that travels through memory not to
- collide with anything.
-
Warning: this is even more evil than it seems. Pagedirs this file
talks about are completely different from page directories used by
MMU hardware.
*/
suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
-suspend_pagedir_t *pagedir_save;
#define SWSUSP_SIG "S1SUSPEND"
@@ -122,8 +123,8 @@ static struct swsusp_info swsusp_info;
static unsigned short swapfile_used[MAX_SWAPFILES];
static unsigned short root_swap;
-static int write_page(unsigned long addr, swp_entry_t * loc);
-static int bio_read_page(pgoff_t page_off, void * page);
+static int write_page(unsigned long addr, swp_entry_t *loc);
+static int bio_read_page(pgoff_t page_off, void *page);
static u8 key_iv[MAXKEY+MAXIV];
@@ -355,7 +356,7 @@ static void lock_swapdevices(void)
* This is a partial improvement, since we will at least return other
* errors, though we need to eventually fix the damn code.
*/
-static int write_page(unsigned long addr, swp_entry_t * loc)
+static int write_page(unsigned long addr, swp_entry_t *loc)
{
swp_entry_t entry;
int error = 0;
@@ -383,9 +384,9 @@ static int write_page(unsigned long addr, swp_entry_t * loc)
static void data_free(void)
{
swp_entry_t entry;
- struct pbe * p;
+ struct pbe *p;
- for_each_pbe(p, pagedir_nosave) {
+ for_each_pbe (p, pagedir_nosave) {
entry = p->swap_address;
if (entry.val)
swap_free(entry);
@@ -492,8 +493,8 @@ static void free_pagedir_entries(void)
static int write_pagedir(void)
{
int error = 0;
- unsigned n = 0;
- struct pbe * pbe;
+ unsigned int n = 0;
+ struct pbe *pbe;
printk( "Writing pagedir...");
for_each_pb_page (pbe, pagedir_nosave) {
@@ -507,6 +508,26 @@ static int write_pagedir(void)
}
/**
+ * enough_swap - Make sure we have enough swap to save the image.
+ *
+ * Returns TRUE or FALSE after checking the total amount of swap
+ * space avaiable.
+ *
+ * FIXME: si_swapinfo(&i) returns all swap devices information.
+ * We should only consider resume_device.
+ */
+
+static int enough_swap(unsigned int nr_pages)
+{
+ struct sysinfo i;
+
+ si_swapinfo(&i);
+ pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
+ return i.freeswap > (nr_pages + PAGES_FOR_IO +
+ (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
+}
+
+/**
* write_suspend_image - Write entire image and metadata.
*
*/
@@ -514,6 +535,11 @@ static int write_suspend_image(void)
{
int error;
+ if (!enough_swap(nr_copy_pages)) {
+ printk(KERN_ERR "swsusp: Not enough free swap\n");
+ return -ENOSPC;
+ }
+
init_header();
if ((error = data_write()))
goto FreeData;
@@ -533,27 +559,6 @@ static int write_suspend_image(void)
goto Done;
}
-/**
- * enough_swap - Make sure we have enough swap to save the image.
- *
- * Returns TRUE or FALSE after checking the total amount of swap
- * space avaiable.
- *
- * FIXME: si_swapinfo(&i) returns all swap devices information.
- * We should only consider resume_device.
- */
-
-int enough_swap(unsigned nr_pages)
-{
- struct sysinfo i;
-
- si_swapinfo(&i);
- pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
- return i.freeswap > (nr_pages + PAGES_FOR_IO +
- (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
-}
-
-
/* It is important _NOT_ to umount filesystems at this point. We want
* them synced (in case something goes wrong) but we DO not want to mark
* filesystem clean: it is not. (And it does not matter, if we resume
@@ -563,12 +568,15 @@ int swsusp_write(void)
{
int error;
+ if ((error = swsusp_swap_check())) {
+ printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n");
+ return error;
+ }
lock_swapdevices();
error = write_suspend_image();
/* This will unlock ignored swap devices since writing is finished */
lock_swapdevices();
return error;
-
}
@@ -576,6 +584,7 @@ int swsusp_write(void)
int swsusp_suspend(void)
{
int error;
+
if ((error = arch_prepare_suspend()))
return error;
local_irq_disable();
@@ -587,15 +596,12 @@ int swsusp_suspend(void)
*/
if ((error = device_power_down(PMSG_FREEZE))) {
printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
- local_irq_enable();
- return error;
+ goto Enable_irqs;
}
- if ((error = swsusp_swap_check())) {
- printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n");
- device_power_up();
- local_irq_enable();
- return error;
+ if ((error = save_highmem())) {
+ printk(KERN_ERR "swsusp: Not enough free pages for highmem\n");
+ goto Restore_highmem;
}
save_processor_state();
@@ -603,8 +609,10 @@ int swsusp_suspend(void)
printk(KERN_ERR "Error %d suspending\n", error);
/* Restore control flow magically appears here */
restore_processor_state();
+Restore_highmem:
restore_highmem();
device_power_up();
+Enable_irqs:
local_irq_enable();
return error;
}
@@ -636,127 +644,43 @@ int swsusp_resume(void)
}
/**
- * On resume, for storing the PBE list and the image,
- * we can only use memory pages that do not conflict with the pages
- * which had been used before suspend.
- *
- * We don't know which pages are usable until we allocate them.
- *
- * Allocated but unusable (ie eaten) memory pages are marked so that
- * swsusp_free() can release them
- */
-
-unsigned long get_safe_page(gfp_t gfp_mask)
-{
- unsigned long m;
-
- do {
- m = get_zeroed_page(gfp_mask);
- if (m && PageNosaveFree(virt_to_page(m)))
- /* This is for swsusp_free() */
- SetPageNosave(virt_to_page(m));
- } while (m && PageNosaveFree(virt_to_page(m)));
- if (m) {
- /* This is for swsusp_free() */
- SetPageNosave(virt_to_page(m));
- SetPageNosaveFree(virt_to_page(m));
- }
- return m;
-}
-
-/**
- * check_pagedir - We ensure here that pages that the PBEs point to
- * won't collide with pages where we're going to restore from the loaded
- * pages later
- */
-
-static int check_pagedir(struct pbe *pblist)
-{
- struct pbe *p;
-
- /* This is necessary, so that we can free allocated pages
- * in case of failure
- */
- for_each_pbe (p, pblist)
- p->address = 0UL;
-
- for_each_pbe (p, pblist) {
- p->address = get_safe_page(GFP_ATOMIC);
- if (!p->address)
- return -ENOMEM;
- }
- return 0;
-}
-
-/**
- * swsusp_pagedir_relocate - It is possible, that some memory pages
- * occupied by the list of PBEs collide with pages where we're going to
- * restore from the loaded pages later. We relocate them here.
+ * mark_unsafe_pages - mark the pages that cannot be used for storing
+ * the image during resume, because they conflict with the pages that
+ * had been used before suspend
*/
-static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
+static void mark_unsafe_pages(struct pbe *pblist)
{
struct zone *zone;
unsigned long zone_pfn;
- struct pbe *pbpage, *tail, *p;
- void *m;
- int rel = 0;
+ struct pbe *p;
if (!pblist) /* a sanity check */
- return NULL;
-
- pr_debug("swsusp: Relocating pagedir (%lu pages to check)\n",
- swsusp_info.pagedir_pages);
+ return;
/* Clear page flags */
-
for_each_zone (zone) {
- for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
- if (pfn_valid(zone_pfn + zone->zone_start_pfn))
- ClearPageNosaveFree(pfn_to_page(zone_pfn +
+ for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
+ if (pfn_valid(zone_pfn + zone->zone_start_pfn))
+ ClearPageNosaveFree(pfn_to_page(zone_pfn +
zone->zone_start_pfn));
}
/* Mark orig addresses */
-
for_each_pbe (p, pblist)
SetPageNosaveFree(virt_to_page(p->orig_address));
- tail = pblist + PB_PAGE_SKIP;
-
- /* Relocate colliding pages */
-
- for_each_pb_page (pbpage, pblist) {
- if (PageNosaveFree(virt_to_page((unsigned long)pbpage))) {
- m = (void *)get_safe_page(GFP_ATOMIC | __GFP_COLD);
- if (!m)
- return NULL;
- memcpy(m, (void *)pbpage, PAGE_SIZE);
- if (pbpage == pblist)
- pblist = (struct pbe *)m;
- else
- tail->next = (struct pbe *)m;
- pbpage = (struct pbe *)m;
-
- /* We have to link the PBEs again */
- for (p = pbpage; p < pbpage + PB_PAGE_SKIP; p++)
- if (p->next) /* needed to save the end */
- p->next = p + 1;
-
- rel++;
- }
- tail = pbpage + PB_PAGE_SKIP;
- }
+}
- /* This is for swsusp_free() */
- for_each_pb_page (pbpage, pblist) {
- SetPageNosave(virt_to_page(pbpage));
- SetPageNosaveFree(virt_to_page(pbpage));
+static void copy_page_backup_list(struct pbe *dst, struct pbe *src)
+{
+ /* We assume both lists contain the same number of elements */
+ while (src) {
+ dst->orig_address = src->orig_address;
+ dst->swap_address = src->swap_address;
+ dst = dst->next;
+ src = src->next;
}
-
- printk("swsusp: Relocated %d pages\n", rel);
-
- return pblist;
}
/*
@@ -770,7 +694,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
static atomic_t io_done = ATOMIC_INIT(0);
-static int end_io(struct bio * bio, unsigned int num, int err)
+static int end_io(struct bio *bio, unsigned int num, int err)
{
if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
panic("I/O error reading memory image");
@@ -778,7 +702,7 @@ static int end_io(struct bio * bio, unsigned int num, int err)
return 0;
}
-static struct block_device * resume_bdev;
+static struct block_device *resume_bdev;
/**
* submit - submit BIO request.
@@ -791,10 +715,10 @@ static struct block_device * resume_bdev;
* Then submit it and wait.
*/
-static int submit(int rw, pgoff_t page_off, void * page)
+static int submit(int rw, pgoff_t page_off, void *page)
{
int error = 0;
- struct bio * bio;
+ struct bio *bio;
bio = bio_alloc(GFP_ATOMIC, 1);
if (!bio)
@@ -823,12 +747,12 @@ static int submit(int rw, pgoff_t page_off, void * page)
return error;
}
-static int bio_read_page(pgoff_t page_off, void * page)
+static int bio_read_page(pgoff_t page_off, void *page)
{
return submit(READ, page_off, page);
}
-static int bio_write_page(pgoff_t page_off, void * page)
+static int bio_write_page(pgoff_t page_off, void *page)
{
return submit(WRITE, page_off, page);
}
@@ -838,7 +762,7 @@ static int bio_write_page(pgoff_t page_off, void * page)
* I really don't think that it's foolproof but more than nothing..
*/
-static const char * sanity_check(void)
+static const char *sanity_check(void)
{
dump_info();
if (swsusp_info.version_code != LINUX_VERSION_CODE)
@@ -864,7 +788,7 @@ static const char * sanity_check(void)
static int check_header(void)
{
- const char * reason = NULL;
+ const char *reason = NULL;
int error;
if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info)))
@@ -895,7 +819,7 @@ static int check_sig(void)
* Reset swap signature now.
*/
error = bio_write_page(0, &swsusp_header);
- } else {
+ } else {
return -EINVAL;
}
if (!error)
@@ -912,7 +836,7 @@ static int check_sig(void)
static int data_read(struct pbe *pblist)
{
- struct pbe * p;
+ struct pbe *p;
int error = 0;
int i = 0;
int mod = swsusp_info.image_pages / 100;
@@ -950,7 +874,7 @@ static int data_read(struct pbe *pblist)
static int read_pagedir(struct pbe *pblist)
{
struct pbe *pbpage, *p;
- unsigned i = 0;
+ unsigned int i = 0;
int error;
if (!pblist)
@@ -997,20 +921,25 @@ static int read_suspend_image(void)
int error = 0;
struct pbe *p;
- if (!(p = alloc_pagedir(nr_copy_pages)))
+ if (!(p = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 0)))
return -ENOMEM;
if ((error = read_pagedir(p)))
return error;
-
create_pbe_list(p, nr_copy_pages);
-
- if (!(pagedir_nosave = swsusp_pagedir_relocate(p)))
+ mark_unsafe_pages(p);
+ pagedir_nosave = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1);
+ if (pagedir_nosave) {
+ create_pbe_list(pagedir_nosave, nr_copy_pages);
+ copy_page_backup_list(pagedir_nosave, p);
+ }
+ free_pagedir(p);
+ if (!pagedir_nosave)
return -ENOMEM;
/* Allocate memory for the image and read the data from swap */
- error = check_pagedir(pagedir_nosave);
+ error = alloc_data_pages(pagedir_nosave, GFP_ATOMIC, 1);
if (!error)
error = data_read(pagedir_nosave);