From patchwork Wed Feb 22 10:14:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Daniel Kachhap X-Patchwork-Id: 6879 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id D273023E48 for ; Wed, 22 Feb 2012 10:16:23 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 8CC9DA186A7 for ; Wed, 22 Feb 2012 10:16:23 +0000 (UTC) Received: by mail-iy0-f180.google.com with SMTP id z7so14190952iab.11 for ; Wed, 22 Feb 2012 02:16:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:x-forwarded-to:x-forwarded-for:delivered-to :received-spf:dkim-signature:sender:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references; bh=6yTiNC8+yriTFm0RUC7wnhKihn/GBL3tm+FwWVk6kbk=; b=GydwuePHn1N9sHyhhaJx8Z/AAMWBIdrsShwexTyooiJ/wuWh+N2s2/wI6sKHc/oUsY 5SOMzGkt3WNl/Cfj8WeD5Ww8MFhpCkFyIJRW4tfs3dSMg3k6fq+o1D3JKuQzhsqUx63Z IaIfJXrM2xX1q3GjayaiO5I4qOpAO6cDsNSog= MIME-Version: 1.0 Received: by 10.43.52.74 with SMTP id vl10mr25192178icb.55.1329905783348; Wed, 22 Feb 2012 02:16:23 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.11.10 with SMTP id r10csp130298ibr; Wed, 22 Feb 2012 02:16:22 -0800 (PST) Received: by 10.68.220.71 with SMTP id pu7mr4194852pbc.84.1329905782044; Wed, 22 Feb 2012 02:16:22 -0800 (PST) Received: from mail-pw0-f53.google.com (mail-pw0-f53.google.com [209.85.160.53]) by mx.google.com with ESMTPS id g9si28222995pbd.101.2012.02.22.02.16.21 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 22 Feb 2012 02:16:22 -0800 (PST) Received-SPF: pass (google.com: domain of amitdanielk@gmail.com designates 209.85.160.53 as permitted sender) client-ip=209.85.160.53; Authentication-Results: mx.google.com; spf=pass (google.com: domain of amitdanielk@gmail.com designates 209.85.160.53 as permitted sender) smtp.mail=amitdanielk@gmail.com; dkim=pass header.i=@gmail.com Received: by mail-pw0-f53.google.com with SMTP id rq13so10009753pbb.12 for ; Wed, 22 Feb 2012 02:16:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=6yTiNC8+yriTFm0RUC7wnhKihn/GBL3tm+FwWVk6kbk=; b=dVgV1lJCQgg+pkGVi4otCSMIAosn09bnltCVCTI/s+4FTk3VNn3MP/Hms35+JF/Dzv PiRGJxOHGyrOss3No1rfoRNN8qdK5w2KirC31CFo7wkPXjO5/FOf9vFSLWCdWrnVJ446 KxDx5SEq0SgLuNKkAf0Yup1WRxdALr0q8zRQ4= Received: by 10.68.219.10 with SMTP id pk10mr56100957pbc.87.1329905781066; Wed, 22 Feb 2012 02:16:21 -0800 (PST) Received: from localhost.localdomain ([115.113.119.130]) by mx.google.com with ESMTPS id r10sm30178210pbs.12.2012.02.22.02.16.17 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 22 Feb 2012 02:16:20 -0800 (PST) Sender: amit kachhap From: Amit Daniel Kachhap To: linux-pm@lists.linux-foundation.org Cc: linux-kernel@vger.kernel.org, mjg59@srcf.ucam.org, linux-acpi@vger.kernel.org, lenb@kernel.org, linaro-dev@lists.linaro.org, amit.kachhap@linaro.org, durgadoss.r@intel.com, rob.lee@linaro.org, patches@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 Message-Id: <1329905650-30161-5-git-send-email-amit.kachhap@linaro.org> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1329905650-30161-1-git-send-email-amit.kachhap@linaro.org> References: <1329905650-30161-1-git-send-email-amit.kachhap@linaro.org> X-Gm-Message-State: ALoCoQmjJX56mDIEM76hoH61Y48Tfq1B8s7C+V4Ck5eLrC/LncvjEIOXQpDTtO5rjSNaSXsW40iX 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 --- 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 #include #include +#include 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; };