Commit 0c2d1195 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Allow software_suspend to fail

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.
parent 9db89cf7
...@@ -2288,8 +2288,6 @@ restore_via_state(void) ...@@ -2288,8 +2288,6 @@ restore_via_state(void)
} }
extern long sys_sync(void); extern long sys_sync(void);
extern void pm_prepare_console(void);
extern void pm_restore_console(void);
static int __pmac static int __pmac
pmac_suspend_devices(void) pmac_suspend_devices(void)
......
...@@ -42,30 +42,42 @@ extern int shrink_mem(void); ...@@ -42,30 +42,42 @@ extern int shrink_mem(void);
/* mm/page_alloc.c */ /* mm/page_alloc.c */
extern void drain_local_pages(void); extern void drain_local_pages(void);
/* kernel/power/swsusp.c */
extern int software_suspend(void);
extern unsigned int nr_copy_pages __nosavedata; extern unsigned int nr_copy_pages __nosavedata;
extern suspend_pagedir_t *pagedir_nosave __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 */ #else /* CONFIG_SOFTWARE_SUSPEND */
static inline void software_suspend(void) static inline int software_suspend(void)
{ {
printk("Warning: fake suspend called\n"); printk("Warning: fake suspend called\n");
return -EPERM;
} }
#define software_resume() do { } while(0)
#endif /* CONFIG_SOFTWARE_SUSPEND */ #endif /* CONFIG_SOFTWARE_SUSPEND */
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern void refrigerator(unsigned long); 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 #else
static inline void refrigerator(unsigned long flag) 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 /* CONFIG_PM */
......
...@@ -677,11 +677,22 @@ void do_magic_suspend_2(void) ...@@ -677,11 +677,22 @@ void do_magic_suspend_2(void)
mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME); 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()) { if (arch_prepare_suspend()) {
printk("%sArchitecture failed to prepare\n", name_suspend); printk("%sArchitecture failed to prepare\n", name_suspend);
return; return -EPERM;
} }
if (pm_prepare_console()) if (pm_prepare_console())
printk( "%sCan't allocate a console... proceeding\n", name_suspend); printk( "%sCan't allocate a console... proceeding\n", name_suspend);
...@@ -711,24 +722,12 @@ static void do_software_suspend(void) ...@@ -711,24 +722,12 @@ static void do_software_suspend(void)
*/ */
do_magic(0); do_magic(0);
thaw_processes(); thaw_processes();
} } else
res = -EBUSY;
software_suspend_enabled = 1; software_suspend_enabled = 1;
MDELAY(1000); MDELAY(1000);
pm_restore_console(); pm_restore_console();
} return res;
/*
* 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();
} }
/* More restore stuff */ /* More restore stuff */
...@@ -898,7 +897,7 @@ static int bdev_write_page(struct block_device *bdev, long pos, void *buf) ...@@ -898,7 +897,7 @@ static int bdev_write_page(struct block_device *bdev, long pos, void *buf)
extern dev_t __init name_to_dev_t(const char *line); 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; swp_entry_t next;
int i, nr_pgdir_pages; int i, nr_pgdir_pages;
......
...@@ -475,13 +475,11 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user ...@@ -475,13 +475,11 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
#ifdef CONFIG_SOFTWARE_SUSPEND #ifdef CONFIG_SOFTWARE_SUSPEND
case LINUX_REBOOT_CMD_SW_SUSPEND: case LINUX_REBOOT_CMD_SW_SUSPEND:
if (!software_suspend_enabled) { {
int ret = software_suspend();
unlock_kernel(); unlock_kernel();
return -EAGAIN; return ret;
} }
software_suspend();
do_exit(0);
break;
#endif #endif
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment