From nobody@FreeBSD.org  Sun Jul  5 16:06:19 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id C24FC106564A
	for <freebsd-gnats-submit@FreeBSD.org>; Sun,  5 Jul 2009 16:06:19 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id AFD0D8FC14
	for <freebsd-gnats-submit@FreeBSD.org>; Sun,  5 Jul 2009 16:06:19 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n65G6JUK043184
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 5 Jul 2009 16:06:19 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n65G6JD4043183;
	Sun, 5 Jul 2009 16:06:19 GMT
	(envelope-from nobody)
Message-Id: <200907051606.n65G6JD4043183@www.freebsd.org>
Date: Sun, 5 Jul 2009 16:06:19 GMT
From: Rene Schickbauer <cavac@magicbooks.org>
To: freebsd-gnats-submit@FreeBSD.org
Subject: powerd Support for maxspeed in adaptive modes
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         136354
>Category:       bin
>Synopsis:       [patch] powerd(8): Support for maxspeed in adaptive modes
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jul 05 16:10:00 UTC 2009
>Closed-Date:    
>Last-Modified:  Mon Jul 20 13:20:06 UTC 2009
>Originator:     Rene Schickbauer
>Release:        8-current
>Organization:
>Environment:
FreeBSD titan 8.0-CURRENT-200906 FreeBSD 8.0-CURRENT-200906 #1: Tue Jun 30 13:29:40 CEST 2009     root@titan:/usr/obj/usr/src/sys/GENERIC  i386

>Description:
This patch enables users to use the powerd adaptive modes while still maintaining a cooler/less power hungry system by limiting the max. CPU speed powerd can set.

This patch also includes an update to the powerd manpage. I also moved the description of the available modes to a dedicated section to make them easier to find.

I wrote this patch, to limit my EEE PC's power consumption/heat production without having to fall back to minimum performance.  
>How-To-Repeat:
Run an Intel Atom based NetBook with powerd set to "adaptive" and "make buildworld". It gets hot enough to get you burned when held in hand or lap (like when debugging FreeBSD while waiting for the bus).
>Fix:
See attached patch

Patch attached with submission follows:

diff -u powerd.orig/powerd.8 powerd/powerd.8
--- powerd.orig/powerd.8	2009-07-05 16:04:19.000000000 +0200
+++ powerd/powerd.8	2009-07-05 17:18:12.000000000 +0200
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD: src/usr.sbin/powerd/powerd.8,v 1.13 2008/12/24 09:17:30 trhodes Exp $
 .\"
-.Dd December 24, 2008
+.Dd July 5, 2009
 .Dt POWERD 8
 .Os
 .Sh NAME
@@ -33,7 +33,9 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl a Ar mode
+.Op Fl x Ar maxspeed
 .Op Fl b Ar mode
+.Op Fl y Ar maxspeed
 .Op Fl i Ar percent
 .Op Fl n Ar mode
 .Op Fl p Ar ival
@@ -45,22 +47,10 @@
 .Nm
 utility monitors the system state and sets various power control options
 accordingly.
-It offers three modes (maximum, minimum, and adaptive) that can be
-individually selected while on AC power or batteries.
-The modes maximum, minimum, adaptive and hiadaptive may be abbreviated
-max, min, adp, hadp.
-.Pp
-Maximum mode chooses the highest performance values.
-Minimum mode selects the lowest performance values to get the most power
-savings.
-Adaptive mode attempts to strike a balance by degrading performance when
-the system appears idle and increasing it when the system is busy.
-It offers a good balance between a small performance loss for greatly
-increased power savings.
-Hiadaptive mode is alike adaptive mode, but tuned for systems where
-performance and interactivity are more important then power consumption.
-It rises frequency faster, drops slower and keeps twice lower CPU load.
-The default mode is adaptive for battery power and hiadaptive for the rest.
+It offers multiple modes (maximum, minimum, and two adaptive modes) that can be
+individually selected while on AC power or batteries. See
+.Ar MODES
+below for details.
 .Pp
 The
 .Nm
@@ -99,7 +89,57 @@
 Messages about power changes will be printed to stdout and
 .Nm
 will operate in the foreground.
