Commit e49312fe authored by Thomas Gleixner's avatar Thomas Gleixner

genirq/irqdomain: Reroute device MSI create_mapping

Reroute interrupt allocation in irq_create_fwspec_mapping() if the domain
is a MSI device domain. This is required to convert the support for wire
to MSI bridges to per device MSI domains.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarAnup Patel <apatel@ventanamicro.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240127161753.114685-13-apatel@ventanamicro.com
parent 0ee1578b
...@@ -29,6 +29,7 @@ static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base, ...@@ -29,6 +29,7 @@ static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base,
unsigned int nr_irqs, int node, void *arg, unsigned int nr_irqs, int node, void *arg,
bool realloc, const struct irq_affinity_desc *affinity); bool realloc, const struct irq_affinity_desc *affinity);
static void irq_domain_check_hierarchy(struct irq_domain *domain); static void irq_domain_check_hierarchy(struct irq_domain *domain);
static void irq_domain_free_one_irq(struct irq_domain *domain, unsigned int virq);
struct irqchip_fwid { struct irqchip_fwid {
struct fwnode_handle fwnode; struct fwnode_handle fwnode;
...@@ -858,8 +859,13 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) ...@@ -858,8 +859,13 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
} }
if (irq_domain_is_hierarchy(domain)) { if (irq_domain_is_hierarchy(domain)) {
virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE, if (irq_domain_is_msi_device(domain)) {
fwspec, false, NULL); mutex_unlock(&domain->root->mutex);
virq = msi_device_domain_alloc_wired(domain, hwirq, type);
mutex_lock(&domain->root->mutex);
} else
virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE,
fwspec, false, NULL);
if (virq <= 0) { if (virq <= 0) {
virq = 0; virq = 0;
goto out; goto out;
...@@ -914,7 +920,7 @@ void irq_dispose_mapping(unsigned int virq) ...@@ -914,7 +920,7 @@ void irq_dispose_mapping(unsigned int virq)
return; return;
if (irq_domain_is_hierarchy(domain)) { if (irq_domain_is_hierarchy(domain)) {
irq_domain_free_irqs(virq, 1); irq_domain_free_one_irq(domain, virq);
} else { } else {
irq_domain_disassociate(domain, virq); irq_domain_disassociate(domain, virq);
irq_free_desc(virq); irq_free_desc(virq);
...@@ -1755,6 +1761,14 @@ void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs) ...@@ -1755,6 +1761,14 @@ void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs)
irq_free_descs(virq, nr_irqs); irq_free_descs(virq, nr_irqs);
} }
static void irq_domain_free_one_irq(struct irq_domain *domain, unsigned int virq)
{
if (irq_domain_is_msi_device(domain))
msi_device_domain_free_wired(domain, virq);
else
irq_domain_free_irqs(virq, 1);
}
/** /**
* irq_domain_alloc_irqs_parent - Allocate interrupts from parent domain * irq_domain_alloc_irqs_parent - Allocate interrupts from parent domain
* @domain: Domain below which interrupts must be allocated * @domain: Domain below which interrupts must be allocated
...@@ -1907,9 +1921,9 @@ static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base, ...@@ -1907,9 +1921,9 @@ static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base,
return -EINVAL; return -EINVAL;
} }
static void irq_domain_check_hierarchy(struct irq_domain *domain) static void irq_domain_check_hierarchy(struct irq_domain *domain) { }
{ static void irq_domain_free_one_irq(struct irq_domain *domain, unsigned int virq) { }
}
#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ #endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
#ifdef CONFIG_GENERIC_IRQ_DEBUGFS #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment