Готовим Linux на Asus U31SD/P31SD и подобных

Дистрибутивы > Ubuntu
После приобретения обновки в виде Asus P31SD и последующей установки на него Linux было очень обидно увидеть всего 6 часов автономной работы вместо желаемых 10-12. На Windows обратно вернуться не удалось (тут даже cywgin не помог), поэтому было решено запастись кофе и занять ближайшие выходные решением этих проблем.

Рассматриваем решение на примере Ubuntu 11.10.

Важная, для нас, часть конфигурации ноутбука:
Процессор: Intel Core i3-2310M (Sandybridge)
Видеоадаптер: Nvidia Geforce 520M (Nvidia Optimus)

Итак, сразу после установки Linux мы видим следующие проблемы:
  1. Сумасшедшая яркость.
  2. Повышенное потребление энергии — наша основная цель.
  3. Не работает режим сна — для облегчения жизни заставим его работать

Яркость


Симптом: подсветкой пытаются одновременно управлять хардварный модуль и программный модуль из DE в результате чего случаются скачки в случайном направлении.

Проблемы с яркостью в ноутбуках очень распространены и разнообразны но практически все решаются одним методом: добавлением в параметры загрузки ядра acpi_backlight=vendor, который сигнализирует, что управлением яркостью занимается железо и програмно лезть туда не стоит.

Открываем /etc/default/grub и вписываем параметр в GRUB_CMDLINE_LINUX, получится:
GRUB_CMDLINE_LINUX="acpi_backlight=vendor"

Сохраняем, обновляем конфигурацию grub (sudo update-grub), перезагружаемся и радуемся адекватному поведению подсветки.

Режим сна


Симптом: при отправке ноутбука в сон устройство яростно сопротивляется и, в конечном итоге, зависает.

После недолгих поисков находим виновников: плохо-засыпающие USB-хабы. И рядом находим решение, хук для pm-utils:
/etc/pm/sleep.d/20_custom-asus-u31sd:
#!/bin/sh

BUSES="0000:00:1a.0 0000:00:1d.0"

case "${1}" in
    hibernate|suspend)
    # Switch USB buses off
    for bus in $BUSES; do
        echo -n $bus | tee /sys/bus/pci/drivers/ehci_hcd/unbind
    done
    ;;
    resume|thaw)
    # Switch USB buses back on
    for bus in $BUSES; do
        echo -n $bus | tee /sys/bus/pci/drivers/ehci_hcd/bind
    done
    ;;
esac

Сохраняем, делаем исполняемым (sudo chmod +x /etc/pm/sleep.d/20_custom-asus-u31sd), проверяем.
Работает? Почти. После выходи из сна яркость дисплея падает до минимума… Поправить оплошность можно в этом же хуке. Достать значение яркости можно где-то из /sys. Большинство драйвером называют параметры банально поэтому просто поищем там backlight:
$ find /sys -name backlight
/sys/devices/platform/asus-nb-wmi/backlight

Нашлось! После изучения внутренностей значение яркости оказалось в /sys/devices/platform/asus-nb-wmi/backlight/asus-nb-wmi/brightness. Допишем в предыдущий хук его сохранение и восстановление:
#!/bin/sh

BUSES="0000:00:1a.0 0000:00:1d.0"

case "${1}" in
    hibernate|suspend)
    # Switch USB buses off
    for bus in $BUSES; do
        echo -n $bus | tee /sys/bus/pci/drivers/ehci_hcd/unbind
    done
    # Saving brightness to /tmp/br
    cat /sys/devices/platform/asus-nb-wmi/backlight/asus-nb-wmi/brightness > /tmp/br
    ;;
    resume|thaw)
    # Switch USB buses back on
    for bus in $BUSES; do
        echo -n $bus | tee /sys/bus/pci/drivers/ehci_hcd/bind
    done
    # Restoring brightness from /tmp/br
    cat /tmp/br > /sys/devices/platform/asus-nb-wmi/backlight/asus-nb-wmi/brightness
    ;;
esac

Снова проверяем и… работает! Теперь приступим к основному противнику, энергопотреблению.

Повышенное потребление энергии


Сбивать аппетиты Linux будем аж в 3 этапа.

1. Дискретная графика


Ноутбук оборудован двумя видеоадаптерами: интегрированной (Intel) и дискретной (Nvidia). Но не простой Nvidia, а работающей по технологии Nvidia Optimus. Той самой Optimus, поддержки которой в обозримом будущем в Linux не предвидится.

Но слава open-sourc'у мир полон энтузиастов. Борьбой (а иногда и дружбой) с Optimus занимается Bumblebee. Они достигли хорошего прогресса:
  • Bumblebee умеет включать/отключать дискретную карту в зависимости от потребностей
  • Bumblebee умеет заставлять приложения использовать дискретную карту

Естественно проект полон костылей, но это все же лучше чем ничего.
Займемся установкой:
$ sudo add-apt-repository ppa:bumblebee/stable
$ sudo apt-get update
$ sudo apt-get install bumblebee

К сожалению практически на каждом ноутбуке разная ACPI-команда включения/отключения видеокарты (большая таблица собрана здесь), поэтому управление питанием в Bumblebee по умолчанию выключено. Из таблицы выше берем команды и записываем их в /etc/bumblebee/cardoff и /etc/bumblebee/cardon соответственно:
/etc/bumblebee/cardoff:
\_SB.PCI0.PEG0.GFX0.DOFF

/etc/bumblebee/cardon:
\_SB.PCI0.PEG0.GFX0.DON

Затем в /etc/bumblebee/bumblebee.conf включаем управление питанием:
ENABLE_POWER_MANAGEMENT=Y

и заставляем сервис завершаться (и соответственно выключать дискретную видеокарту) если его никто не использует:
STOP_SERVICE_ON_EXIT=Y

Сохраняем, перезагружаемся, смотрим на потребление энергии — ощутимо уменьшилось.
Прежде чем пойти дальше починим снова ждущий режим: дело в том, что при переходе в сон активный видеодрайвер (nvidia или nouveau) будем пытаться подготовить карту, но карта то у нас выключена. Решим просто и «в лоб»: в выше использованный хук добавим 2 команды:
  • Будем включать карту перед засыпанием.
  • Будем выключать карту после просыпания.

Хук примет следующий вид:
#!/bin/sh

BUSES="0000:00:1a.0 0000:00:1d.0"

case "${1}" in
    hibernate|suspend)
    # Switch USB buses off
    for bus in $BUSES; do
        echo -n $bus | tee /sys/bus/pci/drivers/ehci_hcd/unbind
    done
    cat /sys/devices/platform/asus-nb-wmi/backlight/asus-nb-wmi/brightness > /tmp/br
    # Switch optimus back on before going to sleep, avoids the "constant on"
    # bug that occurs after 2 suspend/resume cycles (thanks kos888)
    echo `cat /etc/bumblebee/cardon` | tee /proc/acpi/call
    ;;
    resume|thaw)
    # Switch USB buses back on
    for bus in $BUSES; do
        echo -n $bus | tee /sys/bus/pci/drivers/ehci_hcd/bind
    done
    cat /tmp/br > /sys/devices/platform/asus-nb-wmi/backlight/asus-nb-wmi/brightness
    # Switch optimus off before resuming, avoids unneccessary power draw
    echo `cat /etc/bumblebee/cardoff` | tee /proc/acpi/call
    ;;
esac


2. Интегрированная видеокарта


Игравшись с разными версиями ядер я случайно заметил уменьшенное энергопотребление на версиях до 2.6.39 включительно. Бросившись в поиск по этим параметрам я в своей догадке не ошибся.
Проблема была обнаружена: виноват патч принятый в драйвер i915 в 3.0 ядре. Но, к счастью, его можно обойти без последствий.
В уже известный /etc/default/grub дописываем параметр i915.i915_enable_rc6=1. Строка расширится до:
GRUB_CMDLINE_LINUX="acpi_backlight=vendor i915.i915_enable_rc6=1"

Обновляем конфигурацию grub, перезагружаемся и смотрим на показания батареи. Теперь можно жить. А можно уменьшить еще!

3. Дополнительные мелкие твики


Запустив powertop и применив все рекомендованные твики можно выжать еще 0,5-1 Wh, что на данном железе может дополнительно дать до часа автономной работы. Все твики от powertop собраны в следующем скрипте:
#!/bin/bash

echo 1 > /sys/module/snd_hda_intel/parameters/power_save

for i in /sys/class/scsi_host/host?/link_power_management_policy; do
    echo min_power > $i
done

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

for i in /sys/bus/{pci,i2c}/devices/*/power/control; do
    echo auto > $i
done

for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
    echo ondemand > $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 min_power > /sys/class/scsi_host/host2/link_power_management_policy
echo min_power > /sys/class/scsi_host/host3/link_power_management_policy
echo min_power > /sys/class/scsi_host/host4/link_power_management_policy
echo min_power > /sys/class/scsi_host/host5/link_power_management_policy

[ -L /sys/bus/usb/devices/1-5/power/level ] && echo auto > /sys/bus/usb/devices/1-5/power/level
[ -L /sys/bus/usb/devices/1-5/power/level ] && echo auto > /sys/bus/usb/devices/1-5/power/level

echo 1500 >  /proc/sys/vm/dirty_writeback_centisecs


Сохраним его, к примеру, в /etc/acpi/power-u31sd.sh, сделаем исполняемым (sudo chmod +x /etc/acpi/power-u31sd.sh), и повесим обработчик на событие battery. Для этого создадим файл, к примеру, /etc/acpi/events/u31sd-power-save, запишем туда:
event=battery
action=/etc/acpi/power-u31sd.sh

Так же неплохо бы выполнить данный скрипт при загрузке: добавим его в /etc/rc.local перед exit 0:
/etc/acpi/power-u31sd.sh
exit 0

Настройка окончена. Официальный пруф:
image
И результаты диаграммой:

Комментарии
]]> ipv6 ready Kiev LUGLinux4MeНостальгияЛичный сайт skeletora ]]>