All of lore.kernel.org
 help / color / mirror / Atom feed
From: Radu Rendec <radu@rendec.net>
To: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
	Helge Deller <deller@gmx.de>, Thomas Gleixner <tglx@kernel.org>
Cc: linux-parisc@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 1/2] genirq: Remove unnecessary NULL check of the kstat_irqs field
Date: Sun,  5 Jul 2026 17:09:50 -0400	[thread overview]
Message-ID: <20260705210951.2717741-2-radu@rendec.net> (raw)
In-Reply-To: <20260705210951.2717741-1-radu@rendec.net>

The kstat_irqs field of struct irq_desc is used to store a per-cpu count
of interrupt events. It is initialized in init_desc(), along with all
the other fields in struct irq_desc that need explicit initialization,
and therefore it's always available (non-NULL) for any valid interrupt
descriptor (with a caveat - see below).

When CONFIG_SPARSE_IRQ is enabled, all interrupt descriptors are always
allocated dynamically via alloc_desc(), which calls init_desc(), so in
that case kstat_irqs is guaranteed to be non-NULL before a valid struct
irq_desc pointer is even returned.

By contrast, when CONFIG_SPARSE_IRQ is disabled, interrupt descriptors
are allocated statically in the irq_desc[] array, and kstat_irqs is
initialized implicitly to NULL. The per-cpu pointer is initialized only
later, for all descriptors, via start_kernel() -> early_irq_init() ->
init_desc().

The kstat_irqs field is used mostly for printing interrupt statistics
(i.e. reading /proc/interrupts), and that cannot happen until much
later, when user-space is fully initialized. So, there is no concern
with that use case.

The list below includes all functions where the NULL check is removed,
along with a list of all possible call chains and/or a brief explanation
of why it's safe to remove the NULL check in that case.

* irq_desc_kstat_cpu() [include/linux/irqdesc.h]
  - All direct call sites use it for printing IRQ statistics.
  - Indirect call site: per_cpu_count_show() - also used for printing
    IRQ statistics.
* kstat_irqs_cpu() [kernel/irq/irqdesc.c]
  - Called by sun3_int7() and sun3_int5() [arch/m68k/sun3/sun3ints.c]
    These are interrupt handlers and cannot be called until their
    corresponding interrupts are initialized in sun3_init_IRQ(). The
    call chain leading to that is:
      start_kernel() -> init_IRQ() [arch/m68k/kernel/ints.c] ->
      mach_init_IRQ = sun3_init_IRQ()
    The init_IRQ() call happens right *after* the early_irq_init() call,
    which means the descriptors are already fully initialized by the
    time the interrupt handlers are even registered.
  - Called by show_interrupts() [arch/s390/kernel/irq.c] - used for
    printing IRQ statistics.
* kstat_irqs() [kernel/irq/irqdesc.c]
  The only possible call chain is via fs/proc/stat.c:
    stat_open() -> show_stat() -> show_all_irqs() -> kstat_irqs_usr() ->
    kstat_irqs()
  It is used for printing IRQ statistics.
* kstat_snapshot_irqs()
  The only possible call chain is via kernel/watchdog.c:
    watchdog_timer_fn() -> is_softlockup() -> start_counting_irqs() ->
    kstat_snapshot_irqs()
  The watchdog timer cannot fire early, before early_irq_init().
* kstat_get_irq_since_snapshot()
  The only possible call chain is via kernel/watchdog.c:
    watchdog_timer_fn() -> report_cpu_status() -> print_irq_counts() ->
    kstat_get_irq_since_snapshot()
  The watchdog timer cannot fire early, before early_irq_init().

Signed-off-by: Radu Rendec <radu@rendec.net>
---
 include/linux/irqdesc.h |  2 +-
 kernel/irq/irqdesc.c    | 11 ++++-------
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index 8080db17c1b1..779d6023c5c2 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -146,7 +146,7 @@ extern struct irq_desc irq_desc[NR_IRQS];
 static inline unsigned int irq_desc_kstat_cpu(struct irq_desc *desc,
 					      unsigned int cpu)
 {
-	return desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, cpu) : 0;
+	return per_cpu(desc->kstat_irqs->cnt, cpu);
 }
 
 static inline struct irq_desc *irq_data_to_desc(struct irq_data *data)
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 80ef4e27dcf4..3a818f07a101 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -1004,7 +1004,7 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	return desc && desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, cpu) : 0;
+	return desc ? irq_desc_kstat_cpu(desc, cpu) : 0;
 }
 
 static unsigned int kstat_irqs_desc(struct irq_desc *desc, const struct cpumask *cpumask)
@@ -1026,7 +1026,7 @@ static unsigned int kstat_irqs(unsigned int irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	if (!desc || !desc->kstat_irqs)
+	if (!desc)
 		return 0;
 	return kstat_irqs_desc(desc, cpu_possible_mask);
 }
@@ -1038,18 +1038,15 @@ void kstat_snapshot_irqs(void)
 	struct irq_desc *desc;
 	unsigned int irq;
 
-	for_each_irq_desc(irq, desc) {
-		if (!desc->kstat_irqs)
-			continue;
+	for_each_irq_desc(irq, desc)
 		this_cpu_write(desc->kstat_irqs->ref, this_cpu_read(desc->kstat_irqs->cnt));
-	}
 }
 
 unsigned int kstat_get_irq_since_snapshot(unsigned int irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	if (!desc || !desc->kstat_irqs)
+	if (!desc)
 		return 0;
 	return this_cpu_read(desc->kstat_irqs->cnt) - this_cpu_read(desc->kstat_irqs->ref);
 }
-- 
2.54.0


  reply	other threads:[~2026-07-05 21:11 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-05 21:09 [PATCH 0/2] Remove unnecessary NULL check of the kstat_irqs field Radu Rendec
2026-07-05 21:09 ` Radu Rendec [this message]
2026-07-07 19:39   ` [tip: irq/core] genirq: " tip-bot2 for Radu Rendec
2026-07-05 21:09 ` [PATCH 2/2] parisc: " Radu Rendec
2026-07-07 19:38   ` [tip: irq/core] " tip-bot2 for Radu Rendec

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=20260705210951.2717741-2-radu@rendec.net \
    --to=radu@rendec.net \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=deller@gmx.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-parisc@vger.kernel.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.