diff options
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/disk.c | 12 | ||||
-rw-r--r-- | kernel/power/main.c | 16 | ||||
-rw-r--r-- | kernel/power/process.c | 6 | ||||
-rw-r--r-- | kernel/power/swsusp.c | 36 |
4 files changed, 41 insertions, 29 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index fb8de63c291..3ec789c6b53 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -16,6 +16,8 @@ #include <linux/device.h> #include <linux/delay.h> #include <linux/fs.h> +#include <linux/mount.h> + #include "power.h" @@ -234,6 +236,16 @@ static int software_resume(void) { int error; + if (!swsusp_resume_device) { + if (!strlen(resume_file)) + return -ENOENT; + swsusp_resume_device = name_to_dev_t(resume_file); + pr_debug("swsusp: Resume From Partition %s\n", resume_file); + } else { + pr_debug("swsusp: Resume From Partition %d:%d\n", + MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); + } + if (noresume) { /** * FIXME: If noresume is specified, we need to find the partition diff --git a/kernel/power/main.c b/kernel/power/main.c index c94cb9e9509..71aa0fd2200 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -19,6 +19,9 @@ #include "power.h" +/*This is just an arbitrary number */ +#define FREE_PAGE_NUMBER (100) + DECLARE_MUTEX(pm_sem); struct pm_ops * pm_ops = NULL; @@ -49,6 +52,7 @@ void pm_set_ops(struct pm_ops * ops) static int suspend_prepare(suspend_state_t state) { int error = 0; + unsigned int free_pages; if (!pm_ops || !pm_ops->enter) return -EPERM; @@ -67,6 +71,16 @@ static int suspend_prepare(suspend_state_t state) goto Thaw; } + if ((free_pages = nr_free_pages()) < FREE_PAGE_NUMBER) { + pr_debug("PM: free some memory\n"); + shrink_all_memory(FREE_PAGE_NUMBER - free_pages); + if (nr_free_pages() < FREE_PAGE_NUMBER) { + error = -ENOMEM; + printk(KERN_ERR "PM: No enough memory\n"); + goto Thaw; + } + } + if (pm_ops->prepare) { if ((error = pm_ops->prepare(state))) goto Thaw; @@ -194,7 +208,7 @@ int software_suspend(void) int pm_suspend(suspend_state_t state) { - if (state > PM_SUSPEND_ON && state < PM_SUSPEND_MAX) + if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX) return enter_state(state); return -EINVAL; } diff --git a/kernel/power/process.c b/kernel/power/process.c index 0a086640bcf..3bd0d261818 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -59,6 +59,7 @@ int freeze_processes(void) int todo; unsigned long start_time; struct task_struct *g, *p; + unsigned long flags; printk( "Stopping tasks: " ); start_time = jiffies; @@ -66,12 +67,9 @@ int freeze_processes(void) todo = 0; read_lock(&tasklist_lock); do_each_thread(g, p) { - unsigned long flags; if (!freezeable(p)) continue; - if ((frozen(p)) || - (p->state == TASK_TRACED) || - (p->state == TASK_STOPPED)) + if (frozen(p)) continue; freeze(p); diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index c285fc5a232..f2bc71b9fe8 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -63,6 +63,7 @@ #include <linux/console.h> #include <linux/highmem.h> #include <linux/bio.h> +#include <linux/mount.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -869,13 +870,6 @@ extern asmlinkage int swsusp_arch_resume(void); asmlinkage int swsusp_save(void) { - int error = 0; - - if ((error = swsusp_swap_check())) { - printk(KERN_ERR "swsusp: FATAL: cannot find swap device, try " - "swapon -a!\n"); - return error; - } return suspend_prepare_image(); } @@ -892,14 +886,20 @@ int swsusp_suspend(void) * at resume time, and evil weirdness ensues. */ if ((error = device_power_down(PMSG_FREEZE))) { - printk(KERN_ERR "Some devices failed to power down, aborting suspend\n"); local_irq_enable(); - swsusp_free(); return error; } + + if ((error = swsusp_swap_check())) { + printk(KERN_ERR "swsusp: FATAL: cannot find swap device, try " + "swapon -a!\n"); + local_irq_enable(); + return error; + } + save_processor_state(); if ((error = swsusp_arch_suspend())) - swsusp_free(); + printk("Error %d suspending\n", error); /* Restore control flow magically appears here */ restore_processor_state(); BUG_ON (nr_copy_pages_check != nr_copy_pages); @@ -1166,9 +1166,9 @@ static int bio_write_page(pgoff_t page_off, void * page) static const char * sanity_check(void) { dump_info(); - if(swsusp_info.version_code != LINUX_VERSION_CODE) + if (swsusp_info.version_code != LINUX_VERSION_CODE) return "kernel version"; - if(swsusp_info.num_physpages != num_physpages) + if (swsusp_info.num_physpages != num_physpages) return "memory size"; if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) return "system type"; @@ -1261,8 +1261,6 @@ static int data_read(struct pbe *pblist) return error; } -extern dev_t name_to_dev_t(const char *line); - /** * read_pagedir - Read page backup list pages from swap */ @@ -1356,16 +1354,6 @@ int swsusp_check(void) { int error; - if (!swsusp_resume_device) { - if (!strlen(resume_file)) - return -ENOENT; - swsusp_resume_device = name_to_dev_t(resume_file); - pr_debug("swsusp: Resume From Partition %s\n", resume_file); - } else { - pr_debug("swsusp: Resume From Partition %d:%d\n", - MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); - } - resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); |