.. | .. |
---|
13 | 13 | |
---|
14 | 14 | #ifndef __ASSEMBLY__ |
---|
15 | 15 | |
---|
| 16 | +#include <linux/bits.h> |
---|
16 | 17 | #include <linux/stringify.h> |
---|
17 | 18 | |
---|
18 | 19 | /* |
---|
.. | .. |
---|
22 | 23 | static inline unsigned long |
---|
23 | 24 | __cmpxchg_u32(volatile int *p, int old, int new) |
---|
24 | 25 | { |
---|
25 | | -#if XCHAL_HAVE_S32C1I |
---|
| 26 | +#if XCHAL_HAVE_EXCLUSIVE |
---|
| 27 | + unsigned long tmp, result; |
---|
| 28 | + |
---|
26 | 29 | __asm__ __volatile__( |
---|
27 | | - " wsr %2, scompare1\n" |
---|
28 | | - " s32c1i %0, %1, 0\n" |
---|
29 | | - : "+a" (new) |
---|
30 | | - : "a" (p), "a" (old) |
---|
| 30 | + "1: l32ex %[result], %[addr]\n" |
---|
| 31 | + " bne %[result], %[cmp], 2f\n" |
---|
| 32 | + " mov %[tmp], %[new]\n" |
---|
| 33 | + " s32ex %[tmp], %[addr]\n" |
---|
| 34 | + " getex %[tmp]\n" |
---|
| 35 | + " beqz %[tmp], 1b\n" |
---|
| 36 | + "2:\n" |
---|
| 37 | + : [result] "=&a" (result), [tmp] "=&a" (tmp) |
---|
| 38 | + : [new] "a" (new), [addr] "a" (p), [cmp] "a" (old) |
---|
| 39 | + : "memory" |
---|
| 40 | + ); |
---|
| 41 | + |
---|
| 42 | + return result; |
---|
| 43 | +#elif XCHAL_HAVE_S32C1I |
---|
| 44 | + __asm__ __volatile__( |
---|
| 45 | + " wsr %[cmp], scompare1\n" |
---|
| 46 | + " s32c1i %[new], %[mem]\n" |
---|
| 47 | + : [new] "+a" (new), [mem] "+m" (*p) |
---|
| 48 | + : [cmp] "a" (old) |
---|
31 | 49 | : "memory" |
---|
32 | 50 | ); |
---|
33 | 51 | |
---|
.. | .. |
---|
35 | 53 | #else |
---|
36 | 54 | __asm__ __volatile__( |
---|
37 | 55 | " rsil a15, "__stringify(TOPLEVEL)"\n" |
---|
38 | | - " l32i %0, %1, 0\n" |
---|
39 | | - " bne %0, %2, 1f\n" |
---|
40 | | - " s32i %3, %1, 0\n" |
---|
| 56 | + " l32i %[old], %[mem]\n" |
---|
| 57 | + " bne %[old], %[cmp], 1f\n" |
---|
| 58 | + " s32i %[new], %[mem]\n" |
---|
41 | 59 | "1:\n" |
---|
42 | 60 | " wsr a15, ps\n" |
---|
43 | 61 | " rsync\n" |
---|
44 | | - : "=&a" (old) |
---|
45 | | - : "a" (p), "a" (old), "r" (new) |
---|
| 62 | + : [old] "=&a" (old), [mem] "+m" (*p) |
---|
| 63 | + : [cmp] "a" (old), [new] "r" (new) |
---|
46 | 64 | : "a15", "memory"); |
---|
47 | 65 | return old; |
---|
48 | 66 | #endif |
---|
.. | .. |
---|
107 | 125 | |
---|
108 | 126 | static inline unsigned long xchg_u32(volatile int * m, unsigned long val) |
---|
109 | 127 | { |
---|
110 | | -#if XCHAL_HAVE_S32C1I |
---|
| 128 | +#if XCHAL_HAVE_EXCLUSIVE |
---|
| 129 | + unsigned long tmp, result; |
---|
| 130 | + |
---|
| 131 | + __asm__ __volatile__( |
---|
| 132 | + "1: l32ex %[result], %[addr]\n" |
---|
| 133 | + " mov %[tmp], %[val]\n" |
---|
| 134 | + " s32ex %[tmp], %[addr]\n" |
---|
| 135 | + " getex %[tmp]\n" |
---|
| 136 | + " beqz %[tmp], 1b\n" |
---|
| 137 | + : [result] "=&a" (result), [tmp] "=&a" (tmp) |
---|
| 138 | + : [val] "a" (val), [addr] "a" (m) |
---|
| 139 | + : "memory" |
---|
| 140 | + ); |
---|
| 141 | + |
---|
| 142 | + return result; |
---|
| 143 | +#elif XCHAL_HAVE_S32C1I |
---|
111 | 144 | unsigned long tmp, result; |
---|
112 | 145 | __asm__ __volatile__( |
---|
113 | | - "1: l32i %1, %2, 0\n" |
---|
114 | | - " mov %0, %3\n" |
---|
115 | | - " wsr %1, scompare1\n" |
---|
116 | | - " s32c1i %0, %2, 0\n" |
---|
117 | | - " bne %0, %1, 1b\n" |
---|
118 | | - : "=&a" (result), "=&a" (tmp) |
---|
119 | | - : "a" (m), "a" (val) |
---|
| 146 | + "1: l32i %[tmp], %[mem]\n" |
---|
| 147 | + " mov %[result], %[val]\n" |
---|
| 148 | + " wsr %[tmp], scompare1\n" |
---|
| 149 | + " s32c1i %[result], %[mem]\n" |
---|
| 150 | + " bne %[result], %[tmp], 1b\n" |
---|
| 151 | + : [result] "=&a" (result), [tmp] "=&a" (tmp), |
---|
| 152 | + [mem] "+m" (*m) |
---|
| 153 | + : [val] "a" (val) |
---|
120 | 154 | : "memory" |
---|
121 | 155 | ); |
---|
122 | 156 | return result; |
---|
.. | .. |
---|
124 | 158 | unsigned long tmp; |
---|
125 | 159 | __asm__ __volatile__( |
---|
126 | 160 | " rsil a15, "__stringify(TOPLEVEL)"\n" |
---|
127 | | - " l32i %0, %1, 0\n" |
---|
128 | | - " s32i %2, %1, 0\n" |
---|
| 161 | + " l32i %[tmp], %[mem]\n" |
---|
| 162 | + " s32i %[val], %[mem]\n" |
---|
129 | 163 | " wsr a15, ps\n" |
---|
130 | 164 | " rsync\n" |
---|
131 | | - : "=&a" (tmp) |
---|
132 | | - : "a" (m), "a" (val) |
---|
| 165 | + : [tmp] "=&a" (tmp), [mem] "+m" (*m) |
---|
| 166 | + : [val] "a" (val) |
---|
133 | 167 | : "a15", "memory"); |
---|
134 | 168 | return tmp; |
---|
135 | 169 | #endif |
---|
.. | .. |
---|
137 | 171 | |
---|
138 | 172 | #define xchg(ptr,x) \ |
---|
139 | 173 | ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) |
---|
| 174 | + |
---|
| 175 | +static inline u32 xchg_small(volatile void *ptr, u32 x, int size) |
---|
| 176 | +{ |
---|
| 177 | + int off = (unsigned long)ptr % sizeof(u32); |
---|
| 178 | + volatile u32 *p = ptr - off; |
---|
| 179 | +#ifdef __BIG_ENDIAN |
---|
| 180 | + int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE; |
---|
| 181 | +#else |
---|
| 182 | + int bitoff = off * BITS_PER_BYTE; |
---|
| 183 | +#endif |
---|
| 184 | + u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff; |
---|
| 185 | + u32 oldv, newv; |
---|
| 186 | + u32 ret; |
---|
| 187 | + |
---|
| 188 | + do { |
---|
| 189 | + oldv = READ_ONCE(*p); |
---|
| 190 | + ret = (oldv & bitmask) >> bitoff; |
---|
| 191 | + newv = (oldv & ~bitmask) | (x << bitoff); |
---|
| 192 | + } while (__cmpxchg_u32(p, oldv, newv) != oldv); |
---|
| 193 | + |
---|
| 194 | + return ret; |
---|
| 195 | +} |
---|
140 | 196 | |
---|
141 | 197 | /* |
---|
142 | 198 | * This only works if the compiler isn't horribly bad at optimizing. |
---|
.. | .. |
---|
150 | 206 | __xchg(unsigned long x, volatile void * ptr, int size) |
---|
151 | 207 | { |
---|
152 | 208 | switch (size) { |
---|
153 | | - case 4: |
---|
154 | | - return xchg_u32(ptr, x); |
---|
| 209 | + case 1: |
---|
| 210 | + return xchg_small(ptr, x, 1); |
---|
| 211 | + case 2: |
---|
| 212 | + return xchg_small(ptr, x, 2); |
---|
| 213 | + case 4: |
---|
| 214 | + return xchg_u32(ptr, x); |
---|
| 215 | + default: |
---|
| 216 | + __xchg_called_with_bad_pointer(); |
---|
| 217 | + return x; |
---|
155 | 218 | } |
---|
156 | | - __xchg_called_with_bad_pointer(); |
---|
157 | | - return x; |
---|
158 | 219 | } |
---|
159 | 220 | |
---|
160 | 221 | #endif /* __ASSEMBLY__ */ |
---|