ARM: OMAP: counter: add locking to read_persistent_clock
Subsystems (2)
PATCH v2 1/1 ARM: OMAP: counter: add locking to read_persistent_clock
From: Colin Cross <[email protected]>
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.
---
[V2] Added signed-off-by and looped in "linux-arm-kernel" list
arch/arm/plat-omap/counter_32k.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
arch/arm/plat-omap/counter_32k.c +14 -7
@@ -55,22 +55,29 @@ static u32 notrace omap_32k_read_sched_clock(void)* nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles;static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK (read_persistent_clock_lock); +static void omap_read_persistent_clock (struct timespec *ts) {unsigned long long nsecs; -cycles_t delta; -struct timespec *tsp = &persistent_ts; +cycles_t last_cycles; +unsigned long flags; + +spin_lock_irqsave (&read_persistent_clock_lock, flags); last_cycles = cycles; cycles = sync32k_cnt_reg ?__raw_readl (sync32k_cnt_reg) :0 ; - delta = cycles - last_cycles; - nsecs =clocksource_cyc2ns (delta, persistent_mult, persistent_shift); + nsecs =clocksource_cyc2ns (cycles - last_cycles, + persistent_mult, persistent_shift); + +timespec_add_ns (&persistent_ts, nsecs); + + *ts = persistent_ts; -timespec_add_ns (tsp, nsecs); - *ts = *tsp; +spin_unlock_irqrestore (&read_persistent_clock_lock, flags); }/**
Signature · 1 line
1.7.9.5
PATCH v2 1/1 ARM: OMAP: counter: add locking to read_persistent_clock
Quoted 8 lines · R Sricharan
From: Colin Cross <[email protected]>
read_persistent_clockuses 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 <[email protected]>Signed-off-by R Sricharan <[email protected]>
Tony, this should probably be queued up for v3.7-rc and flagged for stable.
Thanks,
Kevin
Quoted 47 lines
---
[V2] Added signed-off-by and looped in "linux-arm-kernel" listarch/arm/plat-omap/counter_32k.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)arch/arm/plat-omap/counter_32k.c +14
-7@@ -55,22 +55,29 @@ static u32 notrace omap_32k_read_sched_clock(void)* nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles;static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK (read_persistent_clock_lock); +static void omap_read_persistent_clock (struct timespec *ts) {unsigned long long nsecs; -cycles_t delta; -struct timespec *tsp = &persistent_ts; +cycles_t last_cycles; +unsigned long flags; + +spin_lock_irqsave (&read_persistent_clock_lock, flags); last_cycles = cycles; cycles = sync32k_cnt_reg ?__raw_readl (sync32k_cnt_reg) :0 ; - delta = cycles - last_cycles; - nsecs =clocksource_cyc2ns (delta, persistent_mult, persistent_shift); + nsecs =clocksource_cyc2ns (cycles - last_cycles, + persistent_mult, persistent_shift); + +timespec_add_ns (&persistent_ts, nsecs); + + *ts = persistent_ts; -timespec_add_ns (tsp, nsecs); - *ts = *tsp; +spin_unlock_irqrestore (&read_persistent_clock_lock, flags); }/**
PATCH v2 1/1 ARM: OMAP: counter: add locking to read_persistent_clock
Quoted 8 lines · Kevin Hilman
Quoted 6 lines · R Sricharan
From: Colin Cross <[email protected]>
read_persistent_clockuses a global variable, use a spinlock to ensure non-atomic updates to the variable don't overlap and cause time to move backwards.
Quoted 6 lines
Quoted 2 lines
Signed-off-by Colin Cross <[email protected]>Signed-off-by R Sricharan <[email protected]>Acked-by Kevin Hilman <[email protected]>Tony, this should probably be queued up for v3.7-rc and flagged for stable.
Yes I can see that happening. But then in addition..
Quoted 29 lines
Quoted 29 lines
---
[V2] Added signed-off-by and looped in "linux-arm-kernel" listarch/arm/plat-omap/counter_32k.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)arch/arm/plat-omap/counter_32k.c +7
-3@@ -55,22 +55,29 @@ static u32 notrace omap_32k_read_sched_clock(void)* nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles;static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK (read_persistent_clock_lock); +static void omap_read_persistent_clock (struct timespec *ts) {unsigned long long nsecs; -cycles_t delta; -struct timespec *tsp = &persistent_ts; +cycles_t last_cycles; +unsigned long flags; + +spin_lock_irqsave (&read_persistent_clock_lock, flags);
Quoted 7 lines
arch/arm/plat-omap/counter_32k.c static u32 notrace omap_32k_read_sched_clock(void) · line 74
Quoted 7 lines
arch/arm/plat-omap/counter_32k.c +2
-2last_cycles = cycles; cycles = sync32k_cnt_reg ?__raw_readl (sync32k_cnt_reg) :0 ; - delta = cycles - last_cycles; - nsecs =clocksource_cyc2ns (delta, persistent_mult, persistent_shift); + nsecs =clocksource_cyc2ns (cycles - last_cycles, + persistent_mult, persistent_shift);
..I think there's another bug here where cycles - last_cycles returns wrong value when the timer wraps around as cycles_t is 64 bits and the counter is 32 bits. It seems it's been there since when the read_persistent_clock was added with commit d92cfcbe (OMAP: timekeeping: time should not stop during suspend)?
It seems that after this patch cycles should not be cycles_t but u32, and the result of cycles - last_cycles should also be u32.
Quoted 8 lines
arch/arm/plat-omap/counter_32k.c static u32 notrace omap_32k_read_sched_clock(void) · line 81
Quoted 8 lines
arch/arm/plat-omap/counter_32k.c +4
-2+timespec_add_ns (&persistent_ts, nsecs); + + *ts = persistent_ts; -timespec_add_ns (tsp, nsecs); - *ts = *tsp; +spin_unlock_irqrestore (&read_persistent_clock_lock, flags); }
Regards,
Tony
PATCH v2 1/1 ARM: OMAP: counter: add locking to read_persistent_clock
Hi Tony,
[snip..]
Quoted 36 lines
Quoted 22 lines
Quoted 22 lines
index dbf1e03..2bc51fb 100644
arch/arm/plat-omap/counter_32k.c +7
-3@@ -55,22 +55,29 @@ static u32 notrace omap_32k_read_sched_clock(void)* nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles;static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK (read_persistent_clock_lock); +static void omap_read_persistent_clock (struct timespec *ts) {unsigned long long nsecs; -cycles_t delta; -struct timespec *tsp = &persistent_ts; +cycles_t last_cycles; +unsigned long flags; + +spin_lock_irqsave (&read_persistent_clock_lock, flags);Quoted 7 lines
arch/arm/plat-omap/counter_32k.c static u32 notrace omap_32k_read_sched_clock(void) · line 74
Quoted 7 lines
arch/arm/plat-omap/counter_32k.c +2
-2last_cycles = cycles; cycles = sync32k_cnt_reg ?__raw_readl (sync32k_cnt_reg) :0 ; - delta = cycles - last_cycles; - nsecs =clocksource_cyc2ns (delta, persistent_mult, persistent_shift); + nsecs =clocksource_cyc2ns (cycles - last_cycles, + persistent_mult, persistent_shift);..I think there's another bug here where cycles -
last_cyclesreturns wrong value when the timer wraps around ascycles_tis 64 bits and the counter is 32 bits. It seems it's been there since when theread_persistent_clockwas added with commitd92cfcbe(OMAP: timekeeping: time should not stop during suspend)?
Quoted 4 lines
It seems that after this patch cycles should not be
cycles_tbut u32, and the result of cycles -last_cyclesshould also be u32.
cycles_t is defined as typedef unsigned long cycles_t; Am i missing something here ?
Thanks,
Sricharan
PATCH v2 1/1 ARM: OMAP: counter: add locking to read_persistent_clock
Quoted 40 lines · R, Sricharan
Hi Tony,
[snip..]
Quoted 36 lines
Quoted 22 lines
Quoted 22 lines
index dbf1e03..2bc51fb 100644
arch/arm/plat-omap/counter_32k.c +7
-3@@ -55,22 +55,29 @@ static u32 notrace omap_32k_read_sched_clock(void)* nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles;static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK (read_persistent_clock_lock); +static void omap_read_persistent_clock (struct timespec *ts) {unsigned long long nsecs; -cycles_t delta; -struct timespec *tsp = &persistent_ts; +cycles_t last_cycles; +unsigned long flags; + +spin_lock_irqsave (&read_persistent_clock_lock, flags);Quoted 7 lines
arch/arm/plat-omap/counter_32k.c static u32 notrace omap_32k_read_sched_clock(void) · line 74
Quoted 7 lines
arch/arm/plat-omap/counter_32k.c +2
-2last_cycles = cycles; cycles = sync32k_cnt_reg ?__raw_readl (sync32k_cnt_reg) :0 ; - delta = cycles - last_cycles; - nsecs =clocksource_cyc2ns (delta, persistent_mult, persistent_shift); + nsecs =clocksource_cyc2ns (cycles - last_cycles, + persistent_mult, persistent_shift);..I think there's another bug here where cycles -
last_cyclesreturns wrong value when the timer wraps around ascycles_tis 64 bits and the counter is 32 bits. It seems it's been there since when theread_persistent_clockwas added with commitd92cfcbe(OMAP: timekeeping: time should not stop during suspend)?
Quoted 6 lines
Quoted 4 lines
It seems that after this patch cycles should not be
cycles_tbut u32, and the result of cycles -last_cyclesshould also be u32.
cycles_tis defined as typedef unsigned longcycles_t; Am i missing something here ?
Oh right, cycles_t is unsigned long, it's OK then. Must have grepped for it from some other arch.
Regards,
Tony
PATCH v2 1/1 ARM: OMAP: counter: add locking to read_persistent_clock
Quoted 45 lines · Tony Lindgren
Quoted 44 lines · R, Sricharan
Hi Tony,
[snip..]
Quoted 40 lines
Quoted 22 lines
Quoted 22 lines
index dbf1e03..2bc51fb 100644
arch/arm/plat-omap/counter_32k.c +7
-3@@ -55,22 +55,29 @@ static u32 notrace omap_32k_read_sched_clock(void)* nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles;static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK (read_persistent_clock_lock); +static void omap_read_persistent_clock (struct timespec *ts) {unsigned long long nsecs; -cycles_t delta; -struct timespec *tsp = &persistent_ts; +cycles_t last_cycles; +unsigned long flags; + +spin_lock_irqsave (&read_persistent_clock_lock, flags);Quoted 7 lines
arch/arm/plat-omap/counter_32k.c static u32 notrace omap_32k_read_sched_clock(void) · line 74
Quoted 7 lines
arch/arm/plat-omap/counter_32k.c +2
-2last_cycles = cycles; cycles = sync32k_cnt_reg ?__raw_readl (sync32k_cnt_reg) :0 ; - delta = cycles - last_cycles; - nsecs =clocksource_cyc2ns (delta, persistent_mult, persistent_shift); + nsecs =clocksource_cyc2ns (cycles - last_cycles, + persistent_mult, persistent_shift);..I think there's another bug here where cycles -
last_cyclesreturns wrong value when the timer wraps around ascycles_tis 64 bits and the counter is 32 bits. It seems it's been there since when theread_persistent_clockwas added with commitd92cfcbe(OMAP: timekeeping: time should not stop during suspend)?It seems that after this patch cycles should not be
cycles_tbut u32, and the result of cycles -last_cyclesshould also be u32.
Quoted 5 lines
Quoted 2 lines
cycles_tis defined as typedef unsigned longcycles_t; Am i missing something here ?Oh right,
cycles_tis unsigned long, it's OK then. Must have grepped for it from some other arch.
Applying to fixes with Cc stable.
Regards,
Tony