Merge tag 'for-linus-4.8-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / metag / include / asm / atomic_lnkget.h
1 #ifndef __ASM_METAG_ATOMIC_LNKGET_H
2 #define __ASM_METAG_ATOMIC_LNKGET_H
3
4 #define ATOMIC_INIT(i)  { (i) }
5
6 #define atomic_set(v, i)                WRITE_ONCE((v)->counter, (i))
7
8 #include <linux/compiler.h>
9
10 #include <asm/barrier.h>
11
12 /*
13  * None of these asm statements clobber memory as LNKSET writes around
14  * the cache so the memory it modifies cannot safely be read by any means
15  * other than these accessors.
16  */
17
18 static inline int atomic_read(const atomic_t *v)
19 {
20         int temp;
21
22         asm volatile (
23                 "LNKGETD %0, [%1]\n"
24                 : "=da" (temp)
25                 : "da" (&v->counter));
26
27         return temp;
28 }
29
30 #define ATOMIC_OP(op)                                                   \
31 static inline void atomic_##op(int i, atomic_t *v)                      \
32 {                                                                       \
33         int temp;                                                       \
34                                                                         \
35         asm volatile (                                                  \
36                 "1:     LNKGETD %0, [%1]\n"                             \
37                 "       " #op " %0, %0, %2\n"                           \
38                 "       LNKSETD [%1], %0\n"                             \
39                 "       DEFR    %0, TXSTAT\n"                           \
40                 "       ANDT    %0, %0, #HI(0x3f000000)\n"              \
41                 "       CMPT    %0, #HI(0x02000000)\n"                  \
42                 "       BNZ     1b\n"                                   \
43                 : "=&d" (temp)                                          \
44                 : "da" (&v->counter), "bd" (i)                          \
45                 : "cc");                                                \
46 }                                                                       \
47
48 #define ATOMIC_OP_RETURN(op)                                            \
49 static inline int atomic_##op##_return(int i, atomic_t *v)              \
50 {                                                                       \
51         int result, temp;                                               \
52                                                                         \
53         smp_mb();                                                       \
54                                                                         \
55         asm volatile (                                                  \
56                 "1:     LNKGETD %1, [%2]\n"                             \
57                 "       " #op " %1, %1, %3\n"                           \
58                 "       LNKSETD [%2], %1\n"                             \
59                 "       DEFR    %0, TXSTAT\n"                           \
60                 "       ANDT    %0, %0, #HI(0x3f000000)\n"              \
61                 "       CMPT    %0, #HI(0x02000000)\n"                  \
62                 "       BNZ 1b\n"                                       \
63                 : "=&d" (temp), "=&da" (result)                         \
64                 : "da" (&v->counter), "br" (i)                          \
65                 : "cc");                                                \
66                                                                         \
67         smp_mb();                                                       \
68                                                                         \
69         return result;                                                  \
70 }
71
72 #define ATOMIC_FETCH_OP(op)                                             \
73 static inline int atomic_fetch_##op(int i, atomic_t *v)                 \
74 {                                                                       \
75         int result, temp;                                               \
76                                                                         \
77         smp_mb();                                                       \
78                                                                         \
79         asm volatile (                                                  \
80                 "1:     LNKGETD %1, [%2]\n"                             \
81                 "       " #op " %0, %1, %3\n"                           \
82                 "       LNKSETD [%2], %0\n"                             \
83                 "       DEFR    %0, TXSTAT\n"                           \
84                 "       ANDT    %0, %0, #HI(0x3f000000)\n"              \
85                 "       CMPT    %0, #HI(0x02000000)\n"                  \
86                 "       BNZ 1b\n"                                       \
87                 : "=&d" (temp), "=&d" (result)                          \
88                 : "da" (&v->counter), "bd" (i)                          \
89                 : "cc");                                                \
90                                                                         \
91         smp_mb();                                                       \
92                                                                         \
93         return result;                                                  \
94 }
95
96 #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) ATOMIC_FETCH_OP(op)
97
98 ATOMIC_OPS(add)
99 ATOMIC_OPS(sub)
100
101 #undef ATOMIC_OPS
102 #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op)
103
104 ATOMIC_OPS(and)
105 ATOMIC_OPS(or)
106 ATOMIC_OPS(xor)
107
108 #undef ATOMIC_OPS
109 #undef ATOMIC_FETCH_OP
110 #undef ATOMIC_OP_RETURN
111 #undef ATOMIC_OP
112
113 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
114 {
115         int result, temp;
116
117         smp_mb();
118
119         asm volatile (
120                 "1:     LNKGETD %1, [%2]\n"
121                 "       CMP     %1, %3\n"
122                 "       LNKSETDEQ [%2], %4\n"
123                 "       BNE     2f\n"
124                 "       DEFR    %0, TXSTAT\n"
125                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
126                 "       CMPT    %0, #HI(0x02000000)\n"
127                 "       BNZ     1b\n"
128                 "2:\n"
129                 : "=&d" (temp), "=&d" (result)
130                 : "da" (&v->counter), "bd" (old), "da" (new)
131                 : "cc");
132
133         smp_mb();
134
135         return result;
136 }
137
138 static inline int atomic_xchg(atomic_t *v, int new)
139 {
140         int temp, old;
141
142         asm volatile (
143                 "1:     LNKGETD %1, [%2]\n"
144                 "       LNKSETD [%2], %3\n"
145                 "       DEFR    %0, TXSTAT\n"
146                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
147                 "       CMPT    %0, #HI(0x02000000)\n"
148                 "       BNZ     1b\n"
149                 : "=&d" (temp), "=&d" (old)
150                 : "da" (&v->counter), "da" (new)
151                 : "cc");
152
153         return old;
154 }
155
156 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
157 {
158         int result, temp;
159
160         smp_mb();
161
162         asm volatile (
163                 "1:     LNKGETD %1, [%2]\n"
164                 "       CMP     %1, %3\n"
165                 "       ADD     %0, %1, %4\n"
166                 "       LNKSETDNE [%2], %0\n"
167                 "       BEQ     2f\n"
168                 "       DEFR    %0, TXSTAT\n"
169                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
170                 "       CMPT    %0, #HI(0x02000000)\n"
171                 "       BNZ     1b\n"
172                 "2:\n"
173                 : "=&d" (temp), "=&d" (result)
174                 : "da" (&v->counter), "bd" (u), "bd" (a)
175                 : "cc");
176
177         smp_mb();
178
179         return result;
180 }
181
182 static inline int atomic_sub_if_positive(int i, atomic_t *v)
183 {
184         int result, temp;
185
186         asm volatile (
187                 "1:     LNKGETD %1, [%2]\n"
188                 "       SUBS    %1, %1, %3\n"
189                 "       LNKSETDGE [%2], %1\n"
190                 "       BLT     2f\n"
191                 "       DEFR    %0, TXSTAT\n"
192                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
193                 "       CMPT    %0, #HI(0x02000000)\n"
194                 "       BNZ     1b\n"
195                 "2:\n"
196                 : "=&d" (temp), "=&da" (result)
197                 : "da" (&v->counter), "bd" (i)
198                 : "cc");
199
200         return result;
201 }
202
203 #endif /* __ASM_METAG_ATOMIC_LNKGET_H */