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

作者:
版权:

© 2006 Intel Corporation

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能力的根端口和RCECs。

8.2. 用户指南

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

PCIe AER驱动程序是通过PCIe端口总线驱动程序附着的根端口服务驱动程序。如果用户想使用它,必须编译该驱动程序。它通过CONFIG_PCIEAER启用,而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

在示例中,'Requester ID'表示向根端口发送错误消息的设备的ID。其他字段请参考PCIe规范。

8.2.4. AER速率限制

由于每次事务都可能生成错误消息,我们可能会看到大量错误报告。为了防止垃圾设备泛滥控制台/阻塞执行,消息会按设备和错误类型(可纠正错误与非致命不可纠正错误)进行节流。致命错误,包括DPC错误,不受速率限制。

AER使用DEFAULT_RATELIMIT_BURST(10个事件)在DEFAULT_RATELIMIT_INTERVAL(5秒)内的默认速率限制。

速率限制以sysfs属性的形式公开并可配置。请参阅ABI file testing/sysfs-bus-pci-devices-aer

8.2.5. AER统计/计数器

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

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()函数的callback参数提供复位链路的功能。如果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的更多信息可以在其源代码文档中找到。