1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $)
5 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
8 * This driver fully implements the ACPI thermal policy as described in the
9 * ACPI 2.0 Specification.
11 * TBD: 1. Implement passive cooling hysteresis.
12 * 2. Enhance passive cooling (CPU) states/limit interface to support
13 * concepts of 'multiple limiters', upper/lower limits, etc.
16 #define pr_fmt(fmt) "ACPI: thermal: " fmt
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/dmi.h>
21 #include <linux/init.h>
22 #include <linux/slab.h>
23 #include <linux/types.h>
24 #include <linux/jiffies.h>
25 #include <linux/kmod.h>
26 #include <linux/reboot.h>
27 #include <linux/device.h>
28 #include <linux/thermal.h>
29 #include <linux/acpi.h>
30 #include <linux/workqueue.h>
31 #include <linux/uaccess.h>
32 #include <linux/units.h>
36 #define ACPI_THERMAL_CLASS "thermal_zone"
37 #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
38 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
39 #define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
40 #define ACPI_THERMAL_NOTIFY_DEVICES 0x82
41 #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0
42 #define ACPI_THERMAL_NOTIFY_HOT 0xF1
43 #define ACPI_THERMAL_MODE_ACTIVE 0x00
45 #define ACPI_THERMAL_MAX_ACTIVE 10
46 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
48 #define ACPI_THERMAL_TRIP_PASSIVE (-1)
50 #define ACPI_THERMAL_MAX_NR_TRIPS (ACPI_THERMAL_MAX_ACTIVE + 3)
53 * This exception is thrown out in two cases:
54 * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
55 * when re-evaluating the AML code.
56 * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
57 * We need to re-bind the cooling devices of a thermal zone when this occurs.
59 #define ACPI_THERMAL_TRIPS_EXCEPTION(tz, str) \
61 acpi_handle_info(tz->device->handle, \
62 "ACPI thermal trip point %s changed\n" \
63 "Please report to linux-acpi@vger.kernel.org\n", str); \
67 module_param(act
, int, 0644);
68 MODULE_PARM_DESC(act
, "Disable or override all lowest active trip points.");
71 module_param(crt
, int, 0644);
72 MODULE_PARM_DESC(crt
, "Disable or lower all critical trip points.");
75 module_param(tzp
, int, 0444);
76 MODULE_PARM_DESC(tzp
, "Thermal zone polling frequency, in 1/10 seconds.");
79 module_param(off
, int, 0);
80 MODULE_PARM_DESC(off
, "Set to disable ACPI thermal support.");
83 module_param(psv
, int, 0644);
84 MODULE_PARM_DESC(psv
, "Disable or override all passive trip points.");
86 static struct workqueue_struct
*acpi_thermal_pm_queue
;
88 struct acpi_thermal_trip
{
89 unsigned long temp_dk
;
90 struct acpi_handle_list devices
;
93 struct acpi_thermal_passive
{
94 struct acpi_thermal_trip trip
;
100 struct acpi_thermal_active
{
101 struct acpi_thermal_trip trip
;
104 struct acpi_thermal_trips
{
105 struct acpi_thermal_passive passive
;
106 struct acpi_thermal_active active
[ACPI_THERMAL_MAX_ACTIVE
];
109 struct acpi_thermal
{
110 struct acpi_device
*device
;
112 unsigned long temp_dk
;
113 unsigned long last_temp_dk
;
114 unsigned long polling_frequency
;
116 struct acpi_thermal_trips trips
;
117 struct thermal_zone_device
*thermal_zone
;
118 int kelvin_offset
; /* in millidegrees */
119 struct work_struct thermal_check_work
;
120 struct mutex thermal_check_lock
;
121 refcount_t thermal_check_count
;
124 /* --------------------------------------------------------------------------
125 Thermal Zone Management
126 -------------------------------------------------------------------------- */
128 static int acpi_thermal_get_temperature(struct acpi_thermal
*tz
)
130 acpi_status status
= AE_OK
;
131 unsigned long long tmp
;
136 tz
->last_temp_dk
= tz
->temp_dk
;
138 status
= acpi_evaluate_integer(tz
->device
->handle
, "_TMP", NULL
, &tmp
);
139 if (ACPI_FAILURE(status
))
144 acpi_handle_debug(tz
->device
->handle
, "Temperature is %lu dK\n",
150 static int acpi_thermal_get_polling_frequency(struct acpi_thermal
*tz
)
152 acpi_status status
= AE_OK
;
153 unsigned long long tmp
;
158 status
= acpi_evaluate_integer(tz
->device
->handle
, "_TZP", NULL
, &tmp
);
159 if (ACPI_FAILURE(status
))
162 tz
->polling_frequency
= tmp
;
163 acpi_handle_debug(tz
->device
->handle
, "Polling frequency is %lu dS\n",
164 tz
->polling_frequency
);
169 static int acpi_thermal_temp(struct acpi_thermal
*tz
, int temp_deci_k
)
173 if (temp_deci_k
== THERMAL_TEMP_INVALID
)
174 return THERMAL_TEMP_INVALID
;
176 temp
= deci_kelvin_to_millicelsius_with_offset(temp_deci_k
,
179 return THERMAL_TEMP_INVALID
;
184 static bool acpi_thermal_trip_valid(struct acpi_thermal_trip
*acpi_trip
)
186 return acpi_trip
->temp_dk
!= THERMAL_TEMP_INVALID
;
189 static int active_trip_index(struct acpi_thermal
*tz
,
190 struct acpi_thermal_trip
*acpi_trip
)
192 struct acpi_thermal_active
*active
;
194 active
= container_of(acpi_trip
, struct acpi_thermal_active
, trip
);
195 return active
- tz
->trips
.active
;
198 static long get_passive_temp(struct acpi_thermal
*tz
)
202 if (acpi_passive_trip_temp(tz
->device
, &temp
))
203 return THERMAL_TEMP_INVALID
;
208 static long get_active_temp(struct acpi_thermal
*tz
, int index
)
212 if (acpi_active_trip_temp(tz
->device
, index
, &temp
))
213 return THERMAL_TEMP_INVALID
;
216 * If an override has been provided, apply it so there are no active
217 * trips with thresholds greater than the override.
220 unsigned long long override
= celsius_to_deci_kelvin(act
);
228 static void acpi_thermal_update_trip(struct acpi_thermal
*tz
,
229 const struct thermal_trip
*trip
)
231 struct acpi_thermal_trip
*acpi_trip
= trip
->priv
;
233 if (trip
->type
== THERMAL_TRIP_PASSIVE
) {
237 acpi_trip
->temp_dk
= get_passive_temp(tz
);
239 int index
= active_trip_index(tz
, acpi_trip
);
241 acpi_trip
->temp_dk
= get_active_temp(tz
, index
);
244 if (!acpi_thermal_trip_valid(acpi_trip
))
245 ACPI_THERMAL_TRIPS_EXCEPTION(tz
, "state");
248 static bool update_trip_devices(struct acpi_thermal
*tz
,
249 struct acpi_thermal_trip
*acpi_trip
,
250 int index
, bool compare
)
252 struct acpi_handle_list devices
= { 0 };
253 char method
[] = "_PSL";
255 if (index
!= ACPI_THERMAL_TRIP_PASSIVE
) {
258 method
[3] = '0' + index
;
261 if (!acpi_evaluate_reference(tz
->device
->handle
, method
, NULL
, &devices
)) {
262 acpi_handle_info(tz
->device
->handle
, "%s evaluation failure\n", method
);
266 if (acpi_handle_list_equal(&acpi_trip
->devices
, &devices
)) {
267 acpi_handle_list_free(&devices
);
272 ACPI_THERMAL_TRIPS_EXCEPTION(tz
, "device");
274 acpi_handle_list_replace(&acpi_trip
->devices
, &devices
);
278 static void acpi_thermal_update_trip_devices(struct acpi_thermal
*tz
,
279 const struct thermal_trip
*trip
)
281 struct acpi_thermal_trip
*acpi_trip
= trip
->priv
;
282 int index
= trip
->type
== THERMAL_TRIP_PASSIVE
?
283 ACPI_THERMAL_TRIP_PASSIVE
: active_trip_index(tz
, acpi_trip
);
285 if (update_trip_devices(tz
, acpi_trip
, index
, true))
288 acpi_trip
->temp_dk
= THERMAL_TEMP_INVALID
;
289 ACPI_THERMAL_TRIPS_EXCEPTION(tz
, "state");
292 struct adjust_trip_data
{
293 struct acpi_thermal
*tz
;
297 static int acpi_thermal_adjust_trip(struct thermal_trip
*trip
, void *data
)
299 struct acpi_thermal_trip
*acpi_trip
= trip
->priv
;
300 struct adjust_trip_data
*atd
= data
;
301 struct acpi_thermal
*tz
= atd
->tz
;
304 if (!acpi_trip
|| !acpi_thermal_trip_valid(acpi_trip
))
307 if (atd
->event
== ACPI_THERMAL_NOTIFY_THRESHOLDS
)
308 acpi_thermal_update_trip(tz
, trip
);
310 acpi_thermal_update_trip_devices(tz
, trip
);
312 if (acpi_thermal_trip_valid(acpi_trip
))
313 temp
= acpi_thermal_temp(tz
, acpi_trip
->temp_dk
);
315 temp
= THERMAL_TEMP_INVALID
;
317 thermal_zone_set_trip_temp(tz
->thermal_zone
, trip
, temp
);
322 static void acpi_queue_thermal_check(struct acpi_thermal
*tz
)
324 if (!work_pending(&tz
->thermal_check_work
))
325 queue_work(acpi_thermal_pm_queue
, &tz
->thermal_check_work
);
328 static void acpi_thermal_trips_update(struct acpi_thermal
*tz
, u32 event
)
330 struct adjust_trip_data atd
= { .tz
= tz
, .event
= event
};
331 struct acpi_device
*adev
= tz
->device
;
334 * Use thermal_zone_for_each_trip() to carry out the trip points
335 * update, so as to protect thermal_get_trend() from getting stale
336 * trip point temperatures and to prevent thermal_zone_device_update()
337 * invoked from acpi_thermal_check_fn() from producing inconsistent
340 thermal_zone_for_each_trip(tz
->thermal_zone
,
341 acpi_thermal_adjust_trip
, &atd
);
342 acpi_queue_thermal_check(tz
);
343 acpi_bus_generate_netlink_event(adev
->pnp
.device_class
,
344 dev_name(&adev
->dev
), event
, 0);
347 static int acpi_thermal_get_critical_trip(struct acpi_thermal
*tz
)
352 temp
= celsius_to_deci_kelvin(crt
);
356 acpi_handle_debug(tz
->device
->handle
, "Critical threshold disabled\n");
357 return THERMAL_TEMP_INVALID
;
360 if (acpi_critical_trip_temp(tz
->device
, &temp
))
361 return THERMAL_TEMP_INVALID
;
365 * Below zero (Celsius) values clearly aren't right for sure,
366 * so discard them as invalid.
368 pr_info(FW_BUG
"Invalid critical threshold (%d)\n", temp
);
369 return THERMAL_TEMP_INVALID
;
373 acpi_handle_debug(tz
->device
->handle
, "Critical threshold [%d]\n", temp
);
377 static int acpi_thermal_get_hot_trip(struct acpi_thermal
*tz
)
381 if (acpi_hot_trip_temp(tz
->device
, &temp
) || temp
== THERMAL_TEMP_INVALID
) {
382 acpi_handle_debug(tz
->device
->handle
, "No hot threshold\n");
383 return THERMAL_TEMP_INVALID
;
386 acpi_handle_debug(tz
->device
->handle
, "Hot threshold [%d]\n", temp
);
390 static bool passive_trip_params_init(struct acpi_thermal
*tz
)
392 unsigned long long tmp
;
395 status
= acpi_evaluate_integer(tz
->device
->handle
, "_TC1", NULL
, &tmp
);
396 if (ACPI_FAILURE(status
))
399 tz
->trips
.passive
.tc1
= tmp
;
401 status
= acpi_evaluate_integer(tz
->device
->handle
, "_TC2", NULL
, &tmp
);
402 if (ACPI_FAILURE(status
))
405 tz
->trips
.passive
.tc2
= tmp
;
407 status
= acpi_evaluate_integer(tz
->device
->handle
, "_TFP", NULL
, &tmp
);
408 if (ACPI_SUCCESS(status
)) {
409 tz
->trips
.passive
.delay
= tmp
;
413 status
= acpi_evaluate_integer(tz
->device
->handle
, "_TSP", NULL
, &tmp
);
414 if (ACPI_FAILURE(status
))
417 tz
->trips
.passive
.delay
= tmp
* 100;
422 static bool acpi_thermal_init_trip(struct acpi_thermal
*tz
, int index
)
424 struct acpi_thermal_trip
*acpi_trip
;
427 if (index
== ACPI_THERMAL_TRIP_PASSIVE
) {
428 acpi_trip
= &tz
->trips
.passive
.trip
;
433 if (!passive_trip_params_init(tz
))
436 temp
= psv
> 0 ? celsius_to_deci_kelvin(psv
) :
437 get_passive_temp(tz
);
439 acpi_trip
= &tz
->trips
.active
[index
].trip
;
444 temp
= get_active_temp(tz
, index
);
447 if (temp
== THERMAL_TEMP_INVALID
)
450 if (!update_trip_devices(tz
, acpi_trip
, index
, false))
453 acpi_trip
->temp_dk
= temp
;
457 acpi_trip
->temp_dk
= THERMAL_TEMP_INVALID
;
461 static void acpi_thermal_get_trip_points(struct acpi_thermal
*tz
)
465 acpi_thermal_init_trip(tz
, ACPI_THERMAL_TRIP_PASSIVE
);
467 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
468 if (!acpi_thermal_init_trip(tz
, i
))
472 while (++i
< ACPI_THERMAL_MAX_ACTIVE
)
473 tz
->trips
.active
[i
].trip
.temp_dk
= THERMAL_TEMP_INVALID
;
476 /* sys I/F for generic thermal sysfs support */
478 static int thermal_get_temp(struct thermal_zone_device
*thermal
, int *temp
)
480 struct acpi_thermal
*tz
= thermal_zone_device_priv(thermal
);
486 result
= acpi_thermal_get_temperature(tz
);
490 *temp
= deci_kelvin_to_millicelsius_with_offset(tz
->temp_dk
,
495 static int thermal_get_trend(struct thermal_zone_device
*thermal
,
496 const struct thermal_trip
*trip
,
497 enum thermal_trend
*trend
)
499 struct acpi_thermal
*tz
= thermal_zone_device_priv(thermal
);
500 struct acpi_thermal_trip
*acpi_trip
;
506 acpi_trip
= trip
->priv
;
507 if (!acpi_trip
|| !acpi_thermal_trip_valid(acpi_trip
))
510 switch (trip
->type
) {
511 case THERMAL_TRIP_PASSIVE
:
512 t
= tz
->trips
.passive
.tc1
* (tz
->temp_dk
-
514 tz
->trips
.passive
.tc2
* (tz
->temp_dk
-
517 *trend
= THERMAL_TREND_RAISING
;
519 *trend
= THERMAL_TREND_DROPPING
;
521 *trend
= THERMAL_TREND_STABLE
;
525 case THERMAL_TRIP_ACTIVE
:
526 t
= acpi_thermal_temp(tz
, tz
->temp_dk
);
527 if (t
<= trip
->temperature
)
530 *trend
= THERMAL_TREND_RAISING
;
541 static void acpi_thermal_zone_device_hot(struct thermal_zone_device
*thermal
)
543 struct acpi_thermal
*tz
= thermal_zone_device_priv(thermal
);
545 acpi_bus_generate_netlink_event(tz
->device
->pnp
.device_class
,
546 dev_name(&tz
->device
->dev
),
547 ACPI_THERMAL_NOTIFY_HOT
, 1);
550 static void acpi_thermal_zone_device_critical(struct thermal_zone_device
*thermal
)
552 struct acpi_thermal
*tz
= thermal_zone_device_priv(thermal
);
554 acpi_bus_generate_netlink_event(tz
->device
->pnp
.device_class
,
555 dev_name(&tz
->device
->dev
),
556 ACPI_THERMAL_NOTIFY_CRITICAL
, 1);
558 thermal_zone_device_critical(thermal
);
561 static bool acpi_thermal_should_bind_cdev(struct thermal_zone_device
*thermal
,
562 const struct thermal_trip
*trip
,
563 struct thermal_cooling_device
*cdev
,
564 struct cooling_spec
*c
)
566 struct acpi_thermal_trip
*acpi_trip
= trip
->priv
;
567 struct acpi_device
*cdev_adev
= cdev
->devdata
;
570 /* Skip critical and hot trips. */
574 for (i
= 0; i
< acpi_trip
->devices
.count
; i
++) {
575 acpi_handle handle
= acpi_trip
->devices
.handles
[i
];
577 if (acpi_fetch_acpi_dev(handle
) == cdev_adev
)
584 static const struct thermal_zone_device_ops acpi_thermal_zone_ops
= {
585 .should_bind
= acpi_thermal_should_bind_cdev
,
586 .get_temp
= thermal_get_temp
,
587 .get_trend
= thermal_get_trend
,
588 .hot
= acpi_thermal_zone_device_hot
,
589 .critical
= acpi_thermal_zone_device_critical
,
592 static int acpi_thermal_zone_sysfs_add(struct acpi_thermal
*tz
)
594 struct device
*tzdev
= thermal_zone_device(tz
->thermal_zone
);
597 ret
= sysfs_create_link(&tz
->device
->dev
.kobj
,
598 &tzdev
->kobj
, "thermal_zone");
602 ret
= sysfs_create_link(&tzdev
->kobj
,
603 &tz
->device
->dev
.kobj
, "device");
605 sysfs_remove_link(&tz
->device
->dev
.kobj
, "thermal_zone");
610 static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal
*tz
)
612 struct device
*tzdev
= thermal_zone_device(tz
->thermal_zone
);
614 sysfs_remove_link(&tz
->device
->dev
.kobj
, "thermal_zone");
615 sysfs_remove_link(&tzdev
->kobj
, "device");
618 static int acpi_thermal_register_thermal_zone(struct acpi_thermal
*tz
,
619 const struct thermal_trip
*trip_table
,
620 unsigned int trip_count
,
626 tz
->thermal_zone
= thermal_zone_device_register_with_trips(
627 "acpitz", trip_table
, trip_count
, tz
,
628 &acpi_thermal_zone_ops
, NULL
, passive_delay
,
629 tz
->polling_frequency
* 100);
631 tz
->thermal_zone
= thermal_tripless_zone_device_register(
632 "acpitz", tz
, &acpi_thermal_zone_ops
, NULL
);
634 if (IS_ERR(tz
->thermal_zone
))
635 return PTR_ERR(tz
->thermal_zone
);
637 result
= acpi_thermal_zone_sysfs_add(tz
);
641 result
= thermal_zone_device_enable(tz
->thermal_zone
);
645 dev_info(&tz
->device
->dev
, "registered as thermal_zone%d\n",
646 thermal_zone_device_id(tz
->thermal_zone
));
651 acpi_thermal_zone_sysfs_remove(tz
);
653 thermal_zone_device_unregister(tz
->thermal_zone
);
658 static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal
*tz
)
660 thermal_zone_device_disable(tz
->thermal_zone
);
661 acpi_thermal_zone_sysfs_remove(tz
);
662 thermal_zone_device_unregister(tz
->thermal_zone
);
663 tz
->thermal_zone
= NULL
;
667 /* --------------------------------------------------------------------------
669 -------------------------------------------------------------------------- */
671 static void acpi_thermal_notify(acpi_handle handle
, u32 event
, void *data
)
673 struct acpi_device
*device
= data
;
674 struct acpi_thermal
*tz
= acpi_driver_data(device
);
680 case ACPI_THERMAL_NOTIFY_TEMPERATURE
:
681 acpi_queue_thermal_check(tz
);
683 case ACPI_THERMAL_NOTIFY_THRESHOLDS
:
684 case ACPI_THERMAL_NOTIFY_DEVICES
:
685 acpi_thermal_trips_update(tz
, event
);
688 acpi_handle_debug(device
->handle
, "Unsupported event [0x%x]\n",
695 * On some platforms, the AML code has dependency about
696 * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
697 * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
698 * /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
699 * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
700 * if _TMP has never been evaluated.
702 * As this dependency is totally transparent to OS, evaluate
703 * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
704 * _TMP, before they are actually used.
706 static void acpi_thermal_aml_dependency_fix(struct acpi_thermal
*tz
)
708 acpi_handle handle
= tz
->device
->handle
;
709 unsigned long long value
;
712 acpi_evaluate_integer(handle
, "_CRT", NULL
, &value
);
713 acpi_evaluate_integer(handle
, "_HOT", NULL
, &value
);
714 acpi_evaluate_integer(handle
, "_PSV", NULL
, &value
);
715 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
716 char name
[5] = { '_', 'A', 'C', ('0' + i
), '\0' };
719 status
= acpi_evaluate_integer(handle
, name
, NULL
, &value
);
720 if (status
== AE_NOT_FOUND
)
723 acpi_evaluate_integer(handle
, "_TMP", NULL
, &value
);
727 * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
728 * handles temperature values with a single decimal place. As a consequence,
729 * some implementations use an offset of 273.1 and others use an offset of
730 * 273.2. Try to find out which one is being used, to present the most
731 * accurate and visually appealing number.
733 * The heuristic below should work for all ACPI thermal zones which have a
734 * critical trip point with a value being a multiple of 0.5 degree Celsius.
736 static void acpi_thermal_guess_offset(struct acpi_thermal
*tz
, long crit_temp
)
738 if (crit_temp
!= THERMAL_TEMP_INVALID
&& crit_temp
% 5 == 1)
739 tz
->kelvin_offset
= 273100;
741 tz
->kelvin_offset
= 273200;
744 static void acpi_thermal_check_fn(struct work_struct
*work
)
746 struct acpi_thermal
*tz
= container_of(work
, struct acpi_thermal
,
750 * In general, it is not sufficient to check the pending bit, because
751 * subsequent instances of this function may be queued after one of them
752 * has started running (e.g. if _TMP sleeps). Avoid bailing out if just
753 * one of them is running, though, because it may have done the actual
754 * check some time ago, so allow at least one of them to block on the
755 * mutex while another one is running the update.
757 if (!refcount_dec_not_one(&tz
->thermal_check_count
))
760 mutex_lock(&tz
->thermal_check_lock
);
762 thermal_zone_device_update(tz
->thermal_zone
, THERMAL_EVENT_UNSPECIFIED
);
764 refcount_inc(&tz
->thermal_check_count
);
766 mutex_unlock(&tz
->thermal_check_lock
);
769 static void acpi_thermal_free_thermal_zone(struct acpi_thermal
*tz
)
773 acpi_handle_list_free(&tz
->trips
.passive
.trip
.devices
);
774 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++)
775 acpi_handle_list_free(&tz
->trips
.active
[i
].trip
.devices
);
780 static int acpi_thermal_add(struct acpi_device
*device
)
782 struct thermal_trip trip_table
[ACPI_THERMAL_MAX_NR_TRIPS
] = { 0 };
783 struct acpi_thermal_trip
*acpi_trip
;
784 struct thermal_trip
*trip
;
785 struct acpi_thermal
*tz
;
786 int crit_temp
, hot_temp
;
787 int passive_delay
= 0;
794 tz
= kzalloc(sizeof(struct acpi_thermal
), GFP_KERNEL
);
799 strcpy(tz
->name
, device
->pnp
.bus_id
);
800 strcpy(acpi_device_name(device
), ACPI_THERMAL_DEVICE_NAME
);
801 strcpy(acpi_device_class(device
), ACPI_THERMAL_CLASS
);
802 device
->driver_data
= tz
;
804 acpi_thermal_aml_dependency_fix(tz
);
806 /* Get trip points [_CRT, _PSV, etc.] (required). */
807 acpi_thermal_get_trip_points(tz
);
809 crit_temp
= acpi_thermal_get_critical_trip(tz
);
810 hot_temp
= acpi_thermal_get_hot_trip(tz
);
812 /* Get temperature [_TMP] (required). */
813 result
= acpi_thermal_get_temperature(tz
);
817 /* Set the cooling mode [_SCP] to active cooling. */
818 acpi_execute_simple_method(tz
->device
->handle
, "_SCP",
819 ACPI_THERMAL_MODE_ACTIVE
);
821 /* Determine the default polling frequency [_TZP]. */
823 tz
->polling_frequency
= tzp
;
825 acpi_thermal_get_polling_frequency(tz
);
827 acpi_thermal_guess_offset(tz
, crit_temp
);
831 if (crit_temp
!= THERMAL_TEMP_INVALID
) {
832 trip
->type
= THERMAL_TRIP_CRITICAL
;
833 trip
->temperature
= acpi_thermal_temp(tz
, crit_temp
);
837 if (hot_temp
!= THERMAL_TEMP_INVALID
) {
838 trip
->type
= THERMAL_TRIP_HOT
;
839 trip
->temperature
= acpi_thermal_temp(tz
, hot_temp
);
843 acpi_trip
= &tz
->trips
.passive
.trip
;
844 if (acpi_thermal_trip_valid(acpi_trip
)) {
845 passive_delay
= tz
->trips
.passive
.delay
;
847 trip
->type
= THERMAL_TRIP_PASSIVE
;
848 trip
->temperature
= acpi_thermal_temp(tz
, acpi_trip
->temp_dk
);
849 trip
->priv
= acpi_trip
;
853 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
854 acpi_trip
= &tz
->trips
.active
[i
].trip
;
856 if (!acpi_thermal_trip_valid(acpi_trip
))
859 trip
->type
= THERMAL_TRIP_ACTIVE
;
860 trip
->temperature
= acpi_thermal_temp(tz
, acpi_trip
->temp_dk
);
861 trip
->priv
= acpi_trip
;
865 if (trip
== trip_table
)
866 pr_warn(FW_BUG
"No valid trip points!\n");
868 result
= acpi_thermal_register_thermal_zone(tz
, trip_table
,
874 refcount_set(&tz
->thermal_check_count
, 3);
875 mutex_init(&tz
->thermal_check_lock
);
876 INIT_WORK(&tz
->thermal_check_work
, acpi_thermal_check_fn
);
878 pr_info("%s [%s] (%ld C)\n", acpi_device_name(device
),
879 acpi_device_bid(device
), deci_kelvin_to_celsius(tz
->temp_dk
));
881 result
= acpi_dev_install_notify_handler(device
, ACPI_DEVICE_NOTIFY
,
882 acpi_thermal_notify
, device
);
889 flush_workqueue(acpi_thermal_pm_queue
);
890 acpi_thermal_unregister_thermal_zone(tz
);
892 acpi_thermal_free_thermal_zone(tz
);
897 static void acpi_thermal_remove(struct acpi_device
*device
)
899 struct acpi_thermal
*tz
;
901 if (!device
|| !acpi_driver_data(device
))
904 tz
= acpi_driver_data(device
);
906 acpi_dev_remove_notify_handler(device
, ACPI_DEVICE_NOTIFY
,
907 acpi_thermal_notify
);
909 flush_workqueue(acpi_thermal_pm_queue
);
910 acpi_thermal_unregister_thermal_zone(tz
);
911 acpi_thermal_free_thermal_zone(tz
);
914 #ifdef CONFIG_PM_SLEEP
915 static int acpi_thermal_suspend(struct device
*dev
)
917 /* Make sure the previously queued thermal check work has been done */
918 flush_workqueue(acpi_thermal_pm_queue
);
922 static int acpi_thermal_resume(struct device
*dev
)
924 struct acpi_thermal
*tz
;
925 int i
, j
, power_state
;
930 tz
= acpi_driver_data(to_acpi_device(dev
));
934 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
935 struct acpi_thermal_trip
*acpi_trip
= &tz
->trips
.active
[i
].trip
;
937 if (!acpi_thermal_trip_valid(acpi_trip
))
940 for (j
= 0; j
< acpi_trip
->devices
.count
; j
++) {
941 acpi_bus_update_power(acpi_trip
->devices
.handles
[j
],
946 acpi_queue_thermal_check(tz
);
951 #define acpi_thermal_suspend NULL
952 #define acpi_thermal_resume NULL
954 static SIMPLE_DEV_PM_OPS(acpi_thermal_pm
, acpi_thermal_suspend
, acpi_thermal_resume
);
956 static const struct acpi_device_id thermal_device_ids
[] = {
957 {ACPI_THERMAL_HID
, 0},
960 MODULE_DEVICE_TABLE(acpi
, thermal_device_ids
);
962 static struct acpi_driver acpi_thermal_driver
= {
964 .class = ACPI_THERMAL_CLASS
,
965 .ids
= thermal_device_ids
,
967 .add
= acpi_thermal_add
,
968 .remove
= acpi_thermal_remove
,
970 .drv
.pm
= &acpi_thermal_pm
,
973 static int thermal_act(const struct dmi_system_id
*d
)
976 pr_notice("%s detected: disabling all active thermal trip points\n",
983 static int thermal_nocrt(const struct dmi_system_id
*d
)
985 pr_notice("%s detected: disabling all critical thermal trip point actions.\n",
991 static int thermal_tzp(const struct dmi_system_id
*d
)
994 pr_notice("%s detected: enabling thermal zone polling\n",
996 tzp
= 300; /* 300 dS = 30 Seconds */
1001 static int thermal_psv(const struct dmi_system_id
*d
)
1004 pr_notice("%s detected: disabling all passive thermal trip points\n",
1011 static const struct dmi_system_id thermal_dmi_table
[] __initconst
= {
1013 * Award BIOS on this AOpen makes thermal control almost worthless.
1014 * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1017 .callback
= thermal_act
,
1018 .ident
= "AOpen i915GMm-HFS",
1020 DMI_MATCH(DMI_BOARD_VENDOR
, "AOpen"),
1021 DMI_MATCH(DMI_BOARD_NAME
, "i915GMm-HFS"),
1025 .callback
= thermal_psv
,
1026 .ident
= "AOpen i915GMm-HFS",
1028 DMI_MATCH(DMI_BOARD_VENDOR
, "AOpen"),
1029 DMI_MATCH(DMI_BOARD_NAME
, "i915GMm-HFS"),
1033 .callback
= thermal_tzp
,
1034 .ident
= "AOpen i915GMm-HFS",
1036 DMI_MATCH(DMI_BOARD_VENDOR
, "AOpen"),
1037 DMI_MATCH(DMI_BOARD_NAME
, "i915GMm-HFS"),
1041 .callback
= thermal_nocrt
,
1042 .ident
= "Gigabyte GA-7ZX",
1044 DMI_MATCH(DMI_BOARD_VENDOR
, "Gigabyte Technology Co., Ltd."),
1045 DMI_MATCH(DMI_BOARD_NAME
, "7ZX"),
1051 static int __init
acpi_thermal_init(void)
1055 dmi_check_system(thermal_dmi_table
);
1058 pr_notice("thermal control disabled\n");
1062 acpi_thermal_pm_queue
= alloc_workqueue("acpi_thermal_pm",
1063 WQ_HIGHPRI
| WQ_MEM_RECLAIM
, 0);
1064 if (!acpi_thermal_pm_queue
)
1067 result
= acpi_bus_register_driver(&acpi_thermal_driver
);
1069 destroy_workqueue(acpi_thermal_pm_queue
);
1076 static void __exit
acpi_thermal_exit(void)
1078 acpi_bus_unregister_driver(&acpi_thermal_driver
);
1079 destroy_workqueue(acpi_thermal_pm_queue
);
1082 module_init(acpi_thermal_init
);
1083 module_exit(acpi_thermal_exit
);
1085 MODULE_IMPORT_NS(ACPI_THERMAL
);
1086 MODULE_AUTHOR("Paul Diefenbaugh");
1087 MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
1088 MODULE_LICENSE("GPL");