📄 ixethaccend.c
字号:
/* 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 { /* up-date statistics */ if (pMblk->mBlkHdr.mFlags & M_MCAST) { END_INC_IN_MCAST(pMblk->mBlkHdr.mData,pMblk->mBlkPktHdr.len); } else if (pMblk->mBlkHdr.mFlags & M_BCAST) { END_INC_IN_BCAST(pMblk->mBlkHdr.mData,pMblk->mBlkPktHdr.len); } else { END_INC_IN_UCAST(pMblk->mBlkHdr.mData,pMblk->mBlkPktHdr.len); }#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; /* duplicate the mbuf */ memcpy(newMblk->m_data, pMblk->m_data, pMblk->m_len); newMblk->m_len = pMblk->m_len; /* process the next nblk */ if (next == NULL) { /* free the current mblk */ netMblkClChainFree(pMblk); newMblk->m_next = NULL; } else { /* free the current mblk */ pMblk->m_next = 0; netMblkClChainFree(pMblk); newMblk->m_next = swapMblk(pDrvCtrl, next); } return newMblk; } else { /* drop the remaining of the chain */ netMblkClChainFree(pMblk); return NULL; }}#endif/********************************************************************************* ixEthAccEndSend - the driver send routine** This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it. This is done by a higher layer.** RETURNS: OK, ERROR, or END_ERR_BLOCK.*/LOCAL STATUS ixEthAccEndSend(END_DEVICE * pDrvCtrl, /* device ptr */M_BLK_ID pMblk /* data to send */){ int tmLen = 0; M_BLK *mbufPtr; STATUS rtnStatus = OK; char bumpFlag; char mFlags = 0; char *mData;#ifdef INCLUDE_IXETHACC_64BYTES_PADDING M_BLK *lastMbuf;#endif#ifndef IXE_CACHED_RX_BUFFERS_ENABLE pMblk = swapMblk(pDrvCtrl, pMblk);#endif if (pMblk == NULL) return ERROR; if (pMblk->m_next) { /* remember a flag to increment the stats counters */ bumpFlag = pMblk->mBlkHdr.mData[0] & (UINT8) 0x01 ; #ifdef IXP_DRV_DEBUG_MBUFS elogHook(pMblk, 4, pDrvCtrl->rxBufsRecv,pDrvCtrl->rxBufsReplenish);#endif /* calculate the frame size (sum of chained mbufs) */ for ( mbufPtr = pMblk; mbufPtr; mbufPtr = mbufPtr->m_next ) {#ifdef INCLUDE_IXETHACC_64BYTES_PADDING /* remember the last mbuf where padding may be necessary */ lastMbuf = mbufPtr;#endif tmLen += mbufPtr->m_len; } pMblk->m_pkthdr.len = tmLen;#ifdef INCLUDE_IXETHACC_64BYTES_PADDING /* Add padding at the end of the mbuf * this is normally done by the ixp silicon. * (unless the hardware Padding/FCS generation is disabled) */ if (pMblk->m_pkthdr.len < 64) { /* add trailing bytes in last mbuf */ char *mDataPtr = &(lastMbuf->m_data[lastMbuf->m_len]); char *mClBufPtr = &(lastMbuf->pClBlk->clNode.pClBuf[lastMbuf->pClBlk->clSize]); while((pMblk->m_pkthdr.len < 64) && (mDataPtr < mClBufPtr)) { *mDataPtr++ = 0; lastMbuf->m_len += 1; pMblk->m_pkthdr.len += 1; } }#endif /* blocks and buffers come from cached memory */ for ( mbufPtr = pMblk; mbufPtr; mbufPtr = mbufPtr->m_next ) { IXP425_END_CACHE_FLUSH(mbufPtr->m_data, mbufPtr->m_len);#ifdef IXE_CACHED_RX_BUFFERS_ENABLE /* the access component flush the mbuf header */#else IXP425_END_CACHE_FLUSH(mbufPtr, sizeof(M_BLK));#endif } } else {#ifdef INCLUDE_IXETHACC_64BYTES_PADDING /* Add padding at the end of the mbuf * this is normally done by the ixp silicon. * (unless the harware Padding/FCS generation is disabled) */ if (pMblk->m_len < 64) { char *mDataPtr = &(pMblk->m_data[pMblk->m_len]); char *mClBufPtr = &(pMblk->pClBlk->clNode.pClBuf[pMblk->pClBlk->clSize]); while((pMblk->m_len < 64) && (mDataPtr < mClBufPtr)) { *mDataPtr++ = 0; pMblk->m_len += 1; } }#endif#ifdef IXP_DRV_DEBUG_MBUFS elogHook(pMblk, 4, pDrvCtrl->rxBufsRecv,pDrvCtrl->rxBufsReplenish);#endif /* remember a flag to increment the stats counters */ bumpFlag = (pMblk->m_data[0] & ((UINT8)0x01)) ; mFlags = pMblk->m_flags; /* update the length */ tmLen = pMblk->m_pkthdr.len = pMblk->m_len; /* Xmit blocks and buffers can come from cached memory */ IXP425_END_CACHE_FLUSH(pMblk->m_data, pMblk->m_len);#ifdef IXE_CACHED_RX_BUFFERS_ENABLE /* the access component flush the mbuf header */#else IXP425_END_CACHE_FLUSH(pMblk, sizeof(M_BLK));#endif } /* Little endian target swaps bytes so save the pointer for MIB statistics */ mData = pMblk->mBlkHdr.mData; /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ if (!(pDrvCtrl->flags & IxEthAccEnd_POLLING)) { END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER); } /* place a transmit request */ if ( ixEthAccPortTxFrameSubmit(pDrvCtrl->unit, pMblk, IX_ETH_ACC_TX_DEFAULT_PRIORITY) != IX_ETH_ACC_SUCCESS ) { IXP_DRV_LOG (IXP_DRV_DEBUG_ERROR, "Error Tx Send Unit[%d] : Buffer:08x%08X\n", pDrvCtrl->unit, (int)pMblk, 3, 4, 5, 6);#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->errs++;#endif netMblkClChainFree (pMblk); /* update mib stats */ END_INC_OUT_DISCARDS(); rtnStatus = ERROR; } else { /* WARNING: in the little endian BSP, the mBlkHdr has been endian-swapped */ /* Bump the statistics counters. */ if ( (mFlags & M_MCAST) != 0 ) { END_INC_OUT_MCAST (mData, tmLen); } else if ( (mFlags & M_BCAST) != 0 ) { END_INC_OUT_BCAST (mData, tmLen); } else { END_INC_OUT_UCAST (mData, tmLen); } } if (!(pDrvCtrl->flags & IxEthAccEnd_POLLING)) { END_TX_SEM_GIVE (&pDrvCtrl->end); } DO_EVENT(IXE_EVT_XMT_SEND_EXIT); return(rtnStatus);}/********************************************************************************* ixEthAccEndIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS: A command specific response, usually OK or ERROR.*/LOCAL STATUS ixEthAccEndIoctl(END_DEVICE * pDrvCtrl, /* device receiving command */int cmd, /* ioctl command code */caddr_t data /* command argument */){ int error = 0; long value; IXP_DRV_LOG (IXP_DRV_DEBUG_IOCTL, "ixe: Ioctl:unit[%d]:CMD:0x%08X\n", pDrvCtrl->unit, cmd, 3, 4, 5, 6); switch ((UINT)cmd) { case EIOCSADDR: if (data == NULL) return(EINVAL); bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end), END_HADDR_LEN(&pDrvCtrl->end)); break; case EIOCGADDR: if (data == NULL) return(EINVAL); bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data, END_HADDR_LEN(&pDrvCtrl->end)); break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = -(--value); END_FLAGS_CLR (&pDrvCtrl->end, value); } else { END_FLAGS_SET (&pDrvCtrl->end, value); } ixEthAccEndConfig (pDrvCtrl); break; case EIOCGFLAGS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -