Date: Wed, 17 Jun 2009 11:43:33 +0000 (UTC) From: Rui Paulo <rpaulo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r194352 - projects/mesh11s/sys/dev/acpica Message-ID: <200906171143.n5HBhX1G074380@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rpaulo Date: Wed Jun 17 11:43:33 2009 New Revision: 194352 URL: http://svn.freebsd.org/changeset/base/194352 Log: fix mismerge Modified: projects/mesh11s/sys/dev/acpica/acpi.c Modified: projects/mesh11s/sys/dev/acpica/acpi.c ============================================================================== --- projects/mesh11s/sys/dev/acpica/acpi.c Wed Jun 17 11:42:51 2009 (r194351) +++ projects/mesh11s/sys/dev/acpica/acpi.c Wed Jun 17 11:43:33 2009 (r194352) @@ -61,11 +61,12 @@ __FBSDID("$FreeBSD$"); #include <isa/isavar.h> #include <isa/pnpvar.h> -#include <contrib/dev/acpica/acpi.h> +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <contrib/dev/acpica/include/acnamesp.h> + #include <dev/acpica/acpivar.h> #include <dev/acpica/acpiio.h> -#include <contrib/dev/acpica/achware.h> -#include <contrib/dev/acpica/acnamesp.h> #include "pci_if.h" #include <dev/pci/pcivar.h> @@ -97,6 +98,9 @@ struct mtx acpi_mutex; /* Bitmap of device quirks. */ int acpi_quirks; +/* Supported sleep states. */ +static BOOLEAN acpi_sleep_states[ACPI_S_STATE_COUNT]; + static int acpi_modevent(struct module *mod, int event, void *junk); static int acpi_probe(device_t dev); static int acpi_attach(device_t dev); @@ -142,6 +146,8 @@ static void acpi_probe_order(ACPI_HANDLE static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status); static BOOLEAN acpi_MatchHid(ACPI_HANDLE h, const char *hid); +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 void acpi_shutdown_final(void *arg, int howto); static void acpi_enable_fixed_events(struct acpi_softc *sc); @@ -152,6 +158,8 @@ static int acpi_wake_sysctl_walk(device_ 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 int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_pm_func(u_long cmd, void *arg, ...); @@ -227,9 +235,6 @@ static struct rman acpi_rman_io, acpi_rm #define ACPI_MINIMUM_AWAKETIME 5 -static const char* sleep_state_names[] = { - "S0", "S1", "S2", "S3", "S4", "S5", "NONE"}; - /* Holds the description of the acpi0 device. */ static char acpi_desc[ACPI_OEM_ID_SIZE + ACPI_OEM_TABLE_ID_SIZE + 2]; @@ -254,6 +259,12 @@ TUNABLE_INT("debug.acpi.do_powerstate", SYSCTL_INT(_debug_acpi, OID_AUTO, do_powerstate, CTLFLAG_RW, &acpi_do_powerstate, 1, "Turn off devices when suspending."); +/* Reset system clock while resuming. XXX Remove once tested. */ +static int acpi_reset_clock = 1; +TUNABLE_INT("debug.acpi.reset_clock", &acpi_reset_clock); +SYSCTL_INT(_debug_acpi, OID_AUTO, reset_clock, CTLFLAG_RW, + &acpi_reset_clock, 1, "Reset system clock while resuming."); + /* Allow users to override quirks. */ TUNABLE_INT("debug.acpi.quirks", &acpi_quirks); @@ -406,7 +417,6 @@ static int acpi_attach(device_t dev) { struct acpi_softc *sc; - ACPI_TABLE_FACS *facs; ACPI_STATUS status; int error, state; UINT32 flags; @@ -583,29 +593,31 @@ acpi_attach(device_t dev) } /* Only enable S4BIOS by default if the FACS says it is available. */ - status = AcpiGetTable(ACPI_SIG_FACS, 0, (ACPI_TABLE_HEADER **)&facs); - if (ACPI_FAILURE(status)) { - device_printf(dev, "couldn't get FACS: %s\n", - AcpiFormatException(status)); - error = ENXIO; - goto out; - } - if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT) + if (AcpiGbl_FACS->Flags & ACPI_FACS_S4_BIOS_PRESENT) sc->acpi_s4bios = 1; + /* Probe all supported sleep states. */ + acpi_sleep_states[ACPI_STATE_S0] = TRUE; + for (state = ACPI_STATE_S1; state < ACPI_S_STATE_COUNT; state++) + if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) + acpi_sleep_states[state] = TRUE; + /* * Dispatch the default sleep state to devices. The lid switch is set - * to NONE by default to avoid surprising users. + * to UNKNOWN by default to avoid surprising users. */ - sc->acpi_power_button_sx = ACPI_STATE_S5; - sc->acpi_lid_switch_sx = ACPI_S_STATES_MAX + 1; - sc->acpi_standby_sx = ACPI_STATE_S1; - sc->acpi_suspend_sx = ACPI_STATE_S3; + 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_S_STATES_MAX + 1; + sc->acpi_sleep_button_sx = ACPI_STATE_UNKNOWN; for (state = ACPI_STATE_S1; state <= ACPI_STATE_S4; state++) - if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) { + if (acpi_sleep_states[state]) { sc->acpi_sleep_button_sx = state; break; } @@ -630,9 +642,9 @@ acpi_attach(device_t dev) sc, ACPI_EVENT_PRI_LAST); /* Flag our initial states. */ - sc->acpi_enabled = 1; + sc->acpi_enabled = TRUE; sc->acpi_sstate = ACPI_STATE_S0; - sc->acpi_sleep_disabled = 0; + sc->acpi_sleep_disabled = TRUE; /* Create the control device */ sc->acpi_dev_t = make_dev(&acpi_cdevsw, 0, UID_ROOT, GID_WHEEL, 0644, @@ -648,6 +660,9 @@ acpi_attach(device_t dev) if (!acpi_disabled("bus")) acpi_probe_children(dev); + /* Allow sleep request after a while. */ + timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME); + error = 0; out: @@ -880,7 +895,7 @@ acpi_read_ivar(device_t dev, device_t ch struct acpi_device *ad; if ((ad = device_get_ivars(child)) == NULL) { - printf("device has no ivars\n"); + device_printf(child, "device has no ivars\n"); return (ENOENT); } @@ -919,7 +934,7 @@ acpi_write_ivar(device_t dev, device_t c struct acpi_device *ad; if ((ad = device_get_ivars(child)) == NULL) { - printf("device has no ivars\n"); + device_printf(child, "device has no ivars\n"); return (ENOENT); } @@ -1523,7 +1538,7 @@ acpi_set_powerstate_method(device_t bus, error = 0; h = acpi_get_handle(child); - if (state < ACPI_STATE_D0 || state > ACPI_STATE_D3) + if (state < ACPI_STATE_D0 || state > ACPI_D_STATES_MAX) return (EINVAL); if (h == NULL) return (0); @@ -1797,7 +1812,7 @@ acpi_fake_objhandler(ACPI_HANDLE h, UINT static void acpi_shutdown_final(void *arg, int howto) { - struct acpi_softc *sc; + struct acpi_softc *sc = (struct acpi_softc *)arg; ACPI_STATUS status; /* @@ -1805,42 +1820,42 @@ acpi_shutdown_final(void *arg, int howto * Some chipsets do not power off the system correctly if called from * an AP. */ - sc = arg; if ((howto & RB_POWEROFF) != 0) { status = AcpiEnterSleepStatePrep(ACPI_STATE_S5); if (ACPI_FAILURE(status)) { - printf("AcpiEnterSleepStatePrep failed - %s\n", - AcpiFormatException(status)); + device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n", + AcpiFormatException(status)); return; } - printf("Powering system off using ACPI\n"); + device_printf(sc->acpi_dev, "Powering system off\n"); ACPI_DISABLE_IRQS(); status = AcpiEnterSleepState(ACPI_STATE_S5); - if (ACPI_FAILURE(status)) { - printf("ACPI power-off failed - %s\n", AcpiFormatException(status)); - } else { + if (ACPI_FAILURE(status)) + device_printf(sc->acpi_dev, "power-off failed - %s\n", + AcpiFormatException(status)); + else { DELAY(1000000); - printf("ACPI power-off failed - timeout\n"); + device_printf(sc->acpi_dev, "power-off failed - timeout\n"); } } else if ((howto & RB_HALT) == 0 && (AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) && sc->acpi_handle_reboot) { /* Reboot using the reset register. */ - status = AcpiHwLowLevelWrite( - AcpiGbl_FADT.ResetRegister.BitWidth, + status = AcpiWrite( AcpiGbl_FADT.ResetValue, &AcpiGbl_FADT.ResetRegister); - if (ACPI_FAILURE(status)) { - printf("ACPI reset failed - %s\n", AcpiFormatException(status)); - } else { + if (ACPI_FAILURE(status)) + device_printf(sc->acpi_dev, "reset failed - %s\n", + AcpiFormatException(status)); + else { DELAY(1000000); - printf("ACPI reset failed - timeout\n"); + device_printf(sc->acpi_dev, "reset failed - timeout\n"); } } else if (sc->acpi_do_disable && panicstr == NULL) { /* * Only disable ACPI if the user requested. On some systems, writing * the disable value to SMI_CMD hangs the system. */ - printf("Shutting down ACPI\n"); + device_printf(sc->acpi_dev, "Shutting down\n"); AcpiTerminate(); } } @@ -2271,7 +2286,7 @@ acpi_SetSleepState(struct acpi_softc *sc static int once; if (!once) { - printf( + device_printf(sc->acpi_dev, "warning: acpi_SetSleepState() deprecated, need to update your software\n"); once = 1; } @@ -2282,12 +2297,13 @@ acpi_SetSleepState(struct acpi_softc *sc static void acpi_sleep_force(void *arg) { - struct acpi_softc *sc; + struct acpi_softc *sc = (struct acpi_softc *)arg; - printf("acpi: suspend request timed out, forcing sleep now\n"); - sc = arg; + device_printf(sc->acpi_dev, + "suspend request timed out, forcing sleep now\n"); if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_sstate))) - printf("acpi: force sleep state S%d failed\n", sc->acpi_next_sstate); + device_printf(sc->acpi_dev, "force sleep state S%d failed\n", + sc->acpi_next_sstate); } #endif @@ -2304,8 +2320,10 @@ acpi_ReqSleepState(struct acpi_softc *sc struct apm_clone_data *clone; #endif - if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5) + if (state < ACPI_STATE_S1 || state > ACPI_S_STATES_MAX) return (EINVAL); + if (!acpi_sleep_states[state]) + return (EOPNOTSUPP); /* S5 (soft-off) should be entered directly with no waiting. */ if (state == ACPI_STATE_S5) { @@ -2336,7 +2354,7 @@ acpi_ReqSleepState(struct acpi_softc *sc #endif /* If devd(8) is not running, immediately enter the sleep state. */ - if (devctl_process_running() == FALSE) { + if (!devctl_process_running()) { ACPI_UNLOCK(acpi); if (ACPI_SUCCESS(acpi_EnterSleepState(sc, sc->acpi_next_sstate))) { return (0); @@ -2345,9 +2363,6 @@ acpi_ReqSleepState(struct acpi_softc *sc } } - /* Now notify devd(8) also. */ - acpi_UserNotify("Suspend", ACPI_ROOT_OBJECT, state); - /* * Set a timeout to fire if userland doesn't ack the suspend request * in time. This way we still eventually go to sleep if we were @@ -2357,6 +2372,10 @@ acpi_ReqSleepState(struct acpi_softc *sc */ callout_reset(&sc->susp_force_to, 10 * hz, acpi_sleep_force, sc); ACPI_UNLOCK(acpi); + + /* Now notify devd(8) also. */ + acpi_UserNotify("Suspend", ACPI_ROOT_OBJECT, state); + return (0); #else /* This platform does not support acpi suspend/resume. */ @@ -2390,7 +2409,8 @@ acpi_AckSleepState(struct apm_clone_data if (error) { sc->acpi_next_sstate = 0; callout_stop(&sc->susp_force_to); - printf("acpi: listener on %s cancelled the pending suspend\n", + device_printf(sc->acpi_dev, + "listener on %s cancelled the pending suspend\n", devtoname(clone->cdev)); ACPI_UNLOCK(acpi); return (0); @@ -2432,8 +2452,34 @@ acpi_AckSleepState(struct apm_clone_data static void acpi_sleep_enable(void *arg) { + struct acpi_softc *sc = (struct acpi_softc *)arg; - ((struct acpi_softc *)arg)->acpi_sleep_disabled = 0; + /* Reschedule if the system is not fully up and running. */ + if (!AcpiGbl_SystemAwakeAndRunning) { + timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME); + return; + } + + ACPI_LOCK(acpi); + sc->acpi_sleep_disabled = FALSE; + ACPI_UNLOCK(acpi); +} + +static ACPI_STATUS +acpi_sleep_disable(struct acpi_softc *sc) +{ + ACPI_STATUS status; + + /* Fail if the system is not fully up and running. */ + if (!AcpiGbl_SystemAwakeAndRunning) + return (AE_ERROR); + + ACPI_LOCK(acpi); + status = sc->acpi_sleep_disabled ? AE_ERROR : AE_OK; + sc->acpi_sleep_disabled = TRUE; + ACPI_UNLOCK(acpi); + + return (status); } enum acpi_sleep_state { @@ -2453,22 +2499,34 @@ static ACPI_STATUS acpi_EnterSleepState(struct acpi_softc *sc, int state) { ACPI_STATUS status; - UINT8 TypeA; - UINT8 TypeB; enum acpi_sleep_state slp_state; ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state); + if (state < ACPI_STATE_S1 || state > ACPI_S_STATES_MAX) + 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); + return (AE_SUPPORT); + } + /* Re-entry once we're suspending is not allowed. */ - status = AE_OK; - ACPI_LOCK(acpi); - if (sc->acpi_sleep_disabled) { - ACPI_UNLOCK(acpi); - printf("acpi: suspend request ignored (not ready yet)\n"); - return (AE_ERROR); + status = acpi_sleep_disable(sc); + if (ACPI_FAILURE(status)) { + device_printf(sc->acpi_dev, + "suspend request ignored (not ready yet)\n"); + return (status); + } + + if (state == ACPI_STATE_S5) { + /* + * Shut down cleanly and power off. This will call us back through the + * shutdown handlers. + */ + shutdown_nice(RB_POWEROFF); + return_ACPI_STATUS (AE_OK); } - sc->acpi_sleep_disabled = 1; - ACPI_UNLOCK(acpi); #ifdef SMP thread_lock(curthread); @@ -2483,91 +2541,64 @@ acpi_EnterSleepState(struct acpi_softc * mtx_lock(&Giant); slp_state = ACPI_SS_NONE; - switch (state) { - case ACPI_STATE_S1: - case ACPI_STATE_S2: - case ACPI_STATE_S3: - case ACPI_STATE_S4: - status = AcpiGetSleepTypeData(state, &TypeA, &TypeB); - if (status == AE_NOT_FOUND) { - device_printf(sc->acpi_dev, - "Sleep state S%d not supported by BIOS\n", state); - break; - } else if (ACPI_FAILURE(status)) { - device_printf(sc->acpi_dev, "AcpiGetSleepTypeData failed - %s\n", - AcpiFormatException(status)); - break; - } - sc->acpi_sstate = state; + sc->acpi_sstate = state; - /* Enable any GPEs as appropriate and requested by the user. */ - acpi_wake_prep_walk(state); - slp_state = ACPI_SS_GPE_SET; + /* Enable any GPEs as appropriate and requested by the user. */ + acpi_wake_prep_walk(state); + slp_state = ACPI_SS_GPE_SET; - /* - * Inform all devices that we are going to sleep. If at least one - * device fails, DEVICE_SUSPEND() automatically resumes the tree. - * - * XXX Note that a better two-pass approach with a 'veto' pass - * followed by a "real thing" pass would be better, but the current - * bus interface does not provide for this. - */ - if (DEVICE_SUSPEND(root_bus) != 0) { - device_printf(sc->acpi_dev, "device_suspend failed\n"); - break; - } - slp_state = ACPI_SS_DEV_SUSPEND; + /* + * Inform all devices that we are going to sleep. If at least one + * device fails, DEVICE_SUSPEND() automatically resumes the tree. + * + * XXX Note that a better two-pass approach with a 'veto' pass + * followed by a "real thing" pass would be better, but the current + * bus interface does not provide for this. + */ + if (DEVICE_SUSPEND(root_bus) != 0) { + device_printf(sc->acpi_dev, "device_suspend failed\n"); + goto backout; + } + slp_state = ACPI_SS_DEV_SUSPEND; - /* If testing device suspend only, back out of everything here. */ - if (acpi_susp_bounce) - break; + /* If testing device suspend only, back out of everything here. */ + if (acpi_susp_bounce) + goto backout; - status = AcpiEnterSleepStatePrep(state); - if (ACPI_FAILURE(status)) { - device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n", - AcpiFormatException(status)); - break; - } - slp_state = ACPI_SS_SLP_PREP; + status = AcpiEnterSleepStatePrep(state); + 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); + if (sc->acpi_sleep_delay > 0) + DELAY(sc->acpi_sleep_delay * 1000000); - if (state != ACPI_STATE_S1) { - acpi_sleep_machdep(sc, state); + if (state != ACPI_STATE_S1) { + acpi_sleep_machdep(sc, state); - /* Re-enable ACPI hardware on wakeup from sleep state 4. */ - if (state == ACPI_STATE_S4) - AcpiEnable(); - } else { - ACPI_DISABLE_IRQS(); - status = AcpiEnterSleepState(state); - if (ACPI_FAILURE(status)) { - device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", - AcpiFormatException(status)); - break; - } + /* Re-enable ACPI hardware on wakeup from sleep state 4. */ + if (state == ACPI_STATE_S4) + AcpiEnable(); + } else { + ACPI_DISABLE_IRQS(); + status = AcpiEnterSleepState(state); + if (ACPI_FAILURE(status)) { + device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", + AcpiFormatException(status)); + goto backout; } - slp_state = ACPI_SS_SLEPT; - break; - case ACPI_STATE_S5: - /* - * Shut down cleanly and power off. This will call us back through the - * shutdown handlers. - */ - shutdown_nice(RB_POWEROFF); - break; - case ACPI_STATE_S0: - default: - status = AE_BAD_PARAMETER; - break; } + 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: sc->acpi_next_sstate = 0; if (slp_state >= ACPI_SS_GPE_SET) { acpi_wake_prep_walk(state); @@ -2580,28 +2611,39 @@ acpi_EnterSleepState(struct acpi_softc * if (slp_state >= ACPI_SS_SLEPT) acpi_enable_fixed_events(sc); - /* Allow another sleep request after a while. */ - if (state != ACPI_STATE_S5) - timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME); - - /* Run /etc/rc.resume after we are back. */ - acpi_UserNotify("Resume", ACPI_ROOT_OBJECT, state); - mtx_unlock(&Giant); - /* Warm up timecounter again */ - (void)timecounter->tc_get_timecount(timecounter); - (void)timecounter->tc_get_timecount(timecounter); - #ifdef SMP thread_lock(curthread); sched_unbind(curthread); thread_unlock(curthread); #endif + /* Allow another sleep request after a while. */ + timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME); + + /* Run /etc/rc.resume after we are back. */ + if (devctl_process_running()) + acpi_UserNotify("Resume", ACPI_ROOT_OBJECT, state); + return_ACPI_STATUS (status); } +void +acpi_resync_clock(struct acpi_softc *sc) +{ + + if (!acpi_reset_clock) + return; + + /* + * Warm up timecounter again and reset system clock. + */ + (void)timecounter->tc_get_timecount(timecounter); + (void)timecounter->tc_get_timecount(timecounter); + inittodr(time_second + sc->acpi_sleep_delay); +} + /* Initialize a device's wake GPE. */ int acpi_wake_init(device_t dev, int type) @@ -2906,19 +2948,20 @@ out: static void acpi_system_eventhandler_sleep(void *arg, int state) { + struct acpi_softc *sc = (struct acpi_softc *)arg; int ret; ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state); - /* Check if button action is disabled. */ - if (state == ACPI_S_STATES_MAX + 1) + /* Check if button action is disabled or unknown. */ + if (state == ACPI_STATE_UNKNOWN) return; /* Request that the system prepare to enter the given suspend state. */ - ret = acpi_ReqSleepState((struct acpi_softc *)arg, state); + ret = acpi_ReqSleepState(sc, state); if (ret != 0) - printf("acpi: request to enter state S%d failed (err %d)\n", - state, ret); + device_printf(sc->acpi_dev, + "request to enter state S%d failed (err %d)\n", state, ret); return_VOID; } @@ -3135,19 +3178,19 @@ acpi_deregister_ioctl(u_long cmd, acpi_i } static int -acpiopen(struct cdev *dev, int flag, int fmt, d_thread_t *td) +acpiopen(struct cdev *dev, int flag, int fmt, struct thread *td) { return (0); } static int -acpiclose(struct cdev *dev, int flag, int fmt, d_thread_t *td) +acpiclose(struct cdev *dev, int flag, int fmt, struct thread *td) { return (0); } static int -acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td) +acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) { struct acpi_softc *sc; struct acpi_ioctl_hook *hp; @@ -3183,22 +3226,22 @@ acpiioctl(struct cdev *dev, u_long cmd, case ACPIIO_REQSLPSTATE: state = *(int *)addr; if (state != ACPI_STATE_S5) - error = acpi_ReqSleepState(sc, state); - else { - printf("power off via acpi ioctl not supported\n"); - error = ENXIO; - } + return (acpi_ReqSleepState(sc, state)); + device_printf(sc->acpi_dev, "power off via acpi ioctl not supported\n"); + error = EOPNOTSUPP; break; case ACPIIO_ACKSLPSTATE: error = *(int *)addr; error = acpi_AckSleepState(sc->acpi_clone, error); break; case ACPIIO_SETSLPSTATE: /* DEPRECATED */ - error = EINVAL; state = *(int *)addr; - if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX) - if (ACPI_SUCCESS(acpi_SetSleepState(sc, state))) - error = 0; + if (state < ACPI_STATE_S0 || state > ACPI_S_STATES_MAX) + return (EINVAL); + if (!acpi_sleep_states[state]) + return (EOPNOTSUPP); + if (ACPI_FAILURE(acpi_SetSleepState(sc, state))) + error = ENXIO; break; default: error = ENXIO; @@ -3209,16 +3252,43 @@ acpiioctl(struct cdev *dev, u_long cmd, } static int +acpi_sname2sstate(const char *sname) +{ + int sstate; + + 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); + return (-1); +} + +static const char * +acpi_sstate2sname(int sstate) +{ + static const char *snames[] = { "S0", "S1", "S2", "S3", "S4", "S5" }; + + if (sstate >= ACPI_STATE_S0 && sstate <= ACPI_STATE_S5) + return (snames[sstate]); + else if (sstate == ACPI_STATE_UNKNOWN) + return ("NONE"); + return (NULL); +} + +static int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS) { int error; struct sbuf sb; - UINT8 state, TypeA, TypeB; + UINT8 state; sbuf_new(&sb, NULL, 32, SBUF_AUTOEXTEND); - for (state = ACPI_STATE_S1; state < ACPI_S_STATES_MAX + 1; state++) - if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) - sbuf_printf(&sb, "S%d ", state); + for (state = ACPI_STATE_S1; state < ACPI_S_STATE_COUNT; state++) + if (acpi_sleep_states[state]) + sbuf_printf(&sb, "%s ", acpi_sstate2sname(state)); sbuf_trim(&sb); sbuf_finish(&sb); error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req); @@ -3230,27 +3300,20 @@ static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS) { char sleep_state[10]; - int error; - u_int new_state, old_state; + int error, new_state, old_state; - old_state = *(u_int *)oidp->oid_arg1; - if (old_state > ACPI_S_STATES_MAX + 1) - strlcpy(sleep_state, "unknown", sizeof(sleep_state)); - else - strlcpy(sleep_state, sleep_state_names[old_state], sizeof(sleep_state)); + 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); if (error == 0 && req->newptr != NULL) { - new_state = ACPI_STATE_S0; - for (; new_state <= ACPI_S_STATES_MAX + 1; new_state++) - if (strcmp(sleep_state, sleep_state_names[new_state]) == 0) - break; - if (new_state <= ACPI_S_STATES_MAX + 1) { - if (new_state != old_state) - *(u_int *)oidp->oid_arg1 = new_state; - } else - error = EINVAL; + new_state = acpi_sname2sstate(sleep_state); + if (new_state < ACPI_STATE_S1) + return (EINVAL); + if (new_state < ACPI_S_STATE_COUNT && !acpi_sleep_states[new_state]) + return (EOPNOTSUPP); + if (new_state != old_state) + *(int *)oidp->oid_arg1 = new_state; } - return (error); } @@ -3320,8 +3383,6 @@ static struct debugtag dbg_layer[] = { }; static struct debugtag dbg_level[] = { - {"ACPI_LV_ERROR", ACPI_LV_ERROR}, - {"ACPI_LV_WARN", ACPI_LV_WARN}, {"ACPI_LV_INIT", ACPI_LV_INIT}, {"ACPI_LV_DEBUG_OBJECT", ACPI_LV_DEBUG_OBJECT}, {"ACPI_LV_INFO", ACPI_LV_INFO},
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906171143.n5HBhX1G074380>