Thermal: Add Hysteresis attributes
The Linux Thermal Framework does not support hysteresis attributes. Most thermal sensors, today, have a hysteresis value associated with trip points. This patch adds hysteresis attributes on a per-trip-point basis, to the Thermal Framework. These attributes are optionally writable. Signed-off-by: Durgadoss R <durgadoss.r@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
parent
c56f5c0342
commit
27365a6c7d
|
@ -121,6 +121,7 @@ Thermal zone device sys I/F, created once it's registered:
|
||||||
|---mode: Working mode of the thermal zone
|
|---mode: Working mode of the thermal zone
|
||||||
|---trip_point_[0-*]_temp: Trip point temperature
|
|---trip_point_[0-*]_temp: Trip point temperature
|
||||||
|---trip_point_[0-*]_type: Trip point type
|
|---trip_point_[0-*]_type: Trip point type
|
||||||
|
|---trip_point_[0-*]_hyst: Hysteresis value for this trip point
|
||||||
|
|
||||||
Thermal cooling device sys I/F, created once it's registered:
|
Thermal cooling device sys I/F, created once it's registered:
|
||||||
/sys/class/thermal/cooling_device[0-*]:
|
/sys/class/thermal/cooling_device[0-*]:
|
||||||
|
@ -190,6 +191,11 @@ trip_point_[0-*]_type
|
||||||
thermal zone.
|
thermal zone.
|
||||||
RO, Optional
|
RO, Optional
|
||||||
|
|
||||||
|
trip_point_[0-*]_hyst
|
||||||
|
The hysteresis value for a trip point, represented as an integer
|
||||||
|
Unit: Celsius
|
||||||
|
RW, Optional
|
||||||
|
|
||||||
cdev[0-*]
|
cdev[0-*]
|
||||||
Sysfs link to the thermal cooling device node where the sys I/F
|
Sysfs link to the thermal cooling device node where the sys I/F
|
||||||
for cooling device throttling control represents.
|
for cooling device throttling control represents.
|
||||||
|
|
|
@ -239,6 +239,52 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
|
||||||
return sprintf(buf, "%ld\n", temperature);
|
return sprintf(buf, "%ld\n", temperature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
trip_point_hyst_store(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;
|
||||||
|
unsigned long temperature;
|
||||||
|
|
||||||
|
if (!tz->ops->set_trip_hyst)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (kstrtoul(buf, 10, &temperature))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are not doing any check on the 'temperature' value
|
||||||
|
* here. The driver implementing 'set_trip_hyst' has to
|
||||||
|
* take care of this.
|
||||||
|
*/
|
||||||
|
ret = tz->ops->set_trip_hyst(tz, trip, temperature);
|
||||||
|
|
||||||
|
return ret ? ret : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct thermal_zone_device *tz = to_thermal_zone(dev);
|
||||||
|
int trip, ret;
|
||||||
|
unsigned long temperature;
|
||||||
|
|
||||||
|
if (!tz->ops->get_trip_hyst)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
|
||||||
|
|
||||||
|
return ret ? ret : sprintf(buf, "%ld\n", temperature);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
passive_store(struct device *dev, struct device_attribute *attr,
|
passive_store(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
|
@ -1091,21 +1137,29 @@ EXPORT_SYMBOL(thermal_zone_device_update);
|
||||||
static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
|
static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
|
||||||
{
|
{
|
||||||
int indx;
|
int indx;
|
||||||
|
int size = sizeof(struct thermal_attr) * tz->trips;
|
||||||
|
|
||||||
tz->trip_type_attrs =
|
tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
|
||||||
kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
|
|
||||||
if (!tz->trip_type_attrs)
|
if (!tz->trip_type_attrs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
tz->trip_temp_attrs =
|
tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
|
||||||
kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
|
|
||||||
if (!tz->trip_temp_attrs) {
|
if (!tz->trip_temp_attrs) {
|
||||||
kfree(tz->trip_type_attrs);
|
kfree(tz->trip_type_attrs);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (indx = 0; indx < tz->trips; indx++) {
|
if (tz->ops->get_trip_hyst) {
|
||||||
|
tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL);
|
||||||
|
if (!tz->trip_hyst_attrs) {
|
||||||
|
kfree(tz->trip_type_attrs);
|
||||||
|
kfree(tz->trip_temp_attrs);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (indx = 0; indx < tz->trips; indx++) {
|
||||||
/* create trip type attribute */
|
/* create trip type attribute */
|
||||||
snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
|
snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
|
||||||
"trip_point_%d_type", indx);
|
"trip_point_%d_type", indx);
|
||||||
|
@ -1136,6 +1190,26 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
|
||||||
|
|
||||||
device_create_file(&tz->device,
|
device_create_file(&tz->device,
|
||||||
&tz->trip_temp_attrs[indx].attr);
|
&tz->trip_temp_attrs[indx].attr);
|
||||||
|
|
||||||
|
/* create Optional trip hyst attribute */
|
||||||
|
if (!tz->ops->get_trip_hyst)
|
||||||
|
continue;
|
||||||
|
snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
|
||||||
|
"trip_point_%d_hyst", indx);
|
||||||
|
|
||||||
|
sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
|
||||||
|
tz->trip_hyst_attrs[indx].attr.attr.name =
|
||||||
|
tz->trip_hyst_attrs[indx].name;
|
||||||
|
tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
|
||||||
|
tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
|
||||||
|
if (tz->ops->set_trip_hyst) {
|
||||||
|
tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
|
||||||
|
tz->trip_hyst_attrs[indx].attr.store =
|
||||||
|
trip_point_hyst_store;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_create_file(&tz->device,
|
||||||
|
&tz->trip_hyst_attrs[indx].attr);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1149,9 +1223,13 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
|
||||||
&tz->trip_type_attrs[indx].attr);
|
&tz->trip_type_attrs[indx].attr);
|
||||||
device_remove_file(&tz->device,
|
device_remove_file(&tz->device,
|
||||||
&tz->trip_temp_attrs[indx].attr);
|
&tz->trip_temp_attrs[indx].attr);
|
||||||
|
if (tz->ops->get_trip_hyst)
|
||||||
|
device_remove_file(&tz->device,
|
||||||
|
&tz->trip_hyst_attrs[indx].attr);
|
||||||
}
|
}
|
||||||
kfree(tz->trip_type_attrs);
|
kfree(tz->trip_type_attrs);
|
||||||
kfree(tz->trip_temp_attrs);
|
kfree(tz->trip_temp_attrs);
|
||||||
|
kfree(tz->trip_hyst_attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -60,6 +60,10 @@ struct thermal_zone_device_ops {
|
||||||
unsigned long *);
|
unsigned long *);
|
||||||
int (*set_trip_temp) (struct thermal_zone_device *, int,
|
int (*set_trip_temp) (struct thermal_zone_device *, int,
|
||||||
unsigned long);
|
unsigned long);
|
||||||
|
int (*get_trip_hyst) (struct thermal_zone_device *, int,
|
||||||
|
unsigned long *);
|
||||||
|
int (*set_trip_hyst) (struct thermal_zone_device *, int,
|
||||||
|
unsigned long);
|
||||||
int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
|
int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
|
||||||
int (*notify) (struct thermal_zone_device *, int,
|
int (*notify) (struct thermal_zone_device *, int,
|
||||||
enum thermal_trip_type);
|
enum thermal_trip_type);
|
||||||
|
@ -98,6 +102,7 @@ struct thermal_zone_device {
|
||||||
struct device device;
|
struct device device;
|
||||||
struct thermal_attr *trip_temp_attrs;
|
struct thermal_attr *trip_temp_attrs;
|
||||||
struct thermal_attr *trip_type_attrs;
|
struct thermal_attr *trip_type_attrs;
|
||||||
|
struct thermal_attr *trip_hyst_attrs;
|
||||||
void *devdata;
|
void *devdata;
|
||||||
int trips;
|
int trips;
|
||||||
int tc1;
|
int tc1;
|
||||||
|
|
Loading…
Reference in New Issue