diff options
Diffstat (limited to 'drivers/net/npe/IxEthAccDataPlane.c')
| -rw-r--r-- | drivers/net/npe/IxEthAccDataPlane.c | 2459 | 
1 files changed, 0 insertions, 2459 deletions
| diff --git a/drivers/net/npe/IxEthAccDataPlane.c b/drivers/net/npe/IxEthAccDataPlane.c deleted file mode 100644 index c0b82d99b..000000000 --- a/drivers/net/npe/IxEthAccDataPlane.c +++ /dev/null @@ -1,2459 +0,0 @@ -/** - * @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 - * SPDX-License-Identifier:	BSD-3-Clause - * @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 UINT32 -ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf); - -PRIVATE UINT32 -ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf); - -PRIVATE IxEthAccStatus -ixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId, -				IxEthAccTxPriority *priorityPtr); - -PRIVATE IxEthAccStatus -ixEthAccTxFromSwQ(IxEthAccPortId portId, -		  IxEthAccTxPriority priority); - -PRIVATE IxEthAccStatus -ixEthAccRxFreeFromSwQ(IxEthAccPortId portId); - -PRIVATE void -ixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf); - -PRIVATE void -ixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf); - -PRIVATE IX_STATUS -ixEthAccQmgrLockTxWrite(IxEthAccPortId portId, -			UINT32 qBuffer); - -PRIVATE IX_STATUS -ixEthAccQmgrLockRxWrite(IxEthAccPortId portId, -			UINT32 qBuffer); - -PRIVATE IX_STATUS -ixEthAccQmgrTxWrite(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 UINT32 -ixEthAccMbufTxQPrepare(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 UINT32 -ixEthAccMbufRxQPrepare(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; -} - -/* Convert the mbuf header after NPE transmission - * Since there is nothing changed by the NPE, there is no need - * to process anything but the update of internal stats - * when they are enabled -*/ -PRIVATE void -ixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf) -{ -#ifndef NDEBUG -    /* test for unchained mbufs */ -    if (IX_ETHACC_NE_NEXT(mbuf) == 0) -    { -	/* unchained mbufs : update the stats */ -	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxDoneMBufs); -    } -    else -    { -	/* chained mbufs : walk the chain and update the stats */ -	IX_OSAL_MBUF *ptr = mbuf; - -	do -	{ -	    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxDoneMBufs); -	    ptr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr); -	} -	while (ptr != NULL); -    } -#endif -} - -/* Convert the mbuf header after NPE reception */ -PRIVATE void -ixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf) -{ -    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_ETHACC_NE_NEXT(mbuf) == 0) -    { -	/* unchained mbufs */ -	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxMBufs); - -	/* get the frame length. it is the same than the buffer length */ -	len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf)); -	len &= IX_ETHNPE_ACC_PKTLENGTH_MASK; -	IX_OSAL_MBUF_PKT_LEN(mbuf) = IX_OSAL_MBUF_MLEN(mbuf) = len; - -        /* clears the next packet field */ -	IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) = NULL; -    } -    else -    { -	IX_OSAL_MBUF *ptr = mbuf; -	IX_OSAL_MBUF *nextPtr; -	UINT32 frmLen; - -	/* convert the frame length */ -	frmLen = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf)); -	IX_OSAL_MBUF_PKT_LEN(mbuf) = (frmLen & IX_ETHNPE_ACC_PKTLENGTH_MASK); - -        /* chained mbufs */ -	do -	{ -	    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxMBufs); - -	    /* convert the length */ -	    len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(ptr)); -	    IX_OSAL_MBUF_MLEN(ptr) = (len >> IX_ETHNPE_ACC_LENGTH_OFFSET); - -            /* get the next pointer */ -	    PTR_NPE2VIRT(IX_OSAL_MBUF *,IX_ETHACC_NE_NEXT(ptr), nextPtr); -	    if (nextPtr != NULL) -	    { -		nextPtr = (IX_OSAL_MBUF *)((UINT8 *)nextPtr - offsetof(IX_OSAL_MBUF,ix_ne)); -	    } -	    /* set the next pointer */ -	    IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr) = nextPtr; - -	    /* move to the next buffer */ -	    ptr = nextPtr; -	} -	while (ptr != NULL); -    } -} - -/* write to qmgr if possible and report an overflow if not possible - * Use a fast lock to protect the queue write. - * This way, the tx feature is reentrant. - */ -PRIVATE IX_STATUS -ixEthAccQmgrLockTxWrite(IxEthAccPortId portId, UINT32 qBuffer) -{ -    IX_STATUS qStatus; -    if (ixOsalFastMutexTryLock(&txWriteMutex[portId]) == IX_SUCCESS) -    { -	qStatus = ixQMgrQWrite( -	       IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), -	       &qBuffer); -#ifndef NDEBUG -	if (qStatus != IX_SUCCESS) -	{ -	    TX_STATS_INC(portId, txOverflow); -	} -#endif -	ixOsalFastMutexUnlock(&txWriteMutex[portId]); -    } -    else -    { -	TX_STATS_INC(portId, txLock); -	qStatus = IX_QMGR_Q_OVERFLOW; -    } -    return qStatus; -} - -/* write to qmgr if possible and report an overflow if not possible - * Use a fast lock to protect the queue write. - * This way, the Rx feature is reentrant. - */ -PRIVATE IX_STATUS -ixEthAccQmgrLockRxWrite(IxEthAccPortId portId, UINT32 qBuffer) -{ -    IX_STATUS qStatus; -    if (ixOsalFastMutexTryLock(&rxWriteMutex[portId]) == IX_SUCCESS) -    { -	qStatus = ixQMgrQWrite( -	       IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId), -	       &qBuffer); -#ifndef NDEBUG -	if (qStatus != IX_SUCCESS) -	{ -	    RX_STATS_INC(portId, rxFreeOverflow); -	} -#endif -	ixOsalFastMutexUnlock(&rxWriteMutex[portId]); -    } -    else -    { -	RX_STATS_INC(portId, rxFreeLock); -	qStatus = IX_QMGR_Q_OVERFLOW; -    } -    return qStatus; -} - -/* - * Set the priority and write to a qmgr queue. - */ -PRIVATE IX_STATUS -ixEthAccQmgrTxWrite(IxEthAccPortId portId, UINT32 qBuffer, UINT32 priority) -{ -    /* fill the priority field */ -    qBuffer |= (priority << IX_ETHNPE_QM_Q_FIELD_PRIOR_R); - -    return ixEthAccQmgrLockTxWrite(portId, qBuffer); -} - -/** - * - * @brief This function will discover the highest priority S/W Tx Q that - *        has entries in it - * - * @param portId - (in) the id of the port whose S/W Tx queues are to be searched - *        priorityPtr - (out) the priority of the highest priority occupied q will be written - *                      here - * - * @return IX_ETH_ACC_SUCCESS if an occupied Q is found - *         IX_ETH_ACC_FAIL if no Q has entries - * - * @internal - */ -PRIVATE IxEthAccStatus -ixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId, -				IxEthAccTxPriority *priorityPtr) -{ -    if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline -	== FIFO_NO_PRIORITY) -    { -	if(IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. -	       ixEthAccTxData.txQ[IX_ETH_ACC_TX_DEFAULT_PRIORITY])) -	{ -	    return IX_ETH_ACC_FAIL; -	} -	else -	{ -	    *priorityPtr = IX_ETH_ACC_TX_DEFAULT_PRIORITY; -	    TX_STATS_INC(portId,txPriority[*priorityPtr]); -	    return IX_ETH_ACC_SUCCESS; -	} -    } -    else -    { -	IxEthAccTxPriority highestPriority = IX_ETH_ACC_TX_PRIORITY_7; -	while(1) -	{ -	    if(!IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. -	       ixEthAccTxData.txQ[highestPriority])) -	    { - -		*priorityPtr = highestPriority; -		TX_STATS_INC(portId,txPriority[highestPriority]); -		return IX_ETH_ACC_SUCCESS; - -	    } -	    if (highestPriority == IX_ETH_ACC_TX_PRIORITY_0) -	    { -		return IX_ETH_ACC_FAIL; -	    } -	    highestPriority--; -	} -    } -} - -/** - * - * @brief This function will take a buffer from a TX S/W Q and attempt - *        to add it to the relevant TX H/W Q - * - * @param portId - the port whose TX queue is to be written to - *        priority - identifies the queue from which the entry is to be read - * - * @internal - */ -PRIVATE IxEthAccStatus -ixEthAccTxFromSwQ(IxEthAccPortId portId, -		  IxEthAccTxPriority priority) -{ -    IX_OSAL_MBUF        *mbuf; -    IX_STATUS	   qStatus; - -    IX_OSAL_ENSURE((UINT32)priority <= (UINT32)7, "Invalid priority"); - -    IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD( -	ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], -	mbuf); - -    if (mbuf != NULL) -    { -	/* -	 * Add the Tx buffer to the H/W Tx Q -	 * We do not need to flush here as it is already done -	 * in TxFrameSubmit(). -	 */ -	qStatus = ixEthAccQmgrTxWrite( -	      portId, -	      IX_OSAL_MMU_VIRT_TO_PHYS((UINT32)IX_ETHACC_NE_SHARED(mbuf)), -	      priority); - -	if (qStatus == IX_SUCCESS) -	{ -	    TX_STATS_INC(portId,txFromSwQOK); -	    return IX_SUCCESS; -	} -	else if (qStatus == IX_QMGR_Q_OVERFLOW) -	{ -	    /* -	     * H/W Q overflow, need to save the buffer -	     * back on the s/w Q. -	     * we must put it back on the head of the q to avoid -	     * reordering packet tx -	     */ -	    TX_STATS_INC(portId,txFromSwQDelayed); -	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD( -		ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], -		mbuf); - -	    /*enable Q notification*/ -	    qStatus = ixQMgrNotificationEnable( -		IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), -		IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId)); - -            if (qStatus != IX_SUCCESS && qStatus != IX_QMGR_WARNING) -            { -		TX_INC(portId,txUnexpectedError); -		IX_ETH_ACC_FATAL_LOG( -	            "ixEthAccTxFromSwQ:Unexpected Error: %u\n", -	            qStatus, 0, 0, 0, 0, 0); -            } -	} -	else -	{ -	    TX_INC(portId,txUnexpectedError); - -	    /* recovery attempt */ -	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD( -		ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], -		mbuf); - -	    IX_ETH_ACC_FATAL_LOG( -		"ixEthAccTxFromSwQ:Error: unexpected QM status 0x%08X\n", -		qStatus, 0, 0, 0, 0, 0); -	} -    } -    else -    { -	/* sw queue is empty */ -    } -    return IX_ETH_ACC_FAIL; -} - -/** - * - * @brief This function will take a buffer from a RXfree S/W Q and attempt - *        to add it to the relevant RxFree H/W Q - * - * @param portId - the port whose RXFree queue is to be written to - * - * @internal - */ -PRIVATE IxEthAccStatus -ixEthAccRxFreeFromSwQ(IxEthAccPortId portId) -{ -    IX_OSAL_MBUF        *mbuf; -    IX_STATUS	   qStatus = IX_SUCCESS; - -    IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD( -	  ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, -	  mbuf); -    if (mbuf != NULL) -    { -	/* -	 * Add The Rx Buffer to the H/W Free buffer Q if possible -	 */ -	qStatus = ixEthAccQmgrLockRxWrite(portId, -		  IX_OSAL_MMU_VIRT_TO_PHYS( -			 (UINT32)IX_ETHACC_NE_SHARED(mbuf))); - -	if (qStatus == IX_SUCCESS) -	{ -	    RX_STATS_INC(portId,rxFreeRepFromSwQOK); -	    /* -	     * Buffer added to h/w Q. -	     */ -	    return IX_SUCCESS; -	} -	else if (qStatus == IX_QMGR_Q_OVERFLOW) -	{ -	    /* -	     * H/W Q overflow, need to save the buffer back on the s/w Q. -	     */ -	    RX_STATS_INC(portId,rxFreeRepFromSwQDelayed); - -	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD( -		   ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, -		   mbuf); -	} -	else -	{ -	    /* unexpected qmgr error */ -	    RX_INC(portId,rxUnexpectedError); - -	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD( -		    ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, -		    mbuf); - -	    IX_ETH_ACC_FATAL_LOG("IxEthAccRxFreeFromSwQ:Error: unexpected QM status 0x%08X\n", -				 qStatus, 0, 0, 0, 0, 0); -	} -    } -    else -    { -	/* sw queue is empty */ -    } -    return IX_ETH_ACC_FAIL; -} - - -IX_ETH_ACC_PUBLIC -IxEthAccStatus ixEthAccInitDataPlane() -{ -    UINT32 portId; - -    /* -     * Initialize the service and register callback to other services. -     */ - -    IX_ETH_ACC_MEMSET(&ixEthAccDataStats, -		      0, -		      sizeof(ixEthAccDataStats)); - -    for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) -    { -	ixOsalFastMutexInit(&txWriteMutex[portId]); -	ixOsalFastMutexInit(&rxWriteMutex[portId]); - -	IX_ETH_ACC_MEMSET(&ixEthAccPortData[portId], -			  0, -			  sizeof(ixEthAccPortData[portId])); - -	ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = FIFO_NO_PRIORITY; -    } - -    return (IX_ETH_ACC_SUCCESS); -} - - -IX_ETH_ACC_PUBLIC -IxEthAccStatus ixEthAccPortTxDoneCallbackRegister(IxEthAccPortId portId, -						  IxEthAccPortTxDoneCallback -						  txCallbackFn, -						  UINT32 callbackTag) -{ -    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) -    { -	return (IX_ETH_ACC_FAIL); -    } -    if (!IX_ETH_ACC_IS_PORT_VALID(portId)) -    { -	return (IX_ETH_ACC_INVALID_PORT); -    } - -/* HACK: removing this code to enable NPE-A preliminary testing - *    if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) - *    { - *        IX_ETH_ACC_WARNING_LOG("ixEthAccPortTxDoneCallbackRegister: Unavailable Eth %d: Cannot register TxDone Callback.\n",(INT32)portId,0,0,0,0,0); - *        return IX_ETH_ACC_SUCCESS ; - *    } - */ - -    if (!IX_ETH_IS_PORT_INITIALIZED(portId)) -    { -	return (IX_ETH_ACC_PORT_UNINITIALIZED); -    } -    if (txCallbackFn == 0) -	/* Check for null function pointer here. */ -    { -	return (IX_ETH_ACC_INVALID_ARG); -    } -    ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = txCallbackFn; -    ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = callbackTag; -    return (IX_ETH_ACC_SUCCESS); -} - - -IX_ETH_ACC_PUBLIC -IxEthAccStatus ixEthAccPortRxCallbackRegister(IxEthAccPortId portId, -					      IxEthAccPortRxCallback -					      rxCallbackFn, -					      UINT32 callbackTag) -{ -    IxEthAccPortId port; - -    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) -    { -	return (IX_ETH_ACC_FAIL); -    } -    if (!IX_ETH_ACC_IS_PORT_VALID(portId)) -    { -	return (IX_ETH_ACC_INVALID_PORT); -    } - -    if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) -    { -        IX_ETH_ACC_WARNING_LOG("ixEthAccPortRxCallbackRegister: Unavailable Eth %d: Cannot register Rx Callback.\n",(INT32)portId,0,0,0,0,0); -        return IX_ETH_ACC_SUCCESS ; -    } - -    if (!IX_ETH_IS_PORT_INITIALIZED(portId)) -    { -	return (IX_ETH_ACC_PORT_UNINITIALIZED); -    } - -    /* Check for null function pointer here. */ -    if (rxCallbackFn == NULL) -    { -	return (IX_ETH_ACC_INVALID_ARG); -    } - -    /* Check the user is not changing the callback type -     * when the port is enabled. -    */ -    if (ixEthAccMacState[portId].portDisableState == ACTIVE) -    { -	for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++) -	{ -	    if ((ixEthAccMacState[port].portDisableState == ACTIVE) -		&& (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == true)) -	    { -		/* one of the active ports has a different rx callback type. -		 * Changing the callback type when the port is enabled -		 * is not safe -		 */ -		return (IX_ETH_ACC_INVALID_ARG); -	    } -	} -    } - -    /* update the callback pointer : this is done before -     * registering the new qmgr callback -     */ -    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = rxCallbackFn; -    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = callbackTag; - -    /* update the qmgr callback for rx queues */ -    if (ixEthAccQMgrRxCallbacksRegister(ixEthRxFrameQMCallback) -	!= IX_ETH_ACC_SUCCESS) -    { -	/* unexpected qmgr error */ -        IX_ETH_ACC_FATAL_LOG("ixEthAccPortRxCallbackRegister: unexpected QMgr error, " \ -            "could not register Rx single-buffer callback\n", 0, 0, 0, 0, 0, 0); - -	RX_INC(portId,rxUnexpectedError); -	return (IX_ETH_ACC_INVALID_ARG); -    } - -    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = false; - -    return (IX_ETH_ACC_SUCCESS); -} - -IX_ETH_ACC_PUBLIC -IxEthAccStatus ixEthAccPortMultiBufferRxCallbackRegister( -			 IxEthAccPortId portId, -			 IxEthAccPortMultiBufferRxCallback -			 rxCallbackFn, -			 UINT32 callbackTag) -{ -    IxEthAccPortId port; - -    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) -    { -	return (IX_ETH_ACC_FAIL); -    } -    if (!IX_ETH_ACC_IS_PORT_VALID(portId)) -    { -	return (IX_ETH_ACC_INVALID_PORT); -    } - -    if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) -    { -        IX_ETH_ACC_WARNING_LOG("ixEthAccPortMultiBufferRxCallbackRegister: Unavailable Eth %d: Cannot register Rx Callback.\n",(INT32)portId,0,0,0,0,0); -        return IX_ETH_ACC_SUCCESS ; -    } - -    if (!IX_ETH_IS_PORT_INITIALIZED(portId)) -    { -	return (IX_ETH_ACC_PORT_UNINITIALIZED); -    } - -    /* Check for null function pointer here. */ -    if (rxCallbackFn == NULL) -    { -	return (IX_ETH_ACC_INVALID_ARG); -    } - -    /* Check the user is not changing the callback type -     * when the port is enabled. -    */ -    if (ixEthAccMacState[portId].portDisableState == ACTIVE) -    { -	for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++) -	{ -	    if ((ixEthAccMacState[port].portDisableState == ACTIVE) -		&& (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == false)) -	    { -		/* one of the active ports has a different rx callback type. -		 * Changing the callback type when the port is enabled -		 * is not safe -		 */ -		return (IX_ETH_ACC_INVALID_ARG); -	    } -	} -    } - -    /* update the callback pointer : this is done before -     * registering the new qmgr callback -     */ -    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = rxCallbackFn; -    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = callbackTag; - -    /* update the qmgr callback for rx queues */ -    if (ixEthAccQMgrRxCallbacksRegister(ixEthRxMultiBufferQMCallback) -	!= IX_ETH_ACC_SUCCESS) -    { -	/* unexpected qmgr error */ -	RX_INC(portId,rxUnexpectedError); - -        IX_ETH_ACC_FATAL_LOG("ixEthAccPortMultiBufferRxCallbackRegister: unexpected QMgr error, " \ -            "could not register Rx multi-buffer callback\n", 0, 0, 0, 0, 0, 0); - -	return (IX_ETH_ACC_INVALID_ARG); -    } - -    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = true; - -    return (IX_ETH_ACC_SUCCESS); -} - -IX_ETH_ACC_PUBLIC -IxEthAccStatus ixEthAccPortTxFrameSubmit(IxEthAccPortId portId, -					 IX_OSAL_MBUF *buffer, -					 IxEthAccTxPriority priority) -{ -    IX_STATUS	qStatus = IX_SUCCESS; -    UINT32      qBuffer; -    IxEthAccTxPriority highestPriority; -    IxQMgrQStatus txQStatus; - -#ifndef NDEBUG -    if (buffer == NULL) -    { -	return (IX_ETH_ACC_FAIL); -    } -    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) -    { -	return (IX_ETH_ACC_FAIL); -    } -    if (!IX_ETH_ACC_IS_PORT_VALID(portId)) -    { -	return (IX_ETH_ACC_INVALID_PORT); -    } - -    if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) -    { -        IX_ETH_ACC_FATAL_LOG("ixEthAccPortTxFrameSubmit: Unavailable Eth %d: Cannot submit Tx Frame.\n", -			     (INT32)portId,0,0,0,0,0); -        return IX_ETH_ACC_PORT_UNINITIALIZED ; -    } - -    if (!IX_ETH_IS_PORT_INITIALIZED(portId)) -    { -	return (IX_ETH_ACC_PORT_UNINITIALIZED); -    } -    if ((UINT32)priority > (UINT32)IX_ETH_ACC_TX_PRIORITY_7) -    { -	return (IX_ETH_ACC_INVALID_ARG); -    } -#endif - -    /* -     * Need to Flush the MBUF and its contents (data) as it may be -     * read from the NPE. Convert virtual addresses to physical addresses also. -     */ -    qBuffer = ixEthAccMbufTxQPrepare(buffer); - -    /* -     * If no fifo priority set on Xscale ... -     */ -    if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline == -	FIFO_NO_PRIORITY) -    { -	/* -	 * Add The Tx Buffer to the H/W Tx Q if possible -	 * (the priority is passed to the NPE, because -	 * the NPE is able to reorder the frames -	 * before transmission to the underlying hardware) -	 */ -	qStatus = ixEthAccQmgrTxWrite(portId, -				      qBuffer, -				      IX_ETH_ACC_TX_DEFAULT_PRIORITY); - -	if (qStatus == IX_SUCCESS) -	{ -	    TX_STATS_INC(portId,txQOK); - -	    /* -	     * "best case" scenario : Buffer added to h/w Q. -	     */ -	    return (IX_SUCCESS); -	} -	else if (qStatus == IX_QMGR_Q_OVERFLOW) -	{ -	    /* -	     * We were unable to write the buffer to the -	     * appropriate H/W Q,  Save it in the sw Q. -	     * (use the default priority queue regardless of -	     * input parameter) -	     */ -	    priority = IX_ETH_ACC_TX_DEFAULT_PRIORITY; -	} -	else -	{ -	    /* unexpected qmgr error */ -	    TX_INC(portId,txUnexpectedError); -	    IX_ETH_ACC_FATAL_LOG( -		"ixEthAccPortTxFrameSubmit:Error: qStatus = %u\n", -		(UINT32)qStatus, 0, 0, 0, 0, 0); -	    return (IX_ETH_ACC_FAIL); -	} -    } -    else if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline == -	     FIFO_PRIORITY) -    { - -	/* -	 * For priority transmission, put the frame directly on the H/W queue -	 * if the H/W queue is empty, otherwise, put it in a S/W Q -	 */ -	ixQMgrQStatusGet(IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), &txQStatus); -	if((txQStatus & IX_QMGR_Q_STATUS_E_BIT_MASK) != 0) -	{ -	    /*The tx queue is empty, check whether there are buffers on the s/w queues*/ -	    if(ixEthAccTxSwQHighestPriorityGet(portId,  &highestPriority) -	       !=IX_ETH_ACC_FAIL) -	    { -		/*there are buffers on the s/w queues, submit them*/ -		ixEthAccTxFromSwQ(portId, highestPriority); - -		/* the queue was empty, 1 buffer is already supplied -		 * but is likely to be immediately transmitted and the -		 * hw queue is likely to be empty again, so submit -		 * more from the sw queues -		 */ -		if(ixEthAccTxSwQHighestPriorityGet(portId,  &highestPriority) -		   !=IX_ETH_ACC_FAIL) -		{ -		    ixEthAccTxFromSwQ(portId, highestPriority); -		    /* -		     * and force the buffer supplied to be placed -		     * on a priority queue -		     */ -		    qStatus = IX_QMGR_Q_OVERFLOW; -		} -		else -		{ -		    /*there are no buffers in the s/w queues, submit directly*/ -		    qStatus = ixEthAccQmgrTxWrite(portId, qBuffer, priority); -		} -	    } -	    else -	    { -		/*there are no buffers in the s/w queues, submit directly*/ -		qStatus = ixEthAccQmgrTxWrite(portId, qBuffer, priority); -	    } -	} -	else -	{ -	    qStatus = IX_QMGR_Q_OVERFLOW; -	} -    } -    else -    { -	TX_INC(portId,txUnexpectedError); -	IX_ETH_ACC_FATAL_LOG( -	    "ixEthAccPortTxFrameSubmit:Error: wrong schedule discipline setup\n", -	    0, 0, 0, 0, 0, 0); -	return (IX_ETH_ACC_FAIL); -    } - -    if(qStatus == IX_SUCCESS ) -    { -	TX_STATS_INC(portId,txQOK); -	return IX_ETH_ACC_SUCCESS; -    } -    else if(qStatus == IX_QMGR_Q_OVERFLOW) -    { -	TX_STATS_INC(portId,txQDelayed); -	/* -	 * We were unable to write the buffer to the -	 * appropriate H/W Q,  Save it in a s/w Q. -	 */ -	IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL( -		ixEthAccPortData[portId]. -		ixEthAccTxData.txQ[priority], -		buffer); - -	qStatus = ixQMgrNotificationEnable( -		IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), -		IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId)); - -        if (qStatus != IX_SUCCESS) -	{ -	    if (qStatus == IX_QMGR_WARNING) -	    { -		/* notification is enabled for a queue -		 * which is already empty (the condition is already met) -		 * and there will be no more queue event to drain the sw queue -		 */ -		TX_STATS_INC(portId,txLateNotificationEnabled); - -		/* pull a buffer from the sw queue */ -		if(ixEthAccTxSwQHighestPriorityGet(portId,  &highestPriority) -		   !=IX_ETH_ACC_FAIL) -		{ -		    /*there are buffers on the s/w queues, submit from them*/ -		    ixEthAccTxFromSwQ(portId, highestPriority); -		} -	    } -	    else -	    { -		TX_INC(portId,txUnexpectedError); -		IX_ETH_ACC_FATAL_LOG( -		     "ixEthAccPortTxFrameSubmit: unexpected Error: %u\n", -		     qStatus, 0, 0, 0, 0, 0); -	    } -        } -    } -    else -    { -	TX_INC(portId,txUnexpectedError); -	IX_ETH_ACC_FATAL_LOG( -	     "ixEthAccPortTxFrameSubmit: unexpected Error: %u\n", -	     qStatus, 0, 0, 0, 0, 0); -	return (IX_ETH_ACC_FAIL); -    } - -    return (IX_ETH_ACC_SUCCESS); -} - - -/** - * - * @brief replenish: convert a chain of mbufs to the format - *        expected by the NPE - * -  */ - -IX_ETH_ACC_PUBLIC -IxEthAccStatus ixEthAccPortRxFreeReplenish(IxEthAccPortId portId, -					   IX_OSAL_MBUF *buffer) -{ -    IX_STATUS	qStatus = IX_SUCCESS; -    UINT32      qBuffer; - -    /* -     * Check buffer is valid. -     */ - -#ifndef NDEBUG -    /* check parameter value */ -    if (buffer == 0) -    { -	return (IX_ETH_ACC_FAIL); -    } -    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) -    { -	return (IX_ETH_ACC_FAIL); -    } -    if (!IX_ETH_ACC_IS_PORT_VALID(portId)) -    { -	return (IX_ETH_ACC_INVALID_PORT); -    } - -    /* check initialisation is done */ -    if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) -    { -        IX_ETH_ACC_FATAL_LOG(" ixEthAccPortRxFreeReplenish: Unavailable Eth %d: Cannot replenish Rx Free Q.\n",(INT32)portId,0,0,0,0,0); -        return IX_ETH_ACC_PORT_UNINITIALIZED ; -    } - -    if (!IX_ETH_IS_PORT_INITIALIZED(portId)) -    { -	return (IX_ETH_ACC_PORT_UNINITIALIZED); -    } -    /* check boundaries and constraints */ -    if (IX_OSAL_MBUF_MLEN(buffer) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN) -    { -	return (IX_ETH_ACC_FAIL); -    } -#endif - -    qBuffer = ixEthAccMbufRxQPrepare(buffer); - -    /* -     * Add The Rx Buffer to the H/W Free buffer Q if possible -     */ -    qStatus = ixEthAccQmgrLockRxWrite(portId, qBuffer); - -    if (qStatus == IX_SUCCESS) -    { -	RX_STATS_INC(portId,rxFreeRepOK); -	/* -	 * Buffer added to h/w Q. -	 */ -	return (IX_SUCCESS); -    } -    else if (qStatus == IX_QMGR_Q_OVERFLOW) -    { -	RX_STATS_INC(portId,rxFreeRepDelayed); -	/* -	 * We were unable to write the buffer to the approprate H/W Q, -	 * Save it in a s/w Q. -	 */ -	IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL( -	    ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, -	    buffer); - -	qStatus = ixQMgrNotificationEnable( -	    IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId), -	    IX_ETH_ACC_PORT_TO_RX_FREE_Q_SOURCE(portId)); - -        if (qStatus != IX_SUCCESS) -	{ -	    if (qStatus == IX_QMGR_WARNING) -	    { -		/* notification is enabled for a queue -		 * which is already empty (the condition is already met) -		 * and there will be no more queue event to drain the sw queue -		 * move an entry from the sw queue to the hw queue */ -		RX_STATS_INC(portId,rxFreeLateNotificationEnabled); -		ixEthAccRxFreeFromSwQ(portId); -	    } -	    else -	    { -		RX_INC(portId,rxUnexpectedError); -		IX_ETH_ACC_FATAL_LOG( -		     "ixEthAccRxPortFreeReplenish:Error: %u\n", -		     qStatus, 0, 0, 0, 0, 0); -	    } -        } -    } -    else -    { -	RX_INC(portId,rxUnexpectedError); -	IX_ETH_ACC_FATAL_LOG( -	    "ixEthAccRxPortFreeReplenish:Error: qStatus = %u\n", -	    (UINT32)qStatus, 0, 0, 0, 0, 0); -        return(IX_ETH_ACC_FAIL); -    } -    return (IX_ETH_ACC_SUCCESS); -} - - -IX_ETH_ACC_PUBLIC -IxEthAccStatus ixEthAccTxSchedulingDisciplineSetPriv(IxEthAccPortId portId, -						 IxEthAccSchedulerDiscipline -						 sched) -{ -    if (!IX_ETH_ACC_IS_PORT_VALID(portId)) -    { -	return (IX_ETH_ACC_INVALID_PORT); -    } - -    if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) -    { -        IX_ETH_ACC_WARNING_LOG("ixEthAccTxSchedulingDisciplineSet: Unavailable Eth %d: Cannot set Tx Scheduling Discipline.\n",(INT32)portId,0,0,0,0,0); -        return IX_ETH_ACC_SUCCESS ; -    } - -    if (!IX_ETH_IS_PORT_INITIALIZED(portId)) -    { -	return (IX_ETH_ACC_PORT_UNINITIALIZED); -    } - -    if (sched != FIFO_PRIORITY && sched != FIFO_NO_PRIORITY) -    { -	return (IX_ETH_ACC_INVALID_ARG); -    } - -    ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = sched; -    return (IX_ETH_ACC_SUCCESS); -} - -IX_ETH_ACC_PUBLIC -IxEthAccStatus ixEthAccRxSchedulingDisciplineSetPriv(IxEthAccSchedulerDiscipline -						 sched) -{ -    if (sched != FIFO_PRIORITY && sched != FIFO_NO_PRIORITY) -    { -	return (IX_ETH_ACC_INVALID_ARG); -    } - -    ixEthAccDataInfo.schDiscipline = sched; - -    return (IX_ETH_ACC_SUCCESS); -} - - -/** - * @fn ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) - * - * @brief process incoming frame : - * - * @param @ref IxQMgrCallback IxQMgrMultiBufferCallback - * - * @return none - * - * @internal - * - */ -IX_ETH_ACC_PRIVATE BOOL -ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) -{ -    UINT32 flags; -    IxEthDBStatus result; - -#ifndef NDEBUG -    /* Prudent to at least check the port is within range */ -    if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) -    { -	ixEthAccDataStats.unexpectedError++; -	IX_ETH_ACC_FATAL_LOG( -	     "ixEthRxFrameProcess: Illegal port: %u\n", -	     (UINT32)portId, 0, 0, 0, 0, 0); -	return false; -    } -#endif - -    /* convert fields from mbuf header */ -    ixEthAccMbufFromRxQ(mbufPtr); - -    /* check about any special processing for this frame */ -    flags = IX_ETHACC_NE_FLAGS(mbufPtr); -    if ((flags & (IX_ETHACC_NE_FILTERMASK | IX_ETHACC_NE_NEWSRCMASK)) == 0) -    { -	/* "best case" scenario : nothing special to do for this frame */ -	return true; -    } - -#ifdef CONFIG_IXP425_COMPONENT_ETHDB -    /* if a new source MAC address is detected by the NPE, -     * update IxEthDB with the portId and the MAC address. -     */ -    if ((flags & IX_ETHACC_NE_NEWSRCMASK & ixEthAccNewSrcMask) != 0) -    { -        result = ixEthDBFilteringDynamicEntryProvision(portId, -			  (IxEthDBMacAddr *) IX_ETHACC_NE_SOURCEMAC(mbufPtr)); - -	if (result != IX_ETH_DB_SUCCESS && result != IX_ETH_DB_FEATURE_UNAVAILABLE) -	{ -            if ((ixEthAccMacState[portId].portDisableState == ACTIVE) && (result != IX_ETH_DB_BUSY)) -            { -	        RX_STATS_INC(portId, rxUnexpectedError); -                IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to add source MAC \ -                                    to the Learning/Filtering database\n", 0, 0, 0, 0, 0, 0); -            } -            else -            { -                /* we expect this to fail during PortDisable, as EthDB is disabled for -                 * that port and will refuse to learn new addresses -		 */ -            } -	} -	else -	{ -	    RX_STATS_INC(portId, rxUnlearnedMacAddress); -	} -    } -#endif - -    /* check if this frame should have been filtered -     * by the NPE and take the appropriate action -     */ -    if (((flags & IX_ETHACC_NE_FILTERMASK) != 0) -        && (ixEthAccMacState[portId].portDisableState == ACTIVE)) -    { -        /* If the mbuf was allocated with a small data size, or the current data pointer is not -         * within the allocated data area, then the buffer is non-standard and has to be -         * replenished with the minimum size only -         */ -        if( (IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN) -           || ((UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) > IX_OSAL_MBUF_MDATA(mbufPtr)) -           || ((UINT8 *)(IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) + -              IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr)) -               < IX_OSAL_MBUF_MDATA(mbufPtr)) ) -        { -            /* set to minimum length */ -            IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) = -                IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN; -        } -        else -        { -            /* restore original length */ -            IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) = -                ( IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) - -                 (IX_OSAL_MBUF_MDATA(mbufPtr) - (UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr)) ); -        } - -        /* replenish from here */ -        if (ixEthAccPortRxFreeReplenish(portId, mbufPtr) != IX_ETH_ACC_SUCCESS) -        { -                IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to replenish with filtered frame\ -                                      on port %d\n", portId, 0, 0, 0, 0, 0); -        } - -        RX_STATS_INC(portId, rxFiltered); - -        /* indicate that frame should not be subjected to further processing */ -        return false; -    } - -    return true; -} - - -/** - * @fn ixEthRxFrameQMCallback - * - * @brief receive callback for Frame receive Q from NPE - * - * Frames are passed one-at-a-time to the user - * - * @param @ref IxQMgrCallback - * - * @return none - * - * @internal - * - * Design note : while processing the entry X, entry X+1 is preloaded - * into memory to reduce the number of stall cycles - * - */ -void ixEthRxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) -{ -    IX_OSAL_MBUF    *mbufPtr; -    IX_OSAL_MBUF    *nextMbufPtr; -    UINT32     qEntry; -    UINT32     nextQEntry; -    UINT32     *qEntryPtr; -    UINT32     portId; -    UINT32     destPortId; -    UINT32     npeId; -    UINT32     rxQReadStatus; - -    /* -     * Design note : entries are read in a buffer, This buffer contains -     * an extra zeroed entry so the loop will -     * always terminate on a null entry, whatever the result of Burst read is. -     */ -    UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1]; - -    /* -     * Indication of the number of times the callback is used. -     */ -    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter); - -    do -    { -	/* -	 * Indication of the number of times the queue is drained -	 */ -	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead); - -	/* ensure the last entry of the array contains a zeroed value */ -	qEntryPtr = rxQEntry; -	qEntryPtr[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK] = 0; - -	rxQReadStatus = ixQMgrQBurstRead(qId, -		 IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK, -		 qEntryPtr); - -#ifndef NDEBUG -	if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW) -	    && (rxQReadStatus != IX_SUCCESS)) -	{ -	    ixEthAccDataStats.unexpectedError++; -	    /*major error*/ -	    IX_ETH_ACC_FATAL_LOG( -		"ixEthRxFrameQMCallback:Error: %u\n", -		(UINT32)rxQReadStatus, 0, 0, 0, 0, 0); -	    return; -	} -#endif - -	/* convert and preload the next entry -	 * (the conversion function takes care about null pointers which -	 * are used to mark the end of the loop) -	 */ -	nextQEntry = *qEntryPtr; -	nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, -			  IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); - -	while(nextQEntry != 0) -	{ -	    /* get the next entry */ -	    qEntry = nextQEntry; -	    mbufPtr = nextMbufPtr; - -#ifndef NDEBUG -	    if (mbufPtr == NULL) -	    { -		ixEthAccDataStats.unexpectedError++; -		IX_ETH_ACC_FATAL_LOG( -		    "ixEthRxFrameQMCallback: Null Mbuf Ptr\n", -		    0, 0, 0, 0, 0, 0); -		return; -	    } -#endif - -	    /* convert the next entry -	     * (the conversion function takes care about null pointers which -	     * are used to mark the end of the loop) -	     */ -	    nextQEntry = *(++qEntryPtr); -	    nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, -			      IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); - -	    /* -	     * Get Port and Npe ID from message. -	     */ -	    npeId = ((IX_ETHNPE_QM_Q_RXENET_NPEID_MASK & -		      qEntry) >> IX_ETHNPE_QM_Q_FIELD_NPEID_R); -	    portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); - -	    /* process frame, check the return code and skip the remaining of -	     * the loop if the frame is to be filtered out -	     */ -            if (ixEthRxFrameProcess(portId, mbufPtr)) -            { -	        /* destination portId for this packet */ -	        destPortId = IX_ETHACC_NE_DESTPORTID(mbufPtr); - -                if (destPortId != IX_ETH_DB_UNKNOWN_PORT) -                { -                    destPortId = IX_ETH_DB_NPE_LOGICAL_ID_TO_PORT_ID(destPortId); -                } - -	        /* test if QoS is enabled in ethAcc -	        */ -	        if (ixEthAccDataInfo.schDiscipline == FIFO_PRIORITY) -	        { -		    /* check if there is a higher priority queue -		    * which may require processing and then process it. -		    */ -		    if (ixEthAccDataInfo.higherPriorityQueue[qId] < IX_QMGR_MAX_NUM_QUEUES) -		    { -		        ixEthRxFrameQMCallback(ixEthAccDataInfo.higherPriorityQueue[qId], -					    callbackId); -		    } -	        } - -	        /* -	        * increment priority stats -	        */ -	        RX_STATS_INC(portId,rxPriority[IX_ETHACC_NE_QOS(mbufPtr)]); - -	        /* -	        * increment callback count stats -	        */ -	        RX_STATS_INC(portId,rxFrameClientCallback); - -	        /* -	        * Call user level callback. -	        */ -	        ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn( -		    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag, -		    mbufPtr, -		    destPortId); -            } -	} -    } while (rxQReadStatus == IX_SUCCESS); -} - -/** - * @fn ixEthRxMultiBufferQMCallback - * - * @brief receive callback for Frame receive Q from NPE - * - * Frames are passed as an array to the user - * - * @param @ref IxQMgrCallback - * - * @return none - * - * @internal - * - * Design note : while processing the entry X, entry X+1 is preloaded - * into memory to reduce the number of stall cycles - * - */ -void ixEthRxMultiBufferQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) -{ -    IX_OSAL_MBUF    *mbufPtr; -    IX_OSAL_MBUF    *nextMbufPtr; -    UINT32     qEntry; -    UINT32     nextQEntry; -    UINT32     *qEntryPtr; -    UINT32     portId; -    UINT32     npeId; -    UINT32     rxQReadStatus; -    /* -     * Design note : entries are read in a static buffer, This buffer contains -     * an extra zeroed entry so the loop will -     * always terminate on a null entry, whatever the result of Burst read is. -     */ -    static UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1]; -    static IX_OSAL_MBUF *rxMbufPortArray[IX_ETH_ACC_NUMBER_OF_PORTS][IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1]; -    IX_OSAL_MBUF **rxMbufPtr[IX_ETH_ACC_NUMBER_OF_PORTS]; - -    for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) -    { -	rxMbufPtr[portId] = rxMbufPortArray[portId]; -    } - -    /* -     * Indication of the number of times the callback is used. -     */ -    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter); - -    do -    { -	/* -	 * Indication of the number of times the queue is drained -	 */ -	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead); - -	/* ensure the last entry of the array contains a zeroed value */ -	qEntryPtr = rxQEntry; -	qEntryPtr[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK] = 0; - -	rxQReadStatus = ixQMgrQBurstRead(qId, -		 IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK, -		 qEntryPtr); - -#ifndef NDEBUG -	if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW) -	    && (rxQReadStatus != IX_SUCCESS)) -	{ -	    ixEthAccDataStats.unexpectedError++; -	    /*major error*/ -	    IX_ETH_ACC_FATAL_LOG( -		"ixEthRxFrameMultiBufferQMCallback:Error: %u\n", -		(UINT32)rxQReadStatus, 0, 0, 0, 0, 0); -	    return; -	} -#endif - -	/* convert and preload the next entry -	 * (the conversion function takes care about null pointers which -	 * are used to mark the end of the loop) -	 */ -	nextQEntry = *qEntryPtr; -	nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, -			  IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); - -	while(nextQEntry != 0) -	{ -	    /* get the next entry */ -	    qEntry = nextQEntry; -	    mbufPtr = nextMbufPtr; - -#ifndef NDEBUG -	    if (mbufPtr == NULL) -	    { -		ixEthAccDataStats.unexpectedError++; -		IX_ETH_ACC_FATAL_LOG( -		    "ixEthRxFrameMultiBufferQMCallback:Error: Null Mbuf Ptr\n", -		    0, 0, 0, 0, 0, 0); -		return; -	    } -#endif - -	    /* convert the next entry -	     * (the conversion function takes care about null pointers which -	     * are used to mark the end of the loop) -	     */ -	    nextQEntry = *(++qEntryPtr); -	    nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, -			      IX_ETHNPE_QM_Q_RXENET_ADDR_MASK); - -	    /* -	     * Get Port and Npe ID from message. -	     */ -	    npeId = ((IX_ETHNPE_QM_Q_RXENET_NPEID_MASK & -		      qEntry) >> -		     IX_ETHNPE_QM_Q_FIELD_NPEID_R); -	    portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); - -	    /* skip the remaining of the loop if the frame is -	     * to be filtered out -	     */ -	    if (ixEthRxFrameProcess(portId, mbufPtr)) -	    { -		/* store a mbuf pointer in an array */ -		*rxMbufPtr[portId]++ = mbufPtr; - -		/* -		 * increment priority stats -		 */ -		RX_STATS_INC(portId,rxPriority[IX_ETHACC_NE_QOS(mbufPtr)]); -	    } - -	    /* test for QoS enabled in ethAcc */ -	    if (ixEthAccDataInfo.schDiscipline == FIFO_PRIORITY) -	    { -		/* check if there is a higher priority queue -		 * which may require processing and then process it. -		 */ -		if (ixEthAccDataInfo.higherPriorityQueue[qId] < IX_QMGR_MAX_NUM_QUEUES) -		{ -		    ixEthRxMultiBufferQMCallback(ixEthAccDataInfo.higherPriorityQueue[qId], -						 callbackId); -		} -	    } -	} - -	/* check if any of the the arrays contains any entry */ -	for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) -	{ -	    if (rxMbufPtr[portId] != rxMbufPortArray[portId]) -	    { -		/* add a last NULL pointer at the end of the -		 * array of mbuf pointers -		 */ -		*rxMbufPtr[portId] = NULL; - -		/* -		 * increment callback count stats -		 */ -		RX_STATS_INC(portId,rxFrameClientCallback); - -		/* -		 * Call user level callback with an array of -		 * buffers (NULL terminated) -		 */ -		ixEthAccPortData[portId].ixEthAccRxData. -		    rxMultiBufferCallbackFn( -			    ixEthAccPortData[portId].ixEthAccRxData. -			           rxMultiBufferCallbackTag, -			    rxMbufPortArray[portId]); - -		/* reset the buffer pointer to the beginning of -		 * the array -		 */ -		rxMbufPtr[portId] = rxMbufPortArray[portId]; -	    } -	} - -    } while (rxQReadStatus == IX_SUCCESS); -} - - -/** - * @brief  rxFree low event handler - * - */ -void ixEthRxFreeQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) -{ -    IxEthAccPortId	portId = (IxEthAccPortId) callbackId; -    int		        lockVal; -    UINT32		maxQWritesToPerform = IX_ETH_ACC_MAX_RX_FREE_BUFFERS_LOAD; -    IX_STATUS	        qStatus = IX_SUCCESS; - -    /* -     * We have reached a low threshold on one of the Rx Free Qs -     */ - -    /*note that due to the fact that we are working off an Empty threshold, this callback -      need only write a single entry to the Rx Free queue in order to re-arm the notification -    */ - -    RX_STATS_INC(portId,rxFreeLowCallback); - -    /* -     * Get buffers from approprite S/W Rx freeBufferList Q. -     */ - -#ifndef NDEBUG -    if (!IX_ETH_ACC_IS_PORT_VALID(portId)) -    { -	ixEthAccDataStats.unexpectedError++; -	IX_ETH_ACC_FATAL_LOG( -	    "ixEthRxFreeQMCallback:Error: Invalid Port 0x%08X\n", -	    portId, 0, 0, 0, 0, 0); -	return; -    } -#endif -    IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); -    if (IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. -					ixEthAccRxData.freeBufferList)) -    { -	/* -	 * Turn off Q callback notification for Q in Question. -	 */ -	qStatus = ixQMgrNotificationDisable( -	    IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId)); - - -	IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); - -	if (qStatus != IX_SUCCESS) -	{ -	    RX_INC(portId,rxUnexpectedError); -	    IX_ETH_ACC_FATAL_LOG( -		"ixEthRxFreeQMCallback:Error: unexpected QM status 0x%08X\n", -		qStatus, 0, 0, 0, 0, 0); -	    return; -	} -    } -    else -    { -	IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); -	/* -	 * Load the H/W Q with buffers from the s/w Q. -	 */ - -	do -	{ -	    /* -	     * Consume Q entries. - Note Q contains Physical addresss, -	     * and have already been flushed to memory, -	     * And endianess converted if required. -	     */ -	    if (ixEthAccRxFreeFromSwQ(portId) != IX_SUCCESS) -	    { -		/* -		 * No more entries in s/w Q. -		 * Turn off Q callback indication -		 */ - -		IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); -		if (IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId]. -		    ixEthAccRxData.freeBufferList)) -		{ -		    qStatus = ixQMgrNotificationDisable( -			IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId)); -		} -		IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); -		break; -	    } -	} -	while (--maxQWritesToPerform); -    } -} -/** - * @fn Tx queue low event handler - * - */ -void -ixEthTxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) -{ -    IxEthAccPortId portId = (IxEthAccPortId) callbackId; -    int		   lockVal; -    UINT32	   maxQWritesToPerform = IX_ETH_ACC_MAX_TX_FRAME_TX_CONSUME_PER_CALLBACK; -    IX_STATUS	   qStatus = IX_SUCCESS; -    IxEthAccTxPriority highestPriority; - - -    /* -     * We have reached a low threshold on the Tx Q, and are being asked to -     * supply a buffer for transmission from our S/W TX queues -     */ -    TX_STATS_INC(portId,txLowThreshCallback); - -    /* -     * Get buffers from approprite Q. -     */ - -#ifndef NDEBUG -    if (!IX_ETH_ACC_IS_PORT_VALID(portId)) -    { -	ixEthAccDataStats.unexpectedError++; -	IX_ETH_ACC_FATAL_LOG( -	    "ixEthTxFrameQMCallback:Error: Invalid Port 0x%08X\n", -	    portId, 0, 0, 0, 0, 0); -	return; -    } -#endif - -    do -    { -	/* -	 * Consume Q entries. - Note Q contains Physical addresss, -	 * and have already been flushed to memory, -	 * and endianess already sone if required. -	 */ - -	IX_ETH_ACC_DATA_PLANE_LOCK(lockVal); - -	if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority) == -	   IX_ETH_ACC_FAIL) -	{ -	    /* -	     * No more entries in s/w Q. -	     * Turn off Q callback indication -	     */ -	    qStatus = ixQMgrNotificationDisable( -		IX_ETH_ACC_PORT_TO_TX_Q_ID(portId)); - -	    IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); - -	    if (qStatus != IX_SUCCESS) -	    { -		ixEthAccDataStats.unexpectedError++; -		IX_ETH_ACC_FATAL_LOG( -		    "ixEthTxFrameQMCallback:Error: unexpected QM status 0x%08X\n", -		    qStatus, 0, 0, 0, 0, 0); -	    } - -	    return; -	} -	else -	{ -	    IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal); -	    if (ixEthAccTxFromSwQ(portId,highestPriority)!=IX_SUCCESS) -	    { -                /* nothing left in the sw queue or the hw queues are -                * full. There is no point to continue to drain the -                * sw queues -                */ -		return; -	    } -	} -    } -    while (--maxQWritesToPerform); -} - -/** - * @brief TxDone event handler - * - * Design note : while processing the entry X, entry X+1 is preloaded - * into memory to reduce the number of stall cycles - * - */ - -void -ixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId) -{ -    IX_OSAL_MBUF    *mbufPtr; -    UINT32     qEntry; -    UINT32     *qEntryPtr; -    UINT32     txDoneQReadStatus; -    UINT32     portId; -    UINT32     npeId; - -    /* -     * Design note : entries are read in a static buffer, This buffer contains -     * an extra entyry (which is zeroed by the compiler), so the loop will -     * always terminate on a null entry, whatever the result of Burst read is. -     */ -    static UINT32 txDoneQEntry[IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK + 1]; - -    /* -     * Indication that Tx frames have been transmitted from the NPE. -     */ - -    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.txDoneCallbackCounter); - -    do{ -	qEntryPtr = txDoneQEntry; -	txDoneQReadStatus = ixQMgrQBurstRead(IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, -		     IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK, -		     qEntryPtr); - -#ifndef NDEBUG -	if (txDoneQReadStatus != IX_QMGR_Q_UNDERFLOW -	    && (txDoneQReadStatus != IX_SUCCESS)) -	{ -	    /*major error*/ -	    ixEthAccDataStats.unexpectedError++; -	    IX_ETH_ACC_FATAL_LOG( -		"ixEthTxFrameDoneQMCallback:Error: %u\n", -		(UINT32)txDoneQReadStatus, 0, 0, 0, 0, 0); -	    return; -	} -#endif - -	qEntry = *qEntryPtr; - -	while(qEntry != 0) -	{ -	    mbufPtr = ixEthAccEntryFromQConvert(qEntry, -		      IX_ETHNPE_QM_Q_TXENET_ADDR_MASK); - -#ifndef NDEBUG -	    if (mbufPtr == NULL) -	    { -		ixEthAccDataStats.unexpectedError++; -		IX_ETH_ACC_FATAL_LOG( -		    "ixEthTxFrameDoneQMCallback:Error: Null Mbuf Ptr\n", -		    0, 0, 0, 0, 0, 0); -		return; -	    } -#endif - -	    /* endianness conversions and stats updates */ -	    ixEthAccMbufFromTxQ(mbufPtr); - -	    /* -	     * Get NPE id from message, then convert to portId. -	     */ -	    npeId = ((IX_ETHNPE_QM_Q_TXENETDONE_NPEID_MASK & -		       qEntry) >> -		      IX_ETHNPE_QM_Q_FIELD_NPEID_R); -	    portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); - -#ifndef NDEBUG -	    /* Prudent to at least check the port is within range */ -	    if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) -	    { -		ixEthAccDataStats.unexpectedError++; -		IX_ETH_ACC_FATAL_LOG( -		    "ixEthTxFrameDoneQMCallback: Illegal port: %u\n", -		    (UINT32)portId, 0, 0, 0, 0, 0); -		return; -	    } -#endif - -	    TX_STATS_INC(portId,txDoneClientCallback); - -	    /* -	     * Call user level callback. -	     */ -	    ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn( -		ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag, -		mbufPtr); - -	    /* move to next queue entry */ -	    qEntry = *(++qEntryPtr); - -	} -    } while( txDoneQReadStatus == IX_SUCCESS ); -} - -IX_ETH_ACC_PUBLIC -void ixEthAccDataPlaneShow(void) -{ -    UINT32 numTx0Entries; -    UINT32 numTx1Entries; -    UINT32 numTxDoneEntries; -    UINT32 numRxEntries; -    UINT32 numRxFree0Entries; -    UINT32 numRxFree1Entries; -    UINT32 portId; -#ifdef __ixp46X -    UINT32 numTx2Entries; -    UINT32 numRxFree2Entries; -#endif -#ifndef NDEBUG -    UINT32 priority; -    UINT32 numBuffersInRx=0; -    UINT32 numBuffersInTx=0; -    UINT32 numBuffersInSwQ=0; -    UINT32 totalBuffers=0; -    UINT32 rxFreeCallbackCounter = 0; -    UINT32 txCallbackCounter = 0; -#endif -    UINT32 key; - -    /* snapshot of stats */ -    IxEthAccTxDataStats tx[IX_ETH_ACC_NUMBER_OF_PORTS]; -    IxEthAccRxDataStats rx[IX_ETH_ACC_NUMBER_OF_PORTS]; -    IxEthAccDataPlaneStats stats; - -    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) -    { -	return; -    } - -    /* get a reliable snapshot */ -    key = ixOsalIrqLock(); - -    numTx0Entries = 0; -    ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET0_Q, &numTx0Entries); -    numTx1Entries = 0; -    ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET1_Q, &numTx1Entries); -    numTxDoneEntries = 0; -    ixQMgrQNumEntriesGet( IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, &numTxDoneEntries); -    numRxEntries = 0; -    ixEthAccQMgrRxQEntryGet(&numRxEntries); -    numRxFree0Entries = 0; -    ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q, &numRxFree0Entries); -    numRxFree1Entries = 0; -    ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q, &numRxFree1Entries); - -#ifdef __ixp46X -    numTx2Entries = 0; -    ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET2_Q, &numTx2Entries); -    numRxFree2Entries = 0; -    ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q, &numRxFree2Entries); -#endif - -    for(portId=IX_ETH_PORT_1; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) -    { -	memcpy(&tx[portId], -	       &ixEthAccPortData[portId].ixEthAccTxData.stats, -	       sizeof(tx[portId])); -	memcpy(&rx[portId], -	       &ixEthAccPortData[portId].ixEthAccRxData.stats, -	       sizeof(rx[portId])); -    } -    memcpy(&stats, &ixEthAccDataStats, sizeof(stats)); - -    ixOsalIrqUnlock(key); - -#ifdef NDEBUG -    printf("Detailed statistics collection not supported in this load\n"); -#endif - -    /* print snapshot */ -    for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) -    { -        /* If not IXP42X A0 stepping, proceed to check for existence of coprocessors */ -        if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 != -	     (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK)) -	    || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ())) -        { -                if ((IX_ETH_PORT_1 == portId) && -                    (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == -                     IX_FEATURE_CTRL_COMPONENT_DISABLED)) -                { -                   continue ; -                } -                if ((IX_ETH_PORT_2 == portId) && -                    (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == -                     IX_FEATURE_CTRL_COMPONENT_DISABLED)) -                { -                    continue ; -                } -                if ((IX_ETH_PORT_3 == portId) && -                    (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) == -                     IX_FEATURE_CTRL_COMPONENT_DISABLED)) -                { -                    continue ; -                } -        } - -	printf("PORT %u --------------------------------\n", -	       portId); -#ifndef NDEBUG -	printf("Tx Done Frames                : %u\n", -	       tx[portId].txDoneClientCallback + -	       tx[portId].txDoneSwQDuringDisable + -	       tx[portId].txDoneDuringDisable); -	printf("Tx Frames                     : %u\n", -	       tx[portId].txQOK + tx[portId].txQDelayed); -	printf("Tx H/W Q Added OK             : %u\n", -	       tx[portId].txQOK); -	printf("Tx H/W Q Delayed              : %u\n", -	       tx[portId].txQDelayed); -	printf("Tx From S/W Q Added OK        : %u\n", -	       tx[portId].txFromSwQOK); -	printf("Tx From S/W Q Delayed         : %u\n", -	       tx[portId].txFromSwQDelayed); -	printf("Tx Overflow                   : %u\n", -	       tx[portId].txOverflow); -	printf("Tx Mutual Lock                : %u\n", -	       tx[portId].txLock); -	printf("Tx Late Ntf Enabled           : %u\n", -	       tx[portId].txLateNotificationEnabled); -	printf("Tx Low Thresh CB              : %u\n", -	       tx[portId].txLowThreshCallback); -	printf("Tx Done from H/W Q (Disable)  : %u\n", -	       tx[portId].txDoneDuringDisable); -	printf("Tx Done from S/W Q (Disable)  : %u\n", -	       tx[portId].txDoneSwQDuringDisable); -	for (priority = IX_ETH_ACC_TX_PRIORITY_0; -	     priority <= IX_ETH_ACC_TX_PRIORITY_7; -	     priority++) -	{ -	    if (tx[portId].txPriority[priority]) -	    { -		printf("Tx Priority %u                 : %u\n", -		       priority, -		       tx[portId].txPriority[priority]); -	    } -	} -#endif -	printf("Tx unexpected errors          : %u (should be 0)\n", -	       tx[portId].txUnexpectedError); - -#ifndef NDEBUG -	printf("Rx Frames                     : %u\n", -	       rx[portId].rxFrameClientCallback + -	       rx[portId].rxSwQDuringDisable+ -	       rx[portId].rxDuringDisable); -	printf("Rx Free Replenish             : %u\n", -	       rx[portId].rxFreeRepOK + rx[portId].rxFreeRepDelayed); -	printf("Rx Free H/W Q Added OK        : %u\n", -	       rx[portId].rxFreeRepOK); -	printf("Rx Free H/W Q Delayed         : %u\n", -	       rx[portId].rxFreeRepDelayed); -	printf("Rx Free From S/W Q Added OK   : %u\n", -	       rx[portId].rxFreeRepFromSwQOK); -	printf("Rx Free From S/W Q Delayed    : %u\n", -	       rx[portId].rxFreeRepFromSwQDelayed); -	printf("Rx Free Overflow              : %u\n", -	       rx[portId].rxFreeOverflow); -	printf("Rx Free Mutual Lock           : %u\n", -	       rx[portId].rxFreeLock); -	printf("Rx Free Late Ntf Enabled      : %u\n", -	       rx[portId].rxFreeLateNotificationEnabled); -	printf("Rx Free Low CB                : %u\n", -	       rx[portId].rxFreeLowCallback); -	printf("Rx From H/W Q (Disable)       : %u\n", -	       rx[portId].rxDuringDisable); -	printf("Rx From S/W Q (Disable)       : %u\n", -	       rx[portId].rxSwQDuringDisable); -	printf("Rx unlearned Mac Address      : %u\n", -	       rx[portId].rxUnlearnedMacAddress); -        printf("Rx Filtered (Rx => RxFree)    : %u\n", -            rx[portId].rxFiltered); - -	for (priority = IX_ETH_ACC_TX_PRIORITY_0; -	     priority <= IX_ETH_ACC_TX_PRIORITY_7; -	     priority++) -	{ -	    if (rx[portId].rxPriority[priority]) -	    { -		printf("Rx Priority %u                 : %u\n", -		       priority, -		       rx[portId].rxPriority[priority]); -	    } -	} -#endif -	printf("Rx unexpected errors          : %u (should be 0)\n", -	       rx[portId].rxUnexpectedError); - -#ifndef NDEBUG -	numBuffersInTx = tx[portId].txQOK + -	    tx[portId].txQDelayed - -	    tx[portId].txDoneClientCallback - -	    tx[portId].txDoneSwQDuringDisable - -	    tx[portId].txDoneDuringDisable; - -	printf("# Tx Buffers currently for transmission : %u\n", -	       numBuffersInTx); - -	numBuffersInRx = rx[portId].rxFreeRepOK + -	    rx[portId].rxFreeRepDelayed - -	    rx[portId].rxFrameClientCallback - -	    rx[portId].rxSwQDuringDisable - -	    rx[portId].rxDuringDisable; - -	printf("# Rx Buffers currently for reception    : %u\n", -	       numBuffersInRx); - -	totalBuffers += numBuffersInRx + numBuffersInTx; -#endif -    } - -    printf("---------------------------------------\n"); - -#ifndef NDEBUG -    printf("\n"); -    printf("Mbufs :\n"); -    printf("Tx Unchained mbufs            : %u\n", -	   stats.unchainedTxMBufs); -    printf("Tx Chained bufs               : %u\n", -	   stats.chainedTxMBufs); -    printf("TxDone Unchained mbufs        : %u\n", -	   stats.unchainedTxDoneMBufs); -    printf("TxDone Chained bufs           : %u\n", -	   stats.chainedTxDoneMBufs); -    printf("RxFree Unchained mbufs        : %u\n", -	   stats.unchainedRxFreeMBufs); -    printf("RxFree Chained bufs           : %u\n", -	   stats.chainedRxFreeMBufs); -    printf("Rx Unchained mbufs            : %u\n", -	   stats.unchainedRxMBufs); -    printf("Rx Chained bufs               : %u\n", -	   stats.chainedRxMBufs); - -    printf("\n"); -    printf("Software queue usage :\n"); -    printf("Buffers added to S/W Q        : %u\n", -	   stats.addToSwQ); -    printf("Buffers removed from S/W Q    : %u\n", -	   stats.removeFromSwQ); - -    printf("\n"); -    printf("Hardware queues callbacks :\n"); - -    for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) -    { -	rxFreeCallbackCounter += rx[portId].rxFreeLowCallback; -	txCallbackCounter += tx[portId].txLowThreshCallback; -    } -    printf("Tx Done QM Callback invoked   : %u\n", -	   stats.txDoneCallbackCounter); -    printf("Tx QM Callback invoked        : %u\n", -	   txCallbackCounter); -    printf("Rx QM Callback invoked        : %u\n", -	   stats.rxCallbackCounter); -    printf("Rx QM Callback burst read     : %u\n", -	   stats.rxCallbackBurstRead); -    printf("Rx Free QM Callback invoked   : %u\n", -	   rxFreeCallbackCounter); -#endif -    printf("Unexpected errors in CB       : %u (should be 0)\n", -	   stats.unexpectedError); -    printf("\n"); - -    printf("Hardware queues levels :\n"); -    printf("Transmit Port 1 Q             : %u \n",numTx0Entries); -    printf("Transmit Port 2 Q             : %u \n",numTx1Entries); -#ifdef __ixp46X -    printf("Transmit Port 3 Q             : %u \n",numTx2Entries); -#endif -    printf("Transmit Done Q               : %u \n",numTxDoneEntries); -    printf("Receive Q                     : %u \n",numRxEntries); -    printf("Receive Free Port 1 Q         : %u \n",numRxFree0Entries); -    printf("Receive Free Port 2 Q         : %u \n",numRxFree1Entries); -#ifdef __ixp46X -    printf("Receive Free Port 3 Q         : %u \n",numRxFree2Entries); -#endif - -#ifndef NDEBUG -    printf("\n"); -    printf("# Total Buffers accounted for : %u\n", -	   totalBuffers); - -    numBuffersInSwQ = ixEthAccDataStats.addToSwQ - -	ixEthAccDataStats.removeFromSwQ; - -    printf("    Buffers in S/W Qs         : %u\n", -	   numBuffersInSwQ); -    printf("    Buffers in H/W Qs or NPEs : %u\n", -	   totalBuffers - numBuffersInSwQ); -#endif - -    printf("Rx QoS Discipline             : %s\n", -	   (ixEthAccDataInfo.schDiscipline == -	    FIFO_PRIORITY ) ? "Enabled" : "Disabled"); - -    for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) -    { -	printf("Tx QoS Discipline port %u      : %s\n", -	       portId, -	       (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline == -		FIFO_PRIORITY ) ? "Enabled" : "Disabled"); -    } -    printf("\n"); -} - - - - - |