Howto: Powersaving tweaks with a udev rule

Recommended Posts


I previously made a guide showing how you can utilize pm-utils scripts to enable extra powersaving settings in linux:

I've since found a solution I like better, because its much simpler and I am also trying to lessen my dependence on pm-utils (it seems there's been no active development for the past few years). I'm hoping I'll be able to uninstall it eventually since the latest upower can now use systemd instead of pm-utils for suspend/hibernate, but it still seems to require pm-utils for some things.

Anyway, on to the guide. I found this solution over on the arch forums: https://bbs.archlinu...163335#p1163335.

Basically all this solution is: A udev rule that detects whether your system is on AC or Battery, then runs a script, and passes a true or false value to the script depending on whether you are on AC or Battery.

1. Create the udev rule. Create a file named /etc/udev/rules.d/50-powersave.rules. Place the following in the file:

SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="/usr/bin/powersave true"
SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="1", RUN+="/usr/bin/powersave false"

In this example my powersaving script is located at /usr/bin/powersave. If you want your script in a different location, make sure to change the path there.

2. Create the powersaving script. I've saved my script at /usr/bin/powersave. Here is an example script, this is the one I use on my system. With this type of thing your mileage will vary, you may have to use different commands depending on your hardware and/or preferences. My example script is fairly conservative and should work fine for most:

case "$1" in
true) # Enable power saving settings on battery
# Device Runtime-PM
for dpcontrol in /sys/bus/{pci,spi,i2c}/devices/*/power/control; do echo auto > $dpcontrol; done
# Disable nmi_watchdog
echo 0 > /proc/sys/kernel/nmi_watchdog
# kernel write mode
echo 5 > /proc/sys/vm/laptop_mode
echo 1500 > /proc/sys/vm/dirty_writeback_centisecs
# disk powersave
hdparm -S 36 -B 128 /dev/sda &> /dev/null
for i in /sys/class/scsi_host/host*/link_power_management_policy; do echo min_power > $i; done
# sound card powersave
echo 10 > /sys/module/snd_hda_intel/parameters/power_save
echo Y > /sys/module/snd_hda_intel/parameters/power_save_controller
# wlan0 powersave
iw dev wlan0 set power_save on &> /dev/null
false) # Return to default on AC power
# Device Runtime-PM
for dpcontrol in /sys/bus/{pci,spi,i2c}/devices/*/power/control; do echo on > $dpcontrol; done
# Enable nmi_watchdog
echo 1 > /proc/sys/kernel/nmi_watchdog
# kernel write mode
echo 0 > /proc/sys/vm/laptop_mode
echo 500 > /proc/sys/vm/dirty_writeback_centisecs
# disk powersave
hdparm -S 0 -B 254 /dev/sda &> /dev/null
for i in /sys/class/scsi_host/host*/link_power_management_policy; do echo max_performance > $i; done
# sound card powersave
echo 300 > /sys/module/snd_hda_intel/parameters/power_save
echo Y > /sys/module/snd_hda_intel/parameters/power_save_controller
# wlan0 powersave
iw dev wlan0 set power_save off &> /dev/null
exit 0

3. Then you just make the powersave script executable, and run [b]udevadm control --reload-rules[/b] to make udev recognize the rule we added.

4. Tweak the script to your liking! Below I've explained what the commands in the example do, and some possible things to try out and/or look out for:

