All of lore.kernel.org
 help / color / mirror / Atom feed
From: Durgadoss R <durgadoss.r@intel.com>
To: rui.zhang@intel.com, linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, hongbo.zhang@linaro.org,
	wni@nvidia.com, Durgadoss R <durgadoss.r@intel.com>
Subject: [PATCH 5/8] Thermal: Add 'thermal_map' sysfs node
Date: Tue, 18 Dec 2012 14:59:34 +0530	[thread overview]
Message-ID: <1355822977-4804-6-git-send-email-durgadoss.r@intel.com> (raw)
In-Reply-To: <1355822977-4804-1-git-send-email-durgadoss.r@intel.com>

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 <durgadoss.r@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);
+
 	release_idr(&thermal_zone_idr, &thermal_idr_lock, tz->id);
 	idr_destroy(&tz->idr);
 
@@ -2045,6 +2141,53 @@ struct thermal_sensor *get_sensor_by_name(const char *name)
 }
 EXPORT_SYMBOL(get_sensor_by_name);
 
+int add_map_entry(struct thermal_zone *tz, struct thermal_map *map)
+{
+	int ret, indx;
+
+	if (!tz || !map)
+		return -EINVAL;
+
+	mutex_lock(&zone_list_lock);
+
+	for (indx = 0; indx < MAX_MAPS_PER_ZONE; indx++) {
+		if (tz->map[indx] == NULL)
+			break;
+	}
+
+	if (indx >= MAX_MAPS_PER_ZONE) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	tz->map_attr[indx] = kzalloc(sizeof(struct thermal_map_attr),
+					GFP_KERNEL);
+	if (!tz->map_attr[indx]) {
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	sprintf(tz->map_attr[indx]->name, "map%d", indx);
+
+	tz->map_attr[indx]->attr.attr.name = tz->map_attr[indx]->name;
+	tz->map_attr[indx]->attr.attr.mode = S_IRUGO;
+	tz->map_attr[indx]->attr.show = map_show;
+
+	sysfs_attr_init(&tz->map_attr[indx]->attr.attr);
+	ret = sysfs_create_file(tz->kobj_thermal_map,
+				&tz->map_attr[indx]->attr.attr);
+	if (ret) {
+		kfree(tz->map_attr[indx]);
+		goto exit;
+	}
+
+	tz->map[indx] = map;
+exit:
+	mutex_unlock(&zone_list_lock);
+	return ret;
+}
+EXPORT_SYMBOL(add_map_entry);
+
 int add_sensor_to_zone(struct thermal_zone *tz, struct thermal_sensor *ts)
 {
 	int ret;
@@ -2251,8 +2394,10 @@ void thermal_sensor_unregister(struct thermal_sensor *ts)
 
 	mutex_lock(&zone_list_lock);
 
-	for_each_thermal_zone(tz)
+	for_each_thermal_zone(tz) {
 		remove_sensor_from_zone(tz, ts);
+		remove_sensor_map_entry(tz, ts);
+	}
 
 	mutex_unlock(&zone_list_lock);
 
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 8372f05..581dc87 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -53,6 +53,9 @@
 
 #define MAX_CDEVS_PER_ZONE		5
 
+/* If we map each sensor with every possible cdev for a zone */
+#define MAX_MAPS_PER_ZONE	(MAX_SENSORS_PER_ZONE * MAX_CDEVS_PER_ZONE)
+
 struct thermal_sensor;
 struct thermal_zone_device;
 struct thermal_cooling_device;
@@ -158,6 +161,21 @@ struct thermal_attr {
 	char name[THERMAL_NAME_LENGTH];
 };
 
+struct thermal_map_attr {
+	struct kobj_attribute attr;
+	char name[THERMAL_NAME_LENGTH];
+};
+
+struct thermal_map {
+	enum thermal_trip_type trip_type;
+	char cdev_name[THERMAL_NAME_LENGTH];
+	char sensor_name[THERMAL_NAME_LENGTH];
+
+	int trip_mask;
+	int num_weights;
+	int *weights;
+};
+
 /*
  * This structure defines the trip points for a sensor.
  * The actual values for these trip points come from
@@ -249,6 +267,15 @@ struct thermal_zone {
 	struct kobject *kobj_thermal_trip;
 	struct kobject *kobj_trip[MAX_SENSORS_PER_ZONE];
 	struct thermal_trip_point *sensor_trip[MAX_SENSORS_PER_ZONE];
+
+	/*
+	 * Thermal map information:
+	 * kobj_thermal_map: /sys/class/thermal/zoneX/thermal_map
+	 * map_attr: /sys/class/thermal/zoneX/thermal_map/mapY
+	 */
+	struct kobject *kobj_thermal_map;
+	struct thermal_map_attr *map_attr[MAX_MAPS_PER_ZONE];
+	struct thermal_map *map[MAX_MAPS_PER_ZONE];
 };
 
 /* Structure that holds thermal governor information */
@@ -332,6 +359,8 @@ int add_cdev_to_zone(struct thermal_zone *, struct thermal_cooling_device *);
 int add_sensor_trip_info(struct thermal_zone *, struct thermal_sensor *,
 			struct thermal_trip_point *);
 
+int add_map_entry(struct thermal_zone *, struct thermal_map *);
+
 #ifdef CONFIG_NET
 extern int thermal_generate_netlink_event(u32 orig, enum events event);
 #else
-- 
1.7.9.5


  parent reply	other threads:[~2012-12-18  9:36 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-18  9:29 [PATCH 0/8] Thermal Framework Enhancements Durgadoss R
2012-12-18  9:29 ` [PATCH 1/8] Thermal: Create sensor level APIs Durgadoss R
2012-12-18 11:13   ` Joe Perches
2012-12-18  9:29 ` [PATCH 2/8] Thermal: Create zone " Durgadoss R
2012-12-18 11:30   ` Joe Perches
2012-12-20  6:02     ` R, Durgadoss
2012-12-18  9:29 ` [PATCH 3/8] Thermal: Add APIs to bind cdev to new zone structure Durgadoss R
2012-12-25  8:30   ` Wei Ni
2012-12-26  3:30     ` R, Durgadoss
2012-12-18  9:29 ` [PATCH 4/8] Thermal: Add Thermal_trip sysfs node Durgadoss R
2012-12-20  5:42   ` Greg KH
2012-12-20  7:52     ` R, Durgadoss
2012-12-20 16:12       ` Greg KH
2012-12-20 16:25         ` R, Durgadoss
2012-12-20 16:38           ` Greg KH
2012-12-20 16:58             ` R, Durgadoss
2012-12-20 17:51               ` Greg KH
2012-12-20 18:12                 ` R, Durgadoss
2012-12-27  7:01   ` Hongbo Zhang
2012-12-18  9:29 ` Durgadoss R [this message]
2012-12-18  9:29 ` [PATCH 6/8] Thermal: Add Documentation to new APIs Durgadoss R
2012-12-18  9:29 ` [PATCH 7/8] Thermal: Make PER_ZONE values configurable Durgadoss R
2012-12-18  9:29 ` [PATCH 8/8] Thermal: Dummy driver used for testing Durgadoss R
2012-12-25  8:38   ` Wei Ni
2012-12-26  3:29     ` R, Durgadoss
2012-12-20  5:37 ` [PATCH 0/8] Thermal Framework Enhancements Greg KH
2012-12-20  6:16   ` R, Durgadoss
2012-12-21  8:05 ` Wei Ni
2012-12-21  8:30   ` R, Durgadoss
2012-12-21  8:46     ` Hongbo Zhang
2012-12-21  9:17       ` R, Durgadoss

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1355822977-4804-6-git-send-email-durgadoss.r@intel.com \
    --to=durgadoss.r@intel.com \
    --cc=hongbo.zhang@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rui.zhang@intel.com \
    --cc=wni@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.