Commit 719d1cd8 authored by Michael Ellerman's avatar Michael Ellerman Committed by Paul Mackerras

[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: default avatarMichael Ellerman <michael@ellerman.id.au>
Acked-by: default avatarStephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent ffe1b7e1
...@@ -42,35 +42,8 @@ static char *event_types[HvLpEvent_Type_NumTypes] = { ...@@ -42,35 +42,8 @@ static char *event_types[HvLpEvent_Type_NumTypes] = {
"Virtual I/O" "Virtual I/O"
}; };
static __inline__ int set_inUse(void)
{
int t;
u32 * inUseP = &hvlpevent_queue.xInUseWord;
__asm__ __volatile__("\n\
1: lwarx %0,0,%2 \n\
cmpwi 0,%0,0 \n\
li %0,0 \n\
bne- 2f \n\
addi %0,%0,1 \n\
stwcx. %0,0,%2 \n\
bne- 1b \n\
2: eieio"
: "=&r" (t), "=m" (hvlpevent_queue.xInUseWord)
: "r" (inUseP), "m" (hvlpevent_queue.xInUseWord)
: "cc");
return t;
}
static __inline__ void clear_inUse(void)
{
hvlpevent_queue.xInUseWord = 0;
}
/* Array of LpEvent handler functions */ /* Array of LpEvent handler functions */
extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes]; extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
unsigned long ItLpQueueInProcess = 0;
static struct HvLpEvent * get_next_hvlpevent(void) static struct HvLpEvent * get_next_hvlpevent(void)
{ {
...@@ -144,14 +117,9 @@ void process_hvlpevents(struct pt_regs *regs) ...@@ -144,14 +117,9 @@ void process_hvlpevents(struct pt_regs *regs)
struct HvLpEvent * event; struct HvLpEvent * event;
/* If we have recursed, just return */ /* If we have recursed, just return */
if ( !set_inUse() ) if (!spin_trylock(&hvlpevent_queue.lock))
return; return;
if (ItLpQueueInProcess == 0)
ItLpQueueInProcess = 1;
else
BUG();
for (;;) { for (;;) {
event = get_next_hvlpevent(); event = get_next_hvlpevent();
if (event) { if (event) {
...@@ -187,9 +155,7 @@ void process_hvlpevents(struct pt_regs *regs) ...@@ -187,9 +155,7 @@ void process_hvlpevents(struct pt_regs *regs)
break; break;
} }
ItLpQueueInProcess = 0; spin_unlock(&hvlpevent_queue.lock);
mb();
clear_inUse();
} }
static int set_spread_lpevents(char *str) static int set_spread_lpevents(char *str)
......
...@@ -69,7 +69,7 @@ struct hvlpevent_queue { ...@@ -69,7 +69,7 @@ struct hvlpevent_queue {
char *xSlicEventStackPtr; // 0x20 char *xSlicEventStackPtr; // 0x20
u8 xIndex; // 0x28 unique sequential index. u8 xIndex; // 0x28 unique sequential index.
u8 xSlicRsvd[3]; // 0x29-2b u8 xSlicRsvd[3]; // 0x29-2b
u32 xInUseWord; // 0x2C spinlock_t lock;
}; };
extern struct hvlpevent_queue hvlpevent_queue; extern struct hvlpevent_queue hvlpevent_queue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment