[PATCH 5/8] Thermal: Add 'thermal_map' sysfs node

2012-12-18 Thread Durgadoss R
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

2012-12-18 Thread Durgadoss R
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);
+