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