blob: 4001d5eab4bb7f1fb59e6e62c924bd71b4b10e2f [file] [log] [blame]
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -04001/*
2 * cmpxchg.h -- forked from asm/atomic.h with this copyright:
3 *
4 * Copyright 2010 Tilera Corporation. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation, version 2.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13 * NON INFRINGEMENT. See the GNU General Public License for
14 * more details.
15 *
16 */
17
18#ifndef _ASM_TILE_CMPXCHG_H
19#define _ASM_TILE_CMPXCHG_H
20
21#ifndef __ASSEMBLY__
22
Chris Metcalf6dc96582013-09-06 08:56:45 -040023#include <asm/barrier.h>
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -040024
Chris Metcalf6dc96582013-09-06 08:56:45 -040025/* Nonexistent functions intended to cause compile errors. */
26extern void __xchg_called_with_bad_pointer(void)
27 __compiletime_error("Bad argument size for xchg");
28extern void __cmpxchg_called_with_bad_pointer(void)
29 __compiletime_error("Bad argument size for cmpxchg");
30
31#ifndef __tilegx__
32
33/* Note the _atomic_xxx() routines include a final mb(). */
34int _atomic_xchg(int *ptr, int n);
35int _atomic_xchg_add(int *v, int i);
36int _atomic_xchg_add_unless(int *v, int a, int u);
37int _atomic_cmpxchg(int *ptr, int o, int n);
38u64 _atomic64_xchg(u64 *v, u64 n);
39u64 _atomic64_xchg_add(u64 *v, u64 i);
40u64 _atomic64_xchg_add_unless(u64 *v, u64 a, u64 u);
41u64 _atomic64_cmpxchg(u64 *v, u64 o, u64 n);
42
43#define xchg(ptr, n) \
44 ({ \
45 if (sizeof(*(ptr)) != 4) \
46 __xchg_called_with_bad_pointer(); \
47 smp_mb(); \
48 (typeof(*(ptr)))_atomic_xchg((int *)(ptr), (int)(n)); \
49 })
50
51#define cmpxchg(ptr, o, n) \
52 ({ \
53 if (sizeof(*(ptr)) != 4) \
54 __cmpxchg_called_with_bad_pointer(); \
55 smp_mb(); \
56 (typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o, (int)n); \
57 })
58
59#define xchg64(ptr, n) \
60 ({ \
61 if (sizeof(*(ptr)) != 8) \
62 __xchg_called_with_bad_pointer(); \
63 smp_mb(); \
64 (typeof(*(ptr)))_atomic64_xchg((u64 *)(ptr), (u64)(n)); \
65 })
66
67#define cmpxchg64(ptr, o, n) \
68 ({ \
69 if (sizeof(*(ptr)) != 8) \
70 __cmpxchg_called_with_bad_pointer(); \
71 smp_mb(); \
72 (typeof(*(ptr)))_atomic64_cmpxchg((u64 *)ptr, (u64)o, (u64)n); \
73 })
74
75#else
76
77#define xchg(ptr, n) \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -040078 ({ \
79 typeof(*(ptr)) __x; \
Chris Metcalf6dc96582013-09-06 08:56:45 -040080 smp_mb(); \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -040081 switch (sizeof(*(ptr))) { \
82 case 4: \
Chris Metcalf6dc96582013-09-06 08:56:45 -040083 __x = (typeof(__x))(unsigned long) \
84 __insn_exch4((ptr), (u32)(unsigned long)(n)); \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -040085 break; \
86 case 8: \
Chris Metcalf6dc96582013-09-06 08:56:45 -040087 __x = (typeof(__x)) \
88 __insn_exch((ptr), (unsigned long)(n)); \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -040089 break; \
90 default: \
91 __xchg_called_with_bad_pointer(); \
Chris Metcalf6dc96582013-09-06 08:56:45 -040092 break; \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -040093 } \
Chris Metcalf6dc96582013-09-06 08:56:45 -040094 smp_mb(); \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -040095 __x; \
96 })
97
98#define cmpxchg(ptr, o, n) \
99 ({ \
100 typeof(*(ptr)) __x; \
Chris Metcalf6dc96582013-09-06 08:56:45 -0400101 __insn_mtspr(SPR_CMPEXCH_VALUE, (unsigned long)(o)); \
102 smp_mb(); \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -0400103 switch (sizeof(*(ptr))) { \
104 case 4: \
Chris Metcalf6dc96582013-09-06 08:56:45 -0400105 __x = (typeof(__x))(unsigned long) \
106 __insn_cmpexch4((ptr), (u32)(unsigned long)(n)); \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -0400107 break; \
108 case 8: \
Chris Metcalf6dc96582013-09-06 08:56:45 -0400109 __x = (typeof(__x))__insn_cmpexch((ptr), (u64)(n)); \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -0400110 break; \
111 default: \
112 __cmpxchg_called_with_bad_pointer(); \
Chris Metcalf6dc96582013-09-06 08:56:45 -0400113 break; \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -0400114 } \
Chris Metcalf6dc96582013-09-06 08:56:45 -0400115 smp_mb(); \
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -0400116 __x; \
117 })
118
Chris Metcalf6dc96582013-09-06 08:56:45 -0400119#define xchg64 xchg
120#define cmpxchg64 cmpxchg
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -0400121
Chris Metcalf6dc96582013-09-06 08:56:45 -0400122#endif
123
124#define tas(ptr) xchg((ptr), 1)
Chen Gangcf3a13d2013-07-01 10:21:51 +0800125
Paul Gortmaker34f2c0a2012-04-01 16:38:46 -0400126#endif /* __ASSEMBLY__ */
127
128#endif /* _ASM_TILE_CMPXCHG_H */