суббота, 5 декабря 2009 г.

Ubuntu 9.10 и выше. ThinkPad x200s/x220. Power Saving.

(Продолжение. Начало статьи)


От laptop-mode, который я использовал для 9.04 я отказался, поскольку муторно и непрозрачно. Проще для осмысления pm-utils.

  1. Устраним баг, не дающий включить режим сохранения энергии для Wi-Fi
  2. Установим apmd, pm-utils и expect $ sudo apt-get install apmd pm-utils expect hdparm libnotify-bin Мне expect нужен для управления роутером NBG460N EE из командной строки.

  3. Cоздадим скрипт /usr/lib/pm-utils/power.d/99-savings.sh
    $ sudo gedit /usr/lib/pm-utils/power.d/99-savings.sh
    Копируем листинг к окно редактора и сохраняем.
    ######################################################################################
    # A script to agressively toggle power management between high 
    # performance and very low power usage.
    # For more information on each of these options, see http://www.lesswatts.org
    ################# Ghanges history ###################################################
    #VERSION=0.12   # 31.08.2010 Testing Ubuntu 10.04. Small changes for Wi-Fi control
    #VERSION=0.13   # 21.09.2010 Adding services control: 
                    #   evolution-alarm-notify, 
                    #   postfix, 
                    #   rsyslog
    #VERSION=0.2    # 23.07.2011 Modified for Ubintu 11.04 for Thinkpad x220 4290rw1
    VERSION=0.23    # 27.07.2011 Added store value (Brithness, user, etc ) to /tmp/powersave.ini
                    #   Fix notify-send message
                    #   Added CPU core disabling. Disable cores not affected for power saving
                    #     
    
    #
    # To install:
    #
    # sudo apt-get install apmd pm-utils expect hdparm libnotify-bin
    #
    # Save this file to /usr/lib/pm-utils/power.d/99-savings.sh
    # cd /usr/lib/pm-utils/power.d
    # sudo install 99-savings.sh /etc/pm/sleep.d
    # sudo install 99-savings.sh /etc/pm/power.d
    #
    
    INI=/tmp/powersave.ini
    
    aUsb()
    {
      #################################################
      ## USB Subsystem
      ##
      # 0.7-0.8 W
      case "$1" in
        false)  #ac_power
          for i in /sys/bus/usb/devices/*/power/control
          do
            echo "on" > $i
          done
          ;;
    
        true)  #batt_power
          for i in /sys/bus/usb/devices/*/power/control
          do
            echo "auto" > $i
          done
    
          for i in /sys/bus/usb/devices/*/power/autosuspend
          do
            echo 1 > $i
          done
    
          echo 1 > /sys/module/usbcore/parameters/autosuspend
          ;;
      esac
    }
    
    aSata()
    {
    
      case "$1" in
        false)  #ac_power
          # Set the SATA to max performance
          for i in /sys/class/scsi_host/host*/link_power_management_policy
          do
            echo max_performance > $i
          done
          ;;
    
        true)  #batt_power
          # Set SATA to minimum power
          # 0.7 W
          for i in /sys/class/scsi_host/host*/link_power_management_policy
          do
            echo min_power > $i
          done
          ;;
      esac
    }
    
    aPci()
    {
      case "$1" in
        false)  #ac_power
          for i in /sys/bus/pci/devices/*/power/control
          do
            echo on > $i
          done
          ;;
    
        true)  #batt_power
          for i in /sys/bus/pci/devices/*/power/control
          do
            echo auto > $i
          done
          ;;
      esac
    }
    
    aI2c()
    {
      case "$1" in
        false)  #ac_power
          for i in /sys/bus/i2c/devices/i2c-*/power/control
          do
            echo on > $i
          done
          ;;
    
        true)  #batt_power
          for i in /sys/bus/i2c/devices/i2c-*/power/control
          do
            echo auto > $i
          done
          ;;
      esac
    }
    
    aHdd()
    {
      case "$1" in
        false)  #ac_power
          # Set the drive to mostly stay awake.  Some may want to change -B 200
          # to -B 255 to avoid accumulating Load_Cycle_Counts
          # -S 240 => put in standby after 20 minutes idle
          # -B 200 => do not permit spindown
          # -M => not supported by my drive
          hdparm -B 200 -S 240 -M 254 /dev/sda
    
          # Remount ext3/4 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,atime /
          ;;
    
        true)  #batt_power
          hdparm -B 1 -S 4 -M 128 /dev/sda
          mount -o remount,noatime,commit=600 /
    
          ;;
      esac
    }
    
    aSsd()
    {
    
    # add these commands in the /etc/rc.local
    #  echo deadline > /sys/block/sda/queue/scheduler
    #  echo 1 > /sys/block/sda/queue/iosched/fifo_batch
    #  sysctl -w vm.swappiness=1            # Strongly discourage swapping
    #  sysctl -w vm.vfs_cache_pressure=50   # Don't shrink the inode cache aggressively
      case "$1" in
        false)  #ac_power
          ;;
    
        true)  #batt_power
          ;;
      esac
    }
    
    aI915()
    {
      case "$1" in
        false)  #ac_power
          echo 0 > /sys/module/i915/parameters/powersave
          ;;
    
        true)  #batt_power
          echo 1 > /sys/module/i915/parameters/powersave
          ;;
      esac
    }
    
    aWlan()
    {
          # WiFi power savings.
      case "$1" in
        false)  #ac_power
          /sbin/iwconfig wlan0 power off txpower 14
          ;;
    
        true)  #batt_power
          /sbin/iwconfig wlan0 power on txpower 4
          ;;
      esac
    }
    
    aLan()
    {
      case "$1" in
        false)  #ac_power
          # set the ethernet max speed.
          ethtool -s eth0 wol d
          ethtool -s eth0 autoneg off speed 1000
          ;;
    
        true)  #batt_power
          # set the ethernet power savings.
          # ~ 0.4 W
          ethtool -s eth0 wol d
          ethtool -s eth0 autoneg off speed 100
          ;;
      esac
    }
    
    aCpu()
    {
      #################################################
      ## CPU
      ##
    
      case "$1" in
        false)  #ac_power
          for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
          do
            echo performance > $i
          done
    
          # Enable All Core CPU
          for i in /sys/devices/system/cpu/cpu*/online
          do
            echo 1 > $i
          done
    
          # Shedule Multitreading
          echo 0 > /sys/devices/system/cpu/sched_mc_power_savings
          ;;
    
        true)  #batt_power
          for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
          do
            echo powersave > $i
          done
    
    #      Disable cores not affected for power saving
    #      for i in /sys/devices/system/cpu/cpu*/online
    #      do
    #        echo 0 > $i
    #      done
    
          echo 1 > /sys/devices/system/cpu/sched_mc_power_savings
          ;;
      esac
    }
    
    aSnd()
    {
      case "$1" in
        false)  #ac_power
          echo 0 > /sys/module/snd_hda_intel/parameters/power_save
          ;;
    
        true)  #batt_power
          # Turn off sound card power savings
          # < 0.1 W
          echo 10 > /sys/module/snd_hda_intel/parameters/power_save
          ;;
      esac
    }
    
    aBt()
    {
      case "$1" in
        false)  #ac_power
          # Enable the bluetooth driver
          rfkill unblock bluetooth
          ;;
    
        true)  #batt_power
          # Remove the bluetooth driver
          # 0.3-0.4 W
          rfkill block bluetooth
          ;;
      esac
    }
    
    aDaemons()
    {
      #################################################
      ## demons, services
      ##
    
      case "$1" in
        false)  #ac_power
          # 1. Evolution alarm and integrations
          /usr/lib/evolution/2.32/evolution-alarm-notify &
          #/usr/lib/evolution/e-calendar-factory &
          #/usr/lib/evolution/e-addressbook-factory &
    
          # 2. Starting Sendmail server 
          #postfix start 
    
          # 3. Starting CouchDB & desktopcouch
          dbus-send --session --dest=org.desktopcouch.CouchDB --print-reply --type=method_call / org.desktopcouch.CouchDB.getPort
          ;;
    
        true)  #batt_power
          # 1. Evolution alarm
          killall evolution-alarm-notify
          #killall e-calendar-factory
          #killall e-addressbook-factory
    
          # 2. Stopping Sendmail server 
          #postfix stop
    
          # 3. Stoping CouchDB & desktopcouch
          killall beam.smp
          killall desktopcouch-service
          ;;
      esac
    }
    
    # < 0.1 W
    aWebcam()
    {
      case "$1" in
        false)  #ac_power
          # Enable the webcam driver
          modprobe uvcvideo
          ;;
    
        true)  #batt_power
          # Remove the webcam driver
          modprobe -r uvcvideo
          ;;
      esac
    }
    
    aMemory()
    {
      case "$1" in
        false)  #ac_power
          # 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
          ;;
    
        true)  #batt_power
          # 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
          ;;
      esac
    }
    
    aBrightness()
    {
      case "$1" in
        false)  #ac_power
          # Setup maximum brigthness
          # Thinkpad x220, Ubuntu 11.04
          vBAT_BRI=$(cat /sys/devices/virtual/backlight/acpi_video0/brightness)
          echo $vAC_BRI > /sys/devices/virtual/backlight/acpi_video0/brightness
          ;;
    
        true)  #batt_power
          # Setup brigthness 30%
          vAC_BRI=$(cat /sys/devices/virtual/backlight/acpi_video0/brightness)
          echo $vBAT_BRI > /sys/devices/virtual/backlight/acpi_video0/brightness
          ;;
      esac
    
    }
    
    aMisk()
    {
      case "$1" in
        false)  #ac_power
          # Turn off the laptop mode disk optimization
          echo 0 > /proc/sys/vm/laptop_mode
          echo tsc > /sys/devices/system/clocksource/clocksource0/current_clocksource
    
          # enable logging
          service rsyslog start
    
          # ZiXEL nbg460n. Set maximum wifi speed
          if [ -f /etc/pm/802.11.bgn ]; then /etc/pm/802.11.bgn 1; fi
    
          # enable winbindd
          if [ -f /etc/init.d/winbind ]; then  /etc/init.d/winbind start; fi
    
          # Powersave pci express
          echo performance > /sys/module/pcie_aspm/parameters/policy
          ;;
    
        true)  #batt_power
          # Set laptop disk write mode
          echo 5 > /proc/sys/vm/laptop_mode
          echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource
          # disable logging
          service rsyslog stop
    
          # ZiXEL nbg460n. Set standard wifi speed
          if [ -f /etc/pm/802.11.bgn ]; then /etc/pm/802.11.bgn 0; fi
    
          # disable winbind
          if [ -f /etc/init.d/winbind ]; then  /etc/init.d/winbind stop ; fi
    
          echo powersave > /sys/module/pcie_aspm/parameters/policy
          ;;
      esac
    }
    
    aNotify()
    {
      case "$1" in
        false) #ac_power
          MSGH="AC" 
          MSGT="Maximum Performance Mode"
          MSGI="ac-adapter"
          ;;
        true)  #battery_power 
          MSGH="BATT" 
          MSGT="Battery Power Saving"
          MSGI="battery"
        ;;
      esac
    
      vUSER=`ps -C gnome-session -o user=` #find UID user who start gnome-session
      vPIDS=`pgrep -u $vUSER gnome-session` #find PID
      for PID in $vPIDS; do
        vDBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ \
        | sed -e 's/DBUS_SESSION_BUS_ADDRESS=//')
        DBUS_SESSION_BUS_ADDRESS=$vDBUS_SESSION_BUS_ADDRESS DISPLAY=:0.0 sudo -u $vUSER notify-send "$MSGH" "$MSGT" -i "$MSGI"
      done
    }
    
    aLoadini()
    {
      if [ -e $INI ]; 
        then 
          echo "Restore Value"
          while read LINE
          do
            PARM=$(echo "$LINE" | awk '{print $1}')
            KEY=$(echo "$LINE" | awk '{print $2}')
            case $PARM in
              "AC_BRI")
                vAC_BRI=$KEY
                ;;
              "BAT_BRI")
                vBAT_BRI=$KEY
                ;;
              "USER")
                vUSER=$KEY
                ;;
              "PIDS")
                vPIDS=$KEY
                ;;
              "DBUS_SESSION_BUS_ADDRESS")
                vDBUS_SESSION_BUS_ADDRESS=$KEY
                ;;
            esac
            echo "$PARM $KEY"
          done < $INI
        else
          echo "Reset Value"
          vAC_BRI=15
          vBAT_BRI=8
          vUSER=""
          vPIDS=""
          vDBUS_SESSION_BUS_ADDRESS=""
      fi
    }
    
    aSaveini()
    {
      echo "AC_BRI $vAC_BRI" > $INI
      echo "BAT_BRI $vBAT_BRI" >> $INI
      echo "USER $vUSER" >> $INI
      echo "PIDS $vPIDS" >> $INI
      echo "DBUS_SESSION_BUS_ADDRESS $vDBUS_SESSION_BUS_ADDRESS" >> $INI
    }
    
    
    ##########################################################
    ## Apply settings
    ##
    aLoadini
    
    aCpu $1
    aUsb $1
    aI2c $1
    aSata $1
    aPci $1
    if [ $(hdparm -i /dev/sda | grep Model | awk '{print substr($2,1,3)}') = "SSD" ]; 
      then 
        aSsd $1
      else
        aHdd $1
    fi
    aI915 $1
    aWlan $1
    aLan $1
    aSnd $1
    aBt $1
    aWebcam $1
    aMemory $1
    aDaemons $1
    aBrightness $1
    aMisk $1
    aNotify $1
    
    aSaveini
    

  4. Для управления роутером NBG460N EE из командной строки создадим скрипт: sudo gedit /etc/pm/802.11.bgn Копируем листинг к окно редактора и сохраняем.
    #!/usr/bin/expect
    
    ############################################
    # Set 802.11 /b/g mode for ZiXEL nbg460n ee
    # Need to install expect
    
    spawn "telnet" "192.168.1.1"
    
    expect "Password:"
    send "myPassword\r"
    expect "NBG460NEE>"
    send "wlan radio [lindex $argv 0]\r"
    expect "NBG460NEE>"
    send "exit\r"
    interact
    
    Справедливости ради скажу, что этот скрипт не является надежным.
    Если возникают проблемы с соединением при переходе в режим сохранения энергии лучше от него отказаться и не включать режим 802.11n.

  5. Установка:
    $ cd /usr/lib/pm-utils/power.d $ sudo chmod 755 99-savings.sh $ sudo install 99-savings.sh /etc/pm/sleep.d $ sudo install 99-savings.sh /etc/pm/power.d
  6. Проверка:
    Запускаем powertop
    $ sudo powertop
    и проверяем, что при питании от батареи он не дает никаких рекомендаций.


