[patch V5 00/15] Improve /proc/interrupts further
From: Thomas Gleixner
Date: Wed Apr 01 2026 - 17:51:36 EST
This is a follow up to v4 which can be found here:
https://lore.kernel.org/20260331071453.172185305@xxxxxxxxxx
The v1 cover letter contains a full analysis, explanation and numbers:
https://lore.kernel.org/20260303150539.513068586@xxxxxxxxxx
TLDR:
- The performance of reading of /proc/interrupts has been improved
piecewise over the years, but most of the low hanging fruit has been
left on the table.
Changes vs. V4:
- Moved the header printing ahead of the architecture and update comment
- Dmitry
- Fix the gdbscript so it works with a bitmap larger than one entry and
bring show_irq_err_count() back as it's required by MIPS
- Removed unused variable and resort hunks so it's bisectable.
Delta patch against v4 is below.
The series applies on top of v7.0-rc3 and is also available via git:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git irq-proc-v5
Thanks,
tglx
---
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index ae8b06e01948..7eb07e3bdb4c 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2066,7 +2066,6 @@ static const void *__cleanup_nmi(unsigned int irq, struct irq_desc *desc)
const void *free_nmi(unsigned int irq, void *dev_id)
{
struct irq_desc *desc = irq_to_desc(irq);
- void *ret;
if (!desc || WARN_ON(!irq_is_nmi(desc)))
return NULL;
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index a62d4694f063..3bd394aa7617 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -540,10 +540,7 @@ static int irq_seq_show(struct seq_file *p, void *v)
struct irq_desc *desc = v;
struct irqaction *action;
- if (desc == ARCH_PROC_IRQDESC)
- return arch_show_interrupts(p, constr->num_prec);
-
- /* print header for the first interrupt indicated by !p>private */
+ /* Print header for the first interrupt? */
if (constr->print_header) {
unsigned int cpu;
@@ -554,6 +551,9 @@ static int irq_seq_show(struct seq_file *p, void *v)
constr->print_header = false;
}
+ if (desc == ARCH_PROC_IRQDESC)
+ return arch_show_interrupts(p, constr->num_prec);
+
seq_put_decimal_ull_width(p, "", irq_desc_get_irq(desc), constr->num_prec);
seq_putc(p, ':');
@@ -617,9 +617,9 @@ static void *irq_seq_next_desc(loff_t *pos)
if (desc) {
*pos = irq_desc_get_irq(desc);
/*
- * If valid for output try to acquire a reference count
- * on the descriptor so that it can't be freed after
- * dropping RCU read lock on return.
+ * If valid for output then try to acquire a reference
+ * count on the descriptor so that it can't be freed
+ * after dropping RCU read lock on return.
*/
if (irq_settings_proc_valid(desc) && irq_desc_get_ref(desc))
return desc;
diff --git a/scripts/gdb/linux/interrupts.py b/scripts/gdb/linux/interrupts.py
index 418f3ece2f0f..cf0a02c8124d 100644
--- a/scripts/gdb/linux/interrupts.py
+++ b/scripts/gdb/linux/interrupts.py
@@ -103,12 +103,12 @@ def x86_show_interupts(prec):
info_type = gdb.lookup_type('struct irq_stat_info')
info = gdb.parse_and_eval('irq_stat_info')
bitmap = gdb.parse_and_eval('irq_stat_count_show')
- nbits = 8 * int(bitmap.type.sizeof)
+ bitsperlong = 8 * int(bitmap.type.target().sizeof)
text = ""
for idx in range(int(info.type.sizeof / info_type.sizeof)):
- show = bitmap[idx / nbits]
- if not show & 1 << (idx % nbits):
+ show = bitmap[int(idx / bitsperlong)]
+ if not show & 1 << int(idx % bitsperlong):
continue
pfx = info[idx]['symbol'].string()
desc = info[idx]['text'].string()
@@ -145,6 +145,13 @@ def aarch64_show_interrupts(prec):
text += "%*s: %10lu\n" % (prec, "ERR", gdb.parse_and_eval("irq_err_count"))
return text
+def show_irq_err_count(prec):
+ cnt = utils.gdb_eval_or_none("irq_err_count")
+ text = ""
+ if cnt is not None:
+ text += "%*s: %10u\n" % (prec, "ERR", cnt['counter'])
+ return text
+
def arch_show_interrupts(prec):
text = ""
if utils.is_target_arch("x86"):