8. PCI Express 高级错误报告驱动程序指南 HOWTO

作者:
版权:

© 2006 英特尔公司

8.1. 概述

8.1.1. 关于本指南

本指南描述了 PCI Express (PCIe) 高级错误报告 (AER) 驱动程序的基础知识,并提供有关如何使用它以及如何使端点设备的驱动程序符合 PCIe AER 驱动程序的信息。

8.1.2. 什么是 PCIe AER 驱动程序?

PCIe 错误信号可能发生在 PCIe 链路本身或代表在链路启动的事务。PCIe 定义了两种错误报告范例:基线能力和高级错误报告能力。所有 PCIe 组件都必须具备基线能力,提供一组最小定义的错误报告要求。高级错误报告能力通过 PCIe 高级错误报告扩展能力结构实现,提供更强大的错误报告。

PCIe AER 驱动程序提供支持 PCIe 高级错误报告能力的基础设施。PCIe AER 驱动程序提供三个基本功能

  • 如果发生错误,收集全面的错误信息。

  • 向用户报告错误。

  • 执行错误恢复操作。

AER 驱动程序仅附加到支持 PCIe AER 能力的根端口和 RCEC。

8.2. 用户指南

8.2.1. 将 PCIe AER 根驱动程序包含到 Linux 内核中

PCIe AER 驱动程序是通过 PCIe 端口总线驱动程序附加的根端口服务驱动程序。如果用户想要使用它,必须编译该驱动程序。它通过 CONFIG_PCIEAER 启用,而这又依赖于 CONFIG_PCIEPORTBUS。

8.2.2. 加载 PCIe AER 根驱动程序

某些系统在固件中支持 AER。如果固件处理 AER 的同时启用 Linux AER 支持,将导致不可预测的行为。因此,除非固件通过 ACPI _OSC 方法将 AER 控制权授予操作系统,否则 Linux 不会处理 AER 事件。有关 _OSC 用法的详细信息,请参阅 PCI 固件规范。

8.2.3. AER 错误输出

当捕获到 PCIe AER 错误时,错误消息将输出到控制台。如果它是可纠正的错误,则会作为信息消息输出。否则,它会作为错误打印。因此,用户可以选择不同的日志级别来过滤掉可纠正的错误消息。

下面显示一个示例

0000:50:00.0: PCIe Bus Error: severity=Uncorrected (Fatal), type=Transaction Layer, id=0500(Requester ID)
0000:50:00.0:   device [8086:0329] error status/mask=00100000/00000000
0000:50:00.0:    [20] Unsupported Request    (First)
0000:50:00.0:   TLP Header: 04000001 00200a03 05010000 00050100

在示例中,“请求者 ID”表示将错误消息发送到根端口的设备的 ID。有关其他字段,请参阅 PCIe 规范。

8.2.4. AER 统计信息/计数器

当捕获到 PCIe AER 错误时,计数器/统计信息也会以 sysfs 属性的形式公开,这些属性记录在 Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats 中

8.3. 开发人员指南

要启用错误恢复,软件驱动程序必须提供回调。

为了更好地支持 AER,开发人员需要了解 AER 的工作原理。

PCIe 错误分为两种类型:可纠正错误和不可纠正错误。这种分类基于这些错误的影响,这些错误可能导致性能下降或功能故障。

可纠正错误不会对接口的功能产生影响。PCIe 协议可以恢复,无需任何软件干预或任何数据丢失。这些错误由硬件检测和纠正。

与可纠正错误不同,不可纠正错误会影响接口的功能。不可纠正错误会导致特定事务或特定 PCIe 链路不可靠。根据这些错误情况,不可纠正错误进一步分为非致命错误和致命错误。非致命错误导致特定事务不可靠,但 PCIe 链路本身功能齐全。另一方面,致命错误会导致链路不可靠。

