mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Rosen Penev <rosenp@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Thomas Gleixner <tglx@kernel.org>, Radu Rendec <radu@rendec.net>,
	Dmitry Ilvokhin <d@ilvokhin.com>,
	Waiman Long <longman@redhat.com>,
	Davidlohr Bueso <dbueso@suse.de>, Marc Zyngier <maz@kernel.org>
Subject: [PATCH] genirq: Ignore tot_count for handle_percpu_irq() interrupts
Date: Thu,  5 Nov 2026 21:19:59 -0800	[thread overview]
Message-ID: <20261106051959.901861-1-rosenp@gmail.com> (raw)

handle_percpu_irq() only increments the per CPU statistics and leaves
desc::tot_count untouched, but nothing marks the descriptors that use it
as per CPU. Both /proc/interrupts and kstat_irqs_desc() treat such an
interrupt as a device interrupt and trust desc::tot_count, which stays
zero.

Since /proc/interrupts started to emit zeros for device interrupts with
a zero desc::tot_count, every MIPS CPU interrupt reads as zero there,
including the timer and every device behind it. /proc/interrupts also
missed NMIs handled by handle_fasteoi_nmi(), which kstat_irqs_desc()
already excluded. The /proc/stat counts of handle_percpu_irq() users
have been zero since kstat_irqs_desc() started to use desc::tot_count.

Add irq_desc_has_tot_count(), which covers per CPU interrupts, NMIs and
handle_percpu_irq() users, and use it in both places.

Seen on ASUS RT-N16 and TP-LINK Archer C7 v2 (both MIPS 74K) router, where
the "gpio, ttyS0" lines stayed at zero while the GPIO interrupts chained
behind it counted.

Fixes: 0179464391af ("genirq/proc: Utilize irq_desc::tot_count to avoid evaluation")
Fixes: 1136b0728969 ("genirq: Avoid summation loops for /proc/stat")
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 kernel/irq/internals.h | 12 ++++++++++++
 kernel/irq/irqdesc.c   |  4 +---
 kernel/irq/proc.c      |  7 +++----
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 703a062be878..70dd3a010ce8 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -302,6 +302,18 @@ static inline bool irq_is_nmi(struct irq_desc *desc)
 	return desc->istate & IRQS_NMI;
 }
 
+/*
+ * Per CPU interrupts, NMIs and interrupts handled by handle_percpu_irq()
+ * only update the per CPU statistics and leave desc::tot_count alone.
+ */
+static inline bool irq_desc_has_tot_count(struct irq_desc *desc)
+{
+	return !irq_settings_is_per_cpu_devid(desc) &&
+	       !irq_settings_is_per_cpu(desc) &&
+	       !irq_is_nmi(desc) &&
+	       desc->handle_irq != handle_percpu_irq;
+}
+
 #ifdef CONFIG_PM_SLEEP
 void irq_pm_handle_wakeup(struct irq_desc *desc);
 void irq_pm_install_action(struct irq_desc *desc, struct irqaction *action);
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 7cbcc3fb9e6d..3f7bfe0adfd7 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -1020,9 +1020,7 @@ static unsigned int kstat_irqs_desc(struct irq_desc *desc, const struct cpumask
 	unsigned int sum = 0;
 	int cpu;
 
-	if (!irq_settings_is_per_cpu_devid(desc) &&
-	    !irq_settings_is_per_cpu(desc) &&
-	    !irq_is_nmi(desc))
+	if (irq_desc_has_tot_count(desc))
 		return data_race(desc->tot_count);
 
 	for_each_cpu(cpu, cpumask)
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 0c0df16de581..c985515f5030 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -559,11 +559,10 @@ static int irq_seq_show(struct seq_file *p, void *v)
 	seq_putc(p, ':');
 
 	/*
-	 * Always output per CPU interrupts. Output device interrupts only when
-	 * desc::tot_count is not zero.
+	 * Always output interrupts which do not maintain desc::tot_count.
+	 * Output the others only when desc::tot_count is not zero.
 	 */
-	if (irq_settings_is_per_cpu(desc) || irq_settings_is_per_cpu_devid(desc) ||
-	    data_race(desc->tot_count))
+	if (!irq_desc_has_tot_count(desc) || data_race(desc->tot_count))
 		irq_proc_emit_counts(p, &desc->kstat_irqs->cnt);
 	else
 		irq_proc_emit_zero_counts(p, num_online_cpus());
-- 
2.56.0


                 reply	other threads:[~2026-11-06  5:20 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20261106051959.901861-1-rosenp@gmail.com \
    --to=rosenp@gmail.com \
    --cc=d@ilvokhin.com \
    --cc=dbueso@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=maz@kernel.org \
    --cc=radu@rendec.net \
    --cc=tglx@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

all inboxes | Powered by JetHome®