aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2005-06-30 01:17:02 -0400
committerPaul Mackerras <paulus@samba.org>2005-06-30 01:17:02 -0400
commit719d1cd86780c156f954fc34f34481adac197aec (patch)
treeb9e0a5b98e64459ea4eba77cd9bf3839dbb3a0fd /arch
parentffe1b7e14e6b606bd84cab564aa2f481dbd4e418 (diff)
[PATCH] ppc64: Replace custom locking code with a spinlock
The hvlpevent_queue (formally ItLpQueue) has a member called xInUseWord which is used for serialising access to the queue. Because it's a word (ie. 32 bit) there's a custom 32-bit version of test_and_set_bit() or thereabouts in ItLpQueue.c. The xInUseWord is not shared with they hypervisor, so we can replace it with a spinlock and remove the custom code. There is also another locking mechanism (ItLpQueueInProcess). This is redundant because it's only manipulated while the lock's held. Remove it. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Acked-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/ppc64/kernel/ItLpQueue.c38
1 files changed, 2 insertions, 36 deletions
diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
index a4f32cbf5297..4231861288a3 100644
--- a/arch/ppc64/kernel/ItLpQueue.c
+++ b/arch/ppc64/kernel/ItLpQueue.c
@@ -42,35 +42,8 @@ static char *event_types[HvLpEvent_Type_NumTypes] = {
42 "Virtual I/O" 42 "Virtual I/O"
43}; 43};
44 44
45static __inline__ int set_inUse(void)
46{
47 int t;
48 u32 * inUseP = &hvlpevent_queue.xInUseWord;
49
50 __asm__ __volatile__("\n\
511: lwarx %0,0,%2 \n\
52 cmpwi 0,%0,0 \n\
53 li %0,0 \n\
54 bne- 2f \n\
55 addi %0,%0,1 \n\
56 stwcx. %0,0,%2 \n\
57 bne- 1b \n\
582: eieio"
59 : "=&r" (t), "=m" (hvlpevent_queue.xInUseWord)
60 : "r" (inUseP), "m" (hvlpevent_queue.xInUseWord)
61 : "cc");
62
63 return t;
64}
65
66static __inline__ void clear_inUse(void)
67{
68 hvlpevent_queue.xInUseWord = 0;
69}
70
71/* Array of LpEvent handler functions */ 45/* Array of LpEvent handler functions */
72extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes]; 46extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
73unsigned long ItLpQueueInProcess = 0;
74 47
75static struct HvLpEvent * get_next_hvlpevent(void) 48static struct HvLpEvent * get_next_hvlpevent(void)
76{ 49{
@@ -144,14 +117,9 @@ void process_hvlpevents(struct pt_regs *regs)
144 struct HvLpEvent * event; 117 struct HvLpEvent * event;
145 118
146 /* If we have recursed, just return */ 119 /* If we have recursed, just return */
147 if ( !set_inUse() ) 120 if (!spin_trylock(&hvlpevent_queue.lock))
148 return; 121 return;
149 122
150 if (ItLpQueueInProcess == 0)
151 ItLpQueueInProcess = 1;
152 else
153 BUG();
154
155 for (;;) { 123 for (;;) {
156 event = get_next_hvlpevent(); 124 event = get_next_hvlpevent();
157 if (event) { 125 if (event) {
@@ -187,9 +155,7 @@ void process_hvlpevents(struct pt_regs *regs)
187 break; 155 break;
188 } 156 }
189 157
190 ItLpQueueInProcess = 0; 158 spin_unlock(&hvlpevent_queue.lock);
191 mb();
192 clear_inUse();
193} 159}
194 160
195static int set_spread_lpevents(char *str) 161static int set_spread_lpevents(char *str)