diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 07e57a49d1e8..07162f974deb 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1210,9 +1210,15 @@ static bool __init arch_timer_needs_of_probing(void) static int __init arch_timer_common_init(void) { + int ret; + arch_timer_banner(arch_timers_present); arch_counter_register(arch_timers_present); - return arch_timer_arch_init(); + ret = arch_timer_arch_init(); + if (!ret) + clocksource_select_force(); + + return ret; } /** diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index b21db536fd52..ab8234f8b8ac 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -197,6 +197,7 @@ extern void clocksource_mark_unstable(struct clocksource *cs); extern void clocksource_start_suspend_timing(struct clocksource *cs, u64 start_cycles); extern u64 clocksource_stop_suspend_timing(struct clocksource *cs, u64 now); +extern void clocksource_select_force(void); extern u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cycles); diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 3bcc19ceb073..19243a9a8d14 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -95,7 +95,7 @@ static u64 suspend_start; #ifdef CONFIG_CLOCKSOURCE_WATCHDOG static void clocksource_watchdog_work(struct work_struct *work); -static void clocksource_select(void); +static void clocksource_select(bool force); static LIST_HEAD(watchdog_list); static struct clocksource *watchdog; @@ -700,11 +700,12 @@ static inline void clocksource_update_max_deferment(struct clocksource *cs) #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET -static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur) +static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur, + bool force) { struct clocksource *cs; - if (!finished_booting || list_empty(&clocksource_list)) + if ((!finished_booting && !force) || list_empty(&clocksource_list)) return NULL; /* @@ -722,13 +723,13 @@ static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur) return NULL; } -static void __clocksource_select(bool skipcur) +static void __clocksource_select(bool skipcur, bool force) { bool oneshot = tick_oneshot_mode_active(); struct clocksource *best, *cs; /* Find the best suitable clocksource */ - best = clocksource_find_best(oneshot, skipcur); + best = clocksource_find_best(oneshot, skipcur, force); if (!best) return; @@ -781,22 +782,40 @@ found: * Select the clocksource with the best rating, or the clocksource, * which is selected by userspace override. */ -static void clocksource_select(void) +static void clocksource_select(bool force) { - __clocksource_select(false); + return __clocksource_select(false, force); } static void clocksource_select_fallback(void) { - __clocksource_select(true); + __clocksource_select(true, false); } #else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */ -static inline void clocksource_select(void) { } + +static inline void clocksource_select(bool force) { } static inline void clocksource_select_fallback(void) { } #endif +/** + * clocksource_select_force - Force re-selection of the best clocksource + * among registered clocksources + * + * clocksource_select() can't select the best clocksource before + * calling clocksource_done_booting() and since clocksource_select() + * should be called with clocksource_mutex held, provide a new API + * can be called from other files to select best clockrouce irrespective + * of finished_booting flag. + */ +void clocksource_select_force(void) +{ + mutex_lock(&clocksource_mutex); + clocksource_select(true); + mutex_unlock(&clocksource_mutex); +} + /* * clocksource_done_booting - Called near the end of core bootup * @@ -813,7 +832,7 @@ static int __init clocksource_done_booting(void) * Run the watchdog first to eliminate unstable clock sources */ __clocksource_watchdog_kthread(); - clocksource_select(); + clocksource_select(false); mutex_unlock(&clocksource_mutex); return 0; } @@ -904,6 +923,7 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq } EXPORT_SYMBOL_GPL(__clocksource_update_freq_scale); + /** * __clocksource_register_scale - Used to install new clocksources * @cs: clocksource to be registered @@ -932,7 +952,7 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) clocksource_enqueue_watchdog(cs); clocksource_watchdog_unlock(&flags); - clocksource_select(); + clocksource_select(false); clocksource_select_watchdog(false); __clocksource_suspend_select(cs); mutex_unlock(&clocksource_mutex); @@ -961,7 +981,7 @@ void clocksource_change_rating(struct clocksource *cs, int rating) __clocksource_change_rating(cs, rating); clocksource_watchdog_unlock(&flags); - clocksource_select(); + clocksource_select(false); clocksource_select_watchdog(false); clocksource_suspend_select(false); mutex_unlock(&clocksource_mutex); @@ -1081,7 +1101,7 @@ static ssize_t current_clocksource_store(struct device *dev, ret = sysfs_get_uname(buf, override_name, count); if (ret >= 0) - clocksource_select(); + clocksource_select(false); mutex_unlock(&clocksource_mutex);