From: Len Brown <lenb@kernel.org>
To: Zhang Rui <rui.zhang@intel.com>
Cc: linux-acpi@vger.kernel.org
Subject: Re: [PATCH 8/8] [-mm] ACPI: add ACPI thermal_zone sysfs interface
Date: Thu, 22 Mar 2007 00:58:30 -0400 [thread overview]
Message-ID: <200703220058.30374.lenb@kernel.org> (raw)
In-Reply-To: <1174382500.8833.87.camel@localhost.localdomain>
On Tuesday 20 March 2007 05:21, Zhang Rui wrote:
> From: Zhang Rui <rui.zhang@intel.com>
>
> 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
>
I think this is an improvement over the procfs thermal_zone/*/trip_points
file, which confuses a lot of people with its format.
-Len
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
> 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;
> }
>
prev parent reply other threads:[~2007-03-22 4:59 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-03-20 9:21 [PATCH 8/8] [-mm] ACPI: add ACPI thermal_zone sysfs interface Zhang Rui
2007-03-22 4:58 ` Len Brown [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200703220058.30374.lenb@kernel.org \
--to=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=rui.zhang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.