diff options
author | Jesper Nilsson <jesper.nilsson@axis.com> | 2007-11-30 11:46:11 -0500 |
---|---|---|
committer | Jesper Nilsson <jesper.nilsson@axis.com> | 2008-02-08 05:06:27 -0500 |
commit | ec87ee20c28708bbd22f71f429d2e21c965c44e4 (patch) | |
tree | 8a9fd532909f001bfc9c010ae5b5c05c16b74b2d /arch/cris | |
parent | e867cefbaaac23644414cfe562b4fee7dc604f2e (diff) |
CRIS v32: Update and improve fasttimer.c
- Change include path to machine dependent header files.
- Remove __INLINE__, it expands to inline anyway.
- Don't initialize static variables.
- Change timers to use fasttimer_t instead of timevals.
- Change name of timeval_cmp to fasttime_cmp to highlight this.
- Register name for first timer is regi_timer0, not regi_timer.
- Whitespace and formatting changes.
- Don't return if we're blocking interrupts, goto done and restore interrupts.
- Disable interrupts while walking the fasttimer list, only restore
while doing the callback.
- Remove #ifdef DECLARE_WAITQUEUE, this code won't be used in another OS.
- Remove CVS log.
Diffstat (limited to 'arch/cris')
-rw-r--r-- | arch/cris/arch-v32/kernel/fasttimer.c | 519 |
1 files changed, 195 insertions, 324 deletions
diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c index b40551f9f40d..30514625eee0 100644 --- a/arch/cris/arch-v32/kernel/fasttimer.c +++ b/arch/cris/arch-v32/kernel/fasttimer.c | |||
@@ -1,110 +1,9 @@ | |||
1 | /* $Id: fasttimer.c,v 1.11 2005/01/04 11:15:46 starvik Exp $ | 1 | /* |
2 | * linux/arch/cris/kernel/fasttimer.c | 2 | * linux/arch/cris/kernel/fasttimer.c |
3 | * | 3 | * |
4 | * Fast timers for ETRAX FS | 4 | * Fast timers for ETRAX FS |
5 | * This may be useful in other OS than Linux so use 2 space indentation... | ||
6 | * | ||
7 | * $Log: fasttimer.c,v $ | ||
8 | * Revision 1.11 2005/01/04 11:15:46 starvik | ||
9 | * Don't share timer IRQ. | ||
10 | * | ||
11 | * Revision 1.10 2004/12/07 09:19:38 starvik | ||
12 | * Corrected includes. | ||
13 | * Use correct interrupt macros. | ||
14 | * | ||
15 | * Revision 1.9 2004/05/14 10:18:58 starvik | ||
16 | * Export fast_timer_list | ||
17 | * | ||
18 | * Revision 1.8 2004/05/14 07:58:03 starvik | ||
19 | * Merge of changes from 2.4 | ||
20 | * | ||
21 | * Revision 1.7 2003/07/10 12:06:14 starvik | ||
22 | * Return IRQ_NONE if irq wasn't handled | ||
23 | * | ||
24 | * Revision 1.6 2003/07/04 08:27:49 starvik | ||
25 | * Merge of Linux 2.5.74 | ||
26 | * | ||
27 | * Revision 1.5 2003/06/05 10:16:22 johana | ||
28 | * New INTR_VECT macros. | ||
29 | * | ||
30 | * Revision 1.4 2003/06/03 08:49:45 johana | ||
31 | * Fixed typo. | ||
32 | * | ||
33 | * Revision 1.3 2003/06/02 12:51:27 johana | ||
34 | * Now compiles. | ||
35 | * Commented some include files that probably can be removed. | ||
36 | * | ||
37 | * Revision 1.2 2003/06/02 12:09:41 johana | ||
38 | * Ported to ETRAX FS using the trig interrupt instead of timer1. | ||
39 | * | ||
40 | * Revision 1.3 2002/12/12 08:26:32 starvik | ||
41 | * Don't use C-comments inside CVS comments | ||
42 | * | ||
43 | * Revision 1.2 2002/12/11 15:42:02 starvik | ||
44 | * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/ | ||
45 | * | ||
46 | * Revision 1.1 2002/11/18 07:58:06 starvik | ||
47 | * Fast timers (from Linux 2.4) | ||
48 | * | 5 | * |
49 | * Revision 1.5 2002/10/15 06:21:39 starvik | 6 | * Copyright (C) 2000-2006 Axis Communications AB, Lund, Sweden |
50 | * Added call to init_waitqueue_head | ||
51 | * | ||
52 | * Revision 1.4 2002/05/28 17:47:59 johana | ||
53 | * Added del_fast_timer() | ||
54 | * | ||
55 | * Revision 1.3 2002/05/28 16:16:07 johana | ||
56 | * Handle empty fast_timer_list | ||
57 | * | ||
58 | * Revision 1.2 2002/05/27 15:38:42 johana | ||
59 | * Made it compile without warnings on Linux 2.4. | ||
60 | * (includes, wait_queue, PROC_FS and snprintf) | ||
61 | * | ||
62 | * Revision 1.1 2002/05/27 15:32:25 johana | ||
63 | * arch/etrax100/kernel/fasttimer.c v1.8 from the elinux tree. | ||
64 | * | ||
65 | * Revision 1.8 2001/11/27 13:50:40 pkj | ||
66 | * Disable interrupts while stopping the timer and while modifying the | ||
67 | * list of active timers in timer1_handler() as it may be interrupted | ||
68 | * by other interrupts (e.g., the serial interrupt) which may add fast | ||
69 | * timers. | ||
70 | * | ||
71 | * Revision 1.7 2001/11/22 11:50:32 pkj | ||
72 | * * Only store information about the last 16 timers. | ||
73 | * * proc_fasttimer_read() now uses an allocated buffer, since it | ||
74 | * requires more space than just a page even for only writing the | ||
75 | * last 16 timers. The buffer is only allocated on request, so | ||
76 | * unless /proc/fasttimer is read, it is never allocated. | ||
77 | * * Renamed fast_timer_started to fast_timers_started to match | ||
78 | * fast_timers_added and fast_timers_expired. | ||
79 | * * Some clean-up. | ||
80 | * | ||
81 | * Revision 1.6 2000/12/13 14:02:08 johana | ||
82 | * Removed volatile for fast_timer_list | ||
83 | * | ||
84 | * Revision 1.5 2000/12/13 13:55:35 johana | ||
85 | * Added DEBUG_LOG, added som cli() and cleanup | ||
86 | * | ||
87 | * Revision 1.4 2000/12/05 13:48:50 johana | ||
88 | * Added range check when writing proc file, modified timer int handling | ||
89 | * | ||
90 | * Revision 1.3 2000/11/23 10:10:20 johana | ||
91 | * More debug/logging possibilities. | ||
92 | * Moved GET_JIFFIES_USEC() to timex.h and time.c | ||
93 | * | ||
94 | * Revision 1.2 2000/11/01 13:41:04 johana | ||
95 | * Clean up and bugfixes. | ||
96 | * Created new do_gettimeofday_fast() that gets a timeval struct | ||
97 | * with time based on jiffies and *R_TIMER0_DATA, uses a table | ||
98 | * for fast conversion of timer value to microseconds. | ||
99 | * (Much faster the standard do_gettimeofday() and we don't really | ||
100 | * want to use the true time - we want the "uptime" so timers don't screw up | ||
101 | * when we change the time. | ||
102 | * TODO: Add efficient support for continuous timers as well. | ||
103 | * | ||
104 | * Revision 1.1 2000/10/26 15:49:16 johana | ||
105 | * Added fasttimer, highresolution timers. | ||
106 | * | ||
107 | * Copyright (C) 2000,2001 2002, 2003 Axis Communications AB, Lund, Sweden | ||
108 | */ | 7 | */ |
109 | 8 | ||
110 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
@@ -122,9 +21,9 @@ | |||
122 | 21 | ||
123 | #include <linux/version.h> | 22 | #include <linux/version.h> |
124 | 23 | ||
125 | #include <asm/arch/hwregs/reg_map.h> | 24 | #include <hwregs/reg_map.h> |
126 | #include <asm/arch/hwregs/reg_rdwr.h> | 25 | #include <hwregs/reg_rdwr.h> |
127 | #include <asm/arch/hwregs/timer_defs.h> | 26 | #include <hwregs/timer_defs.h> |
128 | #include <asm/fasttimer.h> | 27 | #include <asm/fasttimer.h> |
129 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
130 | 29 | ||
@@ -140,7 +39,7 @@ | |||
140 | 39 | ||
141 | #define DEBUG_LOG_INCLUDED | 40 | #define DEBUG_LOG_INCLUDED |
142 | #define FAST_TIMER_LOG | 41 | #define FAST_TIMER_LOG |
143 | //#define FAST_TIMER_TEST | 42 | /* #define FAST_TIMER_TEST */ |
144 | 43 | ||
145 | #define FAST_TIMER_SANITY_CHECKS | 44 | #define FAST_TIMER_SANITY_CHECKS |
146 | 45 | ||
@@ -155,15 +54,13 @@ static int sanity_failed = 0; | |||
155 | #define D2(x) | 54 | #define D2(x) |
156 | #define DP(x) | 55 | #define DP(x) |
157 | 56 | ||
158 | #define __INLINE__ inline | 57 | static unsigned int fast_timer_running; |
159 | 58 | static unsigned int fast_timers_added; | |
160 | static int fast_timer_running = 0; | 59 | static unsigned int fast_timers_started; |
161 | static int fast_timers_added = 0; | 60 | static unsigned int fast_timers_expired; |
162 | static int fast_timers_started = 0; | 61 | static unsigned int fast_timers_deleted; |
163 | static int fast_timers_expired = 0; | 62 | static unsigned int fast_timer_is_init; |
164 | static int fast_timers_deleted = 0; | 63 | static unsigned int fast_timer_ints; |
165 | static int fast_timer_is_init = 0; | ||
166 | static int fast_timer_ints = 0; | ||
167 | 64 | ||
168 | struct fast_timer *fast_timer_list = NULL; | 65 | struct fast_timer *fast_timer_list = NULL; |
169 | 66 | ||
@@ -171,8 +68,8 @@ struct fast_timer *fast_timer_list = NULL; | |||
171 | #define DEBUG_LOG_MAX 128 | 68 | #define DEBUG_LOG_MAX 128 |
172 | static const char * debug_log_string[DEBUG_LOG_MAX]; | 69 | static const char * debug_log_string[DEBUG_LOG_MAX]; |
173 | static unsigned long debug_log_value[DEBUG_LOG_MAX]; | 70 | static unsigned long debug_log_value[DEBUG_LOG_MAX]; |
174 | static int debug_log_cnt = 0; | 71 | static unsigned int debug_log_cnt; |
175 | static int debug_log_cnt_wrapped = 0; | 72 | static unsigned int debug_log_cnt_wrapped; |
176 | 73 | ||
177 | #define DEBUG_LOG(string, value) \ | 74 | #define DEBUG_LOG(string, value) \ |
178 | { \ | 75 | { \ |
@@ -202,103 +99,92 @@ struct fast_timer timer_expired_log[NUM_TIMER_STATS]; | |||
202 | int timer_div_settings[NUM_TIMER_STATS]; | 99 | int timer_div_settings[NUM_TIMER_STATS]; |
203 | int timer_delay_settings[NUM_TIMER_STATS]; | 100 | int timer_delay_settings[NUM_TIMER_STATS]; |
204 | 101 | ||
102 | struct work_struct fast_work; | ||
205 | 103 | ||
206 | static void | 104 | static void |
207 | timer_trig_handler(void); | 105 | timer_trig_handler(struct work_struct *work); |
208 | 106 | ||
209 | 107 | ||
210 | 108 | ||
211 | /* Not true gettimeofday, only checks the jiffies (uptime) + useconds */ | 109 | /* Not true gettimeofday, only checks the jiffies (uptime) + useconds */ |
212 | void __INLINE__ do_gettimeofday_fast(struct timeval *tv) | 110 | inline void do_gettimeofday_fast(struct fasttime_t *tv) |
213 | { | 111 | { |
214 | unsigned long sec = jiffies; | 112 | tv->tv_jiff = jiffies; |
215 | unsigned long usec = GET_JIFFIES_USEC(); | 113 | tv->tv_usec = GET_JIFFIES_USEC(); |
216 | |||
217 | usec += (sec % HZ) * (1000000 / HZ); | ||
218 | sec = sec / HZ; | ||
219 | |||
220 | if (usec > 1000000) | ||
221 | { | ||
222 | usec -= 1000000; | ||
223 | sec++; | ||
224 | } | ||
225 | tv->tv_sec = sec; | ||
226 | tv->tv_usec = usec; | ||
227 | } | 114 | } |
228 | 115 | ||
229 | int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1) | 116 | inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1) |
230 | { | 117 | { |
231 | if (t0->tv_sec < t1->tv_sec) | 118 | /* Compare jiffies. Takes care of wrapping */ |
232 | { | 119 | if (time_before(t0->tv_jiff, t1->tv_jiff)) |
233 | return -1; | 120 | return -1; |
234 | } | 121 | else if (time_after(t0->tv_jiff, t1->tv_jiff)) |
235 | else if (t0->tv_sec > t1->tv_sec) | 122 | return 1; |
236 | { | 123 | |
237 | return 1; | 124 | /* Compare us */ |
238 | } | 125 | if (t0->tv_usec < t1->tv_usec) |
239 | if (t0->tv_usec < t1->tv_usec) | 126 | return -1; |
240 | { | 127 | else if (t0->tv_usec > t1->tv_usec) |
241 | return -1; | 128 | return 1; |
242 | } | 129 | return 0; |
243 | else if (t0->tv_usec > t1->tv_usec) | ||
244 | { | ||
245 | return 1; | ||
246 | } | ||
247 | return 0; | ||
248 | } | 130 | } |
249 | 131 | ||
250 | /* Called with ints off */ | 132 | /* Called with ints off */ |
251 | void __INLINE__ start_timer_trig(unsigned long delay_us) | 133 | inline void start_timer_trig(unsigned long delay_us) |
252 | { | 134 | { |
253 | reg_timer_rw_ack_intr ack_intr = { 0 }; | 135 | reg_timer_rw_ack_intr ack_intr = { 0 }; |
254 | reg_timer_rw_intr_mask intr_mask; | 136 | reg_timer_rw_intr_mask intr_mask; |
255 | reg_timer_rw_trig trig; | 137 | reg_timer_rw_trig trig; |
256 | reg_timer_rw_trig_cfg trig_cfg = { 0 }; | 138 | reg_timer_rw_trig_cfg trig_cfg = { 0 }; |
257 | reg_timer_r_time r_time; | 139 | reg_timer_r_time r_time0; |
140 | reg_timer_r_time r_time1; | ||
141 | unsigned char trig_wrap; | ||
142 | unsigned char time_wrap; | ||
258 | 143 | ||
259 | r_time = REG_RD(timer, regi_timer, r_time); | 144 | r_time0 = REG_RD(timer, regi_timer0, r_time); |
260 | 145 | ||
261 | D1(printk("start_timer_trig : %d us freq: %i div: %i\n", | 146 | D1(printk("start_timer_trig : %d us freq: %i div: %i\n", |
262 | delay_us, freq_index, div)); | 147 | delay_us, freq_index, div)); |
263 | /* Clear trig irq */ | 148 | /* Clear trig irq */ |
264 | intr_mask = REG_RD(timer, regi_timer, rw_intr_mask); | 149 | intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); |
265 | intr_mask.trig = 0; | 150 | intr_mask.trig = 0; |
266 | REG_WR(timer, regi_timer, rw_intr_mask, intr_mask); | 151 | REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); |
267 | 152 | ||
268 | /* Set timer values */ | 153 | /* Set timer values and check if trigger wraps. */ |
269 | /* r_time is 100MHz (10 ns resolution) */ | 154 | /* r_time is 100MHz (10 ns resolution) */ |
270 | trig = r_time + delay_us*(1000/10); | 155 | trig_wrap = (trig = r_time0 + delay_us*(1000/10)) < r_time0; |
271 | 156 | ||
272 | timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = trig; | 157 | timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = trig; |
273 | timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us; | 158 | timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us; |
274 | 159 | ||
275 | /* Ack interrupt */ | 160 | /* Ack interrupt */ |
276 | ack_intr.trig = 1; | 161 | ack_intr.trig = 1; |
277 | REG_WR(timer, regi_timer, rw_ack_intr, ack_intr); | 162 | REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); |
278 | 163 | ||
279 | /* Start timer */ | 164 | /* Start timer */ |
280 | REG_WR(timer, regi_timer, rw_trig, trig); | 165 | REG_WR(timer, regi_timer0, rw_trig, trig); |
281 | trig_cfg.tmr = regk_timer_time; | 166 | trig_cfg.tmr = regk_timer_time; |
282 | REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg); | 167 | REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); |
283 | 168 | ||
284 | /* Check if we have already passed the trig time */ | 169 | /* Check if we have already passed the trig time */ |
285 | r_time = REG_RD(timer, regi_timer, r_time); | 170 | r_time1 = REG_RD(timer, regi_timer0, r_time); |
286 | if (r_time < trig) { | 171 | time_wrap = r_time1 < r_time0; |
172 | |||
173 | if ((trig_wrap && !time_wrap) || (r_time1 < trig)) { | ||
287 | /* No, Enable trig irq */ | 174 | /* No, Enable trig irq */ |
288 | intr_mask = REG_RD(timer, regi_timer, rw_intr_mask); | 175 | intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); |
289 | intr_mask.trig = 1; | 176 | intr_mask.trig = 1; |
290 | REG_WR(timer, regi_timer, rw_intr_mask, intr_mask); | 177 | REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); |
291 | fast_timers_started++; | 178 | fast_timers_started++; |
292 | fast_timer_running = 1; | 179 | fast_timer_running = 1; |
293 | } | 180 | } else { |
294 | else | ||
295 | { | ||
296 | /* We have passed the time, disable trig point, ack intr */ | 181 | /* We have passed the time, disable trig point, ack intr */ |
297 | trig_cfg.tmr = regk_timer_off; | 182 | trig_cfg.tmr = regk_timer_off; |
298 | REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg); | 183 | REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); |
299 | REG_WR(timer, regi_timer, rw_ack_intr, ack_intr); | 184 | REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); |
300 | /* call the int routine directly */ | 185 | /* call the int routine */ |
301 | timer_trig_handler(); | 186 | INIT_WORK(&fast_work, timer_trig_handler); |
187 | schedule_work(&fast_work); | ||
302 | } | 188 | } |
303 | 189 | ||
304 | } | 190 | } |
@@ -321,18 +207,15 @@ void start_one_shot_timer(struct fast_timer *t, | |||
321 | tmp = fast_timer_list; | 207 | tmp = fast_timer_list; |
322 | 208 | ||
323 | SANITYCHECK({ /* Check so this is not in the list already... */ | 209 | SANITYCHECK({ /* Check so this is not in the list already... */ |
324 | while (tmp != NULL) | 210 | while (tmp != NULL) { |
325 | { | 211 | if (tmp == t) { |
326 | if (tmp == t) | 212 | printk(KERN_DEBUG |
327 | { | 213 | "timer name: %s data: 0x%08lX already " |
328 | printk("timer name: %s data: 0x%08lX already in list!\n", name, data); | 214 | "in list!\n", name, data); |
329 | sanity_failed++; | 215 | sanity_failed++; |
330 | return; | 216 | goto done; |
331 | } | 217 | } else |
332 | else | ||
333 | { | ||
334 | tmp = tmp->next; | 218 | tmp = tmp->next; |
335 | } | ||
336 | } | 219 | } |
337 | tmp = fast_timer_list; | 220 | tmp = fast_timer_list; |
338 | }); | 221 | }); |
@@ -343,11 +226,10 @@ void start_one_shot_timer(struct fast_timer *t, | |||
343 | t->name = name; | 226 | t->name = name; |
344 | 227 | ||
345 | t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000; | 228 | t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000; |
346 | t->tv_expires.tv_sec = t->tv_set.tv_sec + delay_us / 1000000; | 229 | t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ; |
347 | if (t->tv_expires.tv_usec > 1000000) | 230 | if (t->tv_expires.tv_usec > 1000000) { |
348 | { | ||
349 | t->tv_expires.tv_usec -= 1000000; | 231 | t->tv_expires.tv_usec -= 1000000; |
350 | t->tv_expires.tv_sec++; | 232 | t->tv_expires.tv_jiff += HZ; |
351 | } | 233 | } |
352 | #ifdef FAST_TIMER_LOG | 234 | #ifdef FAST_TIMER_LOG |
353 | timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t; | 235 | timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t; |
@@ -355,15 +237,12 @@ void start_one_shot_timer(struct fast_timer *t, | |||
355 | fast_timers_added++; | 237 | fast_timers_added++; |
356 | 238 | ||
357 | /* Check if this should timeout before anything else */ | 239 | /* Check if this should timeout before anything else */ |
358 | if (tmp == NULL || timeval_cmp(&t->tv_expires, &tmp->tv_expires) < 0) | 240 | if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) { |
359 | { | ||
360 | /* Put first in list and modify the timer value */ | 241 | /* Put first in list and modify the timer value */ |
361 | t->prev = NULL; | 242 | t->prev = NULL; |
362 | t->next = fast_timer_list; | 243 | t->next = fast_timer_list; |
363 | if (fast_timer_list) | 244 | if (fast_timer_list) |
364 | { | ||
365 | fast_timer_list->prev = t; | 245 | fast_timer_list->prev = t; |
366 | } | ||
367 | fast_timer_list = t; | 246 | fast_timer_list = t; |
368 | #ifdef FAST_TIMER_LOG | 247 | #ifdef FAST_TIMER_LOG |
369 | timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; | 248 | timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; |
@@ -372,10 +251,8 @@ void start_one_shot_timer(struct fast_timer *t, | |||
372 | } else { | 251 | } else { |
373 | /* Put in correct place in list */ | 252 | /* Put in correct place in list */ |
374 | while (tmp->next && | 253 | while (tmp->next && |
375 | timeval_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0) | 254 | fasttime_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0) |
376 | { | ||
377 | tmp = tmp->next; | 255 | tmp = tmp->next; |
378 | } | ||
379 | /* Insert t after tmp */ | 256 | /* Insert t after tmp */ |
380 | t->prev = tmp; | 257 | t->prev = tmp; |
381 | t->next = tmp->next; | 258 | t->next = tmp->next; |
@@ -388,6 +265,7 @@ void start_one_shot_timer(struct fast_timer *t, | |||
388 | 265 | ||
389 | D2(printk("start_one_shot_timer: %d us done\n", delay_us)); | 266 | D2(printk("start_one_shot_timer: %d us done\n", delay_us)); |
390 | 267 | ||
268 | done: | ||
391 | local_irq_restore(flags); | 269 | local_irq_restore(flags); |
392 | } /* start_one_shot_timer */ | 270 | } /* start_one_shot_timer */ |
393 | 271 | ||
@@ -431,19 +309,18 @@ int del_fast_timer(struct fast_timer * t) | |||
431 | /* Timer interrupt handler for trig interrupts */ | 309 | /* Timer interrupt handler for trig interrupts */ |
432 | 310 | ||
433 | static irqreturn_t | 311 | static irqreturn_t |
434 | timer_trig_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 312 | timer_trig_interrupt(int irq, void *dev_id) |
435 | { | 313 | { |
436 | reg_timer_r_masked_intr masked_intr; | 314 | reg_timer_r_masked_intr masked_intr; |
437 | |||
438 | /* Check if the timer interrupt is for us (a trig int) */ | 315 | /* Check if the timer interrupt is for us (a trig int) */ |
439 | masked_intr = REG_RD(timer, regi_timer, r_masked_intr); | 316 | masked_intr = REG_RD(timer, regi_timer0, r_masked_intr); |
440 | if (!masked_intr.trig) | 317 | if (!masked_intr.trig) |
441 | return IRQ_NONE; | 318 | return IRQ_NONE; |
442 | timer_trig_handler(); | 319 | timer_trig_handler(NULL); |
443 | return IRQ_HANDLED; | 320 | return IRQ_HANDLED; |
444 | } | 321 | } |
445 | 322 | ||
446 | static void timer_trig_handler(void) | 323 | static void timer_trig_handler(struct work_struct *work) |
447 | { | 324 | { |
448 | reg_timer_rw_ack_intr ack_intr = { 0 }; | 325 | reg_timer_rw_ack_intr ack_intr = { 0 }; |
449 | reg_timer_rw_intr_mask intr_mask; | 326 | reg_timer_rw_intr_mask intr_mask; |
@@ -451,38 +328,45 @@ static void timer_trig_handler(void) | |||
451 | struct fast_timer *t; | 328 | struct fast_timer *t; |
452 | unsigned long flags; | 329 | unsigned long flags; |
453 | 330 | ||
331 | /* We keep interrupts disabled not only when we modify the | ||
332 | * fast timer list, but any time we hold a reference to a | ||
333 | * timer in the list, since del_fast_timer may be called | ||
334 | * from (another) interrupt context. Thus, the only time | ||
335 | * when interrupts are enabled is when calling the timer | ||
336 | * callback function. | ||
337 | */ | ||
454 | local_irq_save(flags); | 338 | local_irq_save(flags); |
455 | 339 | ||
456 | /* Clear timer trig interrupt */ | 340 | /* Clear timer trig interrupt */ |
457 | intr_mask = REG_RD(timer, regi_timer, rw_intr_mask); | 341 | intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); |
458 | intr_mask.trig = 0; | 342 | intr_mask.trig = 0; |
459 | REG_WR(timer, regi_timer, rw_intr_mask, intr_mask); | 343 | REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); |
460 | 344 | ||
461 | /* First stop timer, then ack interrupt */ | 345 | /* First stop timer, then ack interrupt */ |
462 | /* Stop timer */ | 346 | /* Stop timer */ |
463 | trig_cfg.tmr = regk_timer_off; | 347 | trig_cfg.tmr = regk_timer_off; |
464 | REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg); | 348 | REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); |
465 | 349 | ||
466 | /* Ack interrupt */ | 350 | /* Ack interrupt */ |
467 | ack_intr.trig = 1; | 351 | ack_intr.trig = 1; |
468 | REG_WR(timer, regi_timer, rw_ack_intr, ack_intr); | 352 | REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); |
469 | 353 | ||
470 | fast_timer_running = 0; | 354 | fast_timer_running = 0; |
471 | fast_timer_ints++; | 355 | fast_timer_ints++; |
472 | 356 | ||
473 | local_irq_restore(flags); | 357 | fast_timer_function_type *f; |
358 | unsigned long d; | ||
474 | 359 | ||
475 | t = fast_timer_list; | 360 | t = fast_timer_list; |
476 | while (t) | 361 | while (t) { |
477 | { | 362 | struct fasttime_t tv; |
478 | struct timeval tv; | ||
479 | 363 | ||
480 | /* Has it really expired? */ | 364 | /* Has it really expired? */ |
481 | do_gettimeofday_fast(&tv); | 365 | do_gettimeofday_fast(&tv); |
482 | D1(printk("t: %is %06ius\n", tv.tv_sec, tv.tv_usec)); | 366 | D1(printk(KERN_DEBUG |
367 | "t: %is %06ius\n", tv.tv_jiff, tv.tv_usec)); | ||
483 | 368 | ||
484 | if (timeval_cmp(&t->tv_expires, &tv) <= 0) | 369 | if (fasttime_cmp(&t->tv_expires, &tv) <= 0) { |
485 | { | ||
486 | /* Yes it has expired */ | 370 | /* Yes it has expired */ |
487 | #ifdef FAST_TIMER_LOG | 371 | #ifdef FAST_TIMER_LOG |
488 | timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t; | 372 | timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t; |
@@ -490,84 +374,77 @@ static void timer_trig_handler(void) | |||
490 | fast_timers_expired++; | 374 | fast_timers_expired++; |
491 | 375 | ||
492 | /* Remove this timer before call, since it may reuse the timer */ | 376 | /* Remove this timer before call, since it may reuse the timer */ |
493 | local_irq_save(flags); | ||
494 | if (t->prev) | 377 | if (t->prev) |
495 | { | ||
496 | t->prev->next = t->next; | 378 | t->prev->next = t->next; |
497 | } | ||
498 | else | 379 | else |
499 | { | ||
500 | fast_timer_list = t->next; | 380 | fast_timer_list = t->next; |
501 | } | ||
502 | if (t->next) | 381 | if (t->next) |
503 | { | ||
504 | t->next->prev = t->prev; | 382 | t->next->prev = t->prev; |
505 | } | ||
506 | t->prev = NULL; | 383 | t->prev = NULL; |
507 | t->next = NULL; | 384 | t->next = NULL; |
508 | local_irq_restore(flags); | ||
509 | 385 | ||
510 | if (t->function != NULL) | 386 | /* Save function callback data before enabling |
511 | { | 387 | * interrupts, since the timer may be removed and we |
512 | t->function(t->data); | 388 | * don't know how it was allocated (e.g. ->function |
513 | } | 389 | * and ->data may become overwritten after deletion |
514 | else | 390 | * if the timer was stack-allocated). |
515 | { | 391 | */ |
392 | f = t->function; | ||
393 | d = t->data; | ||
394 | |||
395 | if (f != NULL) { | ||
396 | /* Run the callback function with interrupts | ||
397 | * enabled. */ | ||
398 | local_irq_restore(flags); | ||
399 | f(d); | ||
400 | local_irq_save(flags); | ||
401 | } else | ||
516 | DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints); | 402 | DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints); |
517 | } | 403 | } else { |
518 | } | ||
519 | else | ||
520 | { | ||
521 | /* Timer is to early, let's set it again using the normal routines */ | 404 | /* Timer is to early, let's set it again using the normal routines */ |
522 | D1(printk(".\n")); | 405 | D1(printk(".\n")); |
523 | } | 406 | } |
524 | 407 | ||
525 | local_irq_save(flags); | 408 | t = fast_timer_list; |
526 | if ((t = fast_timer_list) != NULL) | 409 | if (t != NULL) { |
527 | { | ||
528 | /* Start next timer.. */ | 410 | /* Start next timer.. */ |
529 | long us; | 411 | long us = 0; |
530 | struct timeval tv; | 412 | struct fasttime_t tv; |
531 | 413 | ||
532 | do_gettimeofday_fast(&tv); | 414 | do_gettimeofday_fast(&tv); |
533 | us = ((t->tv_expires.tv_sec - tv.tv_sec) * 1000000 + | 415 | |
534 | t->tv_expires.tv_usec - tv.tv_usec); | 416 | /* time_after_eq takes care of wrapping */ |
535 | if (us > 0) | 417 | if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff)) |
536 | { | 418 | us = ((t->tv_expires.tv_jiff - tv.tv_jiff) * |
537 | if (!fast_timer_running) | 419 | 1000000 / HZ + t->tv_expires.tv_usec - |
538 | { | 420 | tv.tv_usec); |
421 | |||
422 | if (us > 0) { | ||
423 | if (!fast_timer_running) { | ||
539 | #ifdef FAST_TIMER_LOG | 424 | #ifdef FAST_TIMER_LOG |
540 | timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; | 425 | timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; |
541 | #endif | 426 | #endif |
542 | start_timer_trig(us); | 427 | start_timer_trig(us); |
543 | } | 428 | } |
544 | local_irq_restore(flags); | ||
545 | break; | 429 | break; |
546 | } | 430 | } else { |
547 | else | ||
548 | { | ||
549 | /* Timer already expired, let's handle it better late than never. | 431 | /* Timer already expired, let's handle it better late than never. |
550 | * The normal loop handles it | 432 | * The normal loop handles it |
551 | */ | 433 | */ |
552 | D1(printk("e! %d\n", us)); | 434 | D1(printk("e! %d\n", us)); |
553 | } | 435 | } |
554 | } | 436 | } |
555 | local_irq_restore(flags); | ||
556 | } | 437 | } |
557 | 438 | ||
558 | if (!t) | 439 | local_irq_restore(flags); |
559 | { | 440 | |
441 | if (!t) | ||
560 | D1(printk("ttrig stop!\n")); | 442 | D1(printk("ttrig stop!\n")); |
561 | } | ||
562 | } | 443 | } |
563 | 444 | ||
564 | static void wake_up_func(unsigned long data) | 445 | static void wake_up_func(unsigned long data) |
565 | { | 446 | { |
566 | #ifdef DECLARE_WAITQUEUE | ||
567 | wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data; | 447 | wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data; |
568 | #else | ||
569 | struct wait_queue **sleep_wait_p = (struct wait_queue **)data; | ||
570 | #endif | ||
571 | wake_up(sleep_wait_p); | 448 | wake_up(sleep_wait_p); |
572 | } | 449 | } |
573 | 450 | ||
@@ -577,28 +454,17 @@ static void wake_up_func(unsigned long data) | |||
577 | void schedule_usleep(unsigned long us) | 454 | void schedule_usleep(unsigned long us) |
578 | { | 455 | { |
579 | struct fast_timer t; | 456 | struct fast_timer t; |
580 | #ifdef DECLARE_WAITQUEUE | ||
581 | wait_queue_head_t sleep_wait; | 457 | wait_queue_head_t sleep_wait; |
582 | init_waitqueue_head(&sleep_wait); | 458 | init_waitqueue_head(&sleep_wait); |
583 | { | ||
584 | DECLARE_WAITQUEUE(wait, current); | ||
585 | #else | ||
586 | struct wait_queue *sleep_wait = NULL; | ||
587 | struct wait_queue wait = { current, NULL }; | ||
588 | #endif | ||
589 | 459 | ||
590 | D1(printk("schedule_usleep(%d)\n", us)); | 460 | D1(printk("schedule_usleep(%d)\n", us)); |
591 | add_wait_queue(&sleep_wait, &wait); | ||
592 | set_current_state(TASK_INTERRUPTIBLE); | ||
593 | start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us, | 461 | start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us, |
594 | "usleep"); | 462 | "usleep"); |
595 | schedule(); | 463 | /* Uninterruptible sleep on the fast timer. (The condition is |
596 | set_current_state(TASK_RUNNING); | 464 | * somewhat redundant since the timer is what wakes us up.) */ |
597 | remove_wait_queue(&sleep_wait, &wait); | 465 | wait_event(sleep_wait, !fast_timer_pending(&t)); |
466 | |||
598 | D1(printk("done schedule_usleep(%d)\n", us)); | 467 | D1(printk("done schedule_usleep(%d)\n", us)); |
599 | #ifdef DECLARE_WAITQUEUE | ||
600 | } | ||
601 | #endif | ||
602 | } | 468 | } |
603 | 469 | ||
604 | #ifdef CONFIG_PROC_FS | 470 | #ifdef CONFIG_PROC_FS |
@@ -618,20 +484,22 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
618 | unsigned long flags; | 484 | unsigned long flags; |
619 | int i = 0; | 485 | int i = 0; |
620 | int num_to_show; | 486 | int num_to_show; |
621 | struct timeval tv; | 487 | struct fasttime_t tv; |
622 | struct fast_timer *t, *nextt; | 488 | struct fast_timer *t, *nextt; |
623 | static char *bigbuf = NULL; | 489 | static char *bigbuf = NULL; |
624 | static unsigned long used; | 490 | static unsigned long used; |
625 | 491 | ||
626 | if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE))) | 492 | if (!bigbuf) { |
627 | { | 493 | bigbuf = vmalloc(BIG_BUF_SIZE); |
628 | used = 0; | 494 | if (!bigbuf) { |
629 | bigbuf[0] = '\0'; | 495 | used = 0; |
630 | return 0; | 496 | if (buf) |
631 | } | 497 | buf[0] = '\0'; |
632 | 498 | return 0; | |
633 | if (!offset || !used) | 499 | } |
634 | { | 500 | } |
501 | |||
502 | if (!offset || !used) { | ||
635 | do_gettimeofday_fast(&tv); | 503 | do_gettimeofday_fast(&tv); |
636 | 504 | ||
637 | used = 0; | 505 | used = 0; |
@@ -648,7 +516,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
648 | used += sprintf(bigbuf + used, "Fast timer running: %s\n", | 516 | used += sprintf(bigbuf + used, "Fast timer running: %s\n", |
649 | fast_timer_running ? "yes" : "no"); | 517 | fast_timer_running ? "yes" : "no"); |
650 | used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n", | 518 | used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n", |
651 | (unsigned long)tv.tv_sec, | 519 | (unsigned long)tv.tv_jiff, |
652 | (unsigned long)tv.tv_usec); | 520 | (unsigned long)tv.tv_usec); |
653 | #ifdef FAST_TIMER_SANITY_CHECKS | 521 | #ifdef FAST_TIMER_SANITY_CHECKS |
654 | used += sprintf(bigbuf + used, "Sanity failed: %i\n", | 522 | used += sprintf(bigbuf + used, "Sanity failed: %i\n", |
@@ -661,10 +529,8 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
661 | int end_i = debug_log_cnt; | 529 | int end_i = debug_log_cnt; |
662 | i = 0; | 530 | i = 0; |
663 | 531 | ||
664 | if (debug_log_cnt_wrapped) | 532 | if (debug_log_cnt_wrapped) |
665 | { | ||
666 | i = debug_log_cnt; | 533 | i = debug_log_cnt; |
667 | } | ||
668 | 534 | ||
669 | while ((i != end_i || (debug_log_cnt_wrapped && !used)) && | 535 | while ((i != end_i || (debug_log_cnt_wrapped && !used)) && |
670 | used+100 < BIG_BUF_SIZE) | 536 | used+100 < BIG_BUF_SIZE) |
@@ -697,9 +563,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
697 | "d: %6li us data: 0x%08lX" | 563 | "d: %6li us data: 0x%08lX" |
698 | "\n", | 564 | "\n", |
699 | t->name, | 565 | t->name, |
700 | (unsigned long)t->tv_set.tv_sec, | 566 | (unsigned long)t->tv_set.tv_jiff, |
701 | (unsigned long)t->tv_set.tv_usec, | 567 | (unsigned long)t->tv_set.tv_usec, |
702 | (unsigned long)t->tv_expires.tv_sec, | 568 | (unsigned long)t->tv_expires.tv_jiff, |
703 | (unsigned long)t->tv_expires.tv_usec, | 569 | (unsigned long)t->tv_expires.tv_usec, |
704 | t->delay_us, | 570 | t->delay_us, |
705 | t->data | 571 | t->data |
@@ -719,9 +585,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
719 | "d: %6li us data: 0x%08lX" | 585 | "d: %6li us data: 0x%08lX" |
720 | "\n", | 586 | "\n", |
721 | t->name, | 587 | t->name, |
722 | (unsigned long)t->tv_set.tv_sec, | 588 | (unsigned long)t->tv_set.tv_jiff, |
723 | (unsigned long)t->tv_set.tv_usec, | 589 | (unsigned long)t->tv_set.tv_usec, |
724 | (unsigned long)t->tv_expires.tv_sec, | 590 | (unsigned long)t->tv_expires.tv_jiff, |
725 | (unsigned long)t->tv_expires.tv_usec, | 591 | (unsigned long)t->tv_expires.tv_usec, |
726 | t->delay_us, | 592 | t->delay_us, |
727 | t->data | 593 | t->data |
@@ -739,9 +605,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
739 | "d: %6li us data: 0x%08lX" | 605 | "d: %6li us data: 0x%08lX" |
740 | "\n", | 606 | "\n", |
741 | t->name, | 607 | t->name, |
742 | (unsigned long)t->tv_set.tv_sec, | 608 | (unsigned long)t->tv_set.tv_jiff, |
743 | (unsigned long)t->tv_set.tv_usec, | 609 | (unsigned long)t->tv_set.tv_usec, |
744 | (unsigned long)t->tv_expires.tv_sec, | 610 | (unsigned long)t->tv_expires.tv_jiff, |
745 | (unsigned long)t->tv_expires.tv_usec, | 611 | (unsigned long)t->tv_expires.tv_usec, |
746 | t->delay_us, | 612 | t->delay_us, |
747 | t->data | 613 | t->data |
@@ -752,26 +618,25 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
752 | 618 | ||
753 | used += sprintf(bigbuf + used, "Active timers:\n"); | 619 | used += sprintf(bigbuf + used, "Active timers:\n"); |
754 | local_irq_save(flags); | 620 | local_irq_save(flags); |
755 | local_irq_save(flags); | ||
756 | t = fast_timer_list; | 621 | t = fast_timer_list; |
757 | while (t != NULL && (used+100 < BIG_BUF_SIZE)) | 622 | while (t != NULL && (used+100 < BIG_BUF_SIZE)) |
758 | { | 623 | { |
759 | nextt = t->next; | 624 | nextt = t->next; |
760 | local_irq_restore(flags); | 625 | local_irq_restore(flags); |
761 | used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu " | 626 | used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu " |
762 | "d: %6li us data: 0x%08lX" | 627 | "d: %6li us data: 0x%08lX" |
763 | /* " func: 0x%08lX" */ | 628 | /* " func: 0x%08lX" */ |
764 | "\n", | 629 | "\n", |
765 | t->name, | 630 | t->name, |
766 | (unsigned long)t->tv_set.tv_sec, | 631 | (unsigned long)t->tv_set.tv_jiff, |
767 | (unsigned long)t->tv_set.tv_usec, | 632 | (unsigned long)t->tv_set.tv_usec, |
768 | (unsigned long)t->tv_expires.tv_sec, | 633 | (unsigned long)t->tv_expires.tv_jiff, |
769 | (unsigned long)t->tv_expires.tv_usec, | 634 | (unsigned long)t->tv_expires.tv_usec, |
770 | t->delay_us, | 635 | t->delay_us, |
771 | t->data | 636 | t->data |
772 | /* , t->function */ | 637 | /* , t->function */ |
773 | ); | 638 | ); |
774 | local_irq_disable(); | 639 | local_irq_save(flags); |
775 | if (t->next != nextt) | 640 | if (t->next != nextt) |
776 | { | 641 | { |
777 | printk("timer removed!\n"); | 642 | printk("timer removed!\n"); |
@@ -800,7 +665,7 @@ static volatile int num_test_timeout = 0; | |||
800 | static struct fast_timer tr[10]; | 665 | static struct fast_timer tr[10]; |
801 | static int exp_num[10]; | 666 | static int exp_num[10]; |
802 | 667 | ||
803 | static struct timeval tv_exp[100]; | 668 | static struct fasttime_t tv_exp[100]; |
804 | 669 | ||
805 | static void test_timeout(unsigned long data) | 670 | static void test_timeout(unsigned long data) |
806 | { | 671 | { |
@@ -838,7 +703,7 @@ static void fast_timer_test(void) | |||
838 | int prev_num; | 703 | int prev_num; |
839 | int j; | 704 | int j; |
840 | 705 | ||
841 | struct timeval tv, tv0, tv1, tv2; | 706 | struct fasttime_t tv, tv0, tv1, tv2; |
842 | 707 | ||
843 | printk("fast_timer_test() start\n"); | 708 | printk("fast_timer_test() start\n"); |
844 | do_gettimeofday_fast(&tv); | 709 | do_gettimeofday_fast(&tv); |
@@ -851,21 +716,22 @@ static void fast_timer_test(void) | |||
851 | { | 716 | { |
852 | do_gettimeofday_fast(&tv_exp[j]); | 717 | do_gettimeofday_fast(&tv_exp[j]); |
853 | } | 718 | } |
854 | printk("fast_timer_test() %is %06i\n", tv.tv_sec, tv.tv_usec); | 719 | printk(KERN_DEBUG "fast_timer_test() %is %06i\n", tv.tv_jiff, tv.tv_usec); |
855 | 720 | ||
856 | for (j = 0; j < 1000; j++) | 721 | for (j = 0; j < 1000; j++) |
857 | { | 722 | { |
858 | printk("%i %i %i %i %i\n",j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]); | 723 | printk(KERN_DEBUG "%i %i %i %i %i\n", |
724 | j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]); | ||
859 | j += 4; | 725 | j += 4; |
860 | } | 726 | } |
861 | for (j = 0; j < 100; j++) | 727 | for (j = 0; j < 100; j++) |
862 | { | 728 | { |
863 | printk("%i.%i %i.%i %i.%i %i.%i %i.%i\n", | 729 | printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n", |
864 | tv_exp[j].tv_sec,tv_exp[j].tv_usec, | 730 | tv_exp[j].tv_jiff, tv_exp[j].tv_usec, |
865 | tv_exp[j+1].tv_sec,tv_exp[j+1].tv_usec, | 731 | tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec, |
866 | tv_exp[j+2].tv_sec,tv_exp[j+2].tv_usec, | 732 | tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec, |
867 | tv_exp[j+3].tv_sec,tv_exp[j+3].tv_usec, | 733 | tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec, |
868 | tv_exp[j+4].tv_sec,tv_exp[j+4].tv_usec); | 734 | tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec); |
869 | j += 4; | 735 | j += 4; |
870 | } | 736 | } |
871 | do_gettimeofday_fast(&tv0); | 737 | do_gettimeofday_fast(&tv0); |
@@ -892,14 +758,15 @@ static void fast_timer_test(void) | |||
892 | while (num_test_timeout < i) | 758 | while (num_test_timeout < i) |
893 | { | 759 | { |
894 | if (num_test_timeout != prev_num) | 760 | if (num_test_timeout != prev_num) |
895 | { | ||
896 | prev_num = num_test_timeout; | 761 | prev_num = num_test_timeout; |
897 | } | ||
898 | } | 762 | } |
899 | do_gettimeofday_fast(&tv2); | 763 | do_gettimeofday_fast(&tv2); |
900 | printk("Timers started %is %06i\n", tv0.tv_sec, tv0.tv_usec); | 764 | printk(KERN_INFO "Timers started %is %06i\n", |
901 | printk("Timers started at %is %06i\n", tv1.tv_sec, tv1.tv_usec); | 765 | tv0.tv_jiff, tv0.tv_usec); |
902 | printk("Timers done %is %06i\n", tv2.tv_sec, tv2.tv_usec); | 766 | printk(KERN_INFO "Timers started at %is %06i\n", |
767 | tv1.tv_jiff, tv1.tv_usec); | ||
768 | printk(KERN_INFO "Timers done %is %06i\n", | ||
769 | tv2.tv_jiff, tv2.tv_usec); | ||
903 | DP(printk("buf0:\n"); | 770 | DP(printk("buf0:\n"); |
904 | printk(buf0); | 771 | printk(buf0); |
905 | printk("buf1:\n"); | 772 | printk("buf1:\n"); |
@@ -921,9 +788,9 @@ static void fast_timer_test(void) | |||
921 | printk("%-10s set: %6is %06ius exp: %6is %06ius " | 788 | printk("%-10s set: %6is %06ius exp: %6is %06ius " |
922 | "data: 0x%08X func: 0x%08X\n", | 789 | "data: 0x%08X func: 0x%08X\n", |
923 | t->name, | 790 | t->name, |
924 | t->tv_set.tv_sec, | 791 | t->tv_set.tv_jiff, |
925 | t->tv_set.tv_usec, | 792 | t->tv_set.tv_usec, |
926 | t->tv_expires.tv_sec, | 793 | t->tv_expires.tv_jiff, |
927 | t->tv_expires.tv_usec, | 794 | t->tv_expires.tv_usec, |
928 | t->data, | 795 | t->data, |
929 | t->function | 796 | t->function |
@@ -931,10 +798,12 @@ static void fast_timer_test(void) | |||
931 | 798 | ||
932 | printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n", | 799 | printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n", |
933 | t->delay_us, | 800 | t->delay_us, |
934 | tv_exp[j].tv_sec, | 801 | tv_exp[j].tv_jiff, |
935 | tv_exp[j].tv_usec, | 802 | tv_exp[j].tv_usec, |
936 | exp_num[j], | 803 | exp_num[j], |
937 | (tv_exp[j].tv_sec - t->tv_expires.tv_sec)*1000000 + tv_exp[j].tv_usec - t->tv_expires.tv_usec); | 804 | (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) * |
805 | 1000000 + tv_exp[j].tv_usec - | ||
806 | t->tv_expires.tv_usec); | ||
938 | } | 807 | } |
939 | proc_fasttimer_read(buf5, NULL, 0, 0, 0); | 808 | proc_fasttimer_read(buf5, NULL, 0, 0, 0); |
940 | printk("buf5 after all done:\n"); | 809 | printk("buf5 after all done:\n"); |
@@ -944,7 +813,7 @@ static void fast_timer_test(void) | |||
944 | #endif | 813 | #endif |
945 | 814 | ||
946 | 815 | ||
947 | void fast_timer_init(void) | 816 | int fast_timer_init(void) |
948 | { | 817 | { |
949 | /* For some reason, request_irq() hangs when called froom time_init() */ | 818 | /* For some reason, request_irq() hangs when called froom time_init() */ |
950 | if (!fast_timer_is_init) | 819 | if (!fast_timer_is_init) |
@@ -952,18 +821,20 @@ void fast_timer_init(void) | |||
952 | printk("fast_timer_init()\n"); | 821 | printk("fast_timer_init()\n"); |
953 | 822 | ||
954 | #ifdef CONFIG_PROC_FS | 823 | #ifdef CONFIG_PROC_FS |
955 | if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 ))) | 824 | fasttimer_proc_entry = create_proc_entry("fasttimer", 0, 0); |
956 | fasttimer_proc_entry->read_proc = proc_fasttimer_read; | 825 | if (fasttimer_proc_entry) |
826 | fasttimer_proc_entry->read_proc = proc_fasttimer_read; | ||
957 | #endif /* PROC_FS */ | 827 | #endif /* PROC_FS */ |
958 | if(request_irq(TIMER_INTR_VECT, timer_trig_interrupt, IRQF_DISABLED, | 828 | if (request_irq(TIMER0_INTR_VECT, timer_trig_interrupt, |
959 | "fast timer int", NULL)) | 829 | IRQF_SHARED | IRQF_DISABLED, |
960 | { | 830 | "fast timer int", &fast_timer_list)) |
961 | printk("err: timer1 irq\n"); | 831 | printk(KERN_ERR "err: fasttimer irq\n"); |
962 | } | ||
963 | fast_timer_is_init = 1; | 832 | fast_timer_is_init = 1; |
964 | #ifdef FAST_TIMER_TEST | 833 | #ifdef FAST_TIMER_TEST |
965 | printk("do test\n"); | 834 | printk("do test\n"); |
966 | fast_timer_test(); | 835 | fast_timer_test(); |
967 | #endif | 836 | #endif |
968 | } | 837 | } |
838 | return 0; | ||
969 | } | 839 | } |
840 | __initcall(fast_timer_init); | ||