linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Amit Daniel Kachhap <amit.kachhap@linaro.org>
To: linux-pm@lists.linux-foundation.org
Cc: linaro-dev@lists.linaro.org, patches@linaro.org,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	rob.lee@linaro.org
Subject: [PATCH 4/4] thermal: Add support to report cooling statistics achieved by cooling devices
Date: Wed, 22 Feb 2012 15:44:10 +0530	[thread overview]
Message-ID: <1329905650-30161-5-git-send-email-amit.kachhap@linaro.org> (raw)
In-Reply-To: <1329905650-30161-1-git-send-email-amit.kachhap@linaro.org>

Add a debugfs node code to report effective cooling of all cooling devices
attached to each trip points of a thermal zone. The cooling data reported
will be absolute if the higher temperature trip points are arranged first
otherwise the cooling stats is the cumulative effect of the earlier
invoked cooling handlers.

The basic assumption is that cooling devices will bring down the temperature
in a symmetric manner and those statistics can be stored back and used for
further tuning of the system.

e.g.
cat /sys/kernel/debug/thermal/thermal_zone0/trip_0_cooling
6000
Here trip_0 cooling devices produce 6 degree Celsius temperature drop.

Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
---
 drivers/thermal/thermal_sys.c |  120 +++++++++++++++++++++++++++++++++++++++++
 include/linux/thermal.h       |   13 +++++
 2 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index d4c9b20..9784551 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -34,6 +34,7 @@
 #include <linux/reboot.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
+#include <linux/debugfs.h>
 
 MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
@@ -93,6 +94,97 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
 		mutex_unlock(lock);
 }
 
+static void update_cooling_stats(struct thermal_zone_device *tz, long cur_temp)
+{
+	int count, max_index, cur_interval, used_data = 0;
+	long trip_temp, max_temp = 0, cool_temp;
+
+	if (cur_temp >= tz->last_temperature)
+		return;
+
+	/* find the trip according to last temperature */
+	for (count = 0; count < tz->trips; count++) {
+		tz->ops->get_trip_temp(tz, count, &trip_temp);
+		if (tz->last_temperature >= trip_temp) {
+			if (max_temp < trip_temp) {
+				max_temp = trip_temp;
+				max_index = count;
+			}
+		}
+	}
+
+	if (!max_temp) {
+		tz->last_trip_level = -1;
+		return;
+	}
+
+	cur_interval = tz->stat[max_index].interval_ptr;
+	cool_temp = tz->last_temperature - cur_temp;
+
+	if (tz->last_trip_level != max_index) {
+		if (++cur_interval == INTERVAL_HISTORY)
+			cur_interval = 0;
+		tz->stat[max_index].cool_temp[cur_interval] = cool_temp;
+		tz->stat[max_index].interval_ptr = cur_interval;
+		tz->last_trip_level = max_index;
+	} else {
+		tz->stat[max_index].cool_temp[cur_interval] += cool_temp;
+	}
+
+	/*Average out the cooling for this trip level*/
+	for (count = 0; count < INTERVAL_HISTORY; count++) {
+		if (tz->stat[max_index].cool_temp[count] > 0) {
+			tz->stat[max_index].avg_cool +=
+					tz->stat[max_index].cool_temp[count];
+			used_data++;
+		}
+	}
+	if (used_data > 1)
+		tz->stat[max_index].avg_cool =
+				tz->stat[max_index].avg_cool / used_data;
+	return;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+/* debugfs support to debug cooling info per trip type */
+static struct dentry *thermal_debugfs_root;
+static int thermal_register_debugfs(struct thermal_zone_device *tz)
+{
+	char name[THERMAL_NAME_LENGTH];
+	int count = 0, err = 0;
+	struct dentry *d;
+
+	if (thermal_debugfs_root == NULL)
+		return -EINVAL;
+
+	sprintf(name, "thermal_zone%d", tz->id);
+	d = debugfs_create_dir(name, thermal_debugfs_root);
+	if (!d)
+		return -ENOMEM;
+	tz->d_entry = d;
+	for (count = 0; count < tz->trips; count++) {
+		sprintf(name, "trip_%d_cooling", count);
+		d = debugfs_create_u32(name, S_IRUGO, tz->d_entry,
+					(u32 *)&tz->stat[count].avg_cool);
+		if (!d) {
+			err = -ENOMEM;
+			goto err_debugfs;
+		}
+	}
+	return 0;
+
+err_debugfs:
+	debugfs_remove_recursive(tz->d_entry);
+	return err;
+}
+
+static void thermal_unregister_debugfs(struct thermal_zone_device *tz)
+{
+	debugfs_remove_recursive(tz->d_entry);
+}
+
+#endif
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1051,6 +1143,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 		goto leave;
 	}
 
+	update_cooling_stats(tz, temp);
+
 	for (count = 0; count < tz->trips; count++) {
 		tz->ops->get_trip_type(tz, count, &trip_type);
 		tz->ops->get_trip_temp(tz, count, &trip_temp);
@@ -1211,6 +1305,7 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 	tz->tc2 = tc2;
 	tz->passive_delay = passive_delay;
 	tz->polling_delay = polling_delay;
+	tz->last_trip_level = -1;
 
 	dev_set_name(&tz->device, "thermal_zone%d", tz->id);
 	result = device_register(&tz->device);
@@ -1220,6 +1315,13 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 		return ERR_PTR(result);
 	}
 
