1#ifndef __M32R_LOCAL_H
2#define __M32R_LOCAL_H
3
4
5
6
7
8
9
10
11
12
13#include <linux/percpu.h>
14#include <asm/assembler.h>
15#include <asm/local.h>
16
17
18
19
20
21
22
23
24
25
26
27typedef struct { volatile int counter; } local_t;
28
29#define LOCAL_INIT(i) { (i) }
30
31
32
33
34
35
36
37#define local_read(l) ((l)->counter)
38
39
40
41
42
43
44
45
46#define local_set(l, i) (((l)->counter) = (i))
47
48
49
50
51
52
53
54
55static inline long local_add_return(long i, local_t *l)
56{
57 unsigned long flags;
58 long result;
59
60 local_irq_save(flags);
61 __asm__ __volatile__ (
62 "# local_add_return \n\t"
63 DCACHE_CLEAR("%0", "r4", "%1")
64 "ld %0, @%1; \n\t"
65 "add %0, %2; \n\t"
66 "st %0, @%1; \n\t"
67 : "=&r" (result)
68 : "r" (&l->counter), "r" (i)
69 : "memory"
70#ifdef CONFIG_CHIP_M32700_TS1
71 , "r4"
72#endif
73 );
74 local_irq_restore(flags);
75
76 return result;
77}
78
79
80
81
82
83
84
85
86static inline long local_sub_return(long i, local_t *l)
87{
88 unsigned long flags;
89 long result;
90
91 local_irq_save(flags);
92 __asm__ __volatile__ (
93 "# local_sub_return \n\t"
94 DCACHE_CLEAR("%0", "r4", "%1")
95 "ld %0, @%1; \n\t"
96 "sub %0, %2; \n\t"
97 "st %0, @%1; \n\t"
98 : "=&r" (result)
99 : "r" (&l->counter), "r" (i)
100 : "memory"
101#ifdef CONFIG_CHIP_M32700_TS1
102 , "r4"
103#endif
104 );
105 local_irq_restore(flags);
106
107 return result;
108}
109
110
111
112
113
114
115
116
117#define local_add(i, l) ((void) local_add_return((i), (l)))
118
119
120
121
122
123
124
125
126#define local_sub(i, l) ((void) local_sub_return((i), (l)))
127
128
129
130
131
132
133
134
135
136
137#define local_sub_and_test(i, l) (local_sub_return((i), (l)) == 0)
138
139
140
141
142
143
144
145static inline long local_inc_return(local_t *l)
146{
147 unsigned long flags;
148 long result;
149
150 local_irq_save(flags);
151 __asm__ __volatile__ (
152 "# local_inc_return \n\t"
153 DCACHE_CLEAR("%0", "r4", "%1")
154 "ld %0, @%1; \n\t"
155 "addi %0, #1; \n\t"
156 "st %0, @%1; \n\t"
157 : "=&r" (result)
158 : "r" (&l->counter)
159 : "memory"
160#ifdef CONFIG_CHIP_M32700_TS1
161 , "r4"
162#endif
163 );
164 local_irq_restore(flags);
165
166 return result;
167}
168
169
170
171
172
173
174
175static inline long local_dec_return(local_t *l)
176{
177 unsigned long flags;
178 long result;
179
180 local_irq_save(flags);
181 __asm__ __volatile__ (
182 "# local_dec_return \n\t"
183 DCACHE_CLEAR("%0", "r4", "%1")
184 "ld %0, @%1; \n\t"
185 "addi %0, #-1; \n\t"
186 "st %0, @%1; \n\t"
187 : "=&r" (result)
188 : "r" (&l->counter)
189 : "memory"
190#ifdef CONFIG_CHIP_M32700_TS1
191 , "r4"
192#endif
193 );
194 local_irq_restore(flags);
195
196 return result;
197}
198
199
200
201
202
203
204
205#define local_inc(l) ((void)local_inc_return(l))
206
207
208
209
210
211
212
213#define local_dec(l) ((void)local_dec_return(l))
214
215
216
217
218
219
220
221
222
223#define local_inc_and_test(l) (local_inc_return(l) == 0)
224
225
226
227
228
229
230
231
232
233#define local_dec_and_test(l) (local_dec_return(l) == 0)
234
235
236
237
238
239
240
241
242
243
244#define local_add_negative(i, l) (local_add_return((i), (l)) < 0)
245
246#define local_cmpxchg(l, o, n) (cmpxchg_local(&((l)->counter), (o), (n)))
247#define local_xchg(v, new) (xchg_local(&((l)->counter), new))
248
249
250
251
252
253
254
255
256
257
258static inline int local_add_unless(local_t *l, long a, long u)
259{
260 long c, old;
261 c = local_read(l);
262 for (;;) {
263 if (unlikely(c == (u)))
264 break;
265 old = local_cmpxchg((l), c, c + (a));
266 if (likely(old == c))
267 break;
268 c = old;
269 }
270 return c != (u);
271}
272
273#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
274
275static inline void local_clear_mask(unsigned long mask, local_t *addr)
276{
277 unsigned long flags;
278 unsigned long tmp;
279
280 local_irq_save(flags);
281 __asm__ __volatile__ (
282 "# local_clear_mask \n\t"
283 DCACHE_CLEAR("%0", "r5", "%1")
284 "ld %0, @%1; \n\t"
285 "and %0, %2; \n\t"
286 "st %0, @%1; \n\t"
287 : "=&r" (tmp)
288 : "r" (addr), "r" (~mask)
289 : "memory"
290#ifdef CONFIG_CHIP_M32700_TS1
291 , "r5"
292#endif
293 );
294 local_irq_restore(flags);
295}
296
297static inline void local_set_mask(unsigned long mask, local_t *addr)
298{
299 unsigned long flags;
300 unsigned long tmp;
301
302 local_irq_save(flags);
303 __asm__ __volatile__ (
304 "# local_set_mask \n\t"
305 DCACHE_CLEAR("%0", "r5", "%1")
306 "ld %0, @%1; \n\t"
307 "or %0, %2; \n\t"
308 "st %0, @%1; \n\t"
309 : "=&r" (tmp)
310 : "r" (addr), "r" (mask)
311 : "memory"
312#ifdef CONFIG_CHIP_M32700_TS1
313 , "r5"
314#endif
315 );
316 local_irq_restore(flags);
317}
318
319
320#define smp_mb__before_local_dec() barrier()
321#define smp_mb__after_local_dec() barrier()
322#define smp_mb__before_local_inc() barrier()
323#define smp_mb__after_local_inc() barrier()
324
325
326
327
328
329
330#define __local_inc(l) ((l)->a.counter++)
331#define __local_dec(l) ((l)->a.counter++)
332#define __local_add(i, l) ((l)->a.counter += (i))
333#define __local_sub(i, l) ((l)->a.counter -= (i))
334
335
336
337
338
339
340#endif
341