Root/
1 | /* |
2 | * step_wise.c - A step-by-step Thermal throttling 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 | * If the temperature is higher than a trip point, |
34 | * a. if the trend is THERMAL_TREND_RAISING, use higher cooling |
35 | * state for this trip point |
36 | * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling |
37 | * state for this trip point |
38 | * c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit |
39 | * for this trip point |
40 | * d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit |
41 | * for this trip point |
42 | * If the temperature is lower than a trip point, |
43 | * a. if the trend is THERMAL_TREND_RAISING, do nothing |
44 | * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling |
45 | * state for this trip point, if the cooling state already |
46 | * equals lower limit, deactivate the thermal instance |
47 | * c. if the trend is THERMAL_TREND_RAISE_FULL, do nothing |
48 | * d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit, |
49 | * if the cooling state already equals lower limit, |
50 | * deactive the thermal instance |
51 | */ |
52 | static unsigned long get_target_state(struct thermal_instance *instance, |
53 | enum thermal_trend trend, bool throttle) |
54 | { |
55 | struct thermal_cooling_device *cdev = instance->cdev; |
56 | unsigned long cur_state; |
57 | |
58 | cdev->ops->get_cur_state(cdev, &cur_state); |
59 | |
60 | switch (trend) { |
61 | case THERMAL_TREND_RAISING: |
62 | if (throttle) |
63 | cur_state = cur_state < instance->upper ? |
64 | (cur_state + 1) : instance->upper; |
65 | break; |
66 | case THERMAL_TREND_RAISE_FULL: |
67 | if (throttle) |
68 | cur_state = instance->upper; |
69 | break; |
70 | case THERMAL_TREND_DROPPING: |
71 | if (cur_state == instance->lower) { |
72 | if (!throttle) |
73 | cur_state = -1; |
74 | } else |
75 | cur_state -= 1; |
76 | break; |
77 | case THERMAL_TREND_DROP_FULL: |
78 | if (cur_state == instance->lower) { |
79 | if (!throttle) |
80 | cur_state = -1; |
81 | } else |
82 | cur_state = instance->lower; |
83 | break; |
84 | default: |
85 | break; |
86 | } |
87 | |
88 | return cur_state; |
89 | } |
90 | |
91 | static void update_passive_instance(struct thermal_zone_device *tz, |
92 | enum thermal_trip_type type, int value) |
93 | { |
94 | /* |
95 | * If value is +1, activate a passive instance. |
96 | * If value is -1, deactivate a passive instance. |
97 | */ |
98 | if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE) |
99 | tz->passive += value; |
100 | } |
101 | |
102 | static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) |
103 | { |
104 | long trip_temp; |
105 | enum thermal_trip_type trip_type; |
106 | enum thermal_trend trend; |
107 | struct thermal_instance *instance; |
108 | bool throttle = false; |
109 | int old_target; |
110 | |
111 | if (trip == THERMAL_TRIPS_NONE) { |
112 | trip_temp = tz->forced_passive; |
113 | trip_type = THERMAL_TRIPS_NONE; |
114 | } else { |
115 | tz->ops->get_trip_temp(tz, trip, &trip_temp); |
116 | tz->ops->get_trip_type(tz, trip, &trip_type); |
117 | } |
118 | |
119 | trend = get_tz_trend(tz, trip); |
120 | |
121 | if (tz->temperature >= trip_temp) |
122 | throttle = true; |
123 | |
124 | mutex_lock(&tz->lock); |
125 | |
126 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { |
127 | if (instance->trip != trip) |
128 | continue; |
129 | |
130 | old_target = instance->target; |
131 | instance->target = get_target_state(instance, trend, throttle); |
132 | |
133 | /* Activate a passive thermal instance */ |
134 | if (old_target == THERMAL_NO_TARGET && |
135 | instance->target != THERMAL_NO_TARGET) |
136 | update_passive_instance(tz, trip_type, 1); |
137 | /* Deactivate a passive thermal instance */ |
138 | else if (old_target != THERMAL_NO_TARGET && |
139 | instance->target == THERMAL_NO_TARGET) |
140 | update_passive_instance(tz, trip_type, -1); |
141 | |
142 | |
143 | instance->cdev->updated = false; /* cdev needs update */ |
144 | } |
145 | |
146 | mutex_unlock(&tz->lock); |
147 | } |
148 | |
149 | /** |
150 | * step_wise_throttle - throttles devices asscciated with the given zone |
151 | * @tz - thermal_zone_device |
152 | * @trip - the trip point |
153 | * @trip_type - type of the trip point |
154 | * |
155 | * Throttling Logic: This uses the trend of the thermal zone to throttle. |
156 | * If the thermal zone is 'heating up' this throttles all the cooling |
157 | * devices associated with the zone and its particular trip point, by one |
158 | * step. If the zone is 'cooling down' it brings back the performance of |
159 | * the devices by one step. |
160 | */ |
161 | static int step_wise_throttle(struct thermal_zone_device *tz, int trip) |
162 | { |
163 | struct thermal_instance *instance; |
164 | |
165 | thermal_zone_trip_update(tz, trip); |
166 | |
167 | if (tz->forced_passive) |
168 | thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE); |
169 | |
170 | mutex_lock(&tz->lock); |
171 | |
172 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) |
173 | thermal_cdev_update(instance->cdev); |
174 | |
175 | mutex_unlock(&tz->lock); |
176 | |
177 | return 0; |
178 | } |
179 | |
180 | static struct thermal_governor thermal_gov_step_wise = { |
181 | .name = "step_wise", |
182 | .throttle = step_wise_throttle, |
183 | .owner = THIS_MODULE, |
184 | }; |
185 | |
186 | static int __init thermal_gov_step_wise_init(void) |
187 | { |
188 | return thermal_register_governor(&thermal_gov_step_wise); |
189 | } |
190 | |
191 | static void __exit thermal_gov_step_wise_exit(void) |
192 | { |
193 | thermal_unregister_governor(&thermal_gov_step_wise); |
194 | } |
195 | |
196 | /* This should load after thermal framework */ |
197 | fs_initcall(thermal_gov_step_wise_init); |
198 | module_exit(thermal_gov_step_wise_exit); |
199 | |
200 | MODULE_AUTHOR("Durgadoss R"); |
201 | MODULE_DESCRIPTION("A step-by-step thermal throttling governor"); |
202 | MODULE_LICENSE("GPL"); |
203 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9