diff options
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 107 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 20 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 9 | ||||
-rw-r--r-- | include/asm-i386/msr.h | 3 | ||||
-rw-r--r-- | include/asm-x86_64/msr.h | 3 | ||||
-rw-r--r-- | include/linux/cpufreq.h | 3 |
6 files changed, 143 insertions, 2 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 8b0c7db85a47..f8a8e46acb78 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -58,10 +58,12 @@ enum { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | #define INTEL_MSR_RANGE (0xffff) | 60 | #define INTEL_MSR_RANGE (0xffff) |
61 | #define CPUID_6_ECX_APERFMPERF_CAPABILITY (0x1) | ||
61 | 62 | ||
62 | struct acpi_cpufreq_data { | 63 | struct acpi_cpufreq_data { |
63 | struct acpi_processor_performance *acpi_data; | 64 | struct acpi_processor_performance *acpi_data; |
64 | struct cpufreq_frequency_table *freq_table; | 65 | struct cpufreq_frequency_table *freq_table; |
66 | unsigned int max_freq; | ||
65 | unsigned int resume; | 67 | unsigned int resume; |
66 | unsigned int cpu_feature; | 68 | unsigned int cpu_feature; |
67 | }; | 69 | }; |
@@ -258,6 +260,100 @@ static u32 get_cur_val(cpumask_t mask) | |||
258 | return cmd.val; | 260 | return cmd.val; |
259 | } | 261 | } |
260 | 262 | ||
263 | /* | ||
264 | * Return the measured active (C0) frequency on this CPU since last call | ||
265 | * to this function. | ||
266 | * Input: cpu number | ||
267 | * Return: Average CPU frequency in terms of max frequency (zero on error) | ||
268 | * | ||
269 | * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance | ||
270 | * over a period of time, while CPU is in C0 state. | ||
271 | * IA32_MPERF counts at the rate of max advertised frequency | ||
272 | * IA32_APERF counts at the rate of actual CPU frequency | ||
273 | * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and | ||
274 | * no meaning should be associated with absolute values of these MSRs. | ||
275 | */ | ||
276 | static unsigned int get_measured_perf(unsigned int cpu) | ||
277 | { | ||
278 | union { | ||
279 | struct { | ||
280 | u32 lo; | ||
281 | u32 hi; | ||
282 | } split; | ||
283 | u64 whole; | ||
284 | } aperf_cur, mperf_cur; | ||
285 | |||
286 | cpumask_t saved_mask; | ||
287 | unsigned int perf_percent; | ||
288 | unsigned int retval; | ||
289 | |||
290 | saved_mask = current->cpus_allowed; | ||
291 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | ||
292 | if (get_cpu() != cpu) { | ||
293 | /* We were not able to run on requested processor */ | ||
294 | put_cpu(); | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi); | ||
299 | rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi); | ||
300 | |||
301 | wrmsr(MSR_IA32_APERF, 0,0); | ||
302 | wrmsr(MSR_IA32_MPERF, 0,0); | ||
303 | |||
304 | #ifdef __i386__ | ||
305 | /* | ||
306 | * We dont want to do 64 bit divide with 32 bit kernel | ||
307 | * Get an approximate value. Return failure in case we cannot get | ||
308 | * an approximate value. | ||
309 | */ | ||
310 | if (unlikely(aperf_cur.split.hi || mperf_cur.split.hi)) { | ||
311 | int shift_count; | ||
312 | u32 h; | ||
313 | |||
314 | h = max_t(u32, aperf_cur.split.hi, mperf_cur.split.hi); | ||
315 | shift_count = fls(h); | ||
316 | |||
317 | aperf_cur.whole >>= shift_count; | ||
318 | mperf_cur.whole >>= shift_count; | ||
319 | } | ||
320 | |||
321 | if (((unsigned long)(-1) / 100) < aperf_cur.split.lo) { | ||
322 | int shift_count = 7; | ||
323 | aperf_cur.split.lo >>= shift_count; | ||
324 | mperf_cur.split.lo >>= shift_count; | ||
325 | } | ||
326 | |||
327 | if (aperf_cur.split.lo && mperf_cur.split.lo) { | ||
328 | perf_percent = (aperf_cur.split.lo * 100) / mperf_cur.split.lo; | ||
329 | } else { | ||
330 | perf_percent = 0; | ||
331 | } | ||
332 | |||
333 | #else | ||
334 | if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) { | ||
335 | int shift_count = 7; | ||
336 | aperf_cur.whole >>= shift_count; | ||
337 | mperf_cur.whole >>= shift_count; | ||
338 | } | ||
339 | |||
340 | if (aperf_cur.whole && mperf_cur.whole) { | ||
341 | perf_percent = (aperf_cur.whole * 100) / mperf_cur.whole; | ||
342 | } else { | ||
343 | perf_percent = 0; | ||
344 | } | ||
345 | |||
346 | #endif | ||
347 | |||
348 | retval = drv_data[cpu]->max_freq * perf_percent / 100; | ||
349 | |||
350 | put_cpu(); | ||
351 | set_cpus_allowed(current, saved_mask); | ||
352 | |||
353 | dprintk("cpu %d: performance percent %d\n", cpu, perf_percent); | ||
354 | return retval; | ||
355 | } | ||
356 | |||
261 | static unsigned int get_cur_freq_on_cpu(unsigned int cpu) | 357 | static unsigned int get_cur_freq_on_cpu(unsigned int cpu) |
262 | { | 358 | { |
263 | struct acpi_cpufreq_data *data = drv_data[cpu]; | 359 | struct acpi_cpufreq_data *data = drv_data[cpu]; |
@@ -497,7 +593,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
497 | unsigned int valid_states = 0; | 593 | unsigned int valid_states = 0; |
498 | unsigned int cpu = policy->cpu; | 594 | unsigned int cpu = policy->cpu; |
499 | struct acpi_cpufreq_data *data; | 595 | struct acpi_cpufreq_data *data; |
500 | unsigned int l, h; | ||
501 | unsigned int result = 0; | 596 | unsigned int result = 0; |
502 | struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; | 597 | struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; |
503 | struct acpi_processor_performance *perf; | 598 | struct acpi_processor_performance *perf; |
@@ -591,6 +686,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
591 | } | 686 | } |
592 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | 687 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; |
593 | 688 | ||
689 | data->max_freq = perf->states[0].core_frequency * 1000; | ||
594 | /* table init */ | 690 | /* table init */ |
595 | for (i = 0; i < perf->state_count; i++) { | 691 | for (i = 0; i < perf->state_count; i++) { |
596 | if (i > 0 && perf->states[i].core_frequency == | 692 | if (i > 0 && perf->states[i].core_frequency == |
@@ -625,6 +721,15 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
625 | /* notify BIOS that we exist */ | 721 | /* notify BIOS that we exist */ |
626 | acpi_processor_notify_smm(THIS_MODULE); | 722 | acpi_processor_notify_smm(THIS_MODULE); |
627 | 723 | ||
724 | /* Check for APERF/MPERF support in hardware */ | ||
725 | if (c->x86_vendor == X86_VENDOR_INTEL && c->cpuid_level >= 6) { | ||
726 | unsigned int ecx; | ||
727 | ecx = cpuid_ecx(6); | ||
728 | if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY) { | ||
729 | acpi_cpufreq_driver.getavg = get_measured_perf; | ||
730 | } | ||
731 | } | ||
732 | |||
628 | dprintk("CPU%u - ACPI performance management activated.\n", cpu); | 733 | dprintk("CPU%u - ACPI performance management activated.\n", cpu); |
629 | for (i = 0; i < perf->state_count; i++) | 734 | for (i = 0; i < perf->state_count; i++) |
630 | dprintk(" %cP%d: %d MHz, %d mW, %d uS\n", | 735 | dprintk(" %cP%d: %d MHz, %d mW, %d uS\n", |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 86e69b7f9122..56c433e64d58 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -1274,6 +1274,26 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, | |||
1274 | } | 1274 | } |
1275 | EXPORT_SYMBOL_GPL(cpufreq_driver_target); | 1275 | EXPORT_SYMBOL_GPL(cpufreq_driver_target); |
1276 | 1276 | ||
1277 | int cpufreq_driver_getavg(struct cpufreq_policy *policy) | ||
1278 | { | ||
1279 | int ret = 0; | ||
1280 | |||
1281 | policy = cpufreq_cpu_get(policy->cpu); | ||
1282 | if (!policy) | ||
1283 | return -EINVAL; | ||
1284 | |||
1285 | mutex_lock(&policy->lock); | ||
1286 | |||
1287 | if (cpu_online(policy->cpu) && cpufreq_driver->getavg) | ||
1288 | ret = cpufreq_driver->getavg(policy->cpu); | ||
1289 | |||
1290 | mutex_unlock(&policy->lock); | ||
1291 | |||
1292 | cpufreq_cpu_put(policy); | ||
1293 | return ret; | ||
1294 | } | ||
1295 | EXPORT_SYMBOL_GPL(cpufreq_driver_getavg); | ||
1296 | |||
1277 | /* | 1297 | /* |
1278 | * Locking: Must be called with the lock_cpu_hotplug() lock held | 1298 | * Locking: Must be called with the lock_cpu_hotplug() lock held |
1279 | * when "event" is CPUFREQ_GOV_LIMITS | 1299 | * when "event" is CPUFREQ_GOV_LIMITS |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bf8aa45d4f01..291cfe9400a1 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
@@ -393,8 +393,15 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
393 | * policy. To be safe, we focus 10 points under the threshold. | 393 | * policy. To be safe, we focus 10 points under the threshold. |
394 | */ | 394 | */ |
395 | if (load < (dbs_tuners_ins.up_threshold - 10)) { | 395 | if (load < (dbs_tuners_ins.up_threshold - 10)) { |
396 | unsigned int freq_next = (policy->cur * load) / | 396 | unsigned int freq_next, freq_cur; |
397 | |||
398 | freq_cur = cpufreq_driver_getavg(policy); | ||
399 | if (!freq_cur) | ||
400 | freq_cur = policy->cur; | ||
401 | |||
402 | freq_next = (freq_cur * load) / | ||
397 | (dbs_tuners_ins.up_threshold - 10); | 403 | (dbs_tuners_ins.up_threshold - 10); |
404 | |||
398 | if (!dbs_tuners_ins.powersave_bias) { | 405 | if (!dbs_tuners_ins.powersave_bias) { |
399 | __cpufreq_driver_target(policy, freq_next, | 406 | __cpufreq_driver_target(policy, freq_next, |
400 | CPUFREQ_RELATION_L); | 407 | CPUFREQ_RELATION_L); |
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h index 62b76cd96957..0aa15fc8d918 100644 --- a/include/asm-i386/msr.h +++ b/include/asm-i386/msr.h | |||
@@ -125,6 +125,9 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val) | |||
125 | #define MSR_IA32_PERF_STATUS 0x198 | 125 | #define MSR_IA32_PERF_STATUS 0x198 |
126 | #define MSR_IA32_PERF_CTL 0x199 | 126 | #define MSR_IA32_PERF_CTL 0x199 |
127 | 127 | ||
128 | #define MSR_IA32_MPERF 0xE7 | ||
129 | #define MSR_IA32_APERF 0xE8 | ||
130 | |||
128 | #define MSR_IA32_THERM_CONTROL 0x19a | 131 | #define MSR_IA32_THERM_CONTROL 0x19a |
129 | #define MSR_IA32_THERM_INTERRUPT 0x19b | 132 | #define MSR_IA32_THERM_INTERRUPT 0x19b |
130 | #define MSR_IA32_THERM_STATUS 0x19c | 133 | #define MSR_IA32_THERM_STATUS 0x19c |
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h index 37e194169fac..e61582288737 100644 --- a/include/asm-x86_64/msr.h +++ b/include/asm-x86_64/msr.h | |||
@@ -307,6 +307,9 @@ static inline unsigned int cpuid_edx(unsigned int op) | |||
307 | #define MSR_IA32_PERF_STATUS 0x198 | 307 | #define MSR_IA32_PERF_STATUS 0x198 |
308 | #define MSR_IA32_PERF_CTL 0x199 | 308 | #define MSR_IA32_PERF_CTL 0x199 |
309 | 309 | ||
310 | #define MSR_IA32_MPERF 0xE7 | ||
311 | #define MSR_IA32_APERF 0xE8 | ||
312 | |||
310 | #define MSR_IA32_THERM_CONTROL 0x19a | 313 | #define MSR_IA32_THERM_CONTROL 0x19a |
311 | #define MSR_IA32_THERM_INTERRUPT 0x19b | 314 | #define MSR_IA32_THERM_INTERRUPT 0x19b |
312 | #define MSR_IA32_THERM_STATUS 0x19c | 315 | #define MSR_IA32_THERM_STATUS 0x19c |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 4ea39fee99c7..7f008f6bfdc3 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -172,6 +172,8 @@ extern int __cpufreq_driver_target(struct cpufreq_policy *policy, | |||
172 | unsigned int relation); | 172 | unsigned int relation); |
173 | 173 | ||
174 | 174 | ||
175 | extern int cpufreq_driver_getavg(struct cpufreq_policy *policy); | ||
176 | |||
175 | int cpufreq_register_governor(struct cpufreq_governor *governor); | 177 | int cpufreq_register_governor(struct cpufreq_governor *governor); |
176 | void cpufreq_unregister_governor(struct cpufreq_governor *governor); | 178 | void cpufreq_unregister_governor(struct cpufreq_governor *governor); |
177 | 179 | ||
@@ -204,6 +206,7 @@ struct cpufreq_driver { | |||
204 | unsigned int (*get) (unsigned int cpu); | 206 | unsigned int (*get) (unsigned int cpu); |
205 | 207 | ||
206 | /* optional */ | 208 | /* optional */ |
209 | unsigned int (*getavg) (unsigned int cpu); | ||
207 | int (*exit) (struct cpufreq_policy *policy); | 210 | int (*exit) (struct cpufreq_policy *policy); |
208 | int (*suspend) (struct cpufreq_policy *policy, pm_message_t pmsg); | 211 | int (*suspend) (struct cpufreq_policy *policy, pm_message_t pmsg); |
209 | int (*resume) (struct cpufreq_policy *policy); | 212 | int (*resume) (struct cpufreq_policy *policy); |