Sun Oct 23 19:05:42 EST 2005

ACPI and Speedstep with Linux on my Thinkpad


Well, I've decided to go with Slackware for the laptop mostly because it's what I know. So, Slackware being what it is I had to take matters into my own hands and configure some of the more ugly things that may be done for you in other distributions. In this case it was ACPI and CPU Frequency Throttling (Speedstep). I don't know for sure if this stuff just works on another distro as I didn't try. What can I say, it's hard to break the Slack habit. ;)

The laptop in question is an IBM Thinkpad T30 and according to Google it is well supported in Linux (mostly). I went and installed Slackware 10.2 and most everything worked right out of the box like sound, wireless LAN, and APM. APM worked fine except that I didn't see any support for the Thinkpad buttons and saw that the kernel had a module just for Thinkpads in ACPI. Rather than figure out just what modules I needed to modprobe in I just compiled the things right into the kernel since I can't think of any time I'd not want them there. That worked well, the sleep button worked and when I closed the laptop lid the system went to sleep.

I did notice though that when I was on batter i was only getting about 40 minutes of run time when I was getting about 1.5 hours in Windows. So then it was onto learning how to throttle the CPU speed. Now, this was a pain in the rump. I had the modules I needed loaded and no matter what I did Klaptop wouldn't change the CPU speed when going from between battery and AC. I even compiled all the modules directly into the kernel to see if it helped. No go. I could change the speed manually but not automatically.

It turns out that after some research I learned that this model only supports two speeds of CPU. One at 1.8GHz and the other at 1.2GHz. Klaptop wanted to throttle based on percentage. For some odd reason I could set the percentage manually and it seemed to make a difference in performance but it just wouldn't do it automatically.

So, as far as CPU frequency throttling it can be by a userspace program or by the kernel itself. Klaptop is a userspace program and since that wasn't working I decided to try out letting the kernel do it. I compiled in speedstep-ich and the ondemand governor. The idea is that the ondemand Governor will watch your current CPU needs and adjust the speed accordingly. To get this working all you have to do is make sure the ondemend module and the speedstep module is loaded (or compiled into the kernel) and then echo -n ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor and supposedly it will "just work". For some reason when I echo ondemand into scaling_governor it doesn't take and just stays as userspace. I haven't put much effort into figuring out the why since I'm a bit tired of playing with this. I did figure out that I could manually echo either 1200000 or 1800000 into /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed and it would work. But how to make it do this automatically?

All I did was kept and eye on /var/log/acpid with tail -f and unplugged the AC adapter and plugged it back in a few times. In my case every time I plugged in the adapter it generated an ACPI event called "ac_adapter AC 00000080 00000001" and when I unplugged it a "ac_adapter AC 00000080 00000000" event was generated. All I had to do was create two scripts in /etc/acpi. One of the scripts I called on_battery.sh and it contains:
# Sets the CPU to 1.2 GHz when on battery
#
echo -n 1200000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
#
# Set Hard Drive sleep to 5 minutes
hdparm -S 60 /dev/hda
And the other one called ac_cpu.sh contains:
# Sets the CPU to 1.8 GHz when on wall AC
#
echo -n 1800000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
#
# Set hard drive sleep time to 20 minutes
hdparm -S 240 /dev/hda
I made them executable then went into /etc/acpi/events and created two new files to catch and then run the script to make the CPU frequency change. The two files can be called pretty much anything as far as I can tell as long as they aren't hidden files. I called one ac_cpu and the other onbattery_cpu. ac_cpu contains:
event=ac_adapter AC 00000080 00000001
action=/etc/acpi/ac_cpu.sh
and onbattery_cpu contains:
event=ac_adapter AC 00000080 00000000
action=/etc/acpi/onbattery_cpu.sh
Finally I had to restart acpid with /etc/rc.d/rc.acpid restart and it worked! Now I can get about 1.5 hours out of a full charge instead of 30-45 minutes. And I can put other commands into the scripts to do other things when the state changes. You can see I already have hdparm to tweak my sleep times.

Posted by Brian | Permalink | Categories: Computers and Technology, Work | |