Index: share/man/man4/acpi_thermal.4 =================================================================== --- share/man/man4/acpi_thermal.4 +++ share/man/man4/acpi_thermal.4 @@ -84,6 +84,9 @@ .It Va hw.acpi.thermal.tz%d._PSV Temperature to start passive cooling by throttling down CPU, etc. This value can be overridden by the user. +.It Va hw.acpi.thermal.tz%d._CR3 +Temperature to start critical suspend to RAM (S3). +This value can be overridden by the user. .It Va hw.acpi.thermal.tz%d._HOT Temperature to start critical suspend to disk (S4). This value can be overridden by the user. Index: sys/dev/acpica/acpi_thermal.c =================================================================== --- sys/dev/acpica/acpi_thermal.c +++ sys/dev/acpica/acpi_thermal.c @@ -60,7 +60,7 @@ #define TZ_NOTIFY_TEMPERATURE 0x80 /* Temperature changed. */ #define TZ_NOTIFY_LEVELS 0x81 /* Cooling levels changed. */ #define TZ_NOTIFY_DEVICES 0x82 /* Device lists changed. */ -#define TZ_NOTIFY_CRITICAL 0xcc /* Fake notify that _CRT/_HOT reached. */ +#define TZ_NOTIFY_CRITICAL 0xcc /* Fake notify that _CRT/_HOT/_CR3 reached. */ /* Check for temperature changes every 10 seconds by default */ #define TZ_POLLRATE 10 @@ -78,6 +78,7 @@ ACPI_BUFFER al[TZ_NUMLEVELS]; int crt; int hot; + int cr3; ACPI_BUFFER psl; int psv; int tc1; @@ -97,8 +98,9 @@ int tz_thflags; /*Current temp-related flags*/ #define TZ_THFLAG_NONE 0 #define TZ_THFLAG_PSV (1<<0) -#define TZ_THFLAG_HOT (1<<2) -#define TZ_THFLAG_CRT (1<<3) +#define TZ_THFLAG_CR3 (1<<2) +#define TZ_THFLAG_HOT (1<<3) +#define TZ_THFLAG_CRT (1<<4) int tz_flags; #define TZ_FLAG_NO_SCP (1<<0) /*No _SCP method*/ #define TZ_FLAG_GETPROFILE (1<<1) /*Get power_profile in timeout*/ @@ -282,6 +284,10 @@ OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, offsetof(struct acpi_tz_softc, tz_zone.psv), acpi_tz_temp_sysctl, "IK", "passive cooling temp setpoint"); + SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree), + OID_AUTO, "_CR3", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, + offsetof(struct acpi_tz_softc, tz_zone.cr3), acpi_tz_temp_sysctl, "IK", + "too warm temp setpoint (standby now)"); SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree), OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, offsetof(struct acpi_tz_softc, tz_zone.hot), acpi_tz_temp_sysctl, "IK", @@ -421,6 +427,7 @@ } acpi_tz_getparam(sc, "_CRT", &sc->tz_zone.crt); acpi_tz_getparam(sc, "_HOT", &sc->tz_zone.hot); + acpi_tz_getparam(sc, "_CR3", &sc->tz_zone.cr3); sc->tz_zone.psl.Length = ACPI_ALLOCATE_BUFFER; sc->tz_zone.psl.Pointer = NULL; AcpiEvaluateObject(sc->tz_handle, "_PSL", NULL, &sc->tz_zone.psl); @@ -438,6 +445,7 @@ */ acpi_tz_sanity(sc, &sc->tz_zone.crt, "_CRT"); acpi_tz_sanity(sc, &sc->tz_zone.hot, "_HOT"); + acpi_tz_sanity(sc, &sc->tz_zone.cr3, "_CR3"); acpi_tz_sanity(sc, &sc->tz_zone.psv, "_PSV"); for (i = 0; i < TZ_NUMLEVELS; i++) acpi_tz_sanity(sc, &sc->tz_zone.ac[i], "_ACx"); @@ -495,6 +503,7 @@ static void acpi_tz_monitor(void *Context) { + struct acpi_softc *acpi_sc; struct acpi_tz_softc *sc; struct timespec curtime; int temp; @@ -545,6 +554,8 @@ newflags = TZ_THFLAG_NONE; if (sc->tz_zone.psv != -1 && temp >= sc->tz_zone.psv) newflags |= TZ_THFLAG_PSV; + if (sc->tz_zone.cr3 != -1 && temp >= sc->tz_zone.cr3) + newflags |= TZ_THFLAG_CR3; if (sc->tz_zone.hot != -1 && temp >= sc->tz_zone.hot) newflags |= TZ_THFLAG_HOT; if (sc->tz_zone.crt != -1 && temp >= sc->tz_zone.crt) @@ -604,13 +615,18 @@ * * If we're almost at that threshold, notify the user through devd(8). */ - if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) { + if ((newflags & (TZ_THFLAG_CR3 | TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) { sc->tz_validchecks++; if (sc->tz_validchecks == TZ_VALIDCHECKS) { device_printf(sc->tz_dev, "WARNING - current temperature (%d.%dC) exceeds safe limits\n", TZ_KELVTOC(sc->tz_temperature)); - shutdown_nice(RB_POWEROFF); + if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) + shutdown_nice(RB_POWEROFF); + else { + acpi_sc = acpi_device_get_parent_softc(sc->tz_dev); + acpi_ReqSleepState(acpi_sc, ACPI_STATE_S3); + } } else if (sc->tz_validchecks == TZ_NOTIFYCOUNT) acpi_UserNotify("Thermal", sc->tz_handle, TZ_NOTIFY_CRITICAL); } else {