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