我正在编写一个通过PCIe与Altera FPGA通信的Linux驱动程序。 FPGA支持MSI和MSIx中断。通常,MSI中断似乎工作正常,但是,MSIx中断似乎在某些计算机上运行,而在其他计算机上运行。
经过大量的搜索和反复试验后,我能够重现MSIx中断的问题,而这些中断在以前工作的计算机上无法正常工作。我通过在内核中禁用中断重映射(将intremap=off
传递给内核)来完成此操作。
鉴于我是PCIe驱动程序的新手,这是预期的行为吗?
在我的驱动程序中,我通过调用:
来设置MSI-Xif ((rc = pci_enable_msix_exact(pdev, irqs, NUM_IRQS)) < 0)
printk(KERN_ERR "MSIX ENABLE FAILED: %d\n" rc);
...
for (i = 0; i < NUM_IRQS; ++i) {
irqs[i].entry = i;
rc = devm_request_irq(&pdev->dev, irqs[i].vector, irq_handler,
0, "my_driver", NULL);
if (rc)
printk(KERN_ERR "Failed to request irq: %d\n", i);
}
无论是否启用了中断重映射,此代码都可以工作(不会返回错误)。但是,只有在启用中断重映射时才会调用irq_handler
。
硬件上的MSI-X表根据是否启用了中断重映射而有所不同。
例如,当启用重映射时,表格如下所示:
Vector Ctrl Msg Data Msg Upper Addr Msg Addr
+---------------+---------------+---------------+---------------+
| 0x00000000 | 0x00000000 | 0x00000000 | 0xFEE00618 |
+---------------+---------------+---------------+---------------+
| 0x00000000 | 0x00000001 | 0x00000000 | 0xFEE00618 |
+---------------+---------------+---------------+---------------+
| 0x00000000 | 0x00000002 | 0x00000000 | 0xFEE00618 |
+---------------+---------------+---------------+---------------+
禁用重新映射(intremap=off
)时,它看起来像这样:
Vector Ctrl Msg Data Msg Upper Addr Msg Addr
+---------------+---------------+---------------+---------------+
| 0x00000000 | 0x00004153 | 0x00000000 | 0xFEE0F00C |
+---------------+---------------+---------------+---------------+
| 0x00000000 | 0x00004163 | 0x00000000 | 0xFEE0F00C |
+---------------+---------------+---------------+---------------+
| 0x00000000 | 0x00004173 | 0x00000000 | 0xFEE0F00C |
+---------------+---------------+---------------+---------------+
这里发生了什么? FPGA会出现问题吗?如果在两种情况下看起来都没有问题,驱动程序如何知道MSI-X中断是否会起作用?任何帮助我引导我朝正确方向前进的帮助都会受到高度赞赏。