cmpxchg.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_CSKY_CMPXCHG_H
  3. #define __ASM_CSKY_CMPXCHG_H
  4. #ifdef CONFIG_SMP
  5. #include <linux/bug.h>
  6. #include <asm/barrier.h>
  7. #include <linux/cmpxchg-emu.h>
  8. #define __xchg_relaxed(new, ptr, size) \
  9. ({ \
  10. __typeof__(ptr) __ptr = (ptr); \
  11. __typeof__(new) __new = (new); \
  12. __typeof__(*(ptr)) __ret; \
  13. unsigned long tmp; \
  14. switch (size) { \
  15. case 2: { \
  16. u32 ret; \
  17. u32 shif = ((ulong)__ptr & 2) ? 16 : 0; \
  18. u32 mask = 0xffff << shif; \
  19. __ptr = (__typeof__(ptr))((ulong)__ptr & ~2); \
  20. __asm__ __volatile__ ( \
  21. "1: ldex.w %0, (%4)\n" \
  22. " and %1, %0, %2\n" \
  23. " or %1, %1, %3\n" \
  24. " stex.w %1, (%4)\n" \
  25. " bez %1, 1b\n" \
  26. : "=&r" (ret), "=&r" (tmp) \
  27. : "r" (~mask), \
  28. "r" ((u32)__new << shif), \
  29. "r" (__ptr) \
  30. : "memory"); \
  31. __ret = (__typeof__(*(ptr))) \
  32. ((ret & mask) >> shif); \
  33. break; \
  34. } \
  35. case 4: \
  36. asm volatile ( \
  37. "1: ldex.w %0, (%3) \n" \
  38. " mov %1, %2 \n" \
  39. " stex.w %1, (%3) \n" \
  40. " bez %1, 1b \n" \
  41. : "=&r" (__ret), "=&r" (tmp) \
  42. : "r" (__new), "r"(__ptr) \
  43. :); \
  44. break; \
  45. default: \
  46. BUILD_BUG(); \
  47. } \
  48. __ret; \
  49. })
  50. #define arch_xchg_relaxed(ptr, x) \
  51. (__xchg_relaxed((x), (ptr), sizeof(*(ptr))))
  52. #define __cmpxchg_relaxed(ptr, old, new, size) \
  53. ({ \
  54. __typeof__(ptr) __ptr = (ptr); \
  55. __typeof__(new) __new = (new); \
  56. __typeof__(new) __tmp; \
  57. __typeof__(old) __old = (old); \
  58. __typeof__(*(ptr)) __ret; \
  59. switch (size) { \
  60. case 1: \
  61. __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
  62. break; \
  63. case 4: \
  64. asm volatile ( \
  65. "1: ldex.w %0, (%3) \n" \
  66. " cmpne %0, %4 \n" \
  67. " bt 2f \n" \
  68. " mov %1, %2 \n" \
  69. " stex.w %1, (%3) \n" \
  70. " bez %1, 1b \n" \
  71. "2: \n" \
  72. : "=&r" (__ret), "=&r" (__tmp) \
  73. : "r" (__new), "r"(__ptr), "r"(__old) \
  74. :); \
  75. break; \
  76. default: \
  77. BUILD_BUG(); \
  78. } \
  79. __ret; \
  80. })
  81. #define arch_cmpxchg_relaxed(ptr, o, n) \
  82. (__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr))))
  83. #define __cmpxchg_acquire(ptr, old, new, size) \
  84. ({ \
  85. __typeof__(ptr) __ptr = (ptr); \
  86. __typeof__(new) __new = (new); \
  87. __typeof__(new) __tmp; \
  88. __typeof__(old) __old = (old); \
  89. __typeof__(*(ptr)) __ret; \
  90. switch (size) { \
  91. case 1: \
  92. __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
  93. break; \
  94. case 4: \
  95. asm volatile ( \
  96. "1: ldex.w %0, (%3) \n" \
  97. " cmpne %0, %4 \n" \
  98. " bt 2f \n" \
  99. " mov %1, %2 \n" \
  100. " stex.w %1, (%3) \n" \
  101. " bez %1, 1b \n" \
  102. ACQUIRE_FENCE \
  103. "2: \n" \
  104. : "=&r" (__ret), "=&r" (__tmp) \
  105. : "r" (__new), "r"(__ptr), "r"(__old) \
  106. :); \
  107. break; \
  108. default: \
  109. BUILD_BUG(); \
  110. } \
  111. __ret; \
  112. })
  113. #define arch_cmpxchg_acquire(ptr, o, n) \
  114. (__cmpxchg_acquire((ptr), (o), (n), sizeof(*(ptr))))
  115. #define __cmpxchg(ptr, old, new, size) \
  116. ({ \
  117. __typeof__(ptr) __ptr = (ptr); \
  118. __typeof__(new) __new = (new); \
  119. __typeof__(new) __tmp; \
  120. __typeof__(old) __old = (old); \
  121. __typeof__(*(ptr)) __ret; \
  122. switch (size) { \
  123. case 1: \
  124. __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
  125. break; \
  126. case 4: \
  127. asm volatile ( \
  128. RELEASE_FENCE \
  129. "1: ldex.w %0, (%3) \n" \
  130. " cmpne %0, %4 \n" \
  131. " bt 2f \n" \
  132. " mov %1, %2 \n" \
  133. " stex.w %1, (%3) \n" \
  134. " bez %1, 1b \n" \
  135. FULL_FENCE \
  136. "2: \n" \
  137. : "=&r" (__ret), "=&r" (__tmp) \
  138. : "r" (__new), "r"(__ptr), "r"(__old) \
  139. :); \
  140. break; \
  141. default: \
  142. BUILD_BUG(); \
  143. } \
  144. __ret; \
  145. })
  146. #define arch_cmpxchg(ptr, o, n) \
  147. (__cmpxchg((ptr), (o), (n), sizeof(*(ptr))))
  148. #define arch_cmpxchg_local(ptr, o, n) \
  149. (__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr))))
  150. #else
  151. #include <asm-generic/cmpxchg.h>
  152. #endif
  153. #endif /* __ASM_CSKY_CMPXCHG_H */