From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
To: Ciju Rajan K <crajank@nvidia.com>
Cc: hdegoede@redhat.com, ilpo.jarvinen@linux.intel.com,
tglx@linutronix.de, christophe.jaillet@wanadoo.fr,
vadimp@nvidia.com, platform-driver-x86@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH platform-next v4 1/2] kernel/irq: Add generic interrupt storm detection mechanism
Date: Thu, 15 Jan 2026 10:29:14 +0200 [thread overview]
Message-ID: <aWilWsTaAZeH8x1x@smile.fi.intel.com> (raw)
In-Reply-To: <20260115074909.245852-2-crajank@nvidia.com>
On Thu, Jan 15, 2026 at 09:49:08AM +0200, Ciju Rajan K wrote:
> If the hardware is broken, it is possible that faulty device will
> flood interrupt handler with false events. For example, if fan or
> power supply has damaged presence pin, it will cause permanent
I would say "has a floating presence pin" as the term floating is
well established and describes the case exactly how you put it further
in the text.
> generation of plugged in / plugged out events. As a result, interrupt
> handler will consume a lot of CPU resources and will keep raising
> "UDEV" events to the user space.
>
> This patch provides a mechanism for detecting interrupt storm.
> Use the following criteria: if the specific interrupt was generated
> 'N' times during 'T' seconds, such device is to be considered as
> broken and user will be notified through a call back function.
> This feature can be used by any kernel subsystems or drivers.
>
> The implementation includes:
>
> - irq_storm_cb_t: Callback function type for storm notifications
> - struct irq_storm: Per-IRQ storm detection data structure
> - irq_register_storm_detection(): Register storm detection with
> configurable parameters
> - irq_unregister_storm_detection(): Unregister storm detection
> - Integration with note_interrupt() for automatic storm checking
>
> Callback API parameters:
> - irq: interrupt number to monitor
> - max_freq: maximum allowed frequency (interrupts per second)
> - dev_id: device identifier passed to callback
...
> --- a/include/linux/interrupt.h
> +++ b/include/linux/interrupt.h
> @@ -20,6 +20,7 @@
> #include <asm/ptrace.h>
> #include <asm/irq.h>
> #include <asm/sections.h>
> +#include <linux/jiffies.h>
I would not mix linux/* group with asm/* group and to me the best location for
this inclusion is just before kref.h. Note, this header needs a bit more of
a cleanup, as it includes basically everything (due to kernel.h and maybe other
messed up headers). But this is out of scope of your series.
...
> extern int irq_can_set_affinity(unsigned int irq);
> extern int irq_select_affinity(unsigned int irq);
> +extern bool irq_register_storm_detection(unsigned int irq, unsigned int max_freq,
> + irq_storm_cb_t cb, void *dev_id);
> +extern void irq_unregister_storm_detection(unsigned int irq);
Do we still need "extern" keyword?
> extern int __irq_apply_affinity_hint(unsigned int irq, const struct cpumask *m,
> bool setaffinity);
...
> +struct irq_storm {
> + unsigned long max_cnt;
> + unsigned long last_cnt;
> + unsigned long next_period;
> + irq_storm_cb_t cb;
> + void *dev_id;
> +};
I'm wondering if you have tried to shuffle this layout based on the frequency
of a use of each member. In some cases it might generate less code (can be
measured with bloat-o-meter).
...
> static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id)
> irq_release_resources(desc);
> chip_bus_sync_unlock(desc);
> irq_remove_timings(desc);
> + if (desc->irq_storm) {
Unneeded (duplicate) check.
> + kfree(desc->irq_storm);
> + desc->irq_storm = NULL;
Do we need this? If so, still can be done unconditionally.
> + }
> }
> +/* Minimum frequency threshold */
> +#define IRQ_STORM_MIN_FREQ_HZ 50
> +#define IRQ_STORM_MAX_FREQ_SCALE (IRQ_STORM_MIN_FREQ_HZ * 2)
Plain numbers are easier to read, hence 100
> +/* Time window over which storm check is performed */
> +#define IRQ_STORM_PERIOD_WINDOW_MS (IRQ_STORM_MIN_FREQ_HZ * 20)
MS = HZ?! It's from some other universe with different physics laws.
...
> + * Returns: true on success, false on failure
Are the rest use "Returns" (with "s")? Because the main keyword is "Return".
(Yes, "Returns" works, but it's a secondary one, not even documented IIRC.)
...
> +bool irq_register_storm_detection(unsigned int irq, unsigned int max_freq,
> + irq_storm_cb_t cb, void *dev_id)
> +{
> + struct irq_storm *storm;
> + bool ret = false;
> +
> + if (max_freq < IRQ_STORM_MIN_FREQ_HZ || !cb)
> + return false;
> +
> + storm = kzalloc(sizeof(*storm), GFP_KERNEL);
> + if (!storm)
> + return false;
> +
> + /* Adjust to count per 10ms */
> + storm->max_cnt = max_freq / (IRQ_STORM_MAX_FREQ_SCALE);
> + storm->cb = cb;
> + storm->dev_id = dev_id;
> +
> + scoped_irqdesc_get_and_buslock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
> + if (scoped_irqdesc->action && !scoped_irqdesc->irq_storm) {
> + storm->last_cnt = scoped_irqdesc->tot_count;
> + storm->next_period = jiffies + msecs_to_jiffies(IRQ_STORM_PERIOD_WINDOW_MS);
> + scoped_irqdesc->irq_storm = storm;
> + ret = true;
> + }
> + }
> + if (!ret)
> + kfree(storm);
> +
> + return ret;
Better to avoid negative conditionals in such contexts.
if (ret)
return ret;
kfree(...);
But it's boolean and assigned inside scoped section. Why we can't return true
directly from scoped section?
> +}
...
> +void irq_unregister_storm_detection(unsigned int irq)
> +{
> + scoped_irqdesc_get_and_buslock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
> + if (scoped_irqdesc->irq_storm) {
Dup check, drop it.
> + kfree(scoped_irqdesc->irq_storm);
> + scoped_irqdesc->irq_storm = NULL;
> + }
> + }
> +}
...
> +static void irq_storm_check(struct irq_desc *desc)
> +{
> + struct irq_storm *storm = desc->irq_storm;
> + unsigned long delta, now = jiffies;
> +
> + if (!time_after_eq(now, storm->next_period))
> + return;
> + storm->next_period = now + msecs_to_jiffies(IRQ_STORM_PERIOD_WINDOW_MS);
Just do
#define IRQ_STORM_PERIOD_WINDOW msecs_to_jiffies(1000)
It will address my above comment and make this be read better.
> + delta = desc->tot_count - storm->last_cnt;
> + storm->last_cnt = desc->tot_count;
> + if (delta > storm->max_cnt) {
> + /* Calculate actual frequency: interrupts per second */
> + storm->cb(irq_desc_get_irq(desc),
> + (delta * (IRQ_STORM_MAX_FREQ_SCALE)),
> + storm->dev_id);
> + }
> +}
--
With Best Regards,
Andy Shevchenko
next prev parent reply other threads:[~2026-01-15 8:29 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-15 7:49 [PATCH platform-next v4 0/2] Interrupt storm detection Ciju Rajan K
2026-01-15 7:49 ` [PATCH platform-next v4 1/2] kernel/irq: Add generic interrupt storm detection mechanism Ciju Rajan K
2026-01-15 8:29 ` Andy Shevchenko [this message]
2026-01-15 14:00 ` kernel test robot
2026-01-15 14:11 ` kernel test robot
2026-01-15 7:49 ` [PATCH platform-next v4 2/2] platform/mellanox: mlxreg-hotplug: Enabling interrupt storm detection Ciju Rajan K
2026-01-15 8:34 ` Andy Shevchenko
2026-01-15 14:43 ` kernel test robot
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=aWilWsTaAZeH8x1x@smile.fi.intel.com \
--to=andriy.shevchenko@linux.intel.com \
--cc=christophe.jaillet@wanadoo.fr \
--cc=crajank@nvidia.com \
--cc=hdegoede@redhat.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=platform-driver-x86@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=vadimp@nvidia.com \
/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.