Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Oct 2007 14:07:26 -0400
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-acpi@freebsd.org
Cc:        Dag-Erling =?utf-8?q?Sm=C3=B8rgrav?= <des@des.no>, FreeBSD Current <freebsd-current@freebsd.org>, Nate Lawson <nate@root.org>
Subject:   Re: est doesn't support C2D E6600 and newer CPUs?
Message-ID:  <200710021407.27711.jhb@freebsd.org>
In-Reply-To: <4701E62C.5030909@root.org>
References:  <499c70c0710011109k61d3365n84038115a26e0398@mail.gmail.com> <86lkamawb4.fsf@ds4.des.no> <4701E62C.5030909@root.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tuesday 02 October 2007 02:33:16 am Nate Lawson wrote:
> Dag-Erling Sm=C3=B8rgrav wrote:
> > "Abdullah Ibn Hamad Al-Marri" <almarrie@gmail.com> writes:
> >> [...]
> >=20
> > No need for est, acpi_perf handles the E6600 just fine.
> >=20
> > DES
>=20
> 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=20
was testing the patch below.  The patch below did work for me though even=20
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=20
free the frequency table out from under the driver w/o stopping it.

Index: est.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/cvs/src/sys/i386/cpufreq/est.c,v
retrieving revision 1.11
diff -u -r1.11 est.c
=2D-- 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>
=20
 #include "cpufreq_if.h"
+#include <machine/clock.h>
 #include <machine/md_var.h>
=20
 #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;
 };
=20
@@ -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;
=20
 	sc =3D device_get_softc(dev);
=2D	if (sc->acpi_settings)
+	if (sc->acpi_settings || sc->msr_settings)
 		free(sc->freq_list, M_DEVBUF);
+#endif
 	return (ENXIO);
 }
=20
@@ -1059,6 +1064,9 @@
 	if (error)
 		error =3D est_acpi_info(dev, &sc->freq_list);
=20
+	if (error)
+		error =3D 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);
 }
=20
+/*
+ * 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) !=3D 0)
+		return (EOPNOTSUPP);
+
+	/* Figure out the bus clock. */
+	freq =3D tsc_freq / 1000000;
+	id =3D msr >> 32;
+	bus =3D freq / (id >> 8);
+	device_printf(dev, "Guessed bus clock (high) of %d MHz\n", bus);
+	if (bus !=3D 100 && bus !=3D 133) {
+		/* We may be running on the low frequency. */
+		id =3D msr >> 48;
+		bus =3D freq / (id >> 8);
+		device_printf(dev, "Guessed bus clock (low) of %d MHz\n", bus);
+		if (bus !=3D 100 && bus !=3D 133)
+			return (EOPNOTSUPP);
+	=09
+		/* Calculate high frequency. */
+		id =3D msr >> 32;
+		freq =3D ((id >> 8) & 0xff) * bus;
+	}
+
+	/* Fill out a new freq table containing just the high and low freqs. */
+	sc =3D device_get_softc(dev);
+	fp =3D malloc(sizeof(freq_info) * 3, M_DEVBUF, M_WAITOK | M_ZERO);
+
+	/* First, the high frequency. */
+	volts =3D id & 0xff;
+	if (volts !=3D 0) {
+		volts <<=3D 4;
+		volts +=3D 700;
+	}
+	fp[0].freq =3D freq;
+	fp[0].volts =3D volts;
+	fp[0].id16 =3D id;
+	fp[0].power =3D CPUFREQ_VAL_UNKNOWN;
+	device_printf(dev, "Guessed high setting of %d MHz @ %d Mv\n", freq,
+	    volts);
+
+	/* Second, the low frequency. */
+	id =3D msr >> 48;
+	freq =3D ((id >> 8) & 0xff) * bus;
+	volts =3D id & 0xff;
+	if (volts !=3D 0) {
+		volts <<=3D 4;
+		volts +=3D 700;
+	}
+	fp[1].freq =3D freq;
+	fp[1].volts =3D volts;
+	fp[1].id16 =3D id;
+	fp[1].power =3D 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 =3D TRUE;
+	*freqs =3D fp;
+	return (0);
+}
+
 static freq_info *
 est_get_current(freq_info *freq_list)
 {

=2D-=20
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200710021407.27711.jhb>