aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal/thermal.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-03-13 16:13:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-03-13 16:13:47 -0400
commit96e31022a1b6e7cb173cbb3dce1fde7ba548860a (patch)
treeb50b310790cb79340a5fb67de0485a08dcf31426 /drivers/thermal/thermal.c
parentf2005e1777614b65d1970924ca1b61e4caccb0d3 (diff)
parent29ea5171cbd08a7ef37e543cbf02447033f0e289 (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (32 commits) ACPI: thermal: show temperature in millidegree Celsius thermal: fix generic thermal I/F for hwmon acer-wmi: build depends on i8042 documentation: Move power-related files to Documentation/power/ ACPI: buffer array too short in drivers/acpi/system.c acer-wmi: Add DMI quirk for mail LED support on Acer Aspire 3610/ 5610 acer-wmi: Fix DSDT path in documentation acer-wmi: Make device detection error messages more descriptive laptops: move laptop-mode.txt to Documentation/laptops/ ACPICA: Warn if packages with invalid references are evaluated ACPI: add _PRT quirks to work around broken firmware Hibernation: Fix mark_nosave_pages() ACPI: Ignore _BQC object when registering backlight device ACPI: WMI: Clean up handling of spec violating data blocks acer-wmi: Don't warn if mail LED cannot be detected acer-wmi: Rename mail LED correctly & remove hardcoded colour ACPI: use ACPI_DEBUG_PRINT instead of printk in acpi_processor_hotplug_notify() ACPI: button: make real parent for input devices in device tree toshiba_acpi: Enable autoloading ACPI: EC: Handle IRQ storm on Acer laptops ...
Diffstat (limited to 'drivers/thermal/thermal.c')
-rw-r--r--drivers/thermal/thermal.c169
1 files changed, 143 insertions, 26 deletions
diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c
index 8b86e53ccf7a..41bd4c805ace 100644
--- a/drivers/thermal/thermal.c
+++ b/drivers/thermal/thermal.c
@@ -30,8 +30,10 @@
30#include <linux/idr.h> 30#include <linux/idr.h>
31#include <linux/thermal.h> 31#include <linux/thermal.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <linux/hwmon.h>
34#include <linux/hwmon-sysfs.h>
33 35
34MODULE_AUTHOR("Zhang Rui") 36MODULE_AUTHOR("Zhang Rui");
35MODULE_DESCRIPTION("Generic thermal management sysfs support"); 37MODULE_DESCRIPTION("Generic thermal management sysfs support");
36MODULE_LICENSE("GPL"); 38MODULE_LICENSE("GPL");
37 39
@@ -56,6 +58,9 @@ static LIST_HEAD(thermal_tz_list);
56static LIST_HEAD(thermal_cdev_list); 58static LIST_HEAD(thermal_cdev_list);
57static DEFINE_MUTEX(thermal_list_lock); 59static DEFINE_MUTEX(thermal_list_lock);
58 60
61static struct device *thermal_hwmon;
62#define MAX_THERMAL_ZONES 10
63
59static int get_idr(struct idr *idr, struct mutex *lock, int *id) 64static int get_idr(struct idr *idr, struct mutex *lock, int *id)
60{ 65{
61 int err; 66 int err;
@@ -87,7 +92,67 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
87 mutex_unlock(lock); 92 mutex_unlock(lock);
88} 93}
89 94
90/* sys I/F for thermal zone */ 95/* hwmon sys I/F*/
96static ssize_t
97name_show(struct device *dev, struct device_attribute *attr, char *buf)
98{
99 return sprintf(buf, "thermal_sys_class\n");
100}
101
102static ssize_t
103temp_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
116static ssize_t
117temp_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
131static DEVICE_ATTR(name, 0444, name_show, NULL);
132static 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 */
91 156
92#define to_thermal_zone(_dev) \ 157#define to_thermal_zone(_dev) \
93 container_of(_dev, struct thermal_zone_device, device) 158 container_of(_dev, struct thermal_zone_device, device)
@@ -214,7 +279,7 @@ do { \
214 device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \ 279 device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \
215} while (0) 280} while (0)
216 281
217/* sys I/F for cooling device */ 282/* cooling device sys I/F */
218#define to_cooling_device(_dev) \ 283#define to_cooling_device(_dev) \
219 container_of(_dev, struct thermal_cooling_device, device) 284 container_of(_dev, struct thermal_cooling_device, device)
220 285
@@ -447,6 +512,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
447 struct thermal_zone_device *pos; 512 struct thermal_zone_device *pos;
448 int result; 513 int result;
449 514
515 if (!type)
516 return ERR_PTR(-EINVAL);
517
450 if (strlen(type) >= THERMAL_NAME_LENGTH) 518 if (strlen(type) >= THERMAL_NAME_LENGTH)
451 return ERR_PTR(-EINVAL); 519 return ERR_PTR(-EINVAL);
452 520
@@ -477,11 +545,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
477 } 545 }
478 546
479 /* sys I/F */ 547 /* sys I/F */
480 if (type) { 548 result = device_create_file(&cdev->device, &dev_attr_cdev_type);
481 result = device_create_file(&cdev->device, &dev_attr_cdev_type); 549 if (result)
482 if (result) 550 goto unregister;
483 goto unregister;
484 }
485 551
486 result = device_create_file(&cdev->device, &dev_attr_max_state); 552 result = device_create_file(&cdev->device, &dev_attr_max_state);
487 if (result) 553 if (result)
@@ -547,8 +613,8 @@ void thermal_cooling_device_unregister(struct
547 tz->ops->unbind(tz, cdev); 613 tz->ops->unbind(tz, cdev);
548 } 614 }
549 mutex_unlock(&thermal_list_lock); 615 mutex_unlock(&thermal_list_lock);
550 if (cdev->type[0]) 616
551 device_remove_file(&cdev->device, &dev_attr_cdev_type); 617 device_remove_file(&cdev->device, &dev_attr_cdev_type);
552 device_remove_file(&cdev->device, &dev_attr_max_state); 618 device_remove_file(&cdev->device, &dev_attr_max_state);
553 device_remove_file(&cdev->device, &dev_attr_cur_state); 619 device_remove_file(&cdev->device, &dev_attr_cur_state);
554 620
@@ -580,6 +646,9 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
580 int result; 646 int result;
581 int count; 647 int count;
582 648
649 if (!type)
650 return ERR_PTR(-EINVAL);
651
583 if (strlen(type) >= THERMAL_NAME_LENGTH) 652 if (strlen(type) >= THERMAL_NAME_LENGTH)
584 return ERR_PTR(-EINVAL); 653 return ERR_PTR(-EINVAL);
585 654
@@ -601,6 +670,13 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
601 kfree(tz); 670 kfree(tz);
602 return ERR_PTR(result); 671 return ERR_PTR(result);
603 } 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 }
604 680
605 strcpy(tz->type, type); 681 strcpy(tz->type, type);
606 tz->ops = ops; 682 tz->ops = ops;
@@ -615,13 +691,28 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
615 return ERR_PTR(result); 691 return ERR_PTR(result);
616 } 692 }
617 693
618 /* sys I/F */ 694 /* hwmon sys I/F */
619 if (type) { 695 result = device_create_file(thermal_hwmon,
620 result = device_create_file(&tz->device, &dev_attr_type); 696 &sensor_attrs[tz->id * 2].dev_attr);
621 if (result) 697 if (result)
622 goto unregister; 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 }
623 } 709 }
624 710
711 /* sys I/F */
712 result = device_create_file(&tz->device, &dev_attr_type);
713 if (result)
714 goto unregister;
715
625 result = device_create_file(&tz->device, &dev_attr_temp); 716 result = device_create_file(&tz->device, &dev_attr_temp);
626 if (result) 717 if (result)
627 goto unregister; 718 goto unregister;
@@ -687,8 +778,17 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
687 tz->ops->unbind(tz, cdev); 778 tz->ops->unbind(tz, cdev);
688 mutex_unlock(&thermal_list_lock); 779 mutex_unlock(&thermal_list_lock);
689 780
690 if (tz->type[0]) 781 device_remove_file(thermal_hwmon,
691 device_remove_file(&tz->device, &dev_attr_type); 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);
692 device_remove_file(&tz->device, &dev_attr_temp); 792 device_remove_file(&tz->device, &dev_attr_temp);
693 if (tz->ops->get_mode) 793 if (tz->ops->get_mode)
694 device_remove_file(&tz->device, &dev_attr_mode); 794 device_remove_file(&tz->device, &dev_attr_mode);
@@ -705,6 +805,19 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
705 805
706EXPORT_SYMBOL(thermal_zone_device_unregister); 806EXPORT_SYMBOL(thermal_zone_device_unregister);
707 807
808static 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
708static int __init thermal_init(void) 821static int __init thermal_init(void)
709{ 822{
710 int result = 0; 823 int result = 0;
@@ -716,16 +829,20 @@ static int __init thermal_init(void)
716 mutex_destroy(&thermal_idr_lock); 829 mutex_destroy(&thermal_idr_lock);
717 mutex_destroy(&thermal_list_lock); 830 mutex_destroy(&thermal_list_lock);
718 } 831 }
719 return result;
720}
721 832
722static void __exit thermal_exit(void) 833 thermal_hwmon = hwmon_device_register(NULL);
723{ 834 if (IS_ERR(thermal_hwmon)) {
724 class_unregister(&thermal_class); 835 result = PTR_ERR(thermal_hwmon);
725 idr_destroy(&thermal_tz_idr); 836 thermal_hwmon = NULL;
726 idr_destroy(&thermal_cdev_idr); 837 printk(KERN_ERR PREFIX
727 mutex_destroy(&thermal_idr_lock); 838 "unable to register hwmon device\n");
728 mutex_destroy(&thermal_list_lock); 839 thermal_exit();
840 return result;
841 }
842
843 result = device_create_file(thermal_hwmon, &dev_attr_name);
844
845 return result;
729} 846}
730 847
731subsys_initcall(thermal_init); 848subsys_initcall(thermal_init);