+	/*Allocate variables for cooling stats*/
+	tz->stat  = devm_kzalloc(&tz->device,
+				sizeof(struct thermal_cooling_stats) * trips,
+				GFP_KERNEL);
+	if (!tz->stat)
+		goto unregister;
+
 	/* sys I/F */
 	if (type) {
 		result = device_create_file(&tz->device, &dev_attr_type);
@@ -1257,6 +1359,12 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 	if (result)
 		goto unregister;
 
+#if defined(CONFIG_DEBUG_FS)
+	result = thermal_register_debugfs(tz);
+	if (result)
+		goto unregister;
+#endif
+
 	mutex_lock(&thermal_list_lock);
 	list_add_tail(&tz->node, &thermal_tz_list);
 	if (ops->bind)
@@ -1321,6 +1429,10 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 	for (count = 0; count < tz->trips; count++)
 		TRIP_POINT_ATTR_REMOVE(&tz->device, count);
 
+#if defined(CONFIG_DEBUG_FS)
+	thermal_unregister_debugfs(tz);
+#endif
+
 	thermal_remove_hwmon_sysfs(tz);
 	release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
 	idr_destroy(&tz->idr);
@@ -1440,6 +1552,11 @@ static int __init thermal_init(void)
 		mutex_destroy(&thermal_list_lock);
 	}
 	result = genetlink_init();
+#if defined(CONFIG_DEBUG_FS)
+	thermal_debugfs_root = debugfs_create_dir("thermal", NULL);
+	if (!thermal_debugfs_root)
+		result = -ENOMEM;
+#endif
 	return result;
 }
 
@@ -1451,6 +1568,9 @@ static void __exit thermal_exit(void)
 	mutex_destroy(&thermal_idr_lock);
 	mutex_destroy(&thermal_list_lock);
 	genetlink_exit();
+#if defined(CONFIG_DEBUG_FS)
+	debugfs_remove_recursive(thermal_debugfs_root);
+#endif
 }
 
 fs_initcall(thermal_init);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 8df901f..6f15f85 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -73,6 +73,14 @@ struct thermal_cooling_device_ops {
 #define THERMAL_TRIPS_NONE -1
 #define THERMAL_MAX_TRIPS 12
 #define THERMAL_NAME_LENGTH 20
+#define INTERVAL_HISTORY 12
+
+struct thermal_cooling_stats {
+	int cool_temp[INTERVAL_HISTORY];
+	int interval_ptr;
+	int avg_cool;
+};
+
 struct thermal_cooling_device {
 	int id;
 	char type[THERMAL_NAME_LENGTH];
@@ -103,6 +111,11 @@ struct thermal_zone_device {
 	struct list_head cooling_devices;
 	struct idr idr;
 	struct mutex lock;	/* protect cooling devices list */
+	struct thermal_cooling_stats *stat;
+	int last_trip_level;
+#if defined(CONFIG_DEBUG_FS)
+	struct dentry *d_entry;
+#endif
 	struct list_head node;
 	struct delayed_work poll_queue;
 };
-- 
1.7.1

  parent reply	other threads:[~2012-02-22 10:14 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-22 10:14 [PATCH 0/4] thermal: Adding generic cpu cooling devices Amit Daniel Kachhap
2012-02-22 10:14 ` [PATCH 1/4] thermal: Add a new trip type to use cooling device instance number Amit Daniel Kachhap
2012-02-23  6:46   ` R, Durgadoss
2012-02-23 11:20     ` Amit Kachhap
2012-04-03 14:15       ` [linux-pm] " Eduardo Valentin
2012-04-04  4:23         ` Amit Kachhap
2012-04-04  6:27           ` Eduardo Valentin
2012-02-22 10:14 ` [PATCH 2/4] thermal: Add generic cpufreq cooling implementation Amit Daniel Kachhap
     [not found]   ` <1329905650-30161-3-git-send-email-amit.kachhap-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2012-02-22 10:58     ` Peter Meerwald
2012-02-24 11:04   ` R, Durgadoss
2012-02-27  4:32     ` Amit Kachhap
2012-03-11  4:11   ` [linux-pm] " Sundar
2012-03-13  5:07     ` Amit Kachhap
2012-03-13  9:45       ` [linux-pm] " Sundar
2012-03-13 10:00         ` Amit Kucheria
2012-03-13 10:14           ` Sundar
2012-03-13 10:52             ` Amit Kachhap
2012-03-13 11:43               ` Sundar
2012-02-22 10:14 ` [PATCH 3/4] thermal: Add generic cpuhotplug " Amit Daniel Kachhap
2012-02-22 10:14 ` Amit Daniel Kachhap [this message]
2012-02-22 15:45 ` [linux-pm] [PATCH 0/4] thermal: Adding generic cpu cooling devices Eduardo Valentin

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=1329905650-30161-5-git-send-email-amit.kachhap@linaro.org \
    --to=amit.kachhap@linaro.org \
    --cc=linaro-dev@lists.linaro.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=patches@linaro.org \
    --cc=rob.lee@linaro.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).