Add support for probing EST settings from ACPI. This should handle more

modern CPUs that have multiple VID#s that aren't detectable via public
methods.  We use the control value from acpi_perf as the id16 for setting
a given frequency.
This commit is contained in:
Nate Lawson 2005-03-21 06:43:25 +00:00
parent 602778ab8e
commit b6604696b6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=143902

View File

@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/smp.h>
#include <sys/systm.h>
@ -52,6 +53,7 @@ typedef struct {
uint16_t freq;
uint16_t volts;
uint16_t id16;
int power;
} freq_info;
/* Identifying characteristics of a processor and supported frequencies. */
@ -59,12 +61,13 @@ typedef struct {
const char *vendor;
uint32_t id32;
uint32_t bus_clk;
const freq_info *freqtab;
freq_info *freqtab;
} cpu_info;
struct est_softc {
device_t dev;
const freq_info *freq_list;
device_t dev;
int acpi_settings;
freq_info *freq_list;
};
/* Convert MHz and mV into IDs for passing to the MSR. */
@ -75,7 +78,7 @@ struct est_softc {
/* Format for storing IDs in our table. */
#define FREQ_INFO(MHz, mV, bus_clk) \
{ MHz, mV, ID16(MHz, mV, bus_clk) }
{ MHz, mV, ID16(MHz, mV, bus_clk), CPUFREQ_VAL_UNKNOWN }
#define INTEL(tab, zhi, vhi, zlo, vlo, bus_clk) \
{ GenuineIntel, ID32(zhi, vhi, zlo, vlo, bus_clk), bus_clk, tab }
@ -95,13 +98,13 @@ CTASSERT(EST_MAX_SETTINGS <= MAX_SETTINGS);
* Frequency (MHz) and voltage (mV) settings. Data from the
* Intel Pentium M Processor Datasheet (Order Number 252612), Table 5.
*
* XXX New Dothan processors have multiple VID# with different
* settings for each VID#. Since we can't uniquely identify this info
* Dothan processors have multiple VID#s with different settings for
* each VID#. Since we can't uniquely identify this info
* without undisclosed methods from Intel, we can't support newer
* processors with this table method. If ACPI Px states are supported,
* we can get info from them.
* we get info from them.
*/
const freq_info PM17_130[] = {
static freq_info PM17_130[] = {
/* 130nm 1.70GHz Pentium M */
FREQ_INFO(1700, 1484, INTEL_BUS_CLK),
FREQ_INFO(1400, 1308, INTEL_BUS_CLK),
@ -111,7 +114,7 @@ const freq_info PM17_130[] = {
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM16_130[] = {
static freq_info PM16_130[] = {
/* 130nm 1.60GHz Pentium M */
FREQ_INFO(1600, 1484, INTEL_BUS_CLK),
FREQ_INFO(1400, 1420, INTEL_BUS_CLK),
@ -121,7 +124,7 @@ const freq_info PM16_130[] = {
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM15_130[] = {
static freq_info PM15_130[] = {
/* 130nm 1.50GHz Pentium M */
FREQ_INFO(1500, 1484, INTEL_BUS_CLK),
FREQ_INFO(1400, 1452, INTEL_BUS_CLK),
@ -131,7 +134,7 @@ const freq_info PM15_130[] = {
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM14_130[] = {
static freq_info PM14_130[] = {
/* 130nm 1.40GHz Pentium M */
FREQ_INFO(1400, 1484, INTEL_BUS_CLK),
FREQ_INFO(1200, 1436, INTEL_BUS_CLK),
@ -140,7 +143,7 @@ const freq_info PM14_130[] = {
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM13_130[] = {
static freq_info PM13_130[] = {
/* 130nm 1.30GHz Pentium M */
FREQ_INFO(1300, 1388, INTEL_BUS_CLK),
FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
@ -149,7 +152,7 @@ const freq_info PM13_130[] = {
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM13_LV_130[] = {
static freq_info PM13_LV_130[] = {
/* 130nm 1.30GHz Low Voltage Pentium M */
FREQ_INFO(1300, 1180, INTEL_BUS_CLK),
FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
@ -160,7 +163,7 @@ const freq_info PM13_LV_130[] = {
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM12_LV_130[] = {
static freq_info PM12_LV_130[] = {
/* 130 nm 1.20GHz Low Voltage Pentium M */
FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
FREQ_INFO(1100, 1164, INTEL_BUS_CLK),
@ -170,7 +173,7 @@ const freq_info PM12_LV_130[] = {
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM11_LV_130[] = {
static freq_info PM11_LV_130[] = {
/* 130 nm 1.10GHz Low Voltage Pentium M */
FREQ_INFO(1100, 1180, INTEL_BUS_CLK),
FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
@ -179,7 +182,7 @@ const freq_info PM11_LV_130[] = {
FREQ_INFO( 600, 956, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM11_ULV_130[] = {
static freq_info PM11_ULV_130[] = {
/* 130 nm 1.10GHz Ultra Low Voltage Pentium M */
FREQ_INFO(1100, 1004, INTEL_BUS_CLK),
FREQ_INFO(1000, 988, INTEL_BUS_CLK),
@ -188,7 +191,7 @@ const freq_info PM11_ULV_130[] = {
FREQ_INFO( 600, 844, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM10_ULV_130[] = {
static freq_info PM10_ULV_130[] = {
/* 130 nm 1.00GHz Ultra Low Voltage Pentium M */
FREQ_INFO(1000, 1004, INTEL_BUS_CLK),
FREQ_INFO( 900, 988, INTEL_BUS_CLK),
@ -201,7 +204,7 @@ const freq_info PM10_ULV_130[] = {
* Data from "Intel Pentium M Processor on 90nm Process with
* 2-MB L2 Cache Datasheet", Order Number 302189, Table 5.
*/
const freq_info PM_765A_90[] = {
static freq_info PM_765A_90[] = {
/* 90 nm 2.10GHz Pentium M, VID #A */
FREQ_INFO(2100, 1340, INTEL_BUS_CLK),
FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
@ -213,7 +216,7 @@ const freq_info PM_765A_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_765B_90[] = {
static freq_info PM_765B_90[] = {
/* 90 nm 2.10GHz Pentium M, VID #B */
FREQ_INFO(2100, 1324, INTEL_BUS_CLK),
FREQ_INFO(1800, 1260, INTEL_BUS_CLK),
@ -225,7 +228,7 @@ const freq_info PM_765B_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_765C_90[] = {
static freq_info PM_765C_90[] = {
/* 90 nm 2.10GHz Pentium M, VID #C */
FREQ_INFO(2100, 1308, INTEL_BUS_CLK),
FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
@ -237,7 +240,7 @@ const freq_info PM_765C_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_765E_90[] = {
static freq_info PM_765E_90[] = {
/* 90 nm 2.10GHz Pentium M, VID #E */
FREQ_INFO(2100, 1356, INTEL_BUS_CLK),
FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
@ -249,7 +252,7 @@ const freq_info PM_765E_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_755A_90[] = {
static freq_info PM_755A_90[] = {
/* 90 nm 2.00GHz Pentium M, VID #A */
FREQ_INFO(2000, 1340, INTEL_BUS_CLK),
FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
@ -261,7 +264,7 @@ const freq_info PM_755A_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_755B_90[] = {
static freq_info PM_755B_90[] = {
/* 90 nm 2.00GHz Pentium M, VID #B */
FREQ_INFO(2000, 1324, INTEL_BUS_CLK),
FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
@ -273,7 +276,7 @@ const freq_info PM_755B_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_755C_90[] = {
static freq_info PM_755C_90[] = {
/* 90 nm 2.00GHz Pentium M, VID #C */
FREQ_INFO(2000, 1308, INTEL_BUS_CLK),
FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
@ -285,7 +288,7 @@ const freq_info PM_755C_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_755D_90[] = {
static freq_info PM_755D_90[] = {
/* 90 nm 2.00GHz Pentium M, VID #D */
FREQ_INFO(2000, 1276, INTEL_BUS_CLK),
FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
@ -297,7 +300,7 @@ const freq_info PM_755D_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_745A_90[] = {
static freq_info PM_745A_90[] = {
/* 90 nm 1.80GHz Pentium M, VID #A */
FREQ_INFO(1800, 1340, INTEL_BUS_CLK),
FREQ_INFO(1600, 1292, INTEL_BUS_CLK),
@ -308,7 +311,7 @@ const freq_info PM_745A_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_745B_90[] = {
static freq_info PM_745B_90[] = {
/* 90 nm 1.80GHz Pentium M, VID #B */
FREQ_INFO(1800, 1324, INTEL_BUS_CLK),
FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
@ -319,7 +322,7 @@ const freq_info PM_745B_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_745C_90[] = {
static freq_info PM_745C_90[] = {
/* 90 nm 1.80GHz Pentium M, VID #C */
FREQ_INFO(1800, 1308, INTEL_BUS_CLK),
FREQ_INFO(1600, 1260, INTEL_BUS_CLK),
@ -330,7 +333,7 @@ const freq_info PM_745C_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_745D_90[] = {
static freq_info PM_745D_90[] = {
/* 90 nm 1.80GHz Pentium M, VID #D */
FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
@ -341,7 +344,7 @@ const freq_info PM_745D_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_735A_90[] = {
static freq_info PM_735A_90[] = {
/* 90 nm 1.70GHz Pentium M, VID #A */
FREQ_INFO(1700, 1340, INTEL_BUS_CLK),
FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
@ -351,7 +354,7 @@ const freq_info PM_735A_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_735B_90[] = {
static freq_info PM_735B_90[] = {
/* 90 nm 1.70GHz Pentium M, VID #B */
FREQ_INFO(1700, 1324, INTEL_BUS_CLK),
FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
@ -361,7 +364,7 @@ const freq_info PM_735B_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_735C_90[] = {
static freq_info PM_735C_90[] = {
/* 90 nm 1.70GHz Pentium M, VID #C */
FREQ_INFO(1700, 1308, INTEL_BUS_CLK),
FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
@ -371,7 +374,7 @@ const freq_info PM_735C_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_735D_90[] = {
static freq_info PM_735D_90[] = {
/* 90 nm 1.70GHz Pentium M, VID #D */
FREQ_INFO(1700, 1276, INTEL_BUS_CLK),
FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
@ -381,7 +384,7 @@ const freq_info PM_735D_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_725A_90[] = {
static freq_info PM_725A_90[] = {
/* 90 nm 1.60GHz Pentium M, VID #A */
FREQ_INFO(1600, 1340, INTEL_BUS_CLK),
FREQ_INFO(1400, 1276, INTEL_BUS_CLK),
@ -391,7 +394,7 @@ const freq_info PM_725A_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_725B_90[] = {
static freq_info PM_725B_90[] = {
/* 90 nm 1.60GHz Pentium M, VID #B */
FREQ_INFO(1600, 1324, INTEL_BUS_CLK),
FREQ_INFO(1400, 1260, INTEL_BUS_CLK),
@ -401,7 +404,7 @@ const freq_info PM_725B_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_725C_90[] = {
static freq_info PM_725C_90[] = {
/* 90 nm 1.60GHz Pentium M, VID #C */
FREQ_INFO(1600, 1308, INTEL_BUS_CLK),
FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
@ -411,7 +414,7 @@ const freq_info PM_725C_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_725D_90[] = {
static freq_info PM_725D_90[] = {
/* 90 nm 1.60GHz Pentium M, VID #D */
FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
@ -421,7 +424,7 @@ const freq_info PM_725D_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_715A_90[] = {
static freq_info PM_715A_90[] = {
/* 90 nm 1.50GHz Pentium M, VID #A */
FREQ_INFO(1500, 1340, INTEL_BUS_CLK),
FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
@ -430,7 +433,7 @@ const freq_info PM_715A_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_715B_90[] = {
static freq_info PM_715B_90[] = {
/* 90 nm 1.50GHz Pentium M, VID #B */
FREQ_INFO(1500, 1324, INTEL_BUS_CLK),
FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
@ -439,7 +442,7 @@ const freq_info PM_715B_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_715C_90[] = {
static freq_info PM_715C_90[] = {
/* 90 nm 1.50GHz Pentium M, VID #C */
FREQ_INFO(1500, 1308, INTEL_BUS_CLK),
FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
@ -448,7 +451,7 @@ const freq_info PM_715C_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_715D_90[] = {
static freq_info PM_715D_90[] = {
/* 90 nm 1.50GHz Pentium M, VID #D */
FREQ_INFO(1500, 1276, INTEL_BUS_CLK),
FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
@ -457,7 +460,7 @@ const freq_info PM_715D_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_738_90[] = {
static freq_info PM_738_90[] = {
/* 90 nm 1.40GHz Low Voltage Pentium M */
FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
FREQ_INFO(1300, 1116, INTEL_BUS_CLK),
@ -469,7 +472,7 @@ const freq_info PM_738_90[] = {
FREQ_INFO( 600, 988, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_733_90[] = {
static freq_info PM_733_90[] = {
/* 90 nm 1.10GHz Ultra Low Voltage Pentium M */
FREQ_INFO(1100, 940, INTEL_BUS_CLK),
FREQ_INFO(1000, 924, INTEL_BUS_CLK),
@ -478,7 +481,7 @@ const freq_info PM_733_90[] = {
FREQ_INFO( 600, 812, INTEL_BUS_CLK),
FREQ_INFO( 0, 0, 1),
};
const freq_info PM_723_90[] = {
static freq_info PM_723_90[] = {
/* 90 nm 1.00GHz Ultra Low Voltage Pentium M */
FREQ_INFO(1000, 940, INTEL_BUS_CLK),
FREQ_INFO( 900, 908, INTEL_BUS_CLK),
@ -487,7 +490,7 @@ const freq_info PM_723_90[] = {
FREQ_INFO( 0, 0, 1),
};
const cpu_info ESTprocs[] = {
static cpu_info ESTprocs[] = {
INTEL(PM17_130, 1700, 1484, 600, 956, INTEL_BUS_CLK),
INTEL(PM16_130, 1600, 1484, 600, 956, INTEL_BUS_CLK),
INTEL(PM15_130, 1500, 1484, 600, 956, INTEL_BUS_CLK),
@ -532,9 +535,11 @@ static void est_identify(driver_t *driver, device_t parent);
static int est_probe(device_t parent);
static int est_attach(device_t parent);
static int est_detach(device_t parent);
static int est_find_cpu(const char *vendor, uint64_t msr, uint32_t bus_clk,
const freq_info **freqs);
static const freq_info *est_get_current(const freq_info *freq_list);
static int est_get_info(device_t dev);
static int est_acpi_info(device_t dev, freq_info **freqs);
static int est_table_info(device_t dev, uint64_t msr, uint32_t bus_clk,
freq_info **freqs);
static freq_info *est_get_current(freq_info *freq_list);
static int est_settings(device_t dev, struct cf_setting *sets, int *count);
static int est_set(device_t dev, const struct cf_setting *set);
static int est_get(device_t dev, struct cf_setting *set);
@ -593,7 +598,6 @@ est_identify(driver_t *driver, device_t parent)
static int
est_probe(device_t dev)
{
const freq_info *f;
device_t perf_dev;
uint64_t msr;
int error, type;
@ -616,6 +620,8 @@ est_probe(device_t dev)
msr = rdmsr(MSR_MISC_ENABLE);
if ((msr & MSR_SS_ENABLE) == 0) {
wrmsr(MSR_MISC_ENABLE, msr | MSR_SS_ENABLE);
if (bootverbose)
device_printf(dev, "enabling SpeedStep\n");
/* Check if the enable failed. */
msr = rdmsr(MSR_MISC_ENABLE);
@ -625,17 +631,6 @@ est_probe(device_t dev)
}
}
/* Identify the exact CPU model */
msr = rdmsr(MSR_PERF_STATUS);
if (est_find_cpu(cpu_vendor, msr, INTEL_BUS_CLK, &f) != 0) {
printf(
"CPU claims to support Enhanced Speedstep, but is not recognized.\n"
"Please update driver or contact the maintainer.\n"
"cpu_vendor = %s msr = %0jx, bus_clk = %x\n",
cpu_vendor, msr, INTEL_BUS_CLK);
return (ENXIO);
}
device_set_desc(dev, "Enhanced SpeedStep Frequency Control");
return (0);
}
@ -644,34 +639,126 @@ static int
est_attach(device_t dev)
{
struct est_softc *sc;
uint64_t msr;
sc = device_get_softc(dev);
sc->dev = dev;
msr = rdmsr(MSR_PERF_STATUS);
est_find_cpu(cpu_vendor, msr, INTEL_BUS_CLK, &sc->freq_list);
cpufreq_register(dev);
/* Check CPU for supported settings. */
if (est_get_info(dev))
return (ENXIO);
cpufreq_register(dev);
return (0);
}
static int
est_detach(device_t dev)
{
struct est_softc *sc;
sc = device_get_softc(dev);
if (sc->acpi_settings)
free(sc->freq_list, M_DEVBUF);
return (ENXIO);
}
/*
* Probe for supported CPU settings. First, check our static table of
* settings. If no match, try using the ones offered by acpi_perf
* (i.e., _PSS). We use ACPI second because some systems (IBM R/T40
* series) export both legacy SMM IO-based access and direct MSR access
* but the direct access specifies invalid values for _PSS.
*/
static int
est_find_cpu(const char *vendor, uint64_t msr, uint32_t bus_clk,
const freq_info **freqs)
est_get_info(device_t dev)
{
const cpu_info *p;
struct est_softc *sc;
uint64_t msr;
int error;
sc = device_get_softc(dev);
msr = rdmsr(MSR_PERF_STATUS);
error = est_table_info(dev, msr, INTEL_BUS_CLK, &sc->freq_list);
if (error)
error = est_acpi_info(dev, &sc->freq_list);
if (error) {
printf(
"est: CPU supports Enhanced Speedstep, but is not recognized.\n"
"est: Please update driver or contact the maintainer.\n"
"est: cpu_vendor %s, msr %0jx, bus_clk, %x\n",
cpu_vendor, msr, INTEL_BUS_CLK);
return (ENXIO);
}
return (0);
}
static int
est_acpi_info(device_t dev, freq_info **freqs)
{
struct est_softc *sc;
struct cf_setting *sets;
freq_info *table;
device_t perf_dev;
int count, error, i;
perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
if (perf_dev == NULL || !device_is_attached(perf_dev))
return (ENXIO);
/* Fetch settings from acpi_perf. */
sc = device_get_softc(dev);
table = NULL;
sets = malloc(MAX_SETTINGS * sizeof(*sets), M_TEMP, M_NOWAIT);
if (sets == NULL)
return (ENOMEM);
error = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
if (error)
goto out;
/* Parse settings into our local table format. */
table = malloc(count * sizeof(freq_info), M_DEVBUF, M_NOWAIT);
if (table == NULL) {
error = ENOMEM;
goto out;
}
for (i = 0; i < count; i++) {
/*
* XXX Figure out validity checks for id16. At least some
* systems support both SMM access via SystemIO and the
* direct MSR access but only report the SystemIO values
* via _PSS. However, since we don't know what should be
* valid for this processor, it's hard to know what to check.
*/
table[i].freq = sets[i].freq;
table[i].volts = sets[i].volts;
table[i].id16 = sets[i].spec[0];
table[i].power = sets[i].power;
}
sc->acpi_settings = TRUE;
*freqs = table;
error = 0;
out:
if (sets)
free(sets, M_TEMP);
if (error && table)
free(table, M_DEVBUF);
return (error);
}
static int
est_table_info(device_t dev, uint64_t msr, uint32_t bus_clk, freq_info **freqs)
{
cpu_info *p;
uint32_t id;
/* Find a table which matches (vendor, id, bus_clk). */
id = msr >> 32;
for (p = ESTprocs; p->id32 != 0; p++) {
if (strcmp(p->vendor, vendor) == 0 && p->id32 == id &&
if (strcmp(p->vendor, cpu_vendor) == 0 && p->id32 == id &&
p->bus_clk == bus_clk)
break;
}
@ -679,17 +766,19 @@ est_find_cpu(const char *vendor, uint64_t msr, uint32_t bus_clk,
return (EOPNOTSUPP);
/* Make sure the current setpoint is valid. */
if (est_get_current(p->freqtab) == NULL)
if (est_get_current(p->freqtab) == NULL) {
device_printf(dev, "current setting not found in table\n");
return (EOPNOTSUPP);
}
*freqs = p->freqtab;
return (0);
}
static const freq_info *
est_get_current(const freq_info *freq_list)
static freq_info *
est_get_current(freq_info *freq_list)
{
const freq_info *f;
freq_info *f;
int i;
uint16_t id16;
@ -713,7 +802,7 @@ static int
est_settings(device_t dev, struct cf_setting *sets, int *count)
{
struct est_softc *sc;
const freq_info *f;
freq_info *f;
int i;
sc = device_get_softc(dev);
@ -724,7 +813,7 @@ est_settings(device_t dev, struct cf_setting *sets, int *count)
for (f = sc->freq_list; f->freq != 0; f++, i++) {
sets[i].freq = f->freq;
sets[i].volts = f->volts;
sets[i].power = CPUFREQ_VAL_UNKNOWN;
sets[i].power = f->power;
sets[i].lat = EST_TRANS_LAT;
sets[i].dev = dev;
}
@ -737,7 +826,7 @@ static int
est_set(device_t dev, const struct cf_setting *set)
{
struct est_softc *sc;
const freq_info *f;
freq_info *f;
uint64_t msr;
/* Find the setting matching the requested one. */
@ -764,7 +853,7 @@ static int
est_get(device_t dev, struct cf_setting *set)
{
struct est_softc *sc;
const freq_info *f;
freq_info *f;
sc = device_get_softc(dev);
f = est_get_current(sc->freq_list);
@ -773,7 +862,7 @@ est_get(device_t dev, struct cf_setting *set)
set->freq = f->freq;
set->volts = f->volts;
set->power = CPUFREQ_VAL_UNKNOWN;
set->power = f->power;
set->lat = EST_TRANS_LAT;
set->dev = dev;
return (0);