diff options
author | Durgadoss R <durgadoss.r@intel.com> | 2012-09-18 01:35:01 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2012-11-05 01:00:07 -0500 |
commit | 4ccc5743ae70530f758c7d7ec9a0ca58878e584b (patch) | |
tree | bee1e566ee3cb7b80324a73e34087c06d5e4e66c /drivers/thermal | |
parent | dc76548269ca2c44e5ddc29db5c36188bc4f2234 (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/Kconfig | 6 | ||||
-rw-r--r-- | drivers/thermal/Makefile | 1 | ||||
-rw-r--r-- | drivers/thermal/fair_share.c | 133 |
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 | |||
59 | config 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 | |||
7 | obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o | 7 | obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o |
8 | obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o | 8 | obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o |
9 | obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o | 9 | obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o |
10 | obj-$(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 | */ | ||
36 | static 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 | |||
52 | static 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 | */ | ||
80 | int 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 | |||
111 | struct thermal_governor thermal_gov_fair_share = { | ||
112 | .name = "fair_share", | ||
113 | .throttle = fair_share_throttle, | ||
114 | .owner = THIS_MODULE, | ||
115 | }; | ||
116 | |||
117 | static int __init thermal_gov_fair_share_init(void) | ||
118 | { | ||
119 | return thermal_register_governor(&thermal_gov_fair_share); | ||
120 | } | ||
121 | |||
122 | static 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 */ | ||
128 | fs_initcall(thermal_gov_fair_share_init); | ||
129 | module_exit(thermal_gov_fair_share_exit); | ||
130 | |||
131 | MODULE_AUTHOR("Durgadoss R"); | ||
132 | MODULE_DESCRIPTION("A simple weight based thermal throttling governor"); | ||
133 | MODULE_LICENSE("GPL"); | ||