On Tuesday 02 October 2007 02:33:16 am Nate Lawson wrote: > Dag-Erling Smørgrav wrote: > > "Abdullah Ibn Hamad Al-Marri" <almarrie_at_gmail.com> writes: > >> [...] > > > > No need for est, acpi_perf handles the E6600 just fine. > > > > DES > > Depends on the mobo. Some export the info to acpi and some don't. The > linux driver has some workarounds for that, but it's too complicated for > me to spend time figuring out right now. You have to look at > speedstep-centrino.c and several other files to get the full picture. At some point my laptop suddenly started getting CPU levels from ACPI while I was testing the patch below. The patch below did work for me though even though it only supports the high and low settings. I #if 0'd the code in detach since detach always fails and it would be bad to free the frequency table out from under the driver w/o stopping it. Index: est.c =================================================================== RCS file: /usr/cvs/src/sys/i386/cpufreq/est.c,v retrieving revision 1.11 diff -u -r1.11 est.c --- est.c 11 May 2006 17:35:44 -0000 1.11 +++ est.c 2 Oct 2007 18:04:58 -0000 _at__at_ -38,6 +38,7 _at__at_ #include <sys/systm.h> #include "cpufreq_if.h" +#include <machine/clock.h> #include <machine/md_var.h> #include <contrib/dev/acpica/acpi.h> _at__at_ -70,6 +71,7 _at__at_ struct est_softc { device_t dev; int acpi_settings; + int msr_settings; freq_info *freq_list; }; _at__at_ -897,6 +899,7 _at__at_ 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, freq_info **freqs); +static int est_msr_info(device_t dev, uint64_t msr, 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); _at__at_ -1031,11 +1034,13 _at__at_ static int est_detach(device_t dev) { +#if 0 struct est_softc *sc; sc = device_get_softc(dev); - if (sc->acpi_settings) + if (sc->acpi_settings || sc->msr_settings) free(sc->freq_list, M_DEVBUF); +#endif return (ENXIO); } _at__at_ -1059,6 +1064,9 _at__at_ if (error) error = est_acpi_info(dev, &sc->freq_list); + if (error) + error = est_msr_info(dev, msr, &sc->freq_list); + if (error) { printf( "est: CPU supports Enhanced Speedstep, but is not recognized.\n" _at__at_ -1149,6 +1157,77 _at__at_ return (0); } +/* + * Flesh out a simple rate table containing the high and low frequencies + * based on the current clock speed and the upper 32 bits of the MSR. + */ +static int +est_msr_info(device_t dev, uint64_t msr, freq_info **freqs) +{ + struct est_softc *sc; + freq_info *fp; + int bus, freq, volts; + uint16_t id; + + if (strcmp("GenuineIntel", cpu_vendor) != 0) + return (EOPNOTSUPP); + + /* Figure out the bus clock. */ + freq = tsc_freq / 1000000; + id = msr >> 32; + bus = freq / (id >> 8); + device_printf(dev, "Guessed bus clock (high) of %d MHz\n", bus); + if (bus != 100 && bus != 133) { + /* We may be running on the low frequency. */ + id = msr >> 48; + bus = freq / (id >> 8); + device_printf(dev, "Guessed bus clock (low) of %d MHz\n", bus); + if (bus != 100 && bus != 133) + return (EOPNOTSUPP); + + /* Calculate high frequency. */ + id = msr >> 32; + freq = ((id >> 8) & 0xff) * bus; + } + + /* Fill out a new freq table containing just the high and low freqs. */ + sc = device_get_softc(dev); + fp = malloc(sizeof(freq_info) * 3, M_DEVBUF, M_WAITOK | M_ZERO); + + /* First, the high frequency. */ + volts = id & 0xff; + if (volts != 0) { + volts <<= 4; + volts += 700; + } + fp[0].freq = freq; + fp[0].volts = volts; + fp[0].id16 = id; + fp[0].power = CPUFREQ_VAL_UNKNOWN; + device_printf(dev, "Guessed high setting of %d MHz _at_ %d Mv\n", freq, + volts); + + /* Second, the low frequency. */ + id = msr >> 48; + freq = ((id >> 8) & 0xff) * bus; + volts = id & 0xff; + if (volts != 0) { + volts <<= 4; + volts += 700; + } + fp[1].freq = freq; + fp[1].volts = volts; + fp[1].id16 = id; + fp[1].power = CPUFREQ_VAL_UNKNOWN; + device_printf(dev, "Guessed low setting of %d MHz _at_ %d Mv\n", freq, + volts); + + /* Table is already terminated due to M_ZERO. */ + sc->msr_settings = TRUE; + *freqs = fp; + return (0); +} + static freq_info * est_get_current(freq_info *freq_list) { -- John BaldwinReceived on Tue Oct 02 2007 - 16:53:42 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:18 UTC