]> git.hungrycats.org Git - linux/commitdiff
[power] Adapt swsusp to new PM core. Clean up heavily.
authorPatrick Mochel <mochel@osdl.org>
Tue, 19 Aug 2003 14:53:13 +0000 (07:53 -0700)
committerPatrick Mochel <mochel@osdl.org>
Tue, 19 Aug 2003 14:53:13 +0000 (07:53 -0700)
- Split suspend/resume code into the four functions called from the PM core.
- Remove now-duplicated code.
- Make sure PM core frees memory and sync's disks before we shut down devices.
- Remove software_suspend(), in favor of pm_suspend().
- Remove unused definitions from suspend.h

include/linux/suspend.h
kernel/power/main.c
kernel/power/power.h
kernel/power/swsusp.c
kernel/sys.c

index 28788d8a65ff0b58204875a831e5de76c5732489..da171766c8c8128ed3b06ca86aed90d9d89e4658 100644 (file)
@@ -8,8 +8,7 @@
 #include <linux/notifier.h>
 #include <linux/config.h>
 #include <linux/init.h>
-
-extern unsigned char software_suspend_enabled;
+#include <linux/pm.h>
 
 #ifdef CONFIG_SOFTWARE_SUSPEND
 /* page backup entry */
@@ -46,12 +45,6 @@ extern int shrink_mem(void);
 /* mm/page_alloc.c */
 extern void drain_local_pages(void);
 
-/* kernel/suspend.c */
-extern int software_suspend(void);
-
-extern int register_suspend_notifier(struct notifier_block *);
-extern int unregister_suspend_notifier(struct notifier_block *);
-
 extern unsigned int nr_copy_pages __nosavedata;
 extern suspend_pagedir_t *pagedir_nosave __nosavedata;
 
@@ -72,31 +65,16 @@ static inline int software_suspend(void)
 {
        return -EPERM;
 }
-#define register_suspend_notifier(a)   do { } while(0)
-#define unregister_suspend_notifier(a) do { } while(0)
 #endif /* CONFIG_SOFTWARE_SUSPEND */
 
 
 #ifdef CONFIG_PM
 extern void refrigerator(unsigned long);
-extern int freeze_processes(void);
-extern void thaw_processes(void);
-
-extern int pm_prepare_console(void);
-extern void pm_restore_console(void);
 
 #else
 static inline void refrigerator(unsigned long flag)
 {
 
-}
-static inline int freeze_processes(void)
-{
-       return 0;
-}
-static inline void thaw_processes(void)
-{
-
 }
 #endif /* CONFIG_PM */
 
index 063e98c6bceb2006f90a2263c870212c7f282d82..42bf7233a3a7a7641a48f68895b026c1f8b8aa14 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pm.h>
+#include <linux/fs.h>
+
 
 #include "power.h"
 
@@ -30,6 +32,8 @@ static int have_swsusp = 1;
 static int have_swsusp = 0;
 #endif
 
+extern long sys_sync(void);
+
 
 /**
  *     pm_set_ops - Set the global power method table. 
@@ -128,6 +132,25 @@ static int power_down(u32 mode)
 static int in_suspend __nosavedata = 0;
 
 
+/**
+ *     free_some_memory -  Try to free as much memory as possible
+ *
+ *     ... but do not OOM-kill anyone
+ *
+ *     Notice: all userland should be stopped at this point, or 
+ *     livelock is possible.
+ */
+
+static void free_some_memory(void)
+{
+       printk("Freeing memory: ");
+       while (shrink_all_memory(10000))
+               printk(".");
+       printk("|\n");
+       blk_run_queues();
+}
+
+
 /**
  *     pm_suspend_disk - The granpappy of power management.
  *     
@@ -197,6 +220,7 @@ static int suspend_prepare(u32 state)
 
        pm_prepare_console();
 
+       sys_sync();
        if (freeze_processes()) {
                error = -EAGAIN;
                goto Thaw;
@@ -207,6 +231,10 @@ static int suspend_prepare(u32 state)
                        goto Thaw;
        }
 
+       /* Free memory before shutting down devices. */
+       if (state == PM_SUSPEND_DISK)
+               free_some_memory();
+
        if ((error = device_pm_suspend(state)))
                goto Finish;
 
