4.MSI驱动指南¶

日博365备用网站 admin 2025-10-15 02:50:45

4.4.2. 使用MSI¶

大部分沉重的工作是在PCI层为驱动程序完成的。驱动程序只需要请求PCI层为这个设备设置

MSI功能。

要自动使用MSI或MSI-X中断向量,请使用以下函数:

int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,

unsigned int max_vecs, unsigned int flags);

它为一个PCI设备分配最多至max_vecs的中断向量。它返回分配的向量数量或一个负的错误。

如果设备对最小数量的向量有要求,驱动程序可以传递一个min_vecs参数,设置为这个限制,

如果PCI核不能满足最小数量的向量,将返回-ENOSPC。

flags参数用来指定设备和驱动程序可以使用哪种类型的中断(PCI_IRQ_INTX, PCI_IRQ_MSI,

PCI_IRQ_MSIX)。一个方便的短语(PCI_IRQ_ALL_TYPES)也可以用来要求任何可能的中断类型。

如果PCI_IRQ_AFFINITY标志被设置,pci_alloc_irq_vectors()将把中断分散到可用的CPU上。

要获得传递给require_irq()和free_irq()的Linux IRQ号码和向量,请使用以下函数:

int pci_irq_vector(struct pci_dev *dev, unsigned int nr);

在删除设备之前,应使用以下功能释放任何已分配的资源:

void pci_free_irq_vectors(struct pci_dev *dev);

如果一个设备同时支持MSI-X和MSI功能,这个API将优先使用MSI-X,而不是MSI。MSI-X支

持1到2048之间的任何数量的中断。相比之下,MSI被限制为最多32个中断(而且必须是2的幂)。

此外,MSI中断向量必须连续分配,所以系统可能无法为MSI分配像MSI-X那样多的向量。在一

些平台上,MSI中断必须全部针对同一组CPU,而MSI-X中断可以全部针对不同的CPU。

如果一个设备既不支持MSI-X,也不支持MSI,它就会退回到一个传统的IRQ向量。

MSI或MSI-X中断的典型用法是分配尽可能多的向量,可能达到设备支持的极限。如果nvec大于

设备支持的数量,它将自动被限制在支持的限度内,所以没有必要事先查询支持的向量的数量。:

nvec = pci_alloc_irq_vectors(pdev, 1, nvec, PCI_IRQ_ALL_TYPES)

if (nvec < 0)

goto out_err;

如果一个驱动程序不能或不愿意处理可变数量的MSI中断,它可以要求一个特定数量的中断,将该

数量作为“min_vecs“和“max_vecs“参数传递给pci_alloc_irq_vectors()函数。:

ret = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_ALL_TYPES);

if (ret < 0)

goto out_err;

上述请求类型的最臭名昭著的例子是为一个设备启用单一的MSI模式。它可以通过传递两个1作为

‘min_vecs’和’max_vecs’来实现:

ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);

if (ret < 0)

goto out_err;

一些设备可能不支持使用传统的线路中断,在这种情况下,驱动程序可以指定只接受MSI或MSI-X。:

nvec = pci_alloc_irq_vectors(pdev, 1, nvec, PCI_IRQ_MSI | PCI_IRQ_MSIX);

if (nvec < 0)

goto out_err;