Commit cf15f43a authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

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: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarMichael Kelley <mikelley@microsoft.com>
Tested-by: default avatarNishanth Menon <nm@ti.com>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/20211210221814.780824745@linutronix.de
parent 651b39c4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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)
+36 −0
Original line number Diff line number Diff line
@@ -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)