Skip to content

Commit

Permalink
genirq/msi: Make msi_get_virq() device domain aware
Browse files Browse the repository at this point in the history
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@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Ahmed S. Darwish authored and Thomas Gleixner committed Nov 2, 2022
1 parent 4321d68 commit 022573e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
14 changes: 13 additions & 1 deletion include/linux/msi_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
24 changes: 18 additions & 6 deletions kernel/irq/msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,25 +351,37 @@ struct msi_desc *msi_next_desc(struct device *dev, enum msi_desc_filter filter)
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)
return 0;

desc = xa_load(&dev->msi.data->__store, base + pcimsi ? 0 : index);
if (desc && desc->irq) {
/*
* PCI-MSI has only one descriptor for multiple interrupts.
Expand All @@ -386,7 +398,7 @@ unsigned int msi_get_virq(struct device *dev, unsigned int index)
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[] = {
Expand Down

0 comments on commit 022573e

Please sign in to comment.