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:
parent
c22ca7f04f
commit
f436f17508
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user