Browse Source

Merge branches 'release' and 'thermal' into release

Len Brown 17 years ago
parent
commit
160ff06b18
4 changed files with 162 additions and 42 deletions
  1. 11 11
      Documentation/thermal/sysfs-api.txt
  2. 7 5
      drivers/acpi/thermal.c
  3. 1 0
      drivers/thermal/Kconfig
  4. 143 26
      drivers/thermal/thermal.c

+ 11 - 11
Documentation/thermal/sysfs-api.txt

@@ -143,10 +143,10 @@ type				Strings which represent the thermal zone type.
 				This is given by thermal zone driver as part of registration.
 				This is given by thermal zone driver as part of registration.
 				Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
 				Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
 				RO
 				RO
-				Optional
+				Required
 
 
 temp				Current temperature as reported by thermal zone (sensor)
 temp				Current temperature as reported by thermal zone (sensor)
-				Unit: degree Celsius
+				Unit: millidegree Celsius
 				RO
 				RO
 				Required
 				Required
 
 
@@ -163,7 +163,7 @@ mode				One of the predefined values in [kernel, user]
 					  charge of the thermal management.
 					  charge of the thermal management.
 
 
 trip_point_[0-*]_temp		The temperature above which trip point will be fired
 trip_point_[0-*]_temp		The temperature above which trip point will be fired
-				Unit: degree Celsius
+				Unit: millidegree Celsius
 				RO
 				RO
 				Optional
 				Optional
 
 
@@ -193,7 +193,7 @@ type				String which represents the type of device
 				eg. For memory controller device on intel_menlow platform:
 				eg. For memory controller device on intel_menlow platform:
 				this should be "Memory controller"
 				this should be "Memory controller"
 				RO
 				RO
-				Optional
+				Required
 
 
 max_state			The maximum permissible cooling state of this cooling device.
 max_state			The maximum permissible cooling state of this cooling device.
 				RO
 				RO
@@ -219,16 +219,16 @@ the sys I/F structure will be built like this:
 
 
 |thermal_zone1:
 |thermal_zone1:
 	|-----type:			ACPI thermal zone
 	|-----type:			ACPI thermal zone
-	|-----temp:			37
+	|-----temp:			37000
 	|-----mode:			kernel
 	|-----mode:			kernel
-	|-----trip_point_0_temp:	100
+	|-----trip_point_0_temp:	100000
 	|-----trip_point_0_type:	critical
 	|-----trip_point_0_type:	critical
-	|-----trip_point_1_temp:	80
+	|-----trip_point_1_temp:	80000
 	|-----trip_point_1_type:	passive
 	|-----trip_point_1_type:	passive
-	|-----trip_point_2_temp:	70
-	|-----trip_point_2_type:	active[0]
-	|-----trip_point_3_temp:	60
-	|-----trip_point_3_type:	active[1]
+	|-----trip_point_2_temp:	70000
+	|-----trip_point_2_type:	active0
+	|-----trip_point_3_temp:	60000
+	|-----trip_point_3_type:	active1
 	|-----cdev0:			--->/sys/class/thermal/cooling_device0
 	|-----cdev0:			--->/sys/class/thermal/cooling_device0
 	|-----cdev0_trip_point:		1	/* cdev0 can be used for passive */
 	|-----cdev0_trip_point:		1	/* cdev0 can be used for passive */
 	|-----cdev1:			--->/sys/class/thermal/cooling_device3
 	|-----cdev1:			--->/sys/class/thermal/cooling_device3

+ 7 - 5
drivers/acpi/thermal.c

@@ -879,6 +879,8 @@ static void acpi_thermal_check(void *data)
 }
 }
 
 
 /* sys I/F for generic thermal sysfs support */
 /* sys I/F for generic thermal sysfs support */
+#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)
+
 static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
 static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
 {
 {
 	struct acpi_thermal *tz = thermal->devdata;
 	struct acpi_thermal *tz = thermal->devdata;
@@ -886,7 +888,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
 	if (!tz)
 	if (!tz)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(tz->temperature));
+	return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature));
 }
 }
 
 
 static const char enabled[] = "kernel";
 static const char enabled[] = "kernel";
