]> git.karo-electronics.de Git - linux-beck.git/commitdiff
clocksource: improve sh_cmt clocksource overflow handling
authorMagnus Damm <damm@igel.co.jp>
Tue, 28 Apr 2009 08:17:54 +0000 (08:17 +0000)
committerPaul Mundt <lethal@linux-sh.org>
Tue, 28 Apr 2009 09:01:21 +0000 (18:01 +0900)
This patch improves the sh_cmt clocksource handling.

Currently the counter value is ignored in the case of
overflow. With this patch the overflow flag is read
before and after reading the counter, removing any
counter value and overflow flag mismatch issues.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
drivers/clocksource/sh_cmt.c

index c24756489612e0e129ec66c46da5e1a2b8e96e06..d607ac2d516bda0cddbee933b833e48735727707 100644 (file)
@@ -111,16 +111,21 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
                                        int *has_wrapped)
 {
        unsigned long v1, v2, v3;
+       int o1, o2;
+
+       o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
 
        /* Make sure the timer value is stable. Stolen from acpi_pm.c */
        do {
+               o2 = o1;
                v1 = sh_cmt_read(p, CMCNT);
                v2 = sh_cmt_read(p, CMCNT);
                v3 = sh_cmt_read(p, CMCNT);
-       } while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
-                         || (v3 > v1 && v3 < v2)));
+               o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+       } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
+                         || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
 
-       *has_wrapped = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+       *has_wrapped = o1;
        return v2;
 }
 
@@ -394,7 +399,7 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
        raw = sh_cmt_get_counter(p, &has_wrapped);
 
        if (unlikely(has_wrapped))
-               raw = p->match_value;
+               raw += p->match_value;
        spin_unlock_irqrestore(&p->lock, flags);
 
        return value + raw;