itlpqueue.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 179 行

C
179
字号
/*  * ItLpQueue.c * Copyright (C) 2001 Mike Corrigan  IBM Corporation *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */#include <linux/stddef.h>#include <linux/kernel.h>#include <linux/sched.h>#include <asm/system.h>#include <asm/iSeries/ItLpQueue.h>#include <asm/iSeries/HvLpEvent.h>#include <asm/iSeries/HvCallEvent.h>#include <asm/iSeries/LparData.h>static __inline__ int set_inUse( struct ItLpQueue * lpQueue ){	int t;	u32 * inUseP = &(lpQueue->xInUseWord);	__asm__ __volatile__("\n\1:	lwarx	%0,0,%2		\n\	cmpi	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" (lpQueue->xInUseWord)	: "r" (inUseP), "m" (lpQueue->xInUseWord)	: "cc");	return t;}static __inline__ void clear_inUse( struct ItLpQueue * lpQueue ){	lpQueue->xInUseWord = 0;}// Array of LpEvent handler functionsextern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];unsigned long ItLpQueueInProcess = 0;struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * lpQueue ){	struct HvLpEvent * nextLpEvent = 		(struct HvLpEvent *)lpQueue->xSlicCurEventPtr;	if ( nextLpEvent->xFlags.xValid ) {		// Set pointer to next potential event 		lpQueue->xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 +				      LpEventAlign ) /				      LpEventAlign ) *				      LpEventAlign;		// Wrap to beginning if no room at end		if (lpQueue->xSlicCurEventPtr > lpQueue->xSlicLastValidEventPtr)			lpQueue->xSlicCurEventPtr = lpQueue->xSlicEventStackPtr;	}	else 		nextLpEvent = NULL;	return nextLpEvent;}int ItLpQueue_isLpIntPending( struct ItLpQueue * lpQueue ){	struct HvLpEvent * nextLpEvent =		(struct HvLpEvent *)lpQueue->xSlicCurEventPtr;	return ( nextLpEvent->xFlags.xValid |		 lpQueue->xPlicOverflowIntPending);}void ItLpQueue_clearValid( struct HvLpEvent * event ){	// Clear the valid bit of the event	// Also clear bits within this event that might	// look like valid bits (on 64-byte boundaries)	unsigned extra = (( event->xSizeMinus1 + LpEventAlign ) /						 LpEventAlign ) - 1;	switch ( extra ) {	  case 3:	   ((struct HvLpEvent*)((char*)event+3*LpEventAlign))->xFlags.xValid=0;	  case 2:	   ((struct HvLpEvent*)((char*)event+2*LpEventAlign))->xFlags.xValid=0;	  case 1:	   ((struct HvLpEvent*)((char*)event+1*LpEventAlign))->xFlags.xValid=0;	  case 0:	}	mb();	event->xFlags.xValid = 0;}// No lock is necessary when processing the Lp Queue because a single// processor is assigned to each lpqueue.  Interrupts are disabled// while processing events.// Some device drivers' interrupt handlers run with interrupts // enabled.  This requires us to prevent being re-entered here.// We use the xInUse flag for that.unsigned lpQueue_proc_count[32] = {};unsigned ItLpQueue_process( struct ItLpQueue * lpQueue, struct pt_regs *regs ){	unsigned numIntsProcessed = 0;	struct HvLpEvent * nextLpEvent;	// If we have recursed, just return	if ( !set_inUse( lpQueue ) )		return 0;		if (ItLpQueueInProcess == 0)	    ItLpQueueInProcess = 1;	else	    BUG();		++lpQueue_proc_count[current->processor];		for (;;) {		nextLpEvent = ItLpQueue_getNextLpEvent( lpQueue );				if ( nextLpEvent ) {			// Count events to return to caller			// and count processed events in lpQueue			++numIntsProcessed;			lpQueue->xLpIntCount++;					// Call appropriate handler here, passing 			// a pointer to the LpEvent.  The handler			// must make a copy of the LpEvent if it			// needs it in a bottom half. (perhaps for			// an ACK)						//  Handlers are responsible for ACK processing 			// The Hypervisor guarantees that LpEvents will			// only be delivered with types that we have			// registered for, so no type check is necessary			// here!			if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes )				lpQueue->xLpIntCountByType[nextLpEvent->xType]++;			if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes &&			     lpEventHandler[nextLpEvent->xType] ) 				lpEventHandler[nextLpEvent->xType](nextLpEvent, regs);			else				printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType );						ItLpQueue_clearValid( nextLpEvent );		}		else 	// No more valid events			// If overflow events are pending			// process them			if ( lpQueue->xPlicOverflowIntPending ) {				HvCallEvent_getOverflowLpEvents( 						lpQueue->xIndex);			}			else	// If nothing left then we are done				break;	}	ItLpQueueInProcess = 0;	mb();	clear_inUse( lpQueue );	return numIntsProcessed;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?