diff options
author | Graf Yang <graf.yang@analog.com> | 2009-01-07 10:14:39 -0500 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2009-01-07 10:14:39 -0500 |
commit | 6b3087c64a92a36ae20d33479b4df6d7afc910d4 (patch) | |
tree | 95984fc623658ebf150d0d912a7f6c5a0301a5a9 /arch/blackfin/include/asm/bitops.h | |
parent | c51b4488cd5bff08ed5690a8f303ff7f0894da2a (diff) |
Blackfin arch: SMP supporting patchset: Blackfin header files and machine common code
Blackfin dual core BF561 processor can support SMP like features.
https://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:smp-like
In this patch, we provide SMP extend to Blackfin header files
and machine common code
Signed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin/include/asm/bitops.h')
-rw-r--r-- | arch/blackfin/include/asm/bitops.h | 189 |
1 files changed, 125 insertions, 64 deletions
diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h index c428e4106f89..9964e17232e9 100644 --- a/arch/blackfin/include/asm/bitops.h +++ b/arch/blackfin/include/asm/bitops.h | |||
@@ -7,7 +7,6 @@ | |||
7 | 7 | ||
8 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
9 | #include <asm/byteorder.h> /* swab32 */ | 9 | #include <asm/byteorder.h> /* swab32 */ |
10 | #include <asm/system.h> /* save_flags */ | ||
11 | 10 | ||
12 | #ifdef __KERNEL__ | 11 | #ifdef __KERNEL__ |
13 | 12 | ||
@@ -20,36 +19,71 @@ | |||
20 | #include <asm-generic/bitops/sched.h> | 19 | #include <asm-generic/bitops/sched.h> |
21 | #include <asm-generic/bitops/ffz.h> | 20 | #include <asm-generic/bitops/ffz.h> |
22 | 21 | ||
23 | static __inline__ void set_bit(int nr, volatile unsigned long *addr) | 22 | #ifdef CONFIG_SMP |
23 | |||
24 | #include <linux/linkage.h> | ||
25 | |||
26 | asmlinkage int __raw_bit_set_asm(volatile unsigned long *addr, int nr); | ||
27 | |||
28 | asmlinkage int __raw_bit_clear_asm(volatile unsigned long *addr, int nr); | ||
29 | |||
30 | asmlinkage int __raw_bit_toggle_asm(volatile unsigned long *addr, int nr); | ||
31 | |||
32 | asmlinkage int __raw_bit_test_set_asm(volatile unsigned long *addr, int nr); | ||
33 | |||
34 | asmlinkage int __raw_bit_test_clear_asm(volatile unsigned long *addr, int nr); | ||
35 | |||
36 | asmlinkage int __raw_bit_test_toggle_asm(volatile unsigned long *addr, int nr); | ||
37 | |||
38 | asmlinkage int __raw_bit_test_asm(const volatile unsigned long *addr, int nr); | ||
39 | |||
40 | static inline void set_bit(int nr, volatile unsigned long *addr) | ||
24 | { | 41 | { |
25 | int *a = (int *)addr; | 42 | volatile unsigned long *a = addr + (nr >> 5); |
26 | int mask; | 43 | __raw_bit_set_asm(a, nr & 0x1f); |
27 | unsigned long flags; | 44 | } |
28 | 45 | ||
29 | a += nr >> 5; | 46 | static inline void clear_bit(int nr, volatile unsigned long *addr) |
30 | mask = 1 << (nr & 0x1f); | 47 | { |
31 | local_irq_save(flags); | 48 | volatile unsigned long *a = addr + (nr >> 5); |
32 | *a |= mask; | 49 | __raw_bit_clear_asm(a, nr & 0x1f); |
33 | local_irq_restore(flags); | ||
34 | } | 50 | } |
35 | 51 | ||
36 | static __inline__ void __set_bit(int nr, volatile unsigned long *addr) | 52 | static inline void change_bit(int nr, volatile unsigned long *addr) |
37 | { | 53 | { |
38 | int *a = (int *)addr; | 54 | volatile unsigned long *a = addr + (nr >> 5); |
39 | int mask; | 55 | __raw_bit_toggle_asm(a, nr & 0x1f); |
56 | } | ||
40 | 57 | ||
41 | a += nr >> 5; | 58 | static inline int test_bit(int nr, const volatile unsigned long *addr) |
42 | mask = 1 << (nr & 0x1f); | 59 | { |
43 | *a |= mask; | 60 | volatile const unsigned long *a = addr + (nr >> 5); |
61 | return __raw_bit_test_asm(a, nr & 0x1f) != 0; | ||
44 | } | 62 | } |
45 | 63 | ||
46 | /* | 64 | static inline int test_and_set_bit(int nr, volatile unsigned long *addr) |
47 | * clear_bit() doesn't provide any barrier for the compiler. | 65 | { |
48 | */ | 66 | volatile unsigned long *a = addr + (nr >> 5); |
49 | #define smp_mb__before_clear_bit() barrier() | 67 | return __raw_bit_test_set_asm(a, nr & 0x1f); |
50 | #define smp_mb__after_clear_bit() barrier() | 68 | } |
51 | 69 | ||
52 | static __inline__ void clear_bit(int nr, volatile unsigned long *addr) | 70 | static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) |
71 | { | ||
72 | volatile unsigned long *a = addr + (nr >> 5); | ||
73 | return __raw_bit_test_clear_asm(a, nr & 0x1f); | ||
74 | } | ||
75 | |||
76 | static inline int test_and_change_bit(int nr, volatile unsigned long *addr) | ||
77 | { | ||
78 | volatile unsigned long *a = addr + (nr >> 5); | ||
79 | return __raw_bit_test_toggle_asm(a, nr & 0x1f); | ||
80 | } | ||
81 | |||
82 | #else /* !CONFIG_SMP */ | ||
83 | |||
84 | #include <asm/system.h> /* save_flags */ | ||
85 | |||
86 | static inline void set_bit(int nr, volatile unsigned long *addr) | ||
53 | { | 87 | { |
54 | int *a = (int *)addr; | 88 | int *a = (int *)addr; |
55 | int mask; | 89 | int mask; |
@@ -57,21 +91,23 @@ static __inline__ void clear_bit(int nr, volatile unsigned long *addr) | |||
57 | a += nr >> 5; | 91 | a += nr >> 5; |
58 | mask = 1 << (nr & 0x1f); | 92 | mask = 1 << (nr & 0x1f); |
59 | local_irq_save(flags); | 93 | local_irq_save(flags); |
60 | *a &= ~mask; | 94 | *a |= mask; |
61 | local_irq_restore(flags); | 95 | local_irq_restore(flags); |
62 | } | 96 | } |
63 | 97 | ||
64 | static __inline__ void __clear_bit(int nr, volatile unsigned long *addr) | 98 | static inline void clear_bit(int nr, volatile unsigned long *addr) |
65 | { | 99 | { |
66 | int *a = (int *)addr; | 100 | int *a = (int *)addr; |
67 | int mask; | 101 | int mask; |
68 | 102 | unsigned long flags; | |
69 | a += nr >> 5; | 103 | a += nr >> 5; |
70 | mask = 1 << (nr & 0x1f); | 104 | mask = 1 << (nr & 0x1f); |
105 | local_irq_save(flags); | ||
71 | *a &= ~mask; | 106 | *a &= ~mask; |
107 | local_irq_restore(flags); | ||
72 | } | 108 | } |
73 | 109 | ||
74 | static __inline__ void change_bit(int nr, volatile unsigned long *addr) | 110 | static inline void change_bit(int nr, volatile unsigned long *addr) |
75 | { | 111 | { |
76 | int mask, flags; | 112 | int mask, flags; |
77 | unsigned long *ADDR = (unsigned long *)addr; | 113 | unsigned long *ADDR = (unsigned long *)addr; |
@@ -83,17 +119,7 @@ static __inline__ void change_bit(int nr, volatile unsigned long *addr) | |||
83 | local_irq_restore(flags); | 119 | local_irq_restore(flags); |
84 | } | 120 | } |
85 | 121 | ||
86 | static __inline__ void __change_bit(int nr, volatile unsigned long *addr) | 122 | static inline int test_and_set_bit(int nr, volatile unsigned long *addr) |
87 | { | ||
88 | int mask; | ||
89 | unsigned long *ADDR = (unsigned long *)addr; | ||
90 | |||
91 | ADDR += nr >> 5; | ||
92 | mask = 1 << (nr & 31); | ||
93 | *ADDR ^= mask; | ||
94 | } | ||
95 | |||
96 | static __inline__ int test_and_set_bit(int nr, void *addr) | ||
97 | { | 123 | { |
98 | int mask, retval; | 124 | int mask, retval; |
99 | volatile unsigned int *a = (volatile unsigned int *)addr; | 125 | volatile unsigned int *a = (volatile unsigned int *)addr; |
@@ -109,19 +135,23 @@ static __inline__ int test_and_set_bit(int nr, void *addr) | |||
109 | return retval; | 135 | return retval; |
110 | } | 136 | } |
111 | 137 | ||
112 | static __inline__ int __test_and_set_bit(int nr, volatile unsigned long *addr) | 138 | static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) |
113 | { | 139 | { |
114 | int mask, retval; | 140 | int mask, retval; |
115 | volatile unsigned int *a = (volatile unsigned int *)addr; | 141 | volatile unsigned int *a = (volatile unsigned int *)addr; |
142 | unsigned long flags; | ||
116 | 143 | ||
117 | a += nr >> 5; | 144 | a += nr >> 5; |
118 | mask = 1 << (nr & 0x1f); | 145 | mask = 1 << (nr & 0x1f); |
146 | local_irq_save(flags); | ||
119 | retval = (mask & *a) != 0; | 147 | retval = (mask & *a) != 0; |
120 | *a |= mask; | 148 | *a &= ~mask; |
149 | local_irq_restore(flags); | ||
150 | |||
121 | return retval; | 151 | return retval; |
122 | } | 152 | } |
123 | 153 | ||
124 | static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr) | 154 | static inline int test_and_change_bit(int nr, volatile unsigned long *addr) |
125 | { | 155 | { |
126 | int mask, retval; | 156 | int mask, retval; |
127 | volatile unsigned int *a = (volatile unsigned int *)addr; | 157 | volatile unsigned int *a = (volatile unsigned int *)addr; |
@@ -131,13 +161,50 @@ static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr) | |||
131 | mask = 1 << (nr & 0x1f); | 161 | mask = 1 << (nr & 0x1f); |
132 | local_irq_save(flags); | 162 | local_irq_save(flags); |
133 | retval = (mask & *a) != 0; | 163 | retval = (mask & *a) != 0; |
134 | *a &= ~mask; | 164 | *a ^= mask; |
135 | local_irq_restore(flags); | 165 | local_irq_restore(flags); |
136 | |||
137 | return retval; | 166 | return retval; |
138 | } | 167 | } |
139 | 168 | ||
140 | static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr) | 169 | #endif /* CONFIG_SMP */ |
170 | |||
171 | /* | ||
172 | * clear_bit() doesn't provide any barrier for the compiler. | ||
173 | */ | ||
174 | #define smp_mb__before_clear_bit() barrier() | ||
175 | #define smp_mb__after_clear_bit() barrier() | ||
176 | |||
177 | static inline void __set_bit(int nr, volatile unsigned long *addr) | ||
178 | { | ||
179 | int *a = (int *)addr; | ||
180 | int mask; | ||
181 | |||
182 | a += nr >> 5; | ||
183 | mask = 1 << (nr & 0x1f); | ||
184 | *a |= mask; | ||
185 | } | ||
186 | |||
187 | static inline void __clear_bit(int nr, volatile unsigned long *addr) | ||
188 | { | ||
189 | int *a = (int *)addr; | ||
190 | int mask; | ||
191 | |||
192 | a += nr >> 5; | ||
193 | mask = 1 << (nr & 0x1f); | ||
194 | *a &= ~mask; | ||
195 | } | ||
196 | |||
197 | static inline void __change_bit(int nr, volatile unsigned long *addr) | ||
198 | { | ||
199 | int mask; | ||
200 | unsigned long *ADDR = (unsigned long *)addr; | ||
201 | |||
202 | ADDR += nr >> 5; | ||
203 | mask = 1 << (nr & 31); | ||
204 | *ADDR ^= mask; | ||
205 | } | ||
206 | |||
207 | static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) | ||
141 | { | 208 | { |
142 | int mask, retval; | 209 | int mask, retval; |
143 | volatile unsigned int *a = (volatile unsigned int *)addr; | 210 | volatile unsigned int *a = (volatile unsigned int *)addr; |
@@ -145,26 +212,23 @@ static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr) | |||
145 | a += nr >> 5; | 212 | a += nr >> 5; |
146 | mask = 1 << (nr & 0x1f); | 213 | mask = 1 << (nr & 0x1f); |
147 | retval = (mask & *a) != 0; | 214 | retval = (mask & *a) != 0; |
148 | *a &= ~mask; | 215 | *a |= mask; |
149 | return retval; | 216 | return retval; |
150 | } | 217 | } |
151 | 218 | ||
152 | static __inline__ int test_and_change_bit(int nr, volatile unsigned long *addr) | 219 | static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) |
153 | { | 220 | { |
154 | int mask, retval; | 221 | int mask, retval; |
155 | volatile unsigned int *a = (volatile unsigned int *)addr; | 222 | volatile unsigned int *a = (volatile unsigned int *)addr; |
156 | unsigned long flags; | ||
157 | 223 | ||
158 | a += nr >> 5; | 224 | a += nr >> 5; |
159 | mask = 1 << (nr & 0x1f); | 225 | mask = 1 << (nr & 0x1f); |
160 | local_irq_save(flags); | ||
161 | retval = (mask & *a) != 0; | 226 | retval = (mask & *a) != 0; |
162 | *a ^= mask; | 227 | *a &= ~mask; |
163 | local_irq_restore(flags); | ||
164 | return retval; | 228 | return retval; |
165 | } | 229 | } |
166 | 230 | ||
167 | static __inline__ int __test_and_change_bit(int nr, | 231 | static inline int __test_and_change_bit(int nr, |
168 | volatile unsigned long *addr) | 232 | volatile unsigned long *addr) |
169 | { | 233 | { |
170 | int mask, retval; | 234 | int mask, retval; |
@@ -177,16 +241,7 @@ static __inline__ int __test_and_change_bit(int nr, | |||
177 | return retval; | 241 | return retval; |
178 | } | 242 | } |
179 | 243 | ||
180 | /* | 244 | static inline int __test_bit(int nr, const void *addr) |
181 | * This routine doesn't need to be atomic. | ||
182 | */ | ||
183 | static __inline__ int __constant_test_bit(int nr, const void *addr) | ||
184 | { | ||
185 | return ((1UL << (nr & 31)) & | ||
186 | (((const volatile unsigned int *)addr)[nr >> 5])) != 0; | ||
187 | } | ||
188 | |||
189 | static __inline__ int __test_bit(int nr, const void *addr) | ||
190 | { | 245 | { |
191 | int *a = (int *)addr; | 246 | int *a = (int *)addr; |
192 | int mask; | 247 | int mask; |
@@ -196,10 +251,16 @@ static __inline__ int __test_bit(int nr, const void *addr) | |||
196 | return ((mask & *a) != 0); | 251 | return ((mask & *a) != 0); |
197 | } | 252 | } |
198 | 253 | ||
199 | #define test_bit(nr,addr) \ | 254 | #ifndef CONFIG_SMP |
200 | (__builtin_constant_p(nr) ? \ | 255 | /* |
201 | __constant_test_bit((nr),(addr)) : \ | 256 | * This routine doesn't need irq save and restore ops in UP |
202 | __test_bit((nr),(addr))) | 257 | * context. |
258 | */ | ||
259 | static inline int test_bit(int nr, const void *addr) | ||
260 | { | ||
261 | return __test_bit(nr, addr); | ||
262 | } | ||
263 | #endif | ||
203 | 264 | ||
204 | #include <asm-generic/bitops/find.h> | 265 | #include <asm-generic/bitops/find.h> |
205 | #include <asm-generic/bitops/hweight.h> | 266 | #include <asm-generic/bitops/hweight.h> |