Commit 2d6e58e7 authored by Patrick Mochel's avatar Patrick Mochel

[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).
parent 128b46cd
...@@ -163,27 +163,27 @@ int pm_suspend_disk(void) ...@@ -163,27 +163,27 @@ int pm_suspend_disk(void)
pr_debug("PM: snapshotting memory.\n"); pr_debug("PM: snapshotting memory.\n");
in_suspend = 1; in_suspend = 1;
local_irq_disable();
if ((error = swsusp_save())) if ((error = swsusp_save()))
goto Done; goto Done;
pr_debug("PM: writing image.\n"); if (in_suspend) {
pr_debug("PM: writing image.\n");
/* /*
* FIXME: Leftover from swsusp. Are they necessary? * FIXME: Leftover from swsusp. Are they necessary?
*/ */
mb(); mb();
barrier(); barrier();
error = swsusp_write(); error = swsusp_write();
if (!error && in_suspend) { if (!error) {
error = power_down(pm_disk_mode); error = power_down(pm_disk_mode);
pr_debug("PM: Power down failed.\n"); pr_debug("PM: Power down failed.\n");
}
} else } else
pr_debug("PM: Image restored successfully.\n"); pr_debug("PM: Image restored successfully.\n");
swsusp_free(); swsusp_free();
Done: Done:
local_irq_enable();
finish(); finish();
return error; return error;
} }
...@@ -217,7 +217,6 @@ static int pm_resume(void) ...@@ -217,7 +217,6 @@ static int pm_resume(void)
barrier(); barrier();
mb(); mb();
local_irq_disable();
/* FIXME: The following (comment and mdelay()) are from swsusp. /* FIXME: The following (comment and mdelay()) are from swsusp.
* Are they really necessary? * Are they really necessary?
...@@ -231,7 +230,6 @@ static int pm_resume(void) ...@@ -231,7 +230,6 @@ static int pm_resume(void)
pr_debug("PM: Restoring saved image.\n"); pr_debug("PM: Restoring saved image.\n");
swsusp_restore(); swsusp_restore();
local_irq_enable();
pr_debug("PM: Restore failed, recovering.n"); pr_debug("PM: Restore failed, recovering.n");
finish(); finish();
Free: Free:
......
...@@ -416,11 +416,12 @@ static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages) ...@@ -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; struct sysinfo i;
unsigned int nr_needed_pages = 0; unsigned int nr_needed_pages = 0;
read_swapfiles();
drain_local_pages(); drain_local_pages();
pagedir_nosave = NULL; pagedir_nosave = NULL;
...@@ -486,12 +487,10 @@ static int suspend_prepare_image(void) ...@@ -486,12 +487,10 @@ static int suspend_prepare_image(void)
static int suspend_save_image(void) static int suspend_save_image(void)
{ {
int error; int error;
local_irq_enable();
device_resume(); device_resume();
lock_swapdevices(); lock_swapdevices();
error = write_suspend_image(); error = write_suspend_image();
lock_swapdevices(); lock_swapdevices();
local_irq_disable();
return error; return error;
} }
...@@ -515,35 +514,17 @@ int swsusp_resume(void) ...@@ -515,35 +514,17 @@ int swsusp_resume(void)
if (!resume) { if (!resume) {
save_processor_state(); save_processor_state();
SAVE_REGISTERS SAVE_REGISTERS
swsusp_suspend(); return swsusp_suspend();
return;
} }
GO_TO_SWAPPER_PAGE_TABLES GO_TO_SWAPPER_PAGE_TABLES
COPY_PAGES_BACK COPY_PAGES_BACK
RESTORE_REGISTERS RESTORE_REGISTERS
restore_processor_state(); 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 */ /* More restore stuff */
/* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */ /* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */
...@@ -870,11 +851,18 @@ static int __init read_suspend_image(void) ...@@ -870,11 +851,18 @@ static int __init read_suspend_image(void)
int swsusp_save(void) int swsusp_save(void)
{ {
int error;
#if defined (CONFIG_HIGHMEM) || defined (COFNIG_DISCONTIGMEM) #if defined (CONFIG_HIGHMEM) || defined (COFNIG_DISCONTIGMEM)
printk("swsusp is not supported with high- or discontig-mem.\n"); printk("swsusp is not supported with high- or discontig-mem.\n");
return -EPERM; return -EPERM;
#endif #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) ...@@ -890,7 +878,7 @@ int swsusp_save(void)
int swsusp_write(void) int swsusp_write(void)
{ {
return swsusp_arch_suspend(0); return suspend_save_image();
} }
...@@ -933,7 +921,11 @@ int __init swsusp_read(void) ...@@ -933,7 +921,11 @@ int __init swsusp_read(void)
int __init swsusp_restore(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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment