[V2,23/40] genirq/irqdomain: Reroute device MSI create_mapping

Message ID 20221121140049.743020502@linutronix.de
State New
Headers
Series genirq, irqchip: Convert ARM MSI handling to per device MSI domains |

Commit Message

Thomas Gleixner Nov. 21, 2022, 2:39 p.m. UTC
  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: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/irq/irqdomain.c |   24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
  

Patch

--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -26,6 +26,7 @@  static DEFINE_MUTEX(irq_domain_mutex);
 static struct irq_domain *irq_default_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 fwnode_handle	fwnode;
@@ -822,7 +823,10 @@  unsigned int irq_create_fwspec_mapping(s
 	}
 
 	if (irq_domain_is_hierarchy(domain)) {
-		virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
+		if (irq_domain_is_msi_device(domain))
+			virq = msi_device_domain_alloc_wired(domain, hwirq, type);
+		else
+			virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
 		if (virq <= 0)
 			return 0;
 	} else {
@@ -835,7 +839,7 @@  unsigned int irq_create_fwspec_mapping(s
 	irq_data = irq_get_irq_data(virq);
 	if (!irq_data) {
 		if (irq_domain_is_hierarchy(domain))
-			irq_domain_free_irqs(virq, 1);
+			irq_domain_free_one_irq(domain, virq);
 		else
 			irq_dispose_mapping(virq);
 		return 0;
@@ -876,7 +880,7 @@  void irq_dispose_mapping(unsigned int vi
 		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);
@@ -1706,6 +1710,14 @@  void irq_domain_free_irqs(unsigned int v
 	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
@@ -1865,9 +1877,9 @@  void irq_domain_set_info(struct irq_doma
 	irq_set_handler_data(virq, handler_data);
 }
 
-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