acpi: Use sleep types defined in sys/power.h
This is as opposed to using ACPI sleep states directly (`ACPI_STATE_S*`). We now use `POWER_STYPE_*` added in D52036. This is in preparation for adding support for s2idle, which is not an ACPI sleep state, but needs to be handled specially by `acpi_EnterSleepState`. Reviewed by: cy Approved by: cy Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D52705 Event: EuroBSDcon 2025 Devsummit
This commit is contained in:
+245
-138
@@ -102,6 +102,11 @@ struct acpi_interface {
|
||||
int num;
|
||||
};
|
||||
|
||||
struct acpi_wake_prep_context {
|
||||
struct acpi_softc *sc;
|
||||
enum power_stype stype;
|
||||
};
|
||||
|
||||
static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL };
|
||||
|
||||
/* Global mutex for locking access to the ACPI subsystem. */
|
||||
@@ -111,8 +116,9 @@ struct callout acpi_sleep_timer;
|
||||
/* Bitmap of device quirks. */
|
||||
int acpi_quirks;
|
||||
|
||||
/* Supported sleep states. */
|
||||
static BOOLEAN acpi_sleep_states[ACPI_S_STATE_COUNT];
|
||||
/* Supported sleep states and types. */
|
||||
static bool acpi_supported_stypes[POWER_STYPE_COUNT];
|
||||
static bool acpi_supported_sstates[ACPI_S_STATE_COUNT];
|
||||
|
||||
static void acpi_lookup(void *arg, const char *name, device_t *dev);
|
||||
static int acpi_modevent(struct module *mod, int event, void *junk);
|
||||
@@ -169,21 +175,28 @@ static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level,
|
||||
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 power_stype 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(struct acpi_softc *sc, ACPI_HANDLE handle,
|
||||
enum power_stype stype);
|
||||
static int acpi_wake_run_prep(struct acpi_softc *sc, ACPI_HANDLE handle,
|
||||
enum power_stype stype);
|
||||
static int acpi_wake_prep_walk(struct acpi_softc *sc, enum power_stype 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 int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static void acpi_system_eventhandler_sleep(void *arg,
|
||||
enum power_stype stype);
|
||||
static void acpi_system_eventhandler_wakeup(void *arg,
|
||||
enum power_stype stype);
|
||||
static enum power_stype acpi_sstate_to_stype(int sstate);
|
||||
static int acpi_sname_to_sstate(const char *sname);
|
||||
static const char *acpi_sstate_to_sname(int sstate);
|
||||
static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int acpi_stype_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int acpi_debug_objects_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype);
|
||||
static int acpi_pm_func(u_long cmd, void *arg, enum power_stype stype);
|
||||
@@ -477,6 +490,7 @@ acpi_attach(device_t dev)
|
||||
UINT32 flags;
|
||||
UINT8 TypeA, TypeB;
|
||||
char *env;
|
||||
enum power_stype stype;
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
||||
|
||||
@@ -589,31 +603,30 @@ acpi_attach(device_t dev)
|
||||
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_stype_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_stype_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",
|
||||
"Lid ACPI sleep state. Set to S3 if you want to suspend your laptop when close the Lid.");
|
||||
&sc->acpi_lid_switch_stype, 0, acpi_stype_sysctl, "A",
|
||||
"Lid ACPI sleep state. Set to s2idle or s2mem 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", "");
|
||||
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_standby_sx, 0, acpi_sleep_state_sysctl, "A",
|
||||
"ACPI Sx state to use when going standby (S1 or S2).");
|
||||
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");
|
||||
SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
|
||||
OID_AUTO, "s4bios", CTLFLAG_RW, &sc->acpi_s4bios, 0, "S4BIOS mode");
|
||||
OID_AUTO, "s4bios", CTLFLAG_RW, &sc->acpi_s4bios, 0,
|
||||
"Use S4BIOS when hibernating.");
|
||||
SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
|
||||
OID_AUTO, "verbose", CTLFLAG_RW, &sc->acpi_verbose, 0, "verbose mode");
|
||||
SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
|
||||
@@ -659,31 +672,38 @@ acpi_attach(device_t dev)
|
||||
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) is always supported.
|
||||
*/
|
||||
acpi_supported_sstates[ACPI_STATE_S0] = TRUE;
|
||||
acpi_supported_stypes[POWER_STYPE_AWAKE] = 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_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) {
|
||||
acpi_supported_sstates[state] = TRUE;
|
||||
acpi_supported_stypes[acpi_sstate_to_stype(state)] = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatch the default sleep state to devices. The lid switch is set
|
||||
* Dispatch the default sleep type to devices. The lid switch is set
|
||||
* to UNKNOWN by default to avoid surprising users.
|
||||
*/
|
||||
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;
|
||||
sc->acpi_power_button_stype = acpi_supported_stypes[POWER_STYPE_POWEROFF] ?
|
||||
POWER_STYPE_POWEROFF : POWER_STYPE_UNKNOWN;
|
||||
sc->acpi_lid_switch_stype = POWER_STYPE_UNKNOWN;
|
||||
|
||||
/* Pick the first valid sleep state for the sleep button default. */
|
||||
sc->acpi_sleep_button_sx = ACPI_STATE_UNKNOWN;
|
||||
for (state = ACPI_STATE_S1; state <= ACPI_STATE_S4; state++)
|
||||
if (acpi_sleep_states[state]) {
|
||||
sc->acpi_sleep_button_sx = state;
|
||||
sc->acpi_standby_sx = ACPI_STATE_UNKNOWN;
|
||||
if (acpi_supported_sstates[ACPI_STATE_S1])
|
||||
sc->acpi_standby_sx = ACPI_STATE_S1;
|
||||
else if (acpi_supported_sstates[ACPI_STATE_S2])
|
||||
sc->acpi_standby_sx = ACPI_STATE_S2;
|
||||
|
||||
/* Pick the first valid sleep type for the sleep button default. */
|
||||
sc->acpi_sleep_button_stype = POWER_STYPE_UNKNOWN;
|
||||
for (stype = POWER_STYPE_STANDBY; stype <= POWER_STYPE_HIBERNATE; stype++)
|
||||
if (acpi_supported_stypes[stype]) {
|
||||
sc->acpi_sleep_button_stype = stype;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -708,7 +728,7 @@ acpi_attach(device_t dev)
|
||||
|
||||
/* Flag our initial states. */
|
||||
sc->acpi_enabled = TRUE;
|
||||
sc->acpi_sstate = ACPI_STATE_S0;
|
||||
sc->acpi_stype = POWER_STYPE_AWAKE;
|
||||
sc->acpi_sleep_disabled = TRUE;
|
||||
|
||||
/* Create the control device */
|
||||
@@ -768,6 +788,36 @@ acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype)
|
||||
return (ACPI_STATE_UNKNOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX It would be nice if we didn't need this function, but we'd need
|
||||
* acpi_EnterSleepState and acpi_ReqSleepState to take in actual ACPI S-states,
|
||||
* which won't be possible at the moment because suspend-to-idle (which is not
|
||||
* an ACPI S-state nor maps to one) will be implemented here.
|
||||
*
|
||||
* In the future, we should make generic a lot of the logic in these functions
|
||||
* to enable suspend-to-idle on non-ACPI builds, and then make
|
||||
* acpi_EnterSleepState and acpi_ReqSleepState truly take in ACPI S-states
|
||||
* again.
|
||||
*/
|
||||
static enum power_stype
|
||||
acpi_sstate_to_stype(int sstate)
|
||||
{
|
||||
switch (sstate) {
|
||||
case ACPI_STATE_S0:
|
||||
return (POWER_STYPE_AWAKE);
|
||||
case ACPI_STATE_S1:
|
||||
case ACPI_STATE_S2:
|
||||
return (POWER_STYPE_STANDBY);
|
||||
case ACPI_STATE_S3:
|
||||
return (POWER_STYPE_SUSPEND_TO_MEM);
|
||||
case ACPI_STATE_S4:
|
||||
return (POWER_STYPE_HIBERNATE);
|
||||
case ACPI_STATE_S5:
|
||||
return (POWER_STYPE_POWEROFF);
|
||||
}
|
||||
return (POWER_STYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
static void
|
||||
acpi_set_power_children(device_t dev, int state)
|
||||
{
|
||||
@@ -820,6 +870,7 @@ acpi_resume(device_t dev)
|
||||
static int
|
||||
acpi_shutdown(device_t dev)
|
||||
{
|
||||
struct acpi_softc *sc = device_get_softc(dev);
|
||||
|
||||
bus_topo_assert();
|
||||
|
||||
@@ -830,7 +881,7 @@ acpi_shutdown(device_t dev)
|
||||
* Enable any GPEs that are able to power-on the system (i.e., RTC).
|
||||
* Also, disable any that are not valid for this state (most).
|
||||
*/
|
||||
acpi_wake_prep_walk(ACPI_STATE_S5);
|
||||
acpi_wake_prep_walk(sc, POWER_STYPE_POWEROFF);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -2063,7 +2114,7 @@ acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate)
|
||||
* 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_stype_to_sstate(sc, 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,
|
||||
@@ -3161,9 +3212,9 @@ acpi_sleep_force_task(void *context)
|
||||
{
|
||||
struct acpi_softc *sc = (struct acpi_softc *)context;
|
||||
|
||||
if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_sstate)))
|
||||
device_printf(sc->acpi_dev, "force sleep state S%d failed\n",
|
||||
sc->acpi_next_sstate);
|
||||
if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_stype)))
|
||||
device_printf(sc->acpi_dev, "force sleep state %s failed\n",
|
||||
power_stype_to_name(sc->acpi_next_stype));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3190,24 +3241,24 @@ acpi_sleep_force(void *arg)
|
||||
* acks are in.
|
||||
*/
|
||||
int
|
||||
acpi_ReqSleepState(struct acpi_softc *sc, int state)
|
||||
acpi_ReqSleepState(struct acpi_softc *sc, enum power_stype 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 < POWER_STYPE_AWAKE || stype >= POWER_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 != POWER_STYPE_AWAKE ||
|
||||
suspend_blocked)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Wait until sleep is enabled. */
|
||||
while (sc->acpi_sleep_disabled) {
|
||||
@@ -3216,12 +3267,12 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
|
||||
|
||||
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 == POWER_STYPE_POWEROFF) {
|
||||
ACPI_UNLOCK(acpi);
|
||||
status = acpi_EnterSleepState(sc, state);
|
||||
status = acpi_EnterSleepState(sc, stype);
|
||||
return (ACPI_SUCCESS(status) ? 0 : ENXIO);
|
||||
}
|
||||
|
||||
@@ -3237,7 +3288,7 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@@ -3252,7 +3303,7 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
|
||||
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
|
||||
@@ -3275,17 +3326,17 @@ acpi_AckSleepState(struct apm_clone_data *clone, int error)
|
||||
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 == POWER_STYPE_AWAKE) {
|
||||
ACPI_UNLOCK(acpi);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Caller wants to abort suspend process. */
|
||||
if (error) {
|
||||
sc->acpi_next_sstate = 0;
|
||||
sc->acpi_next_stype = POWER_STYPE_AWAKE;
|
||||
callout_stop(&sc->susp_force_to);
|
||||
device_printf(sc->acpi_dev,
|
||||
"listener on %s cancelled the pending suspend\n",
|
||||
@@ -3315,7 +3366,7 @@ acpi_AckSleepState(struct apm_clone_data *clone, int error)
|
||||
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);
|
||||
@@ -3372,24 +3423,27 @@ enum acpi_sleep_state {
|
||||
* Currently we support S1-S5 but S4 is only S4BIOS
|
||||
*/
|
||||
static ACPI_STATUS
|
||||
acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
acpi_EnterSleepState(struct acpi_softc *sc, enum power_stype stype)
|
||||
{
|
||||
register_t intr;
|
||||
ACPI_STATUS status;
|
||||
ACPI_EVENT_STATUS power_button_status;
|
||||
enum acpi_sleep_state slp_state;
|
||||
int acpi_sstate;
|
||||
int sleep_result;
|
||||
|
||||
ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
|
||||
ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, stype);
|
||||
|
||||
if (state < ACPI_STATE_S1 || state > ACPI_S_STATES_MAX)
|
||||
if (stype <= POWER_STYPE_AWAKE || stype >= POWER_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", power_stype_to_name(stype));
|
||||
return (AE_SUPPORT);
|
||||
}
|
||||
|
||||
acpi_sstate = acpi_stype_to_sstate(sc, stype);
|
||||
|
||||
/* Re-entry once we're suspending is not allowed. */
|
||||
status = acpi_sleep_disable(sc);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
@@ -3398,7 +3452,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
return (status);
|
||||
}
|
||||
|
||||
if (state == ACPI_STATE_S5) {
|
||||
if (stype == POWER_STYPE_POWEROFF) {
|
||||
/*
|
||||
* Shut down cleanly and power off. This will call us back through the
|
||||
* shutdown handlers.
|
||||
@@ -3426,16 +3480,16 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
#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);
|
||||
acpi_wake_prep_walk(sc, stype);
|
||||
slp_state = ACPI_SS_GPE_SET;
|
||||
|
||||
/*
|
||||
@@ -3452,7 +3506,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
}
|
||||
slp_state = ACPI_SS_DEV_SUSPEND;
|
||||
|
||||
status = AcpiEnterSleepStatePrep(state);
|
||||
status = AcpiEnterSleepStatePrep(acpi_sstate);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n",
|
||||
AcpiFormatException(status));
|
||||
@@ -3465,9 +3519,9 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
|
||||
suspendclock();
|
||||
intr = intr_disable();
|
||||
if (state != ACPI_STATE_S1) {
|
||||
sleep_result = acpi_sleep_machdep(sc, state);
|
||||
acpi_wakeup_machdep(sc, state, sleep_result, 0);
|
||||
if (stype != POWER_STYPE_STANDBY) {
|
||||
sleep_result = acpi_sleep_machdep(sc, acpi_sstate);
|
||||
acpi_wakeup_machdep(sc, acpi_sstate, sleep_result, 0);
|
||||
|
||||
/*
|
||||
* XXX According to ACPI specification SCI_EN bit should be restored
|
||||
@@ -3478,10 +3532,10 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
* This hack is picked up from Linux, which claims that it follows
|
||||
* Windows behavior.
|
||||
*/
|
||||
if (sleep_result == 1 && state != ACPI_STATE_S4)
|
||||
if (sleep_result == 1 && stype != POWER_STYPE_HIBERNATE)
|
||||
AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, ACPI_ENABLE_EVENT);
|
||||
|
||||
if (sleep_result == 1 && state == ACPI_STATE_S3) {
|
||||
if (sleep_result == 1 && stype == POWER_STYPE_SUSPEND_TO_MEM) {
|
||||
/*
|
||||
* Prevent mis-interpretation of the wakeup by power button
|
||||
* as a request for power off.
|
||||
@@ -3507,20 +3561,20 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
intr_restore(intr);
|
||||
|
||||
/* call acpi_wakeup_machdep() again with interrupt enabled */
|
||||
acpi_wakeup_machdep(sc, state, sleep_result, 1);
|
||||
acpi_wakeup_machdep(sc, acpi_sstate, sleep_result, 1);
|
||||
|
||||
AcpiLeaveSleepStatePrep(state);
|
||||
AcpiLeaveSleepStatePrep(acpi_sstate);
|
||||
|
||||
if (sleep_result == -1)
|
||||
goto backout;
|
||||
|
||||
/* Re-enable ACPI hardware on wakeup from sleep state 4. */
|
||||
if (state == ACPI_STATE_S4)
|
||||
/* Re-enable ACPI hardware on wakeup from hibernate. */
|
||||
if (stype == POWER_STYPE_HIBERNATE)
|
||||
AcpiEnable();
|
||||
} else {
|
||||
status = AcpiEnterSleepState(state);
|
||||
status = AcpiEnterSleepState(acpi_sstate);
|
||||
intr_restore(intr);
|
||||
AcpiLeaveSleepStatePrep(state);
|
||||
AcpiLeaveSleepStatePrep(acpi_sstate);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
|
||||
AcpiFormatException(status));
|
||||
@@ -3537,13 +3591,13 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
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;
|
||||
acpi_wake_prep_walk(sc, stype);
|
||||
sc->acpi_stype = POWER_STYPE_AWAKE;
|
||||
}
|
||||
if (slp_state >= ACPI_SS_DEV_SUSPEND)
|
||||
DEVICE_RESUME(root_bus);
|
||||
if (slp_state >= ACPI_SS_SLP_PREP)
|
||||
AcpiLeaveSleepState(state);
|
||||
AcpiLeaveSleepState(acpi_sstate);
|
||||
if (slp_state >= ACPI_SS_SLEPT) {
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
/* NB: we are still using ACPI timecounter at this point. */
|
||||
@@ -3552,7 +3606,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
acpi_resync_clock(sc);
|
||||
acpi_enable_fixed_events(sc);
|
||||
}
|
||||
sc->acpi_next_sstate = 0;
|
||||
sc->acpi_next_stype = POWER_STYPE_AWAKE;
|
||||
|
||||
bus_topo_unlock();
|
||||
|
||||
@@ -3578,7 +3632,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
|
||||
|
||||
/* 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);
|
||||
}
|
||||
@@ -3629,8 +3683,10 @@ acpi_wake_set_enable(device_t dev, int enable)
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate)
|
||||
acpi_wake_sleep_prep(struct acpi_softc *sc, ACPI_HANDLE handle,
|
||||
enum power_stype stype)
|
||||
{
|
||||
int sstate;
|
||||
struct acpi_prw_data prw;
|
||||
device_t dev;
|
||||
|
||||
@@ -3639,6 +3695,8 @@ acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate)
|
||||
return (ENXIO);
|
||||
dev = acpi_get_device(handle);
|
||||
|
||||
sstate = acpi_stype_to_sstate(sc, stype);
|
||||
|
||||
/*
|
||||
* The destination sleep state must be less than (i.e., higher power)
|
||||
* or equal to the value specified by _PRW. If this GPE cannot be
|
||||
@@ -3649,22 +3707,24 @@ acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate)
|
||||
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), power_stype_to_name(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), power_stype_to_name(stype));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_wake_run_prep(ACPI_HANDLE handle, int sstate)
|
||||
acpi_wake_run_prep(struct acpi_softc *sc, ACPI_HANDLE handle,
|
||||
enum power_stype stype)
|
||||
{
|
||||
int sstate;
|
||||
struct acpi_prw_data prw;
|
||||
device_t dev;
|
||||
|
||||
@@ -3678,6 +3738,8 @@ acpi_wake_run_prep(ACPI_HANDLE handle, int sstate)
|
||||
if (dev == NULL || (acpi_get_flags(dev) & ACPI_FLAG_WAKE_ENABLED) == 0)
|
||||
return (0);
|
||||
|
||||
sstate = acpi_stype_to_sstate(sc, stype);
|
||||
|
||||
/*
|
||||
* If this GPE couldn't be enabled for the previous sleep state, it was
|
||||
* disabled before going to sleep so re-enable it. If it was enabled,
|
||||
@@ -3701,26 +3763,29 @@ acpi_wake_run_prep(ACPI_HANDLE handle, int sstate)
|
||||
static ACPI_STATUS
|
||||
acpi_wake_prep(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
|
||||
{
|
||||
int sstate;
|
||||
struct acpi_wake_prep_context *ctx = context;
|
||||
|
||||
/* If suspending, run the sleep prep function, otherwise wake. */
|
||||
sstate = *(int *)context;
|
||||
if (AcpiGbl_SystemAwakeAndRunning)
|
||||
acpi_wake_sleep_prep(handle, sstate);
|
||||
acpi_wake_sleep_prep(ctx->sc, handle, ctx->stype);
|
||||
else
|
||||
acpi_wake_run_prep(handle, sstate);
|
||||
acpi_wake_run_prep(ctx->sc, handle, ctx->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(struct acpi_softc *sc, enum power_stype stype)
|
||||
{
|
||||
ACPI_HANDLE sb_handle;
|
||||
struct acpi_wake_prep_context ctx = {
|
||||
.sc = sc,
|
||||
.stype = stype,
|
||||
};
|
||||
|
||||
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, &ctx, NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -3879,31 +3944,35 @@ acpi_parse_prw(ACPI_HANDLE h, struct acpi_prw_data *prw)
|
||||
/* System Event Handlers (registered by EVENTHANDLER_REGISTER) */
|
||||
|
||||
static void
|
||||
acpi_system_eventhandler_sleep(void *arg, int state)
|
||||
acpi_system_eventhandler_sleep(void *arg, enum power_stype stype)
|
||||
{
|
||||
struct acpi_softc *sc = (struct acpi_softc *)arg;
|
||||
int ret;
|
||||
|
||||
ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
|
||||
ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, stype);
|
||||
|
||||
/* 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 power_stype.
|
||||
*/
|
||||
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",
|
||||
power_stype_to_name(stype), ret);
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
static void
|
||||
acpi_system_eventhandler_wakeup(void *arg, int state)
|
||||
acpi_system_eventhandler_wakeup(void *arg, enum power_stype 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. */
|
||||
|
||||
@@ -3917,14 +3986,14 @@ static void
|
||||
acpi_invoke_sleep_eventhandler(void *context)
|
||||
{
|
||||
|
||||
EVENTHANDLER_INVOKE(acpi_sleep_event, *(int *)context);
|
||||
EVENTHANDLER_INVOKE(acpi_sleep_event, *(enum power_stype *)context);
|
||||
}
|
||||
|
||||
static void
|
||||
acpi_invoke_wake_eventhandler(void *context)
|
||||
{
|
||||
|
||||
EVENTHANDLER_INVOKE(acpi_wakeup_event, *(int *)context);
|
||||
EVENTHANDLER_INVOKE(acpi_wakeup_event, *(enum power_stype *)context);
|
||||
}
|
||||
|
||||
UINT32
|
||||
@@ -3940,7 +4009,7 @@ acpi_event_power_button_sleep(void *context)
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
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);
|
||||
#else
|
||||
shutdown_nice(RB_POWEROFF);
|
||||
@@ -3957,7 +4026,7 @@ acpi_event_power_button_wake(void *context)
|
||||
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);
|
||||
}
|
||||
@@ -3970,7 +4039,7 @@ acpi_event_sleep_button_sleep(void *context)
|
||||
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);
|
||||
}
|
||||
@@ -3983,7 +4052,7 @@ acpi_event_sleep_button_wake(void *context)
|
||||
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);
|
||||
}
|
||||
@@ -4179,7 +4248,8 @@ acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
|
||||
{
|
||||
struct acpi_softc *sc;
|
||||
struct acpi_ioctl_hook *hp;
|
||||
int error, state;
|
||||
int error;
|
||||
int sstate;
|
||||
|
||||
error = 0;
|
||||
hp = NULL;
|
||||
@@ -4209,9 +4279,9 @@ acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
|
||||
/* Core system ioctls. */
|
||||
switch (cmd) {
|
||||
case ACPIIO_REQSLPSTATE:
|
||||
state = *(int *)addr;
|
||||
if (state != ACPI_STATE_S5)
|
||||
return (acpi_ReqSleepState(sc, state));
|
||||
sstate = *(int *)addr;
|
||||
if (sstate != ACPI_STATE_S5)
|
||||
return (acpi_ReqSleepState(sc, acpi_sstate_to_stype(sstate)));
|
||||
device_printf(sc->acpi_dev, "power off via acpi ioctl not supported\n");
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
@@ -4220,12 +4290,12 @@ acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
|
||||
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)
|
||||
sstate = *(int *)addr;
|
||||
if (sstate < ACPI_STATE_S0 || sstate > ACPI_STATE_S5)
|
||||
return (EINVAL);
|
||||
if (!acpi_sleep_states[state])
|
||||
if (!acpi_supported_sstates[sstate])
|
||||
return (EOPNOTSUPP);
|
||||
if (ACPI_FAILURE(acpi_SetSleepState(sc, state)))
|
||||
if (ACPI_FAILURE(acpi_SetSleepState(sc, acpi_sstate_to_stype(sstate))))
|
||||
error = ENXIO;
|
||||
break;
|
||||
default:
|
||||
@@ -4237,7 +4307,7 @@ acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_sname2sstate(const char *sname)
|
||||
acpi_sname_to_sstate(const char *sname)
|
||||
{
|
||||
int sstate;
|
||||
|
||||
@@ -4252,14 +4322,15 @@ acpi_sname2sstate(const char *sname)
|
||||
}
|
||||
|
||||
static const char *
|
||||
acpi_sstate2sname(int sstate)
|
||||
acpi_sstate_to_sname(int state)
|
||||
{
|
||||
static const char *snames[] = { "S0", "S1", "S2", "S3", "S4", "S5" };
|
||||
static const char *snames[ACPI_S_STATE_COUNT] = {"S0", "S1", "S2", "S3",
|
||||
"S4", "S5"};
|
||||
|
||||
if (sstate >= ACPI_STATE_S0 && sstate <= ACPI_STATE_S5)
|
||||
return (snames[sstate]);
|
||||
else if (sstate == ACPI_STATE_UNKNOWN)
|
||||
if (state == ACPI_STATE_UNKNOWN)
|
||||
return ("NONE");
|
||||
if (state >= ACPI_STATE_S0 && state < ACPI_S_STATE_COUNT)
|
||||
return (snames[state]);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -4272,8 +4343,8 @@ acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
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));
|
||||
if (acpi_supported_sstates[state])
|
||||
sbuf_printf(&sb, "%s ", acpi_sstate_to_sname(state));
|
||||
sbuf_trim(&sb);
|
||||
sbuf_finish(&sb);
|
||||
error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
|
||||
@@ -4281,27 +4352,64 @@ acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
char sleep_state[10];
|
||||
int error, new_state, old_state;
|
||||
int error;
|
||||
int new_sstate, old_sstate;
|
||||
|
||||
old_state = *(int *)oidp->oid_arg1;
|
||||
strlcpy(sleep_state, acpi_sstate2sname(old_state), sizeof(sleep_state));
|
||||
old_sstate = *(int *)oidp->oid_arg1;
|
||||
strlcpy(sleep_state, acpi_sstate_to_sname(old_sstate), sizeof(sleep_state));
|
||||
error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
|
||||
if (error == 0 && req->newptr != NULL) {
|
||||
new_state = acpi_sname2sstate(sleep_state);
|
||||
if (new_state < ACPI_STATE_S1)
|
||||
new_sstate = acpi_sname_to_sstate(sleep_state);
|
||||
if (new_sstate < 0)
|
||||
return (EINVAL);
|
||||
if (new_state < ACPI_S_STATE_COUNT && !acpi_sleep_states[new_state])
|
||||
if (new_sstate < ACPI_S_STATE_COUNT &&
|
||||
!acpi_supported_sstates[new_sstate])
|
||||
return (EOPNOTSUPP);
|
||||
if (new_state != old_state)
|
||||
*(int *)oidp->oid_arg1 = new_state;
|
||||
if (new_sstate != old_sstate)
|
||||
*(int *)oidp->oid_arg1 = new_sstate;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_stype_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
char name[10];
|
||||
int err;
|
||||
int sstate;
|
||||
enum power_stype new_stype, old_stype;
|
||||
|
||||
old_stype = *(enum power_stype *)oidp->oid_arg1;
|
||||
strlcpy(name, power_stype_to_name(old_stype), sizeof(name));
|
||||
err = sysctl_handle_string(oidp, name, sizeof(name), req);
|
||||
if (err != 0 || req->newptr == NULL)
|
||||
return (err);
|
||||
|
||||
new_stype = power_name_to_stype(name);
|
||||
if (new_stype == POWER_STYPE_UNKNOWN) {
|
||||
sstate = acpi_sname_to_sstate(name);
|
||||
if (sstate < 0)
|
||||
return (EINVAL);
|
||||
printf("warning: this sysctl expects a sleep type, but an ACPI S-state has "
|
||||
"been passed to it. This functionality is deprecated; see acpi(4).\n");
|
||||
MPASS(sstate < ACPI_S_STATE_COUNT);
|
||||
if (acpi_supported_sstates[sstate] == false)
|
||||
return (EOPNOTSUPP);
|
||||
new_stype = acpi_sstate_to_stype(sstate);
|
||||
}
|
||||
|
||||
if (acpi_supported_stypes[new_stype] == false)
|
||||
return (EOPNOTSUPP);
|
||||
if (new_stype != old_stype)
|
||||
*(enum power_stype *)oidp->oid_arg1 = new_stype;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Inform devctl(4) when we receive a Notify. */
|
||||
void
|
||||
acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, uint8_t notify)
|
||||
@@ -4650,7 +4758,7 @@ acpi_reset_interfaces(device_t dev)
|
||||
static int
|
||||
acpi_pm_func(u_long cmd, void *arg, enum power_stype stype)
|
||||
{
|
||||
int error, sstate;
|
||||
int error;
|
||||
struct acpi_softc *sc;
|
||||
|
||||
error = 0;
|
||||
@@ -4661,8 +4769,7 @@ acpi_pm_func(u_long cmd, void *arg, enum power_stype stype)
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
sstate = acpi_stype_to_sstate(sc, stype);
|
||||
if (ACPI_FAILURE(acpi_EnterSleepState(sc, sstate)))
|
||||
if (ACPI_FAILURE(acpi_EnterSleepState(sc, stype)))
|
||||
error = ENXIO;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -235,9 +235,9 @@ acpi_lid_notify_status_changed(void *arg)
|
||||
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);
|
||||
|
||||
@@ -54,20 +54,19 @@ struct acpi_softc {
|
||||
struct cdev *acpi_dev_t;
|
||||
|
||||
int acpi_enabled;
|
||||
int acpi_sstate;
|
||||
enum power_stype 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 power_stype acpi_power_button_stype;
|
||||
enum power_stype acpi_sleep_button_stype;
|
||||
enum power_stype acpi_lid_switch_stype;
|
||||
|
||||
int acpi_standby_sx;
|
||||
int acpi_suspend_sx;
|
||||
int acpi_s4bios;
|
||||
|
||||
int acpi_sleep_delay;
|
||||
int acpi_s4bios;
|
||||
int acpi_do_disable;
|
||||
int acpi_verbose;
|
||||
int acpi_handle_reboot;
|
||||
@@ -75,7 +74,7 @@ struct acpi_softc {
|
||||
vm_offset_t acpi_wakeaddr;
|
||||
vm_paddr_t acpi_wakephys;
|
||||
|
||||
int acpi_next_sstate; /* Next suspend Sx state. */
|
||||
enum power_stype 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. */
|
||||
@@ -412,7 +411,7 @@ ACPI_STATUS acpi_EvaluateOSC(ACPI_HANDLE handle, uint8_t *uuid,
|
||||
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 power_stype 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);
|
||||
|
||||
+13
-12
@@ -235,7 +235,7 @@ apmdtor(void *data)
|
||||
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 != POWER_STYPE_AWAKE &&
|
||||
clone->notify_status != APM_EV_ACKED)
|
||||
acpi_AckSleepState(clone, 0);
|
||||
|
||||
@@ -283,10 +283,10 @@ apmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
|
||||
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 == POWER_STYPE_AWAKE) {
|
||||
if (power_suspend_stype != POWER_STYPE_POWEROFF) {
|
||||
error = acpi_ReqSleepState(acpi_sc,
|
||||
acpi_sc->acpi_suspend_sx);
|
||||
power_suspend_stype);
|
||||
} else {
|
||||
printf(
|
||||
"power off via apm suspend not supported\n");
|
||||
@@ -298,10 +298,10 @@ apmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
|
||||
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 == POWER_STYPE_AWAKE) {
|
||||
if (power_standby_stype != POWER_STYPE_POWEROFF) {
|
||||
error = acpi_ReqSleepState(acpi_sc,
|
||||
acpi_sc->acpi_standby_sx);
|
||||
power_standby_stype);
|
||||
} else {
|
||||
printf(
|
||||
"power off via apm standby not supported\n");
|
||||
@@ -313,10 +313,11 @@ apmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
|
||||
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 != POWER_STYPE_AWAKE &&
|
||||
clone->notify_status == APM_EV_NONE) {
|
||||
ev_info = (struct apm_event_info *)addr;
|
||||
if (acpi_sc->acpi_next_sstate <= ACPI_STATE_S3)
|
||||
/* XXX Check this. */
|
||||
if (acpi_sc->acpi_next_stype == POWER_STYPE_STANDBY)
|
||||
ev_info->type = PMEV_STANDBYREQ;
|
||||
else
|
||||
ev_info->type = PMEV_SUSPENDREQ;
|
||||
@@ -392,7 +393,7 @@ apmpoll(struct cdev *dev, int events, struct thread *td)
|
||||
revents = 0;
|
||||
devfs_get_cdevpriv((void **)&clone);
|
||||
ACPI_LOCK(acpi);
|
||||
if (clone->acpi_sc->acpi_next_sstate)
|
||||
if (clone->acpi_sc->acpi_next_stype != POWER_STYPE_AWAKE)
|
||||
revents |= events & (POLLIN | POLLRDNORM);
|
||||
else
|
||||
selrecord(td, &clone->sel_read);
|
||||
@@ -433,7 +434,7 @@ apmreadfilt(struct knote *kn, long hint)
|
||||
|
||||
ACPI_LOCK(acpi);
|
||||
clone = kn->kn_hook;
|
||||
sleeping = clone->acpi_sc->acpi_next_sstate ? 1 : 0;
|
||||
sleeping = clone->acpi_sc->acpi_next_stype != POWER_STYPE_AWAKE;
|
||||
ACPI_UNLOCK(acpi);
|
||||
return (sleeping);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user