est doesn't support C2D E6600 and newer CPUs?
John Baldwin
jhb at freebsd.org
Tue Oct 2 11:53:43 PDT 2007
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
@@ -38,6 +38,7 @@
#include <sys/systm.h>
#include "cpufreq_if.h"
+#include <machine/clock.h>
#include <machine/md_var.h>
#include <contrib/dev/acpica/acpi.h>
@@ -70,6 +71,7 @@
struct est_softc {
device_t dev;
int acpi_settings;
+ int msr_settings;
freq_info *freq_list;
};
@@ -897,6 +899,7 @@
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);
@@ -1031,11 +1034,13 @@
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);
}
@@ -1059,6 +1064,9 @@
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"
@@ -1149,6 +1157,77 @@
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 @ %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 @ %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 Baldwin
More information about the freebsd-acpi
mailing list