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

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
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -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,
					bool realloc, const struct irq_affinity_desc *affinity);
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 fwnode_handle	fwnode;
@@ -858,6 +859,11 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
	}

	if (irq_domain_is_hierarchy(domain)) {
		if (irq_domain_is_msi_device(domain)) {
			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) {
@@ -914,7 +920,7 @@ void irq_dispose_mapping(unsigned int virq)
		return;

	if (irq_domain_is_hierarchy(domain)) {
		irq_domain_free_irqs(virq, 1);
		irq_domain_free_one_irq(domain, virq);
	} else {
		irq_domain_disassociate(domain, virq);
		irq_free_desc(virq);
@@ -1755,6 +1761,14 @@ void irq_domain_free_irqs(unsigned int virq, unsigned int 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
 * @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,
	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 */

#ifdef CONFIG_GENERIC_IRQ_DEBUGFS