diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 022bacb71a7..765c95c533c 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -186,6 +186,12 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "critical\n"); case THERMAL_TRIP_HOT: return sprintf(buf, "hot\n"); + case THERMAL_TRIP_CONFIGURABLE_HI: + return sprintf(buf, "configurable_hi\n"); + case THERMAL_TRIP_CONFIGURABLE_LOW: + return sprintf(buf, "configurable_low\n"); + case THERMAL_TRIP_CRITICAL_LOW: + return sprintf(buf, "critical_low\n"); case THERMAL_TRIP_PASSIVE: return sprintf(buf, "passive\n"); case THERMAL_TRIP_ACTIVE: @@ -195,6 +201,34 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, } } +static ssize_t +trip_point_type_activate(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + int trip, result; + + if (!tz->ops->activate_trip_type) + return -EPERM; + + if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) + return -EINVAL; + + if (!strncmp(buf, "enabled", sizeof("enabled"))) + result = tz->ops->activate_trip_type(tz, trip, + THERMAL_TRIP_ACTIVATION_ENABLED); + else if (!strncmp(buf, "disabled", sizeof("disabled"))) + result = tz->ops->activate_trip_type(tz, trip, + THERMAL_TRIP_ACTIVATION_DISABLED); + else + result = -EINVAL; + + if (result) + return result; + + return count; +} + static ssize_t trip_point_temp_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -217,6 +251,28 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%ld\n", temperature); } +static ssize_t +trip_point_temp_set(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + int trip, ret; + long temperature; + + if (!tz->ops->set_trip_temp) + return -EPERM; + + if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip)) + return -EINVAL; + + if (!sscanf(buf, "%ld", &temperature)) + return -EINVAL; + + ret = tz->ops->set_trip_temp(tz, trip, temperature); + + return ret; +} + static ssize_t passive_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -284,30 +340,54 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store); static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); static struct device_attribute trip_point_attrs[] = { - __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_0_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_0_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_1_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_1_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_2_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_2_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_3_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_3_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_4_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_4_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_5_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_5_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_6_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_6_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_7_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_7_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_8_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_8_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_9_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_9_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_10_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_10_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_11_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_11_temp, 0644, trip_point_temp_show, + trip_point_temp_set), }; /* sys I/F for cooling device */ @@ -1049,6 +1129,29 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) if (tz->ops->notify) tz->ops->notify(tz, count, trip_type); break; + case THERMAL_TRIP_CONFIGURABLE_HI: + if (temp >= trip_temp) + if (tz->ops->notify) + tz->ops->notify(tz, count, trip_type); + break; + case THERMAL_TRIP_CONFIGURABLE_LOW: + if (temp <= trip_temp) + if (tz->ops->notify) + tz->ops->notify(tz, count, trip_type); + break; + case THERMAL_TRIP_CRITICAL_LOW: + if (temp <= trip_temp) { + if (tz->ops->notify) + ret = tz->ops->notify(tz, count, + trip_type); + if (!ret) { + printk(KERN_EMERG + "Critical temperature reached (%ld C), \ + shutting down.\n", temp/1000); + orderly_poweroff(true); + } + } + break; case THERMAL_TRIP_ACTIVE: list_for_each_entry(instance, &tz->cooling_devices, node) { diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 796f1ff0388..f740640b32d 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -37,11 +37,19 @@ enum thermal_device_mode { THERMAL_DEVICE_ENABLED, }; +enum thermal_trip_activation_mode { + THERMAL_TRIP_ACTIVATION_DISABLED = 0, + THERMAL_TRIP_ACTIVATION_ENABLED, +}; + enum thermal_trip_type { THERMAL_TRIP_ACTIVE = 0, THERMAL_TRIP_PASSIVE, THERMAL_TRIP_HOT, THERMAL_TRIP_CRITICAL, + THERMAL_TRIP_CONFIGURABLE_HI, + THERMAL_TRIP_CONFIGURABLE_LOW, + THERMAL_TRIP_CRITICAL_LOW, }; struct thermal_zone_device_ops { @@ -56,8 +64,12 @@ struct thermal_zone_device_ops { enum thermal_device_mode); int (*get_trip_type) (struct thermal_zone_device *, int, enum thermal_trip_type *); + int (*activate_trip_type) (struct thermal_zone_device *, int, + enum thermal_trip_activation_mode); int (*get_trip_temp) (struct thermal_zone_device *, int, unsigned long *); + int (*set_trip_temp) (struct thermal_zone_device *, int, + long); int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); int (*notify) (struct thermal_zone_device *, int, enum thermal_trip_type);