返回首页

snd_hda_intel 声音回归问题:PCI 重新扫描修复

snd_hda_intel 回归问题的分析:内核更新后 Intel HDA 上的 CORB 重置超时。通过 dmesg 诊断,解决方案 — 通过 sysfs 的 PCI 重新扫描并重新分配 BAR。针对旧硬件的自动化和调试提示。

如何修复声音:针对内核回归的 PCI 重新扫描
Advertisement 728x90

# 修复 snd_hda_intel 回归问题:PCI 重扫描恢复老笔记本音频

在我的 Emachines E732 笔记本上更新内核后,Intel 5 系列/3400 系列 HDA(芯片 ID 8086:3b56)的音频突然消失。aplay -l 显示“未找到声卡”。lspci 能看到设备在 00:1b.0,inxi -Axxz 确认是 snd_hda_intel 驱动,但 journalctl 满是错误:hdaudio hdaudioC0D0: no AFG or MFG node found,所有节点都报错。

dmesg 揭示真相:初始化时出现 snd_hda_intel 0000:00:1b.0: CORB reset timeout#2, CORBRP = 65535,随后是 no codecs initialized。CORB(命令输出环形缓冲区)是编解码器命令的环形缓冲区,0xFFFF 值表示总线挂起或硬件不可访问——读取未初始化的寄存器。

冷启动时的 BAR:mem 0xd4400000-0xd4403fff 64bit。重新加载模块(modprobe -r/-a snd_hda_intel)会重复错误,新时间戳。

Google AdInline article slot

无效的快速修复

常规调整完全没用:

  • 用户空间工具:重装 PipeWire/WirePlumber,调整 alsamixer——没有 ALSA 设备,一切白搭。
  • 模块选项:在 /etc/modprobe.d/alsa-fix.conf 中添加 options snd-hda-intel enable=1 power_save=0 power_save_controller=N model=auto
  • GRUB 参数pci=nocrs pci=nomsi pcie_aspm=off snd_hda_intel.power_save=0 snd_hda_intel.dma_mask=0
  • 热重载modprobe snd_hda_intel msi=0 dsp_driver=1 probe_mask=1

问题出在早期初始化:LTS 内核或 LiveCD 能工作,是因为模块加载顺序或 BIOS 状态不同。

[   17.492159] snd_hda_intel 0000:00:1b.0: CORB reset timeout#2, CORBRP = 65535
[   17.492380] snd_hda_intel 0000:00:1b.0: no codecs initialized

解决方案:通过 sysfs 执行 PCI 热重扫描

关键洞察:冷启动分配了错误的 BAR,但系统暖机后的热重扫描有效。步骤如下:

Google AdInline article slot
  • echo 1 | sudo tee /sys/bus/pci/devices/0000:00:1b.0/remove
  • sleep 2
  • echo 1 | sudo tee /sys/bus/pci/rescan

新的 dmesg 输出:

[  473.969035] pci 0000:00:1b.0: [8086:3b56] ... 
[  473.969102] pci 0000:00:1b.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
[  473.969982] pci 0000:00:1b.0: BAR 0 [mem 0x23c000000-0x23c003fff 64bit]: assigned
[  474.095498] input: HDA Intel MID Mic as /devices/pci0000:00/0000:00:1b.0/sound/card0/input24
[  474.095675] input: HDA Intel MID Headphone as /devices/pci0000:00/0000:00:1b.0/sound/card0/input25

音频恢复:声卡出现在 /dev/snd,PipeWire 检测到设备。罪魁祸首?BIOS 早期提供无效参数;PCI 初始化完成后重扫描分配正确 BAR。

日常自动化

生产环境 systemd 脚本(开机后执行):

Google AdInline article slot
#!/bin/bash
PCI_ID="0000:00:1b.0"
echo 1 > /sys/bus/pci/devices/$PCI_ID/remove
sleep 2
echo 1 > /sys/bus/pci/rescan
# 验证
if aplay -l | grep -q "card 0"; then
    systemctl --user restart pipewire pipewire-pulse wireplumber
fi

放入 /etc/systemd/system/pci-audio-rescan.service,设置 After=multi-user.target

诊断类似回归问题

针对旧 Intel HDA 的 snd_hda_intel:

  • 收集日志dmesg | grep '00:1b.0'journalctl -b -p err | grep hda
  • 检查 BARlspci -vv -s 00:1b.0 | grep BAR
  • 测试重扫描:使用上述 sysfs 方法。
  • 对比内核:LTS vs 主线——PCI 分配或电源管理回归。
  • BIOS/UEFI:有更新就试试,不过 2010 时代芯片组很少有效。

内核 6.8+ 后,老硬件深受其害:PCI 枚举和 ASPM 变更。

关键要点

  • CORBRP=0xFFFF 表示 HDA 控制器卡住,不是 BIOS/编解码器问题。
  • sysfs PCI 重扫描 绕过冷启动超时,重新分配 BAR。
  • LTS 内核 成功是因为时机:模块在 BIOS 接管后加载。
  • 自动化:systemd 服务确保日常使用可靠。
  • 诊断:关注 dmesg 而非用户空间;聚焦 PCI BAR 和 CORB/RIRB。

— Editorial Team

Advertisement 728x90

继续阅读