⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixethaccend.c

📁 INTEL IXP425的VXWORKS BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
        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 + -