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>
[PATCH]: olpc:  Change the suspend method once again

From: Jordan Crouse <[EMAIL PROTECTED]>

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

Signed-off-by:  Jordan Crouse <[EMAIL PROTECTED]>
---

 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:
_______________________________________________
Devel mailing list
[email protected]
http://mailman.laptop.org/mailman/listinfo/devel

Reply via email to