[PATCH] I2C: i2c-nforce2: drop unused define
[pandora-kernel.git] / arch / sparc / lib / debuglocks.c
1 /* $Id: debuglocks.c,v 1.11 2001/09/20 00:35:31 davem Exp $
2  * debuglocks.c: Debugging versions of SMP locking primitives.
3  *
4  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
5  * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au)
6  */
7
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/threads.h>      /* For NR_CPUS */
11 #include <linux/spinlock.h>
12 #include <asm/psr.h>
13 #include <asm/system.h>
14
15 #ifdef CONFIG_SMP
16
17 /* Some notes on how these debugging routines work.  When a lock is acquired
18  * an extra debugging member lock->owner_pc is set to the caller of the lock
19  * acquisition routine.  Right before releasing a lock, the debugging program
20  * counter is cleared to zero.
21  *
22  * Furthermore, since PC's are 4 byte aligned on Sparc, we stuff the CPU
23  * number of the owner in the lowest two bits.
24  */
25
26 #define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A));
27
28 static inline void show(char *str, spinlock_t *lock, unsigned long caller)
29 {
30         int cpu = smp_processor_id();
31
32         printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,
33                 lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
34 }
35
36 static inline void show_read(char *str, rwlock_t *lock, unsigned long caller)
37 {
38         int cpu = smp_processor_id();
39
40         printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", str,
41                 lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
42 }
43
44 static inline void show_write(char *str, rwlock_t *lock, unsigned long caller)
45 {
46         int cpu = smp_processor_id();
47         int i;
48
49         printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)", str,
50                 lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
51
52         for(i = 0; i < NR_CPUS; i++)
53                 printk(" reader[%d]=%08lx", i, lock->reader_pc[i]);
54
55         printk("\n");
56 }
57
58 #undef INIT_STUCK
59 #define INIT_STUCK 100000000
60
61 void _do_spin_lock(spinlock_t *lock, char *str)
62 {
63         unsigned long caller;
64         unsigned long val;
65         int cpu = smp_processor_id();
66         int stuck = INIT_STUCK;
67
68         STORE_CALLER(caller);
69
70 again:
71         __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
72         if(val) {
73                 while(lock->lock) {
74                         if (!--stuck) {
75                                 show(str, lock, caller);
76                                 stuck = INIT_STUCK;
77                         }
78                         barrier();
79                 }
80                 goto again;
81         }
82         lock->owner_pc = (cpu & 3) | (caller & ~3);
83 }
84
85 int _spin_trylock(spinlock_t *lock)
86 {
87         unsigned long val;
88         unsigned long caller;
89         int cpu = smp_processor_id();
90
91         STORE_CALLER(caller);
92
93         __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
94         if(!val) {
95                 /* We got it, record our identity for debugging. */
96                 lock->owner_pc = (cpu & 3) | (caller & ~3);
97         }
98         return val == 0;
99 }
100
101 void _do_spin_unlock(spinlock_t *lock)
102 {
103         lock->owner_pc = 0;
104         barrier();
105         lock->lock = 0;
106 }
107
108 void _do_read_lock(rwlock_t *rw, char *str)
109 {
110         unsigned long caller;
111         unsigned long val;
112         int cpu = smp_processor_id();
113         int stuck = INIT_STUCK;
114
115         STORE_CALLER(caller);
116
117 wlock_again:
118         __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
119         if(val) {
120                 while(rw->lock & 0xff) {
121                         if (!--stuck) {
122                                 show_read(str, rw, caller);
123                                 stuck = INIT_STUCK;
124                         }
125                         barrier();
126                 }
127                 goto wlock_again;
128         }
129
130         rw->reader_pc[cpu] = caller;
131         barrier();
132         rw->lock++;
133 }
134
135 void _do_read_unlock(rwlock_t *rw, char *str)
136 {
137         unsigned long caller;
138         unsigned long val;
139         int cpu = smp_processor_id();
140         int stuck = INIT_STUCK;
141
142         STORE_CALLER(caller);
143
144 wlock_again:
145         __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
146         if(val) {
147                 while(rw->lock & 0xff) {
148                         if (!--stuck) {
149                                 show_read(str, rw, caller);
150                                 stuck = INIT_STUCK;
151                         }
152                         barrier();
153                 }
154                 goto wlock_again;
155         }
156
157         rw->reader_pc[cpu] = 0;
158         barrier();
159         rw->lock -= 0x1ff;
160 }
161
162 void _do_write_lock(rwlock_t *rw, char *str)
163 {
164         unsigned long caller;
165         unsigned long val;
166         int cpu = smp_processor_id();
167         int stuck = INIT_STUCK;
168
169         STORE_CALLER(caller);
170
171 wlock_again:
172         __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
173         if(val) {
174 wlock_wait:
175                 while(rw->lock) {
176                         if (!--stuck) {
177                                 show_write(str, rw, caller);
178                                 stuck = INIT_STUCK;
179                         }
180                         barrier();
181                 }
182                 goto wlock_again;
183         }
184
185         if (rw->lock & ~0xff) {
186                 *(((unsigned char *)&rw->lock)+3) = 0;
187                 barrier();
188                 goto wlock_wait;
189         }
190
191         barrier();
192         rw->owner_pc = (cpu & 3) | (caller & ~3);
193 }
194
195 void _do_write_unlock(rwlock_t *rw)
196 {
197         rw->owner_pc = 0;
198         barrier();
199         rw->lock = 0;
200 }
201
202 #endif /* SMP */