Improve battery life on a MacBook in Ubuntu

I recently got one the newest MacBookPro 13" and after giving a 2 weeks trial period to OSX I decided to switch back to ubuntu and I certainly don't regret it. The only two things I *really* loved in OSX were:

* longer battery life (apple claims up to 7 hours and my experience is on that line)

* very fast and efficient suspend/resume

Those two weren't quite the same in an out-of-the box ubuntu 9.04 installation but with some hacks here and there I got them working not too bad. Here I want to describe what I did and then hopefully with a bit of team work we'll get even better!

the first thing to do is  to enable laptop-mode in /etc/default/acpi-support

Second, do some configurations in /etc/laptop-mode/conf.d


Suspend and Resume actually didn't work at all after installation. I figured the reason was that I didn't have the latest EFI version. So I rebooted in OSX, did the upgrade to 1.7 and voila. Worked fine.
They were still a bit slower than OSX, though. Especially resume (which is the one we care the most, of course). To fix it I did the following

install a package called uswsusp

sudo apt-get install uswsusp

the package carries two nice tools: s2ram and s2disk


First of all make sure they work launching


sudo s2ram --force

to suspend to ram or


sudo s2disk

to hibernate.


I personally don't care too much about hibernation. Nice thing about s2ram, though, is that it goes to sleep maintaining somehow the proper wifi settings so that when you open up the lid again the machine is immediately connected to the internet, exactly as it happens in OSX. The resume takes about 5 seconds and you are ready to go.


By default gnome prompts you with the password after resume. If you don't like this behaviour, you can change it running


gconftool -s /apps/gnome-power-manager/lock/suspend -t bool false

you can of course use s2ram and s2disk as default tools. to do so, you need to replace two of the existing scripts.


sudo cp /usr/lib/hal/scripts/linux/hal-system-power-hibernate-linux /usr/lib/hal/scripts/linux/hal-system-power-hibernate-linux.bak
sudo cp /usr/lib/hal/scripts/linux/hal-system-power-suspend-linux /usr/lib/hal/scripts/linux/hal-system-power-suspend-linux.bak

and then


 sudo gedit /usr/lib/hal/scripts/linux/hal-system-power-hibernate-linux

replace what you find with:


#!/usr/bin/env bash
 sudo gedit /usr/lib/hal/scripts/linux/hal-system-power-suspend-linux

replace what you find with:


#!/usr/bin/env bash
/usr/sbin/s2ram --force


