nohz: fix wrong event handler after online an offlined cpu

On the tickless system(CONFIG_NO_HZ=y and CONFIG_HIGH_RES_TIMERS=n), after
I made an offlined cpu online, I found this cpu's event handler was
tick_handle_periodic, not tick_nohz_handler.

After debuging, I found this bug was caused by the wrong tick mode. the
tick mode is not changed to NOHZ_MODE_INACTIVE when the cpu is offline.

This patch fixes this bug.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by Miao Xie and committed by Ingo Molnar 3c4fbe5e 6a55617e

+9 -2
+4 -1
include/linux/tick.h
··· 74 74 extern int tick_init_highres(void); 75 75 extern int tick_program_event(ktime_t expires, int force); 76 76 extern void tick_setup_sched_timer(void); 77 + # endif 78 + 79 + # if defined CONFIG_NO_HZ || defined CONFIG_HIGH_RES_TIMERS 77 80 extern void tick_cancel_sched_timer(int cpu); 78 81 # else 79 82 static inline void tick_cancel_sched_timer(int cpu) { } 80 - # endif /* HIGHRES */ 83 + # endif 81 84 82 85 # ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 83 86 extern struct tick_device *tick_get_broadcast_device(void);
+5 -1
kernel/time/tick-sched.c
··· 643 643 ts->nohz_mode = NOHZ_MODE_HIGHRES; 644 644 #endif 645 645 } 646 + #endif /* HIGH_RES_TIMERS */ 646 647 648 + #if defined CONFIG_NO_HZ || defined CONFIG_HIGH_RES_TIMERS 647 649 void tick_cancel_sched_timer(int cpu) 648 650 { 649 651 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); 650 652 653 + # ifdef CONFIG_HIGH_RES_TIMERS 651 654 if (ts->sched_timer.base) 652 655 hrtimer_cancel(&ts->sched_timer); 656 + # endif 653 657 654 658 ts->nohz_mode = NOHZ_MODE_INACTIVE; 655 659 } 656 - #endif /* HIGH_RES_TIMERS */ 660 + #endif 657 661 658 662 /** 659 663 * Async notification about clocksource changes