diff options
author | Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | 2007-05-08 03:34:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:20 -0400 |
commit | 7232311ef14c274d88871212a07557f18f4140d1 (patch) | |
tree | 46027210d51dee5fd5086f159d98bac3535a005d /include/asm-mips/system.h | |
parent | 4431f46f5fe0e3b740dfaf09ba34f0b14688185e (diff) |
local_t: mips extension
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/asm-mips/system.h')
-rw-r--r-- | include/asm-mips/system.h | 125 |
1 files changed, 124 insertions, 1 deletions
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 290887077e44..d53dd7245561 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h | |||
@@ -262,6 +262,58 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old, | |||
262 | return retval; | 262 | return retval; |
263 | } | 263 | } |
264 | 264 | ||
265 | static inline unsigned long __cmpxchg_u32_local(volatile int * m, | ||
266 | unsigned long old, unsigned long new) | ||
267 | { | ||
268 | __u32 retval; | ||
269 | |||
270 | if (cpu_has_llsc && R10000_LLSC_WAR) { | ||
271 | __asm__ __volatile__( | ||
272 | " .set push \n" | ||
273 | " .set noat \n" | ||
274 | " .set mips3 \n" | ||
275 | "1: ll %0, %2 # __cmpxchg_u32 \n" | ||
276 | " bne %0, %z3, 2f \n" | ||
277 | " .set mips0 \n" | ||
278 | " move $1, %z4 \n" | ||
279 | " .set mips3 \n" | ||
280 | " sc $1, %1 \n" | ||
281 | " beqzl $1, 1b \n" | ||
282 | "2: \n" | ||
283 | " .set pop \n" | ||
284 | : "=&r" (retval), "=R" (*m) | ||
285 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
286 | : "memory"); | ||
287 | } else if (cpu_has_llsc) { | ||
288 | __asm__ __volatile__( | ||
289 | " .set push \n" | ||
290 | " .set noat \n" | ||
291 | " .set mips3 \n" | ||
292 | "1: ll %0, %2 # __cmpxchg_u32 \n" | ||
293 | " bne %0, %z3, 2f \n" | ||
294 | " .set mips0 \n" | ||
295 | " move $1, %z4 \n" | ||
296 | " .set mips3 \n" | ||
297 | " sc $1, %1 \n" | ||
298 | " beqz $1, 1b \n" | ||
299 | "2: \n" | ||
300 | " .set pop \n" | ||
301 | : "=&r" (retval), "=R" (*m) | ||
302 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
303 | : "memory"); | ||
304 | } else { | ||
305 | unsigned long flags; | ||
306 | |||
307 | local_irq_save(flags); | ||
308 | retval = *m; | ||
309 | if (retval == old) | ||
310 | *m = new; | ||
311 | local_irq_restore(flags); /* implies memory barrier */ | ||
312 | } | ||
313 | |||
314 | return retval; | ||
315 | } | ||
316 | |||
265 | #ifdef CONFIG_64BIT | 317 | #ifdef CONFIG_64BIT |
266 | static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old, | 318 | static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old, |
267 | unsigned long new) | 319 | unsigned long new) |
@@ -315,10 +367,62 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old, | |||
315 | 367 | ||
316 | return retval; | 368 | return retval; |
317 | } | 369 | } |
370 | |||
371 | static inline unsigned long __cmpxchg_u64_local(volatile int * m, | ||
372 | unsigned long old, unsigned long new) | ||
373 | { | ||
374 | __u64 retval; | ||
375 | |||
376 | if (cpu_has_llsc && R10000_LLSC_WAR) { | ||
377 | __asm__ __volatile__( | ||
378 | " .set push \n" | ||
379 | " .set noat \n" | ||
380 | " .set mips3 \n" | ||
381 | "1: lld %0, %2 # __cmpxchg_u64 \n" | ||
382 | " bne %0, %z3, 2f \n" | ||
383 | " move $1, %z4 \n" | ||
384 | " scd $1, %1 \n" | ||
385 | " beqzl $1, 1b \n" | ||
386 | "2: \n" | ||
387 | " .set pop \n" | ||
388 | : "=&r" (retval), "=R" (*m) | ||
389 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
390 | : "memory"); | ||
391 | } else if (cpu_has_llsc) { | ||
392 | __asm__ __volatile__( | ||
393 | " .set push \n" | ||
394 | " .set noat \n" | ||
395 | " .set mips3 \n" | ||
396 | "1: lld %0, %2 # __cmpxchg_u64 \n" | ||
397 | " bne %0, %z3, 2f \n" | ||
398 | " move $1, %z4 \n" | ||
399 | " scd $1, %1 \n" | ||
400 | " beqz $1, 1b \n" | ||
401 | "2: \n" | ||
402 | " .set pop \n" | ||
403 | : "=&r" (retval), "=R" (*m) | ||
404 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
405 | : "memory"); | ||
406 | } else { | ||
407 | unsigned long flags; | ||
408 | |||
409 | local_irq_save(flags); | ||
410 | retval = *m; | ||
411 | if (retval == old) | ||
412 | *m = new; | ||
413 | local_irq_restore(flags); /* implies memory barrier */ | ||
414 | } | ||
415 | |||
416 | return retval; | ||
417 | } | ||
418 | |||
318 | #else | 419 | #else |
319 | extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels( | 420 | extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels( |
320 | volatile int * m, unsigned long old, unsigned long new); | 421 | volatile int * m, unsigned long old, unsigned long new); |
321 | #define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels | 422 | #define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels |
423 | extern unsigned long __cmpxchg_u64_local_unsupported_on_32bit_kernels( | ||
424 | volatile int * m, unsigned long old, unsigned long new); | ||
425 | #define __cmpxchg_u64_local __cmpxchg_u64_local_unsupported_on_32bit_kernels | ||
322 | #endif | 426 | #endif |
323 | 427 | ||
324 | /* This function doesn't exist, so you'll get a linker error | 428 | /* This function doesn't exist, so you'll get a linker error |
@@ -338,7 +442,26 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, | |||
338 | return old; | 442 | return old; |
339 | } | 443 | } |
340 | 444 | ||
341 | #define cmpxchg(ptr,old,new) ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr)))) | 445 | static inline unsigned long __cmpxchg_local(volatile void * ptr, |
446 | unsigned long old, unsigned long new, int size) | ||
447 | { | ||
448 | switch (size) { | ||
449 | case 4: | ||
450 | return __cmpxchg_u32_local(ptr, old, new); | ||
451 | case 8: | ||
452 | return __cmpxchg_u64_local(ptr, old, new); | ||
453 | } | ||
454 | __cmpxchg_called_with_bad_pointer(); | ||
455 | return old; | ||
456 | } | ||
457 | |||
458 | #define cmpxchg(ptr,old,new) \ | ||
459 | ((__typeof__(*(ptr)))__cmpxchg((ptr), \ | ||
460 | (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr)))) | ||
461 | |||
462 | #define cmpxchg_local(ptr,old,new) \ | ||
463 | ((__typeof__(*(ptr)))__cmpxchg_local((ptr), \ | ||
464 | (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr)))) | ||
342 | 465 | ||
343 | extern void set_handler (unsigned long offset, void *addr, unsigned long len); | 466 | extern void set_handler (unsigned long offset, void *addr, unsigned long len); |
344 | extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len); | 467 | extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len); |