ixethaccdataplane.c
来自「有关ARM开发板上的IXP400网络驱动程序的源码以。」· C语言 代码 · 共 2,320 行 · 第 1/5 页
C
2,320 行
"ixEthAccRxPortFreeReplenish:Error: %u\n", qStatus, 0, 0, 0, 0, 0); } } } else { RX_INC(portId,rxUnexpectedError); IX_ETH_ACC_FATAL_LOG( "ixEthAccRxPortFreeReplenish:Error: qStatus = %u\n", (UINT32)qStatus, 0, 0, 0, 0, 0); return(IX_ETH_ACC_FAIL); } return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccTxSchedulingDisciplineSetPriv(IxEthAccPortId portId, IxEthAccSchedulerDiscipline sched){ if (!IX_ETH_ACC_IS_PORT_VALID(portId)) { return (IX_ETH_ACC_INVALID_PORT); } if (!IX_ETH_IS_PORT_INITIALIZED(portId)) { return (IX_ETH_ACC_PORT_UNINITIALIZED); } if (sched != FIFO_PRIORITY && sched != FIFO_NO_PRIORITY) { return (IX_ETH_ACC_INVALID_ARG); } ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = sched; return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccRxSchedulingDisciplineSetPriv(IxEthAccSchedulerDiscipline sched){ int port; /* cannot change the scheduling discipline while any port is active */ for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++) { if (ixEthAccMacState[port].portDisableState == ACTIVE) { return IX_ETH_ACC_FAIL; } } switch(sched) { case FIFO_PRIORITY: /* priority scheduling discipline not supported on IXP42X A0 HW */ if( (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X == ixFeatureCtrlDeviceRead ()) && (IX_FEATURE_CTRL_SILICON_TYPE_A0 == (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))) { return (IX_ETH_ACC_FAIL); } if(ixEthAccDataInfo.rxQMCbTypeSet == NORMAL) { ixEthAccQMgrRxCallbacksRegister( (IxQMgrCallback)ixEthRxPriorityPoll, IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK); } else if(ixEthAccDataInfo.rxQMCbTypeSet == MULTIBUFFER) { ixEthAccQMgrRxCallbacksRegister( (IxQMgrCallback)ixEthRxMultiBufferPriorityPoll, IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK); } /* enable sticky interrupts */ ixQMgrStickyInterruptRegEnable(); break; case FIFO_NO_PRIORITY: if(ixEthAccDataInfo.rxQMCbTypeSet == NORMAL) { ixEthAccQMgrRxCallbacksRegister(ixEthRxFrameQMCallback,0); } else if(ixEthAccDataInfo.rxQMCbTypeSet == MULTIBUFFER) { ixEthAccQMgrRxCallbacksRegister(ixEthRxMultiBufferQMCallback,0); } break; default: return (IX_ETH_ACC_INVALID_ARG); } ixEthAccDataInfo.schDiscipline = sched; return (IX_ETH_ACC_SUCCESS);}/** * @fn ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) * * @brief process incoming frame : * * @param @ref IxQMgrCallback IxQMgrMultiBufferCallback * * @return none * * @internal * */IX_ETH_ACC_PRIVATE BOOL ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr){ UINT32 flags; IxEthDBStatus result;#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( "ixEthRxFrameProcess: Illegal port: %u\n", (UINT32)portId, 0, 0, 0, 0, 0); return FALSE; }#endif /* convert fields from mbuf header */ ixEthAccMbufFromRxQ(mbufPtr); /* check about any special processing for this frame */ flags = IX_ETHACC_NE_FLAGS(mbufPtr); if ((flags & (IX_ETHACC_NE_FILTERMASK | IX_ETHACC_NE_NEWSRCMASK)) == 0) { /* "best case" scenario : nothing special to do for this frame */ return TRUE; } /* if a new source MAC address is detected by the NPE, * update IxEthDB with the portId and the MAC address. */ if ((flags & IX_ETHACC_NE_NEWSRCMASK & ixEthAccNewSrcMask) != 0) { result = ixEthDBFilteringDynamicEntryProvision(portId, (IxEthDBMacAddr *) IX_ETHACC_NE_SOURCEMAC(mbufPtr)); if (result != IX_ETH_DB_SUCCESS && result != IX_ETH_DB_FEATURE_UNAVAILABLE) { if ((ixEthAccMacState[portId].portDisableState == ACTIVE) && (result != IX_ETH_DB_BUSY)) { RX_STATS_INC(portId, rxUnexpectedError); IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to add source MAC to the Learning/Filtering database\n", 0, 0, 0, 0, 0, 0); } else { /* we expect this to fail during PortDisable, as EthDB is disabled for * that port and will refuse to learn new addresses */ } } else { RX_STATS_INC(portId, rxUnlearnedMacAddress); } } /* check if this frame should have been filtered * by the NPE and take the appropriate action */ if (((flags & IX_ETHACC_NE_FILTERMASK) != 0) && (ixEthAccMacState[portId].portDisableState == ACTIVE)) { /* If the mbuf was allocated with a small data size, or the current data pointer is not * within the allocated data area, then the buffer is non-standard and has to be * replenished with the minimum size only */ if( (IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN) || ((UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) > IX_OSAL_MBUF_MDATA(mbufPtr)) || ((UINT8 *)(IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) + IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr)) < IX_OSAL_MBUF_MDATA(mbufPtr)) ) { /* set to minimum length */ IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) = IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN; } else { /* restore original length */ IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) = ( IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) - (IX_OSAL_MBUF_MDATA(mbufPtr) - (UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr)) ); } /* replenish from here */ if (ixEthAccPortRxFreeReplenish(portId, mbufPtr) != IX_ETH_ACC_SUCCESS) { IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to replenish with filtered frame\ on port %d\n", portId, 0, 0, 0, 0, 0); } RX_STATS_INC(portId, rxFiltered); /* indicate that frame should not be subjected to further processing */ return FALSE; } return TRUE;}/** * @fn ixEthRxPriorityPoll * * @brief RX routine to get limited entries from priority queues * * Routine may be called by user, or used as RX QM callback. * Receive queues are processed in priority order. * * @param reserved : placeholder for QM callback usage, ignored * maxQEntries : maximum number of q entries to process * * @return : number of frames processed * * @internal * * Design notes : * While processing the entry X, entry X+1 is preloaded * into memory to reduce the number of stall cycles * */UINT32 ixEthRxPriorityPoll(UINT32 reserved, UINT32 maxQEntries){ IX_OSAL_MBUF *mbufPtr; IX_OSAL_MBUF *nextMbufPtr; IxQMgrQId qId; UINT32 qIndex; UINT32 qEntry; UINT32 nextQEntry; UINT32 *qEntryPtr; UINT32 portId; UINT32 destPortId; UINT32 rxQReadStatus; UINT32 qEntriesProcessed = 0; /* * Design note : entries are read in a buffer, This buffer contains * an extra zeroed entry so the loop will * always terminate on a null entry, whatever the result of Burst read is. */ UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK + 1]; /* * Indication of the number of times the callback is used. */ IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter); for(qId = ixEthAccDataInfo.rxQueues[qIndex = 0]; qId < IX_QMGR_MAX_NUM_QUEUES && qEntriesProcessed < maxQEntries; qId = ixEthAccDataInfo.rxQueues[++qIndex]) { UINT32 qReadCount = maxQEntries - qEntriesProcessed; /* * Indication of the number of times the queue is drained */ IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead); /* ensure the last entry of the array contains a zeroed value */ qEntryPtr = rxQEntry; qEntryPtr[qReadCount] = 0; rxQReadStatus = ixQMgrQBurstRead(qId, qReadCount, qEntryPtr);#ifndef NDEBUG if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW) && (rxQReadStatus != IX_SUCCESS)) { ixEthAccDataStats.unexpectedError++; /*major error*/ IX_ETH_ACC_FATAL_LOG( "ixEthRxPriorityPoll:Error: %u\n", (UINT32)rxQReadStatus, 0, 0, 0, 0, 0); return qEntriesProcessed; }#endif /* convert and preload the next entry * (the conversion function takes care about null pointers which * are used to mark the end of the loop) */ nextQEntry = *qEntryPtr; nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); while(nextQEntry != 0) { /* get the next entry */ qEntry = nextQEntry; mbufPtr = nextMbufPtr;#ifndef NDEBUG if (mbufPtr == NULL) { ixEthAccDataStats.unexpectedError++; IX_ETH_ACC_FATAL_LOG( "ixEthRxPriorityPoll: Null Mbuf Ptr\n", 0, 0, 0, 0, 0, 0); return qEntriesProcessed; }#endif /* convert the next entry * (the conversion function takes care about null pointers which * are used to mark the end of the loop) */ nextQEntry = *(++qEntryPtr); nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); /* * Get Port ID from message. */ portId = IX_ETHNPE_NODE_AND_PORT_TO_PHYSICAL_ID(IX_ETHNPE_QM_Q_RXENET_NPEID_VAL(qEntry),IX_ETHNPE_QM_Q_PID_VAL(qEntry)); /* process frame, check the return code and skip the remaining of * the loop if the frame is to be filtered out */ if (ixEthRxFrameProcess(portId, mbufPtr)) { /* destination portId for this packet */ destPortId = IX_ETHACC_NE_DESTPORTID(mbufPtr); if (destPortId != IX_ETH_DB_UNKNOWN_PORT) { destPortId = IX_ETHNPE_LOGICAL_ID_TO_PHYSICAL_ID(destPortId); } /* * increment priority stats */ RX_STATS_INC(portId,rxPriority[IX_ETHACC_NE_QOS(mbufPtr)]); /* * increment callback count stats */ RX_STATS_INC(portId,rxFrameClientCallback); /* * Call user level callback. */ ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn( ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag, mbufPtr, destPortId); /*increment total number of entries processed*/ qEntriesProcessed++; } } } return qEntriesProcessed;}/** * @fn ixEthRxMultiBufferPriorityPoll * * @brief RX routine to get limited entries from priority queues * * Routine may be called by user, or used as RX QM callback. * Receive queues are processed in priority order. * Buffers are passed as an array to the user callback * * @param reserved : placeholder for QM callback usage, ignored * maxQEntries : maximum number of q entries to process * * @return : number of frames processed * * @internal * * Design notes : * While processing the entry X, entry X+1 is preloaded * into memory to reduce the number of stall cycles * */UINT32 ixEthRxMultiBufferPriorityPoll(UINT32 reserved, UINT32 maxQEntries){ IX_OSAL_MBUF *mbufPtr; IX_OSAL_MBUF *nextMbufPtr; IxQMgrQId qId; UINT32 qIndex; UINT32 qEntry; UINT32 nextQEntry; UINT32 *qEntryPtr; UINT32 portId; UINT32 rxQReadStatus; UINT32 qEntriesProcessed = 0; /* * Design note : entries are read in a buffer, This buffer contains * an extra zeroed entry so the loop will * always terminate on a null entry, whatever the result of Burst read is. */ UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK + 1]; static IX_OSAL_MBUF *rxMbufPortArray[IX_ETH_ACC_NUMBER_OF_PORTS][IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK + 1]; IX_OSAL_MBUF **rxMbufPtr[IX_ETH_ACC_NUMBER_OF_PORTS]; for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) { rxMbufPtr[portId] = rxMbufPortArray[portId]; } /* * Indication of the number of times the callback is used. */ IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter); for(qId = ixEthAccDataInfo.rxQueues[qIndex = 0]; qId < IX_QMGR_MAX_NUM_QUEUES && qEntriesProcessed < maxQEntries; qId = ixEthAccDataInfo.rxQueues[++qIndex]) { UINT32 qReadCount = maxQEntries - qEntriesProcessed; /* * Indication of the number of times the queue is drained */ IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead); /* ensure the last entry of the array contains a zeroed value */ qEntryPtr = rxQEntry; qEntryPtr[qReadCount] = 0; rxQReadStatus = ixQMgrQBurstRead(qId, qReadCount, qEntryPtr);#ifndef NDEBUG if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW) && (rxQReadStatus != IX_SUCCESS)) { ixEthAccDataStats.unexpectedError++; /*major error*/ IX_ETH_ACC_FATAL_LOG( "ixEthRxMultiBufferPriorityPoll:Error: %u\n", (UINT32)rxQReadStatus, 0, 0, 0, 0, 0); return qEntriesProcessed; }#endif /* convert and preload the next entry * (the conversion function takes care about null pointers which * are used to mark the end of the loop) */ nextQEntry = *qEntryPtr; nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); while(nextQEntry != 0) { /* get the next entry */ qEntry = nextQEntry; mbufPtr = nextMbufPtr;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?