1
2
3
4
5#ifndef _ASM_PPC_ATOMIC_H_
6#define _ASM_PPC_ATOMIC_H_
7
8typedef struct { volatile int counter; } atomic_t;
9
10#ifdef __KERNEL__
11
12#define ATOMIC_INIT(i) { (i) }
13
14#define atomic_read(v) ((v)->counter)
15#define atomic_set(v,i) (((v)->counter) = (i))
16
17extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
18extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
19
20#ifdef CONFIG_SMP
21#define SMP_ISYNC "\n\tisync"
22#else
23#define SMP_ISYNC
24#endif
25
26
27
28
29#ifdef CONFIG_IBM405_ERR77
30#define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";"
31#else
32#define PPC405_ERR77(ra,rb)
33#endif
34
35static __inline__ void atomic_add(int a, atomic_t *v)
36{
37 int t;
38
39 __asm__ __volatile__(
40"1: lwarx %0,0,%3 # atomic_add\n\
41 add %0,%2,%0\n"
42 PPC405_ERR77(0,%3)
43" stwcx. %0,0,%3 \n\
44 bne- 1b"
45 : "=&r" (t), "=m" (v->counter)
46 : "r" (a), "r" (&v->counter), "m" (v->counter)
47 : "cc");
48}
49
50static __inline__ int atomic_add_return(int a, atomic_t *v)
51{
52 int t;
53
54 __asm__ __volatile__(
55"1: lwarx %0,0,%2 # atomic_add_return\n\
56 add %0,%1,%0\n"
57 PPC405_ERR77(0,%2)
58" stwcx. %0,0,%2 \n\
59 bne- 1b"
60 SMP_ISYNC
61 : "=&r" (t)
62 : "r" (a), "r" (&v->counter)
63 : "cc", "memory");
64
65 return t;
66}
67
68static __inline__ void atomic_sub(int a, atomic_t *v)
69{
70 int t;
71
72 __asm__ __volatile__(
73"1: lwarx %0,0,%3 # atomic_sub\n\
74 subf %0,%2,%0\n"
75 PPC405_ERR77(0,%3)
76" stwcx. %0,0,%3 \n\
77 bne- 1b"
78 : "=&r" (t), "=m" (v->counter)
79 : "r" (a), "r" (&v->counter), "m" (v->counter)
80 : "cc");
81}
82
83static __inline__ int atomic_sub_return(int a, atomic_t *v)
84{
85 int t;
86
87 __asm__ __volatile__(
88"1: lwarx %0,0,%2 # atomic_sub_return\n\
89 subf %0,%1,%0\n"
90 PPC405_ERR77(0,%2)
91" stwcx. %0,0,%2 \n\
92 bne- 1b"
93 SMP_ISYNC
94 : "=&r" (t)
95 : "r" (a), "r" (&v->counter)
96 : "cc", "memory");
97
98 return t;
99}
100
101static __inline__ void atomic_inc(atomic_t *v)
102{
103 int t;
104
105 __asm__ __volatile__(
106"1: lwarx %0,0,%2 # atomic_inc\n\
107 addic %0,%0,1\n"
108 PPC405_ERR77(0,%2)
109" stwcx. %0,0,%2 \n\
110 bne- 1b"
111 : "=&r" (t), "=m" (v->counter)
112 : "r" (&v->counter), "m" (v->counter)
113 : "cc");
114}
115
116static __inline__ int atomic_inc_return(atomic_t *v)
117{
118 int t;
119
120 __asm__ __volatile__(
121"1: lwarx %0,0,%1 # atomic_inc_return\n\
122 addic %0,%0,1\n"
123 PPC405_ERR77(0,%1)
124" stwcx. %0,0,%1 \n\
125 bne- 1b"
126 SMP_ISYNC
127 : "=&r" (t)
128 : "r" (&v->counter)
129 : "cc", "memory");
130
131 return t;
132}
133
134static __inline__ void atomic_dec(atomic_t *v)
135{
136 int t;
137
138 __asm__ __volatile__(
139"1: lwarx %0,0,%2 # atomic_dec\n\
140 addic %0,%0,-1\n"
141 PPC405_ERR77(0,%2)\
142" stwcx. %0,0,%2\n\
143 bne- 1b"
144 : "=&r" (t), "=m" (v->counter)
145 : "r" (&v->counter), "m" (v->counter)
146 : "cc");
147}
148
149static __inline__ int atomic_dec_return(atomic_t *v)
150{
151 int t;
152
153 __asm__ __volatile__(
154"1: lwarx %0,0,%1 # atomic_dec_return\n\
155 addic %0,%0,-1\n"
156 PPC405_ERR77(0,%1)
157" stwcx. %0,0,%1\n\
158 bne- 1b"
159 SMP_ISYNC
160 : "=&r" (t)
161 : "r" (&v->counter)
162 : "cc", "memory");
163
164 return t;
165}
166
167#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
168#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
169
170
171
172
173
174static __inline__ int atomic_dec_if_positive(atomic_t *v)
175{
176 int t;
177
178 __asm__ __volatile__(
179"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\
180 addic. %0,%0,-1\n\
181 blt- 2f\n"
182 PPC405_ERR77(0,%1)
183" stwcx. %0,0,%1\n\
184 bne- 1b"
185 SMP_ISYNC
186 "\n\
1872:" : "=&r" (t)
188 : "r" (&v->counter)
189 : "cc", "memory");
190
191 return t;
192}
193
194#define smp_mb__before_atomic_dec() smp_mb()
195#define smp_mb__after_atomic_dec() smp_mb()
196#define smp_mb__before_atomic_inc() smp_mb()
197#define smp_mb__after_atomic_inc() smp_mb()
198
199#endif
200#endif
201