Index: dev/acpica/acpi.c =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/acpi.c,v retrieving revision 1.320 diff -u -r1.320 acpi.c --- dev/acpica/acpi.c 29 May 2012 05:28:34 -0000 1.320 +++ dev/acpica/acpi.c 31 May 2012 18:18:29 -0000 @@ -2666,6 +2666,7 @@ 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 @@ 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. */ @@ -2776,7 +2786,6 @@ if (slp_state >= ACPI_SS_DEV_SUSPEND) DEVICE_RESUME(root_bus); if (slp_state >= ACPI_SS_SLP_PREP) { - AcpiLeaveSleepStatePrep(state, acpi_sleep_flags); AcpiLeaveSleepState(state); } if (slp_state >= ACPI_SS_SLEPT) { Index: dev/acpica/acpivar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/acpivar.h,v retrieving revision 1.130 diff -u -r1.130 acpivar.h --- dev/acpica/acpivar.h 17 May 2012 17:58:53 -0000 1.130 +++ dev/acpica/acpivar.h 31 May 2012 18:13:31 -0000 @@ -439,6 +439,8 @@ 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); Index: amd64/acpica/acpi_wakeup.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/acpica/acpi_wakeup.c,v retrieving revision 1.53 diff -u -r1.53 acpi_wakeup.c --- amd64/acpica/acpi_wakeup.c 30 Mar 2012 17:03:06 -0000 1.53 +++ amd64/acpica/acpi_wakeup.c 31 May 2012 18:26:11 -0000 @@ -76,6 +76,10 @@ 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,10 +224,6 @@ 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; @@ -232,9 +232,11 @@ if (sc->acpi_wakeaddr == 0ul) return (ret); + ret = 0; + #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,14 +244,13 @@ 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; } @@ -281,36 +282,52 @@ for (;;) ia32_pause(); - } else { + } else + ret = 1; +out: + return (ret); +} + +int +acpi_wakeup_machdep(struct acpi_softc *sc, int state, + int sleep_result, int intr_enabled) +{ + + if (sleep_result == -1) + goto out; + + if (intr_enabled) { + 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); + + goto out; + } + + 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(); - 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); - - return (ret); +out: + return (sleep_result); } static void * Index: i386/acpica/acpi_wakeup.c =================================================================== RCS file: /home/ncvs/src/sys/i386/acpica/acpi_wakeup.c,v retrieving revision 1.57 diff -u -r1.57 acpi_wakeup.c --- i386/acpica/acpi_wakeup.c 19 May 2012 02:31:38 -0000 1.57 +++ i386/acpica/acpi_wakeup.c 31 May 2012 18:25:27 -0000 @@ -74,6 +74,10 @@ 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,12 +216,7 @@ 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; @@ -225,9 +224,11 @@ if (sc->acpi_wakeaddr == 0ul) return (ret); + ret = 0; + #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,26 +236,12 @@ 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; } @@ -264,8 +251,6 @@ 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 */ @@ -283,36 +268,52 @@ for (;;) ia32_pause(); - } else { + } else + ret = 1; +out: + return (ret); +} + +int +acpi_wakeup_machdep(struct acpi_softc *sc, int state, + int sleep_result, int intr_enabled) +{ + + if (sleep_result == -1) + goto out; + + if (intr_enabled) { + 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); + + goto out; + } + + 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 - 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); - - return (ret); +out: + return (sleep_result); } static void * @@ -373,6 +374,16 @@ /* 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", Index: ia64/acpica/acpi_wakeup.c =================================================================== RCS file: /home/ncvs/src/sys/ia64/acpica/acpi_wakeup.c,v retrieving revision 1.4 diff -u -r1.4 acpi_wakeup.c --- ia64/acpica/acpi_wakeup.c 5 Jun 2009 18:44:36 -0000 1.4 +++ ia64/acpica/acpi_wakeup.c 31 May 2012 18:33:04 -0000 @@ -39,6 +39,13 @@ 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) {