diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2021-12-07 01:27:59 +0300 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2021-12-09 13:52:22 +0300 |
commit | 890337624e1fa2da079fc1c036a62d178c985280 (patch) | |
tree | afbad15dfbe9c1e6f734c8d3722125f77324757a /kernel/irq | |
parent | 57ce3a3c99b21e9c4f951ef01e0a3603c987c259 (diff) | |
download | linux-890337624e1fa2da079fc1c036a62d178c985280.tar.xz |
genirq/msi: Handle PCI/MSI allocation fail in core code
Get rid of yet another irqdomain callback and let the core code return the
already available information of how many descriptors could be allocated.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Bjorn Helgaas <bhelgaas@google.com> # PCI
Link: https://lore.kernel.org/r/20211206210225.046615302@linutronix.de
Diffstat (limited to 'kernel/irq')
-rw-r--r-- | kernel/irq/msi.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 7d78d8aff076..4a7a7f0f5102 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -538,6 +538,27 @@ static bool msi_check_reservation_mode(struct irq_domain *domain, return desc->pci.msi_attrib.is_msix || desc->pci.msi_attrib.can_mask; } +static int msi_handle_pci_fail(struct irq_domain *domain, struct msi_desc *desc, + int allocated) +{ + switch(domain->bus_token) { + case DOMAIN_BUS_PCI_MSI: + case DOMAIN_BUS_VMD_MSI: + if (IS_ENABLED(CONFIG_PCI_MSI)) + break; + fallthrough; + default: + return -ENOSPC; + } + + /* Let a failed PCI multi MSI allocation retry */ + if (desc->nvec_used > 1) + return 1; + + /* If there was a successful allocation let the caller know */ + return allocated ? allocated : -ENOSPC; +} + int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nvec) { @@ -546,6 +567,7 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, struct irq_data *irq_data; struct msi_desc *desc; msi_alloc_info_t arg = { }; + int allocated = 0; int i, ret, virq; bool can_reserve; @@ -560,16 +582,15 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, dev_to_node(dev), &arg, false, desc->affinity); if (virq < 0) { - ret = -ENOSPC; - if (ops->handle_error) - ret = ops->handle_error(domain, desc, ret); - return ret; + ret = msi_handle_pci_fail(domain, desc, allocated); + goto cleanup; } for (i = 0; i < desc->nvec_used; i++) { irq_set_msi_desc_off(virq, i, desc); irq_debugfs_copy_devname(virq + i, dev); } + allocated++; } can_reserve = msi_check_reservation_mode(domain, info, dev); |