Skip to content

Commit 4096fd0

Browse files
author
Thomas Gleixner
committed
clockevents: Add missing resets of the next_event_forced flag
The prevention mechanism against timer interrupt starvation missed to reset the next_event_forced flag in a couple of places: - When the clock event state changes. That can cause the flag to be stale over a shutdown/startup sequence - When a non-forced event is armed, which then prevents rearming before that event. If that event is far out in the future this will cause missed timer interrupts. - In the suspend wakeup handler. That led to stalls which have been reported by several people. Add the missing resets, which fixes the problems for the reporters. Fixes: d6e152d ("clockevents: Prevent timer interrupt starvation") Reported-by: Hanabishi <[email protected]> Reported-by: Eric Naim <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Hanabishi <[email protected]> Tested-by: Eric Naim <[email protected]> Cc: [email protected] Closes: https://lore.kernel.org/[email protected] Link: https://patch.msgid.link/87340xfeje.ffs@tglx
1 parent 1d51b37 commit 4096fd0

2 files changed

Lines changed: 7 additions & 1 deletion

File tree

kernel/time/clockevents.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ static int __clockevents_switch_state(struct clock_event_device *dev,
9494
if (dev->features & CLOCK_EVT_FEAT_DUMMY)
9595
return 0;
9696

97+
/* On state transitions clear the forced flag unconditionally */
98+
dev->next_event_forced = 0;
99+
97100
/* Transition with new state-specific callbacks */
98101
switch (state) {
99102
case CLOCK_EVT_STATE_DETACHED:
@@ -366,8 +369,10 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, b
366369
if (delta > (int64_t)dev->min_delta_ns) {
367370
delta = min(delta, (int64_t) dev->max_delta_ns);
368371
cycles = ((u64)delta * dev->mult) >> dev->shift;
369-
if (!dev->set_next_event((unsigned long) cycles, dev))
372+
if (!dev->set_next_event((unsigned long) cycles, dev)) {
373+
dev->next_event_forced = 0;
370374
return 0;
375+
}
371376
}
372377

373378
if (dev->next_event_forced)

kernel/time/tick-broadcast.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ static struct clock_event_device *tick_get_oneshot_wakeup_device(int cpu)
108108

109109
static void tick_oneshot_wakeup_handler(struct clock_event_device *wd)
110110
{
111+
wd->next_event_forced = 0;
111112
/*
112113
* If we woke up early and the tick was reprogrammed in the
113114
* meantime then this may be spurious but harmless.

0 commit comments

Comments
 (0)