diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2008-01-06 18:06:51 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2008-01-06 18:06:51 +0000 |
commit | c2e51257c1f212071e959a7dfcff600433dac334 (patch) | |
tree | f4b57a397e21b9650346b1efade49ff720f776fd /sys/dev | |
parent | 379ad048e58ff0bf4a6a8022ce465bf88c8b3499 (diff) |
Add a more robust gettempreading that debounces the value (idea from FreeBSD)
Add a macro to convert from K to C
Redo notify and sprinkle some debug
Tested on D810 T60 & Q2010 and tested by several others.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/acpi/acpitz.c | 122 |
1 files changed, 92 insertions, 30 deletions
diff --git a/sys/dev/acpi/acpitz.c b/sys/dev/acpi/acpitz.c index 861c508a0bc..10a989d9c3c 100644 --- a/sys/dev/acpi/acpitz.c +++ b/sys/dev/acpi/acpitz.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpitz.c,v 1.20 2007/11/12 21:38:31 deraadt Exp $ */ +/* $OpenBSD: acpitz.c,v 1.21 2008/01/06 18:06:50 marco Exp $ */ /* * Copyright (c) 2006 Can Erkin Acar <canacar@openbsd.org> * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> @@ -22,6 +22,7 @@ #include <sys/systm.h> #include <sys/device.h> #include <sys/malloc.h> +#include <sys/kernel.h> #include <machine/bus.h> @@ -33,7 +34,9 @@ #include <sys/sensors.h> -#define ACPITZ_MAX_AC 10 +#define KTOC(k) ((k - 2732) / 10) +#define ACPITZ_MAX_AC (10) +#define ACPITZ_TMP_RETRY (3) struct acpitz_softc { struct device sc_dev; @@ -69,6 +72,7 @@ struct cfdriver acpitz_cd = { void acpitz_monitor(struct acpitz_softc *); void acpitz_refresh(void *); int acpitz_notify(struct aml_node *, int, void *); +int acpitz_gettempreading(struct acpitz_softc *, char *); int acpitz_getreading(struct acpitz_softc *, char *); int acpitz_setfan(struct acpitz_softc *, int, char *); int acpitz_setcpu(struct acpitz_softc *, int); @@ -103,28 +107,31 @@ acpitz_attach(struct device *parent, struct device *self, void *aux) sc->sc_devnode = aa->aaa_node->child; sc->sc_lasttmp = -1; - if ((sc->sc_tmp = acpitz_getreading(sc, "_TMP")) == -1) { + if ((sc->sc_tmp = acpitz_gettempreading(sc, "_TMP")) == -1) { printf(": failed to read _TMP\n"); return; } - if ((sc->sc_crt = acpitz_getreading(sc, "_CRT")) == -1) { + if ((sc->sc_crt = acpitz_gettempreading(sc, "_CRT")) == -1) printf(": no critical temperature defined\n"); - sc->sc_crt = 0; - } else - printf(": critical temperature %d degC\n", - (sc->sc_crt - 2732) / 10); + else + printf(": critical temperature %d degC\n", KTOC(sc->sc_crt)); for (i = 0; i < ACPITZ_MAX_AC; i++) { snprintf(name, sizeof name, "_AC%d", i); - sc->sc_ac[i] = acpitz_getreading(sc, name); + sc->sc_ac[i] = acpitz_gettempreading(sc, name); sc->sc_ac_stat[0] = -1; } - sc->sc_hot = acpitz_getreading(sc, "_HOT"); + sc->sc_hot = acpitz_gettempreading(sc, "_HOT"); sc->sc_tc1 = acpitz_getreading(sc, "_TC1"); sc->sc_tc2 = acpitz_getreading(sc, "_TC2"); - sc->sc_psv = acpitz_getreading(sc, "_PSV"); + sc->sc_psv = acpitz_gettempreading(sc, "_PSV"); + dnprintf(10, "%s: _HOT: %d _TC1: %d _TC2: %d _PSV: %d _TMP: %d " + "_CRT: %d\n", DEVNAME(sc), sc->sc_hot, sc->sc_tc1, sc->sc_tc2, + sc->sc_psv, sc->sc_tmp, sc->sc_crt); + + /* get _PSL */ strlcpy(sc->sc_sensdev.xname, DEVNAME(sc), sizeof(sc->sc_sensdev.xname)); @@ -140,7 +147,7 @@ acpitz_attach(struct device *parent, struct device *self, void *aux) } int -acpitz_setcpu(struct acpitz_softc *sc, int trend) +acpitz_setcpu(struct acpitz_softc *sc, int perc) { struct aml_value res0, *ref; int x; @@ -155,7 +162,8 @@ acpitz_setcpu(struct acpitz_softc *sc, int trend) } for (x = 0; x < res0.length; x++) { if (res0.v_package[x]->type != AML_OBJTYPE_OBJREF) { - printf("%s: _PSL[%d] not a object ref\n", DEVNAME(sc), x); + printf("%s: _PSL[%d] not a object ref\n", + DEVNAME(sc), x); continue; } ref = res0.v_package[x]->v_objref.ref; @@ -241,40 +249,53 @@ void acpitz_refresh(void *arg) { struct acpitz_softc *sc = arg; - int i, trend; + int i, perc; extern int acpi_s5; dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc), sc->sc_devnode->parent->name); - if (-1 == (sc->sc_tmp = acpitz_getreading(sc, "_TMP"))) { - dnprintf(30, "%s: %s: failed to read temp\n", DEVNAME(sc), + /* get _TMP and debounce the value */ + if (-1 == (sc->sc_tmp = acpitz_gettempreading(sc, "_TMP"))) { + printf("%s: %s: failed to read temp\n", DEVNAME(sc), sc->sc_devnode->parent->name); - sc->sc_tmp = 0; /* XXX */ + return; } - + /* critical trip points */ if (sc->sc_crt != -1 && sc->sc_crt <= sc->sc_tmp) { - /* Do critical shutdown */ + /* do critical shutdown */ printf("%s: Critical temperature, shutting down\n", DEVNAME(sc)); acpi_s5 = 1; psignal(initproc, SIGUSR1); } - if (sc->sc_hot != -1 && sc->sc_hot <= sc->sc_tmp) + if (sc->sc_hot != -1 && sc->sc_hot <= sc->sc_tmp) { printf("%s: _HOT temperature\n", DEVNAME(sc)); + /* XXX go to S4, until then cool as hard as we can */ + } + /* passive cooling */ if (sc->sc_lasttmp != -1 && sc->sc_tc1 != -1 && sc->sc_tc2 != -1 && sc->sc_psv != -1) { + dnprintf(30, "%s: passive cooling: lasttmp: %d tc1: %d " + "tc2: %d psv: %d\n", DEVNAME(sc), sc->sc_lasttmp, + sc->sc_tc1, sc->sc_tc2, sc->sc_psv); if (sc->sc_psv <= sc->sc_tmp) { sc->sc_pse = 1; - trend = sc->sc_tc1 * (sc->sc_tmp - sc->sc_lasttmp) + + perc = sc->sc_tc1 * (sc->sc_tmp - sc->sc_lasttmp) + sc->sc_tc2 * (sc->sc_tmp - sc->sc_psv); - /* printf("_TZ trend = %d\n", trend); */ + perc /= 10; + if (perc < 0) + perc = 0; + else if (perc > 100) + perc = 100; + /* printf("_TZ perc = %d\n", perc); */ } else if (sc->sc_pse) sc->sc_pse = 0; } sc->sc_lasttmp = sc->sc_tmp; + /* active cooling */ for (i = 0; i < ACPITZ_MAX_AC; i++) { if (sc->sc_ac[i] != -1 && sc->sc_ac[i] <= sc->sc_tmp) { /* turn on fan i */ @@ -296,36 +317,77 @@ acpitz_getreading(struct acpitz_softc *sc, char *name) int rv = -1; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name, 0, NULL, &res)) { - dnprintf(10, "%s: no %s\n", DEVNAME(sc), name); + dnprintf(10, "%s: acpitz_getreading: no %s\n", DEVNAME(sc), name); + aml_freevalue(&res); goto out; } rv = aml_val2int(&res); - out: +out: aml_freevalue(&res); return (rv); } int +acpitz_gettempreading(struct acpitz_softc *sc, char *name) +{ + int rv = -1, tmp = -1, i; + + for (i = 0; i < ACPITZ_TMP_RETRY; i++) { + tmp = acpitz_getreading(sc, name); + if (tmp == -1) + goto out; + if (KTOC(tmp) > 0) { + rv = tmp; + break; + } else { + dnprintf(20, "%s: %d invalid reading on %s, " + "debouncing\n", DEVNAME(sc), tmp, name); + } + + /* debounce value */ + if (cold) + delay(1000000); + else + while (tsleep(sc, PWAIT, "tzsleep", hz) != + EWOULDBLOCK); + } + if (i >= ACPITZ_TMP_RETRY) { + printf("%s: %s: failed to read %s\n", DEVNAME(sc), + sc->sc_devnode->parent->name, name); + goto out; + } + out: + dnprintf(30, "%s: name: %s tmp: %dK => %dC, rv: %d\n", DEVNAME(sc), + name, tmp, KTOC(tmp), rv); + return (rv); +} + +int acpitz_notify(struct aml_node *node, int notify_type, void *arg) { struct acpitz_softc *sc = arg; - u_int64_t crt; + int crt; dnprintf(10, "%s notify: %.2x %s\n", DEVNAME(sc), notify_type, sc->sc_devnode->parent->name); switch (notify_type) { - case 0x81: /* Operating Points changed */ - sc->sc_psv = acpitz_getreading(sc, "_PSV"); + case 0x80: /* hardware notifications */ + break; + case 0x81: /* operating Points changed */ + sc->sc_psv = acpitz_gettempreading(sc, "_PSV"); crt = sc->sc_crt; - sc->sc_crt = acpitz_getreading(sc, "_CRT"); + sc->sc_crt = acpitz_gettempreading(sc, "_CRT"); if (crt != sc->sc_crt) - printf("%s: critical temperature: %u degC", - DEVNAME(sc), (sc->sc_crt - 2732) / 10); + printf("%s: new critical temperature: %u degC", + DEVNAME(sc), KTOC(sc->sc_crt)); + break; + case 0x82: /* re-evaluate thermal device list */ break; default: break; } + acpitz_refresh(sc); return (0); } |