前情提要
上回说到,我给 DKMS 驱动的源码打了 dev->new_ctx && 守卫,dkms build + install 一气呵成,WiFi 回来了
重启后连上 AKU-WiFi,正常上网,我以为这事翻篇了
然后它又崩了
5 月 28 号上午,系统又卡死了
一模一样的症状——鼠标能动但点不了东西,网断了,TTY 切不了,只能长按电源键
查日志:
journalctl -b -1 -p 3kernel: BUG: kernel NULL pointer dereference, address: 0000000000000000kernel: RIP: mt7921_channel_switch_rx_beacon+0x18/0xa0 [mt7902e]kernel: CR2: 0000000000000000还是 channel_switch_rx_beacon,还是 new_ctx 解引用
但我明明打了补丁啊?
真相:补丁从未生效
查了一下到底加载了哪个文件:
modprobe --show-depends mt7902e | grep insmod输出指向 /lib/modules/.../kernel/drivers/.../mt7902e/mt7902e.ko.zst——内核树里的旧模块
翻 updates/dkms/ 目录,DKMS 确实编出了 mt7921e.ko.zst,但系统根本没加载它
for f in $(find /lib/modules/$(uname -r) -name 'mt79*e.ko.zst'); do zstd -dc "$f" -o /tmp/v.ko 2>/dev/null echo "$(basename $(dirname $f)): $(modinfo -F srcversion /tmp/v.ko)"doneupdates/dkms: 826091AD2AE8AEB3DEAC411 ← 打了补丁的版本mt7902e: 76B73429A26E2E6F23382B ← 没打补丁的旧版两个版本同时存在,两个不同的 srcversion
系统默认加载了内核树的旧版 mt7902e.ko,补丁版 mt7921e.ko 就在旁边躺着,但没被用过
根因:dkms.conf 模块名不匹配
/usr/src/mediatek-mt7927-2.10/dkms.conf 里写着:
BUILT_MODULE_NAME[6]="mt7921e"DKMS 编出来的是 mt7921e.ko,放进 updates/dkms/
但系统启动时,PCI ID 14c3:7902 绑定的是 mt7902e,从内核树的 mediatek/mt7902e/ 目录加载
一个叫 mt7921e,一个叫 mt7902e,模块名不同,updates 优先级再高也没用
从前到后的完整时间线:
- 我打了源码补丁 →
dkms build + install→mt7921e.ko进了updates/dkms/ - 重启 → system 按 PCI ID 找驱动 → 找到
mt7902e从内核树加载 → 旧版、未打补丁 - 我还以为开了 → 其实一直在裸奔
- AP 一发 CSA 信标 →
new_ctx是 NULL → 崩
这次真的修了
删掉内核树的旧模块,让 DKMS 的 mt7921e.ko 接管——updates 目录的优先级高于 kernel 目录
# 确认 DKMS 的 mt7921e.ko 支持 MT7902modinfo -F alias /lib/modules/$(uname -r)/updates/dkms/mt7921e.ko.zst | grep 7902
# 删内核树旧模块sudo rm -rf /lib/modules/$(uname -r)/kernel/drivers/net/wireless/mediatek/mt7902e/
# 更新映射sudo depmod -asudo mkinitcpio -P
# 重启sudo reboot重启后 lsmod 里变成 mt7921e 了,不再是 mt7902e——名字变了,但它是同一张卡同一条驱动,只是这次真的加载了打过补丁的版本
cat /sys/module/mt7921e/srcversion# 826091AD2AE8AEB3DEAC411 ✓ 是打过补丁的版本再加一道保险
以后 pacman -Syu 更新 mediatek-mt7927-dkms 后,DKMS 会从源码重新编译——得让它在 rebuild 之前自动打上补丁
加了个 pacman hook,priority 69,比 DKMS 的 70 号 hook 早一步:
[Trigger]Operation=InstallOperation=UpgradeType=PackageTarget=mediatek-mt7927-dkms
[Action]Description=Patching mt7902 CSA NULL deref before DKMS rebuildDepends=mediatek-mt7927-dkmsWhen=PreTransactionExec=/usr/local/share/mt7902-patches/apply-patch.shPreTransaction → 打补丁 → DKMS rebuild → 已修复的模块自动部署
回顾
这条 if (!dev->new_ctx) return; 修了三次:
| 阶段 | 修法 | 以为好了吗 | 实际 |
|---|---|---|---|
| 二进制改 .ko | 改了 20 个字节 | 好了 | 只修了一条路径 |
| DKMS 源码补丁 | 加 dev->new_ctx && | 好了 | 模块名不匹配,压根没加载 |
| 删内核树旧模块 | 让 DKMS 真正接管 | 真好了 | 加上 hook 保内核更新 |
折腾了这么久,最后发现不是补丁不对,是补丁根本没被用上
这次检查过了,加载的是 updates/dkms/mt7921e.ko.zst,srcversion 对得上,源码守卫在,hook 自动保着
应该不会再有了
系统: Arch Linux内核: 7.0.10-zen1-1-zen网卡: MediaTek MT7902 (Filogic 310) PCIe驱动: mediatek-mt7927 DKMS 2.10 (mt7921e)srcversion: 826091AD2AE8AEB3DEAC411Saya提供技术支持
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
