Going to suspend

Jordan Crouse jordan.crouse at amd.com
Fri Mar 9 20:48:21 EST 2007


I just pushed a new patch (attached), that once again changes how we 
suspend the board.  I am ashamed to admit that I thought that the virtual
to physical mapping was 1:1 under 1MB.  It is actually not (it lives in
0xc0000000 or wherever PAGE_OFFSET is set) - and things really started
to work better when I figured that out.

I slightly re-factored the way we go to the OFW hole based on how the 
PCIBIOS code operates - it seems more robust and intelligent then the
way I was doing it before.

So at least now, when you suspend (echo mem > /sys/power/state), it at 
least jumps into the OFW subroutine, but unfortunately, thats as far as
it gets, since OFW also didn't expect us to be mapped clear up in the
C zillion space, so it gets tripped up on these two lines:

cs:0xC00F0018u  BD00080F00   mov ebp,0xf0800
cs:0xC00F001Du  896500       mov [ebp+0x0],esp

I trust Mitch will have that banged into shape in no time.  Have
a happy weekend.

Jordan
-- 
Jordan Crouse
Senior Linux Engineer
Advanced Micro Devices, Inc.
<www.amd.com/embeddedprocessors>
-------------- next part --------------
[PATCH]: olpc:  Change the suspend method once again

From: Jordan Crouse <jordan.crouse at amd.com>

Change the suspend method - this time its a lot cleaner and more
intellegent about how memory is organized.

Signed-off-by:  Jordan Crouse <jordan.crouse at amd.com>
---

 arch/i386/kernel/olpc-pm.c     |   23 +++++++++++++++--------
 arch/i386/kernel/olpc-wakeup.S |    8 +-------
 arch/i386/kernel/setup.c       |    3 +++
 3 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/arch/i386/kernel/olpc-pm.c b/arch/i386/kernel/olpc-pm.c
index 7178161..014dde7 100644
--- a/arch/i386/kernel/olpc-pm.c
+++ b/arch/i386/kernel/olpc-pm.c
@@ -32,7 +32,11 @@ #define CS5536_PM_RTC    (1 << 10)
 /* Enable this when the EC firmare is updated to support SCIs */
 #undef ENABLE_EC_SCI
 
-unsigned long olpc_wakeup_address;
+struct {
+	unsigned long address;
+	unsigned short segment;
+} ofw_bios_entry = { 0, __KERNEL_CS };
+
 extern char wakeup_start, wakeup_end;
 extern void do_olpc_suspend_lowlevel(void);
 extern unsigned long FASTCALL(olpc_copy_wakeup_routine(unsigned long));
@@ -108,7 +112,7 @@ #endif
 
 static int olpc_pm_state_valid (suspend_state_t pm_state)
 {
-        if (olpc_wakeup_address && pm_state == PM_SUSPEND_MEM)
+        if (pm_state == PM_SUSPEND_MEM)
                 return 1;
 
         return 0;
@@ -117,7 +121,7 @@ static int olpc_pm_state_valid (suspend_
 static int olpc_pm_enter (suspend_state_t pm_state)
 {
         /* Only STR is supported */
-        if (olpc_wakeup_address && pm_state != PM_SUSPEND_MEM)
+        if (pm_state != PM_SUSPEND_MEM)
                 return -EINVAL;
 
         /* Save CPU state */
@@ -125,12 +129,8 @@ static int olpc_pm_enter (suspend_state_
 	return 0;
 }
 
-/* This function handles any last minute configuration that we want 
-   to do before we go to sleep.  Mainly this will involve setting 
-   wake events. This is called from do_olpc_suspend_lowlevel */
-
 int asmlinkage
-olpc_setup_sleep_state(u8 sleep_state)
+olpc_do_sleep(u8 sleep_state)
 {
 	/* FIXME: Set the SCI bits we want to wake up on here */
 
@@ -140,6 +140,12 @@ olpc_setup_sleep_state(u8 sleep_state)
 
 
 	/* FIXME: Set the GPE0 bits we want to wake on here */
+
+	/* Call the OFW hole */
+
+	__asm__("call *(%%edi); cld"
+		: : "D" (&ofw_bios_entry));
+
 	return 0;
 }
 
@@ -314,6 +320,7 @@ #endif
 	/* Clear pending interrupt */
 	outl(inl(acpi_base) | 0xFFFF, acpi_base);
 
+	ofw_bios_entry.address = 0xF0000 + PAGE_OFFSET;
 	pm_set_ops(&olpc_pm_ops);
 
 	return 0;
diff --git a/arch/i386/kernel/olpc-wakeup.S b/arch/i386/kernel/olpc-wakeup.S
index c344a7f..b0ecac9 100644
--- a/arch/i386/kernel/olpc-wakeup.S
+++ b/arch/i386/kernel/olpc-wakeup.S
@@ -32,14 +32,8 @@ ENTRY(do_olpc_suspend_lowlevel)
 	call	save_processor_state
 	call	save_registers
 	pushl	$3
-	call	olpc_setup_sleep_state
-	addl	$4, %esp
+	call	olpc_do_sleep
 
-#	We're ready to sleep - go, go, gadget sleep
-	mov     $0xf0000,%eax
-	lcall   *(%eax)
-	
-#	We are back - restore the stack
 	movl    saved_context_esp, %esp
 		
 #	Jump to the return point and restore our state
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index abd3b30..f380eb7 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -439,6 +439,9 @@ #ifdef CONFIG_ACPI_SLEEP
 	 */
 	acpi_reserve_bootmem();
 #endif
+#ifdef CONFIG_OLPC_PM
+	reserve_bootmem(0xf0000, PAGE_SIZE);
+#endif
 #ifdef CONFIG_X86_FIND_SMP_CONFIG
 	/*
 	 * Find and reserve possible boot-time SMP configuration:


More information about the Devel mailing list