index ae7bcbc37845970c97bf91a463069f78cb4a5453..e98de640155d91088e950dc94c82e11230473ee2 100644 (file)
@@ -37,3 +37,10 @@ static inline int swsusp_free(void)
        return 0;
 }
 #endif
+
+
+extern int freeze_processes(void);
+extern void thaw_processes(void);
+
+extern int pm_prepare_console(void);
+extern void pm_restore_console(void);
index d1b2a46de5fa0aeb3b24441a5379c8b53415a8dd..5c70937437d4daad1c447972a2b34a8a318373c0 100644 (file)
@@ -65,8 +65,6 @@
 
 #include "power.h"
 
-extern long sys_sync(void);
-
 unsigned char software_suspend_enabled = 1;
 
 #define __ADDRESS(x)  ((unsigned long) phys_to_virt(x))
@@ -439,29 +437,6 @@ static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
        return pagedir;
 }
 
-static int prepare_suspend_processes(void)
-{
-       sys_sync();     /* Syncing needs pdflushd, so do it before stopping processes */
-       if (freeze_processes()) {
-               printk( KERN_ERR "Suspend failed: Not all processes stopped!\n" );
-               thaw_processes();
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * Try to free as much memory as possible, but do not OOM-kill anyone
- *
- * Notice: all userland should be stopped at this point, or livelock is possible.
- */
-static void free_some_memory(void)
-{
-       printk("Freeing memory: ");
-       while (shrink_all_memory(10000))
-               printk(".");
-       printk("|\n");
-}
 
 /* Make disk drivers accept operations, again */
 static void drivers_unsuspend(void)
@@ -470,28 +445,6 @@ static void drivers_unsuspend(void)
        device_resume(RESUME_ENABLE);
 }
 
-/* Called from process context */
-static int drivers_suspend(void)
-{
-       if (device_suspend(4, SUSPEND_NOTIFY))
-               return -EIO;
-       if (device_suspend(4, SUSPEND_SAVE_STATE)) {
-               device_resume(RESUME_RESTORE_STATE);
-               return -EIO;
-       }
-       if (!pm_suspend_state) {
-               if(pm_send_all(PM_SUSPEND,(void *)3)) {
-                       printk(KERN_WARNING "Problem while sending suspend event\n");
-                       return -EIO;
-               }
-               pm_suspend_state=1;
-       } else
-               printk(KERN_WARNING "PM suspend state already raised\n");
-       device_suspend(4, SUSPEND_DISABLE);
-         
-       return 0;
-}
-
 #define RESUME_PHASE1 1 /* Called from interrupts disabled */
 #define RESUME_PHASE2 2 /* Called with interrupts enabled */
 #define RESUME_ALL_PHASES (RESUME_PHASE1 | RESUME_PHASE2)
@@ -694,72 +647,6 @@ void do_magic_suspend_2(void)
        mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
 }
 
-static int do_software_suspend(void)
-{
-       arch_prepare_suspend();
-       if (pm_prepare_console())
-               printk( "%sCan't allocate a console... proceeding\n", name_suspend);
-       if (!prepare_suspend_processes()) {
-
-               /* At this point, all user processes and "dangerous"
-                   kernel threads are stopped. Free some memory, as we
-                   need half of memory free. */
-
-               free_some_memory();
-               
-               /* No need to invalidate any vfsmnt list -- 
-                * they will be valid after resume, anyway.
-                */
-               blk_run_queues();
-
-               /* Save state of all device drivers, and stop them. */             
-               if (drivers_suspend()==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);
-               thaw_processes();
-       }
-       software_suspend_enabled = 1;
-       MDELAY(1000);
-       pm_restore_console();
-       return 0;
-}
-
-
-/**
- *     software_suspend - initiate suspend-to-swap transition.
- *
- *     This is main interface to the outside world. It needs to be
- *     called from process context.
- */
-
-int software_suspend(void)
-{
-       if(!software_suspend_enabled)
-               return -EINVAL;
-
-       if (num_online_cpus() > 1) {
-               printk(KERN_WARNING "swsusp does not support SMP.\n");  
-               return -EPERM;
-       }
-
-#if defined (CONFIG_HIGHMEM) || defined (COFNIG_DISCONTIGMEM)
-       printk("swsusp is not supported with high- or discontig-mem.\n");
-       return -EPERM;
-#endif
-
-       software_suspend_enabled = 0;
-       might_sleep();
-       return do_software_suspend();
-}
-
 /* More restore stuff */
 
 /* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */
