linux/arch/csky/include/asm/atomic.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2
   3#ifndef __ASM_CSKY_ATOMIC_H
   4#define __ASM_CSKY_ATOMIC_H
   5
   6#include <linux/version.h>
   7#include <asm/cmpxchg.h>
   8#include <asm/barrier.h>
   9
  10#ifdef CONFIG_CPU_HAS_LDSTEX
  11
  12#define __atomic_add_unless __atomic_add_unless
  13static inline int __atomic_add_unless(atomic_t *v, int a, int u)
  14{
  15        unsigned long tmp, ret;
  16
  17        smp_mb();
  18
  19        asm volatile (
  20        "1:     ldex.w          %0, (%3) \n"
  21        "       mov             %1, %0   \n"
  22        "       cmpne           %0, %4   \n"
  23        "       bf              2f       \n"
  24        "       add             %0, %2   \n"
  25        "       stex.w          %0, (%3) \n"
  26        "       bez             %0, 1b   \n"
  27        "2:                              \n"
  28                : "=&r" (tmp), "=&r" (ret)
  29                : "r" (a), "r"(&v->counter), "r"(u)
  30                : "memory");
  31
  32        if (ret != u)
  33                smp_mb();
  34
  35        return ret;
  36}
  37
  38#define ATOMIC_OP(op, c_op)                                             \
  39static inline void atomic_##op(int i, atomic_t *v)                      \
  40{                                                                       \
  41        unsigned long tmp;                                              \
  42                                                                        \
  43        asm volatile (                                                  \
  44        "1:     ldex.w          %0, (%2) \n"                            \
  45        "       " #op "         %0, %1   \n"                            \
  46        "       stex.w          %0, (%2) \n"                            \
  47        "       bez             %0, 1b   \n"                            \
  48                : "=&r" (tmp)                                           \
  49                : "r" (i), "r"(&v->counter)                             \
  50                : "memory");                                            \
  51}
  52
  53#define ATOMIC_OP_RETURN(op, c_op)                                      \
  54static inline int atomic_##op##_return(int i, atomic_t *v)              \
  55{                                                                       \
  56        unsigned long tmp, ret;                                         \
  57                                                                        \
  58        smp_mb();                                                       \
  59        asm volatile (                                                  \
  60        "1:     ldex.w          %0, (%3) \n"                            \
  61        "       " #op "         %0, %2   \n"                            \
  62        "       mov             %1, %0   \n"                            \
  63        "       stex.w          %0, (%3) \n"                            \
  64        "       bez             %0, 1b   \n"                            \
  65                : "=&r" (tmp), "=&r" (ret)                              \
  66                : "r" (i), "r"(&v->counter)                             \
  67                : "memory");                                            \
  68        smp_mb();                                                       \
  69                                                                        \
  70        return ret;                                                     \
  71}
  72
  73#define ATOMIC_FETCH_OP(op, c_op)                                       \
  74static inline int atomic_fetch_##op(int i, atomic_t *v)                 \
  75{                                                                       \
  76        unsigned long tmp, ret;                                         \
  77                                                                        \
  78        smp_mb();                                                       \
  79        asm volatile (                                                  \
  80        "1:     ldex.w          %0, (%3) \n"                            \
  81        "       mov             %1, %0   \n"                            \
  82        "       " #op "         %0, %2   \n"                            \
  83        "       stex.w          %0, (%3) \n"                            \
  84        "       bez             %0, 1b   \n"                            \
  85                : "=&r" (tmp), "=&r" (ret)                              \
  86                : "r" (i), "r"(&v->counter)                             \
  87                : "memory");                                            \
  88        smp_mb();                                                       \
  89                                                                        \
  90        return ret;                                                     \
  91}
  92
  93#else /* CONFIG_CPU_HAS_LDSTEX */
  94
  95#include <linux/irqflags.h>
  96
  97#define __atomic_add_unless __atomic_add_unless
  98static inline int __atomic_add_unless(atomic_t *v, int a, int u)
  99{
 100        unsigned long tmp, ret, flags;
 101
 102        raw_local_irq_save(flags);
 103
 104        asm volatile (
 105        "       ldw             %0, (%3) \n"
 106        "       mov             %1, %0   \n"
 107        "       cmpne           %0, %4   \n"
 108        "       bf              2f       \n"
 109        "       add             %0, %2   \n"
 110        "       stw             %0, (%3) \n"
 111        "2:                              \n"
 112                : "=&r" (tmp), "=&r" (ret)
 113                : "r" (a), "r"(&v->counter), "r"(u)
 114                : "memory");
 115
 116        raw_local_irq_restore(flags);
 117
 118        return ret;
 119}
 120
 121#define ATOMIC_OP(op, c_op)                                             \
 122static inline void atomic_##op(int i, atomic_t *v)                      \
 123{                                                                       \
 124        unsigned long tmp, flags;                                       \
 125                                                                        \
 126        raw_local_irq_save(flags);                                      \
 127                                                                        \
 128        asm volatile (                                                  \
 129        "       ldw             %0, (%2) \n"                            \
 130        "       " #op "         %0, %1   \n"                            \
 131        "       stw             %0, (%2) \n"                            \
 132                : "=&r" (tmp)                                           \
 133                : "r" (i), "r"(&v->counter)                             \
 134                : "memory");                                            \
 135                                                                        \
 136        raw_local_irq_restore(flags);                                   \
 137}
 138
 139#define ATOMIC_OP_RETURN(op, c_op)                                      \
 140static inline int atomic_##op##_return(int i, atomic_t *v)              \
 141{                                                                       \
 142        unsigned long tmp, ret, flags;                                  \
 143                                                                        \
 144        raw_local_irq_save(flags);                                      \
 145                                                                        \
 146        asm volatile (                                                  \
 147        "       ldw             %0, (%3) \n"                            \
 148        "       " #op "         %0, %2   \n"                            \
 149        "       stw             %0, (%3) \n"                            \
 150        "       mov             %1, %0   \n"                            \
 151                : "=&r" (tmp), "=&r" (ret)                              \
 152                : "r" (i), "r"(&v->counter)                             \
 153                : "memory");                                            \
 154                                                                        \
 155        raw_local_irq_restore(flags);                                   \
 156                                                                        \
 157        return ret;                                                     \
 158}
 159
 160#define ATOMIC_FETCH_OP(op, c_op)                                       \
 161static inline int atomic_fetch_##op(int i, atomic_t *v)                 \
 162{                                                                       \
 163        unsigned long tmp, ret, flags;                                  \
 164                                                                        \
 165        raw_local_irq_save(flags);                                      \
 166                                                                        \
 167        asm volatile (                                                  \
 168        "       ldw             %0, (%3) \n"                            \
 169        "       mov             %1, %0   \n"                            \
 170        "       " #op "         %0, %2   \n"                            \
 171        "       stw             %0, (%3) \n"                            \
 172                : "=&r" (tmp), "=&r" (ret)                              \
 173                : "r" (i), "r"(&v->counter)                             \
 174                : "memory");                                            \
 175                                                                        \
 176        raw_local_irq_restore(flags);                                   \
 177                                                                        \
 178        return ret;                                                     \
 179}
 180
 181#endif /* CONFIG_CPU_HAS_LDSTEX */
 182
 183#define atomic_add_return atomic_add_return
 184ATOMIC_OP_RETURN(add, +)
 185#define atomic_sub_return atomic_sub_return
 186ATOMIC_OP_RETURN(sub, -)
 187
 188#define atomic_fetch_add atomic_fetch_add
 189ATOMIC_FETCH_OP(add, +)
 190#define atomic_fetch_sub atomic_fetch_sub
 191ATOMIC_FETCH_OP(sub, -)
 192#define atomic_fetch_and atomic_fetch_and
 193ATOMIC_FETCH_OP(and, &)
 194#define atomic_fetch_or atomic_fetch_or
 195ATOMIC_FETCH_OP(or, |)
 196#define atomic_fetch_xor atomic_fetch_xor
 197ATOMIC_FETCH_OP(xor, ^)
 198
 199#define atomic_and atomic_and
 200ATOMIC_OP(and, &)
 201#define atomic_or atomic_or
 202ATOMIC_OP(or, |)
 203#define atomic_xor atomic_xor
 204ATOMIC_OP(xor, ^)
 205
 206#undef ATOMIC_FETCH_OP
 207#undef ATOMIC_OP_RETURN
 208#undef ATOMIC_OP
 209
 210#include <asm-generic/atomic.h>
 211
 212#endif /* __ASM_CSKY_ATOMIC_H */
 213