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