summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2003-09-08 02:41:39 -0700
committerPatrick Mochel <mochel@osdl.org>2003-09-08 02:41:39 -0700
commit2d6e58e7b2ee73edfab739e122f4d95f51ab5b89 (patch)
tree4c6202c799511d72b5abacede2089b527975dbdf /kernel
parent128b46cd4bc9ebfa5117800e7c20870343e465ad (diff)
[power] Fix swsusp with preempt and clean up.
In order to snapshot memory, interrupts must be disabled. However, in order to write the saved image to disk, interrupts must be re-enabled and devices resumed. Previously, both actions were called from swsusp_arch_suspend(). This patch separates those two actions has only the snapshotting routine called from swsusp_arch_suspend(). swsusp now handles it's own disabling of interrupts only for the time required. This is now handled from swsusp_save() and swsusp_write() now handles writing the image only (called with interrupts enabled). swsusp_save_image() was renamed to swsusp_suspend() (and the old incarnation deleted since it was simply a wrapper).
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/disk.c26
-rw-r--r--kernel/power/swsusp.c44
2 files changed, 30 insertions, 40 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index e7e40119d917..64a3130a5411 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -163,27 +163,27 @@ int pm_suspend_disk(void)
pr_debug("PM: snapshotting memory.\n");
in_suspend = 1;
- local_irq_disable();
if ((error = swsusp_save()))
goto Done;
- pr_debug("PM: writing image.\n");
+ if (in_suspend) {
+ pr_debug("PM: writing image.\n");
- /*
- * FIXME: Leftover from swsusp. Are they necessary?
- */
- mb();
- barrier();
+ /*
+ * FIXME: Leftover from swsusp. Are they necessary?
+ */
+ mb();
+ barrier();
- error = swsusp_write();
- if (!error && in_suspend) {
- error = power_down(pm_disk_mode);
- pr_debug("PM: Power down failed.\n");
+ error = swsusp_write();
+ if (!error) {
+ error = power_down(pm_disk_mode);
+ pr_debug("PM: Power down failed.\n");
+ }
} else
pr_debug("PM: Image restored successfully.\n");
swsusp_free();
Done:
- local_irq_enable();
finish();
return error;
}
@@ -217,7 +217,6 @@ static int pm_resume(void)
barrier();
mb();
- local_irq_disable();
/* FIXME: The following (comment and mdelay()) are from swsusp.
* Are they really necessary?
@@ -231,7 +230,6 @@ static int pm_resume(void)
pr_debug("PM: Restoring saved image.\n");
swsusp_restore();
- local_irq_enable();
pr_debug("PM: Restore failed, recovering.n");
finish();
Free:
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index e9a1e97a2f2b..bb795b6dc537 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -416,11 +416,12 @@ static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
}
-static int suspend_prepare_image(void)
+int swsusp_suspend(void)
{
struct sysinfo i;
unsigned int nr_needed_pages = 0;
+ read_swapfiles();
drain_local_pages();
pagedir_nosave = NULL;
@@ -486,12 +487,10 @@ static int suspend_prepare_image(void)
static int suspend_save_image(void)
{
int error;
- local_irq_enable();
device_resume();
lock_swapdevices();
error = write_suspend_image();
lock_swapdevices();
- local_irq_disable();
return error;
}
@@ -515,35 +514,17 @@ int swsusp_resume(void)
if (!resume) {
save_processor_state();
SAVE_REGISTERS
- swsusp_suspend();
- return;
+ return swsusp_suspend();
}
GO_TO_SWAPPER_PAGE_TABLES
COPY_PAGES_BACK
RESTORE_REGISTERS
restore_processor_state();
- swsusp_resume();
+ return swsusp_resume();
*/
-int swsusp_suspend(void)
-{
- int error;
- read_swapfiles();
- error = suspend_prepare_image();
- if (!error)
- error = suspend_save_image();
- if (error) {
- printk(KERN_EMERG "%sSuspend failed, trying to recover...\n",
- name_suspend);
- barrier();
- mb();
- mdelay(1000);
- }
- return error;
-}
-
/* More restore stuff */
/* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */
@@ -870,11 +851,18 @@ static int __init read_suspend_image(void)
int swsusp_save(void)
{
+ int error;
+
#if defined (CONFIG_HIGHMEM) || defined (COFNIG_DISCONTIGMEM)
printk("swsusp is not supported with high- or discontig-mem.\n");
return -EPERM;
#endif
- return arch_prepare_suspend();
+ if ((error = arch_prepare_suspend()))
+ return error;
+ local_irq_disable();
+ error = swsusp_arch_suspend(0);
+ local_irq_enable();
+ return error;
}
@@ -890,7 +878,7 @@ int swsusp_save(void)
int swsusp_write(void)
{
- return swsusp_arch_suspend(0);
+ return suspend_save_image();
}
@@ -933,7 +921,11 @@ int __init swsusp_read(void)
int __init swsusp_restore(void)
{
- return swsusp_arch_suspend(1);
+ int error;
+ local_irq_disable();
+ error = swsusp_arch_suspend(1);
+ local_irq_enable();
+ return error;
}