From: Patrick Mochel Date: Tue, 19 Aug 2003 15:39:03 +0000 (-0700) Subject: [power] Further swsusp cleanups. X-Git-Tag: v2.6.0-test4~35 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=72a4a1790e1b2ae9c6f450144e3c733ae303ad23;p=history.git [power] Further swsusp cleanups. - Remove drivers_resume() and call from do_magic_resume2(). Handled by core. - When bringing devices back to life, call device_pm_resume() - Make sure we report the error from write_suspend_image() - Remove suspend_power_down() and call to it. Handled by PM core. - Move swap file resetting and freeing of pagedir to swsusp_free() - Remove extraneous in_atomic() checks. - Mark all resume functions __init. - Move resume_suspend_image() inside swsusp_read() and cleanup. - Make do_magic() report error. --- diff --git a/include/asm-i386/suspend.h b/include/asm-i386/suspend.h index f1114b6b5275..0d22ec30019b 100644 --- a/include/asm-i386/suspend.h +++ b/include/asm-i386/suspend.h @@ -38,7 +38,7 @@ struct saved_context { extern void save_processor_state(void); extern void restore_processor_state(void); -extern void do_magic(int resume); +extern int do_magic(int resume); #ifdef CONFIG_ACPI_SLEEP extern unsigned long saved_eip; diff --git a/include/linux/suspend.h b/include/linux/suspend.h index da171766c8c8..132db86c961a 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -48,13 +48,6 @@ extern void drain_local_pages(void); extern unsigned int nr_copy_pages __nosavedata; extern suspend_pagedir_t *pagedir_nosave __nosavedata; -/* Communication between kernel/suspend.c and arch/i386/suspend.c */ - -extern void do_magic_resume_1(void); -extern void do_magic_resume_2(void); -extern void do_magic_suspend_1(void); -extern void do_magic_suspend_2(void); - /* Communication between acpi and arch/i386/suspend.c */ extern void do_suspend_lowlevel(int resume); diff --git a/kernel/power/console.c b/kernel/power/console.c index c05d0e43675f..35b1f50d97de 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c @@ -41,6 +41,11 @@ void pm_restore_console(void) console_loglevel = orig_loglevel; #ifdef SUSPEND_CONSOLE set_console(orig_fgconsole); + + /* FIXME: + * This following part is left over from swsusp. Is it really needed? + */ + update_screen(fg_console); #endif return; } diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 5c70937437d4..4ce75e5c23bb 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -88,8 +88,6 @@ static dev_t resume_device; /* Local variables that should not be affected by save */ unsigned int nr_copy_pages __nosavedata = 0; -static int pm_suspend_state; - /* Suspend pagedir is allocated before final copy, therefore it must be freed after resume @@ -438,36 +436,6 @@ static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages) } -/* Make disk drivers accept operations, again */ -static void drivers_unsuspend(void) -{ - device_resume(RESUME_RESTORE_STATE); - device_resume(RESUME_ENABLE); -} - -#define RESUME_PHASE1 1 /* Called from interrupts disabled */ -#define RESUME_PHASE2 2 /* Called with interrupts enabled */ -#define RESUME_ALL_PHASES (RESUME_PHASE1 | RESUME_PHASE2) -static void drivers_resume(int flags) -{ - if (flags & RESUME_PHASE1) { - device_resume(RESUME_RESTORE_STATE); - device_resume(RESUME_ENABLE); - } - if (flags & RESUME_PHASE2) { - if (pm_suspend_state) { - if(pm_send_all(PM_RESUME,(void *)0)) - printk(KERN_WARNING "Problem while sending resume event\n"); - pm_suspend_state=0; - } else - printk(KERN_WARNING "PM suspend state wasn't raised\n"); - -#ifdef SUSPEND_CONSOLE - update_screen(fg_console); /* Hmm, is this the problem? */ -#endif - } -} - static int suspend_prepare_image(void) { struct sysinfo i; @@ -520,12 +488,14 @@ static int suspend_prepare_image(void) return 0; } -static void suspend_save_image(void) +static int suspend_save_image(void) { - drivers_unsuspend(); + int error; + + device_pm_resume(); lock_swapdevices(); - write_suspend_image(); + error = write_suspend_image(); lock_swapdevices(); /* This will unlock ignored swap devices since writing is finished */ /* It is important _NOT_ to umount filesystems at this point. We want @@ -533,29 +503,7 @@ static void suspend_save_image(void) * filesystem clean: it is not. (And it does not matter, if we resume * correctly, we'll mark system clean, anyway.) */ -} - -static void suspend_power_down(void) -{ - extern int C_A_D; - C_A_D = 0; - printk(KERN_EMERG "%s%s Trying to power down.\n", name_suspend, TEST_SWSUSP ? "Disable TEST_SWSUSP. NOT ": ""); -#ifdef CONFIG_VT - PRINTK(KERN_EMERG "shift_state: %04x\n", shift_state); - mdelay(1000); - if (TEST_SWSUSP ^ (!!(shift_state & (1 << KG_CTRL)))) - machine_restart(NULL); - else -#endif - { - device_shutdown(); - machine_power_off(); - } - - printk(KERN_EMERG "%sProbably not capable for powerdown. System halted.\n", name_suspend); - machine_halt(); - while (1); - /* NOTREACHED */ + return error; } /* @@ -567,32 +515,21 @@ void do_magic_resume_1(void) barrier(); mb(); spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */ - 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 ;-). */ + /* 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 ;-). */ + mdelay(1000); } void do_magic_resume_2(void) { BUG_ON (nr_copy_pages_check != nr_copy_pages); BUG_ON (pagedir_order_check != pagedir_order); - - __flush_tlb_global(); /* Even mappings of "global" things (vmalloc) need to be fixed */ - - PRINTK( "Freeing prev allocated pagedir\n" ); - free_suspend_pagedir((unsigned long) pagedir_save); + + /* Even mappings of "global" things (vmalloc) need to be fixed */ + __flush_tlb_global(); spin_unlock_irq(&suspend_pagedir_lock); - drivers_resume(RESUME_ALL_PHASES); - - PRINTK( "Fixing swap signatures... " ); - mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME); - PRINTK( "ok\n" ); - -#ifdef SUSPEND_CONSOLE - update_screen(fg_console); /* Hmm, is this the problem? */ -#endif } /* do_magic() is implemented in arch/?/kernel/suspend_asm.S, and basically does: @@ -617,40 +554,28 @@ void do_magic_suspend_1(void) { mb(); barrier(); - BUG_ON(in_atomic()); spin_lock_irq(&suspend_pagedir_lock); } -void do_magic_suspend_2(void) +int do_magic_suspend_2(void) { int is_problem; read_swapfiles(); is_problem = suspend_prepare_image(); 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 ?! */ - } - + if (!is_problem) + return suspend_save_image(); 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(); - spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */ mdelay(1000); - - free_pages((unsigned long) pagedir_nosave, pagedir_order); - spin_unlock_irq(&suspend_pagedir_lock); - mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME); + return -EFAULT; } /* More restore stuff */ /* FIXME: Why not memcpy(to, from, 1<version_code != LINUX_VERSION_CODE) return sanity_check_failed("Incorrect kernel version"); @@ -776,7 +701,8 @@ static int sanity_check(struct suspend_header *sh) return 0; } -static int bdev_read_page(struct block_device *bdev, long pos, void *buf) +static int __init bdev_read_page(struct block_device *bdev, + long pos, void *buf) { struct buffer_head *bh; BUG_ON (pos%PAGE_SIZE); @@ -792,7 +718,8 @@ static int bdev_read_page(struct block_device *bdev, long pos, void *buf) extern dev_t __init name_to_dev_t(const char *line); -static int __read_suspend_image(struct block_device *bdev, union diskpage *cur) +static int __init read_suspend_image(struct block_device *bdev, + union diskpage *cur) { swp_entry_t next; int i, nr_pgdir_pages; @@ -869,54 +796,6 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur) return 0; } -static int read_suspend_image(const char * specialfile) -{ - union diskpage *cur; - unsigned long scratch_page = 0; - int error; - char b[BDEVNAME_SIZE]; - - resume_device = name_to_dev_t(specialfile); - scratch_page = get_zeroed_page(GFP_ATOMIC); - cur = (void *) scratch_page; - if (cur) { - struct block_device *bdev; - printk("Resuming from device %s\n", - __bdevname(resume_device, b)); - bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW); - if (IS_ERR(bdev)) { - error = PTR_ERR(bdev); - } else { - set_blocksize(bdev, PAGE_SIZE); - error = __read_suspend_image(bdev, cur); - blkdev_put(bdev, BDEV_RAW); - } - } else error = -ENOMEM; - - if (scratch_page) - free_page(scratch_page); - switch (error) { - case 0: - PRINTK("Reading resume file was successful\n"); - break; - case -EINVAL: - break; - case -EIO: - printk( "%sI/O error\n", name_resume); - break; - case -ENOENT: - printk( "%s%s: No such file or directory\n", name_resume, specialfile); - break; - case -ENOMEM: - printk( "%sNot enough memory\n", name_resume); - break; - default: - printk( "%sError %d resuming\n", name_resume, error ); - } - MDELAY(1000); - return error; -} - /** * swsusp_save - Snapshot memory */ @@ -944,9 +823,7 @@ int swsusp_save(void) int swsusp_write(void) { arch_prepare_suspend(); - do_magic(0); - MDELAY(1000); - return 0; + return do_magic(0); } @@ -954,13 +831,39 @@ int swsusp_write(void) * swsusp_read - Read saved image from swap. */ -int swsusp_read(void) +int __init swsusp_read(void) { + union diskpage *cur; + int error; + char b[BDEVNAME_SIZE]; + if (!strlen(resume_file)) return -ENOENT; - printk("swsusp: %s\n", name_resume ); + + resume_device = name_to_dev_t(resume_file); + printk("swsusp: Resume From Partition: %s, Device: %s\n", + resume_file, __bdevname(resume_device, b)); + + cur = (union diskpage *)get_zeroed_page(GFP_ATOMIC); + if (cur) { + struct block_device *bdev; + bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW); + if (!IS_ERR(bdev)) { + set_blocksize(bdev, PAGE_SIZE); + error = read_suspend_image(bdev, cur); + blkdev_put(bdev, BDEV_RAW); + } else + error = PTR_ERR(bdev); + free_page((unsigned long)cur); + } else + error = -ENOMEM; + + if (!error) + PRINTK("Reading resume file was successful\n"); + else + printk( "%sError %d resuming\n", name_resume, error ); MDELAY(1000); - return read_suspend_image(resume_file); + return error; } @@ -968,10 +871,9 @@ int swsusp_read(void) * swsusp_restore - Replace running kernel with saved image. */ -int swsusp_restore(void) +int __init swsusp_restore(void) { - do_magic(1); - return 0; + return do_magic(1); } @@ -981,6 +883,12 @@ int swsusp_restore(void) int swsusp_free(void) { + PRINTK( "Freeing prev allocated pagedir\n" ); + free_suspend_pagedir((unsigned long) pagedir_save); + + PRINTK( "Fixing swap signatures... " ); + mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME); + PRINTK( "ok\n" ); return 0; }