@@ -1030,55 +917,35 @@ static int read_suspend_image(const char * specialfile)
        return error;
 }
 
-/**
- *     software_resume - Check and load saved image from swap.
- *
- *     Defined as a late_initcall, so it gets called after all devices
- *     have been probed and initialized, but before we've mounted anything.
- */
-
-static int software_resume(void)
-{
-       if (!strlen(resume_file))
-               return 0;
-
-       if (pm_prepare_console())
-               printk("swsusp: Can't allocate a console... proceeding\n");
-
-       printk("swsusp: %s\n", name_resume );
-
-       MDELAY(1000);
-
-       printk("swsusp: resuming from %s\n", resume_file);
-       if (read_suspend_image(resume_file))
-               goto read_failure;
-       do_magic(1);
-       printk("swsusp: Resume failed. Continuing.\n");
-
-read_failure:
-       pm_restore_console();
-       return -EFAULT;
-}
-
-late_initcall(software_resume);
-
-
 /**
  *     swsusp_save - Snapshot memory
  */
 
 int swsusp_save(void) 
 {
+#if defined (CONFIG_HIGHMEM) || defined (COFNIG_DISCONTIGMEM)
+       printk("swsusp is not supported with high- or discontig-mem.\n");
        return -EPERM;
+#endif
+       return 0;
 }
 
 
 /**
  *     swsusp_write - Write saved memory image to swap.
+ *
+ *     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.
  */
 
 int swsusp_write(void)
 {
+       arch_prepare_suspend();
+       do_magic(0);
+       MDELAY(1000);
        return 0;
 }
 
@@ -1089,7 +956,11 @@ int swsusp_write(void)
 
 int swsusp_read(void)
 {
-       return -ENOENT;
+       if (!strlen(resume_file))
+               return -ENOENT;
+       printk("swsusp: %s\n", name_resume );
+       MDELAY(1000);
+       return read_suspend_image(resume_file);
 }
 
 
@@ -1099,6 +970,7 @@ int swsusp_read(void)
 
 int swsusp_restore(void)
 {
+       do_magic(1);
        return 0;
 }
 
@@ -1114,7 +986,8 @@ int swsusp_free(void)
 
 static int __init resume_setup(char *str)
 {
-       strncpy( resume_file, str, 255 );
+       if (strlen(str))
+               strncpy(resume_file, str, 255);
        return 1;
 }
 
@@ -1127,5 +1000,3 @@ static int __init noresume_setup(char *str)
 __setup("noresume", noresume_setup);
 __setup("resume=", resume_setup);
 
-EXPORT_SYMBOL(software_suspend);
-EXPORT_SYMBOL(software_suspend_enabled);
index 3497a1565a618c93a40ce682659a25c1a1043bff..27c19703a1ea75241338a2b90af933081ea21413 100644 (file)
@@ -456,11 +456,8 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
 
 #ifdef CONFIG_SOFTWARE_SUSPEND
        case LINUX_REBOOT_CMD_SW_SUSPEND:
-               if (!software_suspend_enabled) {
-                       unlock_kernel();
-                       return -EAGAIN;
-               }               
-               software_suspend();
+               if (!pm_suspend(PM_SUSPEND_DISK))
+                       break;
                do_exit(0);
                break;
 #endif