[go: nahoru, domu]

thermal.c revision 8b48463f89429af408ff695244dc627e1acff4f7
1/*
2 *  acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $)
3 *
4 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 *  This program is free software; you can redistribute it and/or modify
10 *  it under the terms of the GNU General Public License as published by
11 *  the Free Software Foundation; either version 2 of the License, or (at
12 *  your option) any later version.
13 *
14 *  This program is distributed in the hope that it will be useful, but
15 *  WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 *  General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License along
20 *  with this program; if not, write to the Free Software Foundation, Inc.,
21 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 *
25 *  This driver fully implements the ACPI thermal policy as described in the
26 *  ACPI 2.0 Specification.
27 *
28 *  TBD: 1. Implement passive cooling hysteresis.
29 *       2. Enhance passive cooling (CPU) states/limit interface to support
30 *          concepts of 'multiple limiters', upper/lower limits, etc.
31 *
32 */
33
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/dmi.h>
37#include <linux/init.h>
38#include <linux/slab.h>
39#include <linux/types.h>
40#include <linux/jiffies.h>
41#include <linux/kmod.h>
42#include <linux/reboot.h>
43#include <linux/device.h>
44#include <linux/thermal.h>
45#include <linux/acpi.h>
46#include <asm/uaccess.h>
47
48#define PREFIX "ACPI: "
49
50#define ACPI_THERMAL_CLASS		"thermal_zone"
51#define ACPI_THERMAL_DEVICE_NAME	"Thermal Zone"
52#define ACPI_THERMAL_NOTIFY_TEMPERATURE	0x80
53#define ACPI_THERMAL_NOTIFY_THRESHOLDS	0x81
54#define ACPI_THERMAL_NOTIFY_DEVICES	0x82
55#define ACPI_THERMAL_NOTIFY_CRITICAL	0xF0
56#define ACPI_THERMAL_NOTIFY_HOT		0xF1
57#define ACPI_THERMAL_MODE_ACTIVE	0x00
58
59#define ACPI_THERMAL_MAX_ACTIVE	10
60#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
61
62#define _COMPONENT		ACPI_THERMAL_COMPONENT
63ACPI_MODULE_NAME("thermal");
64
65MODULE_AUTHOR("Paul Diefenbaugh");
66MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
67MODULE_LICENSE("GPL");
68
69static int act;
70module_param(act, int, 0644);
71MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.");
72
73static int crt;
74module_param(crt, int, 0644);
75MODULE_PARM_DESC(crt, "Disable or lower all critical trip points.");
76
77static int tzp;
78module_param(tzp, int, 0444);
79MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
80
81static int nocrt;
82module_param(nocrt, int, 0);
83MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
84
85static int off;
86module_param(off, int, 0);
87MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
88
89static int psv;
90module_param(psv, int, 0644);
91MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
92
93static int acpi_thermal_add(struct acpi_device *device);
94static int acpi_thermal_remove(struct acpi_device *device);
95static void acpi_thermal_notify(struct acpi_device *device, u32 event);
96
97static const struct acpi_device_id  thermal_device_ids[] = {
98	{ACPI_THERMAL_HID, 0},
99	{"", 0},
100};
101MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
102
103#ifdef CONFIG_PM_SLEEP
104static int acpi_thermal_resume(struct device *dev);
105#endif
106static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
107
108static struct acpi_driver acpi_thermal_driver = {
109	.name = "thermal",
110	.class = ACPI_THERMAL_CLASS,
111	.ids = thermal_device_ids,
112	.ops = {
113		.add = acpi_thermal_add,
114		.remove = acpi_thermal_remove,
115		.notify = acpi_thermal_notify,
116		},
117	.drv.pm = &acpi_thermal_pm,
118};
119
120struct acpi_thermal_state {
121	u8 critical:1;
122	u8 hot:1;
123	u8 passive:1;
124	u8 active:1;
125	u8 reserved:4;
126	int active_index;
127};
128
129struct acpi_thermal_state_flags {
130	u8 valid:1;
131	u8 enabled:1;
132	u8 reserved:6;
133};
134
135struct acpi_thermal_critical {
136	struct acpi_thermal_state_flags flags;
137	unsigned long temperature;
138};
139
140struct acpi_thermal_hot {
141	struct acpi_thermal_state_flags flags;
142	unsigned long temperature;
143};
144
145struct acpi_thermal_passive {
146	struct acpi_thermal_state_flags flags;
147	unsigned long temperature;
148	unsigned long tc1;
149	unsigned long tc2;
150	unsigned long tsp;
151	struct acpi_handle_list devices;
152};
153
154struct acpi_thermal_active {
155	struct acpi_thermal_state_flags flags;
156	unsigned long temperature;
157	struct acpi_handle_list devices;
158};
159
160struct acpi_thermal_trips {
161	struct acpi_thermal_critical critical;
162	struct acpi_thermal_hot hot;
163	struct acpi_thermal_passive passive;
164	struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
165};
166
167struct acpi_thermal_flags {
168	u8 cooling_mode:1;	/* _SCP */
169	u8 devices:1;		/* _TZD */
170	u8 reserved:6;
171};
172
173struct acpi_thermal {
174	struct acpi_device * device;
175	acpi_bus_id name;
176	unsigned long temperature;
177	unsigned long last_temperature;
178	unsigned long polling_frequency;
179	volatile u8 zombie;
180	struct acpi_thermal_flags flags;
181	struct acpi_thermal_state state;
182	struct acpi_thermal_trips trips;
183	struct acpi_handle_list devices;
184	struct thermal_zone_device *thermal_zone;
185	int tz_enabled;
186	int kelvin_offset;
187};
188
189/* --------------------------------------------------------------------------
190                             Thermal Zone Management
191   -------------------------------------------------------------------------- */
192
193static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
194{
195	acpi_status status = AE_OK;
196	unsigned long long tmp;
197
198	if (!tz)
199		return -EINVAL;
200
201	tz->last_temperature = tz->temperature;
202
203	status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
204	if (ACPI_FAILURE(status))
205		return -ENODEV;
206
207	tz->temperature = tmp;
208	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
209			  tz->temperature));
210
211	return 0;
212}
213
214static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
215{
216	acpi_status status = AE_OK;
217	unsigned long long tmp;
218
219	if (!tz)
220		return -EINVAL;
221
222	status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
223	if (ACPI_FAILURE(status))
224		return -ENODEV;
225
226	tz->polling_frequency = tmp;
227	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
228			  tz->polling_frequency));
229
230	return 0;
231}
232
233static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
234{
235	if (!tz)
236		return -EINVAL;
237
238	if (!acpi_has_method(tz->device->handle, "_SCP")) {
239		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
240		return -ENODEV;
241	} else if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
242							   "_SCP", mode))) {
243		return -ENODEV;
244	}
245
246	return 0;
247}
248
249#define ACPI_TRIPS_CRITICAL	0x01
250#define ACPI_TRIPS_HOT		0x02
251#define ACPI_TRIPS_PASSIVE	0x04
252#define ACPI_TRIPS_ACTIVE	0x08
253#define ACPI_TRIPS_DEVICES	0x10
254
255#define ACPI_TRIPS_REFRESH_THRESHOLDS	(ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
256#define ACPI_TRIPS_REFRESH_DEVICES	ACPI_TRIPS_DEVICES
257
258#define ACPI_TRIPS_INIT      (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT |	\
259			      ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE |	\
260			      ACPI_TRIPS_DEVICES)
261
262/*
263 * This exception is thrown out in two cases:
264 * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
265 *   when re-evaluating the AML code.
266 * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
267 *   We need to re-bind the cooling devices of a thermal zone when this occurs.
268 */
269#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str)	\
270do {	\
271	if (flags != ACPI_TRIPS_INIT)	\
272		ACPI_EXCEPTION((AE_INFO, AE_ERROR,	\
273		"ACPI thermal trip point %s changed\n"	\
274		"Please send acpidump to linux-acpi@vger.kernel.org", str)); \
275} while (0)
276
277static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
278{
279	acpi_status status = AE_OK;
280	unsigned long long tmp;
281	struct acpi_handle_list devices;
282	int valid = 0;
283	int i;
284
285	/* Critical Shutdown */
286	if (flag & ACPI_TRIPS_CRITICAL) {
287		status = acpi_evaluate_integer(tz->device->handle,
288				"_CRT", NULL, &tmp);
289		tz->trips.critical.temperature = tmp;
290		/*
291		 * Treat freezing temperatures as invalid as well; some
292		 * BIOSes return really low values and cause reboots at startup.
293		 * Below zero (Celsius) values clearly aren't right for sure..
294		 * ... so lets discard those as invalid.
295		 */
296		if (ACPI_FAILURE(status)) {
297			tz->trips.critical.flags.valid = 0;
298			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
299					  "No critical threshold\n"));
300		} else if (tmp <= 2732) {
301			pr_warn(FW_BUG "Invalid critical threshold (%llu)\n",
302				tmp);
303			tz->trips.critical.flags.valid = 0;
304		} else {
305			tz->trips.critical.flags.valid = 1;
306			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
307					  "Found critical threshold [%lu]\n",
308					  tz->trips.critical.temperature));
309		}
310		if (tz->trips.critical.flags.valid == 1) {
311			if (crt == -1) {
312				tz->trips.critical.flags.valid = 0;
313			} else if (crt > 0) {
314				unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
315				/*
316				 * Allow override critical threshold
317				 */
318				if (crt_k > tz->trips.critical.temperature)
319					pr_warn(PREFIX "Critical threshold %d C\n",
320						crt);
321				tz->trips.critical.temperature = crt_k;
322			}
323		}
324	}
325
326	/* Critical Sleep (optional) */
327	if (flag & ACPI_TRIPS_HOT) {
328		status = acpi_evaluate_integer(tz->device->handle,
329				"_HOT", NULL, &tmp);
330		if (ACPI_FAILURE(status)) {
331			tz->trips.hot.flags.valid = 0;
332			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
333					"No hot threshold\n"));
334		} else {
335			tz->trips.hot.temperature = tmp;
336			tz->trips.hot.flags.valid = 1;
337			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
338					"Found hot threshold [%lu]\n",
339					tz->trips.critical.temperature));
340		}
341	}
342
343	/* Passive (optional) */
344	if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
345		(flag == ACPI_TRIPS_INIT)) {
346		valid = tz->trips.passive.flags.valid;
347		if (psv == -1) {
348			status = AE_SUPPORT;
349		} else if (psv > 0) {
350			tmp = CELSIUS_TO_KELVIN(psv);
351			status = AE_OK;
352		} else {
353			status = acpi_evaluate_integer(tz->device->handle,
354				"_PSV", NULL, &tmp);
355		}
356
357		if (ACPI_FAILURE(status))
358			tz->trips.passive.flags.valid = 0;
359		else {
360			tz->trips.passive.temperature = tmp;
361			tz->trips.passive.flags.valid = 1;
362			if (flag == ACPI_TRIPS_INIT) {
363				status = acpi_evaluate_integer(
364						tz->device->handle, "_TC1",
365						NULL, &tmp);
366				if (ACPI_FAILURE(status))
367					tz->trips.passive.flags.valid = 0;
368				else
369					tz->trips.passive.tc1 = tmp;
370				status = acpi_evaluate_integer(
371						tz->device->handle, "_TC2",
372						NULL, &tmp);
373				if (ACPI_FAILURE(status))
374					tz->trips.passive.flags.valid = 0;
375				else
376					tz->trips.passive.tc2 = tmp;
377				status = acpi_evaluate_integer(
378						tz->device->handle, "_TSP",
379						NULL, &tmp);
380				if (ACPI_FAILURE(status))
381					tz->trips.passive.flags.valid = 0;
382				else
383					tz->trips.passive.tsp = tmp;
384			}
385		}
386	}
387	if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
388		memset(&devices, 0, sizeof(struct acpi_handle_list));
389		status = acpi_evaluate_reference(tz->device->handle, "_PSL",
390							NULL, &devices);
391		if (ACPI_FAILURE(status)) {
392			pr_warn(PREFIX "Invalid passive threshold\n");
393			tz->trips.passive.flags.valid = 0;
394		}
395		else
396			tz->trips.passive.flags.valid = 1;
397
398		if (memcmp(&tz->trips.passive.devices, &devices,
399				sizeof(struct acpi_handle_list))) {
400			memcpy(&tz->trips.passive.devices, &devices,
401				sizeof(struct acpi_handle_list));
402			ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
403		}
404	}
405	if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
406		if (valid != tz->trips.passive.flags.valid)
407				ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
408	}
409
410	/* Active (optional) */
411	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
412		char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
413		valid = tz->trips.active[i].flags.valid;
414
415		if (act == -1)
416			break; /* disable all active trip points */
417
418		if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
419			tz->trips.active[i].flags.valid)) {
420			status = acpi_evaluate_integer(tz->device->handle,
421							name, NULL, &tmp);
422			if (ACPI_FAILURE(status)) {
423				tz->trips.active[i].flags.valid = 0;
424				if (i == 0)
425					break;
426				if (act <= 0)
427					break;
428				if (i == 1)
429					tz->trips.active[0].temperature =
430						CELSIUS_TO_KELVIN(act);
431				else
432					/*
433					 * Don't allow override higher than
434					 * the next higher trip point
435					 */
436					tz->trips.active[i - 1].temperature =
437						(tz->trips.active[i - 2].temperature <
438						CELSIUS_TO_KELVIN(act) ?
439						tz->trips.active[i - 2].temperature :
440						CELSIUS_TO_KELVIN(act));
441				break;
442			} else {
443				tz->trips.active[i].temperature = tmp;
444				tz->trips.active[i].flags.valid = 1;
445			}
446		}
447
448		name[2] = 'L';
449		if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
450			memset(&devices, 0, sizeof(struct acpi_handle_list));
451			status = acpi_evaluate_reference(tz->device->handle,
452						name, NULL, &devices);
453			if (ACPI_FAILURE(status)) {
454				pr_warn(PREFIX "Invalid active%d threshold\n",
455					i);
456				tz->trips.active[i].flags.valid = 0;
457			}
458			else
459				tz->trips.active[i].flags.valid = 1;
460
461			if (memcmp(&tz->trips.active[i].devices, &devices,
462					sizeof(struct acpi_handle_list))) {
463				memcpy(&tz->trips.active[i].devices, &devices,
464					sizeof(struct acpi_handle_list));
465				ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
466			}
467		}
468		if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
469			if (valid != tz->trips.active[i].flags.valid)
470				ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
471
472		if (!tz->trips.active[i].flags.valid)
473			break;
474	}
475
476	if ((flag & ACPI_TRIPS_DEVICES)
477	    && acpi_has_method(tz->device->handle, "_TZD")) {
478		memset(&devices, 0, sizeof(devices));
479		status = acpi_evaluate_reference(tz->device->handle, "_TZD",
480						NULL, &devices);
481		if (ACPI_SUCCESS(status)
482		    && memcmp(&tz->devices, &devices, sizeof(devices))) {
483			tz->devices = devices;
484			ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
485		}
486	}
487
488	return 0;
489}
490
491static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
492{
493	int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
494
495	if (ret)
496		return ret;
497
498	valid = tz->trips.critical.flags.valid |
499		tz->trips.hot.flags.valid |
500		tz->trips.passive.flags.valid;
501
502	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
503		valid |= tz->trips.active[i].flags.valid;
504
505	if (!valid) {
506		pr_warn(FW_BUG "No valid trip found\n");
507		return -ENODEV;
508	}
509	return 0;
510}
511
512static void acpi_thermal_check(void *data)
513{
514	struct acpi_thermal *tz = data;
515
516	if (!tz->tz_enabled)
517		return;
518
519	thermal_zone_device_update(tz->thermal_zone);
520}
521
522/* sys I/F for generic thermal sysfs support */
523#define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
524
525static int thermal_get_temp(struct thermal_zone_device *thermal,
526			    unsigned long *temp)
527{
528	struct acpi_thermal *tz = thermal->devdata;
529	int result;
530
531	if (!tz)
532		return -EINVAL;
533
534	result = acpi_thermal_get_temperature(tz);
535	if (result)
536		return result;
537
538	*temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
539	return 0;
540}
541
542static int thermal_get_mode(struct thermal_zone_device *thermal,
543				enum thermal_device_mode *mode)
544{
545	struct acpi_thermal *tz = thermal->devdata;
546
547	if (!tz)
548		return -EINVAL;
549
550	*mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED :
551		THERMAL_DEVICE_DISABLED;
552
553	return 0;
554}
555
556static int thermal_set_mode(struct thermal_zone_device *thermal,
557				enum thermal_device_mode mode)
558{
559	struct acpi_thermal *tz = thermal->devdata;
560	int enable;
561
562	if (!tz)
563		return -EINVAL;
564
565	/*
566	 * enable/disable thermal management from ACPI thermal driver
567	 */
568	if (mode == THERMAL_DEVICE_ENABLED)
569		enable = 1;
570	else if (mode == THERMAL_DEVICE_DISABLED) {
571		enable = 0;
572		pr_warn("thermal zone will be disabled\n");
573	} else
574		return -EINVAL;
575
576	if (enable != tz->tz_enabled) {
577		tz->tz_enabled = enable;
578		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
579			"%s kernel ACPI thermal control\n",
580			tz->tz_enabled ? "Enable" : "Disable"));
581		acpi_thermal_check(tz);
582	}
583	return 0;
584}
585
586static int thermal_get_trip_type(struct thermal_zone_device *thermal,
587				 int trip, enum thermal_trip_type *type)
588{
589	struct acpi_thermal *tz = thermal->devdata;
590	int i;
591
592	if (!tz || trip < 0)
593		return -EINVAL;
594
595	if (tz->trips.critical.flags.valid) {
596		if (!trip) {
597			*type = THERMAL_TRIP_CRITICAL;
598			return 0;
599		}
600		trip--;
601	}
602
603	if (tz->trips.hot.flags.valid) {
604		if (!trip) {
605			*type = THERMAL_TRIP_HOT;
606			return 0;
607		}
608		trip--;
609	}
610
611	if (tz->trips.passive.flags.valid) {
612		if (!trip) {
613			*type = THERMAL_TRIP_PASSIVE;
614			return 0;
615		}
616		trip--;
617	}
618
619	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
620		tz->trips.active[i].flags.valid; i++) {
621		if (!trip) {
622			*type = THERMAL_TRIP_ACTIVE;
623			return 0;
624		}
625		trip--;
626	}
627
628	return -EINVAL;
629}
630
631static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
632				 int trip, unsigned long *temp)
633{
634	struct acpi_thermal *tz = thermal->devdata;
635	int i;
636
637	if (!tz || trip < 0)
638		return -EINVAL;
639
640	if (tz->trips.critical.flags.valid) {
641		if (!trip) {
642			*temp = KELVIN_TO_MILLICELSIUS(
643				tz->trips.critical.temperature,
644				tz->kelvin_offset);
645			return 0;
646		}
647		trip--;
648	}
649
650	if (tz->trips.hot.flags.valid) {
651		if (!trip) {
652			*temp = KELVIN_TO_MILLICELSIUS(
653				tz->trips.hot.temperature,
654				tz->kelvin_offset);
655			return 0;
656		}
657		trip--;
658	}
659
660	if (tz->trips.passive.flags.valid) {
661		if (!trip) {
662			*temp = KELVIN_TO_MILLICELSIUS(
663				tz->trips.passive.temperature,
664				tz->kelvin_offset);
665			return 0;
666		}
667		trip--;
668	}
669
670	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
671		tz->trips.active[i].flags.valid; i++) {
672		if (!trip) {
673			*temp = KELVIN_TO_MILLICELSIUS(
674				tz->trips.active[i].temperature,
675				tz->kelvin_offset);
676			return 0;
677		}
678		trip--;
679	}
680
681	return -EINVAL;
682}
683
684static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
685				unsigned long *temperature) {
686	struct acpi_thermal *tz = thermal->devdata;
687
688	if (tz->trips.critical.flags.valid) {
689		*temperature = KELVIN_TO_MILLICELSIUS(
690				tz->trips.critical.temperature,
691				tz->kelvin_offset);
692		return 0;
693	} else
694		return -EINVAL;
695}
696
697static int thermal_get_trend(struct thermal_zone_device *thermal,
698				int trip, enum thermal_trend *trend)
699{
700	struct acpi_thermal *tz = thermal->devdata;
701	enum thermal_trip_type type;
702	int i;
703
704	if (thermal_get_trip_type(thermal, trip, &type))
705		return -EINVAL;
706
707	if (type == THERMAL_TRIP_ACTIVE) {
708		unsigned long trip_temp;
709		unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature,
710							tz->kelvin_offset);
711		if (thermal_get_trip_temp(thermal, trip, &trip_temp))
712			return -EINVAL;
713
714		if (temp > trip_temp) {
715			*trend = THERMAL_TREND_RAISING;
716			return 0;
717		} else {
718			/* Fall back on default trend */
719			return -EINVAL;
720		}
721	}
722
723	/*
724	 * tz->temperature has already been updated by generic thermal layer,
725	 * before this callback being invoked
726	 */
727	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
728		+ (tz->trips.passive.tc2
729		* (tz->temperature - tz->trips.passive.temperature));
730
731	if (i > 0)
732		*trend = THERMAL_TREND_RAISING;
733	else if (i < 0)
734		*trend = THERMAL_TREND_DROPPING;
735	else
736		*trend = THERMAL_TREND_STABLE;
737	return 0;
738}
739
740
741static int thermal_notify(struct thermal_zone_device *thermal, int trip,
742			   enum thermal_trip_type trip_type)
743{
744	u8 type = 0;
745	struct acpi_thermal *tz = thermal->devdata;
746
747	if (trip_type == THERMAL_TRIP_CRITICAL)
748		type = ACPI_THERMAL_NOTIFY_CRITICAL;
749	else if (trip_type == THERMAL_TRIP_HOT)
750		type = ACPI_THERMAL_NOTIFY_HOT;
751	else
752		return 0;
753
754	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
755					dev_name(&tz->device->dev), type, 1);
756
757	if (trip_type == THERMAL_TRIP_CRITICAL && nocrt)
758		return 1;
759
760	return 0;
761}
762
763static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
764					struct thermal_cooling_device *cdev,
765					bool bind)
766{
767	struct acpi_device *device = cdev->devdata;
768	struct acpi_thermal *tz = thermal->devdata;
769	struct acpi_device *dev;
770	acpi_status status;
771	acpi_handle handle;
772	int i;
773	int j;
774	int trip = -1;
775	int result = 0;
776
777	if (tz->trips.critical.flags.valid)
778		trip++;
779
780	if (tz->trips.hot.flags.valid)
781		trip++;
782
783	if (tz->trips.passive.flags.valid) {
784		trip++;
785		for (i = 0; i < tz->trips.passive.devices.count;
786		    i++) {
787			handle = tz->trips.passive.devices.handles[i];
788			status = acpi_bus_get_device(handle, &dev);
789			if (ACPI_FAILURE(status) || dev != device)
790				continue;
791			if (bind)
792				result =
793					thermal_zone_bind_cooling_device
794					(thermal, trip, cdev,
795					 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
796			else
797				result =
798					thermal_zone_unbind_cooling_device
799					(thermal, trip, cdev);
800			if (result)
801				goto failed;
802		}
803	}
804
805	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
806		if (!tz->trips.active[i].flags.valid)
807			break;
808		trip++;
809		for (j = 0;
810		    j < tz->trips.active[i].devices.count;
811		    j++) {
812			handle = tz->trips.active[i].devices.handles[j];
813			status = acpi_bus_get_device(handle, &dev);
814			if (ACPI_FAILURE(status) || dev != device)
815				continue;
816			if (bind)
817				result = thermal_zone_bind_cooling_device
818					(thermal, trip, cdev,
819					 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
820			else
821				result = thermal_zone_unbind_cooling_device
822					(thermal, trip, cdev);
823			if (result)
824				goto failed;
825		}
826	}
827
828	for (i = 0; i < tz->devices.count; i++) {
829		handle = tz->devices.handles[i];
830		status = acpi_bus_get_device(handle, &dev);
831		if (ACPI_SUCCESS(status) && (dev == device)) {
832			if (bind)
833				result = thermal_zone_bind_cooling_device
834						(thermal, THERMAL_TRIPS_NONE,
835						 cdev, THERMAL_NO_LIMIT,
836						 THERMAL_NO_LIMIT);
837			else
838				result = thermal_zone_unbind_cooling_device
839						(thermal, THERMAL_TRIPS_NONE,
840						 cdev);
841			if (result)
842				goto failed;
843		}
844	}
845
846failed:
847	return result;
848}
849
850static int
851acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
852					struct thermal_cooling_device *cdev)
853{
854	return acpi_thermal_cooling_device_cb(thermal, cdev, true);
855}
856
857static int
858acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
859					struct thermal_cooling_device *cdev)
860{
861	return acpi_thermal_cooling_device_cb(thermal, cdev, false);
862}
863
864static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
865	.bind = acpi_thermal_bind_cooling_device,
866	.unbind	= acpi_thermal_unbind_cooling_device,
867	.get_temp = thermal_get_temp,
868	.get_mode = thermal_get_mode,
869	.set_mode = thermal_set_mode,
870	.get_trip_type = thermal_get_trip_type,
871	.get_trip_temp = thermal_get_trip_temp,
872	.get_crit_temp = thermal_get_crit_temp,
873	.get_trend = thermal_get_trend,
874	.notify = thermal_notify,
875};
876
877static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
878{
879	int trips = 0;
880	int result;
881	acpi_status status;
882	int i;
883
884	if (tz->trips.critical.flags.valid)
885		trips++;
886
887	if (tz->trips.hot.flags.valid)
888		trips++;
889
890	if (tz->trips.passive.flags.valid)
891		trips++;
892
893	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
894			tz->trips.active[i].flags.valid; i++, trips++);
895
896	if (tz->trips.passive.flags.valid)
897		tz->thermal_zone =
898			thermal_zone_device_register("acpitz", trips, 0, tz,
899						&acpi_thermal_zone_ops, NULL,
900						     tz->trips.passive.tsp*100,
901						     tz->polling_frequency*100);
902	else
903		tz->thermal_zone =
904			thermal_zone_device_register("acpitz", trips, 0, tz,
905						&acpi_thermal_zone_ops, NULL,
906						0, tz->polling_frequency*100);
907	if (IS_ERR(tz->thermal_zone))
908		return -ENODEV;
909
910	result = sysfs_create_link(&tz->device->dev.kobj,
911				   &tz->thermal_zone->device.kobj, "thermal_zone");
912	if (result)
913		return result;
914
915	result = sysfs_create_link(&tz->thermal_zone->device.kobj,
916				   &tz->device->dev.kobj, "device");
917	if (result)
918		return result;
919
920	status = acpi_attach_data(tz->device->handle,
921				  acpi_bus_private_data_handler,
922				  tz->thermal_zone);
923	if (ACPI_FAILURE(status)) {
924		pr_err(PREFIX "Error attaching device data\n");
925		return -ENODEV;
926	}
927
928	tz->tz_enabled = 1;
929
930	dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
931		 tz->thermal_zone->id);
932	return 0;
933}
934
935static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
936{
937	sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
938	sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
939	thermal_zone_device_unregister(tz->thermal_zone);
940	tz->thermal_zone = NULL;
941	acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
942}
943
944
945/* --------------------------------------------------------------------------
946                                 Driver Interface
947   -------------------------------------------------------------------------- */
948
949static void acpi_thermal_notify(struct acpi_device *device, u32 event)
950{
951	struct acpi_thermal *tz = acpi_driver_data(device);
952
953
954	if (!tz)
955		return;
956
957	switch (event) {
958	case ACPI_THERMAL_NOTIFY_TEMPERATURE:
959		acpi_thermal_check(tz);
960		break;
961	case ACPI_THERMAL_NOTIFY_THRESHOLDS:
962		acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
963		acpi_thermal_check(tz);
964		acpi_bus_generate_netlink_event(device->pnp.device_class,
965						  dev_name(&device->dev), event, 0);
966		break;
967	case ACPI_THERMAL_NOTIFY_DEVICES:
968		acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
969		acpi_thermal_check(tz);
970		acpi_bus_generate_netlink_event(device->pnp.device_class,
971						  dev_name(&device->dev), event, 0);
972		break;
973	default:
974		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
975				  "Unsupported event [0x%x]\n", event));
976		break;
977	}
978}
979
980/*
981 * On some platforms, the AML code has dependency about
982 * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
983 * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
984 *    /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
985 * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
986 *    if _TMP has never been evaluated.
987 *
988 * As this dependency is totally transparent to OS, evaluate
989 * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
990 * _TMP, before they are actually used.
991 */
992static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
993{
994	acpi_handle handle = tz->device->handle;
995	unsigned long long value;
996	int i;
997
998	acpi_evaluate_integer(handle, "_CRT", NULL, &value);
999	acpi_evaluate_integer(handle, "_HOT", NULL, &value);
1000	acpi_evaluate_integer(handle, "_PSV", NULL, &value);
1001	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1002		char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
1003		acpi_status status;
1004
1005		status = acpi_evaluate_integer(handle, name, NULL, &value);
1006		if (status == AE_NOT_FOUND)
1007			break;
1008	}
1009	acpi_evaluate_integer(handle, "_TMP", NULL, &value);
1010}
1011
1012static int acpi_thermal_get_info(struct acpi_thermal *tz)
1013{
1014	int result = 0;
1015
1016
1017	if (!tz)
1018		return -EINVAL;
1019
1020	acpi_thermal_aml_dependency_fix(tz);
1021
1022	/* Get trip points [_CRT, _PSV, etc.] (required) */
1023	result = acpi_thermal_get_trip_points(tz);
1024	if (result)
1025		return result;
1026
1027	/* Get temperature [_TMP] (required) */
1028	result = acpi_thermal_get_temperature(tz);
1029	if (result)
1030		return result;
1031
1032	/* Set the cooling mode [_SCP] to active cooling (default) */
1033	result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
1034	if (!result)
1035		tz->flags.cooling_mode = 1;
1036
1037	/* Get default polling frequency [_TZP] (optional) */
1038	if (tzp)
1039		tz->polling_frequency = tzp;
1040	else
1041		acpi_thermal_get_polling_frequency(tz);
1042
1043	return 0;
1044}
1045
1046/*
1047 * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
1048 * handles temperature values with a single decimal place. As a consequence,
1049 * some implementations use an offset of 273.1 and others use an offset of
1050 * 273.2. Try to find out which one is being used, to present the most
1051 * accurate and visually appealing number.
1052 *
1053 * The heuristic below should work for all ACPI thermal zones which have a
1054 * critical trip point with a value being a multiple of 0.5 degree Celsius.
1055 */
1056static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
1057{
1058	if (tz->trips.critical.flags.valid &&
1059	    (tz->trips.critical.temperature % 5) == 1)
1060		tz->kelvin_offset = 2731;
1061	else
1062		tz->kelvin_offset = 2732;
1063}
1064
1065static int acpi_thermal_add(struct acpi_device *device)
1066{
1067	int result = 0;
1068	struct acpi_thermal *tz = NULL;
1069
1070
1071	if (!device)
1072		return -EINVAL;
1073
1074	tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
1075	if (!tz)
1076		return -ENOMEM;
1077
1078	tz->device = device;
1079	strcpy(tz->name, device->pnp.bus_id);
1080	strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
1081	strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1082	device->driver_data = tz;
1083
1084	result = acpi_thermal_get_info(tz);
1085	if (result)
1086		goto free_memory;
1087
1088	acpi_thermal_guess_offset(tz);
1089
1090	result = acpi_thermal_register_thermal_zone(tz);
1091	if (result)
1092		goto free_memory;
1093
1094	pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
1095		acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature));
1096	goto end;
1097
1098free_memory:
1099	kfree(tz);
1100end:
1101	return result;
1102}
1103
1104static int acpi_thermal_remove(struct acpi_device *device)
1105{
1106	struct acpi_thermal *tz = NULL;
1107
1108	if (!device || !acpi_driver_data(device))
1109		return -EINVAL;
1110
1111	tz = acpi_driver_data(device);
1112
1113	acpi_thermal_unregister_thermal_zone(tz);
1114	kfree(tz);
1115	return 0;
1116}
1117
1118#ifdef CONFIG_PM_SLEEP
1119static int acpi_thermal_resume(struct device *dev)
1120{
1121	struct acpi_thermal *tz;
1122	int i, j, power_state, result;
1123
1124	if (!dev)
1125		return -EINVAL;
1126
1127	tz = acpi_driver_data(to_acpi_device(dev));
1128	if (!tz)
1129		return -EINVAL;
1130
1131	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1132		if (!(&tz->trips.active[i]))
1133			break;
1134		if (!tz->trips.active[i].flags.valid)
1135			break;
1136		tz->trips.active[i].flags.enabled = 1;
1137		for (j = 0; j < tz->trips.active[i].devices.count; j++) {
1138			result = acpi_bus_update_power(
1139					tz->trips.active[i].devices.handles[j],
1140					&power_state);
1141			if (result || (power_state != ACPI_STATE_D0)) {
1142				tz->trips.active[i].flags.enabled = 0;
1143				break;
1144			}
1145		}
1146		tz->state.active |= tz->trips.active[i].flags.enabled;
1147	}
1148
1149	acpi_thermal_check(tz);
1150
1151	return AE_OK;
1152}
1153#endif
1154
1155static int thermal_act(const struct dmi_system_id *d) {
1156
1157	if (act == 0) {
1158		pr_notice(PREFIX "%s detected: "
1159			  "disabling all active thermal trip points\n", d->ident);
1160		act = -1;
1161	}
1162	return 0;
1163}
1164static int thermal_nocrt(const struct dmi_system_id *d) {
1165
1166	pr_notice(PREFIX "%s detected: "
1167		  "disabling all critical thermal trip point actions.\n", d->ident);
1168	nocrt = 1;
1169	return 0;
1170}
1171static int thermal_tzp(const struct dmi_system_id *d) {
1172
1173	if (tzp == 0) {
1174		pr_notice(PREFIX "%s detected: "
1175			  "enabling thermal zone polling\n", d->ident);
1176		tzp = 300;	/* 300 dS = 30 Seconds */
1177	}
1178	return 0;
1179}
1180static int thermal_psv(const struct dmi_system_id *d) {
1181
1182	if (psv == 0) {
1183		pr_notice(PREFIX "%s detected: "
1184			  "disabling all passive thermal trip points\n", d->ident);
1185		psv = -1;
1186	}
1187	return 0;
1188}
1189
1190static struct dmi_system_id thermal_dmi_table[] __initdata = {
1191	/*
1192	 * Award BIOS on this AOpen makes thermal control almost worthless.
1193	 * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1194	 */
1195	{
1196	 .callback = thermal_act,
1197	 .ident = "AOpen i915GMm-HFS",
1198	 .matches = {
1199		DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1200		DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1201		},
1202	},
1203	{
1204	 .callback = thermal_psv,
1205	 .ident = "AOpen i915GMm-HFS",
1206	 .matches = {
1207		DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1208		DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1209		},
1210	},
1211	{
1212	 .callback = thermal_tzp,
1213	 .ident = "AOpen i915GMm-HFS",
1214	 .matches = {
1215		DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1216		DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1217		},
1218	},
1219	{
1220	 .callback = thermal_nocrt,
1221	 .ident = "Gigabyte GA-7ZX",
1222	 .matches = {
1223		DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
1224		DMI_MATCH(DMI_BOARD_NAME, "7ZX"),
1225		},
1226	},
1227	{}
1228};
1229
1230static int __init acpi_thermal_init(void)
1231{
1232	int result = 0;
1233
1234	dmi_check_system(thermal_dmi_table);
1235
1236	if (off) {
1237		pr_notice(PREFIX "thermal control disabled\n");
1238		return -ENODEV;
1239	}
1240
1241	result = acpi_bus_register_driver(&acpi_thermal_driver);
1242	if (result < 0)
1243		return -ENODEV;
1244
1245	return 0;
1246}
1247
1248static void __exit acpi_thermal_exit(void)
1249{
1250
1251	acpi_bus_unregister_driver(&acpi_thermal_driver);
1252
1253	return;
1254}
1255
1256module_init(acpi_thermal_init);
1257module_exit(acpi_thermal_exit);
1258