diff options
author | john stultz <johnstul@us.ibm.com> | 2006-06-26 03:25:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 12:58:20 -0400 |
commit | 734efb467b31e56c2f9430590a9aa867ecf3eea1 (patch) | |
tree | 30bf6b52d1e67128e656fb9a01cd7e6e13b7755e | |
parent | ade1a29e168ba08b699a418ff5e762315fa33f70 (diff) |
[PATCH] Time: Clocksource Infrastructure
This introduces the clocksource management infrastructure. A clocksource is a
driver-like architecture generic abstraction of a free-running counter. This
code defines the clocksource structure, and provides management code for
registering, selecting, accessing and scaling clocksources.
Additionally, this includes the trivial jiffies clocksource, a lowest common
denominator clocksource, provided mainly for use as an example.
[hirofumi@mail.parknet.co.jp: Don't enable IRQ too early]
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | Documentation/kernel-parameters.txt | 14 | ||||
-rw-r--r-- | include/linux/clocksource.h | 181 | ||||
-rw-r--r-- | kernel/time/Makefile | 1 | ||||
-rw-r--r-- | kernel/time/clocksource.c | 344 | ||||
-rw-r--r-- | kernel/time/jiffies.c | 73 |
5 files changed, 609 insertions, 4 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index bca6f389da66..968631678d4a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -61,6 +61,7 @@ parameter is applicable: | |||
61 | MTD MTD support is enabled. | 61 | MTD MTD support is enabled. |
62 | NET Appropriate network support is enabled. | 62 | NET Appropriate network support is enabled. |
63 | NUMA NUMA support is enabled. | 63 | NUMA NUMA support is enabled. |
64 | GENERIC_TIME The generic timeofday code is enabled. | ||
64 | NFS Appropriate NFS support is enabled. | 65 | NFS Appropriate NFS support is enabled. |
65 | OSS OSS sound support is enabled. | 66 | OSS OSS sound support is enabled. |
66 | PARIDE The ParIDE subsystem is enabled. | 67 | PARIDE The ParIDE subsystem is enabled. |
@@ -341,10 +342,11 @@ running once the system is up. | |||
341 | Value can be changed at runtime via | 342 | Value can be changed at runtime via |
342 | /selinux/checkreqprot. | 343 | /selinux/checkreqprot. |
343 | 344 | ||
344 | clock= [BUGS=IA-32,HW] gettimeofday timesource override. | 345 | clock= [BUGS=IA-32, HW] gettimeofday clocksource override. |
345 | Forces specified timesource (if avaliable) to be used | 346 | [Deprecated] |
346 | when calculating gettimeofday(). If specicified | 347 | Forces specified clocksource (if avaliable) to be used |
347 | timesource is not avalible, it defaults to PIT. | 348 | when calculating gettimeofday(). If specified |
349 | clocksource is not avalible, it defaults to PIT. | ||
348 | Format: { pit | tsc | cyclone | pmtmr } | 350 | Format: { pit | tsc | cyclone | pmtmr } |
349 | 351 | ||
350 | disable_8254_timer | 352 | disable_8254_timer |
@@ -1617,6 +1619,10 @@ running once the system is up. | |||
1617 | 1619 | ||
1618 | time Show timing data prefixed to each printk message line | 1620 | time Show timing data prefixed to each printk message line |
1619 | 1621 | ||
1622 | clocksource= [GENERIC_TIME] Override the default clocksource | ||
1623 | Override the default clocksource and use the clocksource | ||
1624 | with the name specified. | ||
1625 | |||
1620 | tipar.timeout= [HW,PPT] | 1626 | tipar.timeout= [HW,PPT] |
1621 | Set communications timeout in tenths of a second | 1627 | Set communications timeout in tenths of a second |
1622 | (default 15). | 1628 | (default 15). |
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h new file mode 100644 index 000000000000..c4187cda0ee4 --- /dev/null +++ b/include/linux/clocksource.h | |||
@@ -0,0 +1,181 @@ | |||
1 | /* linux/include/linux/clocksource.h | ||
2 | * | ||
3 | * This file contains the structure definitions for clocksources. | ||
4 | * | ||
5 | * If you are not a clocksource, or timekeeping code, you should | ||
6 | * not be including this file! | ||
7 | */ | ||
8 | #ifndef _LINUX_CLOCKSOURCE_H | ||
9 | #define _LINUX_CLOCKSOURCE_H | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | #include <linux/timex.h> | ||
13 | #include <linux/time.h> | ||
14 | #include <linux/list.h> | ||
15 | #include <asm/div64.h> | ||
16 | #include <asm/io.h> | ||
17 | |||
18 | /* clocksource cycle base type */ | ||
19 | typedef u64 cycle_t; | ||
20 | |||
21 | /** | ||
22 | * struct clocksource - hardware abstraction for a free running counter | ||
23 | * Provides mostly state-free accessors to the underlying hardware. | ||
24 | * | ||
25 | * @name: ptr to clocksource name | ||
26 | * @list: list head for registration | ||
27 | * @rating: rating value for selection (higher is better) | ||
28 | * To avoid rating inflation the following | ||
29 | * list should give you a guide as to how | ||
30 | * to assign your clocksource a rating | ||
31 | * 1-99: Unfit for real use | ||
32 | * Only available for bootup and testing purposes. | ||
33 | * 100-199: Base level usability. | ||
34 | * Functional for real use, but not desired. | ||
35 | * 200-299: Good. | ||
36 | * A correct and usable clocksource. | ||
37 | * 300-399: Desired. | ||
38 | * A reasonably fast and accurate clocksource. | ||
39 | * 400-499: Perfect | ||
40 | * The ideal clocksource. A must-use where | ||
41 | * available. | ||
42 | * @read: returns a cycle value | ||
43 | * @mask: bitmask for two's complement | ||
44 | * subtraction of non 64 bit counters | ||
45 | * @mult: cycle to nanosecond multiplier | ||
46 | * @shift: cycle to nanosecond divisor (power of two) | ||
47 | * @update_callback: called when safe to alter clocksource values | ||
48 | * @is_continuous: defines if clocksource is free-running. | ||
49 | * @interval_cycles: Used internally by timekeeping core, please ignore. | ||
50 | * @interval_snsecs: Used internally by timekeeping core, please ignore. | ||
51 | */ | ||
52 | struct clocksource { | ||
53 | char *name; | ||
54 | struct list_head list; | ||
55 | int rating; | ||
56 | cycle_t (*read)(void); | ||
57 | cycle_t mask; | ||
58 | u32 mult; | ||
59 | u32 shift; | ||
60 | int (*update_callback)(void); | ||
61 | int is_continuous; | ||
62 | |||
63 | /* timekeeping specific data, ignore */ | ||
64 | cycle_t interval_cycles; | ||
65 | u64 interval_snsecs; | ||
66 | }; | ||
67 | |||
68 | |||
69 | /** | ||
70 | * clocksource_khz2mult - calculates mult from khz and shift | ||
71 | * @khz: Clocksource frequency in KHz | ||
72 | * @shift_constant: Clocksource shift factor | ||
73 | * | ||
74 | * Helper functions that converts a khz counter frequency to a timsource | ||
75 | * multiplier, given the clocksource shift value | ||
76 | */ | ||
77 | static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant) | ||
78 | { | ||
79 | /* khz = cyc/(Million ns) | ||
80 | * mult/2^shift = ns/cyc | ||
81 | * mult = ns/cyc * 2^shift | ||
82 | * mult = 1Million/khz * 2^shift | ||
83 | * mult = 1000000 * 2^shift / khz | ||
84 | * mult = (1000000<<shift) / khz | ||
85 | */ | ||
86 | u64 tmp = ((u64)1000000) << shift_constant; | ||
87 | |||
88 | tmp += khz/2; /* round for do_div */ | ||
89 | do_div(tmp, khz); | ||
90 | |||
91 | return (u32)tmp; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * clocksource_hz2mult - calculates mult from hz and shift | ||
96 | * @hz: Clocksource frequency in Hz | ||
97 | * @shift_constant: Clocksource shift factor | ||
98 | * | ||
99 | * Helper functions that converts a hz counter | ||
100 | * frequency to a timsource multiplier, given the | ||
101 | * clocksource shift value | ||
102 | */ | ||
103 | static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant) | ||
104 | { | ||
105 | /* hz = cyc/(Billion ns) | ||
106 | * mult/2^shift = ns/cyc | ||
107 | * mult = ns/cyc * 2^shift | ||
108 | * mult = 1Billion/hz * 2^shift | ||
109 | * mult = 1000000000 * 2^shift / hz | ||
110 | * mult = (1000000000<<shift) / hz | ||
111 | */ | ||
112 | u64 tmp = ((u64)1000000000) << shift_constant; | ||
113 | |||
114 | tmp += hz/2; /* round for do_div */ | ||
115 | do_div(tmp, hz); | ||
116 | |||
117 | return (u32)tmp; | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * read_clocksource: - Access the clocksource's current cycle value | ||
122 | * @cs: pointer to clocksource being read | ||
123 | * | ||
124 | * Uses the clocksource to return the current cycle_t value | ||
125 | */ | ||
126 | static inline cycle_t read_clocksource(struct clocksource *cs) | ||
127 | { | ||
128 | return cs->read(); | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * cyc2ns - converts clocksource cycles to nanoseconds | ||
133 | * @cs: Pointer to clocksource | ||
134 | * @cycles: Cycles | ||
135 | * | ||
136 | * Uses the clocksource and ntp ajdustment to convert cycle_ts to nanoseconds. | ||
137 | * | ||
138 | * XXX - This could use some mult_lxl_ll() asm optimization | ||
139 | */ | ||
140 | static inline s64 cyc2ns(struct clocksource *cs, cycle_t cycles) | ||
141 | { | ||
142 | u64 ret = (u64)cycles; | ||
143 | ret = (ret * cs->mult) >> cs->shift; | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * calculate_clocksource_interval - Calculates a clocksource interval struct | ||
149 | * | ||
150 | * @c: Pointer to clocksource. | ||
151 | * @length_nsec: Desired interval length in nanoseconds. | ||
152 | * | ||
153 | * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment | ||
154 | * pair and interval request. | ||
155 | * | ||
156 | * Unless you're the timekeeping code, you should not be using this! | ||
157 | */ | ||
158 | static inline void calculate_clocksource_interval(struct clocksource *c, | ||
159 | unsigned long length_nsec) | ||
160 | { | ||
161 | u64 tmp; | ||
162 | |||
163 | /* XXX - All of this could use a whole lot of optimization */ | ||
164 | tmp = length_nsec; | ||
165 | tmp <<= c->shift; | ||
166 | tmp += c->mult/2; | ||
167 | do_div(tmp, c->mult); | ||
168 | |||
169 | c->interval_cycles = (cycle_t)tmp; | ||
170 | if(c->interval_cycles == 0) | ||
171 | c->interval_cycles = 1; | ||
172 | |||
173 | c->interval_snsecs = (u64)c->interval_cycles * c->mult; | ||
174 | } | ||
175 | |||
176 | /* used to install a new clocksource */ | ||
177 | int register_clocksource(struct clocksource*); | ||
178 | void reselect_clocksource(void); | ||
179 | struct clocksource* get_next_clocksource(void); | ||
180 | |||
181 | #endif /* _LINUX_CLOCKSOURCE_H */ | ||
diff --git a/kernel/time/Makefile b/kernel/time/Makefile new file mode 100644 index 000000000000..e1dfd8e86cce --- /dev/null +++ b/kernel/time/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y += clocksource.o jiffies.o | |||
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c new file mode 100644 index 000000000000..95dd2200a109 --- /dev/null +++ b/kernel/time/clocksource.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * linux/kernel/time/clocksource.c | ||
3 | * | ||
4 | * This file contains the functions which manage clocksource drivers. | ||
5 | * | ||
6 | * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) | ||
7 | * | ||
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. | ||
12 | * | ||
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. | ||
17 | * | ||
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. | ||
21 | * | ||
22 | * TODO WishList: | ||
23 | * o Allow clocksource drivers to be unregistered | ||
24 | * o get rid of clocksource_jiffies extern | ||
25 | */ | ||
26 | |||
27 | #include <linux/clocksource.h> | ||
28 | #include <linux/sysdev.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/module.h> | ||
31 | |||
32 | /* XXX - Would like a better way for initializing curr_clocksource */ | ||
33 | extern struct clocksource clocksource_jiffies; | ||
34 | |||
35 | /*[Clocksource internal variables]--------- | ||
36 | * curr_clocksource: | ||
37 | * currently selected clocksource. Initialized to clocksource_jiffies. | ||
38 | * next_clocksource: | ||
39 | * pending next selected clocksource. | ||
40 | * clocksource_list: | ||
41 | * linked list with the registered clocksources | ||
42 | * clocksource_lock: | ||
43 | * protects manipulations to curr_clocksource and next_clocksource | ||
44 | * and the clocksource_list | ||
45 | * override_name: | ||
46 | * Name of the user-specified clocksource. | ||
47 | */ | ||
48 | static struct clocksource *curr_clocksource = &clocksource_jiffies; | ||
49 | static struct clocksource *next_clocksource; | ||
50 | static LIST_HEAD(clocksource_list); | ||
51 | static DEFINE_SPINLOCK(clocksource_lock); | ||
52 | static char override_name[32]; | ||
53 | static int finished_booting; | ||
54 | |||
55 | /* clocksource_done_booting - Called near the end of bootup | ||
56 | * | ||
57 | * Hack to avoid lots of clocksource churn at boot time | ||
58 | */ | ||
59 | static int clocksource_done_booting(void) | ||
60 | { | ||
61 | finished_booting = 1; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | late_initcall(clocksource_done_booting); | ||
66 | |||
67 | /** | ||
68 | * get_next_clocksource - Returns the selected clocksource | ||
69 | * | ||
70 | */ | ||
71 | struct clocksource *get_next_clocksource(void) | ||
72 | { | ||
73 | unsigned long flags; | ||
74 | |||
75 | spin_lock_irqsave(&clocksource_lock, flags); | ||
76 | if (next_clocksource && finished_booting) { | ||
77 | curr_clocksource = next_clocksource; | ||
78 | next_clocksource = NULL; | ||
79 | } | ||
80 | spin_unlock_irqrestore(&clocksource_lock, flags); | ||
81 | |||
82 | return curr_clocksource; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * select_clocksource - Finds the best registered clocksource. | ||
87 | * | ||
88 | * Private function. Must hold clocksource_lock when called. | ||
89 | * | ||
90 | * Looks through the list of registered clocksources, returning | ||
91 | * the one with the highest rating value. If there is a clocksource | ||
92 | * name that matches the override string, it returns that clocksource. | ||
93 | */ | ||
94 | static struct clocksource *select_clocksource(void) | ||
95 | { | ||
96 | struct clocksource *best = NULL; | ||
97 | struct list_head *tmp; | ||
98 | |||
99 | list_for_each(tmp, &clocksource_list) { | ||
100 | struct clocksource *src; | ||
101 | |||
102 | src = list_entry(tmp, struct clocksource, list); | ||
103 | if (!best) | ||
104 | best = src; | ||
105 | |||
106 | /* check for override: */ | ||
107 | if (strlen(src->name) == strlen(override_name) && | ||
108 | !strcmp(src->name, override_name)) { | ||
109 | best = src; | ||
110 | break; | ||
111 | } | ||
112 | /* pick the highest rating: */ | ||
113 | if (src->rating > best->rating) | ||
114 | best = src; | ||
115 | } | ||
116 | |||
117 | return best; | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * is_registered_source - Checks if clocksource is registered | ||
122 | * @c: pointer to a clocksource | ||
123 | * | ||
124 | * Private helper function. Must hold clocksource_lock when called. | ||
125 | * | ||
126 | * Returns one if the clocksource is already registered, zero otherwise. | ||
127 | */ | ||
128 | static int is_registered_source(struct clocksource *c) | ||
129 | { | ||
130 | int len = strlen(c->name); | ||
131 | struct list_head *tmp; | ||
132 | |||
133 | list_for_each(tmp, &clocksource_list) { | ||
134 | struct clocksource *src; | ||
135 | |||
136 | src = list_entry(tmp, struct clocksource, list); | ||
137 | if (strlen(src->name) == len && !strcmp(src->name, c->name)) | ||
138 | return 1; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * register_clocksource - Used to install new clocksources | ||
146 | * @t: clocksource to be registered | ||
147 | * | ||
148 | * Returns -EBUSY if registration fails, zero otherwise. | ||
149 | */ | ||
150 | int register_clocksource(struct clocksource *c) | ||
151 | { | ||
152 | int ret = 0; | ||
153 | unsigned long flags; | ||
154 | |||
155 | spin_lock_irqsave(&clocksource_lock, flags); | ||
156 | /* check if clocksource is already registered */ | ||
157 | if (is_registered_source(c)) { | ||
158 | printk("register_clocksource: Cannot register %s. " | ||
159 | "Already registered!", c->name); | ||
160 | ret = -EBUSY; | ||
161 | } else { | ||
162 | /* register it */ | ||
163 | list_add(&c->list, &clocksource_list); | ||
164 | /* scan the registered clocksources, and pick the best one */ | ||
165 | next_clocksource = select_clocksource(); | ||
166 | } | ||
167 | spin_unlock_irqrestore(&clocksource_lock, flags); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | EXPORT_SYMBOL(register_clocksource); | ||
172 | |||
173 | /** | ||
174 | * reselect_clocksource - Rescan list for next clocksource | ||
175 | * | ||
176 | * A quick helper function to be used if a clocksource changes its | ||
177 | * rating. Forces the clocksource list to be re-scaned for the best | ||
178 | * clocksource. | ||
179 | */ | ||
180 | void reselect_clocksource(void) | ||
181 | { | ||
182 | unsigned long flags; | ||
183 | |||
184 | spin_lock_irqsave(&clocksource_lock, flags); | ||
185 | next_clocksource = select_clocksource(); | ||
186 | spin_unlock_irqrestore(&clocksource_lock, flags); | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * sysfs_show_current_clocksources - sysfs interface for current clocksource | ||
191 | * @dev: unused | ||
192 | * @buf: char buffer to be filled with clocksource list | ||
193 | * | ||
194 | * Provides sysfs interface for listing current clocksource. | ||
195 | */ | ||
196 | static ssize_t | ||
197 | sysfs_show_current_clocksources(struct sys_device *dev, char *buf) | ||
198 | { | ||
199 | char *curr = buf; | ||
200 | |||
201 | spin_lock_irq(&clocksource_lock); | ||
202 | curr += sprintf(curr, "%s ", curr_clocksource->name); | ||
203 | spin_unlock_irq(&clocksource_lock); | ||
204 | |||
205 | curr += sprintf(curr, "\n"); | ||
206 | |||
207 | return curr - buf; | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * sysfs_override_clocksource - interface for manually overriding clocksource | ||
212 | * @dev: unused | ||
213 | * @buf: name of override clocksource | ||
214 | * @count: length of buffer | ||
215 | * | ||
216 | * Takes input from sysfs interface for manually overriding the default | ||
217 | * clocksource selction. | ||
218 | */ | ||
219 | static ssize_t sysfs_override_clocksource(struct sys_device *dev, | ||
220 | const char *buf, size_t count) | ||
221 | { | ||
222 | size_t ret = count; | ||
223 | /* strings from sysfs write are not 0 terminated! */ | ||
224 | if (count >= sizeof(override_name)) | ||
225 | return -EINVAL; | ||
226 | |||
227 | /* strip of \n: */ | ||
228 | if (buf[count-1] == '\n') | ||
229 | count--; | ||
230 | if (count < 1) | ||
231 | return -EINVAL; | ||
232 | |||
233 | spin_lock_irq(&clocksource_lock); | ||
234 | |||
235 | /* copy the name given: */ | ||
236 | memcpy(override_name, buf, count); | ||
237 | override_name[count] = 0; | ||
238 | |||
239 | /* try to select it: */ | ||
240 | next_clocksource = select_clocksource(); | ||
241 | |||
242 | spin_unlock_irq(&clocksource_lock); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * sysfs_show_available_clocksources - sysfs interface for listing clocksource | ||
249 | * @dev: unused | ||
250 | * @buf: char buffer to be filled with clocksource list | ||
251 | * | ||
252 | * Provides sysfs interface for listing registered clocksources | ||
253 | */ | ||
254 | static ssize_t | ||
255 | sysfs_show_available_clocksources(struct sys_device *dev, char *buf) | ||
256 | { | ||
257 | struct list_head *tmp; | ||
258 | char *curr = buf; | ||
259 | |||
260 | spin_lock_irq(&clocksource_lock); | ||
261 | list_for_each(tmp, &clocksource_list) { | ||
262 | struct clocksource *src; | ||
263 | |||
264 | src = list_entry(tmp, struct clocksource, list); | ||
265 | curr += sprintf(curr, "%s ", src->name); | ||
266 | } | ||
267 | spin_unlock_irq(&clocksource_lock); | ||
268 | |||
269 | curr += sprintf(curr, "\n"); | ||
270 | |||
271 | return curr - buf; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Sysfs setup bits: | ||
276 | */ | ||
277 | static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources, | ||
278 | sysfs_override_clocksource); | ||
279 | |||
280 | static SYSDEV_ATTR(available_clocksource, 0600, | ||
281 | sysfs_show_available_clocksources, NULL); | ||
282 | |||
283 | static struct sysdev_class clocksource_sysclass = { | ||
284 | set_kset_name("clocksource"), | ||
285 | }; | ||
286 | |||
287 | static struct sys_device device_clocksource = { | ||
288 | .id = 0, | ||
289 | .cls = &clocksource_sysclass, | ||
290 | }; | ||
291 | |||
292 | static int init_clocksource_sysfs(void) | ||
293 | { | ||
294 | int error = sysdev_class_register(&clocksource_sysclass); | ||
295 | |||
296 | if (!error) | ||
297 | error = sysdev_register(&device_clocksource); | ||
298 | if (!error) | ||
299 | error = sysdev_create_file( | ||
300 | &device_clocksource, | ||
301 | &attr_current_clocksource); | ||
302 | if (!error) | ||
303 | error = sysdev_create_file( | ||
304 | &device_clocksource, | ||
305 | &attr_available_clocksource); | ||
306 | return error; | ||
307 | } | ||
308 | |||
309 | device_initcall(init_clocksource_sysfs); | ||
310 | |||
311 | /** | ||
312 | * boot_override_clocksource - boot clock override | ||
313 | * @str: override name | ||
314 | * | ||
315 | * Takes a clocksource= boot argument and uses it | ||
316 | * as the clocksource override name. | ||
317 | */ | ||
318 | static int __init boot_override_clocksource(char* str) | ||
319 | { | ||
320 | unsigned long flags; | ||
321 | spin_lock_irqsave(&clocksource_lock, flags); | ||
322 | if (str) | ||
323 | strlcpy(override_name, str, sizeof(override_name)); | ||
324 | spin_unlock_irqrestore(&clocksource_lock, flags); | ||
325 | return 1; | ||
326 | } | ||
327 | |||
328 | __setup("clocksource=", boot_override_clocksource); | ||
329 | |||
330 | /** | ||
331 | * boot_override_clock - Compatibility layer for deprecated boot option | ||
332 | * @str: override name | ||
333 | * | ||
334 | * DEPRECATED! Takes a clock= boot argument and uses it | ||
335 | * as the clocksource override name | ||
336 | */ | ||
337 | static int __init boot_override_clock(char* str) | ||
338 | { | ||
339 | printk("Warning! clock= boot option is deprecated.\n"); | ||
340 | |||
341 | return boot_override_clocksource(str); | ||
342 | } | ||
343 | |||
344 | __setup("clock=", boot_override_clock); | ||
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c new file mode 100644 index 000000000000..1fe8376e717b --- /dev/null +++ b/kernel/time/jiffies.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /*********************************************************************** | ||
2 | * linux/kernel/time/jiffies.c | ||
3 | * | ||
4 | * This file contains the jiffies based clocksource. | ||
5 | * | ||
6 | * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) | ||
7 | * | ||
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. | ||
12 | * | ||
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. | ||
17 | * | ||
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. | ||
21 | * | ||
22 | ************************************************************************/ | ||
23 | #include <linux/clocksource.h> | ||
24 | #include <linux/jiffies.h> | ||
25 | #include <linux/init.h> | ||
26 | |||
27 | /* The Jiffies based clocksource is the lowest common | ||
28 | * denominator clock source which should function on | ||
29 | * all systems. It has the same coarse resolution as | ||
30 | * the timer interrupt frequency HZ and it suffers | ||
31 | * inaccuracies caused by missed or lost timer | ||
32 | * interrupts and the inability for the timer | ||
33 | * interrupt hardware to accuratly tick at the | ||
34 | * requested HZ value. It is also not reccomended | ||
35 | * for "tick-less" systems. | ||
36 | */ | ||
37 | #define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ)) | ||
38 | |||
39 | /* Since jiffies uses a simple NSEC_PER_JIFFY multiplier | ||
40 | * conversion, the .shift value could be zero. However | ||
41 | * this would make NTP adjustments impossible as they are | ||
42 | * in units of 1/2^.shift. Thus we use JIFFIES_SHIFT to | ||
43 | * shift both the nominator and denominator the same | ||
44 | * amount, and give ntp adjustments in units of 1/2^8 | ||
45 | * | ||
46 | * The value 8 is somewhat carefully chosen, as anything | ||
47 | * larger can result in overflows. NSEC_PER_JIFFY grows as | ||
48 | * HZ shrinks, so values greater then 8 overflow 32bits when | ||
49 | * HZ=100. | ||
50 | */ | ||
51 | #define JIFFIES_SHIFT 8 | ||
52 | |||
53 | static cycle_t jiffies_read(void) | ||
54 | { | ||
55 | return (cycle_t) jiffies; | ||
56 | } | ||
57 | |||
58 | struct clocksource clocksource_jiffies = { | ||
59 | .name = "jiffies", | ||
60 | .rating = 0, /* lowest rating*/ | ||
61 | .read = jiffies_read, | ||
62 | .mask = 0xffffffff, /*32bits*/ | ||
63 | .mult = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */ | ||
64 | .shift = JIFFIES_SHIFT, | ||
65 | .is_continuous = 0, /* tick based, not free running */ | ||
66 | }; | ||
67 | |||
68 | static int __init init_jiffies_clocksource(void) | ||
69 | { | ||
70 | return register_clocksource(&clocksource_jiffies); | ||
71 | } | ||
72 | |||
73 | module_init(init_jiffies_clocksource); | ||