aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris
diff options
context:
space:
mode:
authorJesper Nilsson <jesper.nilsson@axis.com>2007-11-30 11:46:11 -0500
committerJesper Nilsson <jesper.nilsson@axis.com>2008-02-08 05:06:27 -0500
commitec87ee20c28708bbd22f71f429d2e21c965c44e4 (patch)
tree8a9fd532909f001bfc9c010ae5b5c05c16b74b2d /arch/cris
parente867cefbaaac23644414cfe562b4fee7dc604f2e (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.c519
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 57static unsigned int fast_timer_running;
159 58static unsigned int fast_timers_added;
160static int fast_timer_running = 0; 59static unsigned int fast_timers_started;
161static int fast_timers_added = 0; 60static unsigned int fast_timers_expired;
162static int fast_timers_started = 0; 61static unsigned int fast_timers_deleted;
163static int fast_timers_expired = 0; 62static unsigned int fast_timer_is_init;
164static int fast_timers_deleted = 0; 63static unsigned int fast_timer_ints;
165static int fast_timer_is_init = 0;
166static int fast_timer_ints = 0;
167 64
168struct fast_timer *fast_timer_list = NULL; 65struct 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
172static const char * debug_log_string[DEBUG_LOG_MAX]; 69static const char * debug_log_string[DEBUG_LOG_MAX];
173static unsigned long debug_log_value[DEBUG_LOG_MAX]; 70static unsigned long debug_log_value[DEBUG_LOG_MAX];
174static int debug_log_cnt = 0; 71static unsigned int debug_log_cnt;
175static int debug_log_cnt_wrapped = 0; 72static 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];
202int timer_div_settings[NUM_TIMER_STATS]; 99int timer_div_settings[NUM_TIMER_STATS];
203int timer_delay_settings[NUM_TIMER_STATS]; 100int timer_delay_settings[NUM_TIMER_STATS];
204 101
102struct work_struct fast_work;
205 103
206static void 104static void
207timer_trig_handler(void); 105timer_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 */
212void __INLINE__ do_gettimeofday_fast(struct timeval *tv) 110inline 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
229int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1) 116inline 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 */
251void __INLINE__ start_timer_trig(unsigned long delay_us) 133inline 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
268done:
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
433static irqreturn_t 311static irqreturn_t
434timer_trig_interrupt(int irq, void *dev_id, struct pt_regs *regs) 312timer_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
446static void timer_trig_handler(void) 323static 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
564static void wake_up_func(unsigned long data) 445static 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)
577void schedule_usleep(unsigned long us) 454void 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;
800static struct fast_timer tr[10]; 665static struct fast_timer tr[10];
801static int exp_num[10]; 666static int exp_num[10];
802 667
803static struct timeval tv_exp[100]; 668static struct fasttime_t tv_exp[100];
804 669
805static void test_timeout(unsigned long data) 670static 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
947void fast_timer_init(void) 816int 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);