Blame view

drivers/cpufreq/freq_table.c 6.02 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
  /*
   * linux/drivers/cpufreq/freq_table.c
   *
   * Copyright (C) 2002 - 2003 Dominik Brodowski
4f7436942   Dominik Brodowski   [CPUFREQ] clarify...
5
6
7
8
9
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/cpufreq.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
21
22
23
24
  /*********************************************************************
   *                     FREQUENCY TABLE HELPERS                       *
   *********************************************************************/
  
  int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
  				    struct cpufreq_frequency_table *table)
  {
  	unsigned int min_freq = ~0;
  	unsigned int max_freq = 0;
355eb3180   Dave Jones   [CPUFREQ] Remove ...
25
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26

97acec55d   Dave Jones   [CPUFREQ] checkpa...
27
  	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
  		unsigned int freq = table[i].frequency;
  		if (freq == CPUFREQ_ENTRY_INVALID) {
2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
30
31
  			pr_debug("table entry %u is invalid, skipping
  ", i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
  
  			continue;
  		}
2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
35
36
  		pr_debug("table entry %u: %u kHz, %u index
  ",
e08f5f5bb   Gautham R Shenoy   [CPUFREQ] Fix cod...
37
  					i, freq, table[i].index);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  		if (freq < min_freq)
  			min_freq = freq;
  		if (freq > max_freq)
  			max_freq = freq;
  	}
  
  	policy->min = policy->cpuinfo.min_freq = min_freq;
  	policy->max = policy->cpuinfo.max_freq = max_freq;
  
  	if (policy->min == ~0)
  		return -EINVAL;
  	else
  		return 0;
  }
  EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
  
  
  int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
  				   struct cpufreq_frequency_table *table)
  {
  	unsigned int next_larger = ~0;
5557976ca   Dave Jones   [CPUFREQ] Fix ano...
59
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  	unsigned int count = 0;
2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
61
62
  	pr_debug("request for verification of policy (%u - %u kHz) for cpu %u
  ",
e08f5f5bb   Gautham R Shenoy   [CPUFREQ] Fix cod...
63
  					policy->min, policy->max, policy->cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
  
  	if (!cpu_online(policy->cpu))
  		return -EINVAL;
e08f5f5bb   Gautham R Shenoy   [CPUFREQ] Fix cod...
67
68
  	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
  				     policy->cpuinfo.max_freq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69

97acec55d   Dave Jones   [CPUFREQ] checkpa...
70
  	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
75
76
77
78
79
80
81
  		unsigned int freq = table[i].frequency;
  		if (freq == CPUFREQ_ENTRY_INVALID)
  			continue;
  		if ((freq >= policy->min) && (freq <= policy->max))
  			count++;
  		else if ((next_larger > freq) && (freq > policy->max))
  			next_larger = freq;
  	}
  
  	if (!count)
  		policy->max = next_larger;
e08f5f5bb   Gautham R Shenoy   [CPUFREQ] Fix cod...
82
83
  	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
  				     policy->cpuinfo.max_freq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84

2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
85
86
  	pr_debug("verification lead to (%u - %u kHz) for cpu %u
  ",
e08f5f5bb   Gautham R Shenoy   [CPUFREQ] Fix cod...
87
  				policy->min, policy->max, policy->cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
92
93
94
95
96
97
98
99
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
  
  
  int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
  				   struct cpufreq_frequency_table *table,
  				   unsigned int target_freq,
  				   unsigned int relation,
  				   unsigned int *index)
  {
484944a5b   Dave Jones   [CPUFREQ] Remove ...
100
101
102
103
104
105
106
107
  	struct cpufreq_frequency_table optimal = {
  		.index = ~0,
  		.frequency = 0,
  	};
  	struct cpufreq_frequency_table suboptimal = {
  		.index = ~0,
  		.frequency = 0,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  	unsigned int i;
2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
109
110
  	pr_debug("request for target %u kHz (relation: %u) for cpu %u
  ",
e08f5f5bb   Gautham R Shenoy   [CPUFREQ] Fix cod...
111
  					target_freq, relation, policy->cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
  
  	switch (relation) {
  	case CPUFREQ_RELATION_H:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
  		suboptimal.frequency = ~0;
  		break;
  	case CPUFREQ_RELATION_L:
  		optimal.frequency = ~0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
122
123
  		break;
  	}
  
  	if (!cpu_online(policy->cpu))
  		return -EINVAL;
97acec55d   Dave Jones   [CPUFREQ] checkpa...
124
  	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
129
  		unsigned int freq = table[i].frequency;
  		if (freq == CPUFREQ_ENTRY_INVALID)
  			continue;
  		if ((freq < policy->min) || (freq > policy->max))
  			continue;
97acec55d   Dave Jones   [CPUFREQ] checkpa...
130
  		switch (relation) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  		case CPUFREQ_RELATION_H:
  			if (freq <= target_freq) {
  				if (freq >= optimal.frequency) {
  					optimal.frequency = freq;
  					optimal.index = i;
  				}
  			} else {
  				if (freq <= suboptimal.frequency) {
  					suboptimal.frequency = freq;
  					suboptimal.index = i;
  				}
  			}
  			break;
  		case CPUFREQ_RELATION_L:
  			if (freq >= target_freq) {
  				if (freq <= optimal.frequency) {
  					optimal.frequency = freq;
  					optimal.index = i;
  				}
  			} else {
  				if (freq >= suboptimal.frequency) {
  					suboptimal.frequency = freq;
  					suboptimal.index = i;
  				}
  			}
  			break;
  		}
  	}
  	if (optimal.index > i) {
  		if (suboptimal.index > i)
  			return -EINVAL;
  		*index = suboptimal.index;
  	} else
  		*index = optimal.index;
2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
165
166
  	pr_debug("target is %u (%u kHz, %u)
  ", *index, table[*index].frequency,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
170
171
  		table[*index].index);
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
f16250669   Tejun Heo   percpu: make perc...
172
  static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  /**
e32d22f77   Fenghua Yu   [CPUFREQ] fix inc...
174
   * show_available_freqs - show available frequencies for the specified CPU
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
   */
97acec55d   Dave Jones   [CPUFREQ] checkpa...
176
  static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
180
181
  {
  	unsigned int i = 0;
  	unsigned int cpu = policy->cpu;
  	ssize_t count = 0;
  	struct cpufreq_frequency_table *table;
f16250669   Tejun Heo   percpu: make perc...
182
  	if (!per_cpu(cpufreq_show_table, cpu))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  		return -ENODEV;
f16250669   Tejun Heo   percpu: make perc...
184
  	table = per_cpu(cpufreq_show_table, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185

97acec55d   Dave Jones   [CPUFREQ] checkpa...
186
  	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
191
192
193
194
195
196
197
198
  		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
  			continue;
  		count += sprintf(&buf[count], "%d ", table[i].frequency);
  	}
  	count += sprintf(&buf[count], "
  ");
  
  	return count;
  
  }
  
  struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
e08f5f5bb   Gautham R Shenoy   [CPUFREQ] Fix cod...
199
200
  	.attr = { .name = "scaling_available_frequencies",
  		  .mode = 0444,
e08f5f5bb   Gautham R Shenoy   [CPUFREQ] Fix cod...
201
  		},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
206
207
208
209
  	.show = show_available_freqs,
  };
  EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
  
  /*
   * if you use these, you must assure that the frequency table is valid
   * all the time between get_attr and put_attr!
   */
32ee8c3e4   Dave Jones   [CPUFREQ] Lots of...
210
  void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
  				      unsigned int cpu)
  {
2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
213
214
  	pr_debug("setting show_table for cpu %u to %p
  ", cpu, table);
f16250669   Tejun Heo   percpu: make perc...
215
  	per_cpu(cpufreq_show_table, cpu) = table;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
  }
  EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
  
  void cpufreq_frequency_table_put_attr(unsigned int cpu)
  {
2d06d8c49   Dominik Brodowski   [CPUFREQ] use dyn...
221
222
  	pr_debug("clearing show_table for cpu %u
  ", cpu);
f16250669   Tejun Heo   percpu: make perc...
223
  	per_cpu(cpufreq_show_table, cpu) = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
228
  }
  EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
  
  struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
  {
f16250669   Tejun Heo   percpu: make perc...
229
  	return per_cpu(cpufreq_show_table, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
  }
  EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
97acec55d   Dave Jones   [CPUFREQ] checkpa...
232
233
234
  MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
  MODULE_DESCRIPTION("CPUfreq frequency table helpers");
  MODULE_LICENSE("GPL");