aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2014-12-03 23:12:07 -0500
committerEduardo Valentin <edubezval@gmail.com>2014-12-08 13:11:54 -0500
commit4843c4a190495aec41c8a87365697e933dc88bc9 (patch)
tree102b19e35891754c59c56bfb8bf2b1c1d9012dd9 /drivers/thermal
parentf6859014c7e7cc0e7688525741fc3a0e7aee63be (diff)
thermal: cpu_cooling: Use cpufreq_dev->freq_table for finding level/freq
get_property() was an over complicated beast with BUGs. It used to believe that cpufreq table is present in ascending or descending order, which might not always be true. Previous patch has created another freq table in descending order for us and we better use it now. With that get_property() simply goes away and another helper get_level() comes in. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/cpu_cooling.c108
1 files changed, 19 insertions, 89 deletions
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index cb5a4b914187..cd6f64291076 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -112,85 +112,27 @@ static void release_idr(struct idr *idr, int id)
112 112
113/* Below code defines functions to be used for cpufreq as cooling device */ 113/* Below code defines functions to be used for cpufreq as cooling device */
114 114
115enum cpufreq_cooling_property {
116 GET_LEVEL,
117 GET_FREQ,
118};
119
120/** 115/**
121 * get_property - fetch a property of interest for a given cpu. 116 * get_level: Find the level for a particular frequency
122 * @cpufreq_dev: cpufreq_dev for which the property is required 117 * @cpufreq_dev: cpufreq_dev for which the property is required
123 * @input: query parameter 118 * @freq: Frequency
124 * @output: query return
125 * @property: type of query (frequency, level)
126 *
127 * This is the common function to
128 * 1. translate frequency to cooling state
129 * 2. translate cooling state to frequency
130 * 119 *
131 * Note that the code may be not in good shape 120 * Return: level on success, THERMAL_CSTATE_INVALID on error.
132 * but it is written in this way in order to:
133 * a) reduce duplicate code as most of the code can be shared.
134 * b) make sure the logic is consistent when translating between
135 * cooling states and frequencies.
136 *
137 * Return: 0 on success, -EINVAL when invalid parameters are passed.
138 */ 121 */
139static int get_property(struct cpufreq_cooling_device *cpufreq_dev, 122static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_dev,
140 unsigned long input, unsigned int *output, 123 unsigned int freq)
141 enum cpufreq_cooling_property property)
142{ 124{
143 int i; 125 unsigned long level;
144 unsigned long level = 0;
145 unsigned int freq = CPUFREQ_ENTRY_INVALID;
146 int descend = -1;
147 struct cpufreq_frequency_table *pos, *table;
148
149 if (!output)
150 return -EINVAL;
151
152 table = cpufreq_frequency_get_table(cpumask_first(&cpufreq_dev->allowed_cpus));
153 if (!table)
154 return -EINVAL;
155
156 cpufreq_for_each_valid_entry(pos, table) {
157 /* ignore duplicate entry */
158 if (freq == pos->frequency)
159 continue;
160
161 /* get the frequency order */
162 if (freq != CPUFREQ_ENTRY_INVALID && descend == -1)
163 descend = freq > pos->frequency;
164
165 freq = pos->frequency;
166 }
167
168 if (property == GET_FREQ)
169 level = descend ? input : (cpufreq_dev->max_level - input);
170
171 i = 0;
172 cpufreq_for_each_valid_entry(pos, table) {
173 /* ignore duplicate entry */
174 if (freq == pos->frequency)
175 continue;
176 126
177 /* now we have a valid frequency entry */ 127 for (level = 0; level <= cpufreq_dev->max_level; level++) {
178 freq = pos->frequency; 128 if (freq == cpufreq_dev->freq_table[level])
129 return level;
179 130
180 if (property == GET_LEVEL && (unsigned int)input == freq) { 131 if (freq > cpufreq_dev->freq_table[level])
181 /* get level by frequency */ 132 break;
182 *output = descend ? i : (cpufreq_dev->max_level - i);
183 return 0;
184 }
185 if (property == GET_FREQ && level == i) {
186 /* get frequency by level */
187 *output = freq;
188 return 0;
189 }
190 i++;
191 } 133 }
192 134
193 return -EINVAL; 135 return THERMAL_CSTATE_INVALID;
194} 136}
195 137
196/** 138/**
@@ -211,14 +153,8 @@ unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
211 mutex_lock(&cooling_cpufreq_lock); 153 mutex_lock(&cooling_cpufreq_lock);
212 list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { 154 list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
213 if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) { 155 if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) {
214 unsigned int val;
215
216 mutex_unlock(&cooling_cpufreq_lock); 156 mutex_unlock(&cooling_cpufreq_lock);
217 if (get_property(cpufreq_dev, (unsigned long)freq, &val, 157 return get_level(cpufreq_dev, freq);
218 GET_LEVEL))
219 return THERMAL_CSTATE_INVALID;
220
221 return (unsigned long)val;
222 } 158 }
223 } 159 }
224 mutex_unlock(&cooling_cpufreq_lock); 160 mutex_unlock(&cooling_cpufreq_lock);
@@ -323,16 +259,16 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
323 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; 259 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
324 unsigned int cpu = cpumask_any(&cpufreq_device->allowed_cpus); 260 unsigned int cpu = cpumask_any(&cpufreq_device->allowed_cpus);
325 unsigned int clip_freq; 261 unsigned int clip_freq;
326 int ret; 262
263 /* Request state should be less than max_level */
264 if (WARN_ON(state > cpufreq_device->max_level))
265 return -EINVAL;
327 266
328 /* Check if the old cooling action is same as new cooling action */ 267 /* Check if the old cooling action is same as new cooling action */
329 if (cpufreq_device->cpufreq_state == state) 268 if (cpufreq_device->cpufreq_state == state)
330 return 0; 269 return 0;
331 270
332 ret = get_property(cpufreq_device, state, &clip_freq, GET_FREQ); 271 clip_freq = cpufreq_device->freq_table[state];
333 if (ret)
334 return ret;
335
336 cpufreq_device->cpufreq_state = state; 272 cpufreq_device->cpufreq_state = state;
337 cpufreq_device->cpufreq_val = clip_freq; 273 cpufreq_device->cpufreq_val = clip_freq;
338 274
@@ -402,13 +338,6 @@ __cpufreq_cooling_register(struct device_node *np,
402 if (!cpufreq_dev) 338 if (!cpufreq_dev)
403 return ERR_PTR(-ENOMEM); 339 return ERR_PTR(-ENOMEM);
404 340
405 ret = get_property(cpufreq_dev, 0, &cpufreq_dev->cpufreq_val, GET_FREQ);
406 if (ret) {
407 pr_err("%s: Failed to get frequency: %d", __func__, ret);
408 cool_dev = ERR_PTR(ret);
409 goto free_cdev;
410 }
411
412 /* Find max levels */ 341 /* Find max levels */
413 cpufreq_for_each_valid_entry(pos, table) 342 cpufreq_for_each_valid_entry(pos, table)
414 cpufreq_dev->max_level++; 343 cpufreq_dev->max_level++;
@@ -452,6 +381,7 @@ __cpufreq_cooling_register(struct device_node *np,
452 pr_debug("%s: freq:%u KHz\n", __func__, freq); 381 pr_debug("%s: freq:%u KHz\n", __func__, freq);
453 } 382 }
454 383
384 cpufreq_dev->cpufreq_val = cpufreq_dev->freq_table[0];
455 cpufreq_dev->cool_dev = cool_dev; 385 cpufreq_dev->cool_dev = cool_dev;
456 386
457 mutex_lock(&cooling_cpufreq_lock); 387 mutex_lock(&cooling_cpufreq_lock);