Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
freq_table.c
Go to the documentation of this file.
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 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/cpufreq.h>
16 
17 /*********************************************************************
18  * FREQUENCY TABLE HELPERS *
19  *********************************************************************/
20 
23 {
24  unsigned int min_freq = ~0;
25  unsigned int max_freq = 0;
26  unsigned int i;
27 
28  for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
29  unsigned int freq = table[i].frequency;
30  if (freq == CPUFREQ_ENTRY_INVALID) {
31  pr_debug("table entry %u is invalid, skipping\n", i);
32 
33  continue;
34  }
35  pr_debug("table entry %u: %u kHz, %u index\n",
36  i, freq, table[i].index);
37  if (freq < min_freq)
38  min_freq = freq;
39  if (freq > max_freq)
40  max_freq = freq;
41  }
42 
43  policy->min = policy->cpuinfo.min_freq = min_freq;
44  policy->max = policy->cpuinfo.max_freq = max_freq;
45 
46  if (policy->min == ~0)
47  return -EINVAL;
48  else
49  return 0;
50 }
52 
53 
56 {
57  unsigned int next_larger = ~0;
58  unsigned int i;
59  unsigned int count = 0;
60 
61  pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n",
62  policy->min, policy->max, policy->cpu);
63 
64  if (!cpu_online(policy->cpu))
65  return -EINVAL;
66 
67  cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
68  policy->cpuinfo.max_freq);
69 
70  for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
71  unsigned int freq = table[i].frequency;
72  if (freq == CPUFREQ_ENTRY_INVALID)
73  continue;
74  if ((freq >= policy->min) && (freq <= policy->max))
75  count++;
76  else if ((next_larger > freq) && (freq > policy->max))
77  next_larger = freq;
78  }
79 
80  if (!count)
81  policy->max = next_larger;
82 
83  cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
84  policy->cpuinfo.max_freq);
85 
86  pr_debug("verification lead to (%u - %u kHz) for cpu %u\n",
87  policy->min, policy->max, policy->cpu);
88 
89  return 0;
90 }
92 
93 
96  unsigned int target_freq,
97  unsigned int relation,
98  unsigned int *index)
99 {
100  struct cpufreq_frequency_table optimal = {
101  .index = ~0,
102  .frequency = 0,
103  };
104  struct cpufreq_frequency_table suboptimal = {
105  .index = ~0,
106  .frequency = 0,
107  };
108  unsigned int i;
109 
110  pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
111  target_freq, relation, policy->cpu);
112 
113  switch (relation) {
114  case CPUFREQ_RELATION_H:
115  suboptimal.frequency = ~0;
116  break;
117  case CPUFREQ_RELATION_L:
118  optimal.frequency = ~0;
119  break;
120  }
121 
122  if (!cpu_online(policy->cpu))
123  return -EINVAL;
124 
125  for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
126  unsigned int freq = table[i].frequency;
127  if (freq == CPUFREQ_ENTRY_INVALID)
128  continue;
129  if ((freq < policy->min) || (freq > policy->max))
130  continue;
131  switch (relation) {
132  case CPUFREQ_RELATION_H:
133  if (freq <= target_freq) {
134  if (freq >= optimal.frequency) {
135  optimal.frequency = freq;
136  optimal.index = i;
137  }
138  } else {
139  if (freq <= suboptimal.frequency) {
140  suboptimal.frequency = freq;
141  suboptimal.index = i;
142  }
143  }
144  break;
145  case CPUFREQ_RELATION_L:
146  if (freq >= target_freq) {
147  if (freq <= optimal.frequency) {
148  optimal.frequency = freq;
149  optimal.index = i;
150  }
151  } else {
152  if (freq >= suboptimal.frequency) {
153  suboptimal.frequency = freq;
154  suboptimal.index = i;
155  }
156  }
157  break;
158  }
159  }
160  if (optimal.index > i) {
161  if (suboptimal.index > i)
162  return -EINVAL;
163  *index = suboptimal.index;
164  } else
165  *index = optimal.index;
166 
167  pr_debug("target is %u (%u kHz, %u)\n", *index, table[*index].frequency,
168  table[*index].index);
169 
170  return 0;
171 }
173 
174 static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
178 static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
179 {
180  unsigned int i = 0;
181  unsigned int cpu = policy->cpu;
182  ssize_t count = 0;
184 
185  if (!per_cpu(cpufreq_show_table, cpu))
186  return -ENODEV;
187 
188  table = per_cpu(cpufreq_show_table, cpu);
189 
190  for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
191  if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
192  continue;
193  count += sprintf(&buf[count], "%d ", table[i].frequency);
194  }
195  count += sprintf(&buf[count], "\n");
196 
197  return count;
198 
199 }
200 
202  .attr = { .name = "scaling_available_frequencies",
203  .mode = 0444,
204  },
205  .show = show_available_freqs,
206 };
207 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
208 
209 /*
210  * if you use these, you must assure that the frequency table is valid
211  * all the time between get_attr and put_attr!
212  */
214  unsigned int cpu)
215 {
216  pr_debug("setting show_table for cpu %u to %p\n", cpu, table);
217  per_cpu(cpufreq_show_table, cpu) = table;
218 }
220 
221 void cpufreq_frequency_table_put_attr(unsigned int cpu)
222 {
223  pr_debug("clearing show_table for cpu %u\n", cpu);
224  per_cpu(cpufreq_show_table, cpu) = NULL;
225 }
227 
229 {
230  return per_cpu(cpufreq_show_table, cpu);
231 }
233 
234 MODULE_AUTHOR("Dominik Brodowski <[email protected]>");
235 MODULE_DESCRIPTION("CPUfreq frequency table helpers");
236 MODULE_LICENSE("GPL");