aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorDurgadoss R <durgadoss.r@intel.com>2012-09-18 01:35:01 -0400
committerZhang Rui <rui.zhang@intel.com>2012-11-05 01:00:07 -0500
commit4ccc5743ae70530f758c7d7ec9a0ca58878e584b (patch)
treebee1e566ee3cb7b80324a73e34087c06d5e4e66c /drivers/thermal
parentdc76548269ca2c44e5ddc29db5c36188bc4f2234 (diff)
Thermal: Introduce fair_share thermal governor
This patch introduces a simple 'weight' based governor named fair_share governor. Whenever the thermal framework gets notified of the trip point violation, this governor (if configured), throttles the cooling devices associated with a thermal zone. This mapping between a thermal zone and a cooling device and the effectiveness of cooling are provided in the platform layer. Signed-off-by: Durgadoss R <durgadoss.r@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/Kconfig6
-rw-r--r--drivers/thermal/Makefile1
-rw-r--r--drivers/thermal/fair_share.c133
3 files changed, 140 insertions, 0 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index e1cb6bd75f60..84b0f0382e5d 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -55,3 +55,9 @@ config EXYNOS_THERMAL
55 help 55 help
56 If you say yes here you get support for TMU (Thermal Managment 56 If you say yes here you get support for TMU (Thermal Managment
57 Unit) on SAMSUNG EXYNOS series of SoC. 57 Unit) on SAMSUNG EXYNOS series of SoC.
58
59config FAIR_SHARE
60 bool "Fair-share thermal governor"
61 depends on THERMAL
62 help
63 Enable this to manage platform thermals using fair-share governor.
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 885550dc64b7..30540dde4080 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
7obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 7obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
8obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o 8obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
9obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o 9obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
10obj-$(CONFIG_FAIR_SHARE) += fair_share.o
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
new file mode 100644
index 000000000000..5d3a7a3e6a7a
--- /dev/null
+++ b/drivers/thermal/fair_share.c
@@ -0,0 +1,133 @@
1/*
2 * fair_share.c - A simple weight based Thermal governor
3 *
4 * Copyright (C) 2012 Intel Corp
5 * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/module.h>
28#include <linux/thermal.h>
29
30#include "thermal_core.h"
31
32/**
33 * get_trip_level: - obtains the current trip level for a zone
34 * @tz: thermal zone device
35 */
36static int get_trip_level(struct thermal_zone_device *tz)
37{
38 int count = 0;
39 unsigned long trip_temp;
40
41 if (tz->trips == 0 || !tz->ops->get_trip_temp)
42 return 0;
43
44 for (count = 0; count < tz->trips; count++) {
45 tz->ops->get_trip_temp(tz, count, &trip_temp);
46 if (tz->temperature < trip_temp)
47 break;
48 }
49 return count;
50}
51
52static long get_target_state(struct thermal_zone_device *tz,
53 struct thermal_cooling_device *cdev, int weight, int level)
54{
55 unsigned long max_state;
56
57 cdev->ops->get_max_state(cdev, &max_state);
58
59 return (long)(weight * level * max_state) / (100 * tz->trips);
60}
61
62/**
63 * fair_share_throttle - throttles devices asscciated with the given zone
64 * @tz - thermal_zone_device
65 *
66 * Throttling Logic: This uses three parameters to calculate the new
67 * throttle state of the cooling devices associated with the given zone.
68 *
69 * Parameters used for Throttling:
70 * P1. max_state: Maximum throttle state exposed by the cooling device.
71 * P2. weight[i]/100:
72 * How 'effective' the 'i'th device is, in cooling the given zone.
73 * P3. cur_trip_level/max_no_of_trips:
74 * This describes the extent to which the devices should be throttled.
75 * We do not want to throttle too much when we trip a lower temperature,
76 * whereas the throttling is at full swing if we trip critical levels.
77 * (Heavily assumes the trip points are in ascending order)
78 * new_state of cooling device = P3 * P2 * P1
79 */
80int fair_share_throttle(struct thermal_zone_device *tz, int trip)
81{
82 const struct thermal_zone_params *tzp;
83 struct thermal_cooling_device *cdev;
84 struct thermal_instance *instance;
85 int i;
86 int cur_trip_level = get_trip_level(tz);
87
88 if (!tz->tzp || !tz->tzp->tbp)
89 return -EINVAL;
90
91 tzp = tz->tzp;
92
93 for (i = 0; i < tzp->num_tbps; i++) {
94 if (!tzp->tbp[i].cdev)
95 continue;
96
97 cdev = tzp->tbp[i].cdev;
98 instance = get_thermal_instance(tz, cdev, trip);
99 if (!instance)
100 continue;
101
102 instance->target = get_target_state(tz, cdev,
103 tzp->tbp[i].weight, cur_trip_level);
104
105 instance->cdev->updated = false;
106 thermal_cdev_update(cdev);
107 }
108 return 0;
109}
110
111struct thermal_governor thermal_gov_fair_share = {
112 .name = "fair_share",
113 .throttle = fair_share_throttle,
114 .owner = THIS_MODULE,
115};
116
117static int __init thermal_gov_fair_share_init(void)
118{
119 return thermal_register_governor(&thermal_gov_fair_share);
120}
121
122static void __exit thermal_gov_fair_share_exit(void)
123{
124 thermal_unregister_governor(&thermal_gov_fair_share);
125}
126
127/* This should load after thermal framework */
128fs_initcall(thermal_gov_fair_share_init);
129module_exit(thermal_gov_fair_share_exit);
130
131MODULE_AUTHOR("Durgadoss R");
132MODULE_DESCRIPTION("A simple weight based thermal throttling governor");
133MODULE_LICENSE("GPL");