Merge tag 'please-pull-sys_bpf' 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)                ((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), "bd" (i)                          \
65                 : "cc");                                                \
66                                                                         \
67         smp_mb();                                                       \
68                                                                         \
69         return result;                                                  \
70 }
71
72 #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op)
73
74 ATOMIC_OPS(add)
75 ATOMIC_OPS(sub)
76
77 #undef ATOMIC_OPS
78 #undef ATOMIC_OP_RETURN
79 #undef ATOMIC_OP
80
81 static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
82 {
83         int temp;
84
85         asm volatile (
86                 "1:     LNKGETD %0, [%1]\n"
87                 "       AND     %0, %0, %2\n"
88                 "       LNKSETD [%1] %0\n"
89                 "       DEFR    %0, TXSTAT\n"
90                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
91                 "       CMPT    %0, #HI(0x02000000)\n"
92                 "       BNZ     1b\n"
93                 : "=&d" (temp)
94                 : "da" (&v->counter), "bd" (~mask)
95                 : "cc");
96 }
97
98 static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
99 {
100         int temp;
101
102         asm volatile (
103                 "1:     LNKGETD %0, [%1]\n"
104                 "       OR      %0, %0, %2\n"
105                 "       LNKSETD [%1], %0\n"
106                 "       DEFR    %0, TXSTAT\n"
107                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
108                 "       CMPT    %0, #HI(0x02000000)\n"
109                 "       BNZ     1b\n"
110                 : "=&d" (temp)
111                 : "da" (&v->counter), "bd" (mask)
112                 : "cc");
113 }
114
115 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
116 {
117         int result, temp;
118
119         smp_mb();
120
121         asm volatile (
122                 "1:     LNKGETD %1, [%2]\n"
123                 "       CMP     %1, %3\n"
124                 "       LNKSETDEQ [%2], %4\n"
125                 "       BNE     2f\n"
126                 "       DEFR    %0, TXSTAT\n"
127                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
128                 "       CMPT    %0, #HI(0x02000000)\n"
129                 "       BNZ     1b\n"
130                 "2:\n"
131                 : "=&d" (temp), "=&d" (result)
132                 : "da" (&v->counter), "bd" (old), "da" (new)
133                 : "cc");
134
135         smp_mb();
136
137         return result;
138 }
139
140 static inline int atomic_xchg(atomic_t *v, int new)
141 {
142         int temp, old;
143
144         asm volatile (
145                 "1:     LNKGETD %1, [%2]\n"
146                 "       LNKSETD [%2], %3\n"
147                 "       DEFR    %0, TXSTAT\n"
148                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
149                 "       CMPT    %0, #HI(0x02000000)\n"
150                 "       BNZ     1b\n"
151                 : "=&d" (temp), "=&d" (old)
152                 : "da" (&v->counter), "da" (new)
153                 : "cc");
154
155         return old;
156 }
157
158 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
159 {
160         int result, temp;
161
162         smp_mb();
163
164         asm volatile (
165                 "1:     LNKGETD %1, [%2]\n"
166                 "       CMP     %1, %3\n"
167                 "       ADD     %0, %1, %4\n"
168                 "       LNKSETDNE [%2], %0\n"
169                 "       BEQ     2f\n"
170                 "       DEFR    %0, TXSTAT\n"
171                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
172                 "       CMPT    %0, #HI(0x02000000)\n"
173                 "       BNZ     1b\n"
174                 "2:\n"
175                 : "=&d" (temp), "=&d" (result)
176                 : "da" (&v->counter), "bd" (u), "bd" (a)
177                 : "cc");
178
179         smp_mb();
180
181         return result;
182 }
183
184 static inline int atomic_sub_if_positive(int i, atomic_t *v)
185 {
186         int result, temp;
187
188         asm volatile (
189                 "1:     LNKGETD %1, [%2]\n"
190                 "       SUBS    %1, %1, %3\n"
191                 "       LNKSETDGE [%2], %1\n"
192                 "       BLT     2f\n"
193                 "       DEFR    %0, TXSTAT\n"
194                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
195                 "       CMPT    %0, #HI(0x02000000)\n"
196                 "       BNZ     1b\n"
197                 "2:\n"
198                 : "=&d" (temp), "=&da" (result)
199                 : "da" (&v->counter), "bd" (i)
200                 : "cc");
201
202         return result;
203 }
204
205 #endif /* __ASM_METAG_ATOMIC_LNKGET_H */