+.It Fl x Ar mode
+Selects the
+.Ar maxspeed
+in Mhz for adaptive modes to use while on AC power.
+.It Fl y Ar mode
+Selects the
+.Ar maxspeed
+in Mhz for adaptive modes to use while on battery power.
 .El
+.Sh MODES
+The following
+.Ar mode
+flags are currently implemented:
+.Pp
+.Ar max
+or
+.Ar maximum
+mode chooses the highest performance values.
+.Pp
+.Ar min
+or
+.Ar minimum
+mode selects the lowest performance values to get the most power
+savings.
+.Pp
+.Ar adp
+or
+.Ar adaptive
+mode attempts to strike a balance by degrading performance when
+the system appears idle and increasing it when the system is busy.
+It offers a good balance between a small performance loss for greatly
+increased power savings.
+.Pp
+.Ar hadp
+or
+.Ar hiadaptive
+mode is alike adaptive mode, but tuned for systems where
+performance and interactivity are more important then power consumption.
+It rises frequency faster, drops slower and keeps twice lower CPU load.
+.Pp
+For both adaptive modes, it is possible to set
+.Ar maxspeed
+to lower power consumption by limiting the dynamic range
+.Nm
+uses.
+.Pp
+The default mode is
+.Ar adaptive
+for battery power and
+.Ar hiadaptive
+for the rest.
 .Sh SEE ALSO
 .Xr acpi 4 ,
 .Xr apm 4 ,
@@ -121,6 +161,8 @@
 then updated it for
 .Xr cpufreq 4 ,
 added features, and wrote this manual page.
+.An Rene Schickbauer
+added speed limiting and rewrote parts of this manual page.
 .Sh BUGS
 The
 .Nm
diff -u powerd.orig/powerd.c powerd/powerd.c
--- powerd.orig/powerd.c	2009-07-05 16:04:19.000000000 +0200
+++ powerd/powerd.c	2009-07-05 17:22:35.000000000 +0200
@@ -118,6 +118,9 @@
 #endif
 static int	devd_pipe = -1;
 
+static int  maxspeed_ac = 0;
+static int  maxspeed_battery = 0;
+
 #define DEVD_RETRY_INTERVAL 60 /* seconds */
 static struct timeval tried_devd;
 
@@ -418,7 +421,7 @@
 {
 
 	fprintf(stderr,
-"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile]\n");
+"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile] [-x maxspeed] [-y maxspeed]\n");
 	exit(1);
 }
 
@@ -431,13 +434,16 @@
 	struct pidfh *pfh = NULL;
 	const char *pidfile = NULL;
 	int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load;
-	int ch, mode, mode_ac, mode_battery, mode_none;
+	int ch, mode, mode_ac, mode_battery, mode_none, maxspeed;
 	uint64_t mjoules_used;
 	size_t len;
 
 	/* Default mode for all AC states is adaptive. */
 	mode_ac = mode_none = MODE_HIADAPTIVE;
 	mode_battery = MODE_ADAPTIVE;
+    maxspeed_ac = 0;
+    maxspeed_battery = 0;
+    maxspeed = 0;
 	cpu_running_mark = DEFAULT_ACTIVE_PERCENT;
 	cpu_idle_mark = DEFAULT_IDLE_PERCENT;
 	poll_ival = DEFAULT_POLL_INTERVAL;
@@ -448,7 +454,7 @@
 	if (geteuid() != 0)
 		errx(1, "must be root to run");
 
-	while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:v")) != -1)
+	while ((ch = getopt(argc, argv, "a:b:x:y:i:n:p:P:r:v")) != -1)
 		switch (ch) {
 		case 'a':
 			parse_mode(optarg, &mode_ac, ch);
@@ -464,6 +470,22 @@
 				usage();
 			}
 			break;
+        case 'x':
+            maxspeed_ac = atoi(optarg);
+			if (maxspeed_ac <= 0) {
+				warnx("%d is not a valid CPU speed",
+				    maxspeed_ac);
+				usage();
+			}
+            break;
+        case 'y':
+            maxspeed_battery = atoi(optarg);
+			if (maxspeed_battery <= 0) {
+				warnx("%d is not a valid CPU speed",
+				    maxspeed_battery);
+				usage();
+			}
+            break;
 		case 'n':
 			parse_mode(optarg, &mode_none, ch);
 			break;
