summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@digitalimplant.org>2004-07-16 21:11:04 -0700
committerPatrick Mochel <mochel@digitalimplant.org>2004-07-16 21:11:04 -0700
commit44ea4dc07e7a1281293386e755f9a96d523e84b3 (patch)
tree99e0bd51774ccad7efb5d161d868fede9014ab4e /kernel
parent2e633f4f6ed2cff8f3d46bad6cf0b24da81a56a1 (diff)
[Power Mgmt] Consolidate pmdisk and swsusp low-level handling.
- Split do_magic into swsusp_arch_suspend() and swsusp_arch_resume(). - Clean up based on pmdisk implementation - Only save registers we need to. - Use rep;movsl for copying, rather than doing each byte. - Create swsusp_suspend and swsusp_resume wrappers for calling the assmebly routines that: - Call {save,restore}_processor_state() in each. - Disable/enable interrupts in each. - Call swsusp_{suspend,restore} in software_{suspend,resume} - Kill all the do_magic_* functions. - Remove prototypes from linux/suspend.h - Remove similar pmdisk functions. - Update calls in kernel/power/disk.c to use swsusp versions.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/disk.c8
-rw-r--r--kernel/power/pmdisk.c89
-rw-r--r--kernel/power/swsusp.c115
3 files changed, 50 insertions, 162 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 6abcf99b7ada..f3a4a4b1bb56 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -23,10 +23,10 @@
extern u32 pm_disk_mode;
extern struct pm_ops * pm_ops;
-extern int pmdisk_save(void);
+extern int swsusp_suspend(void);
extern int pmdisk_write(void);
extern int pmdisk_read(void);
-extern int pmdisk_restore(void);
+extern int swsusp_resume(void);
extern int pmdisk_free(void);
@@ -161,7 +161,7 @@ int pm_suspend_disk(void)
pr_debug("PM: snapshotting memory.\n");
in_suspend = 1;
- if ((error = pmdisk_save()))
+ if ((error = swsusp_save()))
goto Done;
if (in_suspend) {
@@ -227,7 +227,7 @@ static int pm_resume(void)
mdelay(1000);
pr_debug("PM: Restoring saved image.\n");
- pmdisk_restore();
+ swsusp_resume();
pr_debug("PM: Restore failed, recovering.n");
finish();
Free:
diff --git a/kernel/power/pmdisk.c b/kernel/power/pmdisk.c
index f10253a3840a..bbe93fdc1cdf 100644
--- a/kernel/power/pmdisk.c
+++ b/kernel/power/pmdisk.c
@@ -249,28 +249,7 @@ static int write_suspend_image(void)
extern void free_suspend_pagedir(unsigned long);
-extern int suspend_prepare_image(void);
-/**
- * pmdisk_suspend - Atomically snapshot the system.
- *
- * This must be called with interrupts disabled, to prevent the
- * system changing at all from underneath us.
- *
- * To do this, we count the number of pages in the system that we
- * need to save; make sure we have enough memory and swap to clone
- * the pages and save them in swap, allocate the space to hold them,
- * and then snapshot them all.
- */
-
-int pmdisk_suspend(void)
-{
- int error = 0;
-
- if ((error = swsusp_swap_check()))
- return error;
- return suspend_prepare_image();
-}
/**
@@ -297,36 +276,6 @@ static int suspend_save_image(void)
return error;
}
-/*
- * Magic happens here
- */
-
-int pmdisk_resume(void)
-{
- BUG_ON (nr_copy_pages_check != nr_copy_pages);
- BUG_ON (pagedir_order_check != pagedir_order);
-
- /* Even mappings of "global" things (vmalloc) need to be fixed */
- __flush_tlb_global();
- return 0;
-}
-
-/* pmdisk_arch_suspend() is implemented in arch/?/power/pmdisk.S,
- and basically does:
-
- if (!resume) {
- save_processor_state();
- SAVE_REGISTERS
- return pmdisk_suspend();
- }
- GO_TO_SWAPPER_PAGE_TABLES
- COPY_PAGES_BACK
- RESTORE_REGISTERS
- restore_processor_state();
- return pmdisk_resume();
-
- */
-
/* More restore stuff */
@@ -563,28 +512,6 @@ static int __init read_suspend_image(void)
goto Done;
}
-/**
- * pmdisk_save - Snapshot memory
- */
-
-int pmdisk_save(void)
-{
- int error;
-
-#if defined (CONFIG_HIGHMEM) || defined (CONFIG_DISCONTIGMEM)
- pr_debug("pmdisk: not supported with high- or discontig-mem.\n");
- return -EPERM;
-#endif
- if ((error = arch_prepare_suspend()))
- return error;
- local_irq_disable();
- save_processor_state();
- error = pmdisk_arch_suspend(0);
- restore_processor_state();
- local_irq_enable();
- return error;
-}
-
/**
* pmdisk_write - Write saved memory image to swap.
@@ -633,22 +560,6 @@ int __init pmdisk_read(void)
/**
- * pmdisk_restore - Replace running kernel with saved image.
- */
-
-int __init pmdisk_restore(void)
-{
- int error;
- local_irq_disable();
- save_processor_state();
- error = pmdisk_arch_suspend(1);
- restore_processor_state();
- local_irq_enable();
- return error;
-}
-
-
-/**
* pmdisk_free - Free memory allocated to hold snapshot.
*/
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 91d8390dc2f5..7de6b26f4efe 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -893,80 +893,58 @@ static void suspend_finish(void)
#endif
}
-/*
- * Magic happens here
- */
-asmlinkage void do_magic_resume_1(void)
-{
- barrier();
- mb();
- spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */
+extern asmlinkage int swsusp_arch_suspend(void);
+extern asmlinkage int swsusp_arch_resume(void);
- device_power_down(3);
- PRINTK( "Waiting for DMAs to settle down...\n");
- mdelay(1000); /* We do not want some readahead with DMA to corrupt our memory, right?
- Do it with disabled interrupts for best effect. That way, if some
- driver scheduled DMA, we have good chance for DMA to finish ;-). */
-}
-asmlinkage void do_magic_resume_2(void)
+asmlinkage int swsusp_save(void)
{
- BUG_ON (nr_copy_pages_check != nr_copy_pages);
- BUG_ON (pagedir_order_check != pagedir_order);
+ int error = 0;
- __flush_tlb_global(); /* Even mappings of "global" things (vmalloc) need to be fixed */
- device_power_up();
- spin_unlock_irq(&suspend_pagedir_lock);
+ if ((error = swsusp_swap_check()))
+ return error;
+ return suspend_prepare_image();
}
-/* do_magic() is implemented in arch/?/kernel/suspend_asm.S, and basically does:
-
- if (!resume) {
- do_magic_suspend_1();
- save_processor_state();
- SAVE_REGISTERS
- do_magic_suspend_2();
- return;
- }
- GO_TO_SWAPPER_PAGE_TABLES
- do_magic_resume_1();
- COPY_PAGES_BACK
- RESTORE_REGISTERS
+int swsusp_suspend(void)
+{
+ int error;
+ if ((error = arch_prepare_suspend()))
+ return error;
+ local_irq_disable();
+ save_processor_state();
+ error = swsusp_arch_suspend();
restore_processor_state();
- do_magic_resume_2();
+ local_irq_enable();
+ return error;
+}
- */
-asmlinkage void do_magic_suspend_1(void)
+asmlinkage int swsusp_restore(void)
{
- mb();
- barrier();
- BUG_ON(in_atomic());
- spin_lock_irq(&suspend_pagedir_lock);
+ BUG_ON (nr_copy_pages_check != nr_copy_pages);
+ BUG_ON (pagedir_order_check != pagedir_order);
+
+ /* Even mappings of "global" things (vmalloc) need to be fixed */
+ __flush_tlb_global();
+ return 0;
}
-asmlinkage void do_magic_suspend_2(void)
+int swsusp_resume(void)
{
- int is_problem;
- swsusp_swap_check();
- device_power_down(3);
- is_problem = suspend_prepare_image();
- device_power_up();
- spin_unlock_irq(&suspend_pagedir_lock);
- if (!is_problem) {
- kernel_fpu_end(); /* save_processor_state() does kernel_fpu_begin, and we need to revert it in order to pass in_atomic() checks */
- BUG_ON(in_atomic());
- suspend_save_image();
- suspend_power_down(); /* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */
- }
+ int error;
+ local_irq_disable();
+ save_processor_state();
+ error = swsusp_arch_resume();
+ restore_processor_state();
+ local_irq_enable();
+ return error;
+}
- printk(KERN_EMERG "%sSuspend failed, trying to recover...\n", name_suspend);
- MDELAY(1000); /* So user can wait and report us messages if armageddon comes :-) */
- barrier();
- mb();
-}
+
+static int in_suspend __nosavedata = 0;
/*
* This is main interface to the outside world. It needs to be
@@ -998,16 +976,15 @@ int software_suspend(void)
/* Save state of all device drivers, and stop them. */
printk("Suspending devices... ");
if ((res = device_suspend(3))==0) {
- /* If stopping device drivers worked, we proceed basically into
- * suspend_save_image.
- *
- * do_magic(0) returns after system is resumed.
- *
- * do_magic() copies all "used" memory to "free" memory, then
- * unsuspends all device drivers, and writes memory to disk
- * using normal kernel mechanism.
- */
- do_magic(0);
+ in_suspend = 1;
+
+ res = swsusp_save();
+
+ if (!res && in_suspend) {
+ suspend_save_image();
+ suspend_power_down();
+ }
+ in_suspend = 0;
suspend_finish();
}
thaw_processes();
@@ -1352,7 +1329,7 @@ static int __init software_resume(void)
/* FIXME: Should we stop processes here, just to be safer? */
disable_nonboot_cpus();
device_suspend(3);
- do_magic(1);
+ swsusp_resume();
panic("This never returns");
read_failure: