MSI 中断如何在 linux 驱动程序中工作?
Posted
技术标签:
【中文标题】MSI 中断如何在 linux 驱动程序中工作?【英文标题】:How does MSI interrupt work in linux driver? 【发布时间】:2016-08-15 21:47:36 【问题描述】:目前正在开发 PCI 设备驱动程序。该设备的编程如下: 当 DMA 传输完成时,设备会向 PC 发送一个 MSI 中断,其中包含 MSI 数据“001”二进制。
现在我正在为这个 pci 设备编写驱动程序,对于 MSI 部分,我有一些问题。
在***中,它说:
MSI 允许设备将少量中断描述数据写入特殊的内存映射 I/O 地址,然后芯片组将相应的中断传递给处理器。
Q1:所以在我的情况下,small amount of interrupt-describing data
是从 pci 设备发送到 PC 的"001"
?
在我的驱动程序代码中,MSI irq 是这样注册的:
err = pci_enable_msi(my_pci_dev);
err = request_irq(my_pci_dev->irq, irq_handler, 0, "PCI_FPGA_CARD", NULL);
irq_handler
的定义如下:
static irqreturn_t irq_handler(int irq, void *dev_id)
printk(KERN_INFO "(irq_handler): Called\n");
return IRQ_HANDLED;
Q2:有了上面的3个内核函数,我们如何才能得到消息"001"
?
Q3:PCI 设备最多支持 8 个 MSI 向量,所以要使用所有这 8 个向量,我应该在下面使用哪个代码或者都不正确:
err = pci_enable_msi_block(my_pci_dev,8);
err = request_irq(my_pci_dev->irq, irq_handler, 0, "PCI_FPGA_CARD", NULL);
或
err = pci_enable_msi(my_pci_dev);
err = request_irq(my_pci_dev->irq, irq_handler_0, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_1, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_2, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_3, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_4, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_5, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_6, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_7, 0, "PCI_FPGA_CARD", NULL);
3 个问题 ~~ 感谢您的帮助。
【问题讨论】:
Q1:您似乎没有从您发布的引用中得到任何线索。 MSI 由 PCI 根主机处理,它将中断作为消息传递到特定的内存地址。此地址对您隐藏。 Q2:因此,您根本不必关心这些。 Q3:如果您的向量很少,您需要在 PCI 配置空间中正确定义它们。您需要使用_msi_range()
类型的函数来处理 MSI。在请求 IRQ 中,您必须从一组中选择正确的 IRQ 行号。
【参考方案1】:
迟到的答案。希望它仍然有帮助。
A1:是的。 MSI 是从设备到 CPU 的已发布内存写入。 TLP 以 CPU 分配的 MSI 地址为目标,有效载荷是 MSI DATA,在本例中为“001”。地址和数据(偏移)组合定义了一个唯一的中断向量。所以对于不同的“数据”,你可以有多个中断和处理程序。
A2:通常你不需要它。以下来自***。
对 MSI 的一个常见误解是它允许设备发送 作为中断的一部分将数据发送到处理器。发送的数据为 内存写入事务的一部分由芯片组用于 确定在哪个处理器上触发哪个中断;该数据是 设备无法将其他信息传达给 中断处理程序。
如果您仍然好奇,请检查 MSI 能力的 MSI DATA 寄存器。它可能包含“001”,但我尚未验证。无论如何,这个“001”应该与 ISR 无关。
A3:您应该注册多个处理程序。使用 MSI,您有一个连续的向量,MSI-X 为每个中断向量提供了一个单独的地址和数据表。
对于 MSI:
request_irq(my_pci_dev->irq, irq_handler_0, ...);
request_irq(my_pci_dev->irq + 1, irq_handler_1, ...);
request_irq(my_pci_dev->irq + 2, irq_handler_2, ...);
对于 MSI-X:
request_irq(my_pci_dev->pMsixEntries[0].vector, irq_handler_0, ...);
request_irq(my_pci_dev->pMsixEntries[1].vector, irq_handler_1, ...);
request_irq(my_pci_dev->pMsixEntries[2].vector, irq_handler_2, ...);
【讨论】:
以上是关于MSI 中断如何在 linux 驱动程序中工作?的主要内容,如果未能解决你的问题,请参考以下文章