uboot/arch/arm/cpu/ixp/npe/IxQMgrQCfg.c
<<
>>
Prefs
   1/**
   2 * @file    QMgrQCfg.c
   3 *
   4 * @author Intel Corporation
   5 * @date    30-Oct-2001
   6 * 
   7 * @brief   This modules provides an interface for setting up the static
   8 * configuration of AQM queues.This file contains the following
   9 * functions:
  10 *
  11 * 
  12 * 
  13 * @par
  14 * IXP400 SW Release version 2.0
  15 * 
  16 * -- Copyright Notice --
  17 * 
  18 * @par
  19 * Copyright 2001-2005, Intel Corporation.
  20 * All rights reserved.
  21 * 
  22 * @par
  23 * Redistribution and use in source and binary forms, with or without
  24 * modification, are permitted provided that the following conditions
  25 * are met:
  26 * 1. Redistributions of source code must retain the above copyright
  27 *    notice, this list of conditions and the following disclaimer.
  28 * 2. Redistributions in binary form must reproduce the above copyright
  29 *    notice, this list of conditions and the following disclaimer in the
  30 *    documentation and/or other materials provided with the distribution.
  31 * 3. Neither the name of the Intel Corporation nor the names of its contributors
  32 *    may be used to endorse or promote products derived from this software
  33 *    without specific prior written permission.
  34 * 
  35 * @par
  36 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
  37 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  39 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46 * SUCH DAMAGE.
  47 * 
  48 * @par
  49 * -- End of Copyright Notice --
  50*/
  51
  52/*
  53 * System defined include files.
  54 */
  55
  56/*
  57 * User defined include files.
  58 */
  59#include "IxOsal.h"
  60#include "IxQMgr.h"
  61#include "IxQMgrAqmIf_p.h"
  62#include "IxQMgrQCfg_p.h"
  63#include "IxQMgrDefines_p.h"
  64
  65/*
  66 * #defines and macros used in this file.
  67 */
  68
  69#define IX_QMGR_MIN_ENTRY_SIZE_IN_WORDS 16
  70
  71/* Total size of SRAM */
  72#define IX_QMGR_AQM_SRAM_SIZE_IN_BYTES 0x4000
  73
  74/*
  75 * Check that qId is a valid queue identifier. This is provided to
  76 * make the code easier to read.
  77 */
  78#define IX_QMGR_QID_IS_VALID(qId) \
  79(((qId) >= (IX_QMGR_MIN_QID)) && ((qId) <= (IX_QMGR_MAX_QID)))
  80
  81/*
  82 * Typedefs whose scope is limited to this file.
  83 */
  84
  85/*
  86 * This struct describes an AQM queue.
  87 * N.b. bufferSizeInWords and qEntrySizeInWords are stored in the queue
  88 * as these are requested by Access in the data path. sizeInEntries is
  89 * not required by the data path so it can be calculated dynamically.
  90 * 
  91 */
  92typedef struct
  93{
  94    char qName[IX_QMGR_MAX_QNAME_LEN+1];       /* Textual description of a queue*/
  95    IxQMgrQSizeInWords qSizeInWords;           /* The number of words in the queue */
  96    IxQMgrQEntrySizeInWords qEntrySizeInWords; /* Number of words per queue entry*/
  97    BOOL isConfigured;                         /* This flag is TRUE if the queue has
  98                                                *   been configured
  99                                                */
 100} IxQMgrCfgQ;
 101
 102/*
 103 * Variable declarations global to this file. Externs are followed by
 104 * statics.
 105 */
 106
 107extern UINT32 * ixQMgrAqmIfQueAccRegAddr[]; 
 108
 109/* Store data required to inline read and write access
 110 */
 111IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[IX_QMGR_MAX_NUM_QUEUES];
 112
 113static IxQMgrCfgQ cfgQueueInfo[IX_QMGR_MAX_NUM_QUEUES];
 114
 115/* This pointer holds the starting address of AQM SRAM not used by
 116 * the AQM queues.
 117 */
 118static UINT32 freeSramAddress=0;
 119
 120/* 4 words of zeroed memory for inline access */
 121static UINT32 zeroedPlaceHolder[4] = { 0, 0, 0, 0 };
 122
 123static BOOL cfgInitialized = FALSE;
 124
 125static IxOsalMutex ixQMgrQCfgMutex;
 126
 127/*
 128 * Statistics
 129 */
 130static IxQMgrQCfgStats stats;
 131
 132/*
 133 * Function declarations
 134 */
 135PRIVATE BOOL
 136watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level);
 137
 138PRIVATE BOOL
 139qSizeInWordsIsOk (IxQMgrQSizeInWords qSize);
 140
 141PRIVATE BOOL
 142qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize);
 143
 144/*
 145 * Function definitions.
 146 */
 147void
 148ixQMgrQCfgInit (void)
 149{
 150    int loopIndex;
 151    
 152    for (loopIndex=0; loopIndex < IX_QMGR_MAX_NUM_QUEUES;loopIndex++)
 153    {
 154        /* info for code inlining */
 155        ixQMgrAqmIfQueAccRegAddr[loopIndex] = zeroedPlaceHolder;
 156
 157        /* info for code inlining */
 158        ixQMgrQInlinedReadWriteInfo[loopIndex].qReadCount = 0;
 159        ixQMgrQInlinedReadWriteInfo[loopIndex].qWriteCount = 0;
 160        ixQMgrQInlinedReadWriteInfo[loopIndex].qAccRegAddr = zeroedPlaceHolder;
 161        ixQMgrQInlinedReadWriteInfo[loopIndex].qUOStatRegAddr = zeroedPlaceHolder;
 162        ixQMgrQInlinedReadWriteInfo[loopIndex].qUflowStatBitMask = 0;
 163        ixQMgrQInlinedReadWriteInfo[loopIndex].qOflowStatBitMask = 0;
 164        ixQMgrQInlinedReadWriteInfo[loopIndex].qEntrySizeInWords = 0;
 165        ixQMgrQInlinedReadWriteInfo[loopIndex].qSizeInEntries = 0;
 166        ixQMgrQInlinedReadWriteInfo[loopIndex].qConfigRegAddr = zeroedPlaceHolder;
 167   }
 168
 169    /* Initialise the AqmIf component */
 170    ixQMgrAqmIfInit ();
 171   
 172    /* Reset all queues to have queue name = NULL, entry size = 0 and
 173     * isConfigured = false
 174     */
 175    for (loopIndex=0; loopIndex < IX_QMGR_MAX_NUM_QUEUES;loopIndex++)
 176    {
 177        strcpy (cfgQueueInfo[loopIndex].qName, "");
 178        cfgQueueInfo[loopIndex].qSizeInWords = 0;
 179        cfgQueueInfo[loopIndex].qEntrySizeInWords = 0;
 180        cfgQueueInfo[loopIndex].isConfigured = FALSE;
 181
 182        /* Statistics */
 183        stats.qStats[loopIndex].isConfigured = FALSE;
 184        stats.qStats[loopIndex].qName = cfgQueueInfo[loopIndex].qName;
 185    }
 186
 187    /* Statistics */
 188    stats.wmSetCnt = 0;
 189
 190    ixQMgrAqmIfSramBaseAddressGet (&freeSramAddress);
 191    
 192    ixOsalMutexInit(&ixQMgrQCfgMutex);
 193
 194    cfgInitialized = TRUE;
 195}
 196
 197void
 198ixQMgrQCfgUninit (void)
 199{
 200    cfgInitialized = FALSE;
 201
 202    /* Uninitialise the AqmIf component */
 203    ixQMgrAqmIfUninit ();
 204}
 205
 206IX_STATUS
 207ixQMgrQConfig (char *qName,
 208              IxQMgrQId qId,
 209              IxQMgrQSizeInWords qSizeInWords,
 210              IxQMgrQEntrySizeInWords qEntrySizeInWords)
 211{
 212    UINT32 aqmLocalBaseAddress;
 213
 214    if (!cfgInitialized)
 215    {
 216        return IX_FAIL;
 217    }
 218    
 219    if (!IX_QMGR_QID_IS_VALID(qId))
 220    {
 221        return IX_QMGR_INVALID_Q_ID;
 222    }
 223    
 224    else if (NULL == qName)
 225    {
 226        return IX_QMGR_PARAMETER_ERROR;
 227    }
 228    
 229    else if (strlen (qName) > IX_QMGR_MAX_QNAME_LEN)
 230    {
 231        return IX_QMGR_PARAMETER_ERROR;
 232    }
 233
 234    else if (!qSizeInWordsIsOk (qSizeInWords))
 235    {
 236        return IX_QMGR_INVALID_QSIZE;
 237    }
 238
 239    else if (!qEntrySizeInWordsIsOk (qEntrySizeInWords))
 240    {
 241        return IX_QMGR_INVALID_Q_ENTRY_SIZE;
 242    }
 243    
 244    else if (cfgQueueInfo[qId].isConfigured)
 245    {
 246        return IX_QMGR_Q_ALREADY_CONFIGURED;
 247    }
 248   
 249    ixOsalMutexLock(&ixQMgrQCfgMutex, IX_OSAL_WAIT_FOREVER);
 250
 251    /* Write the config register */
 252    ixQMgrAqmIfQueCfgWrite (qId,
 253                           qSizeInWords,
 254                           qEntrySizeInWords,
 255                           freeSramAddress);
 256
 257
 258    strcpy (cfgQueueInfo[qId].qName, qName);
 259    cfgQueueInfo[qId].qSizeInWords = qSizeInWords;
 260    cfgQueueInfo[qId].qEntrySizeInWords = qEntrySizeInWords;
 261
 262    /* store pre-computed information in the same cache line
 263     * to facilitate inlining of QRead and QWrite functions 
 264     * in IxQMgr.h
 265     */
 266    ixQMgrQInlinedReadWriteInfo[qId].qReadCount = 0;
 267    ixQMgrQInlinedReadWriteInfo[qId].qWriteCount = 0;
 268    ixQMgrQInlinedReadWriteInfo[qId].qEntrySizeInWords = qEntrySizeInWords;
 269    ixQMgrQInlinedReadWriteInfo[qId].qSizeInEntries = 
 270                (UINT32)qSizeInWords / (UINT32)qEntrySizeInWords;
 271
 272    /* Calculate the new freeSramAddress from the size of the queue
 273     * currently being configured.
 274     */
 275    freeSramAddress += (qSizeInWords * IX_QMGR_NUM_BYTES_PER_WORD);
 276
 277    /* Get the virtual SRAM address */
 278    ixQMgrAqmIfBaseAddressGet (&aqmLocalBaseAddress);
 279
 280    IX_OSAL_ASSERT((freeSramAddress - (aqmLocalBaseAddress + (IX_QMGR_QUEBUFFER_SPACE_OFFSET))) <=
 281              IX_QMGR_QUE_BUFFER_SPACE_SIZE);
 282
 283    /* The queue is now configured */
 284    cfgQueueInfo[qId].isConfigured = TRUE;
 285
 286    ixOsalMutexUnlock(&ixQMgrQCfgMutex);
 287
 288#ifndef NDEBUG
 289    /* Update statistics */
 290    stats.qStats[qId].isConfigured = TRUE;
 291    stats.qStats[qId].qName = cfgQueueInfo[qId].qName;
 292#endif
 293    return IX_SUCCESS;
 294}
 295
 296IxQMgrQSizeInWords
 297ixQMgrQSizeInWordsGet (IxQMgrQId qId)
 298{
 299    /* No parameter checking as this is used on the data path */
 300    return (cfgQueueInfo[qId].qSizeInWords);
 301}
 302
 303IX_STATUS
 304ixQMgrQSizeInEntriesGet (IxQMgrQId qId,
 305                         unsigned *qSizeInEntries)
 306{
 307    if (!ixQMgrQIsConfigured(qId))
 308    {
 309        return IX_QMGR_Q_NOT_CONFIGURED;
 310    }
 311
 312    if(NULL == qSizeInEntries)
 313    {
 314        return IX_QMGR_PARAMETER_ERROR;
 315    }
 316
 317    *qSizeInEntries = (UINT32)(cfgQueueInfo[qId].qSizeInWords) /
 318        (UINT32)cfgQueueInfo[qId].qEntrySizeInWords;
 319
 320    return IX_SUCCESS;
 321}
 322
 323IxQMgrQEntrySizeInWords
 324ixQMgrQEntrySizeInWordsGet (IxQMgrQId qId)
 325{
 326    /* No parameter checking as this is used on the data path */
 327    return (cfgQueueInfo[qId].qEntrySizeInWords);
 328}
 329
 330IX_STATUS
 331ixQMgrWatermarkSet (IxQMgrQId qId,
 332                    IxQMgrWMLevel ne,
 333                    IxQMgrWMLevel nf)
 334{    
 335    IxQMgrQStatus qStatusOnEntry;/* The queue status on entry/exit */
 336    IxQMgrQStatus qStatusOnExit; /* to this function               */
 337
 338    if (!ixQMgrQIsConfigured(qId))
 339    {
 340        return IX_QMGR_Q_NOT_CONFIGURED;
 341    }
 342
 343    if (!watermarkLevelIsOk (qId, ne))
 344    {
 345        return IX_QMGR_INVALID_Q_WM;
 346    }
 347
 348    if (!watermarkLevelIsOk (qId, nf))
 349    {
 350        return IX_QMGR_INVALID_Q_WM;
 351    }
 352
 353    /* Get the current queue status */
 354    ixQMgrAqmIfQueStatRead (qId, &qStatusOnEntry);
 355
 356#ifndef NDEBUG
 357    /* Update statistics */
 358    stats.wmSetCnt++;
 359#endif
 360
 361    ixQMgrAqmIfWatermarkSet (qId,
 362                            ne,
 363                            nf);
 364
 365    /* Get the current queue status */
 366    ixQMgrAqmIfQueStatRead (qId, &qStatusOnExit);
 367  
 368    /* If the status has changed return a warning */
 369    if (qStatusOnEntry != qStatusOnExit)
 370    {
 371        return IX_QMGR_WARNING;
 372    }
 373
 374    return IX_SUCCESS;
 375}
 376
 377IX_STATUS
 378ixQMgrAvailableSramAddressGet (UINT32 *address,
 379                              unsigned *sizeOfFreeRam)
 380{
 381    UINT32 aqmLocalBaseAddress;
 382
 383    if ((NULL == address)||(NULL == sizeOfFreeRam)) 
 384    {
 385        return IX_QMGR_PARAMETER_ERROR;
 386    }
 387    if (!cfgInitialized)
 388    {
 389        return IX_FAIL;
 390    }
 391
 392    *address = freeSramAddress;
 393
 394    /* Get the virtual SRAM address */
 395    ixQMgrAqmIfBaseAddressGet (&aqmLocalBaseAddress);
 396
 397    /* 
 398     * Calculate the size in bytes of free sram 
 399     * i.e. current free SRAM virtual pointer from
 400     *      (base + total size)
 401     */
 402    *sizeOfFreeRam = 
 403        (aqmLocalBaseAddress +
 404        IX_QMGR_AQM_SRAM_SIZE_IN_BYTES) -
 405        freeSramAddress;
 406
 407    if (0 == *sizeOfFreeRam)
 408    {
 409        return IX_QMGR_NO_AVAILABLE_SRAM;
 410    }
 411
 412    return IX_SUCCESS;
 413}
 414
 415BOOL
 416ixQMgrQIsConfigured (IxQMgrQId qId)
 417{
 418    if (!IX_QMGR_QID_IS_VALID(qId))
 419    {
 420        return FALSE;
 421    }
 422
 423    return cfgQueueInfo[qId].isConfigured;
 424}
 425
 426IxQMgrQCfgStats*
 427ixQMgrQCfgStatsGet (void)
 428{
 429    return &stats;
 430}
 431
 432IxQMgrQCfgStats*
 433ixQMgrQCfgQStatsGet (IxQMgrQId qId)
 434{
 435    unsigned int ne;
 436    unsigned int nf;
 437    UINT32 baseAddress;
 438    UINT32 readPtr;
 439    UINT32 writePtr;
 440
 441    stats.qStats[qId].qSizeInWords = cfgQueueInfo[qId].qSizeInWords;
 442    stats.qStats[qId].qEntrySizeInWords = cfgQueueInfo[qId].qEntrySizeInWords;
 443    
 444    if (IX_SUCCESS != ixQMgrQNumEntriesGet (qId, &stats.qStats[qId].numEntries))
 445    {
 446        if (IX_QMGR_WARNING != ixQMgrQNumEntriesGet (qId, &stats.qStats[qId].numEntries))
 447        {
 448           IX_QMGR_LOG_WARNING1("Failed to get the number of entries in queue.... %d\n", qId);
 449        }
 450    }
 451
 452    ixQMgrAqmIfQueCfgRead (qId,
 453                           stats.qStats[qId].numEntries,
 454                           &baseAddress,
 455                           &ne,
 456                           &nf,
 457                           &readPtr,
 458                           &writePtr);
 459        
 460    stats.qStats[qId].baseAddress = baseAddress;
 461    stats.qStats[qId].ne = ne;
 462    stats.qStats[qId].nf = nf;
 463    stats.qStats[qId].readPtr = readPtr;
 464    stats.qStats[qId].writePtr = writePtr;
 465
 466    return &stats;
 467}
 468
 469/* 
 470 * Static function definitions
 471 */
 472
 473PRIVATE BOOL
 474watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level)
 475{
 476    unsigned qSizeInEntries;
 477
 478    switch (level)
 479    {
 480        case IX_QMGR_Q_WM_LEVEL0: 
 481        case IX_QMGR_Q_WM_LEVEL1: 
 482        case IX_QMGR_Q_WM_LEVEL2: 
 483        case IX_QMGR_Q_WM_LEVEL4: 
 484        case IX_QMGR_Q_WM_LEVEL8: 
 485        case IX_QMGR_Q_WM_LEVEL16:
 486        case IX_QMGR_Q_WM_LEVEL32:
 487        case IX_QMGR_Q_WM_LEVEL64:
 488            break;
 489        default:
 490            return FALSE;
 491    }
 492
 493    /* Check watermark is not bigger than the qSizeInEntries */
 494    ixQMgrQSizeInEntriesGet(qId, &qSizeInEntries);
 495
 496    if ((unsigned)level > qSizeInEntries)
 497    {
 498        return FALSE;
 499    }
 500
 501    return TRUE;
 502}
 503
 504PRIVATE BOOL
 505qSizeInWordsIsOk (IxQMgrQSizeInWords qSize)
 506{
 507    BOOL status;
 508
 509    switch (qSize)
 510    {   
 511        case IX_QMGR_Q_SIZE16:
 512        case IX_QMGR_Q_SIZE32:
 513        case IX_QMGR_Q_SIZE64:
 514        case IX_QMGR_Q_SIZE128:
 515            status = TRUE;
 516            break;
 517        default:
 518            status = FALSE;
 519            break;
 520    }
 521
 522    return status;
 523}
 524
 525PRIVATE BOOL
 526qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize)
 527{
 528    BOOL status;
 529
 530    switch (entrySize)
 531    {
 532        case IX_QMGR_Q_ENTRY_SIZE1:
 533        case IX_QMGR_Q_ENTRY_SIZE2:
 534        case IX_QMGR_Q_ENTRY_SIZE4:
 535            status = TRUE;
 536            break;
 537        default:
 538            status = FALSE;
 539            break;
 540    }
 541
 542    return status;
 543}
 544