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

traffic_manager.c (197060B)


      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  * File:        traffic_manager.c
      8  * Purpose:     Tomahawk3 IDB, EDB and MMU routines
      9  * Requires:
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/drv.h>
     15 #include <soc/mem.h>
     16 #include <soc/debug.h>
     17 #include <soc/hash.h>
     18 
     19 #if defined(BCM_TOMAHAWK3_SUPPORT)
     20 
     21 #include <soc/tomahawk3.h>
     22 #include <soc/init/tomahawk3_idb_init.h>
     23 #include <soc/init/tomahawk3_port_init.h>
     24 #include <soc/tomahawk2_tdm.h>
     25 #include <soc/init/tomahawk3_tdm.h>
     26 #include <soc/init/tomahawk3_ep_init.h>
     27 #include <bcm_int/common/tx.h>
     28 #include <soc/flexport/tomahawk3_flexport.h>
     29 
     30 soc_th3_mmu_info_t *th3_cosq_mmu_info[SOC_MAX_NUM_DEVICES];
     31 soc_th3_sched_profile_info_t th3_sched_profile_info[SOC_MAX_NUM_DEVICES][SOC_TH3_MAX_NUM_SCHED_PROFILE][SOC_TH3_NUM_GP_QUEUES];
     32 int L1_TO_L0_MAPPING[SOC_MAX_NUM_DEVICES][SOC_TH3_MAX_NUM_SCHED_PROFILE]
     33                                 [SOC_TH3_NUM_GP_QUEUES];
     34 int L0_TO_L1_MAPPING_NUM[SOC_MAX_NUM_DEVICES][SOC_TH3_MAX_NUM_SCHED_PROFILE]
     35                                         [SOC_TH3_NUM_GP_QUEUES];
     36 int L0_TO_COSQ_MAPPING[SOC_MAX_NUM_DEVICES][SOC_TH3_MAX_NUM_SCHED_PROFILE]
     37                                         [SOC_TH3_NUM_GP_QUEUES];
     38 
     39 int soc_th3_chip_queue_num_get(int unit, soc_port_t port, int qid, int type,
     40         int *hw_index) {
     41     /* type 0 UC queue, type 1 MC queue */
     42     int mmu_local_port, mmuq, pipe, num_ucq;
     43     uint32 pipe_map;
     44     soc_info_t *si = &SOC_INFO(unit);
     45     int q_base_list[] = {0, 276, 516, 744, 972, 1200, 1440, 1680};
     46     if (!SOC_PORT_VALID(unit, port)) {
     47         return SOC_E_PORT;
     48     }
     49     pipe = si->port_pipe[port];
     50     mmu_local_port = si->port_l2i_mapping[port];
     51     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
     52     if (!(pipe_map & (1U << pipe))) {
     53         return SOC_E_PORT;
     54     }
     55     num_ucq = _soc_th3_get_num_ucq(unit);
     56     if (type == 0) {
     57         if (qid == -1) {
     58             /* return the starting q_num */
     59             *hw_index = q_base_list[pipe] + mmu_local_port * SOC_TH3_NUM_GP_QUEUES;
     60         } else {
     61             if (qid >= num_ucq) {
     62                 return SOC_E_PARAM;
     63             }
     64             mmuq = qid;
     65             *hw_index = q_base_list[pipe] +
     66                     mmu_local_port * SOC_TH3_NUM_GP_QUEUES + mmuq;
     67         }
     68     } else if (type == 1) {
     69         if (qid == -1) {
     70             *hw_index = q_base_list[pipe] +
     71                 mmu_local_port * SOC_TH3_NUM_GP_QUEUES + num_ucq;
     72 
     73         } else {
     74             if (qid >= SOC_TH3_NUM_GP_QUEUES - num_ucq) {
     75                 return SOC_E_PARAM;
     76             }
     77             mmuq = num_ucq + qid;
     78             *hw_index = q_base_list[pipe] +
     79                     mmu_local_port * SOC_TH3_NUM_GP_QUEUES + mmuq;
     80         }
     81     }
     82     return SOC_E_NONE;
     83 }
     84 
     85 uint32
     86 soc_th3_mmu_chip_port_num (int unit, int port)
     87 {
     88     soc_info_t *si = &SOC_INFO(unit);
     89     int global_mmu_port, phy_port, mmu_chip_port, pipe;
     90     pipe = si->port_pipe[port];
     91     phy_port = si->port_l2p_mapping[port];
     92     global_mmu_port = si->port_p2m_mapping[phy_port];
     93     mmu_chip_port = (global_mmu_port % SOC_TH3_MMU_PORT_STRIDE) +
     94                     (pipe * SOC_TH3_MAX_DEV_PORTS_PER_PIPE);
     95     return mmu_chip_port;
     96 }
     97 
     98 uint32
     99 soc_th3_mmu_local_port_num (int unit, int port)
    100 {
    101     soc_info_t *si = &SOC_INFO(unit);
    102     return si->port_l2i_mapping[port];
    103 }
    104 
    105 
    106 /*
    107  *Function: soc_tomahawk3_mem_is_itm
    108  *Purpose: check if memory is in ITM block
    109  *Params:
    110  *  unit: Device unit number
    111  *  mem: base memory
    112  */
    113 int soc_tomahawk3_mem_is_itm(int unit, soc_mem_t mem)
    114 {
    115     int block_info_index;
    116 
    117     if (mem != INVALIDm) {
    118         if (SOC_MEM_IS_VALID(unit, mem)) {
    119            block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
    120            if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_ITM) {
    121                return 1;
    122            }
    123         }
    124     }
    125     return 0;
    126 }
    127 
    128 /*
    129  *Function: soc_tomahawk3_reg_is_itm
    130  *Purpose: check if register is in ITM block
    131  *Params:
    132  *  unit: Device unit number
    133  *  mem: base register
    134  */
    135 int soc_tomahawk3_reg_is_itm(int unit, soc_reg_t reg)
    136 {
    137     if (reg != INVALIDr) {
    138         if (SOC_REG_IS_VALID(unit, reg)) {
    139             return (SOC_REG_BLOCK_IS(unit, reg, SOC_BLK_MMU_ITM));
    140         }
    141     }
    142 
    143     return 0;
    144 }
    145 
    146 
    147 /*Function to check if the itm, base_index combination is valid
    148  *Base Type: IPORT/IPIPE: Pipes 0,1,6,7 ITM0, Pipes 2,3,4,5 ITM1
    149  *Base Type: EPORT/EPIPE: Can be in both ITMs;
    150  *ITM should be valied for device config (esp. for half setups)
    151  *Base Type: ITM: Passed ITM is valid
    152  */
    153 int
    154 soc_tomahawk3_itm_base_index_check(int unit, int base_type, int itm,
    155                                   int base_index, char *msg)
    156 {
    157     soc_info_t *si;
    158     int pipe;
    159     uint32 map;
    160     char *base_name;
    161 
    162     si = &SOC_INFO(unit);
    163 
    164     if (itm == -1 || base_index == -1) {
    165         return SOC_E_NONE;
    166     }
    167 
    168     if (itm < NUM_ITM(unit) && si->itm_ipipe_map[itm] == 0) {
    169         if (msg) {
    170             LOG_CLI((BSL_META_U(unit,
    171                                 "%s: ITM%d is not in config\n"),
    172                      msg, itm));
    173         }
    174         return SOC_E_PARAM;
    175     }
    176 
    177     switch (base_type) {
    178     case 0: /* IPORT */
    179     case 1: /* EPORT */
    180         base_name = base_type == 0 ? "IPORT" : "EPORT";
    181         pipe = si->port_pipe[base_index];
    182         if (pipe == -1) {
    183             if (msg) {
    184                 LOG_CLI((BSL_META_U(unit,
    185                                     "%s: %s%d is not in config\n"),
    186                          msg, base_name, base_index));
    187             }
    188         } else if (itm < NUM_ITM(unit)) { /* Unique access type */
    189             map = base_type == 0 ?
    190                 si->ipipe_itm_map[pipe] : si->itm_map;
    191             if (map & (1 << itm)) {
    192                 break;
    193             }
    194             if (msg != NULL) {
    195                 LOG_CLI((BSL_META_U(unit,
    196                                     "%s: %s%d is not in ITM%d\n"),
    197                          msg, base_name, base_index, itm));
    198             }
    199         } else {
    200             break;
    201         }
    202         return SOC_E_PARAM;
    203     case 2: /* IPIPE */
    204     case 3: /* EPIPE */
    205         if (base_type == 2) {
    206             base_name = "IPIPE";
    207             map = si->ipipe_itm_map[base_index];
    208         } else {
    209             base_name = "EPIPE";
    210             map = si->itm_map;
    211         }
    212         if (map == 0) {
    213             if (msg) {
    214                 LOG_CLI((BSL_META_U(unit,
    215                                     "%s: %s%d is not in config\n"),
    216                          msg, base_name, base_index));
    217             }
    218         } else if (itm < NUM_ITM(unit)) { /* Unique access type */
    219             if (map & (1 << itm)) {
    220                 break;
    221             }
    222             if (msg != NULL) {
    223                 LOG_CLI((BSL_META_U(unit,
    224                                     "%s: %s%d is not in ITM%d\n"),
    225                          msg, base_name, base_index, itm));
    226             }
    227         } else {
    228             break;
    229         }
    230         return SOC_E_PARAM;
    231     case 4: /* CHIP */
    232         break;
    233     case 5: /* ITM*/
    234         if (si->itm_ipipe_map[base_index] != 0) {
    235             break;
    236         }
    237         if (msg != NULL) {
    238             LOG_CLI((BSL_META_U(unit,
    239                                 "%s: ITM%d is not in config\n"),
    240                      msg, base_index));
    241         }
    242         return SOC_E_PARAM;
    243     }
    244 
    245     return SOC_E_NONE;
    246 }
    247 
    248 /*
    249  *Function: _soc_tomahawk3_itm_reg_check
    250  *Purpose: Check if resigter is in ITM block and passed ITM value is in range
    251  *         Override itm with access_type for unique memories
    252  *         Call check to verify itm/base_index combination
    253  *Params:
    254  *  unit: Device unit number
    255  *  reg:  Register name
    256  *  itm:  ITM#
    257  *  base_index: base index to be accessed
    258  */
    259 STATIC int
    260 _soc_tomahawk3_itm_reg_check(int unit, soc_reg_t reg, int itm, int base_index)
    261 {
    262     int acc_type, base_type;
    263 
    264     if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_ITM)) {
    265         LOG_CLI((BSL_META_U(unit,
    266                             "%s is not ITM register\n"), SOC_REG_NAME(unit, reg)));
    267         return SOC_E_PARAM;
    268     }
    269 
    270     if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */
    271         if (itm == -1 || itm >= NUM_ITM(unit)) {
    272             LOG_CLI((BSL_META_U(unit,
    273                                 "%s bad ITM value %d\n"),
    274                      SOC_REG_NAME(unit, reg), itm));
    275             return SOC_E_PARAM;
    276         }
    277     } else {
    278         acc_type = SOC_REG_ACC_TYPE(unit, reg);
    279         if (acc_type < NUM_ITM(unit)) { /* UNIQUE per ITM register */
    280             if (itm != acc_type) {
    281                 LOG_CLI((BSL_META_U(unit,
    282                                     "Ovveride ITM value %d with ACC_TYPE of %s\n"),
    283                          itm, SOC_REG_NAME(unit, reg)));
    284             }
    285             itm = acc_type;
    286         } else { /* non-UNIQUE register */
    287             return SOC_E_NONE;
    288         }
    289     }
    290     /*retrieve bits [25:23] of memory address for base_type*/
    291     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
    292 
    293     return soc_tomahawk3_itm_base_index_check(unit, base_type, itm, base_index,
    294                                              SOC_REG_NAME(unit, reg));
    295 }
    296 
    297 /*
    298  * Parameters for soc_tomahawk3_itm_reg_access:
    299  *
    300  *    base unique  reg/  itm   write action          read action
    301  *   index  type   mem
    302  *    ==== ====== ===== ===   ================      =================
    303  * #1   -1  no     -     -    all ITMs        first pipe in the first ITM
    304  * #2   -1  yes   base   -1   (same as #1)
    305  * #3   -1  yes   base  0-3   all pipes in the ITM  first pipe in the ITM
    306  * #4   -1  yes  itm0-3  -    (same as #3)
    307  * #5  0-1  no     -     -    applicable ITMs       first ITM has the pipe
    308  *
    309  * - S/W will loop through base types (i.e. pipes) if base_index==-1
    310  * - S/W will loop through applicable ITMs if itm==-1 on unique access type
    311  *   base view (H/W will do the loop for other access types)
    312  */
    313 STATIC int
    314 _soc_tomahawk3_itm_reg_access(int unit, soc_reg_t reg, int itm, int base_index,
    315                              int index, uint64 *data, int write)
    316 {
    317     soc_info_t *si;
    318     soc_reg_t orig_reg;
    319     int port, pipe;
    320     int base_type, break_after_first;
    321     int loop_index;
    322     uint32 base_index_map, itm_map=0;
    323     soc_pbmp_t base_index_pbmp;
    324     uint32 inst;
    325 
    326     si = &SOC_INFO(unit);
    327     orig_reg = reg;
    328     /*retrieve bits [25:23] of memory address for base_type*/
    329     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
    330     break_after_first = TRUE;
    331 
    332     if (itm >= 0 && base_index >= 0) {
    333         SOC_IF_ERROR_RETURN
    334             (_soc_tomahawk3_itm_reg_check(unit, reg, itm, base_index));
    335     }
    336 
    337     if (base_index < -1) {
    338             return SOC_E_PARAM;
    339     }
    340     switch (base_type) {
    341     case 0: /* IPORT */
    342     case 1: /* EPORT */
    343         if (itm >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
    344             reg = SOC_REG_UNIQUE_ACC(unit, reg)[itm];
    345         }
    346         if (base_index == -1) {
    347             SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit));
    348         } else {
    349             /* This argument is logical port, same as soc_reg_get/set */
    350             SOC_PBMP_PORT_SET(base_index_pbmp, base_index);
    351         }
    352         SOC_PBMP_ITER(base_index_pbmp, port) {
    353             pipe = si->port_pipe[port];
    354             if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
    355                 itm_map = base_type == 0 ?
    356                     si->ipipe_itm_map[pipe]:
    357                     si->itm_map;
    358 
    359                 if (write) {
    360                     break_after_first = FALSE;
    361                 }
    362             }
    363             for (itm = 0; itm < NUM_ITM(unit); itm++) {
    364                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
    365                     if (!(itm_map & (1 << itm))) {
    366                         continue;
    367                     }
    368                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[itm];
    369                 }
    370                 if (write) {
    371                     SOC_IF_ERROR_RETURN
    372                         (soc_reg_set(unit, reg, port, index, *data));
    373                 } else {
    374                     SOC_IF_ERROR_RETURN
    375                         (soc_reg_get(unit, reg, port, index, data));
    376                 }
    377                 if (break_after_first) {
    378                     break;
    379                 }
    380             }
    381         }
    382         break;
    383     case 2: /* IPIPE */
    384     case 3: /* EPIPE */
    385         if (itm >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
    386             reg = SOC_REG_UNIQUE_ACC(unit, reg)[itm];
    387         }
    388         soc_tomahawk3_pipe_map_get(unit, &base_index_map);
    389         if (base_index != -1) {
    390             base_index_map &= 1 << base_index;
    391             if (base_index_map == 0) {
    392                 return SOC_E_PARAM;
    393             }
    394         }
    395 
    396         for (base_index = 0; base_index < _TH3_PIPES_PER_DEV; base_index++) {
    397             if (!(base_index_map & (1 << base_index))) {
    398                 continue;
    399             }
    400             /* Select the right ITM for IPIPE and both ITMs for EPIPE*/
    401             if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
    402                 itm_map = base_type == 2 ?
    403                     si->ipipe_itm_map[base_index]:
    404                     si->itm_map;
    405                 if (write) {
    406                     break_after_first = FALSE;
    407                 }
    408             }
    409             /*Check the ITM value passed through params*/
    410             if (itm >=0) {
    411                 itm_map &= (1 << itm);
    412             }
    413             for (itm = 0; itm < NUM_ITM(unit); itm++) {
    414                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
    415                     if (!(itm_map & (1 << itm))) {
    416                         continue;
    417                     }
    418                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[itm];
    419                 }
    420                 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
    421                 if (write) {
    422                     SOC_IF_ERROR_RETURN
    423                         (soc_reg_set(unit, reg, inst, index, *data));
    424                 } else {
    425                     SOC_IF_ERROR_RETURN
    426                         (soc_reg_get(unit, reg, inst, index, data));
    427                 }
    428                 if (break_after_first) {
    429                     break;
    430                 }
    431             }
    432         }
    433         break;
    434     case 4: /* CHIP */
    435         if (write) {
    436             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data));
    437         } else {
    438             SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data));
    439         }
    440         break;
    441     case 5: /* ITM */
    442         if (itm >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
    443             reg = SOC_REG_UNIQUE_ACC(unit, reg)[itm];
    444         }
    445 
    446         if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL ||
    447             SOC_REG_ACC_TYPE(unit, reg) < NUM_ITM(unit)) {
    448             base_index_map = 1;
    449         } else if (base_index == -1) {
    450             base_index_map = 0x3; /*Use both ITMs*/
    451         } else {
    452             base_index_map = 1 << base_index;
    453         }
    454 
    455         /* Loop through ITM(s) only on UNIQUE type base register */
    456         if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
    457             itm_map=si->itm_map;
    458             break_after_first = FALSE;
    459         }
    460 
    461         for (loop_index = 0; loop_index < NUM_ITM(unit); loop_index++) {
    462             if (!(base_index_map & (1 << loop_index))) {
    463                 continue;
    464             }
    465             for (itm = 0; itm < NUM_ITM(unit); itm++) {
    466                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
    467                     if (!(itm_map & (1 << itm))) {
    468                         continue;
    469                     }
    470                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[itm];
    471                 }
    472                 inst = loop_index | SOC_REG_ADDR_INSTANCE_MASK;
    473                 if (write) {
    474                     SOC_IF_ERROR_RETURN
    475                         (soc_reg_set(unit, reg, inst, index, *data));
    476                 } else {
    477                     SOC_IF_ERROR_RETURN
    478                         (soc_reg_get(unit, reg, inst, index, data));
    479                 }
    480                 if (break_after_first) {
    481                     break;
    482                 }
    483             }
    484         }
    485         break;
    486     /* No default case as base_type can have value only between 0-5 */
    487     }
    488 
    489     return SOC_E_NONE;
    490 }
    491 
    492 /*
    493  *Function: soc_tomahawk3_itm_reg32_set
    494  *Purpose: Set ITM register
    495  */
    496 int
    497 soc_tomahawk3_itm_reg32_set(int unit, soc_reg_t reg, int itm, int base_index,
    498                            int index, uint32 data)
    499 {
    500     uint64 data64;
    501 
    502     COMPILER_64_SET(data64, 0, data);
    503     SOC_IF_ERROR_RETURN(_soc_tomahawk3_itm_reg_access(unit, reg, itm, base_index,
    504                                                      index, &data64, TRUE));
    505 
    506     return SOC_E_NONE;
    507 }
    508 
    509 /*
    510  *Function: soc_tomahawk3_itm_reg32_get
    511  *Purpose: Get ITM register
    512  */
    513 int
    514 soc_tomahawk3_itm_reg32_get(int unit, soc_reg_t reg, int itm, int base_index,
    515                            int index, uint32 *data)
    516 {
    517     uint64 data64;
    518 
    519     COMPILER_64_SET(data64, 0, *data);
    520     SOC_IF_ERROR_RETURN(_soc_tomahawk3_itm_reg_access(unit, reg, itm, base_index,
    521                                                      index, &data64, FALSE));
    522     *data = COMPILER_64_LO(data64);
    523 
    524     return SOC_E_NONE;
    525 }
    526 
    527 /*
    528  *Function: soc_tomahawk3_itm_reg_set
    529  *Purpose: Set ITM register
    530  */
    531 int
    532 soc_tomahawk3_itm_reg_set(int unit, soc_reg_t reg, int itm, int base_index,
    533                          int index, uint64 data)
    534 {
    535     return _soc_tomahawk3_itm_reg_access(unit, reg, itm, base_index,
    536                                         index, &data, TRUE);
    537 }
    538 
    539 /*
    540  *Function: soc_tomahawk3_itm_reg_get
    541  *Purpose: Get ITM register
    542  */
    543 int
    544 soc_tomahawk3_itm_reg_get(int unit, soc_reg_t reg, int itm, int base_index,
    545                          int index, uint64 *data)
    546 {
    547     return _soc_tomahawk3_itm_reg_access(unit, reg, itm, base_index,
    548                                         index, data, FALSE);
    549 }
    550 
    551 /*
    552  *Function to check if the EB, base_index combination is valid
    553  *Base Type: IPORT/IPIPE: Can be in any of the 8 EBs
    554  *Base Type: EPORT/EPIPE: Can only be in one EB corresponding to the port/pipe.
    555  *Base Type: ITM: Can be in any EB
    556  *EB should be valied for device config (esp. for half setups)
    557  */
    558 int
    559 soc_tomahawk3_eb_base_index_check(int unit, int base_type, int eb,
    560                                  int base_index, char *msg)
    561 {
    562     soc_info_t *si;
    563     int pipe;
    564     uint32 map, pipe_map =0;
    565     char *base_name;
    566 
    567 
    568     si = &SOC_INFO(unit);
    569 
    570     if (eb == -1 || base_index == -1) {
    571         return SOC_E_NONE;
    572     }
    573 
    574     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
    575 
    576     if ((eb < _TH3_PIPES_PER_DEV) && ((pipe_map & (1 << eb)) == 0)) {
    577         if (msg) {
    578             LOG_CLI((BSL_META_U(unit,
    579                                 "%s: EB%d is not in config\n"),
    580                      msg, eb));
    581         }
    582         return SOC_E_PARAM;
    583     }
    584 
    585     switch (base_type) {
    586     case 0: /* IPORT */
    587     case 1: /* EPORT */
    588         base_name = base_type == 0 ? "IPORT" : "EPORT";
    589         pipe = si->port_pipe[base_index];
    590         if (pipe == -1) {
    591             if (msg) {
    592                 LOG_CLI((BSL_META_U(unit,
    593                                     "%s: %s%d is not in config\n"),
    594                          msg, base_name, base_index));
    595             }
    596         } else if (eb < _TH3_PIPES_PER_DEV) { /* Unique access type */
    597             map = base_type == 0 ?
    598                 pipe_map : (1 << eb);
    599             if (msg != NULL) {
    600                 LOG_CLI((BSL_META_U(unit,
    601                                     "%s: %s%d is not in EB%d\n"),
    602                          msg, base_name, base_index, eb));
    603             }
    604         } else {
    605             break;
    606         }
    607         return SOC_E_PARAM;
    608     case 2: /* IPIPE */
    609     case 3: /* EPIPE */
    610         if (base_type == 2) {
    611             base_name = "IPIPE";
    612             map = pipe_map;
    613         } else {
    614             base_name = "EPIPE";
    615             map = (1 << eb);
    616         }
    617         if (map == 0) {
    618             if (msg) {
    619                 LOG_CLI((BSL_META_U(unit,
    620                                     "%s: %s%d is not in config\n"),
    621                          msg, base_name, base_index));
    622             }
    623         } else if (eb < _TH3_PIPES_PER_DEV) { /* Unique access type */
    624             if (map & (1 << eb)) {
    625                 break;
    626             }
    627             if (msg != NULL) {
    628                 LOG_CLI((BSL_META_U(unit,
    629                                     "%s: %s%d is not in EB%d\n"),
    630                          msg, base_name, base_index, eb));
    631             }
    632         } else {
    633             break;
    634         }
    635         return SOC_E_PARAM;
    636     case 4: /* CHIP */
    637         break;
    638     case 5: /* ITM */
    639         if ((si->itm_map & (1 << base_index)) == 0) {
    640             if (msg != NULL) {
    641                 LOG_CLI((BSL_META_U(unit,
    642                                     "%s: ITM%d is not in config\n"),
    643                          msg, base_index));
    644             }
    645         } else {
    646             break;
    647         }
    648         return SOC_E_PARAM;
    649     }
    650 
    651     return SOC_E_NONE;
    652 }
    653 
    654 /*
    655  *Function: _soc_tomahawk3_eb_reg_check
    656  *Purpose: Check if resigter is in EB block and passed EB value is in range
    657  *         Override itm with access_type for unique memories
    658  *         Call check to verify EB/base_index combination
    659  */
    660 STATIC int
    661 _soc_tomahawk3_eb_reg_check(int unit, soc_reg_t reg, int eb, int base_index)
    662 {
    663     int acc_type, base_type;
    664 
    665     if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_EB)) {
    666         LOG_CLI((BSL_META_U(unit,
    667                             "%s is not EB register\n"), SOC_REG_NAME(unit, reg)));
    668         return SOC_E_PARAM;
    669     }
    670 
    671     if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */
    672         if (eb == -1 || eb >= _TH3_PIPES_PER_DEV) {
    673             LOG_CLI((BSL_META_U(unit,
    674                                 "%s bad EB value %d\n"),
    675                      SOC_REG_NAME(unit, reg), eb));
    676             return SOC_E_PARAM;
    677         }
    678     } else {
    679         acc_type = SOC_REG_ACC_TYPE(unit, reg);
    680         if (acc_type < _TH3_PIPES_PER_DEV) { /* UNIQUE per EB register */
    681             if (eb != acc_type) {
    682                 LOG_CLI((BSL_META_U(unit,
    683                                     "Ovveride EB value %d with ACC_TYPE of %s\n"),
    684                          eb, SOC_REG_NAME(unit, reg)));
    685             }
    686             eb = acc_type;
    687         } else { /* non-UNIQUE register */
    688             return SOC_E_NONE;
    689         }
    690     }
    691     /*retrieve bits [25:23] of memory address for base_type*/
    692     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
    693 
    694     return soc_tomahawk3_eb_base_index_check(unit, base_type, eb, base_index,
    695                                             SOC_REG_NAME(unit, reg));
    696 }
    697 
    698 /*
    699  *Function: _soc_tomahawk3_eb_reg_access
    700  *Purpose: Set/get resgisters in EB block
    701  */
    702 STATIC int
    703 _soc_tomahawk3_eb_reg_access(int unit, soc_reg_t reg, int eb, int base_index,
    704                             int index, uint64 *data, int write)
    705 {
    706     soc_info_t *si;
    707     int port;
    708     int base_type, loop_index;
    709     uint32 base_index_map;
    710     soc_pbmp_t base_index_pbmp;
    711     uint32 inst;
    712 
    713     si = &SOC_INFO(unit);
    714     /*retrieve bits [25:23] of memory address for base_type*/
    715     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
    716 
    717     if (eb >= 0 && base_index >= 0) {
    718         SOC_IF_ERROR_RETURN
    719             (_soc_tomahawk3_eb_reg_check(unit, reg, eb, base_index));
    720     }
    721 
    722     switch (base_type) {
    723     case 0: /* IPORT */
    724     case 1: /* EPORT */
    725         /* No unique access type for such base_type */
    726         if (base_index == -1) {
    727             SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit));
    728         } else {
    729             /* This argument is logical port, same as soc_reg_get/set */
    730             SOC_PBMP_PORT_SET(base_index_pbmp, base_index);
    731         }
    732 
    733         SOC_PBMP_ITER(base_index_pbmp, port) {
    734             if (write) {
    735                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, index, *data));
    736             } else {
    737                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, index, data));
    738             }
    739         }
    740         break;
    741     case 2: /* IPIPE */
    742     case 3: /* EPIPE */
    743         /* No unique access type for such base_type */
    744         soc_tomahawk3_pipe_map_get(unit, &base_index_map);
    745         if (base_index != -1) {
    746             base_index_map &= 1 << base_index;
    747             if (base_index_map == 0) {
    748                 return SOC_E_PARAM;
    749             }
    750         }
    751 
    752         for (loop_index = 0; loop_index < _TH3_PIPES_PER_DEV; loop_index++) {
    753             if (!(base_index_map & (1 << loop_index))) {
    754                 continue;
    755             }
    756             inst = loop_index | SOC_REG_ADDR_INSTANCE_MASK;
    757             if (write) {
    758                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
    759             } else {
    760                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
    761             }
    762         }
    763         break;
    764     case 4: /* CHIP */
    765         if (write) {
    766             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data));
    767         } else {
    768             SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data));
    769         }
    770         break;
    771     case 5: /* ITM */
    772         /* No unique access type for such base_type */
    773         if (base_index == -1) {
    774             base_index_map = si->itm_map;
    775         } else {
    776             base_index_map = 1 << base_index;
    777         }
    778 
    779         for (loop_index = 0; loop_index < NUM_ITM(unit); loop_index++) {
    780             if (!(base_index_map & (1 << loop_index))) {
    781                 continue;
    782             }
    783             inst = loop_index | SOC_REG_ADDR_INSTANCE_MASK;
    784             if (write) {
    785                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
    786             } else {
    787                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
    788             }
    789         }
    790         break;
    791     default:
    792         return SOC_E_INTERNAL;
    793     }
    794 
    795     return SOC_E_NONE;
    796 }
    797 
    798 /*
    799  *Function: _soc_tomahawk3_eb_reg32_set
    800  *Purpose: Set resgisters in EB block
    801  */
    802 int
    803 soc_tomahawk3_eb_reg32_set(int unit, soc_reg_t reg, int eb, int base_index,
    804                           int index, uint32 data)
    805 {
    806     uint64 data64;
    807 
    808     COMPILER_64_SET(data64, 0, data);
    809     SOC_IF_ERROR_RETURN(_soc_tomahawk3_eb_reg_access(unit, reg, eb, base_index,
    810                                                     index, &data64, TRUE));
    811 
    812     return SOC_E_NONE;
    813 }
    814 
    815 /*
    816  *Function: _soc_tomahawk3_eb_reg32_get
    817  *Purpose: Get resgisters in EB block
    818  */
    819 int
    820 soc_tomahawk3_eb_reg32_get(int unit, soc_reg_t reg, int eb, int base_index,
    821                           int index, uint32 *data)
    822 {
    823     uint64 data64;
    824 
    825     COMPILER_64_SET(data64, 0, *data);
    826     SOC_IF_ERROR_RETURN(_soc_tomahawk3_eb_reg_access(unit, reg, eb, base_index,
    827                                                     index, &data64, FALSE));
    828     *data = COMPILER_64_LO(data64);
    829 
    830     return SOC_E_NONE;
    831 }
    832 
    833 /*
    834  *Function: _soc_tomahawk3_eb_reg_set
    835  *Purpose: Set resgisters in EB block
    836  */
    837 int
    838 soc_tomahawk3_eb_reg_set(int unit, soc_reg_t reg, int eb, int base_index,
    839                         int index, uint64 data)
    840 {
    841     return _soc_tomahawk3_eb_reg_access(unit, reg, eb, base_index,
    842                                        index, &data, TRUE);
    843 }
    844 
    845 /*
    846  *Function: _soc_tomahawk3_eb_reg_get
    847  *Purpose: Get resgisters in EB block
    848  */
    849 int
    850 soc_tomahawk3_eb_reg_get(int unit, soc_reg_t reg, int eb, int base_index,
    851                         int index, uint64 *data)
    852 {
    853     return _soc_tomahawk3_eb_reg_access(unit, reg, eb, base_index,
    854                                        index, data, FALSE);
    855 }
    856 
    857 /*
    858  *Function: _soc_tomahawk3_itm_mem_check
    859  *Purpose: Check 1. If memory is in ITM block
    860  *               2. If the passed ITM value is in range
    861  *         Override ITM value with access type of the ITM memory
    862  */
    863 STATIC int
    864 _soc_tomahawk3_itm_mem_check(int unit, soc_mem_t mem, int itm, int base_index)
    865 {
    866     int block_info_index, acc_type, base_type;
    867 
    868     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
    869     if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_ITM) {
    870         LOG_CLI((BSL_META_U(unit,
    871                             "%s is not ITM memory\n"), SOC_MEM_NAME(unit, mem)));
    872         return SOC_E_PARAM;
    873     }
    874 
    875     if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */
    876         if (itm == -1 || itm >= NUM_ITM(unit)) {
    877             LOG_CLI((BSL_META_U(unit,
    878                                 "%s bad ITM value %d\n"),
    879                      SOC_MEM_NAME(unit, mem), itm));
    880             return SOC_E_PARAM;
    881         }
    882     } else {
    883         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
    884         if (acc_type < NUM_ITM(unit)) { /* UNIQUE per ITM memory */
    885             if (itm != acc_type) {
    886                 LOG_CLI((BSL_META_U(unit,
    887                                     "Ovveride ITM value %d with ACC_TYPE of %s\n"),
    888                          itm, SOC_MEM_NAME(unit, mem)));
    889                 itm = acc_type;
    890             }
    891         } else { /* non-UNIQUE memory */
    892             return SOC_E_NONE;
    893         }
    894     }
    895     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
    896 
    897     return soc_tomahawk3_itm_base_index_check(unit, base_type, itm, base_index,
    898                                              SOC_MEM_NAME(unit, mem));
    899 }
    900 
    901 /*Function to retrieve the ITM memory list corresponding to specific ITM or base_type
    902  *
    903  * Base Type:0/1: IPORT/EPORT: No MMU memories available with this base type
    904  * Base Type:2: IPIPE: returns _PIPEx memory list
    905  * Base Type:3: EPIPE: returns _ITMx_PIPEy if acc_type is UNIQUE
    906  *                     returns _PIPEx memories for non-unique memories
    907  * Base Type:4: CHIP:  returns _ITMx mem list if acc_type = UNIQUE
    908  * Base Type:5: ITM:   returns _ITMx mem list if acc_type = UNIQUE
    909  */
    910 STATIC int
    911 _soc_tomahawk3_retrieve_itm_mem_list(int unit, soc_mem_t mem, int itm,
    912         int base_index, soc_mem_t *mem_list, int max_mem_cnt, int *number_of_mems)
    913 {
    914 #define _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 31
    915     soc_info_t *si;
    916     int base_type, acc_type;
    917     uint32 base_index_map, itm_map=0;
    918     int mem_index = 0;
    919     int loop_index;
    920 
    921     si = &SOC_INFO(unit);
    922     /*retrieve bits [25:23] of memory address for base_type*/
    923     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
    924 
    925     switch (base_type) {
    926         case 2: /* IPIPE */
    927         case 3: /* EPIPE */
    928             if (max_mem_cnt < (NUM_ITM(unit) * _TH3_PIPES_PER_DEV)) {
    929                 /*Max combinations is 2 ITMs * 8 PIPEs */
    930                 return SOC_E_INTERNAL;
    931             }
    932             /* Memory doesnt have enumeration */
    933             if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
    934                 mem_list[mem_index++] = mem;
    935                 break;
    936             }
    937             soc_tomahawk3_pipe_map_get(unit, &base_index_map);
    938             if (base_index != -1) {
    939                 base_index_map &= (1 << base_index);
    940                 if (base_index_map == 0) {
    941                     return SOC_E_PARAM;
    942                 }
    943             }
    944             for (loop_index = 0; loop_index < _TH3_PIPES_PER_DEV; loop_index++) {
    945                 if (!(base_index_map & (1 << loop_index))) {
    946                     continue;
    947                 }
    948                 acc_type = SOC_MEM_ACC_TYPE
    949                             (unit, SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, 0));
    950                 if ((acc_type != _TH3_MMU_SBUS_ACC_TYPE_UNIQUE)|| base_type ==2) {
    951                     /* Single/Duplicate acc_type memories only have _PIPEx*/
    952                     mem_list[mem_index++] =
    953                         SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, loop_index);
    954                 } else {
    955                     /*Unique acc_type memories with _ITMx_PIPEy*/
    956                     itm_map = si->itm_map;
    957                     if (itm != -1) {
    958                         itm_map &= (1 << itm);
    959                         if (itm_map == 0) {
    960                             return SOC_E_PARAM;
    961                         }
    962                     }
    963                     for (itm = 0; itm < NUM_ITM(unit); itm++) {
    964                         if (!(itm_map & (1 << itm))) {
    965                             continue;
    966                         }
    967                         mem_list[mem_index++] =
    968                             SOC_MEM_UNIQUE_ACC_ITM_PIPE
    969                                             (unit, mem, itm, loop_index);
    970                                         LOG_ERROR(BSL_LS_SOC_COMMON,
    971                           (BSL_META_U(unit,
    972                                       "mmu_mem %d added to list \n"),
    973                            SOC_MEM_UNIQUE_ACC_ITM_PIPE
    974                                             (unit, mem, itm, loop_index)));
    975                     }
    976                 }
    977             }
    978             break;
    979         case 4: /* CHIP */
    980         case 5: /* ITM */
    981            if (max_mem_cnt < NUM_ITM(unit)) {
    982                 /*Max combinations is 2 ITMs */
    983                 return SOC_E_INTERNAL;
    984             }
    985 
    986             /* No memory enumeration available. Non-unique memories */
    987             if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
    988                 mem_list[mem_index++] = mem;
    989                 break;
    990             }
    991             itm_map = si->itm_map;
    992             if (itm != -1) {
    993                 itm_map &= (1 << itm);
    994                 if (itm_map == 0) {
    995                     return SOC_E_PARAM;
    996                 }
    997             }
    998             if (base_index != -1) {
    999                 itm_map &= (1 << base_index);
   1000                 if (itm_map == 0) {
   1001                     return SOC_E_PARAM;
   1002                 }
   1003             }
   1004 
   1005             /* Unique memories with _ITMx */
   1006             for (loop_index = 0; loop_index < NUM_ITM(unit); loop_index++) {
   1007                 if (!(itm_map & (1 << loop_index))) {
   1008                     continue;
   1009                 }
   1010                 mem_list[mem_index++] =
   1011                     SOC_MEM_UNIQUE_ACC_ITM(unit, mem, loop_index);
   1012             }
   1013             break;
   1014         case 0: /* IPORT */
   1015         case 1: /* EPORT */
   1016         default:
   1017             return SOC_E_INTERNAL;
   1018     }
   1019     *number_of_mems = mem_index;
   1020 
   1021 #undef _TH3_MMU_SBUS_ACC_TYPE_UNIQUE
   1022     return SOC_E_NONE;
   1023 }
   1024 
   1025 /*Function to read/write all ITM memories based on memory list retrieval*/
   1026 STATIC int
   1027 _soc_tomahawk3_itm_mem_access(int unit, soc_mem_t mem, int itm, int base_index,
   1028                              int copyno, int offset_in_section,
   1029                              void *entry_data, int write)
   1030 {
   1031 #define _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 31
   1032     int mem_index, mem_cnt;
   1033     int index;
   1034     soc_mem_t mem_list[64] = {INVALIDm};
   1035 
   1036     if (itm >= 0 && base_index >= 0) {
   1037         SOC_IF_ERROR_RETURN
   1038             (_soc_tomahawk3_itm_mem_check(unit, mem, itm, base_index));
   1039     }
   1040     SOC_IF_ERROR_RETURN
   1041         (_soc_tomahawk3_retrieve_itm_mem_list (unit, mem, itm, base_index,
   1042                                             mem_list, 64, &mem_cnt));
   1043     index = offset_in_section;
   1044     if(write) {
   1045         /*Write to all memories in list*/
   1046         for (mem_index = 0; mem_index < mem_cnt; mem_index ++) {
   1047             SOC_IF_ERROR_RETURN(soc_mem_write
   1048                 (unit, mem_list[mem_index], copyno, index, entry_data));
   1049         }
   1050     } else {
   1051         /*Read only from the 1st memory in list*/
   1052         SOC_IF_ERROR_RETURN(soc_mem_read
   1053                 (unit, mem_list[0], copyno, index, entry_data));
   1054     }
   1055 #undef _TH3_MMU_SBUS_ACC_TYPE_UNIQUE
   1056     return SOC_E_NONE;
   1057 }
   1058 
   1059 /*Function to read/write all ITM memories based on memory list retrieval*/
   1060 STATIC int
   1061 _soc_tomahawk3_itm_mem_access_range(int unit, soc_mem_t mem, int itm, int base_index,
   1062                              int copyno, int idx_min, int idx_max,
   1063                              void *entry_data, int write)
   1064 {
   1065 #define _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 31
   1066     int mem_cnt;
   1067     soc_mem_t mem_list[64] = {INVALIDm};
   1068 
   1069     if (itm >= 0 && base_index >= 0) {
   1070         SOC_IF_ERROR_RETURN
   1071             (_soc_tomahawk3_itm_mem_check(unit, mem, itm, base_index));
   1072     }
   1073     SOC_IF_ERROR_RETURN
   1074         (_soc_tomahawk3_retrieve_itm_mem_list (unit, mem, itm, base_index,
   1075                                             mem_list, 64, &mem_cnt));
   1076     if(write) {
   1077         /* Write goes here, but since this was made for WB, not supported */
   1078     } else {
   1079         /*Read only from the 1st memory in list, but read it all*/
   1080         SOC_IF_ERROR_RETURN(soc_mem_read_range
   1081                 (unit, mem_list[0], MEM_BLOCK_ANY,
   1082                  idx_min, idx_max, entry_data));
   1083     }
   1084 #undef _TH3_MMU_SBUS_ACC_TYPE_UNIQUE
   1085     return SOC_E_NONE;
   1086 }
   1087 /*
   1088  * Function: soc_tomahawk3_itm_mem_write
   1089  * Purpose: Write to memories of different acc_type/base_type in the ITM block
   1090  */
   1091 int
   1092 soc_tomahawk3_itm_mem_write(int unit, soc_mem_t mem, int itm, int base_index,
   1093                            int copyno, int offset_in_section, void *entry_data)
   1094 {
   1095     return _soc_tomahawk3_itm_mem_access(unit, mem, itm, base_index, copyno,
   1096                                         offset_in_section, entry_data, TRUE);
   1097 }
   1098 
   1099 /*
   1100  * Function: soc_tomahawk3_itm_mem_read
   1101  * Purpose: Read memories of different acc_type/base_type in the ITM block
   1102  */
   1103 int
   1104 soc_tomahawk3_itm_mem_read(int unit, soc_mem_t mem, int itm, int base_index,
   1105                           int copyno, int offset_in_section, void *entry_data)
   1106 {
   1107     return _soc_tomahawk3_itm_mem_access(unit, mem, itm, base_index, copyno,
   1108                                         offset_in_section, entry_data, FALSE);
   1109 }
   1110 
   1111 int
   1112 soc_tomahawk3_itm_mem_read_range(int unit, soc_mem_t mem, int itm, int base_index,
   1113                           int copyno, int idx_min, int idx_max, void *entry_data)
   1114 {
   1115     return _soc_tomahawk3_itm_mem_access_range(unit, mem, itm, base_index, copyno,
   1116                                         idx_min, idx_max, entry_data, FALSE);
   1117 }
   1118 STATIC int
   1119 _soc_tomahawk3_eb_mem_check(int unit, soc_mem_t mem, int eb, int base_index)
   1120 {
   1121     int block_info_index, acc_type, base_type;
   1122 
   1123     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   1124     if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_EB) {
   1125         LOG_CLI((BSL_META_U(unit,
   1126                             "%s is not EB memory\n"), SOC_MEM_NAME(unit, mem)));
   1127         return SOC_E_PARAM;
   1128     }
   1129 
   1130     if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */
   1131         if (eb == -1 || eb >= _TH3_PIPES_PER_DEV) {
   1132             LOG_CLI((BSL_META_U(unit,
   1133                                 "%s bad PIPE value %d\n"),
   1134                      SOC_MEM_NAME(unit, mem), eb));
   1135             return SOC_E_PARAM;
   1136         }
   1137     } else {
   1138         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
   1139         if (acc_type < _TH3_PIPES_PER_DEV) { /* UNIQUE per EB memory */
   1140             if (eb != acc_type) {
   1141                 LOG_CLI((BSL_META_U(unit,
   1142                                     "Ovveride EB value %d with ACC_TYPE of %s\n"),
   1143                          eb, SOC_MEM_NAME(unit, mem)));
   1144                 eb = acc_type;
   1145             }
   1146         } else { /* non-UNIQUE memory */
   1147             return SOC_E_NONE;
   1148         }
   1149     }
   1150     /*retrieve bits [25:23] of memory address for base_type*/
   1151     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   1152 
   1153     return soc_tomahawk3_eb_base_index_check(unit, base_type, eb, base_index,
   1154                                             SOC_MEM_NAME(unit, mem));
   1155 }
   1156 
   1157 /*Function to retrieve the EB memory list corresponding to specific EB or base_type
   1158  *
   1159  * Base Type:0/1: IPORT/EPORT: No MMU memories available with this base type
   1160  * Base Type:3: EPIPE: returns _PIPEx memory list
   1161  * Base Type:2: IPIPE: returns _EBx_PIPEy if acc_type is UNIQUE
   1162  *                     returns _PIPEx memories for non-unique memories
   1163  * Base Type:4: CHIP:  returns _PIPEx mem list if acc_type = UNIQUE
   1164  * Base Type:5: ITM:   returns _EBx_ITMy mem list if acc_type = UNIQUE
   1165  *                     returns _ITMx mem list for non-unique memories
   1166  */
   1167 STATIC int
   1168 _soc_tomahawk3_retrieve_eb_mem_list (int unit, soc_mem_t mem, int eb,
   1169                            int base_index, soc_mem_t *mem_list, int max_mem_cnt,
   1170                            int *mem_cnt)
   1171 {
   1172     #define _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 31
   1173     soc_info_t *si;
   1174     int mem_index;
   1175     int base_type, acc_type;
   1176     uint32 base_index_map, eb_map=0;
   1177     int loop_index;
   1178 
   1179     si = &SOC_INFO(unit);
   1180     /*retrieve bits [25:23] of memory address for base_type*/
   1181     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   1182     mem_index = 0;
   1183 
   1184     if (eb >= 0 && base_index >= 0) {
   1185         SOC_IF_ERROR_RETURN
   1186             (_soc_tomahawk3_eb_mem_check(unit, mem, eb, base_index));
   1187     }
   1188     switch (base_type) {
   1189     case 2: /* IPIPE */
   1190     case 3: /* EPIPE */
   1191         if (max_mem_cnt < (_TH3_PIPES_PER_DEV * _TH3_PIPES_PER_DEV)) {
   1192             /*Max combinations is 8 EBs * 8 PIPEs*/
   1193             return SOC_E_INTERNAL;
   1194         }
   1195         /* no _PIPEx, no _ITMx */
   1196         if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
   1197             mem_list[mem_index++] = mem;
   1198             break;
   1199         }
   1200         soc_tomahawk3_pipe_map_get(unit, &base_index_map);
   1201         eb_map = base_index_map;
   1202         if (base_index != -1) {
   1203             base_index_map &= (1 << base_index);
   1204             if (base_index_map == 0) {
   1205                 return SOC_E_PARAM;
   1206             }
   1207         }
   1208         for (loop_index = 0; loop_index < _TH3_PIPES_PER_DEV; loop_index++) {
   1209             if (!(base_index_map & (1 << loop_index))) {
   1210                 continue;
   1211             }
   1212             acc_type = SOC_MEM_ACC_TYPE
   1213                         (unit, SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, 0));
   1214             if ((acc_type != _TH3_MMU_SBUS_ACC_TYPE_UNIQUE)|| (base_type ==3)) {
   1215                 /* Single/Duplicate acc_type memories only have _PIPEx*/
   1216                 /*Base_type EPIPE memories in block EB have same behavior as Single*/
   1217                 mem_list[mem_index++] =
   1218                     SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, loop_index);
   1219             } else {
   1220                 /*Unique acc_type memories with _EBx_PIPEy*/
   1221                 for (eb = 0; eb < _TH3_PIPES_PER_DEV; eb++) {
   1222                     if (!(eb_map & (1 << eb))) {
   1223                         continue;
   1224                     }
   1225                     mem_list[mem_index++] =
   1226                         SOC_MEM_UNIQUE_ACC_EB_PIPE
   1227                                         (unit, mem, eb, loop_index);
   1228                 }
   1229             }
   1230         }
   1231         break;
   1232     case 4: /* CHIP */
   1233         if (max_mem_cnt < _TH3_PIPES_PER_DEV * _TH3_PIPES_PER_DEV) {
   1234             /*Max combinations is 8 EBs*/
   1235             return SOC_E_INTERNAL;
   1236         }
   1237          if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
   1238             mem_list[mem_index++] = mem;
   1239             break;
   1240         }
   1241         soc_tomahawk3_pipe_map_get(unit, &eb_map);
   1242         if (eb != -1) {
   1243             eb_map &= (1 << eb);
   1244             if (eb_map == 0) {
   1245                 return SOC_E_PARAM;
   1246             }
   1247         }
   1248         /*Unique memories across different EBs are enumerated with _PIPEx */
   1249         for (eb = 0; eb < _TH3_PIPES_PER_DEV; eb++) {
   1250             if (!(eb_map & (1 << eb))) {
   1251                 continue;
   1252             }
   1253             mem_list[mem_index++] =
   1254                 SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, eb);
   1255         }
   1256         break;
   1257     case 5: /* ITM */
   1258         if (max_mem_cnt < NUM_ITM(unit) * _TH3_PIPES_PER_DEV) {
   1259             /*Max combinations is 8 EBs * 2 ITMs */
   1260             return SOC_E_INTERNAL;
   1261         }
   1262         /* no _ITMx, _PIPEx */
   1263         if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
   1264             mem_list[mem_index++] = mem;
   1265             break;
   1266         }
   1267         soc_tomahawk3_pipe_map_get(unit, &eb_map);
   1268         if (eb != -1) {
   1269             eb_map &= (1 << eb);
   1270             if (eb_map == 0) {
   1271                 return SOC_E_PARAM;
   1272             }
   1273         }
   1274         base_index_map = si->itm_map;
   1275         if (base_index != -1) {
   1276             base_index_map &= (1 << base_index);
   1277             if (base_index_map== 0) {
   1278                 return SOC_E_PARAM;
   1279             }
   1280         }
   1281         for (loop_index = 0; loop_index < NUM_ITM(unit); loop_index++) {
   1282             if (!(base_index_map & (1 << loop_index))) {
   1283                 continue;
   1284             }
   1285             acc_type = SOC_MEM_ACC_TYPE
   1286                         (unit, SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, 0));
   1287             if ((acc_type != _TH3_MMU_SBUS_ACC_TYPE_UNIQUE)) {
   1288                 /* Single/Duplicate acc_type memories only have _ITMx*/
   1289                 mem_list[mem_index++] =
   1290                     SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, loop_index);
   1291             } else {
   1292                 /*Unique acc_type memories with _EBx_ITMy*/
   1293                 for (eb = 0; eb < _TH3_PIPES_PER_DEV; eb++) {
   1294                     if (!(eb_map & (1 << eb))) {
   1295                         continue;
   1296                     }
   1297                     mem_list[mem_index++] =
   1298                         SOC_MEM_UNIQUE_ACC_EB_ITM
   1299                                         (unit, mem,eb, loop_index);
   1300                 }
   1301             }
   1302         }
   1303         break;
   1304     case 0: /* IPORT */
   1305     case 1: /* EPORT */
   1306     default:
   1307         /*No MMU memories supported with base_tyep IPORT/EPORT*/
   1308         return SOC_E_INTERNAL;
   1309     }
   1310     *mem_cnt = mem_index;
   1311 
   1312 #undef _TH3_MMU_SBUS_ACC_TYPE_UNIQUE
   1313     return SOC_E_NONE;
   1314 }
   1315 
   1316 /*Function : _soc_tomahawk3_eb_mem_access
   1317  *Purpose: read/write memories in EB
   1318  */
   1319 STATIC int
   1320 _soc_tomahawk3_eb_mem_access(int unit, soc_mem_t mem, int eb, int base_index,
   1321                              int copyno, int offset_in_section,
   1322                              void *entry_data, int write)
   1323 {
   1324     int mem_index, mem_cnt;
   1325     int index;
   1326     soc_mem_t mem_list[64] = {INVALIDm};
   1327 
   1328     if (eb >= 0 && base_index >= 0) {
   1329         SOC_IF_ERROR_RETURN
   1330             (_soc_tomahawk3_eb_mem_check(unit, mem, eb, base_index));
   1331     }
   1332     _soc_tomahawk3_retrieve_eb_mem_list (unit, mem, eb, base_index,
   1333                                             mem_list, 64, &mem_cnt);
   1334     index = offset_in_section;
   1335     if(write) {
   1336         /*Write to all memories in list*/
   1337         for (mem_index = 0; mem_index < mem_cnt; mem_index ++) {
   1338             SOC_IF_ERROR_RETURN(soc_mem_write
   1339                 (unit, mem_list[mem_index], copyno, index, entry_data));
   1340         }
   1341     } else {
   1342         /*Read only from the 1st memory in list*/
   1343         SOC_IF_ERROR_RETURN(soc_mem_read
   1344                 (unit, mem_list[0], copyno, index, entry_data));
   1345     }
   1346     return SOC_E_NONE;
   1347 }
   1348 
   1349 /*Function : _soc_tomahawk3_eb_mem_write
   1350  *Purpose: write memories in EB
   1351  */
   1352 int
   1353 soc_tomahawk3_eb_mem_write(int unit, soc_mem_t mem, int eb, int base_index,
   1354                           int copyno, int offset_in_section, void *entry_data)
   1355 {
   1356     return _soc_tomahawk3_eb_mem_access(unit, mem, eb, base_index, copyno,
   1357                                        offset_in_section, entry_data, TRUE);
   1358 }
   1359 
   1360 /*Function : _soc_tomahawk3_eb_mem_read
   1361  *Purpose: read memories in EB
   1362  */
   1363 int
   1364 soc_tomahawk3_eb_mem_read(int unit, soc_mem_t mem, int eb, int base_index,
   1365                          int copyno, int offset_in_section, void *entry_data)
   1366 {
   1367     return _soc_tomahawk3_eb_mem_access(unit, mem, eb, base_index, copyno,
   1368                                        offset_in_section, entry_data, FALSE);
   1369 }
   1370 
   1371 /*
   1372  *Function: soc_retrieve_mem_list_for_port
   1373  *Purpose: Function to retrieve the memory expansion base on logical port # and
   1374  *base memory name
   1375  *         Users of this function do not need the knowledge of memory's
   1376  *         base_type, access_type or block
   1377  * Fnction only returns the memory list and the address need to be calculated by
   1378  * the user
   1379  */
   1380 int
   1381 soc_th3_retrieve_mmu_mem_list_for_port(int unit, int port, soc_mem_t mem, int blk_num,
   1382                                 soc_mem_t *mem_list, int max_mem_cnt, int *mem_cnt)
   1383 {
   1384     int block_info_index, base_type;
   1385     int pipe, base_index;
   1386     soc_info_t *si = &SOC_INFO(unit);
   1387 
   1388     pipe = si->port_pipe[port];
   1389     /*retrieve bits [25:23] of memory address for base_type*/
   1390     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   1391 
   1392     switch(base_type) {
   1393         case 2: /*IPIPE*/
   1394         case 3: /*EPIPE*/
   1395             base_index = pipe;
   1396             break;
   1397         case 4: /*CHIP*/
   1398             base_index = 0;
   1399             break;
   1400         case 5: /*ITM*/
   1401             /*ITM 0 if port is in pipes 0,1,6,7 else ITM1*/
   1402             base_index = blk_num;
   1403             break;
   1404         default:
   1405             base_index = -1;
   1406             break;
   1407     }
   1408 
   1409     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   1410 
   1411     if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_ITM) {
   1412         _soc_tomahawk3_retrieve_itm_mem_list (unit, mem, blk_num, base_index,
   1413                                             mem_list, max_mem_cnt, mem_cnt);
   1414     } else if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_EB) {
   1415         _soc_tomahawk3_retrieve_eb_mem_list (unit, mem, blk_num, base_index,
   1416                                             mem_list, max_mem_cnt, mem_cnt);
   1417     } else {
   1418         LOG_CLI((BSL_META_U(unit,
   1419                             "%s is not ITM or EB memory\n"), SOC_MEM_NAME(unit, mem)));
   1420         return SOC_E_PARAM;
   1421     }
   1422     return SOC_E_NONE;
   1423 }
   1424 
   1425 /*
   1426  * CPU port (mmu port 32): 48 MC queues
   1427  * Loopback port (mmu port 33,97,161,225): 10 MC queues
   1428  * Mgmt port (mmu port 96,160): 10 UC, 10 MC queues
   1429  */
   1430 int
   1431 soc_tomahawk3_num_cosq_init(int unit, int port)
   1432 {
   1433     soc_info_t *si;
   1434     int  local_mmu_port, num_uc_q, pipe, pipe_index;
   1435     int pipe_queue_base[_TH3_PIPES_PER_DEV];
   1436     int mc_q_mode = 2; /* mc_q_mode defines the number of UC/MC queues
   1437                       * for all ports except CPU
   1438                       */
   1439     /*Number of queues per pipe is
   1440      *pipe 0: 18 FP, 1 LB, 1 CPU: 18*12 + 12 + 48 = 296
   1441      *pipe 1,5: 18FP, 1 LB, 1 MGMT: 18*12 + 12 + 12 = 240
   1442      *pipe 2,3,4: 18 FP, 1 LB: 18*12 + 12 = 228
   1443      *pipe 6,7: 18 FP, 1 LB, 1 Extra port: 18*12 + 12 + 12 = 240
   1444      */
   1445     int num_queues_pipe[] = {276, 240, 228, 228, 228, 240, 240, 240};
   1446     si = &SOC_INFO(unit);
   1447 
   1448     mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, _TH3_MC_Q_MODE_DEFAULT);
   1449 
   1450     if (mc_q_mode == 1) {
   1451         num_uc_q = 10;
   1452     } else if (mc_q_mode == 2) {
   1453         num_uc_q = 8;
   1454     } else if (mc_q_mode == 3) {
   1455         num_uc_q = 6;
   1456     } else {
   1457         num_uc_q = 12;
   1458     }
   1459     pipe_queue_base[0] = 0;
   1460     for (pipe_index = 1; pipe_index < _TH3_PIPES_PER_DEV; pipe_index++) {
   1461         pipe_queue_base[pipe_index] = num_queues_pipe[pipe_index - 1] +
   1462                                         pipe_queue_base[pipe_index - 1];
   1463     }
   1464     local_mmu_port = SOC_TH3_MMU_LOCAL_PORT(unit, port);
   1465     pipe = si->port_pipe[port];
   1466     if (IS_CPU_PORT(unit, port)) {
   1467         si->port_num_cosq[port] = SOC_TH3_NUM_CPU_QUEUES;
   1468         si->port_cosq_base[port] =
   1469             (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + pipe_queue_base[pipe];
   1470         LOG_INFO(BSL_LS_SOC_COMMON,
   1471                  (BSL_META_U(unit,
   1472                              "CPU info mmu_port:%d, port_cosq_base:%d\n"),
   1473                   local_mmu_port, si->port_cosq_base[port]));
   1474     } else {
   1475         si->port_num_cosq[port] = SOC_TH3_NUM_GP_QUEUES - num_uc_q;
   1476         si->port_cosq_base[port] =
   1477             (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + num_uc_q
   1478                                                 + pipe_queue_base[pipe];
   1479         si->port_num_uc_cosq[port] = num_uc_q;
   1480         si->port_uc_cosq_base[port] =
   1481                      (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) +
   1482                                         pipe_queue_base[pipe];
   1483         si->port_num_ext_cosq[port] = 0;
   1484     }
   1485     return SOC_E_NONE;
   1486 }
   1487 
   1488 static int
   1489 soc_th3_check_mmu_mem_init_done(int unit) {
   1490     struct {
   1491         soc_reg_t ref_reg;
   1492         soc_field_t done_field;
   1493     } itm_rf_list[] = {
   1494         {MMU_TOQ_STATUSr, INIT_DONEf},
   1495         {MMU_WRED_MEM_INIT_STATUSr, DONEf},
   1496         {INVALIDr, INVALIDf}
   1497     };
   1498     struct {
   1499         soc_reg_t ref_reg;
   1500         soc_field_t done_field;
   1501     } pipe_rf_list[] = {
   1502         {MMU_EBCFP_INIT_DONEr, DONEf},
   1503         {EBTOQ_STATUSr, INIT_DONEf},
   1504         {INVALIDr, INVALIDf}
   1505     };
   1506     uint32 rval;
   1507     int idx, done, itm, pipe;
   1508     soc_reg_t reg;
   1509     soc_field_t field;
   1510     soc_info_t *si = &SOC_INFO(unit);
   1511     uint32 itm_map = si->itm_map;
   1512     uint32 pipe_map;
   1513 
   1514     for (idx = 0; itm_rf_list[idx].ref_reg != INVALIDr; idx++) {
   1515         reg = itm_rf_list[idx].ref_reg;
   1516         field = itm_rf_list[idx].done_field;
   1517         for (itm = 0; itm < NUM_ITM(unit); itm++) {
   1518             if (itm_map & (1 << itm)) {
   1519                 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 0, itm, &rval));
   1520                 done = soc_reg_field_get(unit, reg, rval, field);
   1521                 if (!done) {
   1522                     LOG_INFO(BSL_LS_SOC_COSQ,
   1523                         (BSL_META_U(unit,
   1524                             " MMU Memory Init done not set after toggling"
   1525                             "INIT_MEM \n")));
   1526                     return SOC_E_INTERNAL;
   1527                 }
   1528             }
   1529         }
   1530     }
   1531 
   1532     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   1533     for (idx = 0; pipe_rf_list[idx].ref_reg != INVALIDr; idx++) {
   1534         reg = pipe_rf_list[idx].ref_reg;
   1535         field = pipe_rf_list[idx].done_field;
   1536         for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) {
   1537             if (pipe_map & (1 << pipe)) {
   1538                 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 0, pipe, &rval));
   1539                 done = soc_reg_field_get(unit, reg, rval, field);
   1540                 if (!done) {
   1541                     LOG_ERROR(BSL_LS_SOC_COSQ,
   1542                         (BSL_META_U(unit,
   1543                             " MMU Memory Init done not set after toggling"
   1544                             "INIT_MEM \n")));
   1545                     return SOC_E_INTERNAL;
   1546                 }
   1547             }
   1548         }
   1549     }
   1550     return SOC_E_NONE;
   1551 }
   1552 /*Function to initialize IDB and MMU memories*/
   1553 int
   1554 soc_tomahawk3_init_tm_memory(int unit)
   1555 {
   1556     uint32 rval;
   1557     soc_reg_t reg;
   1558     int parity_en;
   1559     uint32 pipe_map;
   1560     int in_progress =1, init_usec, pipe;
   1561     soc_timeout_t to;
   1562     soc_info_t *si = &SOC_INFO(unit);
   1563     uint32 entry[SOC_MAX_MEM_WORDS];
   1564     soc_mem_t mem;
   1565 
   1566     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   1567 
   1568     /* Initialize IDB memory */
   1569     for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) {
   1570         /* skip pipes that don't exist */
   1571         if (!(pipe_map & (1 << pipe))) {
   1572             continue;
   1573         }
   1574         rval = 0;
   1575         reg = SOC_REG_UNIQUE_ACC(unit,  IDB_HW_RESET_CONTROLr)[pipe];
   1576         soc_reg_field_set(unit, reg, &rval, RESET_ALLf, 1);
   1577         soc_reg_field_set(unit, reg, &rval, VALIDf, 1);
   1578         soc_reg_field_set(unit, reg, &rval, COUNTf, 0x80);
   1579         SOC_IF_ERROR_RETURN
   1580             (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1581     }
   1582 
   1583     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   1584     if (SAL_BOOT_SIMULATION) {
   1585         init_usec = 10000000;
   1586     } else {
   1587         init_usec = 50000;
   1588     }
   1589     if (!SAL_BOOT_SIMULATION) {
   1590         soc_timeout_init(&to, init_usec, 0);
   1591 
   1592         /* Wait for IPIPE memory initialization done */
   1593         in_progress = pipe_map;
   1594         do {
   1595             for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) {
   1596                 rval = 0;
   1597 
   1598                 /* skip pipes that don't exist */
   1599                 if (!(pipe_map & (1 << pipe))) {
   1600                     continue;
   1601                 }
   1602 
   1603                 reg = SOC_REG_UNIQUE_ACC(unit,  IDB_HW_RESET_CONTROLr)[pipe];
   1604                 if (in_progress & (1 << pipe)) { /* not done yet */
   1605                     SOC_IF_ERROR_RETURN
   1606                         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1607                         if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   1608                             in_progress ^= 1 << pipe;
   1609                         }
   1610                 }
   1611             }
   1612             if (soc_timeout_check(&to)) {
   1613                 LOG_WARN(BSL_LS_SOC_COMMON,
   1614                          (BSL_META_U(unit,
   1615                                      "unit %d : IDB_HW_RESET timeout\n"), unit));
   1616                 break;
   1617             }
   1618         } while (in_progress != 0);
   1619     }
   1620     parity_en = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   1621     /*Initialize MMU memory*/
   1622     rval = 0;
   1623     reg = MMU_GLBCFG_MISCCONFIGr;
   1624     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1625     soc_reg_field_set(unit, reg, &rval, ECCP_ENf, 1);
   1626     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1627     sal_usleep(20);
   1628     soc_reg_field_set(unit, reg, &rval, INIT_MEMf, 1);
   1629     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1630     soc_reg_field_set(unit, reg, &rval, INIT_MEMf, 0);
   1631     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1632     sal_usleep(30);
   1633 
   1634     if (!SAL_BOOT_SIMULATION) {
   1635         SOC_IF_ERROR_RETURN(soc_th3_check_mmu_mem_init_done(unit));
   1636     }
   1637     soc_reg_field_set(unit, reg, &rval, ECCP_ENf, parity_en);
   1638     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1639 
   1640 
   1641     for (pipe = 0; pipe < _TH3_PIPES_PER_DEV ; pipe++) {
   1642         if (!SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1643             mem = SOC_MEM_UNIQUE_ACC(unit, MMU_EBCFP_MXM_TAG_MEMm)[pipe];
   1644             soc_mem_field32_set(unit, mem, &entry, DATAf, 0x1);
   1645             SOC_IF_ERROR_RETURN
   1646                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, &entry));
   1647         }
   1648     }
   1649 
   1650     return SOC_E_NONE;
   1651 }
   1652 
   1653 /*Start: Port mapping functions*/
   1654 STATIC int
   1655 _soc_th3_mmu_port_to_phy_port_map (int unit, int dev_port, int phy_port,
   1656         int mmu_port)
   1657 {
   1658     /*
   1659      *MMU_INTFI_MMU_PORT_TO_PHY_PORT_MAPPING
   1660      *MMU_INTFO_MMU_PORT_TO_PHY_PORT_MAPPING
   1661      *MMU_EBPTS_MMU_PORT_TO_PHY_PORT_MAPPING-
   1662      */
   1663     soc_reg_t reg_list[] = {MMU_INTFI_MMU_PORT_TO_PHY_PORT_MAPPINGr,
   1664                             MMU_INTFO_MMU_PORT_TO_PHY_PORT_MAPPINGr,
   1665                             MMU_EBPTS_MMU_PORT_TO_PHY_PORT_MAPPINGr,
   1666                             };
   1667     soc_reg_t reg;
   1668     uint32 rval;
   1669     int reg_index, field_val, num_regs;
   1670     int pipe;
   1671     soc_info_t *si = &SOC_INFO(unit);
   1672     num_regs = sizeof(reg_list) / sizeof(soc_reg_t);
   1673 
   1674     pipe = si->port_pipe[dev_port];
   1675     for (reg_index = 0; reg_index < num_regs; reg_index ++) {
   1676         rval = 0;
   1677         reg = reg_list[reg_index];
   1678         if (SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block,
   1679                     SOC_BLK_MMU_EB)) {
   1680             /* Pipe 0 is special because of CPU port being port 0. Range is 0 - 32 */
   1681             if (pipe  ==  0) {
   1682                 field_val = phy_port % (SOC_TH3_MAX_PHY_PORTS_PER_PIPE + 1);
   1683             } else {
   1684                 field_val = (phy_port - 1) % SOC_TH3_MAX_PHY_PORTS_PER_PIPE;
   1685             }
   1686             if (IS_LB_PORT(unit, dev_port)) {
   1687                 /*Local phy port 33 to be used for all LB ports*/
   1688                 field_val = SOC_TH3_LB_PORT_LOCAL_PHY_NUM;
   1689             }
   1690             if(IS_MANAGEMENT_PORT(unit, dev_port)) {
   1691                 /*Local phy port 32 to be used for all LB ports*/
   1692                 field_val = SOC_TH3_MGMT_PORT_LOCAL_PHY_NUM;
   1693             }
   1694         } else {
   1695             field_val = phy_port;
   1696         }
   1697         soc_reg_field_set(unit, reg, &rval, PHY_PORT_NUMf,
   1698                           field_val);
   1699         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, dev_port, 0, rval));
   1700     }
   1701     return SOC_E_NONE;
   1702 }
   1703 
   1704 STATIC int
   1705 _soc_th3_mmu_port_to_dev_port_map (int unit, int dev_port, int mmu_port)
   1706 {
   1707     /*
   1708      *MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPING - Global dev to Global mmu
   1709      *MMU_EBCFP_MMU_PORT_TO_DEVICE_PORT_MAPPING - Global MMU to global dev
   1710      *MMU_RQE_PORT_TO_DEVICE_PORT_MAPPING-memory, global dev to global mmu
   1711      *MMU_THDO_DEVICE_PORT_MAP -memory, chip port num to dev port
   1712      */
   1713     soc_reg_t reg_list[] = {MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPINGr,
   1714                             MMU_EBCFP_MMU_PORT_TO_DEVICE_PORT_MAPPINGr};
   1715     soc_mem_t mem_list[] = {MMU_RQE_DEVICE_TO_MMU_PORT_MAPPINGm,
   1716                             MMU_THDO_DEVICE_PORT_MAPm};
   1717     soc_field_t reg_field = INVALIDf, mem_field = INVALIDf;
   1718     soc_reg_t reg;
   1719     soc_mem_t mem;
   1720     uint32 entry[SOC_MAX_MEM_WORDS];
   1721     uint32 rval;
   1722     int reg_index, field_val = -1, index = -1, mem_index,  num_regs, num_mems;
   1723     num_regs = sizeof(reg_list) / sizeof(soc_reg_t);
   1724     num_mems = sizeof(mem_list) / sizeof(soc_mem_t);
   1725 
   1726     sal_memset(entry, 0, sizeof(entry));
   1727     for (reg_index = 0; reg_index < num_regs; reg_index++) {
   1728         rval = 0;
   1729         reg = reg_list[reg_index];
   1730         switch(reg) {
   1731             case MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPINGr:
   1732                 reg_field = MMU_PORTf;
   1733                 field_val = mmu_port; /*Global mmu port*/
   1734                 index = dev_port;
   1735                 break;
   1736             case MMU_EBCFP_MMU_PORT_TO_DEVICE_PORT_MAPPINGr:
   1737                 reg_field = DEVICE_PORTf;
   1738                 field_val = dev_port;
   1739                 /*dev port to mmu port conversion done in soc_reg_write*/
   1740                 index = dev_port;
   1741                 break;
   1742             default:
   1743                 break;
   1744         }
   1745         soc_reg_field_set(unit, reg, &rval, reg_field,
   1746                           field_val);
   1747         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, index, 0, rval));
   1748     }
   1749     for (mem_index = 0; mem_index < num_mems; mem_index++) {
   1750         mem = mem_list[mem_index];
   1751         switch(mem) {
   1752             case MMU_RQE_DEVICE_TO_MMU_PORT_MAPPINGm:
   1753                 mem_field = MMU_PORTf;
   1754                 field_val = mmu_port; /*Global mmu port*/
   1755                 index = dev_port;
   1756                 break;
   1757             case MMU_THDO_DEVICE_PORT_MAPm:
   1758                 mem_field = DEVICE_PORTf;
   1759                 field_val = dev_port;
   1760                 index = SOC_TH3_MMU_CHIP_PORT(unit, dev_port);
   1761                 break;
   1762             default:
   1763                 break;
   1764         }
   1765         soc_mem_field32_set(unit, mem, &entry, mem_field , field_val);
   1766         SOC_IF_ERROR_RETURN
   1767             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry));
   1768     }
   1769     return SOC_E_NONE;
   1770 }
   1771 
   1772 int
   1773 soc_tomahawk3_mmu_port_mapping_init (int unit)
   1774 {
   1775     soc_info_t *si;
   1776     int port, phy_port, mmu_port;
   1777     si = &SOC_INFO(unit);
   1778 
   1779 
   1780     PBMP_ALL_ITER(unit, port) {
   1781         phy_port = si->port_l2p_mapping[port];
   1782         mmu_port = si->port_p2m_mapping[phy_port];
   1783         LOG_INFO(BSL_LS_SOC_COSQ,
   1784             (BSL_META_U(unit,
   1785                 " Dev Port:%d MMU_port:%d Phy Port:%d\n"),
   1786 			                port, mmu_port, phy_port));
   1787         _soc_th3_mmu_port_to_phy_port_map(unit, port, phy_port, mmu_port);
   1788         _soc_th3_mmu_port_to_dev_port_map(unit, port, mmu_port);
   1789     }
   1790     return SOC_E_NONE;
   1791 }
   1792 /*End: Port mapping init functions*/
   1793 
   1794 int
   1795 soc_tomahawk3_en_mmu_refresh (int unit)
   1796 {
   1797     int reg_index;
   1798     soc_field_t refresh_field = REFRESH_DISABLEf;
   1799     soc_reg_t reg_list[] = {MMU_MTRO_CONFIGr, MMU_WRED_REFRESH_CONTROLr};
   1800     uint32 rval;
   1801     int num_regs = sizeof(reg_list) / sizeof(soc_reg_t);
   1802 
   1803     for (reg_index = 0; reg_index < num_regs; reg_index++) {
   1804         rval = 0;
   1805         soc_reg_field_set(unit, reg_list[reg_index], &rval, refresh_field, 0);
   1806         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg_list[reg_index],
   1807                     REG_PORT_ANY, 0, rval));
   1808     }
   1809     return SOC_E_NONE;
   1810 }
   1811 
   1812 STATIC int
   1813 soc_tomahawk3_ifp_cos_map_init_rqe_flush_war (int unit)
   1814 {
   1815     
   1816     int mem_index;
   1817     int pri;
   1818     soc_mem_t mem = IFP_COS_MAPm;
   1819     soc_field_t rqe_cos = IFP_RQE_Q_NUMf;
   1820     uint32 entry[SOC_MAX_MEM_WORDS];
   1821 
   1822     for (pri = 0; pri < _TH3_MMU_NUM_RQE_QUEUES; pri++) {
   1823         mem_index = (_TH3_IFP_COS_MAP_RSVD_PROF * _TH3_MMU_NUM_INT_PRI) + pri;
   1824         SOC_IF_ERROR_RETURN
   1825             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, mem_index, &entry));
   1826         soc_mem_field32_set(unit, mem, &entry, rqe_cos, pri);
   1827         SOC_IF_ERROR_RETURN
   1828         (soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_index, &entry));
   1829     }
   1830     return SOC_E_NONE;
   1831 }
   1832 
   1833 /*
   1834  * Function: soc_th3_mmu_rqe_queue_number_init
   1835  * Purpose: Initialize to use separate RQE queue numbers for mirror and CPU
   1836  * packets
   1837  * Param: unit: device number
   1838  */
   1839 int
   1840 soc_th3_mmu_rqe_queue_number_init(int unit)
   1841 {
   1842     uint32 rval = 0;
   1843     soc_reg_t reg;
   1844     uint16 dev_id;
   1845     uint8 rev_id;
   1846 
   1847     soc_cm_get_id(unit, &dev_id, &rev_id);
   1848 
   1849     /*RQE queue number for CPU hi packets*/
   1850     reg = CPU_HI_RQE_Q_NUMr;
   1851     SOC_IF_ERROR_RETURN
   1852         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1853     if (rev_id == BCM56980_A0_REV_ID) {
   1854         soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_A0_CPU_HI_RQE_Q_NUM);
   1855     } else {
   1856         soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_CPU_HI_RQE_Q_NUM);
   1857     }
   1858     SOC_IF_ERROR_RETURN
   1859         (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1860 
   1861     /*RQE queue number for CPU lo packets*/
   1862     reg = CPU_LO_RQE_Q_NUMr;
   1863     rval = 0;
   1864     SOC_IF_ERROR_RETURN
   1865         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1866     if (rev_id == BCM56980_A0_REV_ID) {
   1867         soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_A0_CPU_LO_RQE_Q_NUM);
   1868     } else {
   1869         soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_CPU_LO_RQE_Q_NUM);
   1870     }
   1871     SOC_IF_ERROR_RETURN
   1872         (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1873 
   1874     /*RQE queue number for Mirror packets*/
   1875     reg = MIRROR_RQE_Q_NUMr;
   1876     rval = 0;
   1877     SOC_IF_ERROR_RETURN
   1878         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1879     if (rev_id == BCM56980_A0_REV_ID) {
   1880         soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_A0_MIRR_RQE_Q_NUM);
   1881     } else {
   1882         soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_MIRR_RQE_Q_NUM);
   1883     }
   1884     SOC_IF_ERROR_RETURN
   1885         (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1886 
   1887     reg = MMU_CRB_RQE_QUEUE_CONFIGr;
   1888     rval = 0;
   1889     SOC_IF_ERROR_RETURN
   1890         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1891     if (rev_id == BCM56980_A0_REV_ID) {
   1892         soc_reg_field_set(unit, reg, &rval, CPUHI_RQE_QUEUE_NUMf, _TH3_A0_CPU_HI_RQE_Q_NUM);
   1893         soc_reg_field_set(unit, reg, &rval, CPULO_RQE_QUEUE_NUMf, _TH3_A0_CPU_LO_RQE_Q_NUM);
   1894         soc_reg_field_set(unit, reg, &rval, MIRROR_RQE_QUEUE_NUMf, _TH3_A0_MIRR_RQE_Q_NUM);
   1895     } else {
   1896         soc_reg_field_set(unit, reg, &rval, CPUHI_RQE_QUEUE_NUMf, _TH3_CPU_HI_RQE_Q_NUM);
   1897         soc_reg_field_set(unit, reg, &rval, CPULO_RQE_QUEUE_NUMf, _TH3_CPU_LO_RQE_Q_NUM);
   1898         soc_reg_field_set(unit, reg, &rval, MIRROR_RQE_QUEUE_NUMf, _TH3_MIRR_RQE_Q_NUM);
   1899     }
   1900     SOC_IF_ERROR_RETURN
   1901         (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1902 
   1903     /* Initialize IFP_COS_MAP reserved profile fro RQE flush WAR (SDK-142748)*/
   1904     SOC_IF_ERROR_RETURN(
   1905             soc_tomahawk3_ifp_cos_map_init_rqe_flush_war(unit));
   1906 
   1907     return SOC_E_NONE;
   1908 }
   1909 
   1910 /*
   1911  * Function: soc_tomahawk3_mmu_port_rx_enables
   1912  * Purpose: Enable MMU to receive traffic on different ports as part of init
   1913  * Param: unit: device number
   1914  */
   1915 int
   1916 soc_tomahawk3_mmu_port_rx_enables(int unit) {
   1917     int pipe, dev_port, itm;
   1918     uint32 rval;
   1919     soc_info_t *si = &SOC_INFO(unit);
   1920     uint32 itm_map = si->itm_map;
   1921 
   1922     PBMP_ALL_ITER(unit, dev_port) {
   1923         SOC_IF_ERROR_RETURN
   1924             (soc_reg32_get(unit, MMU_CRB_SRC_PORT_CFGr, dev_port, 0,
   1925                                                                 &rval));
   1926         soc_reg_field_set(unit, MMU_CRB_SRC_PORT_CFGr, &rval,
   1927                                              RX_PORT_ENf, 1);
   1928         SOC_IF_ERROR_RETURN
   1929             (soc_reg32_set(unit, MMU_CRB_SRC_PORT_CFGr, dev_port, 0,
   1930                                                                 rval));
   1931     }
   1932     for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) {
   1933         if (!SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1934             LOG_INFO(BSL_LS_SOC_COSQ,
   1935                 (BSL_META_U(unit, "Programming for Pipe:%d\n"), pipe));
   1936             rval = 0;
   1937             SOC_IF_ERROR_RETURN
   1938                 (soc_reg32_get(unit, MMU_THDO_CONFIG_PORTr, REG_PORT_ANY, pipe,
   1939                                &rval));
   1940             /*Enable for all MMU ports in a pipe*/
   1941             soc_reg_field_set(unit, MMU_THDO_CONFIG_PORTr, &rval,
   1942                                            OUTPUT_PORT_RX_ENABLEf, 0xfffff);
   1943             SOC_IF_ERROR_RETURN
   1944                 (soc_reg32_set(unit, MMU_THDO_CONFIG_PORTr, REG_PORT_ANY, pipe,
   1945                                rval));
   1946         }
   1947     }
   1948     for(itm = 0; itm < NUM_ITM(unit); itm++) {
   1949         if (itm_map & (1 << itm)) {
   1950             rval = 0;
   1951             SOC_IF_ERROR_RETURN
   1952                 (soc_reg32_get(unit, MMU_THDO_ENGINE_ENABLES_CFGr, itm,
   1953                                REG_PORT_ANY, &rval));
   1954             /*Enable for all MMU ports in a pipe*/
   1955             soc_reg_field_set(unit, MMU_THDO_ENGINE_ENABLES_CFGr, &rval,
   1956                                            SRC_PORT_DROP_COUNT_ENABLEf, 1);
   1957             SOC_IF_ERROR_RETURN
   1958                 (soc_reg32_set(unit, MMU_THDO_ENGINE_ENABLES_CFGr, itm,
   1959                                REG_PORT_ANY, rval));
   1960 
   1961         }
   1962     }
   1963     /*Disable THDO counter overflow interrupt (SDK-133360)*/
   1964     rval = 0;
   1965     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, MMU_THDO_CPU_INT_SETr,
   1966                                         REG_PORT_ANY, 0, &rval));
   1967     soc_reg_field_set(unit, MMU_THDO_CPU_INT_SETr, &rval, COUNTER_OVERFLOWf, 0);
   1968     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_THDO_CPU_INT_SETr,
   1969                                    REG_PORT_ANY, 0, rval));
   1970     return SOC_E_NONE;
   1971 }
   1972 
   1973 /*
   1974  * Function: soc_tomahawk3_cell_pointer_init
   1975  * Purpose: Initialize cell pointer memory in MMU during init
   1976  * Param: unit: device number
   1977  */
   1978 int
   1979 soc_tomahawk3_cell_pointer_init(int unit)
   1980 {
   1981     uint64 rval, cfap_bank;
   1982     uint32 rval32;
   1983     int itm;
   1984     soc_info_t *si = &SOC_INFO(unit);
   1985     uint32 itm_map = si->itm_map;
   1986     COMPILER_64_ZERO(rval);
   1987     /*Enable all 34 CFAP banks in each ITM*/
   1988     COMPILER_64_SET(cfap_bank, 0x3, 0xffffffff);
   1989     for (itm = 0; itm < NUM_ITM(unit); itm++) {
   1990         if (itm_map & (1 << itm)) {
   1991             LOG_INFO(BSL_LS_SOC_COSQ,
   1992                 (BSL_META_U(unit, "Programming for ITM:%d\n"), itm));
   1993             SOC_IF_ERROR_RETURN
   1994                 (soc_tomahawk3_itm_reg_get(unit, MMU_CFAP_INIT_64r,
   1995                                            itm, itm, 0, &rval));
   1996             COMPILER_64_OR(rval, cfap_bank);
   1997             SOC_IF_ERROR_RETURN
   1998                 (soc_tomahawk3_itm_reg_set(unit, MMU_CFAP_INIT_64r,
   1999                                            itm, itm, 0, rval));
   2000         }
   2001     }
   2002 
   2003     /* SDK-142571 MMU_CFAP_ARBITER_MASK should be 2 */
   2004     rval32 = 0;
   2005     SOC_IF_ERROR_RETURN
   2006         (soc_tomahawk3_itm_reg32_get(unit, MMU_CFAP_ARBITER_MASKr,
   2007                                    -1, -1, 0, &rval32));
   2008     soc_reg_field_set(unit, MMU_CFAP_ARBITER_MASKr, &rval32,
   2009             MASKf, 2);
   2010     SOC_IF_ERROR_RETURN
   2011         (soc_tomahawk3_itm_reg32_set(unit, MMU_CFAP_ARBITER_MASKr,
   2012                                    -1, -1, 0, rval32));
   2013 
   2014     return SOC_E_NONE;
   2015 }
   2016 
   2017 /*
   2018  *Function: soc_tomahawk3_cosq_profile_info_init
   2019  *Purpose: init data struct for scheduler hierachy for a particular profile
   2020  */
   2021 int
   2022 soc_tomahawk3_cosq_profile_info_init(int unit, int profile_idx)
   2023 {
   2024     int queue_num;
   2025 
   2026     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2027         th3_sched_profile_info[unit][profile_idx][queue_num].cos = -1;
   2028         th3_sched_profile_info[unit][profile_idx][queue_num].mmuq[0] = -1;
   2029         th3_sched_profile_info[unit][profile_idx][queue_num].mmuq[1] = -1;
   2030         th3_sched_profile_info[unit][profile_idx][queue_num].strict_priority = 0;
   2031         th3_sched_profile_info[unit][profile_idx][queue_num].fc_is_uc_only = 0;
   2032     }
   2033     return SOC_E_NONE;
   2034 
   2035 }
   2036 
   2037 /*
   2038  *Function: soc_cosq_profile_struct_init
   2039  *Purpose: init data struct for scheduler hierachy
   2040  */
   2041 int
   2042 soc_cosq_profile_struct_init(int unit, int profile)
   2043 {
   2044     int queue_num;
   2045 
   2046     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2047         L1_TO_L0_MAPPING[unit][profile][queue_num] = -1;
   2048         L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] = 0;
   2049         L0_TO_COSQ_MAPPING[unit][profile][queue_num] = -1;
   2050     }
   2051     return SOC_E_NONE;
   2052 }
   2053 
   2054 /*
   2055  *Function: soc_tomahawk3_cosq_port_info_init
   2056  *Purpose: init data struct for scheduler hierachy for a particular port
   2057  */
   2058 int
   2059 soc_tomahawk3_cosq_port_info_init(int unit, int port_num)
   2060 {
   2061     int queue_num;
   2062 
   2063     if (th3_cosq_mmu_info[unit] == NULL) {
   2064         return SOC_E_MEMORY;
   2065     }
   2066 
   2067     /*general port initialization*/
   2068     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2069         /*level 0*/
   2070         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2071             L0[queue_num].level = 0;
   2072         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2073             L0[queue_num].in_use = 0;
   2074         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2075             L0[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR;
   2076         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2077             L0[queue_num].weight = 0;
   2078         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2079             L0[queue_num].fc_is_uc_only = 0;
   2080         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2081             L0[queue_num].hw_index = queue_num;
   2082         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2083             L0[queue_num].cos = -1;
   2084         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2085             L0[queue_num].parent = NULL;
   2086         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2087             L0[queue_num].children[0] = NULL;
   2088         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2089             L0[queue_num].children[1] = NULL;
   2090     }
   2091     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2092         /*level 1*/
   2093         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2094             L1[queue_num].level = 1;
   2095         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2096             L1[queue_num].in_use = 0;
   2097         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2098             L1[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR;
   2099         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2100             L1[queue_num].weight = 0;
   2101         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2102             L1[queue_num].fc_is_uc_only = 0;
   2103         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2104             L1[queue_num].hw_index = queue_num;
   2105         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2106             L1[queue_num].cos = -1;
   2107         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2108             L1[queue_num].parent = NULL;
   2109         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2110             L1[queue_num].children[0] = NULL;
   2111         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2112             L1[queue_num].children[1] = NULL;
   2113     }
   2114     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2115         /*level 2*/
   2116         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2117             mmuq[queue_num].level = 2;
   2118         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2119             mmuq[queue_num].in_use = 1;
   2120         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2121             mmuq[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR;
   2122         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2123             mmuq[queue_num].weight = 0;
   2124         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2125             mmuq[queue_num].fc_is_uc_only = 0;
   2126         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2127             mmuq[queue_num].hw_index = queue_num;
   2128         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2129             mmuq[queue_num].cos = -1;
   2130         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2131             mmuq[queue_num].parent = NULL;
   2132         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2133             mmuq[queue_num].children[0] = NULL;
   2134         th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2135             mmuq[queue_num].children[1] = NULL;
   2136     }
   2137     return SOC_E_NONE;
   2138 }
   2139 
   2140 void soc_gport_tree_print(int unit, int port)
   2141 {
   2142     int cosq_idx;
   2143 
   2144     /* Print */
   2145     for (cosq_idx = 0; cosq_idx <  SOC_TH3_COS_MAX; cosq_idx++) {
   2146         LOG_INFO(BSL_LS_SOC_COSQ,
   2147             (BSL_META_U(unit, "\n L0 [%0d, %0d] in_use=%0d, level=%0d, hw_index=%0d, cos=%0d "),
   2148              port, cosq_idx, th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].in_use,
   2149              th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].level,
   2150              th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].hw_index,
   2151              th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].cos));
   2152         if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].parent != NULL) {
   2153             LOG_INFO(BSL_LS_SOC_COSQ,
   2154                 (BSL_META_U(unit, "parent.hw_index=%0d "),
   2155                  th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].parent->hw_index));
   2156         }
   2157         if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].children[0] != NULL) {
   2158             LOG_INFO(BSL_LS_SOC_COSQ,
   2159                 (BSL_META_U(unit, "children[0].hw_index=%0d "),
   2160                  th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].children[0]->hw_index));
   2161             if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].children[1] != NULL) {
   2162                 LOG_INFO(BSL_LS_SOC_COSQ,
   2163                 (BSL_META_U(unit, "children[1].hw_index=%0d "),
   2164                  th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].children[1]->hw_index));
   2165             }
   2166         }
   2167 
   2168         LOG_INFO(BSL_LS_SOC_COSQ,
   2169             (BSL_META_U(unit, "\n L1 [%0d, %0d] in_use=%0d, level=%0d, hw_index=%0d, cos=%0d "),
   2170              port, cosq_idx, th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].in_use,
   2171              th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].level,
   2172              th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].hw_index,
   2173              th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].cos));
   2174         if (th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].parent != NULL) {
   2175             LOG_INFO(BSL_LS_SOC_COSQ,
   2176                 (BSL_META_U(unit, "parent.hw_index=%0d "),
   2177                  th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].parent->hw_index));
   2178         }
   2179         if (th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].children[0] != NULL) {
   2180             LOG_INFO(BSL_LS_SOC_COSQ,
   2181                 (BSL_META_U(unit, "children[0].hw_index=%0d "),
   2182                  th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].children[0]->hw_index));
   2183             if (th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].children[1] != NULL) {
   2184                 LOG_INFO(BSL_LS_SOC_COSQ,
   2185                 (BSL_META_U(unit, "children[1].hw_index=%0d "),
   2186                  th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].children[1]->hw_index));
   2187             }
   2188         }
   2189 
   2190         LOG_INFO(BSL_LS_SOC_COSQ,
   2191             (BSL_META_U(unit, "\n mmuq [%0d, %0d] in_use=%0d, level=%0d, hw_index=%0d, cos=%0d "),
   2192              port, cosq_idx, th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].in_use,
   2193              th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].level,
   2194              th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].hw_index,
   2195              th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].cos));
   2196         if (th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].parent != NULL) {
   2197             LOG_INFO(BSL_LS_SOC_COSQ,
   2198                 (BSL_META_U(unit, "parent.hw_index=%0d "),
   2199                      th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].parent->hw_index));
   2200         }
   2201         if (th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].children[0] != NULL) {
   2202             LOG_INFO(BSL_LS_SOC_COSQ,
   2203                 (BSL_META_U(unit, "children[0].hw_index=%0d "),
   2204                  th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].children[0]->hw_index));
   2205             if (th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].children[1] != NULL) {
   2206                 LOG_INFO(BSL_LS_SOC_COSQ,
   2207                 (BSL_META_U(unit, "children[1].hw_index=%0d "),
   2208                  th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].children[1]->hw_index));
   2209             }
   2210         }
   2211     }
   2212 }
   2213 
   2214 /*
   2215  *Function: soc_cosq_struct_init
   2216  *Purpose: init data struct for scheduler hierachy
   2217  */
   2218 int
   2219 soc_cosq_struct_init(int unit)
   2220 {
   2221     int port_num, queue_num, profile, i;
   2222     /*L1 to L0 is port based in reg file. Keep the profile based mapping in software*/
   2223     for (profile = 0; profile < SOC_TH3_MAX_NUM_SCHED_PROFILE; profile++) {
   2224         for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2225             L1_TO_L0_MAPPING[unit][profile][queue_num] = -1;
   2226             L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] = 0;
   2227             L0_TO_COSQ_MAPPING[unit][profile][queue_num] = -1;
   2228         }
   2229     }
   2230     if (th3_cosq_mmu_info[unit] == NULL) {
   2231          /*th3_cosq_mmu_info is not freed */
   2232         th3_cosq_mmu_info[unit] =
   2233             sal_alloc(sizeof(soc_th3_mmu_info_t), "soc_th3_mmu_info_t");
   2234         if (th3_cosq_mmu_info[unit] == NULL) {
   2235             return SOC_E_MEMORY;
   2236         }
   2237     }
   2238     /*general port initialization*/
   2239     for (port_num = 0; port_num < SOC_TH3_MAX_NUM_PORTS; port_num++) {
   2240         for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2241             /*level 0*/
   2242             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2243                 L0[queue_num].level = 0;
   2244             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2245                 L0[queue_num].in_use = 0;
   2246             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2247                 L0[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR;
   2248             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2249                 L0[queue_num].weight = 0;
   2250             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2251                 L0[queue_num].fc_is_uc_only = 0;
   2252             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2253                 L0[queue_num].hw_index = queue_num;
   2254             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2255                 L0[queue_num].cos = -1;
   2256             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2257                 L0[queue_num].parent = NULL;
   2258             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2259                 L0[queue_num].children[0] = NULL;
   2260             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2261                 L0[queue_num].children[1] = NULL;
   2262         }
   2263         for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2264             /*level 1*/
   2265             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2266                 L1[queue_num].level = 1;
   2267             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2268                 L1[queue_num].in_use = 0;
   2269             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2270                 L1[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR;
   2271             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2272                 L1[queue_num].weight = 0;
   2273             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2274                 L1[queue_num].fc_is_uc_only = 0;
   2275             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2276                 L1[queue_num].hw_index = queue_num;
   2277             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2278                 L1[queue_num].cos = -1;
   2279             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2280                 L1[queue_num].parent = NULL;
   2281             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2282                 L1[queue_num].children[0] = NULL;
   2283             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2284                 L1[queue_num].children[1] = NULL;
   2285         }
   2286         for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2287             /*level 2*/
   2288             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2289                 mmuq[queue_num].level = 2;
   2290             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2291                 mmuq[queue_num].in_use = 1;
   2292             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2293                 mmuq[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR;
   2294             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2295                 mmuq[queue_num].weight = 0;
   2296             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2297                 mmuq[queue_num].fc_is_uc_only = 0;
   2298             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2299                 mmuq[queue_num].hw_index = queue_num;
   2300             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2301                 mmuq[queue_num].cos = -1;
   2302             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2303                 mmuq[queue_num].parent = NULL;
   2304             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2305                 mmuq[queue_num].children[0] = NULL;
   2306             th3_cosq_mmu_info[unit]->th3_port_info[port_num].
   2307                 mmuq[queue_num].children[1] = NULL;
   2308         }
   2309     }
   2310     /*cpu port initialization*/
   2311     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2312         /*levl 0*/
   2313         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].level = 0;
   2314         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].in_use = 0;
   2315         th3_cosq_mmu_info[unit]->th3_cpu_port_info.
   2316             L0[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR;
   2317         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].weight = 0;
   2318         th3_cosq_mmu_info[unit]->th3_cpu_port_info.
   2319             L0[queue_num].hw_index = queue_num;
   2320         th3_cosq_mmu_info[unit]->th3_cpu_port_info.
   2321             L0[queue_num].cos = queue_num;
   2322         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].parent = NULL;
   2323         for (i = 0; i < SOC_TH3_NUM_CPU_QUEUES; i++) {
   2324             th3_cosq_mmu_info[unit]->th3_cpu_port_info.
   2325                 L0[queue_num].children[i] = NULL;
   2326         }
   2327     }
   2328     for (queue_num = 0; queue_num < SOC_TH3_NUM_CPU_QUEUES; queue_num++) {
   2329         /*level 1*/
   2330         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].level = 1;
   2331         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].in_use = 0;
   2332         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].
   2333             sched_policy = SOC_TH3_SCHED_MODE_WRR;
   2334         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].weight = 0;
   2335         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].
   2336             hw_index = queue_num;
   2337         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].cos = -1;
   2338         th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].parent = NULL;
   2339         for (i = 0; i < SOC_TH3_NUM_CPU_QUEUES; i++) {
   2340             th3_cosq_mmu_info[unit]->th3_cpu_port_info.
   2341                 L1[queue_num].children[i] = NULL;
   2342         }
   2343     }
   2344     return SOC_E_NONE;
   2345 }
   2346 /*
   2347  *Function: soc_tomahawk3_mcq_mode_set
   2348  *Purpose: Program MC_Q_MODE value to configure number of UC and MC queues per
   2349  *          port
   2350  *Params:
   2351  *       unit: Device unit number
   2352  *       mode: mc_q_mode value (rage: 0-3)
   2353  */
   2354 
   2355 int
   2356 soc_tomahawk3_mcq_mode_set(int unit, int mode)
   2357 {
   2358     soc_reg_t reg;
   2359     uint32 rval;
   2360     int i;
   2361     soc_reg_t reg_array[] = {MMU_INTFO_CONFIG0r,
   2362                              MMU_TOQ_CONFIGr,
   2363                              MMU_THDO_CONFIGr,
   2364                              MMU_CRB_CONFIGr,
   2365                              MMU_WRED_CONFIGr};
   2366     if (mode < 0 || mode > 3) {
   2367         return SOC_E_PARAM;
   2368     }
   2369     for (i = 0; i < sizeof(reg_array) / sizeof(reg); i++) {
   2370         reg = reg_array[i];
   2371         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 0, 0, &rval));
   2372         soc_reg_field_set(unit, reg, &rval, MC_Q_MODEf, mode);
   2373         SOC_IF_ERROR_RETURN
   2374             (soc_tomahawk3_itm_reg32_set(unit, reg, -1, -1, -1, rval));
   2375     }
   2376     return SOC_E_NONE;
   2377 }
   2378 
   2379 /* Function:
   2380  *      soc_tomahawk3_port_schedule_state_basic_setup
   2381  * Purpose:
   2382  *      Setup Global params in port_schedule_state structure
   2383  *      to DV FlexPort API
   2384  * Parameters:
   2385  *      unit                 - (IN)  Unit number.
   2386  *      port_schedule_state  - (OUT) Port resource state.
   2387  * Returns:
   2388  *      BCM_E_xxx
   2389  */
   2390 STATIC int
   2391 soc_tomahawk3_port_schedule_state_basic_setup(int unit,
   2392                 soc_port_schedule_state_t *port_schedule_state)
   2393 {
   2394 #define _TH3_CPU_LB_PORT_SPEED 10000
   2395 #if 0
   2396     soc_control_t *soc = SOC_CONTROL(unit);
   2397 #endif
   2398     soc_info_t *si = &SOC_INFO(unit);
   2399     soc_port_map_type_t *in_portmap;
   2400     soc_asf_prop_t *cutthru_prop;
   2401     int port, latency;
   2402     int dpr_freq;
   2403     /* Core clock frequency */
   2404     port_schedule_state->frequency = si->frequency;
   2405 
   2406     /*MMU lossless mode. default to 1(lossy)*/
   2407     port_schedule_state->lossless = soc_property_get(unit, spn_MMU_LOSSLESS,
   2408             SOC_TH3_MMU_LOSSLESS_DEFAULT_DISABLE);
   2409 
   2410     /* Construct in_port_map */
   2411     in_portmap = &port_schedule_state->in_port_map;
   2412 
   2413     /*DPP clock frequency in MHz needs to be passed*/
   2414     dpr_freq = soc_property_get(unit, spn_DPR_CLOCK_FREQUENCY, -1);
   2415     SOC_IF_ERROR_RETURN
   2416         (soc_tomahawk3_dpr_frequency_range_check(unit, dpr_freq));
   2417     in_portmap->port_p2PBLK_inst_mapping[0] = dpr_freq;
   2418 
   2419     PBMP_ALL_ITER(unit, port) {
   2420         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   2421             continue;
   2422         }
   2423         in_portmap->log_port_speed[port] = si->port_speed_max[port];
   2424         in_portmap->port_num_lanes[port] = si->port_num_lanes[port];
   2425         /*Override port speed for CPU and LB ports*/
   2426         if (IS_CPU_PORT(unit, port) || (IS_LB_PORT(unit, port))) {
   2427             in_portmap->log_port_speed[port] = _TH3_CPU_LB_PORT_SPEED;
   2428         }
   2429     }
   2430     sal_memcpy(in_portmap->port_p2l_mapping, si->port_p2l_mapping,
   2431                 sizeof(int) * SOC_MAX_NUM_PORTS);
   2432     sal_memcpy(in_portmap->port_l2p_mapping, si->port_l2p_mapping,
   2433                 sizeof(int) * SOC_MAX_NUM_PORTS);
   2434     sal_memcpy(in_portmap->port_p2m_mapping, si->port_p2m_mapping,
   2435                 sizeof(int) * SOC_MAX_NUM_PORTS);
   2436     sal_memcpy(in_portmap->port_m2p_mapping, si->port_m2p_mapping,
   2437                 sizeof(int) * SOC_MAX_NUM_MMU_PORTS);
   2438     sal_memcpy(in_portmap->port_l2i_mapping, si->port_l2i_mapping,
   2439                 sizeof(int) * SOC_MAX_NUM_PORTS);
   2440     /*physical pbm is dont care for init
   2441      *sal_memcpy(&in_portmap->physical_pbm, &si->physical_pbm, sizeof(pbmp_t));
   2442      */
   2443     sal_memcpy(&in_portmap->management_pbm, &si->management_pbm,
   2444                 sizeof(pbmp_t));
   2445     /* Construct in_port_map */
   2446     cutthru_prop = &port_schedule_state->cutthru_prop;
   2447     SOC_IF_ERROR_RETURN(soc_th_latency_get(unit, &latency));
   2448     cutthru_prop->switch_bypass_mode = latency;
   2449     /* Construct tdm_ingress_schedule_pipe and tdm_egress_schedule_pipe */
   2450     port_schedule_state->is_flexport = 0;
   2451     /*DV function to setup out_port_map.
   2452      *Required before calling any DV function
   2453      */
   2454         SOC_IF_ERROR_RETURN(soc_tomahawk3_tdm_set_out_port_map(unit,
   2455                 port_schedule_state));
   2456 #undef _TH3_CPU_LB_PORT_SPEED
   2457     return SOC_E_NONE;
   2458 }
   2459 
   2460 
   2461 
   2462 /*
   2463  * Function:
   2464  *      soc_tomahawk3_port_schedule_tdm_init
   2465  * Purpose:
   2466  *      Initialize TDM information in port_schedule_state that will be passed
   2467  *      to DV FlexPort API
   2468  * Parameters:
   2469  *      unit                 - (IN)  Unit number.
   2470  *      port_schedule_state  - (OUT) Port resource state.
   2471  * Returns:
   2472  *      BCM_E_xxx
   2473  * Notes:
   2474  *      If called during Scheduler Initialization, only below values need to be
   2475  *      properly set:
   2476  *        soc_tdm_schedule_pipe_t::num_slices
   2477  *        soc_tdm_schedule_t:: cal_len
   2478  */
   2479 STATIC int
   2480 soc_tomahawk3_port_schedule_tdm_init(int unit, soc_port_schedule_state_t
   2481         *port_schedule_state)
   2482 {
   2483 #if 0
   2484     soc_control_t *soc = SOC_CONTROL(unit);
   2485     _soc_tomahawk2_tdm_t *tdm = soc->tdm_info;
   2486     soc_tdm_schedule_t *sched;
   2487 #endif
   2488     soc_tdm_schedule_pipe_t *tdm_ischd, *tdm_eschd;
   2489     int pipe;
   2490     /*int *port_p2PBLK_inst_mapping;*/
   2491 
   2492 #if 0
   2493     if (tdm == NULL) {
   2494         /*XGSSIM will skip tdm configuration on TH2*/
   2495         if (SAL_BOOT_XGSSIM) {
   2496             return SOC_E_NONE;
   2497         }
   2498         return SOC_E_INIT;
   2499     }
   2500 #endif
   2501     /* Construct tdm_ingress_schedule_pipe and tdm_egress_schedule_pipe */
   2502     for (pipe = 0; pipe <  _TH3_PIPES_PER_DEV; pipe++) {
   2503         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
   2504         tdm_eschd = &port_schedule_state->tdm_egress_schedule_pipe[pipe];
   2505 
   2506         tdm_ischd->num_slices = _TH3_OVS_HPIPE_COUNT_PER_PIPE;
   2507         tdm_eschd->num_slices = _TH3_OVS_HPIPE_COUNT_PER_PIPE;
   2508 
   2509 #if 0
   2510     is_flexport = port_schedule_state->is_flexport;
   2511         if (is_flexport) {
   2512             /* TDM Calendar is always in slice 0 */
   2513             sal_memcpy(tdm_ischd->tdm_schedule_slice[0].linerate_schedule,
   2514                         tdm->tdm_pipe[pipe].idb_tdm,
   2515                         sizeof(int)*_TH3_TDM_LENGTH);
   2516             sal_memcpy(tdm_eschd->tdm_schedule_slice[0].linerate_schedule,
   2517                         tdm->tdm_pipe[pipe].mmu_tdm,
   2518                         sizeof(int)*_TH3_TDM_LENGTH);
   2519         }
   2520 #endif
   2521 #if 0
   2522         /* OVS */
   2523         for (hpipe = 0; hpipe < _TH3_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
   2524             /* IDB OVERSUB*/
   2525             sched = &tdm_ischd->tdm_schedule_slice[hpipe];
   2526             sched->cal_len = _TH3_TDM_LENGTH;
   2527 
   2528             /* MMU OVERSUB */
   2529             sched = &tdm_eschd->tdm_schedule_slice[hpipe];
   2530             sched->cal_len = _TH3_TDM_LENGTH;
   2531 
   2532         }
   2533 #endif
   2534     }
   2535     return SOC_E_NONE;
   2536 }
   2537 
   2538 int _soc_th3_get_num_ucq(int unit)
   2539 {
   2540     int mc_q_mode, num_ucq;
   2541 
   2542     mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, 2);
   2543     num_ucq = (mc_q_mode == 0) ? 12 : (mc_q_mode == 1) ? 10 :
   2544               (mc_q_mode == 2) ? 8  : (mc_q_mode == 3) ? 6 : 8;
   2545 
   2546     return num_ucq;
   2547 }
   2548 
   2549 int _soc_th3_get_num_mcq(int unit)
   2550 {
   2551     int mc_q_mode, num_mcq;
   2552 
   2553     mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, 2);
   2554     num_mcq = (mc_q_mode == 0) ? 0 : (mc_q_mode == 1) ? 2 :
   2555               (mc_q_mode == 2) ? 4 : (mc_q_mode == 3) ? 6 : 4;
   2556 
   2557     return num_mcq;
   2558 }
   2559 
   2560 
   2561 /*
   2562  *Function: soc_tomahawk3_l0_cos_set
   2563  *Purpose: Assign Hardware L0 index to a cos
   2564  */
   2565 int
   2566 soc_tomahawk3_l0_cos_set(int unit, soc_port_t port, int hw_index, soc_cos_t cos)
   2567 {
   2568     if (cos < 0 || cos >= SOC_TH3_NUM_GP_QUEUES || hw_index < 0 || hw_index >=
   2569             SOC_TH3_NUM_GP_QUEUES) {
   2570         return SOC_E_PARAM;
   2571     }
   2572     th3_cosq_mmu_info[unit]->th3_port_info[port].L0[hw_index].cos = cos;
   2573     LOG_INFO(BSL_LS_SOC_COSQ,
   2574             (BSL_META_U(unit, "Port: %0d L0[%0d].cos: %0d in_use:%0d\n"),
   2575              port, hw_index, cos, th3_cosq_mmu_info[unit]->th3_port_info[port].L0[hw_index].in_use));
   2576     return SOC_E_NONE;
   2577 }
   2578 
   2579 /*
   2580  *Function: soc_tomahawk3_sched_profile_attach
   2581  *Purpose: Update port structure for scheduler based on profile information
   2582  *         Program the MMU to SCHQ mapping fro the profile in HW
   2583  */
   2584 int
   2585 soc_tomahawk3_sched_profile_attach(int unit, soc_port_t port, int profile)
   2586 {
   2587     soc_reg_t reg;
   2588     uint32 rval;
   2589     uint64 rval_64;
   2590     int queue_num, i;
   2591     int mmuq, schedq;
   2592     soc_reg_t reg_array[] = {MMU_EBPCC_MMUQ_SCHQ_CFGr,
   2593                              MMU_MTRO_MMUQ_SCHQ_CFGr,
   2594                              MMU_QSCH_MMUQ_TO_SCHQ_MAPr,
   2595                              MMU_PORT_MMUQ_SCHQ_CFGr};
   2596 
   2597     soc_field_t schedq_field[] = {
   2598         SCH_Q_NUM_0f, SCH_Q_NUM_1f,
   2599         SCH_Q_NUM_2f, SCH_Q_NUM_3f,
   2600         SCH_Q_NUM_4f, SCH_Q_NUM_5f,
   2601         SCH_Q_NUM_6f, SCH_Q_NUM_7f,
   2602         SCH_Q_NUM_8f, SCH_Q_NUM_9f,
   2603         SCH_Q_NUM_10f, SCH_Q_NUM_11f,
   2604     };
   2605     soc_field_t mmuq_field[12] = {
   2606         MMU_Q_NUM_0f, MMU_Q_NUM_1f,
   2607         MMU_Q_NUM_2f, MMU_Q_NUM_3f,
   2608         MMU_Q_NUM_4f, MMU_Q_NUM_5f,
   2609         MMU_Q_NUM_6f, MMU_Q_NUM_7f,
   2610         MMU_Q_NUM_8f, MMU_Q_NUM_9f,
   2611         MMU_Q_NUM_10f, MMU_Q_NUM_11f,
   2612     };
   2613     if (IS_CPU_PORT(unit, port)) {
   2614         return SOC_E_NONE;
   2615     }
   2616     for (i = 0; i < sizeof(reg_array) / sizeof(reg); i++) {
   2617         reg = reg_array[i];
   2618         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   2619         soc_reg_field_set(unit, reg, &rval, Q_PROFILE_SELf, profile);
   2620         SOC_IF_ERROR_RETURN
   2621             (soc_reg32_set(unit, reg, port, 0, rval));
   2622     }
   2623 
   2624     /*L1 to L0 mapping construct*/
   2625     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2626         if (L1_TO_L0_MAPPING[unit][profile][queue_num] != -1) {
   2627             soc_th3_cosq_node_t *parent;
   2628             parent = &th3_cosq_mmu_info[unit]->th3_port_info[port].
   2629                 L0[L1_TO_L0_MAPPING[unit][profile][queue_num]];
   2630             th3_cosq_mmu_info[unit]->th3_port_info[port].
   2631                 L1[queue_num].parent = parent;
   2632         } else {
   2633             th3_cosq_mmu_info[unit]->th3_port_info[port].
   2634                 L1[queue_num].parent = NULL;
   2635         }
   2636     }
   2637     /*L0 to L1 mapping construct*/
   2638     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2639         if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 0) {
   2640             th3_cosq_mmu_info[unit]->th3_port_info[port].
   2641                 L0[queue_num].in_use = 0;
   2642             continue;
   2643         } else {
   2644             th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].in_use = 1;
   2645             th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].cos = 
   2646                 L0_TO_COSQ_MAPPING[unit][profile][queue_num];
   2647 
   2648             if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 1) {
   2649                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   2650                     children[0] = &th3_cosq_mmu_info[unit]->th3_port_info[port].
   2651                     L1[queue_num];
   2652             } else if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 2) {
   2653                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   2654                     children[0] = &th3_cosq_mmu_info[unit]->th3_port_info[port].
   2655                     L1[queue_num];
   2656                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   2657                     children[1] = &th3_cosq_mmu_info[unit]->th3_port_info[port].
   2658                     L1[queue_num - 1];
   2659             } else {
   2660                 /* No children */
   2661                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   2662                     children[0] = NULL;
   2663             }
   2664         }
   2665     }
   2666     /*mmuq to schedq mapping construct*/
   2667     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2668         reg = MMU_EBPCC_MMUQ_SCHQ_PROFILEr;
   2669         SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, profile, &rval_64));
   2670         schedq = soc_reg64_field32_get(unit, reg, rval_64, schedq_field[queue_num]);
   2671         th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue_num].parent =
   2672             &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   2673     }
   2674     /*schedq to mmuq mapping construct*/
   2675     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2676         reg = MMU_PPSCH_SCHQ_MMUQ_PROFILEr;
   2677         SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, profile, &rval_64));
   2678         mmuq = soc_reg64_field32_get(unit, reg, rval_64, mmuq_field[queue_num]);
   2679         th3_cosq_mmu_info[unit]->th3_port_info[port].L1[queue_num].children[0]
   2680             = &th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq];
   2681     }
   2682     return SOC_E_NONE;
   2683 }
   2684 
   2685 /*
   2686  *Function: soc_tomahawk3_sched_profile_attach_reinit
   2687  *Purpose: Update port structure for scheduler based on profile information
   2688  *         Program the MMU to SCHQ mapping fro the profile in HW
   2689  */
   2690 int
   2691 soc_tomahawk3_sched_profile_attach_reinit(int unit, soc_port_t port, int profile)
   2692 {
   2693     int queue_num;
   2694 
   2695     /*L1 to L0 mapping construct*/
   2696     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2697         if (L1_TO_L0_MAPPING[unit][profile][queue_num] != -1) {
   2698             soc_th3_cosq_node_t *parent;
   2699             parent = &th3_cosq_mmu_info[unit]->th3_port_info[port].
   2700                 L0[L1_TO_L0_MAPPING[unit][profile][queue_num]];
   2701             th3_cosq_mmu_info[unit]->th3_port_info[port].
   2702                 L1[queue_num].parent = parent;
   2703         } else {
   2704             th3_cosq_mmu_info[unit]->th3_port_info[port].
   2705                 L1[queue_num].parent = NULL;
   2706         }
   2707     }
   2708     /*L0 to L1 mapping construct*/
   2709     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   2710         if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 0) {
   2711             th3_cosq_mmu_info[unit]->th3_port_info[port].
   2712                 L0[queue_num].in_use = 0;
   2713             continue;
   2714         } else {
   2715             th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].in_use = 1;
   2716             th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].cos = 
   2717                 L0_TO_COSQ_MAPPING[unit][profile][queue_num];
   2718 
   2719             if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 1) {
   2720                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   2721                     children[0] = &th3_cosq_mmu_info[unit]->th3_port_info[port].
   2722                     L1[queue_num];
   2723             } else if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 2) {
   2724                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   2725                     children[0] = &th3_cosq_mmu_info[unit]->th3_port_info[port].
   2726                     L1[queue_num];
   2727                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   2728                     children[1] = &th3_cosq_mmu_info[unit]->th3_port_info[port].
   2729                     L1[queue_num - 1];
   2730             } else {
   2731                 /* No children */
   2732                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   2733                     children[0] = NULL;
   2734             }
   2735         }
   2736     }
   2737 
   2738     return SOC_E_NONE;
   2739 }
   2740 
   2741 /*
   2742  *Function: soc_tomahawk3_sched_profile_get
   2743  *Purpose: Get the scheduler rofile for a port
   2744  */
   2745 int
   2746 soc_tomahawk3_sched_profile_get(int unit, soc_port_t port, int *profile)
   2747 {
   2748     soc_reg_t reg;
   2749     uint32 rval;
   2750 
   2751     if (profile == NULL) {
   2752         return SOC_E_PARAM;
   2753     }
   2754 
   2755     if (IS_CPU_PORT(unit, port)) {
   2756         return SOC_E_NONE;
   2757     }
   2758 
   2759     reg = MMU_EBPCC_MMUQ_SCHQ_CFGr;
   2760     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   2761     *profile = soc_reg_field_get(unit, reg, rval, Q_PROFILE_SELf);
   2762 
   2763     return SOC_E_NONE;
   2764 }
   2765 
   2766 /*
   2767  *Function: soc_profile_port_list_get
   2768  *Purpose: retrieve information of all ports attached to a profile
   2769  */
   2770 int
   2771 soc_profile_port_list_get(int unit, int profile, int port_in_profile[])
   2772 {
   2773     soc_reg_t reg = MMU_EBPCC_MMUQ_SCHQ_CFGr;
   2774     int profile_in_use;
   2775     uint32 rval;
   2776     soc_port_t port;
   2777 
   2778     SOC_PBMP_ITER(PBMP_ALL(unit), port) {
   2779         if (!IS_CPU_PORT(unit, port)) {
   2780             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   2781             profile_in_use = soc_reg_field_get(unit, reg, rval, Q_PROFILE_SELf);
   2782             if (profile == profile_in_use) {
   2783                 port_in_profile[port] = 1;
   2784             } else {
   2785                 port_in_profile[port] = 0;
   2786             }
   2787         }
   2788     }
   2789     return SOC_E_NONE;
   2790 }
   2791 
   2792 /*
   2793  *Function: soc_tomahawk3_l1_to_l0_profile_set
   2794  *Purpose: Update L1 to L0 mapping information in HW and teh SW structure
   2795  */
   2796 int
   2797 soc_tomahawk3_l1_to_l0_profile_set(int unit, int profile, int L0, int schedq,
   2798         int port_in_profile[])
   2799 {
   2800     soc_reg_t reg = INVALIDr;
   2801     uint64 rval_64;
   2802     uint32 mapping = 0;
   2803     int port;
   2804     uint32 rval;
   2805 
   2806     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   2807         return SOC_E_PARAM;
   2808     }
   2809 
   2810     L1_TO_L0_MAPPING[unit][profile][schedq] = L0;
   2811     L0_TO_L1_MAPPING_NUM[unit][profile][L0]++;
   2812     LOG_INFO(BSL_LS_SOC_COSQ,
   2813                 (BSL_META_U(unit, "Profile %d L1_TO_L0_MAPPING[%d]: %d L0_TO_L1_MAPPING_NUM[%d]: %d\n"),
   2814                         profile, schedq,  L1_TO_L0_MAPPING[unit][profile][schedq], L0, L0_TO_L1_MAPPING_NUM[unit][profile][L0]));
   2815 
   2816     for (port = 0; port < SOC_TH3_MAX_NUM_PORTS; port++) {
   2817         if (port_in_profile[port] == 1) {
   2818             /* Set same value of L1 to L0 map in MTRO*/
   2819             reg = MMU_MTRO_MMUQ_SCHQ_CFGr;
   2820             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   2821             mapping = soc_reg_field_get(unit, reg, rval, L1_TO_L0_MAPf);
   2822              /*L1_TO_L0_MAP [x] configures L1[x], where x = 0..10.  Note L1[11]
   2823               *is only connected to L0[11] so is not included in this config.
   2824               *bit[x]=0: (default) L1[x] connected to L0[x];
   2825               *bit[x]=1: (default) L1[x] connected to L0[x+1]
   2826               */
   2827             if (schedq == L0)
   2828                 mapping = mapping & ~(1 << schedq);
   2829             else
   2830                 mapping = mapping | (1 << schedq);
   2831 
   2832             soc_reg_field_set(unit, reg, &rval, L1_TO_L0_MAPf, mapping);
   2833             SOC_IF_ERROR_RETURN
   2834                 (soc_reg32_set(unit, reg, port, 0, rval));
   2835 
   2836             reg = MMU_QSCH_PORT_CONFIGr;
   2837             SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval_64));
   2838             soc_reg64_field32_set(unit, reg, &rval_64, L1_TO_L0_MAPPINGf, mapping);
   2839             SOC_IF_ERROR_RETURN
   2840                 (soc_reg64_set(unit, reg, port, 0, rval_64));
   2841 
   2842             th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].parent =
   2843                 &th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0];
   2844             th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].in_use = 1;
   2845             if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0]
   2846                                                                   == NULL) {
   2847                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0]
   2848                     = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   2849                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].in_use = 1;
   2850             } else {
   2851                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[1]
   2852                     = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   2853             }
   2854         }
   2855     }
   2856     return SOC_E_NONE;
   2857 }
   2858 
   2859 /*
   2860  *Function: soc_tomahawk3_l1_to_l0_profile_set_reinit
   2861  *Purpose: Update L1 to L0 mapping information in HW and teh SW structure
   2862  */
   2863 int
   2864 soc_tomahawk3_l1_to_l0_profile_set_reinit(int unit, int profile, int L0, int schedq,
   2865         int port_in_profile[])
   2866 {
   2867     int port;
   2868 
   2869     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   2870         return SOC_E_PARAM;
   2871     }
   2872 
   2873     L1_TO_L0_MAPPING[unit][profile][schedq] = L0;
   2874     L0_TO_L1_MAPPING_NUM[unit][profile][L0]++;
   2875 
   2876     for (port = 0; port < SOC_TH3_MAX_NUM_PORTS; port++) {
   2877         if (port_in_profile[port] == 1) {
   2878             th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].parent =
   2879                 &th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0];
   2880             th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].in_use = 1;
   2881             if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0]
   2882                                                                   == NULL) {
   2883                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0]
   2884                     = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   2885                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].in_use = 1;
   2886             } else {
   2887                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[1]
   2888                     = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   2889             }
   2890         }
   2891     }
   2892     return SOC_E_NONE;
   2893 }
   2894 
   2895 
   2896 /*
   2897  *Function: soc_tomahawk3_l1_to_l0_profile_update_per_port
   2898  *Purpose: Update L1 to L0 mapping information in HW and teh SW structure
   2899  */
   2900 int
   2901 soc_tomahawk3_l1_to_l0_profile_update_per_port(int unit, int port, int profile)
   2902 {
   2903     int L0[SOC_TH3_COS_MAX];
   2904     int schedq[SOC_TH3_COS_MAX];
   2905     int i;
   2906 
   2907     for (i = 0; i < SOC_TH3_COS_MAX; i++) {
   2908         L0[i] = L1_TO_L0_MAPPING[unit][profile][i];
   2909         schedq[i] = i;
   2910         SOC_IF_ERROR_RETURN
   2911             (soc_tomahawk3_l1_to_l0_profile_set_per_port(unit, port, profile, L0[i], schedq[i]));
   2912     }
   2913     return SOC_E_NONE;
   2914 }
   2915 
   2916 /*
   2917  *Function: soc_tomahawk3_l1_to_l0_profile_set_per_port
   2918  *Purpose: Update L1 to L0 mapping information in HW and teh SW structure
   2919  */
   2920 int
   2921 soc_tomahawk3_l1_to_l0_profile_set_per_port(int unit, int port, int profile, int L0, int schedq)
   2922 {
   2923     soc_reg_t reg = INVALIDr;
   2924     uint64 rval_64;
   2925     uint32 mapping = 0;
   2926     uint32 rval;
   2927 
   2928     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   2929         return SOC_E_PARAM;
   2930     }
   2931 
   2932     /* Set same value of L1 to L0 map in MTRO*/
   2933     reg = MMU_MTRO_MMUQ_SCHQ_CFGr;
   2934     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   2935     mapping = soc_reg_field_get(unit, reg, rval, L1_TO_L0_MAPf);
   2936      /*L1_TO_L0_MAP [x] configures L1[x], where x = 0..10.  Note L1[11]
   2937       *is only connected to L0[11] so is not included in this config.
   2938       *bit[x]=0: (default) L1[x] connected to L0[x];
   2939       *bit[x]=1: (default) L1[x] connected to L0[x+1]
   2940       */
   2941     if (schedq == L0) {
   2942         mapping = mapping & ~(1 << schedq);
   2943     }
   2944     else {
   2945         mapping = mapping | (1 << schedq);
   2946     }
   2947 
   2948     soc_reg_field_set(unit, reg, &rval, L1_TO_L0_MAPf, mapping);
   2949     SOC_IF_ERROR_RETURN
   2950         (soc_reg32_set(unit, reg, port, 0, rval));
   2951 
   2952     reg = MMU_QSCH_PORT_CONFIGr;
   2953     SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval_64));
   2954     soc_reg64_field32_set(unit, reg, &rval_64, L1_TO_L0_MAPPINGf, mapping);
   2955     SOC_IF_ERROR_RETURN
   2956         (soc_reg64_set(unit, reg, port, 0, rval_64));
   2957 
   2958     th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].parent =
   2959         &th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0];
   2960     th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].in_use = 1;
   2961     if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0]
   2962                                                           == NULL) {
   2963         th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0]
   2964             = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   2965         th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].in_use = 1;
   2966     } else {
   2967         th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[1]
   2968             = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   2969     }
   2970 
   2971     soc_gport_tree_print(unit, port);
   2972 
   2973     return SOC_E_NONE;
   2974 }
   2975 
   2976 
   2977 /*! @fn void soc_print_port_schedule_state(int unit,
   2978  *               soc_port_schedule_state_t *port_schedule_state)
   2979  *  @param unit Chip unit number.
   2980  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
   2981  *         variable.
   2982  *  @brief Debug API to print port_schedule_state
   2983  */
   2984 void
   2985 soc_th3_print_port_schedule_state(int                        unit,
   2986                               soc_port_schedule_state_t *port_schedule_state)
   2987 {
   2988 
   2989     LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   2990               "\n\nPRINTING soc_port_schedule_state_t \n")));
   2991 
   2992     LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   2993               "frequency= %4dMHz\n"), port_schedule_state->frequency));
   2994     LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   2995               "DPP frequency= %4dMHz\n"),
   2996                 port_schedule_state->in_port_map.port_p2PBLK_inst_mapping[0]));
   2997     LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   2998               "lossless= %1d\n"), port_schedule_state->lossless));
   2999     LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   3000               "is_flexport= %1d\n"), port_schedule_state->is_flexport));
   3001 
   3002     LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   3003               "\nPRINTING soc_port_schedule_state_t::in_port_map\n")));
   3004     soc_print_port_map(unit, &port_schedule_state->in_port_map);
   3005 
   3006     if (port_schedule_state->is_flexport == 1) {
   3007         LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   3008                   "\nPRINTING soc_port_schedule_state_t::out_port_map\n")));
   3009         soc_print_port_map(unit, &port_schedule_state->out_port_map);
   3010     }
   3011 
   3012 #if 0
   3013     if ((port_schedule_state->is_flexport == 1) &&
   3014         (port_schedule_state->nport > 0)) {
   3015         LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   3016                   "\n====== FLEXPORT RESOURCES ===== num entries= %d = \n"),
   3017                   port_schedule_state->nport));
   3018         for (i = 0; i < port_schedule_state->nport; i++) {
   3019             soc_print_port_resource(unit, &port_schedule_state->resource[i], i);
   3020         }
   3021     }
   3022 #endif
   3023 }
   3024 
   3025 /*Function:
   3026  *  soc_tomahawk3_tdm_update
   3027  *Purpose:
   3028  *  Setup port_schedule_state structure and call TDM init
   3029  *Params:
   3030  * unit: Chip unit number
   3031  */
   3032 int
   3033 soc_tomahawk3_tdm_update (int unit)
   3034 {
   3035     soc_port_schedule_state_t *port_schedule_state;
   3036     int rv;
   3037 
   3038     port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t),
   3039                                     "Tomahawk3 soc_port_schedule_state_t");
   3040     if (port_schedule_state == NULL) {
   3041         return SOC_E_MEMORY;
   3042     }
   3043     sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t));
   3044     rv = soc_tomahawk3_port_schedule_state_basic_setup(unit,
   3045             port_schedule_state);
   3046     rv = soc_tomahawk3_port_schedule_tdm_init(unit, port_schedule_state);
   3047 
   3048     soc_th3_print_port_schedule_state(unit, port_schedule_state);
   3049 
   3050     rv = soc_tomahawk3_tdm_init(unit, port_schedule_state);
   3051 
   3052     if (rv != SOC_E_NONE) {
   3053         LOG_CLI((BSL_META_U(unit,
   3054             "Unable to configure TDM, please contact your "
   3055             "Field Applications Engineer or Sales Manager for "
   3056             "additional assistance.\n")));
   3057         sal_free(port_schedule_state);
   3058         return rv;
   3059     }
   3060 
   3061     /* Update SOC TDM info */
   3062     /*The TDM infor needs to be captured in SOC_CONTROL->tdm_info before
   3063      *port_schedule_state is freed. This function needs to be defined for TH3*/
   3064     /*rv = soc_th2_soc_tdm_update(unit, port_schedule_state);*/
   3065 
   3066     sal_free(port_schedule_state);
   3067     return rv;
   3068 }
   3069 
   3070 /*
   3071  *Function: soc_tomahawk3_cpu_l1_to_l0_profile_set
   3072  *Purpose: Update L1 to L0 mapping information  for CPU port
   3073  */
   3074 int
   3075 soc_tomahawk3_cpu_l1_to_l0_profile_set(int unit, int L0, int schedq)
   3076 {
   3077     soc_reg_t reg = INVALIDr;
   3078     uint32 rval;
   3079     th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[L0].in_use = 1;
   3080     th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[L0].children[schedq] =
   3081         &th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[schedq];
   3082     th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[schedq].in_use = 1;
   3083     th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[schedq].parent =
   3084         &th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[L0];
   3085 
   3086     reg = MMU_MTRO_CPU_L1_TO_L0_MAPPINGr;
   3087     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, schedq, &rval));
   3088     soc_reg_field_set(unit, reg, &rval, SELECTf, L0);
   3089     SOC_IF_ERROR_RETURN
   3090         (soc_reg32_set(unit, reg, REG_PORT_ANY, schedq, rval));
   3091 
   3092     reg = MMU_QSCH_CPU_L1_TO_L0_MAPPINGr;
   3093     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, schedq, &rval));
   3094     soc_reg_field_set(unit, reg, &rval, SELECTf, L0);
   3095     SOC_IF_ERROR_RETURN
   3096         (soc_reg32_set(unit, reg, REG_PORT_ANY, schedq, rval));
   3097     return SOC_E_NONE;
   3098 }
   3099 
   3100 /*
   3101  *Function: soc_tomahawk3_mmuq_to_schedq_profile_set_per_port
   3102  *Purpose: Updated MMUQ to SCHQ mapping profile
   3103  */
   3104 int
   3105 soc_tomahawk3_mmuq_to_schedq_profile_set_per_port(int unit, int port, int schedq,
   3106         int mmuq)
   3107 {
   3108     th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq].parent =
   3109         &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   3110     th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].children[0]
   3111         = &th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq];
   3112     return SOC_E_NONE;
   3113 }
   3114 /*
   3115  *Function: soc_tomahawk3_mmuq_to_schedq_profile_set
   3116  *Purpose: Updated MMUQ to SCHQ mapping profile
   3117  */
   3118 int
   3119 soc_tomahawk3_mmuq_to_schedq_profile_set(int unit, int profile, int schedq,
   3120         int mmuq, int port_in_profile[])
   3121 {
   3122     soc_reg_t reg = INVALIDr;
   3123     uint64 rval_64;
   3124     int port;
   3125     soc_field_t schedq_field[12] = {
   3126         SCH_Q_NUM_0f, SCH_Q_NUM_1f,
   3127         SCH_Q_NUM_2f, SCH_Q_NUM_3f,
   3128         SCH_Q_NUM_4f, SCH_Q_NUM_5f,
   3129         SCH_Q_NUM_6f, SCH_Q_NUM_7f,
   3130         SCH_Q_NUM_8f, SCH_Q_NUM_9f,
   3131         SCH_Q_NUM_10f, SCH_Q_NUM_11f,
   3132     };
   3133     soc_field_t mmuq_field[12] = {
   3134         MMU_Q_NUM_0f, MMU_Q_NUM_1f,
   3135         MMU_Q_NUM_2f, MMU_Q_NUM_3f,
   3136         MMU_Q_NUM_4f, MMU_Q_NUM_5f,
   3137         MMU_Q_NUM_6f, MMU_Q_NUM_7f,
   3138         MMU_Q_NUM_8f, MMU_Q_NUM_9f,
   3139         MMU_Q_NUM_10f, MMU_Q_NUM_11f,
   3140     };
   3141 
   3142     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   3143         return SOC_E_PARAM;
   3144     }
   3145     reg = MMU_EBPCC_MMUQ_SCHQ_PROFILEr;
   3146     SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, profile, &rval_64));
   3147     soc_reg64_field32_set(unit, reg, &rval_64, schedq_field[mmuq], schedq);
   3148     SOC_IF_ERROR_RETURN
   3149         (soc_reg64_set(unit, reg, 0, profile, rval_64));
   3150 
   3151     reg = MMU_MTRO_MMUQ_SCHQ_PROFILEr;
   3152     SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, profile, &rval_64));
   3153     soc_reg64_field32_set(unit, reg, &rval_64, schedq_field[mmuq], schedq);
   3154     SOC_IF_ERROR_RETURN
   3155         (soc_reg64_set(unit, reg, 0, profile, rval_64));
   3156 
   3157     reg = MMU_PPSCH_SCHQ_MMUQ_PROFILEr;
   3158     SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, profile, &rval_64));
   3159     soc_reg64_field32_set(unit, reg, &rval_64, mmuq_field[schedq], mmuq);
   3160     SOC_IF_ERROR_RETURN
   3161         (soc_reg64_set(unit, reg, 0, profile, rval_64));
   3162 
   3163     for (port = 0; port < SOC_TH3_MAX_NUM_PORTS; port++) {
   3164         if (port_in_profile[port] == 1) {
   3165             th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq].parent =
   3166                 &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   3167             th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].children[0]
   3168                 = &th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq];
   3169         }
   3170     }
   3171     return SOC_E_NONE;
   3172 }
   3173 
   3174 /*
   3175  *Function: soc_tomahawk3_mmuq_to_schedq_profile_set_reinit
   3176  *Purpose: Updated MMUQ to SCHQ mapping profile
   3177  */
   3178 int
   3179 soc_tomahawk3_mmuq_to_schedq_profile_set_reinit(int unit, int profile, int schedq,
   3180         int mmuq, int port_in_profile[])
   3181 {
   3182     int port;
   3183 
   3184     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   3185         return SOC_E_PARAM;
   3186     }
   3187 
   3188     for (port = 0; port < SOC_TH3_MAX_NUM_PORTS; port++) {
   3189         if (port_in_profile[port] == 1) {
   3190             th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq].parent =
   3191                 &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq];
   3192             th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].children[0]
   3193                 = &th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq];
   3194         }
   3195     }
   3196     return SOC_E_NONE;
   3197 }
   3198 
   3199 /*
   3200  *Function: soc_tomahawk3_sched_update_init
   3201  *Purpose: Wrapper function to set L0->schedq->MMUQ map for a specific profile
   3202  */
   3203 int
   3204 soc_tomahawk3_sched_update_init(int unit, int profile, int *L0, int *schedq,
   3205         int *mmuq, int *cos, int *strict_priority, int* fc_is_uc_only)
   3206 {
   3207     int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0};
   3208     int port, queue;
   3209 
   3210     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   3211         return SOC_E_PARAM;
   3212     }
   3213     /*check which ports is using this profile*/
   3214     soc_profile_port_list_get(unit, profile, port_in_profile);
   3215 
   3216     PBMP_ALL_ITER(unit, port) {
   3217         if (port_in_profile[port]) {
   3218             LOG_INFO(BSL_LS_SOC_COSQ,
   3219                 (BSL_META_U(unit, "Port info init for port %0d\n"),
   3220                         port));
   3221             soc_tomahawk3_cosq_port_info_init(unit, port);
   3222         }
   3223     }
   3224 
   3225     soc_tomahawk3_cosq_profile_info_init(unit, profile);
   3226 
   3227     for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3228         /* initialize per profile structure */
   3229         int cosq_index;
   3230         cosq_index = L0[queue];
   3231         if (cos[queue] == -1) {
   3232             continue;
   3233         }
   3234         th3_sched_profile_info[unit][profile][cosq_index].cos = cos[queue];
   3235         th3_sched_profile_info[unit][profile][cosq_index].strict_priority = strict_priority[queue];
   3236         th3_sched_profile_info[unit][profile][cosq_index].fc_is_uc_only = fc_is_uc_only[queue];
   3237         if (th3_sched_profile_info[unit][profile][cosq_index].mmuq[0] == -1) {
   3238             th3_sched_profile_info[unit][profile][cosq_index].mmuq[0] = mmuq[queue];
   3239         }
   3240         else {
   3241             th3_sched_profile_info[unit][profile][cosq_index].mmuq[1] = mmuq[queue];
   3242         }
   3243 
   3244         SOC_IF_ERROR_RETURN
   3245             (soc_tomahawk3_l1_to_l0_profile_set(unit, profile, L0[queue], schedq[queue],
   3246                                                 port_in_profile));
   3247         SOC_IF_ERROR_RETURN
   3248             (soc_tomahawk3_mmuq_to_schedq_profile_set(unit, profile, schedq[queue],
   3249                                                       mmuq[queue], port_in_profile));
   3250         L0_TO_COSQ_MAPPING[unit][profile][queue] = cos[queue];
   3251     }
   3252 
   3253     SOC_IF_ERROR_RETURN
   3254         (soc_cosq_sched_policy_init(unit, profile));
   3255 
   3256     PBMP_ALL_ITER(unit, port) {
   3257         if (port_in_profile[port]) {
   3258             for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3259                 SOC_IF_ERROR_RETURN
   3260                     (soc_tomahawk3_l0_cos_set(unit, port, queue, cos[queue]));
   3261             }
   3262 
   3263             LOG_INFO(BSL_LS_SOC_COSQ,
   3264                 (BSL_META_U(unit, "Attach port %d to profile %d\n"),
   3265                  port, profile));
   3266             SOC_IF_ERROR_RETURN
   3267                 (soc_tomahawk3_sched_profile_attach(unit, port, profile));
   3268         }
   3269     }
   3270     return SOC_E_NONE;
   3271 }
   3272 
   3273 /*
   3274  *Function: soc_tomahawk3_sched_update_reinit
   3275  *Purpose: Wrapper function to set L0->schedq->MMUQ map for a specific profile
   3276  */
   3277 int
   3278 soc_tomahawk3_sched_update_reinit(int unit, int profile, int *L0, int *schedq,
   3279         int *mmuq, int *cos, int *strict_priority, int* fc_is_uc_only)
   3280 {
   3281     int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0};
   3282     int port, queue;
   3283 
   3284     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   3285         return SOC_E_PARAM;
   3286     }
   3287     /*check which ports is using this profile*/
   3288     soc_profile_port_list_get(unit, profile, port_in_profile);
   3289 
   3290     SOC_IF_ERROR_RETURN(soc_cosq_profile_struct_init(unit, profile));
   3291 
   3292     PBMP_ALL_ITER(unit, port) {
   3293         if (port_in_profile[port]) {
   3294             LOG_INFO(BSL_LS_SOC_COSQ,
   3295                 (BSL_META_U(unit, "Port info init for port %0d\n"),
   3296                         port));
   3297             soc_tomahawk3_cosq_port_info_init(unit, port);
   3298         }
   3299     }
   3300 
   3301     for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3302         SOC_IF_ERROR_RETURN
   3303             (soc_tomahawk3_l1_to_l0_profile_set_reinit(unit, profile, L0[queue], schedq[queue],
   3304                                                 port_in_profile));
   3305         SOC_IF_ERROR_RETURN
   3306             (soc_tomahawk3_mmuq_to_schedq_profile_set_reinit(unit, profile, schedq[queue],
   3307                                                       mmuq[queue], port_in_profile));
   3308         L0_TO_COSQ_MAPPING[unit][profile][queue] = cos[queue];
   3309     }
   3310 
   3311     SOC_IF_ERROR_RETURN
   3312         (soc_cosq_sched_policy_reinit(unit, profile));
   3313 
   3314     PBMP_ALL_ITER(unit, port) {
   3315         if (port_in_profile[port]) {
   3316             for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3317                 SOC_IF_ERROR_RETURN
   3318                     (soc_tomahawk3_l0_cos_set(unit, port, queue, cos[queue]));
   3319             }
   3320 
   3321             LOG_INFO(BSL_LS_SOC_COSQ,
   3322                 (BSL_META_U(unit, "Attach port %d to profile %d\n"),
   3323                  port, profile));
   3324             SOC_IF_ERROR_RETURN
   3325                 (soc_tomahawk3_sched_profile_attach_reinit(unit, port, profile));
   3326         }
   3327     }
   3328     return SOC_E_NONE;
   3329 }
   3330 
   3331 
   3332 /*
   3333  *Function: soc_tomahawk3_sched_update_flex_per_port
   3334  *Purpose: Wrapper function to set L0->schedq->MMUQ map for a specific profile
   3335  */
   3336 int
   3337 soc_tomahawk3_sched_update_flex_per_port(int unit, int port, int profile, int *L0, int *schedq,
   3338         int *mmuq, int *cos)
   3339 {
   3340     int queue;
   3341 
   3342     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   3343         return SOC_E_PARAM;
   3344     }
   3345 
   3346     soc_tomahawk3_cosq_port_info_init(unit, port);
   3347 
   3348     for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3349         SOC_IF_ERROR_RETURN
   3350             (soc_tomahawk3_l1_to_l0_profile_set_per_port(unit, port, profile, L0[queue], schedq[queue]));
   3351         SOC_IF_ERROR_RETURN
   3352             (soc_tomahawk3_mmuq_to_schedq_profile_set_per_port(unit, port, schedq[queue],
   3353                                                       mmuq[queue]));
   3354     }
   3355 
   3356     /* Not needed for flex . Done in cosq_port_attach
   3357     SOC_IF_ERROR_RETURN
   3358         (soc_cosq_sched_policy_init(unit, profile, sp_child, sp_parent));
   3359     */
   3360 
   3361     for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3362         SOC_IF_ERROR_RETURN
   3363             (soc_tomahawk3_l0_cos_set(unit, port, queue, cos[queue]));
   3364     }
   3365 
   3366     LOG_INFO(BSL_LS_SOC_COSQ,
   3367         (BSL_META_U(unit, "Attach port %d to profile %d\n"),
   3368          port, profile));
   3369     SOC_IF_ERROR_RETURN
   3370         (soc_tomahawk3_sched_profile_attach(unit, port, profile));
   3371 
   3372     return SOC_E_NONE;
   3373 }
   3374 
   3375 /*
   3376  *Function: soc_tomahawk3_sched_profile_set
   3377  *Purpose: Wrapper function to set L0->schedq->MMUQ map for a specific profile
   3378  */
   3379 int
   3380 soc_tomahawk3_sched_profile_set(int unit, int profile, int L0, int schedq,
   3381         int mmuq)
   3382 {
   3383     int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0};
   3384 
   3385     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   3386         return SOC_E_PARAM;
   3387     }
   3388     /*check which ports is using this profile*/
   3389     soc_profile_port_list_get(unit, profile, port_in_profile);
   3390 
   3391     SOC_IF_ERROR_RETURN
   3392         (soc_tomahawk3_l1_to_l0_profile_set(unit, profile, L0, schedq,
   3393                                             port_in_profile));
   3394     SOC_IF_ERROR_RETURN
   3395         (soc_tomahawk3_mmuq_to_schedq_profile_set(unit, profile, schedq,
   3396                                                   mmuq, port_in_profile));
   3397 
   3398     return SOC_E_NONE;
   3399 }
   3400 
   3401 /*
   3402  *Function: soc_cosq_hierarchy_init
   3403  *Purpose: Wrapper function to setup scheduler hierarchy for the unit
   3404  */
   3405 int
   3406 soc_cosq_hierarchy_init(int unit)
   3407 {
   3408 #define _TH3_MMU_NUM_CPU_QUEUES_PER_COS 4
   3409     int profile = 0;
   3410     int queue, cpu_l1;
   3411     soc_port_t port;
   3412     int i, rv;
   3413     _soc_mmu_cfg_scheduler_profile_t *sched_profile;
   3414     int L0[SOC_TH3_NUM_GP_QUEUES];
   3415     int schedq[SOC_TH3_NUM_GP_QUEUES];
   3416     int mmuq[SOC_TH3_NUM_GP_QUEUES];
   3417     int cos_list[SOC_TH3_NUM_GP_QUEUES];
   3418     int strict_priority[SOC_TH3_NUM_GP_QUEUES];
   3419     int fc_is_uc_only[SOC_TH3_NUM_GP_QUEUES];
   3420     int sched_port_profile_map[SOC_TH3_MAX_NUM_PORTS];
   3421     int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0};
   3422 
   3423     rv = SOC_E_NONE;
   3424 
   3425     /* Override default init from config.bcm */
   3426     sched_profile = soc_mmu_cfg_scheduler_profile_alloc(unit);
   3427     if (!sched_profile) {
   3428         return SOC_E_MEMORY;
   3429     }
   3430 
   3431     /*Map all ports to use profile 0 by default*/
   3432     for (i = 0; i < SOC_TH3_MAX_NUM_PORTS; i++)
   3433         sched_port_profile_map[i] = 0;
   3434 
   3435     /* Override via bcm config */
   3436     rv = _soc_mmu_tomahawk3_scheduler_profile_reset(unit, sched_profile);
   3437     if (rv != SOC_E_NONE) {
   3438         goto exit;
   3439     }
   3440     _soc_mmu_cfg_scheduler_profile_read(unit, sched_profile, sched_port_profile_map);
   3441     rv = _soc_mmu_tomahawk3_scheduler_profile_check(unit, sched_profile);
   3442 
   3443     /* If overriden values break the rules, do back to default */
   3444     if (SOC_FAILURE(rv)) {
   3445         LOG_INFO(BSL_LS_SOC_COSQ,
   3446                 (BSL_META_U(unit, "Override failed Resetting scheduler profile to default init\n")));
   3447         rv = _soc_mmu_tomahawk3_scheduler_profile_reset(unit, sched_profile);
   3448         if (rv != SOC_E_NONE) {
   3449             goto exit;
   3450         }
   3451     }
   3452 
   3453     /* Init */
   3454 
   3455     /*Map ports to profile. Default is profile 0 */
   3456     PBMP_ALL_ITER(unit, port) {
   3457         LOG_INFO(BSL_LS_SOC_COSQ,
   3458             (BSL_META_U(unit, "Attach port %d to profile %d\n"),
   3459              port, sched_port_profile_map[port]));
   3460         rv = soc_tomahawk3_sched_profile_attach(unit, port, sched_port_profile_map[port]);
   3461         if (rv != SOC_E_NONE) {
   3462             goto exit;
   3463         }
   3464     }
   3465 
   3466     for (profile = 0; profile < SOC_TH3_MAX_NUM_SCHED_PROFILE; profile++) {
   3467         soc_tomahawk3_cosq_profile_info_init(unit, profile);
   3468 
   3469         if (sched_profile[profile].valid != 1) {
   3470 
   3471             continue;
   3472         }
   3473 
   3474         rv = _soc_scheduler_profile_mapping_setup(unit, sched_profile, profile,
   3475             L0, schedq, mmuq, cos_list, strict_priority, fc_is_uc_only);
   3476         if (rv != SOC_E_NONE) {
   3477             goto exit;
   3478         }
   3479 
   3480         for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3481             /* initialize per profile structure */
   3482             int cosq_index;
   3483             cosq_index = L0[queue];
   3484             if (cos_list[queue] == -1) {
   3485                 continue;
   3486             }
   3487             th3_sched_profile_info[unit][profile][cosq_index].cos = cos_list[queue];
   3488             th3_sched_profile_info[unit][profile][cosq_index].strict_priority = strict_priority[queue];
   3489             th3_sched_profile_info[unit][profile][cosq_index].fc_is_uc_only = fc_is_uc_only[queue];
   3490             if (th3_sched_profile_info[unit][profile][cosq_index].mmuq[0] == -1) {
   3491                 th3_sched_profile_info[unit][profile][cosq_index].mmuq[0] = mmuq[queue];
   3492             }
   3493             else {
   3494                 th3_sched_profile_info[unit][profile][cosq_index].mmuq[1] = mmuq[queue];
   3495             }
   3496 
   3497             /*initilization of L0.i->schedq.i->mmuq.i*/
   3498             rv = soc_tomahawk3_sched_profile_set(unit, profile, L0[queue], schedq[queue], mmuq[queue]);
   3499             if (rv != SOC_E_NONE) {
   3500                 goto exit;
   3501             }
   3502             L0_TO_COSQ_MAPPING[unit][profile][queue] = cos_list[queue];
   3503         }
   3504         rv = soc_cosq_sched_policy_init(unit, profile);
   3505         if (rv != SOC_E_NONE) {
   3506             goto exit;
   3507         }
   3508 
   3509         /*check which ports is using this profile*/
   3510         soc_profile_port_list_get(unit, profile, port_in_profile);
   3511 
   3512         PBMP_ALL_ITER(unit, port) {
   3513             if (port_in_profile[port]) {
   3514                 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3515                     /* Max number of device ports in TH3 is 160*/
   3516                     if (cos_list[queue] == -1) {
   3517                         continue;
   3518                     }
   3519                     rv = soc_tomahawk3_l0_cos_set(unit, port, queue, cos_list[queue]);
   3520                     if (rv != SOC_E_NONE) {
   3521                         goto exit;
   3522                     }
   3523                 }
   3524             }
   3525         }
   3526     }
   3527 
   3528     /* CPU Port */
   3529     for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3530         for(i = 0; i < _TH3_MMU_NUM_CPU_QUEUES_PER_COS; i++) {
   3531             cpu_l1 = queue * _TH3_MMU_NUM_CPU_QUEUES_PER_COS + i;
   3532             if (cpu_l1 >= SOC_TH3_NUM_CPU_QUEUES) {
   3533                 break;
   3534             } else {
   3535                 rv = soc_tomahawk3_cpu_l1_to_l0_profile_set(unit, 0, cpu_l1);
   3536                 if (rv != SOC_E_NONE) {
   3537                     goto exit;
   3538                 }
   3539             }
   3540         }
   3541     }
   3542 
   3543 exit:
   3544     soc_mmu_cfg_scheduler_profile_free(unit, sched_profile);
   3545 
   3546 #undef _TH3_MMU_NUM_CPU_QUEUES_PER_COS
   3547 
   3548     return rv;
   3549 }
   3550 
   3551 /*
   3552  *Function: soc_cosq_sched_policy_init
   3553  *Purpose: Initialize scheduling discipline in HW and SW structure based on config bcm
   3554  */
   3555 int
   3556 soc_cosq_sched_policy_init(int unit, int profile)
   3557 {
   3558     soc_reg_t reg = INVALIDr;
   3559     uint64 rval;
   3560     int queue_num;
   3561     soc_port_t port;
   3562     int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0};
   3563 
   3564     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   3565         return SOC_E_PARAM;
   3566     }
   3567 
   3568     /*check which ports is using this profile*/
   3569     soc_profile_port_list_get(unit, profile, port_in_profile);
   3570 
   3571     PBMP_ALL_ITER(unit, port) {
   3572         /* Max number of device ports in TH3 is 160*/
   3573         if (!IS_CPU_PORT(unit, port)) {
   3574             if (port_in_profile[port] == 0)
   3575                 continue;
   3576             reg = MMU_QSCH_PORT_CONFIGr;
   3577             SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval));
   3578             soc_reg64_field32_set(unit, reg, &rval, ENABLE_WRRf, 1);
   3579             soc_reg64_field32_set(unit, reg, &rval, SP_L0_CHILDf, 0);
   3580             soc_reg64_field32_set(unit, reg, &rval, SP_L0_PARENTf, 0);
   3581             SOC_IF_ERROR_RETURN
   3582                 (soc_reg64_set(unit, reg, port, 0, rval));
   3583             for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   3584                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   3585                     sched_policy = SOC_TH3_SCHED_MODE_WRR;
   3586                 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[queue_num].
   3587                     sched_policy = SOC_TH3_SCHED_MODE_WRR;
   3588             }
   3589         } else {
   3590             reg = MMU_QSCH_CPU_PORT_CONFIGr;
   3591             SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
   3592             soc_reg64_field32_set(unit, reg, &rval, ENABLE_WRRf, 1);
   3593             soc_reg64_field32_set(unit, reg, &rval, SP_L0f, 0);
   3594             soc_reg64_field32_set(unit, reg, &rval, SP_L1f, 0);
   3595             SOC_IF_ERROR_RETURN
   3596                 (soc_reg64_set(unit, reg, 0, 0, rval));
   3597             for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   3598                 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].
   3599                     sched_policy = SOC_TH3_SCHED_MODE_WRR;
   3600             }
   3601             for (queue_num = 0; queue_num < SOC_TH3_NUM_CPU_QUEUES; queue_num++) {
   3602                 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].
   3603                     sched_policy = SOC_TH3_SCHED_MODE_WRR;
   3604             }
   3605         }
   3606     }
   3607     return SOC_E_NONE;
   3608 }
   3609 
   3610 /*
   3611  *Function: soc_cosq_sched_policy_reinit
   3612  *Purpose: Initialize scheduling discipline in HW and SW structure based on config bcm
   3613  */
   3614 int
   3615 soc_cosq_sched_policy_reinit(int unit, int profile)
   3616 {
   3617     int queue_num;
   3618     soc_port_t port;
   3619     int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0};
   3620 
   3621     if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   3622         return SOC_E_PARAM;
   3623     }
   3624 
   3625     /*check which ports is using this profile*/
   3626     soc_profile_port_list_get(unit, profile, port_in_profile);
   3627 
   3628     PBMP_ALL_ITER(unit, port) {
   3629         /* Max number of device ports in TH3 is 160*/
   3630         if (!IS_CPU_PORT(unit, port)) {
   3631             if (port_in_profile[port] == 0)
   3632                 continue;
   3633             for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   3634                 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].
   3635                     sched_policy = SOC_TH3_SCHED_MODE_WRR;
   3636                 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[queue_num].
   3637                     sched_policy = SOC_TH3_SCHED_MODE_WRR;
   3638             }
   3639         } else {
   3640             for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   3641                 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].
   3642                     sched_policy = SOC_TH3_SCHED_MODE_WRR;
   3643             }
   3644             for (queue_num = 0; queue_num < SOC_TH3_NUM_CPU_QUEUES; queue_num++) {
   3645                 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].
   3646                     sched_policy = SOC_TH3_SCHED_MODE_WRR;
   3647             }
   3648         }
   3649     }
   3650     return SOC_E_NONE;
   3651 }
   3652 
   3653 
   3654 
   3655 /*
   3656  *Function: soc_tomahawk3_schduler_hier_show
   3657  *Purpose: FUnction to display configured hierarchy
   3658  */
   3659 int
   3660 soc_tomahawk3_schduler_hier_show(int unit,int port)
   3661 {
   3662     int queue, queue_num;
   3663 
   3664      if (SOC_PORT_VALID(unit, port)) {
   3665         LOG_CLI(("PORT        L0          COS         SCHEDQ      MMUQ\n"));
   3666         if (IS_CPU_PORT(unit, port)) {
   3667             for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3668                 for (queue_num = 0; queue_num < SOC_TH3_NUM_CPU_QUEUES;
   3669                                                             queue_num++) {
   3670                     if (th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue].
   3671                             children[queue_num] != NULL) {
   3672                         LOG_CLI((BSL_META_U(unit,
   3673                             "%-8d    "), port));
   3674                         LOG_CLI((BSL_META_U(unit,
   3675                             "%-8d    "),
   3676                             th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue].
   3677                             hw_index));
   3678                         LOG_CLI((BSL_META_U(unit,
   3679                             "%-8d    "),
   3680                             th3_cosq_mmu_info[unit]->th3_cpu_port_info.
   3681                             L0[queue].cos));
   3682                         LOG_CLI((BSL_META_U(unit,
   3683                             "%-8d    \n"),
   3684                             queue_num));
   3685                     }
   3686                 }
   3687             }
   3688         } else {
   3689             for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) {
   3690                 /* Max number of device ports in TH3 is 160*/
   3691                 /* coverity[overrun-local] */
   3692                 if (th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue].
   3693                         parent == NULL ||
   3694                     th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue].
   3695                     parent->parent == NULL) {
   3696                     LOG_CLI((BSL_META_U(unit,
   3697                              "%-8d    unknown    unknown    unknown    %d\n"),
   3698                              port, queue));
   3699                 } else {
   3700                     LOG_CLI((BSL_META_U(unit,
   3701                         "%-8d    "), port));
   3702                     LOG_CLI((BSL_META_U(unit,
   3703                         "%-8d    "),
   3704                         th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue].
   3705                         parent->parent->hw_index));
   3706                     LOG_CLI((BSL_META_U(unit,
   3707                         "%-8d    "),
   3708                         th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue].
   3709                         parent->parent->cos));
   3710                     LOG_CLI((BSL_META_U(unit,
   3711                         "%-8d    "),
   3712                         th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue].
   3713                         parent->hw_index));
   3714                     LOG_CLI((BSL_META_U(unit,
   3715                         "%-8d    \n"), queue));
   3716                 }
   3717             }
   3718         }
   3719     } else {
   3720         LOG_CLI(("Invalid port: %d \n", port));
   3721         return SOC_E_PORT;
   3722     }
   3723     return SOC_E_NONE;
   3724 }
   3725 
   3726 
   3727 /*
   3728  *Function: soc_tomahawk3_scheduler_init
   3729  *Purpose: Wrapper for init code
   3730  */
   3731 int
   3732 soc_tomahawk3_scheduler_init(int unit)
   3733 {
   3734     int mode = 2;
   3735     uint32 rval;
   3736     int pipe, voq_fairness_en = 1;
   3737     uint32 pipe_map, itm_map;
   3738     soc_info_t *si = &SOC_INFO(unit);
   3739     int itm, num_valid_itms = 0;
   3740     /* int port, cosq_idx; */
   3741 
   3742     mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, _TH3_MC_Q_MODE_DEFAULT);
   3743     SOC_IF_ERROR_RETURN
   3744         (soc_tomahawk3_mcq_mode_set(unit, mode));
   3745     SOC_IF_ERROR_RETURN
   3746         (soc_cosq_struct_init(unit));
   3747     SOC_IF_ERROR_RETURN
   3748         (soc_cosq_hierarchy_init(unit));
   3749 
   3750     itm_map = si->itm_map;
   3751     for (itm = 0; itm < NUM_ITM(unit); itm++) {
   3752         if (itm_map & (1 << itm)) {
   3753             num_valid_itms++;
   3754         }
   3755     }
   3756     if (num_valid_itms < NUM_ITM(unit)) {
   3757         voq_fairness_en = 0;
   3758     }
   3759 
   3760     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   3761 
   3762     for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) {
   3763         if (pipe_map & (1 << pipe)) {
   3764             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, MMU_QSCH_SPECIAL_CONFIGr,
   3765                         pipe, 0, &rval));
   3766             soc_reg_field_set(unit, MMU_QSCH_SPECIAL_CONFIGr, &rval,
   3767                     ENABLE_THDO_INFOf, voq_fairness_en);
   3768             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_QSCH_SPECIAL_CONFIGr,
   3769                         pipe, 0, rval));
   3770         }
   3771     }
   3772 
   3773     return SOC_E_NONE;
   3774 }
   3775 
   3776 /*Function: soc_tomahawk3_idb_init_update
   3777  *Purpose: IDB init sequence and threhsold configuration
   3778  *Param:
   3779  *  unit: Device unit number
   3780  */
   3781 int
   3782 soc_tomahawk3_idb_init_update(int unit)
   3783 {
   3784     soc_port_schedule_state_t *port_schedule_state;
   3785 
   3786     port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t),
   3787                                     "Tomahawk3 soc_port_schedule_state_t");
   3788     if (port_schedule_state == NULL) {
   3789         return SOC_E_MEMORY;
   3790     }
   3791     sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t));
   3792 
   3793     SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup(unit,
   3794         port_schedule_state));
   3795 
   3796     SOC_IF_ERROR_RETURN(soc_tomahawk3_idb_init(unit, port_schedule_state));
   3797 
   3798     sal_free(port_schedule_state);
   3799 
   3800     return SOC_E_NONE;
   3801 }
   3802 
   3803 /*Function: soc_tomahawk3_cdport_init
   3804  *Purpose: CDPORT init sequence for pm8x50 ports
   3805  *Param:
   3806  *  unit: Device unit number
   3807  */
   3808 int
   3809 soc_tomahawk3_cdport_init (int unit)
   3810 {
   3811     soc_port_schedule_state_t *port_schedule_state;
   3812     int pipe, pm, pmnum;
   3813     soc_info_t *si = &SOC_INFO(unit);
   3814 
   3815     port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t),
   3816                                     "Tomahawk3 soc_port_schedule_state_t");
   3817     if (port_schedule_state == NULL) {
   3818         return SOC_E_MEMORY;
   3819     }
   3820     sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t));
   3821 
   3822     SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup
   3823         (unit, port_schedule_state));
   3824 
   3825     for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) {
   3826         if (!SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   3827             for (pm = 0; pm < _TH3_PBLKS_PER_PIPE; pm++) {
   3828                 pmnum = pipe * _TH3_PBLKS_PER_PIPE + pm;
   3829                 /*Set CDPORT_MAC_MODE based on port speed*/
   3830                 SOC_IF_ERROR_RETURN(soc_tomahawk3_set_cdmac_port_mode(
   3831                       unit, &port_schedule_state->out_port_map, pmnum));
   3832             }
   3833         }
   3834     }
   3835 
   3836     sal_free(port_schedule_state);
   3837     return SOC_E_NONE;
   3838 }
   3839 
   3840 /*Function:
   3841  *  soc_tomahawk3_ep_top_init
   3842  *Purpose:
   3843  *  EP to Dev port map
   3844  *  Initialize cell credits from MMU tpo EDB based on port speed
   3845  *  Set CT class init
   3846  *  EDB start xmit count
   3847  *  EGR_ENABLE.PRT_ENABLE is set
   3848  *Params:
   3849  * unit: Chip unit number
   3850  */
   3851 int
   3852 soc_tomahawk3_ep_top_init(int unit)
   3853 {
   3854     soc_port_schedule_state_t *port_schedule_state;
   3855 
   3856     port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t),
   3857                                     "Tomahawk3 soc_port_schedule_state_t");
   3858     if (port_schedule_state == NULL) {
   3859         return SOC_E_MEMORY;
   3860     }
   3861     sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t));
   3862 
   3863     SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup(unit,
   3864         port_schedule_state));
   3865 
   3866     SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_init(unit, port_schedule_state));
   3867 
   3868     sal_free(port_schedule_state);
   3869     return SOC_E_NONE;
   3870 }
   3871 
   3872 /*Function:
   3873  *  soc_tomahawk3_slot_pipeline_config
   3874  *Purpose:
   3875  *  Configure slot pipieline latency in EP based on chip latency mode
   3876  *  and Core to DPP clock frequency ratio
   3877  *Params:
   3878  * unit: Chip unit number
   3879  */
   3880 int
   3881 soc_tomahawk3_slot_pipeline_config(int unit)
   3882 {
   3883     soc_port_schedule_state_t *port_schedule_state;
   3884     port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t),
   3885                                     "Tomahawk3 soc_port_schedule_state_t");
   3886     if (port_schedule_state == NULL) {
   3887         return SOC_E_MEMORY;
   3888     }
   3889     sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t));
   3890 
   3891     SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup(unit,
   3892         port_schedule_state));
   3893     /*Epost slot pipeline config*/
   3894     SOC_IF_ERROR_RETURN(
   3895         soc_tomahawk3_ep_set_slot_pipeline_config(unit, port_schedule_state));
   3896     /*Ipost slot pipeline config*/
   3897     SOC_IF_ERROR_RETURN(
   3898         soc_tomahawk3_ip_slot_pipeline_config(unit, port_schedule_state));
   3899 
   3900     sal_free(port_schedule_state);
   3901     return SOC_E_NONE;
   3902 }
   3903 
   3904 /*Function:
   3905  *  soc_tomahawk3_enable_ingress_forwarding
   3906  *Purpose:
   3907  *  Enable traffic forwarding to port in IP
   3908  *Params:
   3909  * unit: Chip unit number
   3910  */
   3911 int
   3912 soc_tomahawk3_enable_ingress_forwarding (int unit)
   3913 {
   3914     soc_port_schedule_state_t *port_schedule_state;
   3915         port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t),
   3916                                     "Tomahawk3 soc_port_schedule_state_t");
   3917     if (port_schedule_state == NULL) {
   3918         return SOC_E_MEMORY;
   3919     }
   3920     sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t));
   3921 
   3922     SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup(unit,
   3923         port_schedule_state));
   3924 
   3925     SOC_IF_ERROR_RETURN
   3926         (soc_tomahawk3_en_epc_link_bmap(unit, port_schedule_state));
   3927     SOC_IF_ERROR_RETURN
   3928         (soc_tomahawk3_en_dest_port_bmap(unit, port_schedule_state));
   3929 
   3930     sal_free(port_schedule_state);
   3931     return SOC_E_NONE;
   3932 }
   3933 
   3934 /*
   3935  * Function: _soc_tomahawk3_per_port_speed_encode_program
   3936  * Purpose: Initialize cell pointer memory in MMU during init
   3937  * Param: unit: device number
   3938  *      : port: Global device port number
   3939  *      : port_speed: Port speed in Mbps
   3940  */
   3941 STATIC int
   3942 _soc_tomahawk3_per_port_speed_encode_program(int unit, int port,
   3943         int port_speed)
   3944 {
   3945     struct {
   3946         soc_reg_t ref_reg;
   3947         soc_field_t encode_field;
   3948     } rf_list[] = {
   3949         {MMU_CRB_SRC_PORT_CFGr, PORT_SPEEDf},
   3950         {MMU_EBCTM_EPORT_CT_CFGr, DST_PORT_SPEEDf},
   3951         {MMU_SCB_SOURCE_PORT_CFGr, PORT_SPEEDf},
   3952         {MMU_EBPCC_EPORT_CFGr, DST_PORT_SPEEDf},
   3953         {MMU_EBQS_PORT_CFGr, PORT_SPEEDf},
   3954         {INVALIDr, INVALIDf}
   3955     };
   3956     uint32 rval;
   3957     int i, special_speed_encode_val = 0, speed_encode_val = 0, oqs_speed_encoding = 0;
   3958     soc_reg_t oqs_reg = MMU_OQS_AGER_DST_PORT_MAPr;
   3959 
   3960     /*Retrieve encoding value to be used based on port speed*/
   3961     /* Speed encoding
   3962      *0 - Reserved,
   3963      *1 - 10G,
   3964      *2 - 25G,
   3965      *3 - 40G,
   3966      *4 - 50G,
   3967      *5 - 100G,
   3968      *6 - 200G,
   3969      *7 - 400G
   3970      */
   3971     switch (port_speed) {
   3972         case 400000: speed_encode_val = 7; break;
   3973         case 200000: speed_encode_val = 6; break;
   3974         case 100000: speed_encode_val = 5; break;
   3975         case 50000:  speed_encode_val = 4; break;
   3976         case 40000:  speed_encode_val = 3; break;
   3977         case 25000:  speed_encode_val = 2; break;
   3978         case 10000:  speed_encode_val = 1; break;
   3979         default:     speed_encode_val = 0; break;
   3980     }
   3981     /* SDK-130693: Special configuration needed for ports with
   3982        port speed below 100G in SCB */
   3983     switch (port_speed) {
   3984         case 400000: special_speed_encode_val = 7; break;
   3985         case 200000: special_speed_encode_val = 6; break;
   3986         case 100000: special_speed_encode_val = 5; break;
   3987         case 50000:  special_speed_encode_val = 5; break;
   3988         case 40000:  special_speed_encode_val = 5; break;
   3989         case 25000:  special_speed_encode_val = 5; break;
   3990         case 10000:  special_speed_encode_val = 5; break;
   3991         default:     special_speed_encode_val = 0; break;
   3992     }
   3993     for (i = 0; rf_list[i].ref_reg != INVALIDr; i++) {
   3994         if (!SOC_REG_IS_VALID(unit, rf_list[i].ref_reg)) {
   3995             continue;
   3996         }
   3997         if ((rf_list[i].ref_reg == MMU_EBCTM_EPORT_CT_CFGr) &&
   3998                 ((IS_MANAGEMENT_PORT(unit, port)) ||
   3999                  (IS_CPU_PORT(unit, port)) ||
   4000                  (IS_LB_PORT(unit, port)))) {
   4001             /*Register valid only for non-management front panel ports*/
   4002             continue;
   4003         }
   4004         SOC_IF_ERROR_RETURN
   4005             (soc_reg32_get(unit, rf_list[i].ref_reg, port, 0, &rval));
   4006         if (rf_list[i].ref_reg == MMU_SCB_SOURCE_PORT_CFGr) {
   4007             /* SDK-130693: Special configuration needed for ports with
   4008                port speed below 100G in SCB */
   4009             soc_reg_field_set(unit, rf_list[i].ref_reg, &rval,
   4010                         rf_list[i].encode_field, special_speed_encode_val);
   4011         } else {
   4012             soc_reg_field_set(unit, rf_list[i].ref_reg, &rval,
   4013                         rf_list[i].encode_field, speed_encode_val);
   4014         }
   4015         SOC_IF_ERROR_RETURN
   4016             (soc_reg32_set(unit, rf_list[i].ref_reg, port, 0, rval));
   4017     }
   4018     /*Setup port speed in  OQS ager based on 4-speed encoding*/
   4019     /*port_speed encoding - 0:<=50GE, 1:100GE, 2:200GE, 3:400GE*/
   4020     if (port_speed <= 50000) {
   4021         oqs_speed_encoding = 0;
   4022     } else if (port_speed == 100000) {
   4023         oqs_speed_encoding = 1;
   4024     } else if (port_speed == 200000) {
   4025         oqs_speed_encoding = 2;
   4026     } else if (port_speed == 400000) {
   4027         oqs_speed_encoding = 3;
   4028     } else {
   4029         return SOC_E_PARAM;
   4030     }
   4031     SOC_IF_ERROR_RETURN
   4032         (soc_reg32_get(unit, oqs_reg, port, 0, &rval));
   4033     soc_reg_field_set(unit, oqs_reg, &rval, PORT_SPEEDf, oqs_speed_encoding);
   4034     SOC_IF_ERROR_RETURN
   4035         (soc_reg32_set(unit, oqs_reg, port, 0, rval));
   4036     return SOC_E_NONE;
   4037 }
   4038 
   4039 /*
   4040  * Function: soc_tomahawk3_tm_port_speed_encoding
   4041  * Purpose: Setup port speed encoding in different MMU stages
   4042  * Param: unit: device number
   4043  */
   4044 int
   4045 soc_tomahawk3_tm_port_speed_encoding(int unit)
   4046 {
   4047     int port, speed;
   4048     soc_info_t *si = &SOC_INFO(unit);
   4049     int speed_encode;
   4050     /* recommended values of ager_limit based on speed encoding*/
   4051     int ager_limit[4] = {4, 4, 3, 2};
   4052     soc_reg_t reg;
   4053     soc_field_t field;
   4054     int index, cpu_ager_limit;
   4055     uint32 rval = 0;
   4056 
   4057     /*Front panel ports*/
   4058     PBMP_PORT_ITER(unit, port) {
   4059         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   4060             continue;
   4061         }
   4062         speed = si->port_speed_max[port];
   4063         SOC_IF_ERROR_RETURN
   4064         (_soc_tomahawk3_per_port_speed_encode_program(unit, port, speed));
   4065     }
   4066     /*LB ports*/
   4067 #define _TH3_SPL_PORT_SPEED 10000
   4068     PBMP_LB_ITER(unit, port) {
   4069         SOC_IF_ERROR_RETURN
   4070         (_soc_tomahawk3_per_port_speed_encode_program(unit, port,
   4071                                                       _TH3_SPL_PORT_SPEED));
   4072     }
   4073     /*CPU port*/
   4074 #define _TH3_CPU_PORT_NUM 0
   4075     SOC_IF_ERROR_RETURN
   4076     (_soc_tomahawk3_per_port_speed_encode_program(unit, _TH3_CPU_PORT_NUM,
   4077                                                   _TH3_SPL_PORT_SPEED));
   4078 #undef _TH3_CPU_PORT_NUM
   4079 #undef _TH3_SPL_PORT_SPEED
   4080 
   4081     /* Configure OQS ager limit based on port speed encoding. */
   4082     reg = MMU_OQS_AGER_LIMITr;
   4083     field = AGER_LIMITf;
   4084     /* OQS port_speed encoding - 0:<=50GE, 1:100GE, 2:200GE, 3:400GE*/
   4085     for (speed_encode = 0; speed_encode < 4; speed_encode++) {
   4086         /* Program same ager limit for 2 indices mapped to the same speed encode */
   4087         /* indexed by {port_speed[1:0], HP_MMUQ[0]} */
   4088         for (index = (speed_encode * 2); index < ((speed_encode + 1) * 2);
   4089                 index++) {
   4090             rval = 0;
   4091             SOC_IF_ERROR_RETURN
   4092                 (soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   4093             soc_reg_field_set(unit, reg, &rval, field, ager_limit[speed_encode]);
   4094             SOC_IF_ERROR_RETURN
   4095                 (soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   4096         }
   4097     }
   4098     /* Ager limit config for CPU port */
   4099     index = 8;
   4100     rval = 0;
   4101     cpu_ager_limit = 4;
   4102     SOC_IF_ERROR_RETURN
   4103         (soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   4104     soc_reg_field_set(unit, reg, &rval, field, cpu_ager_limit);
   4105     SOC_IF_ERROR_RETURN
   4106         (soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   4107 
   4108     return SOC_E_NONE;
   4109 }
   4110 
   4111 /*
   4112  * Function to Set Parent(L0) for a given L1 queue of the CPU port
   4113  * Note: Only child @ L1 level is supported.
   4114  * Because only L1 level queues can be attached to different parent (L0.0-L0.9)
   4115  * of the CPU port.
   4116  */
   4117 int
   4118 soc_th3_cosq_cpu_parent_set(int unit, int child_index, int child_level,
   4119                            int parent_index)
   4120 {
   4121     if (child_level != SOC_TH3_NODE_LVL_L1) {
   4122         /* Only child at L1 are allowed to move */
   4123         return SOC_E_PARAM;
   4124     }
   4125     soc_tomahawk3_cpu_l1_to_l0_profile_set(unit, parent_index, child_index);
   4126 
   4127     return SOC_E_NONE;
   4128 }
   4129 
   4130 int
   4131 soc_th3_sched_weight_set(int unit, int port, int level,
   4132                         int index, int weight, int mc)
   4133 {
   4134     soc_info_t *si;
   4135     soc_mem_t mem = INVALIDm;
   4136     uint32 entry[SOC_MAX_MEM_WORDS];
   4137     int pipe, local_mmu_port;
   4138 
   4139     si = &SOC_INFO(unit);
   4140 
   4141     pipe = si->port_pipe[port];
   4142     local_mmu_port = SOC_TH3_MMU_LOCAL_PORT(unit, port);
   4143 
   4144     if (level == SOC_TH3_NODE_LVL_L0) {
   4145         mem = MMU_QSCH_L0_WEIGHT_MEMm;
   4146         if (IS_CPU_PORT(unit, port)) {
   4147             index = TH3_MMU_CPU_MCQ_OFFSET + index;
   4148         } else if (IS_LB_PORT(unit, port)) {
   4149             index = TH3_MMU_LB_MCQ_OFFSET + index;
   4150         } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) {
   4151             index = TH3_MMU_MGMT_Q_OFFSET + index;
   4152         } else {
   4153             index = (local_mmu_port  * SOC_TH3_NUM_GP_QUEUES) + index;
   4154         }
   4155     } else if (level == SOC_TH3_NODE_LVL_L1) {
   4156         mem = MMU_QSCH_L1_WEIGHT_MEMm;
   4157 
   4158         if (IS_CPU_PORT(unit, port)) {
   4159             index = TH3_MMU_CPU_MCQ_OFFSET + index;
   4160         } else if (IS_LB_PORT(unit, port)) {
   4161             index = TH3_MMU_LB_MCQ_OFFSET + index;
   4162         } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) {
   4163             index = TH3_MMU_MGMT_Q_OFFSET + index;
   4164         } else {
   4165             index = (local_mmu_port  * SOC_TH3_NUM_GP_QUEUES) + index;
   4166         }
   4167     } else {
   4168         return SOC_E_PARAM;
   4169     }
   4170 
   4171     mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe];
   4172 
   4173     SOC_IF_ERROR_RETURN
   4174         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
   4175     soc_mem_field32_set(unit, mem, &entry, WEIGHTf, weight);
   4176     SOC_IF_ERROR_RETURN
   4177         (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry));
   4178 
   4179     return SOC_E_NONE;
   4180 }
   4181 
   4182 /*
   4183  * Function to Get Parent(L0) for a given L1 queue of the CPU port
   4184  * Note: Only child @ L1 level is supported.
   4185  * Because only L1 level queues can be attached to different parent (L0.0-L0.9)
   4186  * of the CPU port.
   4187  */
   4188 int
   4189 soc_th3_cosq_cpu_parent_get(int unit, int child_index, int child_level,
   4190                            int *parent_index)
   4191 {
   4192     soc_reg_t reg = MMU_QSCH_CPU_L1_TO_L0_MAPPINGr;
   4193     uint32 rval = 0;
   4194 
   4195     if (child_level != SOC_TH3_NODE_LVL_L1) {
   4196         /* Only child at L1 are allowed to move */
   4197         return SOC_E_PARAM;
   4198     }
   4199     /* Set the L1 queue's parent to the given L0 node */
   4200     SOC_IF_ERROR_RETURN
   4201         (soc_reg32_get(unit, reg, 0, child_index, &rval));
   4202     *parent_index = soc_reg_field_get(unit, reg, rval, SELECTf);
   4203 
   4204     return SOC_E_NONE;
   4205 }
   4206 
   4207 /*
   4208  * Function to Get Parent(L0) for a given L1 queue of any FP port
   4209  * Note: Only child @ L1 level is supported.
   4210  * Because only L1 level queues can be attached to different parent (L0.0-L0.11)
   4211  * of the FP port.
   4212  */
   4213 int
   4214 soc_th3_cosq_parent_get(int unit, int port, int child_index, int child_level,
   4215                            int *parent_index)
   4216 {
   4217     soc_reg_t reg = MMU_QSCH_PORT_CONFIGr;
   4218     uint64 rval_64;
   4219     uint32 mapping = 0;
   4220     soc_reg_t prof_reg = MMU_MTRO_MMUQ_SCHQ_CFGr;
   4221     soc_reg_t map_reg = MMU_MTRO_MMUQ_SCHQ_PROFILEr;
   4222     int port_profile = 0;
   4223     uint32 rval;
   4224     soc_field_t schedq_field[12] = {
   4225         SCH_Q_NUM_0f, SCH_Q_NUM_1f,
   4226         SCH_Q_NUM_2f, SCH_Q_NUM_3f,
   4227         SCH_Q_NUM_4f, SCH_Q_NUM_5f,
   4228         SCH_Q_NUM_6f, SCH_Q_NUM_7f,
   4229         SCH_Q_NUM_8f, SCH_Q_NUM_9f,
   4230         SCH_Q_NUM_10f, SCH_Q_NUM_11f,
   4231     };
   4232 
   4233 
   4234     if (child_level == SOC_TH3_NODE_LVL_L1) {
   4235         /* Set the L1 queue's parent to the given L0 node */
   4236         SOC_IF_ERROR_RETURN
   4237             (soc_reg64_get(unit, reg, 0, port, &rval_64));
   4238         mapping = soc_reg64_field32_get(unit, reg, rval_64, L1_TO_L0_MAPPINGf);
   4239 
   4240         if ((mapping & (1 << child_index)) == 0) {
   4241             *parent_index = child_index;
   4242         } else {
   4243             *parent_index = child_index+1;
   4244         }
   4245     } else if (child_level == SOC_TH3_NODE_LVL_L2) {
   4246         /* Retrieve schedq mapped to MMUQ*/
   4247         rval = 0;
   4248         SOC_IF_ERROR_RETURN
   4249             (soc_reg32_get(unit, prof_reg, port, 0, &rval));
   4250         port_profile = soc_reg_field_get(unit, prof_reg, rval, Q_PROFILE_SELf);
   4251         SOC_IF_ERROR_RETURN
   4252             (soc_reg64_get(unit, map_reg, REG_PORT_ANY, port_profile, &rval_64));
   4253         *parent_index = soc_reg64_field32_get(unit, map_reg, rval_64,
   4254                 schedq_field[child_index]);
   4255 
   4256     } else {
   4257         return SOC_E_PARAM;
   4258     }
   4259 
   4260     return SOC_E_NONE;
   4261 }
   4262 
   4263 int
   4264 soc_th3_sched_weight_get(int unit, int port, int level,
   4265                         int index, int *weight, int mc)
   4266 {
   4267     soc_info_t *si;
   4268     soc_mem_t mem = INVALIDm;
   4269     uint32 entry[SOC_MAX_MEM_WORDS];
   4270     int pipe, local_mmu_port;
   4271 
   4272     si = &SOC_INFO(unit);
   4273 
   4274     pipe = si->port_pipe[port];
   4275     local_mmu_port = SOC_TH3_MMU_LOCAL_PORT(unit, port);
   4276 
   4277     if (level == SOC_TH3_NODE_LVL_L0) {
   4278         mem = MMU_QSCH_L0_WEIGHT_MEMm;
   4279     } else if (level == SOC_TH3_NODE_LVL_L1) {
   4280         mem = MMU_QSCH_L1_WEIGHT_MEMm;
   4281     } else {
   4282         return SOC_E_PARAM;
   4283     }
   4284 
   4285     if (IS_CPU_PORT(unit, port)) {
   4286         index = TH3_MMU_CPU_MCQ_OFFSET + index;
   4287     } else if (IS_LB_PORT(unit, port)) {
   4288         index = TH3_MMU_LB_MCQ_OFFSET + index;
   4289     } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) {
   4290         index = TH3_MMU_MGMT_Q_OFFSET + index;
   4291     } else {
   4292         index = (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + index;
   4293     }
   4294 
   4295     mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe];
   4296     SOC_IF_ERROR_RETURN
   4297         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
   4298     *weight = soc_mem_field32_get(unit, mem, &entry, WEIGHTf);
   4299 
   4300     return SOC_E_NONE;
   4301 }
   4302 
   4303 int
   4304 soc_th3_cosq_sched_mode_get(int unit, soc_port_t port, int level, int index,
   4305                            soc_th3_sched_mode_e* mode, int* weight, int mc)
   4306 {
   4307     soc_reg_t reg = INVALIDr;
   4308     uint32 wrr_mask;
   4309     uint64 rval;
   4310     soc_field_t reg_field = INVALIDf;
   4311     LOG_INFO(BSL_LS_SOC_COSQ,
   4312              (BSL_META_U(unit,
   4313                  "START: soc_th3_cosq_sched_mode_get Port:%d Level:%d index=%d\n"),
   4314                  port, level, index));
   4315 
   4316     /* selection between SP and WxRR is based on weight property. */
   4317     SOC_IF_ERROR_RETURN(soc_th3_sched_weight_get(unit, port,
   4318                                                 level, index, weight, mc));
   4319 
   4320     if (IS_CPU_PORT(unit, port)) {
   4321         reg = MMU_QSCH_CPU_PORT_CONFIGr;
   4322     } else {
   4323         reg = MMU_QSCH_PORT_CONFIGr;
   4324     }
   4325     if (level == SOC_TH3_NODE_LVL_L1) {
   4326         if (IS_CPU_PORT(unit, port)) {
   4327             reg_field = SP_L1f;
   4328         } else {
   4329             reg_field = SP_L0_PARENTf;
   4330         }
   4331         if (IS_CPU_PORT(unit, port)) {
   4332             int parent_index = 0;
   4333              SOC_IF_ERROR_RETURN
   4334                 (soc_th3_cosq_cpu_parent_get(unit, index, SOC_TH3_NODE_LVL_L1,
   4335                                             &parent_index));
   4336             index = parent_index;
   4337         } else {
   4338             int parent_index = 0;
   4339              SOC_IF_ERROR_RETURN
   4340                 (soc_th3_cosq_parent_get(unit, port, index, SOC_TH3_NODE_LVL_L1,
   4341                                             &parent_index));
   4342             index = parent_index;
   4343         }
   4344     } else if (level == SOC_TH3_NODE_LVL_L0) {
   4345         if (IS_CPU_PORT(unit, port)) {
   4346             reg_field = SP_L0f;
   4347         } else {
   4348             reg_field = SP_L0_CHILDf;
   4349         }
   4350     } else {
   4351         return SOC_E_PARAM;
   4352     }
   4353 
   4354     SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval));
   4355     wrr_mask = soc_reg64_field32_get(unit, reg, rval, reg_field);
   4356     if (wrr_mask & (1 << index)) {
   4357         *mode = SOC_TH3_SCHED_MODE_STRICT;
   4358     } else {
   4359         wrr_mask = soc_reg64_field32_get(unit, reg, rval, ENABLE_WRRf);
   4360         if (wrr_mask) {
   4361             *mode = SOC_TH3_SCHED_MODE_WRR;
   4362         } else {
   4363             *mode = SOC_TH3_SCHED_MODE_WERR;
   4364         }
   4365 
   4366     }
   4367     LOG_INFO(BSL_LS_SOC_COSQ,
   4368              (BSL_META_U(unit,
   4369                  "END: soc_th3_cosq_sched_mode_get Port:%d Level:%d index=%d MODE=%d WT=%d\n"),
   4370                  port, level, index, *mode, *weight));
   4371 
   4372     return SOC_E_NONE;
   4373 }
   4374 
   4375 int
   4376 soc_th3_cosq_sched_mode_set(int unit, soc_port_t port, int level, int index,
   4377                            soc_th3_sched_mode_e mode, int weight, int mc)
   4378 {
   4379     soc_reg_t reg = INVALIDr;
   4380     uint32 wrr_mask;
   4381     uint64 rval;
   4382     soc_field_t reg_field = INVALIDf;
   4383 
   4384     LOG_INFO(BSL_LS_SOC_COSQ,
   4385              (BSL_META_U(unit,
   4386                  "START: soc_th3_cosq_sched_mode_set Port:%d Level:%d index=%d MODE=%d WT=%d\n"),
   4387                  port, level, index, mode, weight));
   4388 
   4389     /* selection between SP and WxRR is based on weight property. */
   4390     SOC_IF_ERROR_RETURN(soc_th3_sched_weight_set(unit, port,
   4391                                                 level, index, weight, mc));
   4392 
   4393     if (IS_CPU_PORT(unit, port)) {
   4394         reg = MMU_QSCH_CPU_PORT_CONFIGr;
   4395     } else {
   4396         reg = MMU_QSCH_PORT_CONFIGr;
   4397     }
   4398 
   4399     if (level == SOC_TH3_NODE_LVL_L0) {
   4400         if (IS_CPU_PORT(unit, port)) {
   4401             reg_field = SP_L0f;
   4402         } else {
   4403             reg_field = SP_L0_CHILDf;
   4404         }
   4405         /* index = 0; */
   4406     } else if (level == SOC_TH3_NODE_LVL_L1) {
   4407         if (IS_CPU_PORT(unit, port)) {
   4408             reg_field = SP_L1f;
   4409         } else {
   4410             reg_field = SP_L0_PARENTf;
   4411         }
   4412         if (IS_CPU_PORT(unit, port)) {
   4413             int parent_index = 0;
   4414             reg = MMU_QSCH_CPU_PORT_CONFIGr;
   4415             SOC_IF_ERROR_RETURN
   4416                 (soc_th3_cosq_cpu_parent_get(unit, index, SOC_TH3_NODE_LVL_L1,
   4417                                             &parent_index));
   4418             index = parent_index;
   4419         } else {
   4420             int parent_index = 0;
   4421             reg = MMU_QSCH_PORT_CONFIGr;
   4422             SOC_IF_ERROR_RETURN
   4423                 (soc_th3_cosq_parent_get(unit, port, index, SOC_TH3_NODE_LVL_L1,
   4424                                             &parent_index));
   4425             index = parent_index;
   4426         }
   4427     } else {
   4428         return SOC_E_PARAM;
   4429     }
   4430 
   4431     LOG_INFO(BSL_LS_SOC_COSQ,
   4432              (BSL_META_U(unit,
   4433                  "END: soc_th3_cosq_sched_mode_set Port:%d Level:%d index=%d MODE=%d WT=%d\n"),
   4434                  port, level, index, mode, weight));
   4435 
   4436     SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval));
   4437     if (mode == SOC_TH3_SCHED_MODE_WRR) {
   4438         soc_reg64_field32_set(unit, reg, &rval, ENABLE_WRRf, 1);
   4439         wrr_mask = soc_reg64_field32_get(unit, reg, rval, reg_field);
   4440         wrr_mask &= ~(1 << index);
   4441         soc_reg64_field32_set(unit, reg, &rval, reg_field, wrr_mask);
   4442     } else if (mode == SOC_TH3_SCHED_MODE_WERR) {
   4443         soc_reg64_field32_set(unit, reg, &rval, ENABLE_WRRf, 0);
   4444         wrr_mask = soc_reg64_field32_get(unit, reg, rval, reg_field);
   4445         wrr_mask &= ~(1 << index);
   4446         soc_reg64_field32_set(unit, reg, &rval, reg_field, wrr_mask);
   4447     } else {
   4448         wrr_mask = soc_reg64_field32_get(unit, reg, rval, reg_field);
   4449         wrr_mask |= (1 << index);
   4450         soc_reg64_field32_set(unit, reg, &rval, reg_field, wrr_mask);
   4451     }
   4452 
   4453     SOC_IF_ERROR_RETURN(soc_reg64_set(unit, reg, port, 0, rval));
   4454 
   4455     /* WAR: set port 32 besides CPU reg,
   4456        as CPU WRED takes some info from port 32.
   4457     if (reg2 != INVALIDr) {
   4458         SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg2, port, 0, &rval));
   4459         wrr_mask = soc_reg_field_get(unit, reg2, rval, ENABLE_WRRf);
   4460         wrr_mask &= ~(1 << index);
   4461         wrr_mask |= (fval << index);
   4462         soc_reg64_field32_set(unit, reg2, &rval, ENABLE_WRRf, wrr_mask);
   4463         SOC_IF_ERROR_RETURN(soc_reg64_set(unit, reg2, port, 0, rval));
   4464     }
   4465        Note: Do not need this workaround in TH3? */
   4466 
   4467     return SOC_E_NONE;
   4468 }
   4469 
   4470 
   4471 /*
   4472  *Function: soc_tomahawk3_scb_init
   4473  *Purpose: Wrapper for init code
   4474  */
   4475 int
   4476 soc_tomahawk3_scb_init(int unit)
   4477 {
   4478     soc_reg_t reg;
   4479     uint32 rval;
   4480     uint16 dev_id;
   4481     uint8 rev_id;
   4482 
   4483     soc_cm_get_id(unit, &dev_id, &rev_id);
   4484 
   4485     /* SDK-130693: Special configuration needed for ports with
   4486        port speed below 100G in SCB */
   4487     reg = MMU_SCB_ARBITER_AGER_CFGr;
   4488     SOC_IF_ERROR_RETURN
   4489         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4490     soc_reg_field_set(unit, reg, &rval, AGER_LIMIT_50f, 0);
   4491     SOC_IF_ERROR_RETURN
   4492             (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   4493 
   4494     if (rev_id != BCM56980_A0_REV_ID) {
   4495         reg = MMU_SCB_SRAF_FIFO_THRESHr;
   4496         SOC_IF_ERROR_RETURN
   4497             (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4498         soc_reg_field_set(unit, reg, &rval, THRESHf, 12);
   4499         SOC_IF_ERROR_RETURN
   4500                 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   4501     }
   4502     return SOC_E_NONE;
   4503 }
   4504 
   4505 /*
   4506  *Function: soc_tomahawk3_wred_init
   4507  *Purpose: Wrapper for init code
   4508  */
   4509 int
   4510 soc_tomahawk3_wred_init(int unit)
   4511 {
   4512     soc_reg_t reg;
   4513     uint64 rval;
   4514 
   4515     /* initiate Queue length update from both THDO simultaneously */
   4516     reg = MMU_WRED_CONFIG_READYr;
   4517     SOC_IF_ERROR_RETURN
   4518         (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4519     soc_reg64_field32_set(unit, reg, &rval, WRED_READYf, 1);
   4520     SOC_IF_ERROR_RETURN
   4521             (soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval));
   4522 
   4523     return SOC_E_NONE;
   4524 }
   4525 
   4526 /*
   4527  *Function: soc_tomahawk3_rl_init
   4528  *Purpose: Wrapper for init code
   4529  */
   4530 int
   4531 soc_tomahawk3_rl_init(int unit)
   4532 {
   4533     uint32 rval;
   4534 
   4535     /* SDK-141834 SWAR to change MMU_RL_CONFIG value */
   4536     SOC_IF_ERROR_RETURN
   4537         (soc_reg32_get(unit, MMU_RL_CONFIGr, REG_PORT_ANY, 0, &rval));
   4538     soc_reg_field_set(unit, MMU_RL_CONFIGr, &rval, ITREORDER_LIMITf, 511);
   4539     SOC_IF_ERROR_RETURN
   4540             (soc_reg32_set(unit, MMU_RL_CONFIGr, REG_PORT_ANY, 0, rval));
   4541 
   4542     return SOC_E_NONE;
   4543 }
   4544 
   4545 /*
   4546  * Function: soc_tomahawk3_get_cos_for_mmu_queue
   4547  * Purpose: Helper function that returns the cos value for an mmuq
   4548 */
   4549 
   4550 int soc_tomahawk3_get_cos_for_mmu_queue(int unit, int profile, int mmuq)
   4551 {
   4552     int queue_num;
   4553     int cos = -1;
   4554 
   4555     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   4556         if (th3_sched_profile_info[unit][profile][queue_num].mmuq[0] == mmuq) {
   4557             cos = th3_sched_profile_info[unit][profile][queue_num].cos;
   4558             break;
   4559         }
   4560         if (th3_sched_profile_info[unit][profile][queue_num].mmuq[1] == mmuq) {
   4561             cos = th3_sched_profile_info[unit][profile][queue_num].cos;
   4562             break;
   4563         }
   4564     }
   4565     return cos;
   4566 
   4567 }
   4568 
   4569 /*
   4570  * Function: soc_tomahawk3_get_fc_only_uc_for_cos
   4571  * Purpose:
   4572  *   Helper function that returns the fc_only_uc for a given {profile, cos}
   4573 */
   4574 
   4575 int
   4576 soc_tomahawk3_get_fc_only_uc_for_cos(int unit, int profile, int cos)
   4577 {
   4578     int queue_num;
   4579     int fc_only_uc = 0;
   4580 
   4581     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   4582         if (th3_sched_profile_info[unit][profile][queue_num].cos == cos) {
   4583             fc_only_uc =
   4584                 th3_sched_profile_info[unit][profile][queue_num].fc_is_uc_only;
   4585             break;
   4586         }
   4587     }
   4588     return fc_only_uc;
   4589 
   4590 }
   4591 
   4592 /*
   4593  * Function: soc_tomahawk3_get_sp_for_cos
   4594  * Purpose:
   4595  *   Helper function that returns the strict priority for a given {profile, cos}
   4596 */
   4597 
   4598 int
   4599 soc_tomahawk3_get_sp_for_cos(int unit, int profile, int cos)
   4600 {
   4601     int queue_num;
   4602     int sp = 0;
   4603 
   4604     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   4605         if (th3_sched_profile_info[unit][profile][queue_num].cos == cos) {
   4606             sp =
   4607                 th3_sched_profile_info[unit][profile][queue_num].strict_priority;
   4608             break;
   4609         }
   4610     }
   4611     return sp;
   4612 
   4613 }
   4614 
   4615 int soc_tomahawk3_profile_exists(int unit, int profile)
   4616 {
   4617     int profile_exists = 0;
   4618     int queue_num;
   4619 
   4620     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   4621         if (th3_sched_profile_info[unit][profile][queue_num].cos != -1) {
   4622             profile_exists = 1;
   4623             break;
   4624         }
   4625     }
   4626     return profile_exists;
   4627 }
   4628 
   4629 int
   4630 soc_tomahawk3_get_sched_profile_max_cos(int unit, int profile) {
   4631     int max_cos = 0;
   4632     int queue_num, cos;
   4633 
   4634     for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) {
   4635         cos = th3_sched_profile_info[unit][profile][queue_num].cos;
   4636         if (cos > max_cos) {
   4637             max_cos = cos;
   4638         }
   4639     }
   4640     return max_cos;
   4641 }
   4642 
   4643 STATIC int
   4644 soc_transmit_rqe_flush_packet (int unit, int rqe_num) {
   4645     bcm_pkt_t *pkt = NULL;
   4646     uint8 *payload;
   4647     int rv = SOC_E_NONE;
   4648     bcm_port_t dest_port = _TH3_MMU_SPARE_DST_PORT; /* Use spare port as destination */
   4649 
   4650     /* Create test packet */
   4651     pkt = soc_cm_salloc(unit, sizeof(bcm_pkt_t), "pkt buffer");
   4652     if (pkt == NULL) {
   4653         return SOC_E_MEMORY;
   4654     }
   4655     payload = soc_cm_salloc(unit, 68,
   4656                             "pkt alloc data");
   4657     if (payload == NULL) {
   4658         soc_cm_sfree(unit, pkt);
   4659         return BCM_E_FAIL;
   4660     }
   4661     sal_memset(payload, 1, 68);
   4662     BCM_PKT_ONE_BUF_SETUP(pkt, payload, 68);
   4663 
   4664     pkt->flags = BCM_TX_LINKDOWN_TRANSMIT;
   4665     pkt->flags2 = BCM_PKT_F2_MC_QUEUE;
   4666     pkt->flags |= BCM_PKT_F_ROUTED;
   4667     pkt->flags |= BCM_TX_PRIO_INT;
   4668     pkt->unit = unit;
   4669     pkt->call_back = NULL;
   4670     BCM_PKT_TX_LEN_SET(pkt, 68);
   4671     pkt->vlan = 1;
   4672     pkt->prio_int = rqe_num;
   4673     pkt->cos = 0;
   4674     pkt->rqe_q_num = rqe_num;
   4675     SOC_PBMP_CLEAR(pkt->tx_l3pbmp);
   4676     SOC_PBMP_CLEAR(pkt->tx_pbmp);
   4677     SOC_PBMP_PORT_ADD(pkt->tx_l3pbmp, dest_port);
   4678     SOC_PBMP_PORT_ADD(pkt->tx_pbmp, dest_port);
   4679     pkt->dest_port = dest_port;
   4680     pkt->dst_gport = dest_port;
   4681 
   4682     /* LB HDR fields for SOBMH packet*/
   4683     pkt->flags2 |= BCM_PKT_F2_CPU_TX_PROC;
   4684     pkt->rx_port = _TH3_MMU_SPARE_SRC_PORT; /* Spare port from ITM1*/
   4685     pkt->txprocmh_destination_type = 15;
   4686     pkt->txprocmh_destination = dest_port;
   4687     pkt->txprocmh_qos_fields_valid = 1;
   4688 
   4689     pkt->pkt_data[0].data[12] = 0x81;
   4690     pkt->pkt_data[0].data[13] = 0x00;
   4691     pkt->pkt_data[0].data[14] = 0x00;
   4692     pkt->pkt_data[0].data[15] = 0x01;
   4693 
   4694     rv = bcm_common_tx(unit, pkt, NULL);
   4695 
   4696     if (payload != NULL) {
   4697         soc_cm_sfree(unit, payload);
   4698     }
   4699     if (pkt != NULL) {
   4700         soc_cm_sfree(unit, pkt);
   4701     }
   4702 
   4703     return rv;
   4704 }
   4705 
   4706 int
   4707 soc_tomahawk3_cpu_tx_rqe_queues_for_flush (int unit, int itm) {
   4708     int num_rqe_queues;
   4709     int rqe_q, i;
   4710     int num_packets = 7; /*Transmit 7 packets fro each queue*/
   4711     uint16 dev_id;
   4712     uint8 rev_id;
   4713     int rv = SOC_E_NONE;
   4714     uint32 rd_val, rval, wr_val;
   4715     soc_reg_t reg_int_stat = MMU_RQE_INT_STATr;
   4716     soc_reg_t reg_int_en = MMU_RQE_INT_ENr;
   4717     int invld_dest_en = 0;
   4718     int itm_int;
   4719     soc_info_t *si = &SOC_INFO(unit);
   4720     uint32 itm_map = si->itm_map;
   4721     int count = 0;
   4722     bcm_pbmp_t link_bmap;
   4723     uint32 entry[SOC_MAX_MEM_FIELD_WORDS];
   4724 
   4725     /* Disable RQE_INVALID_DEST interrupt */
   4726     SOC_IF_ERROR_RETURN(
   4727             soc_reg32_rawport_get(unit, reg_int_en, REG_PORT_ANY, 0, &rval));
   4728     invld_dest_en = soc_reg_field_get(unit, reg_int_en, rval, INVALID_DESTf);
   4729     wr_val = 0;
   4730     soc_reg_field_set(unit, reg_int_en, &rval, INVALID_DESTf, wr_val);
   4731     SOC_IF_ERROR_RETURN(
   4732             soc_reg32_rawport_set(unit, reg_int_en, REG_PORT_ANY, 0, rval));
   4733 
   4734     /* Add Spare ports 158 & 98 to IP's  EPC_LINK_BMAP */
   4735     soc_mem_lock(unit, EPC_LINK_BMAPm);
   4736     rv = soc_mem_read(unit, EPC_LINK_BMAPm, MEM_BLOCK_ANY, 0, entry);
   4737     if (rv != SOC_E_NONE) {
   4738         soc_mem_unlock(unit, EPC_LINK_BMAPm);
   4739         return SOC_E_INTERNAL;
   4740     }
   4741     soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf,
   4742             &link_bmap);
   4743     SOC_PBMP_PORT_ADD(link_bmap, _TH3_MMU_SPARE_DST_PORT);
   4744     SOC_PBMP_PORT_ADD(link_bmap, _TH3_MMU_SPARE_SRC_PORT);
   4745     soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf,
   4746             &link_bmap);
   4747     rv = soc_mem_write(unit, EPC_LINK_BMAPm, MEM_BLOCK_ALL, 0, &entry);
   4748     soc_mem_unlock(unit, EPC_LINK_BMAPm);
   4749     if (rv != SOC_E_NONE) {
   4750         return SOC_E_INTERNAL;
   4751     }
   4752 
   4753     /* Add Spare ports 158 & 98 to IP's  ING_DEST_PORT_ENABLE */
   4754     soc_mem_lock(unit, ING_DEST_PORT_ENABLEm);
   4755     rv = soc_mem_read(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ANY,
   4756                              0, entry);
   4757     if (rv != SOC_E_NONE) {
   4758         soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm);
   4759         return SOC_E_INTERNAL;
   4760     }
   4761     soc_mem_pbmp_field_get(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf,
   4762             &link_bmap);
   4763     BCM_PBMP_PORT_ADD(link_bmap, _TH3_MMU_SPARE_DST_PORT);
   4764     BCM_PBMP_PORT_ADD(link_bmap, _TH3_MMU_SPARE_SRC_PORT);
   4765     soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf,
   4766             &link_bmap);
   4767     rv = soc_mem_write(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ALL, 0,
   4768                 &entry);
   4769     soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm);
   4770     if (rv != SOC_E_NONE) {
   4771         return SOC_E_INTERNAL;
   4772     }
   4773 
   4774     /* Transmit 7 packets to each RQE queue in use */
   4775     soc_cm_get_id(unit, &dev_id, &rev_id);
   4776     if (rev_id == BCM56980_A0_REV_ID) {
   4777         num_rqe_queues = _TH3_A0_MMU_NUM_RQE_QUEUES;
   4778     } else {
   4779         num_rqe_queues = _TH3_MMU_NUM_RQE_QUEUES;
   4780     }
   4781     for (rqe_q = 0; rqe_q < num_rqe_queues; rqe_q++) {
   4782         for (i = 0; i < num_packets; i++) {
   4783             SOC_IF_ERROR_RETURN(
   4784                     soc_transmit_rqe_flush_packet(unit, rqe_q));
   4785         }
   4786     }
   4787 
   4788     /* Wait for MMU_RQE_INT_STAT.FLUSH_DONE interrupt to be set */
   4789     while (1) {
   4790         SOC_IF_ERROR_RETURN(soc_reg32_rawport_get(unit, reg_int_stat,
   4791                                                     itm, 0, &rval));
   4792         rd_val = soc_reg_field_get(unit, reg_int_stat,
   4793                                     rval, FLUSH_DONEf);
   4794         if (rd_val == 1) {
   4795             break;
   4796         }
   4797         sal_usleep(1 + (SAL_BOOT_QUICKTURN ? 1 : 0) * EMULATION_FACTOR);
   4798         count++;
   4799         if (count > 30000) {
   4800             LOG_ERROR(BSL_LS_SOC_COMMON,
   4801                       (BSL_META_U(unit,
   4802                            "RQE Port Flush : FLUSH_DONE isn't reset even after 30000 "
   4803                            "iterations\n")));
   4804             return SOC_E_FAIL;
   4805         }
   4806     }
   4807     /* Clear RQE INVALID_DEST INT STAT*/
   4808     wr_val = 1; /*w1tc*/
   4809     for (itm_int = 0; itm_int < NUM_ITM(unit); itm_int++) {
   4810         if (itm_map & (1 << itm_int)) {
   4811             rval = 0;
   4812             soc_reg_field_set(unit, reg_int_stat, &rval, INVALID_DESTf, wr_val);
   4813             SOC_IF_ERROR_RETURN(
   4814                     soc_reg32_rawport_set(unit, reg_int_stat, itm_int, 0, rval));
   4815         }
   4816     }
   4817 
   4818     /* Restore RQE INVALID_DEST INT_EN */
   4819     SOC_IF_ERROR_RETURN(
   4820             soc_reg32_rawport_get(unit, reg_int_en, REG_PORT_ANY, 0, &rval));
   4821     wr_val = invld_dest_en;
   4822     soc_reg_field_set(unit, reg_int_en, &rval, INVALID_DESTf, wr_val);
   4823     SOC_IF_ERROR_RETURN(
   4824             soc_reg32_rawport_set(unit, reg_int_en, REG_PORT_ANY, 0, rval));
   4825 
   4826     /* Remove Spare ports 158 & 98 from IP's EPC_LINK_BMAP */
   4827     soc_mem_lock(unit, EPC_LINK_BMAPm);
   4828     rv = soc_mem_read(unit, EPC_LINK_BMAPm, MEM_BLOCK_ANY, 0, entry);
   4829     if (rv != SOC_E_NONE) {
   4830         soc_mem_unlock(unit, EPC_LINK_BMAPm);
   4831         return SOC_E_INTERNAL;
   4832     }
   4833     soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf,
   4834             &link_bmap);
   4835     BCM_PBMP_PORT_REMOVE(link_bmap, _TH3_MMU_SPARE_DST_PORT);
   4836     BCM_PBMP_PORT_REMOVE(link_bmap, _TH3_MMU_SPARE_SRC_PORT);
   4837     soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf,
   4838             &link_bmap);
   4839     rv = soc_mem_write(unit, EPC_LINK_BMAPm, MEM_BLOCK_ALL, 0,
   4840                 &entry);
   4841     soc_mem_unlock(unit, EPC_LINK_BMAPm);
   4842     if (rv != SOC_E_NONE) {
   4843         return SOC_E_INTERNAL;
   4844     }
   4845 
   4846     /* Remove Spare ports 158 & 98 from IP's  ING_DEST_PORT_ENABLE */
   4847     soc_mem_lock(unit, ING_DEST_PORT_ENABLEm);
   4848     rv = soc_mem_read(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ANY,
   4849                              0, entry);
   4850     if (rv != SOC_E_NONE) {
   4851         soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm);
   4852         return SOC_E_INTERNAL;
   4853     }
   4854     soc_mem_pbmp_field_get(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf,
   4855             &link_bmap);
   4856     BCM_PBMP_PORT_REMOVE(link_bmap, _TH3_MMU_SPARE_DST_PORT);
   4857     BCM_PBMP_PORT_REMOVE(link_bmap, _TH3_MMU_SPARE_SRC_PORT);
   4858     soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf,
   4859             &link_bmap);
   4860     rv = soc_mem_write(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ALL, 0,
   4861                 &entry);
   4862     soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm);
   4863     if (rv != SOC_E_NONE) {
   4864         return SOC_E_INTERNAL;
   4865     }
   4866 
   4867     return SOC_E_NONE;
   4868 }
   4869 
   4870 int
   4871 soc_th3_mmu_enable_non_func_intr(int unit) {
   4872     int i;
   4873     soc_reg_t loop_reg;
   4874     soc_field_t loop_field;
   4875     uint32 rval;
   4876     struct {
   4877         soc_reg_t int_reg;
   4878         soc_field_t int_en_field;
   4879     } int_rf_list[] = {
   4880         {MMU_MTRO_CPU_INT_ENr, CNT_OVERFLOWf},
   4881         {MMU_THDI_CPU_INT_ENr, POOL_COUNTER_OVERFLOWf},
   4882         {MMU_THDI_CPU_INT_ENr, POOL_COUNTER_UNDERFLOWf},
   4883         {MMU_THDO_CPU_INT_ENr, COUNTER_UNDERFLOWf},
   4884         {MMU_THDO_CPU_INT_ENr, SPID_MISMATCHf},
   4885         {MMU_THDR_QE_CPU_INT_ENr, CNT_OVERFLOWf},
   4886         {MMU_THDR_QE_CPU_INT_ENr, CNT_UNDERFLOWf},
   4887         {MMU_EBCTM_CPU_INT_ENr, OVERFLOW_INTR_ENf},
   4888         {MMU_EBCTM_CPU_INT_ENr, UNDERFLOW_INTR_ENf},
   4889         {MMU_EBCFP_CPU_INT_ENr, EB_MISCONFIGUREDf},
   4890         {MMU_EBCFP_CPU_INT_ENr, MTU_VIOLATIONf},
   4891         {MMU_CRB_CPU_INT_ENr, MTU_VIOLATION_INTR_ENf},
   4892         {MMU_CRB_CPU_INT_ENr, INV_SRC_PORT_INTR_ENf},
   4893         {MMU_CRB_CPU_INT_ENr, INV_DST_PORT_INTR_ENf},
   4894         {MMU_RQE_INT_ENr, INVALID_DESTf},
   4895         {MMU_RQE_INT_ENr, CCP_OVERFLOWf},
   4896         {MMU_RQE_INT_ENr, L3_PURGEf},
   4897         {INVALIDr, INVALIDf}
   4898     };
   4899     soc_reg_t itm_int_reg = MMU_ITMCFG_CPU_INT_ENr;
   4900     soc_reg_t eb_int_reg = MMU_EBCFG_CPU_INT_ENr;
   4901     soc_field_t itm_intr_fields[6] = {THDR_INT_ENf, THDO_INT_ENf, THDI_INT_ENf,
   4902                                      RQE_INT_ENf, CRB_INT_ENf, CFAP_INT_ENf};
   4903     soc_field_t eb_intr_fields[3] = {MTRO_INT_ENf, EBCTM_INT_ENf, EBCFP_INT_ENf};
   4904 
   4905     /* Set Leaf block level interrupt enables*/
   4906     for (i = 0; int_rf_list[i].int_reg != INVALIDr; i++) {
   4907         if (!SOC_REG_IS_VALID(unit, int_rf_list[i].int_reg)) {
   4908             continue;
   4909         }
   4910         loop_reg = int_rf_list[i].int_reg;
   4911         loop_field = int_rf_list[i].int_en_field;
   4912         SOC_IF_ERROR_RETURN
   4913             (soc_reg32_get(unit, loop_reg, REG_PORT_ANY, 0, &rval));
   4914         soc_reg_field_set(unit, loop_reg, &rval, loop_field, 1);
   4915         SOC_IF_ERROR_RETURN
   4916             (soc_reg32_set(unit, loop_reg, REG_PORT_ANY, 0, rval));
   4917     }
   4918 
   4919     /* Set ITM level interrupt enables */
   4920     for (i = 0; i < (sizeof(itm_intr_fields)) / (sizeof(soc_field_t)); i++) {
   4921         rval = 0;
   4922         SOC_IF_ERROR_RETURN
   4923             (soc_reg32_get(unit, itm_int_reg, REG_PORT_ANY, 0, &rval));
   4924         soc_reg_field_set(unit, itm_int_reg, &rval, itm_intr_fields[i], 1);
   4925         SOC_IF_ERROR_RETURN
   4926             (soc_reg32_set(unit, itm_int_reg, REG_PORT_ANY, 0, rval));
   4927     }
   4928     /* Set EB level interrupt enables */
   4929     for (i = 0; i < (sizeof(eb_intr_fields)) / (sizeof(soc_field_t)); i++) {
   4930         rval = 0;
   4931         SOC_IF_ERROR_RETURN
   4932             (soc_reg32_get(unit, eb_int_reg, REG_PORT_ANY, 0, &rval));
   4933         soc_reg_field_set(unit, eb_int_reg, &rval, eb_intr_fields[i], 1);
   4934         SOC_IF_ERROR_RETURN
   4935             (soc_reg32_set(unit, eb_int_reg, REG_PORT_ANY, 0, rval));
   4936     }
   4937     /* All GLB interrupts required are enabled as part of SER init */
   4938     return SOC_E_NONE;
   4939 }
   4940 
   4941 STATIC int
   4942 soc_th3_clear_itm_int_stat (int unit, int itm, soc_field_t itm_intr_field)
   4943 {
   4944     uint32 rval = 0;
   4945     soc_reg_t itm_intr_reg = MMU_ITMCFG_CPU_INT_STATr;
   4946     soc_reg_t glb_intr_reg = MMU_GLBCFG_CPU_INT_STATr;
   4947     soc_field_t glb_fields[] = {ITMCFG0_INT_STATf, ITMCFG1_INT_STATf};
   4948     int wr_val = 1; /* w1tc */
   4949 
   4950     /*Clear ITM level interrupt*/
   4951     rval = 0;
   4952     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, itm_intr_reg, itm, 0, &rval));
   4953     soc_reg_field_set(unit, itm_intr_reg, &rval, itm_intr_field, wr_val);
   4954     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, itm_intr_reg, itm, 0, rval));
   4955     /*Clear GLB level interrupt*/
   4956     rval = 0;
   4957     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, glb_intr_reg, itm, 0, &rval));
   4958     soc_reg_field_set(unit, glb_intr_reg, &rval, glb_fields[itm], wr_val);
   4959     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, glb_intr_reg, itm, 0, rval));
   4960 
   4961     return SOC_E_NONE;
   4962 }
   4963 
   4964 STATIC int
   4965 soc_th3_clear_eb_int_stat (int unit, int pipe, soc_field_t eb_intr_field)
   4966 {
   4967     uint32 rval = 0;
   4968     soc_reg_t eb_intr_reg = MMU_EBCFG_CPU_INT_STATr;
   4969     soc_reg_t glb_intr_reg = MMU_GLBCFG_CPU_INT_STATr;
   4970     soc_field_t glb_fields[] = {EBCFG0_INT_STATf, EBCFG1_INT_STATf,
   4971         EBCFG2_INT_STATf, EBCFG3_INT_STATf, EBCFG4_INT_STATf, EBCFG5_INT_STATf,
   4972         EBCFG6_INT_STATf, EBCFG7_INT_STATf};
   4973     int wr_val = 1; /* w1tc */
   4974 
   4975     /*Clear EB level interrupt*/
   4976     rval = 0;
   4977     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, eb_intr_reg, pipe, 0, &rval));
   4978     soc_reg_field_set(unit, eb_intr_reg, &rval, eb_intr_field, wr_val);
   4979     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, eb_intr_reg, pipe, 0, rval));
   4980     /*Clear GLB level interrupt*/
   4981     rval = 0;
   4982     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, glb_intr_reg, pipe, 0, &rval));
   4983     soc_reg_field_set(unit, glb_intr_reg, &rval, glb_fields[pipe], wr_val);
   4984     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, glb_intr_reg, pipe, 0, rval));
   4985 
   4986     return SOC_E_NONE;
   4987 }
   4988 
   4989 
   4990 
   4991 int
   4992 soc_th3_process_itm_cfap_int (int unit, int itm, soc_field_t itm_intr_field) {
   4993     soc_reg_t block_intr_reg = MMU_CFAP_INT_STATr;
   4994     uint64 rval64;
   4995     soc_field_t bst_int = BST_TRIG_STATf;
   4996     int wr_val = 1; /* w1tc */
   4997 
   4998     COMPILER_64_ZERO(rval64);
   4999     SOC_IF_ERROR_RETURN(
   5000             soc_reg64_get(unit, block_intr_reg, itm, 0, &rval64));
   5001     if (soc_reg64_field32_get(unit, block_intr_reg, rval64, bst_int)) {
   5002         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   5003                             (BSL_META_U(unit, "Unit: %0d -- Servicing CFAP"
   5004                                         "BST intr from ITM = %0d \n"),
   5005                              unit, itm));
   5006         /* Clear BST interrupt*/
   5007         soc_reg64_field32_set(unit, block_intr_reg, &rval64, bst_int, wr_val);
   5008         SOC_IF_ERROR_RETURN(
   5009                 soc_reg64_set(unit, block_intr_reg, itm, 0, rval64));
   5010         /* Clear ITM and GLB level interrupts */
   5011         SOC_IF_ERROR_RETURN(
   5012             soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5013         /* BST callback for stats processing */
   5014         SOC_IF_ERROR_RETURN
   5015             (soc_th3_process_mmu_bst(unit, itm, itm_intr_field));
   5016     }
   5017     return SOC_E_NONE;
   5018 }
   5019 
   5020 int
   5021 soc_th3_process_itm_thdi_int (int unit, int itm, soc_field_t itm_intr_field) {
   5022     soc_reg_t block_intr_reg = MMU_THDI_CPU_INT_STATr;
   5023     uint32 rval = 0, intr_reg_val = 0;
   5024     soc_field_t thdi_intr_fields[] = {POOL_COUNTER_UNDERFLOW_STATf,
   5025         POOL_COUNTER_OVERFLOW_STATf};
   5026     soc_field_t bst_int = BST_TRIG_STATf;
   5027     int wr_val = 1; /* w1tc */
   5028     int i;
   5029 
   5030     SOC_IF_ERROR_RETURN(
   5031             soc_reg32_get(unit, block_intr_reg, itm, 0, &intr_reg_val));
   5032     if (soc_reg_field_get(unit, block_intr_reg, intr_reg_val, bst_int)) {
   5033         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   5034                             (BSL_META_U(unit, "Unit: %0d -- Servicing THDI"
   5035                                         "BST intr from ITM = %0d \n"),
   5036                              unit, itm));
   5037         /* Clear BST interrupt*/
   5038         SOC_IF_ERROR_RETURN(
   5039                 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5040         soc_reg_field_set(unit, block_intr_reg, &rval, bst_int, wr_val);
   5041         SOC_IF_ERROR_RETURN(
   5042                 soc_reg32_set(unit, block_intr_reg, itm, 0, rval));
   5043         /* Clear ITM and GLB level interrupts */
   5044         SOC_IF_ERROR_RETURN(
   5045             soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5046         /* BST callback for stats processing */
   5047         SOC_IF_ERROR_RETURN
   5048             (soc_th3_process_mmu_bst(unit, itm, itm_intr_field));
   5049     } else {
   5050         for (i = 0; i < (sizeof(thdi_intr_fields) / sizeof(soc_field_t)); i++) {
   5051             SOC_IF_ERROR_RETURN(
   5052                 soc_reg32_get(unit, block_intr_reg, itm, 0, &intr_reg_val));
   5053             if (!soc_reg_field_get(unit, block_intr_reg,
   5054                                    intr_reg_val, thdi_intr_fields[i])) {
   5055                 continue;
   5056             }
   5057             switch(thdi_intr_fields[i]) {
   5058                 case POOL_COUNTER_UNDERFLOWf:
   5059                     LOG_ERROR(BSL_LS_SOC_COMMON,
   5060                             (BSL_META_U(unit, "Unit: %0d -- THDI Pool Counter"
   5061                                         "Underflow intr set for ITM = %0d \n"),
   5062                              unit, itm));
   5063                     break;
   5064                 case POOL_COUNTER_OVERFLOWf:
   5065                     LOG_ERROR(BSL_LS_SOC_COMMON,
   5066                             (BSL_META_U(unit, "Unit: %0d -- THDI Pool Counter"
   5067                                         "Overflow intr set for ITM = %0d \n"),
   5068                              unit, itm));
   5069                     break;
   5070                 default:
   5071                     break;
   5072             }
   5073             /*Clear block(THDI) level interrupt*/
   5074             rval = 0;
   5075             SOC_IF_ERROR_RETURN(
   5076                     soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5077             soc_reg_field_set(unit, block_intr_reg, &rval,
   5078                     thdi_intr_fields[i], wr_val);
   5079             SOC_IF_ERROR_RETURN(
   5080                     soc_reg32_set(unit, block_intr_reg, itm, 0, rval));
   5081         }
   5082         /* Clear ITM and GLB level interrupts */
   5083         SOC_IF_ERROR_RETURN(
   5084             soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5085 
   5086     }
   5087     return SOC_E_NONE;
   5088 }
   5089 
   5090 int
   5091 soc_th3_process_itm_thdo_int (int unit, int itm, soc_field_t itm_intr_field) {
   5092     soc_reg_t block_intr_reg = MMU_THDO_CPU_INT_STATr;
   5093     soc_reg_t thdo_bst_int_reg = MMU_THDO_BST_CPU_INT_STATr;
   5094     uint32 rval = 0;
   5095     soc_field_t thdo_intr_fields[] = {COUNTER_UNDERFLOWf, SPID_MISMATCHf};
   5096     soc_field_t bst_int = BSTf;
   5097     int wr_val = 1; /* w1tc */
   5098     int i;
   5099 
   5100     SOC_IF_ERROR_RETURN(
   5101             soc_reg32_get(unit, thdo_bst_int_reg, itm, 0, &rval));
   5102     if (soc_reg_field_get(unit, thdo_bst_int_reg, rval, bst_int)) {
   5103         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   5104                             (BSL_META_U(unit, "Unit: %0d -- Servicing THDO"
   5105                                         "BST intr from ITM = %0d \n"),
   5106                              unit, itm));
   5107         /* Clear BST interrupt*/
   5108         soc_reg_field_set(unit, thdo_bst_int_reg, &rval, bst_int, wr_val);
   5109         SOC_IF_ERROR_RETURN(
   5110                 soc_reg32_set(unit, thdo_bst_int_reg, itm, 0, rval));
   5111         /* Clear ITM and GLB level interrupts */
   5112         SOC_IF_ERROR_RETURN(
   5113             soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5114         /* BST callback for stats processing */
   5115         SOC_IF_ERROR_RETURN
   5116             (soc_th3_process_mmu_bst(unit, itm, itm_intr_field));
   5117     } else {
   5118         for (i = 0; i < (sizeof(thdo_intr_fields) / sizeof(soc_field_t)); i++) {
   5119             SOC_IF_ERROR_RETURN(
   5120                 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5121             if (!soc_reg_field_get(unit, block_intr_reg,
   5122                                    rval, thdo_intr_fields[i])) {
   5123                 continue;
   5124             }
   5125             switch(thdo_intr_fields[i]) {
   5126                 case SPID_MISMATCHf:
   5127                     LOG_ERROR(BSL_LS_SOC_COMMON,
   5128                             (BSL_META_U(unit, "Unit: %0d -- SPID Mismatch"
   5129                              "intr set for ITM = %0d \n"),
   5130                              unit, itm));
   5131                     break;
   5132                 case COUNTER_UNDERFLOWf:
   5133                     LOG_ERROR(BSL_LS_SOC_COMMON,
   5134                             (BSL_META_U(unit, "Unit: %0d -- THDO Counter"
   5135                              " Underflow intr set for ITM = %0d \n"),
   5136                              unit, itm));
   5137 
   5138                     break;
   5139                 default:
   5140                     break;
   5141             }
   5142             /*Clear block(THDO) level interrupt*/
   5143             rval = 0;
   5144             SOC_IF_ERROR_RETURN(
   5145                     soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5146             soc_reg_field_set(unit, block_intr_reg, &rval,
   5147                     thdo_intr_fields[i], wr_val);
   5148             SOC_IF_ERROR_RETURN(
   5149                     soc_reg32_set(unit, block_intr_reg, itm, 0, rval));
   5150         }
   5151         /* Clear ITM and GLB level interrupts */
   5152         SOC_IF_ERROR_RETURN(
   5153             soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5154     }
   5155 
   5156     return SOC_E_NONE;
   5157 }
   5158 
   5159 int
   5160 soc_th3_process_itm_thdr_int (int unit, int itm, soc_field_t itm_intr_field) {
   5161     soc_reg_t block_intr_reg = MMU_THDR_QE_CPU_INT_STATr;
   5162     uint32 rval = 0;
   5163     soc_field_t thdr_intr_fields[] = {CNT_UNDERFLOWf, CNT_OVERFLOWf};
   5164     soc_field_t bst_int = BSTf;
   5165     int wr_val = 1; /* w1tc */
   5166     int i;
   5167 
   5168     SOC_IF_ERROR_RETURN(
   5169             soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5170     if (soc_reg_field_get(unit, block_intr_reg, rval, bst_int)) {
   5171         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   5172                             (BSL_META_U(unit, "Unit: %0d -- Servicing THDR QE"
   5173                                         "BST intr from ITM = %0d \n"),
   5174                              unit, itm));
   5175         /* Clear BST interrupt*/
   5176         soc_reg_field_set(unit, block_intr_reg, &rval, bst_int, wr_val);
   5177         SOC_IF_ERROR_RETURN(
   5178                 soc_reg32_set(unit, block_intr_reg, itm, 0, rval));
   5179         /* Clear ITM and GLB level interrupts */
   5180         SOC_IF_ERROR_RETURN(
   5181             soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5182         /* BST callback for stats processing */
   5183         SOC_IF_ERROR_RETURN
   5184             (soc_th3_process_mmu_bst(unit, itm, itm_intr_field));
   5185     } else {
   5186         for (i = 0; i < (sizeof(thdr_intr_fields) / sizeof(soc_field_t)); i++) {
   5187             SOC_IF_ERROR_RETURN(
   5188                 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5189             if (!soc_reg_field_get(unit, block_intr_reg,
   5190                                    rval, thdr_intr_fields[i])) {
   5191                 continue;
   5192             }
   5193             switch(thdr_intr_fields[i]) {
   5194                 case CNT_OVERFLOWf:
   5195                     LOG_ERROR(BSL_LS_SOC_COMMON,
   5196                             (BSL_META_U(unit, "Unit: %0d -- THDR QE Counter"
   5197                              " Overflow intr set for ITM = %0d \n"),
   5198                              unit, itm));
   5199                     break;
   5200                 case CNT_UNDERFLOWf:
   5201                     LOG_ERROR(BSL_LS_SOC_COMMON,
   5202                             (BSL_META_U(unit, "Unit: %0d -- THDR QE Counter"
   5203                              " Underflow intr set for ITM = %0d \n"),
   5204                              unit, itm));
   5205 
   5206                     break;
   5207                 default:
   5208                     break;
   5209             }
   5210             /*Clear block(THDR QE) level interrupt*/
   5211             rval = 0;
   5212             SOC_IF_ERROR_RETURN(
   5213                     soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5214             soc_reg_field_set(unit, block_intr_reg, &rval,
   5215                     thdr_intr_fields[i], wr_val);
   5216             SOC_IF_ERROR_RETURN(
   5217                     soc_reg32_set(unit, block_intr_reg, itm, 0, rval));
   5218         }
   5219         /* Clear ITM and GLB level interrupts */
   5220         SOC_IF_ERROR_RETURN(
   5221             soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5222     }
   5223 
   5224     return SOC_E_NONE;
   5225 }
   5226 
   5227 int
   5228 soc_th3_process_itm_rqe_int (int unit, int itm, soc_field_t itm_intr_field) {
   5229     soc_reg_t block_intr_reg = MMU_RQE_INT_STATr;
   5230     uint32 rval = 0;
   5231     soc_field_t thdr_intr_fields[] = {INVALID_DESTf, CCP_OVERFLOWf, L3_PURGEf};
   5232     int wr_val = 1; /* w1tc */
   5233     int i;
   5234 
   5235     for (i = 0; i < (sizeof(thdr_intr_fields) / sizeof(soc_field_t)); i++) {
   5236         SOC_IF_ERROR_RETURN(
   5237             soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5238         if (!soc_reg_field_get(unit, block_intr_reg,
   5239                                rval, thdr_intr_fields[i])) {
   5240             continue;
   5241         }
   5242         switch(thdr_intr_fields[i]) {
   5243             case CCP_OVERFLOWf:
   5244                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5245                         (BSL_META_U(unit, "Unit: %0d -- Multicast copy count"
   5246                          " exceeded 1K intr set for ITM = %0d \n"),
   5247                          unit, itm));
   5248                 break;
   5249             case INVALID_DESTf:
   5250                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5251                         (BSL_META_U(unit, "Unit: %0d -- Invalid destination port"
   5252                          " in L2/L3 bitmap intr set for ITM = %0d \n"),
   5253                          unit, itm));
   5254 
   5255                 break;
   5256             case L3_PURGEf:
   5257                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5258                         (BSL_META_U(unit, "Unit: %0d -- Packet drop due to"
   5259                          " invalid multicast config intr set for ITM = %0d \n"),
   5260                          unit, itm));
   5261 
   5262                 break;
   5263             default:
   5264                 break;
   5265         }
   5266         /*Clear block(RQE) level interrupt*/
   5267         rval = 0;
   5268         SOC_IF_ERROR_RETURN(
   5269                 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5270         soc_reg_field_set(unit, block_intr_reg, &rval,
   5271                 thdr_intr_fields[i], wr_val);
   5272         SOC_IF_ERROR_RETURN(
   5273                 soc_reg32_set(unit, block_intr_reg, itm, 0, rval));
   5274     }
   5275     /* Clear ITM and GLB level interrupts */
   5276     SOC_IF_ERROR_RETURN(
   5277         soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5278 
   5279     return SOC_E_NONE;
   5280 }
   5281 
   5282 int
   5283 soc_th3_process_itm_crb_int (int unit, int itm, soc_field_t itm_intr_field) {
   5284     soc_reg_t block_intr_reg = MMU_CRB_CPU_INT_STATr;
   5285     uint32 rval = 0;
   5286     soc_field_t thdr_intr_fields[] = {MTU_VIOLATION_INTR_STATf,
   5287         INV_SRC_PORT_INTR_STATf, INV_DST_PORT_INTR_STATf};
   5288     int wr_val = 1; /* w1tc */
   5289     int i;
   5290 
   5291     for (i = 0; i < (sizeof(thdr_intr_fields) / sizeof(soc_field_t)); i++) {
   5292         SOC_IF_ERROR_RETURN(
   5293             soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5294         if (!soc_reg_field_get(unit, block_intr_reg,
   5295                                rval, thdr_intr_fields[i])) {
   5296             continue;
   5297         }
   5298         switch(thdr_intr_fields[i]) {
   5299             case MTU_VIOLATION_INTR_STATf:
   5300                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5301                         (BSL_META_U(unit, "Unit: %0d -- MTU violation"
   5302                          " intr set for ITM = %0d \n"),
   5303                          unit, itm));
   5304                 break;
   5305             case INV_SRC_PORT_INTR_STATf:
   5306                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5307                         (BSL_META_U(unit, "Unit: %0d -- Invalid source port"
   5308                          " intr set for ITM = %0d \n"),
   5309                          unit, itm));
   5310                 break;
   5311             case INV_DST_PORT_INTR_STATf:
   5312                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5313                         (BSL_META_U(unit, "Unit: %0d -- Invalid dest port"
   5314                          " intr set for ITM = %0d \n"),
   5315                          unit, itm));
   5316                 break;
   5317             default:
   5318                 break;
   5319         }
   5320         /*Clear block(THDR QE) level interrupt*/
   5321         rval = 0;
   5322         SOC_IF_ERROR_RETURN(
   5323                 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval));
   5324         soc_reg_field_set(unit, block_intr_reg, &rval,
   5325                 thdr_intr_fields[i], wr_val);
   5326         SOC_IF_ERROR_RETURN(
   5327                 soc_reg32_set(unit, block_intr_reg, itm, 0, rval));
   5328     }
   5329     /* Clear ITM and GLB level interrupts */
   5330     SOC_IF_ERROR_RETURN(
   5331         soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field));
   5332 
   5333     return SOC_E_NONE;
   5334 }
   5335 
   5336 int
   5337 soc_th3_process_eb_ebctm_int (int unit, int pipe, soc_field_t eb_intr_field) {
   5338     soc_reg_t block_intr_reg = MMU_EBCTM_CPU_INT_STATr;
   5339     uint32 rval = 0;
   5340     soc_field_t ebctm_intr_fields[] = {OVERFLOW_INTR_STATf, UNDERFLOW_INTR_STATf};
   5341     int wr_val = 1; /* w1tc */
   5342     int i;
   5343 
   5344     for (i = 0; i < (sizeof(ebctm_intr_fields) / sizeof(soc_field_t)); i++) {
   5345         SOC_IF_ERROR_RETURN(
   5346             soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval));
   5347         if (!soc_reg_field_get(unit, block_intr_reg,
   5348                                rval, ebctm_intr_fields[i])) {
   5349             continue;
   5350         }
   5351         switch(ebctm_intr_fields[i]) {
   5352             case OVERFLOW_INTR_STATf:
   5353                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5354                         (BSL_META_U(unit, "Unit: %0d -- EBCTM counters Overflow"
   5355                          " intr set for PIPE = %0d \n"),
   5356                          unit, pipe));
   5357                 break;
   5358             case UNDERFLOW_INTR_STATf:
   5359                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5360                         (BSL_META_U(unit, "Unit: %0d -- EBCTM counters Underflow"
   5361                          " intr set for PIPE = %0d \n"),
   5362                          unit, pipe));
   5363 
   5364                 break;
   5365             default:
   5366                 break;
   5367         }
   5368         /*Clear block(EBCTM) level interrupt*/
   5369         rval = 0;
   5370         SOC_IF_ERROR_RETURN(
   5371                 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval));
   5372         soc_reg_field_set(unit, block_intr_reg, &rval,
   5373                 ebctm_intr_fields[i], wr_val);
   5374         SOC_IF_ERROR_RETURN(
   5375                 soc_reg32_set(unit, block_intr_reg, pipe, 0, rval));
   5376     }
   5377     /* Clear EB and GLB level interrupts */
   5378     SOC_IF_ERROR_RETURN(
   5379         soc_th3_clear_eb_int_stat(unit, pipe, eb_intr_field));
   5380 
   5381     return SOC_E_NONE;
   5382 }
   5383 
   5384 int
   5385 soc_th3_process_eb_ebcfp_int (int unit, int pipe, soc_field_t eb_intr_field) {
   5386     soc_reg_t block_intr_reg = MMU_EBCFP_CPU_INT_STATr;
   5387     uint32 rval = 0;
   5388     soc_field_t ebcfp_intr_field = MTU_VIOLATIONf;
   5389     int wr_val = 1; /* w1tc */
   5390 
   5391         SOC_IF_ERROR_RETURN(
   5392             soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval));
   5393         if (soc_reg_field_get(unit, block_intr_reg,
   5394                                rval, ebcfp_intr_field)) {
   5395             LOG_ERROR(BSL_LS_SOC_COMMON,
   5396                     (BSL_META_U(unit, "Unit: %0d -- MTU violation in EB"
   5397                      " group intr set for PIPE = %0d \n"),
   5398                      unit, pipe));
   5399         }
   5400         /*Clear block(EBCFP) level interrupt*/
   5401         rval = 0;
   5402         SOC_IF_ERROR_RETURN(
   5403                 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval));
   5404         soc_reg_field_set(unit, block_intr_reg, &rval,
   5405                 ebcfp_intr_field, wr_val);
   5406         SOC_IF_ERROR_RETURN(
   5407                 soc_reg32_set(unit, block_intr_reg, pipe, 0, rval));
   5408     /* Clear EB and GLB level interrupts */
   5409     SOC_IF_ERROR_RETURN(
   5410         soc_th3_clear_eb_int_stat(unit, pipe, eb_intr_field));
   5411 
   5412     return SOC_E_NONE;
   5413 }
   5414 
   5415 int
   5416 soc_th3_process_eb_mtro_int (int unit, int pipe, soc_field_t eb_intr_field) {
   5417     soc_reg_t block_intr_reg = MMU_MTRO_CPU_INT_STATr;
   5418     uint32 rval = 0;
   5419     soc_field_t mtro_intr_field = CNT_OVERFLOWf;
   5420     int wr_val = 1; /* w1tc */
   5421 
   5422     if (soc_reg_field_get(unit, block_intr_reg, rval, mtro_intr_field)) {
   5423         SOC_IF_ERROR_RETURN(
   5424             soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval));
   5425         LOG_ERROR(BSL_LS_SOC_COMMON,
   5426                 (BSL_META_U(unit, "Unit: %0d -- Counter overflow in MTRO"
   5427                  " intr set for PIPE = %0d \n"),
   5428                  unit, pipe));
   5429         /*Clear block(MTRO) level interrupt*/
   5430         rval = 0;
   5431         SOC_IF_ERROR_RETURN(
   5432                 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval));
   5433         soc_reg_field_set(unit, block_intr_reg, &rval,
   5434                 mtro_intr_field, wr_val);
   5435         SOC_IF_ERROR_RETURN(
   5436                 soc_reg32_set(unit, block_intr_reg, pipe, 0, rval));
   5437         /* Clear EB and GLB level interrupts */
   5438         SOC_IF_ERROR_RETURN(
   5439             soc_th3_clear_eb_int_stat(unit, pipe, eb_intr_field));
   5440     }
   5441 
   5442     return SOC_E_NONE;
   5443 }
   5444 
   5445 #endif /* BCM_TOMAHAWK3_SUPPORT */