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 (90348B)


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