public inbox for linux-arch@vger.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: liqin.chen@sunplusct.com
Cc: linux-arch@vger.kernel.org, linux-kernel@vger.kernel.org,
	Arnd Bergmann <arnd@arndb.de>,
	Andrew Morton <akpm@linux-foundation.org>,
	torvalds@linux-foundation.org
Subject: Re: [PATCH 22/27] score: create kernel files signal.c sys_score.c time.c
Date: Tue, 9 Jun 2009 10:51:13 +0200 (CEST)	[thread overview]
Message-ID: <alpine.LFD.2.00.0906091028020.3351@localhost.localdomain> (raw)
In-Reply-To: <OF32AB4A20.4574C065-ON482575D0.00243CB1-482575D0.0024AD26@sunplusct.com>

Chen,

On Tue, 9 Jun 2009, liqin.chen@sunplusct.com wrote:

> +static struct irqaction timer_irq = {
> +       .handler = timer_interrupt,
> +       .flags = IRQF_DISABLED | IRQF_TIMER,
> +       .mask = CPU_MASK_NONE,
> +       .name = "timer",
> +};
> +
> +static int comparator_next_event(unsigned long delta,
> +               struct clock_event_device *evdev)
> +{
> +       unsigned long   flags;
> +
> +       raw_local_irq_save(flags);


  This function is always called with interrupts disabled.

> +       __raw_writel((TMR_M_PERIODIC | TMR_IE_ENABLE), (void *)P_TIMER0_CTRL);

  Can you please move the type cast to the define or better have a:

  static const __iomem void *timer_ctrl = .....;

  somehwere at the top of the file/

> +       __raw_writel(delta, (void *)P_TIMER0_PRELOAD);
> +       __raw_writel(__raw_readl((void *)P_TIMER0_CTRL) | TMR_ENABLE,
> +               (void *)P_TIMER0_CTRL);
> +
> +       raw_local_irq_restore(flags);
> +
> +       return 0;
> +}
> +
> +static void comparator_mode(enum clock_event_mode mode,
> +               struct clock_event_device *evdev)
> +{
> +       unsigned long   flags;
> +
> +       switch (mode) {
> +       case CLOCK_EVT_MODE_PERIODIC:
> +               raw_local_irq_save(flags);

  This function is also called with interrupts disabled.


> +               __raw_writel((TMR_M_PERIODIC | TMR_IE_ENABLE),
> +                       (void *)P_TIMER0_CTRL);
> +               __raw_writel(SYSTEM_CLOCK/100, (void *)P_TIMER0_PRELOAD);

  shouldn't 100 be replaced by HZ ?

> +               __raw_writel(__raw_readl((void *)P_TIMER0_CTRL) | 
> TMR_ENABLE,
> +                       (void *)P_TIMER0_CTRL);
> +               raw_local_irq_restore(flags);
> +               break;
> +       case CLOCK_EVT_MODE_ONESHOT:
> +       case CLOCK_EVT_MODE_RESUME:
> +       case CLOCK_EVT_MODE_UNUSED:
> +       case CLOCK_EVT_MODE_SHUTDOWN:
> +               break;
> +       default:
> +               BUG();
> +       }
> +}
> +
> +static struct clock_event_device comparator = {
> +       .name           = "avr32_comparator",
> +       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
> +       .shift          = 16,
> +       .set_next_event = comparator_next_event,
> +       .set_mode       = comparator_mode,
> +};
> +
> +static u32 score_tick_cnt;
> +
> +static cycle_t score_read_clk(struct clocksource *cs)
> +{
> +       unsigned long flags;
> +
> +       local_irq_save(flags);
> +       score_tick_cnt += SYSTEM_CLOCK/100;
> +       local_irq_restore(flags);

  How is that supposed to work ? read_clk() is called from various
  places in the kernel and you seem to add some constant value to it
  on every call. That can not work at all. You need a counter which
  is incrementing at a constant rate and can be read out.

  If you do not have a continous counter then you should not provide a
  clock source. The generic code will then provide the jiffies clock
  source. In that case you need to disable the oneshot mode of your
  clock event device as well.

> +
> +       return score_tick_cnt;
> +}
> +
> +static struct clocksource score_clk = {
> +       .name   = "timer",
> +       .rating = 250,
> +       .read   = score_read_clk,
> +       .shift  = 20,
> +       .mask   = CLOCKSOURCE_MASK(32),
> +       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,

  yeah, continuously wrong :)

> +};
> +
> +void __init time_init(void)
> +{
> +       xtime.tv_sec = mktime(2009, 1, 1, 0, 0, 0);
> +       xtime.tv_nsec = 0;
> +
> +       set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec,
> +                               -xtime.tv_nsec);

  xtime setup is done in the generic time keeping code already. Please
  remove.

> +       /* disable timer, timer interrupt enable */
> +       __raw_writel((TMR_M_PERIODIC | TMR_IE_ENABLE), (void 
> *)P_TIMER0_CTRL);
> +       __raw_writel(SYSTEM_CLOCK/100, (void *)P_TIMER0_PRELOAD); /* 10ms 
> */
> +
> +       /* start timer */
> +       __raw_writel(__raw_readl((void *)P_TIMER0_CTRL) | TMR_ENABLE,
> +               (void *)P_TIMER0_CTRL);

  No need to start the timer here. When you register your clock event
  device the set_mode function is called and the timer is started.

  Your implementation is not going to work at all.

  A clock event device is a device which delivers either periodic or
  one shot interrupts. It is registered with the generic clockevents
  layer which takes care of setting up the device via the set_mode
  call back.

  The clock source device is a device which provides a monotonic
  increasing counter which can wrap around at some point. The wrap
  around point has to be power of 2 and is defined via the .mask
  member of the clock source device structure. The generic time
  keeping code takes care of the conversion to nsec based time and
  handles NTP and other adjustments.

  So in practice you need either two hardware devices (counter and
  interrupt generator) or a device which has a monotonic increasing
  counter and a match register which generates an interrupt when the
  counter value and the match register are the same.

Thanks,

	tglx

  reply	other threads:[~2009-06-09  8:52 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-09  6:36 [PATCH 22/27] score: create kernel files signal.c sys_score.c time.c liqin.chen
2009-06-09  8:51 ` Thomas Gleixner [this message]
2009-06-13  6:26   ` liqin.chen
2009-06-13  6:26     ` liqin.chen
2009-06-09 17:52 ` Arnd Bergmann
2009-06-09 17:52   ` Arnd Bergmann
2009-06-13  6:43   ` liqin.chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.LFD.2.00.0906091028020.3351@localhost.localdomain \
    --to=tglx@linutronix.de \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liqin.chen@sunplusct.com \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox