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