Linux PCIe驱动程序具有MSI的定期长延迟

时间:2017-02-11 04:41:03

标签: linux latency pci-e irq isr

我已经为Linux v4.1.15(非PREEMPT_RT)创建了一个PCIe驱动程序,其中只有一个IRQ,它是从FPGA的MSI生成的。我的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;
}

MSI每隔300 us从FPGA(Cyclone V)发送一次,我的ISR非常快速地被触发并且处理时没有失败(延迟<5 us)。问题是大约每隔3秒(抖动相对较小的3秒),我的ISR的延迟会跳到大约1.5毫秒到2毫秒;这是通过改变我的ISR来测量范围,将值写回FPGA并监控来自FPGA的引脚。 spin_lock的{​​{1}}仅用于我的代码中的另一个位置,但仅用于递减计数器,就像我的ISR递增它一样。我正在使用1 GHz的iMX6四核CPU,系统正在使用简单的Yocto映像(核心映像最小),因此CPU上没有真正运行的东西。 CPU连接的唯一其他硬件是以太网,但发送的数据非常少,数据更新频率超过3秒。

问题:

  • 如何确定Linux为何会定期增加延迟 我的ISR?
  • 我可以做些什么来减少延迟?

其他信息:

  • 我已将传递给msi_counter的标记更改为request_irq()以及其他值,似乎没有任何修复 这种周期性延迟增加。

  • 此外,当我查看IRFQ_NO_SUSPEND | IRFQ_NO_THREAD时,它显示只有核心0 (四个核心中的第一个)是我的ISR运行的唯一核心。一世 不知道这是否有任何意义,但我认为这是值得的 提。

  • 每个MSI传输一次从FPGA到CPU的数据(每300 us一次),传输数据的时间稳定在17 us。没有数据从CPU发送到FPGA。

最终解决方案:

我创建了一个PREEMPT_RT内核映像,并使用标记cat /proc/interrupts创建了我的ISR request_irq()。我还将IRQF_NO_SUSPEND | IRQF_NO_THREAD | IRQF_PERCPU替换为spin_lock,改进来自PREEMPT_RT。我现在的平均延迟时间约为12 us。

1 个答案:

答案 0 :(得分:0)

您可以在spin_lock之前和之后添加计时器。如果时间差异超过某个阈值,则再增加一次。你可以计算延迟是由spin_lock造成的。如果它与您看到延迟的频率相匹配,那么您可以尝试找出其他锁定持有者不释放它的原因。拿着锁可以抢先一步吗?

另一件需要关注的事情是,spin_lock本身需要很长时间才能获得低但非零的概率吗?