2003-09-28 10:06:17

by Pavel Machek

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

Hi!
>> makes it work here (*). Please apply,

>No.

>I'm not going to apply warring patches. You two sort it out

This should not be warring patch. Pat
already has variant in his tree,
feel free to pull from him - but it
would be nice to have working swsusp
in -test6. --p


2003-09-28 17:40:44

by Linus Torvalds

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3


On 28 Sep 2003 [email protected] wrote:
>
> This should not be warring patch. Pat
> already has variant in his tree,
> feel free to pull from him - but it
> would be nice to have working swsusp
> in -test6. --p

Ok. In that case, can we remove the '#if 0' blocks entirely, or at least
add a big comment on why they are there but disabled?

I'd also like to have some kind of readme or similar on the different
suspend/resume issues, and why we have two different approaches. Hmm?

Linus

2003-09-28 18:00:12

by Pavel Machek

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

HI!

> > This should not be warring patch. Pat
> > already has variant in his tree,
> > feel free to pull from him - but it
> > would be nice to have working swsusp
> > in -test6. --p
>
> Ok. In that case, can we remove the '#if 0' blocks entirely, or at least
> add a big comment on why they are there but disabled?

Like this?

> I'd also like to have some kind of readme or similar on the different
> suspend/resume issues, and why we have two different
> approaches. Hmm?

I do not yet have details "how is patricks pmdisk different from
swsusp", so this documentation is hard to write at this point.
Pavel

Index: include/linux/suspend.h
===================================================================
RCS file: /home/pavel/sf/bitbucket/bkcvs/linux-2.5/include/linux/suspend.h,v
retrieving revision 1.18
diff -u -u -r1.18 suspend.h
--- include/linux/suspend.h 21 Aug 2003 23:44:53 -0000 1.18
+++ include/linux/suspend.h 26 Sep 2003 10:53:27 -0000
@@ -8,7 +8,11 @@
#include <linux/notifier.h>
#include <linux/config.h>
#include <linux/init.h>
-#include <linux/pm.h>
+
+extern unsigned char software_suspend_enabled;
+
+#define NORESUME 1
+#define RESUME_SPECIFIED 2

#ifdef CONFIG_SOFTWARE_SUSPEND
/* page backup entry */
@@ -45,30 +49,61 @@
/* mm/page_alloc.c */
extern void drain_local_pages(void);

+/* kernel/suspend.c */
+extern void software_suspend(void);
+extern void software_resume(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;

+/* Communication between kernel/suspend.c and arch/i386/suspend.c */
+
+extern void do_magic_resume_1(void);
+extern void do_magic_resume_2(void);
+extern void do_magic_suspend_1(void);
+extern void do_magic_suspend_2(void);
+
/* Communication between acpi and arch/i386/suspend.c */

extern void do_suspend_lowlevel(int resume);
extern void do_suspend_lowlevel_s4bios(int resume);

#else /* CONFIG_SOFTWARE_SUSPEND */
-static inline int software_suspend(void)
+static inline void software_suspend(void)
{
+ printk("Warning: fake suspend called\n");
return -EPERM;
}
+#define software_resume() do { } while(0)
+#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 */

#endif /* _LINUX_SWSUSP_H */
Index: kernel/sys.c
===================================================================
RCS file: /home/pavel/sf/bitbucket/bkcvs/linux-2.5/kernel/sys.c,v
retrieving revision 1.60
diff -u -u -r1.60 sys.c
--- kernel/sys.c 21 Sep 2003 22:37:10 -0000 1.60
+++ kernel/sys.c 26 Sep 2003 10:53:27 -0000
@@ -456,8 +456,11 @@

#ifdef CONFIG_SOFTWARE_SUSPEND
case LINUX_REBOOT_CMD_SW_SUSPEND:
- if (!pm_suspend(PM_SUSPEND_DISK))
- break;
+ if (!software_suspend_enabled) {
+ unlock_kernel();
+ return -EAGAIN;
+ }
+ software_suspend();
do_exit(0);
break;
#endif
Index: kernel/power/main.c
===================================================================
RCS file: /home/pavel/sf/bitbucket/bkcvs/linux-2.5/kernel/power/main.c,v
retrieving revision 1.3
diff -u -u -r1.3 main.c
--- kernel/power/main.c 21 Aug 2003 23:44:53 -0000 1.3
+++ kernel/power/main.c 28 Sep 2003 17:50:10 -0000
@@ -172,7 +172,7 @@

static int pm_suspend_disk(void)
{
- int error;
+ int error = -EPERM;

pr_debug("PM: Attempting to suspend to disk.\n");
if (pm_disk_mode == PM_DISK_FIRMWARE)
@@ -183,6 +183,9 @@

pr_debug("PM: snapshotting memory.\n");
in_suspend = 1;
+#if 0
+ /* Patrick is likely to s/swsusp_/pmdisk_/ in next release,
+ but #if 0 is needed so that this compiles. */
if ((error = swsusp_save()))
goto Done;

@@ -195,6 +198,7 @@
} else
pr_debug("PM: Image restored successfully.\n");
swsusp_free();
+#endif
Done:
return error;
}
@@ -356,6 +360,9 @@

