📄 ixethaccend.c
字号:
{ return(ERROR); } /* * If you need clusters to store received packets into then get them * here ahead of time. */ if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->end.pNetPool, IX_ETHACC_RX_MBUF_MIN_SIZE, FALSE)) == NULL) return(ERROR); /* The number of cblk/mblk pairs allocated for NPE */ pDrvCtrl->rxBufsAlloc = IXETHACC_MBLKS; IXP_DRV_LOG (IXP_DRV_DEBUG_LOAD, "Memory setup complete\n", 1, 2, 3, 4, 5, 6);#ifdef IXP_DRV_DEBUG /* allow log messages to print */ taskDelay(240);#endif IXP_DRV_DEBUG return OK;}/********************************************************************************* Return buffers to the Intel Ethernet Engine */LOCAL __inline__ STATUS ixEthAccEndReplenish(END_DEVICE *pDrvCtrl, /* interrupting device */M_BLK *pMblk){ if (ixOsServFastMutexTryLock(&(pDrvCtrl->fastReplMutex)) == IX_SUCCESS) { if (ixEthAccPortRxFreeReplenish(pDrvCtrl->unit, pMblk) == IX_ETH_ACC_SUCCESS) { pDrvCtrl->rxBufsReplenish++; /* The number of mblk sent to NPE */ ixOsServFastMutexUnlock(&(pDrvCtrl->fastReplMutex)); IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "ixEthAccEndRepl: replenished mbuf %8.8x\n", (UINT32)pMblk, 2, 3, 4, 5, 6); } else {#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->errs++;#endif ixOsServFastMutexUnlock(&(pDrvCtrl->fastReplMutex)); /* Free buffer back to its pool */ netMblkClChainFree (pMblk); IXP_DRV_LOG(IXP_DRV_DEBUG_RX,"Error:replenish Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); return ERROR; /* unable to replenish */ } } else { /* replenish is already running at this time * Free buffer back to its pool */ netMblkClChainFree (pMblk); } return OK;}/********************************************************************************* Return buffers from the fast pool to the Intel Ethernet Engine */LOCAL void ixEthAccEndReplenishFast(END_DEVICE *pDrvCtrl /* interrupting device */){ M_BLK_ID pMblk; int oldLevel; UINT32 rxBufsActive; /* drain all buffers from the fast path pool */ while (pDrvCtrl->replRd < pDrvCtrl->replWr) { pMblk = pDrvCtrl->replBufList[pDrvCtrl->replRd++ & RECBUF_MASK]; IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "ixEthAccEndRepl fast: received mbuf %8.8x\n", (UINT32)pMblk, 2, 3, 4, 5, 6); /* check the mblk is ready for replenish */ oldLevel = intLock (); /* protect the mbuf structure */ if(pMblk->pClBlk->clRefCnt != 1 || pMblk->m_next != NULL) { /* this mblk may be shared by other components, * or is chained to an other mbuf, so release * it to the pool. */ intUnlock (oldLevel); netMblkClChainFree (pMblk); continue; } intUnlock (oldLevel); rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; if (rxBufsActive >= pDrvCtrl->rxBufsAlloc) { netMblkClChainFree (pMblk); continue; } /* increment stats about fast replenish */#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tnetFastReplenish++;#endif#ifdef IXE_CACHED_RX_BUFFERS_ENABLE /* * Mblk header is invalidated in ethAcc component. * We need only invalidate up to the contents of the use * of this buffer. */ DO_EVENT(IXE_EVT_RCV_REPLENISH_LOOP_CACHEOPS); IXP425_END_CACHE_INVALIDATE(pMblk->m_data, pMblk->m_len);#endif /* Force Quad align for Ip packet headers */ pMblk->m_data = ALIGN_MDATA(pMblk->pClBlk->clNode.pClBuf); pMblk->m_len = IX_ETHACC_RX_MBUF_MIN_SIZE; pMblk->mBlkPktHdr.len = IX_ETHACC_RX_MBUF_MIN_SIZE; pMblk->m_nextpkt = NULL;#ifdef IXP_DRV_DEBUG_MBUFS elogHook(pMblk, 2, 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); } 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; pMblk->m_nextpkt = 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -