Linux on the move with acpi

Linux has good support for all sorts of varied and interesting hardware these days, right across the spectrum from esoteric mainframes to the common desktop PC. But configuring a computer such as a laptop or netbook to be energy efficient to save battery power can still be a source of frustration for linux users. Or at least it was to this linux user.

ACPI, the standard for power management, is capable of switching off or disabling devices to save power, such as shutting down wireless or bluetooth transmitters, ethernet ports, dimming monitor screens, spinning down idle hard drives and putting processors in to sleep states. This replaces the previous standard, APM. Older computers from before about 2000 support only apm, the newest computers support only acpi, with those built around the changeover supporting acpm and an incomplete acpi specification. It’s a good idea to have one or the other, and not to run both at the same time.

It has improved greatly, but power management support in linux is, as much as anything, a work in progress. Using Debian-based Crunchbang, my Samsung Q320 did not respond to acpi events at all – removing the power cable and switching to battery power did not dim the screen or scale down the processor frequency, for example. On a mission to squeeze more than 1hr 50min from my battery, I embarked on the following odyssey.

Install Acpi support

It may seem obvious, but as acpi is not a system essential, it is quite possible to run linux without any acpi layer at all. Kernel support for acpi has been included since kernel versions 2.4, and newer 2.6 kernels provide better support for more features and hardware. But you’ll still need to install the rest.

$ sudo apt-get install acpid acpi-fakekey pm-utils

This will set up the acpi daemon (acpid) to listen for acpi system events and run scripts in /etc/acpi to trigger system sleep, suspend, hibernate, and resume events.

acpi-fakekey generates fake key-press events to represent those keys providing acpi functions that are not recognised by the kernel. Getting dead keys recognised is in fact another complication in the process.

pm-utils is a distribution-neutral standardised set of hooks that can be called to trigger or resume from a sleep, suspend or hibernate acpi call, configured by placing scripts in /etc/pm/.

Add to that some utilities:

$ sudo apt-get install acpi acpitool acpi_listen

acpi is a very simple command line utility that will return information about the battery, AC adaptor, thermal trip points and CPU states, and I include it here really only because it comes with most distributions and some scripts may depend on it.

acpitool is a much more substantial acpi command line client that can query and manipulate acpi information and trigger acpi events. Some functions such as changing backlight settings are limited to Toshiba, Asus and IBM hardware.

acpi_listen runs in a terminal and intercepts and prints acpi requests as they appear, in the same way xev does for key-presses.

Hardware-specific acpi layer

With the essentials installed, we need to fill the gaps between the generic linux acpi drivers and the various function key combinations, hotkeys and extra buttons that are particular to each laptop model or manufacturer.

For those with IBM, Toshiba, Acer or Asus models, installing acpi-support may be enough: $ sudo apt-get install acpi-support, but this package has been deprecated, in Ubuntu at least. It includes a command line tool and more scripts that run in response to the non-standard buttons most laptops use to set low-power modes, hibernation, brightness settings, etc. It is configured from /etc/default/acpi-support and controlled by /etc/init.d/acpi-support. But it’s not much use for my Samsung, for example.

It turns out that Samsung laptops have a somewhat rocky history in terms of bulletproof linux compatibility. But developer Fortunato Ventre of the Linux On My Samsung project has made excellent progress carving out a functioning acpi implementation for Samsung netbooks, which by extension (mostly) works with other Samsung machines.

Add the project Launchpad PPA repository at launchpad.net/~voria/+archive/ppa to /etc/apt/sources.list (how to). There are several tools for different purposes, you might not need all of them. The easy-slow-down-manager lets you set the fan speed between fast, normal and silent (slow). samsung_backlight and nvidia-bl-dkms are two LCD screen backlight drivers that replace the standard and incompatible video.ko acpi driver. This will allow programs to change the screen brightness directly. samsung-tools includes a command line tool and graphic interface (samsung-tools-preferences) that can manually set up what function key combinations trigger which actions. More usefully it also provides a gui for powersaving measures, as we’ll see.

The updated udev and linux packages provide no-hacks-required support for different Samsung models by providing udev with the identifier strings for the hardware, but as mine wasn’t included I didn’t bother, and it seems to (mostly) work anyway. See if you’re model is listed in this thread.

I tried the nvidia_bl module but my Q320 didn’t like it; trying to change the brightness would blank the screen and it would refuse to come back again, forcing a reboot. So I used the samsung_backlight module, loaded automatically as the package installer compiles support into the kernel, and prevented the standard acpi video driver from loading by adding:

blacklist video

to /etc/modprobe.d/fbdev-blacklist.conf

Finally, the kernel must be told to use the new driver by editing a line in /etc/default/grub:

GRUB_CMDLINE_LINUX="acpi_backlight=vendor"

Followed by:

$ sudo update-grub
$ sudo update-initramfs -u

And finally, add a line to the Section “Device” clause of /etc/x11/xorg.conf:

Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "GeForce G 105M"
# add line below to get brightness keys working
Option "RegistryDwords" "EnableBrightnessControl=1"
EndSection

After which (on restarting X) my brightness keys worked, and the screen dimmed when I pulled out the power cord. Now that’s progress.

Power saving tools

