Re: Enhanced SpeedStep driver available

Maxim Sobolev <[email protected]>
Newsgroups gmane.os.freebsd.current,gmane.os.freebsd.devel.mobile
Organization Porta Software Ltd
Message-ID <[email protected]>
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
>>
>> _______________________________________________
>> [email protected] mailing list
>> http://lists.freebsd.org/mailman/listinfo/freebsd-current
>> To unsubscribe, send any mail to 
>> "[email protected]"
>>
>>
>>
> 
> _______________________________________________
> [email protected] mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-current
> To unsubscribe, send any mail to "[email protected]"
> 
> 
>

_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "[email protected]"
estctrl.c.diff (text/plain, 3.9 KB)
--- 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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.