Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / cpufreq / freq_table.c
1 /*
2  * linux/drivers/cpufreq/freq_table.c
3  *
4  * Copyright (C) 2002 - 2003 Dominik Brodowski
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  */
11
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14 #include <linux/cpufreq.h>
15 #include <linux/module.h>
16
17 /*********************************************************************
18  *                     FREQUENCY TABLE HELPERS                       *
19  *********************************************************************/
20
21 bool policy_has_boost_freq(struct cpufreq_policy *policy)
22 {
23         struct cpufreq_frequency_table *pos, *table = policy->freq_table;
24
25         if (!table)
26                 return false;
27
28         cpufreq_for_each_valid_entry(pos, table)
29                 if (pos->flags & CPUFREQ_BOOST_FREQ)
30                         return true;
31
32         return false;
33 }
34 EXPORT_SYMBOL_GPL(policy_has_boost_freq);
35
36 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
37                                     struct cpufreq_frequency_table *table)
38 {
39         struct cpufreq_frequency_table *pos;
40         unsigned int min_freq = ~0;
41         unsigned int max_freq = 0;
42         unsigned int freq;
43
44         cpufreq_for_each_valid_entry(pos, table) {
45                 freq = pos->frequency;
46
47                 if (!cpufreq_boost_enabled()
48                     && (pos->flags & CPUFREQ_BOOST_FREQ))
49                         continue;
50
51                 pr_debug("table entry %u: %u kHz\n", (int)(pos - table), freq);
52                 if (freq < min_freq)
53                         min_freq = freq;
54                 if (freq > max_freq)
55                         max_freq = freq;
56         }
57
58         policy->min = policy->cpuinfo.min_freq = min_freq;
59         policy->max = policy->cpuinfo.max_freq = max_freq;
60
61         if (policy->min == ~0)
62                 return -EINVAL;
63         else
64                 return 0;
65 }
66
67 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
68                                    struct cpufreq_frequency_table *table)
69 {
70         struct cpufreq_frequency_table *pos;
71         unsigned int freq, next_larger = ~0;
72         bool found = false;
73
74         pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n",
75                                         policy->min, policy->max, policy->cpu);
76
77         cpufreq_verify_within_cpu_limits(policy);
78
79         cpufreq_for_each_valid_entry(pos, table) {
80                 freq = pos->frequency;
81
82                 if ((freq >= policy->min) && (freq <= policy->max)) {
83                         found = true;
84                         break;
85                 }
86
87                 if ((next_larger > freq) && (freq > policy->max))
88                         next_larger = freq;
89         }
90
91         if (!found) {
92                 policy->max = next_larger;
93                 cpufreq_verify_within_cpu_limits(policy);
94         }
95
96         pr_debug("verification lead to (%u - %u kHz) for cpu %u\n",
97                                 policy->min, policy->max, policy->cpu);
98
99         return 0;
100 }
101 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
102
103 /*
104  * Generic routine to verify policy & frequency table, requires driver to set
105  * policy->freq_table prior to it.
106  */
107 int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
108 {
109         if (!policy->freq_table)
110                 return -ENODEV;
111
112         return cpufreq_frequency_table_verify(policy, policy->freq_table);
113 }
114 EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify);
115
116 int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
117                                  unsigned int target_freq,
118                                  unsigned int relation)
119 {
120         struct cpufreq_frequency_table optimal = {
121                 .driver_data = ~0,
122                 .frequency = 0,
123         };
124         struct cpufreq_frequency_table suboptimal = {
125                 .driver_data = ~0,
126                 .frequency = 0,
127         };
128         struct cpufreq_frequency_table *pos;
129         struct cpufreq_frequency_table *table = policy->freq_table;
130         unsigned int freq, diff, i = 0;
131         int index;
132
133         pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
134                                         target_freq, relation, policy->cpu);
135
136         switch (relation) {
137         case CPUFREQ_RELATION_H:
138                 suboptimal.frequency = ~0;
139                 break;
140         case CPUFREQ_RELATION_L:
141         case CPUFREQ_RELATION_C:
142                 optimal.frequency = ~0;
143                 break;
144         }
145
146         cpufreq_for_each_valid_entry_idx(pos, table, i) {
147                 freq = pos->frequency;
148
149                 if ((freq < policy->min) || (freq > policy->max))
150                         continue;
151                 if (freq == target_freq) {
152                         optimal.driver_data = i;
153                         break;
154                 }
155                 switch (relation) {
156                 case CPUFREQ_RELATION_H:
157                         if (freq < target_freq) {
158                                 if (freq >= optimal.frequency) {
159                                         optimal.frequency = freq;
160                                         optimal.driver_data = i;
161                                 }
162                         } else {
163                                 if (freq <= suboptimal.frequency) {
164                                         suboptimal.frequency = freq;
165                                         suboptimal.driver_data = i;
166                                 }
167                         }
168                         break;
169                 case CPUFREQ_RELATION_L:
170                         if (freq > target_freq) {
171                                 if (freq <= optimal.frequency) {
172                                         optimal.frequency = freq;
173                                         optimal.driver_data = i;
174                                 }
175                         } else {
176                                 if (freq >= suboptimal.frequency) {
177                                         suboptimal.frequency = freq;
178                                         suboptimal.driver_data = i;
179                                 }
180                         }
181                         break;
182                 case CPUFREQ_RELATION_C:
183                         diff = abs(freq - target_freq);
184                         if (diff < optimal.frequency ||
185                             (diff == optimal.frequency &&
186                              freq > table[optimal.driver_data].frequency)) {
187                                 optimal.frequency = diff;
188                                 optimal.driver_data = i;
189                         }
190                         break;
191                 }
192         }
193         if (optimal.driver_data > i) {
194                 if (suboptimal.driver_data > i) {
195                         WARN(1, "Invalid frequency table: %d\n", policy->cpu);
196                         return 0;
197                 }
198
199                 index = suboptimal.driver_data;
200         } else
201                 index = optimal.driver_data;
202
203         pr_debug("target index is %u, freq is:%u kHz\n", index,
204                  table[index].frequency);
205         return index;
206 }
207 EXPORT_SYMBOL_GPL(cpufreq_table_index_unsorted);
208
209 int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
210                 unsigned int freq)
211 {
212         struct cpufreq_frequency_table *pos, *table = policy->freq_table;
213         int idx;
214
215         if (unlikely(!table)) {
216                 pr_debug("%s: Unable to find frequency table\n", __func__);
217                 return -ENOENT;
218         }
219
220         cpufreq_for_each_valid_entry_idx(pos, table, idx)
221                 if (pos->frequency == freq)
222                         return idx;
223
224         return -EINVAL;
225 }
226 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index);
227
228 /**
229  * show_available_freqs - show available frequencies for the specified CPU
230  */
231 static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
232                                     bool show_boost)
233 {
234         ssize_t count = 0;
235         struct cpufreq_frequency_table *pos, *table = policy->freq_table;
236
237         if (!table)
238                 return -ENODEV;
239
240         cpufreq_for_each_valid_entry(pos, table) {
241                 /*
242                  * show_boost = true and driver_data = BOOST freq
243                  * display BOOST freqs
244                  *
245                  * show_boost = false and driver_data = BOOST freq
246                  * show_boost = true and driver_data != BOOST freq
247                  * continue - do not display anything
248                  *
249                  * show_boost = false and driver_data != BOOST freq
250                  * display NON BOOST freqs
251                  */
252                 if (show_boost ^ (pos->flags & CPUFREQ_BOOST_FREQ))
253                         continue;
254
255                 count += sprintf(&buf[count], "%d ", pos->frequency);
256         }
257         count += sprintf(&buf[count], "\n");
258
259         return count;
260
261 }
262
263 #define cpufreq_attr_available_freq(_name)        \
264 struct freq_attr cpufreq_freq_attr_##_name##_freqs =     \
265 __ATTR_RO(_name##_frequencies)
266
267 /**
268  * show_scaling_available_frequencies - show available normal frequencies for
269  * the specified CPU
270  */
271 static ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy,
272                                                   char *buf)
273 {
274         return show_available_freqs(policy, buf, false);
275 }
276 cpufreq_attr_available_freq(scaling_available);
277 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
278
279 /**
280  * show_available_boost_freqs - show available boost frequencies for
281  * the specified CPU
282  */
283 static ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy,
284                                               char *buf)
285 {
286         return show_available_freqs(policy, buf, true);
287 }
288 cpufreq_attr_available_freq(scaling_boost);
289 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_boost_freqs);
290
291 struct freq_attr *cpufreq_generic_attr[] = {
292         &cpufreq_freq_attr_scaling_available_freqs,
293 #ifdef CONFIG_CPU_FREQ_BOOST_SW
294         &cpufreq_freq_attr_scaling_boost_freqs,
295 #endif
296         NULL,
297 };
298 EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
299
300 static int set_freq_table_sorted(struct cpufreq_policy *policy)
301 {
302         struct cpufreq_frequency_table *pos, *table = policy->freq_table;
303         struct cpufreq_frequency_table *prev = NULL;
304         int ascending = 0;
305
306         policy->freq_table_sorted = CPUFREQ_TABLE_UNSORTED;
307
308         cpufreq_for_each_valid_entry(pos, table) {
309                 if (!prev) {
310                         prev = pos;
311                         continue;
312                 }
313
314                 if (pos->frequency == prev->frequency) {
315                         pr_warn("Duplicate freq-table entries: %u\n",
316                                 pos->frequency);
317                         return -EINVAL;
318                 }
319
320                 /* Frequency increased from prev to pos */
321                 if (pos->frequency > prev->frequency) {
322                         /* But frequency was decreasing earlier */
323                         if (ascending < 0) {
324                                 pr_debug("Freq table is unsorted\n");
325                                 return 0;
326                         }
327
328                         ascending++;
329                 } else {
330                         /* Frequency decreased from prev to pos */
331
332                         /* But frequency was increasing earlier */
333                         if (ascending > 0) {
334                                 pr_debug("Freq table is unsorted\n");
335                                 return 0;
336                         }
337
338                         ascending--;
339                 }
340
341                 prev = pos;
342         }
343
344         if (ascending > 0)
345                 policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_ASCENDING;
346         else
347                 policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_DESCENDING;
348
349         pr_debug("Freq table is sorted in %s order\n",
350                  ascending > 0 ? "ascending" : "descending");
351
352         return 0;
353 }
354
355 int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
356                                       struct cpufreq_frequency_table *table)
357 {
358         int ret;
359
360         ret = cpufreq_frequency_table_cpuinfo(policy, table);
361         if (ret)
362                 return ret;
363
364         policy->freq_table = table;
365         return set_freq_table_sorted(policy);
366 }
367 EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
368
369 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
370 MODULE_DESCRIPTION("CPUfreq frequency table helpers");
371 MODULE_LICENSE("GPL");