事情起因也很简单。
昨天下班没关机器,合上笔记本盖子,外接屏还停在登录界面。今天早上看见整机卡死,强制关机前屏幕上还挂着 Chrome 和系统通知。前天也冒过系统通知,于是第一反应是:
是不是通知把系统弄挂了?
查完 journalctl 之后,答案很明确:不是。
卡死长什么样
上一启动周期里,大约 05:12 起,内核开始报 soft lockup:
- CPU#8 长时间卡住
- HardIRQ 占用约 98%
- 最频繁的中断是
irq#141(enp2s0:mac) - 调用栈落在
stmmac/dwmac4_irq_status
网卡是 Motorcomm YT8531S(驱动 dwmac_motorcomm),口子叫 enp2s0。
这是典型的 中断风暴:MAC 状态位清不干净,中断一直来,某个 CPU 被硬中断打满,界面当然没反应。Chrome / 桌面通知只是卡死时还留在锁屏上的东西,不是诱因。
日志里反复出现的:
ucsi_acpi USBC000:00: failed to re-enable notifications (-110)
也不是桌面通知,而是 USB-C 控制器在 suspend/resume 边界超时。容易望文生义,但和弹窗无关。
真正的上游:整晚在浅睡里空转
合盖后系统走的是:
PM: suspend entry (s2idle)
这台机 /sys/power/mem_sleep 只有 [s2idle],没有传统 S3 deep。
s2idle 是浅睡:CPU 进深 C-state,但中断子系统还醒着,USB / Type-C / 外接显示很容易当「门铃」。
更扎眼的是节奏:
- 睡着大约 十几秒 就被叫醒
- 锁屏上空闲约 15 分钟 又自动挂起
- 整夜循环几十次
15 分钟从哪来?GNOME 电源设置:
sleep-inactive-ac-timeout = 900
sleep-inactive-ac-type = suspend
所以「反复唤醒」其实是两段机制拼起来的:
- 谁负责再睡:空闲 900 秒自动挂起
- 谁负责吵醒:硬件唤醒源(当晚环境见下;ACPI
PEP._DSM/ACDC.RTAC每轮还报错)
有线网卡更像是 反复 suspend/resume 之后的受害者,不是当晚的门铃。某一次循环里 MAC 中断死循环,机器就彻底卡死了。
当晚插着什么
合盖时外接大致是:
- 显示器的 全功能 Type-C(视频 + 数据/供电一类能力都走这根线)
- 罗技无线鼠标的 2.4G 接收器(在用)
- 外接 USB 键盘
- 另一个 闲置的罗技 2.4G 接收器(鼠标没用,接收器还插着)
其中全功能 Type-C 屏嫌疑最大;两个接收器和键盘也都是合法 USB 唤醒源。闲置接收器等于多挂一个门铃,平时就该拔掉。
为什么显示器 Type-C 特别容易反复叫醒
全功能 Type-C 接显示器,往往不只是「多一个 USB 设备」,而是一条线上叠了好几套协议:
- DP Alt Mode:视频信号。面板电源、链路训练、热插拔检测(HPD)在休眠边界上很容易抖一下,内核会当成「显示状态变了」。
- USB / USB BillBoard / Hub:很多显示器 Type-C 口背后还有内部 hub,会枚举键鼠转发、摄像头、上游充电协商等。
- UCSI / PD 供电协商:插着就会谈电压电流。本机日志每轮 resume 后都有
ucsi_acpi ... failed to re-enable notifications (-110)(超时),说明 Type-C 控制器在 suspend/resume 时状态不干净,随后更容易再打中断。 - 和 s2idle 合在一起更糟:浅睡不断电到「门铃全关」,控制器和线缆还活着,上述任一事件都能把 CPU 从 idle 里拉起来。传统深睡 S3 会把更多设备真下电,外接屏没那么容易每隔十几秒喊人。
所以不是「Type-C 显示器有毒」,而是:一根线绑了显示 + USB + 供电,事件面太宽,又正好撞上只能 s2idle 的平台。合盖后外接屏还亮着登录界面,等于整晚把这条嘈杂链路留在唤醒路径上。
挂起和休眠不是一回事
排查过程中,概念也值得写清楚:
| 说法 | 实际 | 状态在哪 | 能否真正断电 |
|---|---|---|---|
| 挂起 / 睡眠 | suspend(此处多为 s2idle) | 内存 | 否,内存仍供电 |
| 休眠 | hibernate | 磁盘 swap | 可以 |
挂起 ≈ 休眠到内存:醒得快,合盖过夜仍耗电,也容易被外设叫醒。
休眠 ≈ 休眠到硬盘:更省电,依赖够大的磁盘 swap。
还有一种听起来很香的折中:suspend-then-hibernate(先挂起,挂够一段时间再自动休眠)。
在这台「合盖 + DP/USB-C 外接屏」的机器上,它不可靠。
原因很直接:这条路径的前提是先能稳稳挂着。日志里 s2idle 往往十几秒就被叫醒;门铃还在响,后面的「长时间后再写盘休眠」根本走不到。结果不是「挂久了会休眠」,而是永远进不了休眠,只剩被 DP 反复吵醒的浅睡循环。
GNOME 50 的「设置 → 电源」里,也基本看不到「空闲后休眠」——界面多半只有自动挂起,以及电源键选挂起/休眠。底层键其实在:
org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type
org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type
可用 gsettings 或 Dconf Editor 设成 hibernate / nothing,但不要指望外接 DP 场景下用「先挂起再等休眠」解决问题。外接屏过夜更稳妥的是:直接休眠、关机,或拔掉显示后再合盖。
Fedora 默认只有 zram(内存里的压缩交换区)。关机 zram 就没了,不能拿来真正断电休眠。
想真正休眠,先搞清 swap 在哪
本机当时大致是:
- 内存:条子 32 GiB,UI 约 32.9 GB;
free -h显示 30Gi —— 只是 GB / GiB 单位不同,外加一点固件/核显预留 - Swap:只有 8G zram,没有磁盘 swap
btrfs 根分区占满了 Linux 那块盘,末尾没有空闲扇区;要切真正的 swap 分区就得缩容,等于「高速上换胎」,更稳妥是 Live USB 离线做。
更省事、也符合 Fedora 文档方向的,是在现有盘上建 swap 文件。
恢复时内核也不是「先挂载文件系统再 open() 文件」,而是用块设备 + resume_offset(或 UEFI 里的 HibernateLocation)按物理偏移读镜像。btrfs 因为 CoW,要用 btrfs filesystem mkswapfile 这类专用路径,关掉写时复制,位置才稳定。
第一版 DIY,和官方路径的差距
一开始按「手写 resume」做了一版:
- 路径在
/swap/swapfile grubby写上resume=UUID=... resume_offset=...- 关掉 zram
systemctl hibernate 先撞上 Access denied。不是 root 没权,是 SELinux:
systemd_logind_t 无法 read/open /swap/swapfile(标签 default_t)
用 audit2allow 放行 default_t 能救急,但太宽。
Fedora Magazine 更推荐的做法是:
- 独立 subvolume:
/var/swap - 文件:
/var/swap/swapfile - SELinux 标签:
swapfile_t - UEFI 下靠 systemd 写入 HibernateLocation,不必长期维护 cmdline 里的
resume= - dracut 加上
resume模块后重建 initramfs
于是把 DIY 残留清掉,迁到官方路径:
- 删除
/swap、fstab 旧条目、BLS 里的resume=/resume_offset= - 去掉宽泛的
hibernate_swapfile模块 - 新建
var/swapsubvolume + 32G swapfile,标签已是swapfile_t CanHibernate→"yes"
zram 仍保持禁用(个人选择;官方文档允许磁盘 swap 与 zram 并存)。
实用结论
合盖 + 外接屏 + 只有 s2idle 的笔记本,过夜很容易变成「浅睡空转」。空闲自动挂起会放大循环;Motorcomm 有线网卡则可能在循环末端用中断风暴把机器钉死。
有 DP 误唤醒时,suspend-then-hibernate 也救不了:挂都挂不住,就谈不上稍后自动休眠。
短期规避:
- 过夜关机,或拔掉 Type-C 显示器再合盖;闲置的 2.4G 接收器不要留着
- 插电时关掉自动挂起(
sleep-inactive-ac-type=nothing),或空闲直接hibernate - 不要依赖「先挂起、挂久了再休眠」
- 主要用 Wi‑Fi 时禁用
enp2s0,避开这类网卡驱动问题
长期:
- 按 Magazine 路径准备真正休眠,需要省电时直接休眠
- ACPI / 网卡问题可同时反馈整机厂与 Fedora/内核
下次再在锁屏上看到通知,至少知道:它多半只是证人,不是凶手。
环境备忘
- 机器:机械革命无界 14(GX4HRXL)
- 系统:Fedora Linux 44,内核 7.1.x
- 桌面:GNOME
- 文件系统:btrfs(
subvol=root/home,另加var/swap) - 当晚外设:全功能 Type-C 显示器、罗技 2.4G 接收器 ×2(其一闲置)、USB 键盘
- 参考:Update on hibernation in Fedora Workstation