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)
}
extern long sys_sync(void);
extern void pm_prepare_console(void);
extern void pm_restore_console(void);
static int __pmac
pmac_suspend_devices(void)
......
......@@ -42,30 +42,42 @@ 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 */
......
......@@ -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_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, 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;
......
......@@ -475,13 +475,11 @@ 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) {
{
int ret = software_suspend();
unlock_kernel();
return -EAGAIN;
return ret;
}
software_suspend();
do_exit(0);
break;
#endif
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