PCIe (PCI Express) 中的 Completion Timeout 是一个重要的错误检测机制。
一、基本概念
- Completion Timeout 是 PCIe 事务完成的超时机制
- 当发起方发送请求后,在规定时间内没有收到完成包(Completion)就会触发超时
- 这是 PCIe 协议中的一个保护机制
二、主要功能
// 典型的超时处理示例
struct pci_dev *pdev;
int timeout_value;
// 设置超时值
pci_write_config_word(pdev,
PCI_COMPLETION_TIMEOUT_REGISTER,
timeout_value);
// 检查超时状态
u16 status;
pci_read_config_word(pdev, PCI_STATUS, &status);
if (status & PCI_STATUS_COMPLETION_TIMEOUT) {
// 处理超时错误
}
三、超时值范围
- 最小值:50微秒(50us)
- 最大值:50毫秒(50ms)
- 可编程范围值:
- 50us - 100us
- 1ms - 10ms
- 16ms - 55ms
- 等等
四、常见原因
- 目标设备无响应
- 系统总线拥塞
- 设备故障
- 配置错误
- 驱动程序问题
五、处理机制
// PCIe设备驱动中的超时处理示例
static irqreturn_t pcie_error_handler(int irq, void *dev_id)
{
struct pci_dev *pdev = (struct pci_dev *)dev_id;
u32 status;
// 读取错误状态
pcie_capability_read_dword(pdev, PCI_EXP_DEVSTA, &status);
if (status & PCI_EXP_DEVSTA_CED) { // Completion Timeout
// 1. 记录错误
dev_err(&pdev->dev, "Completion Timeout detected\n");
// 2. 重置设备
pci_reset_function(pdev);
// 3. 重新初始化设备
reinit_device(pdev);
// 4. 清除错误状态
pcie_capability_write_dword(pdev, PCI_EXP_DEVSTA,
PCI_EXP_DEVSTA_CED);
}
return IRQ_HANDLED;
}
六、预防措施
- 合理设置超时值
- 实现错误恢复机制
- 监控系统性能
- 定期检查设备状态
七、配置示例
// 设置和配置Completion Timeout
static int configure_completion_timeout(struct pci_dev *pdev)
{
u16 ctl2;
// 读取当前配置
pcie_capability_read_word(pdev, PCI_EXP_DEVCTL2, &ctl2);
// 设置新的超时值
ctl2 &= ~PCI_EXP_DEVCTL2_COMP_TIMEOUT;
ctl2 |= PCI_EXP_DEVCTL2_COMP_TIMEOUT_50MS; // 设置为50ms
// 写回配置
pcie_capability_write_word(pdev, PCI_EXP_DEVCTL2, ctl2);
return 0;
}
八、监控和调试
// 监控PCIe设备状态
static void monitor_pcie_device(struct pci_dev *pdev)
{
u16 status, control;
// 读取设备状态
pci_read_config_word(pdev, PCI_STATUS, &status);
pci_read_config_word(pdev, PCI_COMMAND, &control);
dev_info(&pdev->dev,
"PCIe Status: 0x%04x, Control: 0x%04x\n",
status, control);
if (status & PCI_STATUS_COMPLETION_TIMEOUT) {
dev_warn(&pdev->dev, "Completion Timeout detected\n");
// 实现恢复逻辑
}
}
九、最佳实践
- 根据设备特性选择合适的超时值
- 实现完整的错误处理机制
- 记录和监控超时事件
- 定期维护和检查设备状态
- 在驱动程序中实现自动恢复机制
这个机制对于保证 PCIe 设备的可靠运行非常重要,需要在驱动开发中特别注意。