• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef __ASM_METAG_ATOMIC_LNKGET_H
2 #define __ASM_METAG_ATOMIC_LNKGET_H
3 
4 #define ATOMIC_INIT(i)	{ (i) }
5 
6 #define atomic_set(v, i)		WRITE_ONCE((v)->counter, (i))
7 
8 #include <linux/compiler.h>
9 
10 #include <asm/barrier.h>
11 
12 /*
13  * None of these asm statements clobber memory as LNKSET writes around
14  * the cache so the memory it modifies cannot safely be read by any means
15  * other than these accessors.
16  */
17 
atomic_read(const atomic_t * v)18 static inline int atomic_read(const atomic_t *v)
19 {
20 	int temp;
21 
22 	asm volatile (
23 		"LNKGETD %0, [%1]\n"
24 		: "=da" (temp)
25 		: "da" (&v->counter));
26 
27 	return temp;
28 }
29 
30 #define ATOMIC_OP(op)							\
31 static inline void atomic_##op(int i, atomic_t *v)			\
32 {									\
33 	int temp;							\
34 									\
35 	asm volatile (							\
36 		"1:	LNKGETD %0, [%1]\n"				\
37 		"	" #op "	%0, %0, %2\n"				\
38 		"	LNKSETD [%1], %0\n"				\
39 		"	DEFR	%0, TXSTAT\n"				\
40 		"	ANDT	%0, %0, #HI(0x3f000000)\n"		\
41 		"	CMPT	%0, #HI(0x02000000)\n"			\
42 		"	BNZ	1b\n"					\
43 		: "=&d" (temp)						\
44 		: "da" (&v->counter), "bd" (i)				\
45 		: "cc");						\
46 }									\
47 
48 #define ATOMIC_OP_RETURN(op)						\
49 static inline int atomic_##op##_return(int i, atomic_t *v)		\
50 {									\
51 	int result, temp;						\
52 									\
53 	smp_mb();							\
54 									\
55 	asm volatile (							\
56 		"1:	LNKGETD %1, [%2]\n"				\
57 		"	" #op "	%1, %1, %3\n"				\
58 		"	LNKSETD [%2], %1\n"				\
59 		"	DEFR	%0, TXSTAT\n"				\
60 		"	ANDT	%0, %0, #HI(0x3f000000)\n"		\
61 		"	CMPT	%0, #HI(0x02000000)\n"			\
62 		"	BNZ 1b\n"					\
63 		: "=&d" (temp), "=&da" (result)				\
64 		: "da" (&v->counter), "br" (i)				\
65 		: "cc");						\
66 									\
67 	smp_mb();							\
68 									\
69 	return result;							\
70 }
71 
72 #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op)
73 
74 ATOMIC_OPS(add)
ATOMIC_OPS(sub)75 ATOMIC_OPS(sub)
76 
77 ATOMIC_OP(and)
78 ATOMIC_OP(or)
79 ATOMIC_OP(xor)
80 
81 #undef ATOMIC_OPS
82 #undef ATOMIC_OP_RETURN
83 #undef ATOMIC_OP
84 
85 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
86 {
87 	int result, temp;
88 
89 	smp_mb();
90 
91 	asm volatile (
92 		"1:	LNKGETD	%1, [%2]\n"
93 		"	CMP	%1, %3\n"
94 		"	LNKSETDEQ [%2], %4\n"
95 		"	BNE	2f\n"
96 		"	DEFR	%0, TXSTAT\n"
97 		"	ANDT	%0, %0, #HI(0x3f000000)\n"
98 		"	CMPT	%0, #HI(0x02000000)\n"
99 		"	BNZ	1b\n"
100 		"2:\n"
101 		: "=&d" (temp), "=&d" (result)
102 		: "da" (&v->counter), "bd" (old), "da" (new)
103 		: "cc");
104 
105 	smp_mb();
106 
107 	return result;
108 }
109 
atomic_xchg(atomic_t * v,int new)110 static inline int atomic_xchg(atomic_t *v, int new)
111 {
112 	int temp, old;
113 
114 	asm volatile (
115 		"1:	LNKGETD %1, [%2]\n"
116 		"	LNKSETD	[%2], %3\n"
117 		"	DEFR	%0, TXSTAT\n"
118 		"	ANDT	%0, %0, #HI(0x3f000000)\n"
119 		"	CMPT	%0, #HI(0x02000000)\n"
120 		"	BNZ	1b\n"
121 		: "=&d" (temp), "=&d" (old)
122 		: "da" (&v->counter), "da" (new)
123 		: "cc");
124 
125 	return old;
126 }
127 
__atomic_add_unless(atomic_t * v,int a,int u)128 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
129 {
130 	int result, temp;
131 
132 	smp_mb();
133 
134 	asm volatile (
135 		"1:	LNKGETD %1, [%2]\n"
136 		"	CMP	%1, %3\n"
137 		"	ADD	%0, %1, %4\n"
138 		"	LNKSETDNE [%2], %0\n"
139 		"	BEQ	2f\n"
140 		"	DEFR	%0, TXSTAT\n"
141 		"	ANDT	%0, %0, #HI(0x3f000000)\n"
142 		"	CMPT	%0, #HI(0x02000000)\n"
143 		"	BNZ	1b\n"
144 		"2:\n"
145 		: "=&d" (temp), "=&d" (result)
146 		: "da" (&v->counter), "bd" (u), "bd" (a)
147 		: "cc");
148 
149 	smp_mb();
150 
151 	return result;
152 }
153 
atomic_sub_if_positive(int i,atomic_t * v)154 static inline int atomic_sub_if_positive(int i, atomic_t *v)
155 {
156 	int result, temp;
157 
158 	asm volatile (
159 		"1:	LNKGETD %1, [%2]\n"
160 		"	SUBS	%1, %1, %3\n"
161 		"	LNKSETDGE [%2], %1\n"
162 		"	BLT	2f\n"
163 		"	DEFR	%0, TXSTAT\n"
164 		"	ANDT	%0, %0, #HI(0x3f000000)\n"
165 		"	CMPT	%0, #HI(0x02000000)\n"
166 		"	BNZ	1b\n"
167 		"2:\n"
168 		: "=&d" (temp), "=&da" (result)
169 		: "da" (&v->counter), "bd" (i)
170 		: "cc");
171 
172 	return result;
173 }
174 
175 #endif /* __ASM_METAG_ATOMIC_LNKGET_H */
176