最差的PCIe MSI中断延迟抖动超过100us正常吗?

最差的PCIe MSI中断延迟抖动超过100us正常吗?

我尝试找出 Linux 中中断抖动的值,尤其是在最坏的情况下。考虑了两个测试平台,一个是 Raspberry Pi 4B,另一个是配备 intel i9 CPU 和 ASUS 主板的高端 PC。

   +-+ +-+ +-+     Raspberry Pi 4B
   | | | | | |   -------------+
 --+ +-+ +-+ +-   1. GPIO     |              +--------------+
Signal Generator              |              |              |
                              +----> +-----+ |    Linux     |
                                     | CPU | | ------------ |
                              +----> +-----+ |    Kernel    |
       |  |                   |              |              |
     +-+--+-+     2. PCIe MSI |              +--------------+
   --+ FPGA +--   ------------+
     +-+--+-+      high-end PC (i9-9900K)
       |  |

对于Raspberry Pi,使用输出固定频率方波的信号发生器作为中断源。对于高端PC,采用带有PCIe的Xilinx FPGA板作为中断源,中断类型为MSI。信号发生器和 Xilinx FPGA 板都可以生成时间抖动很小(<1us)的中断。

以下是irq_handler树莓派4B中驱动代码的功能

static irqreturn_t gpio_ts_handler(int irq, void *arg) {

    struct timespec64 timestamp;
    struct gpio_ts_devinfo *devinfo;
    int nwritten;

    ktime_get_real_ts64(&timestamp);   // get the time

    // lock the data fifo and insert the timestamp
    spin_lock(&devinfo->spinlock);
    nwritten = gpio_fifo_write(devinfo->fifo, &timestamp, 1);
    spin_unlock(&devinfo->spinlock);
    if (nwritten != 1) {
        printk(KERN_ERR "GPIOTS: ISR fifo overflow\n");
    }

    // wake up the waiting thread which then read timestamp from the fifo
    wake_up(&devinfo->waitqueue);

    return IRQ_HANDLED;
}

以下是irq_handler高端PC中驱动代码的功能

// IRQ handler
static irqreturn_t fPCI_event_isr (int irq, void *cookie)
{
    struct timespec64 tsc_now = {.tsc_high = 0; .tsc_low = 0};
    struct fPCI_dev *drv_data =  (struct fPCI_dev *) cookie;
    int nwritten;
    int fifo_size;
   
    // get TSC timestamp
    get_tsc_cpuid((tsc_now.tsc_high), (tsc_now.tsc_low));
    spin_lock(&(drv_data->spin_lock));
    nwritten = fpci_fifo_write(drv_data->fifo, &tsc_now, 1);
    spin_unlock(&(drv_data->spin_lock));
    if (nwritten != 1)
        printk(KERN_INFO, "fPCI_event_isr: fifo overflow!\n");
    
    fifo_size = fpci_fifo_size(drv_data->fifo);
    if (fifo_size > FIFO_SIZE/2)
        wake_up(&(drv_data->waitqueue));
    
    return IRQ_HANDLED;
}

在IRQ处理程序的代码中,首先将当前时间存储在FIFO中。然后,用户空间线程从 FIFO 读取时间数据,并对中断的抖动进行计数。结果如下两张图所示。

在此输入图像描述

在此输入图像描述

我的问题是:

1 为什么 PCIe MSI 中断比 GPIO 中断具有更大的延迟抖动?

2 现代 PCIe MSI 中断在最坏的情况下有大约 100us 的延迟变化是否正常(有什么我错过的吗)?如何最大限度地减少延迟(抖动)的这种变化。

相关内容