Skip to content

Commit 4e879de

Browse files
committed
genirq: Move irq_wait_for_poll() to call site
Move it to the call site so that the waiting for the INPROGRESS flag can be reused by an upcoming mitigation for a potential live lock in the edge type handler. No functional change. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Liangyan <liangyan.peng@bytedance.com> Reviewed-by: Jiri Slaby <jirislaby@kernel.org> Link: https://lore.kernel.org/all/20250718185311.948555026@linutronix.de
1 parent 46958a7 commit 4e879de

3 files changed

Lines changed: 26 additions & 46 deletions

File tree

kernel/irq/chip.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,21 @@ void unmask_threaded_irq(struct irq_desc *desc)
457457
unmask_irq(desc);
458458
}
459459

460-
static bool irq_check_poll(struct irq_desc *desc)
461-
{
462-
if (!(desc->istate & IRQS_POLL_INPROGRESS))
463-
return false;
464-
return irq_wait_for_poll(desc);
460+
/* Busy wait until INPROGRESS is cleared */
461+
static bool irq_wait_on_inprogress(struct irq_desc *desc)
462+
{
463+
if (IS_ENABLED(CONFIG_SMP)) {
464+
do {
465+
raw_spin_unlock(&desc->lock);
466+
while (irqd_irq_inprogress(&desc->irq_data))
467+
cpu_relax();
468+
raw_spin_lock(&desc->lock);
469+
} while (irqd_irq_inprogress(&desc->irq_data));
470+
471+
/* Might have been disabled in meantime */
472+
return !irqd_irq_disabled(&desc->irq_data) && desc->action;
473+
}
474+
return false;
465475
}
466476

467477
static bool irq_can_handle_pm(struct irq_desc *desc)
@@ -481,10 +491,15 @@ static bool irq_can_handle_pm(struct irq_desc *desc)
481491
if (irq_pm_check_wakeup(desc))
482492
return false;
483493

484-
/*
485-
* Handle a potential concurrent poll on a different core.
486-
*/
487-
return irq_check_poll(desc);
494+
/* Check whether the interrupt is polled on another CPU */
495+
if (unlikely(desc->istate & IRQS_POLL_INPROGRESS)) {
496+
if (WARN_ONCE(irq_poll_cpu == smp_processor_id(),
497+
"irq poll in progress on cpu %d for irq %d\n",
498+
smp_processor_id(), desc->irq_data.irq))
499+
return false;
500+
return irq_wait_on_inprogress(desc);
501+
}
502+
return false;
488503
}
489504

490505
static inline bool irq_can_handle_actions(struct irq_desc *desc)

kernel/irq/internals.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define istate core_internal_state__do_not_mess_with_it
2121

2222
extern bool noirqdebug;
23+
extern int irq_poll_cpu;
2324

2425
extern struct irqaction chained_action;
2526

@@ -112,7 +113,6 @@ irqreturn_t handle_irq_event(struct irq_desc *desc);
112113
int check_irq_resend(struct irq_desc *desc, bool inject);
113114
void clear_irq_resend(struct irq_desc *desc);
114115
void irq_resend_init(struct irq_desc *desc);
115-
bool irq_wait_for_poll(struct irq_desc *desc);
116116
void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action);
117117

118118
void wake_threads_waitq(struct irq_desc *desc);

kernel/irq/spurious.c

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,44 +19,9 @@ static int irqfixup __read_mostly;
1919
#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10)
2020
static void poll_spurious_irqs(struct timer_list *unused);
2121
static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs);
22-
static int irq_poll_cpu;
22+
int irq_poll_cpu;
2323
static atomic_t irq_poll_active;
2424

25-
/*
26-
* We wait here for a poller to finish.
27-
*
28-
* If the poll runs on this CPU, then we yell loudly and return
29-
* false. That will leave the interrupt line disabled in the worst
30-
* case, but it should never happen.
31-
*
32-
* We wait until the poller is done and then recheck disabled and
33-
* action (about to be disabled). Only if it's still active, we return
34-
* true and let the handler run.
35-
*/
36-
bool irq_wait_for_poll(struct irq_desc *desc)
37-
{
38-
lockdep_assert_held(&desc->lock);
39-
40-
if (WARN_ONCE(irq_poll_cpu == smp_processor_id(),
41-
"irq poll in progress on cpu %d for irq %d\n",
42-
smp_processor_id(), desc->irq_data.irq))
43-
return false;
44-
45-
#ifdef CONFIG_SMP
46-
do {
47-
raw_spin_unlock(&desc->lock);
48-
while (irqd_irq_inprogress(&desc->irq_data))
49-
cpu_relax();
50-
raw_spin_lock(&desc->lock);
51-
} while (irqd_irq_inprogress(&desc->irq_data));
52-
/* Might have been disabled in meantime */
53-
return !irqd_irq_disabled(&desc->irq_data) && desc->action;
54-
#else
55-
return false;
56-
#endif
57-
}
58-
59-
6025
/*
6126
* Recovery handler for misrouted interrupts.
6227
*/

0 commit comments

Comments
 (0)