diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c index b5a65e212df2f9a1e4b55df717a7f97652b1ed61..9cc9e67036942668fd83489d9639c11dc578d77c 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) { + ktime_t next_event; + /* * 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,19 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc) * hrtimer_start() can call into tracing. */ RCU_NONIDLE( { + next_event = this_cpu_ptr(&tick_cpu_device)->evtdev->next_event; + + /* + * 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 >= next_event) + tick_program_event(next_event, 1); + hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED_HARD); /* * The core tick broadcast mode expects bc->bound_on to be set