📄 ixethaccend.c
字号:
DO_EVENT(IXE_EVT_RCV_REPLENISH_LOOP_BOTTOM); }}/********************************************************************************* Return buffers from the slow vxWorks pool to the Intel Ethernet Engine */LOCAL void ixEthAccEndReplenishSlow(END_DEVICE *pDrvCtrl /* interrupting device */){ M_BLK_ID pMblk; UINT32 rxBufsActive; /* replenish from buffers from fast replenish queue */ ixEthAccEndReplenishFast(pDrvCtrl); /* replenish from buffers from vxWorks pool */ rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; while (rxBufsActive < pDrvCtrl->rxBufsAlloc) { if ((pMblk = netTupleGet(pDrvCtrl->end.pNetPool, IX_ETHACC_RX_MBUF_MIN_SIZE + ALIGN_MLEN, M_DONTWAIT, MT_HEADER, FALSE )) == NULL) {#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tupleGetFail++;#endif /* Clear the error */ if( errnoGet () == S_netBufLib_NO_POOL_MEMORY ) errnoSet(0); break; } IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "ixEthAccEndRepl slow: replenish mbuf %8.8x\n", (UINT32)pMblk, 2, 3, 4, 5, 6);#ifdef IXE_CACHED_RX_BUFFERS_ENABLE DO_EVENT(IXE_EVT_RCV_REPLENISH_LOOP_CACHEOPS); IXP425_END_CACHE_INVALIDATE(pMblk->m_data, IX_ETHACC_RX_MBUF_MIN_SIZE + ALIGN_MLEN);#endif /* Force Quad align for Ip packet on cache line boundary */ pMblk->m_data = ALIGN_MDATA(pMblk->m_data); pMblk->m_len = IX_ETHACC_RX_MBUF_MIN_SIZE; pMblk->mBlkPktHdr.len = IX_ETHACC_RX_MBUF_MIN_SIZE; pMblk->m_next = NULL;#ifdef IXP_DRV_DEBUG_MBUFS elogHook(pMblk, 1, pDrvCtrl->rxBufsRecv,pDrvCtrl->rxBufsReplenish);#endif if (ixEthAccEndReplenish(pDrvCtrl, pMblk) != OK) { IXP_DRV_LOG(IXP_DRV_DEBUG_ERROR,"Error:replenish Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); return; } rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; DO_EVENT(IXE_EVT_RCV_REPLENISH_LOOP_BOTTOM); }}/********************************************************************************* ixEthAccEndStart - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR**/LOCAL STATUS ixEthAccEndStart(END_OBJ * pDrv /* device ID */){ IxEthAccStatus result; END_DEVICE *pDrvCtrl = (END_DEVICE *)pDrv; /* * Register Tx Done Callback */ IXP_DRV_LOG(IXP_DRV_DEBUG_LOAD,"Registering IxEthAcc Callbacks Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); result = ixEthAccPortTxDoneCallbackRegister( pDrvCtrl->unit, ixEthAccEndTxDoneCallback, (UINT32) pDrvCtrl); if ( result != IX_ETH_ACC_SUCCESS) { IXP_DRV_LOG(IXP_DRV_DEBUG_LOAD,"Error:Registering IxEthAcc Tx Callbacks Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); return(ERROR); } /* * Now register Rx Done Callback */ result = ixEthAccPortRxCallbackRegister( pDrvCtrl->unit, ixEthAccEndRxCallback, (UINT32) pDrvCtrl); if ( result != IX_ETH_ACC_SUCCESS) { IXP_DRV_LOG(IXP_DRV_DEBUG_LOAD,"Error:Registering IxEthAcc Rx Callbacks Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); return(ERROR); } /* reset the counters */#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tnetReceived = 0; /* packets processed to ipastack */ pDrvCtrl->tnetDrop = 0; /* packets dropped by tnet task */ pDrvCtrl->tnetJobAddFail = 0; /* netjobadd invoke */ pDrvCtrl->tnetFastReplenish = 0; /* successful fast replenish */ pDrvCtrl->tupleGetFail = 0; /* nettupleGet failures */ pDrvCtrl->tupleTxAlloc = 0; /* mbufs allocated for TX */ pDrvCtrl->errs = 0; /* error counter */#endif IXP_DRV_DEBUG_MBUFS IXP_DRV_LOG(IXP_DRV_DEBUG_LOAD,"Replenish IxEthAcc Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); /* replenish */ ixEthAccEndReplenishSlow(pDrvCtrl); IXP_DRV_LOG(IXP_DRV_DEBUG_LOAD,"Enable IxEthAcc Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); /* enable hw and starts the rx traffic */ result = ixdp425EthLibStart(pDrvCtrl->unit); if ( result != IX_SUCCESS) { IXP_DRV_LOG(IXP_DRV_DEBUG_LOAD, "Error:Enabling IxEthAcc Port[%d], result=%d\n", pDrvCtrl->unit, result,3,4,5,6); return(ERROR); } IXP_DRV_LOG(IXP_DRV_DEBUG_LOAD,"Flags set IxEthAcc Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING)); return(OK);}/********************************************************************************* ixEthAccEndPacketGet - get next received message** Get next received message. Returns NULL if none are* ready.** RETURNS: ptr to next packet, or NULL if none ready.*/char* ixEthAccEndPacketGet(END_DEVICE *pDrvCtrl /* device structure */){ /* Not supported by this device */ return(char *)NULL;}#ifdef IXETHACCEND_CSR_1_1/**************************************************************************** * vxWorks patch : recover buffers from a pool, which are alder than * the indicated time-to-live (ttl) value * This will be used to recover fragmented packets which will never * be released because the driver is dropping the rx traffic */LOCAL void ixEthAccEnd_ip_ttl_mbuf_release(int maxTtl, NET_POOL_ID poolId){ extern int ipfragttl; extern struct ipq ipq; struct ipq *fp; int s; s = splnet(); fp = ipq.next; if (fp) { while (fp != &ipq) { fp = fp->next; /* release entries which are older than the ttl * and which first mbuf belongs to the mbuf pool passed * as a parameter, and which are already waiting for * reassembly (because chaning already started). * Other entries (which don't need reassembly) are not affected */ if (fp->prev->ipq_ttl > ipfragttl || fp->prev->ipq_ttl + maxTtl < IP_FRAG_TTL_DFLT) { if (fp->prev->pMbufPkt->m_nextpkt != NULL && fp->prev->pMbufPkt->pClBlk->pNetPool == poolId) { ip_freef(fp->prev); } } } } splx(s);}/**************************************************************************** * update the stack time-to-live (ttl) value, depending * on the actual load: if many mbufs are already used, more mbufs should not * stay for a while inside the vxWorks stack. */#define IP_FRAG_TTL_MIN 4LOCAL void ixEthAccEnd_ip_ttl_update(END_DEVICE *pDrvCtrl){ /* degrade the ttl value depending on the current number * of available mbufs * the result value will be in the following range * IP_FRAG_TTL_MIN <= ipFragTtl <= IP_FRAG_TTL_DFLT */ UINT32 rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; pDrvCtrl->ipFragTtl = IP_FRAG_TTL_MIN + ((IP_FRAG_TTL_DFLT-IP_FRAG_TTL_MIN) * rxBufsActive) / pDrvCtrl->rxBufsAlloc; { /* update the global frag ttl value with the worst-case * interface value. There is a side effect : * it affect all interfaces. */ extern int ipfragttl; END_DEVICE *pOtherDrvCtrl = ixEthAccpDrvCtrl[1 - pDrvCtrl->unit]; if (pOtherDrvCtrl && pOtherDrvCtrl->ipFragTtl <= pDrvCtrl->ipFragTtl) { ipfragttl = pOtherDrvCtrl->ipFragTtl; } else { ipfragttl = pDrvCtrl->ipFragTtl; } }}#endif/********************************************************************************* ixEthAccEndHandleRcvInt - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** RETURNS: N/A.*/LOCAL void ixEthAccEndHandleRcvInt(END_DEVICE *pDrvCtrl /* interrupting device */){ M_BLK_ID pMblk; UINT32 rxBufsActive; pDrvCtrl->netJobAddOut++; DO_EVENT(IXE_EVT_RCV_HANDLE_ENTRY); while (1) { DO_EVENT(IXE_EVT_RCV_RECEIVE_LOOP_TOP); if (pDrvCtrl->recRd == pDrvCtrl->recWr) { /* queue empty */ break; } DO_EVENT(IXE_EVT_RCV_HANDLE_ENTRY); /* queue not empty, get a mbuf */ pMblk = pDrvCtrl->recBufList[pDrvCtrl->recRd++ & RECBUF_MASK]; IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "ixEthAccEndRcvInt: received mbuf %8.8x\n", (UINT32)pMblk, 2, 3, 4, 5, 6); DO_EVENT(IXE_EVT_RCV_RECEIVE_LOOP_CACHEOPS);#ifdef IXE_CACHED_RX_BUFFERS_ENABLE /* * We need only invalidate up to the contents of the use * of this buffer. But because * - the buffers are invalidated during replenish * - the buffers are aligned on cache line boundaries if the * cache is enabled, * it is not necessary to invalidate the cache. */ /* IXP425_END_CACHE_INVALIDATE(pMblk->m_data, pMblk->m_len); */#endif#ifdef IXP_DRV_DEBUG_MBUFS elogHook(pMblk, 3, pDrvCtrl->rxBufsRecv, pDrvCtrl->rxBufsReplenish);#endif pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* No chained MBUF's on receive side, and NPE set the pktlen field * pMblk->mBlkPktHdr.len = pMblk->m_len; * pMblk->m_next = 0; */ rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; if (rxBufsActive < IXETHACC_REPL_FAST_THRESHOLD) { /* replenish as much as possible */ ixEthAccEndReplenishFast(pDrvCtrl); rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; } if (rxBufsActive < IXETHACC_REPL_SLOW_THRESHOLD) { /* replenish as much as possible */ ixEthAccEndReplenishSlow(pDrvCtrl); rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; } /* Now start a prefetch on the packet payload * This will bring to memory the MAC addresses * and a part of the IP header. */ PREFETCH(pMblk->m_data) ; if (rxBufsActive < 2) { /* The number of cblk/mblk pairs owned by NPE * is gone low. This mbuf will be used for replenish. * If we don't replenish, rx events will not take * place and traffic is blocked (because replenish * is done from RX */ netMblkClChainFree (pMblk); #ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tnetDrop++;#endif#ifdef IXETHACCEND_CSR_1_1 /* update the ip ttl for this interface */ ixEthAccEnd_ip_ttl_update(pDrvCtrl); /* recover ttl-expired mbufs from the stack */ ixEthAccEnd_ip_ttl_mbuf_release(pDrvCtrl->ipFragTtl, pDrvCtrl->end.pNetPool);#endif } else { END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);#ifdef IXETHACCEND_CSR_1_1 /* update the ip ttl for this interface */ ixEthAccEnd_ip_ttl_update(pDrvCtrl);#endif#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tnetReceived++;#endif IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "ixEthAccEndRcvInt: mbuf %8.8x sent to stack\n", (UINT32)pMblk, 2, 3, 4, 5, 6); /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk); } } /* replenish all buffers */ ixEthAccEndReplenishSlow(pDrvCtrl); DO_EVENT(IXE_EVT_RCV_HANDLE_EXIT);}/********************************************************************************* swapMblk: the driver send routine** This routine is used to replace a mbuf chain with mbuf appropriate * for transmission (they need to be aligned, or in uncached memory)***/#ifndef IXE_CACHED_RX_BUFFERS_ENABLEstatic M_BLK *swapMblk(END_DEVICE *pDrvCtrl, M_BLK *pMblk){ M_BLK *newMblk; if (pMblk == NULL) { return NULL; } /* check if the mbuf if from the driver pool */ if ((MBLK_TO_NET_POOL(pMblk) == pDrvCtrl->end.pNetPool) || (MBLK_TO_NET_POOL(pMblk) == ixEthAccpDrvCtrl[1 - pDrvCtrl->unit]->end.pNetPool)) { /* use current mbuf because it belongs to the driver pools */ if (pMblk->m_next == NULL) { /* check for unchained (happy day scenario) */ return pMblk; } else { pMblk->m_next = swapMblk(pDrvCtrl, pMblk->m_next); return pMblk; } } /* Check if mbuf header and payload is aligned */ if (((UINT32)pMblk & (IX_XSCALE_CACHE_LINE_SIZE - 1)) == 0 && ((UINT32)(pMblk->m_data) & (IX_XSCALE_CACHE_LINE_SIZE - 1)) <= 3) { /* use current mbuf, because it is correctly aligned */ pMblk->m_next = swapMblk(pDrvCtrl, pMblk->m_next); return pMblk; } /* the cache operations over mbufs will destroy * the information in adjacent mbuf. * The solution is to get a new mbuf with correct alignement */#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tupleTxAlloc++;#endif newMblk = netTupleGet(pDrvCtrl->end.pNetPool, pMblk->m_len, M_DONTWAIT, MT_HEADER, FALSE ); if (newMblk != NULL) { M_BLK *next = pMblk->m_next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -