Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 05 Sep 2004 19:54:17 +0300
From:      Maxim Sobolev <sobomax@portaone.com>
To:        Colin Percival <colin.percival@wadham.ox.ac.uk>
Cc:        freebsd-mobile@FreeBSD.ORG
Subject:   Re: Enhanced SpeedStep driver available
Message-ID:  <413B44B9.7020704@portaone.com>
In-Reply-To: <4120F823.2040802@portaone.com>
References:  <6.1.0.6.1.20040816074348.03f99338@popserver.sfu.ca> <4120F823.2040802@portaone.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------080500030706020202000104
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Please see attached a patch which adds support to TCC speed control 
available in every intel p4 processor. This patch requires up-to-date 
current system to work properly, since I've recently addes ESS-like 
sysctl that can be used to obtain list of speed steps supported by TCC 
circuit.

It would be nice to have it integrated into the estctrl.

Thanks!

-Maxim

Maxim Sobolev wrote:
> Colin Percival wrote:
> 
>>   Thanks to everyone who has been sending me data about their
>> processors (and in particular, the 90nm versions), I now have
>> a first draft of a Enhanced SpeedStep driver available.  For
>> people with the appropriate processors (Pentium M only), this
>> makes it possible to adjust the cpu frequency via a new sysctl
>> (hw.est_curfreq), and have the cpu voltage adjusted at the
>> same time.
>>   I've also put together a very simple control daemon which
>> reads kern.cp_time every second and adjusts the cpu frequency
>> based on the fraction of cpu time which is idle.  This increases
>> my laptop's battery life by around 40%.
> 
> 
> It would be nice if you can extend it to use whatever speed control 
> method is available (e.g. ACPI, TCC, ESS etc), so that it can be used on 
> older machines as well.
> 
> -Maxim
> 
> 
>>   All the code is online at
>> http://www.daemonology.net/freebsd-est/
>>   Assuming I don't hear any major bug reports in the next few
>> days, I'll package these into ports and hopefully get them into
>> the ports tree in time for 5.3-RELEASE.
>>
>> Colin Percival
>>
>> _______________________________________________
>> freebsd-current@freebsd.org mailing list
>> http://lists.freebsd.org/mailman/listinfo/freebsd-current
>> To unsubscribe, send any mail to 
>> "freebsd-current-unsubscribe@freebsd.org"
>>
>>
>>
> 
> _______________________________________________
> freebsd-current@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-current
> To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org"
> 
> 
> 


--------------080500030706020202000104
Content-Type: text/plain;
 name="estctrl.c.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="estctrl.c.diff"

--- estctrl.c	2004/08/21 15:43:59	1.1
+++ estctrl.c	2004/08/23 19:04:51
@@ -38,9 +38,21 @@
 #include<unistd.h>
 
 static int readtimes(long * idle, long * total);
-static int readfreqs(int * numfreqs, int ** freqs);
-static int readcurfreq(int * curfreq);
-static int setcurfreq(int freq);
+static int readfreqs(int cmethod, int * numfreqs, int ** freqs);
+static int readcurfreq(int cmethod, int * curfreq);
+static int setcurfreq(int cmethod, int freq);
+
+#define	CMETHOD_ESS	(0)
+#define	CMETHOD_TCC	(1)
+
+const struct {
+	const char *slevels;
+	const char *clevel;
+	const char *measure;
+} sctl_names[2] = {
+	{"hw.est_freqs", "hw.est_curfreq", "MHz"},
+	{"hw.p4tcc.cpuperf_levels", "hw.p4tcc.cpuperf", "%"}
+};
 
 static int readtimes(long * idle, long * total)
 {
@@ -67,17 +79,18 @@
 	return 0;
 }
 
-static int readfreqs(int * numfreqs, int ** freqs)
+static int readfreqs(int cmethod, int * numfreqs, int ** freqs)
 {
 	char *freqstr, *p, *q;
 	int i;
 	size_t len = 0;
 
-	if (sysctlbyname("hw.est_freqs", NULL, &len, NULL, 0))
+	if (sysctlbyname(sctl_names[cmethod].slevels, NULL, &len, NULL, 0))
 		return -1;
 	if ((freqstr = malloc(len)) == NULL)
 		return -1;
-	if (sysctlbyname("hw.est_freqs", (void *)freqstr, &len, NULL, 0))
+	if (sysctlbyname(sctl_names[cmethod].slevels, (void *)freqstr, &len,
+	    NULL, 0))
 		return -1;
 
 	*numfreqs = 1;
@@ -105,21 +118,23 @@
 	return 0;
 }
 
-static int readcurfreq(int * curfreq)
+static int readcurfreq(int cmethod, int * curfreq)
 {
 	size_t len = sizeof(*curfreq);
 
-	if (sysctlbyname("hw.est_curfreq", curfreq, &len, NULL, 0))
+	if (sysctlbyname(sctl_names[cmethod].clevel, curfreq, &len, NULL, 0))
 		return -1;
 
 	return 0;
 }
 
-static int setcurfreq(int freq)
+static int setcurfreq(int cmethod, int freq)
 {
 
-	printf("Setting frequency to %d\n", freq);
-	if (sysctlbyname("hw.est_curfreq", NULL, NULL, &freq, sizeof(freq)))
+	printf("Setting frequency to %d%s\n", freq,
+	    sctl_names[cmethod].measure);
+	if (sysctlbyname(sctl_names[cmethod].clevel, NULL, NULL, &freq,
+	    sizeof(freq)))
 		return -1;
 
 	return 0;
@@ -130,16 +145,31 @@
 	long idle, total;
 	int * freqs, numfreqs;
 	int curfreq, i;
+	int cmethod;
 
 	if (readtimes(NULL, NULL))
 		err(1, "readtimes");
-	if (readfreqs(&numfreqs, &freqs))
+
+	if (readfreqs(CMETHOD_ESS, &numfreqs, &freqs) == 0) {
+		cmethod = CMETHOD_ESS;
+	} else if (readfreqs(CMETHOD_TCC, &numfreqs, &freqs) == 0) {
+		cmethod = CMETHOD_TCC;
+		/*
+		 * On some machines, TCC lies right after boot,
+		 * so that set it explicitly to the current level.
+		 */
+		if (readcurfreq(cmethod, &curfreq))
+			err(1, "Error reading current CPU frequency");
+		if (setcurfreq(cmethod, curfreq))
+			err(1, "Error setting CPU frequency");
+	} else {
 		err(1, "Error reading supported CPU frequencies");
+	}
 
 	do {
 		sleep(1);
 
-		if (readcurfreq(&curfreq))
+		if (readcurfreq(cmethod, &curfreq))
 			err(1, "Error reading current CPU frequency");
 		if (readtimes(&idle, &total))
 			err(1, "readtimes");
@@ -149,9 +179,10 @@
 				if (curfreq < freqs[i])
 					break;
 			printf("Idle time < 50%%, increasing clock"
-			    " speed from %dMHz to %dMHz\n", curfreq,
-			    freqs[i]);
-			if (setcurfreq(freqs[i]))
+			    " speed from %d%s to %d%s\n", curfreq,
+			    sctl_names[cmethod].measure, freqs[i],
+			    sctl_names[cmethod].measure);
+			if (setcurfreq(cmethod, freqs[i]))
 				err(1, "Error setting CPU frequency");
 		}
 		if ((idle > (total * 3) / 4) && (curfreq > freqs[0])) {
@@ -159,9 +190,10 @@
 				if (curfreq > freqs[i])
 					break;
 			printf("Idle time > 75%%, decreasing clock"
-			    " speed from %dMHz to %dMHz\n", curfreq,
-			    freqs[i]);
-			if (setcurfreq(freqs[i]))
+			    " speed from %d%s to %d%s\n", curfreq,
+			    sctl_names[cmethod].measure, freqs[i],
+			    sctl_names[cmethod].measure);
+			if (setcurfreq(cmethod, freqs[i]))
 				err(1, "Error setting CPU frequency");
 		}
 	} while(1);

--------------080500030706020202000104--



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