Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / m32r / include / asm / local.h
1 #ifndef __M32R_LOCAL_H
2 #define __M32R_LOCAL_H
3
4 /*
5  *  linux/include/asm-m32r/local.h
6  *
7  *  M32R version:
8  *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
9  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
10  *    Copyright (C) 2007  Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
11  */
12
13 #include <linux/percpu.h>
14 #include <asm/assembler.h>
15 #include <asm/local.h>
16
17 /*
18  * Atomic operations that C can't guarantee us.  Useful for
19  * resource counting etc..
20  */
21
22 /*
23  * Make sure gcc doesn't try to be clever and move things around
24  * on us. We need to use _exactly_ the address the user gave us,
25  * not some alias that contains the same information.
26  */
27 typedef struct { volatile int counter; } local_t;
28
29 #define LOCAL_INIT(i)   { (i) }
30
31 /**
32  * local_read - read local variable
33  * @l: pointer of type local_t
34  *
35  * Atomically reads the value of @l.
36  */
37 #define local_read(l)   ((l)->counter)
38
39 /**
40  * local_set - set local variable
41  * @l: pointer of type local_t
42  * @i: required value
43  *
44  * Atomically sets the value of @l to @i.
45  */
46 #define local_set(l, i) (((l)->counter) = (i))
47
48 /**
49  * local_add_return - add long to local variable and return it
50  * @i: long value to add
51  * @l: pointer of type local_t
52  *
53  * Atomically adds @i to @l and return (@i + @l).
54  */
55 static 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  /* CONFIG_CHIP_M32700_TS1 */
73         );
74         local_irq_restore(flags);
75
76         return result;
77 }
78
79 /**
80  * local_sub_return - subtract long from local variable and return it
81  * @i: long value to subtract
82  * @l: pointer of type local_t
83  *
84  * Atomically subtracts @i from @l and return (@l - @i).
85  */
86 static 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  /* CONFIG_CHIP_M32700_TS1 */
104         );
105         local_irq_restore(flags);
106
107         return result;
108 }
109
110 /**
111  * local_add - add long to local variable
112  * @i: long value to add
113  * @l: pointer of type local_t
114  *
115  * Atomically adds @i to @l.
116  */
117 #define local_add(i, l) ((void) local_add_return((i), (l)))
118
119 /**
120  * local_sub - subtract the local variable
121  * @i: long value to subtract
122  * @l: pointer of type local_t
123  *
124  * Atomically subtracts @i from @l.
125  */
126 #define local_sub(i, l) ((void) local_sub_return((i), (l)))
127
128 /**
129  * local_sub_and_test - subtract value from variable and test result
130  * @i: integer value to subtract
131  * @l: pointer of type local_t
132  *
133  * Atomically subtracts @i from @l and returns
134  * true if the result is zero, or false for all
135  * other cases.
136  */
137 #define local_sub_and_test(i, l) (local_sub_return((i), (l)) == 0)
138
139 /**
140  * local_inc_return - increment local variable and return it
141  * @l: pointer of type local_t
142  *
143  * Atomically increments @l by 1 and returns the result.
144  */
145 static 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  /* CONFIG_CHIP_M32700_TS1 */
163         );
164         local_irq_restore(flags);
165
166         return result;
167 }
168
169 /**
170  * local_dec_return - decrement local variable and return it
171  * @l: pointer of type local_t
172  *
173  * Atomically decrements @l by 1 and returns the result.
174  */
175 static 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  /* CONFIG_CHIP_M32700_TS1 */
193         );
194         local_irq_restore(flags);
195
196         return result;
197 }
198
199 /**
200  * local_inc - increment local variable
201  * @l: pointer of type local_t
202  *
203  * Atomically increments @l by 1.
204  */
205 #define local_inc(l) ((void)local_inc_return(l))
206
207 /**
208  * local_dec - decrement local variable
209  * @l: pointer of type local_t
210  *
211  * Atomically decrements @l by 1.
212  */
213 #define local_dec(l) ((void)local_dec_return(l))
214
215 /**
216  * local_inc_and_test - increment and test
217  * @l: pointer of type local_t
218  *
219  * Atomically increments @l by 1
220  * and returns true if the result is zero, or false for all
221  * other cases.
222  */
223 #define local_inc_and_test(l) (local_inc_return(l) == 0)
224
225 /**
226  * local_dec_and_test - decrement and test
227  * @l: pointer of type local_t
228  *
229  * Atomically decrements @l by 1 and
230  * returns true if the result is 0, or false for all
231  * other cases.
232  */
233 #define local_dec_and_test(l) (local_dec_return(l) == 0)
234
235 /**
236  * local_add_negative - add and test if negative
237  * @l: pointer of type local_t
238  * @i: integer value to add
239  *
240  * Atomically adds @i to @l and returns true
241  * if the result is negative, or false when
242  * result is greater than or equal to zero.
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  * local_add_unless - add unless the number is a given value
251  * @l: pointer of type local_t
252  * @a: the amount to add to l...
253  * @u: ...unless l is equal to u.
254  *
255  * Atomically adds @a to @l, so long as it was not @u.
256  * Returns non-zero if @l was not @u, and zero otherwise.
257  */
258 static 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
275 static 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  /* CONFIG_CHIP_M32700_TS1 */
293         );
294         local_irq_restore(flags);
295 }
296
297 static 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  /* CONFIG_CHIP_M32700_TS1 */
315         );
316         local_irq_restore(flags);
317 }
318
319 /* Atomic operations are already serializing on m32r */
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 /* Use these for per-cpu local_t variables: on some archs they are
326  * much more efficient than these naive implementations.  Note they take
327  * a variable, not an address.
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 /* Use these for per-cpu local_t variables: on some archs they are
336  * much more efficient than these naive implementations.  Note they take
337  * a variable, not an address.
338  */
339
340 #endif /* __M32R_LOCAL_H */