From f587015e8803babe6c194170b80f1188d2c0bdc2 Mon Sep 17 00:00:00 2001 From: "Se Wang (Patrick) Oh" Date: Fri, 29 May 2015 14:57:05 -0700 Subject: [PATCH 1/2] clocksource: add API to force re-selection of the best clocksource As the best clocksource is not selected till core boot completion, only periodic tick timer works and it increases jiffies by one at every tick updates. If interrupt is disabled more than one tick(10ms), timer interrupts are missed and jiffies can't be updated at every 10ms and it can be behind the real time. So add API to force re- selection of the best clocksource among registered clocksources so that the best clocksource can be selected whenever it is available. Change-Id: I481de3cdf1df8f0e35ed10aee7ab3882bf7a35b3 Signed-off-by: Se Wang (Patrick) Oh Signed-off-by: Elliot Berman --- include/linux/clocksource.h | 1 + kernel/time/clocksource.c | 46 ++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 13 deletions(-) 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); From 4914b031a98b93efe6eb990b3f2302c2d726377e Mon Sep 17 00:00:00 2001 From: "Se Wang (Patrick) Oh" Date: Thu, 11 Jun 2015 18:10:07 -0700 Subject: [PATCH 2/2] ARM: arch_timer: force re-selection of the best clocksource As the best clocksource is not selected till core boot completion, only periodic tick timer works and it increases jiffies by one at every tick updates. If interrupt is disabled more than one tick(10ms), timer interrupts are missed and jiffies can't be updated at every 10ms and It can be behind the real time. So make it possible to select the best clocksource right after arm arch timer initialization, so that jiffies can be increased by multiple counts since then. Change-Id: Id8c4e3ce9b9e44061fef7ad7e678ca1c27d84bb1 Signed-off-by: Se Wang (Patrick) Oh Signed-off-by: Elliot Berman --- drivers/clocksource/arm_arch_timer.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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; } /**