Author: iwasaki
Date: Fri Jun  1 15:26:32 2012
New Revision: 236403
URL: http://svn.freebsd.org/changeset/base/236403

Log:
  Call AcpiLeaveSleepStatePrep() in interrupt disabled context
  (described in ACPICA source code).
  
  - Move intr_disable() and intr_restore() from acpi_wakeup.c to acpi.c
    and call AcpiLeaveSleepStatePrep() in interrupt disabled context.
  - Add acpi_wakeup_machdep() to execute wakeup MD procedures and call
    it twice in interrupt disabled/enabled context (ia64 version is
    just dummy).
  - Rename wakeup_cpus variable in acpi_sleep_machdep() to suspcpus in
    order to be shared by acpi_sleep_machdep() and acpi_wakeup_machdep().
  - Move identity mapping related code to acpi_install_wakeup_handler()
    (i386 version) for preparation of x86/acpica/acpi_wakeup.c
    (MFC candidate).
  
  Reviewed by:  jkim@
  MFC after:    2 days

Modified:
  head/sys/amd64/acpica/acpi_wakeup.c
  head/sys/dev/acpica/acpi.c
  head/sys/dev/acpica/acpivar.h
  head/sys/i386/acpica/acpi_wakeup.c
  head/sys/ia64/acpica/acpi_wakeup.c

Modified: head/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/amd64/acpica/acpi_wakeup.c Fri Jun  1 15:02:23 2012        
(r236402)
+++ head/sys/amd64/acpica/acpi_wakeup.c Fri Jun  1 15:26:32 2012        
(r236403)
@@ -76,6 +76,10 @@ static struct pcb    **susppcbs;
 static void            **suspfpusave;
 #endif
 
+#ifdef SMP
+static cpuset_t                suspcpus;
+#endif
+
 int                    acpi_restorecpu(uint64_t, vm_offset_t);
 
 static void            *acpi_alloc_wakeup_handler(void);
