diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2021-12-10 23:19:23 +0100 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2021-12-16 22:16:40 +0100 |
commit | cf15f43acaad31dabb2646cef170a506a1d663eb (patch) | |
tree | edf03c996e5ceb82d3523f4494ae581fb7d8107e /kernel/irq | |
parent | 651b39c48813acac2b77850014390f4062a4835d (diff) |
genirq/msi: Provide interface to retrieve Linux interrupt number
This allows drivers to retrieve the Linux interrupt number instead of
fiddling with MSI descriptors.
msi_get_virq() returns the Linux interrupt number or 0 in case that there
is no entry for the given MSI index.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Michael Kelley <mikelley@microsoft.com>
Tested-by: Nishanth Menon <nm@ti.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/20211210221814.780824745@linutronix.de
Diffstat (limited to 'kernel/irq')
-rw-r--r-- | kernel/irq/msi.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 8e433f1a24fb..ab5e83f41188 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -105,6 +105,42 @@ int msi_setup_device_data(struct device *dev) return 0; } +/** + * msi_get_virq - Return Linux interrupt number of a MSI interrupt + * @dev: Device to operate on + * @index: MSI interrupt index to look for (0-based) + * + * Return: The Linux interrupt number on success (> 0), 0 if not found + */ +unsigned int msi_get_virq(struct device *dev, unsigned int index) +{ + struct msi_desc *desc; + bool pcimsi; + + if (!dev->msi.data) + return 0; + + pcimsi = dev_is_pci(dev) ? to_pci_dev(dev)->msi_enabled : false; + + for_each_msi_entry(desc, dev) { + /* PCI-MSI has only one descriptor for multiple interrupts. */ + if (pcimsi) { + if (desc->irq && index < desc->nvec_used) + return desc->irq + index; + break; + } + + /* + * PCI-MSIX and platform MSI use a descriptor per + * interrupt. + */ + if (desc->msi_index == index) + return desc->irq; + } + return 0; +} +EXPORT_SYMBOL_GPL(msi_get_virq); + #ifdef CONFIG_SYSFS static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr, char *buf) |