added mtd driver
[linux-2.4.git] / include / asm-ppc / spinlock.h
1 #ifndef __ASM_SPINLOCK_H
2 #define __ASM_SPINLOCK_H
3
4 #include <asm/system.h>
5 #include <asm/processor.h>
6
7 #if defined(CONFIG_DEBUG_SPINLOCK)
8 #define SPINLOCK_DEBUG 1
9 #else
10 #define SPINLOCK_DEBUG 0
11 #endif
12
13 /*
14  * Simple spin lock operations.
15  */
16
17 typedef struct {
18         volatile unsigned long lock;
19 #if SPINLOCK_DEBUG
20         volatile unsigned long owner_pc;
21         volatile unsigned long owner_cpu;
22 #endif
23 } spinlock_t;
24
25 #ifdef __KERNEL__
26 #if SPINLOCK_DEBUG
27 #define SPINLOCK_DEBUG_INIT     , 0, 0
28 #else
29 #define SPINLOCK_DEBUG_INIT     /* */
30 #endif
31
32 #define SPIN_LOCK_UNLOCKED      (spinlock_t) { 0 SPINLOCK_DEBUG_INIT }
33
34 #define spin_lock_init(x)       do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
35 #define spin_is_locked(x)       ((x)->lock != 0)
36 #define spin_unlock_wait(x)     do { barrier(); } while(spin_is_locked(x))
37
38 #if SPINLOCK_DEBUG
39
40 extern void _spin_lock(spinlock_t *lock);
41 extern void _spin_unlock(spinlock_t *lock);
42 extern int spin_trylock(spinlock_t *lock);
43
44 #define spin_lock(lp)                   _spin_lock(lp)
45 #define spin_unlock(lp)                 _spin_unlock(lp)
46
47 #else /* ! SPINLOCK_DEBUG */
48
49 static inline void spin_lock(spinlock_t *lock)
50 {
51         unsigned long tmp;
52
53         __asm__ __volatile__(
54         "b      1f              # spin_lock\n\
55 2:      lwzx    %0,0,%1\n\
56         cmpwi   0,%0,0\n\
57         bne+    2b\n\
58 1:      lwarx   %0,0,%1\n\
59         cmpwi   0,%0,0\n\
60         bne-    2b\n"
61         PPC405_ERR77(0,%1)
62 "       stwcx.  %2,0,%1\n\
63         bne-    2b\n\
64         isync"
65         : "=&r"(tmp)
66         : "r"(&lock->lock), "r"(1)
67         : "cr0", "memory");
68 }
69
70 static inline void spin_unlock(spinlock_t *lock)
71 {
72         __asm__ __volatile__("eieio             # spin_unlock": : :"memory");
73         lock->lock = 0;
74 }
75
76 #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
77
78 #endif
79
80 /*
81  * Read-write spinlocks, allowing multiple readers
82  * but only one writer.
83  *
84  * NOTE! it is quite common to have readers in interrupts
85  * but no interrupt writers. For those circumstances we
86  * can "mix" irq-safe locks - any writer needs to get a
87  * irq-safe write-lock, but readers can get non-irqsafe
88  * read-locks.
89  */
90 typedef struct {
91         volatile unsigned long lock;
92 #if SPINLOCK_DEBUG
93         volatile unsigned long owner_pc;
94 #endif
95 } rwlock_t;
96
97 #if SPINLOCK_DEBUG
98 #define RWLOCK_DEBUG_INIT     , 0
99 #else
100 #define RWLOCK_DEBUG_INIT     /* */
101 #endif
102
103 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 RWLOCK_DEBUG_INIT }
104 #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
105
106 #if SPINLOCK_DEBUG
107
108 extern void _read_lock(rwlock_t *rw);
109 extern void _read_unlock(rwlock_t *rw);
110 extern void _write_lock(rwlock_t *rw);
111 extern void _write_unlock(rwlock_t *rw);
112
113 #define read_lock(rw)           _read_lock(rw)
114 #define write_lock(rw)          _write_lock(rw)
115 #define write_unlock(rw)        _write_unlock(rw)
116 #define read_unlock(rw)         _read_unlock(rw)
117
118 #else /* ! SPINLOCK_DEBUG */
119
120 static __inline__ void read_lock(rwlock_t *rw)
121 {
122         unsigned int tmp;
123
124         __asm__ __volatile__(
125         "b      2f              # read_lock\n\
126 1:      lwzx    %0,0,%1\n\
127         cmpwi   0,%0,0\n\
128         blt+    1b\n\
129 2:      lwarx   %0,0,%1\n\
130         addic.  %0,%0,1\n\
131         ble-    1b\n"
132         PPC405_ERR77(0,%1)
133 "       stwcx.  %0,0,%1\n\
134         bne-    2b\n\
135         isync"
136         : "=&r"(tmp)
137         : "r"(&rw->lock)
138         : "cr0", "memory");
139 }
140
141 static __inline__ void read_unlock(rwlock_t *rw)
142 {
143         unsigned int tmp;
144
145         __asm__ __volatile__(
146         "eieio                  # read_unlock\n\
147 1:      lwarx   %0,0,%1\n\
148         addic   %0,%0,-1\n"
149         PPC405_ERR77(0,%1)
150 "       stwcx.  %0,0,%1\n\
151         bne-    1b"
152         : "=&r"(tmp)
153         : "r"(&rw->lock)
154         : "cr0", "memory");
155 }
156
157 static __inline__ void write_lock(rwlock_t *rw)
158 {
159         unsigned int tmp;
160
161         __asm__ __volatile__(
162         "b      2f              # write_lock\n\
163 1:      lwzx    %0,0,%1\n\
164         cmpwi   0,%0,0\n\
165         bne+    1b\n\
166 2:      lwarx   %0,0,%1\n\
167         cmpwi   0,%0,0\n\
168         bne-    1b\n"
169         PPC405_ERR77(0,%1)
170 "       stwcx.  %2,0,%1\n\
171         bne-    2b\n\
172         isync"
173         : "=&r"(tmp)
174         : "r"(&rw->lock), "r"(-1)
175         : "cr0", "memory");
176 }
177
178 static __inline__ void write_unlock(rwlock_t *rw)
179 {
180         __asm__ __volatile__("eieio             # write_unlock": : :"memory");
181         rw->lock = 0;
182 }
183
184 #endif
185
186 #endif /* __ASM_SPINLOCK_H */
187 #endif /* __KERNEL__ */