Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

timers/nohz: Switch to ONESHOT_STOPPED in the low-res handler when the tick is stopped

When tick_nohz_stop_tick() stops the tick and high resolution timers are
disabled, then the clock event device is not put into ONESHOT_STOPPED
mode. This can lead to spurious timer interrupts with some clock event
device drivers that don't shut down entirely after firing.

Eliminate these by putting the device into ONESHOT_STOPPED mode at points
where it is not being reprogrammed. When there are no timers active, then
tick_program_event() with KTIME_MAX can be used to stop the device. When
there is a timer active, the device can be stopped at the next tick (any
new timer added by timers will reprogram the tick).

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20220422141446.915024-1-npiggin@gmail.com

authored by

Nicholas Piggin and committed by
Thomas Gleixner
62c1256d ce8abf34

+10 -2
+10 -2
kernel/time/tick-sched.c
··· 928 928 if (unlikely(expires == KTIME_MAX)) { 929 929 if (ts->nohz_mode == NOHZ_MODE_HIGHRES) 930 930 hrtimer_cancel(&ts->sched_timer); 931 + else 932 + tick_program_event(KTIME_MAX, 1); 931 933 return; 932 934 } 933 935 ··· 1366 1364 tick_sched_do_timer(ts, now); 1367 1365 tick_sched_handle(ts, regs); 1368 1366 1369 - /* No need to reprogram if we are running tickless */ 1370 - if (unlikely(ts->tick_stopped)) 1367 + if (unlikely(ts->tick_stopped)) { 1368 + /* 1369 + * The clockevent device is not reprogrammed, so change the 1370 + * clock event device to ONESHOT_STOPPED to avoid spurious 1371 + * interrupts on devices which might not be truly one shot. 1372 + */ 1373 + tick_program_event(KTIME_MAX, 1); 1371 1374 return; 1375 + } 1372 1376 1373 1377 hrtimer_forward(&ts->sched_timer, now, TICK_NSEC); 1374 1378 tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);