ACPI: thinkpad-acpi: preserve radio state across shutdown
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / sparc / include / asm / spinlock_64.h
blob120cfe4577c752bc44a417cdf2e4c1cef986f1c9
1 /* spinlock.h: 64-bit Sparc spinlock support.
3 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
4 */
6 #ifndef __SPARC64_SPINLOCK_H
7 #define __SPARC64_SPINLOCK_H
9 #ifndef __ASSEMBLY__
11 /* To get debugging spinlocks which detect and catch
12 * deadlock situations, set CONFIG_DEBUG_SPINLOCK
13 * and rebuild your kernel.
16 /* All of these locking primitives are expected to work properly
17 * even in an RMO memory model, which currently is what the kernel
18 * runs in.
20 * There is another issue. Because we play games to save cycles
21 * in the non-contention case, we need to be extra careful about
22 * branch targets into the "spinning" code. They live in their
23 * own section, but the newer V9 branches have a shorter range
24 * than the traditional 32-bit sparc branch variants. The rule
25 * is that the branches that go into and out of the spinner sections
26 * must be pre-V9 branches.
29 #define __raw_spin_is_locked(lp) ((lp)->lock != 0)
31 #define __raw_spin_unlock_wait(lp) \
32 do { rmb(); \
33 } while((lp)->lock)
35 static inline void __raw_spin_lock(raw_spinlock_t *lock)
37 unsigned long tmp;
39 __asm__ __volatile__(
40 "1: ldstub [%1], %0\n"
41 " membar #StoreLoad | #StoreStore\n"
42 " brnz,pn %0, 2f\n"
43 " nop\n"
44 " .subsection 2\n"
45 "2: ldub [%1], %0\n"
46 " membar #LoadLoad\n"
47 " brnz,pt %0, 2b\n"
48 " nop\n"
49 " ba,a,pt %%xcc, 1b\n"
50 " .previous"
51 : "=&r" (tmp)
52 : "r" (lock)
53 : "memory");
56 static inline int __raw_spin_trylock(raw_spinlock_t *lock)
58 unsigned long result;
60 __asm__ __volatile__(
61 " ldstub [%1], %0\n"
62 " membar #StoreLoad | #StoreStore"
63 : "=r" (result)
64 : "r" (lock)
65 : "memory");
67 return (result == 0UL);
70 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
72 __asm__ __volatile__(
73 " membar #StoreStore | #LoadStore\n"
74 " stb %%g0, [%0]"
75 : /* No outputs */
76 : "r" (lock)
77 : "memory");
80 static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
82 unsigned long tmp1, tmp2;
84 __asm__ __volatile__(
85 "1: ldstub [%2], %0\n"
86 " membar #StoreLoad | #StoreStore\n"
87 " brnz,pn %0, 2f\n"
88 " nop\n"
89 " .subsection 2\n"
90 "2: rdpr %%pil, %1\n"
91 " wrpr %3, %%pil\n"
92 "3: ldub [%2], %0\n"
93 " membar #LoadLoad\n"
94 " brnz,pt %0, 3b\n"
95 " nop\n"
96 " ba,pt %%xcc, 1b\n"
97 " wrpr %1, %%pil\n"
98 " .previous"
99 : "=&r" (tmp1), "=&r" (tmp2)
100 : "r"(lock), "r"(flags)
101 : "memory");
104 /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
106 static void inline __read_lock(raw_rwlock_t *lock)
108 unsigned long tmp1, tmp2;
110 __asm__ __volatile__ (
111 "1: ldsw [%2], %0\n"
112 " brlz,pn %0, 2f\n"
113 "4: add %0, 1, %1\n"
114 " cas [%2], %0, %1\n"
115 " cmp %0, %1\n"
116 " membar #StoreLoad | #StoreStore\n"
117 " bne,pn %%icc, 1b\n"
118 " nop\n"
119 " .subsection 2\n"
120 "2: ldsw [%2], %0\n"
121 " membar #LoadLoad\n"
122 " brlz,pt %0, 2b\n"
123 " nop\n"
124 " ba,a,pt %%xcc, 4b\n"
125 " .previous"
126 : "=&r" (tmp1), "=&r" (tmp2)
127 : "r" (lock)
128 : "memory");
131 static int inline __read_trylock(raw_rwlock_t *lock)
133 int tmp1, tmp2;
135 __asm__ __volatile__ (
136 "1: ldsw [%2], %0\n"
137 " brlz,a,pn %0, 2f\n"
138 " mov 0, %0\n"
139 " add %0, 1, %1\n"
140 " cas [%2], %0, %1\n"
141 " cmp %0, %1\n"
142 " membar #StoreLoad | #StoreStore\n"
143 " bne,pn %%icc, 1b\n"
144 " mov 1, %0\n"
145 "2:"
146 : "=&r" (tmp1), "=&r" (tmp2)
147 : "r" (lock)
148 : "memory");
150 return tmp1;
153 static void inline __read_unlock(raw_rwlock_t *lock)
155 unsigned long tmp1, tmp2;
157 __asm__ __volatile__(
158 " membar #StoreLoad | #LoadLoad\n"
159 "1: lduw [%2], %0\n"
160 " sub %0, 1, %1\n"
161 " cas [%2], %0, %1\n"
162 " cmp %0, %1\n"
163 " bne,pn %%xcc, 1b\n"
164 " nop"
165 : "=&r" (tmp1), "=&r" (tmp2)
166 : "r" (lock)
167 : "memory");
170 static void inline __write_lock(raw_rwlock_t *lock)
172 unsigned long mask, tmp1, tmp2;
174 mask = 0x80000000UL;
176 __asm__ __volatile__(
177 "1: lduw [%2], %0\n"
178 " brnz,pn %0, 2f\n"
179 "4: or %0, %3, %1\n"
180 " cas [%2], %0, %1\n"
181 " cmp %0, %1\n"
182 " membar #StoreLoad | #StoreStore\n"
183 " bne,pn %%icc, 1b\n"
184 " nop\n"
185 " .subsection 2\n"
186 "2: lduw [%2], %0\n"
187 " membar #LoadLoad\n"
188 " brnz,pt %0, 2b\n"
189 " nop\n"
190 " ba,a,pt %%xcc, 4b\n"
191 " .previous"
192 : "=&r" (tmp1), "=&r" (tmp2)
193 : "r" (lock), "r" (mask)
194 : "memory");
197 static void inline __write_unlock(raw_rwlock_t *lock)
199 __asm__ __volatile__(
200 " membar #LoadStore | #StoreStore\n"
201 " stw %%g0, [%0]"
202 : /* no outputs */
203 : "r" (lock)
204 : "memory");
207 static int inline __write_trylock(raw_rwlock_t *lock)
209 unsigned long mask, tmp1, tmp2, result;
211 mask = 0x80000000UL;
213 __asm__ __volatile__(
214 " mov 0, %2\n"
215 "1: lduw [%3], %0\n"
216 " brnz,pn %0, 2f\n"
217 " or %0, %4, %1\n"
218 " cas [%3], %0, %1\n"
219 " cmp %0, %1\n"
220 " membar #StoreLoad | #StoreStore\n"
221 " bne,pn %%icc, 1b\n"
222 " nop\n"
223 " mov 1, %2\n"
224 "2:"
225 : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
226 : "r" (lock), "r" (mask)
227 : "memory");
229 return result;
232 #define __raw_read_lock(p) __read_lock(p)
233 #define __raw_read_trylock(p) __read_trylock(p)
234 #define __raw_read_unlock(p) __read_unlock(p)
235 #define __raw_write_lock(p) __write_lock(p)
236 #define __raw_write_unlock(p) __write_unlock(p)
237 #define __raw_write_trylock(p) __write_trylock(p)
239 #define __raw_read_can_lock(rw) (!((rw)->lock & 0x80000000UL))
240 #define __raw_write_can_lock(rw) (!(rw)->lock)
242 #define _raw_spin_relax(lock) cpu_relax()
243 #define _raw_read_relax(lock) cpu_relax()
244 #define _raw_write_relax(lock) cpu_relax()
246 #endif /* !(__ASSEMBLY__) */
248 #endif /* !(__SPARC64_SPINLOCK_H) */