684 字
2 分钟
MT7902 再再再再续
2026-05-28

前情提要#

上回说到,我给 DKMS 驱动的源码打了 dev->new_ctx && 守卫,dkms build + install 一气呵成,WiFi 回来了

重启后连上 AKU-WiFi,正常上网,我以为这事翻篇了

然后它又崩了#

5 月 28 号上午,系统又卡死了

一模一样的症状——鼠标能动但点不了东西,网断了,TTY 切不了,只能长按电源键

查日志:

journalctl -b -1 -p 3
kernel: BUG: kernel NULL pointer dereference, address: 0000000000000000
kernel: 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)"
done
updates/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 优先级再高也没用

从前到后的完整时间线:

  1. 我打了源码补丁 → dkms build + installmt7921e.ko 进了 updates/dkms/
  2. 重启 → system 按 PCI ID 找驱动 → 找到 mt7902e 从内核树加载 → 旧版、未打补丁
  3. 我还以为开了 → 其实一直在裸奔
  4. AP 一发 CSA 信标 → new_ctx 是 NULL → 崩

这次真的修了#

删掉内核树的旧模块,让 DKMS 的 mt7921e.ko 接管——updates 目录的优先级高于 kernel 目录

# 确认 DKMS 的 mt7921e.ko 支持 MT7902
modinfo -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 -a
sudo 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 早一步:

/etc/pacman.d/hooks/69-mt7902-patch.hook
[Trigger]
Operation=Install
Operation=Upgrade
Type=Package
Target=mediatek-mt7927-dkms
[Action]
Description=Patching mt7902 CSA NULL deref before DKMS rebuild
Depends=mediatek-mt7927-dkms
When=PreTransaction
Exec=/usr/local/share/mt7902-patches/apply-patch.sh

PreTransaction → 打补丁 → DKMS rebuild → 已修复的模块自动部署

回顾#

这条 if (!dev->new_ctx) return; 修了三次:

阶段修法以为好了吗实际
二进制改 .ko改了 20 个字节好了只修了一条路径
DKMS 源码补丁加 dev->new_ctx &&好了模块名不匹配,压根没加载
删内核树旧模块让 DKMS 真正接管真好了加上 hook 保内核更新

折腾了这么久,最后发现不是补丁不对,是补丁根本没被用上

这次检查过了,加载的是 updates/dkms/mt7921e.ko.zst,srcversion 对得上,源码守卫在,hook 自动保着

应该不会再有了

补丁仓库:https://github.com/GT001well/mt7902e-null-fix

系统: Arch Linux
内核: 7.0.10-zen1-1-zen
网卡: MediaTek MT7902 (Filogic 310) PCIe
驱动: mediatek-mt7927 DKMS 2.10 (mt7921e)
srcversion: 826091AD2AE8AEB3DEAC411

Saya提供技术支持

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

MT7902 再再再再续
https://text.lilystar.cn/posts/mt7902-再再再再续/
作者
Lily
发布于
2026-05-28
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录