OSDN Git Service

Merge tag 'v4.4.214' into 10
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / kernel / time / clocksource.c
index a20368e..3b43159 100644 (file)
@@ -108,7 +108,7 @@ static int finished_booting;
 
 #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;
@@ -422,7 +422,7 @@ static int clocksource_watchdog_kthread(void *data)
 {
        mutex_lock(&clocksource_mutex);
        if (__clocksource_watchdog_kthread())
-               clocksource_select();
+               clocksource_select(false);
        mutex_unlock(&clocksource_mutex);
        return 0;
 }
@@ -562,11 +562,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;
 
        /*
@@ -584,13 +585,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;
 
@@ -630,22 +631,40 @@ static void __clocksource_select(bool skipcur)
  * 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
  *
@@ -662,7 +681,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;
 }
@@ -751,6 +770,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
@@ -772,7 +792,7 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
        mutex_lock(&clocksource_mutex);
        clocksource_enqueue(cs);
        clocksource_enqueue_watchdog(cs);
-       clocksource_select();
+       clocksource_select(false);
        clocksource_select_watchdog(false);
        mutex_unlock(&clocksource_mutex);
        return 0;
@@ -795,7 +815,7 @@ void clocksource_change_rating(struct clocksource *cs, int rating)
 {
        mutex_lock(&clocksource_mutex);
        __clocksource_change_rating(cs, rating);
-       clocksource_select();
+       clocksource_select(false);
        clocksource_select_watchdog(false);
        mutex_unlock(&clocksource_mutex);
 }
@@ -899,7 +919,7 @@ static ssize_t sysfs_override_clocksource(struct device *dev,
 
        ret = sysfs_get_uname(buf, override_name, count);
        if (ret >= 0)
-               clocksource_select();
+               clocksource_select(false);
 
        mutex_unlock(&clocksource_mutex);