Last of all, we need to install scripts and tools that will take advantage of this new power-saving framework by shutting down power-hungry devices that are not being used.

$ sudo apt-get install laptop-mode-tools cpufrequtils powertop

The laptop-mode-tools will add a directory /etc/laptop-mode where scripts can be placed which when triggered by acpi events will run other programs such as hdparm, sdparm and ethtool (all dependencies installed at the same time) to configure disk drive and other PCI device’s power-down timeouts or set some level of power-saving. It is configured from /etc/laptop-mode/laptop-mode.conf. It does other clever things too, such as restarting syslogd with alternate settings so that logfiles are not constantly being written to when the disk is trying idling. It is worth noting that the laptop-mode in the Ubuntu repositories is a crippled version, which the developer recommends replacing with the full Debian package.

cpufrequtils installs programs that can manage processor states, switch up or down the CPU speed according to load, and place it sleep states when idle. It also provides a means to set the CPU demand governor, which controls how aggressive or passive the CPU will be in trying to sleep.

powertop is from the official LessWatts linux acpi project from Intel developers. Like top, it shows what processes are calling interrupts and waking the CPU so you can hunt them down and shut them off to save power. Better still it provides a simple interface that identifies these programs and offers an on/off toggle to do it for you.

And with that, you should have all you need.

Tweaking and debugging

One thing to watch out for is the rate at which hard disks idle, spindown and then restart. Some drives assume a very aggressive power management mode, but if there is a lot of disk activity then the drive will be spinning down and up again every minute or less, which is going to have a serious impact on the lifespan of your drive. It is easy enough to set a less aggressive timing, the tricky bit comes in locating which program and which config file controls the setting. In this case, hdparm (/etc/hdparm.conf), laptop-mode (/etc/laptop-mode/laptop-mode.conf) and samsung-tools (/etc/samsung-tools/scripts) could all be the culprit.

$ sudo hdparm -B[1...255] /dev/sda

This will set the the power management feature of the drive, where 1 is the most aggressive power management, 254 is top performance, and 255 disables power management. Settings between 1 and 127 will allow spin-down and head parking, 128 and above will not. If the sound (and slight delay) of the drives spinning up irritates or worries you, set this to 128 or higher.

$ sudo hdparm -S[1...255] /dev/sda

This controls the idle time-out setting of the drive, ie., how long the drive will wait since the last read or write before switching to lower-power idle mode, and also how long to wait before timing out and sleeping, as in -B above. Note -s (lowercase s) puts the drive to sleep, so don’t mistype.

Esoterically, this figure represents the following: 0 disables time-out/idle mode; 1 to 240 represents multiples of five seconds, from 5 secs to 20 minutes; 241 to 251 represent multiples of 30 minutes, from 30 mins to 5.5 hours; 252 represents 21 minutes, 253 is a vendor-defined period in the region of hours, and 254 is reserved; 255 represents, bizarrely, 21 minutes and 15 seconds. Suck on that.

If laptop mode has been enabled to control all devices, check its config file for the same settings:


# Set to 0 to disable
CONTROL_HD_IDLE_TIMEOUT=1
#
# Idle timeout values. (hdparm -S)
# Default is 2 hours on AC (NOLM_HD_IDLE_TIMEOUT_SECONDS=7200) and 20 seconds
# for battery and for AC with laptop mode on.
#
LM_AC_HD_IDLE_TIMEOUT_SECONDS=300
LM_BATT_HD_IDLE_TIMEOUT_SECONDS=20
NOLM_HD_IDLE_TIMEOUT_SECONDS=72
#
# Should laptop mode tools control the hard drive power management settings?
#
# Set to 0 to disable
CONTROL_HD_POWERMGMT=1
#
# Power management for HD (hdparm -B values)
#
BATT_HD_POWERMGMT=200
LM_AC_HD_POWERMGMT=254
NOLM_AC_HD_POWERMGMT=254

Running samsung-tools-preferences should reflect the values from laptop-mode.conf in the laptop-mode-tools dialog, with the appropriate boxes selected or blank.

For everything else there’s powertop. Run it as root and switch to the wonderfully named Tunables tab using cursors – it will show a list of devices that can be low-powered or disabled, including (on Intel-based chipsets) most PCI/PCIe and USB bus devices and host controllers, ATA/SATA chipsets and drives. Use the cursors to select those marked “Bad” and change them to “Good”. That’s it. You’ll notice the difference between running powertop on mains power or battery – there’s little point in turning powersaving on for every device when plugged into the mains, unless you really want to help save the planet by a couple of watts.

There’s a lot of very fragmented and, by its nature, very hardware-specific information about acpi around the internet. Some informative pages can be found at the Arch wiki (pm-utils, cpufrequtils, laptop-mode, Acpi hotkeys), the Ubuntu wiki (power management and troubleshooting) and an exhaustive page at IBM thinkwiki.

And what was the result of this struggle? Well, battery life of 1hr 50min rose to somewhere around 2hr 20min, and peaked at 3hr 1min, but swayed wildly between the three depending on whether I was just looking at the battery meter, or actually using the computer. What have we learned? Well, battery life estimations are largely worthless. Oh, and it turned out my battery was down to 50% of it’s original capacity, after just two and a half years. Looks like I’m staying within sprinting pace of the mains for now…