]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/metag/include/asm/atomic_lnkget.h
Merge remote-tracking branch 'ext4/dev'
[karo-tx-linux.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), "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 ATOMIC_OP(and)
78 ATOMIC_OP(or)
79 ATOMIC_OP(xor)
80
81 #undef ATOMIC_OPS
82 #undef ATOMIC_OP_RETURN
83 #undef ATOMIC_OP
84
85 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
86 {
87         int result, temp;
88
89         smp_mb();
90
91         asm volatile (
92                 "1:     LNKGETD %1, [%2]\n"
93                 "       CMP     %1, %3\n"
94                 "       LNKSETDEQ [%2], %4\n"
95                 "       BNE     2f\n"
96                 "       DEFR    %0, TXSTAT\n"
97                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
98                 "       CMPT    %0, #HI(0x02000000)\n"
99                 "       BNZ     1b\n"
100                 "2:\n"
101                 : "=&d" (temp), "=&d" (result)
102                 : "da" (&v->counter), "bd" (old), "da" (new)
103                 : "cc");
104
105         smp_mb();
106
107         return result;
108 }
109
110 static inline int atomic_xchg(atomic_t *v, int new)
111 {
112         int temp, old;
113
114         asm volatile (
115                 "1:     LNKGETD %1, [%2]\n"
116                 "       LNKSETD [%2], %3\n"
117                 "       DEFR    %0, TXSTAT\n"
118                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
119                 "       CMPT    %0, #HI(0x02000000)\n"
120                 "       BNZ     1b\n"
121                 : "=&d" (temp), "=&d" (old)
122                 : "da" (&v->counter), "da" (new)
123                 : "cc");
124
125         return old;
126 }
127
128 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
129 {
130         int result, temp;
131
132         smp_mb();
133
134         asm volatile (
135                 "1:     LNKGETD %1, [%2]\n"
136                 "       CMP     %1, %3\n"
137                 "       ADD     %0, %1, %4\n"
138                 "       LNKSETDNE [%2], %0\n"
139                 "       BEQ     2f\n"
140                 "       DEFR    %0, TXSTAT\n"
141                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
142                 "       CMPT    %0, #HI(0x02000000)\n"
143                 "       BNZ     1b\n"
144                 "2:\n"
145                 : "=&d" (temp), "=&d" (result)
146                 : "da" (&v->counter), "bd" (u), "bd" (a)
147                 : "cc");
148
149         smp_mb();
150
151         return result;
152 }
153
154 static inline int atomic_sub_if_positive(int i, atomic_t *v)
155 {
156         int result, temp;
157
158         asm volatile (
159                 "1:     LNKGETD %1, [%2]\n"
160                 "       SUBS    %1, %1, %3\n"
161                 "       LNKSETDGE [%2], %1\n"
162                 "       BLT     2f\n"
163                 "       DEFR    %0, TXSTAT\n"
164                 "       ANDT    %0, %0, #HI(0x3f000000)\n"
165                 "       CMPT    %0, #HI(0x02000000)\n"
166                 "       BNZ     1b\n"
167                 "2:\n"
168                 : "=&d" (temp), "=&da" (result)
169                 : "da" (&v->counter), "bd" (i)
170                 : "cc");
171
172         return result;
173 }
174
175 #endif /* __ASM_METAG_ATOMIC_LNKGET_H */