aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-m32r
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>2008-02-07 03:16:17 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 11:42:32 -0500
commit7b631c2de63b4475351258197409983c8189ed04 (patch)
tree915d5b3d1b7ba8f47e0f5abfba70aec94c106d9e /include/asm-m32r
parent4b78fff6e736cae55dc3fb5570c7ef4037eca9b7 (diff)
New cmpxchg_local (optimized for UP case) for m32r
Add __xchg_local, xchg_local (define), __cmpxchg_local_u32, __cmpxchg_local, cmpxchg_local(macro). cmpxchg_local and cmpxchg64_local will use the architecture specific __cmpxchg_local_u32 for 32 bits arguments, and use the generic __cmpxchg_local_generic for 8, 16 and 64 bits arguments. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Acked-by: Hirokazu Takata <takata@linux-m32r.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/asm-m32r')
-rw-r--r--include/asm-m32r/system.h111
1 files changed, 101 insertions, 10 deletions
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index 2365de5c2955..7e7eb3703d85 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -121,8 +121,11 @@ static inline void local_irq_disable(void)
121 121
122#define nop() __asm__ __volatile__ ("nop" : : ) 122#define nop() __asm__ __volatile__ ("nop" : : )
123 123
124#define xchg(ptr,x) \ 124#define xchg(ptr, x) \
125 ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) 125 ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
126#define xchg_local(ptr, x) \
127 ((__typeof__(*(ptr)))__xchg_local((unsigned long)(x), (ptr), \
128 sizeof(*(ptr))))
126 129
127#ifdef CONFIG_SMP 130#ifdef CONFIG_SMP
128extern void __xchg_called_with_bad_pointer(void); 131extern void __xchg_called_with_bad_pointer(void);
@@ -146,7 +149,7 @@ extern void __xchg_called_with_bad_pointer(void);
146#endif /* CONFIG_CHIP_M32700_TS1 */ 149#endif /* CONFIG_CHIP_M32700_TS1 */
147 150
148static __always_inline unsigned long 151static __always_inline unsigned long
149__xchg(unsigned long x, volatile void * ptr, int size) 152__xchg(unsigned long x, volatile void *ptr, int size)
150{ 153{
151 unsigned long flags; 154 unsigned long flags;
152 unsigned long tmp = 0; 155 unsigned long tmp = 0;
@@ -196,6 +199,42 @@ __xchg(unsigned long x, volatile void * ptr, int size)
196 return (tmp); 199 return (tmp);
197} 200}
198 201
202static __always_inline unsigned long
203__xchg_local(unsigned long x, volatile void *ptr, int size)
204{
205 unsigned long flags;
206 unsigned long tmp = 0;
207
208 local_irq_save(flags);
209
210 switch (size) {
211 case 1:
212 __asm__ __volatile__ (
213 "ldb %0, @%2 \n\t"
214 "stb %1, @%2 \n\t"
215 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
216 break;
217 case 2:
218 __asm__ __volatile__ (
219 "ldh %0, @%2 \n\t"
220 "sth %1, @%2 \n\t"
221 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
222 break;
223 case 4:
224 __asm__ __volatile__ (
225 "ld %0, @%2 \n\t"
226 "st %1, @%2 \n\t"
227 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
228 break;
229 default:
230 __xchg_called_with_bad_pointer();
231 }
232
233 local_irq_restore(flags);
234
235 return (tmp);
236}
237
199#define __HAVE_ARCH_CMPXCHG 1 238#define __HAVE_ARCH_CMPXCHG 1
200 239
201static inline unsigned long 240static inline unsigned long
@@ -228,6 +267,37 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
228 return retval; 267 return retval;
229} 268}
230 269
270static inline unsigned long
271__cmpxchg_local_u32(volatile unsigned int *p, unsigned int old,
272 unsigned int new)
273{
274 unsigned long flags;
275 unsigned int retval;
276
277 local_irq_save(flags);
278 __asm__ __volatile__ (
279 DCACHE_CLEAR("%0", "r4", "%1")
280 "ld %0, @%1; \n"
281 " bne %0, %2, 1f; \n"
282 "st %3, @%1; \n"
283 " bra 2f; \n"
284 " .fillinsn \n"
285 "1:"
286 "st %0, @%1; \n"
287 " .fillinsn \n"
288 "2:"
289 : "=&r" (retval)
290 : "r" (p), "r" (old), "r" (new)
291 : "cbit", "memory"
292#ifdef CONFIG_CHIP_M32700_TS1
293 , "r4"
294#endif /* CONFIG_CHIP_M32700_TS1 */
295 );
296 local_irq_restore(flags);
297
298 return retval;
299}
300
231/* This function doesn't exist, so you'll get a linker error 301/* This function doesn't exist, so you'll get a linker error
232 if something tries to do an invalid cmpxchg(). */ 302 if something tries to do an invalid cmpxchg(). */
233extern void __cmpxchg_called_with_bad_pointer(void); 303extern void __cmpxchg_called_with_bad_pointer(void);
@@ -247,13 +317,34 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
247 return old; 317 return old;
248} 318}
249 319
250#define cmpxchg(ptr,o,n) \ 320#define cmpxchg(ptr, o, n) \
251 ({ \ 321 ((__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)(o), \
252 __typeof__(*(ptr)) _o_ = (o); \ 322 (unsigned long)(n), sizeof(*(ptr))))
253 __typeof__(*(ptr)) _n_ = (n); \ 323
254 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ 324#include <asm-generic/cmpxchg-local.h>
255 (unsigned long)_n_, sizeof(*(ptr))); \ 325
256 }) 326static inline unsigned long __cmpxchg_local(volatile void *ptr,
327 unsigned long old,
328 unsigned long new, int size)
329{
330 switch (size) {
331 case 4:
332 return __cmpxchg_local_u32(ptr, old, new);
333 default:
334 return __cmpxchg_local_generic(ptr, old, new, size);
335 }
336
337 return old;
338}
339
340/*
341 * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
342 * them available.
343 */
344#define cmpxchg_local(ptr, o, n) \
345 ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
346 (unsigned long)(n), sizeof(*(ptr))))
347#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
257 348
258#endif /* __KERNEL__ */ 349#endif /* __KERNEL__ */
259 350