The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@kernel.org>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, Michael Kelley <mhklinux@outlook.com>,
	Dmitry Ilvokhin <d@ilvokhin.com>, Radu Rendec <radu@rendec.net>,
	Jan Kiszka <jan.kiszka@siemens.com>,
	Kieran Bingham <kbingham@kernel.org>,
	Florian Fainelli <florian.fainelli@broadcom.com>,
	Marc Zyngier <maz@kernel.org>
Subject: [patch V6 15/16] genirq/proc: Runtime size the chip name
Date: Sun, 17 May 2026 22:02:44 +0200	[thread overview]
Message-ID: <20260517194932.085786035@kernel.org> (raw)
In-Reply-To: 20260517194421.705253664@kernel.org

From: Thomas Gleixner <tglx@kernel.org>

The chip name column in the /proc/interrupt output is 8 characters and
right aligned, which causes visual clutter due to the fixed length and the
alignment. Many interrupt chips, e.g. PCI/MSI[X] have way longer names.

Update the length when a chip is assigned to an interrupt and utilize this
information for the output. Align it left so all chip names start at the
begin of the column.

Update the GDB script as well and disentangle the header maze so it
actually works with all .config combinations.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Reviewed-by: Dmitry Ilvokhin <d@ilvokhin.com>
---
V6: Fix recursive header inclusion - 0day
V3: New patch
---
 kernel/irq/chip.c               |    6 +++--
 kernel/irq/debugfs.h            |   44 ++++++++++++++++++++++++++++++++++++
 kernel/irq/internals.h          |   48 ++--------------------------------------
 kernel/irq/irqdomain.c          |    5 +++-
 kernel/irq/proc.c               |   33 +++++++++++++++++++++++----
 kernel/irq/proc.h               |   13 ++++++++++
 scripts/gdb/linux/interrupts.py |   23 ++++++++++++-------
 7 files changed, 111 insertions(+), 61 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -47,9 +47,11 @@ int irq_set_chip(unsigned int irq, const
 		scoped_irqdesc->irq_data.chip = (struct irq_chip *)(chip ?: &no_irq_chip);
 		ret = 0;
 	}
-	/* For !CONFIG_SPARSE_IRQ make the irq show up in allocated_irqs. */
-	if (!ret)
+	if (!ret) {
+		/* For !CONFIG_SPARSE_IRQ make the irq show up in allocated_irqs. */
 		irq_mark_irq(irq);
+		irq_proc_update_chip(chip);
+	}
 	return ret;
 }
 EXPORT_SYMBOL(irq_set_chip);
--- /dev/null
+++ b/kernel/irq/debugfs.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _KERNEL_IRQ_DEBUGFS_H
+#define _KERNEL_IRQ_DEBUGFS_H
+
+#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
+#include <linux/debugfs.h>
+
+struct irq_bit_descr {
+	unsigned int	mask;
+	char		*name;
+};
+
+#define BIT_MASK_DESCR(m)	{ .mask = m, .name = #m }
+
+void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state,
+			 const struct irq_bit_descr *sd, int size);
+
+void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc);
+static inline void irq_remove_debugfs_entry(struct irq_desc *desc)
+{
+	debugfs_remove(desc->debugfs_file);
+	kfree(desc->dev_name);
+}
+void irq_debugfs_copy_devname(int irq, struct device *dev);
+# ifdef CONFIG_IRQ_DOMAIN
+void irq_domain_debugfs_init(struct dentry *root);
+# else
+static inline void irq_domain_debugfs_init(struct dentry *root)
+{
+}
+# endif
+#else /* CONFIG_GENERIC_IRQ_DEBUGFS */
+static inline void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *d)
+{
+}
+static inline void irq_remove_debugfs_entry(struct irq_desc *d)
+{
+}
+static inline void irq_debugfs_copy_devname(int irq, struct device *dev)
+{
+}
+#endif /* CONFIG_GENERIC_IRQ_DEBUGFS */
+
+#endif
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -12,6 +12,9 @@
 #include <linux/rcuref.h>
 #include <linux/sched/clock.h>
 
+#include "debugfs.h"
+#include "proc.h"
+
 #ifdef CONFIG_SPARSE_IRQ
 # define MAX_SPARSE_IRQS	INT_MAX
 #else
@@ -149,12 +152,6 @@ static inline void unregister_handler_pr
 static inline void irq_proc_update_valid(struct irq_desc *desc) { }
 #endif
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_GENERIC_IRQ_SHOW)
-void irq_proc_calc_prec(void);
-#else
-static inline void irq_proc_calc_prec(void) { }
-#endif
-
 struct irq_desc *irq_find_desc_at_or_after(unsigned int offset);
 
 extern bool irq_can_set_affinity_usr(unsigned int irq);
@@ -398,42 +395,3 @@ static inline struct irq_data *irqd_get_
 	return NULL;
 #endif
 }
-
-#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
-#include <linux/debugfs.h>
-
-struct irq_bit_descr {
-	unsigned int	mask;
-	char		*name;
-};
-
-#define BIT_MASK_DESCR(m)	{ .mask = m, .name = #m }
-
-void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state,
-			 const struct irq_bit_descr *sd, int size);
-
-void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc);
-static inline void irq_remove_debugfs_entry(struct irq_desc *desc)
-{
-	debugfs_remove(desc->debugfs_file);
-	kfree(desc->dev_name);
-}
-void irq_debugfs_copy_devname(int irq, struct device *dev);
-# ifdef CONFIG_IRQ_DOMAIN
-void irq_domain_debugfs_init(struct dentry *root);
-# else
-static inline void irq_domain_debugfs_init(struct dentry *root)
-{
-}
-# endif
-#else /* CONFIG_GENERIC_IRQ_DEBUGFS */
-static inline void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *d)
-{
-}
-static inline void irq_remove_debugfs_entry(struct irq_desc *d)
-{
-}
-static inline void irq_debugfs_copy_devname(int irq, struct device *dev)
-{
-}
-#endif /* CONFIG_GENERIC_IRQ_DEBUGFS */
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -20,6 +20,8 @@
 #include <linux/smp.h>
 #include <linux/fs.h>
 
+#include "proc.h"
+
 static LIST_HEAD(irq_domain_list);
 static DEFINE_MUTEX(irq_domain_mutex);
 
