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