aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2012-10-08 17:01:12 -0400
committerTony Lindgren <tony@atomide.com>2012-10-08 17:01:12 -0400
commit9d7d6e363b06934221b81a859d509844c97380df (patch)
tree9b46831e4161307d6571724654f049da5b04a55a /arch/arm
parent5e090ed7af10729a396a25df43d69a236e789736 (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.c21
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 */
54static struct timespec persistent_ts; 54static struct timespec persistent_ts;
55static cycles_t cycles, last_cycles; 55static cycles_t cycles;
56static unsigned int persistent_mult, persistent_shift; 56static unsigned int persistent_mult, persistent_shift;
57static DEFINE_SPINLOCK(read_persistent_clock_lock);
58
57static void omap_read_persistent_clock(struct timespec *ts) 59static 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/**