Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108974466
D48720.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
39 KB
Referenced Files
None
Subscribers
None
D48720.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D48720: acpi: Suspend-to-idle support (S0i)
Attached
Detach File
Event Timeline
Log In to Comment