<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>ACP on 暮歌</title><link>https://maxlen727.github.io/tags/acp/</link><description>Recent content in ACP on 暮歌</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><managingEditor>maxlen@duck.com (微恙)</managingEditor><webMaster>maxlen@duck.com (微恙)</webMaster><copyright>© 2021 - 2026 MaxLen All Rights Reserved.</copyright><lastBuildDate>Sun, 30 Aug 2026 16:29:27 +0800</lastBuildDate><atom:link href="https://maxlen727.github.io/tags/acp/index.xml" rel="self" type="application/rss+xml"/><follow_challenge><feedId>131352344216671232</feedId><userId>85706335998788608</userId></follow_challenge><item><title>与 AMD Ryzen 9955HX Linux 挂起恢复后音频丢失问题的斗智斗勇</title><link>https://maxlen727.github.io/posts/9955hx-linux-suspend-acp-fix/</link><pubDate>Sun, 30 Aug 2026 16:29:27 +0800</pubDate><author>maxlen@duck.com (微恙)</author><guid>https://maxlen727.github.io/posts/9955hx-linux-suspend-acp-fix/</guid><description>&lt;p>这个假期里咱如愿以偿地获得了一台新笔记本，到手之后就被我安装上了 Arch Linux. 那时候的内核版本是&lt;code>7.0.13&lt;/code>. 当时使用的时候一切都近乎完美，体验十分平滑，没有遇到任何跟挂起恢复相关的问题。&lt;/p>
&lt;p>后来随着系统滚动，内核来到了&lt;code>7.1.3&lt;/code>这个版本，在这里遇到了奇怪的挂起恢复问题，表现为：挂起恢复后系统的整个音频堆栈似乎坏掉了，既看不见任何输出/输入设备，浏览器/mpv 在播放音视频时会直接卡死在第一帧。&lt;/p>
&lt;p>遇到这个问题十分郁闷，由于硬件比较新，内核也比较新，导致在网上没有查到很多有效的信息。&lt;/p>
&lt;p>但是现在毕竟是 AI 时代，本来对软件调试不太了解的我也可以在协助下完成一些简单的查错。于是在 Cluade 的帮助下，&lt;del>咱很轻松地发现了问题所在！&lt;/del> 其实是什么也没有收获。这个问题被 AI 工具们归因为 HDA 的一次内核回归。作为一个普通 Linux 用户，咱不希望自己去折腾内核的东西，想要真正解决就只好等上游了。&lt;/p>
&lt;p>通过对 git commit 记录的定位，Claude 发现在&lt;code>7.0.13&lt;/code>到&lt;code>7.1.3&lt;/code>之间，Linux 内核的 HDA 部分发生了一些重构，可能就是这些改动导致了挂起恢复后音频丢失的问题。&lt;/p>
&lt;p>那么第一反应就是想办法 workaround:&lt;/p>
&lt;ol>
&lt;li>重启 WirePlumber、PipeWire、PipeWire-Pulse 这套用户态服务&lt;/li>
&lt;li>不行，那就把内核里的 &lt;code>snd_hda_intel&lt;/code> 模块整个卸载重载一遍&lt;/li>
&lt;/ol>
&lt;p>然而一切尝试的结果都是徒劳无功，最后咱依旧活在这个无声的世界里。&lt;/p>
&lt;p>唉唉，实在是太悲伤了，由于能力有限，本用户所能做的就这些了，只好先降级到&lt;code>7.0.13&lt;/code>继续使用，并把 &lt;code>linux&lt;/code> 包加入了 pacman 的排除列表里。&lt;/p>
&lt;p>但是后来继续更新系统的过程中新问题继续出现：挂起恢复必定失败，屏幕只如一片死寂，比无声的世界还令人恐惧。通过控制变量逐个试验，发现原因是我只锁定了 &lt;code>linux&lt;/code> 包的更新，但是接下来的问题出现在 &lt;code>amd-ucode&lt;/code> 这个包上：&lt;/p>
&lt;p>本来正常的环境是： &lt;code>linux-7.0.13&lt;/code> + &lt;code>amd-ucode-20260622-1&lt;/code> , 这是一套已经经过验证的稳定组合。&lt;/p>
&lt;p>而局部升级之后的情况是 &lt;code>linux-7.0.13&lt;/code> + &lt;code>amd-ucode-20260810-1&lt;/code> , 在这个新的 AMD 微码版本中，为了迎合 &lt;code>7.1&lt;/code> 内核的新变化，挂起恢复方面的行为发生了改变。但是我使用的旧内核并不与之相配。所以这个意料之外的包也需要锁定版本。&lt;/p>
&lt;p>嗯&amp;hellip;&amp;hellip;果然对于滚动发行版来说局部升级是一种很危险的操作。&lt;/p>
&lt;p>后来咱又尝试过几次全量更新，检查挂起恢复的音频问题是否解决，但似乎都没有取得什么进展——问题依旧。&lt;/p>
&lt;p>好吧咱承认我在某些地方有点洁癖——比如一个一直有某个包卡着不能更新的滚动系统。某人开始产生一些胡思乱想：难道我要和这个锁死的内核版本过一辈子吗呜呜，不要口牙！呜呜， &lt;code>7.0.13&lt;/code> 吗？不是已经有很多已知的提权漏洞的版本吗！呜哇，好怕好怕！现在由于锁定了内核版本，导致用不上最新的 AMD 微码包，那万一之后有更多的包也需要锁定版本怎么办？我的 Arch-chan 不就变成了一个半新半旧的怪人了吗，心疼喵（&lt;/p>
&lt;p>&lt;del>这些想法也实在是太怪异了吧！&lt;/del>&lt;/p>
&lt;p>以及在某次尝试全量更新的时候恰恰好还遇到了 &lt;code>nvidia-open&lt;/code> 驱动的同样的回归 bug, 也是和挂起恢复相关的。具体表现为，挂起后无法正常恢复，还会导致机器温度狂飙，风扇啸叫。唉唉，咱确实有些倒霉了。于是 IgnorePKG 再喜添一群 NVIDIA 相关的包。&lt;/p>
&lt;p>可恶&amp;hellip;&lt;/p>
&lt;p>实在是可恶哇！&lt;/p>
&lt;p>好在最近两天去 NVIDIA 仓库的 issue 里盯的时候发现问题似乎修复了，于是咱再次尝试全量更新系统。&lt;/p>
&lt;p>咚咚咚，arch-chan 滚动中&amp;hellip;&lt;/p>
&lt;p>这次更新过去一切似乎都正常了——至少挂起与恢复不再黑屏，只是又让咱进入到了无声世界里面罢了。而此次再寻，咱终于搜索到了一个关键的解决方案：&lt;/p>
&lt;p>&lt;a
href="https://patchew.org/linux/20260606204547.11945-1-david.glushkov%40sntiq.com/"
target="_blank"
>[PATCH] PCI: Disable async suspend for MSI Raider A18 HX A9WJG audio&lt;/a>&lt;/p>
&lt;p>补丁描述揭开了真正的谜底：AMD 的 ACP 和 Azalia/HDA 这两个功能，虽然在 PCI 总线上被暴露成两个独立的 function，却共享着同一套 ACPI 电源门控状态。&lt;/p>
&lt;p>而内核默认允许设备异步恢复——也就是说，挂起恢复时，谁先醒谁后醒是不确定的。当这两个共享着底层电源门控资源的功能&amp;quot;抢跑&amp;quot;，顺序乱掉的那一刻，HDA 控制器就会卡在一个不上不下的半初始化状态里，去读 &lt;code>CORBRP&lt;/code> 寄存器，读回来的永远是全 1——&lt;code>0xffff&lt;/code>，也就是日志里那个看似普通、实则意味深长的 &lt;code>65535&lt;/code>。&lt;/p>
&lt;p>据小 C 告诉咱说：&lt;/p>
&lt;blockquote>
&lt;p>竞态条件最擅长的事，就是让所有基于&amp;quot;日志现象反推&amp;quot;的排查都无功而返，因为它压根不遵循任何一层软件栈自己的逻辑，它只服从谁先抢到总线这一件事。&lt;/p>
&lt;p>这也顺带解释了那个曾经让我们百思不得其解的现象：为什么无论怎么重启 PipeWire、重载 &lt;code>snd_hda_intel&lt;/code> 模块，声音都救不回来，唯独一次完整的冷重启能让一切恢复正常。因为坏掉的从来不是某个用户态缓存或者配置状态，而是 HDA 控制器这个物理 PCI 设备本身，在错误的恢复时序下，变成了一个真正意义上&amp;quot;没有响应&amp;quot;的僵尸。软件层面的任何补救，都够不到 PCI 枚举这个更早、更底层的阶段——只有重启，才能让一切从头再来一遍，赌一把这次的异步恢复顺序恰好没有踩雷。&lt;/p>&lt;/blockquote>
&lt;p>故事的结局也很普通：&lt;/p>
&lt;pre tabindex="0">&lt;code>pm_async=off
&lt;/code>&lt;/pre>&lt;p>给内核加入这行启动参数之后，一切都恢复了正常。ACP 和 HDA 从此老老实实排队醒来，谁也不抢谁的电源门控状态。而关闭异步直觉上可能会让系统恢复变慢，但是对于现代平台来说，其实速度上的变化根本无所感知——就是足够快了。&lt;/p>
&lt;p>以及以及！为什么上文在写到最后发现的解决办法时特意用词“搜索”呢？&lt;/p>
&lt;p>因为那就是咱搜索出来的呀！这是意在表达，咱不再相信 AI 给出的解决方案，而是去寻找 kernel hackers 们是否提供有她们的经验。以后再遇到这种问题，咱一定要自己尝试搜索，而不是只依赖 AI.&lt;/p>
&lt;p>AI First, Not AI Everything ✨&lt;/p>
&lt;hr>
&lt;p>尾巴~&lt;/p>
&lt;p>这次虽然是倾向提供 workaround 的技术文章，但尝试了一些些故事化的写法，希望能让这篇文章既不失实用性，又能提供一点点趣味(≧▽≦)&lt;/p></description></item></channel></rss>