Blame view

drivers/thermal/step_wise.c 5.65 KB
e151a202a   Durgadoss R   Thermal: Introduc...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   *  step_wise.c - A step-by-step Thermal throttling governor
   *
   *  Copyright (C) 2012 Intel Corp
   *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
   *
   *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; version 2 of the License.
   *
   *  This program is distributed in the hope that it will be useful, but
   *  WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
e151a202a   Durgadoss R   Thermal: Introduc...
24
25
26
27
28
29
30
31
32
33
  #include <linux/thermal.h>
  
  #include "thermal_core.h"
  
  /*
   * If the temperature is higher than a trip point,
   *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
   *       state for this trip point
   *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
   *       state for this trip point
3dbfff3df   Zhang Rui   Introduce THERMAL...
34
35
36
37
38
39
40
41
42
43
44
45
46
   *    c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit
   *       for this trip point
   *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit
   *       for this trip point
   * If the temperature is lower than a trip point,
   *    a. if the trend is THERMAL_TREND_RAISING, do nothing
   *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
   *       state for this trip point, if the cooling state already
   *       equals lower limit, deactivate the thermal instance
   *    c. if the trend is THERMAL_TREND_RAISE_FULL, do nothing
   *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit,
   *       if the cooling state already equals lower limit,
   *       deactive the thermal instance
e151a202a   Durgadoss R   Thermal: Introduc...
47
48
   */
  static unsigned long get_target_state(struct thermal_instance *instance,
3dbfff3df   Zhang Rui   Introduce THERMAL...
49
  				enum thermal_trend trend, bool throttle)
e151a202a   Durgadoss R   Thermal: Introduc...
50
51
52
53
54
  {
  	struct thermal_cooling_device *cdev = instance->cdev;
  	unsigned long cur_state;
  
  	cdev->ops->get_cur_state(cdev, &cur_state);
3dbfff3df   Zhang Rui   Introduce THERMAL...
55
56
  	switch (trend) {
  	case THERMAL_TREND_RAISING:
e79fe642c   Andrew Bresticker   thermal: step_wis...
57
  		if (throttle) {
3dbfff3df   Zhang Rui   Introduce THERMAL...
58
59
  			cur_state = cur_state < instance->upper ?
  				    (cur_state + 1) : instance->upper;
e79fe642c   Andrew Bresticker   thermal: step_wis...
60
61
62
  			if (cur_state < instance->lower)
  				cur_state = instance->lower;
  		}
3dbfff3df   Zhang Rui   Introduce THERMAL...
63
64
65
66
67
68
69
70
71
  		break;
  	case THERMAL_TREND_RAISE_FULL:
  		if (throttle)
  			cur_state = instance->upper;
  		break;
  	case THERMAL_TREND_DROPPING:
  		if (cur_state == instance->lower) {
  			if (!throttle)
  				cur_state = -1;
e79fe642c   Andrew Bresticker   thermal: step_wis...
72
  		} else {
3dbfff3df   Zhang Rui   Introduce THERMAL...
73
  			cur_state -= 1;
e79fe642c   Andrew Bresticker   thermal: step_wis...
74
75
76
  			if (cur_state > instance->upper)
  				cur_state = instance->upper;
  		}
3dbfff3df   Zhang Rui   Introduce THERMAL...
77
78
79
80
81
82
83
84
85
86
  		break;
  	case THERMAL_TREND_DROP_FULL:
  		if (cur_state == instance->lower) {
  			if (!throttle)
  				cur_state = -1;
  		} else
  			cur_state = instance->lower;
  		break;
  	default:
  		break;
e151a202a   Durgadoss R   Thermal: Introduc...
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  	}
  
  	return cur_state;
  }
  
  static void update_passive_instance(struct thermal_zone_device *tz,
  				enum thermal_trip_type type, int value)
  {
  	/*
  	 * If value is +1, activate a passive instance.
  	 * If value is -1, deactivate a passive instance.
  	 */
  	if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE)
  		tz->passive += value;
  }
