Author: avg
Date: Wed Mar  6 10:23:56 2013
New Revision: 247881
URL: http://svnweb.freebsd.org/changeset/base/247881

Log:
  MFC r233579,236403,236408: make interrupt flags management closer to head
  
  r233579: Restore interrupt state after executing AcpiEnterSleepState().
  r236403,236408: acpi_wakeup_machdep/acpi_sleep_machdep
  
  The merged changes are modified a bit to account for lots of missing
  acpi and acpica MFCs.
  For the same reason MFC to stable/8 is not practical.
  
  MFC slackers: iwasaki, jkim

Modified:
  stable/9/sys/amd64/acpica/acpi_wakeup.c
  stable/9/sys/dev/acpica/acpi.c
  stable/9/sys/dev/acpica/acpivar.h
  stable/9/sys/i386/acpica/acpi_wakeup.c
  stable/9/sys/ia64/acpica/acpi_wakeup.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- stable/9/sys/amd64/acpica/acpi_wakeup.c     Wed Mar  6 09:53:38 2013        
(r247880)
+++ stable/9/sys/amd64/acpica/acpi_wakeup.c     Wed Mar  6 10:23:56 2013        
(r247881)
@@ -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: stable/9/sys/dev/acpica/acpi.c
==============================================================================
--- stable/9/sys/dev/acpica/acpi.c      Wed Mar  6 09:53:38 2013        
(r247880)
+++ stable/9/sys/dev/acpica/acpi.c      Wed Mar  6 10:23:56 2013        
(r247881)
@@ -1960,6 +1960,7 @@ static void
 acpi_shutdown_final(void *arg, int howto)
 {
     struct acpi_softc *sc = (struct acpi_softc *)arg;
+    register_t intr;
     ACPI_STATUS status;
 
     /*
@@ -1975,13 +1976,15 @@ acpi_shutdown_final(void *arg, int howto
            return;
        }
        device_printf(sc->acpi_dev, "Powering system off\n");
-       ACPI_DISABLE_IRQS();
+       intr = intr_disable();
        status = AcpiEnterSleepState(ACPI_STATE_S5);
-       if (ACPI_FAILURE(status))
+       if (ACPI_FAILURE(status)) {
+           intr_restore(intr);
            device_printf(sc->acpi_dev, "power-off failed - %s\n",
                AcpiFormatException(status));
-       else {
+       } else {
            DELAY(1000000);
+           intr_restore(intr);
            device_printf(sc->acpi_dev, "power-off failed - timeout\n");
        }
     } else if ((howto & RB_HALT) == 0 && sc->acpi_handle_reboot) {
@@ -2652,8 +2655,10 @@ enum acpi_sleep_state {
 static ACPI_STATUS
 acpi_EnterSleepState(struct acpi_softc *sc, int state)
 {
-    ACPI_STATUS        status;
+    register_t intr;
+    ACPI_STATUS status;
     enum acpi_sleep_state slp_state;
+    int sleep_result;
 
     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 
@@ -2733,15 +2738,24 @@ acpi_EnterSleepState(struct acpi_softc *
     if (sc->acpi_sleep_delay > 0)
        DELAY(sc->acpi_sleep_delay * 1000000);
 
+    intr = intr_disable();
     if (state != ACPI_STATE_S1) {
-       acpi_sleep_machdep(sc, state);
+       sleep_result = acpi_sleep_machdep(sc, state);
+       acpi_wakeup_machdep(sc, state, sleep_result, 0);
+       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. */
        if (state == ACPI_STATE_S4)
            AcpiEnable();
     } else {
-       ACPI_DISABLE_IRQS();
        status = AcpiEnterSleepState(state);
+       intr_restore(intr);
        if (ACPI_FAILURE(status)) {
            device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
                          AcpiFormatException(status));

Modified: stable/9/sys/dev/acpica/acpivar.h
==============================================================================
--- stable/9/sys/dev/acpica/acpivar.h   Wed Mar  6 09:53:38 2013        
(r247880)
+++ stable/9/sys/dev/acpica/acpivar.h   Wed Mar  6 10:23:56 2013        
(r247881)
@@ -434,6 +434,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: stable/9/sys/i386/acpica/acpi_wakeup.c
==============================================================================
--- stable/9/sys/i386/acpica/acpi_wakeup.c      Wed Mar  6 09:53:38 2013        
(r247880)
+++ stable/9/sys/i386/acpica/acpi_wakeup.c      Wed Mar  6 10:23:56 2013        
(r247881)
@@ -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: stable/9/sys/ia64/acpica/acpi_wakeup.c
==============================================================================
--- stable/9/sys/ia64/acpica/acpi_wakeup.c      Wed Mar  6 09:53:38 2013        
(r247880)
+++ stable/9/sys/ia64/acpica/acpi_wakeup.c      Wed Mar  6 10:23:56 2013        
(r247881)
@@ -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)
 {
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "[email protected]"

Reply via email to