summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_cpu.c
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2009-05-31 08:59:15 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2009-05-31 08:59:15 +0000
commit71b3aa67385738a9468cd53579db0bab9d9e1b11 (patch)
tree030b83e49101bf16a03e903c30d999414d9ed8e8 /sys/kern/kern_cpu.c
parent30e73eac6de760d0293a34ebc877732430398679 (diff)
downloadFreeBSD-src-71b3aa67385738a9468cd53579db0bab9d9e1b11.zip
FreeBSD-src-71b3aa67385738a9468cd53579db0bab9d9e1b11.tar.gz
Provide a new CPU device driver ivar to report the nominal speed of the
CPU, if available. This is meant to solve the issue of cpufreq misreporting speeds on CPUs that boot in a reduced power mode and have only relative speed control.
Diffstat (limited to 'sys/kern/kern_cpu.c')
-rw-r--r--sys/kern/kern_cpu.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/sys/kern/kern_cpu.c b/sys/kern/kern_cpu.c
index 7b0b588..9f7f615 100644
--- a/sys/kern/kern_cpu.c
+++ b/sys/kern/kern_cpu.c
@@ -158,12 +158,16 @@ cpufreq_attach(device_t dev)
CF_MTX_INIT(&sc->lock);
sc->curr_level.total_set.freq = CPUFREQ_VAL_UNKNOWN;
SLIST_INIT(&sc->saved_freq);
- /* Try to get current CPU freq to use it as maximum later if needed */
- pc = cpu_get_pcpu(dev);
- if (cpu_est_clockrate(pc->pc_cpuid, &rate) == 0)
- sc->max_mhz = rate / 1000000;
- else
- sc->max_mhz = CPUFREQ_VAL_UNKNOWN;
+ /* Try to get nominal CPU freq to use it as maximum later if needed */
+ sc->max_mhz = cpu_get_nominal_mhz(dev);
+ /* If that fails, try to measure the current rate */
+ if (sc->max_mhz <= 0) {
+ pc = cpu_get_pcpu(dev);
+ if (cpu_est_clockrate(pc->pc_cpuid, &rate) == 0)
+ sc->max_mhz = rate / 1000000;
+ else
+ sc->max_mhz = CPUFREQ_VAL_UNKNOWN;
+ }
/*
* Only initialize one set of sysctls for all CPUs. In the future,
@@ -581,15 +585,20 @@ cf_levels_method(device_t dev, struct cf_level *levels, int *count)
/*
* If there are no absolute levels, create a fake one at 100%. We
* then cache the clockrate for later use as our base frequency.
- *
- * XXX This assumes that the first time through, if we only have
- * relative drivers, the CPU is currently running at 100%.
*/
if (TAILQ_EMPTY(&sc->all_levels)) {
if (sc->max_mhz == CPUFREQ_VAL_UNKNOWN) {
- pc = cpu_get_pcpu(dev);
- cpu_est_clockrate(pc->pc_cpuid, &rate);
- sc->max_mhz = rate / 1000000;
+ sc->max_mhz = cpu_get_nominal_mhz(dev);
+ /*
+ * If the CPU can't report a rate for 100%, hope
+ * the CPU is running at its nominal rate right now,
+ * and use that instead.
+ */
+ if (sc->max_mhz <= 0) {
+ pc = cpu_get_pcpu(dev);
+ cpu_est_clockrate(pc->pc_cpuid, &rate);
+ sc->max_mhz = rate / 1000000;
+ }
}
memset(&sets[0], CPUFREQ_VAL_UNKNOWN, sizeof(*sets));
sets[0].freq = sc->max_mhz;
OpenPOWER on IntegriCloud