1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_POWERPC_CMPXCHG_H_ 3 #define _ASM_POWERPC_CMPXCHG_H_ 4 5 #ifdef __KERNEL__ 6 #include <linux/compiler.h> 7 #include <asm/synch.h> 8 #include <linux/bug.h> 9 10 #ifdef __BIG_ENDIAN 11 #define BITOFF_CAL(size, off) ((sizeof(u32) - size - off) * BITS_PER_BYTE) 12 #else 13 #define BITOFF_CAL(size, off) (off * BITS_PER_BYTE) 14 #endif 15 16 #define XCHG_GEN(type, sfx, cl) \ 17 static inline u32 __xchg_##type##sfx(volatile void *p, u32 val) \ 18 { \ 19 unsigned int prev, prev_mask, tmp, bitoff, off; \ 20 \ 21 off = (unsigned long)p % sizeof(u32); \ 22 bitoff = BITOFF_CAL(sizeof(type), off); \ 23 p -= off; \ 24 val <<= bitoff; \ 25 prev_mask = (u32)(type)-1 << bitoff; \ 26 \ 27 __asm__ __volatile__( \ 28 "1: lwarx %0,0,%3\n" \ 29 " andc %1,%0,%5\n" \ 30 " or %1,%1,%4\n" \ 31 " stwcx. %1,0,%3\n" \ 32 " bne- 1b\n" \ 33 : "=&r" (prev), "=&r" (tmp), "+m" (*(u32*)p) \ 34 : "r" (p), "r" (val), "r" (prev_mask) \ 35 : "cc", cl); \ 36 \ 37 return prev >> bitoff; \ 38 } 39 40 #define CMPXCHG_GEN(type, sfx, br, br2, cl) \ 41 static inline \ 42 u32 __cmpxchg_##type##sfx(volatile void *p, u32 old, u32 new) \ 43 { \ 44 unsigned int prev, prev_mask, tmp, bitoff, off; \ 45 \ 46 off = (unsigned long)p % sizeof(u32); \ 47 bitoff = BITOFF_CAL(sizeof(type), off); \ 48 p -= off; \ 49 old <<= bitoff; \ 50 new <<= bitoff; \ 51 prev_mask = (u32)(type)-1 << bitoff; \ 52 \ 53 __asm__ __volatile__( \ 54 br \ 55 "1: lwarx %0,0,%3\n" \ 56 " and %1,%0,%6\n" \ 57 " cmpw 0,%1,%4\n" \ 58 " bne- 2f\n" \ 59 " andc %1,%0,%6\n" \ 60 " or %1,%1,%5\n" \ 61 " stwcx. %1,0,%3\n" \ 62 " bne- 1b\n" \ 63 br2 \ 64 "\n" \ 65 "2:" \ 66 : "=&r" (prev), "=&r" (tmp), "+m" (*(u32*)p) \ 67 : "r" (p), "r" (old), "r" (new), "r" (prev_mask) \ 68 : "cc", cl); \ 69 \ 70 return prev >> bitoff; \ 71 } 72 73 /* 74 * Atomic exchange 75 * 76 * Changes the memory location '*p' to be val and returns 77 * the previous value stored there. 78 */ 79 80 #ifndef CONFIG_PPC_HAS_LBARX_LHARX 81 XCHG_GEN(u8, _local, "memory"); 82 XCHG_GEN(u8, _relaxed, "cc"); 83 XCHG_GEN(u16, _local, "memory"); 84 XCHG_GEN(u16, _relaxed, "cc"); 85 #else 86 static __always_inline unsigned long 87 __xchg_u8_local(volatile void *p, unsigned long val) 88 { 89 unsigned long prev; 90 91 __asm__ __volatile__( 92 "1: lbarx %0,0,%2 # __xchg_u8_local\n" 93 " stbcx. %3,0,%2 \n" 94 " bne- 1b" 95 : "=&r" (prev), "+m" (*(volatile unsigned char *)p) 96 : "r" (p), "r" (val) 97 : "cc", "memory"); 98 99 return prev; 100 } 101 102 static __always_inline unsigned long 103 __xchg_u8_relaxed(u8 *p, unsigned long val) 104 { 105 unsigned long prev; 106 107 __asm__ __volatile__( 108 "1: lbarx %0,0,%2 # __xchg_u8_relaxed\n" 109 " stbcx. %3,0,%2\n" 110 " bne- 1b" 111 : "=&r" (prev), "+m" (*p) 112 : "r" (p), "r" (val) 113 : "cc"); 114 115 return prev; 116 } 117 118 static __always_inline unsigned long 119 __xchg_u16_local(volatile void *p, unsigned long val) 120 { 121 unsigned long prev; 122 123 __asm__ __volatile__( 124 "1: lharx %0,0,%2 # __xchg_u16_local\n" 125 " sthcx. %3,0,%2\n" 126 " bne- 1b" 127 : "=&r" (prev), "+m" (*(volatile unsigned short *)p) 128 : "r" (p), "r" (val) 129 : "cc", "memory"); 130 131 return prev; 132 } 133 134 static __always_inline unsigned long 135 __xchg_u16_relaxed(u16 *p, unsigned long val) 136 { 137 unsigned long prev; 138 139 __asm__ __volatile__( 140 "1: lharx %0,0,%2 # __xchg_u16_relaxed\n" 141 " sthcx. %3,0,%2\n" 142 " bne- 1b" 143 : "=&r" (prev), "+m" (*p) 144 : "r" (p), "r" (val) 145 : "cc"); 146 147 return prev; 148 } 149 #endif 150 151 static __always_inline unsigned long 152 __xchg_u32_local(volatile void *p, unsigned long val) 153 { 154 unsigned long prev; 155 156 __asm__ __volatile__( 157 "1: lwarx %0,0,%2 \n" 158 " stwcx. %3,0,%2 \n\ 159 bne- 1b" 160 : "=&r" (prev), "+m" (*(volatile unsigned int *)p) 161 : "r" (p), "r" (val) 162 : "cc", "memory"); 163 164 return prev; 165 } 166 167 static __always_inline unsigned long 168 __xchg_u32_relaxed(u32 *p, unsigned long val) 169 { 170 unsigned long prev; 171 172 __asm__ __volatile__( 173 "1: lwarx %0,0,%2\n" 174 " stwcx. %3,0,%2\n" 175 " bne- 1b" 176 : "=&r" (prev), "+m" (*p) 177 : "r" (p), "r" (val) 178 : "cc"); 179 180 return prev; 181 } 182 183 #ifdef CONFIG_PPC64 184 static __always_inline unsigned long 185 __xchg_u64_local(volatile void *p, unsigned long val) 186 { 187 unsigned long prev; 188 189 __asm__ __volatile__( 190 "1: ldarx %0,0,%2 \n" 191 " stdcx. %3,0,%2 \n\ 192 bne- 1b" 193 : "=&r" (prev), "+m" (*(volatile unsigned long *)p) 194 : "r" (p), "r" (val) 195 : "cc", "memory"); 196 197 return prev; 198 } 199 200 static __always_inline unsigned long 201 __xchg_u64_relaxed(u64 *p, unsigned long val) 202 { 203 unsigned long prev; 204 205 __asm__ __volatile__( 206 "1: ldarx %0,0,%2\n" 207 " stdcx. %3,0,%2\n" 208 " bne- 1b" 209 : "=&r" (prev), "+m" (*p) 210 : "r" (p), "r" (val) 211 : "cc"); 212 213 return prev; 214 } 215 #endif 216 217 static __always_inline unsigned long 218 __xchg_local(void *ptr, unsigned long x, unsigned int size) 219 { 220 switch (size) { 221 case 1: 222 return __xchg_u8_local(ptr, x); 223 case 2: 224 return __xchg_u16_local(ptr, x); 225 case 4: 226 return __xchg_u32_local(ptr, x); 227 #ifdef CONFIG_PPC64 228 case 8: 229 return __xchg_u64_local(ptr, x); 230 #endif 231 } 232 BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg_local"); 233 return x; 234 } 235 236 static __always_inline unsigned long 237 __xchg_relaxed(void *ptr, unsigned long x, unsigned int size) 238 { 239 switch (size) { 240 case 1: 241 return __xchg_u8_relaxed(ptr, x); 242 case 2: 243 return __xchg_u16_relaxed(ptr, x); 244 case 4: 245 return __xchg_u32_relaxed(ptr, x); 246 #ifdef CONFIG_PPC64 247 case 8: 248 return __xchg_u64_relaxed(ptr, x); 249 #endif 250 } 251 BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg_relaxed"); 252 return x; 253 } 254 #define arch_xchg_local(ptr,x) \ 255 ({ \ 256 __typeof__(*(ptr)) _x_ = (x); \ 257 (__typeof__(*(ptr))) __xchg_local((ptr), \ 258 (unsigned long)_x_, sizeof(*(ptr))); \ 259 }) 260 261 #define arch_xchg_relaxed(ptr, x) \ 262 ({ \ 263 __typeof__(*(ptr)) _x_ = (x); \ 264 (__typeof__(*(ptr))) __xchg_relaxed((ptr), \ 265 (unsigned long)_x_, sizeof(*(ptr))); \ 266 }) 267 268 /* 269 * Compare and exchange - if *p == old, set it to new, 270 * and return the old value of *p. 271 */ 272 #ifndef CONFIG_PPC_HAS_LBARX_LHARX 273 CMPXCHG_GEN(u8, , PPC_ATOMIC_ENTRY_BARRIER, PPC_ATOMIC_EXIT_BARRIER, "memory"); 274 CMPXCHG_GEN(u8, _local, , , "memory"); 275 CMPXCHG_GEN(u8, _acquire, , PPC_ACQUIRE_BARRIER, "memory"); 276 CMPXCHG_GEN(u8, _relaxed, , , "cc"); 277 CMPXCHG_GEN(u16, , PPC_ATOMIC_ENTRY_BARRIER, PPC_ATOMIC_EXIT_BARRIER, "memory"); 278 CMPXCHG_GEN(u16, _local, , , "memory"); 279 CMPXCHG_GEN(u16, _acquire, , PPC_ACQUIRE_BARRIER, "memory"); 280 CMPXCHG_GEN(u16, _relaxed, , , "cc"); 281 #else 282 static __always_inline unsigned long 283 __cmpxchg_u8(volatile unsigned char *p, unsigned long old, unsigned long new) 284 { 285 unsigned int prev; 286 287 __asm__ __volatile__ ( 288 PPC_ATOMIC_ENTRY_BARRIER 289 "1: lbarx %0,0,%2 # __cmpxchg_u8\n" 290 " cmpw 0,%0,%3\n" 291 " bne- 2f\n" 292 " stbcx. %4,0,%2\n" 293 " bne- 1b" 294 PPC_ATOMIC_EXIT_BARRIER 295 "\n\ 296 2:" 297 : "=&r" (prev), "+m" (*p) 298 : "r" (p), "r" (old), "r" (new) 299 : "cc", "memory"); 300 301 return prev; 302 } 303 304 static __always_inline unsigned long 305 __cmpxchg_u8_local(volatile unsigned char *p, unsigned long old, 306 unsigned long new) 307 { 308 unsigned int prev; 309 310 __asm__ __volatile__ ( 311 "1: lbarx %0,0,%2 # __cmpxchg_u8_local\n" 312 " cmpw 0,%0,%3\n" 313 " bne- 2f\n" 314 " stbcx. %4,0,%2\n" 315 " bne- 1b\n" 316 "2:" 317 : "=&r" (prev), "+m" (*p) 318 : "r" (p), "r" (old), "r" (new) 319 : "cc", "memory"); 320 321 return prev; 322 } 323 324 static __always_inline unsigned long 325 __cmpxchg_u8_relaxed(u8 *p, unsigned long old, unsigned long new) 326 { 327 unsigned long prev; 328 329 __asm__ __volatile__ ( 330 "1: lbarx %0,0,%2 # __cmpxchg_u8_relaxed\n" 331 " cmpw 0,%0,%3\n" 332 " bne- 2f\n" 333 " stbcx. %4,0,%2\n" 334 " bne- 1b\n" 335 "2:" 336 : "=&r" (prev), "+m" (*p) 337 : "r" (p), "r" (old), "r" (new) 338 : "cc"); 339 340 return prev; 341 } 342 343 static __always_inline unsigned long 344 __cmpxchg_u8_acquire(u8 *p, unsigned long old, unsigned long new) 345 { 346 unsigned long prev; 347 348 __asm__ __volatile__ ( 349 "1: lbarx %0,0,%2 # __cmpxchg_u8_acquire\n" 350 " cmpw 0,%0,%3\n" 351 " bne- 2f\n" 352 " stbcx. %4,0,%2\n" 353 " bne- 1b\n" 354 PPC_ACQUIRE_BARRIER 355 "2:" 356 : "=&r" (prev), "+m" (*p) 357 : "r" (p), "r" (old), "r" (new) 358 : "cc", "memory"); 359 360 return prev; 361 } 362 363 static __always_inline unsigned long 364 __cmpxchg_u16(volatile unsigned short *p, unsigned long old, unsigned long new) 365 { 366 unsigned int prev; 367 368 __asm__ __volatile__ ( 369 PPC_ATOMIC_ENTRY_BARRIER 370 "1: lharx %0,0,%2 # __cmpxchg_u16\n" 371 " cmpw 0,%0,%3\n" 372 " bne- 2f\n" 373 " sthcx. %4,0,%2\n" 374 " bne- 1b\n" 375 PPC_ATOMIC_EXIT_BARRIER 376 "2:" 377 : "=&r" (prev), "+m" (*p) 378 : "r" (p), "r" (old), "r" (new) 379 : "cc", "memory"); 380 381 return prev; 382 } 383 384 static __always_inline unsigned long 385 __cmpxchg_u16_local(volatile unsigned short *p, unsigned long old, 386 unsigned long new) 387 { 388 unsigned int prev; 389 390 __asm__ __volatile__ ( 391 "1: lharx %0,0,%2 # __cmpxchg_u16_local\n" 392 " cmpw 0,%0,%3\n" 393 " bne- 2f\n" 394 " sthcx. %4,0,%2\n" 395 " bne- 1b" 396 "2:" 397 : "=&r" (prev), "+m" (*p) 398 : "r" (p), "r" (old), "r" (new) 399 : "cc", "memory"); 400 401 return prev; 402 } 403 404 static __always_inline unsigned long 405 __cmpxchg_u16_relaxed(u16 *p, unsigned long old, unsigned long new) 406 { 407 unsigned long prev; 408 409 __asm__ __volatile__ ( 410 "1: lharx %0,0,%2 # __cmpxchg_u16_relaxed\n" 411 " cmpw 0,%0,%3\n" 412 " bne- 2f\n" 413 " sthcx. %4,0,%2\n" 414 " bne- 1b\n" 415 "2:" 416 : "=&r" (prev), "+m" (*p) 417 : "r" (p), "r" (old), "r" (new) 418 : "cc"); 419 420 return prev; 421 } 422 423 static __always_inline unsigned long 424 __cmpxchg_u16_acquire(u16 *p, unsigned long old, unsigned long new) 425 { 426 unsigned long prev; 427 428 __asm__ __volatile__ ( 429 "1: lharx %0,0,%2 # __cmpxchg_u16_acquire\n" 430 " cmpw 0,%0,%3\n" 431 " bne- 2f\n" 432 " sthcx. %4,0,%2\n" 433 " bne- 1b\n" 434 PPC_ACQUIRE_BARRIER 435 "2:" 436 : "=&r" (prev), "+m" (*p) 437 : "r" (p), "r" (old), "r" (new) 438 : "cc", "memory"); 439 440 return prev; 441 } 442 #endif 443 444 static __always_inline unsigned long 445 __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) 446 { 447 unsigned int prev; 448 449 __asm__ __volatile__ ( 450 PPC_ATOMIC_ENTRY_BARRIER 451 "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ 452 cmpw 0,%0,%3\n\ 453 bne- 2f\n" 454 " stwcx. %4,0,%2\n\ 455 bne- 1b" 456 PPC_ATOMIC_EXIT_BARRIER 457 "\n\ 458 2:" 459 : "=&r" (prev), "+m" (*p) 460 : "r" (p), "r" (old), "r" (new) 461 : "cc", "memory"); 462 463 return prev; 464 } 465 466 static __always_inline unsigned long 467 __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old, 468 unsigned long new) 469 { 470 unsigned int prev; 471 472 __asm__ __volatile__ ( 473 "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ 474 cmpw 0,%0,%3\n\ 475 bne- 2f\n" 476 " stwcx. %4,0,%2\n\ 477 bne- 1b" 478 "\n\ 479 2:" 480 : "=&r" (prev), "+m" (*p) 481 : "r" (p), "r" (old), "r" (new) 482 : "cc", "memory"); 483 484 return prev; 485 } 486 487 static __always_inline unsigned long 488 __cmpxchg_u32_relaxed(u32 *p, unsigned long old, unsigned long new) 489 { 490 unsigned long prev; 491 492 __asm__ __volatile__ ( 493 "1: lwarx %0,0,%2 # __cmpxchg_u32_relaxed\n" 494 " cmpw 0,%0,%3\n" 495 " bne- 2f\n" 496 " stwcx. %4,0,%2\n" 497 " bne- 1b\n" 498 "2:" 499 : "=&r" (prev), "+m" (*p) 500 : "r" (p), "r" (old), "r" (new) 501 : "cc"); 502 503 return prev; 504 } 505 506 /* 507 * cmpxchg family don't have order guarantee if cmp part fails, therefore we 508 * can avoid superfluous barriers if we use assembly code to implement 509 * cmpxchg() and cmpxchg_acquire(), however we don't do the similar for 510 * cmpxchg_release() because that will result in putting a barrier in the 511 * middle of a ll/sc loop, which is probably a bad idea. For example, this 512 * might cause the conditional store more likely to fail. 513 */ 514 static __always_inline unsigned long 515 __cmpxchg_u32_acquire(u32 *p, unsigned long old, unsigned long new) 516 { 517 unsigned long prev; 518 519 __asm__ __volatile__ ( 520 "1: lwarx %0,0,%2 # __cmpxchg_u32_acquire\n" 521 " cmpw 0,%0,%3\n" 522 " bne- 2f\n" 523 " stwcx. %4,0,%2\n" 524 " bne- 1b\n" 525 PPC_ACQUIRE_BARRIER 526 "\n" 527 "2:" 528 : "=&r" (prev), "+m" (*p) 529 : "r" (p), "r" (old), "r" (new) 530 : "cc", "memory"); 531 532 return prev; 533 } 534 535 #ifdef CONFIG_PPC64 536 static __always_inline unsigned long 537 __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) 538 { 539 unsigned long prev; 540 541 __asm__ __volatile__ ( 542 PPC_ATOMIC_ENTRY_BARRIER 543 "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ 544 cmpd 0,%0,%3\n\ 545 bne- 2f\n\ 546 stdcx. %4,0,%2\n\ 547 bne- 1b" 548 PPC_ATOMIC_EXIT_BARRIER 549 "\n\ 550 2:" 551 : "=&r" (prev), "+m" (*p) 552 : "r" (p), "r" (old), "r" (new) 553 : "cc", "memory"); 554 555 return prev; 556 } 557 558 static __always_inline unsigned long 559 __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old, 560 unsigned long new) 561 { 562 unsigned long prev; 563 564 __asm__ __volatile__ ( 565 "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ 566 cmpd 0,%0,%3\n\ 567 bne- 2f\n\ 568 stdcx. %4,0,%2\n\ 569 bne- 1b" 570 "\n\ 571 2:" 572 : "=&r" (prev), "+m" (*p) 573 : "r" (p), "r" (old), "r" (new) 574 : "cc", "memory"); 575 576 return prev; 577 } 578 579 static __always_inline unsigned long 580 __cmpxchg_u64_relaxed(u64 *p, unsigned long old, unsigned long new) 581 { 582 unsigned long prev; 583 584 __asm__ __volatile__ ( 585 "1: ldarx %0,0,%2 # __cmpxchg_u64_relaxed\n" 586 " cmpd 0,%0,%3\n" 587 " bne- 2f\n" 588 " stdcx. %4,0,%2\n" 589 " bne- 1b\n" 590 "2:" 591 : "=&r" (prev), "+m" (*p) 592 : "r" (p), "r" (old), "r" (new) 593 : "cc"); 594 595 return prev; 596 } 597 598 static __always_inline unsigned long 599 __cmpxchg_u64_acquire(u64 *p, unsigned long old, unsigned long new) 600 { 601 unsigned long prev; 602 603 __asm__ __volatile__ ( 604 "1: ldarx %0,0,%2 # __cmpxchg_u64_acquire\n" 605 " cmpd 0,%0,%3\n" 606 " bne- 2f\n" 607 " stdcx. %4,0,%2\n" 608 " bne- 1b\n" 609 PPC_ACQUIRE_BARRIER 610 "\n" 611 "2:" 612 : "=&r" (prev), "+m" (*p) 613 : "r" (p), "r" (old), "r" (new) 614 : "cc", "memory"); 615 616 return prev; 617 } 618 #endif 619 620 static __always_inline unsigned long 621 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, 622 unsigned int size) 623 { 624 switch (size) { 625 case 1: 626 return __cmpxchg_u8(ptr, old, new); 627 case 2: 628 return __cmpxchg_u16(ptr, old, new); 629 case 4: 630 return __cmpxchg_u32(ptr, old, new); 631 #ifdef CONFIG_PPC64 632 case 8: 633 return __cmpxchg_u64(ptr, old, new); 634 #endif 635 } 636 BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg"); 637 return old; 638 } 639 640 static __always_inline unsigned long 641 __cmpxchg_local(void *ptr, unsigned long old, unsigned long new, 642 unsigned int size) 643 { 644 switch (size) { 645 case 1: 646 return __cmpxchg_u8_local(ptr, old, new); 647 case 2: 648 return __cmpxchg_u16_local(ptr, old, new); 649 case 4: 650 return __cmpxchg_u32_local(ptr, old, new); 651 #ifdef CONFIG_PPC64 652 case 8: 653 return __cmpxchg_u64_local(ptr, old, new); 654 #endif 655 } 656 BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_local"); 657 return old; 658 } 659 660 static __always_inline unsigned long 661 __cmpxchg_relaxed(void *ptr, unsigned long old, unsigned long new, 662 unsigned int size) 663 { 664 switch (size) { 665 case 1: 666 return __cmpxchg_u8_relaxed(ptr, old, new); 667 case 2: 668 return __cmpxchg_u16_relaxed(ptr, old, new); 669 case 4: 670 return __cmpxchg_u32_relaxed(ptr, old, new); 671 #ifdef CONFIG_PPC64 672 case 8: 673 return __cmpxchg_u64_relaxed(ptr, old, new); 674 #endif 675 } 676 BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_relaxed"); 677 return old; 678 } 679 680 static __always_inline unsigned long 681 __cmpxchg_acquire(void *ptr, unsigned long old, unsigned long new, 682 unsigned int size) 683 { 684 switch (size) { 685 case 1: 686 return __cmpxchg_u8_acquire(ptr, old, new); 687 case 2: 688 return __cmpxchg_u16_acquire(ptr, old, new); 689 case 4: 690 return __cmpxchg_u32_acquire(ptr, old, new); 691 #ifdef CONFIG_PPC64 692 case 8: 693 return __cmpxchg_u64_acquire(ptr, old, new); 694 #endif 695 } 696 BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_acquire"); 697 return old; 698 } 699 #define arch_cmpxchg(ptr, o, n) \ 700 ({ \ 701 __typeof__(*(ptr)) _o_ = (o); \ 702 __typeof__(*(ptr)) _n_ = (n); \ 703 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ 704 (unsigned long)_n_, sizeof(*(ptr))); \ 705 }) 706 707 708 #define arch_cmpxchg_local(ptr, o, n) \ 709 ({ \ 710 __typeof__(*(ptr)) _o_ = (o); \ 711 __typeof__(*(ptr)) _n_ = (n); \ 712 (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \ 713 (unsigned long)_n_, sizeof(*(ptr))); \ 714 }) 715 716 #define arch_cmpxchg_relaxed(ptr, o, n) \ 717 ({ \ 718 __typeof__(*(ptr)) _o_ = (o); \ 719 __typeof__(*(ptr)) _n_ = (n); \ 720 (__typeof__(*(ptr))) __cmpxchg_relaxed((ptr), \ 721 (unsigned long)_o_, (unsigned long)_n_, \ 722 sizeof(*(ptr))); \ 723 }) 724 725 #define arch_cmpxchg_acquire(ptr, o, n) \ 726 ({ \ 727 __typeof__(*(ptr)) _o_ = (o); \ 728 __typeof__(*(ptr)) _n_ = (n); \ 729 (__typeof__(*(ptr))) __cmpxchg_acquire((ptr), \ 730 (unsigned long)_o_, (unsigned long)_n_, \ 731 sizeof(*(ptr))); \ 732 }) 733 #ifdef CONFIG_PPC64 734 #define arch_cmpxchg64(ptr, o, n) \ 735 ({ \ 736 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ 737 arch_cmpxchg((ptr), (o), (n)); \ 738 }) 739 #define arch_cmpxchg64_local(ptr, o, n) \ 740 ({ \ 741 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ 742 arch_cmpxchg_local((ptr), (o), (n)); \ 743 }) 744 #define arch_cmpxchg64_relaxed(ptr, o, n) \ 745 ({ \ 746 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ 747 arch_cmpxchg_relaxed((ptr), (o), (n)); \ 748 }) 749 #define arch_cmpxchg64_acquire(ptr, o, n) \ 750 ({ \ 751 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ 752 arch_cmpxchg_acquire((ptr), (o), (n)); \ 753 }) 754 #else 755 #include <asm-generic/cmpxchg-local.h> 756 #define arch_cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n)) 757 #endif 758 759 #endif /* __KERNEL__ */ 760 #endif /* _ASM_POWERPC_CMPXCHG_H_ */ 761