void ixQMgrShow (void) { IxQMgrQCfgStats *qCfgStats = NULL; IxQMgrDispatcherStats *dispatcherStats = NULL; int i; UINT32 lowIntRegRead, upIntRegRead; qCfgStats = ixQMgrQCfgStatsGet (); dispatcherStats = ixQMgrDispatcherStatsGet (); ixQMgrAqmIfQInterruptRegRead (IX_QMGR_QUELOW_GROUP, &lowIntRegRead); ixQMgrAqmIfQInterruptRegRead (IX_QMGR_QUEUPP_GROUP, &upIntRegRead); printf("Generic Stats........\n"); printf("=====================\n"); printf("Loop Run Count..........%u\n",dispatcherStats->loopRunCnt); printf("Watermark set count.....%d\n", qCfgStats->wmSetCnt); printf("===========================================\n"); printf("On the fly Interrupt Register Stats........\n"); printf("===========================================\n"); printf("Lower Interrupt Register............0x%08x\n",lowIntRegRead); printf("Upper Interrupt Register............0x%08x\n",upIntRegRead); printf("==============================================\n"); printf("Queue Specific Stats........\n"); printf("============================\n"); for (i=0; i<IX_QMGR_MAX_NUM_QUEUES; i++) { if (ixQMgrQIsConfigured(i)) { ixQMgrQShow(i); } } printf("============================\n"); }
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 (); } }
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 }