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