diff options
| author | Patrick Mochel <mochel@digitalimplant.org> | 2004-07-16 21:11:04 -0700 |
|---|---|---|
| committer | Patrick Mochel <mochel@digitalimplant.org> | 2004-07-16 21:11:04 -0700 |
| commit | 44ea4dc07e7a1281293386e755f9a96d523e84b3 (patch) | |
| tree | 99e0bd51774ccad7efb5d161d868fede9014ab4e /kernel | |
| parent | 2e633f4f6ed2cff8f3d46bad6cf0b24da81a56a1 (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.c | 8 | ||||
| -rw-r--r-- | kernel/power/pmdisk.c | 89 | ||||
| -rw-r--r-- | kernel/power/swsusp.c | 115 |
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: |