@@ -980,21 +982,21 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
 
 	if (tz->trips.critical.flags.valid) {
 	if (tz->trips.critical.flags.valid) {
 		if (!trip)
 		if (!trip)
-			return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
 				tz->trips.critical.temperature));
 				tz->trips.critical.temperature));
 		trip--;
 		trip--;
 	}
 	}
 
 
 	if (tz->trips.hot.flags.valid) {
 	if (tz->trips.hot.flags.valid) {
 		if (!trip)
 		if (!trip)
-			return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
 					tz->trips.hot.temperature));
 					tz->trips.hot.temperature));
 		trip--;
 		trip--;
 	}
 	}
 
 
 	if (tz->trips.passive.flags.valid) {
 	if (tz->trips.passive.flags.valid) {
 		if (!trip)
 		if (!trip)
-			return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
 					tz->trips.passive.temperature));
 					tz->trips.passive.temperature));
 		trip--;
 		trip--;
 	}
 	}
@@ -1002,7 +1004,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
 		tz->trips.active[i].flags.valid; i++) {
 		tz->trips.active[i].flags.valid; i++) {
 		if (!trip)
 		if (!trip)
-			return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
 					tz->trips.active[i].temperature));
 					tz->trips.active[i].temperature));
 		trip--;
 		trip--;
 	}
 	}

+ 1 - 0
drivers/thermal/Kconfig

@@ -4,6 +4,7 @@
 
 
 menuconfig THERMAL
 menuconfig THERMAL
 	bool "Generic Thermal sysfs driver"
 	bool "Generic Thermal sysfs driver"
+	select HWMON
 	default y
 	default y
 	help
 	help
 	  Generic Thermal Sysfs driver offers a generic mechanism for
 	  Generic Thermal Sysfs driver offers a generic mechanism for

+ 143 - 26
drivers/thermal/thermal.c

@@ -30,8 +30,10 @@
 #include <linux/idr.h>
 #include <linux/idr.h>
 #include <linux/thermal.h>
 #include <linux/thermal.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 
 
-MODULE_AUTHOR("Zhang Rui")
+MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 
@@ -56,6 +58,9 @@ static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_cdev_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(thermal_list_lock);
 
 
+static struct device *thermal_hwmon;
+#define MAX_THERMAL_ZONES	10
+
 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
 {
 {
 	int err;
 	int err;
@@ -87,7 +92,67 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
 		mutex_unlock(lock);
 		mutex_unlock(lock);
 }
 }
 
 
-/* sys I/F for thermal zone */
+/* hwmon sys I/F*/
+static ssize_t
+name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "thermal_sys_class\n");
+}
+
+static ssize_t
+temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct thermal_zone_device *tz;
+	struct sensor_device_attribute *sensor_attr
+						= to_sensor_dev_attr(attr);
+
+	list_for_each_entry(tz, &thermal_tz_list, node)
+		if (tz->id == sensor_attr->index)
+			return tz->ops->get_temp(tz, buf);
+
+	return -ENODEV;
+}
+
+static ssize_t
+temp_crit_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct thermal_zone_device *tz;
+	struct sensor_device_attribute *sensor_attr
+						= to_sensor_dev_attr(attr);
+
+	list_for_each_entry(tz, &thermal_tz_list, node)
+		if (tz->id == sensor_attr->index)
+			return tz->ops->get_trip_temp(tz, 0, buf);
+
+	return -ENODEV;
+}
+
+static DEVICE_ATTR(name, 0444, name_show, NULL);
+static struct sensor_device_attribute sensor_attrs[] = {
+	SENSOR_ATTR(temp1_input, 0444, temp_input_show, NULL, 0),
+	SENSOR_ATTR(temp1_crit, 0444, temp_crit_show, NULL, 0),
+	SENSOR_ATTR(temp2_input, 0444, temp_input_show, NULL, 1),
+	SENSOR_ATTR(temp2_crit, 0444, temp_crit_show, NULL, 1),
+	SENSOR_ATTR(temp3_input, 0444, temp_input_show, NULL, 2),
+	SENSOR_ATTR(temp3_crit, 0444, temp_crit_show, NULL, 2),
+	SENSOR_ATTR(temp4_input, 0444, temp_input_show, NULL, 3),
+	SENSOR_ATTR(temp4_crit, 0444, temp_crit_show, NULL, 3),
+	SENSOR_ATTR(temp5_input, 0444, temp_input_show, NULL, 4),
+	SENSOR_ATTR(temp5_crit, 0444, temp_crit_show, NULL, 4),
+	SENSOR_ATTR(temp6_input, 0444, temp_input_show, NULL, 5),
+	SENSOR_ATTR(temp6_crit, 0444, temp_crit_show, NULL, 5),
+	SENSOR_ATTR(temp7_input, 0444, temp_input_show, NULL, 6),
+	SENSOR_ATTR(temp7_crit, 0444, temp_crit_show, NULL, 6),
+	SENSOR_ATTR(temp8_input, 0444, temp_input_show, NULL, 7),
+	SENSOR_ATTR(temp8_crit, 0444, temp_crit_show, NULL, 7),
+	SENSOR_ATTR(temp9_input, 0444, temp_input_show, NULL, 8),
+	SENSOR_ATTR(temp9_crit, 0444, temp_crit_show, NULL, 8),
+	SENSOR_ATTR(temp10_input, 0444, temp_input_show, NULL, 9),
+	SENSOR_ATTR(temp10_crit, 0444, temp_crit_show, NULL, 9),
+};
+
+/* thermal zone sys I/F */
 
 
 #define to_thermal_zone(_dev) \
 #define to_thermal_zone(_dev) \
 	container_of(_dev, struct thermal_zone_device, device)
 	container_of(_dev, struct thermal_zone_device, device)
