genirq/msi: Provide interface to retrieve Linux interrupt number
authorThomas Gleixner <tglx@linutronix.de>
Fri, 10 Dec 2021 22:19:23 +0000 (23:19 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 16 Dec 2021 21:16:40 +0000 (22:16 +0100)
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
include/linux/msi.h
kernel/irq/msi.c

index d206239..7593fc3 100644 (file)
@@ -153,6 +153,8 @@ struct msi_device_data {
 
 int msi_setup_device_data(struct device *dev);
 
+unsigned int msi_get_virq(struct device *dev, unsigned int index);
+
 /* Helpers to hide struct msi_desc implementation details */
 #define msi_desc_to_dev(desc)          ((desc)->dev)
 #define dev_to_msi_list(dev)           (&(dev)->msi_list)
index 8e433f1..ab5e83f 100644 (file)
@@ -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)