aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips/system.h
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>2007-05-08 03:34:47 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:20 -0400
commit7232311ef14c274d88871212a07557f18f4140d1 (patch)
tree46027210d51dee5fd5086f159d98bac3535a005d /include/asm-mips/system.h
parent4431f46f5fe0e3b740dfaf09ba34f0b14688185e (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.h125
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
265static 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
266static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old, 318static 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
371static 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
319extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels( 420extern 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
423extern 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)))) 445static 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
343extern void set_handler (unsigned long offset, void *addr, unsigned long len); 466extern void set_handler (unsigned long offset, void *addr, unsigned long len);
344extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len); 467extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);