Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[linux-2.6/kmemtrace.git] / drivers / thermal / thermal.c
blob41bd4c805ace249c6c43f44066df7c049d0cdac4
1 /*
2 * thermal.c - Generic Thermal Management Sysfs support.
4 * Copyright (C) 2008 Intel Corp
5 * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
6 * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2 of the License.
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.
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.
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 #include <linux/module.h>
27 #include <linux/device.h>
28 #include <linux/err.h>
29 #include <linux/kdev_t.h>
30 #include <linux/idr.h>
31 #include <linux/thermal.h>
32 #include <linux/spinlock.h>
33 #include <linux/hwmon.h>
34 #include <linux/hwmon-sysfs.h>
36 MODULE_AUTHOR("Zhang Rui");
37 MODULE_DESCRIPTION("Generic thermal management sysfs support");
38 MODULE_LICENSE("GPL");
40 #define PREFIX "Thermal: "
42 struct thermal_cooling_device_instance {
43 int id;
44 char name[THERMAL_NAME_LENGTH];
45 struct thermal_zone_device *tz;
46 struct thermal_cooling_device *cdev;
47 int trip;
48 char attr_name[THERMAL_NAME_LENGTH];
49 struct device_attribute attr;
50 struct list_head node;
53 static DEFINE_IDR(thermal_tz_idr);
54 static DEFINE_IDR(thermal_cdev_idr);
55 static DEFINE_MUTEX(thermal_idr_lock);
57 static LIST_HEAD(thermal_tz_list);
58 static LIST_HEAD(thermal_cdev_list);
59 static DEFINE_MUTEX(thermal_list_lock);
61 static struct device *thermal_hwmon;
62 #define MAX_THERMAL_ZONES 10
64 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
66 int err;
68 again:
69 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
70 return -ENOMEM;
72 if (lock)
73 mutex_lock(lock);
74 err = idr_get_new(idr, NULL, id);
75 if (lock)
76 mutex_unlock(lock);
77 if (unlikely(err == -EAGAIN))
78 goto again;
79 else if (unlikely(err))
80 return err;
82 *id = *id & MAX_ID_MASK;
83 return 0;
86 static void release_idr(struct idr *idr, struct mutex *lock, int id)
88 if (lock)
89 mutex_lock(lock);
90 idr_remove(idr, id);
91 if (lock)
92 mutex_unlock(lock);
95 /* hwmon sys I/F*/
96 static ssize_t
97 name_show(struct device *dev, struct device_attribute *attr, char *buf)
99 return sprintf(buf, "thermal_sys_class\n");
102 static ssize_t
103 temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
105 struct thermal_zone_device *tz;
106 struct sensor_device_attribute *sensor_attr
107 = to_sensor_dev_attr(attr);
109 list_for_each_entry(tz, &thermal_tz_list, node)
110 if (tz->id == sensor_attr->index)
111 return tz->ops->get_temp(tz, buf);
113 return -ENODEV;
116 static ssize_t
117 temp_crit_show(struct device *dev, struct device_attribute *attr,
118 char *buf)
120 struct thermal_zone_device *tz;
121 struct sensor_device_attribute *sensor_attr
122 = to_sensor_dev_attr(attr);
124 list_for_each_entry(tz, &thermal_tz_list, node)
125 if (tz->id == sensor_attr->index)
126 return tz->ops->get_trip_temp(tz, 0, buf);
128 return -ENODEV;
131 static DEVICE_ATTR(name, 0444, name_show, NULL);
132 static struct sensor_device_attribute sensor_attrs[] = {
133 SENSOR_ATTR(temp1_input, 0444, temp_input_show, NULL, 0),
134 SENSOR_ATTR(temp1_crit, 0444, temp_crit_show, NULL, 0),
135 SENSOR_ATTR(temp2_input, 0444, temp_input_show, NULL, 1),
136 SENSOR_ATTR(temp2_crit, 0444, temp_crit_show, NULL, 1),
137 SENSOR_ATTR(temp3_input, 0444, temp_input_show, NULL, 2),
138 SENSOR_ATTR(temp3_crit, 0444, temp_crit_show, NULL, 2),
139 SENSOR_ATTR(temp4_input, 0444, temp_input_show, NULL, 3),
140 SENSOR_ATTR(temp4_crit, 0444, temp_crit_show, NULL, 3),
141 SENSOR_ATTR(temp5_input, 0444, temp_input_show, NULL, 4),
142 SENSOR_ATTR(temp5_crit, 0444, temp_crit_show, NULL, 4),
143 SENSOR_ATTR(temp6_input, 0444, temp_input_show, NULL, 5),
144 SENSOR_ATTR(temp6_crit, 0444, temp_crit_show, NULL, 5),
145 SENSOR_ATTR(temp7_input, 0444, temp_input_show, NULL, 6),
146 SENSOR_ATTR(temp7_crit, 0444, temp_crit_show, NULL, 6),
147 SENSOR_ATTR(temp8_input, 0444, temp_input_show, NULL, 7),
148 SENSOR_ATTR(temp8_crit, 0444, temp_crit_show, NULL, 7),
149 SENSOR_ATTR(temp9_input, 0444, temp_input_show, NULL, 8),
150 SENSOR_ATTR(temp9_crit, 0444, temp_crit_show, NULL, 8),
151 SENSOR_ATTR(temp10_input, 0444, temp_input_show, NULL, 9),
152 SENSOR_ATTR(temp10_crit, 0444, temp_crit_show, NULL, 9),
155 /* thermal zone sys I/F */
157 #define to_thermal_zone(_dev) \
158 container_of(_dev, struct thermal_zone_device, device)
160 static ssize_t
161 type_show(struct device *dev, struct device_attribute *attr, char *buf)
163 struct thermal_zone_device *tz = to_thermal_zone(dev);
165 return sprintf(buf, "%s\n", tz->type);
168 static ssize_t
169 temp_show(struct device *dev, struct device_attribute *attr, char *buf)
171 struct thermal_zone_device *tz = to_thermal_zone(dev);
173 if (!tz->ops->get_temp)
174 return -EPERM;
176 return tz->ops->get_temp(tz, buf);
179 static ssize_t
180 mode_show(struct device *dev, struct device_attribute *attr, char *buf)
182 struct thermal_zone_device *tz = to_thermal_zone(dev);
184 if (!tz->ops->get_mode)
185 return -EPERM;
187 return tz->ops->get_mode(tz, buf);
190 static ssize_t
191 mode_store(struct device *dev, struct device_attribute *attr,
192 const char *buf, size_t count)
194 struct thermal_zone_device *tz = to_thermal_zone(dev);
195 int result;
197 if (!tz->ops->set_mode)
198 return -EPERM;
200 result = tz->ops->set_mode(tz, buf);
201 if (result)
202 return result;
204 return count;
207 static ssize_t
208 trip_point_type_show(struct device *dev, struct device_attribute *attr,
209 char *buf)
211 struct thermal_zone_device *tz = to_thermal_zone(dev);
212 int trip;
214 if (!tz->ops->get_trip_type)
215 return -EPERM;
217 if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
218 return -EINVAL;
220 return tz->ops->get_trip_type(tz, trip, buf);
223 static ssize_t
224 trip_point_temp_show(struct device *dev, struct device_attribute *attr,
225 char *buf)
227 struct thermal_zone_device *tz = to_thermal_zone(dev);
228 int trip;
230 if (!tz->ops->get_trip_temp)
231 return -EPERM;
233 if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
234 return -EINVAL;
236 return tz->ops->get_trip_temp(tz, trip, buf);
239 static DEVICE_ATTR(type, 0444, type_show, NULL);
240 static DEVICE_ATTR(temp, 0444, temp_show, NULL);
241 static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
243 static struct device_attribute trip_point_attrs[] = {
244 __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
245 __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
246 __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
247 __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
248 __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
249 __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
250 __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
251 __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
252 __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
253 __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
254 __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
255 __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
256 __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
257 __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
258 __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
259 __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
260 __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
261 __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
262 __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
263 __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
266 #define TRIP_POINT_ATTR_ADD(_dev, _index, result) \
267 do { \
268 result = device_create_file(_dev, \
269 &trip_point_attrs[_index * 2]); \
270 if (result) \
271 break; \
272 result = device_create_file(_dev, \
273 &trip_point_attrs[_index * 2 + 1]); \
274 } while (0)
276 #define TRIP_POINT_ATTR_REMOVE(_dev, _index) \
277 do { \
278 device_remove_file(_dev, &trip_point_attrs[_index * 2]); \
279 device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \
280 } while (0)
282 /* cooling device sys I/F */
283 #define to_cooling_device(_dev) \
284 container_of(_dev, struct thermal_cooling_device, device)
286 static ssize_t
287 thermal_cooling_device_type_show(struct device *dev,
288 struct device_attribute *attr, char *buf)
290 struct thermal_cooling_device *cdev = to_cooling_device(dev);
292 return sprintf(buf, "%s\n", cdev->type);
295 static ssize_t
296 thermal_cooling_device_max_state_show(struct device *dev,
297 struct device_attribute *attr, char *buf)
299 struct thermal_cooling_device *cdev = to_cooling_device(dev);
301 return cdev->ops->get_max_state(cdev, buf);
304 static ssize_t
305 thermal_cooling_device_cur_state_show(struct device *dev,
306 struct device_attribute *attr, char *buf)
308 struct thermal_cooling_device *cdev = to_cooling_device(dev);
310 return cdev->ops->get_cur_state(cdev, buf);
313 static ssize_t
314 thermal_cooling_device_cur_state_store(struct device *dev,
315 struct device_attribute *attr,
316 const char *buf, size_t count)
318 struct thermal_cooling_device *cdev = to_cooling_device(dev);
319 int state;
320 int result;
322 if (!sscanf(buf, "%d\n", &state))
323 return -EINVAL;
325 if (state < 0)
326 return -EINVAL;
328 result = cdev->ops->set_cur_state(cdev, state);
329 if (result)
330 return result;
331 return count;
334 static struct device_attribute dev_attr_cdev_type =
335 __ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
336 static DEVICE_ATTR(max_state, 0444,
337 thermal_cooling_device_max_state_show, NULL);
338 static DEVICE_ATTR(cur_state, 0644,
339 thermal_cooling_device_cur_state_show,
340 thermal_cooling_device_cur_state_store);
342 static ssize_t
343 thermal_cooling_device_trip_point_show(struct device *dev,
344 struct device_attribute *attr, char *buf)
346 struct thermal_cooling_device_instance *instance;
348 instance =
349 container_of(attr, struct thermal_cooling_device_instance, attr);
351 if (instance->trip == THERMAL_TRIPS_NONE)
352 return sprintf(buf, "-1\n");
353 else
354 return sprintf(buf, "%d\n", instance->trip);
357 /* Device management */
360 * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
361 * @tz: thermal zone device
362 * @trip: indicates which trip point the cooling devices is
363 * associated with in this thermal zone.
364 * @cdev: thermal cooling device
366 * This function is usually called in the thermal zone device .bind callback.
368 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
369 int trip,
370 struct thermal_cooling_device *cdev)
372 struct thermal_cooling_device_instance *dev;
373 struct thermal_cooling_device_instance *pos;
374 struct thermal_zone_device *pos1;
375 struct thermal_cooling_device *pos2;
376 int result;
378 if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
379 return -EINVAL;
381 list_for_each_entry(pos1, &thermal_tz_list, node) {
382 if (pos1 == tz)
383 break;
385 list_for_each_entry(pos2, &thermal_cdev_list, node) {
386 if (pos2 == cdev)
387 break;
390 if (tz != pos1 || cdev != pos2)
391 return -EINVAL;
393 dev =
394 kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
395 if (!dev)
396 return -ENOMEM;
397 dev->tz = tz;
398 dev->cdev = cdev;
399 dev->trip = trip;
400 result = get_idr(&tz->idr, &tz->lock, &dev->id);
401 if (result)
402 goto free_mem;
404 sprintf(dev->name, "cdev%d", dev->id);
405 result =
406 sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name);
407 if (result)
408 goto release_idr;
410 sprintf(dev->attr_name, "cdev%d_trip_point", dev->id);
411 dev->attr.attr.name = dev->attr_name;
412 dev->attr.attr.mode = 0444;
413 dev->attr.show = thermal_cooling_device_trip_point_show;
414 result = device_create_file(&tz->device, &dev->attr);
415 if (result)
416 goto remove_symbol_link;
418 mutex_lock(&tz->lock);
419 list_for_each_entry(pos, &tz->cooling_devices, node)
420 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
421 result = -EEXIST;
422 break;
424 if (!result)
425 list_add_tail(&dev->node, &tz->cooling_devices);
426 mutex_unlock(&tz->lock);
428 if (!result)
429 return 0;
431 device_remove_file(&tz->device, &dev->attr);
432 remove_symbol_link:
433 sysfs_remove_link(&tz->device.kobj, dev->name);
434 release_idr:
435 release_idr(&tz->idr, &tz->lock, dev->id);
436 free_mem:
437 kfree(dev);
438 return result;
441 EXPORT_SYMBOL(thermal_zone_bind_cooling_device);
444 * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone
445 * @tz: thermal zone device
446 * @trip: indicates which trip point the cooling devices is
447 * associated with in this thermal zone.
448 * @cdev: thermal cooling device
450 * This function is usually called in the thermal zone device .unbind callback.
452 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
453 int trip,
454 struct thermal_cooling_device *cdev)
456 struct thermal_cooling_device_instance *pos, *next;
458 mutex_lock(&tz->lock);
459 list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
460 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
461 list_del(&pos->node);
462 mutex_unlock(&tz->lock);
463 goto unbind;
466 mutex_unlock(&tz->lock);
468 return -ENODEV;
470 unbind:
471 device_remove_file(&tz->device, &pos->attr);
472 sysfs_remove_link(&tz->device.kobj, pos->name);
473 release_idr(&tz->idr, &tz->lock, pos->id);
474 kfree(pos);
475 return 0;
478 EXPORT_SYMBOL(thermal_zone_unbind_cooling_device);
480 static void thermal_release(struct device *dev)
482 struct thermal_zone_device *tz;
483 struct thermal_cooling_device *cdev;
485 if (!strncmp(dev->bus_id, "thermal_zone", sizeof "thermal_zone" - 1)) {
486 tz = to_thermal_zone(dev);
487 kfree(tz);
488 } else {
489 cdev = to_cooling_device(dev);
490 kfree(cdev);
494 static struct class thermal_class = {
495 .name = "thermal",
496 .dev_release = thermal_release,
500 * thermal_cooling_device_register - register a new thermal cooling device
501 * @type: the thermal cooling device type.
502 * @devdata: device private data.
503 * @ops: standard thermal cooling devices callbacks.
505 struct thermal_cooling_device *thermal_cooling_device_register(char *type,
506 void *devdata,
507 struct
508 thermal_cooling_device_ops
509 *ops)
511 struct thermal_cooling_device *cdev;
512 struct thermal_zone_device *pos;
513 int result;
515 if (!type)
516 return ERR_PTR(-EINVAL);
518 if (strlen(type) >= THERMAL_NAME_LENGTH)
519 return ERR_PTR(-EINVAL);
521 if (!ops || !ops->get_max_state || !ops->get_cur_state ||
522 !ops->set_cur_state)
523 return ERR_PTR(-EINVAL);
525 cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
526 if (!cdev)
527 return ERR_PTR(-ENOMEM);
529 result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id);
530 if (result) {
531 kfree(cdev);
532 return ERR_PTR(result);
535 strcpy(cdev->type, type);
536 cdev->ops = ops;
537 cdev->device.class = &thermal_class;
538 cdev->devdata = devdata;
539 sprintf(cdev->device.bus_id, "cooling_device%d", cdev->id);
540 result = device_register(&cdev->device);
541 if (result) {
542 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
543 kfree(cdev);
544 return ERR_PTR(result);
547 /* sys I/F */
548 result = device_create_file(&cdev->device, &dev_attr_cdev_type);
549 if (result)
550 goto unregister;
552 result = device_create_file(&cdev->device, &dev_attr_max_state);
553 if (result)
554 goto unregister;
556 result = device_create_file(&cdev->device, &dev_attr_cur_state);
557 if (result)
558 goto unregister;
560 mutex_lock(&thermal_list_lock);
561 list_add(&cdev->node, &thermal_cdev_list);
562 list_for_each_entry(pos, &thermal_tz_list, node) {
563 if (!pos->ops->bind)
564 continue;
565 result = pos->ops->bind(pos, cdev);
566 if (result)
567 break;
570 mutex_unlock(&thermal_list_lock);
572 if (!result)
573 return cdev;
575 unregister:
576 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
577 device_unregister(&cdev->device);
578 return ERR_PTR(result);
581 EXPORT_SYMBOL(thermal_cooling_device_register);
584 * thermal_cooling_device_unregister - removes the registered thermal cooling device
585 * @cdev: the thermal cooling device to remove.
587 * thermal_cooling_device_unregister() must be called when the device is no
588 * longer needed.
590 void thermal_cooling_device_unregister(struct
591 thermal_cooling_device
592 *cdev)
594 struct thermal_zone_device *tz;
595 struct thermal_cooling_device *pos = NULL;
597 if (!cdev)
598 return;
600 mutex_lock(&thermal_list_lock);
601 list_for_each_entry(pos, &thermal_cdev_list, node)
602 if (pos == cdev)
603 break;
604 if (pos != cdev) {
605 /* thermal cooling device not found */
606 mutex_unlock(&thermal_list_lock);
607 return;
609 list_del(&cdev->node);
610 list_for_each_entry(tz, &thermal_tz_list, node) {
611 if (!tz->ops->unbind)
612 continue;
613 tz->ops->unbind(tz, cdev);
615 mutex_unlock(&thermal_list_lock);
617 device_remove_file(&cdev->device, &dev_attr_cdev_type);
618 device_remove_file(&cdev->device, &dev_attr_max_state);
619 device_remove_file(&cdev->device, &dev_attr_cur_state);
621 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
622 device_unregister(&cdev->device);
623 return;
626 EXPORT_SYMBOL(thermal_cooling_device_unregister);
629 * thermal_zone_device_register - register a new thermal zone device
630 * @type: the thermal zone device type
631 * @trips: the number of trip points the thermal zone support
632 * @devdata: private device data
633 * @ops: standard thermal zone device callbacks
635 * thermal_zone_device_unregister() must be called when the device is no
636 * longer needed.
638 struct thermal_zone_device *thermal_zone_device_register(char *type,
639 int trips,
640 void *devdata, struct
641 thermal_zone_device_ops
642 *ops)
644 struct thermal_zone_device *tz;
645 struct thermal_cooling_device *pos;
646 int result;
647 int count;
649 if (!type)
650 return ERR_PTR(-EINVAL);
652 if (strlen(type) >= THERMAL_NAME_LENGTH)
653 return ERR_PTR(-EINVAL);
655 if (trips > THERMAL_MAX_TRIPS || trips < 0)
656 return ERR_PTR(-EINVAL);
658 if (!ops || !ops->get_temp)
659 return ERR_PTR(-EINVAL);
661 tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
662 if (!tz)
663 return ERR_PTR(-ENOMEM);
665 INIT_LIST_HEAD(&tz->cooling_devices);
666 idr_init(&tz->idr);
667 mutex_init(&tz->lock);
668 result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
669 if (result) {
670 kfree(tz);
671 return ERR_PTR(result);
673 if (tz->id >= MAX_THERMAL_ZONES) {
674 printk(KERN_ERR PREFIX
675 "Too many thermal zones\n");
676 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
677 kfree(tz);
678 return ERR_PTR(-EINVAL);
681 strcpy(tz->type, type);
682 tz->ops = ops;
683 tz->device.class = &thermal_class;
684 tz->devdata = devdata;
685 tz->trips = trips;
686 sprintf(tz->device.bus_id, "thermal_zone%d", tz->id);
687 result = device_register(&tz->device);
688 if (result) {
689 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
690 kfree(tz);
691 return ERR_PTR(result);
694 /* hwmon sys I/F */
695 result = device_create_file(thermal_hwmon,
696 &sensor_attrs[tz->id * 2].dev_attr);
697 if (result)
698 goto unregister;
700 if (trips > 0) {
701 char buf[40];
702 result = tz->ops->get_trip_type(tz, 0, buf);
703 if (result > 0 && !strcmp(buf, "critical\n")) {
704 result = device_create_file(thermal_hwmon,
705 &sensor_attrs[tz->id * 2 + 1].dev_attr);
706 if (result)
707 goto unregister;
711 /* sys I/F */
712 result = device_create_file(&tz->device, &dev_attr_type);
713 if (result)
714 goto unregister;
716 result = device_create_file(&tz->device, &dev_attr_temp);
717 if (result)
718 goto unregister;
720 if (ops->get_mode) {
721 result = device_create_file(&tz->device, &dev_attr_mode);
722 if (result)
723 goto unregister;
726 for (count = 0; count < trips; count++) {
727 TRIP_POINT_ATTR_ADD(&tz->device, count, result);
728 if (result)
729 goto unregister;
732 mutex_lock(&thermal_list_lock);
733 list_add_tail(&tz->node, &thermal_tz_list);
734 if (ops->bind)
735 list_for_each_entry(pos, &thermal_cdev_list, node) {
736 result = ops->bind(tz, pos);
737 if (result)
738 break;
740 mutex_unlock(&thermal_list_lock);
742 if (!result)
743 return tz;
745 unregister:
746 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
747 device_unregister(&tz->device);
748 return ERR_PTR(result);
751 EXPORT_SYMBOL(thermal_zone_device_register);
754 * thermal_device_unregister - removes the registered thermal zone device
755 * @tz: the thermal zone device to remove
757 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
759 struct thermal_cooling_device *cdev;
760 struct thermal_zone_device *pos = NULL;
761 int count;
763 if (!tz)
764 return;
766 mutex_lock(&thermal_list_lock);
767 list_for_each_entry(pos, &thermal_tz_list, node)
768 if (pos == tz)
769 break;
770 if (pos != tz) {
771 /* thermal zone device not found */
772 mutex_unlock(&thermal_list_lock);
773 return;
775 list_del(&tz->node);
776 if (tz->ops->unbind)
777 list_for_each_entry(cdev, &thermal_cdev_list, node)
778 tz->ops->unbind(tz, cdev);
779 mutex_unlock(&thermal_list_lock);
781 device_remove_file(thermal_hwmon,
782 &sensor_attrs[tz->id * 2].dev_attr);
783 if (tz->trips > 0) {
784 char buf[40];
785 if (tz->ops->get_trip_type(tz, 0, buf) > 0)
786 if (!strcmp(buf, "critical\n"))
787 device_remove_file(thermal_hwmon,
788 &sensor_attrs[tz->id * 2 + 1].dev_attr);
791 device_remove_file(&tz->device, &dev_attr_type);
792 device_remove_file(&tz->device, &dev_attr_temp);
793 if (tz->ops->get_mode)
794 device_remove_file(&tz->device, &dev_attr_mode);
796 for (count = 0; count < tz->trips; count++)
797 TRIP_POINT_ATTR_REMOVE(&tz->device, count);
799 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
800 idr_destroy(&tz->idr);
801 mutex_destroy(&tz->lock);
802 device_unregister(&tz->device);
803 return;
806 EXPORT_SYMBOL(thermal_zone_device_unregister);
808 static void thermal_exit(void)
810 if (thermal_hwmon) {
811 device_remove_file(thermal_hwmon, &dev_attr_name);
812 hwmon_device_unregister(thermal_hwmon);
814 class_unregister(&thermal_class);
815 idr_destroy(&thermal_tz_idr);
816 idr_destroy(&thermal_cdev_idr);
817 mutex_destroy(&thermal_idr_lock);
818 mutex_destroy(&thermal_list_lock);
821 static int __init thermal_init(void)
823 int result = 0;
825 result = class_register(&thermal_class);
826 if (result) {
827 idr_destroy(&thermal_tz_idr);
828 idr_destroy(&thermal_cdev_idr);
829 mutex_destroy(&thermal_idr_lock);
830 mutex_destroy(&thermal_list_lock);
833 thermal_hwmon = hwmon_device_register(NULL);
834 if (IS_ERR(thermal_hwmon)) {
835 result = PTR_ERR(thermal_hwmon);
836 thermal_hwmon = NULL;
837 printk(KERN_ERR PREFIX
838 "unable to register hwmon device\n");
839 thermal_exit();
840 return result;
843 result = device_create_file(thermal_hwmon, &dev_attr_name);
845 return result;
848 subsys_initcall(thermal_init);
849 module_exit(thermal_exit);