📄 ixethacccommon.c
字号:
/** * @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.1 * * -- Copyright Notice -- * * @par * Copyright (c) 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"#include "IxNpeDl.h" /** * @addtogroup IxEthAccPri *@{ */extern IxEthAccInfo ixEthAccDataInfo;/** * @brief Stores Rx Queue info for all rx queues */IX_ETH_ACC_PRIVATEIxEthAccRxQueue ixEthAccRxQueues[IX_ETHACC_MAX_RX_QUEUES+1];/* storage for the qmgr register base addresses */UINT32 ixEthAccQMIntEnableBaseAddress;UINT32 ixEthAccQMIntStatusBaseAddress;/** * * @brief Data structure template for RX Queues * */IX_ETH_ACC_PRIVATEIxEthAccQregInfo ixEthAccQmgrRxTemplate ={ IX_QMGR_QUEUE_INVALID, /**< 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_QMGR_Q_SOURCE_ID_NOT_E, /**< 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 RX Free Queues * */IX_ETH_ACC_PRIVATEIxEthAccQregInfo ixEthAccQmgrRxFreeTemplate ={ IX_QMGR_QUEUE_INVALID, "Eth Rx Free Q", ixEthRxFreeQMCallback, (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 */ FALSE, /**< Disable Q notification at startup */ IX_QMGR_Q_SOURCE_ID_E, /**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /***< Q Low water mark */ IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */};/** * * @brief Data structure template for TX Queues * */IX_ETH_ACC_PRIVATEIxEthAccQregInfo ixEthAccQmgrTxTemplate ={ IX_QMGR_QUEUE_INVALID, "Eth Tx Q", ixEthTxFrameQMCallback, (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 */ FALSE, /**< Disable Q notification at startup */ IX_QMGR_Q_SOURCE_ID_E, /**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */};/** * * @brief Data structure template for TxDone Queue * */IX_ETH_ACC_PRIVATEIxEthAccQregInfo ixEthAccQmgrTxDoneTemplate ={ IX_ETH_ACC_TX_DONE_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_QMGR_Q_SOURCE_ID_NOT_E, /**< 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 */};/** * @brief RX Queue size table indexed by relative queue priority */IX_ETH_ACC_PRIVATE constIxQMgrQSizeInWords ixEthAccRxQueueSizeTable[IX_ETHACC_MAX_RX_QUEUES] ={ IX_QMGR_Q_SIZE128, /* highest priority */ IX_QMGR_Q_SIZE64, /* second highest */ IX_QMGR_Q_SIZE32, /* third highest */ IX_QMGR_Q_SIZE16, /* fourth highest */ IX_QMGR_Q_SIZE16, /* fifth highest */ IX_QMGR_Q_SIZE16, /* sixth highest */ IX_QMGR_Q_SIZE16, /* seventh highest */ IX_QMGR_Q_SIZE16 /* lowest */};/** * @brief Queue nearly full watermark table indexed by NPE count */IX_ETH_ACC_PRIVATE constIxQMgrWMLevel ixEthAccQueueNFWatermarkTable[] ={ IX_QMGR_Q_WM_LEVEL0, /* NPE count == 0 (invalid) */ IX_QMGR_Q_WM_LEVEL0, /* NPE count == 1 */ IX_QMGR_Q_WM_LEVEL1, /* NPE count == 2 */ IX_QMGR_Q_WM_LEVEL2, /* NPE count == 3 */ IX_QMGR_Q_WM_LEVEL4, /* NPE count == 4 */ IX_QMGR_Q_WM_LEVEL4, /* NPE count == 5 */ IX_QMGR_Q_WM_LEVEL8, /* NPE count == 6 */ IX_QMGR_Q_WM_LEVEL8 /* NPE count == 7 */};/** * @brief Static Queue assignment array per NPEs indexed by NPE ID */IX_ETH_ACC_PRIVATE constUINT8 ixEthAccNpeStaticQueueConfigs[][2] ={ /* { TX Queue , RX Free Queue } */ { IX_ETH_ACC_TX_NPEA_Q, IX_ETH_ACC_RX_FREE_NPEA_Q}, { IX_ETH_ACC_TX_NPEB_Q, IX_ETH_ACC_RX_FREE_NPEB_Q}, { IX_ETH_ACC_TX_NPEC_Q, IX_ETH_ACC_RX_FREE_NPEC_Q}};/** * @fn ixEthAccQMgrQueueSetup(IxEthAccQregInfo*) * * @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){ int ret; ret = ixQMgrQConfig( qInfoDes->qName, qInfoDes->qId, qInfoDes->qSize, qInfoDes->qWords); /* If queue is already configured, continue anyway */ if(ret != IX_SUCCESS && ret != IX_QMGR_Q_ALREADY_CONFIGURED) { 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);}/* * ixEthAccQMgrQueueUnsetup () * added to the same file */PRIVATE IxEthAccStatusixEthAccQMgrQueueUnsetup (IxEthAccQregInfo *qInfoDes){ if (IX_ETH_ACC_SUCCESS != ixQMgrNotificationDisable(qInfoDes->qId)) { IX_ETH_ACC_WARNING_LOG ("Failed to disable the notification\n", 0, 0, 0, 0, 0, 0); return IX_ETH_ACC_FAIL; } return IX_ETH_ACC_SUCCESS;}/** * @fn ixEthAccGetRxQueueList(IxEthAccPortId, IxEthAccRxQueue *) * * @brief Fill in and sort the rx queue array * * @li select all Rx queues as configured by ethDB for all ports * @li sort the queues by traffic class * * @param none * * @return UINT32 (num Rx queues) * * @internal */IX_ETH_ACC_PRIVATEIxEthAccStatus ixEthAccGetRxQueueList(IxEthAccPortId portId, IxEthAccRxQueue *rxQueues){ IxEthDBStatus ixEthDBStatus = IX_ETH_DB_SUCCESS; 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; UINT32 rxQueue = 0; UINT32 sortIterations = 0; IxEthNpeNodeId ixNpeId = IX_ETHNPE_PHYSICAL_ID_TO_NODE(portId); /* * Queue Selection step: * * The following code selects all the queues and fills * the RxQueue array * */ /* 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( portId, 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) { /* search the queue in the list of queues * already used by an other port or QoS */ for ( rxQueue = 0; ((rxQueues[rxQueue].npeCount != 0) && (rxQueue < IX_ETHACC_MAX_RX_QUEUES)); 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 (rxQueues[rxQueue].npeCount == 0) { /* new queue not found in the current list, * add a new entry. */ IX_OSAL_ASSERT(rxQueue < IX_ETHACC_MAX_RX_QUEUES); rxQueues[rxQueue].qId = ixEthDBParameter; rxQueues[rxQueue].npeCount = 1; rxQueues[rxQueue].npeId = ixNpeId; rxQueues[rxQueue].trafficClass = ixEthDBTrafficClass; } } else { /* unexpected property type (not Integer) */ IX_ETH_ACC_WARNING_LOG("ixEthAccGetRxQueueList: unexpected property type returned by EthDB\n", 0, 0, 0, 0, 0, 0); /* no point to continue to iterate */ return (IX_ETH_ACC_FAIL); } } else { /* No Rx queue configured for this port * and this traffic class. Do nothing. */ } } /* check there is at least 1 rx queue : there is no point * to continue if there is no rx queue configured */ if (rxQueues[0].npeCount == 0) { IX_ETH_ACC_WARNING_LOG("ixEthAccGetRxQueueList: no queues configured, bailing out\n", 0, 0, 0, 0, 0, 0); /* queue configuration error so return queue count 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; (rxQueues[rxQueue+1].npeCount != 0) && (rxQueue < IX_ETHACC_MAX_RX_QUEUES - sortIterations); rxQueue++) { /* compare adjacent elements */ if ((rxQueues[rxQueue].trafficClass < rxQueues[rxQueue+1].trafficClass) || ((rxQueues[rxQueue].trafficClass ==
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -