]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/tile/include/asm/cmpxchg.h
rt2x00: rt2800pci: use module_pci_driver macro
[karo-tx-linux.git] / arch / tile / include / asm / cmpxchg.h
1 /*
2  * cmpxchg.h -- forked from asm/atomic.h with this copyright:
3  *
4  * Copyright 2010 Tilera Corporation. All Rights Reserved.
5  *
6  *   This program is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU General Public License
8  *   as published by the Free Software Foundation, version 2.
9  *
10  *   This program is distributed in the hope that it will be useful, but
11  *   WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13  *   NON INFRINGEMENT.  See the GNU General Public License for
14  *   more details.
15  *
16  */
17
18 #ifndef _ASM_TILE_CMPXCHG_H
19 #define _ASM_TILE_CMPXCHG_H
20
21 #ifndef __ASSEMBLY__
22
23 #include <asm/barrier.h>
24
25 /* Nonexistent functions intended to cause compile errors. */
26 extern void __xchg_called_with_bad_pointer(void)
27         __compiletime_error("Bad argument size for xchg");
28 extern void __cmpxchg_called_with_bad_pointer(void)
29         __compiletime_error("Bad argument size for cmpxchg");
30
31 #ifndef __tilegx__
32
33 /* Note the _atomic_xxx() routines include a final mb(). */
34 int _atomic_xchg(int *ptr, int n);
35 int _atomic_xchg_add(int *v, int i);
36 int _atomic_xchg_add_unless(int *v, int a, int u);
37 int _atomic_cmpxchg(int *ptr, int o, int n);
38 u64 _atomic64_xchg(u64 *v, u64 n);
39 u64 _atomic64_xchg_add(u64 *v, u64 i);
40 u64 _atomic64_xchg_add_unless(u64 *v, u64 a, u64 u);
41 u64 _atomic64_cmpxchg(u64 *v, u64 o, u64 n);
42
43 #define xchg(ptr, n)                                                    \
44         ({                                                              \
45                 if (sizeof(*(ptr)) != 4)                                \
46                         __xchg_called_with_bad_pointer();               \
47                 smp_mb();                                               \
48                 (typeof(*(ptr)))_atomic_xchg((int *)(ptr), (int)(n));   \
49         })
50
51 #define cmpxchg(ptr, o, n)                                              \
52         ({                                                              \
53                 if (sizeof(*(ptr)) != 4)                                \
54                         __cmpxchg_called_with_bad_pointer();            \
55                 smp_mb();                                               \
56                 (typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o, (int)n); \
57         })
58
59 #define xchg64(ptr, n)                                                  \
60         ({                                                              \
61                 if (sizeof(*(ptr)) != 8)                                \
62                         __xchg_called_with_bad_pointer();               \
63                 smp_mb();                                               \
64                 (typeof(*(ptr)))_atomic64_xchg((u64 *)(ptr), (u64)(n)); \
65         })
66
67 #define cmpxchg64(ptr, o, n)                                            \
68         ({                                                              \
69                 if (sizeof(*(ptr)) != 8)                                \
70                         __cmpxchg_called_with_bad_pointer();            \
71                 smp_mb();                                               \
72                 (typeof(*(ptr)))_atomic64_cmpxchg((u64 *)ptr, (u64)o, (u64)n); \
73         })
74
75 #else
76
77 #define xchg(ptr, n)                                                    \
78         ({                                                              \
79                 typeof(*(ptr)) __x;                                     \
80                 smp_mb();                                               \
81                 switch (sizeof(*(ptr))) {                               \
82                 case 4:                                                 \
83                         __x = (typeof(__x))(unsigned long)              \
84                                 __insn_exch4((ptr), (u32)(unsigned long)(n)); \
85                         break;                                          \
86                 case 8:                                                 \
87                         __x = (typeof(__x))                     \
88                                 __insn_exch((ptr), (unsigned long)(n)); \
89                         break;                                          \
90                 default:                                                \
91                         __xchg_called_with_bad_pointer();               \
92                         break;                                          \
93                 }                                                       \
94                 smp_mb();                                               \
95                 __x;                                                    \
96         })
97
98 #define cmpxchg(ptr, o, n)                                              \
99         ({                                                              \
100                 typeof(*(ptr)) __x;                                     \
101                 __insn_mtspr(SPR_CMPEXCH_VALUE, (unsigned long)(o));    \
102                 smp_mb();                                               \
103                 switch (sizeof(*(ptr))) {                               \
104                 case 4:                                                 \
105                         __x = (typeof(__x))(unsigned long)              \
106                                 __insn_cmpexch4((ptr), (u32)(unsigned long)(n)); \
107                         break;                                          \
108                 case 8:                                                 \
109                         __x = (typeof(__x))__insn_cmpexch((ptr), (u64)(n)); \
110                         break;                                          \
111                 default:                                                \
112                         __cmpxchg_called_with_bad_pointer();            \
113                         break;                                          \
114                 }                                                       \
115                 smp_mb();                                               \
116                 __x;                                                    \
117         })
118
119 #define xchg64 xchg
120 #define cmpxchg64 cmpxchg
121
122 #endif
123
124 #define tas(ptr) xchg((ptr), 1)
125
126 #endif /* __ASSEMBLY__ */
127
128 #endif /* _ASM_TILE_CMPXCHG_H */