Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/acpi By reading the ACPI dump I figured out that my



details:   https://anonhg.NetBSD.org/src/rev/e0da2c25e1ce
branches:  trunk
changeset: 749291:e0da2c25e1ce
user:      cegger <cegger%NetBSD.org@localhost>
date:      Wed Nov 25 13:54:23 2009 +0000

description:
By reading the ACPI dump I figured out that my
HP Pavillion dv9700 laptop features a fan sensor
in the ACPI Thermal Zone which is beyond of the ACPI
Spec.

envstat shows
[acpitz0]
  Processor Thermal Zone:     56.000   95.000                       degC
                     FAN:       2840                                 RPM

envstat -W shows the limits
[acpitz0]
  Processor Thermal Zone:     55.000                                degC
                     FAN:       2570     4500     2000               RPM

Patch presented on tech-kern@.

No comments.

diffstat:

 sys/dev/acpi/acpi_tz.c |  183 +++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 155 insertions(+), 28 deletions(-)

diffs (truncated from 319 to 300 lines):

diff -r ad29805f228a -r e0da2c25e1ce sys/dev/acpi/acpi_tz.c
--- a/sys/dev/acpi/acpi_tz.c    Wed Nov 25 13:53:19 2009 +0000
+++ b/sys/dev/acpi/acpi_tz.c    Wed Nov 25 13:54:23 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_tz.c,v 1.48 2009/11/23 14:42:39 cegger Exp $ */
+/* $NetBSD: acpi_tz.c,v 1.49 2009/11/25 13:54:23 cegger Exp $ */
 
 /*
  * Copyright (c) 2003 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.48 2009/11/23 14:42:39 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.49 2009/11/25 13:54:23 cegger Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -100,13 +100,17 @@
        /* Thermal constants for use in passive cooling formulas */
        UINT32 tc1, tc2;
        /* Current temperature of the thermal zone */
-       UINT32 tmp;
+       UINT32 prevtmp, tmp;
        /* Thermal sampling period for passive cooling, in tenths of seconds */
        UINT32 tsp;
        /* Package of references to devices in this TZ (optional) */
        ACPI_BUFFER tzd;
        /* Recommended TZ polling frequency, in tenths of seconds */
        UINT32 tzp;
+       /* Thermal zone name */
+       char *name;
+       /* FAN min, max, current rpms */
+       UINT32 fanmin, fanmax, fancurrent;
 };
 
 struct acpitz_softc {
@@ -114,13 +118,15 @@
        struct acpitz_zone sc_zone;
        struct callout sc_callout;
        struct sysmon_envsys *sc_sme;
-       envsys_data_t sc_sensor;
+       envsys_data_t sc_temp_sensor;
+       envsys_data_t sc_fan_sensor;
        int sc_active;          /* active cooling level */
        int sc_flags;
        int sc_rate;            /* tz poll rate */
        int sc_zone_expire;
 
        int sc_first;
+       int sc_have_fan;        /* FAN sensor is optional */
 };
 
 static void    acpitz_get_status(void *);
@@ -139,6 +145,11 @@
 static void    acpitz_init_envsys(device_t);
 static void    acpitz_get_limits(struct sysmon_envsys *, envsys_data_t *,
                                  sysmon_envsys_lim_t *);
+static int     acpitz_get_fanspeed(device_t, UINT32 *, UINT32 *, UINT32 *);
+#ifdef notyet
+static ACPI_STATUS
+               acpitz_set_fanspeed(device_t, UINT32);
+#endif
 
 CFATTACH_DECL_NEW(acpitz, sizeof(struct acpitz_softc), acpitz_match,
     acpitz_attach, NULL, NULL);
@@ -190,7 +201,16 @@
 
        sc->sc_zone_expire = ATZ_ZONE_EXPIRE / sc->sc_zone.tzp;
        sc->sc_first = 1;
+       sc->sc_have_fan = 0;
+       if (acpitz_get_fanspeed(self,
+           &sc->sc_zone.fanmin, &sc->sc_zone.fanmax, &sc->sc_zone.fancurrent)
+           == 0)
+               sc->sc_have_fan = 1;
 
+       rv = acpi_eval_string(sc->sc_devnode->ad_handle,
+           "REGN", &sc->sc_zone.name);
+       if (ACPI_FAILURE(rv))
+               sc->sc_zone.name = __UNCONST("temperature");
        acpitz_get_zone(self, 1);
        acpitz_get_status(self);
 
@@ -226,6 +246,7 @@
        struct acpitz_softc *sc = device_private(dv);
        UINT32 tmp, active;
        int i, flags;
+       UINT32 fmin, fmax, fcurrent;
 
        sc->sc_zone_expire--;
        if (sc->sc_zone_expire <= 0) {
@@ -239,17 +260,29 @@
                aprint_error_dev(dv, "failed to evaluate _TMP\n");
                return;
        }
+
+       sc->sc_zone.prevtmp = sc->sc_zone.tmp;
        sc->sc_zone.tmp = tmp;
+       if (sc->sc_first)
+               sc->sc_zone.prevtmp = tmp;
        /* XXX sanity check for tmp here? */
 
+       if (acpitz_get_fanspeed(dv, &fmin, &fmax, &fcurrent) == 0) {
+               if (fcurrent != ATZ_TMP_INVALID)
+                       sc->sc_zone.fancurrent = fcurrent;
+       }
+
        /*
         * The temperature unit for envsys(4) is microKelvin, so convert to
         * that from ACPI's microKelvin. Also, the ACPI specification assumes
         * that K = C + 273.2 rather than the nominal 273.15 used by envsys(4),
         * so we correct for that too.
         */
-       sc->sc_sensor.value_cur = ATZ2UKELVIN(sc->sc_zone.tmp);
-       sc->sc_sensor.state = ENVSYS_SVALID;
+       sc->sc_temp_sensor.value_cur = ATZ2UKELVIN(sc->sc_zone.tmp);
+       sc->sc_temp_sensor.state = ENVSYS_SVALID;
+
+       sc->sc_fan_sensor.value_cur = sc->sc_zone.fancurrent;
+       sc->sc_fan_sensor.state = ENVSYS_SVALID;
 
        if (sc->sc_flags & ATZ_F_VERBOSE)
                acpitz_print_status(dv);
@@ -271,7 +304,7 @@
                                active = i;
                }
                if (active != ATZ_ACTIVE_NONE)
-                       sc->sc_sensor.state = ENVSYS_SWARNOVER;
+                       sc->sc_temp_sensor.state = ENVSYS_SWARNOVER;
 
                flags = sc->sc_flags &
                    ~(ATZ_F_CRITICAL|ATZ_F_HOT|ATZ_F_PASSIVE);
@@ -289,12 +322,12 @@
                        int changed = (sc->sc_flags ^ flags) & flags;
                        sc->sc_flags = flags;
                        if (changed & ATZ_F_CRITICAL) {
-                               sc->sc_sensor.state = ENVSYS_SCRITOVER;
+                               sc->sc_temp_sensor.state = ENVSYS_SCRITOVER;
                                aprint_debug_dev(dv,
                                    "zone went critical at temp %sC\n",
                                    acpitz_celcius_string(tmp));
                        } else if (changed & ATZ_F_HOT) {
-                               sc->sc_sensor.state = ENVSYS_SCRITOVER;
+                               sc->sc_temp_sensor.state = ENVSYS_SCRITOVER;
                                aprint_debug_dev(dv,
                                    "zone went hot at temp %sC\n",
                                    acpitz_celcius_string(tmp));
@@ -338,6 +371,10 @@
 
        printf("%s: zone temperature is now %sC\n", device_xname(dv),
            acpitz_celcius_string(sc->sc_zone.tmp));
+       if (sc->sc_have_fan) {
+               printf("%s: fan rpm %u\n", device_xname(dv),
+                   sc->sc_zone.fancurrent);
+       }
 
        return;
 }
@@ -478,7 +515,8 @@
        acpitz_get_integer(dv, "_HOT", &sc->sc_zone.hot);
        sc->sc_zone.psl.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
        sc->sc_zone.psl.Pointer = NULL;
-       AcpiEvaluateObject(sc, "_PSL", NULL, &sc->sc_zone.psl);
+       AcpiEvaluateObject(sc->sc_devnode->ad_handle,
+           "_PSL", NULL, &sc->sc_zone.psl);
        acpitz_get_integer(dv, "_PSV", &sc->sc_zone.psv);
        acpitz_get_integer(dv, "_TC1", &sc->sc_zone.tc1);
        acpitz_get_integer(dv, "_TC2", &sc->sc_zone.tc2);
@@ -584,6 +622,59 @@
        return 0;
 }
 
