aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-frv
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-frv')
-rw-r--r--include/asm-frv/atomic.h91
-rw-r--r--include/asm-frv/system.h70
2 files changed, 84 insertions, 77 deletions
diff --git a/include/asm-frv/atomic.h b/include/asm-frv/atomic.h
index 066386ac238e..d425d8d0ad77 100644
--- a/include/asm-frv/atomic.h
+++ b/include/asm-frv/atomic.h
@@ -16,6 +16,7 @@
16 16
17#include <linux/types.h> 17#include <linux/types.h>
18#include <asm/spr-regs.h> 18#include <asm/spr-regs.h>
19#include <asm/system.h>
19 20
20#ifdef CONFIG_SMP 21#ifdef CONFIG_SMP
21#error not SMP safe 22#error not SMP safe
@@ -258,85 +259,23 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
258 259
259#define tas(ptr) (xchg((ptr), 1)) 260#define tas(ptr) (xchg((ptr), 1))
260 261
261/*****************************************************************************/
262/*
263 * compare and conditionally exchange value with memory
264 * - if (*ptr == test) then orig = *ptr; *ptr = test;
265 * - if (*ptr != test) then orig = *ptr;
266 */
267#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
268
269#define cmpxchg(ptr, test, new) \
270({ \
271 __typeof__(ptr) __xg_ptr = (ptr); \
272 __typeof__(*(ptr)) __xg_orig, __xg_tmp; \
273 __typeof__(*(ptr)) __xg_test = (test); \
274 __typeof__(*(ptr)) __xg_new = (new); \
275 \
276 switch (sizeof(__xg_orig)) { \
277 case 4: \
278 asm volatile( \
279 "0: \n" \
280 " orcc gr0,gr0,gr0,icc3 \n" \
281 " ckeq icc3,cc7 \n" \
282 " ld.p %M0,%1 \n" \
283 " orcr cc7,cc7,cc3 \n" \
284 " sub%I4cc %1,%4,%2,icc0 \n" \
285 " bne icc0,#0,1f \n" \
286 " cst.p %3,%M0 ,cc3,#1 \n" \
287 " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
288 " beq icc3,#0,0b \n" \
289 "1: \n" \
290 : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp) \
291 : "r"(__xg_new), "NPr"(__xg_test) \
292 : "memory", "cc7", "cc3", "icc3", "icc0" \
293 ); \
294 break; \
295 \
296 default: \
297 __xg_orig = 0; \
298 asm volatile("break"); \
299 break; \
300 } \
301 \
302 __xg_orig; \
303})
304
305#else
306
307extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
308
309#define cmpxchg(ptr, test, new) \
310({ \
311 __typeof__(ptr) __xg_ptr = (ptr); \
312 __typeof__(*(ptr)) __xg_orig; \
313 __typeof__(*(ptr)) __xg_test = (test); \
314 __typeof__(*(ptr)) __xg_new = (new); \
315 \
316 switch (sizeof(__xg_orig)) { \
317 case 4: __xg_orig = __cmpxchg_32(__xg_ptr, __xg_test, __xg_new); break; \
318 default: \
319 __xg_orig = 0; \
320 asm volatile("break"); \
321 break; \
322 } \
323 \
324 __xg_orig; \
325})
326
327#endif
328
329#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new)) 262#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
330#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) 263#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
331 264
332#define atomic_add_unless(v, a, u) \ 265static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
333({ \ 266{
334 int c, old; \ 267 int c, old;
335 c = atomic_read(v); \ 268 c = atomic_read(v);
336 while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ 269 for (;;) {
337 c = old; \ 270 if (unlikely(c == (u)))
338 c != (u); \ 271 break;
339}) 272 old = atomic_cmpxchg((v), c, c + (a));
273 if (likely(old == c))
274 break;
275 c = old;
276 }
277 return c != (u);
278}
340 279
341#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) 280#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
342 281
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index 1166899317d7..be303b3eef40 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -13,7 +13,6 @@
13#define _ASM_SYSTEM_H 13#define _ASM_SYSTEM_H
14 14
15#include <linux/linkage.h> 15#include <linux/linkage.h>
16#include <asm/atomic.h>
17 16
18struct thread_struct; 17struct thread_struct;
19 18
@@ -197,4 +196,73 @@ extern void free_initmem(void);
197 196
198#define arch_align_stack(x) (x) 197#define arch_align_stack(x) (x)
199 198
199/*****************************************************************************/
200/*
201 * compare and conditionally exchange value with memory
202 * - if (*ptr == test) then orig = *ptr; *ptr = test;
203 * - if (*ptr != test) then orig = *ptr;
204 */
205#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
206
207#define cmpxchg(ptr, test, new) \
208({ \
209 __typeof__(ptr) __xg_ptr = (ptr); \
210 __typeof__(*(ptr)) __xg_orig, __xg_tmp; \
211 __typeof__(*(ptr)) __xg_test = (test); \
212 __typeof__(*(ptr)) __xg_new = (new); \
213 \
214 switch (sizeof(__xg_orig)) { \
215 case 4: \
216 asm volatile( \
217 "0: \n" \
218 " orcc gr0,gr0,gr0,icc3 \n" \
219 " ckeq icc3,cc7 \n" \
220 " ld.p %M0,%1 \n" \
221 " orcr cc7,cc7,cc3 \n" \
222 " sub%I4cc %1,%4,%2,icc0 \n" \
223 " bne icc0,#0,1f \n" \
224 " cst.p %3,%M0 ,cc3,#1 \n" \
225 " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
226 " beq icc3,#0,0b \n" \
227 "1: \n" \
228 : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp) \
229 : "r"(__xg_new), "NPr"(__xg_test) \
230 : "memory", "cc7", "cc3", "icc3", "icc0" \
231 ); \
232 break; \
233 \
234 default: \
235 __xg_orig = 0; \
236 asm volatile("break"); \
237 break; \
238 } \
239 \
240 __xg_orig; \
241})
242
243#else
244
245extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
246
247#define cmpxchg(ptr, test, new) \
248({ \
249 __typeof__(ptr) __xg_ptr = (ptr); \
250 __typeof__(*(ptr)) __xg_orig; \
251 __typeof__(*(ptr)) __xg_test = (test); \
252 __typeof__(*(ptr)) __xg_new = (new); \
253 \
254 switch (sizeof(__xg_orig)) { \
255 case 4: __xg_orig = __cmpxchg_32(__xg_ptr, __xg_test, __xg_new); break; \
256 default: \
257 __xg_orig = 0; \
258 asm volatile("break"); \
259 break; \
260 } \
261 \
262 __xg_orig; \
263})
264
265#endif
266
267
200#endif /* _ASM_SYSTEM_H */ 268#endif /* _ASM_SYSTEM_H */