Commit ff16cab69b6ed621686cf342306785175775152d

Authored by Len Brown
1 parent 76ecb4f2d7

thermal: re-name thermal.c to thermal_sys.c

thermal_sys was already the name of the resulting module,
and it is built from  this one source file.

Signed-off-by: Len Brown <len.brown@intel.com>

Showing 3 changed files with 899 additions and 900 deletions Side-by-side Diff

drivers/thermal/Makefile
... ... @@ -2,6 +2,5 @@
2 2 # Makefile for sensor chip drivers.
3 3 #
4 4  
5   -thermal_sys-objs += thermal.o
6 5 obj-$(CONFIG_THERMAL) += thermal_sys.o
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   -
34   -MODULE_AUTHOR("Zhang Rui");
35   -MODULE_DESCRIPTION("Generic thermal management sysfs support");
36   -MODULE_LICENSE("GPL");
37   -
38   -#define PREFIX "Thermal: "
39   -
40   -struct thermal_cooling_device_instance {
41   - int id;
42   - char name[THERMAL_NAME_LENGTH];
43   - struct thermal_zone_device *tz;
44   - struct thermal_cooling_device *cdev;
45   - int trip;
46   - char attr_name[THERMAL_NAME_LENGTH];
47   - struct device_attribute attr;
48   - struct list_head node;
49   -};
50   -
51   -static DEFINE_IDR(thermal_tz_idr);
52   -static DEFINE_IDR(thermal_cdev_idr);
53   -static DEFINE_MUTEX(thermal_idr_lock);
54   -
55   -static LIST_HEAD(thermal_tz_list);
56   -static LIST_HEAD(thermal_cdev_list);
57   -static DEFINE_MUTEX(thermal_list_lock);
58   -
59   -static int get_idr(struct idr *idr, struct mutex *lock, int *id)
60   -{
61   - int err;
62   -
63   - again:
64   - if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
65   - return -ENOMEM;
66   -
67   - if (lock)
68   - mutex_lock(lock);
69   - err = idr_get_new(idr, NULL, id);
70   - if (lock)
71   - mutex_unlock(lock);
72   - if (unlikely(err == -EAGAIN))
73   - goto again;
74   - else if (unlikely(err))
75   - return err;
76   -
77   - *id = *id & MAX_ID_MASK;
78   - return 0;
79   -}
80   -
81   -static void release_idr(struct idr *idr, struct mutex *lock, int id)
82   -{
83   - if (lock)
84   - mutex_lock(lock);
85   - idr_remove(idr, id);
86   - if (lock)
87   - mutex_unlock(lock);
88   -}
89   -
90   -/* sys I/F for thermal zone */
91   -
92   -#define to_thermal_zone(_dev) \
93   - container_of(_dev, struct thermal_zone_device, device)
94   -
95   -static ssize_t
96   -type_show(struct device *dev, struct device_attribute *attr, char *buf)
97   -{
98   - struct thermal_zone_device *tz = to_thermal_zone(dev);
99   -
100   - return sprintf(buf, "%s\n", tz->type);
101   -}
102   -
103   -static ssize_t
104   -temp_show(struct device *dev, struct device_attribute *attr, char *buf)
105   -{
106   - struct thermal_zone_device *tz = to_thermal_zone(dev);
107   -
108   - if (!tz->ops->get_temp)
109   - return -EPERM;
110   -
111   - return tz->ops->get_temp(tz, buf);
112   -}
113   -
114   -static ssize_t
115   -mode_show(struct device *dev, struct device_attribute *attr, char *buf)
116   -{
117   - struct thermal_zone_device *tz = to_thermal_zone(dev);
118   -
119   - if (!tz->ops->get_mode)
120   - return -EPERM;
121   -
122   - return tz->ops->get_mode(tz, buf);
123   -}
124   -
125   -static ssize_t
126   -mode_store(struct device *dev, struct device_attribute *attr,
127   - const char *buf, size_t count)
128   -{
129   - struct thermal_zone_device *tz = to_thermal_zone(dev);
130   - int result;
131   -
132   - if (!tz->ops->set_mode)
133   - return -EPERM;
134   -
135   - result = tz->ops->set_mode(tz, buf);
136   - if (result)
137   - return result;
138   -
139   - return count;
140   -}
141   -
142   -static ssize_t
143   -trip_point_type_show(struct device *dev, struct device_attribute *attr,
144   - char *buf)
145   -{
146   - struct thermal_zone_device *tz = to_thermal_zone(dev);
147   - int trip;
148   -
149   - if (!tz->ops->get_trip_type)
150   - return -EPERM;
151   -
152   - if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
153   - return -EINVAL;
154   -
155   - return tz->ops->get_trip_type(tz, trip, buf);
156   -}
157   -
158   -static ssize_t
159   -trip_point_temp_show(struct device *dev, struct device_attribute *attr,
160   - char *buf)
161   -{
162   - struct thermal_zone_device *tz = to_thermal_zone(dev);
163   - int trip;
164   -
165   - if (!tz->ops->get_trip_temp)
166   - return -EPERM;
167   -
168   - if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
169   - return -EINVAL;
170   -
171   - return tz->ops->get_trip_temp(tz, trip, buf);
172   -}
173   -
174   -static DEVICE_ATTR(type, 0444, type_show, NULL);
175   -static DEVICE_ATTR(temp, 0444, temp_show, NULL);
176   -static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
177   -
178   -static struct device_attribute trip_point_attrs[] = {
179   - __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
180   - __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
181   - __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
182   - __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
183   - __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
184   - __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
185   - __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
186   - __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
187   - __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
188   - __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
189   - __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
190   - __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
191   - __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
192   - __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
193   - __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
194   - __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
195   - __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
196   - __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
197   - __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
198   - __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
199   - __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
200   - __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
201   - __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
202   - __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
203   -};
204   -
205   -#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \
206   -do { \
207   - result = device_create_file(_dev, \
208   - &trip_point_attrs[_index * 2]); \
209   - if (result) \
210   - break; \
211   - result = device_create_file(_dev, \
212   - &trip_point_attrs[_index * 2 + 1]); \
213   -} while (0)
214   -
215   -#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \
216   -do { \
217   - device_remove_file(_dev, &trip_point_attrs[_index * 2]); \
218   - device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \
219   -} while (0)
220   -
221   -/* sys I/F for cooling device */
222   -#define to_cooling_device(_dev) \
223   - container_of(_dev, struct thermal_cooling_device, device)
224   -
225   -static ssize_t
226   -thermal_cooling_device_type_show(struct device *dev,
227   - struct device_attribute *attr, char *buf)
228   -{
229   - struct thermal_cooling_device *cdev = to_cooling_device(dev);
230   -
231   - return sprintf(buf, "%s\n", cdev->type);
232   -}
233   -
234   -static ssize_t
235   -thermal_cooling_device_max_state_show(struct device *dev,
236   - struct device_attribute *attr, char *buf)
237   -{
238   - struct thermal_cooling_device *cdev = to_cooling_device(dev);
239   -
240   - return cdev->ops->get_max_state(cdev, buf);
241   -}
242   -
243   -static ssize_t
244   -thermal_cooling_device_cur_state_show(struct device *dev,
245   - struct device_attribute *attr, char *buf)
246   -{
247   - struct thermal_cooling_device *cdev = to_cooling_device(dev);
248   -
249   - return cdev->ops->get_cur_state(cdev, buf);
250   -}
251   -
252   -static ssize_t
253   -thermal_cooling_device_cur_state_store(struct device *dev,
254   - struct device_attribute *attr,
255   - const char *buf, size_t count)
256   -{
257   - struct thermal_cooling_device *cdev = to_cooling_device(dev);
258   - int state;
259   - int result;
260   -
261   - if (!sscanf(buf, "%d\n", &state))
262   - return -EINVAL;
263   -
264   - if (state < 0)
265   - return -EINVAL;
266   -
267   - result = cdev->ops->set_cur_state(cdev, state);
268   - if (result)
269   - return result;
270   - return count;
271   -}
272   -
273   -static struct device_attribute dev_attr_cdev_type =
274   -__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
275   -static DEVICE_ATTR(max_state, 0444,
276   - thermal_cooling_device_max_state_show, NULL);
277   -static DEVICE_ATTR(cur_state, 0644,
278   - thermal_cooling_device_cur_state_show,
279   - thermal_cooling_device_cur_state_store);
280   -
281   -static ssize_t
282   -thermal_cooling_device_trip_point_show(struct device *dev,
283   - struct device_attribute *attr, char *buf)
284   -{
285   - struct thermal_cooling_device_instance *instance;
286   -
287   - instance =
288   - container_of(attr, struct thermal_cooling_device_instance, attr);
289   -
290   - if (instance->trip == THERMAL_TRIPS_NONE)
291   - return sprintf(buf, "-1\n");
292   - else
293   - return sprintf(buf, "%d\n", instance->trip);
294   -}
295   -
296   -/* Device management */
297   -
298   -#if defined(CONFIG_HWMON) || \
299   - (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE))
300   -/* hwmon sys I/F */
301   -#include <linux/hwmon.h>
302   -static LIST_HEAD(thermal_hwmon_list);
303   -
304   -static ssize_t
305   -name_show(struct device *dev, struct device_attribute *attr, char *buf)
306   -{
307   - struct thermal_hwmon_device *hwmon = dev->driver_data;
308   - return sprintf(buf, "%s\n", hwmon->type);
309   -}
310   -static DEVICE_ATTR(name, 0444, name_show, NULL);
311   -
312   -static ssize_t
313   -temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
314   -{
315   - struct thermal_hwmon_attr *hwmon_attr
316   - = container_of(attr, struct thermal_hwmon_attr, attr);
317   - struct thermal_zone_device *tz
318   - = container_of(hwmon_attr, struct thermal_zone_device,
319   - temp_input);
320   -
321   - return tz->ops->get_temp(tz, buf);
322   -}
323   -
324   -static ssize_t
325   -temp_crit_show(struct device *dev, struct device_attribute *attr,
326   - char *buf)
327   -{
328   - struct thermal_hwmon_attr *hwmon_attr
329   - = container_of(attr, struct thermal_hwmon_attr, attr);
330   - struct thermal_zone_device *tz
331   - = container_of(hwmon_attr, struct thermal_zone_device,
332   - temp_crit);
333   -
334   - return tz->ops->get_trip_temp(tz, 0, buf);
335   -}
336   -
337   -
338   -static int
339   -thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
340   -{
341   - struct thermal_hwmon_device *hwmon;
342   - int new_hwmon_device = 1;
343   - int result;
344   -
345   - mutex_lock(&thermal_list_lock);
346   - list_for_each_entry(hwmon, &thermal_hwmon_list, node)
347   - if (!strcmp(hwmon->type, tz->type)) {
348   - new_hwmon_device = 0;
349   - mutex_unlock(&thermal_list_lock);
350   - goto register_sys_interface;
351   - }
352   - mutex_unlock(&thermal_list_lock);
353   -
354   - hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL);
355   - if (!hwmon)
356   - return -ENOMEM;
357   -
358   - INIT_LIST_HEAD(&hwmon->tz_list);
359   - strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
360   - hwmon->device = hwmon_device_register(NULL);
361   - if (IS_ERR(hwmon->device)) {
362   - result = PTR_ERR(hwmon->device);
363   - goto free_mem;
364   - }
365   - hwmon->device->driver_data = hwmon;
366   - result = device_create_file(hwmon->device, &dev_attr_name);
367   - if (result)
368   - goto unregister_hwmon_device;
369   -
370   - register_sys_interface:
371   - tz->hwmon = hwmon;
372   - hwmon->count++;
373   -
374   - snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH,
375   - "temp%d_input", hwmon->count);
376   - tz->temp_input.attr.attr.name = tz->temp_input.name;
377   - tz->temp_input.attr.attr.mode = 0444;
378   - tz->temp_input.attr.show = temp_input_show;
379   - result = device_create_file(hwmon->device, &tz->temp_input.attr);
380   - if (result)
381   - goto unregister_hwmon_device;
382   -
383   - if (tz->ops->get_crit_temp) {
384   - unsigned long temperature;
385   - if (!tz->ops->get_crit_temp(tz, &temperature)) {
386   - snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH,
387   - "temp%d_crit", hwmon->count);
388   - tz->temp_crit.attr.attr.name = tz->temp_crit.name;
389   - tz->temp_crit.attr.attr.mode = 0444;
390   - tz->temp_crit.attr.show = temp_crit_show;
391   - result = device_create_file(hwmon->device,
392   - &tz->temp_crit.attr);
393   - if (result)
394   - goto unregister_hwmon_device;
395   - }
396   - }
397   -
398   - mutex_lock(&thermal_list_lock);
399   - if (new_hwmon_device)
400   - list_add_tail(&hwmon->node, &thermal_hwmon_list);
401   - list_add_tail(&tz->hwmon_node, &hwmon->tz_list);
402   - mutex_unlock(&thermal_list_lock);
403   -
404   - return 0;
405   -
406   - unregister_hwmon_device:
407   - device_remove_file(hwmon->device, &tz->temp_crit.attr);
408   - device_remove_file(hwmon->device, &tz->temp_input.attr);
409   - if (new_hwmon_device) {
410   - device_remove_file(hwmon->device, &dev_attr_name);
411   - hwmon_device_unregister(hwmon->device);
412   - }
413   - free_mem:
414   - if (new_hwmon_device)
415   - kfree(hwmon);
416   -
417   - return result;
418   -}
419   -
420   -static void
421   -thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
422   -{
423   - struct thermal_hwmon_device *hwmon = tz->hwmon;
424   -
425   - tz->hwmon = NULL;
426   - device_remove_file(hwmon->device, &tz->temp_input.attr);
427   - device_remove_file(hwmon->device, &tz->temp_crit.attr);
428   -
429   - mutex_lock(&thermal_list_lock);
430   - list_del(&tz->hwmon_node);
431   - if (!list_empty(&hwmon->tz_list)) {
432   - mutex_unlock(&thermal_list_lock);
433   - return;
434   - }
435   - list_del(&hwmon->node);
436   - mutex_unlock(&thermal_list_lock);
437   -
438   - device_remove_file(hwmon->device, &dev_attr_name);
439   - hwmon_device_unregister(hwmon->device);
440   - kfree(hwmon);
441   -}
442   -#else
443   -static int
444   -thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
445   -{
446   - return 0;
447   -}
448   -
449   -static void
450   -thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
451   -{
452   -}
453   -#endif
454   -
455   -
456   -/**
457   - * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
458   - * @tz: thermal zone device
459   - * @trip: indicates which trip point the cooling devices is
460   - * associated with in this thermal zone.
461   - * @cdev: thermal cooling device
462   - *
463   - * This function is usually called in the thermal zone device .bind callback.
464   - */
465   -int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
466   - int trip,
467   - struct thermal_cooling_device *cdev)
468   -{
469   - struct thermal_cooling_device_instance *dev;
470   - struct thermal_cooling_device_instance *pos;
471   - struct thermal_zone_device *pos1;
472   - struct thermal_cooling_device *pos2;
473   - int result;
474   -
475   - if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
476   - return -EINVAL;
477   -
478   - list_for_each_entry(pos1, &thermal_tz_list, node) {
479   - if (pos1 == tz)
480   - break;
481   - }
482   - list_for_each_entry(pos2, &thermal_cdev_list, node) {
483   - if (pos2 == cdev)
484   - break;
485   - }
486   -
487   - if (tz != pos1 || cdev != pos2)
488   - return -EINVAL;
489   -
490   - dev =
491   - kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
492   - if (!dev)
493   - return -ENOMEM;
494   - dev->tz = tz;
495   - dev->cdev = cdev;
496   - dev->trip = trip;
497   - result = get_idr(&tz->idr, &tz->lock, &dev->id);
498   - if (result)
499   - goto free_mem;
500   -
501   - sprintf(dev->name, "cdev%d", dev->id);
502   - result =
503   - sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name);
504   - if (result)
505   - goto release_idr;
506   -
507   - sprintf(dev->attr_name, "cdev%d_trip_point", dev->id);
508   - dev->attr.attr.name = dev->attr_name;
509   - dev->attr.attr.mode = 0444;
510   - dev->attr.show = thermal_cooling_device_trip_point_show;
511   - result = device_create_file(&tz->device, &dev->attr);
512   - if (result)
513   - goto remove_symbol_link;
514   -
515   - mutex_lock(&tz->lock);
516   - list_for_each_entry(pos, &tz->cooling_devices, node)
517   - if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
518   - result = -EEXIST;
519   - break;
520   - }
521   - if (!result)
522   - list_add_tail(&dev->node, &tz->cooling_devices);
523   - mutex_unlock(&tz->lock);
524   -
525   - if (!result)
526   - return 0;
527   -
528   - device_remove_file(&tz->device, &dev->attr);
529   - remove_symbol_link:
530   - sysfs_remove_link(&tz->device.kobj, dev->name);
531   - release_idr:
532   - release_idr(&tz->idr, &tz->lock, dev->id);
533   - free_mem:
534   - kfree(dev);
535   - return result;
536   -}
537   -
538   -EXPORT_SYMBOL(thermal_zone_bind_cooling_device);
539   -
540   -/**
541   - * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone
542   - * @tz: thermal zone device
543   - * @trip: indicates which trip point the cooling devices is
544   - * associated with in this thermal zone.
545   - * @cdev: thermal cooling device
546   - *
547   - * This function is usually called in the thermal zone device .unbind callback.
548   - */
549   -int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
550   - int trip,
551   - struct thermal_cooling_device *cdev)
552   -{
553   - struct thermal_cooling_device_instance *pos, *next;
554   -
555   - mutex_lock(&tz->lock);
556   - list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
557   - if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
558   - list_del(&pos->node);
559   - mutex_unlock(&tz->lock);
560   - goto unbind;
561   - }
562   - }
563   - mutex_unlock(&tz->lock);
564   -
565   - return -ENODEV;
566   -
567   - unbind:
568   - device_remove_file(&tz->device, &pos->attr);
569   - sysfs_remove_link(&tz->device.kobj, pos->name);
570   - release_idr(&tz->idr, &tz->lock, pos->id);
571   - kfree(pos);
572   - return 0;
573   -}
574   -
575   -EXPORT_SYMBOL(thermal_zone_unbind_cooling_device);
576   -
577   -static void thermal_release(struct device *dev)
578   -{
579   - struct thermal_zone_device *tz;
580   - struct thermal_cooling_device *cdev;
581   -
582   - if (!strncmp(dev->bus_id, "thermal_zone", sizeof "thermal_zone" - 1)) {
583   - tz = to_thermal_zone(dev);
584   - kfree(tz);
585   - } else {
586   - cdev = to_cooling_device(dev);
587   - kfree(cdev);
588   - }
589   -}
590   -
591   -static struct class thermal_class = {
592   - .name = "thermal",
593   - .dev_release = thermal_release,
594   -};
595   -
596   -/**
597   - * thermal_cooling_device_register - register a new thermal cooling device
598   - * @type: the thermal cooling device type.
599   - * @devdata: device private data.
600   - * @ops: standard thermal cooling devices callbacks.
601   - */
602   -struct thermal_cooling_device *thermal_cooling_device_register(char *type,
603   - void *devdata,
604   - struct
605   - thermal_cooling_device_ops
606   - *ops)
607   -{
608   - struct thermal_cooling_device *cdev;
609   - struct thermal_zone_device *pos;
610   - int result;
611   -
612   - if (strlen(type) >= THERMAL_NAME_LENGTH)
613   - return ERR_PTR(-EINVAL);
614   -
615   - if (!ops || !ops->get_max_state || !ops->get_cur_state ||
616   - !ops->set_cur_state)
617   - return ERR_PTR(-EINVAL);
618   -
619   - cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
620   - if (!cdev)
621   - return ERR_PTR(-ENOMEM);
622   -
623   - result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id);
624   - if (result) {
625   - kfree(cdev);
626   - return ERR_PTR(result);
627   - }
628   -
629   - strcpy(cdev->type, type);
630   - cdev->ops = ops;
631   - cdev->device.class = &thermal_class;
632   - cdev->devdata = devdata;
633   - sprintf(cdev->device.bus_id, "cooling_device%d", cdev->id);
634   - result = device_register(&cdev->device);
635   - if (result) {
636   - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
637   - kfree(cdev);
638   - return ERR_PTR(result);
639   - }
640   -
641   - /* sys I/F */
642   - if (type) {
643   - result = device_create_file(&cdev->device, &dev_attr_cdev_type);
644   - if (result)
645   - goto unregister;
646   - }
647   -
648   - result = device_create_file(&cdev->device, &dev_attr_max_state);
649   - if (result)
650   - goto unregister;
651   -
652   - result = device_create_file(&cdev->device, &dev_attr_cur_state);
653   - if (result)
654   - goto unregister;
655   -
656   - mutex_lock(&thermal_list_lock);
657   - list_add(&cdev->node, &thermal_cdev_list);
658   - list_for_each_entry(pos, &thermal_tz_list, node) {
659   - if (!pos->ops->bind)
660   - continue;
661   - result = pos->ops->bind(pos, cdev);
662   - if (result)
663   - break;
664   -
665   - }
666   - mutex_unlock(&thermal_list_lock);
667   -
668   - if (!result)
669   - return cdev;
670   -
671   - unregister:
672   - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
673   - device_unregister(&cdev->device);
674   - return ERR_PTR(result);
675   -}
676   -
677   -EXPORT_SYMBOL(thermal_cooling_device_register);
678   -
679   -/**
680   - * thermal_cooling_device_unregister - removes the registered thermal cooling device
681   - * @cdev: the thermal cooling device to remove.
682   - *
683   - * thermal_cooling_device_unregister() must be called when the device is no
684   - * longer needed.
685   - */
686   -void thermal_cooling_device_unregister(struct
687   - thermal_cooling_device
688   - *cdev)
689   -{
690   - struct thermal_zone_device *tz;
691   - struct thermal_cooling_device *pos = NULL;
692   -
693   - if (!cdev)
694   - return;
695   -
696   - mutex_lock(&thermal_list_lock);
697   - list_for_each_entry(pos, &thermal_cdev_list, node)
698   - if (pos == cdev)
699   - break;
700   - if (pos != cdev) {
701   - /* thermal cooling device not found */
702   - mutex_unlock(&thermal_list_lock);
703   - return;
704   - }
705   - list_del(&cdev->node);
706   - list_for_each_entry(tz, &thermal_tz_list, node) {
707   - if (!tz->ops->unbind)
708   - continue;
709   - tz->ops->unbind(tz, cdev);
710   - }
711   - mutex_unlock(&thermal_list_lock);
712   - if (cdev->type[0])
713   - device_remove_file(&cdev->device, &dev_attr_cdev_type);
714   - device_remove_file(&cdev->device, &dev_attr_max_state);
715   - device_remove_file(&cdev->device, &dev_attr_cur_state);
716   -
717   - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
718   - device_unregister(&cdev->device);
719   - return;
720   -}
721   -
722   -EXPORT_SYMBOL(thermal_cooling_device_unregister);
723   -
724   -/**
725   - * thermal_zone_device_register - register a new thermal zone device
726   - * @type: the thermal zone device type
727   - * @trips: the number of trip points the thermal zone support
728   - * @devdata: private device data
729   - * @ops: standard thermal zone device callbacks
730   - *
731   - * thermal_zone_device_unregister() must be called when the device is no
732   - * longer needed.
733   - */
734   -struct thermal_zone_device *thermal_zone_device_register(char *type,
735   - int trips,
736   - void *devdata, struct
737   - thermal_zone_device_ops
738   - *ops)
739   -{
740   - struct thermal_zone_device *tz;
741   - struct thermal_cooling_device *pos;
742   - int result;
743   - int count;
744   -
745   - if (strlen(type) >= THERMAL_NAME_LENGTH)
746   - return ERR_PTR(-EINVAL);
747   -
748   - if (trips > THERMAL_MAX_TRIPS || trips < 0)
749   - return ERR_PTR(-EINVAL);
750   -
751   - if (!ops || !ops->get_temp)
752   - return ERR_PTR(-EINVAL);
753   -
754   - tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
755   - if (!tz)
756   - return ERR_PTR(-ENOMEM);
757   -
758   - INIT_LIST_HEAD(&tz->cooling_devices);
759   - idr_init(&tz->idr);
760   - mutex_init(&tz->lock);
761   - result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
762   - if (result) {
763   - kfree(tz);
764   - return ERR_PTR(result);
765   - }
766   -
767   - strcpy(tz->type, type);
768   - tz->ops = ops;
769   - tz->device.class = &thermal_class;
770   - tz->devdata = devdata;
771   - tz->trips = trips;
772   - sprintf(tz->device.bus_id, "thermal_zone%d", tz->id);
773   - result = device_register(&tz->device);
774   - if (result) {
775   - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
776   - kfree(tz);
777   - return ERR_PTR(result);
778   - }
779   -
780   - /* sys I/F */
781   - if (type) {
782   - result = device_create_file(&tz->device, &dev_attr_type);
783   - if (result)
784   - goto unregister;
785   - }
786   -
787   - result = device_create_file(&tz->device, &dev_attr_temp);
788   - if (result)
789   - goto unregister;
790   -
791   - if (ops->get_mode) {
792   - result = device_create_file(&tz->device, &dev_attr_mode);
793   - if (result)
794   - goto unregister;
795   - }
796   -
797   - for (count = 0; count < trips; count++) {
798   - TRIP_POINT_ATTR_ADD(&tz->device, count, result);
799   - if (result)
800   - goto unregister;
801   - }
802   -
803   - result = thermal_add_hwmon_sysfs(tz);
804   - if (result)
805   - goto unregister;
806   -
807   - mutex_lock(&thermal_list_lock);
808   - list_add_tail(&tz->node, &thermal_tz_list);
809   - if (ops->bind)
810   - list_for_each_entry(pos, &thermal_cdev_list, node) {
811   - result = ops->bind(tz, pos);
812   - if (result)
813   - break;
814   - }
815   - mutex_unlock(&thermal_list_lock);
816   -
817   - if (!result)
818   - return tz;
819   -
820   - unregister:
821   - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
822   - device_unregister(&tz->device);
823   - return ERR_PTR(result);
824   -}
825   -
826   -EXPORT_SYMBOL(thermal_zone_device_register);
827   -
828   -/**
829   - * thermal_device_unregister - removes the registered thermal zone device
830   - * @tz: the thermal zone device to remove
831   - */
832   -void thermal_zone_device_unregister(struct thermal_zone_device *tz)
833   -{
834   - struct thermal_cooling_device *cdev;
835   - struct thermal_zone_device *pos = NULL;
836   - int count;
837   -
838   - if (!tz)
839   - return;
840   -
841   - mutex_lock(&thermal_list_lock);
842   - list_for_each_entry(pos, &thermal_tz_list, node)
843   - if (pos == tz)
844   - break;
845   - if (pos != tz) {
846   - /* thermal zone device not found */
847   - mutex_unlock(&thermal_list_lock);
848   - return;
849   - }
850   - list_del(&tz->node);
851   - if (tz->ops->unbind)
852   - list_for_each_entry(cdev, &thermal_cdev_list, node)
853   - tz->ops->unbind(tz, cdev);
854   - mutex_unlock(&thermal_list_lock);
855   -
856   - if (tz->type[0])
857   - device_remove_file(&tz->device, &dev_attr_type);
858   - device_remove_file(&tz->device, &dev_attr_temp);
859   - if (tz->ops->get_mode)
860   - device_remove_file(&tz->device, &dev_attr_mode);
861   -
862   - for (count = 0; count < tz->trips; count++)
863   - TRIP_POINT_ATTR_REMOVE(&tz->device, count);
864   -
865   - thermal_remove_hwmon_sysfs(tz);
866   - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
867   - idr_destroy(&tz->idr);
868   - mutex_destroy(&tz->lock);
869   - device_unregister(&tz->device);
870   - return;
871   -}
872   -
873   -EXPORT_SYMBOL(thermal_zone_device_unregister);
874   -
875   -static int __init thermal_init(void)
876   -{
877   - int result = 0;
878   -
879   - result = class_register(&thermal_class);
880   - if (result) {
881   - idr_destroy(&thermal_tz_idr);
882   - idr_destroy(&thermal_cdev_idr);
883   - mutex_destroy(&thermal_idr_lock);
884   - mutex_destroy(&thermal_list_lock);
885   - }
886   - return result;
887   -}
888   -
889   -static void __exit thermal_exit(void)
890   -{
891   - class_unregister(&thermal_class);
892   - idr_destroy(&thermal_tz_idr);
893   - idr_destroy(&thermal_cdev_idr);
894   - mutex_destroy(&thermal_idr_lock);
895   - mutex_destroy(&thermal_list_lock);
896   -}
897   -
898   -subsys_initcall(thermal_init);
899   -module_exit(thermal_exit);
drivers/thermal/thermal_sys.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 +
  34 +MODULE_AUTHOR("Zhang Rui");
  35 +MODULE_DESCRIPTION("Generic thermal management sysfs support");
  36 +MODULE_LICENSE("GPL");
  37 +
  38 +#define PREFIX "Thermal: "
  39 +
  40 +struct thermal_cooling_device_instance {
  41 + int id;
  42 + char name[THERMAL_NAME_LENGTH];
  43 + struct thermal_zone_device *tz;
  44 + struct thermal_cooling_device *cdev;
  45 + int trip;
  46 + char attr_name[THERMAL_NAME_LENGTH];
  47 + struct device_attribute attr;
  48 + struct list_head node;
  49 +};
  50 +
  51 +static DEFINE_IDR(thermal_tz_idr);
  52 +static DEFINE_IDR(thermal_cdev_idr);
  53 +static DEFINE_MUTEX(thermal_idr_lock);
  54 +
  55 +static LIST_HEAD(thermal_tz_list);
  56 +static LIST_HEAD(thermal_cdev_list);
  57 +static DEFINE_MUTEX(thermal_list_lock);
  58 +
  59 +static int get_idr(struct idr *idr, struct mutex *lock, int *id)
  60 +{
  61 + int err;
  62 +
  63 + again:
  64 + if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
  65 + return -ENOMEM;
  66 +
  67 + if (lock)
  68 + mutex_lock(lock);
  69 + err = idr_get_new(idr, NULL, id);
  70 + if (lock)
  71 + mutex_unlock(lock);
  72 + if (unlikely(err == -EAGAIN))
  73 + goto again;
  74 + else if (unlikely(err))
  75 + return err;
  76 +
  77 + *id = *id & MAX_ID_MASK;
  78 + return 0;
  79 +}
  80 +
  81 +static void release_idr(struct idr *idr, struct mutex *lock, int id)
  82 +{
  83 + if (lock)
  84 + mutex_lock(lock);
  85 + idr_remove(idr, id);
  86 + if (lock)
  87 + mutex_unlock(lock);
  88 +}
  89 +
  90 +/* sys I/F for thermal zone */
  91 +
  92 +#define to_thermal_zone(_dev) \
  93 + container_of(_dev, struct thermal_zone_device, device)
  94 +
  95 +static ssize_t
  96 +type_show(struct device *dev, struct device_attribute *attr, char *buf)
  97 +{
  98 + struct thermal_zone_device *tz = to_thermal_zone(dev);
  99 +
  100 + return sprintf(buf, "%s\n", tz->type);
  101 +}
  102 +
  103 +static ssize_t
  104 +temp_show(struct device *dev, struct device_attribute *attr, char *buf)
  105 +{
  106 + struct thermal_zone_device *tz = to_thermal_zone(dev);
  107 +
  108 + if (!tz->ops->get_temp)
  109 + return -EPERM;
  110 +
  111 + return tz->ops->get_temp(tz, buf);
  112 +}
  113 +
  114 +static ssize_t
  115 +mode_show(struct device *dev, struct device_attribute *attr, char *buf)
  116 +{
  117 + struct thermal_zone_device *tz = to_thermal_zone(dev);
  118 +
  119 + if (!tz->ops->get_mode)
  120 + return -EPERM;
  121 +
  122 + return tz->ops->get_mode(tz, buf);
  123 +}
  124 +
  125 +static ssize_t
  126 +mode_store(struct device *dev, struct device_attribute *attr,
  127 + const char *buf, size_t count)
  128 +{
  129 + struct thermal_zone_device *tz = to_thermal_zone(dev);
  130 + int result;
  131 +
  132 + if (!tz->ops->set_mode)
  133 + return -EPERM;
  134 +
  135 + result = tz->ops->set_mode(tz, buf);
  136 + if (result)
  137 + return result;
  138 +
  139 + return count;
  140 +}
  141 +
  142 +static ssize_t
  143 +trip_point_type_show(struct device *dev, struct device_attribute *attr,
  144 + char *buf)
  145 +{
  146 + struct thermal_zone_device *tz = to_thermal_zone(dev);
  147 + int trip;
  148 +
  149 + if (!tz->ops->get_trip_type)
  150 + return -EPERM;
  151 +
  152 + if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
  153 + return -EINVAL;
  154 +
  155 + return tz->ops->get_trip_type(tz, trip, buf);
  156 +}
  157 +
  158 +static ssize_t
  159 +trip_point_temp_show(struct device *dev, struct device_attribute *attr,
  160 + char *buf)
  161 +{
  162 + struct thermal_zone_device *tz = to_thermal_zone(dev);
  163 + int trip;
  164 +
  165 + if (!tz->ops->get_trip_temp)
  166 + return -EPERM;
  167 +
  168 + if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
  169 + return -EINVAL;
  170 +
  171 + return tz->ops->get_trip_temp(tz, trip, buf);
  172 +}
  173 +
  174 +static DEVICE_ATTR(type, 0444, type_show, NULL);
  175 +static DEVICE_ATTR(temp, 0444, temp_show, NULL);
  176 +static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
  177 +
  178 +static struct device_attribute trip_point_attrs[] = {
  179 + __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
  180 + __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
  181 + __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
  182 + __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
  183 + __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
  184 + __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
  185 + __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
  186 + __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
  187 + __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
  188 + __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
  189 + __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
  190 + __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
  191 + __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
  192 + __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
  193 + __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
  194 + __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
  195 + __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
  196 + __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
  197 + __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
  198 + __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
  199 + __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
  200 + __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
  201 + __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
  202 + __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
  203 +};
  204 +
  205 +#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \
  206 +do { \
  207 + result = device_create_file(_dev, \
  208 + &trip_point_attrs[_index * 2]); \
  209 + if (result) \
  210 + break; \
  211 + result = device_create_file(_dev, \
  212 + &trip_point_attrs[_index * 2 + 1]); \
  213 +} while (0)
  214 +
  215 +#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \
  216 +do { \
  217 + device_remove_file(_dev, &trip_point_attrs[_index * 2]); \
  218 + device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \
  219 +} while (0)
  220 +
  221 +/* sys I/F for cooling device */
  222 +#define to_cooling_device(_dev) \
  223 + container_of(_dev, struct thermal_cooling_device, device)
  224 +
  225 +static ssize_t
  226 +thermal_cooling_device_type_show(struct device *dev,
  227 + struct device_attribute *attr, char *buf)
  228 +{
  229 + struct thermal_cooling_device *cdev = to_cooling_device(dev);
  230 +
  231 + return sprintf(buf, "%s\n", cdev->type);
  232 +}
  233 +
  234 +static ssize_t
  235 +thermal_cooling_device_max_state_show(struct device *dev,
  236 + struct device_attribute *attr, char *buf)
  237 +{
  238 + struct thermal_cooling_device *cdev = to_cooling_device(dev);
  239 +
  240 + return cdev->ops->get_max_state(cdev, buf);
  241 +}
  242 +
  243 +static ssize_t
  244 +thermal_cooling_device_cur_state_show(struct device *dev,
  245 + struct device_attribute *attr, char *buf)
  246 +{
  247 + struct thermal_cooling_device *cdev = to_cooling_device(dev);
  248 +
  249 + return cdev->ops->get_cur_state(cdev, buf);
  250 +}
  251 +
  252 +static ssize_t
  253 +thermal_cooling_device_cur_state_store(struct device *dev,
  254 + struct device_attribute *attr,
  255 + const char *buf, size_t count)
  256 +{
  257 + struct thermal_cooling_device *cdev = to_cooling_device(dev);
  258 + int state;
  259 + int result;
  260 +
  261 + if (!sscanf(buf, "%d\n", &state))
  262 + return -EINVAL;
  263 +
  264 + if (state < 0)
  265 + return -EINVAL;
  266 +
  267 + result = cdev->ops->set_cur_state(cdev, state);
  268 + if (result)
  269 + return result;
  270 + return count;
  271 +}
  272 +
  273 +static struct device_attribute dev_attr_cdev_type =
  274 +__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
  275 +static DEVICE_ATTR(max_state, 0444,
  276 + thermal_cooling_device_max_state_show, NULL);
  277 +static DEVICE_ATTR(cur_state, 0644,
  278 + thermal_cooling_device_cur_state_show,
  279 + thermal_cooling_device_cur_state_store);
  280 +
  281 +static ssize_t
  282 +thermal_cooling_device_trip_point_show(struct device *dev,
  283 + struct device_attribute *attr, char *buf)
  284 +{
  285 + struct thermal_cooling_device_instance *instance;
  286 +
  287 + instance =
  288 + container_of(attr, struct thermal_cooling_device_instance, attr);
  289 +
  290 + if (instance->trip == THERMAL_TRIPS_NONE)
  291 + return sprintf(buf, "-1\n");
  292 + else
  293 + return sprintf(buf, "%d\n", instance->trip);
  294 +}
  295 +
  296 +/* Device management */
  297 +
  298 +#if defined(CONFIG_HWMON) || \
  299 + (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE))
  300 +/* hwmon sys I/F */
  301 +#include <linux/hwmon.h>
  302 +static LIST_HEAD(thermal_hwmon_list);
  303 +
  304 +static ssize_t
  305 +name_show(struct device *dev, struct device_attribute *attr, char *buf)
  306 +{
  307 + struct thermal_hwmon_device *hwmon = dev->driver_data;
  308 + return sprintf(buf, "%s\n", hwmon->type);
  309 +}
  310 +static DEVICE_ATTR(name, 0444, name_show, NULL);
  311 +
  312 +static ssize_t
  313 +temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
  314 +{
  315 + struct thermal_hwmon_attr *hwmon_attr
  316 + = container_of(attr, struct thermal_hwmon_attr, attr);
  317 + struct thermal_zone_device *tz
  318 + = container_of(hwmon_attr, struct thermal_zone_device,
  319 + temp_input);
  320 +
  321 + return tz->ops->get_temp(tz, buf);
  322 +}
  323 +
  324 +static ssize_t
  325 +temp_crit_show(struct device *dev, struct device_attribute *attr,
  326 + char *buf)
  327 +{
  328 + struct thermal_hwmon_attr *hwmon_attr
  329 + = container_of(attr, struct thermal_hwmon_attr, attr);
  330 + struct thermal_zone_device *tz
  331 + = container_of(hwmon_attr, struct thermal_zone_device,
  332 + temp_crit);
  333 +
  334 + return tz->ops->get_trip_temp(tz, 0, buf);
  335 +}
  336 +
  337 +
  338 +static int
  339 +thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
  340 +{
  341 + struct thermal_hwmon_device *hwmon;
  342 + int new_hwmon_device = 1;
  343 + int result;
  344 +
  345 + mutex_lock(&thermal_list_lock);
  346 + list_for_each_entry(hwmon, &thermal_hwmon_list, node)
  347 + if (!strcmp(hwmon->type, tz->type)) {
  348 + new_hwmon_device = 0;
  349 + mutex_unlock(&thermal_list_lock);
  350 + goto register_sys_interface;
  351 + }
  352 + mutex_unlock(&thermal_list_lock);
  353 +
  354 + hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL);
  355 + if (!hwmon)
  356 + return -ENOMEM;
  357 +
  358 + INIT_LIST_HEAD(&hwmon->tz_list);
  359 + strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
  360 + hwmon->device = hwmon_device_register(NULL);
  361 + if (IS_ERR(hwmon->device)) {
  362 + result = PTR_ERR(hwmon->device);
  363 + goto free_mem;
  364 + }
  365 + hwmon->device->driver_data = hwmon;
  366 + result = device_create_file(hwmon->device, &dev_attr_name);
  367 + if (result)
  368 + goto unregister_hwmon_device;
  369 +
  370 + register_sys_interface:
  371 + tz->hwmon = hwmon;
  372 + hwmon->count++;
  373 +
  374 + snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH,
  375 + "temp%d_input", hwmon->count);
  376 + tz->temp_input.attr.attr.name = tz->temp_input.name;
  377 + tz->temp_input.attr.attr.mode = 0444;
  378 + tz->temp_input.attr.show = temp_input_show;
  379 + result = device_create_file(hwmon->device, &tz->temp_input.attr);
  380 + if (result)
  381 + goto unregister_hwmon_device;
  382 +
  383 + if (tz->ops->get_crit_temp) {
  384 + unsigned long temperature;
  385 + if (!tz->ops->get_crit_temp(tz, &temperature)) {
  386 + snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH,
  387 + "temp%d_crit", hwmon->count);
  388 + tz->temp_crit.attr.attr.name = tz->temp_crit.name;
  389 + tz->temp_crit.attr.attr.mode = 0444;
  390 + tz->temp_crit.attr.show = temp_crit_show;
  391 + result = device_create_file(hwmon->device,
  392 + &tz->temp_crit.attr);
  393 + if (result)
  394 + goto unregister_hwmon_device;
  395 + }
  396 + }
  397 +
  398 + mutex_lock(&thermal_list_lock);
  399 + if (new_hwmon_device)
  400 + list_add_tail(&hwmon->node, &thermal_hwmon_list);
  401 + list_add_tail(&tz->hwmon_node, &hwmon->tz_list);
  402 + mutex_unlock(&thermal_list_lock);
  403 +
  404 + return 0;
  405 +
  406 + unregister_hwmon_device:
  407 + device_remove_file(hwmon->device, &tz->temp_crit.attr);
  408 + device_remove_file(hwmon->device, &tz->temp_input.attr);
  409 + if (new_hwmon_device) {
  410 + device_remove_file(hwmon->device, &dev_attr_name);
  411 + hwmon_device_unregister(hwmon->device);
  412 + }
  413 + free_mem:
  414 + if (new_hwmon_device)
  415 + kfree(hwmon);
  416 +
  417 + return result;
  418 +}
  419 +
  420 +static void
  421 +thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
  422 +{
  423 + struct thermal_hwmon_device *hwmon = tz->hwmon;
  424 +
  425 + tz->hwmon = NULL;
  426 + device_remove_file(hwmon->device, &tz->temp_input.attr);
  427 + device_remove_file(hwmon->device, &tz->temp_crit.attr);
  428 +
  429 + mutex_lock(&thermal_list_lock);
  430 + list_del(&tz->hwmon_node);
  431 + if (!list_empty(&hwmon->tz_list)) {
  432 + mutex_unlock(&thermal_list_lock);
  433 + return;
  434 + }
  435 + list_del(&hwmon->node);
  436 + mutex_unlock(&thermal_list_lock);
  437 +
  438 + device_remove_file(hwmon->device, &dev_attr_name);
  439 + hwmon_device_unregister(hwmon->device);
  440 + kfree(hwmon);
  441 +}
  442 +#else
  443 +static int
  444 +thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
  445 +{
  446 + return 0;
  447 +}
  448 +
  449 +static void
  450 +thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
  451 +{
  452 +}
  453 +#endif
  454 +
  455 +
  456 +/**
  457 + * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
  458 + * @tz: thermal zone device
  459 + * @trip: indicates which trip point the cooling devices is
  460 + * associated with in this thermal zone.
  461 + * @cdev: thermal cooling device
  462 + *
  463 + * This function is usually called in the thermal zone device .bind callback.
  464 + */
  465 +int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
  466 + int trip,
  467 + struct thermal_cooling_device *cdev)
  468 +{
  469 + struct thermal_cooling_device_instance *dev;
  470 + struct thermal_cooling_device_instance *pos;
  471 + struct thermal_zone_device *pos1;
  472 + struct thermal_cooling_device *pos2;
  473 + int result;
  474 +
  475 + if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
  476 + return -EINVAL;
  477 +
  478 + list_for_each_entry(pos1, &thermal_tz_list, node) {
  479 + if (pos1 == tz)
  480 + break;
  481 + }
  482 + list_for_each_entry(pos2, &thermal_cdev_list, node) {
  483 + if (pos2 == cdev)
  484 + break;
  485 + }
  486 +
  487 + if (tz != pos1 || cdev != pos2)
  488 + return -EINVAL;
  489 +
  490 + dev =
  491 + kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
  492 + if (!dev)
  493 + return -ENOMEM;
  494 + dev->tz = tz;
  495 + dev->cdev = cdev;
  496 + dev->trip = trip;
  497 + result = get_idr(&tz->idr, &tz->lock, &dev->id);
  498 + if (result)
  499 + goto free_mem;
  500 +
  501 + sprintf(dev->name, "cdev%d", dev->id);
  502 + result =
  503 + sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name);
  504 + if (result)
  505 + goto release_idr;
  506 +
  507 + sprintf(dev->attr_name, "cdev%d_trip_point", dev->id);
  508 + dev->attr.attr.name = dev->attr_name;
  509 + dev->attr.attr.mode = 0444;
  510 + dev->attr.show = thermal_cooling_device_trip_point_show;
  511 + result = device_create_file(&tz->device, &dev->attr);
  512 + if (result)
  513 + goto remove_symbol_link;
  514 +
  515 + mutex_lock(&tz->lock);
  516 + list_for_each_entry(pos, &tz->cooling_devices, node)
  517 + if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
  518 + result = -EEXIST;
  519 + break;
  520 + }
  521 + if (!result)
  522 + list_add_tail(&dev->node, &tz->cooling_devices);
  523 + mutex_unlock(&tz->lock);
  524 +
  525 + if (!result)
  526 + return 0;
  527 +
  528 + device_remove_file(&tz->device, &dev->attr);
  529 + remove_symbol_link:
  530 + sysfs_remove_link(&tz->device.kobj, dev->name);
  531 + release_idr:
  532 + release_idr(&tz->idr, &tz->lock, dev->id);
  533 + free_mem:
  534 + kfree(dev);
  535 + return result;
  536 +}
  537 +
  538 +EXPORT_SYMBOL(thermal_zone_bind_cooling_device);
  539 +
  540 +/**
  541 + * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone
  542 + * @tz: thermal zone device
  543 + * @trip: indicates which trip point the cooling devices is
  544 + * associated with in this thermal zone.
  545 + * @cdev: thermal cooling device
  546 + *
  547 + * This function is usually called in the thermal zone device .unbind callback.
  548 + */
  549 +int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
  550 + int trip,
  551 + struct thermal_cooling_device *cdev)
  552 +{
  553 + struct thermal_cooling_device_instance *pos, *next;
  554 +
  555 + mutex_lock(&tz->lock);
  556 + list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
  557 + if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
  558 + list_del(&pos->node);
  559 + mutex_unlock(&tz->lock);
  560 + goto unbind;
  561 + }
  562 + }
  563 + mutex_unlock(&tz->lock);
  564 +
  565 + return -ENODEV;
  566 +
  567 + unbind:
  568 + device_remove_file(&tz->device, &pos->attr);
  569 + sysfs_remove_link(&tz->device.kobj, pos->name);
  570 + release_idr(&tz->idr, &tz->lock, pos->id);
  571 + kfree(pos);
  572 + return 0;
  573 +}
  574 +
  575 +EXPORT_SYMBOL(thermal_zone_unbind_cooling_device);
  576 +
  577 +static void thermal_release(struct device *dev)
  578 +{
  579 + struct thermal_zone_device *tz;
  580 + struct thermal_cooling_device *cdev;
  581 +
  582 + if (!strncmp(dev->bus_id, "thermal_zone", sizeof "thermal_zone" - 1)) {
  583 + tz = to_thermal_zone(dev);
  584 + kfree(tz);
  585 + } else {
  586 + cdev = to_cooling_device(dev);
  587 + kfree(cdev);
  588 + }
  589 +}
  590 +
  591 +static struct class thermal_class = {
  592 + .name = "thermal",
  593 + .dev_release = thermal_release,
  594 +};
  595 +
  596 +/**
  597 + * thermal_cooling_device_register - register a new thermal cooling device
  598 + * @type: the thermal cooling device type.
  599 + * @devdata: device private data.
  600 + * @ops: standard thermal cooling devices callbacks.
  601 + */
  602 +struct thermal_cooling_device *thermal_cooling_device_register(char *type,
  603 + void *devdata,
  604 + struct
  605 + thermal_cooling_device_ops
  606 + *ops)
  607 +{
  608 + struct thermal_cooling_device *cdev;
  609 + struct thermal_zone_device *pos;
  610 + int result;
  611 +
  612 + if (strlen(type) >= THERMAL_NAME_LENGTH)
  613 + return ERR_PTR(-EINVAL);
  614 +
  615 + if (!ops || !ops->get_max_state || !ops->get_cur_state ||
  616 + !ops->set_cur_state)
  617 + return ERR_PTR(-EINVAL);
  618 +
  619 + cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
  620 + if (!cdev)
  621 + return ERR_PTR(-ENOMEM);
  622 +
  623 + result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id);
  624 + if (result) {
  625 + kfree(cdev);
  626 + return ERR_PTR(result);
  627 + }
  628 +
  629 + strcpy(cdev->type, type);
  630 + cdev->ops = ops;
  631 + cdev->device.class = &thermal_class;
  632 + cdev->devdata = devdata;
  633 + sprintf(cdev->device.bus_id, "cooling_device%d", cdev->id);
  634 + result = device_register(&cdev->device);
  635 + if (result) {
  636 + release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
  637 + kfree(cdev);
  638 + return ERR_PTR(result);
  639 + }
  640 +
  641 + /* sys I/F */
  642 + if (type) {
  643 + result = device_create_file(&cdev->device, &dev_attr_cdev_type);
  644 + if (result)
  645 + goto unregister;
  646 + }
  647 +
  648 + result = device_create_file(&cdev->device, &dev_attr_max_state);
  649 + if (result)
  650 + goto unregister;
  651 +
  652 + result = device_create_file(&cdev->device, &dev_attr_cur_state);
  653 + if (result)
  654 + goto unregister;
  655 +
  656 + mutex_lock(&thermal_list_lock);
  657 + list_add(&cdev->node, &thermal_cdev_list);
  658 + list_for_each_entry(pos, &thermal_tz_list, node) {
  659 + if (!pos->ops->bind)
  660 + continue;
  661 + result = pos->ops->bind(pos, cdev);
  662 + if (result)
  663 + break;
  664 +
  665 + }
  666 + mutex_unlock(&thermal_list_lock);
  667 +
  668 + if (!result)
  669 + return cdev;
  670 +
  671 + unregister:
  672 + release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
  673 + device_unregister(&cdev->device);
  674 + return ERR_PTR(result);
  675 +}
  676 +
  677 +EXPORT_SYMBOL(thermal_cooling_device_register);
  678 +
  679 +/**
  680 + * thermal_cooling_device_unregister - removes the registered thermal cooling device
  681 + * @cdev: the thermal cooling device to remove.
  682 + *
  683 + * thermal_cooling_device_unregister() must be called when the device is no
  684 + * longer needed.
  685 + */
  686 +void thermal_cooling_device_unregister(struct
  687 + thermal_cooling_device
  688 + *cdev)
  689 +{
  690 + struct thermal_zone_device *tz;
  691 + struct thermal_cooling_device *pos = NULL;
  692 +
  693 + if (!cdev)
  694 + return;
  695 +
  696 + mutex_lock(&thermal_list_lock);
  697 + list_for_each_entry(pos, &thermal_cdev_list, node)
  698 + if (pos == cdev)
  699 + break;
  700 + if (pos != cdev) {
  701 + /* thermal cooling device not found */
  702 + mutex_unlock(&thermal_list_lock);
  703 + return;
  704 + }
  705 + list_del(&cdev->node);
  706 + list_for_each_entry(tz, &thermal_tz_list, node) {
  707 + if (!tz->ops->unbind)
  708 + continue;
  709 + tz->ops->unbind(tz, cdev);
  710 + }
  711 + mutex_unlock(&thermal_list_lock);
  712 + if (cdev->type[0])
  713 + device_remove_file(&cdev->device, &dev_attr_cdev_type);
  714 + device_remove_file(&cdev->device, &dev_attr_max_state);
  715 + device_remove_file(&cdev->device, &dev_attr_cur_state);
  716 +
  717 + release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
  718 + device_unregister(&cdev->device);
  719 + return;
  720 +}
  721 +
  722 +EXPORT_SYMBOL(thermal_cooling_device_unregister);
  723 +
  724 +/**
  725 + * thermal_zone_device_register - register a new thermal zone device
  726 + * @type: the thermal zone device type
  727 + * @trips: the number of trip points the thermal zone support
  728 + * @devdata: private device data
  729 + * @ops: standard thermal zone device callbacks
  730 + *
  731 + * thermal_zone_device_unregister() must be called when the device is no
  732 + * longer needed.
  733 + */
  734 +struct thermal_zone_device *thermal_zone_device_register(char *type,
  735 + int trips,
  736 + void *devdata, struct
  737 + thermal_zone_device_ops
  738 + *ops)
  739 +{
  740 + struct thermal_zone_device *tz;
  741 + struct thermal_cooling_device *pos;
  742 + int result;
  743 + int count;
  744 +
  745 + if (strlen(type) >= THERMAL_NAME_LENGTH)
  746 + return ERR_PTR(-EINVAL);
  747 +
  748 + if (trips > THERMAL_MAX_TRIPS || trips < 0)
  749 + return ERR_PTR(-EINVAL);
  750 +
  751 + if (!ops || !ops->get_temp)
  752 + return ERR_PTR(-EINVAL);
  753 +
  754 + tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
  755 + if (!tz)
  756 + return ERR_PTR(-ENOMEM);
  757 +
  758 + INIT_LIST_HEAD(&tz->cooling_devices);
  759 + idr_init(&tz->idr);
  760 + mutex_init(&tz->lock);
  761 + result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
  762 + if (result) {
  763 + kfree(tz);
  764 + return ERR_PTR(result);
  765 + }
  766 +
  767 + strcpy(tz->type, type);
  768 + tz->ops = ops;
  769 + tz->device.class = &thermal_class;
  770 + tz->devdata = devdata;
  771 + tz->trips = trips;
  772 + sprintf(tz->device.bus_id, "thermal_zone%d", tz->id);
  773 + result = device_register(&tz->device);
  774 + if (result) {
  775 + release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
  776 + kfree(tz);
  777 + return ERR_PTR(result);
  778 + }
  779 +
  780 + /* sys I/F */
  781 + if (type) {
  782 + result = device_create_file(&tz->device, &dev_attr_type);
  783 + if (result)
  784 + goto unregister;
  785 + }
  786 +
  787 + result = device_create_file(&tz->device, &dev_attr_temp);
  788 + if (result)
  789 + goto unregister;
  790 +
  791 + if (ops->get_mode) {
  792 + result = device_create_file(&tz->device, &dev_attr_mode);
  793 + if (result)
  794 + goto unregister;
  795 + }
  796 +
  797 + for (count = 0; count < trips; count++) {
  798 + TRIP_POINT_ATTR_ADD(&tz->device, count, result);
  799 + if (result)
  800 + goto unregister;
  801 + }
  802 +
  803 + result = thermal_add_hwmon_sysfs(tz);
  804 + if (result)
  805 + goto unregister;
  806 +
  807 + mutex_lock(&thermal_list_lock);
  808 + list_add_tail(&tz->node, &thermal_tz_list);
  809 + if (ops->bind)
  810 + list_for_each_entry(pos, &thermal_cdev_list, node) {
  811 + result = ops->bind(tz, pos);
  812 + if (result)
  813 + break;
  814 + }
  815 + mutex_unlock(&thermal_list_lock);
  816 +
  817 + if (!result)
  818 + return tz;
  819 +
  820 + unregister:
  821 + release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
  822 + device_unregister(&tz->device);
  823 + return ERR_PTR(result);
  824 +}
  825 +
  826 +EXPORT_SYMBOL(thermal_zone_device_register);
  827 +
  828 +/**
  829 + * thermal_device_unregister - removes the registered thermal zone device
  830 + * @tz: the thermal zone device to remove
  831 + */
  832 +void thermal_zone_device_unregister(struct thermal_zone_device *tz)
  833 +{
  834 + struct thermal_cooling_device *cdev;
  835 + struct thermal_zone_device *pos = NULL;
  836 + int count;
  837 +
  838 + if (!tz)
  839 + return;
  840 +
  841 + mutex_lock(&thermal_list_lock);
  842 + list_for_each_entry(pos, &thermal_tz_list, node)
  843 + if (pos == tz)
  844 + break;
  845 + if (pos != tz) {
  846 + /* thermal zone device not found */
  847 + mutex_unlock(&thermal_list_lock);
  848 + return;
  849 + }
  850 + list_del(&tz->node);
  851 + if (tz->ops->unbind)
  852 + list_for_each_entry(cdev, &thermal_cdev_list, node)
  853 + tz->ops->unbind(tz, cdev);
  854 + mutex_unlock(&thermal_list_lock);
  855 +
  856 + if (tz->type[0])
  857 + device_remove_file(&tz->device, &dev_attr_type);
  858 + device_remove_file(&tz->device, &dev_attr_temp);
  859 + if (tz->ops->get_mode)
  860 + device_remove_file(&tz->device, &dev_attr_mode);
  861 +
  862 + for (count = 0; count < tz->trips; count++)
  863 + TRIP_POINT_ATTR_REMOVE(&tz->device, count);
  864 +
  865 + thermal_remove_hwmon_sysfs(tz);
  866 + release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
  867 + idr_destroy(&tz->idr);
  868 + mutex_destroy(&tz->lock);
  869 + device_unregister(&tz->device);
  870 + return;
  871 +}
  872 +
  873 +EXPORT_SYMBOL(thermal_zone_device_unregister);
  874 +
  875 +static int __init thermal_init(void)
  876 +{
  877 + int result = 0;
  878 +
  879 + result = class_register(&thermal_class);
  880 + if (result) {
  881 + idr_destroy(&thermal_tz_idr);
  882 + idr_destroy(&thermal_cdev_idr);
  883 + mutex_destroy(&thermal_idr_lock);
  884 + mutex_destroy(&thermal_list_lock);
  885 + }
  886 + return result;
  887 +}
  888 +
  889 +static void __exit thermal_exit(void)
  890 +{
  891 + class_unregister(&thermal_class);
  892 + idr_destroy(&thermal_tz_idr);
  893 + idr_destroy(&thermal_cdev_idr);
  894 + mutex_destroy(&thermal_idr_lock);
  895 + mutex_destroy(&thermal_list_lock);
  896 +}
  897 +
  898 +subsys_initcall(thermal_init);
  899 +module_exit(thermal_exit);