uboot/cpu/ixp/npe/IxEthAccCommon.c
<<
>>
Prefs
   1/**
   2 * @file IxEthAccCommon.c
   3 *
   4 * @author Intel Corporation
   5 * @date 12-Feb-2002
   6 *
   7 * @brief This file contains the implementation common support routines for the component
   8 *
   9 * Design Notes:
  10 *
  11 * @par
  12 * IXP400 SW Release version 2.0
  13 *
  14 * -- Copyright Notice --
  15 *
  16 * @par
  17 * Copyright 2001-2005, Intel Corporation.
  18 * All rights reserved.
  19 *
  20 * @par
  21 * Redistribution and use in source and binary forms, with or without
  22 * modification, are permitted provided that the following conditions
  23 * are met:
  24 * 1. Redistributions of source code must retain the above copyright
  25 *    notice, this list of conditions and the following disclaimer.
  26 * 2. Redistributions in binary form must reproduce the above copyright
  27 *    notice, this list of conditions and the following disclaimer in the
  28 *    documentation and/or other materials provided with the distribution.
  29 * 3. Neither the name of the Intel Corporation nor the names of its contributors
  30 *    may be used to endorse or promote products derived from this software
  31 *    without specific prior written permission.
  32 *
  33 * @par
  34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
  35 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  37 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  44 * SUCH DAMAGE.
  45 *
  46 * @par
  47 * -- End of Copyright Notice --
  48 */
  49
  50/*
  51 * Component header files
  52 */
  53
  54#include "IxOsal.h"
  55#include "IxEthAcc.h"
  56#include "IxEthDB.h"
  57#include "IxNpeMh.h"
  58#include "IxEthDBPortDefs.h"
  59#include "IxFeatureCtrl.h"
  60#include "IxEthAcc_p.h"
  61#include "IxEthAccQueueAssign_p.h"
  62
  63#include "IxEthAccDataPlane_p.h"
  64#include "IxEthAccMii_p.h"
  65
  66/**
  67 * @addtogroup IxEthAccPri
  68 *@{
  69 */
  70
  71extern IxEthAccInfo   ixEthAccDataInfo;
  72
  73/**
  74 *
  75 * @brief Maximum number of RX queues set to be the maximum number
  76 * of traffic calsses.
  77 *
  78 */
  79#define IX_ETHACC_MAX_RX_QUEUES \
  80      (IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY \
  81      - IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY \
  82      + 1)
  83
  84/**
  85 *
  86 * @brief Maximum number of 128 entry RX queues
  87 *
  88 */
  89#define IX_ETHACC_MAX_LARGE_RX_QUEUES 4
  90
  91/**
  92 *
  93 * @brief Data structure template for Default RX Queues
  94 *
  95 */
  96IX_ETH_ACC_PRIVATE
  97IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate =
  98  {
  99    IX_ETH_ACC_RX_FRAME_ETH_Q,       /**< Queue ID */
 100    "Eth Rx Q",
 101    ixEthRxFrameQMCallback,          /**< Functional callback */
 102    (IxQMgrCallbackId) 0,            /**< Callback tag        */
 103    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
 104    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
 105    TRUE,                            /**< Enable Q notification at startup */
 106    IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback   */
 107    IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
 108    IX_QMGR_Q_WM_LEVEL1,             /**< Q High water mark - needed by NPE */
 109  };
 110
 111/**
 112 *
 113 * @brief Data structure template for Small RX Queues
 114 *
 115 */
 116IX_ETH_ACC_PRIVATE
 117IxEthAccQregInfo ixEthAccQmgrRxSmallTemplate =
 118  {
 119    IX_ETH_ACC_RX_FRAME_ETH_Q,       /**< Queue ID */
 120    "Eth Rx Q",
 121    ixEthRxFrameQMCallback,          /**< Functional callback */
 122    (IxQMgrCallbackId) 0,            /**< Callback tag        */
 123    IX_QMGR_Q_SIZE64,                /**< Allocate Smaller Q */
 124    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
 125    TRUE,                            /**< Enable Q notification at startup */
 126    IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback   */
 127    IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
 128    IX_QMGR_Q_WM_LEVEL1,             /**< Q High water mark - needed by NPE */
 129  };
 130
 131
 132/**
 133 *
 134 * @brief Data structure used to register & initialize the Queues
 135 *
 136 */
 137IX_ETH_ACC_PRIVATE
 138IxEthAccQregInfo ixEthAccQmgrStaticInfo[]=
 139{
 140  {
 141    IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q,
 142    "Eth Rx Fr Q 1",
 143    ixEthRxFreeQMCallback,
 144    (IxQMgrCallbackId) IX_ETH_PORT_1,
 145    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
 146    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
 147    FALSE,                           /**< Disable Q notification at startup */
 148    IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback  */
 149    IX_QMGR_Q_WM_LEVEL0,             /***< Q Low water mark */
 150    IX_QMGR_Q_WM_LEVEL64,            /**< Q High water mark */
 151  },
 152
 153  {
 154    IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q,
 155    "Eth Rx Fr Q 2",
 156    ixEthRxFreeQMCallback,
 157    (IxQMgrCallbackId) IX_ETH_PORT_2,
 158    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
 159    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
 160    FALSE,                           /**< Disable Q notification at startup */
 161    IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE,  /**< Q Condition to drive callback  */
 162    IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
 163    IX_QMGR_Q_WM_LEVEL64,            /**< Q High water mark */
 164  },
 165#ifdef __ixp46X
 166  {
 167    IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q,
 168    "Eth Rx Fr Q 3",
 169    ixEthRxFreeQMCallback,
 170    (IxQMgrCallbackId) IX_ETH_PORT_3,
 171    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
 172    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
 173    FALSE,                           /**< Disable Q notification at startup */
 174    IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE,  /**< Q Condition to drive callback  */
 175    IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
 176    IX_QMGR_Q_WM_LEVEL64,            /**< Q High water mark */
 177  },
 178#endif
 179  {
 180     IX_ETH_ACC_TX_FRAME_ENET0_Q,
 181    "Eth Tx Q 1",
 182     ixEthTxFrameQMCallback,
 183     (IxQMgrCallbackId) IX_ETH_PORT_1,
 184    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
 185    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
 186    FALSE,                           /**< Disable Q notification at startup */
 187    IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE,  /**< Q Condition to drive callback  */
 188    IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
 189    IX_QMGR_Q_WM_LEVEL64,            /**< Q High water mark */
 190  },
 191
 192  {
 193     IX_ETH_ACC_TX_FRAME_ENET1_Q,
 194    "Eth Tx Q 2",
 195     ixEthTxFrameQMCallback,
 196     (IxQMgrCallbackId) IX_ETH_PORT_2,
 197    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
 198    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
 199    FALSE,                           /**< Disable Q notification at startup */
 200    IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE,      /**< Q Condition to drive callback  */
 201    IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
 202    IX_QMGR_Q_WM_LEVEL64,            /**< Q High water mark */
 203  },
 204#ifdef __ixp46X
 205  {
 206     IX_ETH_ACC_TX_FRAME_ENET2_Q,
 207    "Eth Tx Q 3",
 208     ixEthTxFrameQMCallback,
 209     (IxQMgrCallbackId) IX_ETH_PORT_3,
 210    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
 211    IX_QMGR_Q_ENTRY_SIZE1,           /** Queue Entry Sizes - all Q entries are single ord entries   */
 212    FALSE,                           /** Disable Q notification at startup */
 213    IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE,      /** Q Condition to drive callback  */
 214    IX_QMGR_Q_WM_LEVEL0,             /* No queues use almost empty */
 215    IX_QMGR_Q_WM_LEVEL64,             /** Q High water mark - needed used  */
 216  },
 217#endif
 218  {
 219     IX_ETH_ACC_TX_FRAME_DONE_ETH_Q,
 220    "Eth Tx Done Q",
 221     ixEthTxFrameDoneQMCallback,
 222     (IxQMgrCallbackId) 0,
 223    IX_QMGR_Q_SIZE128,               /**< Allocate Max Size Q */
 224    IX_QMGR_Q_ENTRY_SIZE1,           /**< Queue Entry Sizes - all Q entries are single word entries   */
 225    TRUE,                            /**< Enable Q notification at startup */
 226    IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE, /**< Q Condition to drive callback  */
 227    IX_QMGR_Q_WM_LEVEL0,             /**< Q Low water mark */
 228    IX_QMGR_Q_WM_LEVEL2,             /**< Q High water mark - needed by NPE */
 229  },
 230
 231  {  /* Null Termination entry
 232      */
 233     (IxQMgrQId)0,
 234     (char *) NULL,
 235     (IxQMgrCallback) NULL,
 236     (IxQMgrCallbackId) 0,
 237     0,
 238     0,
 239     0,
 240     0,
 241     0,
 242     0
 243  }
 244
 245};
 246
 247/**
 248 *
 249 * @brief Data structure used to register & initialize the Queues
 250 *
 251 * The structure will be filled at run time depending on the NPE
 252 * image already loaded and the QoS configured in ethDB.
 253 *
 254 */
 255IX_ETH_ACC_PRIVATE
 256IxEthAccQregInfo ixEthAccQmgrRxQueuesInfo[IX_ETHACC_MAX_RX_QUEUES+1]=
 257{
 258  {  /* PlaceHolder for rx queues
 259      * depending on the QoS configured
 260      */
 261     (IxQMgrQId)0,
 262     (char *) NULL,
 263     (IxQMgrCallback) NULL,
 264     (IxQMgrCallbackId) 0,
 265     0,
 266     0,
 267     0,
 268     0,
 269     0,
 270     0
 271  },
 272
 273  {  /* PlaceHolder for rx queues
 274      * depending on the QoS configured
 275      */
 276     (IxQMgrQId)0,
 277     (char *) NULL,
 278     (IxQMgrCallback) NULL,
 279     (IxQMgrCallbackId) 0,
 280     0,
 281     0,
 282     0,
 283     0,
 284     0,
 285     0
 286  },
 287
 288  {  /* PlaceHolder for rx queues
 289      * depending on the QoS configured
 290      */
 291     (IxQMgrQId)0,
 292     (char *) NULL,
 293     (IxQMgrCallback) NULL,
 294     (IxQMgrCallbackId) 0,
 295     0,
 296     0,
 297     0,
 298     0,
 299     0,
 300     0
 301  },
 302
 303  {  /* PlaceHolder for rx queues
 304      * depending on the QoS configured
 305      */
 306     (IxQMgrQId)0,
 307     (char *) NULL,
 308     (IxQMgrCallback) NULL,
 309     (IxQMgrCallbackId) 0,
 310     0,
 311     0,
 312     0,
 313     0,
 314     0,
 315     0
 316  },
 317
 318  {  /* PlaceHolder for rx queues
 319      * depending on the QoS configured
 320      */
 321     (IxQMgrQId)0,
 322     (char *) NULL,
 323     (IxQMgrCallback) NULL,
 324     (IxQMgrCallbackId) 0,
 325     0,
 326     0,
 327     0,
 328     0,
 329     0,
 330     0
 331  },
 332
 333  {  /* PlaceHolder for rx queues
 334      * depending on the QoS configured
 335      */
 336      (IxQMgrQId)0,
 337     (char *) NULL,
 338     (IxQMgrCallback) NULL,
 339     (IxQMgrCallbackId) 0,
 340     0,
 341     0,
 342     0,
 343     0,
 344     0,
 345     0
 346  },
 347
 348  {  /* PlaceHolder for rx queues
 349      * depending on the QoS configured
 350      */
 351     (IxQMgrQId)0,
 352     (char *) NULL,
 353     (IxQMgrCallback) NULL,
 354     (IxQMgrCallbackId) 0,
 355     0,
 356     0,
 357     0,
 358     0,
 359     0,
 360     0
 361  },
 362
 363  {  /* PlaceHolder for rx queues
 364      * depending on the QoS configured
 365      */
 366     (IxQMgrQId)0,
 367     (char *) NULL,
 368     (IxQMgrCallback) NULL,
 369     (IxQMgrCallbackId) 0,
 370     0,
 371     0,
 372     0,
 373     0,
 374     0,
 375     0
 376  },
 377
 378  {  /* Null Termination entry
 379      */
 380     (IxQMgrQId)0,
 381     (char *) NULL,
 382     (IxQMgrCallback) NULL,
 383     (IxQMgrCallbackId) 0,
 384     0,
 385     0,
 386     0,
 387     0,
 388     0,
 389     0
 390  }
 391
 392};
 393
 394/* forward declarations */
 395IX_ETH_ACC_PRIVATE IxEthAccStatus
 396ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes);
 397
 398/**
 399 * @fn ixEthAccQMgrQueueSetup(void)
 400 *
 401 * @brief Setup one queue and its event, and register the callback required
 402 * by this component to the QMgr
 403 *
 404 * @internal
 405 */
 406IX_ETH_ACC_PRIVATE IxEthAccStatus
 407ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes)
 408{
 409    /*
 410     * Configure each Q.
 411     */
 412    if ( ixQMgrQConfig( qInfoDes->qName,
 413                        qInfoDes->qId,
 414                        qInfoDes->qSize,
 415                        qInfoDes->qWords) != IX_SUCCESS)
 416    {
 417        return IX_ETH_ACC_FAIL;
 418    }
 419
 420    if ( ixQMgrWatermarkSet( qInfoDes->qId,
 421                             qInfoDes->AlmostEmptyThreshold,
 422                             qInfoDes->AlmostFullThreshold
 423                             ) != IX_SUCCESS)
 424    {
 425        return IX_ETH_ACC_FAIL;
 426    }
 427
 428    /*
 429     * Set dispatcher priority.
 430     */
 431    if ( ixQMgrDispatcherPrioritySet( qInfoDes->qId,
 432                                      IX_ETH_ACC_QM_QUEUE_DISPATCH_PRIORITY)
 433         != IX_SUCCESS)
 434    {
 435        return IX_ETH_ACC_FAIL;
 436    }
 437
 438    /*
 439     * Register callbacks for each Q.
 440     */
 441    if ( ixQMgrNotificationCallbackSet(qInfoDes->qId,
 442                                       qInfoDes->qCallback,
 443                                       qInfoDes->callbackTag)
 444         != IX_SUCCESS )
 445    {
 446        return IX_ETH_ACC_FAIL;
 447    }
 448
 449    /*
 450     * Set notification condition for Q
 451     */
 452    if ( qInfoDes->qNotificationEnableAtStartup == TRUE )
 453    {
 454        if (   ixQMgrNotificationEnable(qInfoDes->qId,
 455                                        qInfoDes->qConditionSource)
 456               != IX_SUCCESS )
 457        {
 458            return IX_ETH_ACC_FAIL;
 459        }
 460    }
 461
 462    return(IX_ETH_ACC_SUCCESS);
 463}
 464
 465/**
 466 * @fn ixEthAccQMgrQueuesConfig(void)
 467 *
 468 * @brief Setup all the queues and register all callbacks required
 469 * by this component to the QMgr
 470 *
 471 * The RxFree queues, tx queues, rx queues are configured statically
 472 *
 473 * Rx queues configuration is driven by QoS setup.
 474 * Many Rx queues may be required when QoS is enabled (this depends
 475 * on IxEthDB setup and the images being downloaded). The configuration
 476 * of the rxQueues is done in many steps as follows:
 477 *
 478 * @li select all Rx queues as configured by ethDB for all ports
 479 * @li sort the queues by traffic class
 480 * @li build the priority dependency for all queues
 481 * @li fill the configuration for all rx queues
 482 * @li configure all statically configured queues
 483 * @li configure all dynamically configured queues
 484 *
 485 * @param none
 486 *
 487 * @return IxEthAccStatus
 488 *
 489 * @internal
 490 */
 491IX_ETH_ACC_PUBLIC
 492IxEthAccStatus ixEthAccQMgrQueuesConfig(void)
 493{
 494    struct
 495    {
 496        int npeCount;
 497        UINT32 npeId;
 498        IxQMgrQId qId;
 499        IxEthDBProperty trafficClass;
 500    } rxQueues[IX_ETHACC_MAX_RX_QUEUES];
 501
 502    UINT32 rxQueue = 0;
 503    UINT32 rxQueueCount = 0;
 504    IxQMgrQId ixQId =IX_QMGR_MAX_NUM_QUEUES;
 505    IxEthDBStatus ixEthDBStatus = IX_ETH_DB_SUCCESS;
 506    IxEthDBPortId ixEthDbPortId = 0;
 507    IxEthAccPortId ixEthAccPortId = 0;
 508    UINT32 ixNpeId = 0;
 509    UINT32 ixHighestNpeId = 0;
 510    UINT32 sortIterations = 0;
 511    IxEthAccStatus ret = IX_ETH_ACC_SUCCESS;
 512    IxEthAccQregInfo *qInfoDes = NULL;
 513    IxEthDBProperty ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
 514    IxEthDBPropertyType ixEthDBPropertyType = IX_ETH_DB_INTEGER_PROPERTY;
 515    UINT32 ixEthDBParameter = 0;
 516    BOOL completelySorted = FALSE;
 517
 518    /* Fill the corspondance between ports and queues
 519     * This defines the mapping from port to queue Ids.
 520     */
 521
 522    ixEthAccPortData[IX_ETH_PORT_1].ixEthAccRxData.rxFreeQueue
 523        = IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q;
 524    ixEthAccPortData[IX_ETH_PORT_2].ixEthAccRxData.rxFreeQueue
 525        = IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q;
 526#ifdef __ixp46X
 527    ixEthAccPortData[IX_ETH_PORT_3].ixEthAccRxData.rxFreeQueue
 528        = IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q;
 529#endif
 530    ixEthAccPortData[IX_ETH_PORT_1].ixEthAccTxData.txQueue
 531        = IX_ETH_ACC_TX_FRAME_ENET0_Q;
 532    ixEthAccPortData[IX_ETH_PORT_2].ixEthAccTxData.txQueue
 533        = IX_ETH_ACC_TX_FRAME_ENET1_Q;
 534#ifdef __ixp46X
 535    ixEthAccPortData[IX_ETH_PORT_3].ixEthAccTxData.txQueue
 536        = IX_ETH_ACC_TX_FRAME_ENET2_Q;
 537#endif
 538    /* Fill the corspondance between ports and NPEs
 539     * This defines the mapping from port to npeIds.
 540     */
 541
 542    ixEthAccPortData[IX_ETH_PORT_1].npeId = IX_NPEMH_NPEID_NPEB;
 543    ixEthAccPortData[IX_ETH_PORT_2].npeId = IX_NPEMH_NPEID_NPEC;
 544#ifdef __ixp46X
 545    ixEthAccPortData[IX_ETH_PORT_3].npeId = IX_NPEMH_NPEID_NPEA;
 546#endif
 547    /* set the default rx scheduling discipline */
 548    ixEthAccDataInfo.schDiscipline = FIFO_NO_PRIORITY;
 549
 550    /*
 551     * Queue Selection step:
 552     *
 553     * The following code selects all the queues and build
 554     * a temporary array which contains for each queue
 555     * - the queue Id,
 556     * - the highest traffic class (in case of many
 557     * priorities configured for the same queue on different
 558     * ports)
 559     * - the number of different Npes which are
 560     * configured to write to this queue.
 561     *
 562     * The output of this loop is a temporary array of RX queues
 563     * in any order.
 564     *
 565     */
 566#ifdef CONFIG_IXP425_COMPONENT_ETHDB
 567    for (ixEthAccPortId = 0;
 568         (ixEthAccPortId < IX_ETH_ACC_NUMBER_OF_PORTS)
 569             && (ret == IX_ETH_ACC_SUCCESS);
 570         ixEthAccPortId++)
 571    {
 572        /* map between ethDb and ethAcc port Ids */
 573        ixEthDbPortId = (IxEthDBPortId)ixEthAccPortId;
 574
 575        /* map between npeId and ethAcc port Ids */
 576        ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId);
 577
 578        /* Iterate thru the different priorities */
 579        for (ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
 580             ixEthDBTrafficClass <= IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY;
 581             ixEthDBTrafficClass++)
 582        {
 583            ixEthDBStatus = ixEthDBFeaturePropertyGet(
 584              ixEthDbPortId,
 585              IX_ETH_DB_VLAN_QOS,
 586              ixEthDBTrafficClass,
 587              &ixEthDBPropertyType,
 588              (void *)&ixEthDBParameter);
 589
 590            if (ixEthDBStatus == IX_ETH_DB_SUCCESS)
 591            {
 592                /* This port and QoS class are mapped to
 593                 * a RX queue.
 594                 */
 595                if (ixEthDBPropertyType == IX_ETH_DB_INTEGER_PROPERTY)
 596                {
 597                    /* remember the highest npe Id supporting ethernet */
 598                    if (ixNpeId > ixHighestNpeId)
 599                    {
 600                        ixHighestNpeId = ixNpeId;
 601                    }
 602
 603                    /* search the queue in the list of queues
 604                     * already used by an other port or QoS
 605                     */
 606                    for (rxQueue = 0;
 607                         rxQueue < rxQueueCount;
 608                         rxQueue++)
 609                    {
 610                        if (rxQueues[rxQueue].qId == (IxQMgrQId)ixEthDBParameter)
 611                        {
 612                            /* found an existing setup, update the number of ports
 613                             * for this queue if the port maps to
 614                             * a different NPE.
 615                             */
 616                            if (rxQueues[rxQueue].npeId != ixNpeId)
 617                            {
 618                                rxQueues[rxQueue].npeCount++;
 619                                rxQueues[rxQueue].npeId = ixNpeId;
 620                            }
 621                            /* get the highest traffic class for this queue */
 622                            if (rxQueues[rxQueue].trafficClass > ixEthDBTrafficClass)
 623                            {
 624                                rxQueues[rxQueue].trafficClass = ixEthDBTrafficClass;
 625                            }
 626                            break;
 627                        }
 628                    }
 629                    if (rxQueue == rxQueueCount)
 630                    {
 631                        /* new queue not found in the current list,
 632                         * add a new entry.
 633                         */
 634                        IX_OSAL_ASSERT(rxQueueCount < IX_ETHACC_MAX_RX_QUEUES);
 635                        rxQueues[rxQueueCount].qId = ixEthDBParameter;
 636                        rxQueues[rxQueueCount].npeCount = 1;
 637                        rxQueues[rxQueueCount].npeId = ixNpeId;
 638                        rxQueues[rxQueueCount].trafficClass = ixEthDBTrafficClass;
 639                        rxQueueCount++;
 640                    }
 641                }
 642                else
 643                {
 644                    /* unexpected property type (not Integer) */
 645                    ret = IX_ETH_ACC_FAIL;
 646
 647                    IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: unexpected property type returned by EthDB\n", 0, 0, 0, 0, 0, 0);
 648
 649                    /* no point to continue to iterate */
 650                    break;
 651                }
 652            }
 653            else
 654            {
 655                /* No Rx queue configured for this port
 656                 * and this traffic class. Do nothing.
 657                 */
 658            }
 659        }
 660
 661        /* notify EthDB that queue initialization is complete and traffic class allocation is frozen */
 662        ixEthDBFeaturePropertySet(ixEthDbPortId,
 663            IX_ETH_DB_VLAN_QOS,
 664            IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE,
 665            NULL /* ignored */);
 666    }
 667
 668#else
 669
 670    ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId);
 671    rxQueues[0].qId = 4;
 672    rxQueues[0].npeCount = 1;
 673    rxQueues[0].npeId = ixNpeId;
 674    rxQueues[0].trafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY;
 675    rxQueueCount++;
 676
 677#endif
 678
 679    /* check there is at least 1 rx queue : there is no point
 680     * to continue if there is no rx queue configured
 681     */
 682    if ((rxQueueCount == 0) || (ret == IX_ETH_ACC_FAIL))
 683    {
 684        IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: no queues configured, bailing out\n", 0, 0, 0, 0, 0, 0);
 685        return (IX_ETH_ACC_FAIL);
 686    }
 687
 688    /* Queue sort step:
 689     *
 690     * Re-order the array of queues by decreasing traffic class
 691     * using a bubble sort. (trafficClass 0 is the lowest
 692     * priority traffic, trafficClass 7 is the highest priority traffic)
 693     *
 694     * Primary sort order is traffic class
 695     * Secondary sort order is npeId
 696     *
 697     * Note that a bubble sort algorithm is not very efficient when
 698     * the number of queues grows . However, this is not a very bad choice
 699     * considering the very small number of entries to sort. Also, bubble
 700     * sort is extremely fast when the list is already sorted.
 701     *
 702     * The output of this loop is a sorted array of queues.
 703     *
 704     */
 705    sortIterations = 0;
 706    do
 707    {
 708        sortIterations++;
 709        completelySorted = TRUE;
 710        for (rxQueue = 0;
 711             rxQueue < rxQueueCount - sortIterations;
 712             rxQueue++)
 713        {
 714            /* compare adjacent elements */
 715            if ((rxQueues[rxQueue].trafficClass <
 716                rxQueues[rxQueue+1].trafficClass)
 717                || ((rxQueues[rxQueue].trafficClass ==
 718                     rxQueues[rxQueue+1].trafficClass)
 719                    &&(rxQueues[rxQueue].npeId <
 720                       rxQueues[rxQueue+1].npeId)))
 721            {
 722                /* swap adjacent elements */
 723                int npeCount = rxQueues[rxQueue].npeCount;
 724                UINT32 npeId = rxQueues[rxQueue].npeId;
 725                IxQMgrQId qId = rxQueues[rxQueue].qId;
 726                IxEthDBProperty trafficClass = rxQueues[rxQueue].trafficClass;
 727                rxQueues[rxQueue].npeCount = rxQueues[rxQueue+1].npeCount;
 728                rxQueues[rxQueue].npeId = rxQueues[rxQueue+1].npeId;
 729                rxQueues[rxQueue].qId = rxQueues[rxQueue+1].qId;
 730                rxQueues[rxQueue].trafficClass = rxQueues[rxQueue+1].trafficClass;
 731                rxQueues[rxQueue+1].npeCount = npeCount;
 732                rxQueues[rxQueue+1].npeId = npeId;
 733                rxQueues[rxQueue+1].qId = qId;
 734                rxQueues[rxQueue+1].trafficClass = trafficClass;
 735                completelySorted = FALSE;
 736            }
 737        }
 738    }
 739    while (!completelySorted);
 740
 741    /* Queue traffic class list:
 742     *
 743     * Fill an array of rx queues linked by ascending traffic classes.
 744     *
 745     * If the queues are configured as follows
 746     *   qId 6 -> traffic class 0 (lowest)
 747     *   qId 7 -> traffic class 0
 748     *   qId 8 -> traffic class 6
 749     *   qId 12 -> traffic class 7 (highest)
 750     *
 751     * Then the output of this loop will be
 752     *
 753     * higherPriorityQueue[6] = 8
 754     * higherPriorityQueue[7] = 8
 755     * higherPriorityQueue[8] = 12
 756     * higherPriorityQueue[12] = Invalid queueId
 757     * higherPriorityQueue[...] = Invalid queueId
 758     *
 759     * Note that this queue ordering does not handle all possibilities
 760     * that could result from different rules associated with different
 761     * ports, and inconsistencies in the rules. In all cases, the
 762     * output of this  algorithm is a simple linked list of queues,
 763     * without closed circuit.
 764
 765     * This list is implemented as an array with invalid values initialized
 766     * with an "invalid" queue id which is the maximum number of queues.
 767     *
 768     */
 769
 770    /*
 771     * Initialise the rx queue list.
 772     */
 773    for (rxQueue = 0; rxQueue < IX_QMGR_MAX_NUM_QUEUES; rxQueue++)
 774    {
 775        ixEthAccDataInfo.higherPriorityQueue[rxQueue] = IX_QMGR_MAX_NUM_QUEUES;
 776    }
 777
 778    /* build the linked list for this NPE.
 779     */
 780    for (ixNpeId = 0;
 781         ixNpeId <= ixHighestNpeId;
 782         ixNpeId++)
 783    {
 784        /* iterate thru the sorted list of queues
 785         */
 786        ixQId = IX_QMGR_MAX_NUM_QUEUES;
 787        for (rxQueue = 0;
 788             rxQueue < rxQueueCount;
 789             rxQueue++)
 790        {
 791            if (rxQueues[rxQueue].npeId == ixNpeId)
 792            {
 793                ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId;
 794                /* iterate thru queues with the same traffic class
 795                 * than the current queue. (queues are ordered by descending
 796                 * traffic classes and npeIds).
 797                 */
 798                while ((rxQueue < rxQueueCount - 1)
 799                       && (rxQueues[rxQueue].trafficClass
 800                           == rxQueues[rxQueue+1].trafficClass)
 801                       && (ixNpeId == rxQueues[rxQueue].npeId))
 802                {
 803                    rxQueue++;
 804                    ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId;
 805                }
 806                ixQId = rxQueues[rxQueue].qId;
 807            }
 808        }
 809    }
 810
 811    /* point on the first dynamic queue description */
 812    qInfoDes = ixEthAccQmgrRxQueuesInfo;
 813
 814    /* update the list of queues with the rx queues */
 815    for (rxQueue = 0;
 816         (rxQueue < rxQueueCount) && (ret == IX_ETH_ACC_SUCCESS);
 817         rxQueue++)
 818    {
 819        /* Don't utilize more than IX_ETHACC_MAX_LARGE_RX_QUEUES queues
 820         * with the full 128 entries.  For the lower priority queues, use
 821         * a smaller number of entries.  This ensures queue resources
 822         * remain available for other components.
 823         */
 824        if( (rxQueueCount > IX_ETHACC_MAX_LARGE_RX_QUEUES) &&
 825            (rxQueue < rxQueueCount - IX_ETHACC_MAX_LARGE_RX_QUEUES) )
 826        {
 827            /* add the small RX Queue setup template to the list of queues */
 828            memcpy(qInfoDes, &ixEthAccQmgrRxSmallTemplate, sizeof(*qInfoDes));
 829        } else {
 830            /* add the default RX Queue setup template to the list of queues */
 831            memcpy(qInfoDes, &ixEthAccQmgrRxDefaultTemplate, sizeof(*qInfoDes));
 832        }
 833
 834        /* setup the RxQueue ID */
 835        qInfoDes->qId = rxQueues[rxQueue].qId;
 836
 837        /* setup the RxQueue watermark level
 838         *
 839         * Each queue can be filled by many NPEs. To avoid the
 840         * NPEs to write to a full queue, need to set the
 841         * high watermark level for nearly full condition.
 842         * (the high watermark level are a power of 2
 843         * starting from the top of the queue)
 844         *
 845         * Number of     watermark
 846         *   ports        level
 847         *    1             0
 848         *    2             1
 849         *    3             2
 850         *    4             4
 851         *    5             4
 852         *    6             8
 853         *    n          approx. 2**ceil(log2(n))
 854         */
 855        if (rxQueues[rxQueue].npeCount == 1)
 856        {
 857            qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL0;
 858        }
 859        else if (rxQueues[rxQueue].npeCount == 2)
 860        {
 861            qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL1;
 862        }
 863        else if (rxQueues[rxQueue].npeCount == 3)
 864        {
 865            qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL2;
 866        }
 867        else
 868        {
 869            /* reach the maximum number for CSR 2.0 */
 870            IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: maximum number of NPEs per queue reached, bailing out\n", 0, 0, 0, 0, 0, 0);
 871            ret = IX_ETH_ACC_FAIL;
 872            break;
 873        }
 874
 875        /* move to next queue entry */
 876        ++qInfoDes;
 877    }
 878
 879    /* configure the static list (RxFree, Tx and TxDone queues) */
 880    for (qInfoDes = ixEthAccQmgrStaticInfo;
 881         (qInfoDes->qCallback != (IxQMgrCallback) NULL )
 882             && (ret == IX_ETH_ACC_SUCCESS);
 883         ++qInfoDes)
 884    {
 885        ret = ixEthAccQMgrQueueSetup(qInfoDes);
 886    }
 887
 888    /* configure the dynamic list (Rx queues) */
 889    for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
 890         (qInfoDes->qCallback != (IxQMgrCallback) NULL )
 891             && (ret == IX_ETH_ACC_SUCCESS);
 892         ++qInfoDes)
 893    {
 894        ret = ixEthAccQMgrQueueSetup(qInfoDes);
 895    }
 896
 897    return(ret);
 898}
 899
 900/**
 901 * @fn ixEthAccQMgrRxQEntryGet(UINT32 *rxQueueEntries)
 902 *
 903 * @brief Add and return the total number of entries in all Rx queues
 904 *
 905 * @param UINT32 rxQueueEntries[in] number of entries in all queues
 906 *
 907 * @return void
 908 *
 909 * @note Rx queues configuration is driven by Qos Setup. There is a
 910 * variable number of rx queues which are set at initialisation.
 911 *
 912 * @internal
 913 */
 914IX_ETH_ACC_PUBLIC
 915void ixEthAccQMgrRxQEntryGet(UINT32 *numRxQueueEntries)
 916{
 917    UINT32 rxQueueLevel;
 918    IxEthAccQregInfo *qInfoDes;;
 919
 920    *numRxQueueEntries = 0;
 921
 922    /* iterate thru rx queues */
 923    for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
 924         qInfoDes->qCallback != (IxQMgrCallback)NULL;
 925         ++qInfoDes)
 926    {
 927        /* retrieve the rx queue level */
 928        rxQueueLevel = 0;
 929        ixQMgrQNumEntriesGet(qInfoDes->qId, &rxQueueLevel);
 930        (*numRxQueueEntries) += rxQueueLevel;
 931    }
 932}
 933
 934/**
 935 * @fn ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback)
 936 *
 937 * @brief Change the callback registered to all rx queues.
 938 *
 939 * @param IxQMgrCallback ixQMgrCallback[in] QMgr callback to register
 940 *
 941 * @return IxEthAccStatus
 942 *
 943 * @note The user may decide to use different Rx mechanisms
 944 * (e.g. receive many frames at the same time , or receive
 945 *  one frame at a time, depending on the overall application
 946 *  performances). A different QMgr callback is registered. This
 947 *  way, there is no excessive pointer checks in the datapath.
 948 *
 949 * @internal
 950 */
 951IX_ETH_ACC_PUBLIC
 952IxEthAccStatus ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback)
 953{
 954    IxEthAccQregInfo *qInfoDes;
 955    IxEthAccStatus ret = IX_ETH_ACC_SUCCESS;
 956
 957    /* parameter check */
 958    if (NULL == ixQMgrCallback)
 959    {
 960        ret = IX_ETH_ACC_FAIL;
 961    }
 962
 963    /* iterate thru rx queues */
 964    for (qInfoDes = ixEthAccQmgrRxQueuesInfo;
 965         (qInfoDes->qCallback != (IxQMgrCallback) NULL )
 966             && (ret == IX_ETH_ACC_SUCCESS);
 967         ++qInfoDes)
 968    {
 969        /* register the rx callback for all queues */
 970        if (ixQMgrNotificationCallbackSet(qInfoDes->qId,
 971                                             ixQMgrCallback,
 972                                             qInfoDes->callbackTag
 973                                             ) != IX_SUCCESS)
 974        {
 975            ret = IX_ETH_ACC_FAIL;
 976        }
 977    }
 978    return(ret);
 979}
 980
 981/**
 982 * @fn ixEthAccSingleEthNpeCheck(IxEthAccPortId portId)
 983 *
 984 * @brief Check the npe exists for this port
 985 *
 986 * @param IxEthAccPortId portId[in] port
 987 *
 988 * @return IxEthAccStatus
 989 *
 990 * @internal
 991 */
 992IX_ETH_ACC_PUBLIC
 993IxEthAccStatus ixEthAccSingleEthNpeCheck(IxEthAccPortId portId)
 994{
 995
 996    /* If not IXP42X A0 stepping, proceed to check for existence of coprocessors */
 997    if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
 998        (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
 999        || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
1000      {
1001            if ((IX_ETH_PORT_1 == portId) &&
1002                (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
1003                 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1004            {
1005                return IX_ETH_ACC_SUCCESS;
1006            }
1007
1008            if ((IX_ETH_PORT_2 == portId) &&
1009                (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) ==
1010                 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1011            {
1012                return IX_ETH_ACC_SUCCESS;
1013            }
1014
1015            if ((IX_ETH_PORT_3 == portId) &&
1016                (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) ==
1017                 IX_FEATURE_CTRL_COMPONENT_ENABLED))
1018            {
1019                return IX_ETH_ACC_SUCCESS;
1020            }
1021
1022            return IX_ETH_ACC_FAIL;
1023      }
1024
1025    return IX_ETH_ACC_SUCCESS;
1026}
1027
1028/**
1029 * @fn ixEthAccStatsShow(void)
1030 *
1031 * @brief Displays all EthAcc stats
1032 *
1033 * @return void
1034 *
1035 */
1036void ixEthAccStatsShow(IxEthAccPortId portId)
1037{
1038    ixEthAccMdioShow();
1039
1040    printf("\nPort %u\nUnicast MAC : ", portId);
1041    ixEthAccPortUnicastAddressShow(portId);
1042    ixEthAccPortMulticastAddressShow(portId);
1043    printf("\n");
1044
1045    ixEthAccDataPlaneShow();
1046}
1047
1048
1049
1050