Date: Fri, 1 Jun 2012 15:26:33 +0000 (UTC) From: Mitsuru IWASAKI <iwasaki@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r236403 - in head/sys: amd64/acpica dev/acpica i386/acpica ia64/acpica Message-ID: <201206011526.q51FQX8h027075@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206011526.q51FQX8h027075>