mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
irqdomain: Allow giving name suffix for domain
Devices can provide multiple interrupt lines. One reason for this is that a device has multiple subfunctions, each providing its own interrupt line. Another reason is that a device can be designed to be used (also) on a system where some of the interrupts can be routed to another processor. A line often further acts as a demultiplex for specific interrupts and has it's respective set of interrupt (status, mask, ack, ...) registers. Regmap supports the handling of these registers and demultiplexing interrupts, but the interrupt domain code ends up assigning the same name for the per interrupt line domains. This causes a naming collision in the debugFS code and leads to confusion, as /proc/interrupts shows two separate interrupts with the same domain name and hardware interrupt number. Instead of adding a workaround in regmap or driver code, allow giving a name suffix for the domain name when the domain is created. Add a name_suffix field in the irq_domain_info structure and make irq_domain_instantiate() use this suffix if it is given when a domain is created. [ tglx: Adopt it to the cleanup patch and fixup the invalid NULL return ] Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/871q2yvk5x.ffs@tglx
This commit is contained in:
parent
1bf2c92829
commit
1e7c052925
@ -295,6 +295,8 @@ struct irq_domain_chip_generic_info;
|
|||||||
* @virq_base: The first Linux interrupt number for legacy domains to
|
* @virq_base: The first Linux interrupt number for legacy domains to
|
||||||
* immediately associate the interrupts after domain creation
|
* immediately associate the interrupts after domain creation
|
||||||
* @bus_token: Domain bus token
|
* @bus_token: Domain bus token
|
||||||
|
* @name_suffix: Optional name suffix to avoid collisions when multiple
|
||||||
|
* domains are added using same fwnode
|
||||||
* @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
|
* @dgc_info: Geneneric chip information structure pointer used to
|
||||||
@ -313,6 +315,7 @@ struct irq_domain_info {
|
|||||||
unsigned int hwirq_base;
|
unsigned int hwirq_base;
|
||||||
unsigned int virq_base;
|
unsigned int virq_base;
|
||||||
enum irq_domain_bus_token bus_token;
|
enum irq_domain_bus_token bus_token;
|
||||||
|
const char *name_suffix;
|
||||||
const struct irq_domain_ops *ops;
|
const struct irq_domain_ops *ops;
|
||||||
void *host_data;
|
void *host_data;
|
||||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||||
|
@ -140,11 +140,14 @@ static int alloc_name(struct irq_domain *domain, char *base, enum irq_domain_bus
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_handle *fwnode,
|
static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_handle *fwnode,
|
||||||
enum irq_domain_bus_token bus_token)
|
enum irq_domain_bus_token bus_token, const char *suffix)
|
||||||
{
|
{
|
||||||
char *name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) :
|
const char *sep = suffix ? "-" : "";
|
||||||
kasprintf(GFP_KERNEL, "%pfw", fwnode);
|
const char *suf = suffix ? : "";
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%s%s%d", fwnode, suf, sep, bus_token) :
|
||||||
|
kasprintf(GFP_KERNEL, "%pfw-%s", fwnode, suf);
|
||||||
if (!name)
|
if (!name)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -172,12 +175,25 @@ static int alloc_unknown_name(struct irq_domain *domain, enum irq_domain_bus_tok
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int irq_domain_set_name(struct irq_domain *domain, const struct fwnode_handle *fwnode,
|
static int irq_domain_set_name(struct irq_domain *domain, const struct irq_domain_info *info)
|
||||||
enum irq_domain_bus_token bus_token)
|
|
||||||
{
|
{
|
||||||
|
enum irq_domain_bus_token bus_token = info->bus_token;
|
||||||
|
const struct fwnode_handle *fwnode = info->fwnode;
|
||||||
|
|
||||||
if (is_fwnode_irqchip(fwnode)) {
|
if (is_fwnode_irqchip(fwnode)) {
|
||||||
struct irqchip_fwid *fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
|
struct irqchip_fwid *fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The name_suffix is only intended to be used to avoid a name
|
||||||
|
* collision when multiple domains are created for a single
|
||||||
|
* device and the name is picked using a real device node.
|
||||||
|
* (Typical use-case is regmap-IRQ controllers for devices
|
||||||
|
* providing more than one physical IRQ.) There should be no
|
||||||
|
* need to use name_suffix with irqchip-fwnode.
|
||||||
|
*/
|
||||||
|
if (info->name_suffix)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
switch (fwid->type) {
|
switch (fwid->type) {
|
||||||
case IRQCHIP_FWNODE_NAMED:
|
case IRQCHIP_FWNODE_NAMED:
|
||||||
case IRQCHIP_FWNODE_NAMED_ID:
|
case IRQCHIP_FWNODE_NAMED_ID:
|
||||||
@ -189,7 +205,7 @@ static int irq_domain_set_name(struct irq_domain *domain, const struct fwnode_ha
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || is_software_node(fwnode)) {
|
} else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || is_software_node(fwnode)) {
|
||||||
return alloc_fwnode_name(domain, fwnode, bus_token);
|
return alloc_fwnode_name(domain, fwnode, bus_token, info->name_suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domain->name)
|
if (domain->name)
|
||||||
@ -215,7 +231,7 @@ static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info
|
|||||||
if (!domain)
|
if (!domain)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
err = irq_domain_set_name(domain, info->fwnode, info->bus_token);
|
err = irq_domain_set_name(domain, info);
|
||||||
if (err) {
|
if (err) {
|
||||||
kfree(domain);
|
kfree(domain);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
Loading…
Reference in New Issue
Block a user