openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

oob.c (89032B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * OOB Flow Control and OOB Stats
      8  * Purpose: API to set different OOB Flow Control and OOB Stats registers.
      9  */
     10 
     11 #include <sal/core/libc.h>
     12 
     13 #include <shared/bsl.h>
     14 #include <soc/defs.h>
     15 
     16 #if defined(BCM_TRIDENT3_SUPPORT)
     17 #include <soc/drv.h>
     18 #include <soc/mem.h>
     19 #include <soc/profile_mem.h>
     20 #include <soc/debug.h>
     21 #include <soc/trident3.h>
     22 
     23 #include <bcm/error.h>
     24 #include <bcm/oob.h>
     25 
     26 #include <bcm_int/esw/mbcm.h>
     27 #include <bcm_int/esw/trident3.h>
     28 
     29 #include <bcm_int/esw_dispatch.h>
     30 #include <bcm_int/esw/stat.h>
     31 
     32 #ifdef BCM_WARM_BOOT_SUPPORT
     33 #include <bcm_int/esw/switch.h>
     34 #endif /* BCM_WARM_BOOT_SUPPORT */
     35 
     36 /* Number of Traffic Class */
     37 #define _TD3_NUM_TC  8
     38 /* Number of OOB FC Rx Interface */
     39 #define _TD3_NUM_OOB_FC_RX_INTF    4
     40 /* Maximum Value of Channel Base Value */
     41 #define _TD3_MAX_CHANNEL_BASE    63
     42 
     43 /* Total number of Indexes in OOBFC RX memory */
     44 #define _TD3_MAX_RX_MEM_ENTRY    96
     45 
     46 /* Maximum Value of OOB Stats Config_ID */
     47 #define _TD3_MAX_STATS_CONFIG_ID 3
     48 
     49 /* Total number of Indexes in OOB Stats Service Pool List */
     50 #define _TD3_MAX_IDX_STATS_POOL_LIST    8
     51 
     52 /* Total number of Indexes in OOB Stats UC Queue List */
     53 #define _TD3_MAX_IDX_STATS_QUEUE_LIST     1320
     54 
     55 /* Total number of UC Queue per port. */
     56 #define _TD3_NUM_UCAST_QUEUE_PER_PORT 10
     57 
     58 /* Total number of pipes per slice */
     59 #define _TD3_NUM_PIPE_PER_SLICE       2
     60 
     61 /* 0xF is the end of reporting of OOB Pool Stats */
     62 #define _TD3_OOB_STATS_END_POOL_REPORT   0xF
     63 
     64 /* 0x7FF is the end of reporting of OOB Queue Stats */
     65 #define _TD3_OOB_STATS_END_QUEUE_REPORT   0x7FF
     66 
     67 /* if OOBFC_CHANNEL_BASE.POOL_EN is not valid then use
     68  * OOBFC_CHANNEL_BASE.MC_EN; functionality is same based on
     69  * Architecture team*/
     70 #define _TD3_OOB_FC_TX_POOL_EN_SUPPORT 0
     71 #define _TD3_OOB_FC_TX_MC_EN_SUPPORT   1
     72 
     73 typedef struct _bcm_td3_oob_fc_rx_intf_info_s {
     74     uint32 channel_base; /* HCFC channel base */
     75     int enable;          /* Interface enable */
     76     uint8 num_ports;     /* Number of ports monitored */
     77     uint8 lookup_base;   /* Look up base in the OOB FC Rx Memory */
     78 } _bcm_td3_oob_fc_rx_intf_info_t;
     79     
     80 /*
     81  * Function:
     82  *      _bcm_td3_oob_fc_tx_config_flags_set
     83  * Purpose:
     84  *      Set OOB FC Tx enable flags
     85  * Parameters:
     86  *      unit - (IN) StrataSwitch unit number.
     87  *      flags - (IN) OOB FC Tx flags
     88  * Returns:
     89  *      BCM_E_XXX
     90  */
     91 STATIC int
     92 _bcm_td3_oob_fc_tx_config_flags_set(int unit, uint32 flags)
     93 {
     94     uint32 rval = 0;
     95     uint64 rval64;
     96     uint64 field64;
     97 
     98     COMPILER_64_ZERO(rval64);
     99     COMPILER_64_ZERO(field64);
    100 
    101     if (flags & BCM_OOB_FC_TX_FCN_EN) {
    102         BCM_IF_ERROR_RETURN
    103             (soc_reg32_get(unit, INTFO_FCN_ENr, 0, 0, &rval));
    104         soc_reg_field_set(unit, INTFO_FCN_ENr, &rval, ENf, 0x1);
    105         BCM_IF_ERROR_RETURN
    106             (soc_reg32_set(unit, INTFO_FCN_ENr, 0, 0, rval));
    107     } else {
    108         BCM_IF_ERROR_RETURN
    109             (soc_reg32_get(unit, INTFO_FCN_ENr, 0, 0, &rval));
    110         soc_reg_field_set(unit, INTFO_FCN_ENr, &rval, ENf, 0x0);
    111         BCM_IF_ERROR_RETURN
    112             (soc_reg32_set(unit, INTFO_FCN_ENr, 0, 0, rval));
    113     }
    114 
    115     BCM_IF_ERROR_RETURN
    116         (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r,
    117                        0, 0, &rval64));
    118     if (flags & BCM_OOB_FC_TX_ING_EN) {
    119         COMPILER_64_SET(field64, 0, 1);
    120     }
    121     soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64,
    122                         ING_ENf, field64);
    123 
    124     COMPILER_64_ZERO(field64);
    125     if (flags & BCM_OOB_FC_TX_EGR_EN) {
    126         COMPILER_64_SET(field64, 0, 1);
    127     }
    128     soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64,
    129                         ENG_ENf, field64);
    130     if (_TD3_OOB_FC_TX_POOL_EN_SUPPORT) {
    131         COMPILER_64_ZERO(field64);
    132         if (flags & BCM_OOB_FC_TX_POOL_EN) {
    133             COMPILER_64_SET(field64, 0, 1);
    134         }
    135         soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64,
    136                             POOL_ENf, field64);
    137 
    138         BCM_IF_ERROR_RETURN
    139             (soc_reg64_set(unit, OOBFC_CHANNEL_BASE_64r, 0, 0, rval64));
    140     } else if (_TD3_OOB_FC_TX_MC_EN_SUPPORT) {
    141         COMPILER_64_ZERO(field64);
    142         if (flags & BCM_OOB_FC_TX_POOL_EN) {
    143             COMPILER_64_SET(field64, 0, 1);
    144         }
    145         soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64,
    146                             MC_ENf, field64);
    147 
    148         BCM_IF_ERROR_RETURN
    149             (soc_reg64_set(unit, OOBFC_CHANNEL_BASE_64r, 0, 0, rval64));
    150     }
    151     return BCM_E_NONE;
    152 }
    153 
    154 /*
    155  * Function:
    156  *      _bcm_td3_oob_fc_tx_config_ipg_set
    157  * Purpose:
    158  *      Set OOB FC Tx inter packet gap
    159  * Parameters:
    160  *      unit - (IN) StrataSwitch unit number.
    161  *      ipg - (IN) OOB FC Tx inter packet gap
    162  * Returns:
    163  *      BCM_E_XXX
    164  */
    165 STATIC int
    166 _bcm_td3_oob_fc_tx_config_ipg_set(int unit, uint8 ipg)
    167 {
    168     uint32 rval;
    169 
    170     BCM_IF_ERROR_RETURN
    171         (soc_reg32_get(unit, OOBFC_TX_IDLEr, 0, 0, &rval));
    172     soc_reg_field_set(unit, OOBFC_TX_IDLEr, &rval,
    173                       IDLE_GAPf, ipg);
    174     BCM_IF_ERROR_RETURN
    175         (soc_reg32_set(unit, OOBFC_TX_IDLEr, 0, 0, rval));
    176     return BCM_E_NONE;
    177 }
    178 
    179 /*
    180  * Function:
    181  *      _bcm_td3_oob_fc_tx_config_gcs_id_set
    182  * Purpose:
    183  *      Set OOB FC Tx global congestion reporting
    184  *      service pool id
    185  * Parameters:
    186  *      unit - (IN) StrataSwitch unit number.
    187  *      id - (IN) OOB FC Tx global congestion service pool id
    188  * Returns:
    189  *      BCM_E_XXX
    190  */
    191 STATIC int
    192 _bcm_td3_oob_fc_tx_config_gcs_id_set(int unit,
    193                              bcm_service_pool_id_t id)
    194 {
    195     uint32 rval;
    196 
    197     BCM_IF_ERROR_RETURN
    198         (soc_reg32_get(unit, OOBFC_GCSr, 0, 0, &rval));
    199     soc_reg_field_set(unit, OOBFC_GCSr, &rval,
    200                       GCS_IDf, id);
    201     BCM_IF_ERROR_RETURN
    202         (soc_reg32_set(unit, OOBFC_GCSr, 0, 0, rval));
    203 
    204     return BCM_E_NONE;
    205 }
    206 
    207 /*
    208  * Function:
    209  *      _bcm_td3_oob_fc_tx_config_egr_mode_set
    210  * Purpose:
    211  *      Set OOB FC Tx egress congestion reporting mode
    212  * Parameters:
    213  *      unit - (IN) StrataSwitch unit number.
    214  *      mode - (IN) OOB FC Tx egress congestion reporting mode
    215  * Returns:
    216  *      BCM_E_XXX
    217  */
    218 STATIC int
    219 _bcm_td3_oob_fc_tx_config_egr_mode_set(int unit,
    220                              bcm_oob_egress_mode_t mode)
    221 {
    222     uint64 rval64;
    223     uint64 field64;
    224 
    225     COMPILER_64_ZERO(field64);
    226 
    227     BCM_IF_ERROR_RETURN
    228         (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r,
    229                        0, 0, &rval64));
    230     COMPILER_64_SET(field64, 0, mode);
    231     soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64,
    232                         ENG_MODEf, field64);
    233     BCM_IF_ERROR_RETURN
    234         (soc_reg64_set(unit, OOBFC_CHANNEL_BASE_64r,
    235                        0, 0, rval64));
    236 
    237     return BCM_E_NONE;
    238 }
    239 
    240 /*
    241  * Function:
    242  *      _bcm_td3_oob_fc_tx_config_flags_get
    243  * Purpose:
    244  *      Get OOB FC Tx enable status
    245  * Parameters:
    246  *      unit - (IN) StrataSwitch unit number.
    247  *      config - (OUT) OOB FC Tx configuration
    248  * Returns:
    249  *      BCM_E_XXX
    250  */
    251 STATIC int
    252 _bcm_td3_oob_fc_tx_config_flags_get(int unit,
    253                               bcm_oob_fc_tx_config_t *config)
    254 {
    255     uint32 rval = 0;
    256     uint64 rval64;
    257     uint64 regval64;
    258 
    259     COMPILER_64_ZERO(rval64);
    260     COMPILER_64_ZERO(regval64);
    261 
    262     config->flags = 0x0;
    263 
    264     BCM_IF_ERROR_RETURN
    265         (soc_reg32_get(unit, INTFO_FCN_ENr, 0, 0, &rval));
    266 
    267     if (soc_reg_field_get(unit, INTFO_FCN_ENr, rval, ENf)) {
    268         config->flags |= BCM_OOB_FC_TX_FCN_EN;
    269     }
    270 
    271     BCM_IF_ERROR_RETURN
    272         (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r,
    273                        0, 0, &rval64));
    274 
    275     regval64 = soc_reg64_field_get(unit, OOBFC_CHANNEL_BASE_64r,
    276                             rval64, ING_ENf);
    277     if (!COMPILER_64_IS_ZERO(regval64)) {
    278         config->flags |= BCM_OOB_FC_TX_ING_EN;
    279     }
    280 
    281     regval64 = soc_reg64_field_get(unit, OOBFC_CHANNEL_BASE_64r,
    282                             rval64, ENG_ENf);
    283     if (!COMPILER_64_IS_ZERO(regval64)) {
    284         config->flags |= BCM_OOB_FC_TX_EGR_EN;
    285     }
    286     if (_TD3_OOB_FC_TX_POOL_EN_SUPPORT) {
    287         regval64 = soc_reg64_field_get(unit, OOBFC_CHANNEL_BASE_64r,
    288                                 rval64, POOL_ENf);
    289         if (!COMPILER_64_IS_ZERO(regval64)) {
    290             config->flags |= BCM_OOB_FC_TX_POOL_EN;
    291         }
    292     } else if (_TD3_OOB_FC_TX_MC_EN_SUPPORT) {
    293         regval64 = soc_reg64_field_get(unit, OOBFC_CHANNEL_BASE_64r,
    294                                 rval64, MC_ENf);
    295         if (!COMPILER_64_IS_ZERO(regval64)) {
    296             config->flags |= BCM_OOB_FC_TX_POOL_EN;
    297         }
    298     }
    299 
    300     return BCM_E_NONE;
    301 }
    302 
    303 /*
    304  * Function:
    305  *      _bcm_td3_oob_fc_tx_config_ipg_get
    306  * Purpose:
    307  *      Get OOB FC Tx inter packet gap
    308  * Parameters:
    309  *      unit - (IN) StrataSwitch unit number.
    310  *      config - (OUT) OOB FC Tx configuration
    311  * Returns:
    312  *      BCM_E_XXX
    313  */
    314 STATIC int
    315 _bcm_td3_oob_fc_tx_config_ipg_get(int unit,
    316                             bcm_oob_fc_tx_config_t *config)
    317 {
    318     uint32 rval;
    319 
    320     BCM_IF_ERROR_RETURN
    321         (soc_reg32_get(unit, OOBFC_TX_IDLEr, 0, 0, &rval));
    322 
    323     config->inter_pkt_gap = soc_reg_field_get(unit, OOBFC_TX_IDLEr,
    324                                               rval, IDLE_GAPf);
    325 
    326     return BCM_E_NONE;
    327 }
    328 
    329 /*
    330  * Function:
    331  *      _bcm_td3_oob_fc_tx_config_gcs_id_get
    332  * Purpose:
    333  *      Get OOB FC Tx global congestion reporting
    334  *      service pool id
    335  * Parameters:
    336  *      unit - (IN) StrataSwitch unit number.
    337  *      config - (OUT) OOB FC Tx configuration
    338  * Returns:
    339  *      BCM_E_XXX
    340  */
    341 STATIC int
    342 _bcm_td3_oob_fc_tx_config_gcs_id_get(int unit,
    343                               bcm_oob_fc_tx_config_t *config)
    344 {
    345     uint32 rval;
    346 
    347     BCM_IF_ERROR_RETURN
    348         (soc_reg32_get(unit, OOBFC_GCSr, 0, 0, &rval));
    349 
    350     config->gcs_id = soc_reg_field_get(unit, OOBFC_GCSr, rval,
    351                                        GCS_IDf);
    352 
    353     return BCM_E_NONE;
    354 }
    355 
    356 /*
    357  * Function:
    358  *      _bcm_td3_oob_fc_tx_config_egr_mode_get
    359  * Purpose:
    360  *      Get OOB FC Tx egress congestion reporting mode
    361  * Parameters:
    362  *      unit - (IN) StrataSwitch unit number.
    363  *      config - (OUT) OOB FC Tx configuration
    364  * Returns:
    365  *      BCM_E_XXX
    366  */
    367 STATIC int
    368 _bcm_td3_oob_fc_tx_config_egr_mode_get(int unit,
    369                                   bcm_oob_fc_tx_config_t *config)
    370 {
    371     uint64 rval64;
    372 
    373     BCM_IF_ERROR_RETURN
    374         (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r,
    375                        0, 0, &rval64));
    376 
    377     config->egr_mode = soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r,
    378                                              rval64, ENG_MODEf);
    379 
    380     return BCM_E_NONE;
    381 }
    382 
    383 /*
    384  * Function:
    385  *      _bcm_td3_oob_localport_resolve
    386  * Purpose:
    387  *      Get the logical port from modport gport
    388  * Parameters:
    389  *      unit - (IN) StrataSwitch unit number.
    390  *      gport - (IN) Modport gport.
    391  *      local_port - (OUT) Logical port number.
    392  * Returns:
    393  *      BCM_E_XXX
    394  */
    395 STATIC int
    396 _bcm_td3_oob_localport_resolve(int unit, bcm_gport_t gport,
    397                         bcm_port_t *local_port)
    398 {
    399     bcm_module_t module;
    400     bcm_port_t port;
    401     bcm_trunk_t trunk;
    402     int id, result;
    403 
    404     if (!BCM_GPORT_IS_SET(gport)) {
    405         if (!SOC_PORT_VALID(unit, gport)) {
    406             return BCM_E_PORT;
    407         }
    408         *local_port = gport;
    409         return BCM_E_NONE;
    410     }
    411 
    412     BCM_IF_ERROR_RETURN
    413         (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id));
    414 
    415     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result));
    416     if (result == FALSE) {
    417         return BCM_E_PARAM;
    418     }
    419 
    420     *local_port = port;
    421 
    422     return BCM_E_NONE;
    423 }
    424 
    425 /*
    426  * Function:
    427  *      _bcm_td3_oob_fc_rx_get_intf_info
    428  * Purpose:
    429  *      Get the per OOBFC Rx interface info structure
    430  * Parameters:
    431  *      unit - (IN) StrataSwitch unit number.
    432  *      info - (OUT) Per OOBFC RX interface info structure.
    433  *      intf_id - (IN) OOBFC Rx Interface ID.
    434  * Returns:
    435  *      BCM_E_XXX
    436  */
    437 STATIC int
    438 _bcm_td3_oob_fc_rx_get_intf_info(int unit, _bcm_td3_oob_fc_rx_intf_info_t *info,
    439                             bcm_oob_fc_rx_intf_id_t intf_id)
    440 {
    441     uint32 rval = 0x0;
    442     soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r,
    443                                                  OOBFC_CHIF_CFG1r,
    444                                                  OOBFC_CHIF_CFG2r,
    445                                                  OOBFC_CHIF_CFG3r};
    446 
    447     BCM_IF_ERROR_RETURN
    448         (soc_reg32_get(unit, cfg_reg[intf_id], 0, 0, &rval));
    449         
    450     info->enable = soc_reg_field_get(unit, cfg_reg[intf_id], rval,
    451                                      OOBFC_CH_ENf);
    452     if (info->enable == 1) {
    453         info->num_ports = soc_reg_field_get(unit, cfg_reg[intf_id], rval,
    454                                             CH_PORT_NUMf);
    455         info->lookup_base = soc_reg_field_get(unit, cfg_reg[intf_id], rval,
    456                                               LOOKUP_BASEf);
    457         info->channel_base = soc_reg_field_get(unit, cfg_reg[intf_id], rval,
    458                                                OOBFC_CH_BASEf);
    459     }
    460     return BCM_E_NONE;
    461 }
    462 
    463 /*
    464  * Function:
    465  *      _bcm_td3_oob_fc_rx_disable_intf
    466  * Purpose:
    467  *      Disable OOBFC Rx interface.
    468  * Parameters:
    469  *      unit - (IN) StrataSwitch unit number.
    470  *      intf_id - (IN) OOBFC Rx Interface ID.
    471  * Returns:
    472  *      BCM_E_XXX
    473  */
    474 STATIC int
    475 _bcm_td3_oob_fc_rx_disable_intf(int unit,
    476                            bcm_oob_fc_rx_intf_id_t intf_id)
    477 {
    478     uint32 rval = 0x0;
    479     soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r,
    480                                                  OOBFC_CHIF_CFG1r,
    481                                                  OOBFC_CHIF_CFG2r,
    482                                                  OOBFC_CHIF_CFG3r};
    483 
    484     BCM_IF_ERROR_RETURN
    485         (soc_reg32_get(unit, cfg_reg[intf_id], 0, 0, &rval));
    486     soc_reg_field_set(unit, cfg_reg[intf_id], &rval,
    487                       OOBFC_CH_ENf, 0);
    488     BCM_IF_ERROR_RETURN
    489         (soc_reg32_set(unit, cfg_reg[intf_id], 0, 0, rval));
    490 
    491     return BCM_E_NONE;
    492 }
    493 
    494 /*
    495  * Function:
    496  *      _bcm_td3_oob_fc_rx_enable_intf
    497  * Purpose:
    498  *      Enable OOBFC Rx interface.
    499  * Parameters:
    500  *      unit - (IN) StrataSwitch unit number.
    501  *      intf_id - (IN) OOBFC Rx Interface ID.
    502  * Returns:
    503  *      BCM_E_XXX
    504  */
    505 STATIC int
    506 _bcm_td3_oob_fc_rx_enable_intf(int unit,
    507                           bcm_oob_fc_rx_intf_id_t intf_id)
    508 {
    509     uint32 rval = 0x0;
    510     soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r,
    511                                                  OOBFC_CHIF_CFG1r,
    512                                                  OOBFC_CHIF_CFG2r,
    513                                                  OOBFC_CHIF_CFG3r};
    514 
    515     BCM_IF_ERROR_RETURN
    516         (soc_reg32_get(unit, cfg_reg[intf_id], 0, 0, &rval));
    517 
    518     soc_reg_field_set(unit, cfg_reg[intf_id], &rval,
    519                       OOBFC_CH_ENf, 1);
    520     BCM_IF_ERROR_RETURN
    521         (soc_reg32_set(unit, cfg_reg[intf_id], 0, 0, rval));
    522 
    523     return BCM_E_NONE;
    524 }
    525 
    526 /*
    527  * Function:
    528  *      _bcm_td3_oob_fc_rx_intf_get_lookup_base
    529  * Purpose:
    530  *      Get the look base in OOBFC Rx Memory for
    531  *      given OOBFC Rx interface.
    532  * Parameters:
    533  *      unit - (IN) StrataSwitch unit number.
    534  *      intf_id - (IN) OOBFC Rx Interface ID.
    535  *      look_base - (OUT) Lookup base in OOBFC Rx Memory
    536  * Returns:
    537  *      BCM_E_XXX
    538  */
    539 STATIC int
    540 _bcm_td3_oob_fc_rx_intf_get_lookup_base(int unit,
    541                                 bcm_oob_fc_rx_intf_id_t intf_id,
    542                                 uint32 *lookup_base)
    543 {
    544     uint32 rval = 0x0;
    545     soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r,
    546                                                  OOBFC_CHIF_CFG1r,
    547                                                  OOBFC_CHIF_CFG2r,
    548                                                  OOBFC_CHIF_CFG3r};
    549 
    550     BCM_IF_ERROR_RETURN
    551         (soc_reg32_get(unit, cfg_reg[intf_id], 0, 0, &rval));
    552 
    553     *lookup_base = soc_reg_field_get(unit, cfg_reg[intf_id], rval,
    554                                      LOOKUP_BASEf);
    555 
    556     return BCM_E_NONE;
    557 }
    558 
    559 
    560 /*
    561  * Function:
    562  *      bcm_td3_oob_fc_tx_config_set
    563  * Purpose:
    564  *      Set OOB FC Tx global configuration.
    565  * Parameters:
    566  *      unit - (IN) StrataSwitch unit number.
    567  *      config - (IN) OOB FC Tx global configuration
    568  * Returns:
    569  *      BCM_E_XXX
    570  */
    571 int
    572 bcm_td3_oob_fc_tx_config_set(int unit,
    573                             bcm_oob_fc_tx_config_t *config)
    574 {
    575     if (config == NULL) {
    576         return BCM_E_PARAM;
    577     }
    578 
    579     if ((config->gcs_id < 0) && (config->gcs_id >= _TD3_MMU_NUM_POOL)) {
    580         return BCM_E_PARAM;
    581     }
    582 
    583     if ((config->egr_mode < 0) && (config->egr_mode >= bcmOOBFCTxReportCount)) {
    584         return BCM_E_PARAM;
    585     }
    586 
    587     /* Enabling/Disabling FCN, OOBFC Tx Ingress, Egress and Service Pool */ 
    588     BCM_IF_ERROR_RETURN
    589         (_bcm_td3_oob_fc_tx_config_flags_set(unit, config->flags));
    590 
    591     /* Setting Inter packet Gap between two HCFC message */
    592     BCM_IF_ERROR_RETURN
    593         (_bcm_td3_oob_fc_tx_config_ipg_set(unit, config->inter_pkt_gap));
    594 
    595     /* Setting service pool id whose congestion state will be
    596        reported in every HCFC message */
    597     BCM_IF_ERROR_RETURN
    598         (_bcm_td3_oob_fc_tx_config_gcs_id_set(unit, config->gcs_id));
    599 
    600     /* Setting Egress mode for reporting OOBFC message. */
    601     BCM_IF_ERROR_RETURN
    602         (_bcm_td3_oob_fc_tx_config_egr_mode_set(unit, config->egr_mode));
    603 
    604     return BCM_E_NONE;
    605 }
    606 
    607 /*
    608  * Function:
    609  *      bcm_td3_oob_fc_tx_config_get
    610  * Purpose:
    611  *      Get OOB FC Tx global configuration.
    612  * Parameters:
    613  *      unit - (IN) StrataSwitch unit number.
    614  *      config - (OUT) OOB FC Tx global configuration
    615  * Returns:
    616  *      BCM_E_XXX
    617  */
    618 int
    619 bcm_td3_oob_fc_tx_config_get(int unit,
    620                             bcm_oob_fc_tx_config_t *config)
    621 {
    622     if (config == NULL) {
    623         return BCM_E_PARAM;
    624     }
    625 
    626     /* Get the congestion state reporting status of FCN,
    627        OOBFC Tx Ingress, Egress and Service Pool */
    628     BCM_IF_ERROR_RETURN
    629         (_bcm_td3_oob_fc_tx_config_flags_get(unit, config));
    630 
    631     /* Get the configured Inter Packet Gap between OOBFC Tx message.*/
    632     BCM_IF_ERROR_RETURN
    633         (_bcm_td3_oob_fc_tx_config_ipg_get(unit, config));
    634 
    635     /* Setting service pool id whose congestion state will be
    636        reported in every HCFC message */
    637     BCM_IF_ERROR_RETURN
    638         (_bcm_td3_oob_fc_tx_config_gcs_id_get(unit, config));
    639 
    640     /* Get the configured Egress mode of OOBFC Tx side */
    641     BCM_IF_ERROR_RETURN
    642         (_bcm_td3_oob_fc_tx_config_egr_mode_get(unit, config));
    643 
    644     return BCM_E_NONE;
    645 }
    646 
    647 /*
    648  * Function:
    649  *      _bcm_td3_oob_fc_tx_port_control_set
    650  * Purpose:
    651  *      Set OOB FC Tx Port configuration.
    652  * Parameters:
    653  *      unit - (IN) StrataSwitch unit number.
    654  *      gport - (IN) Modport Gport
    655  *      status - (IN) Status of Congestion State reporting 
    656  *      dir - (IN) Direction 0 = Ingreess, 1 = Egress
    657  * Returns:
    658  *      BCM_E_XXX
    659  */
    660 int
    661 _bcm_td3_oob_fc_tx_port_control_set(int unit, bcm_port_t localport,
    662                               int status, int dir)
    663 {
    664     uint32 rval = 0;
    665     uint64 rval64;
    666     static const soc_field_t field[2] = {ING_PORT_ENf, ENG_PORT_ENf};
    667     static const soc_reg_t reg[2][3] = {
    668         {OOBFC_ING_PORT_EN0_64r, OOBFC_ING_PORT_EN1_64r, OOBFC_ING_PORT_EN2r},
    669         {OOBFC_ENG_PORT_EN0_64r, OOBFC_ENG_PORT_EN1_64r, OOBFC_ENG_PORT_EN2r}};
    670 
    671     if ((status != 1) && (status != 0)) {
    672         return BCM_E_PARAM;
    673     }
    674 
    675     if (dir > 1) {
    676         return BCM_E_PARAM;
    677     }
    678 
    679     COMPILER_64_ZERO(rval64);
    680 
    681     if ((localport >= 0) && (localport < 64)) {
    682         /* For logical port 0-63 */
    683         if (dir == 1) {
    684             /* Setting per egress port QSEL only for the first time when
    685                enable/disable congestion state reporting of OOBFC */
    686             BCM_IF_ERROR_RETURN
    687                 (soc_reg64_get(unit, OOBFC_ENG_PORT_QSEL0_64r,
    688                                0, 0, &rval64));
    689             if (!COMPILER_64_BITTEST(rval64, localport)) {
    690                 COMPILER_64_BITSET(rval64, localport);
    691                 soc_reg64_field_set(unit, OOBFC_ENG_PORT_QSEL0_64r, &rval64,
    692                                     ENG_PORT_QSELf, rval64);
    693                 BCM_IF_ERROR_RETURN
    694                     (soc_reg64_set(unit, OOBFC_ENG_PORT_QSEL0_64r,
    695                                    0, 0, rval64));
    696             }
    697         }
    698 
    699         BCM_IF_ERROR_RETURN
    700             (soc_reg64_get(unit, reg[dir][0], 0, 0, &rval64));
    701         if (((status == 1) && (!COMPILER_64_BITTEST(rval64, localport))) ||
    702             ((status == 0) && (COMPILER_64_BITTEST(rval64, localport)))) {
    703             if (status == 1) {
    704                 COMPILER_64_BITSET(rval64, localport);
    705             } else {
    706                 COMPILER_64_BITCLR(rval64, localport);
    707             }
    708             soc_reg64_field_set(unit, reg[dir][0], &rval64,
    709                                 field[dir], rval64);
    710             BCM_IF_ERROR_RETURN
    711                 (soc_reg64_set(unit, reg[dir][0], 0, 0, rval64));
    712         }
    713     } else if ((localport >= 64) && (localport < 128)) {
    714         /* For logical port 64-127 */
    715         if (dir == 1) {
    716             /* Setting per egress port QSEL only for the first time when
    717                enable/disable congestion state reporting of OOBFC */
    718             BCM_IF_ERROR_RETURN
    719                 (soc_reg64_get(unit, OOBFC_ENG_PORT_QSEL1_64r,
    720                                0, 0, &rval64));
    721             if (!COMPILER_64_BITTEST(rval64, (localport % 64))) {
    722                 COMPILER_64_BITSET(rval64, (localport % 64));
    723                 soc_reg64_field_set(unit, OOBFC_ENG_PORT_QSEL1_64r, &rval64,
    724                                     ENG_PORT_QSELf, rval64);
    725                 BCM_IF_ERROR_RETURN
    726                     (soc_reg64_set(unit, OOBFC_ENG_PORT_QSEL1_64r,
    727                                    0, 0, rval64));
    728             }
    729         }
    730 
    731         BCM_IF_ERROR_RETURN
    732             (soc_reg64_get(unit, reg[dir][1], 0, 0, &rval64));
    733         if (((status == 1) && (!COMPILER_64_BITTEST(rval64, (localport % 64)))) ||
    734             ((status == 0) && (COMPILER_64_BITTEST(rval64, (localport % 64))))) {
    735             if (status == 1) {
    736                 COMPILER_64_BITSET(rval64, (localport % 64));
    737             } else {
    738                 COMPILER_64_BITCLR(rval64, (localport % 64));
    739             }
    740             soc_reg64_field_set(unit, reg[dir][1], &rval64,
    741                                 field[dir], rval64);
    742             BCM_IF_ERROR_RETURN
    743                 (soc_reg64_set(unit, reg[dir][1], 0, 0, rval64));
    744         }
    745     } else if ((localport >= 128) && (localport < 136)) {
    746         /* For logical port 128-135 */
    747         if (dir == 1) {
    748             /* Setting per egress port QSEL only for the first time when
    749                enable/disable congestion state reporting of OOBFC */
    750             BCM_IF_ERROR_RETURN
    751                 (soc_reg32_get(unit, OOBFC_ENG_PORT_QSEL2r,
    752                                0, 0, &rval));
    753             if (!(rval & (0x1 << (localport % 128)))) {
    754                 rval |= 0x1 << (localport % 128);
    755                 rval &= 0xFF;
    756                 soc_reg_field_set(unit, OOBFC_ENG_PORT_QSEL2r, &rval,
    757                                     ENG_PORT_QSELf, rval);
    758                 BCM_IF_ERROR_RETURN
    759                     (soc_reg32_set(unit, OOBFC_ENG_PORT_QSEL2r,
    760                                    0, 0, rval));
    761             }
    762         }
    763 
    764         BCM_IF_ERROR_RETURN
    765             (soc_reg32_get(unit, reg[dir][2], 0, 0, &rval));
    766         if (((status == 1) && (!(rval & (0x1 << (localport % 128))))) ||
    767             ((status == 0) && ((rval & (0x1 << (localport % 128)))))) {
    768             if (status == 1) {
    769                 rval |= 0x1 << (localport % 128);
    770                 rval &= 0xFF;
    771             } else {
    772                 rval &= ~(0x1 << (localport % 128));
    773                 rval &= 0xFF;
    774             }
    775             soc_reg_field_set(unit, reg[dir][2], &rval, field[dir], rval);
    776 
    777             BCM_IF_ERROR_RETURN
    778                 (soc_reg32_set(unit, reg[dir][2], 0, 0, rval));
    779         }
    780     } else {
    781         return BCM_E_PARAM;
    782     }
    783 
    784     return BCM_E_NONE;
    785 }
    786 
    787 /*
    788  * Function:
    789  *      _bcm_td3_oob_fc_tx_port_control_get
    790  * Purpose:
    791  *      Get OOB FC Tx side Port configuration.
    792  * Parameters:
    793  *      unit - (IN) StrataSwitch unit number.
    794  *      gport - (IN) Modport Gport
    795  *      status - (OUT) Status of Congestion State reporting 
    796  *      dir - (IN) Direction 0 = Ingreess, 1 = Egress
    797  * Returns:
    798  *      BCM_E_XXX
    799  */
    800 int
    801 _bcm_td3_oob_fc_tx_port_control_get(int unit, bcm_port_t localport,
    802                                  int *status, int dir)
    803 {
    804     uint32 rval = 0;
    805     uint64 rval64;
    806     static const soc_reg_t reg[2][3] = {
    807         {OOBFC_ING_PORT_EN0_64r, OOBFC_ING_PORT_EN1_64r, OOBFC_ING_PORT_EN2r},
    808         {OOBFC_ENG_PORT_EN0_64r, OOBFC_ENG_PORT_EN1_64r, OOBFC_ENG_PORT_EN2r}};
    809 
    810     if (dir > 1) {
    811         return BCM_E_PARAM;
    812     }
    813 
    814     COMPILER_64_ZERO(rval64);
    815 
    816     if ((localport >= 0) && (localport < 64)) {
    817         /* For logical port 0-63 */
    818         BCM_IF_ERROR_RETURN
    819             (soc_reg64_get(unit, reg[dir][0], 0, 0, &rval64));
    820         if (COMPILER_64_BITTEST(rval64, localport)) {
    821             *status = 0x1;
    822         } else {
    823             *status = 0x0;
    824         }
    825     } else if ((localport >= 64) && (localport < 128)) {
    826         /* For logical port 64-127 */
    827         BCM_IF_ERROR_RETURN
    828             (soc_reg64_get(unit, reg[dir][1], 0, 0, &rval64));
    829 
    830         if (COMPILER_64_BITTEST(rval64, (localport % 64))) {
    831             *status = 0x1;
    832         } else {
    833             *status = 0x0;
    834         }
    835     } else if ((localport >= 128) && (localport < 136)) {
    836         /* For logical port 128-135 */
    837         BCM_IF_ERROR_RETURN
    838             (soc_reg32_get(unit, reg[dir][2], 0, 0, &rval));
    839         if (rval & (0x1 << (localport % 128))) {
    840             *status = 0x1;
    841         } else {
    842             *status = 0x0;
    843         }
    844     } else {
    845         return BCM_E_PARAM;
    846     }
    847 
    848     return BCM_E_NONE;
    849 }
    850 
    851 /*
    852 * Function:
    853 *      bcm_td3_oob_fc_tx_info_get
    854 * Purpose:
    855 *      Get OOB FC Tx global information.
    856 * Parameters:
    857 *      unit - (IN) StrataSwitch unit number.
    858 *      info - (OUT) OOB FC Tx global information
    859 * Returns:
    860 *      BCM_E_XXX
    861 */
    862 int
    863 bcm_td3_oob_fc_tx_info_get(int unit, bcm_oob_fc_tx_info_t *info)
    864 {
    865     uint64 rval64;
    866 
    867     if (info == NULL) {
    868         return BCM_E_PARAM;
    869     }
    870 
    871     BCM_IF_ERROR_RETURN
    872         (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r,
    873                        0, 0, &rval64));
    874 
    875     /* Get the Channel base value for HCFC messages containing
    876        congestion state of different resources */
    877     /* Ingress Ports */
    878     info->ing_base =  (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r,
    879                                                    rval64, ING_BASEf);
    880 
    881     /* Egress Unicast Queue */
    882     info->ucast_base =  (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r,
    883                                                      rval64, ENGU_BASEf);
    884 
    885     /* Egress Multicast Queue */
    886     info->mcast_base =  (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r,
    887                                                      rval64, ENGM_BASEf);
    888 
    889     /* Egress Cos Queue */
    890     info->cos_base =  (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r,
    891                                                    rval64, ENGG_BASEf);
    892     if (_TD3_OOB_FC_TX_POOL_EN_SUPPORT) {
    893         /* Ingress and Egress Service Pool Congestion */
    894         info->pool_base =  (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r,
    895                                                       rval64, POOL_BASEf);
    896     } else if (_TD3_OOB_FC_TX_MC_EN_SUPPORT) {
    897         info->pool_base =  (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r,
    898                                                       rval64, MC_BASEf);
    899     }
    900     return BCM_E_NONE;
    901 }
    902 
    903 /*
    904  * Function:
    905  *      _bcm_td3_oob_fc_rx_config_enable_set
    906  * Purpose:
    907  *      Enable and configure the given OOB FC Rx Interface
    908  * Parameters:
    909  *      unit - (IN) StrataSwitch unit number
    910  *      intf_id - (IN) OOB FC Rx Interface Number
    911  *      channel_base - (IN) HCFC channel base
    912  *      array_count - (IN) Number of gports in the gport array
    913  *      gport_array - (IN) Array of modport type gport
    914  * Returns:
    915  *      BCM_E_XXX
    916  */
    917 STATIC int
    918 _bcm_td3_oob_fc_rx_config_enable_set(int unit,
    919                             bcm_oob_fc_rx_intf_id_t intf_id,
    920                             uint8 channel_base,
    921                             int array_count,
    922                             bcm_gport_t *gport_array)
    923 {
    924     _bcm_td3_oob_fc_rx_intf_info_t info[_TD3_NUM_OOB_FC_RX_INTF];
    925     char *sysport_buf, *tc2pri_buf;
    926     uint32 sysport_list[_TD3_MAX_RX_MEM_ENTRY];
    927     int rv = BCM_E_INTERNAL;
    928     void *pentry1, *pentry2;
    929     uint32 rval = 0x0;
    930     int mem_wsz = 0;
    931     int i = 0, total_num_ports = 0;
    932     bcm_port_t localport;
    933     uint64 tc_to_pri_mapping;
    934     uint32 tc_to_pri_mapping_low = 0x0;
    935     uint32 tc_to_pri_mapping_high = 0x0;
    936     soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r,
    937                                                  OOBFC_CHIF_CFG1r,
    938                                                  OOBFC_CHIF_CFG2r,
    939                                                  OOBFC_CHIF_CFG3r};
    940 
    941     COMPILER_64_ZERO(tc_to_pri_mapping);
    942 
    943     sal_memset(info, 0, sizeof(_bcm_td3_oob_fc_rx_intf_info_t) *
    944                _TD3_NUM_OOB_FC_RX_INTF);
    945     sal_memset(sysport_list, 0, sizeof(uint32) *
    946                _TD3_MAX_RX_MEM_ENTRY);
    947 
    948     /* Backup the per OOBFC Rx interface configuration */
    949     for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) {
    950         BCM_IF_ERROR_RETURN
    951             (_bcm_td3_oob_fc_rx_get_intf_info(unit, &info[i], i));
    952         /* Compute the total number of ports which is
    953            already configured */
    954         if (info[i].enable == 1) {
    955             total_num_ports += info[i].num_ports;
    956         }
    957     }
    958 
    959     /* Return error if trying to enable already enabled
    960        OOBFC Rx Interface */
    961     if (info[intf_id].enable == 1) {
    962         return BCM_E_PARAM;
    963     }
    964 
    965     /* Return error if there is no room in memory to accomodate
    966        the list of ports which need to programmed in memory */
    967     if ((total_num_ports + array_count) > _TD3_MAX_RX_MEM_ENTRY) {
    968         return BCM_E_PARAM;
    969     }
    970 
    971     /* Read the MMU_CHFC_SYSPORT_MAPPING memory into sysport_buf */
    972     mem_wsz = sizeof(uint32) *
    973                 soc_mem_entry_words(unit, MMU_CHFC_SYSPORT_MAPPINGm);
    974     sysport_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz,
    975                                 "oob sysport_buf");
    976     if (sysport_buf == NULL) {
    977         return BCM_E_MEMORY;
    978     }
    979 
    980     if (soc_mem_read_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL,
    981                            0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) {
    982         rv = BCM_E_INTERNAL;
    983         soc_cm_sfree(unit, sysport_buf);
    984         return rv;
    985     }
    986 
    987     /* Read the MMU_INTFO_TC2PRI_MAPPING memory into tc2pri_buf */
    988     mem_wsz = sizeof(uint32) *
    989                 soc_mem_entry_words(unit, MMU_INTFO_TC2PRI_MAPPINGm);
    990     tc2pri_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz,
    991                                "oob tc2pri_buf");
    992     if (tc2pri_buf == NULL) {
    993         rv = BCM_E_MEMORY;
    994         soc_cm_sfree(unit, sysport_buf);
    995         return rv;
    996     }
    997 
    998     if (soc_mem_read_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL,
    999                            0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) {
   1000         rv = BCM_E_INTERNAL;
   1001         soc_cm_sfree(unit, tc2pri_buf);
   1002         soc_cm_sfree(unit, sysport_buf);
   1003         return rv;
   1004     }
   1005 
   1006     /* Creating a list of logical port number from a list of
   1007        modport gport */
   1008     for (i = 0; i < array_count; i++) {
   1009         rv = _bcm_td3_oob_localport_resolve(unit, gport_array[i],
   1010                                            &localport);
   1011         if (rv != BCM_E_NONE) {
   1012             soc_cm_sfree(unit, tc2pri_buf);
   1013             soc_cm_sfree(unit, sysport_buf);
   1014             return rv;
   1015         }
   1016         sysport_list[i] = localport;
   1017     }
   1018 
   1019     /* Fill the info structure for the given interface */
   1020     info[intf_id].enable = 1;
   1021     info[intf_id].channel_base = channel_base;
   1022     info[intf_id].lookup_base = total_num_ports;
   1023     info[intf_id].num_ports = array_count;
   1024 
   1025     /* Program sysport_list in MMU_CHFC_SYSPORT_MAPPING */
   1026     /* Program default value into MMU_INTFO_TC2PRI_MAPPING */
   1027     for (i = 0; i < array_count; i++) {
   1028         pentry1 = soc_mem_table_idx_to_pointer(unit,
   1029                                                MMU_CHFC_SYSPORT_MAPPINGm,
   1030                                                void*, sysport_buf,
   1031                                                (total_num_ports + i));
   1032         pentry2 = soc_mem_table_idx_to_pointer(unit,
   1033                                                MMU_INTFO_TC2PRI_MAPPINGm,
   1034                                                void*, tc2pri_buf,
   1035                                                (total_num_ports + i));
   1036         soc_mem_field32_set(unit, MMU_CHFC_SYSPORT_MAPPINGm, pentry1,
   1037                             SYS_PORTf, sysport_list[i]);
   1038         /* TC to PRI Mapping Default Value is unity mapped
   1039            TC=7 mapped PRI=7 0x80 (bits 63-56)
   1040            TC=6 mapped PRI=6 0x40 (bits 55-48)
   1041            TC=5 mapped PRI=5 0x20 (bits 47-40) 
   1042            TC=4 mapped PRI=4 0x10 (bits 39-32)
   1043            TC=3 mapped PRI=3 0x08 (bits 31-24)
   1044            TC=2 mapped PRI=2 0x04 (bits 23-16)
   1045            TC=1 mapped PRI=1 0x02 (bits 15-8)
   1046            TC=0 mapped PRI=0 0x01 (bits 7-0)
   1047          */
   1048         tc_to_pri_mapping_high |= 0x80 << 24;
   1049         tc_to_pri_mapping_high |= 0x40 << 16;
   1050         tc_to_pri_mapping_high |= 0x20 << 8;
   1051         tc_to_pri_mapping_high |= 0x10;
   1052         tc_to_pri_mapping_low |= 0x08 << 24;
   1053         tc_to_pri_mapping_low |= 0x04 << 16;
   1054         tc_to_pri_mapping_low |= 0x02 << 8;
   1055         tc_to_pri_mapping_low |= 0x01;
   1056 
   1057         COMPILER_64_SET(tc_to_pri_mapping, tc_to_pri_mapping_high,
   1058                         tc_to_pri_mapping_low);
   1059 
   1060         soc_mem_field64_set(unit, MMU_INTFO_TC2PRI_MAPPINGm,
   1061                             pentry2, PRI_BMPf, tc_to_pri_mapping);
   1062     }
   1063 
   1064     if (soc_mem_write_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL,
   1065                             0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) {
   1066         rv = BCM_E_INTERNAL;
   1067         soc_cm_sfree(unit, tc2pri_buf);
   1068         soc_cm_sfree(unit, sysport_buf);
   1069         return rv;
   1070     }
   1071 
   1072     if (soc_mem_write_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL,
   1073                             0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) {
   1074         rv = BCM_E_INTERNAL;
   1075         soc_cm_sfree(unit, tc2pri_buf);
   1076         soc_cm_sfree(unit, sysport_buf);
   1077         return rv;
   1078     }
   1079 
   1080     /* Program the given interface configuration register.*/
   1081     rv = soc_reg32_get(unit, cfg_reg[intf_id],
   1082                        0, 0, &rval);
   1083     if (rv != BCM_E_NONE) {
   1084         soc_cm_sfree(unit, tc2pri_buf);
   1085         soc_cm_sfree(unit, sysport_buf);
   1086         return rv;
   1087     }
   1088     soc_reg_field_set(unit, cfg_reg[intf_id], &rval,
   1089                       OOBFC_CH_ENf, info[intf_id].enable);
   1090     soc_reg_field_set(unit, cfg_reg[intf_id], &rval,
   1091                       OOBFC_CH_BASEf, info[intf_id].channel_base);
   1092     soc_reg_field_set(unit, cfg_reg[intf_id], &rval,
   1093                       LOOKUP_BASEf, info[intf_id].lookup_base);
   1094     soc_reg_field_set(unit, cfg_reg[intf_id], &rval,
   1095                       CH_PORT_NUMf, info[intf_id].num_ports);
   1096     rv = soc_reg32_set(unit, cfg_reg[intf_id],
   1097                        0, 0, rval);
   1098     if (rv != BCM_E_NONE) {
   1099         soc_cm_sfree(unit, tc2pri_buf);
   1100         soc_cm_sfree(unit, sysport_buf);
   1101         return rv;
   1102     }
   1103 
   1104     rv = BCM_E_NONE;
   1105     soc_cm_sfree(unit, tc2pri_buf);
   1106     soc_cm_sfree(unit, sysport_buf);
   1107     return rv;
   1108 }
   1109 
   1110 /*
   1111  * Function:
   1112  *      _bcm_td3_oob_fc_rx_port_offset_get
   1113  * Purpose:
   1114  *      Get the channel offset value for a given port
   1115  *      in the HCFC message received on a given OOB FC
   1116  *      Rx Interface
   1117  * Parameters:
   1118  *      unit - (IN) StrataSwitch unit number
   1119  *      intf_id - (IN) OOB FC Rx Interface Number
   1120  *      gport - (IN) Modport gport
   1121  *      offset - (OUT) Channel offset value
   1122  * Returns:
   1123  *      BCM_E_XXX
   1124  */
   1125 STATIC int
   1126 _bcm_td3_oob_fc_rx_port_offset_get(int unit,
   1127                          bcm_oob_fc_rx_intf_id_t intf_id,
   1128                          bcm_gport_t gport,
   1129                          uint32 *offset)
   1130 {
   1131     bcm_oob_fc_rx_config_t config;
   1132     bcm_gport_t gport_array[_TD3_MAX_RX_MEM_ENTRY] = {0x0};
   1133     int array_count = 0, i = 0;
   1134 
   1135     /* Get the configured list of gport array
   1136        and array count*/
   1137     BCM_IF_ERROR_RETURN
   1138         (bcm_td3_oob_fc_rx_config_get(unit, intf_id, &config,
   1139                                      _TD3_MAX_RX_MEM_ENTRY, gport_array,
   1140                                      &array_count));
   1141 
   1142     if (config.enable == 0) {
   1143         return BCM_E_PARAM;
   1144     }
   1145 
   1146     /* Get the Channel offset of the port in HCFC message */
   1147     for (i = 0; i < array_count; i++) {
   1148         if (gport == gport_array[i]) {
   1149             break;
   1150         }
   1151     }
   1152 
   1153     /* Return error if gport is not there in the list */
   1154     if (i == array_count) {
   1155         return BCM_E_NOT_FOUND;
   1156     }
   1157 
   1158     *offset = i;
   1159     
   1160     return BCM_E_NONE;
   1161 }
   1162 
   1163 /*
   1164  * Function:
   1165  *      _bcm_td3_oob_fc_rx_tc_mapping_get
   1166  * Purpose:
   1167  *      Get the traffic class to priority
   1168  *      mapping for given OOB FC Rx Interface at
   1169  *      given idx in the memory.
   1170  * Parameters:
   1171  *      unit - (IN) StrataSwitch unit number
   1172  *      intf_id - (IN) OOB FC Rx Interface Number
   1173  *      tc - (IN) Traffic Class array[0-7]
   1174  *      pri_bmp - (OUT) Priority Bitmap[0-7]
   1175  *      idx - (IN) Index in TC to PRI mapping memory
   1176  * Returns:
   1177  *      BCM_E_XXX
   1178  */
   1179 STATIC int
   1180 _bcm_td3_oob_fc_rx_tc_mapping_get(int unit,
   1181                         bcm_oob_fc_rx_intf_id_t intf_id,
   1182                         uint32 tc, uint32 *pri_bmp,
   1183                         uint32 idx)
   1184 {
   1185     char *tc2pri_buf;
   1186     uint64 tc2pri;
   1187     void *pentry;
   1188     int mem_wsz = 0;
   1189 
   1190     COMPILER_64_ZERO(tc2pri);
   1191 
   1192     /* Read the MMU_INTFO_TC2PRI_MAPPING memory into tc2pri_buf */
   1193     mem_wsz = sizeof(uint32) *
   1194                 soc_mem_entry_words(unit, MMU_INTFO_TC2PRI_MAPPINGm);
   1195     tc2pri_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz,
   1196                                          "oob tc2pri_buf");
   1197     if (tc2pri_buf == NULL) {
   1198         return BCM_E_MEMORY;
   1199     }
   1200 
   1201     if (soc_mem_read_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL,
   1202                            0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) {
   1203         soc_cm_sfree(unit, tc2pri_buf);
   1204         return BCM_E_INTERNAL;
   1205     }
   1206 
   1207     /* Get the pointer to the given index. */
   1208     pentry = soc_mem_table_idx_to_pointer(unit,
   1209                                           MMU_INTFO_TC2PRI_MAPPINGm,
   1210                                           void*, tc2pri_buf, idx);
   1211 
   1212     soc_mem_field64_get(unit, MMU_INTFO_TC2PRI_MAPPINGm,
   1213                         pentry, PRI_BMPf, &tc2pri);
   1214 
   1215     /* Get tc2pri value */
   1216     COMPILER_64_SHR(tc2pri, (8 * tc));
   1217     *pri_bmp = COMPILER_64_LO(tc2pri) & 0xFF;
   1218 
   1219     soc_cm_sfree(unit, tc2pri_buf);
   1220     return BCM_E_NONE;
   1221 }
   1222 
   1223 /*
   1224  * Function:
   1225  *      _bcm_td3_oob_fc_rx_tc_mapping_set
   1226  * Purpose:
   1227  *      Set the traffic class to priority
   1228  *      mapping for given OOB FC Rx Interface at
   1229  *      given idx in the memory.
   1230  * Parameters:
   1231  *      unit - (IN) StrataSwitch unit number
   1232  *      intf_id - (IN) OOB FC Rx Interface Number
   1233  *      tc - (IN) Traffic Class array[0-7]
   1234  *      pri_bmp - (IN) Priority Bitmap[0-7]
   1235  *      idx - (IN) Index in TC to PRI mapping memory
   1236  * Returns:
   1237  *      BCM_E_XXX
   1238  */
   1239 STATIC int
   1240 _bcm_td3_oob_fc_rx_tc_mapping_set(int unit,
   1241                           bcm_oob_fc_rx_intf_id_t intf_id, uint32 tc,
   1242                           uint32 pri_bmp, uint32 idx)
   1243 {
   1244     char *tc2pri_buf;
   1245     uint64 tc2pri;
   1246     uint64 mask64;
   1247     uint64 pri_bmp64;
   1248     int rv = BCM_E_INTERNAL;
   1249     void *pentry;
   1250     int mem_wsz = 0;
   1251 
   1252     COMPILER_64_ZERO(tc2pri);
   1253     COMPILER_64_ZERO(mask64);
   1254     COMPILER_64_ZERO(pri_bmp64);
   1255 
   1256     /* Read the MMU_INTFO_TC2PRI_MAPPING memory into tc2pri_buf */
   1257     mem_wsz = sizeof(uint32) *
   1258                 soc_mem_entry_words(unit, MMU_INTFO_TC2PRI_MAPPINGm);
   1259     tc2pri_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz,
   1260                                          "oob tc2pri_buf");
   1261     if (tc2pri_buf == NULL) {
   1262         return BCM_E_MEMORY;
   1263     }
   1264 
   1265     if (soc_mem_read_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL,
   1266                            0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) {
   1267         rv = BCM_E_INTERNAL;
   1268         soc_cm_sfree(unit, tc2pri_buf);
   1269         return rv;
   1270     }
   1271 
   1272     /* Get the pointer to the given index. */
   1273     pentry = soc_mem_table_idx_to_pointer(unit,
   1274                                           MMU_INTFO_TC2PRI_MAPPINGm,
   1275                                           void*, tc2pri_buf, idx);
   1276 
   1277     soc_mem_field64_get(unit, MMU_INTFO_TC2PRI_MAPPINGm,
   1278                         pentry, PRI_BMPf, &tc2pri);
   1279 
   1280 
   1281     /* Disable the given OOBFC Rx interface */
   1282     rv = _bcm_td3_oob_fc_rx_disable_intf(unit, intf_id);
   1283     if (rv != BCM_E_NONE) {
   1284         soc_cm_sfree(unit, tc2pri_buf);
   1285         return rv;
   1286     }
   1287 
   1288     /* Update tc2pri value */
   1289     COMPILER_64_SET(pri_bmp64, 0, pri_bmp);
   1290     COMPILER_64_SHL(pri_bmp64, (tc * 8));
   1291     COMPILER_64_MASK_CREATE(mask64, 8, (tc * 8));
   1292     COMPILER_64_NOT(mask64);
   1293     COMPILER_64_AND(tc2pri, mask64);
   1294     COMPILER_64_OR(tc2pri, pri_bmp64);
   1295 
   1296     /* Program tc2pri MMU_INTFO_TC2PRI_MAPPING */
   1297     soc_mem_field64_set(unit, MMU_INTFO_TC2PRI_MAPPINGm,
   1298                         pentry, PRI_BMPf, tc2pri);
   1299 
   1300     if (soc_mem_write_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL,
   1301                             0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) {
   1302         rv = BCM_E_INTERNAL;
   1303         soc_cm_sfree(unit, tc2pri_buf);
   1304         return rv;
   1305     }
   1306 
   1307     /* Enable the given OOBFC Rx interface back */
   1308     rv = _bcm_td3_oob_fc_rx_enable_intf(unit, intf_id);
   1309     if (rv != BCM_E_NONE) {
   1310         soc_cm_sfree(unit, tc2pri_buf);
   1311         return rv;
   1312     }
   1313 
   1314     rv = BCM_E_NONE;
   1315     soc_cm_sfree(unit, tc2pri_buf);
   1316     return rv;
   1317 }
   1318 
   1319 /*
   1320  * Function:
   1321  *      _bcm_td3_oob_fc_rx_config_disable_set
   1322  * Purpose:
   1323  *      Disable and reset the configuration of the
   1324  *      given OOB FC Rx Interface
   1325  * Parameters:
   1326  *      unit - (IN) StrataSwitch unit number
   1327  *      intf_id - (IN) OOB FC Rx Interface Number
   1328  * Returns:
   1329  *      BCM_E_XXX
   1330  */
   1331 STATIC int
   1332 _bcm_td3_oob_fc_rx_config_disable_set(int unit,
   1333                             bcm_oob_fc_rx_intf_id_t intf_id)
   1334 {
   1335     _bcm_td3_oob_fc_rx_intf_info_t old_info[_TD3_NUM_OOB_FC_RX_INTF];
   1336     _bcm_td3_oob_fc_rx_intf_info_t new_info[_TD3_NUM_OOB_FC_RX_INTF];
   1337     char *sysport_buf, *tc2pri_buf;
   1338     uint32 old_sysport_list[_TD3_MAX_RX_MEM_ENTRY];
   1339     uint64 old_tc2pri_list[_TD3_MAX_RX_MEM_ENTRY];
   1340     uint32 new_sysport_list[_TD3_MAX_RX_MEM_ENTRY];
   1341     uint64 new_tc2pri_list[_TD3_MAX_RX_MEM_ENTRY];
   1342     int rv = BCM_E_INTERNAL;
   1343     int mem_wsz = 0;
   1344     int i = 0, j = 0, k = 0;
   1345     void *pentry;
   1346     uint32 rval = 0x0;
   1347     soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r,
   1348                                                  OOBFC_CHIF_CFG1r,
   1349                                                  OOBFC_CHIF_CFG2r,
   1350                                                  OOBFC_CHIF_CFG3r};
   1351 
   1352     sal_memset(old_info, 0, sizeof(_bcm_td3_oob_fc_rx_intf_info_t) *
   1353                _TD3_NUM_OOB_FC_RX_INTF);
   1354     sal_memset(new_info, 0, sizeof(_bcm_td3_oob_fc_rx_intf_info_t) *
   1355                _TD3_NUM_OOB_FC_RX_INTF);
   1356     sal_memset(old_sysport_list, 0, sizeof(uint32) *
   1357                _TD3_MAX_RX_MEM_ENTRY);
   1358     sal_memset(new_sysport_list, 0, sizeof(uint32) *
   1359                _TD3_MAX_RX_MEM_ENTRY);
   1360     sal_memset(old_tc2pri_list, 0, sizeof(uint64) *
   1361                _TD3_MAX_RX_MEM_ENTRY);
   1362     sal_memset(new_tc2pri_list, 0, sizeof(uint64) *
   1363                _TD3_MAX_RX_MEM_ENTRY);
   1364 
   1365     /* Store all the OOBFC Rx interface configuration */
   1366     for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) {
   1367         BCM_IF_ERROR_RETURN
   1368             (_bcm_td3_oob_fc_rx_get_intf_info(unit, &old_info[i], i));
   1369     }
   1370 
   1371     /* Read the MMU_CHFC_SYSPORT_MAPPING memory into sysport_buf */
   1372     mem_wsz = sizeof(uint32) *
   1373                 soc_mem_entry_words(unit, MMU_CHFC_SYSPORT_MAPPINGm);
   1374     sysport_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz,
   1375                                          "oob sysport_buf");
   1376     if (sysport_buf == NULL) {
   1377         return BCM_E_MEMORY;
   1378     }
   1379 
   1380     if (soc_mem_read_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL,
   1381                            0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) {
   1382         rv = BCM_E_INTERNAL;
   1383         soc_cm_sfree(unit, sysport_buf);
   1384         return rv;
   1385     }
   1386 
   1387     /* Store the sysport_buf in old_sysport_list */
   1388     for (i = 0; i < _TD3_MAX_RX_MEM_ENTRY; i++) {
   1389         pentry = soc_mem_table_idx_to_pointer(unit,
   1390                                               MMU_CHFC_SYSPORT_MAPPINGm,
   1391                                               void*, sysport_buf, i);
   1392         old_sysport_list[i] = soc_mem_field32_get(unit,
   1393                                                   MMU_CHFC_SYSPORT_MAPPINGm,
   1394                                                   pentry, SYS_PORTf);
   1395     }
   1396 
   1397     /* Read the MMU_INTFO_TC2PRI_MAPPING memory into tc2pri_list */
   1398     mem_wsz = sizeof(uint32) *
   1399                 soc_mem_entry_words(unit, MMU_INTFO_TC2PRI_MAPPINGm);
   1400     tc2pri_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz,
   1401                                          "oob tc2pri_buf");
   1402     if (tc2pri_buf == NULL) {
   1403         rv = BCM_E_MEMORY;
   1404         soc_cm_sfree(unit, sysport_buf);
   1405         return rv;
   1406     }
   1407 
   1408     if (soc_mem_read_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL,
   1409                            0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) {
   1410         rv = BCM_E_INTERNAL;
   1411         soc_cm_sfree(unit, tc2pri_buf);
   1412         soc_cm_sfree(unit, sysport_buf);
   1413         return rv;
   1414     }
   1415 
   1416     /* Store the tc2pri_buf in old_tc2pri_list */
   1417     for (i = 0; i < _TD3_MAX_RX_MEM_ENTRY; i++) {
   1418         pentry = soc_mem_table_idx_to_pointer(unit,
   1419                                               MMU_INTFO_TC2PRI_MAPPINGm,
   1420                                               void*, tc2pri_buf, i);
   1421         soc_mem_field64_get(unit, MMU_INTFO_TC2PRI_MAPPINGm,
   1422                             pentry, PRI_BMPf, &old_tc2pri_list[i]);
   1423     }
   1424 
   1425     /* Disable all the OOBFC Rx interface */
   1426     for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) {
   1427         if (old_info[i].enable == 1) {
   1428             rv = _bcm_td3_oob_fc_rx_disable_intf(unit, i);
   1429             if (rv != BCM_E_NONE) {
   1430                 soc_cm_sfree(unit, tc2pri_buf);
   1431                 soc_cm_sfree(unit, sysport_buf);
   1432                 return rv;
   1433             }
   1434         }
   1435     }
   1436 
   1437     /* Generate new_info */
   1438     /* Genrate new_sysport_list */
   1439     /* Genrate new_tc2pri_list */
   1440     j = 0;
   1441     k = 0;
   1442     for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) {
   1443         if (i != intf_id) {
   1444             new_info[i].enable = old_info[i].enable;
   1445             new_info[i].channel_base = old_info[i].channel_base;
   1446             new_info[i].num_ports = old_info[i].num_ports;
   1447             if (new_info[i].enable) {
   1448                 new_info[i].lookup_base = j;
   1449             } else {
   1450                 new_info[i].lookup_base = 0x0;
   1451             }
   1452             for (k = 0; k < new_info[i].num_ports; k++) {
   1453                 new_sysport_list[j] = old_sysport_list[old_info[i].lookup_base + k];
   1454                 new_tc2pri_list[j] = old_tc2pri_list[old_info[i].lookup_base + k];
   1455                 j++;
   1456             }
   1457         } else {
   1458             new_info[i].enable = 0;
   1459             new_info[i].channel_base = 0;
   1460             new_info[i].lookup_base = 0;
   1461             new_info[i].num_ports = 0;
   1462         }
   1463     }
   1464 
   1465     /* Program new_tc2pri_list in MMU_INTFO_TC2PRI_MAPPING */
   1466     for (i = 0; i < _TD3_MAX_RX_MEM_ENTRY; i++) {
   1467         pentry = soc_mem_table_idx_to_pointer(unit,
   1468                                               MMU_INTFO_TC2PRI_MAPPINGm,
   1469                                               void*, tc2pri_buf, i);
   1470         soc_mem_field64_set(unit, MMU_INTFO_TC2PRI_MAPPINGm,
   1471                             pentry, PRI_BMPf, new_tc2pri_list[i]);
   1472     }
   1473 
   1474     if (soc_mem_write_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL,
   1475                             0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) {
   1476         rv = BCM_E_INTERNAL;
   1477         soc_cm_sfree(unit, tc2pri_buf);
   1478         soc_cm_sfree(unit, sysport_buf);
   1479         return rv;
   1480     }
   1481 
   1482     /* Program new_sysport_list MMU_CHFC_SYSPORT_MAPPING */
   1483     for (i = 0; i < _TD3_MAX_RX_MEM_ENTRY; i++) {
   1484         pentry = soc_mem_table_idx_to_pointer(unit,
   1485                                               MMU_CHFC_SYSPORT_MAPPINGm,
   1486                                               void*, sysport_buf, i);
   1487         soc_mem_field32_set(unit, MMU_CHFC_SYSPORT_MAPPINGm, pentry,
   1488                             SYS_PORTf, new_sysport_list[i]);
   1489     }
   1490 
   1491     if (soc_mem_write_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL,
   1492                             0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) {
   1493         rv = BCM_E_INTERNAL;
   1494         soc_cm_sfree(unit, tc2pri_buf);
   1495         soc_cm_sfree(unit, sysport_buf);
   1496         return rv;
   1497     }
   1498 
   1499     /* Program all the OOBFC Rx interface configuration register */
   1500     for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) {
   1501         rv = soc_reg32_get(unit, cfg_reg[i],
   1502                            0, 0, &rval);
   1503         if (rv != BCM_E_NONE) {
   1504             soc_cm_sfree(unit, tc2pri_buf);
   1505             soc_cm_sfree(unit, sysport_buf);
   1506             return rv;
   1507         }
   1508         soc_reg_field_set(unit, cfg_reg[i], &rval,
   1509                           OOBFC_CH_ENf, new_info[i].enable);
   1510         soc_reg_field_set(unit, cfg_reg[i], &rval,
   1511                           OOBFC_CH_BASEf, new_info[i].channel_base);
   1512         soc_reg_field_set(unit, cfg_reg[i], &rval,
   1513                           LOOKUP_BASEf, new_info[i].lookup_base);
   1514         soc_reg_field_set(unit, cfg_reg[i], &rval,
   1515                           CH_PORT_NUMf, new_info[i].num_ports);
   1516         rv = soc_reg32_set(unit, cfg_reg[i],
   1517                            0, 0, rval);
   1518         if (rv != BCM_E_NONE) {
   1519             soc_cm_sfree(unit, tc2pri_buf);
   1520             soc_cm_sfree(unit, sysport_buf);
   1521             return rv;
   1522         }
   1523     }
   1524 
   1525     rv = BCM_E_NONE;
   1526     soc_cm_sfree(unit, tc2pri_buf);
   1527     soc_cm_sfree(unit, sysport_buf);
   1528     return rv;
   1529 }
   1530 
   1531 /*
   1532  * Function:
   1533  *      _bcm_td3_oob_fc_rx_config_get
   1534  * Purpose:
   1535  *      Get the configuration and status
   1536  *      each OOB FC Rx Interface.
   1537  * Parameters:
   1538  *      unit - (IN) StrataSwitch unit number
   1539  *      intf_id - (IN) OOB FC Rx Interface Number
   1540  *      config - (OUT) OOB FC Rx Interface Config
   1541  *      array_max - (IN) Maximum Lenght of Gport array passed
   1542  *      gport_array - (OUT) Array of modport type gport
   1543  *      array_count - (OUT) Number of gports returned in the gport array
   1544  * Returns:
   1545  *      BCM_E_XXX
   1546  */
   1547 STATIC int
   1548 _bcm_td3_oob_fc_rx_config_get(int unit,
   1549                  bcm_oob_fc_rx_intf_id_t intf_id,
   1550                  bcm_oob_fc_rx_config_t *config,
   1551                  int array_max,
   1552                  bcm_gport_t *gport_array,
   1553                  int *array_count)
   1554 {
   1555     _bcm_td3_oob_fc_rx_intf_info_t info;
   1556     int rv = BCM_E_INTERNAL;
   1557     char *sysport_buf;
   1558     void *pentry;
   1559     int mem_wsz = 0;
   1560     int i = 0 , j = 0;
   1561     bcm_gport_t gport;
   1562     uint32 new_sysport_list[_TD3_MAX_RX_MEM_ENTRY];
   1563 
   1564     sal_memset(&info, 0, sizeof(_bcm_td3_oob_fc_rx_intf_info_t));
   1565     sal_memset(new_sysport_list, 0, sizeof(uint32) *
   1566                _TD3_MAX_RX_MEM_ENTRY);
   1567     
   1568     /* Store all the OOBFC Rx interface configuration */
   1569     BCM_IF_ERROR_RETURN
   1570             (_bcm_td3_oob_fc_rx_get_intf_info(unit, &info, intf_id));
   1571 
   1572     /* If given OOBFC Rx Interface is not enabled then
   1573        return empty gport array */
   1574     if (info.enable == 0) {
   1575         sal_memset(config, 0, sizeof(bcm_oob_fc_rx_config_t));
   1576         sal_memset(gport_array, 0, sizeof(bcm_gport_t) * array_max);
   1577         *array_count = 0;
   1578         return BCM_E_NONE;
   1579     } else {
   1580         config->enable = info.enable;
   1581         config->channel_base = info.channel_base;
   1582         /* Read the MMU_CHFC_SYSPORT_MAPPING memory into sysport_buf */
   1583         mem_wsz = sizeof(uint32) *
   1584                     soc_mem_entry_words(unit, MMU_CHFC_SYSPORT_MAPPINGm);
   1585         sysport_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz,
   1586                                              "oob sysport_buf");
   1587         if (sysport_buf == NULL) {
   1588             return BCM_E_MEMORY;
   1589         }
   1590 
   1591         if (soc_mem_read_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL,
   1592                                0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) {
   1593             rv = BCM_E_INTERNAL;
   1594             soc_cm_sfree(unit, sysport_buf);
   1595             return rv;
   1596         }
   1597 
   1598         if (array_max >= info.num_ports) {
   1599             *array_count = info.num_ports;
   1600         } else {
   1601             *array_count = array_max;
   1602         }
   1603 
   1604         /* Store the required number of indexes into a sysport_list */
   1605         for (i = info.lookup_base, j = 0;
   1606              i < (info.lookup_base + *array_count); i++, j++) {
   1607             pentry = soc_mem_table_idx_to_pointer(unit,
   1608                                                   MMU_CHFC_SYSPORT_MAPPINGm,
   1609                                                   void*, sysport_buf, i);
   1610             new_sysport_list[j] = soc_mem_field32_get(unit,
   1611                                                       MMU_CHFC_SYSPORT_MAPPINGm,
   1612                                                       pentry, SYS_PORTf);
   1613         }
   1614 
   1615         /* Convert the sysport list into a modport gport list */
   1616         for (i = 0; i < *array_count; i++) {
   1617             rv = bcm_esw_port_gport_get(unit, new_sysport_list[i],
   1618                                         &gport);
   1619             if (rv != BCM_E_NONE) {
   1620                 soc_cm_sfree(unit, sysport_buf);
   1621                 return rv;
   1622             }
   1623             gport_array[i] = gport;
   1624         }
   1625 
   1626     }
   1627 
   1628     rv = BCM_E_NONE;
   1629     soc_cm_sfree(unit, sysport_buf);
   1630     return rv;
   1631 }
   1632 
   1633 /*
   1634  * Function:
   1635  *      bcm_td3_oob_fc_rx_config_set
   1636  * Purpose:
   1637  *      Set the configuration and enable 
   1638  *      each OOB FC Rx Interface.
   1639  * Parameters:
   1640  *      unit - (IN) StrataSwitch unit number
   1641  *      intf_id - (IN) OOB FC Rx Interface Number
   1642  *      config - (IN) OOB FC Rx Interface Config
   1643  *      array_count - (IN) Number of gports in the gport array
   1644  *      gport_array - (IN) Array of modport type gport
   1645  * Returns:
   1646  *      BCM_E_XXX
   1647  */
   1648 int
   1649 bcm_td3_oob_fc_rx_config_set(int unit,
   1650                      bcm_oob_fc_rx_intf_id_t intf_id,
   1651                      bcm_oob_fc_rx_config_t *config,
   1652                      int array_count,
   1653                      bcm_gport_t *gport_array)
   1654 {
   1655     if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) {
   1656         return BCM_E_PARAM;
   1657     }
   1658 
   1659     if (config == NULL) {
   1660         return BCM_E_PARAM;
   1661     }
   1662 
   1663     if ((config->enable != 0) && (config->enable != 1)) {
   1664         return BCM_E_PARAM;
   1665     }
   1666 
   1667     if ((config->enable == 1) &&
   1668         ((array_count == 0) || (gport_array == NULL) ||
   1669         (array_count > _TD3_MAX_RX_MEM_ENTRY))) {
   1670         return BCM_E_PARAM;
   1671     }
   1672 
   1673     if ((config->enable == 1) &&
   1674         ((config->channel_base > _TD3_MAX_CHANNEL_BASE))) {
   1675         return BCM_E_PARAM;
   1676     }
   1677 
   1678     if (config->enable == 1) {
   1679         /* Add entries into MMU_CHFC_SYSPORT_MAPPING memory */
   1680         BCM_IF_ERROR_RETURN
   1681             (_bcm_td3_oob_fc_rx_config_enable_set(unit, intf_id,
   1682                                                  config->channel_base,
   1683                                                  array_count, gport_array));
   1684     } else {
   1685         /* Remove entries from MMU_CHFC_SYSPORT_MAPPING memory */
   1686         BCM_IF_ERROR_RETURN
   1687             (_bcm_td3_oob_fc_rx_config_disable_set(unit, intf_id));
   1688     }
   1689 
   1690     return BCM_E_NONE;
   1691 }
   1692 
   1693 /*
   1694  * Function:
   1695  *      bcm_td3_oob_fc_rx_config_get
   1696  * Purpose:
   1697  *      Get the configuration and status
   1698  *      each OOB FC Rx Interface.
   1699  * Parameters:
   1700  *      unit - (IN) StrataSwitch unit number
   1701  *      intf_id - (IN) OOB FC Rx Interface Number
   1702  *      config - (OUT) OOB FC Rx Interface Config
   1703  *      array_max - (IN) Maximum Lenght of Gport array passed
   1704  *      gport_array - (OUT) Array of modport type gport
   1705  *      array_count - (OUT) Number of gports returned in the gport array
   1706  * Returns:
   1707  *      BCM_E_XXX
   1708  */
   1709 int
   1710 bcm_td3_oob_fc_rx_config_get(int unit,
   1711                      bcm_oob_fc_rx_intf_id_t intf_id,
   1712                      bcm_oob_fc_rx_config_t *config,
   1713                      int array_max,
   1714                      bcm_gport_t *gport_array,
   1715                      int *array_count)
   1716 {
   1717     if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) {
   1718         return BCM_E_PARAM;
   1719     }
   1720 
   1721     if ((gport_array == NULL) ||
   1722         (config == NULL) ||
   1723         (array_count == NULL)) {
   1724         return BCM_E_PARAM;
   1725     }
   1726 
   1727     BCM_IF_ERROR_RETURN
   1728         (_bcm_td3_oob_fc_rx_config_get(unit, intf_id,
   1729                                       config, array_max,
   1730                                       gport_array,
   1731                                       array_count));
   1732 
   1733     return BCM_E_NONE;
   1734 }
   1735 
   1736 /*
   1737  * Function:
   1738  *      bcm_td3_oob_fc_rx_port_tc_mapping_multi_set
   1739  * Purpose:
   1740  *      Set the per port traffic class to priority
   1741  *      mapping for each OOB FC Rx Interface.
   1742  * Parameters:
   1743  *      unit - (IN) StrataSwitch unit number
   1744  *      intf_id - (IN) OOB FC Rx Interface Number
   1745  *      gport - (IN) Modport type gport
   1746  *      array_count - (IN) Number of elements in Traffic Class array
   1747  *      tc - (IN) Traffic Class array[0-7]
   1748  *      pri_bmp - (IN) Priority Bitmap Array[0-7]
   1749  * Returns:
   1750  *      BCM_E_XXX
   1751  */
   1752 int
   1753 bcm_td3_oob_fc_rx_port_tc_mapping_multi_set(int unit,
   1754                                  bcm_oob_fc_rx_intf_id_t intf_id,
   1755                                  bcm_gport_t gport,
   1756                                  int array_count,
   1757                                  uint32 *tc,
   1758                                  uint32 *pri_bmp)
   1759 {
   1760     int i = 0;
   1761 
   1762     if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) {
   1763         return BCM_E_PARAM;
   1764     }
   1765 
   1766     if ((array_count < 1) || (array_count > _TD3_NUM_TC)) {
   1767         return BCM_E_PARAM;
   1768     }
   1769 
   1770     if ((tc == NULL) || (pri_bmp == NULL)) {
   1771         return BCM_E_PARAM;
   1772     }
   1773 
   1774     for (i = 0; i < array_count; i++) {
   1775         if ((tc[i] > (_TD3_NUM_TC - 1)) || (pri_bmp[i] > 0xFF)) {
   1776             return BCM_E_PARAM;
   1777         }
   1778     }
   1779 
   1780     for (i = 0; i < array_count; i++) {
   1781         BCM_IF_ERROR_RETURN
   1782             (bcm_td3_oob_fc_rx_port_tc_mapping_set(unit, intf_id,
   1783                                                   gport, tc[i],
   1784                                                   pri_bmp[i]));
   1785     }
   1786 
   1787     return BCM_E_NONE;
   1788 }
   1789 
   1790 /*
   1791  * Function:
   1792  *      bcm_td3_oob_fc_rx_port_tc_mapping_multi_get
   1793  * Purpose:
   1794  *      Get the per port traffic class to priority
   1795  *      mapping for each OOB FC Rx Interface.
   1796  * Parameters:
   1797  *      unit - (IN) StrataSwitch unit number
   1798  *      intf_id - (IN) OOB FC Rx Interface Number
   1799  *      gport - (IN) Modport type gport
   1800  *      array_max - (IN) Maximum Length tc and pri_bmp array
   1801  *      tc - (OUT) Traffic Class array[0-7]
   1802  *      pri_bmp - (OUT) Priority Bitmap Array[0-7]
   1803  *      array_count - (OUT) Number of elements in Traffic Class array
   1804  * Returns:
   1805  *      BCM_E_XXX
   1806  */
   1807 int
   1808 bcm_td3_oob_fc_rx_port_tc_mapping_multi_get(int unit,
   1809                                      bcm_oob_fc_rx_intf_id_t intf_id,
   1810                                      bcm_gport_t gport,
   1811                                      int array_max,
   1812                                      uint32 *tc,
   1813                                      uint32 *pri_bmp,
   1814                                      int *array_count)
   1815 {
   1816     int i = 0;
   1817 
   1818     if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) {
   1819         return BCM_E_PARAM;
   1820     }
   1821 
   1822     if (array_max < 1) {
   1823         return BCM_E_PARAM;
   1824     }
   1825 
   1826     if ((array_count == NULL) ||
   1827         (tc == NULL) ||
   1828         (pri_bmp == NULL)) {
   1829         return BCM_E_PARAM;
   1830     }
   1831 
   1832     if (array_max > _TD3_NUM_TC) {
   1833         *array_count = _TD3_NUM_TC;
   1834     } else {
   1835         *array_count = array_max;
   1836     }
   1837 
   1838     for (i = 0; i < *array_count; i++) {
   1839         if (tc[i] > (_TD3_NUM_TC - 1)) {
   1840             return BCM_E_PARAM;
   1841         }
   1842     }
   1843 
   1844     for (i = 0; i < *array_count; i++) {
   1845         BCM_IF_ERROR_RETURN
   1846             (bcm_td3_oob_fc_rx_port_tc_mapping_get(unit, intf_id,
   1847                                                   gport, tc[i],
   1848                                                   &pri_bmp[i]));
   1849     }
   1850     return BCM_E_NONE;
   1851 }
   1852 
   1853 
   1854 /*
   1855  * Function:
   1856  *      bcm_td3_oob_fc_rx_port_tc_mapping_set
   1857  * Purpose:
   1858  *      Set the per port traffic class to priority
   1859  *      mapping for each OOB FC Rx Interface.
   1860  * Parameters:
   1861  *      unit - (IN) StrataSwitch unit number
   1862  *      intf_id - (IN) OOB FC Rx Interface Number
   1863  *      gport - (IN) Modport type gport
   1864  *      tc - (IN) Traffic Class array[0-7]
   1865  *      pri_bmp - (IN) Priority Bitmap[0-7]
   1866  * Returns:
   1867  *      BCM_E_XXX
   1868  */
   1869 int
   1870 bcm_td3_oob_fc_rx_port_tc_mapping_set(int unit,
   1871                                  bcm_oob_fc_rx_intf_id_t intf_id,
   1872                                  bcm_gport_t gport,
   1873                                  uint32 tc,
   1874                                  uint32 pri_bmp)
   1875 {
   1876     uint32 idx = 0;
   1877     uint32 offset = 0;
   1878     uint32 lookup_base = 0;
   1879 
   1880     if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) {
   1881         return BCM_E_PARAM;
   1882     }
   1883 
   1884     if ((tc > (_TD3_NUM_TC - 1)) || (pri_bmp > 0xFF)) {
   1885         return BCM_E_PARAM;
   1886     }
   1887 
   1888     BCM_IF_ERROR_RETURN
   1889         (_bcm_td3_oob_fc_rx_port_offset_get(unit, intf_id,
   1890                                            gport, &offset));
   1891 
   1892     /* Get lookup base */
   1893     BCM_IF_ERROR_RETURN
   1894         (_bcm_td3_oob_fc_rx_intf_get_lookup_base(unit, intf_id,
   1895                                                 &lookup_base));
   1896 
   1897     idx = offset + lookup_base;
   1898 
   1899     BCM_IF_ERROR_RETURN
   1900         (_bcm_td3_oob_fc_rx_tc_mapping_set(unit, intf_id, tc,
   1901                                           pri_bmp, idx));
   1902 
   1903     return BCM_E_NONE;
   1904 }
   1905 
   1906 /*
   1907  * Function:
   1908  *      bcm_td3_oob_fc_rx_port_tc_mapping_get
   1909  * Purpose:
   1910  *      Set the per port traffic class to priority
   1911  *      mapping for each OOB FC Rx Interface.
   1912  * Parameters:
   1913  *      unit - (IN) StrataSwitch unit number
   1914  *      intf_id - (IN) OOB FC Rx Interface Number
   1915  *      gport - (IN) Modport type gport
   1916  *      tc - (IN) Traffic Class array[0-7]
   1917  *      pri_bmp - (OUT) Priority Bitmap[0-7]
   1918  * Returns:
   1919  *      BCM_E_XXX
   1920  */
   1921 int
   1922 bcm_td3_oob_fc_rx_port_tc_mapping_get(int unit,
   1923                                  bcm_oob_fc_rx_intf_id_t intf_id,
   1924                                  bcm_gport_t gport,
   1925                                  uint32 tc,
   1926                                  uint32 *pri_bmp)
   1927 {
   1928     uint32 idx = 0;
   1929     uint32 offset = 0;
   1930     uint32 lookup_base = 0;
   1931 
   1932     if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) {
   1933         return BCM_E_PARAM;
   1934     }
   1935 
   1936     if (tc > (_TD3_NUM_TC - 1)) {
   1937         return BCM_E_PARAM;
   1938     }
   1939 
   1940     BCM_IF_ERROR_RETURN
   1941         (_bcm_td3_oob_fc_rx_port_offset_get(unit, intf_id,
   1942                                            gport, &offset));
   1943 
   1944     /* Get lookup base */
   1945     BCM_IF_ERROR_RETURN
   1946         (_bcm_td3_oob_fc_rx_intf_get_lookup_base(unit, intf_id,
   1947                                                 &lookup_base));
   1948 
   1949     idx = offset + lookup_base;
   1950 
   1951     BCM_IF_ERROR_RETURN
   1952         (_bcm_td3_oob_fc_rx_tc_mapping_get(unit, intf_id, tc,
   1953                                           pri_bmp, idx));
   1954 
   1955     return BCM_E_NONE;
   1956 }
   1957 
   1958 /*
   1959  * Function:
   1960  *      bcm_td3_oob_fc_rx_port_offset_get
   1961  * Purpose:
   1962  *      Get the Channel offset value for a given port
   1963  *      on given OOB FC Rx Interface.
   1964  * Parameters:
   1965  *      unit - (IN) StrataSwitch unit number
   1966  *      intf_id - (IN) OOB FC Rx Interface Number
   1967  *      gport - (IN) Modport type gport
   1968  *      offset - (OUT) Channel offset value in HCFC message
   1969  * Returns:
   1970  *      BCM_E_XXX
   1971  */
   1972 int
   1973 bcm_td3_oob_fc_rx_port_offset_get(int unit,
   1974                              bcm_oob_fc_rx_intf_id_t intf_id,
   1975                              bcm_gport_t gport,
   1976                              uint32 *offset)
   1977 {
   1978     if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) {
   1979         return BCM_E_PARAM;
   1980     }
   1981 
   1982     BCM_IF_ERROR_RETURN
   1983         (_bcm_td3_oob_fc_rx_port_offset_get(unit, intf_id,
   1984                                            gport, offset));
   1985 
   1986     return BCM_E_NONE;
   1987 }
   1988 
   1989 
   1990 /*
   1991  * Function:
   1992  *      _bcm_td3_oob_stats_config_flags_set
   1993  * Purpose:
   1994  *      Set the enable control for OOB STATS.
   1995  * Parameters:
   1996  *      unit - (IN) StrataSwitch unit number
   1997  *      flags - (IN) OOB Stats Enable controls
   1998  * Returns:
   1999  *      BCM_E_XXX
   2000  */
   2001 STATIC int
   2002 _bcm_td3_oob_stats_config_flags_set(int unit, uint32 flags)
   2003 {
   2004     uint32 rval = 0;
   2005 
   2006     BCM_IF_ERROR_RETURN
   2007         (soc_reg32_get(unit, STATS_INTF_REPORT_ENr, 0, 0, &rval));
   2008 
   2009     soc_reg_field_set(unit, STATS_INTF_REPORT_ENr, &rval, TIMESTAMP_ENf,
   2010                       ((flags & BCM_OOB_STATS_TIMESTAMP_EN) ? 0x1 : 0x0));
   2011 
   2012     soc_reg_field_set(unit, STATS_INTF_REPORT_ENr, &rval, INST_SERV_POOL_SIZE_ENf,
   2013                       ((flags & BCM_OOB_STATS_POOL_EN) ? 0x1 : 0x0));
   2014 
   2015     soc_reg_field_set(unit, STATS_INTF_REPORT_ENr, &rval, INST_UC_QSIZE_ENf,
   2016                       ((flags & BCM_OOB_STATS_QUEUE_EN) ? 0x1 : 0x0));
   2017 
   2018     BCM_IF_ERROR_RETURN
   2019         (soc_reg32_set(unit, STATS_INTF_REPORT_ENr, 0, 0, rval));
   2020 
   2021     return BCM_E_NONE;
   2022 }
   2023 
   2024 /*
   2025  * Function:
   2026  *      _bcm_td3_oob_stats_config_ipg_set
   2027  * Purpose:
   2028  *      Set the inter packet gap for OOB STATS.
   2029  * Parameters:
   2030  *      unit - (IN) StrataSwitch unit number
   2031  *      ipg - (IN) OOB Stats inter packet gap(clock cycles)
   2032  *                 can range from 0-255
   2033  * Returns:
   2034  *      BCM_E_XXX
   2035  */
   2036 STATIC int
   2037 _bcm_td3_oob_stats_config_ipg_set(int unit, uint8 ipg)
   2038 {
   2039     uint32 rval = 0;
   2040 
   2041     BCM_IF_ERROR_RETURN
   2042         (soc_reg32_get(unit, OOB_STATS_TX_IDLEr, 0, 0, &rval));
   2043     soc_reg_field_set(unit, OOB_STATS_TX_IDLEr, &rval,
   2044                       IDLE_GAPf, ipg);
   2045     BCM_IF_ERROR_RETURN
   2046         (soc_reg32_set(unit, OOB_STATS_TX_IDLEr, 0, 0, rval));
   2047 
   2048     return BCM_E_NONE;
   2049 }
   2050 
   2051 /*
   2052  * Function:
   2053  *      _bcm_td3_oob_stats_config_cfg_id_set
   2054  * Purpose:
   2055  *      Set the inter packet gap for OOB STATS.
   2056  * Parameters:
   2057  *      unit - (IN) StrataSwitch unit number
   2058  *      cfg_id - (IN) OOB Stats config ID.
   2059  * Returns:
   2060  *      BCM_E_XXX
   2061  */
   2062 STATIC int
   2063 _bcm_td3_oob_stats_config_cfg_id_set(int unit, uint8 cfg_id)
   2064 {
   2065     uint32 rval = 0;
   2066 
   2067     BCM_IF_ERROR_RETURN
   2068         (soc_reg32_get(unit, STATS_INTF_CONFIG_IDr, 0, 0, &rval));
   2069     soc_reg_field_set(unit, STATS_INTF_CONFIG_IDr, &rval,
   2070                       CONFIG_IDf, cfg_id);
   2071     BCM_IF_ERROR_RETURN
   2072         (soc_reg32_set(unit, STATS_INTF_CONFIG_IDr, 0, 0, rval));
   2073 
   2074     return BCM_E_NONE;
   2075 }
   2076 
   2077 /*
   2078  * Function:
   2079  *      _bcm_td3_oob_stats_config_flags_get
   2080  * Purpose:
   2081  *      Get the enable control for OOB STATS.
   2082  * Parameters:
   2083  *      unit - (IN) StrataSwitch unit number
   2084  *      config - (OUT) OOB Stats Configuration structure
   2085  * Returns:
   2086  *      BCM_E_XXX
   2087  */
   2088 STATIC int
   2089 _bcm_td3_oob_stats_config_flags_get(int unit,
   2090                         bcm_oob_stats_config_t *config)
   2091 {
   2092     uint32 rval = 0;
   2093 
   2094     config->flags = 0x0;
   2095 
   2096     BCM_IF_ERROR_RETURN
   2097         (soc_reg32_get(unit, STATS_INTF_REPORT_ENr, 0, 0, &rval));
   2098 
   2099     if (soc_reg_field_get(unit, STATS_INTF_REPORT_ENr,
   2100                           rval, TIMESTAMP_ENf)) {
   2101         config->flags |= BCM_OOB_STATS_TIMESTAMP_EN;
   2102     }
   2103 
   2104     if (soc_reg_field_get(unit, STATS_INTF_REPORT_ENr,
   2105                           rval, INST_SERV_POOL_SIZE_ENf)) {
   2106         config->flags |= BCM_OOB_STATS_POOL_EN;
   2107     }
   2108 
   2109     if (soc_reg_field_get(unit, STATS_INTF_REPORT_ENr,
   2110                           rval, INST_UC_QSIZE_ENf)) {
   2111         config->flags |= BCM_OOB_STATS_QUEUE_EN;
   2112     }
   2113 
   2114     return BCM_E_NONE;
   2115 }
   2116 
   2117 /*
   2118  * Function:
   2119  *      _bcm_td3_oob_stats_config_ipg_get
   2120  * Purpose:
   2121  *      Get the inter packet gap for OOB STATS.
   2122  * Parameters:
   2123  *      unit - (IN) StrataSwitch unit number
   2124  *      config - (OUT) OOB Stats Configuration structure
   2125  * Returns:
   2126  *      BCM_E_XXX
   2127  */
   2128 STATIC int
   2129 _bcm_td3_oob_stats_config_ipg_get(int unit,
   2130                         bcm_oob_stats_config_t *config)
   2131 {
   2132     uint32 rval = 0;
   2133 
   2134     config->inter_pkt_gap = 0x0;
   2135 
   2136     BCM_IF_ERROR_RETURN
   2137         (soc_reg32_get(unit, OOB_STATS_TX_IDLEr, 0, 0, &rval));
   2138 
   2139     config->inter_pkt_gap = soc_reg_field_get(unit, OOB_STATS_TX_IDLEr,
   2140                                               rval, IDLE_GAPf);
   2141     return BCM_E_NONE;
   2142 }
   2143 
   2144 /*
   2145  * Function:
   2146  *      _bcm_td3_oob_stats_config_cfg_id_get
   2147  * Purpose:
   2148  *      Get the Config ID for OOB STATS.
   2149  * Parameters:
   2150  *      unit - (IN) StrataSwitch unit number
   2151  *      config - (OUT) OOB Stats Configuration structure
   2152  * Returns:
   2153  *      BCM_E_XXX
   2154  */
   2155 STATIC int
   2156 _bcm_td3_oob_stats_config_cfg_id_get(int unit,
   2157                         bcm_oob_stats_config_t *config)
   2158 {
   2159     uint32 rval = 0;
   2160 
   2161     config->config_id = 0x0;
   2162 
   2163     BCM_IF_ERROR_RETURN
   2164         (soc_reg32_get(unit, STATS_INTF_CONFIG_IDr, 0, 0, &rval));
   2165 
   2166     config->config_id = soc_reg_field_get(unit, STATS_INTF_CONFIG_IDr,
   2167                                           rval, CONFIG_IDf);
   2168 
   2169     return BCM_E_NONE;
   2170 }
   2171 
   2172 /*
   2173  * Function:
   2174  *      _bcm_td3_oob_stats_pool_mapping_set
   2175  * Purpose:
   2176  *      Set the service pool id at a given index in the memory
   2177  *      so that OOB Stats will be reported in the same order
   2178  *      as the service pool ids are programmed in the memory.
   2179  * Parameters:
   2180  *      unit - (IN) StrataSwitch unit number
   2181  *      offset - (IN) Index at which service pool
   2182  *               in the service pool list needs to be added
   2183  *      spid - (IN) Specifies the service pool for which the corresponding pool
   2184  *             size should be reported. Mapping as follows:
   2185  *                 0-3: Report stats for ingress service pool ID 0-3
   2186  *                 4-7: Report stats for egress service pool ID 0-3
   2187  *                 15: End reporting round
   2188  *             Reset Value: 0xF
   2189  * Returns:
   2190  *      BCM_E_XXX
   2191  */
   2192 STATIC int
   2193 _bcm_td3_oob_stats_pool_mapping_set(int unit,
   2194                         int offset, uint32 spid)
   2195 {
   2196     uint32 entry[SOC_MAX_MEM_WORDS];
   2197 
   2198     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   2199 
   2200     /* Read the STATS_INTF_SERVPOOL_LIST memory into entry buffer */
   2201     SOC_IF_ERROR_RETURN
   2202         (soc_mem_read(unit, STATS_INTF_SERVPOOL_LISTm, MEM_BLOCK_ALL,
   2203                       offset, entry));
   2204 
   2205     soc_mem_field32_set(unit, STATS_INTF_SERVPOOL_LISTm, entry,
   2206                         SPIDf, spid);
   2207 
   2208     /* Write the entry buffer into STATS_INTF_SERVPOOL_LIST memory */
   2209     SOC_IF_ERROR_RETURN
   2210         (soc_mem_write(unit, STATS_INTF_SERVPOOL_LISTm, MEM_BLOCK_ALL,
   2211                       offset, entry));
   2212 
   2213     return BCM_E_NONE;
   2214 }
   2215 
   2216 /*
   2217  * Function:
   2218  *      _bcm_td3_oob_stats_pool_mapping_get
   2219  * Purpose:
   2220  *      Get the service pool id at a given index in the memory.
   2221  *      OOB Stats will be reported in the same order
   2222  *      as the service pool ids are programmed in the memory.
   2223  * Parameters:
   2224  *      unit - (IN) StrataSwitch unit number
   2225  *      offset - (IN) Index at which service pool
   2226  *               in the service pool list needs to be added
   2227  *      spid - (OUT) Specifies the service pool for which the corresponding pool
   2228  *             size should be reported. Mapping as follows:
   2229  *                 0-3: Report stats for ingress service pool ID 0-3
   2230  *                 4-7: Report stats for egress service pool ID 0-3
   2231  *                 15: End reporting round
   2232  *             Reset Value: 0xF
   2233  * Returns:
   2234  *      BCM_E_XXX
   2235  */
   2236 STATIC int
   2237 _bcm_td3_oob_stats_pool_mapping_get(int unit,
   2238                         int offset, uint32 *spid)
   2239 {
   2240     uint32 entry[SOC_MAX_MEM_WORDS];
   2241 
   2242     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   2243 
   2244     /* Read the STATS_INTF_SERVPOOL_LIST memory entry buffer */
   2245     SOC_IF_ERROR_RETURN
   2246         (soc_mem_read(unit, STATS_INTF_SERVPOOL_LISTm, MEM_BLOCK_ALL,
   2247                       offset, entry));
   2248 
   2249     *spid = soc_mem_field32_get(unit, STATS_INTF_SERVPOOL_LISTm, entry,
   2250                                 SPIDf);
   2251 
   2252     return BCM_E_NONE;
   2253 }
   2254 
   2255 /*
   2256  * Function:
   2257  *      _bcm_td3_oob_stats_queue_mapping_set
   2258  * Purpose:
   2259  *      Set the queue id at a given index in the memory
   2260  *      so that OOB Stats will be reported in the same order
   2261  *      as the queue ids are programmed in the memory.
   2262  * Parameters:
   2263  *      unit - (IN) StrataSwitch unit number
   2264  *      offset - (IN) Index at which Queue Id
   2265  *               in the queue list needs to be added
   2266  *      pipe_id - (IN) pipe ID 
   2267  *      queue_id - (IN) logical queue ID
   2268  * Returns:
   2269  *      BCM_E_XXX
   2270  */
   2271 STATIC int
   2272 _bcm_td3_oob_stats_queue_mapping_set(int unit,
   2273                         int offset, int pipe_id, int queue_id)
   2274 {
   2275     uint32 entry[SOC_MAX_MEM_WORDS];
   2276 
   2277     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   2278 
   2279     /* Read the STATS_INTF_QUEUE_LIST memory entry buffer */
   2280     SOC_IF_ERROR_RETURN
   2281         (soc_mem_read(unit, STATS_INTF_QUEUE_LISTm, MEM_BLOCK_ALL,
   2282                       offset, entry));
   2283 
   2284     soc_mem_field32_set(unit, STATS_INTF_QUEUE_LISTm, entry,
   2285                         PIPE_IDf, pipe_id);
   2286     soc_mem_field32_set(unit, STATS_INTF_QUEUE_LISTm, entry,
   2287                         LOGICAL_QUEUE_IDf, queue_id);
   2288 
   2289     /* Write the entry buffer into STATS_INTF_QUEUE_LIST memory */
   2290     SOC_IF_ERROR_RETURN
   2291         (soc_mem_write(unit, STATS_INTF_QUEUE_LISTm, MEM_BLOCK_ALL,
   2292                       offset, entry));
   2293 
   2294     return BCM_E_NONE;
   2295 }
   2296 
   2297 /*
   2298  * Function:
   2299  *      _bcm_td3_oob_stats_queue_mapping_get
   2300  * Purpose:
   2301  *      Get the UC queue id at a given index in the memory.
   2302  *      OOB Stats will be reported in the same order
   2303  *      as the UC queue ids are programmed in the memory.
   2304  * Parameters:
   2305  *      unit - (IN) StrataSwitch unit number
   2306  *      offset - (IN) Index at which Queue Id
   2307  *               in the queue list needs to be added
   2308  *      gport - (OUT) UC Queue gport
   2309  * Returns:
   2310  *      BCM_E_XXX
   2311  */
   2312 STATIC int
   2313 _bcm_td3_oob_stats_queue_mapping_get(int unit, int offset,
   2314                          bcm_gport_t *gport)
   2315 {
   2316     int logical_queue_id = -1;
   2317     int pipe_id = -1;
   2318     bcm_cos_t cosq = -1;
   2319     soc_info_t *si;
   2320     int mmu_port = 1, phy_port = -1, logical_port = -1;
   2321     uint32 entry[SOC_MAX_MEM_WORDS];
   2322 
   2323     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   2324 
   2325     /* Read the STATS_INTF_QUEUE_LIST memory entry buffer */
   2326     SOC_IF_ERROR_RETURN
   2327         (soc_mem_read(unit, STATS_INTF_QUEUE_LISTm, MEM_BLOCK_ALL,
   2328                       offset, entry));
   2329 
   2330     logical_queue_id = soc_mem_field32_get(unit, STATS_INTF_QUEUE_LISTm, entry,
   2331                                            LOGICAL_QUEUE_IDf);
   2332 
   2333     pipe_id = soc_mem_field32_get(unit, STATS_INTF_QUEUE_LISTm, entry,
   2334                                   PIPE_IDf);
   2335 
   2336     if (logical_queue_id == _TD3_OOB_STATS_END_QUEUE_REPORT) {
   2337         *gport = _TD3_OOB_STATS_END_QUEUE_REPORT;
   2338     } else {
   2339         si = &SOC_INFO(unit);
   2340 
   2341         if (si == NULL) {
   2342             return BCM_E_INTERNAL;
   2343         }
   2344 
   2345         cosq = logical_queue_id % _TD3_NUM_UCAST_QUEUE_PER_PORT;
   2346         mmu_port = (pipe_id * (SOC_TD3_MMU_PORT_STRIDE + 1))
   2347                     + (logical_queue_id / _TD3_NUM_UCAST_QUEUE_PER_PORT); 
   2348 
   2349         phy_port = si->port_m2p_mapping[mmu_port];
   2350         logical_port = si->port_p2l_mapping[phy_port];
   2351         BCM_IF_ERROR_RETURN
   2352             (_bcm_td3_cosq_port_cos_resolve(unit, logical_port, cosq,
   2353                                            _BCM_TD3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   2354                                            gport));
   2355     }
   2356 
   2357     return BCM_E_NONE;
   2358 }
   2359 
   2360 /*
   2361  * Function:
   2362  *      bcm_td3_oob_stats_config_set
   2363  * Purpose:
   2364  *      Set the global configuration setting
   2365  *      for OOB STATS.
   2366  * Parameters:
   2367  *      unit - (IN) StrataSwitch unit number
   2368  *      config - (IN) OOB Stats Configuration structure
   2369  * Returns:
   2370  *      BCM_E_XXX
   2371  */
   2372 int bcm_td3_oob_stats_config_set(int unit,
   2373                 bcm_oob_stats_config_t *config)
   2374 {
   2375     if (config == NULL) {
   2376         return BCM_E_PARAM;
   2377     }
   2378 
   2379     if (config->config_id > _TD3_MAX_STATS_CONFIG_ID) {
   2380         return BCM_E_PARAM;
   2381     }
   2382 
   2383     BCM_IF_ERROR_RETURN
   2384         (_bcm_td3_oob_stats_config_flags_set(unit, config->flags));
   2385 
   2386     BCM_IF_ERROR_RETURN
   2387         (_bcm_td3_oob_stats_config_ipg_set(unit,
   2388                                           config->inter_pkt_gap));
   2389 
   2390     BCM_IF_ERROR_RETURN
   2391         (_bcm_td3_oob_stats_config_cfg_id_set(unit,
   2392                                              config->config_id));
   2393 
   2394     return BCM_E_NONE;
   2395 }
   2396 
   2397 /*
   2398  * Function:
   2399  *      bcm_td3_oob_stats_config_get
   2400  * Purpose:
   2401  *      Get the global configuration setting
   2402  *      for OOB STATS.
   2403  * Parameters:
   2404  *      unit - (IN) StrataSwitch unit number
   2405  *      config - (OUT) OOB Stats Configuration structure
   2406  * Returns:
   2407  *      BCM_E_XXX
   2408  */
   2409 int bcm_td3_oob_stats_config_get(int unit,
   2410                 bcm_oob_stats_config_t *config)
   2411 {
   2412     if (config == NULL) {
   2413         return BCM_E_PARAM;
   2414     }
   2415 
   2416     BCM_IF_ERROR_RETURN
   2417         (_bcm_td3_oob_stats_config_flags_get(unit, config));
   2418 
   2419     BCM_IF_ERROR_RETURN
   2420         (_bcm_td3_oob_stats_config_ipg_get(unit, config));
   2421 
   2422     BCM_IF_ERROR_RETURN
   2423         (_bcm_td3_oob_stats_config_cfg_id_get(unit, config));
   2424 
   2425     return BCM_E_NONE;
   2426 }
   2427 
   2428 
   2429 /*
   2430  * Function:
   2431  *      bcm_td3_oob_stats_pool_mapping_multi_set
   2432  * Purpose:
   2433  *      Set the service pool id at a given index in the memory
   2434  *      so that OOB Stats will be reported in the same order
   2435  *      as the service pool ids are programmed in the memory.
   2436  * Parameters:
   2437  *      unit - (IN) StrataSwitch unit number
   2438  *      array_count - (IN) Number of elements in array
   2439  *      offset_array - (IN) Indexes at which service pool
   2440  *                      in the service pool list needs to be added
   2441  *      dir_array - (IN) Direction array
   2442  *      pool_array - (IN) Service Pool ID array
   2443  * Returns:
   2444  *      BCM_E_XXX
   2445  */
   2446 int bcm_td3_oob_stats_pool_mapping_multi_set(int unit,
   2447                         int array_count, int *offset_array,
   2448                         uint8 *dir_array, bcm_service_pool_id_t *pool_array)
   2449 {
   2450     int idx = 0;
   2451 
   2452     if ((array_count < 0) || (array_count > _TD3_MAX_IDX_STATS_POOL_LIST)) {
   2453         return BCM_E_PARAM;
   2454     }
   2455 
   2456     if ((offset_array == NULL) ||
   2457         (dir_array == NULL) ||
   2458         (pool_array == NULL)) {
   2459         return BCM_E_PARAM;
   2460     }
   2461 
   2462     for (idx = 0; idx < array_count; idx++) {
   2463         if ((offset_array[idx] < 0) &&
   2464             (offset_array[idx] >= _TD3_MAX_IDX_STATS_POOL_LIST)) {
   2465             return BCM_E_PARAM;
   2466         }
   2467     }
   2468 
   2469     for (idx = 0; idx < array_count; idx++) {
   2470         BCM_IF_ERROR_RETURN
   2471             (bcm_td3_oob_stats_pool_mapping_set(unit, offset_array[idx],
   2472                                                dir_array[idx],
   2473                                                pool_array[idx]));
   2474     }
   2475 
   2476     return BCM_E_NONE;
   2477 }
   2478 
   2479 /*
   2480  * Function:
   2481  *      bcm_td3_oob_stats_pool_mapping_multi_get
   2482  * Purpose:
   2483  *      Get the service pool id at a given index in the memory.
   2484  *      OOB Stats will be reported in the same order
   2485  *      as the service pool ids are programmed in the memory.
   2486  * Parameters:
   2487  *      unit - (IN) StrataSwitch unit number
   2488  *      array_max - (IN) Number of elements in array
   2489  *      offset_array - (IN) Indexes at which service pool
   2490  *                      in the service pool list needs to be added
   2491  *      dir_array - (OUT) Direction array
   2492  *      pool_array - (OUT) Service Pool ID array
   2493  *      array_count - (OUT) Number of elements returned in the array
   2494  * Returns:
   2495  *      BCM_E_XXX
   2496  */
   2497 int bcm_td3_oob_stats_pool_mapping_multi_get(int unit,
   2498                         int array_max, int *offset_array, uint8 *dir_array,
   2499                         bcm_service_pool_id_t *pool_array, int *array_count)
   2500 {
   2501     int idx = 0;
   2502 
   2503     if ((offset_array == NULL) ||
   2504         (dir_array == NULL) ||
   2505         (pool_array == NULL) ||
   2506         (array_count == NULL)) {
   2507             return BCM_E_PARAM;
   2508     }
   2509 
   2510     if ((array_max >= 0) && (array_max <= _TD3_MAX_IDX_STATS_POOL_LIST)) {
   2511         *array_count = array_max;
   2512     } else if (array_max > _TD3_MAX_IDX_STATS_POOL_LIST) {
   2513         *array_count = _TD3_MAX_IDX_STATS_POOL_LIST;
   2514     } else {
   2515         return BCM_E_PARAM;
   2516     }
   2517 
   2518     for (idx = 0; idx < *array_count; idx++) {
   2519         if ((offset_array[idx] < 0) &&
   2520             (offset_array[idx] >= _TD3_MAX_IDX_STATS_POOL_LIST)) {
   2521             return BCM_E_PARAM;
   2522         }
   2523     }
   2524 
   2525     for (idx = 0; idx < *array_count; idx++) {
   2526         BCM_IF_ERROR_RETURN
   2527             (bcm_td3_oob_stats_pool_mapping_get(unit, offset_array[idx],
   2528                                                &dir_array[idx],
   2529                                                &pool_array[idx]));
   2530 
   2531     }
   2532 
   2533     return BCM_E_NONE;
   2534 }
   2535 
   2536 /*
   2537  * Function:
   2538  *      bcm_td3_oob_stats_pool_mapping_set
   2539  * Purpose:
   2540  *      Set the service pool id at a given index in the memory
   2541  *      so that OOB Stats will be reported in the same order
   2542  *      as the service pool ids are programmed in the memory.
   2543  * Parameters:
   2544  *      unit - (IN) StrataSwitch unit number
   2545  *      offset - (IN) Index at which service pool
   2546  *               in the service pool list needs to be added
   2547  *      dir - (IN) Direction
   2548  *      pool - (IN) Service Pool ID
   2549  * Returns:
   2550  *      BCM_E_XXX
   2551  */
   2552 int bcm_td3_oob_stats_pool_mapping_set(int unit,
   2553                         int offset, uint8 dir,
   2554                         bcm_service_pool_id_t pool)
   2555 {
   2556     uint32 spid = 0x0;
   2557 
   2558     if (((pool < 0) || (pool >= _TD3_MMU_NUM_POOL)) &&
   2559         (pool != _TD3_OOB_STATS_END_POOL_REPORT)) {
   2560         return BCM_E_PARAM;
   2561     }
   2562 
   2563     if ((offset < 0) || (offset >= _TD3_MAX_IDX_STATS_POOL_LIST)) {
   2564         return BCM_E_PARAM;
   2565     }
   2566 
   2567     if ((dir != BCM_OOB_STATS_INGRESS) &&
   2568         (dir != BCM_OOB_STATS_EGRESS)) {
   2569         if (pool != _TD3_OOB_STATS_END_POOL_REPORT) {
   2570             return BCM_E_PARAM;
   2571         }
   2572     }
   2573 
   2574     if ((dir == BCM_OOB_STATS_EGRESS) &&
   2575         (pool != _TD3_OOB_STATS_END_POOL_REPORT)) {
   2576         /* Egress Service Pool spid value [4, ..., 7]*/
   2577         spid = pool | 0x4;
   2578     } else {
   2579         /* Ingress Service Pool spid value [0, ..., 3]*/
   2580         spid = pool;
   2581     }
   2582 
   2583     BCM_IF_ERROR_RETURN
   2584         (_bcm_td3_oob_stats_pool_mapping_set(unit, offset, spid));
   2585 
   2586     return BCM_E_NONE;
   2587 }
   2588 
   2589 /*
   2590  * Function:
   2591  *      bcm_td3_oob_stats_pool_mapping_get
   2592  * Purpose:
   2593  *      Get the service pool id at a given index in the memory.
   2594  *      OOB Stats will be reported in the same order
   2595  *      as the service pool ids are programmed in the memory.
   2596  * Parameters:
   2597  *      unit - (IN) StrataSwitch unit number
   2598  *      offset - (IN) Index at which service pool
   2599  *               in the service pool list needs to be added
   2600  *      dir - (OUT) Direction
   2601  *      pool - (OUT) Service Pool ID
   2602  * Returns:
   2603  *      BCM_E_XXX
   2604  */
   2605 int bcm_td3_oob_stats_pool_mapping_get(int unit,
   2606                         int offset, uint8 *dir,
   2607                         bcm_service_pool_id_t *pool)
   2608 {
   2609     uint32 spid = 0x0;
   2610 
   2611     if ((offset < 0) || (offset >= _TD3_MAX_IDX_STATS_POOL_LIST)) {
   2612         return BCM_E_PARAM;
   2613     }
   2614 
   2615     BCM_IF_ERROR_RETURN
   2616         (_bcm_td3_oob_stats_pool_mapping_get(unit, offset, &spid));
   2617 
   2618     if (spid == _TD3_OOB_STATS_END_POOL_REPORT) {
   2619         *pool = _TD3_OOB_STATS_END_POOL_REPORT;
   2620     } else {
   2621         /* Ingress Service Pool spid value [0, ..., 3]*/
   2622         /* Egress Service Pool spid value [4, ..., 7]*/
   2623         *pool = spid & 0x3;
   2624         if (spid & 0x4) {
   2625             *dir = BCM_OOB_STATS_EGRESS;
   2626         } else {
   2627             *dir = BCM_OOB_STATS_INGRESS;
   2628         }
   2629     }
   2630 
   2631     return BCM_E_NONE;
   2632 }
   2633 
   2634 /*
   2635  * Function:
   2636  *      bcm_td3_oob_stats_queue_mapping_multi_set
   2637  * Purpose:
   2638  *      Set the queue id at a given index in the memory
   2639  *      so that OOB Stats will be reported in the same order
   2640  *      as the service pool ids are programmed in the memory.
   2641  * Parameters:
   2642  *      unit - (IN) StrataSwitch unit number
   2643  *      array_count - (IN) Number of elements in array
   2644  *      offset_array - (IN) Indexes at which Queue Id
   2645  *                      in the queue list needs to be added
   2646  *      gport_array - (IN) Queue gport array
   2647  * Returns:
   2648  *      BCM_E_XXX
   2649  */
   2650 int bcm_td3_oob_stats_queue_mapping_multi_set(int unit,
   2651                         int array_count, int *offset_array,
   2652                         bcm_gport_t *gport_array)
   2653 {
   2654     int idx = 0;
   2655 
   2656     if ((array_count < 0) || (array_count > _TD3_MAX_IDX_STATS_QUEUE_LIST)) {
   2657         return BCM_E_PARAM;
   2658     }
   2659 
   2660     if ((offset_array == NULL) ||
   2661         (gport_array == NULL)) {
   2662         return BCM_E_PARAM;
   2663     }
   2664 
   2665     for (idx = 0; idx < array_count; idx++) {
   2666         if ((offset_array[idx] < 0) &&
   2667             (offset_array[idx] >= _TD3_MAX_IDX_STATS_QUEUE_LIST)) {
   2668             return BCM_E_PARAM;
   2669         }
   2670     }
   2671 
   2672     for (idx = 0; idx < array_count; idx++) {
   2673         BCM_IF_ERROR_RETURN
   2674             (bcm_td3_oob_stats_queue_mapping_set(unit, offset_array[idx],
   2675                                                 gport_array[idx]));
   2676     }
   2677 
   2678     return BCM_E_NONE;
   2679 }
   2680 
   2681 /*
   2682  * Function:
   2683  *      bcm_td3_oob_stats_queue_mapping_multi_get
   2684  * Purpose:
   2685  *      Get the queue id at a given index in the memory.
   2686  *      OOB Stats will be reported in the same order
   2687  *      as the queue ids are programmed in the memory.
   2688  * Parameters:
   2689  *      unit - (IN) StrataSwitch unit number
   2690  *      array_max - (IN) Maximum number of elements in array
   2691  *      offset_array - (IN) Indexes at which Queue Id
   2692  *                      in the queue list needs to be added
   2693  *      gport_array - (OUT) Queue gport array
   2694  *      array_count - (OUT) Number of elements in array
   2695  * Returns:
   2696  *      BCM_E_XXX
   2697  */
   2698 int bcm_td3_oob_stats_queue_mapping_multi_get(int unit,
   2699                         int array_max, int *offset_array,
   2700                         bcm_gport_t *gport_array, int *array_count)
   2701 {
   2702     int idx = 0;
   2703 
   2704     if ((offset_array == NULL) ||
   2705         (gport_array == NULL) ||
   2706         (array_count == NULL)) {
   2707         return BCM_E_PARAM;
   2708     }
   2709 
   2710     if ((array_max >= 0) && (array_max <= _TD3_MAX_IDX_STATS_QUEUE_LIST)) {
   2711         *array_count = array_max;
   2712     } else if (array_max > _TD3_MAX_IDX_STATS_QUEUE_LIST) {
   2713         *array_count = _TD3_MAX_IDX_STATS_QUEUE_LIST;
   2714     } else {
   2715         return BCM_E_PARAM;
   2716     }
   2717 
   2718     for (idx = 0; idx < *array_count; idx++) {
   2719         BCM_IF_ERROR_RETURN
   2720             (bcm_td3_oob_stats_queue_mapping_get(unit, offset_array[idx],
   2721                                                 &gport_array[idx]));
   2722     }
   2723 
   2724     return BCM_E_NONE;
   2725 }
   2726 
   2727 
   2728 /*
   2729  * Function:
   2730  *      bcm_td3_oob_stats_queue_mapping_set
   2731  * Purpose:
   2732  *      Set the queue id at a given index in the memory
   2733  *      so that OOB Stats will be reported in the same order
   2734  *      as the service pool ids are programmed in the memory.
   2735  * Parameters:
   2736  *      unit - (IN) StrataSwitch unit number
   2737  *      offset - (IN) Index at which Queue Id
   2738  *               in the queue list needs to be added
   2739  *      gport - (IN) Queue gport
   2740  * Returns:
   2741  *      BCM_E_XXX
   2742  */
   2743 int bcm_td3_oob_stats_queue_mapping_set(int unit,
   2744                         int offset, bcm_gport_t gport)
   2745 {
   2746     bcm_port_t local_port = -1;
   2747     int logical_queue_id = -1;
   2748     int hw_index = -1;
   2749     int mmu_port, phy_port;
   2750     soc_info_t *si;
   2751     int pipe = -1;
   2752 
   2753     if ((offset < 0) || (offset >= _TD3_MAX_IDX_STATS_QUEUE_LIST)) {
   2754         return BCM_E_PARAM;
   2755     }
   2756 
   2757     if (gport == _TD3_OOB_STATS_END_QUEUE_REPORT) {
   2758         logical_queue_id = _TD3_OOB_STATS_END_QUEUE_REPORT;
   2759     } else {
   2760         si = &SOC_INFO(unit);
   2761 
   2762         if (si == NULL) {
   2763             return BCM_E_INTERNAL;
   2764         }
   2765 
   2766         BCM_IF_ERROR_RETURN
   2767             (_bcm_td3_cosq_index_resolve(unit, gport, -1,
   2768                                         _BCM_TD3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   2769                                         &local_port, &hw_index, NULL));
   2770 
   2771         phy_port = si->port_l2p_mapping[local_port];
   2772         mmu_port = si->port_p2m_mapping[phy_port];
   2773 
   2774         pipe = si->port_pipe[local_port];
   2775         logical_queue_id = ((mmu_port % (SOC_TD3_MMU_PORT_STRIDE + 1)) *
   2776                            _TD3_NUM_UCAST_QUEUE_PER_PORT) +
   2777                            (hw_index % _TD3_NUM_UCAST_QUEUE_PER_PORT);
   2778     }
   2779 
   2780     BCM_IF_ERROR_RETURN
   2781         (_bcm_td3_oob_stats_queue_mapping_set(unit, offset, pipe,
   2782                                              logical_queue_id));
   2783 
   2784     return BCM_E_NONE;
   2785 }
   2786 
   2787 /*
   2788  * Function:
   2789  *      bcm_td3_oob_stats_queue_mapping_get
   2790  * Purpose:
   2791  *      Get the queue id at a given index in the memory.
   2792  *      OOB Stats will be reported in the same order
   2793  *      as the queue ids are programmed in the memory.
   2794  * Parameters:
   2795  *      unit - (IN) StrataSwitch unit number
   2796  *      offset - (IN) Index at which Queue Id
   2797  *               in the queue list needs to be added
   2798  *      gport - (OUT) Queue gport
   2799  * Returns:
   2800  *      BCM_E_XXX
   2801  */
   2802 int bcm_td3_oob_stats_queue_mapping_get(int unit,
   2803                         int offset, bcm_gport_t *gport)
   2804 {
   2805     if ((offset < 0) || (offset >= _TD3_MAX_IDX_STATS_QUEUE_LIST)) {
   2806         return BCM_E_PARAM;
   2807     }
   2808 
   2809     if (gport == NULL) {
   2810         return BCM_E_PARAM;
   2811     }
   2812 
   2813     BCM_IF_ERROR_RETURN
   2814         (_bcm_td3_oob_stats_queue_mapping_get(unit, offset, gport));
   2815 
   2816     return BCM_E_NONE;
   2817 }
   2818 
   2819 #endif /* BCM_TRIDENT3_SUPPORT */