Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+2 −36
Original line number Diff line number Diff line
@@ -42,35 +42,8 @@ static char *event_types[HvLpEvent_Type_NumTypes] = {
	"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 */
extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
unsigned long ItLpQueueInProcess = 0;

static struct HvLpEvent * get_next_hvlpevent(void)
{
@@ -144,14 +117,9 @@ void process_hvlpevents(struct pt_regs *regs)
	struct HvLpEvent * event;

	/* If we have recursed, just return */
	if ( !set_inUse() )
	if (!spin_trylock(&hvlpevent_queue.lock))
		return;

	if (ItLpQueueInProcess == 0)
		ItLpQueueInProcess = 1;
	else
		BUG();

	for (;;) {
		event = get_next_hvlpevent();
		if (event) {
@@ -187,9 +155,7 @@ void process_hvlpevents(struct pt_regs *regs)
			break;
	}

	ItLpQueueInProcess = 0;
	mb();
	clear_inUse();
	spin_unlock(&hvlpevent_queue.lock);
}

static int set_spread_lpevents(char *str)
+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ struct hvlpevent_queue {
	char	*xSlicEventStackPtr;	// 0x20
	u8	xIndex;			// 0x28 unique sequential index.
	u8	xSlicRsvd[3];		// 0x29-2b
	u32	xInUseWord;		// 0x2C
	spinlock_t	lock;
};

extern struct hvlpevent_queue hvlpevent_queue;