0001
0002 #ifndef _ARCH_POWERPC_LOCAL_H
0003 #define _ARCH_POWERPC_LOCAL_H
0004
0005 #ifdef CONFIG_PPC_BOOK3S_64
0006
0007 #include <linux/percpu.h>
0008 #include <linux/atomic.h>
0009 #include <linux/irqflags.h>
0010
0011 #include <asm/hw_irq.h>
0012
0013 typedef struct
0014 {
0015 long v;
0016 } local_t;
0017
0018 #define LOCAL_INIT(i) { (i) }
0019
0020 static __inline__ long local_read(const local_t *l)
0021 {
0022 return READ_ONCE(l->v);
0023 }
0024
0025 static __inline__ void local_set(local_t *l, long i)
0026 {
0027 WRITE_ONCE(l->v, i);
0028 }
0029
0030 #define LOCAL_OP(op, c_op) \
0031 static __inline__ void local_##op(long i, local_t *l) \
0032 { \
0033 unsigned long flags; \
0034 \
0035 powerpc_local_irq_pmu_save(flags); \
0036 l->v c_op i; \
0037 powerpc_local_irq_pmu_restore(flags); \
0038 }
0039
0040 #define LOCAL_OP_RETURN(op, c_op) \
0041 static __inline__ long local_##op##_return(long a, local_t *l) \
0042 { \
0043 long t; \
0044 unsigned long flags; \
0045 \
0046 powerpc_local_irq_pmu_save(flags); \
0047 t = (l->v c_op a); \
0048 powerpc_local_irq_pmu_restore(flags); \
0049 \
0050 return t; \
0051 }
0052
0053 #define LOCAL_OPS(op, c_op) \
0054 LOCAL_OP(op, c_op) \
0055 LOCAL_OP_RETURN(op, c_op)
0056
0057 LOCAL_OPS(add, +=)
0058 LOCAL_OPS(sub, -=)
0059
0060 #define local_add_negative(a, l) (local_add_return((a), (l)) < 0)
0061 #define local_inc_return(l) local_add_return(1LL, l)
0062 #define local_inc(l) local_inc_return(l)
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 #define local_inc_and_test(l) (local_inc_return(l) == 0)
0073
0074 #define local_dec_return(l) local_sub_return(1LL, l)
0075 #define local_dec(l) local_dec_return(l)
0076 #define local_sub_and_test(a, l) (local_sub_return((a), (l)) == 0)
0077 #define local_dec_and_test(l) (local_dec_return((l)) == 0)
0078
0079 static __inline__ long local_cmpxchg(local_t *l, long o, long n)
0080 {
0081 long t;
0082 unsigned long flags;
0083
0084 powerpc_local_irq_pmu_save(flags);
0085 t = l->v;
0086 if (t == o)
0087 l->v = n;
0088 powerpc_local_irq_pmu_restore(flags);
0089
0090 return t;
0091 }
0092
0093 static __inline__ long local_xchg(local_t *l, long n)
0094 {
0095 long t;
0096 unsigned long flags;
0097
0098 powerpc_local_irq_pmu_save(flags);
0099 t = l->v;
0100 l->v = n;
0101 powerpc_local_irq_pmu_restore(flags);
0102
0103 return t;
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 static __inline__ int local_add_unless(local_t *l, long a, long u)
0116 {
0117 unsigned long flags;
0118 int ret = 0;
0119
0120 powerpc_local_irq_pmu_save(flags);
0121 if (l->v != u) {
0122 l->v += a;
0123 ret = 1;
0124 }
0125 powerpc_local_irq_pmu_restore(flags);
0126
0127 return ret;
0128 }
0129
0130 #define local_inc_not_zero(l) local_add_unless((l), 1, 0)
0131
0132
0133
0134
0135
0136
0137 #define __local_inc(l) ((l)->v++)
0138 #define __local_dec(l) ((l)->v++)
0139 #define __local_add(i,l) ((l)->v+=(i))
0140 #define __local_sub(i,l) ((l)->v-=(i))
0141
0142 #else
0143
0144 #include <asm-generic/local.h>
0145
0146 #endif
0147
0148 #endif