Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 234908
b: refs/heads/master
c: 5df9150
h: refs/heads/master
v: v3
  • Loading branch information
jacob.jun.pan@linux.intel.com authored and Thomas Gleixner committed Feb 18, 2011
1 parent 2f9d716 commit 4b21365
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 57 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 13884c6680973f0ce3483dc59b636b4962d6dafe
refs/heads/master: 5df91509d324d44cfb11e55d9cb02fe18b53b045
60 changes: 4 additions & 56 deletions trunk/arch/x86/kernel/apb_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,64 +506,12 @@ static int apbt_next_event(unsigned long delta,
return 0;
}

/*
* APB timer clock is not in sync with pclk on Langwell, which translates to
* unreliable read value caused by sampling error. the error does not add up
* overtime and only happens when sampling a 0 as a 1 by mistake. so the time
* would go backwards. the following code is trying to prevent time traveling
* backwards. little bit paranoid.
*/
static cycle_t apbt_read_clocksource(struct clocksource *cs)
{
unsigned long t0, t1, t2;
static unsigned long last_read;

bad_count:
t1 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
t2 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
if (unlikely(t1 < t2)) {
pr_debug("APBT: read current count error %lx:%lx:%lx\n",
t1, t2, t2 - t1);
goto bad_count;
}
/*
* check against cached last read, makes sure time does not go back.
* it could be a normal rollover but we will do tripple check anyway
*/
if (unlikely(t2 > last_read)) {
/* check if we have a normal rollover */
unsigned long raw_intr_status =
apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
/*
* cs timer interrupt is masked but raw intr bit is set if
* rollover occurs. then we read EOI reg to clear it.
*/
if (raw_intr_status & (1 << phy_cs_timer_id)) {
apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
goto out;
}
pr_debug("APB CS going back %lx:%lx:%lx ",
t2, last_read, t2 - last_read);
bad_count_x3:
pr_debug("triple check enforced\n");
t0 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
udelay(1);
t1 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
udelay(1);
t2 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
if ((t2 > t1) || (t1 > t0)) {
printk(KERN_ERR "Error: APB CS tripple check failed\n");
goto bad_count_x3;
}
}
out:
last_read = t2;
return (cycle_t)~t2;
unsigned long current_count;

current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
return (cycle_t)~current_count;
}

static int apbt_clocksource_register(void)
Expand Down

0 comments on commit 4b21365

Please sign in to comment.