diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c index b5a65e212df2f9a1e4b55df717a7f97652b1ed61..b8e79f8012f3e618aa88e14a0ec66104ed9fdea8 100644 --- a/kernel/time/tick-broadcast-hrtimer.c +++ b/kernel/time/tick-broadcast-hrtimer.c @@ -42,6 +42,8 @@ static int bc_shutdown(struct clock_event_device *evt) */ static int bc_set_next(ktime_t expires, struct clock_event_device *bc) { + struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev); + /* * This is called either from enter/exit idle code or from the * broadcast handler. In all cases tick_broadcast_lock is held. @@ -62,6 +64,18 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc) * hrtimer_start() can call into tracing. */ RCU_NONIDLE( { + + /* + * This can be called from CPU offline operation to move broadcast + * assignment. If tick_broadcast_force_mask is set, the CPU local + * timer device may be disabled. And hrtimer_reprogram() will not + * called if the timer is not the first expiring timer. Reprogram + * the cpu local timer device to ensure we can take over the + * broadcast duty. + */ + if (tick_check_broadcast_expired() && expires >= dev->next_event) + clockevents_program_event(dev, dev->next_event, 1); + hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED_HARD); /* * The core tick broadcast mode expects bc->bound_on to be set