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

Cache object: cb630216876d7f05fd95fe702ef136a7


[ 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.