l2.c (442581B)
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: l2.c 8 * Purpose: Triumph3 L2 function implementations 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 #if defined(BCM_TRIUMPH3_SUPPORT) 15 16 #include <assert.h> 17 18 #include <sal/core/libc.h> 19 20 #include <soc/mem.h> 21 #include <soc/cm.h> 22 #include <soc/drv.h> 23 #include <soc/register.h> 24 #include <soc/memory.h> 25 #include <soc/hash.h> 26 #include <soc/l2x.h> 27 #include <soc/l2u.h> 28 #include <soc/triumph3.h> 29 #include <soc/ism_hash.h> 30 #ifdef BCM_KATANA2_SUPPORT 31 #include <soc/katana2.h> 32 #endif 33 #include <bcm/l2.h> 34 #include <bcm/error.h> 35 #include <bcm/failover.h> 36 37 #include <bcm_int/esw/l2gre.h> 38 #include <bcm_int/esw/l2.h> 39 #include <bcm_int/esw/mpls.h> 40 #include <bcm_int/esw/mim.h> 41 #include <bcm_int/common/multicast.h> 42 #include <bcm_int/esw/stack.h> 43 #include <bcm_int/esw/trill.h> 44 #include <bcm_int/esw/virtual.h> 45 #include <bcm_int/esw/vlan.h> 46 #include <bcm_int/esw/triumph3.h> 47 #include <bcm_int/esw_dispatch.h> 48 #include <bcm_int/esw/triumph.h> 49 50 /**************************************************************** 51 * 52 * L2 software tables, per unit. 53 */ 54 static int _bcm_tr3_l2_init[BCM_MAX_NUM_UNITS]; 55 static soc_profile_mem_t *_bcm_l2_tr3_port_cbl_profile[BCM_MAX_NUM_UNITS]; 56 57 /* 58 * Define: 59 * BCM_TR3_L2_INIT 60 * Purpose: 61 * Causes a routine to return BCM_E_INIT if L2 software module 62 * is not yet initialized. 63 */ 64 65 #define BCM_TR3_L2_INIT(unit) \ 66 if (0 == _bcm_tr3_l2_init[unit]) return BCM_E_INIT 67 68 /*********************************************************************** 69 * 70 * L2X Message Registration 71 */ 72 73 #define _BCM_TR3_L2_CB_MAX 3 74 75 typedef struct _bcm_tr3_l2x_cb_entry_s { 76 bcm_l2_addr_callback_t fn; 77 void *fn_data; 78 } _bcm_tr3_l2_cb_entry_t; 79 80 #define _BCM_TR3_L2X_THREAD_STOP (1 << 0) 81 typedef struct _bcm_tr3_l2_data_s { 82 _bcm_tr3_l2_cb_entry_t cb[_BCM_TR3_L2_CB_MAX]; 83 int cb_count; 84 int flags; 85 sal_mutex_t l2_mutex; 86 } _bcm_tr3_l2_data_t; 87 88 static _bcm_tr3_l2_data_t *_bcm_tr3_l2_data[SOC_MAX_NUM_DEVICES]; 89 90 91 #define BCM_TR3_L2_CB_LOCK(unit) \ 92 sal_mutex_take(_bcm_tr3_l2_data[unit]->l2_mutex, sal_mutex_FOREVER) 93 94 #define BCM_TR3_L2_CB_UNLOCK(unit) \ 95 sal_mutex_give(_bcm_tr3_l2_data[unit]->l2_mutex) 96 97 #define BCM_TR3_L2_CB_MUTEX(unit) \ 98 if (_bcm_tr3_l2_data[unit] == NULL || \ 99 (_bcm_tr3_l2_data[unit]->l2_mutex == NULL && \ 100 (_bcm_tr3_l2_data[unit]->l2_mutex = \ 101 sal_mutex_create("bcm_tr3_l2_lock")) == NULL)) \ 102 return BCM_E_MEMORY 103 104 /**************************************************************** 105 * 106 * L2 MAC block software accounting, per unit. 107 */ 108 109 typedef struct _bcm_tr3_mac_block_info_s { 110 bcm_pbmp_t mb_pbmp; 111 int ref_count; 112 } _bcm_tr3_mac_block_info_t; 113 114 static _bcm_tr3_mac_block_info_t *_tr3_mbi_entries[BCM_MAX_NUM_UNITS]; 115 static int _tr3_mbi_num[BCM_MAX_NUM_UNITS]; 116 117 /**************************************************************** 118 * 119 * L2 learn limit software representation, per unit. 120 */ 121 122 #define BCM_MAC_LIMIT_MAX(_u_) (soc_feature(_u_, soc_feature_esm_support)) ? \ 123 ((soc_mem_index_count(_u_, L2_ENTRY_1m)) + \ 124 (soc_mem_index_count(_u_, EXT_L2_ENTRY_1m)) + \ 125 (soc_mem_index_count(_u_, EXT_L2_ENTRY_2m))): \ 126 (soc_mem_index_count(_u_, L2_ENTRY_1m)) 127 128 /**************************************************************** 129 * 130 * L2 entry types in one structure. 131 */ 132 133 #define _BCM_TR3_L2_SELECT_REDUCED \ 134 (_BCM_TR3_L2_SELECT_L2_ENTRY_1 | _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) 135 #define _BCM_TR3_L2_SELECT_EXTENDED \ 136 (_BCM_TR3_L2_SELECT_L2_ENTRY_2 | _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) 137 #define _BCM_TR3_L2_SELECT_INTERNAL \ 138 (_BCM_TR3_L2_SELECT_L2_ENTRY_1 | _BCM_TR3_L2_SELECT_L2_ENTRY_2) 139 #define _BCM_TR3_L2_SELECT_EXTERNAL \ 140 (_BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1 | _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) 141 #define _BCM_TR3_L2_SELECT_ALL_TABLES \ 142 (_BCM_TR3_L2_SELECT_REDUCED | _BCM_TR3_L2_SELECT_EXTENDED) 143 144 static uint8 _bcm_tr3_l2_mems_valid[SOC_MAX_NUM_DEVICES]; 145 146 #define _BCM_TR3_L2_SELECT_ALL(unit) _bcm_tr3_l2_mems_valid[unit] 147 148 #define _BCM_TR3_L2_MEM_BANKS_ALL (-1) 149 150 #define _BCM_TR3_L2_MEM_TYPE_VALID(_entries_, _mem_type_) \ 151 (0 != (_entries_->entry_flags & _BCM_TR3_L2_SELECT_##_mem_type_)) 152 153 /**************************************************************** 154 * 155 * L2 entry field abstractions 156 */ 157 158 typedef enum _bcm_tr3_l2_mem_type_e { 159 _BCM_TR3_L2_MEM_L2_ENTRY_1, 160 _BCM_TR3_L2_MEM_L2_ENTRY_2, 161 _BCM_TR3_L2_MEM_EXT_L2_ENTRY_1, 162 _BCM_TR3_L2_MEM_EXT_L2_ENTRY_2, 163 _BCM_TR3_L2_MEM_NUM 164 } _bcm_tr3_l2_mem_type_t; 165 166 static soc_mem_t _bcm_tr3_l2_mems[_BCM_TR3_L2_MEM_NUM] = { 167 L2_ENTRY_1m, 168 L2_ENTRY_2m, 169 EXT_L2_ENTRY_1m, 170 EXT_L2_ENTRY_2m 171 }; 172 173 typedef enum _bcm_tr3_l2_memacc_type_e { 174 _BCM_TR3_L2_MEMACC_VALID, 175 _BCM_TR3_L2_MEMACC_VALID_1, 176 _BCM_TR3_L2_MEMACC_FREE, 177 _BCM_TR3_L2_MEMACC_KEY_TYPE, 178 _BCM_TR3_L2_MEMACC_KEY_TYPE_1, 179 _BCM_TR3_L2_MEMACC_VLAN_ID, 180 _BCM_TR3_L2_MEMACC_VFI, 181 _BCM_TR3_L2_MEMACC_MAC_ADDR, 182 _BCM_TR3_L2_MEMACC_PORT_NUM, 183 _BCM_TR3_L2_MEMACC_TGID, 184 _BCM_TR3_L2_MEMACC_L2MC_PTR, 185 _BCM_TR3_L2_MEMACC_MODULE_ID, 186 _BCM_TR3_L2_MEMACC_DESTINATION, 187 _BCM_TR3_L2_MEMACC_DEST_TYPE, 188 _BCM_TR3_L2_MEMACC_PENDING, 189 _BCM_TR3_L2_MEMACC_LIMIT_COUNTED, 190 _BCM_TR3_L2_MEMACC_REMOTE, 191 _BCM_TR3_L2_MEMACC_RPE, 192 _BCM_TR3_L2_MEMACC_PRI, 193 _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX, 194 _BCM_TR3_L2_MEMACC_CLASS_ID, 195 _BCM_TR3_L2_MEMACC_CLASS_ID_FULL, 196 _BCM_TR3_L2_MEMACC_SCP, 197 _BCM_TR3_L2_MEMACC_SRC_DISCARD, 198 _BCM_TR3_L2_MEMACC_DST_DISCARD, 199 _BCM_TR3_L2_MEMACC_DST_CPU, 200 _BCM_TR3_L2_MEMACC_WIDE, 201 _BCM_TR3_L2_MEMACC_WIDE_1, 202 _BCM_TR3_L2_MEMACC_STATIC_BIT, 203 _BCM_TR3_L2_MEMACC_STATIC_BIT_1, 204 _BCM_TR3_L2_MEMACC_HITSA, 205 _BCM_TR3_L2_MEMACC_HITDA, 206 _BCM_TR3_L2_MEMACC_LOCAL_SA, 207 _BCM_TR3_L2_MEMACC_Q_TAG, 208 _BCM_TR3_L2_MEMACC_EH_TAG_TYPE, 209 _BCM_TR3_L2_MEMACC_EH_TM, 210 _BCM_TR3_L2_MEMACC_EH_QUEUE_TAG, 211 _BCM_TR3_L2_MEMACC_NUM 212 } _bcm_tr3_l2_memacc_type_t; 213 214 static soc_field_t _bcm_tr3_l2_entry_1_field_memacc_map[_BCM_TR3_L2_MEMACC_NUM] = { 215 VALIDf, 216 INVALIDf, 217 INVALIDf, 218 KEY_TYPEf, 219 INVALIDf, 220 L2__VLAN_IDf, 221 L2__VFIf, 222 L2__MAC_ADDRf, 223 L2__PORT_NUMf, 224 L2__TGIDf, 225 L2__L2MC_PTRf, 226 L2__MODULE_IDf, 227 L2__DESTINATIONf, 228 L2__DEST_TYPEf, 229 L2__PENDINGf, 230 L2__LIMIT_COUNTEDf, 231 L2__REMOTEf, 232 L2__RPEf, 233 L2__PRIf, 234 L2__MAC_BLOCK_INDEXf, 235 L2__CLASS_IDf, 236 L2__CLASS_ID_FULLf, 237 L2__SCPf, 238 INVALIDf, 239 INVALIDf, 240 INVALIDf, 241 WIDEf, 242 INVALIDf, 243 STATIC_BITf, 244 INVALIDf, 245 HITSAf, 246 HITDAf, 247 LOCAL_SAf, 248 INVALIDf, 249 INVALIDf, 250 INVALIDf, 251 INVALIDf, 252 }; 253 254 static soc_field_t _bcm_tr3_l2_entry_2_field_memacc_map[_BCM_TR3_L2_MEMACC_NUM] = { 255 VALID_0f, 256 VALID_1f, 257 INVALIDf, 258 KEY_TYPE_0f, 259 KEY_TYPE_1f, 260 L2__VLAN_IDf, 261 L2__VFIf, 262 L2__MAC_ADDRf, 263 L2__PORT_NUMf, 264 L2__TGIDf, 265 L2__L2MC_PTRf, 266 L2__MODULE_IDf, 267 L2__DESTINATIONf, 268 L2__DEST_TYPEf, 269 L2__PENDINGf, 270 L2__LIMIT_COUNTEDf, 271 L2__REMOTEf, 272 L2__RPEf, 273 L2__PRIf, 274 L2__MAC_BLOCK_INDEXf, 275 L2__CLASS_IDf, 276 L2__CLASS_ID_FULLf, 277 L2__SCPf, 278 L2__SRC_DISCARDf, 279 L2__DST_DISCARDf, 280 L2__DST_CPUf, 281 WIDE_0f, 282 WIDE_1f, 283 STATIC_BIT_0f, 284 STATIC_BIT_1f, 285 HITSAf, 286 HITDAf, 287 LOCAL_SAf, 288 L2__SIRIUS_Q_TAGf, 289 L2__EH_TAG_TYPEf, 290 L2__EH_TMf, 291 L2__EH_QUEUE_TAGf, 292 }; 293 294 static soc_field_t _bcm_tr3_ext_l2_entry_1_field_memacc_map[_BCM_TR3_L2_MEMACC_NUM] = { 295 INVALIDf, 296 INVALIDf, 297 FREEf, 298 KEY_TYPEf, 299 INVALIDf, 300 VLAN_IDf, 301 VFIf, 302 MAC_ADDRf, 303 PORT_NUMf, 304 TGIDf, 305 INVALIDf, 306 MODULE_IDf, 307 DESTINATIONf, 308 DEST_TYPEf, 309 PENDINGf, 310 LIMIT_COUNTEDf, 311 REMOTEf, 312 RPEf, 313 PRIf, 314 MAC_BLOCK_INDEXf, 315 CLASS_IDf, 316 CLASS_ID_FULLf, 317 SCPf, 318 INVALIDf, 319 INVALIDf, 320 INVALIDf, 321 INVALIDf, 322 INVALIDf, 323 STATIC_BITf, 324 INVALIDf, 325 HITSAf, 326 HITDAf, 327 LOCAL_SAf, 328 INVALIDf, 329 INVALIDf, 330 INVALIDf, 331 INVALIDf, 332 }; 333 334 static soc_field_t _bcm_tr3_ext_l2_entry_2_field_memacc_map[_BCM_TR3_L2_MEMACC_NUM] = { 335 INVALIDf, 336 INVALIDf, 337 FREEf, 338 KEY_TYPEf, 339 INVALIDf, 340 VLAN_IDf, 341 VFIf, 342 MAC_ADDRf, 343 PORT_NUMf, 344 TGIDf, 345 INVALIDf, 346 MODULE_IDf, 347 DESTINATIONf, 348 DEST_TYPEf, 349 PENDINGf, 350 LIMIT_COUNTEDf, 351 REMOTEf, 352 RPEf, 353 PRIf, 354 MAC_BLOCK_INDEXf, 355 CLASS_IDf, 356 CLASS_ID_FULLf, 357 SCPf, 358 SRC_DISCARDf, 359 DST_DISCARDf, 360 CPUf, 361 INVALIDf, 362 INVALIDf, 363 STATIC_BITf, 364 INVALIDf, 365 HITSAf, 366 HITDAf, 367 LOCAL_SAf, 368 SIRIUS_Q_TAGf, 369 EH_TAG_TYPEf, 370 EH_TMf, 371 EH_QUEUE_TAGf, 372 }; 373 374 static soc_field_t *_bcm_tr3_l2_field_memacc_maps[_BCM_TR3_L2_MEM_NUM] = { 375 _bcm_tr3_l2_entry_1_field_memacc_map, 376 _bcm_tr3_l2_entry_2_field_memacc_map, 377 _bcm_tr3_ext_l2_entry_1_field_memacc_map, 378 _bcm_tr3_ext_l2_entry_2_field_memacc_map, 379 }; 380 381 static soc_memacc_t *_bcm_tr3_l2_memacc_list[BCM_MAX_NUM_UNITS][_BCM_TR3_L2_MEM_NUM]; 382 383 #define _BCM_TR3_L2_MEMACC(_unit_, _mem_type_, _memacc_type_) \ 384 &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_##_mem_type_] \ 385 [_memacc_type_]) 386 387 #define _BCM_TR3_L2_FIELD_MEMACC(_unit_, _mem_type_, _field_type_) \ 388 &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_##_mem_type_] \ 389 [_BCM_TR3_L2_MEMACC_##_field_type_]) 390 391 #define _BCM_TR3_L2_1_FIELD_MEMACC(_unit_, _field_type_) \ 392 &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_L2_ENTRY_1] \ 393 [_BCM_TR3_L2_MEMACC_##_field_type_]) 394 395 #define _BCM_TR3_L2_1_FIELD32_MEMACC_GET(_unit_, _entry_, _field_type_) \ 396 soc_memacc_field32_get(_BCM_TR3_L2_1_FIELD_MEMACC(_unit_, \ 397 _field_type_), _entry_) 398 399 #define _BCM_TR3_L2_2_FIELD_MEMACC(_unit_, _field_type_) \ 400 &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_L2_ENTRY_2] \ 401 [_BCM_TR3_L2_MEMACC_##_field_type_]) 402 403 #define _BCM_TR3_L2_2_FIELD32_MEMACC_GET(_unit_, _entry_, _field_type_) \ 404 soc_memacc_field32_get(_BCM_TR3_L2_2_FIELD_MEMACC(_unit_, \ 405 _field_type_), _entry_) 406 407 #define _BCM_TR3_EXT_L2_1_FIELD_MEMACC(_unit_, _field_type_) \ 408 &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_EXT_L2_ENTRY_1] \ 409 [_BCM_TR3_L2_MEMACC_##_field_type_]) 410 411 #define _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(_unit_, _entry_, _field_type_) \ 412 soc_memacc_field32_get(_BCM_TR3_EXT_L2_1_FIELD_MEMACC(_unit_, \ 413 _field_type_), _entry_) 414 415 #define _BCM_TR3_EXT_L2_2_FIELD_MEMACC(_unit_, _field_type_) \ 416 &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_EXT_L2_ENTRY_2] \ 417 [_BCM_TR3_L2_MEMACC_##_field_type_]) 418 419 #define _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(_unit_, _entry_, _field_type_) \ 420 soc_memacc_field32_get(_BCM_TR3_EXT_L2_2_FIELD_MEMACC(_unit_, \ 421 _field_type_), _entry_) 422 423 /**************************************************************** 424 * 425 * L2 data definitions 426 */ 427 #define _BCM_TR3_L2_CLASS_ID_REDUCED_MASK 0x3f 428 429 typedef struct _bcm_tr3_l2_bookkeeping_s { 430 uint16 *my_station_hash; /* Hash values for MY STATION entries */ 431 my_station_tcam_entry_t *my_station_shadow; 432 my_station_tcam_entry_t my_station_l3_mask; 433 my_station_tcam_entry_t my_station_tunnel_mask; 434 } _bcm_tr3_l2_bookkeeping_t; 435 436 static _bcm_tr3_l2_bookkeeping_t _bcm_tr3_l2_bk_info[BCM_MAX_NUM_UNITS] = {{ 0 }}; 437 438 #define L2_INFO(_unit_) (&_bcm_tr3_l2_bk_info[_unit_]) 439 #define MY_STATION_HASH(_unit_, _index_) \ 440 (_bcm_tr3_l2_bk_info[_unit_].my_station_hash[_index_]) 441 442 /**************************************************************** 443 * 444 * Misc definitions 445 */ 446 #define _BCM_ALL_L2X_MEM_LOCK(unit) \ 447 SOC_L2X_MEM_LOCK(unit); \ 448 if (soc_feature(unit, soc_feature_esm_support)) { \ 449 SOC_EXT_L2X_MEM_LOCK(unit); \ 450 } 451 452 #define _BCM_ALL_L2X_MEM_UNLOCK(unit) \ 453 if (soc_feature(unit, soc_feature_esm_support)) { \ 454 SOC_EXT_L2X_MEM_UNLOCK(unit); \ 455 } \ 456 SOC_L2X_MEM_UNLOCK(unit); 457 458 #define _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv) \ 459 if (!BCM_SUCCESS(rv)) { \ 460 if (soc_feature(unit, soc_feature_esm_support)) { \ 461 SOC_EXT_L2X_MEM_UNLOCK(unit); \ 462 } \ 463 SOC_L2X_MEM_UNLOCK(unit); \ 464 return rv; \ 465 } 466 467 /**************************************************************** 468 * 469 * Debug L2 counts 470 */ 471 /* Definition for extern variable '_l2_addr_counts' */ 472 l2_count_data_t _l2_addr_counts; 473 474 STATIC int 475 _bcm_tr3_l2_replace(int unit, uint32 flags, bcm_l2_addr_t *match_addr, 476 bcm_module_t new_module, bcm_port_t new_port, 477 bcm_trunk_t new_trunk); 478 479 /* 480 * Function: 481 * _bcm_tr3_l2_memacc_init 482 * Description: 483 * Initialize the memory accelerators for the L2 tables enabled 484 * on this device variation. 485 * Parameters: 486 * unit - StrataSwitch unit number. 487 */ 488 489 STATIC int 490 _bcm_tr3_l2_memacc_init(int unit) 491 { 492 int alloc_size, rv = BCM_E_NONE; 493 soc_field_t *memacc_map; 494 soc_memacc_t *memacc_list; 495 int mem_idx, mam_ix, memacc_map_size = _BCM_TR3_L2_MEMACC_NUM; 496 497 alloc_size = (memacc_map_size * sizeof(soc_memacc_t)); 498 499 for (mem_idx = _BCM_TR3_L2_MEM_L2_ENTRY_1; 500 mem_idx < _BCM_TR3_L2_MEM_NUM; 501 mem_idx++) { 502 if (0 == (_BCM_TR3_L2_SELECT_ALL(unit) & (1 << mem_idx))) { 503 /* Table not enabled in this configuration */ 504 continue; 505 } 506 507 _bcm_tr3_l2_memacc_list[unit][mem_idx] = 508 sal_alloc(alloc_size, "L2 tables memacc data"); 509 if (NULL == _bcm_tr3_l2_memacc_list[unit][mem_idx]) { 510 rv = BCM_E_MEMORY; 511 break; 512 } 513 514 memacc_map = _bcm_tr3_l2_field_memacc_maps[mem_idx]; 515 memacc_list = _bcm_tr3_l2_memacc_list[unit][mem_idx]; 516 517 for (mam_ix = 0; mam_ix < memacc_map_size; mam_ix++) { 518 if (INVALIDf == memacc_map[mam_ix]) { 519 SOC_MEMACC_INVALID_SET(&(memacc_list[mam_ix])); 520 continue; 521 } 522 rv = soc_memacc_init(unit, _bcm_tr3_l2_mems[mem_idx], 523 memacc_map[mam_ix], 524 &(memacc_list[mam_ix])); 525 if (BCM_FAILURE(rv)) { 526 break; 527 } 528 } 529 530 if (BCM_FAILURE(rv)) { 531 break; 532 } 533 } 534 535 return rv; 536 } 537 538 typedef struct _bcm_tr3_l2_valid_memacc_s { 539 soc_memacc_t *valid; 540 soc_memacc_t *key_type; 541 soc_memacc_t *free; 542 soc_memacc_t *wide; 543 } _bcm_tr3_l2_valid_memacc_t; 544 545 /* 546 * Function: 547 * _bcm_tr3_l2_entry_traverse_valid 548 * Description: 549 * Check if given traversed L2 entry is Valid 550 * Parameters: 551 * memacc_list L2 memory accessors pre-loaded 552 * l2_entry L2 entry read from HW 553 * valid (OUT) Entry valid indicator 554 * Return: 555 * BCM_E_XXX 556 */ 557 int 558 _bcm_tr3_l2_entry_traverse_valid(_bcm_tr3_l2_valid_memacc_t *memacc_list, 559 uint32 *l2_entry, int *valid) 560 { 561 uint32 fval = 0; 562 int key_type; 563 564 if ((NULL == l2_entry) || (NULL == valid) || (NULL == memacc_list)) { 565 return BCM_E_PARAM; 566 } 567 568 if (NULL != memacc_list->valid) { 569 fval = soc_memacc_field32_get(memacc_list->valid, l2_entry); 570 571 if (fval && memacc_list->key_type) { 572 key_type = 573 soc_memacc_field32_get(memacc_list->key_type, l2_entry); 574 if ((SOC_MEM_KEY_L2_ENTRY_1_L2_VFI != key_type) && 575 (SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE != key_type) && 576 (SOC_MEM_KEY_L2_ENTRY_2_L2_VFI != key_type) && 577 (SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE != key_type)) { 578 /* Skip non-bridge/VFI L2 entries */ 579 fval = 0; 580 } 581 } 582 } else if (NULL != memacc_list->free) { 583 fval = !soc_memacc_field32_get(memacc_list->free, l2_entry); 584 } 585 586 *valid = fval ? TRUE : FALSE; 587 588 return (BCM_E_NONE); 589 } 590 591 /* 592 * Function: 593 * _bcm_tr3_l2_traverse_mem 594 * Description: 595 * Helper function to _bcm_tr3_l2_traverse to itterate over given 596 * memory and actually read the table and parse entries. 597 * Parameters: 598 * unit device number 599 * mem L2 memory to read 600 * trav_st Traverse structure with all the data. 601 * Return: 602 * BCM_E_XXX 603 */ 604 int 605 _bcm_tr3_l2_traverse_mem(int unit, soc_mem_t mem, 606 _bcm_l2_traverse_t *trav_st) 607 { 608 /* Indexes to iterate over memories, chunks and entries */ 609 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 610 int buf_size, valid, chunksize, chnk_end; 611 /* Buffer to store chunk of L2 table we currently work on */ 612 uint32 *l2_tbl_chnk; 613 uint32 *l2_entry; 614 int rv = BCM_E_NONE; 615 uint32 l2_entry_2[SOC_MAX_MEM_WORDS]; 616 uint32 *l2_src[4] = {0}; 617 _bcm_tr3_l2_valid_memacc_t l2_trav_memaccs; 618 619 if (!soc_mem_index_count(unit, mem)) { 620 return BCM_E_NONE; 621 } 622 623 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 624 L2_MEM_CHUNKS_DEFAULT); 625 626 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 627 l2_tbl_chnk = soc_cm_salloc(unit, buf_size, "l2 traverse"); 628 if (NULL == l2_tbl_chnk) { 629 return BCM_E_MEMORY; 630 } 631 632 switch (mem) { 633 case L2_ENTRY_1m: 634 l2_trav_memaccs.valid = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 635 _BCM_TR3_L2_MEMACC_VALID); 636 l2_trav_memaccs.key_type = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 637 _BCM_TR3_L2_MEMACC_KEY_TYPE); 638 l2_trav_memaccs.free = NULL; 639 l2_trav_memaccs.wide = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 640 _BCM_TR3_L2_MEMACC_WIDE); 641 break; 642 case EXT_L2_ENTRY_1m: 643 l2_trav_memaccs.valid = NULL; 644 l2_trav_memaccs.key_type = NULL; 645 l2_trav_memaccs.free = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 646 _BCM_TR3_L2_MEMACC_FREE); 647 l2_trav_memaccs.wide = NULL; 648 break; 649 case EXT_L2_ENTRY_2m: 650 l2_trav_memaccs.valid = NULL; 651 l2_trav_memaccs.key_type = NULL; 652 l2_trav_memaccs.free = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 653 _BCM_TR3_L2_MEMACC_FREE); 654 l2_trav_memaccs.wide = NULL; 655 break; 656 default: 657 return BCM_E_INTERNAL; 658 } 659 660 mem_idx_max = soc_mem_index_max(unit, mem); 661 for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 662 chnk_idx += chunksize) { 663 sal_memset((void *)l2_tbl_chnk, 0, buf_size); 664 665 chnk_idx_max = 666 ((chnk_idx + chunksize) < mem_idx_max) ? 667 (chnk_idx + chunksize - 1) : mem_idx_max; 668 669 soc_mem_lock(unit, mem); 670 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 671 chnk_idx, chnk_idx_max, l2_tbl_chnk); 672 soc_mem_unlock(unit, mem); 673 if (SOC_FAILURE(rv)) { 674 break; 675 } 676 chnk_end = (chnk_idx_max - chnk_idx); 677 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 678 l2_entry = 679 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 680 l2_tbl_chnk, ent_idx); 681 rv = _bcm_tr3_l2_entry_traverse_valid(&l2_trav_memaccs, 682 l2_entry, &valid); 683 if (BCM_FAILURE(rv)) { 684 break; 685 } 686 687 if (FALSE == valid) { 688 continue; 689 } 690 691 if ((NULL != l2_trav_memaccs.wide) && 692 (0 != soc_memacc_field32_get(l2_trav_memaccs.wide, 693 l2_entry))) { 694 /* The first element of an L2_ENTRY_2 entry detected */ 695 l2_src[0] = l2_entry; 696 l2_src[1] = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 697 l2_tbl_chnk, ent_idx + 1); 698 699 soc_mem_base_to_wide_entry_conv(unit, L2_ENTRY_2m, 700 L2_ENTRY_1m, 701 l2_entry_2, l2_src, 702 TYPE_1_TO_TYPE_2); 703 704 trav_st->data = l2_entry_2; 705 trav_st->mem = L2_ENTRY_2m; 706 trav_st->mem_idx = (chnk_idx + ent_idx) / 2; 707 ent_idx++; 708 } else { 709 trav_st->data = l2_entry; 710 trav_st->mem = mem; 711 trav_st->mem_idx = chnk_idx + ent_idx; 712 } 713 rv = trav_st->int_cb(unit, (void *)trav_st); 714 if (BCM_FAILURE(rv)) { 715 break; 716 } 717 } 718 if (BCM_FAILURE(rv)) { 719 break; 720 } 721 } 722 soc_cm_sfree(unit, l2_tbl_chnk); 723 return rv; 724 } 725 726 /* 727 * Function: 728 * _bcm_tr3_l2_traverse 729 * Description: 730 * Helper function to bcm_tr3_l2_traverse to itterate over tables 731 * and actually read the momery 732 * Parameters: 733 * unit device number 734 * trav_st Traverse structure with all the data. 735 * Return: 736 * BCM_E_XXX 737 */ 738 int 739 _bcm_tr3_l2_traverse(int unit, _bcm_l2_traverse_t *trav_st) 740 { 741 BCM_IF_ERROR_RETURN 742 (_bcm_tr3_l2_traverse_mem(unit, L2_ENTRY_1m, trav_st)); 743 744 if (soc_feature(unit, soc_feature_esm_support)) { 745 BCM_IF_ERROR_RETURN 746 (_bcm_tr3_l2_traverse_mem(unit, EXT_L2_ENTRY_1m, trav_st)); 747 BCM_IF_ERROR_RETURN 748 (_bcm_tr3_l2_traverse_mem(unit, EXT_L2_ENTRY_2m, trav_st)); 749 } 750 751 return BCM_E_NONE; 752 } 753 754 #ifdef BCM_WARM_BOOT_SUPPORT 755 int 756 _bcm_tr3_l2_reload_mbi_cb(int unit, void *trav_st) 757 { 758 int mb_index; 759 _bcm_l2_traverse_t *trv = (_bcm_l2_traverse_t *)trav_st; 760 _bcm_tr3_mac_block_info_t *mbi = trv->user_data; 761 762 trv = (_bcm_l2_traverse_t *)trav_st; 763 764 switch(trv->mem) { 765 case L2_ENTRY_1m: 766 mb_index = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, trv->data, 767 MAC_BLOCK_INDEX); 768 break; 769 case L2_ENTRY_2m: 770 mb_index = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, trv->data, 771 MAC_BLOCK_INDEX); 772 break; 773 case EXT_L2_ENTRY_1m: 774 mb_index = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, trv->data, 775 MAC_BLOCK_INDEX); 776 break; 777 case EXT_L2_ENTRY_2m: 778 mb_index = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, trv->data, 779 MAC_BLOCK_INDEX); 780 break; 781 default: 782 return BCM_E_INTERNAL; 783 } 784 785 mbi[mb_index].ref_count++; 786 return BCM_E_NONE; 787 } 788 789 /* 790 * Function: 791 * _bcm_tr3_l2_reload_mbi 792 * Description: 793 * Load MAC block info from hardware into software data structures. 794 * Parameters: 795 * unit - StrataSwitch unit number. 796 */ 797 798 STATIC int 799 _bcm_tr3_l2_reload_mbi(int unit) 800 { 801 _bcm_tr3_mac_block_info_t *mbi = _tr3_mbi_entries[unit]; 802 mac_block_entry_t mbe; 803 int mb_index; 804 pbmp_t mb_pbmp; 805 _bcm_l2_traverse_t trav_st; 806 807 /* 808 * Refresh MAC Block information from the hardware tables. 809 */ 810 811 for (mb_index = 0; mb_index < _tr3_mbi_num[unit]; mb_index++) { 812 SOC_IF_ERROR_RETURN 813 (READ_MAC_BLOCKm(unit, MEM_BLOCK_ANY, mb_index, &mbe)); 814 815 SOC_PBMP_CLEAR(mb_pbmp); 816 817 SOC_PBMP_WORD_SET(mb_pbmp, 0, soc_MAC_BLOCKm_field32_get(unit, 818 &mbe, MAC_BLOCK_MASK_W0f)); 819 SOC_PBMP_WORD_SET(mb_pbmp, 1, soc_MAC_BLOCKm_field32_get(unit, 820 &mbe, MAC_BLOCK_MASK_W1f)); 821 BCM_PBMP_ASSIGN(mbi[mb_index].mb_pbmp, mb_pbmp); 822 } 823 824 if (!SOC_CONTROL(unit)->l2x_group_enable) { 825 sal_memset(&trav_st, 0, sizeof(_bcm_l2_traverse_t)); 826 827 trav_st.user_cb = NULL; 828 trav_st.user_data = mbi; 829 trav_st.int_cb = _bcm_tr3_l2_reload_mbi_cb; 830 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_traverse(unit, &trav_st)); 831 } 832 833 return BCM_E_NONE; 834 } 835 #endif /* BCM_WARM_BOOT_SUPPORT */ 836 837 /* 838 * Function: 839 * _bcm_tr3_l2_mbi_init 840 * Purpose: 841 * Initialize BCM L2 MAC block index data. 842 * Parameters: 843 * unit - (IN) Unit number. 844 * Returns: 845 * BCM_E_xxx 846 * Notes: 847 */ 848 int 849 _bcm_tr3_l2_mbi_init(int unit) 850 { 851 if (_tr3_mbi_entries[unit] != NULL) { 852 sal_free(_tr3_mbi_entries[unit]); 853 _tr3_mbi_entries[unit] = NULL; 854 } 855 856 _tr3_mbi_num[unit] = soc_mem_index_count(unit, MAC_BLOCKm); 857 _tr3_mbi_entries[unit] = sal_alloc(_tr3_mbi_num[unit] * 858 sizeof(_bcm_tr3_mac_block_info_t), 859 "BCM L2X MAC blocking info"); 860 if (!_tr3_mbi_entries[unit]) { 861 return BCM_E_MEMORY; 862 } 863 864 sal_memset(_tr3_mbi_entries[unit], 0, 865 _tr3_mbi_num[unit] * sizeof(_bcm_tr3_mac_block_info_t)); 866 867 #ifdef BCM_WARM_BOOT_SUPPORT 868 if (SOC_WARM_BOOT(unit)) { 869 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_reload_mbi(unit)); 870 } 871 #endif /* BCM_WARM_BOOT_SUPPORT */ 872 873 return BCM_E_NONE; 874 } 875 876 /* 877 * Function: 878 * _bcm_tr3_mac_block_insert 879 * Purpose: 880 * Find or create a MAC_BLOCK table entry matching the given bitmap. 881 * Parameters: 882 * unit - Unit number 883 * mb_pbmp - egress port bitmap for source MAC blocking 884 * mb_index - (OUT) Index of MAC_BLOCK table with bitmap. 885 * Returns: 886 * BCM_E_NONE Success 887 * BCM_E_INTERNAL Chip access failure 888 * BCM_E_RESOURCE No more MAC_BLOCK entries available 889 * BCM_E_PARAM Bad bitmap supplied 890 */ 891 STATIC int 892 _bcm_tr3_mac_block_insert(int unit, bcm_pbmp_t mb_pbmp, int *mb_index) 893 { 894 int cur_index = 0; 895 _bcm_tr3_mac_block_info_t *mbi = _tr3_mbi_entries[unit]; 896 mac_block_entry_t mbe; 897 bcm_pbmp_t temp_pbmp; 898 899 /* Check for reasonable pbmp */ 900 BCM_PBMP_ASSIGN(temp_pbmp, mb_pbmp); 901 BCM_PBMP_AND(temp_pbmp, PBMP_ALL(unit)); 902 if (BCM_PBMP_NEQ(mb_pbmp, temp_pbmp)) { 903 return BCM_E_PARAM; 904 } 905 906 for (cur_index = 0; cur_index < _tr3_mbi_num[unit]; cur_index++) { 907 if (BCM_PBMP_EQ(mbi[cur_index].mb_pbmp, mb_pbmp)) { 908 mbi[cur_index].ref_count++; 909 *mb_index = cur_index; 910 return BCM_E_NONE; 911 } 912 } 913 914 /* Not in table already, see if any space free */ 915 for (cur_index = 1; cur_index < _tr3_mbi_num[unit]; cur_index++) { 916 if (mbi[cur_index].ref_count == 0) { 917 /* Attempt insert */ 918 sal_memset(&mbe, 0, sizeof(mac_block_entry_t)); 919 920 soc_mem_pbmp_field_set(unit, MAC_BLOCKm, &mbe, MAC_BLOCK_MASKf, 921 &mb_pbmp); 922 SOC_IF_ERROR_RETURN(WRITE_MAC_BLOCKm(unit, MEM_BLOCK_ALL, 923 cur_index, &mbe)); 924 mbi[cur_index].ref_count++; 925 BCM_PBMP_ASSIGN(mbi[cur_index].mb_pbmp, mb_pbmp); 926 *mb_index = cur_index; 927 return BCM_E_NONE; 928 } 929 } 930 931 /* Didn't find a free slot, out of table space */ 932 return BCM_E_RESOURCE; 933 } 934 935 /* 936 * Function: 937 * _bcm_tr3_mac_block_delete 938 * Purpose: 939 * Remove reference to MAC_BLOCK table entry matching the given bitmap. 940 * Parameters: 941 * unit - Unit number 942 * mb_index - Index of MAC_BLOCK table with bitmap. 943 */ 944 STATIC void 945 _bcm_tr3_mac_block_delete(int unit, int mb_index) 946 { 947 if (_tr3_mbi_entries[unit][mb_index].ref_count > 0) { 948 _tr3_mbi_entries[unit][mb_index].ref_count--; 949 } else if (mb_index) { 950 951 /* Someone reran init without flushing the L2 table */ 952 } /* else mb_index = 0, as expected for learning */ 953 } 954 955 /* 956 * Function: 957 * _bcm_tr3_l2hw_entries_field32_set 958 * Purpose: 959 * Set a field32 value for a Triumph3 L2 entry collection 960 * Parameters: 961 * unit Unit number 962 * l2_entries (IN/OUT) Triumph3 L2 entries structure 963 * l2_field Memacc type 964 * val Field value to set 965 */ 966 void 967 _bcm_tr3_l2hw_entries_field32_set(int unit, 968 _bcm_tr3_l2_entries_t *l2_entries, 969 _bcm_tr3_l2_memacc_type_t l2_field, 970 uint32 val) 971 { 972 soc_memacc_t *memacc; 973 974 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 975 /* L2_ENTRY_1 */ 976 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, l2_field); 977 if (SOC_MEMACC_VALID(memacc)) { 978 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_1), val); 979 } 980 } 981 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 982 /* L2_ENTRY_2 */ 983 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, l2_field); 984 if (SOC_MEMACC_VALID(memacc)) { 985 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), val); 986 } 987 } 988 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) { 989 /* EXT_L2_ENTRY_1 */ 990 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, l2_field); 991 if (SOC_MEMACC_VALID(memacc)) { 992 soc_memacc_field32_set(memacc, 993 &(l2_entries->ext_l2_entry_1), val); 994 } 995 } 996 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) { 997 /* EXT_L2_ENTRY_2 */ 998 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, l2_field); 999 if (SOC_MEMACC_VALID(memacc)) { 1000 soc_memacc_field32_set(memacc, 1001 &(l2_entries->ext_l2_entry_2), val); 1002 } 1003 } 1004 } 1005 1006 /* 1007 * Function: 1008 * _bcm_tr3_l2hw_entries_field32_get 1009 * Purpose: 1010 * Get a field32 value from a Triumph3 L2 entry collection 1011 * Parameters: 1012 * unit Unit number 1013 * l2_entries Triumph3 L2 entries structure 1014 * l2_field 1015 */ 1016 uint32 1017 _bcm_tr3_l2hw_entries_field32_get(int unit, 1018 _bcm_tr3_l2_entries_t *l2_entries, 1019 _bcm_tr3_l2_memacc_type_t l2_field) 1020 { 1021 soc_memacc_t *memacc; 1022 1023 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 1024 /* L2_ENTRY_1 */ 1025 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, l2_field); 1026 if (SOC_MEMACC_VALID(memacc)) { 1027 return soc_memacc_field32_get(memacc, &(l2_entries->l2_entry_1)); 1028 } 1029 } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 1030 /* L2_ENTRY_2 */ 1031 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, l2_field); 1032 if (SOC_MEMACC_VALID(memacc)) { 1033 return soc_memacc_field32_get(memacc, &(l2_entries->l2_entry_2)); 1034 } 1035 } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) { 1036 /* EXT_L2_ENTRY_1 */ 1037 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, l2_field); 1038 if (SOC_MEMACC_VALID(memacc)) { 1039 return soc_memacc_field32_get(memacc, 1040 &(l2_entries->ext_l2_entry_1)); 1041 } 1042 } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) { 1043 /* L2_ENTRY_2 */ 1044 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, l2_field); 1045 if (SOC_MEMACC_VALID(memacc)) { 1046 return soc_memacc_field32_get(memacc, 1047 &(l2_entries->ext_l2_entry_2)); 1048 } 1049 } 1050 1051 return 0; 1052 } 1053 1054 /* 1055 * Function: 1056 * _bcm_tr3_l2api_to_l2hw 1057 * Purpose: 1058 * Convert an L2 API data structure to a Triumph3 L2 entry collection 1059 * Parameters: 1060 * unit Unit number 1061 * l2_entries (OUT) Triumph3 L2 entries structure 1062 * l2addr L2 API data structure 1063 * key_only Only construct key portion 1064 */ 1065 int 1066 _bcm_tr3_l2api_to_l2hw(int unit, _bcm_tr3_l2_entries_t *l2_entries, 1067 bcm_l2_addr_t *l2addr, int key_only) 1068 { 1069 int is_vfi = FALSE; 1070 bcm_vlan_t vid, vlan_vfi; 1071 _bcm_tr3_l2_memacc_type_t field_type; 1072 soc_memacc_t *memacc; 1073 uint32 field_val; 1074 int pri_field_len; 1075 int max_pri; 1076 1077 pri_field_len = soc_mem_field_length(unit, L2_ENTRY_1m, PRIf); 1078 max_pri = (1 << pri_field_len) - 1; 1079 1080 /* Allow the maximum priority as per the device table support */ 1081 if ((l2addr->cos_dst < BCM_PRIO_MIN) || (l2addr->cos_dst > max_pri)) { 1082 return BCM_E_PARAM; 1083 } 1084 1085 /* BCM_L2_MIRROR is not supported starting from Triumph */ 1086 if (l2addr->flags & BCM_L2_MIRROR) { 1087 return BCM_E_PARAM; 1088 } 1089 1090 /* Setting both flags is not a valid configuration. */ 1091 if ((l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT) && 1092 (l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL)) { 1093 return BCM_E_PARAM; 1094 } 1095 1096 vlan_vfi = vid = l2addr->vid; 1097 if (_BCM_VPN_VFI_IS_SET(vid)) { 1098 is_vfi = TRUE; 1099 _BCM_VPN_GET(vlan_vfi, _BCM_VPN_TYPE_VFI, vid); 1100 } 1101 1102 field_type = _BCM_TR3_L2_MEMACC_VLAN_ID; 1103 if (is_vfi) { 1104 field_type = _BCM_TR3_L2_MEMACC_VFI; 1105 } else if (!_BCM_VPN_VFI_IS_SET(vid)) { 1106 VLAN_CHK_ID(unit, vid); 1107 } 1108 1109 if (is_vfi || !_BCM_VPN_VFI_IS_SET(vid)) { 1110 /* VLAN field, all desired entries */ 1111 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1112 field_type, vlan_vfi); 1113 /* The key types are different per entry type, 1114 * so handle individually here */ 1115 if (_BCM_TR3_L2_MEM_TYPE_VALID(l2_entries, L2_ENTRY_1)) { 1116 /* L2_ENTRY_1 */ 1117 field_val = is_vfi ? 1118 SOC_MEM_KEY_L2_ENTRY_1_L2_VFI : 1119 SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE; 1120 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 1121 _BCM_TR3_L2_MEMACC_KEY_TYPE); 1122 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_1), 1123 field_val); 1124 } 1125 if (_BCM_TR3_L2_MEM_TYPE_VALID(l2_entries, L2_ENTRY_2)) { 1126 /* L2_ENTRY_2 */ 1127 field_val = is_vfi ? 1128 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI : 1129 SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE; 1130 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1131 _BCM_TR3_L2_MEMACC_KEY_TYPE); 1132 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1133 field_val); 1134 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1135 _BCM_TR3_L2_MEMACC_KEY_TYPE_1); 1136 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1137 field_val); 1138 } 1139 if (_BCM_TR3_L2_MEM_TYPE_VALID(l2_entries, EXT_L2_ENTRY_1)) { 1140 /* EXT_L2_ENTRY_1 */ 1141 field_val = is_vfi ? 1142 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI : 1143 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE; 1144 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 1145 _BCM_TR3_L2_MEMACC_KEY_TYPE); 1146 soc_memacc_field32_set(memacc, &(l2_entries->ext_l2_entry_1), 1147 field_val); 1148 } 1149 if (_BCM_TR3_L2_MEM_TYPE_VALID(l2_entries, EXT_L2_ENTRY_2)) { 1150 /* EXT_L2_ENTRY_2 */ 1151 field_val = is_vfi ? 1152 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI : 1153 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE; 1154 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 1155 _BCM_TR3_L2_MEMACC_KEY_TYPE); 1156 soc_memacc_field32_set(memacc, &(l2_entries->ext_l2_entry_2), 1157 field_val); 1158 } 1159 } 1160 1161 /* MAC address has individual macros, so handle here */ 1162 field_type = _BCM_TR3_L2_MEMACC_MAC_ADDR; 1163 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 1164 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 1165 _BCM_TR3_L2_MEMACC_MAC_ADDR); 1166 soc_memacc_mac_addr_set(memacc, &(l2_entries->l2_entry_1), 1167 l2addr->mac); 1168 } 1169 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 1170 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1171 _BCM_TR3_L2_MEMACC_MAC_ADDR); 1172 soc_memacc_mac_addr_set(memacc, &(l2_entries->l2_entry_2), 1173 l2addr->mac); 1174 } 1175 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) { 1176 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 1177 _BCM_TR3_L2_MEMACC_MAC_ADDR); 1178 soc_memacc_mac_addr_set(memacc, &(l2_entries->ext_l2_entry_1), 1179 l2addr->mac); 1180 } 1181 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) { 1182 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 1183 _BCM_TR3_L2_MEMACC_MAC_ADDR); 1184 soc_memacc_mac_addr_set(memacc, &(l2_entries->ext_l2_entry_2), 1185 l2addr->mac); 1186 } 1187 1188 /* At this point, we've set the bridge/VFI key info ISM or ESM entries. 1189 * We can use these to search for any existing entry of this key. 1190 */ 1191 if (key_only) { 1192 return BCM_E_NONE; 1193 } 1194 1195 if (BCM_MAC_IS_MCAST(l2addr->mac)) { 1196 if (l2addr->l2mc_group < 0) { 1197 return BCM_E_PARAM; 1198 } 1199 if (_BCM_MULTICAST_IS_VPLS(l2addr->l2mc_group) || 1200 _BCM_MULTICAST_IS_MIM(l2addr->l2mc_group) || 1201 _BCM_MULTICAST_IS_WLAN(l2addr->l2mc_group) || 1202 _BCM_MULTICAST_IS_VLAN(l2addr->l2mc_group) || 1203 _BCM_MULTICAST_IS_NIV(l2addr->l2mc_group) || 1204 _BCM_MULTICAST_IS_L2GRE(l2addr->l2mc_group) || 1205 _BCM_MULTICAST_IS_SUBPORT(l2addr->l2mc_group) || 1206 _BCM_MULTICAST_IS_EXTENDER(l2addr->l2mc_group)) { 1207 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1208 _BCM_TR3_L2_MEMACC_DEST_TYPE, 0x3); 1209 } 1210 1211 if (_BCM_MULTICAST_IS_SET(l2addr->l2mc_group)) { 1212 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1213 _BCM_TR3_L2_MEMACC_DESTINATION, 1214 _BCM_MULTICAST_ID_GET(l2addr->l2mc_group)); 1215 } else { 1216 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1217 _BCM_TR3_L2_MEMACC_L2MC_PTR, 1218 l2addr->l2mc_group); 1219 } 1220 } else { 1221 bcm_port_t port = -1; 1222 bcm_trunk_t tgid = BCM_TRUNK_INVALID; 1223 bcm_module_t modid = -1; 1224 int gport_id = -1; 1225 1226 if (BCM_GPORT_IS_SET(l2addr->port)) { 1227 _bcm_l2_gport_params_t g_params; 1228 1229 if (BCM_GPORT_IS_BLACK_HOLE(l2addr->port)) { 1230 /* Must use an extended entry for this property */ 1231 l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED; 1232 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1233 _BCM_TR3_L2_MEMACC_SRC_DISCARD, 1); 1234 } else { 1235 /* 1236 * The SRC_DISCARD field only exists in some entry types, 1237 * was cleared with the init of the entries structure 1238 * when this was called. 1239 */ 1240 BCM_IF_ERROR_RETURN 1241 (_bcm_esw_l2_gport_parse(unit, l2addr, &g_params)); 1242 1243 switch (g_params.type) { 1244 case _SHR_GPORT_TYPE_TRUNK: 1245 tgid = g_params.param0; 1246 break; 1247 case _SHR_GPORT_TYPE_MODPORT: 1248 port = g_params.param0; 1249 modid = g_params.param1; 1250 break; 1251 case _SHR_GPORT_TYPE_LOCAL_CPU: 1252 port = g_params.param0; 1253 BCM_IF_ERROR_RETURN 1254 (bcm_esw_stk_my_modid_get(unit, &modid)); 1255 break; 1256 case _SHR_GPORT_TYPE_SUBPORT_GROUP: 1257 gport_id = g_params.param0; 1258 break; 1259 case _SHR_GPORT_TYPE_SUBPORT_PORT: 1260 gport_id = g_params.param0; 1261 break; 1262 case _SHR_GPORT_TYPE_MPLS_PORT: 1263 gport_id = g_params.param0; 1264 break; 1265 case _SHR_GPORT_TYPE_MIM_PORT: 1266 case _SHR_GPORT_TYPE_WLAN_PORT: 1267 case _SHR_GPORT_TYPE_VLAN_PORT: 1268 case _SHR_GPORT_TYPE_NIV_PORT: 1269 case _SHR_GPORT_TYPE_TRILL_PORT: 1270 case _SHR_GPORT_TYPE_L2GRE_PORT: 1271 case _SHR_GPORT_TYPE_VXLAN_PORT: 1272 case _SHR_GPORT_TYPE_EXTENDER_PORT: 1273 gport_id = g_params.param0; 1274 break; 1275 default: 1276 return BCM_E_PORT; 1277 } 1278 } 1279 } else if (l2addr->flags & BCM_L2_TRUNK_MEMBER) { 1280 tgid = l2addr->tgid; 1281 1282 } else { 1283 PORT_DUALMODID_VALID(unit, l2addr->port); 1284 BCM_IF_ERROR_RETURN( 1285 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 1286 l2addr->modid, l2addr->port, 1287 &modid, &port)); 1288 /* Check parameters */ 1289 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 1290 return BCM_E_BADID; 1291 } 1292 if (!SOC_PORT_ADDRESSABLE(unit, port)) { 1293 return BCM_E_PORT; 1294 } 1295 } 1296 1297 /* Setting l2_entries fields according to parameters */ 1298 if ( BCM_TRUNK_INVALID != tgid) { 1299 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1300 _BCM_TR3_L2_MEMACC_DEST_TYPE, 0x1); 1301 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1302 _BCM_TR3_L2_MEMACC_TGID, tgid); 1303 /* 1304 * Note: RTAG is ignored here. Use bcm_trunk_psc_set to 1305 * to set for a given trunk. 1306 */ 1307 if (l2addr->flags & BCM_L2_REMOTE_TRUNK) { 1308 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1309 _BCM_TR3_L2_MEMACC_REMOTE, 1); 1310 } 1311 } else if (-1 != port) { 1312 /* DEST_TYPE field was cleared by calling function. */ 1313 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1314 _BCM_TR3_L2_MEMACC_MODULE_ID, modid); 1315 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1316 _BCM_TR3_L2_MEMACC_PORT_NUM, port); 1317 } else if (-1 != gport_id) { 1318 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1319 _BCM_TR3_L2_MEMACC_DEST_TYPE, 0x2); 1320 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1321 _BCM_TR3_L2_MEMACC_DESTINATION, 1322 gport_id); 1323 } 1324 } 1325 1326 field_type = _BCM_TR3_L2_MEMACC_CLASS_ID_FULL; 1327 if (l2addr->flags & BCM_L2_SETPRI) { 1328 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1329 _BCM_TR3_L2_MEMACC_RPE, 1); 1330 if ((SOC_CONTROL(unit)->l2x_group_enable) && 1331 (l2addr->group != (l2addr->group & 1332 _BCM_TR3_L2_CLASS_ID_REDUCED_MASK))) { 1333 /* The priority field is an overlay on the high bits of the 1334 * class id, so we can't use the full size if RPE is set 1335 * on the reduced entry size. Must be extended entry now. 1336 */ 1337 l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED; 1338 } else { 1339 field_type = _BCM_TR3_L2_MEMACC_CLASS_ID; 1340 } 1341 } 1342 1343 if (SOC_CONTROL(unit)->l2x_group_enable) { 1344 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1345 field_type, l2addr->group); 1346 } /* else MAC_BLOCK_INDEXf is handled in the add/remove functions below */ 1347 1348 if (l2addr->flags & BCM_L2_SETPRI) { 1349 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1350 _BCM_TR3_L2_MEMACC_PRI, l2addr->cos_dst); 1351 } 1352 1353 if (l2addr->flags & BCM_L2_COPY_TO_CPU) { 1354 /* CPU bit is only in the extended entry format. */ 1355 l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED; 1356 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1357 _BCM_TR3_L2_MEMACC_DST_CPU, 1); 1358 } 1359 1360 if (l2addr->flags & BCM_L2_DISCARD_DST) { 1361 /* Destination discard bit is only in the extended entry format. */ 1362 l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED; 1363 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1364 _BCM_TR3_L2_MEMACC_DST_DISCARD, 1); 1365 } 1366 1367 if (l2addr->flags & BCM_L2_DISCARD_SRC) { 1368 /* Source discard bit is only in the extended entry format. */ 1369 l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED; 1370 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1371 _BCM_TR3_L2_MEMACC_SRC_DISCARD, 1); 1372 } 1373 1374 if (l2addr->flags & BCM_L2_COS_SRC_PRI) { 1375 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1376 _BCM_TR3_L2_MEMACC_SCP, 1); 1377 } 1378 1379 if ((!(l2addr->flags & (BCM_L2_L3LOOKUP | BCM_L2_MCAST | 1380 BCM_L2_STATIC | BCM_L2_LEARN_LIMIT_EXEMPT))) || 1381 l2addr->flags & BCM_L2_LEARN_LIMIT) { 1382 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1383 _BCM_TR3_L2_MEMACC_LIMIT_COUNTED, 1); 1384 } 1385 1386 if (l2addr->flags & BCM_L2_PENDING) { 1387 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1388 _BCM_TR3_L2_MEMACC_PENDING, 1); 1389 } 1390 1391 /* If BCM_L2_DES_HIT is set, HITDA has to be set. But if only BCM_L2_HIT 1392 is set, HITDA has to be set based on aging scheme */ 1393 if ((l2addr->flags & BCM_L2_DES_HIT) || 1394 (l2addr->flags & BCM_L2_HIT)) { 1395 if ((!SOC_CONTROL(unit)->l2x_age_hitsa_only) || 1396 (l2addr->flags & BCM_L2_DES_HIT)) { 1397 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1398 _BCM_TR3_L2_MEMACC_HITDA, 1); 1399 } 1400 } 1401 1402 if ((l2addr->flags & BCM_L2_SRC_HIT) || 1403 (l2addr->flags & BCM_L2_HIT)) { 1404 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1405 _BCM_TR3_L2_MEMACC_HITSA, 1); 1406 } 1407 1408 if (l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL) { 1409 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1410 _BCM_TR3_L2_MEMACC_REMOTE, 1); 1411 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1412 _BCM_TR3_L2_MEMACC_LIMIT_COUNTED, 1); 1413 } 1414 1415 1416 1417 if (l2addr->flags & BCM_L2_STATIC) { 1418 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries, 1419 _BCM_TR3_L2_MEMACC_STATIC_BIT, 1); 1420 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 1421 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1422 _BCM_TR3_L2_MEMACC_STATIC_BIT_1); 1423 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1); 1424 } 1425 } 1426 1427 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 1428 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 1429 _BCM_TR3_L2_MEMACC_VALID); 1430 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_1), 1); 1431 } 1432 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 1433 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1434 _BCM_TR3_L2_MEMACC_VALID); 1435 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1); 1436 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1437 _BCM_TR3_L2_MEMACC_VALID_1); 1438 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1); 1439 1440 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1441 _BCM_TR3_L2_MEMACC_WIDE); 1442 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1); 1443 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1444 _BCM_TR3_L2_MEMACC_WIDE_1); 1445 soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1); 1446 } 1447 1448 /* EXT L2 tables use FREE field instead of VALID */ 1449 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) { 1450 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 1451 _BCM_TR3_L2_MEMACC_FREE); 1452 soc_memacc_field32_set(memacc, &(l2_entries->ext_l2_entry_1), 0); 1453 } 1454 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) { 1455 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 1456 _BCM_TR3_L2_MEMACC_FREE); 1457 soc_memacc_field32_set(memacc, &(l2_entries->ext_l2_entry_2), 0); 1458 } 1459 1460 if (0 == l2_entries->entry_flags) { 1461 /* We couldn't find a memory which can satisfy the requested 1462 * L2 addr specification. 1463 */ 1464 return BCM_E_PARAM; 1465 } 1466 1467 return BCM_E_NONE; 1468 } 1469 1470 /* 1471 * Function: 1472 * _bcm_tr3_l2_from_l2_1 1473 * Purpose: 1474 * Convert an L2_ENTRY_1 to an L2 API data structure 1475 1476 * Parameters: 1477 * unit Unit number 1478 * l2addr (OUT) L2 API data structure 1479 * L2_entry_1 L2_ENTRY_1 hardware entry 1480 */ 1481 int 1482 _bcm_tr3_l2_from_l2_1(int unit, bcm_l2_addr_t *l2addr, 1483 l2_entry_1_entry_t *l2_entry_1) 1484 { 1485 _bcm_gport_dest_t dest; 1486 int mb_index; 1487 bcm_module_t mod; 1488 bcm_port_t port; 1489 soc_memacc_t *memacc; 1490 int isGport = 0; 1491 #if defined(INCLUDE_L3) 1492 int vfi; 1493 #endif 1494 sal_memset(l2addr, 0, sizeof(*l2addr)); 1495 1496 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, KEY_TYPE) == 1497 SOC_MEM_KEY_L2_ENTRY_1_L2_VFI) { 1498 #if defined(INCLUDE_L3) 1499 vfi = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, VFI); 1500 /* VPLS or MIM VPN */ 1501 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 1502 _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi); 1503 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) { 1504 _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi); 1505 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) { 1506 BCM_IF_ERROR_RETURN( 1507 _bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid)); 1508 } 1509 #endif 1510 } else { 1511 l2addr->vid = 1512 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, VLAN_ID); 1513 } 1514 1515 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 1516 _BCM_TR3_L2_MEMACC_MAC_ADDR); 1517 soc_memacc_mac_addr_get(memacc, l2_entry_1, l2addr->mac); 1518 1519 _bcm_gport_dest_t_init(&dest); 1520 #if defined(INCLUDE_L3) 1521 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1522 DEST_TYPE) == 0x2) { 1523 int vp; 1524 1525 vp = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1526 DESTINATION); 1527 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1528 KEY_TYPE) == 1529 SOC_MEM_KEY_L2_ENTRY_1_L2_VFI) { 1530 /* MPLS/MiM virtual port unicast */ 1531 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 1532 dest.mpls_id = vp; 1533 dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT; 1534 isGport=1; 1535 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) { 1536 dest.mim_id = vp; 1537 dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT; 1538 isGport=1; 1539 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 1540 dest.l2gre_id= vp; 1541 dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT; 1542 isGport=1; 1543 } else { 1544 /* L2 entries with Stale VPN */ 1545 dest.gport_type = BCM_GPORT_INVALID; 1546 isGport=0; 1547 } 1548 } else { 1549 /* Subport/WLAN unicast */ 1550 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) { 1551 dest.subport_id = vp; 1552 dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP; 1553 isGport=1; 1554 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) { 1555 dest.wlan_id = vp; 1556 dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT; 1557 isGport=1; 1558 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 1559 dest.vlan_vp_id = vp; 1560 dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT; 1561 isGport=1; 1562 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 1563 dest.trill_id = vp; 1564 dest.gport_type = _SHR_GPORT_TYPE_TRILL_PORT; 1565 isGport=1; 1566 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 1567 dest.niv_id = vp; 1568 dest.gport_type = _SHR_GPORT_TYPE_NIV_PORT; 1569 isGport=1; 1570 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 1571 dest.extender_id = vp; 1572 dest.gport_type = _SHR_GPORT_TYPE_EXTENDER_PORT; 1573 isGport=1; 1574 } else { 1575 /* L2 entries with Stale Gport */ 1576 dest.gport_type = BCM_GPORT_INVALID; 1577 isGport=0; 1578 } 1579 } 1580 } else { 1581 #endif /* INCLUDE_L3 */ 1582 BCM_IF_ERROR_RETURN 1583 (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 1584 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1585 DEST_TYPE) == 0x1) { 1586 int psc = 0; 1587 l2addr->tgid = 1588 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, TGID); 1589 bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc); 1590 dest.tgid = l2addr->tgid; 1591 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 1592 1593 l2addr->flags |= BCM_L2_TRUNK_MEMBER; 1594 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1595 REMOTE)) { 1596 l2addr->flags |= BCM_L2_REMOTE_TRUNK; 1597 } 1598 } else { 1599 if (BCM_MAC_IS_MCAST(l2addr->mac)) { 1600 l2addr->flags |= BCM_L2_MCAST; 1601 l2addr->l2mc_group = 1602 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1603 L2MC_PTR); 1604 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_1, KEY_TYPE) == 1605 SOC_MEM_KEY_L2_ENTRY_1_L2_VFI) { 1606 #if defined(INCLUDE_L3) 1607 vfi = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, VFI); 1608 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 1609 _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, 1610 _BCM_MULTICAST_TYPE_VPLS, l2addr->l2mc_group); 1611 } else 1612 #endif /* INCLUDE_L3 */ 1613 { 1614 _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, 1615 _BCM_MULTICAST_TYPE_MIM, l2addr->l2mc_group); 1616 } 1617 } 1618 isGport = 0; 1619 } else { 1620 mod = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1621 MODULE_ID); 1622 port = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1623 PORT_NUM); 1624 BCM_IF_ERROR_RETURN 1625 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 1626 mod, port, &mod, &port)); 1627 l2addr->modid = mod; 1628 l2addr->port = port; 1629 dest.port = l2addr->port; 1630 dest.modid = l2addr->modid; 1631 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 1632 } 1633 } 1634 #if defined(INCLUDE_L3) 1635 } 1636 #endif /* INCLUDE_L3 */ 1637 1638 if (isGport) { 1639 BCM_IF_ERROR_RETURN 1640 (_bcm_esw_gport_construct(unit, &dest, &l2addr->port)); 1641 } 1642 1643 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, RPE)) { 1644 l2addr->flags |= BCM_L2_SETPRI; 1645 l2addr->cos_dst = 1646 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, PRI); 1647 } 1648 l2addr->cos_src = l2addr->cos_dst; 1649 1650 if (SOC_CONTROL(unit)->l2x_group_enable) { 1651 if (l2addr->flags & BCM_L2_SETPRI) { 1652 l2addr->group = 1653 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1654 CLASS_ID); 1655 } else { 1656 /* Use extended field name when available for non-RPE case. */ 1657 l2addr->group = 1658 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1659 CLASS_ID_FULL); 1660 } 1661 } else { 1662 mb_index = 1663 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1664 MAC_BLOCK_INDEX); 1665 if (mb_index) { 1666 BCM_PBMP_ASSIGN(l2addr->block_bitmap, 1667 _tr3_mbi_entries[unit][mb_index].mb_pbmp); 1668 } 1669 } 1670 1671 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, SCP)) { 1672 l2addr->flags |= BCM_L2_COS_SRC_PRI; 1673 } 1674 1675 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, PENDING)) { 1676 l2addr->flags |= BCM_L2_PENDING; 1677 } 1678 1679 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, STATIC_BIT)) { 1680 l2addr->flags |= BCM_L2_STATIC; 1681 } 1682 1683 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, HITDA)) { 1684 l2addr->flags |= BCM_L2_DES_HIT; 1685 if (!SOC_CONTROL(unit)->l2x_age_hitsa_only) { 1686 l2addr->flags |= BCM_L2_HIT; 1687 } 1688 } 1689 1690 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, HITSA)) { 1691 l2addr->flags |= BCM_L2_SRC_HIT; 1692 l2addr->flags |= BCM_L2_HIT; 1693 } 1694 1695 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, LOCAL_SA)) { 1696 l2addr->flags |= BCM_L2_NATIVE; 1697 } 1698 1699 if ((!(l2addr->flags & BCM_L2_STATIC)) || 1700 l2addr->flags & BCM_L2_LEARN_LIMIT ) { 1701 if (!_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, 1702 LIMIT_COUNTED)) { 1703 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT; 1704 } 1705 } 1706 1707 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, REMOTE)) { 1708 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL; 1709 } 1710 1711 return BCM_E_NONE; 1712 } 1713 1714 /* 1715 * Function: 1716 * _bcm_tr3_l2_from_l2_2 1717 * Purpose: 1718 * Convert an L2_ENTRY_2 to an L2 API data structure 1719 1720 * Parameters: 1721 * unit Unit number 1722 * l2addr (OUT) L2 API data structure 1723 * l2_entry_2 L2_ENTRY_2 hardware entry 1724 */ 1725 int 1726 _bcm_tr3_l2_from_l2_2(int unit, bcm_l2_addr_t *l2addr, 1727 l2_entry_2_entry_t *l2_entry_2) 1728 { 1729 _bcm_gport_dest_t dest; 1730 int mb_index; 1731 bcm_module_t mod; 1732 bcm_port_t port; 1733 soc_memacc_t *memacc; 1734 int isGport = 0; 1735 #if defined(INCLUDE_L3) 1736 int vfi; 1737 #endif 1738 sal_memset(l2addr, 0, sizeof(*l2addr)); 1739 1740 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, KEY_TYPE) == 1741 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) { 1742 #if defined(INCLUDE_L3) 1743 vfi = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, VFI); 1744 /* VPLS or MIM VPN */ 1745 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 1746 _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi); 1747 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) { 1748 _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi); 1749 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) { 1750 BCM_IF_ERROR_RETURN( 1751 _bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid)); 1752 } 1753 1754 #endif 1755 } else { 1756 l2addr->vid = 1757 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, VLAN_ID); 1758 } 1759 1760 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 1761 _BCM_TR3_L2_MEMACC_MAC_ADDR); 1762 soc_memacc_mac_addr_get(memacc, l2_entry_2, l2addr->mac); 1763 1764 _bcm_gport_dest_t_init(&dest); 1765 #if defined(INCLUDE_L3) 1766 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1767 DEST_TYPE) == 0x2) { 1768 int vp; 1769 1770 vp = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1771 DESTINATION); 1772 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1773 KEY_TYPE) == 1774 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) { 1775 /* MPLS/MiM virtual port unicast */ 1776 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 1777 dest.mpls_id = vp; 1778 dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT; 1779 isGport=1; 1780 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) { 1781 dest.mim_id = vp; 1782 dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT; 1783 isGport=1; 1784 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 1785 dest.mim_id = vp; 1786 dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT; 1787 isGport=1; 1788 } else { 1789 /* L2 entries with Stale VPN */ 1790 dest.gport_type = BCM_GPORT_INVALID; 1791 isGport=0; 1792 } 1793 } else { 1794 /* Subport/WLAN unicast */ 1795 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) { 1796 dest.subport_id = vp; 1797 dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP; 1798 isGport=1; 1799 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) { 1800 dest.wlan_id = vp; 1801 dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT; 1802 isGport=1; 1803 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 1804 dest.vlan_vp_id = vp; 1805 dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT; 1806 isGport=1; 1807 } else { 1808 /* L2 entries with Stale Gport */ 1809 dest.gport_type = BCM_GPORT_INVALID; 1810 isGport=0; 1811 } 1812 } 1813 } else { 1814 #endif /* INCLUDE_L3 */ 1815 BCM_IF_ERROR_RETURN 1816 (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 1817 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1818 DEST_TYPE) == 0x1) { 1819 int psc = 0; 1820 l2addr->tgid = 1821 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, TGID); 1822 bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc); 1823 dest.tgid = l2addr->tgid; 1824 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 1825 1826 l2addr->flags |= BCM_L2_TRUNK_MEMBER; 1827 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1828 REMOTE)) { 1829 l2addr->flags |= BCM_L2_REMOTE_TRUNK; 1830 } 1831 } else { 1832 if (BCM_MAC_IS_MCAST(l2addr->mac)) { 1833 l2addr->flags |= BCM_L2_MCAST; 1834 l2addr->l2mc_group = 1835 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1836 L2MC_PTR); 1837 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, KEY_TYPE) == 1838 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) { 1839 #if defined(INCLUDE_L3) 1840 vfi = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_2, VFI); 1841 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 1842 _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, 1843 _BCM_MULTICAST_TYPE_VPLS, l2addr->l2mc_group); 1844 } else 1845 #endif /* INCLUDE_L3 */ 1846 { 1847 _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, 1848 _BCM_MULTICAST_TYPE_MIM, l2addr->l2mc_group); 1849 } 1850 } 1851 isGport = 0; 1852 } else { 1853 mod = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1854 MODULE_ID); 1855 port = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1856 PORT_NUM); 1857 BCM_IF_ERROR_RETURN 1858 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 1859 mod, port, &mod, &port)); 1860 l2addr->modid = mod; 1861 l2addr->port = port; 1862 dest.port = l2addr->port; 1863 dest.modid = l2addr->modid; 1864 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 1865 } 1866 } 1867 #if defined(INCLUDE_L3) 1868 } 1869 #endif /* INCLUDE_L3 */ 1870 1871 if (isGport) { 1872 BCM_IF_ERROR_RETURN 1873 (_bcm_esw_gport_construct(unit, &dest, &l2addr->port)); 1874 } 1875 1876 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, RPE)) { 1877 l2addr->flags |= BCM_L2_SETPRI; 1878 l2addr->cos_dst = 1879 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, PRI); 1880 } 1881 l2addr->cos_src = l2addr->cos_dst; 1882 1883 if (SOC_CONTROL(unit)->l2x_group_enable) { 1884 l2addr->group = 1885 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1886 CLASS_ID_FULL); 1887 } else { 1888 mb_index = 1889 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1890 MAC_BLOCK_INDEX); 1891 if (mb_index) { 1892 BCM_PBMP_ASSIGN(l2addr->block_bitmap, 1893 _tr3_mbi_entries[unit][mb_index].mb_pbmp); 1894 } 1895 } 1896 1897 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, DST_CPU)) { 1898 l2addr->flags |= BCM_L2_COPY_TO_CPU; 1899 } 1900 1901 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, DST_DISCARD)) { 1902 l2addr->flags |= BCM_L2_DISCARD_DST; 1903 } 1904 1905 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, SRC_DISCARD)) { 1906 l2addr->flags |= BCM_L2_DISCARD_SRC; 1907 } 1908 1909 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, SCP)) { 1910 l2addr->flags |= BCM_L2_COS_SRC_PRI; 1911 } 1912 1913 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, PENDING)) { 1914 l2addr->flags |= BCM_L2_PENDING; 1915 } 1916 1917 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, STATIC_BIT)) { 1918 l2addr->flags |= BCM_L2_STATIC; 1919 } 1920 1921 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, HITDA)) { 1922 l2addr->flags |= BCM_L2_DES_HIT; 1923 if (!SOC_CONTROL(unit)->l2x_age_hitsa_only) { 1924 l2addr->flags |= BCM_L2_HIT; 1925 } 1926 } 1927 1928 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, HITSA)) { 1929 l2addr->flags |= BCM_L2_SRC_HIT; 1930 l2addr->flags |= BCM_L2_HIT; 1931 } 1932 1933 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, LOCAL_SA)) { 1934 l2addr->flags |= BCM_L2_NATIVE; 1935 } 1936 1937 if ((!(l2addr->flags & BCM_L2_STATIC)) || 1938 l2addr->flags & BCM_L2_LEARN_LIMIT ) { 1939 if (!_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, 1940 LIMIT_COUNTED)) { 1941 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT; 1942 } 1943 } 1944 1945 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, REMOTE)) { 1946 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL; 1947 } 1948 1949 1950 1951 return BCM_E_NONE; 1952 } 1953 1954 /* 1955 * Function: 1956 * _bcm_tr3_l2_from_ext_l2_1 1957 * Purpose: 1958 * Convert an EXT_L2_ENTRY_1 to an L2 API data structure 1959 1960 * Parameters: 1961 * unit Unit number 1962 * l2addr (OUT) L2 API data structure 1963 * ext_l2_entry_1 EXT_L2_ENTRY_1 hardware entry 1964 */ 1965 int 1966 _bcm_tr3_l2_from_ext_l2_1(int unit, bcm_l2_addr_t *l2addr, 1967 ext_l2_entry_1_entry_t *ext_l2_entry_1) 1968 { 1969 _bcm_gport_dest_t dest; 1970 int mb_index; 1971 bcm_module_t mod; 1972 bcm_port_t port; 1973 soc_memacc_t *memacc; 1974 int isGport = 0; 1975 #if defined(INCLUDE_L3) 1976 int vfi; 1977 #endif 1978 sal_memset(l2addr, 0, sizeof(*l2addr)); 1979 1980 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 1981 KEY_TYPE) == 1982 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI) { 1983 #if defined(INCLUDE_L3) 1984 vfi = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 1985 VFI); 1986 /* VPLS or MIM VPN */ 1987 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 1988 _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi); 1989 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) { 1990 _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi); 1991 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) { 1992 BCM_IF_ERROR_RETURN( 1993 _bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid)); 1994 } 1995 #endif 1996 } else { 1997 l2addr->vid = 1998 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 1999 VLAN_ID); 2000 } 2001 2002 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 2003 _BCM_TR3_L2_MEMACC_MAC_ADDR); 2004 soc_memacc_mac_addr_get(memacc, ext_l2_entry_1, l2addr->mac); 2005 2006 _bcm_gport_dest_t_init(&dest); 2007 #if defined(INCLUDE_L3) 2008 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2009 DEST_TYPE) == 0x2) { 2010 int vp; 2011 2012 vp = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2013 DESTINATION); 2014 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2015 KEY_TYPE) == 2016 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI) { 2017 /* MPLS/MiM virtual port unicast */ 2018 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 2019 dest.mpls_id = vp; 2020 dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT; 2021 isGport=1; 2022 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) { 2023 dest.mim_id = vp; 2024 dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT; 2025 isGport=1; 2026 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 2027 dest.l2gre_id= vp; 2028 dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT; 2029 isGport=1; 2030 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) { 2031 dest.vxlan_id= vp; 2032 dest.gport_type = _SHR_GPORT_TYPE_VXLAN_PORT; 2033 isGport=1; 2034 } else { 2035 /* L2 entries with Stale VPN */ 2036 dest.gport_type = BCM_GPORT_INVALID; 2037 isGport=0; 2038 } 2039 } else { 2040 /* Subport/WLAN unicast */ 2041 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) { 2042 dest.subport_id = vp; 2043 dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP; 2044 isGport=1; 2045 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) { 2046 dest.wlan_id = vp; 2047 dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT; 2048 isGport=1; 2049 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 2050 dest.vlan_vp_id = vp; 2051 dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT; 2052 isGport=1; 2053 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 2054 dest.trill_id = vp; 2055 dest.gport_type = _SHR_GPORT_TYPE_TRILL_PORT; 2056 isGport=1; 2057 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 2058 dest.niv_id = vp; 2059 dest.gport_type = _SHR_GPORT_TYPE_NIV_PORT; 2060 isGport=1; 2061 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 2062 dest.extender_id = vp; 2063 dest.gport_type = _SHR_GPORT_TYPE_EXTENDER_PORT; 2064 isGport=1; 2065 } else { 2066 /* L2 entries with Stale VPN */ 2067 dest.gport_type = BCM_GPORT_INVALID; 2068 isGport=0; 2069 } 2070 } 2071 } else { 2072 #endif /* INCLUDE_L3 */ 2073 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2074 DEST_TYPE) == 0x1) { 2075 int psc = 0; 2076 l2addr->tgid = 2077 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2078 TGID); 2079 bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc); 2080 dest.tgid = l2addr->tgid; 2081 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 2082 2083 l2addr->flags |= BCM_L2_TRUNK_MEMBER; 2084 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2085 REMOTE)) { 2086 l2addr->flags |= BCM_L2_REMOTE_TRUNK; 2087 } 2088 } else { 2089 mod = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2090 MODULE_ID); 2091 port = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2092 PORT_NUM); 2093 BCM_IF_ERROR_RETURN 2094 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 2095 mod, port, &mod, &port)); 2096 l2addr->modid = mod; 2097 l2addr->port = port; 2098 dest.port = l2addr->port; 2099 dest.modid = l2addr->modid; 2100 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 2101 } 2102 BCM_IF_ERROR_RETURN 2103 (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 2104 #if defined(INCLUDE_L3) 2105 } 2106 #endif /* INCLUDE_L3 */ 2107 2108 if (isGport) { 2109 BCM_IF_ERROR_RETURN 2110 (_bcm_esw_gport_construct(unit, &dest, &l2addr->port)); 2111 } 2112 2113 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, RPE)) { 2114 l2addr->flags |= BCM_L2_SETPRI; 2115 l2addr->cos_dst = 2116 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2117 PRI); 2118 } 2119 l2addr->cos_src = l2addr->cos_dst; 2120 2121 if (SOC_CONTROL(unit)->l2x_group_enable) { 2122 if (l2addr->flags & BCM_L2_SETPRI) { 2123 l2addr->group = 2124 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2125 CLASS_ID); 2126 } else { 2127 l2addr->group = 2128 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2129 CLASS_ID_FULL); 2130 } 2131 } else { 2132 mb_index = 2133 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2134 MAC_BLOCK_INDEX); 2135 if (mb_index) { 2136 BCM_PBMP_ASSIGN(l2addr->block_bitmap, 2137 _tr3_mbi_entries[unit][mb_index].mb_pbmp); 2138 } 2139 } 2140 2141 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, SCP)) { 2142 l2addr->flags |= BCM_L2_COS_SRC_PRI; 2143 } 2144 2145 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2146 PENDING)) { 2147 l2addr->flags |= BCM_L2_PENDING; 2148 } 2149 2150 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2151 STATIC_BIT)) { 2152 l2addr->flags |= BCM_L2_STATIC; 2153 } 2154 2155 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2156 HITDA)) { 2157 l2addr->flags |= BCM_L2_DES_HIT; 2158 if (!SOC_CONTROL(unit)->l2x_age_hitsa_only) { 2159 l2addr->flags |= BCM_L2_HIT; 2160 } 2161 } 2162 2163 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2164 HITSA)) { 2165 l2addr->flags |= BCM_L2_SRC_HIT; 2166 l2addr->flags |= BCM_L2_HIT; 2167 } 2168 2169 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2170 LOCAL_SA)) { 2171 l2addr->flags |= BCM_L2_NATIVE; 2172 } 2173 2174 if ((!(l2addr->flags & BCM_L2_STATIC)) || 2175 l2addr->flags & BCM_L2_LEARN_LIMIT) { 2176 if (!_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2177 LIMIT_COUNTED)) { 2178 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT; 2179 } 2180 } 2181 2182 if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 2183 REMOTE)) { 2184 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL; 2185 } 2186 2187 return BCM_E_NONE; 2188 } 2189 2190 /* 2191 * Function: 2192 * _bcm_tr3_l2_from_ext_l2_2 2193 * Purpose: 2194 * Convert an EXT_L2_ENTRY_2 to an L2 API data structure 2195 2196 * Parameters: 2197 * unit Unit number 2198 * l2addr (OUT) L2 API data structure 2199 * ext_l2_entry_2 EXT_L2_ENTRY_2 hardware entry 2200 */ 2201 int 2202 _bcm_tr3_l2_from_ext_l2_2(int unit, bcm_l2_addr_t *l2addr, 2203 ext_l2_entry_2_entry_t *ext_l2_entry_2) 2204 { 2205 _bcm_gport_dest_t dest; 2206 int mb_index; 2207 bcm_module_t mod; 2208 bcm_port_t port; 2209 soc_memacc_t *memacc; 2210 int isGport = 0; 2211 #if defined(INCLUDE_L3) 2212 int vfi; 2213 #endif 2214 sal_memset(l2addr, 0, sizeof(*l2addr)); 2215 2216 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2217 KEY_TYPE) == 2218 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI) { 2219 #if defined(INCLUDE_L3) 2220 vfi = _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2221 VFI); 2222 /* VPLS or MIM VPN */ 2223 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 2224 _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi); 2225 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) { 2226 _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi); 2227 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) { 2228 BCM_IF_ERROR_RETURN( 2229 _bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid)); 2230 } 2231 #endif 2232 } else { 2233 l2addr->vid = 2234 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2235 VLAN_ID); 2236 } 2237 2238 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 2239 _BCM_TR3_L2_MEMACC_MAC_ADDR); 2240 soc_memacc_mac_addr_get(memacc, ext_l2_entry_2, l2addr->mac); 2241 2242 _bcm_gport_dest_t_init(&dest); 2243 #if defined(INCLUDE_L3) 2244 if (soc_mem_field32_get(unit, EXT_L2_ENTRY_2m, 2245 ext_l2_entry_2, DEST_TYPEf) == 0x2) { 2246 int vp; 2247 2248 vp = _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2249 DESTINATION); 2250 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2251 KEY_TYPE) == 2252 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI) { 2253 /* MPLS/MiM virtual port unicast */ 2254 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 2255 dest.mpls_id = vp; 2256 dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT; 2257 isGport=1; 2258 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) { 2259 dest.mim_id = vp; 2260 dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT; 2261 isGport=1; 2262 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 2263 dest.mim_id = vp; 2264 dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT; 2265 isGport=1; 2266 } else { 2267 /* L2 entries with Stale VPN */ 2268 dest.gport_type = BCM_GPORT_INVALID; 2269 isGport=0; 2270 } 2271 } else { 2272 /* Subport/WLAN unicast */ 2273 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) { 2274 dest.subport_id = vp; 2275 dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP; 2276 isGport=1; 2277 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) { 2278 dest.wlan_id = vp; 2279 dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT; 2280 isGport=1; 2281 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 2282 dest.vlan_vp_id = vp; 2283 dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT; 2284 isGport=1; 2285 } else { 2286 return BCM_E_INTERNAL; /* Cannot reach here */ 2287 } 2288 } 2289 } else { 2290 #endif /* INCLUDE_L3 */ 2291 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2292 DEST_TYPE) == 0x1) { 2293 int psc = 0; 2294 l2addr->tgid = 2295 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2296 TGID); 2297 bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc); 2298 dest.tgid = l2addr->tgid; 2299 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 2300 2301 l2addr->flags |= BCM_L2_TRUNK_MEMBER; 2302 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2303 REMOTE)) { 2304 l2addr->flags |= BCM_L2_REMOTE_TRUNK; 2305 } 2306 } else { 2307 mod = 2308 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2309 MODULE_ID); 2310 port = 2311 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2312 PORT_NUM); 2313 BCM_IF_ERROR_RETURN 2314 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 2315 mod, port, &mod, &port)); 2316 l2addr->modid = mod; 2317 l2addr->port = port; 2318 dest.port = l2addr->port; 2319 dest.modid = l2addr->modid; 2320 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 2321 } 2322 BCM_IF_ERROR_RETURN 2323 (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 2324 #if defined(INCLUDE_L3) 2325 } 2326 #endif /* INCLUDE_L3 */ 2327 2328 if (isGport) { 2329 BCM_IF_ERROR_RETURN 2330 (_bcm_esw_gport_construct(unit, &dest, &l2addr->port)); 2331 } 2332 2333 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, RPE)) { 2334 l2addr->flags |= BCM_L2_SETPRI; 2335 l2addr->cos_dst = 2336 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, PRI); 2337 } 2338 l2addr->cos_src = l2addr->cos_dst; 2339 2340 if (SOC_CONTROL(unit)->l2x_group_enable) { 2341 l2addr->group = 2342 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2343 CLASS_ID_FULL); 2344 } else { 2345 mb_index = 2346 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2347 MAC_BLOCK_INDEX); 2348 if (mb_index) { 2349 BCM_PBMP_ASSIGN(l2addr->block_bitmap, 2350 _tr3_mbi_entries[unit][mb_index].mb_pbmp); 2351 } 2352 } 2353 2354 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2355 DST_CPU)) { 2356 l2addr->flags |= BCM_L2_COPY_TO_CPU; 2357 } 2358 2359 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2360 DST_DISCARD)) { 2361 l2addr->flags |= BCM_L2_DISCARD_DST; 2362 } 2363 2364 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2365 SRC_DISCARD)) { 2366 l2addr->flags |= BCM_L2_DISCARD_SRC; 2367 } 2368 2369 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2370 SCP)) { 2371 l2addr->flags |= BCM_L2_COS_SRC_PRI; 2372 } 2373 2374 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2375 PENDING)) { 2376 l2addr->flags |= BCM_L2_PENDING; 2377 } 2378 2379 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2380 STATIC_BIT)) { 2381 l2addr->flags |= BCM_L2_STATIC; 2382 } 2383 2384 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2385 HITDA)) { 2386 l2addr->flags |= BCM_L2_DES_HIT; 2387 if (!SOC_CONTROL(unit)->l2x_age_hitsa_only) { 2388 l2addr->flags |= BCM_L2_HIT; 2389 } 2390 } 2391 2392 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2393 HITSA)) { 2394 l2addr->flags |= BCM_L2_SRC_HIT; 2395 l2addr->flags |= BCM_L2_HIT; 2396 } 2397 2398 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2399 LOCAL_SA)) { 2400 l2addr->flags |= BCM_L2_NATIVE; 2401 } 2402 2403 if ((!(l2addr->flags & BCM_L2_STATIC)) || 2404 l2addr->flags & BCM_L2_LEARN_LIMIT ) { 2405 if (!_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2406 LIMIT_COUNTED)) { 2407 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT; 2408 } 2409 } 2410 2411 if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 2412 REMOTE)) { 2413 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL; 2414 } 2415 2416 return BCM_E_NONE; 2417 } 2418 2419 /* 2420 * Function: 2421 * _bcm_tr3_l2api_from_l2hw 2422 * Purpose: 2423 * Convert an EXT_L2_ENTRY_2 to an L2 API data structure 2424 2425 * Parameters: 2426 * unit Unit number 2427 * l2addr (OUT) L2 API data structure 2428 * l2_entries Triumph3 L2 entries structure 2429 * 2430 * Note: 2431 * The l2_entries structure should only have one valid entry. 2432 */ 2433 int 2434 _bcm_tr3_l2api_from_l2hw(int unit, bcm_l2_addr_t *l2addr, 2435 _bcm_tr3_l2_entries_t *l2_entries) 2436 { 2437 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 2438 /* L2_ENTRY_1 */ 2439 return _bcm_tr3_l2_from_l2_1(unit, l2addr, &(l2_entries->l2_entry_1)); 2440 } 2441 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 2442 /* L2_ENTRY_2 */ 2443 return _bcm_tr3_l2_from_l2_2(unit, l2addr, &(l2_entries->l2_entry_2)); 2444 } 2445 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) { 2446 /* EXT_L2_ENTRY_1 */ 2447 return _bcm_tr3_l2_from_ext_l2_1(unit, l2addr, 2448 &(l2_entries->ext_l2_entry_1)); 2449 } 2450 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) { 2451 /* L2_ENTRY_2 */ 2452 return _bcm_tr3_l2_from_ext_l2_2(unit, l2addr, 2453 &(l2_entries->ext_l2_entry_2)); 2454 } 2455 return BCM_E_NOT_FOUND; 2456 } 2457 2458 /* 2459 * Function: 2460 * _bcm_tr3_l2_entries_lookup 2461 * Purpose: 2462 * Serach for an L2 entry specified in an L2 entries structure 2463 2464 * Parameters: 2465 * unit Unit number 2466 * l2_entries (IN) Triumph3 L2 entries structure (search keys) 2467 * l2_entries_lookup (OUT) Triumph3 L2 entries structure (match return) 2468 */ 2469 int 2470 _bcm_tr3_l2_entries_lookup(int unit, _bcm_tr3_l2_entries_t *l2_entries, 2471 _bcm_tr3_l2_entries_t *l2_entries_lookup) 2472 { 2473 int l2_index, rv = BCM_E_NOT_FOUND; 2474 2475 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 2476 rv = soc_mem_generic_lookup(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 2477 _BCM_TR3_L2_MEM_BANKS_ALL, 2478 &(l2_entries->l2_entry_1), 2479 &(l2_entries_lookup->l2_entry_1), &l2_index); 2480 2481 if (BCM_FAILURE(rv) && (BCM_E_NOT_FOUND != rv)) { 2482 return rv; 2483 } else if (BCM_SUCCESS(rv)) { 2484 /* Found in L2_ENTRY_1 */ 2485 l2_entries_lookup->entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1; 2486 } /* else not found */ 2487 } 2488 2489 if ((BCM_E_NOT_FOUND == rv) && 2490 (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2)) { 2491 rv = soc_mem_generic_lookup(unit, L2_ENTRY_2m, MEM_BLOCK_ANY, 2492 _BCM_TR3_L2_MEM_BANKS_ALL, 2493 &(l2_entries->l2_entry_2), 2494 &(l2_entries_lookup->l2_entry_2), 2495 &l2_index); 2496 2497 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 2498 return rv; 2499 } else if (BCM_SUCCESS(rv)) { 2500 /* Found in L2_ENTRY_2 */ 2501 l2_entries_lookup->entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_2; 2502 } /* else not found */ 2503 } 2504 2505 if ((BCM_E_NOT_FOUND == rv) && 2506 (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1)) { 2507 rv = soc_mem_generic_lookup(unit, EXT_L2_ENTRY_1m, MEM_BLOCK_ANY, 2508 _BCM_TR3_L2_MEM_BANKS_ALL, 2509 &(l2_entries->ext_l2_entry_1), 2510 &(l2_entries_lookup->ext_l2_entry_1), 2511 &l2_index); 2512 2513 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 2514 return rv; 2515 } else if (BCM_SUCCESS(rv)) { 2516 /* Found in EXT_L2_ENTRY_1 */ 2517 l2_entries_lookup->entry_flags = 2518 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1; 2519 } /* else not found */ 2520 } 2521 2522 if ((BCM_E_NOT_FOUND == rv) && 2523 (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2)) { 2524 rv = soc_mem_generic_lookup(unit, EXT_L2_ENTRY_2m, MEM_BLOCK_ANY, 2525 _BCM_TR3_L2_MEM_BANKS_ALL, 2526 &(l2_entries->ext_l2_entry_2), 2527 &(l2_entries_lookup->ext_l2_entry_2), 2528 &l2_index); 2529 2530 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 2531 return rv; 2532 } else if (BCM_SUCCESS(rv)) { 2533 /* Found in EXT_L2_ENTRY_2 */ 2534 l2_entries_lookup->entry_flags = 2535 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2; 2536 } /* else not found */ 2537 } 2538 2539 return rv; 2540 } 2541 2542 /* 2543 * Function: 2544 * _bcm_tr3_l2_entries_delete 2545 * Purpose: 2546 * Delete an L2 entry specified in an L2 entries structure 2547 2548 * Parameters: 2549 * unit Unit number 2550 * l2_entries Triumph3 L2 entries structure 2551 * 2552 * Note: 2553 * The l2_entries structure should only have one valid entry. 2554 */ 2555 int 2556 _bcm_tr3_l2_entries_delete(int unit, _bcm_tr3_l2_entries_t *l2_entries) 2557 { 2558 int rv, mb_index = 0; 2559 int l2_index; 2560 soc_control_t *soc = SOC_CONTROL(unit); 2561 SOC_L2_DEL_SYNC_LOCK(soc); 2562 /* The entry changed tables on update, so remove the old entry */ 2563 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 2564 rv = soc_mem_search(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, &l2_index, 2565 (void *)&(l2_entries->l2_entry_1), 2566 (void *)&(l2_entries->l2_entry_1), 0); 2567 if (BCM_SUCCESS(rv)) { 2568 rv = soc_mem_delete_return_old(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 2569 (void *)&(l2_entries->l2_entry_1), 2570 (void *)&(l2_entries->l2_entry_1)); 2571 if (BCM_SUCCESS(rv)) { 2572 rv = soc_tr3_l2x_sync_delete(unit, L2_ENTRY_1m, 2573 (uint32 *)&(l2_entries->l2_entry_1), 2574 l2_index,0); 2575 } 2576 } 2577 } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 2578 rv = soc_mem_search(unit, L2_ENTRY_2m, MEM_BLOCK_ANY, &l2_index, 2579 (void *)&(l2_entries->l2_entry_2), 2580 (void *)&(l2_entries->l2_entry_2), 0); 2581 if (BCM_SUCCESS(rv)) { 2582 rv = soc_mem_delete_return_old(unit, L2_ENTRY_2m, MEM_BLOCK_ANY, 2583 (void *)&(l2_entries->l2_entry_2), 2584 (void *)&(l2_entries->l2_entry_2)); 2585 if (BCM_SUCCESS(rv)) { 2586 rv = soc_tr3_l2x_sync_delete(unit, L2_ENTRY_2m, 2587 (uint32 *)&(l2_entries->l2_entry_2), 2588 l2_index, 0); 2589 } 2590 } 2591 } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) { 2592 rv = soc_mem_search(unit, EXT_L2_ENTRY_1m, MEM_BLOCK_ANY, &l2_index, 2593 (void *)&(l2_entries->ext_l2_entry_1), 2594 (void *)&(l2_entries->ext_l2_entry_1), 0); 2595 if (BCM_SUCCESS(rv)) { 2596 rv = soc_mem_delete_return_old(unit, EXT_L2_ENTRY_1m, 2597 MEM_BLOCK_ANY, 2598 (void *)&(l2_entries->ext_l2_entry_1), 2599 (void *)&(l2_entries->ext_l2_entry_1)); 2600 if (BCM_SUCCESS(rv)) { 2601 rv = soc_tr3_l2x_sync_delete(unit, EXT_L2_ENTRY_1m, 2602 (uint32 *)&(l2_entries->ext_l2_entry_1), 2603 l2_index, 0); 2604 } 2605 } 2606 } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) { 2607 rv = soc_mem_search(unit, EXT_L2_ENTRY_2m, MEM_BLOCK_ANY, &l2_index, 2608 (void *)&(l2_entries->ext_l2_entry_2), 2609 (void *)&(l2_entries->ext_l2_entry_2), 0); 2610 if (BCM_SUCCESS(rv)) { 2611 rv = soc_mem_delete_return_old(unit, EXT_L2_ENTRY_2m, 2612 MEM_BLOCK_ANY, 2613 (void *)&(l2_entries->ext_l2_entry_2), 2614 (void *)&(l2_entries->ext_l2_entry_2)); 2615 if (BCM_SUCCESS(rv)) { 2616 rv = soc_tr3_l2x_sync_delete(unit, EXT_L2_ENTRY_2m, 2617 (uint32 *)&(l2_entries->ext_l2_entry_2), 2618 l2_index, 0); 2619 } 2620 } 2621 } else { 2622 SOC_L2_DEL_SYNC_UNLOCK(soc); 2623 /* This should have been caught earlier. */ 2624 return BCM_E_INTERNAL; 2625 } 2626 SOC_L2_DEL_SYNC_UNLOCK(soc); 2627 if (BCM_SUCCESS(rv)) { 2628 /* Delete the MAC_BLOCK reference, if appropriate */ 2629 if (!SOC_L2X_GROUP_ENABLE_GET(unit)) { 2630 mb_index = _bcm_tr3_l2hw_entries_field32_get(unit, 2631 l2_entries, 2632 _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX); 2633 _bcm_tr3_mac_block_delete(unit, mb_index); 2634 } 2635 } 2636 2637 return rv; 2638 } 2639 2640 #ifdef BCM_KATANA2_SUPPORT 2641 STATIC int 2642 _kt2_l2_delete_all_by_hw(int unit, int vfi, uint32 replace_flags) 2643 { 2644 int rv = BCM_E_NONE; 2645 sal_usecs_t start_time; 2646 int diff_time; 2647 uint32 rval; 2648 int field_len; 2649 l2x_entry_t l2x_entry; 2650 uint32 l2_bulk_match_mask[SOC_MAX_MEM_FIELD_WORDS] = {0}; 2651 uint32 l2_bulk_match_data[SOC_MAX_MEM_FIELD_WORDS] = {0}; 2652 bcm_mac_t mac_data; 2653 uint8 static_bit_val = 0; 2654 2655 sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 2656 2657 soc_mem_field32_set(unit, L2Xm, &l2x_entry, VALIDf, 1); 2658 2659 field_len = soc_mem_field_length(unit, L2Xm, KEY_TYPEf); 2660 soc_mem_field32_set(unit, L2Xm, &l2x_entry, KEY_TYPEf, 2661 (1 << field_len) - 1); 2662 2663 /* Match for STATIC_BIT in the Mask */ 2664 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 2665 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 2666 soc_mem_field32_set(unit, L2Xm, &l2x_entry, STATIC_BITf, 1); 2667 } 2668 2669 /* Match for Unicast or Multicast Mac in the Mask */ 2670 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 2671 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 2672 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 2673 2674 mac_data[0] = 0x01; 2675 if (vfi <= 0) { 2676 soc_mem_mac_addr_set(unit, L2Xm, &l2x_entry, L2__MAC_ADDRf, 2677 mac_data); 2678 } else { 2679 soc_mem_mac_addr_set(unit, L2Xm, &l2x_entry, VFI__MAC_ADDRf, 2680 mac_data); 2681 } 2682 } 2683 2684 sal_memcpy(l2_bulk_match_mask, &l2x_entry, 2685 sizeof(l2_bulk_match_mask_entry_t)); 2686 _BCM_ALL_L2X_MEM_LOCK(unit); 2687 /*Set match mask*/ 2688 rv = WRITE_L2_BULK_MATCH_MASKm(unit, MEM_BLOCK_ALL, 0, l2_bulk_match_mask); 2689 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2690 2691 /* Ensure that STATIC_BIT is set in data as per flag */ 2692 static_bit_val = 0; 2693 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 2694 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 2695 2696 if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) { 2697 static_bit_val = 1; 2698 } 2699 soc_mem_field32_set(unit, L2Xm, &l2x_entry, STATIC_BITf, 2700 static_bit_val); 2701 } 2702 2703 /* Ensure that Bit 40 is set in data as per flag */ 2704 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 2705 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 2706 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 2707 2708 if (replace_flags & BCM_L2_REPLACE_MATCH_MC) { 2709 mac_data[0] = 0x01; 2710 } 2711 if (vfi <= 0) { 2712 soc_mem_mac_addr_set(unit, L2Xm, &l2x_entry, L2__MAC_ADDRf, 2713 mac_data); 2714 } else { 2715 soc_mem_mac_addr_set(unit, L2Xm, &l2x_entry, VFI__MAC_ADDRf, 2716 mac_data); 2717 } 2718 } 2719 2720 if (vfi <= 0) { 2721 soc_mem_field32_set(unit, L2Xm, &l2x_entry, KEY_TYPEf, 2722 KT2_L2_HASH_KEY_TYPE_BRIDGE); 2723 } 2724 2725 sal_memcpy(l2_bulk_match_data, &l2x_entry, 2726 sizeof(l2_bulk_match_data_entry_t)); 2727 /*Set match data*/ 2728 rv = WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0, l2_bulk_match_data); 2729 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2730 2731 rv = READ_L2_BULK_CONTROLr(unit, &rval); 2732 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2733 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0); 2734 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 2735 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 2736 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2737 2738 /* Delete entries for KT2_L2_HASH_KEY_TYPE_BRIDGE */ 2739 if (vfi <= 0) { 2740 start_time = sal_time_usecs(); 2741 diff_time = 0; 2742 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 2743 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 2744 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2745 LOG_VERBOSE(BSL_LS_SOC_COMMON,(BSL_META_U(unit, 2746 "Time taken for bulk del L2_ENTRY_L2_BRIDGE: %d\n"), 2747 diff_time)); 2748 } else { 2749 /* Delete entries for KT2_L2_HASH_KEY_TYPE_VFI */ 2750 soc_mem_field32_set(unit, L2Xm, &l2x_entry, KEY_TYPEf, 2751 KT2_L2_HASH_KEY_TYPE_VFI); 2752 2753 sal_memcpy(l2_bulk_match_data, &l2x_entry, 2754 sizeof(l2_bulk_match_data_entry_t)); 2755 /*Set match data*/ 2756 rv = WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0, 2757 l2_bulk_match_data); 2758 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2759 2760 start_time = sal_time_usecs(); 2761 diff_time = 0; 2762 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 2763 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 2764 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2765 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 2766 "Time taken for bulk del L2_ENTRY_L2_VFI: %d\n"), 2767 diff_time)); 2768 } 2769 /* Clear parity status on L2 bulk operation */ 2770 BCM_IF_ERROR_RETURN 2771 (soc_reg_field32_modify(unit, L2_BULK_CONTROLr, 2772 REG_PORT_ANY, STARTf, 0)); 2773 BCM_IF_ERROR_RETURN 2774 (soc_reg_field32_modify(unit, L2_BULK_CONTROLr, 2775 REG_PORT_ANY, COMPLETEf, 0)); 2776 _BCM_ALL_L2X_MEM_UNLOCK(unit); 2777 return rv; 2778 } 2779 #endif /* BCM_KATANA2_SUPPORT */ 2780 2781 STATIC int 2782 _tr3_l2_delete_all_by_hw(int unit, int vfi, uint32 replace_flags) 2783 { 2784 int rv = BCM_E_NONE; 2785 sal_usecs_t start_time; 2786 int diff_time; 2787 uint32 rval; 2788 int field_len; 2789 l2_bulk_entry_t l2_bulk; 2790 l2_entry_1_entry_t l2_entry_1; 2791 l2_entry_2_entry_t l2_entry_2; 2792 ext_l2_entry_1_entry_t ext_l2_entry_1; 2793 ext_l2_entry_2_entry_t ext_l2_entry_2; 2794 int ext_l2; 2795 bcm_mac_t mac_data; 2796 uint8 static_bit_val = 0; 2797 2798 sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1)); 2799 sal_memset(&l2_entry_2, 0, sizeof(l2_entry_2)); 2800 2801 /* First work on L2_ENTRY_1 */ 2802 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, VALIDf, 1); 2803 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 1); 2804 2805 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf); 2806 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 2807 (1 << field_len) - 1); 2808 2809 /* Match for STATIC_BIT in the Mask */ 2810 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 2811 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 2812 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, STATIC_BITf, 1); 2813 } 2814 2815 /* Match for Unicast/Multicast Mac in the Mask */ 2816 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 2817 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 2818 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 2819 2820 mac_data[0] = 0x01; 2821 if (vfi <= 0) { 2822 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, L2__MAC_ADDRf, 2823 mac_data); 2824 } else { 2825 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, VFI__MAC_ADDRf, 2826 mac_data); 2827 } 2828 } 2829 2830 sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1)); 2831 _BCM_ALL_L2X_MEM_LOCK(unit); 2832 /* Set match mask */ 2833 /* Index 1 points to L2_BULK_MATCH_MASK address in L2_BULK table */ 2834 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk); 2835 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2836 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 0); 2837 2838 /* Ensure that STATIC_BIT is set as per flag in data */ 2839 static_bit_val = 0; 2840 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 2841 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 2842 2843 if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) { 2844 static_bit_val = 1; 2845 } 2846 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, STATIC_BITf, 2847 static_bit_val); 2848 } 2849 2850 /* Ensure that Bit 40 is set as per flag in data */ 2851 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 2852 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 2853 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 2854 2855 if (replace_flags & BCM_L2_REPLACE_MATCH_MC) { 2856 mac_data[0]=0x01; 2857 } 2858 if (vfi <= 0) { 2859 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, L2__MAC_ADDRf, 2860 mac_data); 2861 } else { 2862 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, VFI__MAC_ADDRf, 2863 mac_data); 2864 } 2865 } 2866 2867 if (vfi <= 0) { 2868 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 2869 SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE); 2870 } 2871 sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1)); 2872 /* Set match data */ 2873 /* Index 0 points to L2_BULK_MATCH_DATA address in L2_BULK table */ 2874 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk); 2875 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2876 rv = READ_L2_BULK_CONTROLr(unit, &rval); 2877 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2878 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0); 2879 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 2880 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 2881 _SOC_TR3_L2_BULK_BURST_MAX); 2882 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 2883 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 2884 soc_mem_index_count(unit, L2_ENTRY_1m)); 2885 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0); 2886 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 2887 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2888 if (vfi <= 0) { 2889 start_time = sal_time_usecs(); 2890 diff_time = 0; 2891 /* Delete entries for SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE */ 2892 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 2893 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 2894 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2895 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2896 (BSL_META_U(unit, 2897 "Time taken for bulk del L2_ENTRY_1_L2_BRIDGE: %d\n"), 2898 diff_time)); 2899 } else { 2900 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 2901 SOC_MEM_KEY_L2_ENTRY_1_L2_VFI); 2902 sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1)); 2903 /* Set match data */ 2904 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk); 2905 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2906 start_time = sal_time_usecs(); 2907 diff_time = 0; 2908 /* Delete entries for SOC_MEM_KEY_L2_ENTRY_1_L2_VFI */ 2909 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 2910 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 2911 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2912 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2913 (BSL_META_U(unit, 2914 "Time taken for bulk del L2_ENTRY_1_L2_VFI: %d\n"), 2915 diff_time)); 2916 } 2917 /* Then work on L2_ENTRY_2 */ 2918 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_0f, 1); 2919 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_1f, 1); 2920 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_0f, 1); 2921 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_1f, 1); 2922 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, KEY_TYPE_0f); 2923 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f, 2924 (1 << field_len) - 1); 2925 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f, 2926 (1 << field_len) - 1); 2927 2928 /* Match for STATIC_BIT in the Mask */ 2929 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 2930 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 2931 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_0f, 1); 2932 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_1f, 1); 2933 } 2934 2935 /* Match for Unicast/Multicast Mac in the Mask */ 2936 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 2937 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 2938 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 2939 2940 mac_data[0] = 0x01; 2941 if (vfi <= 0) { 2942 soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, L2__MAC_ADDRf, 2943 mac_data); 2944 } else { 2945 soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, VFI__MAC_ADDRf, 2946 mac_data); 2947 } 2948 } 2949 2950 sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2)); 2951 /* Set match mask */ 2952 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk); 2953 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2954 if (vfi <= 0) { 2955 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f, 2956 SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE); 2957 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f, 2958 SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE); 2959 } 2960 2961 /* Ensure that STATIC_BIT is set as per flag in data */ 2962 static_bit_val = 0; 2963 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 2964 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 2965 2966 if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) { 2967 static_bit_val = 1; 2968 } 2969 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_0f, 2970 static_bit_val); 2971 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_1f, 2972 static_bit_val); 2973 } 2974 2975 /* Ensure that Bit 40 is set as per flag in data */ 2976 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 2977 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 2978 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 2979 2980 if (replace_flags & BCM_L2_REPLACE_MATCH_MC) { 2981 mac_data[0]=0x01; 2982 } 2983 if (vfi <= 0) { 2984 soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, L2__MAC_ADDRf, 2985 mac_data); 2986 } else { 2987 soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, VFI__MAC_ADDRf, 2988 mac_data); 2989 } 2990 } 2991 2992 sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2)); 2993 /* Set match data */ 2994 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk); 2995 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2996 rv = READ_L2_BULK_CONTROLr(unit, &rval); 2997 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 2998 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1); 2999 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 3000 soc_mem_index_count(unit, L2_ENTRY_2m)); 3001 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 3002 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3003 if (vfi <= 0) { 3004 /* Set the Key type match */ 3005 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval)); 3006 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 3007 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE); 3008 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval)); 3009 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval)); 3010 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 3011 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE); 3012 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval)); 3013 3014 start_time = sal_time_usecs(); 3015 diff_time = 0; 3016 /* Delete entries for SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE */ 3017 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3018 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 3019 3020 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3021 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3022 (BSL_META_U(unit, 3023 "Time taken for bulk del L2_ENTRY_2_L2_BRIDGE: %d\n"), 3024 diff_time)); 3025 } else { 3026 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f, 3027 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI); 3028 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f, 3029 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI); 3030 sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2)); 3031 /* Set match data */ 3032 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk); 3033 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3034 /* Set the Key type match */ 3035 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval)); 3036 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 3037 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_2_L2_VFI); 3038 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval)); 3039 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval)); 3040 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 3041 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_2_L2_VFI); 3042 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval)); 3043 3044 start_time = sal_time_usecs(); 3045 diff_time = 0; 3046 /* Delete entries for SOC_MEM_KEY_L2_ENTRY_2_L2_VFI */ 3047 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3048 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 3049 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3050 (BSL_META_U(unit, 3051 "Time taken for bulk del L2_ENTRY_2_L2_VFI: %d\n"), 3052 diff_time)); 3053 } 3054 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3055 3056 if (!soc_feature(unit, soc_feature_esm_support)) { 3057 _BCM_ALL_L2X_MEM_UNLOCK(unit); 3058 return rv; 3059 } 3060 ext_l2 = soc_property_get(unit, "EXT_L2_BULK_CLEAR", 0); 3061 if (ext_l2 == 2) { 3062 goto _ext_l2_2_bulk; 3063 } 3064 /* First work on EXT_L2_ENTRY_1 */ 3065 sal_memset(&ext_l2_entry_1, 0, sizeof(ext_l2_entry_1)); 3066 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, FREEf, 1); 3067 if (vfi >= 0) { 3068 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, KEY_TYPEf); 3069 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 3070 (1 << field_len) - 1); 3071 } 3072 3073 /* Match for STATIC_BIT in the Mask */ 3074 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 3075 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 3076 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, 3077 STATIC_BITf, 1); 3078 } 3079 3080 /* Match for Unicast/Multicast Mac in the Mask */ 3081 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 3082 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 3083 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 3084 mac_data[0] = 0x01; 3085 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, MAC_ADDRf, 3086 mac_data); 3087 } 3088 3089 sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1)); 3090 /* Set match mask */ 3091 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk); 3092 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3093 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 3094 if (vfi <= 0) { 3095 sal_memset(&ext_l2_entry_1, 0, sizeof(ext_l2_entry_1)); 3096 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 3097 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE); 3098 3099 /* Ensure that STATIC_BIT is set as per flag in data */ 3100 static_bit_val = 0; 3101 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 3102 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 3103 3104 if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) { 3105 static_bit_val = 1; 3106 } 3107 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, 3108 STATIC_BITf, static_bit_val); 3109 } 3110 3111 /* Ensure that Bit 40 is set as per flag in data */ 3112 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 3113 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 3114 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 3115 3116 if (replace_flags & BCM_L2_REPLACE_MATCH_MC) { 3117 mac_data[0]=0x01; 3118 } 3119 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, MAC_ADDRf, 3120 mac_data); 3121 } 3122 sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1)); 3123 } 3124 /* Set match data */ 3125 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk); 3126 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3127 rv = READ_L2_BULK_CONTROLr(unit, &rval); 3128 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3129 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 3130 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 3131 _SOC_TR3_L2_BULK_BURST_MAX); 3132 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 3133 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 3134 SOC_MEM_TR3_EXT_L2_MAX_ENTRIES); 3135 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1); 3136 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 3137 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3138 if (vfi <= 0) { 3139 /* Set the Key type match */ 3140 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval)); 3141 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 3142 KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE); 3143 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval)); 3144 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval)); 3145 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 3146 KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE); 3147 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval)); 3148 3149 start_time = sal_time_usecs(); 3150 diff_time = 0; 3151 /* Delete entries */ 3152 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3153 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 3154 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3155 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3156 (BSL_META_U(unit, 3157 "Time taken for bulk del EXT_L2_ENTRY_1: %d\n"), 3158 diff_time)); 3159 } else { 3160 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 3161 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI); 3162 3163 /* Ensure that STATIC_BIT is set as per flag in data */ 3164 static_bit_val = 0; 3165 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 3166 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 3167 3168 if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) { 3169 static_bit_val = 1; 3170 } 3171 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, 3172 STATIC_BITf, static_bit_val); 3173 } 3174 3175 /* Ensure that Bit 40 is set as per flag in data */ 3176 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 3177 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 3178 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 3179 3180 if (replace_flags & BCM_L2_REPLACE_MATCH_MC) { 3181 mac_data[0]=0x01; 3182 } 3183 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, MAC_ADDRf, 3184 mac_data); 3185 } 3186 sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1)); 3187 /* Set match data */ 3188 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk); 3189 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3190 /* Set the Key type match */ 3191 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval)); 3192 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 3193 KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI); 3194 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval)); 3195 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval)); 3196 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 3197 KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI); 3198 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval)); 3199 3200 start_time = sal_time_usecs(); 3201 diff_time = 0; 3202 /* Delete entries */ 3203 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3204 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 3205 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3206 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3207 (BSL_META_U(unit, 3208 "Time taken for bulk del EXT_L2_ENTRY_1: %d\n"), 3209 diff_time)); 3210 } 3211 rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0); 3212 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3213 /* Issue dummy op */ 3214 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0); 3215 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 3216 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1); 3217 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 3218 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3219 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3220 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3221 rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0); 3222 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3223 3224 _ext_l2_2_bulk: 3225 if (ext_l2 == 1) { 3226 _BCM_ALL_L2X_MEM_UNLOCK(unit); 3227 return rv; 3228 } 3229 /* Then work on EXT_L2_ENTRY_2 */ 3230 sal_memset(&ext_l2_entry_2, 0, sizeof(ext_l2_entry_2)); 3231 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_2, FREEf, 1); 3232 if (vfi >= 0) { 3233 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, KEY_TYPEf); 3234 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 3235 (1 << field_len) - 1); 3236 } 3237 3238 /* Match for STATIC_BIT in the Mask */ 3239 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 3240 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 3241 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, 3242 STATIC_BITf, 1); 3243 } 3244 3245 /* Match for Unicast/Multicast Mac in the Mask */ 3246 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 3247 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 3248 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 3249 mac_data[0] = 0x01; 3250 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, MAC_ADDRf, 3251 mac_data); 3252 } 3253 3254 sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2)); 3255 /* Set match mask */ 3256 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk); 3257 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 3258 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3259 if (vfi <= 0) { 3260 sal_memset(&ext_l2_entry_2, 0, sizeof(ext_l2_entry_2)); 3261 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 3262 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE); 3263 3264 /* Ensure that STATIC_BIT is set as per flag in data */ 3265 static_bit_val = 0; 3266 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 3267 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 3268 3269 if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) { 3270 static_bit_val = 1; 3271 } 3272 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, 3273 STATIC_BITf, static_bit_val); 3274 } 3275 3276 /* Ensure that Bit 40 is set as per flag in data */ 3277 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 3278 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 3279 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 3280 3281 if (replace_flags & BCM_L2_REPLACE_MATCH_MC) { 3282 mac_data[0]=0x01; 3283 } 3284 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, MAC_ADDRf, 3285 mac_data); 3286 } 3287 sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2)); 3288 } 3289 /* Set match data */ 3290 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk); 3291 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3292 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 3293 rv = READ_L2_BULK_CONTROLr(unit, &rval); 3294 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3295 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 3296 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 3297 _SOC_TR3_L2_BULK_BURST_MAX); 3298 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1); 3299 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 3300 SOC_MEM_TR3_EXT_L2_MAX_ENTRIES); 3301 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1); 3302 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 3303 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3304 if (vfi <= 0) { 3305 /* Set the Key type match */ 3306 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval)); 3307 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 3308 KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE); 3309 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval)); 3310 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval)); 3311 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 3312 KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE); 3313 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval)); 3314 3315 start_time = sal_time_usecs(); 3316 diff_time = 0; 3317 /* Delete entries */ 3318 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3319 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3320 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 3321 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3322 (BSL_META_U(unit, 3323 "Time taken for bulk del EXT_L2_ENTRY_2: %d\n"), 3324 diff_time)); 3325 } else { 3326 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 3327 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI); 3328 3329 /* Ensure that STATIC_BIT is set as per flag in data */ 3330 static_bit_val = 0; 3331 if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) || 3332 (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) { 3333 3334 if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) { 3335 static_bit_val = 1; 3336 } 3337 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, 3338 STATIC_BITf, static_bit_val); 3339 } 3340 3341 /* Ensure that Bit 40 is set as per flag in data */ 3342 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 3343 if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) || 3344 (replace_flags & BCM_L2_REPLACE_MATCH_MC)) { 3345 3346 if (replace_flags & BCM_L2_REPLACE_MATCH_MC) { 3347 mac_data[0]=0x01; 3348 } 3349 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, MAC_ADDRf, 3350 mac_data); 3351 } 3352 sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2)); 3353 /* Set match data */ 3354 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk); 3355 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3356 /* Set the Key type match */ 3357 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval)); 3358 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 3359 KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI); 3360 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval)); 3361 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval)); 3362 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 3363 KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI); 3364 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval)); 3365 3366 start_time = sal_time_usecs(); 3367 diff_time = 0; 3368 /* Delete entries */ 3369 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3370 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 3371 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3372 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3373 (BSL_META_U(unit, 3374 "Time taken for bulk del EXT_L2_ENTRY_2: %d\n"), 3375 diff_time)); 3376 } 3377 rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0); 3378 /* Issue dummy op */ 3379 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0); 3380 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 3381 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1); 3382 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 3383 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3384 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3385 _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 3386 rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0); 3387 _BCM_ALL_L2X_MEM_UNLOCK(unit); 3388 3389 return rv; 3390 } 3391 3392 /* 3393 * Function: 3394 * _tr3_l2x_delete_all 3395 * Purpose: 3396 * Clear the ISM L2 table by invalidating entries. 3397 * Parameters: 3398 * unit - StrataSwitch unit # 3399 * Returns: 3400 * SOC_E_XXX 3401 */ 3402 3403 STATIC int 3404 _tr3_l2x_delete_all(int unit) 3405 { 3406 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 3407 int chunksize, chnk_end; 3408 int index_min, wide_entry_half, clear_entry; 3409 int rv = BCM_E_NONE; 3410 int *buffer = NULL; 3411 int mem_size; 3412 int modified; 3413 l2_entry_1_entry_t *l2_entry_1; 3414 soc_memacc_t *memacc_valid, *memacc_key_type; 3415 uint32 key_type; 3416 3417 if(soc_property_get(unit, spn_MEM_CLEAR_HW_ACCELERATION, 1) && 3418 !SAL_BOOT_SIMULATION) { 3419 return _tr3_l2_delete_all_by_hw(unit, -1, 0); 3420 } 3421 3422 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 3423 L2_MEM_CHUNKS_DEFAULT); 3424 3425 index_min = soc_mem_index_min(unit, L2_ENTRY_1m); 3426 mem_idx_max = soc_mem_index_max(unit, L2_ENTRY_1m); /* Current size */ 3427 mem_size = chunksize * sizeof(l2_entry_1_entry_t); 3428 3429 buffer = soc_cm_salloc(unit, mem_size, "L2_ENTRY_1_delete"); 3430 if (NULL == buffer) { 3431 return SOC_E_MEMORY; 3432 } 3433 3434 memacc_valid = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 3435 _BCM_TR3_L2_MEMACC_VALID); 3436 memacc_key_type = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 3437 _BCM_TR3_L2_MEMACC_KEY_TYPE); 3438 3439 soc_mem_lock(unit, L2_ENTRY_1m); 3440 for (chnk_idx = index_min; chnk_idx <= mem_idx_max; chnk_idx += chunksize) { 3441 chnk_idx_max = 3442 ((chnk_idx + chunksize) < mem_idx_max) ? 3443 (chnk_idx + chunksize - 1) : mem_idx_max; 3444 rv = soc_mem_read_range(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 3445 chnk_idx, chnk_idx_max, buffer); 3446 if (SOC_FAILURE(rv)) { 3447 break; 3448 } 3449 chnk_end = (chnk_idx_max - chnk_idx); 3450 modified = FALSE; 3451 wide_entry_half = FALSE; 3452 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 3453 l2_entry_1 = 3454 soc_mem_table_idx_to_pointer(unit, L2_ENTRY_1m, 3455 l2_entry_1_entry_t *, 3456 buffer, ent_idx); 3457 if (wide_entry_half) { 3458 /* Clear the second half of a wide entry */ 3459 sal_memcpy(l2_entry_1, 3460 soc_mem_entry_null(unit, L2_ENTRY_1m), 3461 sizeof(l2_entry_1_entry_t)); 3462 wide_entry_half = FALSE; 3463 continue; 3464 } 3465 3466 if (!soc_memacc_field32_get(memacc_valid, l2_entry_1)) { 3467 continue; 3468 } 3469 key_type = soc_memacc_field32_get(memacc_key_type, l2_entry_1); 3470 3471 3472 clear_entry = FALSE; 3473 if ((SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE == key_type) || 3474 (SOC_MEM_KEY_L2_ENTRY_1_L2_VFI == key_type)) { 3475 clear_entry = TRUE; 3476 } 3477 if ((SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE == key_type) || 3478 (SOC_MEM_KEY_L2_ENTRY_2_L2_VFI == key_type)) { 3479 clear_entry = TRUE; 3480 wide_entry_half = TRUE; 3481 } 3482 if (clear_entry) { 3483 sal_memcpy(l2_entry_1, 3484 soc_mem_entry_null(unit, L2_ENTRY_1m), 3485 sizeof(l2_entry_1_entry_t)); 3486 modified = TRUE; 3487 } 3488 } 3489 if (!modified) { 3490 continue; 3491 } 3492 rv = soc_mem_write_range(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, 3493 chnk_idx, chnk_idx_max, buffer); 3494 if (SOC_FAILURE(rv)) { 3495 break; 3496 } 3497 } 3498 soc_cm_sfree(unit, buffer); 3499 3500 soc_mem_unlock(unit, L2_ENTRY_1m); 3501 3502 /* External memories don't need key_type checks, so use 3503 * standard memory clear operation. */ 3504 if (soc_feature(unit, soc_feature_esm_support)) { 3505 if (BCM_SUCCESS(rv)) { 3506 rv = soc_mem_clear(unit, EXT_L2_ENTRY_1m, COPYNO_ALL, FALSE); 3507 } 3508 if (BCM_SUCCESS(rv)) { 3509 rv = soc_mem_clear(unit, EXT_L2_ENTRY_2m, COPYNO_ALL, FALSE); 3510 } 3511 } 3512 3513 if (SOC_CONTROL(unit)->arlShadow != NULL) { 3514 sal_mutex_take(SOC_CONTROL(unit)->arlShadowMutex, sal_mutex_FOREVER); 3515 (void) shr_avl_delete_all(SOC_CONTROL(unit)->arlShadow); 3516 sal_mutex_give(SOC_CONTROL(unit)->arlShadowMutex); 3517 } 3518 3519 return rv; 3520 } 3521 3522 /* 3523 * Function: 3524 * _bcm_tr3_l2_learn_limit_system_set 3525 * Purpose: 3526 * Set MAC learn limit for a system 3527 * Parameters: 3528 * unit - BCM unit number 3529 * flags - Action bitmask 3530 * limit - System limit of MAC addresses to learn 3531 * Negative limit disables the check 3532 * Returns: 3533 * BCM_E_XXX 3534 */ 3535 STATIC int 3536 _bcm_tr3_l2_learn_limit_system_set(int unit, uint32 flags, int limit) 3537 { 3538 uint32 rval, orval, regval; 3539 int tocpu, drop, enable; 3540 3541 if (limit < 0) { 3542 tocpu = 0; 3543 drop = 0; 3544 limit = BCM_MAC_LIMIT_MAX(unit); 3545 enable = 0; 3546 } else { 3547 tocpu = flags & BCM_L2_LEARN_LIMIT_ACTION_CPU ? 1 : 0; 3548 drop = flags & BCM_L2_LEARN_LIMIT_ACTION_DROP ? 1 : 0; 3549 enable = 1; 3550 } 3551 3552 /* Starting from Triumph this flag is not supported */ 3553 if (flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) { 3554 return BCM_E_PARAM; 3555 } 3556 3557 BCM_IF_ERROR_RETURN(READ_RSEL1_MISC_CONTROLr(unit, ®val)); 3558 soc_reg_field_set(unit, RSEL1_MISC_CONTROLr, ®val, 3559 MAC_LIMIT_ENABLEf, enable); 3560 BCM_IF_ERROR_RETURN(WRITE_RSEL1_MISC_CONTROLr(unit, regval)); 3561 3562 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval)); 3563 orval = rval; 3564 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 3565 SYS_OVER_LIMIT_TOCPUf, tocpu); 3566 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 3567 SYS_OVER_LIMIT_DROPf, drop); 3568 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, SYS_LIMITf, limit); 3569 /* 3570 * Enable/Disable MAC limiting for internal L2 and also 3571 * for external L2 if it is available. 3572 */ 3573 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 3574 ENABLE_INTERNAL_L2_ENTRYf, enable); 3575 if (soc_feature(unit, soc_feature_esm_support)) { 3576 if ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_1m) && 3577 (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_1m))) || 3578 ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_2m) && 3579 (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_2m))))) { 3580 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 3581 ENABLE_EXTERNAL_L2_ENTRYf, enable); 3582 } 3583 } 3584 if (rval != orval) { 3585 BCM_IF_ERROR_RETURN(WRITE_SYS_MAC_LIMIT_CONTROLr(unit, rval)); 3586 } 3587 3588 return BCM_E_NONE; 3589 } 3590 3591 /* 3592 * Function: 3593 * _bcm_tr3_l2_learn_limit_init 3594 * Purpose: 3595 * Init the system to support MAC learn limit 3596 * Parameters: 3597 * unit - BCM unit number 3598 * Returns: 3599 * BCM_E_XXX 3600 */ 3601 STATIC int 3602 _bcm_tr3_l2_learn_limit_init(int unit) 3603 { 3604 int32 maxInitVal; 3605 int rv, idx, idx_min, idx_max; 3606 uint8 *port_or_trunk_mac_limit_buf = NULL; 3607 uint8 *vlan_or_vfi_mac_limit_buf = NULL; 3608 vlan_or_vfi_mac_limit_entry_t *vlan_or_vfi_mac_limit_entry = NULL; 3609 port_or_trunk_mac_limit_entry_t *port_or_trunk_mac_limit_entry = NULL; 3610 maxInitVal = BCM_MAC_LIMIT_MAX(unit); 3611 3612 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_learn_limit_system_set(unit, 0, -1)); 3613 BCM_IF_ERROR_RETURN 3614 (soc_mem_clear(unit, PORT_OR_TRUNK_MAC_LIMITm, COPYNO_ALL, FALSE)); 3615 BCM_IF_ERROR_RETURN 3616 (soc_mem_clear(unit, VLAN_OR_VFI_MAC_LIMITm, COPYNO_ALL, FALSE)); 3617 3618 /* PORT_OR_TRUNK_MAC_LIMIT table*/ 3619 port_or_trunk_mac_limit_buf = soc_cm_salloc(unit, 3620 SOC_MEM_TABLE_BYTES(unit,PORT_OR_TRUNK_MAC_LIMITm), 3621 "port_or_trunk"); 3622 if (port_or_trunk_mac_limit_buf == NULL) { 3623 return BCM_E_MEMORY; 3624 } 3625 3626 idx_min = soc_mem_index_min(unit, PORT_OR_TRUNK_MAC_LIMITm); 3627 idx_max = soc_mem_index_max(unit, PORT_OR_TRUNK_MAC_LIMITm); 3628 rv = soc_mem_read_range(unit, PORT_OR_TRUNK_MAC_LIMITm, 3629 MEM_BLOCK_ANY, idx_min, idx_max, 3630 port_or_trunk_mac_limit_buf); 3631 3632 if (BCM_FAILURE(rv)) { 3633 goto cleanup; 3634 } 3635 3636 for(idx = idx_min; idx<= idx_max; idx++) { 3637 port_or_trunk_mac_limit_entry = 3638 soc_mem_table_idx_to_pointer(unit, PORT_OR_TRUNK_MAC_LIMITm, 3639 port_or_trunk_mac_limit_entry_t *, 3640 port_or_trunk_mac_limit_buf, 3641 idx); 3642 soc_PORT_OR_TRUNK_MAC_LIMITm_field32_set(unit, 3643 port_or_trunk_mac_limit_entry, 3644 LIMITf, maxInitVal); 3645 } 3646 rv = soc_mem_write_range(unit, PORT_OR_TRUNK_MAC_LIMITm, MEM_BLOCK_ALL, 3647 idx_min, idx_max, port_or_trunk_mac_limit_buf); 3648 if (BCM_FAILURE(rv)) { 3649 goto cleanup; 3650 } 3651 3652 /* VLAN_OR_VFI_MAC_LIMIT table*/ 3653 vlan_or_vfi_mac_limit_buf = soc_cm_salloc(unit, 3654 SOC_MEM_TABLE_BYTES(unit, VLAN_OR_VFI_MAC_LIMITm), 3655 "vlan_or_vfi"); 3656 if (vlan_or_vfi_mac_limit_buf == NULL) { 3657 return BCM_E_MEMORY; 3658 } 3659 3660 idx_min = soc_mem_index_min(unit, VLAN_OR_VFI_MAC_LIMITm); 3661 idx_max = soc_mem_index_max(unit, VLAN_OR_VFI_MAC_LIMITm); 3662 rv = soc_mem_read_range(unit, VLAN_OR_VFI_MAC_LIMITm, 3663 MEM_BLOCK_ANY, idx_min, idx_max, 3664 vlan_or_vfi_mac_limit_buf); 3665 3666 if (BCM_FAILURE(rv)) { 3667 goto cleanup; 3668 } 3669 3670 for(idx = idx_min; idx<= idx_max; idx++) { 3671 vlan_or_vfi_mac_limit_entry = 3672 soc_mem_table_idx_to_pointer(unit, VLAN_OR_VFI_MAC_LIMITm, 3673 vlan_or_vfi_mac_limit_entry_t *, 3674 vlan_or_vfi_mac_limit_buf, 3675 idx); 3676 soc_PORT_OR_TRUNK_MAC_LIMITm_field32_set(unit, 3677 vlan_or_vfi_mac_limit_entry, 3678 LIMITf, maxInitVal); 3679 } 3680 rv = soc_mem_write_range(unit, VLAN_OR_VFI_MAC_LIMITm, MEM_BLOCK_ALL, 3681 idx_min, idx_max, vlan_or_vfi_mac_limit_buf); 3682 if (BCM_FAILURE(rv)) { 3683 goto cleanup; 3684 } 3685 3686 3687 cleanup: 3688 3689 if (port_or_trunk_mac_limit_buf) { 3690 soc_cm_sfree(unit, port_or_trunk_mac_limit_buf); 3691 } 3692 3693 if (vlan_or_vfi_mac_limit_buf) { 3694 soc_cm_sfree(unit, vlan_or_vfi_mac_limit_buf); 3695 } 3696 3697 return rv; 3698 } 3699 3700 /* 3701 * Function: 3702 * _bcm_tr3_l2_hash_dynamic_replace 3703 * Purpose: 3704 * Given an L2 entries structure, search for dynamic entries to 3705 * eject in favor of the new entry. 3706 * Parameters: 3707 * unit - (IN) Unit number. 3708 * l2_entries (IN/OUT) Triumph3 L2 entries structure 3709 * Returns: 3710 * BCM_E_xxx 3711 * Notes: 3712 * In case new entry is double wide,we check for any dynamic narrow entries 3713 * which can be deleted or free, and then do an insert. del_low_idx and 3714 * del_high_idx are set if the entry is not free and has to be deleted 3715 * before insert. 3716 */ 3717 int 3718 _bcm_tr3_l2_hash_dynamic_replace(int unit, _bcm_tr3_l2_entries_t *l2_entries) 3719 { 3720 uint32 *kt, valid; 3721 void *entry; 3722 int rv, rvt, base_index, l2_index=0, skip_entry; 3723 int cf_hit, cf_unhit, narrow_avail = 0; 3724 int del_low_idx = 0, del_high_idx = 0; 3725 soc_mem_t mem; 3726 soc_field_t ktf; 3727 uint8 i, bidx, num_ent; 3728 _soc_ism_mem_banks_t mem_banks; 3729 soc_memacc_t *memacc; 3730 bcm_mac_t mac; 3731 uint32 l2_entry[SOC_MAX_MEM_WORDS], result, bucket_index; 3732 uint32 key_type_1[] = {SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE, 3733 SOC_MEM_KEY_L2_ENTRY_1_L2_VFI}; 3734 uint32 key_type_2[] = {SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE, 3735 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI}; 3736 int index_cache[_SOC_ISM_MAX_BANKS] = {-1}; 3737 3738 /* NOTE: Implementation assumes that enough criteria/info will be set 3739 in the bcm_l2_addr_t param to not have any ambiguity between 3740 ENTRY_1 and ENTRY_2, i.e the following conditions would not 3741 be true together */ 3742 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 3743 mem = L2_ENTRY_1m; 3744 entry = &l2_entries->l2_entry_1; 3745 kt = key_type_1; 3746 valid = VALIDf; 3747 ktf = KEY_TYPEf; 3748 } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 3749 mem = L2_ENTRY_2m; 3750 entry = &l2_entries->l2_entry_2; 3751 kt = key_type_2; 3752 valid = VALID_0f; 3753 ktf = KEY_TYPE_0f; 3754 } else { 3755 return BCM_E_PARAM; 3756 } 3757 rv = soc_ism_get_banks_for_mem(unit, mem, mem_banks.banks, 3758 mem_banks.bank_size, &mem_banks.count); 3759 if (SOC_FAILURE(rv)) { 3760 return BCM_E_INTERNAL; 3761 } 3762 if (mem_banks.count == 0) { 3763 return BCM_E_NOT_FOUND; 3764 } 3765 3766 /* Don't let the table rearrange in the background */ 3767 BCM_IF_ERROR_RETURN(soc_l2x_freeze(unit)); 3768 3769 cf_hit = cf_unhit = -1; 3770 SOC_L2X_MEM_LOCK(unit); 3771 for (bidx = 0; bidx < mem_banks.count; bidx++) { 3772 /* base index depends on the view, L2_ENTRY_1 or L2_ENTRY_2 */ 3773 rv = soc_generic_hash(unit, mem, entry, 3774 (uint32)1 << mem_banks.banks[bidx], 3775 0, &base_index, &result, 3776 &bucket_index, &num_ent); 3777 if (SOC_FAILURE(rv)) { 3778 rv = BCM_E_INTERNAL; 3779 break; 3780 } 3781 /* Cache indexes for later use, based on the newer entry type*/ 3782 index_cache[bidx] = base_index; 3783 for (i = 0; i < num_ent; i++ ) { 3784 skip_entry = FALSE; 3785 l2_index = base_index + i; 3786 rv = soc_mem_read(unit, mem, COPYNO_ALL, l2_index, l2_entry); 3787 if (SOC_FAILURE(rv)) { 3788 rv = BCM_E_MEMORY; 3789 break; 3790 } 3791 if (!soc_mem_field32_get(unit, mem, &l2_entry, valid)) { 3792 if (mem == L2_ENTRY_2m) { 3793 soc_mem_t mem1 = L2_ENTRY_1m; 3794 rv = soc_mem_read(unit, mem1, COPYNO_ALL, 3795 (2 * l2_index) + 1, l2_entry); 3796 if (SOC_FAILURE(rv)) { 3797 rv = BCM_E_MEMORY; 3798 break; 3799 } 3800 if (soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) { 3801 continue; 3802 } 3803 } 3804 /* Found invalid entry - stop the search, victim found */ 3805 cf_unhit = l2_index; 3806 break; 3807 } 3808 /* Check if the newer entry and existing entry belong to the same 3809 memory view */ 3810 if (((soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[0]) || 3811 (soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[1]))) { 3812 if (mem == L2_ENTRY_1m) { 3813 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 3814 STATIC_BIT)) { 3815 /* Skip static entries */ 3816 skip_entry = TRUE; 3817 } 3818 if (!skip_entry) { 3819 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 3820 _BCM_TR3_L2_MEMACC_MAC_ADDR); 3821 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 3822 if (BCM_MAC_IS_MCAST(mac)) { 3823 skip_entry = TRUE; 3824 } 3825 } 3826 if (!skip_entry) { 3827 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 3828 HITDA) || 3829 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 3830 HITSA)) { 3831 cf_hit = l2_index; 3832 } else { 3833 /* Found unhit entry - 3834 * stop search, victim found */ 3835 cf_unhit = l2_index; 3836 break; 3837 } 3838 } 3839 } else { 3840 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, 3841 STATIC_BIT)) { 3842 /* Skip static entries */ 3843 skip_entry = TRUE; 3844 } 3845 if (!skip_entry) { 3846 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 3847 _BCM_TR3_L2_MEMACC_MAC_ADDR); 3848 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 3849 if (BCM_MAC_IS_MCAST(mac)) { 3850 skip_entry = TRUE; 3851 } 3852 } 3853 if (!skip_entry) { 3854 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, 3855 HITDA) || 3856 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, 3857 HITSA)) { 3858 cf_hit = l2_index; 3859 } else { 3860 /* Found unhit entry - 3861 * stop search, victim found */ 3862 cf_unhit = l2_index; 3863 break; 3864 } 3865 } 3866 } 3867 } 3868 } 3869 if (SOC_FAILURE(rv) || (cf_unhit >= 0)) { 3870 break; 3871 } 3872 } 3873 3874 if ((cf_unhit >= 0) || (cf_hit >= 0)) { 3875 /* Prefer unhit entries over hit entries */ 3876 l2_index = (cf_unhit >= 0)? cf_unhit : cf_hit; 3877 rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL, 3878 l2_index); 3879 } else { 3880 if (mem == L2_ENTRY_2m) { 3881 soc_mem_t mem1 = L2_ENTRY_1m; 3882 3883 /* Try replacing 2 consecutive narrow entries with one wide */ 3884 kt = key_type_1; 3885 for (bidx = 0; bidx < mem_banks.count; bidx++) { 3886 for (i = 0; i < 2; i++) { 3887 narrow_avail = 0; 3888 del_low_idx = 0; 3889 del_high_idx = 0; 3890 /* We cached the wide entry index pre-emptively */ 3891 l2_index = index_cache[bidx]*2 + i*2; 3892 rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry); 3893 if (SOC_FAILURE(rv)) { 3894 rv = BCM_E_MEMORY; 3895 break; 3896 } 3897 if (!soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) { 3898 /* Found one invalid entry */ 3899 narrow_avail++; 3900 } else if (((soc_mem_field32_get(unit, mem1, &l2_entry, 3901 KEY_TYPEf) == kt[0]) || 3902 (soc_mem_field32_get(unit, mem1, &l2_entry, 3903 KEY_TYPEf) == kt[1]))) { 3904 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 3905 STATIC_BIT)) { 3906 /* Skip static entries */ 3907 continue; 3908 } else { 3909 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 3910 _BCM_TR3_L2_MEMACC_MAC_ADDR); 3911 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 3912 if (BCM_MAC_IS_MCAST(mac)) { 3913 continue; 3914 } 3915 } 3916 narrow_avail++; 3917 del_low_idx = 1; 3918 } 3919 /* narrow_avail should be one */ 3920 l2_index++; 3921 rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry); 3922 if (SOC_FAILURE(rv)) { 3923 rv = BCM_E_MEMORY; 3924 break; 3925 } 3926 if (!soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) { 3927 /* Found two invalid entry */ 3928 narrow_avail++; 3929 break; 3930 } else if (((soc_mem_field32_get(unit, mem1, &l2_entry, 3931 KEY_TYPEf) == kt[0]) || 3932 (soc_mem_field32_get(unit, mem1, &l2_entry, 3933 KEY_TYPEf) == kt[1]))) { 3934 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 3935 STATIC_BIT)) { 3936 /* Skip static entries */ 3937 continue; 3938 } else { 3939 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 3940 _BCM_TR3_L2_MEMACC_MAC_ADDR); 3941 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 3942 if (BCM_MAC_IS_MCAST(mac)) { 3943 continue; 3944 } 3945 } 3946 narrow_avail++; 3947 del_high_idx = 1; 3948 break; 3949 } 3950 } 3951 if (SOC_FAILURE(rv)) { 3952 break; 3953 } 3954 if (narrow_avail == 2) { 3955 if (del_low_idx) { 3956 rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index-1); 3957 if (SOC_FAILURE(rv)) { 3958 rv = BCM_E_MEMORY; 3959 break; 3960 } 3961 } 3962 if (del_high_idx) { 3963 rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index); 3964 if (SOC_FAILURE(rv)) { 3965 rv = BCM_E_MEMORY; 3966 break; 3967 } 3968 } 3969 /* Get the cached wide entry index */ 3970 l2_index = index_cache[bidx] + i; 3971 break; 3972 } 3973 } 3974 /* we may endup here when first entry is invalid and 3975 second one is static */ 3976 if (SOC_FAILURE(rv) || (narrow_avail < 2)) { 3977 /* coverity[value_overwrite] */ 3978 l2_index = 0; /* Never used, but stops compiler uninit complaint */ 3979 rv = BCM_E_FULL; /* no dynamics to delete */ 3980 } 3981 } else { 3982 /* Try to find a wide entry and replace with a narrow one */ 3983 soc_mem_t mem1 = L2_ENTRY_2m; 3984 kt = key_type_2; 3985 for (bidx = 0; bidx < mem_banks.count; bidx++) { 3986 for (i = 0; i < 2; i++) { 3987 l2_index = index_cache[bidx]/2 + i; 3988 rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry); 3989 if (SOC_FAILURE(rv)) { 3990 rv = BCM_E_MEMORY; 3991 break; 3992 } 3993 if ((soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[0]) || 3994 (soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[1])) { 3995 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, 3996 STATIC_BIT)) { 3997 continue; 3998 } 3999 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 4000 _BCM_TR3_L2_MEMACC_MAC_ADDR); 4001 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 4002 if (BCM_MAC_IS_MCAST(mac)) { 4003 continue; 4004 } 4005 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, HITDA) || 4006 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, HITSA)) { 4007 cf_hit = l2_index; 4008 } else { 4009 /* Found unhit entry - 4010 * stop search, victim found */ 4011 cf_unhit = l2_index; 4012 break; 4013 } 4014 } 4015 } 4016 if (cf_unhit < 0) { 4017 if (cf_hit >= 0) { 4018 l2_index = cf_hit; 4019 } else { 4020 rv = BCM_E_FULL; 4021 } 4022 } 4023 } 4024 if (SOC_SUCCESS(rv)) { 4025 rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index); 4026 } 4027 } 4028 } 4029 if (SOC_SUCCESS(rv)) { 4030 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry); 4031 } 4032 SOC_L2X_MEM_UNLOCK(unit); 4033 rvt = soc_l2x_thaw(unit); 4034 return SOC_FAILURE(rv) ? rv : rvt; 4035 } 4036 4037 /* 4038 * Function: 4039 * _bcm_tr3_l2_hash_pending_override 4040 * Purpose: 4041 * Given an L2 entries structure, search for pending entries to 4042 * eject in favor of the new entry. 4043 * Parameters: 4044 * unit - (IN) Unit number. 4045 * l2_entries (IN/OUT) Triumph3 L2 entries structure 4046 * Returns: 4047 * BCM_E_xxx 4048 * Notes: 4049 * In case new entry is double wide,we check for any pending narrow entries 4050 * which can be deleted or free, and then do an insert. del_low_idx and 4051 * del_high_idx are set if the entry is not free and has to be deleted 4052 * before insert. 4053 */ 4054 int 4055 _bcm_tr3_l2_hash_pending_override(int unit, _bcm_tr3_l2_entries_t *l2_entries) 4056 { 4057 uint32 *kt, valid; 4058 void *entry; 4059 int rv, rvt, base_index, l2_index=0, skip_entry; 4060 int p_hit, narrow_avail = 0; 4061 int del_low_idx = 0, del_high_idx = 0; 4062 soc_mem_t mem; 4063 soc_field_t ktf; 4064 uint8 i, bidx, num_ent; 4065 _soc_ism_mem_banks_t mem_banks; 4066 soc_memacc_t *memacc; 4067 bcm_mac_t mac; 4068 uint32 l2_entry[SOC_MAX_MEM_WORDS], result, bucket_index; 4069 uint32 key_type_1[] = {SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE, 4070 SOC_MEM_KEY_L2_ENTRY_1_L2_VFI}; 4071 uint32 key_type_2[] = {SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE, 4072 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI}; 4073 int index_cache[_SOC_ISM_MAX_BANKS] = {-1}; 4074 4075 /* NOTE: Implementation assumes that enough criteria/info will be set 4076 in the bcm_l2_addr_t param to not have any ambiguity between 4077 ENTRY_1 and ENTRY_2, i.e the following conditions would not 4078 be true together */ 4079 if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 4080 mem = L2_ENTRY_1m; 4081 entry = &l2_entries->l2_entry_1; 4082 kt = key_type_1; 4083 valid = VALIDf; 4084 ktf = KEY_TYPEf; 4085 } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 4086 mem = L2_ENTRY_2m; 4087 entry = &l2_entries->l2_entry_2; 4088 kt = key_type_2; 4089 valid = VALID_0f; 4090 ktf = KEY_TYPE_0f; 4091 } else { 4092 return BCM_E_PARAM; 4093 } 4094 rv = soc_ism_get_banks_for_mem(unit, mem, mem_banks.banks, 4095 mem_banks.bank_size, &mem_banks.count); 4096 if (SOC_FAILURE(rv)) { 4097 return BCM_E_INTERNAL; 4098 } 4099 if (mem_banks.count == 0) { 4100 return BCM_E_NOT_FOUND; 4101 } 4102 4103 /* Don't let the table rearrange in the background */ 4104 BCM_IF_ERROR_RETURN(soc_l2x_freeze(unit)); 4105 4106 p_hit = -1; 4107 SOC_L2X_MEM_LOCK(unit); 4108 for (bidx = 0; bidx < mem_banks.count; bidx++) { 4109 /* base index depends on the view, L2_ENTRY_1 or L2_ENTRY_2 */ 4110 rv = soc_generic_hash(unit, mem, entry, 4111 (uint32)1 << mem_banks.banks[bidx], 4112 0, &base_index, &result, 4113 &bucket_index, &num_ent); 4114 if (SOC_FAILURE(rv)) { 4115 rv = BCM_E_INTERNAL; 4116 break; 4117 } 4118 /* Cache indexes for later use, based on the newer entry type*/ 4119 index_cache[bidx] = base_index; 4120 for (i = 0; i < num_ent; i++ ) { 4121 skip_entry = FALSE; 4122 l2_index = base_index + i; 4123 rv = soc_mem_read(unit, mem, COPYNO_ALL, l2_index, l2_entry); 4124 if (SOC_FAILURE(rv)) { 4125 rv = BCM_E_MEMORY; 4126 break; 4127 } 4128 if (!soc_mem_field32_get(unit, mem, &l2_entry, valid)) { 4129 if (mem == L2_ENTRY_2m) { 4130 soc_mem_t mem1 = L2_ENTRY_1m; 4131 rv = soc_mem_read(unit, mem1, COPYNO_ALL, 4132 (2 * l2_index) + 1, l2_entry); 4133 if (SOC_FAILURE(rv)) { 4134 rv = BCM_E_MEMORY; 4135 break; 4136 } 4137 if (soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) { 4138 continue; 4139 } 4140 } 4141 /* Found invalid entry - stop the search, victim found */ 4142 p_hit = l2_index; 4143 break; 4144 } 4145 /* Check if the newer entry and existing entry belong to the same 4146 memory view */ 4147 if (((soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[0]) || 4148 (soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[1]))) { 4149 if (mem == L2_ENTRY_1m) { 4150 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 4151 STATIC_BIT)) { 4152 /* Skip static entries */ 4153 skip_entry = TRUE; 4154 } 4155 if (!skip_entry) { 4156 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 4157 _BCM_TR3_L2_MEMACC_MAC_ADDR); 4158 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 4159 if (BCM_MAC_IS_MCAST(mac)) { 4160 skip_entry = TRUE; 4161 } 4162 } 4163 if (!skip_entry) { 4164 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 4165 PENDING)) { 4166 p_hit = l2_index; 4167 break; 4168 } 4169 } 4170 } else { 4171 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, 4172 STATIC_BIT)) { 4173 /* Skip static entries */ 4174 skip_entry = TRUE; 4175 } 4176 if (!skip_entry) { 4177 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 4178 _BCM_TR3_L2_MEMACC_MAC_ADDR); 4179 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 4180 if (BCM_MAC_IS_MCAST(mac)) { 4181 skip_entry = TRUE; 4182 } 4183 } 4184 if (!skip_entry) { 4185 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, 4186 PENDING)) { 4187 p_hit = l2_index; 4188 break; 4189 } 4190 } 4191 } 4192 } 4193 } 4194 if (SOC_FAILURE(rv) || (p_hit >= 0)) { 4195 break; 4196 } 4197 } 4198 4199 if (p_hit >= 0) { 4200 l2_index = p_hit; 4201 rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL, 4202 l2_index); 4203 } else { 4204 if (mem == L2_ENTRY_2m) { 4205 soc_mem_t mem1 = L2_ENTRY_1m; 4206 4207 /* Try replacing 2 consecutive narrow entries with one wide */ 4208 kt = key_type_1; 4209 for (bidx = 0; bidx < mem_banks.count; bidx++) { 4210 for (i = 0; i < 2; i++) { 4211 narrow_avail = 0; 4212 del_low_idx = 0; 4213 del_high_idx = 0; 4214 /* We cached the wide entry index pre-emptively */ 4215 l2_index = index_cache[bidx]*2 + i*2; 4216 rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry); 4217 if (SOC_FAILURE(rv)) { 4218 rv = BCM_E_MEMORY; 4219 break; 4220 } 4221 if (!soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) { 4222 /* Found one invalid entry */ 4223 narrow_avail++; 4224 } else if (((soc_mem_field32_get(unit, mem1, &l2_entry, 4225 KEY_TYPEf) == kt[0]) || 4226 (soc_mem_field32_get(unit, mem1, &l2_entry, 4227 KEY_TYPEf) == kt[1]))) { 4228 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 4229 STATIC_BIT)) { 4230 /* Skip static entries */ 4231 continue; 4232 } else { 4233 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 4234 _BCM_TR3_L2_MEMACC_MAC_ADDR); 4235 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 4236 if (BCM_MAC_IS_MCAST(mac)) { 4237 continue; 4238 } 4239 } 4240 narrow_avail++; 4241 del_low_idx = 1; 4242 } 4243 /* narrow_avail should be one */ 4244 l2_index++; 4245 rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry); 4246 if (SOC_FAILURE(rv)) { 4247 rv = BCM_E_MEMORY; 4248 break; 4249 } 4250 if (!soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) { 4251 /* Found two invalid entry */ 4252 narrow_avail++; 4253 break; 4254 } else if (((soc_mem_field32_get(unit, mem1, &l2_entry, 4255 KEY_TYPEf) == kt[0]) || 4256 (soc_mem_field32_get(unit, mem1, &l2_entry, 4257 KEY_TYPEf) == kt[1]))) { 4258 if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry, 4259 STATIC_BIT)) { 4260 /* Skip static entries */ 4261 continue; 4262 } else { 4263 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, 4264 _BCM_TR3_L2_MEMACC_MAC_ADDR); 4265 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 4266 if (BCM_MAC_IS_MCAST(mac)) { 4267 continue; 4268 } 4269 } 4270 narrow_avail++; 4271 del_high_idx = 1; 4272 break; 4273 } 4274 } 4275 if (SOC_FAILURE(rv)) { 4276 break; 4277 } 4278 if (narrow_avail == 2) { 4279 if (del_low_idx) { 4280 rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index-1); 4281 if (SOC_FAILURE(rv)) { 4282 rv = BCM_E_MEMORY; 4283 break; 4284 } 4285 } 4286 if (del_high_idx) { 4287 rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index); 4288 if (SOC_FAILURE(rv)) { 4289 rv = BCM_E_MEMORY; 4290 break; 4291 } 4292 } 4293 /* Get the cached wide entry index */ 4294 l2_index = index_cache[bidx] + i; 4295 break; 4296 } 4297 } 4298 /* we may endup here when first entry is invalid and 4299 second one is static */ 4300 if (SOC_FAILURE(rv) || (narrow_avail < 2)) { 4301 /* coverity[value_overwrite] */ 4302 l2_index = 0; /* Never used, but stops compiler uninit complaint */ 4303 rv = BCM_E_FULL; /* no dynamics to delete */ 4304 } 4305 } else { 4306 /* Try to find a wide entry and replace with a narrow one */ 4307 soc_mem_t mem1 = L2_ENTRY_2m; 4308 kt = key_type_2; 4309 for (bidx = 0; bidx < mem_banks.count; bidx++) { 4310 for (i = 0; i < 2; i++) { 4311 l2_index = index_cache[bidx]/2 + i; 4312 rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry); 4313 if (SOC_FAILURE(rv)) { 4314 rv = BCM_E_MEMORY; 4315 break; 4316 } 4317 if ((soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[0]) || 4318 (soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[1])) { 4319 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, 4320 STATIC_BIT)) { 4321 continue; 4322 } 4323 memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, 4324 _BCM_TR3_L2_MEMACC_MAC_ADDR); 4325 soc_memacc_mac_addr_get(memacc, l2_entry, mac); 4326 if (BCM_MAC_IS_MCAST(mac)) { 4327 continue; 4328 } 4329 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, PENDING)) { 4330 p_hit = l2_index; 4331 break; 4332 } 4333 } 4334 } 4335 if (p_hit >= 0) { 4336 l2_index = p_hit; 4337 } else { 4338 rv = BCM_E_FULL; 4339 } 4340 } 4341 if (SOC_SUCCESS(rv)) { 4342 rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index); 4343 } 4344 } 4345 } 4346 if (SOC_SUCCESS(rv)) { 4347 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry); 4348 } 4349 SOC_L2X_MEM_UNLOCK(unit); 4350 rvt = soc_l2x_thaw(unit); 4351 return SOC_FAILURE(rv) ? rv : rvt; 4352 } 4353 4354 /**************************************************************************** 4355 * 4356 * L2 Callbacks Registration 4357 */ 4358 static bcm_l2_addr_callback_t _bcm_tr3_l2_cbs[SOC_MAX_NUM_DEVICES]; 4359 static void *_bcm_tr3_l2_cb_data[SOC_MAX_NUM_DEVICES]; 4360 4361 void 4362 _bcm_tr3_l2_register_callback(int unit, uint32 flags, 4363 soc_mem_t mem_type, 4364 l2_combo_entry_t *entry_del, 4365 l2_combo_entry_t *entry_add, 4366 void *fn_data) 4367 { 4368 if (_bcm_tr3_l2_cbs[unit] != NULL) { 4369 bcm_l2_addr_t l2addr_del, l2addr_add; 4370 uint32 set_flags = 0; /* Common flags: Move, From/to native */ 4371 _bcm_tr3_l2_entries_t l2_entries; 4372 4373 /* First, set up the entries: decode HW entries and set flags */ 4374 if (entry_del != NULL) { 4375 l2_entries.entry_flags = 0; 4376 switch (mem_type) { 4377 case L2_ENTRY_1m: 4378 sal_memcpy(&l2_entries.l2_entry_1, entry_del, 4379 sizeof(l2_entry_1_entry_t)); 4380 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_1; 4381 break; 4382 case L2_ENTRY_2m: 4383 sal_memcpy(&l2_entries.l2_entry_2, entry_del, 4384 sizeof(l2_entry_2_entry_t)); 4385 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_2; 4386 break; 4387 case EXT_L2_ENTRY_1m: 4388 sal_memcpy(&l2_entries.ext_l2_entry_1, entry_del, 4389 sizeof(ext_l2_entry_1_entry_t)); 4390 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1; 4391 break; 4392 case EXT_L2_ENTRY_2m: 4393 sal_memcpy(&l2_entries.ext_l2_entry_2, entry_del, 4394 sizeof(ext_l2_entry_2_entry_t)); 4395 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2; 4396 break; 4397 default: assert(0); 4398 } 4399 (void)_bcm_tr3_l2api_from_l2hw(unit, &l2addr_del, &l2_entries); 4400 } 4401 if (entry_add != NULL) { 4402 l2_entries.entry_flags = 0; 4403 switch (mem_type) { 4404 case L2_ENTRY_1m: 4405 sal_memcpy(&l2_entries.l2_entry_1, entry_add, 4406 sizeof(l2_entry_1_entry_t)); 4407 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_1; 4408 break; 4409 case L2_ENTRY_2m: 4410 sal_memcpy(&l2_entries.l2_entry_2, entry_add, 4411 sizeof(l2_entry_2_entry_t)); 4412 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_2; 4413 break; 4414 case EXT_L2_ENTRY_1m: 4415 sal_memcpy(&l2_entries.ext_l2_entry_1, entry_add, 4416 sizeof(ext_l2_entry_1_entry_t)); 4417 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1; 4418 break; 4419 case EXT_L2_ENTRY_2m: 4420 sal_memcpy(&l2_entries.ext_l2_entry_2, entry_add, 4421 sizeof(ext_l2_entry_2_entry_t)); 4422 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2; 4423 break; 4424 default: assert(0); 4425 } 4426 (void)_bcm_tr3_l2api_from_l2hw(unit, &l2addr_add, &l2_entries); 4427 } 4428 4429 if ((entry_del != NULL) && (entry_add != NULL)) { /* It's a move */ 4430 set_flags |= BCM_L2_MOVE; 4431 if (SOC_USE_GPORT(unit)) { 4432 if (l2addr_del.port != l2addr_add.port) { 4433 set_flags |= BCM_L2_MOVE_PORT; 4434 } 4435 } else { 4436 if (l2addr_del.modid != l2addr_add.modid || 4437 l2addr_del.tgid != l2addr_add.tgid || 4438 l2addr_del.port != l2addr_add.port) { 4439 set_flags |= BCM_L2_MOVE_PORT; 4440 } 4441 } 4442 if (!(l2addr_del.flags & BCM_L2_TRUNK_MEMBER)) { 4443 if (bcm_tr3_l2_port_native(unit, l2addr_del.modid, 4444 l2addr_del.port) > 0) { 4445 set_flags |= BCM_L2_FROM_NATIVE; 4446 set_flags |= BCM_L2_NATIVE; 4447 } 4448 } 4449 if (!(l2addr_add.flags & BCM_L2_TRUNK_MEMBER)) { 4450 if (bcm_tr3_l2_port_native(unit, l2addr_add.modid, 4451 l2addr_add.port) > 0) { 4452 set_flags |= BCM_L2_TO_NATIVE; 4453 set_flags |= BCM_L2_NATIVE; 4454 } 4455 } 4456 l2addr_del.flags |= set_flags; 4457 l2addr_add.flags |= set_flags; 4458 } else if (entry_del != NULL) { /* Age out or simple delete */ 4459 if (!(l2addr_del.flags & BCM_L2_TRUNK_MEMBER)) { 4460 if (bcm_tr3_l2_port_native(unit, l2addr_del.modid, 4461 l2addr_del.port) > 0) { 4462 l2addr_del.flags |= BCM_L2_NATIVE; 4463 } 4464 } 4465 } else if (entry_add != NULL) { /* Insert or learn */ 4466 if (!(l2addr_add.flags & BCM_L2_TRUNK_MEMBER)) { 4467 if (bcm_tr3_l2_port_native(unit, l2addr_add.modid, 4468 l2addr_add.port) > 0) { 4469 l2addr_add.flags |= BCM_L2_NATIVE; 4470 } 4471 } 4472 if (flags & SOC_L2X_ENTRY_OVERFLOW) { 4473 l2addr_add.flags |= BCM_L2_ENTRY_OVERFLOW; 4474 } 4475 } 4476 4477 /* The entries are now set up. Make the callbacks */ 4478 if (entry_del != NULL) { 4479 _bcm_tr3_l2_cbs[unit](unit, &l2addr_del, BCM_L2_CALLBACK_DELETE, 4480 _bcm_tr3_l2_cb_data[unit]); 4481 } 4482 if (entry_add != NULL) { 4483 _bcm_tr3_l2_cbs[unit](unit, &l2addr_add, BCM_L2_CALLBACK_ADD, 4484 _bcm_tr3_l2_cb_data[unit]); 4485 } 4486 } 4487 } 4488 4489 /* 4490 * Function: 4491 * _bcm_tr3_l2_hw_init 4492 * Purpose: 4493 * Initialize the BCM L2 HW subsystem. 4494 * Parameters: 4495 * unit - (IN) Unit number. 4496 * Returns: 4497 * BCM_E_xxx 4498 * Notes: 4499 */ 4500 int 4501 _bcm_tr3_l2_hw_init(int unit) 4502 { 4503 int rv, lclass, was_running = FALSE; 4504 uint32 flags; 4505 sal_usecs_t interval; 4506 4507 if (soc_l2x_running(unit, &flags, &interval)) { 4508 was_running = TRUE; 4509 BCM_IF_ERROR_RETURN(soc_tr3_l2x_stop(unit)); 4510 } 4511 4512 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) { 4513 if (!(SAL_BOOT_QUICKTURN || SAL_BOOT_SIMULATION || 4514 SAL_BOOT_BCMSIM)) { 4515 (void)_tr3_l2x_delete_all(unit); 4516 4517 /* 4518 * Init class based learning 4519 */ 4520 BCM_IF_ERROR_RETURN(soc_mem_clear(unit, PORT_CBL_TABLEm, 4521 MEM_BLOCK_ALL, 0)); 4522 for (lclass = 0; lclass < SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr); 4523 lclass++) { 4524 BCM_IF_ERROR_RETURN(WRITE_CBL_ATTRIBUTEr(unit, lclass, 0)); 4525 } 4526 } 4527 } 4528 4529 4530 4531 rv = _bcm_tr3_l2_mbi_init(unit); 4532 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 4533 return rv; 4534 } 4535 4536 /* bcm_l2_register clients */ 4537 soc_l2_entry_register(unit, _bcm_tr3_l2_register_callback, NULL); 4538 4539 if (was_running) { 4540 interval = (SAL_BOOT_BCMSIM) ? BCMSIM_L2XMSG_INTERVAL : interval; 4541 soc_l2x_start(unit, flags, interval); 4542 } 4543 4544 return BCM_E_NONE; 4545 } 4546 4547 /* 4548 * Function: 4549 * _bcm_tr3_l2_cache_gport_resolve 4550 * Purpose: 4551 * Convert destination in a GPORT format to modid port pair or trunk id 4552 * Parameters: 4553 * unit - Unit number 4554 * l2caddr - (IN/OUT) Hardware-independent L2 entry 4555 * Returns: 4556 * BCM_E_XXX 4557 */ 4558 STATIC int 4559 _bcm_tr3_l2_cache_gport_resolve(int unit, bcm_l2_cache_addr_t *l2caddr) 4560 { 4561 bcm_port_t port; 4562 bcm_module_t modid; 4563 bcm_trunk_t tgid; 4564 int id; 4565 4566 if (BCM_GPORT_IS_SET(l2caddr->dest_port)) { 4567 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, l2caddr->dest_port, 4568 &modid, &port, &tgid, &id)); 4569 /* MPLS MIM and WLAN GPORTS are not currently supported. */ 4570 if (-1 != id) { 4571 return (BCM_E_UNAVAIL); 4572 } 4573 /* Trunk GPORT */ 4574 if (BCM_TRUNK_INVALID != tgid) { 4575 l2caddr->flags |= BCM_L2_CACHE_TRUNK; 4576 l2caddr->dest_trunk = tgid; 4577 } else { /* MODPORT GPORT */ 4578 l2caddr->dest_port = port; 4579 l2caddr->dest_modid = modid; 4580 } 4581 } 4582 4583 if (BCM_GPORT_IS_SET(l2caddr->src_port)) { 4584 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, l2caddr->src_port, 4585 &port)); 4586 l2caddr->src_port = port; 4587 } 4588 4589 return BCM_E_NONE; 4590 } 4591 4592 /* 4593 * Function: 4594 * _bcm_tr3_l2_cache_gport_construct 4595 * Purpose: 4596 * Constract a GPORT destination format from modid port pair or trunk id 4597 * Parameters: 4598 * unit - Unit number 4599 * l2caddr - (IN/OUT) Hardware-independent L2 entry 4600 * Returns: 4601 * BCM_E_XXX 4602 */ 4603 STATIC int 4604 _bcm_tr3_l2_cache_gport_construct(int unit, bcm_l2_cache_addr_t *l2caddr) 4605 { 4606 bcm_gport_t gport; 4607 _bcm_gport_dest_t gport_dst; 4608 4609 _bcm_gport_dest_t_init(&gport_dst); 4610 4611 if (l2caddr->flags & BCM_L2_CACHE_TRUNK) { 4612 gport_dst.gport_type = BCM_GPORT_TYPE_TRUNK; 4613 gport_dst.tgid = l2caddr->dest_trunk; 4614 } else { 4615 gport_dst.gport_type = BCM_GPORT_TYPE_MODPORT; 4616 gport_dst.modid = l2caddr->dest_modid; 4617 gport_dst.port = l2caddr->dest_port; 4618 } 4619 4620 BCM_IF_ERROR_RETURN( 4621 _bcm_esw_gport_construct(unit, &gport_dst, &gport)); 4622 4623 l2caddr->dest_port = gport; 4624 4625 gport_dst.gport_type = BCM_GPORT_TYPE_MODPORT; 4626 gport_dst.port = l2caddr->src_port; 4627 BCM_IF_ERROR_RETURN( 4628 bcm_esw_stk_my_modid_get(unit, &gport_dst.modid)); 4629 if (gport_dst.modid < 0) { 4630 return BCM_E_UNAVAIL; 4631 } 4632 4633 BCM_IF_ERROR_RETURN( 4634 _bcm_esw_gport_construct(unit, &gport_dst, &gport)); 4635 4636 l2caddr->src_port = gport; 4637 4638 return BCM_E_NONE; 4639 } 4640 4641 /* 4642 * Function: 4643 * _bcm_tr3_l2_cache_to_l2u 4644 * Purpose: 4645 * Convert a hardware-independent L2 cache entry to a L2 User table entry. 4646 * Parameters: 4647 * unit - Unit number 4648 * l2u_entry - (OUT) Firebolt L2 User entry 4649 * l2caddr - Hardware-independent L2 entry 4650 * Returns: 4651 * BCM_E_XXX 4652 */ 4653 STATIC int 4654 _bcm_tr3_l2_cache_to_l2u(int unit, 4655 l2u_entry_t *l2u_entry, bcm_l2_cache_addr_t *l2caddr) 4656 { 4657 bcm_module_t mod_in, mod_out; 4658 bcm_port_t port_in, port_out; 4659 uint16 vfi; 4660 uint32 mask[2]; 4661 soc_field_t port_field = 0; 4662 int skip_l2u, isGport, modid_field_len, port_field_len; 4663 bcm_vlan_t vlan; 4664 4665 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 4666 4667 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 4668 4669 int pri_field_len; 4670 int max_pri; 4671 /* If VPN specified do not perform vlan id check */ 4672 if (!_BCM_VPN_IS_SET(l2caddr->vlan)) { 4673 VLAN_CHK_ID(unit, l2caddr->vlan); 4674 } 4675 4676 if (l2caddr->flags & BCM_L2_CACHE_SETPRI) { 4677 pri_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm, PRIf); 4678 max_pri = (1 << pri_field_len) - 1; 4679 4680 /* Allow the maximum internal priority as per the device support */ 4681 if ((l2caddr->prio < BCM_PRIO_MIN) || (l2caddr->prio > max_pri)) { 4682 return BCM_E_PARAM; 4683 } 4684 } 4685 4686 sal_memset(l2u_entry, 0, sizeof (*l2u_entry)); 4687 4688 _l2u_field32_set(unit, l2u_entry, VALIDf, 1); 4689 _l2u_mac_addr_set(unit, l2u_entry, MAC_ADDRf, l2caddr->mac); 4690 4691 if (_BCM_VPN_IS_SET(l2caddr->vlan)) { 4692 _l2u_field32_set(unit, l2u_entry, KEY_TYPEf, 1); 4693 _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, l2caddr->vlan); 4694 _l2u_field32_set(unit, l2u_entry, VFIf, vfi); 4695 4696 if (l2caddr->flags & BCM_L2_CACHE_PROTO_PKT) { 4697 if (soc_mem_field_valid(unit, L2_USER_ENTRYm, 4698 L2_PROTOCOL_PKTf)) { 4699 _l2u_field32_set(unit, l2u_entry, L2_PROTOCOL_PKTf, 1); 4700 } else { 4701 return BCM_E_UNAVAIL; 4702 } 4703 } 4704 4705 } else { 4706 _l2u_field32_set(unit, l2u_entry, KEY_TYPEf, 0); 4707 vlan = l2caddr->vlan; 4708 _l2u_field32_set(unit, l2u_entry, VLAN_IDf, vlan); 4709 } 4710 4711 if (l2caddr->flags & BCM_L2_CACHE_SETPRI) { 4712 _l2u_field32_set(unit, l2u_entry, PRIf, l2caddr->prio); 4713 _l2u_field32_set(unit, l2u_entry, RPEf, 1); 4714 } 4715 4716 if (l2caddr->flags & BCM_L2_CACHE_CPU) { 4717 _l2u_field32_set(unit, l2u_entry, CPUf, 1); 4718 } 4719 4720 if (l2caddr->flags & BCM_L2_CACHE_BPDU) { 4721 _l2u_field32_set(unit, l2u_entry, BPDUf, 1); 4722 } 4723 4724 if (l2caddr->flags & BCM_L2_CACHE_DISCARD) { 4725 _l2u_field32_set(unit, l2u_entry, DST_DISCARDf, 1); 4726 } 4727 4728 if (l2caddr->flags & BCM_L2_CACHE_LEARN_DISABLE) { 4729 _l2u_field32_set(unit, l2u_entry, DO_NOT_LEARN_MACSAf, 1); 4730 } 4731 4732 if (BCM_GPORT_IS_SET(l2caddr->dest_port) || 4733 BCM_GPORT_IS_SET(l2caddr->src_port)) { 4734 BCM_IF_ERROR_RETURN( 4735 _bcm_tr3_l2_cache_gport_resolve(unit, l2caddr)); 4736 isGport = 1; 4737 } else { 4738 isGport = 0; 4739 } 4740 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 4741 if (l2caddr->flags & BCM_L2_CACHE_TRUNK) { 4742 _l2u_field32_set(unit, l2u_entry, Tf, 1); 4743 _l2u_field32_set(unit, l2u_entry, TGIDf, l2caddr->dest_trunk); 4744 } else { 4745 port_field = PORT_NUMf; 4746 } 4747 } else { 4748 if (l2caddr->flags & BCM_L2_CACHE_TRUNK) { 4749 _l2u_field32_set(unit, l2u_entry, MODULE_IDf, 4750 BCM_TRUNK_TO_MODIDf(unit, 4751 l2caddr->dest_trunk)); 4752 _l2u_field32_set(unit, l2u_entry, PORT_TGIDf, 4753 BCM_TRUNK_TO_TGIDf(unit, 4754 l2caddr->dest_trunk)); 4755 } else { 4756 port_field = PORT_TGIDf; 4757 } 4758 } 4759 4760 if (!((l2caddr->flags & BCM_L2_CACHE_TRUNK) || 4761 (l2caddr->flags & BCM_L2_CACHE_MULTICAST))) { 4762 mod_in = l2caddr->dest_modid; 4763 port_in = l2caddr->dest_port; 4764 if (!isGport) { 4765 PORT_DUALMODID_VALID(unit, port_in); 4766 } 4767 BCM_IF_ERROR_RETURN 4768 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 4769 mod_in, port_in, &mod_out, &port_out)); 4770 if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) { 4771 return BCM_E_BADID; 4772 } 4773 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 4774 return BCM_E_PORT; 4775 } 4776 _l2u_field32_set(unit, l2u_entry, MODULE_IDf, mod_out); 4777 _l2u_field32_set(unit, l2u_entry, port_field, port_out); 4778 } 4779 4780 if ((l2caddr->flags & BCM_L2_CACHE_MULTICAST) && 4781 !_BCM_VPN_IS_SET(l2caddr->vlan)) { 4782 if (_BCM_MULTICAST_IS_SET(l2caddr->group)) { 4783 if (_BCM_MULTICAST_IS_L2(l2caddr->group)) { 4784 port_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm, 4785 port_field); 4786 modid_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm, 4787 MODULE_IDf); 4788 /* If MACDA is MC, HW interprets value encoded in MODULE_IDf 4789 and PORT_FIELD as L2MC_INDEX */ 4790 _l2u_field32_set(unit, l2u_entry, port_field, 4791 (_BCM_MULTICAST_ID_GET(l2caddr->group) & 4792 ((1 << port_field_len) - 1))); 4793 _l2u_field32_set(unit, l2u_entry, MODULE_IDf, 4794 ((_BCM_MULTICAST_ID_GET(l2caddr->group) >> 4795 port_field_len) & 4796 ((1 << modid_field_len) - 1))); 4797 } else { 4798 return BCM_E_PARAM; 4799 } 4800 } 4801 } 4802 4803 if (l2caddr->flags & BCM_L2_CACHE_L3) { 4804 _l2u_field32_set(unit, l2u_entry, RESERVED_0f, 1); 4805 } 4806 4807 _l2u_mac_addr_set(unit, l2u_entry, MASKf, l2caddr->mac_mask); 4808 _l2u_field_get(unit, l2u_entry, MASKf, mask); 4809 mask[1] |= (l2caddr->vlan_mask & 0xfff) << 16; 4810 4811 if (!(l2caddr->flags & BCM_L2_CACHE_L3)) { 4812 if ((l2caddr->src_port) || (l2caddr->src_port_mask) ) { 4813 return BCM_E_PORT; 4814 } 4815 } 4816 4817 _l2u_field_set(unit, l2u_entry, MASKf, mask); 4818 _l2u_field32_set(unit, l2u_entry, CLASS_IDf, l2caddr->lookup_class); 4819 4820 return BCM_E_NONE; 4821 } 4822 return BCM_E_UNAVAIL; 4823 } 4824 4825 /* 4826 * Function: 4827 * _bcm_tr3_l2_from_l2u 4828 * Purpose: 4829 * Convert L2 User table entry to a hardware-independent L2 cache entry. 4830 * Parameters: 4831 * unit - Unit number 4832 * l2caddr - (OUT) Hardware-independent L2 entry 4833 * l2u_entry - Firebolt L2 User entry 4834 * Returns: 4835 * BCM_E_XXX 4836 */ 4837 STATIC int 4838 _bcm_tr3_l2_cache_from_l2u(int unit, 4839 bcm_l2_cache_addr_t *l2caddr, l2u_entry_t *l2u_entry) 4840 { 4841 bcm_module_t mod_in = 0, mod_out; 4842 bcm_port_t port_in = 0, port_out; 4843 uint32 mask[2]; 4844 int skip_l2u, isGport, port_field_len, modid_field_len, rval; 4845 #if defined(INCLUDE_L3) 4846 bcm_vlan_t vlan; 4847 #endif 4848 4849 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 4850 4851 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 4852 4853 sal_memset(l2caddr, 0, sizeof (*l2caddr)); 4854 4855 if (!_l2u_field32_get(unit, l2u_entry, VALIDf)) { 4856 return BCM_E_NOT_FOUND; 4857 } 4858 4859 _l2u_mac_addr_get(unit, l2u_entry, MAC_ADDRf, l2caddr->mac); 4860 4861 if (_l2u_field32_get(unit, l2u_entry, KEY_TYPEf)) { 4862 #if defined(INCLUDE_L3) 4863 /* key type 1 i.e. VFI */ 4864 vlan = _l2u_field32_get(unit, l2u_entry, VFIf); 4865 if (_bcm_vfi_used_get(unit, vlan, _bcmVfiTypeMpls)) { 4866 _BCM_VPN_SET(l2caddr->vlan, _BCM_VPN_TYPE_VFI, vlan); 4867 } else if (_bcm_vfi_used_get(unit, vlan, _bcmVfiTypeMim)) { 4868 _BCM_VPN_SET(l2caddr->vlan, _BCM_VPN_TYPE_VFI, vlan); 4869 } else if (_bcm_vfi_used_get(unit, vlan, _bcmVfiTypeL2Gre)) { 4870 BCM_IF_ERROR_RETURN( 4871 _bcm_tr3_l2gre_vpn_get(unit, (int) vlan, &l2caddr->vlan)); 4872 } 4873 4874 #endif 4875 } else { /* key type 0 i.e. VLAN ID */ 4876 l2caddr->vlan = _l2u_field32_get(unit, l2u_entry, VLAN_IDf); 4877 } 4878 4879 l2caddr->prio = _l2u_field32_get(unit, l2u_entry, PRIf); 4880 4881 if (_l2u_field32_get(unit, l2u_entry, RPEf)) { 4882 l2caddr->flags |= BCM_L2_CACHE_SETPRI; 4883 } 4884 4885 if (_l2u_field32_get(unit, l2u_entry, CPUf)) { 4886 l2caddr->flags |= BCM_L2_CACHE_CPU; 4887 } 4888 4889 if (_l2u_field32_get(unit, l2u_entry, BPDUf)) { 4890 l2caddr->flags |= BCM_L2_CACHE_BPDU; 4891 } 4892 4893 if (soc_mem_field_valid(unit, L2_USER_ENTRYm, L2_PROTOCOL_PKTf)) { 4894 if (_l2u_field32_get(unit, l2u_entry, L2_PROTOCOL_PKTf)) { 4895 l2caddr->flags |= BCM_L2_CACHE_PROTO_PKT; 4896 } 4897 } 4898 4899 if (_l2u_field32_get(unit, l2u_entry, DST_DISCARDf)) { 4900 l2caddr->flags |= BCM_L2_CACHE_DISCARD; 4901 } 4902 4903 if (_l2u_field32_get(unit, l2u_entry, DO_NOT_LEARN_MACSAf)) { 4904 l2caddr->flags |= BCM_L2_CACHE_LEARN_DISABLE; 4905 } 4906 4907 if (_l2u_field32_get(unit, l2u_entry, Tf)) { 4908 l2caddr->flags |= BCM_L2_CACHE_TRUNK; 4909 l2caddr->dest_trunk = _l2u_field32_get(unit, l2u_entry, TGIDf); 4910 } 4911 4912 if (BCM_MAC_IS_MCAST(l2caddr->mac) && 4913 !_BCM_VPN_IS_SET(l2caddr->vlan)) { 4914 l2caddr->flags |= BCM_L2_CACHE_MULTICAST; 4915 mod_in = _l2u_field32_get(unit, l2u_entry, MODULE_IDf); 4916 port_in = _l2u_field32_get(unit, l2u_entry, PORT_NUMf); 4917 l2caddr->dest_modid = mod_in; 4918 l2caddr->dest_port = port_in; 4919 port_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm, 4920 PORT_NUMf); 4921 modid_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm, 4922 MODULE_IDf); 4923 /* If MACDA is MC, HW interprets value encoded in MODULE_IDf 4924 and PORT_FIELD as L2MC_INDEX */ 4925 l2caddr->group = ((port_in & ((1 << port_field_len) - 1)) | 4926 ((mod_in & ((1 << modid_field_len) - 1)) 4927 << port_field_len)); 4928 /* Translate l2mc index */ 4929 BCM_IF_ERROR_RETURN( 4930 bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType, 4931 &rval)); 4932 if (rval) { 4933 _BCM_MULTICAST_GROUP_SET(l2caddr->group, _BCM_MULTICAST_TYPE_L2, 4934 l2caddr->group); 4935 } 4936 } 4937 4938 if (!((l2caddr->flags & BCM_L2_CACHE_TRUNK) || 4939 (l2caddr->flags & BCM_L2_CACHE_MULTICAST))) { 4940 mod_in = _l2u_field32_get(unit, l2u_entry, MODULE_IDf); 4941 port_in = _l2u_field32_get(unit, l2u_entry, PORT_NUMf); 4942 4943 if (!SOC_MODID_ADDRESSABLE(unit, mod_in)) { 4944 return BCM_E_BADID; 4945 } 4946 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4947 mod_in, port_in, &mod_out, 4948 &port_out)); 4949 l2caddr->dest_modid = mod_out; 4950 l2caddr->dest_port = port_out; 4951 } 4952 BCM_IF_ERROR_RETURN( 4953 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 4954 4955 if (_l2u_field32_get(unit, l2u_entry, RESERVED_0f)) { 4956 l2caddr->flags |= BCM_L2_CACHE_L3; 4957 } 4958 4959 if (isGport) { 4960 BCM_IF_ERROR_RETURN( 4961 _bcm_tr3_l2_cache_gport_construct(unit, l2caddr)); 4962 } 4963 4964 _l2u_mac_addr_get(unit, l2u_entry, MASKf, l2caddr->mac_mask); 4965 _l2u_field_get(unit, l2u_entry, MASKf, mask); 4966 l2caddr->vlan_mask = (mask[1] >> 16) & 0xfff; 4967 l2caddr->lookup_class = _l2u_field32_get(unit, l2u_entry, CLASS_IDf); 4968 4969 return BCM_E_NONE; 4970 } 4971 return BCM_E_UNAVAIL; 4972 } 4973 4974 /* 4975 * Function: 4976 * _bcm_tr3_l2cache_to_my_station 4977 * Purpose: 4978 * Convert an L2 API data structure to a MY_STATION_TCAM entry 4979 * Parameters: 4980 * unit Unit number 4981 * my_station_entry (OUT) MY_STATION_TCAM entry 4982 * l2caddr L2 API data structure 4983 */ 4984 STATIC void 4985 _bcm_tr3_l2cache_to_my_station(int unit, 4986 my_station_tcam_entry_t *my_station_entry, 4987 bcm_l2_cache_addr_t *l2caddr) 4988 { 4989 4990 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, VALIDf, 1); 4991 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, VLAN_IDf, 4992 l2caddr->vlan); 4993 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, VLAN_ID_MASKf, 4994 l2caddr->vlan_mask); 4995 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, my_station_entry, MAC_ADDRf, 4996 l2caddr->mac); 4997 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, my_station_entry, MAC_ADDR_MASKf, 4998 l2caddr->mac_mask); 4999 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, ING_PORT_NUMf, 5000 l2caddr->src_port); 5001 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, 5002 ING_PORT_NUM_MASKf, l2caddr->src_port_mask); 5003 5004 if (l2caddr->flags & BCM_L2_CACHE_L3) { 5005 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, 5006 IPV4_TERMINATION_ALLOWEDf, 1); 5007 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, 5008 IPV6_TERMINATION_ALLOWEDf, 1); 5009 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, 5010 ARP_RARP_TERMINATION_ALLOWEDf, 1); 5011 } 5012 5013 if (l2caddr->flags & BCM_L2_CACHE_DISCARD) { 5014 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, 5015 DISCARDf, 1); 5016 } 5017 if (l2caddr->flags & BCM_L2_CACHE_CPU) { 5018 soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, 5019 COPY_TO_CPUf, 1); 5020 } 5021 } 5022 5023 /* 5024 * Function: 5025 * _bcm_tr3_l2cache_from_my_station 5026 * Purpose: 5027 * Convert a MY_STATION_TCAM entry to an L2cache API data structure 5028 * Parameters: 5029 * unit (IN) Unit number 5030 * l2caddr (OUT) L2cache API data structure 5031 * my_station_entry MY_STATION_TCAM entry 5032 */ 5033 STATIC void 5034 _bcm_tr3_l2cache_from_my_station(int unit, bcm_l2_cache_addr_t *l2caddr, 5035 my_station_tcam_entry_t *my_station_entry) 5036 { 5037 sal_memset(l2caddr, 0, sizeof(*l2caddr)); 5038 5039 /* Valid bit is ignored here; entry is assumed valid */ 5040 5041 soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, (uint32 *)my_station_entry, 5042 MAC_ADDRf, l2caddr->mac); 5043 soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, (uint32 *)my_station_entry, 5044 MAC_ADDR_MASKf, l2caddr->mac_mask); 5045 l2caddr->vlan = soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry, 5046 VLAN_IDf); 5047 l2caddr->vlan_mask = soc_mem_field32_get(unit, MY_STATION_TCAMm, 5048 my_station_entry, VLAN_ID_MASKf); 5049 5050 l2caddr->src_port = soc_mem_field32_get(unit, MY_STATION_TCAMm, 5051 my_station_entry, ING_PORT_NUMf); 5052 5053 l2caddr->src_port_mask = soc_mem_field32_get(unit, MY_STATION_TCAMm, 5054 my_station_entry, ING_PORT_NUM_MASKf); 5055 5056 l2caddr->flags |= BCM_L2_CACHE_L3; 5057 if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry, 5058 DISCARDf)) { 5059 l2caddr->flags |= BCM_L2_CACHE_DISCARD; 5060 } 5061 if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry, 5062 COPY_TO_CPUf)) { 5063 l2caddr->flags |= BCM_L2_CACHE_CPU; 5064 } 5065 } 5066 5067 /* 5068 * Function: 5069 * _bcm_tr3_my_station_lookup 5070 * Purpose: 5071 * Perform following exact matched in MY_STATION_TCAM table: 5072 * - target entry lookup: 5073 * match the entry specified by vlan/mac and optional port 5074 * - (optional) alternate entry lookup: (when alt_index != NULL) 5075 * match the possible entry having the same vlan/mac as the target entry 5076 * Parameters: 5077 * unit Unit number 5078 * mac MAC address key 5079 * vlan VLAN id key 5080 * port Source port number key (-1 means to match any) 5081 * index_to_be_skip The index to be omit during lookup 5082 * entry_index (OUT) target entry index (if BCM_E_NONE) 5083 * available entry index or -1 (if BCM_E_NOT_FOUND) 5084 * alt_index (OUT) alternate entry index or -1 (if BCM_E_NOT_FOUND) 5085 * if alt_index is NULL, that means lookup only 5086 * Returns: 5087 * BCM_E_NONE - target entry found 5088 * BCM_E_NOT_FOUND - target entry not found 5089 * Notes: 5090 * if (target entry is found) { 5091 * entry_index: index for the matched target entry 5092 * alt_index: N/A 5093 * } else if (alternate entry is found) { 5094 * entry_index: index for the free entry to be used (-1 if table full) 5095 * alt_index: index for the matched alternate entry 5096 * *** caller needs to compare both indices, move the entry if needed 5097 * } else { 5098 * entry_index: index for the free entry to be used (-1 if table full) 5099 * alt_index: -1 5100 * } 5101 */ 5102 STATIC int 5103 _bcm_tr3_my_station_lookup(int unit, bcm_mac_t mac, bcm_vlan_t vlan, 5104 bcm_port_t port, int index_to_skip, 5105 int *entry_index, int *alt_index) 5106 { 5107 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 5108 my_station_tcam_entry_t *entry, entry0, entry1, entry2, mask0, mask1; 5109 int index0, index1, free_index, i, entry_words; 5110 int start, end, step; 5111 bcm_mac_t mac_mask; 5112 uint32 port_mask; 5113 5114 LOG_INFO(BSL_LS_BCM_L2, 5115 (BSL_META_U(unit, 5116 "_bcm_tr3_my_station_lookup: unit=%d " 5117 "mac=%02x:%02x:%02x:%02x:%02x:%02x vlan=%d port=%d " 5118 "index_to_skip=%d\n"), 5119 unit, vlan, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], 5120 port, index_to_skip)); 5121 5122 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 5123 port_mask = 5124 (1 << soc_mem_field_length(unit, MY_STATION_TCAMm, ING_PORT_NUMf)) - 1; 5125 5126 entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm); 5127 5128 /* 5129 * entry0, mask0 are for target entry 5130 * entry1, mask1 are for alternate entry 5131 * if (port == -1) 5132 * entry0 is: vlan/mac/00/fff/ffffffffffff/ff 5133 * entry1 is: vlan/mac/xx/fff/ffffffffffff/ff 5134 * start from last entry (free index needs to have larger index than 5135 * any alternate entry) 5136 * else 5137 * entry0 is: vlan/mac/port/fff/ffffffffffff/ff 5138 * entry1 is: vlan/mac/00/fff/ffffffffffff/ff 5139 * start from first entry (free index needs to have smaller index than 5140 * the alternate entry) 5141 */ 5142 sal_memset(&entry0, 0, sizeof(entry0)); 5143 soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, VALIDf, 1); 5144 soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, VLAN_IDf, vlan); 5145 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, &entry0, MAC_ADDRf, mac); 5146 soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, VLAN_ID_MASKf, 0xfff); 5147 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, &entry0, MAC_ADDR_MASKf, 5148 mac_mask); 5149 mask0 = entry0; 5150 soc_mem_field32_set(unit, MY_STATION_TCAMm, &mask0, VLAN_IDf, 0xfff); 5151 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, &mask0, MAC_ADDRf, mac_mask); 5152 soc_mem_field32_set(unit, MY_STATION_TCAMm, &mask0, ING_PORT_NUMf, 5153 port_mask); 5154 soc_mem_field32_set(unit, MY_STATION_TCAMm, &mask0, ING_PORT_NUM_MASKf, 5155 port_mask); 5156 if (alt_index != NULL) { 5157 entry1 = entry0; 5158 mask1 = mask0; 5159 } 5160 5161 if (port == -1) { 5162 start = soc_mem_index_max(unit, MY_STATION_TCAMm); 5163 end = -1; 5164 step = -1; 5165 } else { 5166 soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, ING_PORT_NUMf, 5167 port); 5168 soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, 5169 ING_PORT_NUM_MASKf, port_mask); 5170 start = 0; 5171 end = soc_mem_index_count(unit, MY_STATION_TCAMm); 5172 step = 1; 5173 } 5174 5175 if (alt_index != NULL) { 5176 if (port == -1) { 5177 soc_mem_field32_set(unit, MY_STATION_TCAMm, &mask1, ING_PORT_NUMf, 5178 0); 5179 } 5180 5181 /* entry2 is for checking VALID bit */ 5182 sal_memset(&entry2, 0, sizeof(entry2)); 5183 soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry2, VALIDf, 1); 5184 } 5185 5186 index1 = -1; 5187 free_index = -1; 5188 for (index0 = start; index0 != end; index0 += step) { 5189 /* Skip the entry that we want to move (we know it matches) */ 5190 if (index0 == index_to_skip) { 5191 continue; 5192 } 5193 5194 entry = &info->my_station_shadow[index0]; 5195 5196 /* Try matching target entry */ 5197 for (i = 0; i < entry_words; i++) { 5198 if ((entry->entry_data[i] ^ entry0.entry_data[i]) & 5199 mask0.entry_data[i]) { 5200 break; 5201 } 5202 } 5203 if (i == entry_words) { 5204 /* Target entry is found, no more action needed */ 5205 *entry_index = index0; 5206 LOG_INFO(BSL_LS_BCM_L2, 5207 (BSL_META_U(unit, 5208 "_bcm_tr3_my_station_lookup: found entry_index=%d\n"), 5209 *entry_index)); 5210 return BCM_E_NONE; 5211 } 5212 5213 if (alt_index == NULL) { /* lookup only */ 5214 continue; 5215 } 5216 5217 /* Keep track index of the first free entry */ 5218 if (free_index == -1) { 5219 for (i = 0; i < entry_words; i++) { 5220 if (entry->entry_data[i] & entry2.entry_data[i]) { 5221 break; 5222 } 5223 } 5224 if (i == entry_words) { 5225 if (index1 != -1) { 5226 /* Both free entry and alternate entry are found */ 5227 *entry_index = index0; 5228 *alt_index = index1; 5229 LOG_INFO(BSL_LS_BCM_L2, 5230 (BSL_META_U(unit, 5231 "_bcm_tr3_my_station_lookup: not found " 5232 "entry_index=%d alt_index=%d\n"), 5233 *entry_index, *alt_index)); 5234 return BCM_E_NOT_FOUND; 5235 } else { 5236 free_index = index0; 5237 continue; 5238 } 5239 } 5240 } 5241 5242 /* Try matching alternate entry. If alternate entry is found, it 5243 * implies target entry is not in the table */ 5244 for (i = 0; i < entry_words; i++) { 5245 if ((entry->entry_data[i] ^ entry1.entry_data[i]) & 5246 mask1.entry_data[i]) { 5247 break; 5248 } 5249 } 5250 if (i == entry_words) { 5251 if (free_index != -1) { 5252 /* both free entry and alternate entry are found */ 5253 *entry_index = free_index; 5254 *alt_index = index0; 5255 LOG_INFO(BSL_LS_BCM_L2, 5256 (BSL_META_U(unit, 5257 "_bcm_tr3_my_station_lookup: not found " 5258 "entry_index=%d alt_index=%d\n"), 5259 *entry_index, *alt_index)); 5260 return BCM_E_NOT_FOUND; 5261 } else { 5262 index1 = index0; 5263 continue; 5264 } 5265 } 5266 } 5267 5268 *entry_index = free_index; 5269 if (alt_index != NULL) { 5270 *alt_index = index1; 5271 } 5272 LOG_INFO(BSL_LS_BCM_L2, 5273 (BSL_META_U(unit, 5274 "_bcm_tr3_my_station_lookup: not found " 5275 "entry_index=%d alt_index=%d\n"), 5276 *entry_index, alt_index != NULL ? *alt_index : -100)); 5277 5278 return BCM_E_NOT_FOUND; 5279 } 5280 5281 /* 5282 * Function: 5283 * bcm_tr3_l2cache_myStation_set 5284 * Purpose: 5285 * Add MY_STATION_TCAM entry from L2 cache API 5286 * Parameters: 5287 * unit Unit number 5288 * index Index 5289 * l2caddr L2 cache API data structure 5290 */ 5291 int 5292 _bcm_tr3_l2cache_myStation_set(int unit, int index, bcm_l2_cache_addr_t *l2caddr) 5293 { 5294 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 5295 int rv, entry_index, alt_index; 5296 my_station_tcam_entry_t *entry; 5297 l2u_entry_t l2u_entry; 5298 bcm_vlan_t vlan; 5299 bcm_mac_t mac; 5300 bcm_port_t port; 5301 5302 VLAN_CHK_ID(unit, l2caddr->vlan); 5303 5304 soc_mem_lock(unit, MY_STATION_TCAMm); 5305 5306 entry_index = -1; 5307 entry = &info->my_station_shadow[index]; 5308 if (!soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, VALIDf)) { 5309 /* Entry is not in used */ 5310 entry_index = index; 5311 } else { 5312 /* Check if the existing entry is added by l2cache API */ 5313 rv = soc_l2u_get(unit, &l2u_entry, index); 5314 if (BCM_SUCCESS(rv) && 5315 (soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry, 5316 RESERVED_0f))) { 5317 entry_index = index; 5318 } 5319 } 5320 if (entry_index != -1) { 5321 /* The entry is not used by API other than l2cache */ 5322 sal_memset(entry, 0, sizeof(*entry)); 5323 _bcm_tr3_l2cache_to_my_station(unit, entry, l2caddr); 5324 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 5325 entry); 5326 soc_mem_unlock(unit, MY_STATION_TCAMm); 5327 return rv; 5328 } 5329 5330 /* Need to move the current entry */ 5331 vlan = soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, VLAN_IDf); 5332 soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, entry, MAC_ADDRf, mac); 5333 if (soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, 5334 ING_PORT_NUM_MASKf) == 0) { 5335 port = -1; 5336 } else { 5337 port = soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, 5338 ING_PORT_NUMf); 5339 } 5340 rv = _bcm_tr3_my_station_lookup(unit, mac, vlan, port, index, &entry_index, 5341 &alt_index); 5342 if (rv == BCM_E_NOT_FOUND && entry_index == -1) { 5343 /* No free entry available for insertion */ 5344 rv = BCM_E_FULL; 5345 } 5346 if (rv != BCM_E_NOT_FOUND) { 5347 soc_mem_unlock(unit, MY_STATION_TCAMm); 5348 return rv; 5349 } 5350 5351 if (alt_index != -1 && 5352 ((port == -1 && alt_index > entry_index) || 5353 (port != -1 && alt_index < entry_index))) { 5354 /* Free entry is available for moving the target entry and alternate 5355 * entry exists. However need to swap these 2 entries to maintain 5356 * proper lookup precedence */ 5357 info->my_station_shadow[entry_index] = 5358 info->my_station_shadow[alt_index]; 5359 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, entry_index, 5360 &info->my_station_shadow[entry_index]); 5361 if (BCM_FAILURE(rv)) { 5362 soc_mem_unlock(unit, MY_STATION_TCAMm); 5363 return rv; 5364 } 5365 entry_index = alt_index; 5366 } 5367 5368 /* Move the entry at specified index to the available free location */ 5369 info->my_station_shadow[entry_index] = *entry; 5370 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, entry_index, 5371 entry); 5372 if (BCM_FAILURE(rv)) { 5373 soc_mem_unlock(unit, MY_STATION_TCAMm); 5374 return rv; 5375 } 5376 5377 /* Add the new entry */ 5378 sal_memset(entry, 0, sizeof(*entry)); 5379 _bcm_tr3_l2cache_to_my_station(unit, entry, l2caddr); 5380 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 5381 entry); 5382 5383 soc_mem_unlock(unit, MY_STATION_TCAMm); 5384 return rv; 5385 } 5386 5387 /* 5388 * Function: 5389 * _bcm_tr3_l2cache_myStation_delete 5390 * Purpose: 5391 * Delete l2cache entry from myStation TCAM 5392 * Parameters: 5393 * unit - [IN] Unit number 5394 * index - [IN] index to a table 5395 */ 5396 STATIC int 5397 _bcm_tr3_l2cache_myStation_delete(int unit, int index) 5398 { 5399 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 5400 int rv, i, entry_words; 5401 my_station_tcam_entry_t *entry; 5402 l2u_entry_t l2u_entry; 5403 uint32 *l3_mask, *tunnel_mask; 5404 5405 l3_mask = info->my_station_l3_mask.entry_data; 5406 tunnel_mask = info->my_station_tunnel_mask.entry_data; 5407 entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm); 5408 5409 soc_mem_lock(unit, MY_STATION_TCAMm); 5410 5411 entry = &info->my_station_shadow[index]; 5412 5413 /* Check if the entry has L3 related flag enabled */ 5414 for (i = 0; i < entry_words; i++) { 5415 if (entry->entry_data[i] & l3_mask[i]) { 5416 break; 5417 } 5418 } 5419 if (i == entry_words) { 5420 soc_mem_unlock(unit, MY_STATION_TCAMm); 5421 return BCM_E_NOT_FOUND; 5422 } 5423 5424 /* Check if the entry is valid */ 5425 if (!soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, VALIDf)) { 5426 soc_mem_unlock(unit, MY_STATION_TCAMm); 5427 return BCM_E_NOT_FOUND; 5428 } 5429 5430 /* Check if the entry is added by l2cache API */ 5431 rv = soc_l2u_get(unit, &l2u_entry, index); 5432 if (BCM_FAILURE(rv)) { 5433 soc_mem_unlock(unit, MY_STATION_TCAMm); 5434 return rv; 5435 } 5436 if (!soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry, 5437 RESERVED_0f)) { 5438 return BCM_E_NOT_FOUND; 5439 } 5440 /* Check to see if we need to delete or modify the entry */ 5441 for (i = 0; i < entry_words; i++) { 5442 if (entry->entry_data[i] & tunnel_mask[i]) { 5443 break; 5444 } 5445 } 5446 if (i == entry_words) { 5447 /* Delete the entry if no tunnel related flag is enabled */ 5448 sal_memset(entry, 0, sizeof(*entry)); 5449 } else { 5450 /* Modify the entry if any tunnel related flag is enabled */ 5451 for (i = 0; i < entry_words; i++) { 5452 entry->entry_data[i] &= ~l3_mask[i]; 5453 } 5454 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, DISCARDf, 0); 5455 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, COPY_TO_CPUf, 0); 5456 } 5457 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, entry); 5458 5459 soc_mem_unlock(unit, MY_STATION_TCAMm); 5460 return rv; 5461 } 5462 5463 /* 5464 * Function: 5465 * _bcm_tr3_l2cache_myStation_get 5466 * Purpose: 5467 * Get l2cache entry for L2 processing. 5468 * Parameters: 5469 * unit - [IN] Unit number 5470 * index - [IN] index to a table 5471 * l2addr - [OUT] pointer to l2_cache structure to fill 5472 */ 5473 STATIC int 5474 _bcm_tr3_l2cache_myStation_get(int unit, int index, bcm_l2_cache_addr_t *l2caddr) 5475 { 5476 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 5477 int i, entry_words; 5478 my_station_tcam_entry_t *entry; 5479 l2u_entry_t l2u_entry; 5480 uint32 *l3_mask; 5481 5482 l3_mask = info->my_station_l3_mask.entry_data; 5483 entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm); 5484 5485 entry = &info->my_station_shadow[index]; 5486 5487 /* Check if the entry has L3 related flag enabled */ 5488 for (i = 0; i < entry_words; i++) { 5489 if (entry->entry_data[i] & l3_mask[i]) { 5490 break; 5491 } 5492 } 5493 if (i == entry_words) { 5494 return BCM_E_NOT_FOUND; 5495 } 5496 5497 /* Check if the entry is valid */ 5498 if (!soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, VALIDf)) { 5499 return BCM_E_NOT_FOUND; 5500 } 5501 5502 /* Check if the entry is added by l2cache API */ 5503 SOC_IF_ERROR_RETURN(soc_l2u_get(unit, &l2u_entry, index)); 5504 if (! soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry, 5505 RESERVED_0f)) { 5506 return BCM_E_NOT_FOUND; 5507 } 5508 5509 _bcm_tr3_l2cache_from_my_station(unit, l2caddr, entry); 5510 5511 return BCM_E_NONE; 5512 5513 } 5514 5515 5516 /* 5517 * Function: 5518 * _bcm_tr3_l2_learn_limit_system_get 5519 * Purpose: 5520 * Get MAC learn limit for a system 5521 * Parameters: 5522 * unit - BCM unit number 5523 * flags - Action bitmask 5524 * limit - System limit of MAC addresses to learn 5525 * Negative if limit disabled 5526 * Returns: 5527 * BCM_E_XXX 5528 */ 5529 STATIC int 5530 _bcm_tr3_l2_learn_limit_system_get(int unit, uint32 *flags, int *limit) 5531 { 5532 uint32 rval; 5533 5534 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval)); 5535 *flags &= ~(BCM_L2_LEARN_LIMIT_ACTION_DROP | 5536 BCM_L2_LEARN_LIMIT_ACTION_CPU); 5537 if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, 5538 SYS_OVER_LIMIT_TOCPUf)) { 5539 *flags |= BCM_L2_LEARN_LIMIT_ACTION_CPU; 5540 } 5541 if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, 5542 SYS_OVER_LIMIT_DROPf)) { 5543 *flags |= BCM_L2_LEARN_LIMIT_ACTION_DROP; 5544 } 5545 /* 5546 * When MAC limiting is enabled, ENABLE_INTERNAL_L2_ENTRYf 5547 * is always set. So only checking for this field 5548 * to retrieve MAC limit value 5549 */ 5550 if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, 5551 ENABLE_INTERNAL_L2_ENTRYf)) { 5552 *limit = soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, 5553 SYS_LIMITf); 5554 } else { 5555 *limit = -1; 5556 } 5557 5558 return BCM_E_NONE; 5559 } 5560 5561 /* 5562 * Function: 5563 * _bcm_tr3_l2_learn_limit_get 5564 * Purpose: 5565 * Get MAC learn limit for a port/trunk/vlan 5566 * Parameters: 5567 * unit - BCM unit number 5568 * mem - PORT_OR_TRUNK_MAC_LIMITm or VLAN_OR_VFI_MAC_LIMITm 5569 * index - for PORT_OR_TRUNK_MAC_LIMITm 5570 * 0 - 127: trunk identifier 5571 * 128 - 181: port identifier + 128 5572 * for VLAN_OR_VFI_MAC_LIMITm 5573 * 0 - 4095: VLAN identifier 5574 * 4096 - 5119: virtual forwarding instance + 4096 5575 * flags - Action bitmask 5576 * limit - Max number of MAC addresses can be learned for the specified 5577 * identifier 5578 * Negative if limit disabled (i.e. unlimit) 5579 * Returns: 5580 * BCM_E_XXX 5581 */ 5582 STATIC int 5583 _bcm_tr3_l2_learn_limit_get(int unit, soc_mem_t mem, int index, uint32* flags, 5584 int* limit) 5585 { 5586 uint32 entry[SOC_MAX_MEM_WORDS]; 5587 5588 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry)); 5589 *flags &= ~(BCM_L2_LEARN_LIMIT_ACTION_DROP | 5590 BCM_L2_LEARN_LIMIT_ACTION_CPU); 5591 if (soc_mem_field32_get(unit, mem, &entry, OVER_LIMIT_DROPf)) { 5592 *flags |= BCM_L2_LEARN_LIMIT_ACTION_DROP; 5593 } 5594 if (soc_mem_field32_get(unit, mem, &entry, OVER_LIMIT_TOCPUf)) { 5595 *flags |= BCM_L2_LEARN_LIMIT_ACTION_CPU; 5596 } 5597 *limit = soc_mem_field32_get(unit, mem, &entry, LIMITf); 5598 5599 return BCM_E_NONE; 5600 } 5601 5602 5603 /* 5604 * Function: 5605 * _bcm_tr3_l2_learn_limit_set 5606 * Purpose: 5607 * Set MAC learn limit for a port/trunk/vlan 5608 * Parameters: 5609 * unit - BCM unit number 5610 * mem - PORT_OR_TRUNK_MAC_LIMITm or VLAN_OR_VFI_MAC_LIMITm 5611 * index - for PORT_OR_TRUNK_MAC_LIMITm 5612 * 0 - 127: trunk identifier 5613 * 128 - 181: port identifier + 128 5614 * for VLAN_OR_VFI_MAC_LIMITm 5615 * 0 - 4095: VLAN identifier 5616 * 4096 - 5119: virtual forwarding instance + 4096 5617 * flags - Action bitmask 5618 * limit - Max number of MAC addresses can be learned for the specified 5619 * identifier 5620 * Negative if limit disabled (i.e. unlimit) 5621 * Returns: 5622 * BCM_E_XXX 5623 */ 5624 STATIC int 5625 _bcm_tr3_l2_learn_limit_set(int unit, soc_mem_t mem, int index, uint32 flags, 5626 int limit) 5627 { 5628 uint32 entry[SOC_MAX_MEM_WORDS], rval; 5629 int rv; 5630 port_or_trunk_mac_limit_entry_t init_entry; 5631 int32 max_limit; 5632 5633 if (limit < 0) { 5634 soc_mem_lock(unit, mem); 5635 sal_memcpy(&init_entry, soc_mem_entry_null(unit,mem), 5636 sizeof(init_entry)); 5637 5638 /* Reset Limit value is different than soc_mem_entry_null 5639 * for devices with ESM */ 5640 max_limit = BCM_MAC_LIMIT_MAX(unit); 5641 5642 soc_mem_field32_set(unit, mem, &init_entry, LIMITf, max_limit); 5643 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &init_entry); 5644 5645 soc_mem_unlock(unit, mem); 5646 return rv; 5647 } 5648 5649 soc_mem_lock(unit, mem); 5650 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry); 5651 if (BCM_SUCCESS(rv)) { 5652 soc_mem_field32_set(unit, mem, &entry, OVER_LIMIT_TOCPUf, 5653 flags & BCM_L2_LEARN_LIMIT_ACTION_CPU ? 1 : 0); 5654 soc_mem_field32_set(unit, mem, &entry, OVER_LIMIT_DROPf, 5655 flags & BCM_L2_LEARN_LIMIT_ACTION_DROP ? 1 : 0); 5656 soc_mem_field32_set(unit, mem, &entry, LIMITf, limit); 5657 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry); 5658 } 5659 soc_mem_unlock(unit, mem); 5660 5661 if (BCM_FAILURE(rv)) { 5662 return rv; 5663 } 5664 5665 /* Registers RSEL1_MISC_CONTROL and SYS_MAC_LIMIT_CONTROL are 5666 * identical in config. Enable if any of Port, Trunk, Vlan, 5667 * VFI, or system learn limits are enabled, disable only when 5668 * system limit is disabled */ 5669 5670 BCM_IF_ERROR_RETURN(READ_RSEL1_MISC_CONTROLr(unit, &rval)); 5671 soc_reg_field_set(unit, RSEL1_MISC_CONTROLr, &rval, 5672 MAC_LIMIT_ENABLEf, 1); 5673 BCM_IF_ERROR_RETURN(WRITE_RSEL1_MISC_CONTROLr(unit, rval)); 5674 5675 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval)); 5676 5677 /* 5678 * Enable MAC limiting for internal L2 and also for external L2 5679 * if it is available 5680 */ 5681 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 5682 ENABLE_INTERNAL_L2_ENTRYf, 1); 5683 if (soc_feature(unit, soc_feature_esm_support)) { 5684 if ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_1m) && 5685 (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_1m))) || 5686 ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_2m) && 5687 (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_2m))))) { 5688 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 5689 ENABLE_EXTERNAL_L2_ENTRYf, 1); 5690 } 5691 } 5692 return (WRITE_SYS_MAC_LIMIT_CONTROLr(unit, rval)); 5693 } 5694 5695 /* 5696 * Function: 5697 * _bcm_tr3_l2_to_my_station 5698 * Purpose: 5699 * Convert an L2 API data structure to a Triumph3 MY_STATION_TCAM entry 5700 * Parameters: 5701 * unit Unit number 5702 * entry (OUT) MY_STATION_TCAM entry 5703 * l2addr L2 API data structure 5704 */ 5705 STATIC void 5706 _bcm_tr3_l2_to_my_station(int unit, my_station_tcam_entry_t *entry, 5707 bcm_l2_addr_t *l2addr, int incl_key_mask) 5708 { 5709 bcm_mac_t mac_mask; 5710 uint32 fval; 5711 5712 if (incl_key_mask) { 5713 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VALIDf, 1); 5714 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VLAN_IDf, 5715 l2addr->vid); 5716 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VLAN_ID_MASKf, 0xfff); 5717 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, entry, MAC_ADDRf, 5718 l2addr->mac); 5719 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 5720 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, entry, MAC_ADDR_MASKf, 5721 mac_mask); 5722 } 5723 5724 fval = l2addr->flags & BCM_L2_L3LOOKUP ? 1: 0; 5725 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, 5726 IPV4_TERMINATION_ALLOWEDf, fval); 5727 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, 5728 IPV6_TERMINATION_ALLOWEDf, fval); 5729 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, 5730 ARP_RARP_TERMINATION_ALLOWEDf, fval); 5731 5732 fval = l2addr->flags & BCM_L2_DISCARD_DST ? 1 : 0; 5733 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, DISCARDf, fval); 5734 fval = l2addr->flags & BCM_L2_COPY_TO_CPU ? 1 : 0; 5735 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, COPY_TO_CPUf, fval); 5736 } 5737 5738 /* 5739 * Function: 5740 * _bcm_tr3_l2_from_my_station 5741 * Purpose: 5742 * Convert a Triumph3 MY_STATION_TCAM entry to an L2 API data structure 5743 * Parameters: 5744 * unit Unit number 5745 * l2addr (OUT) L2 API data structure 5746 * my_station_entry MY_STATION_TCAM entry 5747 */ 5748 STATIC void 5749 _bcm_tr3_l2_from_my_station(int unit, bcm_l2_addr_t *l2addr, 5750 my_station_tcam_entry_t *my_station_entry) 5751 { 5752 sal_memset(l2addr, 0, sizeof(*l2addr)); 5753 5754 /* Valid bit is ignored here; entry is assumed valid */ 5755 5756 soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, (uint32 *)my_station_entry, 5757 MAC_ADDRf, l2addr->mac); 5758 l2addr->vid = soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry, 5759 VLAN_IDf); 5760 5761 if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry, 5762 IPV4_TERMINATION_ALLOWEDf)) { 5763 l2addr->flags |= BCM_L2_L3LOOKUP; 5764 } 5765 5766 if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry, 5767 DISCARDf)) { 5768 l2addr->flags |= BCM_L2_DISCARD_DST; 5769 } 5770 if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry, 5771 COPY_TO_CPUf)) { 5772 l2addr->flags |= BCM_L2_COPY_TO_CPU; 5773 } 5774 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT; 5775 } 5776 5777 /* 5778 * Function: 5779 * bcm_tr3_l2_myStation_get 5780 * Purpose: 5781 * Get (MAC, VLAN) entry for L2 processing. 5782 * Frames destined to (MAC, VLAN) is subjected to L2/L3 processing. 5783 * Parameters: 5784 * unit - Unit number 5785 * mac - MAC address 5786 * vlan - VLAN ID 5787 */ 5788 int 5789 _bcm_tr3_l2_myStation_get (int unit, bcm_mac_t mac, bcm_vlan_t vid, 5790 bcm_l2_addr_t *l2addr) 5791 { 5792 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 5793 int index, i, entry_words; 5794 my_station_tcam_entry_t *entry; 5795 l2u_entry_t l2u_entry; 5796 uint32 *l3_mask; 5797 5798 /* Handle VFIs as well as invalid vlans */ 5799 if (vid > BCM_VLAN_MAX) { 5800 return BCM_E_NOT_FOUND; 5801 } 5802 5803 l3_mask = info->my_station_l3_mask.entry_data; 5804 entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm); 5805 5806 BCM_IF_ERROR_RETURN 5807 (_bcm_tr3_my_station_lookup(unit, mac, vid, -1, -1, &index, NULL)); 5808 5809 entry = &info->my_station_shadow[index]; 5810 5811 /* Check if the entry has L3 related flag enabled */ 5812 for (i = 0; i < entry_words; i++) { 5813 if (entry->entry_data[i] & l3_mask[i]) { 5814 break; 5815 } 5816 } 5817 if (i == entry_words) { 5818 return BCM_E_NOT_FOUND; 5819 } 5820 5821 /* Check if the entry is not added by l2cache API */ 5822 SOC_IF_ERROR_RETURN(soc_l2u_get(unit, &l2u_entry, index)); 5823 if (soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry, 5824 RESERVED_0f)) { 5825 return BCM_E_NOT_FOUND; 5826 } 5827 5828 _bcm_tr3_l2_from_my_station(unit, l2addr, entry); 5829 5830 return BCM_E_NONE; 5831 } 5832 5833 /* 5834 * Function: 5835 * _bcm_tr3_l2_myStation_add 5836 * Purpose: 5837 * Add l2 entry for L3 processing. 5838 * Parameters: 5839 * unit - [IN] Unit number 5840 * l2addr - [IN] pointer to l2_addr structure 5841 */ 5842 STATIC int 5843 _bcm_tr3_l2_myStation_add(int unit, bcm_l2_addr_t *l2addr) 5844 { 5845 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 5846 int rv, index, alt_index; 5847 my_station_tcam_entry_t *entry; 5848 l2u_entry_t l2u_entry; 5849 5850 VLAN_CHK_ID(unit, l2addr->vid); 5851 5852 soc_mem_lock(unit, MY_STATION_TCAMm); 5853 5854 rv = _bcm_tr3_my_station_lookup(unit, l2addr->mac, l2addr->vid, -1, -1, 5855 &index, &alt_index); 5856 if (BCM_SUCCESS(rv)) { 5857 /* Check if the entry is not added by l2cache API */ 5858 rv = soc_l2u_get(unit, &l2u_entry, index); 5859 if (BCM_FAILURE(rv)) { 5860 soc_mem_unlock(unit, MY_STATION_TCAMm); 5861 return rv; 5862 } 5863 if (soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry, 5864 RESERVED_0f)) { 5865 soc_mem_unlock(unit, MY_STATION_TCAMm); 5866 return BCM_E_EXISTS; 5867 } 5868 /* Entry exist, update the entry */ 5869 entry = &info->my_station_shadow[index]; 5870 _bcm_tr3_l2_to_my_station(unit, entry, l2addr, FALSE); 5871 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 5872 entry); 5873 } else if (rv == BCM_E_NOT_FOUND && index == -1) { 5874 /* No free entry available for insertion */ 5875 rv = BCM_E_FULL; 5876 } 5877 if (rv != BCM_E_NOT_FOUND) { 5878 soc_mem_unlock(unit, MY_STATION_TCAMm); 5879 return rv; 5880 } 5881 5882 if (alt_index > index) { 5883 /* Free entry is available for new entry insertion and alternate entry 5884 * exists. However need to swap these 2 entries to maintain proper 5885 * lookup precedence */ 5886 info->my_station_shadow[index] = info->my_station_shadow[alt_index]; 5887 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 5888 &info->my_station_shadow[index]); 5889 if (BCM_FAILURE(rv)) { 5890 soc_mem_unlock(unit, MY_STATION_TCAMm); 5891 return rv; 5892 } 5893 index = alt_index; 5894 } 5895 5896 /* Add the new entry */ 5897 entry = &info->my_station_shadow[index]; 5898 sal_memset(entry, 0, sizeof(*entry)); 5899 _bcm_tr3_l2_to_my_station(unit, entry, l2addr, TRUE); 5900 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, entry); 5901 5902 soc_mem_unlock(unit, MY_STATION_TCAMm); 5903 return rv; 5904 } 5905 5906 /* 5907 * Function: 5908 * _bcm_tr3_l2_myStation_delete 5909 * Purpose: 5910 * Delete an l2 entry for L3 processing. 5911 * Parameters: 5912 * unit - (IN) Unit number 5913 * mac - (IN) MAC address to delete 5914 * vid - (IN) VLAN id 5915 * index_used - (OUT) index of entry that was deleted 5916 */ 5917 STATIC int 5918 _bcm_tr3_l2_myStation_delete(int unit, bcm_mac_t mac, bcm_vlan_t vid, 5919 int *index_used) 5920 { 5921 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 5922 int rv, index, i, entry_words; 5923 my_station_tcam_entry_t *entry; 5924 l2u_entry_t l2u_entry; 5925 uint32 *l3_mask, *tunnel_mask; 5926 5927 VLAN_CHK_ID(unit, vid); 5928 5929 l3_mask = info->my_station_l3_mask.entry_data; 5930 tunnel_mask = info->my_station_tunnel_mask.entry_data; 5931 entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm); 5932 5933 soc_mem_lock(unit, MY_STATION_TCAMm); 5934 5935 rv = _bcm_tr3_my_station_lookup(unit, mac, vid, -1, -1, &index, NULL); 5936 if (BCM_SUCCESS(rv)) { 5937 entry = &info->my_station_shadow[index]; 5938 5939 /* Check if the entry has L3 related flag enabled */ 5940 for (i = 0; i < entry_words; i++) { 5941 if (entry->entry_data[i] & l3_mask[i]) { 5942 break; 5943 } 5944 } 5945 if (i == entry_words) { 5946 soc_mem_unlock(unit, MY_STATION_TCAMm); 5947 return BCM_E_NOT_FOUND; 5948 } 5949 5950 /* Check if the entry is not added by l2cache API */ 5951 rv = soc_l2u_get(unit, &l2u_entry, index); 5952 if (BCM_FAILURE(rv)) { 5953 soc_mem_unlock(unit, MY_STATION_TCAMm); 5954 return rv; 5955 } 5956 5957 if (soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry, 5958 RESERVED_0f)) { 5959 soc_mem_unlock(unit, MY_STATION_TCAMm); 5960 return BCM_E_NOT_FOUND; 5961 } 5962 /* Check to see if we need to delete or modify the entry */ 5963 for (i = 0; i < entry_words; i++) { 5964 if (entry->entry_data[i] & tunnel_mask[i]) { 5965 break; 5966 } 5967 } 5968 if (i == entry_words) { 5969 /* Delete the entry if no tunnel related flag is enabled */ 5970 sal_memset(entry, 0, sizeof(*entry)); 5971 } else { 5972 /* Modify the entry if any tunnel related flag is enabled */ 5973 for (i = 0; i < entry_words; i++) { 5974 entry->entry_data[i] &= ~l3_mask[i]; 5975 } 5976 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, DISCARDf, 0); 5977 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, COPY_TO_CPUf, 5978 0); 5979 } 5980 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 5981 entry); 5982 } 5983 5984 soc_mem_unlock(unit, MY_STATION_TCAMm); 5985 return rv; 5986 } 5987 5988 /* 5989 * Function: 5990 * _bcm_tr3_l2_bookkeeping_info_init 5991 * Purpose: 5992 * Initialize the Tr3 L2 book keeping info 5993 * Parameters: 5994 * unit - (IN) Unit number 5995 */ 5996 STATIC int 5997 _bcm_tr3_l2_bookkeeping_info_init(int unit) 5998 { 5999 int num_station, alloc_size; 6000 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 6001 6002 num_station = soc_mem_index_count(unit, MY_STATION_TCAMm); 6003 alloc_size = sizeof(my_station_tcam_entry_t) * num_station; 6004 6005 if (NULL == info->my_station_shadow) { 6006 info->my_station_shadow = 6007 sal_alloc(alloc_size, "my station shadow"); 6008 if (info->my_station_shadow == NULL) { 6009 return BCM_E_MEMORY; 6010 } 6011 sal_memset(info->my_station_shadow, 0, alloc_size); 6012 } 6013 6014 /* L3 flags */ 6015 soc_mem_field32_set(unit, MY_STATION_TCAMm, 6016 &info->my_station_l3_mask, 6017 IPV4_TERMINATION_ALLOWEDf, 1); 6018 soc_mem_field32_set(unit, MY_STATION_TCAMm, 6019 &info->my_station_l3_mask, 6020 IPV6_TERMINATION_ALLOWEDf, 1); 6021 soc_mem_field32_set(unit, MY_STATION_TCAMm, 6022 &info->my_station_l3_mask, 6023 ARP_RARP_TERMINATION_ALLOWEDf, 1); 6024 /* Tunnel flags */ 6025 soc_mem_field32_set(unit, MY_STATION_TCAMm, 6026 &info->my_station_tunnel_mask, 6027 MIM_TERMINATION_ALLOWEDf, 1); 6028 soc_mem_field32_set(unit, MY_STATION_TCAMm, 6029 &info->my_station_tunnel_mask, 6030 MPLS_TERMINATION_ALLOWEDf, 1); 6031 soc_mem_field32_set(unit, MY_STATION_TCAMm, 6032 &info->my_station_tunnel_mask, 6033 TRILL_TERMINATION_ALLOWEDf, 1); 6034 6035 return BCM_E_NONE; 6036 } 6037 6038 STATIC int 6039 _bcm_tr3_l2_cbl_init(int unit) { 6040 6041 soc_mem_t mem; 6042 int entry_words; 6043 int index_max; 6044 union { 6045 port_cbl_table_entry_t port_cbl[128]; 6046 uint32 w[1]; 6047 } entry; 6048 void *entries[1]; 6049 soc_profile_mem_t *profile; 6050 int module; 6051 uint32 profile_index; 6052 int field_len; 6053 6054 /* Create profile for PORT_CBL_TABLE table */ 6055 if (!SOC_WARM_BOOT(unit)) { 6056 BCM_IF_ERROR_RETURN(soc_mem_clear(unit, PORT_CBL_TABLEm, 6057 COPYNO_ALL, FALSE)); 6058 } 6059 if (_bcm_l2_tr3_port_cbl_profile[unit] == NULL) { 6060 _bcm_l2_tr3_port_cbl_profile[unit] = 6061 sal_alloc(sizeof(soc_profile_mem_t), 6062 "PORT_CBL_TABLE profile"); 6063 if (_bcm_l2_tr3_port_cbl_profile[unit] == NULL) { 6064 return BCM_E_MEMORY; 6065 } 6066 soc_profile_mem_t_init(_bcm_l2_tr3_port_cbl_profile[unit]); 6067 } 6068 profile = _bcm_l2_tr3_port_cbl_profile[unit]; 6069 mem = PORT_CBL_TABLEm; 6070 entry_words = sizeof(port_cbl_table_entry_t) / sizeof(uint32); 6071 field_len = soc_mem_field_length(unit, PORT_CBL_TABLE_MODBASEm, 6072 BASEf); 6073 /* coverity[large_shift : FALSE] */ 6074 index_max = (1 << (field_len - 1)) - 1; 6075 entries[0] = &entry; 6076 sal_memset(&entry.port_cbl[0], 0, sizeof(entry.port_cbl[0])); 6077 field_len = soc_mem_field_length(unit, PORT_CBL_TABLEm, 6078 PORT_LEARNING_CLASSf); 6079 soc_mem_field32_set(unit, PORT_CBL_TABLEm, &entry.port_cbl[0], 6080 PORT_LEARNING_CLASSf, (1 << field_len) - 1); 6081 6082 BCM_IF_ERROR_RETURN 6083 (soc_profile_mem_index_create(unit, &mem, &entry_words, NULL, 6084 &index_max, entries, 1, 6085 profile)); 6086 6087 if (!SOC_WARM_BOOT(unit)) { 6088 BCM_IF_ERROR_RETURN(soc_mem_clear(unit, PORT_CBL_TABLE_MODBASEm, 6089 COPYNO_ALL, FALSE)); 6090 sal_memset(entry.port_cbl, 0, sizeof(entry.port_cbl)); 6091 BCM_IF_ERROR_RETURN 6092 (soc_profile_mem_add(unit, profile, entries, 6093 SOC_PORT_ADDR_MAX(unit) + 1, 6094 &profile_index)); 6095 for (module = 1; module <= SOC_MODID_MAX(unit); module++) { 6096 SOC_IF_ERROR_RETURN 6097 (soc_profile_mem_reference 6098 (unit, profile, profile_index, 6099 SOC_PORT_ADDR_MAX(unit) + 1)); 6100 } 6101 } 6102 #ifdef BCM_WARM_BOOT_SUPPORT 6103 else { 6104 port_cbl_table_modbase_entry_t base_entry; 6105 6106 for (module = 0; module <= SOC_MODID_MAX(unit); module++) { 6107 SOC_IF_ERROR_RETURN 6108 (soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm, 6109 MEM_BLOCK_ANY, module, &base_entry)); 6110 profile_index = 6111 soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm, 6112 &base_entry, BASEf); 6113 SOC_IF_ERROR_RETURN 6114 (soc_profile_mem_reference 6115 (unit, profile, profile_index, 6116 SOC_PORT_ADDR_MAX(unit) + 1)); 6117 } 6118 } 6119 #endif /* BCM_WARM_BOOT_SUPPORT */ 6120 6121 return BCM_E_NONE; 6122 } 6123 6124 #ifdef BCM_WARM_BOOT_SUPPORT 6125 /* 6126 * Function: 6127 * _bcm_tr3_l2_reinit 6128 * Purpose: 6129 * Recover L2_INFO s/w state for TR3 6130 * Parameters: 6131 * unit - (IN) Unit number. 6132 * Returns: 6133 * BCM_E_xxx 6134 * Notes: 6135 */ 6136 STATIC int 6137 _bcm_tr3_l2_reinit(int unit) 6138 { 6139 int i, num_station; 6140 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 6141 my_station_tcam_entry_t entry; 6142 bcm_mac_t mac_addr; 6143 bcm_vlan_t vid; 6144 bcm_l2_addr_t l2addr; 6145 int rv; 6146 6147 /* Compute hash for each entry */ 6148 num_station = soc_mem_index_count(unit, MY_STATION_TCAMm); 6149 for (i = 0; i < num_station; i++) { 6150 6151 sal_memcpy(&entry, soc_mem_entry_null(unit, MY_STATION_TCAMm), 6152 sizeof(my_station_tcam_entry_t)); 6153 BCM_IF_ERROR_RETURN 6154 (READ_MY_STATION_TCAMm(unit, MEM_BLOCK_ANY, i, &entry)); 6155 if (!soc_mem_field32_get(unit, 6156 MY_STATION_TCAMm, &entry, VALIDf)) { 6157 continue; 6158 } 6159 6160 soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, 6161 &entry, MAC_ADDRf, mac_addr); 6162 vid = soc_mem_field32_get(unit, MY_STATION_TCAMm, 6163 &entry, VLAN_IDf); 6164 6165 rv = _bcm_tr3_l2_addr_get(unit, mac_addr, vid, TRUE, &l2addr); 6166 if (BCM_FAILURE(rv)) { 6167 continue; 6168 } 6169 6170 sal_memcpy(&info->my_station_shadow[i], &entry, 6171 sizeof(my_station_tcam_entry_t)); 6172 } 6173 6174 return BCM_E_NONE; 6175 } 6176 #endif /* BCM_WARM_BOOT_SUPPORT */ 6177 6178 /* 6179 * Function: 6180 * bcm_tr3_l2_init 6181 * Purpose: 6182 * Initialize the BCM L2 subsystem. 6183 * Parameters: 6184 * unit - (IN) Unit number. 6185 * Returns: 6186 * BCM_E_xxx 6187 * Notes: 6188 */ 6189 int 6190 bcm_tr3_l2_init(int unit) 6191 { 6192 int rv; 6193 int frozen; 6194 uint32 regval = 0; 6195 6196 BCM_IF_ERROR_RETURN(soc_tr3_l2_is_frozen(unit, &frozen)); 6197 if (TRUE == frozen) { 6198 return BCM_E_BUSY; 6199 } 6200 6201 BCM_IF_ERROR_RETURN(bcm_tr3_l2_detach(unit)); 6202 6203 /* First, determine which memories are active in this device */ 6204 _bcm_tr3_l2_mems_valid[unit] = 0; 6205 if (0 < soc_mem_index_count(unit, L2_ENTRY_1m)) { 6206 /* The ISM tables are active, so include them */ 6207 _bcm_tr3_l2_mems_valid[unit] |= _BCM_TR3_L2_SELECT_INTERNAL; 6208 } 6209 if (soc_feature(unit, soc_feature_esm_support)) { 6210 if (SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_1m) && 6211 (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_1m))) { 6212 /* The ESM standard table is active, so include it */ 6213 _bcm_tr3_l2_mems_valid[unit] |= 6214 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1; 6215 } 6216 if ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_2m)) && 6217 (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_2m))) { 6218 /* The ESM wide table is active, so include it */ 6219 _bcm_tr3_l2_mems_valid[unit] |= 6220 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2; 6221 } 6222 } 6223 6224 /* If, only ESM is available and no ISM, then learn on ESM tables */ 6225 if (!(_bcm_tr3_l2_mems_valid[unit] & _BCM_TR3_L2_SELECT_INTERNAL)) { 6226 if ((_bcm_tr3_l2_mems_valid[unit] & 6227 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) || 6228 (_bcm_tr3_l2_mems_valid[unit] & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2)) 6229 { 6230 BCM_IF_ERROR_RETURN(READ_LEARN_CONTROLr(unit, ®val)); 6231 soc_reg_field_set(unit, LEARN_CONTROLr, ®val, 6232 EXTERNAL_L2_ENTRYf, 1); 6233 BCM_IF_ERROR_RETURN(WRITE_LEARN_CONTROLr(unit, regval)); 6234 } 6235 } 6236 6237 /* Initialize memory accelation structures */ 6238 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_memacc_init(unit)); 6239 6240 /* Clear the HW state and associated SW data */ 6241 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_hw_init(unit)); 6242 6243 if (!SOC_WARM_BOOT(unit)) { 6244 /* 6245 * Init L2 cache 6246 */ 6247 rv = bcm_tr3_l2_cache_init(unit); 6248 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 6249 return rv; 6250 } 6251 } 6252 6253 /* 6254 * Init L2 learn limit 6255 */ 6256 rv = _bcm_tr3_l2_learn_limit_init(unit); 6257 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 6258 return rv; 6259 } 6260 6261 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cbl_init(unit)); 6262 6263 /* Create callback data structure */ 6264 _bcm_tr3_l2_data[unit] = sal_alloc(sizeof(*_bcm_tr3_l2_data[unit]), 6265 "BCM TR3 L2 callback data"); 6266 if (NULL == _bcm_tr3_l2_data[unit]) { 6267 return BCM_E_MEMORY; 6268 } 6269 sal_memset(_bcm_tr3_l2_data[unit], 0, sizeof(*_bcm_tr3_l2_data[unit])); 6270 6271 if (SOC_CONTROL(unit)->l2x_age_interval != 0) { 6272 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit)); 6273 } 6274 6275 /* L2 book keeping info init */ 6276 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_bookkeeping_info_init(unit)); 6277 6278 if(soc_property_get(unit, spn_RUN_L2_SW_AGING, 0)) { 6279 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, 0)); 6280 } 6281 if (soc_feature(unit, soc_feature_l2_overflow)) { 6282 if(soc_property_get(unit, spn_L2_OVERFLOW_EVENT, 0)) { 6283 SOC_CONTROL_LOCK(unit); 6284 SOC_CONTROL(unit)->l2_overflow_enable = TRUE; 6285 SOC_CONTROL_UNLOCK(unit); 6286 } 6287 } 6288 _bcm_tr3_l2_init[unit] = 1; /* some positive value */ 6289 6290 6291 BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_control_init(unit)); 6292 6293 #ifdef BCM_WARM_BOOT_SUPPORT 6294 if (SOC_WARM_BOOT(unit)) { 6295 BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_reload(unit)); 6296 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_reinit(unit)); 6297 6298 } 6299 #endif 6300 6301 return BCM_E_NONE; 6302 } 6303 6304 /* 6305 * Function: 6306 * bcm_tr3_l2_clear 6307 * Purpose: 6308 * Clear the BCM L2 subsystem. 6309 * Parameters: 6310 * unit - (IN) Unit number. 6311 * Returns: 6312 * BCM_E_xxx 6313 * Notes: 6314 */ 6315 int 6316 bcm_tr3_l2_clear(int unit) 6317 { 6318 BCM_TR3_L2_INIT(unit); 6319 6320 /* Clear the HW state and associated SW data */ 6321 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_hw_init(unit)); 6322 6323 /* Stop l2x thread if callback registration started it. */ 6324 if (_bcm_tr3_l2_data[unit]->flags & _BCM_TR3_L2X_THREAD_STOP) { 6325 BCM_IF_ERROR_RETURN(soc_tr3_l2x_stop(unit)); 6326 } 6327 6328 /* Clear registered callbacks from _bcm_tr3_l2_data structure */ 6329 _bcm_tr3_l2_data[unit]->cb_count = 0; 6330 _bcm_tr3_l2_data[unit]->flags = 0; 6331 sal_memset(&_bcm_tr3_l2_data[unit]->cb, 0, 6332 sizeof(_bcm_tr3_l2_data[unit]->cb)); 6333 6334 _bcm_tr3_l2_init[unit] = 1; 6335 return BCM_E_NONE; 6336 } 6337 6338 /* 6339 * Function: 6340 * bcm_tr3_l2_detach 6341 * Purpose: 6342 * Finalize the BCM L2 subsystem. 6343 * Parameters: 6344 * unit - (IN) Unit number. 6345 * Returns: 6346 * BCM_E_xxx 6347 * Notes: 6348 */ 6349 int 6350 bcm_tr3_l2_detach(int unit) 6351 { 6352 int frozen; 6353 int mem_idx; 6354 6355 #ifdef BCM_WARM_BOOT_SUPPORT 6356 if (SOC_WARM_BOOT(unit)) { 6357 _bcm_tr3_l2_init[unit] = 0; 6358 return BCM_E_NONE; 6359 } 6360 #endif /* BCM_WARM_BOOT_SUPPORT */ 6361 6362 /* Verify the table is not frozen */ 6363 BCM_IF_ERROR_RETURN(soc_tr3_l2_is_frozen(unit, &frozen)); 6364 if (TRUE == frozen) { 6365 return BCM_E_BUSY; 6366 } 6367 6368 if (_tr3_mbi_entries[unit] != NULL) { 6369 sal_free(_tr3_mbi_entries[unit]); 6370 _tr3_mbi_entries[unit] = NULL; 6371 } 6372 6373 /* Deallocate resources used by station control support. */ 6374 BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_control_deinit(unit)); 6375 6376 /* Deallocate _bcm_tr3_l2_data structure if callbacks were registered */ 6377 if (NULL != _bcm_tr3_l2_data[unit]) { 6378 if (NULL != _bcm_tr3_l2_data[unit]->l2_mutex) { 6379 sal_mutex_destroy(_bcm_tr3_l2_data[unit]->l2_mutex); 6380 } 6381 sal_free(_bcm_tr3_l2_data[unit]); 6382 _bcm_tr3_l2_data[unit] = NULL; 6383 } 6384 6385 /* Deallocate memory acceration structures */ 6386 for (mem_idx = _BCM_TR3_L2_MEM_L2_ENTRY_1; 6387 mem_idx < _BCM_TR3_L2_MEM_NUM; 6388 mem_idx++) { 6389 if (NULL != _bcm_tr3_l2_memacc_list[unit][mem_idx]) { 6390 sal_free(_bcm_tr3_l2_memacc_list[unit][mem_idx]); 6391 _bcm_tr3_l2_memacc_list[unit][mem_idx] = NULL; 6392 } 6393 } 6394 6395 _bcm_tr3_l2_init[unit] = 0; 6396 return BCM_E_NONE; 6397 } 6398 6399 /* 6400 * Function: 6401 * bcm_tr3_l2_addr_add 6402 * Purpose: 6403 * Add an L2 address entry to the specified device. 6404 * Parameters: 6405 * unit - (IN) Unit number. 6406 * l2addr - (IN) Pointer to bcm_l2_addr_t containing all valid fields. 6407 * Returns: 6408 * BCM_E_xxx 6409 * Notes: 6410 */ 6411 int 6412 bcm_tr3_l2_addr_add(int unit, bcm_l2_addr_t *l2addr) 6413 { 6414 _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup; 6415 l2_combo_entry_t ovf_entry; 6416 uint32 key_ent[SOC_MAX_MEM_WORDS], key_ovf[SOC_MAX_MEM_WORDS]; 6417 soc_mem_t mem_type; 6418 int rv, mb_index = 0; 6419 uint8 l2_flags; 6420 6421 BCM_TR3_L2_INIT(unit); 6422 6423 /* Input parameters check. */ 6424 if (NULL == l2addr) { 6425 return (BCM_E_PARAM); 6426 } 6427 6428 if (l2addr->flags & BCM_L2_LOCAL_CPU) { 6429 l2addr->port = CMIC_PORT(unit); 6430 BCM_IF_ERROR_RETURN(bcm_esw_stk_modid_get(unit, &l2addr->modid)); 6431 } 6432 6433 if (l2addr->flags & BCM_L2_TRUNK_MEMBER) { 6434 BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, l2addr->tgid)); 6435 } 6436 6437 if (SOC_L2X_GROUP_ENABLE_GET(unit)) { 6438 if (soc_feature(unit, soc_feature_extended_address_class)) { 6439 if ((l2addr->group > SOC_EXT_ADDR_CLASS_MAX(unit)) || 6440 (l2addr->group < 0)) { 6441 return (BCM_E_PARAM); 6442 } 6443 } else if ((l2addr->group > SOC_ADDR_CLASS_MAX(unit)) || 6444 (l2addr->group < 0)) { 6445 return (BCM_E_PARAM); 6446 } 6447 if (!BCM_PBMP_IS_NULL(l2addr->block_bitmap)) { 6448 return (BCM_E_PARAM); 6449 } 6450 } else { 6451 if (l2addr->group) { 6452 return (BCM_E_PARAM); 6453 } 6454 } 6455 6456 if (l2addr->flags & BCM_L2_L3LOOKUP) { 6457 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_myStation_add(unit, l2addr)); 6458 } 6459 6460 /* Does the entry exist already? */ 6461 sal_memset(&l2_entries_lookup, 0, sizeof (l2_entries_lookup)); 6462 sal_memset(&l2_entries, 0, sizeof (l2_entries)); 6463 l2_entries.entry_flags = _BCM_TR3_L2_SELECT_ALL(unit); 6464 BCM_IF_ERROR_RETURN(_bcm_tr3_l2api_to_l2hw(unit, &l2_entries, 6465 l2addr, FALSE)); 6466 6467 /* Store the flags which indicates which memory that the entry should go */ 6468 l2_flags = l2_entries.entry_flags; 6469 6470 /* For lookup purpose set flags to ALL, so that search is done in 6471 * all the 4 possible tables 6472 */ 6473 l2_entries.entry_flags =_BCM_TR3_L2_SELECT_ALL(unit); 6474 6475 _BCM_ALL_L2X_MEM_LOCK(unit); 6476 rv = _bcm_tr3_l2_entries_lookup(unit, &l2_entries, &l2_entries_lookup); 6477 6478 /* Restore the flags back to original value */ 6479 l2_entries.entry_flags = l2_flags; 6480 6481 if (BCM_E_NOT_FOUND == rv) { 6482 l2_entries_lookup.entry_flags = 0; /* No found entries */ 6483 } else if (BCM_FAILURE(rv)) { 6484 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6485 return rv; 6486 } 6487 6488 if (0 != (l2_entries_lookup.entry_flags & l2_entries.entry_flags)) { 6489 /* The existing location is capable of holding the requested info, 6490 * so overwrite it. Mark the current table location as the 6491 * only one of interest. 6492 */ 6493 l2_entries.entry_flags = l2_entries_lookup.entry_flags; 6494 } 6495 6496 if (!SOC_L2X_GROUP_ENABLE_GET(unit)) { 6497 /* Mac blocking, attempt to associate with bitmap entry */ 6498 rv = _bcm_tr3_mac_block_insert(unit, l2addr->block_bitmap, 6499 &mb_index); 6500 if (BCM_E_NONE != rv) { 6501 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6502 return rv; 6503 } 6504 _bcm_tr3_l2hw_entries_field32_set(unit, &l2_entries, 6505 _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX, mb_index); 6506 } 6507 6508 rv = BCM_E_FULL; 6509 /* In order of efficiency? */ 6510 if (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 6511 rv = soc_mem_insert_return_old(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 6512 (void *)&(l2_entries.l2_entry_1), 6513 (void *)&(l2_entries.l2_entry_1)); 6514 } 6515 if ((l2_entries.entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) && 6516 (BCM_E_FULL == rv)) { 6517 rv = soc_mem_insert_return_old(unit, EXT_L2_ENTRY_1m, MEM_BLOCK_ANY, 6518 (void *)&(l2_entries.ext_l2_entry_1), 6519 (void *)&(l2_entries.ext_l2_entry_1)); 6520 } 6521 if ((l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) && 6522 (BCM_E_FULL == rv)) { 6523 rv = soc_mem_insert_return_old(unit, L2_ENTRY_2m, MEM_BLOCK_ANY, 6524 (void *)&(l2_entries.l2_entry_2), 6525 (void *)&(l2_entries.l2_entry_2)); 6526 } 6527 if ((l2_entries.entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) && 6528 (BCM_E_FULL == rv)) { 6529 rv = soc_mem_insert_return_old(unit, EXT_L2_ENTRY_2m, MEM_BLOCK_ANY, 6530 (void *)&(l2_entries.ext_l2_entry_2), 6531 (void *)&(l2_entries.ext_l2_entry_2)); 6532 } 6533 6534 if ((BCM_E_FULL == rv) && (l2addr->flags & BCM_L2_REPLACE_DYNAMIC)) { 6535 /* coverity[stack_use_callee] */ 6536 /* coverity[stack_use_overflow] */ 6537 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6538 rv = _bcm_tr3_l2_hash_dynamic_replace(unit, &l2_entries); 6539 _BCM_ALL_L2X_MEM_LOCK(unit); 6540 } else if ((BCM_E_FULL == rv) && (l2addr->flags & BCM_L2_ADD_OVERRIDE_PENDING)) { 6541 /* coverity[stack_use_callee] */ 6542 /* coverity[stack_use_overflow] */ 6543 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6544 rv = _bcm_tr3_l2_hash_pending_override(unit, &l2_entries); 6545 _BCM_ALL_L2X_MEM_LOCK(unit); 6546 } else if (rv == BCM_E_EXISTS) { 6547 if (!SOC_L2X_GROUP_ENABLE_GET(unit)) { 6548 mb_index = _bcm_tr3_l2hw_entries_field32_get(unit, &l2_entries, 6549 _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX); 6550 _bcm_tr3_mac_block_delete(unit, mb_index); 6551 } 6552 rv = BCM_E_NONE; 6553 } 6554 6555 if ((rv < 0) && !SOC_L2X_GROUP_ENABLE_GET(unit)) { 6556 _bcm_tr3_mac_block_delete(unit, mb_index); 6557 } 6558 6559 if (BCM_SUCCESS(rv)) { 6560 if (soc_feature(unit, soc_feature_l2_overflow) && 6561 (l2addr->flags & BCM_L2_ENTRY_OVERFLOW)) { 6562 /* Check if this entry is in the overflow memory and resume process */ 6563 if (soc_tr3_l2_overflow_entry_get(unit, &ovf_entry, &mem_type)) { 6564 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6565 return BCM_E_INTERNAL; 6566 } 6567 sal_memset(key_ent, 0, sizeof(key_ent)); 6568 sal_memset(key_ovf, 0, sizeof(key_ovf)); 6569 /* Extract and compare key only (for matching mem types) */ 6570 if ((mem_type == L2_ENTRY_1m) && 6571 (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1)) { 6572 soc_mem_field_get(unit, mem_type, l2_entries.l2_entry_1.entry_data, 6573 L2__KEYf, key_ent); 6574 soc_mem_field_get(unit, mem_type, ovf_entry.words, L2__KEYf, 6575 key_ovf); 6576 if (sal_memcmp(key_ent, key_ovf, sizeof(key_ent))) { 6577 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6578 return BCM_E_PARAM; 6579 } else { 6580 if (soc_tr3_l2_overflow_start(unit)) { 6581 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6582 return BCM_E_INTERNAL; 6583 } 6584 } 6585 } else if ((mem_type == L2_ENTRY_2m) && 6586 (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2)) { 6587 soc_mem_field_get(unit, mem_type, l2_entries.l2_entry_2.entry_data, 6588 L2__KEYf, key_ent); 6589 soc_mem_field_get(unit, mem_type, ovf_entry.words, L2__KEY_0f, 6590 key_ovf); 6591 if (sal_memcmp(key_ent, key_ovf, sizeof(key_ent))) { 6592 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6593 return BCM_E_PARAM; 6594 } else { 6595 if (soc_tr3_l2_overflow_start(unit)) { 6596 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6597 return BCM_E_INTERNAL; 6598 } 6599 } 6600 } else { 6601 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6602 return BCM_E_PARAM; 6603 } 6604 } 6605 6606 if ((0 != l2_entries_lookup.entry_flags) && 6607 (0 == (l2_entries_lookup.entry_flags & l2_entries.entry_flags))) { 6608 rv = _bcm_tr3_l2_entries_delete(unit, &l2_entries_lookup); 6609 6610 if (!SOC_L2X_GROUP_ENABLE_GET(unit)) { 6611 mb_index = 6612 _bcm_tr3_l2hw_entries_field32_get(unit, &l2_entries_lookup, 6613 _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX); 6614 _bcm_tr3_mac_block_delete(unit, mb_index); 6615 } 6616 } 6617 } 6618 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6619 6620 return rv; 6621 } 6622 6623 /* 6624 * Function: 6625 * bcm_tr3_l2_addr_delete 6626 * Purpose: 6627 * Delete an L2 address entry from the specified device. 6628 * Parameters: 6629 * unit - (IN) Unit number. 6630 * mac - (IN) MAC address to delete 6631 * vid - (IN) VLAN id 6632 * Returns: 6633 * BCM_E_xxx 6634 * Notes: 6635 */ 6636 int 6637 bcm_tr3_l2_addr_delete(int unit, bcm_mac_t mac, bcm_vlan_t vid) 6638 { 6639 bcm_l2_addr_t l2addr; 6640 _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup; 6641 int l2_index, mb_index; 6642 int rv = BCM_E_NONE; 6643 6644 BCM_TR3_L2_INIT(unit); 6645 6646 if (BCM_VLAN_VALID(vid)) { 6647 /* Flush any myStation entry */ 6648 rv = _bcm_tr3_l2_myStation_delete(unit, mac, vid, &l2_index); 6649 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) { 6650 if (rv != BCM_E_NONE) { 6651 return rv; 6652 } 6653 } 6654 } 6655 6656 bcm_l2_addr_t_init(&l2addr, mac, vid); 6657 6658 /* Does the entry exist already? */ 6659 sal_memset(&l2_entries_lookup, 0, sizeof (l2_entries_lookup)); 6660 sal_memset(&l2_entries, 0, sizeof (l2_entries)); 6661 l2_entries.entry_flags = _BCM_TR3_L2_SELECT_ALL(unit); 6662 BCM_IF_ERROR_RETURN(_bcm_tr3_l2api_to_l2hw(unit, &l2_entries, 6663 &l2addr, TRUE)); 6664 6665 _BCM_ALL_L2X_MEM_LOCK(unit); 6666 rv = _bcm_tr3_l2_entries_lookup(unit, (void *)&l2_entries, 6667 (void *)&l2_entries_lookup); 6668 6669 if (BCM_E_NONE != rv) { 6670 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6671 return rv; 6672 } 6673 6674 if (!SOC_L2X_GROUP_ENABLE_GET(unit)) { 6675 mb_index = _bcm_tr3_l2hw_entries_field32_get(unit, 6676 &l2_entries_lookup, 6677 _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX); 6678 _bcm_tr3_mac_block_delete(unit, mb_index); 6679 } 6680 6681 rv = _bcm_tr3_l2_entries_delete(unit, &l2_entries_lookup); 6682 _BCM_ALL_L2X_MEM_UNLOCK(unit); 6683 6684 return rv; 6685 } 6686 6687 /* 6688 * Function: 6689 * _bcm_tr3_delete_replace_flags_convert 6690 * Description: 6691 * A helper function to all delete_by APIs to use bcm_l2_replace. 6692 * Converts L2 flags to L2 replace flags compatable to use with bcm_l2_replace 6693 * Parameters: 6694 * unit [IN]- device unit 6695 * flags [IN] - BCM_L2_DELETE_XXX 6696 * repl_flags [OUT]- Vflags BCM_L2_REPLACE_XXX 6697 * Returns: 6698 * BCM_E_XXX 6699 */ 6700 6701 STATIC int 6702 _bcm_tr3_delete_replace_flags_convert(int unit, uint32 flags, uint32 *repl_flags) 6703 { 6704 uint32 tmp_flags = 0; 6705 6706 if (flags & BCM_L2_REPLACE_AGE){ 6707 tmp_flags = BCM_L2_REPLACE_AGE; 6708 }else{ 6709 tmp_flags = BCM_L2_REPLACE_DELETE; 6710 } 6711 6712 if (flags & BCM_L2_DELETE_PENDING) { 6713 tmp_flags |= BCM_L2_REPLACE_PENDING; 6714 } 6715 if (flags & BCM_L2_DELETE_STATIC) { 6716 tmp_flags |= BCM_L2_REPLACE_MATCH_STATIC; 6717 } 6718 if (flags & BCM_L2_DELETE_NO_CALLBACKS) { 6719 tmp_flags |= BCM_L2_REPLACE_NO_CALLBACKS; 6720 } 6721 if (flags & BCM_L2_LEARN_LIMIT) { 6722 tmp_flags |= BCM_L2_REPLACE_LEARN_LIMIT; 6723 } 6724 6725 if ((flags & BCM_L2_REPLACE_MATCH_UC) && (flags & BCM_L2_REPLACE_MATCH_MC)) 6726 { 6727 /* Both flags are contradictory and can't be set together */ 6728 return BCM_E_PARAM; 6729 } 6730 6731 if (flags & BCM_L2_REPLACE_MATCH_UC) { 6732 tmp_flags |= BCM_L2_REPLACE_MATCH_UC; 6733 } 6734 6735 if (flags & BCM_L2_REPLACE_MATCH_MC) { 6736 tmp_flags |= BCM_L2_REPLACE_MATCH_MC; 6737 } 6738 6739 *repl_flags = tmp_flags; 6740 return BCM_E_NONE; 6741 } 6742 6743 /* 6744 * Function: 6745 * bcm_tr3_l2_addr_delete_by_port 6746 * Purpose: 6747 * Delete L2 entries associated with a destination module/port. 6748 * Parameters: 6749 * unit - (IN) Unit number. 6750 * mod - (IN) <UNDEF> 6751 * port - (IN) <UNDEF> 6752 * flags - (IN) <UNDEF> 6753 * Returns: 6754 * BCM_E_xxx 6755 * Notes: 6756 */ 6757 int 6758 bcm_tr3_l2_addr_delete_by_port(int unit, 6759 bcm_module_t mod, 6760 bcm_port_t port, 6761 uint32 flags) 6762 { 6763 bcm_l2_addr_t match_addr; 6764 uint32 repl_flags; 6765 6766 BCM_TR3_L2_INIT(unit); 6767 6768 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 6769 if (!BCM_GPORT_IS_SET(port) && mod == -1) { 6770 if (!SOC_PORT_VALID(unit, port)) { 6771 return BCM_E_PORT; 6772 } 6773 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid)); 6774 } else { 6775 match_addr.modid = mod; 6776 } 6777 match_addr.port = port; 6778 BCM_IF_ERROR_RETURN 6779 (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags)); 6780 repl_flags |= BCM_L2_REPLACE_MATCH_DEST; 6781 return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0); 6782 } 6783 6784 /* 6785 * Function: 6786 * bcm_tr3_l2_addr_delete_by_mac 6787 * Purpose: 6788 * Delete L2 entries associated with a MAC address. 6789 * Parameters: 6790 * unit - (IN) Unit number. 6791 * mac - (IN) <UNDEF> 6792 * flags - (IN) <UNDEF> 6793 * Returns: 6794 * BCM_E_xxx 6795 * Notes: 6796 */ 6797 int 6798 bcm_tr3_l2_addr_delete_by_mac(int unit, 6799 bcm_mac_t mac, 6800 uint32 flags) 6801 { 6802 bcm_l2_addr_t match_addr; 6803 uint32 repl_flags; 6804 6805 BCM_TR3_L2_INIT(unit); 6806 6807 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 6808 sal_memcpy(match_addr.mac, mac, sizeof(bcm_mac_t)); 6809 BCM_IF_ERROR_RETURN 6810 (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags)); 6811 repl_flags |= BCM_L2_REPLACE_MATCH_MAC; 6812 BCM_IF_ERROR_RETURN 6813 (_bcm_tr3_l2_replace(unit, repl_flags|BCM_L2_REPLACE_VPN_TYPE, &match_addr, 0, 0, 0)); 6814 return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0); 6815 } 6816 6817 /* 6818 * Function: 6819 * bcm_tr3_l2_addr_delete_by_vlan 6820 * Purpose: 6821 * Delete L2 entries associated with a VLAN. 6822 * Parameters: 6823 * unit - (IN) Unit number. 6824 * vid - (IN) <UNDEF> 6825 * flags - (IN) <UNDEF> 6826 * Returns: 6827 * BCM_E_xxx 6828 * Notes: 6829 */ 6830 int 6831 bcm_tr3_l2_addr_delete_by_vlan(int unit, 6832 bcm_vlan_t vid, 6833 uint32 flags) 6834 { 6835 bcm_l2_addr_t match_addr; 6836 uint32 repl_flags; 6837 6838 BCM_TR3_L2_INIT(unit); 6839 6840 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 6841 match_addr.vid = vid; 6842 BCM_IF_ERROR_RETURN 6843 (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags)); 6844 repl_flags |= BCM_L2_REPLACE_MATCH_VLAN; 6845 return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0); 6846 } 6847 6848 /* 6849 * Function: 6850 * bcm_tr3_l2_addr_delete_by_trunk 6851 * Purpose: 6852 * Delete L2 entries associated with a trunk. 6853 * Parameters: 6854 * unit - (IN) Unit number. 6855 * tid - (IN) <UNDEF> 6856 * flags - (IN) <UNDEF> 6857 * Returns: 6858 * BCM_E_xxx 6859 * Notes: 6860 */ 6861 int 6862 bcm_tr3_l2_addr_delete_by_trunk(int unit, 6863 bcm_trunk_t tid, 6864 uint32 flags) 6865 { 6866 bcm_l2_addr_t match_addr; 6867 uint32 repl_flags; 6868 6869 BCM_TR3_L2_INIT(unit); 6870 6871 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 6872 match_addr.tgid = tid; 6873 match_addr.flags |= BCM_L2_TRUNK_MEMBER; 6874 BCM_IF_ERROR_RETURN 6875 (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags)); 6876 repl_flags |= BCM_L2_REPLACE_MATCH_DEST; 6877 return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0); 6878 } 6879 6880 /* 6881 * Function: 6882 * bcm_tr3_l2_addr_delete_by_mac_port 6883 * Purpose: 6884 * Delete L2 entries associated with a MAC address and a 6885 * destination module/port. 6886 * Parameters: 6887 * unit - (IN) Unit number. 6888 * mac - (IN) <UNDEF> 6889 * mod - (IN) <UNDEF> 6890 * port - (IN) <UNDEF> 6891 * flags - (IN) <UNDEF> 6892 * Returns: 6893 * BCM_E_xxx 6894 * Notes: 6895 */ 6896 int 6897 bcm_tr3_l2_addr_delete_by_mac_port(int unit, 6898 bcm_mac_t mac, 6899 bcm_module_t mod, 6900 bcm_port_t port, 6901 uint32 flags) 6902 { 6903 bcm_l2_addr_t match_addr; 6904 uint32 repl_flags; 6905 6906 BCM_TR3_L2_INIT(unit); 6907 6908 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 6909 sal_memcpy(match_addr.mac, mac, sizeof(bcm_mac_t)); 6910 if (!BCM_GPORT_IS_SET(port) && mod == -1) { 6911 if (!SOC_PORT_VALID(unit, port)) { 6912 return BCM_E_PORT; 6913 } 6914 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid)); 6915 } else { 6916 match_addr.modid = mod; 6917 } 6918 match_addr.port = port; 6919 BCM_IF_ERROR_RETURN 6920 (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags)); 6921 repl_flags |= BCM_L2_REPLACE_MATCH_MAC | BCM_L2_REPLACE_MATCH_DEST; 6922 return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0); 6923 } 6924 6925 /* 6926 * Function: 6927 * bcm_tr3_l2_addr_delete_by_vlan_port 6928 * Purpose: 6929 * Delete L2 entries associated with a VLAN and a destination 6930 * module/port. 6931 * Parameters: 6932 * unit - (IN) Unit number. 6933 * vid - (IN) <UNDEF> 6934 * mod - (IN) <UNDEF> 6935 * port - (IN) <UNDEF> 6936 * flags - (IN) <UNDEF> 6937 * Returns: 6938 * BCM_E_xxx 6939 * Notes: 6940 */ 6941 int 6942 bcm_tr3_l2_addr_delete_by_vlan_port(int unit, 6943 bcm_vlan_t vid, 6944 bcm_module_t mod, 6945 bcm_port_t port, 6946 uint32 flags) 6947 { 6948 bcm_l2_addr_t match_addr; 6949 uint32 repl_flags; 6950 6951 BCM_TR3_L2_INIT(unit); 6952 6953 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 6954 match_addr.vid = vid; 6955 if (!BCM_GPORT_IS_SET(port) && mod == -1) { 6956 if (!SOC_PORT_VALID(unit, port)) { 6957 return BCM_E_PORT; 6958 } 6959 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid)); 6960 } else { 6961 match_addr.modid = mod; 6962 } 6963 match_addr.port = port; 6964 BCM_IF_ERROR_RETURN 6965 (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags)); 6966 repl_flags |= BCM_L2_REPLACE_MATCH_VLAN |BCM_L2_REPLACE_MATCH_DEST; 6967 return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0); 6968 } 6969 6970 /* 6971 * Function: 6972 * bcm_tr3_l2_addr_delete_by_vlan_trunk 6973 * Purpose: 6974 * Delete L2 entries associated with a VLAN and a destination 6975 * module/port. 6976 * Parameters: 6977 * unit - (IN) Unit number. 6978 * vid - (IN) <UNDEF> 6979 * tid - (IN) <UNDEF> 6980 * flags - (IN) <UNDEF> 6981 * Returns: 6982 * BCM_E_xxx 6983 * Notes: 6984 */ 6985 int 6986 bcm_tr3_l2_addr_delete_by_vlan_trunk(int unit, 6987 bcm_vlan_t vid, 6988 bcm_trunk_t tid, 6989 uint32 flags) 6990 { 6991 bcm_l2_addr_t match_addr; 6992 uint32 repl_flags; 6993 6994 BCM_TR3_L2_INIT(unit); 6995 6996 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 6997 match_addr.vid = vid; 6998 match_addr.tgid = tid; 6999 match_addr.flags |= BCM_L2_TRUNK_MEMBER; 7000 BCM_IF_ERROR_RETURN 7001 (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags)); 7002 repl_flags |= BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_DEST; 7003 return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0); 7004 } 7005 7006 /* 7007 * Function: 7008 * _bcm_tr3_l2_addr_get 7009 * Purpose: 7010 * Check if an L2 entry is present in the L2 table. 7011 * Parameters: 7012 * unit - (IN) Unit number. 7013 * mac_addr - (IN) input MAC address to search 7014 * vid - (IN) input VLAN ID to search 7015 * check_l2_only - (IN) only check if the target exist in L2 table. 7016 * l2addr - (OUT) Pointer to bcm_l2_addr_t structureI 7017 * to receive result 7018 * Returns: 7019 * BCM_E_xxx 7020 * Notes: 7021 */ 7022 int 7023 _bcm_tr3_l2_addr_get(int unit, bcm_mac_t mac_addr, bcm_vlan_t vid, 7024 int check_l2_only, bcm_l2_addr_t *l2addr) 7025 { 7026 _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup; 7027 int rv, rval; 7028 7029 /* First check if in My Station table in case it's an L3-enabled 7030 * entry. 7031 */ 7032 if (!check_l2_only) { 7033 rv = _bcm_tr3_l2_myStation_get(unit, mac_addr, vid, l2addr); 7034 if (BCM_E_NOT_FOUND != rv) { 7035 return rv; 7036 } 7037 } 7038 7039 bcm_l2_addr_t_init(l2addr, mac_addr, vid); 7040 7041 /* Find if the entry exists */ 7042 sal_memset(&l2_entries_lookup, 0, sizeof (l2_entries_lookup)); 7043 sal_memset(&l2_entries, 0, sizeof (l2_entries)); 7044 l2_entries.entry_flags = _BCM_TR3_L2_SELECT_ALL(unit); 7045 BCM_IF_ERROR_RETURN(_bcm_tr3_l2api_to_l2hw(unit, &l2_entries, 7046 l2addr, TRUE)); 7047 7048 _BCM_ALL_L2X_MEM_LOCK(unit); 7049 rv = _bcm_tr3_l2_entries_lookup(unit, (void *)&l2_entries, 7050 (void *)&l2_entries_lookup); 7051 7052 if (BCM_E_NONE != rv) { 7053 _BCM_ALL_L2X_MEM_UNLOCK(unit); 7054 return rv; 7055 } 7056 7057 if (check_l2_only) { 7058 _BCM_ALL_L2X_MEM_UNLOCK(unit); 7059 return rv; 7060 } 7061 7062 /* Translate back to API abstraction */ 7063 rv = _bcm_tr3_l2api_from_l2hw(unit, l2addr, &l2_entries_lookup); 7064 _BCM_ALL_L2X_MEM_UNLOCK(unit); 7065 7066 /* Translate l2mc index */ 7067 BCM_IF_ERROR_RETURN( 7068 bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType, &rval)); 7069 if ((rval) && BCM_MAC_IS_MCAST(l2addr->mac) && 7070 !(_BCM_MULTICAST_IS_SET(l2addr->l2mc_group))) { 7071 _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, _BCM_MULTICAST_TYPE_L2, 7072 l2addr->l2mc_group); 7073 } 7074 7075 return rv; 7076 } 7077 7078 int 7079 bcm_tr3_l2_addr_get(int unit, bcm_mac_t mac_addr, bcm_vlan_t vid, 7080 bcm_l2_addr_t *l2addr) 7081 { 7082 return _bcm_tr3_l2_addr_get(unit, mac_addr, vid, FALSE, l2addr); 7083 } 7084 7085 /* 7086 * Function: 7087 * _bcm_tr3_l2_addr_callback 7088 * Description: 7089 * Callback used with chip addr registration functions. 7090 * This callback calls all the top level client callbacks. 7091 * Parameters: 7092 * unit - StrataSwitch PCI device unit number (driver internal). 7093 * l2addr 7094 * insert 7095 * userdata 7096 * Returns: 7097 */ 7098 STATIC void 7099 _bcm_tr3_l2_addr_callback(int unit, bcm_l2_addr_t *l2addr, int insert, 7100 void *userdata) 7101 { 7102 _bcm_tr3_l2_data_t *ad = _bcm_tr3_l2_data[unit]; 7103 int i; 7104 7105 if (ad->l2_mutex == NULL) { 7106 return; 7107 } 7108 7109 BCM_TR3_L2_CB_LOCK(unit); 7110 for(i = 0; i < _BCM_TR3_L2_CB_MAX; i++) { 7111 if(ad->cb[i].fn) { 7112 ad->cb[i].fn(unit, l2addr, insert, ad->cb[i].fn_data); 7113 } 7114 } 7115 BCM_TR3_L2_CB_UNLOCK(unit); 7116 } 7117 7118 /* 7119 * Function: 7120 * bcm_tr3_l2_addr_register 7121 * Purpose: 7122 * Register/Unregister a callback routine for BCM L2 subsystem. 7123 * Parameters: 7124 * unit - (IN) Unit number. 7125 * callback - (IN) <UNDEF> 7126 * userdata - (IN) <UNDEF> 7127 * Returns: 7128 * BCM_E_xxx 7129 * Notes: 7130 */ 7131 int 7132 bcm_tr3_l2_addr_register(int unit, 7133 bcm_l2_addr_callback_t callback, 7134 void *userdata) 7135 { 7136 _bcm_tr3_l2_data_t *ad = _bcm_tr3_l2_data[unit]; 7137 int i; 7138 #if defined(BCM_XGS_SWITCH_SUPPORT) 7139 int rv; 7140 int usec; 7141 #endif /* BCM_XGS_SWITCH_SUPPORT */ 7142 7143 if (!SOC_IS_XGS_SWITCH(unit)) { 7144 return BCM_E_UNAVAIL; 7145 } 7146 7147 BCM_TR3_L2_INIT(unit); 7148 7149 _bcm_tr3_l2_cbs[unit] = _bcm_tr3_l2_addr_callback; 7150 _bcm_tr3_l2_cb_data[unit] = NULL; 7151 7152 BCM_TR3_L2_CB_MUTEX(unit); 7153 BCM_TR3_L2_CB_LOCK(unit); 7154 #if defined(BCM_XGS_SWITCH_SUPPORT) 7155 /* Start L2x thread if it isn't running already. */ 7156 if (!soc_tr3_l2x_running(unit, NULL, NULL)) { 7157 usec = (SAL_BOOT_BCMSIM)? BCMSIM_L2XMSG_INTERVAL : 3000000; 7158 usec = soc_property_get(unit, spn_L2XMSG_THREAD_USEC, usec); 7159 rv = soc_tr3_l2x_start(unit, 0, usec); 7160 if ((BCM_FAILURE(rv)) && (rv != BCM_E_UNAVAIL)) { 7161 _bcm_tr3_l2_cbs[unit] = NULL; 7162 _bcm_tr3_l2_cb_data[unit] = NULL; 7163 BCM_TR3_L2_CB_UNLOCK(unit); 7164 return(rv); 7165 } 7166 ad->flags |= _BCM_TR3_L2X_THREAD_STOP; 7167 } 7168 if (soc_feature(unit, soc_feature_l2_overflow)) { 7169 rv = soc_tr3_l2_overflow_start(unit); 7170 if ((BCM_FAILURE(rv)) && (rv != BCM_E_UNAVAIL)) { 7171 _bcm_tr3_l2_cbs[unit] = NULL; 7172 _bcm_tr3_l2_cb_data[unit] = NULL; 7173 BCM_TR3_L2_CB_UNLOCK(unit); 7174 return(rv); 7175 } 7176 } 7177 #endif /* BCM_XGS_SWITCH_SUPPORT */ 7178 7179 /* See if the function is already registered (with same data) */ 7180 for (i = 0; i < _BCM_TR3_L2_CB_MAX; i++) { 7181 if (ad->cb[i].fn == callback && ad->cb[i].fn_data == userdata) { 7182 BCM_TR3_L2_CB_UNLOCK(unit); 7183 return BCM_E_NONE; 7184 } 7185 } 7186 7187 /* Not found; add to list. */ 7188 for (i = 0; i < _BCM_TR3_L2_CB_MAX; i++) { 7189 if (ad->cb[i].fn == NULL) { 7190 ad->cb[i].fn = callback; 7191 ad->cb[i].fn_data = userdata; 7192 ad->cb_count++; 7193 break; 7194 } 7195 } 7196 7197 BCM_TR3_L2_CB_UNLOCK(unit); 7198 return i >= _BCM_TR3_L2_CB_MAX ? BCM_E_RESOURCE : BCM_E_NONE; 7199 } 7200 7201 /* 7202 * Function: 7203 * bcm_tr3_l2_addr_unregister 7204 * Purpose: 7205 * Register/Unregister a callback routine for BCM L2 subsystem. 7206 * Parameters: 7207 * unit - (IN) Unit number. 7208 * callback - (IN) <UNDEF> 7209 * userdata - (IN) <UNDEF> 7210 * Returns: 7211 * BCM_E_xxx 7212 * Notes: 7213 */ 7214 int 7215 bcm_tr3_l2_addr_unregister(int unit, 7216 bcm_l2_addr_callback_t callback, 7217 void *userdata) 7218 { 7219 _bcm_tr3_l2_data_t *ad = _bcm_tr3_l2_data[unit]; 7220 int rv = BCM_E_NOT_FOUND; 7221 int i; 7222 7223 if (!SOC_IS_XGS_SWITCH(unit)) { 7224 return BCM_E_UNAVAIL; 7225 } 7226 7227 BCM_TR3_L2_INIT(unit); 7228 BCM_TR3_L2_CB_MUTEX(unit); 7229 BCM_TR3_L2_CB_LOCK(unit); 7230 7231 for (i = 0; i < _BCM_TR3_L2_CB_MAX; i++) { 7232 if((ad->cb[i].fn == callback) && (ad->cb[i].fn_data == userdata)) { 7233 rv = BCM_E_NONE; 7234 ad->cb[i].fn = NULL; 7235 ad->cb[i].fn_data = NULL; 7236 ad->cb_count--; 7237 if (ad->cb_count == 0) { 7238 _bcm_tr3_l2_cbs[unit] = NULL; 7239 _bcm_tr3_l2_cb_data[unit] = NULL; 7240 7241 #if defined(BCM_XGS_SWITCH_SUPPORT) 7242 /* Stop l2x thread if callback registration started it. */ 7243 if (ad->flags & _BCM_TR3_L2X_THREAD_STOP) { 7244 rv = soc_tr3_l2x_stop(unit); 7245 ad->flags &= ~_BCM_TR3_L2X_THREAD_STOP; 7246 } 7247 #endif /* BCM_XGS_SWITCH_SUPPORT */ 7248 } 7249 } 7250 } 7251 7252 BCM_TR3_L2_CB_UNLOCK(unit); 7253 return (rv); 7254 } 7255 7256 /* 7257 * Function: 7258 * bcm_tr3_l2_age_timer_set 7259 * Purpose: 7260 * Set/Get the age timer. 7261 * Parameters: 7262 * unit - (IN) Unit number. 7263 * age_seconds - (IN) <UNDEF> 7264 * Returns: 7265 * BCM_E_xxx 7266 * Notes: 7267 */ 7268 int 7269 bcm_tr3_l2_age_timer_set(int unit, int age_seconds) 7270 { 7271 int rv, enabled; 7272 7273 if (age_seconds < 0) { 7274 return BCM_E_PARAM; 7275 } 7276 enabled = age_seconds ? 1 : 0; 7277 rv = SOC_FUNCTIONS(unit)->soc_age_timer_set(unit, age_seconds, enabled); 7278 return rv; 7279 } 7280 7281 /* 7282 * Function: 7283 * bcm_tr3_l2_age_timer_get 7284 * Purpose: 7285 * Set/Get the age timer. 7286 * Parameters: 7287 * unit - (IN) Unit number. 7288 * age_seconds - (OUT) <UNDEF> 7289 * Returns: 7290 * BCM_E_xxx 7291 * Notes: 7292 */ 7293 int 7294 bcm_tr3_l2_age_timer_get(int unit, int *age_seconds) 7295 { 7296 int rv, seconds, enabled; 7297 7298 rv = SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled); 7299 if (enabled) { 7300 *age_seconds = seconds; 7301 } else { 7302 *age_seconds = 0; 7303 } 7304 return rv; 7305 } 7306 7307 /* 7308 * Function: 7309 * bcm_tr3_l2_conflict_get 7310 * Purpose: 7311 * Given an L2 address entry, return existing addresses which 7312 * could conflict. 7313 * Parameters: 7314 * unit - (IN) Unit number. 7315 * addr - (IN) Pointer to bcm_l2_addr_t structure to seeking conflict 7316 * cf_array - (OUT) Array of bcm_l2_addr_t structures to return 7317 * conflicting entries 7318 * cf_max - (IN) Maximum entries of supplied cf_array 7319 * cf_count - (OUT) Number of conflicting entries returned in cf_array 7320 * Returns: 7321 * BCM_E_xxx 7322 * Notes: 7323 */ 7324 int 7325 bcm_tr3_l2_conflict_get(int unit, bcm_l2_addr_t *addr, 7326 bcm_l2_addr_t *cf_array, int cf_max, int *cf_count) 7327 { 7328 uint32 *kt; 7329 void *entry; 7330 int rv, index; 7331 soc_mem_t mem; 7332 uint32 valid; 7333 uint8 i, bidx, flag, num_ent; 7334 _soc_ism_mem_banks_t mem_banks; 7335 _bcm_tr3_l2_entries_t l2_entries, l2_entries_match; 7336 uint32 l2_entry[SOC_MAX_MEM_WORDS], result, bucket_index; 7337 uint32 key_type_1[] = {SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI}; 7338 uint32 key_type_2[] = {SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE, SOC_MEM_KEY_L2_ENTRY_2_L2_VFI}; 7339 7340 BCM_TR3_L2_INIT(unit); 7341 7342 /* Input parameters check. */ 7343 if ((NULL == addr) || (NULL == cf_count) || 7344 (NULL == cf_array) || (cf_max <= 0)) { 7345 return (BCM_E_PARAM); 7346 } 7347 sal_memset(&l2_entries, 0, sizeof (l2_entries)); 7348 l2_entries.entry_flags = _BCM_TR3_L2_SELECT_ALL(unit); 7349 BCM_IF_ERROR_RETURN(_bcm_tr3_l2api_to_l2hw(unit, &l2_entries, 7350 addr, FALSE)); 7351 /* NOTE: Implementation assumes that enough criteria/info will be set 7352 in the bcm_l2_addr_t param to not have any ambiguity between 7353 ENTRY_1 and ENTRY_2, i.e the following conditions would not 7354 be true together */ 7355 if (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) { 7356 mem = L2_ENTRY_1m; 7357 entry = &l2_entries.l2_entry_1; 7358 kt = key_type_1; 7359 valid = VALIDf; 7360 flag = _BCM_TR3_L2_SELECT_L2_ENTRY_1; 7361 } else if (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) { 7362 mem = L2_ENTRY_2m; 7363 entry = &l2_entries.l2_entry_2; 7364 kt = key_type_2; 7365 valid = VALID_0f; 7366 flag = _BCM_TR3_L2_SELECT_L2_ENTRY_2; 7367 } else { 7368 return BCM_E_PARAM; 7369 } 7370 rv = soc_ism_get_banks_for_mem(unit, mem, mem_banks.banks, 7371 mem_banks.bank_size, &mem_banks.count); 7372 if (SOC_FAILURE(rv)) { 7373 return BCM_E_INTERNAL; 7374 } 7375 if (mem_banks.count == 0) { 7376 return BCM_E_NOT_FOUND; 7377 } 7378 *cf_count = 0; 7379 for (bidx = 0; bidx < mem_banks.count; bidx++) { 7380 rv = soc_generic_hash(unit, mem, entry, (uint32)1 << mem_banks.banks[bidx], 7381 0, &index, &result, &bucket_index, &num_ent); 7382 if (SOC_FAILURE(rv)) { 7383 return BCM_E_INTERNAL; 7384 } 7385 for (i = 0; (i < num_ent) && (*cf_count < cf_max);) { 7386 rv = soc_mem_read(unit, mem, COPYNO_ALL, index + i, l2_entry); 7387 if (SOC_FAILURE(rv)) { 7388 return BCM_E_MEMORY; 7389 } 7390 if (soc_mem_field32_get(unit, mem, &l2_entry, valid) && 7391 ((soc_mem_field32_get(unit, mem, &l2_entry, KEY_TYPEf) == kt[0]) || 7392 (soc_mem_field32_get(unit, mem, &l2_entry, KEY_TYPEf) == kt[1]))) { 7393 l2_entries_match.entry_flags = flag; 7394 if (mem == L2_ENTRY_1m) { 7395 sal_memcpy(&l2_entries_match.l2_entry_1, l2_entry, 7396 sizeof(l2_entry_1_entry_t)); 7397 } else { 7398 sal_memcpy(&l2_entries_match.l2_entry_2, l2_entry, 7399 sizeof(l2_entry_2_entry_t)); 7400 } 7401 BCM_IF_ERROR_RETURN 7402 (_bcm_tr3_l2api_from_l2hw(unit, &cf_array[*cf_count], &l2_entries_match)); 7403 *cf_count += 1; 7404 } 7405 i += soc_ism_get_bucket_offset(unit, mem, -1, entry, l2_entry); 7406 } 7407 } 7408 return BCM_E_NONE; 7409 } 7410 7411 /* 7412 * Function: 7413 * bcm_tr3_l2_port_native 7414 * Purpose: 7415 * Determine if the given port is "native" from the point of view 7416 * of L2. 7417 * Parameters: 7418 * unit - (IN) Unit number. 7419 * modid - (IN) <UNDEF> 7420 * port - (IN) <UNDEF> 7421 * Returns: 7422 * BCM_E_xxx 7423 * Notes: 7424 */ 7425 int 7426 bcm_tr3_l2_port_native(int unit, int modid, int port) 7427 { 7428 int unit_modid; 7429 int unit_port; /* In case unit supports multiple module IDs */ 7430 bcm_trunk_t tgid; 7431 int id, isLocal; 7432 7433 BCM_TR3_L2_INIT(unit); 7434 7435 if (BCM_GPORT_IS_SET(port)) { 7436 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, port, &modid, 7437 &port, &tgid, &id)); 7438 7439 if (-1 != id || BCM_TRUNK_INVALID != tgid) { 7440 return FALSE; 7441 } 7442 } 7443 7444 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, modid, &isLocal)); 7445 if (isLocal != TRUE) { 7446 return FALSE; 7447 } 7448 7449 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &unit_modid)); 7450 if (unit_modid != modid) { 7451 unit_port = port + 32; 7452 } else { 7453 unit_port = port; 7454 } 7455 7456 if (IS_ST_PORT(unit, unit_port)) { 7457 return FALSE; 7458 } 7459 7460 return TRUE; 7461 } 7462 7463 /* 7464 * Function: 7465 * bcm_tr3_l2_cache_init 7466 * Purpose: 7467 * Initialize the L2 cache. 7468 * Parameters: 7469 * unit - (IN) Unit number. 7470 * Returns: 7471 * BCM_E_xxx 7472 * Notes: 7473 */ 7474 int 7475 bcm_tr3_l2_cache_init(int unit) 7476 { 7477 int skip_l2u; 7478 7479 if (!SOC_UNIT_VALID(unit)) { 7480 return BCM_E_UNIT; 7481 } 7482 7483 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 7484 7485 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 7486 bcm_l2_cache_addr_t addr; 7487 l2u_entry_t entry; 7488 int index; 7489 7490 if (!SAL_BOOT_QUICKTURN) { 7491 SOC_IF_ERROR_RETURN 7492 (soc_mem_clear(unit, L2_USER_ENTRYm, COPYNO_ALL, TRUE)); 7493 } 7494 7495 bcm_l2_cache_addr_t_init(&addr); 7496 addr.flags = BCM_L2_CACHE_CPU | BCM_L2_CACHE_BPDU; 7497 /* Set default BPDU addresses (01:80:c2:00:00:00) */ 7498 ENET_SET_MACADDR(addr.mac, _soc_mac_spanning_tree); 7499 ENET_SET_MACADDR(addr.mac_mask, _soc_mac_all_ones); 7500 7501 addr.dest_port = CMIC_PORT(unit); 7502 7503 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cache_to_l2u(unit, &entry, &addr)); 7504 for (index = 0; index < L2U_BPDU_COUNT; index++) { 7505 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, index, &index)); 7506 } 7507 7508 if (!SAL_BOOT_QUICKTURN) { 7509 /* Set 01:80:c2:00:00:10 */ 7510 addr.mac[5] = 0x10; 7511 7512 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cache_to_l2u(unit, &entry, &addr)); 7513 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index)); 7514 /* Set 01:80:c2:00:00:0x */ 7515 addr.mac[5] = 0x00; 7516 addr.mac_mask[5] = 0xf0; 7517 7518 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cache_to_l2u(unit, &entry, &addr)); 7519 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index)); 7520 /* Set 01:80:c2:00:00:2x */ 7521 addr.mac[5] = 0x20; 7522 7523 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cache_to_l2u(unit, &entry, &addr)); 7524 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index)); 7525 } 7526 7527 return BCM_E_NONE; 7528 } 7529 return BCM_E_UNAVAIL; 7530 } 7531 7532 /* 7533 * Function: 7534 * bcm_tr3_l2_cache_set 7535 * Purpose: 7536 * Set an L2 cache entry. 7537 * Parameters: 7538 * unit - (IN) Unit number. 7539 * index - (IN) <UNDEF> 7540 * addr - (IN) <UNDEF> 7541 * index_used - (OUT) <UNDEF> 7542 * Returns: 7543 * BCM_E_xxx 7544 * Notes: 7545 */ 7546 int 7547 bcm_tr3_l2_cache_set(int unit, 7548 int index, 7549 bcm_l2_cache_addr_t *addr, 7550 int *index_used) 7551 { 7552 int skip_l2u; 7553 7554 if (!SOC_UNIT_VALID(unit)) { 7555 return BCM_E_UNIT; 7556 } 7557 BCM_TR3_L2_INIT(unit); 7558 7559 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 7560 7561 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 7562 7563 l2u_entry_t l2u_entry; 7564 bcm_l2_cache_addr_t l2_addr; 7565 7566 sal_memcpy(&l2_addr, addr, sizeof(bcm_l2_cache_addr_t)); 7567 7568 if (soc_feature(unit, soc_feature_extended_address_class)) { 7569 if ((l2_addr.lookup_class > SOC_EXT_ADDR_CLASS_MAX(unit)) || 7570 (l2_addr.lookup_class < 0)) { 7571 return (BCM_E_PARAM); 7572 } 7573 } else if ((l2_addr.lookup_class > SOC_ADDR_CLASS_MAX(unit)) || 7574 (l2_addr.lookup_class < 0)) { 7575 return (BCM_E_PARAM); 7576 } 7577 7578 /* ESW architecture can't support multiple destinations */ 7579 if (BCM_PBMP_NOT_NULL(l2_addr.dest_ports)) { 7580 return BCM_E_PARAM; 7581 } 7582 7583 7584 BCM_IF_ERROR_RETURN( 7585 _bcm_tr3_l2_cache_to_l2u(unit, &l2u_entry, &l2_addr)); 7586 7587 SOC_IF_ERROR_RETURN( 7588 soc_l2u_insert(unit, &l2u_entry, index, index_used)); 7589 7590 if (l2_addr.flags & BCM_L2_CACHE_L3) { 7591 return (_bcm_tr3_l2cache_myStation_set(unit, *index_used, &l2_addr)); 7592 } 7593 7594 return BCM_E_NONE; 7595 } 7596 return BCM_E_UNAVAIL; 7597 } 7598 7599 /* 7600 * Function: 7601 * bcm_tr3_l2_cache_get 7602 * Purpose: 7603 * Get an L2 cache entry. 7604 * Parameters: 7605 * unit - (IN) Unit number. 7606 * index - (IN) <UNDEF> 7607 * addr - (OUT) <UNDEF> 7608 * Returns: 7609 * BCM_E_xxx 7610 * Notes: 7611 */ 7612 int 7613 bcm_tr3_l2_cache_get(int unit, 7614 int index, 7615 bcm_l2_cache_addr_t *addr) 7616 { 7617 int skip_l2u; 7618 7619 if (!SOC_UNIT_VALID(unit)) { 7620 return BCM_E_UNIT; 7621 } 7622 7623 BCM_TR3_L2_INIT(unit); 7624 7625 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 7626 7627 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 7628 l2u_entry_t l2u_entry; 7629 7630 SOC_IF_ERROR_RETURN( 7631 soc_l2u_get(unit, &l2u_entry, index)); 7632 7633 BCM_IF_ERROR_RETURN( 7634 _bcm_tr3_l2_cache_from_l2u(unit, addr, &l2u_entry)); 7635 7636 if (addr->flags & BCM_L2_CACHE_L3) { 7637 BCM_IF_ERROR_RETURN 7638 (_bcm_tr3_l2cache_myStation_get(unit, index, addr)); 7639 } 7640 7641 return BCM_E_NONE; 7642 } 7643 return BCM_E_UNAVAIL; 7644 } 7645 7646 /* 7647 * Function: 7648 * bcm_tr3_l2_cache_delete 7649 * Purpose: 7650 * Clear an L2 cache entry. 7651 * Parameters: 7652 * unit - (IN) Unit number. 7653 * index - (IN) <UNDEF> 7654 * Returns: 7655 * BCM_E_xxx 7656 * Notes: 7657 */ 7658 int 7659 bcm_tr3_l2_cache_delete(int unit, int index) 7660 { 7661 int skip_l2u, rv; 7662 l2u_entry_t entry; 7663 7664 if (!SOC_UNIT_VALID(unit)) { 7665 return BCM_E_UNIT; 7666 } 7667 7668 BCM_TR3_L2_INIT(unit); 7669 7670 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 7671 7672 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 7673 if (index < 0 || index > soc_mem_index_max(unit, L2_USER_ENTRYm)) { 7674 return BCM_E_PARAM; 7675 } 7676 soc_mem_lock(unit, L2_USER_ENTRYm); 7677 rv = READ_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry); 7678 7679 if (BCM_SUCCESS(rv) && _l2u_field32_get(unit, &entry, RESERVED_0f)) { 7680 rv = _bcm_tr3_l2cache_myStation_delete(unit, index); 7681 } 7682 7683 if (BCM_SUCCESS(rv)) { 7684 sal_memset(&entry, 0, sizeof(entry)); 7685 rv = WRITE_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry); 7686 } 7687 7688 soc_mem_unlock(unit, L2_USER_ENTRYm); 7689 return rv; 7690 } 7691 return BCM_E_UNAVAIL; 7692 } 7693 7694 /* 7695 * Function: 7696 * bcm_tr3_l2_cache_delete_all 7697 * Purpose: 7698 * Clear all L2 cache entries. 7699 * Parameters: 7700 * unit - (IN) Unit number. 7701 * Returns: 7702 * BCM_E_xxx 7703 * Notes: 7704 */ 7705 int 7706 bcm_tr3_l2_cache_delete_all(int unit) 7707 { 7708 int skip_l2u, rv, index, index_max; 7709 l2u_entry_t entry; 7710 7711 if (!SOC_UNIT_VALID(unit)) { 7712 return BCM_E_UNIT; 7713 } 7714 7715 BCM_TR3_L2_INIT(unit); 7716 7717 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 7718 7719 7720 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 7721 7722 index_max = soc_mem_index_max(unit, L2_USER_ENTRYm); 7723 7724 rv = BCM_E_NONE; 7725 soc_mem_lock(unit, L2_USER_ENTRYm); 7726 for (index = 0; index <= index_max; index++) { 7727 rv = READ_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry); 7728 if (BCM_SUCCESS(rv) && _l2u_field32_get(unit, &entry, RESERVED_0f)) { 7729 rv = _bcm_tr3_l2cache_myStation_delete(unit, index); 7730 /* Ignore entry not found case */ 7731 if (rv == BCM_E_NOT_FOUND) { 7732 rv = BCM_E_NONE; 7733 } 7734 } 7735 7736 if (BCM_SUCCESS(rv)) { 7737 sal_memset(&entry, 0, sizeof(entry)); 7738 rv = WRITE_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry); 7739 } 7740 7741 if (BCM_FAILURE(rv)) { 7742 break; 7743 } 7744 } 7745 soc_mem_unlock(unit, L2_USER_ENTRYm); 7746 return rv; 7747 } 7748 return BCM_E_UNAVAIL; 7749 } 7750 7751 /* 7752 * Function: 7753 * bcm_tr3_metro_myStation_add 7754 * Purpose: 7755 * Add a (MAC, VLAN) for tunnel/MPLS/TRILL processing. 7756 * Frames destined to (MAC, VLAN) is subjected to MPLS processing. 7757 * Shared by MPLS, MIM and TRILL 7758 * Parameters: 7759 * unit - Unit number 7760 * mac - MAC address 7761 * vlan - VLAN ID 7762 * port - Ingress port 7763 */ 7764 int 7765 bcm_tr3_metro_myStation_add(int unit, bcm_mac_t mac, 7766 bcm_vlan_t vlan, bcm_port_t port) 7767 { 7768 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 7769 int rv, index, alt_index, i, entry_words; 7770 my_station_tcam_entry_t *entry; 7771 uint32 *tunnel_mask; 7772 bcm_mac_t mac_mask; 7773 uint32 port_mask; 7774 7775 tunnel_mask = info->my_station_tunnel_mask.entry_data; 7776 entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm); 7777 7778 soc_mem_lock(unit, MY_STATION_TCAMm); 7779 7780 rv = _bcm_tr3_my_station_lookup(unit, mac, vlan, port, -1, &index, 7781 &alt_index); 7782 if (BCM_SUCCESS(rv)) { 7783 /* Entry exist, update the entry */ 7784 entry = &info->my_station_shadow[index]; 7785 for (i = 0; i < entry_words; i++) { 7786 entry->entry_data[i] |= tunnel_mask[i]; 7787 } 7788 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 7789 entry); 7790 } else if (rv == BCM_E_NOT_FOUND && index == -1) { 7791 /* No free entry available for insertion */ 7792 rv = BCM_E_FULL; 7793 } 7794 if (rv != BCM_E_NOT_FOUND) { 7795 soc_mem_unlock(unit, MY_STATION_TCAMm); 7796 return rv; 7797 } 7798 7799 if (alt_index != -1 && 7800 ((port == -1 && alt_index > index) || 7801 (port != -1 && alt_index < index))) { 7802 /* Free entry is available for new entry insertion and alternate entry 7803 * exists. However need to swap these 2 entries to maintain proper 7804 * lookup precedence */ 7805 rv = soc_mem_read(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, alt_index, 7806 &info->my_station_shadow[index]); 7807 if (BCM_SUCCESS(rv)) { 7808 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 7809 &info->my_station_shadow[index]); 7810 } 7811 if (BCM_FAILURE(rv)) { 7812 soc_mem_unlock(unit, MY_STATION_TCAMm); 7813 return rv; 7814 } 7815 index = alt_index; 7816 } 7817 7818 /* Add the new entry */ 7819 entry = &info->my_station_shadow[index]; 7820 sal_memset(entry, 0, sizeof(*entry)); 7821 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VALIDf, 1); 7822 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VLAN_IDf, vlan); 7823 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VLAN_ID_MASKf, 0xfff); 7824 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, entry, MAC_ADDRf, mac); 7825 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 7826 soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, entry, MAC_ADDR_MASKf, 7827 mac_mask); 7828 if (port != -1) { 7829 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, ING_PORT_NUMf, 7830 port); 7831 port_mask = (1 << soc_mem_field_length(unit, MY_STATION_TCAMm, 7832 ING_PORT_NUMf)) - 1; 7833 soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, ING_PORT_NUM_MASKf, 7834 port_mask); 7835 } 7836 for (i = 0; i < entry_words; i++) { 7837 entry->entry_data[i] |= tunnel_mask[i]; 7838 } 7839 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, entry); 7840 7841 soc_mem_unlock(unit, MY_STATION_TCAMm); 7842 return rv; 7843 } 7844 7845 /* 7846 * Function: 7847 * bcm_tr3_l2_tunnel_add 7848 * Purpose: 7849 * Add a destination L2 address to trigger tunnel processing. 7850 * Parameters: 7851 * unit - (IN) Unit number. 7852 * mac - (IN) MAC address 7853 * vlan - (IN) VLAN ID 7854 * Returns: 7855 * BCM_E_xxx 7856 * Notes: 7857 */ 7858 int 7859 bcm_tr3_l2_tunnel_add(int unit, bcm_mac_t mac, bcm_vlan_t vlan) 7860 { 7861 BCM_TR3_L2_INIT(unit); 7862 return bcm_tr3_metro_myStation_add(unit, mac, vlan, -1); 7863 } 7864 7865 /* 7866 * Function: 7867 * bcm_tr3_metro_myStation_delete 7868 * Purpose: 7869 * Delete a (MAC, VLAN) for tunnel/MPLS processing. 7870 * Shared by MPLS and MIM 7871 * Parameters: 7872 * unit - Unit number 7873 * mac - MAC address 7874 * vlan - VLAN ID 7875 */ 7876 int 7877 bcm_tr3_metro_myStation_delete(int unit, bcm_mac_t mac, 7878 bcm_vlan_t vlan, bcm_port_t port) 7879 { 7880 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 7881 int rv, index, i, entry_words; 7882 my_station_tcam_entry_t *entry; 7883 uint32 *l3_mask, *tunnel_mask; 7884 7885 l3_mask = info->my_station_l3_mask.entry_data; 7886 tunnel_mask = info->my_station_tunnel_mask.entry_data; 7887 entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm); 7888 7889 soc_mem_lock(unit, MY_STATION_TCAMm); 7890 7891 rv = _bcm_tr3_my_station_lookup(unit, mac, vlan, port, -1, &index, NULL); 7892 if (BCM_SUCCESS(rv)) { 7893 entry = &info->my_station_shadow[index]; 7894 7895 /* Check if the entry has tunnel related flag enabled */ 7896 for (i = 0; i < entry_words; i++) { 7897 if (entry->entry_data[i] & tunnel_mask[i]) { 7898 break; 7899 } 7900 } 7901 if (i == entry_words) { 7902 soc_mem_unlock(unit, MY_STATION_TCAMm); 7903 return BCM_E_NOT_FOUND; 7904 } 7905 7906 /* Check to see if we need to delete or modify the entry */ 7907 for (i = 0; i < entry_words; i++) { 7908 if (entry->entry_data[i] & l3_mask[i]) { 7909 break; 7910 } 7911 } 7912 if (i == entry_words) { 7913 /* Delete the entry if no L3 related flag is enabled */ 7914 sal_memset(entry, 0, sizeof(*entry)); 7915 } else { 7916 /* Modify the entry if any L3 related flag is enabled */ 7917 for (i = 0; i < entry_words; i++) { 7918 entry->entry_data[i] &= ~tunnel_mask[i]; 7919 } 7920 } 7921 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 7922 entry); 7923 } 7924 7925 soc_mem_unlock(unit, MY_STATION_TCAMm); 7926 return rv; 7927 } 7928 7929 /* 7930 * Function: 7931 * bcm_tr3_l2_tunnel_delete 7932 * Purpose: 7933 * Clear a destination L2 address used to trigger tunnel 7934 * processing. 7935 * Parameters: 7936 * unit - (IN) Unit number. 7937 * mac - (IN) MAC address 7938 * vlan - (IN) VLAN ID 7939 * Returns: 7940 * BCM_E_xxx 7941 * Notes: 7942 */ 7943 int 7944 bcm_tr3_l2_tunnel_delete(int unit, bcm_mac_t mac, bcm_vlan_t vlan) 7945 { 7946 return bcm_tr3_metro_myStation_delete(unit, mac, vlan, -1); 7947 } 7948 7949 /* 7950 * Function: 7951 * bcm_tr3_metro_myStation_delete_all 7952 * Purpose: 7953 * Delete all (MAC, VLAN) for tunnel/MPLS processing. 7954 * Shared by MPLS and MIM 7955 * Parameters: 7956 * unit - Unit number 7957 */ 7958 int 7959 bcm_tr3_metro_myStation_delete_all(int unit) 7960 { 7961 _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit); 7962 int rv, index, i, num_entries, entry_words; 7963 my_station_tcam_entry_t *entry, valid_mask; 7964 uint32 *l3_mask, *tunnel_mask; 7965 7966 sal_memset(&valid_mask, 0, sizeof(valid_mask)); 7967 soc_mem_field32_set(unit, MY_STATION_TCAMm, &valid_mask, VALIDf, 1); 7968 7969 l3_mask = info->my_station_l3_mask.entry_data; 7970 tunnel_mask = info->my_station_tunnel_mask.entry_data; 7971 num_entries = soc_mem_index_count(unit, MY_STATION_TCAMm); 7972 entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm); 7973 7974 soc_mem_lock(unit, MY_STATION_TCAMm); 7975 7976 rv = BCM_E_NONE; 7977 for (index = 0; index < num_entries; index++) { 7978 entry = &info->my_station_shadow[index]; 7979 7980 /* Check if the entry has tunnel related flag enabled */ 7981 for (i = 0; i < entry_words; i++) { 7982 if (entry->entry_data[i] & tunnel_mask[i]) { 7983 break; 7984 } 7985 } 7986 if (i == entry_words) { 7987 continue; 7988 } 7989 7990 /* Check if the entry is valid */ 7991 for (i = 0; i < entry_words; i++) { 7992 if (entry->entry_data[i] & valid_mask.entry_data[i]) { 7993 break; 7994 } 7995 } 7996 if (i == entry_words) { 7997 continue; 7998 } 7999 8000 /* Check to see if we need to delete or modify the entry */ 8001 for (i = 0; i < entry_words; i++) { 8002 if (entry->entry_data[i] & l3_mask[i]) { 8003 break; 8004 } 8005 } 8006 if (i == entry_words) { 8007 /* Delete the entry if no L3 related flag is enabled */ 8008 sal_memset(entry, 0, sizeof(*entry)); 8009 } else { 8010 /* Modify the entry if any L3 related flag is enabled */ 8011 for (i = 0; i < entry_words; i++) { 8012 entry->entry_data[i] &= ~tunnel_mask[i]; 8013 } 8014 } 8015 rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, 8016 entry); 8017 } 8018 8019 soc_mem_unlock(unit, MY_STATION_TCAMm); 8020 return rv; 8021 } 8022 8023 /* 8024 * Function: 8025 * bcm_tr3_l2_tunnel_delete_all 8026 * Purpose: 8027 * Clear all destination L2 addresses used to trigger tunnel 8028 * processing. 8029 * Parameters: 8030 * unit - (IN) Unit number. 8031 * Returns: 8032 * BCM_E_xxx 8033 * Notes: 8034 */ 8035 int 8036 bcm_tr3_l2_tunnel_delete_all(int unit) 8037 { 8038 BCM_TR3_L2_INIT(unit); 8039 return bcm_tr3_metro_myStation_delete_all(unit); 8040 } 8041 8042 /* 8043 * Function: 8044 * bcm_tr3_l2_learn_limit_set 8045 * Purpose: 8046 * Set L2 addresses learn limit. 8047 * Parameters: 8048 * unit - (IN) Unit number. 8049 * limit - (IN) <UNDEF> 8050 * Returns: 8051 * BCM_E_xxx 8052 * Notes: 8053 */ 8054 int 8055 bcm_tr3_l2_learn_limit_set(int unit, bcm_l2_learn_limit_t *limit) 8056 { 8057 int32 max_limit; 8058 uint32 type, action; 8059 8060 BCM_TR3_L2_INIT(unit); 8061 8062 if (!limit) { 8063 return BCM_E_PARAM; 8064 } 8065 8066 max_limit = BCM_MAC_LIMIT_MAX(unit); 8067 8068 if (limit->limit > max_limit) { 8069 return BCM_E_PARAM; 8070 } 8071 8072 type = limit->flags & 8073 (BCM_L2_LEARN_LIMIT_SYSTEM | BCM_L2_LEARN_LIMIT_VLAN | 8074 BCM_L2_LEARN_LIMIT_PORT | BCM_L2_LEARN_LIMIT_TRUNK); 8075 8076 action = limit->flags & 8077 (BCM_L2_LEARN_LIMIT_ACTION_DROP | BCM_L2_LEARN_LIMIT_ACTION_CPU | 8078 BCM_L2_LEARN_LIMIT_ACTION_PREFER); 8079 8080 if (!type) { 8081 return BCM_E_PARAM; 8082 } 8083 8084 if (type != BCM_L2_LEARN_LIMIT_SYSTEM && 8085 (action & BCM_L2_LEARN_LIMIT_ACTION_PREFER)) { 8086 return BCM_E_PARAM; 8087 } 8088 8089 if (type & BCM_L2_LEARN_LIMIT_SYSTEM) { 8090 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_learn_limit_system_set(unit, action, 8091 limit->limit)); 8092 } 8093 8094 if (type & BCM_L2_LEARN_LIMIT_PORT) { 8095 int index; 8096 if (BCM_GPORT_IS_SET(limit->port)) { 8097 BCM_IF_ERROR_RETURN( 8098 bcm_esw_port_local_get(unit, limit->port, &(limit->port))); 8099 } 8100 8101 if (!SOC_PORT_VALID(unit, limit->port)) { 8102 return BCM_E_PORT; 8103 } 8104 8105 /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit 8106 and only for Raptor/Raven devices */ 8107 if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) { 8108 return BCM_E_PARAM; 8109 } 8110 8111 index = limit->port + soc_mem_index_count(unit, TRUNK_GROUPm); 8112 BCM_IF_ERROR_RETURN 8113 (_bcm_tr3_l2_learn_limit_set(unit, PORT_OR_TRUNK_MAC_LIMITm, 8114 index, action, limit->limit)); 8115 } 8116 8117 if (type & BCM_L2_LEARN_LIMIT_TRUNK) { 8118 int index; 8119 /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit 8120 and only for Raptor/Raven devices */ 8121 if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) { 8122 return BCM_E_PARAM; 8123 } 8124 8125 if (limit->trunk < 0 || 8126 limit->trunk >= soc_mem_index_count(unit, TRUNK_GROUPm)) { 8127 return BCM_E_PARAM; 8128 } 8129 index = limit->trunk; 8130 BCM_IF_ERROR_RETURN 8131 (_bcm_tr3_l2_learn_limit_set(unit, PORT_OR_TRUNK_MAC_LIMITm, 8132 index, action, limit->limit)); 8133 } 8134 8135 if (type & BCM_L2_LEARN_LIMIT_VLAN) { 8136 int index, vfi; 8137 /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit 8138 and only for Raptor/Raven devices */ 8139 if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) { 8140 return BCM_E_PARAM; 8141 } 8142 8143 8144 if (_BCM_VPN_VFI_IS_SET(limit->vlan)) { 8145 vfi = 0; 8146 _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, limit->vlan); 8147 if (vfi >= soc_mem_index_count(unit, VFIm)) { 8148 return BCM_E_PARAM; 8149 } 8150 index = vfi + soc_mem_index_count(unit, VLAN_TABm); 8151 } else { 8152 if (limit->vlan >= soc_mem_index_count(unit, VLAN_TABm)) { 8153 return BCM_E_PARAM; 8154 } 8155 index = limit->vlan; 8156 } 8157 BCM_IF_ERROR_RETURN 8158 (_bcm_tr3_l2_learn_limit_set(unit, VLAN_OR_VFI_MAC_LIMITm, 8159 index, action, limit->limit)); 8160 } 8161 8162 return BCM_E_NONE; 8163 } 8164 8165 /* 8166 * Function: 8167 * bcm_tr3_l2_learn_limit_get 8168 * Purpose: 8169 * Get L2 addresses learn limit. 8170 * Parameters: 8171 * unit - (IN) Unit number. 8172 * limit - (IN/OUT) <UNDEF> 8173 * Returns: 8174 * BCM_E_xxx 8175 * Notes: 8176 */ 8177 int 8178 bcm_tr3_l2_learn_limit_get(int unit, bcm_l2_learn_limit_t *limit) 8179 { 8180 uint32 type; 8181 int index, vfi; 8182 8183 BCM_TR3_L2_INIT(unit); 8184 8185 if (!limit) { 8186 return BCM_E_PARAM; 8187 } 8188 8189 type = limit->flags & 8190 (BCM_L2_LEARN_LIMIT_SYSTEM | BCM_L2_LEARN_LIMIT_VLAN | 8191 BCM_L2_LEARN_LIMIT_PORT | BCM_L2_LEARN_LIMIT_TRUNK); 8192 8193 switch (type) { 8194 case BCM_L2_LEARN_LIMIT_SYSTEM: 8195 return _bcm_tr3_l2_learn_limit_system_get(unit, &limit->flags, 8196 &limit->limit); 8197 break; 8198 case BCM_L2_LEARN_LIMIT_PORT: 8199 if (BCM_GPORT_IS_SET(limit->port)) { 8200 BCM_IF_ERROR_RETURN( 8201 bcm_esw_port_local_get(unit, limit->port, &(limit->port))); 8202 } 8203 8204 if (!SOC_PORT_VALID(unit, limit->port)) { 8205 return BCM_E_PORT; 8206 } 8207 index = limit->port + soc_mem_index_count(unit, TRUNK_GROUPm); 8208 return _bcm_tr3_l2_learn_limit_get(unit, PORT_OR_TRUNK_MAC_LIMITm, 8209 index, &limit->flags, 8210 &limit->limit); 8211 break; 8212 case BCM_L2_LEARN_LIMIT_TRUNK: 8213 8214 if (limit->trunk < 0 || 8215 limit->trunk >= soc_mem_index_count(unit, TRUNK_GROUPm)) { 8216 return BCM_E_PARAM; 8217 } 8218 index = limit->trunk; 8219 return _bcm_tr3_l2_learn_limit_get(unit, PORT_OR_TRUNK_MAC_LIMITm, 8220 index, &limit->flags, 8221 &limit->limit); 8222 break; 8223 case BCM_L2_LEARN_LIMIT_VLAN: 8224 if (_BCM_VPN_VFI_IS_SET(limit->vlan)) { 8225 vfi = 0; 8226 _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, limit->vlan); 8227 if (vfi >= soc_mem_index_count(unit, VFIm)) { 8228 return BCM_E_PARAM; 8229 } 8230 index = vfi + soc_mem_index_count(unit, VLAN_TABm); 8231 } else { 8232 if (limit->vlan >= soc_mem_index_count(unit, VLAN_TABm)) { 8233 return BCM_E_PARAM; 8234 } 8235 index = limit->vlan; 8236 } 8237 return _bcm_tr3_l2_learn_limit_get(unit, VLAN_OR_VFI_MAC_LIMITm, 8238 index, &limit->flags, 8239 &limit->limit); 8240 break; 8241 default: 8242 return BCM_E_PARAM; 8243 } 8244 8245 return BCM_E_UNAVAIL; 8246 } 8247 8248 /* 8249 * Function: 8250 * bcm_tr3_l2_learn_class_set 8251 * Purpose: 8252 * Set/Get attributes for the specified L2 learning class. 8253 * Parameters: 8254 * unit - (IN) Unit number. 8255 * lclass - (IN) <UNDEF> 8256 * lclass_prio - (IN) <UNDEF> 8257 * flags - (IN) <UNDEF> 8258 * Returns: 8259 * BCM_E_xxx 8260 * Notes: 8261 */ 8262 int 8263 bcm_tr3_l2_learn_class_set(int unit, int lclass, int lclass_prio, uint32 flags) 8264 { 8265 uint32 data; 8266 8267 BCM_TR3_L2_INIT(unit); 8268 8269 if (lclass < 0 || lclass >= SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr) || 8270 lclass_prio < 0 || 8271 lclass_prio >= (1 << soc_reg_field_length(unit, CBL_ATTRIBUTEr, 8272 PORT_LEARNING_PRIORITYf))) { 8273 return (BCM_E_PARAM); 8274 } 8275 8276 BCM_IF_ERROR_RETURN(READ_CBL_ATTRIBUTEr(unit, lclass, &data)); 8277 soc_reg_field_set(unit, CBL_ATTRIBUTEr, &data, PORT_LEARNING_PRIORITYf, 8278 lclass_prio); 8279 soc_reg_field_set(unit, CBL_ATTRIBUTEr, &data, ALLOW_MOVE_IN_CLASSf, 8280 flags & BCM_L2_LEARN_CLASS_MOVE ? 1 : 0); 8281 BCM_IF_ERROR_RETURN(WRITE_CBL_ATTRIBUTEr(unit, lclass, data)); 8282 8283 return BCM_E_NONE; 8284 } 8285 8286 /* 8287 * Function: 8288 * bcm_tr3_l2_learn_class_get 8289 * Purpose: 8290 * Set/Get attributes for the specified L2 learning class. 8291 * Parameters: 8292 * unit - (IN) Unit number. 8293 * lclass - (IN) <UNDEF> 8294 * lclass_prio - (OUT) <UNDEF> 8295 * flags - (OUT) <UNDEF> 8296 * Returns: 8297 * BCM_E_xxx 8298 * Notes: 8299 */ 8300 int 8301 bcm_tr3_l2_learn_class_get(int unit, int lclass, int *lclass_pri, uint32 *flags) 8302 { 8303 uint32 data; 8304 8305 BCM_TR3_L2_INIT(unit); 8306 8307 if (!soc_feature(unit, soc_feature_class_based_learning)) { 8308 return (BCM_E_UNAVAIL); 8309 } 8310 8311 if (lclass < 0 || lclass >= SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr) || 8312 lclass_pri == NULL || flags == NULL) { 8313 return (BCM_E_PARAM); 8314 } 8315 8316 BCM_IF_ERROR_RETURN(READ_CBL_ATTRIBUTEr(unit, lclass, &data)); 8317 *lclass_pri = soc_reg_field_get(unit, CBL_ATTRIBUTEr, data, 8318 PORT_LEARNING_PRIORITYf); 8319 *flags = 0; 8320 if (soc_reg_field_get(unit, CBL_ATTRIBUTEr, data, ALLOW_MOVE_IN_CLASSf)) { 8321 *flags |= BCM_L2_LEARN_CLASS_MOVE; 8322 } 8323 8324 return (BCM_E_NONE); 8325 } 8326 8327 /* 8328 * Function: 8329 * bcm_tr3_l2_learn_port_class_set 8330 * Purpose: 8331 * Set/Get L2 learning class for the specified port. 8332 * Parameters: 8333 * unit - (IN) Unit number. 8334 * port - (IN) <UNDEF> 8335 * lclass - (IN) <UNDEF> 8336 * Returns: 8337 * BCM_E_xxx 8338 * Notes: 8339 */ 8340 int 8341 bcm_tr3_l2_learn_port_class_set(int unit, bcm_gport_t port, int lclass) 8342 { 8343 int gport_id; 8344 bcm_module_t mod_out; 8345 bcm_port_t port_out; 8346 bcm_trunk_t trunk_id; 8347 soc_profile_mem_t *profile; 8348 port_cbl_table_modbase_entry_t base_entry; 8349 port_cbl_table_entry_t cbl_entries[128]; 8350 void *entries[1]; 8351 uint32 old_index, index; 8352 int rv; 8353 profile = _bcm_l2_tr3_port_cbl_profile[unit]; 8354 entries[0] = &cbl_entries; 8355 8356 BCM_TR3_L2_INIT(unit); 8357 8358 if (!soc_feature(unit, soc_feature_class_based_learning)) { 8359 return (BCM_E_UNAVAIL); 8360 } 8361 8362 BCM_L2_LEARN_CLASSID_VALID(lclass); 8363 8364 BCM_IF_ERROR_RETURN 8365 (_bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, &trunk_id, 8366 &gport_id)); 8367 8368 if (gport_id != -1) { 8369 if (!BCM_GPORT_IS_MPLS_PORT(port) && 8370 !BCM_GPORT_IS_SUBPORT_GROUP(port) && 8371 !BCM_GPORT_IS_SUBPORT_PORT(port) && 8372 !BCM_GPORT_IS_MIM_PORT(port) && 8373 !BCM_GPORT_IS_VLAN_PORT(port) && 8374 !BCM_GPORT_IS_WLAN_PORT(port) && 8375 !BCM_GPORT_IS_TRILL_PORT(port) && 8376 !BCM_GPORT_IS_NIV_PORT(port) && 8377 !BCM_GPORT_IS_L2GRE_PORT(port) && 8378 !BCM_GPORT_IS_EXTENDER_PORT(port)) { 8379 return BCM_E_PARAM; 8380 } 8381 return soc_mem_field32_modify(unit, PORT_CBL_TABLEm, gport_id, 8382 VIRTUAL_PORT_LEARNING_CLASSf, lclass); 8383 } else if (trunk_id != -1) { 8384 return soc_mem_field32_modify(unit, TRUNK_CBL_TABLEm, trunk_id, 8385 PORT_LEARNING_CLASSf, lclass); 8386 } else { 8387 8388 soc_mem_lock(unit, PORT_CBL_TABLE_MODBASEm); 8389 8390 rv = soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm, MEM_BLOCK_ALL, mod_out, 8391 &base_entry); 8392 if (SOC_FAILURE(rv)) { 8393 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 8394 return rv; 8395 } 8396 old_index = soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm, 8397 &base_entry, BASEf); 8398 rv = soc_profile_mem_get(unit, profile, old_index, 8399 SOC_PORT_ADDR_MAX(unit) + 1, entries); 8400 if (BCM_FAILURE(rv)) { 8401 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 8402 return rv; 8403 } 8404 soc_mem_field32_set(unit, PORT_CBL_TABLEm, &cbl_entries[port_out], 8405 PORT_LEARNING_CLASSf, lclass); 8406 rv = soc_profile_mem_add(unit, profile, entries, 8407 SOC_PORT_ADDR_MAX(unit) + 1, &index); 8408 if (BCM_FAILURE(rv)) { 8409 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 8410 return rv; 8411 } 8412 rv = soc_mem_field32_modify(unit, PORT_CBL_TABLE_MODBASEm, mod_out, 8413 BASEf, index); 8414 if (BCM_FAILURE(rv)) { 8415 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 8416 return rv; 8417 } 8418 rv = soc_profile_mem_delete(unit, profile, old_index); 8419 8420 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 8421 } 8422 8423 return rv; 8424 } 8425 8426 /* 8427 * Function: 8428 * bcm_tr3_l2_learn_port_class_get 8429 * Purpose: 8430 * Set/Get L2 learning class for the specified port. 8431 * Parameters: 8432 * unit - (IN) Unit number. 8433 * port - (IN) Ingress generic port 8434 * lclass - (OUT) learning class id (0 - 3) 8435 * Returns: 8436 * BCM_E_xxx 8437 * Notes: 8438 */ 8439 int 8440 bcm_tr3_l2_learn_port_class_get(int unit, 8441 bcm_gport_t port, 8442 int *lclass) 8443 { 8444 int gport_id; 8445 bcm_module_t mod_out; 8446 bcm_port_t port_out; 8447 bcm_trunk_t trunk_id; 8448 soc_profile_mem_t *profile; 8449 port_cbl_table_modbase_entry_t base_entry; 8450 port_cbl_table_entry_t cbl_entries[128]; 8451 void *entries[1]; 8452 uint32 index; 8453 port_cbl_table_entry_t port_entry; 8454 trunk_cbl_table_entry_t trunk_entry; 8455 8456 BCM_TR3_L2_INIT(unit); 8457 8458 BCM_IF_ERROR_RETURN 8459 (_bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, &trunk_id, 8460 &gport_id)); 8461 8462 if (lclass == NULL) { 8463 return (BCM_E_PARAM); 8464 } 8465 8466 if (gport_id != -1) { 8467 if (!BCM_GPORT_IS_MPLS_PORT(port) && 8468 !BCM_GPORT_IS_SUBPORT_GROUP(port) && 8469 !BCM_GPORT_IS_SUBPORT_PORT(port) && 8470 !BCM_GPORT_IS_MIM_PORT(port) && 8471 !BCM_GPORT_IS_VLAN_PORT(port) && 8472 !BCM_GPORT_IS_WLAN_PORT(port) && 8473 !BCM_GPORT_IS_TRILL_PORT(port) && 8474 !BCM_GPORT_IS_NIV_PORT(port) && 8475 !BCM_GPORT_IS_L2GRE_PORT(port) && 8476 !BCM_GPORT_IS_EXTENDER_PORT(port)) { 8477 return BCM_E_PARAM; 8478 } 8479 BCM_IF_ERROR_RETURN 8480 (READ_PORT_CBL_TABLEm(unit, MEM_BLOCK_ALL, gport_id, &port_entry)); 8481 *lclass = soc_mem_field32_get(unit, PORT_CBL_TABLEm, &port_entry, 8482 VIRTUAL_PORT_LEARNING_CLASSf); 8483 } else if (trunk_id != -1) { 8484 BCM_IF_ERROR_RETURN 8485 (READ_TRUNK_CBL_TABLEm(unit, MEM_BLOCK_ALL, trunk_id, &trunk_entry)); 8486 *lclass = soc_mem_field32_get(unit, TRUNK_CBL_TABLEm, &trunk_entry, 8487 PORT_LEARNING_CLASSf); 8488 } else { 8489 profile = _bcm_l2_tr3_port_cbl_profile[unit]; 8490 entries[0] = &cbl_entries; 8491 8492 BCM_IF_ERROR_RETURN 8493 (soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm, MEM_BLOCK_ALL, mod_out, 8494 &base_entry)); 8495 index = soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm, &base_entry, 8496 BASEf); 8497 8498 BCM_IF_ERROR_RETURN 8499 (soc_profile_mem_get(unit, profile, index, 8500 SOC_PORT_ADDR_MAX(unit) + 1, entries)); 8501 *lclass = soc_mem_field32_get(unit, PORT_CBL_TABLEm, 8502 &cbl_entries[port_out], 8503 PORT_LEARNING_CLASSf); 8504 } 8505 8506 return (BCM_E_NONE); 8507 } 8508 8509 /* 8510 * Function: 8511 * _bcm_tr3_l2_traverse_int_cb 8512 * Description: 8513 * Simple internal callback function for bcm_l2_traverse API 8514 * just to call a user provided callback on a given entry. 8515 * Parameters: 8516 * unit device number 8517 * trav_st traverse structure 8518 * Return: 8519 * BCM_E_XXX 8520 */ 8521 8522 int 8523 _bcm_tr3_l2_traverse_int_cb(int unit, void *trav_st) 8524 { 8525 _bcm_l2_traverse_t *trv; 8526 bcm_l2_addr_t l2_addr; 8527 8528 trv = (_bcm_l2_traverse_t *)trav_st; 8529 8530 switch(trv->mem) { 8531 case L2_ENTRY_1m: 8532 BCM_IF_ERROR_RETURN 8533 (_bcm_tr3_l2_from_l2_1(unit, &l2_addr, 8534 (l2_entry_1_entry_t *)trv->data)); 8535 if (_l2_addr_counts.flags & L2_DUMP_COUNT) { 8536 _l2_addr_counts.l2_count.l2_entry_1++; 8537 } 8538 break; 8539 case L2_ENTRY_2m: 8540 BCM_IF_ERROR_RETURN 8541 (_bcm_tr3_l2_from_l2_2(unit, &l2_addr, 8542 (l2_entry_2_entry_t *)trv->data)); 8543 if (_l2_addr_counts.flags & L2_DUMP_COUNT) { 8544 _l2_addr_counts.l2_count.l2_entry_2++; 8545 } 8546 break; 8547 case EXT_L2_ENTRY_1m: 8548 BCM_IF_ERROR_RETURN 8549 (_bcm_tr3_l2_from_ext_l2_1(unit, &l2_addr, 8550 (ext_l2_entry_1_entry_t *)trv->data)); 8551 if (_l2_addr_counts.flags & L2_DUMP_COUNT) { 8552 _l2_addr_counts.l2_count.ext_l2_entry_1++; 8553 } 8554 break; 8555 case EXT_L2_ENTRY_2m: 8556 BCM_IF_ERROR_RETURN 8557 (_bcm_tr3_l2_from_ext_l2_2(unit, &l2_addr, 8558 (ext_l2_entry_2_entry_t *)trv->data)); 8559 if (_l2_addr_counts.flags & L2_DUMP_COUNT) { 8560 _l2_addr_counts.l2_count.ext_l2_entry_2++; 8561 } 8562 break; 8563 default: 8564 return BCM_E_INTERNAL; 8565 } 8566 8567 return trv->user_cb(unit, &l2_addr, trv->user_data); 8568 } 8569 8570 /* 8571 * Function: 8572 * bcm_tr3_l2_traverse 8573 * Purpose: 8574 * Traverse L2 table 8575 * Parameters: 8576 * unit - (IN) Unit number. 8577 * trav_st Traverse structure with all the data. 8578 * Returns: 8579 * BCM_E_xxx 8580 * Notes: 8581 */ 8582 int 8583 bcm_tr3_l2_traverse(int unit, _bcm_l2_traverse_t *trav_st) 8584 { 8585 /* Override generic ESW traverse callback with TR3 version */ 8586 trav_st->int_cb = _bcm_tr3_l2_traverse_int_cb; 8587 8588 return (_bcm_tr3_l2_traverse(unit, trav_st)); 8589 } 8590 8591 STATIC int 8592 _bcm_tr3_l2e_ppa_match(int unit, _soc_tr3_l2_replace_t *rep_st, int mem) 8593 { 8594 _soc_tr3_l2e_ppa_info_t *ppa_info; 8595 _soc_tr3_l2e_ppa_vlan_t *ppa_vlan; 8596 ext_l2_entry_1_entry_t l2_entry_1, old_l2_entry_1; 8597 ext_l2_entry_2_entry_t l2_entry_2, old_l2_entry_2; 8598 int i, imin, imax, rv, nmatches; 8599 uint32 entdata, entmask, entvalue; 8600 soc_memacc_t *memacc; 8601 8602 if (SOC_CONTROL(unit)->l2x_mode == L2MODE_POLL) { 8603 return BCM_E_UNAVAIL; 8604 } 8605 8606 if (mem == EXT_L2_ENTRY_1m) { 8607 /* EXT_L2_ENTRY_1 */ 8608 ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info; 8609 ppa_vlan = SOC_CONTROL(unit)->ext_l2_ppa_vlan; 8610 if (ppa_info == NULL) { 8611 return BCM_E_NONE; 8612 } 8613 8614 imin = soc_mem_index_min(unit, mem); 8615 imax = soc_mem_index_max(unit, mem); 8616 8617 /* convert match data */ 8618 entdata = _SOC_TR3_L2E_VALID; 8619 entmask = _SOC_TR3_L2E_VALID; 8620 if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 8621 entdata |= 0x00000000; 8622 entmask |= _SOC_TR3_L2E_STATIC; 8623 } 8624 if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) { 8625 entdata |= (rep_st->key_vlan & _SOC_TR3_L2E_VLAN_MASK) << 8626 _SOC_TR3_L2E_VLAN_SHIFT; 8627 entmask |= _SOC_TR3_L2E_VLAN_MASK << _SOC_TR3_L2E_VLAN_SHIFT; 8628 imin = ppa_vlan->vlan_min[rep_st->key_vlan]; 8629 imax = ppa_vlan->vlan_max[rep_st->key_vlan]; 8630 } 8631 if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) { 8632 if (rep_st->match_dest.trunk != -1) { 8633 entdata |= _SOC_TR3_L2E_T | 8634 ((rep_st->match_dest.trunk & _SOC_TR3_L2E_TRUNK_MASK) 8635 << _SOC_TR3_L2E_TRUNK_SHIFT); 8636 entmask |= _SOC_TR3_L2E_T | 8637 (_SOC_TR3_L2E_TRUNK_MASK << _SOC_TR3_L2E_TRUNK_SHIFT); 8638 } else if (rep_st->match_dest.vp != -1) { 8639 entdata |= _SOC_TR3_L2E_VP | 8640 ((rep_st->match_dest.vp & _SOC_TR3_L2E_DESTINATION_MASK) 8641 << _SOC_TR3_L2E_DESTINATION_SHIFT); 8642 entmask |= _SOC_TR3_L2E_VP | 8643 (_SOC_TR3_L2E_DESTINATION_MASK << 8644 _SOC_TR3_L2E_DESTINATION_SHIFT); 8645 } else { 8646 entdata |= 8647 ((rep_st->match_dest.module & _SOC_TR3_L2E_MOD_MASK) << 8648 _SOC_TR3_L2E_MOD_SHIFT) | 8649 ((rep_st->match_dest.port & _SOC_TR3_L2E_PORT_MASK) << 8650 _SOC_TR3_L2E_PORT_SHIFT); 8651 entmask |= _SOC_TR3_L2E_T | _SOC_TR3_L2E_VP | 8652 (_SOC_TR3_L2E_MOD_MASK << _SOC_TR3_L2E_MOD_SHIFT) | 8653 (_SOC_TR3_L2E_PORT_MASK << _SOC_TR3_L2E_PORT_SHIFT); 8654 } 8655 } 8656 8657 nmatches = 0; 8658 8659 if (imin >= 0) { 8660 if ((imax - imin) > SOC_CONTROL(unit)->ext_l2_ppa_threshold) { 8661 return BCM_E_UNAVAIL; 8662 } 8663 for (i = imin; i <= imax; i++) { 8664 entvalue = ppa_info[i].data; 8665 if ((entvalue & entmask) != entdata) { 8666 continue; 8667 } 8668 if (rep_st->flags & BCM_L2_REPLACE_MATCH_MAC) { 8669 if (ENET_CMP_MACADDR(rep_st->key_mac, ppa_info[i].mac)) { 8670 continue; 8671 } 8672 } 8673 nmatches += 1; 8674 8675 /* lookup the matched entry */ 8676 sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1)); 8677 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 8678 _BCM_TR3_L2_MEMACC_VLAN_ID); 8679 soc_memacc_field32_set(memacc, &l2_entry_1, (entvalue >> 16) & 0xfff); 8680 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 8681 _BCM_TR3_L2_MEMACC_MAC_ADDR); 8682 soc_memacc_mac_addr_set(memacc, &l2_entry_1, 8683 ppa_info[i].mac); 8684 8685 /* In case of a VP entry, also assign the KEY_TYPE */ 8686 if(entvalue & _SOC_TR3_L2E_VP) { 8687 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 8688 _BCM_TR3_L2_MEMACC_KEY_TYPE); 8689 soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->ext_key_type); 8690 } 8691 8692 /* operate on matched entry */ 8693 if (rep_st->flags & BCM_L2_REPLACE_DELETE) { 8694 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 0, 8695 &l2_entry_1, &l2_entry_1, NULL); 8696 if (rv < 0) { 8697 return rv; 8698 } 8699 } else { 8700 /* replace destination fields */ 8701 rv = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY, 0, 8702 &l2_entry_1, &l2_entry_1, NULL); 8703 if (rep_st->flags & BCM_L2_REPLACE_NEW_TRUNK) { 8704 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 8705 _BCM_TR3_L2_MEMACC_DEST_TYPE); 8706 soc_memacc_field32_set(memacc, &l2_entry_1, 1); 8707 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 8708 _BCM_TR3_L2_MEMACC_TGID); 8709 soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->new_dest.trunk); 8710 } else { 8711 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 8712 _BCM_TR3_L2_MEMACC_MODULE_ID); 8713 soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->new_dest.module); 8714 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, 8715 _BCM_TR3_L2_MEMACC_PORT_NUM); 8716 soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->new_dest.port); 8717 } 8718 /* re-insert entry */ 8719 rv = soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY, 0, 8720 &l2_entry_1, &old_l2_entry_1, NULL); 8721 if (rv == BCM_E_EXISTS) { 8722 rv = BCM_E_NONE; 8723 } 8724 if (rv < 0) { 8725 return rv; 8726 } 8727 } 8728 } 8729 } 8730 LOG_VERBOSE(BSL_LS_SOC_COMMON, 8731 (BSL_META_U(unit, 8732 "tr_l2e_ppa_match 1: imin=%d imax=%d nmatches=%d flags=0x%x\n"), 8733 imin, imax, nmatches, rep_st->flags)); 8734 } else { 8735 /* EXT_L2_ENTRY_2 */ 8736 ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info_2; 8737 ppa_vlan = SOC_CONTROL(unit)->ext_l2_ppa_vlan_2; 8738 if (ppa_info == NULL) { 8739 return BCM_E_NONE; 8740 } 8741 8742 mem = EXT_L2_ENTRY_2m; 8743 imin = soc_mem_index_min(unit, mem); 8744 imax = soc_mem_index_max(unit, mem); 8745 8746 /* convert match data */ 8747 entdata = _SOC_TR3_L2E_VALID; 8748 entmask = _SOC_TR3_L2E_VALID; 8749 if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 8750 entdata |= 0x00000000; 8751 entmask |= _SOC_TR3_L2E_STATIC; 8752 } 8753 if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) { 8754 entdata |= (rep_st->key_vlan & _SOC_TR3_L2E_VLAN_MASK) << 8755 _SOC_TR3_L2E_VLAN_SHIFT; 8756 entmask |= _SOC_TR3_L2E_VLAN_MASK << _SOC_TR3_L2E_VLAN_SHIFT; 8757 imin = ppa_vlan->vlan_min[rep_st->key_vlan]; 8758 imax = ppa_vlan->vlan_max[rep_st->key_vlan]; 8759 } 8760 if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) { 8761 if (rep_st->match_dest.trunk != -1) { 8762 entdata |= _SOC_TR3_L2E_T | 8763 ((rep_st->match_dest.trunk & _SOC_TR3_L2E_TRUNK_MASK) 8764 << _SOC_TR3_L2E_TRUNK_SHIFT); 8765 entmask |= _SOC_TR3_L2E_T | 8766 (_SOC_TR3_L2E_TRUNK_MASK << _SOC_TR3_L2E_TRUNK_SHIFT); 8767 } else if (rep_st->match_dest.vp != -1) { 8768 entdata |= _SOC_TR3_L2E_VP | 8769 ((rep_st->match_dest.vp & _SOC_TR3_L2E_DESTINATION_MASK) 8770 << _SOC_TR3_L2E_DESTINATION_SHIFT); 8771 entmask |= _SOC_TR3_L2E_VP | 8772 (_SOC_TR3_L2E_DESTINATION_MASK << 8773 _SOC_TR3_L2E_DESTINATION_SHIFT); 8774 } else { 8775 entdata |= 8776 ((rep_st->match_dest.module & _SOC_TR3_L2E_MOD_MASK) << 8777 _SOC_TR3_L2E_MOD_SHIFT) | 8778 ((rep_st->match_dest.port & _SOC_TR3_L2E_PORT_MASK) << 8779 _SOC_TR3_L2E_PORT_SHIFT); 8780 entmask |= _SOC_TR3_L2E_T | _SOC_TR3_L2E_VP | 8781 (_SOC_TR3_L2E_MOD_MASK << _SOC_TR3_L2E_MOD_SHIFT) | 8782 (_SOC_TR3_L2E_PORT_MASK << _SOC_TR3_L2E_PORT_SHIFT); 8783 } 8784 } 8785 8786 nmatches = 0; 8787 8788 if (imin >= 0) { 8789 if ((imax - imin) > SOC_CONTROL(unit)->ext_l2_ppa_threshold) { 8790 return BCM_E_UNAVAIL; 8791 } 8792 for (i = imin; i <= imax; i++) { 8793 entvalue = ppa_info[i].data; 8794 if ((entvalue & entmask) != entdata) { 8795 continue; 8796 } 8797 if (rep_st->flags & BCM_L2_REPLACE_MATCH_MAC) { 8798 if (ENET_CMP_MACADDR(rep_st->key_mac, ppa_info[i].mac)) { 8799 continue; 8800 } 8801 } 8802 nmatches += 1; 8803 8804 /* lookup the matched entry */ 8805 sal_memset(&l2_entry_2, 0, sizeof(l2_entry_2)); 8806 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 8807 _BCM_TR3_L2_MEMACC_VLAN_ID); 8808 soc_memacc_field32_set(memacc, &l2_entry_2, (entvalue >> 16) & 0xfff); 8809 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 8810 _BCM_TR3_L2_MEMACC_MAC_ADDR); 8811 soc_memacc_mac_addr_set(memacc, &l2_entry_2, 8812 ppa_info[i].mac); 8813 8814 /* In case of a VP entry, also assign the KEY_TYPE */ 8815 if(entvalue & _SOC_TR3_L2E_VP) { 8816 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 8817 _BCM_TR3_L2_MEMACC_KEY_TYPE); 8818 soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->ext_key_type); 8819 } 8820 8821 /* operate on matched entry */ 8822 if (rep_st->flags & BCM_L2_REPLACE_DELETE) { 8823 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 0, 8824 &l2_entry_2, &l2_entry_2, NULL); 8825 if (rv < 0) { 8826 return rv; 8827 } 8828 } else { 8829 /* replace destination fields */ 8830 rv = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY, 0, 8831 &l2_entry_2, &l2_entry_2, NULL); 8832 if (rep_st->flags & BCM_L2_REPLACE_NEW_TRUNK) { 8833 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 8834 _BCM_TR3_L2_MEMACC_DEST_TYPE); 8835 soc_memacc_field32_set(memacc, &l2_entry_2, 1); 8836 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 8837 _BCM_TR3_L2_MEMACC_TGID); 8838 soc_memacc_field32_set(memacc, &l2_entry_2, rep_st->new_dest.trunk); 8839 } else { 8840 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 8841 _BCM_TR3_L2_MEMACC_MODULE_ID); 8842 soc_memacc_field32_set(memacc, &l2_entry_2, rep_st->new_dest.module); 8843 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, 8844 _BCM_TR3_L2_MEMACC_PORT_NUM); 8845 soc_memacc_field32_set(memacc, &l2_entry_2, rep_st->new_dest.port); 8846 } 8847 /* re-insert entry */ 8848 rv = soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY, 0, 8849 &l2_entry_2, &old_l2_entry_2, NULL); 8850 if (rv == BCM_E_EXISTS) { 8851 rv = BCM_E_NONE; 8852 } 8853 if (rv < 0) { 8854 return rv; 8855 } 8856 } 8857 } 8858 } 8859 LOG_VERBOSE(BSL_LS_SOC_COMMON, 8860 (BSL_META_U(unit, 8861 "tr_l2e_ppa_match 2: imin=%d imax=%d nmatches=%d flags=0x%x\n"), 8862 imin, imax, nmatches, rep_st->flags)); 8863 } 8864 return BCM_E_NONE; 8865 } 8866 8867 /* 8868 * Function: 8869 * _bcm_tr3_l2_bulk_control 8870 * Description: 8871 * Setup hardware L2 bulk control registers 8872 * Parameters: 8873 * unit device number 8874 * rep_st structure with information of what to replace 8875 * Return: 8876 * BCM_E_XXX 8877 */ 8878 STATIC int 8879 _bcm_tr3_l2_bulk_control(int unit, _soc_tr3_l2_replace_t *rep_st) 8880 { 8881 int rv = BCM_E_NONE; 8882 uint32 rval; 8883 8884 SOC_IF_ERROR_RETURN(READ_L2_BULK_CONTROLr(unit, &rval)); 8885 if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) { 8886 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 8887 ((rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS) ? 0 : 1)); 8888 } else { 8889 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0); 8890 } 8891 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 8892 (rep_st->flags & BCM_L2_REPLACE_AGE ? 3: (rep_st->flags & BCM_L2_REPLACE_DELETE ? 1 : 2))); 8893 8894 /* First work on L2_ENTRY_1m */ 8895 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 8896 _SOC_TR3_L2_BULK_BURST_MAX); 8897 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 8898 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 8899 soc_mem_index_count(unit, L2_ENTRY_1m)); 8900 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0); 8901 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 8902 8903 /* Set match mask */ 8904 BCM_IF_ERROR_RETURN 8905 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &rep_st->match_mask1)); 8906 /* Set match data */ 8907 BCM_IF_ERROR_RETURN 8908 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &rep_st->match_data1)); 8909 /* Set replace mask */ 8910 BCM_IF_ERROR_RETURN 8911 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 3, &rep_st->new_mask1)); 8912 /* Set replace data */ 8913 BCM_IF_ERROR_RETURN 8914 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 2, &rep_st->new_data1)); 8915 8916 BCM_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 8917 8918 /* Then work on L2_ENTRY_2 */ 8919 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1); 8920 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 8921 soc_mem_index_count(unit, L2_ENTRY_2m)); 8922 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 8923 8924 /* Set match mask */ 8925 BCM_IF_ERROR_RETURN 8926 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &rep_st->match_mask2)); 8927 /* Set match data */ 8928 BCM_IF_ERROR_RETURN 8929 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &rep_st->match_data2)); 8930 /* Set replace mask */ 8931 BCM_IF_ERROR_RETURN 8932 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 3, &rep_st->new_mask2)); 8933 /* Set replace data */ 8934 BCM_IF_ERROR_RETURN 8935 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 2, &rep_st->new_data2)); 8936 8937 BCM_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 8938 8939 if (!soc_feature(unit, soc_feature_esm_support)) { 8940 return BCM_E_NONE; 8941 } 8942 8943 /* First work on EXT_L2_ENTRY_1 */ 8944 if (SOC_CONTROL(unit)->l2e_ppa) { 8945 rv = _bcm_tr3_l2e_ppa_match(unit, rep_st, EXT_L2_ENTRY_1m); 8946 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 8947 return rv; 8948 } 8949 } 8950 if (!SOC_CONTROL(unit)->l2e_ppa || (rv == BCM_E_UNAVAIL)) { 8951 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 8952 _SOC_TR3_L2_BULK_BURST_MAX); 8953 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 8954 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 8955 SOC_MEM_TR3_EXT_L2_MAX_ENTRIES); 8956 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1); 8957 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 8958 8959 /* Set match mask */ 8960 BCM_IF_ERROR_RETURN 8961 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &rep_st->ext_match_mask1)); 8962 /* Set match data */ 8963 BCM_IF_ERROR_RETURN 8964 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &rep_st->ext_match_data1)); 8965 /* Set replace mask */ 8966 BCM_IF_ERROR_RETURN 8967 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 3, &rep_st->ext_new_mask1)); 8968 /* Set replace data */ 8969 BCM_IF_ERROR_RETURN 8970 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 2, &rep_st->ext_new_data1)); 8971 8972 BCM_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 8973 SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0)); 8974 /* Issue dummy op */ 8975 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0); 8976 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 8977 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1); 8978 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 8979 SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 8980 SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0)); 8981 } 8982 8983 rv = BCM_E_NONE; 8984 /* Then work on EXT_L2_ENTRY_2 */ 8985 if (SOC_CONTROL(unit)->l2e_ppa) { 8986 rv = _bcm_tr3_l2e_ppa_match(unit, rep_st, EXT_L2_ENTRY_2m); 8987 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 8988 return rv; 8989 } 8990 } 8991 if (!SOC_CONTROL(unit)->l2e_ppa || (rv == BCM_E_UNAVAIL)) { 8992 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 8993 (rep_st->flags & BCM_L2_REPLACE_AGE ? 8994 3 : (rep_st->flags & BCM_L2_REPLACE_DELETE ? 1 : 2))); 8995 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1); 8996 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 8997 SOC_MEM_TR3_EXT_L2_MAX_ENTRIES); 8998 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 8999 9000 /* Set match mask */ 9001 BCM_IF_ERROR_RETURN 9002 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &rep_st->ext_match_mask2)); 9003 /* Set match data */ 9004 BCM_IF_ERROR_RETURN 9005 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &rep_st->ext_match_data2)); 9006 /* Set replace mask */ 9007 BCM_IF_ERROR_RETURN 9008 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 3, &rep_st->ext_new_mask2)); 9009 /* Set replace data */ 9010 BCM_IF_ERROR_RETURN 9011 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 2, &rep_st->ext_new_data2)); 9012 9013 BCM_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 9014 SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0)); 9015 /* Issue dummy op */ 9016 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0); 9017 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 9018 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1); 9019 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 9020 SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 9021 SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0)); 9022 } 9023 9024 return BCM_E_NONE; 9025 } 9026 9027 /* 9028 * Function: 9029 * _bcm_tr3_l2_replace_by_hw 9030 * Description: 9031 * Helper function to _bcm_tr3_l2_replace_by_hw 9032 * Parameters: 9033 * unit device number 9034 * rep_st structure with information of what to replace 9035 * Return: 9036 * BCM_E_XXX 9037 */ 9038 STATIC int 9039 _bcm_tr3_l2_replace_by_hw(int unit, _soc_tr3_l2_replace_t *rep_st) 9040 { 9041 int rv, seconds, enabled; 9042 9043 if (NULL == rep_st) { 9044 return BCM_E_PARAM; 9045 } 9046 /* Read l2 aging interval. */ 9047 SOC_IF_ERROR_RETURN 9048 (SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled)); 9049 if (enabled) { 9050 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit)); 9051 } 9052 _BCM_ALL_L2X_MEM_LOCK(unit); 9053 rv = _bcm_tr3_l2_bulk_control(unit, rep_st); 9054 _BCM_ALL_L2X_MEM_UNLOCK(unit); 9055 if (BCM_FAILURE(rv)) { 9056 if (enabled) { 9057 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds)); 9058 } 9059 return rv; 9060 } 9061 9062 if (!(rep_st->flags & BCM_L2_REPLACE_DELETE)) { 9063 if(enabled) { 9064 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds)); 9065 } 9066 return BCM_E_NONE; 9067 } 9068 9069 if (SOC_L2_DEL_SYNC_LOCK(SOC_CONTROL(unit)) < 0) { 9070 if (enabled) { 9071 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds)); 9072 } 9073 return BCM_E_RESOURCE; 9074 } 9075 rv = _soc_tr3_l2x_sync_replace(unit, rep_st, 9076 rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ? 9077 SOC_L2X_NO_CALLBACKS : 0); 9078 SOC_L2_DEL_SYNC_UNLOCK(SOC_CONTROL(unit)); 9079 if (enabled) { 9080 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds)); 9081 } 9082 return rv; 9083 } 9084 9085 /* 9086 * Function: 9087 * _bcm_tr3_l2_replace_dest_setup 9088 * Description: 9089 * Helper function to bcm_l2_replace API to setup a destination 9090 */ 9091 STATIC int 9092 _bcm_tr3_l2_replace_dest_setup(int unit, bcm_module_t module, bcm_port_t port, 9093 bcm_trunk_t trunk, int is_trunk, 9094 _soc_tr3_l2_replace_dest_t *dest) 9095 { 9096 /* If all are -1, means ignore the replacement with new destination */ 9097 if (module == -1 && port == -1 && trunk == -1) { 9098 dest->module = dest->port = dest->trunk = dest->vp = -1; 9099 return BCM_E_NONE; 9100 } 9101 9102 if (BCM_GPORT_IS_SET(port)) { 9103 if (BCM_GPORT_IS_MPLS_PORT(port) || 9104 BCM_GPORT_IS_SUBPORT_GROUP(port) || 9105 BCM_GPORT_IS_SUBPORT_PORT(port) || 9106 BCM_GPORT_IS_MIM_PORT(port) || 9107 BCM_GPORT_IS_VLAN_PORT(port) || 9108 BCM_GPORT_IS_WLAN_PORT(port) || 9109 BCM_GPORT_IS_TRILL_PORT(port) || 9110 BCM_GPORT_IS_NIV_PORT(port) || 9111 BCM_GPORT_IS_L2GRE_PORT(port) || 9112 BCM_GPORT_IS_EXTENDER_PORT(port)) { 9113 /* all these gport has similar encoding format */ 9114 dest->vp = port & 0xffffff; 9115 } else { 9116 BCM_IF_ERROR_RETURN 9117 (_bcm_esw_gport_resolve(unit, port, &dest->module, &dest->port, 9118 &dest->trunk, &dest->vp)); 9119 } 9120 } else if (is_trunk) { 9121 BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, trunk)); 9122 dest->trunk = trunk; 9123 dest->vp = -1; 9124 } else { 9125 PORT_DUALMODID_VALID(unit, port); 9126 BCM_IF_ERROR_RETURN 9127 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, module, port, 9128 &dest->module, &dest->port)); 9129 if (!SOC_MODID_ADDRESSABLE(unit, dest->module)) { 9130 return BCM_E_BADID; 9131 } 9132 if (!SOC_PORT_ADDRESSABLE(unit, dest->port)) { 9133 return BCM_E_PORT; 9134 } 9135 dest->trunk = -1; 9136 dest->vp = -1; 9137 } 9138 9139 return BCM_E_NONE; 9140 } 9141 9142 STATIC int 9143 _bcm_tr3_l2_replace_data_mask_setup(int unit, _soc_tr3_l2_replace_t *rep) 9144 { 9145 bcm_mac_t mac_mask; 9146 bcm_mac_t mac_data; 9147 int key_type; 9148 int field_len; 9149 9150 sal_memset(&rep->match_mask1, 0, sizeof(l2_entry_1_entry_t)); 9151 sal_memset(&rep->match_data1, 0, sizeof(l2_entry_1_entry_t)); 9152 sal_memset(&rep->new_mask1, 0, sizeof(l2_entry_1_entry_t)); 9153 sal_memset(&rep->new_data1, 0, sizeof(l2_entry_1_entry_t)); 9154 sal_memset(&rep->match_mask2, 0, sizeof(l2_entry_2_entry_t)); 9155 sal_memset(&rep->match_data2, 0, sizeof(l2_entry_2_entry_t)); 9156 sal_memset(&rep->new_mask2, 0, sizeof(l2_entry_2_entry_t)); 9157 sal_memset(&rep->new_data2, 0, sizeof(l2_entry_2_entry_t)); 9158 9159 if (soc_feature(unit, soc_feature_esm_support)) { 9160 sal_memset(&rep->ext_match_mask1, 0, sizeof(ext_l2_entry_1_entry_t)); 9161 sal_memset(&rep->ext_match_data1, 0, sizeof(ext_l2_entry_1_entry_t)); 9162 sal_memset(&rep->ext_new_mask1, 0, sizeof(ext_l2_entry_1_entry_t)); 9163 sal_memset(&rep->ext_new_data1, 0, sizeof(ext_l2_entry_1_entry_t)); 9164 sal_memset(&rep->ext_match_mask2, 0, sizeof(ext_l2_entry_2_entry_t)); 9165 sal_memset(&rep->ext_match_data2, 0, sizeof(ext_l2_entry_2_entry_t)); 9166 sal_memset(&rep->ext_new_mask2, 0, sizeof(ext_l2_entry_2_entry_t)); 9167 sal_memset(&rep->ext_new_data2, 0, sizeof(ext_l2_entry_2_entry_t)); 9168 } 9169 /* First work on Internal L2 */ 9170 /* First work on L2_ENTRY_1m */ 9171 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, VALIDf, 1); 9172 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, VALIDf, 1); 9173 9174 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, WIDEf, 1); 9175 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, WIDEf, 0); 9176 9177 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf); 9178 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, KEY_TYPEf, 9179 (1 << field_len) - 1); 9180 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, KEY_TYPEf, 9181 rep->key_type); 9182 9183 if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) { 9184 if (rep->key_vfi != -1) { 9185 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__VFIf); 9186 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, L2__VFIf, 9187 (1 << field_len) - 1); 9188 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, L2__VFIf, 9189 rep->key_vfi); 9190 } else { 9191 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, 9192 L2__VLAN_IDf, 0xfff); 9193 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, 9194 L2__VLAN_IDf, rep->key_vlan); 9195 } 9196 } 9197 9198 if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) { 9199 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 9200 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_mask1, 9201 L2__MAC_ADDRf, mac_mask); 9202 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_data1, 9203 L2__MAC_ADDRf, rep->key_mac); 9204 } 9205 9206 if ((rep->flags & BCM_L2_REPLACE_MATCH_UC) && 9207 !(rep->flags & BCM_L2_REPLACE_MATCH_MC)) { 9208 /* The 40th bit of Unicast must be 0 */ 9209 sal_memset(&mac_mask, 0x00, sizeof(mac_mask)); 9210 mac_mask[0] = 0x01; 9211 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 9212 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_mask1, L2__MAC_ADDRf, 9213 mac_mask); 9214 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_data1, L2__MAC_ADDRf, 9215 mac_data); 9216 } else if ((rep->flags & BCM_L2_REPLACE_MATCH_MC) && 9217 !(rep->flags & BCM_L2_REPLACE_MATCH_UC)) { 9218 /* The 40th bit of Multicast must be 1 */ 9219 sal_memset(&mac_mask, 0x00, sizeof(mac_mask)); 9220 mac_mask[0] = 0x01; 9221 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 9222 mac_data[0] = 0x01; 9223 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_mask1, L2__MAC_ADDRf, 9224 mac_mask); 9225 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_data1, L2__MAC_ADDRf, 9226 mac_data); 9227 } 9228 9229 if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) { 9230 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__DEST_TYPEf); 9231 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, 9232 L2__DEST_TYPEf, (1 << field_len) - 1); 9233 if (rep->match_dest.vp != -1) { 9234 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, 9235 L2__DEST_TYPEf, 2); 9236 9237 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, 9238 L2__DESTINATIONf); 9239 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, 9240 L2__DESTINATIONf, (1 << field_len) - 1); 9241 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, 9242 L2__DESTINATIONf, rep->match_dest.vp); 9243 } else if (rep->match_dest.trunk != -1) { 9244 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, 9245 L2__DEST_TYPEf, 1); 9246 9247 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__TGIDf); 9248 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, 9249 L2__TGIDf, (1 << field_len) - 1); 9250 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, 9251 L2__TGIDf, rep->match_dest.trunk); 9252 } else { 9253 /* L2__DEST_TYPEf == 0 */ 9254 9255 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, 9256 L2__MODULE_IDf); 9257 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, 9258 L2__MODULE_IDf, (1 << field_len) - 1); 9259 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, 9260 L2__MODULE_IDf, rep->match_dest.module); 9261 9262 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__PORT_NUMf); 9263 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, 9264 L2__PORT_NUMf, (1 << field_len) - 1); 9265 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, 9266 L2__PORT_NUMf, rep->match_dest.port); 9267 } 9268 } 9269 9270 if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 9271 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, STATIC_BITf, 9272 1); 9273 /* STATIC_BIT field in data is 0 */ 9274 } 9275 9276 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, L2__PENDINGf, 1); 9277 if (rep->flags & BCM_L2_REPLACE_PENDING) { 9278 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, L2__PENDINGf, 9279 1); 9280 } 9281 9282 if (!(rep->flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) { 9283 if (rep->new_dest.vp != -1) { 9284 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__DEST_TYPEf); 9285 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9286 L2__DEST_TYPEf, (1 << field_len) - 1); 9287 9288 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1, 9289 L2__DEST_TYPEf, 2); 9290 9291 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, 9292 L2__DESTINATIONf); 9293 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9294 L2__DESTINATIONf, (1 << field_len) - 1); 9295 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1, 9296 L2__DESTINATIONf, rep->new_dest.vp); 9297 } else if (rep->new_dest.trunk != -1) { 9298 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__DEST_TYPEf); 9299 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9300 L2__DEST_TYPEf, (1 << field_len) - 1); 9301 9302 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1, 9303 L2__DEST_TYPEf, 1); 9304 9305 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__TGIDf); 9306 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9307 L2__TGIDf, (1 << field_len) - 1); 9308 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1, 9309 L2__TGIDf, rep->new_dest.trunk); 9310 } else if (rep->new_dest.port != -1 9311 && rep->new_dest.module != -1) { 9312 /* L2__DEST_TYPEf == 0 */ 9313 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__DEST_TYPEf); 9314 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9315 L2__DEST_TYPEf, (1 << field_len) - 1); 9316 9317 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, 9318 L2__MODULE_IDf); 9319 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9320 L2__MODULE_IDf, (1 << field_len) - 1); 9321 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1, 9322 L2__MODULE_IDf, rep->new_dest.module); 9323 9324 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__PORT_NUMf); 9325 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9326 L2__PORT_NUMf, (1 << field_len) - 1); 9327 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1, 9328 L2__PORT_NUMf, rep->new_dest.port); 9329 } 9330 9331 if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) { 9332 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9333 HITDAf, 1); 9334 } 9335 if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) { 9336 soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1, 9337 HITSAf, 1); 9338 } 9339 } 9340 9341 /* Then work on L2_ENTRY_2 */ 9342 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, VALID_0f, 1); 9343 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, VALID_1f, 1); 9344 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, VALID_0f, 1); 9345 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, VALID_1f, 1); 9346 9347 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, WIDE_0f, 1); 9348 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, WIDE_1f, 1); 9349 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, WIDE_0f, 1); 9350 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, WIDE_1f, 1); 9351 9352 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, KEY_TYPE_0f); 9353 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, KEY_TYPE_0f, 9354 (1 << field_len) - 1); 9355 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, KEY_TYPE_1f, 9356 (1 << field_len) - 1); 9357 if (rep->key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE) { 9358 key_type = SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE; 9359 } else if (rep->key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_VFI) { 9360 key_type = SOC_MEM_KEY_L2_ENTRY_2_L2_VFI; 9361 } else { 9362 key_type = rep->key_type; 9363 } 9364 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, KEY_TYPE_0f, 9365 key_type); 9366 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, KEY_TYPE_1f, 9367 key_type); 9368 9369 if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) { 9370 if (rep->key_vfi != -1) { 9371 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__VFIf); 9372 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, L2__VFIf, 9373 (1 << field_len) - 1); 9374 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, L2__VFIf, 9375 rep->key_vfi); 9376 } else { 9377 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9378 L2__VLAN_IDf, 0xfff); 9379 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, 9380 L2__VLAN_IDf, rep->key_vlan); 9381 } 9382 } 9383 9384 if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) { 9385 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 9386 soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9387 L2__MAC_ADDRf, mac_mask); 9388 soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &rep->match_data2, 9389 L2__MAC_ADDRf, rep->key_mac); 9390 } 9391 9392 if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) { 9393 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__DEST_TYPEf); 9394 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9395 L2__DEST_TYPEf, (1 << field_len) - 1); 9396 if (rep->match_dest.vp != -1) { 9397 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, 9398 L2__DEST_TYPEf, 2); 9399 9400 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, 9401 L2__DESTINATIONf); 9402 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9403 L2__DESTINATIONf, (1 << field_len) - 1); 9404 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, 9405 L2__DESTINATIONf, rep->match_dest.vp); 9406 } else if (rep->match_dest.trunk != -1) { 9407 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, 9408 L2__DEST_TYPEf, 1); 9409 9410 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__TGIDf); 9411 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9412 L2__TGIDf, (1 << field_len) - 1); 9413 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, 9414 L2__TGIDf, rep->match_dest.trunk); 9415 } else { 9416 /* L2__DEST_TYPEf == 0 */ 9417 9418 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, 9419 L2__MODULE_IDf); 9420 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9421 L2__MODULE_IDf, (1 << field_len) - 1); 9422 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, 9423 L2__MODULE_IDf, rep->match_dest.module); 9424 9425 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__PORT_NUMf); 9426 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9427 L2__PORT_NUMf, (1 << field_len) - 1); 9428 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, 9429 L2__PORT_NUMf, rep->match_dest.port); 9430 } 9431 } 9432 9433 if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 9434 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9435 STATIC_BIT_0f, 1); 9436 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, 9437 STATIC_BIT_1f, 1); 9438 /* STATIC_BIT field in data is 0 */ 9439 } 9440 9441 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, L2__PENDINGf, 1); 9442 if (rep->flags & BCM_L2_REPLACE_PENDING) { 9443 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, L2__PENDINGf, 9444 1); 9445 } 9446 9447 if (!(rep->flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) { 9448 if (rep->new_dest.vp != -1) { 9449 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__DEST_TYPEf); 9450 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9451 L2__DEST_TYPEf, (1 << field_len) - 1); 9452 9453 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2, 9454 L2__DEST_TYPEf, 2); 9455 9456 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, 9457 L2__DESTINATIONf); 9458 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9459 L2__DESTINATIONf, (1 << field_len) - 1); 9460 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2, 9461 L2__DESTINATIONf, rep->new_dest.vp); 9462 } else if (rep->new_dest.trunk != -1) { 9463 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__DEST_TYPEf); 9464 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9465 L2__DEST_TYPEf, (1 << field_len) - 1); 9466 9467 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2, 9468 L2__DEST_TYPEf, 1); 9469 9470 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__TGIDf); 9471 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9472 L2__TGIDf, (1 << field_len) - 1); 9473 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2, 9474 L2__TGIDf, rep->new_dest.trunk); 9475 } else if (rep->new_dest.port != -1 9476 && rep->new_dest.module != -1) { 9477 /* L2__DEST_TYPEf == 0 */ 9478 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__DEST_TYPEf); 9479 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9480 L2__DEST_TYPEf, (1 << field_len) - 1); 9481 9482 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, 9483 L2__MODULE_IDf); 9484 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9485 L2__MODULE_IDf, (1 << field_len) - 1); 9486 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2, 9487 L2__MODULE_IDf, rep->new_dest.module); 9488 9489 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, 9490 L2__PORT_NUMf); 9491 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9492 L2__PORT_NUMf, (1 << field_len) - 1); 9493 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2, 9494 L2__PORT_NUMf, rep->new_dest.port); 9495 } 9496 9497 if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) { 9498 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9499 HITDAf, 1); 9500 } 9501 if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) { 9502 soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2, 9503 HITSAf, 1); 9504 } 9505 } 9506 9507 /* Then work on External L2 */ 9508 if (!soc_feature(unit, soc_feature_esm_support)) { 9509 return BCM_E_NONE; 9510 } 9511 9512 /* First work on EXT_L2_ENTRY_1 */ 9513 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, KEY_TYPEf); 9514 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, KEY_TYPEf, 9515 (1 << field_len) - 1); 9516 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, KEY_TYPEf, 9517 rep->ext_key_type); 9518 9519 if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) { 9520 if (rep->key_vfi != -1) { 9521 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, VFIf); 9522 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9523 VFIf, (1 << field_len) - 1); 9524 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9525 VFIf, rep->key_vfi); 9526 } else { 9527 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9528 VLAN_IDf, 0xfff); 9529 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9530 VLAN_IDf, rep->key_vlan); 9531 } 9532 } 9533 9534 if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) { 9535 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 9536 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9537 MAC_ADDRf, mac_mask); 9538 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9539 MAC_ADDRf, rep->key_mac); 9540 } 9541 9542 if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) { 9543 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, DEST_TYPEf); 9544 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9545 DEST_TYPEf, (1 << field_len) - 1); 9546 if (rep->match_dest.vp != -1) { 9547 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9548 DEST_TYPEf, 2); 9549 9550 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, 9551 DESTINATIONf); 9552 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9553 DESTINATIONf, (1 << field_len) - 1); 9554 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9555 DESTINATIONf, rep->match_dest.vp); 9556 } else if (rep->match_dest.trunk != -1) { 9557 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9558 DEST_TYPEf, 1); 9559 9560 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, TGIDf); 9561 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9562 TGIDf, (1 << field_len) - 1); 9563 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9564 TGIDf, rep->match_dest.trunk); 9565 } else { 9566 /* DEST_TYPEf == 0 */ 9567 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, 9568 MODULE_IDf); 9569 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9570 MODULE_IDf, (1 << field_len) - 1); 9571 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9572 MODULE_IDf, rep->match_dest.module); 9573 9574 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, PORT_NUMf); 9575 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9576 PORT_NUMf, (1 << field_len) - 1); 9577 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9578 PORT_NUMf, rep->match_dest.port); 9579 } 9580 } 9581 9582 if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 9583 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 9584 STATIC_BITf, 1); 9585 /* STATIC_BIT field in data is 0 */ 9586 } 9587 9588 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, PENDINGf, 9589 1); 9590 if (rep->flags & BCM_L2_REPLACE_PENDING) { 9591 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 9592 PENDINGf, 1); 9593 } 9594 9595 if (!(rep->flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) { 9596 if (rep->new_dest.vp != -1) { 9597 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, DEST_TYPEf); 9598 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9599 DEST_TYPEf, (1 << field_len) - 1); 9600 9601 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1, 9602 DEST_TYPEf, 2); 9603 9604 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, 9605 DESTINATIONf); 9606 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9607 DESTINATIONf, (1 << field_len) - 1); 9608 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1, 9609 DESTINATIONf, rep->new_dest.vp); 9610 } else if (rep->new_dest.trunk != -1) { 9611 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, DEST_TYPEf); 9612 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9613 DEST_TYPEf, (1 << field_len) - 1); 9614 9615 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1, 9616 DEST_TYPEf, 1); 9617 9618 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, TGIDf); 9619 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9620 TGIDf, (1 << field_len) - 1); 9621 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1, 9622 TGIDf, rep->new_dest.trunk); 9623 } else if (rep->new_dest.port != -1 9624 && rep->new_dest.module != -1) { 9625 /* DEST_TYPEf == 0 */ 9626 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, DEST_TYPEf); 9627 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9628 DEST_TYPEf, (1 << field_len) - 1); 9629 9630 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, 9631 MODULE_IDf); 9632 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9633 MODULE_IDf, (1 << field_len) - 1); 9634 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1, 9635 MODULE_IDf, rep->new_dest.module); 9636 9637 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, PORT_NUMf); 9638 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9639 PORT_NUMf, (1 << field_len) - 1); 9640 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1, 9641 PORT_NUMf, rep->new_dest.port); 9642 } 9643 9644 if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) { 9645 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9646 HITDAf, 1); 9647 } 9648 if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) { 9649 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1, 9650 HITSAf, 1); 9651 } 9652 } 9653 9654 /* Then work on EXT_L2_ENTRY_2 */ 9655 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, KEY_TYPEf); 9656 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, KEY_TYPEf, 9657 (1 << field_len) - 1); 9658 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, KEY_TYPEf, 9659 rep->ext_key_type); 9660 9661 if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) { 9662 if (rep->key_vfi != -1) { 9663 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, VFIf); 9664 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9665 VFIf, (1 << field_len) - 1); 9666 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9667 VFIf, rep->key_vfi); 9668 } else { 9669 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9670 VLAN_IDf, 0xfff); 9671 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9672 VLAN_IDf, rep->key_vlan); 9673 } 9674 } 9675 9676 if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) { 9677 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 9678 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9679 MAC_ADDRf, mac_mask); 9680 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9681 MAC_ADDRf, rep->key_mac); 9682 } 9683 9684 if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) { 9685 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, DEST_TYPEf); 9686 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9687 DEST_TYPEf, (1 << field_len) - 1); 9688 if (rep->match_dest.vp != -1) { 9689 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9690 DEST_TYPEf, 2); 9691 9692 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, 9693 DESTINATIONf); 9694 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9695 DESTINATIONf, (1 << field_len) - 1); 9696 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9697 DESTINATIONf, rep->match_dest.vp); 9698 } else if (rep->match_dest.trunk != -1) { 9699 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9700 DEST_TYPEf, 1); 9701 9702 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, TGIDf); 9703 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9704 TGIDf, (1 << field_len) - 1); 9705 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9706 TGIDf, rep->match_dest.trunk); 9707 } else { 9708 /* DEST_TYPEf == 0 */ 9709 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, 9710 MODULE_IDf); 9711 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9712 MODULE_IDf, (1 << field_len) - 1); 9713 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9714 MODULE_IDf, rep->match_dest.module); 9715 9716 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, PORT_NUMf); 9717 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9718 PORT_NUMf, (1 << field_len) - 1); 9719 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9720 PORT_NUMf, rep->match_dest.port); 9721 } 9722 } 9723 9724 if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 9725 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 9726 STATIC_BITf, 1); 9727 /* STATIC_BIT field in data is 0 */ 9728 } 9729 9730 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, PENDINGf, 9731 1); 9732 if (rep->flags & BCM_L2_REPLACE_PENDING) { 9733 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 9734 PENDINGf, 1); 9735 } 9736 9737 if (!(rep->flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) { 9738 if (rep->new_dest.vp != -1) { 9739 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, DEST_TYPEf); 9740 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9741 DEST_TYPEf, (1 << field_len) - 1); 9742 9743 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2, 9744 DEST_TYPEf, 2); 9745 9746 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, 9747 DESTINATIONf); 9748 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9749 DESTINATIONf, (1 << field_len) - 1); 9750 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2, 9751 DESTINATIONf, rep->new_dest.vp); 9752 } else if (rep->new_dest.trunk != -1) { 9753 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, DEST_TYPEf); 9754 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9755 DEST_TYPEf, (1 << field_len) - 1); 9756 9757 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2, 9758 DEST_TYPEf, 1); 9759 9760 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, TGIDf); 9761 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9762 TGIDf, (1 << field_len) - 1); 9763 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2, 9764 TGIDf, rep->new_dest.trunk); 9765 } else if (rep->new_dest.port != -1 9766 && rep->new_dest.module != -1) { 9767 /* DEST_TYPEf == 0 */ 9768 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, DEST_TYPEf); 9769 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9770 DEST_TYPEf, (1 << field_len) - 1); 9771 9772 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, 9773 MODULE_IDf); 9774 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9775 MODULE_IDf, (1 << field_len) - 1); 9776 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2, 9777 MODULE_IDf, rep->new_dest.module); 9778 9779 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, 9780 PORT_NUMf); 9781 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9782 PORT_NUMf, (1 << field_len) - 1); 9783 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2, 9784 PORT_NUMf, rep->new_dest.port); 9785 } 9786 9787 if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) { 9788 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9789 HITDAf, 1); 9790 } 9791 if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) { 9792 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2, 9793 HITSAf, 1); 9794 } 9795 } 9796 return BCM_E_NONE; 9797 } 9798 9799 STATIC int 9800 _soc_tr3_l2_sync_mem_cache(int unit, _soc_tr3_l2_replace_t *rep_st) 9801 { 9802 uint8 *vmap, *vmap1; 9803 soc_mem_t mem = L2_ENTRY_1m, ov_mem = L2_ENTRY_2m; 9804 uint32 *cache, *entry, *match_data, *match_mask; 9805 uint32 *new_data, *new_mask; 9806 int index_max, idx, i; 9807 int entry_dw = soc_mem_entry_words(unit, mem); 9808 int entry_words = soc_mem_entry_words(unit, mem); 9809 int copyno = SOC_MEM_BLOCK_ANY(unit, mem); 9810 9811 /* First work on L2_ENTRY_1m */ 9812 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 9813 if (cache == NULL) { 9814 return BCM_E_NONE; 9815 } 9816 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 9817 vmap1 = SOC_MEM_STATE(unit, ov_mem).vmap[copyno]; 9818 index_max = soc_mem_index_max(unit, mem); 9819 for (idx = 0; idx <= index_max; idx++) { 9820 if (!CACHE_VMAP_TST(vmap, idx)) { 9821 continue; 9822 } 9823 entry = cache + (idx * entry_dw); 9824 if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) { 9825 continue; 9826 } 9827 if (!soc_mem_field32_get(unit, mem, entry, STATIC_BITf)) { 9828 continue; 9829 } 9830 match_data = (uint32 *)&rep_st->match_data1; 9831 match_mask = (uint32 *)&rep_st->match_mask1; 9832 for (i = 0; i < entry_words; i++) { 9833 if ((entry[i] ^ match_data[i]) & match_mask[i]) { 9834 break; 9835 } 9836 } 9837 if (i != entry_words) { 9838 continue; 9839 } 9840 /* Match found, delete or replace entry */ 9841 LOG_VERBOSE(BSL_LS_SOC_COMMON, 9842 (BSL_META_U(unit, 9843 "Match found in L2_1 bulk cache op: %d\n"), idx)); 9844 if (rep_st->flags & BCM_L2_REPLACE_DELETE) { 9845 /* Delete op - invalidate the entry */ 9846 CACHE_VMAP_CLR(vmap, idx); 9847 CACHE_VMAP_CLR(vmap1, idx/2); 9848 } else { 9849 /* Replace op - update entry */ 9850 new_data = (uint32 *)&rep_st->new_data1; 9851 new_mask = (uint32 *)&rep_st->new_mask1; 9852 for (i = 0; i < entry_words; i++) { 9853 entry[i] ^= (entry[i] ^ new_data[i]) & new_mask[i]; 9854 } 9855 } 9856 } 9857 9858 /* Then work on L2_ENTRY_2m */ 9859 mem = L2_ENTRY_2m; 9860 ov_mem = L2_ENTRY_1m; 9861 entry_dw = soc_mem_entry_words(unit, mem); 9862 entry_words = soc_mem_entry_words(unit, mem); 9863 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 9864 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 9865 if (cache == NULL) { 9866 return BCM_E_NONE; 9867 } 9868 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 9869 vmap1 = SOC_MEM_STATE(unit, ov_mem).vmap[copyno]; 9870 index_max = soc_mem_index_max(unit, mem); 9871 for (idx = 0; idx <= index_max; idx++) { 9872 if (!CACHE_VMAP_TST(vmap, idx)) { 9873 continue; 9874 } 9875 entry = cache + (idx * entry_dw); 9876 if (!soc_mem_field32_get(unit, mem, entry, VALID_0f)) { 9877 continue; 9878 } 9879 if (!soc_mem_field32_get(unit, mem, entry, STATIC_BIT_0f)) { 9880 continue; 9881 } 9882 match_data = (uint32 *)&rep_st->match_data2; 9883 match_mask = (uint32 *)&rep_st->match_mask2; 9884 for (i = 0; i < entry_words; i++) { 9885 if ((entry[i] ^ match_data[i]) & match_mask[i]) { 9886 break; 9887 } 9888 } 9889 if (i != entry_words) { 9890 continue; 9891 } 9892 /* Match found, delete or replace entry */ 9893 LOG_VERBOSE(BSL_LS_SOC_COMMON, 9894 (BSL_META_U(unit, 9895 "Match found in L2_2 bulk cache op: %d\n"), idx)); 9896 if (rep_st->flags & BCM_L2_REPLACE_DELETE) { 9897 /* Delete op - invalidate the entry */ 9898 CACHE_VMAP_CLR(vmap, idx); 9899 CACHE_VMAP_CLR(vmap1, idx/2); 9900 } else { 9901 /* Replace op - update entry */ 9902 new_data = (uint32 *)&rep_st->new_data2; 9903 new_mask = (uint32 *)&rep_st->new_mask2; 9904 for (i = 0; i < entry_words; i++) { 9905 entry[i] ^= (entry[i] ^ new_data[i]) & new_mask[i]; 9906 } 9907 } 9908 } 9909 9910 return BCM_E_NONE; 9911 } 9912 9913 STATIC int 9914 _is_soc_tr3_l2_mem_cache_enabled(int unit) 9915 { 9916 soc_mem_t mem = L2_ENTRY_1m; 9917 uint32 *cache; 9918 int copyno = SOC_MEM_BLOCK_ANY(unit, mem); 9919 9920 9921 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 9922 if (cache == NULL) { 9923 return FALSE; 9924 } 9925 9926 return TRUE; 9927 } 9928 9929 STATIC int 9930 _bcm_tr3_l2_replace(int unit, uint32 flags, bcm_l2_addr_t *match_addr, 9931 bcm_module_t new_module, bcm_port_t new_port, 9932 bcm_trunk_t new_trunk) 9933 { 9934 _soc_tr3_l2_replace_t rep_st; 9935 int rv = BCM_E_UNAVAIL; 9936 int mode; 9937 9938 sal_memset(&rep_st, 0, sizeof(_soc_tr3_l2_replace_t)); 9939 9940 /*Either of BCM_L2_REPLACE_DELETE or BCM_L2_REPLACE_AGE can bet set, but not both*/ 9941 if ((flags & BCM_L2_REPLACE_DELETE) && (flags & BCM_L2_REPLACE_AGE )) { 9942 return BCM_E_PARAM; 9943 } 9944 9945 rep_st.flags = flags; 9946 9947 /*Set the detination in rep_st*/ 9948 if (0 == (flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) { 9949 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_replace_dest_setup 9950 (unit, new_module, new_port, new_trunk, 9951 flags & BCM_L2_REPLACE_NEW_TRUNK, 9952 &rep_st.new_dest)); 9953 } 9954 9955 /*Set the match criteria in rep_st*/ 9956 if (flags & BCM_L2_REPLACE_MATCH_DEST) { 9957 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_replace_dest_setup 9958 (unit, match_addr->modid, match_addr->port, 9959 match_addr->tgid, 9960 match_addr->flags & BCM_L2_TRUNK_MEMBER, 9961 &rep_st.match_dest)); 9962 if (rep_st.match_dest.vp != -1) { 9963 if (!((BCM_GPORT_IS_WLAN_PORT(match_addr->port)) || 9964 (BCM_GPORT_IS_NIV_PORT(match_addr->port)) || 9965 (BCM_GPORT_IS_TRILL_PORT(match_addr->port)) || 9966 (BCM_GPORT_IS_VLAN_PORT(match_addr->port)))) { 9967 /* Note: For MPLS, MiM, L2GRE, VXLAN VFI types only */ 9968 rep_st.key_type = SOC_MEM_KEY_L2_ENTRY_1_L2_VFI; 9969 rep_st.ext_key_type = SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI; 9970 } 9971 } 9972 } 9973 9974 if (flags & BCM_L2_REPLACE_MATCH_VLAN) { 9975 rep_st.key_vfi = -1; 9976 if (_BCM_VPN_VFI_IS_SET(match_addr->vid)) { 9977 _BCM_VPN_GET(rep_st.key_vfi, _BCM_VPN_TYPE_VFI, match_addr->vid); 9978 } 9979 if (rep_st.key_vfi != -1) { 9980 if (rep_st.key_vfi > soc_mem_index_max(unit, VFIm)) { 9981 return BCM_E_PARAM; 9982 } 9983 rep_st.key_type = SOC_MEM_KEY_L2_ENTRY_1_L2_VFI; 9984 rep_st.ext_key_type = SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI; 9985 } else { 9986 VLAN_CHK_ID(unit, match_addr->vid); 9987 rep_st.key_vlan = match_addr->vid; 9988 } 9989 } 9990 9991 if (flags & BCM_L2_REPLACE_MATCH_MAC) { 9992 sal_memcpy(&rep_st.key_mac, match_addr->mac, sizeof(bcm_mac_t)); 9993 /* When replace L2 by MAC, key type must be provided. */ 9994 /* Key type is 0 by default for L2 Bridge. */ 9995 /* Here add support for explicitly assigned VFI type */ 9996 if (flags & BCM_L2_REPLACE_VPN_TYPE) { 9997 rep_st.key_type = SOC_MEM_KEY_L2_ENTRY_1_L2_VFI; /* VFI Type */ 9998 rep_st.ext_key_type = SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI; /*EXT VFI Type */ 9999 } 10000 } 10001 10002 if ((NULL == match_addr) && (flags & BCM_L2_REPLACE_VPN_TYPE)) { 10003 rep_st.key_type = SOC_MEM_KEY_L2_ENTRY_1_L2_VFI; 10004 rep_st.ext_key_type = SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI; 10005 } 10006 10007 BCM_IF_ERROR_RETURN(_bcm_tr3_l2_replace_data_mask_setup(unit, &rep_st)); 10008 10009 mode = SOC_CONTROL(unit)->l2x_mode; 10010 /* Delete operation don't require freeze */ 10011 if ((0 == (flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) || 10012 mode != L2MODE_FIFO || _is_soc_tr3_l2_mem_cache_enabled(unit)) { 10013 BCM_IF_ERROR_RETURN(bcm_esw_l2_addr_freeze(unit)); 10014 } 10015 rv = _bcm_tr3_l2_replace_by_hw(unit, &rep_st); 10016 10017 if (SOC_SUCCESS(rv) && (rep_st.flags & BCM_L2_REPLACE_MATCH_STATIC)) { 10018 /* update the entries in mem cache with the bulk op results */ 10019 rv = _soc_tr3_l2_sync_mem_cache(unit, &rep_st); 10020 } 10021 10022 if ((0 == (flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) || 10023 mode != L2MODE_FIFO || _is_soc_tr3_l2_mem_cache_enabled(unit)) { 10024 BCM_IF_ERROR_RETURN(bcm_esw_l2_addr_thaw(unit)); 10025 } 10026 10027 return rv; 10028 } 10029 10030 /* 10031 * Function: 10032 * bcm_tr3_l2_replace 10033 * Purpose: 10034 * Replace L2 entries matching given criterions 10035 * Parameters: 10036 * unit - (IN) Unit number. 10037 * flags - (IN) <UNDEF> 10038 * match_addr - (IN) <UNDEF> 10039 * new_module - (IN) <UNDEF> 10040 * new_port - (IN) <UNDEF> 10041 * new_trunk - (IN) <UNDEF> 10042 * Returns: 10043 * BCM_E_xxx 10044 * Notes: 10045 */ 10046 int 10047 bcm_tr3_l2_replace(int unit, uint32 flags, bcm_l2_addr_t *match_addr, 10048 bcm_module_t new_module, bcm_port_t new_port, 10049 bcm_trunk_t new_trunk) 10050 { 10051 BCM_TR3_L2_INIT(unit); 10052 10053 if (!flags) { 10054 return BCM_E_PARAM; 10055 } 10056 if ((flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE)) && 10057 (flags & BCM_L2_REPLACE_NEW_TRUNK)) { 10058 return BCM_E_PARAM; 10059 } 10060 10061 if ((flags & BCM_L2_REPLACE_DELETE) && (flags & BCM_L2_REPLACE_MATCH_MAC) && 10062 ((flags & BCM_L2_REPLACE_MATCH_UC) || (flags & BCM_L2_REPLACE_MATCH_MC))) { 10063 return BCM_E_PARAM; 10064 } 10065 10066 /* matching L2 address allowed to be NULL together with */ 10067 /* BCM_L2_REPLACE_DELETE/BCM_L2_REPLACE_AGE flag indicating to delete/age all entries. */ 10068 if (NULL == match_addr) { 10069 if (!(flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) { 10070 return BCM_E_PARAM; 10071 } 10072 flags &= ~(BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_MAC | 10073 BCM_L2_REPLACE_MATCH_DEST); 10074 10075 if (flags & BCM_L2_REPLACE_VLAN_AND_VPN_TYPE) { 10076 /* coverity[var_deref_model] */ 10077 BCM_IF_ERROR_RETURN 10078 (_bcm_tr3_l2_replace(unit, flags, match_addr, new_module, 10079 new_port, new_trunk)); 10080 flags ^= BCM_L2_REPLACE_VPN_TYPE; 10081 } 10082 } 10083 10084 /* 10085 * COVERITY 10086 * 10087 * Coverity complains that the NULL pointer match_addr is dereferenced 10088 * in the below call. But it is only dereferenced for one of the 10089 * three flags that are explicitly removed above. 10090 */ 10091 /* coverity[var_deref_model : FALSE] */ 10092 return _bcm_tr3_l2_replace(unit, flags, match_addr, new_module, new_port, 10093 new_trunk); 10094 } 10095 10096 /* 10097 * Function: 10098 * _bcm_tr3_l2_addr_delete_mcast_by_hw 10099 * Purpose: 10100 * Delete all L2 multicast entries by hardware bulk operation. 10101 * Parameters: 10102 * unit - (IN) Unit number. 10103 * Returns: 10104 * BCM_E_xxx 10105 * Notes: 10106 */ 10107 STATIC int 10108 _bcm_tr3_l2_addr_delete_mcast_by_hw(int unit) 10109 { 10110 bcm_mac_t mac_mask; 10111 uint32 rval; 10112 l2_bulk_entry_t l2_bulk; 10113 l2_entry_1_entry_t l2_entry_1; 10114 l2_entry_2_entry_t l2_entry_2; 10115 ext_l2_entry_1_entry_t ext_l2_entry_1; 10116 ext_l2_entry_2_entry_t ext_l2_entry_2; 10117 int field_len; 10118 10119 sal_memset(&mac_mask, 0, sizeof(mac_mask)); 10120 mac_mask[0] = 1; /* bit 40 */ 10121 10122 /* ************************ */ 10123 /* First work on L2_ENTRY_1 */ 10124 /* ************************ */ 10125 10126 /* Set match mask */ 10127 sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1)); 10128 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, VALIDf, 1); 10129 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 1); 10130 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf); 10131 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 10132 (1 << field_len) - 1); 10133 soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, L2__MAC_ADDRf, 10134 mac_mask); 10135 10136 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 10137 sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1)); 10138 SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk)); 10139 10140 /* Set match data */ 10141 /* VALIDf is already set to 1 */ 10142 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 0); 10143 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 10144 SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE); 10145 /* Bit 40 of L2__MAC_ADDRf is already set to 1 */ 10146 sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1)); 10147 SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk)); 10148 10149 /* Set bulk control */ 10150 rval = 0; 10151 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0); 10152 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 10153 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 10154 _SOC_TR3_L2_BULK_BURST_MAX); 10155 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 10156 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 10157 soc_mem_index_count(unit, L2_ENTRY_1m)); 10158 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0); 10159 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 10160 SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 10161 10162 /* *********************** */ 10163 /* Then work on L2_ENTRY_2 */ 10164 /* *********************** */ 10165 10166 /* Set match mask */ 10167 sal_memset(&l2_entry_2, 0, sizeof(l2_entry_2)); 10168 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_0f, 1); 10169 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_1f, 1); 10170 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_0f, 1); 10171 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_1f, 1); 10172 field_len = soc_mem_field_length(unit, L2_ENTRY_2m, KEY_TYPE_0f); 10173 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f, 10174 (1 << field_len) - 1); 10175 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f, 10176 (1 << field_len) - 1); 10177 soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, L2__MAC_ADDRf, 10178 mac_mask); 10179 10180 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 10181 sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2)); 10182 SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk)); 10183 10184 /* Set match data */ 10185 /* VALID_0f and VALID_1f are already set to 1 */ 10186 /* WIDE_0f and WIDE_1f are already set to 1 */ 10187 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f, 10188 SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE); 10189 soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f, 10190 SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE); 10191 /* Bit 40 of L2__MAC_ADDRf is already set to 1 */ 10192 sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2)); 10193 SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk)); 10194 10195 /* Set bulk control */ 10196 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1); 10197 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 10198 soc_mem_index_count(unit, L2_ENTRY_2m)); 10199 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0); 10200 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 10201 SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 10202 10203 /* *************************** */ 10204 /* Next work on EXT_L2_ENTRY_1 */ 10205 /* *************************** */ 10206 10207 if (!soc_feature(unit, soc_feature_esm_support)) { 10208 return BCM_E_NONE; 10209 } 10210 10211 /* Set match mask */ 10212 sal_memset(&ext_l2_entry_1, 0, sizeof(ext_l2_entry_1)); 10213 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, FREEf, 1); 10214 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, KEY_TYPEf); 10215 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 10216 (1 << field_len) - 1); 10217 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, MAC_ADDRf, 10218 mac_mask); 10219 10220 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 10221 sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1)); 10222 SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk)); 10223 10224 /* Set match data */ 10225 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, FREEf, 0); 10226 soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 10227 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE); 10228 /* Bit 40 of MAC_ADDRf is already set to 1 */ 10229 sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1)); 10230 SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk)); 10231 10232 /* Set bulk control */ 10233 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 10234 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 10235 SOC_MEM_TR3_EXT_L2_MAX_ENTRIES); 10236 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1); 10237 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 10238 SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 10239 SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0)); 10240 /* Issue dummy op */ 10241 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0); 10242 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 10243 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1); 10244 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 10245 SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 10246 SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0)); 10247 10248 /* ****************************** */ 10249 /* Finally work on EXT_L2_ENTRY_2 */ 10250 /* ****************************** */ 10251 10252 /* Set match mask */ 10253 sal_memset(&ext_l2_entry_2, 0, sizeof(ext_l2_entry_2)); 10254 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, FREEf, 1); 10255 field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, KEY_TYPEf); 10256 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 10257 (1 << field_len) - 1); 10258 soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, MAC_ADDRf, 10259 mac_mask); 10260 10261 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 10262 sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2)); 10263 SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk)); 10264 10265 /* Set match data */ 10266 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, FREEf, 0); 10267 soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 10268 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE); 10269 /* Bit 40 of MAC_ADDRf is already set to 1 */ 10270 sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2)); 10271 SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk)); 10272 10273 /* Set bulk control */ 10274 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 10275 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1); 10276 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 10277 SOC_MEM_TR3_EXT_L2_MAX_ENTRIES); 10278 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1); 10279 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 10280 SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 10281 SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0)); 10282 /* Issue dummy op */ 10283 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0); 10284 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 10285 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1); 10286 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 10287 SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 10288 SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0)); 10289 10290 return BCM_E_NONE; 10291 } 10292 10293 /* 10294 * Function: 10295 * _bcm_tr3_l2_addr_delete_mcast_by_sw 10296 * Purpose: 10297 * Delete all L2 multicast entries by traversing all L2 tables. 10298 * Parameters: 10299 * unit - (IN) Unit number. 10300 * Returns: 10301 * BCM_E_xxx 10302 * Notes: 10303 */ 10304 STATIC int 10305 _bcm_tr3_l2_addr_delete_mcast_by_sw(int unit) 10306 { 10307 int rv = BCM_E_NONE; 10308 int buf_size, chunksize; 10309 uint32 *l2_tbl_chnk; 10310 soc_mem_t mem; 10311 int chnk_idx, chnk_idx_max, mem_idx_max; 10312 int modified; 10313 int chnk_end, ent_idx; 10314 uint32 *l2_entry; 10315 int key_type; 10316 bcm_mac_t mac_addr; 10317 10318 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 10319 L2_MEM_CHUNKS_DEFAULT); 10320 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 10321 l2_tbl_chnk = soc_cm_salloc(unit, buf_size, "l2 mcast delete"); 10322 if (NULL == l2_tbl_chnk) { 10323 return BCM_E_MEMORY; 10324 } 10325 10326 /* First work on L2_ENTRY_1 */ 10327 10328 mem = L2_ENTRY_1m; 10329 mem_idx_max = soc_mem_index_max(unit, mem); 10330 for (chnk_idx = soc_mem_index_min(unit, mem); 10331 chnk_idx <= mem_idx_max; chnk_idx += chunksize) { 10332 10333 sal_memset((void *)l2_tbl_chnk, 0, buf_size); 10334 chnk_idx_max = ((chnk_idx + chunksize) <= mem_idx_max) ? 10335 (chnk_idx + chunksize - 1) : mem_idx_max; 10336 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 10337 chnk_idx, chnk_idx_max, l2_tbl_chnk); 10338 if (BCM_FAILURE(rv)) { 10339 break; 10340 } 10341 10342 modified = FALSE; 10343 chnk_end = (chnk_idx_max - chnk_idx); 10344 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx++) { 10345 l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 10346 l2_tbl_chnk, ent_idx); 10347 10348 if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) { 10349 continue; 10350 } 10351 10352 key_type = soc_mem_field32_get(unit, mem, l2_entry, 10353 KEY_TYPEf); 10354 if (SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE != key_type) { 10355 continue; 10356 } 10357 10358 soc_mem_mac_addr_get(unit, mem, l2_entry, L2__MAC_ADDRf, mac_addr); 10359 if (!BCM_MAC_IS_MCAST(mac_addr)) { 10360 continue; 10361 } 10362 10363 sal_memcpy(l2_entry, soc_mem_entry_null(unit, mem), 10364 sizeof(l2_entry_1_entry_t)); 10365 modified = TRUE; 10366 } 10367 10368 if (modified) { 10369 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 10370 chnk_idx, chnk_idx_max, l2_tbl_chnk); 10371 if (BCM_FAILURE(rv)) { 10372 break; 10373 } 10374 } 10375 } 10376 10377 if (BCM_FAILURE(rv)) { 10378 soc_cm_sfree(unit, l2_tbl_chnk); 10379 return rv; 10380 } 10381 10382 /* Then work on L2_ENTRY_2 */ 10383 10384 mem = L2_ENTRY_2m; 10385 mem_idx_max = soc_mem_index_max(unit, mem); 10386 for (chnk_idx = soc_mem_index_min(unit, mem); 10387 chnk_idx <= mem_idx_max; 10388 chnk_idx += chunksize) { 10389 10390 sal_memset((void *)l2_tbl_chnk, 0, buf_size); 10391 chnk_idx_max = ((chnk_idx + chunksize) <= mem_idx_max) ? 10392 (chnk_idx + chunksize - 1) : mem_idx_max; 10393 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 10394 chnk_idx, chnk_idx_max, l2_tbl_chnk); 10395 if (BCM_FAILURE(rv)) { 10396 break; 10397 } 10398 10399 modified = FALSE; 10400 chnk_end = (chnk_idx_max - chnk_idx); 10401 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx++) { 10402 l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 10403 l2_tbl_chnk, ent_idx); 10404 10405 if (!soc_mem_field32_get(unit, mem, l2_entry, VALID_0f)) { 10406 continue; 10407 } 10408 if (!soc_mem_field32_get(unit, mem, l2_entry, VALID_1f)) { 10409 continue; 10410 } 10411 10412 key_type = soc_mem_field32_get(unit, mem, l2_entry, 10413 KEY_TYPE_0f); 10414 if (SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE != key_type) { 10415 continue; 10416 } 10417 10418 soc_mem_mac_addr_get(unit, mem, l2_entry, L2__MAC_ADDRf, mac_addr); 10419 if (!BCM_MAC_IS_MCAST(mac_addr)) { 10420 continue; 10421 } 10422 10423 sal_memcpy(l2_entry, soc_mem_entry_null(unit, mem), 10424 sizeof(l2_entry_2_entry_t)); 10425 modified = TRUE; 10426 } 10427 10428 if (modified) { 10429 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 10430 chnk_idx, chnk_idx_max, l2_tbl_chnk); 10431 if (BCM_FAILURE(rv)) { 10432 break; 10433 } 10434 } 10435 } 10436 10437 if (BCM_FAILURE(rv)) { 10438 soc_cm_sfree(unit, l2_tbl_chnk); 10439 return rv; 10440 } 10441 10442 /* Next work on EXT_L2_ENTRY_1 */ 10443 10444 if (!soc_feature(unit, soc_feature_esm_support)) { 10445 return BCM_E_NONE; 10446 } 10447 10448 mem = EXT_L2_ENTRY_1m; 10449 mem_idx_max = soc_mem_index_max(unit, mem); 10450 for (chnk_idx = soc_mem_index_min(unit, mem); 10451 chnk_idx <= mem_idx_max; 10452 chnk_idx += chunksize) { 10453 10454 sal_memset((void *)l2_tbl_chnk, 0, buf_size); 10455 chnk_idx_max = ((chnk_idx + chunksize) <= mem_idx_max) ? 10456 (chnk_idx + chunksize - 1) : mem_idx_max; 10457 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 10458 chnk_idx, chnk_idx_max, l2_tbl_chnk); 10459 if (BCM_FAILURE(rv)) { 10460 break; 10461 } 10462 10463 modified = FALSE; 10464 chnk_end = (chnk_idx_max - chnk_idx); 10465 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx++) { 10466 l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 10467 l2_tbl_chnk, ent_idx); 10468 10469 if (soc_mem_field32_get(unit, mem, l2_entry, FREEf)) { 10470 continue; 10471 } 10472 10473 key_type = soc_mem_field32_get(unit, mem, l2_entry, 10474 KEY_TYPEf); 10475 if (SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE != key_type) { 10476 continue; 10477 } 10478 10479 soc_mem_mac_addr_get(unit, mem, l2_entry, MAC_ADDRf, mac_addr); 10480 if (!BCM_MAC_IS_MCAST(mac_addr)) { 10481 continue; 10482 } 10483 10484 sal_memcpy(l2_entry, soc_mem_entry_null(unit, mem), 10485 sizeof(ext_l2_entry_1_entry_t)); 10486 modified = TRUE; 10487 } 10488 10489 if (modified) { 10490 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 10491 chnk_idx, chnk_idx_max, l2_tbl_chnk); 10492 if (BCM_FAILURE(rv)) { 10493 break; 10494 } 10495 } 10496 } 10497 10498 if (BCM_FAILURE(rv)) { 10499 soc_cm_sfree(unit, l2_tbl_chnk); 10500 return rv; 10501 } 10502 10503 /* Finally work on EXT_L2_ENTRY_2 */ 10504 10505 mem = EXT_L2_ENTRY_2m; 10506 mem_idx_max = soc_mem_index_max(unit, mem); 10507 for (chnk_idx = soc_mem_index_min(unit, mem); 10508 chnk_idx <= mem_idx_max; 10509 chnk_idx += chunksize) { 10510 10511 sal_memset((void *)l2_tbl_chnk, 0, buf_size); 10512 chnk_idx_max = ((chnk_idx + chunksize) <= mem_idx_max) ? 10513 (chnk_idx + chunksize - 1) : mem_idx_max; 10514 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 10515 chnk_idx, chnk_idx_max, l2_tbl_chnk); 10516 if (BCM_FAILURE(rv)) { 10517 break; 10518 } 10519 10520 modified = FALSE; 10521 chnk_end = (chnk_idx_max - chnk_idx); 10522 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx++) { 10523 l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 10524 l2_tbl_chnk, ent_idx); 10525 10526 if (soc_mem_field32_get(unit, mem, l2_entry, FREEf)) { 10527 continue; 10528 } 10529 10530 key_type = soc_mem_field32_get(unit, mem, l2_entry, 10531 KEY_TYPEf); 10532 if (SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE != key_type) { 10533 continue; 10534 } 10535 10536 soc_mem_mac_addr_get(unit, mem, l2_entry, MAC_ADDRf, mac_addr); 10537 if (!BCM_MAC_IS_MCAST(mac_addr)) { 10538 continue; 10539 } 10540 10541 sal_memcpy(l2_entry, soc_mem_entry_null(unit, mem), 10542 sizeof(ext_l2_entry_2_entry_t)); 10543 modified = TRUE; 10544 } 10545 10546 if (modified) { 10547 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 10548 chnk_idx, chnk_idx_max, l2_tbl_chnk); 10549 if (BCM_FAILURE(rv)) { 10550 break; 10551 } 10552 } 10553 } 10554 10555 soc_cm_sfree(unit, l2_tbl_chnk); 10556 return rv; 10557 } 10558 10559 /* 10560 * Function: 10561 * bcm_tr3_l2_addr_delete_mcast 10562 * Purpose: 10563 * Delete all L2 multicast entries. 10564 * Parameters: 10565 * unit - (IN) Unit number. 10566 * bulk - (IN) Hardware bulk delete indication. 10567 * Returns: 10568 * BCM_E_xxx 10569 * Notes: 10570 */ 10571 int 10572 bcm_tr3_l2_addr_delete_mcast(int unit, int bulk) 10573 { 10574 int rv, seconds, enabled; 10575 10576 SOC_IF_ERROR_RETURN 10577 (SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled)); 10578 if (enabled) { 10579 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit)); 10580 } 10581 _BCM_ALL_L2X_MEM_LOCK(unit); 10582 10583 if (bulk) { 10584 rv = _bcm_tr3_l2_addr_delete_mcast_by_hw(unit); 10585 } else { 10586 rv = _bcm_tr3_l2_addr_delete_mcast_by_sw(unit); 10587 } 10588 10589 _BCM_ALL_L2X_MEM_UNLOCK(unit); 10590 if(enabled) { 10591 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds)); 10592 } 10593 return rv; 10594 } 10595 10596 /* 10597 * Function: 10598 * bcm_tr3_cross_connect_add 10599 * Purpose: 10600 * Add a VLAN cross connect entry 10601 * Parameters: 10602 * unit - Device unit number 10603 * outer_vlan - Outer vlan ID 10604 * inner_vlan - Inner vlan ID 10605 * port_1 - First port in the cross-connect 10606 * port_2 - Second port in the cross-connect 10607 * Returns: 10608 * BCM_E_NONE - Success. 10609 * BCM_E_XXX 10610 */ 10611 int 10612 bcm_tr3_l2_cross_connect_add(int unit, bcm_vlan_t outer_vlan, 10613 bcm_vlan_t inner_vlan, bcm_gport_t port_1, 10614 bcm_gport_t port_2) 10615 { 10616 _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup; 10617 int rv, gport_id; 10618 bcm_port_t port_out; 10619 bcm_module_t mod_out; 10620 bcm_trunk_t trunk_id; 10621 10622 BCM_TR3_L2_INIT(unit); 10623 10624 sal_memset(&l2_entries, 0, sizeof (l2_entries)); 10625 l2_entries.entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1; 10626 if ((outer_vlan < BCM_VLAN_DEFAULT) || (outer_vlan > BCM_VLAN_MAX)) { 10627 return BCM_E_PARAM; 10628 } else if (inner_vlan == BCM_VLAN_INVALID) { 10629 /* Single cross-connect (use only outer_vid) */ 10630 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), 10631 KEY_TYPEf, 10632 SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT); 10633 } else { 10634 if ((inner_vlan < BCM_VLAN_DEFAULT) || (inner_vlan > BCM_VLAN_MAX)) { 10635 return BCM_E_PARAM; 10636 } 10637 /* Double cross-connect (use both outer_vid and inner_vid) */ 10638 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), 10639 KEY_TYPEf, 10640 SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT); 10641 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VLAN__IVIDf, inner_vlan); 10642 } 10643 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), STATIC_BITf, 1); 10644 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VALIDf, 1); 10645 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VLAN__OVIDf, outer_vlan); 10646 10647 /* See if the entry already exists */ 10648 sal_memset(&l2_entries_lookup, 0, sizeof (l2_entries_lookup)); 10649 l2_entries.entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1; 10650 rv = _bcm_tr3_l2_entries_lookup(unit, &l2_entries, &l2_entries_lookup); 10651 if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) { 10652 return rv; 10653 } 10654 10655 /* Resolve first port */ 10656 BCM_IF_ERROR_RETURN 10657 (_bcm_esw_gport_resolve(unit, port_1, &mod_out, &port_out, &trunk_id, 10658 &gport_id)); 10659 if (BCM_GPORT_IS_TRUNK(port_1)) { 10660 soc_L2_ENTRY_1m_field32_set(unit, 10661 &(l2_entries.l2_entry_1), 10662 VLAN__DEST_TYPE_0f, 1); 10663 soc_L2_ENTRY_1m_field32_set(unit, 10664 &(l2_entries.l2_entry_1), 10665 VLAN__TGID_0f, trunk_id); 10666 } else if (BCM_GPORT_IS_SUBPORT_GROUP(port_1) 10667 || BCM_GPORT_IS_VLAN_PORT(port_1)) { 10668 soc_L2_ENTRY_1m_field32_set(unit, 10669 &(l2_entries.l2_entry_1), 10670 VLAN__DEST_TYPE_0f, 0x2); 10671 soc_L2_ENTRY_1m_field32_set(unit, 10672 &(l2_entries.l2_entry_1), 10673 VLAN__DESTINATION_0f, gport_id); 10674 } else { 10675 if ((mod_out == -1) ||(port_out == -1)) { 10676 return BCM_E_PORT; 10677 } 10678 soc_L2_ENTRY_1m_field32_set(unit, 10679 &(l2_entries.l2_entry_1), 10680 VLAN__DEST_TYPE_0f, 0); 10681 soc_L2_ENTRY_1m_field32_set(unit, 10682 &(l2_entries.l2_entry_1), 10683 VLAN__MODULE_ID_0f, mod_out); 10684 soc_L2_ENTRY_1m_field32_set(unit, 10685 &(l2_entries.l2_entry_1), 10686 VLAN__PORT_NUM_0f, port_out); 10687 } 10688 10689 /* Resolve second port */ 10690 BCM_IF_ERROR_RETURN 10691 (_bcm_esw_gport_resolve(unit, port_2, &mod_out, &port_out, &trunk_id, 10692 &gport_id)); 10693 if (BCM_GPORT_IS_TRUNK(port_2)) { 10694 soc_L2_ENTRY_1m_field32_set(unit, 10695 &(l2_entries.l2_entry_1), 10696 VLAN__DEST_TYPE_1f, 1); 10697 soc_L2_ENTRY_1m_field32_set(unit, 10698 &(l2_entries.l2_entry_1), 10699 VLAN__TGID_1f, trunk_id); 10700 } else if (BCM_GPORT_IS_SUBPORT_GROUP(port_2) 10701 || BCM_GPORT_IS_VLAN_PORT(port_2)) { 10702 soc_L2_ENTRY_1m_field32_set(unit, 10703 &(l2_entries.l2_entry_1), 10704 VLAN__DEST_TYPE_1f, 0x2); 10705 soc_L2_ENTRY_1m_field32_set(unit, 10706 &(l2_entries.l2_entry_1), 10707 VLAN__DESTINATION_1f, gport_id); 10708 } else { 10709 if ((mod_out == -1) ||(port_out == -1)) { 10710 return BCM_E_PORT; 10711 } 10712 soc_L2_ENTRY_1m_field32_set(unit, 10713 &(l2_entries.l2_entry_1), 10714 VLAN__DEST_TYPE_1f, 0); 10715 soc_L2_ENTRY_1m_field32_set(unit, 10716 &(l2_entries.l2_entry_1), 10717 VLAN__MODULE_ID_1f, mod_out); 10718 soc_L2_ENTRY_1m_field32_set(unit, 10719 &(l2_entries.l2_entry_1), 10720 VLAN__PORT_NUM_1f, port_out); 10721 } 10722 10723 rv = BCM_E_FULL; 10724 rv = soc_mem_insert_return_old(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 10725 (void *)&(l2_entries.l2_entry_1), 10726 (void *)&(l2_entries.l2_entry_1)); 10727 if (rv == BCM_E_FULL) { 10728 rv = _bcm_tr3_l2_hash_dynamic_replace(unit, &l2_entries); 10729 } 10730 if (BCM_SUCCESS(rv)) { 10731 if (soc_feature(unit, soc_feature_ppa_bypass)) { 10732 SOC_CONTROL(unit)->l2x_ppa_bypass = TRUE; 10733 } 10734 } 10735 10736 return rv; 10737 } 10738 10739 /* 10740 * Function: 10741 * bcm_tr3_l2_cross_connect_delete 10742 * Purpose: 10743 * Delete a VLAN cross connect entry 10744 * Parameters: 10745 * unit - Device unit number 10746 * outer_vlan - Outer vlan ID 10747 * inner_vlan - Inner vlan ID 10748 * Returns: 10749 * BCM_E_NONE - Success. 10750 * BCM_E_XXX 10751 */ 10752 int 10753 bcm_tr3_l2_cross_connect_delete(int unit, bcm_vlan_t outer_vlan, 10754 bcm_vlan_t inner_vlan) 10755 { 10756 _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup; 10757 int mb_index; 10758 int rv; 10759 10760 BCM_TR3_L2_INIT(unit); 10761 10762 sal_memset(&l2_entries, 0, sizeof (l2_entries)); 10763 l2_entries.entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1; 10764 if ((outer_vlan < BCM_VLAN_DEFAULT) || (outer_vlan > BCM_VLAN_MAX)) { 10765 return BCM_E_PARAM; 10766 } else if (inner_vlan == BCM_VLAN_INVALID) { 10767 /* Single cross-connect (use only outer_vid) */ 10768 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), 10769 KEY_TYPEf, 10770 SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT); 10771 } else { 10772 if ((inner_vlan < BCM_VLAN_DEFAULT) || (inner_vlan > BCM_VLAN_MAX)) { 10773 return BCM_E_PARAM; 10774 } 10775 /* Double cross-connect (use both outer_vid and inner_vid) */ 10776 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), 10777 KEY_TYPEf, 10778 SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT); 10779 10780 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VLAN__IVIDf, inner_vlan); 10781 } 10782 10783 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), STATIC_BITf, 1); 10784 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VALIDf, 1); 10785 soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VLAN__OVIDf, outer_vlan); 10786 10787 _BCM_ALL_L2X_MEM_LOCK(unit); 10788 rv = _bcm_tr3_l2_entries_lookup(unit, (void *)&l2_entries, 10789 (void *)&l2_entries_lookup); 10790 10791 if (BCM_E_NONE != rv) { 10792 _BCM_ALL_L2X_MEM_UNLOCK(unit); 10793 return rv; 10794 } 10795 10796 if (!SOC_L2X_GROUP_ENABLE_GET(unit)) { 10797 mb_index = _bcm_tr3_l2hw_entries_field32_get(unit, &l2_entries_lookup, 10798 _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX); 10799 _bcm_tr3_mac_block_delete(unit, mb_index); 10800 } 10801 10802 rv = _bcm_tr3_l2_entries_delete(unit, &l2_entries_lookup); 10803 _BCM_ALL_L2X_MEM_UNLOCK(unit); 10804 10805 return rv; 10806 } 10807 10808 /* 10809 * Function: 10810 * bcm_tr3_l2_cross_connect_delete_all 10811 * Purpose: 10812 * Delete all VLAN cross connect entries 10813 * Parameters: 10814 * unit - Device unit number 10815 * Returns: 10816 * BCM_E_NONE - Success. 10817 * BCM_E_XXX 10818 */ 10819 int 10820 bcm_tr3_l2_cross_connect_delete_all(int unit) 10821 { 10822 int index_min, index_max, index, mem_max; 10823 l2_entry_1_entry_t *l2_entry_1; 10824 int rv = BCM_E_NONE; 10825 int *buffer = NULL; 10826 int mem_size, idx, chnk_end; 10827 int chunksize, modified; 10828 soc_mem_t mem = L2_ENTRY_1m; 10829 10830 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 10831 L2_MEM_CHUNKS_DEFAULT); 10832 index_min = soc_mem_index_min(unit, mem); 10833 mem_max = soc_mem_index_max(unit, mem); 10834 mem_size = chunksize * sizeof(l2_entry_only_entry_t); 10835 10836 buffer = soc_cm_salloc(unit, mem_size, "L2_ENTRY_1_delete"); 10837 if (NULL == buffer) { 10838 return SOC_E_MEMORY; 10839 } 10840 10841 soc_mem_lock(unit, L2_ENTRY_1m); 10842 for (idx = index_min; idx <= mem_max; idx += chunksize) { 10843 index_max = idx + chunksize - 1; 10844 if ( index_max > mem_max) { 10845 index_max = mem_max; 10846 } 10847 if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, 10848 idx, index_max, buffer)) < 0 ) { 10849 soc_cm_sfree(unit, buffer); 10850 soc_mem_unlock(unit, L2_ENTRY_1m); 10851 return rv; 10852 } 10853 modified = 0; 10854 chnk_end = index_max - idx; 10855 for (index = 0; index <= chnk_end; index++) { 10856 l2_entry_1 = 10857 soc_mem_table_idx_to_pointer(unit, mem, l2_entry_1_entry_t *, 10858 buffer, index); 10859 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VALIDf) && 10860 ((soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, KEY_TYPEf) == 10861 SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT) || 10862 (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, KEY_TYPEf) == 10863 SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT))) { 10864 sal_memcpy(l2_entry_1, soc_mem_entry_null(unit, mem), 10865 sizeof(l2_entry_1_entry_t)); 10866 modified = 1; 10867 } 10868 } 10869 if (modified) { 10870 if ((rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 10871 idx, index_max, buffer)) < 0) { 10872 soc_cm_sfree(unit, buffer); 10873 soc_mem_unlock(unit, L2_ENTRY_1m); 10874 return rv; 10875 } 10876 } 10877 } 10878 10879 if (SOC_CONTROL(unit)->arlShadow != NULL) { 10880 sal_mutex_take(SOC_CONTROL(unit)->arlShadowMutex, sal_mutex_FOREVER); 10881 (void) shr_avl_delete_all(SOC_CONTROL(unit)->arlShadow); 10882 sal_mutex_give(SOC_CONTROL(unit)->arlShadowMutex); 10883 } 10884 soc_cm_sfree(unit, buffer); 10885 soc_mem_unlock(unit, L2_ENTRY_1m); 10886 10887 return rv; 10888 } 10889 10890 /* 10891 * Function: 10892 * bcm_tr3_l2_cross_connect_traverse 10893 * Purpose: 10894 * Walks through the valid cross connect entries and calls 10895 * the user supplied callback function for each entry. 10896 * Parameters: 10897 * unit - (IN) bcm device. 10898 * trav_fn - (IN) Callback function. 10899 * user_data - (IN) User data to be passed to callback function. 10900 * Returns: 10901 * BCM_E_NONE - Success. 10902 * BCM_E_XXX 10903 */ 10904 int 10905 bcm_tr3_l2_cross_connect_traverse(int unit, 10906 bcm_vlan_cross_connect_traverse_cb cb, 10907 void *user_data) 10908 { 10909 int index_min, index_max, index, mem_max; 10910 l2_entry_1_entry_t *l2_entry_1; 10911 int rv = SOC_E_NONE; 10912 int *buffer = NULL; 10913 int mem_size, idx, chunksize, chnk_end; 10914 bcm_gport_t port_1 = BCM_GPORT_INVALID, port_2 = BCM_GPORT_INVALID; 10915 bcm_vlan_t outer_vlan, inner_vlan; 10916 bcm_port_t port_in, port_out; 10917 bcm_module_t mod_in, mod_out; 10918 soc_mem_t mem = L2_ENTRY_1m; 10919 10920 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 10921 L2_MEM_CHUNKS_DEFAULT); 10922 index_min = soc_mem_index_min(unit, mem); 10923 mem_max = soc_mem_index_max(unit, mem); 10924 mem_size = chunksize * sizeof(l2_entry_1_entry_t); 10925 10926 buffer = soc_cm_salloc(unit, mem_size, "cross connect traverse"); 10927 if (NULL == buffer) { 10928 return SOC_E_MEMORY; 10929 } 10930 sal_memset((void *)buffer, 0, mem_size); 10931 10932 soc_mem_lock(unit, L2_ENTRY_1m); 10933 for (idx = index_min; idx <= mem_max; idx += chunksize) { 10934 index_max = idx + chunksize - 1; 10935 if ( index_max > mem_max) { 10936 index_max = mem_max; 10937 } 10938 if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, 10939 idx, index_max, buffer)) < 0 ) { 10940 soc_cm_sfree(unit, buffer); 10941 soc_mem_unlock(unit, L2_ENTRY_1m); 10942 return rv; 10943 } 10944 chnk_end = index_max - idx; 10945 for (index = 0; index <= chnk_end ; index++) { 10946 l2_entry_1 = 10947 soc_mem_table_idx_to_pointer(unit, mem, 10948 l2_entry_1_entry_t *, buffer, index); 10949 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VALIDf)) { 10950 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, KEY_TYPEf) == 10951 SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT) { 10952 /* Double cross-connect entry */ 10953 inner_vlan = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__IVIDf); 10954 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, KEY_TYPEf) == 10955 SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT) { 10956 /* Single cross-connect entry */ 10957 inner_vlan = BCM_VLAN_INVALID; 10958 } else { 10959 /* Not a cross-connect entry, ignore */ 10960 continue; 10961 } 10962 outer_vlan = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__OVIDf); 10963 10964 /* Get first port params */ 10965 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_0f) == 2) { 10966 int vpg; 10967 vpg = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DESTINATION_0f); 10968 BCM_GPORT_SUBPORT_GROUP_SET(port_1, vpg); 10969 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_0f) == 1) { 10970 BCM_GPORT_TRUNK_SET(port_1, 10971 soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__TGID_0f)); 10972 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_0f) == 0) { 10973 port_in = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__PORT_NUM_0f); 10974 mod_in = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__MODULE_ID_0f); 10975 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 10976 mod_in, port_in, &mod_out, &port_out); 10977 if (BCM_FAILURE(rv)) { 10978 soc_cm_sfree(unit, buffer); 10979 soc_mem_unlock(unit, L2_ENTRY_1m); 10980 return rv; 10981 } 10982 BCM_GPORT_MODPORT_SET(port_1, mod_out, port_out); 10983 } 10984 10985 /* Get second port params */ 10986 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_1f) == 2) { 10987 int vpg; 10988 vpg = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DESTINATION_1f); 10989 BCM_GPORT_SUBPORT_GROUP_SET(port_2, vpg); 10990 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_1f) == 1) { 10991 BCM_GPORT_TRUNK_SET(port_2, soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__TGID_1f)); 10992 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_1f) == 0) { 10993 port_in = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__PORT_NUM_1f); 10994 mod_in = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__MODULE_ID_1f); 10995 BCM_IF_ERROR_RETURN 10996 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 10997 mod_in, port_in, &mod_out, &port_out)); 10998 BCM_GPORT_MODPORT_SET(port_2, mod_out, port_out); 10999 } 11000 11001 /* Call application call-back */ 11002 rv = cb(unit, outer_vlan, inner_vlan, port_1, port_2, user_data); 11003 #ifdef BCM_CB_ABORT_ON_ERR 11004 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 11005 soc_cm_sfree(unit, buffer); 11006 soc_mem_unlock(unit, L2_ENTRY_1m); 11007 return rv; 11008 } 11009 #endif 11010 } 11011 } 11012 } 11013 soc_cm_sfree(unit, buffer); 11014 soc_mem_unlock(unit, L2_ENTRY_1m); 11015 11016 return BCM_E_NONE; 11017 } 11018 11019 int 11020 bcm_tr3_failover_ring_config_set(int unit, bcm_failover_ring_t *failover_ring) 11021 { 11022 int match_type = -1, i, rv, gport_id; 11023 uint32 map_size, rval; 11024 SHR_BITDCL *vlan_map = NULL, *vpn_map = NULL; 11025 bcm_module_t mod_out; 11026 bcm_port_t port_out; 11027 bcm_trunk_t trunk_id; 11028 /* 11029 * match_type = -1 means forced_flooding/learn_disabling based on physical 11030 * port or VP 11031 * match_type = 0 means forced_flooding/learn_disabling based on VLAN or 11032 * port + VLAN 11033 * match_type = 1 means forced_flooding/learn_disabling based on VPN or 11034 * VP + VPN 11035 */ 11036 if (!failover_ring) { 11037 return BCM_E_PARAM; 11038 } 11039 /* 11040 * If only one of the ports(port0 or port1) are valid, then we have to write 11041 * that port value into both FLOOD_LEARN_MATCH_PORT_Ar and 11042 * FLOOD_LEARN_MATCH_PORT_Br due to hardware behavior. 11043 */ 11044 if ((failover_ring->port0 != BCM_GPORT_INVALID) && 11045 (failover_ring->port1 == BCM_GPORT_INVALID)) { 11046 failover_ring->port1 = failover_ring->port0; 11047 } 11048 if ((failover_ring->port1 != BCM_GPORT_INVALID) && 11049 (failover_ring->port0 == BCM_GPORT_INVALID)) { 11050 failover_ring->port0 = failover_ring->port1; 11051 } 11052 /* Configure h/w tables and memory */ 11053 if (failover_ring->flags & 11054 (BCM_FAILOVER_LOOKUP_DISABLE | BCM_FAILOVER_LEARN_DISABLE)) { 11055 if(failover_ring->port0 != BCM_GPORT_INVALID) { 11056 BCM_IF_ERROR_RETURN 11057 (_bcm_esw_gport_resolve(unit, failover_ring->port0, &mod_out, 11058 &port_out, &trunk_id, &gport_id)); 11059 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_MATCH_PORT_Ar(unit, &rval)); 11060 if (-1 != gport_id) { 11061 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 11062 DESTINATIONf, gport_id); 11063 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 11064 DEST_TYPEf, 2); 11065 } else if (BCM_TRUNK_INVALID != trunk_id) { 11066 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 11067 DESTINATIONf, trunk_id); 11068 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 11069 DEST_TYPEf, 1); 11070 } else if (!(-1 == port_out || -1 == mod_out)) { 11071 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 11072 PORT_NUMf, port_out); 11073 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 11074 MODULE_IDf, mod_out); 11075 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 11076 DEST_TYPEf, 0); 11077 } 11078 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_MATCH_PORT_Ar(unit, rval)); 11079 } 11080 if (failover_ring->port1 != BCM_GPORT_INVALID) { 11081 BCM_IF_ERROR_RETURN 11082 (_bcm_esw_gport_resolve(unit, failover_ring->port1, &mod_out, 11083 &port_out, &trunk_id, &gport_id)); 11084 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_MATCH_PORT_Br(unit, &rval)); 11085 if (-1 != gport_id) { 11086 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 11087 DESTINATIONf, gport_id); 11088 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 11089 DEST_TYPEf, 2); 11090 } else if (BCM_TRUNK_INVALID != trunk_id) { 11091 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 11092 DESTINATIONf, trunk_id); 11093 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 11094 DEST_TYPEf, 1); 11095 } else if (!(-1 == port_out || -1 == mod_out)) { 11096 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 11097 PORT_NUMf, port_out); 11098 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 11099 MODULE_IDf, mod_out); 11100 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 11101 DEST_TYPEf, 0); 11102 } 11103 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_MATCH_PORT_Br(unit, rval)); 11104 } 11105 /* 11106 * KT2 and TR3 have hardware restriction that forced_flooding / 11107 * learn_disabling can be set only for all VPNs and not for set 11108 * of VPNs. Hence, vpn_vector will be used only for future 11109 * devices which overcome this hardware restriction. 11110 */ 11111 if (failover_ring->flags & BCM_FAILOVER_VPN_TYPE) { 11112 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 11113 if (SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)) { 11114 match_type = 1; 11115 } else 11116 #endif 11117 { 11118 map_size = SHR_BITALLOCSIZE(BCM_VPN_MAX+1); 11119 vpn_map = soc_cm_salloc(unit, map_size, "Failover ring vpn map"); 11120 if (NULL == vpn_map) { 11121 return (SOC_E_MEMORY); 11122 } 11123 sal_memset(vpn_map, 0, map_size); 11124 for (i = BCM_VPN_MIN; i < BCM_VPN_MAX; i++) { 11125 if (BCM_VPN_VEC_GET(failover_ring->vpn_vector, i)) { 11126 SHR_BITSET(vpn_map, i); 11127 match_type = 1; 11128 } 11129 } 11130 if (match_type == 1) { 11131 if ((rv = soc_mem_write_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am, 11132 MEM_BLOCK_ALL, 0, soc_mem_index_max( 11133 unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am), 11134 vpn_map)) < 0) { 11135 soc_cm_sfree(unit, vpn_map); 11136 return rv; 11137 } 11138 if ((rv = soc_mem_write_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm, 11139 MEM_BLOCK_ALL, 0, soc_mem_index_max( 11140 unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm), 11141 vpn_map)) < 0) { 11142 soc_cm_sfree(unit, vpn_map); 11143 return rv; 11144 } 11145 } 11146 soc_cm_sfree(unit, vpn_map); 11147 } 11148 if (match_type == 1) { 11149 /* 11150 * As we are writing vlan_vector/vpn_vector into both 11151 * FLOOD_LEARN_MATCH_VLANS_PORT_Am and 11152 * FLOOD_LEARN_MATCH_VLANS_PORT_Bm, we have to set key_type into 11153 * both FLOOD_LEARN_KEY_TYPE_PORT_Ar and 11154 * FLOOD_LEARN_KEY_TYPE_PORT_Br. 11155 */ 11156 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_KEY_TYPE_PORT_Ar(unit, 11157 &rval)); 11158 #ifdef BCM_KATANA2_SUPPORT 11159 if (SOC_IS_KATANA2(unit)) { 11160 soc_reg_field_set(unit, FLOOD_LEARN_KEY_TYPE_PORT_Ar, &rval, 11161 KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_VFI); 11162 } 11163 #endif 11164 if (SOC_IS_TRIUMPH3(unit)) { 11165 soc_reg_field_set(unit, FLOOD_LEARN_KEY_TYPE_PORT_Ar, &rval, 11166 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI); 11167 } 11168 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_KEY_TYPE_PORT_Ar(unit, 11169 rval)); 11170 11171 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_KEY_TYPE_PORT_Br(unit, 11172 &rval)); 11173 #ifdef BCM_KATANA2_SUPPORT 11174 if (SOC_IS_KATANA2(unit)) { 11175 soc_reg_field_set(unit, FLOOD_LEARN_KEY_TYPE_PORT_Br, &rval, 11176 KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_VFI); 11177 } 11178 #endif 11179 if (SOC_IS_TRIUMPH3(unit)) { 11180 soc_reg_field_set(unit, FLOOD_LEARN_KEY_TYPE_PORT_Br, &rval, 11181 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI); 11182 } 11183 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_KEY_TYPE_PORT_Br(unit, 11184 rval)); 11185 } 11186 } else { 11187 map_size = SHR_BITALLOCSIZE(BCM_VLAN_MAX+1); 11188 vlan_map = soc_cm_salloc(unit, map_size, "Failover ring vlan map"); 11189 if (NULL == vlan_map) { 11190 return (SOC_E_MEMORY); 11191 } 11192 sal_memset(vlan_map, 0, map_size); 11193 for (i = BCM_VLAN_MIN; i < BCM_VLAN_MAX; i++) { 11194 if (BCM_VLAN_VEC_GET(failover_ring->vlan_vector, i)) { 11195 SHR_BITSET(vlan_map, i); 11196 match_type = 0; 11197 } 11198 } 11199 if ((rv = soc_mem_write_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am, 11200 MEM_BLOCK_ALL, 0, soc_mem_index_max( 11201 unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am), 11202 vlan_map)) < 0) { 11203 soc_cm_sfree(unit, vlan_map); 11204 return rv; 11205 } 11206 if ((rv = soc_mem_write_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm, 11207 MEM_BLOCK_ALL, 0, soc_mem_index_max( 11208 unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm), 11209 vlan_map)) < 0) { 11210 soc_cm_sfree(unit, vlan_map); 11211 return rv; 11212 } 11213 soc_cm_sfree(unit, vlan_map); 11214 } 11215 11216 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_CONTROLr(unit, &rval)); 11217 if (failover_ring->flags & BCM_FAILOVER_LOOKUP_DISABLE) { 11218 soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, FLOOD_FORCEf, 11219 1); 11220 } 11221 if (failover_ring->flags & BCM_FAILOVER_LEARN_DISABLE) { 11222 soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, LEARN_DISABLEf, 11223 1); 11224 } 11225 if (match_type != -1) { 11226 soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 11227 MATCH_KEY_TYPE_PORT_Af, 1); 11228 soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 11229 MATCH_KEY_TYPE_PORT_Bf, 1); 11230 } 11231 if ((failover_ring->port0 != BCM_GPORT_INVALID) || 11232 (failover_ring->port1 != BCM_GPORT_INVALID)) { 11233 /* 11234 * In KT2 and TR3, as we do forced_flooding/learn_disabling for all 11235 * VPNs irrespective of VPs, we would not set MATCH_PORT_Af and 11236 * MATCH_PORT_Bf if match_type is 1. 11237 */ 11238 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 11239 if ((SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)) && 11240 (match_type != 1)) 11241 #endif 11242 { 11243 soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 11244 MATCH_PORT_Af, 1); 11245 soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 11246 MATCH_PORT_Bf, 1); 11247 } 11248 } 11249 if (match_type != -1) { 11250 /* 11251 * In KT2 and TR3, as we would not consider vpn_vector due to 11252 * hardware restriction, we won't set MATCH_VLANS_PORT_Af and 11253 * MATCH_VLANS_PORT_Bf if match_type is 1. 11254 */ 11255 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 11256 if ((SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)) && 11257 (match_type != 1)) 11258 #endif 11259 { 11260 soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 11261 MATCH_VLANS_PORT_Af, 1); 11262 soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 11263 MATCH_VLANS_PORT_Bf, 1); 11264 } 11265 } 11266 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_CONTROLr(unit, rval)); 11267 } else if (failover_ring->flags & BCM_FAILOVER_CLEAR) { 11268 rval = 0; 11269 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_CONTROLr(unit, rval)); 11270 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_MATCH_PORT_Ar(unit, rval)); 11271 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_MATCH_PORT_Br(unit, rval)); 11272 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_KEY_TYPE_PORT_Ar(unit, rval)); 11273 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_KEY_TYPE_PORT_Br(unit, rval)); 11274 SOC_IF_ERROR_RETURN 11275 (soc_mem_clear(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am, COPYNO_ALL, 11276 0)); 11277 SOC_IF_ERROR_RETURN 11278 (soc_mem_clear(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm, COPYNO_ALL, 11279 0)); 11280 } 11281 return BCM_E_NONE; 11282 } 11283 11284 int 11285 bcm_tr3_failover_ring_config_get(int unit, bcm_failover_ring_t *failover_ring) 11286 { 11287 int i, rv, vp, dest_type = -1; 11288 uint8 no_clear = 0; 11289 _bcm_gport_dest_t dest; 11290 SHR_BITDCL *vlan_map = NULL, *vpn_map = NULL; 11291 uint32 map_size, rval, is_vfi; 11292 11293 COMPILER_REFERENCE(vp); 11294 11295 if (!failover_ring) { 11296 return BCM_E_PARAM; 11297 } 11298 bcm_failover_ring_t_init(failover_ring); 11299 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_KEY_TYPE_PORT_Ar(unit, &rval)); 11300 is_vfi = soc_reg_field_get(unit, FLOOD_LEARN_KEY_TYPE_PORT_Ar, rval, 11301 KEY_TYPEf); 11302 /* 11303 * is_vfi = zero means KEY_TYPE is VLAN 11304 * is_vfi = non-zero value means KEY_TYPE is VFI 11305 */ 11306 if (is_vfi) { 11307 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 11308 if (!(SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit))) 11309 #endif 11310 { 11311 /* 11312 * KT2 && TR3 have hardware restriction that forced_flooding / 11313 * learn_disabling can be set only for all VPNs and not for set of 11314 * VPNs. Hence, vpn_vector will be used only for future devices 11315 * which overcome this hardware restriction. 11316 */ 11317 /* Construct vpn vector */ 11318 map_size = SHR_BITALLOCSIZE(BCM_VPN_MAX+1); 11319 vpn_map = soc_cm_salloc(unit, map_size, "Failover ring vpn map"); 11320 if (NULL == vpn_map) { 11321 return (SOC_E_MEMORY); 11322 } 11323 sal_memset(vpn_map, 0, map_size); 11324 if ((rv = soc_mem_read_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am, 11325 MEM_BLOCK_ALL, 0, soc_mem_index_max(unit, 11326 FLOOD_LEARN_MATCH_VLANS_PORT_Am), 11327 vpn_map)) < 0) { 11328 soc_cm_sfree(unit, vpn_map); 11329 return rv; 11330 } 11331 for (i = BCM_VPN_MIN; i < BCM_VPN_MAX; i++) { 11332 if (BCM_VPN_VEC_GET(vpn_map, i)) { 11333 SHR_BITSET(failover_ring->vpn_vector, i); 11334 } 11335 } 11336 soc_cm_sfree(unit, vpn_map); 11337 } 11338 } else { 11339 /* Construct vlan vector */ 11340 map_size = SHR_BITALLOCSIZE(BCM_VLAN_MAX+1); 11341 vlan_map = soc_cm_salloc(unit, map_size, "Failover ring vlan map"); 11342 if (NULL == vlan_map) { 11343 return (SOC_E_MEMORY); 11344 } 11345 sal_memset(vlan_map, 0, map_size); 11346 if ((rv = soc_mem_read_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am, 11347 MEM_BLOCK_ALL, 0, soc_mem_index_max(unit, 11348 FLOOD_LEARN_MATCH_VLANS_PORT_Am), 11349 vlan_map)) < 0) { 11350 soc_cm_sfree(unit, vlan_map); 11351 return rv; 11352 } 11353 for (i = BCM_VLAN_MIN; i < BCM_VLAN_MAX; i++) { 11354 if (BCM_VLAN_VEC_GET(vlan_map, i)) { 11355 SHR_BITSET(failover_ring->vlan_vector, i); 11356 } 11357 } 11358 soc_cm_sfree(unit, vlan_map); 11359 } 11360 /* Construct flags */ 11361 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_CONTROLr(unit, &rval)); 11362 if (soc_reg_field_get(unit, FLOOD_LEARN_CONTROLr, rval, FLOOD_FORCEf)) { 11363 failover_ring->flags |= BCM_FAILOVER_LOOKUP_DISABLE; 11364 no_clear++; 11365 } 11366 if (soc_reg_field_get(unit, FLOOD_LEARN_CONTROLr, rval, LEARN_DISABLEf)) { 11367 failover_ring->flags |= BCM_FAILOVER_LEARN_DISABLE; 11368 no_clear++; 11369 } 11370 if (is_vfi) { 11371 failover_ring->flags |= BCM_FAILOVER_VPN_TYPE; 11372 } 11373 if (no_clear == 0) { 11374 failover_ring->flags |= BCM_FAILOVER_CLEAR; 11375 } 11376 /* Construct gport info */ 11377 _bcm_gport_dest_t_init(&dest); 11378 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_MATCH_PORT_Ar(unit, &rval)); 11379 if (rval) { 11380 dest_type = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 11381 DEST_TYPEf); 11382 } else { 11383 dest_type = -1; 11384 } 11385 if (dest_type == 0) { 11386 dest.port = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 11387 PORT_NUMf); 11388 dest.modid = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 11389 MODULE_IDf); 11390 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 11391 } else if (dest_type == 1) { 11392 dest.tgid = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 11393 DESTINATIONf); 11394 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 11395 } else if (dest_type == 2) { 11396 vp = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 11397 DESTINATIONf); 11398 #if defined(INCLUDE_L3) 11399 if ((rv = _bcm_vp_gport_dest_fill(unit, vp, &dest)) < 0) { 11400 return rv; 11401 } 11402 #endif 11403 } 11404 if (dest_type != -1) { 11405 BCM_IF_ERROR_RETURN 11406 (_bcm_esw_gport_construct(unit, &dest, &failover_ring->port0)); 11407 } 11408 _bcm_gport_dest_t_init(&dest); 11409 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_MATCH_PORT_Br(unit, &rval)); 11410 if (rval) { 11411 dest_type = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 11412 DEST_TYPEf); 11413 } else { 11414 dest_type = -1; 11415 } 11416 if (dest_type == 0) { 11417 dest.port = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 11418 PORT_NUMf); 11419 dest.modid = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 11420 MODULE_IDf); 11421 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 11422 } else if (dest_type == 1) { 11423 dest.tgid = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 11424 DESTINATIONf); 11425 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 11426 } else if (dest_type == 2) { 11427 vp = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 11428 DESTINATIONf); 11429 #if defined(INCLUDE_L3) 11430 if ((rv = _bcm_vp_gport_dest_fill(unit, vp, &dest)) < 0) { 11431 return rv; 11432 } 11433 #endif 11434 } 11435 if (dest_type != -1) { 11436 BCM_IF_ERROR_RETURN 11437 (_bcm_esw_gport_construct(unit, &dest, &failover_ring->port1)); 11438 } 11439 return BCM_E_NONE; 11440 } 11441 11442 int 11443 _bcm_tr3_l2_ring_replace(int unit, bcm_l2_ring_t *l2_ring) 11444 { 11445 int match_type = -1, rv = BCM_E_NONE, gport_id, vp_type = 0; 11446 uint32 map_size, i, rval; 11447 SHR_BITDCL *vlan_map = NULL, *vpn_map = NULL; 11448 bcm_module_t mod_out; 11449 bcm_port_t port_out; 11450 bcm_trunk_t trunk_id; 11451 uint32 r_flags = 0; 11452 11453 /* 11454 * match_type = -1 means flushing based on physical port or VP 11455 * match_type = 0 means flushing based on VLAN or port + VLAN 11456 * match_type = 1 means flushing based on VPN or VP + VPN 11457 */ 11458 if (!l2_ring) { 11459 return BCM_E_PARAM; 11460 } 11461 11462 /* Flag Validation Check */ 11463 if (((l2_ring->flags & BCM_L2_REPLACE_DYNAMIC) && 11464 (l2_ring->flags & BCM_L2_REPLACE_MATCH_STATIC)) || 11465 ((l2_ring->flags & BCM_L2_REPLACE_MATCH_UC) && 11466 (l2_ring->flags & BCM_L2_REPLACE_MATCH_MC))) { 11467 return BCM_E_PARAM; 11468 } 11469 11470 /* 11471 * If only one of the ports(port0 or port1) are valid, then we have to write 11472 * that port value into both L2_BULK_MATCH_PORT_Ar and 11473 * L2_BULK_MATCH_PORT_Br due to hardware behavior. 11474 */ 11475 if ((l2_ring->port0 != BCM_GPORT_INVALID) && 11476 (l2_ring->port1 == BCM_GPORT_INVALID)) { 11477 l2_ring->port1 = l2_ring->port0; 11478 } 11479 if ((l2_ring->port1 != BCM_GPORT_INVALID) && 11480 (l2_ring->port0 == BCM_GPORT_INVALID)) { 11481 l2_ring->port0 = l2_ring->port1; 11482 } 11483 11484 /* Get replace flags */ 11485 r_flags = l2_ring->flags; 11486 11487 /* Configure h/w tables and memory */ 11488 if (l2_ring->flags & BCM_L2_REPLACE_PROTECTION_RING) { 11489 if (l2_ring->port0 != BCM_GPORT_INVALID) { 11490 BCM_IF_ERROR_RETURN 11491 (_bcm_esw_gport_resolve(unit, l2_ring->port0, &mod_out, 11492 &port_out, &trunk_id, &gport_id)); 11493 SOC_IF_ERROR_RETURN(READ_L2_BULK_MATCH_PORT_Ar(unit, &rval)); 11494 if (-1 != gport_id) { 11495 vp_type = 1; 11496 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 11497 DESTINATIONf, gport_id); 11498 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 11499 DEST_TYPEf, 2); 11500 } else if (BCM_TRUNK_INVALID != trunk_id) { 11501 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 11502 DESTINATIONf, trunk_id); 11503 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 11504 DEST_TYPEf, 1); 11505 } else if (!(-1 == port_out || -1 == mod_out)) { 11506 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 11507 PORT_NUMf, port_out); 11508 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 11509 MODULE_IDf, mod_out); 11510 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 11511 DEST_TYPEf, 0); 11512 } 11513 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_MATCH_PORT_Ar(unit, rval)); 11514 } 11515 if (l2_ring->port1 != BCM_GPORT_INVALID) { 11516 BCM_IF_ERROR_RETURN 11517 (_bcm_esw_gport_resolve(unit, l2_ring->port1, &mod_out, 11518 &port_out, &trunk_id, &gport_id)); 11519 SOC_IF_ERROR_RETURN(READ_L2_BULK_MATCH_PORT_Br(unit, &rval)); 11520 if (-1 != gport_id) { 11521 vp_type = 1; 11522 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 11523 DESTINATIONf, gport_id); 11524 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 11525 DEST_TYPEf, 2); 11526 } else if (BCM_TRUNK_INVALID != trunk_id) { 11527 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 11528 DESTINATIONf, trunk_id); 11529 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 11530 DEST_TYPEf, 1); 11531 } else if (!(-1 == port_out || -1 == mod_out)) { 11532 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 11533 PORT_NUMf, port_out); 11534 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 11535 MODULE_IDf, mod_out); 11536 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 11537 DEST_TYPEf, 0); 11538 } 11539 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_MATCH_PORT_Br(unit, rval)); 11540 } 11541 if (l2_ring->flags & BCM_L2_REPLACE_VPN_TYPE) { 11542 map_size = SHR_BITALLOCSIZE(BCM_VPN_MAX+1); 11543 vpn_map = soc_cm_salloc(unit, map_size, "Failover ring vpn map"); 11544 if (NULL == vpn_map) { 11545 return (SOC_E_MEMORY); 11546 } 11547 sal_memset(vpn_map, 0, map_size); 11548 for (i = BCM_VPN_MIN; i < BCM_VPN_MAX; i++) { 11549 if (BCM_VPN_VEC_GET(l2_ring->vpn_vector, i)) { 11550 SHR_BITSET(vpn_map, i); 11551 match_type = 1; 11552 } 11553 } 11554 if (match_type == 1) { 11555 if ((rv = soc_mem_write_range(unit, L2_BULK_MATCH_VLANS_PORT_Am, 11556 MEM_BLOCK_ALL, 0, soc_mem_index_max( 11557 unit, L2_BULK_MATCH_VLANS_PORT_Am), 11558 vpn_map)) < 0) { 11559 soc_cm_sfree(unit, vpn_map); 11560 return rv; 11561 } 11562 if ((rv = soc_mem_write_range(unit, L2_BULK_MATCH_VLANS_PORT_Bm, 11563 MEM_BLOCK_ALL, 0, soc_mem_index_max( 11564 unit, L2_BULK_MATCH_VLANS_PORT_Bm), 11565 vpn_map)) < 0) { 11566 soc_cm_sfree(unit, vpn_map); 11567 return rv; 11568 } 11569 /* 11570 * As we are writing vlan_vector/vpn_vector into both 11571 * L2_BULK_MATCH_VLANS_PORT_Am and 11572 * L2_BULK_MATCH_VLANS_PORT_Bm, we have to set key_type into 11573 * both L2_BULK_KEY_TYPE_PORT_Ar and 11574 * L2_BULK_KEY_TYPE_PORT_Br. 11575 */ 11576 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval)); 11577 #ifdef BCM_KATANA2_SUPPORT 11578 if (SOC_IS_KATANA2(unit)) { 11579 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 11580 KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_VFI); 11581 } 11582 #endif 11583 if (SOC_IS_TRIUMPH3(unit)) { 11584 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 11585 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI); 11586 } 11587 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval)); 11588 11589 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval)); 11590 #ifdef BCM_KATANA2_SUPPORT 11591 if (SOC_IS_KATANA2(unit)) { 11592 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 11593 KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_VFI); 11594 } 11595 #endif 11596 if (SOC_IS_TRIUMPH3(unit)) { 11597 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 11598 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI); 11599 } 11600 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval)); 11601 } 11602 soc_cm_sfree(unit, vpn_map); 11603 } else { 11604 vp_type = 0; 11605 map_size = SHR_BITALLOCSIZE(BCM_VLAN_MAX+1); 11606 vlan_map = soc_cm_salloc(unit, map_size, "Failover ring vlan map"); 11607 if (NULL == vlan_map) { 11608 return (SOC_E_MEMORY); 11609 } 11610 sal_memset(vlan_map, 0, map_size); 11611 for (i = BCM_VLAN_MIN; i < BCM_VLAN_MAX; i++) { 11612 if (BCM_VLAN_VEC_GET(l2_ring->vlan_vector, i)) { 11613 SHR_BITSET(vlan_map, i); 11614 match_type = 0; 11615 } 11616 } 11617 if ((rv = soc_mem_write_range(unit, L2_BULK_MATCH_VLANS_PORT_Am, 11618 MEM_BLOCK_ALL, 0, soc_mem_index_max( 11619 unit, L2_BULK_MATCH_VLANS_PORT_Am), 11620 vlan_map)) < 0) { 11621 soc_cm_sfree(unit, vlan_map); 11622 return rv; 11623 } 11624 if ((rv = soc_mem_write_range(unit, L2_BULK_MATCH_VLANS_PORT_Bm, 11625 MEM_BLOCK_ALL, 0, soc_mem_index_max( 11626 unit, L2_BULK_MATCH_VLANS_PORT_Bm), 11627 vlan_map)) < 0) { 11628 soc_cm_sfree(unit, vlan_map); 11629 return rv; 11630 } 11631 11632 /* 11633 * As we are writing vlan_vector/vpn_vector into both 11634 * L2_BULK_MATCH_VLANS_PORT_Am and 11635 * L2_BULK_MATCH_VLANS_PORT_Bm, we have to set key_type into 11636 * both L2_BULK_KEY_TYPE_PORT_Ar and 11637 * L2_BULK_KEY_TYPE_PORT_Br. 11638 */ 11639 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval)); 11640 #ifdef BCM_KATANA2_SUPPORT 11641 if (SOC_IS_KATANA2(unit)) { 11642 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 11643 KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_BRIDGE); 11644 } 11645 #endif 11646 if (SOC_IS_TRIUMPH3(unit)) { 11647 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 11648 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE); 11649 } 11650 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval)); 11651 11652 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval)); 11653 #ifdef BCM_KATANA2_SUPPORT 11654 if (SOC_IS_KATANA2(unit)) { 11655 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 11656 KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_BRIDGE); 11657 } 11658 #endif 11659 if (SOC_IS_TRIUMPH3(unit)) { 11660 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval, 11661 KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE); 11662 } 11663 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval)); 11664 soc_cm_sfree(unit, vlan_map); 11665 } 11666 SOC_IF_ERROR_RETURN(READ_AUX_L2_BULK_CONTROLr(unit, &rval)); 11667 if ((l2_ring->port0 != BCM_GPORT_INVALID) || 11668 (l2_ring->port1 != BCM_GPORT_INVALID)) { 11669 soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 11670 MATCH_PORT_Af, 1); 11671 soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 11672 MATCH_PORT_Bf, 1); 11673 } 11674 if (match_type != -1) { 11675 soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 11676 MATCH_VLANS_PORT_Af, 1); 11677 soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 11678 MATCH_VLANS_PORT_Bf, 1); 11679 soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 11680 MATCH_KEY_TYPE_PORT_Af, 1); 11681 soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 11682 MATCH_KEY_TYPE_PORT_Bf, 1); 11683 } 11684 soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, BULK_OPS_ENABLEf, 11685 1); 11686 SOC_IF_ERROR_RETURN(WRITE_AUX_L2_BULK_CONTROLr(unit, rval)); 11687 /* 11688 * match_type is set to 1 in case of flushing based on VP 11689 */ 11690 if (vp_type) { 11691 match_type = 1; 11692 } 11693 #ifdef BCM_KATANA2_SUPPORT 11694 if (SOC_IS_KATANA2(unit)) { 11695 rv = _kt2_l2_delete_all_by_hw(unit, match_type, r_flags); 11696 } else 11697 #endif 11698 { 11699 rv = _tr3_l2_delete_all_by_hw(unit, match_type, r_flags); 11700 } 11701 if (rv < 0) { 11702 LOG_ERROR(BSL_LS_BCM_L2, 11703 (BSL_META_U(unit, 11704 "Error deleting entries: %d\n"), rv)); 11705 } 11706 11707 /* Trunk port delete */ 11708 if ((BCM_GPORT_IS_TRUNK(l2_ring->port0)) 11709 || (BCM_GPORT_IS_TRUNK(l2_ring->port1))) { 11710 SOC_IF_ERROR_RETURN(READ_L2_BULK_MATCH_PORT_Ar(unit, &rval)); 11711 if (soc_reg_field_get(unit, L2_BULK_MATCH_PORT_Ar, 11712 rval, DEST_TYPEf) == 1) { 11713 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, 11714 &rval, MODULE_IDf, 0x80); 11715 } 11716 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_MATCH_PORT_Ar(unit, rval)); 11717 11718 SOC_IF_ERROR_RETURN(READ_L2_BULK_MATCH_PORT_Br(unit, &rval)); 11719 if (soc_reg_field_get(unit, L2_BULK_MATCH_PORT_Br, 11720 rval, DEST_TYPEf) == 1) { 11721 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, 11722 &rval, MODULE_IDf, 0x80); 11723 } 11724 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_MATCH_PORT_Br(unit, rval)); 11725 #ifdef BCM_KATANA2_SUPPORT 11726 if (SOC_IS_KATANA2(unit)) { 11727 rv = _kt2_l2_delete_all_by_hw(unit, match_type, r_flags); 11728 } else 11729 #endif 11730 { 11731 rv = _tr3_l2_delete_all_by_hw(unit, match_type, r_flags); 11732 } 11733 if (rv < 0) { 11734 LOG_ERROR(BSL_LS_BCM_L2, 11735 (BSL_META_U(unit, 11736 "Error deleting entries: %d\n"), rv)); 11737 } 11738 } 11739 rval = 0; 11740 SOC_IF_ERROR_RETURN(WRITE_AUX_L2_BULK_CONTROLr(unit, rval)); 11741 } 11742 return rv; 11743 } 11744 11745 int 11746 bcm_tr3_l2_ring_replace(int unit, bcm_l2_ring_t *l2_ring) 11747 { 11748 int rv = BCM_E_NONE; 11749 _BCM_ALL_L2X_MEM_LOCK(unit); 11750 rv = _bcm_tr3_l2_ring_replace(unit, l2_ring); 11751 _BCM_ALL_L2X_MEM_UNLOCK(unit); 11752 return rv; 11753 } 11754 11755 /* 11756 * Function: 11757 * bcm_tr3_bfd_l2_hash_dynamic_replace 11758 * Purpose: 11759 * Replace dynamic L2 entries in a dual hash. 11760 * Parameters: 11761 * unit - Unit number 11762 * l2x_entry - Entry to insert instead of dynamic entry. 11763 * Returns: 11764 * BCM_E_NONE Success 11765 * BCM_E_XXX Error 11766 */ 11767 11768 int bcm_tr3_bfd_l2_hash_dynamic_replace(int unit, void *l2x_entry) 11769 { 11770 _bcm_tr3_l2_entries_t l2_entry; 11771 11772 sal_memset(&l2_entry, 0, sizeof(_bcm_tr3_l2_entries_t)); 11773 sal_memcpy(&l2_entry.l2_entry_1, l2x_entry, sizeof(l2_entry_1_entry_t)); 11774 l2_entry.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_1; 11775 11776 return _bcm_tr3_l2_hash_dynamic_replace(unit, &l2_entry); 11777 } 11778 11779 #endif /* BCM_TRIUMPH3_SUPPORT */