[PATCH 8/8] [-mm] ACPI: add ACPI thermal_zone sysfs interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Zhang Rui <rui.zhang@xxxxxxxxx>

Add ACPI thermal_zone sysfs interface.

Required attributes:
Attribute	Mode	Description
state		RO	state of the current thermal zone
			(ok/passive/active[x]/hot/critical)
cooling_mode	RW	the cooling policy of the current thermal zone.
			0x00 = active, 0x01 = passive, 0xff = critical.
polling_freq	RW	
temperature	RO	temperature of the current thermal zone.(celsius)
critical_temp	RW	critical trip point where OSPM must perform a
			critical shutdown

Optional attributes:
Attribute	Mode	Description
hot_temp	RW	critical trip point where OSPM may choose to
			transition the system into S4	
passive_temp	RW	the passive cooling policy threshold value
passive_tc1	RO	thermal constant for passive cooling
passive_tc2	RO	thermal constant for passive cooling
passive_tsp	RO	thermal sampling period for passive cooling
active0_temp	RW	active cooling policy threshold value
...
active9_temp	RW	active cooling policy threshold value

Syslinks to cooling devices(dynamic, optional):
passive_cooling_device0
...
passive_cooling_device9

active0_cooling_device0
...
active0_cooling_device9
...
...
active9_cooling_device0
...
active9_cooling_device9


Signed-off-by: Zhang Rui <rui.zhang@xxxxxxxxx>
---
 drivers/acpi/thermal.c |  713 ++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 622 insertions(+), 91 deletions(-)

Index: linux-2.6.21-rc4-mm1/drivers/acpi/thermal.c
===================================================================
--- linux-2.6.21-rc4-mm1.orig/drivers/acpi/thermal.c	2007-03-20 16:16:23.000000000 +0800
+++ linux-2.6.21-rc4-mm1/drivers/acpi/thermal.c	2007-03-20 16:30:21.000000000 +0800
@@ -83,19 +83,6 @@ MODULE_PARM_DESC(tzp, "Thermal zone poll
 static int acpi_thermal_add(struct acpi_device *device);
 static int acpi_thermal_remove(struct acpi_device *device, int type);
 static int acpi_thermal_resume(struct acpi_device *device);
-static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_trip_points(struct file *,
-					      const char __user *, size_t,
-					      loff_t *);
-static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_cooling_mode(struct file *,
-					       const char __user *, size_t,
-					       loff_t *);
-static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
-					  size_t, loff_t *);
 
 static struct acpi_driver acpi_thermal_driver = {
 	.name = "thermal",
@@ -176,44 +163,6 @@ struct acpi_thermal {
 	struct timer_list timer;
 };
 
-static const struct file_operations acpi_thermal_state_fops = {
-	.open = acpi_thermal_state_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_thermal_temp_fops = {
-	.open = acpi_thermal_temp_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_thermal_trip_fops = {
-	.open = acpi_thermal_trip_open_fs,
-	.read = seq_read,
-	.write = acpi_thermal_write_trip_points,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_thermal_cooling_fops = {
-	.open = acpi_thermal_cooling_open_fs,
-	.read = seq_read,
-	.write = acpi_thermal_write_cooling_mode,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_thermal_polling_fops = {
-	.open = acpi_thermal_polling_open_fs,
-	.read = seq_read,
-	.write = acpi_thermal_write_polling,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
 /* --------------------------------------------------------------------------
                              Thermal Zone Management
    -------------------------------------------------------------------------- */
@@ -305,15 +254,25 @@ static int acpi_thermal_set_cooling_mode
 	return 0;
 }
 
+static int acpi_thermal_cooling_device_update(struct acpi_thermal *thermal, int state,
+						  struct acpi_handle_list *new_devices);
+static int acpi_thermal_sysfs_update(struct acpi_thermal *thermal, struct acpi_thermal_state *old_state);
 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 {
 	acpi_status status = AE_OK;
 	int i = 0;
+	struct acpi_handle_list devices;
+	struct acpi_thermal_state state;
 
 
 	if (!tz)
 		return -EINVAL;
 
+	state.hot = tz->trips.hot.flags.valid;
+	state.passive= tz->trips.passive.flags.valid;
+	for (state.active_index = 0; state.active_index < ACPI_THERMAL_MAX_ACTIVE &&
+		tz->trips.active[state.active_index].flags.valid; state.active_index ++);
+
 	/* Critical Shutdown (required) */
 
 	status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL,
@@ -374,7 +333,7 @@ static int acpi_thermal_get_trip_points(
 
 		status =
 		    acpi_evaluate_reference(tz->device->handle, "_PSL", NULL,
-					    &tz->trips.passive.devices);
+					    &devices);
 		if (ACPI_FAILURE(status))
 			tz->trips.passive.flags.valid = 0;
 
@@ -386,6 +345,13 @@ static int acpi_thermal_get_trip_points(
 					  tz->trips.passive.temperature));
 	}
 
+	if (!tz->trips.passive.flags.valid)
+		devices.count = 0;
+	status = acpi_thermal_cooling_device_update(tz, -1, &devices);
+	if (status)
+		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+				  "Passive cooling device update failed!\n"));
+
 	/* Active: Fans, etc. (optional) */
 
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
@@ -396,22 +362,35 @@ static int acpi_thermal_get_trip_points(
 		    acpi_evaluate_integer(tz->device->handle, name, NULL,
 					  &tz->trips.active[i].temperature);
 		if (ACPI_FAILURE(status))
-			break;
-
-		name[2] = 'L';
-		status =
-		    acpi_evaluate_reference(tz->device->handle, name, NULL,
-					    &tz->trips.active[i].devices);
-		if (ACPI_SUCCESS(status)) {
-			tz->trips.active[i].flags.valid = 1;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "Found active threshold [%d]:[%lu]\n",
-					  i, tz->trips.active[i].temperature));
-		} else
-			ACPI_EXCEPTION((AE_INFO, status,
-					"Invalid active threshold [%d]", i));
+			tz->trips.active[i].flags.valid = 0;
+		else {
+			name[2] = 'L';
+			status =
+			    acpi_evaluate_reference(tz->device->handle, name, NULL,
+						    &devices);
+			if (ACPI_SUCCESS(status)) {
+				tz->trips.active[i].flags.valid = 1;
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+						  "Found active threshold [%d]:[%lu]\n",
+						  i, tz->trips.active[i].temperature));
+			} else {
+				tz->trips.active[i].flags.valid = 0;
+				ACPI_EXCEPTION((AE_INFO, status,
+						"Invalid active threshold [%d]", i));
+			}
+		}
+		if (!tz->trips.active[i].flags.valid)
+			devices.count = 0;
+		status = acpi_thermal_cooling_device_update(tz, i, &devices);
+		if (status)
+			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+				  	"Active[%d] cooling device update failed!\n", i));
 	}
 
