diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2012-11-10 18:30:02 -0500 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2012-12-19 00:10:22 -0500 |
commit | 219b1e4c61c108731bb665962231b1fa057f6c71 (patch) | |
tree | 97ccb1c5069dea39b132086faf48607cf3b78cd3 /arch/xtensa | |
parent | 00273125c39be9cbf619aef90147354a9ed8c385 (diff) |
xtensa: add s32c1i-based atomic ops implementations
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa')
-rw-r--r-- | arch/xtensa/include/asm/atomic.h | 271 | ||||
-rw-r--r-- | arch/xtensa/include/asm/cmpxchg.h | 71 |
2 files changed, 236 insertions, 106 deletions
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index 24f50cada70c..c3f289174c10 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h | |||
@@ -66,19 +66,35 @@ | |||
66 | */ | 66 | */ |
67 | static inline void atomic_add(int i, atomic_t * v) | 67 | static inline void atomic_add(int i, atomic_t * v) |
68 | { | 68 | { |
69 | unsigned int vval; | 69 | #if XCHAL_HAVE_S32C1I |
70 | 70 | unsigned long tmp; | |
71 | __asm__ __volatile__( | 71 | int result; |
72 | "rsil a15, "__stringify(LOCKLEVEL)"\n\t" | 72 | |
73 | "l32i %0, %2, 0 \n\t" | 73 | __asm__ __volatile__( |
74 | "add %0, %0, %1 \n\t" | 74 | "1: l32i %1, %3, 0\n" |
75 | "s32i %0, %2, 0 \n\t" | 75 | " wsr %1, scompare1\n" |
76 | "wsr a15, ps \n\t" | 76 | " add %0, %1, %2\n" |
77 | "rsync \n" | 77 | " s32c1i %0, %3, 0\n" |
78 | : "=&a" (vval) | 78 | " bne %0, %1, 1b\n" |
79 | : "a" (i), "a" (v) | 79 | : "=&a" (result), "=&a" (tmp) |
80 | : "a15", "memory" | 80 | : "a" (i), "a" (v) |
81 | ); | 81 | : "memory" |
82 | ); | ||
83 | #else | ||
84 | unsigned int vval; | ||
85 | |||
86 | __asm__ __volatile__( | ||
87 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
88 | " l32i %0, %2, 0\n" | ||
89 | " add %0, %0, %1\n" | ||
90 | " s32i %0, %2, 0\n" | ||
91 | " wsr a15, ps\n" | ||
92 | " rsync\n" | ||
93 | : "=&a" (vval) | ||
94 | : "a" (i), "a" (v) | ||
95 | : "a15", "memory" | ||
96 | ); | ||
97 | #endif | ||
82 | } | 98 | } |
83 | 99 | ||
84 | /** | 100 | /** |
@@ -90,19 +106,35 @@ static inline void atomic_add(int i, atomic_t * v) | |||
90 | */ | 106 | */ |
91 | static inline void atomic_sub(int i, atomic_t *v) | 107 | static inline void atomic_sub(int i, atomic_t *v) |
92 | { | 108 | { |
93 | unsigned int vval; | 109 | #if XCHAL_HAVE_S32C1I |
94 | 110 | unsigned long tmp; | |
95 | __asm__ __volatile__( | 111 | int result; |
96 | "rsil a15, "__stringify(LOCKLEVEL)"\n\t" | 112 | |
97 | "l32i %0, %2, 0 \n\t" | 113 | __asm__ __volatile__( |
98 | "sub %0, %0, %1 \n\t" | 114 | "1: l32i %1, %3, 0\n" |
99 | "s32i %0, %2, 0 \n\t" | 115 | " wsr %1, scompare1\n" |
100 | "wsr a15, ps \n\t" | 116 | " sub %0, %1, %2\n" |
101 | "rsync \n" | 117 | " s32c1i %0, %3, 0\n" |
102 | : "=&a" (vval) | 118 | " bne %0, %1, 1b\n" |
103 | : "a" (i), "a" (v) | 119 | : "=&a" (result), "=&a" (tmp) |
104 | : "a15", "memory" | 120 | : "a" (i), "a" (v) |
105 | ); | 121 | : "memory" |
122 | ); | ||
123 | #else | ||
124 | unsigned int vval; | ||
125 | |||
126 | __asm__ __volatile__( | ||
127 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
128 | " l32i %0, %2, 0\n" | ||
129 | " sub %0, %0, %1\n" | ||
130 | " s32i %0, %2, 0\n" | ||
131 | " wsr a15, ps\n" | ||
132 | " rsync\n" | ||
133 | : "=&a" (vval) | ||
134 | : "a" (i), "a" (v) | ||
135 | : "a15", "memory" | ||
136 | ); | ||
137 | #endif | ||
106 | } | 138 | } |
107 | 139 | ||
108 | /* | 140 | /* |
@@ -111,40 +143,78 @@ static inline void atomic_sub(int i, atomic_t *v) | |||
111 | 143 | ||
112 | static inline int atomic_add_return(int i, atomic_t * v) | 144 | static inline int atomic_add_return(int i, atomic_t * v) |
113 | { | 145 | { |
114 | unsigned int vval; | 146 | #if XCHAL_HAVE_S32C1I |
115 | 147 | unsigned long tmp; | |
116 | __asm__ __volatile__( | 148 | int result; |
117 | "rsil a15,"__stringify(LOCKLEVEL)"\n\t" | 149 | |
118 | "l32i %0, %2, 0 \n\t" | 150 | __asm__ __volatile__( |
119 | "add %0, %0, %1 \n\t" | 151 | "1: l32i %1, %3, 0\n" |
120 | "s32i %0, %2, 0 \n\t" | 152 | " wsr %1, scompare1\n" |
121 | "wsr a15, ps \n\t" | 153 | " add %0, %1, %2\n" |
122 | "rsync \n" | 154 | " s32c1i %0, %3, 0\n" |
123 | : "=&a" (vval) | 155 | " bne %0, %1, 1b\n" |
124 | : "a" (i), "a" (v) | 156 | " add %0, %0, %2\n" |
125 | : "a15", "memory" | 157 | : "=&a" (result), "=&a" (tmp) |
126 | ); | 158 | : "a" (i), "a" (v) |
127 | 159 | : "memory" | |
128 | return vval; | 160 | ); |
161 | |||
162 | return result; | ||
163 | #else | ||
164 | unsigned int vval; | ||
165 | |||
166 | __asm__ __volatile__( | ||
167 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
168 | " l32i %0, %2, 0\n" | ||
169 | " add %0, %0, %1\n" | ||
170 | " s32i %0, %2, 0\n" | ||
171 | " wsr a15, ps\n" | ||
172 | " rsync\n" | ||
173 | : "=&a" (vval) | ||
174 | : "a" (i), "a" (v) | ||
175 | : "a15", "memory" | ||
176 | ); | ||
177 | |||
178 | return vval; | ||
179 | #endif | ||
129 | } | 180 | } |
130 | 181 | ||
131 | static inline int atomic_sub_return(int i, atomic_t * v) | 182 | static inline int atomic_sub_return(int i, atomic_t * v) |
132 | { | 183 | { |
133 | unsigned int vval; | 184 | #if XCHAL_HAVE_S32C1I |
134 | 185 | unsigned long tmp; | |
135 | __asm__ __volatile__( | 186 | int result; |
136 | "rsil a15,"__stringify(LOCKLEVEL)"\n\t" | 187 | |
137 | "l32i %0, %2, 0 \n\t" | 188 | __asm__ __volatile__( |
138 | "sub %0, %0, %1 \n\t" | 189 | "1: l32i %1, %3, 0\n" |
139 | "s32i %0, %2, 0 \n\t" | 190 | " wsr %1, scompare1\n" |
140 | "wsr a15, ps \n\t" | 191 | " sub %0, %1, %2\n" |
141 | "rsync \n" | 192 | " s32c1i %0, %3, 0\n" |
142 | : "=&a" (vval) | 193 | " bne %0, %1, 1b\n" |
143 | : "a" (i), "a" (v) | 194 | " sub %0, %0, %2\n" |
144 | : "a15", "memory" | 195 | : "=&a" (result), "=&a" (tmp) |
145 | ); | 196 | : "a" (i), "a" (v) |
146 | 197 | : "memory" | |
147 | return vval; | 198 | ); |
199 | |||
200 | return result; | ||
201 | #else | ||
202 | unsigned int vval; | ||
203 | |||
204 | __asm__ __volatile__( | ||
205 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
206 | " l32i %0, %2, 0\n" | ||
207 | " sub %0, %0, %1\n" | ||
208 | " s32i %0, %2, 0\n" | ||
209 | " wsr a15, ps\n" | ||
210 | " rsync\n" | ||
211 | : "=&a" (vval) | ||
212 | : "a" (i), "a" (v) | ||
213 | : "a15", "memory" | ||
214 | ); | ||
215 | |||
216 | return vval; | ||
217 | #endif | ||
148 | } | 218 | } |
149 | 219 | ||
150 | /** | 220 | /** |
@@ -251,38 +321,70 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) | |||
251 | 321 | ||
252 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | 322 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
253 | { | 323 | { |
254 | unsigned int all_f = -1; | 324 | #if XCHAL_HAVE_S32C1I |
255 | unsigned int vval; | 325 | unsigned long tmp; |
256 | 326 | int result; | |
257 | __asm__ __volatile__( | 327 | |
258 | "rsil a15,"__stringify(LOCKLEVEL)"\n\t" | 328 | __asm__ __volatile__( |
259 | "l32i %0, %2, 0 \n\t" | 329 | "1: l32i %1, %3, 0\n" |
260 | "xor %1, %4, %3 \n\t" | 330 | " wsr %1, scompare1\n" |
261 | "and %0, %0, %4 \n\t" | 331 | " and %0, %1, %2\n" |
262 | "s32i %0, %2, 0 \n\t" | 332 | " s32c1i %0, %3, 0\n" |
263 | "wsr a15, ps \n\t" | 333 | " bne %0, %1, 1b\n" |
264 | "rsync \n" | 334 | : "=&a" (result), "=&a" (tmp) |
265 | : "=&a" (vval), "=a" (mask) | 335 | : "a" (~mask), "a" (v) |
266 | : "a" (v), "a" (all_f), "1" (mask) | 336 | : "memory" |
267 | : "a15", "memory" | 337 | ); |
268 | ); | 338 | #else |
339 | unsigned int all_f = -1; | ||
340 | unsigned int vval; | ||
341 | |||
342 | __asm__ __volatile__( | ||
343 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
344 | " l32i %0, %2, 0\n" | ||
345 | " xor %1, %4, %3\n" | ||
346 | " and %0, %0, %4\n" | ||
347 | " s32i %0, %2, 0\n" | ||
348 | " wsr a15, ps\n" | ||
349 | " rsync\n" | ||
350 | : "=&a" (vval), "=a" (mask) | ||
351 | : "a" (v), "a" (all_f), "1" (mask) | ||
352 | : "a15", "memory" | ||
353 | ); | ||
354 | #endif | ||
269 | } | 355 | } |
270 | 356 | ||
271 | static inline void atomic_set_mask(unsigned int mask, atomic_t *v) | 357 | static inline void atomic_set_mask(unsigned int mask, atomic_t *v) |
272 | { | 358 | { |
273 | unsigned int vval; | 359 | #if XCHAL_HAVE_S32C1I |
274 | 360 | unsigned long tmp; | |
275 | __asm__ __volatile__( | 361 | int result; |
276 | "rsil a15,"__stringify(LOCKLEVEL)"\n\t" | 362 | |
277 | "l32i %0, %2, 0 \n\t" | 363 | __asm__ __volatile__( |
278 | "or %0, %0, %1 \n\t" | 364 | "1: l32i %1, %3, 0\n" |
279 | "s32i %0, %2, 0 \n\t" | 365 | " wsr %1, scompare1\n" |
280 | "wsr a15, ps \n\t" | 366 | " or %0, %1, %2\n" |
281 | "rsync \n" | 367 | " s32c1i %0, %3, 0\n" |
282 | : "=&a" (vval) | 368 | " bne %0, %1, 1b\n" |
283 | : "a" (mask), "a" (v) | 369 | : "=&a" (result), "=&a" (tmp) |
284 | : "a15", "memory" | 370 | : "a" (mask), "a" (v) |
285 | ); | 371 | : "memory" |
372 | ); | ||
373 | #else | ||
374 | unsigned int vval; | ||
375 | |||
376 | __asm__ __volatile__( | ||
377 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
378 | " l32i %0, %2, 0\n" | ||
379 | " or %0, %0, %1\n" | ||
380 | " s32i %0, %2, 0\n" | ||
381 | " wsr a15, ps\n" | ||
382 | " rsync\n" | ||
383 | : "=&a" (vval) | ||
384 | : "a" (mask), "a" (v) | ||
385 | : "a15", "memory" | ||
386 | ); | ||
387 | #endif | ||
286 | } | 388 | } |
287 | 389 | ||
288 | /* Atomic operations are already serializing */ | 390 | /* Atomic operations are already serializing */ |
@@ -294,4 +396,3 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v) | |||
294 | #endif /* __KERNEL__ */ | 396 | #endif /* __KERNEL__ */ |
295 | 397 | ||
296 | #endif /* _XTENSA_ATOMIC_H */ | 398 | #endif /* _XTENSA_ATOMIC_H */ |
297 | |||
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h index 64dad04a9d27..25869a190490 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,16 +106,32 @@ 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) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) |