pr_debug("PM: Reading swsusp image.\n");

+#if 0
+ /* Patrick is likely to s/swsusp_/pmdisk_/ in next release,
+ but #if 0 is needed so that this compiles. */
if ((error = swsusp_read()))
goto Done;

@@ -371,6 +378,7 @@
suspend_finish(PM_SUSPEND_DISK);
Free:
swsusp_free();
+#endif
Done:
pr_debug("PM: Resume from disk failed.\n");
return 0;
Index: kernel/power/swsusp.c
===================================================================
RCS file: /home/pavel/sf/bitbucket/bkcvs/linux-2.5/kernel/power/swsusp.c,v
retrieving revision 1.4
diff -u -u -r1.4 swsusp.c
--- kernel/power/swsusp.c 21 Aug 2003 23:44:53 -0000 1.4
+++ kernel/power/swsusp.c 27 Sep 2003 20:52:00 -0000
@@ -5,7 +5,8 @@
* machine suspend feature using pretty near only high-level routines
*
* Copyright (C) 1998-2001 Gabor Kuti <[email protected]>
- * Copyright (C) 1998,2001,2002 Pavel Machek <[email protected]>
+ * Copyright (C) 1998,2001-2003 Pavel Machek <[email protected]>
+ * Copyright (C) 2003 Patrick Mochel <[email protected]>
*
* I'd like to thank the following people for their work:
*
@@ -65,7 +66,9 @@

#include "power.h"

-unsigned char software_suspend_enabled = 1;
+extern long sys_sync(void);
+
+unsigned char software_suspend_enabled = 0;

#define __ADDRESS(x) ((unsigned long) phys_to_virt(x))
#define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT)
@@ -83,11 +86,14 @@
static int pagedir_order_check;
static int nr_copy_pages_check;

-static char resume_file[256]; /* For resume= kernel option */
+static int resume_status;
+static char resume_file[256] = ""; /* For resume= kernel option */
static dev_t resume_device;
/* Local variables that should not be affected by save */
unsigned int nr_copy_pages __nosavedata = 0;

+static int pm_suspend_state;
+
/* Suspend pagedir is allocated before final copy, therefore it
must be freed after resume

@@ -347,10 +353,15 @@
int pfn;
struct page *page;

+#ifdef CONFIG_DISCONTIGMEM
+ panic("Discontingmem not supported");
+#else
BUG_ON (max_pfn != num_physpages);
-
+#endif
for (pfn = 0; pfn < max_pfn; pfn++) {
page = pfn_to_page(pfn);
+ if (PageHighMem(page))
+ panic("Swsusp not supported on highmem boxes. Send 1GB of RAM to <[email protected]> and try again ;-).");

if (!PageReserved(page)) {
if (PageNosave(page))
@@ -435,6 +446,74 @@
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)
+{
+ device_resume();
+}
+
+/* Called from process context */
+static int drivers_suspend(void)
+{
+ device_suspend(4);
+ if(!pm_suspend_state) {
+ if(pm_send_all(PM_SUSPEND,(void *)3)) {
+ printk(KERN_WARNING "Problem while sending suspend event\n");
+ return(1);
+ }
+ pm_suspend_state=1;
+ } else
+ printk(KERN_WARNING "PM suspend state already raised\n");
+ device_power_down(4);
+ 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)
+static void drivers_resume(int flags)
+{
+ if (flags & RESUME_PHASE1) {
+ dpm_power_up();
+ }
+ if (flags & RESUME_PHASE2) {
+ device_resume();
+ if(pm_suspend_state) {
+ if(pm_send_all(PM_RESUME,(void *)0))
+ printk(KERN_WARNING "Problem while sending resume event\n");
+ pm_suspend_state=0;
+ } else
+ printk(KERN_WARNING "PM suspend state wasn't raised\n");
+
+#ifdef SUSPEND_CONSOLE
+ update_screen(fg_console); /* Hmm, is this the problem? */
+#endif
+ }
+}

