From: Pavel Machek <pavel@ucw.cz>

software_suspend() can fail for quite a lot of reasons (for example not
enough swapspace).  However current interface returned void, so you could
not propagate error back to userland.  This fixes it.  Plus
__read_suspend_image() is only done during init time, so we might as well
mark it __init.



---

 include/linux/suspend.h |   26 +++++++++++++++++++-------
 kernel/power/swsusp.c   |   35 +++++++++++++++++------------------
 kernel/sys.c            |    8 +++-----
 3 files changed, 39 insertions(+), 30 deletions(-)

diff -puN include/linux/suspend.h~swsusp-software_suspend-retval-fix include/linux/suspend.h
--- 25/include/linux/suspend.h~swsusp-software_suspend-retval-fix	2004-01-20 21:32:38.000000000 -0800
+++ 25-akpm/include/linux/suspend.h	2004-01-20 21:32:38.000000000 -0800
@@ -42,31 +42,43 @@ extern int shrink_mem(void);
 /* mm/page_alloc.c */
 extern void drain_local_pages(void);
 
+/* kernel/power/swsusp.c */
+extern int software_suspend(void);
+
 extern unsigned int nr_copy_pages __nosavedata;
 extern suspend_pagedir_t *pagedir_nosave __nosavedata;
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_SOFTWARE_SUSPEND
-
-extern unsigned char software_suspend_enabled;
 
-extern void software_suspend(void);
 #else	/* CONFIG_SOFTWARE_SUSPEND */
-static inline void software_suspend(void)
+static inline int software_suspend(void)
 {
 	printk("Warning: fake suspend called\n");
+	return -EPERM;
 }
+#define software_resume()		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 */
 
 #endif /* _LINUX_SWSUSP_H */
diff -puN kernel/power/swsusp.c~swsusp-software_suspend-retval-fix kernel/power/swsusp.c
--- 25/kernel/power/swsusp.c~swsusp-software_suspend-retval-fix	2004-01-20 21:32:38.000000000 -0800
+++ 25-akpm/kernel/power/swsusp.c	2004-01-20 21:32:38.000000000 -0800
@@ -677,11 +677,22 @@ void do_magic_suspend_2(void)
 	mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
 }
 
-static void do_software_suspend(void)
+/*
+ * This is main interface to the outside world. It needs to be
+ * called from process context.
+ */
+int software_suspend(void)
 {
+	int res;
+	if (!software_suspend_enabled)
+		return -EAGAIN;
+
+	software_suspend_enabled = 0;
+	might_sleep();
+
 	if (arch_prepare_suspend()) {
 		printk("%sArchitecture failed to prepare\n", name_suspend);
-		return;
+		return -EPERM;
 	}		
 	if (pm_prepare_console())
 		printk( "%sCan't allocate a console... proceeding\n", name_suspend);
@@ -711,24 +722,12 @@ static void do_software_suspend(void)
 			 */
 			do_magic(0);
 		thaw_processes();
-	}
+	} else
+		res = -EBUSY;
 	software_suspend_enabled = 1;
 	MDELAY(1000);
 	pm_restore_console();
-}
-
-/*
- * This is main interface to the outside world. It needs to be
- * called from process context.
- */
-void software_suspend(void)
-{
-	if(!software_suspend_enabled)
-		return;
-
-	software_suspend_enabled = 0;
-	might_sleep();
-	do_software_suspend();
+	return res;
 }
 
 /* More restore stuff */
@@ -898,7 +897,7 @@ static int bdev_write_page(struct block_
 
 extern dev_t __init name_to_dev_t(const char *line);
 
-static int __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume)
+static int __init __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume)
 {
 	swp_entry_t next;
 	int i, nr_pgdir_pages;
diff -puN kernel/sys.c~swsusp-software_suspend-retval-fix kernel/sys.c
--- 25/kernel/sys.c~swsusp-software_suspend-retval-fix	2004-01-20 21:32:38.000000000 -0800
+++ 25-akpm/kernel/sys.c	2004-01-20 21:32:38.000000000 -0800
@@ -475,13 +475,11 @@ asmlinkage long sys_reboot(int magic1, i
 
 #ifdef CONFIG_SOFTWARE_SUSPEND
 	case LINUX_REBOOT_CMD_SW_SUSPEND:
-		if (!software_suspend_enabled) {
+		{
+			int ret = software_suspend();
 			unlock_kernel();
-			return -EAGAIN;
+			return ret;
 		}
-		software_suspend();
-		do_exit(0);
-		break;
 #endif
 
 	default:

_