Merge "ARM: arch_timer: force re-selection of the best clocksource"

This commit is contained in:
qctecmdr 2019-07-31 17:45:21 -07:00 • committed by Gerrit - the friendly Code Review server
commit bcb0048ac7
3 changed files with 41 additions and 14 deletions

View file

@ -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;
}
/**

View file

@ -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);

View file

@ -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);