From 2fd144aa1baeda4a8502099cddba364eb59320d0 Mon Sep 17 00:00:00 2001 From: Prakruthi Deepak Heragu Date: Thu, 18 Jul 2019 16:19:23 -0700 Subject: [PATCH] irqdomain: Implement and expose API to clear IRQ mapping for radix tree The irq_domain_remove() API expects all the irqs of the domain be cleared before it is called, else it throws a warning. A framework creating a radix tree to map all the irqs used by its clients cannot be sure if all the clients cleared their irqs. Thus to avoid this warning, we can use this API irq_dispose_all_tree_mappings() to ensure that all irqs belonging to the domain are cleared before the domain is itself removed. Change-Id: Ied1f20c990aba9d4760091d9ed3d48c3e4f3d5d9 Signed-off-by: Prakruthi Deepak Heragu --- include/linux/irqdomain.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 07ec8b390161..2e29bba9e6fa 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -35,6 +35,8 @@ #include #include #include +#include +#include struct device_node; struct irq_domain; @@ -380,6 +382,37 @@ extern unsigned int irq_create_mapping(struct irq_domain *host, extern unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec); extern void irq_dispose_mapping(unsigned int virq); +/** +* irq_dispose_all_tree_mappings() - Unmaps all interrupts from a domain +* @domain: domain owning the interrupt range +* +* This routine helps unmap all the interrupts that were mapped to the +* domain using a radix tree. +*/ +static inline void irq_dispose_all_tree_mappings( + struct irq_domain *domain) +{ + struct irq_data **irq_data; + unsigned int num_irqs = 0; + unsigned int max_irqs = domain->mapcount; + unsigned int index = 0; + + if (!max_irqs) + return; + + irq_data = kcalloc(max_irqs, sizeof(*irq_data), GFP_KERNEL); + if (!irq_data) + return; + + rcu_read_lock(); + num_irqs = radix_tree_gang_lookup(&domain->revmap_tree, + (void **)irq_data, 0, max_irqs); + rcu_read_unlock(); + for (index = 0; index < num_irqs; index++) + irq_dispose_mapping(irq_data[index]->irq); + kfree(irq_data); +} + /** * irq_linear_revmap() - Find a linux irq from a hw irq number. * @domain: domain owning this hardware interrupt