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

ipmc.c (18262B)


      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:        ipmc.c
      8  * Purpose:     Tomahawk3 multicast replication implementation.
      9  */
     10 #ifdef BCM_TOMAHAWK3_SUPPORT
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/defs.h>
     15 #include <sal/core/libc.h>
     16 
     17 #include <soc/drv.h>
     18 #include <soc/mem.h>
     19 
     20 #include <bcm/types.h>
     21 #include <bcm/error.h>
     22 
     23 #include <bcm_int/esw_dispatch.h>
     24 #include <bcm_int/esw/ipmc.h>
     25 #include <bcm_int/esw/tomahawk.h>
     26 #include <bcm_int/esw/tomahawk3.h>
     27 #include <bcm_int/esw/firebolt.h>
     28 
     29 #include <bcm_int/esw/stack.h>
     30 #include <bcm_int/esw/l3.h>
     31 #include <soc/tomahawk.h>
     32 #include <soc/tomahawk3.h>
     33 #include <soc/flexport/tomahawk3_mmu_flexport.h>
     34 
     35 STATIC int
     36 _bcm_th3_repl_head_tbl_read(int unit, int index, uint32 *entry, uint32 *head_ptr)
     37 {
     38     soc_mem_t repl_hd_tbl;
     39 
     40     repl_hd_tbl = MMU_REPL_HEAD_TBLm;
     41     SOC_IF_ERROR_RETURN(soc_mem_read(unit, repl_hd_tbl, MEM_BLOCK_ALL,
     42                                      index, entry));
     43     if (head_ptr) {
     44         *head_ptr = soc_mem_field32_get(unit, repl_hd_tbl, entry, HEAD_PTRf);
     45     }
     46 
     47     return BCM_E_NONE;
     48 }
     49 
     50 
     51 STATIC int
     52 _bcm_th3_repl_head_tbl_write(int unit, int index, uint32 *entry)
     53 {
     54     soc_mem_t repl_hd_tbl;
     55     repl_hd_tbl = MMU_REPL_HEAD_TBLm;
     56     SOC_IF_ERROR_RETURN(soc_mem_write(unit, repl_hd_tbl, MEM_BLOCK_ALL,
     57                                           index, entry));
     58 
     59     return BCM_E_NONE;
     60 }
     61 
     62 /*
     63  * Function:
     64  *	bcm_th3_repl_list_start_ptr_get
     65  * Purpose:
     66  *      Get replication list start pointer for given (repl_group, port).
     67  * Parameters:
     68  *	unit       - StrataSwitch PCI device unit number.
     69  *	repl_group - The replication group number.
     70  *	port       - Port.
     71  *	start_ptr  - (OUT) Replication list's start pointer to
     72  *	             REPL_LIST table.
     73  * Returns:
     74  *	BCM_E_XXX
     75  */
     76 int
     77 bcm_th3_repl_list_start_ptr_get(int unit, int repl_group, bcm_port_t port,
     78         int *start_ptr)
     79 {
     80     soc_mem_t repl_group_table;
     81     soc_field_t member_bitmap_f, head_index_f;
     82     int member_bitmap_index;
     83     mmu_repl_group_info_tbl_entry_t repl_group_entry;
     84     uint32 fldbuf[SOC_PBMP_WORD_MAX];
     85     int i;
     86     soc_pbmp_t member_bitmap;
     87     int member_id, member;
     88     int head_index;
     89     uint32 repl_head_entry[SOC_MAX_MEM_FIELD_WORDS];
     90 
     91     member_bitmap_f = MEMBER_BMPf;
     92     head_index_f = BASE_PTRf;
     93 
     94 #ifdef INCLUDE_L3
     95     if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
     96         BCM_IF_ERROR_RETURN(bcm_th_port_to_aggid(unit, port, &member_bitmap_index));
     97     } else
     98 #endif
     99     {
    100         /* Get member bitmap index */
    101         member_bitmap_index = port;
    102     }
    103 
    104     /* Get member bitmap */
    105     repl_group_table = MMU_REPL_GROUP_INFO_TBLm;
    106 
    107     SOC_IF_ERROR_RETURN
    108         (soc_mem_read(unit, repl_group_table, MEM_BLOCK_ANY,
    109                       repl_group, &repl_group_entry));
    110     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
    111     soc_mem_field_get(unit, repl_group_table, (uint32 *)&repl_group_entry,
    112             member_bitmap_f, fldbuf);
    113     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
    114         SOC_PBMP_WORD_SET(member_bitmap, i, fldbuf[i]);
    115     }
    116 
    117     /* Check if port is in member bitmap */
    118     if (!SOC_PBMP_MEMBER(member_bitmap, member_bitmap_index)) {
    119         *start_ptr = 0;
    120         return BCM_E_NONE;
    121     }
    122 
    123     /* Get replication list start pointer */
    124     member_id = 0;
    125     SOC_PBMP_ITER(member_bitmap, member) {
    126         if (member == member_bitmap_index) {
    127             break;
    128         }
    129         member_id++;
    130     }
    131     head_index = member_id + soc_mem_field32_get(unit, repl_group_table,
    132             &repl_group_entry, head_index_f);
    133 
    134     SOC_IF_ERROR_RETURN
    135             (_bcm_th3_repl_head_tbl_read(unit, head_index,
    136                                      repl_head_entry, (uint32 *)start_ptr));
    137 
    138 
    139     return BCM_E_NONE;
    140 }
    141 
    142 STATIC int
    143 _bcm_th3_initial_copy_count_set(int unit, int repl_head_ptr, int intf_count)
    144 {
    145     /* each replication head entry is associated with a ICC entry*/
    146     int icc_entry_ptr;
    147     int icc_field_index;
    148     mmu_repl_member_icc_entry_t entry;
    149     soc_mem_t mem;
    150     int icc_val;
    151     soc_field_t icc_fields[] = {
    152                               ICC_VAL0f, ICC_VAL1f, ICC_VAL2f, ICC_VAL3f,
    153                               ICC_VAL4f, ICC_VAL5f, ICC_VAL6f, ICC_VAL7f,
    154                               ICC_VAL8f, ICC_VAL9f, ICC_VAL10f, ICC_VAL11f,
    155                               ICC_VAL12f, ICC_VAL13f, ICC_VAL14f, ICC_VAL15f,
    156                               ICC_VAL16f, ICC_VAL17f, ICC_VAL18f, ICC_VAL19f,
    157                               ICC_VAL20f, ICC_VAL21f, ICC_VAL22f, ICC_VAL23f,
    158                               ICC_VAL24f, ICC_VAL25f, ICC_VAL26f, ICC_VAL27f,
    159                               ICC_VAL28f, ICC_VAL29f, ICC_VAL30f, ICC_VAL31f,
    160                               ICC_VAL32f, ICC_VAL33f, ICC_VAL34f, ICC_VAL35f,
    161                               ICC_VAL36f, ICC_VAL37f, ICC_VAL38f, ICC_VAL39f,
    162                               ICC_VAL40f, ICC_VAL41f, ICC_VAL42f, ICC_VAL43f,
    163                               ICC_VAL44f, ICC_VAL45f, ICC_VAL46f, ICC_VAL47f,
    164                               ICC_VAL48f, ICC_VAL49f, ICC_VAL50f, ICC_VAL51f,
    165                               ICC_VAL52f, ICC_VAL53f, ICC_VAL54f, ICC_VAL55f,
    166                               ICC_VAL56f, ICC_VAL57f, ICC_VAL58f, ICC_VAL59f,
    167                               ICC_VAL60f, ICC_VAL61f, ICC_VAL62f, ICC_VAL63f,
    168 
    169                              };
    170     icc_entry_ptr = repl_head_ptr / TH3_IPMC_MAX_INTF_COUNT_PER_ENTRY;
    171     icc_field_index = repl_head_ptr % TH3_IPMC_MAX_INTF_COUNT_PER_ENTRY;
    172     /* ICC value is equal to inft_count for repl counts 1-31 */
    173     /* ICC value will be 0 for repl_count = 0 or > 31*/
    174     icc_val = intf_count > 31 ? 0 : intf_count;
    175     mem = MMU_REPL_MEMBER_ICCm;
    176     SOC_IF_ERROR_RETURN
    177         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, icc_entry_ptr, &entry));
    178     soc_MMU_REPL_MEMBER_ICCm_field32_set(unit, &entry,
    179                     icc_fields[icc_field_index], icc_val);
    180 
    181     SOC_IF_ERROR_RETURN
    182             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, icc_entry_ptr, &entry));
    183 
    184     return BCM_E_NONE;
    185 }
    186 
    187 STATIC int
    188 _bcm_th3_initial_copy_count_get(int unit, int repl_head_ptr, int *intf_count)
    189 {
    190     /* each replication head entry is associated with a ICC entry*/
    191     int icc_entry_ptr;
    192     int icc_field_index;
    193     mmu_repl_member_icc_entry_t entry;
    194     soc_mem_t mem;
    195     soc_field_t icc_fields[] = {
    196                               ICC_VAL0f, ICC_VAL1f, ICC_VAL2f, ICC_VAL3f,
    197                               ICC_VAL4f, ICC_VAL5f, ICC_VAL6f, ICC_VAL7f,
    198                               ICC_VAL8f, ICC_VAL9f, ICC_VAL10f, ICC_VAL11f,
    199                               ICC_VAL12f, ICC_VAL13f, ICC_VAL14f, ICC_VAL15f,
    200                               ICC_VAL16f, ICC_VAL17f, ICC_VAL18f, ICC_VAL19f,
    201                               ICC_VAL20f, ICC_VAL21f, ICC_VAL22f, ICC_VAL23f,
    202                               ICC_VAL24f, ICC_VAL25f, ICC_VAL26f, ICC_VAL27f,
    203                               ICC_VAL28f, ICC_VAL29f, ICC_VAL30f, ICC_VAL31f,
    204                               ICC_VAL32f, ICC_VAL33f, ICC_VAL34f, ICC_VAL35f,
    205                               ICC_VAL36f, ICC_VAL37f, ICC_VAL38f, ICC_VAL39f,
    206                               ICC_VAL40f, ICC_VAL41f, ICC_VAL42f, ICC_VAL43f,
    207                               ICC_VAL44f, ICC_VAL45f, ICC_VAL46f, ICC_VAL47f,
    208                               ICC_VAL48f, ICC_VAL49f, ICC_VAL50f, ICC_VAL51f,
    209                               ICC_VAL52f, ICC_VAL53f, ICC_VAL54f, ICC_VAL55f,
    210                               ICC_VAL56f, ICC_VAL57f, ICC_VAL58f, ICC_VAL59f,
    211                               ICC_VAL60f, ICC_VAL61f, ICC_VAL62f, ICC_VAL63f,
    212 
    213                              };
    214 
    215     if(intf_count == NULL) {
    216         return BCM_E_PARAM;
    217     }
    218     icc_entry_ptr = repl_head_ptr / TH3_IPMC_MAX_INTF_COUNT_PER_ENTRY;
    219     icc_field_index = repl_head_ptr % TH3_IPMC_MAX_INTF_COUNT_PER_ENTRY;
    220 
    221     mem = MMU_REPL_MEMBER_ICCm;
    222     SOC_IF_ERROR_RETURN
    223         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, icc_entry_ptr, &entry));
    224     *intf_count = soc_MMU_REPL_MEMBER_ICCm_field32_get(unit, &entry,
    225                     icc_fields[icc_field_index]);
    226 
    227     return BCM_E_NONE;
    228 }
    229 
    230 /* Function:
    231  *	bcm_th3_repl_list_start_ptr_set
    232  * Purpose:
    233  *      Set replication list start pointer for given (repl_group, port).
    234  * Parameters:
    235  *	unit       - StrataSwitch PCI device unit number.
    236  *	repl_group - The replication group number.
    237  *	port       - Port.
    238  *	start_ptr  - Replication list's start pointer.
    239  *	intf_count - Replication list's interface count.
    240  * Returns:
    241  *	BCM_E_XXX
    242  */
    243 int
    244 bcm_th3_repl_list_start_ptr_set(int unit, int repl_group, bcm_port_t port,
    245                 int start_ptr, int intf_count)
    246 {
    247     int add_member;
    248     soc_mem_t repl_group_table;
    249     soc_mem_t repl_head_table;
    250     soc_field_t member_bitmap_f, head_index_f;
    251     int member_bitmap_index;
    252     int pipe;
    253     mmu_repl_group_info_tbl_entry_t repl_group_entry;
    254     uint32 fldbuf[SOC_PBMP_WORD_MAX];
    255     int i;
    256     soc_pbmp_t old_member_bitmap;
    257     soc_pbmp_t new_member_bitmap;
    258     int old_member_count, new_member_count;
    259     int old_head_index, new_head_index;
    260     int member_id, member, old_member_id, new_member_id;
    261     uint32 repl_head_entry[SOC_MAX_MEM_FIELD_WORDS];
    262     uint32 old_repl_head_entry[SOC_MAX_MEM_FIELD_WORDS];
    263     int member_bitmap_len;
    264     soc_info_t *si = &SOC_INFO(unit);
    265     uint32 itm_map = si->itm_map;
    266     int itm, rv;
    267 
    268     if (start_ptr > 0) {
    269         add_member = TRUE;
    270     } else {
    271         add_member = FALSE;
    272     }
    273 
    274     member_bitmap_f = MEMBER_BMPf;
    275     head_index_f = BASE_PTRf;
    276 
    277 #ifdef INCLUDE_L3
    278     if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
    279         BCM_IF_ERROR_RETURN(bcm_th_port_to_aggid(unit, port, &member_bitmap_index));
    280     } else
    281 #endif
    282     {
    283         /* Get member bitmap index */
    284         member_bitmap_index = port;
    285     }
    286 
    287     member_bitmap_len = soc_mem_field_length(unit, MMU_REPL_GROUP_INFO_TBLm,
    288                                              member_bitmap_f);
    289     if (member_bitmap_index >= member_bitmap_len) {
    290         return BCM_E_PARAM;
    291     }
    292 
    293     /* Get old member bitmap and old head index */
    294     pipe = 0;
    295 
    296     repl_head_table = MMU_REPL_HEAD_TBLm;
    297 
    298     repl_group_table = MMU_REPL_GROUP_INFO_TBLm;
    299 
    300     SOC_IF_ERROR_RETURN
    301         (soc_mem_read(unit, repl_group_table, MEM_BLOCK_ANY,
    302                       repl_group, &repl_group_entry));
    303     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
    304     soc_mem_field_get(unit, repl_group_table, (uint32 *)&repl_group_entry,
    305             member_bitmap_f, fldbuf);
    306     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
    307         SOC_PBMP_WORD_SET(old_member_bitmap, i, fldbuf[i]);
    308     }
    309     SOC_PBMP_ASSIGN(new_member_bitmap, old_member_bitmap);
    310     SOC_PBMP_COUNT(old_member_bitmap, old_member_count);
    311     old_head_index = soc_mem_field32_get(unit, repl_group_table,
    312             &repl_group_entry, head_index_f);
    313 
    314     if (add_member) {
    315         /* Update REPL_HEAD table */
    316         sal_memset(repl_head_entry, 0, sizeof(repl_head_entry));
    317         soc_mem_field32_set(unit, repl_head_table, repl_head_entry,
    318                             HEAD_PTRf, start_ptr);
    319         if (SOC_PBMP_MEMBER(old_member_bitmap, member_bitmap_index)) {
    320             /* Port is already a member of the group */
    321             member_id = 0;
    322             SOC_PBMP_ITER(old_member_bitmap, member) {
    323                 if (member == member_bitmap_index) {
    324                     break;
    325                 }
    326                 member_id++;
    327             }
    328             SOC_IF_ERROR_RETURN
    329                 (_bcm_th3_repl_head_tbl_write(unit,
    330                  (old_head_index + member_id), repl_head_entry));
    331             BCM_IF_ERROR_RETURN
    332                 (_bcm_th3_initial_copy_count_set(unit,
    333                           (old_head_index + member_id), intf_count));
    334             new_head_index = old_head_index;
    335         } else {
    336             SOC_PBMP_PORT_ADD(new_member_bitmap, member_bitmap_index);
    337             new_member_count = old_member_count + 1;
    338             BCM_IF_ERROR_RETURN(bcm_th3_repl_head_alloc(unit,
    339                         0, new_member_count, &new_head_index));
    340             old_member_id = 0;
    341             new_member_id = 0;
    342             SOC_PBMP_ITER(new_member_bitmap, member) {
    343                 int old_icc = 0;
    344                 if (member == member_bitmap_index) {
    345                     SOC_IF_ERROR_RETURN
    346                         (_bcm_th3_repl_head_tbl_write(unit,
    347                                        (new_head_index + new_member_id),
    348                                        repl_head_entry));
    349                     BCM_IF_ERROR_RETURN
    350                         (_bcm_th3_initial_copy_count_set(unit,
    351                             (new_head_index + new_member_id), intf_count));
    352                 } else {
    353                     SOC_IF_ERROR_RETURN
    354                         (_bcm_th3_repl_head_tbl_read(unit,
    355                                       (old_head_index + old_member_id),
    356                                       old_repl_head_entry, NULL));
    357                     SOC_IF_ERROR_RETURN(_bcm_th3_initial_copy_count_get(unit,
    358                                    (old_head_index + old_member_id), &old_icc));
    359                     SOC_IF_ERROR_RETURN
    360                         (_bcm_th3_repl_head_tbl_write(unit,
    361                                        (new_head_index + new_member_id),
    362                                        old_repl_head_entry));
    363                     BCM_IF_ERROR_RETURN
    364                         (_bcm_th3_initial_copy_count_set(unit,
    365                               (new_head_index + new_member_id), old_icc));
    366                     old_member_id++;
    367                 }
    368                 new_member_id++;
    369             }
    370         }
    371 
    372         /* Update REPL_GROUP entry */
    373         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
    374             fldbuf[i] = SOC_PBMP_WORD_GET(new_member_bitmap, i);
    375         }
    376         soc_mem_field_set(unit, repl_group_table, (uint32 *)&repl_group_entry,
    377                 member_bitmap_f, fldbuf);
    378         soc_mem_field32_set(unit, repl_group_table, &repl_group_entry,
    379                 head_index_f, new_head_index);
    380 
    381         SOC_IF_ERROR_RETURN
    382             (soc_mem_write(unit, repl_group_table, MEM_BLOCK_ALL,
    383                            repl_group, &repl_group_entry));
    384         if (!SAL_BOOT_SIMULATION) {
    385             /* mmu rqe Flush*/
    386             for (itm = 0; itm < NUM_ITM(unit); itm++) {
    387                 if (itm_map & (1 << itm)) {
    388                     /* Issue RQE flush twice per each ITM*/
    389                    rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 1);
    390                    if (rv != BCM_E_NONE) {
    391                        return BCM_E_INTERNAL;
    392                    }
    393                    rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 2);
    394                    if (rv != BCM_E_NONE) {
    395                        return BCM_E_INTERNAL;
    396                    }
    397                 }
    398             }
    399         }
    400 
    401         /* Release old block of REPL_HEAD entries */
    402         if (old_member_count > 0 && old_head_index != new_head_index) {
    403             BCM_IF_ERROR_RETURN(bcm_th3_repl_head_free(unit,
    404                         pipe, old_head_index, old_member_count));
    405         }
    406 
    407 
    408     } else { /* Remove member from replication group */
    409 
    410         if (!SOC_PBMP_MEMBER(old_member_bitmap, member_bitmap_index)) {
    411             /* Port is not a member. Nothing more to do. */
    412             return BCM_E_NONE;
    413         }
    414 
    415         /* Update REPL_HEAD table */
    416         new_member_count = old_member_count - 1;
    417         if (new_member_count > 0) {
    418             BCM_IF_ERROR_RETURN(bcm_th3_repl_head_alloc(unit,
    419                         0, new_member_count, &new_head_index));
    420             old_member_id = 0;
    421             new_member_id = 0;
    422             SOC_PBMP_ITER(old_member_bitmap, member) {
    423                 if (member != member_bitmap_index) {
    424                     int old_icc = 0;
    425                     SOC_IF_ERROR_RETURN
    426                         (_bcm_th3_repl_head_tbl_read(unit,
    427                                       (old_head_index + old_member_id),
    428                                       old_repl_head_entry, NULL));
    429                     SOC_IF_ERROR_RETURN(_bcm_th3_initial_copy_count_get(unit,
    430                                    (old_head_index + old_member_id), &old_icc));
    431                     SOC_IF_ERROR_RETURN
    432                         (_bcm_th3_repl_head_tbl_write(unit,
    433                                        (new_head_index + new_member_id),
    434                                        old_repl_head_entry));
    435                     BCM_IF_ERROR_RETURN
    436                         (_bcm_th3_initial_copy_count_set(unit,
    437                             (new_head_index + new_member_id), old_icc));
    438                     new_member_id++;
    439                 }
    440                 old_member_id++;
    441             }
    442         } else {
    443             new_head_index = 0;
    444         }
    445 
    446         /* Update REPL_GROUP entry */
    447         SOC_PBMP_PORT_REMOVE(new_member_bitmap, member_bitmap_index);
    448         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
    449             fldbuf[i] = SOC_PBMP_WORD_GET(new_member_bitmap, i);
    450         }
    451         soc_mem_field_set(unit, repl_group_table, (uint32 *)&repl_group_entry,
    452                 member_bitmap_f, fldbuf);
    453         soc_mem_field32_set(unit, repl_group_table, &repl_group_entry,
    454                 head_index_f, new_head_index);
    455 
    456         SOC_IF_ERROR_RETURN
    457             (soc_mem_write(unit, repl_group_table, MEM_BLOCK_ALL,
    458                            repl_group, &repl_group_entry));
    459 
    460         if (!SAL_BOOT_SIMULATION) {
    461             /* mmu rqe Flush*/
    462             for (itm = 0; itm < NUM_ITM(unit); itm++) {
    463                 if (itm_map & (1 << itm)) {
    464                     /* Issue RQE flush twice per each ITM*/
    465                    rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 1);
    466                    if (rv != BCM_E_NONE) {
    467                        return BCM_E_INTERNAL;
    468                    }
    469                    rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 2);
    470                    if (rv != BCM_E_NONE) {
    471                        return BCM_E_INTERNAL;
    472                    }
    473                 }
    474             }
    475         }
    476         /* Release old block of REPL_HEAD entries */
    477         BCM_IF_ERROR_RETURN(bcm_th3_repl_head_free(unit,
    478                     pipe, old_head_index, old_member_count));
    479     }
    480 
    481     return BCM_E_NONE;
    482 }
    483 
    484 #endif