📄 ixethaccdataplane.c
字号:
/** * @brief rxFree low event handler * */void ixEthRxFreeQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId){ IxEthAccPortId portId = (IxEthAccPortId) callbackId; int lockVal; UINT32 maxQWritesToPerform = IX_ETH_ACC_MAX_RX_FREE_BUFFERS_LOAD; IX_STATUS qStatus = IX_SUCCESS; /* * We have reached a low threshold on one of the Rx Free Qs */ /*note that due to the fact that we are working off an Empty threshold, this callback need only write a single entry to the Rx Free queue in order to re-arm the notification */ RX_STATS_INC(portId,rxFreeLowCallback); /* * Get buffers from approprite S/W Rx freeBufferList Q. */#ifndef NDEBUG if (!IX_ETH_ACC_IS_PORT_VALID(portId)) { ixEthAccDataStats.unexpectedError++; IX_ETH_ACC_FATAL_LOG( "ixEthRxFreeQMCallback:Error: Invalid Port 0x%08X\n", portId, 0, 0, 0, 0, 0); return; }#endif IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); if (IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. ixEthAccRxData.freeBufferList)) { /* * Turn off Q callback notification for Q in Question. */ qStatus = ixQMgrNotificationDisable( IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId)); IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); if (qStatus != IX_SUCCESS) { RX_INC(portId,rxUnexpectedError); IX_ETH_ACC_FATAL_LOG( "ixEthRxFreeQMCallback:Error: unexpected QM status 0x%08X\n", qStatus, 0, 0, 0, 0, 0); return; } } else { IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); /* * Load the H/W Q with buffers from the s/w Q. */ do { /* * Consume Q entries. - Note Q contains Physical addresss, * and have already been flushed to memory, * And endianess converted if required. */ if (ixEthAccRxFreeFromSwQ(portId) != IX_SUCCESS) { /* * No more entries in s/w Q. * Turn off Q callback indication */ IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); if (IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. ixEthAccRxData.freeBufferList)) { qStatus = ixQMgrNotificationDisable( IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId)); } IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); break; } } while (--maxQWritesToPerform); }}/** * @fn Tx queue low event handler * */voidixEthTxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId){ IxEthAccPortId portId = (IxEthAccPortId) callbackId; int lockVal; UINT32 maxQWritesToPerform = IX_ETH_ACC_MAX_TX_FRAME_TX_CONSUME_PER_CALLBACK; IX_STATUS qStatus = IX_SUCCESS; IxEthAccTxPriority highestPriority; /* * We have reached a low threshold on the Tx Q, and are being asked to * supply a buffer for transmission from our S/W TX queues */ TX_STATS_INC(portId,txLowThreshCallback); /* * Get buffers from approprite Q. */#ifndef NDEBUG if (!IX_ETH_ACC_IS_PORT_VALID(portId)) { ixEthAccDataStats.unexpectedError++; IX_ETH_ACC_FATAL_LOG( "ixEthTxFrameQMCallback:Error: Invalid Port 0x%08X\n", portId, 0, 0, 0, 0, 0); return; }#endif do { /* * Consume Q entries. - Note Q contains Physical addresss, * and have already been flushed to memory, * and endianess already sone if required. */ IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority) == IX_ETH_ACC_FAIL) { /* * No more entries in s/w Q. * Turn off Q callback indication */ qStatus = ixQMgrNotificationDisable( IX_ETH_ACC_PORT_TO_TX_Q_ID(portId)); IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); if (qStatus != IX_SUCCESS) { ixEthAccDataStats.unexpectedError++; IX_ETH_ACC_FATAL_LOG( "ixEthTxFrameQMCallback:Error: unexpected QM status 0x%08X\n", qStatus, 0, 0, 0, 0, 0); } return; } else { IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); if (ixEthAccTxFromSwQ(portId,highestPriority)!=IX_SUCCESS) { /* nothing left in the sw queue or the hw queues are * full. There is no point to continue to drain the * sw queues */ return; } } } while (--maxQWritesToPerform);}/** * @brief TxDone event handler * * Design note : while processing the entry X, entry X+1 is preloaded * into memory to reduce the number of stall cycles * */voidixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId){ IX_OSAL_MBUF *mbufPtr; UINT32 qEntry; UINT32 *qEntryPtr; UINT32 txDoneQReadStatus; UINT32 portId; UINT32 npeId; /* * Design note : entries are read in a static buffer, This buffer contains * an extra entyry (which is zeroed by the compiler), so the loop will * always terminate on a null entry, whatever the result of Burst read is. */ static UINT32 txDoneQEntry[IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK + 1]; /* * Indication that Tx frames have been transmitted from the NPE. */ IX_ETH_ACC_STATS_INC(ixEthAccDataStats.txDoneCallbackCounter); do{ qEntryPtr = txDoneQEntry; txDoneQReadStatus = ixQMgrQBurstRead(IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK, qEntryPtr);#ifndef NDEBUG if (txDoneQReadStatus != IX_QMGR_Q_UNDERFLOW && (txDoneQReadStatus != IX_SUCCESS)) { /*major error*/ ixEthAccDataStats.unexpectedError++; IX_ETH_ACC_FATAL_LOG( "ixEthTxFrameDoneQMCallback:Error: %u\n", (UINT32)txDoneQReadStatus, 0, 0, 0, 0, 0); return; }#endif qEntry = *qEntryPtr; while(qEntry != 0) { mbufPtr = ixEthAccEntryFromQConvert(qEntry, IX_ETHNPE_QM_Q_TXENET_ADDR_MASK);#ifndef NDEBUG if (mbufPtr == NULL) { ixEthAccDataStats.unexpectedError++; IX_ETH_ACC_FATAL_LOG( "ixEthTxFrameDoneQMCallback:Error: Null Mbuf Ptr\n", 0, 0, 0, 0, 0, 0); return; }#endif /* endianness conversions and stats updates */ ixEthAccMbufFromTxQ(mbufPtr); /* * Get NPE id from message, then convert to portId. */ npeId = ((IX_ETHNPE_QM_Q_TXENETDONE_NPEID_MASK & qEntry) >> IX_ETHNPE_QM_Q_FIELD_NPEID_R); portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);#ifndef NDEBUG /* Prudent to at least check the port is within range */ if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) { ixEthAccDataStats.unexpectedError++; IX_ETH_ACC_FATAL_LOG( "ixEthTxFrameDoneQMCallback: Illegal port: %u\n", (UINT32)portId, 0, 0, 0, 0, 0); return; }#endif TX_STATS_INC(portId,txDoneClientCallback); /* * Call user level callback. */ ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn( ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag, mbufPtr); /* move to next queue entry */ qEntry = *(++qEntryPtr); } } while( txDoneQReadStatus == IX_SUCCESS );}IX_ETH_ACC_PUBLICvoid ixEthAccDataPlaneShow(void){ UINT32 numTx0Entries; UINT32 numTx1Entries; UINT32 numTxDoneEntries; UINT32 numRxEntries; UINT32 numRxFree0Entries; UINT32 numRxFree1Entries; UINT32 portId;#ifdef __ixp46X UINT32 numTx2Entries; UINT32 numRxFree2Entries;#endif#ifndef NDEBUG UINT32 priority; UINT32 numBuffersInRx=0; UINT32 numBuffersInTx=0; UINT32 numBuffersInSwQ=0; UINT32 totalBuffers=0; UINT32 rxFreeCallbackCounter = 0; UINT32 txCallbackCounter = 0;#endif UINT32 key; /* snapshot of stats */ IxEthAccTxDataStats tx[IX_ETH_ACC_NUMBER_OF_PORTS]; IxEthAccRxDataStats rx[IX_ETH_ACC_NUMBER_OF_PORTS]; IxEthAccDataPlaneStats stats; if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) { return; } /* get a reliable snapshot */ key = ixOsalIrqLock(); numTx0Entries = 0; ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET0_Q, &numTx0Entries); numTx1Entries = 0; ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET1_Q, &numTx1Entries); numTxDoneEntries = 0; ixQMgrQNumEntriesGet( IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, &numTxDoneEntries); numRxEntries = 0; ixEthAccQMgrRxQEntryGet(&numRxEntries); numRxFree0Entries = 0; ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q, &numRxFree0Entries); numRxFree1Entries = 0; ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q, &numRxFree1Entries);#ifdef __ixp46X numTx2Entries = 0; ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET2_Q, &numTx2Entries); numRxFree2Entries = 0; ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q, &numRxFree2Entries);#endif for(portId=IX_ETH_PORT_1; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) { memcpy(&tx[portId], &ixEthAccPortData[portId].ixEthAccTxData.stats, sizeof(tx[portId])); memcpy(&rx[portId], &ixEthAccPortData[portId].ixEthAccRxData.stats, sizeof(rx[portId])); } memcpy(&stats, &ixEthAccDataStats, sizeof(stats)); ixOsalIrqUnlock(key);#ifdef NDEBUG printf("Detailed statistics collection not supported in this load\n");#endif /* print snapshot */ for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) { /* If not IXP42X A0 stepping, proceed to check for existence of coprocessors */ if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 != (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK)) || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ())) { if ((IX_ETH_PORT_1 == portId) && (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == IX_FEATURE_CTRL_COMPONENT_DISABLED)) { continue ; } if ((IX_ETH_PORT_2 == portId) && (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == IX_FEATURE_CTRL_COMPONENT_DISABLED)) { continue ; } if ((IX_ETH_PORT_3 == portId) && (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) == IX_FEATURE_CTRL_COMPONENT_DISABLED)) { continue ; } } printf("PORT %u --------------------------------\n", portId);#ifndef NDEBUG printf("Tx Done Frames : %u\n", tx[portId].txDoneClientCallback + tx[portId].txDoneSwQDuringDisable + tx[portId].txDoneDuringDisable); printf("Tx Frames : %u\n", tx[portId].txQOK + tx[portId].txQDelayed); printf("Tx H/W Q Added OK : %u\n", tx[portId].txQOK); printf("Tx H/W Q Delayed : %u\n", tx[portId].txQDelayed); printf("Tx From S/W Q Added OK : %u\n", tx[portId].txFromSwQOK); printf("Tx From S/W Q Delayed : %u\n", tx[portId].txFromSwQDelayed); printf("Tx Overflow : %u\n", tx[portId].txOverflow); printf("Tx Mutual Lock : %u\n", tx[portId].txLock); printf("Tx Late Ntf Enabled : %u\n", tx[portId].txLateNotificationEnabled); printf("Tx Low Thresh CB : %u\n", tx[portId].txLowThreshCallback); printf("Tx Done from H/W Q (Disable) : %u\n", tx[portId].txDoneDuringDisable); printf("Tx Done from S/W Q (Disable) : %u\n", tx[portId].txDoneSwQDuringDisable); for (priority = IX_ETH_ACC_TX_PRIORITY_0; priority <= IX_ETH_ACC_TX_PRIORITY_7; priority++) { if (tx[portId].txPriority[priority]) { printf("Tx Priority %u : %u\n", priority, tx[portId].txPriority[priority]); } }#endif printf("Tx unexpected errors : %u (should be 0)\n", tx[portId].txUnexpectedError);#ifndef NDEBUG printf("Rx Frames : %u\n", rx[portId].rxFrameClientCallback + rx[portId].rxSwQDuringDisable+ rx[portId].rxDuringDisable); printf("Rx Free Replenish : %u\n", rx[portId].rxFreeRepOK + rx[portId].rxFreeRepDelayed); printf("Rx Free H/W Q Added OK : %u\n", rx[portId].rxFreeRepOK); printf("Rx Free H/W Q Delayed : %u\n", rx[portId].rxFreeRepDelayed); printf("Rx Free From S/W Q Added OK : %u\n", rx[portId].rxFreeRepFromSwQOK); printf("Rx Free From S/W Q Delayed : %u\n", rx[portId].rxFreeRepFromSwQDelayed); printf("Rx Free Overflow : %u\n", rx[portId].rxFreeOverflow); printf("Rx Free Mutual Lock : %u\n", rx[portId].rxFreeLock); printf("Rx Free Late Ntf Enabled : %u\n", rx[portId].rxFreeLateNotificationEnabled); printf("Rx Free Low CB : %u\n", rx[portId].rxFreeLowCallback); printf("Rx From H/W Q (Disable) : %u\n", rx[portId].rxDuringDisable); printf("Rx From S/W Q (Disable) : %u\n", rx[portId].rxSwQDuringDisable); printf("Rx unlearned Mac Address : %u\n", rx[portId].rxUnlearnedMacAddress); printf("Rx Filtered (Rx => RxFree) : %u\n", rx[portId].rxFiltered); for (priority = IX_ETH_ACC_TX_PRIORITY_0; priority <= IX_ETH_ACC_TX_PRIORITY_7; priority++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -