mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
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: d6e152d905 ("clockevents: Prevent timer interrupt starvation")
Reported-by: Hanabishi <i.r.e.c.c.a.k.u.n+kernel.org@gmail.com>
Reported-by: Eric Naim <dnaim@cachyos.org>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: Hanabishi <i.r.e.c.c.a.k.u.n+kernel.org@gmail.com>
Tested-by: Eric Naim <dnaim@cachyos.org>
Cc: stable@vger.kernel.org
Closes: https://lore.kernel.org/68d1e9ac-2780-4be3-8ee3-0788062dd3a4@gmail.com
Link: https://patch.msgid.link/87340xfeje.ffs@tglx
This commit is contained in:
parent
1d51b370a0
commit
4096fd0e8e
|
|
@ -94,6 +94,9 @@ static int __clockevents_switch_state(struct clock_event_device *dev,
|
|||
if (dev->features & CLOCK_EVT_FEAT_DUMMY)
|
||||
return 0;
|
||||
|
||||
/* On state transitions clear the forced flag unconditionally */
|
||||
dev->next_event_forced = 0;
|
||||
|
||||
/* Transition with new state-specific callbacks */
|
||||
switch (state) {
|
||||
case CLOCK_EVT_STATE_DETACHED:
|
||||
|
|
@ -366,8 +369,10 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, b
|
|||
if (delta > (int64_t)dev->min_delta_ns) {
|
||||
delta = min(delta, (int64_t) dev->max_delta_ns);
|
||||
cycles = ((u64)delta * dev->mult) >> dev->shift;
|
||||
if (!dev->set_next_event((unsigned long) cycles, dev))
|
||||
if (!dev->set_next_event((unsigned long) cycles, dev)) {
|
||||
dev->next_event_forced = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->next_event_forced)
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ static struct clock_event_device *tick_get_oneshot_wakeup_device(int cpu)
|
|||
|
||||
static void tick_oneshot_wakeup_handler(struct clock_event_device *wd)
|
||||
{
|
||||
wd->next_event_forced = 0;
|
||||
/*
|
||||
* If we woke up early and the tick was reprogrammed in the
|
||||
* meantime then this may be spurious but harmless.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user