Skip to content

Commit 1e7c052

Browse files
M-VaittinenKAGA-KOKO
authored andcommitted
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 <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/all/871q2yvk5x.ffs@tglx
1 parent 1bf2c92 commit 1e7c052

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

include/linux/irqdomain.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ struct irq_domain_chip_generic_info;
295295
* @virq_base: The first Linux interrupt number for legacy domains to
296296
* immediately associate the interrupts after domain creation
297297
* @bus_token: Domain bus token
298+
* @name_suffix: Optional name suffix to avoid collisions when multiple
299+
* domains are added using same fwnode
298300
* @ops: Domain operation callbacks
299301
* @host_data: Controller private data pointer
300302
* @dgc_info: Geneneric chip information structure pointer used to
@@ -313,6 +315,7 @@ struct irq_domain_info {
313315
unsigned int hwirq_base;
314316
unsigned int virq_base;
315317
enum irq_domain_bus_token bus_token;
318+
const char *name_suffix;
316319
const struct irq_domain_ops *ops;
317320
void *host_data;
318321
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY

kernel/irq/irqdomain.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,14 @@ static int alloc_name(struct irq_domain *domain, char *base, enum irq_domain_bus
140140
}
141141

142142
static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_handle *fwnode,
143-
enum irq_domain_bus_token bus_token)
143+
enum irq_domain_bus_token bus_token, const char *suffix)
144144
{
145-
char *name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) :
146-
kasprintf(GFP_KERNEL, "%pfw", fwnode);
145+
const char *sep = suffix ? "-" : "";
146+
const char *suf = suffix ? : "";
147+
char *name;
147148

149+
name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%s%s%d", fwnode, suf, sep, bus_token) :
150+
kasprintf(GFP_KERNEL, "%pfw-%s", fwnode, suf);
148151
if (!name)
149152
return -ENOMEM;
150153

@@ -172,12 +175,25 @@ static int alloc_unknown_name(struct irq_domain *domain, enum irq_domain_bus_tok
172175
return 0;
173176
}
174177

175-
static int irq_domain_set_name(struct irq_domain *domain, const struct fwnode_handle *fwnode,
176-
enum irq_domain_bus_token bus_token)
178+
static int irq_domain_set_name(struct irq_domain *domain, const struct irq_domain_info *info)
177179
{
180+
enum irq_domain_bus_token bus_token = info->bus_token;
181+
const struct fwnode_handle *fwnode = info->fwnode;
182+
178183
if (is_fwnode_irqchip(fwnode)) {
179184
struct irqchip_fwid *fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
180185

186+
/*
187+
* The name_suffix is only intended to be used to avoid a name
188+
* collision when multiple domains are created for a single
189+
* device and the name is picked using a real device node.
190+
* (Typical use-case is regmap-IRQ controllers for devices
191+
* providing more than one physical IRQ.) There should be no
192+
* need to use name_suffix with irqchip-fwnode.
193+
*/
194+
if (info->name_suffix)
195+
return -EINVAL;
196+
181197
switch (fwid->type) {
182198
case IRQCHIP_FWNODE_NAMED:
183199
case IRQCHIP_FWNODE_NAMED_ID:
@@ -189,7 +205,7 @@ static int irq_domain_set_name(struct irq_domain *domain, const struct fwnode_ha
189205
}
190206

191207
} else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || is_software_node(fwnode)) {
192-
return alloc_fwnode_name(domain, fwnode, bus_token);
208+
return alloc_fwnode_name(domain, fwnode, bus_token, info->name_suffix);
193209
}
194210

195211
if (domain->name)
@@ -215,7 +231,7 @@ static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info
215231
if (!domain)
216232
return ERR_PTR(-ENOMEM);
217233

218-
err = irq_domain_set_name(domain, info->fwnode, info->bus_token);
234+
err = irq_domain_set_name(domain, info);
219235
if (err) {
220236
kfree(domain);
221237
return ERR_PTR(err);

0 commit comments

Comments
 (0)