diff options
author | Colin Cross <ccross@android.com> | 2012-10-08 17:01:12 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2012-10-08 17:01:12 -0400 |
commit | 9d7d6e363b06934221b81a859d509844c97380df (patch) | |
tree | 9b46831e4161307d6571724654f049da5b04a55a /arch/arm | |
parent | 5e090ed7af10729a396a25df43d69a236e789736 (diff) |
ARM: OMAP: counter: add locking to read_persistent_clock
read_persistent_clock uses a global variable, use a spinlock to
ensure non-atomic updates to the variable don't overlap and cause
time to move backwards.
Signed-off-by: Colin Cross <ccross@android.com>
Signed-off-by: R Sricharan <r.sricharan@ti.com>
Cc: stable@vger.kernel.org
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/plat-omap/counter_32k.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index 2e826f1faf7b..87ba8dd0d791 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c | |||
@@ -52,22 +52,29 @@ static u32 notrace omap_32k_read_sched_clock(void) | |||
52 | * nsecs and adds to a monotonically increasing timespec. | 52 | * nsecs and adds to a monotonically increasing timespec. |
53 | */ | 53 | */ |
54 | static struct timespec persistent_ts; | 54 | static struct timespec persistent_ts; |
55 | static cycles_t cycles, last_cycles; | 55 | static cycles_t cycles; |
56 | static unsigned int persistent_mult, persistent_shift; | 56 | static unsigned int persistent_mult, persistent_shift; |
57 | static DEFINE_SPINLOCK(read_persistent_clock_lock); | ||
58 | |||
57 | static void omap_read_persistent_clock(struct timespec *ts) | 59 | static void omap_read_persistent_clock(struct timespec *ts) |
58 | { | 60 | { |
59 | unsigned long long nsecs; | 61 | unsigned long long nsecs; |
60 | cycles_t delta; | 62 | cycles_t last_cycles; |
61 | struct timespec *tsp = &persistent_ts; | 63 | unsigned long flags; |
64 | |||
65 | spin_lock_irqsave(&read_persistent_clock_lock, flags); | ||
62 | 66 | ||
63 | last_cycles = cycles; | 67 | last_cycles = cycles; |
64 | cycles = sync32k_cnt_reg ? __raw_readl(sync32k_cnt_reg) : 0; | 68 | cycles = sync32k_cnt_reg ? __raw_readl(sync32k_cnt_reg) : 0; |
65 | delta = cycles - last_cycles; | ||
66 | 69 | ||
67 | nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift); | 70 | nsecs = clocksource_cyc2ns(cycles - last_cycles, |
71 | persistent_mult, persistent_shift); | ||
72 | |||
73 | timespec_add_ns(&persistent_ts, nsecs); | ||
74 | |||
75 | *ts = persistent_ts; | ||
68 | 76 | ||
69 | timespec_add_ns(tsp, nsecs); | 77 | spin_unlock_irqrestore(&read_persistent_clock_lock, flags); |
70 | *ts = *tsp; | ||
71 | } | 78 | } |
72 | 79 | ||
73 | /** | 80 | /** |