GNU Linux-libre 4.14.259-gnu1
[releases.git] / arch / metag / include / asm / cmpxchg.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __ASM_METAG_CMPXCHG_H
3 #define __ASM_METAG_CMPXCHG_H
4
5 #include <asm/barrier.h>
6
7 #if defined(CONFIG_METAG_ATOMICITY_IRQSOFF)
8 #include <asm/cmpxchg_irq.h>
9 #elif defined(CONFIG_METAG_ATOMICITY_LOCK1)
10 #include <asm/cmpxchg_lock1.h>
11 #elif defined(CONFIG_METAG_ATOMICITY_LNKGET)
12 #include <asm/cmpxchg_lnkget.h>
13 #endif
14
15 extern void __xchg_called_with_bad_pointer(void);
16
17 #define __xchg(ptr, x, size)                            \
18 ({                                                      \
19         unsigned long __xchg__res;                      \
20         volatile void *__xchg_ptr = (ptr);              \
21         switch (size) {                                 \
22         case 4:                                         \
23                 __xchg__res = xchg_u32(__xchg_ptr, x);  \
24                 break;                                  \
25         case 1:                                         \
26                 __xchg__res = xchg_u8(__xchg_ptr, x);   \
27                 break;                                  \
28         default:                                        \
29                 __xchg_called_with_bad_pointer();       \
30                 __xchg__res = x;                        \
31                 break;                                  \
32         }                                               \
33                                                         \
34         __xchg__res;                                    \
35 })
36
37 #define xchg(ptr, x)    \
38         ((__typeof__(*(ptr)))__xchg((ptr), (unsigned long)(x), sizeof(*(ptr))))
39
40 /* This function doesn't exist, so you'll get a linker error
41  * if something tries to do an invalid cmpxchg(). */
42 extern void __cmpxchg_called_with_bad_pointer(void);
43
44 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
45                                       unsigned long new, int size)
46 {
47         switch (size) {
48         case 4:
49                 return __cmpxchg_u32(ptr, old, new);
50         }
51         __cmpxchg_called_with_bad_pointer();
52         return old;
53 }
54
55 #define cmpxchg(ptr, o, n)                                              \
56         ({                                                              \
57                 __typeof__(*(ptr)) _o_ = (o);                           \
58                 __typeof__(*(ptr)) _n_ = (n);                           \
59                 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
60                                                (unsigned long)_n_,      \
61                                                sizeof(*(ptr)));         \
62         })
63
64 #endif /* __ASM_METAG_CMPXCHG_H */