@@ -214,7 +279,7 @@ do {	\
 	device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]);	\
 	device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]);	\
 } while (0)
 } while (0)
 
 
-/* sys I/F for cooling device */
+/* cooling device sys I/F */
 #define to_cooling_device(_dev)	\
 #define to_cooling_device(_dev)	\
 	container_of(_dev, struct thermal_cooling_device, device)
 	container_of(_dev, struct thermal_cooling_device, device)
 
 
@@ -447,6 +512,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
 	struct thermal_zone_device *pos;
 	struct thermal_zone_device *pos;
 	int result;
 	int result;
 
 
+	if (!type)
+		return ERR_PTR(-EINVAL);
+
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
 		return ERR_PTR(-EINVAL);
 		return ERR_PTR(-EINVAL);
 
 
@@ -477,11 +545,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
 	}
 	}
 
 
 	/* sys I/F */
 	/* sys I/F */
-	if (type) {
-		result = device_create_file(&cdev->device, &dev_attr_cdev_type);
-		if (result)
-			goto unregister;
-	}
+	result = device_create_file(&cdev->device, &dev_attr_cdev_type);
+	if (result)
+		goto unregister;
 
 
 	result = device_create_file(&cdev->device, &dev_attr_max_state);
 	result = device_create_file(&cdev->device, &dev_attr_max_state);
 	if (result)
 	if (result)
@@ -547,8 +613,8 @@ void thermal_cooling_device_unregister(struct
 		tz->ops->unbind(tz, cdev);
 		tz->ops->unbind(tz, cdev);
 	}
 	}
 	mutex_unlock(&thermal_list_lock);
 	mutex_unlock(&thermal_list_lock);
-	if (cdev->type[0])
-		device_remove_file(&cdev->device, &dev_attr_cdev_type);
+
+	device_remove_file(&cdev->device, &dev_attr_cdev_type);
 	device_remove_file(&cdev->device, &dev_attr_max_state);
 	device_remove_file(&cdev->device, &dev_attr_max_state);
 	device_remove_file(&cdev->device, &dev_attr_cur_state);
 	device_remove_file(&cdev->device, &dev_attr_cur_state);
 
 
@@ -580,6 +646,9 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 	int result;
 	int result;
 	int count;
 	int count;
 
 
+	if (!type)
+		return ERR_PTR(-EINVAL);
+
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
 		return ERR_PTR(-EINVAL);
 		return ERR_PTR(-EINVAL);
 
 
@@ -601,6 +670,13 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 		kfree(tz);
 		kfree(tz);
 		return ERR_PTR(result);
 		return ERR_PTR(result);
 	}
 	}
+	if (tz->id >= MAX_THERMAL_ZONES) {
+		printk(KERN_ERR PREFIX
+			"Too many thermal zones\n");
+		release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
+		kfree(tz);
+		return ERR_PTR(-EINVAL);
+	}
 
 
 	strcpy(tz->type, type);
 	strcpy(tz->type, type);
 	tz->ops = ops;
 	tz->ops = ops;
@@ -615,13 +691,28 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 		return ERR_PTR(result);
 		return ERR_PTR(result);
 	}
 	}
 
 
