aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/clocksource.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2013-04-25 16:31:46 -0400
committerThomas Gleixner <tglx@linutronix.de>2013-05-16 05:09:16 -0400
commita89c7edbe7d7aa80f507915f3dd801211b116b79 (patch)
tree9981bee7be59b28979438fc2701228874856607b /kernel/time/clocksource.c
parent7eaeb34305dee26634f7c98ae62646da5cebe91d (diff)
clocksource: Let clocksource_unregister() return success/error
The unregister call can fail, if the clocksource is the current one and there is no replacement clocksource available. It can also fail, if the clocksource is the watchdog clocksource and I'm not going to provide support for this. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: John Stultz <john.stultz@linaro.org> Cc: Magnus Damm <magnus.damm@gmail.com> Link: http://lkml.kernel.org/r/20130425143436.029915527@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/clocksource.c')
-rw-r--r--kernel/time/clocksource.c33
1 files changed, 12 insertions, 21 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 791d1aeb17ac..31b90332f47b 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -389,28 +389,17 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs)
389 389
390static void clocksource_dequeue_watchdog(struct clocksource *cs) 390static void clocksource_dequeue_watchdog(struct clocksource *cs)
391{ 391{
392 struct clocksource *tmp;
393 unsigned long flags; 392 unsigned long flags;
394 393
395 spin_lock_irqsave(&watchdog_lock, flags); 394 spin_lock_irqsave(&watchdog_lock, flags);
396 if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { 395 if (cs != watchdog) {
397 /* cs is a watched clocksource. */ 396 if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) {
398 list_del_init(&cs->wd_list); 397 /* cs is a watched clocksource. */
399 } else if (cs == watchdog) { 398 list_del_init(&cs->wd_list);
400 /* Reset watchdog cycles */ 399 /* Check if the watchdog timer needs to be stopped. */
401 clocksource_reset_watchdog(); 400 clocksource_stop_watchdog();
402 /* Current watchdog is removed. Find an alternative. */
403 watchdog = NULL;
404 list_for_each_entry(tmp, &clocksource_list, list) {
405 if (tmp == cs || tmp->flags & CLOCK_SOURCE_MUST_VERIFY)
406 continue;
407 if (!watchdog || tmp->rating > watchdog->rating)
408 watchdog = tmp;
409 } 401 }
410 } 402 }
411 cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
412 /* Check if the watchdog timer needs to be stopped. */
413 clocksource_stop_watchdog();
414 spin_unlock_irqrestore(&watchdog_lock, flags); 403 spin_unlock_irqrestore(&watchdog_lock, flags);
415} 404}
416 405
@@ -841,13 +830,15 @@ static int clocksource_unbind(struct clocksource *cs)
841 * clocksource_unregister - remove a registered clocksource 830 * clocksource_unregister - remove a registered clocksource
842 * @cs: clocksource to be unregistered 831 * @cs: clocksource to be unregistered
843 */ 832 */
844void clocksource_unregister(struct clocksource *cs) 833int clocksource_unregister(struct clocksource *cs)
845{ 834{
835 int ret = 0;
836
846 mutex_lock(&clocksource_mutex); 837 mutex_lock(&clocksource_mutex);
847 clocksource_dequeue_watchdog(cs); 838 if (!list_empty(&cs->list))
848 list_del(&cs->list); 839 ret = clocksource_unbind(cs);
849 clocksource_select();
850 mutex_unlock(&clocksource_mutex); 840 mutex_unlock(&clocksource_mutex);
841 return ret;
851} 842}
852EXPORT_SYMBOL(clocksource_unregister); 843EXPORT_SYMBOL(clocksource_unregister);
853 844