From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.mindbit.ro (xs1.mindbit.ro [80.86.107.70]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0E97C3DFC68 for ; Thu, 2 Apr 2026 17:27:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.86.107.70 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775150860; cv=none; b=om6fG+gE/xi31Qw8VQAeiqzEYS4F7o//aNu/DjwOcpdasSCnsf5AF9/uS/YmRqfYKzTwMKJI33UVVEGooqXNQn4oXujgrQMGBYYKthOKqnpd0QKdUW2+O2/WhQ2LFLwv/DKUNCX3mLI9Nw47PhCjwZumoxeM1NieNeuXlp8j9to= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775150860; c=relaxed/simple; bh=2AfkQst8I8nv+6N8Pq1J6SXUEeTGOtIz7466yyg9pGc=; h=Message-ID:Subject:From:To:Cc:Date:In-Reply-To:References: Content-Type:MIME-Version; b=COFU8Ouf1JFI4CLKMhovKlqEfCCIOVFn3qpJjtyKvKUN607yEfrpE0fV0RHwk0VIFrSRC041xQM4lUN358edbfMclyhjCh/qYYicbXiGATjWT7JFl81oCa1q9nfebrbyI16Wp/l4s7tHDAqm9EnzHYnDHc0nQOxW53rNFJ7B+78= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=rendec.net; spf=pass smtp.mailfrom=rendec.net; dkim=pass (2048-bit key) header.d=rendec.net header.i=@rendec.net header.b=pODhT6cQ; arc=none smtp.client-ip=80.86.107.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=rendec.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rendec.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rendec.net header.i=@rendec.net header.b="pODhT6cQ" Received: from dog.kanata.rendec.net (pool-174-112-193-187.cpe.net.cable.rogers.com [174.112.193.187]) by mail.mindbit.ro (Postfix) with ESMTPSA id 53C11C2526; Thu, 2 Apr 2026 20:27:33 +0300 (EEST) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.mindbit.ro 53C11C2526 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rendec.net; s=default; t=1775150854; bh=9MScSr/2AAOg5zD26oyNhEICrgl7WsXSvvKtnGnAH8Y=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=pODhT6cQE1q+hvwDMiFXIYu5/yCc6GnsxIQrCilv4RetjxYBxBudCyFWL0GWrln15 4DOQZZOnPWtwWahzsqFU9URnw7Fg/JTez/00Ihditm/Fb6S6hOz3iiYcjJrPxxzEgP qrJpYbWedZ31U52BvMU9qC+S8jkq1SUG1VhPYpQzMVYAC7334kcYBUtg3++AUKG+hj UThbZ9jQkaA660Aj/EwVQBAy9etLP5vQLrZhEUafSYO4jmcJ2GY+vtBZmvLIuU4aD6 9cLx2xZYlLIjtFtHdGSQn6BS4VdC43wDMmqjYriwuqPJjujQ2VTUpwcz+kPUane4Da ff1a3cM8OTfOg== Message-ID: <9979b635916ba7b2ea5cfb26e7eb4d97d2012cca.camel@rendec.net> Subject: Re: [patch V5 10/15] genirq: Cache the condition for /proc/interrupts exposure From: Radu Rendec To: Thomas Gleixner , LKML Cc: x86@kernel.org, Michael Kelley , Dmitry Ilvokhin , Jan Kiszka , Kieran Bingham , Florian Fainelli , Marc Zyngier Date: Thu, 02 Apr 2026 13:27:31 -0400 In-Reply-To: <20260401201348.694692490@kernel.org> References: <20260401195625.213446764@kernel.org> <20260401201348.694692490@kernel.org> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.56.2 (3.56.2-2.fc42) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 On Wed, 2026-04-01 at 23:52 +0200, Thomas Gleixner wrote: > From: Thomas Gleixner >=20 > show_interrupts() evaluates a boatload of conditions to establish whether > it should expose an interrupt in /proc/interrupts or not. >=20 > That can be simplified by caching the condition in an internal status fla= g, > which is updated when one of the relevant inputs changes. >=20 > The irq_desc::kstat_irq check is dropped because visible interrupt > descriptors always have a valid pointer. >=20 > As a result the number of instructions and branches for reading > /proc/interrupts is reduced significantly. >=20 > Signed-off-by: Thomas Gleixner > Reviewed-by: Dmitry Ilvokhin > --- > V4: Cover freeing of per CPU and NMI type interrupts > V3: Remove the historical kstat_irq check - Radu > V2: s/IRQF_/IRQ/ and fixup the enum treatment - Dmitry > --- > =C2=A0include/linux/irq.h=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0 1 + > =C2=A0kernel/irq/chip.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0= 2 ++ > =C2=A0kernel/irq/internals.h |=C2=A0=C2=A0=C2=A0 2 ++ > =C2=A0kernel/irq/manage.c=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0=C2=A0 8 +++++++= - > =C2=A0kernel/irq/proc.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0 15 ++= +++++++++---- > =C2=A0kernel/irq/settings.h=C2=A0 |=C2=A0=C2=A0 13 +++++++++++++ > =C2=A06 files changed, 36 insertions(+), 5 deletions(-) > --- a/include/linux/irq.h > +++ b/include/linux/irq.h > @@ -99,6 +99,7 @@ enum { > =C2=A0 IRQ_DISABLE_UNLAZY =3D (1 << 19), > =C2=A0 IRQ_HIDDEN =3D (1 << 20), > =C2=A0 IRQ_NO_DEBUG =3D (1 << 21), > + IRQ_RESERVED =3D (1 << 22), > =C2=A0}; > =C2=A0 > =C2=A0#define IRQF_MODIFY_MASK \ > --- a/kernel/irq/chip.c > +++ b/kernel/irq/chip.c > @@ -1004,6 +1004,7 @@ static void > =C2=A0 WARN_ON(irq_chip_pm_get(irq_desc_get_irq_data(desc))); > =C2=A0 irq_activate_and_startup(desc, IRQ_RESEND); > =C2=A0 } > + irq_proc_update_valid(desc); > =C2=A0} > =C2=A0 > =C2=A0void __irq_set_handler(unsigned int irq, irq_flow_handler_t handle,= int is_chained, > @@ -1064,6 +1065,7 @@ void irq_modify_status(unsigned int irq, > =C2=A0 trigger =3D tmp; > =C2=A0 > =C2=A0 irqd_set(&desc->irq_data, trigger); > + irq_proc_update_valid(desc); > =C2=A0 } > =C2=A0} > =C2=A0EXPORT_SYMBOL_GPL(irq_modify_status); > --- a/kernel/irq/internals.h > +++ b/kernel/irq/internals.h > @@ -123,6 +123,7 @@ extern void register_irq_proc(unsigned i > =C2=A0extern void unregister_irq_proc(unsigned int irq, struct irq_desc *= desc); > =C2=A0extern void register_handler_proc(unsigned int irq, struct irqactio= n *action); > =C2=A0extern void unregister_handler_proc(unsigned int irq, struct irqact= ion *action); > +void irq_proc_update_valid(struct irq_desc *desc); > =C2=A0#else > =C2=A0static inline void register_irq_proc(unsigned int irq, struct irq_d= esc *desc) { } > =C2=A0static inline void unregister_irq_proc(unsigned int irq, struct irq= _desc *desc) { } > @@ -130,6 +131,7 @@ static inline void register_handler_proc > =C2=A0 struct irqaction *action) { } > =C2=A0static inline void unregister_handler_proc(unsigned int irq, > =C2=A0 =C2=A0=C2=A0 struct irqaction *action) { } > +static inline void irq_proc_update_valid(struct irq_desc *desc) { } > =C2=A0#endif > =C2=A0 > =C2=A0extern bool irq_can_set_affinity_usr(unsigned int irq); > --- a/kernel/irq/manage.c > +++ b/kernel/irq/manage.c > @@ -1802,6 +1802,7 @@ static int > =C2=A0 __enable_irq(desc); > =C2=A0 } > =C2=A0 > + irq_proc_update_valid(desc); > =C2=A0 raw_spin_unlock_irqrestore(&desc->lock, flags); > =C2=A0 chip_bus_sync_unlock(desc); > =C2=A0 mutex_unlock(&desc->request_mutex); > @@ -1906,6 +1907,7 @@ static struct irqaction *__free_irq(stru > =C2=A0 desc->affinity_hint =3D NULL; > =C2=A0#endif > =C2=A0 > + irq_proc_update_valid(desc); > =C2=A0 raw_spin_unlock_irqrestore(&desc->lock, flags); > =C2=A0 /* > =C2=A0 * Drop bus_lock here so the changes which were done in the chip > @@ -2047,6 +2049,8 @@ static const void *__cleanup_nmi(unsigne > =C2=A0 irq_shutdown_and_deactivate(desc); > =C2=A0 } > =C2=A0 > + irq_proc_update_valid(desc); > + > =C2=A0 if (action) > =C2=A0 unregister_handler_proc(irq, action); > =C2=A0 kfree(action); > @@ -2433,8 +2437,10 @@ static struct irqaction *__free_percpu_i > =C2=A0 *action_ptr =3D action->next; > =C2=A0 > =C2=A0 /* Demote from NMI if we killed the last action */ > - if (!desc->action) > + if (!desc->action) { > =C2=A0 desc->istate &=3D ~IRQS_NMI; > + irq_proc_update_valid(desc); > + } > =C2=A0 } > =C2=A0 > =C2=A0 unregister_handler_proc(irq, action); > --- a/kernel/irq/proc.c > +++ b/kernel/irq/proc.c > @@ -439,6 +439,16 @@ void init_irq_proc(void) > =C2=A0 register_irq_proc(irq, desc); > =C2=A0} > =C2=A0 > +void irq_proc_update_valid(struct irq_desc *desc) > +{ > + u32 set =3D _IRQ_PROC_VALID; > + > + if (irq_settings_is_hidden(desc) || irq_desc_is_chained(desc) || !desc-= >action) > + set =3D 0; > + > + irq_settings_update_proc_valid(desc, set); > +} > + > =C2=A0#ifdef CONFIG_GENERIC_IRQ_SHOW > =C2=A0 > =C2=A0int __weak arch_show_interrupts(struct seq_file *p, int prec) > @@ -514,10 +524,7 @@ int show_interrupts(struct seq_file *p, > =C2=A0 > =C2=A0 guard(rcu)(); > =C2=A0 desc =3D irq_to_desc(i); > - if (!desc || irq_settings_is_hidden(desc)) > - return 0; > - > - if (!desc->action || irq_desc_is_chained(desc) || !desc->kstat_irqs) > + if (!desc || !irq_settings_proc_valid(desc)) > =C2=A0 return 0; > =C2=A0 > =C2=A0 seq_printf(p, "%*d:", prec, i); > --- a/kernel/irq/settings.h > +++ b/kernel/irq/settings.h > @@ -18,6 +18,7 @@ enum { > =C2=A0 _IRQ_DISABLE_UNLAZY =3D IRQ_DISABLE_UNLAZY, > =C2=A0 _IRQ_HIDDEN =3D IRQ_HIDDEN, > =C2=A0 _IRQ_NO_DEBUG =3D IRQ_NO_DEBUG, > + _IRQ_PROC_VALID =3D IRQ_RESERVED, > =C2=A0 _IRQF_MODIFY_MASK =3D IRQF_MODIFY_MASK, > =C2=A0}; > =C2=A0 > @@ -34,6 +35,7 @@ enum { > =C2=A0#define IRQ_DISABLE_UNLAZY GOT_YOU_MORON > =C2=A0#define IRQ_HIDDEN GOT_YOU_MORON > =C2=A0#define IRQ_NO_DEBUG GOT_YOU_MORON > +#define IRQ_RESERVED GOT_YOU_MORON > =C2=A0#undef IRQF_MODIFY_MASK > =C2=A0#define IRQF_MODIFY_MASK GOT_YOU_MORON > =C2=A0 > @@ -180,3 +182,14 @@ static inline bool irq_settings_no_debug > =C2=A0{ > =C2=A0 return desc->status_use_accessors & _IRQ_NO_DEBUG; > =C2=A0} > + > +static inline bool irq_settings_proc_valid(struct irq_desc *desc) > +{ > + return desc->status_use_accessors & _IRQ_PROC_VALID; > +} > + > +static inline void irq_settings_update_proc_valid(struct irq_desc *desc,= u32 set) > +{ > + desc->status_use_accessors &=3D ~_IRQ_PROC_VALID; > + desc->status_use_accessors |=3D (set & _IRQ_PROC_VALID); > +} Reviewed-by: Radu Rendec