[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>
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 6ed4f91..43ad4e5 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -30,6 +30,9 @@
 	__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 @@
 	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 @@
 	__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 @@
 	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 @@
 "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 @@
 "	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");