diff options
author | Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | 2007-05-08 03:34:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:19 -0400 |
commit | f46e477ed94f6407982690ef53dab7898834268f (patch) | |
tree | 40b53e2bfab3f532fcd490a5aad54b39deef7a51 /include/asm-powerpc/system.h | |
parent | 8ffe9d0bffa441de41d8543a984e552d49293641 (diff) |
atomic.h: add atomic64 cmpxchg, xchg and add_unless to powerpc
[akpm@linux-foundation.org: build fixes]
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/asm-powerpc/system.h')
-rw-r--r-- | include/asm-powerpc/system.h | 130 |
1 files changed, 129 insertions, 1 deletions
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index d3e0906ff2bc..77bf5873a013 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
8 | 8 | ||
9 | #include <asm/hw_irq.h> | 9 | #include <asm/hw_irq.h> |
10 | #include <asm/atomic.h> | ||
11 | 10 | ||
12 | /* | 11 | /* |
13 | * Memory barrier. | 12 | * Memory barrier. |
@@ -227,6 +226,29 @@ __xchg_u32(volatile void *p, unsigned long val) | |||
227 | return prev; | 226 | return prev; |
228 | } | 227 | } |
229 | 228 | ||
229 | /* | ||
230 | * Atomic exchange | ||
231 | * | ||
232 | * Changes the memory location '*ptr' to be val and returns | ||
233 | * the previous value stored there. | ||
234 | */ | ||
235 | static __inline__ unsigned long | ||
236 | __xchg_u32_local(volatile void *p, unsigned long val) | ||
237 | { | ||
238 | unsigned long prev; | ||
239 | |||
240 | __asm__ __volatile__( | ||
241 | "1: lwarx %0,0,%2 \n" | ||
242 | PPC405_ERR77(0,%2) | ||
243 | " stwcx. %3,0,%2 \n\ | ||
244 | bne- 1b" | ||
245 | : "=&r" (prev), "+m" (*(volatile unsigned int *)p) | ||
246 | : "r" (p), "r" (val) | ||
247 | : "cc", "memory"); | ||
248 | |||
249 | return prev; | ||
250 | } | ||
251 | |||
230 | #ifdef CONFIG_PPC64 | 252 | #ifdef CONFIG_PPC64 |
231 | static __inline__ unsigned long | 253 | static __inline__ unsigned long |
232 | __xchg_u64(volatile void *p, unsigned long val) | 254 | __xchg_u64(volatile void *p, unsigned long val) |
@@ -246,6 +268,23 @@ __xchg_u64(volatile void *p, unsigned long val) | |||
246 | 268 | ||
247 | return prev; | 269 | return prev; |
248 | } | 270 | } |
271 | |||
272 | static __inline__ unsigned long | ||
273 | __xchg_u64_local(volatile void *p, unsigned long val) | ||
274 | { | ||
275 | unsigned long prev; | ||
276 | |||
277 | __asm__ __volatile__( | ||
278 | "1: ldarx %0,0,%2 \n" | ||
279 | PPC405_ERR77(0,%2) | ||
280 | " stdcx. %3,0,%2 \n\ | ||
281 | bne- 1b" | ||
282 | : "=&r" (prev), "+m" (*(volatile unsigned long *)p) | ||
283 | : "r" (p), "r" (val) | ||
284 | : "cc", "memory"); | ||
285 | |||
286 | return prev; | ||
287 | } | ||
249 | #endif | 288 | #endif |
250 | 289 | ||
251 | /* | 290 | /* |
@@ -269,12 +308,33 @@ __xchg(volatile void *ptr, unsigned long x, unsigned int size) | |||
269 | return x; | 308 | return x; |
270 | } | 309 | } |
271 | 310 | ||
311 | static __inline__ unsigned long | ||
312 | __xchg_local(volatile void *ptr, unsigned long x, unsigned int size) | ||
313 | { | ||
314 | switch (size) { | ||
315 | case 4: | ||
316 | return __xchg_u32_local(ptr, x); | ||
317 | #ifdef CONFIG_PPC64 | ||
318 | case 8: | ||
319 | return __xchg_u64_local(ptr, x); | ||
320 | #endif | ||
321 | } | ||
322 | __xchg_called_with_bad_pointer(); | ||
323 | return x; | ||
324 | } | ||
272 | #define xchg(ptr,x) \ | 325 | #define xchg(ptr,x) \ |
273 | ({ \ | 326 | ({ \ |
274 | __typeof__(*(ptr)) _x_ = (x); \ | 327 | __typeof__(*(ptr)) _x_ = (x); \ |
275 | (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ | 328 | (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ |
276 | }) | 329 | }) |
277 | 330 | ||
331 | #define xchg_local(ptr,x) \ | ||
332 | ({ \ | ||
333 | __typeof__(*(ptr)) _x_ = (x); \ | ||
334 | (__typeof__(*(ptr))) __xchg_local((ptr), \ | ||
335 | (unsigned long)_x_, sizeof(*(ptr))); \ | ||
336 | }) | ||
337 | |||
278 | #define tas(ptr) (xchg((ptr),1)) | 338 | #define tas(ptr) (xchg((ptr),1)) |
279 | 339 | ||
280 | /* | 340 | /* |
@@ -306,6 +366,28 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) | |||
306 | return prev; | 366 | return prev; |
307 | } | 367 | } |
308 | 368 | ||
369 | static __inline__ unsigned long | ||
370 | __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old, | ||
371 | unsigned long new) | ||
372 | { | ||
373 | unsigned int prev; | ||
374 | |||
375 | __asm__ __volatile__ ( | ||
376 | "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ | ||
377 | cmpw 0,%0,%3\n\ | ||
378 | bne- 2f\n" | ||
379 | PPC405_ERR77(0,%2) | ||
380 | " stwcx. %4,0,%2\n\ | ||
381 | bne- 1b" | ||
382 | "\n\ | ||
383 | 2:" | ||
384 | : "=&r" (prev), "+m" (*p) | ||
385 | : "r" (p), "r" (old), "r" (new) | ||
386 | : "cc", "memory"); | ||
387 | |||
388 | return prev; | ||
389 | } | ||
390 | |||
309 | #ifdef CONFIG_PPC64 | 391 | #ifdef CONFIG_PPC64 |
310 | static __inline__ unsigned long | 392 | static __inline__ unsigned long |
311 | __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) | 393 | __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) |
@@ -328,6 +410,27 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) | |||
328 | 410 | ||
329 | return prev; | 411 | return prev; |
330 | } | 412 | } |
413 | |||
414 | static __inline__ unsigned long | ||
415 | __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old, | ||
416 | unsigned long new) | ||
417 | { | ||
418 | unsigned long prev; | ||
419 | |||
420 | __asm__ __volatile__ ( | ||
421 | "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ | ||
422 | cmpd 0,%0,%3\n\ | ||
423 | bne- 2f\n\ | ||
424 | stdcx. %4,0,%2\n\ | ||
425 | bne- 1b" | ||
426 | "\n\ | ||
427 | 2:" | ||
428 | : "=&r" (prev), "+m" (*p) | ||
429 | : "r" (p), "r" (old), "r" (new) | ||
430 | : "cc", "memory"); | ||
431 | |||
432 | return prev; | ||
433 | } | ||
331 | #endif | 434 | #endif |
332 | 435 | ||
333 | /* This function doesn't exist, so you'll get a linker error | 436 | /* This function doesn't exist, so you'll get a linker error |
@@ -350,6 +453,22 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, | |||
350 | return old; | 453 | return old; |
351 | } | 454 | } |
352 | 455 | ||
456 | static __inline__ unsigned long | ||
457 | __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new, | ||
458 | unsigned int size) | ||
459 | { | ||
460 | switch (size) { | ||
461 | case 4: | ||
462 | return __cmpxchg_u32_local(ptr, old, new); | ||
463 | #ifdef CONFIG_PPC64 | ||
464 | case 8: | ||
465 | return __cmpxchg_u64_local(ptr, old, new); | ||
466 | #endif | ||
467 | } | ||
468 | __cmpxchg_called_with_bad_pointer(); | ||
469 | return old; | ||
470 | } | ||
471 | |||
353 | #define cmpxchg(ptr,o,n) \ | 472 | #define cmpxchg(ptr,o,n) \ |
354 | ({ \ | 473 | ({ \ |
355 | __typeof__(*(ptr)) _o_ = (o); \ | 474 | __typeof__(*(ptr)) _o_ = (o); \ |
@@ -358,6 +477,15 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, | |||
358 | (unsigned long)_n_, sizeof(*(ptr))); \ | 477 | (unsigned long)_n_, sizeof(*(ptr))); \ |
359 | }) | 478 | }) |
360 | 479 | ||
480 | |||
481 | #define cmpxchg_local(ptr,o,n) \ | ||
482 | ({ \ | ||
483 | __typeof__(*(ptr)) _o_ = (o); \ | ||
484 | __typeof__(*(ptr)) _n_ = (n); \ | ||
485 | (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \ | ||
486 | (unsigned long)_n_, sizeof(*(ptr))); \ | ||
487 | }) | ||
488 | |||
361 | #ifdef CONFIG_PPC64 | 489 | #ifdef CONFIG_PPC64 |
362 | /* | 490 | /* |
363 | * We handle most unaligned accesses in hardware. On the other hand | 491 | * We handle most unaligned accesses in hardware. On the other hand |