【问题标题】:Linux PCIe driver has periodic long latency for MSILinux PCIe 驱动程序对 MSI 有周期性的长延迟
【发布时间】: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


【解决方案1】:

您可以在 spin_lock 前后添加计时器。如果时间差超过某个阈值,则增加另一个时间。您会计算由于 spin_lock 导致延迟的频率。如果它与您看到延迟的频率相匹配,那么您可以尝试找出其他锁持有者不释放它的原因。它可以在持有锁时被抢占吗?

要研究的另一件事是 spin_lock 本身是否应该以较低但不为零的概率花费很长时间?

【讨论】:

  • 定时器的想法很有趣,但它不适用于我的应用程序,因为 MSI 在数据准备好时到达,所以当数据准备好时,我需要在 CPU 和 FPGA 之间进行某种“握手”。尽管我正在考虑使用您的计时器想法来查看 spin_lock 是否会被抢占。我对spin_lock了解不多,但我认为它对抢占免疫。
  • 我的意思是另一个持有锁的线程可能在持有锁时被抢占。至于另一个建议, spin_lock 平均速度很快。但它有一个非零方差(因为它在旋转)。这意味着它有可能(可能性很小)花费的时间超过您可以忍受的时间。
猜你喜欢
  • 1970-01-01
  • 2019-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
相关资源
最近更新 更多