static int suspend_prepare_image(void)
{
@@ -488,14 +567,13 @@
return 0;
}

-static int suspend_save_image(void)
+static void suspend_save_image(void)
{
- int error;
-
- device_resume();
+ drivers_unsuspend();

lock_swapdevices();
- error = write_suspend_image();
+ write_suspend_image();
+printk("locking_swapdevices\n");
lock_swapdevices(); /* This will unlock ignored swap devices since writing is finished */

/* It is important _NOT_ to umount filesystems at this point. We want
@@ -503,7 +581,30 @@
* filesystem clean: it is not. (And it does not matter, if we resume
* correctly, we'll mark system clean, anyway.)
*/
- return error;
+printk("exiting function\n");
+}
+
+static void suspend_power_down(void)
+{
+ extern int C_A_D;
+ C_A_D = 0;
+ printk(KERN_EMERG "%s%s Trying to power down.\n", name_suspend, TEST_SWSUSP ? "Disable TEST_SWSUSP. NOT ": "");
+#ifdef CONFIG_VT
+ PRINTK(KERN_EMERG "shift_state: %04x\n", shift_state);
+ mdelay(1000);
+ if (TEST_SWSUSP ^ (!!(shift_state & (1 << KG_CTRL))))
+ machine_restart(NULL);
+ else
+#endif
+ {
+ device_shutdown();
+ machine_power_off();
+ }
+
+ printk(KERN_EMERG "%sProbably not capable for powerdown. System halted.\n", name_suspend);
+ machine_halt();
+ while (1);
+ /* NOTREACHED */
}

/*
@@ -515,21 +616,32 @@
barrier();
mb();
spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */
+
PRINTK( "Waiting for DMAs to settle down...\n");
- /* We do not want some readahead with DMA to corrupt our memory, right?
- Do it with disabled interrupts for best effect. That way, if some
- driver scheduled DMA, we have good chance for DMA to finish ;-). */
- mdelay(1000);
+ mdelay(1000); /* We do not want some readahead with DMA to corrupt our memory, right?
+ Do it with disabled interrupts for best effect. That way, if some
+ driver scheduled DMA, we have good chance for DMA to finish ;-). */
}

void do_magic_resume_2(void)
{
BUG_ON (nr_copy_pages_check != nr_copy_pages);
BUG_ON (pagedir_order_check != pagedir_order);
-
- /* Even mappings of "global" things (vmalloc) need to be fixed */
- __flush_tlb_global();
+
+ __flush_tlb_global(); /* Even mappings of "global" things (vmalloc) need to be fixed */
+
+ PRINTK( "Freeing prev allocated pagedir\n" );
+ free_suspend_pagedir((unsigned long) pagedir_save);
spin_unlock_irq(&suspend_pagedir_lock);
+ drivers_resume(RESUME_ALL_PHASES);
+
+ PRINTK( "Fixing swap signatures... " );
+ mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
+ PRINTK( "ok\n" );
+
+#ifdef SUSPEND_CONSOLE
+ update_screen(fg_console); /* Hmm, is this the problem? */
+#endif
}

