📄 ixethaccdataplane.c
字号:
/** * @file IxEthDataPlane.c * * @author Intel Corporation * @date 12-Feb-2002 * * @brief This file contains the implementation of the IXPxxx * Ethernet Access Data plane component * * Design Notes: * * @par * IXP400 SW Release version 2.0 * * -- Copyright Notice -- * * @par * Copyright 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * @par * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @par * -- End of Copyright Notice -- */#include "IxNpeMh.h"#include "IxEthAcc.h"#include "IxEthDB.h"#include "IxOsal.h"#include "IxEthDBPortDefs.h"#include "IxFeatureCtrl.h"#include "IxEthAcc_p.h"#include "IxEthAccQueueAssign_p.h"extern PUBLIC IxEthAccMacState ixEthAccMacState[];extern PUBLIC UINT32 ixEthAccNewSrcMask;/** * private functions prototype */PRIVATE IX_OSAL_MBUF *ixEthAccEntryFromQConvert(UINT32 qEntry, UINT32 mask);PRIVATE UINT32ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf);PRIVATE UINT32ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf);PRIVATE IxEthAccStatusixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId, IxEthAccTxPriority *priorityPtr);PRIVATE IxEthAccStatusixEthAccTxFromSwQ(IxEthAccPortId portId, IxEthAccTxPriority priority);PRIVATE IxEthAccStatusixEthAccRxFreeFromSwQ(IxEthAccPortId portId);PRIVATE voidixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf);PRIVATE voidixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf);PRIVATE IX_STATUSixEthAccQmgrLockTxWrite(IxEthAccPortId portId, UINT32 qBuffer);PRIVATE IX_STATUSixEthAccQmgrLockRxWrite(IxEthAccPortId portId, UINT32 qBuffer);PRIVATE IX_STATUSixEthAccQmgrTxWrite(IxEthAccPortId portId, UINT32 qBuffer, UINT32 priority);/** * @addtogroup IxEthAccPri *@{ *//* increment a counter only when stats are enabled */#define TX_STATS_INC(port,field) \ IX_ETH_ACC_STATS_INC(ixEthAccPortData[port].ixEthAccTxData.stats.field)#define RX_STATS_INC(port,field) \ IX_ETH_ACC_STATS_INC(ixEthAccPortData[port].ixEthAccRxData.stats.field)/* always increment the counter (mainly used for unexpected errors) */#define TX_INC(port,field) \ ixEthAccPortData[port].ixEthAccTxData.stats.field++#define RX_INC(port,field) \ ixEthAccPortData[port].ixEthAccRxData.stats.field++PRIVATE IxEthAccDataPlaneStats ixEthAccDataStats;extern IxEthAccPortDataInfo ixEthAccPortData[];extern IxEthAccInfo ixEthAccDataInfo;PRIVATE IxOsalFastMutex txWriteMutex[IX_ETH_ACC_NUMBER_OF_PORTS];PRIVATE IxOsalFastMutex rxWriteMutex[IX_ETH_ACC_NUMBER_OF_PORTS];/** * * @brief Mbuf header conversion macros : they implement the * different conversions using a temporary value. They also double-check * that the parameters can be converted to/from NPE format. * */#if defined(__wince) && !defined(IN_KERNEL)#define PTR_VIRT2NPE(ptrSrc,dst) \ do { UINT32 temp; \ IX_OSAL_ENSURE(sizeof(ptrSrc) == sizeof(UINT32), "Wrong parameter type"); \ IX_OSAL_ENSURE(sizeof(dst) == sizeof(UINT32), "Wrong parameter type"); \ temp = (UINT32)IX_OSAL_MBUF_MBUF_VIRTUAL_TO_PHYSICAL_TRANSLATION((IX_OSAL_MBUF*)ptrSrc); \ (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \ while(0)#define PTR_NPE2VIRT(type,src,ptrDst) \ do { void *temp; \ IX_OSAL_ENSURE(sizeof(type) == sizeof(UINT32), "Wrong parameter type"); \ IX_OSAL_ENSURE(sizeof(src) == sizeof(UINT32), "Wrong parameter type"); \ IX_OSAL_ENSURE(sizeof(ptrDst) == sizeof(UINT32), "Wrong parameter type"); \ temp = (void *)IX_OSAL_SWAP_BE_SHARED_LONG(src); \ (ptrDst) = (type)IX_OSAL_MBUF_MBUF_PHYSICAL_TO_VIRTUAL_TRANSLATION(temp); } \ while(0)#else#define PTR_VIRT2NPE(ptrSrc,dst) \ do { UINT32 temp; \ IX_OSAL_ENSURE(sizeof(ptrSrc) == sizeof(UINT32), "Wrong parameter type"); \ IX_OSAL_ENSURE(sizeof(dst) == sizeof(UINT32), "Wrong parameter type"); \ temp = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS(ptrSrc); \ (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \ while(0)#define PTR_NPE2VIRT(type,src,ptrDst) \ do { void *temp; \ IX_OSAL_ENSURE(sizeof(type) == sizeof(UINT32), "Wrong parameter type"); \ IX_OSAL_ENSURE(sizeof(src) == sizeof(UINT32), "Wrong parameter type"); \ IX_OSAL_ENSURE(sizeof(ptrDst) == sizeof(UINT32), "Wrong parameter type"); \ temp = (void *)IX_OSAL_SWAP_BE_SHARED_LONG(src); \ (ptrDst) = (type)IX_OSAL_MMU_PHYS_TO_VIRT(temp); } \ while(0)#endif/** * * @brief Mbuf payload pointer conversion macros : Wince has its own * method to convert the buffer pointers */#if defined(__wince) && !defined(IN_KERNEL)#define DATAPTR_VIRT2NPE(ptrSrc,dst) \ do { UINT32 temp; \ temp = (UINT32)IX_OSAL_MBUF_DATA_VIRTUAL_TO_PHYSICAL_TRANSLATION(ptrSrc); \ (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \ while(0)#else#define DATAPTR_VIRT2NPE(ptrSrc,dst) PTR_VIRT2NPE(IX_OSAL_MBUF_MDATA(ptrSrc),dst)#endif/* Flush the shared part of the mbuf header */#define IX_ETHACC_NE_CACHE_FLUSH(mbufPtr) \ do { \ IX_OSAL_CACHE_FLUSH(IX_ETHACC_NE_SHARED(mbufPtr), \ sizeof(IxEthAccNe)); \ } \ while(0)/* Invalidate the shared part of the mbuf header */#define IX_ETHACC_NE_CACHE_INVALIDATE(mbufPtr) \ do { \ IX_OSAL_CACHE_INVALIDATE(IX_ETHACC_NE_SHARED(mbufPtr), \ sizeof(IxEthAccNe)); \ } \ while(0)/* Preload one cache line (shared mbuf headers are aligned * and their size is 1 cache line) * * IX_OSAL_CACHED is defined when the mbuf headers are * allocated from cached memory. * * Other processor on emulation environment may not implement * preload function */#ifdef IX_OSAL_CACHED #if (CPU!=SIMSPARCSOLARIS) && !defined (__wince) #define IX_ACC_DATA_CACHE_PRELOAD(ptr) \ do { /* preload a cache line (Xscale Processor) */ \ __asm__ (" pld [%0]\n": : "r" (ptr)); \ } \ while(0) #else /* preload not implemented on different processor */ #define IX_ACC_DATA_CACHE_PRELOAD(mbufPtr) \ do { /* nothing */ } while (0) #endif#else /* preload not needed if cache is not enabled */ #define IX_ACC_DATA_CACHE_PRELOAD(mbufPtr) \ do { /* nothing */ } while (0)#endif/** * * @brief function to retrieve the correct pointer from * a queue entry posted by the NPE * * @param qEntry : entry from qmgr queue * mask : applicable mask for this queue * (4 most significant bits are used for additional informations) * * @return IX_OSAL_MBUF * pointer to mbuf header * * @internal */PRIVATE IX_OSAL_MBUF *ixEthAccEntryFromQConvert(UINT32 qEntry, UINT32 mask){ IX_OSAL_MBUF *mbufPtr; if (qEntry != 0) { /* mask NPE bits (e.g. priority, port ...) */ qEntry &= mask;#if IX_ACC_DRAM_PHYS_OFFSET != 0 /* restore the original address pointer (if PHYS_OFFSET is not 0) */ qEntry |= (IX_ACC_DRAM_PHYS_OFFSET & ~IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);#endif /* get the mbuf pointer address from the npe-shared address */ qEntry -= offsetof(IX_OSAL_MBUF,ix_ne); /* phys2virt mbuf */ mbufPtr = (IX_OSAL_MBUF *)IX_OSAL_MMU_PHYS_TO_VIRT(qEntry); /* preload the cacheline shared with NPE */ IX_ACC_DATA_CACHE_PRELOAD(IX_ETHACC_NE_SHARED(mbufPtr)); /* preload the cacheline used by xscale */ IX_ACC_DATA_CACHE_PRELOAD(mbufPtr); } else { mbufPtr = NULL; } return mbufPtr;}/* Convert the mbuf header for NPE transmission */PRIVATE UINT32ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf){ UINT32 qbuf; UINT32 len; /* endianess swap for tci and flags note: this is done only once, even for chained buffers */ IX_ETHACC_NE_FLAGS(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_FLAGS(mbuf)); IX_ETHACC_NE_VLANTCI(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_VLANTCI(mbuf)); /* test for unchained mbufs */ if (IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) == NULL) { /* "best case" scenario : unchained mbufs */ IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxMBufs); /* payload pointer conversion */ DATAPTR_VIRT2NPE(mbuf, IX_ETHACC_NE_DATA(mbuf)); /* unchained mbufs : the frame length is the mbuf length * and the 2 identical lengths are stored in the same * word. */ len = IX_OSAL_MBUF_MLEN(mbuf); /* set the length in both length and pktLen 16-bits fields */ len |= (len << IX_ETHNPE_ACC_LENGTH_OFFSET); IX_ETHACC_NE_LEN(mbuf) = IX_OSAL_SWAP_BE_SHARED_LONG(len); /* unchained mbufs : next contains 0 */ IX_ETHACC_NE_NEXT(mbuf) = 0; /* flush shared header after all address conversions */ IX_ETHACC_NE_CACHE_FLUSH(mbuf); } else { /* chained mbufs */ IX_OSAL_MBUF *ptr = mbuf; IX_OSAL_MBUF *nextPtr; UINT32 frmLen; /* get the frame length from the header of the first buffer */ frmLen = IX_OSAL_MBUF_PKT_LEN(mbuf); do { IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxMBufs); /* payload pointer */ DATAPTR_VIRT2NPE(ptr,IX_ETHACC_NE_DATA(ptr)); /* Buffer length and frame length are stored in the same word */ len = IX_OSAL_MBUF_MLEN(ptr); len = frmLen | (len << IX_ETHNPE_ACC_LENGTH_OFFSET); IX_ETHACC_NE_LEN(ptr) = IX_OSAL_SWAP_BE_SHARED_LONG(len); /* get the virtual next chain pointer */ nextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr); if (nextPtr != NULL) { /* shared pointer of the next buffer is chained */ PTR_VIRT2NPE(IX_ETHACC_NE_SHARED(nextPtr), IX_ETHACC_NE_NEXT(ptr)); } else { IX_ETHACC_NE_NEXT(ptr) = 0; } /* flush shared header after all address conversions */ IX_ETHACC_NE_CACHE_FLUSH(ptr); /* move to next buffer */ ptr = nextPtr; /* the frame length field is set only in the first buffer * and is zeroed in the next buffers */ frmLen = 0; } while(ptr != NULL); } /* virt2phys mbuf itself */ qbuf = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS( IX_ETHACC_NE_SHARED(mbuf)); /* Ensure the bits which are reserved to exchange information with * the NPE are cleared * * If the mbuf address is not correctly aligned, or from an * incompatible memory range, there is no point to continue */ IX_OSAL_ENSURE(((qbuf & ~IX_ETHNPE_QM_Q_TXENET_ADDR_MASK) == 0), "Invalid address range"); return qbuf;}/* Convert the mbuf header for NPE reception */PRIVATE UINT32ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf){ UINT32 len; UINT32 qbuf; if (IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) == NULL) { /* "best case" scenario : unchained mbufs */ IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxFreeMBufs); /* unchained mbufs : payload pointer */ DATAPTR_VIRT2NPE(mbuf, IX_ETHACC_NE_DATA(mbuf)); /* unchained mbufs : set the buffer length * and the frame length field is zeroed */ len = (IX_OSAL_MBUF_MLEN(mbuf) << IX_ETHNPE_ACC_LENGTH_OFFSET); IX_ETHACC_NE_LEN(mbuf) = IX_OSAL_SWAP_BE_SHARED_LONG(len); /* unchained mbufs : next pointer is null */ IX_ETHACC_NE_NEXT(mbuf) = 0; /* flush shared header after all address conversions */ IX_ETHACC_NE_CACHE_FLUSH(mbuf); /* remove shared header cache line */ IX_ETHACC_NE_CACHE_INVALIDATE(mbuf); } else { /* chained mbufs */ IX_OSAL_MBUF *ptr = mbuf; IX_OSAL_MBUF *nextPtr; do { /* chained mbufs */ IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxFreeMBufs); /* we must save virtual next chain pointer */ nextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr); if (nextPtr != NULL) { /* chaining pointer for NPE */ PTR_VIRT2NPE(IX_ETHACC_NE_SHARED(nextPtr), IX_ETHACC_NE_NEXT(ptr)); } else { IX_ETHACC_NE_NEXT(ptr) = 0; } /* payload pointer */ DATAPTR_VIRT2NPE(ptr,IX_ETHACC_NE_DATA(ptr)); /* buffer length */ len = (IX_OSAL_MBUF_MLEN(ptr) << IX_ETHNPE_ACC_LENGTH_OFFSET); IX_ETHACC_NE_LEN(ptr) = IX_OSAL_SWAP_BE_SHARED_LONG(len); /* flush shared header after all address conversions */ IX_ETHACC_NE_CACHE_FLUSH(ptr); /* remove shared header cache line */ IX_ETHACC_NE_CACHE_INVALIDATE(ptr); /* next mbuf in the chain */ ptr = nextPtr; } while(ptr != NULL); } /* virt2phys mbuf itself */ qbuf = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS( IX_ETHACC_NE_SHARED(mbuf)); /* Ensure the bits which are reserved to exchange information with * the NPE are cleared * * If the mbuf address is not correctly aligned, or from an * incompatible memory range, there is no point to continue */ IX_OSAL_ENSURE(((qbuf & ~IX_ETHNPE_QM_Q_RXENET_ADDR_MASK) == 0), "Invalid address range"); return qbuf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -