diff options
Diffstat (limited to 'kernel/time/clocksource.c')
-rw-r--r-- | kernel/time/clocksource.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index a0af4ffcb6e5..09113347d328 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -121,12 +121,15 @@ static struct clocksource *curr_clocksource; static LIST_HEAD(clocksource_list); static DEFINE_MUTEX(clocksource_mutex); static char override_name[32]; +static int finished_booting; #ifdef CONFIG_CLOCKSOURCE_WATCHDOG +static void clocksource_watchdog_work(struct work_struct *work); + static LIST_HEAD(watchdog_list); static struct clocksource *watchdog; static struct timer_list watchdog_timer; -static struct work_struct watchdog_work; +static DECLARE_WORK(watchdog_work, clocksource_watchdog_work); static DEFINE_SPINLOCK(watchdog_lock); static cycle_t watchdog_last; static int watchdog_running; @@ -153,7 +156,8 @@ static void __clocksource_unstable(struct clocksource *cs) { cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG); cs->flags |= CLOCK_SOURCE_UNSTABLE; - schedule_work(&watchdog_work); + if (finished_booting) + schedule_work(&watchdog_work); } static void clocksource_unstable(struct clocksource *cs, int64_t delta) @@ -205,7 +209,8 @@ static void clocksource_watchdog(unsigned long data) /* Clocksource already marked unstable? */ if (cs->flags & CLOCK_SOURCE_UNSTABLE) { - schedule_work(&watchdog_work); + if (finished_booting) + schedule_work(&watchdog_work); continue; } @@ -257,7 +262,6 @@ static inline void clocksource_start_watchdog(void) { if (watchdog_running || !watchdog || list_empty(&watchdog_list)) return; - INIT_WORK(&watchdog_work, clocksource_watchdog_work); init_timer(&watchdog_timer); watchdog_timer.function = clocksource_watchdog; watchdog_last = watchdog->read(watchdog); @@ -379,6 +383,7 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs) static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { } static inline void clocksource_resume_watchdog(void) { } +static inline int clocksource_watchdog_kthread(void *data) { return 0; } #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */ @@ -414,8 +419,6 @@ void clocksource_touch_watchdog(void) #ifdef CONFIG_GENERIC_TIME -static int finished_booting; - /** * clocksource_select - Select the best clocksource available * @@ -460,6 +463,12 @@ static void clocksource_select(void) } } +#else /* CONFIG_GENERIC_TIME */ + +static inline void clocksource_select(void) { } + +#endif + /* * clocksource_done_booting - Called near the end of core bootup * @@ -470,17 +479,19 @@ static void clocksource_select(void) static int __init clocksource_done_booting(void) { finished_booting = 1; + + /* + * Run the watchdog first to eliminate unstable clock sources + */ + clocksource_watchdog_kthread(NULL); + + mutex_lock(&clocksource_mutex); clocksource_select(); + mutex_unlock(&clocksource_mutex); return 0; } fs_initcall(clocksource_done_booting); -#else /* CONFIG_GENERIC_TIME */ - -static inline void clocksource_select(void) { } - -#endif - /* * Enqueue the clocksource sorted by rating */ |