Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/cris/arch-v32/kernel/fasttimer.c
15125 views
1
/*
2
* linux/arch/cris/kernel/fasttimer.c
3
*
4
* Fast timers for ETRAX FS
5
*
6
* Copyright (C) 2000-2006 Axis Communications AB, Lund, Sweden
7
*/
8
9
#include <linux/errno.h>
10
#include <linux/sched.h>
11
#include <linux/kernel.h>
12
#include <linux/param.h>
13
#include <linux/string.h>
14
#include <linux/vmalloc.h>
15
#include <linux/interrupt.h>
16
#include <linux/time.h>
17
#include <linux/delay.h>
18
19
#include <asm/irq.h>
20
#include <asm/system.h>
21
22
#include <hwregs/reg_map.h>
23
#include <hwregs/reg_rdwr.h>
24
#include <hwregs/timer_defs.h>
25
#include <asm/fasttimer.h>
26
#include <linux/proc_fs.h>
27
28
/*
29
* timer0 is running at 100MHz and generating jiffies timer ticks
30
* at 100 or 1000 HZ.
31
* fasttimer gives an API that gives timers that expire "between" the jiffies
32
* giving microsecond resolution (10 ns).
33
* fasttimer uses reg_timer_rw_trig register to get interrupt when
34
* r_time reaches a certain value.
35
*/
36
37
38
#define DEBUG_LOG_INCLUDED
39
#define FAST_TIMER_LOG
40
/* #define FAST_TIMER_TEST */
41
42
#define FAST_TIMER_SANITY_CHECKS
43
44
#ifdef FAST_TIMER_SANITY_CHECKS
45
static int sanity_failed;
46
#endif
47
48
#define D1(x)
49
#define D2(x)
50
#define DP(x)
51
52
static unsigned int fast_timer_running;
53
static unsigned int fast_timers_added;
54
static unsigned int fast_timers_started;
55
static unsigned int fast_timers_expired;
56
static unsigned int fast_timers_deleted;
57
static unsigned int fast_timer_is_init;
58
static unsigned int fast_timer_ints;
59
60
struct fast_timer *fast_timer_list = NULL;
61
62
#ifdef DEBUG_LOG_INCLUDED
63
#define DEBUG_LOG_MAX 128
64
static const char * debug_log_string[DEBUG_LOG_MAX];
65
static unsigned long debug_log_value[DEBUG_LOG_MAX];
66
static unsigned int debug_log_cnt;
67
static unsigned int debug_log_cnt_wrapped;
68
69
#define DEBUG_LOG(string, value) \
70
{ \
71
unsigned long log_flags; \
72
local_irq_save(log_flags); \
73
debug_log_string[debug_log_cnt] = (string); \
74
debug_log_value[debug_log_cnt] = (unsigned long)(value); \
75
if (++debug_log_cnt >= DEBUG_LOG_MAX) \
76
{ \
77
debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \
78
debug_log_cnt_wrapped = 1; \
79
} \
80
local_irq_restore(log_flags); \
81
}
82
#else
83
#define DEBUG_LOG(string, value)
84
#endif
85
86
87
#define NUM_TIMER_STATS 16
88
#ifdef FAST_TIMER_LOG
89
struct fast_timer timer_added_log[NUM_TIMER_STATS];
90
struct fast_timer timer_started_log[NUM_TIMER_STATS];
91
struct fast_timer timer_expired_log[NUM_TIMER_STATS];
92
#endif
93
94
int timer_div_settings[NUM_TIMER_STATS];
95
int timer_delay_settings[NUM_TIMER_STATS];
96
97
struct work_struct fast_work;
98
99
static void
100
timer_trig_handler(struct work_struct *work);
101
102
103
104
/* Not true gettimeofday, only checks the jiffies (uptime) + useconds */
105
inline void do_gettimeofday_fast(struct fasttime_t *tv)
106
{
107
tv->tv_jiff = jiffies;
108
tv->tv_usec = GET_JIFFIES_USEC();
109
}
110
111
inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1)
112
{
113
/* Compare jiffies. Takes care of wrapping */
114
if (time_before(t0->tv_jiff, t1->tv_jiff))
115
return -1;
116
else if (time_after(t0->tv_jiff, t1->tv_jiff))
117
return 1;
118
119
/* Compare us */
120
if (t0->tv_usec < t1->tv_usec)
121
return -1;
122
else if (t0->tv_usec > t1->tv_usec)
123
return 1;
124
return 0;
125
}
126
127
/* Called with ints off */
128
inline void start_timer_trig(unsigned long delay_us)
129
{
130
reg_timer_rw_ack_intr ack_intr = { 0 };
131
reg_timer_rw_intr_mask intr_mask;
132
reg_timer_rw_trig trig;
133
reg_timer_rw_trig_cfg trig_cfg = { 0 };
134
reg_timer_r_time r_time0;
135
reg_timer_r_time r_time1;
136
unsigned char trig_wrap;
137
unsigned char time_wrap;
138
139
r_time0 = REG_RD(timer, regi_timer0, r_time);
140
141
D1(printk("start_timer_trig : %d us freq: %i div: %i\n",
142
delay_us, freq_index, div));
143
/* Clear trig irq */
144
intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask);
145
intr_mask.trig = 0;
146
REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask);
147
148
/* Set timer values and check if trigger wraps. */
149
/* r_time is 100MHz (10 ns resolution) */
150
trig_wrap = (trig = r_time0 + delay_us*(1000/10)) < r_time0;
151
152
timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = trig;
153
timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us;
154
155
/* Ack interrupt */
156
ack_intr.trig = 1;
157
REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr);
158
159
/* Start timer */
160
REG_WR(timer, regi_timer0, rw_trig, trig);
161
trig_cfg.tmr = regk_timer_time;
162
REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg);
163
164
/* Check if we have already passed the trig time */
165
r_time1 = REG_RD(timer, regi_timer0, r_time);
166
time_wrap = r_time1 < r_time0;
167
168
if ((trig_wrap && !time_wrap) || (r_time1 < trig)) {
169
/* No, Enable trig irq */
170
intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask);
171
intr_mask.trig = 1;
172
REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask);
173
fast_timers_started++;
174
fast_timer_running = 1;
175
} else {
176
/* We have passed the time, disable trig point, ack intr */
177
trig_cfg.tmr = regk_timer_off;
178
REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg);
179
REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr);
180
/* call the int routine */
181
INIT_WORK(&fast_work, timer_trig_handler);
182
schedule_work(&fast_work);
183
}
184
185
}
186
187
/* In version 1.4 this function takes 27 - 50 us */
188
void start_one_shot_timer(struct fast_timer *t,
189
fast_timer_function_type *function,
190
unsigned long data,
191
unsigned long delay_us,
192
const char *name)
193
{
194
unsigned long flags;
195
struct fast_timer *tmp;
196
197
D1(printk("sft %s %d us\n", name, delay_us));
198
199
local_irq_save(flags);
200
201
do_gettimeofday_fast(&t->tv_set);
202
tmp = fast_timer_list;
203
204
#ifdef FAST_TIMER_SANITY_CHECKS
205
/* Check so this is not in the list already... */
206
while (tmp != NULL) {
207
if (tmp == t) {
208
printk(KERN_DEBUG
209
"timer name: %s data: 0x%08lX already "
210
"in list!\n", name, data);
211
sanity_failed++;
212
goto done;
213
} else
214
tmp = tmp->next;
215
}
216
tmp = fast_timer_list;
217
#endif
218
219
t->delay_us = delay_us;
220
t->function = function;
221
t->data = data;
222
t->name = name;
223
224
t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
225
t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ;
226
if (t->tv_expires.tv_usec > 1000000) {
227
t->tv_expires.tv_usec -= 1000000;
228
t->tv_expires.tv_jiff += HZ;
229
}
230
#ifdef FAST_TIMER_LOG
231
timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
232
#endif
233
fast_timers_added++;
234
235
/* Check if this should timeout before anything else */
236
if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) {
237
/* Put first in list and modify the timer value */
238
t->prev = NULL;
239
t->next = fast_timer_list;
240
if (fast_timer_list)
241
fast_timer_list->prev = t;
242
fast_timer_list = t;
243
#ifdef FAST_TIMER_LOG
244
timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
245
#endif
246
start_timer_trig(delay_us);
247
} else {
248
/* Put in correct place in list */
249
while (tmp->next &&
250
fasttime_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
251
tmp = tmp->next;
252
/* Insert t after tmp */
253
t->prev = tmp;
254
t->next = tmp->next;
255
if (tmp->next)
256
{
257
tmp->next->prev = t;
258
}
259
tmp->next = t;
260
}
261
262
D2(printk("start_one_shot_timer: %d us done\n", delay_us));
263
264
done:
265
local_irq_restore(flags);
266
} /* start_one_shot_timer */
267
268
static inline int fast_timer_pending (const struct fast_timer * t)
269
{
270
return (t->next != NULL) || (t->prev != NULL) || (t == fast_timer_list);
271
}
272
273
static inline int detach_fast_timer (struct fast_timer *t)
274
{
275
struct fast_timer *next, *prev;
276
if (!fast_timer_pending(t))
277
return 0;
278
next = t->next;
279
prev = t->prev;
280
if (next)
281
next->prev = prev;
282
if (prev)
283
prev->next = next;
284
else
285
fast_timer_list = next;
286
fast_timers_deleted++;
287
return 1;
288
}
289
290
int del_fast_timer(struct fast_timer * t)
291
{
292
unsigned long flags;
293
int ret;
294
295
local_irq_save(flags);
296
ret = detach_fast_timer(t);
297
t->next = t->prev = NULL;
298
local_irq_restore(flags);
299
return ret;
300
} /* del_fast_timer */
301
302
303
/* Interrupt routines or functions called in interrupt context */
304
305
/* Timer interrupt handler for trig interrupts */
306
307
static irqreturn_t
308
timer_trig_interrupt(int irq, void *dev_id)
309
{
310
reg_timer_r_masked_intr masked_intr;
311
/* Check if the timer interrupt is for us (a trig int) */
312
masked_intr = REG_RD(timer, regi_timer0, r_masked_intr);
313
if (!masked_intr.trig)
314
return IRQ_NONE;
315
timer_trig_handler(NULL);
316
return IRQ_HANDLED;
317
}
318
319
static void timer_trig_handler(struct work_struct *work)
320
{
321
reg_timer_rw_ack_intr ack_intr = { 0 };
322
reg_timer_rw_intr_mask intr_mask;
323
reg_timer_rw_trig_cfg trig_cfg = { 0 };
324
struct fast_timer *t;
325
unsigned long flags;
326
327
/* We keep interrupts disabled not only when we modify the
328
* fast timer list, but any time we hold a reference to a
329
* timer in the list, since del_fast_timer may be called
330
* from (another) interrupt context. Thus, the only time
331
* when interrupts are enabled is when calling the timer
332
* callback function.
333
*/
334
local_irq_save(flags);
335
336
/* Clear timer trig interrupt */
337
intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask);
338
intr_mask.trig = 0;
339
REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask);
340
341
/* First stop timer, then ack interrupt */
342
/* Stop timer */
343
trig_cfg.tmr = regk_timer_off;
344
REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg);
345
346
/* Ack interrupt */
347
ack_intr.trig = 1;
348
REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr);
349
350
fast_timer_running = 0;
351
fast_timer_ints++;
352
353
fast_timer_function_type *f;
354
unsigned long d;
355
356
t = fast_timer_list;
357
while (t) {
358
struct fasttime_t tv;
359
360
/* Has it really expired? */
361
do_gettimeofday_fast(&tv);
362
D1(printk(KERN_DEBUG
363
"t: %is %06ius\n", tv.tv_jiff, tv.tv_usec));
364
365
if (fasttime_cmp(&t->tv_expires, &tv) <= 0) {
366
/* Yes it has expired */
367
#ifdef FAST_TIMER_LOG
368
timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
369
#endif
370
fast_timers_expired++;
371
372
/* Remove this timer before call, since it may reuse the timer */
373
if (t->prev)
374
t->prev->next = t->next;
375
else
376
fast_timer_list = t->next;
377
if (t->next)
378
t->next->prev = t->prev;
379
t->prev = NULL;
380
t->next = NULL;
381
382
/* Save function callback data before enabling
383
* interrupts, since the timer may be removed and we
384
* don't know how it was allocated (e.g. ->function
385
* and ->data may become overwritten after deletion
386
* if the timer was stack-allocated).
387
*/
388
f = t->function;
389
d = t->data;
390
391
if (f != NULL) {
392
/* Run the callback function with interrupts
393
* enabled. */
394
local_irq_restore(flags);
395
f(d);
396
local_irq_save(flags);
397
} else
398
DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints);
399
} else {
400
/* Timer is to early, let's set it again using the normal routines */
401
D1(printk(".\n"));
402
}
403
404
t = fast_timer_list;
405
if (t != NULL) {
406
/* Start next timer.. */
407
long us = 0;
408
struct fasttime_t tv;
409
410
do_gettimeofday_fast(&tv);
411
412
/* time_after_eq takes care of wrapping */
413
if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
414
us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
415
1000000 / HZ + t->tv_expires.tv_usec -
416
tv.tv_usec);
417
418
if (us > 0) {
419
if (!fast_timer_running) {
420
#ifdef FAST_TIMER_LOG
421
timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
422
#endif
423
start_timer_trig(us);
424
}
425
break;
426
} else {
427
/* Timer already expired, let's handle it better late than never.
428
* The normal loop handles it
429
*/
430
D1(printk("e! %d\n", us));
431
}
432
}
433
}
434
435
local_irq_restore(flags);
436
437
if (!t)
438
D1(printk("ttrig stop!\n"));
439
}
440
441
static void wake_up_func(unsigned long data)
442
{
443
wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data;
444
wake_up(sleep_wait_p);
445
}
446
447
448
/* Useful API */
449
450
void schedule_usleep(unsigned long us)
451
{
452
struct fast_timer t;
453
wait_queue_head_t sleep_wait;
454
init_waitqueue_head(&sleep_wait);
455
456
D1(printk("schedule_usleep(%d)\n", us));
457
start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us,
458
"usleep");
459
/* Uninterruptible sleep on the fast timer. (The condition is
460
* somewhat redundant since the timer is what wakes us up.) */
461
wait_event(sleep_wait, !fast_timer_pending(&t));
462
463
D1(printk("done schedule_usleep(%d)\n", us));
464
}
465
466
#ifdef CONFIG_PROC_FS
467
static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
468
,int *eof, void *data_unused);
469
static struct proc_dir_entry *fasttimer_proc_entry;
470
#endif /* CONFIG_PROC_FS */
471
472
#ifdef CONFIG_PROC_FS
473
474
/* This value is very much based on testing */
475
#define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300)
476
477
static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
478
,int *eof, void *data_unused)
479
{
480
unsigned long flags;
481
int i = 0;
482
int num_to_show;
483
struct fasttime_t tv;
484
struct fast_timer *t, *nextt;
485
static char *bigbuf = NULL;
486
static unsigned long used;
487
488
if (!bigbuf) {
489
bigbuf = vmalloc(BIG_BUF_SIZE);
490
if (!bigbuf) {
491
used = 0;
492
if (buf)
493
buf[0] = '\0';
494
return 0;
495
}
496
}
497
498
if (!offset || !used) {
499
do_gettimeofday_fast(&tv);
500
501
used = 0;
502
used += sprintf(bigbuf + used, "Fast timers added: %i\n",
503
fast_timers_added);
504
used += sprintf(bigbuf + used, "Fast timers started: %i\n",
505
fast_timers_started);
506
used += sprintf(bigbuf + used, "Fast timer interrupts: %i\n",
507
fast_timer_ints);
508
used += sprintf(bigbuf + used, "Fast timers expired: %i\n",
509
fast_timers_expired);
510
used += sprintf(bigbuf + used, "Fast timers deleted: %i\n",
511
fast_timers_deleted);
512
used += sprintf(bigbuf + used, "Fast timer running: %s\n",
513
fast_timer_running ? "yes" : "no");
514
used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n",
515
(unsigned long)tv.tv_jiff,
516
(unsigned long)tv.tv_usec);
517
#ifdef FAST_TIMER_SANITY_CHECKS
518
used += sprintf(bigbuf + used, "Sanity failed: %i\n",
519
sanity_failed);
520
#endif
521
used += sprintf(bigbuf + used, "\n");
522
523
#ifdef DEBUG_LOG_INCLUDED
524
{
525
int end_i = debug_log_cnt;
526
i = 0;
527
528
if (debug_log_cnt_wrapped)
529
i = debug_log_cnt;
530
531
while ((i != end_i || (debug_log_cnt_wrapped && !used)) &&
532
used+100 < BIG_BUF_SIZE)
533
{
534
used += sprintf(bigbuf + used, debug_log_string[i],
535
debug_log_value[i]);
536
i = (i+1) % DEBUG_LOG_MAX;
537
}
538
}
539
used += sprintf(bigbuf + used, "\n");
540
#endif
541
542
num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
543
NUM_TIMER_STATS);
544
used += sprintf(bigbuf + used, "Timers started: %i\n", fast_timers_started);
545
for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE) ; i++)
546
{
547
int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;
548
549
#if 1 //ndef FAST_TIMER_LOG
550
used += sprintf(bigbuf + used, "div: %i delay: %i"
551
"\n",
552
timer_div_settings[cur],
553
timer_delay_settings[cur]
554
);
555
#endif
556
#ifdef FAST_TIMER_LOG
557
t = &timer_started_log[cur];
558
used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
559
"d: %6li us data: 0x%08lX"
560
"\n",
561
t->name,
562
(unsigned long)t->tv_set.tv_jiff,
563
(unsigned long)t->tv_set.tv_usec,
564
(unsigned long)t->tv_expires.tv_jiff,
565
(unsigned long)t->tv_expires.tv_usec,
566
t->delay_us,
567
t->data
568
);
569
#endif
570
}
571
used += sprintf(bigbuf + used, "\n");
572
573
#ifdef FAST_TIMER_LOG
574
num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
575
NUM_TIMER_STATS);
576
used += sprintf(bigbuf + used, "Timers added: %i\n", fast_timers_added);
577
for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
578
{
579
t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
580
used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
581
"d: %6li us data: 0x%08lX"
582
"\n",
583
t->name,
584
(unsigned long)t->tv_set.tv_jiff,
585
(unsigned long)t->tv_set.tv_usec,
586
(unsigned long)t->tv_expires.tv_jiff,
587
(unsigned long)t->tv_expires.tv_usec,
588
t->delay_us,
589
t->data
590
);
591
}
592
used += sprintf(bigbuf + used, "\n");
593
594
num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
595
NUM_TIMER_STATS);
596
used += sprintf(bigbuf + used, "Timers expired: %i\n", fast_timers_expired);
597
for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
598
{
599
t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
600
used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
601
"d: %6li us data: 0x%08lX"
602
"\n",
603
t->name,
604
(unsigned long)t->tv_set.tv_jiff,
605
(unsigned long)t->tv_set.tv_usec,
606
(unsigned long)t->tv_expires.tv_jiff,
607
(unsigned long)t->tv_expires.tv_usec,
608
t->delay_us,
609
t->data
610
);
611
}
612
used += sprintf(bigbuf + used, "\n");
613
#endif
614
615
used += sprintf(bigbuf + used, "Active timers:\n");
616
local_irq_save(flags);
617
t = fast_timer_list;
618
while (t != NULL && (used+100 < BIG_BUF_SIZE))
619
{
620
nextt = t->next;
621
local_irq_restore(flags);
622
used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
623
"d: %6li us data: 0x%08lX"
624
/* " func: 0x%08lX" */
625
"\n",
626
t->name,
627
(unsigned long)t->tv_set.tv_jiff,
628
(unsigned long)t->tv_set.tv_usec,
629
(unsigned long)t->tv_expires.tv_jiff,
630
(unsigned long)t->tv_expires.tv_usec,
631
t->delay_us,
632
t->data
633
/* , t->function */
634
);
635
local_irq_save(flags);
636
if (t->next != nextt)
637
{
638
printk("timer removed!\n");
639
}
640
t = nextt;
641
}
642
local_irq_restore(flags);
643
}
644
645
if (used - offset < len)
646
{
647
len = used - offset;
648
}
649
650
memcpy(buf, bigbuf + offset, len);
651
*start = buf;
652
*eof = 1;
653
654
return len;
655
}
656
#endif /* PROC_FS */
657
658
#ifdef FAST_TIMER_TEST
659
static volatile unsigned long i = 0;
660
static volatile int num_test_timeout = 0;
661
static struct fast_timer tr[10];
662
static int exp_num[10];
663
664
static struct fasttime_t tv_exp[100];
665
666
static void test_timeout(unsigned long data)
667
{
668
do_gettimeofday_fast(&tv_exp[data]);
669
exp_num[data] = num_test_timeout;
670
671
num_test_timeout++;
672
}
673
674
static void test_timeout1(unsigned long data)
675
{
676
do_gettimeofday_fast(&tv_exp[data]);
677
exp_num[data] = num_test_timeout;
678
if (data < 7)
679
{
680
start_one_shot_timer(&tr[i], test_timeout1, i, 1000, "timeout1");
681
i++;
682
}
683
num_test_timeout++;
684
}
685
686
DP(
687
static char buf0[2000];
688
static char buf1[2000];
689
static char buf2[2000];
690
static char buf3[2000];
691
static char buf4[2000];
692
);
693
694
static char buf5[6000];
695
static int j_u[1000];
696
697
static void fast_timer_test(void)
698
{
699
int prev_num;
700
int j;
701
702
struct fasttime_t tv, tv0, tv1, tv2;
703
704
printk("fast_timer_test() start\n");
705
do_gettimeofday_fast(&tv);
706
707
for (j = 0; j < 1000; j++)
708
{
709
j_u[j] = GET_JIFFIES_USEC();
710
}
711
for (j = 0; j < 100; j++)
712
{
713
do_gettimeofday_fast(&tv_exp[j]);
714
}
715
printk(KERN_DEBUG "fast_timer_test() %is %06i\n", tv.tv_jiff, tv.tv_usec);
716
717
for (j = 0; j < 1000; j++)
718
{
719
printk(KERN_DEBUG "%i %i %i %i %i\n",
720
j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]);
721
j += 4;
722
}
723
for (j = 0; j < 100; j++)
724
{
725
printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n",
726
tv_exp[j].tv_jiff, tv_exp[j].tv_usec,
727
tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec,
728
tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec,
729
tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec,
730
tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec);
731
j += 4;
732
}
733
do_gettimeofday_fast(&tv0);
734
start_one_shot_timer(&tr[i], test_timeout, i, 50000, "test0");
735
DP(proc_fasttimer_read(buf0, NULL, 0, 0, 0));
736
i++;
737
start_one_shot_timer(&tr[i], test_timeout, i, 70000, "test1");
738
DP(proc_fasttimer_read(buf1, NULL, 0, 0, 0));
739
i++;
740
start_one_shot_timer(&tr[i], test_timeout, i, 40000, "test2");
741
DP(proc_fasttimer_read(buf2, NULL, 0, 0, 0));
742
i++;
743
start_one_shot_timer(&tr[i], test_timeout, i, 60000, "test3");
744
DP(proc_fasttimer_read(buf3, NULL, 0, 0, 0));
745
i++;
746
start_one_shot_timer(&tr[i], test_timeout1, i, 55000, "test4xx");
747
DP(proc_fasttimer_read(buf4, NULL, 0, 0, 0));
748
i++;
749
do_gettimeofday_fast(&tv1);
750
751
proc_fasttimer_read(buf5, NULL, 0, 0, 0);
752
753
prev_num = num_test_timeout;
754
while (num_test_timeout < i)
755
{
756
if (num_test_timeout != prev_num)
757
prev_num = num_test_timeout;
758
}
759
do_gettimeofday_fast(&tv2);
760
printk(KERN_INFO "Timers started %is %06i\n",
761
tv0.tv_jiff, tv0.tv_usec);
762
printk(KERN_INFO "Timers started at %is %06i\n",
763
tv1.tv_jiff, tv1.tv_usec);
764
printk(KERN_INFO "Timers done %is %06i\n",
765
tv2.tv_jiff, tv2.tv_usec);
766
DP(printk("buf0:\n");
767
printk(buf0);
768
printk("buf1:\n");
769
printk(buf1);
770
printk("buf2:\n");
771
printk(buf2);
772
printk("buf3:\n");
773
printk(buf3);
774
printk("buf4:\n");
775
printk(buf4);
776
);
777
printk("buf5:\n");
778
printk(buf5);
779
780
printk("timers set:\n");
781
for(j = 0; j<i; j++)
782
{
783
struct fast_timer *t = &tr[j];
784
printk("%-10s set: %6is %06ius exp: %6is %06ius "
785
"data: 0x%08X func: 0x%08X\n",
786
t->name,
787
t->tv_set.tv_jiff,
788
t->tv_set.tv_usec,
789
t->tv_expires.tv_jiff,
790
t->tv_expires.tv_usec,
791
t->data,
792
t->function
793
);
794
795
printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n",
796
t->delay_us,
797
tv_exp[j].tv_jiff,
798
tv_exp[j].tv_usec,
799
exp_num[j],
800
(tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) *
801
1000000 + tv_exp[j].tv_usec -
802
t->tv_expires.tv_usec);
803
}
804
proc_fasttimer_read(buf5, NULL, 0, 0, 0);
805
printk("buf5 after all done:\n");
806
printk(buf5);
807
printk("fast_timer_test() done\n");
808
}
809
#endif
810
811
812
int fast_timer_init(void)
813
{
814
/* For some reason, request_irq() hangs when called froom time_init() */
815
if (!fast_timer_is_init)
816
{
817
printk("fast_timer_init()\n");
818
819
#ifdef CONFIG_PROC_FS
820
fasttimer_proc_entry = create_proc_entry("fasttimer", 0, 0);
821
if (fasttimer_proc_entry)
822
fasttimer_proc_entry->read_proc = proc_fasttimer_read;
823
#endif /* PROC_FS */
824
if (request_irq(TIMER0_INTR_VECT, timer_trig_interrupt,
825
IRQF_SHARED | IRQF_DISABLED,
826
"fast timer int", &fast_timer_list))
827
printk(KERN_ERR "err: fasttimer irq\n");
828
fast_timer_is_init = 1;
829
#ifdef FAST_TIMER_TEST
830
printk("do test\n");
831
fast_timer_test();
832
#endif
833
}
834
return 0;
835
}
836
__initcall(fast_timer_init);
837
838