misc/125707: powerd: patch to force a method of battery state query

Konstantin Stepanov milezv at yandex.ru
Thu Jul 17 09:00:04 UTC 2008


>Number:         125707
>Category:       misc
>Synopsis:       powerd: patch to force a method of battery state query
>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:   Thu Jul 17 09:00:03 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Konstantin Stepanov
>Release:        FreeBSD 7 STABLE #11
>Organization:
>Environment:
FreeBSD knote 7.0-STABLE FreeBSD 7.0-STABLE #11: Thu May 29 17:12:45 EEST 2008     root at knote:/usr/src/sys/i386/compile/KNOTE  i386

>Description:
powerd by default tries to use "best" method of battery state discovery.
On my machine it tries to use "devd", which is running ok, but my battery uses CMBAT method, so "power on" event is not distinguished from "battery on" event report:

kstep at knote:p2/var/log% sudo devd -Dd
Parsing /etc/devd.conf
setting scsi-controller-regex=(aac|adv|adw|aha|ahb|ahc|ahd|aic|amd|amr|asr|bt|ciss|ct|dpt|esp|ida|iir|ips|isp|mlx|mly|mpt|ncr|ncv|nsp|stg|sym|trm|wds)[0-9]+
Parsing files in /etc/devd
Parsing files in /usr/local/etc/devd

### Here is pulled my power cable out ###

Processing event '!system=ACPI subsystem=CMBAT type=\_SB_.PCI0.LPCB.BAT1 notify=0x80'
Pushing table
setting system=ACPI
setting subsystem=CMBAT
setting type=\_SB_.PCI0.LPCB.BAT1
setting notify=0x80
Processing notify event
Testing system=ACPI against ^ACPI
Testing subsystem=CMBAT against ^ACAD
Testing system=ACPI against ^ACPI
Testing subsystem=CMBAT against ^Thermal
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ACPI
Testing subsystem=CMBAT against ^Suspend
Testing system=ACPI against ^ACPI
Testing subsystem=CMBAT against ^Resume
Testing system=ACPI against ^IFNET
Testing system=ACPI against ^IFNET
Testing system=ACPI against ^IFNET
Testing system=ACPI against ^IFNET
Popping table

### Here I inserted my power cable back ###

Processing event '!system=ACPI subsystem=CMBAT type=\_SB_.PCI0.LPCB.BAT1 notify=0x80'
Pushing table
setting system=ACPI
setting subsystem=CMBAT
setting type=\_SB_.PCI0.LPCB.BAT1
setting notify=0x80
Processing notify event
Testing system=ACPI against ^ACPI
Testing subsystem=CMBAT against ^ACAD
Testing system=ACPI against ^ACPI
Testing subsystem=CMBAT against ^Thermal
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ZFS
Testing system=ACPI against ^ACPI
Testing subsystem=CMBAT against ^Suspend
Testing system=ACPI against ^ACPI
Testing subsystem=CMBAT against ^Resume
Testing system=ACPI against ^IFNET
Testing system=ACPI against ^IFNET
Testing system=ACPI against ^IFNET
Testing system=ACPI against ^IFNET
Popping table

Summary:
"battery on" event gives message:
Processing event '!system=ACPI subsystem=CMBAT type=\_SB_.PCI0.LPCB.BAT1 

"power on" event gives message:
Processing event '!system=ACPI subsystem=CMBAT type=\_SB_.PCI0.LPCB.BAT1 

So there's no way on my notebook to distinguish turning power on or off via devd daemon, as powerd tries and ends up in either state constantly:


*** power is on ***
kstep at knote:p1~% sudo powerd -b adaptive -n adaptive -a maximum -v
powerd: using sysctl for AC line status
powerd: using devd for AC line status

*** pulled power cable off => adaptive mode ***

idle time > 90%, decreasing clock speed from 1600 MHz to 1400 MHz
idle time > 90%, decreasing clock speed from 1400 MHz to 1333 MHz
idle time > 90%, decreasing clock speed from 1333 MHz to 1166 MHz
idle time > 90%, decreasing clock speed from 1166 MHz to 1067 MHz
idle time < 65%, increasing clock speed from 1067 MHz to 1333 MHz
idle time > 90%, decreasing clock speed from 1333 MHz to 1166 MHz
idle time > 90%, decreasing clock speed from 1166 MHz to 1067 MHz
idle time < 65%, increasing clock speed from 1067 MHz to 1333 MHz
idle time < 65%, increasing clock speed from 1333 MHz to 1600 MHz
idle time > 90%, decreasing clock speed from 1600 MHz to 1400 MHz
idle time > 90%, decreasing clock speed from 1400 MHz to 1333 MHz
idle time > 90%, decreasing clock speed from 1333 MHz to 1166 MHz
idle time > 90%, decreasing clock speed from 1166 MHz to 1067 MHz
idle time > 90%, decreasing clock speed from 1067 MHz to 933 MHz
idle time > 90%, decreasing clock speed from 933 MHz to 800 MHz
idle time < 65%, increasing clock speed from 800 MHz to 1067 MHz