@@ -220,21 +224,14 @@ acpi_wakeup_cpus(struct acpi_softc *sc, 
 int
 acpi_sleep_machdep(struct acpi_softc *sc, int state)
 {
-#ifdef SMP
-       cpuset_t        wakeup_cpus;
-#endif
-       register_t      rf;
        ACPI_STATUS     status;
-       int             ret;
-
-       ret = -1;
 
        if (sc->acpi_wakeaddr == 0ul)
-               return (ret);
+               return (-1);    /* couldn't alloc wake memory */
 
 #ifdef SMP
-       wakeup_cpus = all_cpus;
-       CPU_CLR(PCPU_GET(cpuid), &wakeup_cpus);
+       suspcpus = all_cpus;
+       CPU_CLR(PCPU_GET(cpuid), &suspcpus);
 #endif
 
        if (acpi_resume_beep != 0)
@@ -242,16 +239,15 @@ acpi_sleep_machdep(struct acpi_softc *sc
 
        AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));
 
-       rf = intr_disable();
        intr_suspend();
 
        if (savectx(susppcbs[0])) {
                ctx_fpusave(suspfpusave[0]);
 #ifdef SMP
-               if (!CPU_EMPTY(&wakeup_cpus) &&
-                   suspend_cpus(wakeup_cpus) == 0) {
+               if (!CPU_EMPTY(&suspcpus) &&
+                   suspend_cpus(suspcpus) == 0) {
                        device_printf(sc->acpi_dev, "Failed to suspend APs\n");
-                       goto out;
+                       return (0);     /* couldn't sleep */
                }
 #endif
 
@@ -276,41 +272,54 @@ acpi_sleep_machdep(struct acpi_softc *sc
                        device_printf(sc->acpi_dev,
                            "AcpiEnterSleepState failed - %s\n",
                            AcpiFormatException(status));
-                       goto out;
+                       return (0);     /* couldn't sleep */
                }
 
                for (;;)
                        ia32_pause();
-       } else {
-               pmap_init_pat();
-               load_cr3(susppcbs[0]->pcb_cr3);
-               initializecpu();
-               PCPU_SET(switchtime, 0);
-               PCPU_SET(switchticks, ticks);
-#ifdef SMP
-               if (!CPU_EMPTY(&wakeup_cpus))
-                       acpi_wakeup_cpus(sc, &wakeup_cpus);
-#endif
-               ret = 0;
        }
 
-out:
+       return (1);     /* wakeup successfully */
+}
+
+int
+acpi_wakeup_machdep(struct acpi_softc *sc, int state,
+    int sleep_result, int intr_enabled)
+{
+
+       if (sleep_result == -1)
+               return (sleep_result);
+
+       if (intr_enabled == 0) {
+               /* Wakeup MD procedures in interrupt disabled context */
+               if (sleep_result == 1) {
+                       pmap_init_pat();
+                       load_cr3(susppcbs[0]->pcb_cr3);
+                       initializecpu();
+                       PCPU_SET(switchtime, 0);
+                       PCPU_SET(switchticks, ticks);
 #ifdef SMP
-       if (!CPU_EMPTY(&wakeup_cpus))
-               restart_cpus(wakeup_cpus);
+                       if (!CPU_EMPTY(&suspcpus))
+                               acpi_wakeup_cpus(sc, &suspcpus);
 #endif
+               }
 
-       mca_resume();
-       intr_resume();
-       intr_restore(rf);
-
-       AcpiSetFirmwareWakingVector(0);
+#ifdef SMP
+               if (!CPU_EMPTY(&suspcpus))
+                       restart_cpus(suspcpus);
+#endif
+               mca_resume();
+               intr_resume();
+       } else {
+               /* Wakeup MD procedures in interrupt enabled context */
+               AcpiSetFirmwareWakingVector(0);
 
-       if (ret == 0 && mem_range_softc.mr_op != NULL &&
-           mem_range_softc.mr_op->reinit != NULL)
-               mem_range_softc.mr_op->reinit(&mem_range_softc);
+               if (sleep_result == 1 && mem_range_softc.mr_op != NULL &&
+                   mem_range_softc.mr_op->reinit != NULL)
+                       mem_range_softc.mr_op->reinit(&mem_range_softc);
+       }
 
-       return (ret);
+       return (sleep_result);
 }
 
 static void *

Modified: head/sys/dev/acpica/acpi.c
==============================================================================
--- head/sys/dev/acpica/acpi.c  Fri Jun  1 15:02:23 2012        (r236402)
+++ head/sys/dev/acpica/acpi.c  Fri Jun  1 15:26:32 2012        (r236403)
@@ -2666,6 +2666,7 @@ acpi_EnterSleepState(struct acpi_softc *
     register_t intr;
     ACPI_STATUS status;
     enum acpi_sleep_state slp_state;
+    int sleep_result;
 
     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 
@@ -2746,7 +2747,16 @@ acpi_EnterSleepState(struct acpi_softc *
        DELAY(sc->acpi_sleep_delay * 1000000);
 
     if (state != ACPI_STATE_S1) {
-       if (acpi_sleep_machdep(sc, state))
+       intr = intr_disable();
+       sleep_result = acpi_sleep_machdep(sc, state);
+       acpi_wakeup_machdep(sc, state, sleep_result, 0);
+       AcpiLeaveSleepStatePrep(state, acpi_sleep_flags);
+       intr_restore(intr);
+
+       /* call acpi_wakeup_machdep() again with interrupt enabled */
+       acpi_wakeup_machdep(sc, state, sleep_result, 1);
+
+       if (sleep_result == -1)
                goto backout;
 
        /* Re-enable ACPI hardware on wakeup from sleep state 4. */
@@ -2775,10 +2785,8 @@ backout:
     }
     if (slp_state >= ACPI_SS_DEV_SUSPEND)
        DEVICE_RESUME(root_bus);
-    if (slp_state >= ACPI_SS_SLP_PREP) {
-       AcpiLeaveSleepStatePrep(state, acpi_sleep_flags);
+    if (slp_state >= ACPI_SS_SLP_PREP)
        AcpiLeaveSleepState(state);
-    }
     if (slp_state >= ACPI_SS_SLEPT) {
        acpi_resync_clock(sc);
        acpi_enable_fixed_events(sc);

Modified: head/sys/dev/acpica/acpivar.h
==============================================================================
--- head/sys/dev/acpica/acpivar.h       Fri Jun  1 15:02:23 2012        
(r236402)
+++ head/sys/dev/acpica/acpivar.h       Fri Jun  1 15:26:32 2012        
(r236403)
@@ -439,6 +439,8 @@ int         acpi_disabled(char *subsys);
 int            acpi_machdep_init(device_t dev);
 void           acpi_install_wakeup_handler(struct acpi_softc *sc);
 int            acpi_sleep_machdep(struct acpi_softc *sc, int state);
+int            acpi_wakeup_machdep(struct acpi_softc *sc, int state,
+                   int sleep_result, int intr_enabled);
 int            acpi_table_quirks(int *quirks);
 int            acpi_machdep_quirks(int *quirks);
 

Modified: head/sys/i386/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/i386/acpica/acpi_wakeup.c  Fri Jun  1 15:02:23 2012        
(r236402)
+++ head/sys/i386/acpica/acpi_wakeup.c  Fri Jun  1 15:26:32 2012        
(r236403)
@@ -74,6 +74,10 @@ extern struct pcb    **susppcbs;
 static struct pcb      **susppcbs;
 #endif
 
+#ifdef SMP
+static cpuset_t                suspcpus;
+#endif
+
 static void            *acpi_alloc_wakeup_handler(void);
 static void            acpi_stop_beep(void *);
 
@@ -212,22 +216,14 @@ acpi_wakeup_cpus(struct acpi_softc *sc, 
 int
 acpi_sleep_machdep(struct acpi_softc *sc, int state)
 {
-#ifdef SMP
-       cpuset_t        wakeup_cpus;
-#endif
-       register_t      cr3, rf;
        ACPI_STATUS     status;
-       struct pmap     *pm;
-       int             ret;
-
-       ret = -1;
 
        if (sc->acpi_wakeaddr == 0ul)
-               return (ret);
+               return (-1);    /* couldn't alloc wake memory */
 
 #ifdef SMP
-       wakeup_cpus = all_cpus;
-       CPU_CLR(PCPU_GET(cpuid), &wakeup_cpus);
+       suspcpus = all_cpus;
+       CPU_CLR(PCPU_GET(cpuid), &suspcpus);
 #endif
 
        if (acpi_resume_beep != 0)
@@ -235,28 +231,14 @@ acpi_sleep_machdep(struct acpi_softc *sc
 
        AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));
 
-       rf = intr_disable();
        intr_suspend();
 
-       /*
-        * Temporarily switch to the kernel pmap because it provides
-        * an identity mapping (setup at boot) for the low physical
-        * memory region containing the wakeup code.
-        */
-       pm = kernel_pmap;
-       cr3 = rcr3();
-#ifdef PAE
-       load_cr3(vtophys(pm->pm_pdpt));
-#else
-       load_cr3(vtophys(pm->pm_pdir));
-#endif
-
        if (suspendctx(susppcbs[0])) {
 #ifdef SMP
-               if (!CPU_EMPTY(&wakeup_cpus) &&
-                   suspend_cpus(wakeup_cpus) == 0) {
+               if (!CPU_EMPTY(&suspcpus) &&
+                   suspend_cpus(suspcpus) == 0) {
                        device_printf(sc->acpi_dev, "Failed to suspend APs\n");
-                       goto out;
+                       return (0);     /* couldn't sleep */
                }
 #endif
 
@@ -264,8 +246,6 @@ acpi_sleep_machdep(struct acpi_softc *sc
                WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
 
                WAKECODE_FIXUP(wakeup_cr4, register_t, susppcbs[0]->pcb_cr4);
-               WAKECODE_FIXUP(wakeup_cr3, register_t, susppcbs[0]->pcb_cr3);
-
                WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[0]);
 
                /* Call ACPICA to enter the desired sleep state */
@@ -278,41 +258,54 @@ acpi_sleep_machdep(struct acpi_softc *sc
                        device_printf(sc->acpi_dev,
                            "AcpiEnterSleepState failed - %s\n",
                            AcpiFormatException(status));
-                       goto out;
+                       return (0);     /* couldn't sleep */
                }
 
                for (;;)
                        ia32_pause();
-       } else {
-               pmap_init_pat();
-               initializecpu();
-               PCPU_SET(switchtime, 0);
-               PCPU_SET(switchticks, ticks);
+       }
+
+       return (1);     /* wakeup successfully */
+}
+
+int
+acpi_wakeup_machdep(struct acpi_softc *sc, int state,
+    int sleep_result, int intr_enabled)
+{
+
+       if (sleep_result == -1)
+               return (sleep_result);
+
+       if (intr_enabled == 0) {
+               /* Wakeup MD procedures in interrupt disabled context */
+               if (sleep_result == 1) {
+                       pmap_init_pat();
+                       load_cr3(susppcbs[0]->pcb_cr3);
+                       initializecpu();
+                       PCPU_SET(switchtime, 0);
+                       PCPU_SET(switchticks, ticks);
 #ifdef SMP
-               if (!CPU_EMPTY(&wakeup_cpus))
-                       acpi_wakeup_cpus(sc, &wakeup_cpus);
+                       if (!CPU_EMPTY(&suspcpus))
+                               acpi_wakeup_cpus(sc, &suspcpus);
 #endif
-               ret = 0;
-       }
+               }
 
-out:
 #ifdef SMP
-       if (!CPU_EMPTY(&wakeup_cpus))
-               restart_cpus(wakeup_cpus);
+               if (!CPU_EMPTY(&suspcpus))
+                       restart_cpus(suspcpus);
 #endif
+               mca_resume();
+               intr_resume();
+       } else {
+               /* Wakeup MD procedures in interrupt enabled context */
+               AcpiSetFirmwareWakingVector(0);
 
-       load_cr3(cr3);
-       mca_resume();
-       intr_resume();
-       intr_restore(rf);
-
-       AcpiSetFirmwareWakingVector(0);
-
-       if (ret == 0 && mem_range_softc.mr_op != NULL &&
-           mem_range_softc.mr_op->reinit != NULL)
-               mem_range_softc.mr_op->reinit(&mem_range_softc);
+               if (sleep_result == 1 && mem_range_softc.mr_op != NULL &&
+                   mem_range_softc.mr_op->reinit != NULL)
+                       mem_range_softc.mr_op->reinit(&mem_range_softc);
+       }
 
-       return (ret);
+       return (sleep_result);
 }
 
 static void *
@@ -373,6 +366,16 @@ acpi_install_wakeup_handler(struct acpi_
 
        /* Save pointers to some global data. */
        WAKECODE_FIXUP(wakeup_ret, void *, resumectx);
+       /*
+        * Temporarily switch to the kernel pmap because it provides
+        * an identity mapping (setup at boot) for the low physical
+        * memory region containing the wakeup code.
+        */
+#ifdef PAE
+       WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdpt));
+#else
+       WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdir));
+#endif
 
        if (bootverbose)
                device_printf(sc->acpi_dev, "wakeup code va %#x pa %#jx\n",

Modified: head/sys/ia64/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/ia64/acpica/acpi_wakeup.c  Fri Jun  1 15:02:23 2012        
(r236402)
+++ head/sys/ia64/acpica/acpi_wakeup.c  Fri Jun  1 15:26:32 2012        
(r236403)
@@ -39,6 +39,13 @@ acpi_sleep_machdep(struct acpi_softc *sc
        return (0);
 }
 
+int
+acpi_wakeup_machdep(struct acpi_softc *sc, int state,
+    int sleep_result, int intr_enabled)
+{
+       return (0);
+}
+
 void
 acpi_install_wakeup_handler(struct acpi_softc *sc)
 {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to