/* do_magic() is implemented in arch/?/kernel/suspend_asm.S, and basically does:
@@ -554,28 +666,93 @@
{
mb();
barrier();
+ BUG_ON(in_atomic());
spin_lock_irq(&suspend_pagedir_lock);
}

-int do_magic_suspend_2(void)
+void do_magic_suspend_2(void)
{
int is_problem;
read_swapfiles();
is_problem = suspend_prepare_image();
spin_unlock_irq(&suspend_pagedir_lock);
- if (!is_problem)
- return suspend_save_image();
+ if (!is_problem) {
+ kernel_fpu_end(); /* save_processor_state() does kernel_fpu_begin, and we need to revert it in order to pass in_atomic() checks */
+ BUG_ON(in_atomic());
+ suspend_save_image();
+printk("leaving suspend_2\n");
+ suspend_power_down(); /* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */
+ }
+
printk(KERN_EMERG "%sSuspend failed, trying to recover...\n", name_suspend);
+ MDELAY(1000); /* So user can wait and report us messages if armageddon comes :-) */
+
barrier();
mb();
+ spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */
mdelay(1000);
- return -EFAULT;
+
+ free_pages((unsigned long) pagedir_nosave, pagedir_order);
+ spin_unlock_irq(&suspend_pagedir_lock);
+ mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
+}
+
+static void do_software_suspend(void)
+{
+ printk("Doing software_suspend()\n");
+ 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();
+}
+
+/*
+ * 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 */

/* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */
-static void __init copy_pagedir(suspend_pagedir_t *to, suspend_pagedir_t *from)
+static void copy_pagedir(suspend_pagedir_t *to, suspend_pagedir_t *from)
{
int i;
char *topointer=(char *)to, *frompointer=(char *)from;
@@ -592,8 +769,8 @@
/*
* Returns true if given address/order collides with any orig_address
*/
-static int __init does_collide_order(suspend_pagedir_t *pagedir,
- unsigned long addr, int order)
+static int does_collide_order(suspend_pagedir_t *pagedir, unsigned long addr,
+ int order)
{
int i;
unsigned long addre = addr + (PAGE_SIZE<<order);
@@ -610,7 +787,7 @@
* We check here that pagedir & pages it points to won't collide with pages
* where we're going to restore from the loaded pages later
*/
-static int __init check_pagedir(void)
+static int check_pagedir(void)
{
int i;

@@ -628,7 +805,7 @@
return 0;
}

-static int __init relocate_pagedir(void)
+static int relocate_pagedir(void)
{
/*
* We have to avoid recursion (not to overflow kernel stack),
@@ -678,13 +855,13 @@
* I really don't think that it's foolproof but more than nothing..
*/

-static int __init sanity_check_failed(char *reason)
+static int sanity_check_failed(char *reason)
{
printk(KERN_ERR "%s%s\n",name_resume,reason);
return -EPERM;
}

-static int __init sanity_check(struct suspend_header *sh)
+static int sanity_check(struct suspend_header *sh)
{
if(sh->version_code != LINUX_VERSION_CODE)
return sanity_check_failed("Incorrect kernel version");
@@ -701,8 +878,7 @@
return 0;
}

-static int __init bdev_read_page(struct block_device *bdev,
- long pos, void *buf)
+static int bdev_read_page(struct block_device *bdev, long pos, void *buf)
{
struct buffer_head *bh;
BUG_ON (pos%PAGE_SIZE);
@@ -716,10 +892,31 @@
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);

-static int __init read_suspend_image(struct block_device *bdev,
- union diskpage *cur)
+static int __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume)
{
swp_entry_t next;
int i, nr_pgdir_pages;
@@ -744,9 +941,18 @@
else if (!memcmp("S2",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
else {
- printk("swsusp: %s: Unable to find suspended-data signature (%.10s - misspelled?\n",
+ if (noresume)
+ return -EINVAL;
+ panic("%sUnable to find suspended-data signature (%.10s - misspelled?\n",
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 );
@@ -796,115 +1002,125 @@
return 0;
}

-/**
- * 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();
- return do_magic(0);
-}
-
-
-/**
- * swsusp_read - Read saved image from swap.
- */
-
-int __init swsusp_read(void)
+static int read_suspend_image(const char * specialfile, int noresume)
{
union diskpage *cur;
+ unsigned long scratch_page = 0;
int error;
char b[BDEVNAME_SIZE];

- if (!strlen(resume_file))
- return -ENOENT;
-
- resume_device = name_to_dev_t(resume_file);
- printk("swsusp: Resume From Partition: %s, Device: %s\n",
- resume_file, __bdevname(resume_device, b));
-
- cur = (union diskpage *)get_zeroed_page(GFP_ATOMIC);
+ resume_device = name_to_dev_t(specialfile);
+ scratch_page = get_zeroed_page(GFP_ATOMIC);
+ cur = (void *) scratch_page;
if (cur) {
struct block_device *bdev;
+ printk("Resuming from device %s\n",
+ __bdevname(resume_device, b));
bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW);
- if (!IS_ERR(bdev)) {
+ if (IS_ERR(bdev)) {
+ error = PTR_ERR(bdev);
+ } else {
set_blocksize(bdev, PAGE_SIZE);
- error = read_suspend_image(bdev, cur);
+ error = __read_suspend_image(bdev, cur, noresume);
blkdev_put(bdev, BDEV_RAW);
- } else
- error = PTR_ERR(bdev);
- free_page((unsigned long)cur);
- } else
- error = -ENOMEM;
+ }
+ } else error = -ENOMEM;

- if (!error)
- PRINTK("Reading resume file was successful\n");
- else
- printk( "%sError %d resuming\n", name_resume, error );
+ if (scratch_page)
+ free_page(scratch_page);
+ switch (error) {
+ case 0:
+ PRINTK("Reading resume file was successful\n");
+ break;
+ case -EINVAL:
+ break;
+ case -EIO:
+ printk( "%sI/O error\n", name_resume);
+ break;
+ case -ENOENT:
+ printk( "%s%s: No such file or directory\n", name_resume, specialfile);
+ break;
+ case -ENOMEM:
+ printk( "%sNot enough memory\n", name_resume);
+ break;
+ default:
+ printk( "%sError %d resuming\n", name_resume, error );
+ }
MDELAY(1000);
return error;
}

-
/**
- * swsusp_restore - Replace running kernel with saved image.
+ * software_resume - Resume from a saved image.
+ *
+ * Called as a late_initcall (so all devices are discovered and
+ * initialized), we call swsusp to see if we have a saved image or not.
+ * If so, we quiesce devices, the restore the saved image. We will
+ * return above (in pm_suspend_disk() ) if everything goes well.
+ * Otherwise, we fail gracefully and return to the normally
+ * scheduled program.
+ *
*/
-
-int __init swsusp_restore(void)
+static void software_resume(void)
{
- return do_magic(1);
-}
+ if (num_online_cpus() > 1) {
+ printk(KERN_WARNING "Software Suspend has malfunctioning SMP support. Disabled :(\n");
+ 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);

-/**
- * swsusp_free - Free memory allocated to hold snapshot.
- */
+ if (pm_prepare_console())
+ printk("swsusp: Can't allocate a console... proceeding\n");

-int swsusp_free(void)
-{
- PRINTK( "Freeing prev allocated pagedir\n" );
- free_suspend_pagedir((unsigned long) pagedir_save);
+ if (!resume_file[0] && resume_status == RESUME_SPECIFIED) {
+ printk( "suspension device unspecified\n" );
+ return;
+ }

- PRINTK( "Fixing swap signatures... " );
- mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
- PRINTK( "ok\n" );
- return 0;
+ printk( "resuming from %s\n", resume_file);
+ if (read_suspend_image(resume_file, 0))
+ goto read_failure;
+ do_magic(1);
+ panic("This never returns");
+
+read_failure:
+ pm_restore_console();
+ return;
}

+late_initcall(software_resume);
+
static int __init resume_setup(char *str)
{
- if (strlen(str))
- strncpy(resume_file, str, 255);
+ if (resume_status == NORESUME)
+ return 1;
+
+ strncpy( resume_file, str, 255 );
+ resume_status = RESUME_SPECIFIED;
+
return 1;
}

static int __init noresume_setup(char *str)
{
- resume_file[0] = '\0';
+ resume_status = NORESUME;
return 1;
}

__setup("noresume", noresume_setup);
__setup("resume=", resume_setup);

+EXPORT_SYMBOL(software_suspend);
+EXPORT_SYMBOL(software_suspend_enabled);




--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

2003-09-28 18:58:22

by Nigel Cunningham

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

Could you also give me some clear direction on where you want me to put
my 2.4 port. Should it go in kernel/power, or somewhere else? (I'm
assuming you don't want 3 versions of swsusp?!). I'd like to put it in
the right place when I start populating swsusp25.bkbits.net, so you're
not pulling changesets later that only move the code around (I know bk
reduces the cost, but...).

Regards,

Nigel

On Mon, 2003-09-29 at 05:40, Linus Torvalds wrote:
> On 28 Sep 2003 [email protected] wrote:
> >
> > This should not be warring patch. Pat
> > already has variant in his tree,
> > feel free to pull from him - but it
> > would be nice to have working swsusp
> > in -test6. --p
>
> Ok. In that case, can we remove the '#if 0' blocks entirely, or at least
> add a big comment on why they are there but disabled?
>
> I'd also like to have some kind of readme or similar on the different
> suspend/resume issues, and why we have two different approaches. Hmm?
>
> Linus
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Nigel Cunningham
495 St Georges Road South, Hastings 4201, New Zealand

You see, at just the right time, when we were still powerless,
Christ died for the ungodly.
-- Romans 5:6, NIV.

2003-09-28 19:08:58

by Pavel Machek

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

Hi!

> Could you also give me some clear direction on where you want me to put
> my 2.4 port. Should it go in kernel/power, or somewhere else? (I'm
> assuming you don't want 3 versions of swsusp?!). I'd like to put it in
> the right place when I start populating swsusp25.bkbits.net, so you're
> not pulling changesets later that only move the code around (I know bk
> reduces the cost, but...).

I believe kernel/power is the right place. And no, 3 versions would
not be good thing.
Pavel

--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

2003-09-28 20:49:06

by Pavel Machek

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

Hi!

> > > This should not be warring patch. Pat
> > > already has variant in his tree,
> > > feel free to pull from him - but it
> > > would be nice to have working swsusp
> > > in -test6. --p
> >
> > Ok. In that case, can we remove the '#if 0' blocks entirely, or at least
> > add a big comment on why they are there but disabled?
>
> Like this?

Sorry, discard this. I do not know what went wrong, but my bkcvs did
not seem to contain those changes, nor can I see them at bkbits.net,
yet -test6 contains them.

Sorry for confusion.
Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

2003-09-29 16:17:56

by Patrick Mochel

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3


> > Ok. In that case, can we remove the '#if 0' blocks entirely, or at least
> > add a big comment on why they are there but disabled?
>
> Like this?

Pavel, I don't even know where to begin, but I will suggest that you check
your sources better. I did apply the patch to revert swsusp to the state
it was in -test3. According to bitkeeper, it's ChangeSet 1.1217.3.31,
which can be viewed here:

http://linus.bkbits.net:8080/linux-2.5/[email protected]

It was merged last Thursday night, which means it should have been in
-test5-bk13. The changelog also appeared on the bk-commits-head list.


Next, if you're going to patch my code, do *not* do crap like this:

> +#if 0
> + /* Patrick is likely to s/swsusp_/pmdisk_/ in next release,
> + but #if 0 is needed so that this compiles. */
> if ((error = swsusp_save()))
> goto Done;
>
> @@ -195,6 +198,7 @@
> } else
> pr_debug("PM: Image restored successfully.\n");
> swsusp_free();
> +#endif

I asked you several weeks ago to submit a patch that simply removed the
calls to swsusp. You did not, and you choose here to simply break it, and
add a bullshit comment to it.

If you're going to 'fix' the code, take a minute to submit a patch that
does not add #ifdef's, and with a comment that actually makes sense to
someone other than you.

And, if you're going to submit a patch, please do so against the current
release.


Pat

2003-09-29 16:55:52

by Patrick Mochel

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3


> Could you also give me some clear direction on where you want me to put
> my 2.4 port. Should it go in kernel/power, or somewhere else? (I'm
> assuming you don't want 3 versions of swsusp?!). I'd like to put it in
> the right place when I start populating swsusp25.bkbits.net, so you're
> not pulling changesets later that only move the code around (I know bk
> reduces the cost, but...).

Please put it in kernel/power/.

It's completely alright to have three suspend-to-disk implementations. For
one, porting it does not imply that it will be merged into mainline, as
is. I would like to see convergence of the competing solutions, and I
fully intend to leverage the work that you've done and integrate it into
the core power management code, and the pmdisk implementation.

The power management core provides, among other things, a framework for
properly suspending and resuming a system. Persistant state retention is
one aspect, albeit the largest in terms of importance and sheer size. I
would like to see backend mechanism for storing state abstracted from the
snapshotting process.

This means that there may be several low-level 'drivers' that each deal
with reading/writing data on a particular format. And, it means that much
of the overhead of swsusp, etc, can be folded into the core PM code.

I do not have more technical details about this ATM, but I will work with
you to make sure things are streamlined as much as possible during and
after your port.


Pat

2003-09-29 18:55:14

by Nigel Cunningham

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

On Tue, 2003-09-30 at 04:51, Patrick Mochel wrote:
> > Could you also give me some clear direction on where you want me to put
> > my 2.4 port. Should it go in kernel/power, or somewhere else? (I'm
> > assuming you don't want 3 versions of swsusp?!). I'd like to put it in
> > the right place when I start populating swsusp25.bkbits.net, so you're
> > not pulling changesets later that only move the code around (I know bk
> > reduces the cost, but...).
>
> Please put it in kernel/power/.

Ok. I'll do that then.

> It's completely alright to have three suspend-to-disk implementations. For
> one, porting it does not imply that it will be merged into mainline, as
> is. I would like to see convergence of the competing solutions, and I
> fully intend to leverage the work that you've done and integrate it into
> the core power management code, and the pmdisk implementation.
>
> The power management core provides, among other things, a framework for
> properly suspending and resuming a system. Persistant state retention is
> one aspect, albeit the largest in terms of importance and sheer size. I
> would like to see backend mechanism for storing state abstracted from the
> snapshotting process.

I'd certainly like to see such additions somehow implemented as optional
extras. The core functionality ought not be a great monolithic mass.

> This means that there may be several low-level 'drivers' that each deal
> with reading/writing data on a particular format. And, it means that much

I've had enquiries about adding support for UML, NFS and encryption
support; they would match well with your desire for a more general
solution.

> of the overhead of swsusp, etc, can be folded into the core PM code.

Yes; I have a pretty clear distinction between the code for freezing
processes and syncing data and that which actually saves the data.

> I do not have more technical details about this ATM, but I will work with
> you to make sure things are streamlined as much as possible during and
> after your port.

Great. I'll start the work in earnest tomorrow. Today I'm packing up
books :>

Nigel

--
Nigel Cunningham
495 St Georges Road South, Hastings 4201, New Zealand

You see, at just the right time, when we were still powerless,
Christ died for the ungodly.
-- Romans 5:6, NIV.

2003-09-29 19:25:14

by Pavel Machek

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

Hi!

> > > Ok. In that case, can we remove the '#if 0' blocks entirely, or at least
> > > add a big comment on why they are there but disabled?
> >
> > Like this?
>
> Pavel, I don't even know where to begin, but I will suggest that you check
> your sources better. I did apply the patch to revert swsusp to the state
> it was in -test3. According to bitkeeper, it's ChangeSet 1.1217.3.31,
> which can be viewed here:

I'm sorry, I did update on bkcvs and could not find patch. Probably I
screwed up when dealing with bkcvs.

Pavel

--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

2003-09-29 20:49:07

by Pavel Machek

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

Hi!

> > I'd also like to have some kind of readme or similar on the different
> > suspend/resume issues, and why we have two different
> > approaches. Hmm?

<azbestos underwear on>What about this one?</off>

Pavel

--- clean/Documentation/power/swsusp.txt 2003-08-27 12:00:01.000000000 +0200
+++ linux/Documentation/power/swsusp.txt 2003-09-29 22:44:27.000000000 +0200
@@ -17,6 +17,23 @@
You need to append resume=/dev/your_swap_partition to kernel command
line. Then you suspend by echo 4 > /proc/acpi/sleep.

+Pavel's unreliable guide to swsusp mess
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+They are currently two versions of swap suspend in the kernel, old
+"Pavel's" version in kernel/power/swsusp.c and new "Patrick's" version
+in kernel/power/pmdisk.c. They provide same functionality; old version
+looks ugly but was tested, while new version looks nicer but did not
+receive so much testing. echo 4 > /proc/acpi/sleep calls old version,
+echo disk > /sys/power/state calls new one.
+
+[In future, when new version is stable enough, two things can happen
+
+* new version is moved into swsusp.c, and swsusp is renamed to swap
+ suspend (Pavel prefers this)
+
+* pmdisk is kept as is and swsusp.c is removed from kernel]
+
[Notice. Rest docs is pretty outdated (see date!) It should be safe to
use swsusp on ext3/reiserfs these days.]

--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

2003-09-29 21:35:09

by Pavel Machek

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

Hi!

> > > I'd also like to have some kind of readme or similar on the different
> > > suspend/resume issues, and why we have two different
> > > approaches. Hmm?
>
> <azbestos underwear on>What about this one?</off>

Thanks to Tomas Szepe, grammar fixed a bit.

--- clean/Documentation/power/swsusp.txt 2003-08-27 12:00:01.000000000 +0200
+++ linux/Documentation/power/swsusp.txt 2003-09-29 23:29:43.000000000 +0200
@@ -17,6 +17,24 @@
You need to append resume=/dev/your_swap_partition to kernel command
line. Then you suspend by echo 4 > /proc/acpi/sleep.

+Pavel's unreliable guide to swsusp mess
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+They are currently two versions of swap suspend in the kernel, the old
+"Pavel's" version in kernel/power/swsusp.c and the new "Patrick's"
+version in kernel/power/pmdisk.c. They provide the same functionality;
+the old version looks ugly but was tested, while the new version looks
+nicer but did not receive so much testing. echo 4 > /proc/acpi/sleep
+calls the old version, echo disk > /sys/power/state calls the new one.
+
+[In the future, when the new version is stable enough, two things can
+happen:
+
+* the new version is moved into swsusp.c, and swsusp is renamed to swap
+ suspend (Pavel prefers this)
+
+* pmdisk is kept as is and swsusp.c is removed from the kernel]
+
[Notice. Rest docs is pretty outdated (see date!) It should be safe to
use swsusp on ext3/reiserfs these days.]



--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

2003-09-29 22:02:51

by Pavel Machek

[permalink] [raw]
Subject: Re: pm: Revert swsusp to 2.6.0-test3

Hi!

> > > > I'd also like to have some kind of readme or similar on the different
> > > > suspend/resume issues, and why we have two different
> > > > approaches. Hmm?
> >
> > <azbestos underwear on>What about this one?</off>
>
> Thanks to Tomas Szepe, grammar fixed a bit.

Okay, third version, thanks to Samurai.

--- clean/Documentation/power/swsusp.txt 2003-08-27 12:00:01.000000000 +0200
+++ linux/Documentation/power/swsusp.txt 2003-09-29 23:59:01.000000000 +0200
@@ -17,6 +17,24 @@
You need to append resume=/dev/your_swap_partition to kernel command
line. Then you suspend by echo 4 > /proc/acpi/sleep.

+Pavel's unreliable guide to swsusp mess
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are currently two versions of swap suspend in the kernel, the old
+"Pavel's" version in kernel/power/swsusp.c and the new "Patrick's"
+version in kernel/power/pmdisk.c. They provide the same functionality;
+the old version looks ugly but was tested, while the new version looks
+nicer but did not receive so much testing. echo 4 > /proc/acpi/sleep
+calls the old version, echo disk > /sys/power/state calls the new one.
+
+[In the future, when the new version is stable enough, two things can
+happen:
+
+* the new version is moved into swsusp.c, and swsusp is renamed to swap
+ suspend (Pavel prefers this)
+
+* pmdisk is kept as is and swsusp.c is removed from the kernel]
+
[Notice. Rest docs is pretty outdated (see date!) It should be safe to
use swsusp on ext3/reiserfs these days.]


--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]