2 * linux/kernel/time/clocksource.c
4 * This file contains the functions which manage clocksource drivers.
6 * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * o Allow clocksource drivers to be unregistered
24 * o get rid of clocksource_jiffies extern
27 #include <linux/clocksource.h>
28 #include <linux/sysdev.h>
29 #include <linux/init.h>
30 #include <linux/module.h>
31 #include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */
33 /* XXX - Would like a better way for initializing curr_clocksource */
34 extern struct clocksource clocksource_jiffies;
36 /*[Clocksource internal variables]---------
38 * currently selected clocksource. Initialized to clocksource_jiffies.
40 * pending next selected clocksource.
42 * linked list with the registered clocksources
44 * protects manipulations to curr_clocksource and next_clocksource
45 * and the clocksource_list
47 * Name of the user-specified clocksource.
49 static struct clocksource *curr_clocksource = &clocksource_jiffies;
50 static struct clocksource *next_clocksource;
51 static struct clocksource *clocksource_override;
52 static LIST_HEAD(clocksource_list);
53 static DEFINE_SPINLOCK(clocksource_lock);
54 static char override_name[32];
55 static int finished_booting;
57 /* clocksource_done_booting - Called near the end of bootup
59 * Hack to avoid lots of clocksource churn at boot time
61 static int __init clocksource_done_booting(void)
67 late_initcall(clocksource_done_booting);
70 * clocksource_get_next - Returns the selected clocksource
73 struct clocksource *clocksource_get_next(void)
77 spin_lock_irqsave(&clocksource_lock, flags);
78 if (next_clocksource && finished_booting) {
79 curr_clocksource = next_clocksource;
80 next_clocksource = NULL;
82 spin_unlock_irqrestore(&clocksource_lock, flags);
84 return curr_clocksource;
88 * select_clocksource - Selects the best registered clocksource.
90 * Private function. Must hold clocksource_lock when called.
92 * Select the clocksource with the best rating, or the clocksource,
93 * which is selected by userspace override.
95 static struct clocksource *select_clocksource(void)
97 if (list_empty(&clocksource_list))
100 if (clocksource_override)
101 return clocksource_override;
103 return list_entry(clocksource_list.next, struct clocksource, list);
107 * Enqueue the clocksource sorted by rating
109 static int clocksource_enqueue(struct clocksource *c)
111 struct list_head *tmp, *entry = &clocksource_list;
113 list_for_each(tmp, &clocksource_list) {
114 struct clocksource *cs;
116 cs = list_entry(tmp, struct clocksource, list);
119 /* Keep track of the place, where to insert */
120 if (cs->rating >= c->rating)
123 list_add(&c->list, entry);
125 if (strlen(c->name) == strlen(override_name) &&
126 !strcmp(c->name, override_name))
127 clocksource_override = c;
133 * clocksource_register - Used to install new clocksources
134 * @t: clocksource to be registered
136 * Returns -EBUSY if registration fails, zero otherwise.
138 int clocksource_register(struct clocksource *c)
143 spin_lock_irqsave(&clocksource_lock, flags);
144 ret = clocksource_enqueue(c);
146 next_clocksource = select_clocksource();
147 spin_unlock_irqrestore(&clocksource_lock, flags);
150 EXPORT_SYMBOL(clocksource_register);
153 * clocksource_change_rating - Change the rating of a registered clocksource
156 void clocksource_change_rating(struct clocksource *cs, int rating)
160 spin_lock_irqsave(&clocksource_lock, flags);
162 clocksource_enqueue(cs);
163 next_clocksource = select_clocksource();
164 spin_unlock_irqrestore(&clocksource_lock, flags);
169 * sysfs_show_current_clocksources - sysfs interface for current clocksource
171 * @buf: char buffer to be filled with clocksource list
173 * Provides sysfs interface for listing current clocksource.
176 sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
180 spin_lock_irq(&clocksource_lock);
181 curr += sprintf(curr, "%s ", curr_clocksource->name);
182 spin_unlock_irq(&clocksource_lock);
184 curr += sprintf(curr, "\n");
190 * sysfs_override_clocksource - interface for manually overriding clocksource
192 * @buf: name of override clocksource
193 * @count: length of buffer
195 * Takes input from sysfs interface for manually overriding the default
196 * clocksource selction.
198 static ssize_t sysfs_override_clocksource(struct sys_device *dev,
199 const char *buf, size_t count)
201 struct clocksource *ovr = NULL;
202 struct list_head *tmp;
206 /* strings from sysfs write are not 0 terminated! */
207 if (count >= sizeof(override_name))
211 if (buf[count-1] == '\n')
214 spin_lock_irq(&clocksource_lock);
217 memcpy(override_name, buf, count);
218 override_name[count] = 0;
220 len = strlen(override_name);
222 ovr = clocksource_override;
223 /* try to select it: */
224 list_for_each(tmp, &clocksource_list) {
225 struct clocksource *cs;
227 cs = list_entry(tmp, struct clocksource, list);
228 if (strlen(cs->name) == len &&
229 !strcmp(cs->name, override_name))
234 /* Reselect, when the override name has changed */
235 if (ovr != clocksource_override) {
236 clocksource_override = ovr;
237 next_clocksource = select_clocksource();
240 spin_unlock_irq(&clocksource_lock);
246 * sysfs_show_available_clocksources - sysfs interface for listing clocksource
248 * @buf: char buffer to be filled with clocksource list
250 * Provides sysfs interface for listing registered clocksources
253 sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
255 struct list_head *tmp;
258 spin_lock_irq(&clocksource_lock);
259 list_for_each(tmp, &clocksource_list) {
260 struct clocksource *src;
262 src = list_entry(tmp, struct clocksource, list);
263 curr += sprintf(curr, "%s ", src->name);
265 spin_unlock_irq(&clocksource_lock);
267 curr += sprintf(curr, "\n");
275 static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources,
276 sysfs_override_clocksource);
278 static SYSDEV_ATTR(available_clocksource, 0600,
279 sysfs_show_available_clocksources, NULL);
281 static struct sysdev_class clocksource_sysclass = {
282 set_kset_name("clocksource"),
285 static struct sys_device device_clocksource = {
287 .cls = &clocksource_sysclass,
290 static int __init init_clocksource_sysfs(void)
292 int error = sysdev_class_register(&clocksource_sysclass);
295 error = sysdev_register(&device_clocksource);
297 error = sysdev_create_file(
299 &attr_current_clocksource);
301 error = sysdev_create_file(
303 &attr_available_clocksource);
307 device_initcall(init_clocksource_sysfs);
308 #endif /* CONFIG_SYSFS */
311 * boot_override_clocksource - boot clock override
312 * @str: override name
314 * Takes a clocksource= boot argument and uses it
315 * as the clocksource override name.
317 static int __init boot_override_clocksource(char* str)
320 spin_lock_irqsave(&clocksource_lock, flags);
322 strlcpy(override_name, str, sizeof(override_name));
323 spin_unlock_irqrestore(&clocksource_lock, flags);
327 __setup("clocksource=", boot_override_clocksource);
330 * boot_override_clock - Compatibility layer for deprecated boot option
331 * @str: override name
333 * DEPRECATED! Takes a clock= boot argument and uses it
334 * as the clocksource override name
336 static int __init boot_override_clock(char* str)
338 if (!strcmp(str, "pmtmr")) {
339 printk("Warning: clock=pmtmr is deprecated. "
340 "Use clocksource=acpi_pm.\n");
341 return boot_override_clocksource("acpi_pm");
343 printk("Warning! clock= boot option is deprecated. "
344 "Use clocksource=xyz\n");
345 return boot_override_clocksource(str);
348 __setup("clock=", boot_override_clock);