thermal: fix generic thermal I/F for hwmon
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / drivers / thermal / thermal.c
1 /*
2 * thermal.c - Generic Thermal Management Sysfs support.
3 *
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>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
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.
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
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>
35
36 MODULE_AUTHOR("Zhang Rui");
37 MODULE_DESCRIPTION("Generic thermal management sysfs support");
38 MODULE_LICENSE("GPL");
39
40 #define PREFIX "Thermal: "
41
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;
51 };
52
53 static DEFINE_IDR(thermal_tz_idr);
54 static DEFINE_IDR(thermal_cdev_idr);
55 static DEFINE_MUTEX(thermal_idr_lock);
56
57 static LIST_HEAD(thermal_tz_list);
58 static LIST_HEAD(thermal_cdev_list);
59 static DEFINE_MUTEX(thermal_list_lock);
60
61 static struct device *thermal_hwmon;
62 #define MAX_THERMAL_ZONES 10
63
64 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
65 {
66 int err;
67
68 again:
69 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
70 return -ENOMEM;
71
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;
81
82 *id = *id & MAX_ID_MASK;
83 return 0;
84 }
85
86 static void release_idr(struct idr *idr, struct mutex *lock, int id)
87 {
88 if (lock)
89 mutex_lock(lock);
90 idr_remove(idr, id);
91 if (lock)
92 mutex_unlock(lock);
93 }
94
95 /* hwmon sys I/F*/
96 static ssize_t
97 name_show(struct device *dev, struct device_attribute *attr, char *buf)
98 {
99 return sprintf(buf, "thermal_sys_class\n");
100 }
101
102 static ssize_t
103 temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
104 {
105 struct thermal_zone_device *tz;
106 struct sensor_device_attribute *sensor_attr
107 = to_sensor_dev_attr(attr);
108
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);
112
113 return -ENODEV;
114 }
115
116 static ssize_t
117 temp_crit_show(struct device *dev, struct device_attribute *attr,
118 char *buf)
119 {
120 struct thermal_zone_device *tz;
121 struct sensor_device_attribute *sensor_attr
122 = to_sensor_dev_attr(attr);
123
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);
127
128 return -ENODEV;
129 }
130
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),
153 };
154
155 /* thermal zone sys I/F */
156
157 #define to_thermal_zone(_dev) \
158 container_of(_dev, struct thermal_zone_device, device)
159
160 static ssize_t
161 type_show(struct device *dev, struct device_attribute *attr, char *buf)
162 {
163 struct thermal_zone_device *tz = to_thermal_zone(dev);
164
165 return sprintf(buf, "%s\n", tz->type);
166 }
167
168 static ssize_t
169 temp_show(struct device *dev, struct device_attribute *attr, char *buf)
170 {
171 struct thermal_zone_device *tz = to_thermal_zone(dev);
172
173 if (!tz->ops->get_temp)
174 return -EPERM;
175
176 return tz->ops->get_temp(tz, buf);
177 }
178
179 static ssize_t
180 mode_show(struct device *dev, struct device_attribute *attr, char *buf)
181 {
182 struct thermal_zone_device *tz = to_thermal_zone(dev);
183
184 if (!tz->ops->get_mode)
185 return -EPERM;
186
187 return tz->ops->get_mode(tz, buf);
188 }
189
190 static ssize_t
191 mode_store(struct device *dev, struct device_attribute *attr,
192 const char *buf, size_t count)
193 {
194 struct thermal_zone_device *tz = to_thermal_zone(dev);
195 int result;
196
197 if (!tz->ops->set_mode)
198 return -EPERM;
199
200 result = tz->ops->set_mode(tz, buf);
201 if (result)
202 return result;
203
204 return count;
205 }
206
207 static ssize_t
208 trip_point_type_show(struct device *dev, struct device_attribute *attr,
209 char *buf)
210 {
211 struct thermal_zone_device *tz = to_thermal_zone(dev);
212 int trip;
213
214 if (!tz->ops->get_trip_type)
215 return -EPERM;
216
217 if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
218 return -EINVAL;
219
220 return tz->ops->get_trip_type(tz, trip, buf);
221 }
222
223 static ssize_t
224 trip_point_temp_show(struct device *dev, struct device_attribute *attr,
225 char *buf)
226 {
227 struct thermal_zone_device *tz = to_thermal_zone(dev);
228 int trip;
229
230 if (!tz->ops->get_trip_temp)
231 return -EPERM;
232
233 if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
234 return -EINVAL;
235
236 return tz->ops->get_trip_temp(tz, trip, buf);
237 }
238
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);
242
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),
264 };
265
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)
275
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)
281
282 /* cooling device sys I/F */
283 #define to_cooling_device(_dev) \
284 container_of(_dev, struct thermal_cooling_device, device)
285
286 static ssize_t
287 thermal_cooling_device_type_show(struct device *dev,
288 struct device_attribute *attr, char *buf)
289 {
290 struct thermal_cooling_device *cdev = to_cooling_device(dev);
291
292 return sprintf(buf, "%s\n", cdev->type);
293 }
294
295 static ssize_t
296 thermal_cooling_device_max_state_show(struct device *dev,
297 struct device_attribute *attr, char *buf)
298 {
299 struct thermal_cooling_device *cdev = to_cooling_device(dev);
300
301 return cdev->ops->get_max_state(cdev, buf);
302 }
303
304 static ssize_t
305 thermal_cooling_device_cur_state_show(struct device *dev,
306 struct device_attribute *attr, char *buf)
307 {
308 struct thermal_cooling_device *cdev = to_cooling_device(dev);
309
310 return cdev->ops->get_cur_state(cdev, buf);
311 }
312
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)
317 {
318 struct thermal_cooling_device *cdev = to_cooling_device(dev);
319 int state;
320 int result;
321
322 if (!sscanf(buf, "%d\n", &state))
323 return -EINVAL;
324
325 if (state < 0)
326 return -EINVAL;
327
328 result = cdev->ops->set_cur_state(cdev, state);
329 if (result)
330 return result;
331 return count;
332 }
333
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);
341
342 static ssize_t
343 thermal_cooling_device_trip_point_show(struct device *dev,
344 struct device_attribute *attr, char *buf)
345 {
346 struct thermal_cooling_device_instance *instance;
347
348 instance =
349 container_of(attr, struct thermal_cooling_device_instance, attr);
350
351 if (instance->trip == THERMAL_TRIPS_NONE)
352 return sprintf(buf, "-1\n");
353 else
354 return sprintf(buf, "%d\n", instance->trip);
355 }
356
357 /* Device management */
358
359 /**
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
365 *
366 * This function is usually called in the thermal zone device .bind callback.
367 */
368 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
369 int trip,
370 struct thermal_cooling_device *cdev)
371 {
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;
377
378 if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
379 return -EINVAL;
380
381 list_for_each_entry(pos1, &thermal_tz_list, node) {
382 if (pos1 == tz)
383 break;
384 }
385 list_for_each_entry(pos2, &thermal_cdev_list, node) {
386 if (pos2 == cdev)
387 break;
388 }
389
390 if (tz != pos1 || cdev != pos2)
391 return -EINVAL;
392
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;
403
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;
409
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;
417
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;
423 }
424 if (!result)
425 list_add_tail(&dev->node, &tz->cooling_devices);
426 mutex_unlock(&tz->lock);
427
428 if (!result)
429 return 0;
430
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;
439 }
440
441 EXPORT_SYMBOL(thermal_zone_bind_cooling_device);
442
443 /**
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
449 *
450 * This function is usually called in the thermal zone device .unbind callback.
451 */
452 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
453 int trip,
454 struct thermal_cooling_device *cdev)
455 {
456 struct thermal_cooling_device_instance *pos, *next;
457
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;
464 }
465 }
466 mutex_unlock(&tz->lock);
467
468 return -ENODEV;
469
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;
476 }
477
478 EXPORT_SYMBOL(thermal_zone_unbind_cooling_device);
479
480 static void thermal_release(struct device *dev)
481 {
482 struct thermal_zone_device *tz;
483 struct thermal_cooling_device *cdev;
484
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);
491 }
492 }
493
494 static struct class thermal_class = {
495 .name = "thermal",
496 .dev_release = thermal_release,
497 };
498
499 /**
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.
504 */
505 struct thermal_cooling_device *thermal_cooling_device_register(char *type,
506 void *devdata,
507 struct
508 thermal_cooling_device_ops
509 *ops)
510 {
511 struct thermal_cooling_device *cdev;
512 struct thermal_zone_device *pos;
513 int result;
514
515 if (!type)
516 return ERR_PTR(-EINVAL);
517
518 if (strlen(type) >= THERMAL_NAME_LENGTH)
519 return ERR_PTR(-EINVAL);
520
521 if (!ops || !ops->get_max_state || !ops->get_cur_state ||
522 !ops->set_cur_state)
523 return ERR_PTR(-EINVAL);
524
525 cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
526 if (!cdev)
527 return ERR_PTR(-ENOMEM);
528
529 result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id);
530 if (result) {
531 kfree(cdev);
532 return ERR_PTR(result);
533 }
534
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);
545 }
546
547 /* sys I/F */
548 result = device_create_file(&cdev->device, &dev_attr_cdev_type);
549 if (result)
550 goto unregister;
551
552 result = device_create_file(&cdev->device, &dev_attr_max_state);
553 if (result)
554 goto unregister;
555
556 result = device_create_file(&cdev->device, &dev_attr_cur_state);
557 if (result)
558 goto unregister;
559
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;
568
569 }
570 mutex_unlock(&thermal_list_lock);
571
572 if (!result)
573 return cdev;
574
575 unregister:
576 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
577 device_unregister(&cdev->device);
578 return ERR_PTR(result);
579 }
580
581 EXPORT_SYMBOL(thermal_cooling_device_register);
582
583 /**
584 * thermal_cooling_device_unregister - removes the registered thermal cooling device
585 * @cdev: the thermal cooling device to remove.
586 *
587 * thermal_cooling_device_unregister() must be called when the device is no
588 * longer needed.
589 */
590 void thermal_cooling_device_unregister(struct
591 thermal_cooling_device
592 *cdev)
593 {
594 struct thermal_zone_device *tz;
595 struct thermal_cooling_device *pos = NULL;
596
597 if (!cdev)
598 return;
599
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;
608 }
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);
614 }
615 mutex_unlock(&thermal_list_lock);
616
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);
620
621 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
622 device_unregister(&cdev->device);
623 return;
624 }
625
626 EXPORT_SYMBOL(thermal_cooling_device_unregister);
627
628 /**
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
634 *
635 * thermal_zone_device_unregister() must be called when the device is no
636 * longer needed.
637 */
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)
643 {
644 struct thermal_zone_device *tz;
645 struct thermal_cooling_device *pos;
646 int result;
647 int count;
648
649 if (!type)
650 return ERR_PTR(-EINVAL);
651
652 if (strlen(type) >= THERMAL_NAME_LENGTH)
653 return ERR_PTR(-EINVAL);
654
655 if (trips > THERMAL_MAX_TRIPS || trips < 0)
656 return ERR_PTR(-EINVAL);
657
658 if (!ops || !ops->get_temp)
659 return ERR_PTR(-EINVAL);
660
661 tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
662 if (!tz)
663 return ERR_PTR(-ENOMEM);
664
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);
672 }
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);
679 }
680
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);
692 }
693
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;
699
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;
708 }
709 }
710
711 /* sys I/F */
712 result = device_create_file(&tz->device, &dev_attr_type);
713 if (result)
714 goto unregister;
715
716 result = device_create_file(&tz->device, &dev_attr_temp);
717 if (result)
718 goto unregister;
719
720 if (ops->get_mode) {
721 result = device_create_file(&tz->device, &dev_attr_mode);
722 if (result)
723 goto unregister;
724 }
725
726 for (count = 0; count < trips; count++) {
727 TRIP_POINT_ATTR_ADD(&tz->device, count, result);
728 if (result)
729 goto unregister;
730 }
731
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;
739 }
740 mutex_unlock(&thermal_list_lock);
741
742 if (!result)
743 return tz;
744
745 unregister:
746 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
747 device_unregister(&tz->device);
748 return ERR_PTR(result);
749 }
750
751 EXPORT_SYMBOL(thermal_zone_device_register);
752
753 /**
754 * thermal_device_unregister - removes the registered thermal zone device
755 * @tz: the thermal zone device to remove
756 */
757 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
758 {
759 struct thermal_cooling_device *cdev;
760 struct thermal_zone_device *pos = NULL;
761 int count;
762
763 if (!tz)
764 return;
765
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;
774 }
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);
780
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);
789 }
790
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);
795
796 for (count = 0; count < tz->trips; count++)
797 TRIP_POINT_ATTR_REMOVE(&tz->device, count);
798
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;
804 }
805
806 EXPORT_SYMBOL(thermal_zone_device_unregister);
807
808 static void thermal_exit(void)
809 {
810 if (thermal_hwmon) {
811 device_remove_file(thermal_hwmon, &dev_attr_name);
812 hwmon_device_unregister(thermal_hwmon);
813 }
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);
819 }
820
821 static int __init thermal_init(void)
822 {
823 int result = 0;
824
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);
831 }
832
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;
841 }
842
843 result = device_create_file(thermal_hwmon, &dev_attr_name);
844
845 return result;
846 }
847
848 subsys_initcall(thermal_init);
849 module_exit(thermal_exit);