Restart also doesn't seem to work out of the box. With kernels 2.6.28-13 and -14 the system would go throughout the entire rebooting procedure then hang at the very end with "Restarting System". As a workaround, install kexec-tools and make sure it's active. This will enable kexec restart (meaning, when you restart the computer will skip EFI/GRUB and load directly the kernel.


sudo apt-get install kexec-tools
gedit /etc/default/kexec

and make sure the load exec is set to True.

Extend Battery life.

This is a bit trickier. First of all, we should be aware of what the goal is. Let's learn more about the battery:


gg@ggmac:~$ cat /proc/acpi/battery/BAT0/info 
present:                 yes
design capacity:         54500 mWh
last full capacity:      55300 mWh
battery technology:      rechargeable
design voltage:          10950 mV
design capacity warning: 250 mWh
design capacity low:     100 mWh
capacity granularity 1:  10 mWh
capacity granularity 2:  10 mWh
model number:            bq20z45189ABCDEF0123456789ABCDE
serial number:           
battery type:            LIONz45189ABCDEF0123456789ABCDE
OEM info:                DPONz45189ABCDEF0123456789ABCDE

What we are interested in is the total capacity, in my case about 55W.


Now, we need to know what the consumption is. To do this, the best way is to use powertop


sudo apt-get install powertop

and then:


powertop -d

powertop will run for 15 seconds and collect info about the system. There's plenty of documentation out there: go dive. For now let's say what you care the most is this line:


Power usage (ACPI estimate): 16.3W (2.7 hours)

It says that your laptop consumes about 16W/hour meaning that with a full charge you'd get 55/16=~3.5 hours of battery. Our goal is to go down to something between 9 and 10 W.


Here's how. First of all, the video. You probably have some new version of the nvidia driver. Open xorg.conf and add the following lines to the section Device:


Option "OnDemandVBlankInterrupts" "True"
Option "RegistryDwords" "PowerMizerLevel=0x3"

and the following to the section screen:


Option	   "Coolbits" "1"

these lines will enable VBlankondemand and will set powermizer to "ondemand"; the latter will allow overclocking/downclocking of the GPU.


After having done this, you want to change a couple of kernel settings.


Open /boot/grub/menu.list and add to the kernel line the following:


usbcore.autosuspend=1 hpet=force

so, your kernel line should read something like this:


kernel		(hd0,2)/boot/vmlinuz-2.6.28-13-generic root=/dev/sda3 ro quiet splash usbcore.autosuspend=1 hpet=force vga=791

Finally, the more juicy part. Create a file called 99-savings


gedit ~/99-savings

and copy and paste the following code


#!/usr/bin/env bash

# Go fast on AC power.  Similar to default Ubuntu settings
if on_ac_power; then
  # Set the drive to mostly stay awake.  Some may want to change -B 254
  # to -B 255 to avoid accumulating Load_Cycle_Counts
  hdparm -B 254 -S 240 -M 254 /dev/sda

  # Remount ext3 filesystems so the journal commit only happens every 60
  # seconds.  By default this is 5 but, I prefer to reduce the disk
  # activity a bit.
  mount -o remount,commit=60 /
  mount -o remount,commit=60 /home

  # Turn off the laptop mode disk optimization
  #echo 0 > /proc/sys/vm/laptop_mode

  # Set kernel dirty page value back to default
  echo 10 > /proc/sys/vm/dirty_ratio
  echo 5 > /proc/sys/vm/dirty_background_ratio

  # Only wakeup every 60 seconds to see if we need to write dirty pages
  # By default this is every 5 seconds but, I prefer 60 to reduce disk
  # activity.
  echo 6000 > /proc/sys/vm/dirty_writeback_centisecs

  # Turn off sound card power savings
  echo 0 > /sys/module/snd_hda_intel/parameters/power_save
  # Set the SATA to max performance
  echo max_performance > /sys/class/scsi_host/host0/link_power_management_policy
  echo max_performance > /sys/class/scsi_host/host1/link_power_management_policy

  # Make sure ondemand governor is set
  echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 

  # Enable the webcam driver
#  modprobe uvcvideo

  #restart bluetooth #you can also decide to use RFKILL here. 
  sudo /usr/sbin/hciconfig hci0 up

  # Start optional  services
#  sudo /etc/init.d/cron start
  sudo /etc/init.d/bluetooth start
  sudo /etc/init.d/preload start

  #reset brightness of screen and keyboard
  sudo nvclock -S 85
  sudo echo 50 | sudo tee -a /sys/class/leds/smc::kbd_backlight/brightness

  #Enable eth0
  sudo ifconfig eth0 up

  #reset clock nvidia card (requires coolbits=1)
  sudo nvidia-settings -a GPU2DClockFreqs=100,0
  sudo nvidia-settings -a GPU3DClockFreqs=450,0

else # Save power

  # Set the disks to aggressively save power and use the lowest acoustic
  # level.  Some might find these settings too aggressive.  If so, change 
  # "-S 4" to something larger like -S 24 (two minutes) and -B 128 to -B 254.
  hdparm -B 128 -S 4 -M 128 /dev/sda
  # Change the ext3 commit times to 10 minutes.  This reduces diskhcd
  # activity
  mount -o remount,commit=600 /

  # Set laptop disk write mode
  echo 5 > /proc/sys/vm/laptop_mode

  # Manually set the iwl3945 driver to power savings.
  echo 5 > /sys/bus/pci/drivers/iwl????/0000\:??\:00.0/power_level  

  # Reduce disk activity by waiting up to 10 minutes before doing writes
  echo 90 > /proc/sys/vm/dirty_ratio
  echo 1 > /proc/sys/vm/dirty_background_ratio
  echo 60000 > /proc/sys/vm/dirty_writeback_centisecs

  # Set sound card power savings
  echo 10 > /sys/module/snd_hda_intel/parameters/power_save

  # Set SATA to minimum power
  echo min_power > /sys/class/scsi_host/host0/link_power_management_policy
  echo min_power > /sys/class/scsi_host/host1/link_power_management_policy

  # Make sure ondemand governor is set
  echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 
  # Remove the webcam driver
#  modprobe -r uvcvideo

  #Disable eth0
  sudo ifconfig eth0 down

  # Stop unneccessary  services
#  sudo /etc/init.d/cron stop
  sudo /etc/init.d/bluetooth stop
  sudo /etc/init.d/preload stop

  #poweroff bluetooth
  sudo /usr/sbin/hciconfig hci0 down

  #dim screen and keyboard brightness to minimum
  sudo nvclock -S 15
  sudo echo 0 | sudo tee -a /sys/class/leds/smc::kbd_backlight/brightness

  #downclock nvidia card (requires coolbits=1)
  sudo nvidia-settings -a GPU2DClockFreqs=25,0
  sudo nvidia-settings -a GPU3DClockFreqs=125,0


Most of the content of this script comes from this


and has been tweaked to my needs. Based on your personal taste you can also decide to uncomment the lines with the load/load video module and cron.


install the script doing


sudo install 99-savings /etc/pm/sleep.d
sudo install 99-savings /etc/pm/power.d

In the thread I linked above you also find a script called 99-nvidia You may want to install that one too.


Doing so I get a usage of 9.5W, equivalent of about 6 hours. This is with WIFI on, browsing the internet and having the screen brightness very low.


Still not quite like OSX but not too bad either.


Let me know how it works for you.



original thread



Taxonomy upgrade extras: 
© 2002-2012 Jeroen Diederen. Drupal theme by Kiwi Themes.