diff options
Diffstat (limited to 'drivers/net/npe/IxEthAccCommon.c')
| -rw-r--r-- | drivers/net/npe/IxEthAccCommon.c | 1049 | 
1 files changed, 1049 insertions, 0 deletions
| diff --git a/drivers/net/npe/IxEthAccCommon.c b/drivers/net/npe/IxEthAccCommon.c new file mode 100644 index 000000000..211203dff --- /dev/null +++ b/drivers/net/npe/IxEthAccCommon.c @@ -0,0 +1,1049 @@ +/** + * @file IxEthAccCommon.c + * + * @author Intel Corporation + * @date 12-Feb-2002 + * + * @brief This file contains the implementation common support routines for the 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 -- + */ + +/* + * Component header files + */ + +#include "IxOsal.h" +#include "IxEthAcc.h" +#include "IxEthDB.h" +#include "IxNpeMh.h" +#include "IxEthDBPortDefs.h" +#include "IxFeatureCtrl.h" +#include "IxEthAcc_p.h" +#include "IxEthAccQueueAssign_p.h" + +#include "IxEthAccDataPlane_p.h" +#include "IxEthAccMii_p.h" + +/** + * @addtogroup IxEthAccPri + *@{ + */ + +extern IxEthAccInfo   ixEthAccDataInfo; + +/** + * + * @brief Maximum number of RX queues set to be the maximum number + * of traffic calsses. + * + */ +#define IX_ETHACC_MAX_RX_QUEUES \ +      (IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY \ +      - IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY \ +      + 1) + +/** + * + * @brief Maximum number of 128 entry RX queues + * + */ +#define IX_ETHACC_MAX_LARGE_RX_QUEUES 4 + +/** + * + * @brief Data structure template for Default RX Queues + * + */ +IX_ETH_ACC_PRIVATE +IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate = +  { +    IX_ETH_ACC_RX_FRAME_ETH_Q,	     /**< Queue ID */ +    "Eth Rx Q", +    ixEthRxFrameQMCallback,          /**< Functional callback */ +    (IxQMgrCallbackId) 0,	     /**< Callback tag	      */ +    IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ +    TRUE,			     /**< Enable Q notification at startup */ +    IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback   */ +    IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ +    IX_QMGR_Q_WM_LEVEL1,	     /**< Q High water mark - needed by NPE */ +  }; + +/** + * + * @brief Data structure template for Small RX Queues + * + */ +IX_ETH_ACC_PRIVATE +IxEthAccQregInfo ixEthAccQmgrRxSmallTemplate = +  { +    IX_ETH_ACC_RX_FRAME_ETH_Q,	     /**< Queue ID */ +    "Eth Rx Q", +    ixEthRxFrameQMCallback,          /**< Functional callback */ +    (IxQMgrCallbackId) 0,	     /**< Callback tag	      */ +    IX_QMGR_Q_SIZE64,		     /**< Allocate Smaller Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ +    TRUE,			     /**< Enable Q notification at startup */ +    IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback   */ +    IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ +    IX_QMGR_Q_WM_LEVEL1,	     /**< Q High water mark - needed by NPE */ +  }; + + +/** + * + * @brief Data structure used to register & initialize the Queues + * + */ +IX_ETH_ACC_PRIVATE +IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= +{ +  { +    IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q, +    "Eth Rx Fr Q 1", +    ixEthRxFreeQMCallback, +    (IxQMgrCallbackId) IX_ETH_PORT_1, +    IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ +    FALSE,			     /**< Disable Q notification at startup */ +    IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback  */ +    IX_QMGR_Q_WM_LEVEL0,	     /***< Q Low water mark */ +    IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ +  }, + +  { +    IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q, +    "Eth Rx Fr Q 2", +    ixEthRxFreeQMCallback, +    (IxQMgrCallbackId) IX_ETH_PORT_2, +    IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ +    FALSE,			     /**< Disable Q notification at startup */ +    IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE,  /**< Q Condition to drive callback  */ +    IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ +    IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ +  }, +#ifdef __ixp46X +  { +    IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q, +    "Eth Rx Fr Q 3", +    ixEthRxFreeQMCallback, +    (IxQMgrCallbackId) IX_ETH_PORT_3, +    IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ +    FALSE,			     /**< Disable Q notification at startup */ +    IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE,  /**< Q Condition to drive callback  */ +    IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ +    IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ +  }, +#endif +  { +     IX_ETH_ACC_TX_FRAME_ENET0_Q, +    "Eth Tx Q 1", +     ixEthTxFrameQMCallback, +     (IxQMgrCallbackId) IX_ETH_PORT_1, +    IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ +    FALSE,			     /**< Disable Q notification at startup */ +    IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE,	 /**< Q Condition to drive callback  */ +    IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ +    IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ +  }, + +  { +     IX_ETH_ACC_TX_FRAME_ENET1_Q, +    "Eth Tx Q 2", +     ixEthTxFrameQMCallback, +     (IxQMgrCallbackId) IX_ETH_PORT_2, +    IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ +    FALSE,			     /**< Disable Q notification at startup */ +    IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE,	     /**< Q Condition to drive callback  */ +    IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ +    IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ +  }, +#ifdef __ixp46X +  { +     IX_ETH_ACC_TX_FRAME_ENET2_Q, +    "Eth Tx Q 3", +     ixEthTxFrameQMCallback, +     (IxQMgrCallbackId) IX_ETH_PORT_3, +    IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /** Queue Entry Sizes - all Q entries are single ord entries   */ +    FALSE,			     /** Disable Q notification at startup */ +    IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE,	     /** Q Condition to drive callback  */ +    IX_QMGR_Q_WM_LEVEL0,	     /* No queues use almost empty */ +    IX_QMGR_Q_WM_LEVEL64,	      /** Q High water mark - needed used  */ +  }, +#endif +  { +     IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, +    "Eth Tx Done Q", +     ixEthTxFrameDoneQMCallback, +     (IxQMgrCallbackId) 0, +    IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ +    IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ +    TRUE,			     /**< Enable Q notification at startup */ +    IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE, /**< Q Condition to drive callback  */ +    IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ +    IX_QMGR_Q_WM_LEVEL2,	     /**< Q High water mark - needed by NPE */ +  }, + +  {  /* Null Termination entry +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  } + +}; + +/** + * + * @brief Data structure used to register & initialize the Queues + * + * The structure will be filled at run time depending on the NPE + * image already loaded and the QoS configured in ethDB. + * + */ +IX_ETH_ACC_PRIVATE +IxEthAccQregInfo ixEthAccQmgrRxQueuesInfo[IX_ETHACC_MAX_RX_QUEUES+1]= +{ +  {  /* PlaceHolder for rx queues +      * depending on the QoS configured +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  }, + +  {  /* PlaceHolder for rx queues +      * depending on the QoS configured +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  }, + +  {  /* PlaceHolder for rx queues +      * depending on the QoS configured +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  }, + +  {  /* PlaceHolder for rx queues +      * depending on the QoS configured +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  }, + +  {  /* PlaceHolder for rx queues +      * depending on the QoS configured +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  }, + +  {  /* PlaceHolder for rx queues +      * depending on the QoS configured +      */ +      (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  }, + +  {  /* PlaceHolder for rx queues +      * depending on the QoS configured +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  }, + +  {  /* PlaceHolder for rx queues +      * depending on the QoS configured +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  }, + +  {  /* Null Termination entry +      */ +     (IxQMgrQId)0, +     (char *) NULL, +     (IxQMgrCallback) NULL, +     (IxQMgrCallbackId) 0, +     0, +     0, +     0, +     0, +     0, +     0 +  } + +}; + +/* forward declarations */ +IX_ETH_ACC_PRIVATE IxEthAccStatus +ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes); + +/** + * @fn ixEthAccQMgrQueueSetup(void) + * + * @brief Setup one queue and its event, and register the callback required + * by this component to the QMgr + * + * @internal + */ +IX_ETH_ACC_PRIVATE IxEthAccStatus +ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes) +{ +    /* +     * Configure each Q. +     */ +    if ( ixQMgrQConfig( qInfoDes->qName, +			qInfoDes->qId, +			qInfoDes->qSize, +			qInfoDes->qWords) != IX_SUCCESS) +    { +	return IX_ETH_ACC_FAIL; +    } + +    if ( ixQMgrWatermarkSet( qInfoDes->qId, +			     qInfoDes->AlmostEmptyThreshold, +			     qInfoDes->AlmostFullThreshold +			     ) != IX_SUCCESS) +    { +	return IX_ETH_ACC_FAIL; +    } + +    /* +     * Set dispatcher priority. +     */ +    if ( ixQMgrDispatcherPrioritySet( qInfoDes->qId, +				      IX_ETH_ACC_QM_QUEUE_DISPATCH_PRIORITY) +	 != IX_SUCCESS) +    { +	return IX_ETH_ACC_FAIL; +    } + +    /* +     * Register callbacks for each Q. +     */ +    if ( ixQMgrNotificationCallbackSet(qInfoDes->qId, +				       qInfoDes->qCallback, +				       qInfoDes->callbackTag) +	 != IX_SUCCESS ) +    { +	return IX_ETH_ACC_FAIL; +    } + +    /* +     * Set notification condition for Q +     */ +    if ( qInfoDes->qNotificationEnableAtStartup == TRUE ) +    { +	if (   ixQMgrNotificationEnable(qInfoDes->qId, +					qInfoDes->qConditionSource) +	       != IX_SUCCESS ) +	{ +	    return IX_ETH_ACC_FAIL; +	} +    } + +    return(IX_ETH_ACC_SUCCESS); +} + +/** + * @fn ixEthAccQMgrQueuesConfig(void) + * + * @brief Setup all the queues and register all callbacks required + * by this component to the QMgr + * + * The RxFree queues, tx queues, rx queues are configured statically + * + * Rx queues configuration is driven by QoS setup. + * Many Rx queues may be required when QoS is enabled (this depends + * on IxEthDB setup and the images being downloaded). The configuration + * of the rxQueues is done in many steps as follows: + * + * @li select all Rx queues as configured by ethDB for all ports + * @li sort the queues by traffic class + * @li build the priority dependency for all queues + * @li fill the configuration for all rx queues + * @li configure all statically configured queues + * @li configure all dynamically configured queues + * + * @param none + * + * @return IxEthAccStatus + * + * @internal + */ +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccQMgrQueuesConfig(void) +{ +    struct +    { +	int npeCount; +	UINT32 npeId; +	IxQMgrQId qId; +	IxEthDBProperty trafficClass; +    } rxQueues[IX_ETHACC_MAX_RX_QUEUES]; + +    UINT32 rxQueue = 0; +    UINT32 rxQueueCount = 0; +    IxQMgrQId ixQId =IX_QMGR_MAX_NUM_QUEUES; +    IxEthDBStatus ixEthDBStatus = IX_ETH_DB_SUCCESS; +    IxEthDBPortId ixEthDbPortId = 0; +    IxEthAccPortId ixEthAccPortId = 0; +    UINT32 ixNpeId = 0; +    UINT32 ixHighestNpeId = 0; +    UINT32 sortIterations = 0; +    IxEthAccStatus ret = IX_ETH_ACC_SUCCESS; +    IxEthAccQregInfo *qInfoDes = NULL; +    IxEthDBProperty ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; +    IxEthDBPropertyType ixEthDBPropertyType = IX_ETH_DB_INTEGER_PROPERTY; +    UINT32 ixEthDBParameter = 0; +    BOOL completelySorted = FALSE; + +    /* Fill the corspondance between ports and queues +     * This defines the mapping from port to queue Ids. +     */ + +    ixEthAccPortData[IX_ETH_PORT_1].ixEthAccRxData.rxFreeQueue +	= IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q; +    ixEthAccPortData[IX_ETH_PORT_2].ixEthAccRxData.rxFreeQueue +	= IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q; +#ifdef __ixp46X +    ixEthAccPortData[IX_ETH_PORT_3].ixEthAccRxData.rxFreeQueue +	= IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q; +#endif +    ixEthAccPortData[IX_ETH_PORT_1].ixEthAccTxData.txQueue +	= IX_ETH_ACC_TX_FRAME_ENET0_Q; +    ixEthAccPortData[IX_ETH_PORT_2].ixEthAccTxData.txQueue +	= IX_ETH_ACC_TX_FRAME_ENET1_Q; +#ifdef __ixp46X +    ixEthAccPortData[IX_ETH_PORT_3].ixEthAccTxData.txQueue +	= IX_ETH_ACC_TX_FRAME_ENET2_Q; +#endif +    /* Fill the corspondance between ports and NPEs +     * This defines the mapping from port to npeIds. +     */ + +    ixEthAccPortData[IX_ETH_PORT_1].npeId = IX_NPEMH_NPEID_NPEB; +    ixEthAccPortData[IX_ETH_PORT_2].npeId = IX_NPEMH_NPEID_NPEC; +#ifdef __ixp46X +    ixEthAccPortData[IX_ETH_PORT_3].npeId = IX_NPEMH_NPEID_NPEA; +#endif +    /* set the default rx scheduling discipline */ +    ixEthAccDataInfo.schDiscipline = FIFO_NO_PRIORITY; + +    /* +     * Queue Selection step: +     * +     * The following code selects all the queues and build +     * a temporary array which contains for each queue +     * - the queue Id, +     * - the highest traffic class (in case of many +     * priorities configured for the same queue on different +     * ports) +     * - the number of different Npes which are +     * configured to write to this queue. +     * +     * The output of this loop is a temporary array of RX queues +     * in any order. +     * +     */ +#ifdef CONFIG_IXP425_COMPONENT_ETHDB +    for (ixEthAccPortId = 0; +	 (ixEthAccPortId < IX_ETH_ACC_NUMBER_OF_PORTS) +	     && (ret == IX_ETH_ACC_SUCCESS); +	 ixEthAccPortId++) +    { +	/* map between ethDb and ethAcc port Ids */ +	ixEthDbPortId = (IxEthDBPortId)ixEthAccPortId; + +	/* map between npeId and ethAcc port Ids */ +	ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId); + +	/* Iterate thru the different priorities */ +	for (ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; +	     ixEthDBTrafficClass <= IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY; +	     ixEthDBTrafficClass++) +	{ +	    ixEthDBStatus = ixEthDBFeaturePropertyGet( +	      ixEthDbPortId, +	      IX_ETH_DB_VLAN_QOS, +	      ixEthDBTrafficClass, +	      &ixEthDBPropertyType, +	      (void *)&ixEthDBParameter); + +	    if (ixEthDBStatus == IX_ETH_DB_SUCCESS) +	    { +		/* This port and QoS class are mapped to +		 * a RX queue. +		 */ +		if (ixEthDBPropertyType == IX_ETH_DB_INTEGER_PROPERTY) +		{ +		    /* remember the highest npe Id supporting ethernet */ +		    if (ixNpeId > ixHighestNpeId) +		    { +			ixHighestNpeId = ixNpeId; +		    } + +		    /* search the queue in the list of queues +		     * already used by an other port or QoS +		     */ +		    for (rxQueue = 0; +			 rxQueue < rxQueueCount; +			 rxQueue++) +		    { +			if (rxQueues[rxQueue].qId == (IxQMgrQId)ixEthDBParameter) +			{ +			    /* found an existing setup, update the number of ports +			     * for this queue if the port maps to +			     * a different NPE. +			     */ +			    if (rxQueues[rxQueue].npeId != ixNpeId) +			    { +				rxQueues[rxQueue].npeCount++; +				rxQueues[rxQueue].npeId = ixNpeId; +			    } +			    /* get the highest traffic class for this queue */ +			    if (rxQueues[rxQueue].trafficClass > ixEthDBTrafficClass) +			    { +				rxQueues[rxQueue].trafficClass = ixEthDBTrafficClass; +			    } +			    break; +			} +		    } +		    if (rxQueue == rxQueueCount) +		    { +			/* new queue not found in the current list, +			 * add a new entry. +			 */ +			IX_OSAL_ASSERT(rxQueueCount < IX_ETHACC_MAX_RX_QUEUES); +			rxQueues[rxQueueCount].qId = ixEthDBParameter; +			rxQueues[rxQueueCount].npeCount = 1; +			rxQueues[rxQueueCount].npeId = ixNpeId; +			rxQueues[rxQueueCount].trafficClass = ixEthDBTrafficClass; +			rxQueueCount++; +		    } +		} +		else +		{ +		    /* unexpected property type (not Integer) */ +		    ret = IX_ETH_ACC_FAIL; + +                    IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: unexpected property type returned by EthDB\n", 0, 0, 0, 0, 0, 0); + +		    /* no point to continue to iterate */ +		    break; +		} +	    } +	    else +	    { +		/* No Rx queue configured for this port +		 * and this traffic class. Do nothing. +		 */ +	    } +	} + +        /* notify EthDB that queue initialization is complete and traffic class allocation is frozen */ +        ixEthDBFeaturePropertySet(ixEthDbPortId, +            IX_ETH_DB_VLAN_QOS, +            IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE, +            NULL /* ignored */); +    } + +#else + +    ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId); +    rxQueues[0].qId = 4; +    rxQueues[0].npeCount = 1; +    rxQueues[0].npeId = ixNpeId; +    rxQueues[0].trafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; +    rxQueueCount++; + +#endif + +    /* check there is at least 1 rx queue : there is no point +     * to continue if there is no rx queue configured +     */ +    if ((rxQueueCount == 0) || (ret == IX_ETH_ACC_FAIL)) +    { +        IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: no queues configured, bailing out\n", 0, 0, 0, 0, 0, 0); +	return (IX_ETH_ACC_FAIL); +    } + +    /* Queue sort step: +     * +     * Re-order the array of queues by decreasing traffic class +     * using a bubble sort. (trafficClass 0 is the lowest +     * priority traffic, trafficClass 7 is the highest priority traffic) +     * +     * Primary sort order is traffic class +     * Secondary sort order is npeId +     * +     * Note that a bubble sort algorithm is not very efficient when +     * the number of queues grows . However, this is not a very bad choice +     * considering the very small number of entries to sort. Also, bubble +     * sort is extremely fast when the list is already sorted. +     * +     * The output of this loop is a sorted array of queues. +     * +     */ +    sortIterations = 0; +    do +    { +	sortIterations++; +	completelySorted = TRUE; +	for (rxQueue = 0; +	     rxQueue < rxQueueCount - sortIterations; +	     rxQueue++) +	{ +	    /* compare adjacent elements */ +	    if ((rxQueues[rxQueue].trafficClass < +		rxQueues[rxQueue+1].trafficClass) +		|| ((rxQueues[rxQueue].trafficClass == +		     rxQueues[rxQueue+1].trafficClass) +		    &&(rxQueues[rxQueue].npeId < +		       rxQueues[rxQueue+1].npeId))) +	    { +		/* swap adjacent elements */ +		int npeCount = rxQueues[rxQueue].npeCount; +		UINT32 npeId = rxQueues[rxQueue].npeId; +		IxQMgrQId qId = rxQueues[rxQueue].qId; +		IxEthDBProperty trafficClass = rxQueues[rxQueue].trafficClass; +		rxQueues[rxQueue].npeCount = rxQueues[rxQueue+1].npeCount; +		rxQueues[rxQueue].npeId = rxQueues[rxQueue+1].npeId; +		rxQueues[rxQueue].qId = rxQueues[rxQueue+1].qId; +		rxQueues[rxQueue].trafficClass = rxQueues[rxQueue+1].trafficClass; +		rxQueues[rxQueue+1].npeCount = npeCount; +		rxQueues[rxQueue+1].npeId = npeId; +		rxQueues[rxQueue+1].qId = qId; +		rxQueues[rxQueue+1].trafficClass = trafficClass; +		completelySorted = FALSE; +	    } +	} +    } +    while (!completelySorted); + +    /* Queue traffic class list: +     * +     * Fill an array of rx queues linked by ascending traffic classes. +     * +     * If the queues are configured as follows +     *   qId 6 -> traffic class 0 (lowest) +     *   qId 7 -> traffic class 0 +     *   qId 8 -> traffic class 6 +     *   qId 12 -> traffic class 7 (highest) +     * +     * Then the output of this loop will be +     * +     * higherPriorityQueue[6] = 8 +     * higherPriorityQueue[7] = 8 +     * higherPriorityQueue[8] = 12 +     * higherPriorityQueue[12] = Invalid queueId +     * higherPriorityQueue[...] = Invalid queueId +     * +     * Note that this queue ordering does not handle all possibilities +     * that could result from different rules associated with different +     * ports, and inconsistencies in the rules. In all cases, the +     * output of this  algorithm is a simple linked list of queues, +     * without closed circuit. + +     * This list is implemented as an array with invalid values initialized +     * with an "invalid" queue id which is the maximum number of queues. +     * +     */ + +    /* +     * Initialise the rx queue list. +     */ +    for (rxQueue = 0; rxQueue < IX_QMGR_MAX_NUM_QUEUES; rxQueue++) +    { +	ixEthAccDataInfo.higherPriorityQueue[rxQueue] = IX_QMGR_MAX_NUM_QUEUES; +    } + +    /* build the linked list for this NPE. +     */ +    for (ixNpeId = 0; +	 ixNpeId <= ixHighestNpeId; +	 ixNpeId++) +    { +	/* iterate thru the sorted list of queues +	 */ +	ixQId = IX_QMGR_MAX_NUM_QUEUES; +	for (rxQueue = 0; +	     rxQueue < rxQueueCount; +	     rxQueue++) +	{ +	    if (rxQueues[rxQueue].npeId == ixNpeId) +	    { +		ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId; +		/* iterate thru queues with the same traffic class +		 * than the current queue. (queues are ordered by descending +		 * traffic classes and npeIds). +		 */ +		while ((rxQueue < rxQueueCount - 1) +		       && (rxQueues[rxQueue].trafficClass +			   == rxQueues[rxQueue+1].trafficClass) +		       && (ixNpeId == rxQueues[rxQueue].npeId)) +		{ +		    rxQueue++; +		    ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId; +		} +		ixQId = rxQueues[rxQueue].qId; +	    } +	} +    } + +    /* point on the first dynamic queue description */ +    qInfoDes = ixEthAccQmgrRxQueuesInfo; + +    /* update the list of queues with the rx queues */ +    for (rxQueue = 0; +	 (rxQueue < rxQueueCount) && (ret == IX_ETH_ACC_SUCCESS); +	 rxQueue++) +    { +	/* Don't utilize more than IX_ETHACC_MAX_LARGE_RX_QUEUES queues +	 * with the full 128 entries.  For the lower priority queues, use +	 * a smaller number of entries.  This ensures queue resources +	 * remain available for other components. +	 */ +	if( (rxQueueCount > IX_ETHACC_MAX_LARGE_RX_QUEUES) && +	    (rxQueue < rxQueueCount - IX_ETHACC_MAX_LARGE_RX_QUEUES) ) +	{ +	    /* add the small RX Queue setup template to the list of queues */ +	    memcpy(qInfoDes, &ixEthAccQmgrRxSmallTemplate, sizeof(*qInfoDes)); +	} else { +	    /* add the default RX Queue setup template to the list of queues */ +	    memcpy(qInfoDes, &ixEthAccQmgrRxDefaultTemplate, sizeof(*qInfoDes)); +	} + +	/* setup the RxQueue ID */ +	qInfoDes->qId = rxQueues[rxQueue].qId; + +	/* setup the RxQueue watermark level +	 * +	 * Each queue can be filled by many NPEs. To avoid the +	 * NPEs to write to a full queue, need to set the +	 * high watermark level for nearly full condition. +	 * (the high watermark level are a power of 2 +	 * starting from the top of the queue) +	 * +	 * Number of     watermark +         *   ports        level +         *    1             0 +	 *    2             1 +	 *    3             2 +	 *    4             4 +	 *    5             4 +	 *    6             8 +	 *    n          approx. 2**ceil(log2(n)) +	 */ +	if (rxQueues[rxQueue].npeCount == 1) +	{ +	    qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL0; +	} +	else if (rxQueues[rxQueue].npeCount == 2) +	{ +	    qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL1; +	} +	else if (rxQueues[rxQueue].npeCount == 3) +	{ +	    qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL2; +	} +	else +	{ +	    /* reach the maximum number for CSR 2.0 */ +            IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: maximum number of NPEs per queue reached, bailing out\n", 0, 0, 0, 0, 0, 0); +	    ret = IX_ETH_ACC_FAIL; +	    break; +	} + +	/* move to next queue entry */ +	++qInfoDes; +    } + +    /* configure the static list (RxFree, Tx and TxDone queues) */ +    for (qInfoDes = ixEthAccQmgrStaticInfo; +	 (qInfoDes->qCallback != (IxQMgrCallback) NULL ) +	     && (ret == IX_ETH_ACC_SUCCESS); +	 ++qInfoDes) +    { +	ret = ixEthAccQMgrQueueSetup(qInfoDes); +    } + +    /* configure the dynamic list (Rx queues) */ +    for (qInfoDes = ixEthAccQmgrRxQueuesInfo; +	 (qInfoDes->qCallback != (IxQMgrCallback) NULL ) +	     && (ret == IX_ETH_ACC_SUCCESS); +	 ++qInfoDes) +    { +	ret = ixEthAccQMgrQueueSetup(qInfoDes); +    } + +    return(ret); +} + +/** + * @fn ixEthAccQMgrRxQEntryGet(UINT32 *rxQueueEntries) + * + * @brief Add and return the total number of entries in all Rx queues + * + * @param UINT32 rxQueueEntries[in] number of entries in all queues + * + * @return void + * + * @note Rx queues configuration is driven by Qos Setup. There is a + * variable number of rx queues which are set at initialisation. + * + * @internal + */ +IX_ETH_ACC_PUBLIC +void ixEthAccQMgrRxQEntryGet(UINT32 *numRxQueueEntries) +{ +    UINT32 rxQueueLevel; +    IxEthAccQregInfo *qInfoDes;; + +    *numRxQueueEntries = 0; + +    /* iterate thru rx queues */ +    for (qInfoDes = ixEthAccQmgrRxQueuesInfo; +	 qInfoDes->qCallback != (IxQMgrCallback)NULL; +	 ++qInfoDes) +    { +	/* retrieve the rx queue level */ +	rxQueueLevel = 0; +	ixQMgrQNumEntriesGet(qInfoDes->qId, &rxQueueLevel); +	(*numRxQueueEntries) += rxQueueLevel; +    } +} + +/** + * @fn ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback) + * + * @brief Change the callback registered to all rx queues. + * + * @param IxQMgrCallback ixQMgrCallback[in] QMgr callback to register + * + * @return IxEthAccStatus + * + * @note The user may decide to use different Rx mechanisms + * (e.g. receive many frames at the same time , or receive + *  one frame at a time, depending on the overall application + *  performances). A different QMgr callback is registered. This + *  way, there is no excessive pointer checks in the datapath. + * + * @internal + */ +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback) +{ +    IxEthAccQregInfo *qInfoDes; +    IxEthAccStatus ret = IX_ETH_ACC_SUCCESS; + +    /* parameter check */ +    if (NULL == ixQMgrCallback) +    { +	ret = IX_ETH_ACC_FAIL; +    } + +    /* iterate thru rx queues */ +    for (qInfoDes = ixEthAccQmgrRxQueuesInfo; +	 (qInfoDes->qCallback != (IxQMgrCallback) NULL ) +	     && (ret == IX_ETH_ACC_SUCCESS); +	 ++qInfoDes) +    { +	/* register the rx callback for all queues */ +	if (ixQMgrNotificationCallbackSet(qInfoDes->qId, +					     ixQMgrCallback, +					     qInfoDes->callbackTag +					     ) != IX_SUCCESS) +	{ +	    ret = IX_ETH_ACC_FAIL; +	} +    } +    return(ret); +} + +/** + * @fn ixEthAccSingleEthNpeCheck(IxEthAccPortId portId) + * + * @brief Check the npe exists for this port + * + * @param IxEthAccPortId portId[in] port + * + * @return IxEthAccStatus + * + * @internal + */ +IX_ETH_ACC_PUBLIC +IxEthAccStatus ixEthAccSingleEthNpeCheck(IxEthAccPortId 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_ENABLED)) +            { +                return IX_ETH_ACC_SUCCESS; +            } + +            if ((IX_ETH_PORT_2 == portId) && +                (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == +                 IX_FEATURE_CTRL_COMPONENT_ENABLED)) +            { +                return IX_ETH_ACC_SUCCESS; +            } + +            if ((IX_ETH_PORT_3 == portId) && +                (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) == +                 IX_FEATURE_CTRL_COMPONENT_ENABLED)) +            { +                return IX_ETH_ACC_SUCCESS; +            } + +            return IX_ETH_ACC_FAIL; +      } + +    return IX_ETH_ACC_SUCCESS; +} + +/** + * @fn ixEthAccStatsShow(void) + * + * @brief Displays all EthAcc stats + * + * @return void + * + */ +void ixEthAccStatsShow(IxEthAccPortId portId) +{ +    ixEthAccMdioShow(); + +    printf("\nPort %u\nUnicast MAC : ", portId); +    ixEthAccPortUnicastAddressShow(portId); +    ixEthAccPortMulticastAddressShow(portId); +    printf("\n"); + +    ixEthAccDataPlaneShow(); +} + + + |