带宽与速度

常见原因:

  • 链路两端的 Max Link Speed 不匹配(RC 或 EP 能力不足)
  • 均衡失败后自动降速
  • BIOS/UEFI 设置中限制了 PCIe 速率
  • 信道质量不满足高速要求

排查步骤:

  • 查看 Link Capabilities 寄存器确认双方最大支持速率
  • 查看 Link Status 确认当前协商速率
  • 检查 BIOS 中的 PCIe 速率限制设置
  • 查看内核日志是否有降速记录
  • 确认信道插入损耗是否满足 Gen5 要求(36dB)
lspci -s 03:00.0 -vvv | grep -i "LnkCap\|LnkSta\|LnkCtl" dmesg | grep -i "pcie\|pci.*link"

常见原因:

  • 插槽物理 Lane 数不足(如 x16 插槽实际只接了 x8)
  • RC 端 Lane Reversal 或 Lane Bifurcation 配置
  • BIOS 将 x16 拆分为 x8+x8(用于多 GPU)
  • Configuration 状态下 Lane 协商失败

排查步骤:

  • 查看 Link Capabilities 确认设备支持的最大宽度
  • 查看 Link Status 确认协商的宽度
  • 检查 BIOS 中的 Bifurcation 设置
  • 查看主板规格确认插槽的物理 Lane 连接数
lspci -s 03:00.0 -vvv | grep "Width\|LnkCap\|LnkSta"

使用 带宽计算器 估算不同宽度下的带宽。

原因:ASPM 的 L0s/L1 省电状态会增加链路恢复延迟。某些设备对延迟敏感(如 NVMe、高频交易网卡)。

解决方案:

  • 通过 Link Control 寄存器禁用 ASPM
  • 内核启动参数 pcie_aspm=off 全局禁用
  • 或使用 pcie_aspm=performance 强制性能模式
  • 对延迟不敏感的设备保持 ASPM 开启以省电
lspci -s 03:00.0 -vvv | grep -i "aspm\|L0s\|L1"

错误处理

AER 错误分为可纠正和不可纠正两类:

可纠正错误(Correctable)通常不致命,设备可自动恢复:

  • Receiver Error → 物理层信号质量问题
  • Bad TLP → TLP 的 LCRC 校验失败
  • Replay Timer Timeout → Ack 超时触发重传

不可纠正错误(Uncorrectable)需要关注:

  • 非致命:Poisoned TLP、Completion Timeout、Unsupported Request
  • 致命:Data Link Protocol Error、Receiver Overflow、Malformed TLP

查看 AER 状态:

lspci -s 03:00.0 -vvv | grep -A 20 "Advanced Error" dmesg | grep -i "aer\|pcie.*error"

详细错误码对照见 速查表 AER 部分错误处理详解

排查步骤:

  • 从 dmesg 中提取完整的 AER 错误信息(包含设备 BDF、错误类型、错误位)
  • 确认错误来源设备:lspci -s <BDF> -vvv
  • 根据错误位对照 AER 错误码速查
  • 如果是 Correctable Error 且偶发,可能是信号完整性问题
  • 如果是 Uncorrectable Fatal Error,需要检查驱动是否正确处理了错误恢复
  • 使用 AER 注入测试验证错误恢复逻辑:modprobe aer_inject 后配合用户态 aer-inject 工具(见 Documentation/PCI/pcieaer-howto.rst

配置与资源

常见原因:

  • BIOS/UEFI 可分配的 MMIO 空间有限
  • GPU 等大 BAR 设备需要的空间超过 BIOS 预留(如 GPU 需要 256MB+ BAR)
  • 32 位地址空间耗尽(需启用 64 位 BAR)
  • BIOS 未给 BAR 预留足够窗口时,需要 pci=realloc 强制重新分配(不存在 pci=hugepages 参数)

解决方案:

  • 在 BIOS 中启用 "Above 4G Decoding" 或 "64-bit MMIO"
  • 启用 Resizable BAR(如果设备支持)
  • 内核启动参数添加 pci=realloc 强制重新分配
  • 检查 BAR 大小:lspci -s 03:00.0 -vvv | grep Region
lspci -s 03:00.0 -vvv | grep -i "region\|bar\|memory"

常见原因:

  • 设备未启用 Bus Master 和 Memory Space(Command 寄存器)
  • MSI-X Capability 中的 Table Size 和 BIR 配置不正确
  • 驱动未正确使用 pci_alloc_irq_vectors()
  • IOMMU 配置阻止了中断传递
  • 内核中断描述符表空间不足

排查步骤:

  • 确认 Command 寄存器 bit 2 (Bus Master) 和 bit 1 (Memory Space) 已置位
  • 查看 MSI-X Capability:lspci -s 03:00.0 -vvv | grep -A 10 "MSI-X"
  • 检查内核日志:dmesg | grep -i "msi\|irq"
  • 确认驱动使用现代 API:pci_alloc_irq_vectors(dev, min, max, PCI_IRQ_MSIX)
  • 检查 /proc/interrupts 确认中断是否注册成功

更多见 设备驱动开发 中的中断处理章节

排查步骤(从硬件到软件):

  • 确认设备已正确物理插入(金手指是否完全插入插槽)
  • 确认电源正常(设备 LED 指示灯状态)
  • 检查 PERST# 信号是否正确释放
  • 确认枚举是否成功:lspci -t 查看总线拓扑
  • 检查 ECAM 地址映射是否覆盖了该 Bus 号
  • 查看内核枚举日志:dmesg | grep -i "pci"
  • 如果是热插拔设备,检查 Hot-plug controller 是否正常
  • 尝试手动触发重新枚举:echo 1 > /sys/bus/pci/rescan

可以通过以下方式控制链路速率:

  • BIOS 设置:在 BIOS/UEFI 中设置最大 PCIe 速率
  • 内核参数pcie_aspm=performance 优化性能
  • sysfs:通过 Link Control 寄存器的 Target Link Speed 字段设置
lspci -s 03:00.0 -vvv | grep "LnkCtl2"

修改 Target Link Speed 后,需要触发链路重训:

setpci -s 03:00.0 CAPID+0x30.L=0x... # 设置 Target Link Speed setpci -s 03:00.0 CAPID+0x10.B=0x40 # Retrain Link bit

注意:强制降速可用于排查高速信号问题。如果设备在 Gen3 下正常但 Gen5 下失败,通常是信道质量问题。

调试工具使用

lspci # 列出所有PCI设备 lspci -vvv # 完整详情(含配置空间) lspci -nn # 显示Vendor:Device ID lspci -t # 总线拓扑树 lspci -s 03:00.0 -vvv # 指定设备详情 lspci -xxxx -s 03:00.0 # dump完整4KB配置空间 lspci -d ::0x0200 # 按Class筛选

更多命令见 速查表

抓取 PCIe 数据包需要硬件协议分析仪,常见选项:

  • Teledyne LeCroy Summit 系列:支持 Gen5/Gen6 抓包
  • Keysight U4310A:支持 Gen4 协议分析
  • SerialTek:支持 Gen5 协议分析

软件层面可以查看:

  • 配置空间寄存器值:lspci -xxxx
  • 内核 PCIe trace:echo 1 > /sys/kernel/debug/tracing/events/pci/enable
  • 使用 TLP 构造器 理解包结构

FAQ 持续更新中。如有其他常见问题,欢迎反馈。