e151a202a   Durgadoss R   Thermal: Introduc...
102
103
104
105
106
  static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
  {
  	long trip_temp;
  	enum thermal_trip_type trip_type;
  	enum thermal_trend trend;
b8bb6cb99   Zhang Rui   step_wise: Unify ...
107
108
109
  	struct thermal_instance *instance;
  	bool throttle = false;
  	int old_target;
e151a202a   Durgadoss R   Thermal: Introduc...
110
111
112
113
114
115
116
117
118
119
  
  	if (trip == THERMAL_TRIPS_NONE) {
  		trip_temp = tz->forced_passive;
  		trip_type = THERMAL_TRIPS_NONE;
  	} else {
  		tz->ops->get_trip_temp(tz, trip, &trip_temp);
  		tz->ops->get_trip_type(tz, trip, &trip_type);
  	}
  
  	trend = get_tz_trend(tz, trip);
b8bb6cb99   Zhang Rui   step_wise: Unify ...
120
121
  	if (tz->temperature >= trip_temp)
  		throttle = true;
e151a202a   Durgadoss R   Thermal: Introduc...
122
  	mutex_lock(&tz->lock);
b8bb6cb99   Zhang Rui   step_wise: Unify ...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
  		if (instance->trip != trip)
  			continue;
  
  		old_target = instance->target;
  		instance->target = get_target_state(instance, trend, throttle);
  
  		/* Activate a passive thermal instance */
  		if (old_target == THERMAL_NO_TARGET &&
  			instance->target != THERMAL_NO_TARGET)
  			update_passive_instance(tz, trip_type, 1);
  		/* Deactivate a passive thermal instance */
  		else if (old_target != THERMAL_NO_TARGET &&
  			instance->target == THERMAL_NO_TARGET)
  			update_passive_instance(tz, trip_type, -1);
  
  
  		instance->cdev->updated = false; /* cdev needs update */
  	}
e151a202a   Durgadoss R   Thermal: Introduc...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
  
  	mutex_unlock(&tz->lock);
  }
  
  /**
   * step_wise_throttle - throttles devices asscciated with the given zone
   * @tz - thermal_zone_device
   * @trip - the trip point
   * @trip_type - type of the trip point
   *
   * Throttling Logic: This uses the trend of the thermal zone to throttle.
   * If the thermal zone is 'heating up' this throttles all the cooling
   * devices associated with the zone and its particular trip point, by one
   * step. If the zone is 'cooling down' it brings back the performance of
   * the devices by one step.
   */
b88a49770   Sachin Kamat   thermal: step_wis...
158
  static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
e151a202a   Durgadoss R   Thermal: Introduc...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  {
  	struct thermal_instance *instance;
  
  	thermal_zone_trip_update(tz, trip);
  
  	if (tz->forced_passive)
  		thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE);
  
  	mutex_lock(&tz->lock);
  
  	list_for_each_entry(instance, &tz->thermal_instances, tz_node)
  		thermal_cdev_update(instance->cdev);
  
  	mutex_unlock(&tz->lock);
  
  	return 0;
  }
b88a49770   Sachin Kamat   thermal: step_wis...
176
  static struct thermal_governor thermal_gov_step_wise = {
1f53ef17d   Zhang Rui   Thermal: Fix DEFA...
177
  	.name		= "step_wise",
e151a202a   Durgadoss R   Thermal: Introduc...
178
  	.throttle	= step_wise_throttle,
e151a202a   Durgadoss R   Thermal: Introduc...
179
  };
80a26a5c2   Zhang Rui   Thermal: build th...
180
  int thermal_gov_step_wise_register(void)
e151a202a   Durgadoss R   Thermal: Introduc...
181
182
183
  {
  	return thermal_register_governor(&thermal_gov_step_wise);
  }
80a26a5c2   Zhang Rui   Thermal: build th...
184
  void thermal_gov_step_wise_unregister(void)
e151a202a   Durgadoss R   Thermal: Introduc...
185
186
187
  {
  	thermal_unregister_governor(&thermal_gov_step_wise);
  }