This is an old revision of the document!
Table of Contents
Laptop Hacks
Ho boy, this got difficult really quickly - 4 years ago I had everything working on my laptop with the LXDE spin of fedora plus fluxbox. After a quick spurt of travel using all the laptoppy things like conserving battery life, suspend/resume and lid up and down, I left it alone, using it like a desktop on AC power but updating through various fedora's. Quite unbeknownst to me, systemd
came in and the laptop got broken - I had to re-discover how to do everything again. Now I know and understand some of it and hopefully recording it here will help me next time.
Maybe it'll help you too - but you will almost certainly need to some make tweaks for your particular setup.
Why go through all this? Why not just use a full DE like KDE or gnome to take care of it? With KDE the best I could get (without digging just as deep as I have done here) was about 4 hours of battery life. By doing the hard work and understanding what's going on I can get up to 6.5 hours! Not bad.
Who's doing the work?
This section applies to NOT using a full desktop like gnome or KDE - those monsters do it all for you, nothing to see here, please move along.
For the rest of us using i3, fluxbox etc we need to first install acpid
It turns out that there are several players that respond to laptop events like lid opening & closing, ac power connection, suspend etc even without the distraction of gnome and KDE. Notably acpid
and systemd
. I got _really_ distracted thinking that systemd
was the new, definitive way that had taken over the world - turns out, I was wrong, my machine was still using acpid.
How to tell? AFAICS you look at the logs - /var/log/messages
or journalctl -r
How to change it? No idea - possibly installing acpid
switches over to that.
Power Disconnect/Connect events
If using acpid
I run this in my .xsession
.
# pm-util no longer executes /etc/pm/power.d/* things so if there's a # battery then listen on dbus for a/c connect/disconnect: upower -e |grep -q battery && power-monitor &
Where, power-monitor
is this bit of python which just runs the low-power
script when the power/battery status changes:
#!/bin/env python import gobject, os gobject.threads_init() from dbus import glib glib.init_threads() import dbus bus = dbus.SystemBus() def backtick(command): """ Equivalent of Bourne shell's backtick See http://www.python.org/doc/2.5.1/lib/node534.html """ from subprocess import Popen, PIPE #print "backtick: command='%s'\n" % command value = Popen(["sh", "-c", command], stdout=PIPE).communicate()[0].rstrip() #print "returning '%s'\n" % value return(value) def ac(*args, **kwargs): if args[1]['Online'] == 0: print("unplugged") os.system("sudo /home/bhepple/bin/low-power true") else: print("plugged in") os.system("sudo /home/bhepple/bin/low-power false") def check_battery(*args, **kwargs): battery_status = backtick("acpi -b") print(battery_status) if "Discharging" in battery_status: percent = int( backtick("acpi -b | awk '{print $4}' | tr -d '%,'")) print percent if percent < 10: backtick("battery-alarm&") gobject.timeout_add(60 * 1000, check_battery) # get path from 'upower -e': bus.add_signal_receiver(ac, signal_name="PropertiesChanged", dbus_interface="org.freedesktop.DBus.Properties", path="/org/freedesktop/UPower/devices/line_power_ADP0") check_battery() l = gobject.MainLoop() l.run()
Put this in $HOME/bin/low-power
:
#!/bin/sh POWER="OFF" [[ "${1:-}" && "$1" == "false" ]] && POWER="ON" (( $(id -u) == 0 )) || { echo "$0: needs to run as root" exit 1 } LOG=/tmp/low-power echo "stdout and stderr will be sent to $LOG" exec >$LOG 2>&1 case "$POWER" in OFF) battery-status logger -t $0 "power disconnect: killing bluetooth" systemctl stop bluetooth.target BT_PID=$(ps -ef |grep '[/]usr/libexec/bluetooth/bluetoothd' | awk '{print $2}') [[ "$BT_PID" ]] && kill -9 $BT_PID rmmod bnep btbcm btrtl btusb btintel bluetooth sudo /home/bhepple/bin/01-pm-power-display true sudo /home/bhepple/bin/02-pm-power-tweaks true sudo /home/bhepple/bin/03-pm-power-hda true powertop --auto-tune sleep 3 battery-status echo "consider turning off wifi" echo "consider turning off camera: rmmod uvcvideo" echo "consider turning off ethernet: rmmod r8169 mii" ;; ON) sudo /home/bhepple/bin/01-pm-power-display false sudo /home/bhepple/bin/02-pm-power-tweaks false sudo /home/bhepple/bin/03-pm-power-hda false logger -t $0 "power connect: starting bluetooth" modprobe bluetooth systemctl start bluetooth.target modprobe uvcvideo r8169 mii ;; esac pkill -0 i3blocks && pkill -RTMIN+9 i3blocks cat $LOG
Put this in $HOME/bin/01-pm-power-display
to dim/brighten the display - requires xbacklight
:
#!/bin/sh logger -t $0 "$0 $@" case "$1" in true) # called by pm-powersave on power disconnect xbacklight -display :0 -set 1 logger -t $0 "power disconnect: xbacklight -set 10" ;; false) xbacklight -display :0 -set 40 logger -t $0 "power connect: xbacklight -set 40" ALARM_PID_FILE="/var/run/battery-alarm" [[ -f $ALARM_PID_FILE ]] && { logger -t $0 "alarm pids = $( cat $ALARM_PID_FILE )" for PID in $(cat $ALARM_PID_FILE); do [[ $PID > 0 ]] && kill $PID done rm $ALARM_PID_FILE } ;; esac exit 0
Put this in $HOME/bin/03-pm-power-hda
to maximise battery or performance on the hard disc:
#!/bin/sh logger -t $0 "$0 $@" case "$1" in true) # called by pm-powersave on power disconnect logger -t $0 "power disconnect: hdparm -B1 -S5 /dev/sda" hdparm -B1 -S5 /dev/sda ;; false) # called by pm-powersave on power connect logger -t $0 "power connect: hdparm -B128 -S60 /dev/sda" hdparm -B128 -S60 /dev/sda ;; esac exit 0
Put this in $HOME/bin/02-pm-power-tweaks
for general tweaking - most of this originates from powertop
:
#!/bin/sh # BH logger -t $0 "$0 $@" case "$1" in true) # called by pm-powersave on power disconnect echo 5 > /proc/sys/vm/laptop_mode echo 0 > /proc/sys/kernel/nmi_watchdog echo 1 > /sys/devices/system/cpu/sched_smt_power_savings echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor echo 1500 > /proc/sys/vm/dirty_writeback_centisecs 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 echo min_power > /sys/class/scsi_host/host0/link_power_management_policy echo min_power > /sys/class/scsi_host/host1/link_power_management_policy echo Y > /sys/module/snd_hda_intel/parameters/power_save_controller echo 1 > /sys/module/snd_hda_intel/parameters/power_save for i in /sys/bus/{pci,i2c}/devices/*/power/control; do echo auto > $i; done ;; false) echo 0 > /proc/sys/vm/laptop_mode echo 1 > /proc/sys/kernel/nmi_watchdog echo 0 > /sys/devices/system/cpu/sched_smt_power_savings echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor echo 500 > /proc/sys/vm/dirty_writeback_centisecs for i in /sys/bus/usb/devices/*/power/autosuspend; do echo 2 > $i; done # for i in /sys/bus/usb/devices/*/power/level; do echo auto > $i; done echo max_performance > /sys/class/scsi_host/host0/link_power_management_policy echo max_performance > /sys/class/scsi_host/host1/link_power_management_policy #echo Y > /sys/module/snd_hda_intel/parameters/power_save_controller #echo 1 > /sys/module/snd_hda_intel/parameters/power_save #for i in /sys/bus/{pci,i2c}/devices/*/power/control; do echo auto > $i; done ;; esac exit 0
hibernate/suspend events
Put this into /etc/acpi/events/sleepconf
:
event=button/sleep action=systemctl suspend
I need to reset my synaptics touch pad on resume - this is /usr/local/bin/set-synaptics
:
#!/bin/sh [ "$DISPLAY" ] || { echo $0': $DISPLAY not set' >&2 exit 1 } pkill syndaemon syndaemon -i 1 -d -K synclient VertEdgeScroll=1 HorizEdgeScroll=1 VertTwoFingerScroll=1 HorizTwoFingerScroll=1 PalmDetect=1 TapButton1=1 TapButton2=2 # RTCornerButton=2
If using systemd
then you would put this into /etc/systemd/system/resume@.service
:
[Unit] Description=User resume actions After=suspend.target [Service] User=%I Type=simple ExecStart=/usr/local/bin/set-synaptics [Install] WantedBy=suspend.target
then run systemctl enable resume@bhepple.service
Disable nouveau
I find it slow & buggy so /etc/modprobe.d/blacklist.conf
gets:
blacklist nouveau
and /etc/default/grub
gets:
rdblacklist=nouveau
Run this to get grub updated:
grub2-mkconfig >/boot/grub2/grub.cfg