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);