*** turned back power cable => should be back to "maximum" mode ***

idle time > 90%, decreasing clock speed from 1067 MHz to 933 MHz
idle time > 90%, decreasing clock speed from 933 MHz to 800 MHz
idle time > 90%, decreasing clock speed from 800 MHz to 700 MHz
idle time > 90%, decreasing clock speed from 700 MHz to 600 MHz
idle time < 65%, increasing clock speed from 600 MHz to 800 MHz
idle time > 90%, decreasing clock speed from 800 MHz to 700 MHz
idle time > 90%, decreasing clock speed from 700 MHz to 600 MHz

To solve the problem, I created a patch to add new parameter to force method of power mode discovery (see "Fix to the problem if known" part.
>How-To-Repeat:
0. You should have some kind of PC (notebook) with CM battery and devd daemon running.

1. Run "powerd -b adaptive -n adaptive -a maximum -v" while power is on.
PC's CPU should run at maximum frequency.

2. Turn off power, so PC begin to use battery. powerd should go to "adaptive" mode, CPU's frequency will begin to "jump" up & down depending of PC load.

3. Turn power on again, so PC begin to use external power source. powerd will not turn back to "maximum" mode, CPU's frequency will be still "jumping"...

>Fix:
I created a patch to add "-f <mode>" parameter, so I can run 

% sudo powerd -b adaptive -n adaptive -a maximum -f sysctl

and powerd will use "sysctl" method to distinguish which power mode my notebook is, and this works correctly, switching modes from "maximum" to "adaptive" and back again depending of power source in use.

My patch is attached to this form.

Patch attached with submission follows:

--- powerd.c	2007-06-13 22:05:11.000000000 +0300
+++ /home/kstep/sys/powerd.c	2008-05-13 00:51:33.000000000 +0300
@@ -102,19 +102,20 @@
 
 static volatile sig_atomic_t exit_requested;
 static power_src_t acline_status;
-static enum {
+typedef enum {
 	ac_none,
 	ac_acpi_sysctl,
 	ac_acpi_devd,
 #ifdef USE_APM
 	ac_apm,
 #endif
-} acline_mode;
+} t_acline_mode;
+static t_acline_mode acline_mode;
+static t_acline_mode force_acline_mode = ac_none;
 #ifdef USE_APM
 static int	apm_fd = -1;
 #endif
 static int	devd_pipe = -1;
-
 #define DEVD_RETRY_INTERVAL 60 /* seconds */
 static struct timeval tried_devd;
 
@@ -230,6 +231,7 @@
 static void
 acline_read(void)
 {
+	if (force_acline_mode != ac_none) acline_mode = force_acline_mode;
 	if (acline_mode == ac_acpi_devd) {
 		char buf[DEVCTL_MAXBUF], *ptr;
 		ssize_t rlen;
@@ -275,7 +277,10 @@
 	}
 #endif
 	/* try to (re)connect to devd */
-	if (acline_mode == ac_acpi_sysctl) {
+	if (acline_mode == ac_acpi_sysctl &&
+			(force_acline_mode == ac_none
+			|| force_acline_mode == ac_acpi_devd)) {
+
 		struct timeval now;
 
 		gettimeofday(&now, NULL);
@@ -357,7 +362,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] [-f method] [-p ival] [-r %%] [-P pidfile]\n");
 	exit(1);
 }
 
@@ -387,8 +392,23 @@
 	if (geteuid() != 0)
 		errx(1, "must be root to run");
 
-	while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:v")) != EOF)
+	while ((ch = getopt(argc, argv, "f:a:b:i:n:p:P:r:v")) != EOF)
 		switch (ch) {
+		case 'f':
+			if (strcmp(optarg, "sysctl") == 0)
+			{
+				force_acline_mode = ac_acpi_sysctl;
+			}
+			else if (strcmp(optarg, "devd") == 0)
+			{
+				force_acline_mode = ac_acpi_devd;
+			}
+#if USE_APM
+			else if (strcmp(optarg, "apm") == 0) {
+				force_acline_mode = ac_apm;
+			}
+#endif
+			break;
 		case 'a':
 			parse_mode(optarg, &mode_ac, ch);
 			break;


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list