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.
This commit is contained in:
Nathan Whitehorn 2009-05-31 08:59:15 +00:00
parent c22ca7f04f
commit f436f17508
2 changed files with 31 additions and 12 deletions

View File

@ -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;

View File

@ -36,6 +36,7 @@
*/
#define CPU_IVAR_PCPU 1
#define CPU_IVAR_NOMINAL_MHZ 2
static __inline struct pcpu *cpu_get_pcpu(device_t dev)
{
@ -44,6 +45,15 @@ static __inline struct pcpu *cpu_get_pcpu(device_t dev)
return ((struct pcpu *)v);
}
static __inline int32_t cpu_get_nominal_mhz(device_t dev)
{
uintptr_t v = 0;
if (BUS_READ_IVAR(device_get_parent(dev), dev,
CPU_IVAR_NOMINAL_MHZ, &v) != 0)
return (-1);
return ((int32_t)v);
}
/*
* CPU frequency control interface.
*/