summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2003-08-14 00:40:55 -0700
committerPatrick Mochel <mochel@osdl.org>2003-08-14 00:40:55 -0700
commitbee60089075ef59a0e997148e43069aa3df8e227 (patch)
treebca1e0067bc9e66a48c1d0f51f4f02f030490a16 /kernel
parent310b411f7f1ac37de5c8b9db5edd8b436b4b5eba (diff)
parent0b081c819fa9419fb6e027772f08dccac1f8ea8a (diff)
Hand Merge
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/power/Makefile4
-rw-r--r--kernel/power/console.c14
-rw-r--r--kernel/power/pm.c (renamed from kernel/pm.c)37
-rw-r--r--kernel/power/poweroff.c44
-rw-r--r--kernel/power/process.c1
-rw-r--r--kernel/power/swsusp.c155
7 files changed, 119 insertions, 138 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 495214d708bd..72eb0287e843 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_SMP) += cpu.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += ksyms.o module.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
-obj-$(CONFIG_PM) += pm.o power/
+obj-$(CONFIG_PM) += power/
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_COMPAT) += compat.o
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 2a1e6368f7e5..3a11202cc91e 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -1,2 +1,4 @@
-obj-y := process.o console.o
+obj-y := process.o console.o pm.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
+
+obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
diff --git a/kernel/power/console.c b/kernel/power/console.c
index bfaf3f14c114..c05d0e43675f 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -1,3 +1,9 @@
+/*
+ * drivers/power/process.c - Functions for saving/restoring console.
+ *
+ * Originally from swsusp.
+ */
+
#include <linux/vt_kern.h>
#include <linux/kbd_kern.h>
#include "power.h"
@@ -14,13 +20,13 @@ int pm_prepare_console(void)
#ifdef SUSPEND_CONSOLE
orig_fgconsole = fg_console;
- if(vc_allocate(SUSPEND_CONSOLE))
+ if (vc_allocate(SUSPEND_CONSOLE))
/* we can't have a free VC for now. Too bad,
* we don't want to mess the screen for now. */
return 1;
- set_console (SUSPEND_CONSOLE);
- if(vt_waitactive(SUSPEND_CONSOLE)) {
+ set_console(SUSPEND_CONSOLE);
+ if (vt_waitactive(SUSPEND_CONSOLE)) {
pr_debug("Suspend: Can't switch VCs.");
return 1;
}
@@ -34,7 +40,7 @@ void pm_restore_console(void)
{
console_loglevel = orig_loglevel;
#ifdef SUSPEND_CONSOLE
- set_console (orig_fgconsole);
+ set_console(orig_fgconsole);
#endif
return;
}
diff --git a/kernel/pm.c b/kernel/power/pm.c
index afffd046c2f6..09d55363cefc 100644
--- a/kernel/pm.c
+++ b/kernel/power/pm.c
@@ -24,7 +24,6 @@
#include <linux/slab.h>
#include <linux/pm.h>
#include <linux/interrupt.h>
-#include <linux/sysrq.h>
int pm_active;
@@ -295,39 +294,3 @@ EXPORT_SYMBOL(pm_find);
EXPORT_SYMBOL(pm_active);
-#ifdef CONFIG_MAGIC_SYSRQ
-
-/**
- * handle_poweroff - sysrq callback for power down
- * @key: key pressed (unused)
- * @pt_regs: register state (unused)
- * @kbd: keyboard state (unused)
- * @tty: tty involved (unused)
- *
- * When the user hits Sys-Rq o to power down the machine this is the
- * callback we use.
- */
-
-static void handle_poweroff (int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
-{
- if (pm_power_off)
- pm_power_off();
-}
-
-static struct sysrq_key_op sysrq_poweroff_op = {
- .handler = handle_poweroff,
- .help_msg = "powerOff",
- .action_msg = "Power Off\n"
-};
-
-#endif /* CONFIG_MAGIC_SYSRQ */
-
-
-static int pm_init(void)
-{
- register_sysrq_key('o', &sysrq_poweroff_op);
- return 0;
-}
-
-subsys_initcall(pm_init);
diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c
new file mode 100644
index 000000000000..9abe4ac23f02
--- /dev/null
+++ b/kernel/power/poweroff.c
@@ -0,0 +1,44 @@
+/*
+ * poweroff.c - sysrq handler to gracefully power down machine.
+ *
+ * This file is released under the GPL v2
+ */
+
+#include <linux/kernel.h>
+#include <linux/sysrq.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+
+
+/**
+ * handle_poweroff - sysrq callback for power down
+ * @key: key pressed (unused)
+ * @pt_regs: register state (unused)
+ * @kbd: keyboard state (unused)
+ * @tty: tty involved (unused)
+ *
+ * When the user hits Sys-Rq o to power down the machine this is the
+ * callback we use.
+ */
+
+static void handle_poweroff (int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
+{
+ if (pm_power_off)
+ pm_power_off();
+}
+
+static struct sysrq_key_op sysrq_poweroff_op = {
+ .handler = handle_poweroff,
+ .help_msg = "powerOff",
+ .action_msg = "Power Off\n"
+};
+
+
+static int pm_sysrq_init(void)
+{
+ register_sysrq_key('o', &sysrq_poweroff_op);
+ return 0;
+}
+
+subsys_initcall(pm_sysrq_init);
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 671730612e0f..15c1b340c2ed 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -8,6 +8,7 @@
#undef DEBUG
+#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/suspend.h>
#include <linux/module.h>
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index b9cd4bd18358..3da9c0142676 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -67,7 +67,7 @@
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) __ADDRESS((x) << PAGE_SHIFT)
@@ -85,8 +85,7 @@ spinlock_t suspend_pagedir_lock __nosavedata = SPIN_LOCK_UNLOCKED;
static int pagedir_order_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;
/* Local variables that should not be affected by save */
unsigned int nr_copy_pages __nosavedata = 0;
@@ -352,15 +351,10 @@ static int count_and_copy_data_pages(struct pbe *pagedir_p)
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 <pavel@ucw.cz> and try again ;-).");
if (!PageReserved(page)) {
if (PageNosave(page))
@@ -479,19 +473,23 @@ static void drivers_unsuspend(void)
/* Called from process context */
static int drivers_suspend(void)
{
- device_suspend(4, SUSPEND_NOTIFY);
- device_suspend(4, SUSPEND_SAVE_STATE);
- device_suspend(4, SUSPEND_DISABLE);
- if(!pm_suspend_state) {
+ if (device_suspend(4, SUSPEND_NOTIFY))
+ return -EIO;
+ if (device_suspend(4, SUSPEND_SAVE_STATE)) {
+ device_resume(RESUME_RESTORE_STATE);
+ return -EIO;
+ }
+ if (!pm_suspend_state) {
if(pm_send_all(PM_SUSPEND,(void *)3)) {
printk(KERN_WARNING "Problem while sending suspend event\n");
- return(1);
+ return -EIO;
}
pm_suspend_state=1;
} else
printk(KERN_WARNING "PM suspend state already raised\n");
+ device_suspend(4, SUSPEND_DISABLE);
- return(0);
+ return 0;
}
#define RESUME_PHASE1 1 /* Called from interrupts disabled */
@@ -504,7 +502,7 @@ static void drivers_resume(int flags)
device_resume(RESUME_ENABLE);
}
if (flags & RESUME_PHASE2) {
- if(pm_suspend_state) {
+ 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;
@@ -696,7 +694,7 @@ void do_magic_suspend_2(void)
mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
}
-static void do_software_suspend(void)
+static int do_software_suspend(void)
{
arch_prepare_suspend();
if (pm_prepare_console())
@@ -715,7 +713,7 @@ static void do_software_suspend(void)
blk_run_queues();
/* Save state of all device drivers, and stop them. */
- if(drivers_suspend()==0)
+ if (drivers_suspend()==0)
/* If stopping device drivers worked, we proceed basically into
* suspend_save_image.
*
@@ -731,20 +729,35 @@ static void do_software_suspend(void)
software_suspend_enabled = 1;
MDELAY(1000);
pm_restore_console();
+ return 0;
}
-/*
- * This is main interface to the outside world. It needs to be
- * called from process context.
+
+/**
+ * software_suspend - initiate suspend-to-swap transition.
+ *
+ * This is main interface to the outside world. It needs to be
+ * called from process context.
*/
-void software_suspend(void)
+
+int software_suspend(void)
{
if(!software_suspend_enabled)
- return;
+ 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)
+ printk("swsusp is not supported with high- or discontig-mem.\n");
+ return -EPERM;
+#endif
software_suspend_enabled = 0;
might_sleep();
- do_software_suspend();
+ return do_software_suspend();
}
/* More restore stuff */
@@ -890,31 +903,9 @@ static int bdev_read_page(struct block_device *bdev, long pos, void *buf)
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 __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;
int i, nr_pgdir_pages;
@@ -939,18 +930,9 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur,
else if (!memcmp("S2",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
else {
- if (noresume)
- return -EINVAL;
- panic("%sUnable to find suspended-data signature (%.10s - misspelled?\n",
+ printk("swsusp: %s: Unable to find suspended-data signature (%.10s - misspelled?\n",
name_resume, cur->swh.magic.magic);
- }
- 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);
+ return -EFAULT;
}
printk( "%sSignature found, resuming\n", name_resume );
@@ -1000,7 +982,7 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur,
return 0;
}
-static int read_suspend_image(const char * specialfile, int noresume)
+static int read_suspend_image(const char * specialfile)
{
union diskpage *cur;
unsigned long scratch_page = 0;
@@ -1019,7 +1001,7 @@ static int read_suspend_image(const char * specialfile, int noresume)
error = PTR_ERR(bdev);
} else {
set_blocksize(bdev, PAGE_SIZE);
- error = __read_suspend_image(bdev, cur, noresume);
+ error = __read_suspend_image(bdev, cur);
blkdev_put(bdev, BDEV_RAW);
}
} else error = -ENOMEM;
@@ -1048,64 +1030,47 @@ static int read_suspend_image(const char * specialfile, int noresume)
return error;
}
-/*
- * Called from init kernel_thread.
- * We check if we have an image and if so we try to resume
+/**
+ * software_resume - Check and load saved image from swap.
+ *
+ * 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) {
- 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);
+ if (!strlen(resume_file))
+ return 0;
if (pm_prepare_console())
printk("swsusp: Can't allocate a console... proceeding\n");
- if (!resume_file[0] && resume_status == RESUME_SPECIFIED) {
- printk( "suspension device unspecified\n" );
- return;
- }
+ printk("swsusp: %s\n", name_resume );
+
+ MDELAY(1000);
- printk( "resuming from %s\n", resume_file);
- if (read_suspend_image(resume_file, 0))
+ printk("swsusp: resuming from %s\n", resume_file);
+ if (read_suspend_image(resume_file))
goto read_failure;
do_magic(1);
- panic("This never returns");
+ printk("swsusp: Resume failed. Continuing.\n");
read_failure:
pm_restore_console();
- return;
+ return -EFAULT;
}
+late_initcall(software_resume);
+
static int __init resume_setup(char *str)
{
- 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_status = NORESUME;
+ resume_file[0] = '\0';
return 1;
}