-	/* sys I/F */
-	if (type) {
-		result = device_create_file(&tz->device, &dev_attr_type);
-		if (result)
-			goto unregister;
+	/* hwmon sys I/F */
+	result = device_create_file(thermal_hwmon,
+					&sensor_attrs[tz->id * 2].dev_attr);
+	if (result)
+		goto unregister;
+
+	if (trips > 0) {
+		char buf[40];
+		result = tz->ops->get_trip_type(tz, 0, buf);
+		if (result > 0 && !strcmp(buf, "critical\n")) {
+			result = device_create_file(thermal_hwmon,
+					&sensor_attrs[tz->id * 2 + 1].dev_attr);
+			if (result)
+				goto unregister;
+		}
 	}
 	}
 
 
+	/* sys I/F */
+	result = device_create_file(&tz->device, &dev_attr_type);
+	if (result)
+		goto unregister;
+
 	result = device_create_file(&tz->device, &dev_attr_temp);
 	result = device_create_file(&tz->device, &dev_attr_temp);
 	if (result)
 	if (result)
 		goto unregister;
 		goto unregister;
@@ -687,8 +778,17 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 		    tz->ops->unbind(tz, cdev);
 		    tz->ops->unbind(tz, cdev);
 	mutex_unlock(&thermal_list_lock);
 	mutex_unlock(&thermal_list_lock);
 
 
-	if (tz->type[0])
-		device_remove_file(&tz->device, &dev_attr_type);
+	device_remove_file(thermal_hwmon,
+				&sensor_attrs[tz->id * 2].dev_attr);
+	if (tz->trips > 0) {
+		char buf[40];
+		if (tz->ops->get_trip_type(tz, 0, buf) > 0)
+			if (!strcmp(buf, "critical\n"))
+				device_remove_file(thermal_hwmon,
+				&sensor_attrs[tz->id * 2 + 1].dev_attr);
+	}
+
+	device_remove_file(&tz->device, &dev_attr_type);
 	device_remove_file(&tz->device, &dev_attr_temp);
 	device_remove_file(&tz->device, &dev_attr_temp);
 	if (tz->ops->get_mode)
 	if (tz->ops->get_mode)
 		device_remove_file(&tz->device, &dev_attr_mode);
 		device_remove_file(&tz->device, &dev_attr_mode);
@@ -705,6 +805,19 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 
 
 EXPORT_SYMBOL(thermal_zone_device_unregister);
 EXPORT_SYMBOL(thermal_zone_device_unregister);
 
 
+static void thermal_exit(void)
+{
+	if (thermal_hwmon) {
+		device_remove_file(thermal_hwmon, &dev_attr_name);
+		hwmon_device_unregister(thermal_hwmon);
+	}
+	class_unregister(&thermal_class);
+	idr_destroy(&thermal_tz_idr);
+	idr_destroy(&thermal_cdev_idr);
+	mutex_destroy(&thermal_idr_lock);
+	mutex_destroy(&thermal_list_lock);
+}
+
 static int __init thermal_init(void)
 static int __init thermal_init(void)
 {
 {
 	int result = 0;
 	int result = 0;
@@ -716,16 +829,20 @@ static int __init thermal_init(void)
 		mutex_destroy(&thermal_idr_lock);
 		mutex_destroy(&thermal_idr_lock);
 		mutex_destroy(&thermal_list_lock);
 		mutex_destroy(&thermal_list_lock);
 	}
 	}
-	return result;
-}
 
 
-static void __exit thermal_exit(void)
-{
-	class_unregister(&thermal_class);
-	idr_destroy(&thermal_tz_idr);
-	idr_destroy(&thermal_cdev_idr);
-	mutex_destroy(&thermal_idr_lock);
-	mutex_destroy(&thermal_list_lock);
+	thermal_hwmon = hwmon_device_register(NULL);
+	if (IS_ERR(thermal_hwmon)) {
+		result = PTR_ERR(thermal_hwmon);
+		thermal_hwmon = NULL;
+		printk(KERN_ERR PREFIX
+			"unable to register hwmon device\n");
+		thermal_exit();
+		return result;
+	}
+
+	result = device_create_file(thermal_hwmon, &dev_attr_name);
+
+	return result;
 }
 }
 
 
 subsys_initcall(thermal_init);
 subsys_initcall(thermal_init);