mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-01 06:39:05 +00:00
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
This commit is contained in:
parent
fea922ee9f
commit
e6f67ce32e
@ -210,6 +210,9 @@ enum {
|
|||||||
/* Irq domain is a MSI device domain */
|
/* Irq domain is a MSI device domain */
|
||||||
IRQ_DOMAIN_FLAG_MSI_DEVICE = (1 << 9),
|
IRQ_DOMAIN_FLAG_MSI_DEVICE = (1 << 9),
|
||||||
|
|
||||||
|
/* Irq domain must destroy generic chips when removed */
|
||||||
|
IRQ_DOMAIN_FLAG_DESTROY_GC = (1 << 10),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
|
* Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
|
||||||
* for implementation specific purposes and ignored by the
|
* for implementation specific purposes and ignored by the
|
||||||
@ -259,6 +262,9 @@ static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
|
void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
|
||||||
|
|
||||||
|
struct irq_domain_chip_generic_info;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct irq_domain_info - Domain information structure
|
* struct irq_domain_info - Domain information structure
|
||||||
* @fwnode: firmware node for the interrupt controller
|
* @fwnode: firmware node for the interrupt controller
|
||||||
@ -270,6 +276,8 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
|
|||||||
* @bus_token: Domain bus token
|
* @bus_token: Domain bus token
|
||||||
* @ops: Domain operation callbacks
|
* @ops: Domain operation callbacks
|
||||||
* @host_data: Controller private data pointer
|
* @host_data: Controller private data pointer
|
||||||
|
* @dgc_info: Geneneric chip information structure pointer used to
|
||||||
|
* create generic chips for the domain if not NULL.
|
||||||
* @init: Function called when the domain is created.
|
* @init: Function called when the domain is created.
|
||||||
* Allow to do some additional domain initialisation.
|
* Allow to do some additional domain initialisation.
|
||||||
* @exit: Function called when the domain is destroyed.
|
* @exit: Function called when the domain is destroyed.
|
||||||
@ -290,6 +298,7 @@ struct irq_domain_info {
|
|||||||
*/
|
*/
|
||||||
struct irq_domain *parent;
|
struct irq_domain *parent;
|
||||||
#endif
|
#endif
|
||||||
|
struct irq_domain_chip_generic_info *dgc_info;
|
||||||
int (*init)(struct irq_domain *d);
|
int (*init)(struct irq_domain *d);
|
||||||
void (*exit)(struct irq_domain *d);
|
void (*exit)(struct irq_domain *d);
|
||||||
};
|
};
|
||||||
|
@ -292,16 +292,25 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (info->dgc_info) {
|
||||||
|
err = irq_domain_alloc_generic_chips(domain, info->dgc_info);
|
||||||
|
if (err)
|
||||||
|
goto err_domain_free;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->init) {
|
if (info->init) {
|
||||||
err = info->init(domain);
|
err = info->init(domain);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_domain_free;
|
goto err_domain_gc_remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
__irq_domain_publish(domain);
|
__irq_domain_publish(domain);
|
||||||
|
|
||||||
return domain;
|
return domain;
|
||||||
|
|
||||||
|
err_domain_gc_remove:
|
||||||
|
if (info->dgc_info)
|
||||||
|
irq_domain_remove_generic_chips(domain);
|
||||||
err_domain_free:
|
err_domain_free:
|
||||||
irq_domain_free(domain);
|
irq_domain_free(domain);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
@ -369,6 +378,9 @@ void irq_domain_remove(struct irq_domain *domain)
|
|||||||
|
|
||||||
mutex_unlock(&irq_domain_mutex);
|
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);
|
pr_debug("Removed domain %s\n", domain->name);
|
||||||
irq_domain_free(domain);
|
irq_domain_free(domain);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user