1 From stable-owner@vger.kernel.org Sun Aug 13 05:16:31 2023
2 From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
3 Date: Sun, 13 Aug 2023 03:16:19 +0000
4 Subject: timers/nohz: Switch to ONESHOT_STOPPED in the low-res handler when the tick is stopped
5 To: stable@vger.kernel.org
6 Cc: Guenter Roeck <linux@roeck-us.net>, Steven Rostedt <rostedt@goodmis.org>, Nicholas Piggin <npiggin@gmail.com>, Thomas Gleixner <tglx@linutronix.de>, Joel Fernandes <joel@joelfernandes.org>
7 Message-ID: <20230813031620.2218302-2-joel@joelfernandes.org>
9 From: Nicholas Piggin <npiggin@gmail.com>
11 [ Upstream commit 62c1256d544747b38e77ca9b5bfe3a26f9592576 ]
13 When tick_nohz_stop_tick() stops the tick and high resolution timers are
14 disabled, then the clock event device is not put into ONESHOT_STOPPED
15 mode. This can lead to spurious timer interrupts with some clock event
16 device drivers that don't shut down entirely after firing.
18 Eliminate these by putting the device into ONESHOT_STOPPED mode at points
19 where it is not being reprogrammed. When there are no timers active, then
20 tick_program_event() with KTIME_MAX can be used to stop the device. When
21 there is a timer active, the device can be stopped at the next tick (any
22 new timer added by timers will reprogram the tick).
24 Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
25 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
26 Link: https://lore.kernel.org/r/20220422141446.915024-1-npiggin@gmail.com
27 Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
28 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
30 kernel/time/tick-sched.c | 12 ++++++++++--
31 1 file changed, 10 insertions(+), 2 deletions(-)
33 --- a/kernel/time/tick-sched.c
34 +++ b/kernel/time/tick-sched.c
35 @@ -950,6 +950,8 @@ static void tick_nohz_stop_tick(struct t
36 if (unlikely(expires == KTIME_MAX)) {
37 if (ts->nohz_mode == NOHZ_MODE_HIGHRES)
38 hrtimer_cancel(&ts->sched_timer);
40 + tick_program_event(KTIME_MAX, 1);
44 @@ -1356,9 +1358,15 @@ static void tick_nohz_handler(struct clo
45 tick_sched_do_timer(ts, now);
46 tick_sched_handle(ts, regs);
48 - /* No need to reprogram if we are running tickless */
49 - if (unlikely(ts->tick_stopped))
50 + if (unlikely(ts->tick_stopped)) {
52 + * The clockevent device is not reprogrammed, so change the
53 + * clock event device to ONESHOT_STOPPED to avoid spurious
54 + * interrupts on devices which might not be truly one shot.
56 + tick_program_event(KTIME_MAX, 1);
60 hrtimer_forward(&ts->sched_timer, now, TICK_NSEC);
61 tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);