irqdomain: Let irq_domain_mapping display hierarchical domains
Hierarchical domains seem to be hard to grasp, and a number of aspiring kernel hackers find them utterly discombobulating. In order to ease their pain, let's make them appear in /sys/kernel/debug/irq_domain_mapping, such as the following: 96 0x81808 MSI 0x (null) RADIX MSI 96+ 0x00063 GICv2m 0xffff8003ee116980 RADIX GICv2m 96+ 0x00063 GICv2 0xffff00000916bfd8 LINEAR GICv2 [output compressed to fit in a commit log] This shows that IRQ96 is implemented by a stack of three domains, the + sign indicating the stacking. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Link: http://lkml.kernel.org/r/20170512115538.10767-2-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
08332893e3
commit
fe17a42e70
|
@ -746,13 +746,54 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
|
|||
EXPORT_SYMBOL_GPL(irq_find_mapping);
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_DEBUG
|
||||
static void virq_debug_show_one(struct seq_file *m, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_domain *domain;
|
||||
struct irq_data *data;
|
||||
|
||||
domain = desc->irq_data.domain;
|
||||
data = &desc->irq_data;
|
||||
|
||||
while (domain) {
|
||||
unsigned int irq = data->irq;
|
||||
unsigned long hwirq = data->hwirq;
|
||||
struct irq_chip *chip;
|
||||
bool direct;
|
||||
|
||||
if (data == &desc->irq_data)
|
||||
seq_printf(m, "%5d ", irq);
|
||||
else
|
||||
seq_printf(m, "%5d+ ", irq);
|
||||
seq_printf(m, "0x%05lx ", hwirq);
|
||||
|
||||
chip = irq_data_get_irq_chip(data);
|
||||
seq_printf(m, "%-15s ", (chip && chip->name) ? chip->name : "none");
|
||||
|
||||
seq_printf(m, data ? "0x%p " : " %p ",
|
||||
irq_data_get_irq_chip_data(data));
|
||||
|
||||
seq_printf(m, " %c ", (desc->action && desc->action->handler) ? '*' : ' ');
|
||||
direct = (irq == hwirq) && (irq < domain->revmap_direct_max_irq);
|
||||
seq_printf(m, "%6s%-8s ",
|
||||
(hwirq < domain->revmap_size) ? "LINEAR" : "RADIX",
|
||||
direct ? "(DIRECT)" : "");
|
||||
seq_printf(m, "%s\n", domain->name);
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
domain = domain->parent;
|
||||
data = data->parent_data;
|
||||
#else
|
||||
domain = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int virq_debug_show(struct seq_file *m, void *private)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct irq_desc *desc;
|
||||
struct irq_domain *domain;
|
||||
struct radix_tree_iter iter;
|
||||
void *data, **slot;
|
||||
void **slot;
|
||||
int i;
|
||||
|
||||
seq_printf(m, " %-16s %-6s %-10s %-10s %s\n",
|
||||
|
@ -782,30 +823,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
|
|||
continue;
|
||||
|
||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||
domain = desc->irq_data.domain;
|
||||
|
||||
if (domain) {
|
||||
struct irq_chip *chip;
|
||||
int hwirq = desc->irq_data.hwirq;
|
||||
bool direct;
|
||||
|
||||
seq_printf(m, "%5d ", i);
|
||||
seq_printf(m, "0x%05x ", hwirq);
|
||||
|
||||
chip = irq_desc_get_chip(desc);
|
||||
seq_printf(m, "%-15s ", (chip && chip->name) ? chip->name : "none");
|
||||
|
||||
data = irq_desc_get_chip_data(desc);
|
||||
seq_printf(m, data ? "0x%p " : " %p ", data);
|
||||
|
||||
seq_printf(m, " %c ", (desc->action && desc->action->handler) ? '*' : ' ');
|
||||
direct = (i == hwirq) && (i < domain->revmap_direct_max_irq);
|
||||
seq_printf(m, "%6s%-8s ",
|
||||
(hwirq < domain->revmap_size) ? "LINEAR" : "RADIX",
|
||||
direct ? "(DIRECT)" : "");
|
||||
seq_printf(m, "%s\n", desc->irq_data.domain->name);
|
||||
}
|
||||
|
||||
virq_debug_show_one(m, desc);
|
||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue