Commit f2df1a5f authored by Patrick Mochel's avatar Patrick Mochel

[power] Various swsusp cleanups.

- Move SMP check to software_suspend() (from software_resume()), so we will
  not even attempt to sleep with it enabled.
- Make software_resume() a late initcall, removing the explicit call from
  prepare_namespace(). 
- Initialize software_suspend_enabled to 1, instead of doing it manually in
  software_resume().
- Don't explicitly initialzie resume_file.
- Remove resume_status variable, as we can simply check for (non-) NULL 
  resume_file string. 
- "noresume" setup function changed to simply zero first byte of resume_file
  string, simplifying logic.
- Don't attempt to reset swap signature if noresume is specified.
  - Downstream function (bdev_write_page() wasn't implemented anyway, so we
    can just remove that also).

If noresume is specified, there will still be a suspend image left on the 
swap partition. It may behoove us to never reset the swap signature, and 
always leave the image intact on the disk, since it is a valid snapshot 
that we can resume from at anytime. 

This unconditional behavior would force the user to add 'mkswap <part>' to
their init scripts to reset the partition to swap use. IMO, this is better
anyway.
parent 05f11b37
...@@ -11,9 +11,6 @@ ...@@ -11,9 +11,6 @@
extern unsigned char software_suspend_enabled; extern unsigned char software_suspend_enabled;
#define NORESUME 1
#define RESUME_SPECIFIED 2
#ifdef CONFIG_SOFTWARE_SUSPEND #ifdef CONFIG_SOFTWARE_SUSPEND
/* page backup entry */ /* page backup entry */
typedef struct pbe { typedef struct pbe {
...@@ -51,7 +48,6 @@ extern void drain_local_pages(void); ...@@ -51,7 +48,6 @@ extern void drain_local_pages(void);
/* kernel/suspend.c */ /* kernel/suspend.c */
extern int software_suspend(void); extern int software_suspend(void);
extern void software_resume(void);
extern int register_suspend_notifier(struct notifier_block *); extern int register_suspend_notifier(struct notifier_block *);
extern int unregister_suspend_notifier(struct notifier_block *); extern int unregister_suspend_notifier(struct notifier_block *);
...@@ -76,7 +72,6 @@ static inline int software_suspend(void) ...@@ -76,7 +72,6 @@ static inline int software_suspend(void)
{ {
return -EPERM; return -EPERM;
} }
#define software_resume() do { } while(0)
#define register_suspend_notifier(a) do { } while(0) #define register_suspend_notifier(a) do { } while(0)
#define unregister_suspend_notifier(a) do { } while(0) #define unregister_suspend_notifier(a) do { } while(0)
#endif /* CONFIG_SOFTWARE_SUSPEND */ #endif /* CONFIG_SOFTWARE_SUSPEND */
......
...@@ -370,10 +370,6 @@ void __init prepare_namespace(void) ...@@ -370,10 +370,6 @@ void __init prepare_namespace(void)
is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
/* This has to be before mounting root, because even readonly mount of reiserfs would replay
log corrupting stuff */
software_resume();
if (initrd_load()) if (initrd_load())
goto out; goto out;
......
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
extern long sys_sync(void); extern long sys_sync(void);
unsigned char software_suspend_enabled = 0; unsigned char software_suspend_enabled = 1;
#define __ADDRESS(x) ((unsigned long) phys_to_virt(x)) #define __ADDRESS(x) ((unsigned long) phys_to_virt(x))
#define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT) #define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT)
...@@ -85,8 +85,7 @@ spinlock_t suspend_pagedir_lock __nosavedata = SPIN_LOCK_UNLOCKED; ...@@ -85,8 +85,7 @@ spinlock_t suspend_pagedir_lock __nosavedata = SPIN_LOCK_UNLOCKED;
static int pagedir_order_check; static int pagedir_order_check;
static int nr_copy_pages_check; static int nr_copy_pages_check;
static int resume_status; static char resume_file[256]; /* For resume= kernel option */
static char resume_file[256] = ""; /* For resume= kernel option */
static dev_t resume_device; static dev_t resume_device;
/* Local variables that should not be affected by save */ /* Local variables that should not be affected by save */
unsigned int nr_copy_pages __nosavedata = 0; unsigned int nr_copy_pages __nosavedata = 0;
...@@ -746,6 +745,11 @@ int software_suspend(void) ...@@ -746,6 +745,11 @@ int software_suspend(void)
if(!software_suspend_enabled) if(!software_suspend_enabled)
return -EINVAL; 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) #if defined (CONFIG_HIGHMEM) || defined (COFNIG_DISCONTIGMEM)
printk("swsusp is not supported with high- or discontig-mem.\n"); printk("swsusp is not supported with high- or discontig-mem.\n");
return -EPERM; return -EPERM;
...@@ -899,31 +903,9 @@ static int bdev_read_page(struct block_device *bdev, long pos, void *buf) ...@@ -899,31 +903,9 @@ static int bdev_read_page(struct block_device *bdev, long pos, void *buf)
return 0; return 0;
} }
static int bdev_write_page(struct block_device *bdev, long pos, void *buf)
{
#if 0
struct buffer_head *bh;
BUG_ON (pos%PAGE_SIZE);
bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
if (!bh || (!bh->b_data)) {
return -1;
}
memcpy(bh->b_data, buf, PAGE_SIZE); /* FIXME: may need kmap() */
BUG_ON(!buffer_uptodate(bh));
generic_make_request(WRITE, bh);
if (!buffer_uptodate(bh))
printk(KERN_CRIT "%sWarning %s: Fixing swap signatures unsuccessful...\n", name_resume, resume_file);
wait_on_buffer(bh);
brelse(bh);
return 0;
#endif
printk(KERN_CRIT "%sWarning %s: Fixing swap signatures unimplemented...\n", name_resume, resume_file);
return 0;
}
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 __read_suspend_image(struct block_device *bdev, union diskpage *cur)
{ {
swp_entry_t next; swp_entry_t next;
int i, nr_pgdir_pages; int i, nr_pgdir_pages;
...@@ -948,18 +930,9 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur, ...@@ -948,18 +930,9 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur,
else if (!memcmp("S2",cur->swh.magic.magic,2)) else if (!memcmp("S2",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAPSPACE2",10); memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
else { else {
if (noresume) printk("swsusp: %s: Unable to find suspended-data signature (%.10s - misspelled?\n",
return -EINVAL;
panic("%sUnable to find suspended-data signature (%.10s - misspelled?\n",
name_resume, cur->swh.magic.magic); name_resume, cur->swh.magic.magic);
} return -EFAULT;
if (noresume) {
/* We don't do a sanity check here: we want to restore the swap
whatever version of kernel made the suspend image;
We need to write swap, but swap is *not* enabled so
we must write the device directly */
printk("%s: Fixing swap signatures %s...\n", name_resume, resume_file);
bdev_write_page(bdev, 0, cur);
} }
printk( "%sSignature found, resuming\n", name_resume ); printk( "%sSignature found, resuming\n", name_resume );
...@@ -1009,7 +982,7 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur, ...@@ -1009,7 +982,7 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur,
return 0; return 0;
} }
static int read_suspend_image(const char * specialfile, int noresume) static int read_suspend_image(const char * specialfile)
{ {
union diskpage *cur; union diskpage *cur;
unsigned long scratch_page = 0; unsigned long scratch_page = 0;
...@@ -1028,7 +1001,7 @@ static int read_suspend_image(const char * specialfile, int noresume) ...@@ -1028,7 +1001,7 @@ static int read_suspend_image(const char * specialfile, int noresume)
error = PTR_ERR(bdev); error = PTR_ERR(bdev);
} else { } else {
set_blocksize(bdev, PAGE_SIZE); set_blocksize(bdev, PAGE_SIZE);
error = __read_suspend_image(bdev, cur, noresume); error = __read_suspend_image(bdev, cur);
blkdev_put(bdev, BDEV_RAW); blkdev_put(bdev, BDEV_RAW);
} }
} else error = -ENOMEM; } else error = -ENOMEM;
...@@ -1057,64 +1030,47 @@ static int read_suspend_image(const char * specialfile, int noresume) ...@@ -1057,64 +1030,47 @@ static int read_suspend_image(const char * specialfile, int noresume)
return error; return error;
} }
/* /**
* Called from init kernel_thread. * software_resume - Check and load saved image from swap.
* We check if we have an image and if so we try to resume *
* Defined as a late_initcall, so it gets called after all devices
* have been probed and initialized, but before we've mounted anything.
*/ */
void software_resume(void) static int software_resume(void)
{ {
if (num_online_cpus() > 1) { if (!strlen(resume_file))
printk(KERN_WARNING "Software Suspend has malfunctioning SMP support. Disabled :(\n"); return 0;
return;
}
/* We enable the possibility of machine suspend */
software_suspend_enabled = 1;
if (!resume_status)
return;
printk( "%s", name_resume );
if (resume_status == NORESUME) {
if(resume_file[0])
read_suspend_image(resume_file, 1);
printk( "disabled\n" );
return;
}
MDELAY(1000);
if (pm_prepare_console()) if (pm_prepare_console())
printk("swsusp: Can't allocate a console... proceeding\n"); printk("swsusp: Can't allocate a console... proceeding\n");
if (!resume_file[0] && resume_status == RESUME_SPECIFIED) { printk("swsusp: %s\n", name_resume );
printk( "suspension device unspecified\n" );
return; MDELAY(1000);
}
printk( "resuming from %s\n", resume_file); printk("swsusp: resuming from %s\n", resume_file);
if (read_suspend_image(resume_file, 0)) if (read_suspend_image(resume_file))
goto read_failure; goto read_failure;
do_magic(1); do_magic(1);
panic("This never returns"); printk("swsusp: Resume failed. Continuing.\n");
read_failure: read_failure:
pm_restore_console(); pm_restore_console();
return; return -EFAULT;
} }
late_initcall(software_resume);
static int __init resume_setup(char *str) static int __init resume_setup(char *str)
{ {
if (resume_status == NORESUME)
return 1;
strncpy( resume_file, str, 255 ); strncpy( resume_file, str, 255 );
resume_status = RESUME_SPECIFIED;
return 1; return 1;
} }
static int __init noresume_setup(char *str) static int __init noresume_setup(char *str)
{ {
resume_status = NORESUME; resume_file[0] = '\0';
return 1; return 1;
} }
......
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