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
This commit is contained in:
@@ -153,6 +153,8 @@ struct msi_device_data {
|
|||||||
|
|
||||||
int msi_setup_device_data(struct device *dev);
|
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 */
|
/* Helpers to hide struct msi_desc implementation details */
|
||||||
#define msi_desc_to_dev(desc) ((desc)->dev)
|
#define msi_desc_to_dev(desc) ((desc)->dev)
|
||||||
#define dev_to_msi_list(dev) (&(dev)->msi_list)
|
#define dev_to_msi_list(dev) (&(dev)->msi_list)
|
||||||
|
@@ -105,6 +105,42 @@ int msi_setup_device_data(struct device *dev)
|
|||||||
return 0;
|
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
|
#ifdef CONFIG_SYSFS
|
||||||
static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
|
static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
|
Reference in New Issue
Block a user