summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2005-12-01 15:47:24 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-12-01 15:47:24 +0000
commit00b4c90787298349b799069360ced9ca843153dc (patch)
treecb135bdb9a408ec771c862caae5d86a2d6754861
parentdf2f5e721ed36e21da27e1f415c71ba0e20f31b5 (diff)
[ARM SMP] Use event instructions for spinlocks
ARMv6K CPUs have SEV (send event) and WFE (wait for event) instructions which allow the CPU clock to be suspended until another CPU issues a SEV, rather than spinning on the lock wasting power. Make use of these instructions. Note that WFE does not wait if an event has been sent since the last WFE cleared the event status, so although it may look racy, the instruction implementation ensures that these are dealt with. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--include/asm-arm/spinlock.h26
1 files changed, 24 insertions, 2 deletions
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 6ed4f916b166..43ad4e55878c 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -30,6 +30,9 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
__asm__ __volatile__(
"1: ldrex %0, [%1]\n"
" teq %0, #0\n"
+#ifdef CONFIG_CPU_32v6K
+" wfene\n"
+#endif
" strexeq %0, %2, [%1]\n"
" teqeq %0, #0\n"
" bne 1b"
@@ -65,7 +68,11 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
smp_mb();
__asm__ __volatile__(
-" str %1, [%0]"
+" str %1, [%0]\n"
+#ifdef CONFIG_CPU_32v6K
+" mcr p15, 0, %1, c7, c10, 4\n" /* DSB */
+" sev"
+#endif
:
: "r" (&lock->lock), "r" (0)
: "cc");
@@ -87,6 +94,9 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
__asm__ __volatile__(
"1: ldrex %0, [%1]\n"
" teq %0, #0\n"
+#ifdef CONFIG_CPU_32v6K
+" wfene\n"
+#endif
" strexeq %0, %2, [%1]\n"
" teq %0, #0\n"
" bne 1b"
@@ -122,7 +132,11 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
smp_mb();
__asm__ __volatile__(
- "str %1, [%0]"
+ "str %1, [%0]\n"
+#ifdef CONFIG_CPU_32v6K
+" mcr p15, 0, %1, c7, c10, 4\n" /* DSB */
+" sev\n"
+#endif
:
: "r" (&rw->lock), "r" (0)
: "cc");
@@ -148,6 +162,9 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
"1: ldrex %0, [%2]\n"
" adds %0, %0, #1\n"
" strexpl %1, %0, [%2]\n"
+#ifdef CONFIG_CPU_32v6K
+" wfemi\n"
+#endif
" rsbpls %0, %1, #0\n"
" bmi 1b"
: "=&r" (tmp), "=&r" (tmp2)
@@ -169,6 +186,11 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
" strex %1, %0, [%2]\n"
" teq %1, #0\n"
" bne 1b"
+#ifdef CONFIG_CPU_32v6K
+"\n cmp %0, #0\n"
+" mcreq p15, 0, %0, c7, c10, 4\n"
+" seveq"
+#endif
: "=&r" (tmp), "=&r" (tmp2)
: "r" (&rw->lock)
: "cc");