summaryrefslogtreecommitdiff
path: root/kernel/irq/spurious.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-07-29 22:55:12 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2025-07-29 22:55:12 +0300
commitdba3ec9f2ad085f05528ccd36d6835b06b5370cd (patch)
tree05777ad148977140291c316c58ef9b6a9fa53159 /kernel/irq/spurious.c
parent5623870d9b4f1b9bd4a8b75544f2f9ed2a49afff (diff)
parent8d39d6ec4db5da9899993092227584a97c203fd3 (diff)
downloadlinux-dba3ec9f2ad085f05528ccd36d6835b06b5370cd.tar.xz
Merge tag 'irq-core-2025-07-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq updates from Thomas Gleixner: - Prevent a interrupt migration related live lock in handle_edge_irq() If the interrupt affinity is moved to a new target CPU and the interrupt is currently handled on the previous target CPU for edge type interrupts the handler might get stuck on the previous target for a long time, which causes both involved CPUs to waste cycles and eventually run into a soft-lockup situation. Solve this by checking whether the interrupt is redirected to a new target CPU and if the interrupt is handled on that new target CPU, busy wait for completion instead of masking it and sending the pending but which would cause the old CPU to re-run the handler and in the worst case repeating this excercise for a long time. This only works on architectures which use single CPU interrupt targets, but that's so far the only ones where this behaviour has been observed. - Add a kunit test for interrupt disable depth counts The nested interrupt disable depth has been an issue in the past especially vs. free_irq(), interrupt shutdown and CPU hotplug and their interactions. The test exercises the combinations of these scenarios and checks for correctness. * tag 'irq-core-2025-07-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: genirq: Prevent migration live lock in handle_edge_irq() genirq: Split up irq_pm_check_wakeup() genirq: Move irq_wait_for_poll() to call site genirq: Remove pointless local variable genirq: Add kunit tests for depth counts
Diffstat (limited to 'kernel/irq/spurious.c')
-rw-r--r--kernel/irq/spurious.c37
1 files changed, 1 insertions, 36 deletions
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 8f26982e7300..73280ccb74b0 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -19,45 +19,10 @@ static int irqfixup __read_mostly;
#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10)
static void poll_spurious_irqs(struct timer_list *unused);
static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs);
-static int irq_poll_cpu;
+int irq_poll_cpu;
static atomic_t irq_poll_active;
/*
- * We wait here for a poller to finish.
- *
- * If the poll runs on this CPU, then we yell loudly and return
- * false. That will leave the interrupt line disabled in the worst
- * case, but it should never happen.
- *
- * We wait until the poller is done and then recheck disabled and
- * action (about to be disabled). Only if it's still active, we return
- * true and let the handler run.
- */
-bool irq_wait_for_poll(struct irq_desc *desc)
-{
- lockdep_assert_held(&desc->lock);
-
- if (WARN_ONCE(irq_poll_cpu == smp_processor_id(),
- "irq poll in progress on cpu %d for irq %d\n",
- smp_processor_id(), desc->irq_data.irq))
- return false;
-
-#ifdef CONFIG_SMP
- do {
- raw_spin_unlock(&desc->lock);
- while (irqd_irq_inprogress(&desc->irq_data))
- cpu_relax();
- raw_spin_lock(&desc->lock);
- } while (irqd_irq_inprogress(&desc->irq_data));
- /* Might have been disabled in meantime */
- return !irqd_irq_disabled(&desc->irq_data) && desc->action;
-#else
- return false;
-#endif
-}
-
-
-/*
* Recovery handler for misrouted interrupts.
*/
static bool try_one_irq(struct irq_desc *desc, bool force)