Subject: [PATCH] [acpi thermal] Add proc interface - Identical to legacy interface with files: - state - temperature - trip_points - cooling_mode - polling_frequency Signed-off-by: Patrick Mochel --- drivers/acpi/drivers/thermal/proc.c | 269 +++++++++++++++++++++++++++++++++++ 1 files changed, 268 insertions(+), 1 deletions(-) applies-to: 4a4310da41fc0ef753d2c931130211a103b40d9e afc810dcc06a314bfacbf805fd63979fa6002d81 diff --git a/drivers/acpi/drivers/thermal/proc.c b/drivers/acpi/drivers/thermal/proc.c index 9454df4..fc963f7 100644 --- a/drivers/acpi/drivers/thermal/proc.c +++ b/drivers/acpi/drivers/thermal/proc.c @@ -13,4 +13,271 @@ #include "thermal.h" -acpi_driver_proc_none(thermal); + +static int read_state(struct seq_file * seq, void * offset) +{ + struct acpi_dev * ad = seq->private; + struct acpi_thermal * at = dev_get_drvdata(&ad->dev); + + if (!at->t_state) + seq_printf(seq, "ok"); + else { + if (at->t_state & THERMAL_STATE_CRIT) + seq_printf(seq, "critical "); + if (at->t_state & THERMAL_STATE_HOT) + seq_printf(seq, "hot "); + if (at->t_state & THERMAL_STATE_PSV) + seq_printf(seq, "passive "); + if (at->t_state & THERMAL_STATE_ACT) + seq_printf(seq, "active[%d] ", + at->t_trips.act_index); + } + seq_printf(seq, "\n"); + return 0; +} + +static int open_state(struct inode * inode, struct file * file) +{ + return single_open(file, read_state, PDE(inode)->data); +} + + +static int read_temperature(struct seq_file * seq, void * offset) +{ + struct acpi_dev * ad = seq->private; + struct acpi_thermal * at = dev_get_drvdata(&ad->dev); + + if (!thermal_get_temp(at)) { + seq_printf(seq, "temperature: %ld C\n", + thermal_temp_c(at->t_temp)); + } + return 0; +} + +static int open_temperature(struct inode * inode, struct file * file) +{ + return single_open(file, read_temperature, PDE(inode)->data); +} + + + +static int read_trip_points(struct seq_file * seq, void * offset) +{ + struct acpi_dev * ad = seq->private; + struct acpi_thermal * at = dev_get_drvdata(&ad->dev); + int i; + int j; + + if (at->t_trips.crit_val) + seq_printf(seq, "critical (S5): %ld C\n", + thermal_temp_c(at->t_trips.crit_temp)); + + if (at->t_trips.hot_val) + seq_printf(seq, "hot (S4): %ld C\n", + thermal_temp_c(at->t_trips.hot_temp)); + + if (at->t_trips.psv_val) { + seq_printf(seq, + "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=", + thermal_temp_c(at->t_trips.crit_temp), + at->t_trips.psv_tc1, at->t_trips.psv_tc2, + at->t_trips.psv_tsp); + for (j = 0; j < at->t_trips.psv_devices.count; j++) { + seq_printf(seq, "%p ", + at->t_trips.psv_devices.handles[j]); + } + seq_printf(seq, "\n"); + } + + for (i = 0; i < THERMAL_MAX_ACTIVE; i++) { + struct thermal_active * ta = at->t_trips.act + i; + if (!ta->en) + break; + seq_printf(seq, "active[%d]: %ld C: devices=", + i, thermal_temp_c(ta->temp)); + for (j = 0; j < ta->devices.count; j++) + seq_printf(seq, "%p ", ta->devices.handles[j]); + seq_printf(seq, "\n"); + } + return 0; +} + +#define LIMIT_SIZE 65 + +static ssize_t write_trip_points(struct file *file, + const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct seq_file * m = file->private_data; + struct acpi_dev * ad = m->private; + struct acpi_thermal * at = dev_get_drvdata(&ad->dev); + char * limit_string; + int * act; + int crit, hot, psv; + int i; + int num; + int ret = 0; + + if (count > LIMIT_SIZE - 1) + return -EINVAL; + + limit_string = kzalloc(LIMIT_SIZE, GFP_KERNEL); + if (!limit_string) + return -ENOMEM; + + act = kzalloc(THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL); + if (!act) { + kfree(limit_string); + return -ENOMEM; + } + + if (copy_from_user(limit_string, buffer, count)) + return -EFAULT; + + num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", + &crit, &hot, &psv, + &act[0], &act[1], &act[2], &act[3], &act[4], + &act[5], &act[6], &act[7], &act[8], &act[9]); + if (num < 5) { + dbg("Invalid data format"); + ret = -EINVAL; + goto Done; + } + + at->t_trips.crit_temp = thermal_temp_k(crit); + at->t_trips.hot_temp = thermal_temp_k(hot); + at->t_trips.psv_temp = thermal_temp_k(psv); + for (i = 0; i < num - 3; i++) { + if (at->t_trips.act[i].val) + at->t_trips.act[i].temp = thermal_temp_k(act[i]); + else + break; + } + + Done: + kfree(act); + kfree(limit_string); + return ret ? ret : count; +} + +static int open_trip_points(struct inode * inode, struct file * file) +{ + return single_open(file, read_trip_points, PDE(inode)->data); +} + + +static int read_cooling_mode(struct seq_file * seq, void * offset) +{ + struct acpi_dev * ad = seq->private; + struct acpi_thermal * at = dev_get_drvdata(&ad->dev); + const char * mode; + + if (at->t_cooling_mode == THERMAL_MODE_CRIT) + mode = "critical"; + else if (at->t_cooling_mode) + mode = "passive"; + else + mode = "active"; + seq_printf(seq, "%s\n", mode); + return 0; +} + +static ssize_t write_cooling_mode(struct file *file, + const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct seq_file * m = file->private_data; + struct acpi_dev * ad = m->private; + struct acpi_thermal * at = dev_get_drvdata(&ad->dev); + + char mode_string[12] = ""; + char * end; + u32 mode; + int ret = 0; + + if (count > sizeof(mode_string) - 1) + return -EINVAL; + + if (copy_from_user(mode_string, buffer, count)) + return -EFAULT; + + mode = simple_strtoul(mode_string, &end, 0); + if (*end) + return -EINVAL; + + if (mode == THERMAL_MODE_CRIT || + mode == THERMAL_MODE_ACT || + mode == THERMAL_MODE_PSV) + ret = thermal_set_cooling_mode(at, mode); + + if (!ret) + thermal_check(at); + + return ret ? ret : count; +} + +static int open_cooling_mode(struct inode * inode, struct file * file) +{ + return single_open(file, read_cooling_mode, PDE(inode)->data); +} + + +static int read_polling_frequency(struct seq_file * seq, void * offset) +{ + struct acpi_dev * ad = seq->private; + struct acpi_thermal * at = dev_get_drvdata(&ad->dev); + + if (at->t_poll_freq) + seq_printf(seq, "polling frequency: %lu seconds\n", + (at->t_poll_freq / 10)); + else + seq_printf(seq, "\n"); + return 0; +} + +static ssize_t write_polling_frequency(struct file *file, + const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct seq_file * m = file->private_data; + struct acpi_dev * ad = m->private; + struct acpi_thermal * at = dev_get_drvdata(&ad->dev); + + char poll_string[12] = ""; + char * end; + unsigned long freq; + + int ret = 0; + + if (count > sizeof(poll_string) - 1) + return -EINVAL; + + if (copy_from_user(poll_string, buffer, count)) + return -EFAULT; + + freq = simple_strtoul(poll_string, &end, 0); + if (*end) + return -EINVAL; + + ret = thermal_set_poll_freq(at, freq); + if (!ret) + thermal_check(at); + + return ret ? ret : count; +} + +static int open_polling_frequency(struct inode * inode, struct file * file) +{ + return single_open(file, read_polling_frequency, PDE(inode)->data); +} + +static struct acpi_proc_file thermal_files[] = { + proc_file_ro(state), + proc_file_ro(temperature), + proc_file_rw(trip_points), + proc_file_rw(cooling_mode), + proc_file_rw(polling_frequency), +}; + +acpi_driver_proc_name(thermal, "thermal_zone"); + --- 0.99.9.GIT