static void timer_trig_handler(struct work_struct *work)
{
	reg_timer_rw_ack_intr ack_intr = { 0 };
	reg_timer_rw_intr_mask intr_mask;
	reg_timer_rw_trig_cfg trig_cfg = { 0 };
	struct fast_timer *t;
	fast_timer_function_type *f;
	unsigned long d;
	unsigned long flags;

	/* We keep interrupts disabled not only when we modify the
	 * fast timer list, but any time we hold a reference to a
	 * timer in the list, since del_fast_timer may be called
	 * from (another) interrupt context.  Thus, the only time
	 * when interrupts are enabled is when calling the timer
	 * callback function.
	 */
  local_irq_save(flags);

  /* Clear timer trig interrupt */
	intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask);
  intr_mask.trig = 0;
  REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask);

  /* First stop timer, then ack interrupt */
  /* Stop timer */
  trig_cfg.tmr = regk_timer_off;
	REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg);

  /* Ack interrupt */
  ack_intr.trig = 1;
	REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr);

  fast_timer_running = 0;
  fast_timer_ints++;

  t = fast_timer_list;
	while (t) {
		struct fasttime_t tv;

    /* Has it really expired? */
    do_gettimeofday_fast(&tv);
		D1(printk(KERN_DEBUG
			"t: %is %06ius\n", tv.tv_jiff, tv.tv_usec));

		if (fasttime_cmp(&t->tv_expires, &tv) <= 0) {
      /* Yes it has expired */
#ifdef FAST_TIMER_LOG
      timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
#endif
      fast_timers_expired++;

      /* Remove this timer before call, since it may reuse the timer */
      if (t->prev)
        t->prev->next = t->next;
      else
        fast_timer_list = t->next;
      if (t->next)
        t->next->prev = t->prev;
      t->prev = NULL;
      t->next = NULL;

			/* Save function callback data before enabling
			 * interrupts, since the timer may be removed and we
			 * don't know how it was allocated (e.g. ->function
			 * and ->data may become overwritten after deletion
			 * if the timer was stack-allocated).
			 */
			f = t->function;
			d = t->data;

			if (f != NULL) {
				/* Run the callback function with interrupts
				 * enabled. */
				local_irq_restore(flags);
				f(d);
				local_irq_save(flags);
			} else
        DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints);
		} else {
      /* Timer is to early, let's set it again using the normal routines */
      D1(printk(".\n"));
    }

		t = fast_timer_list;
		if (t != NULL) {
      /* Start next timer.. */
			long us = 0;
			struct fasttime_t tv;

      do_gettimeofday_fast(&tv);

			/* time_after_eq takes care of wrapping */
			if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
				us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
					1000000 / HZ + t->tv_expires.tv_usec -
					tv.tv_usec);

			if (us > 0) {
				if (!fast_timer_running) {
#ifdef FAST_TIMER_LOG
          timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
          start_timer_trig(us);
        }
        break;
			} else {
        /* Timer already expired, let's handle it better late than never.
         * The normal loop handles it
         */
        D1(printk("e! %d\n", us));
      }
    }
  }

	local_irq_restore(flags);

	if (!t)
    D1(printk("ttrig stop!\n"));
}
/* In version 1.4 this function takes 27 - 50 us */
void start_one_shot_timer(struct fast_timer *t,
                          fast_timer_function_type *function,
                          unsigned long data,
                          unsigned long delay_us,
                          const char *name)
{
  unsigned long flags;
  struct fast_timer *tmp;

  D1(printk("sft %s %d us\n", name, delay_us));

  local_irq_save(flags);

  do_gettimeofday_fast(&t->tv_set);
  tmp = fast_timer_list;

#ifdef FAST_TIMER_SANITY_CHECKS
	/* Check so this is not in the list already... */
	while (tmp != NULL) {
		if (tmp == t) {
			printk(KERN_DEBUG
				"timer name: %s data: 0x%08lX already "
				"in list!\n", name, data);
			sanity_failed++;
			goto done;
		} else
			tmp = tmp->next;
	}
	tmp = fast_timer_list;
#endif

  t->delay_us = delay_us;
  t->function = function;
  t->data = data;
  t->name = name;

  t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
	t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ;
	if (t->tv_expires.tv_usec > 1000000) {
    t->tv_expires.tv_usec -= 1000000;
		t->tv_expires.tv_jiff += HZ;
  }
#ifdef FAST_TIMER_LOG
  timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
#endif
  fast_timers_added++;

  /* Check if this should timeout before anything else */
  if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) {
    /* Put first in list and modify the timer value */
    t->prev = NULL;
    t->next = fast_timer_list;
    if (fast_timer_list)
      fast_timer_list->prev = t;
    fast_timer_list = t;
#ifdef FAST_TIMER_LOG
    timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
    start_timer_trig(delay_us);
  } else {
    /* Put in correct place in list */
    while (tmp->next &&
        fasttime_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
      tmp = tmp->next;
    /* Insert t after tmp */
    t->prev = tmp;
    t->next = tmp->next;
    if (tmp->next)
    {
      tmp->next->prev = t;
    }
    tmp->next = t;
  }

  D2(printk("start_one_shot_timer: %d us done\n", delay_us));

done:
  local_irq_restore(flags);
} /* start_one_shot_timer */
Exemple #3
0
static irqreturn_t
timer1_handler(int irq, void *dev_id)
{
  struct fast_timer *t;
  unsigned long flags;

	/* We keep interrupts disabled not only when we modify the
	 * fast timer list, but any time we hold a reference to a
	 * timer in the list, since del_fast_timer may be called
	 * from (another) interrupt context.  Thus, the only time
	 * when interrupts are enabled is when calling the timer
	 * callback function.
	 */
  local_irq_save(flags);

  /* Clear timer1 irq */
  *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);

  /* First stop timer, then ack interrupt */
  /* Stop timer */
  *R_TIMER_CTRL = r_timer_ctrl_shadow =
    (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
    IO_STATE(R_TIMER_CTRL, tm1, stop_ld);

  /* Ack interrupt */
  *R_TIMER_CTRL =  r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);

  fast_timer_running = 0;
  fast_timer_ints++;

  t = fast_timer_list;
  while (t)
  {
		struct fasttime_t tv;
		fast_timer_function_type *f;
		unsigned long d;

    /* Has it really expired? */
    do_gettimeofday_fast(&tv);
		D1(printk(KERN_DEBUG "t: %is %06ius\n",
			tv.tv_jiff, tv.tv_usec));

		if (fasttime_cmp(&t->tv_expires, &tv) <= 0)
    {
      /* Yes it has expired */
#ifdef FAST_TIMER_LOG
      timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
#endif
      fast_timers_expired++;

      /* Remove this timer before call, since it may reuse the timer */
      if (t->prev)
      {
        t->prev->next = t->next;
      }
      else
      {
        fast_timer_list = t->next;
      }
      if (t->next)
      {
        t->next->prev = t->prev;
      }
      t->prev = NULL;
      t->next = NULL;

			/* Save function callback data before enabling
			 * interrupts, since the timer may be removed and
			 * we don't know how it was allocated
			 * (e.g. ->function and ->data may become overwritten
			 * after deletion if the timer was stack-allocated).
			 */
			f = t->function;
			d = t->data;

			if (f != NULL) {
				/* Run callback with interrupts enabled. */
				local_irq_restore(flags);
				f(d);
				local_irq_save(flags);
			} else
        DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
    }
    else
    {
      /* Timer is to early, let's set it again using the normal routines */
      D1(printk(".\n"));
    }

    if ((t = fast_timer_list) != NULL)
    {
      /* Start next timer.. */
			long us = 0;
			struct fasttime_t tv;

      do_gettimeofday_fast(&tv);

			/* time_after_eq takes care of wrapping */
			if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
				us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
					1000000 / HZ + t->tv_expires.tv_usec -
					tv.tv_usec);

      if (us > 0)
      {
        if (!fast_timer_running)
        {
#ifdef FAST_TIMER_LOG
          timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
          start_timer1(us);
        }
        break;
      }
      else
      {
        /* Timer already expired, let's handle it better late than never.
         * The normal loop handles it
         */
        D1(printk("e! %d\n", us));
      }
    }
  }

	local_irq_restore(flags);

  if (!t)
  {
    D1(printk("t1 stop!\n"));
  }

  return IRQ_HANDLED;
}
static irqreturn_t
timer1_handler(int irq, void *dev_id)
{
  struct fast_timer *t;
  unsigned long flags;

	/*                                                        
                                                          
                                                         
                                                          
                                                         
                      
  */
  local_irq_save(flags);

  /*                  */
  *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);

  /*                                      */
  /*            */
  *R_TIMER_CTRL = r_timer_ctrl_shadow =
    (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
    IO_STATE(R_TIMER_CTRL, tm1, stop_ld);

  /*               */
  *R_TIMER_CTRL =  r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);

  fast_timer_running = 0;
  fast_timer_ints++;

  t = fast_timer_list;
  while (t)
  {
		struct fasttime_t tv;
		fast_timer_function_type *f;
		unsigned long d;

    /*                        */
    do_gettimeofday_fast(&tv);
		D1(printk(KERN_DEBUG "t: %is %06ius\n",
			tv.tv_jiff, tv.tv_usec));

		if (fasttime_cmp(&t->tv_expires, &tv) <= 0)
    {
      /*                    */
#ifdef FAST_TIMER_LOG
      timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
#endif
      fast_timers_expired++;

      /*                                                             */
      if (t->prev)
      {
        t->prev->next = t->next;
      }
      else
      {
        fast_timer_list = t->next;
      }
      if (t->next)
      {
        t->next->prev = t->prev;
      }
      t->prev = NULL;
      t->next = NULL;

			/*                                            
                                                    
                                        
                                                        
                                                       
    */
			f = t->function;
			d = t->data;

			if (f != NULL) {
				/*                                       */
				local_irq_restore(flags);
				f(d);
				local_irq_save(flags);
			} else
        DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
    }
    else
    {
      /*                                                                 */
      D1(printk(".\n"));
    }

    if ((t = fast_timer_list) != NULL)
    {
      /*                    */
			long us = 0;
			struct fasttime_t tv;

      do_gettimeofday_fast(&tv);

			/*                                      */
			if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
				us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
					1000000 / HZ + t->tv_expires.tv_usec -
					tv.tv_usec);

      if (us > 0)
      {
        if (!fast_timer_running)
        {
#ifdef FAST_TIMER_LOG
          timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
          start_timer1(us);
        }
        break;
      }
      else
      {
        /*                                                               
                                     
         */
        D1(printk("e! %d\n", us));
      }
    }
  }

	local_irq_restore(flags);

  if (!t)
  {
    D1(printk("t1 stop!\n"));
  }

  return IRQ_HANDLED;
}
void start_one_shot_timer(struct fast_timer *t,
                          fast_timer_function_type *function,
                          unsigned long data,
                          unsigned long delay_us,
                          const char *name)
{
  unsigned long flags;
  struct fast_timer *tmp;

  D1(printk("sft %s %d us\n", name, delay_us));

  local_irq_save(flags);

  do_gettimeofday_fast(&t->tv_set);
  tmp = fast_timer_list;

#ifdef FAST_TIMER_SANITY_CHECKS
	/*                                             */
	while (tmp != NULL) {
		if (tmp == t) {
			printk(KERN_WARNING "timer name: %s data: "
				"0x%08lX already in list!\n", name, data);
			sanity_failed++;
			goto done;
		} else
			tmp = tmp->next;
	}
	tmp = fast_timer_list;
#endif

  t->delay_us = delay_us;
  t->function = function;
  t->data = data;
  t->name = name;

  t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
	t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ;
  if (t->tv_expires.tv_usec > 1000000)
  {
    t->tv_expires.tv_usec -= 1000000;
		t->tv_expires.tv_jiff += HZ;
  }
#ifdef FAST_TIMER_LOG
  timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
#endif
  fast_timers_added++;

  /*                                                   */
	if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
  {
    /*                                              */
    t->prev = NULL;
    t->next = fast_timer_list;
    if (fast_timer_list)
    {
      fast_timer_list->prev = t;
    }
    fast_timer_list = t;
#ifdef FAST_TIMER_LOG
    timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
    start_timer1(delay_us);
  } else {
    /*                              */
		while (tmp->next && fasttime_cmp(&t->tv_expires,
				&tmp->next->tv_expires) > 0)
    {
      tmp = tmp->next;
    }
    /*                    */
    t->prev = tmp;
    t->next = tmp->next;
    if (tmp->next)
    {
      tmp->next->prev = t;
    }
    tmp->next = t;
  }

  D2(printk("start_one_shot_timer: %d us done\n", delay_us));

done:
  local_irq_restore(flags);
} /*                      */
Exemple #6
0
static irqreturn_t
timer1_handler(int irq, void *dev_id)
{
  struct fast_timer *t;
  unsigned long flags;

  local_irq_save(flags);

  
  *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);

  
  
  *R_TIMER_CTRL = r_timer_ctrl_shadow =
    (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
    IO_STATE(R_TIMER_CTRL, tm1, stop_ld);

  
  *R_TIMER_CTRL =  r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);

  fast_timer_running = 0;
  fast_timer_ints++;

  t = fast_timer_list;
  while (t)
  {
		struct fasttime_t tv;
		fast_timer_function_type *f;
		unsigned long d;

    
    do_gettimeofday_fast(&tv);
		D1(printk(KERN_DEBUG "t: %is %06ius\n",
			tv.tv_jiff, tv.tv_usec));

		if (fasttime_cmp(&t->tv_expires, &tv) <= 0)
    {
      
#ifdef FAST_TIMER_LOG
      timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
#endif
      fast_timers_expired++;

      
      if (t->prev)
      {
        t->prev->next = t->next;
      }
      else
      {
        fast_timer_list = t->next;
      }
      if (t->next)
      {
        t->next->prev = t->prev;
      }
      t->prev = NULL;
      t->next = NULL;

			/* Save function callback data before enabling
			 * interrupts, since the timer may be removed and
			 * we don't know how it was allocated
			 * (e.g. ->function and ->data may become overwritten
			 * after deletion if the timer was stack-allocated).
			 */
			f = t->function;
			d = t->data;

			if (f != NULL) {
				
				local_irq_restore(flags);
				f(d);
				local_irq_save(flags);
			} else
        DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
    }
    else
    {
      
      D1(printk(".\n"));
    }

    if ((t = fast_timer_list) != NULL)
    {
      
			long us = 0;
			struct fasttime_t tv;

      do_gettimeofday_fast(&tv);

			
			if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
				us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
					1000000 / HZ + t->tv_expires.tv_usec -
					tv.tv_usec);

      if (us > 0)
      {
        if (!fast_timer_running)
        {
#ifdef FAST_TIMER_LOG
          timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
          start_timer1(us);
        }
        break;
      }
      else
      {
        D1(printk("e! %d\n", us));
      }
    }
  }

	local_irq_restore(flags);

  if (!t)
  {
    D1(printk("t1 stop!\n"));
  }

  return IRQ_HANDLED;
}