atomic-amo.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Atomic operations (AMO).
  4. *
  5. * Copyright (C) 2020-2025 Loongson Technology Corporation Limited
  6. */
  7. #ifndef _ASM_ATOMIC_AMO_H
  8. #define _ASM_ATOMIC_AMO_H
  9. #include <linux/types.h>
  10. #include <asm/barrier.h>
  11. #include <asm/cmpxchg.h>
  12. #define ATOMIC_OP(op, I, asm_op) \
  13. static inline void arch_atomic_##op(int i, atomic_t *v) \
  14. { \
  15. __asm__ __volatile__( \
  16. "am"#asm_op".w" " $zero, %1, %0 \n" \
  17. : "+ZB" (v->counter) \
  18. : "r" (I) \
  19. : "memory"); \
  20. }
  21. #define ATOMIC_OP_RETURN(op, I, asm_op, c_op, mb, suffix) \
  22. static inline int arch_atomic_##op##_return##suffix(int i, atomic_t *v) \
  23. { \
  24. int result; \
  25. \
  26. __asm__ __volatile__( \
  27. "am"#asm_op#mb".w" " %1, %2, %0 \n" \
  28. : "+ZB" (v->counter), "=&r" (result) \
  29. : "r" (I) \
  30. : "memory"); \
  31. \
  32. return result c_op I; \
  33. }
  34. #define ATOMIC_FETCH_OP(op, I, asm_op, mb, suffix) \
  35. static inline int arch_atomic_fetch_##op##suffix(int i, atomic_t *v) \
  36. { \
  37. int result; \
  38. \
  39. __asm__ __volatile__( \
  40. "am"#asm_op#mb".w" " %1, %2, %0 \n" \
  41. : "+ZB" (v->counter), "=&r" (result) \
  42. : "r" (I) \
  43. : "memory"); \
  44. \
  45. return result; \
  46. }
  47. #define ATOMIC_OPS(op, I, asm_op, c_op) \
  48. ATOMIC_OP(op, I, asm_op) \
  49. ATOMIC_OP_RETURN(op, I, asm_op, c_op, _db, ) \
  50. ATOMIC_OP_RETURN(op, I, asm_op, c_op, , _relaxed) \
  51. ATOMIC_FETCH_OP(op, I, asm_op, _db, ) \
  52. ATOMIC_FETCH_OP(op, I, asm_op, , _relaxed)
  53. ATOMIC_OPS(add, i, add, +)
  54. ATOMIC_OPS(sub, -i, add, +)
  55. #define arch_atomic_add_return arch_atomic_add_return
  56. #define arch_atomic_add_return_acquire arch_atomic_add_return
  57. #define arch_atomic_add_return_release arch_atomic_add_return
  58. #define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed
  59. #define arch_atomic_sub_return arch_atomic_sub_return
  60. #define arch_atomic_sub_return_acquire arch_atomic_sub_return
  61. #define arch_atomic_sub_return_release arch_atomic_sub_return
  62. #define arch_atomic_sub_return_relaxed arch_atomic_sub_return_relaxed
  63. #define arch_atomic_fetch_add arch_atomic_fetch_add
  64. #define arch_atomic_fetch_add_acquire arch_atomic_fetch_add
  65. #define arch_atomic_fetch_add_release arch_atomic_fetch_add
  66. #define arch_atomic_fetch_add_relaxed arch_atomic_fetch_add_relaxed
  67. #define arch_atomic_fetch_sub arch_atomic_fetch_sub
  68. #define arch_atomic_fetch_sub_acquire arch_atomic_fetch_sub
  69. #define arch_atomic_fetch_sub_release arch_atomic_fetch_sub
  70. #define arch_atomic_fetch_sub_relaxed arch_atomic_fetch_sub_relaxed
  71. #undef ATOMIC_OPS
  72. #define ATOMIC_OPS(op, I, asm_op) \
  73. ATOMIC_OP(op, I, asm_op) \
  74. ATOMIC_FETCH_OP(op, I, asm_op, _db, ) \
  75. ATOMIC_FETCH_OP(op, I, asm_op, , _relaxed)
  76. ATOMIC_OPS(and, i, and)
  77. ATOMIC_OPS(or, i, or)
  78. ATOMIC_OPS(xor, i, xor)
  79. #define arch_atomic_fetch_and arch_atomic_fetch_and
  80. #define arch_atomic_fetch_and_acquire arch_atomic_fetch_and
  81. #define arch_atomic_fetch_and_release arch_atomic_fetch_and
  82. #define arch_atomic_fetch_and_relaxed arch_atomic_fetch_and_relaxed
  83. #define arch_atomic_fetch_or arch_atomic_fetch_or
  84. #define arch_atomic_fetch_or_acquire arch_atomic_fetch_or
  85. #define arch_atomic_fetch_or_release arch_atomic_fetch_or
  86. #define arch_atomic_fetch_or_relaxed arch_atomic_fetch_or_relaxed
  87. #define arch_atomic_fetch_xor arch_atomic_fetch_xor
  88. #define arch_atomic_fetch_xor_acquire arch_atomic_fetch_xor
  89. #define arch_atomic_fetch_xor_release arch_atomic_fetch_xor
  90. #define arch_atomic_fetch_xor_relaxed arch_atomic_fetch_xor_relaxed
  91. #undef ATOMIC_OPS
  92. #undef ATOMIC_FETCH_OP
  93. #undef ATOMIC_OP_RETURN
  94. #undef ATOMIC_OP
  95. #ifdef CONFIG_64BIT
  96. #define ATOMIC64_OP(op, I, asm_op) \
  97. static inline void arch_atomic64_##op(long i, atomic64_t *v) \
  98. { \
  99. __asm__ __volatile__( \
  100. "am"#asm_op".d " " $zero, %1, %0 \n" \
  101. : "+ZB" (v->counter) \
  102. : "r" (I) \
  103. : "memory"); \
  104. }
  105. #define ATOMIC64_OP_RETURN(op, I, asm_op, c_op, mb, suffix) \
  106. static inline long arch_atomic64_##op##_return##suffix(long i, atomic64_t *v) \
  107. { \
  108. long result; \
  109. __asm__ __volatile__( \
  110. "am"#asm_op#mb".d " " %1, %2, %0 \n" \
  111. : "+ZB" (v->counter), "=&r" (result) \
  112. : "r" (I) \
  113. : "memory"); \
  114. \
  115. return result c_op I; \
  116. }
  117. #define ATOMIC64_FETCH_OP(op, I, asm_op, mb, suffix) \
  118. static inline long arch_atomic64_fetch_##op##suffix(long i, atomic64_t *v) \
  119. { \
  120. long result; \
  121. \
  122. __asm__ __volatile__( \
  123. "am"#asm_op#mb".d " " %1, %2, %0 \n" \
  124. : "+ZB" (v->counter), "=&r" (result) \
  125. : "r" (I) \
  126. : "memory"); \
  127. \
  128. return result; \
  129. }
  130. #define ATOMIC64_OPS(op, I, asm_op, c_op) \
  131. ATOMIC64_OP(op, I, asm_op) \
  132. ATOMIC64_OP_RETURN(op, I, asm_op, c_op, _db, ) \
  133. ATOMIC64_OP_RETURN(op, I, asm_op, c_op, , _relaxed) \
  134. ATOMIC64_FETCH_OP(op, I, asm_op, _db, ) \
  135. ATOMIC64_FETCH_OP(op, I, asm_op, , _relaxed)
  136. ATOMIC64_OPS(add, i, add, +)
  137. ATOMIC64_OPS(sub, -i, add, +)
  138. #define arch_atomic64_add_return arch_atomic64_add_return
  139. #define arch_atomic64_add_return_acquire arch_atomic64_add_return
  140. #define arch_atomic64_add_return_release arch_atomic64_add_return
  141. #define arch_atomic64_add_return_relaxed arch_atomic64_add_return_relaxed
  142. #define arch_atomic64_sub_return arch_atomic64_sub_return
  143. #define arch_atomic64_sub_return_acquire arch_atomic64_sub_return
  144. #define arch_atomic64_sub_return_release arch_atomic64_sub_return
  145. #define arch_atomic64_sub_return_relaxed arch_atomic64_sub_return_relaxed
  146. #define arch_atomic64_fetch_add arch_atomic64_fetch_add
  147. #define arch_atomic64_fetch_add_acquire arch_atomic64_fetch_add
  148. #define arch_atomic64_fetch_add_release arch_atomic64_fetch_add
  149. #define arch_atomic64_fetch_add_relaxed arch_atomic64_fetch_add_relaxed
  150. #define arch_atomic64_fetch_sub arch_atomic64_fetch_sub
  151. #define arch_atomic64_fetch_sub_acquire arch_atomic64_fetch_sub
  152. #define arch_atomic64_fetch_sub_release arch_atomic64_fetch_sub
  153. #define arch_atomic64_fetch_sub_relaxed arch_atomic64_fetch_sub_relaxed
  154. #undef ATOMIC64_OPS
  155. #define ATOMIC64_OPS(op, I, asm_op) \
  156. ATOMIC64_OP(op, I, asm_op) \
  157. ATOMIC64_FETCH_OP(op, I, asm_op, _db, ) \
  158. ATOMIC64_FETCH_OP(op, I, asm_op, , _relaxed)
  159. ATOMIC64_OPS(and, i, and)
  160. ATOMIC64_OPS(or, i, or)
  161. ATOMIC64_OPS(xor, i, xor)
  162. #define arch_atomic64_fetch_and arch_atomic64_fetch_and
  163. #define arch_atomic64_fetch_and_acquire arch_atomic64_fetch_and
  164. #define arch_atomic64_fetch_and_release arch_atomic64_fetch_and
  165. #define arch_atomic64_fetch_and_relaxed arch_atomic64_fetch_and_relaxed
  166. #define arch_atomic64_fetch_or arch_atomic64_fetch_or
  167. #define arch_atomic64_fetch_or_acquire arch_atomic64_fetch_or
  168. #define arch_atomic64_fetch_or_release arch_atomic64_fetch_or
  169. #define arch_atomic64_fetch_or_relaxed arch_atomic64_fetch_or_relaxed
  170. #define arch_atomic64_fetch_xor arch_atomic64_fetch_xor
  171. #define arch_atomic64_fetch_xor_acquire arch_atomic64_fetch_xor
  172. #define arch_atomic64_fetch_xor_release arch_atomic64_fetch_xor
  173. #define arch_atomic64_fetch_xor_relaxed arch_atomic64_fetch_xor_relaxed
  174. #undef ATOMIC64_OPS
  175. #undef ATOMIC64_FETCH_OP
  176. #undef ATOMIC64_OP_RETURN
  177. #undef ATOMIC64_OP
  178. #endif
  179. #endif /* _ASM_ATOMIC_AMO_H */