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

pfc.c (40134B)


      1 
      2 /*
      3  * 
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * Implementation for PFC SOC functions
      9  */
     10 #if defined(BCM_TOMAHAWK3_SUPPORT)
     11 #include <soc/pfc.h>
     12 #include <soc/feature.h>
     13 #include <soc/drv.h>
     14 #include <soc/scache.h>
     15 #include <soc/debug.h>
     16 #include <soc/tomahawk.h>
     17 #include <soc/dma.h>
     18 #include <soc/mmu_config.h>
     19 #include <soc/error.h>
     20 
     21 #define _TH3_PFC_PRIORITY_GROUP_NUM 8
     22 #define _TH3_PFC_EB_GROUP_NUM 9
     23 
     24 #define _TH3_PFC_PRIORITY_MAX_INDEX 7
     25 #define _TH3_PFC_INDEX_INVALID -1
     26 
     27 #define _TH3_PFC_COS_NUM_MASK_OFFSET 12 /* total 12 cos using bits[11:0]*/
     28 
     29 typedef struct _soc_th3_pfc_eb_group_config_s {
     30     int opt_group[TH3_PFC_COS_NUM]; /* PFC optimized COS */
     31     int eb_group[TH3_PFC_COS_NUM]; /* COS to EB mapping */
     32     uint8 eb_group_sp[_TH3_PFC_EB_GROUP_NUM]; /* EB group Scheduling Policy
     33                                         * 1: Static Priority
     34                                         * 0: Round Robin
     35                                        */
     36     uint8 eb_group_opt[_TH3_PFC_EB_GROUP_NUM]; /* 1, EB group is optimized */
     37     int mmuq_eb_group[TH3_PFC_MMU_QUEUE_NUM]; /* MMU queue EB group mapping */
     38 } _soc_th3_pfc_eb_group_config_t;
     39 
     40 typedef enum _soc_th3_pfc_port_speed_id_e {
     41 
     42     _SOC_TH3_PFC_PORT_SPEED_50G = 0,
     43     _SOC_TH3_PFC_PORT_SPEED_100G = 1,
     44     _SOC_TH3_PFC_PORT_SPEED_200G = 2,
     45     _SOC_TH3_PFC_PORT_SPEED_400G = 3,
     46     _SOC_TH3_PFCPORT_SPEED_NUM = 4
     47 
     48 } _SOC_th3_pfc_port_speed_id_t;
     49 
     50 static const int opt_group_num_flexport[4][4] = {
     51                                         {2, 3, 4, 4},
     52                                         {2, 3, 4, 4},
     53                                         {1, 2, 3, 3},
     54                                         {1, 2, 3, 3},
     55                                     };
     56 static const int magt_opt_group_num_flexport[4] = {4, 4, 3, 3};
     57 
     58 STATIC int
     59 _soc_th3_pfc_mtu_encoding_get(int unit, int mtu_size)
     60 {
     61     int mtu_id;
     62 
     63     if (mtu_size <= 1024) { /* < 1K */
     64         mtu_id = 0;
     65     }
     66     else if (mtu_size <= 2150) { /* < 2.1K */
     67         mtu_id = 1;
     68     }
     69     else if (mtu_size <= 4196) {/* < 4K */
     70         mtu_id = 2;
     71     }
     72     else if (mtu_size <= 9416) {/* < 9K */
     73         mtu_id = 3;
     74     }
     75     else {
     76         mtu_id = _TH3_PFC_INDEX_INVALID;
     77     }
     78     return mtu_id;
     79 }
     80 
     81 STATIC int
     82 _soc_th3_pfc_speed_encoding_get(int unit, int speed)
     83 {
     84     int speed_id;
     85 
     86     if (speed < 50000) {
     87         speed = 50000;
     88     }
     89 
     90     switch(speed) {
     91         case 50000:
     92             speed_id = _SOC_TH3_PFC_PORT_SPEED_50G;
     93             break;
     94         case 100000:
     95             speed_id = _SOC_TH3_PFC_PORT_SPEED_100G;
     96             break;
     97         case 200000:
     98             speed_id = _SOC_TH3_PFC_PORT_SPEED_200G;
     99             break;
    100         case 400000:
    101             speed_id = _SOC_TH3_PFC_PORT_SPEED_400G;
    102             break;
    103         default:
    104             speed_id = -1;
    105     }
    106 
    107     return speed_id;
    108 }
    109 
    110 STATIC void
    111 _soc_th3_pfc_eb_group_config_t_init(_soc_th3_pfc_eb_group_config_t *config)
    112 {
    113     int i;
    114     sal_memset(config, 0, sizeof(_soc_th3_pfc_eb_group_config_t));
    115     for (i = 0; i < TH3_PFC_COS_NUM; i++) {
    116         config->eb_group[i] =  _TH3_PFC_INDEX_INVALID;
    117     }
    118 }
    119 
    120 STATIC void
    121 _soc_th3_print_pfc_sched_profile_info (int unit, int profile_id,
    122         _soc_th3_pfc_eb_group_config_t *eb_config)
    123 {
    124     int max_cos = 0;
    125     int cos, idx, l0_idx = 0;
    126     int mmuq0, mmuq1;
    127     int fc_only_uc, sp;
    128     int ebg_grp0, ebg_grp1, pfc_opt_grp, ebg_cos;
    129     int sp0, sp1;
    130 
    131     max_cos = soc_tomahawk3_get_sched_profile_max_cos(unit, profile_id);
    132 
    133     LOG_VERBOSE(BSL_LS_SOC_MMU, (BSL_META_U(unit,
    134                 " Cos    MMUQ0    MMUQ1    FC_UC    SP    PFC_opt    "
    135                 "EB_grp(cos)  EB_group0  EB_group1  SP(0)  SP(1)\n")));
    136 
    137     for (cos = max_cos; cos >= 0; cos--) {
    138         for (idx = 0; idx < SOC_TH3_NUM_GP_QUEUES; idx++) {
    139             if (th3_sched_profile_info[unit][profile_id][idx].cos == cos) {
    140                 l0_idx = idx;
    141                 break;
    142             }
    143         }
    144         mmuq0 = th3_sched_profile_info[unit][profile_id][l0_idx].mmuq[0];
    145         mmuq1 = th3_sched_profile_info[unit][profile_id][l0_idx].mmuq[1];
    146         fc_only_uc = th3_sched_profile_info[unit][profile_id][l0_idx].fc_is_uc_only;
    147         sp = th3_sched_profile_info[unit][profile_id][l0_idx].strict_priority;
    148         ebg_cos = eb_config->eb_group[cos];
    149         ebg_grp0 = eb_config->mmuq_eb_group[mmuq0];
    150         ebg_grp1 = eb_config->mmuq_eb_group[mmuq1];
    151         pfc_opt_grp = eb_config->opt_group[cos];
    152         sp0 = eb_config->eb_group_sp[ebg_grp0];
    153         sp1 = eb_config->eb_group_sp[ebg_grp1];
    154         LOG_VERBOSE(BSL_LS_SOC_MMU, (BSL_META_U(unit,
    155                 " %2d      %2d      %2d         %d      %d       %d           "
    156                 "%d           %d          %d         %d      %d\n"),
    157 			                cos, mmuq0, mmuq1, fc_only_uc, sp, pfc_opt_grp,
    158                             ebg_cos, ebg_grp0, ebg_grp1, sp0, sp1));
    159 
    160 
    161     }
    162 }
    163 
    164 /*
    165  * Function:
    166  *     _soc_th3_pfc_opt_bmp_validate
    167  * Purpose:
    168  *   To check the validity of COS lists for all PFC priorities.
    169  * Parameters:
    170  *     unit       - (IN) unit number
    171  *     config_array  - (IN) PFC class config array
    172  *     array_len - (IN) The array length
    173  * Returns:
    174  *     SOC_E_XXX
    175  */
    176 
    177 STATIC int
    178 _soc_th3_pfc_opt_bmp_validate(
    179     int unit,
    180     soc_cosq_pfc_class_map_config_t *config_array,
    181     int array_len)
    182 {
    183     int i, j;
    184     uint32 opt_bmp_agg;
    185     if (config_array == NULL)
    186         return SOC_E_PARAM;
    187 
    188     if (array_len > TH3_PFC_PRIORITY_NUM)
    189         return SOC_E_PARAM;
    190 /*
    191 *   two conditions have to be met
    192 *   1. for any two optimized PFC priorities, the list of CoS must be either
    193 *      mutually exclusive or equal.
    194 *   2. A priority p0 can be PFC optimized if there is no other priority p1
    195 *      that COS list of p1 is a subset of COS list of p0.
    196  */
    197     for (i = 0; i< array_len; i++)   {
    198         if (!config_array[i].pfc_optimized ||
    199                     !config_array[i].cos_list_bmp) {
    200             continue;
    201         }
    202 
    203         for (j = 0; j < array_len; j++) {
    204             if (j == i || !config_array[j].cos_list_bmp) {
    205                 continue;
    206             }
    207             opt_bmp_agg = config_array[i].cos_list_bmp &
    208                                               config_array[j].cos_list_bmp;
    209             if (config_array[j].pfc_optimized) {
    210                 /*  contition 1 */
    211                 if ((opt_bmp_agg != 0) &&
    212                        (config_array[i].cos_list_bmp != config_array[j].cos_list_bmp)) {
    213                     return SOC_E_PARAM;
    214                 }
    215             } else {
    216                 /* condition 2*/
    217                 if (opt_bmp_agg == config_array[j].cos_list_bmp) {
    218                     return SOC_E_PARAM;
    219                 }
    220 
    221             }
    222         }
    223     }
    224 
    225     return SOC_E_NONE;
    226 
    227 }
    228 
    229 /*
    230  * Function:
    231  *     _soc_th3_pfc_rx_config_validate
    232  * Purpose:
    233  *   To check if the input Config array is valid
    234  * Parameters:
    235  *     unit       - (IN) unit number
    236  *     config_array  - (IN) PFC class config array
    237  *     array_len - (IN) The array length
    238  * Returns:
    239  *     SOC_E_XXX
    240  */
    241 
    242 STATIC int
    243 _soc_th3_pfc_rx_config_validate(
    244     int unit,
    245     soc_cosq_pfc_class_map_config_t *config_array,
    246     int array_len)
    247 {
    248 
    249     int i;
    250     if (config_array == NULL) {
    251         return SOC_E_PARAM;
    252     }
    253 
    254     for (i = 0; i < array_len; i++) {
    255 
    256         if ((config_array[i].cos_list_bmp >> _TH3_PFC_COS_NUM_MASK_OFFSET)) {
    257             return SOC_E_PARAM;
    258         }
    259     }
    260 
    261     SOC_IF_ERROR_RETURN(_soc_th3_pfc_opt_bmp_validate
    262                             (unit, config_array, TH3_PFC_PRIORITY_NUM));
    263 
    264     return SOC_E_NONE;
    265 }
    266 
    267 /*
    268  * Function:
    269  *     _soc_th3_pfc_eb_group_allocate
    270  * Purpose:
    271  *   First Assign EB groups to COS
    272  *   Then set EB scheduling based on
    273  *      1. EB group assignment,
    274  *      2. SP_P field from scheduler domain input.
    275  * Parameters:
    276  *     unit       - (IN) unit number
    277  *     eb_config  - (IN/OUT) EB group config
    278  *     num_opt_group - (IN) the required number of optimized groups
    279  * Returns:
    280  *     SOC_E_XXX
    281  */
    282 
    283 STATIC int
    284 _soc_th3_pfc_eb_group_allocate(
    285     int unit,
    286     int profile_id,
    287     _soc_th3_pfc_eb_group_config_t *eb_config,
    288     int num_opt_group)
    289 {
    290 
    291     int n_avail_eb, non_opt_num;
    292     int i, cos_num, invalid_index = _TH3_PFC_INDEX_INVALID;
    293     int rr_set = 0;
    294     int max_cos = 0;
    295     /*the maximum index of EB group */
    296     n_avail_eb = _TH3_PFC_EB_GROUP_NUM - 1;
    297     /* maximum index of non-opt EB*/
    298     non_opt_num = n_avail_eb - num_opt_group;
    299 
    300     max_cos = soc_tomahawk3_get_sched_profile_max_cos(unit, profile_id);
    301     for (cos_num = max_cos; cos_num >= 0; cos_num--) {
    302         int eb_sp = soc_tomahawk3_get_sp_for_cos(unit, profile_id, cos_num);
    303         if (eb_config->opt_group[cos_num] !=0 &&
    304                             eb_config->eb_group[cos_num] == invalid_index) {
    305 
    306             eb_config->eb_group[cos_num] = n_avail_eb--;
    307 
    308             for (i = cos_num -1; i >= 0; i--) {
    309                 if (eb_config->opt_group[i]
    310                                     == eb_config->opt_group[cos_num]) {
    311                     eb_config->eb_group[i] = eb_config->eb_group[cos_num];
    312 
    313                     /* the EB group is set to SP as long as there exists one of the
    314                     * COSs assigned to it is SP planned.
    315                     */
    316                     eb_sp |= soc_tomahawk3_get_sp_for_cos(unit, profile_id, i);
    317                 }
    318             }
    319             eb_config->eb_group_opt[eb_config->eb_group[cos_num]] = 1;
    320 
    321         } else if (eb_config->eb_group[cos_num] == invalid_index) {
    322             if (non_opt_num > 0) {
    323                 /* if free EB_GRP is available, then set EB_GRP(cos_num) to
    324                  * the next available EB_GRP with largest index.
    325                 */
    326                 eb_config->eb_group[cos_num] = n_avail_eb--;
    327                 non_opt_num--;
    328             } else {
    329                 /* if free EB_GRP is not available, then set EB_GRP(current_cos) to 0
    330                  * and set scheduling policy to round robin
    331                 */
    332                 eb_config->eb_group[cos_num] = 0;
    333                 rr_set = 1;
    334             }
    335         }
    336         if (!rr_set) {
    337             if (eb_sp == 1) {
    338                 eb_config->eb_group_sp[eb_config->eb_group[cos_num]] = 1;
    339             } else {
    340                 rr_set = 1;
    341             }
    342         }
    343 
    344     }
    345 
    346     return SOC_E_NONE;
    347 
    348 }
    349 
    350 STATIC int
    351 _soc_th3_pfc_mmuq_is_mc(int unit, int q_num) {
    352     int mc_q_mode, num_ucq;
    353     mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, 2);
    354     num_ucq = (mc_q_mode == 0) ? 12 : (mc_q_mode == 1) ? 10 :
    355               (mc_q_mode == 2) ? 8  : (mc_q_mode == 3) ? 6 : 8;
    356 
    357     return (q_num >= 0 && q_num < num_ucq) ? 0 : 1;
    358 }
    359 
    360 /*
    361  * Function:
    362  *     _soc_th3_pfc_mmu_to_eb_mapping
    363  * Purpose:
    364  *     Map MMU queues to EB groups.
    365  * Parameters:
    366  *     unit       - (IN) unit number
    367  *     eb_config  - (IN/OUT) EB group config
    368  *     profile_id - (IN) Profile index
    369  * Returns:
    370  *     SOC_E_XXX
    371  */
    372 STATIC int
    373 _soc_th3_pfc_mmuq_to_eb_mapping(
    374     int unit,
    375     int profile_id,
    376     _soc_th3_pfc_eb_group_config_t *eb_config)
    377 {
    378 
    379     int i, q_num, cos_f_q, eb_grp_n;
    380     int fc_only_uc;
    381 
    382     for (q_num = 0; q_num < TH3_PFC_MMU_QUEUE_NUM; q_num++) {
    383         cos_f_q = soc_tomahawk3_get_cos_for_mmu_queue(unit, profile_id, q_num);
    384         if (cos_f_q == -1) {
    385             return SOC_E_PARAM;
    386         }
    387         eb_grp_n = eb_config->eb_group[cos_f_q];
    388 
    389         fc_only_uc = soc_tomahawk3_get_fc_only_uc_for_cos(unit, profile_id,
    390                 cos_f_q);
    391         if (_soc_th3_pfc_mmuq_is_mc(unit, q_num) && fc_only_uc) {
    392             for (i = eb_grp_n; i >= 0; i--) {
    393                 if (eb_config->eb_group_opt[i] != 1) {
    394                     break;
    395                 }
    396             }
    397             if (i >= 0) {
    398                 eb_config->mmuq_eb_group[q_num] = i;
    399             } else {
    400                 return SOC_E_FAIL;
    401             }
    402 
    403         } else {
    404             eb_config->mmuq_eb_group[q_num] = eb_grp_n;
    405 
    406         }
    407     }
    408     return SOC_E_NONE;
    409 }
    410 
    411 /*
    412  * Function:
    413  *     _soc_th3_pfc_rx_mapping_hw_write
    414  * Purpose:
    415  *     Write PFC-rx realted HW tables/registers
    416  * Parameters:
    417  *     unit       -  (IN) unit number
    418  *     config_arry - (IN) PFC rx config array
    419  *     len         - (IN) array length
    420  *     eb_config  -  (IN) EB group config
    421  *     profile_id -  (IN) Profile index
    422  * Returns:
    423  *     SOC_E_XXX
    424  */
    425 
    426 STATIC int
    427 _soc_th3_pfc_rx_mapping_hw_write(
    428     int unit,
    429     int profile_id,
    430     soc_cosq_pfc_class_map_config_t *config_array,
    431     int len,
    432     _soc_th3_pfc_eb_group_config_t *eb_config)
    433 {
    434     int i, pri, cos, pri_ebg, mmuq1 = -1, mmuq2 = -1;
    435     uint32 cos_bmp, mmuq_bmp, ebg_bmp, sp_bmp, hp_bmp, reg_index, rval;
    436     uint64 rval64;
    437     int fc_only_uc = 0, cos_f_q = 0;
    438 
    439     soc_reg_t pri_reg = MMU_INTFI_PFCPRI_PROFILEr,
    440               mmuq_reg = MMU_EBCFP_MMUQ_EBGRP_PROFILEr,
    441               sp_reg = MMU_EBQS_EBQ_PROFILEr,
    442               hp_reg = MMU_OQS_AGER_Q_PROFILE_HP_MMUQr;
    443 
    444     soc_field_t mmuq_field = PFCPRI_MMUQ_BMPf,
    445                 ebg_field = PFCPRI_EBGRP_BMPf,
    446                 sp_field = SP_ENABLE_BMPf,
    447                 hp_field = HP_MMUQ_BITMAPf;
    448 
    449     soc_field_t mmuq_fields[] = {
    450                     MMUQ0_EBGRP_NUMf, MMUQ1_EBGRP_NUMf, MMUQ2_EBGRP_NUMf,
    451                     MMUQ3_EBGRP_NUMf, MMUQ4_EBGRP_NUMf, MMUQ5_EBGRP_NUMf,
    452                     MMUQ6_EBGRP_NUMf, MMUQ7_EBGRP_NUMf, MMUQ8_EBGRP_NUMf,
    453                     MMUQ9_EBGRP_NUMf, MMUQ10_EBGRP_NUMf, MMUQ11_EBGRP_NUMf
    454                 };
    455 
    456     /* write PFC-rx priority to MMUq(s) and EB group(s) Mapping profile */
    457     for (pri = 0; pri < TH3_PFC_PRIORITY_NUM && pri < len; pri++) {
    458         mmuq_bmp = 0;
    459         ebg_bmp = 0;
    460         cos_bmp = config_array[pri].cos_list_bmp;
    461 
    462         reg_index = profile_id + pri * TH3_PFC_RX_PROFILE_NUM_ENTRIES;
    463         SOC_TH3_PFC_BMP_ITER(cos_bmp, TH3_PFC_COS_NUM, cos) {
    464             int idx = -1;
    465             int l0_idx = -1;
    466             for (idx = 0; idx < SOC_TH3_NUM_GP_QUEUES; idx++) {
    467                 if (th3_sched_profile_info[unit][profile_id][idx].cos == cos) {
    468                     l0_idx = idx;
    469                     break;
    470                 }
    471             }
    472             if (l0_idx != -1) {
    473                 mmuq1 = th3_sched_profile_info[unit][profile_id][l0_idx].mmuq[0];
    474                 mmuq2 = th3_sched_profile_info[unit][profile_id][l0_idx].mmuq[1];
    475             }
    476 
    477             /* flow control just the UC queue when FC_ONLY_UC=1. */
    478             if ((mmuq1 != -1) && (mmuq2 != -1)) {
    479                 cos_f_q = soc_tomahawk3_get_cos_for_mmu_queue(unit, profile_id, mmuq1);
    480                 if (cos_f_q == -1) {
    481                     return SOC_E_PARAM;
    482                 }
    483                 fc_only_uc = soc_tomahawk3_get_fc_only_uc_for_cos(unit, profile_id,
    484                                                                   cos_f_q);
    485                 if (!(_soc_th3_pfc_mmuq_is_mc(unit, mmuq1) && (fc_only_uc))) {
    486                     mmuq_bmp |= 1U << mmuq1;
    487                 }
    488 
    489                 if (!(_soc_th3_pfc_mmuq_is_mc(unit, mmuq2) && (fc_only_uc))) {
    490                     mmuq_bmp |= 1U << mmuq2;
    491                 }
    492             } else {
    493                 if (mmuq1 != -1) {
    494                     mmuq_bmp |= 1U << mmuq1;
    495                 }
    496                 if (mmuq2 != -1) {
    497                     mmuq_bmp |= 1U << mmuq2;
    498                 }
    499             }
    500 
    501             pri_ebg = eb_config->eb_group[cos];
    502             if (eb_config->eb_group_opt[pri_ebg] == 1) {
    503                 ebg_bmp |= 1U << pri_ebg;
    504             }
    505         }
    506 
    507         SOC_TH3_PFC_BMP_ITER(cos_bmp, TH3_PFC_COS_NUM, cos) {
    508             if (eb_config->eb_group_opt[eb_config->eb_group[cos]] == 0) {
    509                 ebg_bmp = 0;
    510                 break;
    511             }
    512         }
    513 
    514         SOC_IF_ERROR_RETURN
    515             (soc_reg32_get(unit, pri_reg, REG_PORT_ANY, reg_index, &rval));
    516         soc_reg_field_set(unit, pri_reg, &rval, mmuq_field, mmuq_bmp);
    517         soc_reg_field_set(unit, pri_reg, &rval, ebg_field, ebg_bmp);
    518         SOC_IF_ERROR_RETURN
    519             (soc_reg32_set(unit, pri_reg, REG_PORT_ANY, reg_index, rval));
    520 
    521     }
    522 
    523     /* write MMUq to EB group mapping profile */
    524     COMPILER_64_ZERO(rval64);
    525     SOC_IF_ERROR_RETURN
    526             (soc_reg64_get(unit, mmuq_reg, REG_PORT_ANY, profile_id, &rval64));
    527 
    528     for (i = 0; i < TH3_PFC_MMU_QUEUE_NUM; i++) {
    529         soc_reg64_field32_set(unit, mmuq_reg, &rval64, mmuq_fields[i],
    530                                             eb_config->mmuq_eb_group[i]);
    531     }
    532     SOC_IF_ERROR_RETURN
    533             (soc_reg64_set(unit, mmuq_reg, REG_PORT_ANY, profile_id, rval64));
    534 
    535     sp_bmp = 0;
    536     for (i = 0; i < _TH3_PFC_EB_GROUP_NUM; i++) {
    537         if (eb_config->eb_group_sp[i] == 1) {
    538             sp_bmp |= 1U << i;
    539         }
    540     }
    541     /* static scheduling setting for EB groups */
    542     rval = 0;
    543     SOC_IF_ERROR_RETURN
    544         (soc_reg32_get(unit, sp_reg, REG_PORT_ANY, profile_id, &rval));
    545     soc_reg_field_set(unit, sp_reg, &rval, sp_field, sp_bmp);
    546     SOC_IF_ERROR_RETURN
    547         (soc_reg32_set(unit, sp_reg, REG_PORT_ANY, profile_id, rval));
    548 
    549     /* if MMUQ is mapped to a static-priority EB, then it is HP queue */
    550     hp_bmp = 0;
    551     for (i = 0; i < TH3_PFC_MMU_QUEUE_NUM; i++) {
    552         if(eb_config->eb_group_sp[eb_config->mmuq_eb_group[i]] == 1) {
    553             hp_bmp |= 1U << i;
    554         }
    555     }
    556     rval = 0;
    557     SOC_IF_ERROR_RETURN
    558         (soc_reg32_get(unit, hp_reg, REG_PORT_ANY, profile_id, &rval));
    559     soc_reg_field_set(unit, hp_reg, &rval, hp_field, hp_bmp);
    560 
    561     SOC_IF_ERROR_RETURN
    562         (soc_reg32_set(unit, hp_reg, REG_PORT_ANY, profile_id, rval));
    563 
    564     return SOC_E_NONE;
    565 }
    566 
    567 int
    568 soc_th3_pfc_rx_priority_mapping_profile_get(
    569     int unit,
    570     int profile_id,
    571     int max_count,
    572     soc_cosq_pfc_class_map_config_t *config_array,
    573     int *count)
    574 {
    575     int pri;
    576     uint32 cos_bmp, mmuq_bmp, ebg_bmp, reg_index, rval, mmuq, cos_id;
    577 
    578     soc_reg_t pri_reg = MMU_INTFI_PFCPRI_PROFILEr;
    579     soc_field_t mmuq_field = PFCPRI_MMUQ_BMPf,
    580                 ebg_field = PFCPRI_EBGRP_BMPf;
    581 
    582     /* if max_count = 0, config_array has to be NULL */
    583     if(max_count == 0) {
    584         if((NULL != config_array))
    585             return SOC_E_PARAM;
    586     }
    587 
    588     if(profile_id < TH3_PFC_CLASS_PROFILE_ID_MIN ||
    589                    profile_id > TH3_PFC_CLASS_PROFILE_ID_MAX) {
    590 
    591         return SOC_E_PARAM;
    592     }
    593 
    594     for(pri = 0; pri < max_count && pri < TH3_PFC_PRIORITY_NUM; pri++) {
    595         cos_bmp = 0;
    596 
    597         rval = 0;
    598         reg_index = profile_id + pri * TH3_PFC_RX_PROFILE_NUM_ENTRIES;
    599         SOC_IF_ERROR_RETURN
    600             (soc_reg32_get(unit, pri_reg, REG_PORT_ANY, reg_index, &rval));
    601         mmuq_bmp = soc_reg_field_get(unit, pri_reg, rval, mmuq_field);
    602         ebg_bmp = soc_reg_field_get(unit, pri_reg, rval, ebg_field);
    603 
    604         if(mmuq_bmp != 0) {
    605             config_array[pri].pfc_enable = 1;
    606             SOC_TH3_PFC_BMP_ITER(mmuq_bmp, TH3_PFC_MMU_QUEUE_NUM, mmuq) {
    607                 cos_id = soc_tomahawk3_get_cos_for_mmu_queue(unit, profile_id, mmuq);
    608                 cos_bmp |= 1U << cos_id;
    609             }
    610             config_array[pri].cos_list_bmp = cos_bmp;
    611         }
    612 
    613         if(ebg_bmp != 0) config_array[pri].pfc_optimized = 1;
    614 
    615     }
    616 
    617     *count = pri;
    618 
    619     return SOC_E_NONE;
    620 }
    621 
    622 STATIC int
    623 _soc_th3_pfc_check_higher_pri_cos_bmp(int unit, soc_cosq_pfc_class_map_config_t
    624         *config_array, int pri_num)
    625 {
    626     int pri;
    627 
    628     for (pri = (pri_num + 1); pri <= _TH3_PFC_PRIORITY_MAX_INDEX; pri++ ) {
    629         if (config_array[pri_num].cos_list_bmp ==
    630                 config_array[pri].cos_list_bmp) {
    631             return 1;
    632         }
    633     }
    634 
    635     return 0;
    636 }
    637 
    638 
    639 /*
    640  * Function:
    641  *      soc_th3_pfc_rx_priority_mapping_profile_set
    642  * Purpose:
    643  *      Set the PFC rx priority to MMU and EB group mapping.
    644  * Parameters:
    645  *      unit       - (IN) device id.
    646  *      port     - (IN) logic port.
    647  *      config_array   - (IN) PFC rx config array.
    648  *      count  - (IN) The length of array
    649  *                    It needs to be fixed at 8. All PFC priorities should
    650  *                    be configured at once, and the config array must be
    651  *                    arranged in ascending order of PFC priorities.
    652  *                    0, 1, ... , 7.
    653  * Returns:
    654  *      SOC_E_XXX
    655  */
    656 
    657 int
    658 soc_th3_pfc_rx_priority_mapping_profile_set(
    659     int unit,
    660     int profile_id,
    661     soc_cosq_pfc_class_map_config_t  *config_array,
    662     int count)
    663 {
    664 
    665     int pri_num, cos_num;
    666     int opt_count = 0;
    667     _soc_th3_pfc_eb_group_config_t eb_config;
    668 
    669 
    670 
    671     if (profile_id < TH3_PFC_CLASS_PROFILE_ID_MIN ||
    672                    profile_id > TH3_PFC_CLASS_PROFILE_ID_MAX) {
    673         return SOC_E_PARAM;
    674     }
    675 
    676     if (config_array == NULL || count != TH3_PFC_PRIORITY_NUM)
    677         return SOC_E_PARAM;
    678 
    679     SOC_IF_ERROR_RETURN
    680             (_soc_th3_pfc_rx_config_validate(unit, config_array, count));
    681 
    682     _soc_th3_pfc_eb_group_config_t_init(&eb_config);
    683 
    684     /* Start from priority 7 and check every priority */
    685     for (pri_num = _TH3_PFC_PRIORITY_MAX_INDEX; pri_num >= 0; pri_num--) {
    686         if (config_array[pri_num].pfc_optimized == 1
    687                                 && config_array[pri_num].cos_list_bmp !=0) {
    688             /* If PFC_Optimized(priority) is set and cos_list_bmp is not 0  &&
    689              * no other higher PFC optimized priority has same cos list */
    690             if (!_soc_th3_pfc_check_higher_pri_cos_bmp(unit, config_array,
    691                         pri_num)) {
    692                     opt_count++;
    693             }
    694             /* set PFC_Optimized_Group(cos) for every cos in the list
    695              *to the same value opt_count
    696              * opt_count is the number of PFC optimized groups used so far
    697             */
    698             for (cos_num = 0; cos_num < TH3_PFC_COS_NUM; cos_num++) {
    699 
    700                 if (SOC_TH3_PFC_BMP_MEMBER(
    701                             config_array[pri_num].cos_list_bmp, cos_num)) {
    702                     eb_config.opt_group[cos_num] = opt_count;
    703                 }
    704             }
    705 
    706         }
    707     }
    708 
    709     SOC_IF_ERROR_RETURN
    710         (_soc_th3_pfc_eb_group_allocate(unit, profile_id, &eb_config, opt_count));
    711 
    712     SOC_IF_ERROR_RETURN
    713         (_soc_th3_pfc_mmuq_to_eb_mapping(unit, profile_id, &eb_config));
    714 
    715     /* Add function to print debug info for CoS-domain intermediary values */
    716     _soc_th3_print_pfc_sched_profile_info(unit, profile_id, &eb_config);
    717 
    718     SOC_IF_ERROR_RETURN
    719         (_soc_th3_pfc_rx_mapping_hw_write(unit, profile_id, config_array, count,
    720                                             &eb_config));
    721 
    722     return SOC_E_NONE;
    723 }
    724 
    725 /*
    726  * Function:
    727  *      soc_th3_pfc_tx_priority_mapping_profile_op
    728  * Purpose:
    729  *      To set/get a PG-property profile.
    730  * Parameters:
    731  *      unit       - (IN) device id.
    732  *      profile_id     - (IN) profile ID.
    733  *      max_count   - (IN) max lenghth of PG array
    734  *                         valid only for _get operation
    735  *      op  - (IN) operation type, _get or _set
    736  *      array_count (IN/OUT) valid length of array
    737  *                          IN for _set, OUT for _get
    738  *      pg_array  (IN/OUT) PG array, index by PFC priority
    739                             IN for _set, OUT for _get
    740  * Returns:
    741  *      SOC_E_XXX
    742  */
    743 
    744 int
    745 soc_th3_pfc_tx_priority_mapping_profile_op(
    746     int unit,
    747     int profile_id,
    748     int max_count,
    749     soc_th3_pfc_pfc_profile_op_t op,
    750     int *array_count,
    751     int *pg_array)
    752 {
    753 #define _TH3_PFC_PRIORITY_GROUP_ID_MAX 7
    754     int i;
    755     uint32 rval;
    756     soc_reg_t reg = MMU_THDI_PFCPRI_PG_PROFILEr;
    757 
    758     soc_field_t field_array[TH3_PFC_PRIORITY_NUM] = {
    759                 PFCPRI0_PGf, PFCPRI1_PGf, PFCPRI2_PGf, PFCPRI3_PGf,
    760                 PFCPRI4_PGf, PFCPRI5_PGf, PFCPRI6_PGf, PFCPRI7_PGf
    761     };
    762     if (profile_id < TH3_PFC_PROPERTIES_PROFILE_ID_MIN ||
    763                    profile_id > TH3_PFC_PROPERTIES_PROFILE_ID_MAX) {
    764 
    765         return SOC_E_PARAM;
    766     }
    767 
    768 
    769     SOC_IF_ERROR_RETURN
    770                 (soc_reg32_get(unit, reg, REG_PORT_ANY, profile_id, &rval));
    771 
    772     if (SOC_TH3_PFC_PROFILE_OP_SET == op) {
    773         if (*array_count > TH3_PFC_PRIORITY_NUM || *array_count <= 0) {
    774             return SOC_E_PARAM;
    775         }
    776 
    777         if (pg_array == NULL) {
    778             return SOC_E_PARAM;
    779         }
    780 
    781         for (i = 0; i < *array_count; i++) {
    782             if (pg_array[i] < 0 || pg_array[i] > _TH3_PFC_PRIORITY_GROUP_ID_MAX) {
    783                 return SOC_E_PARAM;
    784             }
    785             soc_reg_field_set(unit, reg, &rval, field_array[i], pg_array[i]);
    786         }
    787         SOC_IF_ERROR_RETURN
    788                 (soc_reg32_set(unit, reg, REG_PORT_ANY, profile_id, rval));
    789     } else if (SOC_TH3_PFC_PROFILE_OP_GET == op) {
    790 
    791         if ((0 == max_count && pg_array != NULL) ||
    792                             (0 != max_count && pg_array == NULL)) {
    793             return SOC_E_PARAM;
    794         }
    795 
    796         for (i = 0; i < max_count && i < TH3_PFC_PRIORITY_NUM; i++) {
    797             pg_array[i] = soc_reg_field_get(unit, reg, rval, field_array[i]);
    798         }
    799         *array_count = i;
    800     }
    801 
    802     return SOC_E_NONE;
    803 }
    804 
    805 /*
    806  * Function:
    807  *      soc_th3_pfc_pg_profile_op
    808  * Purpose:
    809  *      To set/get a PG-property profile.
    810  * Parameters:
    811  *      unit       - (IN) device id.
    812  *      profile_id     - (IN) profile ID.
    813  *      max_count   - (IN) max lenghth of PG-property config array
    814  *                         valid only for _get operation
    815  *      op  - (IN) operation type, _get or _set
    816  *      array_count (IN/OUT) valid length of array
    817  *                          IN for _set, OUT for _get
    818  *      properties  (IN/OUT) PG-property config array
    819                             IN for _set, OUT for _get
    820  * Returns:
    821  *      SOC_E_XXX
    822  */
    823 
    824 int
    825 soc_th3_pfc_pg_profile_op(
    826     int unit,
    827     int profile_id,
    828     int max_count,
    829     soc_th3_pfc_pfc_profile_op_t op,
    830     int* array_count,
    831     soc_cosq_priority_group_properties_t *properties)
    832 {
    833 #define _TH3_PFC_SPID_MAX_INDEX 3
    834 #define _TH3_PFC_HDRMID_MAX_INDEX 3
    835     int i, pg_id;
    836     uint64 rval;
    837     soc_reg_t reg = MMU_THDI_PG_PROFILEr;
    838 
    839     soc_field_t hdrm_farray[_TH3_PFC_PRIORITY_GROUP_NUM] = {
    840                 PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf,
    841                 PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf
    842     };
    843     soc_field_t sp_farray[_TH3_PFC_PRIORITY_GROUP_NUM] = {
    844                 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
    845                 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf,
    846     };
    847 
    848     if (profile_id < TH3_PFC_PROPERTIES_PROFILE_ID_MIN ||
    849                    profile_id > TH3_PFC_PROPERTIES_PROFILE_ID_MAX) {
    850         return SOC_E_PARAM;
    851     }
    852 
    853 
    854     SOC_IF_ERROR_RETURN
    855                 (soc_reg64_get(unit, reg, REG_PORT_ANY, profile_id, &rval));
    856 
    857     if (SOC_TH3_PFC_PROFILE_OP_SET == op) {
    858         if (*array_count < 0 || *array_count > _TH3_PFC_PRIORITY_GROUP_NUM) {
    859             return SOC_E_PARAM;
    860         }
    861          if (properties == NULL) {
    862             return SOC_E_PARAM;
    863          }
    864 
    865         for (i = 0; i < *array_count; i++) {
    866             pg_id = properties[i].priority_group_id;
    867             if (pg_id != -1) {
    868                 if(pg_id < 0 || pg_id >= _TH3_PFC_PRIORITY_GROUP_NUM) {
    869                     return SOC_E_PARAM;
    870                 }
    871             } else {
    872                 continue;
    873             }
    874             if (properties[i].service_pool_id != -1) {
    875                 if(properties[i].service_pool_id < 0 ||
    876                     properties[i].service_pool_id > _TH3_PFC_SPID_MAX_INDEX) {
    877                     return SOC_E_PARAM;
    878                 }
    879                 soc_reg64_field32_set(unit, reg, &rval, sp_farray[pg_id],
    880                                         properties[i].service_pool_id);
    881             }
    882             if (properties[i].headroom_pool_id != -1) {
    883                 if(properties[i].headroom_pool_id < 0 ||
    884                         properties[i].headroom_pool_id > _TH3_PFC_HDRMID_MAX_INDEX) {
    885                     return SOC_E_PARAM;
    886                 }
    887                 soc_reg64_field32_set(unit, reg, &rval, hdrm_farray[pg_id],
    888                                             properties[i].headroom_pool_id);
    889             }
    890         }
    891         SOC_IF_ERROR_RETURN
    892                 (soc_reg64_set(unit, reg, REG_PORT_ANY, profile_id, rval));
    893 
    894     } else if (SOC_TH3_PFC_PROFILE_OP_GET == op) {
    895          if ((0 == max_count && properties != NULL) ||
    896                             (0 != max_count && properties == NULL)) {
    897             return SOC_E_PARAM;
    898          }
    899          for (i = 0; i < max_count && i < _TH3_PFC_PRIORITY_GROUP_NUM; i++) {
    900             properties[i].priority_group_id = i;
    901 
    902             properties[i].service_pool_id =
    903                         soc_reg64_field32_get(unit, reg, rval, sp_farray[i]);
    904             properties[i].headroom_pool_id =
    905                         soc_reg64_field32_get(unit, reg, rval, hdrm_farray[i]);
    906          }
    907          *array_count = i;
    908     }
    909 #undef _TH3_PFC_SPID_MAX_INDEX
    910 #undef _TH3_PFC_HDRMID_MAX_INDEX
    911     return SOC_E_NONE;
    912 }
    913 
    914 /*
    915  * Function:
    916  *      soc_th3_pfc_num_optimized_group_get
    917  * Purpose:
    918  *      Get the maximum number of optimized PFC groups for a given port.
    919  * Parameters:
    920  *      unit       - (IN) device id.
    921  *      port       - (IN) logic port number.
    922  *      num        - (OUT) number of optimized PFC groups supported.
    923  * Returns:
    924  *      SOC_E_XXX
    925  */
    926 
    927 int
    928 soc_th3_pfc_num_optimized_group_get(
    929     int unit,
    930     soc_port_t port,
    931     int *num)
    932 {
    933     int speed, mtu_size;
    934     uint32 speed_id, mtu_id;
    935     soc_info_t *si = &SOC_INFO(unit);
    936 
    937     /* PFC optimized group is not supported for LB port */
    938     if (SOC_PBMP_MEMBER(si->lb_pbm, port)) {
    939         *num = 0;
    940         return SOC_E_NONE;
    941     }
    942 
    943     if (IS_MANAGEMENT_PORT(unit,port)) {
    944         speed = si->port_speed_max[port];
    945     } else if (si->flex_eligible) {
    946         speed = 50000;
    947     } else {
    948         speed = si->port_init_speed[port];
    949         if (speed == 0) {
    950             speed = si->port_speed_max[port];
    951         }
    952     }
    953     speed_id = _soc_th3_pfc_speed_encoding_get(unit, speed);
    954 
    955     mtu_size = soc_property_get(unit, spn_MMU_PFC_GROUP_OPTIMIZED_MTU_SIZE, 9416);
    956     mtu_id = _soc_th3_pfc_mtu_encoding_get(unit, mtu_size);
    957 
    958     if (mtu_id == -1 || speed_id == -1) {
    959         return SOC_E_PARAM;
    960     }
    961     if (IS_MANAGEMENT_PORT(unit,port)) {
    962         *num = magt_opt_group_num_flexport[mtu_id];
    963     } else if (IS_LB_PORT(unit,port)) {
    964         *num = 0;
    965     } else {
    966         *num = opt_group_num_flexport[mtu_id][speed_id];
    967     }
    968     return SOC_E_NONE;
    969 }
    970 
    971 /*
    972  * Function:
    973  *      soc_th3_pfc_config_profile_id_set
    974  * Purpose:
    975  *      Set the PFC-related profile ID for a given port.
    976  * Parameters:
    977  *      unit       - (IN) device id.
    978  *      port       - (IN) logic port number.
    979  *      type       - (IN) profile type.
    980  *      profile_id - (IN) profile ID.
    981  * Returns:
    982  *      SOC_E_XXX
    983  */
    984 
    985 int
    986 soc_th3_pfc_config_profile_id_set(
    987     int unit,
    988     soc_port_t port,
    989     soc_th3_pfc_profile_t type,
    990     uint32 profile_id)
    991 {
    992 
    993     soc_reg_t reg = INVALIDr;
    994     soc_field_t field = INVALIDf;
    995     uint32 rval;
    996     int i, count = 0, opt_num = 0, max_opt_num = 0;
    997     soc_cosq_pfc_class_map_config_t config_array[TH3_PFC_PRIORITY_NUM];
    998     sal_memset(config_array, 0, sizeof(soc_cosq_pfc_class_map_config_t) * TH3_PFC_PRIORITY_NUM);
    999     if (type >= socTH3PFCProfileMax) {
   1000         return SOC_E_PARAM;
   1001     }
   1002 
   1003     switch(type) {
   1004         case socTH3PFCPGProperties:
   1005             if (profile_id > TH3_PFC_PROPERTIES_PROFILE_ID_MAX) {
   1006                 return SOC_E_PARAM;
   1007             }
   1008             reg = MMU_THDI_ING_PORT_CONFIGr;
   1009             field = PG_PROFILE_SELf;
   1010             break;
   1011 
   1012 
   1013         case socTH3PFCReceiveClass:
   1014             if (profile_id > TH3_PFC_CLASS_PROFILE_ID_MAX) {
   1015                 return SOC_E_PARAM;
   1016             }
   1017             /* check if a port can have the required number of PFC optimized groups */
   1018             SOC_IF_ERROR_RETURN(soc_th3_pfc_num_optimized_group_get(
   1019                                    unit, port, &max_opt_num));
   1020             SOC_IF_ERROR_RETURN(
   1021                 soc_th3_pfc_rx_priority_mapping_profile_get(unit, profile_id,
   1022                     TH3_PFC_PRIORITY_NUM, config_array, &count));
   1023             for (i =0; i < count; i++) {
   1024                 if (config_array[i].pfc_optimized) {
   1025                     opt_num++;
   1026                     if (opt_num > max_opt_num) {
   1027                         return SOC_E_PARAM;
   1028                     }
   1029                 }
   1030             }
   1031             reg = MMU_EBQS_PORT_CFGr;
   1032             field = PROFILE_SELf;
   1033 
   1034             SOC_IF_ERROR_RETURN(
   1035                 soc_reg32_get(unit, reg, port, 0, &rval));
   1036             soc_reg_field_set(unit, reg, &rval, field, profile_id);
   1037             SOC_IF_ERROR_RETURN
   1038                     (soc_reg32_set(unit, reg, port, 0, rval));
   1039 
   1040             reg = MMU_EBCFP_EGR_PORT_CFGr;
   1041             field = PROFILE_SELf;
   1042             SOC_IF_ERROR_RETURN(
   1043                 soc_reg32_get(unit, reg, port, 0, &rval));
   1044             soc_reg_field_set(unit, reg, &rval, field, profile_id);
   1045             SOC_IF_ERROR_RETURN
   1046                     (soc_reg32_set(unit, reg, port, 0, rval));
   1047 
   1048             reg = MMU_OQS_AGER_DST_PORT_MAPr;
   1049             field = PROFILE_SELf;
   1050             SOC_IF_ERROR_RETURN(
   1051                 soc_reg32_get(unit, reg, port, 0, &rval));
   1052             soc_reg_field_set(unit, reg, &rval, field, profile_id);
   1053             SOC_IF_ERROR_RETURN
   1054                     (soc_reg32_set(unit, reg, port, 0, rval));
   1055 
   1056             reg = MMU_INTFI_EGR_PORT_CFGr;
   1057             field = PROFILE_SELf;
   1058             break;
   1059 
   1060         default:
   1061             return SOC_E_UNAVAIL;
   1062 
   1063     }
   1064 
   1065     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   1066     soc_reg_field_set(unit, reg, &rval, field, profile_id);
   1067     SOC_IF_ERROR_RETURN
   1068                     (soc_reg32_set(unit, reg, port, 0, rval));
   1069     return SOC_E_NONE;
   1070 
   1071 }
   1072 
   1073 /*
   1074  * Function:
   1075  *      soc_th3_pfc_config_profile_id_get
   1076  * Purpose:
   1077  *      Get the PFC-related profile ID for a given port.
   1078  * Parameters:
   1079  *      unit       - (IN) device id.
   1080  *      port       - (IN) logic port number.
   1081  *      type       - (IN) profile type.
   1082  *      profile_id - (OUT) profile ID.
   1083  * Returns:
   1084  *      SOC_E_XXX
   1085  */
   1086 
   1087 int
   1088 soc_th3_pfc_config_profile_id_get(
   1089     int unit,
   1090     soc_port_t port,
   1091     soc_th3_pfc_profile_t type,
   1092     uint32 *profile_id)
   1093 {
   1094 
   1095     soc_reg_t reg = INVALIDr;
   1096     soc_field_t field = INVALIDf;
   1097     uint32 rval, fval;
   1098 
   1099     if (profile_id == NULL || type >= socTH3PFCProfileMax) {
   1100         return SOC_E_PARAM;
   1101     }
   1102 
   1103     switch(type) {
   1104         case socTH3PFCPGProperties:
   1105             reg = MMU_THDI_ING_PORT_CONFIGr;
   1106             field = PG_PROFILE_SELf;
   1107             break;
   1108 
   1109         case socTH3PFCReceiveClass:
   1110             reg = MMU_INTFI_EGR_PORT_CFGr;
   1111             field = PROFILE_SELf;
   1112             break;
   1113 
   1114         default:
   1115             return SOC_E_UNAVAIL;
   1116 
   1117     }
   1118 
   1119     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   1120     fval = soc_reg_field_get(unit, reg, rval, field);
   1121     *profile_id = fval;
   1122 
   1123     return SOC_E_NONE;
   1124 
   1125 }
   1126 
   1127 /*
   1128  * Function:
   1129  *      soc_th3_pfc_rx_init_from_cfg
   1130  * Purpose:
   1131  *      To set PFC class profile from config variables
   1132  *      during init time.
   1133  *      config variables should follow the format below
   1134  *      1. mmu_pfc_class_profile_<profile_id>.pfc_priority<priority number>. \
   1135  *       cos_list=<Comma Seperated Values>
   1136  *      2. mmu_pfc_class_profile_<profile_id>.pfc_priority. \
   1137  *       optimized=<Comma Seperated Values>, the number of values should be equal
   1138  *       to the # of PFC priorities. 0: non-optimized, 1: optimized.
   1139  * Parameters:
   1140  *      unit       - (IN) device id.
   1141  * Returns:
   1142  *      SOC_E_XXX
   1143  */
   1144 
   1145 int
   1146 soc_th3_pfc_rx_init_from_cfg(int unit)
   1147 {
   1148     int i, j, cos_idx, count, rv = SOC_E_NONE, set_profile = 0;
   1149     char s_name[SOC_PROPERTY_NAME_MAX], s_opt[SOC_PROPERTY_NAME_MAX];
   1150     int cos_list[TH3_PFC_COS_NUM], opt_val[TH3_PFC_PRIORITY_NUM];
   1151     soc_cosq_pfc_class_map_config_t rx_config[TH3_PFC_PRIORITY_NUM];
   1152     int mtu_size;
   1153     uint32 rval = 0;
   1154 
   1155     for (i = 0; i <= TH3_PFC_CLASS_PROFILE_ID_MAX; i++) {
   1156         set_profile = 0;
   1157         sal_memset(rx_config, 0, TH3_PFC_PRIORITY_NUM * sizeof(rx_config[0]));
   1158         sal_memset(opt_val, 0, TH3_PFC_PRIORITY_NUM * sizeof(opt_val[0]));
   1159 
   1160         /* read pfc optimized config per profile */
   1161         sal_sprintf(s_opt, "%s_%d.%s.%s",
   1162                         spn_MMU_PFC_CLASS_PROFILE, i,
   1163                             spn_PFC_PRIORITY, spn_OPTIMIZED);
   1164         (void) soc_property_get_csv
   1165                         (unit, s_opt, TH3_PFC_PRIORITY_NUM, opt_val);
   1166 
   1167         /* read cos_list per PFC priority per Profile
   1168          * , and fill structure soc_cosq_pfc_class_map_config_t
   1169         */
   1170         for (j = 0; j < TH3_PFC_PRIORITY_NUM; j++) {
   1171 
   1172             rx_config[j].pfc_optimized = opt_val[j];
   1173 
   1174             sal_sprintf(s_name, "%s_%d.%s%d.%s",
   1175                         spn_MMU_PFC_CLASS_PROFILE, i,
   1176                           spn_PFC_PRIORITY, j, spn_COS_LIST);
   1177             count = soc_property_get_csv
   1178                         (unit, s_name, TH3_PFC_COS_NUM, cos_list);
   1179             if (!count) {
   1180                 continue;
   1181             }
   1182             for (cos_idx = 0; cos_idx < count; cos_idx++) {
   1183                 rx_config[j].cos_list_bmp |= 1U << cos_list[cos_idx];
   1184                 rx_config[j].pfc_enable = 1;
   1185             }
   1186             if (!set_profile) {
   1187                 set_profile = 1;
   1188             }
   1189         }
   1190 
   1191         if (set_profile) {
   1192             rv = soc_th3_pfc_rx_priority_mapping_profile_set
   1193                     (unit, i, rx_config, TH3_PFC_PRIORITY_NUM);
   1194             if (rv != SOC_E_NONE) {
   1195                 /* Output error log */
   1196             }
   1197         }
   1198     }
   1199 
   1200     mtu_size =  soc_property_get(unit, spn_MMU_PFC_GROUP_OPTIMIZED_MTU_SIZE, 9416);
   1201 
   1202     if (mtu_size < 9416) {
   1203         mtu_size = (mtu_size + _TH3_MMU_BYTES_PER_CELL - 1) / _TH3_MMU_BYTES_PER_CELL;
   1204         rval = 0;
   1205         SOC_IF_ERROR_RETURN
   1206             (soc_reg32_get(unit, MMU_EBCFP_OPT_EBGRP_REDUCED_MTUr,
   1207                            REG_PORT_ANY, 0, &rval));
   1208 
   1209         soc_reg_field_set(unit, MMU_EBCFP_OPT_EBGRP_REDUCED_MTUr, &rval,
   1210                          REDUCED_MTUf, mtu_size);
   1211         SOC_IF_ERROR_RETURN
   1212             (soc_reg32_set(unit, MMU_EBCFP_OPT_EBGRP_REDUCED_MTUr,
   1213                            REG_PORT_ANY, 0, rval));
   1214 
   1215        /* specify to use this setting for all 8 profiles and 8 PFC priorities. */
   1216         for (i = 0; i <= TH3_PFC_CLASS_PROFILE_ID_MAX; i++) {
   1217             SOC_IF_ERROR_RETURN
   1218                 (soc_reg32_get(unit, MMU_EBCFP_OPT_EBGRP_MTU_PROFILEr,
   1219                                REG_PORT_ANY, i, &rval));
   1220             soc_reg_field_set(unit, MMU_EBCFP_OPT_EBGRP_MTU_PROFILEr,
   1221                              &rval, OPT_EBGRP_MAX_MTU_BMPf, 0);
   1222             SOC_IF_ERROR_RETURN
   1223                 (soc_reg32_set(unit, MMU_EBCFP_OPT_EBGRP_MTU_PROFILEr,
   1224                                REG_PORT_ANY, i, rval));
   1225         }
   1226     }
   1227     return SOC_E_NONE;
   1228 }
   1229 
   1230 /* PFC priority to PG mapping is also handled in THDI code*/
   1231 
   1232 /*
   1233  * Function:
   1234  *      soc_th3_pfc_priority_to_pg_map_init_from_cfg
   1235  * Purpose:
   1236  *      To set PFC-tx priority to PG mapping profile from config variables
   1237  *      during init time.
   1238  *      config variables should follow the format below:
   1239  *      buf.mapprofile<profile_id>.pfcclass_to_priority_group=<csv>
   1240  * Parameters:
   1241  *      unit       - (IN) device id.
   1242  * Returns:
   1243  *      SOC_E_XXX
   1244  */
   1245 
   1246 int
   1247 soc_th3_pfc_priority_to_pg_map_init_from_cfg(int unit)
   1248 {
   1249     int i, count, rv = SOC_E_NONE;
   1250     char s_name[SOC_PROPERTY_NAME_MAX];
   1251     int pg_list[TH3_PFC_PRIORITY_NUM];
   1252 
   1253     sal_memset(pg_list, 0, TH3_PFC_PRIORITY_NUM * sizeof(pg_list[0]));
   1254 
   1255     for (i = 0; i <= TH3_PFC_CLASS_PROFILE_ID_MAX; i++) {
   1256 
   1257         /* read PFC-tx to PG mapping per profile */
   1258         sal_sprintf(s_name, "%s.%s%d.%s",
   1259                         spn_BUF, spn_MAPPROFILE, i, spn_PFCCLASS_TO_PRIORITY_GROUP);
   1260         count = soc_property_get_csv
   1261                         (unit, s_name, TH3_PFC_PRIORITY_NUM, pg_list);
   1262         if (count > 0) {
   1263             rv = soc_th3_pfc_tx_priority_mapping_profile_op(
   1264                 unit, i, TH3_PFC_PRIORITY_NUM, SOC_TH3_PFC_PROFILE_OP_SET,
   1265                     &count, pg_list);
   1266         }
   1267 
   1268         if (rv != SOC_E_NONE) {
   1269             /* Output error log */
   1270         }
   1271 
   1272     }
   1273     return SOC_E_NONE;
   1274 }
   1275 
   1276 #endif