背景
已经通过独立实验确认:
Panel power cycle delay = 500 ms
对于目标机器的内置 eDP 面板过短。
实验结果:
0.5 秒 → 故障
1 秒 → 故障
2 秒 → 稳定
3 秒 → 稳定
因此决定修改 Linux i915 源码。
一、源码位置
相关实现位于:
drivers/gpu/drm/i915/display/intel_pps.c
关键赋值:
intel_dp->pps.panel_power_cycle_delay =
pps_units_to_msecs(final->power_cycle);
修改为:
intel_dp->pps.panel_power_cycle_delay =
pps_units_to_msecs(final->power_cycle);
intel_dp->pps.panel_power_cycle_delay =
max(intel_dp->pps.panel_power_cycle_delay, 2000);
实际也可以写成单行:
intel_dp->pps.panel_power_cycle_delay = max(intel_dp->pps.panel_power_cycle_delay, 2000);
二、为什么使用 max()
这个修改不是:
强制所有机器使用 2000 ms
而是:
最低不得低于 2000 ms
逻辑相当于:
firmware = 500
→ 2000
firmware = 1000
→ 2000
firmware = 2500
→ 2500
这样比直接:
panel_power_cycle_delay = 2000;
更合理。
三、为什么不修改其他 PPS 参数
原参数例如:
Panel power up delay: 200
Panel power down delay: 60
Panel power cycle delay: 500
Backlight on delay: 1
Backlight off delay: 200
实验只证明:
完整 OFF → ON 间隔
与故障高度相关。
没有证据表明:
power_up
power_down
backlight_on
backlight_off
存在问题。
因此遵循最小修改原则,只改变:
panel_power_cycle_delay
四、内核模块必须精确匹配当前内核
例如某次使用:
Linux 7.1.8-arch1-3
自定义模块的:
vermagic
也必须是:
7.1.8-arch1-3 SMP preempt mod_unload
不能拿旧模块直接加载到:
7.1.9-arch1-2
甚至不能假设同一个主版本的小更新也兼容。
五、Arch localversion 很重要
Arch 内核源码不仅包含:
VERSION
PATCHLEVEL
SUBLEVEL
还会使用:
localversion.10-pkgrel
localversion.20-pkgname
例如:
7.1.8-arch1-3
中的:
-arch1-3
必须正确生成。
否则编译出的模块可能出现:
vermagic mismatch
六、使用官方 Module.symvers
单独编译外部或局部模块时,一个关键文件是:
Module.symvers
应优先使用已安装、完全对应目标内核的:
/usr/lib/modules/<kernel-release>/build/Module.symvers
而不是重新生成一套不匹配的符号版本信息。
七、只编译 i915
无需编译整颗 Linux kernel。
准备完成后可以:
make -j"$(nproc)" \
M=drivers/gpu/drm/i915 \
modules
最终产生:
drivers/gpu/drm/i915/i915.ko
同时可能产生:
kvmgt.ko
等同目录模块。
八、BTF warning
编译过程中可能出现:
Skipping BTF generation for i915.ko
due to unavailability of vmlinux
对于这种局部模块构建,它不代表编译失败。
只要最终:
i915.ko
成功生成即可。
九、验证 vermagic
例如:
modinfo drivers/gpu/drm/i915/i915.ko |
grep '^vermagic:'
必须与:
modinfo -k <kernel-release> i915 |
grep '^vermagic:'
完全一致。
十、安装到 updates/
不覆盖 Arch 官方模块。
官方模块继续保留:
/usr/lib/modules/<kernel-release>/kernel/drivers/gpu/drm/i915/i915.ko.zst
自定义模块安装:
/usr/lib/modules/<kernel-release>/updates/i915.ko.zst
例如:
sudo install -Dm644 \
/tmp/i915-custom.ko.zst \
/usr/lib/modules/<kernel-release>/updates/i915.ko.zst
sudo depmod -a <kernel-release>
十一、为什么使用 updates/
kmod 默认会优先解析:
updates/
中的模块。
因此:
modinfo -k <kernel-release> -n i915
应返回:
/lib/modules/<kernel-release>/updates/i915.ko.zst
而官方文件仍然存在。
这样回退非常简单:
sudo rm \
/usr/lib/modules/<kernel-release>/updates/i915.ko.zst
sudo depmod -a <kernel-release>
之后:
modinfo -k <kernel-release> -n i915
即可重新解析到官方版本。
十二、Late KMS 的好处
由于 i915 没有放入 initramfs:
NO I915 IN INITRAMFS
所以修改 /usr/lib/modules/.../updates/ 后不需要为了 i915 重新生成 initramfs。
如果未来改为 Early KMS,则需要重新评估:
mkinitcpio
流程。