diff options
Diffstat (limited to 'arch/xtensa/include/asm/cmpxchg.h')
| -rw-r--r-- | arch/xtensa/include/asm/cmpxchg.h | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h index 64dad04a9d27..d9ab131bc1aa 100644 --- a/arch/xtensa/include/asm/cmpxchg.h +++ b/arch/xtensa/include/asm/cmpxchg.h | |||
| @@ -22,17 +22,30 @@ | |||
| 22 | static inline unsigned long | 22 | static inline unsigned long |
| 23 | __cmpxchg_u32(volatile int *p, int old, int new) | 23 | __cmpxchg_u32(volatile int *p, int old, int new) |
| 24 | { | 24 | { |
| 25 | __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t" | 25 | #if XCHAL_HAVE_S32C1I |
| 26 | "l32i %0, %1, 0 \n\t" | 26 | __asm__ __volatile__( |
| 27 | "bne %0, %2, 1f \n\t" | 27 | " wsr %2, scompare1\n" |
| 28 | "s32i %3, %1, 0 \n\t" | 28 | " s32c1i %0, %1, 0\n" |
| 29 | "1: \n\t" | 29 | : "+a" (new) |
| 30 | "wsr a15, ps \n\t" | 30 | : "a" (p), "a" (old) |
| 31 | "rsync \n\t" | 31 | : "memory" |
| 32 | : "=&a" (old) | 32 | ); |
| 33 | : "a" (p), "a" (old), "r" (new) | 33 | |
| 34 | : "a15", "memory"); | 34 | return new; |
| 35 | return old; | 35 | #else |
| 36 | __asm__ __volatile__( | ||
| 37 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
| 38 | " l32i %0, %1, 0\n" | ||
| 39 | " bne %0, %2, 1f\n" | ||
| 40 | " s32i %3, %1, 0\n" | ||
| 41 | "1:\n" | ||
| 42 | " wsr a15, ps\n" | ||
| 43 | " rsync\n" | ||
| 44 | : "=&a" (old) | ||
| 45 | : "a" (p), "a" (old), "r" (new) | ||
| 46 | : "a15", "memory"); | ||
| 47 | return old; | ||
| 48 | #endif | ||
| 36 | } | 49 | } |
| 37 | /* This function doesn't exist, so you'll get a linker error | 50 | /* This function doesn't exist, so you'll get a linker error |
| 38 | * if something tries to do an invalid cmpxchg(). */ | 51 | * if something tries to do an invalid cmpxchg(). */ |
| @@ -93,19 +106,36 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, | |||
| 93 | 106 | ||
| 94 | static inline unsigned long xchg_u32(volatile int * m, unsigned long val) | 107 | static inline unsigned long xchg_u32(volatile int * m, unsigned long val) |
| 95 | { | 108 | { |
| 96 | unsigned long tmp; | 109 | #if XCHAL_HAVE_S32C1I |
| 97 | __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t" | 110 | unsigned long tmp, result; |
| 98 | "l32i %0, %1, 0 \n\t" | 111 | __asm__ __volatile__( |
| 99 | "s32i %2, %1, 0 \n\t" | 112 | "1: l32i %1, %2, 0\n" |
| 100 | "wsr a15, ps \n\t" | 113 | " mov %0, %3\n" |
| 101 | "rsync \n\t" | 114 | " wsr %1, scompare1\n" |
| 102 | : "=&a" (tmp) | 115 | " s32c1i %0, %2, 0\n" |
| 103 | : "a" (m), "a" (val) | 116 | " bne %0, %1, 1b\n" |
| 104 | : "a15", "memory"); | 117 | : "=&a" (result), "=&a" (tmp) |
| 105 | return tmp; | 118 | : "a" (m), "a" (val) |
| 119 | : "memory" | ||
| 120 | ); | ||
| 121 | return result; | ||
| 122 | #else | ||
| 123 | unsigned long tmp; | ||
| 124 | __asm__ __volatile__( | ||
| 125 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
| 126 | " l32i %0, %1, 0\n" | ||
| 127 | " s32i %2, %1, 0\n" | ||
| 128 | " wsr a15, ps\n" | ||
| 129 | " rsync\n" | ||
| 130 | : "=&a" (tmp) | ||
| 131 | : "a" (m), "a" (val) | ||
| 132 | : "a15", "memory"); | ||
| 133 | return tmp; | ||
| 134 | #endif | ||
| 106 | } | 135 | } |
| 107 | 136 | ||
| 108 | #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | 137 | #define xchg(ptr,x) \ |
| 138 | ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | ||
| 109 | 139 | ||
| 110 | /* | 140 | /* |
| 111 | * This only works if the compiler isn't horribly bad at optimizing. | 141 | * This only works if the compiler isn't horribly bad at optimizing. |