@@ -1532,6 +1534,7 @@ int irq_domain_set_hwirq_and_chip(struct
 	irq_data->chip = (struct irq_chip *)(chip ? chip : &no_irq_chip);
 	irq_data->chip_data = chip_data;
 
+	irq_proc_update_chip(chip);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(irq_domain_set_hwirq_and_chip);
@@ -2081,7 +2084,7 @@ static void irq_domain_free_one_irq(stru
 #endif	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 
 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
-#include "internals.h"
+#include "debugfs.h"
 
 static struct dentry *domain_dir;
 
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -456,10 +456,14 @@ int __weak arch_show_interrupts(struct s
 	return 0;
 }
 
+static DEFINE_RAW_SPINLOCK(irq_proc_constraints_lock);
+
 static struct irq_proc_constraints {
 	unsigned int	num_prec;
+	unsigned int	chip_width;
 } irq_proc_constraints __read_mostly = {
 	.num_prec	= 4,
+	.chip_width	= 8,
 };
 
 #ifndef ACTUAL_NR_IRQS
@@ -472,7 +476,23 @@ void irq_proc_calc_prec(void)
 
 	for (prec = 4, n = 10000; prec < 10 && n <= total_nr_irqs; ++prec)
 		n *= 10;
-	WRITE_ONCE(irq_proc_constraints.num_prec, prec);
+
+	guard(raw_spinlock_irqsave)(&irq_proc_constraints_lock);
+	if (prec > irq_proc_constraints.num_prec)
+		WRITE_ONCE(irq_proc_constraints.num_prec, prec);
+}
+
+void irq_proc_update_chip(const struct irq_chip *chip)
+{
+	unsigned int len = chip && chip->name ? strlen(chip->name) : 0;
+
+	if (!len || len <= READ_ONCE(irq_proc_constraints.chip_width))
+		return;
+
+	/* Can be invoked from interrupt disabled contexts */
+	guard(raw_spinlock_irqsave)(&irq_proc_constraints_lock);
+	if (len > irq_proc_constraints.chip_width)
+		WRITE_ONCE(irq_proc_constraints.chip_width, len);
 }
 
 /* Same as seq_put_decimal_ull_width(p, " ", cnt, 10) */
@@ -514,6 +534,7 @@ void irq_proc_emit_counts(struct seq_fil
 
 int show_interrupts(struct seq_file *p, void *v)
 {
+	unsigned int chip_width = READ_ONCE(irq_proc_constraints.chip_width);
 	unsigned int prec = READ_ONCE(irq_proc_constraints.num_prec);
 	int i = *(loff_t *) v, j;
 	struct irqaction *action;
@@ -549,18 +570,20 @@ int show_interrupts(struct seq_file *p,
 		irq_proc_emit_counts(p, &desc->kstat_irqs->cnt);
 	else
 		irq_proc_emit_zero_counts(p, num_online_cpus());
-	seq_putc(p, ' ');
+
+	/* Enforce a visual gap */
+	seq_write(p, "  ", 2);
 
 	guard(raw_spinlock_irq)(&desc->lock);
 	if (desc->irq_data.chip) {
 		if (desc->irq_data.chip->irq_print_chip)
 			desc->irq_data.chip->irq_print_chip(&desc->irq_data, p);
 		else if (desc->irq_data.chip->name)
-			seq_printf(p, "%8s", desc->irq_data.chip->name);
+			seq_printf(p, "%-*s", chip_width, desc->irq_data.chip->name);
 		else
-			seq_printf(p, "%8s", "-");
+			seq_printf(p, "%-*s", chip_width, "-");
 	} else {
-		seq_printf(p, "%8s", "None");
+		seq_printf(p, "%-*s", chip_width, "None");
 	}
 
 	seq_putc(p, ' ');
--- /dev/null
+++ b/kernel/irq/proc.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _KERNEL_IRQ_PROC_H
+#define _KERNEL_IRQ_PROC_H
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_GENERIC_IRQ_SHOW)
+void irq_proc_calc_prec(void);
+void irq_proc_update_chip(const struct irq_chip *chip);
+#else
+static inline void irq_proc_calc_prec(void) { }
+static inline void irq_proc_update_chip(const struct irq_chip *chip) { }
+#endif
+
+#endif
--- a/scripts/gdb/linux/interrupts.py
+++ b/scripts/gdb/linux/interrupts.py
@@ -20,7 +20,7 @@ irq_desc_type = utils.CachedType("struct
 def irqd_is_level(desc):
     return desc['irq_data']['common']['state_use_accessors'] & constants.LX_IRQD_LEVEL
 
-def show_irq_desc(prec, irq):
+def show_irq_desc(prec, chip_width, irq):
     text = ""
 
     desc = mapletree.mtree_load(gdb.parse_and_eval("&sparse_irqs"), irq)
@@ -58,7 +58,7 @@ irq_desc_type = utils.CachedType("struct
         else:
             name = "-"
 
-    text += "  %-8s" % (name)
+    text += "  %-*s" % (chip_width, name)
 
     if desc['irq_data']['domain']:
         text += "  %*lu" % (prec, desc['irq_data']['hwirq'])
@@ -171,11 +171,18 @@ irq_desc_type = utils.CachedType("struct
 
     def invoke(self, arg, from_tty):
         nr_irqs = gdb.parse_and_eval("total_nr_irqs")
-        prec = 4
-        j = 10000
-        while prec < 10 and j <= nr_irqs:
-            prec += 1
-            j *= 10
+        constr = utils.gdb_eval_or_none('irq_proc_constraints')
+
+        if constr:
+            prec = int(constr['num_prec'])
+            chip_width = int(constr['chip_width'])
+        else:
+            prec = 4
+            j = 10000
+            while prec < 10 and j <= nr_irqs:
+                prec += 1
+                j *= 10
+            chip_width = 8
 
         gdb.write("%*s" % (prec + 8, ""))
         for cpu in cpus.each_online_cpu():
@@ -186,7 +193,7 @@ irq_desc_type = utils.CachedType("struct
             raise gdb.GdbError("Unable to find the sparse IRQ tree, is CONFIG_SPARSE_IRQ enabled?")
 
         for irq in range(nr_irqs):
-            gdb.write(show_irq_desc(prec, irq))
+            gdb.write(show_irq_desc(prec, chip_width, irq))
         gdb.write(arch_show_interrupts(prec))
 
 


  parent reply	other threads:[~2026-05-17 20:02 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-17 20:01 [patch V6 00/16] Improve /proc/interrupts further Thomas Gleixner
2026-05-17 20:01 ` [patch V6 01/16] x86/irq: Optimize interrupts decimals printing Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Dmitry Ilvokhin
2026-05-17 20:01 ` [patch V6 02/16] genirq/proc: Avoid formatting zero counts in /proc/interrupts Thomas Gleixner
2026-05-19 21:24   ` Shrikanth Hegde
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:01 ` [patch V6 03/16] genirq/proc: Utilize irq_desc::tot_count to avoid evaluation Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:01 ` [patch V6 04/16] x86/irq: Make irqstats array based Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:01 ` [patch V6 05/16] x86/irq: Suppress unlikely interrupt stats by default Thomas Gleixner
2026-05-21 15:52   ` Shrikanth Hegde
2026-05-21 20:46     ` Thomas Gleixner
2026-05-23 17:48   ` Shrikanth Hegde
2026-05-24 12:37     ` Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:01 ` [patch V6 06/16] x86/irq: Move IOAPIC misrouted and PIC/APIC error counts into irq_stats Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 07/16] scripts/gdb: Update x86 interrupts to the array based storage Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 08/16] genirq: Expose nr_irqs in core code Thomas Gleixner
2026-05-19 21:29   ` Shrikanth Hegde
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 09/16] genirq/manage: Make NMI cleanup RT safe Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 10/16] genirq: Cache the condition for /proc/interrupts exposure Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 11/16] genirq: Calculate precision only when required Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 12/16] genirq/proc: Increase default interrupt number precision to four Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 13/16] genirq: Add rcuref count to struct irq_desc Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 14/16] genirq: Expose irq_find_desc_at_or_after() in core code Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` Thomas Gleixner [this message]
2026-05-26 14:22   ` [tip: irq/core] genirq/proc: Runtime size the chip name tip-bot2 for Thomas Gleixner
2026-05-17 20:02 ` [patch V6 16/16] genirq/proc: Speed up /proc/interrupts iteration Thomas Gleixner
2026-05-26 14:22   ` [tip: irq/core] " tip-bot2 for Thomas Gleixner
2026-05-18  3:54 ` [patch V6 00/16] Improve /proc/interrupts further mhklkml
2026-05-19 21:18 ` Shrikanth Hegde
2026-05-20 15:27   ` Thomas Gleixner
2026-05-21  4:34     ` Shrikanth Hegde
2026-05-21  7:53       ` Thomas Gleixner
2026-05-21 14:48         ` Shrikanth Hegde
2026-05-21 21:07           ` Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260517194932.085786035@kernel.org \
    --to=tglx@kernel.org \
    --cc=d@ilvokhin.com \
    --cc=florian.fainelli@broadcom.com \
    --cc=jan.kiszka@siemens.com \
    --cc=kbingham@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=mhklinux@outlook.com \
    --cc=radu@rendec.net \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox