Commit | Line | Data |
---|---|---|
6006c0d8 JH |
1 | #ifndef __ASM_METAG_ATOMIC_LNKGET_H |
2 | #define __ASM_METAG_ATOMIC_LNKGET_H | |
3 | ||
4 | #define ATOMIC_INIT(i) { (i) } | |
5 | ||
62e8a325 | 6 | #define atomic_set(v, i) WRITE_ONCE((v)->counter, (i)) |
6006c0d8 JH |
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 | ||
d6dfe250 PZ |
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) \ | |
096a8b6d | 64 | : "da" (&v->counter), "br" (i) \ |
d6dfe250 PZ |
65 | : "cc"); \ |
66 | \ | |
67 | smp_mb(); \ | |
68 | \ | |
69 | return result; \ | |
6006c0d8 JH |
70 | } |
71 | ||
d6dfe250 | 72 | #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) |
6006c0d8 | 73 | |
d6dfe250 PZ |
74 | ATOMIC_OPS(add) |
75 | ATOMIC_OPS(sub) | |
6006c0d8 | 76 | |
5b4a2f0f PZ |
77 | ATOMIC_OP(and) |
78 | ATOMIC_OP(or) | |
79 | ATOMIC_OP(xor) | |
80 | ||
d6dfe250 PZ |
81 | #undef ATOMIC_OPS |
82 | #undef ATOMIC_OP_RETURN | |
83 | #undef ATOMIC_OP | |
6006c0d8 | 84 | |
6006c0d8 JH |
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 */ |