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

Cache object: 390de2492a91ccaa42768add32fd4193


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