aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2012-11-10 18:30:02 -0500
committerChris Zankel <chris@zankel.net>2012-12-19 00:10:22 -0500
commit219b1e4c61c108731bb665962231b1fa057f6c71 (patch)
tree97ccb1c5069dea39b132086faf48607cf3b78cd3 /arch/xtensa
parent00273125c39be9cbf619aef90147354a9ed8c385 (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.h271
-rw-r--r--arch/xtensa/include/asm/cmpxchg.h71
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 */
67static inline void atomic_add(int i, atomic_t * v) 67static 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 */
91static inline void atomic_sub(int i, atomic_t *v) 107static 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
112static inline int atomic_add_return(int i, atomic_t * v) 144static 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
131static inline int atomic_sub_return(int i, atomic_t * v) 182static 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
252static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) 322static 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
271static inline void atomic_set_mask(unsigned int mask, atomic_t *v) 357static 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 @@
22static inline unsigned long 22static 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
94static inline unsigned long xchg_u32(volatile int * m, unsigned long val) 107static 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))))