線網(wǎng)卡驅(qū)動(dòng)實(shí)戰(zhàn))
裝過(guò) Linux 的朋友基本都有類(lèi)似遭遇系統(tǒng)裝好了界面也正常結(jié)果右上角偏偏沒(méi)有 WiFi 圖標(biāo)。尤其是一臺(tái)嶄新的筆記本或者剛換的 USB 無(wú)線網(wǎng)卡插上去一點(diǎn)反應(yīng)沒(méi)有那一刻的心情真的有點(diǎn)崩潰。這次要聊的就是 Ubuntu 20.04 下面 Realtek 無(wú)線網(wǎng)卡的驅(qū)動(dòng)安裝問(wèn)題具體型號(hào)是 b852 系列對(duì)應(yīng) Realtek RTL8852BE 等 WiFi 6 網(wǎng)卡。這類(lèi)網(wǎng)卡在 Windows 下很省心驅(qū)動(dòng)自動(dòng)裝好但到了 Linux 下就成了玄學(xué)——因?yàn)楣俜絻?nèi)核自帶的驅(qū)動(dòng)源里沒(méi)有對(duì)應(yīng)模塊或者有模塊但默認(rèn)沒(méi)啟用又或者模塊版本太舊根本不識(shí)別。更要命的是很多朋友遇到驅(qū)動(dòng)問(wèn)題時(shí)本身就在一個(gè)沒(méi)網(wǎng)絡(luò)的環(huán)境里。學(xué)校機(jī)房、公司內(nèi)網(wǎng)、宿舍只有網(wǎng)線口但沒(méi)網(wǎng)線、或者干脆就是一臺(tái)不能聯(lián)網(wǎng)的裸機(jī)。這就是離線安裝最折磨人的地方你想裝網(wǎng)卡驅(qū)動(dòng)但網(wǎng)卡驅(qū)動(dòng)裝不上就沒(méi)有網(wǎng)你沒(méi)網(wǎng)就不能用 apt 自動(dòng)下載依賴包。破解這個(gè)死循環(huán)需要一點(diǎn)思路也需要提前準(zhǔn)備一些救援工具。這篇文章就把整個(gè)過(guò)程中涉及的原理、步驟、坑和經(jīng)驗(yàn)全部攤開(kāi)來(lái)講包括怎么在沒(méi)有網(wǎng)絡(luò)的情況下把編譯工具鏈、內(nèi)核頭文件和驅(qū)動(dòng)源碼全部準(zhǔn)備好以及有哪些備用方案可以在斷網(wǎng)時(shí)救急。先說(shuō)明一下我這里說(shuō)的 b852 是一個(gè)系列的統(tǒng)稱實(shí)際你可能在 lspci 里看到的是 Realtek RTL8852BE 或者 RTL8852AE也可能看到 Device b852 這個(gè)硬件 ID。它們基本都是同一代 WiFi 6 無(wú)線網(wǎng)卡方案驅(qū)動(dòng)處理方式大同小異。這篇文章會(huì)以這個(gè)系列為主線覆蓋從識(shí)別硬件型號(hào)到離線編譯安裝再到開(kāi)機(jī)自動(dòng)加載的完整流程。1. 為什么 Ubuntu 20.04 默認(rèn)搞不定這張網(wǎng)卡1.1 內(nèi)核、固件和驅(qū)動(dòng)模塊的關(guān)系要理解這個(gè)問(wèn)題先得弄清楚 Linux 無(wú)線網(wǎng)卡工作時(shí)的三層關(guān)系硬件芯片、內(nèi)核驅(qū)動(dòng)模塊、固件文件。硬件芯片就是網(wǎng)卡本身它需要內(nèi)核里對(duì)應(yīng)的驅(qū)動(dòng)模塊比如 rtw89_pci.ko來(lái)指揮它工作而這個(gè)模塊在運(yùn)行時(shí)還需要一份固件文件比如 rtw8852be_fw.bin加載到網(wǎng)卡內(nèi)部網(wǎng)卡才真正能收發(fā)射頻信號(hào)。三層缺一不可任何一層的版本不對(duì)或者缺失表現(xiàn)就是網(wǎng)卡枚舉不到或者反復(fù)掉線。Ubuntu 20.04 的默認(rèn)內(nèi)核是 5.4 系列而 Realtek RTL8852BE 對(duì)應(yīng)的 rtw89 驅(qū)動(dòng)是在內(nèi)核 5.13 之后才正式進(jìn)了 mainline。也就是說(shuō)Ubuntu 20.04 自帶的 5.4/5.8/5.11 內(nèi)核根本沒(méi)有可用的 rtw89 驅(qū)動(dòng)模塊。即使你手動(dòng)改了驅(qū)動(dòng)來(lái)源也大概率需要自己去編譯因?yàn)楣俜絻?nèi)核里壓根沒(méi)有這個(gè)源碼。這就是第一個(gè)瓶頸內(nèi)核太老。Ubuntu 20.04 的 LTS 版本為了保證穩(wěn)定性不會(huì)輕易升級(jí)大版本內(nèi)核而新硬件的驅(qū)動(dòng)往往只跟隨新內(nèi)核發(fā)布。所以不換內(nèi)核、不打補(bǔ)丁的情況下這張網(wǎng)卡在系統(tǒng)看來(lái)就相當(dāng)于一個(gè)不存在的設(shè)備。1.2 為什么網(wǎng)卡在 lspci 里能看到但系統(tǒng)不識(shí)別你打開(kāi)終端輸入 lspci十有八九能看到類(lèi)似這樣的輸出02:00.0 Network controller: Realtek Semiconductor Co., Ltd. Device b852很多人看到這一行就覺(jué)得系統(tǒng)已經(jīng)識(shí)別了呀為什么不工作這里要解釋清楚lspci 只是 PCIe 總線層面的枚舉它看到的是硬件設(shè)備的 IDs并不代表內(nèi)核有對(duì)應(yīng)的驅(qū)動(dòng)把它接住。就像你在門(mén)口看到一封信從門(mén)縫塞進(jìn)來(lái)但這不代表你已經(jīng)讀完了信。真正的工作負(fù)載在驅(qū)動(dòng)模塊上沒(méi)有匹配的驅(qū)動(dòng)模塊lspci 能看到設(shè)備但系統(tǒng)不知道如何跟網(wǎng)卡通信。更直觀的檢查方式是lspci -nnk | grep -A 3 02:00.0如果沒(méi)有看到 Kernel driver in use: rtw89_pci 這樣的字樣而是停在 Kernel modules: ... 為空就說(shuō)明沒(méi)有驅(qū)動(dòng)在用。這是你在排查所有無(wú)線網(wǎng)卡問(wèn)題時(shí)首先要做的一步別急著去下載源碼先確認(rèn)設(shè)備到底卡在哪一層。1.3 離線環(huán)境為什么更容易翻車(chē)在線環(huán)境下驅(qū)動(dòng)問(wèn)題相對(duì)好解決加一個(gè)第三方 PPA比如 lwfinger/rtw89然后 apt update apt install 就完事了。但在離線環(huán)境全部依賴都要手動(dòng)準(zhǔn)備。你需要的東西不僅有驅(qū)動(dòng)源碼還有編譯它所需的工具鏈和內(nèi)核頭文件。很多新手只帶了驅(qū)動(dòng)源碼的 tar 包結(jié)果執(zhí)行 make 的時(shí)候報(bào) Cannot find kernel headers 或者 gcc: command not found當(dāng)場(chǎng)卡住。離線安裝的核心心法很簡(jiǎn)單你要在有網(wǎng)的另一臺(tái)機(jī)器上把所有需要的包全部下載好打包成光盤(pán)或 U 盤(pán)帶過(guò)去。關(guān)鍵是你得知道到底需要哪些包以及它們之間的依賴關(guān)系。這部分我會(huì)在后面專(zhuān)門(mén)用一個(gè)章節(jié)來(lái)講。實(shí)操知識(shí)Realtek 8812BU/8822CE 等常見(jiàn)型號(hào)與 b852 的關(guān)系順帶提醒一下Realtek 的無(wú)線網(wǎng)卡型號(hào)非常多不同型號(hào)的驅(qū)動(dòng)方案差異巨大。老一點(diǎn)的 RTL8188/8192 用 rtlwifi/rtl8xxxu 內(nèi)核模塊RTL8821/8812 用 rtl8812au 外部驅(qū)動(dòng)RTL8822/8852 系列則用到 rtw88/rtw89 內(nèi)核驅(qū)動(dòng)。如果你搜索時(shí)直接搜Realtek 無(wú)線網(wǎng)卡驅(qū)動(dòng)很容易下到完全不對(duì)的東西。先確認(rèn)硬件 ID 再動(dòng)手這是血淚教訓(xùn)。b852 這個(gè)設(shè)備 ID 對(duì)應(yīng)的是 RTL8852BE要用 rtw89 系列的驅(qū)動(dòng)代碼而不是 rtl8812au 之類(lèi)的老驅(qū)動(dòng)。2. 離線安裝的整體思路與前置準(zhǔn)備2.1 兩種可行的技術(shù)路線對(duì)比針對(duì) Ubuntu 20.04 RTL8852BE業(yè)界主流的方案大體上分兩條路。第一條路是打補(bǔ)丁升級(jí)內(nèi)核。因?yàn)?rtw89 驅(qū)動(dòng)在 5.13 內(nèi)核中已經(jīng)包含如果你能把內(nèi)核升到 5.15比如 Ubuntu 的 HWE 內(nèi)核或者 mainline 內(nèi)核那么驅(qū)動(dòng)模塊就直接有了。HWEHardware Enablement內(nèi)核是 Ubuntu 專(zhuān)門(mén)為新硬件準(zhǔn)備的20.04 后面幾個(gè)小版本會(huì)提供 5.15 內(nèi)核的 HWE。這條路的好處是一勞永逸內(nèi)核帶著驅(qū)動(dòng)而且和系統(tǒng)集成度高。壞處是內(nèi)核升級(jí)可能帶來(lái)其他軟件的兼容性風(fēng)險(xiǎn)離線環(huán)境下升級(jí)內(nèi)核還需要準(zhǔn)備大量?jī)?nèi)核 deb 包體積很大。第二條路是手動(dòng)編譯外部驅(qū)動(dòng)。從 Realtek 官方 GitHub 或者 lwfinger 的倉(cāng)庫(kù)拉取 rtw89 源碼在自己當(dāng)前內(nèi)核上編譯成 .ko 模塊加載進(jìn)系統(tǒng)。這條路不需要換內(nèi)核對(duì)系統(tǒng)整體影響小但每次內(nèi)核更新后模塊需要重新編譯用 DKMS 可以自動(dòng)化。離線環(huán)境下準(zhǔn)備源碼和編譯依賴比準(zhǔn)備整個(gè)內(nèi)核包要輕量得多。我建議新手優(yōu)先走第二條路因?yàn)樗珳?zhǔn)打擊只解決網(wǎng)卡問(wèn)題不波及系統(tǒng)其他部分。如果你需要同時(shí)解決很多新硬件問(wèn)題比如新的核顯、新的聲卡那升級(jí)內(nèi)核可能更劃算。2.2 在有網(wǎng)的機(jī)器上準(zhǔn)備離線安裝包離線安裝的實(shí)際難點(diǎn)在于你需要在一臺(tái)能上網(wǎng)的 Ubuntu 20.04 機(jī)器上把所有需要的 deb 包拉下來(lái)然后再搬運(yùn)到目標(biāo)機(jī)器上。這里有個(gè)特別需要注意的原則裝飾包的版本要和目標(biāo)機(jī)器的系統(tǒng)版本一致因?yàn)閮?nèi)核頭文件和 gcc 版本直接影響編譯結(jié)果。最穩(wěn)妥的做法就是用一臺(tái)同樣裝 Ubuntu 20.04 的機(jī)器作為打包機(jī)。需要準(zhǔn)備的內(nèi)容分三類(lèi)。第一類(lèi)是編譯工具鏈。主要是 gcc、make、build-essential。你可以用 apt download 的方式逐個(gè)下載也可以用更省事的方法apt-get download build-essential gcc make dkmsbuild-essential 在 Ubuntu 里是一個(gè) meta 包它依賴 gcc、g、make 等但你 apt-get download 只是下載它本身并不會(huì)自動(dòng)把依賴也下載下來(lái)。所以你需要用另一種方式apt-cache depends build-essential通過(guò)這個(gè)命令查看它的依賴樹(shù)然后手動(dòng)把依賴列出來(lái)再逐個(gè) apt-get download。這個(gè)過(guò)程有點(diǎn)繁瑣。更推薦的做法是使用 apt 的--download-only參數(shù)配合apt-get install --reinstallmkdir /tmp/netinstall cd /tmp/netinstall apt-get install --reinstall --download-only build-essential dkms這樣 apt 會(huì)把 build-essential 和它的所有依賴包全部下載到 /var/cache/apt/archives 目錄下你直接把這個(gè)目錄里的 .deb 文件全部拷走就行。第二類(lèi)是內(nèi)核頭文件和內(nèi)核模塊頭文件。編譯內(nèi)核模塊必須用到當(dāng)前內(nèi)核的 headers版本必須完全匹配apt-get install --reinstall --download-only linux-headers-$(uname -r)注意uname -r必須在目標(biāo)機(jī)器上執(zhí)行因?yàn)轭^和頭之間不能混用。如果你在打包機(jī)上執(zhí)行uname -r得到的版本號(hào)和目標(biāo)機(jī)器不同編譯出來(lái)的模塊可能加載不上。第三類(lèi)是驅(qū)動(dòng)源碼。你可以從 GitHub 上下載源碼包這里推薦兩個(gè)源Realtek 官方 GitHub 倉(cāng)庫(kù)https://github.com/rtw88/rtw89 這個(gè)是內(nèi)核上游驅(qū)動(dòng)的源代碼鏡像更接近 mainlinelwfinger/rtw89 倉(cāng)庫(kù)https://github.com/lwfinger/rtw89 維護(hù)很活躍修復(fù)了很多新內(nèi)核的兼容問(wèn)題支持范圍更廣我個(gè)人的建議是用 lwfinger 的版本因?yàn)樗鼘?duì) Ubuntu 20.04 的適配性更好而且它自帶 DKMS 支持的配置文件可以直接安裝成內(nèi)核模塊管理后續(xù)內(nèi)核升級(jí)時(shí)能自動(dòng)重編譯。2.3 如何用 U 盤(pán)/移動(dòng)硬盤(pán)把環(huán)境搬過(guò)去有了這些包之后你需要做一個(gè)離線安裝工具箱。這里有個(gè)小技巧不要直接把 deb 文件放在 U 盤(pán)根目錄就完事了建議按目錄分類(lèi)整理/offline-tool/ ├── drv/ # 驅(qū)動(dòng)源碼壓縮包 ├── debs/ # 所有依賴的 deb 包 ├── scripts/ # 一鍵安裝腳本 └── README.md # 安裝說(shuō)明這么做的原因是目標(biāo)機(jī)器上的環(huán)境可能比較干凈你可能需要連續(xù)執(zhí)行多個(gè) dpkg 命令如果文件全堆在一起很容易漏裝某個(gè)依賴。README 里把安裝順序?qū)懞冒凑枕樞騺?lái)能少踩很多坑。還有一個(gè)細(xì)節(jié)U 盤(pán)的文件系統(tǒng)建議用 exFAT 或者 ext4盡量不要用 NTFS因?yàn)橐恍?Linux 發(fā)行版對(duì) NTFS 的掛載需要額外驅(qū)動(dòng)雖然 Ubuntu 20.04 默認(rèn)裝了 ntfs-3g但保不齊你的目標(biāo)機(jī)器環(huán)境更精簡(jiǎn)。另外U 盤(pán)里放一個(gè)md5sums.txt方便校驗(yàn)文件是否完整拷貝尤其 deb 包這種二進(jìn)制文件拷貝過(guò)程中損壞一個(gè)字節(jié)都可能讓 dpkg 安裝時(shí)報(bào)錯(cuò)。3. 驅(qū)動(dòng)源碼的獲取與選擇3.1 官方倉(cāng)庫(kù)、第三方倉(cāng)庫(kù)和發(fā)行版補(bǔ)丁的區(qū)別Realtek 驅(qū)動(dòng)的源碼在互聯(lián)網(wǎng)上有好幾個(gè)版本這是新手最容易迷惑的地方。簡(jiǎn)單區(qū)分一下官方 GitHub 上的 rtw89 是 Linux 內(nèi)核模塊的上游源代碼它和 Linux mainline 內(nèi)核同步維護(hù)。如果你用的是比較新的內(nèi)核比如 5.15直接用官方倉(cāng)庫(kù)的代碼往往就能編譯通過(guò)。但如果你用的還是較老的內(nèi)核比如 5.4官方倉(cāng)庫(kù)的代碼可能會(huì)因?yàn)?API 變化而編譯失敗需要你在編譯時(shí)手動(dòng)做一些適配。lwfinger 的倉(cāng)庫(kù)維護(hù)目標(biāo)就更加向下兼容。這個(gè)維護(hù)者長(zhǎng)期做 Realtek 網(wǎng)卡驅(qū)動(dòng)的移植和兼容工作他的倉(cāng)庫(kù)代碼通常會(huì)兼容較老的內(nèi)核 API也會(huì)附帶更完整的固件文件加載邏輯。對(duì) Ubuntu 20.04 這種老系統(tǒng)我優(yōu)先推薦 lwfinger 的版本。還有一種是發(fā)行版補(bǔ)丁比如 Debian 的 linux firmware 包或 Ubuntu 的 linux-firmware 包。但要注意固件文件和驅(qū)動(dòng)源碼是兩回事。很多時(shí)候你缺的不是驅(qū)動(dòng)代碼而是固件文件。比如你在 dmesg 里看到rtw89_8852be: Direct firmware load for rtw89/rtw8852be_fw.bin failed這就說(shuō)明驅(qū)動(dòng)模塊在嘗試加載固件時(shí)沒(méi)找到文件。這種情況你需要裝 linux-firmware 或者單獨(dú)下載固件文件放到 /lib/firmware/rtw89/ 目錄。恰恰這個(gè)細(xì)節(jié)會(huì)導(dǎo)致你明明編譯成功了驅(qū)動(dòng)模塊但網(wǎng)卡還是無(wú)法工作。3.2 具體怎么下載和校驗(yàn)如果你在有網(wǎng)的機(jī)器上可以用 git clone 拉源碼git clone https://github.com/lwfinger/rtw89.git然后打包tar czf rtw89.tar.gz rtw89/如果你用的 GitHub 下載 zip 的網(wǎng)頁(yè)方式記得在下載時(shí)選擇對(duì)應(yīng)分支通常 master 或者 main 就行。另外強(qiáng)烈建議下載后生成一下源碼包的哈希值sha256sum rtw89.tar.gz把哈希值寫(xiě)進(jìn) README到了目標(biāo)機(jī)器上可以先校驗(yàn)一遍防止拷過(guò)去之后文件損壞。雖然這個(gè)概率很低但離線環(huán)境下排查問(wèn)題的代價(jià)極高提前花十秒校驗(yàn)一下很劃算。還有一件事要注意確認(rèn)目標(biāo)機(jī)器是否缺少固件文件。這個(gè)在離線環(huán)境下尤其重要。你可以到 linux-firmware 的 Git 倉(cāng)庫(kù)里https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/找到 rtw89 目錄下的 .bin 文件手動(dòng)放到目標(biāo)機(jī)器的 /lib/firmware/rtw89/ 下。如果你用的驅(qū)動(dòng)源碼包比較新它可能自帶 copy-firmware 腳本或者文檔說(shuō)明仔細(xì)看一下 README。4. 依賴解決的完整實(shí)戰(zhàn)從打包到落地4.1 離線依賴安裝的兩種方法對(duì)比到了目標(biāo)機(jī)器上安裝 deb 包一般有兩種方式。一種是直接用 dpkgsudo dpkg -i /path/to/offline-tool/debs/*.deb但 dpkg 不會(huì)自動(dòng)處理依賴關(guān)系如果安裝順序不對(duì)它會(huì)提示依賴問(wèn)題。所以更推薦用另一種方式sudo apt install /path/to/offline-tool/debs/*.debapt 會(huì)讀取這些本地 deb 文件的依賴信息并嘗試從系統(tǒng)已有的包包括你手動(dòng)放進(jìn)來(lái)的這些 deb中滿足依賴。只要 debs 目錄里的包足夠完整apt 就能自己理清順序全部裝好。這比手動(dòng)排列 dpkg 命令要省心太多。如果你下載了很多包但不確定是否完整可以用這個(gè)簡(jiǎn)單方法檢查dpkg-deb -I /path/to/package.deb | grep Depends:看看某個(gè) deb 的依賴項(xiàng)然后和 debs 目錄列表比對(duì)缺哪個(gè)就去補(bǔ)哪個(gè)。4.2 安裝驅(qū)動(dòng)源碼并編譯假設(shè)你已經(jīng)把 rtw89 源碼解壓到了目標(biāo)機(jī)器的 home 目錄接著進(jìn)入源碼目錄先看一下 README 或者 Makefile 文件開(kāi)頭的注釋確認(rèn)編譯步驟。通常這個(gè)倉(cāng)庫(kù)的編譯流程是make sudo make install在動(dòng)手之前先執(zhí)行一下make clean這個(gè)命令不是必須的但如果你的源碼包是從別處拷貝來(lái)的遇到了什么奇怪的編譯錯(cuò)誤先 clean 一下可以排除緩存殘留問(wèn)題。編譯過(guò)程中你可能遇到的第一個(gè)報(bào)錯(cuò)是缺少內(nèi)核頭文件make[1]: *** /lib/modules/5.4.0-XXX-generic/build: 沒(méi)有那個(gè)文件或目錄這就說(shuō)明內(nèi)核頭文件沒(méi)裝。回到 debs 目錄找到 linux-headers-$(uname -r) 和 linux-headers-$(uname -r | cut -d- -f1)-common 等包安裝上去。安裝完后再執(zhí)行一下ls /lib/modules/$(uname -r)/build如果能正常列出內(nèi)容就說(shuō)明頭文件目錄就緒了。編譯命令跑完后會(huì)生成 .ko 文件。用 make install 把它安裝到 /lib/modules/$(uname -r)/ 下面然后執(zhí)行sudo depmod -a sudo modprobe rtw89_pcidepmod 是更新模塊依賴關(guān)系modprobe 是加載模塊。如果加載成功再次執(zhí)行l(wèi)spci -nnk | grep -A 3 02:00.0這時(shí)應(yīng)該能看到 Kernel driver in use: rtw89_pci 了。4.3 DKMS 與開(kāi)機(jī)自動(dòng)加載的設(shè)置到這里驅(qū)動(dòng)雖然裝上了但還沒(méi)完。如果你直接重啟可能驅(qū)動(dòng)模塊會(huì)不見(jiàn)因?yàn)?modprobe 只是臨時(shí)的除非系統(tǒng)啟動(dòng)時(shí)會(huì)自動(dòng)加載這個(gè)模塊。有兩種方式保證開(kāi)機(jī)自動(dòng)加載。第一種是手動(dòng)配置。把 rtw89_pci 寫(xiě)入 /etc/modulesecho rtw89_pci | sudo tee -a /etc/modules這樣每次啟動(dòng)時(shí)內(nèi)核會(huì)嘗試加載這個(gè)模塊。第二種是更優(yōu)雅的 DKMS 方式。DKMS 的全稱是 Dynamic Kernel Module Support它可以管理外部?jī)?nèi)核模塊的安裝并且在內(nèi)核升級(jí)時(shí)自動(dòng)重新編譯。這樣你就不用擔(dān)心以后系統(tǒng)更新內(nèi)核導(dǎo)致驅(qū)動(dòng)失效的問(wèn)題。安裝 DKMS 和內(nèi)核頭文件sudo apt install dkms linux-headers-$(uname -r)然后進(jìn)入源碼目錄執(zhí)行sudo dkms add . sudo dkms build -m rtw89 -v 1.0 sudo dkms install -m rtw89 -v 1.0其中-v 1.0的版本號(hào)要根據(jù)源碼里的 dkms.conf 文件來(lái)確定。你可以在 dkms.conf 里看到這樣一行PACKAGE_VERSION1.0把這個(gè)版本號(hào)抄下來(lái)替換進(jìn)命令即可。DKMS 安裝成功后它會(huì)自動(dòng)注冊(cè)模塊到系統(tǒng)啟動(dòng)流程里以后內(nèi)核升級(jí)也不會(huì)丟。強(qiáng)烈建議用這種方式。關(guān)于固件的補(bǔ)充步驟驅(qū)動(dòng)模塊可以加載成功不代表 WiFi 就能正常工作。如果你發(fā)現(xiàn)模塊加載正常但ip link里沒(méi)有 wlan0 接口多半是固件缺失。確認(rèn)方法sudo dmesg | grep rtw89如果看到 firmware 相關(guān)的報(bào)錯(cuò)就去 linux-firmware 倉(cāng)庫(kù)下載 rtw89 固件文件。具體需要三個(gè)文件rtw8852be_fw.bin、rtw8852b_table.bin、rtw8852b_fw.bin具體名稱以驅(qū)動(dòng)源碼要求為準(zhǔn)。把它們放到 /lib/firmware/rtw89/ 目錄然后重新加載模塊sudo rmmod rtw89_pci sudo modprobe rtw89_pci這時(shí)再查 dmesg應(yīng)該能看到固件加載成功的日志。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 編譯報(bào)錯(cuò)速查表我把自己和網(wǎng)友實(shí)際遇到過(guò)的編譯問(wèn)題整理成了一張表按出現(xiàn)頻率排了個(gè)序報(bào)錯(cuò)信息原因解決方式/lib/modules/.../build 不存在缺少內(nèi)核頭文件安裝 linux-headers-$(uname -r)gcc: 未找到命令缺少編譯工具鏈安裝 build-essential函數(shù)未聲明 / 隱式聲明內(nèi)核 API 版本太老源碼不兼容換 lwfinger 的 rtw89 版本或換新內(nèi)核undefined reference to ...內(nèi)核配置缺少某些符號(hào)檢查內(nèi)核 config開(kāi)啟 CONFIG_CFG80211 和 CONFIG_MAC80211權(quán)限不足非 root 編譯sudo make或用 root 用戶操作make: *** 沒(méi)有規(guī)則可以創(chuàng)建目標(biāo) modules沒(méi)有進(jìn)入源碼根目錄cd 到源碼目錄再執(zhí)行 make5.2 CONFIG_CFG80211 和 CONFIG_MAC80211 是什么有些朋友編譯時(shí)遇到undefined reference或者unknown symbol原因在于內(nèi)核配置關(guān)閉了無(wú)線網(wǎng)絡(luò)框架相關(guān)的選項(xiàng)。RTW89 驅(qū)動(dòng)依賴內(nèi)核的 cfg80211 和 mac80211 子系統(tǒng)這兩個(gè)是 Linux 無(wú)線網(wǎng)絡(luò)的基礎(chǔ)框架。如果沒(méi)有這些配置項(xiàng)驅(qū)動(dòng)代碼里引用的函數(shù)符號(hào)就找不到。檢查方法grep CONFIG_CFG80211 /boot/config-$(uname -r) grep CONFIG_MAC80211 /boot/config-$(uname -r)如果結(jié)果顯示# CONFIG_CFG80211 is not set說(shuō)明內(nèi)核沒(méi)啟用無(wú)線框架。這種情況很少見(jiàn)因?yàn)榇蠖鄶?shù)發(fā)行版內(nèi)核都啟用了這些選項(xiàng)。如果你用的精簡(jiǎn)內(nèi)核或者自己編譯的內(nèi)核就需要注意這個(gè)點(diǎn)。解決方案一般不是去重編內(nèi)核那太痛苦了而是換一個(gè)發(fā)行版提供的標(biāo)準(zhǔn)內(nèi)核比如 Ubuntu 的 generic 內(nèi)核。在離線環(huán)境下你需要額外準(zhǔn)備 linux-image-generic 和匹配的 linux-modules 包。5.3 WiFi 圖標(biāo)不顯示但模塊已加載模塊加載成功后右上角的網(wǎng)絡(luò)圖標(biāo)不顯示先不要急著懷疑驅(qū)動(dòng)。按順序排查執(zhí)行ip link看有沒(méi)有 wlan0 或者 wlp2s0 接口。有接口但處于 DOWN 狀態(tài)執(zhí)行sudo ip link set wlan0 up。如果提示 RTNETLINK answers: Operation not possible due to RF-kill說(shuō)明無(wú)線開(kāi)關(guān)被硬件禁用了。執(zhí)行rfkill list查看如果是 soft block可以用rfkill unblock wifi解除。如果接口都正常檢查 NetworkManager 是否在運(yùn)行systemctl status NetworkManager。有些精簡(jiǎn)系統(tǒng)用的是 systemd-networkd 或其他網(wǎng)絡(luò)管理器需要你手動(dòng)用 nmcli 連接 WiFi。我之前遇到過(guò)一種情況驅(qū)動(dòng)和固件都沒(méi)問(wèn)題接口也出現(xiàn)了但 NetworkManager 一直不顯示 WiFi 列表。最后發(fā)現(xiàn)是 NetworkManager 沒(méi)有 wifi 后端權(quán)限把它加入 netdev 用戶組就解決了sudo usermod -a -G netdev $USER這個(gè)坑比較冷門(mén)但也值得記錄一下。5.4 模塊已加載但搜索不到 WiFi 信號(hào)這種情況大概率是固件版本和驅(qū)動(dòng)版本不匹配。你可能從 A 地方下載了驅(qū)動(dòng)源碼從 B 地方下載了固件兩者版本不一致表現(xiàn)出來(lái)就是能掃描到零個(gè) AP或者能掃到但連不上、連上就掉線。解決辦法是把驅(qū)動(dòng)源碼自帶的固件一般在 firmware 子目錄下復(fù)制到 /lib/firmware/rtw89/確保固件和驅(qū)動(dòng)來(lái)自同一份源碼包。還有一個(gè)容易被忽略的點(diǎn)WiFi 6 網(wǎng)卡默認(rèn)啟用了 802.11ax 模式部分老路由器對(duì)這個(gè)模式兼容性不好導(dǎo)致連接不穩(wěn)定??梢試L試禁用 802.11axsudo modprobe rtw89_pci disable_11ax1如果確認(rèn)有效就把它寫(xiě)入 /etc/modprobe.d/rtw89.confoptions rtw89_pci disable_11ax1這個(gè)參數(shù)在部分型號(hào)的老驅(qū)動(dòng)里沒(méi)有可以先通過(guò)modinfo rtw89_pci查看可用參數(shù)列表。5.5 沒(méi)有有網(wǎng)打包機(jī)時(shí)的備用方案最后聊一個(gè)現(xiàn)實(shí)問(wèn)題如果你身邊壓根沒(méi)有第二臺(tái)能上網(wǎng)的 Ubuntu 機(jī)器怎么破方案一用 U 盤(pán)啟動(dòng)一個(gè) Live 系統(tǒng)。下載 Ubuntu Desktop 的 ISO 文件寫(xiě)入 U 盤(pán)然后在 U 盤(pán)啟動(dòng)的 Live 環(huán)境里聯(lián)網(wǎng)下載依賴包再把 deb 包打包放到硬盤(pán)分區(qū)里。前提是你的筆記本在這個(gè) Live 環(huán)境里能識(shí)別有線網(wǎng)卡或者能通過(guò)手機(jī) USB 共享網(wǎng)絡(luò)。方案二手機(jī) USB 網(wǎng)絡(luò)共享。對(duì)手機(jī)接入電腦開(kāi)啟USB 網(wǎng)絡(luò)共享Ubuntu 系統(tǒng)一般會(huì)自動(dòng)識(shí)別為一個(gè)有線網(wǎng)卡接口rndis_host 或者 cdc_ether這樣你就能在目標(biāo)機(jī)器上直接聯(lián)網(wǎng)了。這個(gè)方案很多老手都在用不只是裝驅(qū)動(dòng)時(shí)好用任何斷網(wǎng)救援場(chǎng)景都能用上強(qiáng)烈建議掌握。操作步驟是把手機(jī)用 USB 線連上電腦手機(jī)端設(shè)置里開(kāi)啟USB 網(wǎng)絡(luò)共享Ubuntu 的 NetworkManager 一般會(huì)自動(dòng)彈出一個(gè)新連接幾分鐘內(nèi)搞定網(wǎng)絡(luò)。方案三如果你手頭有樹(shù)莓派或者其他 Linux 小主機(jī)可以把它們當(dāng)作下載機(jī)在它們上下載 deb 包再拷貝到目標(biāo)機(jī)器。但要提醒一下下載包的機(jī)器架構(gòu)不同會(huì)導(dǎo)致 deb 包不通用。X86 機(jī)器上要下載 amd64 架構(gòu)的包ARM 樹(shù)莓派上下載的是 arm64 架構(gòu)不能混用。所以更好的辦法是直接用手機(jī) USB 共享網(wǎng)絡(luò)只要目標(biāo)機(jī)器能上網(wǎng)所有依賴都能用 apt get 直接裝省去手動(dòng)下載依賴的麻煩。6. 安裝完成后的驗(yàn)證與系統(tǒng)加固6.1 驗(yàn)證網(wǎng)卡是否真正可用驅(qū)動(dòng)加載、固件就位、接口出現(xiàn)這只是第一步。真正驗(yàn)證網(wǎng)卡可用要連上 WiFi 做一次斷網(wǎng)重連測(cè)試。在終端里用 nmcli 連接nmcli dev wifi list nmcli dev wifi connect 你的SSID password 你的密碼如果連接成功用 ping 測(cè)試穩(wěn)定性ping -c 10 223.5.5.5看丟包率和延遲如果都正常說(shuō)明網(wǎng)卡硬件和驅(qū)動(dòng)工作狀態(tài)良好。再用 iperf3 測(cè)一下實(shí)際吞吐能到幾百 Mbps 基本就沒(méi)什么問(wèn)題了。如果你發(fā)現(xiàn)連接后頻繁斷流可以參考前面提到的 disable_11ax1 參數(shù)或者換一個(gè)無(wú)線信道試試。6.2 內(nèi)核升級(jí)后驅(qū)動(dòng)丟失的預(yù)防DKMS 已經(jīng)能解決 90% 的內(nèi)核升級(jí)問(wèn)題但有時(shí)候內(nèi)核版本跨度太大比如從 5.4 升到 5.15DKMS 重編譯也可能失敗。這時(shí)你需要檢查 /var/lib/dkms/rtw89/ 目錄下的 build 日志看看編譯失敗的具體原因一般是內(nèi)核 API 變化導(dǎo)致等待驅(qū)動(dòng)倉(cāng)庫(kù)更新即可。另外還有一個(gè)小技巧在 Ubuntu 的 unattended-upgrades自動(dòng)安全更新配置里可以排除內(nèi)核更新包避免系統(tǒng)半夜自動(dòng)升級(jí)內(nèi)核導(dǎo)致驅(qū)動(dòng)失效。這個(gè)配置在 /etc/apt/apt.conf.d/50unattended-upgrades 里找到 Package-Blacklist 部分加上linux-image-*; linux-headers-*; linux-modules-*;這樣內(nèi)核更新不會(huì)被自動(dòng)執(zhí)行想升級(jí)時(shí)手動(dòng)操作可以更好地控制驅(qū)動(dòng)兼容性。6.3 備份自己的離線驅(qū)動(dòng)部署包既然已經(jīng)安裝成功建議留一個(gè)備份。把 U 盤(pán)里的 debs 目錄和驅(qū)動(dòng)源碼再打一個(gè)包存到本地磁盤(pán)的某個(gè)目錄里標(biāo)注好日期、內(nèi)核版本、驅(qū)動(dòng)版本。以后如果再遇到另一臺(tái)同型號(hào)網(wǎng)卡的機(jī)器或者系統(tǒng)需要重裝直接照著這個(gè)流程走一遍就能快速恢復(fù)。我在實(shí)際工作里就吃過(guò)虧裝完一臺(tái)機(jī)器后沒(méi)留備份過(guò)了幾個(gè)月系統(tǒng)崩了重裝又遇到同樣的驅(qū)動(dòng)問(wèn)題但當(dāng)時(shí)已經(jīng)忘了當(dāng)初具體下載了哪個(gè)倉(cāng)庫(kù)的哪個(gè) commit重新折騰了好幾個(gè)小時(shí)。后來(lái)我把離線部署包固定放在 /srv/offline-packages/ 目錄并且寫(xiě)了一鍵安裝腳本從那以后再也沒(méi)在這個(gè)問(wèn)題上浪費(fèi)時(shí)間。結(jié)尾說(shuō)點(diǎn)實(shí)際感受折騰 Linux 無(wú)線網(wǎng)卡驅(qū)動(dòng)這個(gè)事情很多新手容易陷入一個(gè)誤區(qū)就是盲目試各種教程里的命令結(jié)果越試越亂。我的體會(huì)是任何驅(qū)動(dòng)安裝類(lèi)的問(wèn)題都要先花時(shí)間把硬件 ID - 驅(qū)動(dòng)模塊 - 固件文件 - 內(nèi)核配置這條鏈路看清楚知道當(dāng)前卡在哪一環(huán)再去針對(duì)性解決。尤其是離線環(huán)境準(zhǔn)備工作做得越細(xì)踩的坑就越少。最后再分享一個(gè)小技巧如果你以后看到內(nèi)核日志里報(bào) firmware 加載失敗但又不知道固件文件應(yīng)該叫什么名字可以使用這個(gè)命令modinfo /lib/modules/$(uname -r)/kernel/drivers/net/wireless/realtek/rtw89/rtw89_pci.komodinfo 輸出的信息里通常會(huì)列出固件文件名。比如 fw: rtw89/rtw8852be_fw.bin這個(gè)就是你需要放到 /lib/firmware/rtw89/ 目錄里的文件名。很多驅(qū)動(dòng)源碼的 README 里沒(méi)寫(xiě)清楚固件文件名用這個(gè)方法一查就清楚了。準(zhǔn)備離線包之前先查詢一遍就能把固件一次性準(zhǔn)備好避免到了目標(biāo)機(jī)器上才發(fā)現(xiàn)缺文件的尷尬。