The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/acpica/acpi_thermal.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000, 2001 Michael Smith
    3  * Copyright (c) 2000 BSDi
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include "opt_acpi.h"
   32 #include <sys/param.h>
   33 #include <sys/eventhandler.h>
   34 #include <sys/kernel.h>
   35 #include <sys/bus.h>
   36 #include <sys/cpu.h>
   37 #include <sys/kthread.h>
   38 #include <sys/malloc.h>
   39 #include <sys/module.h>
   40 #include <sys/proc.h>
   41 #include <sys/reboot.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/unistd.h>
   44 #include <sys/power.h>
   45 
   46 #include "cpufreq_if.h"
   47 
   48 #include <contrib/dev/acpica/include/acpi.h>
   49 #include <contrib/dev/acpica/include/accommon.h>
   50 
   51 #include <dev/acpica/acpivar.h>
   52 
   53 /* Hooks for the ACPI CA debugging infrastructure */
   54 #define _COMPONENT      ACPI_THERMAL
   55 ACPI_MODULE_NAME("THERMAL")
   56 
   57 #define TZ_ZEROC        2731
   58 #define TZ_KELVTOC(x)   (((x) - TZ_ZEROC) / 10), abs(((x) - TZ_ZEROC) % 10)
   59 
   60 #define TZ_NOTIFY_TEMPERATURE   0x80 /* Temperature changed. */
   61 #define TZ_NOTIFY_LEVELS        0x81 /* Cooling levels changed. */
   62 #define TZ_NOTIFY_DEVICES       0x82 /* Device lists changed. */
   63 #define TZ_NOTIFY_CRITICAL      0xcc /* Fake notify that _CRT/_HOT/_CR3 reached. */
   64 
   65 /* Check for temperature changes every 10 seconds by default */
   66 #define TZ_POLLRATE     10
   67 
   68 /* Make sure the reported temperature is valid for this number of polls. */
   69 #define TZ_VALIDCHECKS  3
   70 
   71 /* Notify the user we will be shutting down in one more poll cycle. */
   72 #define TZ_NOTIFYCOUNT  (TZ_VALIDCHECKS - 1)
   73 
   74 /* ACPI spec defines this */
   75 #define TZ_NUMLEVELS    10
   76 struct acpi_tz_zone {
   77     int         ac[TZ_NUMLEVELS];
   78     ACPI_BUFFER al[TZ_NUMLEVELS];
   79     int         crt;
   80     int         hot;
   81     int         cr3;
   82     ACPI_BUFFER psl;
   83     int         psv;
   84     int         tc1;
   85     int         tc2;
   86     int         tsp;
   87     int         tzp;
   88 };
   89 
   90 struct acpi_tz_softc {
   91     device_t                    tz_dev;
   92     ACPI_HANDLE                 tz_handle;      /*Thermal zone handle*/
   93     int                         tz_temperature; /*Current temperature*/
   94     int                         tz_active;      /*Current active cooling*/
   95 #define TZ_ACTIVE_NONE          -1
   96 #define TZ_ACTIVE_UNKNOWN       -2
   97     int                         tz_requested;   /*Minimum active cooling*/
   98     int                         tz_thflags;     /*Current temp-related flags*/
   99 #define TZ_THFLAG_NONE          0
  100 #define TZ_THFLAG_PSV           (1<<0)
  101 #define TZ_THFLAG_CR3           (1<<2)
  102 #define TZ_THFLAG_HOT           (1<<3)
  103 #define TZ_THFLAG_CRT           (1<<4)
  104     int                         tz_flags;
  105 #define TZ_FLAG_NO_SCP          (1<<0)          /*No _SCP method*/
  106 #define TZ_FLAG_GETPROFILE      (1<<1)          /*Get power_profile in timeout*/
  107 #define TZ_FLAG_GETSETTINGS     (1<<2)          /*Get devs/setpoints*/
  108     struct timespec             tz_cooling_started;
  109                                         /*Current cooling starting time*/
  110 
  111     struct sysctl_ctx_list      tz_sysctl_ctx;
  112     struct sysctl_oid           *tz_sysctl_tree;
  113     eventhandler_tag            tz_event;
  114 
  115     struct acpi_tz_zone         tz_zone;        /*Thermal zone parameters*/
  116     int                         tz_validchecks;
  117     int                         tz_insane_tmp_notified;
  118 
  119     /* passive cooling */
  120     struct proc                 *tz_cooling_proc;
  121     int                         tz_cooling_proc_running;
  122     int                         tz_cooling_enabled;
  123     int                         tz_cooling_active;
  124     int                         tz_cooling_updated;
  125     int                         tz_cooling_saved_freq;
  126 };
  127 
  128 #define TZ_ACTIVE_LEVEL(act)    ((act) >= 0 ? (act) : TZ_NUMLEVELS)
  129 
  130 #define CPUFREQ_MAX_LEVELS      64 /* XXX cpufreq should export this */
  131 
  132 static int      acpi_tz_probe(device_t dev);
  133 static int      acpi_tz_attach(device_t dev);
  134 static int      acpi_tz_establish(struct acpi_tz_softc *sc);
  135 static void     acpi_tz_monitor(void *Context);
  136 static void     acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg);
  137 static void     acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg);
  138 static void     acpi_tz_getparam(struct acpi_tz_softc *sc, char *node,
  139                                  int *data);
  140 static void     acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what);
  141 static int      acpi_tz_active_sysctl(SYSCTL_HANDLER_ARGS);
  142 static int      acpi_tz_cooling_sysctl(SYSCTL_HANDLER_ARGS);
  143 static int      acpi_tz_temp_sysctl(SYSCTL_HANDLER_ARGS);
  144 static int      acpi_tz_passive_sysctl(SYSCTL_HANDLER_ARGS);
  145 static void     acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify,
  146                                        void *context);
  147 static void     acpi_tz_signal(struct acpi_tz_softc *sc, int flags);
  148 static void     acpi_tz_timeout(struct acpi_tz_softc *sc, int flags);
  149 static void     acpi_tz_power_profile(void *arg);
  150 static void     acpi_tz_thread(void *arg);
  151 static int      acpi_tz_cooling_is_available(struct acpi_tz_softc *sc);
  152 static int      acpi_tz_cooling_thread_start(struct acpi_tz_softc *sc);
  153 
  154 static device_method_t acpi_tz_methods[] = {
  155     /* Device interface */
  156     DEVMETHOD(device_probe,     acpi_tz_probe),
  157     DEVMETHOD(device_attach,    acpi_tz_attach),
  158 
  159     DEVMETHOD_END
  160 };
  161 
  162 static driver_t acpi_tz_driver = {
  163     "acpi_tz",
  164     acpi_tz_methods,
  165     sizeof(struct acpi_tz_softc),
  166 };
  167 
  168 static char *acpi_tz_tmp_name = "_TMP";
  169 
  170 DRIVER_MODULE(acpi_tz, acpi, acpi_tz_driver, 0, 0);
  171 MODULE_DEPEND(acpi_tz, acpi, 1, 1, 1);
  172 
  173 static struct sysctl_ctx_list   acpi_tz_sysctl_ctx;
  174 static struct sysctl_oid        *acpi_tz_sysctl_tree;
  175 
  176 /* Minimum cooling run time */
  177 static int                      acpi_tz_min_runtime;
  178 static int                      acpi_tz_polling_rate = TZ_POLLRATE;
  179 static int                      acpi_tz_override;
  180 
  181 /* Thermal zone polling thread */
  182 static struct proc              *acpi_tz_proc;
  183 ACPI_LOCK_DECL(thermal, "ACPI thermal zone");
  184 
  185 static int                      acpi_tz_cooling_unit = -1;
  186 
  187 static int
  188 acpi_tz_probe(device_t dev)
  189 {
  190     int         result;
  191 
  192     if (acpi_get_type(dev) == ACPI_TYPE_THERMAL && !acpi_disabled("thermal")) {
  193         device_set_desc(dev, "Thermal Zone");
  194         result = -10;
  195     } else
  196         result = ENXIO;
  197     return (result);
  198 }
  199 
  200 static int
  201 acpi_tz_attach(device_t dev)
  202 {
  203     struct acpi_tz_softc        *sc;
  204     struct acpi_softc           *acpi_sc;
  205     int                         error;
  206     char                        oidname[16];
  207 
  208     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  209 
  210     sc = device_get_softc(dev);
  211     sc->tz_dev = dev;
  212     sc->tz_handle = acpi_get_handle(dev);
  213     sc->tz_requested = TZ_ACTIVE_NONE;
  214     sc->tz_active = TZ_ACTIVE_UNKNOWN;
  215     sc->tz_thflags = TZ_THFLAG_NONE;
  216     sc->tz_cooling_proc = NULL;
  217     sc->tz_cooling_proc_running = FALSE;
  218     sc->tz_cooling_active = FALSE;
  219     sc->tz_cooling_updated = FALSE;
  220     sc->tz_cooling_enabled = FALSE;
  221 
  222     /*
  223      * Parse the current state of the thermal zone and build control
  224      * structures.  We don't need to worry about interference with the
  225      * control thread since we haven't fully attached this device yet.
  226      */
  227     if ((error = acpi_tz_establish(sc)) != 0)
  228         return (error);
  229 
  230     /*
  231      * Register for any Notify events sent to this zone.
  232      */
  233     AcpiInstallNotifyHandler(sc->tz_handle, ACPI_DEVICE_NOTIFY,
  234                              acpi_tz_notify_handler, sc);
  235 
  236     /*
  237      * Create our sysctl nodes.
  238      *
  239      * XXX we need a mechanism for adding nodes under ACPI.
  240      */
  241     if (device_get_unit(dev) == 0) {
  242         acpi_sc = acpi_device_get_parent_softc(dev);
  243         sysctl_ctx_init(&acpi_tz_sysctl_ctx);
  244         acpi_tz_sysctl_tree = SYSCTL_ADD_NODE(&acpi_tz_sysctl_ctx,
  245             SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "thermal",
  246             CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
  247         SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
  248                        SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
  249                        OID_AUTO, "min_runtime", CTLFLAG_RW,
  250                        &acpi_tz_min_runtime, 0,
  251                        "minimum cooling run time in sec");
  252         SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
  253                        SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
  254                        OID_AUTO, "polling_rate", CTLFLAG_RW,
  255                        &acpi_tz_polling_rate, 0, "monitor polling interval in seconds");
  256         SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
  257                        SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO,
  258                        "user_override", CTLFLAG_RW, &acpi_tz_override, 0,
  259                        "allow override of thermal settings");
  260     }
  261     sysctl_ctx_init(&sc->tz_sysctl_ctx);
  262     snprintf(oidname, sizeof(oidname), "tz%d", device_get_unit(dev));
  263     sc->tz_sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&sc->tz_sysctl_ctx,
  264         SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO, oidname,
  265         CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "", "thermal_zone");
  266     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  267         OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
  268         &sc->tz_temperature, 0, sysctl_handle_int, "IK",
  269         "current thermal zone temperature");
  270     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  271         OID_AUTO, "active", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
  272         0, acpi_tz_active_sysctl, "I", "cooling is active");
  273     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  274         OID_AUTO, "passive_cooling",
  275         CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
  276         acpi_tz_cooling_sysctl, "I",
  277         "enable passive (speed reduction) cooling");
  278 
  279     SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  280                    OID_AUTO, "thermal_flags", CTLFLAG_RD,
  281                    &sc->tz_thflags, 0, "thermal zone flags");
  282     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  283         OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
  284         offsetof(struct acpi_tz_softc, tz_zone.psv), acpi_tz_temp_sysctl, "IK",
  285         "passive cooling temp setpoint");
  286     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  287         OID_AUTO, "_CR3", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
  288         offsetof(struct acpi_tz_softc, tz_zone.cr3), acpi_tz_temp_sysctl, "IK",
  289         "too warm temp setpoint (standby now)");
  290     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  291         OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
  292         offsetof(struct acpi_tz_softc, tz_zone.hot), acpi_tz_temp_sysctl, "IK",
  293         "too hot temp setpoint (suspend now)");
  294     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  295         OID_AUTO, "_CRT", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
  296         offsetof(struct acpi_tz_softc, tz_zone.crt), acpi_tz_temp_sysctl, "IK",
  297         "critical temp setpoint (shutdown now)");
  298     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  299         OID_AUTO, "_ACx", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
  300         &sc->tz_zone.ac, sizeof(sc->tz_zone.ac), sysctl_handle_opaque, "IK",
  301         "");
  302     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  303         OID_AUTO, "_TC1", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
  304         offsetof(struct acpi_tz_softc, tz_zone.tc1), acpi_tz_passive_sysctl,
  305         "I", "thermal constant 1 for passive cooling");
  306     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  307         OID_AUTO, "_TC2", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
  308         offsetof(struct acpi_tz_softc, tz_zone.tc2), acpi_tz_passive_sysctl,
  309         "I", "thermal constant 2 for passive cooling");
  310     SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
  311         OID_AUTO, "_TSP", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
  312         offsetof(struct acpi_tz_softc, tz_zone.tsp), acpi_tz_passive_sysctl,
  313         "I", "thermal sampling period for passive cooling");
  314 
  315     /*
  316      * Register our power profile event handler.
  317      */
  318     sc->tz_event = EVENTHANDLER_REGISTER(power_profile_change,
  319         acpi_tz_power_profile, sc, 0);
  320 
  321     /*
  322      * Flag the event handler for a manual invocation by our timeout.
  323      * We defer it like this so that the rest of the subsystem has time
  324      * to come up.  Don't bother evaluating/printing the temperature at
  325      * this point; on many systems it'll be bogus until the EC is running.
  326      */
  327     sc->tz_flags |= TZ_FLAG_GETPROFILE;
  328 
  329     return_VALUE (0);
  330 }
  331 
  332 static void
  333 acpi_tz_startup(void *arg __unused)
  334 {
  335     struct acpi_tz_softc *sc;
  336     device_t *devs;
  337     int devcount, error, i;
  338 
  339     devclass_get_devices(devclass_find("acpi_tz"), &devs, &devcount);
  340     if (devcount == 0) {
  341         free(devs, M_TEMP);
  342         return;
  343     }
  344 
  345     /*
  346      * Create thread to service all of the thermal zones.
  347      */
  348     error = kproc_create(acpi_tz_thread, NULL, &acpi_tz_proc, RFHIGHPID, 0,
  349         "acpi_thermal");
  350     if (error != 0)
  351         printf("acpi_tz: could not create thread - %d", error);
  352 
  353     /*
  354      * Create a thread to handle passive cooling for 1st zone which
  355      * has _PSV, _TSP, _TC1 and _TC2.  Users can enable it for other
  356      * zones manually for now.
  357      *
  358      * XXX We enable only one zone to avoid multiple zones conflict
  359      * with each other since cpufreq currently sets all CPUs to the
  360      * given frequency whereas it's possible for different thermal
  361      * zones to specify independent settings for multiple CPUs.
  362      */
  363     for (i = 0; i < devcount; i++) {
  364         sc = device_get_softc(devs[i]);
  365         if (acpi_tz_cooling_is_available(sc)) {
  366             sc->tz_cooling_enabled = TRUE;
  367             error = acpi_tz_cooling_thread_start(sc);
  368             if (error != 0) {
  369                 sc->tz_cooling_enabled = FALSE;
  370                 break;
  371             }
  372             acpi_tz_cooling_unit = device_get_unit(devs[i]);
  373             break;
  374         }
  375     }
  376     free(devs, M_TEMP);
  377 }
  378 SYSINIT(acpi_tz, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, acpi_tz_startup, NULL);
  379 
  380 /*
  381  * Parse the current state of this thermal zone and set up to use it.
  382  *
  383  * Note that we may have previous state, which will have to be discarded.
  384  */
  385 static int
  386 acpi_tz_establish(struct acpi_tz_softc *sc)
  387 {
  388     ACPI_OBJECT *obj;
  389     int         i;
  390     char        nbuf[8];
  391 
  392     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  393 
  394     /* Erase any existing state. */
  395     for (i = 0; i < TZ_NUMLEVELS; i++)
  396         if (sc->tz_zone.al[i].Pointer != NULL)
  397             AcpiOsFree(sc->tz_zone.al[i].Pointer);
  398     if (sc->tz_zone.psl.Pointer != NULL)
  399         AcpiOsFree(sc->tz_zone.psl.Pointer);
  400 
  401     /*
  402      * XXX: We initialize only ACPI_BUFFER to avoid race condition
  403      * with passive cooling thread which refers psv, tc1, tc2 and tsp.
  404      */
  405     bzero(sc->tz_zone.ac, sizeof(sc->tz_zone.ac));
  406     bzero(sc->tz_zone.al, sizeof(sc->tz_zone.al));
  407     bzero(&sc->tz_zone.psl, sizeof(sc->tz_zone.psl));
  408 
  409     /* Evaluate thermal zone parameters. */
  410     for (i = 0; i < TZ_NUMLEVELS; i++) {
  411         sprintf(nbuf, "_AC%d", i);
  412         acpi_tz_getparam(sc, nbuf, &sc->tz_zone.ac[i]);
  413         sprintf(nbuf, "_AL%d", i);
  414         sc->tz_zone.al[i].Length = ACPI_ALLOCATE_BUFFER;
  415         sc->tz_zone.al[i].Pointer = NULL;
  416         AcpiEvaluateObject(sc->tz_handle, nbuf, NULL, &sc->tz_zone.al[i]);
  417         obj = (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer;
  418         if (obj != NULL) {
  419             /* Should be a package containing a list of power objects */
  420             if (obj->Type != ACPI_TYPE_PACKAGE) {
  421                 device_printf(sc->tz_dev, "%s has unknown type %d, rejecting\n",
  422                               nbuf, obj->Type);
  423                 return_VALUE (ENXIO);
  424             }
  425         }
  426     }
  427     acpi_tz_getparam(sc, "_CRT", &sc->tz_zone.crt);
  428     acpi_tz_getparam(sc, "_HOT", &sc->tz_zone.hot);
  429     acpi_tz_getparam(sc, "_CR3", &sc->tz_zone.cr3);
  430     sc->tz_zone.psl.Length = ACPI_ALLOCATE_BUFFER;
  431     sc->tz_zone.psl.Pointer = NULL;
  432     AcpiEvaluateObject(sc->tz_handle, "_PSL", NULL, &sc->tz_zone.psl);
  433     acpi_tz_getparam(sc, "_PSV", &sc->tz_zone.psv);
  434     acpi_tz_getparam(sc, "_TC1", &sc->tz_zone.tc1);
  435     acpi_tz_getparam(sc, "_TC2", &sc->tz_zone.tc2);
  436     acpi_tz_getparam(sc, "_TSP", &sc->tz_zone.tsp);
  437     acpi_tz_getparam(sc, "_TZP", &sc->tz_zone.tzp);
  438 
  439     /*
  440      * Sanity-check the values we've been given.
  441      *
  442      * XXX what do we do about systems that give us the same value for
  443      *     more than one of these setpoints?
  444      */
  445     acpi_tz_sanity(sc, &sc->tz_zone.crt, "_CRT");
  446     acpi_tz_sanity(sc, &sc->tz_zone.hot, "_HOT");
  447     acpi_tz_sanity(sc, &sc->tz_zone.cr3, "_CR3");
  448     acpi_tz_sanity(sc, &sc->tz_zone.psv, "_PSV");
  449     for (i = 0; i < TZ_NUMLEVELS; i++)
  450         acpi_tz_sanity(sc, &sc->tz_zone.ac[i], "_ACx");
  451 
  452     return_VALUE (0);
  453 }
  454 
  455 static char *aclevel_string[] = {
  456     "NONE", "_AC0", "_AC1", "_AC2", "_AC3", "_AC4",
  457     "_AC5", "_AC6", "_AC7", "_AC8", "_AC9"
  458 };
  459 
  460 static __inline const char *
  461 acpi_tz_aclevel_string(int active)
  462 {
  463     if (active < -1 || active >= TZ_NUMLEVELS)
  464         return (aclevel_string[0]);
  465 
  466     return (aclevel_string[active + 1]);
  467 }
  468 
  469 /*
  470  * Get the current temperature.
  471  */
  472 static int
  473 acpi_tz_get_temperature(struct acpi_tz_softc *sc)
  474 {
  475     int         temp;
  476     ACPI_STATUS status;
  477 
  478     ACPI_FUNCTION_NAME ("acpi_tz_get_temperature");
  479 
  480     /* Evaluate the thermal zone's _TMP method. */
  481     status = acpi_GetInteger(sc->tz_handle, acpi_tz_tmp_name, &temp);
  482     if (ACPI_FAILURE(status)) {
  483         ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
  484             "error fetching current temperature -- %s\n",
  485              AcpiFormatException(status));
  486         return (FALSE);
  487     }
  488 
  489     /* Check it for validity. */
  490     acpi_tz_sanity(sc, &temp, acpi_tz_tmp_name);
  491     if (temp == -1)
  492         return (FALSE);
  493 
  494     ACPI_DEBUG_PRINT((ACPI_DB_VALUES, "got %d.%dC\n", TZ_KELVTOC(temp)));
  495     sc->tz_temperature = temp;
  496     return (TRUE);
  497 }
  498 
  499 /*
  500  * Evaluate the condition of a thermal zone, take appropriate actions.
  501  */
  502 static void
  503 acpi_tz_monitor(void *Context)
  504 {
  505     struct acpi_softc    *acpi_sc;
  506     struct acpi_tz_softc *sc;
  507     struct      timespec curtime;
  508     int         temp;
  509     int         i;
  510     int         newactive, newflags;
  511 
  512     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  513 
  514     sc = (struct acpi_tz_softc *)Context;
  515 
  516     /* Get the current temperature. */
  517     if (!acpi_tz_get_temperature(sc)) {
  518         /* XXX disable zone? go to max cooling? */
  519         return_VOID;
  520     }
  521     temp = sc->tz_temperature;
  522 
  523     /*
  524      * Work out what we ought to be doing right now.
  525      *
  526      * Note that the _ACx levels sort from hot to cold.
  527      */
  528     newactive = TZ_ACTIVE_NONE;
  529     for (i = TZ_NUMLEVELS - 1; i >= 0; i--) {
  530         if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i])
  531             newactive = i;
  532     }
  533 
  534     /*
  535      * We are going to get _ACx level down (colder side), but give a guaranteed
  536      * minimum cooling run time if requested.
  537      */
  538     if (acpi_tz_min_runtime > 0 && sc->tz_active != TZ_ACTIVE_NONE &&
  539         sc->tz_active != TZ_ACTIVE_UNKNOWN &&
  540         (newactive == TZ_ACTIVE_NONE || newactive > sc->tz_active)) {
  541         getnanotime(&curtime);
  542         timespecsub(&curtime, &sc->tz_cooling_started, &curtime);
  543         if (curtime.tv_sec < acpi_tz_min_runtime)
  544             newactive = sc->tz_active;
  545     }
  546 
  547     /* Handle user override of active mode */
  548     if (sc->tz_requested != TZ_ACTIVE_NONE && (newactive == TZ_ACTIVE_NONE
  549         || sc->tz_requested < newactive))
  550         newactive = sc->tz_requested;
  551 
  552     /* update temperature-related flags */
  553     newflags = TZ_THFLAG_NONE;
  554     if (sc->tz_zone.psv != -1 && temp >= sc->tz_zone.psv)
  555         newflags |= TZ_THFLAG_PSV;
  556     if (sc->tz_zone.cr3 != -1 && temp >= sc->tz_zone.cr3)
  557         newflags |= TZ_THFLAG_CR3;
  558     if (sc->tz_zone.hot != -1 && temp >= sc->tz_zone.hot)
  559         newflags |= TZ_THFLAG_HOT;
  560     if (sc->tz_zone.crt != -1 && temp >= sc->tz_zone.crt)
  561         newflags |= TZ_THFLAG_CRT;
  562 
  563     /* If the active cooling state has changed, we have to switch things. */
  564     if (sc->tz_active == TZ_ACTIVE_UNKNOWN) {
  565         /*
  566          * We don't know which cooling device is on or off,
  567          * so stop them all, because we now know which
  568          * should be on (if any).
  569          */
  570         for (i = 0; i < TZ_NUMLEVELS; i++) {
  571             if (sc->tz_zone.al[i].Pointer != NULL) {
  572                 acpi_ForeachPackageObject(
  573                     (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer,
  574                     acpi_tz_switch_cooler_off, sc);
  575             }
  576         }
  577         /* now we know that all devices are off */
  578         sc->tz_active = TZ_ACTIVE_NONE;
  579     }
  580 
  581     if (newactive != sc->tz_active) {
  582         /* Turn off unneeded cooling devices that are on, if any are */
  583         for (i = TZ_ACTIVE_LEVEL(sc->tz_active);
  584              i < TZ_ACTIVE_LEVEL(newactive); i++) {
  585             acpi_ForeachPackageObject(
  586                 (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer,
  587                 acpi_tz_switch_cooler_off, sc);
  588         }
  589         /* Turn on cooling devices that are required, if any are */
  590         for (i = TZ_ACTIVE_LEVEL(sc->tz_active) - 1;
  591              i >= TZ_ACTIVE_LEVEL(newactive); i--) {
  592             acpi_ForeachPackageObject(
  593                 (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer,
  594                 acpi_tz_switch_cooler_on, sc);
  595         }
  596 
  597         ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
  598                     "switched from %s to %s: %d.%dC\n",
  599                     acpi_tz_aclevel_string(sc->tz_active),
  600                     acpi_tz_aclevel_string(newactive), TZ_KELVTOC(temp));
  601         sc->tz_active = newactive;
  602         getnanotime(&sc->tz_cooling_started);
  603     }
  604 
  605     /* XXX (de)activate any passive cooling that may be required. */
  606 
  607     /*
  608      * If the temperature is at _HOT or _CRT, increment our event count.
  609      * If it has occurred enough times, shutdown the system.  This is
  610      * needed because some systems will report an invalid high temperature
  611      * for one poll cycle.  It is suspected this is due to the embedded
  612      * controller timing out.  A typical value is 138C for one cycle on
  613      * a system that is otherwise 65C.
  614      *
  615      * If we're almost at that threshold, notify the user through devd(8).
  616      */
  617     if ((newflags & (TZ_THFLAG_CR3 | TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) {
  618         sc->tz_validchecks++;
  619         if (sc->tz_validchecks == TZ_VALIDCHECKS) {
  620             device_printf(sc->tz_dev,
  621                 "WARNING - current temperature (%d.%dC) exceeds safe limits\n",
  622                 TZ_KELVTOC(sc->tz_temperature));
  623             if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0)
  624                 shutdown_nice(RB_POWEROFF);
  625             else {
  626                 acpi_sc = acpi_device_get_parent_softc(sc->tz_dev);
  627                 acpi_ReqSleepState(acpi_sc, ACPI_STATE_S3);
  628             }
  629         } else if (sc->tz_validchecks == TZ_NOTIFYCOUNT)
  630             acpi_UserNotify("Thermal", sc->tz_handle, TZ_NOTIFY_CRITICAL);
  631     } else {
  632         sc->tz_validchecks = 0;
  633     }
  634     sc->tz_thflags = newflags;
  635 
  636     return_VOID;
  637 }
  638 
  639 /*
  640  * Given an object, verify that it's a reference to a device of some sort,
  641  * and try to switch it off.
  642  */
  643 static void
  644 acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg)
  645 {
  646     ACPI_HANDLE                 cooler;
  647 
  648     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  649 
  650     cooler = acpi_GetReference(NULL, obj);
  651     if (cooler == NULL) {
  652         ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get handle\n"));
  653         return_VOID;
  654     }
  655 
  656     ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s off\n",
  657                      acpi_name(cooler)));
  658     acpi_pwr_switch_consumer(cooler, ACPI_STATE_D3);
  659 
  660     return_VOID;
  661 }
  662 
  663 /*
  664  * Given an object, verify that it's a reference to a device of some sort,
  665  * and try to switch it on.
  666  *
  667  * XXX replication of off/on function code is bad.
  668  */
  669 static void
  670 acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg)
  671 {
  672     struct acpi_tz_softc        *sc = (struct acpi_tz_softc *)arg;
  673     ACPI_HANDLE                 cooler;
  674     ACPI_STATUS                 status;
  675 
  676     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  677 
  678     cooler = acpi_GetReference(NULL, obj);
  679     if (cooler == NULL) {
  680         ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get handle\n"));
  681         return_VOID;
  682     }
  683 
  684     ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s on\n",
  685                      acpi_name(cooler)));
  686     status = acpi_pwr_switch_consumer(cooler, ACPI_STATE_D0);
  687     if (ACPI_FAILURE(status)) {
  688         ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
  689                     "failed to activate %s - %s\n", acpi_name(cooler),
  690                     AcpiFormatException(status));
  691     }
  692 
  693     return_VOID;
  694 }
  695 
  696 /*
  697  * Read/debug-print a parameter, default it to -1.
  698  */
  699 static void
  700 acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data)
  701 {
  702 
  703     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  704 
  705     if (ACPI_FAILURE(acpi_GetInteger(sc->tz_handle, node, data))) {
  706         *data = -1;
  707     } else {
  708         ACPI_DEBUG_PRINT((ACPI_DB_VALUES, "%s.%s = %d\n",
  709                          acpi_name(sc->tz_handle), node, *data));
  710     }
  711 
  712     return_VOID;
  713 }
  714 
  715 /*
  716  * Sanity-check a temperature value.  Assume that setpoints
  717  * should be between 0C and 200C.
  718  */
  719 static void
  720 acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what)
  721 {
  722     if (*val != -1 && (*val < TZ_ZEROC || *val > TZ_ZEROC + 2000)) {
  723         /*
  724          * If the value we are checking is _TMP, warn the user only
  725          * once. This avoids spamming messages if, for instance, the
  726          * sensor is broken and always returns an invalid temperature.
  727          *
  728          * This is only done for _TMP; other values always emit a
  729          * warning.
  730          */
  731         if (what != acpi_tz_tmp_name || !sc->tz_insane_tmp_notified) {
  732             device_printf(sc->tz_dev, "%s value is absurd, ignored (%d.%dC)\n",
  733                           what, TZ_KELVTOC(*val));
  734 
  735             /* Don't warn the user again if the read value doesn't improve. */
  736             if (what == acpi_tz_tmp_name)
  737                 sc->tz_insane_tmp_notified = 1;
  738         }
  739         *val = -1;
  740         return;
  741     }
  742 
  743     /* This value is correct. Warn if it's incorrect again. */
  744     if (what == acpi_tz_tmp_name)
  745         sc->tz_insane_tmp_notified = 0;
  746 }
  747 
  748 /*
  749  * Respond to a sysctl on the active state node.
  750  */
  751 static int
  752 acpi_tz_active_sysctl(SYSCTL_HANDLER_ARGS)
  753 {
  754     struct acpi_tz_softc        *sc;
  755     int                         active;
  756     int                         error;
  757 
  758     sc = (struct acpi_tz_softc *)oidp->oid_arg1;
  759     active = sc->tz_active;
  760     error = sysctl_handle_int(oidp, &active, 0, req);
  761 
  762     /* Error or no new value */
  763     if (error != 0 || req->newptr == NULL)
  764         return (error);
  765     if (active < -1 || active >= TZ_NUMLEVELS)
  766         return (EINVAL);
  767 
  768     /* Set new preferred level and re-switch */
  769     sc->tz_requested = active;
  770     acpi_tz_signal(sc, 0);
  771     return (0);
  772 }
  773 
  774 static int
  775 acpi_tz_cooling_sysctl(SYSCTL_HANDLER_ARGS)
  776 {
  777     struct acpi_tz_softc *sc;
  778     int enabled, error;
  779 
  780     sc = (struct acpi_tz_softc *)oidp->oid_arg1;
  781     enabled = sc->tz_cooling_enabled;
  782     error = sysctl_handle_int(oidp, &enabled, 0, req);
  783 
  784     /* Error or no new value */
  785     if (error != 0 || req->newptr == NULL)
  786         return (error);
  787     if (enabled != TRUE && enabled != FALSE)
  788         return (EINVAL);
  789 
  790     if (enabled) {
  791         if (acpi_tz_cooling_is_available(sc))
  792             error = acpi_tz_cooling_thread_start(sc);
  793         else
  794             error = ENODEV;
  795         if (error)
  796             enabled = FALSE;
  797     }
  798     sc->tz_cooling_enabled = enabled;
  799     return (error);
  800 }
  801 
  802 static int
  803 acpi_tz_temp_sysctl(SYSCTL_HANDLER_ARGS)
  804 {
  805     struct acpi_tz_softc        *sc;
  806     int                         temp, *temp_ptr;
  807     int                         error;
  808 
  809     sc = oidp->oid_arg1;
  810     temp_ptr = (int *)(void *)(uintptr_t)((uintptr_t)sc + oidp->oid_arg2);
  811     temp = *temp_ptr;
  812     error = sysctl_handle_int(oidp, &temp, 0, req);
  813 
  814     /* Error or no new value */
  815     if (error != 0 || req->newptr == NULL)
  816         return (error);
  817 
  818     /* Only allow changing settings if override is set. */
  819     if (!acpi_tz_override)
  820         return (EPERM);
  821 
  822     /* Check user-supplied value for sanity. */
  823     acpi_tz_sanity(sc, &temp, "user-supplied temp");
  824     if (temp == -1)
  825         return (EINVAL);
  826 
  827     *temp_ptr = temp;
  828     return (0);
  829 }
  830 
  831 static int
  832 acpi_tz_passive_sysctl(SYSCTL_HANDLER_ARGS)
  833 {
  834     struct acpi_tz_softc        *sc;
  835     int                         val, *val_ptr;
  836     int                         error;
  837 
  838     sc = oidp->oid_arg1;
  839     val_ptr = (int *)(void *)(uintptr_t)((uintptr_t)sc + oidp->oid_arg2);
  840     val = *val_ptr;
  841     error = sysctl_handle_int(oidp, &val, 0, req);
  842 
  843     /* Error or no new value */
  844     if (error != 0 || req->newptr == NULL)
  845         return (error);
  846 
  847     /* Only allow changing settings if override is set. */
  848     if (!acpi_tz_override)
  849         return (EPERM);
  850 
  851     *val_ptr = val;
  852     return (0);
  853 }
  854 
  855 static void
  856 acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
  857 {
  858     struct acpi_tz_softc        *sc = (struct acpi_tz_softc *)context;
  859 
  860     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  861 
  862     switch (notify) {
  863     case TZ_NOTIFY_TEMPERATURE:
  864         /* Temperature change occurred */
  865         acpi_tz_signal(sc, 0);
  866         break;
  867     case TZ_NOTIFY_DEVICES:
  868     case TZ_NOTIFY_LEVELS:
  869         /* Zone devices/setpoints changed */
  870         acpi_tz_signal(sc, TZ_FLAG_GETSETTINGS);
  871         break;
  872     default:
  873         ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
  874                     "unknown Notify event 0x%x\n", notify);
  875         break;
  876     }
  877 
  878     acpi_UserNotify("Thermal", h, notify);
  879 
  880     return_VOID;
  881 }
  882 
  883 static void
  884 acpi_tz_signal(struct acpi_tz_softc *sc, int flags)
  885 {
  886     ACPI_LOCK(thermal);
  887     sc->tz_flags |= flags;
  888     ACPI_UNLOCK(thermal);
  889     wakeup(&acpi_tz_proc);
  890 }
  891 
  892 /*
  893  * Notifies can be generated asynchronously but have also been seen to be
  894  * triggered by other thermal methods.  One system generates a notify of
  895  * 0x81 when the fan is turned on or off.  Another generates it when _SCP
  896  * is called.  To handle these situations, we check the zone via
  897  * acpi_tz_monitor() before evaluating changes to setpoints or the cooling
  898  * policy.
  899  */
  900 static void
  901 acpi_tz_timeout(struct acpi_tz_softc *sc, int flags)
  902 {
  903 
  904     /* Check the current temperature and take action based on it */
  905     acpi_tz_monitor(sc);
  906 
  907     /* If requested, get the power profile settings. */
  908     if (flags & TZ_FLAG_GETPROFILE)
  909         acpi_tz_power_profile(sc);
  910 
  911     /*
  912      * If requested, check for new devices/setpoints.  After finding them,
  913      * check if we need to switch fans based on the new values.
  914      */
  915     if (flags & TZ_FLAG_GETSETTINGS) {
  916         acpi_tz_establish(sc);
  917         acpi_tz_monitor(sc);
  918     }
  919 
  920     /* XXX passive cooling actions? */
  921 }
  922 
  923 /*
  924  * System power profile may have changed; fetch and notify the
  925  * thermal zone accordingly.
  926  *
  927  * Since this can be called from an arbitrary eventhandler, it needs
  928  * to get the ACPI lock itself.
  929  */
  930 static void
  931 acpi_tz_power_profile(void *arg)
  932 {
  933     ACPI_STATUS                 status;
  934     struct acpi_tz_softc        *sc = (struct acpi_tz_softc *)arg;
  935     int                         state;
  936 
  937     state = power_profile_get_state();
  938     if (state != POWER_PROFILE_PERFORMANCE && state != POWER_PROFILE_ECONOMY)
  939         return;
  940 
  941     /* check that we haven't decided there's no _SCP method */
  942     if ((sc->tz_flags & TZ_FLAG_NO_SCP) == 0) {
  943         /* Call _SCP to set the new profile */
  944         status = acpi_SetInteger(sc->tz_handle, "_SCP",
  945             (state == POWER_PROFILE_PERFORMANCE) ? 0 : 1);
  946         if (ACPI_FAILURE(status)) {
  947             if (status != AE_NOT_FOUND)
  948                 ACPI_VPRINT(sc->tz_dev,
  949                             acpi_device_get_parent_softc(sc->tz_dev),
  950                             "can't evaluate %s._SCP - %s\n",
  951                             acpi_name(sc->tz_handle),
  952                             AcpiFormatException(status));
  953             sc->tz_flags |= TZ_FLAG_NO_SCP;
  954         } else {
  955             /* We have to re-evaluate the entire zone now */
  956             acpi_tz_signal(sc, TZ_FLAG_GETSETTINGS);
  957         }
  958     }
  959 }
  960 
  961 /*
  962  * Thermal zone monitor thread.
  963  */
  964 static void
  965 acpi_tz_thread(void *arg)
  966 {
  967     devclass_t  acpi_tz_devclass;
  968     device_t    *devs;
  969     int         devcount, i;
  970     int         flags;
  971     struct acpi_tz_softc **sc;
  972 
  973     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  974 
  975     acpi_tz_devclass = devclass_find("acpi_tz");
  976     devs = NULL;
  977     devcount = 0;
  978     sc = NULL;
  979 
  980     for (;;) {
  981         /* If the number of devices has changed, re-evaluate. */
  982         if (devclass_get_count(acpi_tz_devclass) != devcount) {
  983             if (devs != NULL) {
  984                 free(devs, M_TEMP);
  985                 free(sc, M_TEMP);
  986             }
  987             devclass_get_devices(acpi_tz_devclass, &devs, &devcount);
  988             sc = malloc(sizeof(struct acpi_tz_softc *) * devcount, M_TEMP,
  989                         M_WAITOK | M_ZERO);
  990             for (i = 0; i < devcount; i++)
  991                 sc[i] = device_get_softc(devs[i]);
  992         }
  993 
  994         /* Check for temperature events and act on them. */
  995         for (i = 0; i < devcount; i++) {
  996             ACPI_LOCK(thermal);
  997             flags = sc[i]->tz_flags;
  998             sc[i]->tz_flags &= TZ_FLAG_NO_SCP;
  999             ACPI_UNLOCK(thermal);
 1000             acpi_tz_timeout(sc[i], flags);
 1001         }
 1002 
 1003         /* If more work to do, don't go to sleep yet. */
 1004         ACPI_LOCK(thermal);
 1005         for (i = 0; i < devcount; i++) {
 1006             if (sc[i]->tz_flags & ~TZ_FLAG_NO_SCP)
 1007                 break;
 1008         }
 1009 
 1010         /*
 1011          * If we have no more work, sleep for a while, setting PDROP so that
 1012          * the mutex will not be reacquired.  Otherwise, drop the mutex and
 1013          * loop to handle more events.
 1014          */
 1015         if (i == devcount)
 1016             msleep(&acpi_tz_proc, &thermal_mutex, PZERO | PDROP, "tzpoll",
 1017                 hz * acpi_tz_polling_rate);
 1018         else
 1019             ACPI_UNLOCK(thermal);
 1020     }
 1021 }
 1022 
 1023 static int
 1024 acpi_tz_cpufreq_restore(struct acpi_tz_softc *sc)
 1025 {
 1026     device_t dev;
 1027     int error;
 1028 
 1029     if (!sc->tz_cooling_updated)
 1030         return (0);
 1031     if ((dev = devclass_get_device(devclass_find("cpufreq"), 0)) == NULL)
 1032         return (ENXIO);
 1033     ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
 1034         "temperature %d.%dC: resuming previous clock speed (%d MHz)\n",
 1035         TZ_KELVTOC(sc->tz_temperature), sc->tz_cooling_saved_freq);
 1036     error = CPUFREQ_SET(dev, NULL, CPUFREQ_PRIO_KERN);
 1037     if (error == 0)
 1038         sc->tz_cooling_updated = FALSE;
 1039     return (error);
 1040 }
 1041 
 1042 static int
 1043 acpi_tz_cpufreq_update(struct acpi_tz_softc *sc, int req)
 1044 {
 1045     device_t dev;
 1046     struct cf_level *levels;
 1047     int num_levels, error, freq, desired_freq, perf, i;
 1048 
 1049     levels = malloc(CPUFREQ_MAX_LEVELS * sizeof(*levels), M_TEMP, M_NOWAIT);
 1050     if (levels == NULL)
 1051         return (ENOMEM);
 1052 
 1053     /*
 1054      * Find the main device, cpufreq0.  We don't yet support independent
 1055      * CPU frequency control on SMP.
 1056      */
 1057     if ((dev = devclass_get_device(devclass_find("cpufreq"), 0)) == NULL) {
 1058         error = ENXIO;
 1059         goto out;
 1060     }
 1061 
 1062     /* Get the current frequency. */
 1063     error = CPUFREQ_GET(dev, &levels[0]);
 1064     if (error)
 1065         goto out;
 1066     freq = levels[0].total_set.freq;
 1067 
 1068     /* Get the current available frequency levels. */
 1069     num_levels = CPUFREQ_MAX_LEVELS;
 1070     error = CPUFREQ_LEVELS(dev, levels, &num_levels);
 1071     if (error) {
 1072         if (error == E2BIG)
 1073             printf("cpufreq: need to increase CPUFREQ_MAX_LEVELS\n");
 1074         goto out;
 1075     }
 1076 
 1077     /* Calculate the desired frequency as a percent of the max frequency. */
 1078     perf = 100 * freq / levels[0].total_set.freq - req;
 1079     if (perf < 0)
 1080         perf = 0;
 1081     else if (perf > 100)
 1082         perf = 100;
 1083     desired_freq = levels[0].total_set.freq * perf / 100;
 1084 
 1085     if (desired_freq < freq) {
 1086         /* Find the closest available frequency, rounding down. */
 1087         for (i = 0; i < num_levels; i++)
 1088             if (levels[i].total_set.freq <= desired_freq)
 1089                 break;
 1090 
 1091         /* If we didn't find a relevant setting, use the lowest. */
 1092         if (i == num_levels)
 1093             i--;
 1094     } else {
 1095         /* If we didn't decrease frequency yet, don't increase it. */
 1096         if (!sc->tz_cooling_updated) {
 1097             sc->tz_cooling_active = FALSE;
 1098             goto out;
 1099         }
 1100 
 1101         /* Use saved cpu frequency as maximum value. */
 1102         if (desired_freq > sc->tz_cooling_saved_freq)
 1103             desired_freq = sc->tz_cooling_saved_freq;
 1104 
 1105         /* Find the closest available frequency, rounding up. */
 1106         for (i = num_levels - 1; i >= 0; i--)
 1107             if (levels[i].total_set.freq >= desired_freq)
 1108                 break;
 1109 
 1110         /* If we didn't find a relevant setting, use the highest. */
 1111         if (i == -1)
 1112             i++;
 1113 
 1114         /* If we're going to the highest frequency, restore the old setting. */
 1115         if (i == 0 || desired_freq == sc->tz_cooling_saved_freq) {
 1116             error = acpi_tz_cpufreq_restore(sc);
 1117             if (error == 0)
 1118                 sc->tz_cooling_active = FALSE;
 1119             goto out;
 1120         }
 1121     }
 1122 
 1123     /* If we are going to a new frequency, activate it. */
 1124     if (levels[i].total_set.freq != freq) {
 1125         ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
 1126             "temperature %d.%dC: %screasing clock speed "
 1127             "from %d MHz to %d MHz\n",
 1128             TZ_KELVTOC(sc->tz_temperature),
 1129             (freq > levels[i].total_set.freq) ? "de" : "in",
 1130             freq, levels[i].total_set.freq);
 1131         error = CPUFREQ_SET(dev, &levels[i], CPUFREQ_PRIO_KERN);
 1132         if (error == 0 && !sc->tz_cooling_updated) {
 1133             sc->tz_cooling_saved_freq = freq;
 1134             sc->tz_cooling_updated = TRUE;
 1135         }
 1136     }
 1137 
 1138 out:
 1139     if (levels)
 1140         free(levels, M_TEMP);
 1141     return (error);
 1142 }
 1143 
 1144 /*
 1145  * Passive cooling thread; monitors current temperature according to the
 1146  * cooling interval and calculates whether to scale back CPU frequency.
 1147  */
 1148 static void
 1149 acpi_tz_cooling_thread(void *arg)
 1150 {
 1151     struct acpi_tz_softc *sc;
 1152     int error, perf, curr_temp, prev_temp;
 1153 
 1154     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1155 
 1156     sc = (struct acpi_tz_softc *)arg;
 1157 
 1158     prev_temp = sc->tz_temperature;
 1159     while (sc->tz_cooling_enabled) {
 1160         if (sc->tz_cooling_active)
 1161             (void)acpi_tz_get_temperature(sc);
 1162         curr_temp = sc->tz_temperature;
 1163         if (curr_temp >= sc->tz_zone.psv)
 1164             sc->tz_cooling_active = TRUE;
 1165         if (sc->tz_cooling_active) {
 1166             perf = sc->tz_zone.tc1 * (curr_temp - prev_temp) +
 1167                    sc->tz_zone.tc2 * (curr_temp - sc->tz_zone.psv);
 1168             perf /= 10;
 1169 
 1170             if (perf != 0) {
 1171                 error = acpi_tz_cpufreq_update(sc, perf);
 1172 
 1173                 /*
 1174                  * If error and not simply a higher priority setting was
 1175                  * active, disable cooling.
 1176                  */
 1177                 if (error != 0 && error != EPERM) {
 1178                     device_printf(sc->tz_dev,
 1179                         "failed to set new freq, disabling passive cooling\n");
 1180                     sc->tz_cooling_enabled = FALSE;
 1181                 }
 1182             }
 1183         }
 1184         prev_temp = curr_temp;
 1185         tsleep(&sc->tz_cooling_proc, PZERO, "cooling",
 1186             hz * sc->tz_zone.tsp / 10);
 1187     }
 1188     if (sc->tz_cooling_active) {
 1189         acpi_tz_cpufreq_restore(sc);
 1190         sc->tz_cooling_active = FALSE;
 1191     }
 1192     sc->tz_cooling_proc = NULL;
 1193     ACPI_LOCK(thermal);
 1194     sc->tz_cooling_proc_running = FALSE;
 1195     ACPI_UNLOCK(thermal);
 1196     kproc_exit(0);
 1197 }
 1198 
 1199 /*
 1200  * TODO: We ignore _PSL (list of cooling devices) since cpufreq enumerates
 1201  * all CPUs for us.  However, it's possible in the future _PSL will
 1202  * reference non-CPU devices so we may want to support it then.
 1203  */
 1204 static int
 1205 acpi_tz_cooling_is_available(struct acpi_tz_softc *sc)
 1206 {
 1207     return (sc->tz_zone.tc1 != -1 && sc->tz_zone.tc2 != -1 &&
 1208         sc->tz_zone.tsp != -1 && sc->tz_zone.tsp != 0 &&
 1209         sc->tz_zone.psv != -1);
 1210 }
 1211 
 1212 static int
 1213 acpi_tz_cooling_thread_start(struct acpi_tz_softc *sc)
 1214 {
 1215     int error;
 1216 
 1217     ACPI_LOCK(thermal);
 1218     if (sc->tz_cooling_proc_running) {
 1219         ACPI_UNLOCK(thermal);
 1220         return (0);
 1221     }
 1222     sc->tz_cooling_proc_running = TRUE;
 1223     ACPI_UNLOCK(thermal);
 1224     error = 0;
 1225     if (sc->tz_cooling_proc == NULL) {
 1226         error = kproc_create(acpi_tz_cooling_thread, sc,
 1227             &sc->tz_cooling_proc, RFHIGHPID, 0, "acpi_cooling%d",
 1228             device_get_unit(sc->tz_dev));
 1229         if (error != 0) {
 1230             device_printf(sc->tz_dev, "could not create thread - %d", error);
 1231             ACPI_LOCK(thermal);
 1232             sc->tz_cooling_proc_running = FALSE;
 1233             ACPI_UNLOCK(thermal);
 1234         }
 1235     }
 1236     return (error);
 1237 }

Cache object: 6445418a6d795aef9125ee530f54f705


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.