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 驱动程序中工作?的主要内容,如果未能解决你的问题,请参考以下文章

Remmina 文件夹共享如何在 Linux 中工作?

内核模块的加载如何在 linux 中工作?

rabbitMQ常用方法说明 – 6中工作模式及关键点

Linux,C++,dup(socket) 是不是可以从另一个未分叉的进程中工作(如果不是如何启用它)?

linux可执行文件不工作,但脚本在python中工作

如何在 C# 程序中工作?