@@ -574,12 +596,15 @@
 		switch (acline_status) {
 		case SRC_AC:
 			mode = mode_ac;
+            maxspeed = maxspeed_ac;
 			break;
 		case SRC_BATTERY:
 			mode = mode_battery;
+            maxspeed = maxspeed_battery;
 			break;
 		case SRC_UNKNOWN:
 			mode = mode_none;
+            maxspeed = 0;
 			break;
 		default:
 			errx(1, "invalid AC line status %d", acline_status);
@@ -647,6 +672,7 @@
 					freq *= 2;
 				else
 					freq = freq * load / cpu_running_mark;
+                
 				if (freq > freqs[0])
 					freq = freqs[0];
 			} else if (load < cpu_idle_mark &&
@@ -657,6 +683,11 @@
 				if (freq < freqs[numfreqs - 1])
 					freq = freqs[numfreqs - 1];
 			}
+            if(maxspeed > 0 && freq > maxspeed) {
+                if(vflag)
+                    printf("Limiting calculated freq (%d Mhz) to %d Mhz\n", freq, maxspeed);
+                freq = maxspeed;
+            }
 		} else { /* MODE_HIADAPTIVE */
 			if (load > cpu_running_mark / 2) {
 				if (load > 95 || load > cpu_running_mark)
@@ -673,6 +704,11 @@
 				if (freq < freqs[numfreqs - 1])
 					freq = freqs[numfreqs - 1];
 			}
+            if(maxspeed > 0 && freq > maxspeed) {
+                if(vflag)
+                    printf("Limiting calculated freq (%d Mhz) to %d Mhz\n", freq, maxspeed);
+                freq = maxspeed;
+            }
 		}
 		if (vflag) {
 		    printf("load %3d%%, current freq %4d MHz (%2d), wanted freq %4d MHz\n",


>Release-Note:
>Audit-Trail:

From: "Rene Schickbauer" <cavac@magicbooks.org>
To: bug-followup@FreeBSD.org, freebsd-bugs@FreeBSD.org
Cc:  
Subject: Re: misc/136354: powerd Support for maxspeed in adaptive modes
Date: Mon, 20 Jul 2009 15:17:49 +0200 (CEST)

 ------=_20090720151749_38089
 Content-Type: text/plain; charset="iso-8859-1"
 Content-Transfer-Encoding: 8bit
 
 Here is an updated patch that allows setting of minimum and maximum speeds.
 Seperately for battery and AC mode, of course.
 
 I also updated the man-page.
 
 (Hope i didn't mess this follow-up up, gnats doesn't like my webmail)
 ------=_20090720151749_38089
 Content-Type: text/plain; name="powerd.txt"
 Content-Transfer-Encoding: 8bit
 Content-Disposition: attachment; filename="powerd.txt"
 
 diff -u powerd.orig2/powerd.8 powerd/powerd.8
 --- powerd.orig2/powerd.8	2009-07-20 11:43:20.000000000 +0200
 +++ powerd/powerd.8	2009-07-20 14:43:36.000000000 +0200
 @@ -24,7 +24,7 @@
  .\"
  .\" $FreeBSD: src/usr.sbin/powerd/powerd.8,v 1.13 2008/12/24 09:17:30 trhodes Exp $
  .\"
 -.Dd December 24, 2008
 +.Dd July 5, 2009
  .Dt POWERD 8
  .Os
  .Sh NAME
 @@ -34,6 +34,10 @@
  .Nm
  .Op Fl a Ar mode
  .Op Fl b Ar mode
 +.Op Fl c Ar minspeed
 +.Op Fl d Ar maxspeed
 +.Op Fl e Ar minspeed
 +.Op Fl f Ar maxspeed
  .Op Fl i Ar percent
  .Op Fl n Ar mode
  .Op Fl p Ar ival
 @@ -45,22 +49,10 @@
  .Nm
  utility monitors the system state and sets various power control options
  accordingly.
 -It offers three modes (maximum, minimum, and adaptive) that can be
 -individually selected while on AC power or batteries.
 -The modes maximum, minimum, adaptive and hiadaptive may be abbreviated
 -max, min, adp, hadp.
 -.Pp
 -Maximum mode chooses the highest performance values.
 -Minimum mode selects the lowest performance values to get the most power
 -savings.
 -Adaptive mode attempts to strike a balance by degrading performance when
 -the system appears idle and increasing it when the system is busy.
 -It offers a good balance between a small performance loss for greatly
 -increased power savings.
 -Hiadaptive mode is alike adaptive mode, but tuned for systems where
 -performance and interactivity are more important then power consumption.
 -It rises frequency faster, drops slower and keeps twice lower CPU load.
 -The default mode is adaptive for battery power and hiadaptive for the rest.
 +It offers multiple modes (maximum, minimum, and two adaptive modes) that can be
 +individually selected while on AC power or batteries. See
 +.Ar MODES
 +below for details.
  .Pp
  The
  .Nm
 @@ -74,6 +66,22 @@
  Selects the
  .Ar mode
  to use while on battery power.
 +.It Fl c Ar mode
 +Selects the
 +.Ar minspeed
 +in Mhz for adaptive modes to use while on AC power.
 +.It Fl d Ar mode
 +Selects the
 +.Ar maxspeed
 +in Mhz for adaptive modes to use while on AC power.
 +.It Fl e Ar mode
 +Selects the
 +.Ar minspeed
 +in Mhz for adaptive modes to use while on battery power.
 +.It Fl f Ar mode
 +Selects the
 +.Ar maxspeed
 +in Mhz for adaptive modes to use while on battery power.
  .It Fl i Ar percent
  Specifies the CPU load percent level when adaptive
  mode should begin to degrade performance to save power.
 @@ -100,6 +108,48 @@
  .Nm
  will operate in the foreground.
  .El
 +.Sh MODES
 +The following
 +.Ar mode
 +flags are currently implemented:
 +.Pp
 +.Ar max
 +or
 +.Ar maximum
 +mode chooses the highest performance values.
 +.Pp
 +.Ar min
 +or
 +.Ar minimum
 +mode selects the lowest performance values to get the most power
 +savings.
 +.Pp
 +.Ar adp
 +or
 +.Ar adaptive
 +mode attempts to strike a balance by degrading performance when
 +the system appears idle and increasing it when the system is busy.
 +It offers a good balance between a small performance loss for greatly
 +increased power savings.
 +.Pp
 +.Ar hadp
 +or
 +.Ar hiadaptive
 +mode is alike adaptive mode, but tuned for systems where
 +performance and interactivity are more important then power consumption.
 +It rises frequency faster, drops slower and keeps twice lower CPU load.
 +.Pp
 +For both adaptive modes, it is possible to set
 +.Ar maxspeed
 +to lower power consumption by limiting the dynamic range
 +.Nm
 +uses.
 +.Pp
 +The default mode is
 +.Ar adaptive
 +for battery power and
 +.Ar hiadaptive
 +for the rest.
  .Sh SEE ALSO
  .Xr acpi 4 ,
  .Xr apm 4 ,
 @@ -121,6 +171,8 @@
  then updated it for
  .Xr cpufreq 4 ,
  added features, and wrote this manual page.
 +.An Rene Schickbauer
 +added speed limiting and rewrote parts of this manual page.
  .Sh BUGS
  The
  .Nm
 diff -u powerd.orig2/powerd.c powerd/powerd.c
 --- powerd.orig2/powerd.c	2009-07-20 11:43:20.000000000 +0200
 +++ powerd/powerd.c	2009-07-20 14:53:47.000000000 +0200
 @@ -118,6 +118,11 @@
  #endif
  static int	devd_pipe = -1;
  
 +static int  minspeed_ac = 0;
 +static int  maxspeed_ac = 0;
 +static int  minspeed_battery = 0;
 +static int  maxspeed_battery = 0;
 +
  #define DEVD_RETRY_INTERVAL 60 /* seconds */
  static struct timeval tried_devd;
  
 @@ -154,13 +159,13 @@
  		for (cpu = 0; cpu < ncpus; cpu++) {
  			total = 0;
  			for (i = 0; i < CPUSTATES; i++) {
 -			    total += cp_times[cpu * CPUSTATES + i] -
 +				total += cp_times[cpu * CPUSTATES + i] -
  				cp_times_old[cpu * CPUSTATES + i];
  			}
  			if (total == 0)
  				continue;
  			*load += 100 - (cp_times[cpu * CPUSTATES + CP_IDLE] - 
 -			    cp_times_old[cpu * CPUSTATES + CP_IDLE]) * 100 / total;
 +				cp_times_old[cpu * CPUSTATES + CP_IDLE]) * 100 / total;
  		}
  	}
  
 @@ -302,10 +307,10 @@
  			/* FALLTHROUGH */
  		}
  		if (rlen > 0 &&
 -		    (ptr = strstr(buf, "system=ACPI")) != NULL &&
 -		    (ptr = strstr(ptr, "subsystem=ACAD")) != NULL &&
 -		    (ptr = strstr(ptr, "notify=")) != NULL &&
 -		    sscanf(ptr, "notify=%x", &notify) == 1)
 +			(ptr = strstr(buf, "system=ACPI")) != NULL &&
 +			(ptr = strstr(ptr, "subsystem=ACAD")) != NULL &&
 +			(ptr = strstr(ptr, "notify=")) != NULL &&
 +			sscanf(ptr, "notify=%x", &notify) == 1)
  			acline_status = (notify ? SRC_AC : SRC_BATTERY);
  	}
  	if (acline_mode == ac_sysctl) {
 @@ -314,7 +319,7 @@
  
  		len = sizeof(acline);
  		if (sysctl(acline_mib, acline_mib_len, &acline, &len,
 -		    NULL, 0) == 0)
 +			NULL, 0) == 0)
  			acline_status = (acline ? SRC_AC : SRC_BATTERY);
  		else
  			acline_status = SRC_UNKNOWN;
 @@ -364,7 +369,7 @@
  	devd_addr.sun_family = PF_LOCAL;
  	strlcpy(devd_addr.sun_path, DEVDPIPE, sizeof(devd_addr.sun_path));
  	if (connect(devd_pipe, (struct sockaddr *)&devd_addr,
 -	    sizeof(devd_addr)) == -1) {
 +		sizeof(devd_addr)) == -1) {
  		if (vflag)
  			warn("%s(): connect()", __func__);
  		close(devd_pipe);
 @@ -418,7 +423,7 @@
  {
  
  	fprintf(stderr,
 -"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile]\n");
 +"usage: powerd [-v] [-a mode] [-b mode] [-c minspeed] [-d maxspeed] [-e minspeed] [-f maxspeed] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile] \n");
  	exit(1);
  }
  
 @@ -431,13 +436,19 @@
  	struct pidfh *pfh = NULL;
  	const char *pidfile = NULL;
  	int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load;
 -	int ch, mode, mode_ac, mode_battery, mode_none;
 +	int ch, mode, mode_ac, mode_battery, mode_none, minspeed, maxspeed;
  	uint64_t mjoules_used;
  	size_t len;
  
  	/* Default mode for all AC states is adaptive. */
  	mode_ac = mode_none = MODE_HIADAPTIVE;
  	mode_battery = MODE_ADAPTIVE;
 +	minspeed_ac = 0;
 +	maxspeed_ac = 0;
 +	minspeed_battery = 0;
 +	maxspeed_battery = 0;
 +	minspeed = 0;
 +	maxspeed = 0;
  	cpu_running_mark = DEFAULT_ACTIVE_PERCENT;
  	cpu_idle_mark = DEFAULT_IDLE_PERCENT;
  	poll_ival = DEFAULT_POLL_INTERVAL;
 @@ -448,7 +459,7 @@
  	if (geteuid() != 0)
  		errx(1, "must be root to run");
  
 -	while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:v")) != -1)
 +	while ((ch = getopt(argc, argv, "a:b:c:d:e:f:i:n:p:P:r:v")) != -1)
  		switch (ch) {
  		case 'a':
  			parse_mode(optarg, &mode_ac, ch);
 @@ -456,11 +467,43 @@
  		case 'b':
  			parse_mode(optarg, &mode_battery, ch);
  			break;
 +		case 'c':
 +			minspeed_ac = atoi(optarg);
 +			if (minspeed_ac <= 0) {
 +				warnx("%d is not a valid CPU speed",
 +					minspeed_ac);
 +				usage();
 +			}
 +			break;
 +		case 'd':
 +			maxspeed_ac = atoi(optarg);
 +			if (maxspeed_ac <= 0) {
 +				warnx("%d is not a valid CPU speed",
 +					maxspeed_ac);
 +				usage();
 +			}
 +			break;
 +		case 'e':
 +			minspeed_battery = atoi(optarg);
 +			if (minspeed_battery <= 0) {
 +				warnx("%d is not a valid CPU speed",
 +					minspeed_battery);
 +				usage();
 +			}
 +			break;
 +		case 'f':
 +			maxspeed_battery = atoi(optarg);
 +			if (maxspeed_battery <= 0) {
 +				warnx("%d is not a valid CPU speed",
 +					maxspeed_battery);
 +				usage();
 +			}
 +			break;
  		case 'i':
  			cpu_idle_mark = atoi(optarg);
  			if (cpu_idle_mark < 0 || cpu_idle_mark > 100) {
  				warnx("%d is not a valid percent",
 -				    cpu_idle_mark);
 +					cpu_idle_mark);
  				usage();
  			}
  			break;
 @@ -481,7 +524,7 @@
  			cpu_running_mark = atoi(optarg);
  			if (cpu_running_mark <= 0 || cpu_running_mark > 100) {
  				warnx("%d is not a valid percent",
 -				    cpu_running_mark);
 +					cpu_running_mark);
  				usage();
  			}
  			break;
 @@ -492,6 +535,19 @@
  			usage();
  		}
  
 +	if (minspeed_battery > 0 && maxspeed_battery > 0 &&
 +			minspeed_battery > maxspeed_battery) {
 +		warnx("Battery mode: minspeed (%d) can not be greater than maxspeed (%d)",
 +			minspeed_battery, maxspeed_battery);
 +		usage();
 +	}
 +	if (minspeed_ac > 0 && maxspeed_ac > 0 &&
 +			minspeed_ac > maxspeed_ac) {
 +		warnx("AC mode: minspeed (%d) can not be greater than maxspeed (%d)",
 +			minspeed_ac, maxspeed_ac);
 +		usage();
 +	}
 +
  	mode = mode_none;
  
  	/* Poll interval is in units of ms. */
 @@ -522,7 +578,7 @@
  		if (pfh == NULL) {
  			if (errno == EEXIST) {
  				errx(1, "powerd already running, pid: %d",
 -				    otherpid);
 +					otherpid);
  			}
  			warn("cannot open pid file");
  		}
 @@ -564,8 +620,8 @@
  		if (exit_requested) {
  			if (vflag && mjoules_used != 0)
  				printf("total joules used: %u.%03u\n",
 -				    (u_int)(mjoules_used / 1000),
 -				    (int)mjoules_used % 1000);
 +					(u_int)(mjoules_used / 1000),
 +					(int)mjoules_used % 1000);
  			break;
  		}
  
 @@ -574,12 +630,18 @@
  		switch (acline_status) {
  		case SRC_AC:
  			mode = mode_ac;
 +			minspeed = minspeed_ac;
 +			maxspeed = maxspeed_ac;
  			break;
  		case SRC_BATTERY:
  			mode = mode_battery;
 +			minspeed = minspeed_battery;
 +			maxspeed = maxspeed_battery;
  			break;
  		case SRC_UNKNOWN:
  			mode = mode_none;
 +			minspeed = 0;
 +			maxspeed = 0;
  			break;
  		default:
  			errx(1, "invalid AC line status %d", acline_status);
 @@ -595,7 +657,7 @@
  			/* Keep a sum of all power actually used. */
  			if (mwatts[i] != -1)
  				mjoules_used +=
 -				    (mwatts[i] * (poll_ival / 1000)) / 1000;
 +					(mwatts[i] * (poll_ival / 1000)) / 1000;
  		}
  
  		/* Always switch to the lowest frequency in min mode. */
 @@ -604,12 +666,12 @@
  			if (curfreq != freq) {
  				if (vflag) {
  					printf("now operating on %s power; "
 -					    "changing frequency to %d MHz\n",
 -					    modes[acline_status], freq);
 +						"changing frequency to %d MHz\n",
 +						modes[acline_status], freq);
  				}
  				if (set_freq(freq) != 0) {
  					warn("error setting CPU freq %d",
 -					    freq);
 +						freq);
  					continue;
  				}
  			}
 @@ -622,12 +684,12 @@
  			if (curfreq != freq) {
  				if (vflag) {
  					printf("now operating on %s power; "
 -					    "changing frequency to %d MHz\n",
 -					    modes[acline_status], freq);
 +						"changing frequency to %d MHz\n",
 +						modes[acline_status], freq);
  				}
  				if (set_freq(freq) != 0) {
  					warn("error setting CPU freq %d",
 -				    	    freq);
 +							freq);
  					continue;
  				}
  			}
 @@ -647,16 +709,26 @@
  					freq *= 2;
  				else
  					freq = freq * load / cpu_running_mark;
 +				
  				if (freq > freqs[0])
  					freq = freqs[0];
  			} else if (load < cpu_idle_mark &&
 -			    curfreq * load < freqs[get_freq_id(
 -			    freq * 7 / 8, freqs, numfreqs)] * 
 -			    cpu_running_mark) {
 +				curfreq * load < freqs[get_freq_id(
 +				freq * 7 / 8, freqs, numfreqs)] * 
 +				cpu_running_mark) {
  				freq = freq * 7 / 8;
  				if (freq < freqs[numfreqs - 1])
  					freq = freqs[numfreqs - 1];
  			}
 +			if(maxspeed > 0 && freq > maxspeed) {
 +				if(vflag)
 +					printf("Limiting calculated freq (%d Mhz) to %d Mhz\n", freq, maxspeed);
 +				freq = maxspeed;
 +			} else if(minspeed > 0 && freq < minspeed) {
 +				if(vflag)
 +					printf("Upgrading calculated freq (%d Mhz) to %d Mhz\n", freq, minspeed);
 +				freq = minspeed;
 +			}
  		} else { /* MODE_HIADAPTIVE */
  			if (load > cpu_running_mark / 2) {
  				if (load > 95 || load > cpu_running_mark)
 @@ -666,28 +738,37 @@
  				if (freq > freqs[0] * 2)
  					freq = freqs[0] * 2;
  			} else if (load < cpu_idle_mark / 2 &&
 -			    curfreq * load < freqs[get_freq_id(
 -			    freq * 31 / 32, freqs, numfreqs)] * 
 -			    cpu_running_mark / 2) {
 +				curfreq * load < freqs[get_freq_id(
 +				freq * 31 / 32, freqs, numfreqs)] * 
 +				cpu_running_mark / 2) {
  				freq = freq * 31 / 32;
  				if (freq < freqs[numfreqs - 1])
  					freq = freqs[numfreqs - 1];
  			}
 +			if(maxspeed > 0 && freq > maxspeed) {
 +				if(vflag)
 +					printf("Limiting calculated freq (%d Mhz) to %d Mhz\n", freq, maxspeed);
 +				freq = maxspeed;
 +			} else if(minspeed > 0 && freq < minspeed) {
 +				if(vflag)
 +					printf("Upgrading calculated freq (%d Mhz) to %d Mhz\n", freq, minspeed);
 +				freq = minspeed;
 +			}
  		}
  		if (vflag) {
 -		    printf("load %3d%%, current freq %4d MHz (%2d), wanted freq %4d MHz\n",
 +			printf("load %3d%%, current freq %4d MHz (%2d), wanted freq %4d MHz\n",
  			load, curfreq, i, freq);
  		}
  		j = get_freq_id(freq, freqs, numfreqs);
  		if (i != j) {
  			if (vflag) {
  				printf("changing clock"
 -				    " speed from %d MHz to %d MHz\n",
 -				    freqs[i], freqs[j]);
 +					" speed from %d MHz to %d MHz\n",
 +					freqs[i], freqs[j]);
  			}
  			if (set_freq(freqs[j]))
  				warn("error setting CPU frequency %d",
 -				    freqs[j]);
 +					freqs[j]);
  		}
  	}
  	if (set_freq(initfreq))
 ------=_20090720151749_38089--
 
 
>Unformatted:
