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

Cache object: b80f17262f437a5b9a00ce834d9eae74


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