diff options
-rw-r--r-- | arch/arm/include/asm/spinlock.h | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index 17eb355707dd..da1af5240159 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h | |||
@@ -5,17 +5,36 @@ | |||
5 | #error SMP not supported on pre-ARMv6 CPUs | 5 | #error SMP not supported on pre-ARMv6 CPUs |
6 | #endif | 6 | #endif |
7 | 7 | ||
8 | /* | ||
9 | * sev and wfe are ARMv6K extensions. Uniprocessor ARMv6 may not have the K | ||
10 | * extensions, so when running on UP, we have to patch these instructions away. | ||
11 | */ | ||
12 | #define ALT_SMP(smp, up) \ | ||
13 | "9998: " smp "\n" \ | ||
14 | " .pushsection \".alt.smp.init\", \"a\"\n" \ | ||
15 | " .long 9998b\n" \ | ||
16 | " " up "\n" \ | ||
17 | " .popsection\n" | ||
18 | |||
19 | #ifdef CONFIG_THUMB2_KERNEL | ||
20 | #define SEV ALT_SMP("sev.w", "nop.w") | ||
21 | #define WFE(cond) ALT_SMP("wfe" cond ".w", "nop.w") | ||
22 | #else | ||
23 | #define SEV ALT_SMP("sev", "nop") | ||
24 | #define WFE(cond) ALT_SMP("wfe" cond, "nop") | ||
25 | #endif | ||
26 | |||
8 | static inline void dsb_sev(void) | 27 | static inline void dsb_sev(void) |
9 | { | 28 | { |
10 | #if __LINUX_ARM_ARCH__ >= 7 | 29 | #if __LINUX_ARM_ARCH__ >= 7 |
11 | __asm__ __volatile__ ( | 30 | __asm__ __volatile__ ( |
12 | "dsb\n" | 31 | "dsb\n" |
13 | "sev" | 32 | SEV |
14 | ); | 33 | ); |
15 | #elif defined(CONFIG_CPU_32v6K) | 34 | #else |
16 | __asm__ __volatile__ ( | 35 | __asm__ __volatile__ ( |
17 | "mcr p15, 0, %0, c7, c10, 4\n" | 36 | "mcr p15, 0, %0, c7, c10, 4\n" |
18 | "sev" | 37 | SEV |
19 | : : "r" (0) | 38 | : : "r" (0) |
20 | ); | 39 | ); |
21 | #endif | 40 | #endif |
@@ -46,9 +65,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) | |||
46 | __asm__ __volatile__( | 65 | __asm__ __volatile__( |
47 | "1: ldrex %0, [%1]\n" | 66 | "1: ldrex %0, [%1]\n" |
48 | " teq %0, #0\n" | 67 | " teq %0, #0\n" |
49 | #ifdef CONFIG_CPU_32v6K | 68 | WFE("ne") |
50 | " wfene\n" | ||
51 | #endif | ||
52 | " strexeq %0, %2, [%1]\n" | 69 | " strexeq %0, %2, [%1]\n" |
53 | " teqeq %0, #0\n" | 70 | " teqeq %0, #0\n" |
54 | " bne 1b" | 71 | " bne 1b" |
@@ -107,9 +124,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw) | |||
107 | __asm__ __volatile__( | 124 | __asm__ __volatile__( |
108 | "1: ldrex %0, [%1]\n" | 125 | "1: ldrex %0, [%1]\n" |
109 | " teq %0, #0\n" | 126 | " teq %0, #0\n" |
110 | #ifdef CONFIG_CPU_32v6K | 127 | WFE("ne") |
111 | " wfene\n" | ||
112 | #endif | ||
113 | " strexeq %0, %2, [%1]\n" | 128 | " strexeq %0, %2, [%1]\n" |
114 | " teq %0, #0\n" | 129 | " teq %0, #0\n" |
115 | " bne 1b" | 130 | " bne 1b" |
@@ -176,9 +191,7 @@ static inline void arch_read_lock(arch_rwlock_t *rw) | |||
176 | "1: ldrex %0, [%2]\n" | 191 | "1: ldrex %0, [%2]\n" |
177 | " adds %0, %0, #1\n" | 192 | " adds %0, %0, #1\n" |
178 | " strexpl %1, %0, [%2]\n" | 193 | " strexpl %1, %0, [%2]\n" |
179 | #ifdef CONFIG_CPU_32v6K | 194 | WFE("mi") |
180 | " wfemi\n" | ||
181 | #endif | ||
182 | " rsbpls %0, %1, #0\n" | 195 | " rsbpls %0, %1, #0\n" |
183 | " bmi 1b" | 196 | " bmi 1b" |
184 | : "=&r" (tmp), "=&r" (tmp2) | 197 | : "=&r" (tmp), "=&r" (tmp2) |