lkml.org 
[lkml]   [2004]   [Jul]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[9/25] Merge pmdisk and swsusp

    ChangeSet 1.1851, 2004/07/17 11:11:04-07:00, mochel@digitalimplant.org

    [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.


    arch/i386/power/Makefile | 1
    arch/i386/power/swsusp.S | 78 ++++++++----------------------
    include/linux/suspend.h | 6 --
    kernel/power/disk.c | 8 +--
    kernel/power/pmdisk.c | 89 ----------------------------------
    kernel/power/swsusp.c | 121 +++++++++++++++++++----------------------------
    6 files changed, 74 insertions(+), 229 deletions(-)


    diff -Nru a/arch/i386/power/Makefile b/arch/i386/power/Makefile
    --- a/arch/i386/power/Makefile 2004-07-17 14:51:25 -07:00
    +++ b/arch/i386/power/Makefile 2004-07-17 14:51:25 -07:00
    @@ -1,3 +1,2 @@
    obj-$(CONFIG_PM) += cpu.o
    -obj-$(CONFIG_PM_DISK) += pmdisk.o
    obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
    diff -Nru a/arch/i386/power/swsusp.S b/arch/i386/power/swsusp.S
    --- a/arch/i386/power/swsusp.S 2004-07-17 14:51:25 -07:00
    +++ b/arch/i386/power/swsusp.S 2004-07-17 14:51:25 -07:00
    @@ -15,83 +15,47 @@

    .text

    -ENTRY(do_magic)
    - pushl %ebx
    - cmpl $0,8(%esp)
    - jne resume
    - call do_magic_suspend_1
    - call save_processor_state
    +ENTRY(swsusp_arch_suspend)

    movl %esp, saved_context_esp
    - movl %eax, saved_context_eax
    movl %ebx, saved_context_ebx
    - movl %ecx, saved_context_ecx
    - movl %edx, saved_context_edx
    movl %ebp, saved_context_ebp
    movl %esi, saved_context_esi
    movl %edi, saved_context_edi
    pushfl ; popl saved_context_eflags

    - call do_magic_suspend_2
    - popl %ebx
    + call swsusp_save
    ret

    -resume:
    +ENTRY(swsusp_arch_resume)
    movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx
    movl %ecx,%cr3

    - call do_magic_resume_1
    - movl $0,loop
    - cmpl $0,nr_copy_pages
    - je copy_done
    -copy_loop:
    - movl $0,loop2
    + movl pagedir_nosave,%ebx
    + xorl %eax, %eax
    + xorl %edx, %edx
    .p2align 4,,7
    -copy_one_page:
    - movl pagedir_nosave,%ecx
    - movl loop,%eax
    - movl loop2,%edx
    - sall $4,%eax
    - movl 4(%ecx,%eax),%ebx
    - movl (%ecx,%eax),%eax
    - movb (%edx,%eax),%al
    - movb %al,(%edx,%ebx)
    -
    - movl loop2,%eax
    - leal 1(%eax),%edx
    - movl %edx,loop2
    - movl %edx,%eax
    - cmpl $4095,%eax
    - jbe copy_one_page
    - movl loop,%eax
    - leal 1(%eax),%edx
    - movl %edx,loop
    - movl %edx,%eax
    - cmpl nr_copy_pages,%eax
    - jb copy_loop

    -copy_done:
    - movl $__USER_DS,%eax
    +copy_loop:
    + movl 4(%ebx,%edx),%edi
    + movl (%ebx,%edx),%esi
    +
    + movl $1024, %ecx
    + rep
    + movsl
    +
    + incl %eax
    + addl $16, %edx
    + cmpl nr_copy_pages,%eax
    + jb copy_loop
    + .p2align 4,,7

    - movw %ax, %ds
    - movw %ax, %es
    movl saved_context_esp, %esp
    movl saved_context_ebp, %ebp
    - movl saved_context_eax, %eax
    movl saved_context_ebx, %ebx
    - movl saved_context_ecx, %ecx
    - movl saved_context_edx, %edx
    movl saved_context_esi, %esi
    movl saved_context_edi, %edi
    - call restore_processor_state
    +
    pushl saved_context_eflags ; popfl
    - call do_magic_resume_2
    - popl %ebx
    + call swsusp_restore
    ret
    -
    - .section .data.nosave
    -loop:
    - .quad 0
    -loop2:
    - .quad 0
    - .previous
    diff -Nru a/include/linux/suspend.h b/include/linux/suspend.h
    --- a/include/linux/suspend.h 2004-07-17 14:51:25 -07:00
    +++ b/include/linux/suspend.h 2004-07-17 14:51:25 -07:00
    @@ -75,12 +75,6 @@
    static inline void enable_nonboot_cpus(void) {}
    #endif

    -asmlinkage void do_magic(int is_resume);
    -asmlinkage void do_magic_resume_1(void);
    -asmlinkage void do_magic_resume_2(void);
    -asmlinkage void do_magic_suspend_1(void);
    -asmlinkage void do_magic_suspend_2(void);
    -
    void save_processor_state(void);
    void restore_processor_state(void);
    struct saved_context;
    diff -Nru a/kernel/power/disk.c b/kernel/power/disk.c
    --- a/kernel/power/disk.c 2004-07-17 14:51:25 -07:00
    +++ b/kernel/power/disk.c 2004-07-17 14:51:25 -07:00
    @@ -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 @@

    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 @@
    mdelay(1000);

    pr_debug("PM: Restoring saved image.\n");
    - pmdisk_restore();
    + swsusp_resume();
    pr_debug("PM: Restore failed, recovering.n");
    finish();
    Free:
    diff -Nru a/kernel/power/pmdisk.c b/kernel/power/pmdisk.c
    --- a/kernel/power/pmdisk.c 2004-07-17 14:51:25 -07:00
    +++ b/kernel/power/pmdisk.c 2004-07-17 14:51:25 -07:00
    @@ -249,28 +249,7 @@


    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 @@
    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 @@
    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.
    @@ -628,22 +555,6 @@
    pr_debug("Reading resume file was successful\n");
    else
    pr_debug("pmdisk: Error %d resuming\n", error);
    - return error;
    -}
    -
    -
    -/**
    - * 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;
    }

    diff -Nru a/kernel/power/swsusp.c b/kernel/power/swsusp.c
    --- a/kernel/power/swsusp.c 2004-07-17 14:51:25 -07:00
    +++ b/kernel/power/swsusp.c 2004-07-17 14:51:25 -07:00
    @@ -893,80 +893,58 @@
    #endif
    }

    -/*
    - * Magic happens here
    - */

    -asmlinkage void do_magic_resume_1(void)
    +extern asmlinkage int swsusp_arch_suspend(void);
    +extern asmlinkage int swsusp_arch_resume(void);
    +
    +
    +asmlinkage int swsusp_save(void)
    {
    - barrier();
    - mb();
    - spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */
    + int error = 0;

    - 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 ;-). */
    + if ((error = swsusp_swap_check()))
    + return error;
    + return suspend_prepare_image();
    }

    -asmlinkage void do_magic_resume_2(void)
    +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();
    + local_irq_enable();
    + return error;
    +}
    +
    +
    +asmlinkage int swsusp_restore(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;
    +}

    - __flush_tlb_global(); /* Even mappings of "global" things (vmalloc) need to be fixed */
    - device_power_up();
    - spin_unlock_irq(&suspend_pagedir_lock);
    -}
    -
    -/* 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_resume(void)
    +{
    + int error;
    + local_irq_disable();
    + save_processor_state();
    + error = swsusp_arch_resume();
    restore_processor_state();
    - do_magic_resume_2();
    -
    - */
    + local_irq_enable();
    + return error;
    +}

    -asmlinkage void do_magic_suspend_1(void)
    -{
    - mb();
    - barrier();
    - BUG_ON(in_atomic());
    - spin_lock_irq(&suspend_pagedir_lock);
    -}
    -
    -asmlinkage void do_magic_suspend_2(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 ?! */
    - }

    - 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 @@
    /* 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 @@
    /* 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:
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-03-22 14:04    [W:0.041 / U:118.000 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site