【发布时间】:2017-02-11 04:41:03
【问题描述】:
我已经为 Linux v4.1.15(非 PREEMPT_RT)创建了一个 PCIe 驱动程序,该驱动程序具有一个从 FPGA 的 MSI 生成的 IRQ。我的 ISR 是:
static irq_handler int_handler(int irq, void* dev_id, struct pt_regs* regs)
{
spin_lock(&my_lock);
msi_counter++;
spin_unlock(&my_lock);
return (irq_handler_t) IRQ_HANDLED;
}
从 FPGA (Cyclone V) 每 300 us 发送一次 MSI,我的 ISR 会非常快速地触发,并且不会失败(延迟 msi_counter 的 spin_lock 仅在我的代码中的其他位置使用,但仅用于以与 ISR 递增计数器相同的方式递减计数器。我正在使用 1 GHz 的 iMX6 四核 CPU,并且系统使用的是准系统 Yocto 映像(core-image-minimal),因此 CPU 上没有真正运行任何东西。 CPU 唯一连接的其他硬件是以太网,但发送的数据非常少,并且数据更新频率超过 3 秒。
问题:
- 我如何确定为什么 Linux 会周期性地增加延迟 我的 ISR?
- 我可以做些什么来减少延迟?
其他信息:
我已将传递给
request_irq()的标志更改为IRFQ_NO_SUSPEND | IRFQ_NO_THREAD,以及其他值,但似乎没有任何问题 这种周期性的延迟增加。另外,当我查看
cat /proc/interrupts时,它显示只有核心 0 (四个核心中的第一个)是运行 ISR 的唯一核心。一世 不知道这是否有任何意义,但我认为这是值得的 提到。- 从 FPGA 到 CPU 的数据每 MSI 传输一次(每 300 us 一次),传输数据的时间稳定为 17 us。从来没有数据从 CPU 发送到 FPGA。
最终解决方案:
我创建了一个 PREEMPT_RT 内核映像并创建了带有标志 IRQF_NO_SUSPEND | IRQF_NO_THREAD | IRQF_PERCPU 的 ISR request_irq()。我还用atomic_t 替换了spin_lock,很大的改进来自PREEMPT_RT。我现在的平均延迟约为 12 我们。
【问题讨论】:
-
如果您只需要 Inc 和 dec,您可以使用
atomic类型来避免自旋锁。也可以尝试删除自旋锁以查看延迟是否存在或在等待运行的 IRQ 处理程序中。然后考虑使用 ftrace 或 LTTng 来查看在处理 IRQ 之前运行的内容。 -
@TrentP - 当我有机会的时候,我会给这两个机会。你认为
spin_lock真的是问题所在吗?我认为spin_lock速度很快,不会导致 ISR 进入休眠状态。
标签: linux latency pci-e irq isr