Blame view
drivers/cpufreq/cpufreq_ondemand.c
20.9 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* * drivers/cpufreq/cpufreq_ondemand.c * * Copyright (C) 2001 Russell King * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>. * Jun Nakajima <jun.nakajima@intel.com> * * 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. */ #include <linux/kernel.h> #include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/init.h> |
1da177e4c Linux-2.6.12-rc2 |
16 |
#include <linux/cpufreq.h> |
138a0128c [PATCH] cpufreq b... |
17 |
#include <linux/cpu.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 |
#include <linux/jiffies.h> #include <linux/kernel_stat.h> |
3fc54d37a [CPUFREQ] Convert... |
20 |
#include <linux/mutex.h> |
808009131 [CPUFREQ][6/6] cp... |
21 22 23 |
#include <linux/hrtimer.h> #include <linux/tick.h> #include <linux/ktime.h> |
9411b4ef7 [CPUFREQ] ondeman... |
24 |
#include <linux/sched.h> |
1da177e4c Linux-2.6.12-rc2 |
25 26 27 28 29 |
/* * dbs is used in this file as a shortform for demandbased switching * It helps to keep variable names smaller, simpler */ |
e9d95bf7e [CPUFREQ][4/6] cp... |
30 |
#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) |
1da177e4c Linux-2.6.12-rc2 |
31 |
#define DEF_FREQUENCY_UP_THRESHOLD (80) |
3f78a9f7f [CPUFREQ] add sam... |
32 33 |
#define DEF_SAMPLING_DOWN_FACTOR (1) #define MAX_SAMPLING_DOWN_FACTOR (100000) |
808009131 [CPUFREQ][6/6] cp... |
34 35 |
#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) #define MICRO_FREQUENCY_UP_THRESHOLD (95) |
cef9615a8 [CPUFREQ] ondeman... |
36 |
#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) |
c29f14030 [CPUFREQ] ondeman... |
37 |
#define MIN_FREQUENCY_UP_THRESHOLD (11) |
1da177e4c Linux-2.6.12-rc2 |
38 |
#define MAX_FREQUENCY_UP_THRESHOLD (100) |
32ee8c3e4 [CPUFREQ] Lots of... |
39 40 |
/* * The polling frequency of this governor depends on the capability of |
1da177e4c Linux-2.6.12-rc2 |
41 |
* the processor. Default polling frequency is 1000 times the transition |
32ee8c3e4 [CPUFREQ] Lots of... |
42 43 |
* latency of the processor. The governor will work on any processor with * transition latency <= 10mS, using appropriate sampling |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 48 |
* rate. * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) * this governor will not work. * All times here are in uS. */ |
df8b59be0 [CPUFREQ] Avoid t... |
49 |
#define MIN_SAMPLING_RATE_RATIO (2) |
112124ab0 [CPUFREQ] ondeman... |
50 |
|
cef9615a8 [CPUFREQ] ondeman... |
51 |
static unsigned int min_sampling_rate; |
112124ab0 [CPUFREQ] ondeman... |
52 |
#define LATENCY_MULTIPLIER (1000) |
cef9615a8 [CPUFREQ] ondeman... |
53 |
#define MIN_LATENCY_MULTIPLIER (100) |
1c2562459 [CPUFREQ] allow o... |
54 |
#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) |
1da177e4c Linux-2.6.12-rc2 |
55 |
|
c4028958b WorkStruct: make ... |
56 |
static void do_dbs_timer(struct work_struct *work); |
0e625ac15 [CPUFREQ] ondeman... |
57 58 59 60 61 62 63 64 65 66 67 68 |
static int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event); #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND static #endif struct cpufreq_governor cpufreq_gov_ondemand = { .name = "ondemand", .governor = cpufreq_governor_dbs, .max_transition_latency = TRANSITION_LATENCY_LIMIT, .owner = THIS_MODULE, }; |
c4028958b WorkStruct: make ... |
69 70 |
/* Sampling types */ |
529af7a14 [CPUFREQ] ondeman... |
71 |
enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; |
1da177e4c Linux-2.6.12-rc2 |
72 73 |
struct cpu_dbs_info_s { |
ccb2fe209 [CPUFREQ] Remove ... |
74 |
cputime64_t prev_cpu_idle; |
6b8fcd902 ondemand: Solve a... |
75 |
cputime64_t prev_cpu_iowait; |
ccb2fe209 [CPUFREQ] Remove ... |
76 |
cputime64_t prev_cpu_wall; |
808009131 [CPUFREQ][6/6] cp... |
77 |
cputime64_t prev_cpu_nice; |
32ee8c3e4 [CPUFREQ] Lots of... |
78 |
struct cpufreq_policy *cur_policy; |
2b03f891a [CPUFREQ] checkpa... |
79 |
struct delayed_work work; |
05ca0350e [CPUFREQ][2/2] on... |
80 81 82 83 |
struct cpufreq_frequency_table *freq_table; unsigned int freq_lo; unsigned int freq_lo_jiffies; unsigned int freq_hi_jiffies; |
3f78a9f7f [CPUFREQ] add sam... |
84 |
unsigned int rate_mult; |
529af7a14 [CPUFREQ] ondeman... |
85 |
int cpu; |
5a75c8282 [CPUFREQ] Cleanup... |
86 87 88 89 90 91 92 |
unsigned int sample_type:1; /* * percpu mutex that serializes governor limit change with * do_dbs_timer invocation. We do not want do_dbs_timer to run * when user is changing the governor or limits. */ struct mutex timer_mutex; |
1da177e4c Linux-2.6.12-rc2 |
93 |
}; |
245b2e70e percpu: clean up ... |
94 |
static DEFINE_PER_CPU(struct cpu_dbs_info_s, od_cpu_dbs_info); |
1da177e4c Linux-2.6.12-rc2 |
95 96 |
static unsigned int dbs_enable; /* number of CPUs using this policy */ |
4ec223d02 [CPUFREQ] Fix ond... |
97 |
/* |
326c86dea [CPUFREQ] Remove ... |
98 |
* dbs_mutex protects dbs_enable in governor start/stop. |
4ec223d02 [CPUFREQ] Fix ond... |
99 |
*/ |
ffac80e92 [CPUFREQ] Misc cl... |
100 |
static DEFINE_MUTEX(dbs_mutex); |
1da177e4c Linux-2.6.12-rc2 |
101 |
|
05ca0350e [CPUFREQ][2/2] on... |
102 |
static struct dbs_tuners { |
32ee8c3e4 [CPUFREQ] Lots of... |
103 |
unsigned int sampling_rate; |
32ee8c3e4 [CPUFREQ] Lots of... |
104 |
unsigned int up_threshold; |
e9d95bf7e [CPUFREQ][4/6] cp... |
105 |
unsigned int down_differential; |
32ee8c3e4 [CPUFREQ] Lots of... |
106 |
unsigned int ignore_nice; |
3f78a9f7f [CPUFREQ] add sam... |
107 |
unsigned int sampling_down_factor; |
05ca0350e [CPUFREQ][2/2] on... |
108 |
unsigned int powersave_bias; |
19379b118 ondemand: Make th... |
109 |
unsigned int io_is_busy; |
05ca0350e [CPUFREQ][2/2] on... |
110 |
} dbs_tuners_ins = { |
32ee8c3e4 [CPUFREQ] Lots of... |
111 |
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD, |
3f78a9f7f [CPUFREQ] add sam... |
112 |
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, |
e9d95bf7e [CPUFREQ][4/6] cp... |
113 |
.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, |
9cbad61b4 [PATCH] cpufreq_o... |
114 |
.ignore_nice = 0, |
05ca0350e [CPUFREQ][2/2] on... |
115 |
.powersave_bias = 0, |
1da177e4c Linux-2.6.12-rc2 |
116 |
}; |
3292beb34 sched/accounting:... |
117 |
static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) |
dac1c1a56 [CPUFREQ] ondeman... |
118 |
{ |
3292beb34 sched/accounting:... |
119 |
u64 idle_time; |
612ef28a0 Merge branch 'sch... |
120 |
u64 cur_wall_time; |
3292beb34 sched/accounting:... |
121 |
u64 busy_time; |
ccb2fe209 [CPUFREQ] Remove ... |
122 |
|
3430502d3 [CPUFREQ][3/6] cp... |
123 |
cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); |
ccb2fe209 [CPUFREQ] Remove ... |
124 |
|
612ef28a0 Merge branch 'sch... |
125 126 |
busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; |
3292beb34 sched/accounting:... |
127 128 129 130 |
busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; |
648616343 [S390] cputime: a... |
131 132 |
idle_time = cur_wall_time - busy_time; |
3430502d3 [CPUFREQ][3/6] cp... |
133 |
if (wall) |
3292beb34 sched/accounting:... |
134 |
*wall = jiffies_to_usecs(cur_wall_time); |
3430502d3 [CPUFREQ][3/6] cp... |
135 |
|
3292beb34 sched/accounting:... |
136 |
return jiffies_to_usecs(idle_time); |
dac1c1a56 [CPUFREQ] ondeman... |
137 |
} |
808009131 [CPUFREQ][6/6] cp... |
138 139 |
static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) { |
6beea0cda nohz: Fix update_... |
140 |
u64 idle_time = get_cpu_idle_time_us(cpu, NULL); |
808009131 [CPUFREQ][6/6] cp... |
141 142 143 |
if (idle_time == -1ULL) return get_cpu_idle_time_jiffy(cpu, wall); |
6beea0cda nohz: Fix update_... |
144 145 |
else idle_time += get_cpu_iowait_time_us(cpu, wall); |
808009131 [CPUFREQ][6/6] cp... |
146 |
|
808009131 [CPUFREQ][6/6] cp... |
147 148 |
return idle_time; } |
6b8fcd902 ondemand: Solve a... |
149 150 151 152 153 154 155 156 157 |
static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall) { u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); if (iowait_time == -1ULL) return 0; return iowait_time; } |
05ca0350e [CPUFREQ][2/2] on... |
158 159 160 161 162 |
/* * Find right freq to be set now with powersave_bias on. * Returns the freq_hi to be used right now and will set freq_hi_jiffies, * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. */ |
b5ecf60fe [CPUFREQ] make dr... |
163 164 165 |
static unsigned int powersave_bias_target(struct cpufreq_policy *policy, unsigned int freq_next, unsigned int relation) |
05ca0350e [CPUFREQ][2/2] on... |
166 167 168 169 170 |
{ unsigned int freq_req, freq_reduc, freq_avg; unsigned int freq_hi, freq_lo; unsigned int index = 0; unsigned int jiffies_total, jiffies_hi, jiffies_lo; |
245b2e70e percpu: clean up ... |
171 172 |
struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu); |
05ca0350e [CPUFREQ][2/2] on... |
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
if (!dbs_info->freq_table) { dbs_info->freq_lo = 0; dbs_info->freq_lo_jiffies = 0; return freq_next; } cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, relation, &index); freq_req = dbs_info->freq_table[index].frequency; freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000; freq_avg = freq_req - freq_reduc; /* Find freq bounds for freq_avg in freq_table */ index = 0; cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, CPUFREQ_RELATION_H, &index); freq_lo = dbs_info->freq_table[index].frequency; index = 0; cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, CPUFREQ_RELATION_L, &index); freq_hi = dbs_info->freq_table[index].frequency; /* Find out how long we have to be in hi and lo freqs */ if (freq_hi == freq_lo) { dbs_info->freq_lo = 0; dbs_info->freq_lo_jiffies = 0; return freq_lo; } jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); jiffies_hi = (freq_avg - freq_lo) * jiffies_total; jiffies_hi += ((freq_hi - freq_lo) / 2); jiffies_hi /= (freq_hi - freq_lo); jiffies_lo = jiffies_total - jiffies_hi; dbs_info->freq_lo = freq_lo; dbs_info->freq_lo_jiffies = jiffies_lo; dbs_info->freq_hi_jiffies = jiffies_hi; return freq_hi; } |
5a75c8282 [CPUFREQ] Cleanup... |
212 213 |
static void ondemand_powersave_bias_init_cpu(int cpu) { |
384be2b18 Merge branch 'per... |
214 |
struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); |
5a75c8282 [CPUFREQ] Cleanup... |
215 216 217 |
dbs_info->freq_table = cpufreq_frequency_get_table(cpu); dbs_info->freq_lo = 0; } |
05ca0350e [CPUFREQ][2/2] on... |
218 219 220 221 |
static void ondemand_powersave_bias_init(void) { int i; for_each_online_cpu(i) { |
5a75c8282 [CPUFREQ] Cleanup... |
222 |
ondemand_powersave_bias_init_cpu(i); |
05ca0350e [CPUFREQ][2/2] on... |
223 224 |
} } |
1da177e4c Linux-2.6.12-rc2 |
225 |
/************************** sysfs interface ************************/ |
0e625ac15 [CPUFREQ] ondeman... |
226 |
|
0e625ac15 [CPUFREQ] ondeman... |
227 228 |
static ssize_t show_sampling_rate_min(struct kobject *kobj, struct attribute *attr, char *buf) |
1da177e4c Linux-2.6.12-rc2 |
229 |
{ |
cef9615a8 [CPUFREQ] ondeman... |
230 231 |
return sprintf(buf, "%u ", min_sampling_rate); |
1da177e4c Linux-2.6.12-rc2 |
232 |
} |
6dad2a296 cpufreq: Unify sy... |
233 |
define_one_global_ro(sampling_rate_min); |
1da177e4c Linux-2.6.12-rc2 |
234 235 236 237 |
/* cpufreq_ondemand Governor Tunables */ #define show_one(file_name, object) \ static ssize_t show_##file_name \ |
0e625ac15 [CPUFREQ] ondeman... |
238 |
(struct kobject *kobj, struct attribute *attr, char *buf) \ |
1da177e4c Linux-2.6.12-rc2 |
239 240 241 242 243 |
{ \ return sprintf(buf, "%u ", dbs_tuners_ins.object); \ } show_one(sampling_rate, sampling_rate); |
19379b118 ondemand: Make th... |
244 |
show_one(io_is_busy, io_is_busy); |
1da177e4c Linux-2.6.12-rc2 |
245 |
show_one(up_threshold, up_threshold); |
3f78a9f7f [CPUFREQ] add sam... |
246 |
show_one(sampling_down_factor, sampling_down_factor); |
001893cda [PATCH] cpufreq_c... |
247 |
show_one(ignore_nice_load, ignore_nice); |
05ca0350e [CPUFREQ][2/2] on... |
248 |
show_one(powersave_bias, powersave_bias); |
1da177e4c Linux-2.6.12-rc2 |
249 |
|
0e625ac15 [CPUFREQ] ondeman... |
250 251 |
static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, const char *buf, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
252 253 254 |
{ unsigned int input; int ret; |
ffac80e92 [CPUFREQ] Misc cl... |
255 |
ret = sscanf(buf, "%u", &input); |
5a75c8282 [CPUFREQ] Cleanup... |
256 257 |
if (ret != 1) return -EINVAL; |
cef9615a8 [CPUFREQ] ondeman... |
258 |
dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate); |
1da177e4c Linux-2.6.12-rc2 |
259 260 |
return count; } |
19379b118 ondemand: Make th... |
261 262 263 264 265 266 267 268 269 |
static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, const char *buf, size_t count) { unsigned int input; int ret; ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; |
19379b118 ondemand: Make th... |
270 |
dbs_tuners_ins.io_is_busy = !!input; |
19379b118 ondemand: Make th... |
271 272 |
return count; } |
0e625ac15 [CPUFREQ] ondeman... |
273 274 |
static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, const char *buf, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
275 276 277 |
{ unsigned int input; int ret; |
ffac80e92 [CPUFREQ] Misc cl... |
278 |
ret = sscanf(buf, "%u", &input); |
1da177e4c Linux-2.6.12-rc2 |
279 |
|
32ee8c3e4 [CPUFREQ] Lots of... |
280 |
if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || |
c29f14030 [CPUFREQ] ondeman... |
281 |
input < MIN_FREQUENCY_UP_THRESHOLD) { |
1da177e4c Linux-2.6.12-rc2 |
282 283 |
return -EINVAL; } |
1da177e4c Linux-2.6.12-rc2 |
284 |
dbs_tuners_ins.up_threshold = input; |
1da177e4c Linux-2.6.12-rc2 |
285 286 |
return count; } |
3f78a9f7f [CPUFREQ] add sam... |
287 288 289 290 291 292 293 294 295 |
static ssize_t store_sampling_down_factor(struct kobject *a, struct attribute *b, const char *buf, size_t count) { unsigned int input, j; int ret; ret = sscanf(buf, "%u", &input); if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) return -EINVAL; |
3f78a9f7f [CPUFREQ] add sam... |
296 297 298 299 300 301 302 303 |
dbs_tuners_ins.sampling_down_factor = input; /* Reset down sampling multiplier in case it was active */ for_each_online_cpu(j) { struct cpu_dbs_info_s *dbs_info; dbs_info = &per_cpu(od_cpu_dbs_info, j); dbs_info->rate_mult = 1; } |
3f78a9f7f [CPUFREQ] add sam... |
304 305 |
return count; } |
0e625ac15 [CPUFREQ] ondeman... |
306 307 |
static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b, const char *buf, size_t count) |
3d5ee9e55 [CPUFREQ] Add sup... |
308 309 310 311 312 |
{ unsigned int input; int ret; unsigned int j; |
32ee8c3e4 [CPUFREQ] Lots of... |
313 |
|
ffac80e92 [CPUFREQ] Misc cl... |
314 |
ret = sscanf(buf, "%u", &input); |
2b03f891a [CPUFREQ] checkpa... |
315 |
if (ret != 1) |
3d5ee9e55 [CPUFREQ] Add sup... |
316 |
return -EINVAL; |
2b03f891a [CPUFREQ] checkpa... |
317 |
if (input > 1) |
3d5ee9e55 [CPUFREQ] Add sup... |
318 |
input = 1; |
32ee8c3e4 [CPUFREQ] Lots of... |
319 |
|
2b03f891a [CPUFREQ] checkpa... |
320 |
if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */ |
3d5ee9e55 [CPUFREQ] Add sup... |
321 322 323 |
return count; } dbs_tuners_ins.ignore_nice = input; |
ccb2fe209 [CPUFREQ] Remove ... |
324 |
/* we need to re-evaluate prev_cpu_idle */ |
dac1c1a56 [CPUFREQ] ondeman... |
325 |
for_each_online_cpu(j) { |
ccb2fe209 [CPUFREQ] Remove ... |
326 |
struct cpu_dbs_info_s *dbs_info; |
245b2e70e percpu: clean up ... |
327 |
dbs_info = &per_cpu(od_cpu_dbs_info, j); |
3430502d3 [CPUFREQ][3/6] cp... |
328 329 |
dbs_info->prev_cpu_idle = get_cpu_idle_time(j, &dbs_info->prev_cpu_wall); |
1ca3abdb6 [CPUFREQ] Make ig... |
330 |
if (dbs_tuners_ins.ignore_nice) |
3292beb34 sched/accounting:... |
331 |
dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; |
1ca3abdb6 [CPUFREQ] Make ig... |
332 |
|
3d5ee9e55 [CPUFREQ] Add sup... |
333 |
} |
3d5ee9e55 [CPUFREQ] Add sup... |
334 335 |
return count; } |
0e625ac15 [CPUFREQ] ondeman... |
336 337 |
static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, const char *buf, size_t count) |
05ca0350e [CPUFREQ][2/2] on... |
338 339 340 341 342 343 344 345 346 347 |
{ unsigned int input; int ret; ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; if (input > 1000) input = 1000; |
05ca0350e [CPUFREQ][2/2] on... |
348 349 |
dbs_tuners_ins.powersave_bias = input; ondemand_powersave_bias_init(); |
05ca0350e [CPUFREQ][2/2] on... |
350 351 |
return count; } |
6dad2a296 cpufreq: Unify sy... |
352 |
define_one_global_rw(sampling_rate); |
07d77759c Merge branch 'x86... |
353 |
define_one_global_rw(io_is_busy); |
6dad2a296 cpufreq: Unify sy... |
354 |
define_one_global_rw(up_threshold); |
3f78a9f7f [CPUFREQ] add sam... |
355 |
define_one_global_rw(sampling_down_factor); |
6dad2a296 cpufreq: Unify sy... |
356 357 |
define_one_global_rw(ignore_nice_load); define_one_global_rw(powersave_bias); |
1da177e4c Linux-2.6.12-rc2 |
358 |
|
2b03f891a [CPUFREQ] checkpa... |
359 |
static struct attribute *dbs_attributes[] = { |
1da177e4c Linux-2.6.12-rc2 |
360 361 |
&sampling_rate_min.attr, &sampling_rate.attr, |
1da177e4c Linux-2.6.12-rc2 |
362 |
&up_threshold.attr, |
3f78a9f7f [CPUFREQ] add sam... |
363 |
&sampling_down_factor.attr, |
001893cda [PATCH] cpufreq_c... |
364 |
&ignore_nice_load.attr, |
05ca0350e [CPUFREQ][2/2] on... |
365 |
&powersave_bias.attr, |
19379b118 ondemand: Make th... |
366 |
&io_is_busy.attr, |
1da177e4c Linux-2.6.12-rc2 |
367 368 369 370 371 372 373 374 375 |
NULL }; static struct attribute_group dbs_attr_group = { .attrs = dbs_attributes, .name = "ondemand", }; /************************** sysfs end ************************/ |
00e299fff [CPUFREQ] ondeman... |
376 377 378 379 380 381 382 383 384 385 |
static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) { if (dbs_tuners_ins.powersave_bias) freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H); else if (p->cur == p->max) return; __cpufreq_driver_target(p, freq, dbs_tuners_ins.powersave_bias ? CPUFREQ_RELATION_L : CPUFREQ_RELATION_H); } |
2f8a835c7 [CPUFREQ] Make on... |
386 |
static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) |
1da177e4c Linux-2.6.12-rc2 |
387 |
{ |
c43aa3bd9 [CPUFREQ][2/6] cp... |
388 |
unsigned int max_load_freq; |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 |
struct cpufreq_policy *policy; unsigned int j; |
05ca0350e [CPUFREQ][2/2] on... |
392 |
this_dbs_info->freq_lo = 0; |
1da177e4c Linux-2.6.12-rc2 |
393 |
policy = this_dbs_info->cur_policy; |
ea4876151 [CPUFREQ] ondeman... |
394 |
|
32ee8c3e4 [CPUFREQ] Lots of... |
395 |
/* |
c29f14030 [CPUFREQ] ondeman... |
396 397 |
* Every sampling_rate, we check, if current idle time is less * than 20% (default), then we try to increase frequency |
ccb2fe209 [CPUFREQ] Remove ... |
398 |
* Every sampling_rate, we look for a the lowest |
c29f14030 [CPUFREQ] ondeman... |
399 400 |
* frequency which can sustain the load while keeping idle time over * 30%. If such a frequency exist, we try to decrease to this frequency. |
1da177e4c Linux-2.6.12-rc2 |
401 |
* |
32ee8c3e4 [CPUFREQ] Lots of... |
402 403 404 |
* Any frequency increase takes it to the maximum frequency. * Frequency reduction happens at minimum steps of * 5% (default) of current frequency |
1da177e4c Linux-2.6.12-rc2 |
405 |
*/ |
c43aa3bd9 [CPUFREQ][2/6] cp... |
406 407 |
/* Get Absolute Load - in terms of freq */ max_load_freq = 0; |
835481d9b cpumask: convert ... |
408 |
for_each_cpu(j, policy->cpus) { |
1da177e4c Linux-2.6.12-rc2 |
409 |
struct cpu_dbs_info_s *j_dbs_info; |
6b8fcd902 ondemand: Solve a... |
410 411 |
cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; unsigned int idle_time, wall_time, iowait_time; |
c43aa3bd9 [CPUFREQ][2/6] cp... |
412 413 |
unsigned int load, load_freq; int freq_avg; |
1da177e4c Linux-2.6.12-rc2 |
414 |
|
245b2e70e percpu: clean up ... |
415 |
j_dbs_info = &per_cpu(od_cpu_dbs_info, j); |
3430502d3 [CPUFREQ][3/6] cp... |
416 417 |
cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); |
6b8fcd902 ondemand: Solve a... |
418 |
cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); |
3430502d3 [CPUFREQ][3/6] cp... |
419 |
|
648616343 [S390] cputime: a... |
420 421 |
wall_time = (unsigned int) (cur_wall_time - j_dbs_info->prev_cpu_wall); |
c43aa3bd9 [CPUFREQ][2/6] cp... |
422 |
j_dbs_info->prev_cpu_wall = cur_wall_time; |
648616343 [S390] cputime: a... |
423 424 |
idle_time = (unsigned int) (cur_idle_time - j_dbs_info->prev_cpu_idle); |
c43aa3bd9 [CPUFREQ][2/6] cp... |
425 |
j_dbs_info->prev_cpu_idle = cur_idle_time; |
1da177e4c Linux-2.6.12-rc2 |
426 |
|
648616343 [S390] cputime: a... |
427 428 |
iowait_time = (unsigned int) (cur_iowait_time - j_dbs_info->prev_cpu_iowait); |
6b8fcd902 ondemand: Solve a... |
429 |
j_dbs_info->prev_cpu_iowait = cur_iowait_time; |
1ca3abdb6 [CPUFREQ] Make ig... |
430 |
if (dbs_tuners_ins.ignore_nice) { |
3292beb34 sched/accounting:... |
431 |
u64 cur_nice; |
1ca3abdb6 [CPUFREQ] Make ig... |
432 |
unsigned long cur_nice_jiffies; |
3292beb34 sched/accounting:... |
433 434 |
cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] - j_dbs_info->prev_cpu_nice; |
1ca3abdb6 [CPUFREQ] Make ig... |
435 436 437 438 439 440 |
/* * Assumption: nice time between sampling periods will * be less than 2^32 jiffies for 32 bit sys */ cur_nice_jiffies = (unsigned long) cputime64_to_jiffies64(cur_nice); |
3292beb34 sched/accounting:... |
441 |
j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; |
1ca3abdb6 [CPUFREQ] Make ig... |
442 443 |
idle_time += jiffies_to_usecs(cur_nice_jiffies); } |
6b8fcd902 ondemand: Solve a... |
444 445 446 447 448 449 |
/* * For the purpose of ondemand, waiting for disk IO is an * indication that you're performance critical, and not that * the system is actually idle. So subtract the iowait time * from the cpu idle time. */ |
19379b118 ondemand: Make th... |
450 |
if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time) |
6b8fcd902 ondemand: Solve a... |
451 |
idle_time -= iowait_time; |
3430502d3 [CPUFREQ][3/6] cp... |
452 |
if (unlikely(!wall_time || wall_time < idle_time)) |
c43aa3bd9 [CPUFREQ][2/6] cp... |
453 |
continue; |
c43aa3bd9 [CPUFREQ][2/6] cp... |
454 455 456 457 458 459 460 461 462 463 |
load = 100 * (wall_time - idle_time) / wall_time; freq_avg = __cpufreq_driver_getavg(policy, j); if (freq_avg <= 0) freq_avg = policy->cur; load_freq = load * freq_avg; if (load_freq > max_load_freq) max_load_freq = load_freq; |
1da177e4c Linux-2.6.12-rc2 |
464 |
} |
ccb2fe209 [CPUFREQ] Remove ... |
465 |
/* Check for frequency increase */ |
c43aa3bd9 [CPUFREQ][2/6] cp... |
466 |
if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) { |
3f78a9f7f [CPUFREQ] add sam... |
467 468 469 470 |
/* If switching to max speed, apply sampling_down_factor */ if (policy->cur < policy->max) this_dbs_info->rate_mult = dbs_tuners_ins.sampling_down_factor; |
00e299fff [CPUFREQ] ondeman... |
471 |
dbs_freq_increase(policy, policy->max); |
1da177e4c Linux-2.6.12-rc2 |
472 473 474 475 |
return; } /* Check for frequency decrease */ |
c29f14030 [CPUFREQ] ondeman... |
476 477 478 |
/* if we cannot reduce the frequency anymore, break out early */ if (policy->cur == policy->min) return; |
1da177e4c Linux-2.6.12-rc2 |
479 |
|
c29f14030 [CPUFREQ] ondeman... |
480 481 482 483 484 |
/* * The optimal frequency is the frequency that is the lowest that * can support the current CPU usage without triggering the up * policy. To be safe, we focus 10 points under the threshold. */ |
e9d95bf7e [CPUFREQ][4/6] cp... |
485 486 487 |
if (max_load_freq < (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) * policy->cur) { |
c43aa3bd9 [CPUFREQ][2/6] cp... |
488 |
unsigned int freq_next; |
e9d95bf7e [CPUFREQ][4/6] cp... |
489 490 491 |
freq_next = max_load_freq / (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential); |
dfde5d62e [CPUFREQ][8/8] ac... |
492 |
|
3f78a9f7f [CPUFREQ] add sam... |
493 494 |
/* No longer fully busy, reset rate_mult */ this_dbs_info->rate_mult = 1; |
1dbf58881 [CPUFREQ] Fix ond... |
495 496 |
if (freq_next < policy->min) freq_next = policy->min; |
05ca0350e [CPUFREQ][2/2] on... |
497 498 499 500 501 502 503 504 505 |
if (!dbs_tuners_ins.powersave_bias) { __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); } else { int freq = powersave_bias_target(policy, freq_next, CPUFREQ_RELATION_L); __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); } |
ccb2fe209 [CPUFREQ] Remove ... |
506 |
} |
1da177e4c Linux-2.6.12-rc2 |
507 |
} |
c4028958b WorkStruct: make ... |
508 |
static void do_dbs_timer(struct work_struct *work) |
32ee8c3e4 [CPUFREQ] Lots of... |
509 |
{ |
529af7a14 [CPUFREQ] ondeman... |
510 511 512 513 |
struct cpu_dbs_info_s *dbs_info = container_of(work, struct cpu_dbs_info_s, work.work); unsigned int cpu = dbs_info->cpu; int sample_type = dbs_info->sample_type; |
5cb2c3bd0 [CPUFREQ] calcula... |
514 |
int delay; |
a665df9d5 [CPUFREQ] ondeman... |
515 |
|
5a75c8282 [CPUFREQ] Cleanup... |
516 |
mutex_lock(&dbs_info->timer_mutex); |
56463b78c [CPUFREQ] ondeman... |
517 |
|
05ca0350e [CPUFREQ][2/2] on... |
518 |
/* Common NORMAL_SAMPLE setup */ |
c4028958b WorkStruct: make ... |
519 |
dbs_info->sample_type = DBS_NORMAL_SAMPLE; |
05ca0350e [CPUFREQ][2/2] on... |
520 |
if (!dbs_tuners_ins.powersave_bias || |
c4028958b WorkStruct: make ... |
521 |
sample_type == DBS_NORMAL_SAMPLE) { |
05ca0350e [CPUFREQ][2/2] on... |
522 |
dbs_check_cpu(dbs_info); |
05ca0350e [CPUFREQ][2/2] on... |
523 524 |
if (dbs_info->freq_lo) { /* Setup timer for SUB_SAMPLE */ |
c4028958b WorkStruct: make ... |
525 |
dbs_info->sample_type = DBS_SUB_SAMPLE; |
05ca0350e [CPUFREQ][2/2] on... |
526 |
delay = dbs_info->freq_hi_jiffies; |
5cb2c3bd0 [CPUFREQ] calcula... |
527 528 529 530 531 532 533 534 535 |
} else { /* We want all CPUs to do sampling nearly on * same jiffy */ delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate * dbs_info->rate_mult); if (num_online_cpus() > 1) delay -= jiffies % delay; |
05ca0350e [CPUFREQ][2/2] on... |
536 537 538 |
} } else { __cpufreq_driver_target(dbs_info->cur_policy, |
2b03f891a [CPUFREQ] checkpa... |
539 |
dbs_info->freq_lo, CPUFREQ_RELATION_H); |
5cb2c3bd0 [CPUFREQ] calcula... |
540 |
delay = dbs_info->freq_lo_jiffies; |
05ca0350e [CPUFREQ][2/2] on... |
541 |
} |
57df5573a cpufreq: use syst... |
542 |
schedule_delayed_work_on(cpu, &dbs_info->work, delay); |
5a75c8282 [CPUFREQ] Cleanup... |
543 |
mutex_unlock(&dbs_info->timer_mutex); |
32ee8c3e4 [CPUFREQ] Lots of... |
544 |
} |
1da177e4c Linux-2.6.12-rc2 |
545 |
|
529af7a14 [CPUFREQ] ondeman... |
546 |
static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) |
1da177e4c Linux-2.6.12-rc2 |
547 |
{ |
1ce28d6b1 [CPUFREQ][1/2] on... |
548 549 |
/* We want all CPUs to do sampling nearly on same jiffy */ int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); |
a665df9d5 [CPUFREQ] ondeman... |
550 551 552 |
if (num_online_cpus() > 1) delay -= jiffies % delay; |
2f8a835c7 [CPUFREQ] Make on... |
553 |
|
c4028958b WorkStruct: make ... |
554 |
dbs_info->sample_type = DBS_NORMAL_SAMPLE; |
28287033e Add a new deferra... |
555 |
INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); |
57df5573a cpufreq: use syst... |
556 |
schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay); |
1da177e4c Linux-2.6.12-rc2 |
557 |
} |
2cd7cbdf4 [cpufreq] ondeman... |
558 |
static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) |
1da177e4c Linux-2.6.12-rc2 |
559 |
{ |
b14893a62 [CPUFREQ] fix tim... |
560 |
cancel_delayed_work_sync(&dbs_info->work); |
1da177e4c Linux-2.6.12-rc2 |
561 |
} |
19379b118 ondemand: Make th... |
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
/* * Not all CPUs want IO time to be accounted as busy; this dependson how * efficient idling at a higher frequency/voltage is. * Pavel Machek says this is not so for various generations of AMD and old * Intel systems. * Mike Chan (androidlcom) calis this is also not true for ARM. * Because of this, whitelist specific known (series) of CPUs by default, and * leave all others up to the user. */ static int should_io_be_busy(void) { #if defined(CONFIG_X86) /* * For Intel, Core 2 (model 15) andl later have an efficient idle. */ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model >= 15) return 1; #endif return 0; } |
1da177e4c Linux-2.6.12-rc2 |
584 585 586 587 588 589 |
static int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event) { unsigned int cpu = policy->cpu; struct cpu_dbs_info_s *this_dbs_info; unsigned int j; |
914f7c31b [CPUFREQ] handle ... |
590 |
int rc; |
1da177e4c Linux-2.6.12-rc2 |
591 |
|
245b2e70e percpu: clean up ... |
592 |
this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu); |
1da177e4c Linux-2.6.12-rc2 |
593 594 595 |
switch (event) { case CPUFREQ_GOV_START: |
ffac80e92 [CPUFREQ] Misc cl... |
596 |
if ((!cpu_online(cpu)) || (!policy->cur)) |
1da177e4c Linux-2.6.12-rc2 |
597 |
return -EINVAL; |
3fc54d37a [CPUFREQ] Convert... |
598 |
mutex_lock(&dbs_mutex); |
914f7c31b [CPUFREQ] handle ... |
599 |
|
5a75c8282 [CPUFREQ] Cleanup... |
600 |
dbs_enable++; |
835481d9b cpumask: convert ... |
601 |
for_each_cpu(j, policy->cpus) { |
1da177e4c Linux-2.6.12-rc2 |
602 |
struct cpu_dbs_info_s *j_dbs_info; |
245b2e70e percpu: clean up ... |
603 |
j_dbs_info = &per_cpu(od_cpu_dbs_info, j); |
1da177e4c Linux-2.6.12-rc2 |
604 |
j_dbs_info->cur_policy = policy; |
32ee8c3e4 [CPUFREQ] Lots of... |
605 |
|
3430502d3 [CPUFREQ][3/6] cp... |
606 607 |
j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j, &j_dbs_info->prev_cpu_wall); |
3292beb34 sched/accounting:... |
608 |
if (dbs_tuners_ins.ignore_nice) |
1ca3abdb6 [CPUFREQ] Make ig... |
609 |
j_dbs_info->prev_cpu_nice = |
3292beb34 sched/accounting:... |
610 |
kcpustat_cpu(j).cpustat[CPUTIME_NICE]; |
1da177e4c Linux-2.6.12-rc2 |
611 |
} |
529af7a14 [CPUFREQ] ondeman... |
612 |
this_dbs_info->cpu = cpu; |
3f78a9f7f [CPUFREQ] add sam... |
613 |
this_dbs_info->rate_mult = 1; |
5a75c8282 [CPUFREQ] Cleanup... |
614 |
ondemand_powersave_bias_init_cpu(cpu); |
1da177e4c Linux-2.6.12-rc2 |
615 616 617 618 619 620 |
/* * Start the timerschedule work, when this governor * is used for first time */ if (dbs_enable == 1) { unsigned int latency; |
0e625ac15 [CPUFREQ] ondeman... |
621 622 623 624 625 626 627 |
rc = sysfs_create_group(cpufreq_global_kobject, &dbs_attr_group); if (rc) { mutex_unlock(&dbs_mutex); return rc; } |
1da177e4c Linux-2.6.12-rc2 |
628 |
/* policy latency is in nS. Convert it to uS first */ |
df8b59be0 [CPUFREQ] Avoid t... |
629 630 631 |
latency = policy->cpuinfo.transition_latency / 1000; if (latency == 0) latency = 1; |
cef9615a8 [CPUFREQ] ondeman... |
632 633 634 635 636 637 |
/* Bring kernel and HW constraints together */ min_sampling_rate = max(min_sampling_rate, MIN_LATENCY_MULTIPLIER * latency); dbs_tuners_ins.sampling_rate = max(min_sampling_rate, latency * LATENCY_MULTIPLIER); |
19379b118 ondemand: Make th... |
638 |
dbs_tuners_ins.io_is_busy = should_io_be_busy(); |
1da177e4c Linux-2.6.12-rc2 |
639 |
} |
3fc54d37a [CPUFREQ] Convert... |
640 |
mutex_unlock(&dbs_mutex); |
7d26e2d5e [CPUFREQ] Elimina... |
641 |
|
0e625ac15 [CPUFREQ] ondeman... |
642 |
mutex_init(&this_dbs_info->timer_mutex); |
7d26e2d5e [CPUFREQ] Elimina... |
643 |
dbs_timer_init(this_dbs_info); |
1da177e4c Linux-2.6.12-rc2 |
644 645 646 |
break; case CPUFREQ_GOV_STOP: |
2cd7cbdf4 [cpufreq] ondeman... |
647 |
dbs_timer_exit(this_dbs_info); |
7d26e2d5e [CPUFREQ] Elimina... |
648 649 |
mutex_lock(&dbs_mutex); |
5a75c8282 [CPUFREQ] Cleanup... |
650 |
mutex_destroy(&this_dbs_info->timer_mutex); |
1da177e4c Linux-2.6.12-rc2 |
651 |
dbs_enable--; |
3fc54d37a [CPUFREQ] Convert... |
652 |
mutex_unlock(&dbs_mutex); |
0e625ac15 [CPUFREQ] ondeman... |
653 654 655 |
if (!dbs_enable) sysfs_remove_group(cpufreq_global_kobject, &dbs_attr_group); |
1da177e4c Linux-2.6.12-rc2 |
656 657 658 659 |
break; case CPUFREQ_GOV_LIMITS: |
5a75c8282 [CPUFREQ] Cleanup... |
660 |
mutex_lock(&this_dbs_info->timer_mutex); |
1da177e4c Linux-2.6.12-rc2 |
661 |
if (policy->max < this_dbs_info->cur_policy->cur) |
ffac80e92 [CPUFREQ] Misc cl... |
662 |
__cpufreq_driver_target(this_dbs_info->cur_policy, |
2b03f891a [CPUFREQ] checkpa... |
663 |
policy->max, CPUFREQ_RELATION_H); |
1da177e4c Linux-2.6.12-rc2 |
664 |
else if (policy->min > this_dbs_info->cur_policy->cur) |
ffac80e92 [CPUFREQ] Misc cl... |
665 |
__cpufreq_driver_target(this_dbs_info->cur_policy, |
2b03f891a [CPUFREQ] checkpa... |
666 |
policy->min, CPUFREQ_RELATION_L); |
5a75c8282 [CPUFREQ] Cleanup... |
667 |
mutex_unlock(&this_dbs_info->timer_mutex); |
1da177e4c Linux-2.6.12-rc2 |
668 669 670 671 |
break; } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
672 673 |
static int __init cpufreq_gov_dbs_init(void) { |
4f6e6b9f9 [CPUFREQ] Fix BUG... |
674 675 |
u64 idle_time; int cpu = get_cpu(); |
808009131 [CPUFREQ][6/6] cp... |
676 |
|
21f2e3c86 [CPUFREQ] Remove ... |
677 |
idle_time = get_cpu_idle_time_us(cpu, NULL); |
4f6e6b9f9 [CPUFREQ] Fix BUG... |
678 |
put_cpu(); |
808009131 [CPUFREQ][6/6] cp... |
679 680 681 682 683 |
if (idle_time != -1ULL) { /* Idle micro accounting is supported. Use finer thresholds */ dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; dbs_tuners_ins.down_differential = MICRO_FREQUENCY_DOWN_DIFFERENTIAL; |
cef9615a8 [CPUFREQ] ondeman... |
684 |
/* |
bd74b32b7 Fix documentation... |
685 |
* In nohz/micro accounting case we set the minimum frequency |
cef9615a8 [CPUFREQ] ondeman... |
686 687 688 689 690 691 692 693 |
* not depending on HZ, but fixed (very low). The deferred * timer might skip some samples if idle/sleeping as needed. */ min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; } else { /* For correct statistics, we need 10 ticks for each measure */ min_sampling_rate = MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10); |
808009131 [CPUFREQ][6/6] cp... |
694 |
} |
888a794ca [CPUFREQ] add err... |
695 |
|
57df5573a cpufreq: use syst... |
696 |
return cpufreq_register_governor(&cpufreq_gov_ondemand); |
1da177e4c Linux-2.6.12-rc2 |
697 698 699 700 |
} static void __exit cpufreq_gov_dbs_exit(void) { |
1c2562459 [CPUFREQ] allow o... |
701 |
cpufreq_unregister_governor(&cpufreq_gov_ondemand); |
1da177e4c Linux-2.6.12-rc2 |
702 |
} |
ffac80e92 [CPUFREQ] Misc cl... |
703 704 705 |
MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>"); MODULE_AUTHOR("Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>"); MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for " |
2b03f891a [CPUFREQ] checkpa... |
706 |
"Low Latency Frequency Transition capable processors"); |
ffac80e92 [CPUFREQ] Misc cl... |
707 |
MODULE_LICENSE("GPL"); |
1da177e4c Linux-2.6.12-rc2 |
708 |
|
6915719b3 cpufreq: Initiali... |
709 710 711 |
#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND fs_initcall(cpufreq_gov_dbs_init); #else |
1da177e4c Linux-2.6.12-rc2 |
712 |
module_init(cpufreq_gov_dbs_init); |
6915719b3 cpufreq: Initiali... |
713 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
714 |
module_exit(cpufreq_gov_dbs_exit); |