[b]Runtime-PM:[/b] [size=4][font=arial,helvetica,sans-serif]The first command in the script enables runtime-pm for everything except USB devices (since the kernel does it automatically on my machine, as I explain in the USB autosuspend section. In addition my system requires USB modules to be unloaded before suspend or else it hangs, and I do this via a systemd sleep hook. If I mess with toggling usb powersaving settings on my machine, the values get set inconsistently after suspend/resume). The command to enable runtime-pm for all devices on your machine would be:[/font][/size] [color=#333333][font=Consolas,][b]for i in /sys/bus/*/devices/*/power/control; do echo auto > $i; done[/b]. [font=arial,helvetica,sans-serif][size=4]You can echo "on" instead of auto if you want to disable it on AC. If you don't have bugs like my machine has the above command should work fine :)[/size][/font][/font][/color]

[color=#333333][font=Consolas,][font=arial,helvetica,sans-serif][size=4][b]NMI Watchdog:[/b] This is safe to disable, disabling it saves a bit of battery life.[/size][/font][/font][/color]

[color=#333333][font=Consolas,][font=arial,helvetica,sans-serif][size=4][b]VM Writeback:[/b] Increasing the vm_writeback value on battery causes less disk writes and can save a bit of power (and can help allow the disk to spindown). The value in my example script is the one recommended by powertop and is safe. [/size][/font][/font][/color]

[b]USB autosuspend:[/b] I don't have any usb autosuspend settings in my script, because the newest kernels seem to enable this automatically (on my arch system, even with no powersaving tweaks via pm-utils or this method, usb autosuspend is enabled by default with a 2 second timeout). If you need to enable it manually, you could use these commands:

# usb autosuspend

for i in /sys/bus/usb/devices/*/power/autosuspend; do echo 1 > $i; done
for i in /sys/bus/usb/devices/*/power/level; do echo auto > $i; done

The first command sets the timeout of how many seconds to wait to suspend usb devices after they've been idle, this example uses 1 second. The second command enables usb autosuspend. To disable USB autosuspend you would echo "0" and "on" instead of "1" and "auto".

[b]HDparm Settings: [/b]My script uses pretty conservative hdparm settings that shouldn't spin down your drive like crazy. I use hdparm -S 36 to set the disk spindown timeout to 3 minutes, and hdparm -B 128 which is the most conservative value that still allows disk spindown. If you don't want to use disk spindown at all use [b][color=#333333]hdparm -S 0 -B 254 /dev/sda &> /dev/null[/color][/b] instead.

[b]Sata Link Power Management: [/b]sata aplm is known to be buggy on certain hardware (potentially causing data loss) so only enable this option if you know it works on your machine. To disable it comment out the [color=#333333][font=Consolas,][b]link_power_management_policy[/b] [size=4]line.[/size][/font][/color]

[b]Intel Audio Powersave:[/b] My script enables intel audio powersave on both battery and AC, but with a 5 minute timeout on AC, and 10 seconds on battery. I have intel controller powersave enabled on both AC and Battery due to a bug (If you toggle that one on and off then your audio codecs run at 100% all the time even when they are supposed to be in powersave). So if you want to enable this option this is the recommended way to do it. However enabling controller powersave can produce audible clicks when powersaving goes in and out of effect. If this annoys you, try increasing the timeout values or disabling controller powersave on both ac and battery (by echoing N instead of Y)

[b]Wireless:[/b] Mileage may vary on this one, it depends on the wireless tools your distro uses. My example uses the iw tool to enable wireless powersaving, other distros may use iwconfig. If you need to use iwconfig the command would be:[b] [color=#333333]iwconfig wlan0 power on &> /dev/null[/color][/b]

[b]Screen Brightness: [/b]Gnome does this for me, so there is no screen brightness settings in my script. If you wanted to add this an example would be:

To lower brightness and enable display power management on battery:

for i in /sys/class/backlight/acpi_video*/brightness; do echo 0 > $i; done

xset +dpms
xset dpms 0 0 120

To restore brightness and disable dpms:

for i in /sys/class/backlight/acpi_video*/brightness; do echo 9 > $i; done

xset -dpms

Remember you want to put any settings you want enabled on battery under the "True" section of the script, and settings you want on AC in the "false" section.

I have only tested this method in arch, but see no reason why it wouldn't work in other distros.

Link to post
Share on other sites
  • 2 months later...

Great "how to" Viper, thanks! ... will be trying this on my current distro (Debian). I'll let you know how it went.

Link to post
Share on other sites

Thanks for the script. I am going to do some tweaking to it to run on my T520 with Slackware64.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.