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