xref: /openbmc/linux/kernel/time/clocksource.c (revision d0981a1b)
1734efb46Sjohn stultz /*
2734efb46Sjohn stultz  * linux/kernel/time/clocksource.c
3734efb46Sjohn stultz  *
4734efb46Sjohn stultz  * This file contains the functions which manage clocksource drivers.
5734efb46Sjohn stultz  *
6734efb46Sjohn stultz  * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
7734efb46Sjohn stultz  *
8734efb46Sjohn stultz  * This program is free software; you can redistribute it and/or modify
9734efb46Sjohn stultz  * it under the terms of the GNU General Public License as published by
10734efb46Sjohn stultz  * the Free Software Foundation; either version 2 of the License, or
11734efb46Sjohn stultz  * (at your option) any later version.
12734efb46Sjohn stultz  *
13734efb46Sjohn stultz  * This program is distributed in the hope that it will be useful,
14734efb46Sjohn stultz  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15734efb46Sjohn stultz  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16734efb46Sjohn stultz  * GNU General Public License for more details.
17734efb46Sjohn stultz  *
18734efb46Sjohn stultz  * You should have received a copy of the GNU General Public License
19734efb46Sjohn stultz  * along with this program; if not, write to the Free Software
20734efb46Sjohn stultz  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21734efb46Sjohn stultz  *
22734efb46Sjohn stultz  * TODO WishList:
23734efb46Sjohn stultz  *   o Allow clocksource drivers to be unregistered
24734efb46Sjohn stultz  */
25734efb46Sjohn stultz 
26734efb46Sjohn stultz #include <linux/clocksource.h>
27734efb46Sjohn stultz #include <linux/sysdev.h>
28734efb46Sjohn stultz #include <linux/init.h>
29734efb46Sjohn stultz #include <linux/module.h>
30dc29a365SMathieu Desnoyers #include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */
3179bf2bb3SThomas Gleixner #include <linux/tick.h>
32734efb46Sjohn stultz 
33a038a353SPatrick Ohly void timecounter_init(struct timecounter *tc,
34a038a353SPatrick Ohly 		      const struct cyclecounter *cc,
35a038a353SPatrick Ohly 		      u64 start_tstamp)
36a038a353SPatrick Ohly {
37a038a353SPatrick Ohly 	tc->cc = cc;
38a038a353SPatrick Ohly 	tc->cycle_last = cc->read(cc);
39a038a353SPatrick Ohly 	tc->nsec = start_tstamp;
40a038a353SPatrick Ohly }
41a038a353SPatrick Ohly EXPORT_SYMBOL(timecounter_init);
42a038a353SPatrick Ohly 
43a038a353SPatrick Ohly /**
44a038a353SPatrick Ohly  * timecounter_read_delta - get nanoseconds since last call of this function
45a038a353SPatrick Ohly  * @tc:         Pointer to time counter
46a038a353SPatrick Ohly  *
47a038a353SPatrick Ohly  * When the underlying cycle counter runs over, this will be handled
48a038a353SPatrick Ohly  * correctly as long as it does not run over more than once between
49a038a353SPatrick Ohly  * calls.
50a038a353SPatrick Ohly  *
51a038a353SPatrick Ohly  * The first call to this function for a new time counter initializes
52a038a353SPatrick Ohly  * the time tracking and returns an undefined result.
53a038a353SPatrick Ohly  */
54a038a353SPatrick Ohly static u64 timecounter_read_delta(struct timecounter *tc)
55a038a353SPatrick Ohly {
56a038a353SPatrick Ohly 	cycle_t cycle_now, cycle_delta;
57a038a353SPatrick Ohly 	u64 ns_offset;
58a038a353SPatrick Ohly 
59a038a353SPatrick Ohly 	/* read cycle counter: */
60a038a353SPatrick Ohly 	cycle_now = tc->cc->read(tc->cc);
61a038a353SPatrick Ohly 
62a038a353SPatrick Ohly 	/* calculate the delta since the last timecounter_read_delta(): */
63a038a353SPatrick Ohly 	cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
64a038a353SPatrick Ohly 
65a038a353SPatrick Ohly 	/* convert to nanoseconds: */
66a038a353SPatrick Ohly 	ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta);
67a038a353SPatrick Ohly 
68a038a353SPatrick Ohly 	/* update time stamp of timecounter_read_delta() call: */
69a038a353SPatrick Ohly 	tc->cycle_last = cycle_now;
70a038a353SPatrick Ohly 
71a038a353SPatrick Ohly 	return ns_offset;
72a038a353SPatrick Ohly }
73a038a353SPatrick Ohly 
74a038a353SPatrick Ohly u64 timecounter_read(struct timecounter *tc)
75a038a353SPatrick Ohly {
76a038a353SPatrick Ohly 	u64 nsec;
77a038a353SPatrick Ohly 
78a038a353SPatrick Ohly 	/* increment time by nanoseconds since last call */
79a038a353SPatrick Ohly 	nsec = timecounter_read_delta(tc);
80a038a353SPatrick Ohly 	nsec += tc->nsec;
81a038a353SPatrick Ohly 	tc->nsec = nsec;
82a038a353SPatrick Ohly 
83a038a353SPatrick Ohly 	return nsec;
84a038a353SPatrick Ohly }
85a038a353SPatrick Ohly EXPORT_SYMBOL(timecounter_read);
86a038a353SPatrick Ohly 
87a038a353SPatrick Ohly u64 timecounter_cyc2time(struct timecounter *tc,
88a038a353SPatrick Ohly 			 cycle_t cycle_tstamp)
89a038a353SPatrick Ohly {
90a038a353SPatrick Ohly 	u64 cycle_delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
91a038a353SPatrick Ohly 	u64 nsec;
92a038a353SPatrick Ohly 
93a038a353SPatrick Ohly 	/*
94a038a353SPatrick Ohly 	 * Instead of always treating cycle_tstamp as more recent
95a038a353SPatrick Ohly 	 * than tc->cycle_last, detect when it is too far in the
96a038a353SPatrick Ohly 	 * future and treat it as old time stamp instead.
97a038a353SPatrick Ohly 	 */
98a038a353SPatrick Ohly 	if (cycle_delta > tc->cc->mask / 2) {
99a038a353SPatrick Ohly 		cycle_delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
100a038a353SPatrick Ohly 		nsec = tc->nsec - cyclecounter_cyc2ns(tc->cc, cycle_delta);
101a038a353SPatrick Ohly 	} else {
102a038a353SPatrick Ohly 		nsec = cyclecounter_cyc2ns(tc->cc, cycle_delta) + tc->nsec;
103a038a353SPatrick Ohly 	}
104a038a353SPatrick Ohly 
105a038a353SPatrick Ohly 	return nsec;
106a038a353SPatrick Ohly }
107a038a353SPatrick Ohly EXPORT_SYMBOL(timecounter_cyc2time);
108a038a353SPatrick Ohly 
109734efb46Sjohn stultz /*[Clocksource internal variables]---------
110734efb46Sjohn stultz  * curr_clocksource:
111f1b82746SMartin Schwidefsky  *	currently selected clocksource.
112734efb46Sjohn stultz  * clocksource_list:
113734efb46Sjohn stultz  *	linked list with the registered clocksources
11475c5158fSMartin Schwidefsky  * clocksource_mutex:
11575c5158fSMartin Schwidefsky  *	protects manipulations to curr_clocksource and the clocksource_list
116734efb46Sjohn stultz  * override_name:
117734efb46Sjohn stultz  *	Name of the user-specified clocksource.
118734efb46Sjohn stultz  */
119f1b82746SMartin Schwidefsky static struct clocksource *curr_clocksource;
120734efb46Sjohn stultz static LIST_HEAD(clocksource_list);
12175c5158fSMartin Schwidefsky static DEFINE_MUTEX(clocksource_mutex);
122734efb46Sjohn stultz static char override_name[32];
123734efb46Sjohn stultz 
1245d8b34fdSThomas Gleixner #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
1255d8b34fdSThomas Gleixner static LIST_HEAD(watchdog_list);
1265d8b34fdSThomas Gleixner static struct clocksource *watchdog;
1275d8b34fdSThomas Gleixner static struct timer_list watchdog_timer;
128c55c87c8SMartin Schwidefsky static struct work_struct watchdog_work;
1295d8b34fdSThomas Gleixner static DEFINE_SPINLOCK(watchdog_lock);
1305d8b34fdSThomas Gleixner static cycle_t watchdog_last;
131fb63a0ebSMartin Schwidefsky static int watchdog_running;
132b52f52a0SThomas Gleixner 
133c55c87c8SMartin Schwidefsky static void clocksource_watchdog_work(struct work_struct *work);
134d0981a1bSThomas Gleixner static void __clocksource_change_rating(struct clocksource *cs, int rating);
135c55c87c8SMartin Schwidefsky 
1365d8b34fdSThomas Gleixner /*
13735c35d1aSDaniel Walker  * Interval: 0.5sec Threshold: 0.0625s
1385d8b34fdSThomas Gleixner  */
1395d8b34fdSThomas Gleixner #define WATCHDOG_INTERVAL (HZ >> 1)
14035c35d1aSDaniel Walker #define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 4)
1415d8b34fdSThomas Gleixner 
1428cf4e750SMartin Schwidefsky static void clocksource_unstable(struct clocksource *cs, int64_t delta)
1435d8b34fdSThomas Gleixner {
1445d8b34fdSThomas Gleixner 	printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
1455d8b34fdSThomas Gleixner 	       cs->name, delta);
1465d8b34fdSThomas Gleixner 	cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
147c55c87c8SMartin Schwidefsky 	cs->flags |= CLOCK_SOURCE_UNSTABLE;
148c55c87c8SMartin Schwidefsky 	schedule_work(&watchdog_work);
1495d8b34fdSThomas Gleixner }
1505d8b34fdSThomas Gleixner 
1515d8b34fdSThomas Gleixner static void clocksource_watchdog(unsigned long data)
1525d8b34fdSThomas Gleixner {
153c55c87c8SMartin Schwidefsky 	struct clocksource *cs;
1545d8b34fdSThomas Gleixner 	cycle_t csnow, wdnow;
1555d8b34fdSThomas Gleixner 	int64_t wd_nsec, cs_nsec;
156c55c87c8SMartin Schwidefsky 	int next_cpu;
1575d8b34fdSThomas Gleixner 
1585d8b34fdSThomas Gleixner 	spin_lock(&watchdog_lock);
159fb63a0ebSMartin Schwidefsky 	if (!watchdog_running)
160fb63a0ebSMartin Schwidefsky 		goto out;
1615d8b34fdSThomas Gleixner 
1628e19608eSMagnus Damm 	wdnow = watchdog->read(watchdog);
163155ec602SMartin Schwidefsky 	wd_nsec = clocksource_cyc2ns((wdnow - watchdog_last) & watchdog->mask,
164155ec602SMartin Schwidefsky 				     watchdog->mult, watchdog->shift);
1655d8b34fdSThomas Gleixner 	watchdog_last = wdnow;
1665d8b34fdSThomas Gleixner 
167c55c87c8SMartin Schwidefsky 	list_for_each_entry(cs, &watchdog_list, wd_list) {
168c55c87c8SMartin Schwidefsky 
169c55c87c8SMartin Schwidefsky 		/* Clocksource already marked unstable? */
170c55c87c8SMartin Schwidefsky 		if (cs->flags & CLOCK_SOURCE_UNSTABLE)
171c55c87c8SMartin Schwidefsky 			continue;
172c55c87c8SMartin Schwidefsky 
1738e19608eSMagnus Damm 		csnow = cs->read(cs);
174b52f52a0SThomas Gleixner 
1758cf4e750SMartin Schwidefsky 		/* Clocksource initialized ? */
1768cf4e750SMartin Schwidefsky 		if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
1778cf4e750SMartin Schwidefsky 			cs->flags |= CLOCK_SOURCE_WATCHDOG;
178b52f52a0SThomas Gleixner 			cs->wd_last = csnow;
179b52f52a0SThomas Gleixner 			continue;
180b52f52a0SThomas Gleixner 		}
181b52f52a0SThomas Gleixner 
1828cf4e750SMartin Schwidefsky 		/* Check the deviation from the watchdog clocksource. */
183155ec602SMartin Schwidefsky 		cs_nsec = clocksource_cyc2ns((csnow - cs->wd_last) &
184155ec602SMartin Schwidefsky 					     cs->mask, cs->mult, cs->shift);
1858cf4e750SMartin Schwidefsky 		cs->wd_last = csnow;
1868cf4e750SMartin Schwidefsky 		if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) {
1878cf4e750SMartin Schwidefsky 			clocksource_unstable(cs, cs_nsec - wd_nsec);
1888cf4e750SMartin Schwidefsky 			continue;
1898cf4e750SMartin Schwidefsky 		}
1908cf4e750SMartin Schwidefsky 
1918cf4e750SMartin Schwidefsky 		if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) &&
1928cf4e750SMartin Schwidefsky 		    (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
1935d8b34fdSThomas Gleixner 		    (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {
1945d8b34fdSThomas Gleixner 			cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
19579bf2bb3SThomas Gleixner 			/*
1968cf4e750SMartin Schwidefsky 			 * We just marked the clocksource as highres-capable,
1978cf4e750SMartin Schwidefsky 			 * notify the rest of the system as well so that we
1988cf4e750SMartin Schwidefsky 			 * transition into high-res mode:
19979bf2bb3SThomas Gleixner 			 */
20079bf2bb3SThomas Gleixner 			tick_clock_notify();
2015d8b34fdSThomas Gleixner 		}
2025d8b34fdSThomas Gleixner 	}
2035d8b34fdSThomas Gleixner 
2046993fc5bSAndi Kleen 	/*
205c55c87c8SMartin Schwidefsky 	 * Cycle through CPUs to check if the CPUs stay synchronized
206c55c87c8SMartin Schwidefsky 	 * to each other.
2076993fc5bSAndi Kleen 	 */
208c55c87c8SMartin Schwidefsky 	next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
209cad0e458SMike Travis 	if (next_cpu >= nr_cpu_ids)
2106b954823SRusty Russell 		next_cpu = cpumask_first(cpu_online_mask);
2116993fc5bSAndi Kleen 	watchdog_timer.expires += WATCHDOG_INTERVAL;
2126993fc5bSAndi Kleen 	add_timer_on(&watchdog_timer, next_cpu);
213fb63a0ebSMartin Schwidefsky out:
2145d8b34fdSThomas Gleixner 	spin_unlock(&watchdog_lock);
2155d8b34fdSThomas Gleixner }
2160f8e8ef7SMartin Schwidefsky 
217fb63a0ebSMartin Schwidefsky static inline void clocksource_start_watchdog(void)
218fb63a0ebSMartin Schwidefsky {
219fb63a0ebSMartin Schwidefsky 	if (watchdog_running || !watchdog || list_empty(&watchdog_list))
220fb63a0ebSMartin Schwidefsky 		return;
221c55c87c8SMartin Schwidefsky 	INIT_WORK(&watchdog_work, clocksource_watchdog_work);
222fb63a0ebSMartin Schwidefsky 	init_timer(&watchdog_timer);
223fb63a0ebSMartin Schwidefsky 	watchdog_timer.function = clocksource_watchdog;
224fb63a0ebSMartin Schwidefsky 	watchdog_last = watchdog->read(watchdog);
225fb63a0ebSMartin Schwidefsky 	watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
226fb63a0ebSMartin Schwidefsky 	add_timer_on(&watchdog_timer, cpumask_first(cpu_online_mask));
227fb63a0ebSMartin Schwidefsky 	watchdog_running = 1;
228fb63a0ebSMartin Schwidefsky }
229fb63a0ebSMartin Schwidefsky 
230fb63a0ebSMartin Schwidefsky static inline void clocksource_stop_watchdog(void)
231fb63a0ebSMartin Schwidefsky {
232fb63a0ebSMartin Schwidefsky 	if (!watchdog_running || (watchdog && !list_empty(&watchdog_list)))
233fb63a0ebSMartin Schwidefsky 		return;
234fb63a0ebSMartin Schwidefsky 	del_timer(&watchdog_timer);
235fb63a0ebSMartin Schwidefsky 	watchdog_running = 0;
236fb63a0ebSMartin Schwidefsky }
237fb63a0ebSMartin Schwidefsky 
2380f8e8ef7SMartin Schwidefsky static inline void clocksource_reset_watchdog(void)
2390f8e8ef7SMartin Schwidefsky {
2400f8e8ef7SMartin Schwidefsky 	struct clocksource *cs;
2410f8e8ef7SMartin Schwidefsky 
2420f8e8ef7SMartin Schwidefsky 	list_for_each_entry(cs, &watchdog_list, wd_list)
2430f8e8ef7SMartin Schwidefsky 		cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
2440f8e8ef7SMartin Schwidefsky }
2450f8e8ef7SMartin Schwidefsky 
246b52f52a0SThomas Gleixner static void clocksource_resume_watchdog(void)
247b52f52a0SThomas Gleixner {
2480f8e8ef7SMartin Schwidefsky 	unsigned long flags;
2490f8e8ef7SMartin Schwidefsky 
2500f8e8ef7SMartin Schwidefsky 	spin_lock_irqsave(&watchdog_lock, flags);
2510f8e8ef7SMartin Schwidefsky 	clocksource_reset_watchdog();
2520f8e8ef7SMartin Schwidefsky 	spin_unlock_irqrestore(&watchdog_lock, flags);
253b52f52a0SThomas Gleixner }
254b52f52a0SThomas Gleixner 
255fb63a0ebSMartin Schwidefsky static void clocksource_enqueue_watchdog(struct clocksource *cs)
2565d8b34fdSThomas Gleixner {
2575d8b34fdSThomas Gleixner 	unsigned long flags;
2585d8b34fdSThomas Gleixner 
2595d8b34fdSThomas Gleixner 	spin_lock_irqsave(&watchdog_lock, flags);
2605d8b34fdSThomas Gleixner 	if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) {
261fb63a0ebSMartin Schwidefsky 		/* cs is a clocksource to be watched. */
2625d8b34fdSThomas Gleixner 		list_add(&cs->wd_list, &watchdog_list);
263fb63a0ebSMartin Schwidefsky 		cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
264948ac6d7SThomas Gleixner 	} else {
265fb63a0ebSMartin Schwidefsky 		/* cs is a watchdog. */
266948ac6d7SThomas Gleixner 		if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
2675d8b34fdSThomas Gleixner 			cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
268fb63a0ebSMartin Schwidefsky 		/* Pick the best watchdog. */
2695d8b34fdSThomas Gleixner 		if (!watchdog || cs->rating > watchdog->rating) {
2705d8b34fdSThomas Gleixner 			watchdog = cs;
2715d8b34fdSThomas Gleixner 			/* Reset watchdog cycles */
2720f8e8ef7SMartin Schwidefsky 			clocksource_reset_watchdog();
2735d8b34fdSThomas Gleixner 		}
2745d8b34fdSThomas Gleixner 	}
275fb63a0ebSMartin Schwidefsky 	/* Check if the watchdog timer needs to be started. */
276fb63a0ebSMartin Schwidefsky 	clocksource_start_watchdog();
2775d8b34fdSThomas Gleixner 	spin_unlock_irqrestore(&watchdog_lock, flags);
2785d8b34fdSThomas Gleixner }
279fb63a0ebSMartin Schwidefsky 
280fb63a0ebSMartin Schwidefsky static void clocksource_dequeue_watchdog(struct clocksource *cs)
281fb63a0ebSMartin Schwidefsky {
282fb63a0ebSMartin Schwidefsky 	struct clocksource *tmp;
283fb63a0ebSMartin Schwidefsky 	unsigned long flags;
284fb63a0ebSMartin Schwidefsky 
285fb63a0ebSMartin Schwidefsky 	spin_lock_irqsave(&watchdog_lock, flags);
286fb63a0ebSMartin Schwidefsky 	if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) {
287fb63a0ebSMartin Schwidefsky 		/* cs is a watched clocksource. */
288fb63a0ebSMartin Schwidefsky 		list_del_init(&cs->wd_list);
289fb63a0ebSMartin Schwidefsky 	} else if (cs == watchdog) {
290fb63a0ebSMartin Schwidefsky 		/* Reset watchdog cycles */
291fb63a0ebSMartin Schwidefsky 		clocksource_reset_watchdog();
292fb63a0ebSMartin Schwidefsky 		/* Current watchdog is removed. Find an alternative. */
293fb63a0ebSMartin Schwidefsky 		watchdog = NULL;
294fb63a0ebSMartin Schwidefsky 		list_for_each_entry(tmp, &clocksource_list, list) {
295fb63a0ebSMartin Schwidefsky 			if (tmp == cs || tmp->flags & CLOCK_SOURCE_MUST_VERIFY)
296fb63a0ebSMartin Schwidefsky 				continue;
297fb63a0ebSMartin Schwidefsky 			if (!watchdog || tmp->rating > watchdog->rating)
298fb63a0ebSMartin Schwidefsky 				watchdog = tmp;
299fb63a0ebSMartin Schwidefsky 		}
300fb63a0ebSMartin Schwidefsky 	}
301fb63a0ebSMartin Schwidefsky 	cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
302fb63a0ebSMartin Schwidefsky 	/* Check if the watchdog timer needs to be stopped. */
303fb63a0ebSMartin Schwidefsky 	clocksource_stop_watchdog();
304fb63a0ebSMartin Schwidefsky 	spin_unlock_irqrestore(&watchdog_lock, flags);
305fb63a0ebSMartin Schwidefsky }
306fb63a0ebSMartin Schwidefsky 
307c55c87c8SMartin Schwidefsky static void clocksource_watchdog_work(struct work_struct *work)
308c55c87c8SMartin Schwidefsky {
309c55c87c8SMartin Schwidefsky 	struct clocksource *cs, *tmp;
310c55c87c8SMartin Schwidefsky 	unsigned long flags;
3116ea41d25SThomas Gleixner 	LIST_HEAD(unstable);
312c55c87c8SMartin Schwidefsky 
313d0981a1bSThomas Gleixner 	mutex_lock(&clocksource_mutex);
314c55c87c8SMartin Schwidefsky 	spin_lock_irqsave(&watchdog_lock, flags);
315c55c87c8SMartin Schwidefsky 	list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list)
316c55c87c8SMartin Schwidefsky 		if (cs->flags & CLOCK_SOURCE_UNSTABLE) {
317c55c87c8SMartin Schwidefsky 			list_del_init(&cs->wd_list);
3186ea41d25SThomas Gleixner 			list_add(&cs->wd_list, &unstable);
319c55c87c8SMartin Schwidefsky 		}
320c55c87c8SMartin Schwidefsky 	/* Check if the watchdog timer needs to be stopped. */
321c55c87c8SMartin Schwidefsky 	clocksource_stop_watchdog();
3226ea41d25SThomas Gleixner 	spin_unlock_irqrestore(&watchdog_lock, flags);
3236ea41d25SThomas Gleixner 
3246ea41d25SThomas Gleixner 	/* Needs to be done outside of watchdog lock */
3256ea41d25SThomas Gleixner 	list_for_each_entry_safe(cs, tmp, &unstable, wd_list) {
3266ea41d25SThomas Gleixner 		list_del_init(&cs->wd_list);
327d0981a1bSThomas Gleixner 		__clocksource_change_rating(cs, 0);
3286ea41d25SThomas Gleixner 	}
329d0981a1bSThomas Gleixner 	mutex_unlock(&clocksource_mutex);
330c55c87c8SMartin Schwidefsky }
331c55c87c8SMartin Schwidefsky 
332fb63a0ebSMartin Schwidefsky #else /* CONFIG_CLOCKSOURCE_WATCHDOG */
333fb63a0ebSMartin Schwidefsky 
334fb63a0ebSMartin Schwidefsky static void clocksource_enqueue_watchdog(struct clocksource *cs)
3355d8b34fdSThomas Gleixner {
3365d8b34fdSThomas Gleixner 	if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
3375d8b34fdSThomas Gleixner 		cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
3385d8b34fdSThomas Gleixner }
339b52f52a0SThomas Gleixner 
340fb63a0ebSMartin Schwidefsky static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { }
341b52f52a0SThomas Gleixner static inline void clocksource_resume_watchdog(void) { }
342fb63a0ebSMartin Schwidefsky 
343fb63a0ebSMartin Schwidefsky #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */
3445d8b34fdSThomas Gleixner 
345734efb46Sjohn stultz /**
346b52f52a0SThomas Gleixner  * clocksource_resume - resume the clocksource(s)
347b52f52a0SThomas Gleixner  */
348b52f52a0SThomas Gleixner void clocksource_resume(void)
349b52f52a0SThomas Gleixner {
3502e197586SMatthias Kaehlcke 	struct clocksource *cs;
351b52f52a0SThomas Gleixner 
35275c5158fSMartin Schwidefsky 	mutex_lock(&clocksource_mutex);
353b52f52a0SThomas Gleixner 
35475c5158fSMartin Schwidefsky 	list_for_each_entry(cs, &clocksource_list, list)
355b52f52a0SThomas Gleixner 		if (cs->resume)
356b52f52a0SThomas Gleixner 			cs->resume();
357b52f52a0SThomas Gleixner 
358b52f52a0SThomas Gleixner 	clocksource_resume_watchdog();
359b52f52a0SThomas Gleixner 
36075c5158fSMartin Schwidefsky 	mutex_unlock(&clocksource_mutex);
361b52f52a0SThomas Gleixner }
362b52f52a0SThomas Gleixner 
363b52f52a0SThomas Gleixner /**
3647c3078b6SJason Wessel  * clocksource_touch_watchdog - Update watchdog
3657c3078b6SJason Wessel  *
3667c3078b6SJason Wessel  * Update the watchdog after exception contexts such as kgdb so as not
3677c3078b6SJason Wessel  * to incorrectly trip the watchdog.
3687c3078b6SJason Wessel  *
3697c3078b6SJason Wessel  */
3707c3078b6SJason Wessel void clocksource_touch_watchdog(void)
3717c3078b6SJason Wessel {
3727c3078b6SJason Wessel 	clocksource_resume_watchdog();
3737c3078b6SJason Wessel }
3747c3078b6SJason Wessel 
375f1b82746SMartin Schwidefsky #ifdef CONFIG_GENERIC_TIME
376734efb46Sjohn stultz 
37775c5158fSMartin Schwidefsky static int finished_booting;
378734efb46Sjohn stultz 
379734efb46Sjohn stultz /**
380f1b82746SMartin Schwidefsky  * clocksource_select - Select the best clocksource available
381734efb46Sjohn stultz  *
38275c5158fSMartin Schwidefsky  * Private function. Must hold clocksource_mutex when called.
383734efb46Sjohn stultz  *
38492c7e002SThomas Gleixner  * Select the clocksource with the best rating, or the clocksource,
38592c7e002SThomas Gleixner  * which is selected by userspace override.
386734efb46Sjohn stultz  */
387f1b82746SMartin Schwidefsky static void clocksource_select(void)
388734efb46Sjohn stultz {
389f1b82746SMartin Schwidefsky 	struct clocksource *best, *cs;
3905d8b34fdSThomas Gleixner 
39175c5158fSMartin Schwidefsky 	if (!finished_booting || list_empty(&clocksource_list))
392f1b82746SMartin Schwidefsky 		return;
393f1b82746SMartin Schwidefsky 	/* First clocksource on the list has the best rating. */
394f1b82746SMartin Schwidefsky 	best = list_first_entry(&clocksource_list, struct clocksource, list);
395f1b82746SMartin Schwidefsky 	/* Check for the override clocksource. */
396f1b82746SMartin Schwidefsky 	list_for_each_entry(cs, &clocksource_list, list) {
397f1b82746SMartin Schwidefsky 		if (strcmp(cs->name, override_name) != 0)
398f1b82746SMartin Schwidefsky 			continue;
399f1b82746SMartin Schwidefsky 		/*
400f1b82746SMartin Schwidefsky 		 * Check to make sure we don't switch to a non-highres
401f1b82746SMartin Schwidefsky 		 * capable clocksource if the tick code is in oneshot
402f1b82746SMartin Schwidefsky 		 * mode (highres or nohz)
403f1b82746SMartin Schwidefsky 		 */
404f1b82746SMartin Schwidefsky 		if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) &&
405f1b82746SMartin Schwidefsky 		    tick_oneshot_mode_active()) {
406f1b82746SMartin Schwidefsky 			/* Override clocksource cannot be used. */
407f1b82746SMartin Schwidefsky 			printk(KERN_WARNING "Override clocksource %s is not "
408f1b82746SMartin Schwidefsky 			       "HRT compatible. Cannot switch while in "
409f1b82746SMartin Schwidefsky 			       "HRT/NOHZ mode\n", cs->name);
410f1b82746SMartin Schwidefsky 			override_name[0] = 0;
411f1b82746SMartin Schwidefsky 		} else
412f1b82746SMartin Schwidefsky 			/* Override clocksource can be used. */
413f1b82746SMartin Schwidefsky 			best = cs;
414f1b82746SMartin Schwidefsky 		break;
415734efb46Sjohn stultz 	}
41675c5158fSMartin Schwidefsky 	if (curr_clocksource != best) {
41775c5158fSMartin Schwidefsky 		printk(KERN_INFO "Switching to clocksource %s\n", best->name);
41875c5158fSMartin Schwidefsky 		curr_clocksource = best;
41975c5158fSMartin Schwidefsky 		timekeeping_notify(curr_clocksource);
420f1b82746SMartin Schwidefsky 	}
42175c5158fSMartin Schwidefsky }
42275c5158fSMartin Schwidefsky 
42375c5158fSMartin Schwidefsky /*
42475c5158fSMartin Schwidefsky  * clocksource_done_booting - Called near the end of core bootup
42575c5158fSMartin Schwidefsky  *
42675c5158fSMartin Schwidefsky  * Hack to avoid lots of clocksource churn at boot time.
42775c5158fSMartin Schwidefsky  * We use fs_initcall because we want this to start before
42875c5158fSMartin Schwidefsky  * device_initcall but after subsys_initcall.
42975c5158fSMartin Schwidefsky  */
43075c5158fSMartin Schwidefsky static int __init clocksource_done_booting(void)
43175c5158fSMartin Schwidefsky {
43275c5158fSMartin Schwidefsky 	finished_booting = 1;
43375c5158fSMartin Schwidefsky 	clocksource_select();
43475c5158fSMartin Schwidefsky 	return 0;
43575c5158fSMartin Schwidefsky }
43675c5158fSMartin Schwidefsky fs_initcall(clocksource_done_booting);
437f1b82746SMartin Schwidefsky 
438f1b82746SMartin Schwidefsky #else /* CONFIG_GENERIC_TIME */
439f1b82746SMartin Schwidefsky 
44075c5158fSMartin Schwidefsky static inline void clocksource_select(void) { }
441f1b82746SMartin Schwidefsky 
442f1b82746SMartin Schwidefsky #endif
443734efb46Sjohn stultz 
44492c7e002SThomas Gleixner /*
44592c7e002SThomas Gleixner  * Enqueue the clocksource sorted by rating
446734efb46Sjohn stultz  */
447f1b82746SMartin Schwidefsky static void clocksource_enqueue(struct clocksource *cs)
448734efb46Sjohn stultz {
449f1b82746SMartin Schwidefsky 	struct list_head *entry = &clocksource_list;
450f1b82746SMartin Schwidefsky 	struct clocksource *tmp;
451734efb46Sjohn stultz 
452f1b82746SMartin Schwidefsky 	list_for_each_entry(tmp, &clocksource_list, list)
45392c7e002SThomas Gleixner 		/* Keep track of the place, where to insert */
454f1b82746SMartin Schwidefsky 		if (tmp->rating >= cs->rating)
455f1b82746SMartin Schwidefsky 			entry = &tmp->list;
456f1b82746SMartin Schwidefsky 	list_add(&cs->list, entry);
457734efb46Sjohn stultz }
458734efb46Sjohn stultz 
459734efb46Sjohn stultz /**
460a2752549Sjohn stultz  * clocksource_register - Used to install new clocksources
461734efb46Sjohn stultz  * @t:		clocksource to be registered
462734efb46Sjohn stultz  *
463734efb46Sjohn stultz  * Returns -EBUSY if registration fails, zero otherwise.
464734efb46Sjohn stultz  */
465f1b82746SMartin Schwidefsky int clocksource_register(struct clocksource *cs)
466734efb46Sjohn stultz {
46775c5158fSMartin Schwidefsky 	mutex_lock(&clocksource_mutex);
468f1b82746SMartin Schwidefsky 	clocksource_enqueue(cs);
469f1b82746SMartin Schwidefsky 	clocksource_select();
470fb63a0ebSMartin Schwidefsky 	clocksource_enqueue_watchdog(cs);
47175c5158fSMartin Schwidefsky 	mutex_unlock(&clocksource_mutex);
472f1b82746SMartin Schwidefsky 	return 0;
473734efb46Sjohn stultz }
474a2752549Sjohn stultz EXPORT_SYMBOL(clocksource_register);
475734efb46Sjohn stultz 
476d0981a1bSThomas Gleixner static void __clocksource_change_rating(struct clocksource *cs, int rating)
477d0981a1bSThomas Gleixner {
478d0981a1bSThomas Gleixner 	list_del(&cs->list);
479d0981a1bSThomas Gleixner 	cs->rating = rating;
480d0981a1bSThomas Gleixner 	clocksource_enqueue(cs);
481d0981a1bSThomas Gleixner 	clocksource_select();
482d0981a1bSThomas Gleixner }
483d0981a1bSThomas Gleixner 
484734efb46Sjohn stultz /**
48592c7e002SThomas Gleixner  * clocksource_change_rating - Change the rating of a registered clocksource
486734efb46Sjohn stultz  */
48792c7e002SThomas Gleixner void clocksource_change_rating(struct clocksource *cs, int rating)
488734efb46Sjohn stultz {
48975c5158fSMartin Schwidefsky 	mutex_lock(&clocksource_mutex);
490d0981a1bSThomas Gleixner 	__clocksource_change_rating(cs, rating);
49175c5158fSMartin Schwidefsky 	mutex_unlock(&clocksource_mutex);
492734efb46Sjohn stultz }
493fb63a0ebSMartin Schwidefsky EXPORT_SYMBOL(clocksource_change_rating);
494734efb46Sjohn stultz 
4954713e22cSThomas Gleixner /**
4964713e22cSThomas Gleixner  * clocksource_unregister - remove a registered clocksource
4974713e22cSThomas Gleixner  */
4984713e22cSThomas Gleixner void clocksource_unregister(struct clocksource *cs)
4994713e22cSThomas Gleixner {
50075c5158fSMartin Schwidefsky 	mutex_lock(&clocksource_mutex);
501fb63a0ebSMartin Schwidefsky 	clocksource_dequeue_watchdog(cs);
5024713e22cSThomas Gleixner 	list_del(&cs->list);
503f1b82746SMartin Schwidefsky 	clocksource_select();
50475c5158fSMartin Schwidefsky 	mutex_unlock(&clocksource_mutex);
5054713e22cSThomas Gleixner }
506fb63a0ebSMartin Schwidefsky EXPORT_SYMBOL(clocksource_unregister);
5074713e22cSThomas Gleixner 
5082b013700SDaniel Walker #ifdef CONFIG_SYSFS
509734efb46Sjohn stultz /**
510734efb46Sjohn stultz  * sysfs_show_current_clocksources - sysfs interface for current clocksource
511734efb46Sjohn stultz  * @dev:	unused
512734efb46Sjohn stultz  * @buf:	char buffer to be filled with clocksource list
513734efb46Sjohn stultz  *
514734efb46Sjohn stultz  * Provides sysfs interface for listing current clocksource.
515734efb46Sjohn stultz  */
516734efb46Sjohn stultz static ssize_t
5174a0b2b4dSAndi Kleen sysfs_show_current_clocksources(struct sys_device *dev,
5184a0b2b4dSAndi Kleen 				struct sysdev_attribute *attr, char *buf)
519734efb46Sjohn stultz {
5205e2cb101SMiao Xie 	ssize_t count = 0;
521734efb46Sjohn stultz 
52275c5158fSMartin Schwidefsky 	mutex_lock(&clocksource_mutex);
5235e2cb101SMiao Xie 	count = snprintf(buf, PAGE_SIZE, "%s\n", curr_clocksource->name);
52475c5158fSMartin Schwidefsky 	mutex_unlock(&clocksource_mutex);
525734efb46Sjohn stultz 
5265e2cb101SMiao Xie 	return count;
527734efb46Sjohn stultz }
528734efb46Sjohn stultz 
529734efb46Sjohn stultz /**
530734efb46Sjohn stultz  * sysfs_override_clocksource - interface for manually overriding clocksource
531734efb46Sjohn stultz  * @dev:	unused
532734efb46Sjohn stultz  * @buf:	name of override clocksource
533734efb46Sjohn stultz  * @count:	length of buffer
534734efb46Sjohn stultz  *
535734efb46Sjohn stultz  * Takes input from sysfs interface for manually overriding the default
536734efb46Sjohn stultz  * clocksource selction.
537734efb46Sjohn stultz  */
538734efb46Sjohn stultz static ssize_t sysfs_override_clocksource(struct sys_device *dev,
5394a0b2b4dSAndi Kleen 					  struct sysdev_attribute *attr,
540734efb46Sjohn stultz 					  const char *buf, size_t count)
541734efb46Sjohn stultz {
542734efb46Sjohn stultz 	size_t ret = count;
54392c7e002SThomas Gleixner 
544734efb46Sjohn stultz 	/* strings from sysfs write are not 0 terminated! */
545734efb46Sjohn stultz 	if (count >= sizeof(override_name))
546734efb46Sjohn stultz 		return -EINVAL;
547734efb46Sjohn stultz 
548734efb46Sjohn stultz 	/* strip of \n: */
549734efb46Sjohn stultz 	if (buf[count-1] == '\n')
550734efb46Sjohn stultz 		count--;
551734efb46Sjohn stultz 
55275c5158fSMartin Schwidefsky 	mutex_lock(&clocksource_mutex);
553734efb46Sjohn stultz 
55492c7e002SThomas Gleixner 	if (count > 0)
555734efb46Sjohn stultz 		memcpy(override_name, buf, count);
556734efb46Sjohn stultz 	override_name[count] = 0;
557f1b82746SMartin Schwidefsky 	clocksource_select();
558734efb46Sjohn stultz 
55975c5158fSMartin Schwidefsky 	mutex_unlock(&clocksource_mutex);
560734efb46Sjohn stultz 
561734efb46Sjohn stultz 	return ret;
562734efb46Sjohn stultz }
563734efb46Sjohn stultz 
564734efb46Sjohn stultz /**
565734efb46Sjohn stultz  * sysfs_show_available_clocksources - sysfs interface for listing clocksource
566734efb46Sjohn stultz  * @dev:	unused
567734efb46Sjohn stultz  * @buf:	char buffer to be filled with clocksource list
568734efb46Sjohn stultz  *
569734efb46Sjohn stultz  * Provides sysfs interface for listing registered clocksources
570734efb46Sjohn stultz  */
571734efb46Sjohn stultz static ssize_t
5724a0b2b4dSAndi Kleen sysfs_show_available_clocksources(struct sys_device *dev,
5734a0b2b4dSAndi Kleen 				  struct sysdev_attribute *attr,
5744a0b2b4dSAndi Kleen 				  char *buf)
575734efb46Sjohn stultz {
5762e197586SMatthias Kaehlcke 	struct clocksource *src;
5775e2cb101SMiao Xie 	ssize_t count = 0;
578734efb46Sjohn stultz 
57975c5158fSMartin Schwidefsky 	mutex_lock(&clocksource_mutex);
5802e197586SMatthias Kaehlcke 	list_for_each_entry(src, &clocksource_list, list) {
581cd6d95d8SThomas Gleixner 		/*
582cd6d95d8SThomas Gleixner 		 * Don't show non-HRES clocksource if the tick code is
583cd6d95d8SThomas Gleixner 		 * in one shot mode (highres=on or nohz=on)
584cd6d95d8SThomas Gleixner 		 */
585cd6d95d8SThomas Gleixner 		if (!tick_oneshot_mode_active() ||
5863f68535aSjohn stultz 		    (src->flags & CLOCK_SOURCE_VALID_FOR_HRES))
5875e2cb101SMiao Xie 			count += snprintf(buf + count,
5885e2cb101SMiao Xie 				  max((ssize_t)PAGE_SIZE - count, (ssize_t)0),
5895e2cb101SMiao Xie 				  "%s ", src->name);
590734efb46Sjohn stultz 	}
59175c5158fSMartin Schwidefsky 	mutex_unlock(&clocksource_mutex);
592734efb46Sjohn stultz 
5935e2cb101SMiao Xie 	count += snprintf(buf + count,
5945e2cb101SMiao Xie 			  max((ssize_t)PAGE_SIZE - count, (ssize_t)0), "\n");
595734efb46Sjohn stultz 
5965e2cb101SMiao Xie 	return count;
597734efb46Sjohn stultz }
598734efb46Sjohn stultz 
599734efb46Sjohn stultz /*
600734efb46Sjohn stultz  * Sysfs setup bits:
601734efb46Sjohn stultz  */
6024f95f81aSHeiko Carstens static SYSDEV_ATTR(current_clocksource, 0644, sysfs_show_current_clocksources,
603734efb46Sjohn stultz 		   sysfs_override_clocksource);
604734efb46Sjohn stultz 
6054f95f81aSHeiko Carstens static SYSDEV_ATTR(available_clocksource, 0444,
606734efb46Sjohn stultz 		   sysfs_show_available_clocksources, NULL);
607734efb46Sjohn stultz 
608734efb46Sjohn stultz static struct sysdev_class clocksource_sysclass = {
609af5ca3f4SKay Sievers 	.name = "clocksource",
610734efb46Sjohn stultz };
611734efb46Sjohn stultz 
612734efb46Sjohn stultz static struct sys_device device_clocksource = {
613734efb46Sjohn stultz 	.id	= 0,
614734efb46Sjohn stultz 	.cls	= &clocksource_sysclass,
615734efb46Sjohn stultz };
616734efb46Sjohn stultz 
617ad596171Sjohn stultz static int __init init_clocksource_sysfs(void)
618734efb46Sjohn stultz {
619734efb46Sjohn stultz 	int error = sysdev_class_register(&clocksource_sysclass);
620734efb46Sjohn stultz 
621734efb46Sjohn stultz 	if (!error)
622734efb46Sjohn stultz 		error = sysdev_register(&device_clocksource);
623734efb46Sjohn stultz 	if (!error)
624734efb46Sjohn stultz 		error = sysdev_create_file(
625734efb46Sjohn stultz 				&device_clocksource,
626734efb46Sjohn stultz 				&attr_current_clocksource);
627734efb46Sjohn stultz 	if (!error)
628734efb46Sjohn stultz 		error = sysdev_create_file(
629734efb46Sjohn stultz 				&device_clocksource,
630734efb46Sjohn stultz 				&attr_available_clocksource);
631734efb46Sjohn stultz 	return error;
632734efb46Sjohn stultz }
633734efb46Sjohn stultz 
634734efb46Sjohn stultz device_initcall(init_clocksource_sysfs);
6352b013700SDaniel Walker #endif /* CONFIG_SYSFS */
636734efb46Sjohn stultz 
637734efb46Sjohn stultz /**
638734efb46Sjohn stultz  * boot_override_clocksource - boot clock override
639734efb46Sjohn stultz  * @str:	override name
640734efb46Sjohn stultz  *
641734efb46Sjohn stultz  * Takes a clocksource= boot argument and uses it
642734efb46Sjohn stultz  * as the clocksource override name.
643734efb46Sjohn stultz  */
644734efb46Sjohn stultz static int __init boot_override_clocksource(char* str)
645734efb46Sjohn stultz {
64675c5158fSMartin Schwidefsky 	mutex_lock(&clocksource_mutex);
647734efb46Sjohn stultz 	if (str)
648734efb46Sjohn stultz 		strlcpy(override_name, str, sizeof(override_name));
64975c5158fSMartin Schwidefsky 	mutex_unlock(&clocksource_mutex);
650734efb46Sjohn stultz 	return 1;
651734efb46Sjohn stultz }
652734efb46Sjohn stultz 
653734efb46Sjohn stultz __setup("clocksource=", boot_override_clocksource);
654734efb46Sjohn stultz 
655734efb46Sjohn stultz /**
656734efb46Sjohn stultz  * boot_override_clock - Compatibility layer for deprecated boot option
657734efb46Sjohn stultz  * @str:	override name
658734efb46Sjohn stultz  *
659734efb46Sjohn stultz  * DEPRECATED! Takes a clock= boot argument and uses it
660734efb46Sjohn stultz  * as the clocksource override name
661734efb46Sjohn stultz  */
662734efb46Sjohn stultz static int __init boot_override_clock(char* str)
663734efb46Sjohn stultz {
6645d0cf410Sjohn stultz 	if (!strcmp(str, "pmtmr")) {
6655d0cf410Sjohn stultz 		printk("Warning: clock=pmtmr is deprecated. "
6665d0cf410Sjohn stultz 			"Use clocksource=acpi_pm.\n");
6675d0cf410Sjohn stultz 		return boot_override_clocksource("acpi_pm");
6685d0cf410Sjohn stultz 	}
6695d0cf410Sjohn stultz 	printk("Warning! clock= boot option is deprecated. "
6705d0cf410Sjohn stultz 		"Use clocksource=xyz\n");
671734efb46Sjohn stultz 	return boot_override_clocksource(str);
672734efb46Sjohn stultz }
673734efb46Sjohn stultz 
674734efb46Sjohn stultz __setup("clock=", boot_override_clock);
675