summaryrefslogtreecommitdiffstats
path: root/drivers/thermal/thermal_sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thermal/thermal_sysfs.c')
-rw-r--r--drivers/thermal/thermal_sysfs.c116
1 files changed, 80 insertions, 36 deletions
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index ec495c7dff03..d97f0bc0a26b 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -92,7 +92,14 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
return -EINVAL;
- result = tz->ops->get_trip_type(tz, trip, &type);
+ mutex_lock(&tz->lock);
+
+ if (device_is_registered(dev))
+ result = tz->ops->get_trip_type(tz, trip, &type);
+ else
+ result = -ENODEV;
+
+ mutex_unlock(&tz->lock);
if (result)
return result;
@@ -128,10 +135,17 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
if (kstrtoint(buf, 10, &temperature))
return -EINVAL;
+ mutex_lock(&tz->lock);
+
+ if (!device_is_registered(dev)) {
+ ret = -ENODEV;
+ goto unlock;
+ }
+
if (tz->ops->set_trip_temp) {
ret = tz->ops->set_trip_temp(tz, trip, temperature);
if (ret)
- return ret;
+ goto unlock;
}
if (tz->trips)
@@ -140,16 +154,22 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
if (tz->ops->get_trip_hyst) {
ret = tz->ops->get_trip_hyst(tz, trip, &hyst);
if (ret)
- return ret;
+ goto unlock;
}
ret = tz->ops->get_trip_type(tz, trip, &type);
if (ret)
- return ret;
+ goto unlock;
thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst);
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+ __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+unlock:
+ mutex_unlock(&tz->lock);
+
+ if (ret)
+ return ret;
return count;
}
@@ -168,7 +188,14 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
return -EINVAL;
- ret = tz->ops->get_trip_temp(tz, trip, &temperature);
+ mutex_lock(&tz->lock);
+
+ if (device_is_registered(dev))
+ ret = tz->ops->get_trip_temp(tz, trip, &temperature);
+ else
+ ret = -ENODEV;
+
+ mutex_unlock(&tz->lock);
if (ret)
return ret;
@@ -193,6 +220,13 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
if (kstrtoint(buf, 10, &temperature))
return -EINVAL;
+ mutex_lock(&tz->lock);
+
+ if (!device_is_registered(dev)) {
+ ret = -ENODEV;
+ goto unlock;
+ }
+
/*
* We are not doing any check on the 'temperature' value
* here. The driver implementing 'set_trip_hyst' has to
@@ -201,7 +235,10 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
ret = tz->ops->set_trip_hyst(tz, trip, temperature);
if (!ret)
- thermal_zone_set_trips(tz);
+ __thermal_zone_set_trips(tz);
+
+unlock:
+ mutex_unlock(&tz->lock);
return ret ? ret : count;
}
@@ -220,7 +257,14 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
return -EINVAL;
- ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
+ mutex_lock(&tz->lock);
+
+ if (device_is_registered(dev))
+ ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
+ else
+ ret = -ENODEV;
+
+ mutex_unlock(&tz->lock);
return ret ? ret : sprintf(buf, "%d\n", temperature);
}
@@ -269,16 +313,23 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
if (kstrtoint(buf, 10, &temperature))
return -EINVAL;
- if (!tz->ops->set_emul_temp) {
- mutex_lock(&tz->lock);
+ mutex_lock(&tz->lock);
+
+ if (!device_is_registered(dev)) {
+ ret = -ENODEV;
+ goto unlock;
+ }
+
+ if (!tz->ops->set_emul_temp)
tz->emul_temperature = temperature;
- mutex_unlock(&tz->lock);
- } else {
+ else
ret = tz->ops->set_emul_temp(tz, temperature);
- }
if (!ret)
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+ __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+unlock:
+ mutex_unlock(&tz->lock);
return ret ? ret : count;
}
@@ -589,13 +640,8 @@ static ssize_t max_state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
- int ret;
- ret = cdev->ops->get_max_state(cdev, &state);
- if (ret)
- return ret;
- return sprintf(buf, "%ld\n", state);
+ return sprintf(buf, "%ld\n", cdev->max_state);
}
static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr,
@@ -625,6 +671,10 @@ cur_state_store(struct device *dev, struct device_attribute *attr,
if ((long)state < 0)
return -EINVAL;
+ /* Requested state should be less than max_state + 1 */
+ if (state > cdev->max_state)
+ return -EINVAL;
+
mutex_lock(&cdev->lock);
result = cdev->ops->set_cur_state(cdev, state);
@@ -662,7 +712,6 @@ struct cooling_dev_stats {
spinlock_t lock;
unsigned int total_trans;
unsigned long state;
- unsigned long max_states;
ktime_t last_time;
ktime_t *time_in_state;
unsigned int *trans_table;
@@ -692,7 +741,7 @@ void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
goto unlock;
update_time_in_state(stats);
- stats->trans_table[stats->state * stats->max_states + new_state]++;
+ stats->trans_table[stats->state * (cdev->max_state + 1) + new_state]++;
stats->state = new_state;
stats->total_trans++;
@@ -726,7 +775,7 @@ time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
spin_lock(&stats->lock);
update_time_in_state(stats);
- for (i = 0; i < stats->max_states; i++) {
+ for (i = 0; i <= cdev->max_state; i++) {
len += sprintf(buf + len, "state%u\t%llu\n", i,
ktime_to_ms(stats->time_in_state[i]));
}
@@ -741,7 +790,7 @@ reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
struct cooling_dev_stats *stats = cdev->stats;
- int i, states = stats->max_states;
+ int i, states = cdev->max_state + 1;
spin_lock(&stats->lock);
@@ -750,7 +799,7 @@ reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
memset(stats->trans_table, 0,
states * states * sizeof(*stats->trans_table));
- for (i = 0; i < stats->max_states; i++)
+ for (i = 0; i < states; i++)
stats->time_in_state[i] = ktime_set(0, 0);
spin_unlock(&stats->lock);
@@ -768,7 +817,7 @@ static ssize_t trans_table_show(struct device *dev,
len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
len += snprintf(buf + len, PAGE_SIZE - len, " : ");
- for (i = 0; i < stats->max_states; i++) {
+ for (i = 0; i <= cdev->max_state; i++) {
if (len >= PAGE_SIZE)
break;
len += snprintf(buf + len, PAGE_SIZE - len, "state%2u ", i);
@@ -778,17 +827,17 @@ static ssize_t trans_table_show(struct device *dev,
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
- for (i = 0; i < stats->max_states; i++) {
+ for (i = 0; i <= cdev->max_state; i++) {
if (len >= PAGE_SIZE)
break;
len += snprintf(buf + len, PAGE_SIZE - len, "state%2u:", i);
- for (j = 0; j < stats->max_states; j++) {
+ for (j = 0; j <= cdev->max_state; j++) {
if (len >= PAGE_SIZE)
break;
len += snprintf(buf + len, PAGE_SIZE - len, "%8u ",
- stats->trans_table[i * stats->max_states + j]);
+ stats->trans_table[i * (cdev->max_state + 1) + j]);
}
if (len >= PAGE_SIZE)
break;
@@ -824,14 +873,10 @@ static void cooling_device_stats_setup(struct thermal_cooling_device *cdev)
{
const struct attribute_group *stats_attr_group = NULL;
struct cooling_dev_stats *stats;
- unsigned long states;
+ /* Total number of states is highest state + 1 */
+ unsigned long states = cdev->max_state + 1;
int var;
- if (cdev->ops->get_max_state(cdev, &states))
- goto out;
-
- states++; /* Total number of states is highest state + 1 */
-
var = sizeof(*stats);
var += sizeof(*stats->time_in_state) * states;
var += sizeof(*stats->trans_table) * states * states;
@@ -844,7 +889,6 @@ static void cooling_device_stats_setup(struct thermal_cooling_device *cdev)
stats->trans_table = (unsigned int *)(stats->time_in_state + states);
cdev->stats = stats;
stats->last_time = ktime_get();
- stats->max_states = states;
spin_lock_init(&stats->lock);