diff options
author | Herve Codina <herve.codina@bootlin.com> | 2024-06-14 19:32:16 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2024-06-17 15:48:14 +0200 |
commit | e6f67ce32e8e6dcbadf42dc435fbc9002cabf1f9 (patch) | |
tree | cbc91fca37fbd52412759d3a12aaa162e89453e1 /kernel/irq | |
parent | fea922ee9f8ffd3c2a8e8dfbc68de42905a3982a (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.c | 14 |
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); } |