启用 PCIe 错误报告后,当设备捕获到错误时,会自动向其上方的根端口发送错误消息。根端口在接收到错误报告消息后,会在其内部处理错误消息并将其记录在 AER 能力结构中。记录的错误信息包括将错误报告代理的请求者 ID 存储到错误源识别寄存器中,并相应地设置根错误状态寄存器的错误位。如果在根错误命令寄存器中启用了 AER 错误报告,则当检测到错误时,根端口会生成中断。

请注意,上述错误与 PCIe 层次结构和链路相关。这些错误不包括任何设备特定的错误,因为设备特定的错误仍然会直接发送到设备驱动程序。

8.3.1. 提供回调

8.3.1.2. PCI 错误恢复回调

PCIe AER 根驱动程序使用错误回调来协调与执行错误恢复操作时关联的层次结构中的下游设备驱动程序。

数据 struct pci_driver 有一个指针 err_handler,指向 pci_error_handlers,后者由几个回调函数指针组成。AER 驱动程序遵循 PCI 错误恢复 中定义的规则,除了 PCIe 特定的部分(例如 reset_link)。有关回调的详细定义,请参阅 PCI 错误恢复

以下部分指定何时调用错误回调函数。

8.3.1.3. 可纠正错误

可纠正错误不会对接口的功能产生影响。PCIe 协议可以恢复,无需任何软件干预或任何数据丢失。这些错误不需要任何恢复操作。AER 驱动程序会相应地清除设备的可纠正错误状态寄存器并记录这些错误。

8.3.1.4. 不可纠正(非致命和致命)错误

如果错误消息指示非致命错误,则不需要在上游执行链路重置。AER 驱动程序会调用 error_detected(dev, pci_channel_io_normal) 给相关层次结构中的所有驱动程序。例如

Endpoint <==> Downstream Port B <==> Upstream Port A <==> Root Port

如果上游端口 A 捕获到 AER 错误,则层次结构由下游端口 B 和端点组成。

驱动程序可能会返回 PCI_ERS_RESULT_CAN_RECOVER、PCI_ERS_RESULT_DISCONNECT 或 PCI_ERS_RESULT_NEED_RESET,具体取决于它是否可以恢复或 AER 驱动程序是否接下来调用 mmio_enabled。

如果错误消息指示致命错误,则内核会将 error_detected(dev, pci_channel_io_frozen) 广播给相关层次结构中的所有驱动程序。然后,必须在上游执行链路重置。由于不同类型的设备可能会使用不同的方法来重置链路,因此需要 AER 端口服务驱动程序通过 pcie_do_recovery() 函数的回调参数来提供重置链路的功能。如果 reset_link 不为 NULL,则恢复函数将使用它来重置链路。如果 error_detected 返回 PCI_ERS_RESULT_CAN_RECOVER 并且 reset_link 返回 PCI_ERS_RESULT_RECOVERED,则错误处理将转到 mmio_enabled。

8.3.2. 常见问题解答

如果 PCIe 设备驱动程序未提供错误恢复处理程序(pci_driver->err_handler 等于 NULL)会发生什么?

连接到该驱动程序的设备将不会恢复。如果错误是致命的,则内核将打印出警告消息。有关更多信息,请参阅第 3 节。

如果上游端口服务驱动程序未提供回调 reset_link 会发生什么?

如果错误是由附加服务驱动程序的上游端口报告的,则致命错误恢复将失败。

8.4. 软件错误注入

调试 PCIe AER 错误恢复代码非常困难,因为很难触发真实的硬件错误。基于软件的错误注入可以用来伪造各种类型的 PCIe 错误。

首先,您应该在内核配置中启用 PCIe AER 软件错误注入,也就是说,您的 .config 中应该包含以下项。

CONFIG_PCIEAER_INJECT=y 或 CONFIG_PCIEAER_INJECT=m

使用新内核重启或插入模块后,应该会创建一个名为 /dev/aer_inject 的设备文件。

然后,您需要一个名为 aer-inject 的用户空间工具,可以从以下地址获取:

有关 aer-inject 的更多信息可以在其源代码中的文档中找到。