diff options
Diffstat (limited to 'drivers/net/npe/IxQMgrDispatcher.c')
| -rw-r--r-- | drivers/net/npe/IxQMgrDispatcher.c | 1320 | 
1 files changed, 0 insertions, 1320 deletions
diff --git a/drivers/net/npe/IxQMgrDispatcher.c b/drivers/net/npe/IxQMgrDispatcher.c deleted file mode 100644 index 2baeaafeb..000000000 --- a/drivers/net/npe/IxQMgrDispatcher.c +++ /dev/null @@ -1,1320 +0,0 @@ -/** - * @file    IxQMgrDispatcher.c - * - * @author Intel Corporation - * @date    20-Dec-2001 - *     - * @brief   This file contains the implementation of the Dispatcher sub component - * - *  - * @par - * IXP400 SW Release version 2.0 - *  - * -- Copyright Notice -- - *  - * @par - * Copyright 2001-2005, Intel Corporation. - * All rights reserved. - *  - * @par - * SPDX-License-Identifier:	BSD-3-Clause - * @par - * -- End of Copyright Notice -- -*/ - -/* - * User defined include files. - */ -#include "IxQMgr.h" -#include "IxQMgrAqmIf_p.h" -#include "IxQMgrQCfg_p.h" -#include "IxQMgrDispatcher_p.h" -#include "IxQMgrLog_p.h" -#include "IxQMgrDefines_p.h" -#include "IxFeatureCtrl.h" -#include "IxOsal.h" - - - -/* - * #defines and macros used in this file. - */ - - -/* - * This constant is used to indicate the number of priority levels supported - */ -#define IX_QMGR_NUM_PRIORITY_LEVELS 3 - -/*  - * This constant is used to set the size of the array of status words - */ -#define MAX_Q_STATUS_WORDS      4 - -/* - * This macro is used to check if a given priority is valid - */ -#define IX_QMGR_DISPATCHER_PRIORITY_CHECK(priority) \ -(((priority) >= IX_QMGR_Q_PRIORITY_0) && ((priority) <= IX_QMGR_Q_PRIORITY_2)) - -/* - * This macto is used to check that a given interrupt source is valid - */ -#define IX_QMGR_DISPATCHER_SOURCE_ID_CHECK(srcSel) \ -(((srcSel) >= IX_QMGR_Q_SOURCE_ID_E) && ((srcSel) <= IX_QMGR_Q_SOURCE_ID_NOT_F)) - -/* - * Number of times a dummy callback is called before logging a trace - * message - */ -#define LOG_THROTTLE_COUNT 1000000 - -/* Priority tables limits */ -#define IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX (0) -#define IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX (16) -#define IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX (31) -#define IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX (32) -#define IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX (48) -#define IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX (63) -  -/* - * This macro is used to check if a given callback type is valid - */ -#define IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type) \ -            (((type) >= IX_QMGR_TYPE_REALTIME_OTHER) && \ -            ((type) <= IX_QMGR_TYPE_REALTIME_SPORADIC)) - -/*  - * define max index in lower queue to use in loops  - */ -#define IX_QMGR_MAX_LOW_QUE_TABLE_INDEX (31) - -/* - * Typedefs whose scope is limited to this file. - */ - -/* - * Information on a queue needed by the Dispatcher - */ -typedef struct  -{ -    IxQMgrCallback callback;       /* Notification callback                  */ -    IxQMgrCallbackId callbackId;   /* Notification callback identifier       */ -    unsigned dummyCallbackCount;   /* Number of times runs of dummy callback */ -    IxQMgrPriority priority;       /* Dispatch priority                      */ -    unsigned int statusWordOffset; /* Offset to the status word to check     */ -    UINT32 statusMask;             /* Status mask                            */     -    UINT32 statusCheckValue;       /* Status check value                     */ -    UINT32 intRegCheckMask;	   /* Interrupt register check mask          */ -} IxQMgrQInfo; - -/* - * Variable declarations global to this file. Externs are followed by - * statics. - */ - -/*  - * Flag to keep record of what dispatcher set in featureCtrl when ixQMgrInit() - * is called. This is needed because it is possible that a client might - * change whether the live lock prevention dispatcher is used between - * calls to ixQMgrInit() and ixQMgrDispatcherLoopGet().  - */ -PRIVATE IX_STATUS ixQMgrOrigB0Dispatcher = IX_FEATURE_CTRL_COMPONENT_ENABLED; - -/*  - * keep record of Q types - not in IxQMgrQInfo for performance as - * it is only used with ixQMgrDispatcherLoopRunB0LLP() - */ -PRIVATE IxQMgrType ixQMgrQTypes[IX_QMGR_MAX_NUM_QUEUES]; - -/* - * This array contains a list of queue identifiers ordered by priority. The table - * is split logically between queue identifiers 0-31 and 32-63. - */ -static IxQMgrQId priorityTable[IX_QMGR_MAX_NUM_QUEUES]; - -/* - * This flag indicates to the dispatcher that the priority table needs to be rebuilt. - */ -static BOOL rebuildTable = false; - -/* Dispatcher statistics */ -static IxQMgrDispatcherStats dispatcherStats; - -/* Table of queue information */ -static IxQMgrQInfo dispatchQInfo[IX_QMGR_MAX_NUM_QUEUES]; - -/* Masks use to identify the first queues in the priority tables  -*  when comparing with the interrupt register -*/ -static unsigned int lowPriorityTableFirstHalfMask; -static unsigned int uppPriorityTableFirstHalfMask; - -/* - * Static function prototypes - */ - -/* - * This function is the default callback for all queues - */ -PRIVATE void -dummyCallback (IxQMgrQId qId,	       -	       IxQMgrCallbackId cbId); - -PRIVATE void -ixQMgrDispatcherReBuildPriorityTable (void); - -/* - * Function definitions. - */ -void -ixQMgrDispatcherInit (void) -{ -    int i; -    IxFeatureCtrlProductId productId = 0; -    IxFeatureCtrlDeviceId deviceId = 0; -    BOOL stickyIntSilicon = true; - -    /* Set default priorities */ -    for (i=0; i< IX_QMGR_MAX_NUM_QUEUES; i++) -    { -	dispatchQInfo[i].callback = dummyCallback; -	dispatchQInfo[i].callbackId = 0; -	dispatchQInfo[i].dummyCallbackCount = 0; -	dispatchQInfo[i].priority = IX_QMGR_Q_PRIORITY_2; -	dispatchQInfo[i].statusWordOffset = 0; -	dispatchQInfo[i].statusCheckValue = 0; -	dispatchQInfo[i].statusMask = 0;   -        /*  -	 * There are two interrupt registers, 32 bits each. One for the lower -	 * queues(0-31) and one for the upper queues(32-63). Therefore need to -	 * mod by 32 i.e the min upper queue identifier. -	 */ -	dispatchQInfo[i].intRegCheckMask = (1<<(i%(IX_QMGR_MIN_QUEUPP_QID))); - -        /*  -         * Set the Q types - will only be used with livelock  -         */ -        ixQMgrQTypes[i] = IX_QMGR_TYPE_REALTIME_OTHER; - -	/* Reset queue statistics */ -	dispatcherStats.queueStats[i].callbackCnt = 0; -	dispatcherStats.queueStats[i].priorityChangeCnt = 0; -	dispatcherStats.queueStats[i].intNoCallbackCnt = 0; -	dispatcherStats.queueStats[i].intLostCallbackCnt = 0; -        dispatcherStats.queueStats[i].notificationEnabled = false; -        dispatcherStats.queueStats[i].srcSel = 0; - -    } - -    /* Priority table. Order the table from queue 0 to 63 */ -    ixQMgrDispatcherReBuildPriorityTable(); - -    /* Reset statistics */ -    dispatcherStats.loopRunCnt = 0; - -    /* Get the device ID for the underlying silicon */ -    deviceId = ixFeatureCtrlDeviceRead(); -     -    /* Get the product ID for the underlying silicon */ -    productId = ixFeatureCtrlProductIdRead(); - -    /*  -     * Check featureCtrl to see if Livelock prevention is required  -     */ -    ixQMgrOrigB0Dispatcher = ixFeatureCtrlSwConfigurationCheck(  -                                 IX_FEATURECTRL_ORIGB0_DISPATCHER); - -    /* -     * Check if the silicon supports the sticky interrupt feature. -     * IF (IXP42X AND A0) -> No sticky interrupt feature supported  -     */ -    if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X ==  -        (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) && -        (IX_FEATURE_CTRL_SILICON_TYPE_A0 ==  -        (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId)))  -    { -       stickyIntSilicon = false; -    } - -    /* -     * IF user wants livelock prev option AND silicon supports sticky interrupt  -     * feature -> enable the sticky interrupt bit -     */ -    if ((IX_FEATURE_CTRL_SWCONFIG_DISABLED == ixQMgrOrigB0Dispatcher) && -         stickyIntSilicon)   -    { -        ixQMgrStickyInterruptRegEnable(); -    } -} - -IX_STATUS -ixQMgrDispatcherPrioritySet (IxQMgrQId qId, -			     IxQMgrPriority priority) -{    -    int ixQMgrLockKey; - -    if (!ixQMgrQIsConfigured(qId)) -    { -	return IX_QMGR_Q_NOT_CONFIGURED; -    } -     -    if (!IX_QMGR_DISPATCHER_PRIORITY_CHECK(priority)) -    { -	return IX_QMGR_Q_INVALID_PRIORITY; -    } - -    ixQMgrLockKey = ixOsalIrqLock(); -     -    /* Change priority */ -    dispatchQInfo[qId].priority = priority; -    /* Set flag */ -    rebuildTable = true; - -    ixOsalIrqUnlock(ixQMgrLockKey); - -#ifndef NDEBUG -    /* Update statistics */ -    dispatcherStats.queueStats[qId].priorityChangeCnt++; -#endif - -    return IX_SUCCESS; -} - -IX_STATUS -ixQMgrNotificationCallbackSet (IxQMgrQId qId, -			       IxQMgrCallback callback, -			       IxQMgrCallbackId callbackId) -{ -    if (!ixQMgrQIsConfigured(qId)) -    { -	return IX_QMGR_Q_NOT_CONFIGURED; -    } - -    if (NULL == callback) -    { -	/* Reset to dummy callback */ -	dispatchQInfo[qId].callback = dummyCallback; -	dispatchQInfo[qId].dummyCallbackCount = 0; -	dispatchQInfo[qId].callbackId = 0; -    } -    else  -    { -	dispatchQInfo[qId].callback = callback; -	dispatchQInfo[qId].callbackId = callbackId; -    } - -    return IX_SUCCESS; -} - -IX_STATUS -ixQMgrNotificationEnable (IxQMgrQId qId,  -			  IxQMgrSourceId srcSel) -{ -    IxQMgrQStatus qStatusOnEntry;/* The queue status on entry/exit */ -    IxQMgrQStatus qStatusOnExit; /* to this function               */ -    int ixQMgrLockKey; - -#ifndef NDEBUG -    if (!ixQMgrQIsConfigured (qId)) -    { -	return IX_QMGR_Q_NOT_CONFIGURED; -    } - -    if ((qId < IX_QMGR_MIN_QUEUPP_QID) && -       !IX_QMGR_DISPATCHER_SOURCE_ID_CHECK(srcSel)) -    { -	/* QId 0-31 source id invalid */ -	return IX_QMGR_INVALID_INT_SOURCE_ID; -    } - -    if ((IX_QMGR_Q_SOURCE_ID_NE != srcSel) && -	(qId >= IX_QMGR_MIN_QUEUPP_QID)) -    { -	/* -	 * For queues 32-63 the interrupt source is fixed to the Nearly -	 * Empty status flag and therefore should have a srcSel of NE. -	 */ -	return IX_QMGR_INVALID_INT_SOURCE_ID; -    } -#endif - -#ifndef NDEBUG -    dispatcherStats.queueStats[qId].notificationEnabled = true; -    dispatcherStats.queueStats[qId].srcSel = srcSel; -#endif - -    /* Get the current queue status */ -    ixQMgrAqmIfQueStatRead (qId, &qStatusOnEntry); -   -    /*  -     * Enabling interrupts results in Read-Modify-Write -     * so need critical section -     */ - -    ixQMgrLockKey = ixOsalIrqLock(); - -    /* Calculate the checkMask and checkValue for this q */ -    ixQMgrAqmIfQStatusCheckValsCalc (qId, -				     srcSel, -				     &dispatchQInfo[qId].statusWordOffset, -				     &dispatchQInfo[qId].statusCheckValue, -				     &dispatchQInfo[qId].statusMask); - - -    /* Set the interrupt source is this queue is in the range 0-31 */ -    if (qId < IX_QMGR_MIN_QUEUPP_QID) -    { -	ixQMgrAqmIfIntSrcSelWrite (qId, srcSel); -    } - -    /* Enable the interrupt */ -    ixQMgrAqmIfQInterruptEnable (qId); - -    ixOsalIrqUnlock(ixQMgrLockKey); -     -    /* Get the current queue status */ -    ixQMgrAqmIfQueStatRead (qId, &qStatusOnExit); -   -    /* If the status has changed return a warning */ -    if (qStatusOnEntry != qStatusOnExit) -    { -	return IX_QMGR_WARNING; -    } -     -    return IX_SUCCESS; -} - - -IX_STATUS -ixQMgrNotificationDisable (IxQMgrQId qId) -{ -    int ixQMgrLockKey; - -#ifndef NDEBUG -    /* Validate parameters */ -    if (!ixQMgrQIsConfigured (qId)) -    { -	return IX_QMGR_Q_NOT_CONFIGURED; -    } -#endif -   -    /*  -     * Enabling interrupts results in Read-Modify-Write -     * so need critical section -     */ -#ifndef NDEBUG -    dispatcherStats.queueStats[qId].notificationEnabled = false; -#endif - -    ixQMgrLockKey = ixOsalIrqLock(); - -    ixQMgrAqmIfQInterruptDisable (qId); -     -    ixOsalIrqUnlock(ixQMgrLockKey); - -    return IX_SUCCESS;     -} - -void  -ixQMgrStickyInterruptRegEnable(void) -{ - /* Use Aqm If function to set Interrupt Register0 Bit-3 */  - ixQMgrAqmIfIntSrcSelReg0Bit3Set ();    -} - -#if !defined __XSCALE__ || defined __linux - -/* Count the number of leading zero bits in a word, - * and return the same value than the CLZ instruction. - * - * word (in)    return value (out) - * 0x80000000   0 - * 0x40000000   1 - * ,,,          ,,, - * 0x00000002   30 - * 0x00000001   31 - * 0x00000000   32 - * - * The C version of this function is used as a replacement  - * for system not providing the equivalent of the CLZ  - * assembly language instruction. - * - * Note that this version is big-endian - */ -unsigned int -ixQMgrCountLeadingZeros(UINT32 word) -{ -  unsigned int leadingZerosCount = 0; - -  if (word == 0) -  { -      return 32; -  } -  /* search the first bit set by testing the MSB and shifting the input word */ -  while ((word & 0x80000000) == 0) -  { -      word <<= 1; -      leadingZerosCount++; -  } -  return leadingZerosCount; -} -#endif /* not  __XSCALE__ or __linux */ - -void -ixQMgrDispatcherLoopGet (IxQMgrDispatcherFuncPtr *qDispatcherFuncPtr) -{ -  IxFeatureCtrlProductId productId = 0; -  IxFeatureCtrlDeviceId deviceId = 0; -   -  /* Get the device ID for the underlying silicon */ -  deviceId = ixFeatureCtrlDeviceRead(); - -  /* Get the product ID for the underlying silicon */ -  productId = ixFeatureCtrlProductIdRead (); - -  /* IF (IXP42X AND A0 silicon) -> use ixQMgrDispatcherLoopRunA0 */ -  if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X == -      (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) && -      (IX_FEATURE_CTRL_SILICON_TYPE_A0 ==   -      (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId)))   -  { -    /*For IXP42X A0 silicon */ -    *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunA0 ; -  }  -  else /*For IXP42X B0 or IXP46X silicon*/  -  {  -    if (IX_FEATURE_CTRL_SWCONFIG_ENABLED == ixQMgrOrigB0Dispatcher) -    { -        /* Default for IXP42X B0 and IXP46X silicon */ -        *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0; -    } -    else  -    { -        /* FeatureCtrl indicated that livelock dispatcher be used */ -        *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0LLP; -    } -  } -} - -void -ixQMgrDispatcherLoopRunA0 (IxQMgrDispatchGroup group) -{ -    UINT32 intRegVal;                /* Interrupt reg val */ -    UINT32 intRegValAfterWrite;      /* Interrupt reg val after writing back */ -    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */ -    UINT32 qStatusWordsB4Write[MAX_Q_STATUS_WORDS];  /* Status b4 interrupt write */ -    UINT32 qStatusWordsAfterWrite[MAX_Q_STATUS_WORDS]; /* Status after interrupt write */ -    IxQMgrQInfo *currDispatchQInfo; -    BOOL statusChangeFlag; - -    int priorityTableIndex;/* Priority table index */ -    int qIndex;            /* Current queue being processed */ -    int endIndex;          /* Index of last queue to process */ - -#ifndef NDEBUG -    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||  -	      (group == IX_QMGR_QUELOW_GROUP)); -#endif - -    /* Read Q status registers before interrupt status read/write */ -    ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsB4Write); - -    /* Read the interrupt register */ -    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal); - -    /* No bit set : nothing to process (the reaminder of the algorithm is -    * based on the fact that the interrupt register value contains at -    * least one bit set -    */ -    if (intRegVal == 0)  -    { -#ifndef NDEBUG -	/* Update statistics */ -	dispatcherStats.loopRunCnt++; -#endif - -	/* Rebuild the priority table if needed */ -	if (rebuildTable) -	{ -	    ixQMgrDispatcherReBuildPriorityTable (); -	} - -	return; -    } -    -    /* Write it back to clear the interrupt */ -    ixQMgrAqmIfQInterruptRegWrite (group, intRegVal); - -    /* Read Q status registers after interrupt status read/write */ -    ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsAfterWrite); -  -    /* get the first queue Id from the interrupt register value */ -    qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal); - -    /* check if any change occured during hw register modifications */  -    if (IX_QMGR_QUELOW_GROUP == group) -    { -	statusChangeFlag =  -	    (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]) || -	    (qStatusWordsB4Write[1] != qStatusWordsAfterWrite[1]) || -	    (qStatusWordsB4Write[2] != qStatusWordsAfterWrite[2]) || -	    (qStatusWordsB4Write[3] != qStatusWordsAfterWrite[3]); -    } -    else -    { -	statusChangeFlag =  -	    (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]); -	/* Set the queue range based on the queue group to proccess */ -	qIndex += IX_QMGR_MIN_QUEUPP_QID; -    } - -    if (statusChangeFlag == false) -    { -	/* check if the interrupt register contains  -	 * only 1 bit set (happy day scenario) -	 */ -	currDispatchQInfo = &dispatchQInfo[qIndex]; -	if (intRegVal == currDispatchQInfo->intRegCheckMask) -	{ -	    /* only 1 queue event triggered a notification * -	     * Call the callback function for this queue  -	     */ -	    currDispatchQInfo->callback (qIndex, -					 currDispatchQInfo->callbackId);   -#ifndef NDEBUG -	    /* Update statistics */ -	    dispatcherStats.queueStats[qIndex].callbackCnt++; -#endif -	} -	else  -	{ -	    /* the event is triggered by more than 1 queue,  -	     * the queue search will be starting from the beginning -	     * or the middle of the priority table -	     * -	     * the serach will end when all the bits of the interrupt -	     * register are cleared. There is no need to maintain -	     * a seperate value and test it at each iteration. -	     */ -	    if (IX_QMGR_QUELOW_GROUP == group) -	    { -		/* check if any bit related to queues in the first -		 * half of the priority table is set -		 */ -		if (intRegVal & lowPriorityTableFirstHalfMask) -		{ -		    priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; -		} -		else -		{ -		    priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX; -		} -	    } -	    else  -	    { -		/* check if any bit related to queues in the first -		 * half of the priority table is set -		 */ -		if (intRegVal & uppPriorityTableFirstHalfMask) -		{ -		    priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; -		} -		else -		{ -		    priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX; -		} -	    } -	     -	    /* iterate following the priority table until all the bits  -	     * of the interrupt register are cleared. -	     */ -	    do -	    { -		qIndex = priorityTable[priorityTableIndex++]; -		currDispatchQInfo = &dispatchQInfo[qIndex]; -		intRegCheckMask = currDispatchQInfo->intRegCheckMask; -		 -		/* If this queue caused this interrupt to be raised */ -		if (intRegVal & intRegCheckMask) -		{ -		    /* Call the callback function for this queue */ -		    currDispatchQInfo->callback (qIndex, -						 currDispatchQInfo->callbackId); -#ifndef NDEBUG -		    /* Update statistics */ -		    dispatcherStats.queueStats[qIndex].callbackCnt++; -#endif -		     -		    /* Clear the interrupt register bit */ -		    intRegVal &= ~intRegCheckMask; -		} -	    } -	    while(intRegVal); -	} -    } -    else -    { -    /* A change in queue status occured during the hw interrupt -     * register update. To maintain the interrupt consistency, it -     * is necessary to iterate through all queues of the queue group. -     */ - -    /* Read interrupt status again */ -    ixQMgrAqmIfQInterruptRegRead (group, &intRegValAfterWrite); - -    if (IX_QMGR_QUELOW_GROUP == group) -    { -	priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; -	endIndex = IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX; -    } -    else -    { -	priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; -	endIndex = IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX; -    } - -    for ( ; priorityTableIndex<=endIndex; priorityTableIndex++) -    { -	qIndex = priorityTable[priorityTableIndex]; -	currDispatchQInfo = &dispatchQInfo[qIndex]; -	intRegCheckMask = currDispatchQInfo->intRegCheckMask; - -	/* If this queue caused this interrupt to be raised */ -	if (intRegVal & intRegCheckMask) -	{   -	    /* Call the callback function for this queue */ -	    currDispatchQInfo->callback (qIndex, -					 currDispatchQInfo->callbackId); -#ifndef NDEBUG -	    /* Update statistics */ -	    dispatcherStats.queueStats[qIndex].callbackCnt++; -#endif -	     -	} /* if (intRegVal .. */ - -	/*  -	 * If interrupt bit is set in intRegValAfterWrite don't -	 * proceed as this will be caught in next interrupt -	 */ -	else if ((intRegValAfterWrite & intRegCheckMask) == 0) -	{ -	    /* Check if an interrupt was lost for this Q */ -	    if (ixQMgrAqmIfQStatusCheck(qStatusWordsB4Write, -					qStatusWordsAfterWrite, -					currDispatchQInfo->statusWordOffset, -					currDispatchQInfo->statusCheckValue, -					currDispatchQInfo->statusMask)) -	    { -		/* Call the callback function for this queue */ -		currDispatchQInfo->callback (qIndex,  -					     dispatchQInfo[qIndex].callbackId);                  -#ifndef NDEBUG -		/* Update statistics */ -		dispatcherStats.queueStats[qIndex].callbackCnt++; -		dispatcherStats.queueStats[qIndex].intLostCallbackCnt++; -#endif -	    } /* if ixQMgrAqmIfQStatusCheck(.. */ -	} /* else if ((intRegValAfterWrite ... */ -    } /* for (priorityTableIndex=0 ... */ -    } - -    /* Rebuild the priority table if needed */ -    if (rebuildTable) -    { -	ixQMgrDispatcherReBuildPriorityTable (); -    } - -#ifndef NDEBUG -    /* Update statistics */ -    dispatcherStats.loopRunCnt++; -#endif -} - - - -void -ixQMgrDispatcherLoopRunB0 (IxQMgrDispatchGroup group) -{ -    UINT32 intRegVal;                /* Interrupt reg val */ -    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */ -    IxQMgrQInfo *currDispatchQInfo; - - -    int priorityTableIndex; /* Priority table index */ -    int qIndex;             /* Current queue being processed */ - -#ifndef NDEBUG -    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || -              (group == IX_QMGR_QUELOW_GROUP)); -    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||  -	      (group == IX_QMGR_QUELOW_GROUP)); -#endif - -    /* Read the interrupt register */ -    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal); - - -    /* No queue has interrupt register set */ -    if (intRegVal != 0) -    { - -            /* Write it back to clear the interrupt */ -            ixQMgrAqmIfQInterruptRegWrite (group, intRegVal); - -            /* get the first queue Id from the interrupt register value */ -            qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal); - -            if (IX_QMGR_QUEUPP_GROUP == group) -            { -                /* Set the queue range based on the queue group to proccess */ -                qIndex += IX_QMGR_MIN_QUEUPP_QID; -            } - -            /* check if the interrupt register contains -             * only 1 bit set -             * For example: -             *                                        intRegVal = 0x0010 -             *               currDispatchQInfo->intRegCheckMask = 0x0010 -             *    intRegVal == currDispatchQInfo->intRegCheckMask is true. -             */ -             currDispatchQInfo = &dispatchQInfo[qIndex]; -             if (intRegVal == currDispatchQInfo->intRegCheckMask) -             { -                /* only 1 queue event triggered a notification * -                 * Call the callback function for this queue -                 */ -                currDispatchQInfo->callback (qIndex, -                                     currDispatchQInfo->callbackId); -#ifndef NDEBUG -                /* Update statistics */ -                dispatcherStats.queueStats[qIndex].callbackCnt++; -#endif -             } -             else -             { -                 /* the event is triggered by more than 1 queue, -                  * the queue search will be starting from the beginning -                  * or the middle of the priority table -                  * -                  * the serach will end when all the bits of the interrupt -                  * register are cleared. There is no need to maintain -                  * a seperate value and test it at each iteration. -                  */ -                 if (IX_QMGR_QUELOW_GROUP == group) -                 { -                     /* check if any bit related to queues in the first -                      * half of the priority table is set -                      */ -                     if (intRegVal & lowPriorityTableFirstHalfMask) -                     { -                         priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; -                     } -                     else -                     { -                         priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX; -                     } -                 } -                else -                 { -                     /* check if any bit related to queues in the first -                      * half of the priority table is set -                      */ -                     if (intRegVal & uppPriorityTableFirstHalfMask) -                     { -                         priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; -                     } -                     else -                     { -                         priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX; -                     } -                 } - -                 /* iterate following the priority table until all the bits -                  * of the interrupt register are cleared. -                  */ -                 do -                 { -                     qIndex = priorityTable[priorityTableIndex++]; -                     currDispatchQInfo = &dispatchQInfo[qIndex]; -                     intRegCheckMask = currDispatchQInfo->intRegCheckMask; - -                     /* If this queue caused this interrupt to be raised */ -                     if (intRegVal & intRegCheckMask) -                     { -                         /* Call the callback function for this queue */ -                         currDispatchQInfo->callback (qIndex, -                                              currDispatchQInfo->callbackId); -#ifndef NDEBUG -                         /* Update statistics */ -                         dispatcherStats.queueStats[qIndex].callbackCnt++; -#endif - -                         /* Clear the interrupt register bit */ -                         intRegVal &= ~intRegCheckMask; -                     } -                  } -                  while(intRegVal); -             } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */ -     } /* End of intRegVal != 0 */ - -#ifndef NDEBUG -    /* Update statistics */ -    dispatcherStats.loopRunCnt++; -#endif - -    /* Rebuild the priority table if needed */ -    if (rebuildTable) -    { -        ixQMgrDispatcherReBuildPriorityTable (); -    } -} - -void -ixQMgrDispatcherLoopRunB0LLP (IxQMgrDispatchGroup group) -{ -    UINT32 intRegVal =0;                /* Interrupt reg val */ -    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */ -    IxQMgrQInfo *currDispatchQInfo; - -    int priorityTableIndex; /* Priority table index */ -    int qIndex;             /* Current queue being processed */ - -    UINT32 intRegValCopy = 0; -    UINT32 intEnableRegVal = 0; -    UINT8 i = 0; - -#ifndef NDEBUG -    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || -              (group == IX_QMGR_QUELOW_GROUP)); -#endif - -    /* Read the interrupt register */ -    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal); - -    /*  -     * mask any interrupts that are not enabled  -     */ -    ixQMgrAqmIfQInterruptEnableRegRead (group, &intEnableRegVal); -    intRegVal &= intEnableRegVal; - -    /* No queue has interrupt register set */ -    if (intRegVal != 0) -    { -        if (IX_QMGR_QUELOW_GROUP == group) -        { -            /* -             * As the sticky bit is set, the interrupt register will  -             * not clear if write back at this point because the condition -             * has not been cleared. Take a copy and write back later after -             * the condition has been cleared -             */ -            intRegValCopy = intRegVal; -        } -        else -        { -            /* no sticky for upper Q's, so write back now */ -            ixQMgrAqmIfQInterruptRegWrite (group, intRegVal); -        } - -        /* get the first queue Id from the interrupt register value */ -        qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal); - -        if (IX_QMGR_QUEUPP_GROUP == group) -        { -            /* Set the queue range based on the queue group to proccess */ -            qIndex += IX_QMGR_MIN_QUEUPP_QID; -        } - -        /* check if the interrupt register contains -        * only 1 bit set -        * For example: -        *                                        intRegVal = 0x0010 -        *               currDispatchQInfo->intRegCheckMask = 0x0010 -        *    intRegVal == currDispatchQInfo->intRegCheckMask is true. -        */ -        currDispatchQInfo = &dispatchQInfo[qIndex]; -        if (intRegVal == currDispatchQInfo->intRegCheckMask) -        { - -            /*  -             * check if Q type periodic -  only lower queues can -             * have there type set to periodic  -             */ -            if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex]) -            { -                /*  -                 * Disable the notifications on any sporadics  -                 */ -                for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) -                { -                    if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i]) -                    { -                        ixQMgrNotificationDisable(i); -#ifndef NDEBUG -                        /* Update statistics */ -                        dispatcherStats.queueStats[i].disableCount++; -#endif -                    } -                } -            } - -            currDispatchQInfo->callback (qIndex, -                                         currDispatchQInfo->callbackId); -#ifndef NDEBUG -            /* Update statistics */ -            dispatcherStats.queueStats[qIndex].callbackCnt++; -#endif -        } -        else -        { -            /* the event is triggered by more than 1 queue, -            * the queue search will be starting from the beginning -            * or the middle of the priority table -            * -            * the serach will end when all the bits of the interrupt -            * register are cleared. There is no need to maintain -            * a seperate value and test it at each iteration. -            */ -            if (IX_QMGR_QUELOW_GROUP == group) -            { -                /* check if any bit related to queues in the first -                 * half of the priority table is set -                 */ -                if (intRegVal & lowPriorityTableFirstHalfMask) -                { -                    priorityTableIndex = -                                       IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; -                } -                else -                { -                    priorityTableIndex = -                                       IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX; -                } -            } -            else -            { -                /* check if any bit related to queues in the first -                 * half of the priority table is set -                 */ -                if (intRegVal & uppPriorityTableFirstHalfMask) -                { -                    priorityTableIndex = -                                       IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; -                } -                else -                { -                    priorityTableIndex = -                                       IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX; -                } -            } - -            /* iterate following the priority table until all the bits -             * of the interrupt register are cleared. -             */ -            do -            { -                qIndex = priorityTable[priorityTableIndex++]; -                currDispatchQInfo = &dispatchQInfo[qIndex]; -                intRegCheckMask = currDispatchQInfo->intRegCheckMask; - -                /* If this queue caused this interrupt to be raised */ -                if (intRegVal & intRegCheckMask) -                { -                    /*  -                     * check if Q type periodic - only lower queues can -                     * have there type set to periodic. There can only be one -                     * periodic queue, so the sporadics are only disabled once. -                     */ -                    if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex]) -                    { -                        /*  -                         * Disable the notifications on any sporadics  -                         */ -                        for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) -                        { -                            if (IX_QMGR_TYPE_REALTIME_SPORADIC ==  -                                    ixQMgrQTypes[i]) -                            { -                                ixQMgrNotificationDisable(i); -                                /*  -                                 * remove from intRegVal as we don't want  -                                 * to service any sporadics now -                                 */ -                                intRegVal &= ~dispatchQInfo[i].intRegCheckMask; -#ifndef NDEBUG -                                /* Update statistics */ -                                dispatcherStats.queueStats[i].disableCount++; -#endif -                            } -                        } -                    } - -                    currDispatchQInfo->callback (qIndex, -                                                 currDispatchQInfo->callbackId); -#ifndef NDEBUG -                    /* Update statistics */ -                    dispatcherStats.queueStats[qIndex].callbackCnt++; -#endif -                    /* Clear the interrupt register bit */ -                    intRegVal &= ~intRegCheckMask; -                } -            } -            while(intRegVal); -        } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */ -    } /* End of intRegVal != 0 */ - -#ifndef NDEBUG -    /* Update statistics */ -    dispatcherStats.loopRunCnt++; -#endif - -    if ((intRegValCopy != 0) && (IX_QMGR_QUELOW_GROUP == group)) -    { -        /*  -         * lower groups (therefore sticky) AND at least one enabled interrupt -         * Write back to clear the interrupt  -         */ -        ixQMgrAqmIfQInterruptRegWrite (IX_QMGR_QUELOW_GROUP, intRegValCopy); -    } - -    /* Rebuild the priority table if needed */ -    if (rebuildTable) -    { -        ixQMgrDispatcherReBuildPriorityTable (); -    } -} - -PRIVATE void -ixQMgrDispatcherReBuildPriorityTable (void) -{ -    UINT32 qIndex; -    UINT32 priority; -    int lowQuePriorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; -    int uppQuePriorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; - -    /* Reset the rebuild flag */ -    rebuildTable = false; - -    /* initialize the mak used to identify the queues in the first half -     * of the priority table -     */ -    lowPriorityTableFirstHalfMask = 0; -    uppPriorityTableFirstHalfMask = 0; -     -    /* For each priority level */ -    for(priority=0; priority<IX_QMGR_NUM_PRIORITY_LEVELS; priority++) -    { -	/* Foreach low queue in this priority */ -	for(qIndex=0; qIndex<IX_QMGR_MIN_QUEUPP_QID; qIndex++) -	{ -	    if (dispatchQInfo[qIndex].priority == priority) -	    {  -		/* build the priority table bitmask which match the -		 * queues of the first half of the priority table  -		 */ -		if (lowQuePriorityTableIndex < IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX)  -		{ -		    lowPriorityTableFirstHalfMask |= dispatchQInfo[qIndex].intRegCheckMask; -		} -		/* build the priority table */ -		priorityTable[lowQuePriorityTableIndex++] = qIndex; -	    } -	} -	/* Foreach upp queue */ -	for(qIndex=IX_QMGR_MIN_QUEUPP_QID; qIndex<=IX_QMGR_MAX_QID; qIndex++) -	{ -	    if (dispatchQInfo[qIndex].priority == priority) -	    { -		/* build the priority table bitmask which match the -		 * queues of the first half of the priority table  -		 */ -		if (uppQuePriorityTableIndex < IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX)  -		{ -		    uppPriorityTableFirstHalfMask |= dispatchQInfo[qIndex].intRegCheckMask; -		} -		/* build the priority table */ -		priorityTable[uppQuePriorityTableIndex++] = qIndex; -	    } -	} -    } -} - -IxQMgrDispatcherStats* -ixQMgrDispatcherStatsGet (void) -{ -    return &dispatcherStats; -} - -PRIVATE void -dummyCallback (IxQMgrQId qId, -	       IxQMgrCallbackId cbId) -{ -    /* Throttle the trace message */ -    if ((dispatchQInfo[qId].dummyCallbackCount % LOG_THROTTLE_COUNT) == 0) -    { -	IX_QMGR_LOG_WARNING2("--> dummyCallback: qId (%d), callbackId (%d)\n",qId,cbId); -    } -    dispatchQInfo[qId].dummyCallbackCount++; - -#ifndef NDEBUG -    /* Update statistcs */ -    dispatcherStats.queueStats[qId].intNoCallbackCnt++; -#endif -} -void -ixQMgrLLPShow (int resetStats) -{ -#ifndef NDEBUG -    UINT8 i = 0; -    UINT32 intEnableRegVal = 0; - -    printf ("Livelock statistics are printed on the fly.\n"); -    printf ("qId Type     EnableCnt DisableCnt IntEnableState Callbacks\n"); -    printf ("=== ======== ========= ========== ============== =========\n"); - -    for (i=0; i<= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) -    { -        if (ixQMgrQTypes[i] != IX_QMGR_TYPE_REALTIME_OTHER) -        { -            printf (" %2d ", i); - -            if (ixQMgrQTypes[i] == IX_QMGR_TYPE_REALTIME_SPORADIC) -            { -                printf ("Sporadic"); -            } -            else -            { -                printf ("Periodic"); -            } - -            -            ixQMgrAqmIfQInterruptEnableRegRead (IX_QMGR_QUELOW_GROUP,  -                                                    &intEnableRegVal); -            	 - -	    intEnableRegVal &= dispatchQInfo[i].intRegCheckMask; -            intEnableRegVal = intEnableRegVal >> i; - -            printf (" %10d %10d %10d %10d\n", -                    dispatcherStats.queueStats[i].enableCount, -                    dispatcherStats.queueStats[i].disableCount, -                    intEnableRegVal, -                    dispatcherStats.queueStats[i].callbackCnt); - -            if (resetStats) -            { -                dispatcherStats.queueStats[i].enableCount = -                dispatcherStats.queueStats[i].disableCount =  -                dispatcherStats.queueStats[i].callbackCnt = 0; -            } -        } -    } -#else -    IX_QMGR_LOG0("Livelock Prevention statistics are only collected in debug mode\n"); -#endif -} - -void -ixQMgrPeriodicDone (void) -{ -    UINT32 i = 0; -    UINT32 ixQMgrLockKey = 0; - -    /*  -     * for the lower queues -     */ -    for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) -    { -        /* -         * check for sporadics  -         */ -        if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i]) -        { -             /*  -              * enable any sporadics  -              */ -             ixQMgrLockKey = ixOsalIrqLock(); -             ixQMgrAqmIfQInterruptEnable(i); -             ixOsalIrqUnlock(ixQMgrLockKey); -#ifndef NDEBUG -             /*  -              * Update statistics  -              */ -             dispatcherStats.queueStats[i].enableCount++; -             dispatcherStats.queueStats[i].notificationEnabled = true; -#endif -        } -    } -} -IX_STATUS -ixQMgrCallbackTypeSet (IxQMgrQId qId,  -                       IxQMgrType type) -{ -    UINT32 ixQMgrLockKey = 0; -    IxQMgrType ixQMgrOldType =0; - -#ifndef NDEBUG -    if (!ixQMgrQIsConfigured(qId)) -    { -        return IX_QMGR_Q_NOT_CONFIGURED; -    } -    if (qId >= IX_QMGR_MIN_QUEUPP_QID) -    { -        return IX_QMGR_PARAMETER_ERROR; -    } -    if(!IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type)) -    { -        return IX_QMGR_PARAMETER_ERROR; -    } -#endif - -    ixQMgrOldType = ixQMgrQTypes[qId]; -    ixQMgrQTypes[qId] = type; - -    /* -     * check if Q has been changed from type SPORADIC -     */ -    if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrOldType) -    { -       /*  -        * previously Q was a SPORADIC, this means that LLP -        * might have had it disabled. enable it now. -        */ -       ixQMgrLockKey = ixOsalIrqLock(); -       ixQMgrAqmIfQInterruptEnable(qId); -       ixOsalIrqUnlock(ixQMgrLockKey); - -#ifndef NDEBUG -       /*  -        * Update statistics  -        */ -       dispatcherStats.queueStats[qId].enableCount++; -#endif -    } - -    return IX_SUCCESS; -} - -IX_STATUS -ixQMgrCallbackTypeGet (IxQMgrQId qId,  -                       IxQMgrType *type) -{ -#ifndef NDEBUG -    if (!ixQMgrQIsConfigured(qId)) -    { -        return IX_QMGR_Q_NOT_CONFIGURED; -    } -    if (qId >= IX_QMGR_MIN_QUEUPP_QID) -    { -        return IX_QMGR_PARAMETER_ERROR; -    } -    if(type == NULL) -    { -         return IX_QMGR_PARAMETER_ERROR; -    } -#endif - -    *type = ixQMgrQTypes[qId]; -    return IX_SUCCESS; -}  |