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

extender.c (28924B)


      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  * Purpose: Implements ESW Port Extension APIs
      8  */
      9 
     10 #if defined(INCLUDE_L3)
     11 
     12 #include <soc/drv.h>
     13 #include <soc/scache.h>
     14 #include <soc/mem.h>
     15 #include <soc/util.h>
     16 #include <soc/debug.h>
     17 
     18 #include <bcm/types.h>
     19 #include <bcm/error.h>
     20 #include <bcm/extender.h>
     21 
     22 #include <bcm_int/esw/mbcm.h>
     23 #include <bcm_int/esw/switch.h>
     24 #include <bcm_int/esw_dispatch.h>
     25 #include <bcm_int/esw/triumph3.h>
     26 #include <bcm_int/esw/trident2.h>
     27 #include <bcm_int/esw/greyhound.h>
     28 
     29 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
     30     defined(INCLUDE_L3)
     31 /* Flag to check initialized status */
     32 STATIC int extender_initialized[BCM_MAX_NUM_UNITS];
     33 
     34 #define EXTENDER_INIT(unit)                               \
     35     do {                                                  \
     36         if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {  \
     37             return BCM_E_UNIT;                            \
     38         }                                                 \
     39         if (!extender_initialized[unit]) {                \
     40             return BCM_E_INIT;                            \
     41         }                                                 \
     42     } while (0)
     43 
     44 /* 
     45  * Extender module lock
     46  */
     47 STATIC sal_mutex_t extender_mutex[BCM_MAX_NUM_UNITS] = {NULL};
     48 
     49 #define EXTENDER_LOCK(unit) \
     50         sal_mutex_take(extender_mutex[unit], sal_mutex_FOREVER);
     51 
     52 #define EXTENDER_UNLOCK(unit) \
     53         sal_mutex_give(extender_mutex[unit]); 
     54 
     55 /*
     56  * Function:
     57  *      _bcm_esw_extender_free_resources
     58  * Purpose:
     59  *      Free all allocated tables and memory
     60  * Parameters:
     61  *      unit - SOC unit number
     62  * Returns:
     63  *      Nothing
     64  */
     65 STATIC void
     66 _bcm_esw_extender_free_resources(int unit)
     67 {
     68     if (extender_mutex[unit]) {
     69         sal_mutex_destroy(extender_mutex[unit]);
     70         extender_mutex[unit] = NULL;
     71     } 
     72 }
     73 #endif /* (BCM_TRIUMPH3_SUPPORT||BCM_GREYHOUND_SUPPORT) && INCLUDE_L3 */
     74 
     75 #ifdef BCM_WARM_BOOT_SUPPORT
     76 
     77 #define BCM_WB_VERSION_1_0     SOC_SCACHE_VERSION(1,0)
     78 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0
     79 
     80 /*
     81  * Function:
     82  *      _bcm_esw_extender_sync
     83  * Purpose:
     84  *      Record Extender module persistent info for Level 2 Warm Boot
     85  * Parameters:
     86  *      unit - StrataSwitch unit number.
     87  * Returns:
     88  *      BCM_E_XXX
     89  */
     90 int
     91 _bcm_esw_extender_sync(int unit)
     92 {
     93 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
     94     defined(INCLUDE_L3)
     95     if (soc_feature(unit, soc_feature_port_extension)) {
     96         if (!SOC_IS_GREYHOUND(unit) && !SOC_IS_HURRICANE3(unit)) {
     97 #if defined(BCM_TRIUMPH3_SUPPORT)
     98             soc_scache_handle_t scache_handle;
     99             uint8               *scache_ptr;
    100 
    101             SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_EXTENDER, 0);
    102             BCM_IF_ERROR_RETURN
    103                 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    104                                          0, &scache_ptr,
    105                                          BCM_WB_DEFAULT_VERSION, NULL));
    106 
    107             BCM_IF_ERROR_RETURN(_bcm_tr3_extender_sync(unit, &scache_ptr));
    108 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */
    109         }
    110     }
    111 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    112 
    113     return BCM_E_NONE;
    114 }
    115 
    116 #endif /* BCM_WARM_BOOT_SUPPORT */
    117 
    118 /*
    119  * Function:
    120  *      bcm_esw_extender_init
    121  * Purpose:
    122  *      Init extender module
    123  * Parameters:
    124  *      unit - SOC unit number
    125  * Returns:
    126  *      BCM_E_XXX
    127  */
    128 int
    129 bcm_esw_extender_init(int unit)
    130 {
    131 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    132      defined(INCLUDE_L3)
    133     if (soc_feature(unit, soc_feature_port_extension)) {
    134 
    135 #ifdef BCM_WARM_BOOT_SUPPORT
    136 #if defined(BCM_TRIUMPH3_SUPPORT)
    137         if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    138               SOC_IS_GREYHOUND2(unit))) {
    139             uint32              required_scache_size;
    140             soc_scache_handle_t scache_handle;
    141             uint8               *scache_ptr;
    142             int                 rv = BCM_E_NONE;
    143 
    144             /* Get the required scache size */
    145             BCM_IF_ERROR_RETURN(bcm_tr3_extender_required_scache_size_get(unit,
    146                         &required_scache_size));
    147 
    148             /* Allocate required scache */
    149             SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_EXTENDER, 0);
    150             if (required_scache_size > 0) {
    151                 rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
    152                         (0 == SOC_WARM_BOOT(unit)), required_scache_size,
    153                         &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    154                 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    155                     return rv;
    156                 }
    157             }
    158         }
    159 #endif /*if defined(BCM_TRIUMPH3_SUPPORT) */
    160 #endif /* BCM_WARM_BOOT_SUPPORT */
    161 
    162         if (extender_initialized[unit]) {
    163             BCM_IF_ERROR_RETURN(bcm_esw_extender_cleanup(unit));
    164         }
    165 
    166         if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    167             SOC_IS_GREYHOUND2(unit))) {
    168 #if defined(BCM_TRIUMPH3_SUPPORT)
    169             BCM_IF_ERROR_RETURN(bcm_tr3_extender_init(unit));
    170 #endif
    171         }
    172 
    173         if (extender_mutex[unit] == NULL) {
    174             extender_mutex[unit] = sal_mutex_create("extender mutex");
    175             if (extender_mutex[unit] == NULL) {
    176                 _bcm_esw_extender_free_resources(unit);
    177                 return BCM_E_MEMORY;
    178             }
    179         }
    180         extender_initialized[unit] = TRUE;
    181 
    182         return BCM_E_NONE;
    183     }
    184 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    185 
    186     return BCM_E_UNAVAIL;
    187 }
    188 
    189 
    190 /* Function:
    191  *      bcm_extender_cleanup
    192  * Purpose:
    193  *      Detach extender module, clear all HW states
    194  * Parameters:
    195  *      unit - SOC unit number
    196  * Returns:
    197  *      BCM_E_XXXX
    198  */
    199 int
    200 bcm_esw_extender_cleanup(int unit)
    201 {
    202 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    203     defined(INCLUDE_L3)
    204     if (soc_feature(unit, soc_feature_port_extension)) {
    205 
    206         if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    207             SOC_IS_GREYHOUND2(unit))) {
    208 #if defined(BCM_TRIUMPH3_SUPPORT)
    209             BCM_IF_ERROR_RETURN(bcm_tr3_extender_cleanup(unit));
    210 #endif
    211         }
    212         _bcm_esw_extender_free_resources(unit);
    213 
    214         extender_initialized[unit] = FALSE;
    215 
    216         return BCM_E_NONE;
    217     }
    218 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    219 
    220     return BCM_E_UNAVAIL;
    221 }
    222 
    223 /* Function:
    224  *      bcm_esw_extender_port_add
    225  * Purpose:
    226  *      Create a Port Extender port.
    227  * Parameters:
    228  *      unit - (IN) SOC unit Number
    229  *      extender_port - (IN/OUT) Extender port information
    230  * Returns:
    231  *      BCM_E_XXX
    232  */
    233 int bcm_esw_extender_port_add(int unit, bcm_extender_port_t *extender_port)
    234 {
    235     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    236         SOC_IS_GREYHOUND2(unit)) {
    237         return BCM_E_UNAVAIL;
    238     }
    239 
    240 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    241     if (soc_feature(unit, soc_feature_port_extension)) {
    242 
    243         int rv;
    244 
    245         EXTENDER_INIT(unit);
    246 
    247         EXTENDER_LOCK(unit);
    248 
    249         rv = bcm_tr3_extender_port_add(unit, extender_port);
    250 
    251         EXTENDER_UNLOCK(unit);
    252 
    253         return rv;
    254     }
    255 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    256 
    257     return BCM_E_UNAVAIL;
    258 }
    259 
    260 /* Function:
    261  *      bcm_esw_extender_port_delete
    262  * Purpose:
    263  *      Delete a Port Extender port
    264  * Parameters:
    265  *      unit - (IN) SOC unit number
    266  *      extender_port_id - (IN) Extender port ID
    267  * Returns:
    268  *      BCM_E_XXX
    269  */
    270 int bcm_esw_extender_port_delete(int unit, bcm_gport_t extender_port_id)
    271 {
    272     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    273         SOC_IS_GREYHOUND2(unit)) {
    274         return BCM_E_UNAVAIL;
    275     }
    276 
    277 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    278     if (soc_feature(unit, soc_feature_port_extension)) {
    279         int rv;
    280 
    281         EXTENDER_INIT(unit);
    282 
    283         EXTENDER_LOCK(unit);
    284 
    285         rv = bcm_tr3_extender_port_delete(unit, extender_port_id);
    286 
    287         EXTENDER_UNLOCK(unit);
    288 
    289         return rv;
    290     }
    291 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    292 
    293     return BCM_E_UNAVAIL;
    294 }
    295 
    296 /* Function:
    297  *      bcm_esw_extender_port_delete_all
    298  * Purpose:
    299  *      Delete all Port Extender ports
    300  * Parameters:
    301  *      unit - (IN) SOC unit number
    302  * Returns:
    303  *      BCM_E_XXX
    304  */
    305 int bcm_esw_extender_port_delete_all(int unit)
    306 {
    307     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    308         SOC_IS_GREYHOUND2(unit)) {
    309         return BCM_E_UNAVAIL;
    310     }
    311 
    312 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    313     if (soc_feature(unit, soc_feature_port_extension)) {
    314         int rv;
    315 
    316         EXTENDER_INIT(unit);
    317 
    318         EXTENDER_LOCK(unit);
    319 
    320         rv = bcm_tr3_extender_port_delete_all(unit);
    321 
    322         EXTENDER_UNLOCK(unit);
    323 
    324         return rv;
    325     }
    326 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    327 
    328     return BCM_E_UNAVAIL;
    329 }
    330 
    331 /* Function:
    332  *      bcm_esw_extender_port_get
    333  * Purpose:
    334  *      Get info about a Port Extender port
    335  * Parameters:
    336  *      unit - (IN) SOC unit number
    337  *      extender_port - (IN/OUT) Extender port information
    338  * Returns:
    339  *      BCM_E_XXX
    340  */
    341 int bcm_esw_extender_port_get(int unit, bcm_extender_port_t *extender_port)
    342 {
    343     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    344         SOC_IS_GREYHOUND2(unit)) {
    345         return BCM_E_UNAVAIL;
    346     }
    347 
    348 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    349     if (soc_feature(unit, soc_feature_port_extension)) {
    350         int rv;
    351 
    352         EXTENDER_INIT(unit);
    353 
    354         EXTENDER_LOCK(unit);
    355 
    356         rv = bcm_tr3_extender_port_get(unit, extender_port);
    357 
    358         EXTENDER_UNLOCK(unit);
    359 
    360         return rv;
    361     }
    362 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    363 
    364     return BCM_E_UNAVAIL;
    365 }
    366 
    367 /* Function:
    368  *      bcm_esw_extender_port_traverse
    369  * Purpose:
    370  *      Traverse all valid Port Extender ports and call the
    371  *      supplied callback routine.
    372  * Parameters:
    373  *      unit      - Device Number
    374  *      cb        - User callback function, called once per Extender Port.
    375  *      user_data - cookie
    376  * Returns:
    377  *      BCM_E_XXX
    378  */
    379 int
    380 bcm_esw_extender_port_traverse(int unit,
    381                           bcm_extender_port_traverse_cb cb,
    382                           void *user_data)
    383 {
    384     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    385         SOC_IS_GREYHOUND2(unit)) {
    386         return BCM_E_UNAVAIL;
    387     }
    388 
    389 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    390     if (soc_feature(unit, soc_feature_port_extension)) {
    391         int rv;
    392 
    393         EXTENDER_INIT(unit);
    394 
    395         EXTENDER_LOCK(unit);
    396 
    397         rv = bcm_tr3_extender_port_traverse(unit, cb, user_data);
    398 
    399         EXTENDER_UNLOCK(unit);
    400 
    401         return rv;
    402     }
    403 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    404 
    405     return BCM_E_UNAVAIL;
    406 }
    407 
    408 /* Function:
    409  *      bcm_esw_extender_forward_add
    410  * Purpose:
    411  *      Add a downstream forwarding entry
    412  * Parameters:
    413  *      unit - (IN) Device Number
    414  *      extender_forward_entry - (IN) Forwarding entry
    415  * Returns:
    416  *      BCM_E_XXX
    417  */
    418 int
    419 bcm_esw_extender_forward_add(int unit,
    420         bcm_extender_forward_t *extender_forward_entry)
    421 {
    422     int rv = BCM_E_UNAVAIL;
    423 
    424 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    425     defined(INCLUDE_L3)
    426     if (soc_feature(unit, soc_feature_port_extension)) {
    427 
    428         EXTENDER_INIT(unit);
    429 
    430         EXTENDER_LOCK(unit);
    431 
    432         if (soc_feature(unit, soc_feature_ism_memory)) {
    433 #if defined(BCM_TRIUMPH3_SUPPORT)
    434             rv = bcm_tr3_extender_forward_add(unit, extender_forward_entry);
    435 #endif /* BCM_TRIUMPH3_SUPPORT */
    436         } else {
    437             if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    438                 SOC_IS_GREYHOUND2(unit)) {
    439 #ifdef BCM_GREYHOUND_SUPPORT
    440                 rv = bcm_gh_extender_forward_add(unit, extender_forward_entry);
    441 #endif /* BCM_GREYHOUND_SUPPORT */
    442             } else {
    443 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
    444                 rv = bcm_td2_extender_forward_add(unit, extender_forward_entry);
    445 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
    446             }
    447         }
    448 
    449         EXTENDER_UNLOCK(unit);
    450 
    451         return rv;
    452     }
    453 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    454 
    455     return rv;
    456 }
    457 
    458 /* Function:
    459  *      bcm_esw_extender_forward_delete
    460  * Purpose:
    461  *	Delete a downstream forwarding entry
    462  * Parameters:
    463  *      unit - (IN) Device Number
    464  *      extender_forward_entry - (IN) Forwarding entry
    465  * Returns:
    466  *      BCM_E_XXX
    467  */
    468 int
    469 bcm_esw_extender_forward_delete(int unit,
    470         bcm_extender_forward_t *extender_forward_entry)
    471 {
    472     int rv = BCM_E_UNAVAIL;
    473 
    474 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    475     defined(INCLUDE_L3)
    476     if (soc_feature(unit, soc_feature_port_extension)) {
    477 
    478         EXTENDER_INIT(unit);
    479 
    480         EXTENDER_LOCK(unit);
    481 
    482         if (soc_feature(unit, soc_feature_ism_memory)) {
    483 #if defined(BCM_TRIUMPH3_SUPPORT) 
    484             rv = bcm_tr3_extender_forward_delete(unit, extender_forward_entry);
    485 #endif /* BCM_TRIUMPH3_SUPPORT */
    486         } else {
    487             if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    488                 SOC_IS_GREYHOUND2(unit)) {
    489 #ifdef BCM_GREYHOUND_SUPPORT
    490                 rv = bcm_gh_extender_forward_delete(unit, extender_forward_entry);
    491 #endif /* BCM_GREYHOUND_SUPPORT */
    492             } else {
    493 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
    494                 rv = bcm_td2_extender_forward_delete(unit, extender_forward_entry);
    495 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
    496             }
    497         }
    498 
    499         EXTENDER_UNLOCK(unit);
    500 
    501         return rv;
    502     }
    503 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    504 
    505     return rv;
    506 }
    507 
    508 /* Function:
    509  *      bcm_esw_extender_forward_delete_all
    510  * Purpose:
    511  *      Delete all downstream forwarding entries
    512  * Parameters:
    513  *      unit - Device Number
    514  * Returns:
    515  *      BCM_E_XXX
    516  */
    517 int
    518 bcm_esw_extender_forward_delete_all(int unit)
    519 {
    520     int rv = BCM_E_UNAVAIL;
    521 
    522 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    523     defined(INCLUDE_L3)
    524     if (soc_feature(unit, soc_feature_port_extension)) {
    525 
    526         EXTENDER_INIT(unit);
    527 
    528         EXTENDER_LOCK(unit);
    529 
    530         if (soc_feature(unit, soc_feature_ism_memory)) {
    531 #if defined(BCM_TRIUMPH3_SUPPORT) 
    532             rv = bcm_tr3_extender_forward_delete_all(unit);
    533 #endif /* BCM_TRIUMPH3_SUPPORT */
    534         } else {
    535             if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    536                 SOC_IS_GREYHOUND2(unit)) {
    537 #ifdef BCM_GREYHOUND_SUPPORT
    538                 rv = bcm_gh_extender_forward_delete_all(unit);
    539 #endif /* BCM_GREYHOUND_SUPPORT */
    540             } else {
    541 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
    542                 rv = bcm_td2_extender_forward_delete_all(unit);
    543 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
    544             }
    545         }
    546 
    547         EXTENDER_UNLOCK(unit);
    548 
    549         return rv;
    550     }
    551 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    552 
    553     return rv;
    554 }
    555 
    556 /* Function:
    557  *      bcm_esw_extender_forward_get
    558  * Purpose:
    559  *      Get downstream forwarding entry
    560  * Parameters:
    561  *      unit - (IN) Device Number
    562  *      extender_forward_entry - (IN/OUT) Forwarding entry 
    563  * Returns:
    564  *      BCM_E_XXX
    565  */
    566 int
    567 bcm_esw_extender_forward_get(int unit,
    568         bcm_extender_forward_t *extender_forward_entry)
    569 {
    570     int rv = BCM_E_UNAVAIL;
    571 
    572 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    573     defined(INCLUDE_L3)
    574     if (soc_feature(unit, soc_feature_port_extension)) {
    575 
    576         EXTENDER_INIT(unit);
    577 
    578         EXTENDER_LOCK(unit);
    579 
    580         if (soc_feature(unit, soc_feature_ism_memory)) {
    581 #if defined(BCM_TRIUMPH3_SUPPORT) 
    582             rv = bcm_tr3_extender_forward_get(unit, extender_forward_entry);
    583 #endif /* BCM_TRIUMPH3_SUPPORT */
    584         } else {
    585             if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    586                 SOC_IS_GREYHOUND2(unit)) {
    587 #ifdef BCM_GREYHOUND_SUPPORT
    588                 rv = bcm_gh_extender_forward_get(unit, extender_forward_entry);
    589 #endif /* BCM_GREYHOUND_SUPPORT */
    590             } else {
    591 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
    592                 rv = bcm_td2_extender_forward_get(unit, extender_forward_entry);
    593 #endif /* BCM_TRIDENT2_SUPPORT BCM_PE_SUPPORT */
    594             }
    595         }
    596 
    597         EXTENDER_UNLOCK(unit);
    598 
    599         return rv;
    600     }
    601 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    602 
    603     return rv;
    604 }
    605 
    606 /* Function:
    607  *      bcm_esw_extender_forward_traverse
    608  * Purpose:
    609  *      Traverse all valid downstream forwarding entries and call the
    610  *      supplied callback routine.
    611  * Parameters:
    612  *      unit      - Device Number
    613  *      cb        - User callback function, called once per forwarding entry.
    614  *      user_data - cookie
    615  * Returns:
    616  *      BCM_E_XXX
    617  */
    618 int
    619 bcm_esw_extender_forward_traverse(int unit,
    620                              bcm_extender_forward_traverse_cb cb,
    621                              void *user_data)
    622 {
    623     int rv = BCM_E_UNAVAIL;
    624 
    625 #if (defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    626     defined(INCLUDE_L3)
    627     if (soc_feature(unit, soc_feature_port_extension)) {
    628 
    629         EXTENDER_INIT(unit);
    630 
    631         EXTENDER_LOCK(unit);
    632 
    633         if (soc_feature(unit, soc_feature_ism_memory)) {
    634 #if defined(BCM_TRIUMPH3_SUPPORT) 
    635             rv = bcm_tr3_extender_forward_traverse(unit, cb, user_data);
    636 #endif /* BCM_TRIUMPH3_SUPPORT */
    637         } else {
    638             if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    639                 SOC_IS_GREYHOUND2(unit)) {
    640 #ifdef BCM_GREYHOUND_SUPPORT
    641                 rv = bcm_gh_extender_forward_traverse(unit, cb, user_data);
    642 #endif /* BCM_GREYHOUND_SUPPORT */
    643             } else {
    644 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
    645                 rv = bcm_td2_extender_forward_traverse(unit, cb, user_data);
    646 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
    647             }
    648         }
    649 
    650         EXTENDER_UNLOCK(unit);
    651 
    652         return rv;
    653     }
    654 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    655 
    656     return rv;
    657 }
    658 
    659 /*
    660  * Function:
    661  *      _bcm_esw_extender_port_source_vp_lag_set
    662  * Purpose:
    663  *      Set source VP LAG for an Extender virtual port.
    664  * Parameters:
    665  *      unit - (IN) SOC unit number. 
    666  *      gport - (IN) Extender virtual port GPORT ID. 
    667  *      vp_lag_vp - (IN) VP representing the VP LAG. 
    668  * Returns:
    669  *      BCM_X_XXX
    670  */
    671 int
    672 _bcm_esw_extender_port_source_vp_lag_set(int unit, bcm_gport_t gport,
    673         int vp_lag_vp)
    674 {
    675 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
    676     if (soc_feature(unit, soc_feature_port_extension) &&
    677         soc_feature(unit, soc_feature_vp_lag)) {
    678         int rv;
    679 
    680         EXTENDER_INIT(unit);
    681 
    682         EXTENDER_LOCK(unit);
    683 
    684         rv = bcm_td2_extender_port_source_vp_lag_set(unit, gport, vp_lag_vp);
    685 
    686         EXTENDER_UNLOCK(unit);
    687 
    688         return rv;
    689     }
    690 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
    691 
    692     return BCM_E_UNAVAIL;
    693 }
    694 
    695 /*
    696  * Function:
    697  *      _bcm_esw_extender_port_source_vp_lag_clear
    698  * Purpose:
    699  *      Clear source VP LAG for an Extender virtual port.
    700  * Parameters:
    701  *      unit - (IN) SOC unit number. 
    702  *      gport - (IN) Extender virtual port GPORT ID. 
    703  *      vp_lag_vp - (IN) VP representing the VP LAG. 
    704  * Returns:
    705  *      BCM_X_XXX
    706  */
    707 int
    708 _bcm_esw_extender_port_source_vp_lag_clear(int unit, bcm_gport_t gport,
    709         int vp_lag_vp)
    710 {
    711 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
    712     if (soc_feature(unit, soc_feature_port_extension) &&
    713         soc_feature(unit, soc_feature_vp_lag)) {
    714         int rv;
    715 
    716         EXTENDER_INIT(unit);
    717 
    718         EXTENDER_LOCK(unit);
    719 
    720         rv = bcm_td2_extender_port_source_vp_lag_clear(unit, gport, vp_lag_vp);
    721 
    722         EXTENDER_UNLOCK(unit);
    723 
    724         return rv;
    725     }
    726 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
    727 
    728     return BCM_E_UNAVAIL;
    729 }
    730 
    731 /*
    732  * Function:
    733  *      _bcm_esw_extender_port_source_vp_lag_get
    734  * Purpose:
    735  *      Get source VP LAG for an Extender virtual port.
    736  * Parameters:
    737  *      unit - (IN) SOC unit number. 
    738  *      gport - (IN) Extender virtual port GPORT ID. 
    739  *      vp_lag_vp - (OUT) VP representing the VP LAG. 
    740  * Returns:
    741  *      BCM_X_XXX
    742  */
    743 int
    744 _bcm_esw_extender_port_source_vp_lag_get(int unit, bcm_gport_t gport,
    745         int *vp_lag_vp)
    746 {
    747 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
    748     if (soc_feature(unit, soc_feature_port_extension) &&
    749         soc_feature(unit, soc_feature_vp_lag)) {
    750         int rv;
    751 
    752         EXTENDER_INIT(unit);
    753 
    754         EXTENDER_LOCK(unit);
    755 
    756         rv = bcm_td2_extender_port_source_vp_lag_get(unit, gport, vp_lag_vp);
    757 
    758         EXTENDER_UNLOCK(unit);
    759 
    760         return rv;
    761     }
    762 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
    763 
    764     return BCM_E_UNAVAIL;
    765 }
    766 
    767 /*
    768  * Function:
    769  *      _bcm_esw_extender_port_match_add
    770  * Purpose:
    771  *      Add a match to an existing vp.
    772  * Parameters:
    773  *      unit -             (IN) SOC unit number. 
    774  *      port -             (IN) port of match criteria.
    775  *      extended_port_vid -(IN) extended_port_vid of match criteria.
    776  *      vlan -             (IN) vlan of match criteria.
    777  *      vp -               (IN) the vp of match destination.
    778  * Returns:
    779  *      BCM_X_XXX
    780  */
    781 int
    782 _bcm_esw_extender_port_match_add(int unit, bcm_gport_t port,
    783                                  uint16 extended_port_vid,
    784                                  bcm_vlan_t vlan, int vp)
    785 {
    786 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    787     if (soc_feature(unit, soc_feature_port_extension)) {
    788 
    789         int rv;
    790 
    791         EXTENDER_INIT(unit);
    792 
    793         EXTENDER_LOCK(unit);
    794 
    795         rv = _bcm_tr3_extender_port_match_add(unit, port, extended_port_vid,
    796                                               vlan, vp);
    797 
    798         EXTENDER_UNLOCK(unit);
    799 
    800         return rv;
    801     }
    802 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    803     
    804     return BCM_E_UNAVAIL;
    805 }
    806 
    807 
    808 /*
    809  * Function:
    810  *      _bcm_esw_extender_port_match_delete
    811  * Purpose:
    812  *      delete a match from an existing vp.
    813  * Parameters:
    814  *      unit -             (IN) SOC unit number. 
    815  *      port -             (IN) port of match criteria.
    816  *      extended_port_vid -(IN) extended_port_vid of match criteria.
    817  *      vlan -             (IN) vlan of match criteria.
    818  *      vp -               (IN) the vp of match destination.
    819  * Returns:
    820  *      BCM_X_XXX
    821  */
    822 int
    823 _bcm_esw_extender_port_match_delete(int unit, bcm_gport_t port,
    824                                     uint16 extended_port_vid,
    825                                     bcm_vlan_t vlan, int vp)
    826 {
    827 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    828     if (soc_feature(unit, soc_feature_port_extension)) {
    829 
    830         int rv;
    831 
    832         EXTENDER_INIT(unit);
    833 
    834         EXTENDER_LOCK(unit);
    835 
    836         rv = _bcm_tr3_extender_port_match_delete(unit, port, extended_port_vid,
    837                                                  vlan, vp);
    838 
    839         EXTENDER_UNLOCK(unit);
    840 
    841         return rv;
    842     }
    843 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
    844     
    845     return BCM_E_UNAVAIL;
    846 }
    847 
    848 /* Function:
    849  *      bcm_esw_extender_egress_add
    850  * Purpose:
    851  *      Add a Extender egress object to a Extender port
    852  * Parameters:
    853  *      unit - (IN) SOC unit Number
    854  *      extender_port - (IN) Extender port
    855  *      extender_egress - (IN/OUT) Extender egress object, the egress_if field is output.
    856  * Returns:
    857  *      BCM_E_XXX
    858  */
    859 int
    860 bcm_esw_extender_egress_add(int unit, bcm_gport_t extender_port,
    861     bcm_extender_egress_t *extender_egress)
    862 {
    863 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    864     if ((soc_feature(unit, soc_feature_port_extension))
    865         && (soc_feature(unit, soc_feature_port_extender_vp_sharing))) {
    866         int rv;
    867 
    868         EXTENDER_INIT(unit);
    869 
    870         EXTENDER_LOCK(unit);
    871 
    872         rv = bcm_tr3_extender_egress_add(unit, extender_port,
    873                 extender_egress);
    874 
    875         EXTENDER_UNLOCK(unit);
    876 
    877         return rv;
    878     }
    879 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    880 
    881     return BCM_E_UNAVAIL;
    882 }
    883 
    884 /* Function:
    885  *      bcm_esw_extender_egress_delete
    886  * Purpose:
    887  *      Delete a Extender egress object to a Extender port
    888  * Parameters:
    889  *      unit - (IN) SOC unit Number
    890  *      extender_port - (IN) Extender port
    891  *      extender_egress - (IN) Extender egress object.
    892  * Returns:
    893  *      BCM_E_XXX
    894  */
    895 int
    896 bcm_esw_extender_egress_delete(int unit, bcm_gport_t extender_port,
    897     bcm_extender_egress_t *extender_egress)
    898 {
    899 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    900     if ((soc_feature(unit, soc_feature_port_extension))
    901         && (soc_feature(unit, soc_feature_port_extender_vp_sharing))) {
    902         int rv;
    903 
    904         EXTENDER_INIT(unit);
    905 
    906         EXTENDER_LOCK(unit);
    907 
    908         rv = bcm_tr3_extender_egress_delete(unit, extender_port,
    909                 extender_egress);
    910 
    911         EXTENDER_UNLOCK(unit);
    912 
    913         return rv;
    914     }
    915 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    916 
    917     return BCM_E_UNAVAIL;
    918 }
    919 
    920 /* Function:
    921  *      bcm_esw_extender_egress_set
    922  * Purpose:
    923  *      Delete existing egress object for a Extender port and add
    924  *      an array of extender egress objects to the Extender port
    925  * Parameters:
    926  *      unit - (IN) SOC unit Number
    927  *      extender_port - (IN) Extender port
    928  *      extender_egress_array - (IN) Array of Extender egress objects
    929  * Returns:
    930  *      BCM_E_XXX
    931  */
    932 int
    933 bcm_esw_extender_egress_set(int unit, bcm_gport_t extender_port,
    934         int array_size, bcm_extender_egress_t *extender_egress_array)
    935 {
    936 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    937     if ((soc_feature(unit, soc_feature_port_extension))
    938         && (soc_feature(unit, soc_feature_port_extender_vp_sharing))) {
    939         int rv;
    940 
    941         EXTENDER_INIT(unit);
    942 
    943         EXTENDER_LOCK(unit);
    944 
    945         rv = bcm_tr3_extender_egress_set(unit, extender_port,
    946                 array_size, extender_egress_array);
    947 
    948         EXTENDER_UNLOCK(unit);
    949 
    950         return rv;
    951     }
    952 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    953 
    954     return BCM_E_UNAVAIL;
    955 }
    956 
    957 /* Function:
    958  *      bcm_esw_extender_egress_get
    959  * Purpose:
    960  *      get an Extender egress object for Extender port
    961  * Parameters:
    962  *      unit - (IN) SOC unit Number
    963  *      extender_port - (IN) Extender port
    964  *      extender_egress - (IN/OUT) Extender egress object
    965  * Returns:
    966  *      BCM_E_XXX
    967  */
    968 int
    969 bcm_esw_extender_egress_get(int unit, bcm_gport_t extender_port,
    970         bcm_extender_egress_t *extender_egress)
    971 {
    972 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    973     if ((soc_feature(unit, soc_feature_port_extension))
    974         && (soc_feature(unit, soc_feature_port_extender_vp_sharing))) {
    975         int rv;
    976 
    977         EXTENDER_INIT(unit);
    978 
    979         EXTENDER_LOCK(unit);
    980 
    981         rv = bcm_tr3_extender_egress_get(unit, extender_port,
    982                extender_egress);
    983 
    984         EXTENDER_UNLOCK(unit);
    985 
    986         return rv;
    987     }
    988 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    989 
    990     return BCM_E_UNAVAIL;
    991 }
    992 
    993 /* Function:
    994  *      bcm_esw_extender_egress_get_all
    995  * Purpose:
    996  *      Get array of Extender egress objects for Extender port
    997  * Parameters:
    998  *      unit - (IN) SOC unit Number
    999  *      extender_port - (IN) Extender port
   1000  *      array_size - (IN) Size of Extender egress objects array.
   1001  *      extender_egress_array - (OUT) Array of Extender egress objects.
   1002  *      count - (OUT) Number of Extender egress objects returned.
   1003  * Returns:
   1004  *      BCM_E_XXX
   1005  */
   1006 int
   1007 bcm_esw_extender_egress_get_all(int unit, bcm_gport_t extender_port,
   1008         int array_size, bcm_extender_egress_t *extender_egress_array, int *count)
   1009 {
   1010 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
   1011     if ((soc_feature(unit, soc_feature_port_extension))
   1012         && (soc_feature(unit, soc_feature_port_extender_vp_sharing))) {
   1013         int rv;
   1014 
   1015         EXTENDER_INIT(unit);
   1016 
   1017         EXTENDER_LOCK(unit);
   1018 
   1019         rv = bcm_tr3_extender_egress_get_all(unit, extender_port,
   1020                 array_size, extender_egress_array, count);
   1021 
   1022         EXTENDER_UNLOCK(unit);
   1023 
   1024         return rv;
   1025     }
   1026 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
   1027 
   1028     return BCM_E_UNAVAIL;
   1029 }
   1030 
   1031 /* Function:
   1032  *      bcm_esw_extender_egress_delete_all
   1033  * Purpose:
   1034  *      Delete all Extender egress objects for an Extender Port
   1035  * Parameters:
   1036  *      unit - (IN) SOC unit Number
   1037  *      extender_port - (IN) Extender port
   1038  * Returns:
   1039  *      BCM_E_XXX
   1040  */
   1041 int
   1042 bcm_esw_extender_egress_delete_all(int unit, bcm_gport_t extender_port)
   1043 {
   1044     return bcm_esw_extender_egress_set(unit, extender_port, 0, NULL);
   1045 }
   1046 
   1047 #ifndef BCM_SW_STATE_DUMP_DISABLE
   1048 /*
   1049  * Function:
   1050  *     _bcm_extender_sw_dump
   1051  * Purpose:
   1052  *     Displays extender module information maintained by software.
   1053  * Parameters:
   1054  *     unit - Device unit number
   1055  * Returns:
   1056  *     None
   1057  */
   1058 void
   1059 _bcm_extender_sw_dump(int unit)
   1060 {
   1061 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
   1062     if (soc_feature(unit, soc_feature_port_extension)) {
   1063         if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   1064             SOC_IS_GREYHOUND2(unit))) {
   1065             bcm_tr3_extender_sw_dump(unit);
   1066         }
   1067     }
   1068 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
   1069 
   1070     return;
   1071 }
   1072 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   1073 
   1074 #else   /* INCLUDE_L3 */
   1075 int bcm_esw_extender_not_empty;
   1076 #endif  /* INCLUDE_L3 */
   1077