summaryrefslogtreecommitdiff
path: root/kernel/irq
diff options
context:
space:
mode:
authorHerve Codina <herve.codina@bootlin.com>2024-06-14 19:32:16 +0200
committerThomas Gleixner <tglx@linutronix.de>2024-06-17 15:48:14 +0200
commite6f67ce32e8e6dcbadf42dc435fbc9002cabf1f9 (patch)
treecbc91fca37fbd52412759d3a12aaa162e89453e1 /kernel/irq
parentfea922ee9f8ffd3c2a8e8dfbc68de42905a3982a (diff)
irqdomain: Add support for generic irq chips creation before publishing a domain
The current API functions create an irq_domain and also publish this newly created to domain. Once an irq_domain is published, consumers can request IRQ in order to use them. Some interrupt controller drivers have to perform some more operations with the created irq_domain in order to have it ready to be used. For instance: - Allocate generic irq chips with irq_alloc_domain_generic_chips() - Retrieve the generic irq chips with irq_get_domain_generic_chip() - Initialize retrieved chips: set register base address and offsets, set several hooks such as irq_mask, irq_unmask, ... With the newly introduced irq_domain_alloc_generic_chips(), an interrupt controller driver can use the irq_domain_chip_generic_info structure and set the init() hook to perform its generic chips initialization. In order to avoid a window where the domain is published but not yet ready to be used, handle the generic chip creation (i.e the irq_domain_alloc_generic_chips() call) before the domain is published. Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Herve Codina <herve.codina@bootlin.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/r/20240614173232.1184015-16-herve.codina@bootlin.com
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/irqdomain.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index a0324d8e6dab..4d2a40359eb2 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -292,16 +292,25 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)
}
#endif
+ if (info->dgc_info) {
+ err = irq_domain_alloc_generic_chips(domain, info->dgc_info);
+ if (err)
+ goto err_domain_free;
+ }
+
if (info->init) {
err = info->init(domain);
if (err)
- goto err_domain_free;
+ goto err_domain_gc_remove;
}
__irq_domain_publish(domain);
return domain;
+err_domain_gc_remove:
+ if (info->dgc_info)
+ irq_domain_remove_generic_chips(domain);
err_domain_free:
irq_domain_free(domain);
return ERR_PTR(err);
@@ -369,6 +378,9 @@ void irq_domain_remove(struct irq_domain *domain)
mutex_unlock(&irq_domain_mutex);
+ if (domain->flags & IRQ_DOMAIN_FLAG_DESTROY_GC)
+ irq_domain_remove_generic_chips(domain);
+
pr_debug("Removed domain %s\n", domain->name);
irq_domain_free(domain);
}