Полезные ссылки:
Update:
31/08/2010. Проверил работу на версии 10.04. Поправил команды управления Wi-Fi адаптером.
12/12/2010. С роутером ZiXEL NBG460N EE в режиме, когда на роутере включен протокол 802.11 n/b/g и сохранение энергии на карточке ноута, происходило нарушение работы выражающееся в задержках ping до 6 секунд.
Для восстановления работоспособности роутер переводится в режим 802.11 n/b скриптом 802.11.bgn (требуется expect).
23/07/2011. Переработал структуру скрипта. Обеспечил работу для Ubuntu 11.04 на Thinkpad x220 4290RW1.
10/12/2011. Протестировал на Ubuntu 11.10.

4 комментария:

  1. Как проверить, что этот скрипт работает ? отключаю питание, но ничего не происходит. Я смотрю на /proc/sys/vm/laptop_mode, она не меняется

    ОтветитьУдалить
  2. Я там написал про баг. Меня это тоже очень раздражает.
    Не каждый раз автоматически переходит в powersave.

    Вы правильно смотрите:
    cat /proc/sys/vm/laptop_mode
    с подключенным шнурком питания и отключенным.

    Запустите вручную поочереди следующие команды:
    sudo /usr/lib/pm-utils/power.d/99-savings.sh true
    и
    sudo /usr/lib/pm-utils/power.d/99-savings.sh false
    чтобы проверить, что скрипт правильно отрабатывается.

    ОтветитьУдалить
  3. привет. у меня х230 с док-станцией. заметил, что с данным скриптом ноут намертво виснет при снятии с док-станции. не в курсе, с чем это может быть связано?

    ОтветитьУдалить
    Ответы
    1. Владислав, даже предположить пока не могу.
      У меня нету дока.
      При снятии с дока ноут переходит на питание от батарей и одновременно отключаются внешний дисплей, Usb, и т.д.

      Если есть навыки программирования предлагаю в скрипт вставить отладочную информацию:
      --------------------------------------------
      aCpu $1
      echo "aCpu $1" > $HOME/powersaving.txt
      aUsb $1
      echo "aUsb $1" >> $HOME/powersaving.txt
      aI2c $1
      echo "aI2c $1" >> $HOME/powersaving.txt
      aSata $1
      echo "aSata $1" >> $HOME/powersaving.txt
      aPci $1
      echo "aPci $1" >> $HOME/powersaving.txt
      if [ $(hdparm -i /dev/sda | grep Model | awk '{print substr($2,1,3)}') = "SSD" ];
      then
      aSsd $1
      echo "aSsd $1" >> $HOME/powersaving.txt
      else
      aHdd $1
      echo "aHdd $1" >> $HOME/powersaving.txt
      fi
      aI915 $1
      echo "aI915 $1" >> $HOME/powersaving.txt
      aWlan $1
      echo "aWlan $1" >> $HOME/powersaving.txt
      aLan $1
      echo "aLan $1" >> $HOME/powersaving.txt
      aSnd $1
      echo "aSnd $1" >> $HOME/powersaving.txt
      aBt $1
      echo "aBt $1" >> $HOME/powersaving.txt
      aWebcam $1
      echo "aWebcam $1" >> $HOME/powersaving.txt
      aMemory $1
      echo "aMemory $1" >> $HOME/powersaving.txt
      aDaemons $1
      echo "aDaemons $1" >> $HOME/powersaving.txt
      aBrightness $1
      echo "aBrightness $1" >> $HOME/powersaving.txt
      aMisk $1
      echo "aMisk $1" >> $HOME/powersaving.txt
      aNotify $1
      echo "aNotify $1" >> $HOME/powersaving.txt
      --------------------------------------------
      в домашнем каталоге будет создан файл powersaving.txt

      Если это сложно, то подождите пару дней, я сам вставлю и сделаю установочный пакет.

      Удалить