Re: [patch V3 26/35] genirq/msi: Provide interface to retrieve Linux interrupt number

2021-12-13 Thread Jason Gunthorpe
On Fri, Dec 10, 2021 at 11:19:23PM +0100, Thomas Gleixner wrote:
> From: Thomas Gleixner 
> 
> 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 
> Reviewed-by: Greg Kroah-Hartman 
> ---
> V2: Simplify the implementation and let PCI deal with the PCI specialities - 
> Marc
> ---
>  include/linux/msi.h |2 ++
>  kernel/irq/msi.c|   36 
>  2 files changed, 38 insertions(+)

Reviewed-by: Jason Gunthorpe 

Jason



[patch V3 26/35] genirq/msi: Provide interface to retrieve Linux interrupt number

2021-12-10 Thread Thomas Gleixner
From: Thomas Gleixner 

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 
Reviewed-by: Greg Kroah-Hartman 
---
V2: Simplify the implementation and let PCI deal with the PCI specialities - 
Marc
---
 include/linux/msi.h |2 ++
 kernel/irq/msi.c|   36 
 2 files changed, 38 insertions(+)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -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)
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -105,6 +105,42 @@ int msi_setup_device_data(struct device
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)