Wi-Fi на BCM 4312/4313 в Mint/Ubuntu
Всем счастливым обладателям карточек Broadcom посвящается.
Есть у меня 2 ноута и заставила меня жизнь настроить на них wifi соединение. На первом ноуте стоял Mint на втором Ubuntu. К слову сказать это не первая моя попытка настроить беспроводное соединение под Ubuntu.
Итак по шагам:
1. Идем на сайт компании Broadcom и качаем ихние дровишки себе. Дровишки естественно написаны на языке С и естественно требуют сборки. Скачать дровишки можно тут: http://www.broadcom.com/support/802.11.
2. Все делаем под рутом. Пытаемся собрать дрова и получаем ошибку в каком-то там сишном файле. Это лечится, таблетка тут http://www.mindwerks.net/2011/11/wireless-bcm4312-3-2-kernel/ Т.е. скачанные исходники драйвера от Broadcom перед использование придется пропатчить.
3. В Ридми предлагается выбор - для какого Wireless API собирать драйвер, итого:
make - предоставляем mak'у выбрать самому
make API=WEXT - поддержка старого WEXT модуля
make API=CFG80211 - поддержка нового Wireless API (его то я и выбрал)
драйвер собран, идем дальше.
4. Тут дорожки Mint и Ubuntu у меня разошлись. На этом этапе необходимо загрузить собранный драйвер в ядро.
Для Mint:
копируем собранный драйвер wl.ko например в /lib/modules/`uname -r`/kernel/lib/
для загрузки драйвера при старте системы в /etc/rc.local дописываем перед строкой exit 0
modprobe -r bcma modprobe -r b43 modprobe -r ssb modprobe wl
Для Ubuntu:
для загрузки драйвера при старте системы в /etc/rc.local дописываем перед строкой exit 0
modprobe -r bcma modprobe -r b43 modprobe -r ssb modprobe -r wl modprobe lib80211 modprobe cfg80211 insmod /home/user/hybrid_wl/wl.ko
Система управления модулями ядра в Линухе довольно мутная. В Mint мне не удалось отключить ssb через blacklist.conf поэтому в Ubuntu я решил отключать их принудительно. Единственный минус такой конфигурации - можно случайно удалить wl.ko
После перезагрузки драйвер будет загружен.
5. В Ubuntu мне пришлось поставить wicd для настройки соединения (essid, key), но можно настроить и в ручную как написано тут: настройка wifi вручную
В Mint я настроил соединение в симпатичном Network менеджере, т.е. ручная настройка не понадобилась.
6. Это дополнение написано ровно через месяц после успешной настройки wi-fi на Убунте. Так сложилось, что за месяц я так и не пересел на Mint и честно говоря с момента настройки wi-fi её и не включал. А вот убунтой я пользуюсь ежедневно и одним прекрасным утром Убунта загрузилась, а wi-fi нет...
Худшие опасения, что карточка Broadcom накрылась медным тазом - не оправдались. Под windows на той же машине она прекрасно работала.
Симптомы:
ifconfig - сетевой беспроводной интерфейс отсутствует.
lsmod | grep wl - выдает пустой результат, т.е. модуль с драйвером не запущен.
Ну что ж попробуем запустить драйвер вручную:
sudo insmod <путь к модулю>/wl.ko
выдает загадочную ошибку: "insmod: error inserting '<путь к модулю>/wl.ko': -1 Invalid parameters"
Т.к. в настройках я ничего не менял и обновлений не устанавливал, то появилось предположение об автоматическом обновлении и опыт подсказывал что обновилось скорее всего ядро. И новое ядро не хочет работать со старым драйвером.
Проблема была решена повторной компиляцией модуля wl.ko под новой ядро. После компиляции модуль успешно подключился к новому ядру. А вот автоматические обновления были отключены...
7. Как обычно бывает в таких случаях, happy end оказался временным. Полгода я выборочно ставил обновления, но ядро не обновлял. Честно говоря не было идей как это сделать (ну что поделать никогда не сталкивался с этим вопросом), да и времени тоже. Однако, я все таки нашел время для этого вопроса, т.к. очень хотелось обновиться, а перекомпилировать драйвер совсем не хотелось.
Все что будет написано ниже проверялось под Ubuntu 12.04.2 LTS, думаю на Mint все делается аналогично.
Итак, я обнаружил DKMS (Dynamic Kernel Module Support). Суть этой системы: при загрузке ubuntu c новым ядром, все сконфигурированные в этой системе драйвера автоматически перекомпилируются и устанавливаются в новое ядро. В общем, то что нужно.
Как обычно с наскока сделать не получилось - пришлось читать man и усиленно думать тыквой.
Как сделать сборку и установить драйвер из исходников в автоматическом режиме (при загрузке нового ядра):
0). Возможно dkms не установлен. Если так, то делаем:
sudo apt-get install dkms
1). Качаем драйвер (исходники). Что откуда взять я писал в самом начале статьи.
2). Помещаем папку с исходниками в /usr/src/
3). man dkms подсказывает, что имя папки с драйвером должно иметь формат <name>-<version>. Я свой драйвер назвал hybrid_wl-1.0 (произвольное имя и версия от балды). Т.о. у меня исходники драйвера теперь лежат в /usr/src/hybrid_wl-1.0.
4). Теперь необходимо подсказать системе как собрать исходники и куда положить собранный бинарник.
Для этого создаем файл /usr/src/hybrid_wl-1.0/dkms.conf с таким текстом:
MAKE[0]="make" BUILT_MODULE_NAME[0]=wl DEST_MODULE_LOCATION[0]="/kernel/lib/" PACKAGE_NAME="hybrid_wl" PACKAGE_VERSION="1.0" CLEAN="make clean" AUTOINSTALL="yes"
Индекс позволяет одновременно собрать несколько драйверов из одной папки. Начинается индекс с нуля.
MAKE - команда сборки проекта. Пробовал "make API='CFG80211'" - dkms отказался собирать драйвер, уже было расстроился, но узнал что и без параметра API все собирается правильно и решил не заморачиваться с исправлением ошибки.
BUILT_MODULE_NAME - имя вашего бинарника после сборки. К слову сказать сборка проводится не в /usr/src/hybrid_wl-1.0/. dkms делает линк на исходники в своей папке и сборку проводит там: /var/lib/dkms/<module>/<module-version>/build/ , т.е. в моем случае это было /var/lib/dkms/hybrid_wl/1.0/build/
DEST_MODULE_LOCATION - куда положим собранный бинарник драйвера.
PACKAGE_NAME и PACKAGE_VERSION - название и версия драйвера, используется для формирования пути в /var/lib/dkms/<module>/<module-version>/
CLEAN - очистка сборки, выполняется перед каждой сборкой драйвера
AUTOINSTALL - может принимать 2 значения "yes" и "no". Указывает должен ли собираться драйвер при установке ядра.
5). Сборка и установка драйвера :
Добавляем драйвер в dkms
sudo dkms add hybrid_wl/1.0
Собираем драйвер
sudo dkms build hybrid_wl/1.0
Устанавливаем драйвер в текущее ядро:
sudo dkms install hybrid_wl/1.0
При загрузке нового ядра, dkms попробует собрать и установить в него драйвер
Очень много полезной информации выдает man dkms, в том числе по формату и параметрам dkms.conf
Вот несколько полезных ссылок:
http://www.opennet.ru/tips/info/1826.shtml
http://deepwalker.blogspot.ru/2008/11/810-dkms-nvidia-btrfs.html
Теперь я могу снова включить автоматическое обновление ядра!
8. А история все не кончается и не кончается. Однажды после обновления ядра я забыл вставить в ноутбук сетевой адаптер - батарея разрядилась и ноут отключился. Отключился без нормального завершения работы Ubuntu (хотя dkms успел пересобрать драйвер).
И вот тут начинается нечто непонятное. После включения машины, вайфай не поднялся, т.к. оказалось что dkms собрал драйвер для нового ядра, но при сборке использовал старое. В результате драйвер не мог загрузиться. Как обычно помогла перекомпиляция и замена драйвера в новом ядре.
9. Прошло практически 15 месяцев, я по-прежнему на Ubuntu 12.04 LTS. Все это время в целом без проблем обновлялись ядра серии 3.2.x Пока в один прекрасный день мне не пришла идея попробовать docker Как говорится, сказано сделано, но docker для своей работы требует ядро linux 3.8 т.к. именно в нем была добавлена поддержка технологии lxc. И вот легким движением руки я обновил ядро до 3.8 и... интернет погас, вернее перестал работать wifi. Симптомы все теже
ifconfig - сетевой беспроводной интерфейс отсутствует.
lsmod | grep wl - выдает пустой результат, т.е. модуль с драйвером не запущен.
Однако на этот раз, пересборка драйвера не помогла, поэтому был скачана новая версия драйвера, установлена аналогично старому. А в dkms.conf старого драйвера был изменен один параметр
AUTOINSTALL="no"
По идее это не даст старому драйверу мешать работе нового драйвера.
Перезагружаем ноутбук и вуаля, интернет появился!
10. Пришли длинные новогодние праздники 2015 года. И я решил рискнуть и обновиться до последней LTS версии ubuntu 14.04.1 И угадайте что!?!? Правильно, wifi не поднялся... Кажется что у этой истории не будет конца... При этом симптомы несколько иные, команда
lsmod | grep wl
показала, что модуль драйвера загружен. А значит проблема на этот раз не в драйвере. Скорее всего при upgrad'e что-то сломалось в настройках соединения.
Смотрим какие интерфейсы нам выдает
[moon:~] % sudo iwconfig eth0 no wireless extensions. lo no wireless extensions. wlan0 IEEE 802.11abg ESSID:off/any Mode:Managed Access Point: Not-Associated Tx-Power=200 dBm Retry long limit:7 RTS thr:off Fragment thr:off Encryption key:off Power Management:off
Т.е. у нас присутствует беспроводной сетевой интерфейс с именем wlan0. Смотрим настроен ли он в /etc/network/interfaces :
[moon:~] % sudo cat /etc/network/interfaces ... iface eth1 inet dhcp ... auto eth1
Т.е. мы видим что почему-то сменилось имя беспроводного интерфейса на wlan0, а в настройках по-прежнему указан eth1. Меняем eth1 на wlan0 в /etc/network/interfaces
[moon:~] % sudo cat /etc/network/interfaces ... iface wlan0 inet dhcp ... auto wlan0
и пробуем поискать доступные wifi сети:
[moon:~] % sudo iwlist wlan0 scan
Появился список доступных для подключения сетей! WiFi под Ubuntu в очередной раз побежден! Ура, товарищи!
11. Несмотря на то, что я в прошлый раз справился с wifi, осталась одна проблемка. Каждый раз, после установки нового ядра, не собирался драйвер wifi, и приходилось это делать вручную.
Начал разбираться по принципу - чиним все что некорректно работает.
Обнаружилось что sudo dkms status выдает вместо списка установленных модулей строку: "Error! Could not locate dkms.conf file."
Как я устранял эту проблему? Нашел все dkms.conf Некоторые оказались "невалидными" символическими ссылками - удалил такие ссылки. Все заработало.
После очередного обновления ядра - модули успешно скомпилировались! Ура! Ура!