mercoledì 26 dicembre 2012

Il risparmio energetico in linux

Il noto pessimo supporto da parte dei produttori ai driver per linux, comporta spesso un abbassamento della durata della batteria dei portatili.
Gli utenti linux sanno bene che per ottenere le massime performance da questo sistema operativo è necessario personalizzarlo per il particolare hardware su cui viene installato. Di seguito riporterò la configurazione utilizzata sul mio notebook magari potrà tornare utile a chi è in possesso di un notebook con una configurazione hardware simile.

Il mio notebook è un Asus U36SD, la configurazione hardware è la seguente:
[roberto@u36sd ~]$ lspci
00:00.0 Host bridge: Intel Corporation 2nd Generation Core Processor Family DRAM Controller (rev 09)
00:01.0 PCI bridge: Intel Corporation Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (rev 09)
00:02.0 VGA compatible controller: Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller (rev 09)
00:16.0 Communication controller: Intel Corporation 6 Series/C200 Series Chipset Family MEI Controller #1 (rev 04)
00:1a.0 USB controller: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (rev 05)
00:1b.0 Audio device: Intel Corporation 6 Series/C200 Series Chipset Family High Definition Audio Controller (rev 05)
00:1c.0 PCI bridge: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 1 (rev b5)
00:1c.1 PCI bridge: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 2 (rev b5)
00:1c.3 PCI bridge: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 4 (rev b5)
00:1c.5 PCI bridge: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 6 (rev b5)
00:1d.0 USB controller: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (rev 05)
00:1f.0 ISA bridge: Intel Corporation HM65 Express Chipset Family LPC Controller (rev 05)
00:1f.2 SATA controller: Intel Corporation 6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (rev 05)
00:1f.3 SMBus: Intel Corporation 6 Series/C200 Series Chipset Family SMBus Controller (rev 05)
01:00.0 VGA compatible controller: NVIDIA Corporation GF119 [GeForce GT 520M] (rev a1)
03:00.0 Network controller: Intel Corporation Centrino Wireless-N 1030 [Rainbow Peak] (rev 34)
04:00.0 USB controller: Fresco Logic FL1000G USB 3.0 Host Controller (rev 04)
05:00.0 Ethernet controller: Atheros Communications Inc. AR8151 v2.0 Gigabit Ethernet (rev c0)
Il sistema operativo è Arch Linux aggiornato al 26/12/2012.
[roberto@u36sd ~]$ uname -a
Linux u36sd 3.6.10-1-ARCH #1 SMP PREEMPT Tue Dec 11 09:40:17 CET 2012 x86_64 GNU/Linux
Finora per il risparmio energetico ho sempre utilizzato laptop-mode-utils senza preoccuparmi più di tanto della sua configurazione in dettaglio. Cercando in rete mi sono accorto che il precedente pacchetto è caduto in disuso e una delle soluzioni più adottate al momento è pm-utils.
Come specificato nel wiki di Archlinux, pm-utils è un nuovo framework per l'impostazione della sospensione e per la variazione dello stato dell'alimentazione.  
pm-utils è una collezione di script. È facilmente estendibile tramite l'aggiunta di script personalizzati. Nel mio caso ho utilizzato il pacchetto solo per la gestione dell'alimentazione e non per la sospensione.

Come prima cosa ho rimosso laptop-mode-tools e tutti i suoi file di configurazione in /etc. In seguito ho installato pm-utils.
sudo pacman -Rs laptop-mode-tools
sudo pacman -S pm-utils
Quando al notebook viene rimossa l'alimentazione da rete e passa in alimentazione tramite batteria, viene sollevato un evento che è raccolto da pm-powersave che provvederà a capire quale evento si è verificato e ad eseguire i relativi script.
Gli script predefiniti si trovano nel seguente percorso:
/usr/lib/pm-utils/power.d/
Gli script personalizzati dell'utente si aggiungono creando un nuovo file (non importa il nome del file) nel seguente percorso:
/etc/pm/power.d/
Nel mio caso ho creato in /etc/pm/power.d/ un file chiamato powersave, contenente il seguente script:
#!/bin/sh
# A script to enable laptop power saving features for #! & Debian GNU+linux.
# http://crunchbanglinux.org/forums/topic/11954

# List of modules to unload, space seperated. Edit depending on your hardware and preferences.
#modlist="uvcvideo"
# Bus list for runtime pm. Probably shouldn't touch this.
#buslist="pci spi i2c"

case "$1" in
    true)
    # Enable some power saving settings while on battery
       # Enable laptop mode
       # echo 5 > /proc/sys/vm/laptop_mode
       # Less VM disk activity. Suggested by powertop
        echo 1500 > /proc/sys/vm/dirty_writeback_centisecs
       # Intel power saving
        echo Y > /sys/module/snd_hda_intel/parameters/power_save_controller
        echo 1 > /sys/module/snd_hda_intel/parameters/power_save
       # Set backlight brightness to 50%
       # echo 5 > /sys/devices/virtual/backlight/acpi_video0/brightness
       echo 8 > /sys/class/backlight/acpi_video0/device/backlight/acpi_video0/brightness
       # Cpu governor
       cpupower frequency-set -g powersave
       # USB powersaving
        for i in /sys/bus/usb/devices/*/power/autosuspend; do
            echo 1 > $i
        done
       # SATA power saving
        for i in /sys/class/scsi_host/host*/link_power_management_policy; do
            echo min_power > $i
        done
       # Disable hardware modules to save power
        for mod in $modlist; do
            grep $mod /proc/modules >/dev/null || continue
            modprobe -r $mod 2>/dev/null
        done
       # Enable runtime power management. Suggested by powertop.
        for bus in $buslist; do
            for i in /sys/bus/$bus/devices/*/power/control; do
                echo auto > $i
            done
        done
    ;;
    false)
       #Return settings to default on AC power
        #echo 0 > /proc/sys/vm/laptop_mode
        echo 500 > /proc/sys/vm/dirty_writeback_centisecs
        echo N > /sys/module/snd_hda_intel/parameters/power_save_controller
        echo 0 > /sys/module/snd_hda_intel/parameters/power_save
          echo 10 > /sys/class/backlight/acpi_video0/device/backlight/acpi_video0/brightness
          cpupower frequency-set -g ondemand
        for i in /sys/bus/usb/devices/*/power/autosuspend; do
            echo 2 > $i
        done
        for i in /sys/class/scsi_host/host*/link_power_management_policy
            do echo max_performance > $i
        done
        for mod in $modlist; do
            if ! lsmod | grep $mod; then
                modprobe $mod 2>/dev/null
            fi
        done
        for bus in $buslist; do
            for i in /sys/bus/$bus/devices/*/power/control; do
                echo on > $i
            done
        done
    ;;
esac

exit 0
Dopo bisogna modificare i permessi del file con il seguente comando:
chmod 777 /etc/pm/power.d/powersave
È anche possibile eseguire manualmente gli scripts con il seguente comando:
 pm-powersave true
che abilita la gestione del risparmio energetico
pm-powersave false
che disabilita la gestione del risparmio energetico
I log sono salvati in:
 /var/log/pm-powersave.log
 Nel mio caso dal log mi sono accorto che lo script presente in /usr/lib/pm-utils/power.d/pcie_aspm. Ho risolto il problema modificando la configurazione di Grub2 aggiungendo la stringa pcie_aspm=force nella riga del file /etc/default/grub:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash pcie_aspm=force add_efi_memmap i915.i915_enable_rc6=1 i915.i915_enable_fbc=1 drm.vblankoffdelay=1"
Se si possiede una scheda video Intel (nel mio caso ho una doppia scheda video Intel/Nvidia) si può ottenere un ulteriore risparmio energetico aggiungendo anche i915.i915_enable_rc6=1 i915.i915_enable_fbc=1 drm.vblankoffdelay=1

Infine un utile tool per visualizzare i consumi in dettaglio è powertop, sviluppato dalla Intel.