+	if(acpi_thermal_sysfs_update(tz, &state))
+		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+		  		"Trip point sysfs update failed!\n"));
+
 	return 0;
 }
 
@@ -771,9 +750,495 @@ static void acpi_thermal_check(void *dat
 }
 
 /* --------------------------------------------------------------------------
-                              FS Interface (/proc)
+                              FS Interface (/sys)
    -------------------------------------------------------------------------- */
+static ssize_t
+acpi_thermal_state_show(struct acpi_device *dev, char *buf)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+	int result = 0;
+
+	if (!thermal->state.critical && !thermal->state.hot && !thermal->state.passive
+	    && !thermal->state.active)
+		result = sprintf(buf, "ok\n");
+	else {
+		if (thermal->state.critical)
+			result += sprintf(buf, "critical ");
+		if (thermal->state.hot)
+			result += sprintf(buf, "hot ");
+		if (thermal->state.passive)
+			result += sprintf(buf, "passive ");
+		if (thermal->state.active)
+			result += sprintf(buf, "active[%d]", thermal->state.active_index);
+		sprintf(buf, "\n");
+	}
+	return result;
+}
+static ACPI_DEVICE_ATTR(state, 0444, acpi_thermal_state_show, NULL);
+
+static ssize_t
+acpi_thermal_temperature_show(struct acpi_device *dev, char *buf)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+	int result = 0;
+
+	result = acpi_thermal_get_temperature(thermal);
+	if (!result)
+		return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(thermal->temperature));
+	else
+		return result;
+}
+static ACPI_DEVICE_ATTR(temperature, 0444, acpi_thermal_temperature_show, NULL);
+
+static ssize_t
+acpi_thermal_cooling_mode_show(struct acpi_device *dev, char *buf)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+
+	if (!thermal)
+		return -EINVAL;
+
+	if (thermal->flags.cooling_mode)
+		return sprintf(buf, "0x%02x\n",	  thermal->cooling_mode);
+
+	return 0;
+}
+
+static ssize_t
+acpi_thermal_cooling_mode_store(struct acpi_device *dev,	const char *buf, size_t count)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+	u32 mode;
+	char *end;
+	int ret = 0;
+
+	mode = simple_strtoul(buf, &end, 0);
+	if (*end == '\0')
+		return -EINVAL;
+
+	if (thermal->flags.cooling_mode){
+		ret = acpi_thermal_set_cooling_mode(thermal, mode);
+		if (ret)
+			return ret;
+		acpi_thermal_check(thermal);
+		return count;
+	}
+	else
+		return -ENODEV;
+}
+static ACPI_DEVICE_ATTR(cooling_mode, 0644, acpi_thermal_cooling_mode_show, acpi_thermal_cooling_mode_store);
+
+static ssize_t
+acpi_thermal_polling_freq_show(struct acpi_device *dev, char *buf)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+
+	if (thermal->polling_frequency)
+		return sprintf(buf, "%lu\n", (thermal->polling_frequency / 10));
+
+	return 0;
+}
+
+static ssize_t
+acpi_thermal_polling_freq_store(struct acpi_device *dev, const char *buf, size_t count)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+	unsigned long freq;
+	char * end;
+	int ret = 0;
+
+	freq = simple_strtoul(buf, &end, 0);
+	if (*end == '\0')
+		return -EINVAL;
+
+	ret = acpi_thermal_set_polling(thermal, freq);
+	if (ret)
+		return ret;
+
+	acpi_thermal_check(thermal);
+	return count;
+}
+static ACPI_DEVICE_ATTR(polling_freq, 0644, acpi_thermal_polling_freq_show, acpi_thermal_polling_freq_store);
+
+static ssize_t
+acpi_thermal_passive_tc1_show(struct acpi_device *dev, char *buf)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+
+	if (!thermal)
+		return -EINVAL;
+
+	if (thermal->trips.passive.flags.valid)
+		return sprintf(buf, "%ld\n", thermal->trips.passive.tc1);
+	else
+		return -ENODEV;
+}
+static ACPI_DEVICE_ATTR(passive_tc1, 0444, acpi_thermal_passive_tc1_show, NULL);
+
+static ssize_t
+acpi_thermal_passive_tc2_show(struct acpi_device *dev, char *buf)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+
+	if (!thermal)
+		return -EINVAL;
+
+	if (thermal->trips.passive.flags.valid)
+		return sprintf(buf, "%ld\n", thermal->trips.passive.tc2);
+	else
+		return -ENODEV;
+}
+static ACPI_DEVICE_ATTR(passive_tc2, 0444, acpi_thermal_passive_tc2_show, NULL);
+
+static ssize_t
+acpi_thermal_passive_tsp_show(struct acpi_device *dev, char *buf)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(dev);
+
+	if (!thermal)
+		return -EINVAL;
+
+	if (thermal->trips.passive.flags.valid)
+		return sprintf(buf, "%ld\n", thermal->trips.passive.tsp);
+	else
+		return -ENODEV;
+}
+static ACPI_DEVICE_ATTR(passive_tsp, 0444, acpi_thermal_passive_tsp_show, NULL);
+
+typedef ssize_t (*trip_point_show)(struct acpi_thermal *thermal,
+				   int type, int state, char*buf);
+typedef ssize_t (*trip_point_store)(struct acpi_thermal *thermal, int type,
+				    int state, const char *buf, size_t count);
+
+struct acpi_thermal_trip_point_attr {
+	struct	device_attribute attr;
+	int	type;
+	int	state;
+	trip_point_show	show;
+	trip_point_store	store;
+};
+
+#define ACPI_THERMAL_TRIP_POINT_CRITICAL	0
+#define ACPI_THERMAL_TRIP_POINT_HOT	1
+#define ACPI_THERMAL_TRIP_POINT_PASSIVE	2
+#define ACPI_THERMAL_TRIP_POINT_ACTIVE	3
+
+static ssize_t
+acpi_thermal_trip_point_show(struct acpi_thermal *thermal,
+				   int type, int state, char*buf)
+{
+	ssize_t result = -ENODEV;
+
+	switch(type) {
+	case ACPI_THERMAL_TRIP_POINT_CRITICAL:
+		if (thermal->trips.critical.flags.valid)
+			result = sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(thermal->trips.critical.temperature));
+		break;
+	case ACPI_THERMAL_TRIP_POINT_HOT:
+		if (thermal->trips.hot.flags.valid)
+			result = sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(thermal->trips.hot.temperature));
+		break;
+	case ACPI_THERMAL_TRIP_POINT_PASSIVE:
+		if (thermal->trips.passive.flags.valid)
+			result = sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(thermal->trips.passive.temperature));
+		break;
+	case ACPI_THERMAL_TRIP_POINT_ACTIVE:
+		if (thermal->trips.active[state].flags.valid) {
+			if (state >= 0 && state < ACPI_THERMAL_MAX_ACTIVE)
+				result = sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(thermal->trips.active[state].temperature));
+			else
+				result = -EINVAL;
+		}
+		break;
+	default:
+		result = -EINVAL;
+	}
+
+	return result;
+}
+
+static ssize_t
+acpi_thermal_trip_point_store(struct acpi_thermal *thermal, int type,
+				    int state, const char *buf, size_t count)
+{
+	char *end;
+	u32 val;
+	ssize_t result = -ENODEV;
+
+	val = simple_strtol(buf, &end, 0);
+	if (*end == '\0')
+		return -EINVAL;
+
+	switch(type) {
+	case ACPI_THERMAL_TRIP_POINT_CRITICAL:
+		if (thermal->trips.critical.flags.valid){
+			thermal->trips.critical.temperature = CELSIUS_TO_KELVIN(val);
+			result = count;
+		}
+		break;
+	case ACPI_THERMAL_TRIP_POINT_HOT:
+		if (thermal->trips.hot.flags.valid){
+			thermal->trips.hot.temperature = CELSIUS_TO_KELVIN(val);
+			result = count;
+		}
+		break;
+	case ACPI_THERMAL_TRIP_POINT_PASSIVE:
+		if (thermal->trips.passive.flags.valid){
+			thermal->trips.passive.temperature = CELSIUS_TO_KELVIN(val);
+			result = count;
+		}
+		break;
+	case ACPI_THERMAL_TRIP_POINT_ACTIVE:
+		if (thermal->trips.active[state].flags.valid){
+			if (state >= 0 && state < ACPI_THERMAL_MAX_ACTIVE) {
+				thermal->trips.active[state].temperature = CELSIUS_TO_KELVIN(val);
+				result = count;
+			}
+			else
+				result = -EINVAL;
+		}
+		break;
+	default:
+		result = -EINVAL;
+	}
 
+	return result;
+}
+
+static ssize_t _trip_point_show(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct acpi_thermal_trip_point_attr *thermal_attr = container_of(attr, struct acpi_thermal_trip_point_attr, attr);
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct acpi_thermal *thermal = acpi_driver_data(acpi_dev);
+
+	if (!thermal_attr->store)
+		return -EINVAL;
+
+	return thermal_attr->show(thermal, thermal_attr->type, thermal_attr->state, buf);
+}
+static ssize_t _trip_point_store(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct acpi_thermal_trip_point_attr *thermal_attr = container_of(attr, struct acpi_thermal_trip_point_attr, attr);
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	struct acpi_thermal *thermal = acpi_driver_data(acpi_dev);
+
+	if (!thermal_attr->store)
+		return -EINVAL;
+
+	return thermal_attr->store(thermal, thermal_attr->type, thermal_attr->state, buf, count);
+}
+
+#define ACPI_THERMAL_TRIP_POINT(_name, _type, _state)	\
+struct acpi_thermal_trip_point_attr _name##_attr =	\
+{				\
+	.attr = __ATTR(_name, 0644, _trip_point_show, _trip_point_store),	\
+	.type = _type,	\
+	.state = _state,	\
+	.show = acpi_thermal_trip_point_show,		\
+	.store = acpi_thermal_trip_point_store,	\
+}
+
+
+static ACPI_THERMAL_TRIP_POINT(critical_temp, ACPI_THERMAL_TRIP_POINT_CRITICAL, 0);
+static ACPI_THERMAL_TRIP_POINT(hot_temp, ACPI_THERMAL_TRIP_POINT_HOT, 0);
+static ACPI_THERMAL_TRIP_POINT(passive_temp, ACPI_THERMAL_TRIP_POINT_PASSIVE, 0);
+static ACPI_THERMAL_TRIP_POINT(active0_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 0);
+static ACPI_THERMAL_TRIP_POINT(active1_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 1);
+static ACPI_THERMAL_TRIP_POINT(active2_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 2);
+static ACPI_THERMAL_TRIP_POINT(active3_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 3);
+static ACPI_THERMAL_TRIP_POINT(active4_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 4);
+static ACPI_THERMAL_TRIP_POINT(active5_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 5);
+static ACPI_THERMAL_TRIP_POINT(active6_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 6);
+static ACPI_THERMAL_TRIP_POINT(active7_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 7);
+static ACPI_THERMAL_TRIP_POINT(active8_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 8);
+static ACPI_THERMAL_TRIP_POINT(active9_temp, ACPI_THERMAL_TRIP_POINT_ACTIVE, 9);
+
+static struct device_attribute *thermal_default_attr[] =
+{
+	GET_DEV_ATTR(state),
+	GET_DEV_ATTR(temperature),
+	GET_DEV_ATTR(cooling_mode),
+	GET_DEV_ATTR(polling_freq),
+	GET_DEV_ATTR(critical_temp),
+	NULL,
+};
+
+static struct device_attribute *thermal_optional_attr[] =
+{
+	GET_DEV_ATTR(hot_temp),
+	GET_DEV_ATTR(passive_temp),
+	GET_DEV_ATTR(passive_tc1),
+	GET_DEV_ATTR(passive_tc2),
+	GET_DEV_ATTR(passive_tsp),
+	GET_DEV_ATTR(active0_temp),
+	GET_DEV_ATTR(active1_temp),
+	GET_DEV_ATTR(active2_temp),
+	GET_DEV_ATTR(active3_temp),
+	GET_DEV_ATTR(active4_temp),
+	GET_DEV_ATTR(active5_temp),
+	GET_DEV_ATTR(active6_temp),
+	GET_DEV_ATTR(active7_temp),
+	GET_DEV_ATTR(active8_temp),
+	GET_DEV_ATTR(active9_temp),
+};
+
+static int acpi_thermal_add_sysfs(struct acpi_device* device)
+{
+	int result = 0;
+
+	result = acpi_device_add_sysfs(device, thermal_default_attr);
+
+	/*
+	 * optional trip point attributes (hot/passive/active)
+	 * and syslinks to cooling devices both are dynamic
+	 */
+
+	return result;
+}
+
+static void acpi_thermal_remove_sysfs(struct acpi_device* device)
+{
+	struct acpi_thermal *thermal = acpi_driver_data(device);
+	struct acpi_handle_list new_devices;
+	int i = 0;
+
+	acpi_device_remove_sysfs(device, thermal_default_attr);
+
+	/*
+	 * remove syslinks to cooling devices
+	 */
+	new_devices.count = 0;
+
+	if (thermal->trips.passive.flags.valid)
+		acpi_thermal_cooling_device_update(thermal, -1, &new_devices);
+
+
+	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
+		if (thermal->trips.active[i].flags.valid)
+			acpi_thermal_cooling_device_update(thermal, i, &new_devices);
+
+	/*
+	 * remove optional trip point attributes
+	 */
+	if (thermal->trips.hot.flags.valid )
+		device_remove_file(&device->dev, thermal_optional_attr[0]);
+
+	if (thermal->trips.passive.flags.valid)
+		for (i = 0; i < 4; i++)
+			device_remove_file(&device->dev, thermal_optional_attr[1+i]);
+
+
+	for(i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
+		if ((thermal->trips.active[i].flags.valid))
+			device_remove_file(&device->dev, thermal_optional_attr[5+i]);
+
+	return ;
+}
+
+static int acpi_thermal_cooling_device_update(struct acpi_thermal* thermal, int state,
+						  struct acpi_handle_list *new_devices)
+{
+	struct acpi_device *device = thermal->device;
+	struct acpi_handle_list *old_devices;
+	struct acpi_device *cooling_device;
+	char buf[24];
+	int i = 0;
+	int result = 0;
+
+	if (!device || !new_devices)
+		return -EINVAL;
+
+	if (state == -1) {
+		sprintf(buf, "passive_cooling_device0");
+		old_devices = &thermal->trips.passive.devices;
+	}
+	else
+		if (state >= 0 && state < ACPI_THERMAL_MAX_ACTIVE) {
+			sprintf(buf, "active%d_cooling_device0", state);
+			old_devices = &thermal->trips.active[state].devices;
+		}
+		else
+			return -EINVAL;
+
+	for (i = 0; i < old_devices->count || i < new_devices->count; i++) {
+		if (i >= old_devices->count)
+			old_devices->handles[i] = NULL;
+		if (i >= new_devices->count)
+			new_devices->handles[i] = NULL;
+		if (new_devices->handles[i] != old_devices->handles[i]) {
+			buf[22] = '0'+i;
+
+			if (i < old_devices->count && old_devices->handles[i])
+				sysfs_remove_link(&device->dev.kobj, buf);
+
+			if (i < new_devices->count && new_devices->handles[i]) {
+				acpi_bus_get_device(new_devices->handles[i], &cooling_device);
+				result = sysfs_create_link(&device->dev.kobj, &cooling_device->dev.kobj, buf);
+				if (result)
+					return result;
+			}
+			old_devices->handles[i] = new_devices->handles[i];
+		}
+	}
+	old_devices->count = new_devices->count;
+
+	return result;
+}
+
+static int acpi_thermal_trip_point_update(struct device *dev, struct device_attribute *attr, int type)
+{
+	int result =0;
+
+	if (type)
+		result = device_create_file(dev, attr);
+	else
+		device_remove_file(dev, attr);
+
+	return result;
+}
+
+static int acpi_thermal_sysfs_update(struct acpi_thermal *thermal, struct acpi_thermal_state *old_state)
+{
+	struct acpi_device *device = thermal->device;
+	int result = 0;
+	int i = 0;
+
+	if (thermal->trips.hot.flags.valid != old_state->hot) {
+		result = acpi_thermal_trip_point_update(&device->dev, thermal_optional_attr[0],
+							thermal->trips.hot.flags.valid);
+		if (result)
+			goto done;
+	}
+
+	if (thermal->trips.passive.flags.valid != old_state->passive)
+		for (i = 0; i < 4; i++) {
+			result = acpi_thermal_trip_point_update(&device->dev, thermal_optional_attr[1+i],
+								thermal->trips.passive.flags.valid);
+			if (result)
+				goto done;
+		}
+
+	for(i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
+	{
+		if ((thermal->trips.active[i].flags.valid && i >= old_state->active_index) ||
+			(!thermal->trips.active[i].flags.valid && i < old_state->active_index)) {
+			result = acpi_thermal_trip_point_update(&device->dev, thermal_optional_attr[5+i],
+								thermal->trips.active[i].flags.valid);
+			if (result)
+				goto done;
+		}
+	}
+
+    done:
+	return result;
+}
+
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc)
+   -------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_PROCFS
 static struct proc_dir_entry *acpi_thermal_dir;
 
 static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
@@ -838,6 +1303,7 @@ static int acpi_thermal_temp_open_fs(str
 static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
 {
 	struct acpi_thermal *tz = seq->private;
+	struct acpi_device *device;
 	int i = 0;
 	int j = 0;
 
@@ -860,9 +1326,8 @@ static int acpi_thermal_trip_seq_show(st
 			   tz->trips.passive.tc1, tz->trips.passive.tc2,
 			   tz->trips.passive.tsp);
 		for (j = 0; j < tz->trips.passive.devices.count; j++) {
-
-			seq_printf(seq, "0x%p ",
-				   tz->trips.passive.devices.handles[j]);
+			acpi_bus_get_device(tz->trips.passive.devices.handles[j], &device);
+  			seq_printf(seq, "%4.4s ", acpi_device_bid(device));
 		}
 		seq_puts(seq, "\n");
 	}
@@ -873,9 +1338,10 @@ static int acpi_thermal_trip_seq_show(st
 		seq_printf(seq, "active[%d]:               %ld C: devices=",
 			   i,
 			   KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
-		for (j = 0; j < tz->trips.active[i].devices.count; j++)
-			seq_printf(seq, "0x%p ",
-				   tz->trips.active[i].devices.handles[j]);
+		for (j = 0; j < tz->trips.active[i].devices.count; j++) {
+			acpi_bus_get_device(tz->trips.active[i].devices.handles[j], &device);
+  			seq_printf(seq, "%4.4s ", acpi_device_bid(device));
+		}
 		seq_puts(seq, "\n");
 	}
 
@@ -1067,7 +1533,45 @@ acpi_thermal_write_polling(struct file *
 	return count;
 }
 
-static int acpi_thermal_add_fs(struct acpi_device *device)
+static const struct file_operations acpi_thermal_state_fops = {
+	.open = acpi_thermal_state_open_fs,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations acpi_thermal_temp_fops = {
+	.open = acpi_thermal_temp_open_fs,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations acpi_thermal_trip_fops = {
+	.open = acpi_thermal_trip_open_fs,
+	.read = seq_read,
+	.write = acpi_thermal_write_trip_points,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations acpi_thermal_cooling_fops = {
+	.open = acpi_thermal_cooling_open_fs,
+	.read = seq_read,
+	.write = acpi_thermal_write_cooling_mode,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations acpi_thermal_polling_fops = {
+	.open = acpi_thermal_polling_open_fs,
+	.read = seq_read,
+	.write = acpi_thermal_write_polling,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int acpi_thermal_add_procfs(struct acpi_device *device)
 {
 	struct proc_dir_entry *entry = NULL;
 
@@ -1141,7 +1645,7 @@ static int acpi_thermal_add_fs(struct ac
 	return 0;
 }
 
-static int acpi_thermal_remove_fs(struct acpi_device *device)
+static int acpi_thermal_remove_procfs(struct acpi_device *device)
 {
 
 	if (acpi_device_dir(device)) {
@@ -1162,6 +1666,26 @@ static int acpi_thermal_remove_fs(struct
 	return 0;
 }
 
+static int acpi_thermal_procfs_init(void)
+{
+	acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
+	if (!acpi_thermal_dir)
+		return -ENODEV;
+	acpi_thermal_dir->owner = THIS_MODULE;
+
+	return 0;
+}
+
+static int acpi_thermal_procfs_exit(void)
+{
+	remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
+
+	return 0;
+}
+#else
+declare_acpi_device_procfs(thermal);
+#endif
+
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -1283,10 +1807,14 @@ static int acpi_thermal_add(struct acpi_
 	if (result)
 		goto end;
 
-	result = acpi_thermal_add_fs(device);
+	result = acpi_thermal_add_sysfs(device);
 	if (result)
 		goto end;
 
+	result = acpi_thermal_add_procfs(device);
+	if (result)
+		goto procfs_error;
+
 	init_timer(&tz->timer);
 
 	acpi_thermal_check(tz);
@@ -1296,19 +1824,22 @@ static int acpi_thermal_add(struct acpi_
 					     acpi_thermal_notify, tz);
 	if (ACPI_FAILURE(status)) {
 		result = -ENODEV;
-		goto end;
+		goto notify_error;
 	}
 
 	printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
 	       KELVIN_TO_CELSIUS(tz->temperature));
 
-      end:
-	if (result) {
-		acpi_thermal_remove_fs(device);
-		kfree(tz);
-	}
+	goto end;
 
+  notify_error:
+	acpi_thermal_remove_procfs(device);
+  procfs_error:
+	acpi_thermal_remove_sysfs(device);
+  end:
+	if (result)
+		kfree(tz);
 	return result;
 }
 
@@ -1347,7 +1878,9 @@ static int acpi_thermal_remove(struct ac
 		acpi_thermal_active(tz);
 	}
 
-	acpi_thermal_remove_fs(device);
+	acpi_thermal_remove_procfs(device);
+
+	acpi_thermal_remove_sysfs(device);
 
 	kfree(tz);
 	return 0;
@@ -1390,15 +1923,14 @@ static int __init acpi_thermal_init(void
 {
 	int result = 0;
 
+	result = acpi_thermal_procfs_init();
+	if (result)
+		return result;
 
-	acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
-	if (!acpi_thermal_dir)
-		return -ENODEV;
-	acpi_thermal_dir->owner = THIS_MODULE;
-
+	acpi_thermal_driver.owner = THIS_MODULE;
 	result = acpi_bus_register_driver(&acpi_thermal_driver);
 	if (result < 0) {
-		remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
+		acpi_thermal_procfs_exit();
 		return -ENODEV;
 	}
 
@@ -1407,10 +1939,9 @@ static int __init acpi_thermal_init(void
 
 static void __exit acpi_thermal_exit(void)
 {
-
 	acpi_bus_unregister_driver(&acpi_thermal_driver);
 
-	remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
+	acpi_thermal_procfs_exit();
 
 	return;
 }
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux