[PATCH 5/8] Thermal: Add 'thermal_map' sysfs node
This patch creates a thermal map sysfs node under /sys/class/thermal/thermal_zoneX/. This contains entries named map0, map1 .. mapN. Each map has the following space separated values: trip_type sensor_name cdev_name trip_mask weights Signed-off-by: Durgadoss R --- drivers/thermal/thermal_sys.c | 149 - include/linux/thermal.h | 29 2 files changed, 176 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 29ec073..a3adc00 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -506,6 +506,41 @@ static void remove_cdev_from_zone(struct thermal_zone *tz, tz->cdev_indx--; } +static void __clean_map_entry(struct thermal_zone *tz, int i) +{ + tz->map[i] = NULL; + sysfs_remove_file(tz->kobj_thermal_map, >map_attr[i]->attr.attr); + /* Free map attributes */ + kfree(tz->map_attr[i]); + tz->map_attr[i] = NULL; +} + +static void remove_sensor_map_entry(struct thermal_zone *tz, + struct thermal_sensor *ts) +{ + int i; + + for (i = 0; i < MAX_MAPS_PER_ZONE; i++) { + if (tz->map[i] && !strnicmp(ts->name, tz->map[i]->sensor_name, + THERMAL_NAME_LENGTH)) { + __clean_map_entry(tz, i); + } + } +} + +static void remove_cdev_map_entry(struct thermal_zone *tz, + struct thermal_cooling_device *cdev) +{ + int i; + + for (i = 0; i < MAX_MAPS_PER_ZONE; i++) { + if (tz->map[i] && !strnicmp(cdev->type, tz->map[i]->cdev_name, + THERMAL_NAME_LENGTH)) { + __clean_map_entry(tz, i); + } + } +} + /* sys I/F for thermal zone */ #define to_thermal_zone(_dev) \ @@ -898,6 +933,52 @@ policy_show(struct device *dev, struct device_attribute *devattr, char *buf) } static ssize_t +map_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + int i, indx, ret = 0; + struct thermal_zone *tz; + struct thermal_map *map; + struct device *dev; + char *trip; + + /* +* For maps under /sys/class/thermal/zoneX/thermal_map/mapY: +* attr points to mapY +* kobj points to thermal_map +* kobj->parent points to zoneX +*/ + + /* Get zone pointer */ + dev = container_of(kobj->parent, struct device, kobj); + tz = to_zone(dev); + if (!tz) + return -EINVAL; + + sscanf(attr->attr.name, "map%d", ); + + if (indx < 0 || indx >= MAX_MAPS_PER_ZONE) + return -EINVAL; + + if (!tz->map[indx]) + return sprintf(buf, "\n"); + + map = tz->map[indx]; + + trip = (map->trip_type == THERMAL_TRIP_ACTIVE) ? + "active" : "passive"; + ret += sprintf(buf, "%s", trip); + ret += sprintf(buf + ret, " %s", map->sensor_name); + ret += sprintf(buf + ret, " %s", map->cdev_name); + ret += sprintf(buf + ret, " 0x%x", map->trip_mask); + + for (i = 0; i < map->num_weights; i++) + ret += sprintf(buf + ret, " %d", map->weights[i]); + + ret += sprintf(buf + ret, "\n"); + return ret; +} + +static ssize_t active_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { int i, indx, ret = 0; @@ -1676,8 +1757,10 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) mutex_lock(_list_lock); - for_each_thermal_zone(tmp_tz) + for_each_thermal_zone(tmp_tz) { remove_cdev_from_zone(tmp_tz, cdev); + remove_cdev_map_entry(tmp_tz, cdev); + } mutex_unlock(_list_lock); @@ -1931,12 +2014,19 @@ struct thermal_zone *create_thermal_zone(const char *name, void *devdata) if (!tz->kobj_thermal_trip) goto exit_name; + tz->kobj_thermal_map = kobject_create_and_add("thermal_map", + >device.kobj); + if (!tz->kobj_thermal_map) + goto exit_trip; + /* Add this zone to the global list of thermal zones */ mutex_lock(_list_lock); list_add_tail(>node, _zone_list); mutex_unlock(_list_lock); return tz; +exit_trip: + kobject_del(tz->kobj_thermal_trip); exit_name: device_remove_file(>device, _attr_zone_name); exit_unregister: @@ -2000,6 +2090,12 @@ void remove_thermal_zone(struct thermal_zone *tz) kobject_name(>cdevs[i]->device.kobj)); } + for (i = 0; i < MAX_MAPS_PER_ZONE; i++) + __clean_map_entry(tz, i); + + /* Remove /sys/class/thermal/zoneX/thermal_map */ + kobject_del(tz->kobj_thermal_map); + release_idr(_zone_idr, _idr_lock,
[PATCH 5/8] Thermal: Add 'thermal_map' sysfs node
This patch creates a thermal map sysfs node under /sys/class/thermal/thermal_zoneX/. This contains entries named map0, map1 .. mapN. Each map has the following space separated values: trip_type sensor_name cdev_name trip_mask weights Signed-off-by: Durgadoss R durgados...@intel.com --- drivers/thermal/thermal_sys.c | 149 - include/linux/thermal.h | 29 2 files changed, 176 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 29ec073..a3adc00 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -506,6 +506,41 @@ static void remove_cdev_from_zone(struct thermal_zone *tz, tz-cdev_indx--; } +static void __clean_map_entry(struct thermal_zone *tz, int i) +{ + tz-map[i] = NULL; + sysfs_remove_file(tz-kobj_thermal_map, tz-map_attr[i]-attr.attr); + /* Free map attributes */ + kfree(tz-map_attr[i]); + tz-map_attr[i] = NULL; +} + +static void remove_sensor_map_entry(struct thermal_zone *tz, + struct thermal_sensor *ts) +{ + int i; + + for (i = 0; i MAX_MAPS_PER_ZONE; i++) { + if (tz-map[i] !strnicmp(ts-name, tz-map[i]-sensor_name, + THERMAL_NAME_LENGTH)) { + __clean_map_entry(tz, i); + } + } +} + +static void remove_cdev_map_entry(struct thermal_zone *tz, + struct thermal_cooling_device *cdev) +{ + int i; + + for (i = 0; i MAX_MAPS_PER_ZONE; i++) { + if (tz-map[i] !strnicmp(cdev-type, tz-map[i]-cdev_name, + THERMAL_NAME_LENGTH)) { + __clean_map_entry(tz, i); + } + } +} + /* sys I/F for thermal zone */ #define to_thermal_zone(_dev) \ @@ -898,6 +933,52 @@ policy_show(struct device *dev, struct device_attribute *devattr, char *buf) } static ssize_t +map_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + int i, indx, ret = 0; + struct thermal_zone *tz; + struct thermal_map *map; + struct device *dev; + char *trip; + + /* +* For maps under /sys/class/thermal/zoneX/thermal_map/mapY: +* attr points to mapY +* kobj points to thermal_map +* kobj-parent points to zoneX +*/ + + /* Get zone pointer */ + dev = container_of(kobj-parent, struct device, kobj); + tz = to_zone(dev); + if (!tz) + return -EINVAL; + + sscanf(attr-attr.name, map%d, indx); + + if (indx 0 || indx = MAX_MAPS_PER_ZONE) + return -EINVAL; + + if (!tz-map[indx]) + return sprintf(buf, Unavailable\n); + + map = tz-map[indx]; + + trip = (map-trip_type == THERMAL_TRIP_ACTIVE) ? + active : passive; + ret += sprintf(buf, %s, trip); + ret += sprintf(buf + ret, %s, map-sensor_name); + ret += sprintf(buf + ret, %s, map-cdev_name); + ret += sprintf(buf + ret, 0x%x, map-trip_mask); + + for (i = 0; i map-num_weights; i++) + ret += sprintf(buf + ret, %d, map-weights[i]); + + ret += sprintf(buf + ret, \n); + return ret; +} + +static ssize_t active_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { int i, indx, ret = 0; @@ -1676,8 +1757,10 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) mutex_lock(zone_list_lock); - for_each_thermal_zone(tmp_tz) + for_each_thermal_zone(tmp_tz) { remove_cdev_from_zone(tmp_tz, cdev); + remove_cdev_map_entry(tmp_tz, cdev); + } mutex_unlock(zone_list_lock); @@ -1931,12 +2014,19 @@ struct thermal_zone *create_thermal_zone(const char *name, void *devdata) if (!tz-kobj_thermal_trip) goto exit_name; + tz-kobj_thermal_map = kobject_create_and_add(thermal_map, + tz-device.kobj); + if (!tz-kobj_thermal_map) + goto exit_trip; + /* Add this zone to the global list of thermal zones */ mutex_lock(zone_list_lock); list_add_tail(tz-node, thermal_zone_list); mutex_unlock(zone_list_lock); return tz; +exit_trip: + kobject_del(tz-kobj_thermal_trip); exit_name: device_remove_file(tz-device, dev_attr_zone_name); exit_unregister: @@ -2000,6 +2090,12 @@ void remove_thermal_zone(struct thermal_zone *tz) kobject_name(tz-cdevs[i]-device.kobj)); } + for (i = 0; i MAX_MAPS_PER_ZONE; i++) + __clean_map_entry(tz, i); + + /* Remove /sys/class/thermal/zoneX/thermal_map */ + kobject_del(tz-kobj_thermal_map); +