irqdomain: Let irq_domain_mapping display hierarchical domains
authorMarc Zyngier <marc.zyngier@arm.com>
Fri, 12 May 2017 11:55:35 +0000 (12:55 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Mon, 22 May 2017 20:29:44 +0000 (22:29 +0200)
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>
kernel/irq/irqdomain.c

index 31805f2..1f6cd2c 100644 (file)
@@ -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);
        }