
После приобретения обновки в виде Asus P31SD и последующей установки на него Linux было очень обидно увидеть всего 6 часов автономной работы вместо желаемых 10-12. На Windows обратно вернуться не удалось (тут даже cywgin не помог), поэтому было решено запастись кофе и занять ближайшие выходные решением этих проблем.
Рассматриваем решение на примере Ubuntu 11.10.
P.S. В теории гайд подходит для всех ноутбуков с Sandybridge и Nvidia Optimus.
Важная, для нас, часть конфигурации ноутбука:
Процессор: Intel Core i3-2310M (Sandybridge)
Видеоадаптер: Nvidia Geforce 520M (Nvidia Optimus)
Итак, сразу после установки Linux мы видим следующие проблемы:
- Сумасшедшая яркость.
- Повышенное потребление энергии — наша основная цель.
- Не работает режим сна — для облегчения жизни заставим его работать
Яркость
Симптом: подсветкой пытаются одновременно управлять хардварный модуль и программный модуль из 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? Автоматизируем все это дело через pm-utils. У нас получиться 4 отдельных скрипта:
1. Один из главных твиков, по неизвестным причинам не включенный в стандартную поставку. Меняем режим управления частотой процессора:
/etc/pm/power.d/cpu-governor#!/bin/bash cpu_powersave() { for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo $1 > $i && echo Done. || echo Failed. done } case $1 in true) cpu_powersave "ondemand" ;; false) cpu_powersave "performance" ;; *) exit $NA esac exit 0
2. Меняем режим упра��ления питанием USB-устройств:
/etc/pm/power.d/usb-autosuspend#!/usr/bin/env python from os import listdir, path from sys import argv status = argv[1] USB_PATH = '/sys/bus/usb/devices/' def powersave(status): devices = listdir(USB_PATH) devices = filter(lambda x: ':' not in x, devices) for device in devices: b = listdir(path.join(USB_PATH, device)) b = filter(lambda x: ':' in x, b) is_mouse = False for i in b: if open(path.join(USB_PATH, device, i, 'bInterfaceProtocol')).read().strip() == '02': is_mouse = True break if not is_mouse: open(path.join(USB_PATH, device, 'power/control'), 'w').write(status) if status == 'true': powersave('auto') elif status == 'false': powersave('on')
Скрипт умеет определять мыши и гасить их не будет.
3, 4. Меняем режим управления питанием у остальных устройств:
/etc/pm/power.d/scsi_host-link_power_management#!/bin/bash powersave() { for i in /sys/class/scsi_host/host?/link_power_management_policy; do echo $1 > $i && echo Done. || echo Failed. done } case $1 in true) powersave "min_power" ;; false) powersave "max_performance" ;; *) exit $NA esac exit 0
/etc/pm/power.d/pci-power-control#!/bin/bash powersave() { for i in /sys/bus/pci/devices/*/power/control; do echo $1 > $i && echo Done. || echo Failed. done } case $1 in true) powersave "auto" ;; false) powersave "on" ;; *) exit $NA esac exit 0
Делаем данные файлы исполняемыми и применяем одним махом:
sudo pm-powersave true.Настройка окончена. Официальный пруф:

И результаты диаграммой:

