Browse Source

[POWERPC] Export virq mapping via debugfs

This adds a debugfs file "powerpc/virq_mapping", which shows the virtual
to real mapping of irq numbers.  Enable it with CONFIG_VIRQ_DEBUG.

Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Chen Gong <G.Chen@freescale.com>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Michael Ellerman 17 years ago
parent
commit
60b332e755
2 changed files with 73 additions and 0 deletions
  1. 10 0
      arch/powerpc/Kconfig.debug
  2. 63 0
      arch/powerpc/kernel/irq.c

+ 10 - 0
arch/powerpc/Kconfig.debug

@@ -124,6 +124,16 @@ config IRQSTACKS
 	  for handling hard and soft interrupts.  This can help avoid
 	  for handling hard and soft interrupts.  This can help avoid
 	  overflowing the process kernel stacks.
 	  overflowing the process kernel stacks.
 
 
+config VIRQ_DEBUG
+	bool "Expose hardware/virtual IRQ mapping via debugfs"
+	depends on DEBUG_FS && PPC_MERGE
+	help
+	  This option will show the mapping relationship between hardware irq
+	  numbers and virtual irq numbers. The mapping is exposed via debugfs
+	  in the file powerpc/virq_mapping.
+
+	  If you don't know what this means you don't need it.
+
 config BDI_SWITCH
 config BDI_SWITCH
 	bool "Include BDI-2000 user context switcher"
 	bool "Include BDI-2000 user context switcher"
 	depends on DEBUG_KERNEL && PPC32
 	depends on DEBUG_KERNEL && PPC32

+ 63 - 0
arch/powerpc/kernel/irq.c

@@ -52,6 +52,7 @@
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/bootmem.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
+#include <linux/debugfs.h>
 
 
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/system.h>
@@ -1006,6 +1007,68 @@ static int irq_late_init(void)
 }
 }
 arch_initcall(irq_late_init);
 arch_initcall(irq_late_init);
 
 
+#ifdef CONFIG_VIRQ_DEBUG
+static int virq_debug_show(struct seq_file *m, void *private)
+{
+	unsigned long flags;
+	irq_desc_t *desc;
+	const char *p;
+	char none[] = "none";
+	int i;
+
+	seq_printf(m, "%-5s  %-7s  %-15s  %s\n", "virq", "hwirq",
+		      "chip name", "host name");
+
+	for (i = 1; i < NR_IRQS; i++) {
+		desc = get_irq_desc(i);
+		spin_lock_irqsave(&desc->lock, flags);
+
+		if (desc->action && desc->action->handler) {
+			seq_printf(m, "%5d  ", i);
+			seq_printf(m, "0x%05lx  ", virq_to_hw(i));
+
+			if (desc->chip && desc->chip->typename)
+				p = desc->chip->typename;
+			else
+				p = none;
+			seq_printf(m, "%-15s  ", p);
+
+			if (irq_map[i].host && irq_map[i].host->of_node)
+				p = irq_map[i].host->of_node->full_name;
+			else
+				p = none;
+			seq_printf(m, "%s\n", p);
+		}
+
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
+
+	return 0;
+}
+
+static int virq_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, virq_debug_show, inode->i_private);
+}
+
+static const struct file_operations virq_debug_fops = {
+	.open = virq_debug_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int __init irq_debugfs_init(void)
+{
+	if (debugfs_create_file("virq_mapping", S_IRUGO, powerpc_debugfs_root,
+				 NULL, &virq_debug_fops))
+		return -ENOMEM;
+
+	return 0;
+}
+__initcall(irq_debugfs_init);
+#endif /* CONFIG_VIRQ_DEBUG */
+
 #endif /* CONFIG_PPC_MERGE */
 #endif /* CONFIG_PPC_MERGE */
 
 
 #ifdef CONFIG_PPC64
 #ifdef CONFIG_PPC64