broadcom Ethernet BCM57412 驅動更新記錄(dkms方式)

2023-03-31 06:01:07

一 背景

現場Dell R740xd2機器使用網路卡Broadcom 57412 10Gb SFP+,韌體版本22.21.06.80。bnxt_en.ko核心模組是該網路卡的驅動,我們預設的驅動版本為1.8.0,而韌體版本22.21.06.80需要1.10.2的driver。

本文主要是記錄一些操作步驟,後續出現類似驅動過舊的問題可以快速解決。

二 臨時解決

  1. 現場通過下載Broadcom官方提供的tar包在生產節點上直接make編譯出新的bnxt_en.ko
  2. 替換/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_en.ko
  3. 通過modprobe -r bnxt_enmodprobe bnxt_en重新載入新的模組,可以通過modinfo bnxt_en檢視module的資訊
  4. 使用depmod -a更新module載入的依賴
  5. bnxt_en.ko是網路驅動,在核心init on initramfs 階段就需要載入,因此還要執行update-initramfs -u來更新initramfs image。

三 長久解決

3.1 backport核心程式碼(失敗)

  1. 1.10.2的驅動在linux核心6.1中才有支援,而我們的核心版本是4.14,嘗試直接cherry-pick,衝突過多失敗。
  2. 下載並解壓紅帽4.10核心的iso,替換broadcom/bnxt_en目錄下相關檔案進行編譯。這裡記錄下編譯方式,整體編譯核心速度過慢,我們可以在編譯環境編譯某一個modules:
    1. 複製/usr/src/$(uname -r)/Module.symvers到編譯的核心目錄drivers/net/ethernet/broadcom/bnxt/下面
    2. 執行make modules SUBDIRS=drivers/net/ethernet/broadcom/bnxt就可以編譯啦

結果同樣差距太多,很多改動涉及到公共檔案的介面,故放棄。

3.2 dkms(成功)

既然使用原始碼包可以直接在4.14核心環境上進行編譯,那使用dkms(Dynamic Kernel Module Support)來在需要的時候編譯安裝是一個不錯的選擇,而且bnxt_en體量小,編譯很快,安裝系統時不會佔用太多時間。

製作dkms的deb包

解壓netxtreme-bnxt_en-1.10.2-224.0.157.0.tar原始碼包,目錄結構如下:

drwxrwxr-x  4 18896 dialout 4096 Mar 29 11:59 ./
drwxr-xr-x 18 root  root    4096 Mar 27 18:03 ../
lrwxrwxrwx  1 18896 dialout   27 Nov  3 04:25 bnxt_en -> bnxt_en-1.10.2-224.0.157.0//
drwxrwxr-x  5 18896 dialout 4096 Mar 30 10:01 bnxt_en-1.10.2-224.0.157.0/
lrwxrwxrwx  1 18896 dialout   20 Nov  3 04:25 bnxt_re -> bnxt_re-224.0.157.0//
drwxrwxr-x  2 18896 dialout 4096 Mar 27 19:08 bnxt_re-224.0.157.0/
-rw-r--r--  1 root  root     309 Mar 27 19:12 dkms.conf
-rw-rw-r--  1 18896 dialout  537 Mar 27 17:18 Makefile

其中dkms.conf是我們建立並加入的,內容如下:

PACKAGE_NAME="netxtreme-bnxt_en"
PACKAGE_VERSION="1.10.2"
CLEAN="make clean"
MAKE="make"
BUILT_MODULE_NAME[0]="bnxt_en"
BUILT_MODULE_NAME[1]="bnxt_re"
BUILT_MODULE_LOCATION[0]="bnxt_en"
BUILT_MODULE_LOCATION[1]="bnxt_re"
DEST_MODULE_LOCATION[0]="/updates"
DEST_MODULE_LOCATION[1]="/updates"
AUTOINSTALL="yes"

根據dkms的要求,我們需要將原始碼包移到/usr/src目錄下,即當前原始碼包路徑/usr/src/netxtreme-bnxt_en-1.10.2

  • PACKAGE_NAME:指定要編譯和安裝的模組的名稱
  • PACKAGE_VERSION:模組版本
  • CLEAN:刪除先前編譯生成的核心模組檔案和相關構建檔案
  • MAKE:根據Makefile編譯
  • BUILT_MODULE_NAME:模組名,也就是編譯出來的bnxt_en.ko
  • BUILT_MODULE_LOCATION:存放的位置,這裡是/usr/src/netxtreme-bnxt_en-1.10.2/bnxt_en/
  • DEST_MODULE_LOCATION:將模組放到核心目錄的哪個資料夾下,這裡是/lib/modules/$(uname -r)/updates
  • AUTOINSTALL:安裝完畢後自動載入該模組

接下來就可以驗證dkms是否可以使用了,以下指令:

# 可以檢視當前的dkms模組的情況
dkms status

# 新增到dkms樹,此時是added狀態
dkms add -m netxtreme-bnxt_en -v 1.10.2
# 編譯,成功是built狀態
dkms build -m netxtreme-bnxt_en -v 1.10.2
# 安裝,成功是installed狀態
dkms install -m netxtreme-bnxt_en -v 1.10.2

# 其他指令
# 移除
dkms remove netxtreme-bnxt_en/1.10.2 --all
# 打包deb
dkms mkdeb netxtreme-bnxt_en/1.10.2
# 檢視module資訊
modinfo bnxt_en
# 重新生成module載入依賴關係
depmod -a
# 載入module
modprobe bnxt_en
# 移除module
modprobe -r bnxt_en

根據dkms status確定dkms安裝沒有問題,再通過modinfo確認module的資訊沒問題後,我們就可以將dkms模組打包成deb(ubuntu)了,指令dkms mkdeb netxtreme-bnxt_en/1.10.2,我們可以得到一個名為netxtreme-bnxt-en-dkms_1.10.2_all.deb的deb,這樣就可以在安裝系統或升級階段進行安裝了。

其他問題

如果製作好的deb存在問題,需要在安裝前後做一些清理或載入的工作後才能工作。這個時候可以將netxtreme-bnxt-en-dkms_1.10.2_all.deb解開,具體操作如下:

# 建立工作目錄
mkdir -p extract/DEBIAN && mkdir build

# 提取deb控制檔案
dpkg -e netxtreme-bnxt-en-dkms_1.10.2_all.deb extract/DEBIAN

# 提取原始檔
dpkg -x netxtreme-bnxt-en-dkms_1.10.2_all.deb extract/

提取後extract目錄結構如下:

.
├── DEBIAN
│   ├── control
│   ├── md5sums
│   ├── postinst
│   └── prerm
└── usr
    ├── share
    │   └── netxtreme-bnxt_en-dkms
    │       ├── netxtreme-bnxt_en-1.10.2.dkms.tar.gz
    │       └── postinst
    └── src

我們通過DEBIAN內的檔案對deb安裝前或安裝後進行設定,常用的有preinst、postinst、prerm 和 postrm

  • preinst 指令碼在軟體包被安裝之前執行,通常用來檢查一些先決條件或設定
  • postinst 指令碼在軟體包安裝完成後執行,通常進行設定更新載入等操作
  • prerm和postrm指令碼通常對軟體包解除安裝前後做停止服務,清除資訊等操作

製作好控制檔案後使用指令dpkg-deb -b extract/ build在build目錄下重新生成netxtreme-bnxt-en-dkms_1.10.2_all.deb軟體包。