Page MenuHomeFreeBSD

D48720.diff
No OneTemporary

D48720.diff

diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -58,6 +58,7 @@
#endif
#include <machine/resource.h>
#include <machine/bus.h>
+#include <machine/intr_machdep.h>
#include <sys/rman.h>
#include <isa/isavar.h>
#include <isa/pnpvar.h>
@@ -106,7 +107,7 @@
int acpi_quirks;
/* Supported sleep states. */
-static BOOLEAN acpi_sleep_states[ACPI_S_STATE_COUNT];
+static BOOLEAN acpi_supported_stypes[STYPE_COUNT];
static void acpi_lookup(void *arg, const char *name, device_t *dev);
static int acpi_modevent(struct module *mod, int event, void *junk);
@@ -157,19 +158,19 @@
void *context, void **status);
static void acpi_sleep_enable(void *arg);
static ACPI_STATUS acpi_sleep_disable(struct acpi_softc *sc);
-static ACPI_STATUS acpi_EnterSleepState(struct acpi_softc *sc, int state);
+static ACPI_STATUS acpi_EnterSleepState(struct acpi_softc *sc, enum sleep_type stype);
static void acpi_shutdown_final(void *arg, int howto);
static void acpi_enable_fixed_events(struct acpi_softc *sc);
static void acpi_resync_clock(struct acpi_softc *sc);
-static int acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate);
-static int acpi_wake_run_prep(ACPI_HANDLE handle, int sstate);
-static int acpi_wake_prep_walk(int sstate);
+static int acpi_wake_sleep_prep(ACPI_HANDLE handle, enum sleep_type stype);
+static int acpi_wake_run_prep(ACPI_HANDLE handle, enum sleep_type stype);
+static int acpi_wake_prep_walk(enum sleep_type stype);
static int acpi_wake_sysctl_walk(device_t dev);
static int acpi_wake_set_sysctl(SYSCTL_HANDLER_ARGS);
-static void acpi_system_eventhandler_sleep(void *arg, int state);
-static void acpi_system_eventhandler_wakeup(void *arg, int state);
-static int acpi_sname2sstate(const char *sname);
-static const char *acpi_sstate2sname(int sstate);
+static void acpi_system_eventhandler_sleep(void *arg, enum sleep_type stype);
+static void acpi_system_eventhandler_wakeup(void *arg, enum sleep_type stype);
+static enum sleep_type acpi_sname2stype(const char *sname);
+static const char *acpi_stype2sname(enum sleep_type stype);
static int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
static int acpi_debug_objects_sysctl(SYSCTL_HANDLER_ARGS);
@@ -567,26 +568,26 @@
SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "power_button_state",
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
- &sc->acpi_power_button_sx, 0, acpi_sleep_state_sysctl, "A",
+ &sc->acpi_power_button_stype, 0, acpi_sleep_state_sysctl, "A",
"Power button ACPI sleep state.");
SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "sleep_button_state",
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
- &sc->acpi_sleep_button_sx, 0, acpi_sleep_state_sysctl, "A",
+ &sc->acpi_sleep_button_stype, 0, acpi_sleep_state_sysctl, "A",
"Sleep button ACPI sleep state.");
SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "lid_switch_state",
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
- &sc->acpi_lid_switch_sx, 0, acpi_sleep_state_sysctl, "A",
+ &sc->acpi_lid_switch_stype, 0, acpi_sleep_state_sysctl, "A",
"Lid ACPI sleep state. Set to S3 if you want to suspend your laptop when close the Lid.");
SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "standby_state",
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
- &sc->acpi_standby_sx, 0, acpi_sleep_state_sysctl, "A", "");
+ &sc->acpi_standby_stype, 0, acpi_sleep_state_sysctl, "A", "");
SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "suspend_state",
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
- &sc->acpi_suspend_sx, 0, acpi_sleep_state_sysctl, "A", "");
+ &sc->acpi_suspend_stype, 0, acpi_sleep_state_sysctl, "A", "");
SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "sleep_delay", CTLFLAG_RW, &sc->acpi_sleep_delay, 0,
"sleep delay in seconds");
@@ -624,33 +625,51 @@
sc->acpi_s4bios = 1;
#endif
- /* Probe all supported sleep states. */
- acpi_sleep_states[ACPI_STATE_S0] = TRUE;
- for (state = ACPI_STATE_S1; state < ACPI_S_STATE_COUNT; state++)
+ /*
+ * Probe all supported ACPI sleep states. Awake (S0) and suspend-to-idle
+ * are always supported.
+ */
+ acpi_supported_stypes[STYPE_AWAKE] = TRUE;
+ acpi_supported_stypes[STYPE_SUSPEND_TO_IDLE] = TRUE;
+ for (state = ACPI_STATE_S1; state <= ACPI_STATE_S5; state++)
if (ACPI_SUCCESS(AcpiEvaluateObject(ACPI_ROOT_OBJECT,
__DECONST(char *, AcpiGbl_SleepStateNames[state]), NULL, NULL)) &&
ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB)))
- acpi_sleep_states[state] = TRUE;
+ acpi_supported_stypes[state] = TRUE;
/*
* Dispatch the default sleep state to devices. The lid switch is set
- * to UNKNOWN by default to avoid surprising users.
+ * to UNKNOWN by default to avoid surprising users. The suspend button
+ * prefers STANDBY (S3) over SUSPEND_TO_IDLE at the moment, as
+ * SUSPEND_TO_IDLE may not work as well at the moment.
+ */
+ sc->acpi_power_button_stype = acpi_supported_stypes[STYPE_POWEROFF] ?
+ STYPE_POWEROFF : STYPE_UNKNOWN;
+ sc->acpi_lid_switch_stype = STYPE_UNKNOWN;
+ sc->acpi_standby_stype = acpi_supported_stypes[STYPE_STANDBY] ?
+ STYPE_STANDBY : STYPE_UNKNOWN;
+ sc->acpi_hibernate_stype = acpi_supported_stypes[STYPE_HIBERNATE] ?
+ STYPE_HIBERNATE : STYPE_UNKNOWN;
+ sc->acpi_suspend_stype = STYPE_UNKNOWN;
+
+ if (acpi_supported_stypes[STYPE_SUSPEND])
+ sc->acpi_suspend_stype = STYPE_SUSPEND;
+ else if (acpi_supported_stypes[STYPE_SUSPEND_TO_IDLE])
+ sc->acpi_suspend_stype = STYPE_SUSPEND_TO_IDLE;
+
+ /*
+ * Pick the first valid sleep state for the sleep button default. If that
+ * state was S4 and we support SUSPEND_TO_IDLE, set it to that.
*/
- sc->acpi_power_button_sx = acpi_sleep_states[ACPI_STATE_S5] ?
- ACPI_STATE_S5 : ACPI_STATE_UNKNOWN;
- sc->acpi_lid_switch_sx = ACPI_STATE_UNKNOWN;
- sc->acpi_standby_sx = acpi_sleep_states[ACPI_STATE_S1] ?
- ACPI_STATE_S1 : ACPI_STATE_UNKNOWN;
- sc->acpi_suspend_sx = acpi_sleep_states[ACPI_STATE_S3] ?
- ACPI_STATE_S3 : ACPI_STATE_UNKNOWN;
-
- /* Pick the first valid sleep state for the sleep button default. */
- sc->acpi_sleep_button_sx = ACPI_STATE_UNKNOWN;
+ sc->acpi_sleep_button_stype = ACPI_STATE_UNKNOWN;
for (state = ACPI_STATE_S1; state <= ACPI_STATE_S4; state++)
- if (acpi_sleep_states[state]) {
- sc->acpi_sleep_button_sx = state;
+ if (acpi_supported_stypes[state]) {
+ sc->acpi_sleep_button_stype = state;
break;
}
+ if (sc->acpi_sleep_button_stype == STYPE_HIBERNATE &&
+ acpi_supported_stypes[STYPE_SUSPEND_TO_IDLE])
+ sc->acpi_sleep_button_stype = STYPE_SUSPEND_TO_IDLE;
acpi_enable_fixed_events(sc);
@@ -673,7 +692,7 @@
/* Flag our initial states. */
sc->acpi_enabled = TRUE;
- sc->acpi_sstate = ACPI_STATE_S0;
+ sc->acpi_stype = STYPE_AWAKE;
sc->acpi_sleep_disabled = TRUE;
/* Create the control device */
@@ -711,6 +730,26 @@
return_VALUE (error);
}
+static int
+acpi_stype2sstate(enum sleep_type stype)
+{
+
+ switch (stype) {
+ case STYPE_AWAKE:
+ case STYPE_STANDBY:
+ case STYPE_STANDBY_S2:
+ case STYPE_SUSPEND:
+ case STYPE_HIBERNATE:
+ case STYPE_POWEROFF:
+ return stype;
+ case STYPE_SUSPEND_TO_IDLE:
+ return ACPI_STATE_S3;
+ case STYPE_COUNT:
+ case STYPE_UNKNOWN:
+ return ACPI_STATE_UNKNOWN;
+ }
+}
+
static void
acpi_set_power_children(device_t dev, int state)
{
@@ -1977,7 +2016,7 @@
* Note illegal _S0D is evaluated because some systems expect this.
*/
sc = device_get_softc(bus);
- snprintf(sxd, sizeof(sxd), "_S%dD", sc->acpi_sstate);
+ snprintf(sxd, sizeof(sxd), "_S%dD", acpi_stype2sstate(sc->acpi_stype));
status = acpi_GetInteger(handle, sxd, dstate);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
device_printf(dev, "failed to get %s on %s: %s\n", sxd,
@@ -3071,9 +3110,9 @@
{
struct acpi_softc *sc = (struct acpi_softc *)context;
- if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_sstate)))
+ if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_stype)))
device_printf(sc->acpi_dev, "force sleep state S%d failed\n",
- sc->acpi_next_sstate);
+ sc->acpi_next_stype);
}
static void
@@ -3100,24 +3139,23 @@
* acks are in.
*/
int
-acpi_ReqSleepState(struct acpi_softc *sc, int state)
+acpi_ReqSleepState(struct acpi_softc *sc, enum sleep_type stype)
{
#if defined(__amd64__) || defined(__i386__)
struct apm_clone_data *clone;
ACPI_STATUS status;
- if (state < ACPI_STATE_S1 || state > ACPI_S_STATES_MAX)
+ if (stype < STYPE_AWAKE || stype >= STYPE_COUNT)
return (EINVAL);
- if (!acpi_sleep_states[state])
+ if (!acpi_supported_stypes[stype])
return (EOPNOTSUPP);
/*
* If a reboot/shutdown/suspend request is already in progress or
* suspend is blocked due to an upcoming shutdown, just return.
*/
- if (rebooting || sc->acpi_next_sstate != 0 || suspend_blocked) {
+ if (rebooting || sc->acpi_next_stype != STYPE_AWAKE || suspend_blocked)
return (0);
- }
/* Wait until sleep is enabled. */
while (sc->acpi_sleep_disabled) {
@@ -3126,12 +3164,12 @@
ACPI_LOCK(acpi);
- sc->acpi_next_sstate = state;
+ sc->acpi_next_stype = stype;
/* S5 (soft-off) should be entered directly with no waiting. */
- if (state == ACPI_STATE_S5) {
+ if (stype == STYPE_POWEROFF) {
ACPI_UNLOCK(acpi);
- status = acpi_EnterSleepState(sc, state);
+ status = acpi_EnterSleepState(sc, stype);
return (ACPI_SUCCESS(status) ? 0 : ENXIO);
}
@@ -3147,7 +3185,7 @@
/* If devd(8) is not running, immediately enter the sleep state. */
if (!devctl_process_running()) {
ACPI_UNLOCK(acpi);
- status = acpi_EnterSleepState(sc, state);
+ status = acpi_EnterSleepState(sc, stype);
return (ACPI_SUCCESS(status) ? 0 : ENXIO);
}
@@ -3162,11 +3200,12 @@
ACPI_UNLOCK(acpi);
/* Now notify devd(8) also. */
- acpi_UserNotify("Suspend", ACPI_ROOT_OBJECT, state);
+ acpi_UserNotify("Suspend", ACPI_ROOT_OBJECT, stype);
return (0);
#else
- /* This platform does not support acpi suspend/resume. */
+ device_printf(sc->acpi_dev, "ACPI suspend not supported on this platform"
+ "(TODO suspend to idle should be, however)\n");
return (EOPNOTSUPP);
#endif
}
@@ -3185,17 +3224,17 @@
struct acpi_softc *sc;
int ret, sleeping;
- /* If no pending sleep state, return an error. */
+ /* If no pending sleep type, return an error. */
ACPI_LOCK(acpi);
sc = clone->acpi_sc;
- if (sc->acpi_next_sstate == 0) {
+ if (sc->acpi_next_stype == STYPE_AWAKE) {
ACPI_UNLOCK(acpi);
return (ENXIO);
}
/* Caller wants to abort suspend process. */
if (error) {
- sc->acpi_next_sstate = 0;
+ sc->acpi_next_stype = STYPE_AWAKE;
callout_stop(&sc->susp_force_to);
device_printf(sc->acpi_dev,
"listener on %s cancelled the pending suspend\n",
@@ -3225,12 +3264,13 @@
ACPI_UNLOCK(acpi);
ret = 0;
if (sleeping) {
- if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_sstate)))
+ if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_stype)))
ret = ENODEV;
}
return (ret);
#else
- /* This platform does not support acpi suspend/resume. */
+ device_printf(sc->acpi_dev, "ACPI suspend not supported on this platform"
+ "(TODO suspend to idle should be, however)\n");
return (EOPNOTSUPP);
#endif
}
@@ -3269,34 +3309,141 @@
}
enum acpi_sleep_state {
- ACPI_SS_NONE,
- ACPI_SS_GPE_SET,
- ACPI_SS_DEV_SUSPEND,
- ACPI_SS_SLP_PREP,
- ACPI_SS_SLEPT,
+ ACPI_SS_NONE = 0,
+ ACPI_SS_GPE_SET = 1 << 0,
+ ACPI_SS_DEV_SUSPEND = 1 << 1,
+ ACPI_SS_SPMC_ENTER = 1 << 2,
+ ACPI_SS_SLP_PREP = 1 << 3,
+ ACPI_SS_SLEPT = 1 << 4,
};
+static void
+do_standby(struct acpi_softc *sc, enum acpi_sleep_state *slp_state,
+ register_t rflags)
+{
+ ACPI_STATUS status;
+
+ status = AcpiEnterSleepState(STYPE_STANDBY);
+ intr_restore(rflags);
+ AcpiLeaveSleepStatePrep(STYPE_STANDBY);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
+ AcpiFormatException(status));
+ return;
+ }
+ *slp_state |= ACPI_SS_SLEPT;
+}
+
+static void
+do_sleep(struct acpi_softc *sc, enum acpi_sleep_state *slp_state,
+ register_t rflags, int state)
+{
+ int sleep_result;
+ ACPI_EVENT_STATUS power_button_status;
+
+ MPASS(state == ACPI_STATE_S3 || state == ACPI_STATE_S4);
+
+ sleep_result = acpi_sleep_machdep(sc, state);
+ acpi_wakeup_machdep(sc, state, sleep_result, 0);
+
+ if (sleep_result == 1 && state != ACPI_STATE_S4) {
+ /*
+ * XXX According to ACPI specification SCI_EN bit should be restored
+ * by ACPI platform (BIOS, firmware) to its pre-sleep state.
+ * Unfortunately some BIOSes fail to do that and that leads to
+ * unexpected and serious consequences during wake up like a system
+ * getting stuck in SMI handlers.
+ * This hack is picked up from Linux, which claims that it follows
+ * Windows behavior.
+ */
+ AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, ACPI_ENABLE_EVENT);
+ }
+
+ if (sleep_result == 1 && state == ACPI_STATE_S3) {
+ /*
+ * Prevent misinterpretation of the wakeup by power button
+ * as a request for power off.
+ * Ideally we should post an appropriate wakeup event,
+ * perhaps using acpi_event_power_button_wake or alike.
+ *
+ * Clearing of power button status after wakeup is mandated
+ * by ACPI specification in section "Fixed Power Button".
+ *
+ * XXX As of ACPICA 20121114 AcpiGetEventStatus provides
+ * status as 0/1 corresponding to inactive/active despite
+ * its type being ACPI_EVENT_STATUS. In other words,
+ * we should not test for ACPI_EVENT_FLAG_SET for time being.
+ */
+ if (ACPI_SUCCESS(AcpiGetEventStatus(ACPI_EVENT_POWER_BUTTON,
+ &power_button_status)) && power_button_status != 0) {
+ AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
+ device_printf(sc->acpi_dev, "cleared fixed power button status\n");
+ }
+ }
+
+ intr_restore(rflags);
+
+ /* call acpi_wakeup_machdep() again with interrupt enabled */
+ acpi_wakeup_machdep(sc, state, sleep_result, 1);
+
+ AcpiLeaveSleepStatePrep(state);
+
+ if (sleep_result == -1)
+ return;
+
+ /* Re-enable ACPI hardware on wakeup from sleep state 4. */
+ if (state == ACPI_STATE_S4)
+ AcpiEnable();
+ *slp_state |= ACPI_SS_SLEPT;
+}
+
+static void
+do_idle(struct acpi_softc *sc, enum acpi_sleep_state *slp_state,
+ register_t rflags)
+{
+
+ intr_suspend();
+
+ /*
+ * The CPU will exit idle when interrupted, so we want to minimize the
+ * number of interrupts it can receive while idle. We do this by only
+ * allowing SCI (system control interrupt) interrupts, which are used by
+ * the ACPI firmware to send wake GPEs to the OS.
+ *
+ * XXX We might still receive other spurious non-wake GPEs from noisy
+ * devices that can't be disabled, so this will need to end up being a
+ * suspend-to-idle loop which, when breaking out of idle, will check the
+ * reason for the wakeup and immediately idle the CPU again if it was not a
+ * proper wake event.
+ */
+ intr_enable_src(AcpiGbl_FADT.SciInterrupt);
+
+ cpu_idle(0);
+
+ intr_resume(false);
+ intr_restore(rflags);
+ *slp_state |= ACPI_SS_SLEPT;
+}
+
/*
* Enter the desired system sleep state.
*
- * Currently we support S1-S5 but S4 is only S4BIOS
+ * Currently we support S1-S5 and suspend-to-idle, but S4 is only S4BIOS.
*/
static ACPI_STATUS
-acpi_EnterSleepState(struct acpi_softc *sc, int state)
+acpi_EnterSleepState(struct acpi_softc *sc, enum sleep_type stype)
{
- register_t intr;
+ register_t rflags;
ACPI_STATUS status;
- ACPI_EVENT_STATUS power_button_status;
enum acpi_sleep_state slp_state;
- int sleep_result;
ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
- if (state < ACPI_STATE_S1 || state > ACPI_S_STATES_MAX)
+ if (stype <= STYPE_AWAKE || stype >= STYPE_COUNT)
return_ACPI_STATUS (AE_BAD_PARAMETER);
- if (!acpi_sleep_states[state]) {
- device_printf(sc->acpi_dev, "Sleep state S%d not supported by BIOS\n",
- state);
+ if (!acpi_supported_stypes[stype]) {
+ device_printf(sc->acpi_dev, "Sleep type %s not supported on this "
+ "platform\n", acpi_stype2sname(stype));
return (AE_SUPPORT);
}
@@ -3308,7 +3455,7 @@
return (status);
}
- if (state == ACPI_STATE_S5) {
+ if (stype == STYPE_POWEROFF) {
/*
* Shut down cleanly and power off. This will call us back through the
* shutdown handlers.
@@ -3336,17 +3483,17 @@
#endif
/*
- * Be sure to hold Giant across DEVICE_SUSPEND/RESUME
+ * Be sure to hold bus topology lock across DEVICE_SUSPEND/RESUME.
*/
bus_topo_lock();
slp_state = ACPI_SS_NONE;
- sc->acpi_sstate = state;
+ sc->acpi_stype = stype;
/* Enable any GPEs as appropriate and requested by the user. */
- acpi_wake_prep_walk(state);
- slp_state = ACPI_SS_GPE_SET;
+ acpi_wake_prep_walk(stype);
+ slp_state |= ACPI_SS_GPE_SET;
/*
* Inform all devices that we are going to sleep. If at least one
@@ -3357,112 +3504,99 @@
* bus interface does not provide for this.
*/
if (DEVICE_SUSPEND(root_bus) != 0) {
- device_printf(sc->acpi_dev, "device_suspend failed\n");
- goto backout;
+ device_printf(sc->acpi_dev, "device_suspend failed\n");
+ goto backout;
}
- slp_state = ACPI_SS_DEV_SUSPEND;
+ slp_state |= ACPI_SS_DEV_SUSPEND;
+ AcpiOsSleep(1000);
- status = AcpiEnterSleepStatePrep(state);
- if (ACPI_FAILURE(status)) {
- device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n",
- AcpiFormatException(status));
- goto backout;
+ if (sc->acpi_spmc_device != NULL) {
+ MPASS(sc->acpi_spmc_enter != NULL);
+ if (sc->acpi_spmc_enter(sc->acpi_spmc_device) != 0)
+ device_printf(sc->acpi_dev, "failed to run SPMC entry\n");
+ else
+ slp_state |= ACPI_SS_SPMC_ENTER;
}
- slp_state = ACPI_SS_SLP_PREP;
+
+ if (stype != STYPE_SUSPEND_TO_IDLE) {
+ status = AcpiEnterSleepStatePrep(stype);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n",
+ AcpiFormatException(status));
+ goto backout;
+ }
+ }
+ slp_state |= ACPI_SS_SLP_PREP;
if (sc->acpi_sleep_delay > 0)
DELAY(sc->acpi_sleep_delay * 1000000);
suspendclock();
- intr = intr_disable();
- if (state != ACPI_STATE_S1) {
- sleep_result = acpi_sleep_machdep(sc, state);
- acpi_wakeup_machdep(sc, state, sleep_result, 0);
-
+ rflags = intr_disable();
+ switch (stype) {
+ case STYPE_STANDBY:
+ case STYPE_STANDBY_S2:
+ do_standby(sc, &slp_state, rflags);
+ break;
+ case STYPE_SUSPEND:
+ case STYPE_HIBERNATE:
/*
- * XXX According to ACPI specification SCI_EN bit should be restored
- * by ACPI platform (BIOS, firmware) to its pre-sleep state.
- * Unfortunately some BIOSes fail to do that and that leads to
- * unexpected and serious consequences during wake up like a system
- * getting stuck in SMI handlers.
- * This hack is picked up from Linux, which claims that it follows
- * Windows behavior.
+ * Can pass suspend/hibernate enum sleep_type, as they are directly
+ * mapped to ACPI S-states.
*/
- if (sleep_result == 1 && state != ACPI_STATE_S4)
- AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, ACPI_ENABLE_EVENT);
-
- if (sleep_result == 1 && state == ACPI_STATE_S3) {
- /*
- * Prevent mis-interpretation of the wakeup by power button
- * as a request for power off.
- * Ideally we should post an appropriate wakeup event,
- * perhaps using acpi_event_power_button_wake or alike.
- *
- * Clearing of power button status after wakeup is mandated
- * by ACPI specification in section "Fixed Power Button".
- *
- * XXX As of ACPICA 20121114 AcpiGetEventStatus provides
- * status as 0/1 corressponding to inactive/active despite
- * its type being ACPI_EVENT_STATUS. In other words,
- * we should not test for ACPI_EVENT_FLAG_SET for time being.
- */
- if (ACPI_SUCCESS(AcpiGetEventStatus(ACPI_EVENT_POWER_BUTTON,
- &power_button_status)) && power_button_status != 0) {
- AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
- device_printf(sc->acpi_dev,
- "cleared fixed power button status\n");
- }
- }
-
- intr_restore(intr);
-
- /* call acpi_wakeup_machdep() again with interrupt enabled */
- acpi_wakeup_machdep(sc, state, sleep_result, 1);
-
- AcpiLeaveSleepStatePrep(state);
-
- if (sleep_result == -1)
- goto backout;
-
- /* Re-enable ACPI hardware on wakeup from sleep state 4. */
- if (state == ACPI_STATE_S4)
- AcpiEnable();
- } else {
- status = AcpiEnterSleepState(state);
- intr_restore(intr);
- AcpiLeaveSleepStatePrep(state);
- if (ACPI_FAILURE(status)) {
- device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
- AcpiFormatException(status));
- goto backout;
- }
+ do_sleep(sc, &slp_state, rflags, stype);
+ break;
+ case STYPE_SUSPEND_TO_IDLE:
+ do_idle(sc, &slp_state, rflags);
+ break;
+ case STYPE_AWAKE:
+ case STYPE_POWEROFF:
+ case STYPE_COUNT:
+ case STYPE_UNKNOWN:
+ __unreachable();
}
- slp_state = ACPI_SS_SLEPT;
/*
* Back out state according to how far along we got in the suspend
* process. This handles both the error and success cases.
*/
backout:
- if (slp_state >= ACPI_SS_SLP_PREP)
+ if (slp_state & ACPI_SS_SLP_PREP) {
resumeclock();
- if (slp_state >= ACPI_SS_GPE_SET) {
- acpi_wake_prep_walk(state);
- sc->acpi_sstate = ACPI_STATE_S0;
+ slp_state &= ~ACPI_SS_SLP_PREP;
+ }
+ if (slp_state & ACPI_SS_GPE_SET) {
+ acpi_wake_prep_walk(stype);
+ sc->acpi_stype = STYPE_AWAKE;
+ slp_state &= ~ACPI_SS_GPE_SET;
}
- if (slp_state >= ACPI_SS_DEV_SUSPEND)
+ if (slp_state & ACPI_SS_SPMC_ENTER) {
+ MPASS(sc->acpi_spmc_device != NULL);
+ MPASS(sc->acpi_spmc_exit != NULL);
+ if (sc->acpi_spmc_exit(sc->acpi_spmc_device) != 0)
+ device_printf(sc->acpi_dev, "failed to run SPMC exit\n");
+ slp_state &= ~ACPI_SS_SPMC_ENTER;
+ }
+ if (slp_state & ACPI_SS_DEV_SUSPEND) {
DEVICE_RESUME(root_bus);
- if (slp_state >= ACPI_SS_SLP_PREP)
- AcpiLeaveSleepState(state);
- if (slp_state >= ACPI_SS_SLEPT) {
+ slp_state &= ~ACPI_SS_DEV_SUSPEND;
+ }
+ if (stype != STYPE_SUSPEND_TO_IDLE && slp_state & ACPI_SS_SLP_PREP) {
+ AcpiLeaveSleepState(stype);
+ slp_state &= ~ACPI_SS_SLP_PREP;
+ }
+ if (slp_state & ACPI_SS_SLEPT) {
#if defined(__i386__) || defined(__amd64__)
/* NB: we are still using ACPI timecounter at this point. */
resume_TSC();
#endif
acpi_resync_clock(sc);
acpi_enable_fixed_events(sc);
+ slp_state &= ~ACPI_SS_SLEPT;
}
- sc->acpi_next_sstate = 0;
+ sc->acpi_next_stype = STYPE_AWAKE;
+
+ MPASS(slp_state == ACPI_SS_NONE);
bus_topo_unlock();
@@ -3488,7 +3622,7 @@
/* Run /etc/rc.resume after we are back. */
if (devctl_process_running())
- acpi_UserNotify("Resume", ACPI_ROOT_OBJECT, state);
+ acpi_UserNotify("Resume", ACPI_ROOT_OBJECT, stype);
return_ACPI_STATUS (status);
}
@@ -3539,8 +3673,9 @@
}
static int
-acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate)
+acpi_wake_sleep_prep(ACPI_HANDLE handle, enum sleep_type stype)
{
+ int sstate = acpi_stype2sstate(stype);
struct acpi_prw_data prw;
device_t dev;
@@ -3559,22 +3694,23 @@
if (sstate > prw.lowest_wake) {
AcpiSetGpeWakeMask(prw.gpe_handle, prw.gpe_bit, ACPI_GPE_DISABLE);
if (bootverbose)
- device_printf(dev, "wake_prep disabled wake for %s (S%d)\n",
- acpi_name(handle), sstate);
+ device_printf(dev, "wake_prep disabled wake for %s (%s)\n",
+ acpi_name(handle), acpi_stype2sname(stype));
} else if (dev && (acpi_get_flags(dev) & ACPI_FLAG_WAKE_ENABLED) != 0) {
acpi_pwr_wake_enable(handle, 1);
acpi_SetInteger(handle, "_PSW", 1);
if (bootverbose)
- device_printf(dev, "wake_prep enabled for %s (S%d)\n",
- acpi_name(handle), sstate);
+ device_printf(dev, "wake_prep enabled for %s (%s)\n",
+ acpi_name(handle), acpi_stype2sname(stype));
}
return (0);
}
static int
-acpi_wake_run_prep(ACPI_HANDLE handle, int sstate)
+acpi_wake_run_prep(ACPI_HANDLE handle, enum sleep_type stype)
{
+ int sstate = acpi_stype2sstate(stype);
struct acpi_prw_data prw;
device_t dev;
@@ -3611,26 +3747,26 @@
static ACPI_STATUS
acpi_wake_prep(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
{
- int sstate;
+ enum sleep_type stype;
/* If suspending, run the sleep prep function, otherwise wake. */
- sstate = *(int *)context;
+ stype = *(enum sleep_type *)context;
if (AcpiGbl_SystemAwakeAndRunning)
- acpi_wake_sleep_prep(handle, sstate);
+ acpi_wake_sleep_prep(handle, stype);
else
- acpi_wake_run_prep(handle, sstate);
+ acpi_wake_run_prep(handle, stype);
return (AE_OK);
}
/* Walk the tree rooted at acpi0 to prep devices for suspend/resume. */
static int
-acpi_wake_prep_walk(int sstate)
+acpi_wake_prep_walk(enum sleep_type stype)
{
ACPI_HANDLE sb_handle;
if (ACPI_SUCCESS(AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &sb_handle)))
AcpiWalkNamespace(ACPI_TYPE_DEVICE, sb_handle, 100,
- acpi_wake_prep, NULL, &sstate, NULL);
+ acpi_wake_prep, NULL, &stype, NULL);
return (0);
}
@@ -3789,7 +3925,7 @@
/* System Event Handlers (registered by EVENTHANDLER_REGISTER) */
static void
-acpi_system_eventhandler_sleep(void *arg, int state)
+acpi_system_eventhandler_sleep(void *arg, enum sleep_type stype)
{
struct acpi_softc *sc = (struct acpi_softc *)arg;
int ret;
@@ -3797,23 +3933,27 @@
ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
/* Check if button action is disabled or unknown. */
- if (state == ACPI_STATE_UNKNOWN)
+ if (stype == ACPI_STATE_UNKNOWN)
return;
- /* Request that the system prepare to enter the given suspend state. */
- ret = acpi_ReqSleepState(sc, state);
+ /*
+ * Request that the system prepare to enter the given suspend state. We can
+ * totally pass an ACPI S-state to an enum sleep_type.
+ */
+ ret = acpi_ReqSleepState(sc, stype);
if (ret != 0)
device_printf(sc->acpi_dev,
- "request to enter state S%d failed (err %d)\n", state, ret);
+ "request to enter state %s failed (err %d)\n",
+ acpi_stype2sname(stype), ret);
return_VOID;
}
static void
-acpi_system_eventhandler_wakeup(void *arg, int state)
+acpi_system_eventhandler_wakeup(void *arg, enum sleep_type stype)
{
- ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
+ ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, stype);
/* Currently, nothing to do for wakeup. */
@@ -3827,14 +3967,14 @@
acpi_invoke_sleep_eventhandler(void *context)
{
- EVENTHANDLER_INVOKE(acpi_sleep_event, *(int *)context);
+ EVENTHANDLER_INVOKE(acpi_sleep_event, *(enum sleep_type *)context);
}
static void
acpi_invoke_wake_eventhandler(void *context)
{
- EVENTHANDLER_INVOKE(acpi_wakeup_event, *(int *)context);
+ EVENTHANDLER_INVOKE(acpi_wakeup_event, *(enum sleep_type *)context);
}
UINT32
@@ -3845,7 +3985,7 @@
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
if (ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER,
- acpi_invoke_sleep_eventhandler, &sc->acpi_power_button_sx)))
+ acpi_invoke_sleep_eventhandler, &sc->acpi_power_button_stype)))
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
return_VALUE (ACPI_INTERRUPT_HANDLED);
}
@@ -3858,7 +3998,7 @@
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
if (ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER,
- acpi_invoke_wake_eventhandler, &sc->acpi_power_button_sx)))
+ acpi_invoke_wake_eventhandler, &sc->acpi_power_button_stype)))
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
return_VALUE (ACPI_INTERRUPT_HANDLED);
}
@@ -3871,7 +4011,7 @@
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
if (ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER,
- acpi_invoke_sleep_eventhandler, &sc->acpi_sleep_button_sx)))
+ acpi_invoke_sleep_eventhandler, &sc->acpi_sleep_button_stype)))
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
return_VALUE (ACPI_INTERRUPT_HANDLED);
}
@@ -3884,7 +4024,7 @@
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
if (ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER,
- acpi_invoke_wake_eventhandler, &sc->acpi_sleep_button_sx)))
+ acpi_invoke_wake_eventhandler, &sc->acpi_sleep_button_stype)))
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
return_VALUE (ACPI_INTERRUPT_HANDLED);
}
@@ -4080,7 +4220,8 @@
{
struct acpi_softc *sc;
struct acpi_ioctl_hook *hp;
- int error, state;
+ int error;
+ enum sleep_type stype;
error = 0;
hp = NULL;
@@ -4110,9 +4251,9 @@
/* Core system ioctls. */
switch (cmd) {
case ACPIIO_REQSLPSTATE:
- state = *(int *)addr;
- if (state != ACPI_STATE_S5)
- return (acpi_ReqSleepState(sc, state));
+ stype = *(int *)addr;
+ if (stype != STYPE_POWEROFF)
+ return (acpi_ReqSleepState(sc, stype));
device_printf(sc->acpi_dev, "power off via acpi ioctl not supported\n");
error = EOPNOTSUPP;
break;
@@ -4121,12 +4262,12 @@
error = acpi_AckSleepState(sc->acpi_clone, error);
break;
case ACPIIO_SETSLPSTATE: /* DEPRECATED */
- state = *(int *)addr;
- if (state < ACPI_STATE_S0 || state > ACPI_S_STATES_MAX)
+ stype = *(int *)addr;
+ if (stype < STYPE_AWAKE || stype > STYPE_COUNT)
return (EINVAL);
- if (!acpi_sleep_states[state])
+ if (!acpi_supported_stypes[stype])
return (EOPNOTSUPP);
- if (ACPI_FAILURE(acpi_SetSleepState(sc, state)))
+ if (ACPI_FAILURE(acpi_SetSleepState(sc, stype)))
error = ENXIO;
break;
default:
@@ -4137,31 +4278,35 @@
return (error);
}
-static int
-acpi_sname2sstate(const char *sname)
+static enum sleep_type
+acpi_sname2stype(const char *sname)
{
- int sstate;
+ enum sleep_type stype;
- if (toupper(sname[0]) == 'S') {
- sstate = sname[1] - '0';
- if (sstate >= ACPI_STATE_S0 && sstate <= ACPI_STATE_S5 &&
- sname[2] == '\0')
- return (sstate);
- } else if (strcasecmp(sname, "NONE") == 0)
- return (ACPI_STATE_UNKNOWN);
+ if (strcasecmp(sname, "NONE") == 0)
+ return (STYPE_UNKNOWN);
+ if (strcasecmp(sname, "S0i") == 0)
+ return (STYPE_SUSPEND_TO_IDLE);
+ if (toupper(sname[0]) != 'S')
+ return (-1);
+
+ /* Is regular ACPI S-state. */
+ stype = sname[1] - '0';
+ if (stype >= ACPI_STATE_S0 && stype <= ACPI_STATE_S5 &&
+ sname[2] == '\0')
+ return (stype);
return (-1);
}
static const char *
-acpi_sstate2sname(int sstate)
+acpi_stype2sname(enum sleep_type stype)
{
- static const char *snames[] = { "S0", "S1", "S2", "S3", "S4", "S5" };
+ static const char *snames[STYPE_COUNT] = {"S0", "S1", "S2", "S3", "S4",
+ "S5", "S0i"};
- if (sstate >= ACPI_STATE_S0 && sstate <= ACPI_STATE_S5)
- return (snames[sstate]);
- else if (sstate == ACPI_STATE_UNKNOWN)
- return ("NONE");
- return (NULL);
+ if (stype >= STYPE_AWAKE && stype < STYPE_COUNT)
+ return (snames[stype]);
+ return ("NONE");
}
static int
@@ -4169,12 +4314,12 @@
{
int error;
struct sbuf sb;
- UINT8 state;
+ enum sleep_type stype;
sbuf_new(&sb, NULL, 32, SBUF_AUTOEXTEND);
- for (state = ACPI_STATE_S1; state < ACPI_S_STATE_COUNT; state++)
- if (acpi_sleep_states[state])
- sbuf_printf(&sb, "%s ", acpi_sstate2sname(state));
+ for (stype = STYPE_STANDBY; stype < STYPE_COUNT; stype++)
+ if (acpi_supported_stypes[stype])
+ sbuf_printf(&sb, "%s ", acpi_stype2sname(stype));
sbuf_trim(&sb);
sbuf_finish(&sb);
error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
@@ -4185,20 +4330,21 @@
static int
acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
{
- char sleep_state[10];
- int error, new_state, old_state;
+ char sleep_type[10];
+ int error;
+ enum sleep_type new_stype, old_stype;
- old_state = *(int *)oidp->oid_arg1;
- strlcpy(sleep_state, acpi_sstate2sname(old_state), sizeof(sleep_state));
- error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
+ old_stype = *(enum sleep_type *)oidp->oid_arg1;
+ strlcpy(sleep_type, acpi_stype2sname(old_stype), sizeof(sleep_type));
+ error = sysctl_handle_string(oidp, sleep_type, sizeof(sleep_type), req);
if (error == 0 && req->newptr != NULL) {
- new_state = acpi_sname2sstate(sleep_state);
- if (new_state < ACPI_STATE_S1)
+ new_stype = acpi_sname2stype(sleep_type);
+ if (new_stype <= STYPE_AWAKE)
return (EINVAL);
- if (new_state < ACPI_S_STATE_COUNT && !acpi_sleep_states[new_state])
+ if (new_stype < STYPE_COUNT && !acpi_supported_stypes[new_stype])
return (EOPNOTSUPP);
- if (new_state != old_state)
- *(int *)oidp->oid_arg1 = new_state;
+ if (new_stype != old_stype)
+ *(int *)oidp->oid_arg1 = new_stype;
}
return (error);
}
@@ -4552,10 +4698,11 @@
static int
acpi_pm_func(u_long cmd, void *arg, ...)
{
- int state, acpi_state;
- int error;
- struct acpi_softc *sc;
- va_list ap;
+ int power_sstate;
+ enum sleep_type acpi_stype;
+ int error;
+ struct acpi_softc *sc;
+ va_list ap;
error = 0;
switch (cmd) {
@@ -4567,25 +4714,25 @@
}
va_start(ap, arg);
- state = va_arg(ap, int);
+ power_sstate = va_arg(ap, enum sleep_type);
va_end(ap);
- switch (state) {
+ switch (power_sstate) {
case POWER_SLEEP_STATE_STANDBY:
- acpi_state = sc->acpi_standby_sx;
+ acpi_stype = sc->acpi_standby_stype;
break;
case POWER_SLEEP_STATE_SUSPEND:
- acpi_state = sc->acpi_suspend_sx;
+ acpi_stype = sc->acpi_suspend_stype;
break;
case POWER_SLEEP_STATE_HIBERNATE:
- acpi_state = ACPI_STATE_S4;
+ acpi_stype = sc->acpi_hibernate_stype;
break;
default:
error = EINVAL;
goto out;
}
- if (ACPI_FAILURE(acpi_EnterSleepState(sc, acpi_state)))
+ if (ACPI_FAILURE(acpi_EnterSleepState(sc, acpi_stype)))
error = ENXIO;
break;
default:
diff --git a/sys/dev/acpica/acpi_lid.c b/sys/dev/acpica/acpi_lid.c
--- a/sys/dev/acpica/acpi_lid.c
+++ b/sys/dev/acpica/acpi_lid.c
@@ -235,9 +235,9 @@
sc->lid_status ? "opened" : "closed");
if (sc->lid_status == 0)
- EVENTHANDLER_INVOKE(acpi_sleep_event, acpi_sc->acpi_lid_switch_sx);
+ EVENTHANDLER_INVOKE(acpi_sleep_event, acpi_sc->acpi_lid_switch_stype);
else
- EVENTHANDLER_INVOKE(acpi_wakeup_event, acpi_sc->acpi_lid_switch_sx);
+ EVENTHANDLER_INVOKE(acpi_wakeup_event, acpi_sc->acpi_lid_switch_stype);
out:
ACPI_SERIAL_END(lid);
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -47,23 +47,43 @@
#include <machine/bus.h>
#include <machine/resource.h>
+enum sleep_type {
+ /*
+ * Map these with ACPI S-states the best we can. We want to be able to
+ * assign an S-state to an enum sleep_type. The other way round is
+ * impossible though, as we support additional non-S-state sleep types.
+ */
+ STYPE_AWAKE = ACPI_STATE_S0,
+ STYPE_STANDBY = ACPI_STATE_S1,
+ STYPE_STANDBY_S2 = ACPI_STATE_S2,
+ STYPE_SUSPEND = ACPI_STATE_S3,
+ STYPE_HIBERNATE = ACPI_STATE_S4,
+ STYPE_POWEROFF = ACPI_STATE_S5,
+ STYPE_SUSPEND_TO_IDLE,
+ STYPE_COUNT,
+ STYPE_UNKNOWN = ACPI_STATE_UNKNOWN,
+};
+
+CTASSERT(STYPE_COUNT == 7);
+
struct apm_clone_data;
struct acpi_softc {
device_t acpi_dev;
struct cdev *acpi_dev_t;
int acpi_enabled;
- int acpi_sstate;
+ enum sleep_type acpi_stype;
int acpi_sleep_disabled;
struct sysctl_ctx_list acpi_sysctl_ctx;
struct sysctl_oid *acpi_sysctl_tree;
- int acpi_power_button_sx;
- int acpi_sleep_button_sx;
- int acpi_lid_switch_sx;
+ enum sleep_type acpi_power_button_stype;
+ enum sleep_type acpi_sleep_button_stype;
+ enum sleep_type acpi_lid_switch_stype;
- int acpi_standby_sx;
- int acpi_suspend_sx;
+ enum sleep_type acpi_standby_stype;
+ enum sleep_type acpi_suspend_stype;
+ enum sleep_type acpi_hibernate_stype;
int acpi_sleep_delay;
int acpi_s4bios;
@@ -78,7 +98,7 @@
vm_offset_t acpi_wakeaddr;
vm_paddr_t acpi_wakephys;
- int acpi_next_sstate; /* Next suspend Sx state. */
+ enum sleep_type acpi_next_stype; /* Next suspend sleep type. */
struct apm_clone_data *acpi_clone; /* Pseudo-dev for devd(8). */
STAILQ_HEAD(,apm_clone_data) apm_cdevs; /* All apm/apmctl/acpi cdevs. */
struct callout susp_force_to; /* Force suspend if no acks. */
@@ -383,7 +403,7 @@
uint32_t *caps_out, bool query);
ACPI_STATUS acpi_OverrideInterruptLevel(UINT32 InterruptNumber);
ACPI_STATUS acpi_SetIntrModel(int model);
-int acpi_ReqSleepState(struct acpi_softc *sc, int state);
+int acpi_ReqSleepState(struct acpi_softc *sc, enum sleep_type stype);
int acpi_AckSleepState(struct apm_clone_data *clone, int error);
ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state);
int acpi_wake_set_enable(device_t dev, int enable);
diff --git a/sys/x86/acpica/acpi_apm.c b/sys/x86/acpica/acpi_apm.c
--- a/sys/x86/acpica/acpi_apm.c
+++ b/sys/x86/acpica/acpi_apm.c
@@ -236,7 +236,7 @@
acpi_sc = clone->acpi_sc;
/* We are about to lose a reference so check if suspend should occur */
- if (acpi_sc->acpi_next_sstate != 0 &&
+ if (acpi_sc->acpi_next_stype != STYPE_AWAKE &&
clone->notify_status != APM_EV_ACKED)
acpi_AckSleepState(clone, 0);
@@ -284,10 +284,10 @@
case APMIO_SUSPEND:
if ((flag & FWRITE) == 0)
return (EPERM);
- if (acpi_sc->acpi_next_sstate == 0) {
- if (acpi_sc->acpi_suspend_sx != ACPI_STATE_S5) {
+ if (acpi_sc->acpi_next_stype == STYPE_AWAKE) {
+ if (acpi_sc->acpi_suspend_stype != STYPE_POWEROFF) {
error = acpi_ReqSleepState(acpi_sc,
- acpi_sc->acpi_suspend_sx);
+ acpi_sc->acpi_suspend_stype);
} else {
printf(
"power off via apm suspend not supported\n");
@@ -299,10 +299,10 @@
case APMIO_STANDBY:
if ((flag & FWRITE) == 0)
return (EPERM);
- if (acpi_sc->acpi_next_sstate == 0) {
- if (acpi_sc->acpi_standby_sx != ACPI_STATE_S5) {
+ if (acpi_sc->acpi_next_stype == STYPE_AWAKE) {
+ if (acpi_sc->acpi_standby_stype != STYPE_POWEROFF) {
error = acpi_ReqSleepState(acpi_sc,
- acpi_sc->acpi_standby_sx);
+ acpi_sc->acpi_standby_stype);
} else {
printf(
"power off via apm standby not supported\n");
@@ -314,10 +314,10 @@
case APMIO_NEXTEVENT:
printf("apm nextevent start\n");
ACPI_LOCK(acpi);
- if (acpi_sc->acpi_next_sstate != 0 && clone->notify_status ==
- APM_EV_NONE) {
+ if (acpi_sc->acpi_next_stype != STYPE_AWAKE &&
+ clone->notify_status == APM_EV_NONE) {
ev_info = (struct apm_event_info *)addr;
- if (acpi_sc->acpi_next_sstate <= ACPI_STATE_S3)
+ if (acpi_sc->acpi_next_stype <= STYPE_SUSPEND)
ev_info->type = PMEV_STANDBYREQ;
else
ev_info->type = PMEV_SUSPENDREQ;
@@ -393,7 +393,7 @@
revents = 0;
devfs_get_cdevpriv((void **)&clone);
ACPI_LOCK(acpi);
- if (clone->acpi_sc->acpi_next_sstate)
+ if (clone->acpi_sc->acpi_next_stype != STYPE_AWAKE)
revents |= events & (POLLIN | POLLRDNORM);
else
selrecord(td, &clone->sel_read);
@@ -434,7 +434,7 @@
ACPI_LOCK(acpi);
clone = kn->kn_hook;
- sleeping = clone->acpi_sc->acpi_next_sstate ? 1 : 0;
+ sleeping = clone->acpi_sc->acpi_next_stype != STYPE_AWAKE;
ACPI_UNLOCK(acpi);
return (sleeping);
}
diff --git a/sys/x86/include/intr_machdep.h b/sys/x86/include/intr_machdep.h
--- a/sys/x86/include/intr_machdep.h
+++ b/sys/x86/include/intr_machdep.h
@@ -152,6 +152,7 @@
int intr_remove_handler(void *cookie);
void intr_resume(bool suspend_cancelled);
void intr_suspend(void);
+void intr_enable_src(u_int irq);
void intr_reprogram(void);
void intrcnt_add(const char *name, u_long **countp);
void nexus_add_irq(u_long irq);
diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c
--- a/sys/x86/x86/intr_machdep.c
+++ b/sys/x86/x86/intr_machdep.c
@@ -392,6 +392,15 @@
mtx_unlock(&intrpic_lock);
}
+void
+intr_enable_src(u_int irq)
+{
+ struct intsrc *is;
+
+ is = interrupt_sources[irq];
+ is->is_pic->pic_enable_source(is);
+}
+
static int
intr_assign_cpu(void *arg, int cpu)
{

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 31, 4:34 AM (3 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16347764
Default Alt Text
D48720.diff (39 KB)

Event Timeline