From: Ahmed S. Darwish <darwi@xxxxxxxxxxxxx> In preparation of the upcoming per device multi MSI domain support, change the interface to support lookups based on domain id and zero based index within the domain. Signed-off-by: Ahmed S. Darwish <darwi@xxxxxxxxxxxxx> Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> --- V1A: Fix the locking leak and a operator precedence issue (Dan, kernel robot) This was reported earlier and I missed to fold the fix before posting. :( --- include/linux/msi_api.h | 14 +++++++++++++- kernel/irq/msi.c | 27 +++++++++++++++++++++------ 2 files changed, 34 insertions(+), 7 deletions(-) --- a/include/linux/msi_api.h +++ b/include/linux/msi_api.h @@ -18,6 +18,18 @@ enum msi_domain_ids { MSI_MAX_DEVICE_IRQDOMAINS, }; -unsigned int msi_get_virq(struct device *dev, unsigned int index); +unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index); + +/** + * msi_get_virq - Lookup the Linux interrupt number for a MSI index on the default interrupt domain + * @dev: Device for which the lookup happens + * @index: The MSI index to lookup + * + * Return: The Linux interrupt number on success (> 0), 0 if not found + */ +static inline unsigned int msi_get_virq(struct device *dev, unsigned int index) +{ + return msi_domain_get_virq(dev, MSI_DEFAULT_DOMAIN, index); +} #endif --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -351,25 +351,38 @@ struct msi_desc *msi_next_desc(struct de EXPORT_SYMBOL_GPL(msi_next_desc); /** - * msi_get_virq - Return Linux interrupt number of a MSI interrupt + * msi_domain_get_virq - Lookup the Linux interrupt number for a MSI index on a interrupt domain * @dev: Device to operate on + * @domid: Domain ID of the interrupt domain associated to the device * @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) +unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index) { struct msi_desc *desc; unsigned int ret = 0; - bool pcimsi; + bool pcimsi = false; + int base; if (!dev->msi.data) return 0; - pcimsi = dev_is_pci(dev) ? to_pci_dev(dev)->msi_enabled : false; + if (WARN_ON_ONCE(index >= MSI_MAX_INDEX)) + return 0; + + /* This check is only valid for the PCI default MSI domain */ + if (dev_is_pci(dev) && domid == MSI_DEFAULT_DOMAIN) + pcimsi = to_pci_dev(dev)->msi_enabled; msi_lock_descs(dev); - desc = xa_load(&dev->msi.data->__store, pcimsi ? 0 : index); + + base = msi_get_domain_base_index(dev, domid); + if (base < 0) + goto unlock; + + base += pcimsi ? 0 : index; + desc = xa_load(&dev->msi.data->__store, base); if (desc && desc->irq) { /* * PCI-MSI has only one descriptor for multiple interrupts. @@ -383,10 +396,12 @@ unsigned int msi_get_virq(struct device ret = desc->irq; } } + +unlock: msi_unlock_descs(dev); return ret; } -EXPORT_SYMBOL_GPL(msi_get_virq); +EXPORT_SYMBOL_GPL(msi_domain_get_virq); #ifdef CONFIG_SYSFS static struct attribute *msi_dev_attrs[] = {