summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Machek <pavel@ucw.cz>2002-06-02 23:25:44 -0700
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-06-02 23:25:44 -0700
commit14f546974ba896cff41ce0fc6fd8be36a4d533fa (patch)
treec20c4e9bc8c75db473972816b98cd9724e409020
parent5ca5a885c49751852a4e78b3c529dbc8e3984e98 (diff)
[PATCH] Fix suspend-to-RAM in 2.5.20
I created arch/i386/suspend.c not to clash with ACPI people so much in future. (More stuff is going to move into it in the future, to clean up functions that really do not belong to the headers.)
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/i386/kernel/suspend.c45
-rw-r--r--drivers/acpi/system.c4
-rw-r--r--include/asm-i386/suspend.h24
4 files changed, 71 insertions, 4 deletions
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 9f5347532062..8ca2b738265c 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -24,6 +24,8 @@ obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o
obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
+obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
+obj-$(CONFIG_ACPI_SLEEP) += suspend.o
ifdef CONFIG_VISWS
obj-y += setup-visws.o
obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
diff --git a/arch/i386/kernel/suspend.c b/arch/i386/kernel/suspend.c
new file mode 100644
index 000000000000..9302e601be54
--- /dev/null
+++ b/arch/i386/kernel/suspend.c
@@ -0,0 +1,45 @@
+/*
+ * Suspend support specific for i386.
+ *
+ * Distribute under GPLv2
+ *
+ * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
+ */
+
+#define ACPI_C
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/poll.h>
+#include <linux/delay.h>
+#include <linux/sysrq.h>
+#include <linux/compatmac.h>
+#include <linux/proc_fs.h>
+#include <linux/irq.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <asm/uaccess.h>
+#include <asm/acpi.h>
+
+
+void do_suspend_lowlevel(int resume)
+{
+/*
+ * FIXME: This function should really be written in assembly. Actually
+ * requirement is that it does not touch stack, because %esp will be
+ * wrong during resume before restore_processor_context(). Check
+ * assembly if you modify this.
+ */
+ if (!resume) {
+ save_processor_context();
+ acpi_save_register_state((unsigned long)&&acpi_sleep_done);
+ acpi_enter_sleep_state(3);
+ return;
+ }
+acpi_sleep_done:
+ restore_processor_context();
+}
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index a6b3e8d377ee..f7cd2fc8635b 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -260,10 +260,8 @@ acpi_system_suspend(
u32 state)
{
acpi_status status = AE_ERROR;
-#if 0
unsigned long flags = 0;
- /* this is very broken, so don't do anything until it's fixed */
save_flags(flags);
switch (state)
@@ -289,8 +287,6 @@ acpi_sleep_done:
fix_processor_context();
restore_flags(flags);
-#endif
- printk("ACPI: ACPI-based suspend currently broken, aborting\n");
return status;
}
diff --git a/include/asm-i386/suspend.h b/include/asm-i386/suspend.h
index 203e10e23cb7..b41d88f45928 100644
--- a/include/asm-i386/suspend.h
+++ b/include/asm-i386/suspend.h
@@ -294,3 +294,27 @@ static void do_magic(int resume)
}
#endif
+#ifdef CONFIG_ACPI_SLEEP
+extern unsigned long saved_eip;
+extern unsigned long saved_esp;
+extern unsigned long saved_ebp;
+extern unsigned long saved_ebx;
+extern unsigned long saved_esi;
+extern unsigned long saved_edi;
+
+static inline void acpi_save_register_state(unsigned long return_point)
+{
+ saved_eip = return_point;
+ asm volatile ("movl %%esp,(%0)" : "=m" (saved_esp));
+ asm volatile ("movl %%ebp,(%0)" : "=m" (saved_ebp));
+ asm volatile ("movl %%ebx,(%0)" : "=m" (saved_ebx));
+ asm volatile ("movl %%edi,(%0)" : "=m" (saved_edi));
+ asm volatile ("movl %%esi,(%0)" : "=m" (saved_esi));
+}
+
+#define acpi_restore_register_state() do {} while (0)
+
+/* routines for saving/restoring kernel state */
+extern int acpi_save_state_mem(void);
+extern int acpi_save_state_disk(void);
+#endif