+static int
+acpitz_get_fanspeed(device_t dv,
+    UINT32 *fanmin, UINT32 *fanmax, UINT32 *fancurrent)
+{
+       struct acpitz_softc *sc = device_private(dv);
+       ACPI_STATUS rv;
+       ACPI_HANDLE handle;
+       ACPI_INTEGER fmin, fmax, fcurr;
+       int rc = 0;
+
+       handle = sc->sc_devnode->ad_handle;
+       rv = acpi_eval_integer(handle, "FMIN", &fmin);
+       if (ACPI_FAILURE(rv)) {
+               fmin = ATZ_TMP_INVALID;
+               rc = 1;
+       }
+       rv = acpi_eval_integer(handle, "FMAX", &fmax);
+       if (ACPI_FAILURE(rv)) {
+               fmax = ATZ_TMP_INVALID;
+               rc = 1;
+       }
+       rv = acpi_eval_integer(handle, "FRSP", &fcurr);
+       if (ACPI_FAILURE(rv)) {
+               fcurr = ATZ_TMP_INVALID;
+               rc = 1;
+       }
+
+       if (fanmin)
+               *fanmin = fmin;
+       if (fanmax)
+               *fanmax = fmax;
+       if (fancurrent)
+               *fancurrent = fcurr;
+       return rc;
+}
+
+#ifdef notyet
+static ACPI_STATUS
+acpitz_set_fanspeed(device_t dv, UINT32 fanspeed)
+{
+       struct acpitz_softc *sc = device_private(dv);
+       ACPI_STATUS rv;
+       ACPI_HANDLE handle;
+       handle = sc->sc_devnode->ad_handle;
+
+       rv = acpi_eval_set_integer(handle, "FSSP", fanspeed);
+       if (ACPI_FAILURE(rv))
+               aprint_debug_dev(dv, "failed to set fanspeed to %u rpm: %s\n",
+                       fanspeed, AcpiFormatException(rv));
+       return rv;
+}
+#endif
+
 static void
 acpitz_tick(void *opaque)
 {
@@ -605,16 +696,31 @@
        sc->sc_sme->sme_cookie = sc;
        sc->sc_sme->sme_name = device_xname(dv);
        sc->sc_sme->sme_flags = SME_DISABLE_REFRESH;
-       sc->sc_sensor.monitor = true;
-       sc->sc_sensor.flags = ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP;
-       sc->sc_sensor.units = ENVSYS_STEMP;
-       strlcpy(sc->sc_sensor.desc, "temperature", sizeof(sc->sc_sensor.desc));
-       if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor))
+
+       sc->sc_temp_sensor.monitor = true;
+       sc->sc_temp_sensor.flags = ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP;
+       sc->sc_temp_sensor.units = ENVSYS_STEMP;
+       strlcpy(sc->sc_temp_sensor.desc,
+           sc->sc_zone.name, sizeof(sc->sc_temp_sensor.desc));
+       if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_sensor))
                goto out;
 
+       if (sc->sc_have_fan) {
+               sc->sc_fan_sensor.monitor = true;
+               sc->sc_fan_sensor.flags =
+                   ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP;
+               sc->sc_fan_sensor.units = ENVSYS_SFANRPM;
+               strlcpy(sc->sc_fan_sensor.desc,
+                   "FAN", sizeof(sc->sc_fan_sensor.desc));
+               if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_fan_sensor))
+                       /* ignore error because fan sensor is optional */
+                       aprint_error_dev(dv, "unable to attach fan sensor\n");
+       }
+
        /* hook into sysmon */
        if (sysmon_envsys_register(sc->sc_sme) == 0)
                return;
+
 out:
        aprint_error_dev(dv, "unable to register with sysmon\n");
        sysmon_envsys_destroy(sc->sc_sme);
@@ -627,19 +733,40 @@
        struct acpitz_softc *sc = sme->sme_cookie;
        int i;
 
-       limits->sel_flags = 0;
+       printf("%s: units: %u\n", __func__, edata->units);
 
-       if (sc->sc_zone.hot != ATZ_TMP_INVALID) {
-               limits->sel_flags |= PROP_CRITMAX;
-               limits->sel_critmax = ATZ2UKELVIN(sc->sc_zone.hot);
-       } else if (sc->sc_zone.crt != ATZ_TMP_INVALID) {
-               limits->sel_flags |= PROP_CRITMAX;
-               limits->sel_critmax = ATZ2UKELVIN(sc->sc_zone.crt);
+       switch (edata->units) {
+       case ENVSYS_STEMP:
+               limits->sel_flags = 0;
+               if (sc->sc_zone.hot != ATZ_TMP_INVALID) {
+                       limits->sel_flags |= PROP_CRITMAX;
+                       limits->sel_critmax = ATZ2UKELVIN(sc->sc_zone.hot);
+               } else if (sc->sc_zone.crt != ATZ_TMP_INVALID) {
+                       limits->sel_flags |= PROP_CRITMAX;
+                       limits->sel_critmax = ATZ2UKELVIN(sc->sc_zone.crt);
+               }
+               for (i = 0; i < ATZ_NLEVELS; i++) {
+                       if (sc->sc_zone.ac[i] != ATZ_TMP_INVALID) {
+                               limits->sel_critmax =
+                                   ATZ2UKELVIN(sc->sc_zone.ac[i]);
+                               limits->sel_flags |= PROP_WARNMAX;
+                               break;
+                       }
+               }
+               break;
+
+       case ENVSYS_SFANRPM:
+               limits->sel_flags = 0;



Home | Main Index | Thread Index | Old Index