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