field_common.c (1769010B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * Module: Field Processor APIs 7 * 8 * Purpose: 9 * API for Field Processor (FP) for XGS3 family and later. 10 */ 11 /**/ 12 #include <shared/bsl.h> 13 14 #include <soc/drv.h> 15 #include <soc/scache.h> 16 #include <soc/cmic.h> 17 #include <soc/field.h> 18 #include <shared/pbmp.h> 19 #include <bcm/field.h> 20 #include <bcm/error.h> 21 #include <bcm/mirror.h> 22 #include <bcm/link.h> 23 #include <bcm_int/esw/link.h> 24 #include <bcm/l3.h> 25 #include <bcm_int/esw/l3.h> 26 #include <bcm_int/esw/tsn.h> 27 #ifdef BCM_TRIDENT2_SUPPORT 28 #include <bcm/nat.h> 29 #include <bcm_int/esw/nat.h> 30 #endif 31 32 #if defined(BCM_FIREBOLT_SUPPORT) 33 #include <bcm_int/esw/firebolt.h> 34 #endif 35 36 #if defined(BCM_RAPTOR_SUPPORT) 37 #include <bcm_int/esw/raptor.h> 38 #endif 39 40 #if defined(BCM_TRX_SUPPORT) 41 #include <bcm_int/esw/trx.h> 42 #endif 43 44 #if defined(BCM_TRIUMPH_SUPPORT) 45 #include <bcm_int/esw/triumph.h> 46 #endif 47 48 #if defined(BCM_HGPROXY_COE_SUPPORT) 49 #include <bcm_int/esw/xgs5.h> 50 #endif /* BCM_HGPROXY_COE_SUPPORT */ 51 52 #include <bcm_int/esw/field.h> 53 #include <bcm_int/esw/range.h> 54 #include <bcm_int/esw/triumph2.h> 55 #include <bcm_int/esw/triumph3.h> 56 #include <bcm_int/esw/trident.h> 57 #include <bcm_int/esw/katana.h> 58 #include <bcm_int/esw/trident2.h> 59 #include <bcm_int/esw/tomahawk.h> 60 #include <bcm_int/common/multicast.h> 61 62 #if defined(BCM_ENDURO_SUPPORT) 63 #include <bcm_int/esw/enduro.h> 64 #endif 65 66 #if defined(BCM_HURRICANE_SUPPORT) 67 #include <bcm_int/esw/hurricane.h> 68 #endif 69 70 #if defined(BCM_HURRICANE2_SUPPORT) 71 #include <bcm_int/esw/hurricane2.h> 72 #endif 73 74 #if defined(BCM_KATANA2_SUPPORT) 75 #include <bcm_int/esw/katana2.h> 76 #endif /* BCM_KATANA2_SUPPORT */ 77 78 #if defined(BCM_SABER2_SUPPORT) 79 #include <bcm_int/esw/saber2.h> 80 #endif /* BCM_SABER2_SUPPORT */ 81 82 #include <bcm_int/esw/scorpion.h> 83 #include <bcm_int/esw/trunk.h> 84 #include <bcm_int/esw/mirror.h> 85 #include <bcm_int/esw/stack.h> 86 #include <bcm_int/esw/port.h> 87 #include <bcm_int/control.h> 88 #include <bcm_int/esw/virtual.h> 89 #include <bcm_int/esw_dispatch.h> 90 #include <bcm_int/esw/ecn.h> 91 #include <bcm_int/esw/keygen_api.h> 92 93 94 #if defined(BCM_ESW_SUPPORT) 95 #include <bcm_int/esw/flex_ctr.h> 96 #include <bcm_int/esw/xgs4.h> 97 #endif 98 99 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 100 #include <bcm_int/esw/policer.h> 101 #endif 102 #ifdef BCM_GREYHOUND_SUPPORT 103 #include <bcm_int/esw/greyhound.h> 104 #endif /* BCM_GREYHOUND_SUPPORT */ 105 #ifdef BCM_HURRICANE3_SUPPORT 106 #include <bcm_int/esw/hurricane3.h> 107 #include <bcm_int/esw/flowcnt.h> 108 #endif /* BCM_HURRICANE3_SUPPORT */ 109 #ifdef BCM_GREYHOUND2_SUPPORT 110 #include <bcm_int/esw/greyhound2.h> 111 #endif /* BCM_GREYHOUND2_SUPPORT */ 112 #if defined(INCLUDE_REGEX) 113 #include <bcm_int/esw/bregex.h> 114 #endif 115 #ifdef BCM_TOMAHAWK3_SUPPORT 116 #include <bcm_int/esw/tomahawk3.h> 117 #endif /* BCM_TOMAHAWK3_SUPPORT */ 118 #if defined(BCM_HELIX5_SUPPORT) 119 #include <bcm_int/esw/helix5.h> 120 #endif /* BCM_HELIX5_SUPPORT */ 121 122 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC) 123 #include <bcm_int/common/xflow_macsec_cmn.h> 124 #endif 125 126 #if defined(BCM_ESW_SUPPORT) 127 #ifdef BCM_FIELD_SUPPORT 128 129 #define SAL_ALLOC_T(t, n) ((t *) sal_alloc((n) * sizeof(t), " ")) /* <HP/> */ 130 131 #define BCM_POLICER_XGS_NOSUPPORT_FLAGS (BCM_POLICER_DROP_RED | \ 132 BCM_POLICER_MACRO | \ 133 BCM_POLICER_EGRESS | \ 134 BCM_POLICER_REPLACE_SHARED) 135 136 #define _FIELD_IS_CLASS_ID_B_SEL(_sec_sel_) ((_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF1) \ 137 || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF2) \ 138 || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF3) \ 139 || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF4) \ 140 || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF5) \ 141 || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF6) \ 142 || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF7) \ 143 || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF8)) 144 145 #define _FP_ENTRY_MOVE_DOWN 0x01 146 #define _FP_ENTRY_MOVE_UP 0x02 147 148 int _field_fill_slice_array (int unit, _field_group_t *fg, uint8 *slice_array); 149 /* Static variables */ 150 int prio_set_with_no_free_entries[BCM_MAX_NUM_UNITS] = {FALSE}; 151 152 int 153 _bcm_field_entry_copy_id(int unit, 154 bcm_field_entry_t src_entry, 155 bcm_field_entry_t dst_entry, 156 uint32 flags); 157 158 int 159 _field_tcam_policy_install(int unit, bcm_field_entry_t entry); 160 161 int 162 _field_entry_prio_set(int unit, bcm_field_entry_t entry, int prio); 163 164 int 165 _field_entry_create_id(int unit, bcm_field_group_t group, 166 bcm_field_entry_t entry); 167 168 STATIC int 169 _field_internal_backup_entry_delete(int unit, bcm_field_entry_t temp_entry); 170 171 #if defined(BCM_TRX_SUPPORT) 172 STATIC 173 int _bcm_field_group_entry_port_update(int unit, 174 _field_group_t *fg, 175 bcm_pbmp_t detached_pbmp, 176 bcm_pbmp_t attached_pbmp); 177 #endif 178 179 #if defined(BCM_TOMAHAWK_SUPPORT) 180 STATIC 181 int _bcm_field_group_entry_pipe_port_update(int unit, 182 _field_group_t *fg, 183 bcm_pbmp_t detached_pbmp, 184 bcm_pbmp_t attached_pbmp); 185 #endif 186 STATIC 187 int _bcm_field_slice_idx_allocate(int unit, 188 _field_stage_t *stage_fc, 189 _field_group_t *fg, 190 _field_slice_t *fs, 191 uint32 *slice_idx); 192 193 STATIC 194 int _field_slice_index_type_get(int unit, 195 _field_group_t *fg, 196 _field_slice_t *fs, 197 int slice_idx, 198 int *slice_idx_type); 199 STATIC 200 int _field_slice_next_match_index_get(int unit, _field_group_t *fg, 201 _field_slice_t *fs, int start_idx, 202 int end_idx, int dir, int *next_index); 203 204 STATIC int 205 _field_entry_shift_params_get(int unit, _field_group_t *fg, 206 _field_entry_t *f_ent, int prio, 207 _bcm_field_entry_shift_params_t *sp); 208 209 STATIC int 210 _field_multimode_slice_idx_alloc(int unit, 211 _field_stage_t *stage_fc, _field_group_t *fg, 212 _field_slice_t *fs, uint32 *slice_idx); 213 214 STATIC int 215 _field_multimode_slice_entry_move(int unit, _field_slice_t *fs, 216 _field_entry_t *f_ent, int amount); 217 218 STATIC int 219 _field_multimode_slice_entry_shift_down(int unit, _field_group_t *fg, 220 _field_slice_t *target_fs, uint16 target_idx, 221 _field_slice_t *next_null_fs, uint16 next_null_idx); 222 223 STATIC int 224 _field_multimode_slice_entry_shift_up(int unit, _field_group_t *fg, 225 _field_slice_t *target_fs, uint16 target_idx, 226 _field_slice_t *prev_null_fs, uint16 prev_null_idx); 227 228 STATIC int 229 _field_multimode_slice_entry_compress(int unit, _field_slice_t *fs); 230 231 STATIC int 232 _field_meter_hw_clear(int unit, _field_entry_t *f_ent, 233 int old_hw_index, bcm_policer_mode_t old_mode, 234 int old_pool_index, uint32 old_hw_flags); 235 236 237 extern soc_field_t udf_fields_f[][4]; 238 uint8 wb_write_disable = 0; 239 240 #ifdef BCM_WARM_BOOT_SUPPORT 241 static const uint32 _field_sdk_warmboot_version[][2] = { 242 {((6 << 16) | (4 << 8) | 7 ), BCM_FIELD_WB_VERSION_1_11}, 243 {((6 << 16) | (4 << 8) | 8 ), BCM_FIELD_WB_VERSION_1_14}, 244 {((6 << 16) | (4 << 8) | 9 ), BCM_FIELD_WB_VERSION_1_15}, 245 {((6 << 16) | (4 << 8) | 10 ), BCM_FIELD_WB_VERSION_1_16}, 246 {((6 << 16) | (4 << 8) | 11 ), BCM_FIELD_WB_VERSION_1_18}, 247 {((6 << 16) | (5 << 8) | 0 ), BCM_FIELD_WB_VERSION_1_11}, 248 {((6 << 16) | (5 << 8) | 1 ), BCM_FIELD_WB_VERSION_1_12}, 249 {((6 << 16) | (5 << 8) | 2 ), BCM_FIELD_WB_VERSION_1_15}, 250 {((6 << 16) | (5 << 8) | 3 ), BCM_FIELD_WB_VERSION_1_18}, 251 {((6 << 16) | (5 << 8) | 4 ), BCM_FIELD_WB_VERSION_1_19}, 252 {((6 << 16) | (5 << 8) | 5 ), BCM_FIELD_WB_VERSION_1_20}, 253 {((6 << 16) | (5 << 8) | 6 ), BCM_FIELD_WB_VERSION_1_21}, 254 {((6 << 16) | (5 << 8) | 7 ), BCM_FIELD_WB_VERSION_1_22}, 255 {((6 << 16) | (5 << 8) | 10 ), BCM_FIELD_WB_VERSION_1_23}, 256 {((6 << 16) | (5 << 8) | 11 ), BCM_FIELD_WB_VERSION_1_24}, 257 {((6 << 16) | (5 << 8) | 12 ), BCM_FIELD_WB_VERSION_1_24}, 258 {((6 << 16) | (5 << 8) | 13 ), BCM_FIELD_WB_VERSION_1_25}, 259 {((6 << 16) | (5 << 8) | 14 ), BCM_FIELD_WB_VERSION_1_27}, 260 {((6 << 16) | (5 << 8) | 15 ), BCM_FIELD_WB_VERSION_1_28}, 261 }; 262 #endif /* WARM_BOOT_SUPPORT*/ 263 264 /* 265 * Macro: 266 * FIELD_IS_INIT (internal) 267 * Purpose: 268 * Check that the unit is valid and confirm that the field functions 269 * are initialized. 270 * Parameters: 271 * unit - BCM device number 272 * Notes: 273 * Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or 274 * return(BCM_E_INIT) if fails. 275 */ 276 #define FIELD_IS_INIT(unit) \ 277 if (!soc_feature(unit, soc_feature_field)) { \ 278 return (BCM_E_UNAVAIL); \ 279 } \ 280 if (_field_control[unit] == NULL) { \ 281 LOG_DEBUG(BSL_LS_BCM_FP, \ 282 (BSL_META("FP(unit %d) Error: not initialized\n"), \ 283 unit)); \ 284 return (BCM_E_INIT); \ 285 } 286 287 288 /* 289 * Function: 290 * _bcm_field_is_entry_stage_valid(unit, entry, stage) (internal) 291 * Purpose: 292 * Checks whether the entry is in the stage provided 293 * Parameters: 294 * unit - (IN) BCM device number 295 * entry - (IN) Entry identifier 296 * stage - (IN) Pipeline stage id number 297 * Return values: 298 * Returns BCM_E_XXX 299 * BCM_E_NONE - implies for the particular Entry, Stage is Valid 300 */ 301 int _bcm_field_is_entry_stage_valid(int unit, bcm_field_entry_t entry, 302 _field_stage_id_t stage) 303 { 304 _field_entry_t *f_ent = NULL; 305 306 #if defined(BCM_TOMAHAWK_SUPPORT) 307 if (soc_feature(unit, soc_feature_field_preselector_support) && 308 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 309 return ((_BCM_FIELD_STAGE_INGRESS == stage) ? BCM_E_NONE : BCM_E_PARAM); 310 } 311 #endif /* BCM_TOMAHAWK_SUPPORT */ 312 BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, 313 _FP_ENTRY_PRIMARY, &f_ent)); 314 315 /* All qualifiers applicable for ingress are applicable 316 * for exact match stage also. Hence allow it for exact match 317 * entries when stage is Ingress. */ 318 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 319 stage = (stage == _BCM_FIELD_STAGE_INGRESS) ? \ 320 _BCM_FIELD_STAGE_EXACTMATCH : stage; 321 } 322 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 323 stage = (stage == _BCM_FIELD_STAGE_INGRESS) ? \ 324 _BCM_FIELD_STAGE_FLOWTRACKER : stage; 325 } 326 327 return ((f_ent->group->stage_id == stage) ? BCM_E_NONE : BCM_E_CONFIG); 328 } 329 330 /* 331 * Local function prototypes 332 */ 333 char *_field_qual_name(bcm_field_qualify_t qid); 334 char *_field_group_mode_name(int unit, uint32 group_flags, _field_stage_t *stage_fc); 335 char* _field_stage_name(_field_stage_t *stage_fc); 336 337 STATIC int _field_entry_move(int unit, _field_entry_t *f_ent, int tcam_idx_new); 338 339 /* 340 * Field control data, one per device. 341 */ 342 _field_control_t *_field_control[BCM_MAX_NUM_UNITS]; 343 344 /* Sw WorkAround for EgressPortsAdd Action */ 345 uint8 _field_egr_ports_recovery_lock[BCM_MAX_NUM_UNITS]; 346 _field_egr_ports_recovery_t *_field_egr_ports_recovery[BCM_MAX_NUM_UNITS]; 347 348 #ifdef BCM_WARM_BOOT_SUPPORT 349 350 /* Warmboot recovery for bcmFieldActionDscpMapNew*/ 351 _field_dscp_map_new_eid_list_t *dscp_map_new_eid_list[BCM_MAX_NUM_UNITS]; 352 353 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 354 355 /* Extract a field from a raw HW entry */ 356 357 void 358 _field_extract(uint32 *buf, int offset, int width, uint32 *value) 359 { 360 int idx, wp, bp, len; 361 wp = offset / 32; 362 bp = offset & (32 - 1); 363 idx = 0; 364 365 for (len = width; len > 0; len -= 32) { 366 if (bp) { 367 value[idx] = (buf[wp++] >> bp) & ((1 << (32 - bp)) - 1); 368 value[idx] |= buf[wp] << (32 - bp); 369 } else { 370 value[idx] = buf[wp]; 371 } 372 373 if (len < 32) { 374 value[idx] &= ((1 << len) - 1); 375 } 376 377 idx++; 378 } 379 380 return; 381 } 382 383 #endif 384 385 int 386 _field_state_cleanup(int unit, _field_control_t *fc) 387 { 388 int rv; 389 _field_group_t *fg; 390 391 /* Destroy all entries in unit. */ 392 rv = bcm_esw_field_entry_destroy_all(unit); 393 if (BCM_FAILURE(rv)) { 394 return (rv); 395 } 396 397 FP_LOCK(unit); 398 399 /* Destroy all statistics entities. */ 400 rv = _field_stat_destroy_all(unit); 401 if (BCM_FAILURE(rv)) { 402 FP_UNLOCK(unit); 403 return (rv); 404 } 405 FP_UNLOCK(unit); 406 407 /* Destroy all policers. */ 408 rv = bcm_esw_policer_destroy_all(unit); 409 if (BCM_FAILURE(rv)) { 410 return (rv); 411 } 412 413 /* Destroy all groups in unit. */ 414 fg = fc->groups; 415 while (fg != NULL) { 416 417 rv = bcm_esw_field_group_destroy(unit, fg->gid); 418 if (BCM_FAILURE(rv)) { 419 return (rv); 420 } 421 fg = fc->groups; 422 } 423 return rv; 424 } 425 426 void 427 _bcm_field_last_alloc_eid_incr(int unit) 428 { 429 _field_control_t *fc; 430 int rv = 0; 431 432 /* Get unit FP control structure. */ 433 434 FP_LOCK(unit); 435 rv = (_field_control_get(unit, &fc)); 436 if (BCM_FAILURE(rv)) { 437 FP_UNLOCK(unit); 438 return; 439 } 440 fc->last_allocated_eid++; 441 FP_UNLOCK(unit); 442 443 } 444 int 445 _bcm_field_last_alloc_eid_get(int unit) 446 { 447 _field_control_t *fc; 448 uint32 last_alloc_eid = -1; 449 int rv = 0; 450 451 /* Get unit FP control structure. */ 452 453 FP_LOCK(unit); 454 rv = _field_control_get(unit, &fc); 455 if (BCM_FAILURE(rv)) { 456 FP_UNLOCK(unit); 457 return rv; 458 } 459 last_alloc_eid = fc->last_allocated_eid; 460 FP_UNLOCK(unit); 461 462 return last_alloc_eid; 463 } 464 465 /* 466 * Function: 467 * _field_scache_pointer_init_wb 468 * Purpose: 469 * Initialize field component scache pointers for required partitions 470 * during warm boot 471 * Parameters: 472 * unit - (IN) Unit number. 473 * fc - (IN) Pointer to field control 474 * Returns: 475 * BCM_E_xxx 476 * Notes: 477 */ 478 479 int 480 _field_scache_pointer_init_wb(int unit, _field_control_t *fc) 481 { 482 int rv; 483 uint32 alloc_get; 484 soc_scache_handle_t handle; 485 int incr_size = 0; 486 487 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 1); 488 SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_FIELD, 1); 489 490 /* Get the pointer for the Level 2 cache for partition 1*/ 491 rv = soc_scache_ptr_get(unit, handle, 492 &(fc->scache_ptr[_FIELD_SCACHE_PART_1]), 493 &alloc_get); 494 if (SOC_WARM_BOOT(unit) && (SOC_E_NOT_FOUND == rv)) { 495 SOC_IF_ERROR_RETURN 496 (soc_scache_alloc(unit, handle, 497 fc->scache_size[_FIELD_SCACHE_PART_1] + 498 SOC_WB_SCACHE_CONTROL_SIZE)); 499 rv = soc_scache_ptr_get(unit, handle, 500 &(fc->scache_ptr[_FIELD_SCACHE_PART_1]), 501 &alloc_get); 502 } 503 504 if (BCM_FAILURE(rv)) { 505 return rv; 506 } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_1] + 507 SOC_WB_SCACHE_CONTROL_SIZE) { 508 /* Expected size doesn't match retrieved size */ 509 return BCM_E_INTERNAL; 510 } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_1]) { 511 return BCM_E_MEMORY; 512 } 513 514 /* scache size - partition 1 is increased for TRX devices only 515 * from warmboot version 1_6 and devices like Raven 516 * still follows globalscache allocation method 517 */ 518 if (SOC_IS_TRX(unit)) { 519 /* Get the pointer for the Level 2 cache for partition 0 */ 520 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 0); 521 522 523 if (SOC_WARM_BOOT(unit)) { 524 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_6) { 525 /* Scache size is increased by 16*1024 bytes 526 * from version BCM_FIELD_WB_VERSION_1_6 for partition 0. 527 */ 528 incr_size += (16 * 1024); 529 } 530 531 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_8) { 532 /* Scache size is increased by 128*1024 bytes 533 * from version BCM_FIELD_WB_VERSION_1_8 for partition 0. 534 * with respect to version BCM_FIELD_WB_VERSION_1_6. 535 */ 536 incr_size += (128 * 1024); 537 } 538 539 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_15) { 540 /* 541 * Scache size is increased by 135 * 1024 bytes 542 * from version BCM_FIELD_WB_VERSION_1_15 for partition 0. 543 * with respect to version BCM_FIELD_WB_VERSION_1_8. 544 */ 545 incr_size += (135 * 1024); 546 } 547 548 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_17) { 549 /* 550 * Scache size is increased by 144 * 1024 bytes 551 * from version BCM_FIELD_WB_VERSION_1_17 for sync and recovery of 552 * policer configured rates and bursts 553 * with respect to version BCM_FIELD_WB_VERSION_1_15. 554 */ 555 incr_size += (144 * 1024); 556 } 557 558 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_18) { 559 /* 560 * Scache size is increased by (18 + 3) * 1024 bytes 561 * from version BCM_FIELD_WB_VERSION_1_18 for partition 0. 562 * To add sync for SVP DVP type per entry part and 563 * ingress, src entity selcode per group part 564 * with respect to version BCM_FIELD_WB_VERSION_1_17. 565 */ 566 incr_size += (21 * 1024); 567 } 568 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_19) { 569 /* 570 * Scache size is increased by 571 * ((16 + 1 + 1) * 4) + (16) * 12 bytes 572 * from version BCM_FIELD_WB_VERSION_1_19 for partition 0. 573 * To add sync no parm actions sync enum 4 bytes for each entry 574 * And to add PortPrioIntCosQNew Actions(Rp/Yp/Gp) CosQ Gport values 575 * 12 bytes for each entry in IFP 576 * with respect to version BCM_FIELD_WB_VERSION_1_18. 577 */ 578 incr_size += (264 * 1024); 579 } 580 581 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_20) { 582 /* Allocate additional scache to sync IFP action ingress 583 * and egress mirror gport value in no parm actions sync 584 * enums per entry. IngressMirror and EgressMirror GPORT 585 * can be assigned to single entry. Have to allocate (4+4) 586 * bytes per entry. 587 * IFP = (8 bytes * 512 entries * 12 slices). 588 */ 589 incr_size += (48 * 1024); 590 /* 591 * Scache size is increased by (16 * 1024) * 4 bytes 592 * (16K entries * 4 bytes) for all devices and 593 * (8 * 1024) * 4 * 2 (8K entries * 4 bytes * 2 params 594 * for KT2 devices to sync and recover the params of 595 * fabricQueue action for all entries of Ingress. 596 */ 597 incr_size += (16 * 1024 * 4); 598 } 599 600 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_21) { 601 /* 602 * Group PBMP is synced with max_groups * size of the pbmp array 603 * Sync MirrorIngress and MirrorEgress action parameters per entry 604 * Worst case 16K * 12 bytes 605 */ 606 incr_size += ((512 * _SHR_PBMP_WORD_MAX * 4) + (16 * 1024 * 12)); 607 } 608 609 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_23) { 610 /* 611 * Scache size is increased by 128 * 4 bytes 612 * to syncloopbacktype selcode per group part. 613 * Worst case assuming 128 IFP groups in quad mode 614 * (128 * 4) bytes. 615 */ 616 incr_size += (128 * 4); 617 } 618 619 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_27) { 620 /* 621 * Scache size is increased by FP_MAX_NUM_PIPES * 1 byte 622 * to sync instance for all pipes in EFP/VFP. 623 * _FP_MAX_NUM_PIPES * 1 bytes * 8 groups to sync group 624 * instance for all groups in EFP/VFP. 625 */ 626 incr_size += ((_FP_MAX_NUM_PIPES)+ (_FP_MAX_NUM_PIPES * 8)); 627 } 628 629 } 630 631 if (incr_size > 0) { 632 SOC_IF_ERROR_RETURN 633 (soc_scache_realloc(unit, handle, 634 (incr_size))); 635 rv = soc_scache_ptr_get(unit, handle, 636 &(fc->scache_ptr[_FIELD_SCACHE_PART_0]), 637 &alloc_get); 638 639 if (BCM_FAILURE(rv)) { 640 return rv; 641 } else if (alloc_get != (fc->scache_size[_FIELD_SCACHE_PART_0] + 642 SOC_WB_SCACHE_CONTROL_SIZE)) { 643 /* Expected size doesn't match retrieved size */ 644 return BCM_E_INTERNAL; 645 } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_0]) { 646 return BCM_E_MEMORY; 647 } 648 } 649 } 650 return BCM_E_NONE; 651 } 652 /* Update the scache based on the latest field state */ 653 int 654 _bcm_esw_field_scache_sync(int unit) 655 { 656 int rv = BCM_E_NONE; 657 _field_control_t *fc; 658 _field_stage_t *stage_fc; 659 int (* f)(int, _field_control_t *, _field_stage_t *); 660 uint16 version; 661 #if defined(BCM_TOMAHAWK_SUPPORT) 662 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 663 f = _bcm_field_th_scache_sync; 664 } else 665 #endif /* BCM_TRIDENT2_SUPPORT */ 666 #ifdef BCM_TRIDENT2_SUPPORT 667 if (SOC_IS_TD2_TT2(unit)) { 668 f = _bcm_field_td2_scache_sync; 669 } else 670 #endif /* BCM_TRIDENT2_SUPPORT */ 671 #ifdef BCM_TRX_SUPPORT 672 if (SOC_IS_TRIUMPH(unit) 673 || SOC_IS_VALKYRIE(unit) 674 || SOC_IS_TRIUMPH2(unit) 675 || SOC_IS_APOLLO(unit) 676 || SOC_IS_VALKYRIE2(unit) 677 || SOC_IS_SC_CQ(unit) 678 || SOC_IS_TD_TT(unit) 679 || SOC_IS_KATANAX(unit) 680 || SOC_IS_HURRICANE3(unit) 681 || SOC_IS_GREYHOUND2(unit) 682 ) { 683 f = _field_tr2_scache_sync; 684 } else 685 #endif /* BCM_TRX_SUPPORT */ 686 #ifdef BCM_TRIUMPH3_SUPPORT 687 if (SOC_IS_TRIUMPH3(unit)) { 688 f = _bcm_field_tr3_scache_sync; 689 } else 690 #endif 691 { 692 f = _field_scache_sync; 693 } 694 695 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 696 return BCM_E_NONE; 697 } 698 699 /* Get unit FP control structure. */ 700 701 702 FP_LOCK(unit); 703 rv = _field_control_get(unit, &fc); 704 if (BCM_FAILURE(rv)) { 705 FP_UNLOCK(unit); 706 return rv; 707 } 708 709 /* Initialize scache_pos */ 710 fc->scache_pos = 0; 711 fc->scache_pos1 = 0; 712 713 /* Write the version number */ 714 version = (fc->wb_current_version); 715 sal_memcpy(fc->scache_ptr[_FIELD_SCACHE_PART_0], &version, sizeof(uint16)); 716 fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE; 717 718 /* Write the version number */ 719 if(NULL != fc->scache_ptr[_FIELD_SCACHE_PART_1]) { 720 version = (fc->wb_current_version); 721 sal_memcpy(fc->scache_ptr[_FIELD_SCACHE_PART_1], &version, sizeof(uint16)); 722 fc->scache_pos1 += SOC_WB_SCACHE_CONTROL_SIZE; 723 } 724 725 726 if (SOC_IS_FIREBOLT(unit) || SOC_IS_FIREBOLT2(unit) || 727 SOC_IS_BRADLEY(unit) || SOC_IS_HUMV(unit) || 728 SOC_IS_RAVEN(unit) || SOC_IS_ENDURO(unit) || 729 SOC_IS_HAWKEYE(unit) || SOC_IS_APOLLO(unit) || 730 SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) || 731 SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit) || 732 SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit) || 733 SOC_IS_KATANAX(unit) || SOC_IS_HURRICANEX(unit) || 734 SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND(unit) || 735 SOC_IS_GREYHOUND2(unit)) { 736 737 rv = _field_stage_control_get 738 (unit, 739 _BCM_FIELD_STAGE_INGRESS, 740 &stage_fc 741 ); 742 743 if (BCM_SUCCESS(rv)) 744 { 745 rv = (*f)(unit, fc, stage_fc); 746 } 747 } 748 749 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 750 if (BCM_SUCCESS(rv) && 751 (SOC_IS_FIREBOLT2(unit) || SOC_IS_ENDURO(unit) || 752 SOC_IS_APOLLO(unit) || 753 SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) || 754 SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit) || 755 SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) 756 || SOC_IS_TRIUMPH3(unit) 757 || SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) 758 || SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 759 (soc_feature(unit, soc_feature_field_multi_stage))) { 760 rv = _field_stage_control_get 761 (unit, 762 _BCM_FIELD_STAGE_EGRESS, 763 &stage_fc 764 ); 765 766 if (BCM_SUCCESS(rv)) { 767 rv = (*f)(unit, fc, stage_fc); 768 769 if (BCM_SUCCESS(rv)) { 770 rv = _field_stage_control_get 771 (unit, 772 _BCM_FIELD_STAGE_LOOKUP, 773 &stage_fc 774 ); 775 776 if (BCM_SUCCESS(rv)) { 777 rv = (*f)(unit, fc, stage_fc); 778 779 if (BCM_SUCCESS(rv) && 780 soc_feature(unit, soc_feature_esm_support)) { 781 rv = _field_stage_control_get 782 (unit, 783 _BCM_FIELD_STAGE_EXTERNAL, 784 &stage_fc 785 ); 786 787 if (BCM_SUCCESS(rv)) { 788 rv = (*f)(unit, fc, stage_fc); 789 } 790 } 791 } 792 } 793 } 794 } 795 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRIUMPH_SUPPORT */ 796 #if defined(BCM_TOMAHAWK_SUPPORT) 797 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 798 if (soc_feature(unit, soc_feature_field_compression)) { 799 rv = _field_stage_control_get(unit, 800 _BCM_FIELD_STAGE_CLASS, 801 &stage_fc); 802 if (BCM_SUCCESS(rv)) { 803 rv = (*f)(unit, fc, stage_fc); 804 } 805 BCM_IF_ERROR_RETURN(rv); 806 } 807 808 if (soc_feature(unit, soc_feature_field_exact_match_support)) { 809 810 rv = _field_stage_control_get(unit, 811 _BCM_FIELD_STAGE_EXACTMATCH, 812 &stage_fc); 813 if (BCM_SUCCESS(rv)) { 814 rv = (*f)(unit, fc, stage_fc); 815 } 816 } 817 } 818 #endif /* BCM_TOMAHAWK_SUPPORT */ 819 820 #if defined(BCM_HELIX5_SUPPORT) 821 if (soc_feature(unit, soc_feature_field_flowtracker_support)) { 822 rv = _field_stage_control_get(unit, 823 _BCM_FIELD_STAGE_FLOWTRACKER, 824 &stage_fc); 825 if (BCM_SUCCESS(rv)) { 826 rv = (*f)(unit, fc, stage_fc); 827 } 828 BCM_IF_ERROR_RETURN(rv); 829 } 830 #endif 831 832 FP_UNLOCK(unit); 833 return rv; 834 } 835 836 STATIC int 837 _field_group_entry_write(int unit, int slice_idx, _field_slice_t *fs, 838 _field_control_t *fc, _field_stage_t *stage_fc) 839 { 840 int qset_count, ratio, idx, prev_prio, multigroup, master_slice; 841 uint8 group_auto_expansion = 0, next_group_valid = 0; 842 uint8 stat_present, pol_present, prio_ctrl; 843 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 844 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 845 _field_group_t *fg; 846 _field_entry_t *f_ent; 847 bcm_port_t port; 848 bcm_field_qualify_t q; 849 bcm_pbmp_t port_cmic_pbmp; 850 _field_slice_t *temp_fs = fs; 851 uint8 *count = NULL; 852 _field_stage_t *ingress_stage_fc = NULL; 853 uint8 max_udf_count = 0; 854 uint8 udf_idx; 855 uint8 color_independent; 856 uint8 group_flags = 0; 857 int part_idx; 858 int parts_cnt; 859 860 861 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 862 _BCM_FIELD_STAGE_INGRESS, &ingress_stage_fc)); 863 864 if (ingress_stage_fc->data_ctrl) { 865 max_udf_count = ingress_stage_fc->data_ctrl->num_elems * 2; 866 } 867 868 SOC_PBMP_ASSIGN(port_cmic_pbmp, PBMP_PORT_ALL(unit)); 869 SOC_PBMP_OR(port_cmic_pbmp, PBMP_CMIC(unit)); 870 871 /* Check for multiple groups in a slice */ 872 if (SOC_PBMP_EQ(fs->pbmp, port_cmic_pbmp)) { 873 multigroup = 0; 874 } else { 875 LOG_DEBUG(BSL_LS_BCM_FP, 876 (BSL_META_U(unit, 877 "_field_scache_sync: Multigroup.\n"))); 878 multigroup = 1; 879 } 880 LOG_DEBUG(BSL_LS_BCM_FP, 881 (BSL_META_U(unit, 882 "_field_scache_sync: Writing slice %d @ byte %d...\n"), 883 slice_idx, fc->scache_pos)); 884 885 buf[fc->scache_pos] = (slice_idx << 1) | multigroup; 886 fc->scache_pos++; 887 888 /* Get the master slice if expanded */ 889 master_slice = slice_idx; 890 while (temp_fs->prev != NULL) { 891 temp_fs = temp_fs->prev; 892 master_slice = temp_fs->slice_number; 893 } 894 895 /* Traverse all groups and dump group data for this slice */ 896 fg = fc->groups; 897 while (fg != NULL) { 898 if (fg->stage_id != stage_fc->stage_id) { 899 fg = fg->next; 900 continue; /* Not in this stage */ 901 } 902 if (fg->slices[0].slice_number != master_slice) { 903 LOG_DEBUG(BSL_LS_BCM_FP, 904 (BSL_META_U(unit, 905 "_field_scache_sync: No match on group %d.\n"), 906 fg->gid)); 907 fg = fg->next; 908 continue; /* Not in this slice */ 909 } 910 LOG_DEBUG(BSL_LS_BCM_FP, 911 (BSL_META_U(unit, 912 "_field_scache_sync: Match on group %d...\n"), 913 fg->gid)); 914 915 LOG_DEBUG(BSL_LS_BCM_FP, 916 (BSL_META_U(unit, 917 "_field_scache_sync: Writing group %d @ byte %d...\n"), 918 fg->gid, fc->scache_pos)); 919 920 SOC_PBMP_ITER(fg->pbmp, port) { 921 break; /* Pick first port found as representative */ 922 } 923 924 925 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) { 926 /* Long-id format selected => Save full GID */ 927 928 buf[fc->scache_pos] = fg->gid; 929 fc->scache_pos++; 930 buf[fc->scache_pos] = fg->gid >> 8; 931 fc->scache_pos++; 932 buf[fc->scache_pos] = fg->gid >> 16; 933 fc->scache_pos++; 934 buf[fc->scache_pos] = fg->gid >> 24; 935 fc->scache_pos++; 936 937 buf[fc->scache_pos] = port; 938 fc->scache_pos++; 939 } else { 940 /* Save compact GID */ 941 942 buf[fc->scache_pos] = (fg->gid) & 0xFF; /* GID_lo */ 943 fc->scache_pos++; 944 buf[fc->scache_pos] = ((fg->gid & 0xF00) << 4) | (port & 0xF); 945 fc->scache_pos++; /* GID_hi | port_lo */ 946 buf[fc->scache_pos] = (port >> 4); /* port_hi */ 947 fc->scache_pos++; 948 } 949 950 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) { 951 int i = 0; 952 for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) { 953 buf[fc->scache_pos] = fg->pbmp.pbits[i]; 954 fc->scache_pos++; 955 buf[fc->scache_pos] = fg->pbmp.pbits[i] >> 8; 956 fc->scache_pos++; 957 buf[fc->scache_pos] = fg->pbmp.pbits[i] >> 16; 958 fc->scache_pos++; 959 buf[fc->scache_pos] = fg->pbmp.pbits[i] >> 24; 960 fc->scache_pos++; 961 } 962 } 963 964 buf[fc->scache_pos] = fg->priority; 965 fc->scache_pos++; 966 buf[fc->scache_pos] = fg->priority >> 8; 967 fc->scache_pos++; 968 buf[fc->scache_pos] = fg->priority >> 16; 969 fc->scache_pos++; 970 buf[fc->scache_pos] = fg->priority >> 24; 971 fc->scache_pos++; 972 973 /* Write group action res id */ 974 buf[fc->scache_pos] = fg->action_res_id; 975 fc->scache_pos++; 976 buf[fc->scache_pos] = fg->action_res_id >> 8; 977 fc->scache_pos++; 978 buf[fc->scache_pos] = fg->action_res_id >> 16; 979 fc->scache_pos++; 980 buf[fc->scache_pos] = fg->action_res_id >> 24; 981 fc->scache_pos++; 982 983 /* Obtain list of qualifiers in fg->qset */ 984 qset_count = 0; 985 _FIELD_QSET_ITER(fg->qset, q) { 986 qset_count++; 987 } 988 989 LOG_DEBUG(BSL_LS_BCM_FP, 990 (BSL_META_U(unit, 991 "_field_scache_sync: Writing qset count (%d) @ byte %d...\n"), 992 qset_count, fc->scache_pos)); 993 994 buf[fc->scache_pos] = qset_count; /* qset_count */ 995 fc->scache_pos++; 996 _FIELD_QSET_ITER(fg->qset, q) { 997 LOG_DEBUG(BSL_LS_BCM_FP, 998 (BSL_META_U(unit, 999 "_field_scache_sync: Writing qid %d @ byte %d...\n"), 1000 q, fc->scache_pos)); 1001 1002 buf[fc->scache_pos] = q; /* QID */ 1003 fc->scache_pos++; 1004 if(NULL != buf1) { 1005 buf1[fc->scache_pos1] = q >> 8; 1006 fc->scache_pos1++; 1007 } 1008 } 1009 1010 count = &buf[fc->scache_pos]; 1011 fc->scache_pos++; 1012 *count = 0; 1013 1014 for (q = bcmFieldQualifyCount; q < ((int)_bcmFieldQualifyCount); q++) { 1015 if (BCM_FIELD_QSET_TEST(fg->qset, q)) { 1016 buf[fc->scache_pos] = q - bcmFieldQualifyCount; 1017 fc->scache_pos++; 1018 if(NULL != buf1) { 1019 buf1[fc->scache_pos1] = (q - bcmFieldQualifyCount) >> 8; 1020 fc->scache_pos1++; 1021 } 1022 *count = *count + 1; 1023 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 1024 "_field_scache_sync: Writing qid idx %d @ byte %d...\n"), 1025 q, fc->scache_pos - 1)); 1026 } 1027 } 1028 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 1029 "_field_scache_sync: Writing internal qset count (%d) @ byte %d...\n"), 1030 *count, fc->scache_pos - 1 - *count)); 1031 1032 count = &buf[fc->scache_pos]; 1033 fc->scache_pos++; 1034 *count = 0; 1035 1036 for (udf_idx = 0; udf_idx < max_udf_count ; udf_idx++) { 1037 if (SHR_BITGET(fg->qset.udf_map, udf_idx)) { 1038 buf[fc->scache_pos] = udf_idx; 1039 fc->scache_pos++; 1040 *count = *count + 1; 1041 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 1042 "_field_scache_sync: Writing UDF idx %d @ byte %d...\n"), 1043 udf_idx, fc->scache_pos - 1)); 1044 } 1045 } 1046 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 1047 "_field_scache_sync: Writing udf count (%d) @ byte %d...\n"), 1048 *count, fc->scache_pos - 1 - *count)); 1049 1050 1051 if (fg->flags & _FP_GROUP_SELECT_AUTO_EXPANSION) { 1052 group_auto_expansion = _FIELD_GROUP_AUTO_EXPANSION; 1053 } else { 1054 group_auto_expansion = 0; 1055 } 1056 1057 group_flags = 0; 1058 1059 if (fg->flags & _FP_GROUP_LOOKUP_ENABLED) { 1060 group_flags |= _FIELD_GROUP_LOOKUP_ENABLED; 1061 } 1062 1063 if (fg->flags & _FP_GROUP_WLAN) { 1064 group_flags |= _FIELD_GROUP_WLAN; 1065 } 1066 1067 /* Next group not valid */ 1068 next_group_valid = 0x0; 1069 fg = fg->next; 1070 while (fg != NULL) { 1071 if (multigroup 1072 && (fg->stage_id == stage_fc->stage_id) 1073 && (fg->slices[0].slice_number == slice_idx)) { 1074 /* Next group valid */ 1075 next_group_valid = _FIELD_GROUP_NEXT_GROUP_VALID; 1076 break; 1077 } 1078 fg = fg->next; 1079 } 1080 1081 /* 1082 * In this byte, 6 bits are used as below 1083 * bit 0 -- to indicate wheather next group 1084 * in this slice is valid or not 1085 * bit 1,2 -- contains group's instance. 1086 * bit 5 -- to indicate group lookup enable status. 1087 * bit 6 -- to indicate group is WLAN. 1088 * bit 7 -- to indicate group auto expansion status. 1089 */ 1090 1091 buf[fc->scache_pos] = (group_auto_expansion | next_group_valid | group_flags); 1092 1093 fc->scache_pos++; 1094 } 1095 /* Traverse all entries and dump entry data for this slice */ 1096 if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 1097 ratio = 2; 1098 } else { 1099 ratio = 1; 1100 } 1101 prev_prio = -1; 1102 for (idx = 0; idx < fs->entry_count / ratio; idx++) { 1103 /* Find EID that matches this HW index */ 1104 f_ent = fs->entries[idx]; 1105 if (f_ent == NULL) { 1106 continue; 1107 } 1108 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 1109 prio_ctrl = (f_ent->prio != prev_prio) ? 1 : 0; 1110 stat_present = (f_ent->statistic.flags & 1111 _FP_ENTRY_STAT_INSTALLED) ? 1 : 0; 1112 pol_present = (f_ent->policer[0].flags & 1113 _FP_POLICER_INSTALLED) ? 1 : 0; 1114 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) { 1115 /* Long-id format select => Save complete EID */ 1116 1117 buf[fc->scache_pos] = f_ent->eid; 1118 fc->scache_pos++; 1119 buf[fc->scache_pos] = f_ent->eid >> 8; 1120 fc->scache_pos++; 1121 buf[fc->scache_pos] = f_ent->eid >> 16; 1122 fc->scache_pos++; 1123 buf[fc->scache_pos] = f_ent->eid >> 24; 1124 fc->scache_pos++; 1125 1126 buf[fc->scache_pos] = prio_ctrl 1127 | (stat_present << 1) 1128 | (pol_present << 2); 1129 fc->scache_pos++; 1130 } else { 1131 /* Save compact EID */ 1132 1133 buf[fc->scache_pos] = f_ent->eid & 0xFF; /* EID_lo */ 1134 fc->scache_pos++; 1135 buf[fc->scache_pos] = ((f_ent->eid >> 8) & 0xF) | (prio_ctrl << 4) | 1136 (stat_present << 5) | (pol_present << 6); 1137 /* EID_hi + control bits */ 1138 fc->scache_pos++; 1139 } 1140 if (multigroup) { 1141 /* Multiple groups in slice => Save id of group to which 1142 entry belongs 1143 */ 1144 1145 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) { 1146 /* Save long GID */ 1147 1148 buf[fc->scache_pos] = f_ent->group->gid; 1149 fc->scache_pos++; 1150 buf[fc->scache_pos] = f_ent->group->gid >> 8; 1151 fc->scache_pos++; 1152 buf[fc->scache_pos] = f_ent->group->gid >> 16; 1153 fc->scache_pos++; 1154 buf[fc->scache_pos] = f_ent->group->gid >> 24; 1155 fc->scache_pos++; 1156 } else { 1157 /* Save compact GID */ 1158 1159 buf[fc->scache_pos] = f_ent->group->gid & 0xFF; /* GID_lo */ 1160 fc->scache_pos++; 1161 buf[fc->scache_pos] = (f_ent->group->gid >> 8) & 0xF; 1162 /* GID_hi */ 1163 fc->scache_pos++; 1164 } 1165 } 1166 if (prio_ctrl) { 1167 /* 32-bit priority is written */ 1168 buf[fc->scache_pos] = f_ent->prio & 0xFF; 1169 fc->scache_pos++; 1170 buf[fc->scache_pos] = (f_ent->prio >> 8) & 0xFF; 1171 fc->scache_pos++; 1172 buf[fc->scache_pos] = (f_ent->prio >> 16) & 0xFF; 1173 fc->scache_pos++; 1174 buf[fc->scache_pos] = (f_ent->prio >> 24) & 0xFF; 1175 fc->scache_pos++; 1176 prev_prio = f_ent->prio; 1177 } 1178 /* Write policer and stat object IDs if present */ 1179 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) { 1180 /* Save long IDs */ 1181 1182 if (pol_present) { 1183 buf[fc->scache_pos] = f_ent->policer[0].pid; 1184 fc->scache_pos++; 1185 buf[fc->scache_pos] = f_ent->policer[0].pid >> 8; 1186 fc->scache_pos++; 1187 buf[fc->scache_pos] = f_ent->policer[0].pid >> 16; 1188 fc->scache_pos++; 1189 buf[fc->scache_pos] = f_ent->policer[0].pid >> 24; 1190 fc->scache_pos++; 1191 } 1192 1193 if (stat_present) { 1194 buf[fc->scache_pos] = f_ent->statistic.sid; 1195 fc->scache_pos++; 1196 buf[fc->scache_pos] = f_ent->statistic.sid >> 8; 1197 fc->scache_pos++; 1198 buf[fc->scache_pos] = f_ent->statistic.sid >> 16; 1199 fc->scache_pos++; 1200 buf[fc->scache_pos] = f_ent->statistic.sid >> 24; 1201 fc->scache_pos++; 1202 } 1203 } else { 1204 /* Save compact IDs */ 1205 if (pol_present) { 1206 buf[fc->scache_pos] = (f_ent->policer[0].pid) & 0xFF; 1207 fc->scache_pos++; 1208 } 1209 if (stat_present) { 1210 if (pol_present) { 1211 buf[fc->scache_pos] = 1212 ((f_ent->policer[0].pid >> 8 & 0xF) << 4) | 1213 (f_ent->statistic.sid & 0xF); 1214 fc->scache_pos++; 1215 } else { 1216 buf[fc->scache_pos] = f_ent->statistic.sid & 0xF; 1217 fc->scache_pos++; 1218 } 1219 buf[fc->scache_pos] = (f_ent->statistic.sid >> 4) & 0xFF; 1220 fc->scache_pos++; 1221 } else if (pol_present) { 1222 buf[fc->scache_pos] = 1223 (f_ent->policer[0].pid >> 8 & 0xF) << 4; 1224 fc->scache_pos++; 1225 } 1226 } 1227 1228 parts_cnt = 0; 1229 if ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 1230 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) || 1231 (f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 1232 /* Sync entry part count for SVP & DVP type */ 1233 BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit, 1234 f_ent->group->stage_id, f_ent->group->flags, 1235 &parts_cnt)); 1236 1237 buf[fc->scache_pos] = parts_cnt; 1238 fc->scache_pos++; 1239 } 1240 1241 /* Save Dvp Type */ 1242 buf[fc->scache_pos] = f_ent->dvp_type; 1243 fc->scache_pos++; 1244 for (part_idx = 1; part_idx < parts_cnt; part_idx++) { 1245 buf[fc->scache_pos] = f_ent[part_idx].dvp_type; 1246 fc->scache_pos++; 1247 } 1248 1249 /* Save Svp Type */ 1250 buf[fc->scache_pos] = f_ent->svp_type; 1251 fc->scache_pos++; 1252 for (part_idx = 1; part_idx < parts_cnt; part_idx++) { 1253 buf[fc->scache_pos] = f_ent[part_idx].svp_type; 1254 fc->scache_pos++; 1255 } 1256 1257 /* Save Entry Color independent flag */ 1258 color_independent = (f_ent->flags & 1259 _FP_ENTRY_COLOR_INDEPENDENT) ? 1 : 0; 1260 buf[fc->scache_pos] = color_independent << 7; 1261 fc->scache_pos++; 1262 1263 BCM_IF_ERROR_RETURN(_field_entry_no_param_actions_scache_sync( 1264 unit, stage_fc, fc, f_ent, buf)); 1265 } 1266 } 1267 return BCM_E_NONE; 1268 } 1269 1270 /* 1271 * This function manages the Level 2 warm boot cache. The data will be stored 1272 * in the following format: 1273 * Start indicator (32 bits): Value = IFP/EFP/VFP 1274 * 1275 * Range check IDs (IFP) 1276 * 8-bit ID count (1 uint8) 1277 * ID0 (4 x uint8) 1278 * . 1279 * IDN (4 x uint8) 1280 * 1281 * Data qualifier data, as follows: 1282 * 8-bit data qualifier count (1 uint 8) 1283 * 32-bit data qualifier id (1 int) 1284 * 2-bit "length remainder" | 3-bit flags | 3-bit offset base (1 uint 8) 1285 * 16-bit data qualifier match-data offset (1 uint 16) 1286 * 16-bit hw_bmap field of data qualifier 1287 * (Note that this field is linked to the hardware; namely, the width of this 1288 * bitmap is the number of UDF n-byte chunks supported, i.e. the number of 1289 * "columns" in the UDF_OFFSET table.) 1290 * 1291 * Group/entry data 1292 * Slice num (5 bits) | Multigroup slice indicator (1 bit): (1 uint8) 1293 * GID_lo (8 bits): (1 uint 8) 1294 * GID_hi (4 bits) | Representative_port_lo (4 bits): (1 uint 8) 1295 * Representative_port_hi (2 bits) | Reserved (6 bits): (1 uint 8) 1296 * Group priority (32 bits): (4 uint 8) 1297 * Qualifier count (8 bits): (1 uint 8) 1298 * QID 1 (8 bits): (1 uint 8) 1299 * . 1300 * QID N (8 bits): (1 uint 8) 1301 * Next_group_valid (1 bit) | Reserved (7 bits): (1 uint 8) 1302 * 1303 * Groups are immediately followed by entries, which can have one of the 1304 * following two formats depending on the multigroup slice indicator: 1305 * Long format: 1306 * 8 bit EID_lo: (1 uint 8) 1307 * 4 bit EID_hi | priority_ctrl (1 bit) | Policer (1 bit) | Stat (1 bit): 1308 (1 uint 8) 1309 * 8 bit GID_lo: (1 uint 8) 1310 * 4 bit GID_hi | 4 reserved bits: (1 uint 8) 1311 * priority_0: (1 uint 8) 1312 * priority_1: (1 uint 8) <---- The 32-bit priority is stored only if it is 1313 * priority_2: (1 uint 8) different from the entry before it. 1314 * priority_3: (1 uint 8) 1315 * PID_lo (8 bits): (1 uint8) 1316 * PID_hi (4 bits) | SID_lo (4 bits): (1 uint8) 1317 * SID_hi (4 bits): (1 uint 8) 1318 * DVP_Type (4bits): (1 uint4) 1319 * SVP_Type (4 bits): (1 uint4) 1320 * Reserved (8 bits): (1 uint8) future purpose 1321 * 1322 * Short format: 1323 * 8 bit EID_lo: (1 uint 8) 1324 * 4 bit EID_hi | priority_ctrl (1 bit) | Policer (1 bit) | Stat (1 bit): 1325 (1 uint 8) 1326 * priority_0: (1 uint 8) 1327 * priority_1: (1 uint 8) <---- The 32-bit priority is stored only if it is 1328 * priority_2: (1 uint 8) different from the entry before it. 1329 * priority_3: (1 uint 8) 1330 * PID_lo (8 bits): (1 uint8) 1331 * PID_hi (4 bits) | SID_lo (4 bits): (1 uint8) 1332 * SID_hi (8 bits): (1 uint 8) 1333 * DVP_Type (4bits): (1 uint4) 1334 * SVP_Type (4 bits): (1 uint4) 1335 * Reserved (8 bits): (1 uint8) future purpose 1336 * 1337 * End indicator (32 bits): Value = IFP/EFP/VFP 1338 */ 1339 1340 void 1341 _field_scache_stage_hdr_save(_field_control_t *fc, 1342 uint32 header 1343 ) 1344 { 1345 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 1346 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 1347 1348 /* Mark the beginning of the particular FP section */ 1349 buf[fc->scache_pos] = header; 1350 fc->scache_pos++; 1351 buf[fc->scache_pos] = header >> 8; 1352 fc->scache_pos++; 1353 buf[fc->scache_pos] = header >> 16; 1354 fc->scache_pos++; 1355 buf[fc->scache_pos] = header >> 24; 1356 fc->scache_pos++; 1357 1358 /* Save long-id setting */ 1359 1360 buf[fc->scache_pos] = fc->flags; 1361 fc->scache_pos++; 1362 1363 if(NULL != buf1) { 1364 /* Mark the beginning of the particular FP section */ 1365 buf1[fc->scache_pos1] = header; 1366 fc->scache_pos1++; 1367 buf1[fc->scache_pos1] = header >> 8; 1368 fc->scache_pos1++; 1369 buf1[fc->scache_pos1] = header >> 16; 1370 fc->scache_pos1++; 1371 buf1[fc->scache_pos1] = header >> 24; 1372 fc->scache_pos1++; 1373 } 1374 } 1375 1376 int 1377 _field_scache_stage_hdr_chk(_field_control_t *fc, 1378 uint32 header 1379 ) 1380 { 1381 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 1382 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 1383 uint32 temp; 1384 1385 /* Check header */ 1386 1387 temp = buf[fc->scache_pos]; 1388 fc->scache_pos++; 1389 temp |= buf[fc->scache_pos] << 8; 1390 fc->scache_pos++; 1391 temp |= buf[fc->scache_pos] << 16; 1392 fc->scache_pos++; 1393 temp |= buf[fc->scache_pos] << 24; 1394 fc->scache_pos++; 1395 if (temp != header) { 1396 fc->l2warm = 0; 1397 1398 return (BCM_E_INTERNAL); 1399 } 1400 1401 if(NULL != buf1) { 1402 temp = buf1[fc->scache_pos1]; 1403 fc->scache_pos1++; 1404 temp |= buf1[fc->scache_pos1] << 8; 1405 fc->scache_pos1++; 1406 temp |= buf1[fc->scache_pos1] << 16; 1407 fc->scache_pos1++; 1408 temp |= buf1[fc->scache_pos1] << 24; 1409 fc->scache_pos1++; 1410 if (temp != header) { 1411 fc->l2warm = 0; 1412 return (BCM_E_INTERNAL); 1413 } 1414 } 1415 1416 if ((fc->wb_recovered_version) == BCM_FIELD_WB_VERSION_1_0) { 1417 /* Old scache version, always uses compact ids */ 1418 1419 fc->flags &= ~_FP_STABLE_SAVE_LONG_IDS; 1420 fc->flags &= ~_FP_AUTOEXPAND_WITH_POLICER; 1421 } else { 1422 /* Retrieve long-id setting */ 1423 1424 if (buf[fc->scache_pos] & _FP_STABLE_SAVE_LONG_IDS) { 1425 fc->flags |= _FP_STABLE_SAVE_LONG_IDS; 1426 } else { 1427 fc->flags &= ~_FP_STABLE_SAVE_LONG_IDS; 1428 } 1429 1430 /* Retrieve Intra-slice device setting */ 1431 if (buf[fc->scache_pos] & _FP_INTRASLICE_ENABLE) { 1432 fc->flags |= _FP_INTRASLICE_ENABLE; 1433 } else { 1434 fc->flags &= ~_FP_INTRASLICE_ENABLE; 1435 } 1436 1437 /* Retrieve color independent device setting */ 1438 if (buf[fc->scache_pos] & _FP_COLOR_INDEPENDENT) { 1439 fc->flags |= _FP_COLOR_INDEPENDENT; 1440 } else { 1441 fc->flags &= ~_FP_COLOR_INDEPENDENT; 1442 } 1443 1444 /* Retrieve Stat sync device setting */ 1445 if (buf[fc->scache_pos] & _FP_STAT_SYNC_ENABLE) { 1446 fc->flags |= _FP_STAT_SYNC_ENABLE; 1447 } else { 1448 fc->flags &= ~_FP_STAT_SYNC_ENABLE; 1449 } 1450 1451 /* Retrieve Group Sharing sync device setting */ 1452 if (buf[fc->scache_pos] & _FP_POLICER_GROUP_SHARE_ENABLE) { 1453 fc->flags |= _FP_POLICER_GROUP_SHARE_ENABLE; 1454 } else { 1455 fc->flags &= ~_FP_POLICER_GROUP_SHARE_ENABLE; 1456 } 1457 /* Flag to allow attaching policer to an auto expanded slice */ 1458 if (buf[fc->scache_pos] & _FP_AUTOEXPAND_WITH_POLICER) { 1459 fc->flags |= _FP_AUTOEXPAND_WITH_POLICER; 1460 } else { 1461 fc->flags &= ~_FP_AUTOEXPAND_WITH_POLICER; 1462 } 1463 1464 fc->scache_pos++; 1465 } 1466 1467 return (BCM_E_NONE); 1468 } 1469 1470 void 1471 _field_scache_sync_data_quals_write(_field_control_t *fc, 1472 _field_data_control_t *data_ctrl 1473 ) 1474 { 1475 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 1476 unsigned cnt; 1477 _field_data_qualifier_t *f_dq; 1478 1479 LOG_DEBUG(BSL_LS_BCM_FP, 1480 (BSL_META("FP vverb: _field_scache_sync_data_quals_write...\n"))); 1481 /* Write data qual count */ 1482 1483 for (cnt = 0, f_dq = data_ctrl->data_qual; f_dq; f_dq = f_dq->next, ++cnt); 1484 1485 buf[fc->scache_pos] = cnt; 1486 fc->scache_pos++; 1487 1488 /* For each data qualifier, ... */ 1489 for (f_dq = data_ctrl->data_qual; f_dq; f_dq = f_dq->next) { 1490 /* Write data qual id */ 1491 1492 buf[fc->scache_pos] = f_dq->qid; 1493 fc->scache_pos++; 1494 buf[fc->scache_pos] = f_dq->qid >> 8; 1495 fc->scache_pos++; 1496 buf[fc->scache_pos] = f_dq->qid >> 16; 1497 fc->scache_pos++; 1498 buf[fc->scache_pos] = f_dq->qid >> 24; 1499 fc->scache_pos++; 1500 1501 /* Write data qual "length remainder", flags and offset base */ 1502 buf[fc->scache_pos] = f_dq->elem_count * data_ctrl->elem_size 1503 - f_dq->length 1504 - f_dq->byte_offset; 1505 fc->scache_pos++; 1506 buf[fc->scache_pos] = f_dq->offset_base; 1507 fc->scache_pos++; 1508 buf[fc->scache_pos] = f_dq->flags; 1509 fc->scache_pos++; 1510 buf[fc->scache_pos] = f_dq->flags >> 8; 1511 fc->scache_pos++; 1512 buf[fc->scache_pos] = f_dq->flags >> 16; 1513 fc->scache_pos++; 1514 buf[fc->scache_pos] = f_dq->flags >> 24; 1515 fc->scache_pos++; 1516 1517 /* Write data qual match-data offset */ 1518 buf[fc->scache_pos] = f_dq->offset; 1519 fc->scache_pos++; 1520 buf[fc->scache_pos] = f_dq->offset >> 8; 1521 fc->scache_pos++; 1522 1523 /* Write data qual offset-table occupancy */ 1524 buf[fc->scache_pos] = f_dq->hw_bmap; 1525 fc->scache_pos++; 1526 buf[fc->scache_pos] = f_dq->hw_bmap >> 8; 1527 fc->scache_pos++; 1528 } 1529 } 1530 1531 1532 int 1533 _field_scache_sync(int unit, _field_control_t *fc, 1534 _field_stage_t *stage_fc) 1535 { 1536 int slice_idx, range_count = 0; 1537 int rv = BCM_E_NONE; 1538 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 1539 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 1540 _field_slice_t *fs; 1541 _field_group_t *fg; 1542 uint32 start_char, end_char; 1543 int slice_is_primary; 1544 int slice_mode; 1545 _field_range_t *fr; 1546 int ratio = 0; 1547 int idx; 1548 _field_entry_t *f_ent; 1549 1550 1551 switch (stage_fc->stage_id) { 1552 case _BCM_FIELD_STAGE_INGRESS: 1553 start_char = _FIELD_IFP_DATA_START; 1554 end_char = _FIELD_IFP_DATA_END; 1555 break; 1556 case _BCM_FIELD_STAGE_EGRESS: 1557 start_char = _FIELD_EFP_DATA_START; 1558 end_char = _FIELD_EFP_DATA_END; 1559 break; 1560 case _BCM_FIELD_STAGE_LOOKUP: 1561 start_char = _FIELD_VFP_DATA_START; 1562 end_char = _FIELD_VFP_DATA_END; 1563 break; 1564 default: 1565 return BCM_E_PARAM; 1566 break; 1567 } 1568 1569 LOG_DEBUG(BSL_LS_BCM_FP, 1570 (BSL_META_U(unit, 1571 "_field_scache_sync: Synching scache for FP stage %d...\n"), 1572 stage_fc->stage_id)); 1573 1574 _field_scache_stage_hdr_save(fc, start_char); 1575 1576 /* Save the range check IDs */ 1577 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 1578 fr = stage_fc->ranges; 1579 while (fr) { 1580 fr = fr->next; 1581 range_count++; 1582 } 1583 buf[fc->scache_pos] = (uint8)range_count; 1584 fc->scache_pos++; 1585 if (range_count) { 1586 fr = stage_fc->ranges; 1587 while (fr) { 1588 buf[fc->scache_pos] = fr->rid & 0xFF; 1589 fc->scache_pos++; 1590 buf[fc->scache_pos] = (fr->rid >> 8) & 0xFF; 1591 fc->scache_pos++; 1592 buf[fc->scache_pos] = (fr->rid >> 16) & 0xFF; 1593 fc->scache_pos++; 1594 buf[fc->scache_pos] = (fr->rid >> 24) & 0xFF; 1595 fc->scache_pos++; 1596 fr = fr->next; 1597 } 1598 } 1599 } 1600 1601 /* Save data qualifiers */ 1602 1603 if (stage_fc->data_ctrl != 0) { 1604 _field_scache_sync_data_quals_write(fc, stage_fc->data_ctrl); 1605 } 1606 1607 _field_slice_map_write(unit, fc, stage_fc); 1608 1609 /* First sync the master slices */ 1610 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 1611 LOG_DEBUG(BSL_LS_BCM_FP, 1612 (BSL_META_U(unit, 1613 "_field_scache_sync: Checking slice %d...\n"), 1614 slice_idx)); 1615 1616 /* Skip slices without groups */ 1617 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 1618 fg = fc->groups; 1619 while (fg != NULL) { 1620 if (fg->stage_id != stage_fc->stage_id) { 1621 fg = fg->next; 1622 continue; /* Not in this stage */ 1623 } 1624 if (fg->slices[0].slice_number == slice_idx) { 1625 break; 1626 } 1627 fg = fg->next; 1628 } 1629 if (fg == NULL) { 1630 continue; /* No group found */ 1631 } 1632 /* Also skip expanded slices */ 1633 if (stage_fc->slices[_FP_DEF_INST][slice_idx].prev != NULL) { 1634 continue; 1635 } 1636 /* Ignore secondary slice in paired mode */ 1637 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA_SUPPORT) 1638 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_ENDURO(unit) || 1639 SOC_IS_KATANAX(unit) || SOC_IS_HURRICANEX(unit) || 1640 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) { 1641 soc_field_t fld; 1642 int efp_slice_mode, paired = 0; 1643 uint32 val; 1644 fp_port_field_sel_entry_t pfs; 1645 soc_field_t _fb2_slice_pairing_field[8] = { 1646 SLICE1_0_PAIRINGf, SLICE3_2_PAIRINGf, 1647 SLICE5_4_PAIRINGf, SLICE7_6_PAIRINGf, 1648 SLICE9_8_PAIRINGf, SLICE11_10_PAIRINGf, 1649 SLICE13_12_PAIRINGf, SLICE15_14_PAIRINGf}; 1650 soc_field_t _efp_slice_mode[] = {SLICE_0_MODEf, SLICE_1_MODEf, 1651 SLICE_2_MODEf, SLICE_3_MODEf}; 1652 soc_field_t _vfp_slice_pairing_field[2] = {SLICE1_0_PAIRINGf, 1653 SLICE3_2_PAIRINGf}; 1654 switch (stage_fc->stage_id) { 1655 case _BCM_FIELD_STAGE_INGRESS: 1656 BCM_IF_ERROR_RETURN(soc_mem_read(unit, FP_PORT_FIELD_SELm, 1657 MEM_BLOCK_ANY, 0, &pfs)); 1658 fld = _fb2_slice_pairing_field[slice_idx / 2]; 1659 paired = soc_FP_PORT_FIELD_SELm_field32_get(unit, 1660 &pfs, fld); 1661 break; 1662 case _BCM_FIELD_STAGE_EGRESS: 1663 BCM_IF_ERROR_RETURN(READ_EFP_SLICE_CONTROLr(unit, &val)); 1664 efp_slice_mode = soc_reg_field_get(unit, EFP_SLICE_CONTROLr, 1665 val,_efp_slice_mode[slice_idx]); 1666 if ((efp_slice_mode == _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE)) { 1667 paired = 1; 1668 } 1669 break; 1670 case _BCM_FIELD_STAGE_LOOKUP: 1671 BCM_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, &val)); 1672 fld = _vfp_slice_pairing_field[slice_idx / 2]; 1673 paired = soc_reg_field_get(unit, VFP_KEY_CONTROLr, val, fld); 1674 break; 1675 default: 1676 return BCM_E_PARAM; 1677 break; 1678 } 1679 if (paired && (slice_idx % 2)) { 1680 continue; 1681 } 1682 } 1683 #endif /* BCM_FIREBOLT2_SUPPORT */ 1684 1685 #ifdef BCM_FIREBOLT_SUPPORT 1686 if (SOC_IS_FIREBOLT(unit)) 1687 { 1688 BCM_IF_ERROR_RETURN(_field_fb_slice_is_primary(unit, slice_idx, 1689 &slice_is_primary, &slice_mode)); 1690 1691 if (!slice_is_primary) 1692 { 1693 continue; 1694 } 1695 } 1696 #endif /* BCM_FIREBOLT_SUPPORT */ 1697 1698 #ifdef BCM_RAVEN_SUPPORT 1699 if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) 1700 { 1701 BCM_IF_ERROR_RETURN(_field_fb_slice_is_primary(unit, slice_idx, 1702 &slice_is_primary, &slice_mode)); 1703 1704 if (!slice_is_primary) 1705 { 1706 continue; 1707 } 1708 } 1709 #endif /* BCM_RAVEN_SUPPORT */ 1710 BCM_IF_ERROR_RETURN 1711 (_field_group_entry_write(unit, slice_idx, fs, fc, stage_fc)); 1712 } 1713 1714 /* Now sync the expanded slices */ 1715 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 1716 1717 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 1718 /* Skip empty slices */ 1719 if (fs->entry_count == fs->free_count) { 1720 LOG_DEBUG(BSL_LS_BCM_FP, 1721 (BSL_META_U(unit, 1722 "_field_scache_sync: Slice is empty.\n"))); 1723 continue; 1724 } 1725 /* Skip master slices */ 1726 if (stage_fc->slices[_FP_DEF_INST][slice_idx].prev == NULL) { 1727 continue; 1728 } 1729 1730 /* Ignore secondary slice in paired mode */ 1731 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA_SUPPORT) 1732 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_ENDURO(unit) || 1733 SOC_IS_KATANAX(unit) || SOC_IS_HURRICANEX(unit) || 1734 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) { 1735 soc_field_t fld; 1736 int efp_slice_mode, paired = 0; 1737 uint32 val; 1738 fp_port_field_sel_entry_t pfs; 1739 soc_field_t _fb2_slice_pairing_field[8] = { 1740 SLICE1_0_PAIRINGf, SLICE3_2_PAIRINGf, 1741 SLICE5_4_PAIRINGf, SLICE7_6_PAIRINGf, 1742 SLICE9_8_PAIRINGf, SLICE11_10_PAIRINGf, 1743 SLICE13_12_PAIRINGf, SLICE15_14_PAIRINGf}; 1744 soc_field_t _efp_slice_mode[] = {SLICE_0_MODEf, SLICE_1_MODEf, 1745 SLICE_2_MODEf, SLICE_3_MODEf}; 1746 soc_field_t _vfp_slice_pairing_field[2] = {SLICE1_0_PAIRINGf, 1747 SLICE3_2_PAIRINGf}; 1748 switch (stage_fc->stage_id) { 1749 case _BCM_FIELD_STAGE_INGRESS: 1750 BCM_IF_ERROR_RETURN(soc_mem_read(unit, FP_PORT_FIELD_SELm, 1751 MEM_BLOCK_ANY, 0, &pfs)); 1752 fld = _fb2_slice_pairing_field[slice_idx / 2]; 1753 paired = soc_FP_PORT_FIELD_SELm_field32_get(unit, 1754 &pfs, fld); 1755 break; 1756 case _BCM_FIELD_STAGE_EGRESS: 1757 BCM_IF_ERROR_RETURN(READ_EFP_SLICE_CONTROLr(unit, &val)); 1758 efp_slice_mode = soc_reg_field_get(unit, EFP_SLICE_CONTROLr, 1759 val,_efp_slice_mode[slice_idx]); 1760 if ((efp_slice_mode == _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE)) { 1761 paired = 1; 1762 } 1763 break; 1764 case _BCM_FIELD_STAGE_LOOKUP: 1765 BCM_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, &val)); 1766 fld = _vfp_slice_pairing_field[slice_idx / 2]; 1767 paired = soc_reg_field_get(unit, VFP_KEY_CONTROLr, val, fld); 1768 break; 1769 default: 1770 return BCM_E_PARAM; 1771 break; 1772 } 1773 if (paired && (slice_idx % 2)) { 1774 continue; 1775 } 1776 } 1777 #endif /* BCM_FIREBOLT2_SUPPORT */ 1778 1779 #ifdef BCM_FIREBOLT_SUPPORT 1780 if (SOC_IS_FIREBOLT(unit)) 1781 { 1782 BCM_IF_ERROR_RETURN(_field_fb_slice_is_primary(unit, slice_idx, 1783 &slice_is_primary, &slice_mode)); 1784 1785 if (!slice_is_primary) 1786 { 1787 continue; 1788 } 1789 } 1790 #endif /* BCM_FIREBOLT_SUPPORT */ 1791 1792 #ifdef BCM_RAVEN_SUPPORT 1793 if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) 1794 { 1795 BCM_IF_ERROR_RETURN(_field_fb_slice_is_primary(unit, slice_idx, 1796 &slice_is_primary, &slice_mode)); 1797 1798 if (!slice_is_primary) 1799 { 1800 continue; 1801 } 1802 } 1803 #endif /* BCM_RAVEN_SUPPORT */ 1804 1805 /* 1806 * Skip expanded slices with no entries installed in Hw 1807 * to match recovery logic. 1808 */ 1809 if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 1810 ratio = 2; 1811 } else { 1812 ratio = 1; 1813 } 1814 1815 for (idx = 0; idx < fs->entry_count / ratio; idx++) { 1816 /* Find EID that matches this HW index */ 1817 f_ent = fs->entries[idx]; 1818 if (f_ent == NULL) { 1819 continue; 1820 } 1821 if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) { 1822 continue; 1823 } 1824 break; 1825 } 1826 1827 if (idx == (fs->entry_count / ratio)) { 1828 continue; 1829 } 1830 1831 BCM_IF_ERROR_RETURN 1832 (_field_group_entry_write(unit, slice_idx, fs, fc, stage_fc)); 1833 } 1834 1835 /* Mark end of Slice Info */ 1836 buf[fc->scache_pos] = _FP_WB_END_OF_SLICES; 1837 fc->scache_pos++; 1838 1839 /* Group Slice Selectors */ 1840 BCM_IF_ERROR_RETURN(_field_group_slice_selectors_sync(unit, 1841 &buf[fc->scache_pos], stage_fc->stage_id)); 1842 1843 LOG_DEBUG(BSL_LS_BCM_FP, 1844 (BSL_META_U(unit, 1845 "_field_scache_sync: Writing end of section @ byte %d.\n"), 1846 fc->scache_pos)); 1847 1848 /* Mark the end of the IFP section */ 1849 buf[fc->scache_pos] = end_char & 0xFF; 1850 fc->scache_pos++; 1851 buf[fc->scache_pos] = (end_char >> 8) & 0xFF; 1852 fc->scache_pos++; 1853 buf[fc->scache_pos] = (end_char >> 16) & 0xFF; 1854 fc->scache_pos++; 1855 buf[fc->scache_pos] = (end_char >> 24) & 0xFF; 1856 fc->scache_pos++; 1857 fc->scache_usage = fc->scache_pos; /* Usage in bytes */ 1858 1859 1860 if(NULL != buf1) { 1861 /* Mark the end of the IFP section */ 1862 buf1[fc->scache_pos1] = end_char & 0xFF; 1863 fc->scache_pos1++; 1864 buf1[fc->scache_pos1] = (end_char >> 8) & 0xFF; 1865 fc->scache_pos1++; 1866 buf1[fc->scache_pos1] = (end_char >> 16) & 0xFF; 1867 fc->scache_pos1++; 1868 buf1[fc->scache_pos1] = (end_char >> 24) & 0xFF; 1869 fc->scache_pos1++; 1870 } 1871 1872 /* Check for overflow */ 1873 if (fc->scache_pos > fc->scache_size[_FIELD_SCACHE_PART_0]) { 1874 LOG_DEBUG(BSL_LS_BCM_FP, 1875 (BSL_META_U(unit, 1876 "FP(unit %d) Error: Current Scache Position[%u] exceeds Scache size[%u]\n"), 1877 unit, fc->scache_pos, fc->scache_size[_FIELD_SCACHE_PART_0])); 1878 return BCM_E_INTERNAL; 1879 } 1880 1881 if (buf1 != NULL) { 1882 if (fc->scache_pos1 > fc->scache_size[_FIELD_SCACHE_PART_1]) { 1883 LOG_DEBUG(BSL_LS_BCM_FP, 1884 (BSL_META_U(unit, 1885 "FP(unit %d) Error: Current Scache Position1[%u] exceeds Scache size[%u]\n"), 1886 unit, fc->scache_pos1, fc->scache_size[_FIELD_SCACHE_PART_1])); 1887 return BCM_E_INTERNAL; 1888 } 1889 } 1890 1891 return rv; 1892 } 1893 1894 /* Recover FP data qualifiers */ 1895 1896 int 1897 _field_data_qual_recover(int unit, 1898 _field_control_t *fc, 1899 _field_stage_t *stage_fc 1900 ) 1901 { 1902 _field_data_control_t *data_ctrl; 1903 uint8 *buf; 1904 unsigned dqcnt, n, i, len_rem; 1905 _field_data_qualifier_t *f_dq = NULL; 1906 1907 if ((data_ctrl = stage_fc->data_ctrl) == 0) { 1908 return (BCM_E_NONE); 1909 } 1910 1911 if (fc->l2warm == 0) { 1912 /* No data qualifier recovery in Level 1 */ 1913 return BCM_E_NONE; 1914 } 1915 1916 buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 1917 1918 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 1919 1920 if (soc_mem_is_valid(unit, FP_UDF_TCAMm)) { 1921 /* Device has UDF TCAM => 1922 Recover internal information regarding TCAM entry usage 1923 */ 1924 1925 int rv; 1926 fp_udf_tcam_entry_t fp_udf_tcam_entry; 1927 _field_data_tcam_entry_t *tcam_entryp; 1928 bcm_field_data_packet_format_t pkt_fmt; 1929 int8 valid = 0; 1930 uint32 field = 1; 1931 uint32 mask = 0; 1932 uint32 ct; 1933 1934 /* Recover TCAM entry reference counts and priorities */ 1935 for (tcam_entryp = data_ctrl->tcam_entry_arr, 1936 i = 0, 1937 n = soc_mem_index_count(unit, FP_UDF_TCAMm); 1938 n; 1939 --n, ++i, ++tcam_entryp) { 1940 tcam_entryp->ref_count = buf[fc->scache_pos]; 1941 fc->scache_pos++; 1942 1943 BCM_IF_ERROR_RETURN(soc_mem_read(unit, 1944 FP_UDF_TCAMm, 1945 MEM_BLOCK_ANY, 1946 i, 1947 fp_udf_tcam_entry.entry_data 1948 ) 1949 ); 1950 1951 if (tcam_entryp->ref_count == 0) { 1952 /* TCAM entry is not in use */ 1953 1954 /* Consistency check: the valid bit for the TCAM entry 1955 better be cleared! 1956 */ 1957 if (soc_mem_field32_get(unit, 1958 FP_UDF_TCAMm, 1959 fp_udf_tcam_entry.entry_data, 1960 VALIDf 1961 ) 1962 != 0 1963 ) { 1964 /* Using new UDF module, value of ref_count always 1965 equal zero, but field VALIDf of used UDF entry 1966 equals to one. So need to skip this case. 1967 */ 1968 if (soc_feature(unit, soc_feature_udf_support)) { 1969 if (UDF_CTRL(unit)->udf_used_by_module 1970 == UDF_USED_BY_FIELD_MODULE) { 1971 return (BCM_E_INTERNAL); 1972 } 1973 } else { 1974 return (BCM_E_INTERNAL); 1975 } 1976 } 1977 1978 continue; 1979 } 1980 1981 /* TCAM entry is in use */ 1982 1983 /* Consistency check: the valid bit for the TCAM entry 1984 better be set! 1985 */ 1986 if (soc_mem_field32_get(unit, 1987 FP_UDF_TCAMm, 1988 fp_udf_tcam_entry.entry_data, 1989 VALIDf 1990 ) 1991 == 0 1992 ) { 1993 return (BCM_E_INTERNAL); 1994 } 1995 1996 bcm_field_data_packet_format_t_init(&pkt_fmt); 1997 1998 /* Parse l2 format.*/ 1999 rv = _field_trx2_udf_tcam_entry_l2format_parse( 2000 unit, 2001 fp_udf_tcam_entry.entry_data, 2002 &pkt_fmt.l2 2003 ); 2004 BCM_IF_ERROR_RETURN(rv); 2005 2006 /* Parse vlan_tag format.*/ 2007 rv = _field_trx2_udf_tcam_entry_vlanformat_parse( 2008 unit, 2009 fp_udf_tcam_entry.entry_data, 2010 &pkt_fmt.vlan_tag 2011 ); 2012 BCM_IF_ERROR_RETURN(rv); 2013 2014 /* Parse l3 fields.*/ 2015 rv = _field_trx2_udf_tcam_entry_l3_parse( 2016 unit, 2017 fp_udf_tcam_entry.entry_data, 2018 &pkt_fmt 2019 ); 2020 BCM_IF_ERROR_RETURN(rv); 2021 2022 /* Parse Udf flags */ 2023 rv = _field_trx2_udf_tcam_entry_flags_parse( 2024 unit, 2025 fp_udf_tcam_entry.entry_data, 2026 &pkt_fmt.flags); 2027 2028 BCM_IF_ERROR_RETURN(rv); 2029 2030 /* Recover TCAM entry priority */ 2031 tcam_entryp->priority = 0; 2032 if (pkt_fmt.l2 != BCM_FIELD_DATA_FORMAT_L2_ANY) { 2033 /* L2 format was specified */ 2034 2035 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_L2_FORMAT; 2036 } 2037 2038 if (pkt_fmt.vlan_tag != BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY) { 2039 /* Vlan tag format was specified */ 2040 2041 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_VLAN_FORMAT; 2042 } 2043 2044 if (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_NONE 2045 && pkt_fmt.outer_ip == BCM_FIELD_DATA_FORMAT_IP_ANY 2046 && pkt_fmt.inner_ip == BCM_FIELD_DATA_FORMAT_IP_NONE 2047 ) { 2048 /* Entry corresponds to a call to 2049 bcm_field_data_qualifier_ip_protocol_add() or 2050 bcm_field_data_qualifier_ethertype_add() 2051 */ 2052 2053 if (soc_mem_field32_get(unit, 2054 FP_UDF_TCAMm, 2055 fp_udf_tcam_entry.entry_data, 2056 L3_FIELDS_MASKf) 2057 2058 ) { 2059 if ((soc_mem_field32_get(unit, 2060 FP_UDF_TCAMm, 2061 fp_udf_tcam_entry.entry_data, 2062 L3_FIELDSf) 2063 & 0xff0000) >> 16 2064 2065 ) { 2066 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_IPPROTO; 2067 } 2068 } 2069 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MISC; 2070 } else { 2071 /* Entry corresponds to a call to 2072 bcm_field_data_qualifier_packet_format_add() 2073 */ 2074 if ((pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_NONE) || 2075 (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP) || 2076 (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_GRE)) { 2077 2078 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_L3_FORMAT; 2079 2080 } else if (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_FCOE 2081 || pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_FCOE_INIT) { 2082 2083 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_FCOE_FORMAT; 2084 /* 2085 * Entry matching on Outer + Inner FCOE extended headers has 2086 * higher priority. 2087 */ 2088 if ((BCM_FIELD_DATA_FORMAT_FIBRE_CHAN_ANY 2089 != pkt_fmt.fibre_chan_outer) 2090 && (BCM_FIELD_DATA_FORMAT_FIBRE_CHAN_ANY 2091 != pkt_fmt.fibre_chan_inner)) { 2092 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_FCOE_FORMAT; 2093 } 2094 } else if (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS) { 2095 2096 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_FORMAT; 2097 2098 switch(pkt_fmt.mpls) { 2099 case BCM_FIELD_DATA_FORMAT_MPLS_ONE_LABEL: 2100 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_ONE_LABEL; 2101 break; 2102 case BCM_FIELD_DATA_FORMAT_MPLS_TWO_LABELS: 2103 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_TWO_LABEL; 2104 break; 2105 case BCM_FIELD_DATA_FORMAT_MPLS_THREE_LABELS: 2106 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_THREE_LABEL; 2107 break; 2108 case BCM_FIELD_DATA_FORMAT_MPLS_FOUR_LABELS: 2109 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_FOUR_LABEL; 2110 break; 2111 case BCM_FIELD_DATA_FORMAT_MPLS_FIVE_LABELS: 2112 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_FIVE_LABEL; 2113 break; 2114 case BCM_FIELD_DATA_FORMAT_MPLS_ANY: 2115 break; 2116 default: 2117 return (BCM_E_INTERNAL); 2118 } 2119 } 2120 2121 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_L3_FORMAT; 2122 } 2123 /* Update Priority based on UDF Flags */ 2124 for (ct = 0; ; ct++) { 2125 if (udf_fields_f[ct][field] == INVALIDf) { 2126 break; 2127 } 2128 2129 valid = soc_mem_field_valid(unit, FP_UDF_TCAMm, 2130 udf_fields_f[ct][field]); 2131 if (valid == TRUE) { 2132 if (soc_mem_field32_get(unit, FP_UDF_TCAMm, 2133 fp_udf_tcam_entry.entry_data, udf_fields_f[ct][mask])) { 2134 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_FLAGS; 2135 } 2136 } 2137 } 2138 } 2139 } 2140 2141 #endif /* defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) */ 2142 2143 for (dqcnt = buf[fc->scache_pos++]; dqcnt; --dqcnt) { 2144 _bcm_field_data_qualifier_alloc(unit, &f_dq); 2145 2146 /* Read data qual id */ 2147 2148 f_dq->qid = buf[fc->scache_pos]; 2149 fc->scache_pos++; 2150 f_dq->qid |= buf[fc->scache_pos] << 8; 2151 fc->scache_pos++; 2152 f_dq->qid |= buf[fc->scache_pos] << 16; 2153 fc->scache_pos++; 2154 f_dq->qid |= buf[fc->scache_pos] << 24; 2155 fc->scache_pos++; 2156 2157 /* Read data qual "length remainder", flags and offset base */ 2158 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_10) { 2159 len_rem = buf[fc->scache_pos] >> 6; 2160 f_dq->flags = (buf[fc->scache_pos] >> 1) 2161 & _BCM_FIELD_DATA_QUALIFIER_FLAGS; 2162 f_dq->offset_base = buf[fc->scache_pos] & 7; 2163 fc->scache_pos++; 2164 } else { 2165 len_rem = buf[fc->scache_pos]; 2166 fc->scache_pos++; 2167 2168 f_dq->offset_base = buf[fc->scache_pos]; 2169 fc->scache_pos++; 2170 2171 f_dq->flags = buf[fc->scache_pos]; 2172 fc->scache_pos++; 2173 f_dq->flags |= buf[fc->scache_pos] << 8; 2174 fc->scache_pos++; 2175 f_dq->flags |= buf[fc->scache_pos] << 16; 2176 fc->scache_pos++; 2177 f_dq->flags |= buf[fc->scache_pos] << 24; 2178 fc->scache_pos++; 2179 } 2180 2181 /* Read data qual match-data offset */ 2182 f_dq->offset = buf[fc->scache_pos]; 2183 fc->scache_pos++; 2184 f_dq->offset |= buf[fc->scache_pos] << 8; 2185 fc->scache_pos++; 2186 2187 /* Read data qual hw_bmap */ 2188 f_dq->hw_bmap = buf[fc->scache_pos]; 2189 fc->scache_pos++; 2190 f_dq->hw_bmap |= buf[fc->scache_pos] << 8; 2191 fc->scache_pos++; 2192 2193 /* Find number of elements used */ 2194 for (f_dq->elem_count = i = 0, n = (2 * stage_fc->data_ctrl->num_elems); 2195 n; 2196 --n, ++i 2197 ) { 2198 if (f_dq->hw_bmap & (1U << i)) { 2199 ++f_dq->elem_count; 2200 } 2201 } 2202 2203 /* Consistency check: hw_bmap should not be 0! */ 2204 if (f_dq->elem_count == 0) { 2205 _bcm_field_data_qualifier_free(unit, f_dq); 2206 2207 return (BCM_E_INTERNAL); 2208 } 2209 2210 _field_data_qualifier_init2(unit, stage_fc, f_dq); 2211 2212 f_dq->length = f_dq->elem_count * data_ctrl->elem_size 2213 - f_dq->byte_offset 2214 - len_rem; 2215 2216 /* N.B. fq->flags is not applicable for Triumph2 => Leave as 0 */ 2217 2218 /* Merge qualifier's hw_bmap into overall uasge bmap */ 2219 data_ctrl->usage_bmap |= f_dq->hw_bmap; 2220 } 2221 2222 return (BCM_E_NONE); 2223 } 2224 2225 2226 /* Update a qset's udf_bmap to reflect actual data qualifier usage. */ 2227 2228 void 2229 _field_qset_udf_bmap_reinit(int unit, 2230 _field_stage_t *stage_fc, 2231 bcm_field_qset_t *qset, 2232 int qual_id 2233 ) 2234 { 2235 _field_data_qualifier_t *f_dq; 2236 unsigned elem_idx, n; 2237 int rv; 2238 _field_stage_t *ingress_stage_fc = NULL; 2239 _field_control_t *fc = NULL; 2240 2241 rv = _field_control_get(unit, &fc); 2242 if (BCM_FAILURE(rv)) { 2243 return; 2244 } 2245 if (fc->l2warm) { 2246 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_10) { 2247 return; 2248 } 2249 } 2250 2251 #if defined(BCM_ENDURO_SUPPORT) 2252 if(SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) || 2253 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) { 2254 if (qual_id < _bcmFieldQualifyData0 || qual_id > _bcmFieldQualifyData3) { 2255 return; 2256 } 2257 } else 2258 #endif /* BCM_ENDURO_SUPPORT */ 2259 #if defined(BCM_TOMAHAWK_SUPPORT) 2260 if(soc_feature(unit, soc_feature_field_multi_pipe_support)) 2261 { 2262 if (qual_id < _bcmFieldQualifyData0 || qual_id > _bcmFieldQualifyData9) { 2263 return; 2264 } 2265 } else 2266 #endif /*BCM_TOMAHAWK_SUPPORT*/ 2267 #if defined(BCM_TOMAHAWK3_SUPPORT) 2268 if (soc_feature(unit, soc_feature_udf_selector_support)) { 2269 if (qual_id < _bcmFieldQualifyData0 2270 || qual_id > _bcmFieldQualifyData15) { 2271 return; 2272 } 2273 } else 2274 #endif /*BCM_TOMAHAWK3_SUPPORT*/ 2275 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) 2276 if ((SOC_IS_TD_TT(unit) 2277 || SOC_IS_KATANAX(unit) 2278 || SOC_IS_TRIUMPH3(unit))) { 2279 if (qual_id < _bcmFieldQualifyData0 || qual_id > _bcmFieldQualifyData3) { 2280 return; 2281 } 2282 2283 } else 2284 #endif /* BCM_TRIDENT_SUPPORT || BCM_KATANA_SUPPORT*/ 2285 { 2286 if (qual_id < _bcmFieldQualifyData0 || qual_id > _bcmFieldQualifyData1) { 2287 return; 2288 } 2289 } 2290 2291 /* UDF elements are always stored in Ingress stage control 2292 * irrespective of it being used in any other stage */ 2293 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &ingress_stage_fc); 2294 if (BCM_FAILURE(rv)) { 2295 return; 2296 } 2297 2298 for (f_dq = ingress_stage_fc->data_ctrl->data_qual ; f_dq; f_dq = f_dq->next) { 2299 for (elem_idx = 0, n = ingress_stage_fc->data_ctrl->num_elems * 2; n; --n, ++elem_idx) { 2300 if ((f_dq->hw_bmap & (1U << elem_idx)) == 0) { 2301 continue; 2302 } 2303 2304 SHR_BITSET(qset->udf_map, elem_idx); 2305 } 2306 } 2307 2308 #if defined (BCM_TRIUMPH2_SUPPORT) 2309 if (soc_feature(unit, soc_feature_udf_support)) { 2310 bcmi_xgs4_udf_offset_info_t *tmp; 2311 UDF_LOCK(unit); 2312 for (tmp = UDF_CTRL(unit)->offset_info_head; tmp; tmp = tmp->next) { 2313 for (elem_idx = 0, n = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); n; --n, ++elem_idx) { 2314 if ((tmp->hw_bmap & (1U << elem_idx)) == 0) { 2315 continue; 2316 } 2317 2318 SHR_BITSET(qset->udf_map, elem_idx); 2319 } 2320 } 2321 UDF_UNLOCK(unit); 2322 } 2323 #endif 2324 2325 } 2326 2327 2328 /* Recover range checkers */ 2329 int 2330 _field_range_check_reinit(int unit, _field_stage_t *stage_fc, 2331 _field_control_t *fc) 2332 { 2333 int idx, index_min, index_max, count, valid_count; 2334 uint32 enable, type; 2335 soc_mem_t mem; 2336 uint32 tbl_entry[SOC_MAX_MEM_FIELD_WORDS]; 2337 _field_range_t *fr, **last_fr; 2338 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 2339 2340 count = valid_count = 0; 2341 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 2342 mem = FP_RANGE_CHECKm; 2343 } else { 2344 mem = ESM_RANGE_CHECKm; 2345 } 2346 if (fc->l2warm) { 2347 count = buf[fc->scache_pos]; 2348 fc->scache_pos++; 2349 } 2350 2351 last_fr = &stage_fc->ranges; 2352 index_min = soc_mem_index_min(unit, mem); 2353 index_max = soc_mem_index_max(unit, mem); 2354 for (idx = index_min; idx <= index_max; idx ++) { 2355 sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 2356 BCM_IF_ERROR_RETURN 2357 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tbl_entry)); 2358 soc_mem_field_get(unit, mem, tbl_entry, ENABLEf, &enable); 2359 if (enable == 0) { 2360 continue; 2361 } 2362 valid_count++; 2363 /* Create a new range entry for the list */ 2364 if ((fr = sal_alloc(sizeof (*fr), "fp_range")) == NULL) { 2365 return (BCM_E_MEMORY); 2366 } 2367 sal_memset(fr, 0, sizeof(_field_range_t)); 2368 /* Populate the structure */ 2369 if (fc->l2warm) { 2370 /* Get the IDs */ 2371 fr->rid = 0; 2372 fr->rid |= buf[fc->scache_pos]; 2373 fc->scache_pos++; 2374 fr->rid |= buf[fc->scache_pos] << 8; 2375 fc->scache_pos++; 2376 fr->rid |= buf[fc->scache_pos] << 16; 2377 fc->scache_pos++; 2378 fr->rid |= buf[fc->scache_pos] << 24; 2379 fc->scache_pos++; 2380 } else { 2381 fr->rid = idx; 2382 } 2383 fr->hw_index = idx; 2384 fr->style = _FP_RANGE_STYLE_FIREBOLT; 2385 soc_mem_field_get(unit, mem, tbl_entry, LOWER_BOUNDSf, 2386 (uint32 *)&(fr->min)); 2387 soc_mem_field_get(unit, mem, tbl_entry, UPPER_BOUNDSf, 2388 (uint32 *)&(fr->max)); 2389 if ((SOC_MEM_FIELD_VALID(unit, mem, FIELD_SELECTf))) { 2390 soc_mem_field_get(unit, mem, tbl_entry, FIELD_SELECTf, &type); 2391 switch (type) { 2392 case 0: 2393 fr->flags |= BCM_FIELD_RANGE_SRCPORT; 2394 break; 2395 case 1: 2396 fr->flags |= BCM_FIELD_RANGE_DSTPORT; 2397 break; 2398 case 2: 2399 fr->flags |= BCM_FIELD_RANGE_OUTER_VLAN; 2400 break; 2401 case 3: 2402 fr->flags |= BCM_FIELD_RANGE_PACKET_LENGTH; 2403 break; 2404 default: 2405 break; /* Should never happen */ 2406 } 2407 } else { 2408 soc_mem_field_get(unit, mem, tbl_entry, 2409 SOURCE_DESTINATION_SELECTf, &type); 2410 if (type == 1) { 2411 fr->flags |= BCM_FIELD_RANGE_SRCPORT; 2412 } else { 2413 fr->flags |= BCM_FIELD_RANGE_DSTPORT; 2414 } 2415 } 2416 2417 /* Add to list of range checkers. */ 2418 2419 *last_fr = fr; 2420 last_fr = &fr->next; 2421 } 2422 if (fc->l2warm && count != valid_count) { 2423 return BCM_E_INTERNAL; 2424 } 2425 return BCM_E_NONE; 2426 } 2427 2428 STATIC int 2429 _field_scache_version_size_check(int unit, int former_size, 2430 uint16 former_version, 2431 int current_size, 2432 uint16 current_version) 2433 { 2434 int delta_size[10] = {0}; 2435 uint16 fversion, cversion; 2436 int fsize, csize, cumul_delta_size = 0; 2437 2438 /* Incremental size for BCM_FIELD_WB_VERSION_1_6 */ 2439 delta_size[0] = 16 * 1024; 2440 /* Incremental size for BCM_FIELD_WB_VERSION_1_8 */ 2441 delta_size[1] = 128 * 1024; 2442 /* Incremental size for BCM_FIELD_WB_VERSION_1_15 */ 2443 delta_size[2] = 135 * 1024; 2444 /* Incremental size for BCM_FIELD_WB_VERSION_1_17 */ 2445 delta_size[3] = 144 * 1024; 2446 /* Incremental size for BCM_FIELD_WB_VERSION_1_18 */ 2447 delta_size[4] = 21 * 1024; 2448 /* Incremental size for BCM_FIELD_WB_VERSION_1_19 */ 2449 delta_size[5] = 264 * 1024; 2450 /* Incremental size for BCM_FIELD_WB_VERSION_1_20 */ 2451 delta_size[6] = 48 * 1024; 2452 /* Incremental size for action bcmFieldActionFabricQueue 2453 * adding for BCM_FIELD_WB_VERSION_1_20 2454 */ 2455 delta_size[6] += (16 * 1024 * 4); 2456 /* Incremental size for BCM_FIELD_WB_VERSION_1_21 */ 2457 delta_size[7] = (512 * _SHR_PBMP_WORD_MAX * 4) + (16 * 1024 * 12); 2458 /* Incremental size for BCM_FIELD_WB_VERSION_1_23 */ 2459 delta_size[8] = (128 * 4); 2460 /* Incremental size for BCM_FIELD_WB_VERSION_1_26 */ 2461 delta_size[9] = (_FP_MAX_NUM_PIPES 2462 + (_FP_MAX_NUM_PIPES * 8)); 2463 2464 fversion = former_version; 2465 cversion = current_version; 2466 fsize = former_size; 2467 csize = current_size; 2468 2469 /* This logic only handle upgrade warmboot case, don't consider downgrade case */ 2470 if (fversion < BCM_FIELD_WB_VERSION_1_5) { 2471 /* skip too old version */ 2472 return TRUE; 2473 } 2474 2475 if ((fversion < BCM_FIELD_WB_VERSION_1_6) 2476 && (cversion >= BCM_FIELD_WB_VERSION_1_6)) { 2477 cumul_delta_size += delta_size[0]; 2478 } 2479 2480 if ((fversion < BCM_FIELD_WB_VERSION_1_8) 2481 && (cversion >= BCM_FIELD_WB_VERSION_1_8)) { 2482 cumul_delta_size += delta_size[1]; 2483 } 2484 2485 if ((fversion < BCM_FIELD_WB_VERSION_1_15) 2486 && (cversion >= BCM_FIELD_WB_VERSION_1_15)) { 2487 cumul_delta_size += delta_size[2]; 2488 } 2489 2490 if ((fversion < BCM_FIELD_WB_VERSION_1_17) 2491 && (cversion >= BCM_FIELD_WB_VERSION_1_17)) { 2492 cumul_delta_size += delta_size[3]; 2493 } 2494 2495 if ((fversion < BCM_FIELD_WB_VERSION_1_18) 2496 && (cversion >= BCM_FIELD_WB_VERSION_1_18)) { 2497 cumul_delta_size += delta_size[4]; 2498 } 2499 2500 if ((fversion < BCM_FIELD_WB_VERSION_1_19) 2501 && (cversion >= BCM_FIELD_WB_VERSION_1_19)) { 2502 cumul_delta_size += delta_size[5]; 2503 } 2504 2505 if ((fversion < BCM_FIELD_WB_VERSION_1_20) 2506 && (cversion >= BCM_FIELD_WB_VERSION_1_20)) { 2507 cumul_delta_size += delta_size[6]; 2508 } 2509 2510 if ((fversion < BCM_FIELD_WB_VERSION_1_21) 2511 && (cversion >= BCM_FIELD_WB_VERSION_1_21)) { 2512 cumul_delta_size += delta_size[7]; 2513 } 2514 2515 if ((fversion < BCM_FIELD_WB_VERSION_1_23) 2516 && (cversion >= BCM_FIELD_WB_VERSION_1_23)) { 2517 cumul_delta_size += delta_size[8]; 2518 } 2519 2520 if ((fversion < BCM_FIELD_WB_VERSION_1_26) 2521 && (cversion >= BCM_FIELD_WB_VERSION_1_26)) { 2522 cumul_delta_size += delta_size[9]; 2523 } 2524 2525 if ((fversion < cversion) && 2526 ((csize - fsize) != (cumul_delta_size))) { 2527 return FALSE; 2528 } 2529 2530 return TRUE; 2531 } 2532 2533 /* Initialize field component scache pointers and scache sizes for 2534 multiple partitions */ 2535 int 2536 _field_scache_pointer_init(int unit, _field_control_t *fc) 2537 { 2538 int stable_size; 2539 int rv; 2540 uint32 alloc_get; 2541 soc_scache_handle_t handle; 2542 2543 if ((NULL == fc->scache_ptr[_FIELD_SCACHE_PART_0]) || 2544 (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_1])) { 2545 2546 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 2547 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 2548 _FIELD_SCACHE_PART_0); 2549 if ((stable_size > 0) && !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 2550 if (SOC_IS_TRX(unit)) { 2551 2552 fc->scache_size[_FIELD_SCACHE_PART_0] = 294 * 1024; 2553 /* Taking all average number into account 2554 * (Note:S-Slices , P- Ports and Q - Qualifiers) 2555 * IFP - 16S * 48P * 25Q 2556 * VFP and EFP - 16S * 25Q 2557 */ 2558 fc->scache_size[_FIELD_SCACHE_PART_1] = 20 * 1024; 2559 2560 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_15) { 2561 /* 2562 * OAM => 70 * 1024 ((7 bytes * 8K IFP entries) + (7 bytes * 2K EFP entries)) 2563 * Policer L1 => 20 * 1024 (4 bytes * 20 slices * 256 entries.) 2564 * No Param Actions => 40 * 1024 (4 bytes * 20 slices * 512 entries.) 2565 * Slice/Secondary Selectors => 5 * 1024 (2 bytes * 128 ports/groups * 20 Slices.) 2566 */ 2567 fc->scache_size[_FIELD_SCACHE_PART_0] += 135 * 1024; 2568 } 2569 2570 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_17) { 2571 2572 /* For WB sync and recovery of configured policer rates, 2573 * syncing only the delta value (diff btw configured and programmed 2574 * for ckbits_sec, ckbits_burst, pkbits_sec, pkbits_burst. 2575 * Taking 2 bytes for each of the delta, 2576 * Required size = Maximum Number of entries * 8 bytes 2577 * IFP := 16K * 8 = 128 KB 2578 * EFP := 2K * 8 = 16KB 2579 * Total size = 144 KB 2580 */ 2581 fc->scache_size[_FIELD_SCACHE_PART_0] += 144 * 1024; 2582 } 2583 2584 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_18) { 2585 /* Sync for SVP DVP type per entry part and 2586 * ingress, src entity selcode per group part 2587 */ 2588 fc->scache_size[_FIELD_SCACHE_PART_0] += (21 * 1024); 2589 } 2590 2591 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_19) { 2592 /* Sync for Additional 4bytes to sync 2593 * no parm actions sync enums per entry 2594 * and 12 bytes for PortPrioIntCosQNew 2595 * Actions CosQ Gport Values in IFP Stage 2596 */ 2597 fc->scache_size[_FIELD_SCACHE_PART_0] += (264 * 1024); 2598 } 2599 2600 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) { 2601 /* Allocate additional scache to sync IFP action ingress 2602 * and egress mirror gport value in no parm actions sync 2603 * enums per entry. IngressMirror and EgressMirror GPORT 2604 * can be assigned to single entry. Have to allocate (4+4) 2605 * bytes per entry. 2606 * IFP = (8 bytes * 512 entries * 12 slices). 2607 */ 2608 fc->scache_size[_FIELD_SCACHE_PART_0] += (48 * 1024); 2609 /* 2610 * Scache size is increased by (16 * 1024) * 4 bytes 2611 * (16K entries * 4 bytes) for all devices and 2612 * (8 * 1024) * 4 * 2 (8K entries * 4 bytes * 2 params 2613 * for KT2 devices to sync and recover the params of 2614 * fabricQueue action for all entries of Ingress. 2615 */ 2616 fc->scache_size[_FIELD_SCACHE_PART_0] += (16 * 4 * 1024); 2617 } 2618 2619 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) { 2620 /* 2621 * Group PBMP is synced with max_groups * size of the pbmp array 2622 * Sync MirrorIngress and MirrorEgress action parameters per entry 2623 * Worst case 16K * 12 bytes 2624 */ 2625 fc->scache_size[_FIELD_SCACHE_PART_0] += ((512 * _SHR_PBMP_WORD_MAX * 4) + (16 * 1024 * 12)); 2626 } 2627 2628 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_23) { 2629 /* 2630 * Scache size is increased by 128 * 4 bytes 2631 * to syncloopbacktype selcode per group part. 2632 * Worst case assuming 128 IFP groups in quad mode 2633 * (128 * 4) bytes. 2634 */ 2635 fc->scache_size[_FIELD_SCACHE_PART_0] += (128 * 4); 2636 } 2637 2638 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_26) { 2639 /* 2640 * Scache size is increased by _FP_MAX_NUM_PIPES * 1 bytes 2641 * to sync instance for all pipes in EFP/VFP slice map. 2642 * _FP_MAX_NUM_PIPES * 1 bytes * 8 groups to sync group 2643 * instance for all groups in EFP/VFP 2644 */ 2645 fc->scache_size[_FIELD_SCACHE_PART_0] += ((_FP_MAX_NUM_PIPES) 2646 + (_FP_MAX_NUM_PIPES * 8)); 2647 } 2648 2649 } else { 2650 /* Allocate a section of the Level 2 Warm Boot 2651 * global cache. 2652 * Assume 90% of the total stable size - just a heuristic 2653 */ 2654 fc->scache_size[_FIELD_SCACHE_PART_0] = (9 * stable_size) / 10; 2655 fc->scache_size[_FIELD_SCACHE_PART_1] = (1 * stable_size) / 100; 2656 } 2657 2658 /* Get the pointer for the Level 2 cache */ 2659 rv = soc_scache_ptr_get(unit, handle, 2660 &(fc->scache_ptr[_FIELD_SCACHE_PART_0]), 2661 &alloc_get); 2662 if (!SOC_WARM_BOOT(unit) && (SOC_E_NOT_FOUND == rv)) { 2663 /* Not yet allocated in Cold Boot */ 2664 SOC_IF_ERROR_RETURN 2665 (soc_scache_alloc(unit, handle, 2666 fc->scache_size[_FIELD_SCACHE_PART_0] + 2667 SOC_WB_SCACHE_CONTROL_SIZE)); 2668 rv = soc_scache_ptr_get(unit, handle, 2669 &(fc->scache_ptr[_FIELD_SCACHE_PART_0]), 2670 &alloc_get); 2671 } 2672 /* Fetch WB Recovered Version */ 2673 if (SOC_WARM_BOOT(unit)) { 2674 sal_memcpy(&(fc->wb_recovered_version), 2675 fc->scache_ptr[_FIELD_SCACHE_PART_0], 2676 sizeof(fc->wb_recovered_version)); 2677 } 2678 2679 2680 if (BCM_FAILURE(rv)) { 2681 return rv; 2682 } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_0] + 2683 SOC_WB_SCACHE_CONTROL_SIZE) { 2684 /* Expected size doesn't match retrieved size */ 2685 /* Scache size is increased by 16*1024 bytes 2686 * from version BCM_FIELD_WB_VERSION_1_6.The below check is 2687 * for upgrades from lower versions to BCM_FIELD_WB_VERSION_1_6 2688 * and above. 2689 * Scache size increased by 128 bytes from BCM_FIELD_WB_VERSION_1_8. 2690 * with respect to BCM_FIELD_WB_VERSION_1_6 2691 */ 2692 rv = _field_scache_version_size_check(unit, alloc_get, 2693 (fc->wb_recovered_version), 2694 fc->scache_size[_FIELD_SCACHE_PART_0] + 2695 SOC_WB_SCACHE_CONTROL_SIZE, 2696 (fc->wb_current_version)); 2697 if (rv != TRUE) { 2698 return BCM_E_INTERNAL; 2699 } 2700 } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_0]) { 2701 return BCM_E_MEMORY; 2702 } 2703 2704 if (SOC_WARM_BOOT(unit)) { 2705 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_3) { 2706 return BCM_E_NONE; 2707 } 2708 } 2709 2710 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 1); 2711 SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_FIELD, 1); 2712 2713 /* Get the pointer for the Level 2 cache */ 2714 rv = soc_scache_ptr_get(unit, handle, 2715 &(fc->scache_ptr[_FIELD_SCACHE_PART_1]), 2716 &alloc_get); 2717 if (!SOC_WARM_BOOT(unit) && (SOC_E_NOT_FOUND == rv)) { 2718 /* Not yet allocated in Cold Boot */ 2719 SOC_IF_ERROR_RETURN 2720 (soc_scache_alloc(unit, handle, 2721 fc->scache_size[_FIELD_SCACHE_PART_1] + 2722 SOC_WB_SCACHE_CONTROL_SIZE)); 2723 rv = soc_scache_ptr_get(unit, handle, 2724 &(fc->scache_ptr[_FIELD_SCACHE_PART_1]), 2725 &alloc_get); 2726 } 2727 2728 if (BCM_FAILURE(rv)) { 2729 return rv; 2730 } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_1] + 2731 SOC_WB_SCACHE_CONTROL_SIZE) { 2732 /* Expected size doesn't match retrieved size */ 2733 return BCM_E_INTERNAL; 2734 } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_1]) { 2735 return BCM_E_MEMORY; 2736 } 2737 2738 } 2739 } 2740 return BCM_E_NONE; 2741 } 2742 2743 /* 2744 * Function: 2745 * _field_slice_map_write 2746 * 2747 * Purpose: 2748 * Sync's slice status to scache for a stage (Expanded & master slice idx) 2749 * 2750 * Parameters: 2751 * unit - (IN) BCM device number 2752 * fc - (IN) FP control info. 2753 * stage_fc - (IN) FP stage control info. 2754 * 2755 * Returns: 2756 * BCM_E_XXX 2757 */ 2758 2759 int 2760 _field_slice_map_write(int unit, _field_control_t *fc, 2761 _field_stage_t *stage_fc) 2762 { 2763 uint8 slice_id; /* Slices iterator. */ 2764 _field_slice_t *fs; /* Slice pointer. */ 2765 uint8 *buf; /* Scache pointer. */ 2766 2767 if ((stage_fc == NULL) || (fc == NULL)) { 2768 return BCM_E_PARAM; 2769 } 2770 2771 /* No need to sync external stage */ 2772 if (stage_fc->stage_id >= _BCM_FIELD_STAGE_EXTERNAL) { 2773 return BCM_E_NONE; 2774 } 2775 2776 buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 2777 2778 if (((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) && soc_mem_is_valid(unit, FP_SLICE_MAPm)) 2779 || ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) && SOC_REG_IS_VALID(unit, EFP_SLICE_MAPr)) 2780 || ((stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) && SOC_REG_IS_VALID(unit, VFP_SLICE_MAPr))) { 2781 2782 for (slice_id = 0; slice_id < stage_fc->tcam_slices; slice_id++) { 2783 fs = stage_fc->slices[_FP_DEF_INST] + slice_id; 2784 2785 buf[fc->scache_pos] = (fs->prev != NULL) ? 1 : 0; 2786 /* Go to master slice */ 2787 while (fs->prev != NULL) { 2788 fs = fs->prev; 2789 } 2790 buf[fc->scache_pos] |= (fs->slice_number << 1); 2791 2792 LOG_DEBUG(BSL_LS_BCM_FP, 2793 (BSL_META_U(unit, 2794 "_field_slice_map_write: Writing slice %d master slice %d expanded %d @ byte %d...\n"), 2795 slice_id, (buf[fc->scache_pos] >> 1), (buf[fc->scache_pos] & 0x1), fc->scache_pos)); 2796 2797 fc->scache_pos++; 2798 fs = NULL; 2799 } 2800 } 2801 return BCM_E_NONE; 2802 } 2803 2804 /* 2805 * Function: 2806 * _field_mark_vmap_valid 2807 * 2808 * Purpose: 2809 * Marks a virtual map as valid 2810 * 2811 * Parameters: 2812 * unit - (IN) BCM device number 2813 * stage_fc - (IN) FP stage control info. 2814 * fg - (IN) Select code information filled into the group. 2815 * slice_number - (IN) Slices iterator. 2816 * 2817 * Returns: 2818 * BCM_E_XXX 2819 */ 2820 2821 STATIC int 2822 _field_mark_vmap_valid(int unit, _field_stage_t *stage_fc, 2823 _field_group_t *fg, int s ) 2824 { 2825 int idx, vmap_size, map_id; 2826 _field_virtual_map_t *vvmap; /* Currently used virtual map. */ 2827 _field_slice_t *slices; 2828 2829 BCM_IF_ERROR_RETURN(_bcm_field_virtual_map_size_get(unit, 2830 stage_fc, &vmap_size)); 2831 2832 for (map_id = 0; map_id < _FP_VMAP_CNT; map_id++) { 2833 slices = fg->slices; 2834 while (slices) { 2835 for (idx = 0; idx < vmap_size; idx++) { 2836 vvmap = stage_fc->vmap[fg->instance][map_id] + idx; 2837 2838 if (vvmap->vmap_key == slices[s].slice_number) { 2839 vvmap->valid = TRUE; 2840 vvmap->priority = fg->priority; 2841 /* update VMAP flags with group flags */ 2842 vvmap->flags = fg->flags; 2843 if (map_id == 0) { 2844 /* Update group VMAP */ 2845 fg->vmap_group[s] = vvmap->virtual_group; 2846 } 2847 } 2848 } 2849 slices = slices->next; 2850 } 2851 } 2852 2853 return BCM_E_NONE; 2854 } 2855 2856 /* 2857 * Function: 2858 * _field_group_slice_map_recovery 2859 * 2860 * Purpose: 2861 * Recovers group and stage virtual map 2862 * 2863 * Parameters: 2864 * unit - (IN) BCM device number 2865 * fc - (IN) FP control info. 2866 * stage_fc - (IN) FP stage control info. 2867 * 2868 * Returns: 2869 * BCM_E_XXX 2870 */ 2871 2872 int 2873 _field_group_slice_vmap_recovery(int unit, _field_control_t *fc, 2874 _field_stage_t *stage_fc) 2875 { 2876 _field_group_t *fg; 2877 int idx; 2878 2879 if ((stage_fc == NULL) || (fc == NULL)) { 2880 return BCM_E_PARAM; 2881 } 2882 2883 /* No need to sync external stage */ 2884 if (stage_fc->stage_id >= _BCM_FIELD_STAGE_EXTERNAL) { 2885 return BCM_E_NONE; 2886 } 2887 2888 if (((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) && soc_mem_is_valid(unit, FP_SLICE_MAPm)) 2889 || ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) && SOC_REG_IS_VALID(unit, EFP_SLICE_MAPr)) 2890 || ((stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) && SOC_REG_IS_VALID(unit, VFP_SLICE_MAPr))) { 2891 2892 for (fg = fc->groups; fg ; fg= fg->next) { 2893 /* Skip groups not belonging to stage */ 2894 if (fg->stage_id != stage_fc->stage_id) { 2895 continue; 2896 } 2897 2898 _field_mark_vmap_valid( unit, stage_fc, fg, 0 ); 2899 2900 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 2901 _field_mark_vmap_valid( unit, stage_fc, fg, 1 ); 2902 } 2903 2904 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 2905 _field_mark_vmap_valid( unit, stage_fc, fg, 1 ); 2906 _field_mark_vmap_valid( unit, stage_fc, fg, 2 ); 2907 } 2908 2909 if (fg->action_res_id != BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT) { 2910 for (idx = 1; idx < _FP_PAIR_MAX; idx++) { 2911 fg->vmap_group[idx] = fg->vmap_group[0]; 2912 } 2913 } else if (!(fc->l2warm)) { 2914 /* For L1 Warmboot 2915 * double wide mode groups check to see if slices have same virtual group 2916 * Single wide mode groups action res id will be as -1 */ 2917 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) 2918 || (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 2919 if (fg->vmap_group[0] == fg->vmap_group[1]) { 2920 fg->action_res_id = fg->vmap_group[0]; 2921 for (idx = 2; idx < _FP_PAIR_MAX; idx++) { 2922 fg->vmap_group[idx] = fg->vmap_group[0]; 2923 } 2924 } 2925 } 2926 } 2927 } 2928 } 2929 return BCM_E_NONE; 2930 } 2931 2932 #if defined BCM_KATANA2_SUPPORT || defined BCM_TRIDENT2_SUPPORT 2933 /* 2934 * Function: 2935 * _bcm_notify_qos_reinit_to_fp 2936 * Purpose: 2937 * Notfiy Field module when qos reinit is successful, 2938 * fp uses this notification to update bcmFieldActionDscpMapNew 2939 * action in entry 2940 * 2941 * Parameters: 2942 * unit - (IN) BCM device number 2943 * fc - (IN) FP control info. 2944 * stage_fc - (IN) FP stage control info. 2945 * 2946 * Returns: 2947 * BCM_E_XXX 2948 */ 2949 int _bcm_notify_qos_reinit_to_fp (int unit) { 2950 _field_dscp_map_new_eid_list_t *dscp_map_new_eid_node = NULL; 2951 _field_dscp_map_new_eid_list_t *temp = NULL; 2952 _field_entry_t *f_ent = NULL; 2953 _field_action_t *fa = NULL; 2954 uint32 hw_value = 0; 2955 uint32 param1 = 0; 2956 int param0 = 0; 2957 2958 dscp_map_new_eid_node = dscp_map_new_eid_list[unit]; 2959 2960 /* When DscpMapNew action is configured, after wb recovery, 2961 * param0 will hold the hw_value. Based on hw value, obtain the 2962 * mapId and update the entryId with the mapId as param0 */ 2963 while (dscp_map_new_eid_node != NULL) { 2964 BCM_IF_ERROR_RETURN(bcm_esw_field_action_get(unit, 2965 dscp_map_new_eid_node->eid,bcmFieldActionDscpMapNew, 2966 &hw_value, ¶m1)); 2967 BCM_IF_ERROR_RETURN(_bcm_tr2_qos_idx2id(unit, hw_value, 2968 _BCM_QOS_MAP_TYPE_DSCP_TABLE, ¶m0)); 2969 BCM_IF_ERROR_RETURN(_field_entry_get(unit, 2970 dscp_map_new_eid_node->eid, _FP_ENTRY_PRIMARY, &f_ent)); 2971 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 2972 if (fa->action == bcmFieldActionDscpMapNew) { 2973 fa->param[0] = param0; 2974 break; 2975 } 2976 } 2977 if (fa == NULL) { 2978 return BCM_E_INTERNAL; 2979 } 2980 2981 temp = dscp_map_new_eid_node; 2982 dscp_map_new_eid_node = dscp_map_new_eid_node->next; 2983 sal_free (temp); 2984 temp = NULL; 2985 } 2986 dscp_map_new_eid_list[unit] = NULL; 2987 2988 return BCM_E_NONE; 2989 } 2990 2991 #endif /* BCM_KATANA2_SUPPORT, BCM_TRIDENT2_SUPPORT*/ 2992 #endif /* BCM_WARM_BOOT_SUPPORT */ 2993 2994 #ifdef BCM_TRIDENT2_SUPPORT 2995 /* 2996 * Function: 2997 * bcm_field_efp_update_alternate_key_mask 2998 * Purpose: 2999 * As EFP has 2 types of keys, tcam.key and key_match_tcam.key 3000 * using efp_key_match_type, update the alternate key meaning 3001 * key which is not the current tcam installed key. 3002 * Parameters: 3003 * unit - (IN) Unit number. 3004 * f_ent - (IN) Pointer to field entry 3005 * input_entry_type - (IN) Specifies the key type which is 3006 * currently installed in tcam 3007 * Returns: 3008 * BCM_E_xxx 3009 * Notes: 3010 */ 3011 STATIC int 3012 bcm_field_efp_update_alternate_key_mask(int unit, 3013 _field_entry_t *f_ent_1, 3014 int8 input_entry_type_1) 3015 { 3016 int parts_count = 0; /* Number of entry parts. */ 3017 int part_idx,part_id; /* Entry parts iteration index. */ 3018 int qual_idx; /* Part qualifiers iteration index.*/ 3019 int rv; /* Operation return stauts. */ 3020 int idx; 3021 int idx_max; 3022 int index; 3023 uint32 width; 3024 _field_group_t *fg; /* FP group info structure. */ 3025 _bcm_field_qual_offset_t *q_offset; /* Qualifier offset structure */ 3026 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 3027 _bcm_field_group_qual_t *q_arr_1; /* Qualifiers array. */ 3028 _bcm_field_qual_offset_t *q_offset_1; /* Qualifier offset structure */ 3029 _bcm_field_qual_data_t q_data; 3030 _bcm_field_qual_data_t q_mask; 3031 int8 entry_type; /* entry type of alternate key/mask*/ 3032 _field_tcam_t *tcam; /* Tcam key/mask structure */ 3033 int dirty; /* to check if entry is dirty */ 3034 _field_entry_t *f_ent; /* to hold the entry structure */ 3035 int8 input_entry_type; /* entry type of entry */ 3036 3037 /* Search the entry by eid. */ 3038 rv = _field_entry_get(unit, f_ent_1->eid, _FP_ENTRY_PRIMARY, &f_ent); 3039 BCM_IF_ERROR_RETURN(rv); 3040 3041 fg = f_ent->group; 3042 3043 if (NULL == fg) { 3044 return (BCM_E_INTERNAL); 3045 } 3046 3047 /* Get number of entry parts we have to read. */ 3048 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 3049 fg->flags, &parts_count); 3050 BCM_IF_ERROR_RETURN(rv); 3051 3052 /* clear the data in alternate entry in all the f_ent parts*/ 3053 for (part_idx = 0; part_idx < parts_count; part_idx++) { 3054 /* when tcam.key is NULL, it might be because */ 3055 /* group is in double mode and we are dealing here with f_ent[1] */ 3056 /* in such cases f_ent[0] vaules can be NULL */ 3057 if((f_ent+part_idx)->tcam.key == NULL) { 3058 continue; 3059 } 3060 input_entry_type = (f_ent+part_idx)->efp_key_match_type; 3061 /* clear the data in alternate entry */ 3062 if (input_entry_type == _FP_ENTRY_TYPE_0) { 3063 tcam = &(f_ent+part_idx)->key_match_tcam; 3064 } else { 3065 tcam = &(f_ent+part_idx)->tcam; 3066 } 3067 sal_memset(tcam->key, 0, tcam->key_size); 3068 sal_memset(tcam->mask, 0, tcam->key_size); 3069 } 3070 /* Loop for updating the alternate key in f_ent */ 3071 for (part_idx = 0; part_idx < parts_count; part_idx++) 3072 { 3073 if((f_ent+part_idx)->tcam.key == NULL) { 3074 continue; 3075 } 3076 /* get the efp_key_match_type for f_ent */ 3077 input_entry_type = (f_ent+part_idx)->efp_key_match_type; 3078 /* check the entry dirty flag and keep the same value even */ 3079 /* after the alternate entry is updated */ 3080 dirty = 0; 3081 if ((f_ent+part_idx)->flags & _FP_ENTRY_DIRTY) { 3082 dirty = 1; 3083 } 3084 q_arr = &(fg->qual_arr[input_entry_type][part_idx]); 3085 for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) { 3086 idx_max = -1; 3087 q_offset = q_arr->offset_arr + qual_idx; 3088 3089 /* There is no value associated with zero 3090 * width qualifiers (Stage, Ip4 etc) 3091 */ 3092 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width); 3093 if (0 == width) { 3094 /* if the qualifier is Ip6 or Ip4 3095 * no need to update the key/mask 3096 */ 3097 continue; 3098 } 3099 3100 _FP_QUAL_DATA_CLEAR(q_data); 3101 _FP_QUAL_DATA_CLEAR(q_mask); 3102 3103 /* Read qualifier match value and mask. */ 3104 rv = _bcm_field_qual_value_get(unit, q_offset, f_ent+part_idx, 3105 q_data, q_mask); 3106 if (BCM_FAILURE(rv)) { 3107 return rv; 3108 } 3109 3110 /* Check if qualifier was installed. */ 3111 for (idx = 7; idx >= 0; idx--) { 3112 if (q_mask[idx] != 0) { 3113 idx_max = idx; 3114 break; 3115 } 3116 } 3117 3118 if (idx_max >= 0) { 3119 if (input_entry_type == 1) { 3120 entry_type = 0; 3121 } else { 3122 entry_type = 1; 3123 } 3124 for (part_id = 0; part_id < parts_count; part_id++) 3125 { 3126 if((f_ent+part_id)->tcam.key == NULL) { 3127 continue; 3128 } 3129 q_arr_1 = &(fg->qual_arr[entry_type][part_id]); 3130 for (index = 0; index < q_arr_1->size; index++) 3131 { 3132 if (q_arr->qid_arr[qual_idx] == 3133 q_arr_1->qid_arr[index]) 3134 { 3135 q_offset_1 = q_arr_1->offset_arr + index; 3136 3137 rv = _bcm_field_qual_value_set_by_entry_type(unit, 3138 q_offset_1, 3139 f_ent+part_id, 3140 q_data, q_mask, entry_type); 3141 BCM_IF_ERROR_RETURN(rv); 3142 3143 /* When qualifier is found dont go for next qualifier 3144 * in q_arr 3145 */ 3146 break; 3147 } 3148 } 3149 } 3150 } 3151 } 3152 /* set the entry dirty flag to the same value */ 3153 /* as before the alternate key update */ 3154 if (1 == dirty) { 3155 (f_ent+part_idx)->flags |= _FP_ENTRY_DIRTY; 3156 } else { 3157 (f_ent+part_idx)->flags &= ~_FP_ENTRY_DIRTY; 3158 } 3159 } 3160 return (BCM_E_NONE); 3161 } 3162 #endif /* BCM_TRIDENT2_SUPPORT*/ 3163 3164 /* Given en EID, find the group */ 3165 /* Used in various _qualify APIs */ 3166 int 3167 _bcm_field_entry_group_find(int unit, bcm_field_entry_t eid, 3168 _field_group_t **group_p) 3169 { 3170 int idx; /* Entry index */ 3171 _field_control_t *fc; /* Unit FP control structure. */ 3172 _field_group_t *fg; /* Group information. */ 3173 _field_entry_t *f_ent; /* Field entry info */ 3174 3175 if (NULL == group_p) { 3176 return (BCM_E_PARAM); 3177 } 3178 3179 /* Get unit FP control structure. */ 3180 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 3181 3182 /* Iterate over the groups linked-list */ 3183 fg = fc->groups; 3184 while (fg != NULL) { 3185 /* Now iterate over the entries in this group */ 3186 for (idx = 0; idx < fg->group_status.entry_count; idx++) { 3187 f_ent = fg->entry_arr[idx]; 3188 if (f_ent->eid == eid) { 3189 *group_p = fg; 3190 return BCM_E_NONE; 3191 } 3192 } 3193 fg = fg->next; 3194 } 3195 /* Group with eid not found. */ 3196 return (BCM_E_NOT_FOUND); 3197 3198 } 3199 3200 3201 /* 3202 * Function: 3203 * _bcm_field_action_dest_check 3204 * Purpose: 3205 * Verify destination prameters for fp actions 3206 * Parameters: 3207 * unit - (IN) BCM device number 3208 * fa - (IN) Field action structure. 3209 * Returns: 3210 * BCM_E_XXX 3211 */ 3212 int 3213 _bcm_field_action_dest_check(int unit, _field_action_t *fa) 3214 { 3215 int port_out; /* Calculated port value. */ 3216 int modid_out; /* Calculated module id. */ 3217 int rv; /* Operation return value. */ 3218 3219 /* Input parameters check. */ 3220 if (NULL == fa) { 3221 return (BCM_E_PARAM); 3222 } 3223 3224 /* No checks for Mirror/Mpls/Mim/Wlan gports */ 3225 if (BCM_GPORT_IS_SET(fa->param[1])) { 3226 return (BCM_E_NONE); 3227 } 3228 3229 /* Modport/Trunk were resolved in _field_params_api_to_hw_adapt call.*/ 3230 if (bcmFieldActionRedirectTrunk == fa->action) { 3231 return _bcm_trunk_id_validate(unit, fa->param[0]); 3232 } 3233 3234 /* Check destination module id / port. */ 3235 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 3236 fa->param[0], fa->param[1], 3237 &modid_out, &port_out); 3238 BCM_IF_ERROR_RETURN(rv); 3239 3240 if (!SOC_MODID_ADDRESSABLE(unit, modid_out)) { 3241 return (BCM_E_PARAM); 3242 } 3243 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 3244 return (BCM_E_PORT); 3245 } 3246 return (BCM_E_NONE); 3247 } 3248 3249 #ifdef INCLUDE_L3 3250 /* 3251 * Function: 3252 * _bcm_field_policy_set_l3_nh_resolve 3253 * Purpose: 3254 * Install l3 forwarding policy entry. 3255 * Parameters: 3256 * unit - (IN) BCM device number 3257 * mem - (IN) Policy table memory. 3258 * value - (IN) Egress object id or combined next hop information. 3259 * Returns: 3260 * BCM_E_XXX 3261 */ 3262 int 3263 _bcm_field_policy_set_l3_nh_resolve(int unit, int value, 3264 uint32 *flags, int *nh_ecmp_id) 3265 { 3266 int rv; /* Operation return value. */ 3267 3268 /* Check if egress forwarding mode is enabled. */ 3269 rv = bcm_xgs3_l3_egress_id_parse(unit, value, flags, nh_ecmp_id); 3270 if (rv == BCM_E_DISABLED) { 3271 LOG_DEBUG(BSL_LS_BCM_FP, 3272 (BSL_META_U(unit, 3273 "Error: L3 Egress Mode must be enabled.\n"))); 3274 } 3275 return (rv); 3276 } 3277 3278 /* 3279 * Function: 3280 * _bcm_field_l2_actions_nh_desroy 3281 * 3282 * Purpose: 3283 * Free l3 next hop and egress interface for 3284 * l2 fields update action. 3285 * Parameters: 3286 * unit - (IN) BCM device number. 3287 * nh_index - (IN) Next hop index. 3288 * egr_intf_set - (IN) Egress interface allocated. 3289 * Returns: 3290 * BCM_E_XXX 3291 */ 3292 STATIC int 3293 _bcm_field_l2_actions_nh_destroy(int unit, int nh_index, int egr_intf_set) 3294 { 3295 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry buffer. */ 3296 bcm_l3_egress_t egr; /* Egress forwarding object. */ 3297 uint32 intf; /* Egress L3 interface id. */ 3298 3299 /* Initialization. */ 3300 bcm_l3_egress_t_init(&egr); 3301 3302 /* Read next hop. */ 3303 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3304 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ANY, 3305 nh_index, hw_buf)); 3306 3307 /* clear egress interface information + free interface resource */ 3308 if ((1 == egr_intf_set) || 3309 (SOC_IS_TRIUMPH2(unit) || SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || 3310 SOC_IS_APOLLO(unit) || SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) || 3311 SOC_IS_GREYHOUND(unit) || SOC_IS_TRIUMPH3(unit) || 3312 SOC_IS_GREYHOUND2(unit))) { 3313 /* Get interface id. */ 3314 intf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, hw_buf, INTF_NUMf); 3315 /* Reset interface entry in hw. */ 3316 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3317 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 3318 intf, hw_buf)); 3319 /* Free interface id. */ 3320 BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_free(unit, intf)); 3321 } 3322 3323 /* clear egress next hop table information + free next hop index */ 3324 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3325 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm, 3326 SOC_BLOCK_ALL, nh_index, hw_buf)); 3327 3328 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_index)); 3329 return (BCM_E_NONE); 3330 } 3331 3332 /* 3333 * Function: 3334 * _bcm_field_l2_actions_nh_create 3335 * 3336 * Purpose: 3337 * Free l3 next hop and egress interface for 3338 * l2 fields update action. 3339 * Parameters: 3340 * unit - (IN) BCM device number. 3341 * da_fa - (IN) Update destination mac action. 3342 * sa_fa - (IN) Update source mac action. 3343 * vid_fa - (IN) Update outer vid action. 3344 * vn_new_fa - (IN) Change VN tag action. 3345 * vn_del_fa - (IN) Delete VN tag action. 3346 * e_new_fa - (IN) Change E tag action. 3347 * e_del_fa - (IN) Delete E tag action. 3348 * Returns: 3349 * BCM_E_XXX 3350 */ 3351 STATIC int 3352 _bcm_field_l2_actions_nh_create(int unit, _field_action_t *da_fa, 3353 _field_action_t *sa_fa, 3354 _field_action_t *vid_fa, 3355 _field_action_t *vn_new_fa, 3356 _field_action_t *vn_del_fa, 3357 _field_action_t *e_new_fa, 3358 _field_action_t *e_del_fa) 3359 { 3360 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry buffer. */ 3361 bcm_l3_egress_t egr; /* Egress forwarding object. */ 3362 _bcm_l3_intf_cfg_t intf; /* Egress L3 interface id. */ 3363 int nh_index; /* Next hop index. */ 3364 int nh_flags = 0; /* Next hop flags. */ 3365 int rv = BCM_E_NONE; /* Operation return status. */ 3366 3367 /*validation */ 3368 if (!BCM_XGS3_L3_INITIALIZED(unit)) { 3369 LOG_ERROR(BSL_LS_BCM_FP, 3370 (BSL_META_U(unit, 3371 "Error: L3 module is not initialized.\n"))); 3372 return (BCM_E_INIT); 3373 } 3374 /* Check l3 switching mode. */ 3375 if (!(BCM_XGS3_L3_EGRESS_MODE_ISSET(unit))) { 3376 LOG_ERROR(BSL_LS_BCM_FP, 3377 (BSL_META_U(unit, 3378 "Error: L3 Egress Mode must be enabled.\n"))); 3379 return (BCM_E_DISABLED); 3380 } 3381 /* Initialization. */ 3382 bcm_l3_egress_t_init(&egr); 3383 sal_memset(&intf, 0, sizeof(_bcm_l3_intf_cfg_t)); 3384 3385 /* Extract the policy info from the entry structure. */ 3386 if (NULL != da_fa) { 3387 SAL_MAC_ADDR_FROM_UINT32(egr.mac_addr, da_fa->param); 3388 } 3389 3390 if (NULL != sa_fa) { 3391 SAL_MAC_ADDR_FROM_UINT32(intf.l3i_mac_addr, sa_fa->param); 3392 } 3393 3394 if (NULL != vid_fa) { 3395 intf.l3i_vid = vid_fa->param[0]; 3396 } 3397 3398 if (SOC_IS_TRIUMPH2(unit) 3399 || SOC_IS_TD_TT(unit) 3400 || SOC_IS_KATANAX(unit) 3401 || SOC_IS_APOLLO(unit) 3402 || SOC_IS_ENDURO(unit) 3403 || SOC_IS_HURRICANEX(unit) 3404 || SOC_IS_TRIUMPH3(unit) 3405 || SOC_IS_GREYHOUND(unit) 3406 || SOC_IS_VALKYRIE2(unit) 3407 || SOC_IS_GREYHOUND2(unit) 3408 ) { 3409 /* Create egress l3 interface. */ 3410 BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_alloc(unit, 3411 &intf)); 3412 3413 /* Write egress interface to the hw. */ 3414 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3415 3416 /* Set mac address. */ 3417 soc_mem_mac_addr_set(unit, EGR_L3_INTFm, hw_buf, 3418 MAC_ADDRESSf, intf.l3i_mac_addr); 3419 3420 /* Set vlan id. */ 3421 soc_mem_field32_set(unit, EGR_L3_INTFm, hw_buf, VIDf, intf.l3i_vid); 3422 3423 /* Write interface configuration to the HW. */ 3424 rv = soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 3425 intf.l3i_index, hw_buf); 3426 if (BCM_FAILURE(rv)) { 3427 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 3428 return rv; 3429 } 3430 3431 /* Allocate next hop entry. */ 3432 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 3433 rv = bcm_xgs3_nh_add(unit, nh_flags, &egr, &nh_index); 3434 if (BCM_FAILURE(rv)) { 3435 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3436 (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 3437 intf.l3i_index, hw_buf); 3438 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 3439 return (rv); 3440 } 3441 3442 /* Write egress next hop entry. */ 3443 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3444 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 3445 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || 3446 SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 3447 SOC_IS_GREYHOUND2(unit)) { 3448 /* Set next hop entry type to IFP_ACTIONS. */ 3449 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3450 ENTRY_TYPEf, 6); 3451 3452 /* Set next hop mac address. */ 3453 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3454 IFP_ACTIONS__MAC_ADDRESSf, egr.mac_addr); 3455 3456 /* Set interface id. */ 3457 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3458 IFP_ACTIONS__INTF_NUMf, intf.l3i_index); 3459 3460 /* Set Disable flags. */ 3461 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3462 SOC_IS_KATANA2(unit) ? IFP_ACTIONS__L3_TTL_DISABLEf : 3463 IFP_ACTIONS__L3_UC_TTL_DISABLEf, 3464 0x1); 3465 3466 if (NULL == vid_fa) { 3467 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3468 SOC_IS_KATANA2(unit) ? IFP_ACTIONS__L3_VLAN_DISABLEf : 3469 IFP_ACTIONS__L3_UC_VLAN_DISABLEf, 0x1); 3470 } 3471 3472 if (NULL == sa_fa) { 3473 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3474 SOC_IS_KATANA2(unit) ? IFP_ACTIONS__L3_SA_DISABLEf : 3475 IFP_ACTIONS__L3_UC_SA_DISABLEf, 0x1); 3476 } 3477 3478 if (NULL == da_fa) { 3479 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3480 SOC_IS_KATANA2(unit) ? IFP_ACTIONS__L3_DA_DISABLEf : 3481 IFP_ACTIONS__L3_UC_DA_DISABLEf, 0x1); 3482 } 3483 3484 if (NULL != vn_new_fa) { 3485 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3486 IFP_ACTIONS__VNTAG_ACTIONf, 0x1); 3487 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3488 IFP_ACTIONS__VNTAGf, vn_new_fa->param[0]); 3489 } 3490 3491 if (NULL != vn_del_fa) { 3492 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3493 IFP_ACTIONS__VNTAG_ACTIONf, 0x3); 3494 } 3495 3496 if (NULL != e_new_fa) { 3497 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3498 IFP_ACTIONS__VNTAG_ACTIONf, 0x2); 3499 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3500 IFP_ACTIONS__VNTAGf, e_new_fa->param[0]); 3501 } 3502 3503 if (NULL != e_del_fa) { 3504 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3505 IFP_ACTIONS__VNTAG_ACTIONf, 0x3); 3506 } 3507 3508 } else 3509 #endif /* BCM_TRIDENT_SUPPORT||BCM_GREYHOUND_SUPPORT */ 3510 { 3511 /* Set next hop mac address. */ 3512 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3513 MAC_ADDRESSf, egr.mac_addr); 3514 3515 /* Set interface id. */ 3516 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3517 INTF_NUMf, intf.l3i_index); 3518 3519 /* Set Disable flags. */ 3520 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3521 L3__L3_UC_TTL_DISABLEf, 0x1); 3522 3523 if (NULL == vid_fa) { 3524 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3525 L3__L3_UC_VLAN_DISABLEf, 0x1); 3526 } 3527 3528 if (NULL == sa_fa) { 3529 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3530 L3__L3_UC_SA_DISABLEf, 0x1); 3531 } 3532 3533 if (NULL == da_fa) { 3534 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3535 L3__L3_UC_DA_DISABLEf, 0x1); 3536 } 3537 3538 if (SOC_IS_TRIUMPH3(unit)) { 3539 soc_mem_field32_set(unit, 3540 EGR_L3_NEXT_HOPm, 3541 hw_buf, 3542 ENTRY_TYPEf, 3543 6 3544 ); 3545 if (NULL != e_new_fa) { 3546 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3547 L2_ACTIONS__VNTAG_ACTIONf, 0x2); 3548 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3549 L2_ACTIONS__VNTAGf, e_new_fa->param[0]); 3550 } 3551 3552 if (NULL != e_del_fa) { 3553 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3554 L2_ACTIONS__VNTAG_ACTIONf, 0x3); 3555 } 3556 3557 } 3558 3559 } 3560 /* Insert next hop information. */ 3561 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ALL, 3562 nh_index, hw_buf); 3563 if (BCM_FAILURE(rv)) { 3564 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3565 (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 3566 intf.l3i_index, hw_buf); 3567 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 3568 return (rv); 3569 } 3570 } else { 3571 if (NULL != sa_fa) { 3572 /* Create egress l3 interface. */ 3573 BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_alloc(unit, 3574 &intf)); 3575 3576 /* Write egress interface to the hw. */ 3577 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3578 3579 /* Set mac address. */ 3580 soc_mem_mac_addr_set(unit, EGR_L3_INTFm, hw_buf, 3581 MAC_ADDRESSf, intf.l3i_mac_addr); 3582 3583 /* Set vlan id. */ 3584 soc_mem_field32_set(unit, EGR_L3_INTFm, hw_buf, VIDf, intf.l3i_vid); 3585 3586 /* Write interface configuration to the HW. */ 3587 rv = soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 3588 intf.l3i_index, hw_buf); 3589 if (BCM_FAILURE(rv)) { 3590 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 3591 return rv; 3592 } 3593 } 3594 3595 /* Allocate next hop entry. */ 3596 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 3597 rv = bcm_xgs3_nh_add(unit, nh_flags, &egr, &nh_index); 3598 if (BCM_FAILURE(rv)) { 3599 if (NULL != sa_fa) { 3600 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3601 (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 3602 intf.l3i_index, hw_buf); 3603 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 3604 } 3605 return (rv); 3606 } 3607 3608 /* Write egress next hop entry. */ 3609 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3610 3611 /* Set next hop mac address. */ 3612 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, hw_buf, MAC_ADDRESSf, 3613 egr.mac_addr); 3614 3615 /* Set Outer Vlan ID. */ 3616 if (NULL != vid_fa) { 3617 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3618 INTF_NUMf, intf.l3i_vid); 3619 } else if (NULL != sa_fa) { 3620 /* Set interface id. */ 3621 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3622 INTF_NUMf, intf.l3i_index); 3623 } else { 3624 /* Set interface id. */ 3625 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 3626 INTF_NUMf, 0); 3627 } 3628 3629 /* Insert next hop information. */ 3630 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ALL, 3631 nh_index, hw_buf); 3632 if (BCM_FAILURE(rv)) { 3633 if (NULL != sa_fa) { 3634 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 3635 (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 3636 intf.l3i_index, hw_buf); 3637 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 3638 } 3639 return (rv); 3640 } 3641 } 3642 3643 /* Preserve next hop index in the action structure. */ 3644 if (NULL != vid_fa) { 3645 vid_fa->hw_index = nh_index; 3646 } 3647 3648 if (NULL != sa_fa) { 3649 sa_fa->hw_index = nh_index; 3650 } 3651 3652 if (NULL != da_fa) { 3653 da_fa->hw_index = nh_index; 3654 } 3655 3656 if (NULL != vn_new_fa) { 3657 vn_new_fa->hw_index = nh_index; 3658 } 3659 3660 if (NULL != vn_del_fa) { 3661 vn_del_fa->hw_index = nh_index; 3662 } 3663 3664 if (NULL != e_new_fa) { 3665 e_new_fa->hw_index = nh_index; 3666 } 3667 3668 if (NULL != e_del_fa) { 3669 e_del_fa->hw_index = nh_index; 3670 } 3671 3672 return (BCM_E_NONE); 3673 } 3674 3675 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \ 3676 || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \ 3677 || defined (BCM_ENDURO_SUPPORT) 3678 3679 /* 3680 * Function: 3681 * _bcm_field_l3_egr_entry_type_set 3682 * 3683 * Purpose: 3684 * Modify EGR_L3_NEXT_HOP entry type. 3685 * 3686 * Parameters: 3687 * unit - (IN) BCM device number. 3688 * action - (IN) FP action. 3689 * nh_index - (IN) L3 Next Hop Index. 3690 * entry_type - (IN) Entry type to be set. 3691 * disable_val - (IN) Disable value to be set for L3 fields. 3692 * Returns: 3693 * BCM_E_XXX 3694 */ 3695 int 3696 _bcm_field_l3_egr_entry_type_set(int unit, bcm_field_action_t action, 3697 int nh_index, int entry_type, 3698 int disable_val) 3699 { 3700 int rv = BCM_E_NONE; /* Operation return status. */ 3701 soc_field_t l3_vlan_disable = INVALIDf; /* L3 VLAN disable field. */ 3702 soc_field_t l3_ttl_disable = INVALIDf; /* L3 TTL disable field. */ 3703 soc_field_t l3_sa_disable = INVALIDf; /* L3 SrcMac disable field. */ 3704 soc_field_t l3_da_disable = INVALIDf; /* L3 DstMac disable field. */ 3705 egr_l3_next_hop_entry_t egr_l3_next_hop_entry; /* Egress Next Hop table 3706 * entry info */ 3707 3708 if (SOC_IS_TRIUMPH3(unit)) { 3709 l3_vlan_disable = L2_ACTIONS__L3_UC_VLAN_DISABLEf ; 3710 l3_ttl_disable = L2_ACTIONS__L3_UC_TTL_DISABLEf; 3711 l3_sa_disable = L2_ACTIONS__L3_UC_SA_DISABLEf; 3712 l3_da_disable = L2_ACTIONS__L3_UC_DA_DISABLEf; 3713 } else if (SOC_IS_KATANA2(unit)) { 3714 l3_vlan_disable = IFP_ACTIONS__L3_VLAN_DISABLEf ; 3715 l3_ttl_disable = IFP_ACTIONS__L3_TTL_DISABLEf; 3716 l3_sa_disable = IFP_ACTIONS__L3_SA_DISABLEf; 3717 l3_da_disable = IFP_ACTIONS__L3_DA_DISABLEf; 3718 } else if (SOC_IS_TD_TT(unit) || SOC_IS_GREYHOUND(unit) 3719 || SOC_IS_KATANA(unit) || SOC_IS_HURRICANE3(unit) 3720 || SOC_IS_GREYHOUND2(unit)) { 3721 l3_vlan_disable = IFP_ACTIONS__L3_UC_VLAN_DISABLEf ; 3722 l3_ttl_disable = IFP_ACTIONS__L3_UC_TTL_DISABLEf; 3723 l3_sa_disable = IFP_ACTIONS__L3_UC_SA_DISABLEf; 3724 l3_da_disable = IFP_ACTIONS__L3_UC_DA_DISABLEf; 3725 } else { 3726 return BCM_E_CONFIG; 3727 } 3728 3729 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 3730 MEM_BLOCK_ANY, nh_index, 3731 &(egr_l3_next_hop_entry.entry_data)); 3732 if (BCM_FAILURE(rv)) { 3733 return (rv); 3734 } 3735 3736 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, 3737 ENTRY_TYPEf)) { 3738 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 3739 &(egr_l3_next_hop_entry.entry_data), 3740 ENTRY_TYPEf, entry_type); 3741 } else { 3742 return BCM_E_CONFIG; 3743 } 3744 3745 if (action == bcmFieldActionL3ChangeMacDa) { 3746 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 3747 &(egr_l3_next_hop_entry.entry_data), 3748 l3_vlan_disable, disable_val); 3749 } else { 3750 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 3751 &(egr_l3_next_hop_entry.entry_data), 3752 l3_da_disable, disable_val); 3753 } 3754 3755 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 3756 &(egr_l3_next_hop_entry.entry_data), 3757 l3_sa_disable, disable_val); 3758 3759 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 3760 &(egr_l3_next_hop_entry.entry_data), 3761 l3_ttl_disable, disable_val); 3762 3763 soc_mem_lock(unit, EGR_L3_NEXT_HOPm); 3764 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 3765 nh_index, 3766 &(egr_l3_next_hop_entry.entry_data)); 3767 if (BCM_FAILURE(rv)) { 3768 soc_mem_unlock(unit, EGR_L3_NEXT_HOPm); 3769 return (rv); 3770 } 3771 3772 soc_mem_unlock(unit, EGR_L3_NEXT_HOPm); 3773 return (BCM_E_NONE); 3774 } 3775 3776 /* 3777 * Function: 3778 * _bcm_field_l3_egress_actions_set 3779 * 3780 * Purpose: 3781 * Modify EGR_L3_NEXT_HOP entry type to IFP_ACTIONS (6) for FP Actions. 3782 * 3783 * Parameters: 3784 * unit - (IN) BCM device number. 3785 * f_ent - (IN) Field entry descriptor. 3786 * Returns: 3787 * BCM_E_XXX 3788 */ 3789 int 3790 _bcm_field_l3_egress_actions_set(int unit, _field_entry_t *f_ent) 3791 { 3792 _field_action_t *fa; /* Field action descriptor. */ 3793 int nh_index = 0; /* Next hop index. */ 3794 uint32 ref_count = 0; /* L3 Reference count */ 3795 3796 /* Input parameters check. */ 3797 if (NULL == f_ent) { 3798 return (BCM_E_PARAM); 3799 } 3800 3801 if (_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) { 3802 return (BCM_E_NONE); 3803 } 3804 3805 /* The following chips do not support entry type IFP_ACTIONS (6) */ 3806 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE2(unit)) { 3807 return (BCM_E_NONE); 3808 } 3809 3810 /* Extract the policy info from the entry structure. */ 3811 for (fa = f_ent->actions; 3812 ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); 3813 fa = fa->next) { 3814 switch (fa->action) { 3815 case bcmFieldActionL3ChangeVlan: 3816 break; 3817 3818 case bcmFieldActionL3ChangeMacDa: 3819 break; 3820 3821 default: 3822 continue; 3823 } 3824 3825 /* Validate the Egress object Id */ 3826 /* Make sure the object is only for Next hop entries 3827 and not for Multipath and DVP*/ 3828 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, fa->param[0])) { 3829 nh_index = fa->param[0] - BCM_XGS3_EGRESS_IDX_MIN(unit); 3830 } else { 3831 return BCM_E_PARAM; 3832 } 3833 3834 ref_count = BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, next_hop), 3835 nh_index); 3836 3837 /* Check to handle Entry reinstall */ 3838 if ((_FP_INVALID_INDEX == fa->hw_index) || 3839 (nh_index != fa->hw_index)) { 3840 3841 /* Make sure entry is valid and not inuse by other modules */ 3842 if (ref_count < 1) { 3843 return BCM_E_NOT_FOUND; 3844 } else if (ref_count > 1) { 3845 return BCM_E_BUSY; 3846 } 3847 3848 /* Configure ENTRY_TYPE to 6 (IFP_ACTIONS) */ 3849 BCM_IF_ERROR_RETURN(_bcm_field_l3_egr_entry_type_set(unit, fa->action, 3850 nh_index, 6, 1)); 3851 3852 if (_FP_INVALID_INDEX != fa->hw_index) { 3853 fa->old_index = fa->hw_index; 3854 } 3855 /* Preserve next hop index in the action structure. */ 3856 fa->hw_index = nh_index; 3857 } 3858 } 3859 return (BCM_E_NONE); 3860 } 3861 3862 /* 3863 * Function: 3864 * _bcm_field_l3_egress_actions_reset 3865 * 3866 * Purpose: 3867 * Reset EGR_L3_NEXT_HOP entry type to 0 for FP actions 3868 * 3869 * Parameters: 3870 * unit - (IN) BCM device number. 3871 * f_ent - (IN) Field entry descriptor. 3872 * flags - (IN) Flags. 3873 * Returns: 3874 * BCM_E_XXX 3875 */ 3876 int 3877 _bcm_field_l3_egress_actions_reset(int unit, _field_entry_t *f_ent, int flags) 3878 { 3879 _field_action_t *fa; /* Field action descriptor. */ 3880 int nh_index = 0; /* Next hop id. */ 3881 3882 /* Input parameters check. */ 3883 if (NULL == f_ent) { 3884 return (BCM_E_PARAM); 3885 } 3886 3887 if (_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) { 3888 return (BCM_E_NONE); 3889 } 3890 3891 /* The following chips do not support entry type IFP_ACTIONS (6) */ 3892 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE2(unit)) { 3893 return (BCM_E_NONE); 3894 } 3895 3896 /* Extract the policy info from the entry structure. */ 3897 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 3898 switch (fa->action) { 3899 case bcmFieldActionL3ChangeVlan: 3900 break; 3901 3902 case bcmFieldActionL3ChangeMacDa: 3903 break; 3904 3905 default: 3906 continue; 3907 } 3908 if ((flags & _FP_ACTION_RESOURCE_FREE) && 3909 (_FP_INVALID_INDEX != fa->hw_index)) { 3910 nh_index = fa->hw_index; 3911 fa->hw_index = _FP_INVALID_INDEX; 3912 BCM_IF_ERROR_RETURN 3913 (_bcm_field_l3_egr_entry_type_set(unit, fa->action, 3914 nh_index, 0, 0)); 3915 } 3916 3917 if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) && 3918 (_FP_INVALID_INDEX != fa->old_index)) { 3919 nh_index = fa->old_index; 3920 fa->old_index = _FP_INVALID_INDEX; 3921 BCM_IF_ERROR_RETURN 3922 (_bcm_field_l3_egr_entry_type_set(unit, fa->action, 3923 nh_index, 0, 0)); 3924 } 3925 } 3926 return (BCM_E_NONE); 3927 } 3928 3929 #endif /* (BCM_KATANA_SUPPORT) || (BCM_TRIDENT_SUPPORT) || 3930 (BCM_TRIUMPH3_SUPPORT) || (BCM_GREYHOUND_SUPPORT) */ 3931 3932 3933 /* 3934 * Function: 3935 * _bcm_field_l2_actions_hw_alloc 3936 * 3937 * Purpose: 3938 * Allocate l3 next hop and egress interface for 3939 * l2 fields update action. 3940 * Parameters: 3941 * unit - (IN) BCM device number. 3942 * f_ent - (IN) Field entry descriptor. 3943 * Returns: 3944 * BCM_E_XXX 3945 */ 3946 STATIC int 3947 _bcm_field_l2_actions_hw_alloc(int unit, _field_entry_t *f_ent) 3948 { 3949 _field_action_t *vid_fa; /* Update outer vid action. */ 3950 _field_action_t *sa_fa; /* Update source mac action. */ 3951 _field_action_t *da_fa; /* Update destination mac action.*/ 3952 _field_action_t *vn_new_fa; /* Change VN tag. */ 3953 _field_action_t *vn_del_fa; /* Delete VN tag action. */ 3954 _field_action_t *e_new_fa; /* Change E tag. */ 3955 _field_action_t *e_del_fa; /* Delete E tag action. */ 3956 _field_action_t *fa; /* Field action descriptor. */ 3957 3958 /* 3959 * Applicable to stage ingress on devices which support 3960 * soc_feature_field_action_l2_change feature. 3961 */ 3962 if ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) && 3963 (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id)) { 3964 return (BCM_E_NONE); 3965 } 3966 3967 /* Initialization. */ 3968 sa_fa = da_fa = vid_fa = vn_new_fa = vn_del_fa = e_new_fa = e_del_fa = NULL; 3969 3970 /* Extract the policy info from the entry structure. */ 3971 for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) { 3972 switch (fa->action) { 3973 case bcmFieldActionSrcMacNew: 3974 if (_FP_INVALID_INDEX != fa->hw_index) { 3975 fa->old_index = fa->hw_index; 3976 } 3977 sa_fa = fa; 3978 break; 3979 case bcmFieldActionDstMacNew: 3980 if (_FP_INVALID_INDEX != fa->hw_index) { 3981 fa->old_index = fa->hw_index; 3982 } 3983 da_fa = fa; 3984 break; 3985 case bcmFieldActionOuterVlanNew: 3986 if (_FP_INVALID_INDEX != fa->hw_index) { 3987 fa->old_index = fa->hw_index; 3988 } 3989 vid_fa = fa; 3990 break; 3991 case bcmFieldActionVnTagNew: 3992 if (_FP_INVALID_INDEX != fa->hw_index) { 3993 fa->old_index = fa->hw_index; 3994 } 3995 vn_new_fa = fa; 3996 break; 3997 case bcmFieldActionVnTagDelete: 3998 if (_FP_INVALID_INDEX != fa->hw_index) { 3999 fa->old_index = fa->hw_index; 4000 } 4001 vn_del_fa = fa; 4002 break; 4003 case bcmFieldActionEtagNew: 4004 if (_FP_INVALID_INDEX != fa->hw_index) { 4005 fa->old_index = fa->hw_index; 4006 } 4007 e_new_fa = fa; 4008 break; 4009 case bcmFieldActionEtagDelete: 4010 if (_FP_INVALID_INDEX != fa->hw_index) { 4011 fa->old_index = fa->hw_index; 4012 } 4013 e_del_fa = fa; 4014 break; 4015 default: 4016 continue; 4017 } 4018 } 4019 4020 /* Create nh entry. */ 4021 if ((NULL != vid_fa) || (NULL != da_fa) || (NULL != sa_fa) || 4022 (NULL != vn_new_fa) || (NULL != vn_del_fa) || 4023 (NULL != e_new_fa) || (NULL != e_del_fa)) { 4024 BCM_IF_ERROR_RETURN(_bcm_field_l2_actions_nh_create(unit, da_fa, sa_fa, 4025 vid_fa, vn_new_fa, vn_del_fa, e_new_fa, e_del_fa)); 4026 } 4027 return (BCM_E_NONE); 4028 } 4029 4030 /* 4031 * Function: 4032 * _bcm_field_l2_actions_hw_free 4033 * 4034 * Purpose: 4035 * Free l3 next hop and egress interface for 4036 * l2 fields update action. 4037 * Parameters: 4038 * unit - (IN) BCM device number. 4039 * f_ent - (IN) Field entry descriptor. 4040 * flags - (IN) Free flags (old/new/both). 4041 * Returns: 4042 * BCM_E_XXX 4043 */ 4044 STATIC int 4045 _bcm_field_l2_actions_hw_free(int unit, _field_entry_t *f_ent, 4046 uint32 flags) 4047 { 4048 _field_action_t *fa; /* Field action descriptor. */ 4049 int nh_index; /* Next hop index. */ 4050 int old_nh_index; /* Old next hop index. */ 4051 int egr_intf_set = 0; /* Egress interface allocated */ 4052 int rv = BCM_E_NONE; /* Operation return status. */ 4053 4054 /* Applicable to stage ingress on TRX and FB family of devices only. */ 4055 if ((0 == SOC_IS_TRX(unit)) 4056 && (0 == SOC_IS_FB(unit)) 4057 && (0 == SOC_IS_BRADLEY(unit))) { 4058 return (BCM_E_NONE); 4059 } 4060 4061 if ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) && 4062 (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id)) { 4063 return BCM_E_NONE; 4064 } 4065 4066 /* Initialization. */ 4067 nh_index = old_nh_index = _FP_INVALID_INDEX; 4068 4069 /* Extract the policy info from the entry structure. */ 4070 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 4071 switch (fa->action) { 4072 case bcmFieldActionSrcMacNew: 4073 egr_intf_set = TRUE; 4074 /* passthru */ 4075 /* coverity[MISSING_BREAK: FALSE] */ 4076 case bcmFieldActionOuterVlanNew: 4077 case bcmFieldActionDstMacNew: 4078 case bcmFieldActionVnTagNew: 4079 case bcmFieldActionVnTagDelete: 4080 case bcmFieldActionEtagNew: 4081 case bcmFieldActionEtagDelete: 4082 if ((flags & _FP_ACTION_RESOURCE_FREE) && 4083 (_FP_INVALID_INDEX != fa->hw_index)) { 4084 nh_index = fa->hw_index; 4085 fa->hw_index = _FP_INVALID_INDEX; 4086 } 4087 if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) && 4088 (_FP_INVALID_INDEX != fa->old_index)) { 4089 old_nh_index = fa->old_index; 4090 fa->old_index = _FP_INVALID_INDEX; 4091 } 4092 break; 4093 default: 4094 break; 4095 } 4096 } 4097 4098 /* Destroy old next hop if any. */ 4099 if (_FP_INVALID_INDEX != old_nh_index) { 4100 rv = _bcm_field_l2_actions_nh_destroy(unit, old_nh_index, egr_intf_set); 4101 BCM_IF_ERROR_RETURN(rv); 4102 } 4103 if (_FP_INVALID_INDEX != nh_index) { 4104 rv = _bcm_field_l2_actions_nh_destroy(unit, nh_index, egr_intf_set); 4105 BCM_IF_ERROR_RETURN(rv); 4106 } 4107 return (BCM_E_NONE); 4108 } 4109 #endif /* INCLUDE_L3 */ 4110 4111 /* 4112 * Function: 4113 * _field_dest_type_clear 4114 * Purpose: 4115 * Clear Destination Type value in qualifier data. 4116 * Parameters: 4117 * unit - (IN) BCM device number. 4118 * entry - (IN) entry identifier. 4119 * qual - (IN) field qualifier. 4120 * data - (IN) qualifier data. 4121 * mask - (IN) qualifier mask. 4122 * Returns: 4123 * BCM_E_XXX 4124 */ 4125 int 4126 _field_dest_type_clear(int unit, bcm_field_entry_t entry, 4127 bcm_field_qualify_t qual, uint32 *data, uint32 *mask) 4128 { 4129 #ifdef BCM_TRIUMPH2_SUPPORT 4130 _field_group_t *fg; /* Field group structure */ 4131 int entry_width; /* Forward Entity Select status */ 4132 int dst_fwd_entity_status; /* dst_fwd_entity_sel selector status */ 4133 4134 /* Check if this device supports per-slice control fields */ 4135 if (0 == soc_feature(unit, soc_feature_field_slice_dest_entity_select)) { 4136 return (BCM_E_NONE); 4137 } 4138 4139 BCM_IF_ERROR_RETURN(_bcm_field_entry_group_find(unit, entry, &fg)); 4140 4141 #if defined(BCM_TOMAHAWK_SUPPORT) 4142 /* Return for multi-pipe supported devices */ 4143 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 4144 _BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 4145 return (BCM_E_NONE); 4146 } 4147 #endif /* BCM_TOMAHAWK_SUPPORT */ 4148 4149 /* 4150 * Check if dst_fwd_entity_sel secondary selector is used. 4151 */ 4152 for (entry_width = 0; entry_width < _FP_MAX_ENTRY_WIDTH; entry_width++) { 4153 switch (fg->sel_codes[entry_width].dst_fwd_entity_sel) { 4154 case _bcmFieldFwdEntityGlp: 4155 if (qual == bcmFieldQualifyDstPort 4156 || qual == bcmFieldQualifyDstTrunk) { 4157 dst_fwd_entity_status = TRUE; 4158 } else { 4159 dst_fwd_entity_status = FALSE; 4160 } 4161 break; 4162 case _bcmFieldFwdEntityMplsGport: 4163 if ((qual == bcmFieldQualifyDstMplsGport) || 4164 (qual == bcmFieldQualifyDstMplsGports)) { 4165 dst_fwd_entity_status = TRUE; 4166 } else { 4167 dst_fwd_entity_status = FALSE; 4168 } 4169 break; 4170 case _bcmFieldFwdEntityNivGport: 4171 if ((qual == bcmFieldQualifyDstNivGport) || 4172 (qual == bcmFieldQualifyDstNivGports)) { 4173 dst_fwd_entity_status = TRUE; 4174 } else { 4175 dst_fwd_entity_status = FALSE; 4176 } 4177 break; 4178 case _bcmFieldFwdEntityMimGport: 4179 if ((qual == bcmFieldQualifyDstMimGport) || 4180 (qual == bcmFieldQualifyDstMimGports)) { 4181 dst_fwd_entity_status = TRUE; 4182 } else { 4183 dst_fwd_entity_status = FALSE; 4184 } 4185 break; 4186 case _bcmFieldFwdEntityWlanGport: 4187 if ((qual == bcmFieldQualifyDstWlanGport) || 4188 (qual == bcmFieldQualifyDstWlanGports)) { 4189 dst_fwd_entity_status = TRUE; 4190 } else { 4191 dst_fwd_entity_status = FALSE; 4192 } 4193 break; 4194 case _bcmFieldFwdEntityVxlanGport: 4195 if ((qual == bcmFieldQualifyDstVxlanGport) || 4196 (qual == bcmFieldQualifyDstVxlanGports)) { 4197 dst_fwd_entity_status = TRUE; 4198 } else { 4199 dst_fwd_entity_status = FALSE; 4200 } 4201 break; 4202 case _bcmFieldFwdEntityVlanGport: 4203 if ((qual == bcmFieldQualifyDstVlanGport) || 4204 (qual == bcmFieldQualifyDstVlanGports)) { 4205 dst_fwd_entity_status = TRUE; 4206 } else { 4207 dst_fwd_entity_status = FALSE; 4208 } 4209 break; 4210 case _bcmFieldFwdEntityCommonGport: 4211 if ((qual == bcmFieldQualifyDstGport) || 4212 (qual == bcmFieldQualifyDstGports)) { 4213 dst_fwd_entity_status = TRUE; 4214 } else { 4215 dst_fwd_entity_status = FALSE; 4216 } 4217 break; 4218 case _bcmFieldFwdEntityL3Egress: 4219 dst_fwd_entity_status 4220 = (qual == bcmFieldQualifyDstL3Egress) 4221 ? TRUE : (qual == bcmFieldQualifyDstL3EgressNextHops) 4222 ? TRUE : FALSE; 4223 break; 4224 case _bcmFieldFwdEntityMulticastGroup: 4225 if ((qual == bcmFieldQualifyDstMulticastGroup) || 4226 (qual == bcmFieldQualifyDstMulticastGroups)) { 4227 dst_fwd_entity_status = TRUE; 4228 } else { 4229 dst_fwd_entity_status = FALSE; 4230 } 4231 break; 4232 case _bcmFieldFwdEntityMultipath: 4233 dst_fwd_entity_status = 4234 (qual == bcmFieldQualifyDstMultipath) ? TRUE: FALSE; 4235 break; 4236 default: 4237 dst_fwd_entity_status = FALSE; 4238 } 4239 if (TRUE == dst_fwd_entity_status) { 4240 break; 4241 } 4242 } 4243 4244 if (FALSE == dst_fwd_entity_status) { 4245 return BCM_E_NONE; 4246 } else { 4247 _FIELD_D_TYPE_RESET(*data); 4248 _FIELD_D_TYPE_RESET(*mask); 4249 } 4250 #endif /* !BCM_TRIUMPH2_SUPPORT */ 4251 return BCM_E_NONE; 4252 } 4253 4254 /* 4255 * Function: 4256 * _field_dest_type_qualify 4257 * Purpose: 4258 * Set Destination Type value in qualifier data. 4259 * Parameters: 4260 * unit - (IN) BCM device number. 4261 * entry - (IN) entry identifier. 4262 * qual - (IN) field qualifier. 4263 * data - (IN) qualifier data. 4264 * mask - (IN) qualifier mask. 4265 * flags - (IN) Flags to set d_type. 4266 * Returns: 4267 * BCM_E_XXX 4268 */ 4269 int 4270 _field_dest_type_qualify(int unit, bcm_field_entry_t entry, 4271 bcm_field_qualify_t qual, uint32 *data, uint32 *mask, 4272 uint32 flags) 4273 { 4274 #ifdef BCM_TRIUMPH2_SUPPORT 4275 _field_group_t *fg; /* Field group structure */ 4276 int entry_width; /* Forward Entity Select status */ 4277 int dst_fwd_entity_status; /* dst_fwd_entity_sel selector status */ 4278 4279 /* Check if this device supports per-slice control fields */ 4280 if (0 == soc_feature(unit, soc_feature_field_slice_dest_entity_select)) { 4281 return (BCM_E_NONE); 4282 } 4283 4284 BCM_IF_ERROR_RETURN(_bcm_field_entry_group_find(unit, entry, &fg)); 4285 4286 #if defined(BCM_TOMAHAWK_SUPPORT) 4287 /* Return for multi-pipe supported devices */ 4288 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 4289 _BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 4290 return (BCM_E_NONE); 4291 } 4292 #endif /* BCM_TOMAHAWK_SUPPORT */ 4293 4294 /* 4295 * Check if dst_fwd_entity_sel secondary selector is used. 4296 */ 4297 for (entry_width = 0; entry_width < _FP_MAX_ENTRY_WIDTH; entry_width++) { 4298 switch (fg->sel_codes[entry_width].dst_fwd_entity_sel) { 4299 case _bcmFieldFwdEntityGlp: 4300 if (qual == bcmFieldQualifyDstPort 4301 || qual == bcmFieldQualifyDstTrunk) { 4302 dst_fwd_entity_status = TRUE; 4303 } else { 4304 dst_fwd_entity_status = FALSE; 4305 } 4306 break; 4307 case _bcmFieldFwdEntityMplsGport: 4308 if ((qual == bcmFieldQualifyDstMplsGport) || 4309 (qual == bcmFieldQualifyDstMplsGports)) { 4310 dst_fwd_entity_status = TRUE; 4311 } else { 4312 dst_fwd_entity_status = FALSE; 4313 } 4314 break; 4315 case _bcmFieldFwdEntityNivGport: 4316 if ((qual == bcmFieldQualifyDstNivGport) || 4317 (qual == bcmFieldQualifyDstNivGports)) { 4318 dst_fwd_entity_status = TRUE; 4319 } else { 4320 dst_fwd_entity_status = FALSE; 4321 } 4322 break; 4323 case _bcmFieldFwdEntityMimGport: 4324 if ((qual == bcmFieldQualifyDstMimGport) || 4325 (qual == bcmFieldQualifyDstMimGports)) { 4326 dst_fwd_entity_status = TRUE; 4327 } else { 4328 dst_fwd_entity_status = FALSE; 4329 } 4330 break; 4331 case _bcmFieldFwdEntityWlanGport: 4332 if ((qual == bcmFieldQualifyDstWlanGport) || 4333 (qual == bcmFieldQualifyDstWlanGports)) { 4334 dst_fwd_entity_status = TRUE; 4335 } else { 4336 dst_fwd_entity_status = FALSE; 4337 } 4338 break; 4339 case _bcmFieldFwdEntityVxlanGport: 4340 if ((qual == bcmFieldQualifyDstVxlanGport) || 4341 (qual == bcmFieldQualifyDstVxlanGports)) { 4342 dst_fwd_entity_status = TRUE; 4343 } else { 4344 dst_fwd_entity_status = FALSE; 4345 } 4346 break; 4347 case _bcmFieldFwdEntityVlanGport: 4348 if ((qual == bcmFieldQualifyDstVlanGport) || 4349 (qual == bcmFieldQualifyDstVlanGports)) { 4350 dst_fwd_entity_status = TRUE; 4351 } else { 4352 dst_fwd_entity_status = FALSE; 4353 } 4354 break; 4355 case _bcmFieldFwdEntityCommonGport: 4356 if ((qual == bcmFieldQualifyDstGport) || 4357 (qual == bcmFieldQualifyDstGports)) { 4358 dst_fwd_entity_status = TRUE; 4359 } else { 4360 dst_fwd_entity_status = FALSE; 4361 } 4362 break; 4363 case _bcmFieldFwdEntityL3Egress: 4364 dst_fwd_entity_status 4365 = (qual == bcmFieldQualifyDstL3Egress) 4366 ? TRUE : (qual == bcmFieldQualifyDstL3EgressNextHops) 4367 ? TRUE : FALSE; 4368 break; 4369 case _bcmFieldFwdEntityMulticastGroup: 4370 if ((qual == bcmFieldQualifyDstMulticastGroup) || 4371 (qual == bcmFieldQualifyDstMulticastGroups)) { 4372 dst_fwd_entity_status = TRUE; 4373 } else { 4374 dst_fwd_entity_status = FALSE; 4375 } 4376 break; 4377 case _bcmFieldFwdEntityMultipath: 4378 dst_fwd_entity_status = 4379 (qual == bcmFieldQualifyDstMultipath) ? TRUE: FALSE; 4380 break; 4381 default: 4382 dst_fwd_entity_status = FALSE; 4383 } 4384 if (TRUE == dst_fwd_entity_status) { 4385 break; 4386 } 4387 } 4388 4389 if (FALSE == dst_fwd_entity_status) { 4390 return BCM_E_NONE; 4391 } else { 4392 switch (qual) { 4393 case bcmFieldQualifyDstMplsGport: 4394 case bcmFieldQualifyDstNivGport: 4395 case bcmFieldQualifyDstMimGport: 4396 case bcmFieldQualifyDstWlanGport: 4397 case bcmFieldQualifyDstVxlanGport: 4398 case bcmFieldQualifyDstVlanGport: 4399 case bcmFieldQualifyDstMplsGports: 4400 case bcmFieldQualifyDstNivGports: 4401 case bcmFieldQualifyDstMimGports: 4402 case bcmFieldQualifyDstWlanGports: 4403 case bcmFieldQualifyDstVxlanGports: 4404 case bcmFieldQualifyDstVlanGports: 4405 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeDvp); 4406 break; 4407 case bcmFieldQualifyDstL3Egress: 4408 case bcmFieldQualifyDstL3EgressNextHops: 4409 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeNhi); 4410 break; 4411 case bcmFieldQualifyDstMultipath: 4412 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeEcmp); 4413 break; 4414 case bcmFieldQualifyDstMulticastGroup: 4415 case bcmFieldQualifyDstMulticastGroups: 4416 if (flags & _bcmFieldDestTypeL3mc) { 4417 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeL3mc); 4418 } else if (flags & _bcmFieldDestTypeL2mc) { 4419 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeL2mc); 4420 } else { 4421 return BCM_E_INTERNAL; 4422 } 4423 break; 4424 case bcmFieldQualifyDstGport: 4425 case bcmFieldQualifyDstGports: 4426 if (flags & _bcmFieldDestTypeDglp) { 4427 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeDglp); 4428 } else if (flags & _bcmFieldDestTypeDvp) { 4429 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeDvp); 4430 } else { 4431 return BCM_E_INTERNAL; 4432 } 4433 break; 4434 default: 4435 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeDglp); 4436 } 4437 } 4438 4439 if ((bcmFieldQualifyDstL3EgressNextHops == qual) 4440 || (bcmFieldQualifyDstTrunk == qual) 4441 || (bcmFieldQualifyDstMulticastGroups == qual) 4442 || (bcmFieldQualifyDstPort == qual)) { 4443 _FIELD_D_TYPE_MASK_INSERT(*mask); 4444 } else if ((qual != bcmFieldQualifyDstGports) && 4445 (qual != bcmFieldQualifyDstWlanGports) && 4446 (qual != bcmFieldQualifyDstVlanGports) && 4447 (qual != bcmFieldQualifyDstVxlanGports) && 4448 (qual != bcmFieldQualifyDstMimGports) && 4449 (qual != bcmFieldQualifyDstNivGports) && 4450 (qual != bcmFieldQualifyDstMulticastGroups) && 4451 (qual != bcmFieldQualifyDstMplsGports)) { 4452 *mask = (BCM_FIELD_EXACT_MATCH_MASK); 4453 } 4454 #endif /* !BCM_TRIUMPH2_SUPPORT */ 4455 return BCM_E_NONE; 4456 } 4457 4458 /* 4459 * Function: 4460 * _bcm_field_qual_conf_t_init 4461 * Purpose: 4462 * Initialize qualifier configuration structure. 4463 * Parameters: 4464 * ptr - (OUT) Pointer to field qualifier configuration strucutre. 4465 * 4466 * Returns: 4467 * Void. 4468 */ 4469 void 4470 _bcm_field_qual_conf_t_init(_bcm_field_qual_conf_t *ptr) 4471 { 4472 _bcm_field_selector_t *selector; 4473 4474 if (NULL == ptr) { 4475 return; 4476 } 4477 4478 /* Reset qualifier configuration structure. */ 4479 sal_memset(ptr, 0, sizeof(_bcm_field_qual_conf_t)); 4480 4481 /* Set Selectors to Don't care. */ 4482 selector = &ptr->selector; 4483 selector->dev_sel = _bcmFieldDevSelDisable; 4484 selector->pri_sel = _bcmFieldSliceSelDisable; 4485 selector->sec_sel = _bcmFieldSliceSelDisable; 4486 4487 return; 4488 } 4489 4490 /* 4491 * Function: 4492 * _bcm_field_qual_info_t_init 4493 * Purpose: 4494 * Initialize qualifier info structure. 4495 * Parameters: 4496 * ptr - (OUT) Pointer to field qualifier info strucutre. 4497 * 4498 * Returns: 4499 * Void. 4500 */ 4501 void 4502 _bcm_field_qual_info_t_init(_bcm_field_qual_info_t *ptr) 4503 { 4504 /* Input parameters check. */ 4505 if (NULL == ptr) { 4506 return; 4507 } 4508 4509 /* Reset qualifier configuration structure. */ 4510 sal_memset(ptr, 0, sizeof(_bcm_field_qual_info_t)); 4511 4512 return; 4513 } 4514 4515 /* 4516 * Function: 4517 * _bcm_field_qual_insert 4518 * Purpose: 4519 * Add qualifier to stage qualifers list. 4520 * Parameters: 4521 * unit - (IN) BCM device number. 4522 * stage_fc - (IN) Stage field control strucutre. 4523 * qual_type - (IN) Type of Qualifier. 4524 * qual_id - (IN) Qualifier Id. 4525 * ptr - (IN) Reference to qual configuration structure. 4526 * Returns: 4527 * BCM_E_XXX 4528 */ 4529 int 4530 _bcm_field_qual_insert (int unit, _field_stage_t *stage_fc, int qual_type, 4531 int qual_id, _bcm_field_qual_conf_t *ptr) 4532 { 4533 _bcm_field_qual_info_t *f_qual = NULL; /* Field qualifier info. */ 4534 _bcm_field_qual_conf_t *f_qual_conf = NULL; /* Qualifier configuration. */ 4535 int alloc_size; /* Memory allocation size. */ 4536 4537 /* Input parameters check. */ 4538 if ((NULL == ptr) || (NULL == stage_fc) || 4539 (qual_id < 0) || (qual_id > _bcmFieldQualifyCount)) { 4540 return BCM_E_PARAM; 4541 } 4542 4543 /* Check qualifier support based on flag. */ 4544 if ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) && 4545 (ptr->offset.flags & _BCM_FIELD_QUAL_OFFSET_NO_IFP_SUPPORT)) { 4546 return BCM_E_NONE; 4547 } 4548 if ((_BCM_FIELD_STAGE_EXACTMATCH == stage_fc->stage_id) && 4549 (ptr->offset.flags & _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT)) { 4550 return BCM_E_NONE; 4551 } 4552 if ((_BCM_FIELD_STAGE_FLOWTRACKER == stage_fc->stage_id) && 4553 (ptr->offset.flags & _BCM_FIELD_QUAL_OFFSET_NO_FT_SUPPORT)) { 4554 return BCM_E_NONE; 4555 } 4556 4557 if (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 4558 if (soc_feature(unit, soc_feature_vfp_no_inner_ip_fields_support)) { 4559 switch (qual_id) { 4560 case bcmFieldQualifyInnerIpProtocolCommon: 4561 case bcmFieldQualifyInnerTtl: 4562 case bcmFieldQualifyInnerIpFrag: 4563 case bcmFieldQualifyInnerTos: 4564 case bcmFieldQualifyInnerL4DstPort: 4565 case bcmFieldQualifyInnerL4SrcPort: 4566 case bcmFieldQualifyInnerIpProtocol: 4567 case bcmFieldQualifyInnerDstIp: 4568 case bcmFieldQualifyInnerSrcIp: 4569 case bcmFieldQualifyInnerSrcIp6: 4570 case bcmFieldQualifyInnerDstIp6: 4571 case bcmFieldQualifyInnerSrcIp6High: 4572 case bcmFieldQualifyInnerDstIp6High: 4573 return BCM_E_NONE; 4574 default: 4575 break; 4576 } 4577 } 4578 /* ExtensionHeaderSubcode is not supported in TD3 VFP */ 4579 if (soc_feature(unit, soc_feature_td3_style_fp) 4580 && qual_id == bcmFieldQualifyExtensionHeaderSubCode) { 4581 return BCM_E_NONE; 4582 } 4583 } 4584 4585 /* Assign the stage qual_arr based on the qualifier type */ 4586 if (qual_type == _bcmFieldQualifierTypePresel) { 4587 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 4588 return BCM_E_INTERNAL; 4589 } 4590 f_qual = stage_fc->f_presel_qual_arr[qual_id]; 4591 } else { 4592 f_qual = stage_fc->f_qual_arr[qual_id]; 4593 } 4594 4595 /* Allocate qualifier descriptor. */ 4596 if (NULL == f_qual) { 4597 alloc_size = sizeof(_bcm_field_qual_info_t); 4598 _FP_XGS3_ALLOC(f_qual, alloc_size, "FP qualifier info"); 4599 if (NULL == f_qual) { 4600 return (BCM_E_MEMORY); 4601 } 4602 _bcm_field_qual_info_t_init(f_qual); 4603 f_qual->qid = qual_id; 4604 } 4605 4606 /* Allocate qualifier configurations array. */ 4607 /* Re-alloc configuration array if qualifier has multiple configurations. */ 4608 alloc_size = (f_qual->conf_sz + 1) * sizeof (_bcm_field_qual_conf_t); 4609 4610 /* Allocated qualifier descriptor. */ 4611 _FP_XGS3_ALLOC(f_qual_conf, alloc_size, "FP qualifier config"); 4612 if (NULL == f_qual_conf) { 4613 if (NULL != f_qual->conf_arr) { 4614 sal_free(f_qual->conf_arr); 4615 } 4616 sal_free(f_qual); 4617 if (qual_type == _bcmFieldQualifierTypePresel) { 4618 stage_fc->f_presel_qual_arr[qual_id] = NULL; 4619 } else { 4620 stage_fc->f_qual_arr[qual_id] = NULL; 4621 } 4622 return (BCM_E_MEMORY); 4623 } 4624 4625 /* Copy previous configurations if any. */ 4626 if (NULL != f_qual->conf_arr) { 4627 alloc_size -= sizeof(_bcm_field_qual_conf_t); 4628 sal_memcpy (f_qual_conf, f_qual->conf_arr, alloc_size); 4629 sal_free(f_qual->conf_arr); 4630 } 4631 4632 /* Set configuration array pointer to a new array. */ 4633 f_qual->conf_arr = f_qual_conf; 4634 4635 /* Copy new configuration to configuration array. */ 4636 f_qual->conf_arr[f_qual->conf_sz] = *ptr; 4637 4638 /* Increment number of active configurations. */ 4639 f_qual->conf_sz++; 4640 4641 /* Install qualifier into stage qualifiers array. */ 4642 if (qual_type == _bcmFieldQualifierTypePresel) { 4643 stage_fc->f_presel_qual_arr[qual_id] = f_qual; 4644 } else { 4645 stage_fc->f_qual_arr[qual_id] = f_qual; 4646 } 4647 4648 return (BCM_E_NONE); 4649 } 4650 4651 4652 /* 4653 * Function: 4654 * _field_selector_update_cmp 4655 * Purpose: 4656 * Compare number of update required in order to use 4657 * a qualifier select code. 4658 * Parameters: 4659 * b - (IN) first compared selector. 4660 * a - (IN) second compared selector. 4661 * Returns: 4662 * a<=>b 4663 */ 4664 static INLINE int 4665 _field_selector_update_cmp(void *a, void *b) 4666 { 4667 _bcm_field_qual_conf_t *first; /* First compared selector. */ 4668 _bcm_field_qual_conf_t *second; /* Second compared selector. */ 4669 4670 first = (_bcm_field_qual_conf_t *)a; 4671 second = (_bcm_field_qual_conf_t *)b; 4672 4673 if (first->selector.update_count < 4674 second->selector.update_count) { 4675 return (-1); 4676 } else if (first->selector.update_count > 4677 second->selector.update_count) { 4678 return (1); 4679 } 4680 return (0); 4681 } 4682 4683 /* 4684 * Function: 4685 * _field_qual_info_cmp 4686 * Purpose: 4687 * Compare frequency of two qualifiers appearance. 4688 * Parameters: 4689 * b - (IN) first compared qualifier. 4690 * a - (IN) second compared qualifier. 4691 * Returns: 4692 * a<=>b 4693 */ 4694 static INLINE int 4695 _field_qual_info_cmp (void *a, void *b) 4696 { 4697 _bcm_field_qual_info_t **first; /* First compared qualifier. */ 4698 _bcm_field_qual_info_t **second; /* Second compared qualifier. */ 4699 4700 first = (_bcm_field_qual_info_t **)a; 4701 second = (_bcm_field_qual_info_t **)b; 4702 4703 if ((*first)->conf_sz < (*second)->conf_sz) { 4704 return (-1); 4705 } else if ((*first)->conf_sz > (*second)->conf_sz) { 4706 return (1); 4707 } 4708 return (0); 4709 } 4710 4711 /* 4712 * Function: 4713 * _field_selector_insert 4714 * Purpose: 4715 * Insert selector into a specific tcam part of the entry. 4716 * Parameters: 4717 * sel_arr - (IN) Current entry select codes. 4718 * part_idx - (IN) Tcam part index. 4719 * selector - (IN) Inserted selector. 4720 * Returns: 4721 * BCM_E_XXX 4722 */ 4723 STATIC int 4724 _field_selector_insert (_field_sel_t *sel_arr, int part_idx, 4725 _bcm_field_selector_t *selector) 4726 { 4727 _field_sel_t *tcam_part; /* Tcam part selectors. */ 4728 4729 /* Input parameters check. */ 4730 if ((NULL == sel_arr) || (NULL == selector)) { 4731 return (BCM_E_PARAM); 4732 } 4733 4734 tcam_part = sel_arr + part_idx; 4735 4736 /* Per device selector. */ 4737 switch (selector->dev_sel) { 4738 case _bcmFieldDevSelDisable: 4739 break; 4740 case _bcmFieldDevSelInnerVlanOverlay: 4741 sel_arr[0].inner_vlan_overlay = selector->dev_sel_val; 4742 break; 4743 case _bcmFieldDevSelIntrasliceVfpKey: 4744 sel_arr[0].intraslice_vfp_sel = selector->dev_sel_val; 4745 break; 4746 default: 4747 return (BCM_E_INTERNAL); 4748 } 4749 4750 /* Primary slice selector. */ 4751 switch (selector->pri_sel) { 4752 case _bcmFieldSliceSelDisable: 4753 break; 4754 case _bcmFieldSliceSelFpf1: 4755 tcam_part->fpf1 = selector->pri_sel_val; 4756 break; 4757 case _bcmFieldSliceSelFpf2: 4758 tcam_part->fpf2 = selector->pri_sel_val; 4759 break; 4760 case _bcmFieldSliceSelFpf3: 4761 tcam_part->fpf3 = selector->pri_sel_val; 4762 break; 4763 case _bcmFieldSliceSelFpf4: 4764 tcam_part->fpf4 = selector->pri_sel_val; 4765 break; 4766 case _bcmFieldSliceSelExternal: 4767 tcam_part->extn = selector->pri_sel_val; 4768 break; 4769 default: 4770 return (BCM_E_INTERNAL); 4771 } 4772 4773 /* Per slice selectors are inserted into primary slice only. */ 4774 if ((selector->intraslice) && (0 != part_idx)) { 4775 tcam_part = sel_arr + (part_idx - 1); 4776 } 4777 4778 /* Secondary slice selector. */ 4779 switch (selector->sec_sel) { 4780 case _bcmFieldSliceSelDisable: 4781 break; 4782 case _bcmFieldSliceSrcClassSelect: 4783 tcam_part->src_class_sel = selector->sec_sel_val; 4784 break; 4785 case _bcmFieldSliceDstClassSelect: 4786 tcam_part->dst_class_sel = selector->sec_sel_val; 4787 break; 4788 case _bcmFieldSliceIntfClassSelect: 4789 tcam_part->intf_class_sel = selector->sec_sel_val; 4790 break; 4791 case _bcmFieldSliceLoopbackTypeSelect: 4792 tcam_part->loopback_type_sel = selector->sec_sel_val; 4793 break; 4794 case _bcmFieldSliceIngressEntitySelect: 4795 tcam_part->ingress_entity_sel = selector->sec_sel_val; 4796 break; 4797 case _bcmFieldSliceSrcEntitySelect: 4798 tcam_part->src_entity_sel = selector->sec_sel_val; 4799 break; 4800 case _bcmFieldSliceDstFwdEntitySelect: 4801 tcam_part->dst_fwd_entity_sel = selector->sec_sel_val; 4802 break; 4803 case _bcmFieldSliceFwdFieldSelect: 4804 tcam_part->fwd_field_sel = selector->sec_sel_val; 4805 break; 4806 case _bcmFieldSliceIpHeaderSelect: 4807 tcam_part->ip_header_sel = selector->sec_sel_val; 4808 break; 4809 case _bcmFieldSliceSrcTypeSelect: 4810 tcam_part->src_type_sel = selector->sec_sel_val; 4811 break; 4812 case _bcmFieldSliceIp6AddrSelect: 4813 tcam_part->ip6_addr_sel = selector->sec_sel_val; 4814 break; 4815 case _bcmFieldSliceAuxTag1Select: 4816 tcam_part->aux_tag_1_sel = selector->sec_sel_val; 4817 break; 4818 case _bcmFieldSliceAuxTag2Select: 4819 tcam_part->aux_tag_2_sel = selector->sec_sel_val; 4820 break; 4821 case _bcmFieldSliceOamOverLayEnable: 4822 tcam_part->oam_overlay_sel = selector->sec_sel_val; 4823 break; 4824 case _bcmFieldSliceTtlClassSelect: 4825 tcam_part->ttl_class_sel = selector->sec_sel_val; 4826 break; 4827 case _bcmFieldSliceTcpClassSelect: 4828 tcam_part->tcp_class_sel = selector->sec_sel_val; 4829 break; 4830 case _bcmFieldSliceTosClassSelect: 4831 tcam_part->tos_class_sel = selector->sec_sel_val; 4832 break; 4833 case _bcmFieldSliceSelEgrClassF1: 4834 tcam_part->egr_class_f1_sel = selector->sec_sel_val; 4835 break; 4836 case _bcmFieldSliceSelEgrClassF2: 4837 tcam_part->egr_class_f2_sel = selector->sec_sel_val; 4838 break; 4839 case _bcmFieldSliceSelEgrClassF3: 4840 tcam_part->egr_class_f3_sel = selector->sec_sel_val; 4841 break; 4842 case _bcmFieldSliceSelEgrClassF4: 4843 tcam_part->egr_class_f4_sel = selector->sec_sel_val; 4844 break; 4845 case _bcmFieldSliceSelEgrClassF6: 4846 tcam_part->egr_class_f6_sel = selector->sec_sel_val; 4847 break; 4848 case _bcmFieldSliceSelEgrClassF7: 4849 tcam_part->egr_class_f7_sel = selector->sec_sel_val; 4850 break; 4851 case _bcmFieldSliceSelEgrClassF8: 4852 tcam_part->egr_class_f8_sel = selector->sec_sel_val; 4853 break; 4854 case _bcmFieldSliceSelEgrDvpKey4: 4855 tcam_part->egr_key4_dvp_sel = selector->sec_sel_val; 4856 break; 4857 case _bcmFieldSliceSelEgrDvpKey8: 4858 tcam_part->egr_key8_dvp_sel = selector->sec_sel_val; 4859 break; 4860 case _bcmFieldSliceSelEgrMdlKey4: 4861 tcam_part->egr_key4_mdl_sel = selector->sec_sel_val; 4862 break; 4863 case _bcmFieldSliceSelEgrOamOverlayKey4: 4864 tcam_part->egr_oam_overlay_sel = selector->sec_sel_val; 4865 break; 4866 case _bcmFieldSliceSelEgrDestPortF1: 4867 tcam_part->egr_dest_port_f1_sel = selector->sec_sel_val; 4868 break; 4869 case _bcmFieldSliceSelEgrDestPortF5: 4870 tcam_part->egr_dest_port_f5_sel = selector->sec_sel_val; 4871 break; 4872 case _bcmFieldSliceSelEgrClassIdBF1: 4873 tcam_part->egr_classId_B_f1_sel = selector->sec_sel_val; 4874 break; 4875 case _bcmFieldSliceSelEgrClassIdBF2: 4876 tcam_part->egr_classId_B_f2_sel = selector->sec_sel_val; 4877 break; 4878 case _bcmFieldSliceSelEgrClassIdBF3: 4879 tcam_part->egr_classId_B_f3_sel = selector->sec_sel_val; 4880 break; 4881 case _bcmFieldSliceSelEgrClassIdBF4: 4882 tcam_part->egr_classId_B_f4_sel = selector->sec_sel_val; 4883 break; 4884 case _bcmFieldSliceSelEgrClassIdBF5: 4885 tcam_part->egr_classId_B_f5_sel = selector->sec_sel_val; 4886 break; 4887 case _bcmFieldSliceSelEgrClassIdBF6: 4888 tcam_part->egr_classId_B_f6_sel = selector->sec_sel_val; 4889 break; 4890 case _bcmFieldSliceSelEgrClassIdBF7: 4891 tcam_part->egr_classId_B_f7_sel = selector->sec_sel_val; 4892 break; 4893 case _bcmFieldSliceSelEgrClassIdBF8: 4894 tcam_part->egr_classId_B_f8_sel = selector->sec_sel_val; 4895 break; 4896 case _bcmFieldSliceSelEgrClassKey4: 4897 tcam_part->egr_key4_l3_classId_sel = selector->sec_sel_val; 4898 break; 4899 case _bcmFieldSliceSelEgrClassKey8: 4900 tcam_part->egr_key8_l3_classId_sel = selector->sec_sel_val; 4901 break; 4902 default: 4903 return (BCM_E_INTERNAL); 4904 } 4905 4906 /* Tertiary slice selector */ 4907 switch (selector->ter_sel) { 4908 case _bcmFieldSliceSelDisable: 4909 break; 4910 case _bcmFieldSliceFpf1SrcDstClassSelect: 4911 tcam_part->src_dest_class_f1_sel = selector->ter_sel_val; 4912 break; 4913 case _bcmFieldSliceFpf3SrcDstClassSelect: 4914 tcam_part->src_dest_class_f3_sel = selector->ter_sel_val; 4915 break; 4916 case _bcmFieldSliceOamInterfaceClassSelect: 4917 tcam_part->oam_intf_class_sel = selector->ter_sel_val; 4918 break; 4919 case _bcmFieldSliceSelEgrClassF6: 4920 tcam_part->egr_class_f6_sel = selector->ter_sel_val; 4921 break; 4922 default: 4923 return (BCM_E_INTERNAL); 4924 } 4925 4926 return (BCM_E_NONE); 4927 } 4928 4929 /* 4930 * Function: 4931 * _field_selector_diff 4932 * Purpose: 4933 * Compare selector configuration with current selectors 4934 * status of field group entry. 4935 * Parameters: 4936 * unit - (IN) BCM device number. 4937 * sel_arr - (IN) Current entry select codes. 4938 * part_idx - (IN) Tcam part index. 4939 * selector - (IN) Compared selector. 4940 * diff_count - (OUT) Number of different elements. 4941 * Returns: 4942 * BCM_E_XXX 4943 * NOTE: 4944 * Function returns BCM_E_RESOURCE if configurations are conflicting. 4945 */ 4946 int 4947 _field_selector_diff(int unit, _field_sel_t *sel_arr, int part_idx, 4948 _bcm_field_selector_t *selector, 4949 uint8 *diff_count) 4950 { 4951 uint8 count; /* Required updates count. */ 4952 _field_sel_t *tcam_part; /* Tcam part selectors. */ 4953 #if defined(BCM_FIREBOLT_SUPPORT) 4954 int temp; /* Temporary test variable.*/ 4955 int rv; /* Operation return status.*/ 4956 #endif /* BCM_FIREBOLT_SUPPORT */ 4957 4958 /* Input parameters check. */ 4959 if ((NULL == sel_arr) || (NULL == selector) || (NULL == diff_count)) { 4960 return (BCM_E_PARAM); 4961 } 4962 4963 count = 0; 4964 tcam_part = sel_arr + part_idx; 4965 4966 /* Qualifier is available in the second part of intraslice entry */ 4967 if (selector->intraslice) { 4968 if (_FP_SELCODE_DONT_USE == tcam_part->intraslice) { 4969 return (BCM_E_RESOURCE); 4970 } 4971 } else { 4972 if (_FP_SELCODE_DONT_USE != tcam_part->intraslice) { 4973 return (BCM_E_RESOURCE); 4974 } 4975 } 4976 4977 /* Qualifier is available only in the primary part of a paired 4978 entry */ 4979 4980 if (selector->primary) { 4981 if (part_idx % 2) { 4982 return (BCM_E_RESOURCE); 4983 } 4984 } 4985 4986 /* Qualifier is available only in the secondary part of a paired 4987 entry */ 4988 4989 if (selector->secondary) { 4990 if (_FP_SELCODE_DONT_USE == tcam_part->secondary) { 4991 return (BCM_E_RESOURCE); 4992 } 4993 } 4994 4995 /* Per device selectors. */ 4996 switch (selector->dev_sel) { 4997 case _bcmFieldDevSelDisable: 4998 break; 4999 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 5000 case _bcmFieldDevSelInnerVlanOverlay: 5001 rv = _bcm_field_fb_group_inner_vlan_overlay_get(unit, &temp); 5002 BCM_IF_ERROR_RETURN(rv); 5003 if (((_FP_SELCODE_DONT_CARE != temp) && 5004 (temp != selector->dev_sel_val)) || 5005 ((_FP_SELCODE_DONT_CARE != sel_arr[0].inner_vlan_overlay) && 5006 (sel_arr[0].inner_vlan_overlay != selector->dev_sel_val))) { 5007 return (BCM_E_RESOURCE); 5008 } 5009 break; 5010 #endif /* BCM_FIREBOLT_SUPPORT */ 5011 #if defined(BCM_FIREBOLT2_SUPPORT) 5012 case _bcmFieldDevSelIntrasliceVfpKey: 5013 rv = _bcm_field_vfp_doublewide_key_select_get(unit, &temp); 5014 BCM_IF_ERROR_RETURN(rv); 5015 if (((_FP_SELCODE_DONT_CARE != temp) && 5016 (temp != selector->dev_sel_val)) || 5017 ((_FP_SELCODE_DONT_CARE != sel_arr[0].intraslice_vfp_sel) && 5018 (sel_arr[0].intraslice_vfp_sel != selector->dev_sel_val))) { 5019 return (BCM_E_RESOURCE); 5020 } 5021 break; 5022 #endif /* BCM_FIREBOLT2_SUPPORT */ 5023 default: 5024 return (BCM_E_INTERNAL); 5025 } 5026 5027 5028 /* Primary slice selector. */ 5029 switch (selector->pri_sel) { 5030 case _bcmFieldSliceSelDisable: 5031 break; 5032 case _bcmFieldSliceSelFpf1: 5033 if (tcam_part->fpf1 == _FP_SELCODE_DONT_CARE) { 5034 count++; 5035 } else if (tcam_part->fpf1 != selector->pri_sel_val) { 5036 return (BCM_E_RESOURCE); 5037 } 5038 break; 5039 case _bcmFieldSliceSelFpf2: 5040 if (tcam_part->fpf2 == _FP_SELCODE_DONT_CARE) { 5041 count++; 5042 } else if (tcam_part->fpf2 != selector->pri_sel_val) { 5043 return (BCM_E_RESOURCE); 5044 } 5045 break; 5046 case _bcmFieldSliceSelFpf3: 5047 if (tcam_part->fpf3 == _FP_SELCODE_DONT_CARE) { 5048 count++; 5049 } else if (tcam_part->fpf3 != selector->pri_sel_val) { 5050 return (BCM_E_RESOURCE); 5051 } 5052 break; 5053 case _bcmFieldSliceSelFpf4: 5054 if (tcam_part->fpf4 == _FP_SELCODE_DONT_CARE) { 5055 count++; 5056 } else if (tcam_part->fpf4 != selector->pri_sel_val) { 5057 return (BCM_E_RESOURCE); 5058 } 5059 break; 5060 case _bcmFieldSliceSelExternal: 5061 if (tcam_part->extn == _FP_SELCODE_DONT_CARE) { 5062 count++; 5063 } else if (tcam_part->extn != selector->pri_sel_val) { 5064 return (BCM_E_RESOURCE); 5065 } 5066 break; 5067 default: 5068 return (BCM_E_INTERNAL); 5069 } 5070 5071 /* Secondary slice selector. */ 5072 /* Per slice selectors are inserted into primary slice only. */ 5073 if ((selector->intraslice) && (0 != part_idx)) { 5074 tcam_part = sel_arr + (part_idx - 1); 5075 } 5076 5077 switch (selector->sec_sel) { 5078 case _bcmFieldSliceSelDisable: 5079 break; 5080 case _bcmFieldSliceSrcClassSelect: 5081 if (tcam_part->src_class_sel == _FP_SELCODE_DONT_CARE) { 5082 count++; 5083 } else if (tcam_part->src_class_sel != selector->sec_sel_val) { 5084 return (BCM_E_RESOURCE); 5085 } 5086 break; 5087 case _bcmFieldSliceDstClassSelect: 5088 if (tcam_part->dst_class_sel == _FP_SELCODE_DONT_CARE) { 5089 count++; 5090 } else if (tcam_part->dst_class_sel != selector->sec_sel_val) { 5091 return (BCM_E_RESOURCE); 5092 } 5093 break; 5094 case _bcmFieldSliceIntfClassSelect: 5095 if (tcam_part->intf_class_sel == _FP_SELCODE_DONT_CARE) { 5096 count++; 5097 } else if (tcam_part->intf_class_sel != selector->sec_sel_val) { 5098 return (BCM_E_RESOURCE); 5099 } 5100 break; 5101 case _bcmFieldSliceLoopbackTypeSelect: 5102 if (tcam_part->loopback_type_sel == _FP_SELCODE_DONT_CARE) { 5103 count++; 5104 } else if (tcam_part->loopback_type_sel != selector->sec_sel_val) { 5105 return (BCM_E_RESOURCE); 5106 } 5107 break; 5108 case _bcmFieldSliceIngressEntitySelect: 5109 if (tcam_part->ingress_entity_sel == _FP_SELCODE_DONT_CARE) { 5110 count++; 5111 } else if (tcam_part->ingress_entity_sel != selector->sec_sel_val) { 5112 return (BCM_E_RESOURCE); 5113 } 5114 break; 5115 case _bcmFieldSliceSrcEntitySelect: 5116 if (tcam_part->src_entity_sel == _FP_SELCODE_DONT_CARE) { 5117 count++; 5118 } else if (tcam_part->src_entity_sel != selector->sec_sel_val) { 5119 return (BCM_E_RESOURCE); 5120 } 5121 break; 5122 case _bcmFieldSliceDstFwdEntitySelect: 5123 if (tcam_part->dst_fwd_entity_sel == _FP_SELCODE_DONT_CARE) { 5124 count++; 5125 } else if (tcam_part->dst_fwd_entity_sel != selector->sec_sel_val) { 5126 return (BCM_E_RESOURCE); 5127 } 5128 break; 5129 case _bcmFieldSliceFwdFieldSelect: 5130 if (tcam_part->fwd_field_sel == _FP_SELCODE_DONT_CARE) { 5131 count++; 5132 } else if (tcam_part->fwd_field_sel != selector->sec_sel_val) { 5133 return (BCM_E_RESOURCE); 5134 } 5135 break; 5136 case _bcmFieldSliceIpHeaderSelect: 5137 if (tcam_part->ip_header_sel== _FP_SELCODE_DONT_CARE) { 5138 count++; 5139 } else if (tcam_part->ip_header_sel != selector->sec_sel_val) { 5140 return (BCM_E_RESOURCE); 5141 } 5142 break; 5143 case _bcmFieldSliceSrcTypeSelect: 5144 if (tcam_part->src_type_sel== _FP_SELCODE_DONT_CARE) { 5145 count++; 5146 } else if (tcam_part->src_type_sel != selector->sec_sel_val) { 5147 return (BCM_E_RESOURCE); 5148 } 5149 break; 5150 case _bcmFieldSliceIp6AddrSelect: 5151 if (tcam_part->ip6_addr_sel == _FP_SELCODE_DONT_CARE) { 5152 count++; 5153 } else if (tcam_part->ip6_addr_sel != selector->sec_sel_val) { 5154 return (BCM_E_RESOURCE); 5155 } 5156 break; 5157 case _bcmFieldSliceAuxTag1Select: 5158 if (tcam_part->aux_tag_1_sel == _FP_SELCODE_DONT_CARE) { 5159 ++count; 5160 } else if (tcam_part->aux_tag_1_sel != selector->sec_sel_val) { 5161 return (BCM_E_RESOURCE); 5162 } 5163 break; 5164 case _bcmFieldSliceAuxTag2Select: 5165 if (tcam_part->aux_tag_2_sel == _FP_SELCODE_DONT_CARE) { 5166 ++count; 5167 } else if (tcam_part->aux_tag_2_sel != selector->sec_sel_val) { 5168 return (BCM_E_RESOURCE); 5169 } 5170 break; 5171 case _bcmFieldSliceOamOverLayEnable: 5172 if (tcam_part->oam_overlay_sel == _FP_SELCODE_DONT_CARE) { 5173 ++count; 5174 } else if (tcam_part->oam_overlay_sel != selector->sec_sel_val) { 5175 return (BCM_E_RESOURCE); 5176 } 5177 break; 5178 case _bcmFieldSliceSelEgrClassF1: 5179 if (tcam_part->egr_class_f1_sel == _FP_SELCODE_DONT_CARE) { 5180 ++count; 5181 } else if (tcam_part->egr_class_f1_sel != selector->sec_sel_val) { 5182 return (BCM_E_RESOURCE); 5183 } 5184 break; 5185 case _bcmFieldSliceSelEgrClassF2: 5186 if (tcam_part->egr_class_f2_sel == _FP_SELCODE_DONT_CARE) { 5187 ++count; 5188 } else if (tcam_part->egr_class_f2_sel != selector->sec_sel_val) { 5189 return (BCM_E_RESOURCE); 5190 } 5191 break; 5192 case _bcmFieldSliceSelEgrClassF3: 5193 if (tcam_part->egr_class_f3_sel == _FP_SELCODE_DONT_CARE) { 5194 ++count; 5195 } else if (tcam_part->egr_class_f3_sel != selector->sec_sel_val) { 5196 return (BCM_E_RESOURCE); 5197 } 5198 break; 5199 case _bcmFieldSliceSelEgrClassF4: 5200 if (tcam_part->egr_class_f4_sel == _FP_SELCODE_DONT_CARE) { 5201 ++count; 5202 } else if (tcam_part->egr_class_f4_sel != selector->sec_sel_val) { 5203 return (BCM_E_RESOURCE); 5204 } 5205 break; 5206 case _bcmFieldSliceSelEgrClassF6: 5207 if (tcam_part->egr_class_f6_sel == _FP_SELCODE_DONT_CARE) { 5208 ++count; 5209 } else if (tcam_part->egr_class_f6_sel != selector->sec_sel_val) { 5210 return (BCM_E_RESOURCE); 5211 } 5212 break; 5213 case _bcmFieldSliceSelEgrClassF7: 5214 if (tcam_part->egr_class_f7_sel == _FP_SELCODE_DONT_CARE) { 5215 ++count; 5216 } else if (tcam_part->egr_class_f7_sel != selector->sec_sel_val) { 5217 return (BCM_E_RESOURCE); 5218 } 5219 break; 5220 case _bcmFieldSliceSelEgrClassF8: 5221 if (tcam_part->egr_class_f8_sel == _FP_SELCODE_DONT_CARE) { 5222 ++count; 5223 } else if (tcam_part->egr_class_f8_sel != selector->sec_sel_val) { 5224 return (BCM_E_RESOURCE); 5225 } 5226 break; 5227 case _bcmFieldSliceSelEgrDvpKey4: 5228 if (tcam_part->egr_key4_dvp_sel == _FP_SELCODE_DONT_CARE) { 5229 ++count; 5230 } else if (tcam_part->egr_key4_dvp_sel != selector->sec_sel_val) { 5231 return (BCM_E_RESOURCE); 5232 } 5233 break; 5234 case _bcmFieldSliceSelEgrDvpKey8: 5235 if (tcam_part->egr_key8_dvp_sel == _FP_SELCODE_DONT_CARE) { 5236 ++count; 5237 } else if (tcam_part->egr_key8_dvp_sel != selector->sec_sel_val) { 5238 return (BCM_E_RESOURCE); 5239 } 5240 break; 5241 case _bcmFieldSliceSelEgrMdlKey4: 5242 if (tcam_part->egr_key4_mdl_sel == _FP_SELCODE_DONT_CARE) { 5243 ++count; 5244 } else if (tcam_part->egr_key4_mdl_sel != selector->sec_sel_val) { 5245 return (BCM_E_RESOURCE); 5246 } 5247 break; 5248 case _bcmFieldSliceSelEgrOamOverlayKey4: 5249 if (tcam_part->egr_oam_overlay_sel == _FP_SELCODE_DONT_CARE) { 5250 ++count; 5251 } else if (tcam_part->egr_oam_overlay_sel != selector->sec_sel_val) { 5252 return (BCM_E_RESOURCE); 5253 } 5254 break; 5255 case _bcmFieldSliceSelEgrDestPortF1: 5256 if (tcam_part->egr_dest_port_f1_sel == _FP_SELCODE_DONT_CARE) { 5257 ++count; 5258 } else if (tcam_part->egr_dest_port_f1_sel != selector->sec_sel_val) { 5259 return (BCM_E_RESOURCE); 5260 } 5261 break; 5262 case _bcmFieldSliceSelEgrDestPortF5: 5263 if (tcam_part->egr_dest_port_f5_sel == _FP_SELCODE_DONT_CARE) { 5264 ++count; 5265 } else if (tcam_part->egr_dest_port_f5_sel != selector->sec_sel_val) { 5266 return (BCM_E_RESOURCE); 5267 } 5268 break; 5269 case _bcmFieldSliceSelEgrClassIdBF1: 5270 if (tcam_part->egr_classId_B_f1_sel == _FP_SELCODE_DONT_CARE) { 5271 ++count; 5272 } else if (tcam_part->egr_classId_B_f1_sel != selector->sec_sel_val) { 5273 return (BCM_E_RESOURCE); 5274 } 5275 break; 5276 case _bcmFieldSliceSelEgrClassIdBF2: 5277 if (tcam_part->egr_classId_B_f2_sel == _FP_SELCODE_DONT_CARE) { 5278 ++count; 5279 } else if (tcam_part->egr_classId_B_f2_sel != selector->sec_sel_val) { 5280 return (BCM_E_RESOURCE); 5281 } 5282 break; 5283 case _bcmFieldSliceSelEgrClassIdBF3: 5284 if (tcam_part->egr_classId_B_f3_sel == _FP_SELCODE_DONT_CARE) { 5285 ++count; 5286 } else if (tcam_part->egr_classId_B_f3_sel != selector->sec_sel_val) { 5287 return (BCM_E_RESOURCE); 5288 } 5289 break; 5290 case _bcmFieldSliceSelEgrClassIdBF4: 5291 if (tcam_part->egr_classId_B_f4_sel == _FP_SELCODE_DONT_CARE) { 5292 ++count; 5293 } else if (tcam_part->egr_classId_B_f4_sel != selector->sec_sel_val) { 5294 return (BCM_E_RESOURCE); 5295 } 5296 break; 5297 case _bcmFieldSliceSelEgrClassIdBF5: 5298 if (tcam_part->egr_classId_B_f5_sel == _FP_SELCODE_DONT_CARE) { 5299 ++count; 5300 } else if (tcam_part->egr_classId_B_f5_sel != selector->sec_sel_val) { 5301 return (BCM_E_RESOURCE); 5302 } 5303 break; 5304 case _bcmFieldSliceSelEgrClassIdBF6: 5305 if (tcam_part->egr_classId_B_f6_sel == _FP_SELCODE_DONT_CARE) { 5306 ++count; 5307 } else if (tcam_part->egr_classId_B_f6_sel != selector->sec_sel_val) { 5308 return (BCM_E_RESOURCE); 5309 } 5310 break; 5311 case _bcmFieldSliceSelEgrClassIdBF7: 5312 if (tcam_part->egr_classId_B_f7_sel == _FP_SELCODE_DONT_CARE) { 5313 ++count; 5314 } else if (tcam_part->egr_classId_B_f7_sel != selector->sec_sel_val) { 5315 return (BCM_E_RESOURCE); 5316 } 5317 break; 5318 case _bcmFieldSliceSelEgrClassIdBF8: 5319 if (tcam_part->egr_classId_B_f8_sel == _FP_SELCODE_DONT_CARE) { 5320 ++count; 5321 } else if (tcam_part->egr_classId_B_f8_sel != selector->sec_sel_val) { 5322 return (BCM_E_RESOURCE); 5323 } 5324 break; 5325 case _bcmFieldSliceTtlClassSelect: 5326 if (tcam_part->ttl_class_sel== _FP_SELCODE_DONT_CARE) { 5327 ++count; 5328 } else if (tcam_part->ttl_class_sel != selector->sec_sel_val) { 5329 return (BCM_E_RESOURCE); 5330 } 5331 break; 5332 case _bcmFieldSliceTcpClassSelect: 5333 if (tcam_part->tcp_class_sel== _FP_SELCODE_DONT_CARE) { 5334 ++count; 5335 } else if (tcam_part->tcp_class_sel != selector->sec_sel_val) { 5336 return (BCM_E_RESOURCE); 5337 } 5338 break; 5339 case _bcmFieldSliceTosClassSelect: 5340 if (tcam_part->tos_class_sel== _FP_SELCODE_DONT_CARE) { 5341 ++count; 5342 } else if (tcam_part->tos_class_sel != selector->sec_sel_val) { 5343 return (BCM_E_RESOURCE); 5344 } 5345 break; 5346 case _bcmFieldSliceSelEgrClassKey4: 5347 if (tcam_part->egr_key4_l3_classId_sel== _FP_SELCODE_DONT_CARE) { 5348 ++count; 5349 } else if (tcam_part->egr_key4_l3_classId_sel != selector->sec_sel_val) { 5350 return (BCM_E_RESOURCE); 5351 } 5352 break; 5353 case _bcmFieldSliceSelEgrClassKey8: 5354 if (tcam_part->egr_key8_l3_classId_sel== _FP_SELCODE_DONT_CARE) { 5355 ++count; 5356 } else if (tcam_part->egr_key8_l3_classId_sel != selector->sec_sel_val) { 5357 return (BCM_E_RESOURCE); 5358 } 5359 break; 5360 default: 5361 return (BCM_E_INTERNAL); 5362 } 5363 5364 /* Tertiary slice selector */ 5365 switch (selector->ter_sel) { 5366 case _bcmFieldSliceSelDisable: 5367 break; 5368 case _bcmFieldSliceFpf1SrcDstClassSelect: 5369 if (tcam_part->src_dest_class_f1_sel == _FP_SELCODE_DONT_CARE) { 5370 ++count; 5371 } else if (tcam_part->src_dest_class_f1_sel != selector->ter_sel_val) { 5372 return (BCM_E_RESOURCE); 5373 } 5374 break; 5375 case _bcmFieldSliceFpf3SrcDstClassSelect: 5376 if (tcam_part->src_dest_class_f3_sel == _FP_SELCODE_DONT_CARE) { 5377 ++count; 5378 } else if (tcam_part->src_dest_class_f3_sel != selector->ter_sel_val) { 5379 return (BCM_E_RESOURCE); 5380 } 5381 break; 5382 case _bcmFieldSliceOamInterfaceClassSelect: 5383 if (tcam_part->oam_intf_class_sel == _FP_SELCODE_DONT_CARE) { 5384 ++count; 5385 } else if (tcam_part->oam_intf_class_sel != selector->ter_sel_val) { 5386 return (BCM_E_RESOURCE); 5387 } 5388 break; 5389 case _bcmFieldSliceSelEgrClassF6: 5390 if (tcam_part->egr_class_f6_sel == _FP_SELCODE_DONT_CARE) { 5391 ++count; 5392 } else if (tcam_part->egr_class_f6_sel != selector->ter_sel_val) { 5393 return (BCM_E_RESOURCE); 5394 } 5395 break; 5396 default: 5397 return (BCM_E_INTERNAL); 5398 } 5399 5400 *diff_count = count; 5401 5402 return (BCM_E_NONE); 5403 } 5404 5405 5406 /* 5407 * Function: 5408 * _field_slice_is_empty 5409 * 5410 * Purpose: 5411 * Report if a slice has any entries. 5412 * 5413 * Parameters: 5414 * fc - (IN) Field control structure. 5415 * fs - (IN) Slice control structure. 5416 * empty - (OUT) True - slice is empty/False otherwise. 5417 * 5418 * Returns: 5419 * BCM_E_XXX 5420 */ 5421 STATIC int 5422 _field_slice_is_empty(int unit, _field_slice_t *fs, uint8 *empty) 5423 { 5424 int ratio = 1; /* Free to Total entry ratio. */ 5425 5426 /* Input parameters check. */ 5427 if (NULL == fs) { 5428 return (BCM_E_PARAM); 5429 } 5430 5431 if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 5432 ratio = 2; 5433 } 5434 5435 if (fs->entry_count == ratio * fs->free_count) { 5436 *empty = TRUE; 5437 } else { 5438 *empty = FALSE; 5439 } 5440 return (BCM_E_NONE); 5441 } 5442 5443 /* 5444 * Function: 5445 * _bcm_field_group_status_init 5446 * Purpose: 5447 * Initialize bcm_field_group_status_t structure. 5448 * Parameters: 5449 * unit - (IN)BCM unit number. 5450 * entry - (OUT)Initialized field group status structure. 5451 * Retruns: 5452 * BCM_E_XXX 5453 */ 5454 int 5455 _bcm_field_group_status_init(int unit, bcm_field_group_status_t *entry) 5456 { 5457 /* Input parameters check. */ 5458 if (NULL == entry) { 5459 return (BCM_E_PARAM); 5460 } 5461 5462 sal_memset(entry, 0, sizeof(bcm_field_group_status_t)); 5463 5464 entry->prio_min = BCM_FIELD_GROUP_PRIO_ANY; 5465 entry->prio_max = BCM_FIELD_ENTRY_PRIO_HIGHEST; 5466 entry->entries_total = -1; 5467 entry->entries_free = -1; 5468 entry->counters_total = -1; 5469 entry->counters_free = -1; 5470 entry->meters_total = -1; 5471 entry->meters_free = -1; 5472 entry->entry_count = 0; 5473 entry->counter_count = 0; 5474 entry->meter_count = 0; 5475 5476 return (BCM_E_NONE); 5477 } 5478 5479 /* 5480 * Function: 5481 * _bcm_field_stage_entries_free 5482 * Purpose: 5483 * Free entries array for all stage slices. 5484 * Parameters: 5485 * unit - (IN)BCM unit number. 5486 * stage_fc - (IN)Stage field control 5487 * Retruns: 5488 * BCM_E_XXX 5489 */ 5490 int 5491 _bcm_field_stage_entries_free(int unit, _field_stage_t *stage_fc) 5492 { 5493 _field_slice_t *fs; /* Field slice pointer. */ 5494 int idx; /* Slice iteration index. */ 5495 5496 /* Input parameters check */ 5497 if (NULL == stage_fc) { 5498 return (BCM_E_PARAM); 5499 } 5500 /* Deallocate the entry pointers */ 5501 for (idx = 0; idx < stage_fc->tcam_slices; idx++) { 5502 fs = stage_fc->slices[_FP_DEF_INST] + idx; 5503 if (NULL != fs->entries) { 5504 sal_free(fs->entries); 5505 fs->entries = NULL; 5506 } 5507 } 5508 return (BCM_E_NONE); 5509 } 5510 5511 /* 5512 * Function: 5513 * _field_control_get 5514 * Purpose: 5515 * Lookup a FP control config from a bcm device id. 5516 * Parameters: 5517 * unit - (IN)BCM unit number. 5518 * fc - (OUT) Field control structure. 5519 * Retruns: 5520 * BCM_E_XXX 5521 */ 5522 int 5523 _field_control_get(int unit, _field_control_t **fc) 5524 { 5525 /* Input parameters check. */ 5526 if (NULL == fc) { 5527 return (BCM_E_PARAM); 5528 } 5529 5530 /* Make sure system was initialized. */ 5531 FIELD_IS_INIT(unit); 5532 5533 /* Fill field control structure. */ 5534 *fc = _field_control[unit]; 5535 5536 return (BCM_E_NONE); 5537 } 5538 5539 /* 5540 * Function: _field_slice_info_fill 5541 * 5542 * Purpose: 5543 * fill the slice_info structure with group details 5544 * 5545 * Parameters: 5546 * unit - (IN) BCM device number 5547 * fs - (IN) slice pointer 5548 * group_id - (IN) field group ID 5549 * slice_no - (IN) slice no to match 5550 * flag_base - (IN) flag to be set for base slice 5551 * flag_expanded - (IN) flag to be set for expanded slice 5552 * slice_info - (OUT) Slice information 5553 * 5554 * Returns: 5555 * BCM_E_NONE - if given slice number is used by the group 5556 * BCM_E_NOT_FOUND - if given slice number is not used by the group 5557 */ 5558 5559 int 5560 _field_slice_info_fill(int unit, 5561 _field_slice_t *fs, 5562 int group_id, 5563 int slice_no, 5564 int flag_base, 5565 int flag_expanded, 5566 bcm_field_stage_slice_info_t *slice_info) { 5567 int is_not_first = 0; 5568 int group_cnt = 0; 5569 while (fs != NULL) { 5570 if (is_not_first) { 5571 if (fs->slice_number == slice_no) { 5572 slice_info->flags |= flag_expanded; 5573 /* group_cnt points to the next free index 5574 * in slice_groupid_list 5575 */ 5576 group_cnt = slice_info->slice_gid_ct; 5577 slice_info->slice_gid_list[group_cnt] 5578 = group_id; 5579 slice_info->slice_gid_ct += 1; 5580 return BCM_E_NONE; 5581 } 5582 } else { 5583 if (fs->slice_number == slice_no) { 5584 slice_info->flags |= flag_base; 5585 /* group_cnt points to the next free index 5586 * in slice_groupid_list 5587 */ 5588 group_cnt = slice_info->slice_gid_ct; 5589 slice_info->slice_gid_list[group_cnt] 5590 = group_id; 5591 slice_info->slice_gid_ct += 1; 5592 return BCM_E_NONE; 5593 } 5594 is_not_first = 1; 5595 } 5596 fs = fs->next; 5597 } 5598 return (BCM_E_NOT_FOUND); 5599 } 5600 5601 /* 5602 * Function: _bcm_field_stage_slice_count_get 5603 * 5604 * Purpose: 5605 * Return the number of slices in a given stage 5606 * 5607 * Parameters: 5608 * unit - (IN) BCM device number 5609 * stage_id - (IN) Stage ID 5610 * slice_count - (OUT) Number of slices in a given stage 5611 * 5612 * Returns: 5613 * BCM_E_XXX 5614 */ 5615 int 5616 _bcm_field_stage_slice_count_get( 5617 int unit, 5618 bcm_field_stage_t stage_id, 5619 int *slice_count) { 5620 5621 _field_stage_t *stage_fc; 5622 _field_control_t *fc; 5623 _field_stage_id_t stage_id_used; 5624 int rv = BCM_E_NONE; 5625 5626 if (slice_count == NULL) { 5627 return BCM_E_PARAM; 5628 } 5629 5630 if (stage_id == bcmFieldStageIngress) { 5631 stage_id_used = _BCM_FIELD_STAGE_INGRESS; 5632 } else if (stage_id == bcmFieldStageEgress) { 5633 stage_id_used = _BCM_FIELD_STAGE_EGRESS; 5634 } else if (stage_id == bcmFieldStageLookup) { 5635 stage_id_used = _BCM_FIELD_STAGE_LOOKUP; 5636 } else { 5637 return BCM_E_PARAM; 5638 } 5639 5640 rv = _field_control_get(unit, &fc); 5641 BCM_IF_ERROR_RETURN(rv); 5642 5643 rv = _field_stage_control_get (unit, stage_id_used, &stage_fc); 5644 BCM_IF_ERROR_RETURN(rv); 5645 5646 *slice_count = stage_fc->tcam_slices; 5647 5648 return BCM_E_NONE; 5649 } 5650 5651 /* 5652 * Function: _bcm_field_stage_slice_info_get 5653 * 5654 * Purpose: 5655 * Return the details of the stage and entries 5656 * count of the slice for the given portbitmap 5657 * 5658 * Parameters: 5659 * unit - (IN) BCM device number 5660 * stage_id - (IN) Stage ID 5661 * pbmp - (IN) port bitmap of the pipe for 5662 * which the details are required 5663 * slice_no - (IN) slice no to retrieve the info 5664 * slice_info - (OUT) Slice information 5665 * 5666 * Returns: 5667 * BCM_E_XXX 5668 */ 5669 int 5670 _bcm_field_stage_slice_info_get( 5671 int unit, 5672 bcm_field_stage_t stage_id, 5673 bcm_pbmp_t pbmp, 5674 int slice_no, 5675 bcm_field_stage_slice_info_t *slice_info) { 5676 5677 bcm_port_config_t pc; 5678 _field_stage_t *stage_fc; 5679 _field_group_t *fg; 5680 _field_control_t *fc; 5681 _field_slice_t *fs; 5682 _field_stage_id_t stage_id_used; 5683 int indx = 0; 5684 int inst = 0; 5685 int flags = 0; 5686 int rv = BCM_E_NONE; 5687 int temp_rv = BCM_E_NONE; 5688 5689 if (slice_info == NULL) { 5690 return BCM_E_PARAM; 5691 } 5692 5693 if (stage_id == bcmFieldStageIngress) { 5694 stage_id_used = _BCM_FIELD_STAGE_INGRESS; 5695 } else if (stage_id == bcmFieldStageEgress) { 5696 stage_id_used = _BCM_FIELD_STAGE_EGRESS; 5697 } else if (stage_id == bcmFieldStageLookup) { 5698 stage_id_used = _BCM_FIELD_STAGE_LOOKUP; 5699 } else { 5700 return BCM_E_PARAM; 5701 } 5702 5703 rv = _field_control_get(unit, &fc); 5704 BCM_IF_ERROR_RETURN(rv); 5705 5706 rv = _field_stage_control_get (unit, stage_id_used, &stage_fc); 5707 BCM_IF_ERROR_RETURN(rv); 5708 5709 if ((slice_no < 0) || (slice_no >= stage_fc->tcam_slices)) { 5710 return BCM_E_PARAM; 5711 } 5712 5713 if (stage_fc->oper_mode == bcmFieldGroupOperModePipeLocal) { 5714 if (BCM_PBMP_IS_NULL(pbmp)) { 5715 return BCM_E_PARAM; 5716 } 5717 bcm_port_config_t_init(&pc); 5718 rv = bcm_esw_port_config_get(unit, &pc); 5719 BCM_IF_ERROR_RETURN(rv); 5720 5721 for (indx=0; indx < stage_fc->num_pipes; indx++) { 5722 if (BCM_PBMP_IS_NULL(PBMP_PIPE(unit, indx))) { 5723 continue; 5724 } 5725 if (BCM_PBMP_EQ(pbmp, pc.per_pipe[indx])) { 5726 inst = indx; 5727 break; 5728 } 5729 } 5730 if (indx == stage_fc->num_pipes) { 5731 return BCM_E_PARAM; 5732 } 5733 } 5734 sal_memset(slice_info, 0x00, sizeof(bcm_field_stage_slice_info_t)); 5735 fs = stage_fc->slices[inst]; 5736 /* fill slice_info with free and entry count */ 5737 slice_info->free_entries = 5738 fs[slice_no].free_count; 5739 slice_info->total_entries = 5740 fs[slice_no].entry_count; 5741 /* fill slice_info with group details */ 5742 fg = fc->groups; 5743 for (; fg != NULL; fg = fg->next) { 5744 if ((fg->stage_id == stage_id_used) && 5745 (fg->instance == inst)) { 5746 flags = BCM_FIELD_SLICE_ALLOCATED; 5747 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 5748 flags |= BCM_FIELD_SLICE_MODE_TRIPLE; 5749 } else if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 5750 flags |= BCM_FIELD_SLICE_MODE_DOUBLE; 5751 } else if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) { 5752 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 5753 flags |= BCM_FIELD_SLICE_MODE_INTRADOUBLE; 5754 } else { 5755 flags |= BCM_FIELD_SLICE_MODE_SINGLE; 5756 } 5757 } 5758 /* fill slice_info with group primary slices */ 5759 temp_rv = _field_slice_info_fill(unit, 5760 &fg->slices[0], 5761 fg->gid, 5762 slice_no, 5763 flags | BCM_FIELD_SLICE_PART_PRIMARY, 5764 flags | BCM_FIELD_SLICE_PART_PRIMARY_EXPANDED, 5765 slice_info); 5766 5767 /* fill slice_info with group seconday slices */ 5768 if ((temp_rv == BCM_E_NOT_FOUND) && 5769 ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 5770 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE))) { 5771 temp_rv = _field_slice_info_fill(unit, 5772 &fg->slices[1], 5773 fg->gid, 5774 slice_no, 5775 flags | BCM_FIELD_SLICE_PART_SECONDARY, 5776 flags | BCM_FIELD_SLICE_PART_SECONDARY_EXPANDED, 5777 slice_info); 5778 } 5779 /* fill slice_info with group tertiary slices */ 5780 if ((temp_rv == BCM_E_NOT_FOUND) && 5781 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 5782 _field_slice_info_fill(unit, 5783 &fg->slices[2], 5784 fg->gid, 5785 slice_no, 5786 flags | BCM_FIELD_SLICE_PART_TERTIARY, 5787 flags | BCM_FIELD_SLICE_PART_TERTIARY_EXPANDED, 5788 slice_info); 5789 } 5790 } 5791 } 5792 return rv; 5793 } 5794 5795 5796 /* 5797 * Function: 5798 * _field_egr_ports_recovery_control_get 5799 * Purpose: 5800 * Lookup a FP EGR_PORTS_RECOVERY config 5801 * from a bcm device id. 5802 * Parameters: 5803 * unit - (IN) BCM unit number. 5804 * f_egr_recovery - (OUT) Field Egr_ports_recovery 5805 * structure. 5806 * Returns: 5807 * BCM_E_XXX 5808 */ 5809 int 5810 _field_egr_ports_recovery_control_get(int unit, 5811 _field_egr_ports_recovery_t **f_egr_recovery) 5812 { 5813 /* Input parameters check. */ 5814 if (NULL == f_egr_recovery) { 5815 return (BCM_E_PARAM); 5816 } 5817 5818 /* Fill field control structure. */ 5819 *f_egr_recovery = _field_egr_ports_recovery[unit]; 5820 5821 return (BCM_E_NONE); 5822 } 5823 5824 /* 5825 * Function: 5826 * _field_stage_control_get 5827 * Purpose: 5828 * Lookup stage FP control config from bcm device id and 5829 * pipeline stage number. 5830 * Parameters: 5831 * unit - (IN)BCM unit number. 5832 * stage_id - (IN)Pipeline stage id number. 5833 * stage_fc - (OUT) Stage Field control structure. 5834 * Retruns: 5835 * BCM_E_XXX 5836 */ 5837 int 5838 _field_stage_control_get(int unit, _field_stage_id_t stage_id, 5839 _field_stage_t **stage_fc) 5840 { 5841 _field_stage_t *stage_p; /* Stages iteration pointer. */ 5842 5843 FIELD_IS_INIT(unit); \ 5844 5845 /* Input parameters check. */ 5846 if (NULL == stage_fc) { 5847 return (BCM_E_PARAM); 5848 } 5849 5850 /* Check that module was initialized. */ 5851 if (NULL == (_field_control[unit])->stages) { 5852 LOG_ERROR(BSL_LS_BCM_FP, 5853 (BSL_META_U(unit, 5854 "FP(unit %d) Error: Stage (%d) is not initialized.\n"), 5855 unit, stage_id)); 5856 return (BCM_E_INIT); 5857 } 5858 5859 /* Find a stage with stage_id equals to stage. */ 5860 stage_p = (_field_control[unit])->stages; 5861 while (stage_p) { 5862 if (stage_p->stage_id == stage_id) { 5863 break; 5864 } 5865 stage_p = stage_p->next; 5866 } 5867 5868 if (NULL == stage_p) { 5869 if(((_field_control[unit])->flags & _FP_EXTERNAL_PRESENT) || 5870 (_BCM_FIELD_STAGE_EXTERNAL != stage_id)) 5871 { 5872 LOG_INFO(BSL_LS_BCM_FP, 5873 (BSL_META_U(unit, 5874 "FP(unit %d) Verb: Unknown pipeline stage (%d).\n"), 5875 unit, stage_id)); 5876 } 5877 if (_BCM_FIELD_STAGE_EXTERNAL == stage_id) { 5878 return (BCM_E_UNAVAIL); 5879 } else if (_BCM_FIELD_STAGE_EXACTMATCH == stage_id) { 5880 return (BCM_E_UNAVAIL); 5881 } else if (_BCM_FIELD_STAGE_CLASS == stage_id) { 5882 return (BCM_E_UNAVAIL); 5883 } else if (((stage_id == _BCM_FIELD_STAGE_EGRESS) || 5884 (stage_id == _BCM_FIELD_STAGE_LOOKUP)) && 5885 (!soc_feature(unit, soc_feature_field_multi_stage))) { 5886 return (BCM_E_UNAVAIL); 5887 } else { 5888 return (BCM_E_NOT_FOUND); 5889 } 5890 } 5891 5892 /* Fill stage field control structure. */ 5893 *stage_fc = stage_p; 5894 5895 return (BCM_E_NONE); 5896 } 5897 5898 /* 5899 * Function: 5900 * _field_group_get 5901 * Purpose: 5902 * Lookup a group information on specified bcm device. 5903 * Parameters: 5904 * unit - (IN)BCM device number. 5905 * gid - (IN)Group ID. 5906 * Returns: 5907 * BCM_E_XXX 5908 */ 5909 int 5910 _field_group_get(int unit, bcm_field_group_t gid, _field_group_t **group_p) 5911 { 5912 _field_control_t *fc; /* Unit FP control structure. */ 5913 _field_group_t *fg; /* Group information. */ 5914 5915 if (NULL == group_p) { 5916 return (BCM_E_PARAM); 5917 } 5918 5919 /* Get unit FP control structure. */ 5920 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5921 5922 /* Iterate over the groups linked-list looking for a matching Group ID */ 5923 fg = fc->groups; 5924 while (fg != NULL) { 5925 if (fg->gid == gid) { 5926 *group_p = fg; 5927 return (BCM_E_NONE); 5928 } 5929 fg = fg->next; 5930 } 5931 /* Group with id == gid not found. */ 5932 return (BCM_E_NOT_FOUND); 5933 } 5934 5935 /* 5936 * Function: 5937 * _bcm_field_group_id_generate 5938 * 5939 * Purpose: 5940 * Find an unused Group ID. 5941 * 5942 * Parameters: 5943 * unit - BCM device number 5944 * group - (OUT) new Group ID 5945 * 5946 * Returns: 5947 * BCM_E_NONE - Success 5948 * BCM_E_PARAM - null pointer to group 5949 */ 5950 int 5951 _bcm_field_group_id_generate(int unit, bcm_field_group_t *group) 5952 { 5953 _field_group_t *group_p; /* Group info. */ 5954 5955 /* Input parameters check. */ 5956 if (NULL == group) { 5957 LOG_ERROR(BSL_LS_BCM_FP, 5958 (BSL_META_U(unit, 5959 "FP(unit %d) Error: group == NULL\n"), 5960 unit)); 5961 return (BCM_E_PARAM); 5962 } 5963 5964 *group = _FP_ID_BASE; 5965 5966 while (!BCM_FAILURE(_field_group_get(unit, *group, &group_p))) { 5967 (*group)++; 5968 if ((soc_feature(unit, soc_feature_th3_style_fp)) && 5969 (_FP_ID_MAX == (*group))) { 5970 (*group) = _FP_ID_BASE; 5971 } 5972 } 5973 5974 return (BCM_E_NONE); 5975 } 5976 5977 /* 5978 * Function: 5979 * _bcm_field_entry_tcam_parts_count 5980 * Purpose: 5981 * Get number of tcam entries needed to accomodate an entry. 5982 * Parameters: 5983 * unit - (IN) BCM device number. 5984 * group_flags - (IN) Entry group flags. 5985 * count - (OUT) Entry parts count. 5986 * Returns: 5987 * BCM_E_XXX 5988 */ 5989 int 5990 _bcm_field_entry_tcam_parts_count (int unit, _field_stage_id_t stage_id, 5991 uint32 group_flags, int *part_count) 5992 { 5993 /* Input parameters check. */ 5994 if (NULL == part_count) { 5995 return (BCM_E_PARAM); 5996 } 5997 5998 #if defined(BCM_TOMAHAWK_SUPPORT) 5999 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 6000 ((_BCM_FIELD_STAGE_INGRESS == stage_id) || 6001 (_BCM_FIELD_STAGE_EXACTMATCH == stage_id))) { 6002 return _bcm_field_th_entry_tcam_parts_count(unit, group_flags, 6003 part_count); 6004 } 6005 #endif /* BCM_TOMAHAWK_SUPPORT */ 6006 6007 if (group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) { 6008 if ((group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) || 6009 (group_flags & _FP_GROUP_DW_DEPTH_EXPANDED)) { 6010 *part_count = 2; 6011 } else { 6012 *part_count = 1; 6013 } 6014 } else if (group_flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 6015 if (group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 6016 *part_count = 4; 6017 } else { 6018 *part_count = 2; 6019 } 6020 } else if (group_flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 6021 *part_count = 3; 6022 } 6023 6024 return BCM_E_NONE; 6025 } 6026 6027 /* 6028 * Function: 6029 * _bcm_field_lt_entry_tcam_parts_count 6030 * Purpose: 6031 * Get number of lt tcam entries needed to accomodate an entry. 6032 * Parameters: 6033 * unit - (IN) BCM device number. 6034 * stage_id - (IN) Stage Id 6035 * group_flags - (IN) Entry group flags. 6036 * count - (OUT) Entry parts count. 6037 * Returns: 6038 * BCM_E_XXX 6039 */ 6040 int 6041 _bcm_field_lt_entry_tcam_parts_count(int unit, _field_stage_id_t stage_id, 6042 uint32 group_flags, int *part_count) 6043 { 6044 /* Input paramaters check */ 6045 if (NULL == part_count) { 6046 return BCM_E_PARAM; 6047 } 6048 6049 #if defined(BCM_FLOWTRACKER_SUPPORT) 6050 if (stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 6051 return _bcm_field_th_lt_entry_tcam_parts_count(unit, 6052 stage_id, group_flags, part_count); 6053 } else 6054 #endif 6055 { 6056 return _bcm_field_entry_tcam_parts_count(unit, 6057 stage_id, group_flags, part_count); 6058 } 6059 } 6060 6061 /* 6062 * Function: 6063 * _field_entry_action_dirty 6064 * Purpose: 6065 * Check if only action was modified for the entry after last installation 6066 * Parameters: 6067 * unit - (IN) BCM device number. 6068 * f_ent - (IN) Primary entry pointer. 6069 * dirty - (OUT) Entry dirty flag. 6070 * Returns: 6071 * BCM_E_XXX 6072 */ 6073 int 6074 _field_entry_action_dirty(int unit, _field_entry_t *f_ent, int *dirty) 6075 { 6076 int parts_count = 0; /* Entry tcam parts count. */ 6077 int idx; /* Entry parts iterator. */ 6078 int rv; /* Operation return status. */ 6079 6080 /* Input parameters check. */ 6081 if ((NULL == f_ent) || (NULL == dirty)) { 6082 return (BCM_E_PARAM); 6083 } 6084 6085 /* Get number of tcam parts based on group flags. */ 6086 rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id, 6087 f_ent->group->flags, &parts_count); 6088 BCM_IF_ERROR_RETURN(rv); 6089 6090 /* Check entry dirty and action only dirty for all parts of the entry */ 6091 for (idx = 0; idx < parts_count; idx++) { 6092 LOG_DEBUG(BSL_LS_BCM_FP, 6093 (BSL_META_U(unit, 6094 "FP(unit %d) vverb: _field_entry_action_dirty() Part:%x EntryDirty:%x ActionOnlyDirty:%x\n"), 6095 unit, idx, (f_ent[idx].flags & (_FP_ENTRY_DIRTY)), 6096 (f_ent[idx].flags & (_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY)))); 6097 /* 6098 * If entry dirty is set and action only dirty is not set, 6099 * it is likely a qualifier change, return FALSE. 6100 */ 6101 if ((f_ent[idx].flags & _FP_ENTRY_DIRTY) && 6102 (0 == (f_ent[idx].flags & _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY))) { 6103 *dirty = FALSE; 6104 return (BCM_E_NONE); 6105 } 6106 6107 if ((f_ent[idx].flags & _FP_ENTRY_DIRTY) && 6108 (f_ent[idx].flags & _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY)) { 6109 *dirty = TRUE; 6110 } 6111 } 6112 6113 return (BCM_E_NONE); 6114 } 6115 6116 /* 6117 * Function: 6118 * _field_entry_dirty 6119 * Purpose: 6120 * Check if entry was modified after last installation 6121 * Parameters: 6122 * unit - (IN) BCM device number. 6123 * f_ent - (IN) Primary entry pointer. 6124 * dirty - (OUT) Entry dirty flag. 6125 * Returns: 6126 * BCM_E_XXX 6127 */ 6128 int 6129 _field_entry_dirty(int unit, _field_entry_t *f_ent, int *dirty) 6130 { 6131 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 6132 _field_policer_t *f_pl; /* Field policer descriptor. */ 6133 int parts_count = 0; /* Entry tcam parts count. */ 6134 int idx; /* Entry parts iterator. */ 6135 int rv; /* Operation return status. */ 6136 6137 /* Input parameters check. */ 6138 if ((NULL == f_ent) || (NULL == dirty)) { 6139 return (BCM_E_PARAM); 6140 } 6141 6142 /* Get number of tcam parts based on group flags. */ 6143 rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id, 6144 f_ent->group->flags, &parts_count); 6145 BCM_IF_ERROR_RETURN(rv); 6146 6147 /* If any entry part was changed - reinstall is required. */ 6148 for (idx = 0; idx < parts_count; idx++) { 6149 if (f_ent[idx].flags & _FP_ENTRY_DIRTY) { 6150 break; 6151 } 6152 } 6153 *dirty = (idx < parts_count) ? TRUE : FALSE; 6154 6155 if (0 == (*dirty)) { 6156 /* Policer configuration updates check. */ 6157 for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) { 6158 f_ent_pl = f_ent->policer + idx; 6159 /* Skip invalid policers. */ 6160 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 6161 continue; 6162 } 6163 /* Read policer configuration.*/ 6164 rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl); 6165 BCM_IF_ERROR_RETURN(rv); 6166 6167 /* Check if policer was modified. */ 6168 if (f_pl->hw_flags & _FP_POLICER_DIRTY) { 6169 *dirty = TRUE; 6170 break; 6171 } 6172 } 6173 } 6174 return (BCM_E_NONE); 6175 } 6176 6177 /* 6178 * Function: 6179 * _bcm_field_entry_flags_to_tcam_part 6180 * Purpose: 6181 * Each field entry contains up to 4 TCAM 6182 * entries. This routine maps sw entry flags 6183 * to tcam entry (0-3). 6184 * Note this is not a physical address in tcam. 6185 * Single: 0 6186 * Single & Intraslice Double: 0, 1 6187 * Paired: 0, 1 6188 * Paired & Intraslice Double: 0, 1, 2, 3 6189 * Triple: 0, 1, 2 6190 * Parameters: 6191 * unit - (IN) Device number. 6192 * entry_flags - (IN) Entry flags. 6193 * fg - (IN) Entry group structure. 6194 * entry_part - (OUT) Entry part (0-3) 6195 * Returns: 6196 * BCM_E_NONE - Success 6197 * BCM_E_INTERNAL - Error 6198 */ 6199 int 6200 _bcm_field_entry_flags_to_tcam_part (int unit, uint32 entry_flags, 6201 _field_group_t *fg, 6202 uint8 *entry_part) 6203 { 6204 /* Input parameters check. */ 6205 if (NULL == entry_part || NULL == fg) { 6206 return (BCM_E_PARAM); 6207 } 6208 #if defined(BCM_TOMAHAWK_SUPPORT) 6209 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 6210 (_BCM_FIELD_STAGE_INGRESS == fg->stage_id)) { 6211 return _bcm_field_th_entry_flags_to_tcam_part(unit, entry_flags, 6212 fg->flags, 6213 entry_part); 6214 } 6215 #endif /* BCM_TOMAHAWK_SUPPORT */ 6216 if (entry_flags & _FP_ENTRY_PRIMARY) { 6217 if (entry_flags & _FP_ENTRY_SECOND_HALF) { 6218 *entry_part = 1; 6219 } else { 6220 *entry_part = 0; 6221 } 6222 } else if (entry_flags & _FP_ENTRY_SECONDARY) { 6223 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 6224 if (entry_flags & _FP_ENTRY_SECOND_HALF) { 6225 *entry_part = 3; 6226 } else { 6227 *entry_part = 2; 6228 } 6229 } else { 6230 *entry_part= 1; 6231 } 6232 } else if (entry_flags & _FP_ENTRY_TERTIARY) { 6233 *entry_part = 2; 6234 } else { 6235 return (BCM_E_INTERNAL); 6236 } 6237 return BCM_E_NONE; 6238 } 6239 6240 /* 6241 * Function: 6242 * _bcm_field_tcam_part_to_entry_flags 6243 * Purpose: 6244 * Each field entry contains up to 4 TCAM 6245 * entries. This routine maps tcam entry (0-3) 6246 * to SW entry flags. 6247 * Single: 0 6248 * Single & Intraslice Double: 0, 1 6249 * Paired: 0, 1 6250 * Paired & Intraslice Double: 0, 1, 2, 3 6251 * Triple: 0, 1, 2 6252 * Retrieve the part of the group entry resides in. 6253 * Parameters: 6254 * unit - (IN) Device number. 6255 * entry_part - (IN) Entry Part number. 6256 * fg - (IN) Group Structure. 6257 * entry_flags - (OUT) Entry Flags. 6258 * Returns: 6259 * BCM_E_NONE - Success 6260 * BCM_E_INTERNAL - Error 6261 */ 6262 int 6263 _bcm_field_tcam_part_to_entry_flags(int unit, int entry_part, 6264 _field_group_t *fg, 6265 uint32 *entry_flags) 6266 { 6267 /* Input parameters check. */ 6268 if (NULL == entry_flags || NULL == fg) { 6269 return (BCM_E_PARAM); 6270 } 6271 6272 #if defined(BCM_TOMAHAWK_SUPPORT) 6273 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 6274 ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || 6275 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id))) { 6276 return _bcm_field_th_tcam_part_to_entry_flags(unit, entry_part, 6277 fg->flags, 6278 entry_flags); 6279 } 6280 #endif /* BCM_TOMAHAWK_SUPPORT */ 6281 6282 switch (entry_part) { 6283 case 0: 6284 *entry_flags = _FP_ENTRY_PRIMARY | 6285 _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT; 6286 break; 6287 case 1: 6288 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 6289 *entry_flags = _FP_ENTRY_PRIMARY | 6290 _FP_ENTRY_SECOND_HALF; 6291 } else if (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) { 6292 *entry_flags = _FP_ENTRY_PRIMARY | 6293 _FP_ENTRY_SECOND_HALF | 6294 _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT; 6295 } else { 6296 *entry_flags = _FP_ENTRY_SECONDARY; 6297 } 6298 break; 6299 case 2: 6300 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 6301 *entry_flags = _FP_ENTRY_SECONDARY | 6302 _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT; 6303 } else { 6304 *entry_flags = _FP_ENTRY_TERTIARY | 6305 _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT; 6306 } 6307 break; 6308 case 3: 6309 *entry_flags = _FP_ENTRY_SECONDARY | _FP_ENTRY_SECOND_HALF; 6310 break; 6311 default: 6312 return (BCM_E_INTERNAL); 6313 } 6314 return (BCM_E_NONE); 6315 } 6316 6317 6318 /* 6319 * Function: 6320 * _bcm_field_tcam_part_to_slice_number 6321 * Purpose: 6322 * Each field entry contains up to 4 TCAM 6323 * entries. This routine maps tcam entry (0-3) 6324 * to a slice number 6325 * Parameters: 6326 * unit - (IN) Unit 6327 * entry_part - (IN) Entry Part number. 6328 * fg - (IN) Field Group Structure. 6329 * slice_number - (OUT) Slice number (0-2) 6330 * Returns: 6331 * BCM_E_XXX 6332 */ 6333 int 6334 _bcm_field_tcam_part_to_slice_number(int unit, 6335 int entry_part, 6336 _field_group_t *fg, 6337 uint8 *slice_number) 6338 { 6339 /* Input parameters check. */ 6340 if (NULL == slice_number || NULL == fg) { 6341 return (BCM_E_PARAM); 6342 } 6343 6344 #if defined(BCM_TOMAHAWK_SUPPORT) 6345 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 6346 (_BCM_FIELD_STAGE_INGRESS == fg->stage_id)) { 6347 return _bcm_field_th_tcam_part_to_slice_number(entry_part, fg->flags, 6348 slice_number); 6349 } 6350 #endif /* BCM_TOMAHAWK_SUPPORT */ 6351 6352 switch (entry_part) { 6353 case 0: 6354 *slice_number = 0; 6355 break; 6356 case 1: 6357 if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) || 6358 (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED)) { 6359 *slice_number = 0; 6360 } else { 6361 *slice_number = 1; 6362 } 6363 break; 6364 case 2: 6365 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 6366 *slice_number = 1; 6367 } else { 6368 *slice_number = 2; 6369 } 6370 break; 6371 case 3: 6372 *slice_number = 1; 6373 break; 6374 default: 6375 return (BCM_E_INTERNAL); 6376 } 6377 return (BCM_E_NONE); 6378 } 6379 6380 /* 6381 * Function: 6382 * _field_entry_slice_idx_change 6383 * Purpose: 6384 * Move the software entry to a new slice index. 6385 * Parmeters: 6386 * unit - (IN) BCM device number. 6387 * f_ent - (IN/OUT) Field entry to be moved. 6388 * amount - (IN) Number of indexes to move + or -. 6389 * Returns: 6390 * BCM_E_XXX 6391 */ 6392 STATIC int 6393 _field_entry_slice_idx_change(int unit, _field_entry_t *f_ent, 6394 int parts_count, int *tcam_idx_new) 6395 { 6396 _field_slice_t *fs; /* Field slice control structure. */ 6397 _field_stage_t *stage_fc; /* Stage field control structure. */ 6398 int new_slice_numb = 0; /* Entry new slice number. */ 6399 int new_slice_idx = 0; /* Entry new offset in the slice */ 6400 int instance; /* Pipe Instance. */ 6401 int idx; /* Iteration index. */ 6402 int rv; /* Operation return status. */ 6403 6404 /* Input parameters check. */ 6405 if (NULL == f_ent) { 6406 return (BCM_E_PARAM); 6407 } 6408 6409 if ((NULL == f_ent->group) || (NULL == f_ent->fs)) { 6410 return (BCM_E_PARAM); 6411 } 6412 6413 /* Get stage control structure. */ 6414 rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc); 6415 BCM_IF_ERROR_RETURN(rv); 6416 6417 /* Retrieve instance */ 6418 instance = f_ent->group->instance; 6419 6420 for (idx = 0; idx < parts_count; idx++) { 6421 /* Get slice control structure. */ 6422 fs = f_ent[idx].fs; 6423 6424 /* Move the software entry to the new index. */ 6425 if (prio_set_with_no_free_entries[unit] == FALSE) { 6426 fs->entries[f_ent[idx].slice_idx] = NULL; 6427 } 6428 6429 #if defined(BCM_TOMAHAWK_SUPPORT) 6430 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 6431 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 6432 rv = _bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc, 6433 f_ent, 6434 tcam_idx_new[idx], 6435 &new_slice_numb, 6436 &new_slice_idx); 6437 } else 6438 #endif /* BCM_TOMAHAWK_SUPPORT */ 6439 { 6440 /* Calculate entry new slice & offset in the slice. */ 6441 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, 6442 instance, 6443 tcam_idx_new[idx], 6444 &new_slice_numb, 6445 &new_slice_idx); 6446 } 6447 BCM_IF_ERROR_RETURN(rv); 6448 6449 /* If entry moves across the slices update free/used counters. */ 6450 if ((f_ent[idx].fs->slice_number != new_slice_numb) && 6451 (0 == (f_ent[idx].flags & _FP_ENTRY_SECOND_HALF))) { 6452 fs->free_count++; 6453 stage_fc->slices[instance][new_slice_numb].free_count--; 6454 } 6455 6456 /* Update entry structure. */ 6457 stage_fc->slices[instance][new_slice_numb].entries[new_slice_idx] 6458 = f_ent + idx; 6459 f_ent[idx].fs = &stage_fc->slices[instance][new_slice_numb]; 6460 f_ent[idx].slice_idx = new_slice_idx; 6461 } 6462 6463 return (BCM_E_NONE); 6464 } 6465 6466 /* 6467 * Function: 6468 * _field_entry_t_compare 6469 * Purpose: 6470 * Compare entry id in _field_entry_t structure. 6471 * Parameters: 6472 * b - (IN) first compared qualifier. 6473 * a - (IN) second compared qualifier. 6474 * Returns: 6475 * a<=>b 6476 */ 6477 static INLINE int 6478 _field_entry_t_compare(void *a, void *b) 6479 { 6480 _field_entry_t **first; /* First compared entry. */ 6481 _field_entry_t **second; /* Second compared entry. */ 6482 6483 first = (_field_entry_t **)a; 6484 second = (_field_entry_t **)b; 6485 6486 if ((*first)->eid < (*second)->eid) { 6487 return (-1); 6488 } else if ((*first)->eid > (*second)->eid) { 6489 return (1); 6490 } 6491 return (0); 6492 } 6493 6494 /* 6495 * Function: 6496 * _field_entry_get 6497 * Purpose: 6498 * Lookup a FP rule(entry) from a unit ID and slice & rule id choice. 6499 * Parmeters: 6500 * unit - (IN)BCM device number. 6501 * eid - (IN)Entry id. 6502 * flags - (IN)Entry flags to match. 6503 * entry_p - (OUT) Entry lookup result. 6504 * Returns: 6505 * BCM_E_XXX 6506 */ 6507 int 6508 _field_entry_get(int unit, bcm_field_entry_t eid, uint32 flags, 6509 _field_entry_t **entry_p) 6510 { 6511 _field_entry_t target; /* Entry lookup pointer. */ 6512 _field_entry_t *f_ent; /* Entry lookup pointer. */ 6513 _field_control_t *fc; /* Field control structure. */ 6514 _field_group_t *fg; /* Field group iterator. */ 6515 uint8 entry_part = 0; /* Wide entry part number. */ 6516 int idx; /* Entry index. */ 6517 6518 /* Input parameters check. */ 6519 if (NULL == entry_p) { 6520 return (BCM_E_PARAM); 6521 } 6522 6523 /* Reset target entry */ 6524 target.eid = eid; 6525 f_ent = ⌖ 6526 6527 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 6528 6529 fg = fc->groups; 6530 while (NULL != fg) { 6531 /* Skip empty groups. */ 6532 if (NULL == fg->entry_arr) { 6533 fg = fg->next; 6534 continue; 6535 } 6536 idx = _shr_bsearch(fg->entry_arr, fg->group_status.entry_count, 6537 sizeof(_field_entry_t *), (void *)&f_ent, 6538 _field_entry_t_compare); 6539 if (idx >= 0) { 6540 (void)_bcm_field_entry_flags_to_tcam_part(unit, flags, 6541 fg, 6542 &entry_part); 6543 *entry_p = fg->entry_arr[idx] + entry_part; 6544 return (BCM_E_NONE); 6545 } 6546 fg = fg->next; 6547 } 6548 /* Rule with id == eid not found. */ 6549 return (BCM_E_NOT_FOUND); 6550 } 6551 6552 /* 6553 * Function: 6554 * _field_group_entry_add 6555 * Purpose: 6556 * Insert an entry to field group entry array. 6557 * Parmeters: 6558 * unit - (IN)BCM device number. 6559 * fg - (IN)Field group structure. 6560 * f_ent - (IN)Inserted entry structure. 6561 * Returns: 6562 * BCM_E_XXX 6563 */ 6564 int 6565 _field_group_entry_add (int unit, _field_group_t *fg, 6566 _field_entry_t *f_ent) 6567 { 6568 _field_entry_t **f_ent_arr; /* Field group entry array.*/ 6569 int mem_sz; /* Memory size. */ 6570 int idx; /* Entry insertion index. */ 6571 int tmp; /* Temporary iterator. */ 6572 6573 /* Input parameters check */ 6574 if ((NULL == fg) || (NULL == f_ent)) { 6575 return (BCM_E_PARAM); 6576 } 6577 6578 /* Verify if entry already present in the group . */ 6579 if (NULL != fg->entry_arr) { 6580 idx = _shr_bsearch(fg->entry_arr, fg->group_status.entry_count, 6581 sizeof (_field_entry_t *), &f_ent, 6582 _field_entry_t_compare); 6583 /* Entry already IN. */ 6584 if (idx >= 0) { 6585 return (BCM_E_NONE); 6586 } 6587 } else { 6588 idx = -1; /* Insert into 0 location. */ 6589 } 6590 6591 /* Check if group has enough room for new entry */ 6592 if (fg->group_status.entry_count + 1 > 6593 fg->ent_block_count * _FP_GROUP_ENTRY_ARR_BLOCK) { 6594 6595 mem_sz = _FP_GROUP_ENTRY_ARR_BLOCK * (fg->ent_block_count + 1) * 6596 sizeof(_field_entry_t *); 6597 6598 f_ent_arr = NULL; 6599 6600 _FP_XGS3_ALLOC(f_ent_arr, mem_sz, "field group entries array"); 6601 if (NULL == f_ent_arr) { 6602 return (BCM_E_MEMORY); 6603 } 6604 /* Copy original array to newly allocated one. */ 6605 if (NULL != fg->entry_arr) { 6606 mem_sz = _FP_GROUP_ENTRY_ARR_BLOCK * (fg->ent_block_count) * 6607 sizeof(_field_entry_t *); 6608 sal_memcpy(f_ent_arr, fg->entry_arr, mem_sz); 6609 6610 sal_free (fg->entry_arr); 6611 } 6612 fg->entry_arr = f_ent_arr; 6613 fg->ent_block_count++; 6614 } 6615 /* Make room for inserted entry */ 6616 idx = (((-1) * idx) - 1); 6617 tmp = fg->group_status.entry_count - 1; 6618 while (tmp >= idx) { 6619 /* coverity[var_deref_op : FALSE] */ 6620 fg->entry_arr[tmp + 1] = fg->entry_arr[tmp]; 6621 tmp--; 6622 } 6623 fg->entry_arr[idx] = f_ent; 6624 fg->group_status.entry_count++; 6625 return (BCM_E_NONE); 6626 } 6627 6628 6629 /* 6630 * Function: 6631 * _field_group_entry_delete 6632 * Purpose: 6633 * Remove an entry from field group entry array. 6634 * Parmeters: 6635 * unit - (IN)BCM device number. 6636 * fg - (IN)Field group structure. 6637 * f_ent - (IN)Removed entry structure. 6638 * Returns: 6639 * BCM_E_XXX 6640 */ 6641 int 6642 _field_group_entry_delete(int unit, _field_group_t *fg, 6643 _field_entry_t *f_ent) 6644 { 6645 int idx; /* Entry insertion index. */ 6646 int tmp; /* Temporary iterator. */ 6647 6648 /* Input parameters check */ 6649 if ((NULL == fg) || (NULL == f_ent)) { 6650 return (BCM_E_PARAM); 6651 } 6652 6653 /* Make sure group entry array was not deallocated. */ 6654 if (NULL == fg->entry_arr) { 6655 return (BCM_E_INTERNAL); 6656 } 6657 6658 /* Verify if entry already present in the group . */ 6659 idx = _shr_bsearch(fg->entry_arr, fg->group_status.entry_count, 6660 sizeof (_field_entry_t *), &f_ent, 6661 _field_entry_t_compare); 6662 if (idx < 0) { 6663 return (BCM_E_NOT_FOUND); 6664 } 6665 6666 /* Make room for inserted entry */ 6667 tmp = idx; 6668 while (tmp < fg->group_status.entry_count - 1) { 6669 fg->entry_arr[tmp] = fg->entry_arr[tmp + 1]; 6670 tmp++; 6671 } 6672 fg->group_status.entry_count--; 6673 fg->entry_arr[fg->group_status.entry_count] = NULL; 6674 return (BCM_E_NONE); 6675 } 6676 6677 /* 6678 * Function: 6679 * _bcm_field_entry_get_by_id 6680 * Purpose: 6681 * Lookup a complete FP rule(entry) from a unit & rule id choice. 6682 * Parmeters: 6683 * unit - (IN)BCM device number. 6684 * eid - (IN)Entry id. 6685 * entry_arr - (OUT) Entry lookup result array. (Array of pointers to 6686 * primary/secondary/teriary ... parts of entry. 6687 * Returns: 6688 * BCM_E_XXX 6689 */ 6690 int 6691 _bcm_field_entry_get_by_id(int unit, bcm_field_entry_t eid, 6692 _field_entry_t **entry_arr) 6693 { 6694 int rv; /* Operation return status. */ 6695 6696 /* Input parameters check. */ 6697 if (NULL == entry_arr) { 6698 return (BCM_E_PARAM); 6699 } 6700 6701 /* Initialize entry array. */ 6702 *entry_arr = NULL; 6703 6704 /* Extract primary entry. */ 6705 rv = _field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, entry_arr); 6706 6707 return (rv); 6708 } 6709 6710 /* 6711 * Function: 6712 * _bcm_field_entry_qual_get 6713 * 6714 * Purpose: 6715 * Lookup a _field_entry_t from a unit ID taking into account mode. Since 6716 * double and triple-wide modes can have multiple physical entries with the 6717 * same Entry ID, 6718 * 6719 * Parmeters: 6720 * unit - (IN)BCM device number. 6721 * eid - (IN)Entry id. 6722 * qual - (IN)Qualifier used to select the correct slice 6723 * entry_p - (OUT)Lookup result entry. 6724 * 6725 * Returns: 6726 * BCM_E_XXX 6727 */ 6728 int 6729 _bcm_field_entry_qual_get(int unit, bcm_field_entry_t entry, 6730 int qual, _field_entry_t **entry_p) 6731 { 6732 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 6733 int parts_count = 0; /* Number of entry parts. */ 6734 uint8 entry_type; /* Index to tcam entries of 6735 multiple types */ 6736 int part_idx; /* Entry parts iteration index. */ 6737 int qual_idx; /* Part qualifiers iteration index.*/ 6738 uint8 found; /* Entry lookup flags. */ 6739 _field_group_t *fg; /* FP group info structure. */ 6740 int rv; /* Operation return status. */ 6741 6742 LOG_DEBUG(BSL_LS_BCM_FP, 6743 (BSL_META_U(unit, 6744 "_bcm_field_entry_qual_get\n"))); 6745 6746 /* Input parameters check. */ 6747 if (NULL == entry_p) { 6748 return (BCM_E_PARAM); 6749 } 6750 6751 /* Initialization. */ 6752 found = FALSE; 6753 6754 /* Search the entry by eid. */ 6755 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, entry_p); 6756 BCM_IF_ERROR_RETURN(rv); 6757 6758 fg = (*entry_p)->group; 6759 if (NULL == fg) { 6760 return (BCM_E_INTERNAL); 6761 } 6762 6763 /* If it's an external slice, then the qualifier has to be in the primary 6764 * entry, since that's the only entry it has. */ 6765 if (fg->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 6766 return (BCM_E_NONE); 6767 } 6768 6769 #if defined(BCM_TOMAHAWK_SUPPORT) 6770 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 6771 (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) { 6772 return (BCM_E_NONE); 6773 } 6774 #endif /* BCM_TOMAHAWK_SUPPORT */ 6775 6776 /* Get number of entry parts we have to read. */ 6777 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 6778 fg->flags, &parts_count); 6779 BCM_IF_ERROR_RETURN(rv); 6780 6781 entry_type = _FP_ENTRY_TYPE_DEFAULT; 6782 6783 /* Iterate over all entry parts. */ 6784 for (part_idx = 0; part_idx < parts_count; part_idx++) { 6785 /* Get part qualifiers array. */ 6786 q_arr = &(fg->qual_arr[entry_type][part_idx]); 6787 /* Search array by qualifier id. */ 6788 for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) { 6789 if ((uint16)qual == q_arr->qid_arr[qual_idx]) { 6790 found = TRUE; 6791 break; 6792 } 6793 } 6794 if (found) { 6795 break; 6796 } 6797 } 6798 6799 /* Check lookup status. */ 6800 if (FALSE == found) { 6801 return (BCM_E_NOT_FOUND); 6802 } 6803 6804 *entry_p += part_idx; 6805 return (BCM_E_NONE); 6806 } 6807 6808 #if defined(BCM_TRIDENT2_SUPPORT) 6809 /* 6810 * Function: 6811 * _bcm_field_efp_entry_qual_get 6812 * 6813 * Purpose: 6814 * Lookup a _field_entry_t from a unit ID taking into account mode. Since 6815 * double and triple-wide modes can have multiple physical entries with the 6816 * same Entry ID, 6817 * 6818 * Parmeters: 6819 * unit - (IN)BCM device number. 6820 * eid - (IN)Entry id. 6821 * qual - (IN)Qualifier used to select the correct slice 6822 * entry_p - (OUT)Lookup result entry. 6823 * 6824 * Returns: 6825 * BCM_E_XXX 6826 */ 6827 int 6828 _bcm_field_efp_entry_qual_get(int unit, bcm_field_entry_t entry, 6829 int qual, _field_entry_t **entry_p) 6830 { 6831 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 6832 int parts_count = 0; /* Number of entry parts. */ 6833 uint8 entry_type; /* Index to tcam entries of 6834 multiple types */ 6835 int part_idx; /* Entry parts iteration index. */ 6836 int qual_idx; /* Part qualifiers iteration index.*/ 6837 uint8 found; /* Entry lookup flags. */ 6838 _field_group_t *fg; /* FP group info structure. */ 6839 int rv; /* Operation return status. */ 6840 6841 LOG_DEBUG(BSL_LS_BCM_FP, 6842 (BSL_META_U(unit, 6843 "_bcm_field_efp_entry_qual_get\n"))); 6844 6845 /* Input parameters check. */ 6846 if (NULL == entry_p) { 6847 return (BCM_E_PARAM); 6848 } 6849 6850 /* Initialization. */ 6851 found = FALSE; 6852 6853 /* Search the entry by eid. */ 6854 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, entry_p); 6855 BCM_IF_ERROR_RETURN(rv); 6856 6857 fg = (*entry_p)->group; 6858 if (NULL == fg) { 6859 return (BCM_E_INTERNAL); 6860 } 6861 6862 if (!(SOC_IS_TD2_TT2(unit) && 6863 (_BCM_FIELD_STAGE_EGRESS == fg->stage_id))) { 6864 return (BCM_E_INTERNAL); 6865 } 6866 6867 /* Get number of entry parts we have to read. */ 6868 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 6869 fg->flags, &parts_count); 6870 BCM_IF_ERROR_RETURN(rv); 6871 6872 if ((*entry_p)->efp_key_match_type) { 6873 entry_type = _FP_ENTRY_TYPE_1; 6874 } else { 6875 entry_type = _FP_ENTRY_TYPE_0; 6876 } 6877 6878 /* Iterate over all entry parts. */ 6879 for (part_idx = 0; part_idx < parts_count; part_idx++) { 6880 /* Get part qualifiers array. */ 6881 q_arr = &(fg->qual_arr[entry_type][part_idx]); 6882 /* Search array by qualifier id. */ 6883 for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) { 6884 if ((uint16)qual == q_arr->qid_arr[qual_idx]) { 6885 found = TRUE; 6886 break; 6887 } 6888 } 6889 if (found) { 6890 break; 6891 } 6892 } 6893 6894 /* Check lookup status. */ 6895 if (FALSE == found) { 6896 return (BCM_E_NOT_FOUND); 6897 } 6898 6899 *entry_p += part_idx; 6900 return (BCM_E_NONE); 6901 } 6902 #endif 6903 6904 /* 6905 * Function: 6906 * _bcm_field_policer_get 6907 * Purpose: 6908 * Lookup a Policer description structure by policer id. 6909 * Parmeters: 6910 * unit - (IN)BCM device number. 6911 * pid - (IN)Policer id. 6912 * policer_p - (OUT) Policer lookup result. 6913 * Returns: 6914 * BCM_E_XXX 6915 */ 6916 int 6917 _bcm_field_policer_get(int unit, bcm_policer_t pid, 6918 _field_policer_t **policer_p) 6919 { 6920 _field_policer_t *f_pl; /* Policer lookup pointer. */ 6921 _field_control_t *fc; /* Field control structure. */ 6922 uint32 hash_index; /* Entry hash. */ 6923 6924 /* Input parameters check. */ 6925 if (NULL == policer_p) { 6926 return (BCM_E_PARAM); 6927 } 6928 6929 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 6930 6931 hash_index = pid & _FP_HASH_INDEX_MASK(fc); 6932 f_pl = fc->policer_hash[hash_index]; 6933 while (NULL != f_pl) { 6934 /* Match entry id. */ 6935 if (f_pl->pid == pid) { 6936 *policer_p = f_pl; 6937 return (BCM_E_NONE); 6938 } 6939 f_pl = f_pl->next; 6940 } 6941 6942 /* Policer with pid == pid was not found. */ 6943 return (BCM_E_NOT_FOUND); 6944 } 6945 6946 /* 6947 * Function: 6948 * _field_policer_destroy2 6949 * Purpose: 6950 * Deinitialize a policer entry. 6951 * Parameters: 6952 * unit - (IN) Unit number. 6953 * fc - (IN) Field control structure. 6954 * f_pl - (IN) Internal policer descriptor. 6955 * Returns: 6956 * BCM_E_XXX 6957 * Notes: 6958 */ 6959 int 6960 _field_policer_destroy2(int unit, _field_control_t *fc, 6961 _field_policer_t *f_pl) 6962 { 6963 /* Input parameters check. */ 6964 if ((NULL == fc) || (NULL == f_pl)) { 6965 return (BCM_E_PARAM); 6966 } 6967 6968 /* Reject destroy if policer is in use. */ 6969 if (f_pl->sw_ref_count > 1) { 6970 return (BCM_E_BUSY); 6971 } 6972 6973 /* Remove policer for lookup hash. */ 6974 _FP_HASH_REMOVE(fc->policer_hash, _field_policer_t, f_pl, 6975 (f_pl->pid & _FP_HASH_INDEX_MASK(fc))); 6976 6977 6978 /* De-allocate policer descriptor. */ 6979 sal_free(f_pl); 6980 6981 /* Decrement number of active policers. */ 6982 if (fc->policer_count > 0) { 6983 fc->policer_count--; 6984 } 6985 return (BCM_E_NONE); 6986 } 6987 6988 /* 6989 * Function: 6990 * _field_policer_destroy 6991 * Purpose: 6992 * Deinitialize a policer entry. 6993 * Parameters: 6994 * unit - (IN) Unit number. 6995 * pid - (IN) Policer id. 6996 * Returns: 6997 * BCM_E_XXX 6998 * Notes: 6999 */ 7000 int 7001 _field_policer_destroy(int unit, bcm_policer_t pid) 7002 { 7003 _field_control_t *fc; /* Field control structure. */ 7004 _field_policer_t *f_pl; /* Internal policer descriptor. */ 7005 int rv; /* Operation return status. */ 7006 7007 /* Get field control structure. */ 7008 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7009 7010 /* Find policer info. */ 7011 rv = _bcm_field_policer_get(unit, pid, &f_pl); 7012 if (BCM_FAILURE(rv)) { 7013 return (rv); 7014 } 7015 7016 return _field_policer_destroy2(unit, fc, f_pl); 7017 } 7018 7019 /* 7020 * Function: 7021 * _field_policer_hw_flags_set 7022 * Purpose: 7023 * Update policer installation is required flag. 7024 * Parameters: 7025 * unit - (IN) Unit number. 7026 * f_pl - (IN/OUT) Internal policer descriptor. 7027 * flags - (IN) Internal flags. 7028 * Returns: 7029 * BCM_E_XXX 7030 * Notes: 7031 */ 7032 int 7033 _field_policer_hw_flags_set(int unit, _field_policer_t *f_pl, uint32 flags) 7034 { 7035 /* Input parameters check. */ 7036 if (NULL == f_pl) { 7037 return (BCM_E_PARAM); 7038 } 7039 7040 f_pl->hw_flags |= flags; 7041 7042 switch (f_pl->cfg.mode) { 7043 case bcmPolicerModeSrTcm: 7044 case bcmPolicerModeTrTcm: 7045 case bcmPolicerModeTrTcmDs: 7046 case bcmPolicerModeCoupledTrTcmDs: 7047 case bcmPolicerModeSrTcmModified: 7048 case bcmPolicerModeSrTcmTsn: 7049 case bcmPolicerModeCommitted: 7050 f_pl->hw_flags |= _FP_POLICER_DIRTY; 7051 break; 7052 default: 7053 return (BCM_E_UNAVAIL); 7054 } 7055 return (BCM_E_NONE); 7056 } 7057 7058 /* 7059 * Function: 7060 * _field_policer_id_alloc 7061 * Purpose: 7062 * Allocate a policer id. 7063 * Parameters: 7064 * unit - (IN) BCM device number. 7065 * pid - (OUT) Policer id. 7066 * Returns: 7067 * BCM_E_XXX 7068 * Notes: 7069 */ 7070 int 7071 _field_policer_id_alloc(int unit, bcm_policer_t *pid) 7072 { 7073 int max_count; /* Maximum number of pid to try.*/ 7074 _field_policer_t *f_pl; /* Field policer descriptor. */ 7075 int rv; /* Operation return status. */ 7076 static uint32 last_allocated_pid = 0; /* Policer id alloc tracker. */ 7077 7078 /* Input parameters check. */ 7079 if (NULL == pid) { 7080 return (BCM_E_PARAM); 7081 } 7082 7083 max_count = _FP_ID_MAX; 7084 while (max_count--) { 7085 last_allocated_pid++; 7086 if (_FP_ID_MAX == last_allocated_pid) { 7087 last_allocated_pid = _FP_ID_BASE; 7088 } 7089 rv = _bcm_field_policer_get(unit, last_allocated_pid, &f_pl); 7090 if (BCM_E_NOT_FOUND == rv) { 7091 *pid = last_allocated_pid; 7092 return (BCM_E_NONE); 7093 } 7094 if (BCM_FAILURE(rv)) { 7095 return (rv); 7096 } 7097 } 7098 return (BCM_E_RESOURCE); 7099 } 7100 7101 7102 /* 7103 * Function: 7104 * _field_policer_mode_support 7105 * Purpose: 7106 * Validate policer mode support. 7107 * Parameters: 7108 * unit - (IN) BCM device number. 7109 * f_ent - (IN) Field entry policer attached. 7110 * level - (IN) Level policer attached. 7111 * f_pl - (IN) Policer descriptor. 7112 * Returns: 7113 * BCM_E_XXX 7114 */ 7115 int 7116 _bcm_field_policer_mode_support(int unit, _field_entry_t *f_ent, 7117 int level, _field_policer_t *f_pl) 7118 { 7119 int rv = BCM_E_UNAVAIL; /* Operation return status. */ 7120 7121 if ((0 == level) && (bcmPolicerModePeak == f_pl->cfg.mode)) { 7122 /* bcmPolicerModePeak not supported. */ 7123 return (BCM_E_UNAVAIL); 7124 } 7125 7126 if (1 == level) { 7127 #ifdef BCM_TRIDENT_SUPPORT 7128 if (SOC_IS_TD_TT(unit)) { 7129 /* Trident device does not support Level1 policers. */ 7130 return (rv); 7131 } 7132 #endif 7133 if ((SOC_IS_TRX(unit) 7134 && (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) 7135 || ((_BCM_FIELD_STAGE_EXTERNAL == f_ent->group->stage_id) 7136 && (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)))) { 7137 /* Level 1 flow mode policer must be bcmPolicerModeCommitted. */ 7138 rv = (_FP_POLICER_IS_FLOW_MODE(f_pl)) 7139 ? (BCM_E_NONE) : (BCM_E_PARAM); 7140 } 7141 return (rv); 7142 } 7143 7144 switch (f_pl->cfg.mode) { 7145 case bcmPolicerModeTrTcm: 7146 case bcmPolicerModeSrTcm: 7147 case bcmPolicerModeCommitted: 7148 case bcmPolicerModeGreen: 7149 rv = BCM_E_NONE; 7150 break; 7151 case bcmPolicerModePassThrough: 7152 if (SOC_IS_TRX(unit)) { 7153 rv = BCM_E_NONE; 7154 } else if ((SOC_IS_FIREBOLT2(unit)) 7155 && (_BCM_FIELD_STAGE_EGRESS 7156 == f_ent->group->stage_id)) { 7157 rv = BCM_E_NONE; 7158 } 7159 break; 7160 case bcmPolicerModeTrTcmDs: 7161 if (SOC_IS_TRX(unit)) { 7162 rv = BCM_E_NONE; 7163 } 7164 break; 7165 case bcmPolicerModeSrTcmModified: 7166 if ((soc_feature(unit, soc_feature_field_virtual_queue)) 7167 && ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) 7168 || ((_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) 7169 && ((SOC_IS_TRIDENT2X(unit) 7170 || SOC_IS_TITAN2PLUS(unit)))))) { 7171 rv = BCM_E_NONE; 7172 } 7173 break; 7174 case bcmPolicerModeCoupledTrTcmDs: 7175 if ((soc_feature(unit, soc_feature_field_virtual_queue)) && 7176 (((!SOC_IS_TD_TT(unit)) && 7177 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) || 7178 ((SOC_IS_APACHE(unit) && 7179 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id))))) { 7180 rv = BCM_E_NONE; 7181 } 7182 break; 7183 case bcmPolicerModeSrTcmTsn: 7184 if (SOC_IS_GREYHOUND2(unit)) { 7185 if ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) || 7186 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) { 7187 rv = BCM_E_NONE; 7188 } 7189 } 7190 break; 7191 default: 7192 rv = BCM_E_PARAM; 7193 break; 7194 } 7195 7196 #if defined(BCM_ENDURO_SUPPORT) 7197 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE2(unit) || 7198 SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 7199 SOC_IS_GREYHOUND2(unit)) { 7200 /* Egress stage does not support packet based metering */ 7201 if ((f_pl->cfg.flags & BCM_POLICER_MODE_PACKETS) 7202 && (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) { 7203 rv = BCM_E_PARAM; 7204 } 7205 } 7206 #endif 7207 return (rv); 7208 } 7209 7210 int 7211 _field_policer_mode_support(int unit, _field_entry_t *f_ent, 7212 int level, _field_policer_t *f_pl) 7213 { 7214 #ifdef BCM_TRIUMPH3_SUPPORT 7215 if (SOC_IS_TRIUMPH3(unit)) { 7216 return (_bcm_field_tr3_policer_mode_support(unit, f_ent, level, f_pl)); 7217 } 7218 #endif 7219 7220 return (_bcm_field_policer_mode_support(unit, f_ent, level, f_pl)); 7221 } 7222 7223 7224 /* 7225 * Function: 7226 * _field_policer_create 7227 * Purpose: 7228 * Initialize a policer entry. 7229 * Parameters: 7230 * unit - (IN) BCM device number. 7231 * pol_cfg - (IN) Policer configuration. 7232 * flags - (IN) HW/API specific flags. 7233 * pid - (OUT) Policer id. 7234 * Returns: 7235 * BCM_E_XXX 7236 * Notes: 7237 */ 7238 int 7239 _field_policer_create(int unit, bcm_policer_config_t *pol_cfg, 7240 uint32 flags, bcm_policer_t *pid) 7241 { 7242 _field_control_t *fc; /* Field control structure. */ 7243 int rv; /* Operation return status. */ 7244 _field_policer_t *f_pl = NULL; /* Internal policer descriptor. */ 7245 7246 /* Input parameters check. */ 7247 if (NULL == pol_cfg) { 7248 return (BCM_E_PARAM); 7249 } 7250 7251 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7252 7253 /* Generate policer id. */ 7254 if (0 == (pol_cfg->flags & BCM_POLICER_WITH_ID)) { 7255 BCM_IF_ERROR_RETURN(_field_policer_id_alloc(unit, pid)); 7256 } else { 7257 /* Check if policer id is already in use. */ 7258 rv = _bcm_field_policer_get(unit, *pid, &f_pl); 7259 if (BCM_SUCCESS(rv)) { 7260 7261 /* Verify that replace flag is set. */ 7262 if(0 == (pol_cfg->flags & BCM_POLICER_REPLACE)) { 7263 return (BCM_E_EXISTS); 7264 } 7265 7266 /* Make sure police is not attached to any entry. */ 7267 if (1 != f_pl->sw_ref_count) { 7268 return (BCM_E_BUSY); 7269 } 7270 /* Copy new configuration. */ 7271 sal_memcpy(&f_pl->cfg, pol_cfg, sizeof(bcm_policer_config_t)); 7272 7273 /* Set policer "dirty" flag and return. */ 7274 rv = _field_policer_hw_flags_set(unit, f_pl, flags); 7275 return (rv); 7276 } 7277 } 7278 7279 /* Allocate policer descriptor. */ 7280 _FP_XGS3_ALLOC(f_pl, sizeof (_field_policer_t), "Field policer"); 7281 if (NULL == f_pl) { 7282 return (BCM_E_MEMORY); 7283 } 7284 7285 /* Copy policer configuration. */ 7286 sal_memcpy(&f_pl->cfg, pol_cfg, sizeof(bcm_policer_config_t)); 7287 7288 /* Set policer "dirty" flags. */ 7289 rv = _field_policer_hw_flags_set(unit, f_pl, flags); 7290 if (BCM_FAILURE(rv)) { 7291 sal_free(f_pl); 7292 return (rv); 7293 } 7294 7295 /* Initialize reference count to 1. */ 7296 f_pl->sw_ref_count = 1; 7297 7298 /* Set hw index to - no hw resources allocated. */ 7299 f_pl->pool_index = _FP_INVALID_INDEX; 7300 #ifdef BCM_TRIUMPH3_SUPPORT 7301 f_pl->logical_pool_index = _FP_INVALID_INDEX; 7302 #endif 7303 f_pl->hw_index = _FP_INVALID_INDEX; 7304 7305 /* Initialize policer id. */ 7306 f_pl->pid = *pid; 7307 7308 /* Insert policer into policers hash. */ 7309 _FP_HASH_INSERT(fc->policer_hash, f_pl, (*pid & _FP_HASH_INDEX_MASK(fc))); 7310 7311 /* Increment number of active policers. */ 7312 fc->policer_count++; 7313 7314 return (BCM_E_NONE); 7315 } 7316 7317 /* 7318 * Function: 7319 * _field_meter_mem_get 7320 * Purpose: 7321 * Get meter memory name. 7322 * Parameters: 7323 * unit - (IN) BCM device number. 7324 * stage_fc - (IN) Stage field control. 7325 * mem - (OUT) Meter memory. 7326 * Returns: 7327 * BCM_E_XXX - 7328 */ 7329 STATIC int 7330 _field_meter_mem_get(int unit, _field_stage_t *stage_fc, soc_mem_t *mem) 7331 { 7332 /* Input parameters check. */ 7333 if ((NULL == stage_fc) || (NULL == mem)) { 7334 return (BCM_E_PARAM); 7335 } 7336 7337 switch (stage_fc->stage_id) { 7338 case _BCM_FIELD_STAGE_INGRESS: 7339 *mem = FP_METER_TABLEm; 7340 break; 7341 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 7342 case _BCM_FIELD_STAGE_EGRESS: 7343 *mem = EFP_METER_TABLEm; 7344 break; 7345 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 7346 default: 7347 return (BCM_E_PARAM); 7348 } 7349 return (BCM_E_NONE); 7350 } 7351 /* 7352 * Function: _field_counter_mem_get 7353 * 7354 * Description: 7355 * Service routine used to extract unit field counters memories 7356 * 7357 * Parameters: 7358 * unit - (IN) BCM device number. 7359 * fc - (IN) Field control structure. 7360 * stage_fc - (IN) Stage field control structure. 7361 * counter_x_mem - (OUT)First counters memory. 7362 * counter_y_mem - (OUT)Second counters memory. 7363 * Returns: 7364 * BCM_E_XXX 7365 */ 7366 int 7367 _bcm_field_counter_mem_get(int unit, 7368 _field_stage_t *stage_fc, 7369 soc_mem_t *counter_x_mem, 7370 soc_mem_t *counter_y_mem 7371 ) 7372 { 7373 if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 7374 #ifdef BCM_FIREBOLT_SUPPORT 7375 if (SOC_IS_FBX(unit)) { 7376 #ifdef BCM_BRADLEY_SUPPORT 7377 if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 7378 *counter_x_mem = FP_COUNTER_TABLE_Xm; 7379 *counter_y_mem = FP_COUNTER_TABLE_Ym; 7380 } else 7381 #endif /* BCM_BRADLEY_SUPPORT */ 7382 { 7383 *counter_x_mem = FP_COUNTER_TABLEm; 7384 } 7385 } else 7386 #endif /* BCM_FIREBOLT_SUPPORT */ 7387 { 7388 return (BCM_E_UNAVAIL); 7389 } 7390 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 7391 } else if (_BCM_FIELD_STAGE_LOOKUP== stage_fc->stage_id) { 7392 return (BCM_E_NONE); 7393 } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) { 7394 if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 7395 *counter_x_mem = EFP_COUNTER_TABLE_Xm; 7396 *counter_y_mem = EFP_COUNTER_TABLE_Ym; 7397 } else { 7398 *counter_x_mem = EFP_COUNTER_TABLEm; 7399 } 7400 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 7401 } else if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) { 7402 *counter_x_mem = EXT_FP_CNTRm; 7403 } else { 7404 return (BCM_E_INTERNAL); 7405 } 7406 return (BCM_E_NONE); 7407 } 7408 7409 7410 int 7411 _field_counter_mem_get(int unit, 7412 _field_stage_t *stage_fc, 7413 soc_mem_t *counter_x_mem, 7414 soc_mem_t *counter_y_mem 7415 ) 7416 { 7417 if (NULL == stage_fc || NULL == counter_x_mem || NULL == counter_y_mem) { 7418 return (BCM_E_PARAM); 7419 } 7420 7421 *counter_x_mem = INVALIDm; 7422 *counter_y_mem = INVALIDm; 7423 7424 #ifdef BCM_TRIUMPH3_SUPPORT 7425 if (SOC_IS_TRIUMPH3(unit)) { 7426 return (_bcm_field_tr3_counter_mem_get(unit, 7427 stage_fc, 7428 counter_x_mem, 7429 counter_y_mem 7430 ) 7431 ); 7432 } 7433 #endif 7434 7435 return (_bcm_field_counter_mem_get(unit, 7436 stage_fc, 7437 counter_x_mem, 7438 counter_y_mem 7439 ) 7440 ); 7441 } 7442 7443 7444 /* 7445 * Function: 7446 * _field_entry_counter_move 7447 * Purpose: 7448 * Move the counter for an entry moving across a slice 7449 * Parameters: 7450 * unit - (IN) BCM device number. 7451 * stage_fc - (IN) Stage field control. 7452 * old_slice - (IN) Old counter slice number. 7453 * old_hw_index - (IN) Old counter hw index. 7454 * f_st - (IN) New statistics entity descriptor. 7455 * Returns: 7456 * BCM_E_XXX 7457 */ 7458 int 7459 _bcm_field_entry_counter_move(int unit, _field_stage_t *stage_fc, 7460 uint8 old_slice, int old_hw_index, 7461 _field_stat_t *f_st_old, 7462 _field_stat_t *f_st) 7463 { 7464 soc_mem_t counter_x_mem, counter_y_mem; /* Counter memories */ 7465 _field_control_t *fc; /* FP control information */ 7466 uint32 flags = 0; /* Bytes/Packets Stats type */ 7467 uint64 value; /* Hardware Stats value */ 7468 int new_idx1 = _FP_INVALID_INDEX; /* Primary Hw stats index */ 7469 int new_idx2 = _FP_INVALID_INDEX; /* Secondary Hw stats index */ 7470 int new_idx3 = _FP_INVALID_INDEX; /* Third Hw stats index */ 7471 int nstat; /* Number of stats */ 7472 int rv = BCM_E_INTERNAL; /* Operation return status */ 7473 7474 /* Get field control structure. */ 7475 rv = _field_control_get(unit, &fc); 7476 BCM_IF_ERROR_RETURN(rv); 7477 7478 /* Get the counter memories */ 7479 rv = _field_counter_mem_get(unit, stage_fc, &counter_x_mem, &counter_y_mem); 7480 BCM_IF_ERROR_RETURN(rv); 7481 7482 for (nstat = 0; nstat < f_st_old->nstat; nstat++) { 7483 /* Get Stat value from old hardware index */ 7484 rv = _field_stat_value_get(unit, 0, f_st_old, f_st_old->stat_arr[nstat], 7485 &value); 7486 BCM_IF_ERROR_RETURN(rv); 7487 7488 if (_BCM_FIELD_STAGE_EXTERNAL != stage_fc->stage_id) { 7489 /* Get Stat New hardware index values */ 7490 rv = fc->functions.fp_stat_index_get(unit, f_st, 7491 f_st->stat_arr[nstat], &new_idx1, &new_idx2, &new_idx3, &flags); 7492 BCM_IF_ERROR_RETURN(rv); 7493 } else if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) { 7494 new_idx1 = f_st->hw_index; 7495 } 7496 7497 /* Check if new hardware index is valid */ 7498 if (_FP_INVALID_INDEX == new_idx1) { 7499 return (BCM_E_INTERNAL); 7500 } 7501 7502 if ((flags & _FP_STAT_BYTES) 7503 && (stage_fc->flags & _FP_STAGE_SEPARATE_PACKET_BYTE_COUNTERS)) { 7504 /* 7505 * For devices that do not support separate packet and byte counters 7506 * only _field_x32_counters is used. 7507 */ 7508 7509 #if defined(BCM_TRX_SUPPORT) 7510 /* Zero the accumulated part at new_idx1 */ 7511 COMPILER_64_ZERO(stage_fc->_field_x64_counters[new_idx1]. 7512 accumulated_counter); 7513 7514 /* Copy the accumulated part value */ 7515 COMPILER_64_OR(stage_fc->_field_x64_counters[new_idx1]. 7516 accumulated_counter, value); 7517 7518 /* Zero the last_hw_value at new_idx1 */ 7519 COMPILER_64_ZERO(stage_fc->_field_x64_counters[new_idx1]. 7520 last_hw_value); 7521 7522 /* Zero Y-Pipeline counter values */ 7523 if (INVALIDm != counter_y_mem) { 7524 COMPILER_64_ZERO(stage_fc->_field_y64_counters[new_idx1]. 7525 accumulated_counter); 7526 COMPILER_64_ZERO(stage_fc->_field_y64_counters[new_idx1]. 7527 last_hw_value); 7528 } 7529 7530 /* Zero counters at secondary index */ 7531 if (_FP_INVALID_INDEX != new_idx2) { 7532 COMPILER_64_ZERO(stage_fc->_field_x64_counters[new_idx2]. 7533 accumulated_counter); 7534 COMPILER_64_ZERO(stage_fc->_field_x64_counters[new_idx2]. 7535 last_hw_value); 7536 7537 /* Zero Y-Pipeline counter values at secondary index */ 7538 if (INVALIDm != counter_y_mem) { 7539 COMPILER_64_ZERO(stage_fc->_field_y64_counters[new_idx2]. 7540 accumulated_counter); 7541 COMPILER_64_ZERO(stage_fc->_field_y64_counters[new_idx2]. 7542 last_hw_value); 7543 } 7544 } 7545 #endif 7546 } else { 7547 7548 /* Zero the accumulated part at new_idx1 */ 7549 COMPILER_64_ZERO(stage_fc->_field_x32_counters[new_idx1]. 7550 accumulated_counter); 7551 7552 /* Copy the accumulated part */ 7553 COMPILER_64_OR(stage_fc->_field_x32_counters[new_idx1]. 7554 accumulated_counter, value); 7555 7556 /* Zero the last_hw_value at new_idx1 */ 7557 stage_fc->_field_x32_counters[new_idx1].last_hw_value = 0; 7558 7559 /* Zero Y-Pipeline packet counter values */ 7560 if (INVALIDm != counter_y_mem) { 7561 #if defined(BCM_SCORPION_SUPPORT) 7562 COMPILER_64_ZERO(stage_fc->_field_y32_counters[new_idx1]. 7563 accumulated_counter); 7564 7565 /* Zero the last_hw_value at new_idx1 */ 7566 stage_fc->_field_y32_counters[new_idx1].last_hw_value = 0; 7567 #endif 7568 } 7569 7570 /* Zero counters at secondary index */ 7571 if (_FP_INVALID_INDEX != new_idx2) { 7572 /* Zero the accumulated part at new_idx2 */ 7573 COMPILER_64_ZERO(stage_fc->_field_x32_counters[new_idx2]. 7574 accumulated_counter); 7575 7576 /* Zero the last_hw_value at new_idx2 */ 7577 stage_fc->_field_x32_counters[new_idx2].last_hw_value = 0; 7578 7579 /* Zero Y-Pipeline packet counter values at secondary index */ 7580 if (INVALIDm != counter_y_mem) { 7581 #if defined(BCM_SCORPION_SUPPORT) 7582 COMPILER_64_ZERO(stage_fc->_field_y32_counters[new_idx2]. 7583 accumulated_counter); 7584 7585 /* Zero the last_hw_value at new_idx2 */ 7586 stage_fc->_field_y32_counters[new_idx2].last_hw_value = 0; 7587 #endif 7588 } 7589 } 7590 } 7591 7592 COMPILER_64_ZERO(value); 7593 rv = _field_stat_value_set(unit, f_st_old, f_st_old->stat_arr[nstat], 7594 value); 7595 BCM_IF_ERROR_RETURN(rv); 7596 } 7597 return rv; 7598 } 7599 7600 /* 7601 * Function: 7602 * _field_entry_meter_move 7603 * Purpose: 7604 * Move the meters for an entry moving across a slice 7605 * Parameters: 7606 * unit - (IN) BCM device number. 7607 * stage_fc - (IN) Stage field control. 7608 * instance - (IN) Pipe Instance the entry belongs to. 7609 * old_slice - (IN) Old meter slice number. 7610 * old_hw_index - (IN) Old meter hw index. 7611 * old_flags - (IN) Old meter flags. 7612 * f_pl - (IN) New meter descriptor. 7613 * f_ent - (IN) field entry. 7614 * old_mode - (IN) old meter mode. 7615 * Returns: 7616 * BCM_E_XXX 7617 */ 7618 STATIC int 7619 _field_entry_meter_move(int unit, _field_stage_t *stage_fc, 7620 int instance, uint8 old_slice, int old_hw_index, 7621 uint32 old_flags, _field_policer_t *f_pl, 7622 _field_entry_t *f_ent, bcm_policer_mode_t old_mode) 7623 { 7624 uint32 buf[SOC_MAX_MEM_FIELD_WORDS]; /* Meter memory entry buffer. */ 7625 soc_mem_t mem_x = INVALIDm; /* Meter memory. */ 7626 soc_mem_t mem_y = INVALIDm; /* Meter memory. */ 7627 int old_index; /* Old meter index in memory. */ 7628 int new_index; /* New meter index in memory. */ 7629 7630 #if defined(BCM_TRX_SUPPORT) 7631 if (SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit)) { 7632 BCM_IF_ERROR_RETURN(_field_trx_meter_table_get(unit, stage_fc->stage_id, &mem_x, &mem_y)); 7633 } else 7634 #endif 7635 { 7636 BCM_IF_ERROR_RETURN(_field_meter_mem_get(unit, stage_fc, &mem_x)); 7637 } 7638 7639 old_index = stage_fc->slices[instance][old_slice].start_tcam_idx 7640 + (2 * old_hw_index); 7641 7642 new_index = stage_fc->slices[instance][f_pl->pool_index].start_tcam_idx 7643 + (2 * f_pl->hw_index); 7644 7645 if ((old_index < soc_mem_index_min(unit, mem_x)) || 7646 ((old_index + 1) > soc_mem_index_max(unit, mem_x)) || 7647 (new_index < soc_mem_index_min(unit, mem_x)) || 7648 ((new_index + 1) > soc_mem_index_max(unit, mem_x))) { 7649 return (BCM_E_PARAM); 7650 } 7651 7652 /* Clear entry buffer. */ 7653 sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 7654 7655 /* Copy meter from old location to a new one. */ 7656 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 7657 BCM_IF_ERROR_RETURN 7658 (soc_mem_read(unit, mem_x, MEM_BLOCK_ANY, old_index, buf)); 7659 BCM_IF_ERROR_RETURN 7660 (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index, buf)); 7661 sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 7662 if (INVALIDm != mem_y) { 7663 BCM_IF_ERROR_RETURN 7664 (soc_mem_read(unit, mem_y, MEM_BLOCK_ANY, old_index, buf)); 7665 BCM_IF_ERROR_RETURN 7666 (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index, buf)); 7667 } 7668 7669 sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 7670 BCM_IF_ERROR_RETURN 7671 (soc_mem_read(unit, mem_x, MEM_BLOCK_ANY, old_index + 1, buf)); 7672 BCM_IF_ERROR_RETURN 7673 (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index + 1, buf)); 7674 sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 7675 if (INVALIDm != mem_y) { 7676 BCM_IF_ERROR_RETURN 7677 (soc_mem_read(unit, mem_y, MEM_BLOCK_ANY, old_index + 1, buf)); 7678 BCM_IF_ERROR_RETURN 7679 (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index + 1, buf)); 7680 } 7681 } else { 7682 /* If its flow mode, consider the old flags to 7683 * decide on even or odd meter 7684 */ 7685 if ((bcmPolicerModeCommitted == (f_pl)->cfg.mode) && 7686 (old_flags & _FP_POLICER_EXCESS_METER) ) { 7687 BCM_IF_ERROR_RETURN 7688 (soc_mem_read(unit, mem_x, MEM_BLOCK_ANY, old_index, buf)); 7689 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 7690 BCM_IF_ERROR_RETURN 7691 (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index, buf)); 7692 } else { 7693 BCM_IF_ERROR_RETURN 7694 (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index+1, buf)); 7695 } 7696 sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 7697 if (INVALIDm != mem_y) { 7698 BCM_IF_ERROR_RETURN 7699 (soc_mem_read(unit, mem_y, MEM_BLOCK_ANY, old_index, buf)); 7700 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 7701 BCM_IF_ERROR_RETURN 7702 (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index, buf)); 7703 } else { 7704 BCM_IF_ERROR_RETURN 7705 (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index+1, buf)); 7706 } 7707 } 7708 7709 f_pl->hw_flags &= ~_FP_POLICER_PEAK_DIRTY; 7710 } else if ((bcmPolicerModeCommitted == (f_pl)->cfg.mode) && 7711 (!(old_flags & _FP_POLICER_EXCESS_METER)) ) { 7712 BCM_IF_ERROR_RETURN 7713 (soc_mem_read(unit, mem_x, MEM_BLOCK_ANY, old_index + 1, buf)); 7714 if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 7715 BCM_IF_ERROR_RETURN 7716 (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index+1, buf)); 7717 } else { 7718 BCM_IF_ERROR_RETURN 7719 (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index, buf)); 7720 } 7721 sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 7722 if (INVALIDm != mem_y) { 7723 BCM_IF_ERROR_RETURN 7724 (soc_mem_read(unit, mem_y, MEM_BLOCK_ANY, old_index + 1, buf)); 7725 if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 7726 BCM_IF_ERROR_RETURN 7727 (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index + 1, buf)); 7728 } else { 7729 BCM_IF_ERROR_RETURN 7730 (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index, buf)); 7731 } 7732 } 7733 7734 /* Clear committed dirty bit. */ 7735 f_pl->hw_flags &= ~_FP_POLICER_COMMITTED_DIRTY; 7736 } 7737 } 7738 /* in case pf td2p where _FP_STAGE_AUTOEXPAND_WITH_POLICER 7739 * is set, clear the old meter entry(ie meter entry of source entry) 7740 * from meter table 7741 */ 7742 _field_meter_hw_clear(unit,f_ent, 7743 old_hw_index, old_mode, 7744 old_slice, old_flags); 7745 return (BCM_E_NONE); 7746 } 7747 7748 STATIC int 7749 _field_meter_pool_apply_pool_id_alloc(int unit, _field_stage_t *stage_fc, int instance, 7750 _field_policer_t *f_pl, int half_meters, uint8 *pool_idx) 7751 { 7752 _field_meter_pool_t *f_mp = NULL; /* Meter pool descriptor. */ 7753 7754 if ((0 > f_pl->cfg.pool_id) || 7755 (f_pl->cfg.pool_id > stage_fc->num_meter_pools) || 7756 (0 == (f_pl->cfg.flags & BCM_POLICER_APPLY_GLOBAL_POOL_ID))) { 7757 return BCM_E_PARAM; 7758 } 7759 7760 /* Check if pool_id passed is a valid pool */ 7761 f_mp = stage_fc->meter_pool[instance][f_pl->cfg.pool_id]; 7762 if ((NULL == f_mp)) { 7763 return (BCM_E_INTERNAL); 7764 } 7765 7766 if ((_FP_POLICER_IS_FLOW_MODE(f_pl) && (f_mp->free_meters) > (half_meters-1)) 7767 || (!_FP_POLICER_IS_FLOW_MODE(f_pl) && f_mp->free_meters >= 2)) { 7768 *pool_idx = f_pl->cfg.pool_id; 7769 } else { 7770 return BCM_E_RESOURCE; 7771 } 7772 7773 return BCM_E_NONE; 7774 } 7775 /* 7776 * Function: 7777 * _field_meter_pool_alloc 7778 * 7779 * Purpose: 7780 * Allocate/Find meter pool with free meters 7781 * 7782 * Parameters: 7783 * unit - (IN) BCM device number. 7784 * stage_fc - (IN) Stage field control structure. 7785 * instance - (IN) Pipe Instance. 7786 * f_pl - (IN) Field policer descriptor 7787 * slice_id - (IN) Slice base index. 7788 * pool_idx - (OUT) Meter pool index. 7789 * Returns: 7790 * BCM_E_XXX 7791 */ 7792 STATIC int 7793 _field_meter_pool_alloc(int unit, _field_stage_t *stage_fc, int instance, 7794 _field_policer_t *f_pl, uint8 slice_id, uint8 *pool_idx) 7795 { 7796 _field_meter_pool_t *f_mp; /* Meter pool descriptor. */ 7797 int idx; /* Pool iteration index. */ 7798 int free_pool; /* Free meter pool. */ 7799 /* allocate even meter index for ingress metering for flow mode. 7800 * If set, the non-flow mode is disabled. Is available only for 7801 * Trident+ devices as there is an issue with metering on Y-pipe ports 7802 */ 7803 int use_even_meter; 7804 uint16 devid; 7805 uint8 revid; 7806 int half_meters; 7807 7808 /* Input parameters check. */ 7809 if ((NULL == stage_fc) || (NULL == pool_idx)) { 7810 return (BCM_E_PARAM); 7811 } 7812 half_meters = 1; 7813 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 7814 use_even_meter = soc_property_get(unit, 7815 spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0); 7816 if (use_even_meter) { 7817 soc_cm_get_id(unit, &devid, &revid); 7818 if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)|| 7819 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)|| 7820 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)|| 7821 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)|| 7822 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID) 7823 ) { 7824 half_meters = 2; 7825 } 7826 } 7827 } 7828 7829 if (f_pl->cfg.flags & BCM_POLICER_APPLY_GLOBAL_POOL_ID) { 7830 return _field_meter_pool_apply_pool_id_alloc(unit, stage_fc, instance, 7831 f_pl, half_meters, pool_idx); 7832 } 7833 free_pool = _FP_INVALID_INDEX; 7834 7835 /* Create policer in an existing pool */ 7836 if ((f_pl->level == 1) && (f_pl->cfg.pool_id != -1) 7837 && (f_pl->cfg.flags & BCM_POLICER_WITH_POOL_ID)) { 7838 7839 /* Check if pool_id passed is a valid pool */ 7840 f_mp = stage_fc->meter_pool[instance][f_pl->cfg.pool_id]; 7841 if ((NULL == f_mp) || (f_mp->slice_id == _FP_INVALID_INDEX) 7842 || (f_mp->level != 1)) { 7843 return (BCM_E_INTERNAL); 7844 } 7845 7846 /* If free meters are available then allocate pool */ 7847 if ((_FP_POLICER_IS_FLOW_MODE(f_pl) && 7848 (f_mp->free_meters) > (half_meters-1)) || 7849 (!_FP_POLICER_IS_FLOW_MODE(f_pl) && f_mp->free_meters >= 2)) { 7850 *pool_idx = f_pl->cfg.pool_id; 7851 return (BCM_E_NONE); 7852 } 7853 } 7854 7855 for (idx = 0 ; idx < stage_fc->num_meter_pools; idx++) { 7856 f_mp = stage_fc->meter_pool[instance][idx]; 7857 if (NULL == f_mp) { 7858 return (BCM_E_INTERNAL); 7859 } 7860 7861 /* If we have a matching pool with free entries - just use it. */ 7862 if ((f_mp->slice_id == slice_id) 7863 && (f_mp->level == f_pl->level) 7864 && ((_FP_POLICER_IS_FLOW_MODE(f_pl) && 7865 (f_mp->free_meters) > (half_meters-1)) 7866 || (!_FP_POLICER_IS_FLOW_MODE(f_pl) && f_mp->free_meters >= 2) 7867 )) { 7868 7869 *pool_idx = idx; 7870 f_pl->cfg.pool_id = *pool_idx; 7871 return (BCM_E_NONE); 7872 } 7873 7874 /* Preserve first free pool */ 7875 if ((_FP_INVALID_INDEX == free_pool) && 7876 (_FP_INVALID_INDEX == f_mp->slice_id)) { 7877 free_pool = idx; 7878 } 7879 } 7880 7881 7882 /* We have to use free pool at this point. */ 7883 if (_FP_INVALID_INDEX == free_pool) { 7884 return (BCM_E_RESOURCE); 7885 } 7886 7887 f_mp = stage_fc->meter_pool[instance][free_pool]; 7888 f_mp->slice_id = slice_id; 7889 f_mp->level = f_pl->level; 7890 *pool_idx = free_pool; 7891 f_pl->cfg.pool_id = *pool_idx; 7892 return (BCM_E_NONE); 7893 } 7894 7895 7896 /* 7897 * Function: 7898 * _field_meter_pool_free 7899 * 7900 * Purpose: 7901 * Unreserve a meter pool. 7902 * 7903 * Parameters: 7904 * unit - (IN) BCM device number. 7905 * stage_fc - (IN) Stage field control structure. 7906 * instance - (IN) Pipe Instance. 7907 * pool_idx - (IN) Meter pool index. 7908 * Returns: 7909 * BCM_E_XXX 7910 */ 7911 int 7912 _field_meter_pool_free(int unit, _field_stage_t *stage_fc, 7913 int instance, uint8 pool_idx) 7914 { 7915 _field_meter_pool_t *f_mp; /* Meter pool descriptor. */ 7916 #if defined (BCM_TOMAHAWK_SUPPORT) 7917 _field_control_t *fc; /* Field control */ 7918 #endif 7919 7920 /* Input parameters check. */ 7921 if (NULL == stage_fc) { 7922 return (BCM_E_PARAM); 7923 } 7924 7925 f_mp = stage_fc->meter_pool[instance][pool_idx]; 7926 if (NULL == f_mp) { 7927 return (BCM_E_INTERNAL); 7928 } 7929 7930 /* Make sure pool entries are not in use. */ 7931 if (f_mp->free_meters != f_mp->size) { 7932 return (BCM_E_BUSY); 7933 } 7934 7935 f_mp->slice_id = _FP_INVALID_INDEX; 7936 f_mp->level = -1; 7937 7938 #if defined (BCM_TOMAHAWK_SUPPORT) 7939 if ((soc_feature(unit, soc_feature_field_multi_pipe_support)) && 7940 (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) { 7941 7942 /* Get field control information. */ 7943 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7944 fc->ifp_em_meter_in_use[instance][pool_idx] = 7945 BCM_FIELD_METER_POOL_USED_BY_NONE; 7946 } 7947 #endif 7948 7949 return (BCM_E_NONE); 7950 } 7951 7952 STATIC int 7953 _field_meter_pool_entry_free_old(int unit, _field_stage_t *stage_fc, 7954 int instance, _field_policer_t *f_pl) 7955 { 7956 _field_control_t *fc; 7957 _field_meter_pool_t *f_mp; /* Meter pool descriptor. */ 7958 int idx; /* Meter index. */ 7959 /* allocate even meter index for ingress metering for flow mode. 7960 * If set, the non-flow mode is disabled. Is available only for 7961 * Trident+ devices as there is an issue with metering on Y-pipe ports 7962 */ 7963 int use_even_meter; 7964 int is_trident_plus_use_even_meter; 7965 uint16 devid; 7966 uint8 revid; 7967 7968 /* Input parameters check. */ 7969 if ((NULL == stage_fc) || (NULL == f_pl)) { 7970 return (BCM_E_PARAM); 7971 } 7972 7973 /* Meter pool index sanity check. */ 7974 if (stage_fc->num_meter_pools <= f_pl->old_pool_index) { 7975 return (BCM_E_PARAM); 7976 } 7977 7978 /* Get field control information. */ 7979 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7980 7981 #ifdef BCM_TRIUMPH3_SUPPORT 7982 if (SOC_IS_TRIUMPH3(unit)) { 7983 7984 /* When ingress physical policer pools is split into logical pools 7985 * Allocate pool id and index using the logical meter pool entry 7986 * allocator 7987 */ 7988 if (fc->ingress_logical_policer_pools_mode != 7989 bcmFieldIngressLogicalPolicerPools8x1024) { 7990 LOG_DEBUG(BSL_LS_BCM_FP, 7991 (BSL_META_U(unit, 7992 "FP(unit %d) Policer Pools is in non default mode." 7993 " Logical Meter alloc called.\r\n"), unit)); 7994 return _field_tr3_logical_meter_pool_entry_free_old (unit, stage_fc, f_pl); 7995 } 7996 } 7997 #endif 7998 is_trident_plus_use_even_meter = 0; 7999 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 8000 use_even_meter = soc_property_get(unit, 8001 spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0); 8002 if (use_even_meter) { 8003 soc_cm_get_id(unit, &devid, &revid); 8004 if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)|| 8005 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)|| 8006 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)|| 8007 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)|| 8008 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID) 8009 ) { 8010 is_trident_plus_use_even_meter = 1; 8011 } 8012 } 8013 } 8014 8015 f_mp = stage_fc->meter_pool[instance][f_pl->old_pool_index]; 8016 8017 /* Mark meter as free in the slice. */ 8018 idx = f_pl->old_hw_index * 2; 8019 8020 /* Meter index in the pool sanity check. */ 8021 if ((f_mp->size <= idx) 8022 || (f_mp->size <= (idx + 1))) { 8023 return (BCM_E_PARAM); 8024 } 8025 /* if not flow mode */ 8026 if (bcmPolicerModeCommitted != (f_pl)->old_mode) { 8027 _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx); 8028 _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx + 1); 8029 f_mp->free_meters += 2; 8030 } else { 8031 /* if excess meter */ 8032 if ((bcmPolicerModeCommitted == (f_pl)->old_mode) && 8033 ((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER)) { 8034 _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx); 8035 8036 } else if ((bcmPolicerModeCommitted == (f_pl)->old_mode) && 8037 (!((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER))) { 8038 _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx + 1); 8039 } 8040 f_mp->free_meters++; 8041 if (is_trident_plus_use_even_meter) { 8042 f_mp->free_meters++; 8043 } 8044 } 8045 8046 /* Free empty pool. */ 8047 if (f_mp->free_meters == f_mp->size) { 8048 BCM_IF_ERROR_RETURN 8049 (_field_meter_pool_free(unit, stage_fc, instance, f_pl->pool_index)); 8050 } 8051 8052 return (BCM_E_NONE); 8053 } 8054 /* 8055 * Function: 8056 * _field_meter_pool_entry_free 8057 * 8058 * Purpose: 8059 * Free meter pool entry. 8060 * if necessary free the pool itself. 8061 * 8062 * Parameters: 8063 * unit - (IN) BCM device number. 8064 * stage_fc - (IN) Stage field control structure. 8065 * instance - (IN) Pipe Instance. 8066 * f_pl - (IN) Policer descriptor. 8067 * Returns: 8068 * BCM_E_XXX 8069 */ 8070 STATIC int 8071 _field_meter_pool_entry_free(int unit, _field_stage_t *stage_fc, 8072 int instance, _field_policer_t *f_pl) 8073 { 8074 _field_control_t *fc; 8075 _field_meter_pool_t *f_mp; /* Meter pool descriptor. */ 8076 int idx; /* Meter index. */ 8077 /* allocate even meter index for ingress metering for flow mode. 8078 * If set, the non-flow mode is disabled. Is available only for 8079 * Trident+ devices as there is an issue with metering on Y-pipe ports 8080 */ 8081 int use_even_meter; 8082 int is_trident_plus_use_even_meter; 8083 uint16 devid; 8084 uint8 revid; 8085 8086 /* Input parameters check. */ 8087 if ((NULL == stage_fc) || (NULL == f_pl)) { 8088 return (BCM_E_PARAM); 8089 } 8090 8091 /* Meter pool index sanity check. */ 8092 if (stage_fc->num_meter_pools <= f_pl->pool_index) { 8093 return (BCM_E_PARAM); 8094 } 8095 8096 /* Get field control information. */ 8097 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 8098 8099 #ifdef BCM_TRIUMPH3_SUPPORT 8100 if (SOC_IS_TRIUMPH3(unit)) { 8101 8102 /* When ingress physical policer pools is split into logical pools 8103 * Allocate pool id and index using the logical meter pool entry 8104 * allocator 8105 */ 8106 if (fc->ingress_logical_policer_pools_mode != 8107 bcmFieldIngressLogicalPolicerPools8x1024) { 8108 LOG_DEBUG(BSL_LS_BCM_FP, 8109 (BSL_META_U(unit, 8110 "FP(unit %d) Policer Pools is in non default mode." 8111 " Logical Meter alloc called.\r\n"), unit)); 8112 return _field_tr3_logical_meter_pool_entry_free (unit, stage_fc, f_pl); 8113 } 8114 } 8115 #endif 8116 is_trident_plus_use_even_meter = 0; 8117 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 8118 use_even_meter = soc_property_get(unit, 8119 spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0); 8120 if (use_even_meter) { 8121 soc_cm_get_id(unit, &devid, &revid); 8122 if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)|| 8123 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)|| 8124 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)|| 8125 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)|| 8126 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID) 8127 ) { 8128 is_trident_plus_use_even_meter = 1; 8129 } 8130 } 8131 } 8132 8133 f_mp = stage_fc->meter_pool[instance][f_pl->pool_index]; 8134 8135 /* Mark meter as free in the slice. */ 8136 idx = f_pl->hw_index * 2; 8137 8138 /* Meter index in the pool sanity check. */ 8139 if ((f_mp->size <= idx) 8140 || (f_mp->size <= (idx + 1))) { 8141 return (BCM_E_PARAM); 8142 } 8143 8144 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 8145 _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx); 8146 _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx + 1); 8147 f_mp->free_meters += 2; 8148 } else { 8149 8150 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 8151 _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx); 8152 8153 /* Clear excess meter flag bit. */ 8154 _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl); 8155 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 8156 _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx + 1); 8157 } 8158 f_mp->free_meters++; 8159 if (is_trident_plus_use_even_meter) { 8160 f_mp->free_meters++; 8161 } 8162 } 8163 8164 /* Free empty pool. */ 8165 if (f_mp->free_meters == f_mp->size) { 8166 BCM_IF_ERROR_RETURN 8167 (_field_meter_pool_free(unit, stage_fc, instance, f_pl->pool_index)); 8168 } 8169 8170 /* Reset pool and hw index information in policer structure. */ 8171 f_pl->pool_index = _FP_INVALID_INDEX; 8172 f_pl->hw_index = _FP_INVALID_INDEX; 8173 8174 return (BCM_E_NONE); 8175 } 8176 8177 /* 8178 * Function: 8179 * _field_meter_pool_entry_alloc 8180 * 8181 * Purpose: 8182 * Allocate meter pool entry. 8183 * 8184 * Parameters: 8185 * unit - (IN) BCM device number. 8186 * stage_fc - (IN) Stage field control structure. 8187 * instance - (IN) Pipe Instance. 8188 * pool_slice_id - (IN) Meter pool index. 8189 * f_pl - (IN) Field policer descriptor 8190 * Returns: 8191 * BCM_E_XXX 8192 */ 8193 STATIC int 8194 _field_meter_pool_entry_alloc(int unit, _field_stage_t *stage_fc, int instance, 8195 uint8 pool_slice_id, _field_policer_t *f_pl) 8196 { 8197 uint8 pool_idx; /* Meter pool index. */ 8198 int idx; /* Pool iteration index. */ 8199 _field_meter_pool_t *f_mp; /* Meter pool descriptor. */ 8200 _field_control_t *fc; /* Field control structure. */ 8201 /* allocate even meter index for ingress metering for flow mode. 8202 * If set, the non-flow mode is disabled. Is available only for 8203 * Trident+ devices as there is an issue with metering on Y-pipe ports 8204 */ 8205 int use_even_meter; 8206 int is_trident_plus_use_even_meter; 8207 uint16 devid; 8208 uint8 revid; 8209 8210 /* Input parameters check. */ 8211 if ((NULL == stage_fc) || (NULL == f_pl)) { 8212 return (BCM_E_PARAM); 8213 } 8214 8215 if (f_pl->level >= _FP_POLICER_LEVEL_COUNT) { 8216 return (BCM_E_PARAM); 8217 } 8218 /* Get field control structure. */ 8219 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 8220 8221 #ifdef BCM_TRIUMPH3_SUPPORT 8222 if (SOC_IS_TRIUMPH3(unit)) { 8223 8224 /* When ingress physical policer pools is split into logical pools 8225 * Allocate pool id and index using the logical meter pool entry 8226 * allocator 8227 */ 8228 if (fc->ingress_logical_policer_pools_mode != 8229 bcmFieldIngressLogicalPolicerPools8x1024) { 8230 LOG_DEBUG(BSL_LS_BCM_FP, 8231 (BSL_META_U(unit, 8232 "FP(unit %d) Policer Pools is in non default mode." 8233 " Logical Meter alloc called.\r\n"), unit)); 8234 return _field_tr3_logical_meter_pool_entry_alloc (unit, 8235 stage_fc, 8236 pool_slice_id, 8237 f_pl); 8238 } 8239 } 8240 #endif 8241 8242 /* Allocate meter pool with free meters. */ 8243 BCM_IF_ERROR_RETURN(_field_meter_pool_alloc(unit, stage_fc, instance, f_pl, 8244 pool_slice_id, &pool_idx)); 8245 f_mp = stage_fc->meter_pool[instance][pool_idx]; 8246 8247 is_trident_plus_use_even_meter = 0; 8248 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 8249 use_even_meter = soc_property_get(unit, 8250 spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0); 8251 if (use_even_meter) { 8252 soc_cm_get_id(unit, &devid, &revid); 8253 if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)|| 8254 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)|| 8255 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)|| 8256 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)|| 8257 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID) 8258 ) { 8259 is_trident_plus_use_even_meter = 1; 8260 } 8261 } 8262 } 8263 /* Reserve unused meter. */ 8264 for (idx = 0; idx < f_mp->size; idx++) { 8265 8266 /* Allocate meter indices for non-flow mode meters. */ 8267 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 8268 if (is_trident_plus_use_even_meter) { 8269 return (BCM_E_PARAM); 8270 } 8271 if (0 != (idx % 2)) { 8272 /* skip odd meter indices */ 8273 continue; 8274 } 8275 8276 if ((0 == _FP_METER_BMP_TEST(f_mp->meter_bmp, idx)) 8277 && (0 == _FP_METER_BMP_TEST(f_mp->meter_bmp, idx + 1))) { 8278 _FP_METER_BMP_ADD(f_mp->meter_bmp, idx); 8279 _FP_METER_BMP_ADD(f_mp->meter_bmp, (idx + 1)); 8280 /* Decrement free meters count in meter pool. */ 8281 f_mp->free_meters -= 2; 8282 f_pl->pool_index = pool_idx ; 8283 f_pl->hw_index = (idx / 2); 8284 return (BCM_E_NONE); 8285 } 8286 } 8287 8288 /* Allocate hardware resources for flow mode meters. */ 8289 if (_FP_POLICER_IS_FLOW_MODE(f_pl) 8290 && (0 == _FP_METER_BMP_TEST(f_mp->meter_bmp, idx))) { 8291 if (is_trident_plus_use_even_meter) { 8292 if (0 != (idx % 2)) { 8293 /* skip odd meter indices. */ 8294 continue; 8295 } 8296 } 8297 if (f_pl->hw_flags & _FP_POLICER_DIRTY) { 8298 f_pl->hw_flags &= (idx % 2) 8299 ? ~_FP_POLICER_PEAK_DIRTY 8300 : ~_FP_POLICER_COMMITTED_DIRTY; 8301 } else { 8302 LOG_DEBUG(BSL_LS_BCM_FP, 8303 (BSL_META_U(unit, 8304 "FP(unit %d) Error: Meter alloc called with invalid" 8305 " hw_flags=%x\n"), unit, f_pl->hw_flags)); 8306 return (BCM_E_INTERNAL); 8307 } 8308 8309 if (f_pl->hw_flags & _FP_POLICER_PEAK_DIRTY) { 8310 _FP_POLICER_EXCESS_HW_METER_SET(f_pl); 8311 } else { 8312 _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl); 8313 } 8314 8315 _FP_METER_BMP_ADD(f_mp->meter_bmp, idx); 8316 8317 /* Decrement free meter count in meter pool. */ 8318 if (is_trident_plus_use_even_meter) { 8319 f_mp->free_meters -= 2; 8320 } else { 8321 f_mp->free_meters--; 8322 } 8323 8324 f_pl->pool_index = pool_idx; 8325 f_pl->hw_index = (idx / 2); 8326 return (BCM_E_NONE); 8327 } 8328 } 8329 8330 /* Never reached - pool alloc makes sure at least one meter is available. */ 8331 if (f_mp->free_meters == f_mp->size) { 8332 BCM_IF_ERROR_RETURN(_field_meter_pool_free(unit, stage_fc, instance, pool_idx)); 8333 } 8334 return (BCM_E_RESOURCE); 8335 } 8336 8337 /* 8338 * Function: 8339 * _field_meterpool_hw_entry_alloc 8340 * 8341 * Purpose: 8342 * Allocate field entry meter from a meter pool. 8343 * 8344 * Parameters: 8345 * unit - (IN) BCM device number. 8346 * f_ent - (IN) Field entry structure. 8347 * f_pl - (IN) Field policer descriptor. 8348 * Returns: 8349 * BCM_E_XXX 8350 */ 8351 STATIC int 8352 _field_meterpool_hw_entry_alloc (int unit, _field_entry_t *f_ent, 8353 _field_policer_t *f_pl) 8354 { 8355 _field_stage_id_t stage_id; /* Stage id used for metering. */ 8356 _field_stage_t *stage_fc; /* Field stage control structure. */ 8357 _field_group_t *fg; /* Field group structure. */ 8358 uint8 pool_sid; /* Key to ensure single update per hit. */ 8359 8360 /* Input parameters check. */ 8361 if ((NULL == f_ent) || (NULL == f_pl)) { 8362 return (BCM_E_PARAM); 8363 } 8364 8365 fg = f_ent->group; 8366 stage_id = ((_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) || \ 8367 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) ? \ 8368 _BCM_FIELD_STAGE_INGRESS : fg->stage_id; 8369 8370 /* Get meter pool stage control. */ 8371 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc)); 8372 8373 /* Generate unique pool id. */ 8374 if ((_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) || 8375 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) { 8376 pool_sid = stage_fc->tcam_slices; 8377 } else { 8378 pool_sid = fg->slices->slice_number; 8379 } 8380 8381 /* Allocate an entry within the pool. */ 8382 BCM_IF_ERROR_RETURN 8383 (_field_meter_pool_entry_alloc(unit, stage_fc, 8384 f_ent->group->instance, 8385 pool_sid, f_pl)); 8386 8387 return (BCM_E_NONE); 8388 } 8389 8390 STATIC int 8391 _field_slice_meter_free_old(int unit, _field_entry_t *f_ent, 8392 _field_policer_t *f_pl) 8393 { 8394 _field_stage_t *stage_fc; /* Field stage control structure. */ 8395 _field_slice_t *fs; /* Field slice structure. */ 8396 int idx; 8397 8398 if ((NULL == f_ent) || (NULL == f_pl)) { 8399 return (BCM_E_PARAM); 8400 } 8401 8402 /* Get field stage control structure. */ 8403 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, f_ent->group->stage_id, 8404 &stage_fc)); 8405 8406 /* Get slice policer installed in. */ 8407 fs = stage_fc->slices[f_ent->group->instance] + (f_pl->old_pool_index); 8408 8409 /* Must be a valid meter index. */ 8410 if (f_pl->old_hw_index == _FP_INVALID_INDEX) { 8411 return (BCM_E_INTERNAL); 8412 } 8413 8414 /* Determine even meter's index from meter pair index. */ 8415 idx = f_pl->old_hw_index * 2; 8416 8417 /* Validate input hardware index. */ 8418 if ((idx >= fs->meters_count) || ((idx + 1) >= fs->meters_count)) { 8419 return (BCM_E_INTERNAL); 8420 } 8421 8422 /* Mark meter as free in the slice. */ 8423 /*if not flow mode */ 8424 if (bcmPolicerModeCommitted != (f_pl)->old_mode) { 8425 _FP_METER_BMP_REMOVE(fs->meter_bmp, idx); 8426 _FP_METER_BMP_REMOVE(fs->meter_bmp, idx + 1); 8427 } else { 8428 /* if excess meter */ 8429 if ((bcmPolicerModeCommitted == (f_pl)->old_mode) && 8430 ((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER)) { 8431 _FP_METER_BMP_REMOVE(fs->meter_bmp, idx); 8432 8433 } else if ((bcmPolicerModeCommitted == (f_pl)->old_mode) && 8434 (!((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER))) { 8435 _FP_METER_BMP_REMOVE(fs->meter_bmp, idx + 1); 8436 } 8437 } 8438 8439 return (BCM_E_NONE); 8440 } 8441 /* 8442 * Function: 8443 * _field_slice_meter_free 8444 * 8445 * Purpose: 8446 * Free slice meter. 8447 * 8448 * Parameters: 8449 * unit - (IN) BCM device number. 8450 * f_ent - (IN) Field entry structure. 8451 * f_pl - (IN) Field policer descriptor. 8452 * Returns: 8453 * BCM_E_XXX 8454 */ 8455 STATIC int 8456 _field_slice_meter_free(int unit, _field_entry_t *f_ent, 8457 _field_policer_t *f_pl) 8458 { 8459 _field_stage_t *stage_fc; /* Field stage control structure. */ 8460 _field_slice_t *fs; /* Field slice structure. */ 8461 int idx; 8462 8463 if ((NULL == f_ent) || (NULL == f_pl)) { 8464 return (BCM_E_PARAM); 8465 } 8466 8467 /* Get field stage control structure. */ 8468 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, f_ent->group->stage_id, 8469 &stage_fc)); 8470 8471 /* Get slice policer installed in. */ 8472 fs = stage_fc->slices[f_ent->group->instance] + (f_pl->pool_index); 8473 8474 /* Must be a valid meter index. */ 8475 if (f_pl->hw_index == _FP_INVALID_INDEX) { 8476 return (BCM_E_INTERNAL); 8477 } 8478 8479 /* Determine even meter's index from meter pair index. */ 8480 idx = f_pl->hw_index * 2; 8481 8482 /* Validate input hardware index. */ 8483 if ((idx >= fs->meters_count) || ((idx + 1) >= fs->meters_count)) { 8484 return (BCM_E_INTERNAL); 8485 } 8486 8487 /* Mark meter as free in the slice. */ 8488 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 8489 _FP_METER_BMP_REMOVE(fs->meter_bmp, idx); 8490 _FP_METER_BMP_REMOVE(fs->meter_bmp, idx + 1); 8491 } else { 8492 8493 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 8494 _FP_METER_BMP_REMOVE(fs->meter_bmp, idx); 8495 8496 /* Clear excess meter flag bit. */ 8497 _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl); 8498 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 8499 _FP_METER_BMP_REMOVE(fs->meter_bmp, idx + 1); 8500 } 8501 } 8502 8503 f_pl->hw_index = _FP_INVALID_INDEX; 8504 f_pl->pool_index = _FP_INVALID_INDEX; 8505 return (BCM_E_NONE); 8506 } 8507 8508 /* 8509 * Function: 8510 * _field_slice_meter_alloc 8511 * 8512 * Purpose: 8513 * Allocate a policer for an entry from a slice. 8514 * 8515 * Parameters: 8516 * unit - (IN) BCM device number. 8517 * fs - (IN) Slice policer will be installed in. 8518 * f_pl - (IN) Policer descriptor. 8519 * Returns: 8520 * BCM_E_XXX 8521 */ 8522 STATIC int 8523 _field_slice_meter_alloc(int unit, _field_slice_t *fs, _field_policer_t *f_pl) 8524 { 8525 int idx; /* Policer iteration index. */ 8526 8527 /* Input parameters check. */ 8528 if ((NULL == f_pl) || (NULL == fs)) { 8529 return (BCM_E_PARAM); 8530 } 8531 8532 /* Find unused meter in the slice. */ 8533 for (idx = 0; idx < fs->meters_count; idx++) { 8534 8535 /* Allocate a meter pair for non-flow mode policer. */ 8536 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 8537 8538 if (0 != (idx % 2)) { 8539 /* skip odd meter indices. */ 8540 continue; 8541 } 8542 8543 if ((0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx)) 8544 && (0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx + 1))) { 8545 _FP_METER_BMP_ADD(fs->meter_bmp, idx); 8546 _FP_METER_BMP_ADD(fs->meter_bmp, (idx + 1)); 8547 f_pl->pool_index = fs->slice_number; 8548 f_pl->cfg.pool_id = f_pl->pool_index; 8549 f_pl->hw_index = (idx / 2) ; 8550 break; 8551 } 8552 } 8553 8554 /* Allocate a meter from meter pair for flow mode meters. */ 8555 if (_FP_POLICER_IS_FLOW_MODE(f_pl) 8556 && (0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx))) { 8557 if (f_pl->hw_flags & _FP_POLICER_DIRTY) { 8558 f_pl->hw_flags &= (idx % 2) 8559 ? ~_FP_POLICER_PEAK_DIRTY 8560 : ~_FP_POLICER_COMMITTED_DIRTY; 8561 } else { 8562 /* Meter move operation, flag is set here. */ 8563 f_pl->hw_flags |= (idx % 2) 8564 ? _FP_POLICER_COMMITTED_DIRTY 8565 : _FP_POLICER_PEAK_DIRTY; 8566 } 8567 8568 if (f_pl->hw_flags & _FP_POLICER_PEAK_DIRTY) { 8569 _FP_POLICER_EXCESS_HW_METER_SET(f_pl); 8570 } else { 8571 _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl); 8572 } 8573 8574 _FP_METER_BMP_ADD(fs->meter_bmp, idx); 8575 f_pl->pool_index = fs->slice_number; 8576 f_pl->cfg.pool_id = f_pl->pool_index; 8577 f_pl->hw_index = (idx / 2); 8578 break; 8579 } 8580 } 8581 8582 if (idx == fs->meters_count) { 8583 return (BCM_E_RESOURCE); 8584 } 8585 return (BCM_E_NONE); 8586 } 8587 8588 8589 STATIC int 8590 _field_meter_hw_free_old(int unit, _field_entry_t *f_ent) 8591 { 8592 _field_stage_t *stage_fc; /* Field stage control. */ 8593 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure. */ 8594 _field_policer_t *f_pl; /* Policer descriptor. */ 8595 _field_group_t *fg; /* Field group structure. */ 8596 int rv; /* Operation return status. */ 8597 8598 /* Input parameters check. */ 8599 if (NULL == f_ent) { 8600 return (BCM_E_PARAM); 8601 } 8602 8603 f_ent_pl = f_ent->policer; 8604 fg = f_ent->group; 8605 8606 /* Get stage control structure. */ 8607 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 8608 BCM_IF_ERROR_RETURN(rv); 8609 8610 /* Read policer configuration.*/ 8611 BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 8612 8613 /* Policer slice index sanity check. */ 8614 if ((f_pl->old_pool_index >= stage_fc->tcam_slices) 8615 || (f_pl->old_pool_index == _FP_INVALID_INDEX)) { 8616 return (BCM_E_INTERNAL); 8617 } 8618 8619 /* Free policer id. */ 8620 rv = _field_slice_meter_free_old(unit, f_ent, f_pl); 8621 8622 return (rv); 8623 } 8624 /* 8625 * Function: 8626 * _field_meter_hw_free 8627 * 8628 * Purpose: 8629 * Deallocate a policer from an entry slice. 8630 * 8631 * Parameters: 8632 * unit - (IN) BCM device number. 8633 * f_ent - (IN/OUT) Entry policer belongs to. 8634 * Returns: 8635 * BCM_E_XXX 8636 */ 8637 STATIC int 8638 _field_meter_hw_free(int unit, _field_entry_t *f_ent) 8639 { 8640 _field_stage_t *stage_fc; /* Field stage control. */ 8641 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure. */ 8642 uint8 entry_part; /* Secondary entry part. */ 8643 _field_policer_t *f_pl; /* Policer descriptor. */ 8644 _field_group_t *fg; /* Field group structure. */ 8645 int rv; /* Operation return status. */ 8646 8647 /* Input parameters check. */ 8648 if (NULL == f_ent) { 8649 return (BCM_E_PARAM); 8650 } 8651 8652 f_ent_pl = f_ent->policer; 8653 fg = f_ent->group; 8654 8655 /* Get stage control structure. */ 8656 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 8657 BCM_IF_ERROR_RETURN(rv); 8658 8659 /* Read policer configuration.*/ 8660 BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 8661 8662 /* Policer slice index sanity check. */ 8663 if ((f_pl->pool_index >= stage_fc->tcam_slices) 8664 || (f_pl->pool_index == _FP_INVALID_INDEX)) { 8665 return (BCM_E_INTERNAL); 8666 } 8667 8668 /* Free policer id. */ 8669 rv = _field_slice_meter_free(unit, f_ent, f_pl); 8670 8671 /* Reset entry policer related flags. */ 8672 if (f_ent->flags & _FP_ENTRY_POLICER_IN_SECONDARY_SLICE) { 8673 /* Get primary entry from the second slice. */ 8674 rv = _bcm_field_entry_flags_to_tcam_part(unit, _FP_ENTRY_SECONDARY, 8675 fg, &entry_part); 8676 BCM_IF_ERROR_RETURN(rv); 8677 sal_memset(f_ent[entry_part].policer, 0, sizeof(_field_entry_policer_t)); 8678 f_ent->flags &= ~_FP_ENTRY_POLICER_IN_SECONDARY_SLICE; 8679 } 8680 return (rv); 8681 } 8682 8683 /* 8684 * Function: 8685 * _field_meter_hw_alloc 8686 * 8687 * Purpose: 8688 * Allocate a policer/s for an entry from a slice. 8689 * 8690 * Parameters: 8691 * unit - (IN) BCM device number. 8692 * f_ent - (IN/OUT) Entry array policer belongs to. 8693 * fs - (IN) Desired slice for the policer. 8694 * Returns: 8695 * BCM_E_XXX 8696 */ 8697 STATIC int 8698 _field_meter_hw_alloc(int unit, _field_entry_t *f_ent, _field_slice_t *fs) 8699 { 8700 _field_entry_policer_t *f_ent_pl; /* Field entry policer . */ 8701 _field_policer_t *f_pl; /* Policer descriptor. */ 8702 _field_group_t *fg; /* Field group structure. */ 8703 uint8 entry_part; /* Field entry tcam part . */ 8704 int rv = BCM_E_RESOURCE; /* Operation return status. */ 8705 8706 /* Input parameters check. */ 8707 if ((NULL == f_ent) || (NULL == fs)) { 8708 return (BCM_E_PARAM); 8709 } 8710 8711 f_ent_pl = f_ent->policer; 8712 8713 /* Reject unused policers. */ 8714 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 8715 return (BCM_E_PARAM); 8716 } 8717 8718 /* Read policer configuration. */ 8719 BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 8720 8721 /* 8722 * Allocate meter from a primary slice unless color dependent counter 8723 * is only availabe in secondary slice 8724 */ 8725 if (0 == (f_ent->flags & _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE)) { 8726 rv = _field_slice_meter_alloc(unit, fs, f_pl); 8727 } 8728 if (BCM_E_RESOURCE == rv) { 8729 fg = f_ent->group; 8730 8731 /* Double/Triple wide groups might allocate from secondary slice. */ 8732 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) 8733 || (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 8734 8735 rv = _field_slice_meter_alloc(unit, fs + 1, f_pl); 8736 if (BCM_SUCCESS(rv)) { 8737 8738 /* Get primary entry from the second slice. */ 8739 rv = _bcm_field_entry_flags_to_tcam_part (unit, 8740 _FP_ENTRY_SECONDARY, 8741 fg, &entry_part); 8742 BCM_IF_ERROR_RETURN(rv); 8743 8744 f_ent->flags |= _FP_ENTRY_POLICER_IN_SECONDARY_SLICE; 8745 sal_memcpy(f_ent[entry_part].policer, f_ent->policer, 8746 sizeof(_field_entry_policer_t)); 8747 f_ent[entry_part].policer->flags |= _FP_POLICER_INSTALLED; 8748 } 8749 } 8750 } 8751 return (rv); 8752 } 8753 /* Clear the hardware entries of the meter table */ 8754 STATIC int 8755 _field_meter_hw_clear(int unit, _field_entry_t *f_ent, 8756 int old_hw_index, bcm_policer_mode_t old_mode, 8757 int old_pool_index, uint32 old_hw_flags) 8758 8759 { 8760 _field_stage_t *stage_fc; /* Stage field control structure */ 8761 soc_mem_t meter_table_x; /* Meter table name */ 8762 soc_mem_t meter_table_y; /* Meter table name */ 8763 soc_mem_t meter_table; /* Meter table name */ 8764 int meter_idx; /* Meter hw index */ 8765 int idx; /* Meter hw index */ 8766 int rv = BCM_E_NONE; /* Return value */ 8767 int iter = 0; /* Iteration count */ 8768 8769 8770 meter_table_x = INVALIDm; 8771 meter_table_y = INVALIDm; 8772 /* Get field stage control structure. */ 8773 BCM_IF_ERROR_RETURN 8774 (_field_stage_control_get(unit, f_ent->group->stage_id, 8775 &stage_fc)); 8776 8777 if ((f_ent->group->stage_id != _BCM_FIELD_STAGE_EGRESS) || 8778 (!(SOC_IS_TRIDENT2PLUS(unit)))) { 8779 return BCM_E_NONE; 8780 } 8781 /* Resolve meter table name. */ 8782 #if defined(BCM_TRX_SUPPORT) 8783 if (SOC_IS_TRX(unit)) { 8784 BCM_IF_ERROR_RETURN 8785 (_field_trx_meter_table_get(unit, f_ent->fs->stage_id, 8786 &meter_table_x, &meter_table_y)); 8787 } else 8788 #endif 8789 { 8790 #if defined(BCM_FIREBOLT_SUPPORT) ||defined(BCM_RAPTOR_SUPPORT) 8791 BCM_IF_ERROR_RETURN 8792 (_field_fb_policer_mem_get (unit, f_ent, &meter_table_x)); 8793 #endif 8794 } 8795 8796 8797 /* Must be a valid meter index. */ 8798 if (old_hw_index == _FP_INVALID_INDEX) { 8799 return (BCM_E_INTERNAL); 8800 } 8801 8802 8803 idx = stage_fc->slices[f_ent->group->instance] 8804 [old_pool_index].start_tcam_idx 8805 + (2 * old_hw_index); 8806 8807 meter_idx = idx; 8808 for (iter = 0; iter < 2; iter++) { 8809 idx = meter_idx; 8810 8811 if (0 == iter) { 8812 meter_table = meter_table_x; 8813 } else { 8814 meter_table = meter_table_y; 8815 } 8816 8817 if (meter_table == INVALIDm) { 8818 continue; 8819 } 8820 8821 if (idx < soc_mem_index_min(unit, meter_table) || 8822 idx > soc_mem_index_max(unit, meter_table)) { 8823 return (BCM_E_INTERNAL); 8824 } 8825 8826 if (!(bcmPolicerModeCommitted == old_mode)) { 8827 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 8828 idx, soc_mem_entry_null(unit,meter_table)); 8829 BCM_IF_ERROR_RETURN(rv); 8830 8831 idx++; 8832 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 8833 idx, soc_mem_entry_null(unit,meter_table)); 8834 } else { 8835 if ((bcmPolicerModeCommitted == old_mode) && 8836 (!(old_hw_flags & _FP_POLICER_EXCESS_METER))) { 8837 idx ++; 8838 } 8839 8840 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 8841 idx, soc_mem_entry_null(unit,meter_table)); 8842 } 8843 } 8844 8845 return (BCM_E_NONE); 8846 } 8847 8848 STATIC int 8849 _field_policer_meter_hw_free_old(int unit, _field_entry_t *f_ent, 8850 _field_entry_policer_t *f_ent_pl) 8851 { 8852 _field_stage_t *stage_fc; /* Stage field control structure */ 8853 _field_policer_t *f_pl; /* Policer descriptor */ 8854 soc_mem_t meter_table_x; /* Meter table name */ 8855 soc_mem_t meter_table_y; /* Meter table name */ 8856 soc_mem_t meter_table; /* Meter table name */ 8857 int meter_idx; /* Meter hw index */ 8858 int idx; /* Meter hw index */ 8859 int rv = BCM_E_NONE; /* Return value */ 8860 int iter = 0; /* Iteration count */ 8861 8862 8863 meter_table_x = INVALIDm; 8864 meter_table_y = INVALIDm; 8865 /* Get field stage control structure. */ 8866 BCM_IF_ERROR_RETURN 8867 (_field_stage_control_get(unit, f_ent->group->stage_id, 8868 &stage_fc)); 8869 8870 #if defined(BCM_TOMAHAWK_SUPPORT) 8871 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 8872 return _bcm_field_th_policer_meter_hw_free_old(unit, f_ent, f_ent_pl); 8873 } 8874 #endif 8875 8876 /* Resolve meter table name. */ 8877 #if defined(BCM_TRX_SUPPORT) 8878 if (SOC_IS_TRX(unit)) { 8879 BCM_IF_ERROR_RETURN 8880 (_field_trx_meter_table_get(unit, f_ent->fs->stage_id, 8881 &meter_table_x, &meter_table_y)); 8882 } else 8883 #endif 8884 { 8885 #if defined(BCM_FIREBOLT_SUPPORT) ||defined(BCM_RAPTOR_SUPPORT) 8886 BCM_IF_ERROR_RETURN 8887 (_field_fb_policer_mem_get (unit, f_ent, &meter_table_x)); 8888 #endif 8889 } 8890 8891 /* Read policer configuration.*/ 8892 BCM_IF_ERROR_RETURN 8893 (_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 8894 8895 /* Must be a valid meter index. */ 8896 if (f_pl->hw_index == _FP_INVALID_INDEX) { 8897 return (BCM_E_INTERNAL); 8898 } 8899 8900 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 8901 /* Get slice policer installed in. */ 8902 idx = (f_pl->old_pool_index * 8903 stage_fc->meter_pool[f_ent->group->instance] 8904 [f_pl->old_pool_index]->pool_size) 8905 + (2 * f_pl->old_hw_index); 8906 8907 } else { 8908 idx = stage_fc->slices[f_ent->group->instance] 8909 [f_pl->old_pool_index].start_tcam_idx 8910 + (2 * f_pl->old_hw_index); 8911 } 8912 8913 meter_idx = idx; 8914 for (iter = 0; iter < 2; iter++) { 8915 idx = meter_idx; 8916 8917 if (0 == iter) { 8918 meter_table = meter_table_x; 8919 } else { 8920 meter_table = meter_table_y; 8921 } 8922 8923 if (meter_table == INVALIDm) { 8924 continue; 8925 } 8926 8927 if (idx < soc_mem_index_min(unit, meter_table) || 8928 idx > soc_mem_index_max(unit, meter_table)) { 8929 return (BCM_E_INTERNAL); 8930 } 8931 /* if not flow mode */ 8932 if (bcmPolicerModeCommitted != (f_pl)->old_mode) { 8933 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 8934 idx, soc_mem_entry_null(unit,meter_table)); 8935 BCM_IF_ERROR_RETURN(rv); 8936 8937 idx++; 8938 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 8939 idx, soc_mem_entry_null(unit,meter_table)); 8940 } else { 8941 /* if committed meter */ 8942 if ((bcmPolicerModeCommitted == (f_pl)->old_mode) && 8943 (!((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER))) { 8944 idx ++; 8945 } 8946 8947 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 8948 idx, soc_mem_entry_null(unit,meter_table)); 8949 } 8950 } 8951 8952 return (BCM_E_NONE); 8953 } 8954 /* 8955 * Function: 8956 * _field_policer_meter_hw_free 8957 * 8958 * Purpose: 8959 * Clear the meter entries from the h/w associated with the policer 8960 * 8961 * Parameters: 8962 * unit - (IN) BCM device number. 8963 * level - (IN) Policer level. 8964 * f_ent - (IN) Entry policer belongs to. 8965 * Returns: 8966 * BCM_E_XXX 8967 */ 8968 STATIC int 8969 _field_policer_meter_hw_free(int unit, _field_entry_t *f_ent, 8970 _field_entry_policer_t *f_ent_pl) 8971 { 8972 _field_stage_t *stage_fc; /* Stage field control structure */ 8973 _field_policer_t *f_pl; /* Policer descriptor */ 8974 soc_mem_t meter_table_x; /* Meter table name */ 8975 soc_mem_t meter_table_y; /* Meter table name */ 8976 soc_mem_t meter_table; /* Meter table name */ 8977 int meter_idx; /* Meter hw index */ 8978 int idx; /* Meter hw index */ 8979 int rv = BCM_E_NONE; /* Return value */ 8980 int iter = 0; /* Iteration count */ 8981 8982 8983 meter_table_x = INVALIDm; 8984 meter_table_y = INVALIDm; 8985 /* Get field stage control structure. */ 8986 BCM_IF_ERROR_RETURN 8987 (_field_stage_control_get(unit, f_ent->group->stage_id, 8988 &stage_fc)); 8989 8990 #if defined(BCM_TOMAHAWK_SUPPORT) 8991 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 8992 return _bcm_field_th_policer_meter_hw_free(unit, f_ent, f_ent_pl); 8993 } 8994 #endif 8995 8996 /* Resolve meter table name. */ 8997 #if defined(BCM_TRX_SUPPORT) 8998 if (SOC_IS_TRX(unit)) { 8999 BCM_IF_ERROR_RETURN 9000 (_field_trx_meter_table_get(unit, f_ent->fs->stage_id, 9001 &meter_table_x, &meter_table_y)); 9002 } else 9003 #endif 9004 { 9005 #if defined(BCM_FIREBOLT_SUPPORT) ||defined(BCM_RAPTOR_SUPPORT) 9006 BCM_IF_ERROR_RETURN 9007 (_field_fb_policer_mem_get (unit, f_ent, &meter_table_x)); 9008 #endif 9009 } 9010 9011 /* Read policer configuration.*/ 9012 BCM_IF_ERROR_RETURN 9013 (_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 9014 9015 /* Must be a valid meter index. */ 9016 if (f_pl->hw_index == _FP_INVALID_INDEX) { 9017 return (BCM_E_INTERNAL); 9018 } 9019 9020 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 9021 /* Get slice policer installed in. */ 9022 idx = (f_pl->pool_index * 9023 stage_fc->meter_pool[f_ent->group->instance] 9024 [f_pl->pool_index]->pool_size) 9025 + (2 * f_pl->hw_index); 9026 9027 } else { 9028 idx = stage_fc->slices[f_ent->group->instance] 9029 [f_pl->pool_index].start_tcam_idx 9030 + (2 * f_pl->hw_index); 9031 } 9032 9033 meter_idx = idx; 9034 for (iter = 0; iter < 2; iter++) { 9035 idx = meter_idx; 9036 9037 if (0 == iter) { 9038 meter_table = meter_table_x; 9039 } else { 9040 meter_table = meter_table_y; 9041 } 9042 9043 if (meter_table == INVALIDm) { 9044 continue; 9045 } 9046 9047 if (idx < soc_mem_index_min(unit, meter_table) || 9048 idx > soc_mem_index_max(unit, meter_table)) { 9049 return (BCM_E_INTERNAL); 9050 } 9051 9052 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 9053 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 9054 idx, soc_mem_entry_null(unit,meter_table)); 9055 BCM_IF_ERROR_RETURN(rv); 9056 9057 idx++; 9058 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 9059 idx, soc_mem_entry_null(unit,meter_table)); 9060 } else { 9061 if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 9062 idx ++; 9063 } 9064 9065 rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL, 9066 idx, soc_mem_entry_null(unit,meter_table)); 9067 } 9068 } 9069 9070 return (BCM_E_NONE); 9071 } 9072 9073 STATIC int 9074 _field_policer_hw_free_old(int unit, uint8 level, _field_entry_t *f_ent) 9075 { 9076 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure. */ 9077 _field_stage_t *stage_fc; /* Stage field contol. */ 9078 _field_policer_t *f_pl; /* Policer descriptor. */ 9079 _field_stage_id_t stage_id; /* Stage id used for metering. */ 9080 /* allocate even meter index for ingress metering for flow mode. 9081 * If set, the non-flow mode is disabled. Is available only for 9082 * Trident+ devices as there is an issue with metering on Y-pipe ports 9083 */ 9084 int use_even_meter; 9085 int is_trident_plus_use_even_meter; 9086 uint16 devid; 9087 uint8 revid; 9088 9089 /* Input parameters check. */ 9090 if ((NULL == f_ent) || (level >= _FP_POLICER_LEVEL_COUNT)) { 9091 return (BCM_E_PARAM); 9092 } 9093 9094 f_ent_pl = f_ent->policer + level; 9095 9096 if ((f_ent_pl->flags & _FP_POLICER_VALID) == 0 ) { 9097 return (BCM_E_NONE); 9098 } else { 9099 /* Read policer configuration.*/ 9100 BCM_IF_ERROR_RETURN 9101 (_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 9102 9103 /* Decrement policer reference counter. */ 9104 f_pl->old_sw_ref_count--; 9105 9106 } 9107 9108 /* Read policer configuration.*/ 9109 BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 9110 9111 /* Decrement hw reference count. */ 9112 if (f_pl->old_hw_ref_count > 0) { 9113 f_pl->old_hw_ref_count--; 9114 } 9115 9116 /* Policer not used by any other entry. */ 9117 if (f_pl->old_hw_ref_count == 0) { 9118 9119 stage_id = (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) ? \ 9120 _BCM_FIELD_STAGE_INGRESS : f_ent->group->stage_id; 9121 9122 /* Deinstall policer from hw. */ 9123 BCM_IF_ERROR_RETURN 9124 (_field_stage_control_get(unit, stage_id, &stage_fc)); 9125 9126 _field_policer_meter_hw_free_old(unit, f_ent, f_ent_pl); 9127 /* Mark hw resource as unused in sw. */ 9128 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 9129 BCM_IF_ERROR_RETURN 9130 (_field_meter_pool_entry_free_old(unit, stage_fc, 9131 f_ent->group->instance, f_pl)); 9132 } else { 9133 BCM_IF_ERROR_RETURN(_field_meter_hw_free_old(unit, f_ent)); 9134 } 9135 9136 is_trident_plus_use_even_meter = 0; 9137 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 9138 use_even_meter = soc_property_get(unit, 9139 spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0); 9140 if (use_even_meter) { 9141 soc_cm_get_id(unit, &devid, &revid); 9142 if ((devid == BCM56842_DEVICE_ID)|| 9143 (devid == BCM56844_DEVICE_ID)|| 9144 (devid == BCM56846_DEVICE_ID)|| 9145 (devid == BCM56847_DEVICE_ID)|| 9146 (devid == BCM56053_DEVICE_ID)|| 9147 (devid == BCM56549_DEVICE_ID)|| 9148 (devid == BCM56831_DEVICE_ID)|| 9149 (devid == BCM56835_DEVICE_ID)|| 9150 (devid == BCM56838_DEVICE_ID)|| 9151 (devid == BCM56849_DEVICE_ID) 9152 ) { 9153 is_trident_plus_use_even_meter = 1; 9154 } 9155 } 9156 } 9157 /* decrement group meter count when the hw_ref_count 9158 becomes 0 */ 9159 f_ent->group->group_status.meter_count--; 9160 /* for flow mode, 1 meter is associated to group 9161 and for all other modes, 2 meters are associated */ 9162 if(bcmPolicerModeCommitted != (f_pl)->old_mode) { 9163 f_ent->group->group_status.meter_count--; 9164 } 9165 9166 if(bcmPolicerModeCommitted == (f_pl)->old_mode) { 9167 if (is_trident_plus_use_even_meter) { 9168 f_ent->group->group_status.meter_count--; 9169 } 9170 } 9171 /*reset the old ploicer data stored to default */ 9172 sal_memset(&f_pl->old_cfg, 0x00, sizeof(bcm_policer_config_t)); 9173 f_pl->old_hw_flags = 0; 9174 #ifdef BCM_TRIUMPH3_SUPPORT 9175 f_pl->old_logical_pool_index = _FP_INVALID_INDEX; 9176 #endif 9177 f_pl->old_mode = 0; 9178 f_pl->old_pool_index = _FP_INVALID_INDEX; 9179 f_pl->old_level = 0; 9180 f_pl->old_hw_index = _FP_INVALID_INDEX; 9181 f_pl->old_sw_ref_count = 0; 9182 f_pl->old_hw_ref_count = 0; 9183 } 9184 9185 /* Decrement policer reference counter. */ 9186 f_pl->old_sw_ref_count--; 9187 9188 return (BCM_E_NONE); 9189 } 9190 9191 STATIC int 9192 _field_policer_hw_free(int unit, uint8 level, _field_entry_t *f_ent) 9193 { 9194 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure. */ 9195 _field_stage_t *stage_fc; /* Stage field contol. */ 9196 _field_policer_t *f_pl; /* Policer descriptor. */ 9197 _field_stage_id_t stage_id; /* Stage id used for metering. */ 9198 /* allocate even meter index for ingress metering for flow mode. 9199 * If set, the non-flow mode is disabled. Is available only for 9200 * Trident+ devices as there is an issue with metering on Y-pipe ports 9201 */ 9202 int use_even_meter; 9203 int is_trident_plus_use_even_meter; 9204 uint16 devid; 9205 uint8 revid; 9206 9207 /* Input parameters check. */ 9208 if ((NULL == f_ent) || (level >= _FP_POLICER_LEVEL_COUNT)) { 9209 return (BCM_E_PARAM); 9210 } 9211 9212 f_ent_pl = f_ent->policer + level; 9213 9214 if (f_ent_pl->flags & _FP_POLICER_INSTALLED) { 9215 f_ent_pl->flags = _FP_POLICER_DETACH; 9216 return (BCM_E_NONE); 9217 } else { 9218 if (0 == (f_ent_pl->flags & _FP_POLICER_DETACH)) { 9219 /* Read policer configuration.*/ 9220 BCM_IF_ERROR_RETURN 9221 (_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 9222 9223 /* Decrement policer reference counter. */ 9224 f_pl->sw_ref_count--; 9225 9226 f_ent_pl->pid = _FP_INVALID_INDEX; 9227 f_ent_pl->flags = 0; 9228 9229 return (BCM_E_NONE); 9230 } 9231 } 9232 9233 /* Read policer configuration.*/ 9234 BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl)); 9235 9236 /* Decrement hw reference count. */ 9237 if (f_pl->hw_ref_count > 0) { 9238 f_pl->hw_ref_count--; 9239 } 9240 9241 /* Policer not used by any other entry. */ 9242 if (f_pl->hw_ref_count == 0) { 9243 9244 stage_id = (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) ? \ 9245 _BCM_FIELD_STAGE_INGRESS : f_ent->group->stage_id; 9246 9247 /* Deinstall policer from hw. */ 9248 BCM_IF_ERROR_RETURN 9249 (_field_stage_control_get(unit, stage_id, &stage_fc)); 9250 9251 _field_policer_meter_hw_free(unit, f_ent, f_ent_pl); 9252 /* Mark hw resource as unused in sw. */ 9253 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 9254 BCM_IF_ERROR_RETURN 9255 (_field_meter_pool_entry_free(unit, stage_fc, 9256 f_ent->group->instance, f_pl)); 9257 } else { 9258 BCM_IF_ERROR_RETURN(_field_meter_hw_free(unit, f_ent)); 9259 } 9260 9261 is_trident_plus_use_even_meter = 0; 9262 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 9263 use_even_meter = soc_property_get(unit, 9264 spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0); 9265 if (use_even_meter) { 9266 soc_cm_get_id(unit, &devid, &revid); 9267 if ((devid == BCM56842_DEVICE_ID)|| 9268 (devid == BCM56844_DEVICE_ID)|| 9269 (devid == BCM56846_DEVICE_ID)|| 9270 (devid == BCM56847_DEVICE_ID)|| 9271 (devid == BCM56053_DEVICE_ID)|| 9272 (devid == BCM56549_DEVICE_ID)|| 9273 (devid == BCM56831_DEVICE_ID)|| 9274 (devid == BCM56835_DEVICE_ID)|| 9275 (devid == BCM56838_DEVICE_ID)|| 9276 (devid == BCM56849_DEVICE_ID) 9277 ) { 9278 is_trident_plus_use_even_meter = 1; 9279 } 9280 } 9281 } 9282 /* decrement group meter count when the hw_ref_count 9283 becomes 0 */ 9284 f_ent->group->group_status.meter_count--; 9285 /* for flow mode, 1 meter is associated to group 9286 and for all other modes, 2 meters are associated */ 9287 if(!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 9288 f_ent->group->group_status.meter_count--; 9289 } 9290 9291 if(_FP_POLICER_IS_FLOW_MODE(f_pl)) { 9292 if (is_trident_plus_use_even_meter) { 9293 f_ent->group->group_status.meter_count--; 9294 } 9295 } 9296 /* Mark policer for reinstallation. */ 9297 BCM_IF_ERROR_RETURN (_field_policer_hw_flags_set(unit, f_pl, 0)); 9298 } 9299 9300 /* Decrement policer reference counter. */ 9301 f_pl->sw_ref_count--; 9302 9303 f_ent_pl->pid = _FP_INVALID_INDEX; 9304 f_ent_pl->flags = 0; 9305 9306 return (BCM_E_NONE); 9307 } 9308 9309 /* 9310 * Function: 9311 * _field_policers_hw_alloc 9312 * 9313 * Purpose: 9314 * Allocate policers required for entry installation. 9315 * 9316 * Parameters: 9317 * unit - (IN) BCM device number. 9318 * f_ent - (IN) Field entry array. 9319 * Returns: 9320 * BCM_E_XXX 9321 * Notes: 9322 */ 9323 STATIC int 9324 _field_policers_hw_alloc(int unit, _field_entry_t *f_ent) 9325 { 9326 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 9327 _field_stage_t *stage_fc; /* Stage field control. */ 9328 _field_policer_t *f_pl; /* Field policer descriptor. */ 9329 _field_control_t *fc; /* Field control structure. */ 9330 int idx; /* Policer levels iterator. */ 9331 int rv; /* Operation return status. */ 9332 _field_meter_pool_t *f_mp; /* Meter pool descriptor. */ 9333 /* allocate even meter index for ingress metering for flow mode. 9334 * If set, the non-flow mode is disabled. Is available only for 9335 * Trident+ devices as there is an issue with metering on Y-pipe ports 9336 */ 9337 int use_even_meter; 9338 int is_trident_plus_use_even_meter; 9339 uint16 devid; 9340 uint8 revid; 9341 int eid; /* Entry ID. */ 9342 int tmp = 0; /* Temporary iterator. */ 9343 _field_group_t *fg; /* Field group info. */ 9344 #if defined (BCM_TOMAHAWK_SUPPORT) 9345 _field_stage_t *stage_em; /* Field stage control structure. */ 9346 uint8 pipe = 0; /* Field Pipe Info */ 9347 int meter_pairs_per_pool = 0; 9348 int size = 0; 9349 #endif 9350 9351 /* Input parameters check. */ 9352 if (NULL == f_ent) { 9353 return (BCM_E_PARAM); 9354 } 9355 9356 /* Get field control structure. */ 9357 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 9358 9359 /* Get field stage control structure. */ 9360 rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc); 9361 BCM_IF_ERROR_RETURN(rv); 9362 9363 is_trident_plus_use_even_meter = 0; 9364 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 9365 use_even_meter = soc_property_get(unit, 9366 spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0); 9367 if (use_even_meter) { 9368 soc_cm_get_id(unit, &devid, &revid); 9369 if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)|| 9370 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)|| 9371 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)|| 9372 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)|| 9373 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID) 9374 ) { 9375 is_trident_plus_use_even_meter = 1; 9376 } 9377 } 9378 } 9379 9380 /* Allocate policers if necessary. */ 9381 for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) { 9382 f_ent_pl = f_ent->policer + idx; 9383 /* Skip invalid policers. */ 9384 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 9385 continue; 9386 } 9387 9388 /* Read policer configuration.*/ 9389 rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl); 9390 BCM_IF_ERROR_RETURN(rv); 9391 9392 /* 9393 * Check if entry's primary slice_number matches 9394 * Policer meter pool slice_id for Level0 policer. 9395 */ 9396 if ((!(_FP_POLICER_GROUP_SHARE_ENABLE & fc->flags)) && 9397 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 9398 9399 if ((0 == idx) && (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) 9400 && (_FP_INVALID_INDEX != f_pl->pool_index)) { 9401 9402 #if defined(BCM_TRIUMPH3_SUPPORT) 9403 if (SOC_IS_TRIUMPH3(unit) && 9404 (fc->ingress_logical_policer_pools_mode != 9405 bcmFieldIngressLogicalPolicerPools8x1024)) { 9406 f_mp = stage_fc->logical_meter_pool 9407 [f_pl->logical_pool_index]; 9408 } else 9409 #endif 9410 { 9411 f_mp = stage_fc->meter_pool[f_ent->group->instance] 9412 [f_pl->pool_index]; 9413 } 9414 if (f_ent->group->slices->slice_number != f_mp->slice_id) { 9415 return (BCM_E_PARAM); 9416 } 9417 9418 } 9419 } 9420 9421 /* 9422 * Check policer mode support - double check in case 9423 * attached policer was modified by bcm_policer_set API. 9424 */ 9425 rv = _field_policer_mode_support(unit, f_ent, idx, f_pl); 9426 BCM_IF_ERROR_RETURN(rv); 9427 9428 /* Allocate policer hw index. */ 9429 if (_FP_INVALID_INDEX == f_pl->hw_index) { 9430 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 9431 rv = _field_meterpool_hw_entry_alloc(unit, f_ent, f_pl); 9432 } else { 9433 rv = _field_meter_hw_alloc(unit, f_ent, f_ent->fs); 9434 } 9435 /* if there is an error in alocating the meter 9436 * then reset the policer data of all the entries that are 9437 * using the policer as that of the current entry to the old 9438 * data of the policer and reset the flags 9439 */ 9440 if (BCM_FAILURE(rv)) { 9441 if (f_ent->flags & _FP_ENTRY_METER_MODIFIED) { 9442 /* reset the entry meter modiied flag so that the meter 9443 * entry wont get cleared when meter is not allocated 9444 */ 9445 for (fg = fc->groups; fg != NULL; fg = fg->next) { 9446 tmp = 0; 9447 /* 9448 * Check for all entries where the policer was assigned 9449 */ 9450 while (tmp < fg->group_status.entry_count) { 9451 eid = (fg->entry_arr[tmp])->eid; 9452 /* Get entry description structure. */ 9453 BCM_IF_ERROR_RETURN(_field_entry_get(unit, eid, 9454 _FP_ENTRY_PRIMARY, &f_ent)); 9455 f_ent_pl = f_ent->policer + idx; 9456 if (f_ent_pl->pid == f_pl->pid) { 9457 f_ent->flags &= 9458 ~_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 9459 f_ent->flags &= ~_FP_ENTRY_METER_MODIFIED; 9460 } 9461 tmp++; 9462 } 9463 } 9464 } else if ((idx == 1) && 9465 (f_ent->policer->flags & _FP_POLICER_VALID)) { 9466 /* when hw allocation fails for level 1 policer, 9467 * check if lvl0 is valid and release lvl0 policer 9468 */ 9469 BCM_IF_ERROR_RETURN(_field_policer_hw_free(unit,0,f_ent)); 9470 } 9471 return rv; 9472 } 9473 } 9474 9475 /* Increment hw reference count. */ 9476 if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) { 9477 f_ent_pl->flags |= _FP_POLICER_INSTALLED; 9478 f_pl->hw_ref_count++; 9479 /* Increment group meter count when hw_ref_count 9480 becomes 1 (policer can be shared). */ 9481 f_ent->group->group_status.meter_count++; 9482 /* for flow mode, 1 meter is associated to group 9483 and for all other modes, 2 meters are associated */ 9484 if(!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 9485 f_ent->group->group_status.meter_count++; 9486 } 9487 if(_FP_POLICER_IS_FLOW_MODE(f_pl)) { 9488 if (is_trident_plus_use_even_meter) { 9489 f_ent->group->group_status.meter_count++; 9490 } 9491 } 9492 } 9493 9494 if (f_pl->hw_flags & _FP_POLICER_DIRTY) { 9495 BCM_IF_ERROR_RETURN(fc->functions.fp_policer_install(unit, f_ent, f_pl)); 9496 } 9497 9498 #if defined (BCM_TOMAHAWK_SUPPORT) 9499 if ((soc_feature(unit, soc_feature_field_multi_pipe_support)) && 9500 (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) { 9501 9502 rv = (_field_stage_control_get(unit, 9503 _BCM_FIELD_STAGE_EXACTMATCH , &stage_em)); 9504 9505 if (BCM_SUCCESS(rv)) { 9506 9507 if (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) { 9508 fc->ifp_em_meter_in_use[f_ent->group->instance][f_pl->pool_index] 9509 = BCM_FIELD_METER_POOL_USED_BY_EM; 9510 } else 9511 if (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) { 9512 fc->ifp_em_meter_in_use[f_ent->group->instance][f_pl->pool_index] 9513 = BCM_FIELD_METER_POOL_USED_BY_IFP; 9514 } 9515 9516 if (soc_feature(unit, soc_feature_td3_style_fp)) { 9517 meter_pairs_per_pool = BCM_FIELD_INGRESS_TD3_NUM_METER_PAIRS_PER_POOL; 9518 } else { 9519 meter_pairs_per_pool = BCM_FIELD_INGRESS_TH_NUM_METER_PAIRS_PER_POOL; 9520 } 9521 9522 pipe = f_ent->group->instance; 9523 9524 /* Initialize number of meter per pool.*/ 9525 size = SHR_BITALLOCSIZE(meter_pairs_per_pool << 1); 9526 if ((_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) || 9527 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 9528 sal_memcpy(stage_em->meter_pool[pipe][f_pl->pool_index]->meter_bmp.w, 9529 stage_fc->meter_pool[pipe][f_pl->pool_index]->meter_bmp.w, 9530 size); 9531 stage_em->meter_pool[pipe][f_pl->pool_index]->level = 9532 stage_fc->meter_pool[pipe][f_pl->pool_index]->level; 9533 stage_em->meter_pool[pipe][f_pl->pool_index]->slice_id = 9534 stage_fc->meter_pool[pipe][f_pl->pool_index]->slice_id; 9535 stage_em->meter_pool[pipe][f_pl->pool_index]->size = 9536 stage_fc->meter_pool[pipe][f_pl->pool_index]->size; 9537 stage_em->meter_pool[pipe][f_pl->pool_index]->pool_size = 9538 stage_fc->meter_pool[pipe][f_pl->pool_index]->pool_size; 9539 stage_em->meter_pool[pipe][f_pl->pool_index]->free_meters = 9540 stage_fc->meter_pool[pipe][f_pl->pool_index]->free_meters; 9541 stage_em->meter_pool[pipe][f_pl->pool_index]->num_meter_pairs = 9542 stage_fc->meter_pool[pipe][f_pl->pool_index]->num_meter_pairs; 9543 } 9544 } else { 9545 if (rv != BCM_E_UNAVAIL) { 9546 return rv; 9547 } 9548 } 9549 } 9550 #endif 9551 } 9552 return (BCM_E_NONE); 9553 } 9554 9555 int 9556 _field_policers_hw_free_old(int unit, _field_entry_t *f_ent) 9557 { 9558 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 9559 int idx; /* Policer levels iterator. */ 9560 9561 /* Input parameters check. */ 9562 if (NULL == f_ent) { 9563 return (BCM_E_PARAM); 9564 } 9565 9566 /* meter release will be called only if _FP_ENTRY_METER_MODIFIED 9567 * is set. once the function is called, the flag is reset 9568 * so that it gets called only for the firt time entry install is called. 9569 */ 9570 if ((f_ent->flags & _FP_ENTRY_METER_MODIFIED) == 0) { 9571 return BCM_E_NONE; 9572 } 9573 9574 /* de-allocate policers*/ 9575 for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) { 9576 f_ent_pl = f_ent->policer + idx; 9577 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 9578 continue; 9579 } 9580 BCM_IF_ERROR_RETURN(_field_policer_hw_free_old(unit, idx, f_ent)); 9581 } 9582 9583 /*reset the flag */ 9584 f_ent->flags &= ~_FP_ENTRY_METER_MODIFIED; 9585 return (BCM_E_NONE); 9586 } 9587 9588 /* 9589 * Function: 9590 * _field_policers_hw_free 9591 * 9592 * Purpose: 9593 * Free entry policers. 9594 * 9595 * Parameters: 9596 * unit - (IN) BCM device number. 9597 * f_ent - (IN) Field entry descriptor. 9598 * flags - (IN) Flags to free old/all resources 9599 * Returns: 9600 * BCM_E_XXX 9601 * Notes: 9602 */ 9603 STATIC int 9604 _field_policers_hw_free(int unit, _field_entry_t *f_ent, uint32 flags) 9605 { 9606 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 9607 int idx; /* Policer levels iterator. */ 9608 bcm_policer_t policer_id = -1; /* Policer Id. */ 9609 uint8 isPolicerDetach = 0; 9610 9611 /* Input parameters check. */ 9612 if (NULL == f_ent) { 9613 return (BCM_E_PARAM); 9614 } 9615 9616 /* Allocate policers if necessary. */ 9617 for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) { 9618 f_ent_pl = f_ent->policer + idx; 9619 policer_id = f_ent_pl->pid; 9620 isPolicerDetach = (f_ent_pl->flags & _FP_POLICER_DETACH); 9621 9622 if ((_FP_ACTION_OLD_RESOURCE_FREE & flags) && 9623 (0 == (f_ent_pl->flags & _FP_POLICER_DETACH))) { 9624 /* Old resourse should have the detach flag set */ 9625 continue; 9626 } 9627 9628 if (0 == (f_ent_pl->flags & _FP_POLICER_DETACH)) { 9629 /* Skip invalid policers. */ 9630 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 9631 continue; 9632 } 9633 /* Skip installed policers. */ 9634 if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) { 9635 continue; 9636 } 9637 } 9638 9639 if ((_FP_ACTION_RESOURCE_FREE & flags) && 9640 (0 == (f_ent_pl->flags & _FP_POLICER_DETACH))) { 9641 /* Forced released if h/w resources 9642 * When this comes to this place, then the policer 9643 * is not detached but it is valid and installed 9644 * Mark the policy as detached and release the resource 9645 */ 9646 f_ent_pl->flags = _FP_POLICER_DETACH; 9647 } 9648 9649 BCM_IF_ERROR_RETURN(_field_policer_hw_free(unit, idx, f_ent)); 9650 9651 if ((flags & _FP_ACTION_POLICER_SW_UPDATE) && (!isPolicerDetach)) { 9652 BCM_IF_ERROR_RETURN (bcm_esw_field_entry_policer_attach 9653 (unit,f_ent->eid, 9654 idx,policer_id)); 9655 } 9656 } 9657 return (BCM_E_NONE); 9658 } 9659 9660 9661 /* 9662 * Function: 9663 * _field_entry_policer_detach 9664 * Purpose: 9665 * Detach a policer from a field entry. 9666 * Parameters: 9667 * unit - (IN) Unit number. 9668 * entry_id - (IN) Field entry ID. 9669 * level - (IN) Policer level. 9670 * Returns: 9671 * BCM_E_XXX 9672 * Notes: 9673 */ 9674 int 9675 _field_entry_policer_detach(int unit, _field_entry_t *f_ent, int level) 9676 { 9677 _field_entry_policer_t *f_ent_pl;/* Field entry policer structure.*/ 9678 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 9679 defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 9680 int rv=0; 9681 vfp_policy_table_entry_t vfp_entry; 9682 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT || 9683 BCM_APACHE_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 9684 /* Input parameters check. */ 9685 if ((level >= _FP_POLICER_LEVEL_COUNT) || (level < 0)) { 9686 return (BCM_E_PARAM); 9687 } 9688 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 9689 defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 9690 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit) || 9691 SOC_IS_GREYHOUND2(unit)) { 9692 if ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) || 9693 (SOC_IS_TRIUMPH3(unit) && 9694 (_BCM_FIELD_STAGE_EXTERNAL == f_ent->group->stage_id))) { 9695 rv = _bcm_esw_delete_policer_from_table(unit, 9696 f_ent->global_meter_policer.pid, VFP_POLICY_TABLEm,0,&vfp_entry); 9697 if (BCM_FAILURE(rv)) { 9698 return (rv); 9699 } 9700 f_ent->global_meter_policer.pid = 0; 9701 f_ent->global_meter_policer.flags = 0; 9702 /* Entry must be reinstalled for policer to take effect. */ 9703 f_ent->flags |= _FP_ENTRY_DIRTY; 9704 return (BCM_E_NONE); 9705 } 9706 } 9707 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT || 9708 BCM_APACHE_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 9709 /* Make sure policer attached to the entry. */ 9710 f_ent_pl = f_ent->policer + level; 9711 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 9712 return (BCM_E_EMPTY); 9713 } 9714 9715 /* If entry was installed decrement hw reference counter. */ 9716 BCM_IF_ERROR_RETURN(_field_policer_hw_free (unit, level, f_ent)); 9717 9718 /* 9719 * If qualifiers have not been modified for this entry, 9720 * set Policy table only dirty flag. 9721 */ 9722 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 9723 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 9724 } 9725 /* Mark entry for reinstall. */ 9726 f_ent->flags |= _FP_ENTRY_DIRTY; 9727 9728 return (BCM_E_NONE); 9729 } 9730 9731 /* 9732 * Function: 9733 * _bcm_field_stat_get 9734 * Purpose: 9735 * Lookup a statistics entity description structure by stat id. 9736 * Parmeters: 9737 * unit - (IN) BCM device number. 9738 * sid - (IN) Statistics entity id. 9739 * stat_p - (OUT) Lookup result. 9740 * Returns: 9741 * BCM_E_XXX 9742 */ 9743 int 9744 _bcm_field_stat_get(int unit, int sid, _field_stat_t **stat_p) 9745 { 9746 _field_stat_t *f_st; /* Policer lookup pointer. */ 9747 _field_control_t *fc; /* Field control structure. */ 9748 uint32 hash_index; /* Entry hash. */ 9749 9750 /* Input parameters check. */ 9751 if (NULL == stat_p) { 9752 return (BCM_E_PARAM); 9753 } 9754 9755 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 9756 9757 hash_index = sid & _FP_HASH_INDEX_MASK(fc); 9758 f_st = fc->stat_hash[hash_index]; 9759 while (NULL != f_st) { 9760 /* Match entry id. */ 9761 if (f_st->sid == sid) { 9762 *stat_p = f_st; 9763 return (BCM_E_NONE); 9764 } 9765 f_st = f_st->next; 9766 } 9767 9768 /* Statistics entity with sid == sid was not found. */ 9769 return (BCM_E_NOT_FOUND); 9770 } 9771 9772 /* 9773 * Function: 9774 * _bcm_field_stat_id_alloc 9775 * Purpose: 9776 * Allocate a statistics entity id. 9777 * Parameters: 9778 * unit - (IN) BCM device number. 9779 * sid - (OUT) Stat id. 9780 * Returns: 9781 * BCM_E_XXX 9782 * Notes: 9783 */ 9784 int 9785 _bcm_field_stat_id_alloc(int unit, int *sid) 9786 { 9787 int max_count; /* Maximum number of sids to try.*/ 9788 _field_stat_t *f_st; /* Field stat descriptor. */ 9789 int rv; /* Operation return status. */ 9790 static uint32 last_allocated_sid = 0; /* Policer id alloc tracker. */ 9791 9792 /* Input parameters check. */ 9793 if (NULL == sid) { 9794 return (BCM_E_PARAM); 9795 } 9796 9797 max_count = _FP_ID_MAX; 9798 while (max_count--) { 9799 last_allocated_sid++; 9800 if (_FP_ID_MAX == last_allocated_sid) { 9801 last_allocated_sid = _FP_ID_BASE; 9802 } 9803 rv = _bcm_field_stat_get(unit, last_allocated_sid, &f_st); 9804 if (BCM_E_NOT_FOUND == rv) { 9805 *sid = last_allocated_sid; 9806 return (BCM_E_NONE); 9807 } 9808 if (BCM_FAILURE(rv)) { 9809 return (rv); 9810 } 9811 } 9812 return (BCM_E_RESOURCE); 9813 } 9814 9815 9816 /* 9817 * Function: 9818 * _field_stat_array_to_bmap 9819 * 9820 * Description: 9821 * API caller statistics array bit map 9822 * Parameters: 9823 * unit - (IN) BCM device number. 9824 * f_st - (IN) Field statistics entity. 9825 * bmap - (OUT) Field group id. 9826 * Returns: 9827 * BCM_E_XXX 9828 */ 9829 STATIC int 9830 _field_stat_array_to_bmap(int unit, _field_stat_t *f_st, uint32 *bmap) 9831 { 9832 int idx; 9833 9834 /* Input parameters check */ 9835 if ((NULL == f_st) || (NULL == bmap)) { 9836 return (BCM_E_PARAM); 9837 } 9838 9839 *bmap = 0; 9840 for (idx = 0; idx < f_st->nstat; idx++) { 9841 if (NULL == (f_st->stat_arr + idx)) { 9842 /* 9843 * COVERITY 9844 * 9845 * This conditin may not hit. 9846 * It is kept intentionally as a defensive check. 9847 */ 9848 /* coverity[dead_error_line] */ 9849 return (BCM_E_PARAM); 9850 } 9851 9852 /* coverity[mixed_enums] */ 9853 if ((int)f_st->stat_arr[idx] >= _bcmFieldStatCount) { 9854 return (BCM_E_PARAM); 9855 } 9856 9857 *bmap |= (1 << (int)f_st->stat_arr[idx]); 9858 } 9859 return (BCM_E_NONE); 9860 } 9861 /* 9862 * Function: 9863 * _bcm_field_stat_array_to_bmap 9864 * 9865 * Description: 9866 * API caller statistics array bit map 9867 * Parameters: 9868 * unit - (IN) BCM device number. 9869 * f_st - (IN) Field statistics entity. 9870 * bmap - (OUT) Field group id. 9871 * Returns: 9872 * BCM_E_XXX 9873 */ 9874 int 9875 _bcm_field_stat_array_to_bmap(int unit, _field_stat_t *f_st, uint32 *bmap) 9876 { 9877 return _field_stat_array_to_bmap(unit, f_st, bmap); 9878 } 9879 /* 9880 * Function: 9881 * _field_stat_hw_mode_to_bmap 9882 * 9883 * Description: 9884 * HW counter mode to statistics bitmap. 9885 * Parameters: 9886 * unit - (IN) BCM device number. 9887 * mode - (IN) HW counter mode. 9888 * stage_id - (IN) Stage id. 9889 * hw_bmap - (OUT) Statistics bitmap. 9890 * hw_entry_count - (OUT) Number of counters required. 9891 * Returns: 9892 * BCM_E_XXX 9893 */ 9894 STATIC int 9895 _field_stat_hw_mode_to_bmap(int unit, uint16 mode, 9896 _field_stage_id_t stage_id, 9897 uint32 *hw_bmap, uint8 *hw_entry_count) 9898 { 9899 int rv; 9900 9901 /* Input parameters check. */ 9902 if ((NULL == hw_bmap) || (NULL == hw_entry_count)) { 9903 return (BCM_E_PARAM); 9904 } 9905 9906 #ifdef BCM_TRIUMPH3_SUPPORT 9907 if (SOC_IS_TRIUMPH3(unit)) { 9908 rv = _bcm_field_tr3_stat_hw_mode_to_bmap(unit, 9909 mode, 9910 stage_id, 9911 hw_bmap, 9912 hw_entry_count 9913 ); 9914 } else 9915 #endif 9916 #if defined(BCM_TRIDENT_SUPPORT) 9917 if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) && 9918 (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 9919 rv = _bcm_field_trident_stat_hw_mode_to_bmap(unit, mode, stage_id, 9920 hw_bmap, hw_entry_count); 9921 } else 9922 #endif /* BCM_TRIDENT_SUPPORT */ 9923 #if defined(BCM_TRIUMPH2_SUPPORT) 9924 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) 9925 || SOC_IS_VALKYRIE2(unit)) { 9926 rv = _bcm_field_tr2_stat_hw_mode_to_bmap(unit, mode, stage_id, 9927 hw_bmap, hw_entry_count); 9928 } else 9929 #endif /* !BCM_TRIUMPH2_SUPPORT */ 9930 #if defined(BCM_TRX_SUPPORT) 9931 if (SOC_IS_TRX(unit)) { 9932 rv = _bcm_field_trx_stat_hw_mode_to_bmap(unit, mode, stage_id, 9933 hw_bmap, hw_entry_count); 9934 } else 9935 #endif /* BCM_TRX_SUPPORT */ 9936 { 9937 rv = _bcm_field_fb_stat_hw_mode_to_bmap(unit, mode, stage_id, 9938 hw_bmap, hw_entry_count); 9939 } 9940 return (rv); 9941 } 9942 9943 #if defined(BCM_HURRICANE3_SUPPORT) 9944 /* 9945 * Function: 9946 * _field_flowcnt_mode_get 9947 * Purpose: 9948 * Get flowcnt stat hardware counter mode information 9949 * Parameters: 9950 * unit - (IN) BCM device number 9951 * f_st - (IN) Pointer to field stat structure 9952 * Returns: 9953 * BCM_E_XXX 9954 */ 9955 STATIC int 9956 _field_flowcnt_mode_get(int unit, 9957 _field_stat_t *f_st) 9958 { 9959 uint32 req_bmap; /* Requested statistics bitmap. */ 9960 9961 /* Input parameter check. */ 9962 if (NULL == f_st) { 9963 return (BCM_E_PARAM); 9964 } 9965 9966 /* Get application requested bitmap. */ 9967 BCM_IF_ERROR_RETURN 9968 (_field_stat_array_to_bmap(unit, f_st, &req_bmap)); 9969 9970 /* If bitmap is zero - no mode selection is required. */ 9971 if (0 == req_bmap) { 9972 f_st->hw_mode = 0; 9973 f_st->hw_stat = 0; 9974 f_st->hw_flags |= _FP_STAT_FLOWCNT_CNTR; 9975 f_st->flex_mode = 0; 9976 f_st->hw_entry_count = 0; 9977 return (BCM_E_NONE); 9978 } 9979 9980 /* VFP stages support only Pkt or Byte STATs */ 9981 if ((req_bmap != (1 << (int)bcmFieldStatBytes)) && 9982 (req_bmap != (1 << (int)bcmFieldStatPackets))) { 9983 return (BCM_E_UNAVAIL); 9984 } 9985 9986 /* Initialize stat structure with flowcnt stat parameter info. */ 9987 f_st->hw_mode = (int) bcmStatGroupModeSingle; 9988 f_st->hw_stat = req_bmap; 9989 f_st->hw_flags |= _FP_STAT_FLOWCNT_CNTR; 9990 f_st->flex_mode = 0; 9991 /* No. of hw entries is known only after Flow Count STAT alloc. */ 9992 /* f_st->hw_entry_count = 1; */ 9993 9994 return (BCM_E_NONE); 9995 } 9996 #endif 9997 9998 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 9999 /* 10000 * Function: 10001 * _field_flex_mode_get 10002 * Purpose: 10003 * Get flex stat hardware counter mode information 10004 * Parameters: 10005 * unit - (IN) BCM device number 10006 * f_st - (IN) Pointer to field stat structure 10007 * Returns: 10008 * BCM_E_XXX 10009 */ 10010 STATIC int 10011 _field_flex_mode_get(int unit, 10012 _field_stat_t *f_st) 10013 { 10014 uint32 req_bmap; /* Requested statistics bitmap. */ 10015 uint32 valid_bmap; /* Bitmap of valid flex STAT types. */ 10016 10017 /* Input parameter check. */ 10018 if (NULL == f_st) { 10019 return (BCM_E_PARAM); 10020 } 10021 10022 /* Get application requested bitmap. */ 10023 BCM_IF_ERROR_RETURN 10024 (_field_stat_array_to_bmap(unit, f_st, &req_bmap)); 10025 10026 /* If bitmap is zero - no mode selection is required. */ 10027 if (0 == req_bmap) { 10028 f_st->hw_mode = 0; 10029 f_st->hw_stat = 0; 10030 f_st->hw_flags |= _FP_STAT_FLEX_CNTR; 10031 f_st->flex_mode = 0; 10032 f_st->hw_entry_count = 0; 10033 return (BCM_E_NONE); 10034 } 10035 10036 /* VFP stages support only Pkt and Byte STATs */ 10037 valid_bmap = ((1 << (int) bcmFieldStatBytes) | 10038 (1 << (int) bcmFieldStatPackets)); 10039 10040 /* Validate requested STAT types. */ 10041 if (req_bmap & ~(valid_bmap)) { 10042 return (BCM_E_UNAVAIL); 10043 } 10044 10045 /* Initialize stat structure with flex stat parameter info. */ 10046 f_st->hw_mode = (int) bcmStatGroupModeSingle; 10047 f_st->hw_stat = req_bmap; 10048 f_st->hw_flags |= _FP_STAT_FLEX_CNTR; 10049 f_st->flex_mode = 0; 10050 /* No. of hw entries is known only after Flex Hw STAT alloc. */ 10051 /* f_st->hw_entry_count = 1; */ 10052 10053 return (BCM_E_NONE); 10054 } 10055 #endif 10056 10057 /* 10058 * Function: 10059 * _bcm_field_stat_hw_mode_get 10060 * 10061 * Description: 10062 * Get hw counter mode which will satisfy requested statistics set. 10063 * Parameters: 10064 * unit - (IN) BCM device number. 10065 * f_st - (IN) Field statistics entity. 10066 * stage_id - (IN) Field stage id. 10067 * Returns: 10068 * BCM_E_XXX 10069 */ 10070 int 10071 _bcm_field_stat_hw_mode_get(int unit, _field_stat_t *f_st, 10072 _field_stage_id_t stage_id) 10073 { 10074 uint32 req_bmap; /* Requested statistics bitmap. */ 10075 uint32 hw_bmap; /* HW supported statistics bitmap. */ 10076 uint8 hw_entry_count; /* Number of counter table entries.*/ 10077 uint16 idx; /* HW counter modes iterator. */ 10078 int rv; /* Operation return status. */ 10079 int fp_stat_hw_mode_max; 10080 10081 /* Input parameters check. */ 10082 if (NULL == f_st) { 10083 return (BCM_E_PARAM); 10084 } 10085 10086 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 10087 /* 10088 * If device supports advanced flex counters 10089 * and stage is lookup stage, then get 10090 * flex stat mode for this Stat. 10091 */ 10092 if (soc_feature(unit, soc_feature_advanced_flex_counter) 10093 && ((_BCM_FIELD_STAGE_LOOKUP == stage_id) 10094 || (_BCM_FIELD_STAGE_EXTERNAL == stage_id))) { 10095 return (_field_flex_mode_get(unit, f_st)); 10096 } 10097 #endif 10098 10099 #if defined(BCM_HURRICANE3_SUPPORT) 10100 /* 10101 * If device supports vlan flow counters 10102 * and stage is lookup stage, then get 10103 * flow count stat mode for this Stat. 10104 */ 10105 if (soc_feature(unit, soc_feature_flowcnt) 10106 && (_BCM_FIELD_STAGE_LOOKUP == stage_id)) { 10107 return (_field_flowcnt_mode_get(unit, f_st)); 10108 } 10109 #endif 10110 10111 10112 #ifdef BCM_TRIUMPH3_SUPPORT 10113 if (SOC_IS_TRIUMPH3(unit)) { 10114 BCM_IF_ERROR_RETURN 10115 (_bcm_field_tr3_stat_hw_mode_max(stage_id, 10116 &fp_stat_hw_mode_max 10117 ) 10118 ); 10119 } else 10120 #endif 10121 if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) && 10122 (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 10123 fp_stat_hw_mode_max = _FP_TRIDENT_STAT_HW_MODE_MAX; 10124 } else { 10125 fp_stat_hw_mode_max = _FP_STAT_HW_MODE_MAX; 10126 } 10127 10128 /* Get application requested bitmap. */ 10129 rv = _field_stat_array_to_bmap (unit, f_st, &req_bmap); 10130 BCM_IF_ERROR_RETURN(rv); 10131 10132 /* If bitmap is zero - no mode selection is required. */ 10133 if (0 == req_bmap) { 10134 f_st->hw_stat = 0; 10135 f_st->hw_entry_count = 0; 10136 f_st->hw_mode = 0; 10137 return (BCM_E_NONE); 10138 } 10139 10140 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 10141 if ((soc_feature(unit, soc_feature_field_vfp_flex_counter) || 10142 soc_feature(unit, soc_feature_flowcnt)) 10143 && (_BCM_FIELD_STAGE_LOOKUP == stage_id)) { 10144 10145 hw_bmap = (1 << (int)bcmFieldStatBytes) 10146 | (1 << (int)bcmFieldStatPackets); 10147 10148 if (0 == ((req_bmap | hw_bmap) & ~(hw_bmap))) { 10149 f_st->hw_mode = 1; 10150 f_st->hw_stat = hw_bmap; 10151 f_st->hw_entry_count = 1; 10152 return (BCM_E_NONE); 10153 } 10154 10155 return (BCM_E_UNAVAIL); 10156 } 10157 #endif /* BCM_TRIUMPH2_SUPPORT */ 10158 10159 /* Check if any hw supported mode will produce requested statistics. */ 10160 #ifdef BCM_WARM_BOOT_SUPPORT 10161 if (SOC_WARM_BOOT(unit)) { 10162 /* The f_st->hw_mode has already been read from the HW */ 10163 rv = _field_stat_hw_mode_to_bmap (unit, f_st->hw_mode, stage_id, 10164 &hw_bmap, &hw_entry_count); 10165 } else 10166 #endif 10167 { 10168 for (idx = 1; idx <= fp_stat_hw_mode_max; idx++) { 10169 rv = _field_stat_hw_mode_to_bmap(unit, idx, stage_id, 10170 &hw_bmap, &hw_entry_count); 10171 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 10172 "MODE:0x%x (l:%d u:%d) req_bmap:[0x%x] hw_bmap:[0x%x]" 10173 " hw_entry_count:%d :: [0x%x]\n\r"), idx, (idx & 0x7), 10174 ((idx >> 3) & 0x7), req_bmap, hw_bmap, hw_entry_count, 10175 ((req_bmap | hw_bmap) & ~(hw_bmap)))); 10176 10177 if (rv == BCM_E_CONFIG) { 10178 /* Returns BCM_E_CONFIG, if the given mode is not supported */ 10179 continue; 10180 } 10181 10182 if (0 == ((req_bmap | hw_bmap) & ~(hw_bmap))) { 10183 /* <HP> 10184 10185 For maximizing utilization of hardware counters, this should 10186 select the hw_mode both supports the requested stats 10187 AND minimizes the number of required hardware counters. 10188 10189 </HP> */ 10190 10191 break; 10192 } 10193 } 10194 if (idx > fp_stat_hw_mode_max) { 10195 return (BCM_E_RESOURCE); 10196 } 10197 f_st->hw_mode = idx; 10198 } 10199 10200 f_st->hw_stat = hw_bmap; 10201 f_st->hw_entry_count = hw_entry_count; 10202 10203 return (BCM_E_NONE); 10204 } 10205 10206 10207 /* 10208 * Function: 10209 * _field_stat_destroy2 10210 * Purpose: 10211 * Deinitialize a statistics collection entity 10212 * Parameters: 10213 * unit - (IN) Unit number. 10214 * fc - (IN) Internal stat entity descriptor. 10215 * f_st - (IN) Field stat s 10216 * Returns: 10217 * BCM_E_XXX 10218 * Notes: 10219 */ 10220 int 10221 _field_stat_destroy2(int unit, _field_control_t *fc, _field_stat_t *f_st) 10222 { 10223 /* Input parameters check. */ 10224 if ((NULL == fc) || (NULL == f_st)) { 10225 return (BCM_E_PARAM); 10226 } 10227 10228 /* Reject destroy if policer is in use. */ 10229 if (f_st->sw_ref_count > 1) { 10230 return (BCM_E_BUSY); 10231 } 10232 10233 /* Remove policer for lookup hash. */ 10234 _FP_HASH_REMOVE(fc->stat_hash, _field_stat_t, f_st, 10235 (f_st->sid & _FP_HASH_INDEX_MASK(fc))); 10236 10237 /* De-allocate statistics entity descriptor. */ 10238 if (NULL != f_st->stat_arr) { 10239 sal_free(f_st->stat_arr); 10240 } 10241 if (NULL != f_st->stat_values) { 10242 sal_free(f_st->stat_values); 10243 } 10244 10245 sal_free(f_st); 10246 10247 /* Decrement number of active policers. */ 10248 if (fc->stat_count > 0) { 10249 fc->stat_count--; 10250 } 10251 return (BCM_E_NONE); 10252 } 10253 10254 /* 10255 * Function: 10256 * _field_stat_destroy 10257 * Purpose: 10258 * Deinitialize a statistics collection entity 10259 * Parameters: 10260 * unit - (IN) Unit number. 10261 * sid - (IN) Statistics entity id. 10262 * Returns: 10263 * BCM_E_XXX 10264 * Notes: 10265 */ 10266 int 10267 _field_stat_destroy(int unit, int sid) 10268 { 10269 _field_control_t *fc; /* Field control structure. */ 10270 _field_stat_t *f_st; /* Internal policer descriptor. */ 10271 int rv; /* Operation return status. */ 10272 10273 /* Get field control structure. */ 10274 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 10275 10276 /* Find policer info. */ 10277 rv = _bcm_field_stat_get(unit, sid, &f_st); 10278 BCM_IF_ERROR_RETURN(rv); 10279 10280 return _field_stat_destroy2(unit, fc, f_st); 10281 } 10282 /* 10283 * Function: 10284 * _bcm_field_stat_destroy 10285 * Purpose: 10286 * Deinitialize a statistics collection entity 10287 * Parameters: 10288 * unit - (IN) Unit number. 10289 * sid - (IN) Statistics entity id. 10290 * Returns: 10291 * BCM_E_XXX 10292 * Notes: 10293 */ 10294 int 10295 _bcm_field_stat_destroy(int unit, int sid) 10296 { 10297 return _field_stat_destroy(unit, sid); 10298 } 10299 /* 10300 * Function: 10301 * _field_stat_destroy_all 10302 * Purpose: 10303 * Destroy all statistics collection entities 10304 * Parameters: 10305 * unit - (IN) Unit number. 10306 * Returns: 10307 * BCM_E_XXX 10308 * Notes: 10309 */ 10310 int 10311 _field_stat_destroy_all(int unit) 10312 { 10313 _field_control_t *fc; /* Field control structure. */ 10314 int idx; /* Entry hash iterator. */ 10315 int idx_max; /* Index max. */ 10316 int rv; /* Operation return status. */ 10317 10318 rv = _field_control_get(unit, &fc); 10319 BCM_IF_ERROR_RETURN(rv); 10320 10321 idx_max = _FP_HASH_SZ(fc); 10322 for (idx= 0; idx < idx_max; idx ++) { 10323 while (NULL != fc->stat_hash[idx]) { 10324 rv = _field_stat_destroy2(unit, fc, fc->stat_hash[idx]); 10325 if (BCM_FAILURE(rv)) { 10326 break; 10327 } 10328 } 10329 } 10330 return (rv); 10331 } 10332 10333 /* 10334 * Function: 10335 * _bcm_field_group_stat_destroy 10336 * Purpose: 10337 * Destroy all statistics collection entities 10338 * associated to a field group. 10339 * Parameters: 10340 * unit - (IN) Unit number. 10341 * group - (IN) field group id. 10342 * Returns: 10343 * BCM_E_XXX 10344 * Notes: 10345 */ 10346 int 10347 _bcm_field_group_stat_destroy(int unit, bcm_field_group_t group) 10348 { 10349 _field_control_t *fc; /* Field control structure. */ 10350 int idx; /* Entry hash iterator. */ 10351 int idx_max; /* Index max. */ 10352 int rv; /* Operation return status. */ 10353 _field_stat_t *f_st; /* Reference to Field stat structure. */ 10354 _field_stat_t *f_st_free, *f_st_prev; 10355 10356 rv = _field_control_get(unit, &fc); 10357 BCM_IF_ERROR_RETURN(rv); 10358 10359 idx_max = _FP_HASH_SZ(fc); 10360 for (idx= 0; idx < idx_max; idx ++) { 10361 f_st = fc->stat_hash[idx]; 10362 f_st_prev = NULL; 10363 while (NULL != f_st) { 10364 if (group == f_st->gid) { 10365 if (f_st_prev != NULL) { 10366 f_st_prev->next = f_st->next; 10367 f_st_free = f_st; 10368 f_st = f_st_prev->next; 10369 } else { 10370 f_st_free = f_st; 10371 f_st = f_st->next; 10372 rv = _field_stat_destroy2(unit, fc, f_st_free); 10373 if (BCM_FAILURE(rv)) { 10374 break; 10375 } 10376 continue; 10377 } 10378 10379 /* De-allocate statistics entity descriptor. */ 10380 if (NULL != f_st_free->stat_arr) { 10381 sal_free(f_st_free->stat_arr); 10382 } 10383 if (NULL != f_st_free->stat_values) { 10384 sal_free(f_st_free->stat_values); 10385 } 10386 10387 sal_free(f_st_free); 10388 f_st_free = NULL; 10389 10390 /* Decrement number of active policers. */ 10391 if (fc->stat_count > 0) { 10392 fc->stat_count--; 10393 } 10394 } else { 10395 f_st_prev = f_st; 10396 f_st = f_st->next; 10397 } 10398 } 10399 } 10400 return (rv); 10401 } 10402 10403 /* 10404 * Function: 10405 * _field_stat_array_init 10406 * 10407 * Description: 10408 * Preserve API requested statistics array. 10409 * Parameters: 10410 * unit - (IN) BCM device number. 10411 * f_st - (IN) Field statistics entity. 10412 * nstat - (IN) Number of elements in stat array. 10413 * stat_arr - (IN) Collected statistics descriptors array. 10414 * Returns: 10415 * BCM_E_XXX 10416 */ 10417 int 10418 _field_stat_array_init(int unit, _field_control_t *fc, _field_stat_t *f_st, 10419 int nstat, bcm_field_stat_t *stat_arr) 10420 { 10421 int rv; 10422 10423 /* Input parameters check. */ 10424 if ((NULL == f_st) || (0 == nstat) || (NULL == stat_arr) || (NULL == fc)) { 10425 return (BCM_E_PARAM); 10426 } 10427 10428 /* Free currently allocated stat array if any. */ 10429 if (NULL != f_st->stat_arr) { 10430 sal_free(f_st->stat_arr); 10431 f_st->stat_arr = NULL; 10432 f_st->nstat = 0; 10433 } 10434 10435 /* Free currently allocated values array if any. */ 10436 if (NULL != f_st->stat_values) { 10437 sal_free(f_st->stat_values); 10438 f_st->stat_values = NULL; 10439 } 10440 10441 _FP_XGS3_ALLOC(f_st->stat_arr, (nstat * sizeof (bcm_field_stat_t)), 10442 "Field stat array"); 10443 if (NULL == f_st->stat_arr) { 10444 return (BCM_E_MEMORY); 10445 } 10446 10447 _FP_XGS3_ALLOC(f_st->stat_values, (nstat * sizeof (uint64)), 10448 "Field stat values array"); 10449 if (NULL == f_st->stat_values) { 10450 sal_free(f_st->stat_arr); 10451 f_st->stat_arr = NULL; 10452 return (BCM_E_MEMORY); 10453 } 10454 10455 /* Copy stats array. */ 10456 sal_memcpy(f_st->stat_arr, stat_arr, (nstat * sizeof(bcm_field_stat_t))); 10457 f_st->nstat = nstat; 10458 10459 /* Map stats array to hw mode. */ 10460 rv = fc->functions.fp_stat_hw_mode_get(unit, f_st, f_st->stage_id); 10461 if (BCM_FAILURE(rv)) { 10462 if (!(f_st->hw_flags & _FP_STAT_INTERNAL)) { 10463 sal_free(f_st->stat_arr); 10464 sal_free(f_st->stat_values); 10465 f_st->stat_arr = NULL; 10466 f_st->stat_values = NULL; 10467 } 10468 return (rv); 10469 } 10470 return (BCM_E_NONE); 10471 } 10472 10473 /* 10474 * Function: 10475 * _bcm_field_stat_array_init 10476 * 10477 * Description: 10478 * Preserve API requested statistics array. 10479 * Parameters: 10480 * unit - (IN) BCM device number. 10481 * f_st - (IN) Field statistics entity. 10482 * nstat - (IN) Number of elements in stat array. 10483 * stat_arr - (IN) Collected statistics descriptors array. 10484 * Returns: 10485 * BCM_E_XXX 10486 */ 10487 int 10488 _bcm_field_stat_array_init(int unit, _field_control_t *fc, 10489 _field_stat_t *f_st, int nstat, 10490 bcm_field_stat_t *stat_arr) 10491 { 10492 /* Input parameters check. */ 10493 if ((NULL == f_st) || (0 == nstat) || (NULL == stat_arr) || (NULL == fc)) { 10494 return (BCM_E_PARAM); 10495 } 10496 10497 return _field_stat_array_init(unit, fc, f_st, nstat, stat_arr); 10498 } 10499 /* 10500 * Function: 10501 * _field_stat_create 10502 * 10503 * Description: 10504 * Create statistics collection entity. 10505 * Parameters: 10506 * unit - (IN) BCM device number. 10507 * group - (IN) Field group id. 10508 * nstat - (IN) Number of elements in stat array. 10509 * stat_arr - (IN) Collected statistics descriptors array. 10510 * flags - (IN) HW/API specific flags. 10511 * stat_id - (OUT) Statistics entity id. 10512 * Returns: 10513 * BCM_E_XXX 10514 */ 10515 int 10516 _field_stat_create(int unit, bcm_field_group_t group, int nstat, 10517 bcm_field_stat_t *stat_arr, uint32 flags, int *stat_id) 10518 { 10519 _field_control_t *fc; /* Field control structure. */ 10520 _field_group_t *fg; /* Field group pointer. */ 10521 int rv; /* Operation return status. */ 10522 _field_stat_t *f_st = NULL; /* Internal stat descriptor. */ 10523 int idx; 10524 10525 /* Input parameters check. */ 10526 if ((nstat <= 0) || 10527 (NULL == stat_id) || 10528 (nstat > (_bcmFieldStatCount + 1))) { 10529 return (BCM_E_PARAM); 10530 } 10531 10532 if ((0 != nstat) && (NULL == stat_arr)) { 10533 return (BCM_E_PARAM); 10534 } 10535 10536 for (idx = 0; idx < nstat; idx++) { 10537 if ((stat_arr[idx] < bcmFieldStatBytes) || 10538 (stat_arr[idx] >= bcmFieldStatCount)) { 10539 return (BCM_E_PARAM); 10540 } 10541 } 10542 10543 /* Get field control structure. */ 10544 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 10545 10546 /* Get group descriptor. */ 10547 rv = _field_group_get (unit, group, &fg); 10548 BCM_IF_ERROR_RETURN(rv); 10549 10550 #if defined(BCM_TOMAHAWK_SUPPORT) 10551 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 10552 if(_BCM_FIELD_STAGE_CLASS == fg->stage_id) { 10553 return (BCM_E_UNAVAIL); 10554 } 10555 } 10556 #endif /* BCM_TOMAHAWK_SUPPORT */ 10557 10558 #if defined(BCM_FLOWTRACKER_SUPPORT) 10559 if (soc_feature(unit, soc_feature_field_flowtracker_support) && 10560 (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 10561 return (BCM_E_UNAVAIL); 10562 } 10563 #endif 10564 10565 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 10566 if (!soc_feature(unit, soc_feature_advanced_flex_counter)) { 10567 if ((0 == soc_feature(unit, soc_feature_field_vfp_flex_counter)) && 10568 (0 == soc_feature(unit, soc_feature_flowcnt)) 10569 && (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id)) { 10570 return (BCM_E_UNAVAIL); 10571 } 10572 } 10573 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 10574 10575 if (flags & _FP_STAT_CREATE_ID) { 10576 /* Check if statistics entity id already exists. */ 10577 rv = _bcm_field_stat_get(unit, *stat_id, &f_st); 10578 if (BCM_SUCCESS(rv)) { 10579 /* Stat ID already exists return */ 10580 return (BCM_E_EXISTS); 10581 } 10582 flags = 0; 10583 } else { 10584 /* Generate statistics entity id. */ 10585 BCM_IF_ERROR_RETURN (_bcm_field_stat_id_alloc(unit, stat_id)); 10586 } 10587 10588 /* Allocate statistics descriptor. */ 10589 _FP_XGS3_ALLOC(f_st, sizeof (_field_stat_t), "Field stat entity"); 10590 if (NULL == f_st) { 10591 return (BCM_E_MEMORY); 10592 } 10593 10594 /* Initialize reference count to 1. */ 10595 f_st->sw_ref_count = 1; 10596 10597 /* Set hw index to - no hw resources allocated. */ 10598 f_st->pool_index = _FP_INVALID_INDEX; 10599 f_st->hw_index = _FP_INVALID_INDEX; 10600 10601 /* Initialize stat id. */ 10602 f_st->sid = *stat_id; 10603 10604 /* Store caller internal flags. */ 10605 f_st->hw_flags = flags; 10606 f_st->stage_id = fg->stage_id; 10607 f_st->gid = fg->gid; 10608 10609 /* Allocate counters array. */ 10610 if (0 != nstat) { 10611 rv = _field_stat_array_init(unit, fc, f_st, nstat, stat_arr); 10612 if (BCM_FAILURE(rv)) { 10613 sal_free(f_st); 10614 return (rv); 10615 } 10616 } 10617 10618 10619 /* Insert policer into statistics hash. */ 10620 _FP_HASH_INSERT(fc->stat_hash, f_st, (*stat_id & _FP_HASH_INDEX_MASK(fc))); 10621 10622 /* Increment number of active policers. */ 10623 fc->stat_count++; 10624 f_st->flex_mode = 0; 10625 return (BCM_E_NONE); 10626 } 10627 10628 /* 10629 * Function: 10630 * _field_entry_stat_attach 10631 * 10632 * Description: 10633 * Attach statistics entity to Field Processor entry. 10634 * Parameters: 10635 * unit - (IN) BCM device number. 10636 * entry - (IN) Field entry id. 10637 * stat_id - (IN) Statistics entity id. 10638 * Returns: 10639 * BCM_E_XXX 10640 */ 10641 int 10642 _field_entry_stat_attach(int unit, _field_entry_t *f_ent, int stat_id) 10643 { 10644 _field_entry_stat_t *f_ent_st; /* Field entry statistics structure.*/ 10645 _field_stat_t *f_st; /* Internal statisics descriptor. */ 10646 _field_stage_id_t stage_id; /* Pipeline stage id. */ 10647 int rv; /* Operation return status. */ 10648 _field_stage_t *stage_fc; /* Field stage control structure.*/ 10649 10650 /* Input parameters check. */ 10651 if (NULL == f_ent) { 10652 return (BCM_E_PARAM); 10653 } 10654 10655 /* Get entry pipeline stage id. */ 10656 stage_id = f_ent->group->stage_id; 10657 10658 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 10659 if (!soc_feature(unit, soc_feature_advanced_flex_counter)) { 10660 if (!soc_feature(unit, soc_feature_field_vfp_flex_counter) && 10661 !soc_feature(unit, soc_feature_flowcnt) 10662 && (_BCM_FIELD_STAGE_LOOKUP == stage_id)) { 10663 return (BCM_E_UNAVAIL); 10664 } 10665 } 10666 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 10667 10668 #if defined(BCM_TOMAHAWK_SUPPORT) 10669 if ((soc_feature(unit, soc_feature_td3_style_fp) 10670 && _BCM_FIELD_STAGE_INGRESS == stage_id) 10671 || (_BCM_FIELD_STAGE_EXACTMATCH == stage_id && 10672 !(f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT))) { 10673 if (!(BCM_FIELD_ASET_TEST(f_ent->group->aset, 10674 bcmFieldActionStatGroup))) { 10675 LOG_ERROR(BSL_LS_BCM_FP, 10676 (BSL_META_U(unit, 10677 "FP(unit %d) - Group %d created" 10678 " without action bcmFieldActionStatGroup.\n"), 10679 unit, f_ent->group->gid)); 10680 return (BCM_E_CONFIG); 10681 } 10682 } 10683 #endif /* BCM_TOMAHAWK_SUPPORT */ 10684 10685 /* Check if another statistics entity is already attached. */ 10686 f_ent_st = &f_ent->statistic; 10687 if (f_ent_st->flags & _FP_ENTRY_STAT_VALID) { 10688 return (BCM_E_EXISTS); 10689 } 10690 10691 /* Check if statistics action conflicts with other actions */ 10692 if (f_ent_st->flags & _FP_ENTRY_STAT_NOT_ALLOWED) { 10693 return (BCM_E_CONFIG); 10694 } 10695 10696 /* Get statistics entity description structure. */ 10697 rv = _bcm_field_stat_get(unit, stat_id, &f_st); 10698 BCM_IF_ERROR_RETURN(rv); 10699 10700 if ((f_st->stage_id != stage_id) || 10701 (f_st->gid != f_ent->group->gid)) { 10702 return (BCM_E_PARAM); 10703 } 10704 10705 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10706 if (soc_feature(unit, soc_feature_advanced_flex_counter) && 10707 !soc_feature(unit, soc_feature_field_multi_pipe_support)) { 10708 /* Can't attach flex stat to normal field stat */ 10709 if (((f_st->stage_id == _BCM_FIELD_STAGE_INGRESS) || 10710 (f_st->stage_id == _BCM_FIELD_STAGE_EGRESS)) && 10711 (f_st->hw_flags & \ 10712 (_FP_STAT_FLEX_CNTR | _FP_STAT_INTERNAL_FLEX_COUNTER))) { 10713 return (BCM_E_CONFIG); 10714 } 10715 } 10716 #endif 10717 10718 /* Get stage control information. */ 10719 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc)); 10720 10721 /* Validate STAT pool_index */ 10722 if (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id 10723 && !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) 10724 && !(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) 10725 && (_FP_INVALID_INDEX != f_st->hw_index)) { 10726 if ((!(f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE) 10727 && f_ent->fs->slice_number != f_st->pool_index) 10728 || ((f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE) 10729 && f_ent->fs->slice_number + 1 != f_st->pool_index)) { 10730 LOG_ERROR(BSL_LS_BCM_FP, 10731 (BSL_META_U(unit, 10732 "FP(unit %d) - Counters cannot be shared between slices.\n"), 10733 unit)); 10734 LOG_ERROR(BSL_LS_BCM_FP, 10735 (BSL_META_U(unit, 10736 " Create a new stat and attach to EID=%d.\n"), 10737 f_ent->eid)); 10738 return (BCM_E_CONFIG); 10739 } 10740 } 10741 10742 /* Check if statistics entity can be shared. */ 10743 if (f_st->sw_ref_count > 1) { 10744 /* Statistics sharing is restricted to a single stage. */ 10745 if (stage_id != f_st->stage_id) { 10746 return (BCM_E_PARAM); 10747 } 10748 } 10749 10750 /* Increment statistics entity reference counter. */ 10751 f_st->sw_ref_count++; 10752 10753 /* Attach statistics entity to an entry. */ 10754 f_ent_st->flags |= _FP_ENTRY_STAT_VALID; 10755 f_ent_st->flags |= _FP_ENTRY_STAT_DIRTY; 10756 f_ent_st->sid = stat_id; 10757 10758 /* 10759 * If qualifiers have not been modified for this entry, 10760 * set Policy table only dirty flag. 10761 */ 10762 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 10763 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 10764 } 10765 10766 /* Entry must be reinstalled for statistics to take effect. */ 10767 f_ent->flags |= _FP_ENTRY_DIRTY; 10768 10769 return (BCM_E_NONE); 10770 } 10771 10772 #if defined(BCM_TRIUMPH2_SUPPORT) 10773 /* 10774 * Function: 10775 * _bcm_esw_fp_flex_stat_index_set 10776 * 10777 * Purpose: 10778 * Allocation callback from flex stat module used to notify fp module 10779 * allocated flex stat index. 10780 * Parameters: 10781 * unit - (IN) BCM device number. 10782 * stage_fc - (IN) Stage field control structure. 10783 * f_ent - (IN/OUT) Entry array policer belongs to. 10784 * fs - (IN) Desired slice for the counter. 10785 * Returns: 10786 * BCM_E_XXX 10787 */ 10788 STATIC int 10789 _bcm_esw_fp_flex_stat_index_set(int unit, _bcm_flex_stat_handle_t handle, 10790 int fs_idx, void *cookie) 10791 { 10792 _field_stat_t *f_st = (_field_stat_t *)cookie; 10793 f_st->hw_index = fs_idx; 10794 return (BCM_E_NONE); 10795 } 10796 #endif /* BCM_TRIUMPH2_SUPPORT */ 10797 10798 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 10799 /* 10800 * Function: 10801 * _field_flex_counter_free 10802 * 10803 * Purpose: 10804 * Free flex counter resources used by field entry/entries. 10805 * Parameters: 10806 * unit - (IN) BCM device number. 10807 * f_ent - (IN) Entry array policer belongs to. 10808 * f_st - (IN) Statistics entity. 10809 * Returns: 10810 * BCM_E_XXX 10811 */ 10812 int 10813 _field_flex_counter_free(int unit, _field_entry_t *f_ent, _field_stat_t *f_st) 10814 { 10815 _field_stage_t *stage_fc; 10816 int entry_idx=0; 10817 int rv; 10818 soc_mem_t tcam_mem; /* TCAM memory id. */ 10819 soc_mem_t policy_mem; /* Policy table memory id. */ 10820 _field_stage_id_t stage_id; /* Pipeline stage id. */ 10821 10822 /* Get pipeline stage information. */ 10823 BCM_IF_ERROR_RETURN 10824 (_field_stage_control_get(unit, 10825 f_ent->group->stage_id, 10826 &stage_fc 10827 ) 10828 ); 10829 10830 stage_id = f_ent->group->stage_id; 10831 10832 /* Detach flex stat only if it has been created. */ 10833 if (f_st->flex_mode != 0) { 10834 /* 10835 * Get entry index at which flex STAT information 10836 * has been programmed in policy table. 10837 */ 10838 BCM_IF_ERROR_RETURN 10839 (_bcm_field_slice_offset_to_tcam_idx(unit, 10840 stage_fc, 10841 f_ent->group->instance, 10842 f_ent->fs->slice_number, 10843 f_ent->slice_idx, 10844 &entry_idx 10845 ) 10846 ); 10847 10848 #if defined(BCM_TRIDENT3_SUPPORT) 10849 if (soc_feature(unit, soc_feature_td3_style_fp)){ 10850 rv = _bcm_field_th_tcam_policy_mem_get(unit, f_ent, 10851 &tcam_mem, &policy_mem); 10852 } else 10853 #endif 10854 { 10855 rv = _field_fb_tcam_policy_mem_get(unit, f_ent->group->stage_id, 10856 &tcam_mem, &policy_mem); 10857 } 10858 10859 BCM_IF_ERROR_RETURN(rv); 10860 10861 if (stage_id == _BCM_FIELD_STAGE_EGRESS) { 10862 rv = _bcm_esw_stat_flex_detach_egress_table_counters 10863 (unit, 0, 10864 policy_mem, 10865 entry_idx 10866 ); 10867 } else { 10868 rv = _bcm_esw_stat_flex_detach_ingress_table_counters 10869 (unit, 10870 policy_mem, 10871 entry_idx 10872 ); 10873 } 10874 10875 /* 10876 * Flex STATs module initialized before field module, ignore 10877 * error during bcm_field_detach(). 10878 */ 10879 if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) { 10880 return (rv); 10881 } 10882 10883 /* 10884 * Destroy Flex STAT when created not attached 10885 * through bcm_field_stat_attach API. 10886 */ 10887 if (!(f_st->hw_flags & _FP_STAT_CREATED_BY_FLEX_MODULE)) { 10888 rv = bcm_esw_stat_group_destroy(unit, f_st->flex_mode); 10889 10890 /* 10891 * Flex STATs module initialized before field module, ignore 10892 * error during bcm_field_detach(). 10893 * Ignore:BCM_E_INTERNAL (as multiple stat entries use same SingleMode 10894 */ 10895 if (rv == BCM_E_INTERNAL) { /* Doesn't look appropriate error code but*/ 10896 rv = BCM_E_NONE; 10897 } 10898 if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) { 10899 return (rv); 10900 } 10901 } 10902 /* decrement the group's counter count equal to 10903 the hw counters used for this stat */ 10904 f_ent->group->group_status.counter_count = 10905 f_ent->group->group_status.counter_count - f_st->hw_entry_count; 10906 10907 f_st->hw_index = _FP_INVALID_INDEX; 10908 f_st->pool_index = _FP_INVALID_INDEX; 10909 f_st->hw_entry_count = 0; 10910 f_st->flex_mode = 0; 10911 } 10912 10913 return (BCM_E_NONE); 10914 } 10915 #endif 10916 10917 #if defined(BCM_HURRICANE3_SUPPORT) 10918 /* 10919 * Function: 10920 * _field_flowcnt_counter_free 10921 * 10922 * Purpose: 10923 * Free flow count counter resources used by field entry/entries. 10924 * Parameters: 10925 * unit - (IN) BCM device number. 10926 * f_ent - (IN) Entry array policer belongs to. 10927 * f_st - (IN) Statistics entity. 10928 * Returns: 10929 * BCM_E_XXX 10930 */ 10931 int 10932 _field_flowcnt_counter_free(int unit, _field_entry_t *f_ent, _field_stat_t *f_st) 10933 { 10934 _field_stage_t *stage_fc; 10935 int entry_idx=0; 10936 int rv; 10937 soc_mem_t tcam_mem; /* TCAM memory id. */ 10938 soc_mem_t policy_mem; /* Policy table memory id. */ 10939 10940 /* Get pipeline stage information. */ 10941 BCM_IF_ERROR_RETURN 10942 (_field_stage_control_get(unit, 10943 f_ent->group->stage_id, 10944 &stage_fc 10945 ) 10946 ); 10947 10948 /* Detach flex stat only if it has been created. */ 10949 if (f_st->flex_mode != 0) { 10950 /* 10951 * Get entry index at which flowcnt STAT information 10952 * has been programmed in policy table. 10953 */ 10954 BCM_IF_ERROR_RETURN 10955 (_bcm_field_slice_offset_to_tcam_idx(unit, 10956 stage_fc, 10957 f_ent->group->instance, 10958 f_ent->fs->slice_number, 10959 f_ent->slice_idx, 10960 &entry_idx 10961 ) 10962 ); 10963 10964 rv = _field_fb_tcam_policy_mem_get(unit, f_ent->group->stage_id, 10965 &tcam_mem, &policy_mem); 10966 BCM_IF_ERROR_RETURN(rv); 10967 10968 rv = _bcm_esw_flowcnt_object_table_detach(unit, 10969 policy_mem, entry_idx); 10970 10971 /* 10972 * Flex STATs module initialized before field module, ignore 10973 * error during bcm_field_detach(). 10974 */ 10975 if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) { 10976 return (rv); 10977 } 10978 10979 /* 10980 * Destroy Flow count STAT. 10981 */ 10982 rv = bcm_esw_stat_group_destroy(unit, f_st->flex_mode); 10983 10984 /* 10985 * STATs module initialized before field module, ignore 10986 * error during bcm_field_detach(). 10987 * Ignore:BCM_E_INTERNAL (as multiple stat entries use same SingleMode 10988 */ 10989 if (rv == BCM_E_INTERNAL) { /* Doesn't look appropriate error code but*/ 10990 rv = BCM_E_NONE; 10991 } 10992 if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) { 10993 return (rv); 10994 } 10995 10996 f_st->hw_index = _FP_INVALID_INDEX; 10997 f_st->pool_index = _FP_INVALID_INDEX; 10998 f_st->hw_entry_count = 0; 10999 f_st->flex_mode = 0; 11000 } 11001 11002 return (BCM_E_NONE); 11003 } 11004 #endif 11005 11006 11007 /* 11008 * Function: 11009 * _field_slice_counter_free 11010 * 11011 * Purpose: 11012 * Free a counter from a slice. 11013 * 11014 * Parameters: 11015 * unit - (IN) Bcm device number. 11016 * f_ent - (IN) Field entry. 11017 * f_st - (IN) Statistics entity. 11018 * 11019 * Returns: 11020 * BCM_E_XXX 11021 */ 11022 STATIC int 11023 _field_slice_counter_free(int unit, _field_entry_t *f_ent, _field_stat_t *f_st) 11024 { 11025 uint8 entry_part; /* Secondary slice entry part. */ 11026 _field_group_t *fg; /* Field group structure. */ 11027 _field_slice_t *fs; /* Field slice structure. */ 11028 int idx; /* SW counter index. */ 11029 int rv = BCM_E_NONE; /* Operation return status. */ 11030 11031 if ((NULL == f_ent) || (NULL == f_st)) { 11032 return (BCM_E_PARAM); 11033 } 11034 11035 fg = f_ent->group; 11036 fs = (f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE) ? \ 11037 f_ent->fs + 1: f_ent->fs; 11038 11039 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 11040 if ((soc_feature(unit, soc_feature_advanced_flex_counter) 11041 && (f_st->hw_flags & _FP_STAT_FLEX_CNTR))) { 11042 return (_field_flex_counter_free(unit, f_ent, f_st)); 11043 } 11044 #endif 11045 11046 #if defined(BCM_HURRICANE3_SUPPORT) 11047 if ((soc_feature(unit, soc_feature_flowcnt) 11048 && (f_st->hw_flags & _FP_STAT_FLOWCNT_CNTR))) { 11049 return (_field_flowcnt_counter_free(unit, f_ent, f_st)); 11050 } 11051 #endif 11052 11053 11054 #if defined (BCM_TRIUMPH2_SUPPORT) 11055 /* Free is external for vfp counters. */ 11056 if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) { 11057 if (!soc_feature(unit, soc_feature_advanced_flex_counter)) { 11058 /* During Disable - Pass valid counter index for new STAT API mode 11059 * or zero as counter index for old STAT API mode 11060 */ 11061 if (f_st->flex_mode) { 11062 _bcm_flex_stat_type_t fs_type; 11063 uint32 fs_inx; 11064 11065 fs_type = _BCM_FLEX_STAT_TYPE(f_st->flex_mode); 11066 fs_inx = _BCM_FLEX_STAT_COUNT_INX(f_st->flex_mode); 11067 rv = _bcm_esw_flex_stat_enable_set(unit, 11068 fs_type, 11069 _bcm_esw_fp_flex_stat_index_set, 11070 (void *)f_st, 11071 f_st->sid, 11072 FALSE, 11073 fs_inx); 11074 } else { 11075 rv = _bcm_esw_flex_stat_enable_set(unit, 11076 _bcmFlexStatTypeFp, 11077 _bcm_esw_fp_flex_stat_index_set, 11078 (void *)f_st, 11079 f_st->sid, 11080 FALSE, 11081 0 11082 ); 11083 } 11084 } 11085 11086 f_st->hw_index = _FP_INVALID_INDEX; 11087 f_st->pool_index = _FP_INVALID_INDEX; 11088 11089 /* During system restart flex stat module 11090 * might be reinitialized before fp reinit. Hence 11091 * calls to the flex stat module will result in BCM_E_NOT_FOUND 11092 * error code. 11093 */ 11094 if ((_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) && 11095 (BCM_E_NOT_FOUND == rv)) { 11096 rv = BCM_E_NONE; 11097 } 11098 return (rv); 11099 } 11100 #endif /* BCM_TRIUMPH2_SUPPORT */ 11101 11102 #if defined (BCM_FIREBOLT2_SUPPORT) 11103 if (SOC_IS_FIREBOLT2(unit) && (_BCM_FIELD_STAGE_EGRESS == f_st->stage_id)) { 11104 /* FB2 - doesn't have counter pairs in stage egress. */ 11105 idx = f_st->hw_index; 11106 } else 11107 #endif /* BCM_FIREBOLT2_SUPPORT */ 11108 { 11109 idx = 2 * f_st->hw_index; 11110 } 11111 11112 /* Clear counter is used bit. */ 11113 if (2 == f_st->hw_entry_count) { 11114 _FP_COUNTER_BMP_REMOVE(fs->counter_bmp, idx); 11115 _FP_COUNTER_BMP_REMOVE(fs->counter_bmp, idx + 1); 11116 } else { 11117 /* 11118 * hw_mode refers to COUNTER_MODEf in FP_POLICY_TABLEm 11119 * On TD_TT and KTX, this is a 6-bit field:- 11120 * 0,1,2 bit positions represent lower or even counters 11121 * 3,4,5 bit positions represent upper or odd counters 11122 * 11123 * On rest of the TRX devices, COUNTER_MODEf in FP_POLICY_TABLEm 11124 * and EFP_POLICY_TABLEm are 3-bit fields, where 11125 * value 1 - means lower counter is used 11126 * value 2 - means upper counter is used. 11127 * values [3 - 7] - mean both counters are used 11128 * 11129 * On older devices, COUNTER_MODEf in FP_POLICY_TABLEM 11130 * is a 4 bit field with the upper bit indicating 11131 * byte/packet mode and rest of the 3 bits representing 11132 * the COUNTER_MODE as above.Egress has only one counter, 11133 * no mode selection 11134 */ 11135 if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) && 11136 f_st->stage_id == _BCM_FIELD_STAGE_INGRESS) { 11137 if (f_st->hw_mode > 7) { 11138 idx++; 11139 } 11140 } else if (SOC_IS_TRX(unit)) { 11141 if (f_st->hw_mode > 1) { 11142 idx++; 11143 } 11144 } else { 11145 if ((f_st->hw_mode & 0x7) > 1) { 11146 idx++; 11147 } 11148 } 11149 11150 _FP_COUNTER_BMP_REMOVE(fs->counter_bmp, idx); 11151 } 11152 11153 /* Reset entry policer related flags. */ 11154 if (f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE) { 11155 /* Get primary entry from the second slice. */ 11156 rv = _bcm_field_entry_flags_to_tcam_part (unit, _FP_ENTRY_SECONDARY, 11157 fg, &entry_part); 11158 BCM_IF_ERROR_RETURN(rv); 11159 sal_memset(&f_ent[entry_part].statistic, 0, sizeof(_field_entry_stat_t)); 11160 f_ent->flags &= ~_FP_ENTRY_STAT_IN_SECONDARY_SLICE; 11161 } 11162 11163 /* decrement the group's counter count equal to 11164 the hw counters used for this stat */ 11165 f_ent->group->group_status.counter_count = 11166 f_ent->group->group_status.counter_count - f_st->hw_entry_count; 11167 11168 f_st->hw_index = _FP_INVALID_INDEX; 11169 f_st->pool_index = _FP_INVALID_INDEX; 11170 return BCM_E_NONE; 11171 } 11172 /* 11173 * Function: 11174 * _field_counter32_collect_alloc 11175 * Purpose: 11176 * Initialize software field for collection of 32 (or less) bit counters. 11177 * 11178 * Parameters: 11179 * unit - (IN) BCM device number. 11180 * mem - (IN) Counter memory. 11181 * descr - (IN) Counter descriptor. 11182 * ptr - (OUT) Allocated pointer. 11183 * Returns: 11184 * BCM_E_XXX 11185 */ 11186 STATIC int 11187 _field_counter32_collect_alloc(int unit, soc_mem_t mem, char *descr, 11188 _field_counter32_collect_t **ptr) 11189 { 11190 int mem_size; 11191 11192 /* Input parameters check. */ 11193 if ((NULL == ptr) || (NULL == descr) || (INVALIDm == mem)) { 11194 return (BCM_E_PARAM); 11195 } 11196 11197 /* Allocate a buffer to track counters. */ 11198 mem_size = (soc_mem_index_count(unit, mem) * 11199 sizeof(_field_counter32_collect_t)); 11200 *ptr = sal_alloc(mem_size, descr); 11201 if (NULL == *ptr) { 11202 return (BCM_E_MEMORY); 11203 } 11204 sal_memset(*ptr, 0, mem_size); 11205 return (BCM_E_NONE); 11206 } 11207 /* 11208 * Function: 11209 * _bcm_field_counter32_collect_alloc 11210 * Purpose: 11211 * Initialize software field for collection of 32 (or less) bit counters. 11212 * 11213 * Parameters: 11214 * unit - (IN) BCM device number. 11215 * mem - (IN) Counter memory. 11216 * descr - (IN) Counter descriptor. 11217 * ptr - (OUT) Allocated pointer. 11218 * Returns: 11219 * BCM_E_XXX 11220 */ 11221 int 11222 _bcm_field_counter32_collect_alloc(int unit, soc_mem_t mem, char *descr, 11223 _field_counter32_collect_t **ptr) 11224 { 11225 return _field_counter32_collect_alloc(unit, mem, descr, ptr); 11226 } 11227 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 11228 /* 11229 * Function: 11230 * _field_counter64_collect_alloc 11231 * Purpose: 11232 * Initialize software field for collection > 32 bit counters. 11233 * 11234 * Parameters: 11235 * unit - (IN) BCM device number. 11236 * mem - (IN) Counter memory. 11237 * descr - (IN) Counter descriptor. 11238 * ptr - (OUT) Allocated pointer. 11239 * Returns: 11240 * BCM_E_XXX 11241 */ 11242 STATIC int 11243 _field_counter64_collect_alloc(int unit, soc_mem_t mem, char *descr, 11244 _field_counter64_collect_t **ptr) 11245 { 11246 int mem_size; 11247 11248 /* Input parameters check. */ 11249 if ((NULL == ptr) || (NULL == descr) || (INVALIDm == mem)) { 11250 return (BCM_E_PARAM); 11251 } 11252 11253 /* Allocate a buffer to track counters. */ 11254 mem_size = (soc_mem_index_count(unit, mem) * 11255 sizeof(_field_counter64_collect_t)); 11256 *ptr = sal_alloc(mem_size, descr); 11257 if (NULL == *ptr) { 11258 return (BCM_E_MEMORY); 11259 } 11260 sal_memset(*ptr, 0, mem_size); 11261 return (BCM_E_NONE); 11262 } 11263 /* 11264 * Function: 11265 * _bcm_field_counter64_collect_alloc 11266 * Purpose: 11267 * Initialize software field for collection > 32 bit counters. 11268 * 11269 * Parameters: 11270 * unit - (IN) BCM device number. 11271 * mem - (IN) Counter memory. 11272 * descr - (IN) Counter descriptor. 11273 * ptr - (OUT) Allocated pointer. 11274 * Returns: 11275 * BCM_E_XXX 11276 */ 11277 int 11278 _bcm_field_counter64_collect_alloc(int unit, soc_mem_t mem, char *descr, 11279 _field_counter64_collect_t **ptr) 11280 { 11281 return _field_counter64_collect_alloc(unit, mem, descr, ptr); 11282 } 11283 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 11284 /* 11285 * Function: 11286 * _field_counter_collect_deinit 11287 * Purpose: 11288 * Denitialize software field counters. 11289 * 11290 * Parameters: 11291 * unit - (IN) BCM device number. 11292 * stage_fc - (IN/OUT) Stage field control structure. 11293 * 11294 * Returns: 11295 * BCM_E_XXX 11296 * NOTE: 11297 * FC must be locked & callback deregistred before calling this 11298 * function.. 11299 */ 11300 STATIC int 11301 _field_counter_collect_deinit(int unit, _field_stage_t *stage_fc) 11302 { 11303 _field_control_t *fc; 11304 int rv = 0; 11305 #if defined(BCM_TOMAHAWK_SUPPORT) 11306 int pipe; /* XGS pipeline to operate on. */ 11307 int max_pipes; /* Maximum pipeline per stage. */ 11308 #endif 11309 11310 /* Input parameters check. */ 11311 if (NULL == stage_fc) { 11312 return (BCM_E_PARAM); 11313 } 11314 11315 /* Field control get. */ 11316 11317 11318 FP_LOCK(unit); 11319 rv = _field_control_get(unit, &fc); 11320 if (BCM_FAILURE(rv)) { 11321 FP_UNLOCK(unit); 11322 return rv; 11323 } 11324 11325 11326 if (NULL != stage_fc->_field_x32_counters) { 11327 sal_free(stage_fc->_field_x32_counters); 11328 stage_fc->_field_x32_counters = NULL; 11329 } 11330 11331 #if defined(BCM_TRIUMPH_SUPPORT) 11332 if (NULL != stage_fc->_field_ext_counters) { 11333 sal_free(stage_fc->_field_ext_counters); 11334 stage_fc->_field_ext_counters = NULL; 11335 } 11336 #endif /* !BCM_TRIUMPH_SUPPORT */ 11337 11338 11339 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 11340 if (NULL != stage_fc->_field_x64_counters) { 11341 sal_free(stage_fc->_field_x64_counters); 11342 stage_fc->_field_x64_counters = NULL; 11343 } 11344 11345 if (NULL != stage_fc->_field_y64_counters) { 11346 sal_free(stage_fc->_field_y64_counters); 11347 stage_fc->_field_y64_counters = NULL; 11348 } 11349 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */ 11350 11351 #if defined(BCM_SCORPION_SUPPORT) 11352 if (NULL != stage_fc->_field_y32_counters) { 11353 sal_free(stage_fc->_field_y32_counters); 11354 stage_fc->_field_y32_counters = NULL; 11355 } 11356 #endif /* BCM_SCORPION_SUPPORT */ 11357 11358 if (NULL != stage_fc->_field_memacc_counters) { 11359 sal_free(stage_fc->_field_memacc_counters); 11360 stage_fc->_field_memacc_counters = NULL; 11361 } 11362 11363 #if defined(BCM_TOMAHAWK_SUPPORT) 11364 max_pipes = stage_fc->num_pipes; 11365 if (stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) { 11366 for (pipe = 0; pipe < max_pipes; pipe++ ) { 11367 if (NULL != stage_fc->_field_32_counters[pipe]) { 11368 sal_free(stage_fc->_field_32_counters[pipe]); 11369 stage_fc->_field_32_counters[pipe] = NULL; 11370 } 11371 } 11372 11373 for (pipe = 0; pipe < max_pipes; pipe++ ) { 11374 if (NULL != stage_fc->_field_64_counters[pipe]) { 11375 sal_free(stage_fc->_field_64_counters[pipe]); 11376 stage_fc->_field_32_counters[pipe] = NULL; 11377 } 11378 } 11379 } 11380 #endif 11381 11382 FP_UNLOCK(unit); 11383 11384 return (BCM_E_NONE); 11385 } 11386 /* 11387 * Function: 11388 * _bcm_field_counter_collect_deinit 11389 * Purpose: 11390 * Denitialize software field counters. 11391 * 11392 * Parameters: 11393 * unit - (IN) BCM device number. 11394 * stage_fc - (IN/OUT) Stage field control structure. 11395 * 11396 * Returns: 11397 * BCM_E_XXX 11398 * NOTE: 11399 * FC must be locked & callback deregistred before calling this 11400 * function.. 11401 */ 11402 int 11403 _bcm_field_counter_collect_deinit(int unit, _field_stage_t *stage_fc) 11404 { 11405 return _field_counter_collect_deinit(unit, stage_fc); 11406 } 11407 11408 /* 11409 * Function: 11410 * _field_sw_counter_set 11411 * 11412 * Description: 11413 * Service routine used to set 64-bit software accumulated counters. 11414 * Parameters: 11415 * unit - (IN) BCM device number. 11416 * stage_fc - (IN) Stage field control structure. 11417 * idx - (IN) Counter hw index. 11418 * packet_count - (OUT) Packet Counter value 11419 * byte_count - (OUT) Byte Counter value 11420 * Returns: 11421 * BCM_E_XXX 11422 */ 11423 STATIC int 11424 _field_sw_counter_set(int unit, _field_stage_t *stage_fc, 11425 int idx, uint64 *packet_count, 11426 uint64 *byte_count) 11427 { 11428 _field_control_t *fc; /* Field control structure. */ 11429 soc_mem_t counter_x_mem; /* Counter table on X pipe */ 11430 soc_mem_t counter_y_mem; /* Counter table on Y pipe */ 11431 uint32 *hw_buf_x; /* X memory HW buffer. */ 11432 uint32 *hw_buf_y; /* Y memory HW buffer. */ 11433 int rv; /* Operation return status. */ 11434 11435 hw_buf_x = hw_buf_y = NULL; 11436 11437 /* Get field control structure. */ 11438 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 11439 11440 /* Get counter memory. */ 11441 rv = _field_counter_mem_get(unit, stage_fc, &counter_x_mem, &counter_y_mem); 11442 BCM_IF_ERROR_RETURN(rv); 11443 11444 /* HW index sanity check. */ 11445 if (idx < soc_mem_index_min(unit, counter_x_mem) || 11446 idx > soc_mem_index_max(unit, counter_x_mem)) { 11447 return (BCM_E_INTERNAL); 11448 } 11449 11450 /* Allocate buffer for counter values in HW. */ 11451 _FP_XGS3_ALLOC(hw_buf_x, 2 * WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS), 11452 "Counter buffers"); 11453 if (NULL == hw_buf_x) { 11454 return (BCM_E_MEMORY); 11455 } 11456 11457 /* Read X pipeline counter memory. */ 11458 rv = soc_mem_read(unit, counter_x_mem, MEM_BLOCK_ANY, idx, hw_buf_x); 11459 if (BCM_FAILURE(rv)) { 11460 sal_free(hw_buf_x); 11461 return (BCM_E_MEMORY); 11462 } 11463 11464 /* Read Y pipeline counter memory. */ 11465 if (INVALIDm != counter_y_mem) { 11466 hw_buf_y = hw_buf_x + SOC_MAX_MEM_FIELD_WORDS; 11467 rv = soc_mem_read(unit, counter_y_mem, MEM_BLOCK_ANY, idx, hw_buf_y); 11468 if (BCM_FAILURE(rv)) { 11469 sal_free(hw_buf_x); 11470 return (BCM_E_MEMORY); 11471 } 11472 } 11473 11474 /* Process accumulated counter value. */ 11475 rv = fc->functions.fp_counter_set(unit, stage_fc, counter_x_mem, 11476 hw_buf_x, counter_y_mem, hw_buf_y, 11477 idx, packet_count, byte_count); 11478 sal_free(hw_buf_x); 11479 return (rv); 11480 } 11481 11482 /* 11483 * Function: 11484 * _field_sw_counter_get 11485 * 11486 * Description: 11487 * Service routine used to retrieve 64-bit software accumulated counters. 11488 * Parameters: 11489 * unit - (IN) BCM device number. 11490 * stage_fc - (IN) Stage field control structure. 11491 * idx - (IN) Counter hw index. 11492 * packet_count - (OUT) Packet Counter value 11493 * byte_count - (OUT) Byte Counter value 11494 * Returns: 11495 * BCM_E_XXX 11496 */ 11497 STATIC int 11498 _field_sw_counter_get(int unit, _field_stage_t *stage_fc, 11499 int idx, uint64 *packet_count, 11500 uint64 *byte_count) 11501 { 11502 _field_control_t *fc; /* Field control structure. */ 11503 soc_mem_t counter_x_mem; /* Counter table on X pipe */ 11504 soc_mem_t counter_y_mem; /* Counter table on Y pipe */ 11505 uint32 *hw_buf_x; /* X memory HW buffer. */ 11506 uint32 *hw_buf_y; /* Y memory HW buffer. */ 11507 int rv; /* Operation return status. */ 11508 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 11509 #if defined(BCM_SCORPION_SUPPORT) 11510 _field_counter32_collect_t *cntrs32_buf; /* Sw packet counter value */ 11511 #endif 11512 _field_counter64_collect_t *cntrs64_buf; /* Sw byte counter value */ 11513 #endif 11514 11515 COMPILER_64_ZERO(*packet_count); 11516 COMPILER_64_ZERO(*byte_count); 11517 hw_buf_x = hw_buf_y = NULL; 11518 11519 /* Get field control structure. */ 11520 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 11521 11522 /* Get counter memory. */ 11523 rv = _field_counter_mem_get(unit, stage_fc, &counter_x_mem, &counter_y_mem); 11524 BCM_IF_ERROR_RETURN(rv); 11525 11526 /* HW index sanity check. */ 11527 if (idx < soc_mem_index_min(unit, counter_x_mem) || 11528 idx > soc_mem_index_max(unit, counter_x_mem)) { 11529 return (BCM_E_INTERNAL); 11530 } 11531 11532 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 11533 if ((0 == (fc->flags & _FP_STAT_SYNC_ENABLE)) && 11534 (SOC_IS_TRX(unit) || SOC_IS_BRADLEY(unit))) { 11535 /* Read X pipeline counter memory. */ 11536 if (INVALIDm != counter_x_mem) { 11537 cntrs64_buf = &stage_fc->_field_x64_counters[idx]; 11538 COMPILER_64_ADD_64(*byte_count, 11539 cntrs64_buf->accumulated_counter); 11540 #if defined(BCM_SCORPION_SUPPORT) 11541 cntrs32_buf = &stage_fc->_field_x32_counters[idx]; 11542 COMPILER_64_ADD_64(*packet_count, 11543 cntrs32_buf->accumulated_counter); 11544 #endif 11545 } 11546 11547 /* Read Y pipeline counter memory. */ 11548 if (INVALIDm != counter_y_mem) { 11549 cntrs64_buf = &stage_fc->_field_y64_counters[idx]; 11550 COMPILER_64_ADD_64(*byte_count, 11551 cntrs64_buf->accumulated_counter); 11552 11553 #if defined(BCM_SCORPION_SUPPORT) 11554 cntrs32_buf = &stage_fc->_field_y32_counters[idx]; 11555 COMPILER_64_ADD_64(*packet_count, 11556 cntrs32_buf->accumulated_counter); 11557 #endif 11558 } 11559 } else 11560 #endif 11561 { 11562 /* Allocate buffer for counter values in HW. */ 11563 _FP_XGS3_ALLOC(hw_buf_x, 2 * WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS), 11564 "Counter buffers"); 11565 if (NULL == hw_buf_x) { 11566 return (BCM_E_MEMORY); 11567 } 11568 11569 /* Read X pipeline counter memory. */ 11570 if (INVALIDm != counter_x_mem) { 11571 rv = soc_mem_read(unit, counter_x_mem, MEM_BLOCK_ANY, idx, hw_buf_x); 11572 if (BCM_FAILURE(rv)) { 11573 sal_free(hw_buf_x); 11574 return (BCM_E_MEMORY); 11575 } 11576 } 11577 11578 /* Read Y pipeline counter memory. */ 11579 if (INVALIDm != counter_y_mem) { 11580 hw_buf_y = hw_buf_x + SOC_MAX_MEM_FIELD_WORDS; 11581 rv = soc_mem_read(unit, counter_y_mem, MEM_BLOCK_ANY, idx, hw_buf_y); 11582 if (BCM_FAILURE(rv)) { 11583 sal_free(hw_buf_x); 11584 return (BCM_E_MEMORY); 11585 } 11586 } 11587 11588 /* Process accumulated counter value. */ 11589 rv = fc->functions.fp_counter_get(unit, stage_fc, counter_x_mem, 11590 hw_buf_x, counter_y_mem, hw_buf_y, 11591 idx, packet_count, byte_count); 11592 sal_free(hw_buf_x); 11593 } 11594 return (rv); 11595 } 11596 11597 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 11598 /* 11599 * Function: 11600 * _field_flex_stat_value_set 11601 * 11602 * Description: 11603 * Set 64 bit flex counter value for specific statistic type. 11604 * Parameters: 11605 * unit - (IN) BCM device number. 11606 * f_st - (IN) Statistics entity descriptor. 11607 * stat - (IN) Collected statistics descriptor. 11608 * value - (IN) Collected counters value. 11609 * Returns: 11610 * BCM_E_XXX 11611 */ 11612 STATIC int 11613 _field_flex_stat_value_set(int unit, 11614 _field_stat_t *f_st, 11615 bcm_field_stat_t stat, 11616 uint64 value) 11617 { 11618 _field_stage_t *stage_fc; /* Stage field control. */ 11619 int idx; /* Stat array index. */ 11620 bcm_stat_value_t stat_val = {0}; /* Flex counter statistics. */ 11621 11622 /* Get field control. */ 11623 11624 11625 /* Stage field control structure. */ 11626 BCM_IF_ERROR_RETURN 11627 (_field_stage_control_get(unit, 11628 f_st->stage_id, 11629 &stage_fc 11630 ) 11631 ); 11632 11633 /* Check that stat was requested during statistics entity creation. */ 11634 for (idx = 0; idx < f_st->nstat; idx++) { 11635 if (stat == f_st->stat_arr[idx]) { 11636 break; 11637 } 11638 } 11639 11640 if (idx == f_st->nstat) { 11641 return (BCM_E_PARAM); 11642 } 11643 11644 if (_FP_INVALID_INDEX != f_st->hw_index) { 11645 11646 if (stat == bcmFieldStatPackets) { 11647 COMPILER_64_TO_32_LO(stat_val.packets, value); 11648 } else { 11649 COMPILER_64_SET(stat_val.bytes, 11650 COMPILER_64_HI(value), 11651 COMPILER_64_LO(value)); 11652 } 11653 11654 /* coverity[uninit_use_in_call : FALSE] */ 11655 BCM_IF_ERROR_RETURN 11656 (_bcm_esw_stat_counter_raw_set(unit, 11657 f_st->flex_mode, 11658 (stat == bcmFieldStatBytes) ? 1 : 0, 11659 (f_st->hw_entry_count - 1), 11660 &stat_val 11661 ) 11662 ); 11663 11664 } 11665 11666 return (BCM_E_NONE); 11667 } 11668 #endif 11669 #if defined(BCM_HURRICANE3_SUPPORT) 11670 /* 11671 * Function: 11672 * _field_flowcnt_stat_value_set 11673 * 11674 * Description: 11675 * Set 64 bit flowcnt counter value for specific statistic type. 11676 * Parameters: 11677 * unit - (IN) BCM device number. 11678 * f_st - (IN) Statistics entity descriptor. 11679 * stat - (IN) Collected statistics descriptor. 11680 * value - (IN) Collected counters value. 11681 * Returns: 11682 * BCM_E_XXX 11683 */ 11684 STATIC int 11685 _field_flowcnt_stat_value_set(int unit, 11686 _field_stat_t *f_st, 11687 bcm_field_stat_t stat, 11688 uint64 value) 11689 { 11690 int idx; /* Stat array index. */ 11691 bcm_stat_value_t stat_val; /* Flowcnt counter statistics. */ 11692 uint32 byte_flag; /* Byte or packet */ 11693 11694 /* Check that stat was requested during statistics entity creation. */ 11695 for (idx = 0; idx < f_st->nstat; idx++) { 11696 if (stat == f_st->stat_arr[idx]) { 11697 break; 11698 } 11699 } 11700 11701 if (idx == f_st->nstat) { 11702 return (BCM_E_PARAM); 11703 } 11704 11705 if (_FP_INVALID_INDEX != f_st->hw_index) { 11706 11707 if (stat == bcmFieldStatBytes) { 11708 byte_flag = 1; 11709 COMPILER_64_SET(stat_val.bytes, 11710 COMPILER_64_HI(value), 11711 COMPILER_64_LO(value)); 11712 } else if (stat == bcmFieldStatPackets) { 11713 byte_flag = 0; 11714 COMPILER_64_TO_32_LO(stat_val.packets, value); 11715 } else { 11716 return BCM_E_CONFIG; 11717 } 11718 11719 BCM_IF_ERROR_RETURN 11720 (_bcm_esw_flowcnt_counter_raw_set(unit, f_st->flex_mode, 11721 byte_flag, 11722 0, 11723 &stat_val 11724 ) 11725 ); 11726 11727 } 11728 11729 return (BCM_E_NONE); 11730 } 11731 #endif 11732 11733 /* 11734 * Function: 11735 * _field_stat_value_set 11736 * 11737 * Description: 11738 * Set 64 bit counter value for specific statistic type. 11739 * Parameters: 11740 * unit - (IN) BCM device number. 11741 * f_st - (IN) Statistics entity descriptor. 11742 * stat - (IN) Collected statistics descriptor. 11743 * value - (IN) Collected counters value. 11744 * Returns: 11745 * BCM_E_XXX 11746 */ 11747 int 11748 _field_stat_value_set(int unit, _field_stat_t *f_st, bcm_field_stat_t stat, 11749 uint64 value) 11750 { 11751 _field_stage_t *stage_fc; /* Stage field control. */ 11752 _field_control_t *fc; /* Field control structure. */ 11753 #if defined (BCM_TRIUMPH2_SUPPORT) 11754 _bcm_flex_stat_t flex_stat; /* Flex stat type. */ 11755 #endif /* BCM_TRIUMPH2_SUPPORT */ 11756 int idx1; /* First counter index to read. */ 11757 int idx2; /* Second counter index to read.*/ 11758 int idx3; /* Third counter index to read.*/ 11759 uint32 flags; /* _FP_STAT_XXX. */ 11760 int rv; /* Operation return status. */ 11761 11762 /* Input parameters check. */ 11763 if (NULL == f_st) { 11764 return (BCM_E_PARAM); 11765 } 11766 11767 /* Stage field control structure. */ 11768 rv = _field_stage_control_get(unit, f_st->stage_id, &stage_fc); 11769 BCM_IF_ERROR_RETURN(rv); 11770 11771 /* Get field control. */ 11772 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 11773 11774 #if defined(BCM_TOMAHAWK_SUPPORT) 11775 if ((stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) && 11776 !((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) && 11777 (f_st->hw_flags & _FP_STAT_FLEX_CNTR))) { 11778 return (fc->functions.fp_stat_value_set(unit, f_st, stat, value)); 11779 } 11780 #endif 11781 11782 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 11783 if (soc_feature(unit, soc_feature_advanced_flex_counter)) { 11784 if (f_st->hw_flags & _FP_STAT_FLEX_CNTR) { 11785 return (_field_flex_stat_value_set(unit, 11786 f_st, 11787 stat, 11788 value 11789 ) 11790 ); 11791 } 11792 } 11793 #endif 11794 11795 #if defined(BCM_HURRICANE3_SUPPORT) 11796 if ((_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) 11797 && soc_feature(unit, soc_feature_flowcnt)) { 11798 11799 if (f_st->hw_flags & _FP_STAT_FLOWCNT_CNTR) { 11800 return (_field_flowcnt_stat_value_set(unit, 11801 f_st, 11802 stat, 11803 value 11804 ) 11805 ); 11806 } 11807 } 11808 #endif 11809 11810 #if defined (BCM_TRIUMPH2_SUPPORT) 11811 /* Flexible stat counters handling. */ 11812 if (_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) { 11813 flex_stat = (stat == bcmFieldStatBytes) ? _bcmFlexStatIngressBytes : 11814 _bcmFlexStatIngressPackets; 11815 return _bcm_esw_flex_stat_set(unit, _bcmFlexStatTypeFp, 11816 f_st->sid, flex_stat, value); 11817 } 11818 #endif /* BCM_TRIUMPH2_SUPPORT */ 11819 11820 /* Check that stat was requested during statistics entity creation. */ 11821 for (idx1 = 0; idx1 < f_st->nstat; idx1++) { 11822 if (stat == f_st->stat_arr[idx1]) { 11823 break; 11824 } 11825 } 11826 if (idx1 == f_st->nstat) { 11827 return (BCM_E_PARAM); 11828 } 11829 11830 /* Get hw indexes and flags needed to compose requested statistic.*/ 11831 rv = fc->functions.fp_stat_index_get(unit, f_st, stat, &idx1, 11832 &idx2, &idx3, &flags); 11833 BCM_IF_ERROR_RETURN(rv); 11834 11835 /* Set accumulated counter value at primary index. */ 11836 if (_FP_INVALID_INDEX == idx1) { 11837 return (BCM_E_INTERNAL); 11838 } 11839 11840 if (flags & _FP_STAT_BYTES) { 11841 rv = _field_sw_counter_set(unit, stage_fc, idx1, NULL, &value); 11842 } else { 11843 rv = _field_sw_counter_set(unit, stage_fc, idx1, &value, NULL); 11844 } 11845 BCM_IF_ERROR_RETURN(rv); 11846 11847 /* Reset accumulated counter value at secondary index. */ 11848 if (_FP_INVALID_INDEX != idx2) { 11849 /* <HP> 11850 11851 Should this behaviour be looked at? What this means is that setting 11852 the value for an "implied" stat (i.e. one not directly represented by 11853 a hardware counter, but calculated from hardware counters) affects 11854 values for non-implied stats. 11855 11856 Example: 11857 stat = { red, yellow, not-green } 11858 11859 which is represented in the hardware by 2 counters, one for r and one 11860 for y, and not-green is returned as the sum of r and y hardware 11861 counters. 11862 11863 But, setting the not-green stat to X will set one of the hardware 11864 counters to X and the other to 0. Thus, the r and y counts will be 11865 lost, and one of them will be set to X, and the other to 0 -- rather 11866 bizarre behaviour from an outside point-of-view. 11867 11868 </HP> */ 11869 11870 COMPILER_64_ZERO (value); 11871 if (flags & _FP_STAT_BYTES) { 11872 rv = _field_sw_counter_set(unit, stage_fc, idx2, NULL, &value); 11873 } else { 11874 rv = _field_sw_counter_set(unit, stage_fc, idx2, &value, NULL); 11875 } 11876 } 11877 11878 BCM_IF_ERROR_RETURN(rv); 11879 11880 if (_FP_INVALID_INDEX != idx3) { 11881 COMPILER_64_ZERO (value); 11882 if (flags & _FP_STAT_BYTES) { 11883 rv = _field_sw_counter_set(unit, stage_fc, idx3, NULL, &value); 11884 } else { 11885 rv = _field_sw_counter_set(unit, stage_fc, idx3, &value, NULL); 11886 } 11887 } 11888 11889 return (rv); 11890 } 11891 11892 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 11893 /* 11894 * Function: 11895 * _field_flex_stat_get 11896 * Purpose: 11897 * Get flex stat counter value 11898 * Parameters: 11899 * unit - (IN) BCM device number 11900 * f_st - (IN) Pointer to field stat structure 11901 * stat - (IN) Stat type value to get 11902 * value - (OUT) Stat value 11903 * Returns: 11904 * BCM_E_XXX 11905 */ 11906 STATIC int 11907 _field_flex_stat_get(int unit, 11908 int sync_mode, 11909 _field_stat_t *f_st, 11910 bcm_field_stat_t stat, 11911 uint64 *value) 11912 { 11913 int idx; 11914 bcm_stat_value_t stat_val; 11915 int rv; 11916 11917 /* Stat Type Check. */ 11918 if ((bcmFieldStatPackets != stat) 11919 && (bcmFieldStatBytes != stat)) { 11920 return (BCM_E_PARAM); 11921 } 11922 11923 /* Check that stat was requested during statistics entity creation. */ 11924 for (idx = 0 ; idx < f_st->nstat; idx++) { 11925 if (stat == f_st->stat_arr[idx]) { 11926 break; 11927 } 11928 } 11929 11930 /* Invalid Stat. */ 11931 if (idx == f_st->nstat) { 11932 return (BCM_E_PARAM); 11933 } 11934 11935 COMPILER_64_ZERO(*value); 11936 11937 if (_FP_INVALID_INDEX != f_st->hw_index) { 11938 /* Read stat value using flex stat routine.*/ 11939 rv = _bcm_esw_stat_counter_raw_get(unit, 11940 sync_mode, 11941 f_st->flex_mode, 11942 (stat == bcmFieldStatBytes) ? 1 : 0, 11943 (f_st->hw_entry_count - 1), 11944 &stat_val 11945 ); 11946 /* 11947 * Flex STAT module is initalized before field module during reset. 11948 * Attempt to read flex stats by field module would result in 11949 * error. Ignore these errors. 11950 */ 11951 if (BCM_FAILURE(rv)) { 11952 if (TRUE == _field_control[unit]->init) { 11953 return (rv); 11954 } else { 11955 return (BCM_E_NOT_FOUND); 11956 } 11957 } else { 11958 /* Store retrieved stat value in return variable. */ 11959 if (bcmFieldStatPackets == stat) { 11960 COMPILER_64_ADD_32(*value, stat_val.packets); 11961 } else { 11962 COMPILER_64_OR(*value, stat_val.bytes); 11963 } 11964 } 11965 } 11966 11967 return (BCM_E_NONE); 11968 } 11969 #endif 11970 11971 #if defined(BCM_HURRICANE3_SUPPORT) 11972 /* 11973 * Function: 11974 * _field_flowcnt_stat_get 11975 * Purpose: 11976 * Get vlan flow stat counter value 11977 * Parameters: 11978 * unit - (IN) BCM device number 11979 * f_st - (IN) Pointer to field stat structure 11980 * stat - (IN) Stat type value to get 11981 * value - (OUT) Stat value 11982 * Returns: 11983 * BCM_E_XXX 11984 */ 11985 STATIC int 11986 _field_flowcnt_stat_get(int unit, 11987 int sync_mode, 11988 _field_stat_t *f_st, 11989 bcm_field_stat_t stat, 11990 uint64 *value) 11991 { 11992 int idx; 11993 bcm_stat_value_t stat_val; 11994 int rv; 11995 11996 /* Stat Type Check. */ 11997 if ((bcmFieldStatPackets != stat) 11998 && (bcmFieldStatBytes != stat)) { 11999 return (BCM_E_PARAM); 12000 } 12001 12002 /* Check that stat was requested during statistics entity creation. */ 12003 for (idx = 0 ; idx < f_st->nstat; idx++) { 12004 if (stat == f_st->stat_arr[idx]) { 12005 break; 12006 } 12007 } 12008 12009 /* Invalid Stat. */ 12010 if (idx == f_st->nstat) { 12011 return (BCM_E_PARAM); 12012 } 12013 12014 COMPILER_64_ZERO(*value); 12015 12016 if (_FP_INVALID_INDEX != f_st->hw_index) { 12017 /* Read stat value using flowcnt stat routine.*/ 12018 rv = _bcm_esw_flowcnt_counter_raw_get( 12019 unit, sync_mode, f_st->flex_mode, 12020 (stat == bcmFieldStatBytes) ? 1 : 0, 12021 0, 12022 &stat_val); 12023 /* 12024 * STAT module is initalized before field module during reset. 12025 * Attempt to read flex stats by field module would result in 12026 * error. Ignore these errors. 12027 */ 12028 if (BCM_FAILURE(rv)) { 12029 if (TRUE == _field_control[unit]->init) { 12030 return (rv); 12031 } else { 12032 return (BCM_E_NOT_FOUND); 12033 } 12034 } else { 12035 /* Store retrieved stat value in return variable. */ 12036 if (bcmFieldStatPackets == stat) { 12037 COMPILER_64_ADD_32(*value, stat_val.packets); 12038 } else { 12039 COMPILER_64_OR(*value, stat_val.bytes); 12040 } 12041 } 12042 } 12043 12044 return (BCM_E_NONE); 12045 } 12046 12047 12048 #endif /* BCM_HURRICANE3_SUPPORT */ 12049 12050 /* 12051 * Function: 12052 * _field_stat_value_get 12053 * 12054 * Description: 12055 * Get 64 bit counter value for specific statistic type. 12056 * Parameters: 12057 * unit - (IN) BCM device number. 12058 * f_st - (IN) Statistics entity descriptor. 12059 * stat - (IN) Collected statistics descriptor. 12060 * value - (OUT) Collected counters value. 12061 * Returns: 12062 * BCM_E_XXX 12063 */ 12064 int 12065 _field_stat_value_get(int unit, int sync_mode, _field_stat_t *f_st, bcm_field_stat_t stat, 12066 uint64 *value) 12067 { 12068 uint64 packet_count_1; /* Primary index packet count. */ 12069 uint64 byte_count_1; /* Primary index byte count. */ 12070 uint64 packet_count_2; /* Secondary index packet count.*/ 12071 uint64 byte_count_2; /* Secondary index byte count. */ 12072 uint64 packet_count_3; /* Third counter index packet count. */ 12073 uint64 byte_count_3; /* Third counterindex byte count. */ 12074 _field_stage_t *stage_fc; /* Stage field control. */ 12075 #if defined (BCM_TRIUMPH2_SUPPORT) 12076 _bcm_flex_stat_t flex_stat; /* Flex stat type. */ 12077 #endif /* BCM_TRIUMPH2_SUPPORT */ 12078 _field_control_t *fc; /* Field control structure. */ 12079 int idx1; /* First counter index to read. */ 12080 int idx2; /* Second counter index to read.*/ 12081 int idx3; /* Third counter index to read. */ 12082 uint32 flags; /* _FP_STAT_XXX. */ 12083 int rv; /* Operation return status. */ 12084 12085 /* Input parameters check. */ 12086 if ((NULL == value) || (NULL == f_st)) { 12087 return (BCM_E_PARAM); 12088 } 12089 12090 12091 /* Get field control. */ 12092 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 12093 12094 /* Stage field control structure. */ 12095 rv = _field_stage_control_get(unit, f_st->stage_id, &stage_fc); 12096 BCM_IF_ERROR_RETURN(rv); 12097 12098 #if defined(BCM_TOMAHAWK_SUPPORT) 12099 if ((stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) && 12100 !((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) && 12101 (f_st->hw_flags & _FP_STAT_FLEX_CNTR))) { 12102 return (fc->functions.fp_stat_value_get(unit, sync_mode, 12103 f_st, stat, value)); 12104 } 12105 #endif 12106 12107 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 12108 /* Get flex stat counter value. */ 12109 if (soc_feature(unit, soc_feature_advanced_flex_counter)) { 12110 if (f_st->hw_flags & _FP_STAT_FLEX_CNTR) { 12111 return (_field_flex_stat_get(unit, sync_mode, f_st, stat, value)); 12112 } 12113 } 12114 #endif 12115 12116 #if defined(BCM_HURRICANE3_SUPPORT) 12117 if ((_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) 12118 && (soc_feature(unit, soc_feature_flowcnt))) { 12119 12120 return (_field_flowcnt_stat_get(unit, sync_mode, f_st, stat, value)); 12121 } 12122 #endif 12123 12124 12125 #if defined (BCM_TRIUMPH2_SUPPORT) 12126 /* Flexible stat counters handling. */ 12127 if (_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) { 12128 flex_stat = (stat == bcmFieldStatBytes) ? _bcmFlexStatIngressBytes : 12129 _bcmFlexStatIngressPackets; 12130 return _bcm_esw_flex_stat_get(unit, sync_mode,_bcmFlexStatTypeFp, 12131 f_st->sid, flex_stat, value); 12132 } 12133 #endif /* BCM_TRIUMPH2_SUPPORT */ 12134 12135 /* Initialization. */ 12136 COMPILER_64_ZERO(packet_count_1); 12137 COMPILER_64_ZERO(packet_count_2); 12138 COMPILER_64_ZERO(packet_count_3); 12139 COMPILER_64_ZERO(byte_count_1); 12140 COMPILER_64_ZERO(byte_count_2); 12141 COMPILER_64_ZERO(byte_count_3); 12142 idx1 = idx2 = idx3 = _FP_INVALID_INDEX; 12143 flags = 0; 12144 12145 12146 /* Check that stat was requested during statistics entity creation. */ 12147 for (idx1 = 0; idx1 < f_st->nstat; idx1++) { 12148 if (stat == f_st->stat_arr[idx1]) { 12149 break; 12150 } 12151 } 12152 if (idx1 == f_st->nstat) { 12153 return (BCM_E_PARAM); 12154 } 12155 12156 /* Get hw indexes and flags needed to compose requested statistic.*/ 12157 rv = fc->functions.fp_stat_index_get(unit, f_st, stat, &idx1, 12158 &idx2, &idx3, &flags); 12159 BCM_IF_ERROR_RETURN(rv); 12160 12161 /* Get accumulated counter value at primary index. */ 12162 if (_FP_INVALID_INDEX != idx1) { 12163 rv = _field_sw_counter_get(unit, stage_fc, idx1, &packet_count_1, 12164 &byte_count_1); 12165 BCM_IF_ERROR_RETURN(rv); 12166 } 12167 12168 /* Get accumulated counter value at secondary index. */ 12169 if (_FP_INVALID_INDEX != idx2) { 12170 rv = _field_sw_counter_get(unit, stage_fc, idx2, &packet_count_2, 12171 &byte_count_2); 12172 BCM_IF_ERROR_RETURN(rv); 12173 } 12174 12175 /* Get accumulated counter value at secondary index. */ 12176 if (_FP_INVALID_INDEX != idx3) { 12177 rv = _field_sw_counter_get(unit, stage_fc, idx3, &packet_count_3, 12178 &byte_count_3); 12179 BCM_IF_ERROR_RETURN(rv); 12180 } 12181 12182 /* Get final counter value. */ 12183 COMPILER_64_ZERO(*value); 12184 if (flags & _FP_STAT_BYTES) { 12185 if (flags & _FP_STAT_ADD) { 12186 COMPILER_64_ADD_64(byte_count_1, byte_count_2); 12187 COMPILER_64_ADD_64(byte_count_1, byte_count_3); 12188 } else if (flags & _FP_STAT_SUBSTRACT) { 12189 COMPILER_64_SUB_64(byte_count_1, byte_count_2); 12190 } 12191 COMPILER_64_OR(*value, byte_count_1); 12192 } else { 12193 if (flags & _FP_STAT_ADD) { 12194 COMPILER_64_ADD_64(packet_count_1, packet_count_2); 12195 COMPILER_64_ADD_64(packet_count_1, packet_count_3); 12196 } else if (flags & _FP_STAT_SUBSTRACT) { 12197 COMPILER_64_SUB_64(packet_count_1, packet_count_2); 12198 } 12199 COMPILER_64_OR(*value, packet_count_1); 12200 } 12201 return (BCM_E_NONE); 12202 } 12203 12204 /* 12205 * Function: 12206 * _field_stat_hw_free 12207 * 12208 * Purpose: 12209 * Deallocate hw counter from an entry. 12210 * 12211 * Parameters: 12212 * unit - (IN) BCM device number. 12213 * f_ent - (IN) Entry statistics belongs to. 12214 * Returns: 12215 * BCM_E_XXX 12216 */ 12217 int 12218 _field_stat_hw_free (int unit, _field_entry_t *f_ent) 12219 { 12220 _field_entry_stat_t *f_ent_st; /* Field entry statistics structure. */ 12221 _field_stat_t *f_st; /* Statistics entity descriptor. */ 12222 uint64 value; /* 64 bit zero to reset hw value. */ 12223 int idx; /* Statistics iteration index. */ 12224 int rv; /* Operation return status. */ 12225 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 12226 defined(BCM_HURRICANE3_SUPPORT) 12227 _field_stage_t *stage_fc; /* pipeline stage */ 12228 int entry_idx = 0; /* Entry index at policy table */ 12229 #endif 12230 /* Input parameters check. */ 12231 if (NULL == f_ent) { 12232 return (BCM_E_PARAM); 12233 } 12234 f_ent_st = &f_ent->statistic; 12235 12236 /* Skip uninstalled statistics entity. */ 12237 if (0 == (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED)) { 12238 return (BCM_E_NONE); 12239 } 12240 12241 #if defined(BCM_KATANA2_SUPPORT) 12242 if (soc_feature(unit, soc_feature_flex_stat_compaction_support) && 12243 f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 12244 BCM_IF_ERROR_RETURN( 12245 _bcm_field_kt2_entry_stat_detach(unit, f_ent, 12246 f_ent_st->extended_sid)); 12247 12248 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 12249 return (BCM_E_NONE); 12250 } 12251 #endif 12252 /* No de-allocation is required for external FP. */ 12253 if (_BCM_FIELD_STAGE_EXTERNAL == f_ent->fs->stage_id) { 12254 #ifdef BCM_TRIUMPH3_SUPPORT 12255 if (SOC_IS_TRIUMPH3(unit)) { 12256 /* Update Ingress accounting table's statistics */ 12257 BCM_IF_ERROR_RETURN 12258 (_bcm_esw_tr3_ext_stat_flex_detach_ingress_table_counters( 12259 unit, f_ent)); 12260 } 12261 #endif 12262 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 12263 return (BCM_E_NONE); 12264 } 12265 12266 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 12267 defined(BCM_HURRICANE3_SUPPORT) 12268 /* Get pipeline stage information. */ 12269 BCM_IF_ERROR_RETURN 12270 (_field_stage_control_get(unit, 12271 f_ent->group->stage_id, 12272 &stage_fc 12273 ) 12274 ); 12275 #endif 12276 12277 /* Read stat entity configuration. */ 12278 BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st)); 12279 12280 /* Decrement hw reference count. */ 12281 if (f_st->hw_ref_count > 0) { 12282 f_st->hw_ref_count--; 12283 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 12284 if (soc_feature(unit, soc_feature_advanced_flex_counter)) { 12285 if (f_st->flex_mode != 0 && f_st->hw_ref_count > 0) { 12286 /* 12287 * Get entry index at which flex STAT information 12288 * has been programmed in policy table. 12289 */ 12290 BCM_IF_ERROR_RETURN 12291 (_bcm_field_slice_offset_to_tcam_idx(unit, 12292 stage_fc, 12293 f_ent->group->instance, 12294 f_ent->fs->slice_number, 12295 f_ent->slice_idx, 12296 &entry_idx 12297 ) 12298 ); 12299 12300 rv = _bcm_esw_stat_flex_detach_ingress_table_counters 12301 (unit, 12302 VFP_POLICY_TABLEm, 12303 entry_idx 12304 ); 12305 /* 12306 * Flex STAT module detached before field module, ignore 12307 * error during bcm_field_detach(). 12308 */ 12309 if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) { 12310 return (rv); 12311 } 12312 } 12313 } 12314 #endif 12315 #if defined(BCM_HURRICANE3_SUPPORT) 12316 if (soc_feature(unit, soc_feature_flowcnt) && 12317 (_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id)) { 12318 if (f_st->flex_mode != 0 && f_st->hw_ref_count > 0) { 12319 12320 /* 12321 * Get entry index at which STAT information 12322 * has been programmed in policy table. 12323 */ 12324 BCM_IF_ERROR_RETURN 12325 (_bcm_field_slice_offset_to_tcam_idx(unit, 12326 stage_fc, 12327 f_ent->group->instance, 12328 f_ent->fs->slice_number, 12329 f_ent->slice_idx, 12330 &entry_idx 12331 )); 12332 12333 rv = _bcm_esw_flowcnt_object_table_detach(unit, 12334 VFP_POLICY_TABLEm, entry_idx); 12335 /* 12336 * STAT module detached before field module, ignore 12337 * error during bcm_field_detach(). 12338 */ 12339 if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) { 12340 return (rv); 12341 } 12342 } 12343 } 12344 #endif 12345 12346 } 12347 12348 /* Statistics is not used by any other entry. */ 12349 if (f_st->hw_ref_count == 0) { 12350 COMPILER_64_ZERO(value); 12351 /* Read & Reset individual statistics. */ 12352 for (idx = 0; idx < f_st->nstat; idx++) { 12353 rv = _field_stat_value_get(unit, 0, f_st, f_st->stat_arr[idx], 12354 f_st->stat_values + idx); 12355 if (BCM_FAILURE(rv)) { 12356 /* During system restart flex stat module 12357 * might be reinitialized before fp reinit. Hence 12358 * calls to the flex stat module will result in 12359 * BCM_E_NOT_FOUND * error code. 12360 */ 12361 if (soc_feature(unit, soc_feature_field_multi_pipe_support) 12362 && (_BCM_FIELD_STAGE_EGRESS == f_st->stage_id)) { 12363 if (TRUE == _field_control[unit]->init) { 12364 return rv; 12365 } 12366 } else if (0 == ((_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) 12367 && (BCM_E_NOT_FOUND == rv))) { 12368 return rv; 12369 } 12370 } else { 12371 rv = _field_stat_value_set(unit, f_st, 12372 f_st->stat_arr[idx], value); 12373 BCM_IF_ERROR_RETURN(rv); 12374 } 12375 } 12376 /* Mark hw resource as unused in sw. */ 12377 BCM_IF_ERROR_RETURN(_field_slice_counter_free(unit, f_ent, f_st)); 12378 } 12379 12380 /* 12381 * If qualifiers have not been modified for this entry, 12382 * set Action only dirty flag. 12383 */ 12384 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 12385 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 12386 } 12387 12388 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 12389 12390 /* Mark entry for reinstall. */ 12391 f_ent->flags |= _FP_ENTRY_DIRTY; 12392 return (BCM_E_NONE); 12393 } 12394 12395 /* 12396 * Function: 12397 * _bcm_field_stat_hw_free 12398 * 12399 * Purpose: 12400 * Free counter resources used by field entry/entries. 12401 * Parameters: 12402 * unit - (IN) BCM device number. 12403 * f_ent - (IN) Entry array policer belongs to. 12404 * Returns: 12405 * BCM_E_XXX 12406 */ 12407 int 12408 _bcm_field_stat_hw_free (int unit, _field_entry_t *f_ent) 12409 { 12410 #ifdef BCM_TRIUMPH3_SUPPORT 12411 if (SOC_IS_TRIUMPH3(unit) && 12412 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 12413 return (_bcm_field_tr3_stat_hw_free(unit, f_ent)); 12414 } 12415 #endif 12416 12417 return (_field_stat_hw_free(unit, f_ent)); 12418 } 12419 12420 12421 /* 12422 * Function: 12423 * _field_entry_stat_detach 12424 * 12425 * Description: 12426 * Detach statistics entity from Field processor entry. 12427 * Parameters: 12428 * unit - (IN) BCM device number. 12429 * f_ent - (IN) Field entry structure. 12430 * stat_id - (IN) Statistics entity id. 12431 * Returns: 12432 * BCM_E_XXX 12433 */ 12434 STATIC int 12435 _field_entry_stat_detach(int unit, _field_entry_t *f_ent, int stat_id) 12436 { 12437 _field_stat_t *f_st; /* Internal statistics entity. */ 12438 _field_entry_stat_t *f_ent_st; /* Field entry stat structure. */ 12439 _field_control_t *fc; 12440 int rv; /* Operation return status. */ 12441 12442 /* Input parameters check. */ 12443 if (NULL == f_ent) { 12444 return (BCM_E_PARAM); 12445 } 12446 #if defined(BCM_TRIDENT3_SUPPORT) 12447 if (soc_feature(unit, soc_feature_td3_style_fp) && 12448 f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) { 12449 rv = _bcm_field_td2plus_entry_stat_detach(unit, f_ent, stat_id); 12450 return rv; 12451 } 12452 #endif 12453 #if defined(BCM_KATANA2_SUPPORT) 12454 if (soc_feature(unit, soc_feature_flex_stat_compaction_support) && 12455 f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 12456 rv = _bcm_field_kt2_entry_stat_detach(unit, f_ent, stat_id); 12457 return rv; 12458 } 12459 #endif 12460 /* Make sure statistics entity attached to the entry. */ 12461 f_ent_st = &f_ent->statistic; 12462 12463 if (0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID)) { 12464 return (BCM_E_EMPTY); 12465 } 12466 12467 /* Compare statistics entity id with attached entity id. */ 12468 if (stat_id != f_ent_st->sid) { 12469 return (BCM_E_PARAM); 12470 } 12471 12472 /* Get statics entity descriptor structure. */ 12473 rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st); 12474 BCM_IF_ERROR_RETURN(rv); 12475 12476 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 12477 12478 /* If entry was installed decrement hw reference counter. */ 12479 rv = fc->functions.fp_stat_hw_free(unit, f_ent); 12480 BCM_IF_ERROR_RETURN(rv); 12481 12482 /* Decrement statistics entity reference counter. */ 12483 f_st->sw_ref_count--; 12484 12485 /* If no one else is using the entity and it is internal destroy it. */ 12486 if ((1 == f_st->sw_ref_count) && (f_st->hw_flags & _FP_STAT_INTERNAL)) { 12487 rv = _field_stat_destroy(unit, f_ent_st->sid); 12488 BCM_IF_ERROR_RETURN(rv); 12489 } 12490 12491 /* Detach policer from an entry. */ 12492 f_ent_st->sid = _FP_INVALID_INDEX; 12493 f_ent_st->flags = 0; 12494 f_ent_st->flags = _FP_ENTRY_STAT_DIRTY; 12495 12496 /* 12497 * If qualifiers have not been modified for this entry, 12498 * set Policy table only dirty flag. 12499 */ 12500 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 12501 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 12502 } 12503 /* Mark entry for reinstall. */ 12504 f_ent->flags |= _FP_ENTRY_DIRTY; 12505 12506 return (BCM_E_NONE); 12507 } 12508 /* 12509 * Function: 12510 * _bcm_field_entry_stat_detach 12511 * 12512 * Description: 12513 * Detach statistics entity from Field processor entry. 12514 * Parameters: 12515 * unit - (IN) BCM device number. 12516 * f_ent - (IN) Field entry structure. 12517 * stat_id - (IN) Statistics entity id. 12518 * Returns: 12519 * BCM_E_XXX 12520 */ 12521 int 12522 _bcm_field_entry_stat_detach(int unit, _field_entry_t *f_ent, int stat_id) 12523 { 12524 return _field_entry_stat_detach(unit, f_ent, stat_id); 12525 } 12526 /* 12527 * Function: 12528 * _field_stat_color_dependent 12529 * 12530 * Purpose: 12531 * Check if statistics entity is color dependent. 12532 * 12533 * Parameters: 12534 * unit - (IN) BCM device number. 12535 * f_st - (IN) Field statistics entity.. 12536 * color_dependent - (IN) Field statistics entity.. 12537 * Returns: 12538 * BCM_E_XXX 12539 */ 12540 STATIC int 12541 _field_stat_color_dependent(int unit, _field_stat_t *f_st, 12542 uint8 *color_dependent) 12543 { 12544 /* Input parameters check. */ 12545 if ((NULL == f_st) || (NULL == color_dependent)) { 12546 return (BCM_E_PARAM); 12547 } 12548 #if defined(BCM_TRIDENT_SUPPORT) 12549 if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) && 12550 (f_st->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 12551 switch (f_st->hw_mode & 0x7) { 12552 case (0x0): 12553 /* Fall thru */ 12554 case (0x7): 12555 *color_dependent = FALSE; 12556 break; 12557 default: 12558 *color_dependent = TRUE; 12559 break; 12560 } 12561 switch ((f_st->hw_mode >> 3) & 0x7) { 12562 case (0x0): 12563 /* Fall thru */ 12564 case (0x7): 12565 break; 12566 default: 12567 *color_dependent = TRUE; 12568 break; 12569 } 12570 } else 12571 #endif /* BCM_TRIDENT_SUPPORT */ 12572 { 12573 switch (f_st->hw_mode) { 12574 case (0x0): 12575 case (0x1): 12576 case (0x2): 12577 case (0x9): 12578 case (0xa): 12579 *color_dependent = FALSE; 12580 break; 12581 default: 12582 *color_dependent = TRUE; 12583 break; 12584 } 12585 } 12586 return (BCM_E_NONE); 12587 } 12588 12589 /* 12590 * Function: 12591 * _field_stat_hw_mode_adjust 12592 * 12593 * Purpose: 12594 * Ajust statistics entity mode based on 12595 * allocated counter index. 12596 * 12597 * Parameters: 12598 * unit - (IN) Bcm device number. 12599 * f_st - (IN/OUT) Statistics entity. 12600 * idx - (IN) Allocated hw index. 12601 * 12602 * Returns: 12603 * BCM_E_XXX 12604 */ 12605 STATIC int 12606 _field_stat_hw_mode_adjust(int unit, _field_stat_t *f_st, int idx) 12607 { 12608 /* Input parameters check. */ 12609 if (NULL == f_st) { 12610 return (BCM_E_PARAM); 12611 } 12612 12613 #if defined(BCM_TRIDENT_SUPPORT) 12614 if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) && 12615 (f_st->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 12616 /* Adjust statistics hw mode */ 12617 if (0x1 == (idx & 0x1)) { 12618 if (f_st->hw_mode & 0x7) { 12619 f_st->hw_mode <<= 3; 12620 } 12621 } else { 12622 if (((f_st->hw_mode >> 3) & 0x7)) { 12623 f_st->hw_mode >>= 3; 12624 } 12625 } 12626 } else 12627 #endif /* BCM_TRIDENT_SUPPORT */ 12628 { 12629 /* Adjust statistics hw mode */ 12630 if (0 == (idx & 0x1)) { 12631 if ((0xa == f_st->hw_mode) || (0x2 == f_st->hw_mode)) { 12632 f_st->hw_mode--; 12633 } 12634 } else { 12635 if ((0x9 == f_st->hw_mode) || (0x1 == f_st->hw_mode)) { 12636 f_st->hw_mode++; 12637 } 12638 } 12639 } 12640 return (BCM_E_NONE); 12641 } 12642 12643 /* 12644 * Function: 12645 * _field_slice_counter_alloc 12646 * 12647 * Purpose: 12648 * Allocate a counter from a slice. 12649 * 12650 * Parameters: 12651 * unit - (IN) Bcm device number. 12652 * fs - (IN) Slice where counter resides. 12653 * f_st - (IN/OUT) Statistics entity. 12654 * 12655 * Returns: 12656 * BCM_E_XXX 12657 */ 12658 STATIC int 12659 _field_slice_counter_alloc(int unit, _field_slice_t *fs, _field_stat_t *f_st) 12660 { 12661 int idx; /* Bitmap iteration index. */ 12662 int idx_max; /* Total number of counters. */ 12663 12664 if ((NULL == fs) || (NULL == f_st)) { 12665 return (BCM_E_PARAM); 12666 } 12667 12668 idx_max = fs->counters_count; 12669 12670 /* If counter is disabled skip allocation. */ 12671 if (0 == f_st->hw_mode) { 12672 return (BCM_E_NONE); 12673 } 12674 12675 for (idx = 0; idx < idx_max; idx++) { 12676 /* Double entry counters. (e.g Red + Green) */ 12677 if (0x2 == f_st->hw_entry_count) { 12678 if (0 != (idx % 2)) { 12679 /* Skip odd indexes. */ 12680 continue; 12681 } 12682 if ((0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, idx)) && 12683 (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, (idx + 1)))) { 12684 /* Mark counter as used. */ 12685 _FP_COUNTER_BMP_ADD(fs->counter_bmp, idx); 12686 _FP_COUNTER_BMP_ADD(fs->counter_bmp, idx + 1); 12687 /* Save counter information in statistics entity structure. */ 12688 f_st->pool_index = fs->slice_number; 12689 f_st->hw_index = idx/2; 12690 /* Set counter dirty flag. */ 12691 break; 12692 } else { 12693 continue; 12694 } 12695 } 12696 12697 /* Single entry counters. (e.g Bytes) */ 12698 if ((0x1 == f_st->hw_entry_count) 12699 && (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, idx))) { 12700 /* Mark counter as used. */ 12701 _FP_COUNTER_BMP_ADD(fs->counter_bmp, idx); 12702 /* Save counter information in statistics entity structure. */ 12703 f_st->pool_index = fs->slice_number; 12704 #if defined (BCM_FIREBOLT2_SUPPORT) 12705 if (SOC_IS_FIREBOLT2(unit) && (_BCM_FIELD_STAGE_EGRESS == f_st->stage_id)) { 12706 /* FB2 - doesn't have counter pairs in stage egress. */ 12707 f_st->hw_index = idx; 12708 } else 12709 #endif /* BCM_FIREBOLT2_SUPPORT */ 12710 { 12711 f_st->hw_index = (idx/2); 12712 /* Adjust statistics hw mode */ 12713 BCM_IF_ERROR_RETURN(_field_stat_hw_mode_adjust(unit, f_st, idx)); 12714 } 12715 break; 12716 } 12717 } 12718 if (idx == idx_max) { 12719 return (BCM_E_RESOURCE); 12720 } 12721 return (BCM_E_NONE); 12722 } 12723 12724 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 12725 /* 12726 * Function: 12727 * _field_flex_counter_hw_alloc 12728 * 12729 * Purpose: 12730 * Allocate flex stat hardware resource 12731 * 12732 * Parameters: 12733 * unit - (IN) BCM device number. 12734 * f_ent - (IN) Entry array policer belongs to. 12735 * Returns: 12736 * BCM_E_XXX 12737 */ 12738 STATIC int 12739 _field_flex_counter_hw_alloc(int unit, 12740 _field_entry_t *f_ent) 12741 { 12742 bcm_stat_flex_mode_t offset_mode; /* Counter mode. */ 12743 bcm_stat_group_mode_t stat_mode; /* Stat type bcmStatGroupModeXXX. */ 12744 bcm_stat_object_t stat_obj; /* Stat object type. */ 12745 _field_entry_stat_t *f_ent_st; /* Field entry stat collector. */ 12746 _field_stat_t *f_st; /* Field statistics descriptor. */ 12747 uint32 flex_sid; /* Flex Stat ID. */ 12748 uint32 num_hw_cntrs; /* Number of counters allocated. */ 12749 uint32 pool_num; /* Flex Stat Hw Pool No. */ 12750 uint32 base_index; /* Flex Stat counter base index. */ 12751 12752 /* Input parameters check. */ 12753 if (NULL == f_ent) { 12754 return (BCM_E_PARAM); 12755 } 12756 12757 /* Get field entry STAT structure. */ 12758 f_ent_st = &f_ent->statistic; 12759 12760 /* Read STAT configuration. */ 12761 BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st)); 12762 12763 /* If counter is disabled skip allocation. */ 12764 if (0 == f_st->hw_stat) { 12765 return (BCM_E_NONE); 12766 } 12767 12768 if (_FP_INVALID_INDEX == f_st->hw_index) { 12769 switch (f_st->stage_id) { 12770 case _BCM_FIELD_STAGE_LOOKUP: 12771 stat_obj = bcmStatObjectIngPolicy; 12772 break; 12773 case _BCM_FIELD_STAGE_EXTERNAL: 12774 stat_obj = bcmStatObjectIngEXTPolicy; 12775 break; 12776 default: 12777 /* IFP and EFP stages does not use Flex STAT. */ 12778 return (BCM_E_INTERNAL); 12779 } 12780 12781 /* Create a flex stat group. */ 12782 BCM_IF_ERROR_RETURN 12783 (bcm_esw_stat_group_create(unit, 12784 stat_obj, 12785 (bcm_stat_group_mode_t) f_st->hw_mode, 12786 &flex_sid, 12787 &num_hw_cntrs 12788 ) 12789 ); 12790 12791 /* Get flex counter hardware details stored in flex stat ID.*/ 12792 _bcm_esw_stat_get_counter_id_info(unit, flex_sid, 12793 &stat_mode, 12794 &stat_obj, 12795 &offset_mode, 12796 &pool_num, 12797 &base_index 12798 ); 12799 /* Store flex stat hardware details in stat data structure. */ 12800 f_st->flex_mode = flex_sid; 12801 f_st->pool_index = pool_num; 12802 f_st->hw_index = base_index; 12803 f_st->hw_mode = offset_mode; 12804 f_st->hw_entry_count = num_hw_cntrs; 12805 /* increment the group's counter count equal to 12806 the hw counters used for this stat 12807 */ 12808 f_ent->group->group_status.counter_count = 12809 f_ent->group->group_status.counter_count + f_st->hw_entry_count; 12810 } 12811 12812 /* For VFP, this flag is set in _field_trx_flex_stat_action_set */ 12813 if (_BCM_FIELD_STAGE_EXTERNAL == f_ent->fs->stage_id) { 12814 f_ent->statistic.flags |= _FP_ENTRY_STAT_INSTALLED; 12815 } 12816 return (BCM_E_NONE); 12817 } 12818 #endif 12819 12820 #if defined(BCM_HURRICANE3_SUPPORT) 12821 /* 12822 * Function: 12823 * _field_flowcnt_counter_hw_alloc 12824 * 12825 * Purpose: 12826 * Allocate flow count stat hardware resource 12827 * 12828 * Parameters: 12829 * unit - (IN) BCM device number. 12830 * f_ent - (IN) Entry array policer belongs to. 12831 * Returns: 12832 * BCM_E_XXX 12833 */ 12834 STATIC int 12835 _field_flowcnt_counter_hw_alloc(int unit, 12836 _field_entry_t *f_ent) 12837 { 12838 bcm_stat_object_t stat_obj; /* Stat object type. */ 12839 _field_entry_stat_t *f_ent_st; /* Field entry stat collector. */ 12840 _field_stat_t *f_st; /* Field statistics descriptor. */ 12841 bcm_stat_group_mode_t group; 12842 uint32 profile_group, pool_idx, base_idx; 12843 uint32 flowcnt_sid; /* Flowcnt Stat ID. */ 12844 uint32 num_hw_cntrs; /* Number of counters allocated. */ 12845 12846 /* Input parameters check. */ 12847 if (NULL == f_ent) { 12848 return (BCM_E_PARAM); 12849 } 12850 12851 /* Get field entry STAT structure. */ 12852 f_ent_st = &f_ent->statistic; 12853 12854 /* Read STAT configuration. */ 12855 BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st)); 12856 12857 /* If counter is disabled skip allocation. */ 12858 if (0 == f_st->hw_stat) { 12859 return (BCM_E_NONE); 12860 } 12861 12862 if (_FP_INVALID_INDEX == f_st->hw_index) { 12863 switch (f_st->stage_id) { 12864 case _BCM_FIELD_STAGE_LOOKUP: 12865 stat_obj = bcmStatObjectIngFieldStageLookup; 12866 break; 12867 default: 12868 /* IFP and EFP stages does not use flow count STAT. */ 12869 return (BCM_E_INTERNAL); 12870 } 12871 12872 /* Create a flowcnt stat group. */ 12873 BCM_IF_ERROR_RETURN 12874 (bcm_esw_stat_group_create(unit, 12875 stat_obj, 12876 (bcm_stat_group_mode_t) f_st->hw_mode, 12877 &flowcnt_sid, 12878 &num_hw_cntrs 12879 ) 12880 ); 12881 12882 /* Get flowcnt counter hardware details stored in flowcnt stat ID.*/ 12883 _bcm_esw_flowcnt_counter_id_get(flowcnt_sid, 12884 &group, &stat_obj, &profile_group, &pool_idx, &base_idx); 12885 12886 /* Store flex stat hardware details in stat data structure. */ 12887 f_st->flex_mode = flowcnt_sid; 12888 f_st->pool_index = pool_idx; 12889 f_st->hw_index = base_idx; 12890 f_st->hw_entry_count = num_hw_cntrs; 12891 } 12892 12893 return (BCM_E_NONE); 12894 } 12895 #endif /* BCM_HURRICANE3_SUPPORT */ 12896 12897 12898 /* 12899 * Function: 12900 * _bcm_field_counter_hw_alloc 12901 * 12902 * Purpose: 12903 * Allocate a counter/s for an entry from a slice. 12904 * 12905 * Parameters: 12906 * unit - (IN) BCM device number. 12907 * stage_fc - (IN) Stage field control structure. 12908 * f_ent - (IN/OUT) Entry array policer belongs to. 12909 * fs - (IN) Desired slice for the counter. 12910 * Returns: 12911 * BCM_E_XXX 12912 */ 12913 int 12914 _bcm_field_counter_hw_alloc(int unit, _field_entry_t *f_ent, _field_slice_t *fs) 12915 { 12916 uint8 color_dependent;/* Statistics is color based.*/ 12917 uint8 entry_part; /* Field entry tcam part. */ 12918 _field_entry_stat_t *f_ent_st; /* Field entry stat structure. */ 12919 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 12920 _field_stage_t *stage_fc; /* Stage field control. */ 12921 _field_group_t *fg; /* Field group structure. */ 12922 _field_stat_t *f_st; /* Field statistics descriptor. */ 12923 int rv; /* Operation return status. */ 12924 12925 /* Input parameters check. */ 12926 if ((NULL == f_ent) || (NULL == fs)) { 12927 return (BCM_E_PARAM); 12928 } 12929 12930 fg = f_ent->group; 12931 f_ent_pl = f_ent->policer; 12932 f_ent_st = &f_ent->statistic; 12933 12934 /* Reject unused counters. */ 12935 if (0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID)) { 12936 return (BCM_E_PARAM); 12937 } 12938 12939 /* Read STAT configuration. */ 12940 BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st)); 12941 12942 #if defined(BCM_TRIUMPH2_SUPPORT) 12943 /* Allocation is external for vfp counters. */ 12944 if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id 12945 && !soc_feature(unit, soc_feature_advanced_flex_counter) 12946 && !soc_feature(unit, soc_feature_flowcnt)) { 12947 if ((f_st->hw_flags & _FP_STAT_INTERNAL) && 0 == f_st->hw_mode) { 12948 /* 12949 * Invalid counter mode used for bcmFieldActionUpdateCounter action. 12950 * BCM_FIELD_COUNTER_MODE_DEFAULT or BCM_FIELD_COUNTER_MODE_NO_YES 12951 * are the valid counter modes for lookup stage. 12952 */ 12953 return (BCM_E_CONFIG); 12954 } 12955 /* During Enable - Pass valid counter index for new STAT API mode 12956 * or zero as counter index for old STAT API mode 12957 */ 12958 if (f_st->flex_mode) { 12959 _bcm_flex_stat_type_t fs_type; 12960 uint32 fs_inx; 12961 12962 fs_type = _BCM_FLEX_STAT_TYPE(f_st->flex_mode); 12963 fs_inx = _BCM_FLEX_STAT_COUNT_INX(f_st->flex_mode); 12964 rv = _bcm_esw_flex_stat_enable_set(unit, fs_type, 12965 _bcm_esw_fp_flex_stat_index_set, 12966 (void *)f_st, f_st->sid, 12967 TRUE,fs_inx); 12968 } else { 12969 rv = _bcm_esw_flex_stat_enable_set(unit, _bcmFlexStatTypeFp, 12970 _bcm_esw_fp_flex_stat_index_set, 12971 (void *)f_st, f_st->sid, 12972 TRUE,0); 12973 } 12974 if (BCM_SUCCESS(rv)) { 12975 /* Increment the group counters count equal to 12976 the hw entries count .*/ 12977 f_ent->group->group_status.counter_count = 12978 f_ent->group->group_status.counter_count + f_st->hw_entry_count; 12979 } 12980 return rv; 12981 } 12982 #endif /* BCM_TRIUMPH2_SUPPORT */ 12983 12984 /* Get entry stage control structure. */ 12985 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 12986 BCM_IF_ERROR_RETURN (rv); 12987 12988 12989 /* Verify if statistics entity is color dependent. */ 12990 rv = _field_stat_color_dependent(unit, f_st, &color_dependent); 12991 BCM_IF_ERROR_RETURN (rv); 12992 12993 if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) && 12994 (f_ent_pl->flags & _FP_POLICER_INSTALLED) && 12995 (color_dependent)) { 12996 /* If meter is present, counter must reside in the same slice. */ 12997 if (f_ent->flags & _FP_ENTRY_POLICER_IN_SECONDARY_SLICE) { 12998 rv = _field_slice_counter_alloc(unit, fs + 1, f_st); 12999 if (BCM_SUCCESS(rv)) { 13000 /* Get primary entry from the second slice. */ 13001 rv = _bcm_field_entry_flags_to_tcam_part (unit, 13002 _FP_ENTRY_SECONDARY, 13003 fg, &entry_part); 13004 BCM_IF_ERROR_RETURN(rv); 13005 f_ent->flags |= _FP_ENTRY_STAT_IN_SECONDARY_SLICE; 13006 sal_memcpy(&f_ent[entry_part].statistic, &f_ent->statistic, 13007 sizeof(_field_entry_stat_t)); 13008 f_ent[entry_part].statistic.flags |= _FP_ENTRY_STAT_INSTALLED; 13009 } 13010 } else { 13011 rv = _field_slice_counter_alloc(unit, fs, f_st); 13012 } 13013 } else { 13014 rv = _field_slice_counter_alloc(unit, fs, f_st); 13015 if((BCM_FAILURE(rv)) && 13016 ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 13017 (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE))) { 13018 rv = _field_slice_counter_alloc(unit, fs + 1, f_st); 13019 if (BCM_SUCCESS(rv)) { 13020 rv = _bcm_field_entry_flags_to_tcam_part (unit, 13021 _FP_ENTRY_SECONDARY, 13022 fg, &entry_part); 13023 BCM_IF_ERROR_RETURN(rv); 13024 f_ent->flags |= _FP_ENTRY_STAT_IN_SECONDARY_SLICE; 13025 sal_memcpy(&f_ent[entry_part].statistic, &f_ent->statistic, 13026 sizeof(_field_entry_stat_t)); 13027 f_ent[entry_part].statistic.flags |= _FP_ENTRY_STAT_INSTALLED; 13028 } 13029 } 13030 } 13031 /* Increment the group counters count equal to 13032 the hw entries count .*/ 13033 f_ent->group->group_status.counter_count = 13034 f_ent->group->group_status.counter_count + f_st->hw_entry_count; 13035 return (rv); 13036 } 13037 13038 13039 STATIC int 13040 _field_counter_hw_alloc(int unit, _field_entry_t *f_ent, _field_slice_t *fs) 13041 { 13042 #ifdef BCM_TRIUMPH3_SUPPORT 13043 if (SOC_IS_TRIUMPH3(unit)) { 13044 return (_bcm_field_tr3_counter_hw_alloc(unit, f_ent)); 13045 } 13046 #endif 13047 13048 return (_bcm_field_counter_hw_alloc(unit, f_ent, fs)); 13049 } 13050 13051 13052 /* 13053 * Function: 13054 * _field_stat_hw_alloc 13055 * 13056 * Purpose: 13057 * Allocate counters required for entry installation. 13058 * 13059 * Parameters: 13060 * unit - (IN) BCM device number. 13061 * f_ent - (IN) Field entry array. 13062 * fs - (IN) Slice to allocate a counter. 13063 * Returns: 13064 * BCM_E_XXX 13065 * Notes: 13066 */ 13067 STATIC int 13068 _field_stat_hw_alloc(int unit, _field_entry_t *f_ent) 13069 { 13070 _field_entry_stat_t *f_ent_st; /* Field entry stat structure. */ 13071 _field_stat_t *f_st; /* Field statistics descriptor. */ 13072 int rv; /* Operation return status. */ 13073 _field_stage_t *stage_fc; /* Field stage control structure.*/ 13074 13075 /* Input parameters check. */ 13076 if (NULL == f_ent) { 13077 return (BCM_E_PARAM); 13078 } 13079 13080 f_ent_st = &f_ent->statistic; 13081 13082 /* Skip entries without countres attached. */ 13083 if ((0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID)) || 13084 (f_ent_st->flags & _FP_ENTRY_STAT_EMPTY)) { 13085 return (BCM_E_NONE); 13086 } 13087 13088 /* No allocation is required for external FP, because: 13089 - for TR/TR2, each entry has it's own dedicated counter, and 13090 - for TR3, EXTFP supports only flex counters (as does VFP) 13091 */ 13092 if ((_BCM_FIELD_STAGE_EXTERNAL == f_ent->fs->stage_id) && 13093 !soc_feature(unit, soc_feature_advanced_flex_counter)) { 13094 f_ent_st->flags |= _FP_ENTRY_STAT_INSTALLED; 13095 return (BCM_E_NONE); 13096 } 13097 13098 /* Read statistics entity configuration. */ 13099 rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st); 13100 BCM_IF_ERROR_RETURN (rv); 13101 13102 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 13103 if (soc_feature(unit, soc_feature_advanced_flex_counter)) { 13104 /* Allocate flex STAT entity hw index. */ 13105 if (f_st->hw_flags & _FP_STAT_FLEX_CNTR) { 13106 return (_field_flex_counter_hw_alloc(unit, f_ent)); 13107 } 13108 } 13109 #endif 13110 13111 #if defined(BCM_HURRICANE3_SUPPORT) 13112 if (soc_feature(unit, soc_feature_flowcnt)) { 13113 /* Allocate flowcnt STAT entity hw index. */ 13114 if (f_st->hw_flags & _FP_STAT_FLOWCNT_CNTR) { 13115 return (_field_flowcnt_counter_hw_alloc(unit, f_ent)); 13116 } 13117 } 13118 #endif 13119 13120 /* Allocate statistics entity hw index. */ 13121 if (_FP_INVALID_INDEX == f_st->hw_index) { 13122 rv = _field_counter_hw_alloc(unit, f_ent, f_ent->fs); 13123 BCM_IF_ERROR_RETURN(rv); 13124 } 13125 13126 /* Get stage control information. */ 13127 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 13128 f_ent->fs->stage_id, 13129 &stage_fc 13130 ) 13131 ); 13132 13133 /* Validate STAT pool_index */ 13134 if (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id 13135 && !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) 13136 && !(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) 13137 && (_FP_INVALID_INDEX != f_st->hw_index)) { 13138 if ((!(f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE) 13139 && f_ent->fs->slice_number != f_st->pool_index) 13140 || ((f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE) 13141 && f_ent->fs->slice_number + 1 != f_st->pool_index)) { 13142 LOG_ERROR(BSL_LS_BCM_FP, 13143 (BSL_META_U(unit, 13144 "FP(unit %d) - Counters cannot be shared between slices.\n"), 13145 unit)); 13146 LOG_ERROR(BSL_LS_BCM_FP, 13147 (BSL_META_U(unit, 13148 " Create a new stat and attach to EID=%d.\n"), 13149 f_ent->eid)); 13150 BCM_IF_ERROR_RETURN(_field_slice_counter_free(unit, f_ent, f_st)); 13151 return (BCM_E_CONFIG); 13152 } 13153 } 13154 13155 /* Increment statistics hw reference count. */ 13156 if (0 == (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED)) { 13157 f_ent_st->flags |= _FP_ENTRY_STAT_INSTALLED; 13158 f_st->hw_ref_count++; 13159 if (1 == f_st->hw_ref_count) { 13160 int idx; 13161 13162 /* Write individual statistics privious value. */ 13163 for (idx = 0; idx < f_st->nstat; idx++) { 13164 rv = _field_stat_value_set(unit, f_st, f_st->stat_arr[idx], 13165 f_st->stat_values[idx]); 13166 BCM_IF_ERROR_RETURN(rv); 13167 } 13168 } 13169 } 13170 return (BCM_E_NONE); 13171 } 13172 13173 /* 13174 * Function: 13175 * _bcm_field_stat_hw_alloc 13176 * 13177 * Purpose: 13178 * Allocate counters required for entry installation. 13179 * 13180 * Parameters: 13181 * unit - (IN) BCM device number. 13182 * f_ent - (IN) Field entry array. 13183 * fs - (IN) Slice to allocate a counter. 13184 * Returns: 13185 * BCM_E_XXX 13186 * Notes: 13187 */ 13188 int 13189 _bcm_field_stat_hw_alloc(int unit, _field_entry_t *f_ent) 13190 { 13191 /* Input parameters check. */ 13192 if (NULL == f_ent) { 13193 return (BCM_E_PARAM); 13194 } 13195 13196 return _field_stat_hw_alloc(unit, f_ent); 13197 } 13198 /* 13199 * Function: 13200 * _field_mirror_dest_delete 13201 * Purpose: 13202 * Unset mirroring destination & disable mirroring for rule matching 13203 * packets. 13204 * Parameters: 13205 * unit - (IN) BCM device number 13206 * fa - (IN) Field action descriptor. 13207 * Returns: 13208 * BCM_E_XXX 13209 */ 13210 STATIC int 13211 _field_mirror_dest_delete(int unit, _field_entry_t *f_ent, _field_action_t *fa, uint32 flags) 13212 { 13213 uint32 mirror_flags; /* Mirror module flags. */ 13214 int rv; 13215 uint32 mirror_slot_flags; 13216 13217 /* Input parameters check */ 13218 if ((NULL == fa) || (NULL == f_ent)) { 13219 return (BCM_E_PARAM); 13220 } 13221 13222 /* Set mirror flags. */ 13223 if (bcmFieldActionMirrorIngress == fa->action) { 13224 mirror_flags = BCM_MIRROR_PORT_INGRESS; 13225 } else if (bcmFieldActionMirrorEgress == fa->action) { 13226 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 13227 mirror_flags = BCM_MIRROR_PORT_EGRESS_TRUE; 13228 } else { 13229 /* Stage Ingress */ 13230 mirror_flags = BCM_MIRROR_PORT_EGRESS; 13231 } 13232 } else { 13233 return (BCM_E_PARAM); 13234 } 13235 13236 if ((flags & _FP_ACTION_RESOURCE_FREE) && 13237 (_FP_INVALID_INDEX != fa->hw_index)) { 13238 rv = _bcm_esw_mirror_fp_dest_delete(unit, fa->hw_index, mirror_flags); 13239 BCM_IF_ERROR_RETURN(rv); 13240 fa->hw_index = _FP_INVALID_INDEX; 13241 13242 /* Delete Ref to any mirror slot container if any */ 13243 if (mirror_flags & BCM_MIRROR_PORT_INGRESS) { 13244 mirror_slot_flags = 13245 _BCM_MIRROR_SLOT_INGRESS | _BCM_MIRROR_SLOT_FP; 13246 BCM_IF_ERROR_RETURN 13247 (_bcm_esw_mirror_fp_slot_del_ref(unit, 13248 mirror_slot_flags, 13249 f_ent->ing_mtp_slot_map)); 13250 f_ent->ing_mtp_slot_map = 0; 13251 } 13252 if (mirror_flags & BCM_MIRROR_PORT_EGRESS) { 13253 mirror_slot_flags = 13254 _BCM_MIRROR_SLOT_EGRESS | _BCM_MIRROR_SLOT_FP; 13255 BCM_IF_ERROR_RETURN 13256 (_bcm_esw_mirror_fp_slot_del_ref(unit, 13257 mirror_slot_flags, 13258 f_ent->egr_mtp_slot_map)); 13259 f_ent->egr_mtp_slot_map = 0; 13260 } 13261 } 13262 13263 if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) && 13264 (_FP_INVALID_INDEX != fa->old_index)) { 13265 rv = _bcm_esw_mirror_fp_dest_delete(unit, fa->old_index, mirror_flags); 13266 BCM_IF_ERROR_RETURN(rv); 13267 fa->old_index = _FP_INVALID_INDEX; 13268 13269 /* Delete Referece to Mirror Slot Container if any */ 13270 if (mirror_flags & BCM_MIRROR_PORT_INGRESS) { 13271 mirror_slot_flags = 13272 _BCM_MIRROR_SLOT_INGRESS | _BCM_MIRROR_SLOT_FP; 13273 BCM_IF_ERROR_RETURN 13274 (_bcm_esw_mirror_fp_slot_del_ref(unit, 13275 mirror_slot_flags, 13276 f_ent->ing_mtp_slot_map)); 13277 f_ent->ing_mtp_slot_map = 0; 13278 } 13279 if (mirror_flags & BCM_MIRROR_PORT_EGRESS) { 13280 mirror_slot_flags = 13281 _BCM_MIRROR_SLOT_EGRESS | _BCM_MIRROR_SLOT_FP; 13282 BCM_IF_ERROR_RETURN 13283 (_bcm_esw_mirror_fp_slot_del_ref(unit, 13284 mirror_slot_flags, 13285 f_ent->egr_mtp_slot_map)); 13286 f_ent->egr_mtp_slot_map = 0; 13287 } 13288 } 13289 return (BCM_E_NONE); 13290 } 13291 13292 /* 13293 * Function: 13294 * _field_mirror_dest_add 13295 * Purpose: 13296 * Set mirroring destination & enable mirroring for rule matching 13297 * packets. 13298 * Parameters: 13299 * unit - (IN) BCM device number 13300 * fa - (IN) field action 13301 * Returns: 13302 * BCM_E_XXX 13303 */ 13304 STATIC int 13305 _field_mirror_dest_add (int unit, _field_entry_t *f_ent, _field_action_t *fa) 13306 { 13307 uint32 mirror_flags; /* Mirror module flags. */ 13308 13309 /* Input parameters check. */ 13310 if ((NULL == fa) || (NULL == f_ent)) { 13311 return (BCM_E_PARAM); 13312 } 13313 13314 /* Set mirror flags. */ 13315 if (bcmFieldActionMirrorIngress == fa->action) { 13316 mirror_flags = BCM_MIRROR_PORT_INGRESS; 13317 } else if (bcmFieldActionMirrorEgress == fa->action) { 13318 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 13319 mirror_flags = BCM_MIRROR_PORT_EGRESS_TRUE; 13320 } else { 13321 /* Stage Ingress */ 13322 mirror_flags = BCM_MIRROR_PORT_EGRESS; 13323 } 13324 } else { 13325 return (BCM_E_PARAM); 13326 } 13327 13328 return _bcm_esw_mirror_fp_dest_add(unit, fa->param[0], fa->param[1], 13329 mirror_flags, &fa->hw_index); 13330 } 13331 13332 13333 /* 13334 * Function: 13335 * _field_slice_counter_available 13336 * Purpose: 13337 * Checks if counter might be installed in a slice. 13338 * Parameters: 13339 * unit - (IN) BCM device number. 13340 * f_st - (IN) Field statistics entity. 13341 * fs - (IN) Destination slice. 13342 * Returs: 13343 * BCM_E_XXX 13344 */ 13345 int 13346 _field_slice_counter_available(int unit, _field_stat_t *f_st, _field_slice_t *fs) 13347 { 13348 int idx; /* Counters iteration index. */ 13349 13350 /* Input parameters check. */ 13351 if ((NULL == f_st) || (NULL == fs)) { 13352 return (BCM_E_PARAM); 13353 } 13354 13355 /* Check if target slice has a free counters */ 13356 for (idx = 0; idx < fs->counters_count; idx++) { 13357 if (0x2 == f_st->hw_entry_count) { 13358 if (0 != (idx % 2)) { 13359 /* Skip odd indexes. */ 13360 continue; 13361 } 13362 if ((0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, idx)) && 13363 (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, (idx+ 1)))) { 13364 break; 13365 } 13366 } else if (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, idx)) { 13367 break; 13368 } 13369 } 13370 13371 if (idx == fs->counters_count) { 13372 return (BCM_E_RESOURCE); 13373 } 13374 return (BCM_E_NONE); 13375 } 13376 13377 13378 /* 13379 * Function: 13380 * _field_slice_meter_available 13381 * Purpose: 13382 * Checks if policer might be installed in a slice. 13383 * Parameters: 13384 * unit - (IN) BCM device number. 13385 * f_pl - (IN) Policer descriptor. 13386 * fs - (IN) Destination slice. 13387 * Returs: 13388 * BCM_E_XXX 13389 */ 13390 STATIC int 13391 _field_slice_meter_available(int unit, _field_policer_t *f_pl, _field_slice_t *fs) 13392 { 13393 int idx; /* Meters iteration index. */ 13394 13395 /* Input parameters check. */ 13396 if ((NULL == f_pl) || (NULL == fs)) { 13397 return (BCM_E_PARAM); 13398 } 13399 13400 /* Check if target slice has a free meter */ 13401 for (idx = 0; idx < fs->meters_count; idx++) { 13402 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 13403 if (0 != (idx % 2)) { 13404 /* skip odd */ 13405 continue; 13406 } 13407 13408 if ((0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx)) 13409 && (0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx + 1))) { 13410 break; 13411 } 13412 } 13413 13414 if (_FP_POLICER_IS_FLOW_MODE(f_pl) 13415 && 0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx)) { 13416 break; 13417 } 13418 } 13419 13420 if (idx == fs->meters_count) { 13421 return (BCM_E_RESOURCE); 13422 } 13423 return (BCM_E_NONE); 13424 } 13425 13426 13427 /* 13428 * Function: _field_entry_install_slice_fit 13429 * 13430 * Purpose: Checks if slice has HW resource required for entry installation. 13431 * Parameters: 13432 * unit - (IN) BCM device number. 13433 * stage_fc - (IN) Stage field control. 13434 * f_ent - (IN) Entry to be inserted. 13435 * fs - (IN) Destination slice. 13436 * Returs: 13437 * BCM_E_NONE - Entry fits the slice. 13438 * BCM_E_XXX - Otherwise. 13439 */ 13440 STATIC int 13441 _field_entry_install_slice_fit(int unit, _field_stage_t *stage_fc, 13442 _field_entry_t *f_ent, _field_slice_t *fs) 13443 { 13444 _field_entry_policer_t *f_ent_pl; /* Field entry policers. */ 13445 _field_entry_stat_t *f_ent_st; /* Field entry statistics. */ 13446 _field_stat_t *f_st; /* Field statistics entity. */ 13447 _field_policer_t *f_pl; /* Field policer. */ 13448 _field_group_t *fg; /* Field group structure. */ 13449 uint8 color_dependent;/* Stat is color dependend. */ 13450 int rv; /* Operation return status. */ 13451 13452 /* Input parameters check. */ 13453 if ((NULL == stage_fc) || (NULL == f_ent) || (NULL == fs)) { 13454 return (BCM_E_PARAM); 13455 } 13456 fg = f_ent->group; 13457 13458 /* Reset allocation flags. */ 13459 f_ent->flags &= ~_FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE; 13460 13461 /* If device supports global meter pools or no meter installed -> no issue. */ 13462 f_ent_pl = f_ent->policer; 13463 if ((stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) || 13464 (0 == (f_ent_pl->flags & _FP_POLICER_VALID))) { 13465 f_pl = NULL; 13466 } else { 13467 rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl); 13468 BCM_IF_ERROR_RETURN(rv); 13469 if (_FP_INVALID_INDEX != f_pl->hw_index) { 13470 f_pl = NULL; /* NO allocation required. */ 13471 } 13472 } 13473 13474 /* If device supports global counters or no counter installed -> no issue. */ 13475 f_ent_st = &f_ent->statistic; 13476 if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) { 13477 /* Nothing to do for external FP, because: 13478 - for TR/TR2, each entry has it's own dedicated counter, and 13479 - for TR3, EXTFP supports only flex counters (as does VFP) 13480 */ 13481 f_st = NULL; 13482 } else if ((stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) || 13483 (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) || 13484 (0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID))) { 13485 f_st = NULL; 13486 } else { 13487 rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st); 13488 BCM_IF_ERROR_RETURN(rv); 13489 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 13490 if (soc_feature(unit, soc_feature_advanced_flex_counter)) { 13491 if (f_st->flex_mode != 0) { 13492 return BCM_E_NONE; /* NO allocation required. */ 13493 } 13494 if (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 13495 return BCM_E_NONE; 13496 } 13497 } 13498 #endif 13499 if (_FP_INVALID_INDEX != f_st->hw_index) { 13500 f_st = NULL; /* NO allocation required. */ 13501 } 13502 } 13503 13504 /* Check if counter & meter are available in primary slice. */ 13505 rv = BCM_E_NONE; 13506 /* coverity[new_values : FALSE] */ 13507 if (f_pl != NULL) { 13508 rv = _field_slice_meter_available(unit, f_pl, fs); 13509 } 13510 if ((f_st != NULL) && (BCM_SUCCESS (rv))) { 13511 rv = _field_slice_counter_available(unit, f_st, fs); 13512 } 13513 if (BCM_SUCCESS (rv)) { 13514 return (BCM_E_NONE); 13515 } 13516 13517 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 13518 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 13519 /* No counters -> policer can be allocated from any slice. */ 13520 /* No policers -> counter can be allocated from any slice. */ 13521 if ((f_st == NULL) || (f_pl == NULL)) { 13522 return (BCM_E_NONE); 13523 } 13524 13525 /* 13526 * Only if counter is color blind it might be allocated 13527 * in a slice a different s policer. 13528 */ 13529 13530 /* Check if statistics entity is color dependent. */ 13531 rv = _field_stat_color_dependent(unit, f_st, &color_dependent); 13532 BCM_IF_ERROR_RETURN(rv); 13533 if (FALSE == color_dependent) { 13534 return (BCM_E_NONE); 13535 } 13536 13537 /* Check if counter & meter are available in secondary slice. */ 13538 rv = _field_slice_meter_available(unit, f_pl, fs + 1); 13539 if (BCM_SUCCESS (rv)) { 13540 rv = _field_slice_counter_available(unit, f_st, fs + 1); 13541 } 13542 13543 /* Policer must be allocated from secondary slice */ 13544 if (BCM_SUCCESS (rv)) { 13545 f_ent->flags |= _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE; 13546 return (BCM_E_NONE); 13547 } 13548 } 13549 return (BCM_E_RESOURCE); 13550 } 13551 13552 /* 13553 * Function: _field_entry_move_slice_fit 13554 * 13555 * Purpose: Checks if slice has HW resource required for entry movement. 13556 * Parameters: 13557 * unit - (IN) BCM device number. 13558 * stage_fc - (IN) Stage field control. 13559 * f_ent - (IN) Entry to be inserted. 13560 * fs - (IN) Destination slice. 13561 * freed_counters - (INOUT) Number of counters to be freed by a planned move 13562 * Returs: 13563 * BCM_E_NONE - Entry fits the slice. 13564 * BCM_E_XXX - Otherwise. 13565 */ 13566 STATIC int 13567 _field_entry_move_slice_fit(int unit, _field_stage_t *stage_fc, 13568 _field_entry_t *f_ent, _field_slice_t *fs, int *freed_meters, 13569 int *freed_counters) 13570 { 13571 _field_entry_policer_t *f_ent_pl; /* Field entry policers. */ 13572 _field_entry_stat_t *f_ent_st; /* Field entry statistics. */ 13573 _field_stat_t *f_st; /* Field statistics entity. */ 13574 _field_policer_t *f_pl; /* Field policer. */ 13575 _field_group_t *fg; /* Field group structure. */ 13576 uint8 color_dependent;/* Stat is color dependend. */ 13577 int rv = BCM_E_NONE;/* Operation return status. */ 13578 13579 /* Input parameters check. */ 13580 if ((NULL == stage_fc) || (NULL == f_ent) || (NULL == fs)) { 13581 return (BCM_E_PARAM); 13582 } 13583 13584 fg = f_ent->group; 13585 13586 /* Reset allocation flags. */ 13587 f_ent->flags &= ~_FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE; 13588 13589 /* If device supports global meter pools or no meter installed -> no issue. */ 13590 f_ent_pl = f_ent->policer; 13591 if ((stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) || 13592 (0 == (f_ent_pl->flags & _FP_POLICER_VALID))) { 13593 f_pl = NULL; 13594 } else { 13595 rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl); 13596 BCM_IF_ERROR_RETURN(rv); 13597 13598 /* Reject policers shared by multiple entries. */ 13599 if (2 != f_pl->sw_ref_count) { 13600 return (BCM_E_RESOURCE); 13601 } 13602 } 13603 13604 /* If device supports global counters or no counter installed -> no issue. */ 13605 f_ent_st = &f_ent->statistic; 13606 if ((stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) || 13607 (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) || 13608 (0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID))) { 13609 f_st = NULL; 13610 } else { 13611 rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st); 13612 BCM_IF_ERROR_RETURN(rv); 13613 13614 /* Reject counters shared by multiple entries. */ 13615 if (2 != f_st->sw_ref_count) { 13616 return (BCM_E_RESOURCE); 13617 } 13618 } 13619 13620 /* Check if counter & meter are available in primary slice. */ 13621 13622 rv = BCM_E_NONE; 13623 13624 /* coverity[new_values : FALSE] */ 13625 if (f_pl != NULL && *freed_meters == 0) 13626 { 13627 rv = _field_slice_meter_available(unit, f_pl, fs); 13628 } 13629 13630 if ((f_st != NULL) && (BCM_SUCCESS (rv))) 13631 { 13632 if (f_st->hw_entry_count > *freed_counters) 13633 { 13634 f_st->hw_entry_count -= *freed_counters; 13635 rv = _field_slice_counter_available(unit, f_st, fs); 13636 f_st->hw_entry_count += *freed_counters; 13637 } 13638 } 13639 13640 if (BCM_SUCCESS (rv)) 13641 { 13642 *freed_meters = (f_pl != NULL) ? 1 : 0; 13643 *freed_counters = (f_st != NULL) ? f_st->hw_entry_count : 0; 13644 13645 return (BCM_E_NONE); 13646 } 13647 13648 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 13649 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 13650 /* No counters -> policer can be allocated from any slice. */ 13651 /* No policers -> counter can be allocated from any slice. */ 13652 if ((NULL == f_st) || (NULL == f_pl)) { 13653 return (BCM_E_NONE); 13654 } 13655 13656 /* 13657 * Only if counter is color blind it might be allocated 13658 * in a slice a different s policer. 13659 */ 13660 13661 /* Check if statistics entity is color dependent. */ 13662 rv = _field_stat_color_dependent(unit, f_st, &color_dependent); 13663 BCM_IF_ERROR_RETURN(rv); 13664 if (FALSE == color_dependent) { 13665 return (BCM_E_NONE); 13666 } 13667 13668 /* Check if counter & meter are available in secondary slice. */ 13669 rv = _field_slice_meter_available(unit, f_pl, fs + 1); 13670 if (BCM_SUCCESS (rv)) { 13671 rv = _field_slice_counter_available(unit, f_st, fs + 1); 13672 } 13673 13674 /* Policer must be allocated from secondary slice */ 13675 if (BCM_SUCCESS (rv)) { 13676 f_ent->flags |= _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE; 13677 return (BCM_E_NONE); 13678 } 13679 } 13680 return (BCM_E_RESOURCE); 13681 } 13682 13683 /* 13684 * Function: 13685 * _field_action_hw_resources_free 13686 * Purpose: 13687 * Free hw resources allocated for field action installation. 13688 * Parameters: 13689 * unit - (IN) BCM device number 13690 * f_ent - (IN) Field entry structure. 13691 * fa - (IN) Field action structure. 13692 * Returns: 13693 * BCM_E_XXX 13694 * Notes: 13695 */ 13696 int 13697 _field_action_hw_resources_free(int unit, _field_entry_t *f_ent, 13698 _field_action_t *fa,uint32 flags) 13699 { 13700 int rv; /* Operational Status */ 13701 #if defined(BCM_TOMAHAWK_SUPPORT) 13702 _field_control_t *fc; /* Field Control Structure */ 13703 #endif 13704 #if defined(INCLUDE_L3) 13705 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \ 13706 || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \ 13707 || defined (BCM_ENDURO_SUPPORT) 13708 uint32 flags_action; /* L3 forwarding flags. */ 13709 int nh_ecmp_id; /* Next hop/Ecmp group id. */ 13710 #endif 13711 #endif /* INCLUDE_L3 */ 13712 13713 #if defined(BCM_TRIDENT2_SUPPORT) 13714 soc_mem_t mem; 13715 #endif 13716 13717 #if defined(INCLUDE_L3) 13718 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \ 13719 || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) 13720 flags_action = 0; 13721 nh_ecmp_id = 0; 13722 #endif 13723 #endif 13724 /* Input parameters check. */ 13725 if ((NULL == f_ent) || (NULL == fa)) { 13726 return (BCM_E_PARAM); 13727 } 13728 13729 13730 switch (fa->action) { 13731 case bcmFieldActionMirrorIngress: 13732 case bcmFieldActionMirrorEgress: 13733 return _field_mirror_dest_delete(unit, f_ent, fa,flags); 13734 break; 13735 case bcmFieldActionRedirectMcast: 13736 #if defined(INCLUDE_L3) 13737 case bcmFieldActionRedirectIpmc: 13738 #endif /* INCLUDE_L3 */ 13739 if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){ 13740 break; 13741 } 13742 case bcmFieldActionRedirectPbmp: 13743 case bcmFieldActionEgressMask: 13744 case bcmFieldActionEgressPortsAdd: 13745 /* Applicable to stage ingress on TRX devices only. */ 13746 if ((0 == SOC_IS_TRX(unit)) || 13747 ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) && 13748 (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id))) { 13749 break; 13750 } 13751 #if defined (BCM_TOMAHAWK3_SUPPORT) 13752 if ((fa->action == bcmFieldActionEgressMask) && 13753 (soc_feature(unit, soc_feature_th3_style_fp))) { 13754 BCM_IF_ERROR_RETURN 13755 (_bcm_field_th3_redirect_profile_delete(unit, fa->hw_index)); 13756 } else 13757 #endif 13758 #if defined(BCM_TRX_SUPPORT) 13759 { 13760 BCM_IF_ERROR_RETURN 13761 (_bcm_field_trx_redirect_profile_delete(unit, fa->hw_index)); 13762 } 13763 #endif /* BCM_TRX_SUPPORT */ 13764 break; 13765 #if defined(INCLUDE_L3) 13766 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_TRX_SUPPORT) 13767 case bcmFieldActionSrcMacNew: 13768 case bcmFieldActionDstMacNew: 13769 case bcmFieldActionOuterVlanNew: 13770 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 13771 BCM_IF_ERROR_RETURN(_bcm_field_l2_actions_hw_free(unit, f_ent, 13772 _FP_ACTION_HW_FREE)); 13773 13774 } 13775 break; 13776 #endif /* BCM_TRX_SUPPORT || BCM_FIREBOLT2_SUPPORT */ 13777 13778 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \ 13779 || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \ 13780 || defined (BCM_ENDURO_SUPPORT) 13781 case bcmFieldActionL3ChangeMacDa: 13782 case bcmFieldActionL3ChangeVlan: 13783 if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) 13784 || SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND(unit) || 13785 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 13786 BCM_IF_ERROR_RETURN(_bcm_field_l3_egress_actions_reset(unit, 13787 f_ent, _FP_ACTION_HW_FREE)); 13788 } 13789 break; 13790 case bcmFieldActionL3Switch: 13791 case bcmFieldActionRedirectEgrNextHop: 13792 if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) 13793 || SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND(unit) 13794 || SOC_IS_HURRICANEX(unit) || SOC_IS_ENDURO(unit) 13795 || SOC_IS_GREYHOUND2(unit)) { 13796 BCM_IF_ERROR_RETURN(_bcm_field_policy_set_l3_nh_resolve (unit, 13797 fa->param[0], &flags_action, &nh_ecmp_id)); 13798 13799 BCM_IF_ERROR_RETURN(bcmi_esw_l3_egress_ref_count_update (unit, 13800 fa->param[0], flags_action, nh_ecmp_id,0)); 13801 fa->hw_index = _FP_INVALID_INDEX; 13802 } 13803 break; 13804 #endif /* BCM_KATANA_SUPPORT || BCM_TRIDENT_SUPPORT || BCM_TRIUMPH3_SUPPORT \ 13805 || BCM_GREYHOUND_SUPPORT || BCM_ENDURO_SUPPORT */ 13806 13807 #if defined(BCM_TRIDENT2_SUPPORT) /* BCM_TRIDENT2_SUPPORT */ 13808 case bcmFieldActionNatEgressOverride: 13809 BCM_IF_ERROR_RETURN(_bcm_esw_nat_egress_ref_count_update 13810 (unit, fa->param[0], 0)); 13811 fa->hw_index = _FP_INVALID_INDEX; 13812 break; 13813 #endif /* BCM_TRIDENT2_SUPPORT */ 13814 13815 #endif /* INCLUDE_L3 */ 13816 13817 #if defined(BCM_TRIDENT2_SUPPORT) 13818 case bcmFieldActionHashSelect0: 13819 case bcmFieldActionHashSelect1: 13820 /* Applicable to stage lookup on TRIDENT2 device only. */ 13821 if ((0 == (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) 13822 || soc_feature(unit, soc_feature_field_multi_pipe_support))) 13823 || (_BCM_FIELD_STAGE_LOOKUP != f_ent->group->stage_id)) { 13824 break; 13825 } 13826 mem = ((fa->action == bcmFieldActionHashSelect0)? 13827 VFP_HASH_FIELD_BMAP_TABLE_Am: 13828 VFP_HASH_FIELD_BMAP_TABLE_Bm); 13829 BCM_IF_ERROR_RETURN(_bcm_field_td2_hash_select_profile_delete(unit, 13830 mem, 13831 fa->hw_index)); 13832 break; 13833 #endif /* BCM_TRIDENT2_SUPPORT */ 13834 #if defined(BCM_TOMAHAWK_SUPPORT) 13835 case bcmFieldActionFabricEHAddOrUpdate: 13836 13837 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 13838 if(NULL != fc->functions.fp_eh_mask_profile_hw_free) { 13839 rv = fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, flags); 13840 BCM_IF_ERROR_RETURN(rv); 13841 } 13842 break; 13843 #endif 13844 #if defined(BCM_TRIDENT3_SUPPORT) 13845 case bcmFieldActionVlanActions: 13846 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 13847 if (NULL != fc->functions.fp_vlan_actions_profile_hw_free) { 13848 rv = fc->functions.fp_vlan_actions_profile_hw_free(unit, f_ent, flags); 13849 BCM_IF_ERROR_RETURN(rv); 13850 } 13851 break; 13852 #endif /* BCM_TRIDENT3_SUPPORT */ 13853 #if defined(BCM_FLOWTRACKER_SUPPORT) 13854 case bcmFieldActionFlowtrackerGroupId: 13855 rv = _bcm_field_hx5_ft_group_hw_free(unit, f_ent, flags); 13856 BCM_IF_ERROR_RETURN(rv); 13857 break; 13858 #endif 13859 case bcmFieldActionMatchPbmpRedirect: 13860 case bcmFieldActionMatchPbmpDrop: 13861 if (soc_feature(unit, soc_feature_th3_style_fp)) { 13862 rv = _field_delayed_profile_hw_free(unit, f_ent, flags); 13863 BCM_IF_ERROR_RETURN(rv); 13864 } 13865 break; 13866 default: 13867 break; 13868 } 13869 fa->hw_index = _FP_INVALID_INDEX; 13870 return (BCM_E_NONE); 13871 } 13872 13873 /* 13874 * Function: 13875 * _field_mtp_hw_free 13876 * 13877 * Purpose: 13878 * Free mtp indexes used in field entry 13879 * 13880 * Parameters: 13881 * unit - (IN) BCM device number. 13882 * f_ent - (IN) Field entry descriptor. 13883 * Returns: 13884 * BCM_E_XXX 13885 * Notes: 13886 */ 13887 STATIC int 13888 _field_mtp_hw_free (int unit, _field_entry_t *f_ent, uint32 flags) 13889 { 13890 _field_action_t *fa; /* Field action descriptor. */ 13891 int rv; /* Operation return status. */ 13892 13893 /* Extract action info from the entry structure. */ 13894 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 13895 /* Allocate mtp destination only for mirroring actions */ 13896 if ((bcmFieldActionMirrorIngress != fa->action) && 13897 (bcmFieldActionMirrorEgress != fa->action)) { 13898 continue; 13899 } 13900 13901 if ((_FP_INVALID_INDEX == fa->hw_index) && (_FP_INVALID_INDEX == fa->old_index) ) { 13902 continue; 13903 } 13904 13905 rv = _field_action_hw_resources_free(unit, f_ent, fa,flags); 13906 BCM_IF_ERROR_RETURN(rv); 13907 } 13908 13909 return (BCM_E_NONE); 13910 } 13911 13912 13913 /* 13914 * Function: 13915 * _field_invalid_actions_remove 13916 * Purpose: 13917 * Remove deleted actions from entry actions 13918 * linked list. 13919 * Parameters: 13920 * unit - (IN) BCM device number 13921 * f_ent - (IN) Field entry structure. 13922 * Returns: 13923 * BCM_E_XXX 13924 * Notes: 13925 */ 13926 int 13927 _field_invalid_actions_remove(int unit, _field_entry_t *f_ent) 13928 { 13929 _field_action_t *fa; 13930 _field_action_t *fa_prev = NULL; 13931 _field_action_t *fa_next = NULL; 13932 _field_action_t *fa_iter; /* Field entry actions iterator.*/ 13933 int rv; 13934 #if defined(BCM_TRIDENT_SUPPORT) 13935 uint8 idx; /* Entry array action dest index. */ 13936 uint32 entry_flags; /* Entry flags */ 13937 #endif 13938 #ifdef BCM_KATANA_SUPPORT 13939 uint32 param0 = 0, param1 = 0, in_flags = 0; 13940 int queue_id = 0; 13941 ing_queue_map_entry_t ing_queue_entry; 13942 int referenceCount = 0; 13943 #endif 13944 13945 /* Input parameters check. */ 13946 if (NULL == f_ent) { 13947 return (BCM_E_PARAM); 13948 } 13949 13950 /* Find the action in the entry */ 13951 fa = f_ent->actions; /* start at head */ 13952 while (fa != NULL) { 13953 fa_next = fa->next; 13954 if (fa->flags & _FP_ACTION_VALID) { 13955 fa_prev = fa; 13956 fa = fa_next; 13957 continue; 13958 } 13959 #if defined (BCM_TRIUMPH3_SUPPORT) 13960 if ( SOC_IS_TRIUMPH3(unit) && (_FP_INVALID_INDEX != fa->hw_index) && 13961 ((fa->action == bcmFieldActionReplaceSrcMac) || 13962 (fa->action == bcmFieldActionReplaceDstMac) || 13963 (fa->action == bcmFieldActionReplaceInnerVlan) || 13964 (fa->action == bcmFieldActionReplaceOuterVlan) || 13965 (fa->action == bcmFieldActionReplaceInnerVlanPriority) || 13966 (fa->action == bcmFieldActionReplaceOuterVlanPriority) )) { 13967 rv = _bcm__field_tr3_action_replaceL2Fields_remove_HWEntries(unit, f_ent, fa); 13968 BCM_IF_ERROR_RETURN(rv); 13969 } 13970 #endif 13971 13972 if (_FP_INVALID_INDEX != fa->hw_index) { 13973 /* 13974 * Check if a valid instance of this action exists in 13975 * the entry actions linked list. 13976 * If TRUE, hardware index must be freed only 13977 * after updating policy table with new information. 13978 */ 13979 if ((bcmFieldActionEgressMask == fa->action) 13980 || (bcmFieldActionRedirectBcastPbmp == fa->action) 13981 || (bcmFieldActionRedirectPbmp == fa->action) 13982 || (bcmFieldActionEgressPortsAdd == fa->action) 13983 || (bcmFieldActionRedirectMcast == fa->action) 13984 || (bcmFieldActionRedirectIpmc == fa->action) 13985 || (bcmFieldActionMirrorIngress == fa->action) 13986 || (bcmFieldActionMirrorEgress == fa->action) 13987 || (bcmFieldActionHashSelect0 == fa->action) 13988 || (bcmFieldActionHashSelect1 == fa->action) 13989 || (bcmFieldActionFabricEHAddOrUpdate == fa->action)) { 13990 13991 if(_FP_ACTION_MODIFY & fa->flags) { 13992 13993 13994 fa->flags &= ~_FP_ACTION_MODIFY; 13995 13996 fa_iter = f_ent->actions; 13997 13998 while (fa_iter != NULL) { 13999 if ((1 == (fa_iter->flags & _FP_ACTION_VALID)) 14000 && (fa_iter->action == fa->action) 14001 && (_FP_INVALID_INDEX == fa_iter->hw_index)) { 14002 /* Do not free here. Release the hardware 14003 * index after policy install operation. 14004 */ 14005 fa_iter->hw_index = fa->hw_index; 14006 fa_iter->flags |= _FP_ACTION_MODIFY; 14007 fa->hw_index = _FP_INVALID_INDEX; 14008 break; 14009 } 14010 fa_iter = fa_iter->next; 14011 } 14012 14013 /* Here _FP_ACTION_MODIFY flag cleared means , no duplicate 14014 actions are found i.e an action is removed from the entry. 14015 Those invalid but not modified entries will be removed in 14016 the second pass to this function,so just return BCM_E_NONE 14017 on first pass */ 14018 if(!(_FP_ACTION_MODIFY & fa->flags)) { 14019 fa_prev = fa; 14020 fa = fa_next; 14021 continue; 14022 } 14023 } 14024 } 14025 14026 14027 /* 14028 * Action not set for this entry, free the hardware index. 14029 */ 14030 if (_FP_INVALID_INDEX != fa->hw_index) { 14031 rv = _field_action_hw_resources_free(unit, f_ent, fa, 14032 _FP_ACTION_RESOURCE_FREE); 14033 BCM_IF_ERROR_RETURN(rv); 14034 } 14035 } 14036 14037 if (fa_prev != NULL) { 14038 fa_prev->next = fa->next; 14039 } else { /* matched head of list */ 14040 f_ent->actions = fa_next; 14041 } 14042 #if defined(BCM_KATANA_SUPPORT) 14043 if (SOC_IS_KATANAX(unit)) { 14044 if (fa != NULL) { 14045 if ((fa->action == bcmFieldActionFabricQueue) && 14046 (f_ent->fs->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 14047 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 14048 param0 = fa->param[0]; 14049 param1 = fa->param[1]; 14050 /* For Katana if param1 BCM_FABRIC_QUEUE_xxx 14051 * flags are set then param0 is 14052 * ucast/ucast_subscriber group cosq gport */ 14053 if ((param1 & BCM_FABRIC_QUEUE_DEST_OFFSET) || 14054 (param1 & BCM_FABRIC_QUEUE_CUSTOMER)) { 14055 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(param0) || 14056 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(param0) || 14057 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(param0)) { 14058 #if defined(BCM_KATANA2_SUPPORT) 14059 if (SOC_IS_KATANA2(unit)) { 14060 queue_id = -1; 14061 rv = _bcm_kt2_cosq_index_resolve( 14062 unit, param0, 0, 14063 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 14064 NULL, &queue_id, NULL); 14065 if (BCM_FAILURE(rv) && 14066 (rv != BCM_E_NOT_FOUND)) { 14067 return rv; 14068 } 14069 } else 14070 #endif 14071 { 14072 if (SOC_IS_KATANA(unit)) { 14073 BCM_IF_ERROR_RETURN(_bcm_kt_cosq_index_resolve( 14074 unit, param0, 0, 14075 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 14076 NULL, &queue_id, NULL)); 14077 } 14078 } 14079 } else { 14080 queue_id = param0 & 0xffff; 14081 } 14082 in_flags = param1; 14083 } else { 14084 queue_id = param0 & 0xffff; 14085 in_flags = param0; 14086 } 14087 14088 if (in_flags & BCM_FABRIC_QUEUE_DEST_OFFSET) { 14089 if (queue_id != -1) { 14090 BCM_IF_ERROR_RETURN( 14091 _bcm_field_fabricQueue_action_node_delete (unit, 14092 queue_id, param1, &referenceCount)); 14093 if(referenceCount == 0) { 14094 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, 14095 ING_QUEUE_MAPm, 14096 queue_id, &ing_queue_entry)); 14097 } 14098 } 14099 } 14100 } 14101 } 14102 } 14103 #endif 14104 /* okay to free action */ 14105 if (NULL != (fa->egress_pbmp)) { 14106 sal_free(fa->egress_pbmp); 14107 } 14108 sal_free(fa); 14109 fa = fa_next; 14110 } 14111 14112 #if defined(BCM_TRIDENT_SUPPORT) 14113 if (SOC_IS_TD_TT (unit) && 14114 !(soc_feature(unit, soc_feature_field_multi_pipe_support))) { 14115 if ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 14116 (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) || 14117 (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 14118 14119 if (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 14120 entry_flags = (_FP_ENTRY_PRIMARY | _FP_ENTRY_SECOND_HALF); 14121 } else { 14122 entry_flags = _FP_ENTRY_SECONDARY; 14123 } 14124 14125 rv = _bcm_field_entry_flags_to_tcam_part(unit, entry_flags, 14126 f_ent->group, 14127 &idx); 14128 14129 BCM_IF_ERROR_RETURN(rv); 14130 /* Find the action in the entry */ 14131 fa = f_ent[idx].actions; /* start at head */ 14132 fa_prev = NULL; 14133 fa_next = NULL; 14134 while (fa != NULL) { 14135 fa_next = fa->next; 14136 if (fa->flags & _FP_ACTION_VALID) { 14137 fa_prev = fa; 14138 fa = fa_next; 14139 continue; 14140 } 14141 if (fa_prev != NULL) { 14142 fa_prev->next = fa->next; 14143 } else { /* matched head of list */ 14144 f_ent[idx].actions = fa_next; 14145 } 14146 14147 /* okay to free action */ 14148 if (NULL != (fa->egress_pbmp)) { 14149 sal_free(fa->egress_pbmp); 14150 } 14151 sal_free(fa); 14152 fa = fa_next; 14153 } 14154 } 14155 } 14156 #endif 14157 14158 /* Remove Invalid Oam Actions */ 14159 #if defined BCM_TRIDENT2PLUS_SUPPORT 14160 if (soc_feature(unit, soc_feature_fp_based_oam)) { 14161 rv = _bcm_field_oam_stat_invalid_actions_remove (unit, f_ent); 14162 BCM_IF_ERROR_RETURN(rv); 14163 } 14164 #endif 14165 14166 return (BCM_E_NONE); 14167 } 14168 14169 /* 14170 * Function: 14171 * _field_mtp_hw_alloc 14172 * 14173 * Purpose: 14174 * Allocate mtp indexes required for entry installation. 14175 * 14176 * Parameters: 14177 * unit - (IN) BCM device number. 14178 * f_ent - (IN) Field entry descriptor. 14179 * Returns: 14180 * BCM_E_XXX 14181 * Notes: 14182 */ 14183 STATIC int 14184 _field_mtp_hw_alloc (int unit, _field_entry_t *f_ent) 14185 { 14186 _field_action_t *fa; /* Field action descriptor. */ 14187 int rv; /* Operation return status. */ 14188 int mirror_flags = 0; 14189 14190 /* Extract action info from the entry structure. */ 14191 for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) { 14192 /* Allocate mtp destination only for mirroring actions */ 14193 if ((bcmFieldActionMirrorIngress != fa->action) && 14194 (bcmFieldActionMirrorEgress != fa->action)) { 14195 continue; 14196 } 14197 if(_FP_ACTION_MODIFY & fa->flags) { 14198 fa->old_index = fa->hw_index; 14199 fa->hw_index = _FP_INVALID_INDEX; 14200 } 14201 if (_FP_INVALID_INDEX == fa->hw_index) { 14202 /* Allocate mirror destination. */ 14203 if(BCM_E_RESOURCE == (rv = _field_mirror_dest_add(unit, f_ent, fa))) { 14204 if(_FP_ACTION_MODIFY & fa->flags) { 14205 fa->hw_index = fa->old_index; 14206 fa->old_index = _FP_INVALID_INDEX; 14207 } 14208 for (fa = f_ent->actions; 14209 ((fa != NULL) && 14210 (_FP_ACTION_VALID & fa->flags)); fa = fa->next) { 14211 if ((bcmFieldActionMirrorIngress != fa->action) 14212 && (bcmFieldActionMirrorEgress != fa->action)) { 14213 continue; 14214 } 14215 if (fa->flags & _FP_ACTION_DIRTY) { 14216 /* Free the alloted resources */ 14217 _field_mirror_dest_delete(unit, f_ent, fa, 14218 _FP_ACTION_RESOURCE_FREE); 14219 } 14220 } 14221 } 14222 BCM_IF_ERROR_RETURN(rv); 14223 } else { 14224 if (bcmFieldActionMirrorIngress == fa->action) { 14225 mirror_flags = 14226 _BCM_MIRROR_SLOT_INGRESS | _BCM_MIRROR_SLOT_FP; 14227 BCM_IF_ERROR_RETURN 14228 (_bcm_esw_mirror_fp_slot_del_ref(unit, 14229 mirror_flags, 14230 f_ent->ing_mtp_slot_map)); 14231 f_ent->ing_mtp_slot_map = 0; 14232 } 14233 if (bcmFieldActionMirrorEgress == fa->action) { 14234 if (_BCM_FIELD_STAGE_EGRESS != f_ent->group->stage_id) { 14235 mirror_flags = 14236 _BCM_MIRROR_SLOT_EGRESS | _BCM_MIRROR_SLOT_FP; 14237 BCM_IF_ERROR_RETURN 14238 (_bcm_esw_mirror_fp_slot_del_ref(unit, 14239 mirror_flags, 14240 f_ent->egr_mtp_slot_map)); 14241 f_ent->egr_mtp_slot_map = 0; 14242 } 14243 } 14244 } 14245 } 14246 return (BCM_E_NONE); 14247 } 14248 14249 /* 14250 * Function: 14251 * _field_redirect_profile_hw_free 14252 * 14253 * Purpose: 14254 * Free redirect profile indexes required for entry installation. 14255 * 14256 * Parameters: 14257 * unit - (IN) BCM device number. 14258 * f_ent - (IN) Field entry descriptor. 14259 * flags - (IN) Free flags (old/new/both). 14260 * Returns: 14261 * BCM_E_XXX 14262 * Notes: 14263 */ 14264 STATIC int 14265 _field_redirect_profile_hw_free(int unit, _field_entry_t *f_ent, uint32 flags) 14266 { 14267 _field_action_t *fa; /* Field action descriptor. */ 14268 int rv = BCM_E_NONE; /* Operation return status. */ 14269 14270 /* Applicable to stage ingress on TRX devices only. */ 14271 if ((0 == SOC_IS_TRX(unit)) || 14272 ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) && 14273 (_BCM_FIELD_STAGE_EXTERNAL != f_ent->group->stage_id) && 14274 (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id))) { 14275 if (!SOC_IS_GREYHOUND2(unit)) { 14276 return (BCM_E_NONE); 14277 } 14278 } 14279 14280 /* Extract the policy info from the entry structure. */ 14281 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 14282 switch (fa->action) { 14283 case bcmFieldActionRedirectMcast: 14284 #if defined(INCLUDE_L3) 14285 case bcmFieldActionRedirectIpmc: 14286 #endif /* INCLUDE_L3 */ 14287 if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){ 14288 break; 14289 } 14290 case bcmFieldActionRedirectPbmp: 14291 case bcmFieldActionRedirectBcastPbmp: 14292 case bcmFieldActionEgressMask: 14293 case bcmFieldActionEgressPortsAdd: 14294 #if defined (BCM_TOMAHAWK3_SUPPORT) 14295 if ((fa->action == bcmFieldActionEgressMask) && 14296 (soc_feature(unit, soc_feature_th3_style_fp))) { 14297 if ((flags & _FP_ACTION_RESOURCE_FREE) && 14298 (_FP_INVALID_INDEX != fa->hw_index)) { 14299 rv = _bcm_field_th3_redirect_profile_delete(unit, 14300 fa->hw_index); 14301 BCM_IF_ERROR_RETURN(rv); 14302 fa->hw_index = _FP_INVALID_INDEX; 14303 } 14304 14305 if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) && 14306 (_FP_INVALID_INDEX != fa->old_index)) { 14307 rv = _bcm_field_th3_redirect_profile_delete(unit, 14308 fa->old_index); 14309 BCM_IF_ERROR_RETURN(rv); 14310 fa->old_index = _FP_INVALID_INDEX; 14311 } 14312 } else 14313 #endif 14314 #if defined(BCM_TRX_SUPPORT) 14315 { 14316 if ((flags & _FP_ACTION_RESOURCE_FREE) && 14317 (_FP_INVALID_INDEX != fa->hw_index)) { 14318 rv = _bcm_field_trx_redirect_profile_delete(unit, 14319 fa->hw_index); 14320 BCM_IF_ERROR_RETURN(rv); 14321 fa->hw_index = _FP_INVALID_INDEX; 14322 } 14323 14324 if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) && 14325 (_FP_INVALID_INDEX != fa->old_index)) { 14326 rv = _bcm_field_trx_redirect_profile_delete(unit, 14327 fa->old_index); 14328 BCM_IF_ERROR_RETURN(rv); 14329 fa->old_index = _FP_INVALID_INDEX; 14330 } 14331 } 14332 break; 14333 #endif /* BCM_TRX_SUPPORT */ 14334 #if defined(BCM_TSN_SUPPORT) 14335 case bcmFieldActionMtuProfileIdNew: 14336 if (soc_feature(unit, soc_feature_tsn_mtu_stu) && 14337 (flags & (_FP_ACTION_RESOURCE_FREE | _FP_ACTION_OLD_RESOURCE_FREE))) { 14338 (void)bcmi_esw_tsn_mtu_profile_ref_dec(unit, fa->param[0]); 14339 } 14340 break; 14341 case bcmFieldActionStuProfileIdNew: 14342 if (soc_feature(unit, soc_feature_tsn_mtu_stu) && 14343 (flags & (_FP_ACTION_RESOURCE_FREE | _FP_ACTION_OLD_RESOURCE_FREE))) { 14344 (void)bcmi_esw_tsn_stu_profile_ref_dec(unit, fa->param[0]); 14345 } 14346 break; 14347 #endif /*BCM_TSN_SUPPORT*/ 14348 default: 14349 break; 14350 } 14351 } 14352 return (rv); 14353 } 14354 14355 14356 /* 14357 * Function: 14358 * _field_redirect_profile_hw_alloc 14359 * 14360 * Purpose: 14361 * Allocate redirect profile index required for entry installation. 14362 * 14363 * Parameters: 14364 * unit - (IN) BCM device number. 14365 * f_ent - (IN) Field entry descriptor. 14366 * Returns: 14367 * BCM_E_XXX 14368 * Notes: 14369 */ 14370 STATIC int 14371 _field_redirect_profile_hw_alloc (int unit, _field_entry_t *f_ent) 14372 { 14373 int rv = BCM_E_NONE; /* Operation return status. */ 14374 #if defined (BCM_TRX_SUPPORT) 14375 _field_action_t *fa; /* Field action descriptor. */ 14376 14377 int ref_count; /* Profile use reference count. */ 14378 14379 /* Applicable to stage ingress on TRX devices only. */ 14380 if ((0 == SOC_IS_TRX(unit)) || 14381 ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) && 14382 (_BCM_FIELD_STAGE_EXTERNAL != f_ent->group->stage_id) && 14383 (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id))) { 14384 if (!SOC_IS_GREYHOUND2(unit)) { 14385 return (BCM_E_NONE); 14386 } 14387 } 14388 14389 /* Extract the policy info from the entry structure. */ 14390 for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) { 14391 switch (fa->action) { 14392 case bcmFieldActionRedirectMcast: 14393 #if defined(INCLUDE_L3) 14394 case bcmFieldActionRedirectIpmc: 14395 #endif /* INCLUDE_L3 */ 14396 if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){ 14397 break; 14398 } 14399 case bcmFieldActionRedirectPbmp: 14400 case bcmFieldActionRedirectBcastPbmp: 14401 case bcmFieldActionEgressMask: 14402 case bcmFieldActionEgressPortsAdd: 14403 /* 14404 * Store previous hardware index value in old_index. 14405 */ 14406 fa->old_index = fa->hw_index; 14407 14408 #if defined (BCM_TOMAHAWK3_SUPPORT) 14409 if ((fa->action == bcmFieldActionEgressMask) && 14410 (soc_feature(unit, soc_feature_th3_style_fp))) { 14411 rv = _bcm_field_trx_redirect_profile_alloc(unit, f_ent, fa); 14412 if ((BCM_E_RESOURCE == rv) && 14413 (_FP_INVALID_INDEX != fa->old_index)) { 14414 /* Destroy old profile ONLY 14415 * if it is not used by other entries. 14416 */ 14417 rv = _bcm_field_th3_redirect_profile_ref_count_get(unit, 14418 fa->old_index, 14419 &ref_count); 14420 BCM_IF_ERROR_RETURN(rv); 14421 if (ref_count > 1) { 14422 return (BCM_E_RESOURCE); 14423 } 14424 rv = _bcm_field_th3_redirect_profile_delete(unit, fa->old_index); 14425 BCM_IF_ERROR_RETURN(rv); 14426 14427 /* Destroy old profile is no longer required. */ 14428 fa->old_index = _FP_INVALID_INDEX; 14429 14430 /* Reallocate profile for new action. */ 14431 rv = _bcm_field_trx_redirect_profile_alloc(unit, f_ent, fa); 14432 } 14433 14434 } else 14435 #endif 14436 { 14437 rv = _bcm_field_trx_redirect_profile_alloc(unit, f_ent, fa); 14438 if ((BCM_E_RESOURCE == rv) && 14439 (_FP_INVALID_INDEX != fa->old_index)) { 14440 /* Destroy old profile ONLY 14441 * if it is not used by other entries. 14442 */ 14443 rv = _bcm_field_trx_redirect_profile_ref_count_get(unit, 14444 fa->old_index, 14445 &ref_count); 14446 BCM_IF_ERROR_RETURN(rv); 14447 if (ref_count > 1) { 14448 return (BCM_E_RESOURCE); 14449 } 14450 rv = _bcm_field_trx_redirect_profile_delete(unit, fa->old_index); 14451 BCM_IF_ERROR_RETURN(rv); 14452 14453 /* Destroy old profile is no longer required. */ 14454 fa->old_index = _FP_INVALID_INDEX; 14455 14456 /* Reallocate profile for new action. */ 14457 rv = _bcm_field_trx_redirect_profile_alloc(unit, f_ent, fa); 14458 } 14459 } 14460 break; 14461 #if defined(BCM_TSN_SUPPORT) 14462 case bcmFieldActionMtuProfileIdNew: 14463 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 14464 /* To prevent ref cnt inc from field entry re-install*/ 14465 if (fa->hw_index == _FP_INVALID_INDEX) { 14466 (void)bcmi_esw_tsn_mtu_profile_ref_inc(unit, 14467 fa->param[0]); 14468 fa->hw_index = 0; 14469 } 14470 } else { 14471 return BCM_E_UNAVAIL; 14472 } 14473 break; 14474 case bcmFieldActionStuProfileIdNew: 14475 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 14476 /* To prevent ref cnt inc from field entry re-install*/ 14477 if (fa->hw_index == _FP_INVALID_INDEX) { 14478 (void)bcmi_esw_tsn_stu_profile_ref_inc(unit, 14479 fa->param[0]); 14480 fa->hw_index = 0; 14481 } 14482 } else { 14483 return BCM_E_UNAVAIL; 14484 } 14485 break; 14486 #endif/* BCM_TSN_SUPPORT */ 14487 default: 14488 break; 14489 } 14490 if (BCM_FAILURE(rv)) { 14491 _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 14492 break; 14493 } 14494 } 14495 #endif /* BCM_TRX_SUPPORT */ 14496 return (rv); 14497 } 14498 14499 /* 14500 * Function: 14501 * _field_port_filter_enable_set 14502 * 14503 * Purpose: 14504 * Set the filter enable state in the Port Tables. 14505 * 14506 * Parameters: 14507 * unit - (IN)BCM device number. 14508 * fc - (IN)Field control structure. 14509 * state - (IN) TRUE = to enable 14510 * FALSE = disable filtering. 14511 * 14512 * Returns: 14513 * BCM_E_NONE - Success 14514 * BCM_E_XXX - From table read/write 14515 */ 14516 int 14517 _field_port_filter_enable_set(int unit, _field_control_t *fc, uint32 state) 14518 { 14519 int port; /* Port iterator. */ 14520 int ret_val = BCM_E_NONE; /* Operation return value. */ 14521 bcm_port_config_t port_config;/* Device port config structure.*/ 14522 bcm_pbmp_t port_pbmp, all_pbmp; 14523 14524 /* Input parameters check. */ 14525 if (NULL == fc || ((state != TRUE) && (state != FALSE))) { 14526 return (BCM_E_PARAM); 14527 } 14528 14529 state = (state) ? 1 : 0; 14530 14531 /* Read device port configuration. */ 14532 BCM_IF_ERROR_RETURN(bcm_esw_port_config_get(unit, &port_config)); 14533 BCM_PBMP_CLEAR(port_pbmp); 14534 BCM_PBMP_CLEAR(all_pbmp); 14535 BCM_PBMP_ASSIGN(port_pbmp, port_config.port); 14536 BCM_PBMP_ASSIGN(all_pbmp, port_config.all); 14537 #ifdef BCM_KATANA2_SUPPORT 14538 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 14539 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &port_pbmp)); 14540 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 14541 } 14542 if (soc_feature(unit, soc_feature_linkphy_coe) || 14543 soc_feature(unit, soc_feature_subtag_coe)) { 14544 _bcm_kt2_subport_pbmp_update(unit, &port_pbmp); 14545 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 14546 } 14547 #endif 14548 14549 #if defined(BCM_SABER2_SUPPORT) 14550 if(SOC_IS_SABER2(unit)){ 14551 int oamp_enable; 14552 (void)bcm_sb2_sat_oamp_enable_get(unit, &oamp_enable); 14553 /* Skip OAMP port for saber2 device */ 14554 if(oamp_enable) { 14555 SOC_PBMP_PORT_REMOVE(port_pbmp, 14556 _BCM_SB2_SAT_OAMP_PHY_PORT_NUMBER); 14557 SOC_PBMP_PORT_REMOVE(all_pbmp, 14558 _BCM_SB2_SAT_OAMP_PHY_PORT_NUMBER); 14559 } 14560 } 14561 #endif 14562 14563 FP_LOCK(unit); 14564 14565 /* Iterate over all the ports but CPU set Lookup filtering. */ 14566 BCM_PBMP_ITER(port_pbmp, port) { 14567 /* Set field enable to the hw. */ 14568 ret_val = bcm_esw_port_control_set(unit, port, 14569 bcmPortControlFilterLookup, state); 14570 14571 if (BCM_E_UNAVAIL == ret_val) { 14572 /* Device doesn't support lookup filtering. */ 14573 break; 14574 } 14575 14576 if (BCM_FAILURE(ret_val)) { 14577 FP_UNLOCK(unit); 14578 return (ret_val); 14579 } 14580 } 14581 14582 /* Iterate over all the ports but CPU set ingress filtering. */ 14583 BCM_PBMP_ITER(port_pbmp, port) { 14584 /* Set field enable to the hw. */ 14585 ret_val = bcm_esw_port_control_set(unit, port, 14586 bcmPortControlFilterIngress, state); 14587 if (BCM_FAILURE(ret_val)) { 14588 FP_UNLOCK(unit); 14589 return (ret_val); 14590 } 14591 } 14592 14593 /* Iterate over all the ports set egress filtering. */ 14594 BCM_PBMP_ITER(all_pbmp, port) { 14595 /* Set field enable to the hw. */ 14596 ret_val = bcm_esw_port_control_set(unit, port, 14597 bcmPortControlFilterEgress, state); 14598 14599 if (BCM_E_UNAVAIL == ret_val) { 14600 /* Device doesn't support egress filtering. */ 14601 break; 14602 } 14603 14604 if (BCM_FAILURE(ret_val)) { 14605 FP_UNLOCK(unit); 14606 return (ret_val); 14607 } 14608 } 14609 FP_UNLOCK(unit); 14610 return (BCM_E_NONE); 14611 } 14612 14613 /* 14614 * Function: _field_qualifier_gport_resolve 14615 * 14616 * Purpose: 14617 * Resolves gport as parameter of qualifier. 14618 * 14619 * Parameters: 14620 * unit - (IN) BCM device number 14621 * gport - (IN) GPORT to resolve 14622 * mask - (IN) qualifier mask, in case of gport must be -1 14623 * out_p - (OUT) port encoded into gport. 14624 * out_m - (OUT) module encoded into gport. 14625 * out_t - (OUT) trunk encoded into gport. 14626 * 14627 * Returns: 14628 * BCM_E_NONE - No errors. 14629 * BCM_E_XXX - Otherwise. 14630 */ 14631 14632 int 14633 _field_qualifier_gport_resolve(int unit, bcm_gport_t gport, int mask, 14634 int *out_p, int *out_m, int *out_t) 14635 { 14636 bcm_port_t port; 14637 bcm_module_t modid; 14638 bcm_trunk_t tgid = BCM_TRUNK_INVALID; 14639 int id; 14640 14641 /* In case of gport mask must be exact match */ 14642 if (BCM_FIELD_EXACT_MATCH_MASK != mask) { 14643 return BCM_E_PARAM; 14644 } 14645 14646 BCM_IF_ERROR_RETURN( 14647 _bcm_esw_gport_resolve(unit, gport, &modid, &port, &tgid, &id)); 14648 14649 #if defined(BCM_HGPROXY_COE_SUPPORT) 14650 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 14651 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 14652 /* For this case gport_resolve returns non-negative id */ 14653 } else 14654 #endif 14655 #if defined(BCM_KATANA2_SUPPORT) 14656 if (BCM_GPORT_IS_SET(gport) && 14657 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, gport)) { 14658 /* For this case gport_resolve returns non-negative id */ 14659 } else 14660 #endif 14661 { 14662 if (-1 != id) { 14663 return BCM_E_PORT; 14664 } 14665 } 14666 14667 if (BCM_TRUNK_INVALID != tgid && NULL == out_t) { 14668 return BCM_E_PORT; 14669 } 14670 if (NULL != out_t) { 14671 *out_t = tgid; 14672 } 14673 if (NULL != out_m) { 14674 *out_m = modid; 14675 } 14676 if (NULL != out_p) { 14677 *out_p = port; 14678 } 14679 14680 return (BCM_E_NONE); 14681 } 14682 14683 /* 14684 * Function: _field_params_hw_to_api_adapt 14685 * 14686 * Purpose: 14687 * Adapts action parameters from HW to API space. 14688 * 14689 * Parameters: 14690 * unit - (IN) BCM device number 14691 * action - (IN)Action to adapt parameters for (bcmFieldActionXXX) 14692 * param0 - (IN/OUT)Action parameter 14693 * param1 - (IN/OUT)Action parameter 14694 * 14695 * Returns: 14696 * BCM_E_NONE - No errors. 14697 * BCM_E_XXX - Otherwise. 14698 */ 14699 14700 int 14701 _field_params_hw_to_api_adapt(int unit, bcm_field_action_t action, 14702 uint32 *param0, uint32 *param1) 14703 { 14704 int isGport; 14705 _bcm_gport_dest_t dest; 14706 14707 _bcm_gport_dest_t_init(&dest); 14708 BCM_IF_ERROR_RETURN( 14709 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 14710 14711 switch (action) { 14712 case bcmFieldActionRedirect: 14713 if (isGport) { 14714 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 14715 dest.modid = *param0; 14716 dest.port = *param1; 14717 BCM_IF_ERROR_RETURN( 14718 _bcm_esw_gport_construct(unit, &dest, (bcm_gport_t*)param1)); 14719 *param0 = -1; /* If gport requested param0 should be ignored */ 14720 } 14721 break; 14722 case bcmFieldActionRedirectTrunk: 14723 if (isGport) { 14724 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 14725 dest.tgid = *param0; 14726 BCM_IF_ERROR_RETURN( 14727 _bcm_esw_gport_construct(unit, &dest, (bcm_gport_t*)param0)); 14728 *param1 = -1; /* If gport requested param1 should be ignored */ 14729 } 14730 break; 14731 default: 14732 break; 14733 } 14734 return (BCM_E_NONE); 14735 } 14736 14737 /* 14738 * Function: _field_params_api_to_hw_adapt 14739 * 14740 * Purpose: 14741 * Adapts action parameters from API to HW space. 14742 * 14743 * Parameters: 14744 * unit - (IN) BCM device number 14745 * action - (IN)Action to adapt parameters for (bcmFieldActionXXX) 14746 * param0 - (IN/OUT)Action parameter 14747 * param1 - (IN/OUT)Action parameter 14748 * 14749 * Returns: 14750 * BCM_E_NONE - No errors. 14751 * BCM_E_XXX - Otherwise. 14752 */ 14753 14754 int 14755 _field_params_api_to_hw_adapt(int unit, bcm_field_action_t action, 14756 uint32 *param0, uint32 *param1) 14757 { 14758 bcm_module_t l_modid; 14759 bcm_trunk_t l_tgid; 14760 bcm_port_t l_port; 14761 int id; 14762 14763 14764 switch (action) { 14765 case bcmFieldActionRedirect: 14766 if (BCM_GPORT_IS_SET(*param1)) { 14767 BCM_IF_ERROR_RETURN( 14768 _bcm_esw_gport_resolve(unit, *param1, &l_modid, &l_port, &l_tgid, &id)); 14769 14770 #if defined(BCM_HGPROXY_COE_SUPPORT) 14771 /* modify param0 and param1 for 14772 * SubportPktTag subport gport. 14773 * For this case gport_resolve function returns 14774 * non-negative id */ 14775 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 14776 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, *param1)) { 14777 if (BCM_TRUNK_INVALID != l_tgid) { 14778 return BCM_E_PARAM; 14779 } 14780 *param1 = l_port; 14781 *param0 = l_modid; 14782 } else 14783 #endif 14784 14785 #if defined(BCM_KATANA2_SUPPORT) 14786 /* modify param0 and param1 for 14787 * LinkPHy/SubportPktTag subport gport. 14788 * For this case gport_resolve function returns 14789 * non-negative id */ 14790 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 14791 *param1)) { 14792 if (BCM_TRUNK_INVALID != l_tgid) { 14793 return BCM_E_PARAM; 14794 } 14795 *param1 = l_port; 14796 *param0 = l_modid; 14797 } else 14798 #endif 14799 { 14800 /* Do not modify param0 and param1 if id != -1 */ 14801 if (-1 == id) { 14802 if (BCM_TRUNK_INVALID != l_tgid) { 14803 return BCM_E_PARAM; 14804 } 14805 *param1 = l_port; 14806 *param0 = l_modid; 14807 } 14808 } 14809 } 14810 break; 14811 case bcmFieldActionRedirectTrunk: 14812 if (BCM_GPORT_IS_SET(*param0)) { 14813 BCM_IF_ERROR_RETURN( 14814 _bcm_esw_gport_resolve(unit, *param0, &l_modid, &l_port, &l_tgid, &id)); 14815 14816 #if defined(BCM_HGPROXY_COE_SUPPORT) 14817 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 14818 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, *param0)) { 14819 /* For this case gport_resolve function returns 14820 * non-negative id */ 14821 if ((BCM_TRUNK_INVALID == l_tgid) ){ 14822 return BCM_E_PARAM; 14823 } 14824 *param0 = l_tgid; 14825 *param1 = -1; /* if param0 is trunk, param1 ignored */ 14826 } else 14827 #endif 14828 #if defined(BCM_KATANA2_SUPPORT) 14829 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 14830 *param0)) { 14831 /* For this case gport_resolve function returns 14832 * non-negative id */ 14833 if ((BCM_TRUNK_INVALID == l_tgid) ){ 14834 return BCM_E_PARAM; 14835 } 14836 *param0 = l_tgid; 14837 *param1 = -1; /* if param0 is trunk, param1 ignored */ 14838 } else 14839 #endif 14840 { 14841 if ((-1 != id) || (BCM_TRUNK_INVALID == l_tgid) ){ 14842 return BCM_E_PARAM; 14843 } 14844 *param0 = l_tgid; 14845 *param1 = -1; /* if param0 is trunk, param1 ignored */ 14846 } 14847 } 14848 break; 14849 default: 14850 break; 14851 } 14852 14853 return (BCM_E_NONE); 14854 } 14855 14856 /* 14857 * Function: _field_meter_refresh_enable_set 14858 * 14859 * Purpose: 14860 * Enable meters refresh cycle. 14861 * 14862 * Parameters: 14863 * unit - (IN) BCM device number 14864 * fc - (IN) Field control structure. 14865 * state - (IN) On/Off boolean. 14866 * 14867 * Returns: 14868 * BCM_E_NONE - No errors. 14869 * BCM_E_XXX - Otherwise. 14870 */ 14871 int 14872 _field_meter_refresh_enable_set(int unit, _field_control_t *fc, uint32 state) 14873 { 14874 14875 int rv = BCM_E_NONE; /* Operation return status. */ 14876 #ifdef BCM_TRIUMPH_SUPPORT 14877 soc_reg_t reg; 14878 #endif /* BCM_TRIUMPH_SUPPORT */ 14879 14880 /* Input parameters check. */ 14881 if (NULL == fc || ((state != TRUE) && (state != FALSE))) { 14882 return (BCM_E_PARAM); 14883 } 14884 14885 state = (state) ? 1 : 0; 14886 14887 #ifdef BCM_TRIUMPH_SUPPORT 14888 if (SOC_IS_TR_VL(unit)) { 14889 reg = (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) || 14890 SOC_IS_GREYHOUND(unit)|| SOC_IS_GREYHOUND2(unit)) ? 14891 IESMIF_CONTROLr : IESMIF_CONTROL2r; 14892 if (SOC_REG_IS_VALID (unit, reg)) { 14893 if (SOC_REG_FIELD_VALID(unit, reg, FP_REFRESH_ENABLEf)) { 14894 rv = soc_reg_field32_modify(unit, reg, REG_PORT_ANY, 14895 FP_REFRESH_ENABLEf, state); 14896 BCM_IF_ERROR_RETURN(rv); 14897 } 14898 } 14899 if(!SOC_IS_HURRICANE(unit)) { 14900 if (SOC_REG_IS_VALID (unit, EFP_METER_CONTROLr)) { 14901 if (SOC_REG_FIELD_VALID(unit, EFP_METER_CONTROLr, EFP_REFRESH_ENABLEf)) { 14902 rv = soc_reg_field32_modify(unit, EFP_METER_CONTROLr, REG_PORT_ANY, 14903 EFP_REFRESH_ENABLEf, state); 14904 } 14905 } 14906 BCM_IF_ERROR_RETURN(rv); 14907 } 14908 #if defined(BCM_TOMAHAWK_SUPPORT) 14909 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 14910 rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROLr, 14911 REG_PORT_ANY, 14912 FP_REFRESH_ENABLEf, state); 14913 BCM_IF_ERROR_RETURN(rv); 14914 14915 } else 14916 #endif 14917 #if defined(BCM_APACHE_SUPPORT) 14918 if (SOC_IS_APACHE(unit)) { 14919 rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2_64r, 14920 REG_PORT_ANY, 14921 FP_REFRESH_ENABLEf, state); 14922 BCM_IF_ERROR_RETURN(rv); 14923 14924 } else 14925 #endif 14926 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || 14927 SOC_IS_TRIUMPH3(unit) || SOC_IS_HURRICANE2(unit) || 14928 SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 14929 SOC_IS_GREYHOUND2(unit)) { 14930 rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r, 14931 REG_PORT_ANY, 14932 FP_REFRESH_ENABLEf, state); 14933 BCM_IF_ERROR_RETURN(rv); 14934 } 14935 return rv; 14936 } 14937 #endif /* BCM_TRIUMPH_SUPPORT */ 14938 14939 #ifdef BCM_SCORPION_SUPPORT 14940 if (SOC_IS_SC_CQ(unit)) { 14941 14942 rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r, REG_PORT_ANY, 14943 FP_REFRESH_ENABLEf, state); 14944 BCM_IF_ERROR_RETURN(rv); 14945 if (SOC_SWITCH_BYPASS_MODE_L3_ONLY != SOC_SWITCH_BYPASS_MODE(unit)) { 14946 rv = soc_reg_field32_modify(unit, EFP_METER_CONTROLr, 14947 REG_PORT_ANY, 14948 EFP_REFRESH_ENABLEf, state); 14949 BCM_IF_ERROR_RETURN(rv); 14950 } 14951 return BCM_E_NONE; 14952 } 14953 #endif /* BCM_SCORPION_SUPPORT */ 14954 14955 #ifdef BCM_BRADLEY_SUPPORT 14956 if (SOC_IS_HBX(unit)) { 14957 uint32 sbs_ctrl; 14958 uint32 pipe_sel; 14959 BCM_IF_ERROR_RETURN(READ_SBS_CONTROLr(unit, &sbs_ctrl)); 14960 pipe_sel = soc_reg_field_get(unit, SBS_CONTROLr, sbs_ctrl, 14961 PIPE_SELECTf); 14962 14963 rv =soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r, REG_PORT_ANY, 14964 FP_REFRESH_ENABLEf, state); 14965 BCM_IF_ERROR_RETURN(rv); 14966 14967 /* Flip between X and Y pipe */ 14968 pipe_sel = (pipe_sel == 0) ? 1 : 0; 14969 soc_reg_field_set(unit, SBS_CONTROLr, &sbs_ctrl, PIPE_SELECTf, 14970 pipe_sel); 14971 BCM_IF_ERROR_RETURN(WRITE_SBS_CONTROLr(unit, sbs_ctrl)); 14972 14973 rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r, REG_PORT_ANY, 14974 FP_REFRESH_ENABLEf, state); 14975 BCM_IF_ERROR_RETURN(rv); 14976 /* Restore original pipeline selection */ 14977 pipe_sel = (pipe_sel == 0) ? 1 : 0; 14978 soc_reg_field_set(unit, SBS_CONTROLr, &sbs_ctrl, PIPE_SELECTf, 14979 pipe_sel); 14980 return WRITE_SBS_CONTROLr(unit, sbs_ctrl); 14981 } 14982 #endif /* BCM_BRADLEY_SUPPORT */ 14983 14984 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) 14985 if (soc_feature(unit, soc_feature_field_multi_stage)) { 14986 rv = soc_reg_field32_modify(unit, EFP_METER_CONTROLr, REG_PORT_ANY, 14987 EFP_REFRESH_ENABLEf, state); 14988 BCM_IF_ERROR_RETURN(rv); 14989 } 14990 #endif /* BCM_FIREBOLT2_SUPPORT */ 14991 14992 rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROLr, REG_PORT_ANY, 14993 FP_REFRESH_ENABLEf, state); 14994 14995 return (rv); 14996 } 14997 14998 14999 /* 15000 * Function: 15001 * _bcm_field_stage_qualifiers_free 15002 * Purpose: 15003 * De-initialize stage qaualifiers descriptors. 15004 * Parameters: 15005 * unit - (IN) BCM device number. 15006 * stage_fc - (IN) Field Processor stage control structure. 15007 * 15008 * Returns: 15009 * BCM_E_NONE 15010 */ 15011 int 15012 _bcm_field_stage_qualifiers_free(int unit, _field_stage_t *stage_fc) 15013 { 15014 _bcm_field_qual_info_t *f_qual; /* Qualifier descriptor. */ 15015 int idx; /* Qualifiers iteration index. */ 15016 15017 /* Input parameters check. */ 15018 if (NULL == stage_fc) { 15019 return (BCM_E_PARAM); 15020 } 15021 15022 if (NULL == stage_fc->f_qual_arr) { 15023 return (BCM_E_NONE); 15024 } 15025 15026 for (idx = 0; idx < _bcmFieldQualifyCount; idx++) { 15027 f_qual = stage_fc->f_qual_arr[idx]; 15028 15029 /* Skip unused qualifiers. */ 15030 if (NULL == f_qual) { 15031 continue; 15032 } 15033 /* Free qualifier configurations array. */ 15034 if (NULL != f_qual->conf_arr) sal_free(f_qual->conf_arr); 15035 15036 /* Free qualifier descriptor structure. */ 15037 sal_free(f_qual); 15038 15039 /* Mark qualifier as unused. */ 15040 stage_fc->f_qual_arr[idx] = NULL; 15041 } 15042 15043 /* Free qualifiers array. */ 15044 sal_free(stage_fc->f_qual_arr); 15045 stage_fc->f_qual_arr = NULL; 15046 15047 return (BCM_E_NONE); 15048 } 15049 15050 /* 15051 * Function: 15052 * _field_qual_add 15053 * Purpose: 15054 * Install field selector to selectors table. 15055 * 15056 * Parameters: 15057 * fpf_info - (IN) FPF memory, field, qual table and selector table info. 15058 * qid - (IN) Qualifier id. 15059 * offset - (IN) Qualifier offset. 15060 * width - (IN) Qualifier width. 15061 * code - (IN) FPF table index. 15062 * Returns: 15063 * BCM_E_XXX 15064 */ 15065 int 15066 _field_qual_add (_field_fpf_info_t *fpf_info, int qid, 15067 int offset, int width, int code) 15068 { 15069 _qual_info_t *fq_p; 15070 15071 /* Input parameters check. */ 15072 if ((code >= FPF_SZ_MAX) || (NULL == fpf_info)) { 15073 return (BCM_E_PARAM); 15074 } 15075 15076 /* Allocate qualifier info. */ 15077 fq_p = sal_alloc(sizeof(_qual_info_t), "Qualifier Info"); 15078 if (NULL == fq_p) { 15079 return (BCM_E_MEMORY); 15080 } 15081 15082 /* Set qualifier data. */ 15083 _FP_QUAL_INFO_SET(qid, fpf_info->field, offset, width, fq_p); 15084 15085 /* Insert qual_table */ 15086 fq_p->next = fpf_info->qual_table[code]; 15087 fpf_info->qual_table[code] = fq_p; 15088 15089 /* Insert qual_table */ 15090 BCM_FIELD_QSET_ADD_INTERNAL(fpf_info->sel_table[code], qid); 15091 15092 return (BCM_E_NONE); 15093 } 15094 15095 /* 15096 * Function: 15097 * _bcm_field_group_slice_count_get 15098 * Purpose: 15099 * Retrieve number of slices group occupies 15100 * Parameters: 15101 * flags -(IN) Group flags. 15102 * count -(OUT)Slice count (1-3). 15103 * Returns: 15104 * BCM_E_XXX 15105 */ 15106 int 15107 _bcm_field_group_slice_count_get(uint32 flags, int *count) 15108 { 15109 15110 if (NULL == count) { 15111 return (BCM_E_PARAM); 15112 } 15113 15114 if (flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 15115 *count = 3; 15116 } else if (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 15117 *count = 2; 15118 } else { 15119 *count = 1; 15120 } 15121 return (BCM_E_NONE); 15122 } 15123 15124 /* 15125 * Function: 15126 * _field_qual_offset_get 15127 * Purpose: 15128 * Retrieve qualifier offsets 15129 * Parameters: 15130 * unit - (IN) BCM device number. 15131 * f_ent - (IN) Field entry structure. 15132 * qid - (IN) Qualifier id. 15133 * offset - (OUT) Qualifier offset and width. 15134 * Returns: 15135 * BCM_E_XXX 15136 */ 15137 int 15138 _field_qual_offset_get(int unit, _field_entry_t *f_ent, int qid, 15139 _bcm_field_qual_offset_t **offset) 15140 { 15141 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 15142 _field_group_t *fg; /* Field group structure. */ 15143 uint8 entry_part;/* Wide entry part number. */ 15144 uint8 entry_type; /* Index to tcam entries 15145 of multiple types */ 15146 int rv; /* Operation return status. */ 15147 int idx; /* Entry qualifiers iterator. */ 15148 15149 LOG_DEBUG(BSL_LS_BCM_FP, 15150 (BSL_META_U(unit, 15151 "_field_qual_offset_get\n"))); 15152 15153 /* Input parameters check. */ 15154 if ((NULL == offset) || (NULL == f_ent)) { 15155 return (BCM_E_PARAM); 15156 } 15157 15158 /* Get entry group. */ 15159 fg = f_ent->group; 15160 15161 #if defined(BCM_TOMAHAWK_SUPPORT) 15162 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 15163 (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) { 15164 return (BCM_E_NONE); 15165 } 15166 #endif /* BCM_TOMAHAWK_SUPPORT */ 15167 15168 if (0 == BCM_FIELD_QSET_TEST(fg->qset, qid)) { 15169 /* Only qualifiers that were explicitly requested may be used */ 15170 #ifdef BROADCOM_DEBUG 15171 LOG_ERROR(BSL_LS_BCM_FP, 15172 (BSL_META_U(unit, 15173 "FP(unit %d) Error: qual=%s not in group=%d Qset\n"), 15174 unit, 15175 _field_qual_name(qid), f_ent->group->gid)); 15176 #endif 15177 return (BCM_E_PARAM); 15178 } 15179 15180 /* Get field entry part where qualifier resides. */ 15181 rv = _bcm_field_entry_flags_to_tcam_part (unit, f_ent->flags, fg, 15182 &entry_part); 15183 BCM_IF_ERROR_RETURN(rv); 15184 15185 entry_type = _FP_ENTRY_TYPE_DEFAULT; 15186 15187 /* Get qualifier information. */ 15188 q_arr = &(fg->qual_arr[entry_type][entry_part]); 15189 for (idx = 0; idx < q_arr->size; idx++) { 15190 if (qid == q_arr->qid_arr[idx]) { 15191 *offset = q_arr->offset_arr + idx; 15192 break; 15193 } 15194 } 15195 15196 if (idx == q_arr->size) { 15197 *offset = NULL; 15198 return (BCM_E_NOT_FOUND); 15199 } 15200 return (BCM_E_NONE); 15201 } 15202 #if defined(BCM_TRIDENT2_SUPPORT) 15203 /* 15204 * Function: 15205 * _field_qual_offset_get_by_entry_type 15206 * Purpose: 15207 * Retrieve qualifier offsets 15208 * Parameters: 15209 * unit - (IN) BCM device number. 15210 * f_ent - (IN) Field entry structure. 15211 * qid - (IN) Qualifier id. 15212 * entry_type - (IN) Index to groups qual_arr 15213 * offset - (OUT) Qualifier offset and width. 15214 * Returns: 15215 * BCM_E_XXX 15216 */ 15217 int 15218 _field_qual_offset_get_by_entry_type(int unit, _field_entry_t *f_ent, int qid, 15219 uint8 entry_type, 15220 _bcm_field_qual_offset_t **offset) 15221 { 15222 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 15223 _field_group_t *fg; /* Field group structure. */ 15224 uint8 entry_part;/* Wide entry part number. */ 15225 int rv; /* Operation return status. */ 15226 int idx; /* Entry qualifiers iterator. */ 15227 15228 LOG_DEBUG(BSL_LS_BCM_FP, 15229 (BSL_META_U(unit, 15230 "_field_qual_offset_get_by_entry_type\n"))); 15231 15232 /* Input parameters check. */ 15233 if ((NULL == offset) || (NULL == f_ent)) { 15234 return (BCM_E_PARAM); 15235 } 15236 15237 /* Get entry group. */ 15238 fg = f_ent->group; 15239 15240 if (0 == BCM_FIELD_QSET_TEST(fg->qset, qid)) { 15241 /* Only qualifiers that were explicitly requested may be used */ 15242 #ifdef BROADCOM_DEBUG 15243 LOG_ERROR(BSL_LS_BCM_FP, 15244 (BSL_META_U(unit, 15245 "FP(unit %d) Error: qual=%s not in group=%d Qset\n"), 15246 unit, 15247 _field_qual_name(qid), f_ent->group->gid)); 15248 #endif 15249 return (BCM_E_PARAM); 15250 } 15251 15252 /* Get field entry part where qualifier resides. */ 15253 rv = _bcm_field_entry_flags_to_tcam_part (unit, f_ent->flags, fg, 15254 &entry_part); 15255 BCM_IF_ERROR_RETURN(rv); 15256 15257 /* Get qualifier information. */ 15258 q_arr = &(fg->qual_arr[entry_type][entry_part]); 15259 for (idx = 0; idx < q_arr->size; idx++) { 15260 if (qid == q_arr->qid_arr[idx]) { 15261 *offset = q_arr->offset_arr + idx; 15262 break; 15263 } 15264 } 15265 15266 if (idx == q_arr->size) { 15267 *offset = NULL; 15268 return (BCM_E_NOT_FOUND); 15269 } 15270 return (BCM_E_NONE); 15271 } 15272 #endif 15273 15274 /* 15275 * Function: 15276 * _field_group_qualifiers_free 15277 * Purpose: 15278 * Free group qualifiers array. 15279 * Parameters: 15280 * fg - (IN) Field group structure. 15281 * idx - (IN) Entry part. 15282 * Returns: 15283 * void 15284 * Note: 15285 */ 15286 int 15287 _bcm_field_group_qualifiers_free(_field_group_t *fg, int idx) 15288 { 15289 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 15290 int entry_type; /* holds type(L3/FcoE/L2) of an entry in a group. */ 15291 15292 /* Input parameters check. */ 15293 if ((NULL == fg) || (idx < 0) || (idx >= _FP_MAX_ENTRY_WIDTH)) { 15294 return BCM_E_PARAM; 15295 } 15296 15297 for (entry_type = 0; entry_type < _FP_MAX_ENTRY_TYPES; entry_type++) { 15298 q_arr = &(fg->qual_arr[entry_type][idx]); 15299 15300 /* Free qualifiers arrays. */ 15301 if (NULL != q_arr->qid_arr) { 15302 sal_free(q_arr->qid_arr); 15303 q_arr->qid_arr = NULL; 15304 } 15305 if (NULL != q_arr->offset_arr) { 15306 sal_free(q_arr->offset_arr); 15307 q_arr->offset_arr = NULL; 15308 } 15309 /* Reset arrays size. */ 15310 q_arr->size = 0; 15311 } 15312 15313 return (BCM_E_NONE); 15314 } 15315 15316 /* 15317 * Function: 15318 * _bcm_field_group_default_entry_set 15319 * Purpose: 15320 * Set or Clear default entry status of a entry. 15321 * Parameters: 15322 * unit - (IN) BCM Device Number. 15323 * group - (IN) Field Group ID. 15324 * entry - (IN) Field Entry ID. 15325 * enable - (IN) Enable Flag. 15326 * Returns: 15327 * BCM_E_XXX 15328 * Note: 15329 * Currently it is applicable only for exact 15330 * match stage. 15331 */ 15332 int 15333 _bcm_field_group_default_entry_set(int unit, bcm_field_group_t group, 15334 bcm_field_entry_t entry, int enable) 15335 { 15336 int rv = BCM_E_NONE; /* Operation return status. */ 15337 int idx = 0; /* Entry index */ 15338 _field_group_t *fg = NULL; /* Field group structure. */ 15339 _field_entry_t *f_ent = NULL;/* Field entry pointer. */ 15340 _field_entry_t *f_ent_tmp = NULL; 15341 /* Field entry temp pointer. */ 15342 _field_entry_stat_t *f_ent_st = NULL; 15343 /* Field entry statistics structure.*/ 15344 _field_entry_policer_t *f_ent_pl = NULL; 15345 /* Field entry policer structure. */ 15346 _field_action_t *fa = NULL; /* Field action descriptor. */ 15347 int level = 0; /* Field policer Level. */ 15348 int parts_cnt = 0; /* Field Entry parts count. */ 15349 15350 /* First validate if provided group and entry id exist. */ 15351 BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg)); 15352 BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, 15353 _FP_ENTRY_PRIMARY, &f_ent)); 15354 15355 /* Check enable flag value. */ 15356 if ((enable < 0) && (enable > 1)) { 15357 LOG_ERROR(BSL_LS_BCM_FP, 15358 (BSL_META_U(unit, 15359 "FP(unit %d) Error: enable flag value %d not valid.\n"), 15360 unit, enable)); 15361 return (BCM_E_PARAM); 15362 } 15363 15364 /* Check if entry belongs to same group provided. */ 15365 if (f_ent->group->gid != group) { 15366 LOG_ERROR(BSL_LS_BCM_FP, 15367 (BSL_META_U(unit, 15368 "FP(unit %d) Error: entry=(%d) does not belong to group %d.\n"), 15369 unit, entry, group)); 15370 return (BCM_E_CONFIG); 15371 } 15372 15373 /* Check if Group belongs to exact match stage. */ 15374 if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) { 15375 LOG_ERROR(BSL_LS_BCM_FP, 15376 (BSL_META_U(unit, 15377 "FP(unit %d) Error: group=(%d) stage is not exact match.\n"), 15378 unit, group)); 15379 return (BCM_E_CONFIG); 15380 } 15381 15382 /* Get Field Entry Parts. */ 15383 BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit, 15384 fg->stage_id, 15385 fg->flags, 15386 &parts_cnt)); 15387 15388 /* Check existing set or clear status for entry default status flag. */ 15389 if (enable) { 15390 if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) { 15391 return (BCM_E_NONE); 15392 } 15393 } else { 15394 if (!(f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT)) { 15395 return (BCM_E_NONE); 15396 } 15397 } 15398 15399 /* Check group default entry status for set and clear. */ 15400 if (enable) { 15401 for (idx = 0; idx < fg->group_status.entry_count; idx++) { 15402 f_ent_tmp = fg->entry_arr[idx]; 15403 if (f_ent_tmp->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) { 15404 LOG_ERROR(BSL_LS_BCM_FP, 15405 (BSL_META_U(unit, 15406 "FP(unit %d) Error: group=(%d) already have existing" 15407 "default entry %d.\n"), 15408 unit, group, f_ent_tmp->eid)); 15409 return (BCM_E_CONFIG); 15410 } 15411 } 15412 } 15413 15414 /* Check if entry is installed. */ 15415 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 15416 LOG_ERROR(BSL_LS_BCM_FP, 15417 (BSL_META_U(unit, 15418 "FP(unit %d) Error: entry=(%d) is installed, " 15419 "cannot change default status.\n"), 15420 unit, entry)); 15421 return (BCM_E_CONFIG); 15422 } 15423 15424 /* Check if group have qualifier associated to it. */ 15425 for(idx = 0; idx < parts_cnt; idx++) { 15426 f_ent_tmp = f_ent + idx; 15427 15428 /* Check if any action is attached to entry. */ 15429 fa = f_ent_tmp->actions; 15430 if (fa != NULL) { 15431 LOG_ERROR(BSL_LS_BCM_FP, 15432 (BSL_META_U(unit, 15433 "FP(unit %d) Error: entry=(%d) have action associated, " 15434 "cannot change default status.\n"), 15435 unit, entry)); 15436 return (BCM_E_CONFIG); 15437 } 15438 15439 /* Check if valid stat is attached. */ 15440 f_ent_st = &f_ent_tmp->statistic; 15441 if (f_ent_st->flags & _FP_ENTRY_STAT_VALID) { 15442 LOG_ERROR(BSL_LS_BCM_FP, 15443 (BSL_META_U(unit, 15444 "FP(unit %d) Error: entry=(%d) have stats attached to it, " 15445 "cannot change default status.\n"), 15446 unit, entry)); 15447 return (BCM_E_CONFIG); 15448 } 15449 15450 /* Check if valid policer is attached. */ 15451 for (level = 0; level < _FP_POLICER_LEVEL_COUNT; level++) { 15452 f_ent_pl = f_ent_tmp->policer + level; 15453 if (f_ent_pl->flags & _FP_POLICER_VALID) { 15454 LOG_ERROR(BSL_LS_BCM_FP, 15455 (BSL_META_U(unit, 15456 "FP(unit %d) Error: entry=(%d) have policer attached to " 15457 "it, cannot change default status.\n"), 15458 unit, entry)); 15459 return (BCM_E_CONFIG); 15460 } 15461 } 15462 } 15463 15464 /* Configure entry as default. */ 15465 if (enable) { 15466 /* Clear qualifier if any. */ 15467 BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_clear(unit, entry)); 15468 f_ent->flags |= _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT; 15469 } else { 15470 f_ent->flags &= ~_FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT; 15471 } 15472 15473 return (rv); 15474 } 15475 15476 /* 15477 * Function: 15478 * _bcm_field_group_default_entry_get 15479 * Purpose: 15480 * Get Default Field entry ID associated to group. 15481 * Parameters: 15482 * unit - (IN) BCM Device Number. 15483 * group - (IN) Field Group ID. 15484 * entry - (OUT) Field Entry ID. 15485 * Returns: 15486 * BCM_E_XXX 15487 * Note: 15488 */ 15489 int 15490 _bcm_field_group_default_entry_get(int unit, bcm_field_group_t group, 15491 bcm_field_entry_t *entry) 15492 { 15493 int rv = BCM_E_NONE; /* Operation return status. */ 15494 _field_group_t *fg = NULL; /* Field group structure. */ 15495 _field_entry_t *f_ent = NULL; /* Field entry pointer. */ 15496 int found = 0; /* Entry Found Variable. */ 15497 int idx = 0; /* Entry index */ 15498 15499 /* Input Parameter Check. */ 15500 if (entry == NULL) { 15501 return (BCM_E_PARAM); 15502 } 15503 15504 /* First validate if provided group and entry id exist. */ 15505 BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg)); 15506 15507 /* Check if Group belongs to exact match stage. */ 15508 if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) { 15509 LOG_ERROR(BSL_LS_BCM_FP, 15510 (BSL_META_U(unit, 15511 "FP(unit %d) Error: group=(%d) stage is not exact match.\n"), 15512 unit, group)); 15513 return (BCM_E_PARAM); 15514 } 15515 15516 /* Search for all entries in group. */ 15517 for (idx = 0; idx < fg->group_status.entry_count; idx++) { 15518 f_ent = fg->entry_arr[idx]; 15519 if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) { 15520 found = 1; 15521 break; 15522 } 15523 } 15524 15525 /* Return entry id if found. */ 15526 if (found) { 15527 *entry = f_ent->eid; 15528 } else { 15529 rv = BCM_E_NOT_FOUND; 15530 } 15531 15532 return (rv); 15533 } 15534 15535 /* 15536 * Function: 15537 * _bcm_field_qual_list_append 15538 * Purpose: 15539 * Append a copy of a qualify info linked list. 15540 * Parameters: 15541 * fg - (IN) Field group structure. 15542 * entry_part - (IN) Field entry part. 15543 * fq_src - (IN) Copy source list. 15544 * offset - (IN) Offset within FPFx field. 15545 * Returns: 15546 * BCM_E_NONE 15547 * Note: 15548 */ 15549 int 15550 _bcm_field_qual_list_append(_field_group_t *fg, uint8 entry_part, 15551 _qual_info_t *fq_src, int offset) 15552 { 15553 _bcm_field_qual_offset_t *q_offset_arr; /* Qualifier offsets array. */ 15554 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 15555 _qual_info_t *fq_src_iter; /* Qualifier list iterator. */ 15556 uint16 *qid_arr; /* Qualifier id array. */ 15557 int size; /* Qualifiers array size. */ 15558 15559 /* Input parameters check. */ 15560 if ((NULL == fg) || (NULL == fq_src) || 15561 (entry_part >= _FP_MAX_ENTRY_WIDTH)) { 15562 return (BCM_E_PARAM); 15563 } 15564 15565 /* Initialization. */ 15566 qid_arr = NULL; 15567 q_offset_arr = NULL; 15568 q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][entry_part]); 15569 15570 /* Count number of group qualifiers. */ 15571 fq_src_iter = fq_src; 15572 size = 0; 15573 15574 while (NULL != fq_src_iter) { 15575 if (0 == BCM_FIELD_QSET_TEST(fg->qset, fq_src_iter->qid)) { 15576 fq_src_iter = fq_src_iter->next; 15577 continue; 15578 } 15579 size++; 15580 fq_src_iter = fq_src_iter->next; 15581 } 15582 15583 if (0 == size) { 15584 return (BCM_E_NONE); 15585 } 15586 15587 size += q_arr->size; 15588 15589 /* Allocate qualifiers id and offsets array. */ 15590 _FP_XGS3_ALLOC(qid_arr, size * sizeof (uint16), "Group qual id"); 15591 if (NULL == qid_arr) { 15592 return (BCM_E_MEMORY); 15593 } 15594 15595 _FP_XGS3_ALLOC(q_offset_arr, size * sizeof (_bcm_field_qual_offset_t), 15596 "Group qual offset"); 15597 if (NULL == q_offset_arr) { 15598 sal_free (qid_arr); 15599 return (BCM_E_MEMORY); 15600 } 15601 15602 /* Copy original qualifiers array if any. */ 15603 if (q_arr->size) { 15604 sal_memcpy(qid_arr, q_arr->qid_arr, q_arr->size * sizeof (uint16)); 15605 sal_memcpy(q_offset_arr, q_arr->offset_arr, q_arr->size * sizeof (_bcm_field_qual_offset_t)); 15606 sal_free (q_arr->qid_arr); 15607 sal_free (q_arr->offset_arr); 15608 } 15609 15610 /* Copy qualifiers id and offsets. */ 15611 q_arr->qid_arr = qid_arr; 15612 q_arr->offset_arr = q_offset_arr; 15613 fq_src_iter = fq_src; 15614 while (NULL != fq_src_iter) { 15615 if (0 == BCM_FIELD_QSET_TEST(fg->qset, fq_src_iter->qid)) { 15616 fq_src_iter = fq_src_iter->next; 15617 continue; 15618 } 15619 q_arr->qid_arr[q_arr->size] = fq_src_iter->qid; 15620 q_arr->offset_arr[q_arr->size].offset[0] = fq_src_iter->offset + offset; 15621 q_arr->offset_arr[q_arr->size].width[0] = fq_src_iter->width; 15622 q_arr->offset_arr[q_arr->size].field = fq_src_iter->fpf; 15623 q_arr->size++; 15624 fq_src_iter = fq_src_iter->next; 15625 } 15626 return (BCM_E_NONE); 15627 } 15628 15629 /* 15630 * Function: 15631 * _field_entry_tcam_memory_info_get 15632 * Purpose: 15633 * Get TCAM memory and field names for specific entry. 15634 * Parameters: 15635 * unit - (IN) BCM device number. 15636 * f_ent - (IN) Field entry. 15637 * tcam - (OUT) TCAM memory info. 15638 * Returns: 15639 * BCM_E_XXX 15640 */ 15641 STATIC int 15642 _field_entry_tcam_memory_info_get(int unit, _field_entry_t *f_ent, 15643 _field_tcam_mem_info_t *tcam, int ipbm_overlay) 15644 { 15645 15646 /* Input parameters check. */ 15647 if ((NULL == f_ent) || (NULL == tcam)) { 15648 return (BCM_E_PARAM); 15649 } 15650 15651 #if defined(BCM_FIREBOLT_SUPPORT) 15652 15653 #if defined(BCM_HURRICANE_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 15654 if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 15655 SOC_IS_GREYHOUND2(unit)) { 15656 if (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) { 15657 tcam->key_field = (SOC_IS_HURRICANE2(unit) || 15658 SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 15659 SOC_IS_GREYHOUND2(unit)) ? 15660 DATA_KEYf : DATAf; 15661 tcam->mask_field = DATA_MASKf; 15662 tcam->memory = FP_TCAMm; 15663 } else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 15664 tcam->memory = EFP_TCAMm; 15665 tcam->key_field = KEYf; 15666 tcam->mask_field = KEY_MASKf; 15667 } else if (_BCM_FIELD_STAGE_LOOKUP== f_ent->group->stage_id) { 15668 tcam->memory = VFP_TCAMm; 15669 tcam->key_field = KEYf; 15670 tcam->mask_field = MASKf; 15671 } 15672 15673 } else 15674 #endif /* BCM_HURRICANE_SUPPORT || BCM_GREYHOUND_SUPPORT */ 15675 15676 if (SOC_IS_FBX(unit)) { 15677 if ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 15678 tcam->memory = FP_TCAMm; 15679 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 15680 if (SOC_IS_TD_TT(unit)) 15681 { 15682 tcam->key_field = KEYf; 15683 tcam->mask_field = MASKf; 15684 15685 if (ipbm_overlay) 15686 { 15687 tcam->memory = FP_GM_FIELDSm; 15688 } 15689 } else if ((SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || SOC_IS_KATANAX(unit)) 15690 && ipbm_overlay) { 15691 tcam->key_field = IPBMf; 15692 tcam->mask_field = IPBM_MASKf; 15693 tcam->memory = FP_GLOBAL_MASK_TCAMm; 15694 } else if ((SOC_IS_TRX(unit)) || 15695 (f_ent->flags & _FP_ENTRY_SECOND_HALF)) { 15696 tcam->key_field = DATAf; 15697 tcam->mask_field = DATA_MASKf; 15698 } else 15699 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 15700 { 15701 tcam->key_field = KEYf; 15702 tcam->mask_field = MASKf; 15703 } 15704 } 15705 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 15706 if (soc_feature(unit, soc_feature_field_multi_stage)) { 15707 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 15708 tcam->memory = EFP_TCAMm; 15709 tcam->key_field = KEYf; 15710 tcam->mask_field = KEY_MASKf; 15711 } else if (_BCM_FIELD_STAGE_LOOKUP== f_ent->group->stage_id) { 15712 tcam->memory = VFP_TCAMm; 15713 tcam->key_field = KEYf; 15714 tcam->mask_field = MASKf; 15715 } 15716 } 15717 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 15718 } 15719 #endif /* BCM_FIREBOLT_SUPPORT */ 15720 return (BCM_E_NONE); 15721 } 15722 15723 /* 15724 * Function: 15725 * _bcm_field_qual_tcam_key_mask_free 15726 * Purpose: 15727 * Free tcam key/mask buffers. 15728 * Parameters: 15729 * unit - (IN) BCM device number. 15730 * f_ent - (IN/OUT) Field entry. 15731 * Returns: 15732 * BCM_E_XXX 15733 */ 15734 int 15735 _bcm_field_qual_tcam_key_mask_free(int unit, _field_entry_t *f_ent) 15736 { 15737 /* Input parameters check. */ 15738 if (NULL == f_ent) { 15739 return (BCM_E_PARAM); 15740 } 15741 15742 if (NULL != f_ent->tcam.key) { 15743 sal_free(f_ent->tcam.key); 15744 f_ent->tcam.key = NULL; 15745 } 15746 if (NULL != f_ent->tcam.mask) { 15747 sal_free(f_ent->tcam.mask); 15748 f_ent->tcam.mask = NULL; 15749 } 15750 if (NULL != f_ent->tcam.key_hw) { 15751 sal_free(f_ent->tcam.key_hw); 15752 f_ent->tcam.key_hw = NULL; 15753 } 15754 if (NULL != f_ent->tcam.mask_hw) { 15755 sal_free(f_ent->tcam.mask_hw); 15756 f_ent->tcam.mask_hw = NULL; 15757 } 15758 if (NULL != f_ent->key_match_tcam.key) { 15759 sal_free(f_ent->key_match_tcam.key); 15760 f_ent->key_match_tcam.key = NULL; 15761 } 15762 if (NULL != f_ent->key_match_tcam.mask) { 15763 sal_free(f_ent->key_match_tcam.mask); 15764 f_ent->key_match_tcam.mask = NULL; 15765 } 15766 if (NULL != f_ent->key_match_tcam.key_hw) { 15767 sal_free(f_ent->key_match_tcam.key_hw); 15768 f_ent->key_match_tcam.key_hw = NULL; 15769 } 15770 if (NULL != f_ent->key_match_tcam.mask_hw) { 15771 sal_free(f_ent->key_match_tcam.mask_hw); 15772 f_ent->key_match_tcam.mask_hw = NULL; 15773 } 15774 if (NULL != f_ent->extra_tcam.key) { 15775 sal_free(f_ent->extra_tcam.key); 15776 f_ent->extra_tcam.key = NULL; 15777 } 15778 if (NULL != f_ent->extra_tcam.mask) { 15779 sal_free(f_ent->extra_tcam.mask); 15780 f_ent->extra_tcam.mask = NULL; 15781 } 15782 if (NULL != f_ent->extra_tcam.key_hw) { 15783 sal_free(f_ent->extra_tcam.key_hw); 15784 f_ent->extra_tcam.key_hw = NULL; 15785 } 15786 if (NULL != f_ent->extra_tcam.mask_hw) { 15787 sal_free(f_ent->extra_tcam.mask_hw); 15788 f_ent->extra_tcam.mask_hw = NULL; 15789 } 15790 return (BCM_E_NONE); 15791 } 15792 15793 int _field_qual_tcam_key_mask_get(int unit, _field_entry_t *f_ent, 15794 _field_tcam_t *tcam, int ipbm_overlay) 15795 { 15796 uint32 tcam_entry[SOC_MAX_MEM_FIELD_WORDS]; 15797 _field_tcam_mem_info_t tcam_info = { 0 }; 15798 int tcam_idx; 15799 int rv; 15800 int key_size; 15801 15802 /* Get TCAM memory and Fields information. */ 15803 15804 BCM_IF_ERROR_RETURN(_field_entry_tcam_memory_info_get(unit, f_ent, 15805 &tcam_info, ipbm_overlay)); 15806 15807 if (!SOC_MEM_FIELD_VALID(unit, tcam_info.memory, tcam_info.key_field)) { 15808 return (BCM_E_INTERNAL); 15809 } 15810 /* Key size in bits. */ 15811 key_size = soc_mem_field_length(unit, tcam_info.memory, 15812 tcam_info.key_field); 15813 /* Convert to bytes - full number of words alligned. */ 15814 key_size = (((key_size >> 5) + 1) << 2); 15815 15816 15817 /* Allocate and zero memory for tcam image.*/ 15818 tcam->key = sal_alloc(key_size, "field_entry_tcam_key"); 15819 tcam->mask = sal_alloc(key_size, "field_entry_tcam_mask"); 15820 if ((NULL == tcam->key) || (NULL == tcam->mask)) { 15821 LOG_ERROR(BSL_LS_BCM_FP, 15822 (BSL_META_U(unit, 15823 "FP(unit %d) Error: allocation failure for field_entry tcam\n"), 15824 unit)); 15825 if (tcam->key) sal_free(tcam->key); 15826 if (tcam->mask) sal_free(tcam->mask); 15827 return (BCM_E_MEMORY); 15828 } 15829 sal_memset(tcam->key, 0, key_size); 15830 sal_memset(tcam->mask, 0, key_size); 15831 tcam->key_size = key_size; 15832 15833 /* Read entry from HW if it was installed previously. */ 15834 if(f_ent->flags & _FP_ENTRY_INSTALLED) { 15835 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent, &tcam_idx); 15836 if (BCM_FAILURE(rv)) { 15837 if (tcam->key) sal_free(tcam->key); 15838 if (tcam->mask) sal_free(tcam->mask); 15839 tcam->mask = tcam->key = NULL; 15840 return (rv); 15841 } 15842 rv = soc_mem_read(unit, tcam_info.memory, MEM_BLOCK_ANY, 15843 tcam_idx, tcam_entry); 15844 if (BCM_FAILURE(rv)) { 15845 if (tcam->key) sal_free(tcam->key); 15846 if (tcam->mask) sal_free(tcam->mask); 15847 tcam->mask = tcam->key = NULL; 15848 return (rv); 15849 } 15850 soc_mem_field_get(unit, tcam_info.memory, tcam_entry, 15851 tcam_info.key_field, tcam->key); 15852 soc_mem_field_get(unit, tcam_info.memory, tcam_entry, 15853 tcam_info.mask_field, tcam->mask); 15854 if (SOC_MEM_FIELD_VALID(unit, tcam_info.memory, F4f)) { 15855 soc_mem_field_get(unit, tcam_info.memory, tcam_entry, 15856 F4f, &tcam->f4); 15857 soc_mem_field_get(unit, tcam_info.memory, tcam_entry, 15858 F4_MASKf, &tcam->f4_mask); 15859 } 15860 } 15861 15862 return BCM_E_NONE; 15863 } 15864 15865 /* 15866 * Function: 15867 * _bcm_field_qual_tcam_key_mask_get 15868 * Purpose: 15869 * Allocate & read from hw tcam key/mask image. 15870 * Parameters: 15871 * unit - (IN) BCM device number. 15872 * f_ent - (IN/OUT) Field entry. 15873 * Returns: 15874 * BCM_E_XXX 15875 */ 15876 int 15877 _bcm_field_qual_tcam_key_mask_get(int unit, _field_entry_t *f_ent) 15878 { 15879 /* Input parameters check. */ 15880 if (NULL == f_ent) { 15881 return (BCM_E_PARAM); 15882 } 15883 15884 if (f_ent->flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 15885 if (NULL == f_ent->extra_tcam.key) { 15886 BCM_IF_ERROR_RETURN(_field_qual_tcam_key_mask_get(unit, f_ent, 15887 &f_ent->extra_tcam, 1)); 15888 } 15889 } 15890 15891 /* Check if tcam info already present. */ 15892 if (NULL != f_ent->tcam.key) { 15893 return (BCM_E_NONE); 15894 } 15895 15896 if (_BCM_FIELD_STAGE_EXTERNAL == f_ent->fs->stage_id) { 15897 #if defined(BCM_TRIUMPH_SUPPORT) 15898 if (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) { 15899 return _bcm_field_tr_external_tcam_key_mask_get(unit, f_ent); 15900 } 15901 #endif /* BCM_TRIUMPH_SUPPORT */ 15902 } 15903 15904 #ifdef BCM_TRIDENT2_SUPPORT 15905 if (SOC_IS_TD2_TT2(unit)) { 15906 #if defined(BCM_TOMAHAWK_SUPPORT) 15907 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 15908 ((_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id) || 15909 (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) || 15910 (_BCM_FIELD_STAGE_EGRESS == f_ent->fs->stage_id) || 15911 (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->fs->stage_id) || 15912 (_BCM_FIELD_STAGE_FLOWTRACKER == f_ent->fs->stage_id))) { 15913 BCM_IF_ERROR_RETURN 15914 (_bcm_field_th_qual_tcam_key_mask_get(unit, f_ent, &f_ent->tcam)); 15915 /* EFP has 2 types of keys for each entry. 1. tcam will have 15916 * all the qualifiers i.e., default qset. 2. key_match_tcam is 15917 * a subset of default qset having only Not L3 and Not FCoE quals */ 15918 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 15919 if (NULL != f_ent->key_match_tcam.key) { 15920 return (BCM_E_NONE); 15921 } 15922 /* if key_match_tcam is Null, Allocate memory for it */ 15923 BCM_IF_ERROR_RETURN 15924 (_bcm_field_th_qual_tcam_key_mask_get(unit, f_ent, 15925 &f_ent->key_match_tcam)); 15926 15927 /* At the time of entry install, both tcam and key_match_tcam 15928 * are freed. if entry is already installed, one key will be 15929 * updated from the h/w tcam, and the other key will be updated 15930 * in the below function depending on efp_key_match_type value*/ 15931 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 15932 if(!(f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE 15933 && f_ent->flags & _FP_ENTRY_PRIMARY)) { 15934 return (bcm_field_efp_update_alternate_key_mask(unit, f_ent, 15935 f_ent->efp_key_match_type)); 15936 } 15937 } 15938 return (BCM_E_NONE); 15939 } 15940 15941 } else 15942 #endif /* BCM_TOMAHAWK_SUPPORT */ 15943 { 15944 BCM_IF_ERROR_RETURN 15945 (_bcm_field_td2_qual_tcam_key_mask_get(unit, f_ent, 15946 &f_ent->tcam)); 15947 } 15948 15949 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 15950 if (NULL != f_ent->key_match_tcam.key) { 15951 return (BCM_E_NONE); 15952 } 15953 BCM_IF_ERROR_RETURN 15954 (_bcm_field_td2_qual_tcam_key_mask_get(unit, f_ent, &f_ent->key_match_tcam)); 15955 15956 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 15957 if(!(f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE 15958 && f_ent->flags & _FP_ENTRY_PRIMARY)) { 15959 return (bcm_field_efp_update_alternate_key_mask(unit, f_ent, 15960 f_ent->efp_key_match_type)); 15961 } 15962 } 15963 return (BCM_E_NONE); 15964 } else { 15965 return (BCM_E_NONE); 15966 } 15967 } else 15968 #endif 15969 15970 #ifdef BCM_TRIUMPH3_SUPPORT 15971 if (SOC_IS_TRIUMPH3(unit)) { 15972 return (_bcm_field_tr3_qual_tcam_key_mask_get(unit, f_ent, &f_ent->tcam)); 15973 } 15974 #endif 15975 15976 #ifdef BCM_KATANA2_SUPPORT 15977 if (SOC_IS_KATANA2(unit)) { 15978 return (_bcm_field_kt2_qual_tcam_key_mask_get(unit, f_ent, &f_ent->tcam)); 15979 } 15980 #endif 15981 15982 15983 BCM_IF_ERROR_RETURN(_field_qual_tcam_key_mask_get(unit, f_ent, 15984 &f_ent->tcam, 0)); 15985 15986 return (BCM_E_NONE); 15987 } 15988 15989 15990 /* 15991 * Function: 15992 * _field_qual_value_set 15993 * 15994 * Purpose: 15995 * Set a qualifier field from the designated data and mask arrays. 15996 * 15997 * Parameters: 15998 * unit - (IN) BCM devices number 15999 * qi - (IN) Qualifier offset inside tcam. 16000 * f_ent - (IN) Field entry descriptor. 16001 * p_data - (IN) Inserted data. 16002 * p_mask - (IN) Data mask. 16003 * ipbm_overlay - (IN) Flag to indicate extra_tcam has to be used or not 16004 * key_match_tcam - (IN) Flag to indicate which tcam to use 16005 * Returns: 16006 * BCM_E_XXX 16007 */ 16008 STATIC int 16009 _field_qual_value_set(int unit, _qual_info_t *qi, 16010 _field_entry_t *f_ent, 16011 uint32 *p_data, uint32 *p_mask, 16012 int ipbm_overlay, uint8 key_match_tcam) 16013 { 16014 uint32 u32_mask, *p_fn_data, *p_fn_mask; 16015 int idx, wp, bp, len; 16016 16017 #define DATA_TOO_BIG_FOR_FIELD ((p_data[idx] & ~u32_mask) != 0) 16018 wp = qi->offset / 32; 16019 bp = qi->offset & (32 - 1); 16020 idx = 0; 16021 p_fn_data = p_fn_mask = NULL; 16022 16023 LOG_DEBUG(BSL_LS_BCM_FP, 16024 (BSL_META_U(unit, 16025 "FP(unit %d) vverb: qi={offset=%d, width=%d}, ipbm_overlay=%d, data=0x%08x, mask=0x%08x\n"), 16026 unit, qi->offset, qi->width, ipbm_overlay, *p_data, *p_mask)); 16027 16028 BCM_IF_ERROR_RETURN(_bcm_field_qual_tcam_key_mask_get(unit, f_ent)); 16029 16030 switch (qi->fpf) { 16031 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 16032 case DATAf: 16033 case DATA_KEYf: 16034 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 16035 case KEYf: 16036 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 16037 if (ipbm_overlay) { 16038 p_fn_data = f_ent->extra_tcam.key; 16039 p_fn_mask = f_ent->extra_tcam.mask; 16040 } else 16041 #endif /* BCM_TRIDENT_SUPPORT */ 16042 if (key_match_tcam) { 16043 p_fn_data = f_ent->key_match_tcam.key; 16044 p_fn_mask = f_ent->key_match_tcam.mask; 16045 } else { 16046 p_fn_data = f_ent->tcam.key; 16047 p_fn_mask = f_ent->tcam.mask; 16048 } 16049 16050 break; 16051 #ifdef BCM_FIREBOLT_SUPPORT 16052 case F4f: 16053 p_fn_data = &f_ent->tcam.f4; 16054 /* coverity[ptr_arith : FALSE] */ 16055 p_fn_mask = &f_ent->tcam.f4_mask; 16056 break; 16057 #endif /* BCM_FIREBOLT_SUPPORT */ 16058 default: 16059 LOG_ERROR(BSL_LS_BCM_FP, 16060 (BSL_META_U(unit, 16061 "FP(unit %d) Error: Bad TCAM field=%#05x\n"), 16062 unit, qi->fpf)); 16063 return (BCM_E_INTERNAL); 16064 }; 16065 16066 for (len = qi->width; len > 0; len -= 32) { 16067 if (bp) { 16068 if (len < 32) { 16069 u32_mask = (1 << len) - 1; 16070 /* Chop mask to fit mask field. */ 16071 p_mask[idx] &= u32_mask; 16072 if (DATA_TOO_BIG_FOR_FIELD) { 16073 LOG_ERROR(BSL_LS_BCM_FP, 16074 (BSL_META_U(unit, 16075 "FP(unit %d) Error: data=%#x "), 16076 unit, *p_data)); 16077 LOG_ERROR(BSL_LS_BCM_FP, 16078 (BSL_META_U(unit, 16079 "or mask=%#x too big for field\n"), 16080 *p_mask)); 16081 return (BCM_E_PARAM); 16082 } 16083 } else { 16084 u32_mask = 0xffffffff; 16085 } 16086 16087 p_fn_data[wp] &= ~(u32_mask << bp); 16088 p_fn_data[wp] |= p_data[idx] << bp; 16089 /* 16090 * COVERITY 16091 * 16092 *This flow takes care of the Out-of-bounds access issue 16093 * for data and mask. 16094 */ 16095 /* coverity[ptr_arith : FALSE] */ 16096 16097 p_fn_mask[wp] &= ~(u32_mask << bp); 16098 p_fn_mask[wp] |= p_mask[idx] << bp; 16099 16100 if (len > (32-bp)) { 16101 wp++; 16102 p_fn_data[wp] &= ~(u32_mask >> (32 - bp)); 16103 p_fn_data[wp] |= p_data[idx] >> (32 - bp) & ((1 << bp) - 1); 16104 16105 p_fn_mask[wp] &= ~(u32_mask >> (32 - bp)); 16106 p_fn_mask[wp] |= p_mask[idx] >> (32 - bp) & ((1 << bp) - 1); 16107 } 16108 } else { 16109 if (len < 32) { 16110 u32_mask = (1 << len) - 1; 16111 /* Chop mask to fit mask field. */ 16112 p_mask[idx] &= u32_mask; 16113 if (DATA_TOO_BIG_FOR_FIELD) { 16114 LOG_ERROR(BSL_LS_BCM_FP, 16115 (BSL_META_U(unit, 16116 "FP(unit %d) Error: data=%#x or mask=%#x " 16117 "too big for field\n"), 16118 unit, *p_data, *p_mask)); 16119 return (BCM_E_PARAM); 16120 } 16121 p_fn_data[wp] &= ~u32_mask; 16122 p_fn_data[wp] |= p_data[idx]; 16123 /* coverity[ptr_arith : FALSE] */ 16124 p_fn_mask[wp] &= ~u32_mask; 16125 p_fn_mask[wp++] |= p_mask[idx]; 16126 16127 } else { 16128 p_fn_data[wp] = p_data[idx]; 16129 /* coverity[ptr_arith : FALSE] */ 16130 p_fn_mask[wp++] = p_mask[idx]; 16131 } 16132 } 16133 16134 idx++; 16135 } 16136 16137 f_ent->flags |= _FP_ENTRY_DIRTY; 16138 f_ent->flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY); 16139 16140 return (BCM_E_NONE); 16141 } 16142 #undef DATA_TOO_BIG_FOR_FIELD 16143 16144 /* 16145 * Function: 16146 * _field_qual_value_get 16147 * 16148 * Purpose: 16149 * Retrieve a qualifier value from the designated data/mask 16150 * field pair, returning them to *p_data and *p_mask. 16151 * 16152 * Returns: 16153 * BCM_E_NONE - Success 16154 */ 16155 STATIC int 16156 _field_qual_value_get(int unit, _qual_info_t *qi, _field_entry_t *f_ent, 16157 uint32 *p_data, uint32 *p_mask, int ipbm_overlay) 16158 { 16159 uint32 *p_fn_data, *p_fn_mask; 16160 int idx, wp, bp, len; 16161 16162 /* Input parameters check. */ 16163 if ((NULL == f_ent) || (NULL == p_data) || 16164 (NULL == qi) || (NULL == p_mask)) { 16165 return (BCM_E_PARAM); 16166 } 16167 16168 wp = qi->offset / 32; 16169 bp = qi->offset & (32 - 1); 16170 idx = 0; 16171 p_fn_data = p_fn_mask = NULL; 16172 16173 BCM_IF_ERROR_RETURN(_bcm_field_qual_tcam_key_mask_get(unit, f_ent)); 16174 16175 switch (qi->fpf) { 16176 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 16177 case DATAf: 16178 case DATA_KEYf: 16179 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 16180 case KEYf: 16181 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 16182 if (ipbm_overlay) { 16183 p_fn_data = f_ent->extra_tcam.key; 16184 p_fn_mask = f_ent->extra_tcam.mask; 16185 } else 16186 #endif /* BCM_TRIDENT_SUPPORT */ 16187 #if defined(BCM_TRIDENT2_SUPPORT) 16188 if (SOC_IS_TD2_TT2(unit) && 16189 ((_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) && 16190 (f_ent->efp_key_match_type)) { 16191 p_fn_data = f_ent->key_match_tcam.key; 16192 p_fn_mask = f_ent->key_match_tcam.mask; 16193 } else 16194 #endif 16195 { 16196 p_fn_data = f_ent->tcam.key; 16197 p_fn_mask = f_ent->tcam.mask; 16198 } 16199 break; 16200 #ifdef BCM_FIREBOLT_SUPPORT 16201 case F4f: 16202 p_fn_data = &f_ent->tcam.f4; 16203 p_fn_mask = &f_ent->tcam.f4_mask; 16204 break; 16205 #endif /* BCM_FIREBOLT_SUPPORT */ 16206 default: 16207 LOG_ERROR(BSL_LS_BCM_FP, 16208 (BSL_META_U(unit, 16209 "FP(unit %d) Error: Bad TCAM field=%#05x\n"), 16210 unit, qi->fpf)); 16211 return (BCM_E_INTERNAL); 16212 }; 16213 16214 for (len = qi->width; len > 0; len -= 32) { 16215 if ((NULL == p_fn_data) || (NULL == p_fn_mask)) { 16216 /* 16217 * IPBM Overlay qualifier set in the group but 16218 * not qualified for this entry. 16219 */ 16220 p_data[idx] = 0x0; 16221 p_mask[idx] = 0x0; 16222 } else { 16223 if (bp) { 16224 p_data[idx] = (p_fn_data[wp] >> bp) & ((1 << (32 - bp)) - 1); 16225 /* coverity[ptr_arith : FALSE] */ 16226 p_mask[idx] = (p_fn_mask[wp] >> bp) & ((1 << (32 - bp)) - 1); 16227 if (len > (32-bp)) { 16228 wp++; 16229 p_data[idx] |= p_fn_data[wp] << (32 - bp); 16230 p_mask[idx] |= p_fn_mask[wp] << (32 - bp); 16231 } 16232 } else { 16233 p_data[idx] = p_fn_data[wp]; 16234 /* coverity[ptr_arith : FALSE] */ 16235 p_mask[idx] = p_fn_mask[wp++]; 16236 } 16237 } 16238 16239 if (len < 32) { 16240 p_data[idx] &= ((1 << len) - 1); 16241 p_mask[idx] &= ((1 << len) - 1); 16242 } 16243 16244 idx++; 16245 } 16246 16247 return (BCM_E_NONE); 16248 } 16249 16250 16251 /* 16252 * Function: 16253 * _bcm_field_qual_partial_data_get 16254 * Purpose: 16255 * Get a portion of a uint32 array 16256 * Parameters: 16257 * in_data - uint32 array 16258 * start_pos - starting bit postion in above array requested (base-0) 16259 * len - length of data requested (in bits) 16260 * out_data - uint32 array of in_data from start_pos to start_pos + len 16261 * Returns: 16262 * BCM_E_XXX 16263 * Notes: 16264 * - Calculate the word in in_data where start_pos occurs 16265 * - Calculate the bit position in above word where start_pos occurs 16266 * - Iterate: 16267 * - Get upper half of word (from bit position to end of word) 16268 * - Get remainder portion from next word 16269 * - If required: bit postion not 0 (start_pos not a multiple of 32) 16270 * - If present 16271 * - These two together form one word of out_data 16272 * - Go to next word. 16273 * - Mask the higher (extra) bits in last word of out_data 16274 * 16275 * - max_size is set to 16 (128 bits) as this is used for Ip6 and DstMac 16276 * - max_size is increased to 144 bits as this is used for bcmFieldQualifyL2PayLoad 16277 */ 16278 int 16279 _bcm_field_qual_partial_data_get(uint32 *in_data, uint8 start_pos, 16280 uint16 len, uint32 *out_data) 16281 { 16282 int current_word, bit_pos, result_word; 16283 int i; 16284 int max_size = 16; 16285 16286 /* Input parameters check. */ 16287 if ((NULL == in_data) || (NULL == out_data) || 16288 ((start_pos + len) > 256)) { 16289 return (BCM_E_UNAVAIL); 16290 } 16291 16292 current_word = start_pos / 32; 16293 bit_pos = start_pos - current_word * 32; 16294 16295 sal_memset(out_data, 0, max_size); 16296 16297 for (i = 0, result_word = 0; i < len; 16298 i += 32, current_word++, result_word++) { 16299 16300 out_data[result_word] = in_data[current_word] >> bit_pos; 16301 16302 if ((bit_pos != 0) && ((bit_pos + (len - i)) > 32)) { 16303 out_data[result_word] |= (in_data[current_word + 1] << (32 - bit_pos)); 16304 } 16305 } 16306 /* This check may be redundant as -1 = 0xffffffff */ 16307 if (i != len) { 16308 i -= 32; 16309 out_data[result_word - 1] &= ((1 << (len - i)) - 1); 16310 } 16311 return (BCM_E_NONE); 16312 } 16313 16314 /* 16315 * Function: 16316 * _bcm_field_qual_partial_data_set 16317 * Purpose: 16318 * Set a portion of a uint32 array 16319 * Parameters: 16320 * in_data - uint32 array 16321 * start_pos - starting bit postion in above array requested (base-0) 16322 * len - length of data requested (in bits) 16323 * out_data - uint32 array of in_data from start_pos to start_pos + len 16324 * Returns: 16325 * none 16326 * Notes: 16327 * - Calculate the word in out_data where start_pos occurs 16328 * - Calculate the bit position in above word where start_pos occurs 16329 * - Iterate: 16330 * - Or upper half of word (from bit position to end of word) 16331 * - Set remainder portion to the next word 16332 * - If required: bit postion not 0 (start_pos not a multiple of 32) 16333 * - If present 16334 * - These two together form one word of out_data 16335 * - Go to next word. 16336 * - Mask the higher (extra) bits in last word of out_data 16337 * 16338 * - max_size is set to 16 (128 bits) as this is used for Ip6 and DstMac 16339 * - max_size is increased to 144 bits as this is used for bcmFieldQualifyL2PayLoad 16340 * 16341 * NOTES 16342 * 1. Assumes that there are no extra bits in in_data, i.e. all of in_data is 16343 * copied. 16344 * 2. Assumes that out_data has been zeroed-out. 16345 */ 16346 int 16347 _bcm_field_qual_partial_data_set(uint32 *in_data, uint8 start_pos, 16348 uint16 len, uint32 *out_data) 16349 { 16350 int current_word, bit_pos, result_word; 16351 int i; 16352 16353 /* Input parameters check. */ 16354 if ((NULL == in_data) || (NULL == out_data) || 16355 ((start_pos + len) > 256)) { 16356 return (BCM_E_UNAVAIL); 16357 } 16358 16359 result_word = start_pos / 32; 16360 bit_pos = start_pos - result_word * 32; 16361 16362 for (i = 0, current_word= 0; i < len; 16363 i += 32, current_word++, result_word++) { 16364 16365 out_data[result_word] |= (in_data[current_word] << bit_pos); 16366 16367 if ((bit_pos != 0) && ((bit_pos + (len - i)) > 32)) { 16368 out_data[result_word + 1] |= (in_data[current_word] >> (32 - bit_pos)); 16369 } 16370 } 16371 16372 return (BCM_E_NONE); 16373 } 16374 16375 /* 16376 * Function: 16377 * _field_qual_part_value_get 16378 * 16379 * Purpose: 16380 * Get a qualifier field from the designated data and mask arrays. 16381 * 16382 * Parameters: 16383 * unit - (IN) BCM devices number 16384 * q_offset - (IN) Qualifier offset inside tcam. 16385 * f_ent - (IN) Field entry descriptor. 16386 * p_data - (IN) Inserted data. 16387 * p_mask - (IN) Data mask. 16388 * 16389 * Returns: 16390 * BCM_E_XXX 16391 */ 16392 STATIC int 16393 _field_qual_part_value_get(int unit, 16394 _bcm_field_qual_offset_t *q_offset, 16395 uint8 qual_part, 16396 _field_entry_t *f_ent, 16397 _bcm_field_qual_data_t p_data, 16398 _bcm_field_qual_data_t p_mask) 16399 { 16400 _qual_info_t qi; 16401 int rv; 16402 _bcm_field_qual_data_t data; 16403 _bcm_field_qual_data_t mask; 16404 int offset = 0, idx = 0; 16405 int ipbm_overlay = 0; 16406 16407 /* Input parameters check. */ 16408 if ((NULL == q_offset) || (NULL == f_ent) || 16409 (NULL == p_data) || (NULL == p_mask)) { 16410 return (BCM_E_PARAM); 16411 } 16412 16413 /* Primary offset handling. */ 16414 sal_memset(&qi, 0, sizeof(_qual_info_t)); 16415 16416 _FP_QUAL_DATA_CLEAR(data); 16417 _FP_QUAL_DATA_CLEAR(mask); 16418 qi.fpf = q_offset->field; 16419 qi.offset = q_offset->offset[qual_part]; 16420 qi.width = q_offset->width[qual_part]; 16421 /* calculate offset */ 16422 for (idx = 0; idx < qual_part; idx++) { 16423 offset += q_offset->width[idx]; 16424 } 16425 16426 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 16427 /* 16428 * 1. Check if the part goes into the IPBM TCAM. 16429 * 2. In slice Pairing mode, TCP control flag bits[5:0] are split between 16430 * IFP_PAIRING_IPBM_F0:TCP_FN_5_1[5:1] and IFP_PAIRING_F1:TCP_FN_0[0] 16431 * This special overlay case is handled here (1 == qual_part)... 16432 */ 16433 if ((((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit))) 16434 && SOC_IS_TD_TT(unit) && q_offset->secondary && 16435 ((qual_part == 0 && 1 != q_offset->width[0] && 5 != q_offset->width[1]) || 16436 (1 == qual_part && 1 == q_offset->width[0] && 5 == q_offset->width[1]))) 16437 || ((SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || SOC_IS_KATANAX(unit)) 16438 && q_offset->secondary)) { 16439 ipbm_overlay = 1; 16440 } 16441 #endif 16442 16443 /* Read qualifier information from tcam.. */ 16444 rv = _field_qual_value_get(unit, &qi, f_ent, data, mask, ipbm_overlay); 16445 BCM_IF_ERROR_RETURN(rv); 16446 16447 /* Split primary portion of the qualifier. */ 16448 rv = _bcm_field_qual_partial_data_set(data, offset, 16449 qi.width, p_data); 16450 BCM_IF_ERROR_RETURN(rv); 16451 rv = _bcm_field_qual_partial_data_set(mask, offset, 16452 qi.width, p_mask); 16453 BCM_IF_ERROR_RETURN(rv); 16454 16455 return (BCM_E_NONE); 16456 } 16457 16458 16459 /* 16460 * Function: 16461 * _bcm_field_qual_value_get 16462 * 16463 * Purpose: 16464 * Get a qualifier field from the designated data and mask arrays. 16465 * 16466 * Parameters: 16467 * unit - (IN) BCM devices number 16468 * q_offset - (IN) Qualifier offset inside tcam. 16469 * f_ent - (IN) Field entry descriptor. 16470 * p_data - (IN) Inserted data. 16471 * p_mask - (IN) Data mask. 16472 * 16473 * Returns: 16474 * BCM_E_XXX 16475 */ 16476 int 16477 _bcm_field_qual_value_get(int unit, _bcm_field_qual_offset_t *q_offset, 16478 _field_entry_t *f_ent, _bcm_field_qual_data_t p_data, 16479 _bcm_field_qual_data_t p_mask) 16480 { 16481 int rv, qual_part; 16482 16483 /* Input parameters check. */ 16484 if ((NULL == q_offset) || (NULL == f_ent) || 16485 (NULL == p_data) || (NULL == p_mask)) { 16486 return (BCM_E_PARAM); 16487 } 16488 16489 _FP_QUAL_DATA_CLEAR(p_data); 16490 _FP_QUAL_DATA_CLEAR(p_mask); 16491 16492 /* offset handling */ 16493 for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) { 16494 if (q_offset->width[qual_part] > 0) 16495 { 16496 rv = _field_qual_part_value_get(unit, q_offset, qual_part, 16497 f_ent, p_data, p_mask); 16498 BCM_IF_ERROR_RETURN(rv); 16499 } 16500 } 16501 16502 return (BCM_E_NONE); 16503 } 16504 16505 /* 16506 * Function: 16507 * _field_qual_part_value_set 16508 * 16509 * Purpose: 16510 * Set a qualifier field from the designated data and mask arrays. 16511 * 16512 * Parameters: 16513 * unit - (IN) BCM devices number 16514 * q_offset - (IN) Qualifier offset inside tcam. 16515 * qual_part - (IN) Split qualifier part. 16516 * f_ent - (IN) Field entry descriptor. 16517 * p_data - (IN) Inserted data. 16518 * p_mask - (IN) Data mask. 16519 * key_match_tcam - (IN) Flag to indicate which tcam to use 16520 * Returns: 16521 * BCM_E_XXX 16522 */ 16523 int 16524 _field_qual_part_value_set(int unit, _bcm_field_qual_offset_t *q_offset, 16525 uint8 qual_part, _field_entry_t *f_ent, 16526 uint32 *p_data, uint32 *p_mask, 16527 uint8 key_match_tcam) 16528 { 16529 uint32 data[_FP_QUAL_DATA_WORDS]; 16530 uint32 mask[_FP_QUAL_DATA_WORDS]; 16531 _qual_info_t qi; 16532 int offset = 0; 16533 int ipbm_overlay = 0; 16534 int rv, idx; 16535 16536 LOG_DEBUG(BSL_LS_BCM_FP, 16537 (BSL_META_U(unit, 16538 "_field_qual_part_value_set\n"))); 16539 LOG_DEBUG(BSL_LS_BCM_FP, 16540 (BSL_META_U(unit, 16541 "_field_qual_part_value_set:data:%x mask:%x\n"), 16542 *p_data, *p_mask)); 16543 16544 /* Input parameters check. */ 16545 if ((NULL == q_offset) || (NULL == f_ent) || 16546 (NULL == p_data) || (NULL == p_mask)) { 16547 return (BCM_E_PARAM); 16548 } 16549 16550 /* Primary offset handling. */ 16551 sal_memset(&qi, 0, sizeof(_qual_info_t)); 16552 qi.fpf = q_offset->field; 16553 qi.offset = q_offset->offset[qual_part]; 16554 qi.width = q_offset->width[qual_part]; 16555 /* calculate offset */ 16556 for (idx = 0; idx < qual_part; idx++) { 16557 offset += q_offset->width[idx]; 16558 } 16559 16560 /* Split primary portion of the qualifier. */ 16561 rv = _bcm_field_qual_partial_data_get (p_data, offset, 16562 qi.width, data); 16563 BCM_IF_ERROR_RETURN(rv); 16564 rv = _bcm_field_qual_partial_data_get(p_mask, offset, 16565 qi.width, mask); 16566 BCM_IF_ERROR_RETURN(rv); 16567 16568 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 16569 /* 16570 * 1. Check if the part goes into the IPBM TCAM. 16571 * 2. In slice Pairing mode, TCP control flag bits[5:0] are split between 16572 * IFP_PAIRING_IPBM_F0:TCP_FN_5_1[5:1] and IFP_PAIRING_F1:TCP_FN_0[0] 16573 * This special overlay case is handled here (1 == qual_part)... 16574 */ 16575 if ((((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit))) 16576 && SOC_IS_TD_TT(unit) && q_offset->secondary && 16577 ((qual_part == 0 && 1 != q_offset->width[0] && 5 != q_offset->width[1]) || 16578 (1 == qual_part && 1 == q_offset->width[0] && 5 == q_offset->width[1]))) 16579 || ((SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || SOC_IS_KATANAX(unit)) 16580 && q_offset->secondary)) { 16581 ipbm_overlay = 1; 16582 } 16583 #endif 16584 16585 /* Program qualifier into tcam.. */ 16586 rv = _field_qual_value_set(unit, &qi, f_ent, data, mask, 16587 ipbm_overlay, key_match_tcam); 16588 return (rv); 16589 } 16590 16591 /* 16592 * Function: 16593 * _field_entry_qualifier_key_get 16594 * 16595 * Purpose: 16596 * Get qualifier match value and mask. 16597 * 16598 * Parameters: 16599 * unit - BCM device number 16600 * entry - Entry id. 16601 * qual_id - qualifier id. 16602 * q_data - Qualifier data array. 16603 * q_mask - Qualifier mask array. 16604 * Returns: 16605 * Nothing. 16606 */ 16607 int 16608 _field_entry_qualifier_key_get(int unit, 16609 bcm_field_entry_t entry, 16610 int qual_id, 16611 _bcm_field_qual_data_t q_data, 16612 _bcm_field_qual_data_t q_mask) 16613 { 16614 uint8 entry_part; /* Tcam part number. */ 16615 uint8 entry_type; /* Index to tcam entries of 16616 multiple types */ 16617 _bcm_field_qual_offset_t *q_offset; /* Qualifier offset in the tcam. */ 16618 int qual_idx; /* Tcam part qualifiers iterator.*/ 16619 _field_entry_t *f_ent; /* Field entry structure. */ 16620 _bcm_field_group_qual_t *q_arr; /* Tcam part Qualifiers array. */ 16621 _field_group_t *fg; /* Field group structure. */ 16622 int rv; /* Operation return status. */ 16623 int free_tcam; /* Free tcam key flag. */ 16624 uint32 width; /* Offset width */ 16625 16626 _FP_QUAL_DATA_CLEAR(q_data); 16627 _FP_QUAL_DATA_CLEAR(q_mask); 16628 16629 q_offset = NULL; 16630 free_tcam = FALSE; 16631 16632 #if defined(BCM_TOMAHAWK_SUPPORT) 16633 if (soc_feature(unit, soc_feature_field_preselector_support) && 16634 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 16635 return _bcm_field_presel_qualifier_get(unit, entry, qual_id, 16636 q_data, q_mask); 16637 } 16638 #endif /* BCM_TOMAHAWK_SUPPORT */ 16639 16640 16641 /* Get entry part that contains requested qualifier. */ 16642 #if defined(BCM_TRIDENT2_SUPPORT) 16643 /* Search the entry by eid. */ 16644 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 16645 BCM_IF_ERROR_RETURN(rv); 16646 if (SOC_IS_TD2_TT2(unit) && 16647 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) { 16648 f_ent = NULL; 16649 rv = _bcm_field_efp_entry_qual_get(unit, entry, qual_id, &f_ent); 16650 } else 16651 #endif 16652 { 16653 f_ent = NULL; 16654 rv = _bcm_field_entry_qual_get(unit, entry, qual_id, &f_ent); 16655 } 16656 BCM_IF_ERROR_RETURN(rv); 16657 16658 fg = f_ent->group; 16659 16660 #if defined(BCM_TOMAHAWK_SUPPORT) 16661 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 16662 if ((fg->stage_id == _BCM_FIELD_STAGE_INGRESS) || 16663 (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) || 16664 (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 16665 return _bcm_field_th_entry_qualifier_key_get(unit, entry, qual_id, 16666 q_data, q_mask); 16667 } 16668 if (fg->stage_id == _BCM_FIELD_STAGE_CLASS) { 16669 return _bcm_field_th_class_entry_qualifier_key_get(unit, entry, 16670 qual_id, 16671 q_data, q_mask); 16672 } 16673 } 16674 #endif /* BCM_TOMAHAWK_SUPPORT */ 16675 16676 /* Get entry tcam part number. */ 16677 rv = _bcm_field_entry_flags_to_tcam_part (unit, f_ent->flags, 16678 fg, &entry_part); 16679 BCM_IF_ERROR_RETURN(rv); 16680 16681 /* Check if tcam data has to be freed at the end. */ 16682 if (NULL == f_ent->tcam.key) { 16683 free_tcam = TRUE; 16684 } 16685 16686 entry_type = _FP_ENTRY_TYPE_DEFAULT; 16687 16688 #if defined(BCM_TRIDENT2_SUPPORT) 16689 if (SOC_IS_TD2_TT2(unit) && 16690 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) { 16691 16692 if (f_ent->efp_key_match_type) { 16693 entry_type = _FP_ENTRY_TYPE_1; 16694 } else { 16695 entry_type = _FP_ENTRY_TYPE_0; 16696 } 16697 } 16698 #endif 16699 /* Get entry part qualifiers array. */ 16700 q_arr = &(fg->qual_arr[entry_type][entry_part]); 16701 16702 /* Search array by qualifier id to extract qualifier offsets in the tcam. */ 16703 for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) { 16704 if ((uint16)qual_id == q_arr->qid_arr[qual_idx]) { 16705 q_offset = q_arr->offset_arr + qual_idx; 16706 break; 16707 } 16708 } 16709 if (NULL == q_offset) { 16710 return (BCM_E_INTERNAL); 16711 } 16712 16713 /* Read tcam data/mask. */ 16714 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent); 16715 BCM_IF_ERROR_RETURN(rv); 16716 16717 /* There is no value associated with zero width qualifiers (Stage, Ip4 etc) 16718 */ 16719 /* MERGE-CHANGE */ 16720 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width); 16721 if (width > 0) { 16722 /* Read qualifier match value and mask. */ 16723 rv = _bcm_field_qual_value_get(unit, q_offset, f_ent, q_data, q_mask); 16724 } 16725 16726 if (free_tcam) { 16727 if (NULL != f_ent->tcam.key) { 16728 sal_free(f_ent->tcam.key); 16729 sal_free(f_ent->tcam.mask); 16730 } 16731 if (f_ent->flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 16732 if (NULL != f_ent->extra_tcam.key) { 16733 sal_free(f_ent->extra_tcam.key); 16734 sal_free(f_ent->extra_tcam.mask); 16735 } 16736 } 16737 f_ent->tcam.key = f_ent->tcam.mask = 16738 f_ent->extra_tcam.key = f_ent->extra_tcam.mask = NULL; 16739 16740 #if defined(BCM_TRIDENT2_SUPPORT) 16741 if (SOC_IS_TD2_TT2(unit) && 16742 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) { 16743 16744 if (NULL != f_ent->key_match_tcam.key) { 16745 sal_free(f_ent->key_match_tcam.key); 16746 sal_free(f_ent->key_match_tcam.mask); 16747 } 16748 f_ent->key_match_tcam.key = f_ent->key_match_tcam.mask = NULL; 16749 } 16750 #endif 16751 free_tcam = FALSE; 16752 } 16753 return (rv); 16754 } 16755 /* 16756 * Function: 16757 * _bcm_field_entry_qualifier_uint8_get 16758 * 16759 * Purpose: 16760 * Get qualifier match value and mask. 16761 * 16762 * Parameters: 16763 * unit - BCM device number 16764 * entry - Entry id. 16765 * qual_id - qualifier id. 16766 * data - Qualifier data. 16767 * mask - Qualifier mask. 16768 * Returns: 16769 * Nothing. 16770 */ 16771 int 16772 _bcm_field_entry_qualifier_uint8_get(int unit, bcm_field_entry_t entry, 16773 int qual_id, uint8 *data, 16774 uint8 *mask) 16775 { 16776 _bcm_field_qual_data_t q_data;/* Qualifier match data. */ 16777 _bcm_field_qual_data_t q_mask;/* Qualifier match mask. */ 16778 int rv; /* Operation return status. */ 16779 #if defined(BCM_TRIUMPH3_SUPPORT) 16780 esm_l3_protocol_fn_entry_t l3_proto_fn_entry; 16781 uint32 ip_proto, index; 16782 int idx_end; 16783 _bcm_field_qual_offset_t *q_offset; 16784 _field_entry_t *f_ent; 16785 #endif 16786 /* Input parameters check. */ 16787 if ((NULL == data) || (NULL == mask)) { 16788 return (BCM_E_PARAM); 16789 } 16790 16791 16792 FP_LOCK(unit); 16793 16794 rv = _field_entry_qualifier_key_get(unit, entry, qual_id, q_data, q_mask); 16795 16796 #if defined(BCM_TRIUMPH3_SUPPORT) 16797 if (SOC_IS_TRIUMPH3(unit) && 16798 (qual_id == bcmFieldQualifyIpProtocol) && 16799 BCM_SUCCESS(rv)) { 16800 16801 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 16802 16803 if (BCM_FAILURE(rv)) { 16804 FP_UNLOCK(unit); 16805 return rv; 16806 } 16807 16808 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 16809 16810 rv = _bcm_field_entry_qual_get(unit, entry, qual_id, &f_ent); 16811 if (BCM_FAILURE(rv)) { 16812 FP_UNLOCK(unit); 16813 return rv; 16814 } 16815 16816 rv = _field_qual_offset_get(unit, f_ent, qual_id, &q_offset); 16817 if (BCM_FAILURE(rv)) { 16818 FP_UNLOCK(unit); 16819 return rv; 16820 } 16821 16822 if (((q_offset->offset[0] == 132) || (q_offset->offset[0] == 4)) && 16823 (q_offset->width[0] == 4)) { 16824 /* For EXT_IP4 EXT_L2IP4 and EXT_IP6S ACL, L3_PROTOCOL_FN value from 16825 ESM_L3_PROTOCOL_FN table is treated as data to send it to 16826 external TCAM as key 16827 */ 16828 idx_end = soc_mem_index_max(unit, ESM_L3_PROTOCOL_FNm); 16829 for (index = 0; index < idx_end + 1; index++) { 16830 rv = soc_mem_read(unit, ESM_L3_PROTOCOL_FNm, 16831 MEM_BLOCK_ANY, index, &l3_proto_fn_entry); 16832 if (BCM_FAILURE(rv)) { 16833 FP_UNLOCK(unit); 16834 return rv; 16835 } 16836 16837 ip_proto = soc_mem_field32_get(unit, ESM_L3_PROTOCOL_FNm, &l3_proto_fn_entry, 16838 L3_PROTOCOL_FNf); 16839 if (ip_proto == (q_data[0] & 0xf)) { 16840 q_data[0] = index; 16841 q_mask[0] = 0xff; 16842 break; 16843 } 16844 } 16845 } 16846 } 16847 } 16848 #endif 16849 16850 FP_UNLOCK(unit); 16851 16852 if (BCM_SUCCESS(rv)) { 16853 *data = (uint8)(q_data[0] & 0xff); 16854 *mask = (uint8)(q_mask[0] & 0xff); 16855 } 16856 return (rv); 16857 } 16858 16859 /* 16860 * Function: 16861 * _bcm_field_entry_qualifier_uint16_get 16862 * 16863 * Purpose: 16864 * Get qualifier match value and mask. 16865 * 16866 * Parameters: 16867 * unit - BCM device number 16868 * entry - Entry id. 16869 * qual_id - qualifier id. 16870 * data - Qualifier data. 16871 * mask - Qualifier mask. 16872 * Returns: 16873 * Nothing. 16874 */ 16875 int 16876 _bcm_field_entry_qualifier_uint16_get(int unit, bcm_field_entry_t entry, 16877 int qual_id, uint16 *data, 16878 uint16 *mask) 16879 { 16880 _bcm_field_qual_data_t q_data;/* Qualifier match data. */ 16881 _bcm_field_qual_data_t q_mask;/* Qualifier match mask. */ 16882 int rv; /* Operation return status. */ 16883 /* Input parameters check. */ 16884 if ((NULL == data) || (NULL == mask)) { 16885 return (BCM_E_PARAM); 16886 } 16887 16888 16889 FP_LOCK(unit); 16890 16891 rv = _field_entry_qualifier_key_get(unit, entry, qual_id, q_data, q_mask); 16892 16893 FP_UNLOCK(unit); 16894 16895 if (BCM_SUCCESS(rv)) { 16896 *data = (uint16)(q_data[0] & 0xffff); 16897 *mask = (uint16)(q_mask[0] & 0xffff); 16898 } 16899 return (rv); 16900 } 16901 16902 /* 16903 * Function: 16904 * _bcm_field_entry_qualifier_uint32_get 16905 * 16906 * Purpose: 16907 * Get qualifier match value and mask. 16908 * 16909 * Parameters: 16910 * unit - BCM device number 16911 * entry - Entry id. 16912 * qual_id - qualifier id. 16913 * data - Qualifier data. 16914 * mask - Qualifier mask. 16915 * Returns: 16916 * Nothing. 16917 */ 16918 int 16919 _bcm_field_entry_qualifier_uint32_get(int unit, bcm_field_entry_t entry, 16920 int qual_id, uint32 *data, 16921 uint32 *mask) 16922 { 16923 _bcm_field_qual_data_t q_data;/* Qualifier match data. */ 16924 _bcm_field_qual_data_t q_mask;/* Qualifier match mask. */ 16925 int rv; /* Operation return status. */ 16926 16927 /* Input parameters check. */ 16928 if ((NULL == data) || (NULL == mask)) { 16929 return (BCM_E_PARAM); 16930 } 16931 16932 16933 FP_LOCK(unit); 16934 16935 rv = _field_entry_qualifier_key_get(unit, entry, qual_id, q_data, q_mask); 16936 16937 FP_UNLOCK(unit); 16938 16939 if (BCM_SUCCESS(rv)) { 16940 *data = q_data[0]; 16941 *mask = q_mask[0]; 16942 } 16943 return (rv); 16944 } 16945 16946 /* 16947 * Function: 16948 * _bcm_field_entry_qualifier_uint64_get 16949 * 16950 * Purpose: 16951 * Get qualifier match value and mask. 16952 * 16953 * Parameters: 16954 * unit - BCM device number 16955 * entry - Entry id. 16956 * qual_id - qualifier id. 16957 * data - Qualifier data. 16958 * mask - Qualifier mask. 16959 * Returns: 16960 * BCM_E_XXX. 16961 */ 16962 int 16963 _bcm_field_entry_qualifier_uint64_get(int unit, bcm_field_entry_t entry, 16964 int qual_id, uint64 *data, 16965 uint64 *mask) 16966 { 16967 _bcm_field_qual_data_t q_data;/* Qualifier match data. */ 16968 _bcm_field_qual_data_t q_mask;/* Qualifier match mask. */ 16969 int rv; /* Operation return status. */ 16970 16971 /* Input parameters check. */ 16972 if ((NULL == data) || (NULL == mask)) { 16973 return (BCM_E_PARAM); 16974 } 16975 16976 16977 FP_LOCK(unit); 16978 16979 rv = _field_entry_qualifier_key_get(unit, entry, qual_id, q_data, q_mask); 16980 16981 FP_UNLOCK(unit); 16982 16983 if (BCM_SUCCESS(rv)) { 16984 COMPILER_64_SET(*data, q_data[1], q_data[0]); 16985 COMPILER_64_SET(*mask, q_mask[1], q_mask[0]); 16986 } 16987 return (rv); 16988 } 16989 16990 16991 /* 16992 * Function: 16993 * _bcm_field_qual_value_set 16994 * 16995 * Purpose: 16996 * Set a qualifier field from the designated data and mask arrays. 16997 * 16998 * Parameters: 16999 * unit - (IN) BCM devices number 17000 * q_offset - (IN) Qualifier offset inside tcam. 17001 * f_ent - (IN) Field entry descriptor. 17002 * p_data - (IN) Inserted data. 17003 * p_mask - (IN) Data mask. 17004 * 17005 * Returns: 17006 * BCM_E_XXX 17007 */ 17008 int 17009 _bcm_field_qual_value_set(int unit, _bcm_field_qual_offset_t *q_offset, 17010 _field_entry_t *f_ent, 17011 uint32 *p_data, uint32 *p_mask) 17012 { 17013 int rv; 17014 uint8 qual_part; 17015 17016 LOG_DEBUG(BSL_LS_BCM_FP, 17017 (BSL_META_U(unit, 17018 "_bcm_field_qual_value_set\n"))); 17019 17020 /* Input parameters check. */ 17021 if ((NULL == q_offset) || (NULL == f_ent) || 17022 (NULL == p_data) || (NULL == p_mask)) { 17023 return (BCM_E_PARAM); 17024 } 17025 17026 /* Primary offset handling. */ 17027 for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) { 17028 if (q_offset->width[qual_part] > 0) 17029 { 17030 rv = _field_qual_part_value_set(unit, q_offset, qual_part, f_ent, 17031 p_data, p_mask, 0); 17032 BCM_IF_ERROR_RETURN(rv); 17033 } 17034 } 17035 17036 return (BCM_E_NONE); 17037 } 17038 17039 /* 17040 * Function: 17041 * _bcm_field_qual_value_set_by_entry_type 17042 * 17043 * Purpose: 17044 * Set a qualifier field from the designated data and mask arrays in the 17045 * tcam of the given index. 17046 * 17047 * Parameters: 17048 * unit - (IN) BCM devices number 17049 * q_offset - (IN) Qualifier offset inside tcam. 17050 * f_ent - (IN) Field entry descriptor. 17051 * p_data - (IN) Inserted data. 17052 * p_mask - (IN) Data mask. 17053 * entry_type - (IN) Index of the tcam entry 17054 * 17055 * Returns: 17056 * BCM_E_XXX 17057 */ 17058 17059 int 17060 _bcm_field_qual_value_set_by_entry_type(int unit, 17061 _bcm_field_qual_offset_t *q_offset, 17062 _field_entry_t *f_ent, 17063 uint32 *p_data, 17064 uint32 *p_mask, 17065 uint8 entry_type) 17066 { 17067 uint8 qual_part; 17068 17069 LOG_DEBUG(BSL_LS_BCM_FP, 17070 (BSL_META_U(unit, 17071 "_bcm_field_qual_value_set_by_index\n"))); 17072 17073 /* Input parameters check. */ 17074 if ((NULL == q_offset) || (NULL == f_ent) || 17075 (NULL == p_data) || (NULL == p_mask)) { 17076 return (BCM_E_PARAM); 17077 } 17078 17079 /* Primary offset handling. */ 17080 for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) { 17081 if (q_offset->width[qual_part] > 0) 17082 { 17083 BCM_IF_ERROR_RETURN 17084 (_field_qual_part_value_set(unit, q_offset, qual_part, f_ent, 17085 p_data, p_mask, entry_type)); 17086 } 17087 } 17088 17089 return (BCM_E_NONE); 17090 } 17091 17092 /* 17093 * Function: 17094 * _bcm_field_group_stage_get 17095 * 17096 * Purpose: 17097 * Extract group pipeline stage from qualifiers set. 17098 * 17099 * Parameters: 17100 * unit - (IN)BCM device number. 17101 * qset_p - (IN)Group qualifiers set. 17102 * stage - (OUT)Pipeline stage id. 17103 * 17104 * Returns: 17105 * BCM_E_XXX 17106 */ 17107 int 17108 _bcm_field_group_stage_get(int unit, bcm_field_qset_t *qset_p, 17109 _field_stage_id_t *stage) 17110 { 17111 int stage_count = 0; /* Check that only 1 stage specified in qset */ 17112 17113 /* Input parameters check. */ 17114 if ((NULL == qset_p) || (NULL == stage)) { 17115 return (BCM_E_PARAM); 17116 } 17117 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 17118 /* Set stage based on qualifiers set. */ 17119 if (soc_feature(unit, soc_feature_field_multi_stage)) { 17120 if(BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageIngress)) { 17121 *stage = _BCM_FIELD_STAGE_INGRESS; 17122 stage_count++; 17123 } 17124 if(BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageEgress)) { 17125 *stage = _BCM_FIELD_STAGE_EGRESS; 17126 stage_count++; 17127 } 17128 17129 if(BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageLookup)) { 17130 *stage = _BCM_FIELD_STAGE_LOOKUP; 17131 stage_count++; 17132 } 17133 } 17134 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 17135 17136 if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageExternal)) { 17137 *stage = _BCM_FIELD_STAGE_EXTERNAL; 17138 stage_count++; 17139 } 17140 17141 #if defined(BCM_TOMAHAWK_SUPPORT) 17142 if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageClass)) { 17143 *stage = _BCM_FIELD_STAGE_CLASS; 17144 stage_count++; 17145 } 17146 if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageClassExactMatch)) { 17147 *stage = _BCM_FIELD_STAGE_CLASS; 17148 stage_count++; 17149 } 17150 if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageIngressExactMatch)) { 17151 *stage = _BCM_FIELD_STAGE_EXACTMATCH; 17152 stage_count++; 17153 } 17154 #endif /* BCM_TOMAHAWK_SUPPORT */ 17155 17156 #if defined(BCM_FLOWTRACKER_SUPPORT) 17157 if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageIngressFlowtracker)) { 17158 *stage = _BCM_FIELD_STAGE_FLOWTRACKER; 17159 stage_count++; 17160 } 17161 #endif 17162 17163 if (stage_count == 0) { 17164 /* Default to ingress. */ 17165 *stage = _BCM_FIELD_STAGE_INGRESS; 17166 stage_count++; 17167 } 17168 17169 if (stage_count > 1) { 17170 LOG_ERROR(BSL_LS_BCM_FP, 17171 (BSL_META_U(unit, 17172 "FP(unit %d) Error: More than one pipeline stage was specified.\n"), 17173 unit)); 17174 return (BCM_E_PARAM); 17175 } 17176 17177 return (BCM_E_NONE); 17178 } 17179 17180 /* 17181 * Function: 17182 * _bcm_field_group_stage_validate 17183 * 17184 * Purpose: 17185 * Validate group pipeline stage. 17186 * 17187 * Parameters: 17188 * unit - (IN)BCM device number. 17189 * stage - (IN)Pipeline stage id. 17190 * 17191 * Returns: 17192 * BCM_E_XXX 17193 */ 17194 int 17195 _bcm_field_group_stage_validate(int unit, _field_stage_id_t stage) 17196 { 17197 int rv = BCM_E_NONE; 17198 if (soc_feature(unit, soc_feature_no_ifp) && 17199 _BCM_FIELD_STAGE_INGRESS == stage) { 17200 rv = BCM_E_UNAVAIL; 17201 } 17202 if (soc_feature(unit, soc_feature_no_ifp) && 17203 _BCM_FIELD_STAGE_CLASS == stage) { 17204 rv = BCM_E_UNAVAIL; 17205 } 17206 if (soc_feature(unit, soc_feature_no_vfp) && 17207 _BCM_FIELD_STAGE_LOOKUP == stage) { 17208 rv = BCM_E_UNAVAIL; 17209 } 17210 if (soc_feature(unit, soc_feature_no_efp) && 17211 _BCM_FIELD_STAGE_EGRESS == stage) { 17212 rv = BCM_E_UNAVAIL; 17213 } 17214 if (BCM_FAILURE(rv)) { 17215 LOG_DEBUG(BSL_LS_BCM_FP, 17216 (BSL_META_U(unit, 17217 "FP(unit %d) Verb: stage %d is not supported.\n"), 17218 unit, stage)); 17219 } 17220 return rv; 17221 } 17222 17223 /* 17224 * Function: 17225 * _bcm_field_data_qualifier_free 17226 * 17227 * Purpose: 17228 * Free data qualifier descriptor structure. 17229 * 17230 * Parameters: 17231 * unit - (IN) BCM device number. 17232 * qual - (OUT)Qualifier strusture. 17233 * 17234 * Returns: 17235 * BCM_E_XXX 17236 */ 17237 int 17238 _bcm_field_data_qualifier_free(int unit, _field_data_qualifier_t *qual) 17239 { 17240 /* Input parameters check. */ 17241 if (NULL == qual) { 17242 return (BCM_E_PARAM); 17243 } 17244 17245 /* Free data offset structure. */ 17246 if (NULL != qual->spec) { 17247 sal_free(qual->spec); 17248 } 17249 17250 /* Free data qualifier structure. */ 17251 sal_free(qual); 17252 17253 return (BCM_E_NONE); 17254 } 17255 17256 17257 /* 17258 * Function: 17259 * _field_data_qualifier_bmap_alloc 17260 * 17261 * Purpose: 17262 * Allocate hw resources for data qualifier installation 17263 * Parameters: 17264 * Parameters: 17265 * unit - (IN) BCM device number. 17266 * stage_fc - (IN) Stage field control. 17267 * f_dq - (IN) Field data qualifier descriptor. 17268 * idx_low - (IN) Lower boundary. 17269 * idx_hi - (IN) Upper boundary. 17270 * 17271 * Returns: 17272 * BCM_E_XXX 17273 */ 17274 17275 STATIC int 17276 _field_data_qualifier_bmap_alloc(int unit, 17277 _field_stage_t *stage_fc, 17278 _field_data_qualifier_t *f_dq, 17279 uint8 idx_low, uint8 idx_hi) 17280 { 17281 int idx; /* Data qualifier word iterator. */ 17282 int elem_count; /* Number of elements allocated. */ 17283 int temp_elem_count = 0; /* Number of elements allocated. */ 17284 uint32 *usage_bmap; /* Offset usage bitmap. */ 17285 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 17286 /* Valid HW offsets for FPF1.9 and FPF3.9 */ 17287 SHR_BITDCL udf1_hw_offsets; 17288 #endif /* !BCM_TRIDENT_SUPPORT or BCM_KATANA_SUPPORT or BCM_ENDURO_SUPPORT */ 17289 17290 /* Input parameters check. */ 17291 if ((NULL == f_dq) || (NULL == stage_fc) || 17292 (idx_low > 31) || (idx_hi > 31)) { 17293 return (BCM_E_PARAM); 17294 } 17295 17296 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 17297 memset(&udf1_hw_offsets, 0x0, sizeof(udf1_hw_offsets)); 17298 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit)) { 17299 /* set UDF1.1 for FPF3.9 - {0 0 1 1 0 0 0 0} */ 17300 SHR_BITSET(&udf1_hw_offsets, 0x2); 17301 SHR_BITSET(&udf1_hw_offsets, 0x3); 17302 /* set UDF1.3 for FPF1.9 - {0 0 0 0 0 0 1 1} */ 17303 SHR_BITSET(&udf1_hw_offsets, 0x6); 17304 SHR_BITSET(&udf1_hw_offsets, 0x7); 17305 } else if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) || 17306 SOC_IS_GREYHOUND(unit) || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) 17307 || SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND2(unit)) { 17308 /* set UDF1.1 for FPF3.9 - {0 1 0 0} 1st bit Position */ 17309 SHR_BITSET(&udf1_hw_offsets, 0x1); 17310 /* set UDF1.3 for FPF1.9 - {0 0 0 1} 3rd bit Position */ 17311 SHR_BITSET(&udf1_hw_offsets, 0x3); 17312 } 17313 #endif /* !BCM_TRIDENT_SUPPORT or BCM_KATANA_SUPPORT or BCM_ENDURO_SUPPORT */ 17314 17315 elem_count = 0; 17316 usage_bmap = &stage_fc->data_ctrl->usage_bmap; 17317 for (idx = idx_low; idx <= idx_hi; idx++) { 17318 if (0 == ((*usage_bmap) & (1 << idx))) { 17319 elem_count++; 17320 } 17321 } 17322 17323 if (elem_count >= f_dq->elem_count) { 17324 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 17325 if ((SOC_IS_TD_TT(unit) 17326 || SOC_IS_KATANAX(unit) 17327 || SOC_IS_TRIUMPH3(unit) 17328 || SOC_IS_ENDURO(unit) 17329 || SOC_IS_HURRICANEX(unit) 17330 || SOC_IS_GREYHOUND(unit) 17331 || SOC_IS_TRIUMPH2(unit) 17332 || SOC_IS_APOLLO(unit) 17333 || SOC_IS_VALKYRIE2(unit) 17334 || SOC_IS_GREYHOUND2(unit)) 17335 && !(f_dq->flags & BCM_FIELD_DATA_QUALIFIER_STAGE_LOOKUP)) { 17336 /* Check if index is in UDF1 range (0 - 7) */ 17337 if (((idx_low == 0) 17338 && (idx_hi <= (stage_fc->data_ctrl->num_elems - 1))) 17339 && (f_dq->elem_count > 0 && f_dq->elem_count <= 4)) { 17340 17341 /* Get number of requested elements. */ 17342 elem_count = f_dq->elem_count; 17343 17344 /* Check if requested count of elements are available */ 17345 for (idx = idx_low; ((idx <= idx_hi) && elem_count); idx++) { 17346 /* We check the upper limit of idx_hi and idx_low 17347 in the beginning of the function */ 17348 /* coverity[ptr_arith] */ 17349 if (SHR_BITGET(&udf1_hw_offsets, idx) == 0) { 17350 continue; 17351 } 17352 17353 if (0 == ((*usage_bmap) & (1 << idx))) { 17354 elem_count--; 17355 } 17356 } 17357 17358 /* 17359 * If elem_count is zero, required no. of elements are 17360 * available. 17361 */ 17362 if (0 == elem_count) { 17363 elem_count = f_dq->elem_count; 17364 /* Reserve the indices */ 17365 for (idx = idx_hi; ((idx >= idx_low) && elem_count); idx--) { 17366 /* We check the upper limit of idx_hi and idx_low 17367 in the beginning of the function */ 17368 /* coverity[ptr_arith] */ 17369 if (SHR_BITGET(&udf1_hw_offsets, idx) == 0) { 17370 continue; 17371 } 17372 17373 if (0 == ((*usage_bmap) & (1 << idx))) { 17374 f_dq->hw_bmap |= (1 << idx); 17375 (*usage_bmap) |= (1 << idx); 17376 elem_count--; 17377 } 17378 } 17379 return (BCM_E_NONE); 17380 } 17381 } else if((idx_low == 0) 17382 && (idx_hi == ((stage_fc->data_ctrl->num_elems * 2) - 1))) { 17383 /* When both UDF1 & UDF 2 are required 17384 * Try to fill from UDF2 followed by 17385 * UDF1 specical chunks(0,1,4,5) for more flexibilty and 17386 * then from the remaining UDF1 chunks(2,3,6,7) */ 17387 temp_elem_count = f_dq->elem_count; 17388 for (idx = stage_fc->data_ctrl->num_elems; 17389 ((idx <= idx_hi) && temp_elem_count); idx++) { 17390 if (0 == ((*usage_bmap) & (1 << idx))) { 17391 f_dq->hw_bmap |= (1 << idx); 17392 (*usage_bmap) |= (1 << idx); 17393 temp_elem_count--; 17394 } 17395 } 17396 for (idx = stage_fc->data_ctrl->num_elems - 1 ; 17397 ((idx >= idx_low) && temp_elem_count); idx--) { 17398 /* We check the upper limit of idx_hi and idx_low 17399 in the beginning of the function */ 17400 /* coverity[ptr_arith] */ 17401 if (SHR_BITGET(&udf1_hw_offsets, idx) == 0) { 17402 continue; 17403 } 17404 17405 if (0 == ((*usage_bmap) & (1 << idx))) { 17406 f_dq->hw_bmap |= (1 << idx); 17407 (*usage_bmap) |= (1 << idx); 17408 temp_elem_count--; 17409 } 17410 } 17411 temp_elem_count = f_dq->elem_count - temp_elem_count; 17412 } 17413 } 17414 #endif /* !BCM_TRIDENT_SUPPORT or BCM_KATANA_SUPPORT or BCM_ENDURO_SUPPORT */ 17415 17416 elem_count = f_dq->elem_count - temp_elem_count; 17417 for (idx = idx_low; ((idx <= idx_hi) && elem_count); idx++) { 17418 if (0 == ((*usage_bmap) & (1 << idx))) { 17419 f_dq->hw_bmap |= (1 << idx); 17420 (*usage_bmap) |= (1 << idx); 17421 elem_count--; 17422 } 17423 } 17424 return (BCM_E_NONE); 17425 } 17426 return (BCM_E_RESOURCE); 17427 } 17428 17429 /* 17430 * Function: 17431 * _field_data_qualifier_hw_alloc 17432 * 17433 * Purpose: 17434 * Allocate hw resources for data qualifier installation 17435 * 17436 * Parameters: 17437 * unit - (IN) BCM device number. 17438 * stage_fc - (IN) Stage field control. 17439 * f_dq - (IN) Field data qualifier descriptor. 17440 * Returns: 17441 * BCM_E_XXX 17442 */ 17443 17444 STATIC int 17445 _field_data_qualifier_hw_alloc(int unit, 17446 _field_stage_t *stage_fc, 17447 _field_data_qualifier_t *f_dq) 17448 { 17449 int rv; /* Operation return status. */ 17450 17451 /* Input parameters check. */ 17452 if ((NULL == f_dq) || (NULL == stage_fc)) { 17453 return (BCM_E_PARAM); 17454 } 17455 17456 #if defined(BCM_TOMAHAWK_SUPPORT) 17457 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 17458 return _bcm_field_th_data_qualifier_hw_alloc(unit, stage_fc, f_dq); 17459 } 17460 #endif 17461 #if defined(BCM_TRIDENT2_SUPPORT) 17462 if (SOC_IS_TD2_TT2(unit) && 17463 f_dq->flags & BCM_FIELD_DATA_QUALIFIER_OFFSET_FLEX_HASH) { 17464 /* flex hash uses UDF2_OFFSET4 to UDF2_OFFSET7 */ 17465 rv = _field_data_qualifier_bmap_alloc 17466 (unit, stage_fc, f_dq, 12, ((2 * stage_fc->data_ctrl->num_elems) - 1)); 17467 if (BCM_FAILURE(rv)) { 17468 return (BCM_E_FAIL); 17469 } 17470 return BCM_E_NONE; 17471 } 17472 #endif 17473 17474 /* First try to allocate with single udf */ 17475 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT) 17476 if ((SOC_IS_TD_TT(unit) 17477 || SOC_IS_KATANAX(unit) 17478 || SOC_IS_TRIUMPH3(unit) 17479 || SOC_IS_ENDURO(unit) 17480 || SOC_IS_HURRICANEX(unit) 17481 || SOC_IS_GREYHOUND2(unit)) 17482 && !(f_dq->flags & BCM_FIELD_DATA_QUALIFIER_STAGE_LOOKUP) 17483 && (f_dq->elem_count > 4)) { 17484 /* Try UDF 2 followed by UDF 1*/ 17485 rv = _field_data_qualifier_bmap_alloc 17486 (unit, stage_fc, f_dq, stage_fc->data_ctrl->num_elems, 17487 stage_fc->data_ctrl->num_elems * 2 - 1); 17488 17489 if (BCM_SUCCESS(rv)) { 17490 return (BCM_E_NONE); 17491 } 17492 rv = _field_data_qualifier_bmap_alloc 17493 (unit, stage_fc, f_dq, 0, stage_fc->data_ctrl->num_elems - 1); 17494 17495 if (BCM_SUCCESS(rv)) { 17496 return (BCM_E_NONE); 17497 } 17498 } else 17499 #endif 17500 { 17501 rv = _field_data_qualifier_bmap_alloc 17502 (unit, stage_fc, f_dq, 0, stage_fc->data_ctrl->num_elems - 1); 17503 17504 if (BCM_SUCCESS(rv)) { 17505 return (BCM_E_NONE); 17506 } 17507 rv = _field_data_qualifier_bmap_alloc 17508 (unit, stage_fc, f_dq, stage_fc->data_ctrl->num_elems, 17509 stage_fc->data_ctrl->num_elems * 2 - 1); 17510 17511 if (BCM_SUCCESS(rv)) { 17512 return (BCM_E_NONE); 17513 } 17514 } 17515 17516 /* Need 2 udfs to insert the qualifier. */ 17517 rv = _field_data_qualifier_bmap_alloc 17518 (unit, stage_fc, f_dq, 0, stage_fc->data_ctrl->num_elems * 2 - 1); 17519 17520 return (rv); 17521 } 17522 17523 /* 17524 * Function: 17525 * _bcm_field_data_qualifier_alloc 17526 * 17527 * Purpose: 17528 * Allocate data qualifier descriptor structure. 17529 * 17530 * Parameters: 17531 * unit - (IN) BCM device number. 17532 * qual - (OUT)Qualifier strusture. 17533 * 17534 * Returns: 17535 * BCM_E_XXX 17536 */ 17537 17538 int 17539 _bcm_field_data_qualifier_alloc(int unit, _field_data_qualifier_t **qual) 17540 { 17541 int mem_sz; /* Allocated memory size. */ 17542 _field_data_qualifier_p f_dq;/* Data qualifier pointer. */ 17543 17544 /* Input parameters check. */ 17545 if (NULL == qual) { 17546 return (BCM_E_PARAM); 17547 } 17548 17549 /* Allocate field data qualifier structure. */ 17550 mem_sz = sizeof(_field_data_qualifier_t); 17551 f_dq = sal_alloc(mem_sz, "Data qualifier"); 17552 if (NULL == f_dq) { 17553 return (BCM_E_MEMORY); 17554 } 17555 sal_memset(f_dq, 0, mem_sz); 17556 17557 /* Allocate offsets spec required for qualifier. */ 17558 mem_sz = sizeof(bcm_field_udf_spec_t); 17559 f_dq->spec = sal_alloc(mem_sz, "Data spec"); 17560 if (NULL == f_dq->spec) { 17561 sal_free(f_dq); 17562 return (BCM_E_MEMORY); 17563 } 17564 sal_memset(f_dq->spec->offset, 0xff, sizeof(f_dq->spec->offset)); 17565 *qual = f_dq; 17566 17567 return (BCM_E_NONE); 17568 } 17569 17570 17571 /* 17572 * Function: 17573 * _field_stage_data_ctrl_init 17574 * 17575 * Purpose: 17576 * Allocate and initialize data qualifiers control structure. 17577 * 17578 * Parameters: 17579 * unit - (IN) BCM unit 17580 * stage_fc - (IN/OUT) Stage to be initialize. 17581 * Returns: 17582 * BCM_E_XXX 17583 */ 17584 STATIC int 17585 _field_stage_data_ctrl_init(int unit, _field_stage_t *stage_fc) 17586 { 17587 int mem_sz; 17588 _field_data_control_t *data_ctrl = NULL; 17589 17590 /* Input parameters check. */ 17591 if (NULL == stage_fc) { 17592 return (BCM_E_PARAM); 17593 } 17594 17595 /* Allocate data control structure. */ 17596 mem_sz = sizeof(_field_data_control_t); 17597 _FP_XGS3_ALLOC(data_ctrl, mem_sz, 17598 "Data qualification control"); 17599 if (NULL == data_ctrl) { 17600 return (BCM_E_MEMORY); 17601 } 17602 17603 #if defined(BCM_TRIUMPH2_SUPPORT) 17604 if (SOC_MEM_IS_VALID(unit, FP_UDF_TCAMm)) { 17605 mem_sz = sizeof (_field_data_tcam_entry_t) * 17606 soc_mem_index_count(unit, FP_UDF_TCAMm); 17607 _FP_XGS3_ALLOC(data_ctrl->tcam_entry_arr, mem_sz, 17608 "Udf tcam entry array."); 17609 if (NULL == data_ctrl->tcam_entry_arr) { 17610 sal_free (data_ctrl); 17611 return (BCM_E_MEMORY); 17612 } 17613 } 17614 #endif /* BCM_TRIUMPH2_SUPPORT */ 17615 17616 if (SOC_MEM_FIELD_VALID(unit, FP_UDF_OFFSETm, UDF1_OFFSET4f)) { 17617 data_ctrl->elem_size = 2; 17618 data_ctrl->num_elems = 8; 17619 } else { 17620 data_ctrl->elem_size = 4; 17621 data_ctrl->num_elems = 4; 17622 } 17623 17624 stage_fc->data_ctrl = data_ctrl; 17625 return (BCM_E_NONE); 17626 } 17627 17628 /* 17629 * Function: 17630 * _field_stage_external_data_ctrl_init 17631 * 17632 * Purpose: 17633 * Allocate and initialize external data qualifiers control structure. 17634 * 17635 * Parameters: 17636 * unit - (IN) BCM unit 17637 * stage_fc - (IN/OUT) Stage to be initialize. 17638 * Returns: 17639 * BCM_E_XXX 17640 */ 17641 STATIC int 17642 _field_stage_external_data_ctrl_init(int unit, _field_control_t *fc) 17643 { 17644 _field_stage_t *stage_ingress, *stage_external, *stage_p; 17645 17646 stage_external = stage_ingress = NULL; 17647 stage_p = fc->stages; 17648 17649 while (stage_p) { 17650 if (stage_p->stage_id == _BCM_FIELD_STAGE_INGRESS) { 17651 stage_ingress = stage_p; 17652 } else if (stage_p->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 17653 stage_external = stage_p; 17654 } 17655 stage_p = stage_p->next; 17656 } 17657 17658 if ((stage_ingress == NULL) || (stage_external == NULL)) { 17659 return (BCM_E_INTERNAL); 17660 } 17661 17662 stage_external->data_ctrl = stage_ingress->data_ctrl; 17663 return (BCM_E_NONE); 17664 } 17665 17666 /* 17667 * Function: 17668 * _field_data_qualifier_destroy 17669 * Purpose: 17670 * Destroy a data/offset based qualifier. 17671 * Parameters: 17672 * unit - (IN) Bcm device number. 17673 * qid - (IN) Data qualifier id. 17674 * 17675 * Returns: 17676 * BCM_E_XXX 17677 */ 17678 int 17679 _bcm_field_data_qualifier_destroy(int unit, int qid) 17680 { 17681 _field_data_qualifier_t *f_dq;/* Internal data qualifier descriptor. */ 17682 _field_data_qualifier_t *f_dq_prev;/* Prev data qualifier descriptor.*/ 17683 _field_stage_t *stage_fc; /* Stage field control. */ 17684 int rv; 17685 17686 #if defined (BCM_TRIUMPH2_SUPPORT) 17687 if (soc_feature(unit, soc_feature_udf_support) && UDF_CTRL(unit)) { 17688 if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_UDF_MODULE) { 17689 LOG_CLI((BSL_META("Udf resource is used by UDF module. \n"))); 17690 return (BCM_E_RESOURCE); 17691 } 17692 } 17693 #endif 17694 17695 /* Get stage field control structure. */ 17696 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 17697 BCM_IF_ERROR_RETURN(rv); 17698 17699 f_dq_prev = f_dq = stage_fc->data_ctrl->data_qual; 17700 while (NULL != f_dq) { 17701 if (f_dq->qid == qid) { 17702 /* Free used offset words bitmap. */ 17703 stage_fc->data_ctrl->usage_bmap &= ~f_dq->hw_bmap; 17704 17705 /* Remove qualifier from qualifiers linked list. */ 17706 if (f_dq == f_dq_prev) { 17707 stage_fc->data_ctrl->data_qual = f_dq->next; 17708 } else { 17709 f_dq_prev->next = f_dq->next; 17710 } 17711 /* Free qualifieer allocated memory. */ 17712 BCM_IF_ERROR_RETURN(_bcm_field_data_qualifier_free(unit, f_dq)); 17713 17714 #if defined (BCM_TRIUMPH2_SUPPORT) 17715 if (soc_feature(unit, soc_feature_udf_support) && UDF_CTRL(unit)) { 17716 UDF_LOCK(unit); 17717 if (NULL == stage_fc->data_ctrl->data_qual) { 17718 UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_NONE; 17719 } 17720 UDF_UNLOCK(unit); 17721 } 17722 #endif 17723 return (BCM_E_NONE); 17724 } 17725 f_dq_prev = f_dq; 17726 f_dq = f_dq->next; 17727 } 17728 return (BCM_E_NOT_FOUND); 17729 } 17730 17731 /* 17732 * Function: 17733 * _field_data_qualifier_destroy_all 17734 * Purpose: 17735 * Destroy all data/offset based qualifiers. 17736 * Parameters: 17737 * unit - (IN) bcm device. 17738 * Returns: 17739 * BCM_E_XXX 17740 */ 17741 int 17742 _field_data_qualifier_destroy_all(int unit) 17743 { 17744 _field_data_qualifier_t *f_dq;/* Internal data qualifier descriptor. */ 17745 _field_stage_t *stage_fc; /* Stage field control. */ 17746 int rv; /* Operation return status. */ 17747 17748 /* Get stage field control structure. */ 17749 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 17750 BCM_IF_ERROR_RETURN(rv); 17751 17752 while (NULL != stage_fc->data_ctrl->data_qual) { 17753 f_dq = stage_fc->data_ctrl->data_qual; 17754 BCM_IF_ERROR_RETURN (_bcm_field_data_qualifier_destroy(unit, f_dq->qid)); 17755 } 17756 return (BCM_E_NONE); 17757 } 17758 17759 /* 17760 * Function: 17761 * _field_stage_data_ctrl_deinit 17762 * 17763 * Purpose: 17764 * De-allocate data qualifiers control structure. 17765 * 17766 * Parameters: 17767 * unit - (IN) BCM unit 17768 * stage_fc - (IN/OUT) Stage to be initialize. 17769 * Returns: 17770 * BCM_E_XXX 17771 */ 17772 STATIC int 17773 _field_stage_data_ctrl_deinit(int unit, _field_stage_t *stage_fc) 17774 { 17775 _field_data_control_t *data_ctrl; 17776 17777 /* Input parameters check. */ 17778 if (NULL == stage_fc) { 17779 return (BCM_E_PARAM); 17780 } 17781 17782 if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) { 17783 return (BCM_E_NONE); 17784 } 17785 17786 data_ctrl = stage_fc->data_ctrl; 17787 if (NULL == data_ctrl) { 17788 return (BCM_E_NONE); 17789 } 17790 17791 /* Delete all data qualifiers. */ 17792 _field_data_qualifier_destroy_all(unit) ; 17793 17794 /* Free control structures. */ 17795 if (NULL != data_ctrl->tcam_entry_arr) { 17796 sal_free(data_ctrl->tcam_entry_arr); 17797 } 17798 17799 if (NULL != data_ctrl) { 17800 sal_free(data_ctrl); 17801 } 17802 17803 stage_fc->data_ctrl = NULL; 17804 return (BCM_E_NONE); 17805 } 17806 17807 /* 17808 * Function: 17809 * _bcm_field_data_qualifier_get 17810 * Purpose: 17811 * Get data qualifier by id. 17812 * Parameters: 17813 * unit - (IN) bcm device. 17814 * stage_fc - (IN) Stage field control. 17815 * qid - (IN) Qualifier id. 17816 * data_qual - (OUT) Internal data qualifier descriptor: 17817 * 17818 * Returns: 17819 * BCM_E_XXX 17820 */ 17821 int 17822 _bcm_field_data_qualifier_get(int unit, _field_stage_t *stage_fc, 17823 int qid, _field_data_qualifier_t **data_qual) 17824 { 17825 _field_data_qualifier_p f_dq; /* Field data qualifier iterator. */ 17826 17827 /* Input parameters check. */ 17828 if((NULL == data_qual) || (NULL == stage_fc)){ 17829 return (BCM_E_PARAM); 17830 } 17831 17832 f_dq = stage_fc->data_ctrl->data_qual; 17833 while (NULL != f_dq) { 17834 if (f_dq->qid == qid) { 17835 *data_qual = f_dq; 17836 return (BCM_E_NONE); 17837 } 17838 f_dq = f_dq->next; 17839 } 17840 return (BCM_E_NOT_FOUND); 17841 } 17842 17843 17844 /* 17845 * Function: 17846 * _field_data_qualifier_get 17847 * 17848 * Purpose: 17849 * Get data qualifier by qualifier id. 17850 * 17851 * Parameters: 17852 * unit - (IN) bcm device. 17853 * qual_id - (IN) Id of data qualifier. 17854 * data_qual - (OUT) Internal data qualifier descriptor: 17855 * 17856 * Returns: 17857 * BCM_E_XXX 17858 */ 17859 int 17860 _field_data_qualifier_get(int unit, int qual_id, 17861 _field_data_qualifier_t *data_qual) 17862 { 17863 int rv; 17864 _field_control_t *fc; 17865 _field_stage_t *stage_fc; 17866 _field_data_qualifier_t *f_dq; 17867 17868 /* Parameter checking */ 17869 if (data_qual == NULL) { 17870 LOG_ERROR(BSL_LS_BCM_FP, 17871 (BSL_META_U(unit, 17872 "FP(unit %d) Error: data_qual == NULL.\n"), 17873 unit)); 17874 return (BCM_E_PARAM); 17875 } 17876 17877 /* Point to needed things */ 17878 FP_LOCK(unit); 17879 rv = _field_control_get(unit, &fc); 17880 if (BCM_FAILURE(rv)) { 17881 FP_UNLOCK(unit); 17882 return rv; 17883 } 17884 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 17885 if (BCM_FAILURE(rv)) { 17886 FP_UNLOCK(unit); 17887 return rv; 17888 } 17889 17890 if ((rv = _bcm_field_data_qualifier_get(unit, 17891 stage_fc, qual_id, &f_dq)) == BCM_E_NONE) { 17892 sal_memcpy(data_qual, f_dq, sizeof(_field_data_qualifier_t)); 17893 } 17894 17895 FP_UNLOCK(unit); 17896 17897 return (rv); 17898 } 17899 17900 17901 /* 17902 * Function: 17903 * _field_data_qualifier_id_alloc 17904 * Purpose: 17905 * Allocate unused date qualifier id. 17906 * Parameters: 17907 * unit - (IN) bcm device. 17908 * stage_fc - (IN) Stage field control. 17909 * data_qualifier - (IN) API level qualifier descriptor: 17910 * 17911 * Returns: 17912 * BCM_E_XXX 17913 */ 17914 int 17915 _field_data_qualifier_id_alloc(int unit, _field_stage_t *stage_fc, 17916 bcm_field_data_qualifier_t *data_qualifier) 17917 { 17918 _field_data_qualifier_t *f_dq; /* Data qualifier descriptor. */ 17919 static int last_allocated_qid = 0;/* last allocated qid. */ 17920 int max_try; /* Maximum number of allocation. */ 17921 int qid; /* Qualifier id. */ 17922 int rv; /* Operation return status. */ 17923 17924 17925 /* Input parameters check. */ 17926 if ((NULL == data_qualifier) || (NULL == stage_fc)) { 17927 return (BCM_E_PARAM); 17928 } 17929 17930 /* If qualifier id was passed by the caller, 17931 verify the range and make sure id is not used. */ 17932 if (data_qualifier->flags & BCM_FIELD_DATA_QUALIFIER_WITH_ID) { 17933 qid = data_qualifier->qual_id; 17934 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qid, &f_dq); 17935 if (BCM_SUCCESS(rv)) { 17936 /* Data qual with requested id already exists */ 17937 17938 if (!(data_qualifier->flags & BCM_FIELD_DATA_QUALIFIER_REPLACE)) { 17939 /* "Replace" flag was not specified => Return error */ 17940 17941 return (BCM_E_EXISTS); 17942 } 17943 17944 /* Destroy existing one */ 17945 17946 _bcm_field_data_qualifier_destroy(unit, qid); 17947 } 17948 return (BCM_E_NONE); 17949 } 17950 max_try = _FP_ID_MAX; 17951 qid = last_allocated_qid; 17952 while (max_try--) { 17953 qid++; 17954 if ((qid < _FP_ID_BASE) || (qid >= _FP_ID_MAX)) { 17955 qid = _FP_ID_BASE; 17956 } 17957 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qid, &f_dq); 17958 if (BCM_E_NOT_FOUND == rv) { 17959 last_allocated_qid = qid; 17960 data_qualifier->qual_id = qid; 17961 return (BCM_E_NONE); 17962 } 17963 if (BCM_FAILURE(rv)) { 17964 return (rv); 17965 } 17966 } 17967 return (BCM_E_RESOURCE); 17968 } 17969 17970 17971 int 17972 _field_data_qualifier_init2(int unit, 17973 _field_stage_t *stage_fc, 17974 _field_data_qualifier_t *f_dq 17975 ) 17976 { 17977 int add_offset; /* Additional offset due to l2 */ 17978 /* header size is not multiples of 4. */ 17979 17980 /* Add to stage's data qual list */ 17981 f_dq->next = stage_fc->data_ctrl->data_qual; 17982 stage_fc->data_ctrl->data_qual = f_dq; 17983 17984 /* Verify data qualifier offset base value. */ 17985 switch (f_dq->offset_base) { 17986 /* The following data qualifier offsets are not supported by XGS */ 17987 case bcmFieldDataOffsetBaseTrillPayload: 17988 case bcmFieldDataOffsetBaseTrillHeader: 17989 #ifdef BCM_TRIUMPH2_SUPPORT 17990 /* The following chips support the above mentioned offset base */ 17991 if ((SOC_IS_TD2_TT2(unit)) || (SOC_IS_KATANAX(unit)) || 17992 (SOC_IS_TRIUMPH3(unit)) || (SOC_IS_TRIDENT(unit))) { 17993 break; 17994 } 17995 #endif 17996 case bcmFieldDataOffsetBaseL2Header: 17997 case bcmFieldDataOffsetBaseFirstHeader: 17998 case bcmFieldDataOffsetBaseSecondHeader: 17999 case bcmFieldDataOffsetBaseThirdHeader: 18000 case bcmFieldDataOffsetBaseMplsLabel1Header: 18001 case bcmFieldDataOffsetBaseMplsLabel2Header: 18002 case bcmFieldDataOffsetBaseMplsLabel3Header: 18003 case bcmFieldDataOffsetBaseInnerL2Header: 18004 case bcmFieldDataOffsetBaseFourthHeader: 18005 case bcmFieldDataOffsetBaseForwardingHeader: 18006 case bcmFieldDataOffsetBaseNextForwardingHeader: 18007 { 18008 return (BCM_E_PARAM); 18009 } 18010 break; 18011 default: 18012 break; 18013 } 18014 18015 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) 18016 if (SOC_MEM_IS_VALID(unit, FP_UDF_TCAMm)) { 18017 if (stage_fc->data_ctrl->elem_size <= 2) { /* no wrap around needed */ 18018 f_dq->byte_offset = f_dq->offset % 18019 stage_fc->data_ctrl->elem_size; 18020 } else { 18021 if (bcmFieldDataOffsetBasePacketStart == 18022 f_dq->offset_base) { 18023 f_dq->byte_offset = (f_dq->offset + 2) % 4; 18024 } else { 18025 f_dq->byte_offset = f_dq->offset % 4; 18026 } 18027 } 18028 } else 18029 #endif /* BCM_TRIUMPH2_SUPPORT */ 18030 { 18031 switch (f_dq->offset_base) { 18032 case bcmFieldDataOffsetBaseOuterL3Header: 18033 case bcmFieldDataOffsetBaseInnerL3Header: 18034 case bcmFieldDataOffsetBaseOuterL4Header: 18035 case bcmFieldDataOffsetBaseInnerL4Header: 18036 /* Older devices supports Start of Packet offset only. */ 18037 return (BCM_E_PARAM); 18038 case bcmFieldDataOffsetBasePacketStart: 18039 add_offset = 0; 18040 break; 18041 case bcmFieldDataOffsetBaseHigigHeader: 18042 if (SOC_IS_FB(unit) || 18043 SOC_IS_HB_GW(unit) || 18044 SOC_IS_SC_CQ(unit) || 18045 SOC_IS_ENDURO(unit) || 18046 soc_feature(unit, soc_feature_field_udf_offset_hg_114B)) { 18047 add_offset = 2; 18048 } else { 18049 add_offset = 0; 18050 } 18051 break; 18052 case bcmFieldDataOffsetBaseHigig2Header: 18053 if (SOC_IS_FB(unit) || 18054 SOC_IS_HB_GW(unit) || 18055 SOC_IS_SC_CQ(unit) || 18056 SOC_IS_ENDURO(unit) || 18057 soc_feature(unit, soc_feature_field_udf_offset_hg2_110B)) { 18058 add_offset = 2; 18059 } else { 18060 add_offset = 0; 18061 } 18062 break; 18063 default: 18064 return (BCM_E_PARAM); 18065 } 18066 18067 f_dq->byte_offset = (f_dq->offset + add_offset + 2) % 4; 18068 } 18069 18070 return (BCM_E_NONE); 18071 } 18072 18073 18074 int 18075 _field_data_qualifier_init(int unit, 18076 _field_stage_t *stage_fc, 18077 _field_data_qualifier_t *f_dq, 18078 bcm_field_data_qualifier_t *data_qualifier 18079 ) 18080 { 18081 f_dq->qid = data_qualifier->qual_id; 18082 f_dq->offset_base = data_qualifier->offset_base; 18083 f_dq->offset = data_qualifier->offset; 18084 f_dq->length = data_qualifier->length; 18085 f_dq->flags = data_qualifier->flags & _BCM_FIELD_DATA_QUALIFIER_FLAGS; 18086 18087 BCM_IF_ERROR_RETURN(_field_data_qualifier_init2(unit, stage_fc, f_dq)); 18088 18089 f_dq->elem_count = (f_dq->length + f_dq->byte_offset + 18090 stage_fc->data_ctrl->elem_size - 1 18091 ) 18092 / stage_fc->data_ctrl->elem_size; 18093 18094 return (BCM_E_NONE); 18095 } 18096 18097 void 18098 _field_data_qualifier_debug(int unit, 18099 _field_stage_t *stage_fc, 18100 _field_data_qualifier_t *f_dq) 18101 { 18102 int idx, first=1; 18103 int num_elems; 18104 18105 if (stage_fc == NULL || f_dq == NULL) { 18106 return; 18107 } 18108 18109 num_elems = stage_fc->data_ctrl->num_elems; 18110 LOG_VERBOSE(BSL_LS_BCM_FP, 18111 (BSL_META_U(unit, 18112 "Chunks allocated for Data Qualifier ID - %d:\n\r"), 18113 f_dq->qid)); 18114 LOG_VERBOSE(BSL_LS_BCM_FP, 18115 (BSL_META_U(unit, 18116 "UDF1{"))); 18117 for (idx = 0; idx < num_elems; idx++) { 18118 if (f_dq->hw_bmap & (1 << idx)) { 18119 if (first == 0) { 18120 LOG_VERBOSE(BSL_LS_BCM_FP, 18121 (BSL_META_U(unit, 18122 "), "))); 18123 } 18124 first = 0; 18125 LOG_VERBOSE(BSL_LS_BCM_FP, 18126 (BSL_META_U(unit, 18127 "%d"), 18128 idx)); 18129 } 18130 } 18131 LOG_VERBOSE(BSL_LS_BCM_FP, 18132 (BSL_META_U(unit, 18133 "%s}\n\r"), 18134 (first == 1)?"None":"")); 18135 first = 1; 18136 LOG_VERBOSE(BSL_LS_BCM_FP, 18137 (BSL_META_U(unit, 18138 "UDF2{"))); 18139 for (idx = num_elems; idx < num_elems * 2; idx++) { 18140 if (f_dq->hw_bmap & (1 << idx)) { 18141 if (first == 0) { 18142 LOG_VERBOSE(BSL_LS_BCM_FP, 18143 (BSL_META_U(unit, 18144 "), "))); 18145 } 18146 first = 0; 18147 LOG_VERBOSE(BSL_LS_BCM_FP, 18148 (BSL_META_U(unit, 18149 "%d"), 18150 idx)); 18151 } 18152 } 18153 LOG_VERBOSE(BSL_LS_BCM_FP, 18154 (BSL_META_U(unit, 18155 "%s}\n\r"), 18156 (first == 1)?"None":"")); 18157 } 18158 18159 int 18160 _field_data_qualifier_create(int unit, 18161 bcm_field_data_qualifier_t *data_qualifier) 18162 { 18163 _field_data_qualifier_t *f_dq;/* Internal data qualifier descriptor. */ 18164 _field_stage_t *stage_fc; /* Stage field control. */ 18165 int rv; /* Operation return status. */ 18166 18167 /* Input parameters check. */ 18168 if (NULL == data_qualifier) { 18169 return (BCM_E_PARAM); 18170 } 18171 18172 #if defined (BCM_TRIUMPH2_SUPPORT) 18173 if (soc_feature(unit, soc_feature_udf_support)) { 18174 if (UDF_CTRL(unit) == NULL) { 18175 LOG_CLI((BSL_META("UDF module is not initialized. \n"))); 18176 return (BCM_E_RESOURCE); 18177 } 18178 if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_UDF_MODULE) { 18179 LOG_CLI((BSL_META("Udf resource is used by UDF module. \n"))); 18180 return (BCM_E_RESOURCE); 18181 } 18182 } 18183 #endif 18184 18185 /* Get stage field control structure. */ 18186 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 18187 BCM_IF_ERROR_RETURN(rv); 18188 18189 /* Allocate data qualifier id. */ 18190 rv = _field_data_qualifier_id_alloc(unit, stage_fc, data_qualifier); 18191 BCM_IF_ERROR_RETURN(rv); 18192 18193 /* Allocated internal data qualifier descriptor. */ 18194 rv = _bcm_field_data_qualifier_alloc(unit, &f_dq); 18195 BCM_IF_ERROR_RETURN(rv); 18196 18197 /* Initialize internal data qualifier record from given one */ 18198 rv = _field_data_qualifier_init(unit, stage_fc, f_dq, data_qualifier); 18199 if (BCM_FAILURE(rv)) { 18200 goto error_cleanup; 18201 } 18202 18203 /* Allocate words in hw to accommodate data qualifier. */ 18204 rv = _field_data_qualifier_hw_alloc(unit, stage_fc, f_dq); 18205 if (BCM_FAILURE(rv)) { 18206 goto error_cleanup; 18207 } 18208 18209 if (FP_VERB_CHECK()) { 18210 (void)_field_data_qualifier_debug(unit, stage_fc, f_dq); 18211 } 18212 18213 #if defined (BCM_TRIUMPH2_SUPPORT) 18214 if (soc_feature(unit, soc_feature_udf_support)) { 18215 UDF_LOCK(unit); 18216 UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_FIELD_MODULE; 18217 UDF_UNLOCK(unit); 18218 } 18219 #endif 18220 18221 return (BCM_E_NONE); 18222 18223 error_cleanup: 18224 _bcm_field_data_qualifier_destroy(unit, f_dq->qid); 18225 18226 return (rv); 18227 } 18228 18229 /* 18230 * Function: _field_qualify_data_elem 18231 * 18232 * Purpose: 18233 * 18234 * Parameters: 18235 * unit - (IN) BCM device number. 18236 * eid - (IN) Entry ID. 18237 * f_dq - (IN) Data qualifier descriptor. 18238 * qual_elem_idx - (IN) Data qualifier element index. 18239 * data - (IN) Data bytes for the indicated data qualifier. 18240 * Network byte ordered. 18241 * mask - Mask bytes for the indicated data qualifier. 18242 * Network byte ordered. 18243 * Returns: 18244 * BCM_E_XXX 18245 */ 18246 int 18247 _field_qualify_data_elem(int unit, bcm_field_entry_t eid, 18248 _field_data_qualifier_t *f_dq, 18249 uint8 qual_elem_idx, 18250 uint32 data, uint32 mask) 18251 { 18252 _field_stage_t *stage_fc; 18253 _bcm_field_qual_offset_t *q_offset; 18254 _bcm_field_qual_offset_t q_offset_temp; 18255 _field_entry_t *f_ent = NULL; 18256 int idx; 18257 int rv; 18258 int elem_idx = 0; 18259 int qid = 0; 18260 18261 /* Input parameters check. */ 18262 if (NULL == f_dq) { 18263 return (BCM_E_PARAM); 18264 } 18265 18266 BCM_IF_ERROR_RETURN 18267 (_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc)); 18268 18269 /* Find a proper element to insert the data. */ 18270 for (idx = 0; idx < stage_fc->data_ctrl->num_elems * 2; idx++) { 18271 if (f_dq->hw_bmap & (1 << idx)) { 18272 if (elem_idx == qual_elem_idx) { 18273 break; 18274 } else { 18275 elem_idx++; 18276 } 18277 } 18278 } 18279 18280 /* Get entry info. */ 18281 BCM_IF_ERROR_RETURN 18282 (_field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, &f_ent)); 18283 18284 /* Get data qualifier id. */ 18285 if (idx >= 0 && idx < stage_fc->data_ctrl->num_elems) { 18286 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 18287 if (SOC_IS_ENDURO(unit) 18288 || SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) 18289 || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) 18290 || SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND2(unit)) { 18291 /* Check in group Qset if Data0 is set. */ 18292 if (!BCM_FIELD_QSET_TEST_INTERNAL 18293 (f_ent->group->qset, _bcmFieldQualifyData0)) { 18294 if ((1 == idx) 18295 && !(f_dq->hw_bmap & (1 << 0x0)) 18296 && !(f_dq->hw_bmap & (1 << 0x2))) { 18297 /* qid = UDF1_31_0 */ 18298 qid = _bcmFieldQualifyData3; 18299 } else if ((3 == idx) 18300 && !(f_dq->hw_bmap & (1 << 0x0)) 18301 && !(f_dq->hw_bmap & (1 << 0x2))) { 18302 /* qid = UDF1_95_64 */ 18303 qid = _bcmFieldQualifyData2; 18304 } else { 18305 return (BCM_E_INTERNAL); 18306 } 18307 } else { 18308 /* qid = UDF1_127_0 */ 18309 qid = _bcmFieldQualifyData0; 18310 } 18311 } else 18312 #endif /* BCM_ENDURO_SUPPORT */ 18313 18314 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) 18315 if (SOC_IS_TD_TT(unit) 18316 || SOC_IS_KATANAX(unit) 18317 || SOC_IS_TRIUMPH3(unit)) { 18318 /* Check in group Qset if Data0 is set. */ 18319 if (!BCM_FIELD_QSET_TEST_INTERNAL 18320 (f_ent->group->qset, _bcmFieldQualifyData0)) { 18321 if ((2 == idx || 3 == idx) 18322 && !(f_dq->hw_bmap & 0x33)) { 18323 /* UDF1_95_64 */ 18324 qid = _bcmFieldQualifyData3; 18325 } else if ((6 == idx || 7 == idx) 18326 && !(f_dq->hw_bmap & 0x33)) { 18327 /* UDF1_31_0 */ 18328 qid = _bcmFieldQualifyData2; 18329 } else { 18330 /* 18331 * udf_offset0_1 and udf_offset4_5 must be in 18332 * _bcmFieldQualifyData0 18333 */ 18334 return (BCM_E_INTERNAL); 18335 } 18336 } else { 18337 /* UDF1_127_0 */ 18338 qid = _bcmFieldQualifyData0; 18339 } 18340 } else 18341 #endif /* !BCM_TRIDENT_SUPPORT or BCM_KATANA_SUPPORT*/ 18342 { 18343 qid = _bcmFieldQualifyData0; 18344 } 18345 } else if (idx >= stage_fc->data_ctrl->num_elems && 18346 idx < stage_fc->data_ctrl->num_elems * 2) { 18347 qid = _bcmFieldQualifyData1; 18348 idx -= stage_fc->data_ctrl->num_elems; 18349 } else { 18350 return (BCM_E_INTERNAL); 18351 } 18352 #if defined(BCM_TOMAHAWK_SUPPORT) 18353 /* If device supports per-pipe FP configuration, */ 18354 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 18355 ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 18356 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) { 18357 /* coverity[address_of : FALSE] */ 18358 /* coverity[callee_ptr_arith : FALSE] */ 18359 return (_bcm_field_th_qualify_set(unit, eid, qid, 18360 &data, &mask, 18361 _FP_QUALIFIER_ADD)); 18362 } 18363 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 18364 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 18365 return (_bcm_field_th_class_qualify_set(unit, eid, qid, 18366 &data, &mask)); 18367 } 18368 #endif /* BCM_TOMAHAWK_SUPPORT */ 18369 18370 /* Get entry qualifier should be installed in. */ 18371 f_ent = NULL; 18372 rv = _bcm_field_entry_qual_get(unit, eid, qid, &f_ent); 18373 BCM_IF_ERROR_RETURN(rv); 18374 18375 /* Get entry qualifier offset in tcam. */ 18376 rv = _field_qual_offset_get(unit, f_ent, qid, &q_offset); 18377 BCM_IF_ERROR_RETURN(rv); 18378 18379 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 18380 if (SOC_IS_ENDURO(unit) 18381 || SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) 18382 || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) 18383 || SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND2(unit)) { 18384 if ((qid == _bcmFieldQualifyData2) 18385 || (qid == _bcmFieldQualifyData3)) { 18386 /* Don't have to swap if only one chunk used in UDF1 */ 18387 idx = 0; 18388 } else { 18389 idx = (stage_fc->data_ctrl->num_elems - 1) - idx; 18390 } 18391 } else 18392 #endif /* !BCM_ENDURO_SUPPORT */ 18393 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) 18394 if (SOC_IS_TD_TT(unit) 18395 || SOC_IS_KATANAX(unit) 18396 || SOC_IS_TRIUMPH3(unit)) { 18397 if (qid == _bcmFieldQualifyData3) { 18398 if (2 == idx) { 18399 /* Shift of 2 bytes (16 bits). */ 18400 idx = 1; 18401 } else { 18402 idx = 0; 18403 } 18404 } else { 18405 idx = (stage_fc->data_ctrl->num_elems - 1) - idx; 18406 } 18407 } else 18408 #endif 18409 { 18410 idx = (stage_fc->data_ctrl->num_elems - 1) - idx; 18411 } 18412 18413 sal_memcpy(&q_offset_temp, q_offset, 18414 sizeof(_bcm_field_qual_offset_t)); 18415 18416 q_offset_temp.offset[0] += idx * stage_fc->data_ctrl->elem_size * 8; 18417 q_offset_temp.width[0] = stage_fc->data_ctrl->elem_size * 8; 18418 /* 18419 * COVERITY 18420 * 18421 *This flow takes care of the Out-of-bounds access issue 18422 * for data and mask. 18423 */ 18424 /* coverity[callee_ptr_arith : FALSE] */ 18425 rv = _bcm_field_qual_value_set(unit, &q_offset_temp, f_ent, &data, &mask); 18426 BCM_IF_ERROR_RETURN(rv); 18427 18428 f_ent->flags |= _FP_ENTRY_DIRTY; 18429 return (BCM_E_NONE); 18430 } 18431 18432 /* 18433 * Function: _field_external_qualify_data_elem 18434 * 18435 * Purpose: 18436 * 18437 * Parameters: 18438 * unit - (IN) BCM device number. 18439 * eid - (IN) Entry ID. 18440 * f_dq - (IN) Data qualifier descriptor. 18441 * qual_elem_idx - (IN) Data qualifier element index. 18442 * data - (IN) Data bytes for the indicated data qualifier. 18443 * Network byte ordered. 18444 * mask - Mask bytes for the indicated data qualifier. 18445 * Network byte ordered. 18446 * Returns: 18447 * BCM_E_XXX 18448 */ 18449 int 18450 _field_external_qualify_data_elem(int unit, bcm_field_entry_t eid, 18451 _field_data_qualifier_t *f_dq, 18452 uint8 qual_elem_idx, 18453 uint32 data, uint32 mask) 18454 { 18455 _field_stage_t *stage_fc; 18456 _bcm_field_qual_offset_t *q_offset; 18457 _field_entry_t *f_ent = NULL; 18458 int idx; 18459 int rv; 18460 int elem_idx = 0; 18461 int qid = 0; 18462 18463 /* Input parameters check. */ 18464 if (NULL == f_dq) { 18465 return (BCM_E_PARAM); 18466 } 18467 18468 LOG_DEBUG(BSL_LS_BCM_FP, 18469 (BSL_META_U(unit, 18470 "FP(unit %d) vverb: eid (%d): qual_elem_idx (%d)" 18471 "data (%x) mask (%x)\n"), unit, eid, qual_elem_idx, data, mask)); 18472 18473 BCM_IF_ERROR_RETURN 18474 (_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc)); 18475 18476 /* Find a proper element to insert the data. */ 18477 for (idx = 0; idx < (stage_fc->data_ctrl->num_elems - 2); idx++) { 18478 if (f_dq->hw_bmap & (1 << idx)) { 18479 if (elem_idx == qual_elem_idx) { 18480 break; 18481 } else { 18482 elem_idx++; 18483 } 18484 } 18485 } 18486 18487 /* Get data qualifier id. */ 18488 if ((f_dq->hw_bmap & 0x1) && (idx >= 0 && idx < 2)) { 18489 qid = _bcmFieldQualifyData0; 18490 } else if ((f_dq->hw_bmap & 0x2) && (idx == 1)) { 18491 qid = _bcmFieldQualifyData2; 18492 } else { 18493 return (BCM_E_INTERNAL); 18494 } 18495 18496 /* Get entry qualifier should be installed in. */ 18497 rv = _bcm_field_entry_qual_get(unit, eid, qid, &f_ent); 18498 BCM_IF_ERROR_RETURN(rv); 18499 18500 /* Get entry qualifier offset in tcam. */ 18501 rv = _field_qual_offset_get(unit, f_ent, qid, &q_offset); 18502 BCM_IF_ERROR_RETURN(rv); 18503 /* 18504 * COVERITY 18505 * 18506 *This flow takes care of the Out-of-bounds access issue 18507 * for data and mask. 18508 */ 18509 /* coverity[callee_ptr_arith : FALSE] */ 18510 rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, &data, &mask); 18511 BCM_IF_ERROR_RETURN(rv); 18512 18513 f_ent->flags |= _FP_ENTRY_DIRTY; 18514 return (BCM_E_NONE); 18515 } 18516 18517 18518 /* 18519 * Function: _field_qualify_data 18520 * 18521 * Purpose: 18522 * 18523 * Parameters: 18524 * unit - (IN) BCM device number. 18525 * eid - (IN) Entry ID. 18526 * qual_id - (IN) Data qualifier id. 18527 * data - (IN) Data bytes for the indicated data qualifier. 18528 * Network byte ordered. 18529 * mask - (IN) Mask bytes for the indicated data qualifier. 18530 * Network byte ordered. 18531 * length - (IN) data/mask length. 18532 * Returns: 18533 * BCM_E_XXX 18534 */ 18535 int 18536 _field_qualify_data (int unit, bcm_field_entry_t eid, int qual_id, 18537 uint8 *data, uint8 *mask, uint16 length) 18538 { 18539 _field_stage_t *stage_fc; /* Stage field control. */ 18540 _field_data_qualifier_t *f_dq; /* Data qualifier descriptor. */ 18541 int idx; /* HW bitmap iteration index. */ 18542 int byte_offset;/* Byte offset in the word. */ 18543 int qual_elem_idx; /* Qualifier element index.*/ 18544 uint32 data_elem; /* Hw info data word. */ 18545 uint32 mask_elem; /* Hw info data mask. */ 18546 uint8 data_qual_done = 0; 18547 int rv; /* Operation return status. */ 18548 #ifdef BCM_TRIUMPH_SUPPORT 18549 _field_entry_t *entry_p = NULL; /* Field entry pointer */ 18550 #endif 18551 18552 /* Input parameters check. */ 18553 if ((NULL == data) || (NULL == mask)) { 18554 return (BCM_E_PARAM); 18555 } 18556 18557 18558 18559 /* Get stage field control structure. */ 18560 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 18561 BCM_IF_ERROR_RETURN(rv); 18562 18563 /* Get data qualifier info. */ 18564 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq); 18565 BCM_IF_ERROR_RETURN(rv); 18566 18567 #ifdef BCM_TRIUMPH_SUPPORT 18568 rv = _field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, &entry_p); 18569 BCM_IF_ERROR_RETURN(rv); 18570 #endif 18571 18572 /* 18573 * If provided entry data length is greater than data length used 18574 * to create qualifier then return error 18575 */ 18576 18577 if (length > f_dq->length) { 18578 return (BCM_E_PARAM); 18579 } 18580 18581 #ifdef BCM_TOMAHAWK_SUPPORT 18582 if (_BCM_FIELD_STAGE_EXACTMATCH == entry_p->group->stage_id) { 18583 if (length != f_dq->length) { 18584 return BCM_E_PARAM; 18585 } 18586 } 18587 #endif 18588 18589 #ifdef BCM_TRIUMPH_SUPPORT 18590 if (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) { 18591 /* Get entry qualifier should be installed in. */ 18592 if (entry_p->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 18593 if (length > 4) { 18594 return (BCM_E_PARAM); 18595 } 18596 } 18597 } 18598 #endif 18599 18600 data_elem = 0; 18601 mask_elem = 0; 18602 qual_elem_idx = 0; 18603 byte_offset = f_dq->byte_offset; 18604 for (idx = 0; idx < length; idx++) { 18605 18606 #ifdef BCM_TOMAHAWK_SUPPORT 18607 if (_BCM_FIELD_STAGE_EXACTMATCH == entry_p->group->stage_id) { 18608 if (0xFF != mask[idx]) { 18609 return BCM_E_PARAM; 18610 } 18611 } 18612 #endif 18613 18614 data_elem |= (data[idx] << (8 * (stage_fc->data_ctrl->elem_size - 1 - 18615 byte_offset))); 18616 mask_elem |= (mask[idx] << (8 * (stage_fc->data_ctrl->elem_size - 1 - 18617 byte_offset))); 18618 byte_offset++; 18619 data_qual_done = 0; 18620 18621 if (byte_offset == stage_fc->data_ctrl->elem_size) { 18622 /* Install the element data & mask. */ 18623 #ifdef BCM_TRIUMPH_SUPPORT 18624 if ((SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) && 18625 (entry_p->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL)) { 18626 rv = _field_external_qualify_data_elem(unit, eid, 18627 f_dq, qual_elem_idx, 18628 data_elem, mask_elem); 18629 } else 18630 #endif 18631 #ifdef BCM_TOMAHAWK_SUPPORT 18632 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 18633 rv = _bcm_field_th_field_qualify_data_elem(unit, eid, f_dq, qual_elem_idx, 18634 data_elem, mask_elem); 18635 } else 18636 #endif 18637 { 18638 rv = _field_qualify_data_elem(unit, eid, f_dq, qual_elem_idx, 18639 data_elem, mask_elem); 18640 } 18641 BCM_IF_ERROR_RETURN(rv); 18642 qual_elem_idx++; 18643 byte_offset = 0; 18644 data_elem = 0; 18645 mask_elem = 0; 18646 data_qual_done = 1; 18647 } 18648 } 18649 18650 /* Install last element data & mask, if data/mask still exists to be qualified. 18651 * (data_qual_done == 0) 18652 */ 18653 18654 if (data_qual_done != 1) { 18655 #ifdef BCM_TRIUMPH_SUPPORT 18656 if ((SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) && 18657 (entry_p->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL)) { 18658 rv = _field_external_qualify_data_elem(unit, eid, f_dq, 18659 qual_elem_idx, data_elem, 18660 mask_elem); 18661 } else 18662 #endif 18663 #ifdef BCM_TOMAHAWK_SUPPORT 18664 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 18665 rv = _bcm_field_th_field_qualify_data_elem(unit, eid, f_dq, qual_elem_idx, 18666 data_elem, mask_elem); 18667 } else 18668 #endif 18669 { 18670 rv = _field_qualify_data_elem(unit, eid, f_dq, qual_elem_idx, 18671 data_elem, mask_elem); 18672 } 18673 } 18674 return (rv); 18675 } 18676 18677 /* 18678 * Function: 18679 * _field_selcode_assign 18680 * 18681 * Purpose: 18682 * Calculate the FPFx select codes from a qualifier set and group mode. 18683 * 18684 * Parameters: 18685 * unit - (IN) BCM device number. 18686 * qset - (IN) Client qualifier set. 18687 * selcode_clear - (IN) Clear the selcodes 18688 * fg - (IN/OUT) Group info structure. 18689 * 18690 * Returns: 18691 * BCM_E_PARAM - mode unknown 18692 * BCM_E_RESOURCE - No select code will satisfy qualifier set 18693 * BCM_E_NONE - Success 18694 * 18695 * Notes: 18696 * Calling function is responsible for ensuring appropriate slices 18697 * are available. 18698 * selcode_clear will be 0 (don't clear) when this function is called 18699 * from bcm_field_group_set 18700 */ 18701 int 18702 _field_selcode_assign(int unit, bcm_field_qset_t qset, int selcode_clear, 18703 _field_group_t *fg) 18704 { 18705 _field_stage_t *stage_fc; /* Stage field control structure. */ 18706 _field_control_t *fc; /* Field control structure. */ 18707 int idx; /* Generic iteration index. */ 18708 18709 /* Input parameters check. */ 18710 if (NULL == fg) { 18711 return (BCM_E_PARAM); 18712 } 18713 18714 /* Get field control structure for this device. */ 18715 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 18716 18717 /* Get stage FP control info. */ 18718 BCM_IF_ERROR_RETURN 18719 (_field_stage_control_get(unit, fg->stage_id, &stage_fc)); 18720 18721 /* 18722 * Clear the group's slice Qsets. 18723 * Selcodes need not be cleared if this function is called from group_set 18724 */ 18725 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 18726 if (selcode_clear) { 18727 _FIELD_SELCODE_CLEAR(fg->sel_codes[idx]); 18728 BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(fg, idx)); 18729 } 18730 } 18731 18732 /* Get select codes based on group flags. */ 18733 BCM_IF_ERROR_RETURN (fc->functions.fp_selcode_get(unit, stage_fc, 18734 &qset, fg)); 18735 return (BCM_E_NONE); 18736 } 18737 18738 18739 /* 18740 * Function: 18741 * _field_meters_deinit 18742 * Purpose: 18743 * Deinitialize field slice meters usage bitmap. 18744 * 18745 * Parameters: 18746 * unit - (IN) BCM device number. 18747 * stage_fc - (IN/OUT) Stage field control structure. 18748 * 18749 * Returns: 18750 * BCM_E_XXX 18751 * 18752 * Notes: 18753 * The External stage of Triumph shares the meter pool with Ingress. 18754 * free only when it is called for Ingress. 18755 */ 18756 STATIC int 18757 _field_meters_deinit (int unit, _field_stage_t *stage_fc) 18758 { 18759 _field_slice_t *slice; /* Slice config structure. */ 18760 int slice_idx; /* Slices iterator. */ 18761 18762 /* Input parameters check. */ 18763 if (NULL == stage_fc) { 18764 return (BCM_E_NONE); 18765 } 18766 18767 /* Make sure slices array is initialized. */ 18768 if (NULL == stage_fc->slices[_FP_DEF_INST]) { 18769 return (BCM_E_NONE); 18770 } 18771 18772 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 18773 int i; 18774 if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 18775 return (BCM_E_NONE); 18776 } 18777 for (i = 0; i < stage_fc->num_meter_pools; i++) { 18778 if (stage_fc->meter_pool[_FP_DEF_INST][i] != NULL) { 18779 if (stage_fc->meter_pool[_FP_DEF_INST][i]->meter_bmp.w 18780 != NULL) { 18781 sal_free( 18782 stage_fc->meter_pool[_FP_DEF_INST][i]->meter_bmp.w); 18783 } 18784 sal_free(stage_fc->meter_pool[_FP_DEF_INST][i]); 18785 stage_fc->meter_pool[_FP_DEF_INST][i] = NULL; 18786 } 18787 } 18788 18789 #ifdef BCM_TRIUMPH3_SUPPORT 18790 if (SOC_IS_TRIUMPH3(unit)) { 18791 for (i = 0; i < stage_fc->num_logical_meter_pools; i++) { 18792 if (stage_fc->logical_meter_pool[i] != NULL) { 18793 if (stage_fc->logical_meter_pool[i]->meter_bmp.w != NULL) { 18794 sal_free(stage_fc->logical_meter_pool[i]->meter_bmp.w); 18795 } 18796 sal_free(stage_fc->logical_meter_pool[i]); 18797 stage_fc->logical_meter_pool[i] = NULL; 18798 } 18799 } 18800 } 18801 #endif 18802 18803 return BCM_E_NONE; 18804 } 18805 18806 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 18807 slice = stage_fc->slices[_FP_DEF_INST] + slice_idx; 18808 if (NULL != slice->meter_bmp.w) { 18809 sal_free(slice->meter_bmp.w); 18810 } 18811 slice->meter_bmp.w = NULL; 18812 } 18813 return (BCM_E_NONE); 18814 } 18815 18816 /* 18817 * Function: 18818 * _field_counters_deinit 18819 * Purpose: 18820 * Deinitialize field slice counters bitmap. 18821 * 18822 * Parameters: 18823 * unit - (IN) BCM device number. 18824 * stage_fc - (IN/OUT) Stage field control structure. 18825 * 18826 * Returns: 18827 * BCM_E_XXX 18828 */ 18829 18830 STATIC void 18831 _field_cntr_pools_deinit(int unit, _field_stage_t *stage_fc) 18832 { 18833 _field_cntr_pool_t **pp, *p; 18834 unsigned n; 18835 18836 for (pp = stage_fc->cntr_pool, n = COUNTOF(stage_fc->cntr_pool); n; --n, ++pp) { 18837 if ((p = *pp) == 0) { 18838 continue; 18839 } 18840 18841 sal_free(p->cntr_bmp.w); 18842 sal_free(p); 18843 18844 *pp = 0; 18845 } 18846 } 18847 18848 18849 STATIC int 18850 _field_counters_deinit(int unit, _field_stage_t *stage_fc) 18851 { 18852 _field_slice_t *slice; /* Slice config structure. */ 18853 int slice_idx; /* Slices iterator. */ 18854 18855 /* Input parameters check. */ 18856 if (NULL == stage_fc) { 18857 return (BCM_E_NONE); 18858 } 18859 18860 /* Make sure slices array is initialized. */ 18861 if (NULL == stage_fc->slices[_FP_DEF_INST]) { 18862 return (BCM_E_NONE); 18863 } 18864 18865 /* Destroy 64 bit counters. */ 18866 _field_counter_collect_deinit(unit, stage_fc); 18867 18868 /* 18869 * There is an 1-1 mapping between rules and counters 18870 * for external FP, so no bitmap was allocated. 18871 * (Triumph) 18872 */ 18873 if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) { 18874 return (BCM_E_NONE); 18875 } 18876 18877 /* Denitialize stage slices info. */ 18878 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 18879 if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) { 18880 if (NULL != stage_fc->slices[_FP_DEF_INST][0].counter_bmp.w) { 18881 sal_free (stage_fc->slices[_FP_DEF_INST][0].counter_bmp.w); 18882 } 18883 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 18884 stage_fc->slices[_FP_DEF_INST][slice_idx].counter_bmp.w = NULL; 18885 } 18886 } else if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) { 18887 #if defined(BCM_TRIUMPH2_SUPPORT) 18888 /* Deallocate flexible stat counters. */ 18889 if (soc_feature(unit, soc_feature_field_vfp_flex_counter)) { 18890 _bcm_esw_flex_stat_release_handles(unit, _bcmFlexStatTypeFp); 18891 } 18892 #endif /* BCM_TRIUMPH2_SUPPORT */ 18893 } else 18894 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 18895 { 18896 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 18897 slice = stage_fc->slices[_FP_DEF_INST] + slice_idx; 18898 if (NULL != slice->counter_bmp.w) { 18899 sal_free (slice->counter_bmp.w); 18900 } 18901 slice->counter_bmp.w = NULL; 18902 } 18903 } 18904 18905 _field_cntr_pools_deinit(unit, stage_fc); 18906 18907 return (BCM_E_NONE); 18908 } 18909 18910 /* 18911 * Function: 18912 * _field_stage_delete 18913 * 18914 * Purpose: 18915 * Deinitialize field stage. 18916 * 18917 * Parameters: 18918 * unit - (IN) BCM device number. 18919 * fc - (IN/OUT)Field control info for device. 18920 * stage_fc - (IN) Stage control structure. 18921 * 18922 * Returns: 18923 * BCM_E_XXX 18924 */ 18925 int 18926 _field_stage_delete(int unit, _field_control_t *fc, _field_stage_t *stage_fc) 18927 { 18928 _field_stage_t *stage_iter; /* Device stages iterator. */ 18929 18930 /* Input parameters check. */ 18931 if (NULL == fc) { 18932 return (BCM_E_PARAM); 18933 } 18934 18935 if (NULL == stage_fc) { 18936 return (BCM_E_NONE); 18937 } 18938 18939 /* Destroy data qualifiers control structure */ 18940 _field_stage_data_ctrl_deinit(unit, stage_fc); 18941 18942 /* Deallocate stage qualifiers */ 18943 _bcm_field_stage_qualifiers_free(unit, stage_fc); 18944 18945 /* Free stage slices info. */ 18946 if (NULL != stage_fc->slices[_FP_DEF_INST]) { 18947 18948 /* Deallocate counters usage bitmap. */ 18949 _field_counters_deinit(unit, stage_fc); 18950 18951 /* Deallocate meters usage bitmap. */ 18952 _field_meters_deinit(unit, stage_fc); 18953 18954 /* Deallocate the entry pointers */ 18955 _bcm_field_stage_entries_free(unit, stage_fc); 18956 18957 /* Deallocate the priority management structures */ 18958 _bcm_field_prio_mgmt_deinit(unit, stage_fc); 18959 18960 sal_free(stage_fc->slices[_FP_DEF_INST]); 18961 stage_fc->slices[_FP_DEF_INST] = NULL; 18962 } 18963 18964 /* destroy all ranges */ 18965 while (stage_fc->ranges != NULL) { 18966 bcm_esw_field_range_destroy(unit, stage_fc->ranges->rid); 18967 } 18968 18969 /* Destroy action profile */ 18970 soc_profile_mem_destroy(unit, &stage_fc->ext_act_profile); 18971 #ifdef BCM_TRIDENT2_SUPPORT 18972 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 18973 soc_profile_mem_destroy(unit, &stage_fc->hash_select[0]); 18974 18975 soc_profile_mem_destroy(unit, &stage_fc->hash_select[1]); 18976 } 18977 #endif 18978 /* Remove stage from stages linked list. */ 18979 stage_iter = fc->stages; 18980 while (NULL != stage_iter) { 18981 if (stage_iter == stage_fc) { 18982 fc->stages = stage_fc->next; 18983 break; 18984 } else if (stage_iter->next == stage_fc) { 18985 stage_iter->next = stage_fc->next; 18986 break; 18987 } 18988 stage_iter = stage_iter->next; 18989 } 18990 18991 /* Free stage info. */ 18992 sal_free(stage_fc); 18993 stage_fc = NULL; 18994 18995 return (BCM_E_NONE); 18996 } 18997 18998 /* 18999 * Function: 19000 * _field_stages_destroy 19001 * 19002 * Purpose: 19003 * Deinitialize field stages within the field control struct. 19004 * 19005 * Parameters: 19006 * unit - (IN) BCM device number. 19007 * fc - (IN/OUT)Field control info for device. 19008 * 19009 * Returns: 19010 * BCM_E_XXX 19011 */ 19012 int 19013 _field_stages_destroy(int unit, _field_control_t *fc) 19014 { 19015 _field_stage_t *stage_fc; /* Stage field control structure. */ 19016 19017 /* Input parameters check. */ 19018 if (fc == NULL) { 19019 return (BCM_E_PARAM); 19020 } 19021 19022 FP_LOCK(unit); 19023 19024 /* Free stages & slices structures. */ 19025 while (NULL != fc->stages) { 19026 stage_fc = fc->stages; 19027 19028 /* Free stage resources & stage itself. */ 19029 _field_stage_delete(unit, fc, stage_fc); 19030 } 19031 19032 FP_UNLOCK(unit); 19033 return (BCM_E_NONE); 19034 } 19035 19036 /* 19037 * Function: 19038 * _field_qset_union 19039 * 19040 * Purpose: 19041 * make a union of two qsets 19042 * 19043 * Parameters: 19044 * qset1 - source 1 19045 * qset2 - source 2 19046 * qset_union - (OUT) result of union operation 19047 * 19048 * Returns: 19049 * BCM_E_NONE - Success 19050 */ 19051 int 19052 _field_qset_union(const bcm_field_qset_t *qset1, 19053 const bcm_field_qset_t *qset2, 19054 bcm_field_qset_t *qset_union) 19055 { 19056 int idx; 19057 19058 if (NULL == qset_union) { 19059 return (BCM_E_PARAM); 19060 } 19061 19062 19063 /* Perform the union of the qualifier bitmap. */ 19064 for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) { 19065 qset_union->w[idx] = qset1->w[idx] | qset2->w[idx]; 19066 } 19067 19068 /* Perform the union of the qualifier udfs. */ 19069 for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_USER_NUM_UDFS); idx++) { 19070 qset_union->udf_map[idx] = qset1->udf_map[idx] | qset2->udf_map[idx]; 19071 } 19072 19073 return (BCM_E_NONE); 19074 } 19075 19076 /* 19077 * Function: 19078 * _field_qset_is_subset 19079 * Purpose: 19080 * Determine if qset one is a subset of qset two. 19081 * Parameters: 19082 * qset_1 19083 * qset_2 19084 * Returns: 19085 * TRUE - if 'qset_1' is a subset of 'qset_2' 19086 * FALSE - if 'qset_1' is NOT a subset of 'qset_2' 19087 */ 19088 int 19089 _field_qset_is_subset(const bcm_field_qset_t *qset_1, 19090 const bcm_field_qset_t *qset_2) 19091 { 19092 int idx; 19093 19094 for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) { 19095 if ((qset_1->w[idx] | qset_2->w[idx]) & ~qset_2->w[idx]) { 19096 return (FALSE); 19097 } 19098 } 19099 return (TRUE); 19100 } 19101 19102 /* 19103 * Function: 19104 * _field_qset_diff 19105 * Purpose: 19106 * Calculate the result of subtracting qset_2 from qset_1 19107 * Parameters: 19108 * qset_1 - First parameter 19109 * qset_2 - Second parameter 19110 * Returns: 19111 * (qset_1 - qset_2) 19112 */ 19113 bcm_field_qset_t 19114 _field_qset_diff(const bcm_field_qset_t qset_1, 19115 const bcm_field_qset_t qset_2) 19116 { 19117 int idx; 19118 bcm_field_qset_t qset_result; 19119 19120 BCM_FIELD_QSET_INIT(qset_result); 19121 for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) { 19122 qset_result.w[idx] = qset_1.w[idx] & ~qset_2.w[idx]; 19123 } 19124 return qset_result; 19125 } 19126 19127 /* 19128 * Function: 19129 * _field_qset_is_empty 19130 * Purpose: 19131 * Detect empty Qsets 19132 * Parameters: 19133 * qset - Qset to be tested 19134 * Returns: 19135 * 1 if qset has no qualifiers 19136 * 0 if qset has at least one qualifier 19137 */ 19138 int 19139 _field_qset_is_empty(const bcm_field_qset_t qset) 19140 { 19141 int idx; 19142 19143 for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) { 19144 if (qset.w[idx] != 0) { 19145 return 0; 19146 } 19147 } 19148 return 1; 19149 } 19150 19151 /* 19152 * Function: 19153 * _bcm_field_qset_test 19154 * Purpose: 19155 * Identify if qualifier is part of the qset. 19156 * Parameters: 19157 * qid - Qualifier id. 19158 * qset - Qset to be tested 19159 * result - Result 19160 * Returns: 19161 * BCM_E_XXX 19162 */ 19163 int 19164 _bcm_field_qset_test(bcm_field_qualify_t qid, bcm_field_qset_t *qset, 19165 uint8 *result) 19166 { 19167 bcm_field_qset_t test_qset; 19168 19169 /* Input parameters check. */ 19170 if ((NULL == qset) || (NULL == result)) { 19171 return (BCM_E_PARAM); 19172 } 19173 19174 BCM_FIELD_QSET_INIT(test_qset); 19175 BCM_FIELD_QSET_ADD(test_qset, qid); 19176 19177 *result = (_field_qset_is_subset(&test_qset, qset)) ? TRUE : FALSE; 19178 return (BCM_E_NONE); 19179 } 19180 19181 /* 19182 * Function: _bcm_esw_field_group_mode_get 19183 * 19184 * Purpose: 19185 * Return the mode of a Group ID. This is its single, double or triple-wide 19186 * state. Mode specified the number of slices allocated to the group. 19187 * 19188 * Parameters: 19189 * flags - (IN) Field group flags. 19190 * mode - (OUT) single, double, triple or auto mode. 19191 * 19192 * Returns: 19193 * BCM_E_XXX 19194 */ 19195 int 19196 _bcm_esw_field_group_mode_get(uint32 flags, bcm_field_group_mode_t *mode) 19197 { 19198 /* Input parameters check. */ 19199 if (mode == NULL) { 19200 return (BCM_E_PARAM); 19201 } 19202 19203 if (flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 19204 *mode = bcmFieldGroupModeTriple; 19205 } else if (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 19206 if (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 19207 *mode = bcmFieldGroupModeQuad; 19208 } else { 19209 *mode = bcmFieldGroupModeDouble; 19210 } 19211 } else if (flags & _FP_GROUP_SPAN_SINGLE_SLICE) { 19212 if (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 19213 *mode = bcmFieldGroupModeIntraSliceDouble; 19214 } else if (flags & _FP_GROUP_DW_DEPTH_EXPANDED) { 19215 *mode = bcmFieldGroupModeDouble; 19216 } else { 19217 *mode = bcmFieldGroupModeSingle; 19218 } 19219 } 19220 return (BCM_E_NONE); 19221 } 19222 19223 /* 19224 * Function: 19225 * _field_qual_name 19226 * Purpose: 19227 * Translate a Qualifier enum value to a text string. 19228 * Parameters: 19229 * Enum value from bcm_field_qualify_e. (ex.bcmFieldQualifyInPorts) 19230 * Returns: 19231 * Text name of indicated qualifier enum value. 19232 */ 19233 char * 19234 _field_qual_name(bcm_field_qualify_t qid) 19235 { 19236 /* Text names of the enumerated qualifier IDs. */ 19237 static char *qual_text[bcmFieldQualifyCount] = BCM_FIELD_QUALIFY_STRINGS; 19238 static char *_qual_text[_bcmFieldQualifyCount - bcmFieldQualifyCount] = 19239 _BCM_FIELD_QUALIFY_STRINGS; 19240 19241 if (qid < bcmFieldQualifyCount) { 19242 return qual_text[qid]; 19243 } else if ((int)qid < _bcmFieldQualifyCount) { 19244 return _qual_text[qid - bcmFieldQualifyCount]; 19245 } 19246 return "UnknownQualifier"; 19247 } 19248 19249 /* 19250 * Function: 19251 * _field_stage_name 19252 * Purpose: 19253 * Translate group pipeline stage to a text string. 19254 * Parameters: 19255 * stage_fc stage field control structure. 19256 * Returns: 19257 * Text name of indicated stage qualifier enum value. 19258 */ 19259 char * 19260 _field_stage_name(_field_stage_t *stage_fc) 19261 { 19262 static char *stage_text[] = _BCM_FIELD_STAGE_STRINGS; 19263 19264 if (stage_fc->stage_id >= COUNTOF(stage_text)) { 19265 return "??"; 19266 } 19267 return stage_text[stage_fc->stage_id]; 19268 } 19269 19270 /* 19271 * Function: 19272 * _field_action_name 19273 * Purpose: 19274 * Return text name of indicated action enum value. 19275 */ 19276 char * 19277 _field_action_name(bcm_field_action_t action) 19278 { 19279 /* Text names of Actions. These are used for debugging output and CLIs. 19280 * Note that the order needs to match the bcm_field_action_t enum order. 19281 */ 19282 static char *action_text[] = BCM_FIELD_ACTION_STRINGS; 19283 assert(COUNTOF(action_text) == bcmFieldActionCount); 19284 19285 return (action >= bcmFieldActionCount ? "??" : action_text[action]); 19286 } 19287 19288 19289 /* 19290 * Function: 19291 * _field_group_mode_name 19292 * Purpose: 19293 * Return text name of indicated group mode enum value. 19294 */ 19295 char * 19296 _field_group_mode_name(int unit, uint32 group_flags, 19297 _field_stage_t *stage_fc) 19298 { 19299 bcm_field_group_mode_t mode = 0; 19300 static char *mode_text[bcmFieldGroupModeCount] = 19301 BCM_FIELD_GROUP_MODE_STRINGS; 19302 19303 _bcm_esw_field_group_mode_get(group_flags, &mode); 19304 #if defined (BCM_TOMAHAWK3_SUPPORT) || defined (BCM_HELIX5_SUPPORT) 19305 if ((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) || 19306 soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support)) && 19307 (mode == bcmFieldGroupModeIntraSliceDouble) && 19308 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 19309 mode = bcmFieldGroupModeSingle; 19310 } 19311 #endif 19312 19313 return (mode >= bcmFieldGroupModeCount ? "??" : mode_text[mode]); 19314 } 19315 19316 /* Section: Field Initialization */ 19317 19318 /* 19319 * Function: _field_control_free 19320 * 19321 * Purpose: 19322 * Free field_control structure. 19323 * 19324 * Parameters: 19325 * unit - (IN) BCM device number 19326 * fc - (IN) Field control structure. 19327 * 19328 * Returns: 19329 * BCM_E_XXX 19330 */ 19331 int 19332 _field_control_free(int unit, _field_control_t *fc) 19333 { 19334 #ifdef BCM_TOMAHAWK_SUPPORT 19335 int inst; /* Instance Iterator. */ 19336 int lt_idx; /* Logical Table Index. */ 19337 #endif 19338 19339 if (NULL == fc) { 19340 return (BCM_E_NONE); 19341 } 19342 19343 /* Free policers lookup hash. */ 19344 if (NULL != fc->policer_hash) { 19345 sal_free(fc->policer_hash); 19346 fc->policer_hash = NULL; 19347 } 19348 19349 /* Free counters lookup hash. */ 19350 if (NULL != fc->stat_hash) { 19351 sal_free(fc->stat_hash); 19352 fc->stat_hash = NULL; 19353 } 19354 19355 /* Free udf configuration. */ 19356 if (NULL != fc->udf) { 19357 sal_free(fc->udf); 19358 fc->udf = NULL; 19359 } 19360 19361 /* Free Hints lookup hash. */ 19362 if (NULL != fc->hints_hash) { 19363 sal_free(fc->hints_hash); 19364 fc->hints_hash = NULL; 19365 } 19366 19367 /* Free Hints bitmap. */ 19368 if (NULL != fc->hintid_bmp.w) { 19369 sal_free(fc->hintid_bmp.w); 19370 fc->hintid_bmp.w = NULL; 19371 } 19372 19373 #ifdef BCM_TOMAHAWK_SUPPORT 19374 /* Free presel lookup database. */ 19375 if (NULL != fc->presel_db) { 19376 sal_free(fc->presel_db); 19377 fc->presel_db = NULL; 19378 } 19379 19380 /* Free presel information. */ 19381 if (NULL != fc->presel_info) { 19382 sal_free(fc->presel_info); 19383 fc->presel_info = NULL; 19384 } 19385 19386 /* Free logical table information. */ 19387 for (inst = 0; inst < NUM_PIPE(unit); inst++) { 19388 for (lt_idx = 0; lt_idx < _FP_MAX_NUM_LT; lt_idx++) { 19389 if (NULL != fc->lt_info[inst][lt_idx]) { 19390 sal_free(fc->lt_info[inst][lt_idx]->lt_part_pri); 19391 sal_free(fc->lt_info[inst][lt_idx]); 19392 fc->lt_info[inst][lt_idx] = NULL; 19393 } 19394 } 19395 } 19396 #endif 19397 19398 #if defined (BCM_TRIUMPH3_SUPPORT) 19399 /* Free L2changeFields bitmap. */ 19400 if( (SOC_IS_TRIUMPH3(unit)) && 19401 (NULL != fc->field_action_l2mod_index_bmp.w) ) { 19402 sal_free (fc->field_action_l2mod_index_bmp.w); 19403 fc->field_action_l2mod_index_bmp.w = NULL; 19404 } 19405 #endif 19406 19407 /* 19408 * Retaining "fc" during bcm_field_init for retaining Sticky ExactMatch stage. 19409 */ 19410 if (0 == (fc->flags & _FP_EXACTMATCH_STAGE_SKIP_DETACH)) { 19411 /* Free module control structure. */ 19412 sal_free(fc); 19413 _field_control[unit] = NULL; 19414 } 19415 19416 return (BCM_E_NONE); 19417 } 19418 19419 /* 19420 * Function: 19421 * _field_egr_ports_recovery_control_free 19422 * Purpose: 19423 * Free f_egr_recovery structure 19424 * Parameters: 19425 * unit - (IN) BCM unit number. 19426 * f_egr_recovery - (OUT) Field Egr_ports_recovery 19427 * structure. 19428 * Returns: 19429 * BCM_E_XXX 19430 */ 19431 19432 int 19433 _field_egr_ports_recovery_control_free (int unit, 19434 _field_egr_ports_recovery_t *f_egr_recovery 19435 ) 19436 { 19437 _field_egr_ports_recovery[unit] = NULL; 19438 19439 if (NULL == f_egr_recovery) { 19440 return (BCM_E_PARAM); 19441 } 19442 19443 if (f_egr_recovery->entry_recover_egr_ports != NULL) { 19444 sal_free (f_egr_recovery->entry_recover_egr_ports); 19445 f_egr_recovery->entry_recover_egr_ports = NULL; 19446 } 19447 19448 sal_free (f_egr_recovery); 19449 f_egr_recovery = NULL; 19450 19451 return BCM_E_NONE; 19452 } 19453 19454 19455 /* 19456 * Function: 19457 * _bcm_field_stages_supported_qset_init 19458 * 19459 * Purpose: 19460 * Initialize field stages supported qset for each stage 19461 * 19462 * Parameters: 19463 * unit - (IN) BCM device number. 19464 * 19465 * Returns: 19466 * BCM_E_NONE - Success 19467 * BCM_E_MEMORY - Allocation failure 19468 */ 19469 int 19470 _bcm_field_stages_supported_qset_init(int unit, _field_control_t *fc) 19471 { 19472 _field_stage_t *stage_fc; /* Stage field control structure. */ 19473 bcm_field_qset_t *qset; /* Operation result. */ 19474 int idx; /* Iteration index. */ 19475 #if defined(BCM_TOMAHAWK_SUPPORT) 19476 bcmi_keygen_qual_cfg_info_t **qual_cfg_info = NULL; 19477 bcmi_keygen_qual_flags_bmp_t qual_flags; 19478 #endif 19479 19480 /* Fill supported qset for each pipeline stage. */ 19481 stage_fc = fc->stages; 19482 while (NULL != stage_fc) { 19483 qset = &stage_fc->_field_supported_qset; 19484 19485 #if defined (BCM_TOMAHAWK_SUPPORT) 19486 if ((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support)) && 19487 ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) || 19488 (_BCM_FIELD_STAGE_EXACTMATCH == stage_fc->stage_id))) { 19489 if (stage_fc->qual_cfg_info_db != NULL ) { 19490 qual_cfg_info = stage_fc->qual_cfg_info_db->qual_cfg_info; 19491 for (idx = 0; idx < _bcmFieldQualifyCount; idx++) { 19492 if (NULL != qual_cfg_info[idx]) { 19493 if (_BCM_FIELD_STAGE_EXACTMATCH == stage_fc->stage_id) { 19494 qual_flags = qual_cfg_info[idx]->qual_cfg_arr->qual_flags; 19495 if (SHR_BITGET(qual_flags.w, BCMI_KEYGEN_QUAL_FLAGS_NOT_IN_EM)) { 19496 continue; 19497 } 19498 } 19499 BCM_FIELD_QSET_ADD(*qset, 19500 (stage_fc->qual_cfg_info_db->qual_cfg_info[idx])->qual); 19501 } 19502 } 19503 } 19504 } else 19505 #endif 19506 { 19507 if (stage_fc->f_qual_arr != NULL ) { 19508 for (idx = 0; idx < _bcmFieldQualifyCount; idx++) { 19509 if (NULL != stage_fc->f_qual_arr[idx]) { 19510 BCM_FIELD_QSET_ADD(*qset, (stage_fc->f_qual_arr[idx])->qid); 19511 } 19512 } 19513 #if defined(BCM_TOMAHAWK_SUPPORT) 19514 } else if (stage_fc->qual_cfg_info_db != NULL) { 19515 qual_cfg_info = stage_fc->qual_cfg_info_db->qual_cfg_info; 19516 for (idx = 0; idx < BCM_FIELD_QUALIFY_MAX; idx++) { 19517 if (NULL != qual_cfg_info[idx]) { 19518 BCM_FIELD_QSET_ADD(*qset, (qual_cfg_info[idx])->qual); 19519 } 19520 } 19521 #endif 19522 } 19523 } 19524 19525 stage_fc = stage_fc->next; 19526 } 19527 return (BCM_E_NONE); 19528 } 19529 19530 /* 19531 * Function: 19532 * _field_tcam_info_init 19533 * Purpose: 19534 * Initialize TCAM related information in Field Control 19535 * 19536 * Parameters: 19537 * unit - (IN) BCM device number. 19538 * stage_fc - (IN) Stage field control structure pointer. 19539 * fc - (IN/OUT) Field control infoformation for device. 19540 * 19541 * Returns: 19542 * BCM_E_XXX 19543 */ 19544 STATIC int 19545 _field_tcam_info_init(int unit, _field_stage_t *stage_fc, _field_control_t *fc) 19546 { 19547 soc_mem_t mem = INVALIDm; /* FP tcam memory id for stage/device. */ 19548 19549 /* Input parameters check. */ 19550 if ((NULL == fc) || (NULL == stage_fc)) { 19551 return (BCM_E_PARAM); 19552 } 19553 19554 if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) { 19555 #ifdef BCM_TRIUMPH_SUPPORT 19556 if (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) { 19557 stage_fc->tcam_slices = 9; 19558 } 19559 #endif /* BCM_TRIUMPH_SUPPORT */ 19560 return BCM_E_NONE; 19561 } 19562 19563 if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 19564 #ifdef BCM_FIREBOLT_SUPPORT 19565 if (SOC_IS_FBX(unit)) { 19566 mem = FP_TCAMm; 19567 } 19568 #endif /* BCM_FIREBOLT_SUPPORT */ 19569 19570 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 19571 } else if (soc_feature(unit, soc_feature_field_multi_stage)) { 19572 19573 if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) { 19574 mem = VFP_TCAMm; 19575 } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) { 19576 mem = EFP_TCAMm; 19577 } 19578 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT*/ 19579 } else { 19580 return (BCM_E_UNAVAIL); 19581 } 19582 19583 if (INVALIDm == mem) { 19584 return (BCM_E_UNAVAIL); 19585 } 19586 19587 /* Get tcam size. */ 19588 stage_fc->tcam_sz = soc_mem_index_count(unit, mem); 19589 19590 /* Note fc->tcam_slices only counts internal slices. */ 19591 if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 19592 if (soc_feature(unit, soc_feature_field_slices2)) { 19593 stage_fc->tcam_slices = 2; 19594 } else if (soc_feature(unit, soc_feature_field_slices4)) { 19595 stage_fc->tcam_slices = 4; 19596 } else if (soc_feature(unit, soc_feature_field_slices8)) { 19597 stage_fc->tcam_slices = 8; 19598 } else if (soc_feature(unit, soc_feature_field_slices12)) { 19599 stage_fc->tcam_slices = 12; 19600 } else if (soc_feature(unit, soc_feature_field_slices10)) { 19601 stage_fc->tcam_slices = 10; 19602 } else { 19603 stage_fc->tcam_slices = 16; 19604 } 19605 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 19606 } else if (soc_feature(unit, soc_feature_field_multi_stage)) { 19607 if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) { 19608 stage_fc->tcam_slices = 4; 19609 } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) { 19610 stage_fc->tcam_slices = 4; 19611 } else { 19612 return (BCM_E_PARAM); 19613 } 19614 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 19615 } else { 19616 return (BCM_E_PARAM); 19617 } 19618 19619 19620 /* Check external tcam presence for ingress (default stage) */ 19621 /* Only for EasyRider; Triumph taken care of elsewhere */ 19622 fc->tcam_ext_numb = FP_EXT_TCAM_NONE; 19623 19624 return (BCM_E_NONE); 19625 } 19626 19627 19628 /* 19629 * Function: 19630 * _field_meter_pools_init 19631 * Purpose: 19632 * Initialize field meter pools usage bitmap. 19633 * Parameters: 19634 * unit - (IN) BCM device number. 19635 * stage_fc - (IN/OUT) Stage field control structure. 19636 * Returns: 19637 * BCM_E_XXX 19638 */ 19639 STATIC int 19640 _field_meter_pools_init(int unit, _field_stage_t *stage_fc) 19641 { 19642 int meter_pair_num; /* Number of meter pairs. */ 19643 int pool_idx; /* Meter pools iterator. */ 19644 int size; /* Allocation size. */ 19645 uint16 pool_size; /* Total number of meters in pool. */ 19646 #ifdef BCM_TRIUMPH3_SUPPORT 19647 int rv; /* Operation return status. */ 19648 #endif 19649 19650 19651 /* Input parameters check. */ 19652 if (NULL == stage_fc) { 19653 return (BCM_E_PARAM); 19654 } 19655 19656 if (0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) { 19657 return (BCM_E_PARAM); 19658 } 19659 19660 /* Make sure slices array is initialized. */ 19661 if (NULL == stage_fc->slices[_FP_DEF_INST]) { 19662 return (BCM_E_INTERNAL); 19663 } 19664 19665 /* Set number of meters. */ 19666 #if defined(BCM_SCORPION_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 19667 if (soc_feature(unit, soc_feature_field_meter_pools4)) { 19668 meter_pair_num = _BCM_FIELD_SC_INGRESS_DOUBLE_WIDE_SLICE_SZ; 19669 } else 19670 #endif /* BCM_SCORPION_SUPPORT || BCM_TRIDENT_SUPPORT */ 19671 #if defined(BCM_TRIUMPH_SUPPORT) 19672 if ((stage_fc->flags & _FP_STAGE_HALF_SLICE) && \ 19673 (!soc_feature(unit,soc_feature_field_slice_size128))) { 19674 meter_pair_num = _BCM_FIELD_SLICE_SIZE(stage_fc, _FP_DEF_INST, 0); 19675 } else 19676 #endif /* BCM_TRIUMPH_SUPPORT */ 19677 { 19678 meter_pair_num = _BCM_FIELD_SLICE_SIZE(stage_fc, _FP_DEF_INST, 0) >> 1; 19679 #if defined(BCM_HURRICANE1_SUPPORT) 19680 if (SOC_IS_HURRICANE(unit)) { 19681 /* hurricane has 64 meter pairs/pool */ 19682 meter_pair_num = meter_pair_num / 2; 19683 } 19684 #endif /* BCM_HURRICANE1_SUPPORT */ 19685 } 19686 19687 pool_size = (meter_pair_num * 2); 19688 19689 /* Get number of meter pools for the device. */ 19690 if (soc_feature(unit, soc_feature_field_meter_pools4)) { 19691 stage_fc->num_meter_pools = 4; 19692 } else if (soc_feature(unit, soc_feature_field_meter_pools8)) { 19693 stage_fc->num_meter_pools = 8; 19694 } else if (soc_feature(unit, soc_feature_field_meter_pools12)) { 19695 stage_fc->num_meter_pools = 12; 19696 } else { 19697 stage_fc->num_meter_pools = 16; 19698 } 19699 19700 #ifdef BCM_TRIUMPH3_SUPPORT 19701 if (SOC_IS_TRIUMPH3(unit)) { 19702 BCM_IF_ERROR_RETURN(_bcm_field_tr3_meter_pool_info(unit, 19703 stage_fc, 19704 &stage_fc->num_meter_pools, 19705 &meter_pair_num, &pool_size) 19706 ); 19707 } 19708 #endif 19709 19710 /* Total meters per pool = 2 * (No. of meter pairs) */ 19711 size = SHR_BITALLOCSIZE(meter_pair_num << 1); 19712 19713 for (pool_idx = 0; pool_idx < stage_fc->num_meter_pools; pool_idx++) { 19714 /* Allocate pool usage bitmap. */ 19715 stage_fc->meter_pool[_FP_DEF_INST][pool_idx] = 19716 sal_alloc(sizeof(_field_meter_pool_t), "fp_meter_pool"); 19717 if (stage_fc->meter_pool[_FP_DEF_INST][pool_idx] == NULL) { 19718 _field_meters_deinit (unit, stage_fc); 19719 return (BCM_E_MEMORY); 19720 } 19721 19722 /* Initalize stage meter pool info. */ 19723 /* Pool is not in use. */ 19724 stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->slice_id = -1; 19725 /* Level not yet set */ 19726 stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->level = -1; 19727 /* Total number of meters in pool. */ 19728 stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->pool_size = pool_size; 19729 /* Number of valid meters in pool.*/ 19730 stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->size = (meter_pair_num 19731 * 2); 19732 stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->free_meters = 19733 (meter_pair_num * 2); 19734 stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->num_meter_pairs = 19735 meter_pair_num; 19736 stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->meter_bmp.w = 19737 sal_alloc(size, "fp_meters_map"); 19738 if (stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->meter_bmp.w == NULL) { 19739 _field_meters_deinit(unit, stage_fc); 19740 return (BCM_E_MEMORY); 19741 } 19742 19743 /* Reset pool usage bitmap. */ 19744 sal_memset(stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->meter_bmp.w, 19745 0, size); 19746 } 19747 19748 #ifdef BCM_TRIUMPH3_SUPPORT 19749 /* Logical Pools supported in Triumph3.Init corresponding 19750 * data structures. 19751 */ 19752 if (SOC_IS_TRIUMPH3(unit)) { 19753 rv = _field_tr3_logical_meter_pools_init (unit, stage_fc); 19754 if (rv == BCM_E_MEMORY) { 19755 _field_meters_deinit(unit, stage_fc); 19756 } 19757 return (rv); 19758 } 19759 #endif 19760 return BCM_E_NONE; 19761 } 19762 19763 19764 STATIC int 19765 _field_cntr_pool_info(int unit, 19766 _field_stage_t *stage_fc, 19767 unsigned *cntrs_per_pool 19768 ) 19769 { 19770 stage_fc->num_cntr_pools = 0; 19771 19772 #ifdef BCM_TRIUMPH3_SUPPORT 19773 if (SOC_IS_TRIUMPH3(unit)) { 19774 BCM_IF_ERROR_RETURN(_bcm_field_tr3_cntr_pool_info(unit, 19775 stage_fc, 19776 &stage_fc->num_cntr_pools, 19777 cntrs_per_pool 19778 ) 19779 ); 19780 } 19781 #endif 19782 19783 return (BCM_E_NONE); 19784 } 19785 19786 19787 STATIC int 19788 _field_cntr_pools_init(int unit, _field_stage_t *stage_fc) 19789 { 19790 int errcode = BCM_E_NONE; 19791 unsigned cntrs_per_pool, bmap_size_bytes, n; 19792 _field_cntr_pool_t **pp, *p; 19793 19794 /* Input parameters check. */ 19795 if (NULL == stage_fc) { 19796 return (BCM_E_PARAM); 19797 } 19798 19799 /* Make sure slices array is initialized. */ 19800 if (NULL == stage_fc->slices[_FP_DEF_INST]) { 19801 return (BCM_E_INTERNAL); 19802 } 19803 19804 BCM_IF_ERROR_RETURN(_field_cntr_pool_info(unit, 19805 stage_fc, 19806 &cntrs_per_pool 19807 ) 19808 ); 19809 19810 bmap_size_bytes = SHR_BITALLOCSIZE(cntrs_per_pool); 19811 19812 for (pp = stage_fc->cntr_pool, n = stage_fc->num_cntr_pools; n; --n, ++pp) { 19813 if ((p = SAL_ALLOC_T(_field_cntr_pool_t, 1)) == 0) { 19814 errcode = BCM_E_MEMORY; 19815 break; 19816 } 19817 19818 p->slice_id = -1; 19819 p->size = p->free_cntrs = cntrs_per_pool; 19820 if ((p->cntr_bmp.w = (SHR_BITDCL *) sal_alloc(bmap_size_bytes, " ")) == 0) { 19821 sal_free(p); 19822 errcode = BCM_E_MEMORY; 19823 break; 19824 } 19825 sal_memset(p->cntr_bmp.w, 0, bmap_size_bytes); 19826 19827 *pp = p; 19828 } 19829 19830 if (errcode != BCM_E_NONE) { 19831 _field_counters_deinit(unit, stage_fc); 19832 } 19833 19834 return (errcode); 19835 } 19836 19837 19838 /* 19839 * Function: 19840 * _field_meters_init 19841 * Purpose: 19842 * Initialize field slice meters usage bitmap. 19843 * 19844 * Parameters: 19845 * unit - (IN) BCM device number. 19846 * fc - (IN) Field control structure. 19847 * stage_fc - (IN/OUT) Stage field control structure. 19848 * 19849 * Returns: 19850 * BCM_E_XXX 19851 * Notes: 19852 * Triumph External stage uses the same meter pool as Ingress 19853 * It is inited in _field_external_meters_init 19854 */ 19855 STATIC int 19856 _field_meters_init(int unit, _field_stage_t *stage_fc) 19857 { 19858 int slice_idx; /* Slices iterator. */ 19859 int size; /* Allocation size. */ 19860 _field_slice_t *fs; /* Slice config structure. */ 19861 19862 /* Input parameters check. */ 19863 if (NULL == stage_fc) { 19864 return (BCM_E_PARAM); 19865 } 19866 19867 19868 /* External config was not processed yet - don't initialize meters. 19869 * Lookup stage has no meter support. 19870 */ 19871 if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL 19872 || stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 19873 return (BCM_E_NONE); 19874 } 19875 19876 /* Make sure slices array is initialized. */ 19877 if (NULL == stage_fc->slices[_FP_DEF_INST]) { 19878 return (BCM_E_INTERNAL); 19879 } 19880 19881 /* 19882 * For devices with global meter pools 19883 * Initialize meter pools, skip slice bounded meters . 19884 */ 19885 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 19886 return _field_meter_pools_init(unit, stage_fc); 19887 } 19888 19889 size = SHR_BITALLOCSIZE(_BCM_FIELD_SLICE_SIZE(stage_fc, _FP_DEF_INST, 0)); 19890 19891 /* Iterate over slices & initialize meter infor. */ 19892 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 19893 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 19894 19895 /* Allocate meter usage bitmap. */ 19896 fs->meter_bmp.w = sal_alloc(size, "fp_meters_map"); 19897 if (NULL == fs->meter_bmp.w) { 19898 _field_meters_deinit(unit, stage_fc); 19899 return (BCM_E_MEMORY); 19900 } 19901 19902 /* Set slice meter count & reset usage bitmap. */ 19903 fs->meters_count = _BCM_FIELD_SLICE_SIZE(stage_fc, _FP_DEF_INST, 0); 19904 sal_memset(fs->meter_bmp.w, 0, size); 19905 } 19906 return (BCM_E_NONE); 19907 } 19908 19909 /* 19910 * Function: 19911 * _field_external_meters_init 19912 * Purpose: 19913 * Initialize field meters for external FP 19914 * Parameters: 19915 * unit - (IN) BCM device number. 19916 * fc - (IN) Field control structure 19917 * Returns: 19918 * BCM_E_XXX 19919 */ 19920 STATIC int 19921 _field_external_meters_init(int unit, _field_control_t *fc) 19922 { 19923 int i; 19924 _field_stage_t *stage_ingress, *stage_external, *stage_p; 19925 19926 stage_external = stage_ingress = NULL; 19927 stage_p = fc->stages; 19928 19929 while (stage_p) { 19930 if (stage_p->stage_id == _BCM_FIELD_STAGE_INGRESS) { 19931 stage_ingress = stage_p; 19932 } else if (stage_p->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 19933 stage_external = stage_p; 19934 } 19935 stage_p = stage_p->next; 19936 } 19937 if ((stage_ingress == NULL) || (stage_external == NULL)) { 19938 return (BCM_E_INTERNAL); 19939 } 19940 19941 stage_external->flags |= _FP_STAGE_GLOBAL_METER_POOLS; 19942 stage_external->num_meter_pools = stage_ingress->num_meter_pools; 19943 for (i = 0; i < stage_external->num_meter_pools; i++) { 19944 if (stage_ingress->meter_pool[_FP_DEF_INST][i] == NULL) { 19945 return (BCM_E_INTERNAL); 19946 } 19947 stage_external->meter_pool[_FP_DEF_INST][i] 19948 = stage_ingress->meter_pool[_FP_DEF_INST][i]; 19949 } 19950 return (BCM_E_NONE); 19951 } 19952 19953 /* 19954 * Function: 19955 * _field_slice_counters_alloc 19956 * Purpose: 19957 * Allocate counters usage bitmap for a slice. 19958 * 19959 * Parameters: 19960 * unit - (IN) BCM device number. 19961 * fs - (IN/OUT) Slice control structure. 19962 * 19963 * Returns: 19964 * BCM_E_XXX 19965 */ 19966 STATIC int 19967 _field_slice_counters_alloc(int unit, _field_slice_t *fs) 19968 { 19969 int size; /* Allocation size. */ 19970 /* Input parameters check. */ 19971 if (NULL == fs) { 19972 return (BCM_E_PARAM); 19973 } 19974 19975 size = SHR_BITALLOCSIZE(fs->counters_count); 19976 fs->counter_bmp.w = sal_alloc(size, "fp_counter_map"); 19977 if (NULL == fs->counter_bmp.w) { 19978 return (BCM_E_MEMORY); 19979 } 19980 sal_memset(fs->counter_bmp.w, 0, size); 19981 return (BCM_E_NONE); 19982 } 19983 19984 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 19985 /* 19986 * Function: 19987 * _field_slice_counters_share 19988 * Purpose: 19989 * Share counters usage bitmap between slices. 19990 * 19991 * Parameters: 19992 * unit - (IN) BCM device number. 19993 * stage_fc - (IN/OUT) Stage field control structure. 19994 * slice_src - (IN) Slice sharing counters. 19995 * slice_dst - (IN) Slice receivingshared counters. 19996 * 19997 * Returns: 19998 * BCM_E_XXX 19999 */ 20000 STATIC int 20001 _field_slice_counters_share(int unit, _field_stage_t *stage_fc, 20002 int slice_src, int slice_dst) 20003 { 20004 20005 /* Input parameters check. */ 20006 if (NULL == stage_fc) { 20007 return (BCM_E_PARAM); 20008 } 20009 20010 if (((slice_src < 0) || (slice_src >= stage_fc->tcam_slices)) || 20011 ((slice_dst < 0) || (slice_dst >= stage_fc->tcam_slices))) { 20012 return (BCM_E_PARAM); 20013 } 20014 20015 stage_fc->slices[_FP_DEF_INST][slice_dst].counter_bmp.w = 20016 stage_fc->slices[_FP_DEF_INST][slice_src].counter_bmp.w; 20017 20018 return (BCM_E_NONE); 20019 } 20020 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 20021 20022 20023 /* 20024 * Function: 20025 * _field_counter_memacc_alloc 20026 * Purpose: 20027 * Initialize software cached memory access info for field counters 20028 * 20029 * Parameters: 20030 * unit - (IN) BCM device number. 20031 * mem - (IN) Counter memory. 20032 * descr - (IN) Counter descriptor. 20033 * ptr - (OUT) Allocated pointer. 20034 * Returns: 20035 * BCM_E_XXX 20036 */ 20037 STATIC int 20038 _field_counter_memacc_alloc(int unit, soc_memacc_t **memacc_ptr) 20039 { 20040 int mem_size; 20041 20042 /* Input parameters check. */ 20043 if (NULL == memacc_ptr) { 20044 return (BCM_E_PARAM); 20045 } 20046 20047 mem_size = _FIELD_COUNTER_MEMACC_NUM * sizeof(soc_memacc_t); 20048 *memacc_ptr = sal_alloc(mem_size, "FP counter memory access cache"); 20049 if (NULL == *memacc_ptr) { 20050 return (BCM_E_MEMORY); 20051 } 20052 sal_memset(*memacc_ptr, 0, mem_size); 20053 return (BCM_E_NONE); 20054 } 20055 /* 20056 * Function: 20057 * _field_counter_collect_init 20058 * Purpose: 20059 * Initialize software field 64bit counters. 20060 * 20061 * Parameters: 20062 * unit - (IN) BCM device number. 20063 * fc - (IN) Field control structure. 20064 * stage_fc - (IN/OUT) Stage field control structure. 20065 * 20066 * Returns: 20067 * BCM_E_XXX 20068 */ 20069 STATIC int 20070 _field_counter_collect_init(int unit, _field_control_t *fc, 20071 _field_stage_t *stage_fc) 20072 { 20073 soc_mem_t counter_x_mem; /* Pipeline 1 counters memory. */ 20074 soc_mem_t counter_y_mem; /* Pipeline 2 counters memory. */ 20075 soc_memacc_t *memacc_list; /* Memory access cache list. */ 20076 int retval = BCM_E_NONE; /* Operation return status. */ 20077 20078 /* Input parameters check. */ 20079 if (NULL == stage_fc) { 20080 return (BCM_E_PARAM); 20081 } 20082 20083 #if defined(BCM_TOMAHAWK_SUPPORT) 20084 if (stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) { 20085 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 20086 return BCM_E_NONE; 20087 } 20088 } 20089 #endif 20090 20091 /* 20092 * For counter collection in chunks 20093 * Relevant for External Counter Table of Triumph 20094 */ 20095 stage_fc->counter_collect_table = 0; 20096 stage_fc->counter_collect_index = 0; 20097 20098 BCM_IF_ERROR_RETURN(_field_counter_mem_get(unit, stage_fc, 20099 &counter_x_mem, &counter_y_mem)); 20100 20101 /* Check if stage has counters. */ 20102 if (INVALIDm == counter_x_mem) { 20103 return (BCM_E_NONE); 20104 } 20105 20106 /* Allocate space for cached counter memory access info */ 20107 retval = _field_counter_memacc_alloc(unit, 20108 &(stage_fc->_field_memacc_counters)); 20109 if (BCM_FAILURE(retval)) { 20110 return (retval); 20111 } 20112 memacc_list = stage_fc->_field_memacc_counters; 20113 20114 #if defined(BCM_TRX_SUPPORT) 20115 if (stage_fc->flags & _FP_STAGE_SEPARATE_PACKET_BYTE_COUNTERS) { 20116 retval = _field_counter32_collect_alloc(unit, counter_x_mem, 20117 "FP pipeline X counters", 20118 &stage_fc->_field_x32_counters); 20119 if (BCM_FAILURE(retval)) { 20120 _field_counter_collect_deinit(unit, stage_fc); 20121 return (retval); 20122 } 20123 20124 retval = _field_counter64_collect_alloc(unit, counter_x_mem, 20125 "FP pipeline X byte counters", 20126 &stage_fc->_field_x64_counters); 20127 if(BCM_FAILURE(retval)) { 20128 _field_counter_collect_deinit(unit, stage_fc); 20129 return (retval); 20130 } 20131 20132 retval = soc_memacc_init(unit, counter_x_mem, BYTE_COUNTERf, 20133 &(memacc_list[_FIELD_COUNTER_MEMACC_BYTE])); 20134 if(BCM_FAILURE(retval)) { 20135 _field_counter_collect_deinit(unit, stage_fc); 20136 return (retval); 20137 } 20138 20139 retval = soc_memacc_init(unit, counter_x_mem, PACKET_COUNTERf, 20140 &(memacc_list[_FIELD_COUNTER_MEMACC_PACKET])); 20141 if(BCM_FAILURE(retval)) { 20142 _field_counter_collect_deinit(unit, stage_fc); 20143 return (retval); 20144 } 20145 20146 #if defined (BCM_SCORPION_SUPPORT) 20147 if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 20148 retval = _field_counter32_collect_alloc(unit, counter_y_mem, 20149 "FP pipeline Y counters", 20150 &stage_fc->_field_y32_counters); 20151 if(BCM_FAILURE(retval)) { 20152 _field_counter_collect_deinit(unit, stage_fc); 20153 return (retval); 20154 } 20155 20156 retval = _field_counter64_collect_alloc(unit, counter_y_mem, 20157 "FP pipeline Y byte counters", 20158 &stage_fc->_field_y64_counters); 20159 if(BCM_FAILURE(retval)) { 20160 _field_counter_collect_deinit(unit, stage_fc); 20161 return (retval); 20162 } 20163 20164 retval = soc_memacc_init(unit, counter_y_mem, BYTE_COUNTERf, 20165 &(memacc_list[_FIELD_COUNTER_MEMACC_BYTE_Y])); 20166 if(BCM_FAILURE(retval)) { 20167 _field_counter_collect_deinit(unit, stage_fc); 20168 return (retval); 20169 } 20170 20171 retval = soc_memacc_init(unit, counter_y_mem, PACKET_COUNTERf, 20172 &(memacc_list[_FIELD_COUNTER_MEMACC_PACKET_Y])); 20173 if(BCM_FAILURE(retval)) { 20174 _field_counter_collect_deinit(unit, stage_fc); 20175 return (retval); 20176 } 20177 20178 } 20179 #endif /* BCM_SCORPION_SUPPORT */ 20180 } else 20181 #endif /* BCM_TRX_SUPPORT */ 20182 20183 #if defined(BCM_BRADLEY_SUPPORT) 20184 if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 20185 retval = _field_counter64_collect_alloc(unit, counter_x_mem, 20186 "FP pipeline X byte cntrs", 20187 &stage_fc->_field_x64_counters); 20188 if(BCM_FAILURE(retval)) { 20189 _field_counter_collect_deinit(unit, stage_fc); 20190 return (retval); 20191 } 20192 20193 retval = soc_memacc_init(unit, counter_x_mem, COUNTERf, 20194 &(memacc_list[_FIELD_COUNTER_MEMACC_COUNTER])); 20195 if(BCM_FAILURE(retval)) { 20196 _field_counter_collect_deinit(unit, stage_fc); 20197 return (retval); 20198 } 20199 20200 retval = _field_counter64_collect_alloc(unit, counter_y_mem, 20201 "FP pipeline Y byte cntrs", 20202 &stage_fc->_field_y64_counters); 20203 if(BCM_FAILURE(retval)) { 20204 _field_counter_collect_deinit(unit, stage_fc); 20205 return (retval); 20206 } 20207 20208 retval = soc_memacc_init(unit, counter_y_mem, COUNTERf, 20209 &(memacc_list[_FIELD_COUNTER_MEMACC_COUNTER_Y])); 20210 if(BCM_FAILURE(retval)) { 20211 _field_counter_collect_deinit(unit, stage_fc); 20212 return (retval); 20213 } 20214 } else 20215 #endif /* BCM_BRADLEY_SUPPORT */ 20216 { 20217 retval = _field_counter32_collect_alloc(unit, counter_x_mem, 20218 "FP pipeline X counters", 20219 &stage_fc->_field_x32_counters); 20220 if(BCM_FAILURE(retval)) { 20221 _field_counter_collect_deinit(unit, stage_fc); 20222 return (retval); 20223 } 20224 20225 retval = soc_memacc_init(unit, counter_x_mem, COUNTERf, 20226 &(memacc_list[_FIELD_COUNTER_MEMACC_COUNTER])); 20227 if(BCM_FAILURE(retval)) { 20228 _field_counter_collect_deinit(unit, stage_fc); 20229 return (retval); 20230 } 20231 } 20232 20233 return (retval); 20234 } 20235 20236 /* 20237 * Function: 20238 * _field_counters_init 20239 * Purpose: 20240 * Initialize field slice counters bitmap. 20241 * 20242 * Parameters: 20243 * unit - (IN) BCM device number. 20244 * fc - (IN) Field control structure. 20245 * stage_fc - (IN/OUT) Stage field control structure. 20246 * 20247 * Returns: 20248 * BCM_E_XXX 20249 */ 20250 20251 STATIC int 20252 _field_counters_init(int unit, _field_control_t *fc, 20253 _field_stage_t *stage_fc) 20254 { 20255 _field_slice_t *fs; /* Slice config structure. */ 20256 int slice_idx; /* Slices iterator. */ 20257 int retval; /* Operation return value. */ 20258 int cntr_share = FALSE; /* Share counter with slice 0 */ 20259 20260 /* Input parameters check. */ 20261 if (NULL == stage_fc) { 20262 return (BCM_E_PARAM); 20263 } 20264 20265 /* Make sure slices array is initialized. */ 20266 if (NULL == stage_fc->slices[_FP_DEF_INST]) { 20267 return (BCM_E_INTERNAL); 20268 } 20269 20270 /* Allocate software 64 bit counters image. */ 20271 BCM_IF_ERROR_RETURN(_field_counter_collect_init(unit, fc, stage_fc)); 20272 20273 #if defined(BCM_TRIUMPH_SUPPORT) \ 20274 || defined(BCM_TRIUMPH2_SUPPORT) \ 20275 || defined(BCM_TRIUMPH3_SUPPORT) 20276 /* 20277 * There is an 1-1 mapping between rules and counters 20278 * for external FP, so no bitmap needs to be allocated (Triumph and 20279 * Triumph2); Triumph3 EXTFP can access only flex counters. 20280 */ 20281 if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) { 20282 return (BCM_E_NONE); 20283 } 20284 #endif /* BCM_TRIUMPH_SUPPORT || BCM_TRIUMPH2_SUPPORT || BCM_TRIUMPH3_SUPPORT */ 20285 20286 if (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) { 20287 return (_field_cntr_pools_init(unit, stage_fc)); 20288 } 20289 20290 /* Allocate counters for each of the tcam slices. */ 20291 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 20292 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 20293 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 20294 if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) { 20295 fs->counters_count = 0; 20296 continue; 20297 } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) { 20298 fs->counters_count = soc_mem_index_count(unit, EFP_COUNTER_TABLEm); 20299 20300 if(stage_fc->flags & _FP_STAGE_HALF_SLICE) { 20301 fs->counters_count = fs->counters_count / 2; 20302 } 20303 if (slice_idx) { 20304 cntr_share = TRUE; 20305 } 20306 } else 20307 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 20308 { 20309 if (soc_feature(unit,soc_feature_field_slice_size128)) { 20310 fs->counters_count = fs->entry_count * 2; /*Counters are double the number of TCAM entries*/ 20311 } else { 20312 fs->counters_count = fs->entry_count; 20313 } 20314 } 20315 20316 if (cntr_share) { 20317 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 20318 /* Share counters with slice zero(Global counter pool). */ 20319 retval = _field_slice_counters_share(unit, stage_fc, 20320 0, slice_idx); 20321 if (BCM_FAILURE(retval)) { 20322 _field_counters_deinit(unit, stage_fc); 20323 return (retval); 20324 } 20325 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 20326 } else { 20327 /* Allocate new set of counters for the slice. */ 20328 retval = _field_slice_counters_alloc(unit, fs); 20329 if (BCM_FAILURE(retval)) { 20330 _field_counters_deinit(unit, stage_fc); 20331 return (retval); 20332 } 20333 } 20334 } 20335 return (BCM_E_NONE); 20336 } 20337 20338 /* 20339 * Function: 20340 * _field_entries_init 20341 * Purpose: 20342 * Allocate the memory for entries in all the slices of the stage. 20343 * External TCAM (for Triumph) is taken care of in _bcm_tr_field_init. 20344 * Entries will be de-allocated in bcm_esw_field_detach 20345 * 20346 * Parameters: 20347 * unit - (IN) BCM device number. 20348 * stage_fc - (IN/OUT) Stage field control structure. 20349 * 20350 * Returns: 20351 * BCM_E_XXX 20352 */ 20353 STATIC int 20354 _field_entries_init(int unit, _field_stage_t *stage_fc) 20355 { 20356 int slice_idx; /* Slices iterator. */ 20357 int tcam_idx; /* Slice first entry tcam index tracker. */ 20358 int mem_size; /* Allocation size. */ 20359 int entry_ratio; /* Invalid entries ratio. */ 20360 int entry_ratio_per_slice; /* Invalid entries ratio for each 20361 slice. */ 20362 _field_slice_t *fs; /* Slice config structure. */ 20363 20364 /* Input parameters check. */ 20365 if (NULL == stage_fc) { 20366 return (BCM_E_PARAM); 20367 } 20368 20369 /* Triumph external slice handled in _bcm_tr_field_init. */ 20370 if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 20371 return (BCM_E_NONE); 20372 } 20373 20374 /* Make sure slices array is initialized. */ 20375 if (NULL == stage_fc->slices[_FP_DEF_INST]) { 20376 return (BCM_E_INTERNAL); 20377 } 20378 20379 entry_ratio = (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) ? 4: 20380 ((stage_fc->flags & _FP_STAGE_HALF_SLICE) ? 2 : 1); 20381 20382 /* Iterate over all stage slices and allocated entries for each slice. */ 20383 for (slice_idx = 0, tcam_idx = 0; 20384 slice_idx < stage_fc->tcam_slices; slice_idx++) { 20385 20386 /* Default entry ratio per each slice equals to global entry ratio */ 20387 entry_ratio_per_slice = entry_ratio; 20388 20389 /* Get slice control structure pointer. */ 20390 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 20391 20392 /* Get number of entries in the slice. */ 20393 #if defined(BCM_SCORPION_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 20394 if ((soc_feature(unit, soc_feature_field_ingress_two_slice_types)) && 20395 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 20396 if (SOC_IS_TD2_TT2(unit)){ 20397 if (slice_idx < _BCM_FIELD_TD2_INGRESS_DOUBLE_WIDE_SLICE0) { 20398 fs->entry_count = 20399 _BCM_FIELD_TD2_INGRESS_LARGE_SLICE_SZ; 20400 if (soc_feature(unit, 20401 soc_feature_field_stage_ingress_512_half_slice)) { 20402 entry_ratio_per_slice = 2; 20403 fs->entry_count /= entry_ratio_per_slice; 20404 } 20405 } else { 20406 fs->entry_count = 20407 _BCM_FIELD_TD2_INGRESS_SMALL_SLICE_SZ; 20408 } 20409 20410 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 20411 /* In Trident2 Plus number of entries in each slice is 4 20412 * times entries in Trident2. For OTP variants of Td2Plus 20413 * entry ratio will be used to reduce the entry count 20414 */ 20415 if (SOC_IS_TD2P_TT2P(unit)) { 20416 fs->entry_count = ((fs->entry_count * 4) / entry_ratio); 20417 } 20418 #endif 20419 #if defined(BCM_APACHE_SUPPORT) 20420 /* In Apache number of entries in each slice is 2 20421 * times entries in Trident2. 20422 */ 20423 if(SOC_IS_APACHE(unit)) { 20424 fs->entry_count = (fs->entry_count * 2) / entry_ratio; 20425 } 20426 #endif 20427 } else if (SOC_IS_TD_TT(unit)){ 20428 if (slice_idx < _BCM_FIELD_TD_INGRESS_DOUBLE_WIDE_SLICE0) { 20429 fs->entry_count = 20430 _BCM_FIELD_TD_INGRESS_SINGLE_WIDE_SLICE_SZ; 20431 } else { 20432 fs->entry_count = 20433 _BCM_FIELD_TD_INGRESS_DOUBLE_WIDE_SLICE_SZ; 20434 } 20435 } else { 20436 if (slice_idx < _BCM_FIELD_SC_INGRESS_DOUBLE_WIDE_SLICE0) { 20437 fs->entry_count = 20438 _BCM_FIELD_SC_INGRESS_SINGLE_WIDE_SLICE_SZ; 20439 } else { 20440 fs->entry_count = 20441 _BCM_FIELD_SC_INGRESS_DOUBLE_WIDE_SLICE_SZ; 20442 } 20443 } 20444 } else 20445 #endif /* BCM_SCORPION_SUPPORT || BCM_TRIDENT_SUPPORT */ 20446 { 20447 fs->entry_count = stage_fc->tcam_sz / \ 20448 (entry_ratio_per_slice * stage_fc->tcam_slices); 20449 } 20450 20451 /* Allocate slice entries pointers array. */ 20452 mem_size = fs->entry_count * sizeof (void *); 20453 _FP_XGS3_ALLOC(fs->entries, mem_size, "array of entry pointers"); 20454 if (fs->entries == NULL) { 20455 /* Allocation failed free all previously allocated entries. */ 20456 _bcm_field_stage_entries_free(unit, stage_fc); 20457 return (BCM_E_MEMORY); 20458 } 20459 fs->start_tcam_idx = tcam_idx; 20460 tcam_idx += fs->entry_count * entry_ratio_per_slice; 20461 fs->free_count = fs->entry_count; 20462 } 20463 return (BCM_E_NONE); 20464 } 20465 20466 /* 20467 * Function: 20468 * _field_slices_init 20469 * Purpose: 20470 * Allocate the memory for slices. 20471 * Initialize slice specific flags, parameters. 20472 * 20473 * Parameters: 20474 * unit - (IN) BCM device number. 20475 * stage_fc - (IN/OUT) Stage field control structure. 20476 * fc - (IN/OUT) Field control structure. 20477 * 20478 * Returns: 20479 * BCM_E_XXX 20480 */ 20481 STATIC int 20482 _field_slices_init(int unit, _field_stage_t *stage_fc, _field_control_t *fc) 20483 { 20484 struct _field_slice_s *fs; /* Slice info. */ 20485 int slice_idx; /* Slice iteration index. */ 20486 int mem_size; /* Memory allocation buffer size. */ 20487 20488 /* Input parameters check. */ 20489 if (NULL == stage_fc) { 20490 return (BCM_E_PARAM); 20491 } 20492 20493 /* Allocate slices info. */ 20494 mem_size = stage_fc->tcam_slices * sizeof(struct _field_slice_s); 20495 fs = sal_alloc(mem_size, "stage slices info"); 20496 if (NULL == fs) { 20497 return (BCM_E_MEMORY); 20498 } 20499 20500 sal_memset(fs, 0, mem_size); 20501 stage_fc->slices[_FP_DEF_INST] = fs; 20502 20503 /* Initialize stage slices info. */ 20504 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 20505 fs[slice_idx].slice_number = slice_idx; 20506 fs[slice_idx].stage_id = stage_fc->stage_id; 20507 fs[slice_idx].next = NULL; 20508 fs[slice_idx].prev = NULL; 20509 fs[slice_idx].doublewide_key_select = _FP_SELCODE_DONT_CARE; 20510 fs[slice_idx].src_class_sel = _FP_SELCODE_DONT_CARE; 20511 fs[slice_idx].dst_class_sel = _FP_SELCODE_DONT_CARE; 20512 fs[slice_idx].intf_class_sel = _FP_SELCODE_DONT_CARE; 20513 fs[slice_idx].loopback_type_sel = _FP_SELCODE_DONT_CARE; 20514 fs[slice_idx].ingress_entity_sel = _FP_SELCODE_DONT_CARE; 20515 fs[slice_idx].src_entity_sel = _FP_SELCODE_DONT_CARE; 20516 fs[slice_idx].dst_fwd_entity_sel = _FP_SELCODE_DONT_CARE; 20517 fs[slice_idx].fwd_field_sel = _FP_SELCODE_DONT_CARE; 20518 fs[slice_idx].ttl_class_sel = _FP_SELCODE_DONT_CARE; 20519 fs[slice_idx].tcp_class_sel = _FP_SELCODE_DONT_CARE; 20520 fs[slice_idx].tos_class_sel = _FP_SELCODE_DONT_CARE; 20521 20522 /* Set intraslice capable flag if appropriate. */ 20523 #if defined(BCM_HURRICANE_SUPPORT) 20524 if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 20525 SOC_IS_GREYHOUND2(unit)) { 20526 fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_INTRASLICE_CAPABLE; 20527 } 20528 #endif 20529 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 20530 if (soc_feature(unit, soc_feature_field_multi_stage)) { 20531 if ((_BCM_FIELD_STAGE_INGRESS != stage_fc->stage_id) && 20532 (_BCM_FIELD_STAGE_LOOKUP != stage_fc->stage_id)) { 20533 continue; 20534 } 20535 20536 #if defined(BCM_SCORPION_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) 20537 /* Skip single wide slices on 5682x devices. */ 20538 if ((soc_feature(unit, soc_feature_field_ingress_two_slice_types)) && 20539 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 20540 if (SOC_IS_TD2_TT2(unit)) { 20541 if (_BCM_FIELD_TD2_INGRESS_DOUBLE_WIDE_SLICE0 <= slice_idx) { 20542 fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_SIZE_SMALL; 20543 continue; 20544 } 20545 } else if (SOC_IS_TD_TT(unit)) { 20546 if (_BCM_FIELD_TD_INGRESS_DOUBLE_WIDE_SLICE0 > slice_idx) { 20547 fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_SIZE_SMALL; 20548 continue; 20549 } 20550 } else { 20551 if (_BCM_FIELD_SC_INGRESS_DOUBLE_WIDE_SLICE0 > slice_idx) { 20552 fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_SIZE_SMALL; 20553 continue; 20554 } 20555 } 20556 fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_SIZE_LARGE; 20557 20558 /* TD2: Intra Slice mode not available from IFP stage */ 20559 if (SOC_IS_TD_TT(unit)) { 20560 continue; 20561 } 20562 } 20563 #ifdef BCM_MONTEREY_SUPPORT 20564 /* Monterey: Intra Slice mode not available from IFP stage */ 20565 if (SOC_IS_MONTEREY(unit) && 20566 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 20567 continue; 20568 } 20569 #endif 20570 #endif /* BCM_SCORPION_SUPPORT || BCM_TRIDENT_SUPPORT */ 20571 fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_INTRASLICE_CAPABLE; 20572 } 20573 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 20574 } 20575 20576 return (BCM_E_NONE); 20577 } 20578 20579 /* 20580 * Function: 20581 * _field_stage_add 20582 * 20583 * Purpose: 20584 * Add stage to field processor pipeline. 20585 * 20586 * Parameters: 20587 * unit - (IN) BCM device number. 20588 * fc - (IN/OUT)Field control info for device. 20589 * 20590 * Returns: 20591 * BCM_E_NONE - Success 20592 * BCM_E_MEMORY - Allocation failure 20593 */ 20594 STATIC int 20595 _field_stage_add(int unit, _field_control_t *fc, _field_stage_id_t stage_id) 20596 { 20597 _field_stage_t *stage_fc; /* Stage info. */ 20598 int ret_val; /* Operation return value. */ 20599 int idx; 20600 int map_id; 20601 #if defined(BCM_TRIDENT2_SUPPORT) 20602 soc_mem_t mem; 20603 int entry_words; 20604 #endif /* BCM_TRX_SUPPORT */ 20605 #if defined(BCM_TRIUMPH_SUPPORT) 20606 uint16 dev_id; 20607 uint8 rev_id; 20608 #endif /* BCM_TRIUMPH_SUPPORT */ 20609 int inst; /* Pipe Instance. */ 20610 20611 /* Input parameters check. */ 20612 if (NULL == fc) { 20613 return (BCM_E_PARAM); 20614 } 20615 20616 /* Allocate stage structure. */ 20617 stage_fc = sal_alloc(sizeof(_field_stage_t), "FP stage info"); 20618 if (NULL == stage_fc) { 20619 LOG_ERROR(BSL_LS_BCM_FP, 20620 (BSL_META_U(unit, 20621 "FP(unit %d) Error: Allocation failure for stage info\n"), 20622 unit)); 20623 return (BCM_E_MEMORY); 20624 } 20625 /* Reset allocated buffer. */ 20626 sal_memset(stage_fc, 0, sizeof(_field_stage_t)); 20627 20628 20629 /* Set stage id. */ 20630 stage_fc->stage_id = stage_id; 20631 /* Set default num instances to 1 */ 20632 stage_fc->num_instances = 1; 20633 20634 #ifdef BCM_TRIDENT2_SUPPORT 20635 if (SOC_IS_TD2_TT2(unit)) { 20636 ret_val = _bcm_field_td2_stage_init(unit, stage_fc); 20637 if (BCM_FAILURE(ret_val)) { 20638 sal_free(stage_fc); 20639 return (ret_val); 20640 } 20641 } else 20642 #endif 20643 #ifdef BCM_HELIX4_SUPPORT 20644 if (SOC_IS_HELIX4(unit)) { 20645 ret_val = _bcm_field_helix4_stage_init(unit, stage_fc); 20646 if (BCM_FAILURE(ret_val)) { 20647 sal_free(stage_fc); 20648 return (ret_val); 20649 } 20650 } else 20651 #endif 20652 #ifdef BCM_TRIUMPH3_SUPPORT 20653 if (SOC_IS_TRIUMPH3(unit)) { 20654 ret_val = _bcm_field_tr3_stage_init(unit, stage_fc); 20655 if (BCM_FAILURE(ret_val)) { 20656 sal_free(stage_fc); 20657 return (ret_val); 20658 } 20659 } else 20660 #endif 20661 { 20662 /* Set the stage features */ 20663 if ((soc_feature(unit, soc_feature_field_ingress_global_meter_pools)) && 20664 (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 20665 stage_fc->flags |= _FP_STAGE_GLOBAL_METER_POOLS; 20666 } 20667 20668 #if defined(BCM_TRIUMPH_SUPPORT) 20669 if (SOC_IS_VALKYRIE(unit) || SOC_IS_VALKYRIE2(unit)) { 20670 stage_fc->flags |= _FP_STAGE_HALF_SLICE; 20671 } else if (SOC_IS_APOLLO(unit) 20672 && (_BCM_FIELD_STAGE_LOOKUP != stage_id)) { 20673 stage_fc->flags |= _FP_STAGE_HALF_SLICE; 20674 } 20675 20676 /* 56620/56630 devices have full slices on all stages. */ 20677 /* 56538/56534 devices have half slices on ingress and egress */ 20678 soc_cm_get_id(unit, &dev_id, &rev_id); 20679 if (((BCM56538_DEVICE_ID == dev_id) || (BCM56534_DEVICE_ID == dev_id)) 20680 && (_BCM_FIELD_STAGE_LOOKUP != stage_id)) { 20681 stage_fc->flags |= _FP_STAGE_HALF_SLICE; 20682 } 20683 20684 if ((BCM56630_DEVICE_ID == dev_id) || (BCM56620_DEVICE_ID == dev_id)) { 20685 stage_fc->flags &= ~_FP_STAGE_HALF_SLICE; 20686 } 20687 20688 #ifdef BCM_HURRICANE2_SUPPORT 20689 if (soc_feature(unit, soc_feature_field_slice_size128)) { 20690 stage_fc->flags |= _FP_STAGE_HALF_SLICE; 20691 } 20692 #endif 20693 #endif /* BCM_TRIUMPH_SUPPORT */ 20694 20695 #if defined(BCM_TRX_SUPPORT) 20696 if ((soc_feature(unit, 20697 soc_feature_field_ing_egr_separate_packet_byte_counters)) 20698 && ((stage_id == _BCM_FIELD_STAGE_INGRESS) 20699 || (stage_id == _BCM_FIELD_STAGE_EXTERNAL) 20700 || (stage_id == _BCM_FIELD_STAGE_EGRESS))) { 20701 stage_fc->flags |= _FP_STAGE_SEPARATE_PACKET_BYTE_COUNTERS; 20702 } 20703 #endif /* BCM_TRX_SUPPORT */ 20704 20705 20706 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 20707 if ((soc_feature(unit, soc_feature_field_egress_global_counters)) 20708 && (stage_id == _BCM_FIELD_STAGE_EGRESS)) { 20709 stage_fc->flags |= _FP_STAGE_GLOBAL_COUNTERS; 20710 } 20711 20712 if ((soc_feature(unit, soc_feature_field_vfp_flex_counter)) 20713 && (stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 20714 stage_fc->flags |= _FP_STAGE_GLOBAL_COUNTERS; 20715 } 20716 20717 if (SOC_IS_KATANAX(unit)) { 20718 if ((soc_feature(unit, soc_feature_advanced_flex_counter)) 20719 && (stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 20720 stage_fc->flags |= _FP_STAGE_GLOBAL_COUNTERS; 20721 } 20722 } 20723 if ((soc_feature(unit, soc_feature_flowcnt)) 20724 && (stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 20725 stage_fc->flags |= _FP_STAGE_GLOBAL_COUNTERS; 20726 } 20727 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 20728 20729 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \ 20730 defined(BCM_RAPTOR_SUPPORT) 20731 if ((soc_feature(unit, soc_feature_field_virtual_slice_group) 20732 && (_BCM_FIELD_STAGE_INGRESS == stage_id)) 20733 || (SOC_IS_TRX(unit) 20734 && (_BCM_FIELD_STAGE_EXTERNAL != stage_id) 20735 && soc_feature(unit, soc_feature_field_virtual_slice_group))) { 20736 stage_fc->flags |= _FP_STAGE_AUTO_EXPANSION; 20737 } 20738 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT || BCM_RAPTOR_SUPPORT */ 20739 20740 if ((soc_feature(unit, soc_feature_field_slice_enable)) 20741 && (_BCM_FIELD_STAGE_EXTERNAL != stage_id)) { 20742 stage_fc->flags |= _FP_STAGE_SLICE_ENABLE; 20743 } 20744 20745 20746 /* Init tcam info for stage. */ 20747 ret_val = _field_tcam_info_init(unit, stage_fc, fc); 20748 if (BCM_FAILURE(ret_val)) { 20749 _field_stage_delete(unit, fc, stage_fc); 20750 return (ret_val); 20751 } 20752 } 20753 20754 /* Initialize slices information. */ 20755 ret_val = _field_slices_init (unit, stage_fc, fc); 20756 if (BCM_FAILURE(ret_val)) { 20757 _field_stage_delete(unit, fc, stage_fc); 20758 return (ret_val); 20759 } 20760 20761 /* 20762 * Allocate the memory for entries in all the slices 20763 * external TCAM (for Triumph) is taken care of in _bcm_tr_field_init. 20764 * This will be de-allocated in bcm_esw_field_detach 20765 */ 20766 if (stage_fc->stage_id != _BCM_FIELD_STAGE_EXTERNAL) { 20767 /* Initialize stage slices . */ 20768 ret_val = _field_entries_init (unit, stage_fc); 20769 if (BCM_FAILURE(ret_val)) { 20770 _field_stage_delete(unit, fc, stage_fc); 20771 return (ret_val); 20772 } 20773 } 20774 20775 /* Initialize meters usage bitmap. */ 20776 ret_val = _field_meters_init (unit, stage_fc); 20777 if (BCM_FAILURE(ret_val)) { 20778 _field_stage_delete(unit, fc, stage_fc); 20779 return (ret_val); 20780 } 20781 20782 /* Initialize counters usage bitmap. */ 20783 ret_val = _field_counters_init(unit, fc, stage_fc); 20784 if (BCM_FAILURE(ret_val)) { 20785 _field_stage_delete(unit, fc, stage_fc); 20786 return (ret_val); 20787 } 20788 20789 /* Action profile; will be setup in chip-specific init */ 20790 soc_profile_mem_t_init(&stage_fc->ext_act_profile); 20791 20792 #if defined(BCM_TRIDENT2_SUPPORT) 20793 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 20794 /* hash select 0 action memory profile initialization. */ 20795 soc_profile_mem_t_init(&stage_fc->hash_select[0]); 20796 20797 /* hash select 1 action memory profile initialization. */ 20798 soc_profile_mem_t_init(&stage_fc->hash_select[1]); 20799 } 20800 #endif /* BCM_TRIDENT2_SUPPORT */ 20801 20802 /* Ingress specific initialization. */ 20803 if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 20804 20805 stage_fc->range_id = 1; 20806 20807 /* Initialize stage select codes table. */ 20808 ret_val = _field_stage_data_ctrl_init(unit, stage_fc); 20809 if (BCM_FAILURE(ret_val)) { 20810 _field_stage_delete(unit, fc, stage_fc); 20811 return (ret_val); 20812 } 20813 } 20814 20815 #if defined(BCM_TRIDENT2_SUPPORT) 20816 /* Lookup stage specific initialization. */ 20817 if (((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) && 20818 (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id)) { 20819 /* hash select action memory profile initialization. */ 20820 soc_profile_mem_t_init(&stage_fc->hash_select[0]); 20821 soc_profile_mem_t_init(&stage_fc->hash_select[1]); 20822 20823 /* Hash select 0 action profile table initialization. */ 20824 if (SOC_MEM_IS_VALID(unit, VFP_HASH_FIELD_BMAP_TABLE_Am)) { 20825 mem = VFP_HASH_FIELD_BMAP_TABLE_Am; 20826 entry_words = sizeof(vfp_hash_field_bmap_table_a_entry_t) / 20827 sizeof(uint32); 20828 ret_val = soc_profile_mem_create(unit, &mem, &entry_words, 1, 20829 &stage_fc->hash_select[0]); 20830 20831 if (BCM_FAILURE(ret_val)) { 20832 _field_stage_delete(unit, fc, stage_fc); 20833 return (ret_val); 20834 } 20835 } 20836 /* Hash select 1 action profile table initialization. */ 20837 if (SOC_MEM_IS_VALID(unit, VFP_HASH_FIELD_BMAP_TABLE_Bm)) { 20838 mem = VFP_HASH_FIELD_BMAP_TABLE_Bm; 20839 entry_words = sizeof(vfp_hash_field_bmap_table_a_entry_t) / 20840 sizeof(uint32); 20841 ret_val = soc_profile_mem_create(unit, &mem, &entry_words, 1, 20842 &stage_fc->hash_select[1]); 20843 20844 if (BCM_FAILURE(ret_val)) { 20845 _field_stage_delete(unit, fc, stage_fc); 20846 return (ret_val); 20847 } 20848 } 20849 /* 20850 * Index 0 of vfp_hash_field_bmap_table_a/b is invalid as the 20851 * hardware will consider hash bitmap selection from VFP only 20852 * if HASH_FIELD_BITMAP_PTR_A and HASH_FIELD_BITMAP_PTR_B are non-zero. 20853 * Making the entry to NULL. 20854 */ 20855 ret_val = _bcm_field_td2_hash_select_profile_alloc_reserve_entry(unit, 20856 stage_fc); 20857 if (BCM_FAILURE(ret_val)) { 20858 _field_stage_delete(unit, fc, stage_fc); 20859 return (ret_val); 20860 } 20861 } 20862 #endif /* BCM_TRIDENT2_SUPPORT */ 20863 /* Initializing supported Qset*/ 20864 sal_memset(&stage_fc->_field_supported_qset, 0, sizeof(bcm_field_qset_t)); 20865 20866 /* 20867 * Initialize the FP_SLICE_MAP 20868 * physical_slice and virtual_group are H/W initial values 20869 * Although initialized for all stages, valid only on Raptor (1 stage) 20870 * , FB-2 Ingress stage, Triumph 20871 */ 20872 for (inst = 0; inst < stage_fc->num_instances; inst++) { 20873 if (!(fc->pipe_map & (1 << inst))) { 20874 continue; 20875 } 20876 for (map_id = 0; map_id < _FP_VMAP_CNT; map_id++) { 20877 for (idx = 0; idx < _FP_VMAP_SIZE; idx++) { 20878 stage_fc->vmap[inst][map_id][idx].valid = FALSE; 20879 stage_fc->vmap[inst][map_id][idx].vmap_key = idx; 20880 stage_fc->vmap[inst][map_id][idx].virtual_group = idx; 20881 stage_fc->vmap[inst][map_id][idx].flags = 0; 20882 } 20883 } 20884 } 20885 20886 FP_LOCK(unit); 20887 /* Add stage to field control structure. */ 20888 stage_fc->next = fc->stages; 20889 fc->stages = stage_fc; 20890 FP_UNLOCK(unit); 20891 20892 return (BCM_E_NONE); 20893 } 20894 20895 /* 20896 * Function: 20897 * _field_stages_init 20898 * 20899 * Purpose: 20900 * Initialize field stages array within the field control struct. 20901 * 20902 * Parameters: 20903 * unit - (IN) BCM device number. 20904 * fc - (IN/OUT)Field control info for device. 20905 * 20906 * Returns: 20907 * BCM_E_NONE - Success 20908 * BCM_E_MEMORY - Allocation failure 20909 * 20910 * Notes: 20911 * It is important that _BCM_FIELD_STAGE_INGRESS be inited before 20912 * _BCM_FIELD_STAGE_EXTERNAL 20913 */ 20914 int 20915 _field_stages_init(int unit, _field_control_t *fc) 20916 { 20917 int ret_val; /* Operation return value. */ 20918 20919 20920 /* Input parameters check. */ 20921 if (fc == NULL) { 20922 return (BCM_E_PARAM); 20923 } 20924 20925 #if defined(BCM_TOMAHAWK_SUPPORT) /* BCM_TOMAHAWK_SUPPORT */ 20926 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 20927 /* Initialize stage add and delete functions for tomahawk device. */ 20928 fc->stage_func.fp_stages_add = _bcm_field_th_stages_add; 20929 fc->stage_func.fp_stages_delete = _bcm_field_th_stages_delete; 20930 20931 /* Invoke stage add function. */ 20932 return (fc->stage_func.fp_stages_add(unit, fc)); 20933 } 20934 #endif /* !BCM_TOMAHAWK_SUPPORT*/ 20935 20936 /* Based on unit type add pipeline stages to field control. */ 20937 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 20938 if ((soc_feature(unit, soc_feature_field_multi_stage)) && 20939 (SOC_SWITCH_BYPASS_MODE_L3_ONLY != SOC_SWITCH_BYPASS_MODE(unit))) { 20940 20941 ret_val = _field_stage_add(unit, fc, _BCM_FIELD_STAGE_LOOKUP); 20942 if (BCM_FAILURE(ret_val)) { 20943 _field_stages_destroy(unit, fc); 20944 return (ret_val); 20945 } 20946 20947 ret_val = _field_stage_add(unit, fc, _BCM_FIELD_STAGE_EGRESS); 20948 if (BCM_FAILURE(ret_val)) { 20949 _field_stages_destroy(unit, fc); 20950 return (ret_val); 20951 } 20952 } 20953 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 20954 20955 ret_val = _field_stage_add(unit, fc, _BCM_FIELD_STAGE_INGRESS); 20956 if (BCM_FAILURE(ret_val)) { 20957 _field_stages_destroy(unit, fc); 20958 return (ret_val); 20959 } 20960 20961 /* Add the External TCAM (stage) */ 20962 if ((soc_feature(unit, soc_feature_esm_support)) && 20963 (fc->flags & _FP_EXTERNAL_PRESENT)) { 20964 ret_val = _field_stage_add(unit, fc, _BCM_FIELD_STAGE_EXTERNAL); 20965 if (BCM_FAILURE(ret_val)) { 20966 _field_stages_destroy(unit, fc); 20967 return (ret_val); 20968 } 20969 20970 ret_val = _field_external_meters_init(unit, fc); 20971 if (BCM_FAILURE(ret_val)) { 20972 _field_stages_destroy(unit, fc); 20973 return (ret_val); 20974 } 20975 20976 ret_val = _field_stage_external_data_ctrl_init(unit, fc); 20977 if (BCM_FAILURE(ret_val)) { 20978 _field_stages_destroy(unit, fc); 20979 return (ret_val); 20980 } 20981 } 20982 return (ret_val); 20983 20984 } 20985 /* 20986 * Function: _field_min_virtual_priorty_group_get 20987 * 20988 * Purpose: 20989 * Service routine used to update virtual priority map. 20990 * Function returns a minimum priority group, which 20991 * might be assigned a virtual priority passed to the function. 20992 * Parameters: 20993 * unit - (IN) BCM device number. 20994 * vmap - (IN) Virutal map array. 20995 * vmap_size - (IN) Map size. 20996 * unused_groups - (OUT) Unused virtual groups. 20997 * unused_slices - (OUT) Unused physical slices. 20998 * Returns: 20999 * BCM_E_XXX 21000 */ 21001 STATIC int 21002 _field_min_virtual_priorty_group_get(int unit, _field_virtual_map_t *vmap, 21003 int vmap_size, int *virtual_priority, 21004 int *candidate) 21005 { 21006 int idx; /* Virtual map iteration index. */ 21007 int prio_max; /* Max limit on group priority. */ 21008 int min_group; /* Minimum priority group index. */ 21009 int even_boundary_constraint;/* even boundary constraint */ 21010 int incr_priority = FALSE; /* Increment priority to meet */ 21011 21012 /* Input parameters check. */ 21013 if ((NULL == vmap) || (NULL == candidate) || (NULL == virtual_priority)) { 21014 return (BCM_E_PARAM); 21015 } 21016 21017 /* Initialize max limit for group priority to ANY (unlimited). */ 21018 prio_max = 0x7fffffff; /* Unlimited priority.*/ 21019 min_group = -1; /* No candidates. */ 21020 21021 /* FB2 double wide group must reside in even virtual priority. */ 21022 even_boundary_constraint = (SOC_IS_FIREBOLT2(unit)) ? TRUE : FALSE; 21023 21024 /* Fill new virtual map. */ 21025 for (idx = 0; idx < vmap_size; idx++) { 21026 21027 /* Skip unused virtual priorities. */ 21028 if (vmap[idx].valid == FALSE) { 21029 continue; 21030 } 21031 21032 /* Skip groups not meeting even_boundary_constraint */ 21033 if ((even_boundary_constraint) && 21034 (vmap[idx].flags & _FP_GROUP_SPAN_DOUBLE_SLICE) && 21035 (0 != ((*virtual_priority) % 2))) { 21036 if (prio_max > vmap[idx].priority) { 21037 prio_max = vmap[idx].priority; 21038 } 21039 if (-1 == min_group) { 21040 min_group = idx; 21041 /* Priority increment is required.*/ 21042 incr_priority = TRUE; 21043 } 21044 /* Double wide group -> no point to check next map. */ 21045 idx ++; 21046 continue; 21047 } 21048 21049 /* 21050 * Make sure double wide group with 21051 * lower priority was not skipped because of even_boundary_constraint. 21052 */ 21053 if (prio_max >= vmap[idx].priority) { 21054 min_group = idx; 21055 incr_priority = FALSE; 21056 } 21057 break; 21058 } 21059 21060 if (incr_priority) { 21061 /* 21062 * Originally, a candidate was skipped because of 21063 * even boundary constraint violation (virtual_priority is odd). 21064 * lets use next priority. 21065 */ 21066 (*virtual_priority)++; 21067 } 21068 21069 *candidate = min_group; 21070 21071 return (BCM_E_NONE); 21072 } 21073 21074 /* 21075 * Function: 21076 * _field_slice_clear 21077 * 21078 * Purpose: 21079 * Reset the fields in a slice. Note that the entries list must be 21080 * empty before calling this. Also, this does NOT deallocate the memory for 21081 * the slice itself. Normally, this is used when a group no longer needs 21082 * ownership of a slice so the slice gets returned to the pool of available 21083 * slices. 21084 * 21085 * Paramters: 21086 * unit - BCM device number 21087 * fg - Field group structure. 21088 * fs - Link to physical slice structure to be cleared 21089 * pbmp - Port bitmap to remove from slice 21090 * 21091 * Returns: 21092 * BCM_E_NONE - Success 21093 * BCM_E_BUSY - Entries still in slice, can't clear slice 21094 */ 21095 STATIC int 21096 _field_slice_clear(int unit, _field_group_t *fg, 21097 _field_slice_t *fs, bcm_pbmp_t pbmp) 21098 { 21099 _field_stage_t *stage_fc; /* Stage field control structure. */ 21100 _field_control_t *fc; /* Field control structure. */ 21101 uint32 entry_idx; /* Slice entries iterator. */ 21102 21103 /* Input parameters check. */ 21104 if ((NULL == fs) || (NULL == fg)){ 21105 return (BCM_E_PARAM); 21106 } 21107 /* Get field control structure. */ 21108 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 21109 21110 /* Get stage field control structure. */ 21111 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fs->stage_id, &stage_fc)); 21112 21113 21114 for (entry_idx = 0; entry_idx < fs->entry_count; entry_idx++) { 21115 if (fs->entries[entry_idx] != NULL && 21116 fs->entries[entry_idx]->group->gid == fg->gid) { 21117 LOG_ERROR(BSL_LS_BCM_FP, 21118 (BSL_META_U(unit, 21119 "FP(unit %d) Error: Entries still in slice=%d.\n"), 21120 unit, fs->slice_number)); 21121 return (BCM_E_BUSY); 21122 } 21123 } 21124 21125 if (fg->stage_id != _BCM_FIELD_STAGE_INGRESS) { 21126 BCM_PBMP_CLEAR(fs->pbmp); 21127 } else { 21128 /* Remove ports from slice's port bit map. */ 21129 BCM_PBMP_REMOVE(fs->pbmp, pbmp); 21130 } 21131 21132 /* Clean up group configuration if last group was removed from the slice. */ 21133 if(BCM_PBMP_IS_NULL(fs->pbmp)) { 21134 /* Clear slice configuration in hw. */ 21135 if (NULL != fc->functions.fp_slice_clear) { 21136 BCM_IF_ERROR_RETURN(fc->functions.fp_slice_clear(unit, fg, fs)); 21137 } 21138 21139 fs->group_flags = 0; 21140 fs->doublewide_key_select = _FP_SELCODE_DONT_CARE; 21141 fs->src_class_sel = _FP_SELCODE_DONT_CARE; 21142 fs->dst_class_sel = _FP_SELCODE_DONT_CARE; 21143 fs->intf_class_sel = _FP_SELCODE_DONT_CARE; 21144 fs->loopback_type_sel = _FP_SELCODE_DONT_CARE; 21145 fs->ingress_entity_sel = _FP_SELCODE_DONT_CARE; 21146 fs->src_entity_sel = _FP_SELCODE_DONT_CARE; 21147 fs->dst_fwd_entity_sel = _FP_SELCODE_DONT_CARE; 21148 fs->fwd_field_sel = _FP_SELCODE_DONT_CARE; 21149 fs->ttl_class_sel 21150 = fs->tcp_class_sel 21151 = fs->tos_class_sel 21152 =_FP_SELCODE_DONT_CARE; 21153 fs->aux_tag_1_sel 21154 = fs->aux_tag_2_sel 21155 = fs->oam_overlay_sel 21156 = fs->egr_class_f1_sel 21157 = fs->egr_class_f2_sel 21158 = fs->egr_class_f3_sel 21159 = fs->egr_class_f4_sel 21160 = fs->src_dest_class_f1_sel 21161 = fs->src_dest_class_f3_sel 21162 = fs->egr_key4_dvp_sel 21163 = fs->egr_key4_mdl_sel 21164 = fs->egr_oam_overlay_sel 21165 = fs->oam_intf_class_sel 21166 = fs->egr_dest_port_f1_sel 21167 = fs->egr_dest_port_f5_sel 21168 = _FP_SELCODE_DONT_CARE; 21169 } 21170 21171 return (BCM_E_NONE); 21172 } 21173 21174 /* 21175 * Function: _field_vmap_unused_resources_get 21176 * 21177 * Purpose: 21178 * Service routine used to retrieve unused virtual groups 21179 * and physical slices 21180 * Parameter 21181 * unit - (IN) BCM device number. 21182 * vmap - (IN) Virutal map array. 21183 * vmap_size - (IN) Virtual map size. 21184 * unused_groups - (OUT) Unused virtual groups. 21185 * unused_slices - (OUT) Unused physical slices. 21186 * Returns: 21187 * BCM_E_XXX 21188 */ 21189 STATIC int 21190 _field_vmap_unused_resources_get(int unit, _field_virtual_map_t *vmap, 21191 int vmap_size, uint32 *unused_groups, 21192 uint32 *unused_slices) 21193 { 21194 int idx; /* Virtual map iteration index. */ 21195 uint32 used_groups = 0; /* Used virtual groups. */ 21196 uint32 used_slices = 0; /* Used physical slices. */ 21197 21198 /* Input parameters check. */ 21199 if ((NULL == vmap) || (NULL == unused_groups) || (NULL == unused_slices)) { 21200 return (BCM_E_PARAM); 21201 } 21202 21203 21204 /* Iterate over all currently used groups & update bitmap. */ 21205 for (idx = 0; idx < vmap_size; idx++) { 21206 /* Skip unused virtual priorities. */ 21207 if (vmap[idx].valid == FALSE) { 21208 continue; 21209 } 21210 21211 used_groups |= (1 << vmap[idx].virtual_group); 21212 used_slices |= (1 << vmap[idx].vmap_key); 21213 } 21214 21215 /* Update caller information. */ 21216 *unused_groups = ~used_groups; 21217 *unused_slices = ~used_slices; 21218 21219 return (BCM_E_NONE); 21220 } 21221 21222 /* 21223 * Function: _field_vmap_resource_alloc 21224 * 21225 * Purpose: 21226 * Service routine used to allocate virutal group/physical 21227 * slice from unused resources map. 21228 * Parameter 21229 * unit - (IN) BCM device number. 21230 * vmap - (IN) Virutal map array. 21231 * vmap_size - (IN) Virtual map size. 21232 * resource - (IN) Available resources bitmap. 21233 * allocated_idx - (OUT) Allocated index. 21234 * Returns: 21235 * BCM_E_XXX 21236 */ 21237 STATIC int 21238 _field_vmap_resource_alloc(int unit, _field_virtual_map_t *vmap, 21239 int vmap_size, uint32 *resource, 21240 int *allocated_idx) 21241 { 21242 int idx; /* Tcam slices iteration index. */ 21243 21244 /* Input parameters check. */ 21245 if ((NULL == vmap) || (NULL == resource) || (NULL == allocated_idx)) { 21246 return (BCM_E_PARAM); 21247 } 21248 21249 /* Iterate over all currently used groups & update bitmap. */ 21250 for (idx = 0; idx < vmap_size; idx++) { 21251 if ((*resource) & (1 << idx)) { 21252 break; 21253 } 21254 } 21255 21256 /* Check if any resources are available. */ 21257 if (idx == vmap_size) { 21258 return (BCM_E_RESOURCE); 21259 } 21260 21261 *resource &= ~(1 << idx); 21262 *allocated_idx = idx; 21263 return (BCM_E_NONE); 21264 } 21265 21266 /* 21267 * Function: _bcm_field_group_virtual_map_update 21268 * 21269 * Purpose: 21270 * Find the map between virtual group and vmap group id 21271 * Parameters: 21272 * unit - (IN) BCM device number. 21273 * fg - (INOUT) Field Group Structure. 21274 * Returns: 21275 * BCM_E_XXX 21276 */ 21277 int 21278 _bcm_field_group_virtual_map_update(int unit, _field_group_t *fg) 21279 { 21280 _field_control_t *fc; /* Field control structure. */ 21281 _field_group_t *temp_fg = NULL; 21282 int idx = 0; 21283 21284 /* Input parameters check. */ 21285 if (NULL == fg) { 21286 return (BCM_E_PARAM); 21287 } 21288 21289 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 21290 fg->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 21291 } 21292 /* Find and validate field control. */ 21293 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 21294 21295 for (temp_fg = fc->groups; temp_fg != NULL ; temp_fg = temp_fg->next) { 21296 /* Skip other stages. */ 21297 if (temp_fg->stage_id != fg->stage_id) { 21298 continue; 21299 } 21300 21301 if (temp_fg->action_res_id == BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT) { 21302 continue; 21303 } 21304 21305 if(temp_fg->action_res_id == fg->action_res_id) { 21306 /* ALL VALID action Resoultion Id will have same virtual group */ 21307 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 21308 fg->vmap_group[idx] = temp_fg->vmap_group[0]; 21309 } 21310 break; 21311 } 21312 } 21313 21314 return (BCM_E_NONE); 21315 } 21316 21317 /* 21318 * Function: _field_group_slice_sharing_virtual_map_group 21319 * 21320 * Purpose: 21321 * Find the map between physical slice and vmap group id 21322 * for slice sharing case 21323 * Parameters: 21324 * unit - (IN) BCM device number. 21325 * stage_fc - (IN) Stage field control structure. 21326 * fg - (INOUT) Field Group Structure. 21327 * Returns: 21328 * BCM_E_XXX 21329 */ 21330 int 21331 _field_group_slice_sharing_virtual_map_group(int unit, _field_stage_t *stage_fc, _field_group_t *fg) 21332 { 21333 _field_virtual_map_t *vmap = NULL; 21334 int idx; 21335 int idx1; 21336 int vmap_key; 21337 int vmap_size; 21338 uint8 map_id = _FP_VMAP_DEFAULT; 21339 int rv; 21340 int slice_count = 0; 21341 21342 /* Input parameters check. */ 21343 if ((stage_fc == NULL) || (NULL == fg)) { 21344 return (BCM_E_PARAM); 21345 } 21346 21347 vmap_key = (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) ? \ 21348 (_FP_VMAP_SIZE - 1) : fg->slices->slice_number; 21349 21350 21351 if (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) { 21352 /* Slice sharing is not supported by EXTERNAL stage 21353 * This check should be never hit 21354 * External slices controlled by stage ingress map. */ 21355 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, 21356 &stage_fc); 21357 BCM_IF_ERROR_RETURN(rv); 21358 if((fg->slices)->pkt_type[_FP_EXT_L2]) { 21359 map_id = _FP_EXT_L2; 21360 } else if ((fg->slices)->pkt_type[_FP_EXT_IP4]) { 21361 map_id = _FP_EXT_IP4; 21362 } else if ((fg->slices)->pkt_type[_FP_EXT_IP6]) { 21363 map_id = _FP_EXT_IP6; 21364 } else { 21365 return (BCM_E_INTERNAL); 21366 } 21367 return (BCM_E_UNAVAIL); 21368 } 21369 21370 /* Calculate virtual map size. */ 21371 rv = _bcm_field_virtual_map_size_get(unit, stage_fc, &vmap_size); 21372 BCM_IF_ERROR_RETURN(rv); 21373 21374 rv = _bcm_field_group_slice_count_get(fg->flags, &slice_count); 21375 BCM_IF_ERROR_RETURN(rv); 21376 21377 /* check only in default map */ 21378 for (idx = 0; idx < vmap_size; idx++) { 21379 vmap = (stage_fc->vmap[fg->instance][map_id]) + idx; 21380 if (TRUE != vmap->valid) { 21381 continue; 21382 } 21383 /* Slice sharing is possible only for groups of same mode */ 21384 if ((vmap->vmap_key == vmap_key) 21385 && ((idx + slice_count -1) < vmap_size)){ 21386 for (idx1 = 0; idx1 < slice_count; idx1++) { 21387 fg->vmap_group[idx1] = (vmap + idx1)->virtual_group; 21388 } 21389 if (fg->action_res_id != BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT) 21390 { 21391 for (idx1 = slice_count; idx1 < _FP_PAIR_MAX; idx1++) { 21392 fg->vmap_group[idx1] = fg->vmap_group[0]; 21393 } 21394 } 21395 break; 21396 } 21397 } 21398 21399 if(idx == vmap_size) 21400 { 21401 return (BCM_E_CONFIG); 21402 } 21403 21404 return (BCM_E_NONE); 21405 } 21406 21407 /* 21408 * Function: _bcm_field_virtual_map_size_get 21409 * 21410 * Purpose: 21411 * Calculate virtual map size. 21412 * Parameters: 21413 * unit - (IN) BCM device number. 21414 * stage_fc - (IN) Stage field control structure. 21415 * vmap_size - (OUT) Virtual map size. 21416 * Returns: 21417 * BCM_E_XXX 21418 */ 21419 int 21420 _bcm_field_virtual_map_size_get(int unit, _field_stage_t *stage_fc, int *vmap_size) 21421 { 21422 _field_control_t *fc; /* Field control structure. */ 21423 uint16 dev_id; 21424 uint8 rev_id; 21425 soc_cm_get_id(unit, &dev_id, &rev_id); 21426 21427 /* Input parameters check. */ 21428 if ((NULL == stage_fc) || (NULL == vmap_size)) { 21429 return (BCM_E_PARAM); 21430 } 21431 21432 /* Find and validate field control. */ 21433 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 21434 21435 21436 /* Virtual map on stage ingress contains includes priority 21437 for external slice. 21438 */ 21439 if ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) && \ 21440 (fc->flags & _FP_EXTERNAL_PRESENT)) { 21441 *vmap_size = stage_fc->tcam_slices + 1; 21442 } else { 21443 *vmap_size = stage_fc->tcam_slices; 21444 if ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) && 21445 ((dev_id == BCM55441_DEVICE_ID) || 21446 (dev_id == BCM56240_DEVICE_ID) || 21447 (dev_id == BCM56241_DEVICE_ID) || 21448 (dev_id == BCM56242_DEVICE_ID) || 21449 (dev_id == BCM56243_DEVICE_ID) || 21450 (dev_id == BCM56245_DEVICE_ID) || 21451 (dev_id == BCM56246_DEVICE_ID))) { 21452 *vmap_size = 12; 21453 } 21454 } 21455 return (BCM_E_NONE); 21456 } 21457 21458 /* 21459 * Function: _field_virtual_map_insert2 21460 * 21461 * Purpose: 21462 * For chips which support the virtual slice/group feature, 21463 * 1) Sort groups by priority. 21464 * 2) Aggregate expanded slices into virtual group priority. 21465 * Parameters: 21466 * unit - (IN) BCM device number. 21467 * stage_fc - (IN) Stage field control structure. 21468 * fg - (IN) Field group structure. 21469 * map_id - (IN) Virtual map id. 21470 * vmap_key - (IN) Virtual map key. 21471 * virtual_group - (IN/OUT) Array of up to _FP_PAIR_MAX virtual group ids 21472 * or -1 if Virtual group id needs to be assigned. 21473 * install - (IN) Perform installation in HW flag. 21474 * Returns: 21475 * BCM_E_XXX 21476 */ 21477 STATIC int 21478 _field_virtual_map_insert2(int unit, _field_stage_t *stage_fc, 21479 _field_group_t *fg, uint8 map_id, 21480 int vmap_key, int *virtual_group, 21481 int install) 21482 { 21483 int idx; /* Virtual map iteration index. */ 21484 int idx_tmp; /* Temp iteration index. */ 21485 int sizeof_vmap; /* Virtual map byte size. */ 21486 int candidate; /* Virtual priority candidate group. */ 21487 int slice_count; /* Number of slices for each map entry.*/ 21488 int group_installed; /* Group installation is complete. */ 21489 _field_control_t *fc; /* Field control structure. */ 21490 uint32 unused_groups; /* Unused virtual groups bitmap. */ 21491 uint32 unused_slices; /* Unused physical slices bitmap */ 21492 /* Updated virtual map. */ 21493 _field_virtual_map_t vmap_new[_FP_VMAP_SIZE]; 21494 /* Original virtual map. */ 21495 _field_virtual_map_t vmap_orig[_FP_VMAP_SIZE]; 21496 _field_virtual_map_t *vmap; /* Currently used virtual map. */ 21497 int even_boundary_constraint = FALSE; /* Flag for double wide slices.*/ 21498 int vmap_size; /* Virtual map index count. */ 21499 int rv; /* Operation return status. */ 21500 int idx_pair; /* Virtual map iteration index. */ 21501 int inst; /* Pipe Instance. */ 21502 21503 /* Input parameters check */ 21504 if ((NULL == fg) || (NULL == stage_fc) || (NULL == virtual_group)) { 21505 return (BCM_E_PARAM); 21506 } 21507 21508 /* Find and validate field control. */ 21509 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 21510 21511 inst = fg->instance; 21512 21513 #if defined(BCM_FIREBOLT2_SUPPORT) 21514 if (SOC_IS_FIREBOLT2(unit)) { 21515 /* FB2 supports virtual priority in stage ingress only. */ 21516 if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) { 21517 return (BCM_E_NONE); 21518 } 21519 /* FB2 double wide group must reside in even virtual priority. */ 21520 even_boundary_constraint = TRUE; 21521 } 21522 #endif /* BCM_FIREBOLT2_SUPPORT */ 21523 21524 /* Reset new virtual map. */ 21525 sizeof_vmap = _FP_VMAP_SIZE * sizeof(_field_virtual_map_t); 21526 sal_memset(vmap_new, 0, sizeof_vmap); 21527 21528 /* Calculate virtual map size. */ 21529 rv = _bcm_field_virtual_map_size_get(unit, stage_fc, &vmap_size); 21530 BCM_IF_ERROR_RETURN(rv); 21531 21532 /* Get unused virtual groups & physical slices */ 21533 sal_memcpy(vmap_orig, stage_fc->vmap[inst][map_id], sizeof_vmap); 21534 vmap = vmap_orig; 21535 rv = _field_vmap_unused_resources_get(unit, vmap, vmap_size, 21536 &unused_groups, &unused_slices); 21537 BCM_IF_ERROR_RETURN(rv); 21538 21539 group_installed = FALSE; 21540 /* Fill new virtual map. */ 21541 for (idx = 0; idx < vmap_size;) { 21542 idx_tmp = idx; 21543 vmap = vmap_orig; 21544 rv = _field_min_virtual_priorty_group_get(unit, vmap, vmap_size, 21545 &idx_tmp, &candidate); 21546 BCM_IF_ERROR_RETURN(rv); 21547 21548 if (_FP_INVALID_INDEX != candidate) { 21549 vmap = vmap_orig + candidate; 21550 if ((group_installed) || (vmap->priority <= fg->priority)) { 21551 idx = idx_tmp; 21552 /* Get number of slices required for this map. */ 21553 rv = _bcm_field_group_slice_count_get(vmap->flags, &slice_count); 21554 BCM_IF_ERROR_RETURN(rv); 21555 /* Copy map info for each of the slices. */ 21556 for (idx_tmp = 0; idx_tmp < slice_count; idx_tmp++, idx++) { 21557 vmap_new[idx] = vmap[idx_tmp]; 21558 vmap[idx_tmp].valid = FALSE; 21559 } 21560 continue; 21561 } 21562 } 21563 21564 if (FALSE == group_installed) { 21565 /* New group insertion portion. */ 21566 /* 21567 * Increment virtual priority index to meet even boundary 21568 * constraints. 21569 */ 21570 if ((even_boundary_constraint) && 21571 (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) && 21572 (0 != (idx % 2))) { 21573 idx++; 21574 } 21575 21576 /* Get number of slices required for this map. */ 21577 rv = _bcm_field_group_slice_count_get(fg->flags, &slice_count); 21578 BCM_IF_ERROR_RETURN(rv); 21579 21580 /* Set virtual map info. */ 21581 for (idx_tmp = 0; idx_tmp < slice_count; idx_tmp++, idx++) { 21582 /* Allocate virtual group id. */ 21583 if (BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT == virtual_group[idx_tmp]) { 21584 vmap = vmap_orig; 21585 rv = _field_vmap_resource_alloc(unit, vmap, vmap_size, 21586 &unused_groups, 21587 &virtual_group[idx_tmp]); 21588 BCM_IF_ERROR_RETURN(rv); 21589 /* Valid action res id will have all slices mapped to same virtual group */ 21590 if (BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT != fg->action_res_id) { 21591 for (idx_pair = 1; idx_pair < _FP_PAIR_MAX; idx_pair++) { 21592 virtual_group[idx_pair] = virtual_group[idx_tmp]; 21593 } 21594 } 21595 } 21596 vmap_new[idx].valid = TRUE; 21597 vmap_new[idx].vmap_key = vmap_key + idx_tmp; 21598 vmap_new[idx].virtual_group = virtual_group[idx_tmp]; 21599 vmap_new[idx].priority = fg->priority; 21600 vmap_new[idx].flags = fg->flags; 21601 21602 unused_slices &= ~(1 << (vmap_key + idx_tmp)); 21603 } 21604 group_installed = TRUE; 21605 } 21606 if (-1 == candidate) { 21607 /* No more groups to install. */ 21608 break; 21609 } 21610 } 21611 21612 if (group_installed == FALSE) { 21613 return BCM_E_RESOURCE; 21614 } 21615 21616 /* Assign distinct virtual group numbers to unused virtual slices */ 21617 vmap = vmap_orig; 21618 for (idx = 0; idx < vmap_size; idx++) { 21619 if (vmap_new[idx].valid == TRUE) { 21620 continue; 21621 } 21622 /* Allocated unused virtual group id. */ 21623 rv = _field_vmap_resource_alloc(unit, vmap, vmap_size, 21624 &unused_groups, &idx_tmp); 21625 BCM_IF_ERROR_RETURN(rv); 21626 vmap_new[idx].virtual_group = idx_tmp; 21627 21628 /* Allocated unused physical slice. */ 21629 rv = _field_vmap_resource_alloc(unit, vmap, vmap_size, 21630 &unused_slices, &idx_tmp); 21631 BCM_IF_ERROR_RETURN(rv); 21632 vmap_new[idx].vmap_key = idx_tmp; 21633 } 21634 21635 /* Write new map to the slice virtual map. */ 21636 sal_memcpy(stage_fc->vmap[inst][map_id], vmap_new, sizeof_vmap); 21637 21638 /* 21639 * Write the new_fp_virtual_map to H/W, and 21640 * copy to stage's fp_virtual_map 21641 */ 21642 if (install) { 21643 rv = fc->functions.fp_write_slice_map(unit, stage_fc, fg); 21644 BCM_IF_ERROR_RETURN(rv); 21645 } 21646 #if defined(BROADCOM_DEBUG) 21647 for (idx = 0; idx < vmap_size; idx++) { 21648 vmap = stage_fc->vmap[inst][map_id] + idx; 21649 if (0 == vmap->valid) { 21650 continue; 21651 } 21652 LOG_DEBUG(BSL_LS_BCM_FP, 21653 (BSL_META_U(unit, 21654 "FP(unit %d) vverb: vmap_id (%d): virutal group (%d)" 21655 "physical slice (%d) flags (%d)\n"), 21656 unit, idx, vmap->virtual_group, 21657 vmap->vmap_key, 21658 vmap->flags)); 21659 } 21660 #endif /* BROADCOM_DEBUG */ 21661 return BCM_E_NONE; 21662 } 21663 21664 /* 21665 * Function: _field_virtual_map_insert 21666 * 21667 * Purpose: 21668 * Insert fp group slices 21669 * Parameters: 21670 * unit - (IN) BCM device number. 21671 * stage_fc - (IN) Stage field control structure. 21672 * fg - (IN) Field group structure. 21673 * map_id - (IN) Virtual map id. 21674 * install - (IN) Install the map in hw flag. 21675 * Returns: 21676 * BCM_E_XXX 21677 */ 21678 STATIC int 21679 _field_virtual_map_insert(int unit, _field_stage_t *stage_fc, 21680 _field_group_t *fg, uint8 map_id, 21681 uint8 install) 21682 { 21683 int v_group[_FP_PAIR_MAX]; /* Virtual group id. */ 21684 _field_slice_t *fs; /* Field slice pointer. */ 21685 int vmap_key; /* Virtual map key. */ 21686 int tmp_install; /* Install map in hw. */ 21687 int idx; /* group iteration index. */ 21688 int rv; /* Operation return status. */ 21689 21690 /* Input parameters check. */ 21691 if ((NULL == stage_fc) || (NULL == fg)) { 21692 return (BCM_E_PARAM); 21693 } 21694 21695 /* Initialize virtual group ids. */ 21696 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 21697 v_group[idx] = fg->vmap_group[idx]; 21698 } 21699 21700 /* Get to the last slice. */ 21701 fs = fg->slices; 21702 while (fs->next != NULL) { 21703 fs = fs->next; 21704 } 21705 21706 while (fs != NULL) { 21707 tmp_install = ((fs == fg->slices) && (install)) ? TRUE : FALSE; 21708 vmap_key = (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) ? \ 21709 (_FP_VMAP_SIZE - 1) : fs->slice_number; 21710 rv = _field_virtual_map_insert2(unit, stage_fc, fg, map_id, 21711 vmap_key, v_group, tmp_install); 21712 BCM_IF_ERROR_RETURN(rv); 21713 fs = fs->prev; 21714 } 21715 21716 /* Update virtual group index */ 21717 if (fg->vmap_group[0] == BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT) { 21718 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 21719 fg->vmap_group[idx] = v_group[idx]; 21720 } 21721 } 21722 return (BCM_E_NONE); 21723 } 21724 21725 /* 21726 * Function: _field_virtual_map_remove 21727 * 21728 * Purpose: 21729 * For chips which support the virtual slice/group feature, 21730 * Wipe out groups physical slices from virtual map. 21731 * Parameters: 21732 * unit - (IN) BCM device number. 21733 * stage_fc - (IN) Stage field control structure. 21734 * fg - (IN) Field Group Structure. 21735 * map_id - (IN) Virtual map id. 21736 * vmap_key - (IN) Virtual map key. 21737 * install - (IN) Perform installation in HW flag. 21738 * Returns: 21739 * BCM_E_XXX 21740 */ 21741 STATIC int 21742 _field_virtual_map_remove(int unit, _field_stage_t *stage_fc, _field_group_t *fg, 21743 uint8 map_id, int vmap_key, int install) 21744 { 21745 int idx; /* Virtual map iteration index. */ 21746 int idx_tmp=0; /* Temp iteration index. */ 21747 int slice_count; /* Number of slices used by group.*/ 21748 _field_control_t *fc; /* Field control structure. */ 21749 uint32 unused_groups; /* Unused virtual groups bitmap. */ 21750 uint32 unused_slices; /* Unused physical slices bitmap */ 21751 int rv = BCM_E_NONE; /* Operation return status. */ 21752 int v_group[_FP_PAIR_MAX]; /* Virtual group id. */ 21753 _field_virtual_map_t *vmap = NULL; /* Currently used virtual map. */ 21754 int vmap_size; /* Virtual map size. */ 21755 int inst; /* Pipe Instance. */ 21756 21757 /* Input parameters check. */ 21758 if ((NULL == stage_fc) || (NULL == fg)) { 21759 return (BCM_E_PARAM); 21760 } 21761 21762 /* Find and validate field control. */ 21763 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 21764 21765 inst = fg->instance; 21766 #if defined(BCM_FIREBOLT2_SUPPORT) 21767 if (SOC_IS_FIREBOLT2(unit)) { 21768 /* FB2 supports virtual priority in stage ingress only. */ 21769 if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) { 21770 return (BCM_E_NONE); 21771 } 21772 } 21773 #endif /* BCM_FIREBOLT2_SUPPORT */ 21774 21775 /* Calculate virtual map size. */ 21776 rv = _bcm_field_virtual_map_size_get(unit, stage_fc, &vmap_size); 21777 BCM_IF_ERROR_RETURN(rv); 21778 21779 21780 /* Get virtual group id. */ 21781 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 21782 v_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 21783 } 21784 21785 for (idx = 0; idx < vmap_size; idx++) { 21786 vmap = (stage_fc->vmap[inst][map_id]) + idx; 21787 if (TRUE != vmap->valid) { 21788 continue; 21789 } 21790 if (vmap->vmap_key == vmap_key) { 21791 break; 21792 } 21793 } 21794 21795 /* Make sure virtual group was found. */ 21796 if (idx == vmap_size) { 21797 /* No such virtual group. */ 21798 return (rv); 21799 } 21800 21801 /* Get group width. */ 21802 rv = _bcm_field_group_slice_count_get(vmap->flags, &slice_count); 21803 BCM_IF_ERROR_RETURN(rv); 21804 21805 /* Get virtual group ids. */ 21806 for (idx = 0; idx < slice_count; idx++) { 21807 v_group[idx] = (vmap + idx)->virtual_group; 21808 } 21809 21810 /* Mark group maps as invalid. */ 21811 for (idx = 0; idx < vmap_size; idx++) { 21812 vmap = stage_fc->vmap[inst][map_id] + idx; 21813 if (TRUE != vmap->valid) { 21814 continue; 21815 } 21816 /* Check if slice and virtual group matches to mark it invalid*/ 21817 for (idx_tmp = 0; idx_tmp < slice_count; idx_tmp++) { 21818 if ((vmap->virtual_group == v_group[idx_tmp]) && 21819 (vmap->vmap_key == (vmap_key + idx_tmp))){ 21820 vmap->valid = FALSE; 21821 } 21822 } 21823 } 21824 21825 /* Get unused virtual groups & physical slices */ 21826 vmap = stage_fc->vmap[inst][map_id]; 21827 rv = _field_vmap_unused_resources_get(unit, vmap, vmap_size, 21828 &unused_groups, &unused_slices); 21829 BCM_IF_ERROR_RETURN(rv); 21830 21831 21832 /* Assign distinct virtual group numbers to unused virtual slices */ 21833 for (idx = 0; idx < vmap_size; idx++) { 21834 vmap = (stage_fc->vmap[inst][map_id]) + idx; 21835 if (vmap->valid == TRUE) { 21836 continue; 21837 } 21838 /* Allocated unused virtual group id. */ 21839 rv = _field_vmap_resource_alloc(unit, vmap, vmap_size, 21840 &unused_groups, &idx_tmp); 21841 vmap->virtual_group = idx_tmp; 21842 21843 /* Allocated unused physical slice. */ 21844 rv = _field_vmap_resource_alloc(unit, vmap, vmap_size, 21845 &unused_slices, &idx_tmp); 21846 vmap->vmap_key = idx_tmp; 21847 } 21848 21849 21850 /* 21851 * Write the new_fp_virtual_map to H/W, and copy to stage's fp_virtual_map 21852 */ 21853 if (install) { 21854 rv = fc->functions.fp_write_slice_map(unit, stage_fc, fg); 21855 } 21856 #if defined(BROADCOM_DEBUG) 21857 for (idx = 0; idx < vmap_size; idx++) { 21858 vmap = stage_fc->vmap[inst][map_id] + idx; 21859 if (0 == vmap->valid) { 21860 continue; 21861 } 21862 LOG_DEBUG(BSL_LS_BCM_FP, 21863 (BSL_META_U(unit, 21864 "FP(unit %d) vverb: vmap_id (%d): virutal group (%d)" 21865 "physical slice (%d) flags (%d)\n"), 21866 unit, idx, vmap->virtual_group, 21867 vmap->vmap_key, 21868 vmap->flags)); 21869 } 21870 #endif /* BROADCOM_DEBUG */ 21871 21872 return rv; 21873 } 21874 21875 21876 /* 21877 * Function: _field_group_vmap_delete 21878 * 21879 * Purpose: 21880 * For chips which support the virtual slice/group feature, 21881 * Wipe out groups physical slices from virtual map. 21882 * Parameters: 21883 * unit - (IN) BCM device number. 21884 * stage_fc - (IN) Stage field control structure. 21885 * fg - (IN) Field group structure. 21886 * install - (IN) Perform installation in HW flag. 21887 * Returns: 21888 * BCM_E_XXX 21889 */ 21890 int 21891 _field_group_vmap_delete(int unit, _field_stage_t *stage_fc, 21892 _field_group_t *fg, int install) 21893 { 21894 _field_slice_t *fs; /* Field slice structure. */ 21895 int idx; /* Temp iteration index. */ 21896 int rv; /* Operation return status.*/ 21897 21898 fs = fg->slices; 21899 21900 /* Find and validate field control. */ 21901 21902 21903 /* Loop for deleting all the AUTO expanded slices in group */ 21904 while(fs != NULL) { 21905 21906 switch (stage_fc->stage_id) { 21907 case _BCM_FIELD_STAGE_LOOKUP: 21908 case _BCM_FIELD_STAGE_EGRESS: 21909 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21910 _FP_VMAP_DEFAULT, fs->slice_number, install); 21911 BCM_IF_ERROR_RETURN(rv); 21912 break; 21913 case _BCM_FIELD_STAGE_EXTERNAL: 21914 idx = (_FP_VMAP_SIZE) - 1; 21915 /* External slices controlled by stage ingress map. */ 21916 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, 21917 &stage_fc); 21918 BCM_IF_ERROR_RETURN(rv); 21919 21920 #if defined(BCM_TRIUMPH3_SUPPORT) 21921 if (SOC_IS_TRIUMPH3(unit)) { 21922 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21923 _FP_VMAP_DEFAULT, idx, FALSE); 21924 BCM_IF_ERROR_RETURN(rv); 21925 21926 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21927 _FP_EXT_IP4, idx, FALSE); 21928 BCM_IF_ERROR_RETURN(rv); 21929 21930 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21931 _FP_EXT_IP6, idx, install); 21932 } else 21933 #endif 21934 { 21935 if ((fg->slices)->pkt_type[_FP_EXT_L2]) { 21936 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21937 _FP_EXT_L2, idx, install); 21938 } else if ((fg->slices)->pkt_type[_FP_EXT_IP4]) { 21939 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21940 _FP_EXT_IP4, idx, install); 21941 } else if ((fg->slices)->pkt_type[_FP_EXT_IP6]) { 21942 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21943 _FP_EXT_IP6, idx, install); 21944 } else { 21945 rv = BCM_E_INTERNAL; 21946 } 21947 } 21948 BCM_IF_ERROR_RETURN(rv); 21949 break; 21950 case _BCM_FIELD_STAGE_INGRESS: 21951 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21952 _FP_VMAP_DEFAULT, fs->slice_number, FALSE); 21953 BCM_IF_ERROR_RETURN(rv); 21954 21955 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21956 _FP_EXT_IP4, fs->slice_number, FALSE); 21957 BCM_IF_ERROR_RETURN(rv); 21958 21959 rv = _field_virtual_map_remove(unit, stage_fc, fg, 21960 _FP_EXT_IP6, fs->slice_number, install); 21961 BCM_IF_ERROR_RETURN(rv); 21962 break; 21963 default: 21964 return BCM_E_INTERNAL; 21965 } 21966 fs = fs->next; 21967 } 21968 21969 return (BCM_E_NONE); 21970 } 21971 21972 21973 /* 21974 * Function: _field_group_vmap_add 21975 * 21976 * Purpose: 21977 * For chips which support the virtual slice/group feature, 21978 * Add group physical slices to virtual map. 21979 * Parameters: 21980 * unit - (IN) BCM device number. 21981 * stage_fc - (IN) Stage field control structure. 21982 * fg - (IN) Field group structure. 21983 * Returns: 21984 * BCM_E_XXX 21985 */ 21986 int 21987 _field_group_vmap_add(int unit, _field_stage_t *stage_fc, 21988 _field_group_t *fg) 21989 { 21990 int rv; /* Operation return status.*/ 21991 21992 switch (stage_fc->stage_id) { 21993 case _BCM_FIELD_STAGE_LOOKUP: 21994 case _BCM_FIELD_STAGE_EGRESS: 21995 rv = _field_virtual_map_insert(unit, stage_fc, fg, 21996 _FP_VMAP_DEFAULT, TRUE); 21997 BCM_IF_ERROR_RETURN(rv); 21998 break; 21999 case _BCM_FIELD_STAGE_EXTERNAL: 22000 /* External slices controlled by stage ingress map. */ 22001 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, 22002 &stage_fc); 22003 BCM_IF_ERROR_RETURN(rv); 22004 22005 #if defined(BCM_TRIUMPH3_SUPPORT) 22006 if (SOC_IS_TRIUMPH3(unit)) { 22007 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22008 _FP_VMAP_DEFAULT, FALSE); 22009 BCM_IF_ERROR_RETURN(rv); 22010 22011 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22012 _FP_EXT_IP4, FALSE); 22013 BCM_IF_ERROR_RETURN(rv); 22014 22015 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22016 _FP_EXT_IP6, TRUE); 22017 } else 22018 #endif 22019 { 22020 if ((fg->slices)->pkt_type[_FP_EXT_L2]) { 22021 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22022 _FP_EXT_L2, TRUE); 22023 } else if ((fg->slices)->pkt_type[_FP_EXT_IP4]) { 22024 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22025 _FP_EXT_IP4, TRUE); 22026 } else if ((fg->slices)->pkt_type[_FP_EXT_IP6]) { 22027 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22028 _FP_EXT_IP6, TRUE); 22029 } else { 22030 rv = BCM_E_INTERNAL; 22031 } 22032 } 22033 BCM_IF_ERROR_RETURN(rv); 22034 break; 22035 case _BCM_FIELD_STAGE_INGRESS: 22036 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22037 _FP_VMAP_DEFAULT, FALSE); 22038 BCM_IF_ERROR_RETURN(rv); 22039 22040 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22041 _FP_EXT_IP4, FALSE); 22042 BCM_IF_ERROR_RETURN(rv); 22043 22044 rv = _field_virtual_map_insert(unit, stage_fc, fg, 22045 _FP_EXT_IP6, TRUE); 22046 BCM_IF_ERROR_RETURN(rv); 22047 break; 22048 default: 22049 return BCM_E_INTERNAL; 22050 } 22051 22052 return (BCM_E_NONE); 22053 } 22054 22055 /* 22056 * Function: _field_group_free_unused_slices 22057 * 22058 * Purpose: 22059 * Unallocate group unused slices. 22060 * Parameters: 22061 * unit - (IN) BCM device number. 22062 * stage_fc - (IN) Stage field control structure. 22063 * fg - (IN) Field group structure. 22064 * Returns: 22065 * BCM_E_XXX 22066 */ 22067 int 22068 _field_group_free_unused_slices(int unit, _field_stage_t *stage_fc, 22069 _field_group_t *fg) 22070 { 22071 _field_slice_t *fs; /* Field slice structure. */ 22072 _field_slice_t *fs_next; /* Field slice structure. */ 22073 _field_slice_t *fs_ptr; /* Field slice structure. */ 22074 uint8 empty; /* Slice is empty flag. */ 22075 int idx; /* Group slices iteration index. */ 22076 int remap; /* Reinstall virtual slice map. */ 22077 int count; /* Group slices iteration index. */ 22078 int rv; /* Operation return status. */ 22079 _field_group_t *curr_group; 22080 _field_control_t *fc; 22081 bcm_field_group_mode_t mode1 = 0; 22082 bcm_field_group_mode_t mode2 = 0; 22083 22084 int temp_rv = 0; /* Operation return status. */ 22085 int err_occured = 0; 22086 int virtual_priority = FALSE;/* Virtual priority support flag.*/ 22087 22088 /* We never free first group slice. */ 22089 fs = fg->slices->next; 22090 remap = FALSE; 22091 22092 _field_virtual_priority_support(unit, stage_fc, &virtual_priority); 22093 22094 while (fs != NULL) { 22095 fs_next = fs->next; 22096 rv = _field_slice_is_empty(unit, fs, &empty); 22097 BCM_IF_ERROR_RETURN(rv); 22098 if (empty) { 22099 BCM_IF_ERROR_RETURN 22100 (_bcm_field_group_slice_count_get(fs->group_flags, &count)); 22101 22102 if ((remap == FALSE) 22103 && (virtual_priority)) { 22104 BCM_IF_ERROR_RETURN(_field_group_vmap_delete(unit, stage_fc, fg, FALSE)); 22105 } 22106 22107 remap = TRUE; 22108 /* Preserve next slice to continue the loop over group slices. */ 22109 22110 for (idx = 0; idx < count; idx++) { 22111 /* Remove slice from group slices linked list. */ 22112 fs_ptr = fs + idx; 22113 if (fs_ptr->prev != NULL) { 22114 fs_ptr->prev->next = fs_ptr->next; 22115 } 22116 22117 if (fs_ptr->next != NULL) { 22118 fs_ptr->next->prev = fs_ptr->prev; 22119 } 22120 22121 /* Clear used entries pbmp. */ 22122 /* for a per-port group, the slice should be cleared 22123 * if the entries of all the groups sharing the slice 22124 * are removed. 22125 */ 22126 if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) && 22127 (fg->priority != BCM_FIELD_GROUP_PRIO_ANY)) { 22128 /* Get device Field control structure. */ 22129 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 22130 curr_group = fc->groups; 22131 22132 if (curr_group == NULL) { 22133 return BCM_E_NONE; 22134 } 22135 temp_rv = 0; 22136 err_occured = 0; 22137 while (curr_group != NULL) { 22138 if ((curr_group->stage_id == fg->stage_id) && 22139 (curr_group->flags & 22140 _FP_GROUP_PER_PORT_OR_PBMP) && 22141 (curr_group->priority == fg->priority)) { 22142 _bcm_esw_field_group_mode_get(curr_group->flags, 22143 &mode1); 22144 _bcm_esw_field_group_mode_get(fg->flags, 22145 &mode2); 22146 if( (mode1 == mode2) ){ 22147 /* uninstall selcodes of this group in the 22148 * slice. selcodes are uninstalled only 22149 * when the slice is not having any entry 22150 * of the groups it shares with. 22151 */ 22152 temp_rv = _field_slice_clear(unit, 22153 curr_group, 22154 fs_ptr, 22155 curr_group->pbmp); 22156 if (BCM_FAILURE(temp_rv)) { 22157 err_occured = temp_rv; 22158 } 22159 } 22160 } 22161 curr_group = curr_group->next; 22162 } 22163 if (err_occured) { 22164 return err_occured; 22165 } else { 22166 fs_ptr->next = fs_ptr->prev = NULL; 22167 } 22168 } else { 22169 rv = _field_slice_clear(unit, fg, fs_ptr, fg->pbmp); 22170 BCM_IF_ERROR_RETURN(rv); 22171 fs_ptr->next = fs_ptr->prev = NULL; 22172 } 22173 } 22174 } 22175 fs = fs_next; 22176 } 22177 22178 if ((remap) 22179 && (virtual_priority)){ 22180 /* Remove the group from virtual map . */ 22181 BCM_IF_ERROR_RETURN(_field_group_vmap_add(unit, stage_fc, fg)); 22182 } 22183 22184 return (BCM_E_NONE); 22185 } 22186 22187 /* 22188 * Function: _field_group_uninstall 22189 * 22190 * Purpose: 22191 * Uninstall group from all slices. 22192 * 22193 * Parameters: 22194 * unit - (IN)BCM device number. 22195 * fg - (IN)Field group. 22196 * 22197 * Returns: 22198 * BCM_E_XXX 22199 */ 22200 int 22201 _field_group_uninstall(int unit, _field_group_t *fg) 22202 { 22203 _field_slice_t *fs; /* Field slice structure. */ 22204 _field_slice_t *temp_fs; /* Expanded slices iterator.*/ 22205 int parts_count = 0; /* Number of entry parts. */ 22206 uint32 entry_flags; /* Entry part flags. */ 22207 uint8 slice_number;/* Slices iterator. */ 22208 int rv; /* Operation return status. */ 22209 int idx; /* Slices iterator. */ 22210 22211 22212 /* Find and validate field control. */ 22213 22214 22215 /* Get number of entry parts . */ 22216 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 22217 fg->flags, &parts_count); 22218 BCM_IF_ERROR_RETURN(rv); 22219 22220 22221 for (idx = parts_count - 1; idx >= 0; idx--) { 22222 /* Get entry flags. */ 22223 rv = _bcm_field_tcam_part_to_entry_flags(unit, idx, fg, 22224 &entry_flags); 22225 BCM_IF_ERROR_RETURN(rv); 22226 22227 if (entry_flags & _FP_ENTRY_SECOND_HALF) { 22228 continue; 22229 } 22230 22231 /* Get slice id for entry part */ 22232 rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg, 22233 &slice_number); 22234 BCM_IF_ERROR_RETURN(rv); 22235 22236 fs = fg->slices + slice_number; 22237 while (fs != NULL) { 22238 /* Clear tertiary slice, if in-use. */ 22239 BCM_IF_ERROR_RETURN(_field_slice_clear(unit, fg, fs, fg->pbmp)); 22240 temp_fs = fs->next; 22241 if (fs->prev != NULL) { 22242 fs->prev->next = NULL; 22243 fs->prev = NULL; 22244 } 22245 fs = temp_fs; 22246 } 22247 } 22248 return (BCM_E_NONE); 22249 } 22250 22251 /* 22252 * Function: 22253 * _bcm_field_group_linked_list_remove 22254 * Purpose: 22255 * Remove field group from unit's groups list 22256 * Parameters: 22257 * unit - (IN) BCM device number. 22258 * fg - (IN) State machine tracking structure. 22259 * Returns: 22260 * BCM_E_XXX 22261 */ 22262 int 22263 _bcm_field_group_linked_list_remove(int unit, _field_group_t *fg) 22264 { 22265 _field_control_t *fc; /* Field control structure. */ 22266 _field_group_t *fg_prev; /* Fied group iterator. */ 22267 22268 if (NULL == fg) { 22269 return (BCM_E_PARAM); 22270 } 22271 22272 /* Find and validate field control. */ 22273 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 22274 22275 /* Remove this group from device's linked-list of groups. */ 22276 if (fc->groups == fg) { 22277 fc->groups = fg->next; 22278 } 22279 else { 22280 fg_prev = fc->groups; 22281 while (NULL != fg_prev) { 22282 if (fg_prev->next == fg) { 22283 fg_prev->next = fg->next; 22284 break; 22285 } 22286 fg_prev = fg_prev->next; 22287 } 22288 } 22289 return (BCM_E_NONE); 22290 } 22291 22292 /* 22293 * Function: 22294 * _field_group_linked_list_insert 22295 * Purpose: 22296 * Insert new field group into unit's groups list sorted 22297 * by priority & group width. 22298 * Parameters: 22299 * unit - (IN) BCM device number. 22300 * fsm_ptr - (IN) State machine tracking structure. 22301 * Returns: 22302 * BCM_E_XXX 22303 */ 22304 int 22305 _bcm_field_group_linked_list_insert(int unit, _field_group_add_fsm_t *fsm_ptr) 22306 { 22307 _field_group_t *fg; /* Field group pointer. */ 22308 _field_group_t *fg_iter; /* Field group iterator. */ 22309 _field_group_t *fg_iter_prev; /* Field group iterator. */ 22310 22311 22312 /* Input parameters check. */ 22313 if (NULL == fsm_ptr) { 22314 return (BCM_E_PARAM); 22315 } 22316 22317 fg = fsm_ptr->fg; 22318 if (NULL == fg) { 22319 return (BCM_E_PARAM); 22320 } 22321 22322 /* Linked list insertion must be done after group mode was 22323 decided(after select codes selection stage). On 5682x devices 22324 we might need to reselect select codes based on slice availability, 22325 to avoid double insertion remove any installed group first. 22326 */ 22327 BCM_IF_ERROR_RETURN(_bcm_field_group_linked_list_remove(unit, fg)); 22328 22329 /* Insert new field group into unit's groups list sorted by priority. */ 22330 fg_iter_prev = fg_iter = fsm_ptr->fc->groups; 22331 while (fg_iter != NULL) { 22332 /* Priority comparison: low to high insertion. */ 22333 if (fg_iter->priority > fg->priority) { 22334 break; 22335 } 22336 22337 /* Group width comparison: wide group first. */ 22338 if (fg_iter->priority == fg->priority) { 22339 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 22340 break; 22341 } 22342 22343 if ((0 == (fg_iter->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) && 22344 (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) { 22345 break; 22346 } 22347 } 22348 22349 fg_iter_prev = fg_iter; 22350 fg_iter = fg_iter->next; 22351 } 22352 22353 /* Head of the list insertion. */ 22354 if (fg_iter == fg_iter_prev) { 22355 fg->next = fg_iter; 22356 fsm_ptr->fc->groups = fg; 22357 } else { 22358 fg_iter_prev->next = fg; 22359 fg->next = fg_iter; 22360 } 22361 return (BCM_E_NONE); 22362 } 22363 22364 /* 22365 * Function: _field_group_deinit 22366 * Purpose: 22367 * Destroy field group structure. 22368 * Parameters: 22369 * unit - (IN) BCM device number. 22370 * fg - (IN) Allocated group structure. 22371 * 22372 * Returns: 22373 * BCM_E_NONE - Success 22374 */ 22375 int 22376 _field_group_deinit(int unit, _field_group_t *fg) 22377 { 22378 _field_control_t *fc; /* Field control structure. */ 22379 int idx; /* Qualifiers iteration index. */ 22380 int rv = BCM_E_NONE; /* OPerational Status. */ 22381 22382 if (NULL == fg) { 22383 return (BCM_E_NONE); 22384 } 22385 22386 /* Find and validate field control. */ 22387 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 22388 22389 /* Uninstall group from every slice. */ 22390 if (NULL != fg->slices) { 22391 _field_group_uninstall(unit, fg); 22392 } 22393 22394 /* Deallocate group qualifiers list. */ 22395 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 22396 /* If qualifier set was updated free original qualifiers array. */ 22397 BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(fg, idx)); 22398 } 22399 22400 /* Decrement the use counts for any UDFs used by the group */ 22401 for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) { 22402 /* coverity[ptr_arith] */ 22403 if (SHR_BITGET(fg->qset.udf_map, idx)) { 22404 if (fc->udf[idx].use_count > 0) { 22405 fc->udf[idx].use_count--; 22406 } 22407 } 22408 } 22409 22410 /* Deallocate group entry array if any. */ 22411 if (NULL != fg->entry_arr) { 22412 sal_free(fg->entry_arr); 22413 } 22414 22415 rv = _bcm_field_group_stat_destroy(unit, fg->gid); 22416 BCM_IF_ERROR_RETURN(rv); 22417 22418 /* Remove group from units group list. */ 22419 BCM_IF_ERROR_RETURN(_bcm_field_group_linked_list_remove(unit, fg)); 22420 22421 if ( soc_feature(unit, soc_feature_field_multi_pipe_support) || 22422 soc_feature(unit, soc_feature_field_ingress_two_slice_types)) { 22423 /* Group has been destroyed, Decrement group ref count in 22424 * corresponding hintid in hints hash lookup table */ 22425 BCM_IF_ERROR_RETURN( 22426 _bcm_field_hints_group_count_update (unit, fg->hintid, 0)); 22427 } 22428 22429 sal_free(fg); 22430 return (BCM_E_NONE); 22431 } 22432 22433 #ifdef BCM_FIREBOLT_SUPPORT 22434 /* 22435 * Function: 22436 * _field_fb_slice_to_field 22437 * 22438 * Purpose: 22439 * Determines which FP_SLICE_ENABLEr field corresponds to given slice. 22440 * 22441 * Parameters: 22442 * slice - slice number 22443 * field - (OUT) FP_SLICE_ENABLE register field 22444 * 22445 * Returns: 22446 * BCM_E_NONE - Success 22447 * BCM_E_PARAM - slice number out of range 22448 */ 22449 STATIC int 22450 _field_fb_slice_to_field(_field_group_t *fg, 22451 int slice, soc_field_t *field) 22452 { 22453 static soc_field_t _ifp_slice_enable_field[16] = { 22454 FP_LOOKUP_ENABLE_SLICE_0f, 22455 FP_LOOKUP_ENABLE_SLICE_1f, 22456 FP_LOOKUP_ENABLE_SLICE_2f, 22457 FP_LOOKUP_ENABLE_SLICE_3f, 22458 FP_LOOKUP_ENABLE_SLICE_4f, 22459 FP_LOOKUP_ENABLE_SLICE_5f, 22460 FP_LOOKUP_ENABLE_SLICE_6f, 22461 FP_LOOKUP_ENABLE_SLICE_7f, 22462 FP_LOOKUP_ENABLE_SLICE_8f, 22463 FP_LOOKUP_ENABLE_SLICE_9f, 22464 FP_LOOKUP_ENABLE_SLICE_10f, 22465 FP_LOOKUP_ENABLE_SLICE_11f, 22466 FP_LOOKUP_ENABLE_SLICE_12f, 22467 FP_LOOKUP_ENABLE_SLICE_13f, 22468 FP_LOOKUP_ENABLE_SLICE_14f, 22469 FP_LOOKUP_ENABLE_SLICE_15f}; 22470 22471 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 22472 static soc_field_t _vfp_slice_enable_field[4] = {LOOKUP_ENABLE_SLICE_0f, 22473 LOOKUP_ENABLE_SLICE_1f, 22474 LOOKUP_ENABLE_SLICE_2f, 22475 LOOKUP_ENABLE_SLICE_3f}; 22476 22477 static soc_field_t _efp_slice_enable_field[4] = {LOOKUP_ENABLE_SLICE_0f, 22478 LOOKUP_ENABLE_SLICE_1f, 22479 LOOKUP_ENABLE_SLICE_2f, 22480 LOOKUP_ENABLE_SLICE_3f}; 22481 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 22482 22483 assert(fg != NULL && field != NULL); 22484 if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 22485 if (slice < 0 || slice >= COUNTOF(_ifp_slice_enable_field)) { 22486 return (BCM_E_PARAM); 22487 } 22488 *field = _ifp_slice_enable_field[slice]; 22489 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 22490 } else if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) { 22491 if (slice < 0 || slice >= COUNTOF(_vfp_slice_enable_field)) { 22492 return (BCM_E_PARAM); 22493 } 22494 *field = _vfp_slice_enable_field[slice]; 22495 22496 } else if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) { 22497 if (slice < 0 || slice >= COUNTOF(_efp_slice_enable_field)) { 22498 return (BCM_E_PARAM); 22499 } 22500 *field = _efp_slice_enable_field[slice]; 22501 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 22502 } else { 22503 return (BCM_E_INTERNAL); 22504 } 22505 return (BCM_E_NONE); 22506 } 22507 22508 /* 22509 * Function: 22510 * _field_fb_slice_enable_set 22511 * 22512 * Purpose: 22513 * Enables or disables packet lookup on a hardware slice. 22514 * 22515 * Parameters: 22516 * unit - BCM device number 22517 * slice - Slice number to enable 22518 * enable - enable/disable state of slice 22519 * 22520 * Returns: 22521 * BCM_E_NONE - Success 22522 * BCM_E_INTERNAL - SOC read/write error 22523 * 22524 * Note: 22525 * Calling function is responsible for checking feature availability. 22526 */ 22527 int 22528 _bcm_field_fb_slice_enable_set(int unit, _field_group_t *fg, 22529 uint8 slice, int enable) 22530 { 22531 uint32 reg_val_old, reg_val_new; 22532 soc_field_t field; 22533 22534 LOG_VERBOSE(BSL_LS_BCM_FP, 22535 (BSL_META_U(unit, 22536 "FP: _field_fb_slice_enable_set(slice=%d, enable=%d)\n"), 22537 slice, enable)); 22538 22539 if (NULL == fg) { 22540 return (BCM_E_PARAM); 22541 } 22542 22543 BCM_IF_ERROR_RETURN(_field_fb_slice_to_field(fg, slice, &field)); 22544 enable = (enable ? 1 : 0); 22545 if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 22546 SOC_IF_ERROR_RETURN(READ_FP_SLICE_ENABLEr(unit, ®_val_old)); 22547 reg_val_new = reg_val_old; 22548 soc_reg_field_set(unit, FP_SLICE_ENABLEr, ®_val_new, field, enable); 22549 if (reg_val_new != reg_val_old) { 22550 BCM_IF_ERROR_RETURN(WRITE_FP_SLICE_ENABLEr(unit, reg_val_new)); 22551 } 22552 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 22553 } else if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) { 22554 SOC_IF_ERROR_RETURN(READ_VFP_SLICE_CONTROLr(unit, ®_val_old)); 22555 reg_val_new = reg_val_old; 22556 soc_reg_field_set(unit, VFP_SLICE_CONTROLr, ®_val_new, 22557 field, enable); 22558 if (reg_val_new != reg_val_old) { 22559 SOC_IF_ERROR_RETURN(WRITE_VFP_SLICE_CONTROLr(unit, reg_val_new)); 22560 } 22561 } else if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) { 22562 SOC_IF_ERROR_RETURN(READ_EFP_SLICE_CONTROLr(unit, ®_val_old)); 22563 reg_val_new = reg_val_old; 22564 soc_reg_field_set(unit, EFP_SLICE_CONTROLr, ®_val_new, 22565 field, enable); 22566 if (reg_val_new != reg_val_old) { 22567 BCM_IF_ERROR_RETURN(WRITE_EFP_SLICE_CONTROLr(unit, reg_val_new)); 22568 } 22569 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 22570 } else { 22571 return (BCM_E_INTERNAL); 22572 } 22573 22574 22575 return (BCM_E_NONE); 22576 } 22577 #endif /* BCM_FIREBOLT_SUPPORT */ 22578 22579 22580 STATIC int 22581 _field_slice_enable_set(int unit, 22582 _field_stage_t *stage_fc, 22583 _field_group_t *fg, 22584 _field_slice_t *fs, 22585 unsigned enable 22586 ) 22587 { 22588 if (stage_fc->flags & _FP_STAGE_SLICE_ENABLE) { 22589 #if defined (BCM_TOMAHAWK_SUPPORT) 22590 if ((soc_feature(unit, soc_feature_field_multi_pipe_support)) && 22591 ((fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) || 22592 (fg->stage_id == _BCM_FIELD_STAGE_EGRESS))) { 22593 return (_bcm_field_th_slice_enable_set(unit, 22594 fg, fs, 1)); 22595 } 22596 #endif 22597 #ifdef BCM_TRIUMPH3_SUPPORT 22598 if (SOC_IS_TRIUMPH3(unit)) { 22599 return (_bcm_field_tr3_slice_enable_set(unit, stage_fc, fg, fs, 1)); 22600 } 22601 #endif 22602 #ifdef BCM_FIREBOLT_SUPPORT 22603 return (_bcm_field_fb_slice_enable_set(unit, fg, fs->slice_number, 1)); 22604 #endif /* BCM_FIREBOLT_SUPPORT */ 22605 } 22606 22607 return (BCM_E_NONE); 22608 } 22609 22610 22611 unsigned 22612 _field_stage_action_support_check(int unit, 22613 _field_group_t *fg, 22614 unsigned action 22615 ) 22616 { 22617 _field_control_t *fc; 22618 _field_entry_t f_ent[1]; /* Dummy entry */ 22619 int suppf = 0; 22620 22621 if (BCM_FAILURE(_field_control_get(unit, &fc))) { 22622 return (FALSE); 22623 } 22624 22625 /* Set group in dummy entry, since old code takes entry as parameter 22626 (nothing else in entry matters). 22627 */ 22628 22629 f_ent->group = fg; 22630 22631 return (BCM_SUCCESS(fc->functions.fp_action_support_check(unit, 22632 f_ent, 22633 action, 22634 &suppf 22635 ) 22636 ) 22637 && suppf 22638 ); 22639 } 22640 22641 22642 int 22643 _bcm_field_group_default_aset_set(int unit, _field_group_t *fg) 22644 { 22645 /* Set group's aset to all actions supported by stage */ 22646 22647 unsigned action; 22648 22649 for (action = 0; action < bcmFieldActionCount; ++action) { 22650 if (_field_stage_action_support_check(unit, fg, action)) { 22651 SHR_BITSET(fg->aset.w, action); 22652 } 22653 } 22654 22655 return (BCM_E_NONE); 22656 } 22657 22658 22659 int 22660 _field_group_default_aset_set(int unit, _field_group_t *fg) 22661 { 22662 sal_memset(fg->aset.w, 0, sizeof(fg->aset.w)); 22663 22664 #ifdef BCM_TRIUMPH3_SUPPORT 22665 if (SOC_IS_TRIUMPH3(unit)) { 22666 return (_bcm_field_tr3_group_default_aset_set(unit, fg)); 22667 } 22668 #endif 22669 22670 /* Default aset is set of all supported actions */ 22671 return (_bcm_field_group_default_aset_set(unit, fg)); 22672 } 22673 22674 /* 22675 * Function: 22676 * _field_group_add_selcodes_install 22677 * Purpose: 22678 * Update allocated slice sw controls & 22679 * install slice select codes into hw. 22680 * Parameters: 22681 22682 * unit - (IN) BCM device number. 22683 * fsm_ptr - (IN/OUT) State machine tracking structure. 22684 * Returns: 22685 * BCM_E_XXX 22686 */ 22687 STATIC int 22688 _field_group_add_selcodes_install(int unit, _field_group_add_fsm_t *fsm_ptr) 22689 { 22690 _field_slice_t *fs; /* Slice pointer. */ 22691 _field_group_t *fg; /* Field group pointer. */ 22692 uint32 entry_flags; /* Entry lookup flags. */ 22693 uint8 slice_number; /* Slices iterator. */ 22694 int idx; /* Slice iteration index. */ 22695 int parts_count = 0; /* Number of entry parts. */ 22696 int slice_init; /* Slice sw init needed. */ 22697 int rv; /* Operation return status.*/ 22698 22699 /* Input parameters check. */ 22700 if (NULL == fsm_ptr) { 22701 return (BCM_E_PARAM); 22702 } 22703 22704 fg = fsm_ptr->fg; 22705 22706 /* Check if this is the first group installed in slice. */ 22707 slice_init = BCM_PBMP_IS_NULL(fg->slices[0].pbmp) ? TRUE : FALSE; 22708 22709 /* Install slice/s select codes. */ 22710 BCM_PBMP_OR(fg->slices[0].pbmp, fg->pbmp); 22711 22712 /* Write group parameters to hardware. */ 22713 BCM_IF_ERROR_RETURN(fsm_ptr->fc->functions.fp_group_install(unit, fg)); 22714 22715 /* Get number of entry parts. */ 22716 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 22717 fg->flags, &parts_count); 22718 BCM_IF_ERROR_RETURN(rv); 22719 22720 for (idx = parts_count - 1; idx >= 0; idx--) { 22721 /* Get entry flags. */ 22722 rv = _bcm_field_tcam_part_to_entry_flags(unit, idx, fg, 22723 &entry_flags); 22724 BCM_IF_ERROR_RETURN(rv); 22725 22726 /* Get slice id for entry part */ 22727 rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg, 22728 &slice_number); 22729 BCM_IF_ERROR_RETURN(rv); 22730 22731 /* Get slice pointer. */ 22732 fs = fg->slices + slice_number; 22733 22734 /* Enable slice. */ 22735 if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) { 22736 22737 /* Set per slice configuration & number of free entries in the slice.*/ 22738 if (slice_init) { 22739 fs->free_count = fs->entry_count; 22740 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 22741 fs->free_count >>= 1; 22742 } 22743 /* Set group flags in in slice.*/ 22744 fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK; 22745 } 22746 22747 /* Set slice usage by device ports. */ 22748 BCM_PBMP_OR(fs->pbmp, fg->pbmp); 22749 } 22750 /* Set source class selection. */ 22751 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].src_class_sel) { 22752 fs->src_class_sel = fg->sel_codes[idx].src_class_sel; 22753 } 22754 /* Set destination class selection. */ 22755 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].dst_class_sel) { 22756 fs->dst_class_sel = fg->sel_codes[idx].dst_class_sel; 22757 } 22758 /* Set interface class selection. */ 22759 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].intf_class_sel) { 22760 fs->intf_class_sel = fg->sel_codes[idx].intf_class_sel; 22761 } 22762 /* Set loopback type/tunnel type selection. */ 22763 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].loopback_type_sel) { 22764 fs->loopback_type_sel = fg->sel_codes[idx].loopback_type_sel; 22765 } 22766 /* Set ingress entity selection. */ 22767 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].ingress_entity_sel) { 22768 fs->ingress_entity_sel = fg->sel_codes[idx].ingress_entity_sel; 22769 } 22770 /* Set src entity selection. */ 22771 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].src_entity_sel) { 22772 fs->src_entity_sel = fg->sel_codes[idx].src_entity_sel; 22773 } 22774 /* Set destination forwarding entity selection. */ 22775 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].dst_fwd_entity_sel) { 22776 fs->dst_fwd_entity_sel = fg->sel_codes[idx].dst_fwd_entity_sel; 22777 } 22778 22779 /* Set destination forwarding field selection. */ 22780 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].fwd_field_sel) { 22781 fs->fwd_field_sel = fg->sel_codes[idx].fwd_field_sel; 22782 } 22783 22784 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].ttl_class_sel) { 22785 fs->ttl_class_sel = fg->sel_codes[idx].ttl_class_sel; 22786 } 22787 22788 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].tcp_class_sel) { 22789 fs->tcp_class_sel = fg->sel_codes[idx].tcp_class_sel; 22790 } 22791 22792 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].tos_class_sel) { 22793 fs->tos_class_sel = fg->sel_codes[idx].tos_class_sel; 22794 } 22795 22796 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].aux_tag_1_sel) { 22797 fs->aux_tag_1_sel = fg->sel_codes[idx].aux_tag_1_sel; 22798 } 22799 22800 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].aux_tag_2_sel) { 22801 fs->aux_tag_2_sel = fg->sel_codes[idx].aux_tag_2_sel; 22802 } 22803 22804 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].oam_overlay_sel) { 22805 fs->oam_overlay_sel = fg->sel_codes[idx].oam_overlay_sel; 22806 } 22807 22808 if (fg->sel_codes[idx].egr_class_f1_sel != _FP_SELCODE_DONT_CARE) { 22809 fs->egr_class_f1_sel = fg->sel_codes[idx].egr_class_f1_sel; 22810 } 22811 22812 if (fg->sel_codes[idx].egr_class_f2_sel != _FP_SELCODE_DONT_CARE) { 22813 fs->egr_class_f2_sel = fg->sel_codes[idx].egr_class_f2_sel; 22814 } 22815 22816 if (fg->sel_codes[idx].egr_class_f3_sel != _FP_SELCODE_DONT_CARE) { 22817 fs->egr_class_f3_sel = fg->sel_codes[idx].egr_class_f3_sel; 22818 } 22819 22820 if (fg->sel_codes[idx].egr_class_f4_sel != _FP_SELCODE_DONT_CARE) { 22821 fs->egr_class_f4_sel = fg->sel_codes[idx].egr_class_f4_sel; 22822 } 22823 22824 if (fg->sel_codes[idx].src_dest_class_f1_sel != _FP_SELCODE_DONT_CARE) { 22825 fs->src_dest_class_f1_sel = fg->sel_codes[idx].src_dest_class_f1_sel; 22826 } 22827 22828 if (fg->sel_codes[idx].src_dest_class_f3_sel != _FP_SELCODE_DONT_CARE) { 22829 fs->src_dest_class_f3_sel = fg->sel_codes[idx].src_dest_class_f3_sel; 22830 } 22831 22832 if (fg->sel_codes[idx].egr_key4_dvp_sel != _FP_SELCODE_DONT_CARE) { 22833 fs->egr_key4_dvp_sel = fg->sel_codes[idx].egr_key4_dvp_sel; 22834 } 22835 22836 if (fg->sel_codes[idx].egr_key4_mdl_sel != _FP_SELCODE_DONT_CARE) { 22837 fs->egr_key4_mdl_sel = fg->sel_codes[idx].egr_key4_mdl_sel; 22838 } 22839 22840 if (fg->sel_codes[idx].egr_oam_overlay_sel != _FP_SELCODE_DONT_CARE) { 22841 fs->egr_oam_overlay_sel = fg->sel_codes[idx].egr_oam_overlay_sel; 22842 } 22843 22844 if (fg->sel_codes[idx].oam_intf_class_sel != _FP_SELCODE_DONT_CARE) { 22845 fs->oam_intf_class_sel = fg->sel_codes[idx].oam_intf_class_sel; 22846 } 22847 22848 if (fg->sel_codes[idx].egr_dest_port_f1_sel != _FP_SELCODE_DONT_CARE) { 22849 fs->egr_dest_port_f1_sel = fg->sel_codes[idx].egr_dest_port_f1_sel; 22850 } 22851 22852 if (fg->sel_codes[idx].egr_dest_port_f5_sel != _FP_SELCODE_DONT_CARE) { 22853 fs->egr_dest_port_f5_sel = fg->sel_codes[idx].egr_dest_port_f5_sel; 22854 } 22855 22856 /* Set intraslice double wide key selection. */ 22857 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 22858 if ((_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].fpf2) && 22859 ((idx == _FP_INTRA_SLICE_PART_1) || 22860 (idx == _FP_INTRA_SLICE_PART_3))) { 22861 fs->doublewide_key_select = fg->sel_codes[idx].fpf2; 22862 } 22863 } 22864 } 22865 return (BCM_E_NONE); 22866 } 22867 22868 /* 22869 * Function: 22870 * _field_group_add_adjust_virtual_map 22871 * Purpose: 22872 * Update slices virtual priorities map. 22873 * Parameters: 22874 * unit - (IN) BCM device number. 22875 * fsm_ptr - (IN/OUT) State machine tracking structure. 22876 * Returns: 22877 * BCM_E_XXX 22878 */ 22879 STATIC int 22880 _field_group_add_adjust_virtual_map(int unit, _field_group_add_fsm_t *fsm_ptr) 22881 { 22882 _field_group_t *fg; /* Field group control structure. */ 22883 int virtual_priority = FALSE;/* Virtual priority support flag.*/ 22884 22885 /* Input parameters check. */ 22886 if (NULL == fsm_ptr) { 22887 return (BCM_E_PARAM); 22888 } 22889 22890 _field_virtual_priority_support(unit, fsm_ptr->stage_fc, &virtual_priority); 22891 22892 /* Initialize group pointer. */ 22893 fg = fsm_ptr->fg; 22894 22895 /* Set current state to be previous state. */ 22896 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 22897 22898 /* Update slices virtual priorities map. */ 22899 if (virtual_priority) { 22900 if (BCM_PBMP_EQ(fg->slices->pbmp, fg->pbmp)) { 22901 /* 22902 * If this is a first group in a slice 22903 * a) allocate virtual group. 22904 * b) Update slice virtual priority. 22905 */ 22906 fsm_ptr->rv = _field_group_vmap_add(unit, fsm_ptr->stage_fc, fg); 22907 } else { 22908 /* Slice sharing find the slice in VMAP 22909 * and update the corresponding VMAP group */ 22910 fsm_ptr->rv = _field_group_slice_sharing_virtual_map_group(unit, fsm_ptr->stage_fc, fg); 22911 } 22912 } 22913 22914 if (BCM_SUCCESS(fsm_ptr->rv)) { 22915 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_UDF_UPDATE; 22916 } else { 22917 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 22918 } 22919 return _bcm_field_group_add(unit, fsm_ptr); 22920 } 22921 22922 /* 22923 * Function: 22924 * _field_group_add_hw_qual_list_get 22925 * Purpose: 22926 * Get qualifiers offset in hw. 22927 * Parameters: 22928 * unit - (IN) BCM device number. 22929 * fsm_ptr - (IN/OUT) State machine tracking structure. 22930 * Returns: 22931 * BCM_E_XXX 22932 */ 22933 STATIC int 22934 _field_group_add_hw_qual_list_get(int unit, _field_group_add_fsm_t *fsm_ptr) 22935 { 22936 /* Input parameters check. */ 22937 if (NULL == fsm_ptr) { 22938 return (BCM_E_PARAM); 22939 } 22940 22941 /* Set current state to be previous state. */ 22942 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 22943 22944 /* 22945 * Set the FPFx metadata (bit offset, width) for this HW 22946 * this fills the group's qualifier lists. 22947 */ 22948 fsm_ptr->rv = fsm_ptr->fc->functions.fp_qual_list_get(unit, 22949 fsm_ptr->stage_fc, 22950 fsm_ptr->fg); 22951 if (BCM_FAILURE(fsm_ptr->rv)) { 22952 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 22953 } else { 22954 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_ADJUST_VIRTUAL_MAP; 22955 } 22956 return _bcm_field_group_add(unit, fsm_ptr); 22957 } 22958 22959 /* 22960 * Function: 22961 * _field_udf_usecount_increment 22962 * 22963 * Purpose: 22964 * Increment the use counts for any UDFs used 22965 * 22966 * Parameters: 22967 * fc - unit's field control struct 22968 * fg - group's metadata struct 22969 * 22970 * Returns: 22971 * BCM_E_RESOURCE - Invalid UDF 22972 * BCM_E_NONE - Success 22973 */ 22974 STATIC int 22975 _field_udf_usecount_increment(_field_control_t *fc, _field_group_t *fg) 22976 { 22977 int idx; 22978 22979 for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) { 22980 /* coverity[ptr_arith] */ 22981 if (SHR_BITGET(fg->qset.udf_map, idx)) { 22982 fc->udf[idx].use_count++; 22983 } 22984 } 22985 return (BCM_E_NONE); 22986 } 22987 22988 /* 22989 * Function: 22990 * _field_group_add_udf_update 22991 * Purpose: 22992 * Update udf usage count. 22993 * Parameters: 22994 * unit - (IN) BCM device number. 22995 * fsm_ptr - (IN/OUT) State machine tracking structure. 22996 * Returns: 22997 * BCM_E_XXX 22998 */ 22999 STATIC int 23000 _field_group_add_udf_update(int unit, _field_group_add_fsm_t *fsm_ptr) 23001 { 23002 /* Input parameters check. */ 23003 if (NULL == fsm_ptr) { 23004 return (BCM_E_PARAM); 23005 } 23006 23007 /* Set current state to be previous state. */ 23008 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 23009 23010 /* Increment the use counts for any UDFs used */ 23011 fsm_ptr->rv = _field_udf_usecount_increment(fsm_ptr->fc, fsm_ptr->fg); 23012 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 23013 23014 return _bcm_field_group_add(unit, fsm_ptr); 23015 } 23016 23017 /* 23018 * Function: _field_group_virtual_group_validate 23019 * 23020 * Purpose: 23021 * Verify that there is no virtual group conflict between 23022 * group & other groups in the slice. 23023 * 23024 * Parameters: 23025 * unit - (IN)BCM device number. 23026 * stage_fc - (IN)FP stage control info. 23027 * fg - (IN)FP group 23028 * slice_numb - (IN)Slice number where mode is to be programmed. 23029 * 23030 * Returns: 23031 * BCM_E_NONE - Success 23032 * BCM_E_CONFIG - Slice is already programmed with conflicting priority. 23033 * BCM_E_XXX - Any other error. 23034 */ 23035 STATIC int 23036 _field_group_virtual_group_validate(int unit, _field_stage_t *stage_fc, 23037 _field_group_t *fg, int slice_numb) 23038 { 23039 _field_slice_t *fs; /* First group slice. */ 23040 _field_control_t *fc; 23041 _field_group_t *fg_temp = NULL; 23042 23043 /* Input parameters check. */ 23044 if ((NULL == stage_fc) || (NULL == fg)) { 23045 return (BCM_E_PARAM); 23046 } 23047 23048 if (slice_numb > stage_fc->tcam_slices) { 23049 return (BCM_E_PARAM); 23050 } 23051 23052 LOG_DEBUG(BSL_LS_BCM_FP, 23053 (BSL_META_U(unit, 23054 "FP(unit %d) vverb: _field_group_virtual_group_validate" 23055 "(slice_numb=%d, Virtual group=%d)\n"), unit, slice_numb, 23056 fg->action_res_id)); 23057 23058 /* 23059 * Since we already checked ports & mode it is enough to check 23060 * virtual priority for first slice only. 23061 */ 23062 fs = stage_fc->slices[fg->instance] + slice_numb; 23063 if (BCM_PBMP_IS_NULL(fs->pbmp)) { 23064 /* Slice is not used -> no conflicts. */ 23065 return (BCM_E_NONE); 23066 } 23067 23068 23069 /* 23070 * If two groups sharing a slice they should have the same action resolution id. 23071 */ 23072 23073 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 23074 23075 for (fg_temp = fc->groups; fg_temp != NULL; fg_temp = fg_temp->next) { 23076 if (fg_temp->stage_id != stage_fc->stage_id) { 23077 continue; 23078 } 23079 23080 if (fg_temp == fg) { 23081 continue; 23082 } 23083 23084 /* If slice doesn't belong to group continue */ 23085 if (fg_temp->slices[0].slice_number != fs->slice_number) { 23086 continue; 23087 } 23088 23089 if (fg->action_res_id == fg_temp->action_res_id){ 23090 return (BCM_E_NONE); 23091 } 23092 } 23093 23094 return (BCM_E_CONFIG); 23095 } 23096 23097 /* 23098 * Function: _field_group_virtual_priority_validate 23099 * 23100 * Purpose: 23101 * Verify that ther is no virtual priority conflict between 23102 * group & other groups in the slice. 23103 * 23104 * Parameters: 23105 * unit - (IN)BCM device number. 23106 * stage_fc - (IN)FP stage control info. 23107 * fg - (IN)FP group 23108 * slice_numb - (IN)Slice number where mode is to be programmed. 23109 * 23110 * Returns: 23111 * BCM_E_NONE - Success 23112 * BCM_E_CONFIG - Slice is already programmed with conflicting priority. 23113 * BCM_E_XXX - Any other error. 23114 */ 23115 STATIC int 23116 _field_group_virtual_priority_validate(int unit, _field_stage_t *stage_fc, 23117 _field_group_t *fg, int slice_numb) 23118 { 23119 _field_slice_t *fs; /* First group slice. */ 23120 int idx; /* Virtual map iteration index.*/ 23121 _field_virtual_map_t *vmap; /* Virtual map for stage. */ 23122 23123 /* Input parameters check. */ 23124 if ((NULL == stage_fc) || (NULL == fg)) { 23125 return (BCM_E_PARAM); 23126 } 23127 23128 if (slice_numb > stage_fc->tcam_slices) { 23129 return (BCM_E_PARAM); 23130 } 23131 23132 LOG_DEBUG(BSL_LS_BCM_FP, 23133 (BSL_META_U(unit, 23134 "FP(unit %d) vverb: _field_group_virtual_priority_validate" 23135 "(slice_numb=%d, priority=%d)\n"), unit, slice_numb, 23136 fg->priority)); 23137 23138 /* If group doesn't care about priority - done. */ 23139 if (BCM_FIELD_GROUP_PRIO_ANY == fg->priority) { 23140 return (BCM_E_NONE); 23141 } 23142 23143 /* 23144 * Since we already checked ports & mode it is enough to check 23145 * virtual priority for first slice only. 23146 */ 23147 fs = stage_fc->slices[fg->instance] + slice_numb; 23148 if (BCM_PBMP_IS_NULL(fs->pbmp)) { 23149 /* Slice is not used -> no conflicts. */ 23150 return (BCM_E_NONE); 23151 } 23152 23153 /* 23154 * If two groups sharing a slice they should have the same priority. 23155 */ 23156 vmap = stage_fc->vmap[fg->instance][_FP_VMAP_DEFAULT]; 23157 for (idx = 0; idx < stage_fc->tcam_slices; idx++) { 23158 if (vmap[idx].valid == FALSE) { 23159 continue; 23160 } else { 23161 if (fs->slice_number != vmap[idx].vmap_key) { 23162 continue; 23163 } 23164 if (fg->priority != vmap[idx].priority) { 23165 return (BCM_E_CONFIG); 23166 } 23167 } 23168 } 23169 return (BCM_E_NONE); 23170 } 23171 23172 /* 23173 * Function: _field_group_ports_validate 23174 * 23175 * Purpose: 23176 * Test requested group ports against available ports in the slice or 23177 * slices needed by the group. 23178 * 23179 * Test to see if mode is appropriate for device. Basically this means 23180 * checking for double and triple wide requests on devices that do not 23181 * support it. There are additional range checks, but those should almost 23182 * never fail. 23183 * 23184 * Parameters: 23185 * unit - (IN)BCM device number 23186 * stage_fc - (IN)Stage FP control info. 23187 * instance - (IN)Pipe Instance the group belongs to. 23188 * slice_base - (IN)Primary slice number. 23189 * flags - (IN)Flags with group mode (single, double, triple or Auto-wide). 23190 * pbmp - (IN)Bit map of ports that group is requesting. 23191 * 23192 * Returns: 23193 * BCM_E_CONFIG - Requested at least one port unavailable on one or more 23194 * slices. 23195 * BCM_E_NONE - Success 23196 */ 23197 STATIC int 23198 _field_group_ports_validate(int unit, const _field_stage_t *stage_fc, 23199 int instance, const int slice_base, 23200 const uint8 flags, const bcm_pbmp_t pbmp) 23201 { 23202 _field_slice_t *fs; /* Field slice structure. */ 23203 bcm_pbmp_t pbmp_temp; 23204 bcm_pbmp_t group_pbmp; 23205 23206 LOG_DEBUG(BSL_LS_BCM_FP, 23207 (BSL_META_U(unit, 23208 "FP(unit %d) vverb: _field_group_ports_validate(slice_base=%d," 23209 " flags=%d)\n"), unit, slice_base, flags)); 23210 23211 if (NULL == stage_fc) { 23212 return (BCM_E_PARAM); 23213 } 23214 23215 BCM_PBMP_ASSIGN(group_pbmp, pbmp); 23216 #if defined(BCM_TOMAHAWK_SUPPORT) 23217 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 23218 ((_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) || 23219 (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id))) { 23220 23221 /* Read device port configuration. */ 23222 BCM_PBMP_CLEAR(group_pbmp); 23223 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &group_pbmp)); 23224 } 23225 #endif /* BCM_TOMAHAWK_SUPPORT */ 23226 23227 if (flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 23228 if (slice_base % 4 != 0) { 23229 LOG_DEBUG(BSL_LS_BCM_FP, 23230 (BSL_META_U(unit, 23231 "FP(unit %d) Error: bad slice=%d for triple-mode.\n"), 23232 unit, 23233 slice_base)); 23234 return (BCM_E_PARAM); 23235 } 23236 if ((slice_base + 2) > stage_fc->tcam_slices) { 23237 return (BCM_E_CONFIG); 23238 } 23239 fs = stage_fc->slices[instance] + slice_base + 2; 23240 BCM_PBMP_ASSIGN(pbmp_temp, fs->pbmp); 23241 BCM_PBMP_AND(pbmp_temp, group_pbmp); 23242 if (BCM_PBMP_NOT_NULL(pbmp_temp)) { 23243 LOG_DEBUG(BSL_LS_BCM_FP, 23244 (BSL_META_U(unit, 23245 "FP(unit %d) vverb: slice=%d in-use.\n"), 23246 unit, slice_base)); 23247 return (BCM_E_CONFIG); 23248 } 23249 } 23250 23251 if ((flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 23252 (flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 23253 23254 if (slice_base % 2 != 0) { 23255 LOG_DEBUG(BSL_LS_BCM_FP, 23256 (BSL_META_U(unit, 23257 "FP(unit %d) Error: bad slice=%d for double-mode.\n"), 23258 unit, 23259 slice_base)); 23260 return (BCM_E_PARAM); 23261 } 23262 23263 if ((slice_base + 1) > stage_fc->tcam_slices) { 23264 return (BCM_E_CONFIG); 23265 } 23266 fs = stage_fc->slices[instance] + slice_base + 1; 23267 /* If group is intraslice verify that slice is intraslice capable. */ 23268 if (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 23269 if (0 == (fs->slice_flags & _BCM_FIELD_SLICE_INTRASLICE_CAPABLE)) { 23270 return (BCM_E_CONFIG); 23271 } 23272 } 23273 23274 BCM_PBMP_ASSIGN(pbmp_temp, fs->pbmp); 23275 BCM_PBMP_AND(pbmp_temp, group_pbmp); 23276 if (BCM_PBMP_NOT_NULL(pbmp_temp)) { 23277 LOG_DEBUG(BSL_LS_BCM_FP, 23278 (BSL_META_U(unit, 23279 "FP(unit %d) vverb: slice=%d in-use.\n"), 23280 unit, slice_base)); 23281 return (BCM_E_CONFIG); 23282 } 23283 } 23284 23285 fs = stage_fc->slices[instance] + slice_base; 23286 /* If group is intraslice verify that slice is intraslice capable. */ 23287 if (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 23288 if (0 == (fs->slice_flags & _BCM_FIELD_SLICE_INTRASLICE_CAPABLE)) { 23289 return (BCM_E_CONFIG); 23290 } 23291 } 23292 23293 BCM_PBMP_ASSIGN(pbmp_temp, fs->pbmp); 23294 BCM_PBMP_AND(pbmp_temp, group_pbmp); 23295 if (BCM_PBMP_NOT_NULL(pbmp_temp)) { 23296 LOG_DEBUG(BSL_LS_BCM_FP, 23297 (BSL_META_U(unit, 23298 "FP(unit %d) vverb: slice=%d in-use.\n"), 23299 unit, slice_base)); 23300 return (BCM_E_CONFIG); 23301 } 23302 23303 return (BCM_E_NONE); 23304 } 23305 23306 /* 23307 * Function: _field_group_slice_mode_validate 23308 * 23309 * Purpose: 23310 * Check if group can use the slice e.g. 23311 * per slice configuration for other installed groups 23312 * doesn't create a conflict. 23313 * Parameters: 23314 * unit - (IN)BCM device number. 23315 * slice_num - (IN)Group slice number. 23316 * fs - (IN)Slice control structure. 23317 * fg - (IN)Field group structure. 23318 * 23319 * Returns: 23320 * BCM_E_NONE - No conflicts 23321 * BCM_E_CONFIG - Slice is already programmed with conflicting mode. 23322 * BCM_E_XXX - other errors. 23323 */ 23324 STATIC int 23325 _field_group_slice_mode_validate(int unit, int slice_num, 23326 _field_slice_t *fs, _field_group_t *fg) 23327 { 23328 uint8 slice_number; /* Slices iterator. */ 23329 int idx; /* Slice iteration index. */ 23330 int parts_count = 0; /* Number of entry parts. */ 23331 int rv; /* Operation return status.*/ 23332 23333 /* Input parameters check. */ 23334 if ((NULL == fs) || (NULL == fg)) { 23335 return (BCM_E_PARAM); 23336 } 23337 23338 if (BCM_PBMP_IS_NULL(fs->pbmp)) { 23339 /* Slice is not used -> no conflicts. */ 23340 return (BCM_E_NONE); 23341 } 23342 23343 /* Check for single/double/triple wide mode match. */ 23344 if ((fg->flags & _FP_GROUP_STATUS_MASK) != 23345 (fs->group_flags & _FP_GROUP_STATUS_MASK)) { 23346 return (BCM_E_CONFIG); 23347 } 23348 23349 /* Get number of entry parts. */ 23350 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 23351 fg->flags, &parts_count); 23352 BCM_IF_ERROR_RETURN(rv); 23353 23354 for (idx = 0; idx < parts_count; idx++) { 23355 /* Get slice id for entry part */ 23356 rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg, 23357 &slice_number); 23358 BCM_IF_ERROR_RETURN(rv); 23359 23360 /* Get slice pointer. */ 23361 fs += slice_number; 23362 23363 /* Source class selection comparison. */ 23364 if ((_FP_SELCODE_DONT_CARE != fs->src_class_sel) && 23365 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].src_class_sel) && 23366 (fs->src_class_sel != fg->sel_codes[idx].src_class_sel)) { 23367 return (BCM_E_CONFIG); 23368 } 23369 23370 /* Destination class selection comparison. */ 23371 if ((_FP_SELCODE_DONT_CARE != fs->dst_class_sel) && 23372 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].dst_class_sel) && 23373 (fs->dst_class_sel != fg->sel_codes[idx].dst_class_sel)) { 23374 return (BCM_E_CONFIG); 23375 } 23376 /* Interface class selection comparison. */ 23377 if ((_FP_SELCODE_DONT_CARE != fs->intf_class_sel) && 23378 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].intf_class_sel) && 23379 (fs->intf_class_sel != fg->sel_codes[idx].intf_class_sel)) { 23380 return (BCM_E_CONFIG); 23381 } 23382 /* Loopback type/Tunnel type selection comparison. */ 23383 if ((_FP_SELCODE_DONT_CARE != fs->loopback_type_sel) && 23384 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].loopback_type_sel) && 23385 (fs->loopback_type_sel != fg->sel_codes[idx].loopback_type_sel)) { 23386 return (BCM_E_CONFIG); 23387 } 23388 /* Ingress entity selection comparison. */ 23389 if ((_FP_SELCODE_DONT_CARE != fs->ingress_entity_sel) && 23390 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].ingress_entity_sel) && 23391 (fs->ingress_entity_sel != fg->sel_codes[idx].ingress_entity_sel)) { 23392 return (BCM_E_CONFIG); 23393 } 23394 /* Src entity selection comparison. */ 23395 if ((_FP_SELCODE_DONT_CARE != fs->src_entity_sel) && 23396 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].src_entity_sel) && 23397 (fs->src_entity_sel != fg->sel_codes[idx].src_entity_sel)) { 23398 return (BCM_E_CONFIG); 23399 } 23400 /* Dstination forwarding entity selection comparison. */ 23401 if ((_FP_SELCODE_DONT_CARE != fs->dst_fwd_entity_sel) && 23402 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].dst_fwd_entity_sel) && 23403 (fs->dst_fwd_entity_sel != fg->sel_codes[idx].dst_fwd_entity_sel)) { 23404 return (BCM_E_CONFIG); 23405 } 23406 23407 /* Dstination forwarding entity selection comparison. */ 23408 if ((_FP_SELCODE_DONT_CARE != fs->fwd_field_sel) && 23409 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].fwd_field_sel) && 23410 (fs->fwd_field_sel != fg->sel_codes[idx].fwd_field_sel)) { 23411 return (BCM_E_CONFIG); 23412 } 23413 23414 if ((_FP_SELCODE_DONT_CARE != fs->ttl_class_sel) && 23415 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].ttl_class_sel) && 23416 (fs->ttl_class_sel != fg->sel_codes[idx].ttl_class_sel)) { 23417 return (BCM_E_CONFIG); 23418 } 23419 23420 if ((_FP_SELCODE_DONT_CARE != fs->tos_class_sel) && 23421 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].tos_class_sel) && 23422 (fs->tos_class_sel != fg->sel_codes[idx].tos_class_sel)) { 23423 return (BCM_E_CONFIG); 23424 } 23425 23426 if ((_FP_SELCODE_DONT_CARE != fs->tcp_class_sel) && 23427 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].tcp_class_sel) && 23428 (fs->tcp_class_sel != fg->sel_codes[idx].tcp_class_sel)) { 23429 return (BCM_E_CONFIG); 23430 } 23431 23432 if ((_FP_SELCODE_DONT_CARE != fs->aux_tag_1_sel) && 23433 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].aux_tag_1_sel) && 23434 (fs->aux_tag_1_sel != fg->sel_codes[idx].aux_tag_1_sel)) { 23435 return (BCM_E_CONFIG); 23436 } 23437 23438 if ((_FP_SELCODE_DONT_CARE != fs->aux_tag_2_sel) && 23439 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].aux_tag_2_sel) && 23440 (fs->aux_tag_2_sel != fg->sel_codes[idx].aux_tag_2_sel)) { 23441 return (BCM_E_CONFIG); 23442 } 23443 23444 if ((_FP_SELCODE_DONT_CARE != fs->oam_overlay_sel) && 23445 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].oam_overlay_sel) && 23446 (fs->oam_overlay_sel != fg->sel_codes[idx].oam_overlay_sel)) { 23447 return (BCM_E_CONFIG); 23448 } 23449 if (fs->egr_class_f1_sel != _FP_SELCODE_DONT_CARE 23450 && fg->sel_codes[idx].egr_class_f1_sel != _FP_SELCODE_DONT_CARE 23451 && fs->egr_class_f1_sel != fg->sel_codes[idx].egr_class_f1_sel 23452 ) { 23453 return (BCM_E_CONFIG); 23454 } 23455 23456 if (fs->egr_class_f2_sel != _FP_SELCODE_DONT_CARE 23457 && fg->sel_codes[idx].egr_class_f2_sel != _FP_SELCODE_DONT_CARE 23458 && fs->egr_class_f2_sel != fg->sel_codes[idx].egr_class_f2_sel 23459 ) { 23460 return (BCM_E_CONFIG); 23461 } 23462 23463 if (fs->egr_class_f3_sel != _FP_SELCODE_DONT_CARE 23464 && fg->sel_codes[idx].egr_class_f3_sel != _FP_SELCODE_DONT_CARE 23465 && fs->egr_class_f3_sel != fg->sel_codes[idx].egr_class_f3_sel 23466 ) { 23467 return (BCM_E_CONFIG); 23468 } 23469 23470 if (fs->egr_class_f4_sel != _FP_SELCODE_DONT_CARE 23471 && fg->sel_codes[idx].egr_class_f4_sel != _FP_SELCODE_DONT_CARE 23472 && fs->egr_class_f4_sel != fg->sel_codes[idx].egr_class_f4_sel 23473 ) { 23474 return (BCM_E_CONFIG); 23475 } 23476 23477 if (fs->src_dest_class_f1_sel != _FP_SELCODE_DONT_CARE 23478 && fg->sel_codes[idx].src_dest_class_f1_sel != _FP_SELCODE_DONT_CARE 23479 && fs->src_dest_class_f1_sel != fg->sel_codes[idx].src_dest_class_f1_sel 23480 ) { 23481 return (BCM_E_CONFIG); 23482 } 23483 23484 if (fs->src_dest_class_f3_sel != _FP_SELCODE_DONT_CARE 23485 && fg->sel_codes[idx].src_dest_class_f3_sel != _FP_SELCODE_DONT_CARE 23486 && fs->src_dest_class_f3_sel != fg->sel_codes[idx].src_dest_class_f3_sel 23487 ) { 23488 return (BCM_E_CONFIG); 23489 } 23490 23491 if (fs->egr_key4_dvp_sel != _FP_SELCODE_DONT_CARE 23492 && fg->sel_codes[idx].egr_key4_dvp_sel != _FP_SELCODE_DONT_CARE 23493 && fs->egr_key4_dvp_sel != fg->sel_codes[idx].egr_key4_dvp_sel 23494 ) { 23495 return (BCM_E_CONFIG); 23496 } 23497 23498 if (fs->egr_key4_mdl_sel != _FP_SELCODE_DONT_CARE 23499 && fg->sel_codes[idx].egr_key4_mdl_sel != _FP_SELCODE_DONT_CARE 23500 && fs->egr_key4_mdl_sel != fg->sel_codes[idx].egr_key4_mdl_sel 23501 ) { 23502 return (BCM_E_CONFIG); 23503 } 23504 23505 if (fs->egr_oam_overlay_sel != _FP_SELCODE_DONT_CARE 23506 && fg->sel_codes[idx].egr_oam_overlay_sel != _FP_SELCODE_DONT_CARE 23507 && fs->egr_oam_overlay_sel != fg->sel_codes[idx].egr_oam_overlay_sel 23508 ) { 23509 return (BCM_E_CONFIG); 23510 } 23511 23512 if (fs->oam_intf_class_sel != _FP_SELCODE_DONT_CARE 23513 && fg->sel_codes[idx].oam_intf_class_sel != _FP_SELCODE_DONT_CARE 23514 && fs->oam_intf_class_sel != fg->sel_codes[idx].oam_intf_class_sel 23515 ) { 23516 return (BCM_E_CONFIG); 23517 } 23518 23519 if (fs->egr_dest_port_f1_sel != _FP_SELCODE_DONT_CARE 23520 && fg->sel_codes[idx].egr_dest_port_f1_sel != _FP_SELCODE_DONT_CARE 23521 && fs->egr_dest_port_f1_sel != fg->sel_codes[idx].egr_dest_port_f1_sel 23522 ) { 23523 return (BCM_E_CONFIG); 23524 } 23525 23526 if (fs->egr_dest_port_f5_sel != _FP_SELCODE_DONT_CARE 23527 && fg->sel_codes[idx].egr_dest_port_f5_sel != _FP_SELCODE_DONT_CARE 23528 && fs->egr_dest_port_f5_sel != fg->sel_codes[idx].egr_dest_port_f5_sel 23529 ) { 23530 return (BCM_E_CONFIG); 23531 } 23532 23533 /* Set intraslice double wide key selection. */ 23534 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 23535 if (((idx == _FP_INTRA_SLICE_PART_1) || 23536 (idx == _FP_INTRA_SLICE_PART_3)) && 23537 ((_FP_SELCODE_DONT_CARE != fs->doublewide_key_select) && 23538 (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].fpf2) && 23539 (fs->doublewide_key_select != fg->sel_codes[idx].fpf2))) { 23540 return (BCM_E_CONFIG); 23541 } 23542 } 23543 } 23544 return (BCM_E_NONE); 23545 } 23546 23547 /* 23548 * Function: _field_group_mode_validate 23549 * 23550 * Purpose: 23551 * Check if set of slices are usable for a new group. 23552 * 23553 * Parameters: 23554 * unit - (IN)BCM device number. 23555 * stage_fc - (IN)FP stage control info. 23556 * fg - (IN)FP group 23557 * slice_numb - (IN)Slice number where mode is to be programmed. 23558 * 23559 * Returns: 23560 * BCM_E_NONE - Success 23561 * BCM_E_CONFIG - Slice is already programmed with conflicting mode. 23562 * BCM_E_XXX - Any other error. 23563 */ 23564 STATIC int 23565 _field_group_mode_validate(int unit, _field_stage_t *stage_fc, 23566 _field_group_t *fg, int slice_numb) 23567 { 23568 _field_slice_t *fs; 23569 23570 /* Input parameters check. */ 23571 if ((NULL == stage_fc) || (NULL == fg)) { 23572 return (BCM_E_PARAM); 23573 } 23574 23575 if (slice_numb > stage_fc->tcam_slices) { 23576 return (BCM_E_PARAM); 23577 } 23578 23579 LOG_DEBUG(BSL_LS_BCM_FP, 23580 (BSL_META_U(unit, 23581 "FP(unit %d) vverb: _field_group_mode_validate(slice_numb=%d, " 23582 "flags=%d)\n"), unit, slice_numb, fg->flags)); 23583 23584 /* Confirm that mode will work on specific slice(s). If another group is 23585 * already defined on slice(s), then the requested mode has to match 23586 * the hardware mode. */ 23587 fs = stage_fc->slices[fg->instance] + slice_numb; 23588 23589 return 23590 _field_group_slice_mode_validate(unit, _FP_INTER_SLICE_PART_2, fs, fg); 23591 } 23592 23593 /* 23594 * Function: 23595 * _field_group_add_slice_validate 23596 * Purpose: 23597 * Validate a candidate slice if it fits for a group. 23598 * Parameters: 23599 * unit - (IN BCM device number. 23600 * stage_fc - (IN) State machine tracking structure. 23601 * fg - (IN) Field group structure. 23602 * slice_id - (IN) Candidate slice id. 23603 * Returns: 23604 * BCM_E_XXX 23605 */ 23606 STATIC int 23607 _field_group_add_slice_validate(int unit, _field_stage_t *stage_fc, 23608 _field_group_t *fg, int slice_id) 23609 { 23610 int rv; /* Operation return status. */ 23611 int virtual_priority = FALSE;/* Virtual priority support flag.*/ 23612 23613 /* Input parameters check. */ 23614 if ((NULL == stage_fc) || (NULL == fg)) { 23615 return (BCM_E_PARAM); 23616 } 23617 23618 _field_virtual_priority_support(unit, stage_fc, &virtual_priority); 23619 23620 /* 23621 * If this slice belongs to an auto-expanded group, AND 23622 * is not the first one of that group, 23623 * cannot use it 23624 */ 23625 if (stage_fc->slices[fg->instance][slice_id].prev != NULL) { 23626 return (BCM_E_CONFIG); 23627 } 23628 23629 /* 23630 * Skip the slice if group is intraslice and 23631 * slice is not intraslice capable. 23632 */ 23633 if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 23634 (0 == (stage_fc->slices[fg->instance][slice_id].slice_flags & 23635 _BCM_FIELD_SLICE_INTRASLICE_CAPABLE))) { 23636 return (BCM_E_CONFIG); 23637 } 23638 23639 /* 23640 * Skip the slice if group slice size is small and 23641 * slice is not of smaller size. 23642 */ 23643 if ((fg->flags & _FP_GROUP_SELECT_SMALL_SLICE) && 23644 (0 == (stage_fc->slices[fg->instance][slice_id].slice_flags & 23645 _BCM_FIELD_SLICE_SIZE_SMALL))) { 23646 return (BCM_E_CONFIG); 23647 } 23648 23649 /* 23650 * Skip the slice if group slice size is large and 23651 * slice is not of large size. 23652 */ 23653 if ((fg->flags & _FP_GROUP_SELECT_LARGE_SLICE) && 23654 (0 == (stage_fc->slices[fg->instance][slice_id].slice_flags & 23655 _BCM_FIELD_SLICE_SIZE_LARGE))) { 23656 return (BCM_E_CONFIG); 23657 } 23658 23659 /* 23660 * Make sure there is no conflict between groups ports 23661 * and other groups in the slice. 23662 */ 23663 rv = _field_group_ports_validate(unit, stage_fc, fg->instance, slice_id, 23664 fg->flags, fg->pbmp); 23665 BCM_IF_ERROR_RETURN(rv); 23666 23667 /* 23668 * Make sure there is no conflict between 23669 * group & other groups mode. (single/double/triple) 23670 * do not coexist. 23671 */ 23672 rv = _field_group_mode_validate(unit, stage_fc, fg, slice_id); 23673 BCM_IF_ERROR_RETURN(rv); 23674 23675 /* 23676 * Make sure there is no virtual priority conflict between 23677 * group & other groups in the slice. 23678 */ 23679 if (virtual_priority) { 23680 if (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION) { 23681 fg->flags |= _FP_GROUP_SELECT_AUTO_EXPANSION; 23682 } 23683 rv = _field_group_virtual_priority_validate(unit, stage_fc, 23684 fg, slice_id); 23685 BCM_IF_ERROR_RETURN(rv); 23686 rv = _field_group_virtual_group_validate(unit, stage_fc, 23687 fg, slice_id); 23688 BCM_IF_ERROR_RETURN(rv); 23689 } 23690 23691 return (BCM_E_NONE); 23692 } 23693 23694 /* 23695 * Function: 23696 * _field_virtual_priority_support 23697 * Purpose: 23698 * Check if device supports virtual priority. 23699 * Parameters: 23700 * unit - (IN) BCM device number. 23701 * stage_fc - (IN) Field stage control. 23702 * support - (OUT) TRUE supports virtual priority. 23703 * FALSE otherwise. 23704 * Returns: 23705 * BCM_E_XXX 23706 */ 23707 int 23708 _field_virtual_priority_support(int unit, _field_stage_t *stage_fc, int *support) 23709 { 23710 23711 /* Input parameters check. */ 23712 if ((NULL == stage_fc) || (NULL == support)){ 23713 return (BCM_E_PARAM); 23714 } 23715 23716 if (0 == soc_feature(unit, soc_feature_field_virtual_slice_group)) { 23717 *support = FALSE; 23718 } else if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 23719 *support = TRUE; 23720 } else if (SOC_IS_FIREBOLT2(unit)) { 23721 *support = FALSE; 23722 } else { 23723 *support = TRUE; 23724 } 23725 return (BCM_E_NONE); 23726 } 23727 23728 /* 23729 * Function: 23730 * _field_group_add_slice_allocate 23731 * Purpose: 23732 * Allocate slice for a new group. 23733 * Parameters: 23734 * unit - (IN) BCM device number. 23735 * fsm_ptr - (IN/OUT) State machine tracking structure. 23736 * Returns: 23737 * BCM_E_XXX 23738 */ 23739 STATIC int 23740 _field_group_add_slice_allocate(int unit, _field_group_add_fsm_t *fsm_ptr) 23741 { 23742 _field_group_t *fg; /* Field group pointer. */ 23743 _field_stage_t *stage_fc; /* Stage field control. */ 23744 int slice_id; /* Slices iterator. */ 23745 int virtual_priority = FALSE;/* Virtual priority support flag.*/ 23746 23747 /* Input parameters check. */ 23748 if (NULL == fsm_ptr) { 23749 return (BCM_E_PARAM); 23750 } 23751 23752 /* Group pointer initialization. */ 23753 fg = fsm_ptr->fg; 23754 stage_fc = fsm_ptr->stage_fc; 23755 slice_id = -1; 23756 23757 _field_virtual_priority_support(unit, stage_fc, &virtual_priority); 23758 23759 if ((_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id)) { 23760 /* External slices mapped 1-1 to selected keys.*/ 23761 fg->slices = stage_fc->slices[_FP_DEF_INST] + fg->sel_codes[0].extn; 23762 slice_id = fg->sel_codes[0].extn; 23763 } else if ((BCM_FIELD_GROUP_PRIO_ANY == fsm_ptr->priority) || (virtual_priority)) { 23764 /* If not specified, generate a priority. */ 23765 for (slice_id = 0; slice_id < stage_fc->tcam_slices; slice_id++) { 23766 fsm_ptr->rv = _field_group_add_slice_validate(unit, stage_fc, 23767 fg, slice_id); 23768 if(BCM_SUCCESS(fsm_ptr->rv)) { 23769 break; 23770 } 23771 } 23772 /* Check if allocation was successful. */ 23773 if (slice_id == stage_fc->tcam_slices) { 23774 fsm_ptr->rv = (BCM_E_RESOURCE); 23775 } 23776 } else { 23777 if ((fsm_ptr->priority < 0) || 23778 (fsm_ptr->stage_fc->tcam_slices <= fsm_ptr->priority)) { 23779 LOG_ERROR(BSL_LS_BCM_FP, 23780 (BSL_META_U(unit, 23781 "FP(unit %d) Error: pri=%d out-of-range.\n"), 23782 unit, fsm_ptr->priority)); 23783 fsm_ptr->rv = BCM_E_PARAM; 23784 } else { 23785 slice_id = fsm_ptr->priority; 23786 fsm_ptr->rv = _field_group_add_slice_validate(unit, stage_fc, 23787 fg, slice_id); 23788 } 23789 } 23790 23791 if (BCM_FAILURE(fsm_ptr->rv)) { 23792 /* Different select codes might help for 5682x devices. */ 23793 if ((soc_feature(unit, soc_feature_two_ingress_pipes)) && 23794 (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 23795 ((0 == (fsm_ptr->priority % 2)) || 23796 (BCM_FIELD_GROUP_PRIO_ANY == fsm_ptr->priority))) { 23797 fsm_ptr->rv = (BCM_E_NONE); 23798 fsm_ptr->flags &= ~_BCM_FP_GROUP_ADD_INTRA_SLICE; 23799 fg->flags &= ~_FP_GROUP_INTRASLICE_DOUBLEWIDE; 23800 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 23801 } else if (fsm_ptr->fsm_state_prev == 23802 _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN) { 23803 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 23804 } else if ((fsm_ptr->fsm_state_prev != 23805 _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS) && virtual_priority) { 23806 fsm_ptr->rv = (BCM_E_NONE); 23807 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS; 23808 } else { 23809 if ((fsm_ptr->fsm_state_prev == 23810 _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS) && virtual_priority && 23811 (fsm_ptr->rv == BCM_E_RESOURCE) && 23812 (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) && 23813 (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) && 23814 (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) 23815 ) { 23816 /* If there are atleast two free slices to create a 23817 * double wide group. But, if the slices are not in 23818 * consecutive locations, then state slice align is 23819 * set to align the slices 23820 */ 23821 fsm_ptr->rv = (BCM_E_NONE); 23822 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN; 23823 } else if ((fsm_ptr->fsm_state_prev == 23824 _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS) && 23825 (fsm_ptr->rv == BCM_E_RESOURCE) && 23826 (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) && 23827 (fg->stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 23828 /* For VFP stage, If there are atleast two free slices to 23829 * create a double wide group. But, if the slices are not in 23830 * consecutive locations, then state slice align is 23831 * set to align the slices 23832 */ 23833 fsm_ptr->rv = (BCM_E_NONE); 23834 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN; 23835 } else { 23836 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 23837 } 23838 } 23839 } else { 23840 fg->slices = stage_fc->slices[fg->instance] + slice_id; 23841 fsm_ptr->rv = _field_group_add_selcodes_install(unit, fsm_ptr); 23842 if (BCM_SUCCESS(fsm_ptr->rv)) { 23843 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_HW_QUAL_LIST_GET; 23844 } else { 23845 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 23846 } 23847 } 23848 /* Set current state to be previous state. */ 23849 fsm_ptr->fsm_state_prev = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE; 23850 return _bcm_field_group_add(unit, fsm_ptr); 23851 } 23852 23853 /* 23854 * Function: _field_group_compress 23855 * 23856 * Purpose: 23857 * Compress filed group entries, 23858 * in order to free slices used by the group. 23859 * Paramters: 23860 * unit - (IN) BCM device number 23861 * fg - (IN) Field group structure 23862 * stage_fc - (IN) Stage field control structure. 23863 * Returns: 23864 * BCM_E_XXX 23865 */ 23866 23867 int 23868 _field_group_compress(int unit, _field_group_t *fg, 23869 _field_stage_t *stage_fc) 23870 { 23871 _field_slice_t *fs; /* Field slice structure. */ 23872 _field_slice_t *efs; /* Slice that contains free slots.*/ 23873 int eidx; /* Empty slot index. */ 23874 int idx; /* Slice iteration index. */ 23875 int tmp_idx1; /* Slice entry index 1. */ 23876 int tmp_idx2; /* Slice entry index 2. */ 23877 int slice_sz; /* Number of entries in a slice. */ 23878 int rv; /* Operation return status. */ 23879 23880 /* Input parameters check. */ 23881 if (NULL == fg) { 23882 return (BCM_E_PARAM); 23883 } 23884 23885 /* Stage External doesn't require compression. */ 23886 if (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) { 23887 return (BCM_E_NONE); 23888 } 23889 23890 /* Get group slice pointer. */ 23891 fs = fg->slices; 23892 23893 efs = NULL; 23894 eidx = -1; 23895 while (NULL != fs) { 23896 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 23897 for (idx = 0; idx < slice_sz; idx ++) { 23898 /* Find an empty slot. */ 23899 if (NULL == fs->entries[idx]) { 23900 if (NULL == efs) { 23901 efs = fs; 23902 eidx = idx; 23903 } 23904 continue; 23905 } 23906 23907 if (NULL != efs) { 23908 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 23909 fg->instance, 23910 efs->slice_number, 23911 eidx, &tmp_idx1); 23912 BCM_IF_ERROR_RETURN(rv); 23913 23914 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 23915 fg->instance, 23916 fs->slice_number, 23917 idx, &tmp_idx2); 23918 BCM_IF_ERROR_RETURN(rv); 23919 23920 rv = _field_entry_move(unit, fs->entries[idx], 23921 (tmp_idx1 - tmp_idx2)); 23922 BCM_IF_ERROR_RETURN(rv); 23923 fs = efs; 23924 idx = eidx; 23925 efs = NULL; 23926 eidx = -1; 23927 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 23928 } 23929 } 23930 fs = fs->next; 23931 } 23932 rv = _field_group_free_unused_slices(unit, stage_fc, fg); 23933 return (rv); 23934 } 23935 23936 /* 23937 * Function: 23938 * _field_stage_groups_compress 23939 * Purpose: 23940 * Compress stage groups to free room for inserted group. 23941 * Parameters: 23942 * unit - (IN) BCM device number. 23943 * fc - (IN) Field control structure. 23944 * stage_fc - (IN) Stage field control. 23945 * Returns: 23946 * BCM_E_XXX 23947 */ 23948 STATIC int 23949 _field_stage_groups_compress(int unit, _field_control_t *fc, 23950 _field_stage_t *stage_fc) 23951 { 23952 _field_group_t *fg; /* Field group structure. */ 23953 int rv = BCM_E_NONE; /* Operation return Status */ 23954 23955 /* Input parameters check. */ 23956 if ((NULL == fc) || (NULL == stage_fc)) { 23957 return (BCM_E_PARAM); 23958 } 23959 23960 /* Compress expanded groups. */ 23961 for (fg = fc->groups; fg != NULL; fg = fg->next) { 23962 /* Skip other stages. */ 23963 if (fg->stage_id != stage_fc->stage_id) { 23964 continue; 23965 } 23966 23967 /* Skip new group. */ 23968 if (NULL == fg->slices) { 23969 continue; 23970 } 23971 23972 /* Ignore not expanded groups. */ 23973 if (NULL == fg->slices->next) { 23974 continue; 23975 } 23976 23977 /* Best effort to compress expanded virtual groups. */ 23978 rv = _field_group_compress(unit, fg, stage_fc); 23979 } 23980 return (rv); 23981 } 23982 23983 /* 23984 * Function: 23985 * _field_group_add_cam_compress 23986 * Purpose: 23987 * Compress other groups to free room for inserted group. 23988 * Parameters: 23989 * unit - (IN) BCM device number. 23990 * fsm_ptr - (IN/OUT) State machine tracking structure. 23991 * Returns: 23992 * BCM_E_XXX 23993 */ 23994 STATIC int 23995 _field_group_add_cam_compress(int unit, _field_group_add_fsm_t *fsm_ptr) 23996 { 23997 /* Set current state to be previous state. */ 23998 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 23999 24000 /* Compress expanded groups. */ 24001 fsm_ptr->rv = 24002 (_field_stage_groups_compress(unit, fsm_ptr->fc, fsm_ptr->stage_fc)); 24003 24004 if (BCM_SUCCESS(fsm_ptr->rv)) { 24005 /* Retry allocating slice/s for the new field group. */ 24006 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE; 24007 } else { 24008 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24009 } 24010 24011 24012 return _bcm_field_group_add(unit, fsm_ptr); 24013 } 24014 24015 /* 24016 * Function: 24017 * _bcm_field_group_selcode_initialize 24018 * Purpose: 24019 * Initialize selcodes of a group in a slice. 24020 * Parameters: 24021 * unit - (IN) BCM device number. 24022 * fg - (IN) Group in the slice. 24023 * fs - (IN) Field slice. 24024 * part_index- (IN) part index of group belonging to slice 24025 * Returns: 24026 * BCM_E_XXX 24027 */ 24028 int _bcm_field_group_selcode_initialize(int unit, 24029 _field_group_t *fg, _field_slice_t *fs, 24030 int part_index) { 24031 if (fg == NULL || fs == NULL) { 24032 return BCM_E_PARAM; 24033 } 24034 /* Set source class selection. */ 24035 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].src_class_sel) { 24036 fs->src_class_sel = fg->sel_codes[part_index].src_class_sel; 24037 } 24038 /* Set destination class selection. */ 24039 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].dst_class_sel) { 24040 fs->dst_class_sel = fg->sel_codes[part_index].dst_class_sel; 24041 } 24042 /* Set interface class selection. */ 24043 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].intf_class_sel) { 24044 fs->intf_class_sel = fg->sel_codes[part_index].intf_class_sel; 24045 } 24046 /* Set loopback type/tunnel type selection. */ 24047 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].loopback_type_sel) { 24048 fs->loopback_type_sel = fg->sel_codes[part_index].loopback_type_sel; 24049 } 24050 /* Set ingress entity type selection. */ 24051 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].ingress_entity_sel) { 24052 fs->ingress_entity_sel = fg->sel_codes[part_index].ingress_entity_sel; 24053 } 24054 /* Set src entity type selection. */ 24055 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].src_entity_sel) { 24056 fs->src_entity_sel = fg->sel_codes[part_index].src_entity_sel; 24057 } 24058 /* Set destination forwarding entity type selection. */ 24059 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].dst_fwd_entity_sel) { 24060 fs->dst_fwd_entity_sel = fg->sel_codes[part_index].dst_fwd_entity_sel; 24061 } 24062 24063 /* Set destination forwarding field selection. */ 24064 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].fwd_field_sel) { 24065 fs->fwd_field_sel = fg->sel_codes[part_index].fwd_field_sel; 24066 } 24067 24068 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].ttl_class_sel) { 24069 fs->ttl_class_sel = fg->sel_codes[part_index].ttl_class_sel; 24070 } 24071 24072 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].tos_class_sel) { 24073 fs->tos_class_sel = fg->sel_codes[part_index].tos_class_sel; 24074 } 24075 24076 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].tcp_class_sel) { 24077 fs->tcp_class_sel = fg->sel_codes[part_index].tcp_class_sel; 24078 } 24079 24080 /* Set intraslice double wide key selection. */ 24081 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 24082 if ((_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].fpf2) && 24083 ((part_index == _FP_INTRA_SLICE_PART_1) || 24084 (part_index == _FP_INTRA_SLICE_PART_3))) { 24085 fs->doublewide_key_select = fg->sel_codes[part_index].fpf2; 24086 } 24087 } 24088 return BCM_E_NONE; 24089 } 24090 24091 /* 24092 * Function: 24093 * _bcm_field_slice_group_get_next 24094 * Purpose: 24095 * Retrieve the next valid group pointer associated with the given slice. 24096 * Parameters: 24097 * unit - (IN BCM device number. 24098 * instance - (IN) Pipe to which group belongs to. 24099 * stage_id - (IN) Stage (IFP/VFP/EFP) to which group belongs to. 24100 * slice_id - (IN) Field slice id. 24101 * curr_group - (IN) Reference to current group index associated to slice. 24102 * next_group - (OUT) Reference to next available group index associated to 24103 * the given slice. 24104 * Returns: 24105 * BCM_E_XXX 24106 * Note: 24107 * "*curr_group == NULL" to retrieve the first group associated with the 24108 * given slice. 24109 */ 24110 int 24111 _bcm_field_slice_group_get_next(int unit, 24112 int instance, 24113 _field_stage_id_t stage_id, 24114 int slice_id, 24115 _field_group_t **curr_group, 24116 _field_group_t **next_group) 24117 { 24118 _field_group_t *fg = NULL; 24119 _field_slice_t *fs = NULL; 24120 24121 if (curr_group == NULL || next_group == NULL) { 24122 return BCM_E_PARAM; 24123 } 24124 24125 if (*curr_group == NULL) { 24126 _field_control_t *fc; /* Field Control Structure */ 24127 24128 /* Get device Field control structure. */ 24129 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 24130 fg = fc->groups; 24131 } else { 24132 fg = (*curr_group)->next; 24133 } 24134 24135 *next_group = NULL; 24136 for (; fg != NULL; fg = fg->next) { 24137 if ((instance != fg->instance) || (stage_id != fg->stage_id)) { 24138 continue; 24139 } 24140 24141 for (fs = fg->slices; fs != NULL; fs = fs->next) { 24142 if (fs->slice_number == slice_id) { 24143 *next_group = fg; 24144 return BCM_E_NONE; 24145 } 24146 } 24147 } 24148 return BCM_E_NOT_FOUND; 24149 } 24150 24151 /* update the primary slice pointer of all the groups using the 24152 * given slice 24153 */ 24154 int 24155 _bcm_field_group_primary_slice_update(int unit, 24156 int instance, 24157 _field_stage_id_t stage_id, 24158 int slice_id, 24159 _field_slice_t *fs_primary 24160 ) 24161 { 24162 _field_group_t *fg = NULL; 24163 _field_control_t *fc; /* Field Control Structure */ 24164 24165 if (fs_primary == NULL) { 24166 return BCM_E_PARAM; 24167 } 24168 24169 /* Get device Field control structure. */ 24170 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 24171 fg = fc->groups; 24172 24173 for (; fg != NULL; fg = fg->next) { 24174 if ((instance != fg->instance) || (stage_id != fg->stage_id)) { 24175 continue; 24176 } 24177 if (fg->slices != NULL) { 24178 if (fg->slices[0].slice_number == slice_id) { 24179 fg->slices = fs_primary; 24180 } 24181 } 24182 } 24183 return BCM_E_NONE; 24184 } 24185 24186 /* 24187 * Function: 24188 * _field_group_slice_align 24189 * Purpose: 24190 * Move source slice to des slice so that two consecutive slices are 24191 * free to create a double wide group. 24192 * The destination slice is added before source slice. the selcodes are 24193 * readd from source slice and installed in destination slice. 24194 * If the source slice was the primary slice of a group in that slice, then 24195 * the group slice pointer(fg->slices) of all the groups in the slice will 24196 * be set to the point to destination slice. The entries are moved from 24197 * source to destination slice and the source slice is removed and vmap of 24198 * is reset accordingly. 24199 * Parameters: 24200 * unit - (IN) BCM device number. 24201 * fg - (IN) group of the slice to move. 24202 * stage_fc - (IN) stage pointer 24203 * src_slice - (IN source slice no 24204 * dst_sicice - (IN) desination slice no 24205 * Returns: 24206 * BCM_E_XXX 24207 */ 24208 STATIC int 24209 _field_group_slice_align( 24210 int unit, _field_group_t *fg, 24211 _field_stage_t *stage_fc, 24212 uint8 src_slice, uint8 dst_slice) { 24213 int virtual_priority = FALSE; 24214 _field_slice_t *fs; 24215 24216 _field_slice_t *src_fs; 24217 _field_slice_t *dst_fs; 24218 _field_slice_t *base_ptr; 24219 _field_slice_t *old_fs; 24220 _field_control_t *fc; 24221 24222 int idx; /* Slice iteration index. */ 24223 int tmp_idx1; /* Slice entry index 1. */ 24224 int tmp_idx2; /* Slice entry index 2. */ 24225 int slice_sz; /* Number of entries in a slice. */ 24226 24227 int rv; 24228 uint8 is_root_slice = 0; 24229 uint8 is_cell_codes_init = 0; 24230 _field_group_t *src_fg; 24231 24232 rv = _field_control_get(unit, &fc); 24233 BCM_IF_ERROR_RETURN(rv); 24234 _field_virtual_priority_support(unit, stage_fc, &virtual_priority); 24235 24236 /* Remove original group from the map. */ 24237 if (virtual_priority) { 24238 rv = _field_group_vmap_delete(unit, stage_fc, fg, FALSE); 24239 BCM_IF_ERROR_RETURN(rv); 24240 } 24241 24242 /* Set up the new physical slice parameters in Software */ 24243 /* Get slice pointer for the destination slice. */ 24244 fs = stage_fc->slices[fg->instance] + dst_slice; 24245 24246 /* Enable the destination slice and initialize. */ 24247 BCM_IF_ERROR_RETURN 24248 (_field_slice_enable_set(unit, stage_fc, fg, fs, 1)); 24249 24250 /* Set per slice configuration & number of free entries in the slice.*/ 24251 fs->free_count = fs->entry_count; 24252 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 24253 fs->free_count >>= 1; 24254 } 24255 /* Set group flags in in slice.*/ 24256 fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK; 24257 24258 old_fs = &stage_fc->slices[fg->instance][src_slice]; 24259 /* insert destination slice before source slice */ 24260 if (old_fs->prev == NULL) { 24261 old_fs->prev = fs; 24262 fs->next = old_fs; 24263 fs->prev = NULL; 24264 fg->slices = fs; 24265 is_root_slice = 1; 24266 } else { 24267 fs->prev = old_fs->prev; 24268 old_fs->prev->next = fs; 24269 old_fs->prev = fs; 24270 fs->next = old_fs; 24271 } 24272 24273 BCM_PBMP_OR(fs->pbmp, fg->pbmp); 24274 24275 dst_fs = stage_fc->slices[fg->instance] + dst_slice; 24276 src_fs = stage_fc->slices[fg->instance] + src_slice; 24277 /* loop through all the groups of source slice and 24278 * install the sel codes for dest slice if there are entries 24279 * installed for that group. If the dest slice is primary slice, 24280 * then install sel codes for all groups. 24281 */ 24282 src_fg=NULL; 24283 do { 24284 (void)_bcm_field_slice_group_get_next(unit, 24285 fg->instance, fg->stage_id, 24286 src_fs->slice_number, 24287 &src_fg, &src_fg); 24288 if (src_fg != NULL) { 24289 BCM_PBMP_OR(dst_fs->pbmp, src_fg->pbmp); 24290 24291 if (is_root_slice) { 24292 rv = fc->functions.fp_selcodes_install(unit, src_fg, 24293 dst_slice, 24294 dst_fs->pbmp, 0); 24295 BCM_IF_ERROR_RETURN(rv); 24296 if (is_cell_codes_init == 0) { 24297 is_cell_codes_init = 1; 24298 } 24299 } else { 24300 /* check if the grp has entries in src slice*/ 24301 for (idx = 0; idx < src_fs->entry_count; idx++) { 24302 if ((NULL != src_fs->entries[idx]) && 24303 (NULL != src_fs->entries[idx]->group) && 24304 (src_fs->entries[idx]->group->gid == src_fg->gid)) { 24305 break; 24306 } 24307 } 24308 24309 if (idx != src_fs->entry_count) { 24310 /* 24311 * This means that there is an entry in the slice 24312 * belonging to same group. So,install the selcodes. 24313 */ 24314 rv = fc->functions.fp_selcodes_install(unit, src_fg, 24315 dst_slice, 24316 dst_fs->pbmp, 0); 24317 BCM_IF_ERROR_RETURN(rv); 24318 if (is_cell_codes_init == 0) { 24319 is_cell_codes_init = 1; 24320 } 24321 } 24322 } 24323 if (is_cell_codes_init == 1) { 24324 is_cell_codes_init = 2; 24325 rv = _bcm_field_group_selcode_initialize(unit, 24326 src_fg, dst_fs, 0); 24327 BCM_IF_ERROR_RETURN(rv); 24328 } 24329 } /* if (src_fg != NULL)*/ 24330 } while (src_fg != NULL); 24331 24332 /* Reinstall group virtual map . */ 24333 if (virtual_priority) { 24334 BCM_IF_ERROR_RETURN (_field_group_vmap_add(unit, stage_fc, fg)); 24335 } 24336 /* Move the entries from source to destination slice */ 24337 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, src_fs, slice_sz); 24338 for (idx = 0; idx < slice_sz; idx ++) { 24339 /* Find an empty slot. */ 24340 if (src_fs->entries[idx]) { 24341 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 24342 fg->instance, 24343 src_fs->slice_number, 24344 idx, &tmp_idx1); 24345 BCM_IF_ERROR_RETURN(rv); 24346 24347 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 24348 fg->instance, 24349 dst_fs->slice_number, 24350 idx, &tmp_idx2); 24351 BCM_IF_ERROR_RETURN(rv); 24352 /* move the entry from source slice to destination slice */ 24353 rv = _field_entry_move(unit, src_fs->entries[idx], 24354 (tmp_idx2 - tmp_idx1)); 24355 BCM_IF_ERROR_RETURN(rv); 24356 } 24357 } 24358 if (virtual_priority) { 24359 BCM_IF_ERROR_RETURN(_field_group_vmap_delete( 24360 unit, stage_fc, fg, FALSE)); 24361 } 24362 24363 /*remove the source slice slice*/ 24364 if (is_root_slice) { 24365 /*remove the head*/ 24366 base_ptr = src_fs->prev; 24367 /* since head is changed, set the head for each group whose 24368 * primary slice number is the source slice 24369 */ 24370 (void) _bcm_field_group_primary_slice_update(unit, 24371 fg->instance, fg->stage_id, 24372 src_slice, base_ptr); 24373 } 24374 src_fs->prev->next = src_fs->next; 24375 if (src_fs->next) { 24376 src_fs->next->prev = src_fs->prev; 24377 } 24378 24379 src_fg=NULL; 24380 do { 24381 (void)_bcm_field_slice_group_get_next(unit, 24382 fg->instance, fg->stage_id, 24383 dst_fs->slice_number, 24384 &src_fg, &src_fg); 24385 if (src_fg != NULL) { 24386 rv = _field_slice_clear(unit, src_fg, src_fs, src_fg->pbmp); 24387 BCM_IF_ERROR_RETURN(rv); 24388 } 24389 } while(src_fg != NULL); 24390 /* Clear used entries pbmp. */ 24391 src_fs->next = src_fs->prev = NULL; 24392 24393 if (virtual_priority) { 24394 /* Add the virtual map . */ 24395 BCM_IF_ERROR_RETURN(_field_group_vmap_add(unit, stage_fc, fg)); 24396 } 24397 24398 return BCM_E_NONE; 24399 } 24400 24401 /* 24402 * Function: 24403 * _field_group_add_slice_align 24404 * Purpose: 24405 * move slices so that two consecutive slices are 24406 * free to create a double wide group. 24407 * Parameters: 24408 * unit - (IN) BCM device number. 24409 * fsm_ptr - (IN/OUT) State machine tracking structure. 24410 * Returns: 24411 * BCM_E_XXX 24412 */ 24413 STATIC int 24414 _field_group_add_slice_align(int unit, _field_group_add_fsm_t *fsm_ptr) { 24415 int *free_slice_array = NULL; /* Array containing slice ids */ 24416 uint8 *slice_array_fill = NULL; /* Array containing slice ids */ 24417 int slice_index; /* Slice Index */ 24418 int free_slice_count = 0; 24419 int rv = 0; /* Operation return status. */ 24420 24421 _field_slice_t *src_fs; 24422 _field_slice_t *dst_fs; 24423 uint8 indx = 0; 24424 uint8 src_slice = 0; 24425 uint8 src_slice_free = 0; 24426 _field_group_t *src_fg = NULL; 24427 /* Set current state to be previous state. */ 24428 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 24429 fsm_ptr->rv = BCM_E_NONE; 24430 24431 /* check if atleast two slices are free */ 24432 _FP_XGS3_ALLOC(free_slice_array, sizeof(int) * fsm_ptr->stage_fc->tcam_slices, 24433 "Free Slice Array"); 24434 if (NULL == free_slice_array) { 24435 fsm_ptr->rv = BCM_E_MEMORY; 24436 goto cleanup; 24437 } 24438 24439 for (slice_index = 0; 24440 slice_index < fsm_ptr->stage_fc->tcam_slices; slice_index++) { 24441 if (!(fsm_ptr->stage_fc->slices[0][slice_index].group_flags)) { 24442 free_slice_array[free_slice_count] = slice_index; 24443 free_slice_count++; 24444 } 24445 } 24446 24447 /* double wide group requires atleast 2 slices to be free */ 24448 if (free_slice_count < 2) { 24449 fsm_ptr->rv = BCM_E_RESOURCE; 24450 goto cleanup; 24451 } 24452 24453 _FP_XGS3_ALLOC(slice_array_fill, sizeof(uint8) *fsm_ptr->stage_fc->tcam_slices, 24454 "Slice Array Fill"); 24455 if (NULL == slice_array_fill) { 24456 fsm_ptr->rv = BCM_E_MEMORY; 24457 goto cleanup; 24458 } 24459 24460 /* For each free slice found, find a slice that its partner slice 24461 * can autoexpand. For each free slice found, see if the double byte 24462 * group requested can be created. 24463 * if a slice for auto expansion is found and a double wide group 24464 * can be created, go ahead and move the slice 24465 */ 24466 /* loop for each free slice found*/ 24467 24468 for ( indx = 0; indx < free_slice_count; indx++) { 24469 src_slice_free = free_slice_array[indx]; 24470 src_slice = free_slice_array[indx]; 24471 if ( (free_slice_array[indx] ==0) || 24472 (free_slice_array[indx] % 2 == 0) ) { 24473 src_slice++; 24474 } else { 24475 src_slice--; 24476 } 24477 /* find the first group associated with the slice */ 24478 src_fg = NULL; 24479 (void)_bcm_field_slice_group_get_next(unit, 24480 fsm_ptr->fg->instance, 24481 fsm_ptr->stage_fc->stage_id, 24482 src_slice, 24483 &src_fg, &src_fg); 24484 if ( src_fg == NULL) { 24485 fsm_ptr->rv = BCM_E_INTERNAL; 24486 goto cleanup; 24487 } 24488 24489 for (slice_index = 0; slice_index < fsm_ptr->stage_fc->tcam_slices; slice_index++) { 24490 slice_array_fill[slice_index] = slice_index; 24491 } 24492 24493 rv = _field_fill_slice_array (unit, src_fg, slice_array_fill); 24494 if (rv != BCM_E_NONE) { 24495 fsm_ptr->rv = BCM_E_INTERNAL; 24496 goto cleanup; 24497 } 24498 24499 /* find an empty slice for the slice move */ 24500 for (slice_index = 0; 24501 slice_index < fsm_ptr->stage_fc->tcam_slices; slice_index++) { 24502 if (slice_array_fill[slice_index] == src_slice_free) { 24503 continue; 24504 } 24505 if (fsm_ptr->stage_fc->slices[0][slice_index].group_flags) { 24506 continue; 24507 } 24508 24509 /* Slice move is valid Check if 24510 * the requested group can be created after this move 24511 */ 24512 src_fs = fsm_ptr->stage_fc->slices[src_fg->instance] + src_slice; 24513 dst_fs = fsm_ptr->stage_fc->slices[src_fg->instance] + 24514 slice_array_fill[slice_index]; 24515 if (dst_fs->free_count < 24516 (src_fs->entry_count - src_fs->free_count)) { 24517 continue; 24518 } 24519 24520 /* move the slice and return */ 24521 rv = _field_group_slice_align( 24522 unit, src_fg, fsm_ptr->stage_fc, 24523 src_slice, slice_array_fill[slice_index]); 24524 if (BCM_FAILURE(rv)) { 24525 fsm_ptr->rv = BCM_E_INTERNAL; 24526 goto cleanup; 24527 } else { 24528 fsm_ptr->rv = BCM_E_NONE; 24529 goto cleanup; 24530 } 24531 } 24532 } 24533 24534 goto cleanup; 24535 24536 cleanup: 24537 if (free_slice_array) { 24538 sal_free (free_slice_array); 24539 free_slice_array = NULL; 24540 } 24541 if (slice_array_fill) { 24542 sal_free (slice_array_fill); 24543 slice_array_fill = NULL; 24544 } 24545 if (BCM_SUCCESS(fsm_ptr->rv)) { 24546 /* Retry allocating slice/s for the new field group. */ 24547 fsm_ptr->fsm_state_prev = 24548 _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN; 24549 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE; 24550 } else { 24551 fsm_ptr->fsm_state_prev = 24552 _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN; 24553 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24554 } 24555 24556 return _bcm_field_group_add(unit, fsm_ptr); 24557 } 24558 24559 /* 24560 * Function: 24561 * _field_group_add_initialize 24562 * Purpose: 24563 * Perform fsm initialization & execute basic checks 24564 * required before field group creation. 24565 * Parameters: 24566 * unit - (IN) BCM device number. 24567 * fsm_ptr - (IN/OUT) State machine tracking structure. 24568 * Returns: 24569 * BCM_E_XXX. 24570 */ 24571 STATIC int 24572 _field_group_add_initialize(int unit, _field_group_add_fsm_t *fsm_ptr) 24573 { 24574 24575 _field_stage_id_t stage = _BCM_FIELD_STAGE_INGRESS; /* Group pipeline stage id.*/ 24576 _field_group_t *fg_temp; /* Existing field group pointer. */ 24577 24578 /* Input parameters check. */ 24579 if (NULL == fsm_ptr) { 24580 return (BCM_E_PARAM); 24581 } 24582 24583 /* Set current state to be previous state. */ 24584 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 24585 24586 /* Group IDs must be unique within a unit. */ 24587 if(BCM_SUCCESS(_field_group_get(unit, fsm_ptr->group_id, &fg_temp))) { 24588 LOG_ERROR(BSL_LS_BCM_FP, 24589 (BSL_META_U(unit, 24590 "FP(unit %d) Error: group=%d already exists.\n"), 24591 unit, fsm_ptr->group_id)); 24592 fsm_ptr->rv = (BCM_E_EXISTS); 24593 } 24594 24595 /* Get field stage control pointer. */ 24596 if (BCM_SUCCESS(fsm_ptr->rv)) { 24597 fsm_ptr->rv = _field_control_get(unit, &fsm_ptr->fc); 24598 } 24599 24600 /* Get pipeline stage from qualifiers set. */ 24601 if (BCM_SUCCESS(fsm_ptr->rv)) { 24602 fsm_ptr->rv = _bcm_field_group_stage_get(unit, &fsm_ptr->qset, &stage); 24603 } 24604 24605 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 24606 /* Allow intraslice select codes if they are supported by the stage. */ 24607 if (BCM_SUCCESS(fsm_ptr->rv) && 24608 soc_feature(unit, soc_feature_field_intraslice_double_wide) && 24609 (fsm_ptr->fc->flags & _FP_INTRASLICE_ENABLE) && 24610 (_BCM_FIELD_STAGE_EGRESS != stage) && 24611 (_BCM_FIELD_STAGE_EXTERNAL != stage)) { 24612 /* We might try intraslice group. */ 24613 if (((!SOC_IS_TD_TT(unit)) && 24614 (!((SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 24615 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit) || 24616 (SOC_IS_TRIUMPH3(unit) && 24617 soc_feature(unit, soc_feature_field_stage_quarter_slice))) 24618 && (_BCM_FIELD_STAGE_LOOKUP == stage)))) 24619 || (SOC_IS_TD_TT(unit) && (_BCM_FIELD_STAGE_LOOKUP == stage))) { 24620 /* Hurricane2/GH does not support intraslice double wide mode in VFP */ 24621 /* In Ranger+ one TCAM in each slice is fused out in VFP stage. 24622 * Hence it can not support intraslice double wide mode in VFP */ 24623 /* For TD and TT Intra-slice mode supported only for VFP */ 24624 fsm_ptr->flags |= _BCM_FP_GROUP_ADD_INTRA_SLICE; 24625 } 24626 } 24627 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 24628 24629 /* Get field stage control pointer. */ 24630 if (BCM_SUCCESS(fsm_ptr->rv)) { 24631 fsm_ptr->rv = _field_stage_control_get(unit, stage, &fsm_ptr->stage_fc); 24632 } 24633 24634 #ifdef BCM_TRIUMPH_SUPPORT 24635 /* _bcmFieldQualifyData2 is valid only for external stage on Triumph */ 24636 if (SOC_IS_TRIUMPH(unit)) { 24637 if ((BCM_FIELD_QSET_TEST(fsm_ptr->qset, 24638 bcmFieldQualifyStageExternal) == 0) && 24639 (BCM_FIELD_QSET_TEST(fsm_ptr->qset, 24640 _bcmFieldQualifyData2))) { 24641 BCM_FIELD_QSET_REMOVE_INTERNAL(fsm_ptr->qset, 24642 _bcmFieldQualifyData2); 24643 } 24644 } 24645 #endif /* !BCM_TRIUMPH_SUPPORT || BCM_TRIUMPH2_SUPPORT */ 24646 24647 /* Verify that requested qualifiers set is supported by stage. */ 24648 if (BCM_SUCCESS(fsm_ptr->rv)) { 24649 if (FALSE == _field_qset_is_subset(&fsm_ptr->qset, 24650 &fsm_ptr->stage_fc->_field_supported_qset)) { 24651 LOG_VERBOSE(BSL_LS_BCM_FP, 24652 (BSL_META_U(unit, 24653 "FP(unit %d) Error: Qualifier set is not supported by the device.\n"), 24654 unit)); 24655 fsm_ptr->rv = BCM_E_UNAVAIL; 24656 } 24657 } 24658 24659 if (BCM_FAILURE(fsm_ptr->rv)) { 24660 /* Error occured -> clean up.. */ 24661 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24662 } else { 24663 /* Proceed to group allocation stage. */ 24664 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_ALLOC; 24665 } 24666 return _bcm_field_group_add(unit, fsm_ptr); 24667 } 24668 24669 /* 24670 * Function: 24671 * _field_group_add_alloc 24672 * Purpose: 24673 * Allocate & initialize field group structure. 24674 * Parameters: 24675 * unit - (IN) BCM device number. 24676 * fsm_ptr - (IN/OUT) State machine tracking structure. 24677 * Returns: 24678 * BCM_E_XXX. 24679 */ 24680 STATIC int 24681 _field_group_add_alloc(int unit, _field_group_add_fsm_t *fsm_ptr) 24682 { 24683 int idx; /* Misc iterator. */ 24684 int mem_sz; /* Allocated memory size. */ 24685 _field_group_t *fg = NULL; /* New group info. */ 24686 int virtual_priority = FALSE;/* Virtual priority support flag.*/ 24687 24688 24689 /* Input parameters check. */ 24690 if (NULL == fsm_ptr) { 24691 return (BCM_E_PARAM); 24692 } 24693 24694 /* Set current state to be previous state. */ 24695 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 24696 24697 /* Allocate & initialize memory for field group. */ 24698 mem_sz = sizeof(_field_group_t); 24699 _FP_XGS3_ALLOC(fg, mem_sz, "field group"); 24700 if (NULL == fg) { 24701 LOG_ERROR(BSL_LS_BCM_FP, 24702 (BSL_META_U(unit, 24703 "FP(unit %d) Error:Allocation failure for _field_group_t\n"), 24704 unit)); 24705 fsm_ptr->rv = BCM_E_MEMORY; 24706 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24707 return _bcm_field_group_add(unit, fsm_ptr); 24708 } 24709 24710 24711 /* Initialize group structure. */ 24712 fg->gid = fsm_ptr->group_id; 24713 fg->stage_id = fsm_ptr->stage_fc->stage_id; 24714 fg->qset = fsm_ptr->qset; 24715 fg->pbmp = fsm_ptr->pbmp; 24716 fg->priority = fsm_ptr->priority; 24717 24718 if ( soc_feature(unit, soc_feature_field_multi_pipe_support) || 24719 soc_feature(unit, soc_feature_field_ingress_two_slice_types)) { 24720 fg->hintid = fsm_ptr->hintid; 24721 /* Group has been created, Increment group ref count in 24722 * corresponding hintid in hints hash lookup table */ 24723 fsm_ptr->rv = _bcm_field_hints_group_count_update (unit, fg->hintid, 1); 24724 if (BCM_FAILURE(fsm_ptr->rv)) { 24725 sal_free (fg); 24726 fg = NULL; 24727 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24728 /* coverity[leaked_storage: FALSE] */ 24729 return _bcm_field_group_add(unit, fsm_ptr); 24730 } 24731 } 24732 24733 /* Initialize group status. */ 24734 fsm_ptr->rv = _bcm_field_group_status_init(unit, &fg->group_status); 24735 if (BCM_FAILURE(fsm_ptr->rv)) { 24736 sal_free (fg); 24737 fg = NULL; 24738 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24739 /* coverity[leaked_storage: FALSE] */ 24740 return _bcm_field_group_add(unit, fsm_ptr); 24741 } 24742 24743 if ( soc_feature(unit, soc_feature_field_multi_pipe_support) || 24744 soc_feature(unit, soc_feature_field_ingress_two_slice_types) ) { 24745 /* Update group datastructure from hintid */ 24746 fsm_ptr->rv = _bcm_field_hints_group_info_update (unit, fg); 24747 if (BCM_FAILURE(fsm_ptr->rv)) { 24748 sal_free (fg); 24749 fg = NULL; 24750 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24751 /* coverity[leaked_storage: FALSE] */ 24752 return _bcm_field_group_add(unit, fsm_ptr); 24753 } 24754 } 24755 24756 24757 /* Clear the group's select codes and its slice Qsets. */ 24758 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 24759 _FIELD_SELCODE_CLEAR(fg->sel_codes[idx]); 24760 } 24761 24762 /* By default mark group as active. */ 24763 fg->flags |= _FP_GROUP_LOOKUP_ENABLED; 24764 24765 /* Set special group flags. */ 24766 if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_WLAN) { 24767 fg->flags |= _FP_GROUP_WLAN; 24768 } 24769 24770 /* Set slice size selection group flags. */ 24771 if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_SMALL_SLICE) { 24772 fg->flags |= _FP_GROUP_SELECT_SMALL_SLICE; 24773 } else if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_LARGE_SLICE) { 24774 fg->flags |= _FP_GROUP_SELECT_LARGE_SLICE; 24775 } 24776 24777 /* Set action res id and vmap group to default */ 24778 fg->action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 24779 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 24780 fg->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 24781 } 24782 24783 _field_virtual_priority_support(unit, fsm_ptr->stage_fc, &virtual_priority); 24784 24785 /* Update virtual group related parameters */ 24786 if ((virtual_priority == TRUE) 24787 && (fsm_ptr->stage_fc->stage_id != _BCM_FIELD_STAGE_EXTERNAL)) { 24788 fg->action_res_id = fsm_ptr->action_res_id; 24789 /* If virtual group is valid check if any existing internal vmap group exists */ 24790 if(fg->action_res_id != BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT) 24791 { 24792 fsm_ptr->rv = _bcm_field_group_virtual_map_update(unit, fg); 24793 if (BCM_FAILURE(fsm_ptr->rv)) { 24794 sal_free (fg); 24795 fg = NULL; 24796 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24797 return _bcm_field_group_add(unit, fsm_ptr); 24798 } 24799 } 24800 } 24801 #if defined(BCM_TOMAHAWK_SUPPORT) 24802 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 24803 ((_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) || 24804 (_BCM_FIELD_STAGE_EGRESS == fg->stage_id))) { 24805 24806 /* Set the Field Group's instance information. */ 24807 fsm_ptr->rv = _bcm_field_th_group_instance_set(unit, fg); 24808 if (BCM_FAILURE(fsm_ptr->rv)) { 24809 sal_free (fg); 24810 fg = NULL; 24811 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 24812 return _bcm_field_group_add(unit, fsm_ptr); 24813 } 24814 } 24815 #endif /* BCM_TOMAHAWK_SUPPORT */ 24816 24817 /* Set allocated pointer to FSM structure. */ 24818 fsm_ptr->fg = fg; 24819 /* Update group qset with internal qualifiers. */ 24820 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_UPDATE; 24821 24822 return _bcm_field_group_add(unit, fsm_ptr); 24823 } 24824 24825 /* 24826 * Function: 24827 * _field_group_add_qualify_in_ports 24828 * Purpose: 24829 * Update group application requested qset 24830 * if group is restricted to subset of device ports. 24831 * Parameters: 24832 * unit - (IN) BCM device number. 24833 * fg - (IN/OUT) Field Group pointer. 24834 * Returns: 24835 * BCM_E_XXX 24836 */ 24837 STATIC int 24838 _field_group_add_qualify_in_ports(int unit, _field_group_t *fg) 24839 { 24840 bcm_pbmp_t pbmp_temp; /* Port bitmap buffer. */ 24841 int count; /* Number of ports in PBMP. */ 24842 int qual_in_ports; /* Qualify InPorts flag. */ 24843 24844 24845 /* Input parameters check. */ 24846 if (NULL == fg) { 24847 return (BCM_E_PARAM); 24848 } 24849 24850 #if defined(BCM_TOMAHAWK_SUPPORT) 24851 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 24852 ((_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) || 24853 (_BCM_FIELD_STAGE_EGRESS == fg->stage_id))) { 24854 /* Do nothing */ 24855 return BCM_E_NONE; 24856 } 24857 #endif /* BCM_TOMAHAWK_SUPPORT */ 24858 24859 /* Read device port configuration. */ 24860 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &pbmp_temp)); 24861 24862 /* 24863 * If group active on on all ports no InPort/InPorts 24864 * qualification is required. 24865 */ 24866 if (BCM_PBMP_EQ(fg->pbmp, pbmp_temp)) { 24867 /* Update the instance to default. */ 24868 fg->instance = _FP_DEF_INST; 24869 return (BCM_E_NONE); 24870 } 24871 24872 if (_BCM_FIELD_STAGE_INGRESS != fg->stage_id) { 24873 return (BCM_E_RESOURCE); 24874 } 24875 24876 qual_in_ports = TRUE; 24877 /* 24878 * If there's only 1 port and device capable efficiently 24879 * qualify on source port use InPort qualifier in stead of InPorts 24880 */ 24881 BCM_PBMP_COUNT(fg->pbmp, count); 24882 if ((count == 1) && (!soc_feature(unit, soc_feature_table_hi))) { 24883 if (soc_feature(unit, soc_feature_field_multi_stage)) { 24884 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInPort); 24885 qual_in_ports = FALSE; 24886 } else if (SOC_MEM_FIELD_VALID(unit, FP_TCAMm, SOURCE_PORT_NUMBER_MASKf)) { 24887 /* 24888 * In Order to qualify on a single Higig port - 24889 * Higig quailifier must be present in each rule. 24890 */ 24891 BCM_PBMP_ASSIGN(pbmp_temp, fg->pbmp); 24892 BCM_PBMP_AND(pbmp_temp, PBMP_HG_ALL(unit)); 24893 if (BCM_PBMP_IS_NULL(pbmp_temp)) { 24894 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInPort); 24895 qual_in_ports = FALSE; 24896 } 24897 } 24898 } 24899 if (qual_in_ports) { 24900 if (soc_feature(unit, soc_feature_ifp_no_inports_support)) { 24901 return (BCM_E_UNAVAIL); 24902 } else { 24903 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInPorts); 24904 } 24905 } 24906 return (BCM_E_NONE); 24907 } 24908 24909 #if defined(BCM_TRX_SUPPORT) 24910 /* 24911 * Function: 24912 * _field_group_qset_rangecheck_update 24913 * Purpose: 24914 * Update application requested qset with internal qualifiers. 24915 * Parameters: 24916 * unit - (IN) BCM device number. 24917 * fg - (IN/OUT) Field group structure. 24918 * Returns: 24919 * BCM_E_XXX 24920 */ 24921 STATIC int 24922 _field_group_qset_rangecheck_update(int unit, _field_group_t *fg) 24923 { 24924 _field_stage_t *stage_fc; /* Stage field control structure. */ 24925 /* Input parameters check. */ 24926 if (NULL == fg) { 24927 return (BCM_E_PARAM); 24928 } 24929 24930 24931 if (_BCM_FIELD_STAGE_INGRESS != fg->stage_id) { 24932 return (BCM_E_NONE); 24933 } 24934 24935 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 24936 _BCM_FIELD_STAGE_INGRESS, &stage_fc)); 24937 24938 /* Check if interface Class id qualifiers are not present */ 24939 if (!(BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassPort) || 24940 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassL3) || 24941 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassVPort) || 24942 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassL2))) { 24943 /* Check if stage supports the new internal qualifier */ 24944 if (BCM_FIELD_QSET_TEST(stage_fc->_field_supported_qset, 24945 _bcmFieldQualifyRangeCheckBits24_31)) { 24946 BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifyRangeCheckBits24_31); 24947 } 24948 } 24949 return (BCM_E_NONE); 24950 } 24951 #endif 24952 24953 /* 24954 * Function: 24955 * _field_group_qset_update 24956 * Purpose: 24957 * Update application requested qset with internal qualifiers. 24958 * Parameters: 24959 * unit - (IN) BCM device number. 24960 * fg - (IN/OUT) Field group structure. 24961 * Returns: 24962 * BCM_E_XXX 24963 */ 24964 int 24965 _field_group_qset_update(int unit, _field_group_t *fg) 24966 { 24967 /* Input parameters check. */ 24968 if (NULL == fg) { 24969 return (BCM_E_PARAM); 24970 } 24971 24972 /* All ingress devices implicitly have bcmFieldQualifyStage in Qsets.*/ 24973 if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 24974 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyStage); 24975 } 24976 /* 24977 * Vlan qualifiers ared extended to Id/Cfi/Pri 24978 */ 24979 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyOuterVlan)) { 24980 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyOuterVlanId); 24981 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyOuterVlanPri); 24982 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyOuterVlanCfi); 24983 } 24984 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInnerVlan)) { 24985 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInnerVlanId); 24986 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInnerVlanPri); 24987 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInnerVlanCfi); 24988 } 24989 #ifdef BCM_HURRICANE3_SUPPORT 24990 if (soc_feature(unit, soc_feature_miml)) { 24991 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyMimlVlan)) { 24992 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyMimlVlanId); 24993 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyMimlVlanPri); 24994 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyMimlVlanCfi); 24995 } 24996 } 24997 if (soc_feature(unit, soc_feature_ing_capwap_parser)) { 24998 if (BCM_FIELD_QSET_TEST(fg->qset, 24999 bcmFieldQualifyCapwapPayloadOuterVlan)) { 25000 BCM_FIELD_QSET_ADD(fg->qset, 25001 bcmFieldQualifyCapwapPayloadOuterVlanId); 25002 BCM_FIELD_QSET_ADD(fg->qset, 25003 bcmFieldQualifyCapwapPayloadOuterVlanPri); 25004 BCM_FIELD_QSET_ADD(fg->qset, 25005 bcmFieldQualifyCapwapPayloadOuterVlanCfi); 25006 } 25007 if (BCM_FIELD_QSET_TEST(fg->qset, 25008 bcmFieldQualifyCapwapPayloadInnerVlan)) { 25009 BCM_FIELD_QSET_ADD(fg->qset, 25010 bcmFieldQualifyCapwapPayloadInnerVlanId); 25011 BCM_FIELD_QSET_ADD(fg->qset, 25012 bcmFieldQualifyCapwapPayloadInnerVlanPri); 25013 BCM_FIELD_QSET_ADD(fg->qset, 25014 bcmFieldQualifyCapwapPayloadInnerVlanCfi); 25015 } 25016 } 25017 #endif /* BCM_HURRICANE3_SUPPORT */ 25018 25019 /* 25020 * Automatically include IpType 25021 * if the qset contains PacketFormat/Ip4/Ip6. 25022 * FB2 stage egress and stage external are an exception. 25023 */ 25024 if (_BCM_FIELD_STAGE_EXTERNAL != fg->stage_id) { 25025 if ( 25026 #if defined (BCM_FIREBOLT2_SUPPORT) 25027 ((0 == SOC_IS_FIREBOLT2(unit)) || 25028 (_BCM_FIELD_STAGE_EGRESS != fg->stage_id)) && 25029 #endif /* BCM_FIREBOLT2_SUPPORT */ 25030 ((BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4)) || 25031 (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6)))) { 25032 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyIpType); 25033 } 25034 } 25035 25036 #if defined(BCM_FIREBOLT2_SUPPORT) 25037 if (SOC_IS_FIREBOLT2(unit)) { 25038 /* Device doesn't support qualification on IP without version. */ 25039 if ((BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4)) && 25040 (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6))) { 25041 return (BCM_E_RESOURCE); 25042 } 25043 } 25044 #endif /* BCM_FIREBOLT2_SUPPORT */ 25045 25046 /* 25047 * Add qualification on InPorts/InPort in case group applicable only 25048 * to part of the ports. 25049 */ 25050 BCM_IF_ERROR_RETURN(_field_group_add_qualify_in_ports(unit, fg)); 25051 25052 #ifdef BCM_TRIUMPH3_SUPPORT 25053 if ((SOC_IS_TRIUMPH3(unit)) 25054 || ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) 25055 || (SOC_IS_KATANA2(unit))) { 25056 BCM_IF_ERROR_RETURN(_bcm_field_tr3_group_qset_update(unit, fg)); 25057 } 25058 #endif 25059 25060 #if defined(BCM_TRX_SUPPORT) 25061 if (SOC_IS_TRX(unit) && 25062 !(soc_feature(unit, soc_feature_field_multi_pipe_support)) && 25063 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyRangeCheck)) { 25064 BCM_IF_ERROR_RETURN(_field_group_qset_rangecheck_update(unit, fg)); 25065 } 25066 #endif 25067 25068 return (BCM_E_NONE); 25069 } 25070 25071 /* 25072 * Function: 25073 * _field_group_add_qset_update 25074 * Purpose: 25075 * Update application requested qset with internal qualifiers. 25076 * Parameters: 25077 * unit - (IN) BCM device number. 25078 * fsm_ptr - (IN/OUT) State machine tracking structure. 25079 * Returns: 25080 * BCM_E_XXX 25081 */ 25082 STATIC int 25083 _field_group_add_qset_update(int unit, _field_group_add_fsm_t *fsm_ptr) 25084 { 25085 /* Input parameters check. */ 25086 if (NULL == fsm_ptr) { 25087 return (BCM_E_PARAM); 25088 } 25089 25090 if (NULL == fsm_ptr->fg) { 25091 fsm_ptr->rv = (BCM_E_PARAM); 25092 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 25093 return _bcm_field_group_add(unit, fsm_ptr); 25094 } 25095 25096 /* Set current state to be previous state. */ 25097 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 25098 25099 /* Update group qset with internal qualifiers. */ 25100 fsm_ptr->rv = _field_group_qset_update(unit, fsm_ptr->fg); 25101 25102 if (BCM_FAILURE(fsm_ptr->rv)) { 25103 /* Qset verification/modification failed - clean up. */ 25104 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 25105 } else { 25106 /* Proceed to select codes selection. */ 25107 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25108 } 25109 return _bcm_field_group_add(unit, fsm_ptr); 25110 } 25111 25112 25113 /* 25114 * Function: 25115 * _field_selcode_assign_udf_alternative 25116 * Purpose: 25117 * Calculate the FPFx select codes from a qualifier set and group mode. 25118 * Parameters: 25119 * unit - (IN) BCM device number. 25120 * fsm_ptr - (IN/OUT) State machine tracking structure. 25121 * Returns: 25122 * BCM_E_XXX 25123 */ 25124 STATIC int 25125 _field_selcode_assign_udf_alternative(int unit, _field_group_add_fsm_t *fsm_ptr) 25126 { 25127 _field_group_t *fg; /* Field group pointer. */ 25128 bcm_field_qset_t temp_qset; 25129 25130 /* Input parameters check. */ 25131 if (NULL == fsm_ptr) { 25132 return (BCM_E_PARAM); 25133 } 25134 25135 if (NULL == fsm_ptr->fg) { 25136 return (BCM_E_PARAM); 25137 } 25138 25139 /* Group pointer initialization. */ 25140 fg = fsm_ptr->fg; 25141 25142 if (!(soc_feature(unit, soc_feature_field_multi_pipe_support)) && 25143 (BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyData2) || 25144 BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyData3))) { 25145 /* Try with Data0 instead of optimized Data2/Data3 qualifiers */ 25146 temp_qset = fg->qset; 25147 BCM_FIELD_QSET_REMOVE_INTERNAL(fg->qset, _bcmFieldQualifyData2); 25148 BCM_FIELD_QSET_REMOVE_INTERNAL(fg->qset, _bcmFieldQualifyData3); 25149 BCM_FIELD_QSET_ADD_INTERNAL(fg->qset, _bcmFieldQualifyData0); 25150 25151 LOG_DEBUG(BSL_LS_BCM_FP, 25152 (BSL_META_U(unit, 25153 "Trying with alternative udf...\n"))); 25154 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25155 /* Restore back the old qset in case of failure */ 25156 if (BCM_FAILURE(fsm_ptr->rv)) { 25157 fg->qset = temp_qset; 25158 } 25159 } 25160 25161 return (BCM_E_NONE); 25162 } 25163 25164 /* 25165 * Function: 25166 * _field_group_add_sel_codes_get 25167 * Purpose: 25168 * Calculate the FPFx select codes from a qualifier set and group mode. 25169 * Parameters: 25170 * unit - (IN) BCM device number. 25171 * fsm_ptr - (IN/OUT) State machine tracking structure. 25172 * Returns: 25173 * BCM_E_XXX 25174 */ 25175 STATIC int 25176 _field_group_add_sel_codes_get(int unit, _field_group_add_fsm_t *fsm_ptr) 25177 { 25178 _field_group_t *fg; /* Field group pointer. */ 25179 int orig_group_flags; /* Original group flags. */ 25180 25181 25182 /* Input parameters check. */ 25183 if (NULL == fsm_ptr) { 25184 return (BCM_E_PARAM); 25185 } 25186 25187 if (NULL == fsm_ptr->fg) { 25188 fsm_ptr->rv = (BCM_E_PARAM); 25189 } 25190 25191 /* Check if requested mode is supported by device. */ 25192 switch (fsm_ptr->mode) { 25193 case bcmFieldGroupModeQuad: 25194 if (0 == soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 25195 fsm_ptr->rv = (BCM_E_RESOURCE); 25196 } 25197 break; 25198 case bcmFieldGroupModeTriple: 25199 if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 25200 fsm_ptr->rv = (BCM_E_RESOURCE); 25201 } 25202 #ifdef BCM_TRIDENT_SUPPORT 25203 if (SOC_IS_TD_TT(unit)) 25204 { 25205 fsm_ptr->rv = (BCM_E_UNAVAIL); 25206 } 25207 #endif 25208 /* Fall through. */ 25209 case bcmFieldGroupModeDouble: 25210 if (0 == soc_feature(unit, soc_feature_field_wide)) { 25211 fsm_ptr->rv = (BCM_E_RESOURCE); 25212 } 25213 break; 25214 case bcmFieldGroupModeIntraSliceDouble: 25215 if (0 == soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 25216 fsm_ptr->rv = (BCM_E_RESOURCE); 25217 } 25218 break; 25219 default: 25220 break; 25221 } 25222 if (BCM_FAILURE(fsm_ptr->rv)) { 25223 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 25224 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 25225 return _bcm_field_group_add(unit, fsm_ptr); 25226 } 25227 25228 /* Group pointer initialization. */ 25229 fg = fsm_ptr->fg; 25230 25231 fsm_ptr->rv = BCM_E_RESOURCE; 25232 orig_group_flags = fg->flags; 25233 25234 /* Allocate & initialize memory for field group. */ 25235 if (fsm_ptr->mode == bcmFieldGroupModeAuto) 25236 { 25237 LOG_DEBUG(BSL_LS_BCM_FP, 25238 (BSL_META_U(unit, 25239 "Group mode auto.\n"))); 25240 25241 /* For Auto mode, try Single, Double, then Triple. */ 25242 /* Single wide non intra slice selection. */ 25243 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 25244 LOG_DEBUG(BSL_LS_BCM_FP, 25245 (BSL_META_U(unit, 25246 "Trying single...\n"))); 25247 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE); 25248 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25249 if (BCM_FAILURE(fsm_ptr->rv)) { 25250 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25251 } 25252 } 25253 25254 /* Double wide intra slice selection. */ 25255 if ((BCM_FAILURE(fsm_ptr->rv) && 25256 (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) { 25257 if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 25258 LOG_DEBUG(BSL_LS_BCM_FP, 25259 (BSL_META_U(unit, 25260 "Trying intra...\n"))); 25261 fg->flags = (orig_group_flags | 25262 _FP_GROUP_SPAN_SINGLE_SLICE | 25263 _FP_GROUP_INTRASLICE_DOUBLEWIDE); 25264 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25265 if (BCM_FAILURE(fsm_ptr->rv)) { 25266 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25267 } 25268 } 25269 } 25270 25271 /* Double wide inter slice selection. */ 25272 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 25273 if (BCM_FAILURE(fsm_ptr->rv)) { 25274 LOG_DEBUG(BSL_LS_BCM_FP, 25275 (BSL_META_U(unit, 25276 "Trying double...\n"))); 25277 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_DOUBLE_SLICE); 25278 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25279 if (BCM_FAILURE(fsm_ptr->rv)) { 25280 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25281 } 25282 } 25283 } 25284 25285 /* Quad wide inter & intra slice selection. */ 25286 if ((BCM_FAILURE(fsm_ptr->rv) && 25287 (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) { 25288 if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 25289 LOG_DEBUG(BSL_LS_BCM_FP, 25290 (BSL_META_U(unit, 25291 "Trying quad...\n"))); 25292 fg->flags = (orig_group_flags | 25293 _FP_GROUP_SPAN_DOUBLE_SLICE | 25294 _FP_GROUP_INTRASLICE_DOUBLEWIDE); 25295 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25296 if (BCM_FAILURE(fsm_ptr->rv)) { 25297 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25298 } 25299 } 25300 } 25301 25302 /* Triple wide inter slice selection. */ 25303 if ((0 == soc_feature(unit, soc_feature_field_intraslice_double_wide)) && 25304 (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) && 25305 (!SOC_IS_TD_TT(unit))) { 25306 if (BCM_FAILURE(fsm_ptr->rv)) { 25307 LOG_DEBUG(BSL_LS_BCM_FP, 25308 (BSL_META_U(unit, 25309 "Trying triple...\n"))); 25310 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_TRIPLE_SLICE); 25311 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25312 if (BCM_FAILURE(fsm_ptr->rv)) { 25313 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25314 } 25315 } 25316 } 25317 } else { 25318 switch (fsm_ptr->mode) { 25319 case bcmFieldGroupModeSingle: 25320 /* Single wide non intra slice selection. */ 25321 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 25322 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE); 25323 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25324 if (BCM_FAILURE(fsm_ptr->rv)) { 25325 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25326 } 25327 } 25328 break; 25329 case bcmFieldGroupModeIntraSliceDouble: 25330 /* Double wide intra slice selection. */ 25331 if ((soc_feature(unit, soc_feature_field_intraslice_double_wide)) && 25332 (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE)) { 25333 fg->flags = (orig_group_flags | 25334 _FP_GROUP_SPAN_SINGLE_SLICE | 25335 _FP_GROUP_INTRASLICE_DOUBLEWIDE); 25336 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25337 if (BCM_FAILURE(fsm_ptr->rv)) { 25338 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25339 } 25340 } 25341 break; 25342 case bcmFieldGroupModeDouble: 25343 /* Double wide intra slice selection. */ 25344 if ((soc_feature(unit, soc_feature_field_intraslice_double_wide) && 25345 (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) { 25346 fg->flags = (orig_group_flags | 25347 _FP_GROUP_SPAN_SINGLE_SLICE | 25348 _FP_GROUP_INTRASLICE_DOUBLEWIDE); 25349 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25350 if (BCM_FAILURE(fsm_ptr->rv)) { 25351 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25352 } 25353 } 25354 /* Double wide inter slice selection. */ 25355 if ((BCM_FAILURE(fsm_ptr->rv)) && 25356 (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY))) { 25357 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_DOUBLE_SLICE); 25358 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25359 if (BCM_FAILURE(fsm_ptr->rv)) { 25360 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25361 } 25362 } 25363 break; 25364 case bcmFieldGroupModeTriple: 25365 /* Triple wide inter slice selection. */ 25366 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 25367 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_TRIPLE_SLICE); 25368 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25369 if (BCM_FAILURE(fsm_ptr->rv)) { 25370 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25371 } 25372 } 25373 break; 25374 case bcmFieldGroupModeQuad: 25375 if ((soc_feature(unit, soc_feature_field_intraslice_double_wide) && 25376 (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) { 25377 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_DOUBLE_SLICE | 25378 _FP_GROUP_INTRASLICE_DOUBLEWIDE); 25379 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg); 25380 if (BCM_FAILURE(fsm_ptr->rv)) { 25381 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr)); 25382 } 25383 } 25384 break; 25385 default: 25386 fsm_ptr->rv = (BCM_E_PARAM); 25387 } 25388 } 25389 25390 if (BCM_FAILURE(fsm_ptr->rv)) { 25391 LOG_DEBUG(BSL_LS_BCM_FP, 25392 (BSL_META_U(unit, 25393 "No success so far.\n"))); 25394 /* No luck so far - try different alternative qset if possible. */ 25395 if ((BCM_E_RESOURCE == fsm_ptr->rv) && 25396 (_BCM_FP_GROUP_ADD_STATE_QSET_UPDATE == fsm_ptr->fsm_state_prev)) { 25397 fsm_ptr->rv = (BCM_E_NONE); 25398 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE; 25399 } 25400 } else { 25401 #ifdef BCM_TRIUMPH2_SUPPORT /* BCM_TRIUMPH2_SUPPORT */ 25402 int i, ingress_entity = 0; 25403 #endif /* !BCM_TRIUMPH2_SUPPORT */ 25404 25405 LOG_DEBUG(BSL_LS_BCM_FP, 25406 (BSL_META_U(unit, 25407 "Configuration found...\n"))); 25408 /* Check if unit supports wide rules. */ 25409 if ((!soc_feature(unit, soc_feature_field_wide)) && 25410 (!(fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE))) 25411 { 25412 LOG_DEBUG(BSL_LS_BCM_FP, 25413 (BSL_META_U(unit, 25414 "Double not supported.\n"))); 25415 fsm_ptr->rv = (BCM_E_UNAVAIL); 25416 } 25417 25418 #ifdef BCM_TRIUMPH2_SUPPORT /* BCM_TRIUMPH2_SUPPORT */ 25419 /* 25420 * Check which configuration of SrcMplsGport/SrcMimGport/ 25421 * SrcNivGport is in use. 25422 */ 25423 for (i = 0; i < _FP_MAX_ENTRY_WIDTH; i++) { 25424 if ((fg->sel_codes[i].ingress_entity_sel == 25425 _bcmFieldFwdEntityMimGport) || 25426 (fg->sel_codes[i].ingress_entity_sel == 25427 _bcmFieldFwdEntityMplsGport) || 25428 (fg->sel_codes[i].ingress_entity_sel == 25429 _bcmFieldFwdEntityNivGport) || 25430 (fg->sel_codes[i].ingress_entity_sel == 25431 _bcmFieldFwdEntityWlanGport) || 25432 (fg->sel_codes[i].ingress_entity_sel == 25433 _bcmFieldFwdEntityVxlanGport) || 25434 (fg->sel_codes[i].ingress_entity_sel == 25435 _bcmFieldFwdEntityVlanGport) || 25436 (fg->sel_codes[i].ingress_entity_sel == 25437 _bcmFieldFwdEntityCommonGport)) { 25438 ingress_entity = 1; 25439 break; 25440 } 25441 } 25442 25443 /* Adjust for SvpValid where applicable */ 25444 if (soc_feature(unit, soc_feature_mim) && 25445 (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcMimGport) || 25446 (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcMimGports)) || 25447 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGports) || 25448 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGport)) && 25449 !BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifySvpValid) && 25450 (1 == ingress_entity)) { 25451 25452 /* SrcMimGport */ 25453 BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifySvpValid); 25454 fsm_ptr->rv = (BCM_E_NONE); 25455 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE; 25456 25457 } else if ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) && 25458 (1 == ingress_entity) && 25459 !BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifySvpValid) && 25460 (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcMplsGport) || 25461 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcMplsGports) || 25462 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGports) || 25463 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGport) || 25464 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcNivGport) || 25465 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcNivGports) || 25466 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcVxlanGport) || 25467 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcVxlanGports) || 25468 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcVlanGport) || 25469 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcVlanGports))) { 25470 /* SrcMplsGport or SrcNivGport or SrcVxlanGport or SrcVlanGport */ 25471 BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifySvpValid); 25472 fsm_ptr->rv = (BCM_E_NONE); 25473 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE; 25474 } else 25475 #endif /* !BCM_TRIUMPH2_SUPPORT */ 25476 { 25477 /* Insert group into units group list. */ 25478 if (BCM_SUCCESS(fsm_ptr->rv)) { 25479 fsm_ptr->rv = _bcm_field_group_linked_list_insert(unit, fsm_ptr); 25480 } 25481 25482 /* Success proceed to slice allocation. */ 25483 if (BCM_SUCCESS(fsm_ptr->rv)) { 25484 if ((fsm_ptr->flags & _FP_GROUP_CONFIG_VALIDATE)) { 25485 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 25486 } else { 25487 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE; 25488 } 25489 } else { 25490 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 25491 } 25492 } 25493 } 25494 25495 /* Set current state to be previous state. */ 25496 fsm_ptr->fsm_state_prev = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25497 25498 return _bcm_field_group_add(unit, fsm_ptr); 25499 } 25500 25501 25502 /* 25503 * Function: 25504 * _field_group_add_qset_alternate 25505 * Purpose: 25506 * Update application requested qset with equivalent one 25507 * which might allow to select F1, F2 Fn select codes. 25508 * Parameters: 25509 * unit - (IN) BCM device number. 25510 * fsm_ptr - (IN/OUT) State machine tracking structure. 25511 * Returns: 25512 * BCM_E_XXX 25513 */ 25514 STATIC int 25515 _field_group_add_qset_alternate(int unit, _field_group_add_fsm_t *fsm_ptr) 25516 { 25517 /* Input parameters check. */ 25518 if (NULL == fsm_ptr) { 25519 return (BCM_E_PARAM); 25520 } 25521 25522 /* Set current state to be previous state. */ 25523 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 25524 25525 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 25526 if ((SOC_IS_FIREBOLT2(unit) || SOC_IS_HAWKEYE(unit)) 25527 && (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifyTtl))) { 25528 25529 BCM_FIELD_QSET_REMOVE(fsm_ptr->fg->qset, bcmFieldQualifyTtl); 25530 if (SOC_IS_FIREBOLT2(unit)) { 25531 fsm_ptr->flags |= _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY; 25532 } 25533 25534 /* Proceed to a second attempt of select codes selection. */ 25535 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25536 } else 25537 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAPTOR_SUPPORT */ 25538 #ifdef BCM_TRIUMPH2_SUPPORT 25539 if (soc_feature(unit, soc_feature_mim)) { 25540 /* Proceed to a second attempt of select codes selection. */ 25541 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25542 } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcMplsGport)) { 25543 /* Proceed to a second attempt of select codes selection. */ 25544 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25545 } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcNivGport)) { 25546 /* Proceed to a second attempt of select codes selection. */ 25547 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25548 } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcVxlanGport)) { 25549 /* Proceed to a second attempt of select codes selection. */ 25550 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25551 } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcVlanGport)) { 25552 /* Proceed to a second attempt of select codes selection. */ 25553 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25554 } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcGport)) { 25555 /* Proceed to a second attempt of select codes selection. */ 25556 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25557 } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcGports)) { 25558 /* Proceed to a second attempt of select codes selection. */ 25559 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 25560 } else 25561 #endif 25562 { 25563 fsm_ptr->rv = (BCM_E_RESOURCE); 25564 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 25565 } 25566 return _bcm_field_group_add(unit, fsm_ptr); 25567 } 25568 25569 /* 25570 * Function: 25571 * _field_group_add_end 25572 * Purpose: 25573 * Group add state machine last /clean up state. 25574 * Parameters: 25575 * unit - (IN) BCM device number. 25576 * fsm_ptr - (IN/OUT) State machine tracking structure. 25577 * Returns: 25578 * BCM_E_XXX 25579 */ 25580 STATIC int 25581 _field_group_add_end(int unit, _field_group_add_fsm_t *fsm_ptr) 25582 { 25583 /* Input parameters check. */ 25584 if (NULL == fsm_ptr) { 25585 return (BCM_E_PARAM); 25586 } 25587 25588 if (BCM_FAILURE(fsm_ptr->rv) 25589 || BCM_FAILURE(fsm_ptr->rv = _field_group_default_aset_set(unit, fsm_ptr->fg)) 25590 ) { 25591 _field_group_deinit(unit, fsm_ptr->fg); 25592 } 25593 25594 return (fsm_ptr->rv); 25595 } 25596 25597 /* 25598 * Function: _bcm_field_group_add 25599 * 25600 * Purpose: 25601 * Create a field processor group 25602 * Parameters: 25603 * unit - (IN) BCM device number. 25604 * fsm_ptr - (IN/OUT) State machine tracking structure. 25605 * Returns: 25606 * BCM_E_XXX. 25607 */ 25608 int 25609 _bcm_field_group_add(int unit, _field_group_add_fsm_t *fsm_ptr) 25610 { 25611 int rv; /* Operation return status. */ 25612 /* Group add fsm state names. */ 25613 #if defined(BROADCOM_DEBUG) 25614 static char *_bcm_fp_group_add_state[bcmFieldQualifyCount] = \ 25615 _BCM_FP_GROUP_ADD_STATE_STRINGS; 25616 #endif /* BROADCOM_DEBUG */ 25617 25618 /* Input parameters check. */ 25619 if (NULL == fsm_ptr) { 25620 return (BCM_E_PARAM); 25621 } 25622 25623 rv = (BCM_E_NONE); 25624 25625 #if defined(BROADCOM_DEBUG) 25626 LOG_DEBUG(BSL_LS_BCM_FP, 25627 (BSL_META_U(unit, 25628 "FP(unit %d) vverb: group add: state (%s) state_prev (%s) status (%d).\n"), 25629 unit, 25630 _bcm_fp_group_add_state[fsm_ptr->fsm_state], 25631 _bcm_fp_group_add_state[fsm_ptr->fsm_state_prev], 25632 fsm_ptr->rv)); 25633 #endif /* BROADCOM_DEBUG */ 25634 25635 /* Run through group creation states. */ 25636 switch (fsm_ptr->fsm_state) { 25637 case _BCM_FP_GROUP_ADD_STATE_START: 25638 rv = _field_group_add_initialize(unit, fsm_ptr); 25639 break; 25640 25641 case _BCM_FP_GROUP_ADD_STATE_ALLOC: 25642 rv = _field_group_add_alloc(unit, fsm_ptr); 25643 break; 25644 25645 case _BCM_FP_GROUP_ADD_STATE_QSET_UPDATE: 25646 rv = _field_group_add_qset_update(unit, fsm_ptr); 25647 break; 25648 25649 case _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET: 25650 rv = _field_group_add_sel_codes_get(unit, fsm_ptr); 25651 break; 25652 25653 case _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE: 25654 rv = _field_group_add_qset_alternate(unit, fsm_ptr); 25655 break; 25656 25657 case _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE: 25658 rv = _field_group_add_slice_allocate(unit, fsm_ptr); 25659 break; 25660 25661 case _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS: 25662 rv = _field_group_add_cam_compress(unit, fsm_ptr); 25663 break; 25664 case _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN: 25665 rv = _field_group_add_slice_align(unit, fsm_ptr); 25666 break; 25667 case _BCM_FP_GROUP_ADD_STATE_HW_QUAL_LIST_GET: 25668 rv = _field_group_add_hw_qual_list_get(unit, fsm_ptr); 25669 break; 25670 25671 case _BCM_FP_GROUP_ADD_STATE_UDF_UPDATE: 25672 rv = _field_group_add_udf_update(unit, fsm_ptr); 25673 break; 25674 25675 case _BCM_FP_GROUP_ADD_STATE_ADJUST_VIRTUAL_MAP: 25676 rv = _field_group_add_adjust_virtual_map(unit, fsm_ptr); 25677 break; 25678 25679 case _BCM_FP_GROUP_ADD_STATE_END: 25680 rv = _field_group_add_end(unit, fsm_ptr); 25681 break; 25682 25683 } 25684 return (rv); 25685 } 25686 25687 /* 25688 * Function: 25689 * _bcm_field_entries_free_get 25690 * 25691 * Purpose: 25692 * Return the number of free entries in a slice. 25693 * 25694 * Parameters: 25695 * unit - (IN) BCM device number. 25696 * fs - (IN) Slice to count free entries in. 25697 * fg - (IN) Group (for checking the INTRASLICE-DW flag) 25698 * free_cnt - (OUT)Count of unused entries. 25699 * 25700 * Returns: 25701 * BCM_E_XXX 25702 * 25703 * Notes: 25704 * Assumes all groups in a slice have the same mode (regular/INTRASLICE-DW) 25705 */ 25706 int 25707 _bcm_field_entries_free_get(int unit, _field_slice_t *fs, 25708 _field_group_t *fg, int *free_cnt) 25709 { 25710 /* Input parameters check. */ 25711 if ((NULL == fs) || (NULL == free_cnt)) { 25712 return (BCM_E_PARAM); 25713 } 25714 25715 /* Initialization check. */ 25716 FIELD_IS_INIT(unit); 25717 25718 #if defined(BCM_FLOWTRACKER_SUPPORT) 25719 if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 25720 return _field_hx5_ft_entries_free_get(unit, fs, fg, free_cnt); 25721 } 25722 #endif 25723 25724 *free_cnt = fs->free_count; 25725 return (BCM_E_NONE); 25726 } 25727 25728 /* 25729 * Function: 25730 * _bcm_field_counters_total_get 25731 * 25732 * Purpose: 25733 * Report total number of counters available. 25734 * 25735 * Parameters: 25736 * stage_fc - (IN) Stage field control structure. 25737 * fs - (IN) Slice to count the total counters. 25738 * 25739 * Returns: 25740 * Number of unused counters in slice. 25741 */ 25742 int 25743 _bcm_field_counters_total_get(const _field_stage_t *stage_fc, 25744 const _field_slice_t *fs) 25745 { 25746 int total_count = 0; 25747 /* Input parameters check. */ 25748 if ((NULL == fs) || (NULL == stage_fc)) { 25749 return (BCM_E_PARAM); 25750 } 25751 25752 if (fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 25753 /* 25754 * There is an 1-1 mapping between rules and counters 25755 * for external FP. So, total number of counters is equal 25756 * to number of entries on that slice. 25757 */ 25758 return fs->entry_count; 25759 } else { 25760 if (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) { 25761 int i; 25762 for (i = 0; i < stage_fc->num_cntr_pools; i++) { 25763 total_count += stage_fc->cntr_pool[i]->size; 25764 } 25765 return total_count; 25766 } 25767 return fs->counters_count; 25768 } 25769 } 25770 25771 /* 25772 * Function: 25773 * _bcm_field_counter_free_get 25774 * 25775 * Purpose: 25776 * Report the number of unused counter pairs in a slice. 25777 * 25778 * Parameters: 25779 * stage_fc - (IN) Stage field control structure. 25780 * fs - (IN) Slice to count free counters in. 25781 * 25782 * Returns: 25783 * Number of unused counters in slice. 25784 */ 25785 int 25786 _bcm_field_counter_free_get(const _field_stage_t *stage_fc, 25787 const _field_slice_t *fs) 25788 { 25789 int counter; 25790 int free_count = 0; 25791 25792 /* Input parameters check. */ 25793 if ((NULL == fs) || (NULL == stage_fc)) { 25794 return (BCM_E_PARAM); 25795 } 25796 25797 if (fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 25798 return fs->free_count; 25799 } 25800 if (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) { 25801 int i; 25802 for (i = 0; i < stage_fc->num_cntr_pools; i++) { 25803 free_count += stage_fc->cntr_pool[i]->free_cntrs; 25804 } 25805 return free_count; 25806 } 25807 25808 /* Count unused counters. */ 25809 for (counter = 0; counter < fs->counters_count; counter++) { 25810 if (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, counter)) { 25811 free_count++; 25812 } 25813 } 25814 return free_count; 25815 } 25816 25817 /* 25818 * Function: 25819 * _bcm_field_meters_total_get 25820 * 25821 * Purpose: 25822 * Return total number of meters/meter pairs on device. 25823 * 25824 * Parameters: 25825 * stage_fc - (IN) Stage field control structure. 25826 * instance - (IN) Pipe Instance. 25827 * fs - (IN) Slice to count number of meters. 25828 * 25829 * Returns: 25830 * Total number of meters/meter pairs on device. 25831 */ 25832 int 25833 _bcm_field_meters_total_get(const _field_stage_t *stage_fc, int instance, 25834 const _field_slice_t *fs) 25835 { 25836 int numb_meters = 0; 25837 25838 /* Input parameters check. */ 25839 if ((NULL == fs) || (NULL == stage_fc)) { 25840 return (BCM_E_PARAM); 25841 } 25842 25843 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 25844 int i; 25845 for (i = 0; i < stage_fc->num_meter_pools; i++) { 25846 numb_meters += stage_fc->meter_pool[instance][i]->size; 25847 } 25848 return numb_meters; 25849 } else { 25850 return fs->meters_count; 25851 } 25852 } 25853 25854 /* 25855 * Function: 25856 * _bcm_field_meter_free_get 25857 * 25858 * Purpose: 25859 * Fill in the values of a group status struct. 25860 * 25861 * Parameters: 25862 * stage_fc - (IN) Stage field control structure. 25863 * fg - (IN) field group structure. 25864 * fs - (IN) Slice to count free counters in. 25865 * 25866 * Returns: 25867 * Number of unused meters in slice. 25868 */ 25869 int 25870 _bcm_field_meter_free_get(const _field_stage_t *stage_fc, const 25871 _field_group_t *fg, const _field_slice_t *fs) 25872 { 25873 int meter; 25874 int numb_meters = 0; 25875 int slice_id; 25876 25877 /* Input parameters check. */ 25878 if ((NULL == fs) || (NULL == stage_fc)) { 25879 return (BCM_E_PARAM); 25880 } 25881 25882 /* For stages ExactMatch and External meter pool slice id is 25883 equal to tcam slices */ 25884 if ((_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) || 25885 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) { 25886 slice_id = stage_fc->tcam_slices; 25887 } else { 25888 slice_id = fs->slice_number; 25889 } 25890 25891 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 25892 int i; 25893 for (i = 0; i < stage_fc->num_meter_pools; i++) { 25894 _field_meter_pool_t *mp = stage_fc->meter_pool[fg->instance][i]; 25895 25896 if (mp->slice_id == slice_id /* Pool belongs to slice */ 25897 || mp->slice_id == _FP_INVALID_INDEX /* Pool is unallocated */ 25898 ) { 25899 numb_meters += mp->free_meters; 25900 } 25901 } 25902 return numb_meters; 25903 } 25904 25905 for (meter = 0; meter < fs->meters_count; meter++) { 25906 if (_FP_METER_BMP_TEST(fs->meter_bmp, meter)) { 25907 numb_meters++; 25908 } 25909 } 25910 return fs->meters_count - numb_meters; 25911 } 25912 25913 25914 /* 25915 * Function: 25916 * _field_udf_usecount_update 25917 * 25918 * Purpose: 25919 * Increment the use-counts of any new UDFs. 25920 * 25921 * Parameters: 25922 * udf - Unit's control array of UDFs 25923 * qset_old - Previous Qset 25924 * qset_new - New Qset 25925 * 25926 * Returns: 25927 * nothing 25928 */ 25929 void 25930 _field_udf_usecount_update(_field_udf_t *udf, 25931 bcm_field_qset_t *qset_old, 25932 bcm_field_qset_t *qset_new) 25933 { 25934 int idx_new; 25935 25936 /* For all UDFs in new Qset. */ 25937 for (idx_new = 0; idx_new < BCM_FIELD_USER_NUM_UDFS; idx_new++) { 25938 if (!SHR_BITGET(qset_new->udf_map, idx_new)) { 25939 continue; 25940 } 25941 25942 /* If UDF is in new Qset but not in old Qset, increment use-count. */ 25943 if (!SHR_BITGET(qset_old->udf_map, idx_new)) { 25944 udf[idx_new].use_count++; 25945 } 25946 } 25947 } 25948 25949 /* 25950 * Function: _field_fb_entries_enable_set 25951 * 25952 * Purpose: 25953 * Enable/disable the lookup of entries of a group 25954 * 25955 * Parameters: 25956 * unit - BCM device number 25957 * fg - Group the entry belongs to 25958 * fs - Slice the entry is present in 25959 * enable - lookup enable!=0/disable==0 state of group 25960 * 25961 * Returns: 25962 * BCM_E_NONE - Success 25963 * BCM_E_XXX - BCM error codes 25964 * 25965 * Note: 25966 * For Intraslice-dw (FB2), we run over entries in both half's. 25967 * 25968 * A group may be spanning multiple slices 25969 * (due to group autoexpansion) 25970 */ 25971 int 25972 _field_fb_entries_enable_set(int unit, _field_group_t *fg, 25973 _field_slice_t *fs, int enable) 25974 { 25975 _field_stage_t *stage_fc; 25976 soc_mem_t mem = INVALIDm; 25977 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 25978 int index, i; 25979 25980 /* External stage entries are always enabled */ 25981 if (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) { 25982 return (BCM_E_NONE); 25983 } 25984 25985 BCM_IF_ERROR_RETURN 25986 (_field_stage_control_get(unit, fg->stage_id, &stage_fc)); 25987 25988 if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 25989 mem = FP_TCAMm; 25990 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 25991 } else if (soc_feature(unit, soc_feature_field_multi_stage)) { 25992 if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) { 25993 mem = VFP_TCAMm; 25994 } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) { 25995 mem = EFP_TCAMm; 25996 } else { 25997 return (BCM_E_INTERNAL); 25998 } 25999 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 26000 } else { 26001 return BCM_E_INTERNAL; 26002 } 26003 26004 while (fs->next != NULL) { 26005 fs = fs->next; 26006 } 26007 26008 while (fs != NULL) { 26009 for (i = fs->entry_count - 1; i >= 0; i--) { 26010 if (fs->entries[i] != NULL) { 26011 if (fs->entries[i]->group->gid == fg->gid) { 26012 BCM_IF_ERROR_RETURN( 26013 _bcm_field_entry_tcam_idx_get(unit, fs->entries[i], &index)); 26014 /* Read tcam entry from index. */ 26015 SOC_IF_ERROR_RETURN 26016 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, e)); 26017 26018 /* Set the VALIDf bits appropriately, VALIDf in VFP_TCAM on TH2 only has one bit*/ 26019 #if defined(BCM_TOMAHAWK2_SUPPORT) 26020 if (soc_feature(unit, soc_feature_field_multi_pipe_enhanced) && 26021 _BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) { 26022 soc_mem_field32_set(unit, mem, e, VALIDf, enable? 1 : 0); 26023 } else 26024 #endif /* BCM_TOMAHAWK2_SUPPORT */ 26025 { 26026 if (enable) { 26027 if (fs->entries[i]->flags & _FP_ENTRY_INSTALLED) { 26028 #if defined(BCM_TOMAHAWK3_SUPPORT) 26029 if (SOC_IS_TOMAHAWK3(unit) && 26030 ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) || 26031 (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP))) { 26032 soc_mem_field32_set(unit, mem, e, VALIDf, 1); 26033 } else 26034 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26035 { 26036 soc_mem_field32_set(unit, mem, e, VALIDf, 3); 26037 } 26038 26039 } else { 26040 soc_mem_field32_set(unit, mem, e, VALIDf, 0); 26041 } 26042 } else { 26043 #if defined(BCM_TOMAHAWK3_SUPPORT) 26044 if (SOC_IS_TOMAHAWK3(unit) && 26045 ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) || 26046 (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP))) { 26047 26048 soc_mem_field32_set(unit, mem, e, VALIDf, 0); 26049 } else 26050 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26051 { 26052 soc_mem_field32_set(unit, mem, e, VALIDf, 2); 26053 } 26054 } 26055 } 26056 26057 /* Write back the TCAM entry */ 26058 SOC_IF_ERROR_RETURN 26059 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, e)); 26060 } 26061 } 26062 } 26063 fs = fs->prev; 26064 } 26065 26066 if (enable) { 26067 fg->flags |= _FP_GROUP_LOOKUP_ENABLED; 26068 } else { 26069 fg->flags &= ~_FP_GROUP_LOOKUP_ENABLED; 26070 } 26071 26072 return BCM_E_NONE; 26073 } 26074 26075 /* 26076 * Function: _field_range_flags_check 26077 * 26078 * Purpose: 26079 * Sanity check on range flags. 26080 * 26081 * Parameters: 26082 * unit - (IN) BCM device number. 26083 * flags - (IN) One or more of BCM_FIELD_RANGE_* flags. 26084 * 26085 * Returns: 26086 * BCM_E_XXX - Flags are valid & supported. 26087 */ 26088 int 26089 _field_range_flags_check(int unit, uint32 flags) 26090 { 26091 int cntr; /* Range types counter. */ 26092 26093 /* ESW family of devices do not support range check in lookup stage */ 26094 if (flags & BCM_FIELD_RANGE_LOOKUP) { 26095 return (BCM_E_UNAVAIL); 26096 } 26097 26098 /* Make sure only one range was selected. */ 26099 cntr = 0; 26100 if (flags & BCM_FIELD_RANGE_SRCPORT) { 26101 cntr++; 26102 } 26103 if (flags & BCM_FIELD_RANGE_DSTPORT) { 26104 cntr++; 26105 } 26106 if (flags & BCM_FIELD_RANGE_OUTER_VLAN) { 26107 cntr++; 26108 } 26109 if (flags & BCM_FIELD_RANGE_PACKET_LENGTH) { 26110 cntr++; 26111 } 26112 if (cntr > 1) { 26113 return (BCM_E_PARAM); 26114 } 26115 26116 /* Outer vlan & packet length ranges supported by trx devices only.*/ 26117 if ((flags & BCM_FIELD_RANGE_OUTER_VLAN) || 26118 (flags & BCM_FIELD_RANGE_PACKET_LENGTH)) { 26119 if (0 == SOC_IS_TRX(unit)) { 26120 return (BCM_E_UNAVAIL); 26121 } 26122 } 26123 26124 /* Range TCP/UDP/Invert supported on 5660x devices only. */ 26125 if (flags & (BCM_FIELD_RANGE_TCP | 26126 BCM_FIELD_RANGE_UDP | 26127 BCM_FIELD_RANGE_INVERT)) { 26128 return (BCM_E_UNAVAIL); 26129 } 26130 return (BCM_E_NONE); 26131 } 26132 26133 26134 /* 26135 * Function: _field_range_create 26136 * 26137 * Purpose: 26138 * Create field range object. 26139 * 26140 * Parameters: 26141 * unit - (IN) BCM device number. 26142 * 26143 * Returns: 26144 * BCM_E_XXX 26145 */ 26146 int 26147 _field_range_create(int unit, bcm_field_range_t *range, 26148 uint32 flags, bcm_l4_port_t min, 26149 bcm_l4_port_t max, bcm_if_group_t group) 26150 { 26151 _field_stage_t *stage_fc; 26152 int rv; 26153 26154 if (flags & BCM_FIELD_RANGE_EXTERNAL) { 26155 BCM_IF_ERROR_RETURN 26156 (_field_stage_control_get(unit, _BCM_FIELD_STAGE_EXTERNAL, 26157 &stage_fc)); 26158 } else { 26159 BCM_IF_ERROR_RETURN 26160 (_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, 26161 &stage_fc)); 26162 } 26163 26164 for (;;) { 26165 if (group == -1) { 26166 rv = bcm_esw_field_range_create_id(unit, stage_fc->range_id, 26167 flags, min, max); 26168 } else { 26169 rv = bcm_esw_field_range_group_create_id(unit, stage_fc->range_id, 26170 flags, min, max, group); 26171 } 26172 26173 if (rv != BCM_E_EXISTS) { 26174 break; 26175 } 26176 26177 if (++stage_fc->range_id == 0) { 26178 stage_fc->range_id = 1; 26179 } 26180 } 26181 26182 if (BCM_SUCCESS(rv)) { 26183 *range = stage_fc->range_id; 26184 26185 if (++stage_fc->range_id == 0) { 26186 stage_fc->range_id = 1; 26187 } 26188 } 26189 return rv; 26190 } 26191 26192 /* 26193 * Function: 26194 * _field_fb_er_range_check_set 26195 * Purpose: 26196 * Write the group's range checking parameters into the FP_RANGE_CHECK 26197 * memory. 26198 * Parameters: 26199 * unit - BCM unit 26200 * range - Range HW index 26201 * flags - One of more of the BCM_FIELD_RANGE_* flags 26202 * enable - TRUE or FALSE 26203 * min - Lower bounds of port range to be checked 26204 * max - Upper bounds of port range to be checked 26205 * Returns: 26206 * BCM_E_NONE 26207 * BCM_E_PARAM - Unrecognized flag. 26208 * Notes: 26209 * Calling function should have unit's lock. 26210 */ 26211 int 26212 _field_fb_er_range_check_set(int unit, int range, uint32 flags, int enable, 26213 bcm_l4_port_t min, bcm_l4_port_t max) 26214 { 26215 fp_range_check_entry_t tbl_entry; 26216 uint32 src_chk = 0; 26217 26218 assert(soc_mem_index_valid(unit, FP_RANGE_CHECKm, range)); 26219 26220 if (enable) { 26221 switch (flags & (BCM_FIELD_RANGE_SRCPORT | BCM_FIELD_RANGE_DSTPORT)) { 26222 case BCM_FIELD_RANGE_SRCPORT: 26223 src_chk = 1; 26224 break; 26225 case BCM_FIELD_RANGE_DSTPORT: 26226 break; 26227 default: 26228 LOG_ERROR(BSL_LS_BCM_FP, 26229 (BSL_META_U(unit, 26230 "FP(unit %d) Error: unsupported flags %#x\n"), 26231 unit, flags)); 26232 return (BCM_E_PARAM); 26233 } 26234 } 26235 26236 /* read/modify/write range check memory */ 26237 SOC_IF_ERROR_RETURN(READ_FP_RANGE_CHECKm(unit, MEM_BLOCK_ANY, 26238 range, &tbl_entry)); 26239 26240 soc_FP_RANGE_CHECKm_field32_set(unit, &tbl_entry, 26241 SOURCE_DESTINATION_SELECTf, src_chk); 26242 soc_FP_RANGE_CHECKm_field32_set(unit, &tbl_entry, ENABLEf, enable); 26243 soc_FP_RANGE_CHECKm_field32_set(unit, &tbl_entry, LOWER_BOUNDSf, min); 26244 soc_FP_RANGE_CHECKm_field32_set(unit, &tbl_entry, UPPER_BOUNDSf, max); 26245 26246 SOC_IF_ERROR_RETURN(WRITE_FP_RANGE_CHECKm(unit, MEM_BLOCK_ALL, 26247 range, &tbl_entry)); 26248 26249 return (BCM_E_NONE); 26250 } 26251 26252 /* 26253 * Function: 26254 * _bcm_field_modify_range_checker 26255 * Purpose: 26256 * Modify the configurations of an existing range checker. 26257 * Parameters: 26258 * unit - (IN) BCM device number. 26259 * stage_id - (IN) Pipeline stage id. 26260 * range_id - (IN) Range check ID to use. 26261 * flags - (IN) Range checker type to be set. 26262 * min - (IN) Lower bounds of range to be checked, inclusive. 26263 * max - (IN) Upper bounds of range to be checked, inclusive. 26264 * Returns: 26265 * BCM_E_NOT_FOUND - Range Check id to be modified does not exist. 26266 * BCM_E_NONE - Success. 26267 * Notes: 26268 * Calling function should have unit's lock. 26269 */ 26270 26271 int _bcm_field_modify_range_checker(int unit, _field_stage_id_t stage_id, 26272 int range_id, uint32 flags, 26273 bcm_l4_port_t min, bcm_l4_port_t max) 26274 { 26275 _field_stage_t *stage_fc; /* Stage field control info.*/ 26276 _field_range_t *fr; /* Field range info. */ 26277 int rv; /* Operation return value. */ 26278 26279 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 26280 if (BCM_FAILURE(rv)) { 26281 return rv; 26282 } 26283 26284 for (fr = stage_fc->ranges; fr != NULL; fr = fr->next) { 26285 if (fr->rid == range_id) { 26286 /* Try to program hardware */ 26287 #if defined(BCM_TRX_SUPPORT) 26288 if (SOC_IS_TRX(unit)) { 26289 rv = _bcm_field_trx_range_check_set(unit, fr->hw_index, 26290 flags, 1, min, max); 26291 } else 26292 #endif /* BCM_TRX_SUPPORT */ 26293 { 26294 rv = _field_fb_er_range_check_set(unit, fr->hw_index, 26295 flags, 1, min, max); 26296 } 26297 return rv; 26298 } 26299 } 26300 26301 return BCM_E_NOT_FOUND; 26302 } 26303 26304 /* 26305 * Function: _field_fill_slice_array 26306 * 26307 * Purpose: 26308 * Based on GroupAutoExpansion Flags and MaxGroupSize 26309 * Fill the slice_array with slice ids. 26310 * 26311 * Parameters: 26312 * unit - (IN) BCM device number 26313 * fg - (IN) field group 26314 * slice_array - (INOUT) Array where the slice ids will be filled. 26315 * 26316 * Returns: 26317 * BCM_E_xxx 26318 */ 26319 int _field_fill_slice_array (int unit, _field_group_t *fg, uint8 *slice_array) 26320 { 26321 _field_control_t *fc; /* Field control structure. */ 26322 _field_stage_t *stage_fc; /* Field stage control. */ 26323 int rv = 0; /* Operation return status. */ 26324 int slice_index = 0; /* Slice Index */ 26325 uint8 idx = 0; /* Slice Index */ 26326 int8 autoexpand_hints_set = -1; /* Check AutoExpansion Flag is set*/ 26327 uint16 small_slice_size = 0; /* Small Slice Size */ 26328 uint8 prioritize_large_slice = 0; /* Prioritize large entries */ 26329 int remaining_entries = 0; /* Remaining allowed entries in a group */ 26330 26331 if (NULL == slice_array) { 26332 return BCM_E_PARAM; 26333 } 26334 26335 /* Get field control structure. */ 26336 rv = _field_control_get(unit, &fc); 26337 BCM_IF_ERROR_RETURN(rv); 26338 26339 /* Get stage field control structure. */ 26340 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 26341 BCM_IF_ERROR_RETURN(rv); 26342 26343 /* AutoExpansion Hints Flags supported only for Ingress Stage */ 26344 if ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) 26345 || (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 26346 return BCM_E_NONE; 26347 } 26348 26349 /* AutoExpansion Hints Flags supported only for Ingress Stage which 26350 * has two slice types */ 26351 if (soc_feature(unit, soc_feature_field_ingress_two_slice_types) == 0) { 26352 return BCM_E_NONE; 26353 } 26354 26355 /* If both autoexpansion hint flags specified or both not specified 26356 * it means autoexpansion is not set */ 26357 if ((fg->flags & _FP_GROUP_AUTO_EXPAND_SMALL_SLICE) 26358 && (fg->flags & _FP_GROUP_AUTO_EXPAND_LARGE_SLICE)) { 26359 autoexpand_hints_set = 0; 26360 } 26361 26362 if (((fg->flags & _FP_GROUP_AUTO_EXPAND_SMALL_SLICE) == 0) 26363 && ((fg->flags & _FP_GROUP_AUTO_EXPAND_LARGE_SLICE) == 0)) { 26364 autoexpand_hints_set = 0; 26365 } 26366 26367 /* If AutoExpansion hints not set and maxGroupSize not specified 26368 * Slice allocation will follow default pattern */ 26369 if ((autoexpand_hints_set == 0) && (fg->max_group_size == 0)) { 26370 return BCM_E_NONE; 26371 } 26372 26373 for (slice_index = 0; 26374 slice_index < stage_fc->tcam_slices; slice_index++) { 26375 if (stage_fc->slices[fg->instance][slice_index].slice_flags & 26376 _BCM_FIELD_SLICE_SIZE_SMALL) { 26377 small_slice_size = 26378 stage_fc->slices[fg->instance][slice_index].entry_count; 26379 break; 26380 } 26381 } 26382 26383 if (autoexpand_hints_set == 0) { 26384 remaining_entries = fg->max_group_size - (fg->group_status.entry_count); 26385 if (remaining_entries <= 0) { 26386 /* Falling back to default slice allocation pattern */ 26387 return BCM_E_NONE; 26388 } else { 26389 if (remaining_entries <= small_slice_size) { 26390 prioritize_large_slice = 0; 26391 } else { 26392 prioritize_large_slice = 1; 26393 } 26394 } 26395 } else if (fg->flags & _FP_GROUP_AUTO_EXPAND_SMALL_SLICE) { 26396 prioritize_large_slice = 0; 26397 }else if (fg->flags & _FP_GROUP_AUTO_EXPAND_LARGE_SLICE) { 26398 prioritize_large_slice = 1; 26399 } 26400 26401 if (prioritize_large_slice) { 26402 while (idx < stage_fc->tcam_slices) { 26403 for (slice_index = 0; 26404 slice_index < stage_fc->tcam_slices; slice_index++) { 26405 if (stage_fc->slices[fg->instance][slice_index].slice_flags & 26406 _BCM_FIELD_SLICE_SIZE_LARGE) { 26407 slice_array[idx] = slice_index; 26408 idx++; 26409 } 26410 } 26411 for (slice_index = 0; 26412 slice_index < stage_fc->tcam_slices; slice_index++) { 26413 if (stage_fc->slices[fg->instance][slice_index].slice_flags & 26414 _BCM_FIELD_SLICE_SIZE_SMALL) { 26415 slice_array[idx] = slice_index; 26416 idx++; 26417 } 26418 } 26419 } 26420 } else { 26421 while (idx < stage_fc->tcam_slices) { 26422 for (slice_index = 0; 26423 slice_index < stage_fc->tcam_slices; slice_index++) { 26424 if (stage_fc->slices[fg->instance][slice_index].slice_flags & 26425 _BCM_FIELD_SLICE_SIZE_SMALL) { 26426 slice_array[idx] = slice_index; 26427 idx++; 26428 } 26429 } 26430 for (slice_index = 0; 26431 slice_index < stage_fc->tcam_slices; slice_index++) { 26432 if (stage_fc->slices[fg->instance][slice_index].slice_flags & 26433 _BCM_FIELD_SLICE_SIZE_LARGE) { 26434 slice_array[idx] = slice_index; 26435 idx++; 26436 } 26437 } 26438 } 26439 } 26440 26441 return BCM_E_NONE; 26442 } 26443 26444 /* 26445 * Function: _field_find_empty_slice 26446 * 26447 * Purpose: 26448 * Get a new slice for an existing group if available. 26449 * Used for auto-expansion of groups 26450 * Currently: supported in Raptor, Firebolt2. 26451 * 26452 * Parameters: 26453 * unit - BCM device number 26454 * fg - field group 26455 * fs_ptr - _field_slice_t for the PRIMARY if there is one available. 26456 * 26457 * Returns: 26458 * BCM_E_xxx 26459 * 26460 * Notes: 26461 * Need to change the array size (16) for devices which support 26462 * more slices, and correspondingly change the map arrays in 26463 * bcm_int/esw/field.h 26464 */ 26465 STATIC int 26466 _field_find_empty_slice(int unit, _field_group_t *fg, _field_slice_t **fs_ptr) 26467 { 26468 _field_control_t *fc; /* Field control structure. */ 26469 _field_stage_t *stage_fc; /* Field stage control. */ 26470 _field_slice_t *fs; /* Field slice pointer. */ 26471 uint8 slice_number; /* Slice iterator. */ 26472 int parts_count = 0; /* Number of entry parts. */ 26473 uint32 entry_flags; /* Field entry part flags. */ 26474 int rv; /* Operation return status. */ 26475 int part_index; /* Tcam Part Index */ 26476 int slice_index; /* Slice Index */ 26477 uint8 old_physical_slice; /* Last slice in group. */ 26478 uint8 new_physical_slice; /* Allocated slice. */ 26479 bcm_pbmp_t all_pbmp; /* Port bitmap */ 26480 uint8 *slice_array = NULL; /* Array containing slice ids */ 26481 int virtual_priority = FALSE;/* Virtual priority support flag.*/ 26482 26483 /* Get field control structure. */ 26484 rv = _field_control_get(unit, &fc); 26485 BCM_IF_ERROR_RETURN(rv); 26486 26487 BCM_PBMP_CLEAR(all_pbmp); 26488 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 26489 26490 /* Get stage field control structure. */ 26491 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 26492 BCM_IF_ERROR_RETURN(rv); 26493 26494 if (0 == (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION)) { 26495 return (BCM_E_RESOURCE); 26496 } 26497 26498 fs = &fg->slices[0]; 26499 while (fs->next != NULL) { 26500 fs = fs->next; 26501 } 26502 old_physical_slice = fs->slice_number; 26503 26504 _FP_XGS3_ALLOC(slice_array, sizeof(uint8) * stage_fc->tcam_slices, 26505 "Slice Array"); 26506 if (NULL == slice_array) { 26507 return BCM_E_MEMORY; 26508 } 26509 26510 for (slice_index = 0; slice_index < stage_fc->tcam_slices; slice_index++) { 26511 slice_array[slice_index] = slice_index; 26512 } 26513 26514 rv = _field_fill_slice_array (unit, fg, slice_array); 26515 if (rv != BCM_E_NONE) { 26516 sal_free (slice_array); 26517 slice_array = NULL; 26518 return rv; 26519 } 26520 26521 /* 26522 * Find an empty slice 26523 * Validate the ports and mode 26524 */ 26525 for (slice_index = 0; slice_index < stage_fc->tcam_slices; slice_index++) { 26526 if (slice_index == old_physical_slice) { 26527 continue; 26528 } 26529 rv = _field_group_ports_validate(unit, stage_fc, fg->instance, 26530 slice_array[slice_index], 26531 fg->flags, all_pbmp); 26532 if (BCM_SUCCESS(rv)) { 26533 break; 26534 } 26535 } 26536 26537 if (slice_index == stage_fc->tcam_slices) { 26538 /* No free slice; attempt to compress existing auto expanded groups. */ 26539 rv = _field_stage_groups_compress(unit, fc, stage_fc); 26540 if (rv != BCM_E_NONE) { 26541 sal_free (slice_array); 26542 slice_array = NULL; 26543 return rv; 26544 } 26545 26546 /* Retry slice allocation. */ 26547 for (slice_index = 0; slice_index < stage_fc->tcam_slices; 26548 slice_index++) { 26549 rv = _field_group_ports_validate(unit, stage_fc, fg->instance, 26550 slice_array[slice_index], fg->flags, 26551 all_pbmp); 26552 if (BCM_SUCCESS(rv)) { 26553 break; 26554 } 26555 } 26556 } 26557 26558 if (slice_index == stage_fc->tcam_slices) 26559 { 26560 /* No free slice */ 26561 sal_free (slice_array); 26562 slice_array = NULL; 26563 return (BCM_E_RESOURCE); 26564 } 26565 26566 new_physical_slice = slice_array[slice_index]; 26567 sal_free (slice_array); 26568 slice_array = NULL; 26569 26570 _field_virtual_priority_support(unit, stage_fc, &virtual_priority); 26571 26572 /* Remove original group from the map. */ 26573 if (virtual_priority) { 26574 rv = _field_group_vmap_delete(unit, stage_fc, fg, FALSE); 26575 BCM_IF_ERROR_RETURN(rv); 26576 } 26577 26578 /* Get number of entry parts for the group. */ 26579 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, fg->flags, &parts_count); 26580 BCM_IF_ERROR_RETURN(rv); 26581 26582 26583 /* Set up the new physical slice parameters in Software */ 26584 for(part_index = parts_count - 1; part_index >= 0; part_index--) { 26585 /* Get entry flags. */ 26586 rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, fg, 26587 &entry_flags); 26588 BCM_IF_ERROR_RETURN(rv); 26589 26590 /* Get slice id for entry part */ 26591 rv = _bcm_field_tcam_part_to_slice_number(unit, part_index, fg, 26592 &slice_number); 26593 BCM_IF_ERROR_RETURN(rv); 26594 26595 /* Get slice pointer. */ 26596 fs = stage_fc->slices[fg->instance] + new_physical_slice 26597 + slice_number; 26598 26599 /* Enable slice. */ 26600 if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) { 26601 BCM_IF_ERROR_RETURN 26602 (_field_slice_enable_set(unit, stage_fc, fg, fs, 1)); 26603 26604 /* Set per slice configuration & number of free entries in the slice.*/ 26605 fs->free_count = fs->entry_count; 26606 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 26607 fs->free_count >>= 1; 26608 } 26609 /* Set group flags in in slice.*/ 26610 fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK; 26611 26612 /* Add slice to slices linked list . */ 26613 stage_fc->slices[fg->instance][old_physical_slice + slice_number]. 26614 next = fs; 26615 fs->prev = 26616 &stage_fc->slices[fg->instance][old_physical_slice + slice_number]; 26617 BCM_PBMP_OR(fs->pbmp, fg->pbmp); 26618 } 26619 26620 rv = fc->functions.fp_selcodes_install(unit, fg, 26621 new_physical_slice + slice_number, 26622 fs->pbmp, part_index); 26623 BCM_IF_ERROR_RETURN(rv); 26624 26625 rv = _bcm_field_group_selcode_initialize(unit, 26626 fg, fs, part_index); 26627 BCM_IF_ERROR_RETURN(rv); 26628 } 26629 26630 /* Reinstall group virtual map . */ 26631 if (virtual_priority) { 26632 BCM_IF_ERROR_RETURN (_field_group_vmap_add(unit, stage_fc, fg)); 26633 } 26634 26635 *fs_ptr = stage_fc->slices[fg->instance] + new_physical_slice; 26636 return (BCM_E_NONE); 26637 } 26638 26639 /* 26640 * Function: _field_per_port_group_install_selcodes 26641 * 26642 * Purpose: 26643 * This is called to install the selcodes for a per port 26644 * group. This should be called only for the autoexpanded slice during 26645 * autoexpansion. 26646 * Parameters: 26647 * unit - (IN) BCM device number. 26648 * fg - (IN) Field group. 26649 * fs - (IN) Slice pointer. 26650 * Returns: 26651 * BCM_E_XXX 26652 */ 26653 STATIC int 26654 _field_per_port_group_install_selcodes(int unit, _field_group_t *fg, 26655 _field_slice_t *fs) 26656 { 26657 _field_control_t *fc; /* Field control structure. */ 26658 _field_stage_t *stage_fc; /* Field stage control. */ 26659 uint32 entry_flags; /* Field entry part flags. */ 26660 uint8 new_physical_slice; 26661 /* Allocated slice. */ 26662 uint8 slice_number = 0; 26663 /* Slice index based on the TCAM parts*/ 26664 int part_index = 0; /* TCAM parts index */ 26665 int rv = 0; /* Operation return status */ 26666 int parts_count = 0; 26667 /* Number of entry parts. */ 26668 26669 /* Get field control structure. */ 26670 rv = _field_control_get(unit, &fc); 26671 BCM_IF_ERROR_RETURN(rv); 26672 26673 26674 /* Get stage field control structure. */ 26675 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 26676 BCM_IF_ERROR_RETURN(rv); 26677 26678 new_physical_slice = fs->slice_number; 26679 26680 /* 26681 * Add the selcodes. This case occurs when the slice contains some entries 26682 * from another group and a new entry is to be added in this slice for this 26683 * group. This scenario is for the group with port modes and so, no need 26684 * to update the virtual slice priority. 26685 * 26686 * Get number of entry parts for the group. 26687 */ 26688 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 26689 fg->flags, &parts_count); 26690 BCM_IF_ERROR_RETURN(rv); 26691 26692 /* Set up the new physical slice parameters in Software */ 26693 for(part_index = parts_count - 1; part_index >= 0; part_index--) { 26694 /* Get entry flags. */ 26695 rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, fg, 26696 &entry_flags); 26697 BCM_IF_ERROR_RETURN(rv); 26698 26699 /* Get slice id for entry part */ 26700 rv = _bcm_field_tcam_part_to_slice_number(unit, part_index, fg, 26701 &slice_number); 26702 BCM_IF_ERROR_RETURN(rv); 26703 26704 fs = stage_fc->slices[fg->instance] + new_physical_slice 26705 + slice_number; 26706 26707 /* Enable slice. */ 26708 if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) { 26709 /* Set group flags in in slice.*/ 26710 fs->group_flags |= fg->flags & _FP_GROUP_STATUS_MASK; 26711 26712 BCM_PBMP_OR(fs->pbmp, fg->pbmp); 26713 } 26714 26715 rv = fc->functions.fp_selcodes_install(unit, fg, 26716 new_physical_slice + 26717 slice_number, 26718 fg->pbmp, part_index); 26719 BCM_IF_ERROR_RETURN(rv); 26720 } 26721 26722 return (BCM_E_NONE); 26723 } 26724 26725 /* 26726 * Function: _field_group_check_and_install_selcodes 26727 * 26728 * Purpose: 26729 * Check if this is the first entry for the group 26730 * in the given slice. If this is the first entry 26731 * install the selcodes for the group in this slice 26732 * This function is called when the slice is not empty 26733 * Parameters: 26734 * unit - (IN) BCM device number. 26735 * fg - (IN) Field group. 26736 * fs - (IN) Slice pointer. 26737 * Returns: 26738 * BCM_E_XXX 26739 */ 26740 STATIC int 26741 _field_group_check_and_install_selcodes(int unit, _field_group_t *fg, 26742 _field_slice_t *fs) 26743 { 26744 _field_control_t *fc; /* Field control structure. */ 26745 _field_stage_t *stage_fc; /* Field stage control. */ 26746 uint32 entry_flags; /* Field entry part flags. */ 26747 uint8 new_physical_slice; 26748 /* Allocated slice. */ 26749 uint8 slice_number = 0; 26750 /* Slice index based on the TCAM parts*/ 26751 int idx = 0; /* Index to iter the entries in slice */ 26752 int part_index = 0; /* TCAM parts index */ 26753 int rv = 0; /* Operation return status */ 26754 int parts_count = 0; 26755 /* Number of entry parts. */ 26756 26757 /* Input parameters check. */ 26758 if ((NULL == fg) || (NULL == fs)) { 26759 return (BCM_E_PARAM); 26760 } 26761 26762 /* Get field control structure. */ 26763 rv = _field_control_get(unit, &fc); 26764 BCM_IF_ERROR_RETURN(rv); 26765 26766 /* If the slice is empty, then return BCM_E_NONE */ 26767 if (fs->free_count == fs->entry_count) { 26768 return (BCM_E_NONE); 26769 } 26770 26771 /* 26772 * Scan through all the entries in the slice and check if any 26773 * entry belongs to the given group. If any entry belongs to 26774 * this group, then return. Else, install the selcodes for the 26775 * group 26776 */ 26777 for (idx = 0; idx < fs->entry_count; idx++) { 26778 if ((NULL != fs->entries[idx]) && 26779 (NULL != fs->entries[idx]->group) && 26780 (fs->entries[idx]->group->gid == fg->gid)) { 26781 break; 26782 } 26783 } 26784 26785 if (idx != fs->entry_count) { 26786 /* 26787 * This means that there is an entry in the slice belonging 26788 * to the same group. So, no need to install the selcodes 26789 */ 26790 return (BCM_E_NONE); 26791 } 26792 26793 /* Get stage field control structure. */ 26794 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 26795 BCM_IF_ERROR_RETURN(rv); 26796 26797 new_physical_slice = fs->slice_number; 26798 26799 /* 26800 * Add the selcodes. This case occurs when the slice contains some entries 26801 * from another group and a new entry is to be added in this slice for this 26802 * group. This scenario is for the group with port modes and so, no need 26803 * to update the virtual slice priority. 26804 * 26805 * Get number of entry parts for the group. 26806 */ 26807 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 26808 fg->flags, &parts_count); 26809 BCM_IF_ERROR_RETURN(rv); 26810 26811 /* Set up the new physical slice parameters in Software */ 26812 for(part_index = parts_count - 1; part_index >= 0; part_index--) { 26813 /* Get entry flags. */ 26814 rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, fg, 26815 &entry_flags); 26816 BCM_IF_ERROR_RETURN(rv); 26817 26818 /* Get slice id for entry part */ 26819 rv = _bcm_field_tcam_part_to_slice_number(unit, part_index, fg, 26820 &slice_number); 26821 BCM_IF_ERROR_RETURN(rv); 26822 26823 fs = stage_fc->slices[fg->instance] + new_physical_slice 26824 + slice_number; 26825 26826 /* Enable slice. */ 26827 if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) { 26828 /* Set group flags in in slice.*/ 26829 fs->group_flags |= fg->flags & _FP_GROUP_STATUS_MASK; 26830 26831 BCM_PBMP_OR(fs->pbmp, fg->pbmp); 26832 } 26833 26834 rv = fc->functions.fp_selcodes_install(unit, fg, 26835 new_physical_slice + 26836 slice_number, 26837 fg->pbmp, part_index); 26838 BCM_IF_ERROR_RETURN(rv); 26839 } 26840 26841 return (BCM_E_NONE); 26842 } 26843 26844 STATIC int _field_group_is_policer_attached(int unit, 26845 _field_group_t *fg, 26846 int *is_pol_attached) { 26847 int idx, pidx; 26848 _field_entry_t *f_ent; /* Field entry info */ 26849 bcm_policer_t policer_id; /* Policer id. */ 26850 int rv; 26851 *is_pol_attached = 0; 26852 26853 if (NULL == fg) { 26854 return (BCM_E_PARAM); 26855 } 26856 /*loop throught he entries of the group */ 26857 for (idx = 0; idx < fg->group_status.entry_count; idx++) { 26858 f_ent = fg->entry_arr[idx]; 26859 /* check if entry has a policer attached */ 26860 if(f_ent != NULL) { 26861 for (pidx = 0; pidx < _FP_POLICER_LEVEL_COUNT; pidx++) { 26862 /* Read policer id from entry. */ 26863 rv = bcm_esw_field_entry_policer_get(unit, f_ent->eid, 26864 pidx, &policer_id); 26865 if (BCM_E_NOT_FOUND == rv) { 26866 continue; 26867 } 26868 if (!BCM_FAILURE(rv)) { 26869 *is_pol_attached = 1; 26870 return BCM_E_NONE; 26871 } else { 26872 return rv; 26873 } 26874 } 26875 } 26876 } 26877 return BCM_E_NONE; 26878 } 26879 26880 /* 26881 * Function: _field_group_slice_entry_reserve 26882 * 26883 * Purpose: 26884 * Find a slice attached to a group which has a room 26885 * to insert a new entry. 26886 * Parameters: 26887 * unit - (IN) BCM device number. 26888 * fg - (IN/OUT) Field group. 26889 * fs - (OUT) Slice pointer or NULL. 26890 * Returns: 26891 * BCM_E_XXX 26892 */ 26893 STATIC int 26894 _field_group_slice_entry_reserve(int unit, _field_group_t *fg, 26895 _field_slice_t **fs) 26896 { 26897 _field_slice_t *slice; /* Slice iteration count. */ 26898 int free_entry_cnt;/* Free entries in slice count. */ 26899 _field_stage_t *stage_fc; /* Stage field control info. */ 26900 int is_pol_attached; 26901 int rv; 26902 _field_group_t *curr_group; 26903 _field_control_t *fc; 26904 bcm_field_group_mode_t mode1 = 0; 26905 bcm_field_group_mode_t mode2 = 0; 26906 uint32 state = 0; 26907 26908 26909 /* Input parameters check. */ 26910 if ((NULL == fg) || (NULL == fs)) { 26911 return (BCM_E_PARAM); 26912 } 26913 26914 /* Find an empty spot in one of the groups slices. */ 26915 slice = &fg->slices[0]; 26916 while (slice->next != NULL) { 26917 slice = slice->next; /* Start from the last slice */ 26918 } 26919 26920 while (slice != NULL) { 26921 #if defined(BCM_TOMAHAWK_SUPPORT) 26922 if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 26923 BCM_IF_ERROR_RETURN 26924 (_field_th_em_entries_free_get(unit, fg, 26925 &free_entry_cnt)); 26926 } else 26927 #endif /* BCM_TOMAHAWK_SUPPORT */ 26928 { 26929 BCM_IF_ERROR_RETURN 26930 (_bcm_field_entries_free_get(unit, slice, fg, 26931 &free_entry_cnt)); 26932 } 26933 if (free_entry_cnt) { 26934 break; 26935 } 26936 slice = slice->prev; 26937 } 26938 26939 /* 26940 * If there is no room in existing group slices try to allocate a new one. 26941 * Find a feasible empty slice for auto-expand 26942 * Set these slices in the same virtual group 26943 */ 26944 if (slice == NULL) { 26945 /* Need to check if you need to allocate a new slice */ 26946 if (!(fg->flags & _FP_GROUP_SELECT_AUTO_EXPANSION)) { 26947 return (BCM_E_RESOURCE); 26948 } 26949 26950 /* 26951 * Auto expansion is not allowed if a policer a policer is attached 26952 * to an entry in the group which doesnot support global pools 26953 */ 26954 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 26955 if (BCM_FAILURE(rv)) { 26956 LOG_ERROR(BSL_LS_BCM_FP, 26957 (BSL_META_U(unit, 26958 "FP(unit %d) Error: Stage (%d) control get failure.\n"), 26959 unit, fg->stage_id)); 26960 return (rv); 26961 } 26962 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) { 26963 is_pol_attached = 0; 26964 BCM_IF_ERROR_RETURN(_field_group_is_policer_attached( 26965 unit, fg, &is_pol_attached)); 26966 if(is_pol_attached) { 26967 if ((fg->stage_id == _BCM_FIELD_STAGE_EGRESS) && 26968 (SOC_IS_TRIDENT2PLUS(unit))) { 26969 BCM_IF_ERROR_RETURN(bcm_esw_field_control_get( 26970 unit, bcmFieldControlEgressAutoExpandWithPolicer, 26971 &state)); 26972 if (state == 0) { 26973 return BCM_E_RESOURCE; 26974 } 26975 } else { 26976 return BCM_E_RESOURCE; 26977 } 26978 } 26979 } 26980 26981 #if defined(BCM_TOMAHAWK_SUPPORT) 26982 if (soc_feature(unit, soc_feature_field_multi_pipe_support) 26983 && (fg->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 26984 BCM_IF_ERROR_RETURN 26985 (_bcm_field_th_find_empty_slice(unit, fg, &slice)); 26986 } else 26987 #endif /* BCM_TOMAHAWK_SUPPORT */ 26988 { 26989 BCM_IF_ERROR_RETURN(_field_find_empty_slice(unit, fg, &slice)); 26990 } 26991 26992 BCM_IF_ERROR_RETURN 26993 (_bcm_field_entries_free_get(unit, slice, fg, &free_entry_cnt)); 26994 26995 if (0 == free_entry_cnt) { 26996 LOG_ERROR(BSL_LS_BCM_FP, 26997 (BSL_META_U(unit, 26998 "FP(unit %d) Error: No entries free in slice.\n"), 26999 unit)); 27000 return (BCM_E_RESOURCE); 27001 } 27002 /* for perport groups, the selcodes should be 27003 * installed for all the groups with same prioirty and mode*/ 27004 27005 if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) && 27006 (fg->priority != BCM_FIELD_GROUP_PRIO_ANY)) { 27007 /* Get device Field control structure. */ 27008 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 27009 curr_group = fc->groups; 27010 27011 if (curr_group == NULL) { 27012 return BCM_E_NONE; 27013 } 27014 while (curr_group != NULL) { 27015 if ((curr_group->stage_id == fg->stage_id) && 27016 (curr_group->gid != fg->gid) && 27017 (curr_group->flags & _FP_GROUP_PER_PORT_OR_PBMP) && 27018 (curr_group->priority == fg->priority)) { 27019 _bcm_esw_field_group_mode_get(curr_group->flags, &mode1); 27020 _bcm_esw_field_group_mode_get(fg->flags, &mode2); 27021 if( (mode1 == mode2) ){ 27022 /* install selcodes of this gorup in the slice */ 27023 BCM_IF_ERROR_RETURN( 27024 _field_per_port_group_install_selcodes(unit, 27025 curr_group, 27026 slice)); 27027 } 27028 } 27029 curr_group = curr_group->next; 27030 } 27031 } 27032 27033 } else { 27034 BCM_IF_ERROR_RETURN 27035 (_field_group_check_and_install_selcodes(unit, fg, slice)); 27036 } 27037 *fs = slice; 27038 return (BCM_E_NONE); 27039 } 27040 27041 /* 27042 * Function: 27043 * _field_entry_actions_free 27044 * Purpose: 27045 * Free and deinitialize field entry actions linked list 27046 * Parameters: 27047 * f_ent - (IN/OUT) Field entry with actions. 27048 * color_only - (IN) Color based actions only. 27049 * 27050 * Returns: 27051 * BCM_E_MEMORY - allocation failure 27052 * BCM_E_NONE - Success 27053 */ 27054 STATIC int 27055 _field_entry_actions_free (int unit, _field_entry_t *f_ent, int color_only) 27056 { 27057 _field_action_t *fa; /* Action structure pointer. */ 27058 _field_action_t *fa_prev; /* Action structure pointer. */ 27059 27060 /* Input parameters check.*/ 27061 if (NULL == f_ent) { 27062 return (BCM_E_PARAM); 27063 } 27064 27065 fa_prev = fa = f_ent->actions; 27066 27067 /* Free actions from the entry. */ 27068 while (fa != NULL) { 27069 if (color_only && (!_FP_ACTION_IS_COLOR_BASED(fa->action))) { 27070 fa_prev = fa; 27071 fa = fa->next; 27072 continue; 27073 } 27074 27075 /* Head entry deletion. */ 27076 if (fa == f_ent->actions) { 27077 f_ent->actions = fa->next; 27078 #if defined(BCM_TRIDENT3_SUPPORT) 27079 if (fa->action == bcmFieldActionVlanActions) { 27080 if (f_ent->vlan_action_set) { 27081 sal_free(f_ent->vlan_action_set); 27082 f_ent->vlan_action_set = NULL; 27083 } 27084 } 27085 #endif 27086 if (NULL != (fa->egress_pbmp)) { 27087 sal_free(fa->egress_pbmp); 27088 } 27089 sal_free(fa); 27090 fa_prev = fa = f_ent->actions; 27091 } else { 27092 /* Middle/Tail entry deletion. */ 27093 fa_prev->next = fa->next; 27094 #if defined(BCM_TRIDENT3_SUPPORT) 27095 if (fa->action == bcmFieldActionVlanActions) { 27096 if (f_ent->vlan_action_set) { 27097 sal_free(f_ent->vlan_action_set); 27098 f_ent->vlan_action_set = NULL; 27099 } 27100 } 27101 #endif 27102 if (NULL != (fa->egress_pbmp)) { 27103 sal_free(fa->egress_pbmp); 27104 } 27105 sal_free(fa); 27106 fa = fa_prev->next; 27107 } 27108 } 27109 27110 /* Destroy Oam related actions */ 27111 #if defined BCM_TRIDENT2PLUS_SUPPORT 27112 if (soc_feature(unit, soc_feature_fp_based_oam)){ 27113 BCM_IF_ERROR_RETURN(_bcm_field_oam_stat_actions_destroy (unit,f_ent)); 27114 } 27115 #endif 27116 27117 return (BCM_E_NONE); 27118 } 27119 27120 /* 27121 * Function: 27122 * _field_entry_phys_destroy 27123 * 27124 * Purpose: 27125 * Destroy a physical entry from a slice. Note that this does not remove 27126 * the entry from the hardware. 27127 * 27128 * Parameters: 27129 * unit - BCM device number 27130 * fs - slice that entry resides in 27131 * entry - Entry ID to remove 27132 * 27133 * Returns: 27134 * BCM_E_NONE - Success 27135 */ 27136 int 27137 _field_entry_phys_destroy (int unit, _field_entry_t *f_ent) 27138 { 27139 _field_stage_t *stage_fc; /* Stage field control. */ 27140 _field_group_t *fg; /* Field group structure. */ 27141 _field_slice_t *fs; /* Field slice structure. */ 27142 int parts_count = 0; /* Entry parts count. */ 27143 uint8 slice_number;/* Field entry part slice number. */ 27144 int idx; /* Entry parts iterator. */ 27145 int rv; /* Operation return status. */ 27146 27147 if (NULL == f_ent) { 27148 return (BCM_E_PARAM); 27149 } 27150 27151 fs = f_ent->fs; 27152 fg = f_ent->group; 27153 27154 /* Get field control structure. */ 27155 27156 27157 /* Get stage field control structure. */ 27158 rv = _field_stage_control_get(unit, fs->stage_id, &stage_fc); 27159 BCM_IF_ERROR_RETURN(rv); 27160 27161 /* Get number of entry parts we have to read. */ 27162 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 27163 fg->flags, &parts_count); 27164 BCM_IF_ERROR_RETURN(rv); 27165 27166 for (idx = 0; idx < parts_count; idx++) { 27167 /* Destroy all actions from entry. */ 27168 rv = _field_entry_actions_free (unit, f_ent + idx, FALSE); 27169 BCM_IF_ERROR_RETURN(rv); 27170 27171 /* Free tcam image. */ 27172 if(NULL != f_ent[idx].tcam.key) { 27173 sal_free(f_ent[idx].tcam.key); 27174 } 27175 if(NULL != f_ent[idx].tcam.mask) { 27176 sal_free(f_ent[idx].tcam.mask); 27177 } 27178 if(NULL != f_ent[idx].tcam.key_hw) { 27179 sal_free(f_ent[idx].tcam.key_hw); 27180 } 27181 if(NULL != f_ent[idx].tcam.mask_hw) { 27182 sal_free(f_ent[idx].tcam.mask_hw); 27183 } 27184 if(NULL != f_ent[idx].extra_tcam.key) { 27185 sal_free(f_ent[idx].extra_tcam.key); 27186 } 27187 if(NULL != f_ent[idx].extra_tcam.mask) { 27188 sal_free(f_ent[idx].extra_tcam.mask); 27189 } 27190 if(NULL != f_ent[idx].extra_tcam.key_hw) { 27191 sal_free(f_ent[idx].extra_tcam.key_hw); 27192 } 27193 if(NULL != f_ent[idx].extra_tcam.mask_hw) { 27194 sal_free(f_ent[idx].extra_tcam.mask_hw); 27195 } 27196 if(NULL != f_ent[idx].key_match_tcam.key) { 27197 sal_free(f_ent[idx].key_match_tcam.key); 27198 } 27199 if(NULL != f_ent[idx].key_match_tcam.mask) { 27200 sal_free(f_ent[idx].key_match_tcam.mask); 27201 } 27202 if(NULL != f_ent[idx].key_match_tcam.key_hw) { 27203 sal_free(f_ent[idx].key_match_tcam.key_hw); 27204 } 27205 if(NULL != f_ent[idx].key_match_tcam.mask_hw) { 27206 sal_free(f_ent[idx].key_match_tcam.mask_hw); 27207 } 27208 27209 /* Get slice id for entry part */ 27210 rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg, 27211 &slice_number); 27212 BCM_IF_ERROR_RETURN(rv); 27213 27214 /* Remove entry pointer from the slice. */ 27215 if ((stage_fc->stage_id != _BCM_FIELD_STAGE_EXTERNAL) && 27216 (stage_fc->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) { 27217 fs[slice_number].entries[f_ent[idx].slice_idx] = NULL; 27218 } 27219 27220 /* Increment slice unused entry count. */ 27221 if ((0 == (f_ent[idx].flags & _FP_ENTRY_SECOND_HALF)) || 27222 (f_ent[idx].flags & _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT)) { 27223 fs[slice_number].free_count++; 27224 } 27225 } 27226 27227 /* Remove the entry from group entry array. */ 27228 rv = _field_group_entry_delete(unit, fg, f_ent); 27229 if (BCM_FAILURE(rv)) { 27230 sal_free(f_ent); 27231 return (rv); 27232 } 27233 27234 /* Free the entry */ 27235 sal_free(f_ent); 27236 27237 return (BCM_E_NONE); 27238 } 27239 27240 /* 27241 * Function: 27242 * _bcm_field_entry_part_tcam_idx_get 27243 * 27244 * Purpose: 27245 * Given primary entry slice/idx calculate 27246 * secondary/tertiary/second half slice/index. 27247 * 27248 * Parameters: 27249 * unit - (IN) BCM device number. 27250 * f_ent - (IN) Field entry pointer. 27251 * idx_pri - (IN) Primary entry tcam index. 27252 * ent_part - (IN) Entry part id. 27253 * idx_out - (OUT) Entry part tcam index. 27254 * Returns 27255 * BCM_E_XXX 27256 */ 27257 int 27258 _bcm_field_entry_part_tcam_idx_get(int unit, _field_entry_t *f_ent, 27259 uint32 idx_pri, uint8 ent_part, 27260 int *idx_out) 27261 { 27262 uint8 slice_number = 0;/* Primary entry slice number. */ 27263 int pri_slice = 0; /* Primary entry slice number. */ 27264 int pri_index = 0; /* Primary entry in slice index. */ 27265 int part_index; /* Entry part slice index. */ 27266 _field_stage_t *stage_fc; /* Stage field control. */ 27267 _field_slice_t *fs; /* Field slice structure. */ 27268 _field_group_t *fg; /* Field group structure. */ 27269 int rv; /* Operation return status. */ 27270 27271 /* Input parameters ceck. */ 27272 if ((NULL == f_ent) || (NULL == idx_out)) { 27273 return (BCM_E_PARAM); 27274 } 27275 27276 #if defined(BCM_TOMAHAWK_SUPPORT) 27277 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 27278 (f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 27279 return _bcm_field_th_entry_part_tcam_idx_get(unit, f_ent, idx_pri, 27280 ent_part, idx_out); 27281 } 27282 #endif /* BCM_TOMAHAWK_SUPPORT */ 27283 27284 /* Primary entry index. */ 27285 if (0 == ent_part) { 27286 *idx_out = idx_pri; 27287 return (BCM_E_NONE); 27288 } 27289 27290 fg = f_ent->group; 27291 27292 /* External tcam doesn't support wide entries. */ 27293 if (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) { 27294 return (BCM_E_INTERNAL); 27295 } 27296 27297 /* TCAM Entries are consecutive in DW_DEPTH_EXPANDED. */ 27298 if (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) { 27299 *idx_out = idx_pri + ent_part; 27300 return (BCM_E_NONE); 27301 } 27302 27303 /* Get stage field control structure. */ 27304 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 27305 BCM_IF_ERROR_RETURN(rv); 27306 27307 /* Get primary part entry index & slice. */ 27308 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance, 27309 idx_pri, &pri_slice, 27310 &pri_index); 27311 BCM_IF_ERROR_RETURN(rv); 27312 27313 /* Get entry part slice number 0,1,2 */ 27314 rv = _bcm_field_tcam_part_to_slice_number(unit, ent_part, fg, 27315 &slice_number); 27316 BCM_IF_ERROR_RETURN(rv); 27317 27318 /* Get slice description structure. */ 27319 fs = stage_fc->slices[fg->instance] + (pri_slice + slice_number); 27320 27321 if (f_ent[ent_part].flags & _FP_ENTRY_SECOND_HALF) { 27322 part_index = pri_index + (fs->entry_count >> 1); 27323 } else { 27324 part_index = pri_index; 27325 } 27326 27327 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, fg->instance, 27328 fs->slice_number, part_index, 27329 idx_out); 27330 return (rv); 27331 } 27332 27333 /* 27334 * Function: 27335 * _field_entry_phys_create 27336 * 27337 * Purpose: 27338 * Initialize a physical entry structure. 27339 * 27340 * Parameters: 27341 * unit - (IN) BCM device number. 27342 * stage_fc - (IN) Stage field control structure. 27343 * entry - (IN) Entry ID. 27344 * prio - (IN) Priority relative to other entries in group. 27345 * fs - (IN) Slice where entry resides. 27346 * fg - (IN) Entry's group. 27347 * entry_p - (OUT)Allocated & initialized entry. 27348 * 27349 * Returns 27350 * BCM_E_XXX 27351 * 27352 * Notes: 27353 * Assumes that for wide-mode, the same index within the slice 27354 * is assigned for the 2(3) slices. 27355 */ 27356 STATIC int 27357 _field_entry_phys_create(int unit, _field_stage_t *stage_fc, 27358 bcm_field_entry_t entry, int prio, 27359 _field_slice_t *fs, _field_group_t *fg, 27360 _field_entry_t **entry_p) 27361 { 27362 _field_control_t *fc; /* Field control structure. */ 27363 int idx; /* Slice entries iteration index. */ 27364 int parts_count = 0;/* Number of entry parts. */ 27365 int part_index; /* Entry parts iterator. */ 27366 int rv; /* Operation return status. */ 27367 int mem_sz; /* Memory allocation size. */ 27368 int slice_number = 0;/* Field entry part slice number.*/ 27369 _field_entry_t *f_ent = NULL;/* Field entry structure. */ 27370 int pri_tcam_idx = -1; /* Primary entry tcam index. */ 27371 #if defined(BCM_TOMAHAWK_SUPPORT) 27372 int free_count = 0; /* Free entry count. */ 27373 #endif /* BCM_TOMAHAWK_SUPPORT */ 27374 27375 LOG_DEBUG(BSL_LS_BCM_FP, 27376 (BSL_META_U(unit, 27377 "FP(unit %d): BEGIN " 27378 "_field_entry_phys_create(entry=%d, prio=%d, gid=%d)\n"), 27379 unit, entry, prio, fg->gid)); 27380 27381 if ((NULL == fs) || (NULL == fg) || (NULL == entry_p)) { 27382 return (BCM_E_PARAM); 27383 } 27384 27385 #if defined(BCM_TOMAHAWK_SUPPORT) 27386 if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 27387 BCM_IF_ERROR_RETURN(_field_th_em_entries_free_get(unit, fg, 27388 &free_count)); 27389 /* Check if free entries are available in the UFT. */ 27390 if (0 == free_count) { 27391 return (BCM_E_RESOURCE); 27392 } 27393 } else 27394 #endif 27395 { 27396 /* Check if free entries are available in the slice. */ 27397 if (0 == fs->free_count) { 27398 return (BCM_E_RESOURCE); 27399 } 27400 } 27401 27402 /* Get field control structure. */ 27403 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 27404 27405 /* Get number of parts in field entry based on group flags. */ 27406 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 27407 fg->flags, &parts_count); 27408 BCM_IF_ERROR_RETURN(rv); 27409 27410 /* Allocate and zero memory for field entry. */ 27411 mem_sz = parts_count * sizeof (_field_entry_t); 27412 27413 _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry"); 27414 if (f_ent == NULL) { 27415 LOG_ERROR(BSL_LS_BCM_FP, 27416 (BSL_META_U(unit, 27417 "FP(unit %d) Error: allocation failure for field_entry\n"), 27418 unit)); 27419 return (BCM_E_MEMORY); 27420 } 27421 27422 /* Initalize policer id as invalid for all policer levels. */ 27423 for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) { 27424 f_ent->policer[idx].pid = _FP_INVALID_INDEX; 27425 } 27426 27427 rv = _bcm_field_slice_idx_allocate(unit, stage_fc, 27428 fg, fs, &(f_ent->slice_idx)); 27429 if (BCM_FAILURE(rv)) { 27430 sal_free(f_ent); 27431 } 27432 if (f_ent->slice_idx != _FP_INVALID_INDEX) { 27433 rv = _bcm_field_slice_offset_to_tcam_idx (unit, stage_fc, 27434 fg->instance, 27435 fs->slice_number, 27436 f_ent->slice_idx, 27437 &pri_tcam_idx); 27438 } 27439 if (BCM_FAILURE(rv)) { 27440 sal_free(f_ent); 27441 } 27442 27443 for (idx = 0; idx < parts_count; idx++) { 27444 /* Fill in entry primitives. */ 27445 f_ent[idx].eid = entry; 27446 f_ent[idx].prio = prio; 27447 f_ent[idx].group = fg; 27448 f_ent[idx].ent_copy = NULL; 27449 f_ent[idx].efp_key_match_type = _FP_ENTRY_TYPE_1; 27450 27451 /* Get entry part flags. */ 27452 rv = _bcm_field_tcam_part_to_entry_flags(unit, idx, fg, 27453 &f_ent[idx].flags); 27454 if (BCM_FAILURE(rv)) { 27455 sal_free(f_ent); 27456 return (rv); 27457 } 27458 27459 /* Enable color independent actions based on field control. */ 27460 if (fc->flags & _FP_COLOR_INDEPENDENT) { 27461 f_ent[idx].flags |= _FP_ENTRY_COLOR_INDEPENDENT; 27462 } 27463 27464 /* Given primary entry tcam index calculate entry part tcam index. */ 27465 if (idx && ((_BCM_FIELD_STAGE_EXTERNAL != fg->stage_id) && 27466 (_BCM_FIELD_STAGE_EXACTMATCH != fg->stage_id))) { 27467 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, pri_tcam_idx, 27468 idx, &part_index); 27469 if (BCM_FAILURE(rv)) { 27470 sal_free(f_ent); 27471 return (rv); 27472 } 27473 27474 #if defined(BCM_TOMAHAWK_SUPPORT) 27475 if (soc_feature(unit, soc_feature_field_multi_pipe_support) 27476 && (fg->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 27477 rv = _bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc, 27478 f_ent, part_index, 27479 &slice_number, 27480 (int *)&f_ent[idx].slice_idx); 27481 } else 27482 #endif /* BCM_TOMAHAWK_SUPPORT */ 27483 { 27484 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, 27485 fg->instance, part_index, 27486 &slice_number, 27487 (int *)&f_ent[idx].slice_idx); 27488 } 27489 if (BCM_FAILURE(rv)) { 27490 sal_free(f_ent); 27491 return (rv); 27492 } 27493 f_ent[idx].fs = stage_fc->slices[fg->instance] + slice_number; 27494 } else { 27495 /* Set entry slice. */ 27496 f_ent[idx].fs = fs; 27497 } 27498 27499 /* Mark entry dirty. */ 27500 f_ent[idx].flags |= _FP_ENTRY_DIRTY; 27501 f_ent[idx].flags |= _FP_ENTRY_CREATED_WITHOUT_PRIO; 27502 } 27503 27504 /* Insert the entry into group entry array. */ 27505 rv = _field_group_entry_add(unit, fg, f_ent); 27506 if (BCM_FAILURE(rv)) { 27507 sal_free(f_ent); 27508 return (rv); 27509 } 27510 27511 /* Update slice related parameters after succesful update */ 27512 for (idx = 0; idx < parts_count; idx++) { 27513 /* Decrement slice free entry count. */ 27514 if ((0 == (f_ent[idx].flags & _FP_ENTRY_SECOND_HALF)) || 27515 (f_ent[idx].flags & _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT)) { 27516 f_ent[idx].fs->free_count--; 27517 } 27518 27519 /* Assign entry to a slice */ 27520 if ((fg->stage_id != _BCM_FIELD_STAGE_EXTERNAL) && 27521 (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) { 27522 f_ent[idx].fs->entries[f_ent[idx].slice_idx] = f_ent + idx; 27523 } 27524 } 27525 27526 /* Return allocated/filled entry structure to the caller. */ 27527 *entry_p = f_ent; 27528 return (BCM_E_NONE); 27529 } 27530 27531 /* 27532 * Function: 27533 * _field_tcam_policy_external_reinstall 27534 * 27535 * Purpose: 27536 * Re-Install POLICY_TABLE entry. This writes the 27537 * actions to the hardware. 27538 * 27539 * Parameters: 27540 * unit - (IN) BCM device number. 27541 * f_ent - (IN) Entry to be installed. 27542 * 27543 * Returns: 27544 * BCM_E_INTERNAL - Memory Read failure 27545 * BCM_E_UNAVAIL - Device not supported 27546 * BCM_E_NONE - Success 27547 * 27548 * Notes: 27549 */ 27550 STATIC int 27551 _field_tcam_policy_external_reinstall(int unit, _field_entry_t *f_ent) 27552 { 27553 _field_control_t *fc; /* Field control structure. */ 27554 int rv; /* Operation return status. */ 27555 27556 /* Input parameters check. */ 27557 if (NULL == f_ent) { 27558 return (BCM_E_PARAM); 27559 } 27560 27561 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 27562 27563 /* If not installed, and no qualifiers yet 27564 * i.e. installing empty entry for first time 27565 */ 27566 if (0 == (f_ent->flags & _FP_ENTRY_INSTALLED)) { 27567 BCM_IF_ERROR_RETURN (_bcm_field_qual_tcam_key_mask_get(unit, f_ent)); 27568 } 27569 27570 /* Next copy S/W copy to H/W copy if required */ 27571 if(NULL != f_ent->tcam.key) { 27572 sal_memcpy(f_ent->tcam.key_hw, f_ent->tcam.key, 27573 f_ent->tcam.key_size); 27574 sal_free(f_ent->tcam.key); 27575 f_ent->tcam.key = NULL; 27576 } 27577 if(NULL != f_ent->tcam.mask) { 27578 sal_memcpy(f_ent->tcam.mask_hw, f_ent->tcam.mask, 27579 f_ent->tcam.key_size); 27580 sal_free(f_ent->tcam.mask); 27581 f_ent->tcam.mask = NULL; 27582 } 27583 27584 /* Then install the H/W copy into H/W */ 27585 rv = fc->functions.fp_external_entry_reinstall(unit, f_ent); 27586 27587 if (rv == BCM_E_NONE) { 27588 f_ent->flags &= ~_FP_ENTRY_DIRTY; 27589 f_ent->flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY); 27590 } 27591 return (rv); 27592 } 27593 27594 /* 27595 * Function: 27596 * _field_tcam_policy_external_install 27597 * 27598 * Purpose: 27599 * Install a combined TCAM and POLICY_TABLE entry. This writes the 27600 * qualifiers and actions to the hardware. 27601 * 27602 * Parameters: 27603 * unit - (IN) BCM device number. 27604 * f_ent - (IN) Entry to be installed. 27605 * 27606 * Returns: 27607 * BCM_E_INTERNAL - Memory Read failure 27608 * BCM_E_UNAVAIL - Device not supported 27609 * BCM_E_NONE - Success 27610 * 27611 * Notes: 27612 */ 27613 STATIC int 27614 _field_tcam_policy_external_install(int unit, _field_entry_t *f_ent) 27615 { 27616 _field_control_t *fc; /* Field control structure. */ 27617 int rv; /* Operation return status. */ 27618 27619 27620 /* Input parameters check. */ 27621 if (NULL == f_ent) { 27622 return (BCM_E_PARAM); 27623 } 27624 27625 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 27626 27627 /* If not installed, and no qualifiers yet 27628 * i.e. installing empty entry for first time 27629 */ 27630 if (0 == (f_ent->flags & _FP_ENTRY_INSTALLED)) { 27631 BCM_IF_ERROR_RETURN (_bcm_field_qual_tcam_key_mask_get(unit, f_ent)); 27632 } 27633 27634 /* Next copy S/W copy to H/W copy if required */ 27635 if(NULL != f_ent->tcam.key) { 27636 sal_memcpy(f_ent->tcam.key_hw, f_ent->tcam.key, 27637 f_ent->tcam.key_size); 27638 sal_free(f_ent->tcam.key); 27639 f_ent->tcam.key = NULL; 27640 } 27641 if(NULL != f_ent->tcam.mask) { 27642 sal_memcpy(f_ent->tcam.mask_hw, f_ent->tcam.mask, 27643 f_ent->tcam.key_size); 27644 sal_free(f_ent->tcam.mask); 27645 f_ent->tcam.mask = NULL; 27646 } 27647 27648 /* Then install the H/W copy into H/W */ 27649 rv = fc->functions.fp_external_entry_install(unit, f_ent); 27650 27651 if (rv == BCM_E_NONE) { 27652 f_ent->flags &= ~_FP_ENTRY_DIRTY; 27653 f_ent->flags |= _FP_ENTRY_INSTALLED; 27654 f_ent->flags |= _FP_ENTRY_ENABLED; 27655 } 27656 return (rv); 27657 } 27658 27659 #ifdef INCLUDE_L3 27660 #if defined (BCM_TRIDENT2_SUPPORT) /* BCM_TRIDENT2_SUPPORT */ 27661 /* 27662 * Function: _bcm_field_nat_actions_update 27663 * 27664 * Purpose: Update Egress Nat Reference Count for 27665 * NatEgressOverride action. 27666 * 27667 * Parameters: 27668 * unit - (IN) Device number. 27669 * f_ent - (IN) Field entry. 27670 * set - (IN) Set or reset the Reference count 27671 * based on action add/delete. 27672 * Returns: 27673 * BCM_E_XXX 27674 */ 27675 STATIC int 27676 _bcm_field_nat_actions_update(int unit, _field_entry_t *f_ent, 27677 int set) 27678 { 27679 _field_action_t *fa; /* Field action descriptor. */ 27680 27681 /* Input parameters check. */ 27682 if (NULL == f_ent) { 27683 return (BCM_E_PARAM); 27684 } 27685 27686 if ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) && 27687 (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id)){ 27688 return (BCM_E_NONE); 27689 } 27690 27691 /* Extract the policy info from the entry structure. */ 27692 for (fa = f_ent->actions; 27693 ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); 27694 fa = fa->next) { 27695 if (fa->action != bcmFieldActionNatEgressOverride) { 27696 continue; 27697 } 27698 27699 if (set) { 27700 /* Action is added, increment reference count if not already done.*/ 27701 if ((_FP_ACTION_DIRTY & fa->flags) || SOC_WARM_BOOT(unit)) { 27702 BCM_IF_ERROR_RETURN(_bcm_esw_nat_egress_ref_count_update(unit, fa->param[0], 1)); 27703 /* Setting hw_index to non-zero in order to handle fp action remove, fp action add 27704 * config sequence */ 27705 fa->hw_index = 1; 27706 } 27707 } 27708 else { 27709 /* Action is deleted, decrement reference count if not already done.*/ 27710 if ((fa->flags & _FP_ACTION_DIRTY)) { 27711 continue; 27712 } 27713 27714 BCM_IF_ERROR_RETURN(_bcm_esw_nat_egress_ref_count_update(unit, fa->param[0], 0)); 27715 fa->hw_index = _FP_INVALID_INDEX; 27716 fa->flags |= _FP_ACTION_DIRTY; 27717 } 27718 } 27719 return BCM_E_NONE; 27720 } 27721 #endif /* BCM_TRIDENT2_SUPPORT */ 27722 27723 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \ 27724 || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \ 27725 || defined (BCM_ENDURO_SUPPORT) \ 27726 27727 27728 /* 27729 * Function: 27730 * _field_nh_ref_count_incr 27731 * 27732 * Purpose: 27733 * Increment next hop refCount for RedirectEgrNextHop and 27734 * L3Switch action. 27735 * 27736 * Parameters: 27737 * unit - (IN) BCM device number. 27738 * f_ent - (IN) Entry array 27739 * Returns: 27740 * BCM_E_XXX 27741 * Notes: 27742 */ 27743 int 27744 _field_nh_ref_count_incr (int unit, _field_entry_t *f_ent) 27745 { 27746 _field_action_t *fa = NULL; /* Field action descriptor. */ 27747 uint32 flags; /* L3 forwarding flags. */ 27748 int nh_ecmp_id; /* Next hop/Ecmp group id. */ 27749 27750 /* Extract action info from the entry structure. */ 27751 for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags) 27752 && ((_FP_ACTION_DIRTY & fa->flags) || SOC_WARM_BOOT(unit))); 27753 fa = fa->next) { 27754 if ((fa->action != bcmFieldActionRedirectEgrNextHop) 27755 && (fa->action != bcmFieldActionL3Switch)) { 27756 continue; 27757 } 27758 27759 BCM_IF_ERROR_RETURN(_bcm_field_policy_set_l3_nh_resolve (unit, 27760 fa->param[0], &flags, &nh_ecmp_id)); 27761 27762 BCM_IF_ERROR_RETURN(bcmi_esw_l3_egress_ref_count_update (unit, 27763 fa->param[0], flags, nh_ecmp_id,1)); 27764 27765 /* Setting hw_index to non-zero in order to handle fp action remove, fp action add 27766 * config sequence */ 27767 fa->hw_index = 1; 27768 } 27769 27770 return BCM_E_NONE; 27771 } 27772 27773 /* 27774 * Function: 27775 * _field_nh_ref_count_decr 27776 * 27777 * Purpose: 27778 * Decrement next hop refCount for RedirectEgrNextHop and 27779 * L3Switch action. 27780 * 27781 * Parameters: 27782 * unit - (IN) BCM device number. 27783 * f_ent - (IN) Entry array 27784 * Returns: 27785 * BCM_E_XXX 27786 * Notes: 27787 */ 27788 STATIC int 27789 _field_nh_ref_count_decr (int unit, _field_entry_t *f_ent) 27790 { 27791 _field_action_t *fa = NULL; /* Field action descriptor. */ 27792 uint32 flags; /* L3 forwarding flags. */ 27793 int nh_ecmp_id; /* Next hop/Ecmp group id. */ 27794 27795 /* Extract action info from the entry structure. */ 27796 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 27797 if ((fa->action != bcmFieldActionRedirectEgrNextHop) 27798 && (fa->action != bcmFieldActionL3Switch)) { 27799 continue; 27800 } 27801 27802 /* If action is not valid and dirty, do not decrement 27803 * the ref Count. For modified action, the ref count 27804 * decrement will happen in invalid_actions_free */ 27805 if ((fa->flags & _FP_ACTION_VALID) == 0) { 27806 continue; 27807 } 27808 27809 if ((fa->flags & _FP_ACTION_DIRTY)) { 27810 continue; 27811 } 27812 27813 BCM_IF_ERROR_RETURN(_bcm_field_policy_set_l3_nh_resolve (unit, 27814 fa->param[0], &flags, &nh_ecmp_id)); 27815 27816 BCM_IF_ERROR_RETURN(bcmi_esw_l3_egress_ref_count_update (unit, 27817 fa->param[0], flags, nh_ecmp_id,0)); 27818 fa->hw_index = _FP_INVALID_INDEX; 27819 fa->flags |= _FP_ACTION_DIRTY; 27820 } 27821 27822 return BCM_E_NONE; 27823 } 27824 27825 27826 27827 /* 27828 * Function: 27829 * bcmi_xgs3_fp_l3_egress_ref_count_update 27830 * 27831 * Purpose: 27832 * Increment next hop refCount for RedirectEgrNextHop and 27833 * L3Switch action after warmboot. 27834 * 27835 * Parameters: 27836 * unit - (IN) BCM device number. 27837 * Returns: 27838 * BCM_E_XXX 27839 * Notes: 27840 */ 27841 int 27842 bcmi_xgs3_fp_l3_egress_ref_count_update (int unit) 27843 { 27844 _field_group_t *fg; /* Group information. */ 27845 _field_control_t *fc; /* Field Control Structure. */ 27846 _field_entry_t *f_ent; /* Field Entry. */ 27847 int idx = 0; /* Iteration index. */ 27848 int rv = 0; /* Return Value. */ 27849 27850 /* Get unit FP control structure. */ 27851 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 27852 27853 /* Iterate over the groups linked-list */ 27854 fg = fc->groups; 27855 while (fg != NULL) { 27856 if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS || 27857 fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 27858 /* Now iterate over the entries in this group */ 27859 for (idx = 0; idx < fg->group_status.entry_count; idx++) { 27860 f_ent = fg->entry_arr[idx]; 27861 rv = _field_nh_ref_count_incr (unit, f_ent); 27862 BCM_IF_ERROR_RETURN(rv); 27863 #if defined (BCM_TRIDENT2_SUPPORT) /* BCM_TRIDENT2_SUPPORT */ 27864 rv = _bcm_field_nat_actions_update(unit, f_ent, 1); 27865 BCM_IF_ERROR_RETURN(rv); 27866 #endif /* BCM_TRIDENT2_SUPPORT */ 27867 } 27868 } 27869 fg = fg->next; 27870 } 27871 27872 return rv; 27873 } 27874 27875 27876 #endif /* BCM_KATANA_SUPPORT || BCM_TRIDENT_SUPPORT || BCM_TRIUMPH3_SUPPORT \ 27877 || BCM_GREYHOUND_SUPPORT */ 27878 27879 #endif /* INCLUDE_L3 */ 27880 27881 /* 27882 * Function: 27883 * _field_resources_free 27884 * 27885 * Purpose: 27886 * Free hw resources used in FP entry. 27887 * 27888 * Parameters: 27889 * unit - (IN) BCM device number. 27890 * f_ent - (IN) Field entry structure. 27891 * flags - (IN) Old/installed resource to free. 27892 * Returns: 27893 * BCM_E_XXX 27894 * Notes: 27895 */ 27896 STATIC int 27897 _field_resources_free(int unit, _field_entry_t *f_ent, uint32 flags) 27898 { 27899 int rv; /* Operation return status. */ 27900 _field_control_t *fc; /* Field Control Structure. */ 27901 27902 /* Input parameters check. */ 27903 if (NULL == f_ent) { 27904 return (BCM_E_PARAM); 27905 } 27906 27907 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 27908 27909 /* Free redirection profiles. */ 27910 rv = _field_redirect_profile_hw_free(unit, f_ent, flags); 27911 BCM_IF_ERROR_RETURN(rv); 27912 27913 /* Free mirror destination indexes. */ 27914 rv = _field_mtp_hw_free(unit, f_ent, flags); 27915 BCM_IF_ERROR_RETURN(rv); 27916 27917 #if defined(BCM_TRIDENT2_SUPPORT) 27918 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) || 27919 soc_feature(unit, soc_feature_field_multi_pipe_support))) { 27920 rv = _bcm_field_td2_hash_select_profile_hw_free(unit, f_ent, flags); 27921 BCM_IF_ERROR_RETURN(rv); 27922 } 27923 #endif 27924 27925 /* Free counters. */ 27926 if (flags & _FP_ACTION_RESOURCE_FREE) { 27927 rv = fc->functions.fp_stat_hw_free(unit, f_ent); 27928 BCM_IF_ERROR_RETURN(rv); 27929 } 27930 27931 27932 #if defined(INCLUDE_L3) 27933 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_TRX_SUPPORT) 27934 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 27935 rv = _bcm_field_l2_actions_hw_free(unit, f_ent, flags); 27936 BCM_IF_ERROR_RETURN(rv); 27937 } 27938 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */ 27939 27940 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \ 27941 || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \ 27942 || defined (BCM_ENDURO_SUPPORT) 27943 if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit) 27944 || SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANEX(unit) 27945 || SOC_IS_ENDURO(unit) || SOC_IS_GREYHOUND2(unit)) { 27946 BCM_IF_ERROR_RETURN(_bcm_field_l3_egress_actions_reset(unit, f_ent, 27947 flags)); 27948 27949 /* Decrement next hop ref Count. */ 27950 if (flags & _FP_ACTION_RESOURCE_FREE) { 27951 rv = _field_nh_ref_count_decr (unit, f_ent); 27952 BCM_IF_ERROR_RETURN(rv); 27953 } 27954 } 27955 27956 #endif /* BCM_KATANA_SUPPORT || BCM_TRIDENT_SUPPORT || BCM_TRIUMPH3_SUPPORT \ 27957 || BCM_GREYHOUND_SUPPORT || BCM_ENDURO_SUPPORT */ 27958 27959 #if defined (BCM_TRIDENT2_SUPPORT) /* BCM_TRIDENT2_SUPPORT */ 27960 if (flags & _FP_ACTION_RESOURCE_FREE) { 27961 BCM_IF_ERROR_RETURN(_bcm_field_nat_actions_update(unit, f_ent, 0)); 27962 } 27963 #endif /* BCM_TRIDENT2_SUPPORT */ 27964 27965 #endif /* INCLUDE_L3 */ 27966 27967 #if defined(BCM_TOMAHAWK_SUPPORT) 27968 if(NULL != fc->functions.fp_eh_mask_profile_hw_free) { 27969 fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, flags); 27970 BCM_IF_ERROR_RETURN(rv); 27971 } 27972 #endif 27973 27974 #if defined(BCM_TRIDENT3_SUPPORT) 27975 if (NULL != fc->functions.fp_vlan_actions_profile_hw_free) { 27976 rv = fc->functions.fp_vlan_actions_profile_hw_free(unit, f_ent, flags); 27977 BCM_IF_ERROR_RETURN(rv); 27978 } 27979 #endif /* BCM_TRIDENT3_SUPPORT */ 27980 27981 #if defined(BCM_FLOWTRACKER_SUPPORT) 27982 BCM_IF_ERROR_RETURN(_bcm_field_hx5_ft_group_hw_free(unit, f_ent, 27983 flags)); 27984 #endif 27985 27986 if (soc_feature(unit, soc_feature_th3_style_fp)) { 27987 rv = _field_delayed_profile_hw_free(unit, f_ent, flags); 27988 BCM_IF_ERROR_RETURN(rv); 27989 } 27990 return (BCM_E_NONE); 27991 } 27992 27993 /* 27994 * Function: 27995 * _field_hw_resources_free 27996 * 27997 * Purpose: 27998 * Free hw resources used in FP entry. 27999 * 28000 * Parameters: 28001 * unit - (IN) BCM device number. 28002 * f_ent - (IN) Field entry structure. 28003 * flags - (IN) Old/installed resource to free. 28004 * Returns: 28005 * BCM_E_XXX 28006 * Notes: 28007 */ 28008 STATIC int 28009 _field_hw_resources_free(int unit, _field_entry_t *f_ent, uint32 flags) 28010 { 28011 int rv; /* Operation return status. */ 28012 28013 rv = _field_resources_free(unit, f_ent, flags); 28014 BCM_IF_ERROR_RETURN(rv); 28015 28016 /* Free policers. */ 28017 if (flags & _FP_ACTION_RESOURCE_FREE) { 28018 if (flags & _FP_ACTION_POLICER_SW_UPDATE) { 28019 rv = _field_policers_hw_free(unit, f_ent, 28020 _FP_ACTION_RESOURCE_FREE|_FP_ACTION_POLICER_SW_UPDATE); 28021 } else { 28022 rv = _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28023 } 28024 BCM_IF_ERROR_RETURN(rv); 28025 } 28026 28027 if (flags & _FP_ACTION_OLD_RESOURCE_FREE) { 28028 if (flags & _FP_ACTION_POLICER_SW_UPDATE) { 28029 rv = _field_policers_hw_free(unit, f_ent, 28030 _FP_ACTION_OLD_RESOURCE_FREE|_FP_ACTION_POLICER_SW_UPDATE); 28031 } else { 28032 rv = _field_policers_hw_free(unit, f_ent, _FP_ACTION_OLD_RESOURCE_FREE); 28033 } 28034 BCM_IF_ERROR_RETURN(rv); 28035 } 28036 28037 return (BCM_E_NONE); 28038 } 28039 28040 /* 28041 * Function: 28042 * _field_hw_resources_alloc 28043 * 28044 * Purpose: 28045 * Allocate hw resources required for entry installation. 28046 * 28047 * Parameters: 28048 * unit - (IN) BCM device number. 28049 * f_ent - (IN) Entry array 28050 * Returns: 28051 * BCM_E_XXX 28052 * Notes: 28053 */ 28054 STATIC int 28055 _field_hw_resources_alloc(int unit, _field_entry_t *f_ent) 28056 { 28057 _field_control_t *fc; 28058 _field_stage_t *stage_fc; /* Stage field control. */ 28059 int rv = BCM_E_NONE; /* Operation return status. */ 28060 28061 /* Input parameters check. */ 28062 if (NULL == f_ent) { 28063 return (BCM_E_PARAM); 28064 } 28065 28066 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 28067 28068 /* Get Stage Control structure. */ 28069 rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc); 28070 BCM_IF_ERROR_RETURN(rv); 28071 28072 /* Select slice for hw resources allocation. */ 28073 rv = _field_entry_install_slice_fit(unit, stage_fc, f_ent, f_ent->fs); 28074 BCM_IF_ERROR_RETURN(rv); 28075 28076 /* Allocate policers. */ 28077 BCM_IF_ERROR_RETURN(_field_policers_hw_alloc(unit, f_ent)); 28078 28079 /* Allocate statistics. */ 28080 if ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) && 28081 (soc_feature(unit, soc_feature_field_multi_pipe_support))) { 28082 if (f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY) { 28083 /* Allocate statistics. */ 28084 rv = fc->functions.fp_stat_hw_alloc(unit, f_ent); 28085 if (BCM_FAILURE(rv)) { 28086 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28087 return (rv); 28088 } 28089 } 28090 } else { 28091 /* Allocate statistics. */ 28092 rv = fc->functions.fp_stat_hw_alloc(unit, f_ent); 28093 if (BCM_FAILURE(rv)) { 28094 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28095 return (rv); 28096 } 28097 } 28098 28099 /* Allocate mirror destination indexes. */ 28100 rv = _field_mtp_hw_alloc(unit, f_ent); 28101 if (BCM_FAILURE(rv)) { 28102 fc->functions.fp_stat_hw_free(unit, f_ent); 28103 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28104 return (rv); 28105 } 28106 28107 /* Allocate redirection profiles. */ 28108 rv = _field_redirect_profile_hw_alloc(unit, f_ent); 28109 if (BCM_FAILURE(rv)) { 28110 _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28111 fc->functions.fp_stat_hw_free(unit, f_ent); 28112 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28113 return (rv); 28114 } 28115 28116 #if defined(BCM_TOMAHAWK_SUPPORT) 28117 /* Allocate redirection profiles. */ 28118 if (NULL != fc->functions.fp_eh_mask_profile_hw_alloc) { 28119 rv = fc->functions.fp_eh_mask_profile_hw_alloc(unit, f_ent); 28120 if (BCM_FAILURE(rv)) { 28121 _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28122 fc->functions.fp_stat_hw_free(unit, f_ent); 28123 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28124 _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28125 return (rv); 28126 } 28127 } 28128 #endif 28129 28130 #if defined(BCM_TRIDENT2_SUPPORT) 28131 /* Allocate hash select profiles. */ 28132 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) || 28133 soc_feature(unit, soc_feature_field_multi_pipe_support))) { 28134 rv = _bcm_field_td2_hash_select_profile_hw_alloc(unit, f_ent); 28135 if (BCM_FAILURE(rv)) { 28136 _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28137 fc->functions.fp_stat_hw_free(unit, f_ent); 28138 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28139 _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28140 #if defined(BCM_TOMAHAWK_SUPPORT) 28141 if (NULL != fc->functions.fp_eh_mask_profile_hw_free) { 28142 fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, 28143 _FP_ACTION_HW_FREE); 28144 } 28145 #endif 28146 return (rv); 28147 } 28148 } 28149 #endif /* BCM_TRIDENT2_SUPPORT */ 28150 28151 #if defined (INCLUDE_L3) 28152 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_TRX_SUPPORT) 28153 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 28154 rv = _bcm_field_l2_actions_hw_alloc(unit, f_ent); 28155 if (BCM_FAILURE(rv)) { 28156 _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28157 fc->functions.fp_stat_hw_free(unit, f_ent); 28158 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28159 _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28160 #if defined(BCM_TRIDENT2_SUPPORT) 28161 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) || 28162 soc_feature(unit, soc_feature_field_multi_pipe_support))) { 28163 _bcm_field_td2_hash_select_profile_hw_free(unit, 28164 f_ent, 28165 _FP_ACTION_HW_FREE); 28166 } 28167 #endif 28168 #if defined(BCM_TOMAHAWK_SUPPORT) 28169 if (NULL != fc->functions.fp_eh_mask_profile_hw_free) { 28170 fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, 28171 _FP_ACTION_HW_FREE); 28172 } 28173 #endif 28174 return (rv); 28175 } 28176 } 28177 #endif /* BCM_TRIUMPH2_SUPPORT || defined (BCM_TRIDENT_SUPPORT) */ 28178 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \ 28179 || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \ 28180 || defined (BCM_ENDURO_SUPPORT) 28181 if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit) 28182 || SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANEX(unit) 28183 || SOC_IS_ENDURO(unit) || SOC_IS_GREYHOUND2(unit)) { 28184 rv = _bcm_field_l3_egress_actions_set(unit, f_ent); 28185 if (BCM_SUCCESS(rv)) { 28186 rv = _field_nh_ref_count_incr(unit, f_ent); 28187 if (BCM_FAILURE(rv)) { 28188 _bcm_field_l3_egress_actions_reset(unit, 28189 f_ent, _FP_ACTION_HW_FREE); 28190 } 28191 } 28192 28193 if (BCM_FAILURE(rv)) { 28194 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 28195 _bcm_field_l2_actions_hw_free(unit, f_ent, 28196 _FP_ACTION_RESOURCE_FREE); 28197 } 28198 _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28199 fc->functions.fp_stat_hw_free(unit, f_ent); 28200 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28201 _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28202 #if defined(BCM_TOMAHAWK_SUPPORT) 28203 if (NULL != fc->functions.fp_eh_mask_profile_hw_free) { 28204 fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, 28205 _FP_ACTION_HW_FREE); 28206 } 28207 #endif 28208 return (rv); 28209 } 28210 } 28211 #endif /* BCM_KATANA_SUPPORT || BCM_TRIDENT_SUPPORT || BCM_TRIUMPH3_SUPPORT \ 28212 || BCM_GREYHOUND_SUPPORT || BCM_ENDURO_SUPPORT */ 28213 28214 #if defined (BCM_TRIDENT2_SUPPORT) 28215 rv = _bcm_field_nat_actions_update(unit, f_ent, 1); 28216 if (BCM_FAILURE(rv)) { 28217 if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit) 28218 || SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANEX(unit) 28219 || SOC_IS_ENDURO(unit)) { 28220 _field_nh_ref_count_decr (unit, f_ent); 28221 _bcm_field_l3_egress_actions_reset(unit, 28222 f_ent, _FP_ACTION_HW_FREE); 28223 } 28224 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 28225 _bcm_field_l2_actions_hw_free(unit, f_ent, 28226 _FP_ACTION_RESOURCE_FREE); 28227 } 28228 #if defined(BCM_TRIDENT2_SUPPORT) 28229 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) || 28230 soc_feature(unit, soc_feature_field_multi_pipe_support))) { 28231 _bcm_field_td2_hash_select_profile_hw_free(unit, 28232 f_ent, 28233 _FP_ACTION_HW_FREE); 28234 } 28235 #endif 28236 #if defined(BCM_TOMAHAWK_SUPPORT) 28237 if (NULL != fc->functions.fp_eh_mask_profile_hw_free) { 28238 fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, 28239 _FP_ACTION_HW_FREE); 28240 } 28241 #endif 28242 _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28243 _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28244 fc->functions.fp_stat_hw_free(unit, f_ent); 28245 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28246 } 28247 #endif 28248 28249 28250 /* Delayed Action profile alloc */ 28251 if (soc_feature(unit, soc_feature_th3_style_fp)) { 28252 rv = _field_delayed_profile_hw_alloc(unit, f_ent); 28253 if (BCM_FAILURE(rv)) { 28254 #if defined (BCM_TRIDENT2_SUPPORT) 28255 if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit) 28256 || SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANEX(unit) 28257 || SOC_IS_ENDURO(unit)) { 28258 _field_nh_ref_count_decr (unit, f_ent); 28259 _bcm_field_l3_egress_actions_reset(unit, 28260 f_ent, _FP_ACTION_HW_FREE); 28261 } 28262 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 28263 _bcm_field_l2_actions_hw_free(unit, f_ent, 28264 _FP_ACTION_RESOURCE_FREE); 28265 } 28266 #if defined(BCM_TRIDENT2_SUPPORT) 28267 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) || 28268 SOC_IS_TOMAHAWKX(unit))) { 28269 _bcm_field_td2_hash_select_profile_hw_free(unit, 28270 f_ent, 28271 _FP_ACTION_HW_FREE); 28272 } 28273 #endif 28274 #if defined(BCM_TOMAHAWK_SUPPORT) 28275 if (NULL != fc->functions.fp_eh_mask_profile_hw_free) { 28276 fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, 28277 _FP_ACTION_HW_FREE); 28278 } 28279 #endif 28280 _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28281 _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 28282 fc->functions.fp_stat_hw_free(unit, f_ent); 28283 _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE); 28284 #endif 28285 } 28286 } 28287 28288 #endif /* INCLUDE_L3 */ 28289 28290 #if defined(BCM_TRIDENT3_SUPPORT) 28291 if ((f_ent->vlan_action_set != NULL) && 28292 (fc->functions.fp_vlan_actions_profile_hw_alloc != NULL)) { 28293 fc->functions.fp_vlan_actions_profile_hw_alloc(unit, f_ent); 28294 } 28295 #endif /* BCM_TRIDENT3_SUPPORT */ 28296 28297 #if defined(BCM_FLOWTRACKER_SUPPORT) 28298 if (soc_feature(unit, soc_feature_field_flowtracker_support) && 28299 (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 28300 rv = _bcm_field_hx5_ft_group_hw_alloc(unit, f_ent); 28301 } 28302 #endif /* BCM_FLOWTRACKER_SUPPORT */ 28303 28304 return rv; 28305 } 28306 28307 /* 28308 * Function: 28309 * _field_entry_policer_stat_slice_move 28310 * Purpose: 28311 * Move policer to slice in which counter resides 28312 * Parameters: 28313 * unit - (IN) BCM device number. 28314 * f_ent - (IN) Entry to be installed. 28315 * to_secondary - (IN) Movement direction. 28316 * Returns: 28317 * BCM_E_XXX 28318 */ 28319 STATIC int 28320 _field_entry_policer_stat_slice_move(int unit, 28321 _field_entry_t *f_ent, 28322 int to_secondary) 28323 { 28324 _field_entry_policer_t *f_ent_pl_src; /* Src entry policer descriptor */ 28325 _field_entry_policer_t *f_ent_pl_dst; /* Dest entry policer descriptor */ 28326 _field_stage_t *stage_fc; /* Stage field control. */ 28327 uint8 src_idx; /* Source entry hardware index. */ 28328 uint8 dst_idx; /* Dest entry hardware index. */ 28329 uint8 level; /* Policer level. */ 28330 _field_action_t *fa; /* Entry actions iterator. */ 28331 _field_action_t *fa_next; /* Entry actions iterator. */ 28332 28333 /* Input parameters check */ 28334 if (NULL == f_ent) { 28335 return (BCM_E_PARAM); 28336 } 28337 28338 /* Get stage control structure. */ 28339 BCM_IF_ERROR_RETURN 28340 (_field_stage_control_get(unit, 28341 f_ent->group->stage_id, 28342 &stage_fc 28343 ) 28344 ); 28345 28346 if ((stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) 28347 && !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) 28348 && (f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE)) { 28349 /* Get entry secondary part hardware index. */ 28350 BCM_IF_ERROR_RETURN 28351 (_bcm_field_entry_flags_to_tcam_part(unit, _FP_ENTRY_SECONDARY, 28352 f_ent->group, 28353 &dst_idx 28354 ) 28355 ); 28356 28357 /* Determine source and destination slice indices. */ 28358 if (to_secondary) { 28359 src_idx = 0; 28360 } else { 28361 src_idx = dst_idx; 28362 dst_idx = 0; 28363 } 28364 28365 fa = f_ent[src_idx].actions; 28366 /* Copy all actions from source index to destination index. */ 28367 while (NULL != fa) { 28368 fa_next = fa->next; 28369 /* Insert action to the destination slice actions list. */ 28370 fa->next = f_ent[dst_idx].actions; 28371 f_ent[dst_idx].actions = fa; 28372 /* Remove action from the primary slice actions list. */ 28373 f_ent[src_idx].actions = fa_next; 28374 fa = fa_next; 28375 } 28376 28377 for (level = 0; level < _FP_POLICER_LEVEL_COUNT; level++) { 28378 f_ent_pl_src = f_ent[src_idx].policer + level; 28379 28380 if (f_ent_pl_src->flags & _FP_POLICER_INSTALLED) { 28381 f_ent_pl_dst = (f_ent[dst_idx].policer + level); 28382 f_ent_pl_dst->pid = f_ent_pl_src->pid; 28383 f_ent_pl_dst->flags |= _FP_POLICER_INSTALLED; 28384 28385 f_ent_pl_src->flags &= ~_FP_POLICER_INSTALLED; 28386 f_ent_pl_src->pid = _FP_INVALID_INDEX; 28387 } 28388 } 28389 } 28390 return (BCM_E_NONE); 28391 } 28392 28393 /* 28394 * Function: 28395 * _field_entry_actions_meter_slice_move 28396 * Purpose: 28397 * Move actions to a slice where meter resides. 28398 * Parameters: 28399 * unit - (IN) BCM device number. 28400 * f_ent - (IN) Entry to be installed. 28401 * to_secondary - (IN) Movement direction. 28402 * Returns: 28403 * BCM_E_XXX 28404 */ 28405 STATIC int 28406 _field_entry_actions_meter_slice_move(int unit, _field_entry_t *f_ent, 28407 int to_secondary) 28408 { 28409 _field_stage_t *stage_fc; /* Stage field control. */ 28410 _field_action_t *fa; /* Entry actions iterator. */ 28411 _field_action_t *fa_prev; /* Entry actions iterator. */ 28412 _field_action_t *fa_next; /* Entry actions iterator. */ 28413 uint8 src_idx; /* Entry array action source index. */ 28414 uint8 dst_idx; /* Entry array action dest index. */ 28415 int rv; /* Operation return status. */ 28416 28417 28418 /* Input parameters check */ 28419 if (NULL == f_ent) { 28420 return (BCM_E_PARAM); 28421 } 28422 28423 /* Get stage control structure. */ 28424 rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc); 28425 BCM_IF_ERROR_RETURN(rv); 28426 28427 if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) && 28428 (f_ent->flags & _FP_ENTRY_POLICER_IN_SECONDARY_SLICE)) { 28429 rv = 28430 _bcm_field_entry_flags_to_tcam_part(unit, _FP_ENTRY_SECONDARY, 28431 f_ent->group, &dst_idx); 28432 BCM_IF_ERROR_RETURN(rv); 28433 28434 if (to_secondary) { 28435 src_idx = 0; 28436 } else { 28437 src_idx = dst_idx; 28438 dst_idx = 0; 28439 } 28440 28441 /* Copy all but counter action. */ 28442 fa = f_ent[src_idx].actions; 28443 fa_prev = NULL; 28444 while (NULL != fa) { 28445 fa_next = fa->next; 28446 /* coverity[always_true_or : FALSE]*/ 28447 if ((fa->action != bcmFieldActionUpdateCounter) || 28448 (fa->action != bcmFieldActionCosQCpuNew)|| 28449 (fa->action != bcmFieldActionServicePoolIdNew)|| 28450 (fa->action != bcmFieldActionServicePoolIdPrecedenceNew)) { 28451 28452 /* Insert action to the destination slice actions list. */ 28453 fa->next = f_ent[dst_idx].actions; 28454 f_ent[dst_idx].actions = fa; 28455 /* Remove action from the primary slice actions list. */ 28456 if (NULL == fa_prev) { 28457 f_ent[src_idx].actions = fa_next; 28458 } else { 28459 fa_prev->next = fa_next; 28460 } 28461 } else { 28462 fa_prev = fa; 28463 } 28464 fa = fa_next; 28465 } 28466 } 28467 return (BCM_E_NONE); 28468 } 28469 28470 /* 28471 * Function: _field_entry_tcam_remove 28472 * 28473 * Purpose: 28474 * Remove an entry from the FP tcam. 28475 * 28476 * Parameters: 28477 * unit - (IN) BCM device number 28478 * fc - (IN) Field control structure. 28479 * f_ent - (IN) Primary entry pointer. 28480 * tcam_idx - (IN) Entry tcam index. 28481 * 28482 * Returns: 28483 * BCM_E_XXX 28484 */ 28485 int 28486 _field_entry_tcam_remove(int unit, _field_control_t *fc, 28487 _field_entry_t *f_ent, int tcam_idx) 28488 { 28489 int rv; /* Operation return status. */ 28490 28491 /* Input parameter check. */ 28492 if ((NULL == fc) || (NULL == f_ent)) { 28493 return (BCM_E_PARAM); 28494 } 28495 /* Remove entry in slice. */ 28496 if (f_ent->fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 28497 rv = fc->functions.fp_external_entry_remove(unit, f_ent); 28498 BCM_IF_ERROR_RETURN(rv); 28499 } else { 28500 rv = fc->functions.fp_entry_remove(unit, f_ent, tcam_idx); 28501 BCM_IF_ERROR_RETURN(rv); 28502 } 28503 return (rv); 28504 } 28505 28506 /* 28507 * Function: 28508 * _field_tcam_policy_reinstall 28509 * 28510 * Purpose: 28511 * Re-Install a POLICY_TABLE entry. This re-writes the 28512 * modified actions to the hardware. 28513 * 28514 * Parameters: 28515 * unit - (IN) BCM device number. 28516 * entry - (IN) Entry to be installed. 28517 * Returns: 28518 * BCM_E_XXX 28519 */ 28520 int 28521 _field_tcam_policy_reinstall(int unit, bcm_field_entry_t entry) 28522 { 28523 int tcam_idx[_FP_MAX_ENTRY_WIDTH]; /* Entry tcam index. */ 28524 int parts_count = 0; /* Field entry parts count. */ 28525 _field_entry_t *f_ent; /* Field entry pointer. */ 28526 _field_control_t *fc; /* Field control structure. */ 28527 int idx; /* Iteration index. */ 28528 int rv; /* Operation return status. */ 28529 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 28530 defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 28531 _field_entry_stat_t *f_ent_st = NULL; /* Field entry statistics 28532 structure. */ 28533 _field_stat_t *f_st = NULL; /* Statistics entity 28534 descriptor. */ 28535 #endif 28536 28537 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 28538 LOG_DEBUG(BSL_LS_BCM_FP, 28539 (BSL_META_U(unit, 28540 "FP(unit %d) vverb: _field_tcam_policy_reinstall (%d)\n"), 28541 unit, entry)); 28542 28543 28544 /* Installing the entry. */ 28545 rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent); 28546 BCM_IF_ERROR_RETURN(rv); 28547 28548 /* Get number of parts. */ 28549 rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id, 28550 f_ent->group->flags, &parts_count); 28551 BCM_IF_ERROR_RETURN(rv); 28552 28553 /* Initialize tcam_idx array. */ 28554 sal_memset(tcam_idx, 0, sizeof(tcam_idx)); 28555 28556 /* Get tcam indexes for installed entry. */ 28557 if (f_ent->group->stage_id != _BCM_FIELD_STAGE_EXTERNAL) { 28558 for (idx = parts_count - 1; idx >=0; idx--) { 28559 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx, 28560 tcam_idx + idx); 28561 BCM_IF_ERROR_RETURN(rv); 28562 } 28563 } 28564 28565 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 28566 /* Advanced flex STAT counters reference count handled here. */ 28567 if ((f_ent->flags & _FP_ENTRY_INSTALLED) && 28568 (soc_feature(unit, soc_feature_advanced_flex_counter)) && 28569 !(soc_feature(unit, soc_feature_field_multi_pipe_support))) { 28570 28571 for (idx = 0; idx < parts_count; idx++) { 28572 /* Read existing entry qualifiers from the HW. */ 28573 BCM_IF_ERROR_RETURN 28574 (_bcm_field_qual_tcam_key_mask_get(unit, 28575 f_ent + idx)); 28576 28577 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) { 28578 f_ent_st = &((f_ent + idx)->statistic); 28579 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) { 28580 /* Read stat entity configuration. */ 28581 if ((f_ent_st->flags & _FP_ENTRY_EXTENDED_STAT_VALID) && 28582 soc_feature(unit, soc_feature_flex_stat_compaction_support)) { 28583 /* Read stat entity configuration. */ 28584 BCM_IF_ERROR_RETURN 28585 (_bcm_field_stat_get(unit, f_ent_st->extended_sid, &f_st)); 28586 } else { 28587 BCM_IF_ERROR_RETURN 28588 (_bcm_field_stat_get(unit, f_ent_st->sid, &f_st)); 28589 } 28590 if (f_st->hw_ref_count > 0) { 28591 /* 28592 * If this is the only entry using this stat, store the stat 28593 * values to retain on next attach. 28594 */ 28595 if (1 == f_st->hw_ref_count) { 28596 int i; 28597 for (i= 0; i < f_st->nstat; i++) { 28598 rv = _field_stat_value_get(unit, 0, f_st, 28599 f_st->stat_arr[i], 28600 f_st->stat_values + i); 28601 BCM_IF_ERROR_RETURN(rv); 28602 } 28603 } 28604 BCM_IF_ERROR_RETURN 28605 (_bcm_esw_stat_flex_detach_ingress_table_counters 28606 (unit, VFP_POLICY_TABLEm, tcam_idx[idx])); 28607 if (soc_feature(unit, soc_feature_flex_stat_compaction_support)) { 28608 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED; 28609 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED; 28610 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 28611 } else { 28612 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 28613 } 28614 f_st->hw_ref_count--; 28615 } 28616 } 28617 } 28618 28619 if (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id) { 28620 f_ent_st = &((f_ent + idx)->statistic); 28621 if (f_ent_st->flags & _FP_ENTRY_EXTENDED_STAT_INSTALLED) { 28622 /* Read stat entity configuration. */ 28623 BCM_IF_ERROR_RETURN 28624 (_bcm_field_stat_get(unit, f_ent_st->extended_sid, &f_st)); 28625 if (f_st->hw_ref_count > 0) { 28626 /* 28627 * If this is the only entry using this stat, store the stat 28628 * values to retain on next attach. 28629 */ 28630 if (1 == f_st->hw_ref_count) { 28631 int i; 28632 for (i= 0; i < f_st->nstat; i++) { 28633 rv = _field_stat_value_get(unit, 0, f_st, 28634 f_st->stat_arr[i], 28635 f_st->stat_values + i); 28636 BCM_IF_ERROR_RETURN(rv); 28637 } 28638 } 28639 28640 rv = _bcm_esw_stat_flex_detach_ingress_table_counters 28641 (unit, FP_POLICY_TABLEm, tcam_idx[idx]); 28642 BCM_IF_ERROR_RETURN(rv); 28643 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED; 28644 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED; 28645 f_st->hw_ref_count--; 28646 } 28647 } 28648 } 28649 28650 if (_BCM_FIELD_STAGE_EGRESS == f_ent->fs->stage_id) { 28651 f_ent_st = &((f_ent + idx)->statistic); 28652 if (f_ent_st->flags & _FP_ENTRY_EXTENDED_STAT_INSTALLED) { 28653 /* Read stat entity configuration. */ 28654 BCM_IF_ERROR_RETURN 28655 (_bcm_field_stat_get(unit, f_ent_st->extended_sid, &f_st)); 28656 if (f_st->hw_ref_count > 0) { 28657 /* 28658 * If this is the only entry using this stat, store the stat 28659 * values to retain on next attach. 28660 */ 28661 if (1 == f_st->hw_ref_count) { 28662 int i; 28663 for (i= 0; i < f_st->nstat; i++) { 28664 rv = _field_stat_value_get(unit, 0, f_st, 28665 f_st->stat_arr[i], 28666 f_st->stat_values + i); 28667 BCM_IF_ERROR_RETURN(rv); 28668 } 28669 } 28670 28671 rv = _bcm_esw_stat_flex_detach_egress_table_counters 28672 (unit, 0, EFP_POLICY_TABLEm, tcam_idx[idx]); 28673 BCM_IF_ERROR_RETURN(rv); 28674 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED; 28675 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED; 28676 f_st->hw_ref_count--; 28677 } 28678 } 28679 } 28680 } 28681 } 28682 #endif 28683 28684 #if defined(BCM_HURRICANE3_SUPPORT) 28685 /* Advanced flowcnt STAT counters reference count handled here. */ 28686 if ((f_ent->flags & _FP_ENTRY_INSTALLED) && 28687 (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) && 28688 (soc_feature(unit, soc_feature_flowcnt))) { 28689 28690 for (idx = 0; idx < parts_count; idx++) { 28691 /* Read existing entry qualifiers from the HW. */ 28692 BCM_IF_ERROR_RETURN 28693 (_bcm_field_qual_tcam_key_mask_get(unit, 28694 f_ent + idx)); 28695 28696 f_ent_st = &((f_ent + idx)->statistic); 28697 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) { 28698 /* Read stat entity configuration. */ 28699 BCM_IF_ERROR_RETURN 28700 (_bcm_field_stat_get(unit, f_ent_st->sid, &f_st)); 28701 if (f_st->hw_ref_count > 0) { 28702 28703 /* 28704 * If this is the only entry using this stat, store the stat 28705 * values to retain on next attach. 28706 */ 28707 if (1 == f_st->hw_ref_count) { 28708 int i; 28709 for (i= 0; i < f_st->nstat; i++) { 28710 rv = _field_stat_value_get(unit, 0, f_st, 28711 f_st->stat_arr[i], 28712 f_st->stat_values + i); 28713 BCM_IF_ERROR_RETURN(rv); 28714 } 28715 } 28716 28717 BCM_IF_ERROR_RETURN( 28718 _bcm_esw_flowcnt_object_table_detach(unit, 28719 VFP_POLICY_TABLEm, tcam_idx[idx])); 28720 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 28721 f_st->hw_ref_count--; 28722 } 28723 } 28724 28725 } 28726 } 28727 #endif 28728 28729 28730 #if defined(BCM_TOMAHAWK_SUPPORT) 28731 if ((f_ent->flags & _FP_ENTRY_INSTALLED) && 28732 ((_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id) || 28733 (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id))&& 28734 (soc_feature(unit, soc_feature_advanced_flex_counter)) && 28735 (soc_feature(unit, soc_feature_field_multi_pipe_support))) { 28736 28737 int update_stats = 1; 28738 28739 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) { 28740 if (!(f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY)) { 28741 update_stats = 0; 28742 } 28743 } 28744 28745 if (update_stats) { 28746 f_ent_st = &(f_ent->statistic); 28747 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) { 28748 28749 soc_mem_t tcam_mem = INVALIDm; 28750 soc_mem_t policy_mem = INVALIDm; 28751 28752 /* Read stat entity configuration. */ 28753 rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st); 28754 BCM_IF_ERROR_RETURN(rv); 28755 28756 if (f_st->hw_ref_count > 0) { 28757 28758 int policy_idx; 28759 28760 /* If this is the only entry using this stat, store the stat 28761 * values to retain on next attach. 28762 */ 28763 28764 if (0 == (f_st->hw_ref_count - 1)) { 28765 for (idx= 0; idx < f_st->nstat; idx++) { 28766 rv = _field_stat_value_get(unit, 0, f_st, 28767 f_st->stat_arr[idx], 28768 f_st->stat_values + idx); 28769 BCM_IF_ERROR_RETURN(rv); 28770 } 28771 } 28772 28773 /* (Intra Slice) Double Wide/ Triple wide modes, IFP_TCAM_WIDE 28774 * have 256 entries but IFP_POLICY_TABLE will have 512 entries. 28775 */ 28776 if ((SOC_IS_TOMAHAWKX(unit)) && 28777 (f_ent->fs->stage_id == _BCM_FIELD_STAGE_INGRESS) && 28778 (!(f_ent->group->flags & _FP_GROUP_SPAN_SINGLE_SLICE) || 28779 (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) 28780 )) { 28781 policy_idx = tcam_idx[0] + (f_ent->fs->slice_number * 256); 28782 } else { 28783 policy_idx = tcam_idx[0]; 28784 } 28785 28786 rv = _bcm_field_th_tcam_policy_mem_get(unit, f_ent, 28787 &tcam_mem, &policy_mem); 28788 BCM_IF_ERROR_RETURN(rv); 28789 28790 28791 /* Stats are attached to only first part of multiwide group. 28792 * So in calling stat detach for tcam_idx[0] is enough. 28793 */ 28794 if ((soc_feature(unit, soc_feature_td3_style_fp) 28795 && (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id))) { 28796 rv = 28797 _bcm_esw_stat_flex_detach_ingress_table_counters_sw( 28798 unit, 28799 policy_mem, 0, 28800 f_st->hw_mode, 28801 f_st->hw_index, 28802 f_st->pool_index); 28803 } else { 28804 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 28805 unit, 28806 policy_mem, 28807 policy_idx); 28808 } 28809 BCM_IF_ERROR_RETURN(rv); 28810 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 28811 f_st->hw_ref_count--; 28812 } 28813 } 28814 } 28815 } 28816 #endif 28817 28818 /* Remove deleted actions. */ 28819 rv = _field_invalid_actions_remove(unit, f_ent); 28820 BCM_IF_ERROR_RETURN(rv); 28821 28822 /* Allocate hw resources required for entry installation. */ 28823 rv = _field_hw_resources_alloc(unit, f_ent); 28824 BCM_IF_ERROR_RETURN(rv); 28825 28826 /* Move all actions to the slice where meter resides. */ 28827 rv = _field_entry_actions_meter_slice_move(unit, f_ent, TRUE); 28828 if (BCM_FAILURE(rv)) { 28829 BCM_IF_ERROR_RETURN 28830 (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE)); 28831 return (rv); 28832 } 28833 28834 /* 28835 * For stages that support global meter pools, meters must be in 28836 * same slice as counters. Move policer to counter slice if 28837 * counters are in secondary slice. 28838 */ 28839 rv = _field_entry_policer_stat_slice_move(unit, f_ent, TRUE); 28840 if (BCM_FAILURE(rv)) { 28841 BCM_IF_ERROR_RETURN 28842 (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE)); 28843 return (rv); 28844 } 28845 28846 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 28847 rv = _field_tcam_policy_external_reinstall(unit, f_ent); 28848 } else { 28849 for (idx = parts_count - 1; idx >=0; idx--) { 28850 28851 LOG_DEBUG(BSL_LS_BCM_FP, 28852 (BSL_META_U(unit, 28853 "FP(unit %d) vverb: Part:%x EntryDirty:%x" 28854 " ActionOnlyDirty:%x\n"), unit, idx, 28855 (f_ent[idx].flags & _FP_ENTRY_DIRTY), 28856 (f_ent[idx].flags & _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY))); 28857 28858 /* 28859 * For Trident FP_GM_FIELDS.VALID = 1 when used in paired mode 28860 */ 28861 if (((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit))) 28862 && (!soc_feature(unit, soc_feature_field_multi_pipe_support)) && 28863 SOC_IS_TD_TT(unit) && (idx == 1) && 28864 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 28865 f_ent[idx].flags |= _FP_ENTRY_USES_IPBM_OVERLAY; 28866 } 28867 28868 /* Get entry tcam key/mask. */ 28869 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + idx); 28870 if (BCM_FAILURE(rv)) { 28871 break; 28872 } 28873 28874 if (f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY) { 28875 f_ent[idx].statistic.flags |= _FP_ENTRY_STAT_DIRTY; 28876 } 28877 28878 /* Install physical entry into primary slice */ 28879 rv = fc->functions.fp_tcam_policy_reinstall(unit, f_ent + idx, 28880 tcam_idx[idx]); 28881 if (BCM_FAILURE(rv)) { 28882 break; 28883 } 28884 28885 f_ent[idx].flags &= ~_FP_ENTRY_DIRTY; 28886 f_ent[idx].flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY); 28887 f_ent[idx].statistic.flags &= ~_FP_ENTRY_STAT_DIRTY; 28888 28889 if(NULL != f_ent[idx].tcam.key) { 28890 sal_free(f_ent[idx].tcam.key); 28891 } 28892 28893 if(NULL != f_ent[idx].tcam.mask) { 28894 sal_free(f_ent[idx].tcam.mask); 28895 } 28896 28897 f_ent[idx].tcam.key = f_ent[idx].tcam.mask = NULL; 28898 } 28899 } 28900 28901 if (BCM_FAILURE(rv)) { 28902 (void)_field_entry_actions_meter_slice_move(unit, f_ent, FALSE); 28903 (void)_field_entry_policer_stat_slice_move(unit, f_ent, FALSE); 28904 (void)_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE); 28905 return (rv); 28906 } 28907 28908 /* Move all actions back to the primary slice . */ 28909 rv = _field_entry_actions_meter_slice_move(unit, f_ent, FALSE); 28910 if (BCM_FAILURE(rv)) { 28911 BCM_IF_ERROR_RETURN 28912 (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE)); 28913 return (rv); 28914 } 28915 28916 /* Move policers to primary slice. */ 28917 rv = _field_entry_policer_stat_slice_move(unit, f_ent, FALSE); 28918 if (BCM_FAILURE(rv)) { 28919 BCM_IF_ERROR_RETURN 28920 (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE)); 28921 return (rv); 28922 } 28923 28924 28925 /* Remove stale deleted actions. */ 28926 rv = _field_invalid_actions_remove(unit, f_ent); 28927 BCM_IF_ERROR_RETURN(rv); 28928 28929 /* In case of entry reinstall free previous installation hw resources. */ 28930 rv = _field_hw_resources_free(unit, f_ent, _FP_ACTION_OLD_RESOURCE_FREE); 28931 if (BCM_FAILURE(rv)) { 28932 BCM_IF_ERROR_RETURN 28933 (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE)); 28934 return (rv); 28935 } 28936 return (BCM_E_NONE); 28937 } 28938 28939 /* 28940 * Function: 28941 * bcm_field_find_free_index_in_slice 28942 * 28943 * Purpose: 28944 * Find free index near by current entry 28945 * 28946 * Parameters: 28947 * unit - (IN) BCM device number. 28948 * f_ent_orig - (IN) Current Entry 28949 * direction - (OUT) Direction in which free index found 28950 * free_idx - (OUT) Found free index 28951 * 28952 * Returns: 28953 * BCM_E_INTERNAL -> If free count in slice is zero 28954 * BCM_E_XXX 28955 */ 28956 28957 STATIC int 28958 _bcm_field_find_free_index_in_slice(int unit, _field_entry_t *f_ent_orig, 28959 int *direction, uint32 *free_idx) 28960 { 28961 int iter = 0; 28962 int idx = 0; 28963 28964 idx = f_ent_orig->slice_idx; 28965 28966 if (0 == f_ent_orig->fs->free_count) { 28967 return BCM_E_INTERNAL; 28968 } 28969 28970 for (iter = 0; iter < f_ent_orig->fs->entry_count; iter++) { 28971 if (((idx + iter) < f_ent_orig->fs->entry_count) && 28972 (NULL == f_ent_orig->fs->entries[idx + iter])) { 28973 *direction = _FP_ENTRY_MOVE_DOWN; /* Found Down side */ 28974 *free_idx = idx + iter; 28975 break; 28976 } 28977 if (((idx - iter) >= 0) && 28978 (NULL == f_ent_orig->fs->entries[idx - iter])) { 28979 *direction = _FP_ENTRY_MOVE_UP; /* Found Up side */ 28980 *free_idx = idx - iter; 28981 break; 28982 } 28983 if (((idx + iter) >= f_ent_orig->fs->entry_count) && ((idx - iter) <= 0)) { 28984 break; 28985 } 28986 } 28987 return BCM_E_NONE; 28988 } 28989 28990 /* 28991 * Function: 28992 * _bcm_field_slice_entry_compress 28993 * 28994 * Purpose: 28995 * Compress slice between Start and End TCAM indices 28996 * 28997 * Parameters: 28998 * unit - (IN) BCM device number. 28999 * stage_fc - (IN) Field Stage control structure 29000 * fg - (IN) Field Group structure 29001 * start_tcam_idx - (IN) Index with hole towards which 29002 * compress will be done 29003 * end_tcam_idx - (IN) End Index for slice compress 29004 * direction - (IN) direction(UP/DOWN) towards 29005 * which compression will be done 29006 * first_free_idx - (OUT) Writes the first found free index 29007 * after compression 29008 * if first_free_idx is not NULL. 29009 * 29010 * Returns: 29011 * BCM_E_INTERNAL -> If start index is not NULL or end index is NULL 29012 * BCM_E_XXX 29013 */ 29014 STATIC int 29015 _bcm_field_slice_entry_compress(int unit, _field_stage_t *stage_fc, _field_group_t *fg, 29016 int start_tcam_idx, int end_tcam_idx, int direction, 29017 int *first_free_idx) 29018 { 29019 int from_idx = 0; 29020 int to_idx = 0; 29021 int rv = BCM_E_NONE; 29022 int start_idx = 0; 29023 int end_idx = 0; 29024 int start_slice_numb = 0; 29025 int end_slice_numb = 0; 29026 int slice_numb = 0; 29027 int slice_idx = 0; 29028 _field_slice_t *fs = NULL; 29029 _field_slice_t *start_fs = NULL; 29030 _field_slice_t *end_fs = NULL; 29031 29032 if ((NULL == stage_fc) || (NULL == fg)) { 29033 return BCM_E_PARAM; 29034 } 29035 29036 /* Getting starting slice number and starting slice offset */ 29037 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance, 29038 start_tcam_idx, &start_slice_numb, 29039 &start_idx); 29040 BCM_IF_ERROR_RETURN(rv); 29041 /* Getting end slice number and ending slice offset */ 29042 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance, 29043 end_tcam_idx, &end_slice_numb, 29044 &end_idx); 29045 BCM_IF_ERROR_RETURN(rv); 29046 29047 start_fs = stage_fc->slices[fg->instance] + start_slice_numb; 29048 end_fs = stage_fc->slices[fg->instance] + end_slice_numb; 29049 29050 fs = start_fs; 29051 29052 /* 29053 * Entry present in Start index is expected to be NULL as compression 29054 * may overwrite the existing entry. 29055 * Entry present in End index is expected to be not NULL as compression 29056 * ends with end index compressing NULL entry can't be done. 29057 */ 29058 if ((start_fs->entries[start_idx] != NULL) || (end_fs->entries[end_idx] == NULL)) { 29059 LOG_DEBUG(BSL_LS_BCM_FP, 29060 (BSL_META_U(unit, 29061 "FP(unit %d) Wrong index provided to compress \n"), 29062 unit)); 29063 return BCM_E_INTERNAL; 29064 } 29065 29066 /************************************************************************************************* 29067 Compression logic explained 29068 --------------------------- 29069 Direction : _FP_ENTRY_MOVE_DOWN 29070 Start TCAm index : 7 29071 End TCAM idx : 2 29072 29073 1. 29074 ______ 29075 |______|1 29076 |______|2 ==> End TCAM index 29077 |______|3 29078 |______|4 29079 |______|5 29080 |______|6 29081 |_NULL_|7 ==> Start TCAM index 29082 |______|8 29083 29084 Entry@6 will be copied to 7. 29085 then entry@5 will be copied to 6....... 29086 and ends with entry@2 copy to 3. 29087 ______ ______ 29088 |______|1 |______|1 29089 |______|2 |_NULL_|2 ==> first found free index 29090 |______|3 |______|3 29091 |______|4 ....> |______|4 29092 |______|5 ....> |______|5 29093 |_NULL_|6 |______|6 29094 |______|7 <-- |______|7 29095 |______|8 |______|8 29096 29097 and first free index will be assigned to 2 29098 if first_free_idx is not NULL ptr. 29099 29100 2. 29101 ______ 29102 |______|1 29103 |______|2 ==> End TCAM index 29104 |______|3 29105 |_NULL_|4 29106 |_NULL_|5 29107 |______|6 29108 |_NULL_|7 ==> Start TCAM index 29109 |______|8 29110 29111 29112 Entry@6 will be copied to 7. 29113 Entry@5 is NULL and entry@4 is also NULL 29114 so entry@3 will be copied to 6 29115 and then entry@2 is copied to 5. 29116 29117 ______ ______ 29118 |______|1 |______|1 29119 |______|2 |_NULL_|2 29120 |______|3 |_NULL_|3 29121 |_NULL_|4 ....> |_NULL_|4 ==> first found free index 29122 |_NULL_|5 ....> |______|5 29123 |_NULL_|6 |______|6 29124 |______|7 <-- |______|7 29125 |______|8 |______|8 29126 29127 and first free index will be assigned to 4 29128 if first_free_idx is not NULL ptr. 29129 29130 */ 29131 if (direction == _FP_ENTRY_MOVE_DOWN) { 29132 /* free index found in down direction slice has to be compressed towards down */ 29133 for (slice_idx = start_idx - 1, to_idx = start_tcam_idx, from_idx = start_tcam_idx - 1; 29134 from_idx >= end_tcam_idx; from_idx--, slice_idx-- ) { 29135 if (-1 == slice_idx) { 29136 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance, 29137 from_idx, &slice_numb, 29138 &slice_idx); 29139 BCM_IF_ERROR_RETURN(rv); 29140 if (slice_numb != fs->slice_number) { 29141 /* if compression is across slices end TCAM index will be in previous slice */ 29142 fs = fs->prev; 29143 } 29144 } 29145 if (NULL == fs->entries[slice_idx]) { 29146 /* Ignore holes*/ 29147 continue; 29148 } 29149 rv = _field_entry_move(unit, fs->entries[slice_idx], (to_idx - from_idx)); 29150 BCM_IF_ERROR_RETURN(rv); 29151 to_idx--; 29152 } /*End of For*/ 29153 if (NULL != first_free_idx) { 29154 *first_free_idx= to_idx; 29155 } 29156 } else if (direction & _FP_ENTRY_MOVE_UP) { 29157 /* free index found in up direction slice has to be compressed towards up */ 29158 for (slice_idx = start_idx + 1, to_idx = start_tcam_idx, from_idx = start_tcam_idx + 1; 29159 from_idx <= end_tcam_idx; from_idx++, slice_idx++ ) { 29160 if (fs->entry_count == slice_idx) { 29161 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance, 29162 from_idx, &slice_numb, 29163 &slice_idx); 29164 BCM_IF_ERROR_RETURN(rv); 29165 if (slice_numb != fs->slice_number) { 29166 /* if compression is across slices end TCAM index will be in next slice */ 29167 fs = fs->next; 29168 } 29169 } 29170 if (NULL == fs->entries[slice_idx]) { 29171 /* Ignore holes*/ 29172 continue; 29173 } 29174 rv = _field_entry_move(unit, fs->entries[slice_idx], (to_idx - from_idx)); 29175 BCM_IF_ERROR_RETURN(rv); 29176 to_idx++; 29177 }/*End of For*/ 29178 if (NULL != first_free_idx) { 29179 *first_free_idx= to_idx; 29180 } 29181 } else { 29182 return BCM_E_INTERNAL; 29183 } 29184 return BCM_E_NONE; 29185 } 29186 /* 29187 * Function: 29188 * _field_internal_backup_entry_create 29189 * 29190 * Purpose: 29191 * To achieve hitless update by 29192 * creating a temporary entry during 29193 * current entry modification. 29194 * TCAM and FP_POLICY_TABLEs will be 29195 * copied from orginal entry to the 29196 * temperary entry and 29197 * New Hardware won't be allocated for 29198 * Temperary entry. 29199 * 29200 * Parameters: 29201 * unit - (IN) BCM device number. 29202 * entry - (IN) Current Entry 29203 * temp_entry - (OUT) Entry to be installed. 29204 * 29205 * Returns: 29206 * BCM_E_XXX 29207 */ 29208 STATIC int 29209 _field_internal_backup_entry_create(int unit, bcm_field_entry_t entry, 29210 bcm_field_entry_t *temp_entry) 29211 { 29212 int rv = BCM_E_NONE; /* Return Variable */ 29213 int tcam_idx_orig[_FP_MAX_ENTRY_WIDTH] = {0}; /* Original entry tcam index. */ 29214 int tcam_idx_temp[_FP_MAX_ENTRY_WIDTH] = {0}; /* temp tcam index for the entry.*/ 29215 int idx; 29216 int parts_count = 0; /* Field entry parts count. */ 29217 int direction = 0; 29218 int free_idx_after_compress = 0; 29219 int start_tcam_idx = 0; 29220 int end_tcam_idx = 0; 29221 uint32 free_idx = 0; 29222 uint32 start_idx = 0; 29223 uint32 end_idx = 0; 29224 _field_stage_t *stage_fc = NULL; /* Stage field control structure */ 29225 _field_control_t *fc = NULL; /* Field control structure. */ 29226 _field_entry_t *f_ent_temp = NULL; 29227 _field_entry_t *f_ent_copy_temp = NULL; 29228 _field_entry_t *f_ent_orig = NULL; 29229 29230 LOG_DEBUG(BSL_LS_BCM_FP, 29231 (BSL_META_U(unit, 29232 "FP(unit %d) vverb: _field_internal_backup_entry_create (%d)\n"), 29233 unit, entry)); 29234 /* Check whether entry with INTERNAL_RESERVED_ID is already present */ 29235 if (BCM_SUCCESS(_field_entry_get(unit, (_FP_INTERNAL_RESERVED_ID), 29236 _FP_ENTRY_PRIMARY, 29237 &f_ent_temp))) { 29238 LOG_DEBUG(BSL_LS_BCM_FP, 29239 (BSL_META_U(unit, 29240 "FP(unit %d) Error: " 29241 "Entry _FP_INTERNAL_RESERVED_ID already present" 29242 "Unable to create backup entry for entry (%d)\n"), 29243 unit, entry)); 29244 return BCM_E_EXISTS; 29245 } 29246 29247 /* Get the original entry */ 29248 BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, 29249 _FP_ENTRY_PRIMARY, 29250 &f_ent_orig)); 29251 29252 /* Get field and stage control structures. */ 29253 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 29254 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, f_ent_orig->group->stage_id, &stage_fc)); 29255 29256 *temp_entry = (_FP_INTERNAL_RESERVED_ID); 29257 /* Create backup entry sharing 29258 the same group with original entry */ 29259 rv = _field_entry_create_id (unit, 29260 f_ent_orig->group->gid, 29261 *temp_entry); 29262 /* Fall back to old method if new entry has no space */ 29263 if (BCM_FAILURE(rv)) { 29264 if ((rv == BCM_E_RESOURCE) && ((soc_property_get(unit, 29265 spn_FIELD_ATOMIC_UPDATE, FALSE) == TRUE))) { 29266 return rv; 29267 } 29268 goto fallback; 29269 } 29270 29271 if (!(f_ent_orig->flags & _FP_ENTRY_CREATED_WITHOUT_PRIO)) { 29272 rv = _field_entry_prio_set(unit, *temp_entry, f_ent_orig->prio); 29273 if (BCM_FAILURE(rv)) { 29274 LOG_DEBUG(BSL_LS_BCM_FP, 29275 (BSL_META_U(unit, 29276 "FP(unit %d) Error: " 29277 "Unable to create backup entry for entry (%d)" 29278 "Entry prio set failed with error %d \n"), 29279 unit, entry, rv)); 29280 goto fallback; 29281 } 29282 } 29283 /* Get created backup entry*/ 29284 rv = _field_entry_get(unit, *temp_entry, 29285 _FP_ENTRY_PRIMARY, 29286 &f_ent_temp); 29287 if (BCM_FAILURE(rv)) { 29288 LOG_DEBUG(BSL_LS_BCM_FP, 29289 (BSL_META_U(unit, 29290 "FP(unit %d) Error: " 29291 "Unable to create backup entry for entry (%d)" 29292 "backup entry get failed with error %d \n"), 29293 unit, entry, rv)); 29294 rv = BCM_E_INTERNAL; 29295 goto fallback; 29296 } 29297 /* Get number of parts. */ 29298 rv = _bcm_field_entry_tcam_parts_count (unit, f_ent_orig->group->stage_id, 29299 f_ent_orig->group->flags, &parts_count); 29300 if (BCM_FAILURE(rv)) { 29301 LOG_DEBUG(BSL_LS_BCM_FP, 29302 (BSL_META_U(unit, 29303 "FP(unit %d) Error: " 29304 "Unable to create backup entry for entry (%d)" 29305 "Getting Parts count for original entry failed with error : %d"), 29306 unit, entry, rv)); 29307 rv = BCM_E_INTERNAL; 29308 goto fallback; 29309 } 29310 /* backup entry and original entry entry are not in same slice*/ 29311 if (f_ent_orig->fs->slice_number != f_ent_temp->fs->slice_number) { 29312 /* Check for the global Policers and Statistics associated with the entry. */ 29313 /* Global policer and Installed || Global Stats and installed */ 29314 if(((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) && 29315 ((f_ent_orig->policer[0].flags & _FP_POLICER_INSTALLED) || 29316 (f_ent_orig->policer[1].flags & _FP_POLICER_INSTALLED))) || 29317 ((0 == ((stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) || 29318 (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS))) && 29319 (f_ent_orig->statistic.flags & _FP_ENTRY_STAT_INSTALLED))) { 29320 if (0 == f_ent_orig->fs->free_count) { 29321 LOG_DEBUG(BSL_LS_BCM_FP, 29322 (BSL_META_U(unit, 29323 "FP(unit %d) Error: " 29324 "Unable to create backup entry for entry (%d)" 29325 "No free space in original entry slice\n"), 29326 unit, entry)); 29327 rv = BCM_E_CONFIG; 29328 goto fallback; 29329 } 29330 29331 /* Find the nearest free index to the original entry and direction */ 29332 rv = _bcm_field_find_free_index_in_slice (unit, f_ent_orig, &direction, &free_idx); 29333 if (BCM_FAILURE(rv)) { 29334 LOG_DEBUG(BSL_LS_BCM_FP, 29335 (BSL_META_U(unit, 29336 "FP(unit %d) Error: " 29337 "Unable to create backup entry for entry (%d)" 29338 "Finding free idx failed with error : %d\n"), 29339 unit, entry, rv)); 29340 rv = BCM_E_INTERNAL; 29341 goto fallback; 29342 } 29343 29344 start_idx = free_idx; 29345 /* 29346 * keep the orginal entry stable and move in between entries 29347 * from free index and original entry index 29348 */ 29349 end_idx = (_FP_ENTRY_MOVE_UP == direction) ? 29350 (f_ent_orig->slice_idx - 1) : 29351 (f_ent_orig->slice_idx + 1); 29352 if (start_idx != end_idx) { 29353 /* Get Start TCAM index based on start slice offset */ 29354 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 29355 f_ent_orig->group->instance, 29356 f_ent_orig->fs->slice_number, 29357 start_idx, &start_tcam_idx); 29358 if (BCM_FAILURE(rv)) { 29359 LOG_DEBUG(BSL_LS_BCM_FP, 29360 (BSL_META_U(unit, 29361 "FP(unit %d) Error: " 29362 "Unable to create backup entry for entry (%d)" 29363 "slice compress failed with error %d \n"), 29364 unit, entry, rv)); 29365 rv = BCM_E_INTERNAL; 29366 goto fallback; 29367 } 29368 /* Get end TCAM index based on end slice offset */ 29369 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 29370 f_ent_orig->group->instance, 29371 f_ent_orig->fs->slice_number, 29372 end_idx, &end_tcam_idx); 29373 if (BCM_FAILURE(rv)) { 29374 LOG_DEBUG(BSL_LS_BCM_FP, 29375 (BSL_META_U(unit, 29376 "FP(unit %d) Error: " 29377 "Unable to create backup entry for entry (%d)" 29378 "slice compress failed with error %d \n"), 29379 unit, entry, rv)); 29380 rv = BCM_E_INTERNAL; 29381 goto fallback; 29382 } 29383 /* Compress slice towards the free index and 29384 * make hole near by original entry 29385 */ 29386 rv = _bcm_field_slice_entry_compress (unit, 29387 stage_fc, f_ent_orig->group, 29388 start_tcam_idx, end_tcam_idx, direction, 29389 &free_idx_after_compress); 29390 if (BCM_FAILURE(rv)) { 29391 LOG_DEBUG(BSL_LS_BCM_FP, 29392 (BSL_META_U(unit, 29393 "FP(unit %d) Error: " 29394 "Unable to create backup entry for entry (%d)" 29395 "slice compress failed with error %d \n"), 29396 unit, entry, rv)); 29397 rv = BCM_E_INTERNAL; 29398 goto fallback; 29399 } 29400 } else { 29401 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 29402 f_ent_orig->group->instance, 29403 f_ent_orig->fs->slice_number, 29404 start_idx, &start_tcam_idx); 29405 if (BCM_FAILURE(rv)) { 29406 LOG_DEBUG(BSL_LS_BCM_FP, 29407 (BSL_META_U(unit, 29408 "FP(unit %d) Error: " 29409 "Unable to create backup entry for entry (%d)" 29410 "slice compress failed with error %d \n"), 29411 unit, entry, rv)); 29412 rv = BCM_E_INTERNAL; 29413 goto fallback; 29414 } 29415 free_idx_after_compress = start_tcam_idx; 29416 } 29417 29418 29419 /* Get the tcam_idx for all parts of backup entry using 29420 * free_idx_after_compress 29421 */ 29422 for (idx = 0; idx < parts_count; idx++) { 29423 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent_temp, 29424 free_idx_after_compress, 29425 idx, &tcam_idx_temp[idx]); 29426 if (BCM_FAILURE(rv)) { 29427 LOG_DEBUG(BSL_LS_BCM_FP, 29428 (BSL_META_U(unit, 29429 "FP(unit %d) Error: " 29430 "Unable to create backup entry for entry (%d)" 29431 "tcam idx get failed for part %d " 29432 "with rv %d \n"), 29433 unit, entry, idx, rv)); 29434 rv = BCM_E_INTERNAL; 29435 goto fallback; 29436 } 29437 } 29438 /* change slice index of backup entry to the 29439 * tcam_idx_temp after compres 29440 */ 29441 rv = _field_entry_slice_idx_change (unit, 29442 f_ent_temp, parts_count,tcam_idx_temp); 29443 if (BCM_FAILURE(rv)) { 29444 LOG_DEBUG(BSL_LS_BCM_FP, 29445 (BSL_META_U(unit, 29446 "FP(unit %d) Error: " 29447 "Unable to create backup entry for entry (%d)" 29448 "backup entry slice idx change to the found " 29449 "free idx failed with error %d \n"), 29450 unit, entry, rv)); 29451 rv = BCM_E_INTERNAL; 29452 goto fallback; 29453 } 29454 } 29455 } 29456 /* Calculate the new and old TCAM indexes. */ 29457 for (idx = 0; idx < parts_count; idx++) { 29458 /* Calculate the new and old TCAM indexes. */ 29459 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent_orig + idx, 29460 &tcam_idx_orig[idx]); 29461 if (BCM_FAILURE(rv)) { 29462 LOG_DEBUG(BSL_LS_BCM_FP, 29463 (BSL_META_U(unit, 29464 "FP(unit %d) Error: " 29465 "Unable to create backup entry for entry (%d)" 29466 "TCAM index get for orig entry failed " 29467 "with error %d \n"), 29468 unit, entry, rv)); 29469 rv = BCM_E_INTERNAL; 29470 goto fallback; 29471 } 29472 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent_temp + idx, 29473 &tcam_idx_temp[idx]); 29474 if (BCM_FAILURE(rv)) { 29475 LOG_DEBUG(BSL_LS_BCM_FP, 29476 (BSL_META_U(unit, 29477 "FP(unit %d) Error: " 29478 "Unable to create backup entry for entry (%d)" 29479 "TCAM index get for backup entry failed " 29480 "with error %d \n"), 29481 unit, entry, rv)); 29482 rv = BCM_E_INTERNAL; 29483 goto fallback; 29484 } 29485 } 29486 /* store orginal entry's ent_copy*/ 29487 f_ent_copy_temp = f_ent_orig->ent_copy; 29488 /* 29489 * Assign backup entry to the ent_copy as fp_entry_move 29490 * should not clear FP_TCAM and FP_POLICY_TABLE of original entry 29491 */ 29492 f_ent_orig->ent_copy = f_ent_temp; 29493 29494 rv = fc->functions.fp_entry_move(unit, f_ent_orig, parts_count, 29495 tcam_idx_orig, tcam_idx_temp); 29496 if (BCM_FAILURE(rv)) { 29497 LOG_DEBUG(BSL_LS_BCM_FP, 29498 (BSL_META_U(unit, 29499 "FP(unit %d) Error: " 29500 "Unable to create backup entry for entry (%d)" 29501 "hw entry move failed with error %d \n"), 29502 unit, entry, rv)); 29503 rv = BCM_E_INTERNAL; 29504 } 29505 29506 f_ent_temp->flags |= _FP_ENTRY_INSTALLED; 29507 f_ent_temp->flags |= _FP_ENTRY_ENABLED; 29508 f_ent_orig->ent_copy = f_ent_copy_temp; 29509 29510 fallback: 29511 /*Common cleanup for the method */ 29512 if (BCM_FAILURE(rv)) { 29513 /* Remove the created backup entry upon failure */ 29514 BCM_IF_ERROR_RETURN(_field_internal_backup_entry_delete(unit, *temp_entry)); 29515 29516 if (BCM_E_INTERNAL == rv) { 29517 return rv; 29518 } 29519 29520 /* Fall back to old method */ 29521 if (soc_property_get(unit, 29522 spn_FIELD_ATOMIC_UPDATE, FALSE) == FALSE) { 29523 LOG_DEBUG(BSL_LS_BCM_FP, 29524 (BSL_META_U(unit, 29525 "FP(unit %d) Error: " 29526 "Unable to create backup entry for entry (%d)" 29527 "Falling back to old method \n"), 29528 unit, entry)); 29529 rv = BCM_E_NONE; 29530 *temp_entry = _FP_INVALID_INDEX; 29531 } 29532 return rv; 29533 } 29534 return BCM_E_NONE; 29535 } 29536 29537 /* 29538 * Function: 29539 * _field_internal_backup_entry_delete 29540 * 29541 * Purpose: 29542 * Delete temporary entry created during 29543 * current entry modification 29544 * to achieve hitless update. 29545 * 29546 * Parameters: 29547 * unit - (IN) BCM device number. 29548 * temp_entry - (IN) Entry to be installed. 29549 * 29550 * Returns: 29551 * BCM_E_XXX 29552 */ 29553 STATIC int 29554 _field_internal_backup_entry_delete(int unit, bcm_field_entry_t temp_entry) 29555 { 29556 int rv = BCM_E_NONE; /* Return Variable */ 29557 _field_entry_t *f_ent_check = NULL ; /* Field entry pointer */ 29558 29559 if (BCM_SUCCESS(_field_entry_get(unit, temp_entry, _FP_ENTRY_PRIMARY, 29560 &f_ent_check))) { 29561 rv = bcm_esw_field_entry_destroy(unit, temp_entry); 29562 } 29563 return (rv); 29564 } 29565 29566 /* 29567 * Function: 29568 * _bcm_field_meter_rate_burst_calculate 29569 * 29570 * Purpose: 29571 * Calculate rate and burst of the meter based on 29572 * granularity, refresh_rate and bucket size. 29573 * 29574 * Parameters: 29575 * unit - (IN) BCM device number. 29576 * meter_mem - (IN) Meter table to read 29577 * meter_hw_idx - (IN) Index in the meter table 29578 * flags - (IN) Policer flags. 29579 * prate - (OUT) Policer rate calculated 29580 * pburst - (OUT) Policer burst calculated 29581 * 29582 * Returns: 29583 * BCM_E_XXX 29584 */ 29585 STATIC int 29586 _bcm_field_meter_rate_burst_calculate (uint32 unit, 29587 soc_mem_t meter_mem, 29588 uint32 meter_hw_idx, 29589 uint32 *prate, 29590 uint32 *pburst, 29591 uint32 flags 29592 ) 29593 { 29594 uint32 ent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 29595 uint32 refresh_rate = 0; /* Policer refresh rate. */ 29596 uint32 granularity = 0; /* Policer granularity. */ 29597 uint32 bucket_max = 0; /* Bucket size. */ 29598 29599 BCM_IF_ERROR_RETURN(soc_mem_read(unit, meter_mem, MEM_BLOCK_ANY, 29600 meter_hw_idx, ent)); 29601 29602 refresh_rate = soc_mem_field32_get(unit, meter_mem, ent, REFRESHCOUNTf); 29603 granularity = soc_mem_field32_get(unit, meter_mem, ent, METER_GRANf); 29604 bucket_max = soc_mem_field32_get(unit, meter_mem, ent, BUCKETSIZEf); 29605 29606 BCM_IF_ERROR_RETURN(_bcm_xgs_bucket_encoding_to_kbits 29607 (refresh_rate, bucket_max, granularity, flags, 29608 prate, pburst)); 29609 29610 return BCM_E_NONE; 29611 } 29612 29613 /* 29614 * Function: 29615 * _field_entry_policer_update_actual_hw_rates 29616 * 29617 * Purpose: 29618 * Update actual hardware rates for committed packet rate 29619 * and burst size and peak packet rate and burst size in 29620 * the internal policer structure. 29621 * 29622 * Parameters: 29623 * unit - (IN) BCM device number. 29624 * policer_mem - (IN) Meter table name. 29625 * instance - (IN) FP instance 29626 * f_ent - (IN) Entry policer belongs to. 29627 * f_pl - (IN) Field policer descriptor. 29628 * 29629 * Returns: 29630 * BCM_E_XXX 29631 */ 29632 int 29633 _field_entry_policer_update_actual_hw_rates(int unit, soc_mem_t policer_mem, 29634 int instance, _field_entry_t *f_ent, _field_policer_t *f_pl) 29635 { 29636 uint32 flags; /* Policer flags. */ 29637 _field_stage_t *stage_fc; /* Field stage information. */ 29638 int meter_hw_idx; /* Meter table index. */ 29639 int rv = BCM_E_NONE; /* Operation return status. */ 29640 soc_mem_t meter_mem = policer_mem; /* Meter table name. */ 29641 int meter_offset = 0; /* Odd or even meter. */ 29642 _field_stage_id_t stage_id; /* StageId used for metering*/ 29643 29644 if ((f_pl == NULL) || (f_ent == NULL)) { 29645 return BCM_E_PARAM; 29646 } 29647 29648 if (meter_mem == INVALIDm) { 29649 return BCM_E_PARAM; 29650 } 29651 29652 stage_id = ((_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) || 29653 (_BCM_FIELD_STAGE_EXTERNAL == f_ent->group->stage_id)) ? \ 29654 _BCM_FIELD_STAGE_INGRESS : f_ent->group->stage_id; 29655 29656 /* Get stage control */ 29657 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 29658 BCM_IF_ERROR_RETURN(rv); 29659 29660 if (f_pl->cfg.mode == bcmPolicerModeCommitted) { 29661 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 29662 meter_offset = 0; 29663 } 29664 else { 29665 meter_offset = 1; 29666 } 29667 } 29668 29669 /* Calculate hardware meter index. */ 29670 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 29671 /* 29672 * Hw index is: 29673 * ((Pool number * pool_size) + (2 * pair number) 29674 */ 29675 meter_hw_idx = (f_pl->pool_index * 29676 stage_fc->meter_pool[instance][f_pl->pool_index]->size) 29677 + (2 * f_pl->hw_index) + meter_offset; 29678 } else { 29679 /* 29680 * Hw index is: 29681 * (slice index) + (2 * pair number) 29682 */ 29683 meter_hw_idx = 29684 stage_fc->slices[instance][f_pl->pool_index].start_tcam_idx 29685 + (2 * f_pl->hw_index) + meter_offset; 29686 } 29687 29688 /* lookup bucket size from tables */ 29689 flags = _BCM_XGS_METER_FLAG_GRANULARITY | _BCM_XGS_METER_FLAG_FP_POLICER; 29690 29691 /* TD2 has change in granularity calculation */ 29692 if ((SOC_IS_TD2_TT2(unit)) && 29693 (f_pl->cfg.flags & BCM_POLICER_MODE_PACKETS)) { 29694 flags = flags | _BCM_XGS_METER_FLAG_FP_TD2_POLICER; 29695 } 29696 29697 /* Set packet mode flags setting */ 29698 if (f_pl->cfg.flags & BCM_POLICER_MODE_PACKETS) { 29699 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 29700 } else { 29701 flags &= ~_BCM_XGS_METER_FLAG_PACKET_MODE; 29702 } 29703 29704 f_pl->cfg.actual_ckbits_sec = 0; 29705 f_pl->cfg.actual_ckbits_burst = 0; 29706 f_pl->cfg.actual_pkbits_sec = 0; 29707 f_pl->cfg.actual_pkbits_burst = 0; 29708 29709 if ((f_pl->cfg.mode == bcmPolicerModeTrTcmDs) || 29710 (f_pl->cfg.mode == bcmPolicerModeTrTcm)|| 29711 (f_pl->cfg.mode == bcmPolicerModeSrTcm) || 29712 (f_pl->cfg.mode == bcmPolicerModeSrTcmTsn) || 29713 (f_pl->cfg.mode == bcmPolicerModeSrTcmModified) || 29714 (f_pl->cfg.mode == bcmPolicerModeCoupledTrTcmDs)){ 29715 _bcm_field_meter_rate_burst_calculate(unit, meter_mem, 29716 meter_hw_idx, &f_pl->cfg.actual_pkbits_sec, 29717 &f_pl->cfg.actual_pkbits_burst, flags); 29718 _bcm_field_meter_rate_burst_calculate(unit, meter_mem, 29719 meter_hw_idx + 1, &f_pl->cfg.actual_ckbits_sec, 29720 &f_pl->cfg.actual_ckbits_burst, flags); 29721 } 29722 else { 29723 _bcm_field_meter_rate_burst_calculate(unit, meter_mem, 29724 meter_hw_idx, &f_pl->cfg.actual_ckbits_sec, 29725 &f_pl->cfg.actual_ckbits_burst, flags); 29726 } 29727 29728 /* In Tomahawk EFP metering, Refresh tick duration has changed from 29729 * 7.8125us to 15.625us ,but the RTL does not double the REFRESHCOUNT 29730 * while putting the tokens into the bucket which is causing 50% lesser 29731 * traffic rate than expected. So the work around is the value programmed 29732 * from software in EFP meters needs to be doubled. 29733 */ 29734 if (soc_feature(unit, soc_feature_field_multi_pipe_support) 29735 && (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id)) { 29736 f_pl->cfg.actual_ckbits_sec = (f_pl->cfg.actual_ckbits_sec / 2) ; 29737 f_pl->cfg.actual_pkbits_sec = (f_pl->cfg.actual_pkbits_sec / 2) ; 29738 } 29739 29740 return BCM_E_NONE; 29741 } 29742 29743 /* 29744 * Function: 29745 * _field_tcam_policy_install 29746 * 29747 * Purpose: 29748 * Install a combined TCAM and POLICY_TABLE entry. This writes the 29749 * qualifiers and actions to the hardware. 29750 * 29751 * Parameters: 29752 * unit - (IN) BCM device number. 29753 * entry - (IN) Entry to be installed. 29754 * Returns: 29755 * BCM_E_XXX 29756 */ 29757 int 29758 _field_tcam_policy_install(int unit, bcm_field_entry_t entry) 29759 { 29760 int tcam_idx[_FP_MAX_ENTRY_WIDTH]; /* Entry tcam index. */ 29761 int parts_count = 0; /* Field entry parts count. */ 29762 _field_entry_t *f_ent; /* Field entry pointer. */ 29763 _field_control_t *fc; /* Field control structure. */ 29764 int idx; /* Iteration index. */ 29765 int rv; /* Operation return status. */ 29766 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 29767 defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 29768 _field_entry_stat_t *f_ent_st=NULL; /* Field entry statistics structure. */ 29769 _field_stat_t *f_st=NULL; /* Statistics entity descriptor. */ 29770 #endif 29771 bcm_field_entry_t temp_entry = _FP_INVALID_INDEX; 29772 /* Entry id for internal backup entry*/ 29773 int slice_count = 0; /* count of slices attached to group */ 29774 int slice_count_updated = 0; /* count of slices attached to group 29775 after internal backup entry */ 29776 _field_slice_t *fs = NULL; /* Field Slice Structure */ 29777 29778 LOG_DEBUG(BSL_LS_BCM_FP, 29779 (BSL_META_U(unit, 29780 "FP(unit %d) vverb: bcm_field_policy_install (%d)\n"), 29781 unit, entry)); 29782 29783 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 29784 29785 /* Installing the entry. */ 29786 rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent); 29787 BCM_IF_ERROR_RETURN(rv); 29788 29789 #if defined(BCM_TRX_SUPPORT) 29790 if (BCM_FIELD_QSET_TEST(f_ent->group->qset, bcmFieldQualifyInPorts) && 29791 (!soc_feature(unit, soc_feature_field_multi_pipe_support)) && 29792 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 29793 29794 /* 29795 * Re-Check whether InPorts has ports other than fg->pbmp 29796 * To confirm existing ports from fg->pbmp were not removed 29797 * using bcm_field_group_ports_remove. 29798 */ 29799 bcm_pbmp_t temp_pbm; 29800 29801 BCM_PBMP_ASSIGN(temp_pbm, f_ent->pbmp.data); 29802 BCM_PBMP_OR(temp_pbm, f_ent->group->pbmp); 29803 if (BCM_PBMP_NEQ(temp_pbm, f_ent->group->pbmp)) { 29804 LOG_ERROR(BSL_LS_BCM_FP, 29805 (BSL_META_U(unit, 29806 "FP(unit %d) Error: Field qualifier InPorts " 29807 "in an entry with eid :%d " 29808 "has been qualified with the ports which are not" 29809 " part of its group pbmp with gid : %d \n"), 29810 unit, f_ent->eid, f_ent->group->gid)); 29811 return BCM_E_CONFIG; 29812 } 29813 } 29814 #endif 29815 29816 /* Get number of parts. */ 29817 rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id, 29818 f_ent->group->flags, &parts_count); 29819 BCM_IF_ERROR_RETURN(rv); 29820 29821 /* Initialize tcam_idx array. */ 29822 sal_memset(tcam_idx, 0, sizeof(tcam_idx)); 29823 29824 /* Get tcam indexes for installed entry. */ 29825 if ((f_ent->group->stage_id != _BCM_FIELD_STAGE_EXTERNAL) && 29826 (f_ent->group->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) { 29827 for (idx = parts_count - 1; idx >=0; idx--) { 29828 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx, 29829 tcam_idx + idx); 29830 BCM_IF_ERROR_RETURN(rv); 29831 } 29832 } 29833 29834 /* If entry was previously installed, we better disable it temporarily, 29835 * to avoid intermittent actions. 29836 */ 29837 #if defined(BCM_TOMAHAWK_SUPPORT) 29838 if ((f_ent->flags & _FP_ENTRY_INSTALLED) && 29839 ((_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id) || 29840 (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) || 29841 (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->fs->stage_id)) && 29842 (soc_feature(unit, soc_feature_advanced_flex_counter)) && 29843 (soc_feature(unit, soc_feature_field_multi_pipe_support))) { 29844 int update_stats = 1; 29845 29846 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) { 29847 if(!(f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY)) { 29848 update_stats = 0; 29849 } 29850 } 29851 29852 if (update_stats) { 29853 29854 f_ent_st = &(f_ent->statistic); 29855 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) { 29856 soc_mem_t tcam_mem = INVALIDm; 29857 soc_mem_t policy_mem = INVALIDm; 29858 29859 /* Read stat entity configuration. */ 29860 rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st); 29861 BCM_IF_ERROR_RETURN(rv); 29862 29863 if (f_st->hw_ref_count > 0) { 29864 29865 int policy_idx; 29866 29867 /* If this is the only entry using this stat, store the 29868 * stat values to retain on next attach. 29869 */ 29870 29871 if (0 == (f_st->hw_ref_count - 1)) { 29872 for (idx= 0; idx < f_st->nstat; idx++) { 29873 rv = _field_stat_value_get(unit, 0, f_st, 29874 f_st->stat_arr[idx], 29875 f_st->stat_values + idx); 29876 BCM_IF_ERROR_RETURN(rv); 29877 } 29878 } 29879 29880 /* (Intra Slice) Double Wide/ Triple wide modes, 29881 * IFP_TCAM_WIDE have 256 entries but IFP_POLICY_TABLE 29882 * will have 512 entries. 29883 */ 29884 29885 if (!soc_feature(unit, soc_feature_td3_style_fp) && 29886 (f_ent->fs->stage_id == _BCM_FIELD_STAGE_INGRESS) && 29887 (!(f_ent->group->flags & _FP_GROUP_SPAN_SINGLE_SLICE) || 29888 (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) 29889 ) { 29890 policy_idx = tcam_idx[0] + 29891 (f_ent->fs->slice_number * 256); 29892 } else { 29893 policy_idx = tcam_idx[0]; 29894 } 29895 29896 rv = _bcm_field_th_tcam_policy_mem_get(unit, f_ent, 29897 &tcam_mem, &policy_mem); 29898 BCM_IF_ERROR_RETURN(rv); 29899 /* Stats are attached to only first part of multiwide group 29900 * So in calling stat detach for tcam_idx[0] is enough. 29901 */ 29902 if (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->fs->stage_id 29903 || (soc_feature(unit, soc_feature_td3_style_fp) 29904 && (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id))) { 29905 rv = 29906 _bcm_esw_stat_flex_detach_ingress_table_counters_sw( 29907 unit, 29908 policy_mem, 0, 29909 f_st->hw_mode, 29910 f_st->hw_index, 29911 f_st->pool_index); 29912 } else { 29913 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 29914 unit, 29915 policy_mem, 29916 policy_idx); 29917 } 29918 BCM_IF_ERROR_RETURN(rv); 29919 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 29920 f_st->hw_ref_count--; 29921 } 29922 } 29923 } 29924 } 29925 #endif 29926 29927 /* If entry was previously installed, we better disable it temporarily, 29928 * to avoid intermittent actions. 29929 */ 29930 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 29931 int temp_entry_set = 0; 29932 for (idx = 0; idx < parts_count; idx++) { 29933 /* Read existing entry qualifiers from the HW. */ 29934 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + idx); 29935 if (BCM_FAILURE(rv)) { 29936 goto backup_clean; 29937 } 29938 /* internal backup entry installed temporarily */ 29939 if ((soc_feature(unit, 29940 soc_feature_field_tcam_hitless_update_on_modify)) && 29941 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXTERNAL) && 29942 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) && 29943 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER)) { 29944 29945 fs = f_ent->group->slices; 29946 while(fs->next != NULL) { 29947 slice_count++; 29948 fs = fs->next; 29949 } 29950 29951 if (idx == 0) { 29952 rv = _field_internal_backup_entry_create(unit,f_ent->eid, 29953 &temp_entry); 29954 BCM_IF_ERROR_RETURN(rv); 29955 temp_entry_set = 1; 29956 } 29957 /* Prio set may change the TCAM idx of f_ent 29958 Getting new TCAM idx after bacup entry create*/ 29959 if (temp_entry_set == 1) { 29960 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx, 29961 tcam_idx + idx); 29962 if (BCM_FAILURE(rv)) { 29963 goto backup_clean; 29964 } 29965 } 29966 29967 fs = f_ent->group->slices; 29968 while(fs->next != NULL) { 29969 slice_count_updated++; 29970 fs = fs->next; 29971 } 29972 } 29973 #if ((defined(BCM_KATANA_SUPPORT)) || (defined(BCM_TRIUMPH3_SUPPORT))) 29974 if (soc_feature(unit, soc_feature_advanced_flex_counter)) { 29975 int sid = -1; 29976 29977 f_ent_st = &((f_ent + idx)->statistic); 29978 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) { 29979 if (f_ent->fs->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 29980 if(soc_feature(unit, soc_feature_flex_stat_compaction_support)) { 29981 sid = f_ent_st->extended_sid; 29982 } else { 29983 sid = f_ent_st->sid; 29984 } 29985 } 29986 } else if(f_ent_st->flags & _FP_ENTRY_EXTENDED_STAT_INSTALLED) { 29987 sid = f_ent_st->extended_sid; 29988 } 29989 29990 if (sid != -1) { 29991 /* Read stat entity configuration. */ 29992 rv = _bcm_field_stat_get(unit, sid, &f_st); 29993 if (BCM_FAILURE(rv)) { 29994 goto backup_clean; 29995 } 29996 if (f_st->hw_ref_count > 0) { 29997 soc_mem_t policy_mem = INVALIDm; 29998 /* 29999 * If this is the only entry using this stat, store the stat 30000 * values to retain on next attach. 30001 */ 30002 if (1 == f_st->hw_ref_count) { 30003 int i; 30004 for (i= 0; i < f_st->nstat; i++) { 30005 rv = _field_stat_value_get(unit, 0, f_st, 30006 f_st->stat_arr[i], 30007 f_st->stat_values + i); 30008 if (BCM_FAILURE(rv)) { 30009 goto backup_clean; 30010 } 30011 } 30012 } 30013 switch (f_ent->fs->stage_id) { 30014 case _BCM_FIELD_STAGE_LOOKUP: 30015 case _BCM_FIELD_STAGE_INGRESS: 30016 policy_mem = 30017 (f_ent->fs->stage_id == _BCM_FIELD_STAGE_LOOKUP) 30018 ? VFP_POLICY_TABLEm : FP_POLICY_TABLEm; 30019 rv = _bcm_esw_stat_flex_detach_ingress_table_counters 30020 (unit, policy_mem, tcam_idx[idx]); 30021 if (BCM_FAILURE(rv)) { 30022 goto backup_clean; 30023 } 30024 break; 30025 case _BCM_FIELD_STAGE_EGRESS: 30026 policy_mem = EFP_POLICY_TABLEm; 30027 rv = _bcm_esw_stat_flex_detach_egress_table_counters 30028 (unit, 0, policy_mem, tcam_idx[idx]); 30029 if (BCM_FAILURE(rv)) { 30030 goto backup_clean; 30031 } 30032 break; 30033 default: 30034 rv = BCM_E_INTERNAL; 30035 goto backup_clean; 30036 break; 30037 } 30038 30039 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) { 30040 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 30041 if(soc_feature(unit, 30042 soc_feature_flex_stat_compaction_support) && 30043 (f_ent->fs->stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 30044 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED; 30045 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED; 30046 } 30047 } else { 30048 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED; 30049 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED; 30050 } 30051 f_st->hw_ref_count--; 30052 } 30053 } 30054 } 30055 #endif 30056 30057 30058 #if defined(BCM_HURRICANE3_SUPPORT) 30059 if (soc_feature(unit, soc_feature_flowcnt)) { 30060 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) { 30061 f_ent_st = &((f_ent + idx)->statistic); 30062 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) { 30063 /* Read stat entity configuration. */ 30064 rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st); 30065 if (BCM_FAILURE(rv)) { 30066 goto backup_clean; 30067 } 30068 if (f_st->hw_ref_count > 0) { 30069 /* Disable VLAN Flow counter */ 30070 rv = _bcm_esw_flowcnt_object_table_detach(unit, 30071 VFP_POLICY_TABLEm, tcam_idx[idx]); 30072 if (BCM_FAILURE(rv)) { 30073 goto backup_clean; 30074 } 30075 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED; 30076 f_st->hw_ref_count--; 30077 } 30078 } 30079 } 30080 } 30081 #endif /* BCM_HURRICANE3_SUPPORT */ 30082 /* Disable installed entry. */ 30083 if ( !((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) && 30084 (soc_feature(unit, soc_feature_field_multi_pipe_support)))) { 30085 rv = _field_entry_tcam_remove(unit, fc, f_ent + idx, 30086 tcam_idx[idx]); 30087 if (BCM_FAILURE(rv)) { 30088 goto backup_clean; 30089 } 30090 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 30091 /* 30092 * For not missing each Slice hw_ent_count update for VFP/EFP groups 30093 * Entry install flag should be reset and it will be set once the installation is succesful. 30094 */ 30095 (f_ent + idx)->flags &= ~_FP_ENTRY_INSTALLED; 30096 } 30097 } 30098 } 30099 } 30100 30101 /* Remove deleted actions. */ 30102 rv = _field_invalid_actions_remove(unit, f_ent); 30103 if (BCM_FAILURE(rv)) { 30104 goto backup_clean; 30105 } 30106 30107 /* Allocate hw resources required for entry installation. */ 30108 rv = _field_hw_resources_alloc(unit, f_ent); 30109 if (BCM_FAILURE(rv)) { 30110 goto backup_clean; 30111 } 30112 30113 /* Move all actions to the slice where meter resides. */ 30114 rv = _field_entry_actions_meter_slice_move(unit, f_ent, TRUE); 30115 if (BCM_FAILURE(rv)) { 30116 (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE); 30117 goto backup_clean; 30118 } 30119 30120 /* 30121 * For stages that support global meter pools, meters must be in 30122 * same slice as counters. Move policer to counter slice if 30123 * counters are in secondary slice. 30124 */ 30125 rv = _field_entry_policer_stat_slice_move(unit, f_ent, TRUE); 30126 if (BCM_FAILURE(rv)) { 30127 (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE); 30128 goto backup_clean; 30129 } 30130 30131 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 30132 rv = _field_tcam_policy_external_install(unit, f_ent); 30133 } else if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 30134 #if defined (BCM_TOMAHAWK_SUPPORT) 30135 rv = _field_th_em_entry_install(unit, f_ent); 30136 #endif 30137 } else { 30138 for (idx = parts_count - 1; idx >=0; idx--) { 30139 /* 30140 * For Trident FP_GM_FIELDS.VALID = 1 when used in paired mode 30141 */ 30142 if (((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit))) 30143 && (!soc_feature(unit, soc_feature_field_multi_pipe_support)) && 30144 SOC_IS_TD_TT(unit) && (idx == 1) && 30145 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 30146 f_ent[idx].flags |= _FP_ENTRY_USES_IPBM_OVERLAY; 30147 } 30148 30149 /* Get entry tcam key/mask. */ 30150 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + idx); 30151 if (BCM_FAILURE(rv)) { 30152 break; 30153 } 30154 30155 #if defined(BCM_TRIDENT2_SUPPORT) 30156 if (SOC_IS_TD2_TT2(unit) && 30157 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) { 30158 rv = fc->functions.fp_egress_key_match_type_set(unit, 30159 f_ent + idx); 30160 if (BCM_FAILURE(rv)) { 30161 break; 30162 } 30163 } 30164 #endif 30165 30166 if (f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY) { 30167 f_ent[idx].statistic.flags |= _FP_ENTRY_STAT_DIRTY; 30168 } 30169 /* Install physical entry into primary slice */ 30170 rv = fc->functions.fp_tcam_policy_install(unit, f_ent + idx, 30171 tcam_idx[idx]); 30172 if (BCM_FAILURE(rv)) { 30173 break; 30174 } 30175 f_ent[idx].flags &= ~_FP_ENTRY_DIRTY; 30176 f_ent[idx].flags |= _FP_ENTRY_INSTALLED; 30177 f_ent[idx].flags |= _FP_ENTRY_ENABLED; 30178 f_ent[idx].statistic.flags &= ~_FP_ENTRY_STAT_DIRTY; 30179 #if defined(BCM_TRIDENT2_SUPPORT) 30180 if (SOC_IS_TD2_TT2(unit) && 30181 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)){ 30182 if (NULL != f_ent[idx].key_match_tcam.key) { 30183 sal_free(f_ent[idx].key_match_tcam.key); 30184 } 30185 if (NULL != f_ent[idx].key_match_tcam.mask) { 30186 sal_free(f_ent[idx].key_match_tcam.mask); 30187 } 30188 f_ent[idx].key_match_tcam.key = f_ent[idx].key_match_tcam.mask = NULL; 30189 } 30190 #endif 30191 { 30192 if(NULL != f_ent[idx].tcam.key) sal_free(f_ent[idx].tcam.key); 30193 if(NULL != f_ent[idx].tcam.mask) sal_free(f_ent[idx].tcam.mask); 30194 f_ent[idx].tcam.key = f_ent[idx].tcam.mask = NULL; 30195 } 30196 } 30197 /* 30198 * TD3 qualifies on Inports for all other pipes in Global Mode 30199 * inturn set _FP_ENTRY_DIRTY for all other parts of entry 30200 */ 30201 if (soc_feature(unit, soc_feature_td3_style_fp) && 30202 BCM_FIELD_QSET_TEST(f_ent->group->qset, bcmFieldQualifyInPorts)) { 30203 for (idx = parts_count - 1; idx >=0; idx--) { 30204 f_ent[idx].flags &= ~_FP_ENTRY_DIRTY; 30205 } 30206 } 30207 } 30208 30209 if (BCM_FAILURE(rv)) { 30210 (void)_field_entry_actions_meter_slice_move(unit, f_ent, FALSE); 30211 (void)_field_entry_policer_stat_slice_move(unit, f_ent, FALSE); 30212 (void)_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE); 30213 /* internal backup entry removed */ 30214 goto backup_clean; 30215 } 30216 30217 /* internal backup entry removed */ 30218 if ((soc_feature(unit, soc_feature_field_tcam_hitless_update_on_modify)) && 30219 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXTERNAL) && 30220 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) { 30221 rv = _field_internal_backup_entry_delete(unit, temp_entry); 30222 BCM_IF_ERROR_RETURN(rv); 30223 } 30224 30225 /* Move all actions back to the primary slice . */ 30226 rv = _field_entry_actions_meter_slice_move(unit, f_ent, FALSE); 30227 if (BCM_FAILURE(rv)) { 30228 (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE); 30229 goto backup_clean; 30230 } 30231 30232 /* Move policers to primary slice. */ 30233 rv = _field_entry_policer_stat_slice_move(unit, f_ent, FALSE); 30234 if (BCM_FAILURE(rv)) { 30235 (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE); 30236 goto backup_clean; 30237 } 30238 30239 30240 /* Remove stale deleted actions. */ 30241 rv = _field_invalid_actions_remove(unit, f_ent); 30242 if (BCM_FAILURE(rv)) { 30243 goto backup_clean; 30244 } 30245 BCM_IF_ERROR_RETURN(rv); 30246 30247 /* In case of entry reinstall free previous installation hw resources. */ 30248 rv = _field_hw_resources_free(unit, f_ent, _FP_ACTION_OLD_RESOURCE_FREE); 30249 if (BCM_FAILURE(rv)) { 30250 (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE); 30251 goto backup_clean; 30252 } 30253 30254 backup_clean: 30255 if (BCM_FAILURE(rv)) { 30256 if ((soc_feature(unit, soc_feature_field_tcam_hitless_update_on_modify)) && 30257 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXTERNAL) && 30258 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) { 30259 BCM_IF_ERROR_RETURN(_field_internal_backup_entry_delete(unit, temp_entry)); 30260 } 30261 /* Returning failure error */ 30262 return (rv); 30263 } 30264 return (BCM_E_NONE); 30265 } 30266 30267 30268 30269 30270 /* 30271 * Function: _field_entry_remove 30272 * 30273 * Purpose: 30274 * Remove an entry from the hardware tables. 30275 * 30276 * Parameters: 30277 * unit - (IN) BCM device number 30278 * fc - (IN) Field control structure. 30279 * entry - (IN) Entry to remove. 30280 * 30281 * Returns: 30282 * BCM_E_XXX 30283 */ 30284 int 30285 _field_entry_remove(int unit, _field_control_t *fc, bcm_field_entry_t entry) 30286 { 30287 _field_entry_t *f_ent; /* Field entry pointer. */ 30288 int tcam_idx; /* Entry tcam index. */ 30289 int parts_count = 0; /* Entry parts count. */ 30290 int idx; /* Iteration index. */ 30291 int rv; /* Operation return status. */ 30292 _field_action_t *fa; 30293 30294 rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent); 30295 if (BCM_FAILURE(rv)) { 30296 return (rv); 30297 } 30298 30299 #if defined(BCM_TOMAHAWK_SUPPORT) 30300 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 30301 (_BCM_FIELD_STAGE_CLASS == f_ent->group->stage_id)) { 30302 rv = _bcm_field_th_class_entry_remove(unit, entry); 30303 return (rv); 30304 } 30305 #endif /* BCM_TOMAHAWK_SUPPORT */ 30306 30307 if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) { 30308 /* Entry not installed in hardware to perform remove operation. */ 30309 return (BCM_E_NONE); 30310 } 30311 30312 if ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) || 30313 (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) || 30314 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) || 30315 (_BCM_FIELD_STAGE_FLOWTRACKER == f_ent->group->stage_id)) { 30316 /* Disable the Entry. */ 30317 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_enable_set(unit, entry, 0)); 30318 } 30319 30320 /* Free hw resources allocated during entry installation. */ 30321 rv = _field_resources_free(unit, f_ent, 30322 _FP_ACTION_RESOURCE_FREE | _FP_ACTION_POLICER_SW_UPDATE); 30323 BCM_IF_ERROR_RETURN(rv); 30324 30325 /* Get number of parts. */ 30326 rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id, 30327 f_ent->group->flags, &parts_count); 30328 30329 for (idx = 0; idx < parts_count; idx++) { 30330 /* Store entry in S/W before removing from H/W */ 30331 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + idx); 30332 BCM_IF_ERROR_RETURN(rv); 30333 30334 /* Get entry tcam index. */ 30335 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx, &tcam_idx); 30336 BCM_IF_ERROR_RETURN(rv); 30337 30338 /* Remove entry in slice. */ 30339 30340 rv = _field_entry_tcam_remove(unit, fc, f_ent + idx, tcam_idx); 30341 BCM_IF_ERROR_RETURN(rv); 30342 30343 f_ent[idx].flags |= _FP_ENTRY_DIRTY; 30344 f_ent[idx].flags &= ~_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 30345 f_ent[idx].flags &= ~_FP_ENTRY_INSTALLED; 30346 f_ent[idx].flags &= ~_FP_ENTRY_ENABLED; 30347 } 30348 30349 if (f_ent->statistic.flags & _FP_ENTRY_STAT_VALID) { 30350 f_ent->statistic.flags |= _FP_ENTRY_STAT_DIRTY; 30351 } 30352 30353 /* Free policers. */ 30354 rv = _field_policers_hw_free(unit, f_ent, 30355 _FP_ACTION_RESOURCE_FREE|_FP_ACTION_POLICER_SW_UPDATE); 30356 BCM_IF_ERROR_RETURN(rv); 30357 30358 /* Remove deleted actions. */ 30359 rv = _field_invalid_actions_remove(unit, f_ent); 30360 BCM_IF_ERROR_RETURN(rv); 30361 for (fa = f_ent->actions; (NULL != fa) && (fa->flags & _FP_ACTION_VALID); fa = fa->next) { 30362 fa->flags |= _FP_ACTION_DIRTY; 30363 } 30364 return (BCM_E_NONE); 30365 } 30366 30367 30368 /* Function: _field_reqd_prio_set_move 30369 * 30370 * Purpose: Checks if the entry needs to be moved due to prio set 30371 * 30372 * Parameters: 30373 * unit - 30374 * f_ent - Entry whose priority is being set 30375 * prio - The new priority for f_ent 30376 * 30377 * Returns: 30378 * TRUE/FALSE 30379 */ 30380 int 30381 _field_reqd_prio_set_move(int unit, _field_entry_t *f_ent, int prio) 30382 { 30383 _field_group_t *fg; 30384 _field_slice_t *fs; 30385 _field_stage_t *stage_fc; 30386 int slice_sz; 30387 int idx_type; 30388 30389 int i, flag; /* flag denotes is we are before OR after f_ent */ 30390 30391 fg = f_ent->group; 30392 30393 /* Get stage control structure. */ 30394 BCM_IF_ERROR_RETURN 30395 (_field_stage_control_get(unit, fg->stage_id, &stage_fc)); 30396 30397 fs = &fg->slices[0]; 30398 flag = -1; /* We are before f_ent */ 30399 while (fs != NULL) { 30400 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 30401 for (i = 0; i < slice_sz; i++) { 30402 if (fs->entries[i] == f_ent) { 30403 flag = 1; /* Now, we are after f_ent */ 30404 continue; 30405 } 30406 _field_slice_index_type_get(unit, fg, fs, i, &idx_type); 30407 if ((idx_type == _BCM_FIELD_SLICE_IDX_TYPE_FREE) || 30408 (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_DIFF)) { 30409 continue; 30410 } 30411 if (flag == -1) { 30412 if (_field_entry_prio_cmp(fs->entries[i]->prio, prio) < 0) { 30413 /* 30414 * An entry before f_ent has lower priority than prio 30415 * Movement is required 30416 */ 30417 return TRUE; 30418 } 30419 } else { 30420 if (_field_entry_prio_cmp(fs->entries[i]->prio, prio) > 0) { 30421 /* 30422 * An entry after f_ent has higher priority than prio 30423 * Movement is required 30424 */ 30425 return TRUE; 30426 } 30427 } 30428 } 30429 fs = fs->next; 30430 } 30431 return FALSE; /* f_ent with new prio is in proper location */ 30432 } 30433 30434 /* 30435 * Function: _field_entry_multiple_slice_move_check 30436 * 30437 * Purpose: Checks if a series of entries can be shifted to the 30438 * nearest hole and returns how many entries would end up 30439 * being shifted. 30440 * 30441 * This function is called recursively for each slice in 30442 * which entries need to be shifted. 30443 * 30444 * Parameters: 30445 * unit - unit 30446 * fg - The group to which the slices belong 30447 * entry - Pointer to the entry which is being moved 30448 * null_index - Index of the next empty slot within its slice, in the 30449 * specified direction 30450 * null_fs - Pointer to the next slice with an empty slot, in the 30451 * specified direction 30452 * target_index - Index of the slot in which we want to insert the entry 30453 * target_fs - Pointer to the slice in which we want to insert the entry 30454 * direction - The direction in which we're checking entry shifting 30455 * feasibility; -1 for up or 1 for down 30456 * shifted_entry_count (IN/OUT) - The number of entries that would be shifted 30457 * to make the move possible 30458 * freed_counter_count (IN/OUT) - The number of counters that would be freed 30459 * by the shift 30460 * 30461 * Returs: 30462 * BCM_E_NONE if the move can be done 30463 */ 30464 30465 STATIC int _field_entry_multiple_slice_move_check(int unit, 30466 _field_group_t *fg, _field_entry_t *entry, int null_index, 30467 _field_slice_t *null_fs, int target_index, _field_slice_t *target_fs, 30468 int direction, int *shifted_entry_count, int *freed_meter_count, 30469 int *freed_counter_count) 30470 { 30471 int rv = BCM_E_NONE; 30472 _field_stage_t *stage_fc; 30473 _field_slice_t *adjacent_fs; 30474 int adjacent_index; 30475 int slice_entry_count; 30476 int adjacent_slice_entry_count; 30477 _field_entry_t *entry_to_move; 30478 30479 BCM_IF_ERROR_RETURN 30480 (_field_stage_control_get(unit, target_fs->stage_id, &stage_fc)); 30481 30482 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, target_fs, slice_entry_count); 30483 30484 if (target_fs != null_fs) 30485 { 30486 if (direction < 0) 30487 { 30488 /* Shift up */ 30489 30490 adjacent_fs = target_fs->prev; 30491 30492 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, adjacent_fs, 30493 adjacent_slice_entry_count); 30494 30495 adjacent_index = adjacent_slice_entry_count - 1; 30496 entry_to_move = target_fs->entries[0]; 30497 *shifted_entry_count += target_index; 30498 } 30499 else 30500 { 30501 /* Shift down */ 30502 30503 adjacent_fs = target_fs->next; 30504 adjacent_index = 0; 30505 entry_to_move = target_fs->entries[slice_entry_count - 1]; 30506 *shifted_entry_count += slice_entry_count - target_index; 30507 } 30508 30509 rv = _field_entry_multiple_slice_move_check(unit, fg, 30510 entry_to_move, null_index, null_fs, adjacent_index, 30511 adjacent_fs, direction, shifted_entry_count, freed_meter_count, 30512 freed_counter_count); 30513 30514 BCM_IF_ERROR_RETURN(rv); 30515 } 30516 else 30517 { 30518 *shifted_entry_count += direction * (null_index - target_index); 30519 } 30520 30521 if (entry->fs != target_fs) 30522 { 30523 rv = _field_entry_move_slice_fit(unit, stage_fc, entry, target_fs, 30524 freed_meter_count, freed_counter_count); 30525 } 30526 30527 return rv; 30528 } 30529 30530 /* 30531 * Function: _field_validate_prio_set 30532 * 30533 * Purpose: Checks if the prio_set can be successful. 30534 * Meaningful only when entries need to be moved across slices 30535 * 1. Check that entries moving across slices don't have shared 30536 * meters/counters 30537 * 2. For entries moving across slices, and having meters/counters, 30538 * check if there are resources in the new slice 30539 * 30540 * Parameters: 30541 * unit - unit 30542 * fg - group the entry whose prio is being set belongs to 30543 * f_ent_pri - primary entry whose priorty is to be changed 30544 * prev_null_index - index with no entry just before target_index 30545 * prev_null_fs - corresponding slice 30546 * target_index - the target index where f_ent is supposed to go 30547 * target_fs - the slice where index resides 30548 * next_null_index - index with no entry just after target_index 30549 * next_null_fs - corresponding slice 30550 * dir (OUT) - shift up (-1) or down (+1) 30551 * 30552 * Returs: 30553 * TRUE/FALSE 30554 * 30555 * Notes: 30556 * Check both up and down movement. If both feasible, take the one 30557 * which leads to lesser moves. 30558 * Note the slice_sz for intraslice-double wide (FB2). Also shift_up_amount 30559 * and shift_down_amount are not absolute amounts, but # entries which 30560 * need to be shifted (each entry moves by 1 unit UP/DOWN). 30561 */ 30562 STATIC int 30563 _field_validate_prio_set(int unit, 30564 _field_group_t *fg, _field_entry_t *f_ent_pri, 30565 int prev_null_index, _field_slice_t *prev_null_fs, 30566 int target_index, _field_slice_t *target_fs, 30567 int next_null_index, _field_slice_t *next_null_fs, 30568 int *dir) 30569 { 30570 _field_stage_t *stage_fc; 30571 int rv; 30572 int shift_up = FALSE, shift_down = FALSE; 30573 int shift_up_amount = 0, shift_down_amount = 0; 30574 int up_meters_freed = 0, down_meters_freed = 0; 30575 int up_counters_freed = 0, down_counters_freed = 0; 30576 30577 /* Input parameter check. */ 30578 if ((NULL == f_ent_pri) || (NULL == target_fs)) { 30579 return (BCM_E_PARAM); 30580 } 30581 30582 BCM_IF_ERROR_RETURN 30583 (_field_stage_control_get(unit, target_fs->stage_id, &stage_fc)); 30584 30585 /* 30586 * STEP-1 30587 * Check the shift operation for UP movement 30588 * Entries from target_index up till entry after prev_null_index 30589 * need to move one entry up 30590 */ 30591 30592 if (prev_null_fs != NULL) 30593 { 30594 rv = _field_entry_multiple_slice_move_check(unit, fg, f_ent_pri, 30595 prev_null_index, prev_null_fs, target_index, target_fs, -1, 30596 &shift_up_amount, &up_meters_freed, &up_counters_freed); 30597 30598 shift_up = BCM_SUCCESS(rv); 30599 } 30600 else 30601 { 30602 shift_up = FALSE; 30603 } 30604 30605 /* 30606 * Step-2 30607 * Check the shift operation for DOWN movement 30608 * Entries from target_index till entry before next_null_index 30609 * need to move one entry down 30610 */ 30611 30612 if (next_null_fs != NULL) 30613 { 30614 rv = _field_entry_multiple_slice_move_check(unit, fg, f_ent_pri, 30615 next_null_index, next_null_fs, target_index, target_fs, 1, 30616 &shift_down_amount, &down_meters_freed, &down_counters_freed); 30617 30618 shift_down = BCM_SUCCESS(rv); 30619 } 30620 else 30621 { 30622 shift_down = FALSE; 30623 } 30624 30625 if (shift_up == TRUE) 30626 { 30627 if (shift_down == TRUE) 30628 { 30629 if (shift_up_amount < shift_down_amount) 30630 { 30631 *dir = -1; 30632 } 30633 else 30634 { 30635 *dir = 1; 30636 } 30637 } 30638 else 30639 { 30640 *dir = -1; 30641 } 30642 } 30643 else 30644 { 30645 if (shift_down == TRUE) 30646 { 30647 *dir = 1; 30648 } 30649 else 30650 { 30651 return FALSE; 30652 } 30653 } 30654 30655 return TRUE; 30656 } 30657 30658 /* 30659 * Function: _field_no_free_entries 30660 * 30661 * Purpose: 30662 * To see if the any of the slices allocated to this 30663 * group has any free entries 30664 * 30665 * Parameters: 30666 * unit - BCM device number 30667 * fg - group 30668 * 30669 * Returns: 30670 * FALSE: Atleast 1 free entry 30671 * TRUE: No free entries 30672 * 30673 * Notes: 30674 */ 30675 int 30676 _field_no_free_entries(int unit, _field_group_t *fg) 30677 { 30678 _field_slice_t *fs; 30679 int free_entry_cnt; 30680 30681 fs = &fg->slices[0]; 30682 30683 while (fs != NULL) { 30684 _bcm_field_entries_free_get(unit, fs, fg, &free_entry_cnt); 30685 if (free_entry_cnt) { 30686 return FALSE; 30687 } 30688 fs = fs->next; 30689 } 30690 30691 return TRUE; 30692 } 30693 30694 /* 30695 * Function: 30696 * _field_entry_prio_cmp 30697 * Purpose: 30698 * Compare two entry priorities 30699 * Parameters: 30700 * Returns: 30701 * -1 if prio_first < prio_second 30702 * 0 if prio_first == prio_second 30703 * 1 if prio_first > prio_second 30704 */ 30705 int 30706 _field_entry_prio_cmp(int prio_first, int prio_second) 30707 { 30708 int retval; 30709 30710 if (prio_first == prio_second) { 30711 retval = 0; 30712 } else if (prio_first < prio_second) { 30713 retval = -1; 30714 } else { 30715 retval = 1; 30716 } 30717 return retval; 30718 } 30719 30720 30721 /* 30722 * Function: 30723 * _field_entry_move 30724 * Purpose: 30725 * Move an entry within a slice by "amount" indexes 30726 * 30727 * Parameters: 30728 * unit - BCM device number 30729 * f_ent - entry to be moved 30730 * amount - number of indexes to move + or - 30731 * Returns: 30732 * BCM_E_NONE - Success 30733 */ 30734 STATIC int 30735 _field_entry_move(int unit, _field_entry_t *f_ent, int amount) 30736 { 30737 int tcam_idx_old[_FP_MAX_ENTRY_WIDTH];/* Original entry tcam index. */ 30738 int tcam_idx_new[_FP_MAX_ENTRY_WIDTH];/* Next tcam index for the entry.*/ 30739 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 30740 _field_entry_stat_t *f_ent_st; /* Field entry stat structure. */ 30741 _field_control_t *fc; /* Field control structure. */ 30742 _field_stage_t *stage_fc; /* Stage field control. */ 30743 _field_group_t *fg; /* Field entry group. */ 30744 _field_slice_t *fs; /* Field slice control. */ 30745 _field_policer_t *f_pl = NULL;/* Field policer info. */ 30746 _field_stat_t *f_st = NULL;/* Field statatistics entity. */ 30747 int parts_count = 0; /* Field entry parts count. */ 30748 int idx; 30749 int rv; /* Operation return status. */ 30750 int counter_movement = 0; /* Boolean which tells if entry moved 30751 across slice, and if so, did it 30752 have a counter */ 30753 uint8 entry_part; /* Field entry parts iterator. */ 30754 int meter_movement = 0; /* For meter */ 30755 int meter_index = 0; /* Meter hardware index. */ 30756 int meter_pool_index = 0; /* Meter pool value. */ 30757 int stat_index = 0; /* STAT hardware index. */ 30758 int stat_slice = 0; /* STAT slice value. */ 30759 int new_offset; /* Entry offset in slice. */ 30760 int new_slice_numb = 0; /* New slice number. */ 30761 _field_stat_t f_st_old; /* Old Field statatistics entity. */ 30762 uint64 value; /* STAT value. */ 30763 int nstat; /* STAT array index. */ 30764 int instance; /* Pipe Instance. */ 30765 bcm_policer_mode_t old_mode; 30766 uint32 pl_flags = 0; 30767 old_mode = bcmPolicerModeCount; 30768 LOG_DEBUG(BSL_LS_BCM_FP, 30769 (BSL_META_U(unit, 30770 "FP(unit %d) vverb: BEGIN _field_entry_move(entry=%d," 30771 " amount=%d)\n"), unit, f_ent->eid, amount)); 30772 30773 if (NULL == f_ent) { 30774 return (BCM_E_PARAM); 30775 } 30776 30777 if ((NULL == f_ent->fs) || (NULL == f_ent->group)) { 30778 return (BCM_E_PARAM); 30779 } 30780 30781 #if defined(BCM_FLOWTRACKER_SUPPORT) 30782 if (f_ent->fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) { 30783 return _field_multimode_slice_entry_move(unit, 30784 f_ent->fs, f_ent, amount); 30785 } 30786 #endif 30787 30788 /* Initialization. */ 30789 sal_memset(tcam_idx_old, 0, (_FP_MAX_ENTRY_WIDTH * sizeof(int))); 30790 sal_memset(tcam_idx_new, 0, (_FP_MAX_ENTRY_WIDTH * sizeof(int))); 30791 fg = f_ent->group; 30792 30793 if (amount == 0) { 30794 LOG_WARN(BSL_LS_BCM_FP, 30795 (BSL_META_U(unit, 30796 "Warning: moving entry=%d, same slice_idx=%d(%#x)\n"), 30797 f_ent->eid, f_ent->slice_idx, f_ent->slice_idx)); 30798 return (BCM_E_NONE); 30799 } 30800 30801 /* Get field control structure. */ 30802 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 30803 30804 /* Get stage field control structure. */ 30805 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 30806 BCM_IF_ERROR_RETURN(rv); 30807 30808 /* Get number of parts. */ 30809 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 30810 fg->flags, &parts_count); 30811 BCM_IF_ERROR_RETURN(rv); 30812 30813 /* Retrieve the pipe instance */ 30814 instance = fg->instance; 30815 30816 /* Calculate the new and old TCAM indexes. */ 30817 for (idx = 0; idx < parts_count; idx++) { 30818 /* Calculate the new and old TCAM indexes. */ 30819 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx, 30820 &tcam_idx_old[idx]); 30821 BCM_IF_ERROR_RETURN(rv); 30822 30823 /* Calculate entry part tcam offset. */ 30824 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 30825 tcam_idx_old[0] + amount, 30826 idx, &tcam_idx_new[idx]); 30827 BCM_IF_ERROR_RETURN(rv); 30828 } 30829 30830 /* Get secondary slice entry pointer. */ 30831 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 30832 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 30833 rv = _bcm_field_entry_flags_to_tcam_part (unit, _FP_ENTRY_SECONDARY, 30834 fg, &entry_part); 30835 BCM_IF_ERROR_RETURN(rv); 30836 } 30837 30838 /* Calculate entry new slice number. */ 30839 #if defined(BCM_TOMAHAWK_SUPPORT) 30840 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 30841 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 30842 rv = _bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc, f_ent, 30843 tcam_idx_new[0], &new_slice_numb, 30844 &new_offset); 30845 } else 30846 #endif /* BCM_TOMAHAWK_SUPPORT */ 30847 { 30848 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, instance, 30849 tcam_idx_new[0], &new_slice_numb, 30850 &new_offset); 30851 } 30852 BCM_IF_ERROR_RETURN(rv); 30853 30854 if ((f_ent->fs->slice_number != new_slice_numb) && 30855 (f_ent->flags & _FP_ENTRY_INSTALLED)) { 30856 30857 fs = stage_fc->slices[instance] + new_slice_numb; 30858 30859 /* 30860 * If global meter pools are not present, AND 30861 * current entry has a meter, allocate one in new slice 30862 */ 30863 f_ent_pl = f_ent->policer; 30864 if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) && 30865 (f_ent_pl->flags & _FP_POLICER_INSTALLED)) { 30866 meter_movement = 1; 30867 30868 /* Read policer configuration.*/ 30869 rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl); 30870 BCM_IF_ERROR_RETURN(rv); 30871 30872 /* Preserve original policer hw index, 30873 * flag and mode. 30874 */ 30875 meter_pool_index = f_pl->pool_index; 30876 meter_index = f_pl->hw_index; 30877 pl_flags = f_pl->hw_flags; 30878 old_mode = (f_pl)->cfg.mode; 30879 /* _field_policer_meter_hw_free(unit, f_ent, f_ent_pl); */ 30880 /* Deallocate policer from original entry slice. */ 30881 BCM_IF_ERROR_RETURN(_field_meter_hw_free(unit, f_ent)); 30882 30883 /* Allocate policer in a new slice. */ 30884 rv = _field_meter_hw_alloc(unit, f_ent, fs); 30885 if (BCM_FAILURE(rv)) { 30886 if (rv == BCM_E_RESOURCE) { 30887 /* 30888 * Re-allocate policer resource in original slice 30889 * and re-install the entry in hardware. 30890 */ 30891 BCM_IF_ERROR_RETURN(_field_meter_hw_alloc(unit, f_ent, 30892 f_ent->fs)); 30893 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 30894 f_ent->flags |= _FP_ENTRY_DIRTY; 30895 BCM_IF_ERROR_RETURN 30896 (bcm_esw_field_entry_reinstall(unit, f_ent->eid)); 30897 } 30898 return rv; 30899 } 30900 } 30901 30902 /* 30903 * If global counters are not present, AND 30904 * current entry has a counter, allocate one in new slice 30905 * NOTE: Must be after policer allocation in order to 30906 * determine counter slice. 30907 */ 30908 f_ent_st = &f_ent->statistic; 30909 if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS)) && 30910 (0 == (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) && 30911 (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED)) { 30912 counter_movement = 1; 30913 30914 /* Read statistics entity configuration.*/ 30915 BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st)); 30916 f_st_old = *f_st; 30917 30918 /* Preserve original policer hw index. */ 30919 stat_slice = f_st->pool_index; 30920 stat_index = f_st->hw_index; 30921 30922 /* Deallocate statistics entity from original entry slice. */ 30923 BCM_IF_ERROR_RETURN(_field_slice_counter_free(unit, f_ent, f_st)); 30924 30925 /* Allocate statistics entity in a new slice. */ 30926 BCM_IF_ERROR_RETURN(_field_counter_hw_alloc(unit, f_ent, fs)); 30927 30928 /* Clear allocated new hardware counters */ 30929 for (nstat = 0; nstat < f_st->nstat; nstat++) { 30930 COMPILER_64_ZERO(value); 30931 rv = _field_stat_value_set(unit, 30932 f_st, 30933 f_st->stat_arr[nstat], 30934 value); 30935 BCM_IF_ERROR_RETURN(rv); 30936 } 30937 } 30938 } 30939 30940 /* Move the hardware entry.*/ 30941 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 30942 rv = fc->functions.fp_entry_move(unit, f_ent, parts_count, 30943 tcam_idx_old, tcam_idx_new); 30944 BCM_IF_ERROR_RETURN(rv); 30945 } 30946 30947 /* Move the software entry.*/ 30948 rv = _field_entry_slice_idx_change(unit, f_ent, parts_count, tcam_idx_new); 30949 BCM_IF_ERROR_RETURN(rv); 30950 30951 if (meter_movement) { 30952 f_ent_pl = f_ent->policer; 30953 /* Read policer configuration. */ 30954 rv = _bcm_field_policer_get (unit, f_ent_pl->pid, &f_pl); 30955 BCM_IF_ERROR_RETURN(rv); 30956 30957 rv = _field_entry_meter_move(unit, stage_fc, instance, 30958 meter_pool_index, 30959 meter_index, pl_flags, f_pl, 30960 f_ent, old_mode); 30961 BCM_IF_ERROR_RETURN(rv); 30962 } 30963 30964 if (counter_movement) { 30965 f_ent_st = &f_ent->statistic; 30966 BCM_IF_ERROR_RETURN (_bcm_field_stat_get (unit, f_ent_st->sid, &f_st)); 30967 rv = _bcm_field_entry_counter_move(unit, stage_fc, stat_slice, 30968 stat_index, &f_st_old, f_st); 30969 BCM_IF_ERROR_RETURN(rv); 30970 } 30971 30972 return (BCM_E_NONE); 30973 } 30974 /* 30975 * Function: 30976 * _field_efp_entry_qual_value_qualify 30977 * 30978 * Purpose: 30979 * Utility routine check encoding of a qualifier and decide that qualifier 30980 * can be part of key_match_tcam of an entry. 30981 * 30982 * Parameters: 30983 * unit - (IN) BCM device number 30984 * entry - (IN) Entry ID 30985 * qual_id - (IN) Qualifier Id 30986 * can_qualify - (IN/OUT) Status of the qualifier 30987 * data - (IN) Data to qualify with. 30988 * mask - (IN) Mask to qualify with. 30989 * 30990 * Returns: 30991 * BCM_E_XXX - BCM device number 30992 */ 30993 int 30994 _field_efp_entry_qual_value_qualify(int unit, 30995 bcm_field_entry_t entry, 30996 uint32 qual_id, 30997 uint32 *data, uint32 *mask, 30998 uint8 *can_qualify) 30999 { 31000 int rv; /* Operation return stauts. */ 31001 uint8 slice_mode; /* Slice Mode of the group */ 31002 bcm_field_IpType_t ipType; /* Ip type encoding */ 31003 _field_group_t *fg; /* FP group info structure. */ 31004 _field_entry_t *f_ent; /* Pointer to field entry */ 31005 31006 /* Input parameters checks. */ 31007 if ((NULL == data) || (NULL == mask) || (NULL == can_qualify)) { 31008 return (BCM_E_PARAM); 31009 } 31010 31011 /* Search the entry by eid. */ 31012 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 31013 BCM_IF_ERROR_RETURN(rv); 31014 31015 fg = f_ent->group; 31016 if (NULL == fg) { 31017 return (BCM_E_INTERNAL); 31018 } 31019 31020 *can_qualify = 1; 31021 slice_mode = 0; 31022 31023 #if defined(BCM_TRX_SUPPORT) 31024 #if defined(BCM_TOMAHAWK_SUPPORT) 31025 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 31026 rv = _bcm_field_th_egress_mode_get(unit, fg, &slice_mode); 31027 } else 31028 #endif 31029 { 31030 rv = _bcm_field_trx_egress_mode_get(unit, fg, &slice_mode); 31031 } 31032 BCM_IF_ERROR_RETURN(rv); 31033 #endif 31034 31035 switch (qual_id){ 31036 case bcmFieldQualifyIpType: 31037 #if defined(BCM_TOMAHAWK3_SUPPORT) 31038 if (SOC_IS_TOMAHAWK3(unit)) { 31039 31040 rv = _bcm_field_th3_qualify_ip_type_encode_get(unit, *data, 31041 *mask, &ipType); 31042 } else 31043 #endif /* BCM_TOMAHAWK3_SUPPORT */ 31044 #if defined(BCM_TRIDENT2_SUPPORT) 31045 if (SOC_IS_TD2_TT2(unit)) { 31046 rv = _bcm_field_td2_qualify_ip_type_encode_get(unit, *data, 31047 *mask, &ipType); 31048 } else 31049 #endif /* BCM_TRIDENT2_SUPPORT */ 31050 #if defined(BCM_TRX_SUPPORT) 31051 if (SOC_IS_TRX(unit)) { 31052 rv = _bcm_field_trx_qualify_ip_type_encode_get(unit, *data, 31053 *mask, &ipType); 31054 } else 31055 #endif /* BCM_TRX_SUPPORT */ 31056 #if defined(BCM_FIREBOLT_SUPPORT) 31057 if (SOC_IS_FIREBOLT(unit)) { 31058 rv = _bcm_field_fb_qualify_ip_type_encode_get(unit, fg, 31059 *data, *mask, 31060 &ipType); 31061 } else 31062 #endif /* BCM_FIREBOLT_SUPPORT */ 31063 #if defined(BCM_RAPTOR1_SUPPORT) 31064 if (SOC_IS_RAPTOR(unit)) { 31065 rv = _bcm_field_raptor_qualify_ip_type_get(unit, entry, 31066 &ipType, qual_id); 31067 } else 31068 #endif /* BCM_RAPTOR1_SUPPORT */ 31069 { 31070 rv = BCM_E_INTERNAL; 31071 } 31072 31073 BCM_IF_ERROR_RETURN(rv); 31074 31075 31076 switch(slice_mode) { 31077 case 1: 31078 case 3: 31079 switch(ipType) { 31080 case bcmFieldIpTypeIp: 31081 case bcmFieldIpTypeIpv4NoOpts: 31082 case bcmFieldIpTypeIpv4Any: 31083 case bcmFieldIpTypeIpv6NoExtHdr: 31084 case bcmFieldIpTypeIpv6OneExtHdr: 31085 case bcmFieldIpTypeIpv6TwoExtHdr: 31086 case bcmFieldIpTypeIpv6: 31087 *can_qualify = 0; 31088 break; 31089 default : 31090 break; 31091 } 31092 break; 31093 case 2: 31094 case 5: 31095 switch(ipType) { 31096 case bcmFieldIpTypeIpv6NoExtHdr: 31097 case bcmFieldIpTypeIpv6OneExtHdr: 31098 case bcmFieldIpTypeIpv6TwoExtHdr: 31099 case bcmFieldIpTypeIpv6: 31100 *can_qualify = 0; 31101 break; 31102 #if defined(BCM_TOMAHAWK_SUPPORT) 31103 case bcmFieldIpTypeIp: 31104 case bcmFieldIpTypeIpv4NoOpts: 31105 case bcmFieldIpTypeIpv4Any: 31106 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 31107 *can_qualify = 0; 31108 } 31109 break; 31110 #endif 31111 default : 31112 break; 31113 } 31114 break; 31115 default: 31116 break; 31117 } 31118 break; 31119 default: 31120 break; 31121 } 31122 return BCM_E_NONE; 31123 } 31124 /* 31125 * Function: 31126 * _field_efp_key_match_type_set_on_qual_delete 31127 * 31128 * Purpose: 31129 * Utility routine for setting efp key match type of an entry 31130 * when qualifier is deleted from the entry. 31131 * 31132 * Parameters: 31133 * unit - (IN) BCM device number 31134 * entry - (IN) Entry ID 31135 * Returns: 31136 * BCM_E_XXX - BCM device number 31137 */ 31138 int 31139 _field_efp_key_match_type_set_on_qual_delete(int unit, bcm_field_entry_t entry) 31140 { 31141 int parts_count = 0; /* Number of entry parts. */ 31142 int part_idx; /* Entry parts iteration index. */ 31143 int qual_idx; /* Part qualifiers iteration index.*/ 31144 int rv; /* Operation return stauts. */ 31145 int idx; 31146 int found; 31147 int idx_max; 31148 int index; 31149 uint32 width; 31150 uint8 can_qualify = 1; 31151 _field_group_t *fg; /* FP group info structure. */ 31152 _field_entry_t *f_ent; /* Pointer to field entry */ 31153 _bcm_field_qual_offset_t *q_offset; /* Qualifier offset structure */ 31154 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 31155 _bcm_field_group_qual_t *q_arr_1; /* Qualifiers array. */ 31156 _bcm_field_qual_data_t q_data; 31157 _bcm_field_qual_data_t q_mask; 31158 /* Search the entry by eid. */ 31159 BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, 31160 &f_ent)); 31161 31162 fg = f_ent->group; 31163 if (NULL == fg) { 31164 return (BCM_E_INTERNAL); 31165 } 31166 31167 /* Get number of entry parts we have to read. */ 31168 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 31169 fg->flags, &parts_count); 31170 BCM_IF_ERROR_RETURN(rv); 31171 31172 for (part_idx = 0; part_idx < parts_count; part_idx++) { 31173 q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx]); 31174 for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) { 31175 idx_max = -1; 31176 q_offset = q_arr->offset_arr + qual_idx; 31177 31178 /* There is no value associated with zero 31179 * width qualifiers (Stage, Ip4 etc) 31180 */ 31181 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width); 31182 if (0 == width) { 31183 continue; 31184 } 31185 31186 _FP_QUAL_DATA_CLEAR(q_data); 31187 _FP_QUAL_DATA_CLEAR(q_mask); 31188 31189 31190 /* Read qualifier match value and mask. */ 31191 rv = _bcm_field_qual_value_get(unit, q_offset, 31192 f_ent + part_idx, 31193 q_data, q_mask); 31194 if (BCM_FAILURE(rv)) { 31195 return rv; 31196 } 31197 31198 /* Check if qualifier was installed. */ 31199 for (idx = 3; idx >= 0; idx--) { 31200 if (q_mask[idx] != 0) { 31201 idx_max = idx; 31202 break; 31203 } 31204 } 31205 31206 if (idx_max >= 0) { 31207 found = FALSE; 31208 for (idx = 0; idx < parts_count; idx++) { 31209 q_arr_1 = &(fg->qual_arr[_FP_ENTRY_TYPE_1][idx]); 31210 for (index = 0; index < q_arr_1->size; index++) { 31211 if (q_arr->qid_arr[qual_idx] == 31212 q_arr_1->qid_arr[index]) { 31213 found = TRUE; 31214 break; 31215 } 31216 } 31217 if (TRUE == found) { 31218 rv = _field_efp_entry_qual_value_qualify(unit, entry, 31219 q_arr->qid_arr[qual_idx], 31220 q_data, q_mask, 31221 &can_qualify); 31222 BCM_IF_ERROR_RETURN(rv); 31223 if (!can_qualify) { 31224 found = FALSE; 31225 } else { 31226 break; 31227 } 31228 } 31229 } 31230 if (FALSE == found) { 31231 f_ent->efp_key_match_type = _FP_ENTRY_TYPE_0; 31232 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 31233 (f_ent + 1)->efp_key_match_type = _FP_ENTRY_TYPE_0; 31234 } 31235 return BCM_E_NONE; 31236 } 31237 } 31238 } 31239 } 31240 31241 f_ent->efp_key_match_type = _FP_ENTRY_TYPE_1; 31242 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 31243 (f_ent + 1)->efp_key_match_type = _FP_ENTRY_TYPE_1; 31244 } 31245 return BCM_E_NONE; 31246 } 31247 /* 31248 * Function: 31249 * _field_efp_key_match_type_set 31250 * 31251 * Purpose: 31252 * Utility routine for setting efp key match type of an entry 31253 * 31254 * Parameters: 31255 * unit - (IN) BCM device number 31256 * qual_add - (IN) Flag to indicate qualifier is added/deleted 31257 * entry - (IN) Entry ID 31258 * per_ent_key_type - (IN) Flag to indicate entry can fit in default key 31259 * grp_def_key_type - (IN) Flag to indicate entry can fit in original key 31260 * Returns: 31261 * BCM_E_XXX - BCM device number 31262 */ 31263 int 31264 _field_efp_key_match_type_set(int unit, 31265 uint8 qual_add, 31266 bcm_field_entry_t entry, 31267 uint8 per_ent_key_type, 31268 uint8 grp_def_key_type) 31269 { 31270 _field_group_t *fg; /* FP group info structure. */ 31271 _field_entry_t *f_ent; /* Field entry info structure */ 31272 int8 use_per_ent_key_type; 31273 int rv; /* Operation return stauts. */ 31274 31275 /* Search the entry by eid. */ 31276 BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, 31277 &f_ent)); 31278 31279 fg = f_ent->group; 31280 if (NULL == fg) { 31281 return (BCM_E_INTERNAL); 31282 } 31283 31284 use_per_ent_key_type = 0; 31285 if (qual_add) { 31286 /* When qualifier is added to the field entry */ 31287 if (grp_def_key_type) { 31288 if (per_ent_key_type && f_ent->efp_key_match_type) { 31289 use_per_ent_key_type = 1; 31290 } 31291 } else { 31292 return BCM_E_INTERNAL; 31293 } 31294 31295 f_ent->efp_key_match_type = use_per_ent_key_type; 31296 31297 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 31298 (f_ent + 1)->efp_key_match_type = use_per_ent_key_type; 31299 } 31300 } else { 31301 /* When qualifier is deleted from the field entry */ 31302 if (_FP_ENTRY_TYPE_0 == f_ent->efp_key_match_type) { 31303 rv = _field_efp_key_match_type_set_on_qual_delete(unit, entry); 31304 if (BCM_FAILURE(rv)) { 31305 return rv; 31306 } 31307 } 31308 } 31309 return BCM_E_NONE; 31310 } 31311 /* 31312 * Function: 31313 * _field_efp_qualify32 31314 * 31315 * Purpose: 31316 * Utility routine for qualify APIs taking 32 bits or less. 31317 * This routine applies to only EGRESS stage. 31318 * 31319 * Parameters: 31320 * unit - (IN)BCM device number 31321 * entry - (IN)Entry ID 31322 * qual - (IN) Qualifier field 31323 * data - (IN)Matching data 31324 * mask - (IN)Bit mask for data 31325 * 31326 * Returns: 31327 * BCM_E_NONE - BCM device number 31328 * BCM_E_PARAM - Qualifier not in group's Qset 31329 * BCM_E_INTERNAL - Entry doesnot belong to any group 31330 */ 31331 int 31332 _field_efp_qualify32(int unit, bcm_field_entry_t entry, 31333 int qual, uint32 *data, uint32 *mask) 31334 { 31335 _bcm_field_qual_offset_t *q_offset; /* Qualifier offset structure */ 31336 _field_entry_t *f_ent; /* Field entry structure */ 31337 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 31338 int parts_count = 0; /* Number of entry parts. */ 31339 int part_idx; /* Entry parts iteration index. */ 31340 int qual_idx; /* Part qualifiers iteration index.*/ 31341 uint8 per_ent_key_type; /* Entry lookup flags. */ 31342 uint8 grp_def_key_type; /* Entry lookup flags. */ 31343 _field_group_t *fg; /* FP group info structure. */ 31344 int rv; /* Operation return stauts. */ 31345 int entry_type; /* Type of an entry */ 31346 uint8 can_qualify = 1; 31347 uint32 multi_width; 31348 #if defined(BCM_TRIDENT3_SUPPORT) 31349 uint32 old_data = 0; 31350 #endif /* BCM_TRIDENT3_SUPPORT */ 31351 31352 /* Search the entry by eid. */ 31353 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 31354 BCM_IF_ERROR_RETURN(rv); 31355 31356 fg = f_ent->group; 31357 if (NULL == fg) { 31358 return (BCM_E_INTERNAL); 31359 } 31360 /* Get number of entry parts we have to read. */ 31361 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 31362 fg->flags, &parts_count); 31363 BCM_IF_ERROR_RETURN(rv); 31364 31365 /* update the EFP tcam.key and key_match_tcam.key */ 31366 if (f_ent->flags & _FP_ENTRY_INSTALLED && 31367 f_ent->flags != _FP_ENTRY_DIRTY) { 31368 for (part_idx = 0; part_idx < parts_count; part_idx++) { 31369 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent+part_idx); 31370 BCM_IF_ERROR_RETURN(rv); 31371 } 31372 } 31373 31374 /* Get field entry part that contains the qualifier. */ 31375 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 31376 BCM_IF_ERROR_RETURN(rv); 31377 31378 /* Get qualifier offsets in the tcam. */ 31379 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 31380 BCM_IF_ERROR_RETURN(rv); 31381 31382 31383 /* Exact match requested, make maximum mask value */ 31384 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, multi_width); 31385 if ((32 >= multi_width) && 31386 (*mask == (uint32)BCM_FIELD_EXACT_MATCH_MASK)) { 31387 31388 *mask = ((32 == q_offset->width[0]) || (32 == multi_width)) 31389 ? ~0 : ((1 << multi_width) - 1); 31390 31391 } 31392 31393 if (bcmFieldQualifyIpType == qual) { 31394 rv = bcm_esw_field_qualifier_delete(unit, entry, qual); 31395 BCM_IF_ERROR_RETURN(rv); 31396 } 31397 31398 grp_def_key_type = FALSE; 31399 per_ent_key_type = FALSE; 31400 #if defined(BCM_TRIDENT3_SUPPORT) 31401 /* to reset the data back to original data after being 31402 * updated for bcmFieldQualifyDstVxlanGport 31403 */ 31404 old_data = *data; 31405 #endif /* BCM_TRIDENT3_SUPPORT */ 31406 for (entry_type = 0; entry_type < _FP_MAX_ENTRY_TYPES; entry_type++) { 31407 31408 /* Search the entry by eid. */ 31409 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 31410 BCM_IF_ERROR_RETURN(rv); 31411 31412 fg = f_ent->group; 31413 if (NULL == fg) { 31414 return (BCM_E_INTERNAL); 31415 } 31416 31417 31418 /* Iterate over all entry parts. */ 31419 for (part_idx = 0; part_idx < parts_count; part_idx++) { 31420 /* Get part qualifiers array. */ 31421 q_arr = &(fg->qual_arr[entry_type][part_idx]); 31422 /* Search array by qualifier id. */ 31423 for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) { 31424 if ((uint16)qual == q_arr->qid_arr[qual_idx]) { 31425 q_offset = q_arr->offset_arr + qual_idx; 31426 #if defined(BCM_TRIDENT3_SUPPORT) 31427 /* for Trident3 devices, DstVxlanGPort qualifier is 31428 * supporting using dvp selector along with class b 31429 * selectors. If DVP selector is used, the dvp_valid 31430 * field should be enabled. Below code checks and 31431 * sets the DVP_valid bit in the tcam key where its 31432 * required based on the offset 31433 */ 31434 if (soc_feature(unit, soc_feature_td3_style_fp)) { 31435 if (qual == bcmFieldQualifyDstVxlanGport) { 31436 if (entry_type == 1) { 31437 *data = old_data; 31438 } 31439 if ((q_offset->offset[0] == 0) || 31440 (q_offset->offset[0] == 1) ) { 31441 *data <<= 1; 31442 /* Set DVP Valid bit. */ 31443 *data |= 1; 31444 } 31445 } 31446 } 31447 #endif /* BCM_TRIDENT3_SUPPORT */ 31448 if (_FP_ENTRY_TYPE_1 == entry_type) { 31449 per_ent_key_type = TRUE; 31450 /* Program data/mask pair to tcam buffer. */ 31451 31452 /* 31453 * COVERITY 31454 * 31455 * This flow takes care of the Out-of-bounds access 31456 * issue for data and mask. 31457 */ 31458 31459 /* coverity[callee_ptr_arith : FALSE] */ 31460 rv = _bcm_field_qual_value_set_by_entry_type(unit, 31461 q_offset, 31462 f_ent + part_idx, 31463 data, mask, 1); 31464 BCM_IF_ERROR_RETURN(rv); 31465 31466 /* When qualifier is found dont go for next qualifier 31467 * in q_arr 31468 */ 31469 break; 31470 31471 } else if (_FP_ENTRY_TYPE_0 == entry_type) { 31472 grp_def_key_type = TRUE; 31473 /* Program data/mask pair to tcam buffer. */ 31474 31475 /* 31476 * COVERITY 31477 * 31478 * This flow takes care of the Out-of-bounds access 31479 * issue for data and mask. 31480 */ 31481 31482 /* coverity[callee_ptr_arith : FALSE] */ 31483 31484 rv = _bcm_field_qual_value_set_by_entry_type(unit, 31485 q_offset, 31486 f_ent + part_idx, 31487 data, mask, 0); 31488 BCM_IF_ERROR_RETURN(rv); 31489 31490 /* When qualifier is found dont go for next qualifier 31491 * in q_arr 31492 */ 31493 break; 31494 } 31495 } 31496 } 31497 31498 /* When qualifier is found dont go for next partition */ 31499 if (((_FP_ENTRY_TYPE_0 == entry_type) && grp_def_key_type) || 31500 ((_FP_ENTRY_TYPE_1 == entry_type) && per_ent_key_type)) { 31501 break; 31502 } 31503 } 31504 31505 /* Qualifier must found in select code types populated 31506 * by group create logic 31507 */ 31508 if (FALSE == grp_def_key_type && (_FP_ENTRY_TYPE_0 == entry_type)) { 31509 return (BCM_E_NOT_FOUND); 31510 } 31511 31512 } 31513 31514 if (per_ent_key_type) { 31515 rv = _field_efp_entry_qual_value_qualify(unit, entry, qual, 31516 data, mask, &can_qualify); 31517 BCM_IF_ERROR_RETURN(rv); 31518 if (!can_qualify) { 31519 per_ent_key_type = FALSE; 31520 } 31521 } 31522 31523 rv = _field_efp_key_match_type_set(unit, TRUE, entry, 31524 per_ent_key_type, 31525 grp_def_key_type); 31526 BCM_IF_ERROR_RETURN(rv); 31527 31528 f_ent->flags |= _FP_ENTRY_DIRTY; 31529 31530 return (BCM_E_NONE); 31531 } 31532 /* 31533 * Function: 31534 * _field_qualify_macaddr_get 31535 * Purpose: 31536 * Get qualifier Source or Destination mac address. 31537 * 31538 * Parameters: 31539 * unit - (IN) BCM device number 31540 * entry - (IN) Field entry to qualify on 31541 * qual - (IN) Field qualifier id. 31542 * data - (OUT)Data to qualify with (type varies) 31543 * mask - (OUT)Mask to qualify with (type is same as for data) 31544 * 31545 * Returns: 31546 * BCM_E_INIT - BCM Unit not initialized. 31547 * BCM_E_XXX - Other errors 31548 */ 31549 int 31550 _field_qualify_macaddr_get(int unit, bcm_field_entry_t entry, 31551 bcm_field_qualify_t qual, 31552 bcm_mac_t *data, bcm_mac_t *mask) 31553 { 31554 _bcm_field_qual_offset_t *q_offset; 31555 _field_entry_t *f_ent; 31556 uint32 ref_data[_FP_QUAL_DATA_WORDS]; 31557 uint32 ref_mask[_FP_QUAL_DATA_WORDS]; 31558 int rv; 31559 31560 /* Input parameters check. */ 31561 if ((NULL == data) || (NULL == mask)) { 31562 return (BCM_E_PARAM); 31563 } 31564 31565 /* Get field entry part that contains the qualifier. */ 31566 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 31567 BCM_IF_ERROR_RETURN(rv); 31568 31569 #if defined(BCM_TOMAHAWK_SUPPORT) 31570 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 31571 /* Read qualifier match value and mask. */ 31572 rv = _field_entry_qualifier_key_get(unit, entry, qual, 31573 ref_data, ref_mask); 31574 } else 31575 #endif /* BCM_TOMAHAWK_SUPPORT */ 31576 { 31577 /* Get qualifier offsets in the tcam. */ 31578 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 31579 BCM_IF_ERROR_RETURN(rv); 31580 31581 /* Read qualifier match value and mask. */ 31582 rv = _bcm_field_qual_value_get(unit, q_offset, f_ent, 31583 ref_data, ref_mask); 31584 } 31585 BCM_IF_ERROR_RETURN(rv); 31586 31587 SAL_MAC_ADDR_FROM_UINT32((*data), ref_data); 31588 SAL_MAC_ADDR_FROM_UINT32((*mask), ref_mask); 31589 31590 return (BCM_E_NONE); 31591 } 31592 31593 /* 31594 * Function: 31595 * _field_qualify_macaddr 31596 * Purpose: 31597 * Qualify on a Source or Destination mac address. 31598 * 31599 * Parameters: 31600 * unit - (IN) BCM device number 31601 * entry - (IN) Field entry to qualify on 31602 * qual - (IN) Field qualifier id. 31603 * data - (IN) Data to qualify with (type varies) 31604 * mask - (IN) Mask to qualify with (type is same as for data) 31605 * 31606 * Returns: 31607 * BCM_E_INIT - BCM Unit not initialized. 31608 * BCM_E_XXX - Other errors 31609 */ 31610 int 31611 _field_qualify_macaddr(int unit, bcm_field_entry_t entry, 31612 bcm_field_qualify_t qual, 31613 bcm_mac_t data, bcm_mac_t mask) 31614 { 31615 _bcm_field_qual_offset_t *q_offset; 31616 _field_entry_t *f_ent; 31617 uint32 ref_data[_FP_QUAL_DATA_WORDS]; 31618 uint32 ref_mask[_FP_QUAL_DATA_WORDS]; 31619 int rv; 31620 31621 SAL_MAC_ADDR_TO_UINT32(data, ref_data); 31622 SAL_MAC_ADDR_TO_UINT32(mask, ref_mask); 31623 31624 /* Get field entry part that contains the qualifier. */ 31625 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 31626 BCM_IF_ERROR_RETURN(rv); 31627 31628 #if defined(BCM_TOMAHAWK_SUPPORT) 31629 /* If device supports per-pipe FP configuration, */ 31630 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 31631 ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 31632 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) || 31633 (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER))) { 31634 /* coverity[callee_ptr_arith : FALSE] */ 31635 return (_bcm_field_th_qualify_set(unit, entry, qual, 31636 ref_data, ref_mask, 31637 _FP_QUALIFIER_ADD)); 31638 } 31639 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 31640 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 31641 return (_bcm_field_th_class_qualify_set(unit, entry, qual, 31642 ref_data, ref_mask)); 31643 } 31644 #endif /* BCM_TOMAHAWK_SUPPORT */ 31645 #if defined(BCM_TRIDENT2_SUPPORT) 31646 if (SOC_IS_TD2_TT2(unit)) { 31647 /* Redirect to _field_efp_qualify32 for egress stage */ 31648 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) { 31649 return _field_efp_qualify32(unit, entry, qual, ref_data, ref_mask); 31650 } 31651 } 31652 #endif /* BCM_TRIDENT2_SUPPORT */ 31653 31654 /* Get qualifier offsets in the tcam. */ 31655 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 31656 BCM_IF_ERROR_RETURN(rv); 31657 31658 /* Program data/mask pair to tcam buffer. */ 31659 /* 31660 * COVERITY 31661 * 31662 *This flow takes care of the Out-of-bounds access issue 31663 * for ref_data and ref_mask. 31664 */ 31665 /* coverity[callee_ptr_arith : FALSE] */ 31666 rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, ref_data, ref_mask); 31667 return (rv); 31668 } 31669 31670 /* 31671 * Function: 31672 * _field_qualify_Port 31673 * Purpose: 31674 * Qualify on a Source or Destination Port. 31675 * 31676 * Parameters: 31677 * unit - BCM device number 31678 * entry - Field entry to qualify on 31679 * data_modid - Data to qualify with (type varies) 31680 * mask_modid - Mask to qualify with (type is same as for data) 31681 * data_port - Data to qualify with (type varies) 31682 * mask_port - Mask to qualify with (type is same as for data) 31683 * 31684 * Returns: 31685 * BCM_E_INIT - BCM Unit not initialized. 31686 * BCM_E_INTERNAL - qual neither SrcPort or DstPort 31687 * BCM_E_NOT_FOUND - Entry ID not found in unit. 31688 * BCM_E_PARAM - port data out of range 31689 * BCM_E_XXX - Other errors 31690 */ 31691 int 31692 _field_qualify_Port(int unit, bcm_field_entry_t entry, 31693 bcm_module_t data_modid, bcm_module_t mask_modid, 31694 bcm_port_t data_port, bcm_port_t mask_port, 31695 bcm_field_qualify_t qual) 31696 { 31697 uint32 mod_port_data = 0; /* concatenated modid and port */ 31698 uint32 mod_port_mask = 0; /* concatenated modid and port */ 31699 31700 if (qual != bcmFieldQualifySrcPort 31701 && qual != bcmFieldQualifyDstPort 31702 && qual != bcmFieldQualifySrcGport 31703 && qual != bcmFieldQualifyDstGport) { 31704 LOG_ERROR(BSL_LS_BCM_FP, 31705 (BSL_META_U(unit, 31706 "FP(unit %d) Error: _field_qualify_Port() only works with" 31707 "SrcPort or DstPort \n"), unit)); 31708 return (BCM_E_INTERNAL); 31709 } 31710 31711 /* Range check data port */ 31712 if (!SOC_PORT_ADDRESSABLE(unit, data_port)) { 31713 LOG_ERROR(BSL_LS_BCM_FP, 31714 (BSL_META_U(unit, 31715 "FP(unit %d) Error: data_port=%#x too large\n"), 31716 unit, data_port)); 31717 return (BCM_E_PARAM); 31718 } 31719 31720 /* Set masks to all ones if exact match is specified. */ 31721 if (mask_modid == BCM_FIELD_EXACT_MATCH_MASK) { 31722 mask_modid = SOC_MODID_MAX(unit); 31723 } 31724 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 31725 /* Trunk Bit (Tf) is not with Trunk/Port ID */ 31726 int num_bits_for_port; 31727 if (mask_port == BCM_FIELD_EXACT_MATCH_MASK) { 31728 mask_port = SOC_PORT_ADDR_MAX(unit); 31729 } 31730 num_bits_for_port = _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit)); 31731 /* SrcPort and DstPort are programmed as 0 - 7 bits are used to store port and 7 - 14 are for Module ID 31732 num_bits_for_port is increased by 2 as SOC_PORT_ADDR_MAX returns 5 for Metrolite. 31733 */ 31734 #if defined(BCM_METROLITE_SUPPORT) 31735 if (SOC_IS_METROLITE(unit)) { 31736 num_bits_for_port += 2; 31737 } 31738 #endif 31739 31740 mod_port_data = (data_modid << num_bits_for_port) | data_port; 31741 mod_port_mask = (mask_modid << num_bits_for_port) | mask_port; 31742 /* Clear the trunk ID bit. */ 31743 mod_port_data &= ~(1 << SOC_TRUNK_BIT_POS(unit)); 31744 /* Must match on the T bit (which should be 0) */ 31745 mod_port_mask |= (1 << SOC_TRUNK_BIT_POS(unit)); 31746 31747 if (bcmFieldQualifyDstPort == qual || bcmFieldQualifyDstGport == qual) { 31748 BCM_IF_ERROR_RETURN(_field_dest_type_qualify(unit, 31749 entry, qual, &mod_port_data, &mod_port_mask, 31750 _bcmFieldDestTypeDglp)); 31751 } 31752 31753 return _field_qualify32(unit, entry, qual, mod_port_data, mod_port_mask); 31754 } 31755 31756 /* Note: Trunk bit is the MSB in PORT_TGID */ 31757 if (mask_port == BCM_FIELD_EXACT_MATCH_MASK) { 31758 mask_port = (1 << (SOC_TRUNK_BIT_POS(unit) + 1)) - 1; 31759 } 31760 31761 /* Combine module IDs and ports */ 31762 mod_port_data = (data_modid << (SOC_TRUNK_BIT_POS(unit) + 1)) | data_port; 31763 mod_port_mask = (mask_modid << (SOC_TRUNK_BIT_POS(unit) + 1)) | mask_port; 31764 31765 /* Clear the trunk ID bit. */ 31766 mod_port_data &= ~(1 << SOC_TRUNK_BIT_POS(unit)); 31767 /* Must match on the T bit (which should be 0) */ 31768 mod_port_mask |= (1 << SOC_TRUNK_BIT_POS(unit)); 31769 31770 if (bcmFieldQualifyDstPort == qual || bcmFieldQualifyDstGport == qual) { 31771 BCM_IF_ERROR_RETURN(_field_dest_type_qualify(unit, 31772 entry, qual, &mod_port_data, &mod_port_mask, 31773 _bcmFieldDestTypeDglp)); 31774 } 31775 31776 return _field_qualify32(unit, entry, qual, mod_port_data, mod_port_mask); 31777 } 31778 31779 31780 /* 31781 * Function: 31782 * _field_qualify_Port_get 31783 * Purpose: 31784 * Qualify on a Source or Destination Port. 31785 * 31786 * Parameters: 31787 * unit - BCM device number 31788 * entry - Field entry to qualify on 31789 * data_modid - Data to qualify with (type varies) 31790 * mask_modid - Mask to qualify with (type is same as for data) 31791 * data_port - Data to qualify with (type varies) 31792 * mask_port - Mask to qualify with (type is same as for data) 31793 * 31794 * Returns: 31795 * BCM_E_INIT - BCM Unit not initialized. 31796 * BCM_E_INTERNAL - qual neither SrcPort or DstPort 31797 * BCM_E_NOT_FOUND - Entry ID not found in unit. 31798 * BCM_E_PARAM - port data out of range 31799 * BCM_E_XXX - Other errors 31800 */ 31801 int 31802 _field_qualify_Port_get(int unit, bcm_field_entry_t entry, 31803 bcm_module_t *data_modid, 31804 bcm_module_t *mask_modid, 31805 bcm_port_t *data_port, 31806 bcm_port_t *mask_port, 31807 bcm_field_qualify_t qual) 31808 { 31809 uint32 mod_port_data = 0; /* Concatenated modid and port */ 31810 uint32 mod_port_mask = 0; /* Concatenated modid and port */ 31811 int rv; /* Operation return stauts. */ 31812 int num_bits_for_port; /* Port field size. */ 31813 int trunk_bit_pos = 0; 31814 31815 /* Input parameter check. */ 31816 if ((NULL == data_modid) || (NULL == mask_modid) || 31817 (NULL == data_port) || (NULL == mask_port)) { 31818 return (BCM_E_PARAM); 31819 } 31820 /* Internal sanity check. */ 31821 if (qual != bcmFieldQualifySrcPort 31822 && qual != bcmFieldQualifyDstPort 31823 && qual != bcmFieldQualifySrcGport) { 31824 return (BCM_E_INTERNAL); 31825 } 31826 31827 /* Read qualifier match value and mask. */ 31828 rv = _bcm_field_entry_qualifier_uint32_get(unit, entry, qual, 31829 (uint32 *)&mod_port_data, 31830 (uint32 *)&mod_port_mask); 31831 BCM_IF_ERROR_RETURN(rv); 31832 31833 if (qual == bcmFieldQualifyDstPort) { 31834 BCM_IF_ERROR_RETURN(_field_dest_type_clear(unit, 31835 entry, qual, (uint32 *) &mod_port_data, (uint32 *) &mod_port_mask)); 31836 } 31837 31838 num_bits_for_port = _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit)); 31839 /* SrcPort and DstPort are programmed as 0 - 7 bits are used to store port and 7 - 14 are for Module ID 31840 num_bits_for_port is increased by 2 as SOC_PORT_ADDR_MAX returns 5 for Metrolite. 31841 */ 31842 31843 #if defined(BCM_METROLITE_SUPPORT) 31844 if (SOC_IS_METROLITE(unit)) { 31845 num_bits_for_port += 2; 31846 } 31847 #endif 31848 /* Get the trunk bit position */ 31849 trunk_bit_pos = SOC_TRUNK_BIT_POS(unit); 31850 31851 /* Clear the overlaid trunk bit from the modid mask. */ 31852 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 31853 /* Get the trunk bit position */ 31854 mod_port_mask = mod_port_mask & ~(1 << trunk_bit_pos); 31855 *data_modid = mod_port_data >> num_bits_for_port; 31856 *mask_modid = mod_port_mask >> num_bits_for_port; 31857 31858 *data_port = mod_port_data & ((1 << num_bits_for_port) - 1); 31859 *mask_port = mod_port_mask & ((1 << num_bits_for_port) - 1); 31860 return (rv); 31861 } 31862 31863 /* Get Modid Info */ 31864 *data_modid = mod_port_data >> (trunk_bit_pos + 1); 31865 *mask_modid = mod_port_mask >> (trunk_bit_pos + 1); 31866 31867 /* Get Port Info */ 31868 *data_port = mod_port_data & ((1 << trunk_bit_pos) - 1); 31869 *mask_port = mod_port_mask & ((1 << trunk_bit_pos) - 1); 31870 return (rv); 31871 } 31872 31873 #define _FIELD_TRUNK_BIT_INSERT(_u_, _t_) \ 31874 ((((_t_) & BCM_TGID_PORT_TRUNK_MASK_HI(_u_)) << 1) | \ 31875 BCM_TGID_TRUNK_INDICATOR(_u_) | ((_t_) & BCM_TGID_PORT_TRUNK_MASK(_u_))) 31876 31877 #define _FIELD_TRUNK_BIT_RESET(_u_, _t_) \ 31878 ((((_t_) - ((_t_) & BCM_TGID_PORT_TRUNK_MASK(_u_))) >> 1) | \ 31879 ((_t_) & BCM_TGID_PORT_TRUNK_MASK(_u_))) 31880 31881 31882 /* 31883 * Function: 31884 * _bcm_field_qualify_trunk 31885 * Purpose: 31886 * Qualify on a Source or Destination Trunk ID. 31887 * 31888 * Parameters: 31889 * unit - BCM device number 31890 * entry - Field entry to qualify on 31891 * qual - Field qualifier of type bcmFieldQualifyXXX. 31892 * data - Trunk ID to qualify 31893 * mask - Trunk mask to qualify 31894 * 31895 * Returns: 31896 * BCM_E_INIT - BCM Unit not initialized. 31897 * BCM_E_INTERNAL - qual neither SrcPort or DstPort 31898 * BCM_E_NOT_FOUND - Entry ID not found in unit. 31899 * BCM_E_PARAM - Trunk ID or mask out of range 31900 * BCM_E_XXX - Other errors 31901 */ 31902 int 31903 _bcm_field_qualify_trunk(int unit, 31904 bcm_field_entry_t entry, 31905 bcm_field_qualify_t qual, 31906 bcm_trunk_t data, 31907 bcm_trunk_t mask) 31908 { 31909 bcm_trunk_t q_mask; 31910 _field_entry_t *f_ent; 31911 _bcm_field_qual_offset_t *q_offset; 31912 uint32 q_width; 31913 int rv; 31914 uint32 trunk_bit_pos = SOC_TRUNK_BIT_POS(unit); 31915 31916 if (qual != bcmFieldQualifySrcTrunk && qual != bcmFieldQualifyDstTrunk 31917 && qual != bcmFieldQualifySrcGport && qual != bcmFieldQualifyDstGport) { 31918 LOG_ERROR(BSL_LS_BCM_FP, 31919 (BSL_META_U(unit, 31920 "FP(unit %d) Error: _bcm_field_qualify_trunk() only works with" 31921 "SrcTrunk or DstTrunk or SrcGport\n"), unit)); 31922 return (BCM_E_INTERNAL); 31923 } 31924 31925 /* 31926 * Validate Trunk ID value. spn_TRUNK_EXTEND is TRUE when device 31927 * supports more than 32 FP trunk groups. 31928 */ 31929 if (soc_property_get(unit, spn_TRUNK_EXTEND, 1) 31930 || soc_feature(unit, soc_feature_trunk_extended_only)) { 31931 TRUNK_CHK_TGID_EXTENDED(unit, data); 31932 } else { 31933 TRUNK_CHK_TGID32(unit, data); 31934 } 31935 31936 /* Get field entry part that contains the qualifier. */ 31937 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 31938 BCM_IF_ERROR_RETURN(rv); 31939 31940 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 31941 /* Trunk Bit (Tf) is not with Trunk/Port ID */ 31942 data = data | (1 << trunk_bit_pos); 31943 mask = mask | (1 << trunk_bit_pos); 31944 } else { 31945 data = _FIELD_TRUNK_BIT_INSERT(unit, data); 31946 mask = _FIELD_TRUNK_BIT_INSERT(unit, mask); 31947 } 31948 31949 if (bcmFieldQualifyDstTrunk == qual || bcmFieldQualifyDstGport == qual) { 31950 BCM_IF_ERROR_RETURN(_field_dest_type_qualify(unit, 31951 entry, qual, (uint32 *)&data, (uint32 *)&mask, 31952 _bcmFieldDestTypeDglp)); 31953 } 31954 31955 /* Get qualifier offsets in the tcam. */ 31956 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 31957 BCM_IF_ERROR_RETURN(rv); 31958 31959 /* 31960 * srcTrunk Qualifier contains TrunkBit + Module ID + Port ID 31961 * MSB bit of Module ID indicates Remote trunk identifier 31962 * Ignoring the remote trunk identifier bit. 31963 * MSB bit position for MOD ID is TrunkBit position - 1 31964 */ 31965 q_mask = ~(1 << (trunk_bit_pos-1)); 31966 31967 if (mask == (uint32)BCM_FIELD_EXACT_MATCH_MASK) { 31968 /* Exact match requested, make maximum mask value */ 31969 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, q_width); 31970 mask = (1 << q_width) - 1; 31971 } 31972 mask &= q_mask; 31973 31974 return _field_qualify32(unit, entry, qual, data, mask); 31975 } 31976 31977 /* 31978 * Function: 31979 * _bcm_field_qualify_trunk_get 31980 * Purpose: 31981 * Get qualifiers Trunk ID and mask. 31982 * 31983 * Parameters: 31984 * unit - (IN) BCM device number 31985 * entry - (IN) Field entry to qualify on 31986 * qual - (IN) Field Qualifier of type bcmFieldQualifyXXX. 31987 * data - (OUT) Trunk ID to qualify 31988 * mask - (OUT) Trunk mask to qualify 31989 * 31990 * Returns: 31991 * BCM_E_XXX 31992 */ 31993 int 31994 _bcm_field_qualify_trunk_get(int unit, 31995 bcm_field_entry_t entry, 31996 bcm_field_qualify_t qual, 31997 bcm_trunk_t *data, 31998 bcm_trunk_t *mask) 31999 { 32000 uint32 hw_data = 0; /* HW buffer data. */ 32001 uint32 hw_mask = 0; /* HW buffer mask. */ 32002 int rv; /* Operation return stauts. */ 32003 32004 /* Input parameters check. */ 32005 if ((NULL == data) || (NULL == mask)) { 32006 return (BCM_E_PARAM); 32007 } 32008 32009 if ((qual != bcmFieldQualifySrcTrunk) && (qual != bcmFieldQualifyDstTrunk)) { 32010 return (BCM_E_INTERNAL); 32011 } 32012 32013 /* Read qualifier match value and mask. */ 32014 rv = _bcm_field_entry_qualifier_uint32_get(unit, entry, qual, 32015 &hw_data, &hw_mask); 32016 BCM_IF_ERROR_RETURN(rv); 32017 32018 if (qual == bcmFieldQualifyDstTrunk) { 32019 BCM_IF_ERROR_RETURN(_field_dest_type_clear(unit, 32020 entry, qual, &hw_data, &hw_mask)); 32021 } 32022 32023 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 32024 /* Trunk Bit (Tf) is not with Trunk/Port ID */ 32025 *data = hw_data & ~(1 << SOC_TRUNK_BIT_POS(unit)); 32026 *mask = hw_mask & ~(1 << SOC_TRUNK_BIT_POS(unit)); 32027 } else { 32028 *data = _FIELD_TRUNK_BIT_RESET(unit, hw_data); 32029 *mask = _FIELD_TRUNK_BIT_RESET(unit, hw_mask); 32030 } 32031 return (BCM_E_NONE); 32032 } 32033 #undef _FIELD_TRUNK_BIT_INSERT 32034 #undef _FIELD_TRUNK_BIT_RESET 32035 32036 /* 32037 * Function: 32038 * _field_qualify_source_virtual_port 32039 * 32040 * Purpose: 32041 * Utility routine to qualify MPLS/MIM Source Virtual Port. 32042 * Parameters: 32043 * unit - BCM device number 32044 * entry - Entry ID 32045 * qual - Qualifier field 32046 * data - Matching data 32047 * mask - Bit mask for data 32048 * ingress_entity - Ingress entity type selector status 32049 * 32050 * Returns: 32051 * BCM_E_NONE - BCM device number 32052 * BCM_E_PARAM - Qualifier not in group's Qset 32053 */ 32054 32055 int 32056 _field_qualify_source_virtual_port(int unit, bcm_field_entry_t entry, 32057 int qual, uint32 data, uint32 mask, int ingress_entity) 32058 { 32059 _bcm_field_qual_offset_t *q_offset; 32060 _field_entry_t *f_ent; 32061 int rv; 32062 32063 /* Get field entry part that contains the qualifier. */ 32064 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32065 BCM_IF_ERROR_RETURN(rv); 32066 32067 /* Get qualifier offsets in the tcam. */ 32068 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 32069 BCM_IF_ERROR_RETURN(rv); 32070 32071 if (((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit))) 32072 && (q_offset->secondary)) { 32073 f_ent->flags |= _FP_ENTRY_USES_IPBM_OVERLAY; 32074 } 32075 32076 if (mask == (uint32)BCM_FIELD_EXACT_MATCH_MASK) { 32077 /* Exact match requested, make maximum mask value */ 32078 mask = ((1 << q_offset->width[0]) - 1); 32079 if ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) && 32080 (SOC_IS_KATANAX(unit))) { 32081 /* 32082 * Setting Mask for SVP_VALID. 32083 * In KT2, SB2 and ML SVP_VALID and S_FIELD are not sequent. 32084 * Hence program mask with two different widths 32085 */ 32086 mask |= (((1 << q_offset->width[1]) - 1) << q_offset->width[0]); 32087 } 32088 } 32089 32090 if ((_BCM_FIELD_STAGE_EXTERNAL != f_ent->group->stage_id) 32091 && (0 == ingress_entity)) { 32092 /* Set SVP valid bit to TRUE */ 32093 data |= ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) && 32094 (SOC_IS_KATANAX(unit))) ? (1 << (q_offset->width[0])) : 32095 (1 << (q_offset->width[0] - 1)); 32096 } 32097 32098 /* Program data/mask pair to tcam buffer. */ 32099 /* 32100 * COVERITY 32101 * 32102 *This flow takes care of the Out-of-bounds access issue 32103 * for data and mask. 32104 */ 32105 /* coverity[callee_ptr_arith : FALSE] */ 32106 rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, &data, &mask); 32107 BCM_IF_ERROR_RETURN(rv); 32108 32109 f_ent->flags |= _FP_ENTRY_DIRTY; 32110 return (BCM_E_NONE); 32111 } 32112 32113 /* 32114 * Function: 32115 * _field_qualifier32_input_range_check 32116 * 32117 * Purpose: 32118 * Utility routine for qualfiers input param check for 32119 * qualifiers whose h/w width is less than the bcm api data 32120 * width 32121 * Parameters: 32122 * unit - BCM device number 32123 * entry - Entry Id 32124 * qual_id - Qualifier field 32125 * data - Matching data 32126 * size - size of data 32127 * Return 32128 * BCM_E_NONE 32129 * BCM_E_PARAM 32130 */ 32131 int _field_qualifier32_input_range_check (int unit, int qual, bcm_field_entry_t entry, 32132 uint8 *data, int size) 32133 { 32134 int width = 0; 32135 int rv = 0; 32136 uint32 max_allowed_data = 0; 32137 _field_entry_t *f_ent = NULL; 32138 _bcm_field_qual_offset_t *q_offset; 32139 int bitpos = 0; 32140 32141 if ((data == NULL) || (size == 0)) { 32142 return BCM_E_PARAM; 32143 } 32144 32145 /* Get field entry part that contains the qualifier. */ 32146 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32147 BCM_IF_ERROR_RETURN(rv); 32148 32149 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 32150 BCM_IF_ERROR_RETURN(rv); 32151 32152 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width); 32153 32154 for (bitpos = 0; bitpos < width; bitpos++) { 32155 max_allowed_data |= (1 << bitpos); 32156 } 32157 32158 switch (size) { 32159 case 1: 32160 if (max_allowed_data < (*data)) { 32161 return BCM_E_PARAM; 32162 } 32163 break; 32164 case 2: 32165 if (max_allowed_data < *((uint16 *)data)) { 32166 return BCM_E_PARAM; 32167 } 32168 break; 32169 case 4: 32170 if (max_allowed_data < *((uint32 *)data)) { 32171 return BCM_E_PARAM; 32172 } 32173 break; 32174 default : 32175 return BCM_E_PARAM; 32176 break; 32177 } 32178 32179 return BCM_E_NONE; 32180 } 32181 32182 /* 32183 * Function: 32184 * _field_qualify32 32185 * 32186 * Purpose: 32187 * Utility routine for qualify APIs taking 32 bits or less 32188 * 32189 * Parameters: 32190 * unit - BCM device number 32191 * entry - Entry ID 32192 * qual - Qualifier field 32193 * data - Matching data 32194 * mask - Bit mask for data 32195 * 32196 * Returns: 32197 * BCM_E_NONE - BCM device number 32198 * BCM_E_PARAM - Qualifier not in group's Qset 32199 */ 32200 32201 int 32202 _field_qualify32(int unit, bcm_field_entry_t entry, 32203 int qual, uint32 data, uint32 mask) 32204 { 32205 _bcm_field_qual_offset_t *q_offset; 32206 _field_entry_t *f_ent; 32207 int rv; 32208 #if defined(BCM_TRIUMPH3_SUPPORT) 32209 esm_l3_protocol_fn_entry_t l3_proto_fn_entry; 32210 uint32 ip_proto, index = data; 32211 #endif 32212 32213 #if defined(BCM_TOMAHAWK_SUPPORT) 32214 if (soc_feature(unit, soc_feature_field_preselector_support) && 32215 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 32216 /* coverity[address_of : FALSE] */ 32217 /* coverity[callee_ptr_arith : FALSE] */ 32218 return _bcm_field_presel_qualify_set(unit, entry, qual, &data, &mask); 32219 } 32220 #endif /* BCM_TOMAHAWK_SUPPORT */ 32221 32222 /* Search the entry by eid. */ 32223 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 32224 BCM_IF_ERROR_RETURN(rv); 32225 32226 if (NULL == f_ent->group) { 32227 return (BCM_E_INTERNAL); 32228 } 32229 #if defined(BCM_TRIDENT2_SUPPORT) 32230 if (SOC_IS_TD2_TT2(unit)) { 32231 /* Redirect to _field_efp_qualify32 for egress stage */ 32232 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) { 32233 /* 32234 * COVERITY 32235 * 32236 * This flow takes care of the Out-of-bounds access 32237 * issue for data and mask. 32238 */ 32239 32240 /* coverity[callee_ptr_arith : FALSE] */ 32241 return _field_efp_qualify32(unit, entry, qual, &data, &mask); 32242 } 32243 } 32244 #endif 32245 32246 #if defined(BCM_TOMAHAWK_SUPPORT) 32247 /* If device supports per-pipe FP configuration, */ 32248 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32249 ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 32250 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) || 32251 (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER))) { 32252 /* coverity[address_of : FALSE] */ 32253 /* coverity[callee_ptr_arith : FALSE] */ 32254 return (_bcm_field_th_qualify_set(unit, entry, qual, 32255 &data, &mask, 32256 _FP_QUALIFIER_ADD)); 32257 } 32258 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32259 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 32260 return (_bcm_field_th_class_qualify_set(unit, entry, qual, 32261 &data, &mask)); 32262 } 32263 #endif /* BCM_TOMAHAWK_SUPPORT */ 32264 32265 /* Get field entry part that contains the qualifier. */ 32266 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32267 BCM_IF_ERROR_RETURN(rv); 32268 32269 /* Get qualifier offsets in the tcam. */ 32270 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 32271 BCM_IF_ERROR_RETURN(rv); 32272 32273 if (((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit))) 32274 && (q_offset->secondary)) 32275 { 32276 f_ent->flags |= _FP_ENTRY_USES_IPBM_OVERLAY; 32277 } 32278 32279 if (mask == (uint32)BCM_FIELD_EXACT_MATCH_MASK) { 32280 int multi_width; 32281 32282 /* Exact match requested, make maximum mask value */ 32283 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, multi_width); 32284 mask = (32 == q_offset->width[0]) ? ~0 : ((1 << multi_width) - 1); 32285 } 32286 32287 #if defined(BCM_TRIUMPH3_SUPPORT) 32288 if (SOC_IS_TRIUMPH3(unit)) { 32289 if ((f_ent->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) && 32290 (qual == bcmFieldQualifyIpProtocol) && 32291 ((q_offset->offset[0] == 132) || (q_offset->offset[0] == 4)) && 32292 (q_offset->width[0] == 4)) { 32293 /* For EXT_IP4 EXT_L2IP4 and EXT_IP6S ACL, L3_PROTOCOL_FN value from 32294 ESM_L3_PROTOCOL_FN table is treated as data to send it to 32295 external TCAM as key */ 32296 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ESM_L3_PROTOCOL_FNm, 32297 MEM_BLOCK_ANY, index, &l3_proto_fn_entry)); 32298 soc_mem_field_get(unit, ESM_L3_PROTOCOL_FNm, 32299 l3_proto_fn_entry.entry_data, 32300 L3_PROTOCOL_FNf, &ip_proto); 32301 data = ip_proto; 32302 mask = 0xf; 32303 } 32304 } 32305 #endif 32306 32307 /* Program data/mask pair to tcam buffer. */ 32308 /* 32309 * COVERITY 32310 * 32311 *This flow takes care of the Out-of-bounds access issue 32312 * for data and mask. 32313 */ 32314 /* coverity[callee_ptr_arith : FALSE] */ 32315 rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, &data, &mask); 32316 BCM_IF_ERROR_RETURN(rv); 32317 32318 f_ent->flags |= _FP_ENTRY_DIRTY; 32319 return (BCM_E_NONE); 32320 } 32321 32322 /* 32323 * Function: 32324 * _field_qualify_cpu_queue 32325 * 32326 * Purpose: 32327 * Utility routine to qualify cos queue. 32328 * Parameters: 32329 * unit - BCM device number 32330 * entry - Entry ID 32331 * qual - Qualifier field 32332 * data - Matching data 32333 * mask - Bit mask for data 32334 * 32335 * Returns: 32336 * BCM_E_NONE - BCM device number 32337 * BCM_E_PARAM - Qualifier not in group's Qset 32338 */ 32339 int 32340 _field_qualify_cpu_queue(int unit, bcm_field_entry_t entry, 32341 int qual, uint32 data, uint32 mask) 32342 { 32343 int rv = BCM_E_NONE; /* return value of this function */ 32344 uint32 cos_queue_data = 0; /* concatenated modified cpu queue and MSB 2 32345 bits with 0 */ 32346 uint32 cos_queue_mask = 0; /* concatenated modified cpu queue mask and 32347 MSB 2 bits of original cpu queue mask */ 32348 #if defined(BCM_TRIDENT2_SUPPORT) 32349 char nm = 0x0, nv = 0x0; /* New mask and New value*/ 32350 char om = 0x0, ov = 0x0; /* Original mask and original value */ 32351 #endif 32352 32353 _field_entry_t *f_ent; 32354 /* Get field entry part that contains the qualifier. */ 32355 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32356 BCM_IF_ERROR_RETURN(rv); 32357 32358 cos_queue_data = data; 32359 cos_queue_mask = mask; 32360 32361 #if defined(BCM_TRIDENT2_SUPPORT) 32362 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit)) { 32363 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) { 32364 32365 /* On Trident2 the CPU cos which ranges from 0~47, is shown as 32366 * value=16~63 in EFP logic, basically the H/W adds 16 to the cos 32367 * value in the key.So in S/W, 16 has to be added to actual data 32368 * value and adjust the mask accordingly passed by application code. 32369 * Since all the manipulation required to bit 5 and 6 of 6 bit wide 32370 * CpuCosQNew, we will generate new mask and new data as in table 32371 * below.We also save the MSB two bits of the mask into SPARE_DVP 32372 * field in the EFP entry. 32373 * So the cpuCosQNew is an 8 bit qualifier now. 32374 * -------------------------------------------------------------- 32375 * |Application calls API with | SDK writes S-CHAN with | 32376 * |----------------------------|---------------------------------| 32377 * | | | CPUCOS[5:4] | SPARE_DVP[1:0] | 32378 * | | |---------------|-----------------| 32379 * | MASK[5:4] | DATA[5:4] | MASK | KEY | MASK | KEY | 32380 * |-------------|--------------|--------|------|--------|--------| 32381 * | 00 | xx | 00 | 00 | 00 | 00 | 32382 * |-------------|--------------|--------|------|--------|--------| 32383 * | 01 | x0 | 01 | 01 | 01 | 00 | 32384 * |-------------|--------------|--------|------|--------|--------| 32385 * | 01 | x1 | 11 | 10 | 01 | 00 | 32386 * |-------------|--------------|--------|------|--------|--------| 32387 * | 10 | 0x | 11 | 01 | 10 | 00 | 32388 * | | | ----|------|--------|--------| 32389 * | | | 11 | 10 | 10 | 00 | 32390 * |-------------|--------------|--------|------|--------|--------| 32391 * | 10 | 10 | 11 | 10 | 10 | 00 | 32392 * |-------------|--------------|--------|------|--------|--------| 32393 * | 11 | 00 | 11 | 01 | 11 | 00 | 32394 * |-------------|--------------|--------|------|--------|--------| 32395 * | 11 | 01 | 11 | 10 | 11 | 00 | 32396 * |-------------|--------------|--------|------|--------|--------| 32397 * | 11 | 10 | 11 | 11 | 11 | 00 | 32398 * |-------------|--------------|---------------------------------| 32399 * | 11(or xx) | 11 | Wrong Value from API, | 32400 * | | | cpu only has 48 queues | 32401 * -------------------------------------------------------------- 32402 */ 32403 cos_queue_data = 0; 32404 cos_queue_mask = 0; 32405 ov = (data >> 4) & 0x3; 32406 om = (mask >> 4) & 0x3; 32407 switch(om) { 32408 case 0x0: 32409 case 0x3: 32410 nm = om; 32411 nv = ov + 1; 32412 break; 32413 case 0x1: 32414 switch(ov) { 32415 case 0x0: 32416 case 0x2: 32417 nm = 0x1; 32418 nv = 0x1; 32419 break; 32420 case 0x1: 32421 nm = 0x3; 32422 nv = 0x2; 32423 break; 32424 } 32425 break; 32426 case 0x2: 32427 switch (ov) { 32428 case 0x0: 32429 case 0x1: 32430 /* Invalid DATA & MASK */ 32431 rv = BCM_E_PARAM; 32432 break; 32433 case 0x2: 32434 nm = 0x3; 32435 nv = 0x2; 32436 break; 32437 case 0x3: 32438 /* Invalid DATA & MASK */ 32439 rv = BCM_E_PARAM; 32440 break; 32441 } 32442 break; 32443 /* coverity[dead_error_begin] */ 32444 default: 32445 /* Invalid DATA & MASK */ 32446 rv = BCM_E_PARAM; 32447 } 32448 32449 if (BCM_E_NONE == rv) { 32450 32451 /* Building new mask and new data */ 32452 32453 cos_queue_data = (data & ~(0x3 << 4)) | (nv << 0x4); 32454 cos_queue_mask = (mask & ~(0x3 << 4)) | (nm << 0x4); 32455 32456 /* copying upper most two bits[5:4] of riginal mask and 00 into 32457 MSB two bits[7:6] of new mask and new data respectively */ 32458 32459 cos_queue_data = (cos_queue_data & ~(0x3 << 6)); 32460 cos_queue_mask = (cos_queue_mask & ~(0x3 << 6)) | (om << 0x6); 32461 } else { 32462 return rv; 32463 } 32464 } 32465 } 32466 #endif 32467 32468 rv = _field_qualify32(unit, entry, qual, cos_queue_data, cos_queue_mask); 32469 BCM_IF_ERROR_RETURN(rv); 32470 32471 f_ent->flags |= _FP_ENTRY_DIRTY; 32472 return (BCM_E_NONE); 32473 } 32474 /* 32475 * Function: 32476 * _field_qualify_cpu_queue_get 32477 * 32478 * Purpose: 32479 * Utility routine to extract qualifier cos queue data and mask. 32480 * Parameters: 32481 * unit - (IN) BCM device number 32482 * entry - (IN) Entry ID 32483 * qual - (IN) Qualifier field 32484 * data - (OUT) Qualifier data 32485 * mask - (OUT) Qualifier mask 32486 * 32487 * Returns: 32488 * BCM_E_NONE - BCM device number 32489 * BCM_E_PARAM - Qualifier not in group's Qset 32490 */ 32491 int 32492 _field_qualify_cpu_queue_get(int unit, bcm_field_entry_t entry, 32493 int qual, uint8 *data, uint8 *mask) 32494 { 32495 int rv = BCM_E_NONE; 32496 32497 #if defined(BCM_TRIDENT2_SUPPORT) 32498 _field_entry_t *f_ent; 32499 /* Get field entry part that contains the qualifier. */ 32500 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32501 BCM_IF_ERROR_RETURN(rv); 32502 #endif 32503 32504 if (NULL == data || NULL == mask) { 32505 return BCM_E_PARAM; 32506 } 32507 32508 /* Read qualifier match value and mask. */ 32509 rv = _bcm_field_entry_qualifier_uint8_get(unit, entry, 32510 bcmFieldQualifyCpuQueue, data, mask); 32511 BCM_IF_ERROR_RETURN(rv); 32512 32513 #if defined(BCM_TRIDENT2_SUPPORT) 32514 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit)) { 32515 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) { 32516 32517 *mask = ((*mask & 0xf) | ((*mask & 0xc0) >> 0x2)); 32518 if (*mask & 0x10) { 32519 *data = *data - 0x10; 32520 } else { 32521 *data = *data & *mask; 32522 } 32523 } 32524 } 32525 #endif 32526 32527 return rv; 32528 } 32529 /* 32530 * Function: 32531 * _field_qualify_ip6_get 32532 * 32533 * Purpose: 32534 * Utility routine to extract qualifier IPv6 data and mask. 32535 * 32536 * Parameters: 32537 * unit - (IN) BCM device number 32538 * entry - (IN) BCM field entry id. 32539 * qual - (IN) Qualifier id. 32540 * flags - (IN) Part of IPv6 address specification. 32541 * data - (OUT) Qualifier data. 32542 * mask - (OUT) Qualifier mask. 32543 * Returns: 32544 * BCM_E_XXX 32545 */ 32546 32547 int 32548 _field_qualify_ip6_get(int unit, bcm_field_entry_t entry, 32549 bcm_field_qualify_t qual, 32550 bcm_ip6_t *data, bcm_ip6_t *mask) 32551 { 32552 _bcm_field_qual_offset_t *q_offset; 32553 _field_entry_t *f_ent; 32554 uint32 ref_data[_FP_QUAL_DATA_WORDS]; 32555 uint32 ref_mask[_FP_QUAL_DATA_WORDS]; 32556 uint8 ref_offset; 32557 int rv; 32558 int i; 32559 32560 /* Input parameters check. */ 32561 if ((NULL == data) || (NULL == mask)) { 32562 return (BCM_E_PARAM); 32563 } 32564 32565 /* Initialization. */ 32566 sal_memset(ref_data, 0, 4 * sizeof(uint32)); 32567 sal_memset(ref_mask, 0, 4 * sizeof(uint32)); 32568 switch(qual) { 32569 case bcmFieldQualifySrcIp6High: 32570 case bcmFieldQualifyDstIp6High: 32571 case bcmFieldQualifyInnerSrcIp6High: 32572 case bcmFieldQualifyInnerDstIp6High: 32573 ref_offset = 2; 32574 break; 32575 default: 32576 ref_offset = 0; 32577 } 32578 32579 /* Get field entry part that contains qualifier. */ 32580 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32581 BCM_IF_ERROR_RETURN(rv); 32582 32583 #if defined(BCM_TOMAHAWK_SUPPORT) 32584 /* If device supports per-pipe FP configuration, */ 32585 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32586 ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 32587 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) || 32588 (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER))) { 32589 /* Read qualifier match value and mask. */ 32590 rv = _bcm_field_th_entry_qualifier_key_get(unit, entry, qual, 32591 ref_data, ref_mask); 32592 BCM_IF_ERROR_RETURN(rv); 32593 } else if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32594 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 32595 32596 /* Read qualifier match value and mask. */ 32597 rv = _bcm_field_th_class_entry_qualifier_key_get(unit, entry, qual, 32598 ref_data, ref_mask); 32599 BCM_IF_ERROR_RETURN(rv); 32600 } else 32601 #endif /* BCM_TOMAHAWK_SUPPORT */ 32602 { 32603 /* Get qualifier offsets in the tcam. */ 32604 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 32605 BCM_IF_ERROR_RETURN(rv); 32606 32607 /* Read qualifier match value and mask. */ 32608 rv = _bcm_field_qual_value_get(unit, q_offset, f_ent, 32609 ref_data, ref_mask); 32610 BCM_IF_ERROR_RETURN(rv); 32611 } 32612 32613 /* Rearrange data and mask according to reference offset */ 32614 for (i = (_FP_QUAL_DATA_WORDS - 1); i >= ref_offset ; i--) { 32615 ref_data[i] = ref_data[i - ref_offset]; 32616 ref_mask[i] = ref_mask[i - ref_offset]; 32617 } 32618 for (i = 0; i < ref_offset; i++) { 32619 ref_data[i] = 0x0; 32620 ref_mask[i] = 0x0; 32621 } 32622 32623 SAL_IP6_ADDR_FROM_UINT32((*data), ref_data); 32624 SAL_IP6_ADDR_FROM_UINT32((*mask), ref_mask); 32625 32626 return (BCM_E_NONE); 32627 } 32628 32629 /* 32630 * Function: 32631 * _field_qualify_ip6 32632 * 32633 * Purpose: 32634 * Utility routine for qualify APIs taking IPv6 data and mask. 32635 * 32636 * Parameters: 32637 * unit - (IN) BCM device number 32638 * entry - (IN) BCM field entry id. 32639 * qual - (IN) Qualifier id. 32640 * data - (IN) Qualifier data. 32641 * mask - (IN) Qualifier mask. 32642 * Returns: 32643 * BCM_E_XXX 32644 */ 32645 32646 int 32647 _field_qualify_ip6(int unit, bcm_field_entry_t entry, 32648 bcm_field_qualify_t qual, 32649 bcm_ip6_t data, bcm_ip6_t mask) 32650 { 32651 _bcm_field_qual_offset_t *q_offset; 32652 _field_entry_t *f_ent; 32653 uint32 ref_data[_FP_QUAL_DATA_WORDS]; 32654 uint32 ref_mask[_FP_QUAL_DATA_WORDS]; 32655 uint8 ref_offset; 32656 int rv; 32657 32658 LOG_DEBUG(BSL_LS_BCM_FP, 32659 (BSL_META_U(unit, 32660 "_field_qualify_ip6\n"))); 32661 32662 /* Initialization. */ 32663 switch(qual) { 32664 case bcmFieldQualifySrcIp6High: 32665 case bcmFieldQualifyDstIp6High: 32666 case bcmFieldQualifyInnerSrcIp6High: 32667 case bcmFieldQualifyInnerDstIp6High: 32668 ref_offset = 2; 32669 break; 32670 default: 32671 ref_offset = 0; 32672 } 32673 32674 /* Get field entry part that contains qualifier. */ 32675 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32676 BCM_IF_ERROR_RETURN(rv); 32677 32678 /* Get qualifier offsets in the tcam. */ 32679 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 32680 BCM_IF_ERROR_RETURN(rv); 32681 32682 SAL_IP6_ADDR_TO_UINT32(data, ref_data); 32683 SAL_IP6_ADDR_TO_UINT32(mask, ref_mask); 32684 32685 #if defined(BCM_TOMAHAWK_SUPPORT) 32686 /* If device supports per-pipe FP configuration, */ 32687 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32688 ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 32689 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) || 32690 (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER))) { 32691 /* coverity[callee_ptr_arith : FALSE] */ 32692 return (_bcm_field_th_qualify_set(unit, entry, qual, 32693 ref_data + ref_offset, 32694 ref_mask + ref_offset, 32695 _FP_QUALIFIER_ADD)); 32696 } 32697 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32698 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 32699 return (_bcm_field_th_class_qualify_set(unit, entry, qual, 32700 ref_data + ref_offset, 32701 ref_mask + ref_offset)); 32702 } 32703 #endif /* BCM_TOMAHAWK_SUPPORT */ 32704 32705 #if defined(BCM_TRIDENT2_SUPPORT) 32706 if (SOC_IS_TD2_TT2(unit)) { 32707 /* Redirect to _field_efp_qualify32 for egress stage */ 32708 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) { 32709 return _field_efp_qualify32(unit, entry, qual, 32710 ref_data + ref_offset, 32711 ref_mask + ref_offset); 32712 } 32713 } 32714 #endif 32715 32716 /* Program data/mask pair to tcam buffer. */ 32717 /* 32718 * COVERITY 32719 * 32720 *This flow takes care of the Out-of-bounds access issue 32721 * for ref_data and ref_mask. 32722 */ 32723 /* coverity[callee_ptr_arith : FALSE] */ 32724 rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, 32725 ref_data + ref_offset, 32726 ref_mask + ref_offset); 32727 BCM_IF_ERROR_RETURN(rv); 32728 32729 f_ent->flags |= _FP_ENTRY_DIRTY; 32730 return (BCM_E_NONE); 32731 } 32732 32733 /* 32734 * Function: 32735 * _field_qualify_L2PayloadFirstEightBytes_get 32736 * 32737 * Purpose: 32738 * Utility routine to extract qualifier L2PayloadFirstEightBytes 32739 * data and mask. 32740 * 32741 * Parameters: 32742 * unit - (IN) BCM device number 32743 * entry - (IN) BCM field entry id. 32744 * qual - (IN) Qualifier id. 32745 * data1 - (OUT) Qualifier first four bytes of match data. 32746 * data2 - (OUT) Qualifier last four bytes of match data. 32747 * mask1 - (OUT) Qualifier first four bytes of match mask. 32748 * mask2 - (OUT) Qualifier last four bytes of match mask. 32749 * Returns: 32750 * BCM_E_XXX 32751 */ 32752 32753 int 32754 _field_qualify_L2PayloadFirstEightBytes_get(int unit, 32755 bcm_field_entry_t entry, 32756 bcm_field_qualify_t qual, 32757 uint32 *data1, uint32 *data2, 32758 uint32 *mask1, uint32 *mask2) 32759 { 32760 _bcm_field_qual_offset_t *q_offset; 32761 _field_entry_t *f_ent; 32762 uint32 ref_data[_FP_QUAL_DATA_WORDS]; 32763 uint32 ref_mask[_FP_QUAL_DATA_WORDS]; 32764 int rv; 32765 32766 /* Input parameters check. */ 32767 if ((NULL == data1) || (NULL == data2) || 32768 (NULL == mask1) || (NULL == mask2)) { 32769 return (BCM_E_PARAM); 32770 } 32771 32772 /* Get field entry part that contains qualifier. */ 32773 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32774 BCM_IF_ERROR_RETURN(rv); 32775 32776 sal_memset(&ref_data, 0, sizeof(ref_data)); 32777 sal_memset(&ref_mask, 0, sizeof(ref_mask)); 32778 32779 #if defined(BCM_TOMAHAWK_SUPPORT) 32780 /* If device supports per-pipe FP configuration, */ 32781 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32782 ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 32783 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) { 32784 /* Read qualifier match value and mask. */ 32785 rv = _bcm_field_th_entry_qualifier_key_get(unit, entry, qual, 32786 ref_data, ref_mask); 32787 BCM_IF_ERROR_RETURN(rv); 32788 } else if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32789 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 32790 32791 /* Read qualifier match value and mask. */ 32792 rv = _bcm_field_th_class_entry_qualifier_key_get(unit, entry, qual, 32793 ref_data, ref_mask); 32794 BCM_IF_ERROR_RETURN(rv); 32795 } else 32796 #endif /* BCM_TOMAHAWK_SUPPORT */ 32797 { 32798 /* Get qualifier offsets in the tcam. */ 32799 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 32800 BCM_IF_ERROR_RETURN(rv); 32801 32802 /* Read qualifier match value and mask. */ 32803 rv = _bcm_field_qual_value_get(unit, q_offset, f_ent, ref_data, 32804 ref_mask); 32805 BCM_IF_ERROR_RETURN(rv); 32806 } 32807 32808 _FP_UNPACK_L2_EIGHT_BYTES_PAYLOAD(ref_data, data1, data2); 32809 _FP_UNPACK_L2_EIGHT_BYTES_PAYLOAD(ref_mask, mask1, mask2); 32810 32811 return (BCM_E_NONE); 32812 } 32813 32814 /* 32815 * Function: 32816 * _field_qualify_L2PayloadFirstEightBytes 32817 * 32818 * Purpose: 32819 * Utility routine for qualify L2PayloadFirstEightBytes 32820 * data and mask. 32821 * 32822 * Parameters: 32823 * unit - (IN) BCM device number 32824 * entry - (IN) BCM field entry id. 32825 * qual - (IN) Qualifier id. 32826 * data1 - (IN) Qualifier first four bytes of match data. 32827 * data2 - (IN) Qualifier last four bytes of match data. 32828 * mask1 - (IN) Qualifier first four bytes of match mask. 32829 * mask2 - (IN) Qualifier last four bytes of match mask. 32830 * 32831 * Returns: 32832 * BCM_E_XXX 32833 */ 32834 32835 int 32836 _field_qualify_L2PayloadFirstEightBytes(int unit, 32837 bcm_field_entry_t entry, 32838 bcm_field_qualify_t qual, 32839 uint32 data1, uint32 data2, 32840 uint32 mask1, uint32 mask2) 32841 { 32842 _bcm_field_qual_offset_t *q_offset; 32843 _field_entry_t *f_ent; 32844 uint32 ref_data[_FP_QUAL_DATA_WORDS]; 32845 uint32 ref_mask[_FP_QUAL_DATA_WORDS]; 32846 int rv; 32847 32848 LOG_DEBUG(BSL_LS_BCM_FP, 32849 (BSL_META_U(unit, 32850 "_field_qualify_L2PayloadFirstEightBytes\n"))); 32851 32852 sal_memset(&ref_data, 0, sizeof(ref_data)); 32853 sal_memset(&ref_mask, 0, sizeof(ref_mask)); 32854 32855 _FP_PACK_L2_EIGHT_BYTES_PAYLOAD(data1, data2, ref_data); 32856 _FP_PACK_L2_EIGHT_BYTES_PAYLOAD(mask1, mask2, ref_mask); 32857 32858 /* Get field entry part that contains qualifier. */ 32859 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 32860 BCM_IF_ERROR_RETURN(rv); 32861 32862 #if defined(BCM_TOMAHAWK_SUPPORT) 32863 /* If device supports per-pipe FP configuration, */ 32864 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32865 ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 32866 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) { 32867 /* coverity[callee_ptr_arith : FALSE] */ 32868 return (_bcm_field_th_qualify_set(unit, entry, qual, 32869 ref_data, ref_mask, 32870 _FP_QUALIFIER_ADD)); 32871 } 32872 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 32873 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 32874 return (_bcm_field_th_class_qualify_set(unit, entry, qual, 32875 ref_data, ref_mask)); 32876 } 32877 #endif /* BCM_TOMAHAWK_SUPPORT */ 32878 32879 /* Get qualifier offsets in the tcam. */ 32880 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 32881 BCM_IF_ERROR_RETURN(rv); 32882 32883 /* Program data/mask pair to tcam buffer. */ 32884 /* 32885 * COVERITY 32886 * 32887 *This flow takes care of the Out-of-bounds access issue 32888 * for ref_data and ref_mask. 32889 */ 32890 /* coverity[callee_ptr_arith : FALSE] */ 32891 rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, ref_data, 32892 ref_mask); 32893 BCM_IF_ERROR_RETURN(rv); 32894 32895 f_ent->flags |= _FP_ENTRY_DIRTY; 32896 return (BCM_E_NONE); 32897 } 32898 32899 /* 32900 * Function: 32901 * _field_entry_shift_down 32902 * Purpose: 32903 * 32904 * Parameters: 32905 * unit - BCM device number 32906 * target_fs - slice where the entry in prio_set should go 32907 * target_index - corresponding index 32908 * next_null_fs - slice which contains a NULL entry after target_index 32909 * next_null_index - corresponding index 32910 * Returns: 32911 * BCM_E_NONE - Success 32912 */ 32913 STATIC int 32914 _field_entry_shift_down(int unit, _field_group_t *fg, 32915 _field_slice_t *target_fs, uint16 target_index, 32916 _field_slice_t *next_null_fs, uint16 next_null_index) 32917 { 32918 uint16 slice_idx_empty; 32919 _field_stage_t *stage_fc; 32920 int slice_sz; 32921 int tmp_idx1; 32922 int tmp_idx2; 32923 _field_slice_t *fs; 32924 int rv; 32925 32926 /* Input parameter check. */ 32927 if ((NULL == target_fs) || (NULL == fg) || (NULL == next_null_fs)) { 32928 return (BCM_E_PARAM); 32929 } 32930 32931 if (target_fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) { 32932 return _field_multimode_slice_entry_shift_down(unit, fg, 32933 target_fs, target_index, 32934 next_null_fs, next_null_index); 32935 } 32936 32937 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, target_fs->stage_id, 32938 &stage_fc)); 32939 32940 slice_idx_empty = next_null_index; 32941 fs = next_null_fs; 32942 32943 /* 32944 * Move entries one step down 32945 * starting from the last entry 32946 * IDEA: 32947 * when in different slices, target_fs != fs 32948 * when in same slice, move till slice_idx_empty > target_index 32949 */ 32950 while ((slice_idx_empty > target_index) || (target_fs != fs)) { 32951 /* Move the entry at the previous index to the empty index. */ 32952 if (slice_idx_empty == 0) { 32953 /* Get number of entries in slice. */ 32954 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs->prev, slice_sz); 32955 32956 /* Get higher slice first entry tcam index. */ 32957 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 32958 fg->instance, 32959 fs->slice_number, 32960 slice_idx_empty, 32961 &tmp_idx1); 32962 BCM_IF_ERROR_RETURN(rv); 32963 32964 /* Get lower slice last entry tcam index. */ 32965 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 32966 fg->instance, 32967 fs->prev->slice_number, 32968 slice_sz - 1, &tmp_idx2); 32969 BCM_IF_ERROR_RETURN(rv); 32970 32971 /* Perform entry move. */ 32972 rv = _field_entry_move(unit, fs->prev->entries[slice_sz-1], 32973 (tmp_idx1 - tmp_idx2)); 32974 BCM_IF_ERROR_RETURN(rv); 32975 32976 slice_idx_empty = slice_sz - 1; 32977 fs = fs->prev; 32978 } else { 32979 /* Get higher entry tcam index. */ 32980 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 32981 fg->instance, 32982 fs->slice_number, 32983 slice_idx_empty, 32984 &tmp_idx1); 32985 BCM_IF_ERROR_RETURN(rv); 32986 32987 /* Get lower entry tcam index. */ 32988 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 32989 fg->instance, 32990 fs->slice_number, 32991 slice_idx_empty - 1, 32992 &tmp_idx2); 32993 BCM_IF_ERROR_RETURN(rv); 32994 32995 /* Perform entry move. */ 32996 rv = _field_entry_move(unit, fs->entries[slice_idx_empty - 1], 32997 (tmp_idx1 - tmp_idx2)); 32998 BCM_IF_ERROR_RETURN(rv); 32999 33000 slice_idx_empty--; 33001 } 33002 } 33003 33004 return (BCM_E_NONE); 33005 } 33006 33007 /* 33008 * Function: 33009 * _field_entry_shift_up 33010 * Purpose: 33011 * 33012 * Parameters: 33013 * unit - BCM device number 33014 * target_fs - slice where the entry in prio_set should go 33015 * target_index - corresponding index 33016 * prev_null_fs - slice which contains a NULL entry before target_index 33017 * prev_null_index - corresponding index 33018 * Returns: 33019 * BCM_E_NONE - Success 33020 */ 33021 STATIC int 33022 _field_entry_shift_up(int unit, _field_group_t *fg, 33023 _field_slice_t *target_fs, uint16 target_index, 33024 _field_slice_t *prev_null_fs, uint16 prev_null_index) 33025 { 33026 uint16 slice_idx_empty; 33027 _field_stage_t *stage_fc; 33028 int slice_sz; 33029 int tmp_idx1; 33030 int tmp_idx2; 33031 _field_slice_t *fs; 33032 int rv; 33033 33034 /* Input parameter check. */ 33035 if ((NULL == target_fs) || (NULL == fg) || (NULL == prev_null_fs)) { 33036 return (BCM_E_PARAM); 33037 } 33038 33039 if (target_fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) { 33040 return _field_multimode_slice_entry_shift_up(unit, fg, 33041 target_fs, target_index, 33042 prev_null_fs, prev_null_index); 33043 } 33044 33045 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, target_fs->stage_id, 33046 &stage_fc)); 33047 33048 slice_idx_empty = prev_null_index; 33049 fs = prev_null_fs; 33050 33051 while ((slice_idx_empty < target_index) || (fs != target_fs)) { 33052 /* Move the entry at the next index to the prev. empty index. */ 33053 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 33054 if (slice_idx_empty == (slice_sz - 1)) { 33055 /* Get lower slice last entry tcam index. */ 33056 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 33057 fg->instance, 33058 fs->slice_number, 33059 slice_sz - 1, &tmp_idx1); 33060 BCM_IF_ERROR_RETURN(rv); 33061 33062 /* Get upper slice first entry tcam index. */ 33063 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 33064 fg->instance, 33065 fs->next->slice_number, 33066 0, &tmp_idx2); 33067 BCM_IF_ERROR_RETURN(rv); 33068 33069 /* Perform entry move. */ 33070 rv = _field_entry_move(unit, fs->next->entries[0], 33071 (tmp_idx1 - tmp_idx2)); 33072 BCM_IF_ERROR_RETURN(rv); 33073 33074 fs = fs->next; 33075 slice_idx_empty = 0; 33076 } else { 33077 /* Get lower entry tcam index. */ 33078 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 33079 fg->instance, 33080 fs->slice_number, 33081 slice_idx_empty, 33082 &tmp_idx1); 33083 BCM_IF_ERROR_RETURN(rv); 33084 33085 /* Get higher entry tcam index. */ 33086 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 33087 fg->instance, 33088 fs->slice_number, 33089 slice_idx_empty + 1, 33090 &tmp_idx2); 33091 BCM_IF_ERROR_RETURN(rv); 33092 33093 /* Perform entry move. */ 33094 rv = _field_entry_move(unit, fs->entries[slice_idx_empty + 1], 33095 (tmp_idx1 - tmp_idx2)); 33096 BCM_IF_ERROR_RETURN(rv); 33097 33098 slice_idx_empty++; 33099 } 33100 } 33101 33102 return (BCM_E_NONE); 33103 } 33104 33105 /* 33106 * Function: 33107 * _field_slice_index_type_get 33108 * Purpose: 33109 * Get Index type at given index in the slice. 33110 * Parameters: 33111 * unit - (IN) BCM device number 33112 * fg - (IN) Field group control 33113 * fs - (IN) Field slice control. 33114 * slice_idx- (IN) Index to verify 33115 * slice_idx_type - (OUT) Index type (_BCM_FIELD_SLICE_IDX_TYPE_XXX) 33116 * Returns: 33117 * BCM_E_NONE - Success 33118 * Notes: 33119 * If slice supports multiple group modes, it is required to verify 33120 * if the given index in the slice can be used for comparison or the 33121 * movement of entry in given group. This function returns the following 33122 * type of index in the given slice: 33123 * _BCM_FIELD_SLICE_IDX_TYPE_FREE - Index is free to be used. 33124 * _BCM_FIELD_SLICE_IDX_TYPE_DIFF - Entry at given index has different group 33125 * flags and should be used. 33126 * _BCM_FIELD_SLICE_IDX_TYPE_SAME - Entry at index has same group flags and 33127 * can be used for priority comparison. 33128 */ 33129 STATIC int 33130 _field_slice_index_type_get(int unit, _field_group_t *fg, _field_slice_t *fs, 33131 int slice_idx, int *slice_idx_type) 33132 { 33133 int part = 0; 33134 int rv = BCM_E_NONE; 33135 int parts_count = 0; 33136 uint32 grp_mode_bmp1 = 0; 33137 uint32 grp_mode_bmp2 = 0; 33138 33139 grp_mode_bmp1 = fg->flags & _FP_GROUP_MODE_MASK; 33140 33141 if (fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) { 33142 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 33143 fg->flags, &parts_count); 33144 BCM_IF_ERROR_RETURN(rv); 33145 33146 /* 33147 * Parts count is always non-zero, however adding this check 33148 * to avoid coverity DIVIDE_BY_ZERO error. 33149 */ 33150 if (parts_count == 0) { 33151 return BCM_E_INTERNAL; 33152 } 33153 33154 if ((slice_idx % parts_count) != 0) { 33155 *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_DIFF; 33156 return rv; 33157 } 33158 33159 *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_FREE; 33160 for (part = 0; part < parts_count; part++) { 33161 if (fs->entries[slice_idx + part] != NULL) { 33162 grp_mode_bmp2 = 33163 fs->entries[slice_idx + part]->group->flags & 33164 _FP_GROUP_MODE_MASK; 33165 if (grp_mode_bmp1 == grp_mode_bmp2) { 33166 *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_SAME; 33167 } else { 33168 *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_DIFF; 33169 break; 33170 } 33171 } 33172 } 33173 } else if (fs->entries[slice_idx] == NULL) { 33174 *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_FREE; 33175 } else { 33176 *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_SAME; 33177 } 33178 33179 return rv; 33180 } 33181 /* 33182 * Function: 33183 * _field_slice_next_match_index_get 33184 * Purpose: 33185 * Get next valid index for given group flags in slice from given index 33186 * in given direction. 33187 * Parameters: 33188 * unit - (IN) BCM device number 33189 * fg - (IN) Field group control 33190 * fs - (IN) Field slice control. 33191 * start_idx- (IN) Start index from where search to start. 33192 * end_idx - (IN) End Index for search. 33193 * dir - (IN) Direction of search (-1 for UP and +1 for Down) 33194 * next_idx - (OUT) First compatible index in given direction. 33195 * Returns: 33196 * BCM_E_NONE - Success 33197 * Notes: 33198 * If slice supports multiple group modes, it is essential to use only 33199 * those indices in the slice which has same index type. This function 33200 * searches in the given direction for entry which has same index type 33201 * as input group in the given slice. In case, no compatible entry is 33202 * found in given direction, -1 is returned. 33203 */ 33204 STATIC int 33205 _field_slice_next_match_index_get(int unit, _field_group_t *fg, 33206 _field_slice_t *fs, int start_idx, 33207 int end_idx, int dir, int *next_index) 33208 { 33209 int rv = BCM_E_NONE; 33210 int parts_count = 1; 33211 int index = 0; 33212 int idx_type; 33213 int slice_sz = 0; 33214 33215 if ((fg == NULL) || (fs == NULL) || (next_index == NULL)) { 33216 return BCM_E_PARAM; 33217 } 33218 33219 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 33220 if (end_idx == -1) { 33221 end_idx = (dir == 1) ? (slice_sz - 1) : 0; 33222 } 33223 33224 if (fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) { 33225 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 33226 fg->flags, &parts_count); 33227 BCM_IF_ERROR_RETURN(rv); 33228 33229 if (dir == -1) { /* Search in UP direction. */ 33230 index = start_idx - parts_count; 33231 while(index >= end_idx) { 33232 _field_slice_index_type_get(unit, fg, fs, index, &idx_type); 33233 if (idx_type != _BCM_FIELD_SLICE_IDX_TYPE_DIFF) { 33234 break; 33235 } 33236 index -= parts_count; 33237 } 33238 } else { /* Search in DOWN direction. */ 33239 index = start_idx + parts_count; 33240 while(index <= end_idx) { 33241 _field_slice_index_type_get(unit, fg, fs, index, &idx_type); 33242 if (idx_type != _BCM_FIELD_SLICE_IDX_TYPE_DIFF) { 33243 break; 33244 } 33245 index += parts_count; 33246 } 33247 } 33248 } else { 33249 index = start_idx + dir; 33250 } 33251 33252 if ((index < 0) || (index >= slice_sz)) { 33253 *next_index = -1; 33254 return BCM_E_INTERNAL; 33255 } 33256 33257 *next_index = index; 33258 33259 return BCM_E_NONE; 33260 } 33261 33262 /* 33263 * Function: 33264 * _field_entry_shift_params_get 33265 * Purpose: 33266 * Calculate paramaters required for shifting entry due to priority change. 33267 * Parameters: 33268 * unit - (IN) BCM device number 33269 * fg - (IN) Field group control 33270 * f_ent - (IN) Field entry whose priority is changed. 33271 * prio - (IN) New Priority. 33272 * shift_params - (OUT) shifting related parameters. 33273 * Returns: 33274 * BCM_E_NONE - Success 33275 * Notes: 33276 * If slice supports multiple group modes, it is required to find 33277 * target/next/prev slice/index which has compatible index type to 33278 * be used for comparison or movement of entry. This function performs 33279 * first part of entry movement i.e. finding out target/next/prev field 33280 * slice for given field group and corresponding indices. 33281 */ 33282 STATIC int 33283 _field_entry_shift_params_get(int unit, _field_group_t *fg, 33284 _field_entry_t *f_ent, int prio, 33285 _bcm_field_entry_shift_params_t *shift_params) 33286 { 33287 int rv = BCM_E_NONE; 33288 _field_slice_t *fs = NULL; 33289 int slice_sz = 0; 33290 int slice_idx_target = 0; 33291 int temp = 0; 33292 int idx_type; 33293 _field_slice_t *first_null_fs = NULL; 33294 _field_slice_t *target_fs = NULL; 33295 int first_null_index = 0; 33296 int first_null_flag = 0; 33297 _field_slice_t *next_null_fs = NULL; 33298 int next_null_index = 0; 33299 _field_slice_t *prev_null_fs = NULL; 33300 int prev_null_index = 0; 33301 int decr_on_shift_up = TRUE; 33302 int flag_no_free_entries = 0; 33303 int only_move = FALSE; 33304 int last_valid_index = 0; 33305 33306 if ((fg == NULL) || (f_ent == NULL) || (shift_params == NULL)) { 33307 return BCM_E_INTERNAL; 33308 } 33309 33310 BCM_IF_ERROR_RETURN(rv); 33311 33312 if (_field_no_free_entries(unit, fg) == TRUE) { 33313 if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) { 33314 /* 33315 * As there are no free entries in any of the slices belonging to 33316 * this group, and this entry is NOT installed, 33317 * fake that it does not exist. 33318 */ 33319 if ((f_ent->fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) && 33320 (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED)) { 33321 f_ent->fs->entries[f_ent->slice_idx] = NULL; 33322 f_ent->fs->entries[f_ent->slice_idx + 1] = NULL; 33323 } else { 33324 f_ent->fs->entries[f_ent->slice_idx] = NULL; 33325 } 33326 flag_no_free_entries = TRUE; 33327 } else { 33328 return BCM_E_CONFIG; 33329 } 33330 } 33331 33332 /* Find the target slice index. That is the one with the highest index 33333 * for this priority class. */ 33334 fs = &fg->slices[0]; 33335 while (fs != NULL) { 33336 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 33337 for (slice_idx_target = 0; 33338 slice_idx_target < slice_sz; 33339 slice_idx_target++) { 33340 33341 /* Skip the f_ent itself */ 33342 if (f_ent == fs->entries[slice_idx_target]) { 33343 continue; 33344 } 33345 /* Check if this Index can be used. */ 33346 _field_slice_index_type_get(unit, fg, fs, slice_idx_target, &idx_type); 33347 if (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_FREE) { 33348 prev_null_fs = fs; 33349 prev_null_index = slice_idx_target; 33350 if (first_null_flag == 0) { 33351 first_null_fs = fs; 33352 first_null_index = slice_idx_target; 33353 first_null_flag = 1; 33354 } 33355 continue; 33356 } else if (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_DIFF) { 33357 continue; 33358 } else { /* idx_type == _BCM_FIELD_SLICE_IDX_SAME_TYPE */ 33359 if (fs->entries[slice_idx_target]->flags & 33360 _FP_ENTRY_CREATED_WITHOUT_PRIO) { 33361 continue; 33362 } 33363 first_null_flag = 0; 33364 } 33365 33366 if (_field_entry_prio_cmp(prio, fs->entries[slice_idx_target]->prio) 33367 > 0) { 33368 LOG_DEBUG(BSL_LS_BCM_FP, 33369 (BSL_META_U(unit, 33370 "FP(unit %d) vverb: Found target slice_idx=%d\n"), 33371 unit, slice_idx_target)); 33372 target_fs = fs; 33373 break; 33374 } 33375 } 33376 if (slice_idx_target < slice_sz) { 33377 break; 33378 } 33379 fs = fs->next; 33380 } 33381 temp = slice_idx_target; 33382 while (fs != NULL) { 33383 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 33384 for (; temp < slice_sz; temp++) { 33385 _field_slice_index_type_get(unit, fg, fs, temp, &idx_type); 33386 if (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_FREE) { 33387 next_null_fs = fs; 33388 next_null_index = temp; 33389 break; 33390 } 33391 } 33392 if (next_null_fs != NULL) { 33393 break; 33394 } 33395 fs = fs->next; 33396 temp = 0; 33397 } 33398 33399 /* 33400 * Put the entry back, 33401 * in case there is a context switch, AND 33402 * another thread calls entry_create 33403 */ 33404 if (flag_no_free_entries == TRUE) { 33405 if ((f_ent->fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) && 33406 (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED)) { 33407 f_ent->fs->entries[f_ent->slice_idx] = f_ent; 33408 f_ent->fs->entries[f_ent->slice_idx + 1] = f_ent + 1; 33409 } else { 33410 f_ent->fs->entries[f_ent->slice_idx] = f_ent; 33411 } 33412 } 33413 33414 if ((prev_null_fs == NULL) && (next_null_fs == NULL)) { 33415 return BCM_E_CONFIG; /* No free entries to move */ 33416 } 33417 33418 if (target_fs == NULL) { 33419 /* 33420 * target_fs will be NULL when the target location is after 33421 * the last entry in slice. 33422 * Now, 33423 * 1. There may be NULL entries after last entry 33424 * Insert entry there 33425 * 2. The last entry is at last location in (last) slice 33426 * Need to do a shift_up to free-up the last location. 33427 */ 33428 /* 33429 * Case 1: 33430 * |-------------| 33431 * | 6 | 33432 * |-------------| 33433 * | 5 | 33434 * |-------------| 33435 * | 4 |<--- change priority to 1 33436 * |-------------| 33437 * | 3 | 33438 * |-------------| 33439 * | 2 | 33440 * |-------------| 33441 * | . | 33442 * |NULL .entries| 33443 * | . | 33444 * |-------------| 33445 * 33446 * becomes |-------------| 33447 * | 6 | 33448 * |-------------| 33449 * | 5 | 33450 * |-------------| 33451 * | NULL | 33452 * |-------------| 33453 * | 3 | 33454 * |-------------| 33455 * | 2 | 33456 * |-------------| 33457 * | . | 33458 * |NULL .entries| 33459 * | 1 |<--- comes to the end. 33460 * |-------------| 33461 * 33462 * Case 2: 33463 * |-------------| 33464 * | . | 33465 * |NULL .entries| 33466 * | . | 33467 * |-------------| 33468 * | 6 | 33469 * |-------------| 33470 * | 5 | 33471 * |-------------| 33472 * | 4 |<--- change priority to 1 33473 * |-------------| 33474 * | 3 | 33475 * |-------------| 33476 * | 2 | 33477 * |-------------| 33478 * 33479 * becomes |-------------| 33480 * | . | 33481 * |NULL .entries| 33482 * | 6 | 33483 * |-------------| 33484 * | 5 | 33485 * |-------------| 33486 * | NULL | 33487 * |-------------| 33488 * | 3 | 33489 * |-------------| 33490 * | 2 | 33491 * |-------------| 33492 * | 1 |<--- comes to the end, 33493 * |-------------| others shift UP 33494 */ 33495 fs = &fg->slices[0]; 33496 while (fs->next != NULL) { 33497 fs = fs->next; 33498 } 33499 /* Get first Index from bottom dir Up which has same type */ 33500 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 33501 _field_slice_next_match_index_get(unit, fg, 33502 fs, slice_sz, -1, -1, &last_valid_index); 33503 if ((fs == prev_null_fs) && 33504 (prev_null_index == last_valid_index) && 33505 (first_null_flag == 1)) { 33506 target_fs = first_null_fs; 33507 slice_idx_target = first_null_index; 33508 only_move = TRUE; 33509 } else { 33510 target_fs = fs; 33511 slice_idx_target = last_valid_index; 33512 decr_on_shift_up = FALSE; 33513 } 33514 } 33515 33516 shift_params->target_fs = target_fs; 33517 shift_params->slice_idx_target = slice_idx_target; 33518 shift_params->next_null_fs = next_null_fs; 33519 shift_params->next_null_index = next_null_index; 33520 shift_params->prev_null_fs = prev_null_fs; 33521 shift_params->prev_null_index = prev_null_index; 33522 shift_params->decr_on_shift_up = decr_on_shift_up; 33523 shift_params->flag_no_free_entries = flag_no_free_entries; 33524 shift_params->only_move = only_move; 33525 33526 shift_params->first_null_fs = first_null_fs; 33527 shift_params->first_null_index = first_null_index; 33528 shift_params->first_null_flag = first_null_flag; 33529 33530 return rv; 33531 } 33532 33533 /* 33534 * Function: _field_entry_prio_set 33535 * 33536 * Purpose: 33537 * 33538 * Parameters: 33539 * unit - BCM device number 33540 * entry - Field entry to operate on 33541 * 33542 * Returns: 33543 * BCM_E_NONE Success 33544 * 33545 * Notes: 33546 * The earlier checks guarantee that there is a free slot somewhere 33547 * i.e. in one of the alloted slices for the group. 33548 */ 33549 int 33550 _field_entry_prio_set(int unit, bcm_field_entry_t entry, int prio) 33551 { 33552 int slice_idx_target = 0; 33553 int temp; 33554 int temp1; 33555 int slice_idx_old; 33556 int idx; 33557 _field_control_t *fc; 33558 _field_group_t *fg; 33559 _field_slice_t *fs; 33560 _field_stage_t *stage_fc; 33561 _field_entry_t *f_ent; 33562 int parts_count = 0; 33563 int rv; 33564 int slice_sz; 33565 _field_slice_t *prev_null_fs = NULL; 33566 /* The last NULL entry b4 target loc */ 33567 _field_slice_t *target_fs = NULL; 33568 /* The target slice */ 33569 _field_slice_t *next_null_fs = NULL; 33570 int prev_null_index = -1; 33571 int next_null_index = -1; 33572 int dir = -1; /* Direction of shift: -1 = UP, 1 = DOWN */ 33573 int decr_on_shift_up = TRUE; 33574 int flag_no_free_entries = FALSE; 33575 _bcm_field_entry_shift_params_t shift_params; 33576 33577 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 33578 33579 rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent); 33580 if (BCM_FAILURE(rv)) { 33581 return (rv); 33582 } 33583 33584 fg = f_ent->group; 33585 fs = f_ent->fs; 33586 33587 if (fg->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 33588 rv = fc->functions.fp_external_entry_prio_set(unit, f_ent, prio); 33589 return (rv); 33590 } 33591 33592 #if defined(BCM_TOMAHAWK_SUPPORT) 33593 /* Priority cannot be set for exact match entries. */ 33594 if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 33595 rv = BCM_E_UNAVAIL; 33596 return (rv); 33597 } 33598 /* Priority set for class entries. */ 33599 if (fg->stage_id == _BCM_FIELD_STAGE_CLASS) { 33600 rv = _bcm_field_th_class_entry_prio_set(unit, f_ent, prio); 33601 return (rv); 33602 } 33603 #endif /* BCM_TOMAHAWK_SUPPORT */ 33604 33605 prio_set_with_no_free_entries[unit] = FALSE; /* Global variable */ 33606 33607 /* Get stage control structure. */ 33608 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 33609 if (BCM_FAILURE(rv)) { 33610 return (rv); 33611 } 33612 33613 /* Get number of entry parts we have to read. */ 33614 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 33615 fg->flags, &parts_count); 33616 BCM_IF_ERROR_RETURN(rv); 33617 33618 /* 33619 * If priority is changing, but still in proper place, 33620 * just goto end (change the f_ent->prio to prio) 33621 */ 33622 if (_field_reqd_prio_set_move(unit, f_ent, prio) == FALSE) { 33623 goto end; 33624 } 33625 33626 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 33627 33628 slice_idx_old = f_ent->slice_idx; 33629 if (slice_idx_old >= slice_sz) { 33630 return (BCM_E_INTERNAL); 33631 } 33632 33633 sal_memset(&shift_params, 0, sizeof(shift_params)); 33634 rv = _field_entry_shift_params_get(unit, fg, f_ent, prio, &shift_params); 33635 if (BCM_FAILURE(rv) && 33636 (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) && 33637 (fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES)) { 33638 rv = _field_multimode_slice_entry_compress(unit, fs); 33639 BCM_IF_ERROR_RETURN(rv); 33640 33641 rv = _field_entry_shift_params_get(unit, fg, f_ent, prio, &shift_params); 33642 } 33643 BCM_IF_ERROR_RETURN(rv); 33644 33645 target_fs = shift_params.target_fs; 33646 slice_idx_target= shift_params.slice_idx_target; 33647 next_null_fs = shift_params.next_null_fs; 33648 next_null_index = shift_params.next_null_index; 33649 prev_null_fs = shift_params.prev_null_fs; 33650 prev_null_index = shift_params.prev_null_index; 33651 flag_no_free_entries = shift_params.flag_no_free_entries; 33652 decr_on_shift_up = shift_params.decr_on_shift_up; 33653 33654 if (shift_params.only_move == TRUE) { 33655 goto only_move; 33656 } 33657 33658 /* 33659 * Check if the movement is feasible 33660 * If group spans across slices, need to verify that 33661 * entries moving across slices do not have shared meters, counters 33662 * AND that new slice has meter, counter available, if required 33663 */ 33664 if (_field_validate_prio_set(unit, fg, f_ent, 33665 prev_null_index, prev_null_fs, 33666 slice_idx_target, target_fs, 33667 next_null_index, next_null_fs, 33668 &dir) == FALSE) { 33669 return (BCM_E_PARAM); 33670 } 33671 33672 if (dir == 1) { 33673 /* 33674 * Move the entry at the target index to target_index+1. This may 33675 * mean shifting more entries down to make room. In other words, 33676 * shift the target index and any that follow it down 1 as far as the 33677 * next empty index. 33678 */ 33679 if (target_fs->entries[slice_idx_target] != NULL) { 33680 rv = _field_entry_shift_down(unit, fg, 33681 target_fs, slice_idx_target, 33682 next_null_fs, next_null_index); 33683 BCM_IF_ERROR_RETURN(rv); 33684 } 33685 } else { 33686 /* 33687 * Similar thing for Shifting UP 33688 * Depends on if this falls into Case-2 in the fig. above. 33689 */ 33690 if (decr_on_shift_up == TRUE) { 33691 _field_slice_next_match_index_get(unit, fg, 33692 target_fs, slice_idx_target, -1, -1, &slice_idx_target); 33693 if (slice_idx_target == -1) { 33694 target_fs = target_fs->prev; 33695 /* 33696 * Certain devices have physical slices of different sizes. 33697 * So, determine the target index based on the new target slice. 33698 */ 33699 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, target_fs, slice_sz); 33700 slice_idx_target = slice_sz - 1; 33701 } 33702 } 33703 if (target_fs->entries[slice_idx_target] != NULL) { 33704 rv = _field_entry_shift_up(unit, fg, 33705 target_fs, slice_idx_target, 33706 prev_null_fs, prev_null_index); 33707 BCM_IF_ERROR_RETURN(rv); 33708 } 33709 } 33710 33711 /* Move the entry from its old slice index to the target slice index. */ 33712 only_move: 33713 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 33714 fg->instance, 33715 target_fs->slice_number, 33716 slice_idx_target, &temp); 33717 BCM_IF_ERROR_RETURN(rv); 33718 33719 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 33720 fg->instance, 33721 f_ent->fs->slice_number, 33722 f_ent->slice_idx, &temp1); 33723 BCM_IF_ERROR_RETURN(rv); 33724 33725 if ((temp - temp1) != 0) { 33726 if (flag_no_free_entries) { 33727 prio_set_with_no_free_entries[unit] = TRUE; 33728 } 33729 33730 rv = _field_entry_move(unit, f_ent, (temp - temp1)); 33731 if (BCM_FAILURE(rv)) { 33732 prio_set_with_no_free_entries[unit] = FALSE; 33733 return rv; 33734 } 33735 33736 /* in case _field_entry_move is called from some other function */ 33737 prio_set_with_no_free_entries[unit] = FALSE; 33738 } 33739 33740 end: 33741 /* Assign the requested priority to the entry. */ 33742 for (idx = 0; idx < parts_count; idx++) { 33743 f_ent[idx].prio = prio; 33744 f_ent[idx].flags &= ~_FP_ENTRY_CREATED_WITHOUT_PRIO; 33745 } 33746 33747 if (fg->group_status.prio_max < prio) { 33748 fg->group_status.prio_max = prio; 33749 } 33750 if (0 <= prio && 33751 (prio < fg->group_status.prio_min || fg->group_status.prio_min < 0)) { 33752 fg->group_status.prio_min = prio; 33753 } 33754 33755 return (BCM_E_NONE); 33756 } 33757 33758 #ifdef BCM_WARM_BOOT_SUPPORT 33759 int _field_table_read(int unit, soc_mem_t mem, char **buffer_p, 33760 const char *buffer_name_p) 33761 { 33762 int index_min; 33763 int index_max; 33764 int rv; 33765 33766 *buffer_p = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem), 33767 buffer_name_p); 33768 33769 if (*buffer_p == NULL) 33770 { 33771 return BCM_E_MEMORY; 33772 } 33773 33774 index_min = soc_mem_index_min(unit, mem); 33775 index_max = soc_mem_index_max(unit, mem); 33776 33777 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, 33778 *buffer_p); 33779 33780 return rv; 33781 } 33782 #endif /* BCM_WARM_BOOT_SUPPORT */ 33783 33784 /* 33785 * Function: _bcm_field_valid_pbmp_get 33786 * 33787 * Purpose: 33788 * Returns valid PBMP 33789 * 33790 * Parameters: 33791 * unit - (IN) BCM device number. 33792 * pbm - (OUT) Pbmp structure. 33793 * Returns: 33794 * BCM_E_XXX 33795 */ 33796 int 33797 _bcm_field_valid_pbmp_get(int unit, bcm_pbmp_t *pbm) 33798 { 33799 bcm_pbmp_t valid_pbm; /* Holds valid pbm supported */ 33800 33801 /* Retrieve valid ports */ 33802 BCM_PBMP_CLEAR(valid_pbm); 33803 BCM_PBMP_ASSIGN(valid_pbm, PBMP_ALL(unit)); 33804 BCM_PBMP_REMOVE(valid_pbm, PBMP_LB(unit)); 33805 BCM_PBMP_REMOVE(valid_pbm, PBMP_RDB_ALL(unit)); 33806 BCM_PBMP_REMOVE(valid_pbm, PBMP_MACSEC_ALL(unit)); 33807 BCM_PBMP_REMOVE(valid_pbm, PBMP_FAE_ALL(unit)); 33808 33809 #ifdef BCM_KATANA2_SUPPORT 33810 if (soc_feature(unit, soc_feature_linkphy_coe) || 33811 soc_feature(unit, soc_feature_subtag_coe)) { 33812 _bcm_kt2_subport_pbmp_update(unit, &valid_pbm); 33813 } 33814 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 33815 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &valid_pbm)); 33816 } 33817 #endif /* BCM_KATANA2_SUPPORT */ 33818 33819 BCM_PBMP_ASSIGN(*pbm, valid_pbm); 33820 33821 return BCM_E_NONE; 33822 } 33823 33824 /* 33825 * Function: _bcm_field_qualify_InPorts 33826 * 33827 * Purpose: 33828 * Initialize entry qualifiers for all ports 33829 * 33830 * Parameters: 33831 * unit - (IN) BCM device number. 33832 * entry - (IN) Field entry structure. 33833 * data - (IN) Field pbmp structure. 33834 * mask - (IN) Field pbmp structure. 33835 * Returns: 33836 * BCM_E_XXX 33837 */ 33838 int 33839 _bcm_field_qualify_InPorts(int unit, 33840 bcm_field_entry_t entry, 33841 bcm_field_qualify_t qual, 33842 bcm_pbmp_t data, 33843 bcm_pbmp_t mask) 33844 { 33845 int rv; 33846 bcm_pbmp_t temp_pbm; /* Holds temp pbmp */ 33847 bcm_pbmp_t valid_pbm; /* Holds valid pbm supported */ 33848 _field_group_t *fg; 33849 _field_entry_t *f_ent; 33850 33851 rv = _bcm_field_entry_qual_get(unit, entry, 33852 bcmFieldQualifyInPorts, &f_ent); 33853 BCM_IF_ERROR_RETURN(rv); 33854 33855 /* Confirm that InPorts is in group's Qset. */ 33856 fg = f_ent->group; 33857 if (!BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPorts)) { 33858 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 33859 "Error: InPorts part of entry group's[%d] QSET.\n\r"), 33860 fg->gid)); 33861 return (BCM_E_PARAM); 33862 } 33863 33864 /* 33865 * Validate InPorts data PBMP with group's PBMP. 33866 * Ports in InPorts pbmp should be part of group's PBMP. 33867 */ 33868 BCM_PBMP_ASSIGN(temp_pbm, data); 33869 BCM_PBMP_OR(temp_pbm, fg->pbmp); 33870 if (BCM_PBMP_NEQ(temp_pbm, fg->pbmp)) { 33871 return BCM_E_PARAM; 33872 } 33873 33874 rv = _bcm_field_valid_pbmp_get(unit, &valid_pbm); 33875 if (BCM_FAILURE(rv)) { 33876 return (rv); 33877 } 33878 /* Check and clear invalid ports in the mask. */ 33879 BCM_PBMP_AND(mask, valid_pbm); 33880 33881 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT) 33882 if (soc_feature(unit, soc_feature_field_ingress_ipbm)) { 33883 bcm_pbmp_t lb_pbm; 33884 33885 /* Add data & mask to entry. */ 33886 BCM_PBMP_ASSIGN(f_ent->pbmp.data, data); 33887 BCM_PBMP_ASSIGN(f_ent->pbmp.mask, mask); 33888 33889 /* Add loopback port to ipbm mask to avoid false ingress port match */ 33890 BCM_PBMP_ASSIGN(lb_pbm, PBMP_LB(unit)); 33891 if (BCM_PBMP_NOT_NULL(lb_pbm)) { 33892 BCM_PBMP_OR(f_ent->pbmp.mask, PBMP_LB(unit)); 33893 } 33894 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC) 33895 /* Add MACSEC Port to IPBM mask to avoid match on MACSEC port */ 33896 if (soc_feature(unit, soc_feature_xflow_macsec)) { 33897 bcm_pbmp_t macsec_pbm; 33898 BCM_PBMP_CLEAR(macsec_pbm); 33899 BCM_PBMP_OR(macsec_pbm, PBMP_MACSEC_ALL(unit)); 33900 if (BCM_PBMP_NOT_NULL(macsec_pbm)) { 33901 BCM_PBMP_OR(f_ent->pbmp.mask, PBMP_MACSEC_ALL(unit)); 33902 } 33903 } 33904 #endif 33905 f_ent->flags |= _FP_ENTRY_DIRTY; 33906 f_ent->flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY); 33907 33908 return (BCM_E_NONE); 33909 } 33910 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */ 33911 33912 rv = _field_qualify32(unit, entry, bcmFieldQualifyInPorts, 33913 SOC_PBMP_WORD_GET(data, 0), 33914 SOC_PBMP_WORD_GET(mask, 0)); 33915 return (rv); 33916 } 33917 33918 /* 33919 * Function: _field_entry_qualifiers_init 33920 * 33921 * Purpose: 33922 * Initialize entry qualifiers based on a group qset. 33923 * 33924 * Parameters: 33925 * unit - (IN) BCM device number. 33926 * f_ent - (IN/OUT) Field entry structure. 33927 * Returns: 33928 * BCM_E_XXX 33929 */ 33930 int 33931 _field_entry_qualifiers_init(int unit, _field_entry_t *f_ent) 33932 { 33933 int count; /* Number of ports. */ 33934 bcm_port_t port; /* Port iterator. */ 33935 _field_group_t *fg; /* Field group info. */ 33936 int rv; /* Operation return status. */ 33937 _field_control_t *fc; /* Field control structure. */ 33938 _field_stage_t *stage_fc; /* Stage field control info. */ 33939 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 33940 int parts_count = 0; /* Field entry parts count. */ 33941 int idx; /* Parts iteration index. */ 33942 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 33943 bcm_pbmp_t all_pbmp; 33944 bcm_pbmp_t data_pbmp; 33945 bcm_pbmp_t valid_mask; 33946 33947 fg = f_ent->group; 33948 33949 /* Read device port configuration. */ 33950 BCM_PBMP_CLEAR(all_pbmp); 33951 rv = _bcm_field_valid_pbmp_get(unit, &all_pbmp); 33952 BCM_IF_ERROR_RETURN(rv); 33953 33954 /* Get field control structure. */ 33955 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 33956 33957 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 33958 BCM_IF_ERROR_RETURN(rv); 33959 33960 /* 33961 * If the group has bcmFieldQualifyInPorts in its Qset, qualify the entry 33962 * on the group's port bitmap. 33963 */ 33964 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPorts)) { 33965 if (fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) { 33966 BCM_PBMP_ASSIGN(data_pbmp, fg->pbmp); 33967 BCM_PBMP_ASSIGN(valid_mask, all_pbmp); 33968 BCM_PBMP_OR(valid_mask, PBMP_LB(unit)); 33969 33970 rv = fc->functions.fp_qualify_inports(unit, 33971 f_ent->eid, 33972 bcmFieldQualifyInPorts, 33973 data_pbmp, 33974 valid_mask); 33975 BCM_IF_ERROR_RETURN(rv); 33976 } 33977 } 33978 /* 33979 * If the group has bcmFieldQualifyOutPorts in its Qset, qualify the entry 33980 * on the group's port bitmap. 33981 */ 33982 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyOutPorts)) { 33983 rv = bcm_esw_field_qualify_OutPorts(unit, f_ent->eid, fg->pbmp, 33984 all_pbmp); 33985 BCM_IF_ERROR_RETURN(rv); 33986 } 33987 /* 33988 * If the group has bcmFieldQualifyInPort in its Qset, and there is only 33989 * one port in the group's pbmp, then qualify on that port. 33990 */ 33991 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPort)) { 33992 BCM_PBMP_COUNT(fg->pbmp, count); 33993 if (count == 1) { 33994 BCM_PBMP_ITER(fg->pbmp, port) { 33995 rv = bcm_esw_field_qualify_InPort(unit, f_ent->eid, port, 33996 BCM_FIELD_EXACT_MATCH_MASK); 33997 BCM_IF_ERROR_RETURN(rv); 33998 } 33999 } 34000 } 34001 34002 /* 34003 * If the group has bcmFieldQualifyIp4/6 in Qset add IpType 34004 * default value to the entry. 34005 */ 34006 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4) && 34007 (fg->stage_id != _BCM_FIELD_STAGE_EXTERNAL)) { 34008 rv = bcm_esw_field_qualify_IpType(unit, f_ent->eid, bcmFieldIpTypeIpv4Any); 34009 BCM_IF_ERROR_RETURN(rv); 34010 } 34011 34012 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6) && 34013 (fg->stage_id != _BCM_FIELD_STAGE_EXTERNAL)) { 34014 rv = bcm_esw_field_qualify_IpType(unit, f_ent->eid, bcmFieldIpTypeIpv6); 34015 BCM_IF_ERROR_RETURN(rv); 34016 } 34017 34018 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 34019 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyDstGport) || 34020 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGport)) { 34021 f_ent->dvp_type = f_ent->svp_type = _bcmVpTypeAny; 34022 } 34023 #endif 34024 34025 /* 34026 * Set key match type for egress FP. 34027 */ 34028 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 34029 if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) { 34030 34031 /* Get number of parts in field entry based on group flags. */ 34032 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 34033 fg->flags, &parts_count); 34034 BCM_IF_ERROR_RETURN(rv); 34035 34036 for (idx = 0; idx < parts_count; idx++) { 34037 rv = fc->functions.fp_egress_key_match_type_set(unit, f_ent + idx); 34038 BCM_IF_ERROR_RETURN(rv); 34039 } 34040 } 34041 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 34042 34043 #if defined(BCM_FLOWTRACKER_SUPPORT) 34044 if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 34045 /* Get number of parts in field entry based on group flags. */ 34046 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 34047 fg->flags, &parts_count); 34048 BCM_IF_ERROR_RETURN(rv); 34049 34050 for (idx = 0; idx < parts_count; idx++) { 34051 rv = _bcm_field_hx5_ft_entry_keytype_set(unit, f_ent + idx); 34052 BCM_IF_ERROR_RETURN(rv); 34053 } 34054 } 34055 #endif 34056 34057 /* 34058 * If the group supports Preselector, qualify the entry on the 34059 * Preselector logical table Id. 34060 */ 34061 #if defined(BCM_TOMAHAWK_SUPPORT) 34062 if ((fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) && 34063 (fg->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER)) { 34064 if (BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyPreLogicalTableId) && 34065 (fg->lt_id != -1)) { 34066 uint32 data, mask; 34067 34068 data = fg->lt_id; 34069 mask = BCM_FIELD_EXACT_MATCH_MASK; 34070 /* coverity[address_of : FALSE] */ 34071 /* coverity[callee_ptr_arith : FALSE] */ 34072 rv = _bcm_field_th_qualify_set(unit, f_ent->eid, 34073 _bcmFieldQualifyPreLogicalTableId, 34074 &data, &mask, _FP_QUALIFIER_ADD); 34075 BCM_IF_ERROR_RETURN(rv); 34076 34077 if (soc_feature(unit, soc_feature_fp_ltid_match_all_parts)) { 34078 if (BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyPreLogicalTableId1)) { 34079 /* coverity[address_of : FALSE] */ 34080 /* coverity[callee_ptr_arith : FALSE] */ 34081 rv = _bcm_field_th_qualify_set(unit, f_ent->eid, 34082 _bcmFieldQualifyPreLogicalTableId1, 34083 &data, &mask, _FP_QUALIFIER_ADD); 34084 BCM_IF_ERROR_RETURN(rv); 34085 } 34086 34087 if (BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyPreLogicalTableId2)) { 34088 /* coverity[address_of : FALSE] */ 34089 /* coverity[callee_ptr_arith : FALSE] */ 34090 rv = _bcm_field_th_qualify_set(unit, f_ent->eid, 34091 _bcmFieldQualifyPreLogicalTableId2, 34092 &data, &mask, _FP_QUALIFIER_ADD); 34093 BCM_IF_ERROR_RETURN(rv); 34094 } 34095 } 34096 } else { 34097 return BCM_E_INTERNAL; 34098 } 34099 } 34100 #endif /* BCM_TOMAHAWK_SUPPORT */ 34101 #if defined(BCM_APACHE_SUPPORT) 34102 f_ent->eth_oam_ctrl_mep_type = 0; 34103 f_ent->eth_oam_data_mep_type = 0; 34104 f_ent->mpls_oam_ctrl_mep_type = 0; 34105 f_ent->mpls_oam_data_mep_type = 0; 34106 #endif 34107 return (BCM_E_NONE); 34108 } 34109 34110 /* 34111 * Function: _field_entry_create_id 34112 * 34113 * Purpose: 34114 * Create a blank entry group based on a group; 34115 * allows selection of a specific slot in a slice 34116 * 34117 * Parameters: 34118 * unit - (IN) BCM device number. 34119 * group - (IN) Field group ID. 34120 * entry - (IN) Requested entry ID; must be in the range prio_min through 34121 * prio_max as returned by bcm_field_group_status_get(). 34122 * Returns: 34123 * BCM_E_INIT - unit not initialized 34124 * BCM_E_EXISTS - Entry ID already in use 34125 * BCM_E_NOT_FOUND - Group ID not found in unit 34126 * BCM_E_MEMORY - allocation failure 34127 * BCM_E_NONE - Success 34128 */ 34129 int 34130 _field_entry_create_id(int unit, bcm_field_group_t group, 34131 bcm_field_entry_t entry) 34132 { 34133 _field_stage_t *stage_fc; /* Stage field control info. */ 34134 _field_group_t *fg; /* Field group info. */ 34135 _field_slice_t *fs_pri = NULL; /* Primary slice pointer. */ 34136 _field_entry_t *f_ent; /* Allocated entry buffer. */ 34137 int rv; /* Operation return status. */ 34138 34139 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 34140 "FP(unit %d) vverb: bcm_esw_field_entry_create_id(group=%d," 34141 " entry=%d)\n"), unit, group, entry)); 34142 34143 /* Confirm that 'entry' is not already used on unit */ 34144 if (BCM_SUCCESS(_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent))) { 34145 LOG_DEBUG(BSL_LS_BCM_FP, 34146 (BSL_META_U(unit, 34147 "FP(unit %d) Error: entry=(%d) already exists.\n"), 34148 unit, entry)); 34149 return (BCM_E_EXISTS); 34150 } 34151 34152 /* Get group control structure. */ 34153 rv = _field_group_get(unit, group, &fg); 34154 if (BCM_FAILURE(rv)) { 34155 LOG_DEBUG(BSL_LS_BCM_FP, 34156 (BSL_META_U(unit, 34157 "FP(unit %d) Error: group=(%d) group get failure.\n"), 34158 unit, group)); 34159 return (rv); 34160 } 34161 34162 #if defined(BCM_TOMAHAWK_SUPPORT) 34163 if((soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0) == 1) && 34164 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) { 34165 LOG_DEBUG(BSL_LS_BCM_FP, 34166 (BSL_META_U(unit, 34167 "Error: ExactMatch group:%d is dedicated to Flowtracker app" 34168 " Field entries can't be created in flow tracker groups\n"), 34169 group)); 34170 return BCM_E_UNAVAIL; 34171 } 34172 #endif /* BCM_TOMAHAWK_SUPPORT */ 34173 34174 /* Get group stage control structure. */ 34175 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 34176 if (BCM_FAILURE(rv)) { 34177 LOG_DEBUG(BSL_LS_BCM_FP, 34178 (BSL_META_U(unit, 34179 "FP(unit %d) Error: Stage (%d) control get failure.\n"), 34180 unit, fg->stage_id)); 34181 return (rv); 34182 } 34183 34184 /* Reserve a slice with room for new entry. */ 34185 rv = _field_group_slice_entry_reserve(unit, fg, &fs_pri); 34186 if (BCM_FAILURE(rv)) { 34187 if(entry != _FP_INTERNAL_RESERVED_ID) { 34188 LOG_DEBUG(BSL_LS_BCM_FP, 34189 (BSL_META_U(unit, 34190 "FP(unit %d) Error: Group (%d) no room.\n"), 34191 unit, group)); 34192 } else { 34193 LOG_DEBUG(BSL_LS_BCM_FP, 34194 (BSL_META_U(unit, 34195 "FP(unit %d) Warning: Group (%d) no room." 34196 " Hitless update cannot be done due to " 34197 "resource constraints\n"), 34198 unit, group)); 34199 } 34200 return (rv); 34201 } 34202 34203 /* Create entry in primary slice. */ 34204 rv = _field_entry_phys_create(unit, stage_fc, entry, 34205 BCM_FIELD_ENTRY_PRIO_LOWEST, 34206 fs_pri, fg, &f_ent); 34207 if (BCM_FAILURE(rv)) { 34208 return (rv); 34209 } 34210 34211 /* Initialize entry qualifiers based on group qset. */ 34212 rv = _field_entry_qualifiers_init(unit, f_ent); 34213 if (BCM_FAILURE(rv)) { 34214 _field_entry_phys_destroy(unit, f_ent); 34215 return (rv); 34216 } 34217 return (BCM_E_NONE); 34218 } 34219 34220 /* Function : _field_tpid_hw_decode 34221 * Description : Encode tpid value to hw specific value. 34222 * Parameters : (IN) unit BCM driver unit 34223 * (IN) hw_code HW code. 34224 * (OUT) tpid decoded TPID 34225 * Returns : BCM_E_XXX 34226 */ 34227 int 34228 _field_tpid_hw_decode(int unit, uint32 hw_code, uint16 *tpid) 34229 { 34230 switch (hw_code) { 34231 case 0x0: 34232 *tpid = 0x8100; 34233 break; 34234 case 0x1: 34235 *tpid = 0x9100; 34236 break; 34237 case 0x2: 34238 *tpid = 0x88a8; 34239 break; 34240 default: 34241 return (BCM_E_UNAVAIL); 34242 } 34243 return (BCM_E_NONE); 34244 } 34245 34246 /* Function : _bcm_field_tpid_hw_encode 34247 * Description : Encode tpid value to hw specific value. 34248 * Parameters : (IN) unit BCM driver unit 34249 * (IN) tpid TPID to encode 34250 * (OUT) hw_code HW code. 34251 * Returns : BCM_E_XXX 34252 */ 34253 int 34254 _bcm_field_tpid_hw_encode(int unit, uint16 tpid, uint32 *hw_code) 34255 { 34256 switch (tpid) { 34257 case 0x8100: 34258 *hw_code = 0x00; 34259 break; 34260 case 0x9100: 34261 *hw_code = 0x01; 34262 break; 34263 case 0x88a8: 34264 *hw_code = 0x02; 34265 break; 34266 default: 34267 *hw_code = 0x03; 34268 } 34269 return (BCM_E_NONE); 34270 } 34271 34272 /* 34273 * Function: 34274 * _field_action_alloc 34275 * Purpose: 34276 * Allocate and initialize an action structure. 34277 * Parameters: 34278 * unit - BCM device number. 34279 * action - Action to perform (bcmFieldActionXXX) 34280 * param0 - Action parameter (use 0 if not required) 34281 * param1 - Action parameter (use 0 if not required) 34282 * param2 - Action parameter (use 0 if not required) 34283 * param3 - Action parameter (use 0 if not required) 34284 * param4 - Action parameter (use 0 if not required) 34285 * param5 - Action parameter (use 0 if not required) 34286 * fa (OUT) - pointer to field action structure 34287 * Returns: 34288 * BCM_E_MEMORY - allocation failure 34289 * BCM_E_NONE - Success 34290 */ 34291 int 34292 _field_action_alloc(int unit, bcm_field_action_t action, 34293 uint32 param0, uint32 param1, 34294 uint32 param2, uint32 param3, 34295 uint32 param4, uint32 param5, 34296 _field_action_t **fa) 34297 { 34298 *fa = sal_alloc(sizeof (_field_action_t), "field_action"); 34299 if (*fa == NULL) { 34300 LOG_ERROR(BSL_LS_BCM_FP, 34301 (BSL_META_U(unit, 34302 "FP(unit %d) Error: allocation failure for field_action\n"), 34303 unit)); 34304 return (BCM_E_MEMORY); 34305 } 34306 sal_memset(*fa, 0, sizeof (_field_action_t)); 34307 34308 (*fa)->action = action; 34309 (*fa)->param[0] = param0; 34310 (*fa)->param[1] = param1; 34311 (*fa)->param[2] = param2; 34312 (*fa)->param[3] = param3; 34313 (*fa)->param[4] = param4; 34314 (*fa)->param[5] = param5; 34315 (*fa)->hw_index = _FP_INVALID_INDEX; 34316 (*fa)->old_index = _FP_INVALID_INDEX; 34317 /* mark new action as not yet installed */ 34318 (*fa)->flags |= (_FP_ACTION_VALID | _FP_ACTION_DIRTY); 34319 (*fa)->egress_pbmp = NULL; 34320 (*fa)->elephant_pkts_only = 0; 34321 34322 return (BCM_E_NONE); 34323 } 34324 34325 /* 34326 * Function: _field_action_add 34327 * 34328 * Purpose: 34329 * Add action performed when entry rule is matched for a packet 34330 * 34331 * Parameters: 34332 * unit - (IN) BCM device number. 34333 * fc - (IN) Field control structure. 34334 * f_ent - (IN) Field entry id. 34335 * fa - (IN) Field action structure. 34336 * Returns: 34337 * BCM_E_XXX 34338 */ 34339 int 34340 _field_action_add(int unit, _field_control_t *fc, 34341 bcm_field_entry_t entry, _field_action_t *fa) 34342 { 34343 _field_entry_t *f_ent; /* Field entry structure. */ 34344 _field_action_t *fa_iter; /* Field entry actions iterator.*/ 34345 int rv; /* Operation return status. */ 34346 #if defined(BCM_TRIDENT_SUPPORT) 34347 uint8 idx; /* entry pard Id */ 34348 bcm_field_action_t action, action1; /* Action type */ 34349 uint32 entry_flags = 0; /* Entry flags */ 34350 #endif 34351 #if defined (BCM_TRIUMPH3_SUPPORT) 34352 uint32 bitIndex; 34353 #endif 34354 34355 #if defined(BCM_TOMAHAWK_SUPPORT) 34356 int supported = 0; /* Action Supported flag. */ 34357 int action_size = 0; /* Action Size. */ 34358 #endif /* BCM_TOMAHAWK_SUPPORT */ 34359 34360 #if defined(BCM_TOMAHAWK_SUPPORT) 34361 if (soc_feature(unit, soc_feature_field_preselector_support) && 34362 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 34363 return _bcm_field_presel_action_add(unit, fc, entry, fa); 34364 } 34365 #endif /* BCM_TOMAHAWK_SUPPORT */ 34366 34367 /* Get field entry structure pointer. */ 34368 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 34369 BCM_IF_ERROR_RETURN(rv); 34370 34371 #if defined(BCM_TOMAHAWK_SUPPORT) 34372 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 34373 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 34374 return (BCM_E_UNAVAIL); 34375 } 34376 #endif /* BCM_TOMAHAWK_SUPPORT */ 34377 34378 /* Confirm that action is in aset. */ 34379 /* coverity[ptr_arith] */ 34380 if (SHR_BITGET(f_ent->group->aset.w, fa->action) == 0) { 34381 if(f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 34382 if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) { 34383 #if defined(BCM_TOMAHAWK_SUPPORT) 34384 BCM_IF_ERROR_RETURN( 34385 _bcm_field_th_action_support_check(unit, f_ent, 34386 fa->action, &supported)); 34387 if (!supported) { 34388 #ifdef BROADCOM_DEBUG 34389 LOG_ERROR(BSL_LS_BCM_FP, 34390 (BSL_META_U(unit, 34391 "FP(unit %d) Error: action=%s not supported\n"), 34392 unit,_field_action_name(fa->action))); 34393 #endif 34394 return (BCM_E_UNAVAIL); 34395 } 34396 #endif /* BCM_TOMAHAWK_SUPPORT */ 34397 } else { 34398 #ifdef BROADCOM_DEBUG 34399 LOG_ERROR(BSL_LS_BCM_FP, 34400 (BSL_META_U(unit, 34401 "FP(unit %d) Error: action=%s not supported\n"), 34402 unit,_field_action_name(fa->action))); 34403 #endif 34404 return (BCM_E_UNAVAIL); 34405 } 34406 } else { 34407 #ifdef BROADCOM_DEBUG 34408 LOG_ERROR(BSL_LS_BCM_FP, 34409 (BSL_META_U(unit, 34410 "FP(unit %d) Error: action=%s not supported\n"), 34411 unit,_field_action_name(fa->action))); 34412 #endif 34413 return (BCM_E_UNAVAIL); 34414 } 34415 } 34416 34417 #if defined BCM_TRIDENT2_SUPPORT || defined BCM_TOMAHAWK_SUPPORT 34418 /* Check if actions conflict with Statistics action */ 34419 BCM_IF_ERROR_RETURN (_bcm_field_action_stat_conflict_check(unit, f_ent, fa)); 34420 #endif 34421 34422 /* Oam Actions conflict with Nat actions */ 34423 if (soc_feature(unit, soc_feature_fp_based_oam)) { 34424 if ((fa->action == bcmFieldActionNatEgressOverride) 34425 || (fa->action == bcmFieldActionNat) 34426 || (fa->action == bcmFieldActionNatCancel)) { 34427 if (f_ent->flags & _FP_ENTRY_OAM_STAT_VALID) { 34428 #ifdef BROADCOM_DEBUG 34429 LOG_ERROR(BSL_LS_BCM_FP, 34430 (BSL_META_U(unit, 34431 "FP(unit %d) Error: action=%s conflicts with" 34432 " oam stat action in entry=%d\n"), unit, 34433 _field_action_name(fa->action), entry )); 34434 #endif 34435 return BCM_E_CONFIG; 34436 } 34437 } 34438 } 34439 34440 /* Check for existing actions that conflict with the new action. */ 34441 fa_iter = f_ent->actions; 34442 while (fa_iter != NULL) { 34443 if (0 == (fa_iter->flags & _FP_ACTION_VALID)) { 34444 fa_iter = fa_iter->next; 34445 continue; 34446 } 34447 rv = fc->functions.fp_action_conflict_check(unit, 34448 f_ent, 34449 fa_iter->action, 34450 fa->action); 34451 if (BCM_FAILURE(rv)) { 34452 #ifdef BROADCOM_DEBUG 34453 LOG_ERROR(BSL_LS_BCM_FP, 34454 (BSL_META_U(unit, 34455 "FP(unit %d) Error: action=%s conflicts with " 34456 "existing action in entry=%d\n"), unit, 34457 _field_action_name(fa->action), entry )); 34458 #endif 34459 return (rv); 34460 } 34461 fa_iter = fa_iter->next; 34462 } 34463 #if defined (BCM_TRIUMPH3_SUPPORT) 34464 if(SOC_IS_TRIUMPH3(unit)) { 34465 if(fa->action == bcmFieldActionReplaceSrcMac || 34466 fa->action == bcmFieldActionReplaceDstMac || 34467 fa->action == bcmFieldActionReplaceInnerVlan || 34468 fa->action == bcmFieldActionReplaceOuterVlan || 34469 fa->action == bcmFieldActionReplaceInnerVlanPriority || 34470 fa->action == bcmFieldActionReplaceOuterVlanPriority) { 34471 fa_iter = f_ent->actions; 34472 fa->hw_index = -1; 34473 while (fa_iter != NULL) { 34474 if(fa_iter->action == bcmFieldActionReplaceSrcMac || 34475 fa_iter->action == bcmFieldActionReplaceDstMac || 34476 fa_iter->action == bcmFieldActionReplaceInnerVlan || 34477 fa_iter->action == bcmFieldActionReplaceOuterVlan || 34478 fa_iter->action == bcmFieldActionReplaceInnerVlanPriority || 34479 fa_iter->action == bcmFieldActionReplaceOuterVlanPriority) { 34480 fa->hw_index = fa_iter->hw_index; 34481 break; 34482 } 34483 fa_iter = fa_iter->next; 34484 } 34485 34486 if(fa->hw_index < 0) { 34487 bitIndex = 0; 34488 for (bitIndex=0; bitIndex < fc->_fp_egr_ifp_mod_fields_size;bitIndex++) { 34489 if(SHR_BITGET(fc->field_action_l2mod_index_bmp.w,bitIndex) == 0) { 34490 break; 34491 } 34492 } 34493 SHR_BITSET(fc->field_action_l2mod_index_bmp.w,bitIndex); 34494 fa->hw_index = bitIndex; 34495 } 34496 } 34497 } 34498 #endif 34499 34500 #if defined(BCM_TRIDENT_SUPPORT) 34501 if (SOC_IS_TD_TT(unit) && 34502 !soc_feature(unit, soc_feature_field_multi_pipe_support)) { 34503 if ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 34504 (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) || 34505 (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 34506 if (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 34507 entry_flags = (_FP_ENTRY_PRIMARY | _FP_ENTRY_SECOND_HALF); 34508 } else { 34509 entry_flags = _FP_ENTRY_SECONDARY; 34510 } 34511 rv = _bcm_field_entry_flags_to_tcam_part(unit, entry_flags, 34512 f_ent->group, 34513 &idx); 34514 BCM_IF_ERROR_RETURN(rv); 34515 fa_iter = f_ent[idx].actions; 34516 while (fa_iter != NULL) { 34517 if (0 == (fa_iter->flags & _FP_ACTION_VALID)) { 34518 fa_iter = fa_iter->next; 34519 continue; 34520 } 34521 rv = fc->functions.fp_action_conflict_check(unit, 34522 f_ent, 34523 fa_iter->action, 34524 fa->action); 34525 if (BCM_FAILURE(rv)) { 34526 #ifdef BROADCOM_DEBUG 34527 LOG_ERROR(BSL_LS_BCM_FP, 34528 (BSL_META_U(unit, 34529 "FP(unit %d) Error: action=%s conflicts with " 34530 "existing action in entry=%d\n"), unit, 34531 _field_action_name(fa->action), entry )); 34532 #endif 34533 return (rv); 34534 } 34535 fa_iter = fa_iter->next; 34536 } 34537 } 34538 } 34539 #endif 34540 /* Check action parameters. */ 34541 rv = fc->functions.fp_action_params_check(unit, f_ent, fa); 34542 if (BCM_FAILURE(rv)) { 34543 #ifdef BROADCOM_DEBUG 34544 LOG_ERROR(BSL_LS_BCM_FP, 34545 (BSL_META_U(unit, 34546 "FP(unit %d) Error: action=%s parameters check failed (%d)\n"), 34547 unit, _field_action_name(fa->action), rv)); 34548 #endif 34549 return (rv); 34550 } 34551 34552 /* Check dependency(s) of action */ 34553 if (fc->functions.fp_action_depends_check) { 34554 rv = (*fc->functions.fp_action_depends_check)(unit, f_ent, fa); 34555 if (BCM_FAILURE(rv)) { 34556 #ifdef BROADCOM_DEBUG 34557 LOG_ERROR(BSL_LS_BCM_FP, 34558 (BSL_META_U(unit, 34559 "FP(unit %d) Error: action=%s dependency check failed (%d)\n"), 34560 unit, _field_action_name(fa->action), rv)); 34561 #endif 34562 return (rv); 34563 } 34564 } 34565 34566 34567 #if defined(BCM_TOMAHAWK_SUPPORT) 34568 if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) { 34569 rv = _field_th_em_entry_action_size_get(unit, f_ent, 34570 &action_size, NULL); 34571 if (BCM_FAILURE(rv)) { 34572 return (rv); 34573 } 34574 34575 if (action_size > EM_DEFAULT_POLICY_ACTION_DATA_SIZE) { 34576 return (BCM_E_RESOURCE); 34577 } 34578 } 34579 #endif /* BCM_TOMAHAWK_SUPPORT */ 34580 34581 if (fa->action == bcmFieldActionColorIndependent) { 34582 if (fa->param[0]) { 34583 f_ent->flags |= _FP_ENTRY_COLOR_INDEPENDENT; 34584 } else { 34585 f_ent->flags &= ~_FP_ENTRY_COLOR_INDEPENDENT; 34586 } 34587 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 34588 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 34589 } 34590 f_ent->flags |= _FP_ENTRY_DIRTY; 34591 34592 if (NULL != (fa->egress_pbmp)) { 34593 sal_free(fa->egress_pbmp); 34594 } 34595 sal_free(fa); 34596 return (BCM_E_NONE); 34597 } 34598 34599 #if defined(BCM_TRIDENT_SUPPORT) 34600 if (SOC_IS_TD_TT(unit) && 34601 !soc_feature(unit, soc_feature_field_multi_pipe_support)) { 34602 if ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 34603 (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) || 34604 (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 34605 switch(fa->action) { 34606 case bcmFieldActionCosQCpuNew: 34607 action = bcmFieldActionServicePoolIdNew; 34608 action1 = bcmFieldActionServicePoolIdPrecedenceNew; 34609 break; 34610 case bcmFieldActionServicePoolIdNew: 34611 case bcmFieldActionServicePoolIdPrecedenceNew: 34612 action = bcmFieldActionCosQCpuNew; 34613 action1 = -1; 34614 break; 34615 default: 34616 action = bcmFieldActionCount; 34617 break; 34618 } 34619 if (action != bcmFieldActionCount) { 34620 for (fa_iter = f_ent->actions; 34621 fa_iter != NULL; 34622 fa_iter = fa_iter->next) { 34623 if (((fa_iter->action == action) || 34624 (fa_iter->action == action1)) && 34625 (fa_iter->flags & _FP_ACTION_VALID)) { 34626 rv = _bcm_field_entry_flags_to_tcam_part( 34627 unit, 34628 entry_flags, 34629 f_ent->group, 34630 &idx); 34631 BCM_IF_ERROR_RETURN(rv); 34632 fa->next = f_ent[idx].actions; 34633 f_ent[idx].actions = fa; 34634 if (0 == (f_ent[idx].flags & _FP_ENTRY_DIRTY)) { 34635 f_ent[idx].flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 34636 } 34637 f_ent[idx].flags |= _FP_ENTRY_DIRTY; 34638 return (BCM_E_NONE); 34639 } 34640 } 34641 } 34642 } 34643 } 34644 #endif 34645 34646 #if defined BCM_TRIDENT2_SUPPORT 34647 BCM_IF_ERROR_RETURN(_bcm_field_action_stat_flag_update(unit, f_ent, fa, TRUE)); 34648 #endif 34649 34650 /* Oam Actions conflict with Nat actions */ 34651 if (soc_feature(unit, soc_feature_fp_based_oam)) { 34652 if ((fa->action == bcmFieldActionNatEgressOverride) 34653 || (fa->action == bcmFieldActionNat) 34654 || (fa->action == bcmFieldActionNatCancel)) { 34655 f_ent->flags |= _FP_ENTRY_OAM_STAT_NOT_ALLOWED; 34656 } 34657 } 34658 34659 /* Add action to front of entry's linked-list. */ 34660 fa->next = f_ent->actions; 34661 f_ent->actions = fa; 34662 /* 34663 * Do not set action only dirty flag if qualifier parameter has 34664 * been modified for this entry. 34665 */ 34666 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 34667 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 34668 } 34669 f_ent->flags |= _FP_ENTRY_DIRTY; 34670 34671 return (BCM_E_NONE); 34672 } 34673 34674 /* 34675 * Function: _bcm_field_action_ports_add 34676 * 34677 * Purpose: 34678 * Add action performed when entry rule is matched for a packet 34679 * 34680 * Parameters: 34681 * unit - BCM device number 34682 * entry - entry ID 34683 * action - Action to perform (bcmFieldActionXXX) 34684 * param0 - Action parameter (use 0 if not required) 34685 * param1 - Action parameter (use 0 if not required) 34686 * param2 - Action parameter (use 0 if not required) 34687 * param3 - Action parameter (use 0 if not required) 34688 * param4 - Action parameter (use 0 if not required) 34689 * param5 - Action parameter (use 0 if not required) 34690 * 34691 * Returns: 34692 * BCM_E_XXX 34693 */ 34694 int 34695 _bcm_field_action_ports_add(int unit, 34696 bcm_field_entry_t entry, 34697 bcm_field_action_t action, 34698 uint32 param0, uint32 param1, 34699 uint32 param2, uint32 param3, 34700 uint32 param4, uint32 param5) 34701 { 34702 _field_control_t *fc; /* Field control structure. */ 34703 _field_action_t *fa = NULL; /* Field action descriptor. */ 34704 int rv; /* Operation return status. */ 34705 34706 #ifdef BROADCOM_DEBUG 34707 LOG_DEBUG(BSL_LS_BCM_FP, 34708 (BSL_META_U(unit, 34709 "FP(unit %d) vverb: bcm_field_action_add(entry=%d, action=%s, " 34710 "p0=%d, p1=%d, p2=%d, p3=%d, p4=%d, p5=%d)\n"), unit, entry, 34711 _field_action_name(action), 34712 param0, param1, param2, param3, param4, param5)); 34713 #endif 34714 34715 34716 FP_LOCK(unit); 34717 rv = _field_control_get(unit, &fc); 34718 if (BCM_FAILURE(rv)) { 34719 FP_UNLOCK(unit); 34720 return rv; 34721 } 34722 34723 /* 34724 * Allocate the action descriptor. 34725 */ 34726 rv = _field_action_alloc(unit, action, 34727 param0, param1, param2, param3, param4, param5, &fa); 34728 if (BCM_FAILURE(rv)) { 34729 LOG_ERROR(BSL_LS_BCM_FP, 34730 (BSL_META_U(unit, 34731 "FP(unit %d) Error: failure in _field_action_alloc()\n"), 34732 unit)); 34733 FP_UNLOCK(unit); 34734 return rv; 34735 } 34736 34737 /* 34738 * Add action to entry actions list. 34739 */ 34740 rv = _field_action_add(unit, fc, entry, fa); 34741 FP_UNLOCK(unit); 34742 if (BCM_FAILURE(rv)) { 34743 sal_free(fa); 34744 return rv; 34745 } 34746 return (BCM_E_NONE); 34747 } 34748 34749 /* 34750 * Function: _bcm_field_action_ports_get 34751 * 34752 * Purpose: 34753 * Get parameters associated with an entry action 34754 * 34755 * Parameters: 34756 * unit - BCM device number 34757 * entry - Entry ID 34758 * action - Action to perform (bcmFieldActionXXX) 34759 * param0 - (OUT) Action parameter 34760 * param1 - (OUT) Action parameter 34761 * param2 - (OUT) Action parameter 34762 * param3 - (OUT) Action parameter 34763 * param4 - (OUT) Action parameter 34764 * param5 - (OUT) Action parameter 34765 ** 34766 * Returns: 34767 * BCM_E_INIT - BCM Unit not initialized 34768 * BCM_E_NOT_FOUND - Entry ID not found 34769 * BCM_E_NOT_FOUND - No matching Action for entry 34770 * BCM_E_PARAM - paramX is NULL 34771 * BCM_E_NONE - Success 34772 */ 34773 34774 int 34775 _bcm_field_action_ports_get(int unit, 34776 bcm_field_entry_t entry, 34777 bcm_field_action_t action, 34778 uint32 *param0, uint32 *param1, 34779 uint32 *param2, uint32 *param3, 34780 uint32 *param4, uint32 *param5) 34781 { 34782 _field_entry_t *f_ent; 34783 _field_action_t *fa; 34784 int rv; 34785 34786 /* Input parameters check. */ 34787 if ((NULL == param0) || (NULL == param1) || 34788 (NULL == param2) || (NULL == param3) || 34789 (NULL == param4) || (NULL == param5)) { 34790 return (BCM_E_PARAM); 34791 } 34792 34793 /* Lock the module. */ 34794 34795 FP_LOCK(unit); 34796 34797 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 34798 if (BCM_FAILURE(rv)) { 34799 FP_UNLOCK(unit); 34800 return (rv); 34801 } 34802 34803 /* Find matching action in the entry */ 34804 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 34805 if (fa->action == action) { 34806 break; 34807 } 34808 } 34809 34810 if (fa == NULL) { 34811 FP_UNLOCK(unit); 34812 LOG_VERBOSE(BSL_LS_BCM_FP, 34813 (BSL_META_U(unit, 34814 "FP(unit %d) Error: action not in entry=%d\n"), 34815 unit, entry)); 34816 return (BCM_E_NOT_FOUND); 34817 } 34818 34819 *param0 = fa->param[0]; 34820 *param1 = fa->param[1]; 34821 *param2 = fa->param[2]; 34822 *param3 = fa->param[3]; 34823 *param4 = fa->param[4]; 34824 *param5 = fa->param[5]; 34825 34826 /* Unlock the module. */ 34827 FP_UNLOCK(unit); 34828 34829 return (rv); 34830 } 34831 34832 /* 34833 * Function: 34834 * _bcm_field_slice_offset_to_tcam_idx 34835 * 34836 * Purpose: 34837 * Given stage and tcam_index, 34838 * calculate slice and entry offset in the 34839 * 34840 * Parameters: 34841 * unit - (IN) BCM device number. 34842 * stage_fc - (IN) Pointer to field entry structure. 34843 * instance - (IN) Instance of the pipe, the slice belongs to. 34844 * slice - (IN) Entry slice number. 34845 * slice_idx - (IN) Entry offset in the slice. 34846 * tcam_idx - (OUT) Entry tcam index. 34847 * Returns: 34848 * BCM_E_XXX 34849 */ 34850 int 34851 _bcm_field_slice_offset_to_tcam_idx(int unit, _field_stage_t *stage_fc, 34852 int instance, int slice, int slice_idx, 34853 int *tcam_idx) 34854 { 34855 _field_slice_t *fs; /* Field slice number. */ 34856 34857 /* Input parameters check. */ 34858 if ((NULL == stage_fc) || (NULL == tcam_idx)) { 34859 return (BCM_E_PARAM); 34860 } 34861 34862 #if defined(BCM_TOMAHAWK_SUPPORT) 34863 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 34864 ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) || 34865 (_BCM_FIELD_STAGE_FLOWTRACKER == stage_fc->stage_id))) { 34866 return _bcm_field_th_slice_offset_to_tcam_idx(unit, stage_fc, instance, 34867 slice, slice_idx, tcam_idx); 34868 } 34869 #endif /* BCM_TOMAHAWK_SUPPORT */ 34870 34871 /* Given stage flags slice number and slice index, calculate tcam index. */ 34872 fs = stage_fc->slices[instance] + slice; 34873 34874 if ((stage_fc->flags & _FP_STAGE_HALF_SLICE) && 34875 (slice_idx >= (fs->entry_count >> 1)) && 34876 ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) || 34877 (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id))) { 34878 if ((soc_feature(unit, 34879 soc_feature_field_half_slice_single_tcam)) 34880 && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 34881 /* Currently Half Slice with Single Tcam in a 34882 * Slice is supported only in IFP Stage in Ranger2Plus .*/ 34883 *tcam_idx = fs->start_tcam_idx + slice_idx; 34884 } else { 34885 /* 34886 * Entry in the second quater of the sw slice 34887 * maps to the hw entry in the first quater 34888 * of the secondary tcam. 34889 */ 34890 *tcam_idx = fs->start_tcam_idx + slice_idx + (fs->entry_count >> 1); 34891 } 34892 } else if ((stage_fc->flags & _FP_STAGE_QUARTER_SLICE) && 34893 (slice_idx >= (fs->entry_count >> 1)) && 34894 ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) || 34895 (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id))) { 34896 if ((soc_feature(unit, 34897 soc_feature_field_quarter_slice_single_tcam)) 34898 && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 34899 /* Currently Quarter Slice with Single Tcam in a 34900 * Slice is supported only in IFP Stage in Td2Plus.*/ 34901 *tcam_idx = fs->start_tcam_idx + slice_idx; 34902 } else { 34903 /* 34904 * Entry in the second quater of the sw slice 34905 * maps to the hw entry in the first quater 34906 * of the secondary tcam. 34907 */ 34908 34909 *tcam_idx = fs->start_tcam_idx + slice_idx + 34910 ((fs->entry_count >> 1 )* 3); 34911 } 34912 } else { 34913 *tcam_idx = fs->start_tcam_idx + slice_idx; 34914 } 34915 return (BCM_E_NONE); 34916 } 34917 34918 /* 34919 * Function: 34920 * _bcm_field_tcam_idx_to_slice_offset 34921 * 34922 * Purpose: 34923 * Given stage and tcam_index, 34924 * calculate slice and entry offset in the 34925 * 34926 * Parameters: 34927 * unit - (IN) BCM device number. 34928 * stage_fc - (IN) Pointer to field entry structure. 34929 * instance - (IN) Instance of the pipe, the slice belongs to. 34930 * tcam_idx - (IN) Entry tcam index. 34931 * slice - (OUT) Entry slice number. 34932 * slice_idx - (OUT) Entry offset in the slice. 34933 * Returns: 34934 * BCM_E_XXX 34935 */ 34936 int 34937 _bcm_field_tcam_idx_to_slice_offset(int unit, _field_stage_t *stage_fc, 34938 int instance, int tcam_idx, 34939 int *slice, int *slice_idx) 34940 { 34941 _field_slice_t *fs; /* Field slice number. */ 34942 int idx; /* Slices iteration index. */ 34943 34944 /* Input parameters check. */ 34945 if ((NULL == stage_fc) || (NULL == slice) || 34946 (NULL == slice_idx) || (tcam_idx < 0)) { 34947 return (BCM_E_PARAM); 34948 } 34949 34950 34951 for (idx = 0; idx < stage_fc->tcam_slices; idx++) { 34952 fs = stage_fc->slices[instance] + idx; 34953 if (tcam_idx < (fs->start_tcam_idx + fs->entry_count)) { 34954 *slice = idx; 34955 *slice_idx = tcam_idx - fs->start_tcam_idx; 34956 break; 34957 } 34958 34959 if (stage_fc->flags & _FP_STAGE_HALF_SLICE) { 34960 if (tcam_idx < (fs->start_tcam_idx + (fs->entry_count << 1))) { 34961 *slice = idx; 34962 *slice_idx = tcam_idx - fs->start_tcam_idx - \ 34963 (fs->entry_count >> 1); 34964 break; 34965 } 34966 } 34967 34968 if (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) { 34969 if (tcam_idx < (fs->start_tcam_idx + (fs->entry_count << 2))) { 34970 *slice = idx; 34971 *slice_idx = tcam_idx - fs->start_tcam_idx - \ 34972 ((fs->entry_count >> 1) * 3); 34973 break; 34974 } 34975 } 34976 } 34977 34978 /* Tcam idx sanity check. */ 34979 if (idx == stage_fc->tcam_slices) { 34980 return (BCM_E_PARAM); 34981 } 34982 return (BCM_E_NONE); 34983 } 34984 34985 /* 34986 * Function: 34987 * _bcm_field_entry_tcam_idx_get 34988 * 34989 * Purpose: 34990 * Get the TCAM index of an entry ID. 34991 * 34992 * Parameters: 34993 * unit - (IN) BCM device number. 34994 * f_ent - (IN) Pointer to field entry structure. 34995 * tcam_idx - (OUT) Entry tcam index. 34996 * 34997 * Returns: 34998 * BCM_E_XXX 34999 */ 35000 int 35001 _bcm_field_entry_tcam_idx_get(int unit,_field_entry_t *f_ent, int *tcam_idx) 35002 { 35003 _field_stage_t *stage_fc; /* Stage field control structure. */ 35004 _field_slice_t *fs; /* Field slice number. */ 35005 int rv; /* Operation return status. */ 35006 35007 /* Input parameters check. */ 35008 if ((NULL == f_ent) || (NULL == tcam_idx)) { 35009 return (BCM_E_PARAM); 35010 } 35011 35012 /* Requested entry structure sanity check. */ 35013 if ((NULL == f_ent->group) || (NULL == f_ent->fs)) { 35014 return (BCM_E_PARAM); 35015 } 35016 35017 /* Get stage control structure. */ 35018 rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc); 35019 BCM_IF_ERROR_RETURN(rv); 35020 35021 /* Given entry and stage flags calculate tcam index. */ 35022 fs = f_ent->fs; 35023 if ((stage_fc->flags & _FP_STAGE_HALF_SLICE) && 35024 ((f_ent->flags & _FP_ENTRY_SECOND_HALF) || 35025 (f_ent->slice_idx >= (fs->entry_count >> 1))) && 35026 ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) || 35027 (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id))) { 35028 if ((soc_feature(unit, 35029 soc_feature_field_half_slice_single_tcam)) 35030 && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 35031 /* Currently half Slice with Single Tcam in a 35032 * Slice is supported only in IFP Stage in Ranger2Plus.*/ 35033 *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx; 35034 } else { 35035 /* 35036 * Entry in the second quater of the sw slice 35037 * maps to the hw entry in the first quater 35038 * of the secondary tcam. 35039 */ 35040 *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx + 35041 (fs->entry_count >> 1); 35042 } 35043 } else if ((stage_fc->flags & _FP_STAGE_QUARTER_SLICE) && 35044 (f_ent->slice_idx >= (fs->entry_count >> 1))) { 35045 if ((soc_feature(unit, 35046 soc_feature_field_quarter_slice_single_tcam)) 35047 && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 35048 /* Currently Quarter Slice with Single Tcam in a 35049 * Slice is supported only in IFP Stage in Td2Plus.*/ 35050 *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx; 35051 } else { 35052 *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx + 35053 ((fs->entry_count >> 1) * 3); 35054 } 35055 } else { 35056 *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx; 35057 } 35058 return (BCM_E_NONE); 35059 } 35060 35061 35062 /* 35063 * Function: 35064 * _field_action_delete 35065 * Purpose: 35066 * Delete field action from a field entry. 35067 * Parameters: 35068 * unit - (IN) BCM device number 35069 * entry - (IN) Entry ID 35070 * action - (IN) Action to remove (bcmFieldActionXXX) 35071 * param0 - (IN) Action parameter (use 0 if not required) 35072 * param1 - (IN) Action parameter (use 0 if not required) 35073 * Returns: 35074 * BCM_E_XXX 35075 * Notes: 35076 */ 35077 int 35078 _field_action_delete(int unit, bcm_field_entry_t entry, 35079 bcm_field_action_t action, 35080 uint32 param0, uint32 param1) 35081 { 35082 _field_control_t *fc; /* Field control structure. */ 35083 _field_entry_t *f_ent; 35084 _field_action_t *fa; 35085 _field_action_t *fa_prev = NULL; 35086 int rv; /* Operation return status. */ 35087 #if defined(BCM_TRIDENT_SUPPORT) 35088 uint8 idx; /* Entry array action index. */ 35089 uint32 entry_flags; /* Entry flags */ 35090 #endif 35091 _field_action_t *fa_cnt = NULL; 35092 int8 nat_action_count = 0; 35093 35094 #if defined(BCM_TOMAHAWK_SUPPORT) 35095 if (soc_feature(unit, soc_feature_field_preselector_support) && 35096 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 35097 return _bcm_field_presel_action_delete 35098 (unit, entry, action, param0, param1); 35099 } 35100 #endif /* BCM_TOMAHAWK_SUPPORT */ 35101 35102 /* Get field entry descriptor. */ 35103 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 35104 if (BCM_FAILURE(rv)) { 35105 return (rv); 35106 } 35107 35108 #if defined(BCM_TOMAHAWK_SUPPORT) 35109 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 35110 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 35111 rv = _bcm_field_th_class_action_delete(unit, entry, action); 35112 return (rv); 35113 } 35114 #endif /* BCM_TOMAHAWK_SUPPORT */ 35115 35116 /* Special treatment for pre-historic actions. */ 35117 switch (action) { 35118 case bcmFieldActionColorIndependent: 35119 35120 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 35121 35122 if(fc->flags & _FP_COLOR_INDEPENDENT) { 35123 f_ent->flags |= _FP_ENTRY_COLOR_INDEPENDENT; 35124 } else { 35125 f_ent->flags &= ~_FP_ENTRY_COLOR_INDEPENDENT; 35126 } 35127 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 35128 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 35129 } 35130 f_ent->flags |= _FP_ENTRY_DIRTY; 35131 return (BCM_E_NONE); 35132 default: 35133 break; 35134 } 35135 35136 35137 /* Find the action in the entry */ 35138 fa = f_ent->actions; /* start at head */ 35139 35140 while (fa != NULL) { 35141 if (fa->action != action) { 35142 fa_prev = fa; 35143 fa = fa->next; 35144 continue; 35145 } 35146 35147 /* Some actions might be applied multiple times.*/ 35148 if (((action == bcmFieldActionMirrorIngress) || 35149 (action == bcmFieldActionMirrorEgress)) && 35150 (((uint32)_FP_INVALID_INDEX != param0) && 35151 ((uint32)_FP_INVALID_INDEX != param1))) { 35152 if ((fa->param[0] != param0) || (fa->param[1] != param1)) { 35153 fa_prev = fa; 35154 fa = fa->next; 35155 continue; 35156 } 35157 } 35158 #if defined(BCM_TRIDENT3_SUPPORT) 35159 if (action == bcmFieldActionVlanActions) { 35160 if (f_ent->vlan_action_set) { 35161 sal_free(f_ent->vlan_action_set); 35162 f_ent->vlan_action_set = NULL; 35163 } 35164 } 35165 #endif /* BCM_TRIDENT3_SUPPORT */ 35166 break; 35167 } 35168 35169 #if defined(BCM_TRIDENT_SUPPORT) 35170 if (SOC_IS_TD_TT(unit)) { 35171 if ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 35172 (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) || 35173 (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 35174 if (NULL == fa) { 35175 if (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 35176 entry_flags = (_FP_ENTRY_PRIMARY | _FP_ENTRY_SECOND_HALF); 35177 } else { 35178 entry_flags = _FP_ENTRY_SECONDARY; 35179 } 35180 35181 rv = _bcm_field_entry_flags_to_tcam_part(unit, entry_flags, 35182 f_ent->group, 35183 &idx); 35184 35185 BCM_IF_ERROR_RETURN(rv); 35186 /* Find the action in the entry */ 35187 fa = f_ent[idx].actions; /* start at head */ 35188 fa_prev = NULL; 35189 while (fa != NULL) { 35190 if (fa->action != action) { 35191 fa_prev = fa; 35192 fa = fa->next; 35193 continue; 35194 } 35195 f_ent = &f_ent[idx]; 35196 break; 35197 } 35198 } 35199 } 35200 } 35201 #endif 35202 35203 if (NULL == fa) { 35204 return (BCM_E_NOT_FOUND); 35205 } 35206 35207 #if defined(BCM_TRIDENT2_SUPPORT) 35208 BCM_IF_ERROR_RETURN(_bcm_field_action_stat_flag_update 35209 (unit, f_ent, fa, FALSE)); 35210 #endif 35211 /* Nat Actions Conflict with Oam Actions */ 35212 if (soc_feature(unit, soc_feature_fp_based_oam)) { 35213 if ((fa->action == bcmFieldActionNatCancel) 35214 || (fa->action == bcmFieldActionNatEgressOverride) 35215 || (fa->action == bcmFieldActionNat)) { 35216 fa_cnt = f_ent->actions; /* start at head */ 35217 while (fa_cnt != NULL) { 35218 if ((fa_cnt->action == bcmFieldActionNatCancel) 35219 || (fa_cnt->action == bcmFieldActionNatEgressOverride) 35220 || (fa_cnt->action == bcmFieldActionNat)) { 35221 if (fa_cnt->flags & _FP_ACTION_VALID) { 35222 nat_action_count++; 35223 } 35224 } 35225 fa_cnt = fa_cnt->next; 35226 } 35227 if (nat_action_count == 1) { 35228 f_ent->flags &= ~_FP_ENTRY_OAM_STAT_NOT_ALLOWED; 35229 } 35230 } 35231 } 35232 35233 /* If entry is installed mark action as invalid. 35234 * Invalid actions will be removed during entry remove/reinstall. 35235 */ 35236 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 35237 fa->flags &= ~_FP_ACTION_VALID; 35238 fa->flags |= _FP_ACTION_MODIFY; 35239 /* 35240 * Do not set action only dirty flag if qualifier parameter has 35241 * been modified for this entry. 35242 */ 35243 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 35244 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 35245 } 35246 f_ent->flags |= _FP_ENTRY_DIRTY; 35247 return (BCM_E_NONE); 35248 } 35249 35250 if (fa_prev != NULL) { 35251 fa_prev->next = fa->next; 35252 } else { /* matched head of list */ 35253 f_ent->actions = fa->next; 35254 } 35255 35256 /* okay to free action */ 35257 if (NULL != (fa->egress_pbmp)) { 35258 sal_free(fa->egress_pbmp); 35259 } 35260 sal_free(fa); 35261 fa = NULL; 35262 35263 /* 35264 * Do not set action only dirty flag if qualifier parameter has 35265 * been modified for this entry. 35266 */ 35267 if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) { 35268 f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY; 35269 } 35270 f_ent->flags |= _FP_ENTRY_DIRTY; 35271 return (BCM_E_NONE); 35272 } 35273 #if defined(BCM_TOMAHAWK_SUPPORT) 35274 /* 35275 * Function: 35276 * _bcm_field_34bit_counter_update 35277 * Description: 35278 * Service routine used to update 64-bit software accumulated 34 bit counters. 35279 * Parameters: 35280 * unit - (IN) BCM device number. 35281 * new_val - (IN) New hw counter value from. 35282 * result - (IN/OUT) Operation result. 35283 * Returns: 35284 * BCM_E_XXX 35285 * Notes: 35286 * This is for Tomahawk Devices 35287 */ 35288 int 35289 _bcm_field_34bit_counter_update(int unit, uint32 *new_val, 35290 _field_counter64_collect_t *result) 35291 { 35292 uint64 hw_val; 35293 uint64 diff64; 35294 35295 /* Input parameters check. */ 35296 if ((NULL == new_val) || (NULL == result)) { 35297 return (BCM_E_PARAM); 35298 } 35299 35300 /* Compose H/W counter value. */ 35301 COMPILER_64_SET(hw_val, new_val[1], new_val[0]); 35302 35303 if (COMPILER_64_LE(result->last_hw_value, hw_val)) { 35304 /* diff = hw_val - result->last_hw_value */ 35305 COMPILER_64_ZERO(diff64); 35306 COMPILER_64_OR(diff64, hw_val); 35307 COMPILER_64_SUB_64(diff64, result->last_hw_value); 35308 } else { 35309 /* 35310 * diff = 0x3ffffffff - (result->last_hw_value - hw_val) + 1 35311 * = 0x400000000 - result->last_hw_value + hw_val 35312 */ 35313 COMPILER_64_SET(diff64, 0x4, 0); 35314 COMPILER_64_SUB_64(diff64, result->last_hw_value); 35315 COMPILER_64_ADD_64(diff64, hw_val); 35316 } 35317 35318 COMPILER_64_ADD_64(result->accumulated_counter, diff64); 35319 35320 COMPILER_64_ZERO(result->last_hw_value); 35321 COMPILER_64_OR(result->last_hw_value, hw_val); 35322 35323 return (BCM_E_NONE); 35324 } 35325 35326 /* 35327 * Function: 35328 * _bcm_field_26bit_counter_update 35329 * Description: 35330 * Service routine used to update 64-bit software accumulated 26 bit counter. 35331 * Parameters: 35332 * unit - (IN) BCM device number. 35333 * new_val - (IN) New hw counter value from. 35334 * result - (IN/OUT) Operation result. 35335 * Returns: 35336 * BCM_E_XXX 35337 */ 35338 int 35339 _bcm_field_26bit_counter_update(int unit, uint32 *new_val, 35340 _field_counter32_collect_t *result) 35341 { 35342 uint32 diff; 35343 uint64 diff64; 35344 35345 /* Input parameters check. */ 35346 if ((NULL == new_val) || (NULL == result)) { 35347 return (BCM_E_PARAM); 35348 } 35349 35350 if (result->last_hw_value <= new_val[0]) { 35351 diff = new_val[0] - result->last_hw_value; 35352 } else { 35353 diff = ((1 << 26) - 1) - (result->last_hw_value - new_val[0]) + 1; 35354 } 35355 35356 COMPILER_64_SET(diff64, 0, diff); 35357 COMPILER_64_ADD_64(result->accumulated_counter, diff64); 35358 35359 result->last_hw_value = new_val[0]; 35360 35361 return (BCM_E_NONE); 35362 } 35363 #endif /* BCM_TOMAHAWK_SUPPORT */ 35364 35365 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 35366 35367 /* 35368 * Function: 35369 * _bcm_field_36bit_counter_update 35370 * Description: 35371 * Service routine used to update 64-bit software accumulated 36 bit counters. 35372 * Parameters: 35373 * unit - (IN) BCM device number. 35374 * new_val - (IN) New hw counter value from. 35375 * result - (IN/OUT) Operation result. 35376 * Returns: 35377 * BCM_E_XXX 35378 * Notes: 35379 * This is for Bradley 35380 */ 35381 int 35382 _bcm_field_36bit_counter_update(int unit, uint32 *new_val, 35383 _field_counter64_collect_t *result) 35384 { 35385 uint64 hw_val; 35386 uint64 diff64; 35387 35388 /* Input parameters check. */ 35389 if ((NULL == new_val) || (NULL == result)) { 35390 return (BCM_E_PARAM); 35391 } 35392 35393 /* Compose H/W counter value. */ 35394 COMPILER_64_SET(hw_val, new_val[1], new_val[0]); 35395 35396 if (COMPILER_64_LE(result->last_hw_value, hw_val)) { 35397 /* diff = hw_val - result->last_hw_value */ 35398 COMPILER_64_ZERO(diff64); 35399 COMPILER_64_OR(diff64, hw_val); 35400 COMPILER_64_SUB_64(diff64, result->last_hw_value); 35401 } else { 35402 /* 35403 * diff = 0xfffffffff - (result->last_hw_value - hw_val) + 1 35404 * = 0x1000000000 - result->last_hw_value + hw_val 35405 */ 35406 COMPILER_64_SET(diff64, 0x10, 0); 35407 COMPILER_64_SUB_64(diff64, result->last_hw_value); 35408 COMPILER_64_ADD_64(diff64, hw_val); 35409 } 35410 35411 COMPILER_64_ADD_64(result->accumulated_counter, diff64); 35412 35413 COMPILER_64_ZERO(result->last_hw_value); 35414 COMPILER_64_OR(result->last_hw_value, hw_val); 35415 35416 return (BCM_E_NONE); 35417 } 35418 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH3_SUPPORT */ 35419 /* 35420 * Function: 35421 * _bcm_field_32bit_counter_update 35422 * Description: 35423 * Service routine used to update 64-bit software accumulated 32 bit counter. 35424 * Parameters: 35425 * unit - (IN) BCM device number. 35426 * new_val - (IN) New hw counter value from. 35427 * result - (IN/OUT) Operation result. 35428 * Returns: 35429 * BCM_E_XXX 35430 */ 35431 int 35432 _bcm_field_32bit_counter_update(int unit, uint32 *new_val, 35433 _field_counter32_collect_t *result) 35434 { 35435 uint32 diff; 35436 uint64 diff64; 35437 35438 /* Input parameters check. */ 35439 if ((NULL == new_val) || (NULL == result)) { 35440 return (BCM_E_PARAM); 35441 } 35442 35443 if (result->last_hw_value <= new_val[0]) { 35444 diff = new_val[0] - result->last_hw_value; 35445 } else { 35446 diff = ((0xFFFFFFFFL) - result->last_hw_value) + new_val[0] + 1; 35447 } 35448 35449 COMPILER_64_SET(diff64, 0, diff); 35450 COMPILER_64_ADD_64(result->accumulated_counter, diff64); 35451 35452 result->last_hw_value = new_val[0]; 35453 35454 return (BCM_E_NONE); 35455 } 35456 35457 /* 35458 * Function: 35459 * _bcm_field_29bit_counter_update 35460 * Description: 35461 * Service routine used to update 64-bit software accumulated 29 bit counter. 35462 * Parameters: 35463 * unit - (IN) BCM device number. 35464 * new_val - (IN) New hw counter value from. 35465 * result - (IN/OUT) Operation result. 35466 * Returns: 35467 * BCM_E_XXX 35468 */ 35469 int 35470 _bcm_field_29bit_counter_update(int unit, uint32 *new_val, 35471 _field_counter32_collect_t *result) 35472 { 35473 uint32 diff; 35474 uint64 diff64; 35475 35476 /* Input parameters check. */ 35477 if ((NULL == new_val) || (NULL == result)) { 35478 return (BCM_E_PARAM); 35479 } 35480 35481 if (result->last_hw_value <= new_val[0]) { 35482 diff = new_val[0] - result->last_hw_value; 35483 } else { 35484 diff = ((1 << 29) - 1) - (result->last_hw_value - new_val[0]) + 1; 35485 } 35486 35487 COMPILER_64_SET(diff64, 0, diff); 35488 COMPILER_64_ADD_64(result->accumulated_counter, diff64); 35489 35490 result->last_hw_value = new_val[0]; 35491 35492 return (BCM_E_NONE); 35493 } 35494 #if defined(BCM_TRX_SUPPORT) 35495 /* 35496 * Function: 35497 * _bcm_field_35bit_counter_update 35498 * Description: 35499 * Service routine used to update 64-bit software accumulated 35 bit counters. 35500 * Parameters: 35501 * unit - (IN) BCM device number. 35502 * new_val - (IN) New hw counter value from. 35503 * result - (IN/OUT) Operation result. 35504 * Returns: 35505 * BCM_E_XXX 35506 * Notes: 35507 * This is for BYTE_COUNTER field 35508 */ 35509 int 35510 _bcm_field_35bit_counter_update(int unit, uint32 *new_val, 35511 _field_counter64_collect_t *result) 35512 { 35513 uint64 hw_val; 35514 uint64 diff64; 35515 35516 /* Input parameters check. */ 35517 if ((NULL == new_val) || (NULL == result)) { 35518 return (BCM_E_PARAM); 35519 } 35520 35521 /* Compose H/W counter value. */ 35522 COMPILER_64_SET(hw_val, new_val[1], new_val[0]); 35523 35524 if (COMPILER_64_LE(result->last_hw_value, hw_val)) { 35525 /* diff = hw_val - result->last_hw_value */ 35526 COMPILER_64_ZERO(diff64); 35527 COMPILER_64_OR(diff64, hw_val); 35528 COMPILER_64_SUB_64(diff64, result->last_hw_value); 35529 } else { 35530 /* 35531 * diff = 0x7ffffffff - (result->last_hw_value - hw_val) + 1 35532 * = 0x800000000 - result->last_hw_value + hw_val 35533 */ 35534 COMPILER_64_SET(diff64, 0x8, 0); 35535 COMPILER_64_SUB_64(diff64, result->last_hw_value); 35536 COMPILER_64_ADD_64(diff64, hw_val); 35537 } 35538 35539 COMPILER_64_ADD_64(result->accumulated_counter, diff64); 35540 35541 COMPILER_64_ZERO(result->last_hw_value); 35542 COMPILER_64_OR(result->last_hw_value, hw_val); 35543 35544 return (BCM_E_NONE); 35545 } 35546 #endif /* BCM_TRX_SUPPORT */ 35547 35548 #ifdef BCM_TRIDENT_SUPPORT 35549 /* 35550 * Function: 35551 * _bcm_field_37bit_counter_update 35552 * Description: 35553 * Service routine used to update 64-bit software accumulated 37 bit counters. 35554 * Parameters: 35555 * unit - (IN) BCM device number. 35556 * new_val - (IN) New hw counter value from. 35557 * result - (IN/OUT) Operation result. 35558 * Returns: 35559 * BCM_E_XXX 35560 * Notes: 35561 * This is for Trident2 35562 */ 35563 int 35564 _bcm_field_37bit_counter_update(int unit, uint32 *new_val, 35565 _field_counter64_collect_t *result) 35566 { 35567 uint64 hw_val; 35568 uint64 diff64; 35569 35570 /* Input parameters check. */ 35571 if ((NULL == new_val) || (NULL == result)) { 35572 return (BCM_E_PARAM); 35573 } 35574 35575 /* Compose H/W counter value. */ 35576 COMPILER_64_SET(hw_val, new_val[1], new_val[0]); 35577 35578 if (COMPILER_64_LE(result->last_hw_value, hw_val)) { 35579 /* diff = hw_val - result->last_hw_value */ 35580 COMPILER_64_ZERO(diff64); 35581 COMPILER_64_OR(diff64, hw_val); 35582 COMPILER_64_SUB_64(diff64, result->last_hw_value); 35583 } else { 35584 /* 35585 * diff = 0x1FFFFFFFFF - (result->last_hw_value - hw_val) + 1 35586 * = 0x2000000000 - result->last_hw_value + hw_val 35587 */ 35588 COMPILER_64_SET(diff64, 0x20, 0); 35589 COMPILER_64_SUB_64(diff64, result->last_hw_value); 35590 COMPILER_64_ADD_64(diff64, hw_val); 35591 } 35592 35593 COMPILER_64_ADD_64(result->accumulated_counter, diff64); 35594 35595 COMPILER_64_ZERO(result->last_hw_value); 35596 COMPILER_64_OR(result->last_hw_value, hw_val); 35597 35598 return (BCM_E_NONE); 35599 } 35600 #endif /* BCM_TRIDENT_SUPPORT */ 35601 35602 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 35603 /* 35604 * Function: 35605 * _bcm_field_30bit_counter_update 35606 * Description: 35607 * Service routine used to update 64-bit software accumulated 30 bit counter. 35608 * Parameters: 35609 * unit - (IN) BCM device number. 35610 * new_val - (IN) New hw counter value from. 35611 * result - (IN/OUT) Operation result. 35612 * Returns: 35613 * BCM_E_XXX 35614 */ 35615 int 35616 _bcm_field_30bit_counter_update(int unit, uint32 *new_val, 35617 _field_counter32_collect_t *result) 35618 { 35619 uint32 diff; 35620 uint64 diff64; 35621 35622 /* Input parameters check. */ 35623 if ((NULL == new_val) || (NULL == result)) { 35624 return (BCM_E_PARAM); 35625 } 35626 35627 if (result->last_hw_value <= new_val[0]) { 35628 diff = new_val[0] - result->last_hw_value; 35629 } else { 35630 diff = ((1 << 30) - 1) - (result->last_hw_value - new_val[0]) + 1; 35631 } 35632 35633 COMPILER_64_SET(diff64, 0, diff); 35634 COMPILER_64_ADD_64(result->accumulated_counter, diff64); 35635 35636 result->last_hw_value = new_val[0]; 35637 35638 return (BCM_E_NONE); 35639 } 35640 #endif /* (BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) */ 35641 35642 /* 35643 * Function: 35644 * _bcm_field_sw_counter_update 35645 * Description: 35646 * Service routine used to update 64-bit software accumulated counters. 35647 * based on hw memory block. 35648 * Parameters: 35649 * unit - (IN) BCM device number. 35650 * stage_fc - (IN/OUT) Stage field control structure. 35651 * mem - (IN) Counters memory. 35652 * idx_min - (IN) First counter index in the buffer. 35653 * idx_max - (IN) Last counter index in the buffer. 35654 * buf - (IN) Counters buffer. 35655 * flags - (IN) Device counters flags. 35656 * Returns: 35657 * BCM_E_XXX 35658 */ 35659 int 35660 _bcm_field_sw_counter_update(int unit, _field_stage_t *stage_fc, soc_mem_t mem, 35661 int idx_min, int idx_max, char *buf, int flags) 35662 { 35663 _field_control_t *fc; /* Field control structure. */ 35664 uint32 *entry_p; /* HW entry pointer. */ 35665 int buf_offset; /* Offset into counters buffer. */ 35666 int idx; /* Iteration index. */ 35667 int rv; /* Operartion return status. */ 35668 35669 35670 /* Get field control structure. */ 35671 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 35672 35673 for (idx = idx_min, buf_offset = 0; idx <= idx_max; idx++, buf_offset++) { 35674 /* Read counter value from the first memory. */ 35675 entry_p = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 35676 buf, buf_offset); 35677 35678 /* Process accumulated counter value. */ 35679 if (flags & _FIELD_FIRST_MEMORY_COUNTERS) { 35680 rv = fc->functions.fp_counter_get(unit, stage_fc, mem, 35681 entry_p, INVALIDm, 35682 NULL, idx, NULL, NULL); 35683 } else { 35684 rv = fc->functions.fp_counter_get(unit, stage_fc, INVALIDm, 35685 NULL, mem, entry_p, idx, 35686 NULL, NULL); 35687 } 35688 if (BCM_FAILURE(rv)) { 35689 break; 35690 } 35691 } 35692 return (BCM_E_NONE); 35693 } 35694 35695 /* 35696 * Function: 35697 * _field_mem_counters_read 35698 * Description: 35699 * Service routine used to coolect 64-bit software accumulated counters. 35700 * for a specific stage. 35701 * Parameters: 35702 * unit - (IN) BCM device number. 35703 * stage_fc - (IN/OUT) Stage field control structure. 35704 * mem - (IN) Counters memory. 35705 * Returns: 35706 * BCM_E_XXX 35707 */ 35708 35709 STATIC int 35710 _field_mem_counters_read(int unit, _field_stage_t *stage_fc, 35711 soc_mem_t mem, int flags) 35712 { 35713 int buf_end_idx; /* Buffer end index. */ 35714 int alloc_size; /* DMA buffer size. */ 35715 int max_idx; /* Counter memory index max. */ 35716 int min_idx; /* Counter memory index min. */ 35717 char *buf; /* Buffer to read the table. */ 35718 int idx = 0; /* Table iteration index. */ 35719 int rv = BCM_E_NONE; /* Operation return value. */ 35720 int slice_index = 0; /* Slice index */ 35721 int slice_size = 0; /* Size of each slice */ 35722 int entry_ratio = 0; /* entries per slice */ 35723 35724 /* Input parameters check. */ 35725 if (NULL == stage_fc) { 35726 return (BCM_E_PARAM); 35727 } 35728 35729 /* Make sure memory is valid */ 35730 if (INVALIDm == mem) { 35731 return (BCM_E_NONE); 35732 } 35733 35734 /* Get table boundaries. */ 35735 min_idx = soc_mem_index_min(unit, mem); 35736 max_idx = soc_mem_index_max(unit, mem); 35737 35738 /* Dma part of the table & update software counters. */ 35739 if ((soc_feature(unit, 35740 soc_feature_field_quarter_slice_single_tcam) || 35741 soc_feature(unit, 35742 soc_feature_field_half_slice_single_tcam)) 35743 && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 35744 entry_ratio = (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) ? 4: 35745 ((stage_fc->flags & _FP_STAGE_HALF_SLICE) ? 2 : 1); 35746 idx = min_idx; 35747 for (slice_index = 0; 35748 slice_index < stage_fc->tcam_slices; slice_index++) { 35749 slice_size = stage_fc->slices[_FP_DEF_INST][slice_index].entry_count; 35750 35751 /* Allocate memory buffer. */ 35752 alloc_size = ((slice_size) * sizeof(fp_counter_table_entry_t)); 35753 buf = soc_cm_salloc(unit, alloc_size, "fp_64_bit_counter"); 35754 if (buf == NULL) { 35755 return (BCM_E_MEMORY); 35756 } 35757 buf_end_idx = idx + (slice_size - 1); 35758 35759 /* Dma range of entries in counter table. */ 35760 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, idx, 35761 buf_end_idx, buf); 35762 if (BCM_FAILURE(rv)) { 35763 break; 35764 } 35765 35766 rv = _bcm_field_sw_counter_update(unit, stage_fc, mem, idx, 35767 buf_end_idx, buf, flags); 35768 if (BCM_FAILURE(rv)) { 35769 break; 35770 } 35771 35772 idx += stage_fc->slices[_FP_DEF_INST][slice_index].entry_count * entry_ratio; 35773 soc_cm_sfree(unit, buf); 35774 buf = NULL; 35775 } 35776 } else { 35777 /* Allocate memory buffer. */ 35778 alloc_size = (_FP_64_COUNTER_BUCKET * sizeof(fp_counter_table_entry_t)); 35779 buf = soc_cm_salloc(unit, alloc_size, "fp_64_bit_counter"); 35780 if (buf == NULL) { 35781 return (BCM_E_MEMORY); 35782 } 35783 for (idx = min_idx; idx <= max_idx; idx += _FP_64_COUNTER_BUCKET) { 35784 buf_end_idx = MIN(max_idx, (idx + _FP_64_COUNTER_BUCKET - 1)); 35785 if (soc_feature(unit, soc_feature_field_stage_quarter_slice) && 35786 (SOC_IS_TRIUMPH3(unit))) { 35787 /* Do not access h/w for tcam index mapping to the holes */ 35788 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 35789 buf_end_idx = MIN(max_idx, (idx + 128 - 1)); 35790 } 35791 } 35792 35793 /* Dma range of entries in counter table. */ 35794 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, idx, 35795 buf_end_idx, buf); 35796 if (BCM_FAILURE(rv)) { 35797 break; 35798 } 35799 35800 rv = _bcm_field_sw_counter_update(unit, stage_fc, mem, idx, 35801 buf_end_idx, buf, flags); 35802 if (BCM_FAILURE(rv)) { 35803 break; 35804 } 35805 } 35806 soc_cm_sfree(unit, buf); 35807 } 35808 return (rv); 35809 } 35810 35811 35812 /* 35813 * Function: 35814 * _field_stage_external_counters_collect 35815 * Description: 35816 * Service routine used to coolect 64-bit software accumulated counters. 35817 * For the External-FP (Triumph). 35818 * Parameters: 35819 * unit - (IN) BCM device number. 35820 * fc - (IN) Field control structure. 35821 * stage_fc - (IN/OUT) Stage field control structure. 35822 * Returns: 35823 * BCM_E_XXX 35824 */ 35825 35826 STATIC int 35827 _field_stage_external_counters_collect (int unit, _field_control_t *fc, 35828 _field_stage_t *stage_fc) 35829 { 35830 if ((stage_fc->_field_x32_counters == NULL) 35831 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 35832 && (stage_fc->_field_x64_counters == NULL) 35833 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */ 35834 ) 35835 { 35836 return (BCM_E_UNAVAIL); 35837 } 35838 35839 #ifdef BCM_TRIUMPH_SUPPORT 35840 BCM_IF_ERROR_RETURN 35841 (_bcm_field_tr_external_counters_collect(unit, stage_fc)); 35842 #endif /* BCM_TRIUMPH_SUPPORT */ 35843 35844 return (BCM_E_NONE); 35845 } 35846 /* 35847 * Function: 35848 * _field_stage_counters_collect 35849 * Description: 35850 * Service routine used to coolect 64-bit software accumulated counters. 35851 * for a specific stage. 35852 * Parameters: 35853 * unit - (IN) BCM device number. 35854 * fc - (IN) Field control structure. 35855 * stage_fc - (IN/OUT) Stage field control structure. 35856 * Returns: 35857 * BCM_E_XXX 35858 * Notes: 35859 * None. 35860 */ 35861 35862 STATIC int 35863 _field_stage_counters_collect (int unit, _field_control_t *fc, 35864 _field_stage_t *stage_fc) 35865 { 35866 soc_mem_t counter_x_mem; /* First counters memory. */ 35867 soc_mem_t counter_y_mem; /* Second counters memory */ 35868 /* for dual pipeline devices.*/ 35869 35870 /* Input parameters check. */ 35871 if (NULL == stage_fc) { 35872 return (BCM_E_PARAM); 35873 } 35874 35875 #if defined(BCM_TOMAHAWK_SUPPORT) 35876 if (stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) { 35877 return BCM_E_NONE; 35878 } 35879 #endif 35880 35881 /* Check if counters are available at this stage. */ 35882 if ((stage_fc->_field_x32_counters == NULL) 35883 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 35884 && (stage_fc->_field_x64_counters == NULL) 35885 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */ 35886 ) 35887 { 35888 return (BCM_E_UNAVAIL); 35889 } 35890 35891 /* Get counters memory for the stage. */ 35892 BCM_IF_ERROR_RETURN(_field_counter_mem_get(unit, stage_fc, 35893 &counter_x_mem, &counter_y_mem)); 35894 35895 /* If stage doesn't have counters - we are done. */ 35896 if ((INVALIDm == counter_x_mem) && (INVALIDm == counter_y_mem)) { 35897 return (BCM_E_NONE); 35898 } 35899 35900 if (INVALIDm != counter_x_mem) { 35901 BCM_IF_ERROR_RETURN 35902 (_field_mem_counters_read(unit, stage_fc, counter_x_mem, 35903 _FIELD_FIRST_MEMORY_COUNTERS)); 35904 } 35905 35906 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 35907 if (INVALIDm != counter_y_mem) { 35908 BCM_IF_ERROR_RETURN 35909 (_field_mem_counters_read(unit, stage_fc, counter_y_mem, 35910 _FIELD_SECOND_MEMORY_COUNTERS)); 35911 } 35912 #endif /* BCM_BRADLEY_SUPPORT || BCM_SCORPION_SUPPORT */ 35913 return (BCM_E_NONE); 35914 } 35915 35916 35917 /* 35918 * Function: 35919 * _bcm_esw_fp_counters_collect 35920 * Description: 35921 * Callback routine executed each counter cycle to add up the 35922 * 64-bit software accumulated counter values. 35923 * Parameters: 35924 * unit - (IN) BCM device number. 35925 * Returns: 35926 * BCM_E_XXX 35927 * Notes: 35928 * None. 35929 */ 35930 35931 void 35932 _bcm_esw_fp_counters_collect(int unit) 35933 { 35934 _field_control_t *fc = NULL; /* Field control structure. */ 35935 _field_stage_t *stage_fc; /* Stage field control iterator. */ 35936 35937 35938 FP_LOCK(unit); 35939 if (BCM_FAILURE(_field_control_get(unit, &fc))) { 35940 FP_UNLOCK(unit); 35941 return; 35942 } 35943 35944 /* Collect counters from each fp pipeline stage. */ 35945 stage_fc = fc->stages; 35946 while (NULL != stage_fc) { 35947 if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 35948 _field_stage_external_counters_collect(unit, fc, stage_fc); 35949 } else { 35950 _field_stage_counters_collect(unit, fc, stage_fc); 35951 } 35952 stage_fc = stage_fc->next; 35953 } 35954 35955 FP_UNLOCK(unit); 35956 return; 35957 } 35958 35959 /* Function : 35960 * _field_qualify_IpProtocolCommon_get 35961 * Description : 35962 * Get qualifier common L3 protocol ID 35963 * Parameters : 35964 * unit (IN) BCM device number 35965 * entry (IN) Field entry to qualify 35966 * qual_id (IN) Field qualifier id. 35967 * protocol (OUT) Protocol name to qualify 35968 * Returns: 35969 * BCM_E_XXX 35970 */ 35971 int 35972 _field_qualify_IpProtocolCommon_get(int unit, 35973 bcm_field_entry_t entry, 35974 bcm_field_qualify_t qual_id, 35975 bcm_field_IpProtocolCommon_t *protocol) 35976 { 35977 uint8 data; /* HW encoded data. */ 35978 uint8 mask; /* HW encoded mask. */ 35979 int rv; /* Operation return status. */ 35980 35981 if (NULL == protocol) { 35982 return (BCM_E_PARAM); 35983 } 35984 35985 /* Read qualifier match value and mask. */ 35986 rv = _bcm_field_entry_qualifier_uint8_get(unit, entry, 35987 qual_id, &data, &mask); 35988 BCM_IF_ERROR_RETURN(rv); 35989 35990 if ((0 == data) && (0x7 == mask)) { 35991 *protocol = bcmFieldIpProtocolCommonTcp; 35992 } else if ((1 == data) && (0x7 == mask)) { 35993 *protocol = bcmFieldIpProtocolCommonUdp; 35994 } else if ((2 == data) && (0x7 == mask)) { 35995 *protocol = bcmFieldIpProtocolCommonIgmp; 35996 } else if ((3 == data) && (0x7 == mask)) { 35997 *protocol = bcmFieldIpProtocolCommonIcmp; 35998 } else if ((4 == data) && (0x7 == mask)) { 35999 *protocol = bcmFieldIpProtocolCommonIp6Icmp; 36000 } else if ((5 == data) && (0x7 == mask)) { 36001 *protocol = bcmFieldIpProtocolCommonIp6HopByHop; 36002 } else if ((6 == data) && (0x7 == mask)) { 36003 *protocol = bcmFieldIpProtocolCommonIpInIp; 36004 } else if ((0 == data) && (0x6 == mask)) { 36005 *protocol = bcmFieldIpProtocolCommonTcpUdp; 36006 } else { 36007 return (BCM_E_INTERNAL); 36008 } 36009 return (BCM_E_NONE); 36010 } 36011 36012 /* Function : 36013 * _field_qualify_IpProtocolCommon 36014 * Description : 36015 * Qualify common L3 protocol ID 36016 * Parameters : 36017 * unit (IN) BCM device number 36018 * entry (IN) Field entry to qualify 36019 * qual_id (IN) Field qualifier id. 36020 * protocol (IN) Protocol name to qualify 36021 * Returns: 36022 * BCM_E_XXX 36023 */ 36024 int 36025 _field_qualify_IpProtocolCommon(int unit, bcm_field_entry_t entry, 36026 bcm_field_qualify_t qual_id, 36027 bcm_field_IpProtocolCommon_t protocol) 36028 { 36029 uint32 data; 36030 uint32 mask; 36031 36032 if (protocol >= bcmFieldIpProtocolCommonCount) { 36033 return (BCM_E_PARAM); 36034 } 36035 36036 switch (protocol) { 36037 case bcmFieldIpProtocolCommonTcp: 36038 data = 0x00; 36039 mask = 0x07; 36040 break; 36041 case bcmFieldIpProtocolCommonUdp: 36042 data = 0x01; 36043 mask = 0x07; 36044 break; 36045 case bcmFieldIpProtocolCommonIgmp: 36046 data = 0x02; 36047 mask = 0x07; 36048 break; 36049 case bcmFieldIpProtocolCommonIcmp: 36050 data = 0x03; 36051 mask = 0x07; 36052 break; 36053 case bcmFieldIpProtocolCommonIp6Icmp: 36054 data = 0x04; 36055 mask = 0x07; 36056 break; 36057 case bcmFieldIpProtocolCommonIp6HopByHop: 36058 /* TRX devices do not use extension headers 36059 * for packet ip protocol is determination. 36060 * Please use bcm_esw_field_qualify_ExtensionHeaderType */ 36061 if (SOC_IS_TRX(unit)) { 36062 return (BCM_E_UNAVAIL); 36063 } 36064 data = 0x05; 36065 mask = 0x07; 36066 break; 36067 case bcmFieldIpProtocolCommonIpInIp: 36068 data = 0x06; 36069 mask = 0x07; 36070 break; 36071 case bcmFieldIpProtocolCommonTcpUdp: 36072 data = 0x00; 36073 mask = 0x06; 36074 break; 36075 default: 36076 return (BCM_E_UNAVAIL); 36077 } 36078 return _field_qualify32(unit, entry, qual_id, data, mask); 36079 } 36080 36081 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) \ 36082 || defined(BCM_RAPTOR_SUPPORT) 36083 36084 /* Function : _field_qualify_IpFrag 36085 * Description : qualify on Ip Frag Info. 36086 * Parameters : (IN) unit BCM device number 36087 * (IN) entry Field entry to qualify 36088 * (IN) qual_id Field qualifier id. 36089 * (IN) frag_info bcm_field_IpFrag_t to qualify 36090 * Returns : BCM_E_XXX 36091 */ 36092 int 36093 _field_qualify_IpFrag(int unit, bcm_field_entry_t entry, 36094 bcm_field_qualify_t qual_id, 36095 bcm_field_IpFrag_t frag_info) 36096 { 36097 int rv; 36098 _field_entry_t *f_ent = NULL; 36099 uint32 data; 36100 uint32 mask; 36101 _field_stage_id_t stage_id; 36102 36103 if (frag_info >= bcmFieldIpFragCount) { 36104 return (BCM_E_PARAM); 36105 } 36106 36107 #if defined (BCM_TOMAHAWK_SUPPORT) 36108 if (soc_feature(unit, soc_feature_field_preselector_support) && 36109 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 36110 #if defined (BCM_FLOWTRACKER_SUPPORT) 36111 if (soc_feature(unit, soc_feature_field_flowtracker_support)) { 36112 stage_id =_BCM_FIELD_STAGE_FLOWTRACKER; 36113 } else 36114 #endif /* BCM_FLOWTRACKER_SUPPORT */ 36115 { 36116 return BCM_E_UNAVAIL; 36117 } 36118 } else 36119 #endif /* BCM_TOMAHAWK_SUPPORT */ 36120 { 36121 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 36122 BCM_IF_ERROR_RETURN(rv); 36123 stage_id = f_ent->group->stage_id; 36124 } 36125 36126 #if defined (BCM_TOMAHAWK3_SUPPORT) 36127 if (((_BCM_FIELD_STAGE_INGRESS == stage_id) || 36128 (_BCM_FIELD_STAGE_EXACTMATCH == stage_id)) && 36129 (soc_feature(unit, soc_feature_th3_style_fp))) 36130 { 36131 return _field_th3_qualify_IpFrag(unit, entry, 36132 qual_id, 36133 frag_info); 36134 36135 } 36136 #endif 36137 36138 if ((_BCM_FIELD_STAGE_INGRESS == stage_id) || 36139 (_BCM_FIELD_STAGE_EXACTMATCH == stage_id) || 36140 (_BCM_FIELD_STAGE_FLOWTRACKER == stage_id) || 36141 #if defined (BCM_TRX_SUPPORT) 36142 (SOC_IS_TRX(unit) && 36143 (_BCM_FIELD_STAGE_LOOKUP == stage_id)) || 36144 #endif /* BCM_TRX_SUPPORT */ 36145 (_BCM_FIELD_STAGE_EXTERNAL == stage_id)) { 36146 /* 36147 * IP_FRAG_INFO[1] = (IP_OFFSET == 0) & !MoreFragmentlifyIpFragNonOrFirstbcmFieldQualifyIpFragNonOrFirst 36148 * IP_FRAG_INFO[0] = (IP_OFFSET == 0) 36149 */ 36150 switch(frag_info) { 36151 case bcmFieldIpFragAny: 36152 /* Any fragment of fragmented packet */ 36153 data = 0x00; 36154 mask = 0x02; 36155 break; 36156 case bcmFieldIpFragNon: 36157 /* Non-fragmented packet */ 36158 data = 0x02; 36159 mask = 0x02; 36160 break; 36161 case bcmFieldIpFragFirst: 36162 /* First fragment of fragmented packet*/ 36163 data = 0x01; 36164 mask = 0x03; 36165 break; 36166 case bcmFieldIpFragNonOrFirst: 36167 /* Non-fragmented or first fragment */ 36168 data = 0x01; 36169 mask = 0x01; 36170 break; 36171 case bcmFieldIpFragNotFirst: 36172 /* Not the first fragment */ 36173 data = 0x00; 36174 mask = 0x03; 36175 break; 36176 default: 36177 return (BCM_E_PARAM); 36178 } 36179 } 36180 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 36181 else if((_BCM_FIELD_STAGE_EGRESS == stage_id) || 36182 (_BCM_FIELD_STAGE_LOOKUP == stage_id)) { 36183 /* 36184 * 00 : Not a fragment 36185 * 10 : First fragment 36186 * 11 : Non-first fragment 36187 * 01 : Reserved 36188 */ 36189 switch(frag_info) { 36190 case bcmFieldIpFragAny: 36191 /* Any fragment of fragmented packet */ 36192 data = 0x02; 36193 mask = 0x02; 36194 break; 36195 case bcmFieldIpFragNon: 36196 /* Non-fragmented packet */ 36197 data = 0x00; 36198 mask = 0x03; 36199 break; 36200 case bcmFieldIpFragFirst: 36201 /* First fragment of fragmented packet*/ 36202 data = 0x02; 36203 mask = 0x03; 36204 break; 36205 case bcmFieldIpFragNonOrFirst: 36206 /* Non-fragmented or first fragment */ 36207 data = 0x00; 36208 mask = 0x01; 36209 break; 36210 case bcmFieldIpFragNotFirst: 36211 /* Not the first fragment */ 36212 data = 0x03; 36213 mask = 0x03; 36214 break; 36215 default: 36216 return (BCM_E_PARAM); 36217 } 36218 } 36219 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 36220 else { 36221 return (BCM_E_INTERNAL); 36222 } 36223 rv = _field_qualify32(unit, entry, qual_id, data, mask); 36224 return (rv); 36225 } 36226 36227 36228 /* Function : _field_qualify_IpFrag_get 36229 * Description : qualify on Ip Frag Info. 36230 * Parameters : (IN) unit BCM device number 36231 * (IN) entry Field entry to qualify 36232 * (IN) qual_id Field qualifier id. 36233 * (OUT) frag_info bcm_field_IpFrag_t to qualify 36234 * Returns : BCM_E_XXX 36235 */ 36236 int 36237 _field_qualify_IpFrag_get(int unit, bcm_field_entry_t entry, 36238 bcm_field_qualify_t qual_id, 36239 bcm_field_IpFrag_t *frag_info) 36240 { 36241 _field_entry_t *f_ent; /* Field entry structure. */ 36242 uint32 hw_data = 0; /* HW buffer data. */ 36243 uint32 hw_mask = 0; /* HW buffer mask. */ 36244 int rv; /* Operation return status. */ 36245 _field_stage_id_t stage_id; /* Field entry stage. */ 36246 36247 /* Input parameters check. */ 36248 if (NULL == frag_info) { 36249 return (BCM_E_PARAM); 36250 } 36251 36252 #if defined (BCM_TOMAHAWK_SUPPORT) 36253 if (soc_feature(unit, soc_feature_field_preselector_support) && 36254 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 36255 #if defined (BCM_FLOWTRACKER_SUPPORT) 36256 if (soc_feature(unit, soc_feature_field_flowtracker_support)) { 36257 stage_id =_BCM_FIELD_STAGE_FLOWTRACKER; 36258 } else 36259 #endif /* BCM_FLOWTRACKER_SUPPORT */ 36260 { 36261 return BCM_E_UNAVAIL; 36262 } 36263 } else 36264 #endif /* BCM_TOMAHAWK_SUPPORT */ 36265 { 36266 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 36267 BCM_IF_ERROR_RETURN(rv); 36268 stage_id = f_ent->group->stage_id; 36269 } 36270 36271 #if defined (BCM_TOMAHAWK3_SUPPORT) 36272 if (((_BCM_FIELD_STAGE_INGRESS == stage_id) || 36273 (_BCM_FIELD_STAGE_EXACTMATCH == stage_id)) && 36274 (soc_feature(unit, soc_feature_th3_style_fp))) 36275 { 36276 return _field_th3_qualify_IpFrag_get(unit, entry, 36277 qual_id, 36278 frag_info); 36279 36280 } 36281 #endif 36282 36283 /* Read qualifier match value and mask. */ 36284 rv = _bcm_field_entry_qualifier_uint32_get(unit, entry, 36285 qual_id, 36286 &hw_data, &hw_mask); 36287 BCM_IF_ERROR_RETURN(rv); 36288 36289 if ((_BCM_FIELD_STAGE_INGRESS == stage_id) || 36290 (_BCM_FIELD_STAGE_EXACTMATCH == stage_id) || 36291 (_BCM_FIELD_STAGE_FLOWTRACKER == stage_id) || 36292 #if defined (BCM_TRX_SUPPORT) 36293 (SOC_IS_TRX(unit) && 36294 (_BCM_FIELD_STAGE_LOOKUP == stage_id)) || 36295 #endif /* BCM_TRX_SUPPORT */ 36296 (_BCM_FIELD_STAGE_EXTERNAL == stage_id)) { 36297 /* 36298 * IP_FRAG_INFO[1] = (IP_OFFSET == 0) & !MoreFragment 36299 * IP_FRAG_INFO[0] = (IP_OFFSET == 0) 36300 */ 36301 36302 if ((hw_data == 0x2) && (hw_mask == 0x2)) { 36303 *frag_info = bcmFieldIpFragNon; 36304 } else if ((hw_data == 0x1) && (hw_mask == 0x3)) { 36305 *frag_info = bcmFieldIpFragFirst; 36306 } else if ((hw_data == 0x1) && (hw_mask == 0x1)) { 36307 *frag_info = bcmFieldIpFragNonOrFirst; 36308 } else if ((hw_data == 0x0) && (hw_mask == 0x3)) { 36309 *frag_info = bcmFieldIpFragNotFirst; 36310 } else if ((hw_data == 0x0) && (hw_mask == 0x2)) { 36311 *frag_info = bcmFieldIpFragAny; 36312 } else { 36313 return (BCM_E_INTERNAL); 36314 } 36315 } 36316 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 36317 else if((_BCM_FIELD_STAGE_EGRESS == stage_id) || 36318 (_BCM_FIELD_STAGE_LOOKUP == stage_id)) { 36319 /* 36320 * 00 : Not a fragment 36321 * 10 : First fragment 36322 * 11 : Non-first fragment 36323 * 01 : Reserved 36324 */ 36325 if ((hw_data == 0x0) && (hw_mask == 0x3)) { 36326 *frag_info = bcmFieldIpFragNon; 36327 } else if ((hw_data == 0x2) && (hw_mask == 0x3)) { 36328 *frag_info = bcmFieldIpFragFirst; 36329 } else if ((hw_data == 0x0) && (hw_mask == 0x1)) { 36330 *frag_info = bcmFieldIpFragNonOrFirst; 36331 } else if ((hw_data == 0x3) && (hw_mask == 0x3)) { 36332 *frag_info = bcmFieldIpFragNotFirst; 36333 } else if ((hw_data == 0x2) && (hw_mask == 0x2)) { 36334 *frag_info = bcmFieldIpFragAny; 36335 } else { 36336 return (BCM_E_INTERNAL); 36337 } 36338 } 36339 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 36340 else { 36341 return (BCM_E_INTERNAL); 36342 } 36343 return (BCM_E_NONE); 36344 } 36345 36346 36347 #endif /* BCM_FIREBOLT_SUPPORT || BCM_TRX_SUPPORT || BCM_RAPTOR_SUPPORT */ 36348 36349 /* 36350 * Function: 36351 * _field_qual_selectors_insert 36352 * Purpose: 36353 * Initialize field group select codes. 36354 * Parameters: 36355 * unit - (IN) BCM device number. 36356 * candidate - (IN) Inserted selector set. 36357 * parts_count - (IN) Number of tcam parts. 36358 * selector - (IN/OUT) Result selector set. 36359 * 36360 * Returns: 36361 * BCM_E_XXX 36362 */ 36363 STATIC int 36364 _field_qual_selectors_insert (int unit, _field_sel_t *candidate, 36365 uint8 parts_count, 36366 _bcm_field_selector_t *selector) 36367 { 36368 int8 idx; /* Tcam parts iterator. */ 36369 uint8 selected_part; /* Tcam part selected for 36370 qualifier installation. */ 36371 uint8 update_count_min; /* Minimum selectors update count. */ 36372 uint8 update_count; /* Number of updates required 36373 to accommodate qualifier. */ 36374 int rv; /* Operation return status. */ 36375 36376 /* Input parameters check. */ 36377 if ((NULL == candidate) || (NULL == selector)) { 36378 return (BCM_E_PARAM); 36379 } 36380 36381 update_count_min = _FP_INVALID_INDEX; 36382 selected_part = _FP_INVALID_INDEX; 36383 36384 if (soc_feature(unit, soc_feature_td2p_fp_sw_war)) { 36385 for (idx = (parts_count -1); idx >= 0; idx--) { 36386 update_count = 0; 36387 36388 /* Test if selector can be inserted in a specific tcam part. */ 36389 rv = _field_selector_diff(unit, candidate, idx, selector, &update_count); 36390 if (BCM_FAILURE(rv)) { 36391 continue; 36392 } 36393 36394 if (update_count < update_count_min) { 36395 update_count_min = update_count; 36396 selected_part = idx; 36397 } 36398 } 36399 } else { 36400 for (idx = 0; idx < parts_count; idx++) { 36401 update_count = 0; 36402 36403 /* Test if selector can be inserted in a specific tcam part. */ 36404 rv = _field_selector_diff(unit, candidate, idx, selector, &update_count); 36405 if (BCM_FAILURE(rv)) { 36406 continue; 36407 } 36408 36409 if (update_count < update_count_min) { 36410 update_count_min = update_count; 36411 selected_part = idx; 36412 } 36413 } 36414 } 36415 36416 /* Check if any tcam part can accommodate all the required selectors. */ 36417 if ((uint8)_FP_INVALID_INDEX == selected_part) { 36418 return (BCM_E_RESOURCE); 36419 } 36420 36421 /* Insert selector configuration. */ 36422 rv = _field_selector_insert(candidate, selected_part, selector); 36423 return (rv); 36424 } 36425 36426 /* 36427 * Function: 36428 * _field_qual_selectors_sort 36429 * Purpose: 36430 * Sorf field qualifiers select codes. 36431 * Parameters: 36432 * unit - (IN) BCM device number. 36433 * candidate - (IN) Inserted selector set. 36434 * parts_count - (IN) Number of tcam parts. 36435 * f_qual_arr - (IN/OUT) Result selector set. 36436 * 36437 * Returns: 36438 * BCM_E_XXX 36439 */ 36440 STATIC int 36441 _field_qual_selectors_sort (int unit, 36442 _field_sel_t *candidate, 36443 uint8 parts_count, 36444 _bcm_field_qual_info_t *f_qual) 36445 { 36446 uint8 idx; /* Tcam parts iterator. */ 36447 uint8 conf_idx; /* Configurations iterator. */ 36448 uint8 update_count_min; /* Minimum selectors update count. */ 36449 uint8 update_count; /* Number of updates required 36450 to accommodate qualifier. */ 36451 int rv; /* Operation return status. */ 36452 _bcm_field_selector_t *selector;/* Qualifier select codes config. */ 36453 36454 /* Input parameters check. */ 36455 if ((NULL == candidate) || (NULL == f_qual)) { 36456 return (BCM_E_PARAM); 36457 } 36458 36459 /* Don't sort if only one configuration is available. */ 36460 if (f_qual->conf_sz <= 1) { 36461 return (BCM_E_NONE); 36462 } 36463 36464 /* Get number of updates required for each qualifier configuration. */ 36465 for (conf_idx = 0; conf_idx < f_qual->conf_sz; conf_idx++) { 36466 update_count_min = _FP_INVALID_INDEX; 36467 selector = &((f_qual->conf_arr[conf_idx]).selector); 36468 36469 for (idx = 0; idx < parts_count; idx++) { 36470 update_count = 0; 36471 36472 /* Test if selector can be inserted in a specific tcam part. */ 36473 rv = _field_selector_diff(unit, candidate, idx, 36474 selector, &update_count); 36475 if (BCM_FAILURE(rv)) { 36476 continue; 36477 } 36478 36479 if (update_count < update_count_min) { 36480 update_count_min = update_count; 36481 } 36482 } 36483 /* Keep minimum number of required updates. */ 36484 selector->update_count = update_count_min; 36485 } 36486 36487 /* Qualifier configurations sort based on number of updates required. */ 36488 _shr_sort(f_qual->conf_arr, f_qual->conf_sz, 36489 sizeof(_bcm_field_qual_conf_t), _field_selector_update_cmp); 36490 return (BCM_E_NONE); 36491 } 36492 36493 /* 36494 * Function: 36495 * _field_group_selectors_init 36496 * Purpose: 36497 * Initialize field group select codes. 36498 * Parameters: 36499 * unit - (IN) BCM device number. 36500 * fg - (IN/OUT) Field group structure. 36501 * 36502 * Returns: 36503 * BCM_E_XXX 36504 */ 36505 STATIC int 36506 _field_group_selectors_init(int unit, _field_group_t *fg) 36507 { 36508 /* Input parameters check. */ 36509 if (NULL == fg) { 36510 return (BCM_E_PARAM); 36511 } 36512 36513 fg->sel_codes[0].intraslice = _FP_SELCODE_DONT_USE; 36514 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 36515 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 36516 fg->sel_codes[2].intraslice = _FP_SELCODE_DONT_USE; 36517 } else { 36518 fg->sel_codes[1].intraslice = _FP_SELCODE_DONT_USE; 36519 } 36520 } else if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 36521 fg->sel_codes[1].intraslice = _FP_SELCODE_DONT_USE; 36522 fg->sel_codes[2].intraslice = _FP_SELCODE_DONT_USE; 36523 } 36524 36525 fg->sel_codes[0].secondary = _FP_SELCODE_DONT_USE; 36526 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 36527 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 36528 fg->sel_codes[1].secondary = _FP_SELCODE_DONT_USE; 36529 fg->sel_codes[2].secondary = _FP_SELCODE_DONT_USE; 36530 } 36531 } else if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 36532 fg->sel_codes[1].secondary = _FP_SELCODE_DONT_USE; 36533 fg->sel_codes[2].secondary = _FP_SELCODE_DONT_USE; 36534 } 36535 36536 return BCM_E_NONE; 36537 } 36538 36539 /* 36540 * Function: 36541 * _bcm_field_selcode_qual_arr_free 36542 * Purpose: 36543 * Free memory allocated for the temporary qual array used during group creation. 36544 * Parameters: 36545 * unit - (IN) BCM device number. 36546 * f_qual_arr - (INOUT)Qualifiers information array. 36547 * qual_count - (IN)Qualifiers information array size. 36548 */ 36549 void _bcm_field_selcode_qual_arr_free(int unit, 36550 _bcm_field_qual_info_t ***f_qual_arr, uint16 qual_count) 36551 { 36552 int qual_idx = 0; 36553 36554 if (NULL == f_qual_arr) { 36555 return; 36556 } 36557 36558 if (*f_qual_arr) { 36559 for (qual_idx = 0; qual_idx < qual_count ; qual_idx++) { 36560 if ((*f_qual_arr)[qual_idx]) { 36561 if ((*f_qual_arr)[qual_idx]->conf_arr) { 36562 sal_free((*f_qual_arr)[qual_idx]->conf_arr); 36563 (*f_qual_arr)[qual_idx]->conf_arr = NULL; 36564 } 36565 sal_free((*f_qual_arr)[qual_idx]); 36566 (*f_qual_arr)[qual_idx] = NULL; 36567 } 36568 } 36569 sal_free(*f_qual_arr); 36570 *f_qual_arr = NULL; 36571 } 36572 } 36573 36574 /* 36575 * Function: 36576 * _bcm_field_qualifiers_info_get 36577 * Purpose: 36578 * Copy qualifiers configuration for a given qualifiers set. 36579 * Parameters: 36580 * unit - (IN) BCM device number. 36581 * stage_fc - (IN) Stage Field control structure. 36582 * qset_req - (IN) Client qualifier set. 36583 * f_qual_arr - (OUT)Qualifiers information array. 36584 * qual_arr_size - (OUT)Qualifiers information array size. 36585 * 36586 * Returns: 36587 * BCM_E_XXX 36588 */ 36589 int 36590 _bcm_field_qualifiers_info_get(int unit, _field_stage_t *stage_fc, 36591 bcm_field_qset_t *qset_req, 36592 _bcm_field_qual_info_t ***f_qual_arr, 36593 uint16 *qual_arr_size) 36594 { 36595 uint16 idx; /* Qualifier set iterator. */ 36596 uint16 arr_idx; /* Qualifiers array index. */ 36597 36598 /* Input parameters check. */ 36599 if ((NULL == f_qual_arr) || (NULL == qset_req) || 36600 (NULL == qual_arr_size) || (NULL == stage_fc)) { 36601 return (BCM_E_PARAM); 36602 } 36603 36604 /* Get number of qualifiers in requested qualifier set. */ 36605 *qual_arr_size = 0; 36606 for(idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) { 36607 *qual_arr_size += _shr_popcount(qset_req->w[idx]); 36608 } 36609 36610 36611 /* Allocate & initialize group select codes array. */ 36612 _FP_XGS3_ALLOC((*f_qual_arr), 36613 (*qual_arr_size * sizeof(_bcm_field_qual_info_t *)), 36614 "Field qualifiers"); 36615 if (NULL == (*f_qual_arr)) { 36616 return (BCM_E_MEMORY); 36617 } 36618 36619 /* Copy individual qualifiers information from the requested qset */ 36620 arr_idx = 0; 36621 for (idx = 0; idx < _bcmFieldQualifyCount; idx++) { 36622 /* Skip unused qualifiers. */ 36623 if (0 == BCM_FIELD_QSET_TEST((*qset_req), idx)) { 36624 continue; 36625 } 36626 36627 /* Qualifiers support check. */ 36628 if (NULL == stage_fc->f_qual_arr[idx]) { 36629 sal_free (*f_qual_arr); 36630 return (BCM_E_RESOURCE); 36631 } 36632 36633 /* Make a copy of the qualifier combination for sorting 36634 * instead of using pointer to the data in stage_fc 36635 * this will avoid sorting of qualifiers in stage_fc 36636 * and make group create independent of previously 36637 * created groups. 36638 */ 36639 _FP_XGS3_ALLOC(((*f_qual_arr)[arr_idx]), 36640 (sizeof(_bcm_field_qual_info_t)), 36641 "Field qualifiers"); 36642 if (NULL == (*f_qual_arr)[arr_idx]) { 36643 _bcm_field_selcode_qual_arr_free(unit, f_qual_arr, arr_idx); 36644 return (BCM_E_MEMORY); 36645 } 36646 36647 (*f_qual_arr)[arr_idx]->qid = stage_fc->f_qual_arr[idx]->qid; 36648 (*f_qual_arr)[arr_idx]->conf_sz = stage_fc->f_qual_arr[idx]->conf_sz; 36649 36650 /* Allocate memory for qualifer config array */ 36651 _FP_XGS3_ALLOC(((*f_qual_arr)[arr_idx]->conf_arr), 36652 (stage_fc->f_qual_arr[idx]->conf_sz * sizeof(_bcm_field_qual_conf_t)), 36653 "Field qualifiers"); 36654 if (NULL == (*f_qual_arr)[arr_idx]->conf_arr) { 36655 sal_free((*f_qual_arr)[arr_idx]); 36656 (*f_qual_arr)[arr_idx] = NULL; 36657 _bcm_field_selcode_qual_arr_free(unit, f_qual_arr, arr_idx); 36658 return (BCM_E_MEMORY); 36659 } 36660 36661 /* Copy qual info from stage fc to new memory allocated */ 36662 memcpy((*f_qual_arr)[arr_idx]->conf_arr, stage_fc->f_qual_arr[idx]->conf_arr, 36663 (stage_fc->f_qual_arr[idx]->conf_sz * sizeof(_bcm_field_qual_conf_t))); 36664 36665 arr_idx++; 36666 if (arr_idx == (*qual_arr_size)) { 36667 break; 36668 } 36669 } 36670 36671 /* Qualifier array elements are sorted so less frequently present 36672 qualifiers appear first. */ 36673 _shr_sort((*f_qual_arr), *qual_arr_size, sizeof(_bcm_field_qual_info_t *), 36674 _field_qual_info_cmp); 36675 36676 return (BCM_E_NONE); 36677 } 36678 /* 36679 * Function: 36680 * _field_qual_offsets_copy 36681 * Purpose: 36682 * Copy group qualifiers offsets. 36683 * Parameters: 36684 * unit - (IN) BCM unit number. 36685 * fg - (IN) Field group. 36686 * qual_count - (IN) Number of qualifiers on group qset. 36687 * f_qual_arr - (IN) Qualifier descriptors array. 36688 * fg - (IN/OUT)Select code information filled into the group. 36689 * 36690 * Returns: 36691 * BCM_E_XXX 36692 */ 36693 STATIC int 36694 _field_qual_offsets_copy(int unit, _field_group_t *fg, uint16 qual_count, 36695 _bcm_field_qual_info_t **f_qual_arr, 36696 uint8 *qual_conf_idx) 36697 { 36698 _bcm_field_qual_conf_t *qual_config; /* Qualifier configuration. */ 36699 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 36700 bcm_field_qset_t qset_assigned; /* Assigned to a specific */ 36701 /* entry part qualifiers. */ 36702 int qual_idx; /* Qualifiers iteration index. */ 36703 int part_idx; /* Tcam parts iteration index. */ 36704 int parts_count = 0; /* Number of entry parts. */ 36705 uint8 conf_idx; /* Qualifiers configuration index.*/ 36706 uint8 diff; /* Selector diff . */ 36707 uint16 *qid_arr; /* New qualifiers array. */ 36708 _bcm_field_qual_offset_t *offset_arr;/* New qualifier offsets array. */ 36709 uint16 size = 0; /* Qualifiers array size. */ 36710 int rv; /* Operation return status. */ 36711 36712 /* Input parameters check. */ 36713 if ((NULL == fg) || (NULL == f_qual_arr) || (NULL == qual_conf_idx)) { 36714 return (BCM_E_PARAM); 36715 } 36716 36717 BCM_FIELD_QSET_INIT(qset_assigned); 36718 /* Get number of entry parts we have to read. */ 36719 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 36720 fg->flags, &parts_count); 36721 BCM_IF_ERROR_RETURN(rv); 36722 36723 /* Get currently assigned qualifiers. */ 36724 for (part_idx = 0; part_idx < parts_count; part_idx++) { 36725 q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx]); 36726 for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) { 36727 BCM_FIELD_QSET_ADD (qset_assigned, q_arr->qid_arr[qual_idx]); 36728 } 36729 } 36730 36731 for (part_idx = 0; part_idx < parts_count; part_idx++) { 36732 /* Initialization. */ 36733 offset_arr = NULL; 36734 qid_arr = NULL; 36735 36736 /* Get qualifiers array pointer. */ 36737 q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx]); 36738 size = q_arr->size; 36739 36740 for (qual_idx = 0; qual_idx < qual_count; qual_idx++) { 36741 /* Check if qualifier was already assigned. */ 36742 if (BCM_FIELD_QSET_TEST (qset_assigned, f_qual_arr[qual_idx]->qid)) { 36743 continue; 36744 } 36745 36746 /* Get qualifier configuration index. */ 36747 conf_idx = qual_conf_idx[qual_idx]; 36748 /* Get qualifier configuration for the index. */ 36749 qual_config = f_qual_arr[qual_idx]->conf_arr + conf_idx; 36750 /* Test if selector was inserted in a specific tcam part. */ 36751 rv = _field_selector_diff(unit, fg->sel_codes, part_idx, 36752 &qual_config->selector, 36753 &diff); 36754 if (BCM_FAILURE(rv) || diff) { 36755 continue; 36756 } 36757 size++; 36758 } 36759 36760 /* Allocate qualifiers id and offsets array. */ 36761 _FP_XGS3_ALLOC(qid_arr, (size * sizeof (uint16)), "Group qual id"); 36762 if (NULL == qid_arr) { 36763 return (BCM_E_MEMORY); 36764 } 36765 _FP_XGS3_ALLOC(offset_arr, (size * 36766 sizeof (_bcm_field_qual_offset_t)), "Group qual offset"); 36767 if (NULL == offset_arr) { 36768 sal_free (qid_arr); 36769 return (BCM_E_MEMORY); 36770 } 36771 36772 /* Copy whatever qualifiers the group already have into the new array */ 36773 if (q_arr->size) { 36774 sal_memcpy(qid_arr, q_arr->qid_arr, 36775 q_arr->size * sizeof (uint16)); 36776 sal_memcpy(offset_arr, q_arr->offset_arr, 36777 q_arr->size * sizeof(_bcm_field_qual_offset_t)); 36778 } 36779 size = q_arr->size; 36780 36781 /* Free old group qualifiers. */ 36782 rv = _bcm_field_group_qualifiers_free(fg, part_idx); 36783 if (BCM_FAILURE(rv)) { 36784 sal_free(qid_arr); 36785 sal_free(offset_arr); 36786 return (rv); 36787 } 36788 36789 /* Now let the group point to the new and bigger array */ 36790 q_arr->qid_arr = qid_arr; 36791 q_arr->offset_arr = offset_arr; 36792 q_arr->size = size; 36793 36794 for (qual_idx = 0; qual_idx < qual_count; qual_idx++) { 36795 /* Check if qualifier was already assigned. */ 36796 if (BCM_FIELD_QSET_TEST (qset_assigned, f_qual_arr[qual_idx]->qid)) { 36797 continue; 36798 } 36799 36800 /* Get qualifier configuration index. */ 36801 conf_idx = qual_conf_idx[qual_idx]; 36802 /* Get qualifier configuration for the index. */ 36803 qual_config = f_qual_arr[qual_idx]->conf_arr + conf_idx; 36804 /* Test if selector was inserted in a specific tcam part. */ 36805 rv = _field_selector_diff(unit, fg->sel_codes, part_idx, 36806 &qual_config->selector, 36807 &diff); 36808 if (BCM_FAILURE(rv) || diff) { 36809 continue; 36810 } 36811 q_arr->qid_arr[q_arr->size] = f_qual_arr[qual_idx]->qid; 36812 q_arr->offset_arr[q_arr->size] = qual_config->offset; 36813 q_arr->size++; 36814 BCM_FIELD_QSET_ADD (qset_assigned, f_qual_arr[qual_idx]->qid); 36815 } 36816 } 36817 return (BCM_E_NONE); 36818 } 36819 36820 /* 36821 * Function: 36822 * _bcm_field_qual_lists_get 36823 * Purpose: 36824 * Build a group's qual_info_t linked list by assembling 36825 * linked-lists from each select code. 36826 * Parameters: 36827 * unit - (IN) BCM device number. 36828 * stage_fc - (IN) Stage field control structure. 36829 * fg - (IN) Group control structure. 36830 * Returns: 36831 * BCM_E_XXX 36832 */ 36833 int 36834 _bcm_field_qual_lists_get(int unit, _field_stage_t *stage_fc, 36835 _field_group_t *fg) 36836 { 36837 return (BCM_E_NONE); 36838 } 36839 36840 /* 36841 * Function: 36842 * _bcm_field_selcode_to_qset 36843 * Purpose: 36844 * Find the qset that corresponds to all the possible qualifiers 36845 * supported by the field selection codes (FPF1, FPF2, FPF3). 36846 * Parameters: 36847 * unit - (IN) unit 36848 * stage_fc - (IN) Stage Field control structure. 36849 * fg - (IN) Field group control structure. 36850 * code_id - (IN) Entry part. 36851 * qset - (OUT) Client qualifier set. 36852 * Returns: 36853 * BCM_E_XXX 36854 */ 36855 int 36856 _bcm_field_selcode_to_qset(int unit, _field_stage_t *stage_fc, 36857 _field_group_t *fg, int code_id, 36858 bcm_field_qset_t *qset) 36859 { 36860 /* selectors value. */ 36861 int idx; /* Qualifiers array iterator. */ 36862 36863 /* Input parameters check. */ 36864 if ((NULL == qset) || (NULL == stage_fc) || 36865 (NULL == fg) || (code_id < 0) || (code_id >= _FP_MAX_ENTRY_WIDTH)) { 36866 return (BCM_E_PARAM); 36867 } 36868 36869 BCM_FIELD_QSET_INIT(*qset); 36870 36871 for(idx = 0; idx < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][code_id].size; idx++) { 36872 BCM_FIELD_QSET_ADD(*qset, fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][code_id].qid_arr[idx]); 36873 } 36874 return (BCM_E_NONE); 36875 } 36876 36877 /* 36878 * Function: 36879 * _bcm_field_selcode_get 36880 * Purpose: 36881 * Finds a 4-tuple of select encodings that will satisfy the 36882 * requested qualifier set (Qset). 36883 * Parameters: 36884 * unit - (IN) BCM unit number. 36885 * stage_fc - (IN) Stage Field control structure. 36886 * qset_req - (IN) Client qualifier set. 36887 * fg - (IN/OUT)Select code information filled into the group. 36888 * 36889 * Returns: 36890 * BCM_E_XXX 36891 */ 36892 int 36893 _bcm_field_selcode_get(int unit, _field_stage_t *stage_fc, 36894 bcm_field_qset_t *qset_req, 36895 _field_group_t *fg) 36896 { 36897 #ifdef BCM_WARM_BOOT_SUPPORT 36898 _field_control_t *fc; /* Pointer to field control */ 36899 #endif 36900 _bcm_field_qual_info_t **f_qual_arr; /* Qualifiers information. */ 36901 _bcm_field_qual_conf_t *qual_config; /* Qualifier configuration. */ 36902 uint8 *qual_conf_idx; /* Array of iterators over each */ 36903 /* individual qual configurations. */ 36904 _field_sel_t *sel_arr; /* Selectors status before each */ 36905 /* individual qualifier */ 36906 /* configuration was added. */ 36907 _field_sel_t *candidate; /* Candidate select codes set. */ 36908 uint8 conf_idx = 0; /* Qualifiers configuration index. */ 36909 uint16 qual_count = 0; /* Number of qualifiers in */ 36910 /* the requested qset. */ 36911 int parts_count = 0; /* Number of tcam parts. */ 36912 int qual_idx = 0; /* Qualifiers iteration index. */ 36913 int sel_entry_sz = 0; /* Byte size of sel_arr entity. */ 36914 int rv = BCM_E_NONE; /* Operation return status. */ 36915 36916 /* Input parameters check. */ 36917 if ((NULL == fg) || (NULL == qset_req) || (NULL == stage_fc)) { 36918 return (BCM_E_PARAM); 36919 } 36920 36921 /* Initialization. */ 36922 f_qual_arr = NULL; 36923 qual_config = NULL; 36924 qual_conf_idx = NULL; 36925 sel_arr = NULL; 36926 candidate = NULL; 36927 36928 #ifdef BCM_WARM_BOOT_SUPPORT 36929 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 36930 #endif 36931 /* Update group selectors based on group flags. */ 36932 rv = _field_group_selectors_init(unit, fg); 36933 BCM_IF_ERROR_RETURN(rv); 36934 36935 /* Get qualifiers configuration. */ 36936 /* NOTE: Must free f_qual_arr at the end. */ 36937 rv = _bcm_field_qualifiers_info_get (unit, stage_fc, qset_req, 36938 &f_qual_arr, &qual_count); 36939 BCM_IF_ERROR_RETURN(rv); 36940 36941 /* Allocate and initialize qualifier configurations iterators. */ 36942 _FP_XGS3_ALLOC(qual_conf_idx, (qual_count * sizeof(uint8)), 36943 "Field qualifier configuration"); 36944 if (NULL == qual_conf_idx) { 36945 _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count); 36946 return (BCM_E_MEMORY); 36947 } 36948 36949 /* Get number of entry parts. */ 36950 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 36951 fg->flags, &parts_count); 36952 if (BCM_FAILURE(rv)) { 36953 sal_free(qual_conf_idx); 36954 qual_conf_idx = NULL; 36955 _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count); 36956 return (rv); 36957 } 36958 36959 /* Allocate and initialize select codes status before */ 36960 /* individual qualifier configuration was applied. */ 36961 /* Candidate select codes are in the last element of the array. */ 36962 sel_entry_sz = parts_count * sizeof(_field_sel_t); 36963 _FP_XGS3_ALLOC(sel_arr, ((1 + qual_count) * sel_entry_sz), \ 36964 "Field group select codes"); 36965 if (NULL == sel_arr) { 36966 sal_free(qual_conf_idx); 36967 _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count); 36968 return (BCM_E_MEMORY); 36969 } 36970 36971 /* Initialize first qualifier select codes to group select codes. */ 36972 candidate = sel_arr + (qual_count * parts_count); 36973 sal_memcpy(candidate, fg->sel_codes, sel_entry_sz); 36974 36975 /* Initialize first qualifier select codes to a group defaults */ 36976 sal_memcpy(sel_arr, candidate, sel_entry_sz); 36977 36978 /* Main select codes selection loop over caller requested qualifier set. */ 36979 for (qual_idx = 0; qual_idx < qual_count;) { 36980 36981 /* Get qualifier selcodes configuration index. */ 36982 conf_idx = qual_conf_idx[qual_idx]; 36983 36984 /* 36985 * Sort qualifier configurations so minimum 36986 * change configuration attempted first. 36987 */ 36988 if (0 == conf_idx) { 36989 rv = _field_qual_selectors_sort(unit, candidate, 36990 parts_count, f_qual_arr[qual_idx]); 36991 if (BCM_FAILURE(rv)) { 36992 sal_free(sel_arr); 36993 sal_free(qual_conf_idx); 36994 _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count); 36995 return (rv); 36996 } 36997 } 36998 36999 /* 37000 * Set default return value, in case all configuration 37001 * options were exhausted. 37002 */ 37003 rv = BCM_E_RESOURCE; 37004 37005 /* Loop over possible qualifier configurations. */ 37006 for (;conf_idx < f_qual_arr[qual_idx]->conf_sz; conf_idx++) { 37007 37008 /* Get qualifier configuration for the index. */ 37009 qual_config = f_qual_arr[qual_idx]->conf_arr + conf_idx; 37010 #ifdef BCM_WARM_BOOT_SUPPORT 37011 if (SOC_WARM_BOOT(unit) && (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id)) { 37012 if(soc_feature(unit, soc_feature_td3_style_fp) 37013 && (BCM_FIELD_WB_VERSION_1_25 == fc->wb_recovered_version) 37014 && (_FIELD_IS_CLASS_ID_B_SEL(qual_config->selector.sec_sel) 37015 && (9 != qual_config->selector.sec_sel_val) 37016 && (4 != qual_config->selector.sec_sel_val) 37017 && (2 != qual_config->selector.sec_sel_val))) { 37018 continue; 37019 } 37020 if (soc_feature(unit, soc_feature_td3_style_fp) 37021 && (BCM_FIELD_WB_VERSION_1_25 >= fc->wb_recovered_version) 37022 && (_bcmFieldSliceSelEgrClassIdBF5 == qual_config->selector.sec_sel)) { 37023 continue; 37024 } 37025 } 37026 #endif 37027 /* Skip conflicting configurations. */ 37028 if ((uint8) _FP_INVALID_INDEX == 37029 qual_config->selector.update_count) { 37030 continue; 37031 } 37032 37033 /* 37034 * Attempt to accommodate specific qualifier 37035 * configuration into candidate select codes. 37036 */ 37037 rv = _field_qual_selectors_insert(unit, candidate, 37038 parts_count, 37039 &qual_config->selector); 37040 37041 if (BCM_SUCCESS(rv) || (BCM_E_RESOURCE != rv)) { 37042 break; 37043 } 37044 } 37045 37046 /* 37047 * If code failed to insert qualifier configuration 37048 * attempt a previous qualifier in the list using alternative 37049 * configuration. 37050 */ 37051 if (BCM_FAILURE(rv)) { 37052 if ((qual_idx == 0) || (BCM_E_RESOURCE != rv)) { 37053 break; 37054 } 37055 /* Previous qualifier has to use next available configuration. */ 37056 while (qual_idx > 0) { 37057 /* This qualifier configuration will be re-selected. */ 37058 qual_conf_idx[qual_idx] = 0; 37059 /* Back to the previous qualifier. */ 37060 qual_idx--; 37061 /* Check select codes were modified by qualifier. */ 37062 qual_config = f_qual_arr[qual_idx]->conf_arr + 37063 qual_conf_idx[qual_idx]; 37064 /* If modified -> reverse changes and proceed to next config.*/ 37065 if ((0 == qual_idx) || 37066 (0 != qual_config->selector.update_count)) { 37067 /* Go to the next configuration */ 37068 qual_conf_idx[qual_idx]++; 37069 /* Restore original select codes state. */ 37070 sal_memcpy(candidate, 37071 sel_arr + (qual_idx * parts_count), 37072 sel_entry_sz); 37073 break; 37074 } 37075 } 37076 } else { 37077 /* Preserve current qualifier configuration index. */ 37078 qual_conf_idx[qual_idx] = conf_idx; 37079 /* Proceed to the next qualifier. */ 37080 qual_idx++; 37081 /* Set selection base line for the next qualifier */ 37082 if (qual_idx < qual_count) { 37083 sal_memcpy(sel_arr + (qual_idx * parts_count), 37084 candidate, sel_entry_sz); 37085 } 37086 } 37087 } 37088 if (BCM_SUCCESS(rv)) { 37089 /* Copy selected codes to the group configuration. */ 37090 sal_memcpy(fg->sel_codes, candidate, sel_entry_sz); 37091 /* Copy qualifiers offset to group tcam parts. */ 37092 rv = _field_qual_offsets_copy(unit, fg, qual_count, 37093 f_qual_arr, qual_conf_idx); 37094 } 37095 sal_free(sel_arr); 37096 sal_free(qual_conf_idx); 37097 _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count); 37098 return (rv); 37099 } 37100 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 37101 /* 37102 * Function: 37103 * _field_egress_key_attempt 37104 * Purpose: 37105 * Verify if specific key can satisfy user requested qset. 37106 * 37107 * Parameters: 37108 * unit - (IN) BCM unit number. 37109 * stage_fc - (IN) Stage Field control structure. 37110 * qset_req - (IN) Client qualifier set. 37111 * key_pri - (IN) Primary key id. 37112 * key_sec - (IN) Secondary key id. 37113 * fg - (IN/OUT)Select code information filled into the group. 37114 * 37115 * Returns: 37116 * BCM_E_XXX 37117 */ 37118 int 37119 _bcm_field_egress_key_attempt(int unit, _field_stage_t *stage_fc, 37120 bcm_field_qset_t *qset_req, 37121 uint8 key_pri, uint8 key_sec, 37122 _field_group_t *fg) 37123 { 37124 /* Input parameters check. */ 37125 if ((NULL == fg) || (NULL == qset_req) || (NULL == stage_fc)) { 37126 return (BCM_E_PARAM); 37127 } 37128 fg->sel_codes[0].fpf3= key_pri; 37129 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 37130 fg->sel_codes[1].fpf3= key_sec; 37131 } 37132 /* Verify that each requested qualifier present in the key. */ 37133 return _bcm_field_selcode_get(unit, stage_fc, qset_req, fg); 37134 } 37135 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 37136 37137 /* 37138 * Function: _field_qualify_VlanFormat 37139 * 37140 * Purpose: 37141 * Add qualification data to an entry for Vlan Tag Format. 37142 * 37143 * Parameters: 37144 * unit - (IN) BCM unit number. 37145 * entry - (IN) Entry ID. 37146 * qual_id - (IN) Qualifier id. 37147 * data - (IN) Outer & Inner tag presence info. 37148 * mask - (IN) Data mask. 37149 * Returns: 37150 * BCM_E_XXX 37151 */ 37152 int 37153 _field_qualify_VlanFormat(int unit, bcm_field_entry_t entry, 37154 bcm_field_qualify_t qual_id, 37155 uint8 data, uint8 mask) 37156 { 37157 _field_entry_t *f_ent; /* Field entry structure. */ 37158 int rv; /* Operation return status. */ 37159 uint8 hw_data = data; 37160 uint8 hw_mask = mask; 37161 37162 #if defined(BCM_TOMAHAWK_SUPPORT) 37163 if (soc_feature(unit, soc_feature_field_preselector_support) && 37164 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 37165 #if defined(BCM_TRIDENT3_SUPPORT) 37166 if(soc_feature(unit, soc_feature_td3_style_fp)) { 37167 rv = _bcm_field_td3_qualify_VlanFormat(unit, qual_id, 37168 data, mask, 37169 &hw_data, &hw_mask); 37170 BCM_IF_ERROR_RETURN(rv); 37171 } else 37172 #endif /* BCM_TRIDENT3_SUPPORT */ 37173 { 37174 return BCM_E_UNAVAIL; 37175 } 37176 } else 37177 #endif /* BCM_TOMAHAWK_SUPPORT */ 37178 { 37179 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 37180 if (BCM_FAILURE(rv)) { 37181 return (rv); 37182 } 37183 37184 #if defined (BCM_TOMAHAWK3_SUPPORT) 37185 if (soc_feature(unit, soc_feature_th3_style_fp)) { 37186 if (_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) { 37187 hw_data = (((data & 0x2) >> 1) | ((data & 0x1) << 1)); 37188 hw_mask = (((mask & 0x2) >> 1) | ((mask & 0x1) << 1)); 37189 } 37190 } else 37191 #endif 37192 { 37193 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 37194 if (soc_feature(unit, soc_feature_field_qual_vlanformat_reverse) || 37195 soc_feature(unit, soc_feature_field_multi_stage)) { 37196 if ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) || 37197 (SOC_IS_TRX(unit))) { 37198 hw_data = (((data & 0x2) >> 1) | ((data & 0x1) << 1)); 37199 hw_mask = (((mask & 0x2) >> 1) | ((mask & 0x1) << 1)); 37200 } 37201 } 37202 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 37203 } 37204 } 37205 37206 rv = _field_qualify32(unit, entry, qual_id, hw_data, hw_mask); 37207 return (rv); 37208 } 37209 37210 /* 37211 * Function: _field_qualify_VlanFormat_get 37212 * 37213 * Purpose: 37214 * Get qualification match criteria from an entry for Vlan Tag Format. 37215 * 37216 * Parameters: 37217 * unit - (IN) BCM unit number. 37218 * entry - (IN) Entry ID. 37219 * qual_id - (IN) Qualifier id. 37220 * data - (OUT) Outer & Inner tag presence info. 37221 * mask - (OUT) Data mask. 37222 * Returns: 37223 * BCM_E_XXX 37224 */ 37225 int 37226 _field_qualify_VlanFormat_get(int unit, bcm_field_entry_t entry, 37227 bcm_field_qualify_t qual_id, 37228 uint8 *data, uint8 *mask) 37229 { 37230 uint8 hw_data; /* HW encoded data. */ 37231 uint8 hw_mask; /* HW encoded mask. */ 37232 int rv; /* Operation return status. */ 37233 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 37234 _field_entry_t *f_ent; /* Field entry structure. */ 37235 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 37236 37237 /* Read qualifier match value and mask. */ 37238 rv = _bcm_field_entry_qualifier_uint8_get(unit, entry, qual_id, 37239 &hw_data, &hw_mask); 37240 BCM_IF_ERROR_RETURN(rv); 37241 37242 37243 #if defined(BCM_TOMAHAWK_SUPPORT) 37244 if (soc_feature(unit, soc_feature_field_preselector_support) && 37245 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) { 37246 #if defined(BCM_TRIDENT3_SUPPORT) 37247 if(soc_feature(unit, soc_feature_td3_style_fp)) { 37248 rv = _bcm_field_td3_qualify_VlanFormat_get(unit, qual_id, 37249 hw_data, hw_mask, 37250 data, mask); 37251 BCM_IF_ERROR_RETURN(rv); 37252 } else 37253 #endif /* BCM_TRIDENT3_SUPPORT */ 37254 { 37255 return BCM_E_UNAVAIL; 37256 } 37257 } else 37258 #endif /* BCM_TOMAHAWK_SUPPORT */ 37259 { 37260 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 37261 rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent); 37262 BCM_IF_ERROR_RETURN(rv); 37263 37264 #if defined (BCM_TOMAHAWK3_SUPPORT) 37265 if (soc_feature(unit, soc_feature_th3_style_fp)) { 37266 if (_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) { 37267 *data = (((hw_data & 0x2) >> 1) | ((hw_data & 0x1) << 1)); 37268 *mask = (((hw_mask & 0x2) >> 1) | ((hw_mask & 0x1) << 1)); 37269 } else { 37270 *data = hw_data; 37271 *mask = hw_mask; 37272 } 37273 } else 37274 #endif 37275 { 37276 if (((soc_feature(unit, soc_feature_field_qual_vlanformat_reverse)) || 37277 (soc_feature(unit, soc_feature_field_multi_stage))) && 37278 ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) || 37279 (SOC_IS_TRX(unit)))) { 37280 *data = (((hw_data & 0x2) >> 1) | ((hw_data & 0x1) << 1)); 37281 *mask = (((hw_mask & 0x2) >> 1) | ((hw_mask & 0x1) << 1)); 37282 } else 37283 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 37284 { 37285 *data = hw_data; 37286 *mask = hw_mask; 37287 } 37288 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 37289 } 37290 #endif 37291 37292 } 37293 37294 return (rv); 37295 } 37296 37297 /* 37298 * Function: 37299 * _field_range_dump 37300 * 37301 * Purpose: 37302 * Show contents of a range checker 37303 * 37304 * Parameters: 37305 * fr - range checker structure pointer 37306 * 37307 * Returns: 37308 * Nothing. 37309 */ 37310 void 37311 _field_range_dump(const char *pfx, _field_range_t *fr) 37312 { 37313 LOG_CLI((BSL_META("%s: Range ID=%d, flag=%#x, min=%d, max=%d, hw_index=%d(%#x), "), 37314 pfx, fr->rid, fr->flags, fr->min, fr->max, fr->hw_index, 37315 fr->hw_index)); 37316 LOG_CLI((BSL_META("style=BCM56504\n"))); 37317 } 37318 37319 /* 37320 * Function: 37321 * _field_entry_phys_dump 37322 * 37323 * Purpose: 37324 * Show contents of a physical entry structure 37325 * 37326 * Parameters: 37327 * unit - BCM device number 37328 * f_ent - Physical entry to dump 37329 * entry_part - Field entry part. 37330 * Returns: 37331 * Nothing. 37332 */ 37333 void 37334 _field_entry_phys_dump(int unit, _field_entry_t *f_ent, uint8 entry_part) 37335 { 37336 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 37337 int idx; 37338 int idx_max; 37339 int qual_idx; 37340 int free_tcam = FALSE; 37341 uint32 width; 37342 _field_group_t *fg; 37343 _bcm_field_qual_data_t q_data; 37344 _bcm_field_qual_data_t q_mask; 37345 _bcm_field_qual_offset_t *q_offset; 37346 char *ip_type_str[] = BCM_FIELD_IPTYPE_STRINGS; 37347 int rv; 37348 #if defined(BCM_TRX_SUPPORT) 37349 int range_check_valid = 0; 37350 #endif /* !BCM_TRX_SUPPORT */ 37351 37352 LOG_CLI((BSL_META_U(unit, 37353 " slice=%d, slice_idx=%#x, part =%d prio=%#x, flags=%#x, "), 37354 f_ent->fs->slice_number, f_ent->slice_idx, entry_part, 37355 f_ent->prio, f_ent->flags)); 37356 if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) { 37357 LOG_CLI((BSL_META_U(unit, 37358 "Not installed\n"))); 37359 } else { 37360 LOG_CLI((BSL_META_U(unit, 37361 "Installed, "))); 37362 37363 if (!(f_ent->flags & _FP_ENTRY_ENABLED)) { 37364 LOG_CLI((BSL_META_U(unit, 37365 "Disabled"))); 37366 } 37367 else { 37368 LOG_CLI((BSL_META_U(unit, 37369 "Enabled"))); 37370 } 37371 if (f_ent->flags & _FP_ENTRY_DIRTY) { 37372 LOG_CLI((BSL_META_U(unit, 37373 ", Dirty"))); 37374 } 37375 if (f_ent->flags & _FP_ENTRY_OAM_STAT_VALID) { 37376 LOG_CLI((BSL_META_U(unit, 37377 ", OamStatValid"))); 37378 } 37379 else { 37380 LOG_CLI((BSL_META_U(unit, 37381 "\n"))); 37382 } 37383 } 37384 37385 if ((NULL == f_ent->tcam.key)) { 37386 free_tcam = TRUE; 37387 } 37388 37389 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent); 37390 if (BCM_FAILURE(rv)) { 37391 LOG_CLI((BSL_META_U(unit, 37392 "\nUnit (%d) Entry (%d) tcam key read failure.\n"), 37393 unit, f_ent->eid)); 37394 return; 37395 } 37396 37397 LOG_CLI((BSL_META_U(unit, 37398 " tcam: color_indep=%d, "), 37399 ((f_ent->flags & _FP_ENTRY_COLOR_INDEPENDENT) ? 1 : 0))); 37400 37401 37402 37403 fg = f_ent->group; 37404 idx = _FP_ENTRY_TYPE_DEFAULT; 37405 37406 #if defined(BCM_TRIDENT2_SUPPORT) 37407 if (SOC_IS_TD2_TT2(unit) || 37408 soc_feature(unit, soc_feature_field_multi_pipe_support)) { 37409 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 37410 if (f_ent->efp_key_match_type) { 37411 idx = _FP_ENTRY_TYPE_1; 37412 } else { 37413 idx = _FP_ENTRY_TYPE_0; 37414 } 37415 } 37416 } 37417 #endif 37418 37419 q_arr = &(fg->qual_arr[idx][entry_part]); 37420 for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) { 37421 idx_max = -1; 37422 q_offset = q_arr->offset_arr + qual_idx; 37423 37424 /* 37425 * There is no value associated with zero width qualifiers 37426 * (Stage, Ip4 etc) just print the name. 37427 */ 37428 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width); 37429 if (0 == width) { 37430 switch (q_arr->qid_arr[qual_idx]) { 37431 case bcmFieldQualifyInPorts: 37432 case bcmFieldQualifyInPort: 37433 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_TRX_SUPPORT) 37434 if (BCM_PBMP_NOT_NULL(f_ent->pbmp.mask)) { 37435 char pfmt[SOC_PBMP_FMT_LEN]; 37436 bcm_pbmp_t lb_pbm; 37437 bcm_pbmp_t mask_pbm; 37438 /* Remove loopback port from ipbm mask */ 37439 BCM_PBMP_CLEAR(lb_pbm); 37440 BCM_PBMP_ASSIGN(mask_pbm, f_ent->pbmp.mask); 37441 BCM_PBMP_OR(lb_pbm, PBMP_LB(unit)); 37442 if (BCM_PBMP_NOT_NULL(lb_pbm)) { 37443 BCM_PBMP_REMOVE(mask_pbm, PBMP_LB(unit)); 37444 } 37445 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC) 37446 /* Remove MACSEC Port from IPBM mask */ 37447 if (soc_feature(unit, soc_feature_xflow_macsec)) { 37448 bcm_pbmp_t macsec_pbm; 37449 BCM_PBMP_CLEAR(macsec_pbm); 37450 BCM_PBMP_OR(macsec_pbm, PBMP_MACSEC_ALL(unit)); 37451 if (BCM_PBMP_NOT_NULL(macsec_pbm)) { 37452 BCM_PBMP_REMOVE(mask_pbm, PBMP_MACSEC_ALL(unit)); 37453 } 37454 } 37455 #endif 37456 37457 LOG_CLI((BSL_META_U(unit, 37458 "\n %s "), 37459 _field_qual_name(q_arr->qid_arr[qual_idx]))); 37460 LOG_CLI((BSL_META_U(unit, 37461 "\n DATA="))); 37462 LOG_CLI((BSL_META_U(unit, 37463 "%s"), 37464 SOC_PBMP_FMT(f_ent->pbmp.data, pfmt))); 37465 LOG_CLI((BSL_META_U(unit, 37466 "\n MASK="))); 37467 LOG_CLI((BSL_META_U(unit, 37468 "%s"), 37469 SOC_PBMP_FMT(mask_pbm, pfmt))); 37470 } 37471 #endif 37472 break; 37473 case bcmFieldQualifyHiGig: 37474 if (f_ent->tcam.higig_mask) { 37475 LOG_CLI((BSL_META_U(unit, 37476 "\n %s "), 37477 _field_qual_name(q_arr->qid_arr[qual_idx]))); 37478 LOG_CLI((BSL_META_U(unit, 37479 "\n DATA= %d"), 37480 f_ent->tcam.higig)); 37481 LOG_CLI((BSL_META_U(unit, 37482 "\n MASK= %d"), 37483 f_ent->tcam.higig_mask)); 37484 } 37485 break; 37486 case bcmFieldQualifyIpType: 37487 if ((bcmFieldIpTypeAny != f_ent->tcam.ip_type) && 37488 (bcmFieldIpTypeCount > f_ent->tcam.ip_type)) { 37489 LOG_CLI((BSL_META_U(unit, 37490 "\n %s "), 37491 _field_qual_name(q_arr->qid_arr[qual_idx]))); 37492 LOG_CLI((BSL_META_U(unit, 37493 "\n DATA= %s"), 37494 ip_type_str[f_ent->tcam.ip_type])); 37495 } 37496 break; 37497 default: 37498 LOG_CLI((BSL_META_U(unit, 37499 "\n %s "), 37500 _field_qual_name(q_arr->qid_arr[qual_idx]))); 37501 } 37502 continue; 37503 } else { 37504 #if defined(BCM_FIREBOLT2_SUPPORT) 37505 /* 37506 * Although FB2 has drop qualifier - 37507 * Drop bit is always present in the tcam 37508 * ancestor of the fixed key. 37509 */ 37510 if ((bcmFieldQualifyDrop == q_arr->qid_arr[qual_idx]) && 37511 (SOC_IS_FIREBOLT2(unit))) { 37512 if (f_ent->tcam.drop_mask) { 37513 LOG_CLI((BSL_META_U(unit, 37514 "\n %s "), 37515 _field_qual_name(q_arr->qid_arr[qual_idx]))); 37516 LOG_CLI((BSL_META_U(unit, 37517 "\n DATA= %d"), 37518 f_ent->tcam.drop)); 37519 LOG_CLI((BSL_META_U(unit, 37520 "\n MASK= %d"), 37521 f_ent->tcam.drop_mask)); 37522 } 37523 continue; 37524 } 37525 #endif /* BCM_FIREBOLT2_SUPPORT */ 37526 } 37527 37528 _FP_QUAL_DATA_CLEAR(q_data); 37529 _FP_QUAL_DATA_CLEAR(q_mask); 37530 /* Read qualifier match value and mask. */ 37531 rv = _bcm_field_qual_value_get(unit, q_offset, f_ent, q_data, q_mask); 37532 if (BCM_FAILURE(rv)) { 37533 return; 37534 } 37535 37536 /* Check if qualifier was installed. */ 37537 for (idx = 7; idx >= 0; idx--) { 37538 if (q_mask[idx] != 0) { 37539 idx_max = idx; 37540 break; 37541 } 37542 } 37543 37544 #if defined(BCM_TRX_SUPPORT) 37545 if ((bcmFieldQualifyRangeCheck == q_arr->qid_arr[qual_idx]) && 37546 (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassPort) || 37547 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassL3) || 37548 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassVPort) || 37549 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassL2))) { 37550 for (idx = idx_max; idx >= 0; idx--) { 37551 if (0 != (q_mask[idx] & 0xffffff)) { 37552 range_check_valid = 1; 37553 } 37554 } 37555 if (0 == range_check_valid) { 37556 continue; 37557 } 37558 } 37559 #endif /* !BCM_TRX_SUPPORT */ 37560 37561 if (idx_max >= 0) { 37562 int i; 37563 LOG_CLI((BSL_META_U(unit, 37564 "\n %s "), 37565 _field_qual_name(q_arr->qid_arr[qual_idx]))); 37566 for (i = 0; i < q_offset->num_offsets; i++) { 37567 if (0 != q_offset->width[i]) { 37568 LOG_CLI((BSL_META_U(unit, 37569 "\n Offset%d: %d Width%d: %d "), 37570 i, q_offset->offset[i], i, q_offset->width[i])); 37571 } 37572 } 37573 37574 LOG_CLI((BSL_META_U(unit, 37575 "\n DATA=0x"))); 37576 if (SOC_IS_TRX(unit) 37577 && (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) 37578 && (bcmFieldQualifyInnerVlan == q_arr->qid_arr[qual_idx])) { 37579 /* EFP InnerVlan hardware format is different from IFP. 37580 */ 37581 int32 data = 0; 37582 for (idx = 0; idx <= idx_max; idx++) { 37583 data = ((q_data[idx] & 0xfff0) >> 4) | 37584 ((q_data[idx] & 0xf) << 12); 37585 LOG_CLI((BSL_META_U(unit, 37586 "%08x "), data)); 37587 } 37588 } else { 37589 uint32 data = 0; 37590 uint32 mask = 0; 37591 for (idx = idx_max; idx >= 0; idx--) { 37592 data = q_data[idx]; 37593 mask = q_mask[idx]; 37594 37595 if (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) { 37596 /* Check if HW packet_res must be remmaped for API use */ 37597 if (bcmFieldQualifyPacketRes == q_arr->qid_arr[qual_idx]) { 37598 int (*func)(int, bcm_field_entry_t, uint32 *, uint32 *) 37599 = _field_qualify_PacketRes_get; 37600 37601 #if defined(BCM_TRIDENT2_SUPPORT) 37602 if (SOC_IS_TD2_TT2(unit)) { 37603 func = _bcm_field_td2_qualify_PacketRes_get; 37604 } else 37605 #endif /* BCM_TRIDENT2_SUPPORT */ 37606 #if defined(BCM_TRIUMPH3_SUPPORT) 37607 if (SOC_IS_TRIUMPH3(unit)) { 37608 func = _bcm_field_tr3_qualify_PacketRes_get; 37609 } else 37610 #endif /* BCM_TRIUMPH3_SUPPORT */ 37611 #if defined(BCM_KATANA_SUPPORT) 37612 if (SOC_IS_KATANA(unit)) { 37613 func = _bcm_field_kt_qualify_PacketRes_get; 37614 } else 37615 #endif /* BCM_KATANA_SUPPORT */ 37616 { 37617 #if defined (BCM_KATANA2_SUPPORT) 37618 if (SOC_IS_KATANA2(unit)) { 37619 func = _bcm_field_kt2_qualify_PacketRes_get; 37620 } 37621 #endif /* BCM_KATANA2_SUPPORT */ 37622 } 37623 37624 (*func)(unit, f_ent->eid, &data, &mask); 37625 q_mask[idx] = mask; 37626 } 37627 } 37628 LOG_CLI((BSL_META_U(unit, 37629 "%08x "), data)); 37630 } 37631 } 37632 37633 LOG_CLI((BSL_META_U(unit, 37634 "\n MASK=0x"))); 37635 if (SOC_IS_TRX(unit) 37636 && (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) 37637 && (bcmFieldQualifyInnerVlan == q_arr->qid_arr[qual_idx])) { 37638 /* EFP InnerVlan hardware format is different from IFP. 37639 */ 37640 int32 mask = 0; 37641 for (idx = 0; idx <= idx_max; idx++) { 37642 mask = ((q_mask[idx] & 0xfff0) >> 4) | 37643 ((q_mask[idx] & 0xf) << 12); 37644 LOG_CLI((BSL_META_U(unit, 37645 "%08x "), mask)); 37646 } 37647 } else { 37648 for (idx = idx_max; idx >= 0; idx--) { 37649 LOG_CLI((BSL_META_U(unit, 37650 "%08x "), q_mask[idx])); 37651 } 37652 } 37653 } 37654 } 37655 37656 if (free_tcam) { 37657 if (NULL != f_ent->tcam.key) { 37658 sal_free(f_ent->tcam.key); 37659 sal_free(f_ent->tcam.mask); 37660 } 37661 if (f_ent->flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 37662 if (NULL != f_ent->extra_tcam.key) { 37663 sal_free(f_ent->extra_tcam.key); 37664 sal_free(f_ent->extra_tcam.mask); 37665 } 37666 } 37667 f_ent->tcam.key = f_ent->tcam.mask = 37668 f_ent->extra_tcam.key = f_ent->extra_tcam.mask = NULL; 37669 #if defined(BCM_TRIDENT2_SUPPORT) 37670 if (SOC_IS_TD2_TT2(unit) && 37671 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) { 37672 37673 if (NULL != f_ent->key_match_tcam.key) { 37674 sal_free(f_ent->key_match_tcam.key); 37675 sal_free(f_ent->key_match_tcam.mask); 37676 } 37677 f_ent->key_match_tcam.key = f_ent->key_match_tcam.mask = NULL; 37678 } 37679 #endif 37680 free_tcam = FALSE; 37681 } 37682 37683 LOG_CLI((BSL_META_U(unit, 37684 "\n"))); 37685 } 37686 37687 37688 /* 37689 * Function: 37690 * _field_selcode_dump 37691 * Purpose: 37692 * Output a set of field selects code. 37693 */ 37694 void 37695 _field_selcode_dump(int unit, char *prefix, _field_sel_t *sel_codes, 37696 char *suffix, _field_stage_id_t stage_id) 37697 { 37698 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 37699 char *efp_key_type_str[] = _BCM_EFP_FIELD_KEY_STRINGS; 37700 #endif 37701 if (NULL == sel_codes) { 37702 return; 37703 } 37704 37705 LOG_CLI((BSL_META_U(unit, 37706 "%s{"), (prefix == NULL) ? "" : prefix)); 37707 if (_FP_SELCODE_DONT_CARE != sel_codes->fpf1) { 37708 LOG_CLI((BSL_META_U(unit, 37709 "\n FPF1=%d"), sel_codes->fpf1)); 37710 } 37711 if (_FP_SELCODE_DONT_CARE != sel_codes->fpf2) { 37712 LOG_CLI((BSL_META_U(unit, 37713 "\n FPF2=%d"), sel_codes->fpf2)); 37714 } 37715 if (_FP_SELCODE_DONT_CARE != sel_codes->fpf3) { 37716 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 37717 if (_BCM_FIELD_STAGE_EGRESS == stage_id) { 37718 LOG_CLI((BSL_META_U(unit, 37719 "\n FPF3=%s"), efp_key_type_str[sel_codes->fpf3])); 37720 } else 37721 #endif 37722 { 37723 LOG_CLI((BSL_META_U(unit, 37724 "\n FPF3=%d"), sel_codes->fpf3)); 37725 } 37726 } 37727 if (_FP_SELCODE_DONT_CARE != sel_codes->fpf4) { 37728 LOG_CLI((BSL_META_U(unit, 37729 "\n FPF4=%d"), sel_codes->fpf4)); 37730 } 37731 if (_FP_SELCODE_DONT_CARE != sel_codes->src_class_sel) { 37732 LOG_CLI((BSL_META_U(unit, 37733 "\n SourceClassSelect=%d"), 37734 sel_codes->src_class_sel)); 37735 } 37736 if (_FP_SELCODE_DONT_CARE != sel_codes->dst_class_sel) { 37737 LOG_CLI((BSL_META_U(unit, 37738 "\n DestinationClassSelect=%d"), 37739 sel_codes->dst_class_sel)); 37740 } 37741 if (_FP_SELCODE_DONT_CARE != sel_codes->intf_class_sel) { 37742 LOG_CLI((BSL_META_U(unit, 37743 "\n InterfaceClassSelect=%d"), 37744 sel_codes->intf_class_sel)); 37745 } 37746 if (_FP_SELCODE_DONT_CARE != sel_codes->loopback_type_sel) { 37747 LOG_CLI((BSL_META_U(unit, 37748 "\n LoopbackTypeSelect=%d"), 37749 sel_codes->loopback_type_sel)); 37750 } 37751 if (_FP_SELCODE_DONT_CARE != sel_codes->egr_dest_port_f1_sel) { 37752 LOG_CLI((BSL_META_U(unit, 37753 "\n EgrDstPortF1Select=%d"), 37754 sel_codes->egr_dest_port_f1_sel)); 37755 } 37756 if (_FP_SELCODE_DONT_CARE != sel_codes->egr_dest_port_f5_sel) { 37757 LOG_CLI((BSL_META_U(unit, 37758 "\n EgrDstPortF5Select=%d"), 37759 sel_codes->egr_dest_port_f5_sel)); 37760 } 37761 if (_FP_SELCODE_DONT_CARE != sel_codes->ingress_entity_sel) { 37762 LOG_CLI((BSL_META_U(unit, 37763 "\n IngressEntitySelect=%d"), 37764 sel_codes->ingress_entity_sel)); 37765 } 37766 if (_FP_SELCODE_DONT_CARE != sel_codes->src_entity_sel) { 37767 LOG_CLI((BSL_META_U(unit, 37768 "\n SrcEntitySelect=%d"), 37769 sel_codes->src_entity_sel)); } 37770 37771 if (_FP_SELCODE_DONT_CARE != sel_codes->dst_fwd_entity_sel) { 37772 LOG_CLI((BSL_META_U(unit, 37773 "\n DestinationEntitySelect=%d"), 37774 sel_codes->dst_fwd_entity_sel)); 37775 } 37776 if (_FP_SELCODE_DONT_CARE != sel_codes->fwd_field_sel) { 37777 LOG_CLI((BSL_META_U(unit, 37778 "\n ForwardingFieldSelect=%d"), 37779 sel_codes->fwd_field_sel)); 37780 } 37781 if (_FP_SELCODE_DONT_CARE != sel_codes->ttl_class_sel) { 37782 LOG_CLI((BSL_META_U(unit, 37783 "\n TtlClassSelect=%d"), 37784 sel_codes->ttl_class_sel)); 37785 } 37786 if (_FP_SELCODE_DONT_CARE != sel_codes->tos_class_sel) { 37787 LOG_CLI((BSL_META_U(unit, 37788 "\n TosClassSelect=%d"), 37789 sel_codes->tos_class_sel)); 37790 } 37791 if (_FP_SELCODE_DONT_CARE != sel_codes->tcp_class_sel) { 37792 LOG_CLI((BSL_META_U(unit, 37793 "\n TcpClassSelect=%d"), 37794 sel_codes->tcp_class_sel)); 37795 } 37796 if (_FP_SELCODE_DONT_CARE != sel_codes->ip_header_sel) { 37797 LOG_CLI((BSL_META_U(unit, 37798 "\n IpHeaderSelect=%s"), 37799 (sel_codes->ip_header_sel) ? "Inner" : "Outer")); 37800 } 37801 if (_FP_SELCODE_DONT_CARE != sel_codes->inner_vlan_overlay) { 37802 LOG_CLI((BSL_META_U(unit, 37803 "\n InnerVlanOverlaySelect=%d"), 37804 sel_codes->inner_vlan_overlay)); 37805 } 37806 if (_FP_SELCODE_DONT_CARE != sel_codes->aux_tag_1_sel) { 37807 LOG_CLI((BSL_META_U(unit, 37808 "\n AuxTag1Select=%d"), 37809 sel_codes->aux_tag_1_sel)); 37810 } 37811 if (_FP_SELCODE_DONT_CARE != sel_codes->aux_tag_2_sel) { 37812 LOG_CLI((BSL_META_U(unit, 37813 "\n AuxTag2Select=%d"), 37814 sel_codes->aux_tag_2_sel)); 37815 } 37816 if (_FP_SELCODE_DONT_CARE != sel_codes->oam_overlay_sel) { 37817 LOG_CLI((BSL_META_U(unit, 37818 "\n OamOverlaySelect=%d"), 37819 sel_codes->oam_overlay_sel)); 37820 } 37821 if (_FP_SELCODE_DONT_CARE != sel_codes->intraslice) { 37822 if (_FP_SELCODE_DONT_USE == sel_codes->intraslice) { 37823 LOG_CLI((BSL_META_U(unit, 37824 "\n Intraslice=%s\n"), 37825 "Primary slice.")); 37826 } else { 37827 LOG_CLI((BSL_META_U(unit, 37828 "\n Intraslice=%d\n"), 37829 sel_codes->intraslice)); 37830 } 37831 } 37832 return; 37833 } 37834 37835 37836 /* 37837 * Function: 37838 * _field_slice_dump 37839 * Purpose: 37840 * Output a slice worth of data, including any entries in the slice. 37841 */ 37842 void 37843 _field_slice_dump(int unit, char *prefix, _field_group_t *fg, 37844 _field_slice_t *fs, char *suffix) 37845 { 37846 #if defined(BCM_TOMAHAWK_SUPPORT) 37847 if (soc_feature(unit, soc_feature_field_multi_pipe_support) 37848 && (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) { 37849 _field_stage_t *stage_fc; /* Stage field control structure.*/ 37850 int slice = 0; /* Slice Count Iterator. */ 37851 _field_slice_t *fslice; /*slice structure */ 37852 int free_entries_count = 0; /*free entry count */ 37853 int total_entries_count = 0; /* total entry count */ 37854 int rv; 37855 /* Get field group stage control structure. */ 37856 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 37857 if (BCM_FAILURE(rv)) { 37858 return; 37859 } 37860 /* Retreive Slice Instance. */ 37861 fslice = stage_fc->slices[fg->instance]; 37862 /* Calculate free entry count. */ 37863 for (slice = 0; slice < stage_fc->tcam_slices; slice++) { 37864 free_entries_count += fslice[slice].free_count; 37865 total_entries_count += fslice[slice].entry_count; 37866 } 37867 37868 LOG_CLI((BSL_META_U(unit, 37869 "%s{"), (prefix == NULL) ? "" : prefix)); 37870 LOG_CLI((BSL_META_U(unit, 37871 "slice_number=%d, "), fs->slice_number)); 37872 LOG_CLI((BSL_META_U(unit, 37873 "Entry count=%d(%#x), "), 37874 total_entries_count, total_entries_count)); 37875 LOG_CLI((BSL_META_U(unit, 37876 "Entry free=%d(%#x)"), 37877 free_entries_count, free_entries_count)); 37878 LOG_CLI((BSL_META_U(unit, 37879 "},%s"), (suffix == NULL) ? "" : suffix)); 37880 } else 37881 #endif 37882 { 37883 while (fs != NULL) { 37884 LOG_CLI((BSL_META_U(unit, 37885 "%s{"), (prefix == NULL) ? "" : prefix)); 37886 LOG_CLI((BSL_META_U(unit, 37887 "slice_number=%d, "), fs->slice_number)); 37888 LOG_CLI((BSL_META_U(unit, 37889 "Entry count=%d(%#x), "), 37890 fs->entry_count, fs->entry_count)); 37891 LOG_CLI((BSL_META_U(unit, 37892 "Entry free=%d(%#x)"), 37893 fs->free_count, fs->free_count)); 37894 LOG_CLI((BSL_META_U(unit, 37895 "},%s"), (suffix == NULL) ? "" : suffix)); 37896 fs = fs->next; 37897 } 37898 } 37899 } 37900 37901 /* 37902 * Function: 37903 * _field_qual_list_dump 37904 * Purpose: 37905 * Output qualiers set in 'qset'. 37906 */ 37907 void 37908 _field_qual_list_dump(char *prefix, _field_group_t *fg, uint8 entry_part, char *suffix) 37909 { 37910 37911 _bcm_field_group_qual_t *q_arr; /* Qualifiers array. */ 37912 int first_print = 1; 37913 int idx; 37914 37915 LOG_CLI((BSL_META("%s{"), (prefix == NULL) ? "" : prefix)); 37916 q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][entry_part]); 37917 /* Output the qualifier info list*/ 37918 for (idx = 0; idx < q_arr->size; idx++) { 37919 LOG_CLI((BSL_META("%s%s"), 37920 (first_print ? "" : "->"), 37921 _field_qual_name(q_arr->qid_arr[idx]))); 37922 first_print = 0; 37923 } 37924 LOG_CLI((BSL_META("}%s"), (suffix == NULL) ? "" : suffix)); 37925 } 37926 37927 /* 37928 * Function: 37929 * _field_qset_dump 37930 * Purpose: 37931 * Output qualiers set in 'qset'. 37932 */ 37933 void 37934 _field_qset_dump(char *prefix, bcm_field_qset_t qset, char *suffix) 37935 { 37936 int qual; 37937 int idx; 37938 int first_qual = 1, first_udf_id = 1; 37939 37940 if (prefix == NULL) { 37941 prefix = ""; 37942 } 37943 if (suffix == NULL) { 37944 suffix = ""; 37945 } 37946 37947 LOG_CLI((BSL_META("%s{"), prefix)); 37948 for (qual = 0; qual < _bcmFieldQualifyCount; qual++) { 37949 if (BCM_FIELD_QSET_TEST(qset, qual)) { 37950 LOG_CLI((BSL_META("%s%s"), 37951 (first_qual ? "" : ", "), _field_qual_name(qual))); 37952 first_qual = 0; 37953 } 37954 } 37955 37956 for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) { 37957 if (!SHR_BITGET(qset.udf_map, idx)) { 37958 continue; 37959 } 37960 LOG_CLI((BSL_META("%s%d"), 37961 (first_udf_id ? " : udf_id={" : ", "), idx)); 37962 first_udf_id = 0; 37963 } 37964 if (first_udf_id == 0) { 37965 LOG_CLI((BSL_META("}"))); 37966 } 37967 37968 LOG_CLI((BSL_META("}%s"), suffix)); 37969 } 37970 37971 /* 37972 * Function: 37973 * _field_qset_debug 37974 * Purpose: 37975 * Output qualier set in 'qset' for debug mode only. 37976 */ 37977 void 37978 _field_qset_debug(bcm_field_qset_t qset) 37979 { 37980 int qual; 37981 int first_qual = 1; 37982 37983 LOG_VERBOSE(BSL_LS_BCM_FP, 37984 (BSL_META("{"))); 37985 for (qual = 0; qual < _bcmFieldQualifyCount; qual++) { 37986 if (BCM_FIELD_QSET_TEST(qset, qual)) { 37987 LOG_VERBOSE(BSL_LS_BCM_FP, 37988 (BSL_META("%s%s"), 37989 (first_qual ? "" : "), "), 37990 _field_qual_name(qual))); 37991 first_qual = 0; 37992 } 37993 } 37994 LOG_VERBOSE(BSL_LS_BCM_FP, 37995 (BSL_META("}"))); 37996 } 37997 37998 /* 37999 * Function: 38000 * _field_aset_dump 38001 * Purpose: 38002 * Output qualiers set in 'aset'. 38003 */ 38004 #if defined(BCM_TOMAHAWK_SUPPORT) 38005 void 38006 _field_aset_dump(char *prefix, _bcm_field_aset_t aset, char *suffix) 38007 #else 38008 void 38009 _field_aset_dump(char *prefix, bcm_field_aset_t aset, char *suffix) 38010 #endif 38011 { 38012 int action; 38013 int first_action = 1; 38014 38015 if (prefix == NULL) { 38016 prefix = ""; 38017 } 38018 if (suffix == NULL) { 38019 suffix = ""; 38020 } 38021 38022 LOG_CLI((BSL_META("%s{"), prefix)); 38023 for (action = 0; action < bcmFieldActionCount; action++) { 38024 if (BCM_FIELD_ASET_TEST(aset, action)) { 38025 LOG_CLI((BSL_META("%s%s"), 38026 (first_action ? "" : ", "), _field_action_name(action))); 38027 first_action = 0; 38028 } 38029 } 38030 38031 LOG_CLI((BSL_META("}%s"), suffix)); 38032 } 38033 38034 38035 /* 38036 * Function: 38037 * _field_counter_dump 38038 * Purpose: 38039 * Output fields in a _field_counter_s struct. 38040 */ 38041 int 38042 _field_stat_dump(int unit, const _field_entry_t *f_ent) 38043 { 38044 _field_stat_t *f_st; 38045 int idx; 38046 int rv = BCM_E_NONE; 38047 char *sname[] = BCM_FIELD_STAT; 38048 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 38049 char *aname[] = BCM_FIELD_STAT_ACTION; 38050 #endif 38051 38052 /* Input parameters check. */ 38053 if (f_ent == NULL) { 38054 return (BCM_E_PARAM); 38055 } 38056 38057 if (f_ent->statistic.flags & _FP_ENTRY_STAT_VALID) { 38058 rv = _bcm_field_stat_get (unit, f_ent->statistic.sid, &f_st); 38059 if (BCM_FAILURE(rv)) { 38060 return (rv); 38061 } 38062 38063 38064 LOG_CLI((BSL_META_U(unit, 38065 "{stat id %d slice = %d idx=%d entries=%d}"), 38066 f_st->sid, f_st->pool_index, f_st->hw_index, 38067 f_st->hw_entry_count)); 38068 for (idx = 0; idx < f_st->nstat; idx++) { 38069 /* coverity[mixed_enums] */ 38070 if (f_st->stat_arr[idx] < (bcm_field_stat_t)_bcmFieldStatCount) { 38071 LOG_CLI((BSL_META_U(unit, 38072 "{%s}"), sname[f_st->stat_arr[idx]])); 38073 } 38074 } 38075 } else { 38076 LOG_CLI((BSL_META_U(unit, 38077 "NULL"))); 38078 } 38079 38080 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 38081 if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || 38082 soc_feature(unit, soc_feature_flex_stat_compaction_support)) { 38083 LOG_CLI((BSL_META_U(unit, "\r\n"))); 38084 LOG_CLI((BSL_META_U(unit, 38085 " Extended statistics="))); 38086 if (f_ent->statistic.flags & _FP_ENTRY_EXTENDED_STAT_VALID) { 38087 rv = _bcm_field_stat_get (unit, 38088 f_ent->statistic.extended_sid, &f_st); 38089 if (BCM_FAILURE(rv)) { 38090 return (rv); 38091 } 38092 38093 LOG_CLI((BSL_META_U(unit, 38094 "\r\n {stat id %d action = %s" 38095 " slice = %d idx=%d entries=%d}"), 38096 f_st->sid, aname[f_ent->statistic.stat_action], 38097 f_st->pool_index, f_st->hw_index, 38098 f_st->hw_entry_count)); 38099 for (idx = 0; idx < f_st->nstat; idx++) { 38100 /* coverity[mixed_enums] */ 38101 if (f_st->stat_arr[idx] < (bcm_field_stat_t)_bcmFieldStatCount){ 38102 LOG_CLI((BSL_META_U(unit, 38103 "{%s}"), sname[f_st->stat_arr[idx]])); 38104 } 38105 } 38106 } else { 38107 LOG_CLI((BSL_META_U(unit, 38108 "NULL"))); 38109 } 38110 } 38111 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 38112 return (rv); 38113 } 38114 38115 /* 38116 * Function: 38117 * _field_policers_dump 38118 * Purpose: 38119 38120 * Output meter data for given entry. 38121 */ 38122 void 38123 _field_policers_dump(int unit, _field_entry_t *f_ent) 38124 { 38125 bcm_policer_t policer_id; /* Policer id. */ 38126 _field_policer_t *f_pl; /* Internal policer descriptor. */ 38127 int idx; /* Policers levels iterator. */ 38128 int rv; /* Operation return status. */ 38129 uint8 isPolicerDirty; /* Verify if policer Dirty */ 38130 38131 for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) { 38132 /* Read policer id from entry. */ 38133 rv = bcm_esw_field_entry_policer_get(unit, f_ent->eid, 38134 idx, &policer_id); 38135 if (BCM_E_NOT_FOUND == rv) { 38136 continue; 38137 } 38138 if (BCM_FAILURE(rv)) { 38139 return; 38140 } 38141 38142 /* Get policer reference count. */ 38143 rv = _bcm_field_policer_get(unit, policer_id, &f_pl); 38144 if (BCM_FAILURE(rv)) { 38145 return; 38146 } 38147 38148 if ((f_pl->hw_flags & _FP_POLICER_DIRTY) 38149 || (f_ent->flags & _FP_ENTRY_DIRTY)) { 38150 isPolicerDirty = TRUE; 38151 } else { 38152 isPolicerDirty = FALSE; 38153 } 38154 38155 LOG_CLI((BSL_META_U(unit, 38156 "{pid=%#x, level=%#x, "), f_pl->pid, f_pl->level)); 38157 38158 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 38159 LOG_CLI((BSL_META_U(unit, 38160 "peak_kbits_sec=%#x, peak_kbits_burst=%#x,"), 38161 f_pl->cfg.pkbits_sec, f_pl->cfg.pkbits_burst)); 38162 } 38163 38164 if ((bcmPolicerModePeak != f_pl->cfg.mode)) { 38165 LOG_CLI((BSL_META_U(unit, 38166 " commit_kbits_sec=%#x, commit_kbits_burst=%#x, "), 38167 f_pl->cfg.ckbits_sec, f_pl->cfg.ckbits_burst)); 38168 } 38169 38170 LOG_CLI((BSL_META_U(unit, 38171 "PacketBased=%#x,"), 38172 (f_pl->cfg.flags & BCM_POLICER_MODE_PACKETS) ? 1 : 0)); 38173 38174 LOG_CLI((BSL_META_U(unit, 38175 " mode=%#x, entries=%d, %s}"), 38176 f_pl->cfg.mode, f_pl->sw_ref_count, 38177 (isPolicerDirty) ? "Dirty" : "Clean")); 38178 } 38179 } 38180 38181 /* 38182 * Function: 38183 * _field_action_dump 38184 * Purpose: 38185 * Output fields in a _field_action_s struct. 38186 */ 38187 void 38188 _field_action_dump(const _field_action_t *fa) 38189 { 38190 if (fa == NULL) { 38191 LOG_CLI((BSL_META("NULL"))); 38192 } else { 38193 #if defined(BCM_TOMAHAWK_SUPPORT) 38194 /* 38195 * Manuplate EgressMirror to CopyToCpu Action for CTC WAR. 38196 */ 38197 if ((fa->action == bcmFieldActionMirrorEgress) && 38198 (fa->flags & _BCM_FIELD_ACTION_CTC_MANIPULATE_FLAG)) { 38199 LOG_CLI((BSL_META("{act=%s, param0=%d(%#x), param1=%d(%#x)," 38200 " param2=%d(%#x), param3=%d(%#x)}"), 38201 _field_action_name(bcmFieldActionCopyToCpu), fa->param[2], 38202 fa->param[2], fa->param[3], fa->param[3], 0, 0, 0, 0)); 38203 return; 38204 } 38205 #endif 38206 LOG_CLI((BSL_META("{act=%s, param0=%d(%#x), param1=%d(%#x), param2=%d(%#x), param3=%d(%#x)%s"), 38207 _field_action_name(fa->action), fa->param[0], fa->param[0], 38208 fa->param[1], fa->param[1], fa->param[2], fa->param[2], 38209 fa->param[3], fa->param[3], (fa->flags & _FP_ACTION_VALID) ? "" : ", Dirty")); 38210 #if defined(BCM_TOMAHAWK_SUPPORT) 38211 if (bcmFieldActionFabricEHAddOrUpdate == fa->action) { 38212 LOG_CLI((BSL_META("Extended_Header_Mask_Profile=%d,"), fa->hw_index)); 38213 } 38214 #endif 38215 LOG_CLI((BSL_META("}"))); 38216 38217 } 38218 } 38219 38220 /* 38221 * Function: 38222 * _field_group_status_dump 38223 * Purpose: 38224 * Output the fields in a bcm_field_group_status_s struct. 38225 */ 38226 void 38227 _field_group_status_dump(const bcm_field_group_status_t *gstat) 38228 { 38229 LOG_CLI((BSL_META("{prio_min=%d,"), gstat->prio_min)); 38230 LOG_CLI((BSL_META(" prio_max=%d,"), gstat->prio_max)); 38231 LOG_CLI((BSL_META(" entries_total=%d,"), gstat->entries_total)); 38232 LOG_CLI((BSL_META(" entries_free=%d,"), gstat->entries_free)); 38233 LOG_CLI((BSL_META("\n "))); 38234 LOG_CLI((BSL_META(" counters_total=%d,"), gstat->counters_total)); 38235 LOG_CLI((BSL_META(" counters_free=%d,"), gstat->counters_free)); 38236 LOG_CLI((BSL_META(" meters_total=%d,"), gstat->meters_total)); 38237 LOG_CLI((BSL_META(" meters_free=%d}"), gstat->meters_free)); 38238 } 38239 38240 38241 38242 38243 int 38244 _field_is_inited(int unit) 38245 { 38246 /* Make sure system was initialized. */ 38247 FIELD_IS_INIT(unit); 38248 return BCM_E_NONE; 38249 } 38250 38251 /* 38252 * Function: _bcm_field_linkscan_update 38253 * 38254 * Purpose: 38255 * Register with link scan thread to get port updates. 38256 * 38257 * Parameters: 38258 * unit - (IN) BCM device numberi 38259 * port - (OUT) Port 38260 * *portInfo - (OUT) Port Info Data Structure 38261 * 38262 * Returns: 38263 * BCM_E_NONE - Success 38264 */ 38265 void _bcm_field_linkscan_update(int unit, 38266 bcm_port_t port, 38267 bcm_port_info_t *portInfo) 38268 { 38269 int rc = 0; 38270 int isEntryDirty = 0; 38271 bcm_pbmp_t egrPortPbmp; 38272 _field_entry_t *f_ent; 38273 _field_control_t *fc; 38274 _field_entry_recover_egr_ports_t *egrPortDbEntry = NULL; 38275 _field_entry_recover_egr_ports_t *head; 38276 _field_egr_ports_recovery_t *f_egr_recovery = NULL; 38277 38278 rc = _field_egr_ports_recovery_control_get (unit, &f_egr_recovery); 38279 38280 if (rc != BCM_E_NONE) { 38281 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 38282 "FP (%d) RECOVERY_DB() not initialized\r\n"),unit)); 38283 return; 38284 } 38285 38286 if (f_egr_recovery == NULL) { 38287 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 38288 "FP (%d) RECOVERY_DB() Internal Error\r\n"),unit)); 38289 return; 38290 } 38291 38292 head = f_egr_recovery->entry_recover_egr_ports[port]; 38293 38294 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 38295 "FP (%d) Received update on port = %d en = %d linstat = %d\r\n"), 38296 unit, (int)port,portInfo->enable,portInfo->linkstatus)); 38297 38298 BCM_PBMP_CLEAR(egrPortPbmp); 38299 38300 /* Using the port (which the linkscan notified) as index, loop 38301 * through all the entries in the redirect_pbm_recovery database, 38302 * retrieve the egrPortPbmp configured in that entry and update the 38303 * pbmp based on the port's link status and then reinstall the 38304 * FP entry. 38305 */ 38306 FP_LOCK(unit); 38307 if (NULL != head) { 38308 rc = _field_control_get(unit, &fc); 38309 if (BCM_FAILURE(rc)) { 38310 FP_UNLOCK(unit); 38311 return; 38312 } 38313 38314 38315 egrPortDbEntry = head; 38316 while (egrPortDbEntry != NULL) { 38317 /* Set Global variable to inform that FP action is updated due 38318 to Link Scan Update and hence redirect_pbm_recovery database 38319 should not be modified */ 38320 _field_egr_ports_recovery_lock[unit] = 1; 38321 rc = bcm_esw_field_action_ports_get (unit, egrPortDbEntry->eid, 38322 bcmFieldActionEgressPortsAdd, &egrPortPbmp); 38323 if (rc != BCM_E_NONE) { 38324 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 38325 "FP (%d) RECOVERY_DB() bcm_field_action_ports_get failed \r\n"),unit)); 38326 _field_egr_ports_recovery_lock[unit] = 0; 38327 FP_UNLOCK(unit); 38328 return; 38329 } 38330 38331 if (portInfo->linkstatus == BCM_PORT_LINK_STATUS_UP) { 38332 BCM_PBMP_PORT_ADD (egrPortPbmp, port); 38333 } else { 38334 BCM_PBMP_PORT_REMOVE (egrPortPbmp, port); 38335 } 38336 38337 /* Get field control structure. Check if entry already installed 38338 * If so, reinstall the entry, else just update the fp entry action 38339 */ 38340 rc = _field_entry_get(unit, egrPortDbEntry->eid, 38341 _FP_ENTRY_PRIMARY, &f_ent); 38342 if (BCM_FAILURE(rc)) { 38343 _field_egr_ports_recovery_lock[unit] = 0; 38344 FP_UNLOCK(unit); 38345 return; 38346 } 38347 38348 isEntryDirty = (f_ent->flags & _FP_ENTRY_DIRTY); 38349 38350 rc = bcm_esw_field_action_remove (unit, egrPortDbEntry->eid, 38351 bcmFieldActionEgressPortsAdd); 38352 if (BCM_FAILURE(rc)) { 38353 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 38354 "FP (%d) RECOVERY_DB() bcm_field_action_remove failed"), 38355 unit)); 38356 _field_egr_ports_recovery_lock[unit] = 0; 38357 FP_UNLOCK(unit); 38358 return; 38359 } 38360 rc = bcm_esw_field_action_ports_add (unit, egrPortDbEntry->eid, 38361 bcmFieldActionEgressPortsAdd, egrPortPbmp); 38362 if (BCM_FAILURE(rc)) { 38363 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 38364 "FP (%d) RECOVERY_DB() bcm_field_action_ports_add failed"), 38365 unit)); 38366 _field_egr_ports_recovery_lock[unit] = 0; 38367 FP_UNLOCK(unit); 38368 return; 38369 } 38370 38371 /* Re-install Entry only when Entry is not Dirty*/ 38372 if (!isEntryDirty) { 38373 rc = bcm_esw_field_entry_reinstall (unit, egrPortDbEntry->eid); 38374 if (BCM_FAILURE(rc)) { 38375 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 38376 "FP (%d) RECOVERY_DB() bcm_field_entry_reinstall failed"), 38377 unit)); 38378 _field_egr_ports_recovery_lock[unit] = 0; 38379 FP_UNLOCK(unit); 38380 return; 38381 } 38382 } 38383 egrPortDbEntry = egrPortDbEntry->next; 38384 } 38385 _field_egr_ports_recovery_lock[unit] = 0; 38386 38387 } 38388 FP_UNLOCK(unit); 38389 return; 38390 } 38391 38392 38393 /* 38394 * Function: _bcm_field_control_EgressAutoExpanWithPolicer_set 38395 * 38396 * Purpose: 38397 * Set control status. 38398 * 38399 * Parameters: 38400 * unit - (IN) BCM device number. 38401 * fc - (IN/OUT) Field Control Structure. 38402 * state - (IN) State (0/1). 38403 * 38404 * Returns: 38405 * BCM_E_NONE - Success 38406 * BCM_E_INIT - BCM unit not initialized 38407 * BCM_E_PARAM - Flag state not valid on device 38408 */ 38409 int 38410 _bcm_field_control_EgressAutoExpanWithPolicer_set(int unit, 38411 _field_control_t *fc, uint32 state) 38412 { 38413 _field_stage_t *stage_fc = NULL; /* fc stage structure*/ 38414 _field_group_t *fg; /* Field group structure */ 38415 int slice_sz; /* Number of entries in a slice.*/ 38416 _field_slice_t *fs; /* Field slice structure. */ 38417 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 38418 int idx; /* Slice iteration index. */ 38419 38420 slice_sz = 0; 38421 /*currently supported only for TD2Plus */ 38422 if (!(SOC_IS_TRIDENT2PLUS(unit))) { 38423 return BCM_E_UNAVAIL; 38424 } 38425 38426 if (NULL == fc) { 38427 return (BCM_E_PARAM); 38428 } 38429 38430 if ((state != 0) && (state != 1)) { 38431 return BCM_E_PARAM; 38432 } 38433 BCM_IF_ERROR_RETURN 38434 (_field_stage_control_get(unit, _BCM_FIELD_STAGE_EGRESS, &stage_fc)); 38435 38436 if ((stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) || 38437 (fc->flags &_FP_POLICER_GROUP_SHARE_ENABLE) ) { 38438 return BCM_E_UNAVAIL; 38439 } 38440 38441 if( ((state == 0) && 38442 (!(fc->flags & _FP_AUTOEXPAND_WITH_POLICER))) || 38443 ((state == 1) && 38444 ((fc->flags & _FP_AUTOEXPAND_WITH_POLICER))) ) { 38445 /* do nothing and return */ 38446 return BCM_E_NONE; 38447 } 38448 fg = fc->groups; 38449 while (NULL != fg) { 38450 if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) { 38451 /* Egress group found. Check if the group 38452 * is autoexpanded or has policers attached 38453 */ 38454 fs = fg->slices; 38455 while (NULL != fs) { 38456 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 38457 for (idx = 0; idx < slice_sz; idx ++) { 38458 /* Find non-empty slot. */ 38459 if (NULL != fs->entries[idx]) { 38460 /* check if policer is attached to entry. 38461 * if attached, then we cannot enable the feature 38462 */ 38463 f_ent_pl = fs->entries[idx]->policer; 38464 if ((f_ent_pl) && 38465 (f_ent_pl->pid != _FP_INVALID_INDEX) ) { 38466 return BCM_E_UNAVAIL; 38467 } 38468 } 38469 } 38470 fs = fs->next; 38471 } 38472 } 38473 fg = fg->next; 38474 } 38475 if (state == 0) { 38476 fc->flags &= ~_FP_AUTOEXPAND_WITH_POLICER; 38477 } else { 38478 fc->flags |= _FP_AUTOEXPAND_WITH_POLICER; 38479 } 38480 return BCM_E_NONE; 38481 } 38482 /* 38483 * Function: _bcm_field_control_get 38484 * 38485 * Purpose: 38486 * Get control status info. 38487 * 38488 * Parameters: 38489 * unit - (IN) BCM device number. 38490 * fc - (IN) Field Control Structure. 38491 * control - (IN) Control element to get. 38492 * status - (OUT) Status of field element. 38493 * 38494 * Returns: 38495 * BCM_E_INIT - BCM unit not initialized 38496 * BCM_E_PARAM - *state pointing to NULL 38497 * BCM_E_NONE - Success 38498 */ 38499 int 38500 _bcm_field_control_get(int unit, _field_control_t *fc, 38501 bcm_field_control_t control, uint32 *state) 38502 { 38503 int rv = BCM_E_NONE; /* Operation return status. */ 38504 uint32 val1; 38505 uint32 val2; 38506 uint32 reg_val; /* Register value buffer. */ 38507 #if defined (BCM_TRX_SUPPORT) 38508 uint64 val64; /* Register 64bitvalue buffer. */ 38509 #endif /* BCM_TRX_SUPPORT */ 38510 38511 if (NULL == fc || NULL == state) { 38512 return BCM_E_PARAM; 38513 } 38514 38515 switch (control) { 38516 case bcmFieldControlIntraDoubleEnable: 38517 *state = (fc->flags & _FP_INTRASLICE_ENABLE) ? TRUE : FALSE; 38518 break; 38519 case bcmFieldControlColorIndependent: 38520 *state = (fc->flags & _FP_COLOR_INDEPENDENT) ? TRUE : FALSE; 38521 break; 38522 case bcmFieldControlStage: 38523 rv = (BCM_E_UNAVAIL); 38524 break; 38525 38526 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 38527 case bcmFieldControlExternalUdfEnable: 38528 if (SOC_REG_IS_VALID(unit, ESM_KEYGEN_CTLr)) { 38529 rv = READ_ESM_KEYGEN_CTLr(unit, ®_val); 38530 if (BCM_SUCCESS(rv)) { 38531 *state = soc_reg_field_get(unit, ESM_KEYGEN_CTLr, reg_val, 38532 L2_ACL_PAYLOAD_MODEf); 38533 } 38534 } else { 38535 rv = (BCM_E_UNAVAIL); 38536 } 38537 break; 38538 #endif /* !(BCM_TRIUMPH2_SUPPORT || BCM_TRIUMPH_SUPPORT) */ 38539 38540 case bcmFieldControlSharedVlanFieldSet: 38541 if (SOC_IS_TRX(unit)) { 38542 rv = (BCM_E_UNAVAIL); 38543 break; 38544 } 38545 if (SOC_REG_FIELD_VALID(unit, ING_CONFIGr, MAP_FID_ID_TO_INNER_TAGf)) { 38546 rv = READ_ING_CONFIGr(unit, ®_val); 38547 val1 = soc_reg_field_get(unit, ING_CONFIGr, reg_val, MAP_FID_ID_TO_INNER_TAGf); 38548 val2 = soc_reg_field_get(unit, ING_CONFIGr, reg_val, MAP_FID_ID_TO_OUTER_TAGf); 38549 if ((0 == val1) && (0 == val2)) { 38550 *state = BCM_FIELD_SHARED_VLAN_NONE; 38551 } 38552 if ((0 == val1) && (1 == val2)) { 38553 *state = BCM_FIELD_SHARED_VLAN_OUTER; 38554 } 38555 if ((1 == val1) && (0 == val2)) { 38556 *state = BCM_FIELD_SHARED_VLAN_INNER; 38557 } 38558 } else { 38559 rv = (BCM_E_UNAVAIL); 38560 } 38561 break; 38562 #if defined(BCM_TRX_SUPPORT) 38563 case bcmFieldControlArpAsIp: 38564 if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, ARP_RARP_TO_FPf)) { 38565 rv = READ_ING_CONFIG_64r(unit, &val64); 38566 if (BCM_SUCCESS(rv)) { 38567 reg_val = soc_reg64_field32_get(unit, ING_CONFIG_64r, 38568 val64, ARP_RARP_TO_FPf); 38569 *state = (0x1 & reg_val) ? TRUE : FALSE; 38570 } 38571 } else { 38572 rv = (BCM_E_UNAVAIL); 38573 } 38574 break; 38575 case bcmFieldControlRarpAsIp: 38576 if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, ARP_RARP_TO_FPf)) { 38577 rv = READ_ING_CONFIG_64r(unit, &val64); 38578 if (BCM_SUCCESS(rv)) { 38579 reg_val = soc_reg64_field32_get(unit, ING_CONFIG_64r, 38580 val64, ARP_RARP_TO_FPf); 38581 *state = (0x2 & reg_val) ? TRUE : FALSE; 38582 } 38583 } else { 38584 rv = (BCM_E_UNAVAIL); 38585 } 38586 break; 38587 case bcmFieldControlRedirectIngressVlanCheck: 38588 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38589 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38590 if (BCM_SUCCESS(rv)) { 38591 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38592 reg_val, VLAN_CHECK_ENf); 38593 } 38594 } else { 38595 rv = (BCM_E_UNAVAIL); 38596 } 38597 break; 38598 case bcmFieldControlRedirectNonUcastTrunkResolve: 38599 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38600 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38601 if (BCM_SUCCESS(rv)) { 38602 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38603 reg_val, LAG_RES_ENf); 38604 } 38605 } else { 38606 rv = (BCM_E_UNAVAIL); 38607 } 38608 break; 38609 case bcmFieldControlRedirectNonUcastEtherTrunkResolve: 38610 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38611 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38612 if (BCM_SUCCESS(rv)) { 38613 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38614 reg_val, LAG_RES_ENf); 38615 } 38616 } else { 38617 rv = (BCM_E_UNAVAIL); 38618 } 38619 break; 38620 case bcmFieldControlRedirectNonUcastFabricTrunkResolve: 38621 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38622 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38623 if (BCM_SUCCESS(rv)) { 38624 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38625 reg_val, HGTRUNK_RES_ENf); 38626 } 38627 } else { 38628 rv = (BCM_E_UNAVAIL); 38629 } 38630 break; 38631 case bcmFieldControlRedirectExcludeSrcPort: 38632 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38633 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38634 if (BCM_SUCCESS(rv)) { 38635 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38636 reg_val, SRC_REMOVAL_ENf); 38637 } 38638 } else { 38639 rv = (BCM_E_UNAVAIL); 38640 } 38641 break; 38642 case bcmFieldControlRedirectPortFloodBlock: 38643 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38644 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38645 if (BCM_SUCCESS(rv)) { 38646 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38647 reg_val, PORT_BLOCK_ENf); 38648 } 38649 } else { 38650 rv = (BCM_E_UNAVAIL); 38651 } 38652 break; 38653 case bcmFieldControlRedirectVlanFloodBlock: 38654 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38655 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38656 if (BCM_SUCCESS(rv)) { 38657 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38658 reg_val, VLAN_BLOCK_ENf); 38659 } 38660 } else { 38661 rv = (BCM_E_UNAVAIL); 38662 } 38663 break; 38664 case bcmFieldControlRedirectExcludeEtherSrcPort: 38665 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38666 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38667 if (BCM_SUCCESS(rv)) { 38668 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38669 reg_val, SRC_REMOVAL_ENf); 38670 } 38671 } else { 38672 rv = (BCM_E_UNAVAIL); 38673 } 38674 break; 38675 case bcmFieldControlRedirectExcludeHiGigSrcPort: 38676 if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38677 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38678 if (BCM_SUCCESS(rv)) { 38679 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38680 reg_val, HG_SRC_REMOVAL_ENf); 38681 } 38682 } else { 38683 rv = (BCM_E_UNAVAIL); 38684 } 38685 break; 38686 #endif /* BCM_TRX_SUPPORT */ 38687 case bcmFieldControlStatSyncEnable: 38688 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 38689 if (SOC_IS_TRX(unit) || SOC_IS_BRADLEY(unit)) { 38690 *state = (fc->flags & _FP_STAT_SYNC_ENABLE) ? TRUE : FALSE; 38691 } else 38692 #endif 38693 { 38694 rv = (BCM_E_UNAVAIL); 38695 } 38696 break; 38697 case bcmFieldControlPolicerGroupSharingEnable: 38698 *state = (fc->flags & _FP_POLICER_GROUP_SHARE_ENABLE) ? TRUE : FALSE; 38699 break; 38700 case bcmFieldControlRedirectNextHopExcludeSrcPort: 38701 if (0 == soc_reg_field_valid(unit,SW2_FP_DST_ACTION_CONTROLr, 38702 SRC_REMOVAL_EN_FOR_REDIRECT_TO_NHIf)) { 38703 rv = (BCM_E_UNAVAIL); 38704 } else { 38705 rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, ®_val); 38706 if (BCM_SUCCESS(rv)) { 38707 *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr, 38708 reg_val, 38709 SRC_REMOVAL_EN_FOR_REDIRECT_TO_NHIf); 38710 } 38711 38712 } 38713 break; 38714 #ifdef BCM_TRIUMPH3_SUPPORT 38715 case bcmFieldControlIngressLogicalPolicerPoolsMode: 38716 if (SOC_IS_TRIUMPH3(unit)) { 38717 *state = fc->ingress_logical_policer_pools_mode; 38718 }else { 38719 *state = -1; 38720 rv = BCM_E_UNAVAIL; 38721 } 38722 break; 38723 #endif 38724 38725 #if defined(BCM_METROLITE_SUPPORT) 38726 case bcmFieldControlReplacementTtl: 38727 if (SOC_REG_IS_VALID(unit, EGR_REPLACEMENT_TTLr)) { 38728 rv = READ_EGR_REPLACEMENT_TTLr(unit, ®_val); 38729 if (BCM_SUCCESS(rv)) { 38730 *state = soc_reg_field_get(unit, EGR_REPLACEMENT_TTLr, 38731 reg_val, REPLACEMENT_TTLf); 38732 } else { 38733 rv = (BCM_E_UNAVAIL); 38734 } 38735 } else { 38736 rv = (BCM_E_UNAVAIL); 38737 } 38738 break; 38739 #endif 38740 38741 case bcmFieldControlOverrideStageLookupPhb: 38742 #if defined (BCM_TRX_SUPPORT) 38743 if ((SOC_REG_IS_VALID(unit, ING_CONFIG_64r)) && 38744 (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, 38745 VFP_PRI_ACTION_FB2_MODEf))) { 38746 rv = READ_ING_CONFIG_64r(unit, &val64); 38747 if (BCM_SUCCESS(rv)) { 38748 *state = soc_reg64_field32_get(unit, ING_CONFIG_64r, 38749 val64, VFP_PRI_ACTION_FB2_MODEf); 38750 } 38751 } else { 38752 rv = BCM_E_UNAVAIL; 38753 } 38754 #endif 38755 break; 38756 case bcmFieldControlEgressAutoExpandWithPolicer: 38757 *state = (fc->flags & _FP_AUTOEXPAND_WITH_POLICER) ? 38758 TRUE : FALSE; 38759 break; 38760 default: 38761 rv = (BCM_E_UNAVAIL); 38762 } 38763 38764 return rv; 38765 } 38766 38767 /* 38768 * Function: _bcm_field_control_set 38769 * 38770 * Purpose: 38771 * Set control status. 38772 * 38773 * Parameters: 38774 * unit - (IN) BCM device number. 38775 * fc - (IN/OUT) Field Control Structure. 38776 * control - (IN) Control element to set. 38777 * state - (IN) State (0/1). 38778 * 38779 * Returns: 38780 * BCM_E_NONE - Success 38781 * BCM_E_INIT - BCM unit not initialized 38782 * BCM_E_PARAM - Flag state not valid on device 38783 */ 38784 int 38785 _bcm_field_control_set(int unit, _field_control_t *fc, 38786 bcm_field_control_t control, uint32 state) 38787 { 38788 int rv = BCM_E_NONE; /* Operation return status. */ 38789 uint32 reg_values[2]; /* Register value buffer. */ 38790 soc_field_t reg_fields[2]; /* Register fields to modify. */ 38791 int field_count = 2; /* Number of updated fields. */ 38792 reg_values[0] = reg_values[1] = (state == TRUE) ? 1: 0; 38793 38794 if (NULL == fc) { 38795 return BCM_E_PARAM; 38796 } 38797 38798 switch (control) { 38799 case bcmFieldControlIntraDoubleEnable: 38800 if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 38801 if (state == 0) { 38802 fc->flags &= ~_FP_INTRASLICE_ENABLE; 38803 } else { 38804 fc->flags |= _FP_INTRASLICE_ENABLE; 38805 } 38806 } else if (state == 0) { 38807 fc->flags &= ~_FP_INTRASLICE_ENABLE; 38808 } else { 38809 LOG_ERROR(BSL_LS_BCM_FP, 38810 (BSL_META_U(unit, 38811 "FP(unit %d) Error: Device doesn't support intraslice\n"), 38812 unit)); 38813 rv = (BCM_E_UNAVAIL); 38814 } 38815 break; 38816 case bcmFieldControlColorIndependent: 38817 if (soc_feature(unit, soc_feature_field_color_indep)) { 38818 if (state == 0) { 38819 fc->flags &= ~_FP_COLOR_INDEPENDENT; 38820 } else { 38821 fc->flags |= _FP_COLOR_INDEPENDENT; 38822 } 38823 } else if (state == 0) { 38824 fc->flags &= ~_FP_COLOR_INDEPENDENT; 38825 } else { 38826 LOG_ERROR(BSL_LS_BCM_FP, 38827 (BSL_META_U(unit, 38828 "FP(unit %d) Error: Color Independence unsupported on this unit\n"), 38829 unit)); 38830 rv = BCM_E_UNAVAIL; 38831 } 38832 break; 38833 case bcmFieldControlStage: 38834 rv = (BCM_E_UNAVAIL); 38835 break; 38836 case bcmFieldControlSharedVlanFieldSet: 38837 if (SOC_IS_TRX(unit)) { 38838 rv = (BCM_E_UNAVAIL); 38839 break; 38840 } 38841 if (SOC_REG_FIELD_VALID(unit, ING_CONFIGr, MAP_FID_ID_TO_INNER_TAGf)) { 38842 reg_fields[0] = MAP_FID_ID_TO_INNER_TAGf; 38843 reg_fields[1] = MAP_FID_ID_TO_OUTER_TAGf; 38844 if (BCM_FIELD_SHARED_VLAN_NONE == state) { 38845 reg_values[0] = 0; 38846 reg_values[1] = 0; 38847 } else if (BCM_FIELD_SHARED_VLAN_INNER == state) { 38848 reg_values[0] = 1; 38849 reg_values[1] = 0; 38850 } else if (BCM_FIELD_SHARED_VLAN_OUTER == state) { 38851 reg_values[0] = 0; 38852 reg_values[1] = 1; 38853 } else { 38854 rv = (BCM_E_PARAM); 38855 break; 38856 } 38857 rv = soc_reg_fields32_modify(unit, ING_CONFIGr, REG_PORT_ANY, 38858 field_count, reg_fields, reg_values); 38859 } else { 38860 rv = (BCM_E_UNAVAIL); 38861 } 38862 break; 38863 #if defined(BCM_TRX_SUPPORT) 38864 case bcmFieldControlArpAsIp: 38865 case bcmFieldControlRarpAsIp: 38866 if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, ARP_RARP_TO_FPf)) { 38867 rv = _bcm_field_trx_control_arp_set(unit, control, state); 38868 } else { 38869 rv = (BCM_E_UNAVAIL); 38870 } 38871 break; 38872 case bcmFieldControlRedirectIngressVlanCheck: 38873 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38874 rv = (BCM_E_UNAVAIL); 38875 } else { 38876 reg_fields[0] = VLAN_CHECK_ENf; 38877 field_count = 1; 38878 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38879 REG_PORT_ANY, field_count, 38880 reg_fields, reg_values); 38881 } 38882 break; 38883 case bcmFieldControlRedirectNonUcastTrunkResolve: 38884 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38885 rv = (BCM_E_UNAVAIL); 38886 } else { 38887 reg_fields[0] = LAG_RES_ENf; 38888 reg_fields[1] = HGTRUNK_RES_ENf; 38889 field_count = 2; 38890 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38891 REG_PORT_ANY, field_count, 38892 reg_fields, reg_values); 38893 } 38894 break; 38895 case bcmFieldControlRedirectNonUcastEtherTrunkResolve: 38896 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38897 rv = (BCM_E_UNAVAIL); 38898 } else { 38899 reg_fields[0] = LAG_RES_ENf; 38900 field_count = 1; 38901 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38902 REG_PORT_ANY, field_count, 38903 reg_fields, reg_values); 38904 } 38905 break; 38906 case bcmFieldControlRedirectNonUcastFabricTrunkResolve: 38907 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38908 rv = (BCM_E_UNAVAIL); 38909 } else { 38910 reg_fields[0] = HGTRUNK_RES_ENf; 38911 field_count = 1; 38912 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38913 REG_PORT_ANY, field_count, 38914 reg_fields, reg_values); 38915 } 38916 break; 38917 case bcmFieldControlRedirectExcludeSrcPort: 38918 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38919 rv = (BCM_E_UNAVAIL); 38920 } else { 38921 reg_fields[0] = HG_SRC_REMOVAL_ENf; 38922 reg_fields[1] = SRC_REMOVAL_ENf; 38923 field_count = 2; 38924 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38925 REG_PORT_ANY, field_count, 38926 reg_fields, reg_values); 38927 } 38928 break; 38929 case bcmFieldControlRedirectExcludeEtherSrcPort: 38930 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38931 rv = (BCM_E_UNAVAIL); 38932 } else { 38933 reg_fields[0] = SRC_REMOVAL_ENf; 38934 field_count = 1; 38935 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38936 REG_PORT_ANY, field_count, 38937 reg_fields, reg_values); 38938 } 38939 break; 38940 case bcmFieldControlRedirectExcludeHiGigSrcPort: 38941 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38942 rv = (BCM_E_UNAVAIL); 38943 } else { 38944 reg_fields[0] = HG_SRC_REMOVAL_ENf; 38945 field_count = 1; 38946 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38947 REG_PORT_ANY, field_count, 38948 reg_fields, reg_values); 38949 } 38950 break; 38951 case bcmFieldControlRedirectPortFloodBlock: 38952 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38953 rv = (BCM_E_UNAVAIL); 38954 } else { 38955 reg_fields[0] = PORT_BLOCK_ENf; 38956 field_count = 1; 38957 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38958 REG_PORT_ANY, field_count, 38959 reg_fields, reg_values); 38960 } 38961 break; 38962 case bcmFieldControlRedirectVlanFloodBlock: 38963 if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) { 38964 rv = (BCM_E_UNAVAIL); 38965 } else { 38966 reg_fields[0] = VLAN_BLOCK_ENf; 38967 field_count = 1; 38968 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 38969 REG_PORT_ANY, field_count, 38970 reg_fields, reg_values); 38971 } 38972 break; 38973 #endif /* BCM_TRX_SUPPORT */ 38974 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 38975 case bcmFieldControlExternalUdfEnable: 38976 if (SOC_REG_IS_VALID(unit, ESM_KEYGEN_CTLr)) { 38977 rv = soc_reg_field32_modify(unit, ESM_KEYGEN_CTLr, REG_PORT_ANY, 38978 L2_ACL_PAYLOAD_MODEf, state); 38979 } else { 38980 rv = (BCM_E_UNAVAIL); 38981 } 38982 break; 38983 #endif /* !(BCM_TRIUMPH2_SUPPORT || BCM_TRIUMPH_SUPPORT) */ 38984 case bcmFieldControlStatSyncEnable: 38985 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 38986 if (SOC_IS_TRX(unit) || SOC_IS_BRADLEY(unit)) { 38987 if (state == 0) { 38988 fc->flags &= ~_FP_STAT_SYNC_ENABLE; 38989 } else { 38990 fc->flags |= _FP_STAT_SYNC_ENABLE; 38991 } 38992 } else 38993 #endif 38994 { 38995 rv = (BCM_E_UNAVAIL); 38996 } 38997 break; 38998 case bcmFieldControlPolicerGroupSharingEnable: 38999 if (fc->groups) { 39000 rv = BCM_E_CONFIG; 39001 } else if (state == 0) { 39002 fc->flags &= ~_FP_POLICER_GROUP_SHARE_ENABLE; 39003 } else { 39004 fc->flags |= _FP_POLICER_GROUP_SHARE_ENABLE; 39005 } 39006 break; 39007 case bcmFieldControlRedirectNextHopExcludeSrcPort: 39008 if (0 == soc_reg_field_valid(unit,SW2_FP_DST_ACTION_CONTROLr, 39009 SRC_REMOVAL_EN_FOR_REDIRECT_TO_NHIf)) { 39010 rv = (BCM_E_UNAVAIL); 39011 } else { 39012 reg_fields[0] = SRC_REMOVAL_EN_FOR_REDIRECT_TO_NHIf; 39013 field_count = 1; 39014 rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 39015 REG_PORT_ANY, field_count, 39016 reg_fields, reg_values); 39017 } 39018 break; 39019 #ifdef BCM_TRIUMPH3_SUPPORT 39020 case bcmFieldControlIngressLogicalPolicerPoolsMode: 39021 if (SOC_IS_TRIUMPH3(unit)) { 39022 if (state == fc->ingress_logical_policer_pools_mode) { 39023 return BCM_E_NONE; 39024 } else { 39025 /* Cannot set the field control 39026 * if policers are already created. 39027 */ 39028 if (fc->policer_count > 0) { 39029 return BCM_E_CONFIG; 39030 } 39031 } 39032 switch (state) { 39033 case bcmFieldIngressLogicalPolicerPools16x512Split: 39034 fc->ingress_logical_policer_pools_mode = 39035 bcmFieldIngressLogicalPolicerPools16x512Split; 39036 break; 39037 case bcmFieldIngressLogicalPolicerPools16x512Contiguous: 39038 fc->ingress_logical_policer_pools_mode = 39039 bcmFieldIngressLogicalPolicerPools16x512Contiguous; 39040 break; 39041 case bcmFieldIngressLogicalPolicerPools8x1024: 39042 fc->ingress_logical_policer_pools_mode = 39043 bcmFieldIngressLogicalPolicerPools8x1024; 39044 break; 39045 default: 39046 fc->ingress_logical_policer_pools_mode = 39047 bcmFieldIngressLogicalPolicerPools8x1024; 39048 rv = BCM_E_CONFIG; 39049 } 39050 }else { 39051 fc->ingress_logical_policer_pools_mode = -1; 39052 rv = BCM_E_UNAVAIL; 39053 } 39054 break; 39055 #endif 39056 39057 #if defined(BCM_METROLITE_SUPPORT) 39058 case bcmFieldControlReplacementTtl: 39059 if (SOC_REG_IS_VALID(unit, EGR_REPLACEMENT_TTLr)) { 39060 if (255 >= state ) { 39061 rv = soc_reg_field32_modify(unit, EGR_REPLACEMENT_TTLr, 39062 REG_PORT_ANY, 39063 REPLACEMENT_TTLf, state); 39064 } else { 39065 rv = (BCM_E_PARAM); 39066 } 39067 } else { 39068 rv = (BCM_E_UNAVAIL); 39069 } 39070 break; 39071 #endif /* (BCM_METROLITE_SUPPORT) */ 39072 39073 case bcmFieldControlOverrideStageLookupPhb: 39074 if ((SOC_REG_IS_VALID(unit, ING_CONFIG_64r)) && 39075 (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, 39076 VFP_PRI_ACTION_FB2_MODEf))) { 39077 if (state) { 39078 rv = soc_reg_field32_modify(unit, ING_CONFIG_64r, 39079 REG_PORT_ANY, VFP_PRI_ACTION_FB2_MODEf, 1); 39080 } else { 39081 rv = soc_reg_field32_modify(unit, ING_CONFIG_64r, 39082 REG_PORT_ANY, VFP_PRI_ACTION_FB2_MODEf, 0); 39083 } 39084 } else { 39085 rv = BCM_E_UNAVAIL; 39086 } 39087 break; 39088 case bcmFieldControlEgressAutoExpandWithPolicer: 39089 rv = _bcm_field_control_EgressAutoExpanWithPolicer_set( 39090 unit, fc, state); 39091 break; 39092 default: 39093 rv = (BCM_E_UNAVAIL); 39094 } 39095 39096 return rv; 39097 } 39098 39099 39100 /* Function: _field_hints_control_get 39101 * 39102 * Purpose: 39103 * Get Field Hints Control 39104 * Parameters: 39105 * unit - (IN) BCM device number. 39106 * hint_id - (IN) Hint Id. 39107 * f_ht - (OUT) hints_control_structure 39108 * Returns: 39109 * BCM_E_XXXX. 39110 */ 39111 int _field_hints_control_get(int unit, 39112 bcm_field_hintid_t hint_id, 39113 _field_hints_t **f_ht) 39114 { 39115 uint32 hash_index = 0; /* Hash index */ 39116 _field_hints_t *f_ht_tmp; /* field hints */ 39117 _field_control_t *fc; /* Field control structure. */ 39118 39119 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 39120 39121 hash_index = hint_id & _FP_HASH_INDEX_MASK(fc); 39122 f_ht_tmp = fc->hints_hash[hash_index]; 39123 39124 while (NULL != f_ht_tmp) { 39125 /* Match Hint id. */ 39126 if (f_ht_tmp->hintid == hint_id) { 39127 *f_ht = f_ht_tmp; 39128 break; 39129 } 39130 f_ht_tmp = f_ht_tmp->next; 39131 } 39132 39133 return BCM_E_NONE; 39134 39135 } 39136 39137 #ifdef BCM_WARM_BOOT_SUPPORT 39138 /* Function: _bcm_field_hints_scache_sync 39139 * 39140 * Purpose: 39141 * Sync hints Hash table information into scache 39142 * Parameters: 39143 * unit - (IN) BCM device number. 39144 * fc - (IN) Field Control. 39145 * stage_fc - (IN) Stage Control. 39146 * scache_ptr - (INOUT) Scache Pointer. 39147 * Returns: 39148 * BCM_E_XXXX. 39149 */ 39150 int _bcm_field_hints_scache_sync (int unit, 39151 _field_control_t *fc, 39152 _field_stage_t *stage_fc, 39153 uint8 *scache_ptr) 39154 { 39155 bcm_field_hintid_t hint_id = 0; /* Hint Id */ 39156 _field_hints_t *f_ht = NULL; /* Field hints Structure */ 39157 _field_hint_t *hints_dump = NULL; /* Field hints Structure */ 39158 bcm_field_hint_t *hint_entry; /* Hint Entry */ 39159 uint32 hint_count = 0; /* Hint count */ 39160 uint8 *curr_scache_ptr = scache_ptr; /* Scache Pointer */ 39161 39162 if ((fc == NULL) || (stage_fc == NULL) || (scache_ptr == NULL)) { 39163 return BCM_E_PARAM; 39164 } 39165 39166 if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) { 39167 return BCM_E_NONE; 39168 } 39169 39170 /* Sync hintid bitmap into scache */ 39171 sal_memcpy (curr_scache_ptr, ((fc->hintid_bmp).w), 39172 SHR_BITALLOCSIZE(_FP_HINT_ID_MAX)); 39173 fc->scache_pos += SHR_BITALLOCSIZE(_FP_HINT_ID_MAX); 39174 curr_scache_ptr += SHR_BITALLOCSIZE(_FP_HINT_ID_MAX); 39175 39176 for (hint_id = _FP_HINT_ID_BASE; hint_id < _FP_HINT_ID_MAX; hint_id++) { 39177 if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, hint_id)) { 39178 hint_count = 0; 39179 39180 BCM_IF_ERROR_RETURN(_field_hints_control_get(unit, hint_id, &f_ht)); 39181 if (f_ht == NULL) { 39182 LOG_DEBUG(BSL_LS_BCM_FP, 39183 (BSL_META_U(unit,"FP (unit %d) HintId %d not present" 39184 " in Hint Hash table\r\n"), unit, hint_id)); 39185 continue; 39186 } 39187 39188 /* Sync Hint Id */ 39189 LOG_DEBUG(BSL_LS_BCM_FP, 39190 (BSL_META_U(unit,"@Pos(%d) Syncing hints information" 39191 " for Hint ID (%d)\r\n"), fc->scache_pos, hint_id)); 39192 sal_memcpy (curr_scache_ptr, &(f_ht->hintid), 39193 sizeof(bcm_field_hintid_t)); 39194 fc->scache_pos += sizeof (bcm_field_hintid_t); 39195 curr_scache_ptr += sizeof (bcm_field_hintid_t); 39196 39197 /* Sync Hints Count */ 39198 LOG_DEBUG(BSL_LS_BCM_FP, 39199 (BSL_META_U(unit,"@Pos(%d) Syncing number of Hints" 39200 "present = %d\r\n"), 39201 fc->scache_pos, f_ht->hint_count)); 39202 sal_memcpy (curr_scache_ptr, &(f_ht->hint_count), sizeof(uint16)); 39203 fc->scache_pos += sizeof (uint16); 39204 curr_scache_ptr += sizeof (uint16); 39205 39206 /* Group ref Count will be updated when group is recovered. 39207 * Hence no need to sync group refCount */ 39208 39209 hints_dump = f_ht->hints; 39210 39211 while (hints_dump != NULL) { 39212 hint_entry = hints_dump->hint; 39213 if (hint_entry != NULL) { 39214 LOG_DEBUG(BSL_LS_BCM_FP, 39215 (BSL_META_U(unit,"@Pos(%d) HintId(%d) Syncing" 39216 "HintType = %d\r\n"), fc->scache_pos, 39217 hint_id, hint_entry->hint_type)); 39218 sal_memcpy (curr_scache_ptr, &(hint_entry->hint_type), 39219 sizeof(bcm_field_hint_type_t)); 39220 fc->scache_pos += sizeof (bcm_field_hint_type_t); 39221 curr_scache_ptr += sizeof (bcm_field_hint_type_t); 39222 39223 LOG_DEBUG(BSL_LS_BCM_FP, 39224 (BSL_META_U(unit,"@Pos(%d) HintId(%d) Syncing" 39225 " Flags = %d\r\n"), fc->scache_pos, 39226 hint_id, hint_entry->flags)); 39227 sal_memcpy (curr_scache_ptr, &(hint_entry->flags), 39228 sizeof(uint32)); 39229 fc->scache_pos += sizeof (uint32); 39230 curr_scache_ptr += sizeof (uint32); 39231 39232 LOG_DEBUG(BSL_LS_BCM_FP, 39233 (BSL_META_U(unit,"@Pos(%d) HintId(%d) Sync Max" 39234 " Group Size = %d\r\n"), fc->scache_pos, 39235 hint_id, hint_entry->max_group_size)); 39236 sal_memcpy (curr_scache_ptr, &(hint_entry->max_group_size), 39237 sizeof(uint32)); 39238 fc->scache_pos += sizeof (uint32); 39239 curr_scache_ptr += sizeof (uint32); 39240 } 39241 hint_count++; 39242 hints_dump = hints_dump->next; 39243 } 39244 LOG_DEBUG(BSL_LS_BCM_FP, 39245 (BSL_META_U(unit, "HintId(%d) Number of hints synced (%d)" 39246 " and Number of hints present (%d)\r\n"), 39247 hint_id, hint_count,f_ht->hint_count)); 39248 } 39249 } 39250 return BCM_E_NONE; 39251 } 39252 39253 /* Function: _bcm_field_hints_scache_recover 39254 * 39255 * Purpose: 39256 * Recover hints Hash table information from scache 39257 * Parameters: 39258 * unit - (IN) BCM device number. 39259 * fc - (IN) Field Control. 39260 * stage_fc - (IN) Stage Control. 39261 * scache_ptr - (INOUT) Scache Pointer. 39262 * Returns: 39263 * BCM_E_XXXX. 39264 */ 39265 int _bcm_field_hints_scache_recover (int unit, 39266 _field_control_t *fc, 39267 _field_stage_t *stage_fc, 39268 uint8 *scache_ptr) 39269 { 39270 bcm_field_hintid_t hint_id = 0; /* Hint Id */ 39271 bcm_field_hint_t hint_entry; /* Hint Entry */ 39272 uint16 hint_count = 0; /* Hint Count */ 39273 int count = 0; /* Counter */ 39274 uint8 *curr_scache_ptr = scache_ptr; 39275 39276 if ((fc == NULL) || (stage_fc == NULL) || (scache_ptr == NULL)) { 39277 return BCM_E_PARAM; 39278 } 39279 39280 /* Sync hintid bitmap into scache */ 39281 sal_memcpy (fc->hintid_bmp.w, curr_scache_ptr, 39282 SHR_BITALLOCSIZE(_FP_HINT_ID_MAX)); 39283 fc->scache_pos += SHR_BITALLOCSIZE(_FP_HINT_ID_MAX); 39284 curr_scache_ptr += SHR_BITALLOCSIZE(_FP_HINT_ID_MAX); 39285 39286 for (hint_id = _FP_HINT_ID_BASE; hint_id < _FP_HINT_ID_MAX; hint_id++) { 39287 if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, hint_id)) { 39288 /* Recover Hint Id */ 39289 sal_memcpy (&hint_id, curr_scache_ptr, 39290 sizeof(bcm_field_hintid_t)); 39291 LOG_DEBUG(BSL_LS_BCM_FP, 39292 (BSL_META_U(unit,"@Pos(%d) Recovered hints information" 39293 " for Hint ID (%d)\r\n"), 39294 fc->scache_pos, hint_id)); 39295 fc->scache_pos += sizeof (bcm_field_hintid_t); 39296 curr_scache_ptr += sizeof (bcm_field_hintid_t); 39297 39298 /* Recover Hints Count */ 39299 sal_memcpy (&hint_count, curr_scache_ptr, sizeof(uint16)); 39300 LOG_DEBUG(BSL_LS_BCM_FP, 39301 (BSL_META_U(unit,"@Pos(%d) Recovered number of Hints" 39302 " present = %d\r\n"), fc->scache_pos, hint_count)); 39303 fc->scache_pos += sizeof (uint16); 39304 curr_scache_ptr += sizeof (uint16); 39305 39306 for (count = 0; count < hint_count; count++) { 39307 sal_memset (&hint_entry, 0, sizeof (bcm_field_hint_t)); 39308 sal_memcpy (&(hint_entry.hint_type), curr_scache_ptr, 39309 sizeof(bcm_field_hint_type_t)); 39310 LOG_DEBUG(BSL_LS_BCM_FP, 39311 (BSL_META_U(unit,"@Pos(%d) HintId(%d) Recovered" 39312 " HintType = %d\r\n"), fc->scache_pos, 39313 hint_id, hint_entry.hint_type)); 39314 fc->scache_pos += sizeof (bcm_field_hint_type_t); 39315 curr_scache_ptr += sizeof (bcm_field_hint_type_t); 39316 39317 sal_memcpy (&(hint_entry.flags), curr_scache_ptr, 39318 sizeof(uint32)); 39319 LOG_DEBUG(BSL_LS_BCM_FP, 39320 (BSL_META_U(unit,"@Pos(%d) HintId(%d) Recovered" 39321 " Flags = %d\r\n"), fc->scache_pos, 39322 hint_id, hint_entry.flags)); 39323 fc->scache_pos += sizeof (uint32); 39324 curr_scache_ptr += sizeof (uint32); 39325 39326 sal_memcpy (&(hint_entry.max_group_size), curr_scache_ptr, 39327 sizeof(uint32)); 39328 LOG_DEBUG(BSL_LS_BCM_FP, 39329 (BSL_META_U(unit,"@Pos(%d) HintId(%d) Recovered" 39330 " Max Group Size = %d\r\n"), fc->scache_pos, 39331 hint_id, hint_entry.max_group_size)); 39332 fc->scache_pos += sizeof (uint32); 39333 curr_scache_ptr += sizeof (uint32); 39334 39335 BCM_IF_ERROR_RETURN (bcm_esw_field_hints_add (unit, hint_id, 39336 &hint_entry)); 39337 } 39338 } 39339 } 39340 return BCM_E_NONE; 39341 } 39342 39343 /* Function: _bcm_hints_scache_hintid_sync 39344 * 39345 * Purpose: 39346 * Sync the hint id associated with the group. 39347 * Parameters: 39348 * unit - (IN) BCM device number. 39349 * uint8 - (IN) Scache_ptr 39350 * Returns: 39351 * BCM_E_XXXX. 39352 */ 39353 int _bcm_hints_scache_hintid_sync (int unit, _field_stage_t *stage_fc, 39354 uint8 *scache_ptr) 39355 { 39356 _field_control_t *fc; /* Field control structure. */ 39357 _field_group_t *fg; /* Field group info. */ 39358 uint8 *curr_scache_ptr = scache_ptr; /* Scache Pointer */ 39359 39360 if (scache_ptr == NULL) { 39361 return BCM_E_PARAM; 39362 } 39363 39364 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 39365 39366 fg = fc->groups; 39367 if (NULL == fg) { 39368 return (BCM_E_NONE); 39369 } 39370 39371 for (; fg != NULL; fg = fg->next) { 39372 if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS || 39373 fg->stage_id == _BCM_FIELD_STAGE_EGRESS || 39374 fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 39375 39376 if(stage_fc->stage_id == fg->stage_id) { 39377 sal_memcpy (curr_scache_ptr, &(fg->gid), 39378 sizeof(bcm_field_group_t)); 39379 fc->scache_pos += sizeof (bcm_field_group_t); 39380 curr_scache_ptr += sizeof (bcm_field_group_t); 39381 39382 sal_memcpy (curr_scache_ptr, &(fg->hintid), 39383 sizeof(bcm_field_hintid_t)); 39384 fc->scache_pos += sizeof (bcm_field_hintid_t); 39385 curr_scache_ptr += sizeof (bcm_field_hintid_t); 39386 } 39387 } 39388 } 39389 39390 return BCM_E_NONE; 39391 } 39392 39393 /* Function: _bcm_hints_scache_hintid_recover 39394 * 39395 * Purpose: 39396 * Recover the hint id associated with the group. 39397 * Parameters: 39398 * unit - (IN) BCM device number. 39399 * fc - (IN) Field Control. 39400 * scache_ptr - (IN) Scache Pointer. 39401 * Returns: 39402 * BCM_E_XXXX. 39403 */ 39404 int _bcm_hints_scache_hintid_recover (int unit, 39405 _field_stage_t *stage_fc, 39406 _field_control_t *fc, 39407 uint8 *scache_ptr) 39408 { 39409 uint8 *curr_scache_ptr = scache_ptr; /* Scache Pointer */ 39410 _field_group_t *fg_entry = NULL; /* Field Group Entry */ 39411 _field_group_t *fg = NULL; /* Field Group Entry */ 39412 bcm_field_group_t gid = 0; /* Group Id */ 39413 39414 if ((scache_ptr == NULL) || (fc == NULL)) { 39415 return BCM_E_PARAM; 39416 } 39417 39418 fg = fc->groups; 39419 39420 while (fg != NULL) { 39421 if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS || 39422 fg->stage_id == _BCM_FIELD_STAGE_EGRESS || 39423 fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 39424 if(stage_fc->stage_id == fg->stage_id) { 39425 39426 sal_memcpy (&gid, curr_scache_ptr, 39427 sizeof (bcm_field_group_t)); 39428 fc->scache_pos += sizeof (bcm_field_group_t); 39429 curr_scache_ptr += sizeof (bcm_field_group_t); 39430 39431 BCM_IF_ERROR_RETURN(_field_group_get(unit, gid, &fg_entry)); 39432 if (!(fg_entry->stage_id == _BCM_FIELD_STAGE_INGRESS || 39433 fg_entry->stage_id == _BCM_FIELD_STAGE_EGRESS || 39434 fg_entry->stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 39435 return BCM_E_INTERNAL; 39436 } 39437 39438 sal_memcpy ( &(fg_entry->hintid),curr_scache_ptr, 39439 sizeof(bcm_field_hintid_t)); 39440 fc->scache_pos += sizeof (bcm_field_hintid_t); 39441 curr_scache_ptr += sizeof (bcm_field_hintid_t); 39442 39443 /* Group has been created, Increment group ref count in 39444 * corresponding hintid in hints hash lookup table */ 39445 BCM_IF_ERROR_RETURN(_bcm_field_hints_group_count_update 39446 (unit, fg_entry->hintid, 1)); 39447 BCM_IF_ERROR_RETURN(_bcm_field_hints_group_info_update( 39448 unit, fg_entry)); 39449 } 39450 39451 } 39452 fg = fg->next; 39453 } 39454 39455 return BCM_E_NONE; 39456 } 39457 39458 #endif /* BCM_WARM_BOOT_SUPPORT */ 39459 /* Function: _bcm_field_hints_group_info_update 39460 * 39461 * Purpose: 39462 * During Group creation, update group structure with the 39463 * data from the hintid 39464 * Parameters: 39465 * unit - (IN) BCM device number. 39466 * fg - (INOUT) Field Group Structure. 39467 * Returns: 39468 * BCM_E_XXXX. 39469 */ 39470 int _bcm_field_hints_group_info_update (int unit, 39471 _field_group_t *fg) 39472 { 39473 _field_hints_t *f_ht = NULL; /* Field hints Structure. */ 39474 bcm_field_hint_t *hint_entry; /* Hint Entry. */ 39475 _field_hint_t *hint_list = NULL; /* Field Hints Structure. */ 39476 39477 if (NULL == fg) { 39478 return BCM_E_PARAM; 39479 } 39480 39481 if (fg->hintid == 0) { 39482 LOG_DEBUG(BSL_LS_BCM_FP, 39483 (BSL_META_U(unit,"Hints not configured. Hence no need" 39484 " to update\r\n"))); 39485 return BCM_E_NONE; 39486 } 39487 39488 39489 39490 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, fg->hintid, &f_ht)); 39491 if (f_ht == NULL) { 39492 return (BCM_E_NOT_FOUND); 39493 } 39494 39495 hint_list = f_ht->hints; 39496 39497 while (hint_list != NULL) { 39498 hint_entry = hint_list->hint; 39499 if (hint_entry != NULL) { 39500 /* Hint Found */ 39501 LOG_DEBUG(BSL_LS_BCM_FP, 39502 (BSL_META_U(unit, "Updating Group" 39503 " Structure from hints in hintid %d\r\n"), fg->hintid)); 39504 switch (hint_entry->hint_type) { 39505 case bcmFieldHintTypeCompression: 39506 /* Fill Flags, max_values, start_bit, end_bit */ 39507 break; 39508 case bcmFieldHintTypeExtraction: 39509 /* Fill Flags, max_values, start_bit, end_bit */ 39510 break; 39511 case bcmFieldHintTypeGroupAutoExpansion: 39512 /* Fill Flags, max_group_size */ 39513 if ((hint_entry->flags & BCM_FIELD_GROUP_AUTO_EXPANSION_SMALL) 39514 && (hint_entry->flags & BCM_FIELD_GROUP_AUTO_EXPANSION_LARGE)) { 39515 LOG_ERROR(BSL_LS_BCM_FP, 39516 (BSL_META_U(unit, 39517 "Group(%d) hint flags have" 39518 "both SMALL and LARGE\r\n"),fg->gid)); 39519 return BCM_E_PARAM; 39520 } 39521 if (hint_entry->flags & 39522 BCM_FIELD_GROUP_AUTO_EXPANSION_SMALL) { 39523 fg->flags |= _FP_GROUP_AUTO_EXPAND_SMALL_SLICE; 39524 LOG_DEBUG(BSL_LS_BCM_FP, 39525 (BSL_META_U(unit, 39526 "Updating Group(%d) Structure flag with " 39527 "AutoExpandSmall \r\n"),fg->gid)); 39528 } 39529 if (hint_entry->flags & 39530 BCM_FIELD_GROUP_AUTO_EXPANSION_LARGE) { 39531 fg->flags |= _FP_GROUP_AUTO_EXPAND_LARGE_SLICE; 39532 LOG_DEBUG(BSL_LS_BCM_FP, 39533 (BSL_META_U(unit,"Updating" 39534 " Group(%d) Structure flag with " 39535 "AutoExpandLarge\r\n"), fg->gid)); 39536 } 39537 if (hint_entry->flags & 39538 BCM_FIELD_GROUP_MAX_SIZE_HARD_LIMIT) { 39539 fg->flags |= _FP_GROUP_MAX_SIZE_HARD_LIMIT; 39540 LOG_DEBUG(BSL_LS_BCM_FP, 39541 (BSL_META_U(unit, "Updating Group(%d) " 39542 " Structure flag with MaxGroupSize" 39543 " hardLimit \r\n"),fg->gid)); 39544 } 39545 fg->max_group_size = hint_entry->max_group_size; 39546 39547 LOG_DEBUG(BSL_LS_BCM_FP, 39548 (BSL_META_U(unit,"Updating Group(%d) Structure" 39549 " flag with MaxGroupSize %u \r\n"), 39550 fg->gid, fg->max_group_size)); 39551 break; 39552 case bcmFieldHintTypeExactMatch: 39553 #ifdef BCM_TOMAHAWK_SUPPORT 39554 if (hint_entry->flags & 39555 BCM_FIELD_HINT_EXACT_MATCH_GROUP_PRIORITY) { 39556 if (soc_feature(unit, 39557 soc_feature_field_exact_match_support)) { 39558 _field_th_em_group_priority_hintbased_qset_update( 39559 unit, fg, hint_entry); 39560 } 39561 } 39562 #endif 39563 break; 39564 default: 39565 LOG_DEBUG(BSL_LS_BCM_FP, 39566 (BSL_META_U(unit,"Unknown Hint Type\r\n"))); 39567 return BCM_E_PARAM; 39568 break; 39569 } 39570 } 39571 hint_list = hint_list->next; 39572 } 39573 39574 return BCM_E_NONE; 39575 } 39576 39577 /* Function: _bcm_field_hints_group_count_update 39578 * 39579 * Purpose: 39580 * When a group is created associating with a hint_id, 39581 * increment the refCount in the hint_id for the group. 39582 * Similary decrement the refCount when a group is destroyed. 39583 * Parameters: 39584 * unit - (IN) BCM device number. 39585 * hint_id - (IN) Hint Id. 39586 * action - (IN) Increment/Decrement. 39587 * Returns: 39588 * BCM_E_XXXX. 39589 */ 39590 int _bcm_field_hints_group_count_update (int unit, 39591 bcm_field_hintid_t hint_id, 39592 uint8 action) 39593 { 39594 _field_hints_t *f_ht = NULL; /* Field hints Structure. */ 39595 39596 if (hint_id == 0) { 39597 LOG_DEBUG(BSL_LS_BCM_FP, 39598 (BSL_META_U(unit,"Hints not configured. Hence no need" 39599 " to update\r\n"))); 39600 return BCM_E_NONE; 39601 } 39602 39603 39604 39605 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht)); 39606 if (f_ht == NULL) { 39607 return (BCM_E_NOT_FOUND); 39608 } 39609 39610 if (action) { 39611 f_ht->grp_ref_count++; 39612 LOG_DEBUG(BSL_LS_BCM_FP, 39613 (BSL_META_U(unit,"New Group Attached to hintid %d," 39614 " Group cnt %d\r\n"), hint_id,f_ht->grp_ref_count)); 39615 } else { 39616 if (f_ht->grp_ref_count > 0) { 39617 f_ht->grp_ref_count--; 39618 LOG_DEBUG(BSL_LS_BCM_FP, 39619 (BSL_META_U(unit, "Group detached from hintid %d," 39620 " Group cnt %d\r\n"), hint_id,f_ht->grp_ref_count)); 39621 } 39622 } 39623 39624 return BCM_E_NONE; 39625 } 39626 39627 /* 39628 * Function: 39629 * _field_hints_id_alloc 39630 * Purpose: 39631 * Allocate a hint id. 39632 * Parameters: 39633 * unit - (IN) BCM device number. 39634 * hint_id - (OUT) Hint id. 39635 * Returns: 39636 * BCM_E_XXX 39637 * Notes: 39638 */ 39639 int _field_hints_id_alloc (int unit, bcm_field_hintid_t *hint_id) 39640 { 39641 _field_control_t *fc; /* Field control structure.*/ 39642 uint32 hint_iter = 0; /* Hint Id */ 39643 39644 /* Input parameters check. */ 39645 if (NULL == hint_id) { 39646 return (BCM_E_PARAM); 39647 } 39648 39649 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 39650 39651 for (hint_iter = _FP_HINT_ID_BASE; 39652 hint_iter < _FP_HINT_ID_MAX; hint_iter++) { 39653 if (_FP_HINTID_BMP_TEST((fc->hintid_bmp), hint_iter) == 0) { 39654 *hint_id = hint_iter; 39655 return (BCM_E_NONE); 39656 } 39657 } 39658 return (BCM_E_RESOURCE); 39659 } 39660 39661 39662 /* Function: _bcm_field_hints_add 39663 * 39664 * Purpose: 39665 * Associate hint to hint id. 39666 * Parameters: 39667 * unit - (IN) BCM device number. 39668 * hint_id - (IN) Hint id to which the hint should be associated 39669 * hint - (IN) bcm_field_hint_t structure 39670 * Returns: 39671 * BCM_E_XXXX. 39672 */ 39673 int _bcm_field_hints_add (int unit, 39674 bcm_field_hintid_t hint_id, 39675 bcm_field_hint_t *hint) 39676 { 39677 _field_hints_t *f_ht = NULL; /* Field hints Structure. */ 39678 _field_hints_t *f_ht_new = NULL; /* Field hints Structure. */ 39679 _field_hint_t *hint_entry = NULL; /* Field hints Structure. */ 39680 _field_hint_t *hint_node = NULL; /* Field hints Structure. */ 39681 bcm_field_hint_t tmp_hint; /* Hint Node */ 39682 _field_control_t *fc; /* Field control structure. */ 39683 int rv = BCM_E_NONE; /* Return Value */ 39684 39685 /* Input parameters check. */ 39686 if (hint == NULL) { 39687 return BCM_E_PARAM; 39688 } 39689 39690 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 39691 39692 /* Check if the hint_id is already present in the hash table, 39693 * if so, see if a group is attached to the hintid or the hint 39694 * is already present in the hintid. */ 39695 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht)); 39696 39697 /* Hint id already present in Hints hash table */ 39698 if (f_ht != NULL) { 39699 LOG_DEBUG(BSL_LS_BCM_FP, 39700 (BSL_META_U(unit,"FP(unit %d) hint id %d already present in" 39701 " hash table\r\n"), unit, hint_id)); 39702 /* Check if hint_id is already associated with a group */ 39703 if (f_ht->grp_ref_count != 0) { 39704 LOG_DEBUG(BSL_LS_BCM_FP, 39705 (BSL_META_U(unit,"FP(unit %d) hint id %d already" 39706 " associated with a group \r\n"), unit, hint_id)); 39707 return BCM_E_BUSY; 39708 } 39709 39710 /* Check if max hint count per hintid reached */ 39711 if (f_ht->hint_count >= _FP_MAX_HINTS_PER_HINTID) { 39712 LOG_DEBUG(BSL_LS_BCM_FP, 39713 (BSL_META_U(unit, "FP(unit %d) Maximum hints limit reached" 39714 " for hintid %d\r\n"), unit, hint_id)); 39715 return BCM_E_FULL; 39716 } 39717 39718 /* Check if duplicate hint exists */ 39719 sal_memcpy (&tmp_hint, hint, sizeof (bcm_field_hint_t)); 39720 rv = _bcm_field_hints_node_get (unit, f_ht->hints, 39721 &tmp_hint, &hint_node); 39722 39723 if ((rv == BCM_E_NONE) && (hint_node != NULL)) { 39724 if (bcmFieldHintTypeExtraction != hint_node->hint->hint_type) { 39725 LOG_DEBUG(BSL_LS_BCM_FP, 39726 (BSL_META_U(unit, "FP(unit %d) Duplicate hint addition to " 39727 "hint id %d\r\n"), unit, hint_id)); 39728 return BCM_E_EXISTS; 39729 } 39730 } 39731 } else { 39732 _FP_XGS3_ALLOC (f_ht_new, sizeof (_field_hints_t), "Field Hints"); 39733 if (NULL == f_ht_new) { 39734 return BCM_E_MEMORY; 39735 } 39736 f_ht_new->hintid = hint_id; 39737 f_ht_new->grp_ref_count = 0; 39738 f_ht_new->next = NULL; 39739 } 39740 39741 /* Allocate a Hint Entry and add the hint into hint_entry */ 39742 _FP_XGS3_ALLOC (hint_entry, sizeof (_field_hint_t), 39743 "Field Hint Entry Structure"); 39744 if (NULL == hint_entry) { 39745 sal_free (f_ht_new); 39746 return BCM_E_MEMORY; 39747 } 39748 39749 /* Allocate a Hint Entry and add the hint into hint_entry */ 39750 _FP_XGS3_ALLOC (hint_entry->hint, sizeof (bcm_field_hint_t), 39751 "Field Hint Entry"); 39752 if (NULL == hint_entry->hint) { 39753 sal_free (hint_entry); 39754 sal_free (f_ht_new); 39755 return BCM_E_MEMORY; 39756 } 39757 39758 sal_memcpy (hint_entry->hint, hint, sizeof (bcm_field_hint_t)); 39759 hint_entry->next = NULL; 39760 39761 /* If entry is newly allocated add it to hash database */ 39762 if (f_ht_new != NULL) { 39763 /* Insert hint_id into Hash table. */ 39764 _FP_HASH_INSERT(fc->hints_hash, f_ht_new, 39765 (hint_id & _FP_HASH_INDEX_MASK(fc))); 39766 39767 LOG_DEBUG(BSL_LS_BCM_FP, 39768 (BSL_META_U(unit,"FP(unit %d) HintId added to hash" 39769 " table %d\r\n"), unit, hint_id)); 39770 f_ht = f_ht_new; 39771 } 39772 39773 _FP_HINTS_LINKLIST_INSERT(&(f_ht->hints),hint_entry); 39774 LOG_DEBUG(BSL_LS_BCM_FP, 39775 (BSL_META_U(unit, "FP(unit %d) Hint added to" 39776 " hint id %d\r\n"), unit, hint_id)); 39777 f_ht->hint_count++; 39778 39779 return BCM_E_NONE; 39780 } 39781 39782 39783 /* Function: _bcm_field_hints_node_get 39784 * 39785 * Purpose: 39786 * Return complete hint structure after passing partial structure 39787 * and return the hint_node present in the hint list. 39788 * Parameters: 39789 * unit - (IN) BCM device number. 39790 * hint_list - (IN) Linked List of hints attached to a hint id. 39791 * hint - (INOUT) bcm_field_hint_t structure 39792 * hint_node - (OUT) Node that matches the hint structure. 39793 * Returns: 39794 * BCM_E_XXXX. 39795 */ 39796 int _bcm_field_hints_node_get (int unit, 39797 _field_hint_t *hint_list, 39798 bcm_field_hint_t *hint, 39799 _field_hint_t **hint_node) 39800 { 39801 bcm_field_hint_t *hint_entry; /* Hint Entry */ 39802 39803 /* Input Parameter Check */ 39804 if ((hint_list == NULL) || (hint == NULL)) { 39805 return BCM_E_PARAM; 39806 } 39807 39808 /* Loop through the hints and search for a match, 39809 * if found, fill the entire hint and also return the hint_node 39810 * that matched */ 39811 while (hint_list != NULL) { 39812 hint_entry = hint_list->hint; 39813 if (hint_entry != NULL) { 39814 if (hint_entry->hint_type == hint->hint_type) { 39815 /* Hint Found */ 39816 switch (hint_entry->hint_type) { 39817 case bcmFieldHintTypeCompression: 39818 if (hint_entry->qual == hint->qual) { 39819 LOG_DEBUG(BSL_LS_BCM_FP, 39820 (BSL_META_U(unit, "FP(unit %d) Hint with" 39821 " type = Compression and " 39822 " qual_id %d found\r\n"), 39823 unit, hint->qual)); 39824 *hint_node = hint_list; 39825 /* Fill Flags, max_values, start_bit, end_bit */ 39826 hint->flags = hint_entry->flags; 39827 hint->max_values = hint_entry->max_values; 39828 hint->start_bit = hint_entry->start_bit; 39829 hint->end_bit = hint_entry->end_bit; 39830 return BCM_E_NONE; 39831 } 39832 break; 39833 case bcmFieldHintTypeExtraction: 39834 if (hint_entry->qual == hint->qual) { 39835 LOG_DEBUG(BSL_LS_BCM_FP, 39836 (BSL_META_U(unit, "FP(unit %d) Hint with" 39837 " type = Extraction and " 39838 " qual_id %d found\r\n"), 39839 unit, hint->qual)); 39840 *hint_node = hint_list; 39841 /* Fill Flags, max_values, start_bit, end_bit */ 39842 hint->flags = hint_entry->flags; 39843 hint->max_values = hint_entry->max_values; 39844 hint->start_bit = hint_entry->start_bit; 39845 hint->end_bit = hint_entry->end_bit; 39846 return BCM_E_NONE; 39847 } 39848 break; 39849 case bcmFieldHintTypeGroupAutoExpansion: 39850 { 39851 LOG_DEBUG(BSL_LS_BCM_FP, 39852 (BSL_META_U(unit, "FP(unit %d) Hint with" 39853 " type = GroupAutoExpansion " 39854 " found\r\n"), unit)); 39855 *hint_node = hint_list; 39856 /* Fill Flags, max_group_size */ 39857 hint->flags = hint_entry->flags; 39858 hint->max_group_size = hint_entry->max_group_size; 39859 return BCM_E_NONE; 39860 } 39861 break; 39862 case bcmFieldHintTypeExactMatch: 39863 if (hint_entry->qual == hint->qual) { 39864 LOG_DEBUG(BSL_LS_BCM_FP, 39865 (BSL_META_U(unit, "FP(unit %d) Hint with" 39866 " type = Exact Match and " 39867 " found\r\n"), unit)); 39868 *hint_node = hint_list; 39869 /* Fill Flags, Priority and Qualifier details. */ 39870 hint->flags = hint_entry->flags; 39871 hint->priority = hint_entry->priority; 39872 return BCM_E_NONE; 39873 } 39874 break; 39875 default: 39876 { 39877 LOG_DEBUG(BSL_LS_BCM_FP, 39878 (BSL_META_U(unit, "Unknown Hint Type\r\n"))); 39879 return BCM_E_PARAM; 39880 } 39881 break; 39882 } 39883 } 39884 } 39885 hint_list = hint_list->next; 39886 } 39887 return BCM_E_NOT_FOUND; 39888 } 39889 39890 /* Function: _bcm_field_hints_get 39891 * 39892 * Purpose: 39893 * Return complete hint structure after passing partial structure 39894 * Parameters: 39895 * unit - (IN) BCM device number. 39896 * hint_id - (IN) Hint id to which the hint should be associated 39897 * hint - (INOUT) bcm_field_hint_t structure 39898 * Returns: 39899 * BCM_E_XXXX. 39900 */ 39901 int _bcm_field_hints_get(int unit, 39902 bcm_field_hintid_t hint_id, 39903 bcm_field_hint_t *hint) 39904 { 39905 _field_hints_t *f_ht = NULL; /* Field hints Structure. */ 39906 _field_hint_t *hint_node = NULL; /* Field hints Structure. */ 39907 39908 39909 /* Input parameters check. */ 39910 if (hint == NULL) { 39911 return BCM_E_PARAM; 39912 } 39913 39914 39915 39916 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht)); 39917 if (f_ht == NULL) { 39918 LOG_DEBUG(BSL_LS_BCM_FP, 39919 (BSL_META_U(unit,"FP(unit %d) Hint id %d not present " 39920 "in Hints Hash table.\r\n"), unit, hint_id)); 39921 return (BCM_E_NOT_FOUND); 39922 } 39923 39924 /* Hints corresponding to hint_id not found */ 39925 if (f_ht->hints == NULL) { 39926 LOG_DEBUG(BSL_LS_BCM_FP, 39927 (BSL_META_U(unit, "FP(unit %d) No Hints are associated with " 39928 "hint id %d\r\n"), unit, hint_id)); 39929 return (BCM_E_NOT_FOUND); 39930 } 39931 39932 return _bcm_field_hints_node_get (unit, f_ht->hints, hint, &hint_node); 39933 } 39934 39935 39936 /* Function: _bcm_field_hints_delete 39937 * 39938 * Purpose: 39939 * Delete bcm_field_hint_t structure from a hint_id 39940 * Parameters: 39941 * unit - (IN) BCM device number. 39942 * hint_id - (IN) Hint Id. 39943 * hint - (IN) Hint to delete. 39944 * Returns: 39945 * BCM_E_XXXX. 39946 */ 39947 39948 int _bcm_field_hints_delete (int unit, 39949 bcm_field_hintid_t hint_id, 39950 bcm_field_hint_t *hint) 39951 { 39952 _field_hints_t *f_ht = NULL; /* Field hints Structure. */ 39953 _field_hint_t *hint_node = NULL; /* Field hints Structure. */ 39954 _field_control_t *fc; /* Field control structure. */ 39955 39956 /* Input parameters check. */ 39957 if (hint == NULL) { 39958 return BCM_E_PARAM; 39959 } 39960 39961 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 39962 39963 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht)); 39964 if (f_ht == NULL) { 39965 LOG_DEBUG(BSL_LS_BCM_FP, 39966 (BSL_META_U(unit, "FP (unit %d) HintId %d not present in" 39967 " hints hash table\r\n"), unit, hint_id)); 39968 return (BCM_E_NOT_FOUND); 39969 } 39970 39971 /* HintId is attached to a group. Hence deletion not allowed */ 39972 if (f_ht->grp_ref_count != 0) { 39973 LOG_DEBUG(BSL_LS_BCM_FP, 39974 (BSL_META_U(unit, "FP (unit %d) Group is associated " 39975 " with HintId %d\r\n"), unit, hint_id)); 39976 return BCM_E_BUSY; 39977 } 39978 39979 /* Hints corresponding to hint_id not found */ 39980 if (f_ht->hints == NULL) { 39981 LOG_DEBUG(BSL_LS_BCM_FP, 39982 (BSL_META_U(unit, "FP (unit %d) No hints are present in" 39983 " HintId %d\r\n"), unit, hint_id)); 39984 return (BCM_E_NOT_FOUND); 39985 } 39986 39987 BCM_IF_ERROR_RETURN(_bcm_field_hints_node_get (unit, f_ht->hints, 39988 hint, &hint_node)); 39989 39990 _FP_HINTS_LINKLIST_DELETE (&(f_ht->hints), _field_hint_t, hint_node); 39991 39992 if (f_ht->hint_count > 0) { 39993 f_ht->hint_count--; 39994 } 39995 39996 if (f_ht->hint_count == 0) { 39997 /* Remove hints for lookup hash. */ 39998 _FP_HASH_REMOVE(fc->hints_hash, _field_hints_t, f_ht, 39999 (hint_id & _FP_HASH_INDEX_MASK(fc))); 40000 sal_free (f_ht); 40001 f_ht = NULL; 40002 LOG_DEBUG(BSL_LS_BCM_FP, 40003 (BSL_META_U(unit, "FP (unit %d) HintId %d destroyed from Hint " 40004 "hash table\r\n"), unit, hint_id)); 40005 } 40006 40007 return BCM_E_NONE; 40008 } 40009 40010 40011 /* Function: _bcm_field_hints_delete_all 40012 * 40013 * Purpose: 40014 * Delete all hints from a hint_id 40015 * Parameters: 40016 * unit - (IN) BCM device number. 40017 * hint_id - (IN) Hint id to which the hint should be associated 40018 * Returns: 40019 * BCM_E_XXXX. 40020 */ 40021 int _bcm_field_hints_delete_all (int unit, 40022 bcm_field_hintid_t hint_id) 40023 { 40024 _field_hints_t *f_ht = NULL; /* Field hints Structure. */ 40025 _field_control_t *fc; /* Field control structure. */ 40026 40027 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 40028 40029 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht)); 40030 if (f_ht == NULL) { 40031 LOG_DEBUG(BSL_LS_BCM_FP, 40032 (BSL_META_U(unit, "FP (unit %d) HintId %d not present in " 40033 "Hint Hash table\r\n"), unit, hint_id)); 40034 return (BCM_E_NOT_FOUND); 40035 } 40036 40037 /* HintId is attached to a group. Hence deletion not allowed */ 40038 if (f_ht->grp_ref_count != 0) { 40039 LOG_DEBUG(BSL_LS_BCM_FP, 40040 (BSL_META_U(unit, "FP (unit %d) Group is associated with " 40041 " HintId %d\r\n"), unit, hint_id)); 40042 return BCM_E_BUSY; 40043 } 40044 40045 /* Hints corresponding to hint_id not found. 40046 * delete_all should return BCM_E_NONE 40047 */ 40048 if (f_ht->hints == NULL) { 40049 LOG_DEBUG(BSL_LS_BCM_FP, 40050 (BSL_META_U(unit, "FP (unit %d) No Hints present " 40051 " in a hintid %d\r\n"), unit, hint_id)); 40052 return (BCM_E_NONE); 40053 } 40054 40055 _FP_HINTS_LINKLIST_DELETE_ALL (&(f_ht->hints), _field_hint_t); 40056 40057 f_ht->hint_count = 0; 40058 40059 /* Remove hints for lookup hash. */ 40060 _FP_HASH_REMOVE(fc->hints_hash, _field_hints_t, f_ht, 40061 (hint_id & _FP_HASH_INDEX_MASK(fc))); 40062 sal_free (f_ht); 40063 f_ht = NULL; 40064 LOG_DEBUG(BSL_LS_BCM_FP, 40065 (BSL_META_U(unit, "FP (unit %d) HintId %d destroyed from Hint " 40066 " hash table\r\n"), unit, hint_id)); 40067 40068 return BCM_E_NONE; 40069 } 40070 40071 /* Function: _bcm_field_hints_dump 40072 * 40073 * Purpose: 40074 * Dump the hints database. 40075 * Parameters: 40076 * unit - (IN) BCM device number. 40077 * Returns: 40078 * BCM_E_XXXX. 40079 */ 40080 int _bcm_field_hints_dump (int unit) 40081 { 40082 bcm_field_hintid_t id = 0; /* Hint Id */ 40083 _field_control_t *fc; /* Field control structure.*/ 40084 40085 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 40086 40087 for (id = _FP_HINT_ID_BASE; id < _FP_HINT_ID_MAX; id++) { 40088 if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, id)) { 40089 LOG_DEBUG(BSL_LS_BCM_FP, 40090 (BSL_META_U(unit, "HINTID %d \r\n"), id)); 40091 LOG_DEBUG(BSL_LS_BCM_FP, 40092 (BSL_META_U(unit,"=========\r\n"))); 40093 _bcm_field_hints_display (unit, id); 40094 } 40095 } 40096 40097 return BCM_E_NONE; 40098 } 40099 40100 /* Function: _bcm_field_hints_display 40101 * 40102 * Purpose: 40103 * Dump the hints database. 40104 * Parameters: 40105 * unit - (IN) BCM device number. 40106 * hint_id - (IN) Hint id to which the hint should be associated. 40107 * Returns: 40108 * BCM_E_XXXX. 40109 */ 40110 int _bcm_field_hints_display (int unit, bcm_field_hintid_t hint_id) 40111 { 40112 _field_hints_t *f_ht = NULL; /* Field hints Structure. */ 40113 _field_hint_t *hints_dump = NULL; /* Field hints Structure. */ 40114 bcm_field_hint_t *hint_entry; /* Hint Entry */ 40115 uint32 hint_count = 1; /* Hint Count */ 40116 40117 40118 40119 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht)); 40120 if (f_ht == NULL) { 40121 LOG_DEBUG(BSL_LS_BCM_FP, 40122 (BSL_META_U(unit,"FP (unit %d) HintId %d not present in " 40123 "Hint Hash table\r\n"), unit, hint_id)); 40124 return (BCM_E_NOT_FOUND); 40125 } 40126 40127 hints_dump = f_ht->hints; 40128 40129 LOG_DEBUG(BSL_LS_BCM_FP, 40130 (BSL_META_U(unit,"Hints information for Hint ID (%d)\r\n"),hint_id)); 40131 LOG_DEBUG(BSL_LS_BCM_FP, 40132 (BSL_META_U(unit,"==================================\r\n"))); 40133 LOG_DEBUG(BSL_LS_BCM_FP, 40134 (BSL_META_U(unit,"Number of Groups Attached = %d\r\n"), 40135 f_ht->grp_ref_count)); 40136 LOG_DEBUG(BSL_LS_BCM_FP, 40137 (BSL_META_U(unit, "Number of Hints present = %d\r\n"), 40138 f_ht->hint_count)); 40139 40140 while (hints_dump != NULL) { 40141 hint_entry = hints_dump->hint; 40142 if (hint_entry != NULL) { 40143 LOG_DEBUG(BSL_LS_BCM_FP, 40144 (BSL_META_U(unit, "Hint %d\r\n"), hint_count)); 40145 LOG_DEBUG(BSL_LS_BCM_FP, 40146 (BSL_META_U(unit, "=======\r\n"))); 40147 if (hint_entry->hint_type == bcmFieldHintTypeGroupAutoExpansion) { 40148 LOG_DEBUG(BSL_LS_BCM_FP, 40149 (BSL_META_U(unit, "Hint Type = AutoExpansion\r\n"))); 40150 } else if (hint_entry->hint_type == bcmFieldHintTypeCompression) { 40151 LOG_DEBUG(BSL_LS_BCM_FP, 40152 (BSL_META_U(unit, "HintType = Compression\r\n"))); 40153 } else if (hint_entry->hint_type == bcmFieldHintTypeExtraction) { 40154 LOG_DEBUG(BSL_LS_BCM_FP, 40155 (BSL_META_U(unit, "HintType = Extraction\r\n"))); 40156 } else if (hint_entry->hint_type == bcmFieldHintTypeExactMatch) { 40157 LOG_DEBUG(BSL_LS_BCM_FP, 40158 (BSL_META_U(unit, "HintType = Exact Match\r\n"))); 40159 } else { 40160 LOG_DEBUG(BSL_LS_BCM_FP, 40161 (BSL_META_U(unit, "HintType = Unknown\r\n"))); 40162 } 40163 LOG_DEBUG(BSL_LS_BCM_FP, 40164 (BSL_META_U(unit, "Qual = %u\r\n"), 40165 hint_entry->qual)); 40166 LOG_DEBUG(BSL_LS_BCM_FP, 40167 (BSL_META_U(unit, "Max Values = %u\r\n"), 40168 hint_entry->max_values)); 40169 LOG_DEBUG(BSL_LS_BCM_FP, 40170 (BSL_META_U(unit, "Start Bit = %u\r\n"), 40171 hint_entry->start_bit)); 40172 LOG_DEBUG(BSL_LS_BCM_FP, 40173 (BSL_META_U(unit, "End Bit = %u\r\n"), 40174 hint_entry->end_bit)); 40175 LOG_DEBUG(BSL_LS_BCM_FP, 40176 (BSL_META_U(unit, "Flags = %u\r\n"), 40177 hint_entry->flags)); 40178 LOG_DEBUG(BSL_LS_BCM_FP, 40179 (BSL_META_U(unit, "Max Group Size = %u\r\n"), 40180 hint_entry->max_group_size)); 40181 LOG_DEBUG(BSL_LS_BCM_FP, 40182 (BSL_META_U(unit, "Exact Match Group Priority = %u\r\n"), 40183 hint_entry->priority)); 40184 } 40185 hint_count++; 40186 hints_dump = hints_dump->next; 40187 } 40188 40189 return BCM_E_NONE; 40190 } 40191 40192 int 40193 _field_aset_install(int unit, _field_group_t *fg) 40194 { 40195 #ifdef BCM_TRIUMPH3_SUPPORT 40196 if (SOC_IS_TRIUMPH3(unit)) { 40197 return (_bcm_field_tr3_aset_install(unit, fg)); 40198 } 40199 #endif 40200 40201 return (BCM_E_NONE); 40202 } 40203 40204 /* 40205 * Function: 40206 * _field_group_status_calc 40207 * Purpose: 40208 * Fill in the values of a group status struct. 40209 * Parameters: 40210 * unit - (IN) BCM device number. 40211 * fg - (OUT)Group with up-to-date status structure 40212 * Returns: 40213 * BCM_E_XXX 40214 */ 40215 int 40216 _bcm_field_group_status_calc(int unit, _field_group_t *fg) 40217 { 40218 bcm_field_group_status_t *status; 40219 _field_stage_t *stage_fc; /* Stage field control structure. */ 40220 _field_slice_t *fs; /* Field slice control structure. */ 40221 int count=0; /* Generic purposes counter. */ 40222 int rv; /* Operation return status. */ 40223 int slice_index; 40224 bcm_pbmp_t all_pbmp; 40225 int ratio = 0; 40226 40227 /* Input parameters check. */ 40228 if (NULL == fg) { 40229 return (BCM_E_PARAM); 40230 } 40231 40232 BCM_IF_ERROR_RETURN 40233 (_field_stage_control_get(unit, fg->stage_id, &stage_fc)); 40234 40235 status = &fg->group_status; 40236 40237 /* Calculate total number of entries slices in group slices. */ 40238 40239 status->entries_total = 0; 40240 fs = &fg->slices[0]; 40241 40242 if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 40243 ratio = 2; 40244 } else { 40245 ratio = 1; 40246 } 40247 40248 while (fs != NULL) 40249 { 40250 status->entries_total += fs->entry_count/ratio; 40251 fs = fs->next; 40252 } 40253 40254 status->entries_free = 0; 40255 fs = &fg->slices[0]; 40256 40257 while (fs != NULL) 40258 { 40259 _bcm_field_entries_free_get(unit, fs, fg, &count); 40260 status->entries_free += count; 40261 fs = fs->next; 40262 } 40263 40264 fs = fg->slices; 40265 40266 #if defined(BCM_TOMAHAWK_SUPPORT) 40267 if (soc_feature(unit, soc_feature_field_multi_pipe_support) 40268 && (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id)) { 40269 rv = _bcm_field_th_flex_counter_status_get(unit, fg, 40270 &(status->counters_total), 40271 &(status->counters_free)); 40272 BCM_IF_ERROR_RETURN(rv); 40273 40274 } else 40275 #endif 40276 { 40277 40278 status->counters_total = _bcm_field_counters_total_get(stage_fc, fs); 40279 status->counters_free = _bcm_field_counter_free_get(stage_fc, fs); 40280 } 40281 40282 status->meters_total = _bcm_field_meters_total_get(stage_fc, fg->instance, fs); 40283 status->meters_free = _bcm_field_meter_free_get(stage_fc, fg, fs); 40284 40285 if (!(fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE)) 40286 { 40287 fs += 1; 40288 40289 /* If device supports Per Slice Counters, need to account the counters 40290 * associated to the secondary slice. 40291 */ 40292 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) && 40293 !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) { 40294 status->counters_total += fs->counters_count; 40295 status->counters_free += _bcm_field_counter_free_get(stage_fc, fs); 40296 } 40297 40298 /* 40299 * If device stage supports global meter pools, then 40300 * meter information is already updated. 40301 */ 40302 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) { 40303 status->meters_total += fs->meters_count; 40304 status->meters_free += _bcm_field_meter_free_get(stage_fc, 40305 fg, fs); 40306 } 40307 } 40308 40309 if (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION) 40310 { 40311 /* For expandable groups, find free slices and add the info */ 40312 BCM_PBMP_CLEAR(all_pbmp); 40313 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 40314 40315 for (slice_index = 0; slice_index < stage_fc->tcam_slices; 40316 ++slice_index) 40317 { 40318 /* Ignore the secondary and tertiary slices */ 40319 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 40320 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 40321 if (fg->slices[1].slice_number == slice_index) { 40322 continue; 40323 } 40324 } 40325 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 40326 if (fg->slices[2].slice_number == slice_index) { 40327 continue; 40328 } 40329 } 40330 #if defined(BCM_TOMAHAWK_SUPPORT) 40331 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 40332 _BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 40333 40334 rv = _bcm_field_th_group_add_slice_validate(unit, stage_fc, fg, 40335 slice_index); 40336 } else 40337 #endif /* BCM_TOMAHAWK_SUPPORT */ 40338 { 40339 rv = _field_group_ports_validate(unit, stage_fc, fg->instance, 40340 slice_index, fg->flags, all_pbmp); 40341 } 40342 40343 if (BCM_SUCCESS(rv)) { 40344 fs = stage_fc->slices[fg->instance] + slice_index; 40345 40346 status->entries_total += fs->entry_count/ratio; 40347 status->entries_free += fs->entry_count/ratio; 40348 40349 /* If device supports Per Slice Counters, need to account the counters 40350 * associated to the secondary slice. 40351 */ 40352 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) && 40353 !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) { 40354 status->counters_total += fs->counters_count; 40355 status->counters_free += fs->counters_count; 40356 } 40357 40358 /* 40359 * If device stage supports global meter pools, then 40360 * meter information is already updated. 40361 */ 40362 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) { 40363 status->meters_total += fs->meters_count; 40364 status->meters_free += fs->meters_count; 40365 } 40366 } 40367 } 40368 40369 /* Go through used slice list except first slice for expandable groups */ 40370 fs = &fg->slices[0]; 40371 while (fs != NULL) { 40372 fs = fs->next; 40373 if (fs != NULL) { 40374 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) && 40375 !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) { 40376 status->counters_total += fs->counters_count; 40377 status->counters_free += _bcm_field_counter_free_get(stage_fc, fs); 40378 } 40379 40380 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) { 40381 status->meters_total += fs->meters_count; 40382 status->meters_free += _bcm_field_meter_free_get(stage_fc, 40383 fg, fs); 40384 } 40385 } 40386 } 40387 } 40388 40389 return (BCM_E_NONE); 40390 } 40391 40392 /* 40393 * Function : 40394 * _bcm_field_is_stage_range_check_exist(unit, stage) (internal) 40395 * Purpose : 40396 * Checks whether the field stage has existing range checkers 40397 * Parameters : 40398 * unit - (IN) BCM device number 40399 * stage - (IN) Pipeline stage id number 40400 * Return Values: 40401 * BCM_E_EXISTS - There are existing range checkers. 40402 * BCM_E_NONE - No Existing range checkers. 40403 */ 40404 int _bcm_field_is_stage_range_check_exist (int unit, 40405 _field_stage_id_t stage) 40406 { 40407 _field_stage_t *stage_fc; /* Stage field control info.*/ 40408 _field_control_t *fc; /* Field control structure. */ 40409 int rv; /* Operation return status. */ 40410 40411 rv = _field_control_get(unit, &fc); 40412 BCM_IF_ERROR_RETURN(rv); 40413 40414 rv = _field_stage_control_get(unit, stage, &stage_fc); 40415 BCM_IF_ERROR_RETURN(rv); 40416 40417 if (stage_fc->ranges != NULL) { 40418 return BCM_E_EXISTS; 40419 } 40420 return BCM_E_NONE; 40421 } 40422 40423 40424 /* 40425 * Function: _bcm_field_entry_create_id 40426 * 40427 * Purpose: 40428 * Create a blank entry group based on a group; 40429 * allows selection of a specific slot in a slice 40430 * 40431 * Parameters: 40432 * unit - (IN) BCM device number. 40433 * group - (IN) Field group ID. 40434 * entry - (IN) Requested entry ID; must be in the range prio_min through 40435 * prio_max as returned by bcm_field_group_status_get(). 40436 * Returns: 40437 * BCM_E_INIT - unit not initialized 40438 * BCM_E_EXISTS - Entry ID already in use 40439 * BCM_E_NOT_FOUND - Group ID not found in unit 40440 * BCM_E_MEMORY - allocation failure 40441 * BCM_E_NONE - Success 40442 */ 40443 int 40444 _bcm_field_entry_create_id(int unit, 40445 bcm_field_group_t group, 40446 bcm_field_entry_t entry) 40447 { 40448 _field_group_t *fg; /* Field group structure. */ 40449 int rv; 40450 40451 FP_LOCK(unit); 40452 40453 rv = _field_group_get(unit, group, &fg); 40454 if (BCM_FAILURE(rv)) { 40455 FP_UNLOCK(unit); 40456 return (rv); 40457 } 40458 40459 /* When MaxGroupSizeHardLimit is set and limit is reached 40460 * return BCM_E_FULL */ 40461 if (fg->flags & _FP_GROUP_MAX_SIZE_HARD_LIMIT) { 40462 if (fg->max_group_size - 40463 (fg->group_status.entry_count) <= 0) { 40464 FP_UNLOCK(unit); 40465 return BCM_E_FULL; 40466 } 40467 } 40468 40469 #if defined(BCM_TOMAHAWK_SUPPORT) 40470 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 40471 (fg->stage_id == _BCM_FIELD_STAGE_CLASS)) { 40472 rv = _bcm_field_th_class_entry_create(unit, group, entry); 40473 FP_UNLOCK(unit); 40474 return (rv); 40475 } 40476 #endif /* BCM_TOMAHAWK_SUPPORT */ 40477 40478 rv = _field_entry_create_id(unit, group, entry); 40479 40480 FP_UNLOCK(unit); 40481 return (rv); 40482 } 40483 40484 40485 /* 40486 * Function: _bcm_field_entry_copy_id 40487 * 40488 * Purpose: 40489 * Create a copy of an existing entry with a requested ID 40490 * 40491 * Parameters: 40492 * unit - BCM device number 40493 * src_entry - Source entry to copy 40494 * dst_entry - Destination entry for copy 40495 * flags - flags to control entry copy 40496 * 0 : stats(if attached)will be copied 40497 * BCM_FIELD_ENTRY_COPY_WITHOUT_STATS : Stats are not copied 40498 * 40499 * Returns: 40500 * BCM_E_INIT - BCM Unit not initialized 40501 * BCM_E_NOT_FOUND - Source Entry ID not found 40502 * BCM_E_XXX - Error code from bcm_field_entry_create_id() 40503 * BCM_E_NONE - Success 40504 */ 40505 40506 int 40507 _bcm_field_entry_copy_id(int unit, 40508 bcm_field_entry_t src_entry, 40509 bcm_field_entry_t dst_entry, 40510 uint32 flags) 40511 { 40512 _field_entry_t *f_ent_src, *f_ent_dst; 40513 int parts_count = 0; 40514 _field_action_t *fa_src; 40515 int free_tcam = FALSE; 40516 int rv; 40517 int i; 40518 bcm_pbmp_t pbmp; 40519 _field_stage_t *stage_fc; 40520 40521 40522 FP_LOCK(unit); 40523 40524 rv = _bcm_field_entry_get_by_id(unit, src_entry, &f_ent_src); 40525 if (BCM_FAILURE(rv)) { 40526 FP_UNLOCK(unit); 40527 return (rv); 40528 } 40529 40530 rv = _field_stage_control_get(unit, f_ent_src->group->stage_id, &stage_fc); 40531 if (BCM_FAILURE(rv)) { 40532 FP_UNLOCK(unit); 40533 return (rv); 40534 } 40535 40536 /* Get number of entry parts . */ 40537 rv = _bcm_field_entry_tcam_parts_count (unit, f_ent_src->group->stage_id, 40538 f_ent_src->group->flags, &parts_count); 40539 if (BCM_FAILURE(rv)) { 40540 FP_UNLOCK(unit); 40541 return (rv); 40542 } 40543 40544 40545 /* Creating a new destination entry sets the unit, eid, gid, slice_idx, 40546 * ext, dirty, fs and next fields. Also, it correctly creates multiple 40547 * physical entry structures for wide-mode groups. 40548 */ 40549 40550 rv = _bcm_field_entry_create_id(unit, f_ent_src->group->gid, 40551 dst_entry); 40552 if (BCM_FAILURE(rv)) { 40553 FP_UNLOCK(unit); 40554 return (rv); 40555 } 40556 40557 rv = _bcm_field_entry_get_by_id(unit, dst_entry, &f_ent_dst); 40558 if (BCM_FAILURE(rv)) { 40559 FP_UNLOCK(unit); 40560 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry)); 40561 return (rv); 40562 } 40563 40564 for (i = 0; i < parts_count; i++) { 40565 if (NULL == f_ent_src[i].tcam.key) { 40566 free_tcam = TRUE; 40567 } 40568 40569 #if defined(BCM_TRIDENT2_SUPPORT) 40570 if (SOC_IS_TD2_TT2(unit) && 40571 (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 40572 (f_ent_dst+i)->efp_key_match_type = (f_ent_src+i)->efp_key_match_type; 40573 } 40574 #endif 40575 40576 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent_src + i); 40577 if (BCM_FAILURE(rv)) { 40578 FP_UNLOCK(unit); 40579 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry)); 40580 return (rv); 40581 } 40582 40583 /* Entry create id might allocated tcam already. */ 40584 rv = _bcm_field_qual_tcam_key_mask_free(unit, f_ent_dst + i); 40585 if (BCM_FAILURE(rv)) { 40586 FP_UNLOCK(unit); 40587 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry)); 40588 return (rv); 40589 } 40590 40591 /* Copy qualification data. */ 40592 sal_memcpy(&f_ent_dst[i].tcam, &f_ent_src[i].tcam, 40593 sizeof(_field_tcam_t)); 40594 sal_memcpy(&f_ent_dst[i].extra_tcam, &f_ent_src[i].extra_tcam, 40595 sizeof(_field_tcam_t)); 40596 40597 #if defined(BCM_TRIDENT2_SUPPORT) 40598 if (SOC_IS_TD2_TT2(unit) && 40599 (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 40600 sal_memcpy(&f_ent_dst[i].key_match_tcam, 40601 &f_ent_src[i].key_match_tcam, 40602 sizeof(_field_tcam_t)); 40603 } 40604 #endif 40605 f_ent_dst[i].tcam.key = NULL;/* Do not copy allocated part.*/ 40606 f_ent_dst[i].tcam.mask = NULL;/* Do not copy allocated part.*/ 40607 f_ent_dst[i].extra_tcam.key = NULL;/* Do not copy allocated part.*/ 40608 f_ent_dst[i].extra_tcam.mask = NULL;/* Do not copy allocated part.*/ 40609 if (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 40610 f_ent_dst[i].tcam.key_hw = NULL; 40611 f_ent_dst[i].tcam.mask_hw = NULL; 40612 } 40613 40614 #if defined(BCM_TRIDENT2_SUPPORT) 40615 if (SOC_IS_TD2_TT2(unit) && 40616 (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 40617 f_ent_dst[i].key_match_tcam.key = NULL;/* Do not copy 40618 allocated part.*/ 40619 f_ent_dst[i].key_match_tcam.mask = NULL;/* Do not copy 40620 allocated part.*/ 40621 } 40622 #endif 40623 40624 if (f_ent_src[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 40625 f_ent_dst[i].flags |= _FP_ENTRY_USES_IPBM_OVERLAY; 40626 } 40627 40628 /* Allocate tcam key and mask for destination entry. */ 40629 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent_dst + i); 40630 if (BCM_FAILURE(rv)) { 40631 FP_UNLOCK(unit); 40632 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry)); 40633 return (rv); 40634 } 40635 40636 /* Copy key and mask information. */ 40637 sal_memcpy(f_ent_dst[i].tcam.key, f_ent_src[i].tcam.key, 40638 f_ent_src[i].tcam.key_size); 40639 sal_memcpy(f_ent_dst[i].tcam.mask, f_ent_src[i].tcam.mask, 40640 f_ent_src[i].tcam.key_size); 40641 40642 if (f_ent_src[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 40643 sal_memcpy(f_ent_dst[i].extra_tcam.key, 40644 f_ent_src[i].extra_tcam.key, 40645 f_ent_src[i].extra_tcam.key_size); 40646 40647 sal_memcpy(f_ent_dst[i].extra_tcam.mask, 40648 f_ent_src[i].extra_tcam.mask, 40649 f_ent_src[i].extra_tcam.key_size); 40650 } 40651 #if defined(BCM_TRIDENT2_SUPPORT) 40652 if (SOC_IS_TD2_TT2(unit) && 40653 (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 40654 /* Copy key and mask information. */ 40655 sal_memcpy(f_ent_dst[i].key_match_tcam.key, 40656 f_ent_src[i].key_match_tcam.key, 40657 f_ent_dst[i].key_match_tcam.key_size); 40658 sal_memcpy(f_ent_dst[i].key_match_tcam.mask, 40659 f_ent_src[i].key_match_tcam.mask, 40660 f_ent_dst[i].key_match_tcam.key_size); 40661 40662 } 40663 #endif 40664 if (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 40665 sal_memcpy(f_ent_dst[i].tcam.key_hw, 40666 f_ent_src[i].tcam.key_hw, 40667 f_ent_src[i].tcam.key_size); 40668 sal_memcpy(f_ent_dst[i].tcam.mask_hw, 40669 f_ent_src[i].tcam.mask_hw, 40670 f_ent_src[i].tcam.key_size); 40671 } 40672 40673 if (free_tcam) { 40674 if (NULL != f_ent_src[i].tcam.key) { 40675 sal_free(f_ent_src[i].tcam.key); 40676 sal_free(f_ent_src[i].tcam.mask); 40677 } 40678 if (f_ent_src[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 40679 if (NULL != f_ent_src[i].extra_tcam.key) { 40680 sal_free(f_ent_src[i].extra_tcam.key); 40681 sal_free(f_ent_src[i].extra_tcam.mask); 40682 } 40683 } 40684 f_ent_src[i].tcam.key = f_ent_src[i].tcam.mask = 40685 f_ent_src[i].extra_tcam.key = f_ent_src[i].extra_tcam.mask = 40686 NULL; 40687 #if defined(BCM_TRIDENT2_SUPPORT) 40688 if (SOC_IS_TD2_TT2(unit) && 40689 (f_ent_src[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 40690 if (NULL != f_ent_src[i].key_match_tcam.key) { 40691 sal_free(f_ent_src[i].key_match_tcam.key); 40692 sal_free(f_ent_src[i].key_match_tcam.mask); 40693 } 40694 f_ent_src[i].key_match_tcam.key = NULL; 40695 f_ent_src[i].key_match_tcam.mask = NULL; 40696 } 40697 #endif 40698 free_tcam = FALSE; 40699 } 40700 } 40701 40702 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT) 40703 if ((soc_feature(unit, soc_feature_field_ingress_ipbm)) 40704 || (soc_feature(unit, soc_feature_field_multi_pipe_support))) { 40705 BCM_PBMP_ASSIGN(f_ent_dst->pbmp.data, f_ent_src->pbmp.data); 40706 BCM_PBMP_ASSIGN(f_ent_dst->pbmp.mask, f_ent_src->pbmp.mask); 40707 } 40708 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */ 40709 40710 /* Copy counter, if it exists. */ 40711 /* In case of internal backup entry, copy only for 40712 * devices that have global/flex counter pools 40713 */ 40714 if (!(flags & BCM_FIELD_ENTRY_COPY_WITHOUT_STATS)) { 40715 if (f_ent_src->statistic.flags & _FP_ENTRY_STAT_VALID) { 40716 rv = bcm_esw_field_entry_stat_attach(unit, dst_entry, 40717 f_ent_src->statistic.sid); 40718 if (BCM_FAILURE(rv)) { 40719 FP_UNLOCK(unit); 40720 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy 40721 (unit, dst_entry)); 40722 return (rv); 40723 } 40724 /* Preseve original entry flags. */ 40725 f_ent_dst->statistic.flags = (f_ent_src->statistic.flags & \ 40726 (_FP_ENTRY_STAT_VALID | _FP_ENTRY_STAT_EMPTY | 40727 _FP_ENTRY_STAT_USE_EVEN | _FP_ENTRY_STAT_USE_ODD)); 40728 f_ent_dst->statistic.flags |= _FP_ENTRY_STAT_DIRTY; 40729 } 40730 } 40731 40732 /* Copy meter, if it exists. */ 40733 for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++) { 40734 if (f_ent_src->policer[i].flags & _FP_POLICER_VALID) { 40735 rv = bcm_esw_field_entry_policer_attach(unit, dst_entry, i, 40736 f_ent_src->policer[i].pid); 40737 if (BCM_FAILURE(rv)) { 40738 FP_UNLOCK(unit); 40739 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy 40740 (unit, dst_entry)); 40741 return (rv); 40742 } 40743 } 40744 } 40745 40746 /* Copy source entry's action linked list. */ 40747 /* This also copies the counter specific actions */ 40748 for (i = 0; i < parts_count; i++) { 40749 for (fa_src = f_ent_src[i].actions; 40750 fa_src != NULL; 40751 fa_src = fa_src->next) { 40752 40753 int idx = 0; 40754 if ((bcmFieldActionRedirectPbmp == fa_src->action) 40755 || (bcmFieldActionEgressMask == fa_src->action) 40756 || (bcmFieldActionEgressPortsAdd == fa_src->action) 40757 || (bcmFieldActionRedirectBcastPbmp == fa_src->action)) { 40758 40759 SOC_PBMP_CLEAR(pbmp); 40760 40761 for (idx = 0; (idx < _FP_ACTION_PARAM_SZ) && 40762 (idx < SOC_PBMP_WORD_MAX); idx++) { 40763 40764 SOC_PBMP_WORD_SET(pbmp, idx, fa_src->param[idx]); 40765 } 40766 40767 rv = bcm_esw_field_action_ports_add(unit, 40768 dst_entry, 40769 fa_src->action, 40770 pbmp); 40771 } else { 40772 rv = bcm_esw_field_action_add(unit, 40773 dst_entry, 40774 fa_src->action, 40775 fa_src->param[0], 40776 fa_src->param[1]); 40777 } 40778 if (BCM_FAILURE(rv)) { 40779 FP_UNLOCK(unit); 40780 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy 40781 (unit, dst_entry)); 40782 return (rv); 40783 } 40784 } 40785 } 40786 f_ent_dst->flags |= _FP_ENTRY_DIRTY; 40787 40788 if (!(f_ent_src->flags & _FP_ENTRY_CREATED_WITHOUT_PRIO)) { 40789 /* Set the destination entry's priority to the same as the source's. */ 40790 rv = _field_entry_prio_set(unit, dst_entry, f_ent_src->prio); 40791 40792 if (BCM_FAILURE(rv)) { 40793 FP_UNLOCK(unit); 40794 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry)); 40795 return (rv); 40796 } 40797 } 40798 FP_UNLOCK(unit); 40799 return (rv); 40800 } 40801 40802 40803 40804 /* 40805 * Function: 40806 * _field_qualify_VlanTranslationHit 40807 * Purpose: 40808 * Set match criteria for bcmFieildQualifyVlanTranslationHit 40809 * qualifier from the field entry. 40810 * Parameters: 40811 * unit - (IN) Unit number. 40812 * entry - (IN) BCM field entry id. 40813 * data - (OUT) Qualifier match data. 40814 * mask - (OUT) Qualifier match mask. 40815 * Returns: 40816 * BCM_E_XXX 40817 * Notes: 40818 */ 40819 40820 int 40821 _field_qualify_VlanTranslationHit(int unit, 40822 bcm_field_entry_t entry, 40823 uint8 *data, 40824 uint8 *mask 40825 ) 40826 { 40827 40828 /* Check for valid data mask combinations */ 40829 switch (*data) { 40830 case BCM_FIELD_VXLT_LOOKUP_STATUS_NO_HIT: 40831 *data = 0x0; 40832 *mask = 0x1; 40833 break; 40834 case BCM_FIELD_VXLT_LOOKUP_STATUS_HIT: 40835 *data = 0x1; 40836 *mask = 0x1; 40837 break; 40838 default: 40839 LOG_ERROR(BSL_LS_BCM_FP, 40840 (BSL_META_U(unit, 40841 "FP(unit %d) Error: PacketRes *data=%#x undefined\n"), 40842 unit, 40843 *data)); 40844 return (BCM_E_PARAM); 40845 } 40846 40847 return (BCM_E_NONE); 40848 } 40849 40850 /* 40851 * Function: 40852 * _field_qualify_VlanTranslationHit_get 40853 * Purpose: 40854 * Get match criteria for bcmFieildQualifyVlanTranslationHit 40855 * qualifier from the field entry. 40856 * Parameters: 40857 * unit - (IN) Unit number. 40858 * entry - (IN) BCM field entry id. 40859 * data - (OUT) Qualifier match data. 40860 * mask - (OUT) Qualifier match mask. 40861 * Returns: 40862 * BCM_E_XXX 40863 * Notes: 40864 */ 40865 int 40866 _field_qualify_VlanTranslationHit_get(int unit, 40867 bcm_field_entry_t entry, 40868 uint8 *data, 40869 uint8 *mask 40870 ) 40871 { 40872 /* Translate data #defines to hardware encodings */ 40873 switch (*data) { 40874 case 0x0: 40875 *data = BCM_FIELD_VXLT_LOOKUP_STATUS_NO_HIT; 40876 break; 40877 case 0x1: 40878 *data = BCM_FIELD_VXLT_LOOKUP_STATUS_HIT; 40879 break; 40880 default: 40881 return (BCM_E_INTERNAL); 40882 } 40883 40884 /* 40885 * In bcm_field_qualify_VlanTranslationHit, mask passed by application code 40886 * will be ignored, and SDK will internally set the right mask in h/w. 40887 * In this get routine, giving h/w encoded mask confuses end user. 40888 * So mask is setting to EXACT_MASK(1bit is allocated in h/w to qualify 40889 * Vlan Translation Hit Status). 40890 */ 40891 40892 *mask = 0x1; 40893 40894 return (BCM_E_NONE); 40895 } 40896 40897 40898 int 40899 _field_qualify_PacketRes(int unit, 40900 bcm_field_entry_t entry, 40901 uint32 *data, 40902 uint32 *mask 40903 ) 40904 { 40905 switch (*data) { 40906 case BCM_FIELD_PKT_RES_UNKNOWN: 40907 *data = 0x0; 40908 break; 40909 case BCM_FIELD_PKT_RES_CONTROL: 40910 *data = 0x1; 40911 break; 40912 case BCM_FIELD_PKT_RES_BPDU: 40913 *data = 0x2; 40914 break; 40915 case BCM_FIELD_PKT_RES_L2BC: 40916 *data = 0x3; 40917 break; 40918 case BCM_FIELD_PKT_RES_L2UC: 40919 *data = 0x4; 40920 break; 40921 case BCM_FIELD_PKT_RES_L2UNKNOWN: 40922 *data = 0x5; 40923 break; 40924 case BCM_FIELD_PKT_RES_L3MCUNKNOWN: 40925 #ifdef BCM_RAPTOR1_SUPPORT 40926 if (SOC_IS_RAPTOR(unit)) { 40927 return BCM_E_UNAVAIL; 40928 } 40929 #endif /* BCM_RAPTOR1_SUPPORT */ 40930 *data = 0x6; 40931 break; 40932 case BCM_FIELD_PKT_RES_L3MCKNOWN: 40933 #ifdef BCM_RAPTOR1_SUPPORT 40934 if (SOC_IS_RAPTOR(unit)) { 40935 return BCM_E_UNAVAIL; 40936 } 40937 #endif /* BCM_RAPTOR1_SUPPORT */ 40938 *data = 0x7; 40939 break; 40940 case BCM_FIELD_PKT_RES_L2MCKNOWN: 40941 *data = 0x8; 40942 break; 40943 case BCM_FIELD_PKT_RES_L2MCUNKNOWN: 40944 *data = 0x9; 40945 break; 40946 case BCM_FIELD_PKT_RES_L3UCKNOWN: 40947 #ifdef BCM_RAPTOR1_SUPPORT 40948 if (SOC_IS_RAPTOR(unit)) { 40949 return BCM_E_UNAVAIL; 40950 } 40951 #endif /* BCM_RAPTOR1_SUPPORT */ 40952 *data = 0xA; 40953 break; 40954 case BCM_FIELD_PKT_RES_L3UCUNKNOWN: 40955 #ifdef BCM_RAPTOR1_SUPPORT 40956 if (SOC_IS_RAPTOR(unit)) { 40957 return BCM_E_UNAVAIL; 40958 } 40959 #endif /* BCM_RAPTOR1_SUPPORT */ 40960 *data = 0xB; 40961 break; 40962 case BCM_FIELD_PKT_RES_MPLSKNOWN: 40963 if (SOC_IS_TR_VL(unit)) { 40964 *data = 0xC; 40965 break; 40966 } 40967 return (BCM_E_UNAVAIL); 40968 case BCM_FIELD_PKT_RES_MPLSL3KNOWN: 40969 if (SOC_IS_TR_VL(unit)) { 40970 *data = 0xD; 40971 break; 40972 } 40973 return (BCM_E_UNAVAIL); 40974 case BCM_FIELD_PKT_RES_MPLSL2KNOWN: 40975 if (SOC_IS_TR_VL(unit)) { 40976 *data = 0xE; 40977 break; 40978 } 40979 return (BCM_E_UNAVAIL); 40980 case BCM_FIELD_PKT_RES_MPLSUNKNOWN: 40981 if (SOC_IS_TR_VL(unit)) { 40982 *data = 0xF; 40983 break; 40984 } 40985 return (BCM_E_UNAVAIL); 40986 case BCM_FIELD_PKT_RES_MIMKNOWN: 40987 if (SOC_IS_TR_VL(unit)) { 40988 *data = 0x10; 40989 break; 40990 } 40991 return (BCM_E_UNAVAIL); 40992 case BCM_FIELD_PKT_RES_MIMUNKNOWN: 40993 if (SOC_IS_TR_VL(unit)) { 40994 *data = 0x11; 40995 break; 40996 } 40997 return (BCM_E_UNAVAIL); 40998 default: 40999 LOG_ERROR(BSL_LS_BCM_FP, 41000 (BSL_META_U(unit, 41001 "FP(unit %d) Error: PacketRes *data=%#x undefined\n"), 41002 unit, *data)); 41003 return (BCM_E_PARAM); 41004 } 41005 if ( *mask != *data ) { 41006 *mask = 0x1F; 41007 } 41008 41009 return (BCM_E_NONE); 41010 } 41011 41012 41013 int 41014 _bcm_esw_field_qualify_aux_tag(int unit, 41015 bcm_field_entry_t entry, 41016 bcm_field_qualify_t qual, 41017 uint32 data, 41018 uint32 mask 41019 ) 41020 { 41021 _field_entry_t *f_ent; 41022 _field_group_t *fg; 41023 _bcm_field_qual_offset_t *q_offset; 41024 uint32 ref_data[_FP_QUAL_DATA_WORDS]; 41025 uint32 ref_mask[_FP_QUAL_DATA_WORDS]; 41026 int rv; 41027 41028 41029 FP_LOCK(unit); 41030 41031 /* Get field entry part that contains the qualifier. */ 41032 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 41033 if (BCM_FAILURE(rv)) { 41034 FP_UNLOCK(unit); 41035 return (rv); 41036 } 41037 41038 41039 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 41040 ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) || 41041 (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) || 41042 (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) || 41043 (_BCM_FIELD_STAGE_FLOWTRACKER ==f_ent->group->stage_id))) { 41044 rv = _field_qualify32(unit, entry, qual, data, mask); 41045 FP_UNLOCK(unit); 41046 return rv; 41047 } 41048 41049 /* Get qualifier offsets in the tcam. */ 41050 rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset); 41051 if (BCM_FAILURE(rv)) { 41052 FP_UNLOCK(unit); 41053 return (rv); 41054 } 41055 41056 /* Take the given 32-bit data and mask value, and prefix them with 41057 a 1 bit, which in the hardware is the "tag valid" bit. 41058 */ 41059 41060 /* The LLTAG overlaid the VNTAG lower 16bits, and the LLTAG VALID bit will 41061 disambiguate the field. So the VNTAG_VALID field should be set to 0 and 41062 LLTAG_VALID field should be set to 1. 41063 */ 41064 fg = f_ent->group; 41065 if ((_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) 41066 && (qual == bcmFieldQualifySubportPktTag)) { 41067 ref_data[1] = 2; 41068 ref_mask[1] = 2; 41069 ref_data[0] = (data & 0xffff); 41070 ref_mask[0] = (mask & 0xffff); 41071 } else if ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) 41072 && (qual == bcmFieldQualifySubportPktTag)) { 41073 ref_data[1] = 1; 41074 ref_mask[1] = 1; 41075 ref_data[0] = (data & 0xffff); 41076 ref_mask[0] = (mask & 0xffff); 41077 } else { 41078 ref_data[1] = 1; 41079 ref_mask[1] = 1; 41080 ref_data[0] = data; 41081 ref_mask[0] = mask; 41082 } 41083 41084 /* Program data/mask pair to tcam buffer. */ 41085 /* coverity[callee_ptr_arith : FALSE] */ 41086 rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, 41087 ref_data, ref_mask); 41088 FP_UNLOCK(unit); 41089 return (rv); 41090 } 41091 41092 /* 41093 * Function: 41094 * bcm_esw_field_stat_counter_get 41095 * Description: 41096 * Get counter statistic values for a field entity 41097 * 41098 * Parameters: 41099 * unit - (IN) unit number 41100 * Stat_id - (IN) Statistics entity ID. 41101 * stat - (IN) Type of the counter to retrieve 41102 * I.e. ingress/egress byte/packet) 41103 * num_entries - (IN) Number of counter Entries 41104 * counter_indexes - (IN) Pointer to Counter indexes entries 41105 * counter_values - (OUT) Pointer to counter values 41106 * 41107 * Return Value: 41108 * BCM_E_XXX 41109 * Notes: 41110 */ 41111 41112 int 41113 _bcm_esw_field_stat_counter_get(int unit, int sync_mode, uint32 stat_id, 41114 bcm_field_stat_t stat, uint32 num_entries, 41115 uint32 *counter_indexes, 41116 bcm_stat_value_t *counter_values) 41117 { 41118 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 41119 defined(BCM_HURRICANE3_SUPPORT) 41120 _field_stat_t *f_st=NULL; /* Field statistics entity. */ 41121 uint32 index_count=0; 41122 uint32 byte_flag=0; 41123 41124 if (!soc_feature(unit, soc_feature_advanced_flex_counter) && 41125 !soc_feature(unit, soc_feature_flowcnt)) { 41126 return BCM_E_UNAVAIL; 41127 } 41128 41129 if (stat == bcmFieldStatPackets || 41130 stat == bcmFieldStatGreenPackets || 41131 stat == bcmFieldStatYellowPackets || 41132 stat == bcmFieldStatRedPackets || 41133 stat == bcmFieldStatNotGreenPackets || 41134 stat == bcmFieldStatNotYellowPackets || 41135 stat == bcmFieldStatNotRedPackets) { 41136 byte_flag=0; 41137 } else { 41138 byte_flag=1; 41139 } 41140 41141 41142 BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, stat_id, &f_st)); 41143 if (f_st->flex_mode == 0) { 41144 LOG_VERBOSE(BSL_LS_BCM_FP, 41145 (BSL_META_U(unit, 41146 "Entry not attached \n"))); 41147 return BCM_E_PARAM; 41148 } 41149 for (index_count=0; index_count < num_entries ; index_count++) { 41150 #if defined(BCM_HURRICANE3_SUPPORT) 41151 if (soc_feature(unit, soc_feature_flowcnt)) { 41152 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_counter_raw_get( 41153 unit, sync_mode, f_st->flex_mode, byte_flag, 41154 counter_indexes[index_count], 41155 &counter_values[index_count])); 41156 } 41157 #endif /* BCM_HURRICANE3_SUPPORT */ 41158 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 41159 if (soc_feature(unit, soc_feature_advanced_flex_counter)) { 41160 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_raw_get( 41161 unit, sync_mode, f_st->flex_mode, byte_flag, 41162 counter_indexes[index_count], 41163 &counter_values[index_count])); 41164 } 41165 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT */ 41166 } 41167 return BCM_E_NONE; 41168 #else 41169 return BCM_E_UNAVAIL; 41170 #endif 41171 } 41172 /* 41173 * Function: 41174 * _bcm_esw_field_stat_get 41175 * 41176 * Description: 41177 * Get 64 bit counter value for specific statistic type. 41178 * if sync_mode is set, sync the sw accumulated count 41179 * with hw count value first, else return sw count. 41180 * Parameters: 41181 * unit - (IN) BCM device number. 41182 * sync_mode - (IN) hwcount is to be synced to sw count 41183 * stat_id - (IN) Statistics entity id. 41184 * stat - (IN) Collected statistics descriptor. 41185 * value - (OUT) Collected counters value. 41186 * Returns: 41187 * BCM_E_XXX 41188 */ 41189 int 41190 _bcm_esw_field_stat_get(int unit, int sync_mode, int stat_id, 41191 bcm_field_stat_t stat, uint64 *value) 41192 { 41193 _field_stat_t *f_st; /* Field statistics entity. */ 41194 int rv; /* Operation return status. */ 41195 41196 /* Input parameters check. */ 41197 if (NULL == value) { 41198 return (BCM_E_PARAM); 41199 } 41200 41201 COMPILER_64_ZERO(*value); 41202 41203 /* Get field control structure. */ 41204 41205 FP_LOCK(unit); 41206 41207 /* Get statistics entity descriptor. */ 41208 rv = _bcm_field_stat_get(unit, stat_id, &f_st); 41209 if (BCM_FAILURE(rv)) { 41210 FP_UNLOCK(unit); 41211 return (rv); 41212 } 41213 41214 if (_FP_INVALID_INDEX != f_st->hw_index) { 41215 rv = _field_stat_value_get(unit, sync_mode, f_st, stat, value); 41216 } 41217 41218 FP_UNLOCK(unit); 41219 return (rv); 41220 } 41221 41222 /* 41223 * Function: 41224 * _bcm_esw_field_stat_get32 41225 * 41226 * Description: 41227 * Get lower 32 bit counter value for specific statistic type. 41228 * if sync_mode is set, sync the sw accumulated count 41229 * with hw count value first, else return sw count. 41230 * Parameters: 41231 * unit - (IN) BCM device number. 41232 * sync_mode - (IN) hwcount is to be synced to sw count 41233 * stat_id - (IN) Statistics entity id. 41234 * stat - (IN) Collected statistics descriptor. 41235 * value - (OUT) Collected counters value. 41236 * Returns: 41237 * BCM_E_XXX 41238 */ 41239 int 41240 _bcm_esw_field_stat_get32(int unit, int sync_mode, int stat_id, 41241 bcm_field_stat_t stat, uint32 *value) 41242 { 41243 uint64 val64; /* 64 bit counter value. */ 41244 int rv; /* Operation return status. */ 41245 41246 /* Input parameters check. */ 41247 if (NULL == value) { 41248 return (BCM_E_PARAM); 41249 } 41250 41251 /* Read 64 bit counter value. */ 41252 rv = _bcm_esw_field_stat_get (unit, sync_mode, stat_id, stat, &val64); 41253 if (BCM_SUCCESS(rv)) { 41254 *value = COMPILER_64_LO(val64); 41255 } 41256 return rv; 41257 } 41258 41259 41260 /* 41261 * Function: 41262 * _bcm_field_meter_pair_mode_get 41263 * Purpose: 41264 * Set the config settings for a policer entry. 41265 * Parameters: 41266 * unit - (IN) Unit number. 41267 * f_pl - (IN) Policer config. 41268 * mode - (OUT) Meter pair mode. 41269 * Returns: 41270 * BCM_E_XXX 41271 * Notes: 41272 */ 41273 int 41274 _bcm_field_meter_pair_mode_get(int unit, _field_policer_t *f_pl, 41275 uint32 *mode) 41276 { 41277 /* Input parameters check. */ 41278 if ((NULL == f_pl) || (NULL == mode)) { 41279 return (BCM_E_PARAM); 41280 } 41281 41282 switch (f_pl->cfg.mode) { 41283 case bcmPolicerModeSrTcmTsn: 41284 if (f_pl->cfg.flags & BCM_POLICER_COLOR_BLIND) { 41285 *mode = BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND; 41286 } else { 41287 *mode = BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE; 41288 } 41289 break; 41290 case bcmPolicerModeSrTcmModified: 41291 case bcmPolicerModeSrTcm: 41292 if (f_pl->cfg.flags & BCM_POLICER_COLOR_BLIND) { 41293 *mode = BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND; 41294 } else { 41295 *mode = BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE; 41296 } 41297 break; 41298 case bcmPolicerModeCommitted: 41299 *mode = BCM_FIELD_METER_MODE_FLOW; 41300 break; 41301 case bcmPolicerModeTrTcm: 41302 if (f_pl->cfg.flags & BCM_POLICER_COLOR_BLIND) { 41303 *mode = BCM_FIELD_METER_MODE_trTCM_COLOR_BLIND; 41304 } else { 41305 *mode = BCM_FIELD_METER_MODE_trTCM_COLOR_AWARE; 41306 } 41307 break; 41308 case bcmPolicerModeTrTcmDs: 41309 case bcmPolicerModeCoupledTrTcmDs: 41310 if (f_pl->cfg.flags & BCM_POLICER_COLOR_BLIND) { 41311 *mode = 4; 41312 } else { 41313 *mode = 5; 41314 } 41315 break; 41316 case bcmPolicerModePassThrough: 41317 if (SOC_IS_FIREBOLT2(unit)) { 41318 *mode = 4; 41319 } else { 41320 *mode = BCM_FIELD_METER_MODE_DEFAULT; 41321 } 41322 break; 41323 case bcmPolicerModeGreen: 41324 *mode = BCM_FIELD_METER_MODE_DEFAULT; 41325 break; 41326 default: 41327 return (BCM_E_INTERNAL); 41328 } 41329 return (BCM_E_NONE); 41330 } 41331 41332 /* 41333 * Function: 41334 * _bcm_field_qualify_InPorts_get 41335 * Purpose: 41336 * Get match criteria for bcmFieildQualifyInPorts 41337 * qualifier from the field entry. 41338 * Parameters: 41339 * unit - (IN) Unit number. 41340 * entry - (IN) BCM field entry id. 41341 * qual - (IN) BCM field qualifier. 41342 * data - (OUT) Qualifier match data. 41343 * mask - (OUT) Qualifier match mask. 41344 * Returns: 41345 * BCM_E_XXX 41346 * Notes: 41347 */ 41348 int 41349 _bcm_field_qualify_InPorts_get(int unit, bcm_field_entry_t entry, 41350 bcm_field_qualify_t qual, 41351 bcm_pbmp_t *data, 41352 bcm_pbmp_t *mask) 41353 { 41354 _field_entry_t *f_ent; /* Field entry pointer. */ 41355 uint32 hw_data; /* HW encoded qualifier data. */ 41356 uint32 hw_mask; /* HW encoding qualifier mask. */ 41357 int rv; /* Operation return status. */ 41358 #if defined(BCM_TOMAHAWK_SUPPORT) 41359 _field_stage_t *stage_fc; /* Stage operational Structure. */ 41360 bcm_port_t port; /* Holds physical port number. */ 41361 uint8 instance; /* Field group pipe information. */ 41362 bcm_pbmp_t valid_pbm; /* Holds valid pbm supported */ 41363 #endif 41364 /* Input parameters check. */ 41365 if ((NULL == data) || (NULL == mask)) { 41366 return (BCM_E_PARAM); 41367 } 41368 41369 rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent); 41370 if (BCM_FAILURE(rv)) { 41371 return (rv); 41372 } 41373 41374 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT) 41375 if (soc_feature(unit, soc_feature_field_ingress_ipbm) || 41376 _BCM_FIELD_IS_SLICE_MODE_PBMP_SUPPORTED(f_ent->group->flags)) { 41377 41378 #if defined(BCM_TOMAHAWK_SUPPORT) 41379 /* For TH devices, reset the perpipe ports to the pbmp */ 41380 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 41381 (qual == bcmFieldQualifyInPorts)) { 41382 41383 /* Get the stage control structure. */ 41384 rv = _field_stage_control_get(unit, f_ent->group->stage_id, 41385 &stage_fc); 41386 BCM_IF_ERROR_RETURN(rv); 41387 41388 if (bcmFieldGroupOperModePipeLocal == stage_fc->oper_mode) { 41389 instance = f_ent->group->instance; 41390 BCM_PBMP_ASSIGN(valid_pbm, PBMP_PIPE(unit, 41391 f_ent->group->instance)); 41392 } else { 41393 instance = _BCM_FIELD_GLOBAL_GROUP; 41394 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &valid_pbm)); 41395 } 41396 BCM_PBMP_CLEAR(*data); 41397 BCM_PBMP_CLEAR(*mask); 41398 switch (instance) { 41399 case _BCM_FIELD_PIPE0_GROUP: 41400 case _BCM_FIELD_PIPE1_GROUP: 41401 case _BCM_FIELD_PIPE2_GROUP: 41402 case _BCM_FIELD_PIPE3_GROUP: 41403 case _BCM_FIELD_PIPE4_GROUP: 41404 case _BCM_FIELD_PIPE5_GROUP: 41405 case _BCM_FIELD_PIPE6_GROUP: 41406 case _BCM_FIELD_PIPE7_GROUP: 41407 if (soc_feature(unit, soc_feature_td3_style_fp)) { 41408 BCM_PBMP_ASSIGN(*data, f_ent->pbmp.data); 41409 BCM_PBMP_ASSIGN(*mask, f_ent->pbmp.mask); 41410 } else { 41411 BCM_PBMP_ITER(f_ent->pbmp.data, port) { 41412 BCM_PBMP_PORT_ADD(*data, port + 41413 (_FP_TCAM_IPBMP_SIZE(unit) * f_ent->group->instance)); 41414 } 41415 BCM_PBMP_ITER(f_ent->pbmp.mask, port) { 41416 BCM_PBMP_PORT_ADD(*mask, port + 41417 (_FP_TCAM_IPBMP_SIZE(unit) * f_ent->group->instance)); 41418 } 41419 } 41420 break; 41421 case _BCM_FIELD_GLOBAL_GROUP: 41422 BCM_PBMP_ASSIGN(*data, f_ent->pbmp.data); 41423 BCM_PBMP_ASSIGN(*mask, f_ent->pbmp.mask); 41424 break; 41425 default: 41426 return BCM_E_INTERNAL; 41427 } 41428 BCM_PBMP_AND(*data, valid_pbm); 41429 BCM_PBMP_AND(*mask, valid_pbm); 41430 } else { 41431 /* Add data & mask to entry. */ 41432 BCM_PBMP_ASSIGN(*data, f_ent->pbmp.data); 41433 BCM_PBMP_ASSIGN(*mask, f_ent->pbmp.mask); 41434 } 41435 #else 41436 /* Add data & mask to entry. */ 41437 BCM_PBMP_ASSIGN(*data, f_ent->pbmp.data); 41438 BCM_PBMP_ASSIGN(*mask, f_ent->pbmp.mask); 41439 #endif 41440 41441 if (qual == bcmFieldQualifyInPorts) { 41442 bcm_pbmp_t lb_pbm; /* Loopback port bitmap. */ 41443 41444 /* Remove loopback port from ipbm data and mask */ 41445 BCM_PBMP_CLEAR(lb_pbm); 41446 BCM_PBMP_OR(lb_pbm, PBMP_LB(unit)); 41447 if (BCM_PBMP_NOT_NULL(lb_pbm)) { 41448 BCM_PBMP_REMOVE(*data, PBMP_LB(unit)); 41449 BCM_PBMP_REMOVE(*mask, PBMP_LB(unit)); 41450 } 41451 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC) 41452 /* Remove MACSEC Port from IPBM mask */ 41453 if (soc_feature(unit, soc_feature_xflow_macsec)) { 41454 bcm_pbmp_t macsec_pbm; 41455 BCM_PBMP_CLEAR(macsec_pbm); 41456 BCM_PBMP_OR(macsec_pbm, PBMP_MACSEC_ALL(unit)); 41457 if (BCM_PBMP_NOT_NULL(macsec_pbm)) { 41458 BCM_PBMP_REMOVE(*mask, PBMP_MACSEC_ALL(unit)); 41459 } 41460 } 41461 #endif 41462 } 41463 41464 return (BCM_E_NONE); 41465 } 41466 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */ 41467 41468 /* Read qualifier match value and mask. */ 41469 rv = _bcm_field_entry_qualifier_uint32_get(unit, entry, qual, 41470 (uint32 *)&hw_data, 41471 (uint32 *)&hw_mask); 41472 BCM_IF_ERROR_RETURN(rv); 41473 41474 SOC_PBMP_WORD_SET(*data, 0, hw_data); 41475 SOC_PBMP_WORD_SET(*mask, 0, hw_mask); 41476 return (rv); 41477 } 41478 41479 /* 41480 * Function: 41481 * bcm_esw_field_qualify_PacketRes_get 41482 * Purpose: 41483 * Get match criteria for bcmFieildQualifyPacketRes 41484 * qualifier from the field entry. 41485 * Parameters: 41486 * unit - (IN) Unit number. 41487 * entry - (IN) BCM field entry id. 41488 * data - (OUT) Qualifier match data. 41489 * mask - (OUT) Qualifier match mask. 41490 * Returns: 41491 * BCM_E_XXX 41492 * Notes: 41493 */ 41494 int 41495 _field_qualify_PacketRes_get(int unit, 41496 bcm_field_entry_t entry, 41497 uint32 *data, 41498 uint32 *mask 41499 ) 41500 { 41501 /* Translate data #defines to hardware encodings */ 41502 switch (*data) { 41503 case 0x0: 41504 *data = BCM_FIELD_PKT_RES_UNKNOWN; 41505 break; 41506 case 0x1: 41507 *data = BCM_FIELD_PKT_RES_CONTROL; 41508 break; 41509 case 0x2: 41510 *data = BCM_FIELD_PKT_RES_BPDU; 41511 break; 41512 case 0x3: 41513 *data = BCM_FIELD_PKT_RES_L2BC; 41514 break; 41515 case 0x4: 41516 *data = BCM_FIELD_PKT_RES_L2UC; 41517 break; 41518 case 0x5: 41519 *data = BCM_FIELD_PKT_RES_L2UNKNOWN; 41520 break; 41521 case 0x6: 41522 *data = BCM_FIELD_PKT_RES_L3MCUNKNOWN; 41523 break; 41524 case 0x7: 41525 *data = BCM_FIELD_PKT_RES_L3MCKNOWN; 41526 break; 41527 case 0x8: 41528 *data = BCM_FIELD_PKT_RES_L2MCKNOWN; 41529 break; 41530 case 0x9: 41531 *data = BCM_FIELD_PKT_RES_L2MCUNKNOWN; 41532 break; 41533 case 0xa: 41534 *data = BCM_FIELD_PKT_RES_L3UCKNOWN; 41535 break; 41536 case 0xb: 41537 *data = BCM_FIELD_PKT_RES_L3UCUNKNOWN; 41538 break; 41539 case 0xc: 41540 *data = BCM_FIELD_PKT_RES_MPLSKNOWN; 41541 break; 41542 case 0xd: 41543 *data = BCM_FIELD_PKT_RES_MPLSL3KNOWN; 41544 break; 41545 case 0xe: 41546 *data = BCM_FIELD_PKT_RES_MPLSL2KNOWN; 41547 break; 41548 case 0xf: 41549 *data = BCM_FIELD_PKT_RES_MPLSUNKNOWN; 41550 break; 41551 case 0x10: 41552 *data = BCM_FIELD_PKT_RES_MIMKNOWN; 41553 break; 41554 case 0x11: 41555 *data = BCM_FIELD_PKT_RES_MIMUNKNOWN; 41556 break; 41557 41558 default: 41559 return (BCM_E_INTERNAL); 41560 } 41561 *mask = BCM_FIELD_EXACT_MATCH_MASK; 41562 41563 return (BCM_E_NONE); 41564 } 41565 41566 41567 /* 41568 * Function: 41569 * _bcm_field_entry_backup 41570 * Purpose: 41571 * Backup a field entry configuration. 41572 * Parameters: 41573 * unit - (IN) BCM device number 41574 * entry_id - (IN) Entry identifier 41575 * Returns: 41576 * BCM_E_XXX 41577 */ 41578 int 41579 _bcm_field_entry_backup(int unit, bcm_field_entry_t entry_id) 41580 { 41581 _field_entry_t *f_ent_orig; /* Field entry to be backed up. */ 41582 _field_entry_t *f_ent_copy = NULL; /* Backup copy of field entry. */ 41583 _field_action_t *fa_orig; /* Pointer to entry action list. */ 41584 _field_action_t *fa = NULL; /* Field action descriptor. */ 41585 _field_action_t *fa_free = NULL; /* Field action descriptor. */ 41586 _field_stat_t *f_st; /* Internal Statisics descriptor. */ 41587 _field_policer_t *f_pl; /* Internal policer descriptor. */ 41588 int free_tcam = FALSE; /* KEY/MASK memory alloc status. */ 41589 int parts_count = 0; /* Entry parts count. */ 41590 int i; /* Iterator variable. */ 41591 int rv; /* Operation return status. */ 41592 uint32 mem_sz; /* Field entry alloc size. */ 41593 41594 41595 FP_LOCK(unit); 41596 41597 rv = _bcm_field_entry_get_by_id(unit, 41598 entry_id, 41599 &f_ent_orig); 41600 if (BCM_FAILURE(rv)) { 41601 FP_UNLOCK(unit); 41602 return (rv); 41603 } 41604 41605 if (NULL != f_ent_orig->ent_copy) { 41606 rv = _bcm_field_entry_cleanup(unit, entry_id); 41607 if (BCM_FAILURE(rv)) { 41608 FP_UNLOCK(unit); 41609 return (rv); 41610 } 41611 } 41612 41613 /* Get number of entry parts . */ 41614 rv = _bcm_field_entry_tcam_parts_count(unit, 41615 f_ent_orig->group->stage_id, 41616 f_ent_orig->group->flags, 41617 &parts_count); 41618 if (BCM_FAILURE(rv)) { 41619 FP_UNLOCK(unit); 41620 return (rv); 41621 } 41622 41623 mem_sz = parts_count * sizeof(_field_entry_t); 41624 41625 _FP_XGS3_ALLOC(f_ent_copy, mem_sz, "field entry copy"); 41626 if (f_ent_copy == NULL) { 41627 LOG_ERROR(BSL_LS_BCM_FP, 41628 (BSL_META_U(unit, 41629 "FP(unit %d) Error: allocation failure for field_entry\n"), 41630 unit)); 41631 FP_UNLOCK(unit); 41632 return (BCM_E_MEMORY); 41633 } 41634 41635 41636 for (i = 0; i < parts_count; i++) { 41637 41638 f_ent_copy[i].eid = f_ent_orig[i].eid; 41639 f_ent_copy[i].prio = f_ent_orig[i].prio; 41640 f_ent_copy[i].slice_idx = f_ent_orig[i].slice_idx; 41641 f_ent_copy[i].fs = f_ent_orig[i].fs; 41642 f_ent_copy[i].group = f_ent_orig[i].group; 41643 f_ent_copy[i].flags = f_ent_orig[i].flags; 41644 41645 #if defined(BCM_TRIDENT2_SUPPORT) 41646 if (SOC_IS_TD2_TT2(unit) && 41647 (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 41648 f_ent_copy->efp_key_match_type = f_ent_orig->efp_key_match_type; 41649 } 41650 #endif 41651 41652 if (NULL == f_ent_orig[i].tcam.key) { 41653 free_tcam = TRUE; 41654 } 41655 41656 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent_orig + i); 41657 if (BCM_FAILURE(rv)) { 41658 goto cleanup; 41659 } 41660 41661 /* 41662 * Calling backup routine for the second time, means 41663 * TCAM buffer already allocated needs to be freed. 41664 */ 41665 rv = _bcm_field_qual_tcam_key_mask_free(unit, f_ent_copy + i); 41666 if (BCM_FAILURE(rv)) { 41667 goto cleanup; 41668 } 41669 41670 /* Copy qualification data. */ 41671 sal_memcpy(&f_ent_copy[i].tcam, &f_ent_orig[i].tcam, 41672 sizeof(_field_tcam_t)); 41673 sal_memcpy(&f_ent_copy[i].extra_tcam, &f_ent_orig[i].extra_tcam, 41674 sizeof(_field_tcam_t)); 41675 #if defined(BCM_TRIDENT2_SUPPORT) 41676 if (SOC_IS_TD2_TT2(unit) && 41677 (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 41678 sal_memcpy(&f_ent_copy[i].key_match_tcam, 41679 &f_ent_orig[i].key_match_tcam, 41680 sizeof(_field_tcam_t)); 41681 } 41682 #endif 41683 41684 f_ent_copy[i].tcam.key = NULL;/* Do not copy allocated part.*/ 41685 f_ent_copy[i].tcam.mask = NULL;/* Do not copy allocated part.*/ 41686 f_ent_copy[i].extra_tcam.key = NULL;/* Do not copy allocated part.*/ 41687 f_ent_copy[i].extra_tcam.mask = NULL;/* Do not copy allocated part.*/ 41688 if (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 41689 f_ent_copy[i].tcam.key_hw = NULL; 41690 f_ent_copy[i].tcam.mask_hw = NULL; 41691 } 41692 #if defined(BCM_TRIDENT2_SUPPORT) 41693 if (SOC_IS_TD2_TT2(unit) && 41694 (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 41695 f_ent_copy[i].key_match_tcam.key = NULL; /* Do not copy 41696 allocated part.*/ 41697 f_ent_copy[i].key_match_tcam.mask = NULL; /* Do not copy 41698 allocated part.*/ 41699 } 41700 #endif 41701 41702 /* Allocate tcam key and mask for destination entry. */ 41703 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent_copy + i); 41704 if (BCM_FAILURE(rv)) { 41705 goto cleanup; 41706 } 41707 41708 /* Copy key and mask information. */ 41709 sal_memcpy(f_ent_copy[i].tcam.key, f_ent_orig[i].tcam.key, 41710 f_ent_copy[i].tcam.key_size); 41711 sal_memcpy(f_ent_copy[i].tcam.mask, f_ent_orig[i].tcam.mask, 41712 f_ent_copy[i].tcam.key_size); 41713 41714 if (f_ent_orig[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 41715 sal_memcpy(f_ent_copy[i].extra_tcam.key, 41716 f_ent_orig[i].extra_tcam.key, 41717 f_ent_orig[i].extra_tcam.key_size); 41718 41719 sal_memcpy(f_ent_copy[i].extra_tcam.mask, 41720 f_ent_orig[i].extra_tcam.mask, 41721 f_ent_orig[i].extra_tcam.key_size); 41722 } 41723 41724 if (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 41725 sal_memcpy(f_ent_copy[i].tcam.key_hw, 41726 f_ent_orig[i].tcam.key_hw, 41727 f_ent_orig[i].tcam.key_size); 41728 sal_memcpy(f_ent_copy[i].tcam.mask_hw, 41729 f_ent_orig[i].tcam.mask_hw, 41730 f_ent_orig[i].tcam.key_size); 41731 } 41732 #if defined(BCM_TRIDENT2_SUPPORT) 41733 if (SOC_IS_TD2_TT2(unit) && 41734 (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 41735 /* Copy key and mask information. */ 41736 sal_memcpy(f_ent_copy[i].key_match_tcam.key, 41737 f_ent_orig[i].key_match_tcam.key, 41738 f_ent_copy[i].key_match_tcam.key_size); 41739 sal_memcpy(f_ent_copy[i].key_match_tcam.mask, 41740 f_ent_orig[i].key_match_tcam.mask, 41741 f_ent_copy[i].key_match_tcam.key_size); 41742 41743 } 41744 #endif 41745 if (free_tcam) { 41746 41747 if (NULL != f_ent_orig[i].tcam.key) { 41748 sal_free(f_ent_orig[i].tcam.key); 41749 sal_free(f_ent_orig[i].tcam.mask); 41750 } 41751 41752 if (f_ent_orig[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 41753 if (NULL != f_ent_orig[i].extra_tcam.key) { 41754 sal_free(f_ent_orig[i].extra_tcam.key); 41755 sal_free(f_ent_orig[i].extra_tcam.mask); 41756 } 41757 } 41758 41759 f_ent_orig[i].tcam.key = f_ent_orig[i].tcam.mask = 41760 f_ent_orig[i].extra_tcam.key = f_ent_orig[i].extra_tcam.mask = 41761 NULL; 41762 #if defined(BCM_TRIDENT2_SUPPORT) 41763 if (SOC_IS_TD2_TT2(unit) && 41764 (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 41765 if (NULL != f_ent_orig[i].key_match_tcam.key) { 41766 sal_free(f_ent_orig[i].key_match_tcam.key); 41767 sal_free(f_ent_orig[i].key_match_tcam.mask); 41768 } 41769 f_ent_orig[i].key_match_tcam.key = NULL; 41770 f_ent_orig[i].key_match_tcam.mask = NULL; 41771 } 41772 #endif 41773 free_tcam = FALSE; 41774 } 41775 } 41776 41777 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT) 41778 if (soc_feature(unit, soc_feature_field_ingress_ipbm) || 41779 _BCM_FIELD_IS_SLICE_MODE_PBMP_SUPPORTED(f_ent_orig->group->flags)) { 41780 BCM_PBMP_ASSIGN(f_ent_copy->pbmp.data, f_ent_orig->pbmp.data); 41781 BCM_PBMP_ASSIGN(f_ent_copy->pbmp.mask, f_ent_orig->pbmp.mask); 41782 } 41783 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */ 41784 41785 if (f_ent_orig->statistic.flags & _FP_ENTRY_STAT_VALID) { 41786 41787 /* Get statistics entity description structure. */ 41788 rv = _bcm_field_stat_get(unit, f_ent_orig->statistic.sid, &f_st); 41789 if (BCM_FAILURE(rv)) { 41790 goto cleanup; 41791 } 41792 41793 f_ent_copy->statistic.sid = f_ent_orig->statistic.sid; 41794 41795 /* Increment statistics entity reference counter. */ 41796 f_st->sw_ref_count++; 41797 41798 f_ent_copy->statistic.flags = f_ent_orig->statistic.flags; 41799 41800 } 41801 41802 /* Copy meter, if it exists. */ 41803 for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++) { 41804 41805 if (f_ent_orig->policer[i].flags & _FP_POLICER_VALID) { 41806 41807 /* Get policer description structure. */ 41808 rv = _bcm_field_policer_get(unit, 41809 f_ent_orig->policer[i].pid, 41810 &f_pl); 41811 if (BCM_FAILURE(rv)) { 41812 goto cleanup; 41813 } 41814 41815 f_ent_copy->policer[i].pid = f_ent_orig->policer[i].pid; 41816 41817 /* Increment policer reference counter. */ 41818 f_pl->sw_ref_count++; 41819 41820 f_ent_copy->policer[i].flags = f_ent_orig->policer[i].flags; 41821 } 41822 } 41823 41824 for (fa_orig = f_ent_orig->actions; 41825 fa_orig != NULL; 41826 fa_orig = fa_orig->next) { 41827 rv = _field_action_alloc(unit, 41828 fa_orig->action, 41829 fa_orig->param[0], 41830 fa_orig->param[1], 41831 fa_orig->param[2], 41832 fa_orig->param[3], 41833 fa_orig->param[4], 41834 fa_orig->param[5], 41835 &fa); 41836 if (BCM_FAILURE(rv)) { 41837 LOG_ERROR(BSL_LS_BCM_FP, 41838 (BSL_META_U(unit, 41839 "FP(unit %d) Error: failure in _field_action_alloc()\n"), 41840 unit)); 41841 goto cleanup; 41842 } 41843 41844 fa->next = f_ent_copy->actions; 41845 fa->flags |= fa_orig->flags; 41846 fa->hw_index = fa_orig->hw_index; 41847 fa->old_index = fa_orig->old_index; 41848 f_ent_copy->actions = fa; 41849 } 41850 41851 /*Remove the Installed and Enabled flags in the backup copy 41852 so that restore and install updates tcam*/ 41853 f_ent_copy->flags |= _FP_ENTRY_DIRTY; 41854 f_ent_copy->flags &= ~_FP_ENTRY_INSTALLED; 41855 f_ent_copy->flags &= ~_FP_ENTRY_ENABLED; 41856 41857 f_ent_orig->ent_copy = f_ent_copy; 41858 41859 FP_UNLOCK(unit); 41860 return (BCM_E_NONE); 41861 41862 cleanup: 41863 41864 fa = f_ent_copy->actions; 41865 while (fa != NULL) { 41866 fa_free = fa; 41867 fa = fa->next; 41868 sal_free(fa_free); 41869 } 41870 41871 for (i = 0; i < parts_count; i++) { 41872 _bcm_field_qual_tcam_key_mask_free(unit, f_ent_copy + i); 41873 } 41874 41875 if (NULL != f_ent_copy) { 41876 sal_free(f_ent_copy); 41877 } 41878 41879 FP_UNLOCK(unit); 41880 return (rv); 41881 } 41882 41883 /* 41884 * Function: 41885 * _bcm_field_entry_restore 41886 * Purpose: 41887 * Restore the configuration of a field entry from backup. Resources 41888 * allocated for the backup entry are released by calling the API 41889 * with BCM_FIELD_ENTRY_OPER_CLEANUP flag bit set. 41890 * Parameters: 41891 * unit - (IN) BCM device number 41892 * entry_id - (IN) Entry identifier 41893 * Returns: 41894 * BCM_E_XXX 41895 */ 41896 int 41897 _bcm_field_entry_restore(int unit, bcm_field_entry_t entry_id) 41898 { 41899 _field_entry_t *f_ent_orig; 41900 _field_entry_t *f_ent_copy; 41901 _field_action_t *fa_copy; 41902 _field_action_t *fa = NULL; /* Field action descriptor. */ 41903 _field_action_t *fa_iter = NULL; /* Field action descriptor. */ 41904 _field_stat_t *f_st; /* Internal statisics descriptor. */ 41905 _field_policer_t *f_pl; /* Internal policer descriptor. */ 41906 int parts_count = 0; 41907 int i; 41908 int rv; 41909 41910 41911 41912 FP_LOCK(unit); 41913 41914 rv = _bcm_field_entry_get_by_id(unit, 41915 entry_id, 41916 &f_ent_orig); 41917 if (BCM_FAILURE(rv)) { 41918 FP_UNLOCK(unit); 41919 LOG_ERROR(BSL_LS_BCM_FP, 41920 (BSL_META_U(unit, 41921 "FP(unit %d) Error: failure in " 41922 "bcm_esw_field_entry_policer_detach() - rv:%s\n"), 41923 unit, bcm_errmsg(rv))); 41924 return (rv); 41925 } 41926 41927 if (NULL == f_ent_orig->ent_copy) { 41928 FP_UNLOCK(unit); 41929 return (BCM_E_NOT_FOUND); 41930 } 41931 41932 /* Detach any attached policers. */ 41933 for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++) { 41934 if (f_ent_orig->policer[i].flags & _FP_POLICER_VALID) { 41935 rv = bcm_esw_field_entry_policer_detach(unit, 41936 f_ent_orig->eid, 41937 i); 41938 if (BCM_FAILURE(rv)) { 41939 FP_UNLOCK(unit); 41940 LOG_ERROR(BSL_LS_BCM_FP, 41941 (BSL_META_U(unit, 41942 "FP(unit %d) Error: failure in " 41943 "bcm_esw_field_entry_policer_detach() - rv:%s\n"), 41944 unit, bcm_errmsg(rv))); 41945 return (rv); 41946 } 41947 } 41948 } 41949 41950 /* Detach attached STATs. */ 41951 if (f_ent_orig->statistic.flags & _FP_ENTRY_STAT_VALID) { 41952 rv = bcm_esw_field_entry_stat_detach(unit, 41953 f_ent_orig->eid, 41954 f_ent_orig->statistic.sid); 41955 if (BCM_FAILURE(rv)) { 41956 FP_UNLOCK(unit); 41957 LOG_ERROR(BSL_LS_BCM_FP, 41958 (BSL_META_U(unit, 41959 "FP(unit %d) Error: failure in " 41960 "bcm_esw_field_stat_detach() - rv:%s\n"), 41961 unit, bcm_errmsg(rv))); 41962 return (rv); 41963 } 41964 } 41965 41966 /* Remove all actions set for this entry. */ 41967 rv = bcm_esw_field_action_remove_all(unit, f_ent_orig->eid); 41968 if (BCM_FAILURE(rv)) { 41969 FP_UNLOCK(unit); 41970 LOG_ERROR(BSL_LS_BCM_FP, 41971 (BSL_META_U(unit, 41972 "FP(unit %d) Error: failure in " 41973 "bcm_esw_field_action_remove_all() - rv:%s\n"), 41974 unit, bcm_errmsg(rv))); 41975 return (rv); 41976 } 41977 41978 /* Clear qualifiers set for this entry. */ 41979 rv = bcm_esw_field_qualify_clear(unit, f_ent_orig->eid); 41980 if (BCM_FAILURE(rv)) { 41981 FP_UNLOCK(unit); 41982 LOG_ERROR(BSL_LS_BCM_FP, 41983 (BSL_META_U(unit, 41984 "FP(unit %d) Error: failure in " 41985 "bcm_esw_field_qualify_clear() - rv:%s\n"), 41986 unit, bcm_errmsg(rv))); 41987 return (rv); 41988 } 41989 41990 /* Get the backup entry pointer. */ 41991 f_ent_copy = f_ent_orig->ent_copy; 41992 41993 /* Get number of entry parts . */ 41994 rv = _bcm_field_entry_tcam_parts_count(unit, 41995 f_ent_orig->group->stage_id, 41996 f_ent_orig->group->flags, 41997 &parts_count); 41998 if (BCM_FAILURE(rv)) { 41999 FP_UNLOCK(unit); 42000 return (rv); 42001 } 42002 42003 for (i = 0; i < parts_count; i++) { 42004 f_ent_orig[i].eid = f_ent_copy[i].eid; 42005 f_ent_orig[i].group = f_ent_copy[i].group; 42006 f_ent_orig[i].flags = f_ent_copy[i].flags; 42007 42008 #if defined(BCM_TRIDENT2_SUPPORT) 42009 if (SOC_IS_TD2_TT2(unit) && 42010 (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 42011 f_ent_orig->efp_key_match_type = f_ent_copy->efp_key_match_type; 42012 } 42013 #endif 42014 42015 /* Free allocated portion of sw tcam image. */ 42016 _bcm_field_qual_tcam_key_mask_free(unit, &f_ent_orig[i]); 42017 if (BCM_FAILURE(rv)) { 42018 FP_UNLOCK(unit); 42019 return (rv); 42020 } 42021 42022 /* Copy qualification data. */ 42023 sal_memcpy(&f_ent_orig[i].tcam, &f_ent_copy[i].tcam, 42024 sizeof(_field_tcam_t)); 42025 sal_memcpy(&f_ent_orig[i].extra_tcam, &f_ent_copy[i].extra_tcam, 42026 sizeof(_field_tcam_t)); 42027 42028 #if defined(BCM_TRIDENT2_SUPPORT) 42029 if (SOC_IS_TD2_TT2(unit) && 42030 (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 42031 sal_memcpy(&f_ent_orig[i].key_match_tcam, 42032 &f_ent_copy[i].key_match_tcam, 42033 sizeof(_field_tcam_t)); 42034 } 42035 #endif 42036 f_ent_orig[i].tcam.key = NULL; /* Do not copy allocated part.*/ 42037 f_ent_orig[i].tcam.mask = NULL; /* Do not copy allocated part.*/ 42038 f_ent_orig[i].extra_tcam.key = NULL; /* Do not copy allocated part.*/ 42039 f_ent_orig[i].extra_tcam.mask = NULL; /* Do not copy allocated part.*/ 42040 42041 if (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 42042 f_ent_orig[i].tcam.key_hw = NULL; 42043 f_ent_orig[i].tcam.mask_hw = NULL; 42044 } 42045 #if defined(BCM_TRIDENT2_SUPPORT) 42046 if (SOC_IS_TD2_TT2(unit) && 42047 (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 42048 f_ent_orig[i].key_match_tcam.key = NULL; /* Do not copy 42049 allocated part.*/ 42050 f_ent_orig[i].key_match_tcam.mask = NULL; /* Do not copy 42051 allocated part.*/ 42052 } 42053 #endif 42054 if (f_ent_copy[i].flags & _FP_ENTRY_DIRTY) { 42055 42056 /* Allocate tcam key and mask for entry. */ 42057 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent_orig + i); 42058 if (BCM_FAILURE(rv)) { 42059 FP_UNLOCK(unit); 42060 return (rv); 42061 } 42062 42063 /* Copy key and mask information. */ 42064 sal_memcpy(f_ent_orig[i].tcam.key, f_ent_copy[i].tcam.key, 42065 f_ent_copy[i].tcam.key_size); 42066 sal_memcpy(f_ent_orig[i].tcam.mask, f_ent_copy[i].tcam.mask, 42067 f_ent_copy[i].tcam.key_size); 42068 if (f_ent_orig[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) { 42069 sal_memcpy(f_ent_orig[i].extra_tcam.key, 42070 f_ent_copy[i].extra_tcam.key, 42071 f_ent_copy[i].extra_tcam.key_size); 42072 sal_memcpy(f_ent_orig[i].extra_tcam.mask, 42073 f_ent_copy[i].extra_tcam.mask, 42074 f_ent_copy[i].extra_tcam.key_size); 42075 } 42076 42077 if (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 42078 sal_memcpy(f_ent_orig[i].tcam.key_hw, 42079 f_ent_copy[i].tcam.key_hw, 42080 f_ent_copy[i].tcam.key_size); 42081 sal_memcpy(f_ent_orig[i].tcam.mask_hw, 42082 f_ent_copy[i].tcam.mask_hw, 42083 f_ent_copy[i].tcam.key_size); 42084 } 42085 42086 #if defined(BCM_TRIDENT2_SUPPORT) 42087 if (SOC_IS_TD2_TT2(unit) && 42088 (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) { 42089 /* Copy key and mask information. */ 42090 sal_memcpy(f_ent_orig[i].key_match_tcam.key, 42091 f_ent_copy[i].key_match_tcam.key, 42092 f_ent_orig[i].key_match_tcam.key_size); 42093 sal_memcpy(f_ent_orig[i].key_match_tcam.mask, 42094 f_ent_copy[i].key_match_tcam.mask, 42095 f_ent_orig[i].key_match_tcam.key_size); 42096 42097 } 42098 #endif 42099 } 42100 } 42101 42102 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT) 42103 if (soc_feature(unit, soc_feature_field_ingress_ipbm) || 42104 _BCM_FIELD_IS_SLICE_MODE_PBMP_SUPPORTED(f_ent_copy->group->flags)) { 42105 BCM_PBMP_ASSIGN(f_ent_orig->pbmp.data, f_ent_copy->pbmp.data); 42106 BCM_PBMP_ASSIGN(f_ent_orig->pbmp.mask, f_ent_copy->pbmp.mask); 42107 } 42108 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */ 42109 42110 if (f_ent_copy->statistic.flags & _FP_ENTRY_STAT_VALID) { 42111 42112 /* Get statistics entity description structure. */ 42113 rv = _bcm_field_stat_get(unit, f_ent_copy->statistic.sid, &f_st); 42114 if (BCM_FAILURE(rv)) { 42115 FP_UNLOCK(unit); 42116 return (rv); 42117 } 42118 42119 /* Decrement statistics entity reference counter. */ 42120 f_st->sw_ref_count--; 42121 42122 rv = bcm_esw_field_entry_stat_attach(unit, f_ent_orig->eid, 42123 f_ent_copy->statistic.sid); 42124 if (BCM_FAILURE(rv)) { 42125 FP_UNLOCK(unit); 42126 return (rv); 42127 } 42128 42129 f_ent_copy->statistic.flags 42130 = (f_ent_orig->statistic.flags 42131 & (_FP_ENTRY_STAT_VALID | _FP_ENTRY_STAT_EMPTY 42132 | _FP_ENTRY_STAT_USE_EVEN | _FP_ENTRY_STAT_USE_ODD)); 42133 42134 } 42135 42136 /* Copy meter, if it exists. */ 42137 for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++) { 42138 42139 if (f_ent_copy->policer[i].flags & _FP_POLICER_VALID) { 42140 42141 /* Get policer description structure. */ 42142 rv = _bcm_field_policer_get(unit, 42143 f_ent_copy->policer[i].pid, 42144 &f_pl); 42145 if (BCM_FAILURE(rv)) { 42146 FP_UNLOCK(unit); 42147 return (rv); 42148 } 42149 42150 /* Decrement policer entity reference counter. */ 42151 f_pl->sw_ref_count--; 42152 42153 rv = bcm_esw_field_entry_policer_attach(unit, 42154 f_ent_orig->eid, 42155 i, 42156 f_ent_copy->policer[i].pid); 42157 if (BCM_FAILURE(rv)) { 42158 FP_UNLOCK(unit); 42159 return (rv); 42160 } 42161 } 42162 } 42163 42164 for (fa_copy = f_ent_copy->actions; 42165 fa_copy != NULL; 42166 fa_copy = fa_copy->next) { 42167 rv = _field_action_alloc(unit, 42168 fa_copy->action, 42169 fa_copy->param[0], 42170 fa_copy->param[1], 42171 fa_copy->param[2], 42172 fa_copy->param[3], 42173 fa_copy->param[4], 42174 fa_copy->param[5], 42175 &fa); 42176 if (BCM_FAILURE(rv)) { 42177 LOG_ERROR(BSL_LS_BCM_FP, 42178 (BSL_META_U(unit, 42179 "FP(unit %d) Error: failure in _field_action_alloc()\n"), 42180 unit)); 42181 FP_UNLOCK(unit); 42182 return (rv); 42183 } 42184 42185 fa->next = f_ent_orig->actions; 42186 fa->flags |= fa_copy->flags; 42187 f_ent_orig->actions = fa; 42188 } 42189 42190 /* Free resources allocated for entry dirty actions. */ 42191 rv = _field_invalid_actions_remove(unit, f_ent_orig); 42192 if (BCM_FAILURE(rv)) { 42193 FP_UNLOCK(unit); 42194 LOG_ERROR(BSL_LS_BCM_FP, 42195 (BSL_META_U(unit, 42196 "FP(unit %d) Error: failure in " 42197 "_field_invalid_actions_remove() - rv:%s\n"), 42198 unit, bcm_errmsg(rv))); 42199 return (rv); 42200 } 42201 42202 /* Update hardware index for profiled actions. */ 42203 for (fa = f_ent_copy->actions; 42204 fa != NULL; 42205 fa = fa->next) { 42206 42207 if (_FP_INVALID_INDEX != fa->hw_index) { 42208 fa_iter = f_ent_orig->actions; 42209 while (fa_iter != NULL) { 42210 if ((1 == (fa_iter->flags & _FP_ACTION_VALID)) 42211 && (fa_iter->action == fa->action) 42212 && (_FP_INVALID_INDEX == fa_iter->hw_index)) { 42213 fa_iter->hw_index = fa->hw_index; 42214 fa_iter->old_index = fa->old_index; 42215 break; 42216 } 42217 fa_iter = fa_iter->next; 42218 } 42219 } 42220 } 42221 42222 /* Restore the entry priority. */ 42223 if (!(f_ent_copy->flags & _FP_ENTRY_CREATED_WITHOUT_PRIO)) { 42224 rv = _field_entry_prio_set(unit, entry_id, f_ent_copy[0].prio); 42225 } 42226 42227 FP_UNLOCK(unit); 42228 return (rv); 42229 42230 } 42231 42232 /* 42233 * Function: 42234 * _bcm_field_entry_cleanup 42235 * Purpose: 42236 * Release the resources allocated for the back entry. 42237 * Parameters: 42238 * unit - (IN) BCM device number 42239 * entry_id - (IN) Entry identifier 42240 * Returns: 42241 * BCM_E_XXX 42242 */ 42243 int 42244 _bcm_field_entry_cleanup(int unit, bcm_field_entry_t entry_id) 42245 { 42246 _field_entry_t *f_ent_orig; 42247 _field_entry_t *f_ent_copy; 42248 _field_action_t *fa = NULL; /* Field action descriptor. */ 42249 _field_action_t *fa_free = NULL; /* Field action descriptor. */ 42250 _field_stat_t *f_st; /* Internal Statisics descriptor. */ 42251 _field_policer_t *f_pl; /* Internal policer descriptor. */ 42252 int rv; 42253 int parts_count = 0; 42254 int i; 42255 42256 42257 FP_LOCK(unit); 42258 42259 rv = _bcm_field_entry_get_by_id(unit, 42260 entry_id, 42261 &f_ent_orig); 42262 if (BCM_FAILURE(rv)) { 42263 FP_UNLOCK(unit); 42264 return (rv); 42265 } 42266 42267 if (NULL == f_ent_orig->ent_copy) { 42268 FP_UNLOCK(unit); 42269 /* No resources to free. */ 42270 return (BCM_E_NONE); 42271 } 42272 42273 /* Get number of entry parts . */ 42274 rv = _bcm_field_entry_tcam_parts_count(unit, 42275 f_ent_orig->group->stage_id, 42276 f_ent_orig->group->flags, 42277 &parts_count); 42278 if (BCM_FAILURE(rv)) { 42279 FP_UNLOCK(unit); 42280 return (rv); 42281 } 42282 42283 f_ent_copy = f_ent_orig->ent_copy; 42284 42285 for (i = 0; i < parts_count; i++) { 42286 _bcm_field_qual_tcam_key_mask_free(unit, f_ent_copy + i); 42287 } 42288 42289 if (f_ent_copy->statistic.flags & _FP_ENTRY_STAT_VALID) { 42290 42291 /* Get statistics entity description structure. */ 42292 rv = _bcm_field_stat_get(unit, f_ent_copy->statistic.sid, &f_st); 42293 if (BCM_FAILURE(rv)) { 42294 goto cleanup; 42295 } 42296 /* Decrement statistics entity reference counter. */ 42297 f_st->sw_ref_count--; 42298 } 42299 42300 for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++) { 42301 if (f_ent_copy->policer[i].flags & _FP_POLICER_VALID) { 42302 42303 /* Get policer description structure. */ 42304 rv = _bcm_field_policer_get(unit, 42305 f_ent_copy->policer[i].pid, 42306 &f_pl); 42307 if (BCM_FAILURE(rv)) { 42308 goto cleanup; 42309 } 42310 /* Decrement policer reference counter. */ 42311 f_pl->sw_ref_count--; 42312 } 42313 } 42314 42315 cleanup: 42316 fa = f_ent_copy->actions; 42317 while (fa != NULL) { 42318 fa_free = fa; 42319 fa = fa->next; 42320 sal_free(fa_free); 42321 } 42322 42323 if (NULL != f_ent_copy) { 42324 sal_free(f_ent_orig->ent_copy); 42325 f_ent_orig->ent_copy = NULL; 42326 } 42327 42328 FP_UNLOCK(unit); 42329 return (BCM_E_NONE); 42330 } 42331 42332 #if defined (BCM_TRIUMPH2_SUPPORT) 42333 /* 42334 * Function: 42335 * _bcm_esw_field_udf_chunks_to_int_qset 42336 * Purpose: 42337 * Sets internal data qualifiers corrspeonding to the 42338 * offset chunks used by the UDF. 42339 * Parameters: 42340 * unit - (IN) Unit number. 42341 * udf_chunks_bmap - (IN) UDF offsets chunks map 42342 * qset - (OUT) Qualifier set 42343 * Returns: 42344 * BCM_E_NONE 42345 * Notes: 42346 */ 42347 int 42348 _bcm_esw_field_udf_chunks_to_int_qset(int unit, uint32 udf_chunks_bmap, 42349 bcm_field_qset_t *qset) 42350 { 42351 int gran = 0, max_chunks = 0; 42352 int idx; /* HW bitmap iteration index. */ 42353 int offset0_1 = 0; /* HW offset 0 and 1 usage status. */ 42354 int offset2_3 = 0; /* HW offset 2 and 3 usage status. */ 42355 int offset4_5 = 0; /* HW offset 4 and 5 usage status. */ 42356 int offset6_7 = 0; /* HW offset 6 and 7 usage status. */ 42357 42358 /* Retreive granularity and max chunks in unit */ 42359 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 42360 max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 42361 42362 42363 #if defined(BCM_TOMAHAWK_SUPPORT) 42364 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 42365 42366 #if defined(BCM_TOMAHAWK3_SUPPORT) 42367 if (soc_feature(unit, soc_feature_udf_selector_support)) { 42368 return ( 42369 _bcm_field_th3_udf_chunks_to_int_qset( 42370 unit, udf_chunks_bmap, qset)); 42371 } else 42372 #endif 42373 { 42374 return ( 42375 _bcm_field_th_udf_chunks_to_int_qset( 42376 unit, udf_chunks_bmap, qset)); 42377 } 42378 } 42379 #endif /* BCM_TOMAHAWK_SUPPORT */ 42380 42381 /* First Check Data0 and Data1 Qualify */ 42382 for (idx = 0; idx <= max_chunks; idx++) { 42383 if(udf_chunks_bmap & (1 << idx)) { 42384 if (idx >= 0 && idx < (max_chunks/2)) { 42385 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData0); 42386 } else if (idx >= (max_chunks/2) && idx < max_chunks) { 42387 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData1); 42388 } 42389 } 42390 } 42391 42392 /* Based on Granularity set Data2 and Data3 Qualify */ 42393 if(gran == UDF_OFFSET_GRAN2) { 42394 42395 if (BCM_FIELD_QSET_TEST_INTERNAL(*qset, _bcmFieldQualifyData0)) { 42396 42397 /* See if not having to use all UDF1 */ 42398 BCM_FIELD_QSET_REMOVE_INTERNAL(*qset, _bcmFieldQualifyData0); 42399 BCM_FIELD_QSET_REMOVE_INTERNAL(*qset, _bcmFieldQualifyData2); 42400 BCM_FIELD_QSET_REMOVE_INTERNAL(*qset, _bcmFieldQualifyData3); 42401 42402 /* Get HW offsets usage status. */ 42403 /* coverity[callee_ptr_arith : FALSE] */ 42404 SHR_BITTEST_RANGE(&udf_chunks_bmap, 0, 2, offset0_1); 42405 /* coverity[callee_ptr_arith : FALSE] */ 42406 SHR_BITTEST_RANGE(&udf_chunks_bmap, 2, 2, offset2_3); 42407 /* coverity[callee_ptr_arith : FALSE] */ 42408 SHR_BITTEST_RANGE(&udf_chunks_bmap, 4, 2, offset4_5); 42409 /* coverity[callee_ptr_arith : FALSE] */ 42410 SHR_BITTEST_RANGE(&udf_chunks_bmap, 6, 2, offset6_7); 42411 42412 42413 /* Add new internal qualifiers based on HW offsets usage status. */ 42414 if ((!offset0_1 && !offset4_5) && (offset2_3 || offset6_7)) { 42415 if (offset2_3 && offset6_7) { 42416 /* Add both UDF1_31_0 and UDF1_95_64 */ 42417 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData2); 42418 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData3); 42419 } else if (offset6_7 && !offset2_3) { 42420 /* Add UDF1_31_0 */ 42421 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData2); 42422 } else { 42423 /* Add UDF1_95_64 */ 42424 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData3); 42425 } 42426 } else { 42427 /* Add UDF1_127_0 */ 42428 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData0); 42429 } 42430 } 42431 42432 } 42433 42434 return BCM_E_NONE; 42435 } 42436 42437 42438 42439 /* 42440 * Function: 42441 * bcmi_xgs4_field_qset_udf_id_multi_set 42442 * Purpose: 42443 * Sets the list of udf id objects in the qset 42444 * Parameters: 42445 * unit - (IN) Unit number. 42446 * num_objects - (IN) Number of objects. 42447 * object_list - (IN) List of objects (Ex; UDF ids). 42448 * qset - (OUT) Qualifier set. 42449 * Returns: 42450 * BCM_E_XXX 42451 * Notes: 42452 */ 42453 int 42454 bcmi_xgs4_field_qset_udf_id_multi_set( 42455 int unit, 42456 int num_objects, 42457 int objects_list[], 42458 bcm_field_qset_t *qset 42459 ) 42460 { 42461 42462 int i; 42463 int rv; 42464 uint32 udf_chunks = 0; 42465 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 42466 #ifdef BCM_TOMAHAWK_SUPPORT 42467 int j; 42468 #endif 42469 42470 UDF_LOCK(unit); 42471 42472 for (i = 0; i < num_objects; i++) { 42473 /* Fetch udf info for hw_bmap */ 42474 rv = bcmi_xgs4_udf_offset_node_get(unit, objects_list[i], &offset_info); 42475 if (BCM_FAILURE(rv)) { 42476 UDF_UNLOCK(unit); 42477 return rv; 42478 } 42479 42480 udf_chunks |= offset_info->hw_bmap; 42481 } 42482 42483 /* Update udf_chuks bmap with qset */ 42484 for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) { 42485 /* coverity[ptr_arith] */ 42486 if (SHR_BITGET(qset->udf_map, i)) { 42487 SHR_BITSET(&udf_chunks, i); 42488 } 42489 } 42490 /* Update qset with internal data qualifiers based on udf_chunks */ 42491 rv = _bcm_esw_field_udf_chunks_to_int_qset(unit, udf_chunks, qset); 42492 if (BCM_FAILURE(rv)) { 42493 UDF_UNLOCK(unit); 42494 return rv; 42495 } 42496 42497 /* setting udf_map helps in gets/deletes */ 42498 for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) { 42499 /* coverity[ptr_arith] */ 42500 if (SHR_BITGET(&udf_chunks, i)) { 42501 SHR_BITSET(qset->udf_map, i); 42502 } 42503 } 42504 42505 #ifdef BCM_TOMAHAWK_SUPPORT 42506 /* SDK builds key gen mask for exact match group during group create. 42507 * group control structure has information only about data qualifiers 42508 * (_bcmFieldQualifyData0 - _bcmFieldQualifyData9) and chunks allocated 42509 * in groups qset.But no information is available about which bytes of 42510 * the chunk is actually allocated. 42511 * But we need which bytes of chunk is allocated for the data qualifier to 42512 * properly build the EM key gen mask, in case of partially allocated chunks. 42513 * So updating the unused bits of udf_map in bcm_field_qset_t to hold the 42514 * bytes allocated in chunks allocated for the data qualifier.*/ 42515 for (j = 0; j < num_objects; j++) { 42516 rv = bcmi_xgs4_udf_offset_node_get(unit, objects_list[j], &offset_info); 42517 if (BCM_FAILURE(rv)) { 42518 UDF_UNLOCK(unit); 42519 return rv; 42520 } 42521 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 42522 for (i = 0; i < (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit) * 2); i++) { 42523 if (SHR_BITGET(&(offset_info->byte_bmap), i)) { 42524 SHR_BITSET(qset->udf_map, 42525 (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit) + i)); 42526 } 42527 } 42528 } 42529 } 42530 #endif 42531 42532 UDF_UNLOCK(unit); 42533 42534 return rv; 42535 } 42536 42537 /* 42538 * Function: 42539 * bcmi_xgs4_field_qset_udf_id_multi_delete 42540 * Purpose: 42541 * Deletes list of udf id objects from the qset 42542 * Parameters: 42543 * unit - (IN) Unit number. 42544 * num_objects - (IN) Number of objects. 42545 * object_list - (IN) List of objects (Ex; UDF ids). 42546 * qset - (OUT) Qualifier set. 42547 * Returns: 42548 * BCM_E_XXX 42549 * Notes: 42550 */ 42551 int 42552 bcmi_xgs4_field_qset_udf_id_multi_delete( 42553 int unit, 42554 int num_objects, 42555 int objects_list[], 42556 bcm_field_qset_t *qset 42557 ) 42558 { 42559 42560 int i; 42561 int rv; 42562 uint32 udf_chunks = 0; /* Offset chunks bitmap */ 42563 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; /* UDF offset info */ 42564 42565 42566 UDF_LOCK(unit); 42567 42568 for (i = 0; i < num_objects; i++) { 42569 /* Fetch udf info for hw_bmap */ 42570 rv = bcmi_xgs4_udf_offset_node_get(unit, objects_list[i], &offset_info); 42571 if (BCM_FAILURE(rv)) { 42572 UDF_UNLOCK(unit); 42573 return rv; 42574 } 42575 42576 udf_chunks |= offset_info->hw_bmap; 42577 } 42578 42579 /* Update qset with internal data qualifiers based on udf_chunks */ 42580 rv = _bcm_esw_field_udf_chunks_to_int_qset(unit, udf_chunks, qset); 42581 if (BCM_FAILURE(rv)) { 42582 UDF_UNLOCK(unit); 42583 return rv; 42584 } 42585 42586 /* setting udf_map helps in gets/deletes */ 42587 for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) { 42588 /* coverity[ptr_arith] */ 42589 if (SHR_BITGET(&udf_chunks, i)) { 42590 SHR_BITCLR(qset->udf_map, i); 42591 } 42592 } 42593 42594 UDF_UNLOCK(unit); 42595 42596 return rv; 42597 } 42598 42599 42600 /* 42601 * Function: 42602 * bcmi_xgs4_field_qset_udf_id_multi_get 42603 * Purpose: 42604 * Gets list of udf id objects in a qset 42605 * Parameters: 42606 * unit - (IN) Unit number. 42607 * qset - (IN) Qualifier set. 42608 * max - (IN) Max number of objects. 42609 * object_list - (OUT) List of objects (Ex; UDF ids). 42610 * actual - (OUT) Number of objects. 42611 * Returns: 42612 * BCM_E_XXX 42613 * Notes: 42614 */ 42615 int 42616 bcmi_xgs4_field_qset_udf_id_multi_get( 42617 int unit, 42618 bcm_field_qset_t qset, 42619 int max, 42620 int objects_list[], 42621 int *actual 42622 ) 42623 { 42624 int i; 42625 uint32 hw_bmap = 0; 42626 int max_chunks = 0; 42627 bcmi_xgs4_udf_offset_info_t *tmp; 42628 42629 UDF_LOCK(unit); 42630 42631 max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 42632 42633 /* Input parameters check. */ 42634 if (actual == NULL) { 42635 UDF_UNLOCK(unit); 42636 return BCM_E_PARAM; 42637 } 42638 42639 for (i = 0; i < max_chunks; i++) { 42640 /* coverity[ptr_arith] */ 42641 if (SHR_BITGET(qset.udf_map, i)) { 42642 SHR_BITSET(&hw_bmap, i); 42643 } 42644 } 42645 42646 i = 0; 42647 tmp = UDF_CTRL(unit)->offset_info_head; 42648 42649 while (tmp != NULL) { 42650 if ( hw_bmap & (tmp->hw_bmap)) { 42651 if (i >= max) { 42652 break; 42653 } 42654 objects_list[i++] = tmp->udf_id; 42655 } 42656 tmp = tmp->next; 42657 } 42658 42659 42660 *actual = i; 42661 42662 UDF_UNLOCK(unit); 42663 42664 return BCM_E_NONE; 42665 } 42666 42667 42668 /* 42669 * Function: 42670 * _bcm_esw_field_qual_udf_offsets_get 42671 * Purpose: 42672 * Gets list of udf id objects in a qset 42673 * Parameters: 42674 * unit - (IN) Unit number. 42675 * qid - (IN) Internal Data qualifier. 42676 * chunk_order - (IN) Offset chunks in the order of availability. 42677 * num_chunks - (OUT) Number of chunks. 42678 * Returns: 42679 * BCM_E_NONE 42680 * Notes: 42681 */ 42682 int 42683 _bcm_esw_field_qual_udf_offsets_get(int unit, int qid, _field_group_t *fg, 42684 int chunk_order[], int *num_chunks, 42685 int pipe_num) 42686 { 42687 int idx; 42688 int alloc_count = 0; 42689 uint32 hw_bmap; 42690 int max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 42691 int gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 42692 42693 #if defined (BCM_TOMAHAWK_SUPPORT) 42694 bcm_udf_oper_mode_t udf_oper_mode = bcmUdfOperModeGlobal; 42695 bcmi_xgs4_udf_oper_mode_get(unit, &udf_oper_mode); 42696 42697 if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) && 42698 (udf_oper_mode == bcmUdfOperModePipeLocal)) { 42699 hw_bmap = (UDF_CTRL(unit)->hw_bmap_per_pipe[pipe_num]); 42700 } else 42701 #endif 42702 { 42703 hw_bmap = (UDF_CTRL(unit)->hw_bmap); 42704 } 42705 42706 #if defined(BCM_TOMAHAWK_SUPPORT) 42707 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 42708 ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id))) { 42709 return ( 42710 _bcm_field_th_qual_udf_offsets_get( 42711 unit, qid, chunk_order, num_chunks, hw_bmap)); 42712 } 42713 #endif 42714 42715 for (idx = 0; idx < max_chunks; idx++) { 42716 /* coverity[ptr_arith] */ 42717 if (SHR_BITGET(&hw_bmap, idx)) { 42718 continue; 42719 } 42720 42721 /* Allocate as per granularity */ 42722 if (gran == UDF_OFFSET_GRAN2) { 42723 if (((qid == _bcmFieldQualifyData2) && ((idx == 6) || (idx == 7))) || 42724 ((qid == _bcmFieldQualifyData3) && ((idx == 2) || (idx == 3))) || 42725 ((qid == _bcmFieldQualifyData1) && ((idx >= 8))) || 42726 ((qid == _bcmFieldQualifyData0) && ((idx <= 7)))) { 42727 42728 chunk_order[alloc_count] = idx; 42729 alloc_count++; 42730 42731 if ((*num_chunks + alloc_count) >= max_chunks) { 42732 break; 42733 } 42734 } 42735 } else { 42736 if (((qid == _bcmFieldQualifyData2) && (idx == 3)) || 42737 ((qid == _bcmFieldQualifyData3) && (idx == 1)) || 42738 ((qid == _bcmFieldQualifyData1) && ((idx >= 4))) || 42739 ((qid == _bcmFieldQualifyData0) && ((idx <= 3)))) { 42740 42741 chunk_order[alloc_count] = idx; 42742 alloc_count++; 42743 42744 if ((*num_chunks + alloc_count) >= max_chunks) { 42745 break; 42746 } 42747 } 42748 } 42749 } 42750 42751 *num_chunks += alloc_count; 42752 42753 return BCM_E_NONE; 42754 } 42755 42756 42757 /* 42758 * Function: 42759 * _bcm_esw_field_qset_udf_offsets_alloc 42760 * Purpose: 42761 * Allocates offset chunks based on the INPUT qset. 42762 * Parameters: 42763 * unit - (IN) Unit number. 42764 * stage - (IN) Field Group Stage. 42765 * qset - (IN) Qualifier set. 42766 * req_offsets - (IN) Number of chunks to be allocated. 42767 * offset_array - (OUT) Offset chunks in the order of availability. 42768 * Returns: 42769 * BCM_E_XXX 42770 * Notes: 42771 */ 42772 int 42773 _bcm_esw_field_qset_udf_offsets_alloc(int unit, _field_stage_id_t stage, 42774 bcm_field_qset_t qset, int req_offsets, int offset_array[], int *max_chunks, 42775 int pipe_num) 42776 { 42777 int group_flags[5] = { 42778 /* SINGLE */ 42779 (_FP_GROUP_SPAN_SINGLE_SLICE), 42780 /* DOUBLE_INTRA */ 42781 (_FP_GROUP_SPAN_SINGLE_SLICE | _FP_GROUP_INTRASLICE_DOUBLEWIDE), 42782 /* DOUBLE */ 42783 (_FP_GROUP_SPAN_DOUBLE_SLICE), 42784 /* QUAD_INTRA */ 42785 (_FP_GROUP_SPAN_DOUBLE_SLICE | _FP_GROUP_INTRASLICE_DOUBLEWIDE), 42786 /* TRIPLE */ 42787 (_FP_GROUP_SPAN_TRIPLE_SLICE) 42788 }; 42789 42790 int qset_comb[9][4] = { 42791 /* Internal qualifier Data2 (UDF1_6,UDF1_7) for Gran2 42792 * (UDF1_3) for Gran4 42793 */ 42794 {1, _bcmFieldQualifyData2, -1, -1}, 42795 /* Internal qualifier Data3 (UDF1_2,UDF1_3) for Gran2 42796 * (UDF1_1) for Gran 4 42797 */ 42798 {1, _bcmFieldQualifyData3, -1, -1}, 42799 /* Internal qualifier Data2 & Data3 (UDF1_6,UDF1_7,UDF1_2,UDF1_3) 42800 * for Gran2 and (UDF1_3,UDF1_1) for Gran4 42801 */ 42802 {2, _bcmFieldQualifyData2, 42803 _bcmFieldQualifyData3, 42804 -1}, 42805 /* Internal qualifier Data1 (UDF2) */ 42806 {1, _bcmFieldQualifyData1, -1, -1}, 42807 /* Internal qualifier Data0 (UDF1) */ 42808 {1, _bcmFieldQualifyData0, -1, -1}, 42809 /* Internal qualifier Data1 & Data2 (UDF1_6, UDF1_7 & UDF2) for Gran2 42810 * (UDF1_3 & UDF2) for Gran4 42811 */ 42812 {2, _bcmFieldQualifyData1, 42813 _bcmFieldQualifyData2, 42814 -1}, 42815 /* Internal qualifier Data1 & Data3 (UDF1_2, UDF1_3 & UDF2) for Gran 2 42816 * (UDF1_1 & UDF2) for Gran4 42817 */ 42818 {2, _bcmFieldQualifyData1, 42819 _bcmFieldQualifyData3, 42820 -1}, 42821 /* Internal qualifier Data1, Data2 & Data3 (UDF1_6, UDF1_7, UDF1_2, UDF1_3 & UDF2) 42822 * for Gran2 and (UDF1_3, UDF1_1, & UDF2) for Gran4 42823 */ 42824 {3, _bcmFieldQualifyData1, 42825 _bcmFieldQualifyData2, 42826 _bcmFieldQualifyData3}, 42827 /* Internal qualifier Data0 & Data1 (UDF1 & UDF2) */ 42828 {2, _bcmFieldQualifyData0, 42829 _bcmFieldQualifyData1, 42830 -1} 42831 }; 42832 42833 int i, j; 42834 int qid; 42835 int qual_count; 42836 int rv = BCM_E_NONE; 42837 int num_chunks = 0; 42838 _field_group_t fg; 42839 bcm_field_qset_t qset_test; 42840 int idx; 42841 42842 #if defined (BCM_TOMAHAWK_SUPPORT) 42843 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 42844 ((_BCM_FIELD_STAGE_INGRESS == stage) || (_BCM_FIELD_STAGE_LOOKUP == stage))) { 42845 return (_bcm_field_th_qset_udf_offsets_alloc( 42846 unit, stage, qset, req_offsets, 42847 offset_array, max_chunks, pipe_num)); 42848 42849 } 42850 #endif 42851 42852 /* Initialize group creation tracking structure. */ 42853 sal_memset(&fg, 0, sizeof(fg)); 42854 42855 fg.stage_id = stage; 42856 for (i = 0; i < COUNTOF(group_flags); i++) { 42857 42858 /* TD_TT family support intra_double mode group only in VFP */ 42859 if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 42860 if (((i == 1) || (i == 4)) && (stage != _BCM_FIELD_STAGE_LOOKUP)) { 42861 continue; 42862 } 42863 } 42864 42865 fg.flags = group_flags[i]; 42866 42867 for (j = 0; j < COUNTOF(qset_comb); j++) { 42868 42869 num_chunks = 0; 42870 qual_count = qset_comb[j][0]; 42871 42872 sal_memcpy(&qset_test, &qset, sizeof(bcm_field_qset_t)); 42873 42874 for (qid = 0; qid < qual_count; qid++) { 42875 BCM_FIELD_QSET_ADD_INTERNAL(qset_test, qset_comb[j][1 + qid]); 42876 } 42877 42878 FP_LOCK(unit); 42879 rv = _field_selcode_assign(unit, qset_test, 1, &fg); 42880 FP_UNLOCK(unit); 42881 42882 if (BCM_SUCCESS(rv)) { 42883 42884 for (qid = 0; qid < qual_count; qid++) { 42885 rv = _bcm_esw_field_qual_udf_offsets_get(unit, 42886 qset_comb[j][1 + qid], &fg, 42887 offset_array+num_chunks, &num_chunks, 42888 pipe_num); 42889 if (BCM_FAILURE(rv)) { 42890 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 42891 BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(&fg, idx)); 42892 } 42893 return rv; 42894 } 42895 } 42896 42897 if (num_chunks >= req_offsets) { 42898 break; 42899 } 42900 } 42901 } 42902 42903 if (num_chunks >= req_offsets) { 42904 break; 42905 } 42906 } 42907 42908 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 42909 BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(&fg, idx)); 42910 } 42911 42912 /* The UDF offset allocation to suit in an fp group 42913 * that consists of the user specified qset is not possible */ 42914 if (num_chunks < req_offsets) { 42915 return BCM_E_RESOURCE; 42916 } 42917 42918 *max_chunks = num_chunks; 42919 42920 return BCM_E_NONE; 42921 } 42922 42923 42924 /* 42925 * Function: 42926 * _bcm_xgs4_field_qualify_udf_data_elem 42927 * Purpose: 42928 * Qualify the field entry with data/mask corresponding to an offset chunk. 42929 * Parameters: 42930 * unit - (IN) Unit number. 42931 * eid - (IN) Field Entry. 42932 * offset_info - (IN) UDF offset info. 42933 * data_idx - (IN) The offset chunk index. 42934 * data - (IN) Input data to qualify the entry. 42935 * mask - (IN) Input mask to qualify the entry. 42936 * Returns: 42937 * BCM_E_XXX 42938 * Notes: 42939 */ 42940 int 42941 _bcm_xgs4_field_qualify_udf_data_elem(int unit, bcm_field_entry_t eid, 42942 bcmi_xgs4_udf_offset_info_t *offset_info, 42943 int data_idx, uint32 data, uint32 mask) 42944 { 42945 int rv; 42946 int idx; 42947 int elem_idx = 0; 42948 int qid = 0; 42949 int gran, max_chunks; 42950 _field_entry_t *f_ent = NULL; 42951 _bcm_field_qual_offset_t *q_offset; 42952 _bcm_field_qual_offset_t q_offset_temp; 42953 #if defined (BCM_TOMAHAWK_SUPPORT) 42954 uint32 q_data = 0; /* Qualifier data */ 42955 uint32 q_mask = 0; /* Qualifier mask */ 42956 int bit32_chunk = 0; /* Chunk is 32bit or 16bit */ 42957 uint8 hints_present = 0; 42958 #endif 42959 42960 max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 42961 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 42962 42963 /* Get the appropriate element index to insert the data */ 42964 for (idx = max_chunks - 1; idx >= 0; idx--) { 42965 /* coverity[ptr_arith] */ 42966 if (SHR_BITGET(&(offset_info->hw_bmap), idx)) { 42967 if (elem_idx == data_idx) { 42968 break; 42969 } else { 42970 elem_idx++; 42971 } 42972 } 42973 } 42974 42975 /* Get entry info. */ 42976 BCM_IF_ERROR_RETURN 42977 (_field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, &f_ent)); 42978 42979 #if defined (BCM_TOMAHAWK_SUPPORT) 42980 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 42981 ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) || 42982 (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) || 42983 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) { 42984 BCM_IF_ERROR_RETURN( 42985 _bcm_field_th_qualify_udf_data_elem_get 42986 (unit, idx, max_chunks, &qid)); 42987 } else 42988 #endif 42989 { 42990 /* idx - chunk id; data_idx - ? */ 42991 if ((idx >= 0) && (idx < max_chunks/2)) { 42992 42993 /* 42994 * If _bcmFieldQualifyData0 is not set in the qset, 42995 * either _bcmFieldQualifyData2 or _bcmFieldQualifyData3 42996 * will be set in the qset. 42997 */ 42998 if (gran == UDF_OFFSET_GRAN2) { 42999 if (!BCM_FIELD_QSET_TEST_INTERNAL 43000 (f_ent->group->qset, _bcmFieldQualifyData0)) { 43001 if ((2 == idx || 3 == idx) 43002 && !(offset_info->hw_bmap & 0x33)) { 43003 /* UDF1_95_64 */ 43004 qid = _bcmFieldQualifyData3; 43005 } else if ((6 == idx || 7 == idx) 43006 && !(offset_info->hw_bmap & 0x33)) { 43007 /* UDF1_31_0 */ 43008 qid = _bcmFieldQualifyData2; 43009 } else { 43010 /* 43011 * udf_offset0_1 and udf_offset4_5 must be in 43012 * _bcmFieldQualifyData0 43013 */ 43014 return (BCM_E_INTERNAL); 43015 } 43016 } else { 43017 /* UDF1_127_0 */ 43018 qid = _bcmFieldQualifyData0; 43019 } 43020 } else { 43021 /* GRAN 4 */ 43022 qid = _bcmFieldQualifyData0; 43023 } 43024 } else if ((idx >= max_chunks/2) && 43025 idx < max_chunks) { 43026 qid = _bcmFieldQualifyData1; 43027 idx -= (max_chunks / 2); 43028 } else { 43029 return (BCM_E_INTERNAL); 43030 } 43031 43032 /* Get entry qualifier offset in tcam */ 43033 if(gran == UDF_OFFSET_GRAN2) { 43034 if (qid == _bcmFieldQualifyData3) { 43035 if (idx == 2) { 43036 idx = 1; 43037 } else { 43038 idx = 0; 43039 } 43040 } else { 43041 idx = (((max_chunks/2) - 1) - idx); 43042 } 43043 } else { 43044 /* GRAN4 Case */ 43045 idx = (((max_chunks/2) - 1) - idx); 43046 } 43047 } 43048 #if defined(BCM_TOMAHAWK_SUPPORT) 43049 /* If device supports per-pipe FP configuration, */ 43050 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 43051 ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) || 43052 (f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP) || 43053 (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) { 43054 43055 if (idx != 0x0 && idx != 0x1 && idx != 0x8 && idx != 0x9) 43056 { 43057 if (!(soc_feature(unit, soc_feature_udf_selector_support))) { 43058 bit32_chunk = 1; 43059 } 43060 } 43061 if(bit32_chunk) { 43062 /*Since a 32 bit chunk can be allocated even partially, 43063 do not overwrite existing data in 32bit chunk.*/ 43064 rv = _bcm_field_entry_qualifier_uint32_get(unit, f_ent->eid, qid, 43065 &q_data, &q_mask); 43066 43067 if ((rv != BCM_E_NOT_FOUND) && (BCM_FAILURE(rv))) { 43068 return rv; 43069 } 43070 43071 if (rv == BCM_E_NONE) { 43072 if((idx % 2) == 0) { 43073 /* Idx is even => Upper 16 bits need to be written.Hence,mask the lower 43074 *16 bits of the q_data fetched from tcam and add the data*/ 43075 q_data &= ((1 << 16) - 1); 43076 q_mask &= ((1 << 16) - 1); 43077 43078 data = data << 16 | q_data; 43079 mask = mask << 16 | q_mask; 43080 } else { 43081 /* Idx is odd => Lower 16 bits need to be written.Hence,mask the upper 43082 *16 bits of the q_data fetched from tcam and add the data*/ 43083 q_data &= ~((1 << 16) - 1); 43084 q_mask &= ~((1 << 16) - 1); 43085 43086 data |= q_data; 43087 mask |= q_mask; 43088 } 43089 } 43090 } 43091 43092 /* For exact Match, though 32bit/16bit chunk is partially allocated, 43093 * _bcm_field_th_entry_check_full_mask will expect full mask to during 43094 * validation. 43095 */ 43096 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 43097 43098 if (bit32_chunk) { 43099 if ((idx % 2) == 0) { 43100 mask |= 0xffff; 43101 } else { 43102 mask |= 0xffff0000; 43103 } 43104 } 43105 43106 if (!(offset_info->byte_bmap & (1 << (idx * 2)))) { 43107 mask |= 0xff; 43108 } 43109 43110 if (!(offset_info->byte_bmap & (1 << ((idx * 2) + 1)))) { 43111 mask |= 0xff00; 43112 } 43113 } 43114 43115 if (f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 43116 f_ent = NULL; 43117 rv = _bcm_field_entry_qual_get(unit, eid, qid, &f_ent); 43118 BCM_IF_ERROR_RETURN(rv); 43119 43120 /* Get entry qualifier offset in tcam. */ 43121 rv = _field_qual_offset_get(unit, f_ent, qid, &q_offset); 43122 BCM_IF_ERROR_RETURN(rv); 43123 /* COVERITY 43124 * 43125 * This flow takes care of the Out-of-bounds access issue 43126 * for data and mask. 43127 */ 43128 43129 /* coverity[callee_ptr_arith : FALSE] */ 43130 rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, &data, &mask); 43131 BCM_IF_ERROR_RETURN(rv); 43132 43133 f_ent->flags |= _FP_ENTRY_DIRTY; 43134 43135 return (BCM_E_NONE); 43136 } 43137 /* coverity[address_of : FALSE] */ 43138 /* coverity[callee_ptr_arith : FALSE] */ 43139 rv = (_bcm_field_th_qualify_set(unit, eid, qid, 43140 &data, &mask, 43141 _FP_QUALIFIER_ADD)); 43142 if (BCM_E_PARAM == rv) { 43143 rv = _field_udf_hints_present_get(unit, eid, offset_info->udf_id, &hints_present); 43144 if (BCM_FAILURE(rv)) { 43145 return BCM_E_INTERNAL; 43146 } 43147 if (hints_present && !BCM_FIELD_QSET_TEST_INTERNAL(f_ent->group->qset, qid)) { 43148 rv = BCM_E_NONE; 43149 } 43150 } 43151 43152 return (rv); 43153 } 43154 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 43155 (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) { 43156 return (_bcm_field_th_class_qualify_set(unit, eid, qid, 43157 &data, &mask)); 43158 } 43159 #endif /* BCM_TOMAHAWK_SUPPORT */ 43160 /* Get entry qualifier should be installed in. */ 43161 f_ent = NULL; 43162 rv = _bcm_field_entry_qual_get(unit, eid, qid, &f_ent); 43163 BCM_IF_ERROR_RETURN(rv); 43164 43165 /* Get entry qualifier offset in tcam. */ 43166 rv = _field_qual_offset_get(unit, f_ent, qid, &q_offset); 43167 BCM_IF_ERROR_RETURN(rv); 43168 43169 sal_memcpy(&q_offset_temp, q_offset, 43170 sizeof(_bcm_field_qual_offset_t)); 43171 43172 #ifdef BCM_MONTEREY_SUPPORT 43173 if (soc_feature(unit, soc_feature_monterey_b0_fp_sw_war) && 43174 (q_offset_temp.width[0] == 1)) { 43175 if (idx > 0) { 43176 q_offset_temp.offset[0] = q_offset_temp.offset[1] + (idx * gran * 8) - 1; 43177 q_offset_temp.width[0] = gran * 8; 43178 q_offset_temp.width[1] = 0; 43179 } else { 43180 q_offset_temp.width[1] = (gran * 8) - 1; 43181 } 43182 } else 43183 #endif 43184 { 43185 q_offset_temp.offset[0] += idx * gran * 8; 43186 q_offset_temp.width[0] = gran * 8; 43187 } 43188 43189 /* 43190 * COVERITY 43191 * 43192 * This flow takes care of the Out-of-bounds access issue 43193 * for data and mask. 43194 */ 43195 43196 /* coverity[callee_ptr_arith : FALSE] */ 43197 rv = _bcm_field_qual_value_set(unit, &q_offset_temp, f_ent, &data, &mask); 43198 BCM_IF_ERROR_RETURN(rv); 43199 43200 f_ent->flags |= _FP_ENTRY_DIRTY; 43201 43202 return (BCM_E_NONE); 43203 } 43204 43205 int 43206 _field_udf_hints_present_get(int unit, bcm_field_entry_t eid, 43207 bcm_udf_id_t udf_id, 43208 uint8 *hints_present) 43209 { 43210 int rv = BCM_E_INTERNAL; 43211 bcm_field_hintid_t hintid = 0; 43212 _field_hints_t *f_ht = NULL; /* Field hints Structure. */ 43213 _field_hint_t *hint_node = NULL; /* Field hint Structure. */ 43214 _field_entry_t *f_ent = NULL; 43215 43216 /* Parameters Check */ 43217 if (NULL == hints_present) { 43218 return BCM_E_PARAM; 43219 } 43220 43221 *hints_present = 0; 43222 rv = _field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, &f_ent); 43223 BCM_IF_ERROR_RETURN(rv); 43224 43225 hintid = f_ent->group->hintid; 43226 BCM_IF_ERROR_RETURN(_field_hints_control_get(unit, hintid, &f_ht)); 43227 43228 /* Not a valid hint Id. */ 43229 if (NULL == f_ht) { 43230 return BCM_E_NONE; 43231 } 43232 43233 /* No hinta are attached to the hintid. */ 43234 if (NULL == f_ht->hints) { 43235 return BCM_E_NONE; 43236 } 43237 43238 /* Go through all the hints in the hintid. */ 43239 hint_node = f_ht->hints; 43240 while (NULL != hint_node) { 43241 if ((bcmFieldHintTypeExtraction == hint_node->hint->hint_type) && 43242 (bcmFieldQualifyUdf == hint_node->hint->qual)) { 43243 if (udf_id == hint_node->hint->udf_id) { 43244 *hints_present = 1; 43245 break; 43246 } 43247 } 43248 hint_node = hint_node->next; 43249 } 43250 43251 return rv; 43252 } 43253 43254 /* 43255 * Function: 43256 * bcmi_xgs4_field_qualify_udf_data 43257 * Purpose: 43258 * Add UDF data that the packet must match to trigger qualifier. 43259 * Parameters: 43260 * unit - (IN) Unit number. 43261 * eid - (IN) Field Entry. 43262 * udf_id - (IN) UDF ID. 43263 * length - (IN) Number of bytes to match in field entry. 43264 * data - (IN) Input data to qualify the entry. 43265 * mask - (IN) Input mask to qualify the entry. 43266 * Returns: 43267 * BCM_E_xxx 43268 * Notes: 43269 */ 43270 int 43271 bcmi_xgs4_field_qualify_udf_data (int unit, bcm_field_entry_t eid, 43272 bcm_udf_id_t udf_id, int length, uint8 *data, uint8 *mask) 43273 { 43274 int idx = 0; /* HW bitmap iteration index. */ 43275 int data_idx = 0; /* Qualifier element index. */ 43276 int rv = BCM_E_NONE; /* Operation return status. */ 43277 int byte_offset; /* Byte offset in the word. */ 43278 int gran = 0; /* Granularity of the chunk. */ 43279 uint32 data_elem = 0; /* Hw info data word. */ 43280 uint32 mask_elem = 0; /* Hw info data mask. */ 43281 uint8 data_qual_done = 0; 43282 int size = 0; 43283 uint8 hints_present; 43284 uint8 pdata[32]; 43285 uint8 pmask[32]; 43286 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; /* UDF offset info */ 43287 43288 UDF_LOCK(unit); 43289 43290 /* Get UDF info. */ 43291 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info); 43292 if (BCM_FAILURE(rv)) { 43293 UDF_UNLOCK(unit); 43294 return rv; 43295 } 43296 43297 /* If provided entry data length is greater than UDF width */ 43298 if ((length > offset_info->width) || (length <= 0)) { 43299 UDF_UNLOCK(unit); 43300 return (BCM_E_PARAM); 43301 } 43302 43303 sal_memset(pdata, 0, 32 * sizeof(uint8)); 43304 sal_memset(pmask, 0, 32 * sizeof(uint8)); 43305 sal_memcpy(pdata, data, length); 43306 sal_memcpy(pmask, mask, length); 43307 43308 /* Max chunks */ 43309 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 43310 43311 /* data_idx - chunk iterator */ 43312 data_elem = 0; 43313 mask_elem = 0; 43314 data_idx = 0; 43315 byte_offset = gran - 1; 43316 43317 rv = _field_udf_hints_present_get(unit, eid, udf_id, &hints_present); 43318 if (BCM_FAILURE(rv)) { 43319 UDF_UNLOCK(unit); 43320 return rv; 43321 } 43322 43323 size = hints_present ? length : offset_info->width; 43324 /* 43325 * If the size is odd number, 43326 * make it even by adding 1 to it as the pdata and pmask are already filled 43327 * with 0s at that size + 1 position. 43328 */ 43329 size = (size == 1) ? (size + 1) : size; 43330 /* idx - input data bytes iterator */ 43331 for (idx = size - 1; idx >= 0; idx--) { 43332 data_elem |= (pdata[idx] << (8 * (gran - 1 - byte_offset))); 43333 mask_elem |= (pmask[idx] << (8 * (gran - 1 - byte_offset))); 43334 43335 data_qual_done = 0; 43336 43337 if ((byte_offset == 0)) { 43338 /* Install the element data & mask of "gran" bytes (even if zeros) */ 43339 rv = _bcm_xgs4_field_qualify_udf_data_elem(unit, eid, offset_info, 43340 data_idx, data_elem, mask_elem); 43341 if (BCM_FAILURE(rv)) { 43342 UDF_UNLOCK(unit); 43343 return rv; 43344 } 43345 43346 data_idx += 1; 43347 byte_offset = 0; 43348 data_elem = 0; 43349 mask_elem = 0; 43350 data_qual_done = 1; 43351 } 43352 43353 byte_offset -= 1; 43354 if ((byte_offset == -1)) { 43355 byte_offset = gran - 1; 43356 } 43357 } 43358 43359 /* Install last element data & mask, if data/mask still exists to be qualified */ 43360 if (data_qual_done != 1) { 43361 rv = _bcm_xgs4_field_qualify_udf_data_elem(unit, eid, offset_info, 43362 data_idx, data_elem, mask_elem); 43363 } 43364 43365 UDF_UNLOCK(unit); 43366 43367 return (rv); 43368 } 43369 43370 43371 /* 43372 * Function: 43373 * bcmi_xgs4_field_qualify_udf_get 43374 * Purpose: 43375 * Qualify the field entry with data/mask corresponding to an offset chunk. 43376 * Parameters: 43377 * unit - (IN) Unit number. 43378 * eid - (IN) Field Entry. 43379 * udf_id - (IN) UDF ID. 43380 * max_length - (IN) Length of bytes of data/mask to fetch. 43381 * data - (OUT) Data to qualify the entry. 43382 * mask - (OUT Mask to qualify the entry. 43383 * actual_length - (OUT) Length of bytes of data/mask fetched. 43384 * Returns: 43385 * BCM_E_XXX 43386 * Notes: 43387 */ 43388 int 43389 bcmi_xgs4_field_qualify_udf_get(int unit, bcm_field_entry_t eid, 43390 bcm_udf_id_t udf_id, int max_length, 43391 uint8 *data, uint8 *mask, int *actual_length) 43392 { 43393 _field_stage_t *stage_fc; /* Stage field control. */ 43394 _field_entry_t *f_ent = NULL; 43395 _field_group_t *fg; 43396 bcm_field_qset_t *qset; 43397 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; /* UDF offset info. */ 43398 int num_elems = 0; 43399 int qid = 0; 43400 int idx; /* HW bitmap iteration index. */ 43401 int rv; /* Operation return status. */ 43402 int copy_len; 43403 int len = 0; 43404 int off = 0; 43405 int max_elems = 0; 43406 int min_elems = 0; 43407 int udf1_elems = 0; /* elements in UDF1 */ 43408 int udf2_elems = 0; /* elements in UDF2 */ 43409 _bcm_field_udf_data_t udf_data; /* UDF full data */ 43410 _bcm_field_udf_data_t udf_mask; /* UDF mask for full data */ 43411 _bcm_field_qual_data_t udf_data1; /* UDF full data */ 43412 _bcm_field_qual_data_t udf_mask1; /* UDF mask for full data */ 43413 int gran = 0; 43414 #if defined(BCM_TOMAHAWK_SUPPORT) 43415 uint8 hints_present = 0; 43416 #endif 43417 43418 #ifdef LE_HOST 43419 _bcm_field_udf_data_t udf_data_swap; /* UDF full data */ 43420 _bcm_field_udf_data_t udf_mask_swap; /* UDF mask for full data */ 43421 int part = 0; 43422 #endif /* LE_HOST */ 43423 43424 43425 /* Input parameters check. */ 43426 if ((NULL == data) || (NULL == mask) || 43427 (NULL == actual_length) || (max_length == 0)) { 43428 return (BCM_E_PARAM); 43429 } 43430 43431 UDF_LOCK(unit); 43432 43433 /* Get Granularity */ 43434 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 43435 43436 /* Get UDF info. */ 43437 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info); 43438 if (BCM_FAILURE(rv)) { 43439 UDF_UNLOCK(unit); 43440 return (rv); 43441 } 43442 43443 /* 43444 * If provided entry data length is less than data length used 43445 * to create qualifier then return error 43446 */ 43447 43448 if (max_length < offset_info->width) { 43449 UDF_UNLOCK(unit); 43450 return (BCM_E_PARAM); 43451 } 43452 43453 FP_LOCK(unit); 43454 43455 /* Get stage field control structure. */ 43456 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 43457 if (BCM_FAILURE(rv)) { 43458 FP_UNLOCK(unit); 43459 UDF_UNLOCK(unit); 43460 return (rv); 43461 } 43462 43463 rv = _bcm_field_entry_get_by_id(unit, eid, &f_ent); 43464 if (BCM_FAILURE(rv)) { 43465 FP_UNLOCK(unit); 43466 UDF_UNLOCK(unit); 43467 return (rv); 43468 } 43469 43470 /* Get field group */ 43471 fg = f_ent->group; 43472 43473 #if defined(BCM_TOMAHAWK_SUPPORT) 43474 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 43475 _BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 43476 FP_UNLOCK(unit); 43477 UDF_UNLOCK(unit); 43478 rv = (bcmi_field_th_qualify_udf_get( 43479 unit, eid, udf_id, max_length, 43480 data, mask, actual_length)); 43481 if (BCM_E_NOT_FOUND == rv) { 43482 rv = _field_udf_hints_present_get(unit, eid, udf_id, &hints_present); 43483 if (BCM_FAILURE(rv)) { 43484 return BCM_E_INTERNAL; 43485 } 43486 if (hints_present) { 43487 rv = BCM_E_NONE; 43488 } 43489 } 43490 43491 return rv; 43492 } 43493 #endif 43494 43495 43496 /* get qset */ 43497 qset = &(fg->qset); 43498 43499 /* Get number of elems per UDF and elem size */ 43500 num_elems = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 43501 43502 for (idx = 0; idx < num_elems/2; idx++) { 43503 if (!(offset_info->hw_bmap & (1 << idx))) { 43504 continue; 43505 } 43506 udf1_elems++; 43507 } 43508 43509 for (idx = num_elems/2; idx < num_elems; idx++) { 43510 if (!(offset_info->hw_bmap & (1 << idx))) { 43511 continue; 43512 } 43513 udf2_elems++; 43514 } 43515 43516 if (udf1_elems != 0) { 43517 qid = _bcmFieldQualifyData0; 43518 max_elems = num_elems/2; 43519 min_elems = 0; 43520 } else if (udf2_elems != 0) { 43521 qid = _bcmFieldQualifyData1; 43522 max_elems = num_elems; 43523 min_elems = num_elems/2; 43524 } 43525 43526 do { 43527 /* Qset has Data2 Data3 instead of Data0 qualifier */ 43528 if ((qid == _bcmFieldQualifyData0) && 43529 (!BCM_FIELD_QSET_TEST_INTERNAL(*qset, _bcmFieldQualifyData0))) { 43530 sal_memset(udf_data, 0, sizeof(_bcm_field_qual_data_t)); 43531 sal_memset(udf_mask, 0, sizeof(_bcm_field_qual_data_t)); 43532 if (BCM_FIELD_QSET_TEST_INTERNAL(*qset, _bcmFieldQualifyData2)) { 43533 rv = _field_entry_qualifier_key_get(unit, eid, _bcmFieldQualifyData2, 43534 udf_data1, udf_mask1); 43535 if (BCM_FAILURE(rv)) { 43536 FP_UNLOCK(unit); 43537 UDF_UNLOCK(unit); 43538 return (rv); 43539 } 43540 udf_data[0] = udf_data1[0]; 43541 udf_mask[0] = udf_mask1[0]; 43542 } 43543 if (BCM_FIELD_QSET_TEST_INTERNAL(*qset, _bcmFieldQualifyData3)) { 43544 rv = _field_entry_qualifier_key_get(unit, eid, _bcmFieldQualifyData3, 43545 udf_data1, udf_mask1); 43546 if (BCM_FAILURE(rv)) { 43547 FP_UNLOCK(unit); 43548 UDF_UNLOCK(unit); 43549 return (rv); 43550 } 43551 udf_data[2] = udf_data1[0]; 43552 udf_mask[2] = udf_mask1[0]; 43553 } 43554 } else { 43555 rv = _field_entry_qualifier_key_get(unit, eid, qid, 43556 udf_data, udf_mask); 43557 if (BCM_FAILURE(rv)) { 43558 FP_UNLOCK(unit); 43559 UDF_UNLOCK(unit); 43560 return (rv); 43561 } 43562 } 43563 #ifdef LE_HOST 43564 for (part = 0; part < _FP_UDF_DATA_WORDS; part++) { 43565 udf_data_swap[part]= _shr_swap32(udf_data[part]); 43566 udf_data[part]= udf_data_swap[part]; 43567 udf_mask_swap[part]= _shr_swap32(udf_mask[part]); 43568 udf_mask[part]= udf_mask_swap[part]; 43569 } 43570 #endif /* LE_HOST */ 43571 43572 for (idx = min_elems; idx < max_elems; idx++) { 43573 if (!(offset_info->hw_bmap & (1 << idx))) { 43574 continue; 43575 } 43576 43577 if ((offset_info->width - len) <= 0) { 43578 break; 43579 } 43580 43581 if (gran == UDF_OFFSET_GRAN2) { 43582 /* 43583 * Retreive the relevant data and mask from 4 words 43584 * (4 * 4 = 16 bytes) of data and mask. 43585 * For each index set a chunk(2 bytes) are read. The way 43586 * information is organized is for different index values 43587 * data resides in following location. 43588 * index = 0 data in 12,13 - W = 3 offset = 0 43589 * index = 1 data in 14,15 - W = 3 offset = 2 43590 * index = 2 data in 8,9 - W = 2 offset = 0 43591 * index = 3 data in 10,11 - W = 2 offset = 2 43592 * index = 4 data in 4,5 - W = 1 offset = 0 43593 * index = 5 data in 6,7 - W = 1 offset = 2 43594 * index = 6 data is 0,1 - W = 0 offset = 0 43595 * index = 7 data is 2,3 - W = 0 offset = 2 43596 */ 43597 off = idx % 2 * 2; 43598 copy_len = ((offset_info->width - len) == 1)? 1 : 2; 43599 if (len == 0) { 43600 off += offset_info->byte_offset; 43601 copy_len = 2 - offset_info->byte_offset; 43602 if (copy_len > offset_info->width) { 43603 copy_len = offset_info->width; 43604 } 43605 } 43606 sal_memcpy(data+len, 43607 (uint8 *)&udf_data[((max_elems - 1) 43608 - idx)/2]+off, copy_len); 43609 sal_memcpy(mask+len, 43610 (uint8 *)&udf_mask[((max_elems - 1) 43611 - idx)/2]+off, copy_len); 43612 len += copy_len; 43613 } else { 43614 /* Retreive the relevant data and mask from 4 words 43615 * (4 * 4 = 16 bytes) of data and mask. 43616 * For each index set a chunk(4 bytes) are read. The way 43617 * information is organized is for different index values 43618 * data resides in following location. 43619 * index = 0 data in 12,13,14,15 - W = 3 offset = 0 43620 * index = 1 data in 8,9,10,11 - W = 2 offset = 0 43621 * index = 2 data in 4,5,6,7 - W = 1 offset = 0 43622 * index = 3 data is 0,1,2,3 - W = 0 offset = 0 43623 */ 43624 off = offset_info->byte_offset; 43625 if (len == 0) { 43626 /* first word */ 43627 copy_len = 4 - off; 43628 /* Only one word */ 43629 if (copy_len > offset_info->width) { 43630 copy_len = offset_info->width; 43631 } 43632 sal_memcpy(data+len, 43633 (uint8 *)&udf_data[(max_elems - 1) - idx] + off, 43634 copy_len); 43635 sal_memcpy(mask+len, 43636 (uint8 *)&udf_mask[(max_elems - 1) - idx] + off, 43637 copy_len); 43638 len += copy_len; 43639 } else if ((len + 4) > offset_info->width) { 43640 /* last word */ 43641 sal_memcpy(data+len, 43642 (uint8 *)&udf_data[(max_elems - 1) - idx], 43643 (offset_info->width - len)); 43644 sal_memcpy(mask+len, 43645 (uint8 *)&udf_mask[(max_elems - 1) - idx], 43646 (offset_info->width - len)); 43647 len += (offset_info->width - len); 43648 } else { 43649 /* others */ 43650 sal_memcpy(data+len, 43651 (uint8 *)&udf_data[(max_elems - 1) - idx], 4); 43652 sal_memcpy(mask+len, 43653 (uint8 *)&udf_mask[(max_elems - 1) - idx], 4); 43654 len += 4; 43655 } 43656 } 43657 } 43658 43659 if ((qid == _bcmFieldQualifyData0) && (udf2_elems != 0)) { 43660 qid = _bcmFieldQualifyData1; 43661 max_elems = num_elems; 43662 min_elems = num_elems/2; 43663 continue; 43664 } 43665 43666 *actual_length = offset_info->width; 43667 break; 43668 43669 } while (1); 43670 43671 FP_UNLOCK(unit); 43672 UDF_UNLOCK(unit); 43673 43674 return rv; 43675 } 43676 43677 #endif /* (BCM_TRIUMPH2_SUPPORT) */ 43678 43679 #if defined(INCLUDE_L3) 43680 /* 43681 * Function: _bcm_field_l3_egr_object_ifp_type_get 43682 * 43683 * Purpose: 43684 * Retrieve the IFP type and resolved next hop index with flags for the 43685 * given egress object index. 43686 * 43687 * Parameters: 43688 * unit - (IN) Unit number. 43689 * nh_index - (IN) Egress object index. 43690 * ifp_type - (OUT) TRUE or FALSE 43691 * nh_flags - (OUT) Next Hop Flags 43692 * nh_ecmp_id - (OUT) Resolved Next Hop Index. 43693 * 43694 * Returns: 43695 * BCM_E_XXX 43696 * Notes: 43697 */ 43698 int _bcm_field_l3_egr_object_ifp_type_index_get(int unit, bcm_if_t nh_index, 43699 int *ifp_type, uint32 *nh_flags, 43700 int *nh_ecmp_id) 43701 { 43702 int rv, ct; 43703 int intf_ct = 0; 43704 int intf_size = 0; 43705 bcm_l3_egress_t l3_egr; 43706 bcm_if_t *intf_arr = NULL; 43707 int l3_object_ct = 0; 43708 int ifp_object_ct = 0; 43709 #ifdef BCM_TOMAHAWK_SUPPORT 43710 int i = 0; 43711 int total_intf_ct = 0, tmp_intf_ct = 0; 43712 bcm_if_t *total_intf_arr = NULL; 43713 int offset = 0; 43714 int *intf_arr_cnt = NULL; 43715 #endif 43716 43717 if ((ifp_type == NULL) || (nh_flags == NULL) || (nh_ecmp_id == NULL)) { 43718 return BCM_E_PARAM; 43719 } 43720 43721 /* Get next hop info from Egress Object ID param */ 43722 BCM_IF_ERROR_RETURN(_bcm_field_policy_set_l3_nh_resolve(unit, 43723 nh_index, nh_flags, nh_ecmp_id)); 43724 43725 if (*nh_flags & BCM_L3_MULTIPATH) { 43726 43727 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, nh_index)) { 43728 nh_index += BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 43729 } 43730 43731 rv = bcm_xgs3_l3_egress_multipath_get(unit, nh_index, 43732 0, NULL, &intf_ct); 43733 BCM_IF_ERROR_RETURN(rv); 43734 43735 _FP_XGS3_ALLOC(intf_arr, (sizeof(bcm_if_t) * intf_ct), 43736 "FP: Temp Intf Array"); 43737 if (intf_arr == NULL) { 43738 return (BCM_E_MEMORY); 43739 } 43740 43741 intf_size = intf_ct; 43742 intf_ct = 0; 43743 rv = bcm_esw_l3_egress_multipath_get(unit, nh_index, 43744 intf_size, 43745 intf_arr, &intf_ct); 43746 if (BCM_FAILURE(rv)) { 43747 sal_free(intf_arr); 43748 return BCM_E_PARAM; 43749 } 43750 #ifdef BCM_TOMAHAWK_SUPPORT 43751 /* In case of Hierarchical ECMP, Overlay groups may contain ECMP 43752 interfaces as members. In such cases, these ecmp interfaces have to 43753 be further resolved to get l3 interfaces */ 43754 if ((soc_feature(unit, soc_feature_hierarchical_ecmp) || 43755 (SOC_IS_TRIDENT3X(unit) && (soc_property_get(unit, spn_L3_ECMP_LEVELS, 1) == 2))) && 43756 BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, nh_index)) { 43757 43758 /* coverity[overrun-local] */ 43759 if ((BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, 43760 nh_index - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), BCM_L3_ECMP_OVERLAY))) { 43761 _FP_XGS3_ALLOC(intf_arr_cnt, sizeof(bcm_if_t) * intf_ct, 43762 "FP:temp intf arr"); 43763 /* First get the count of total ECMP interfaces. 43764 Go through all interfaces and get the next level interfaces 43765 if it is an ECMP interface. If not, add that to array of 43766 interfaces Count of ECMP interfaces needs to be maintained 43767 as bcm_xgs3_l3_egress_multipath_get returns interfaces only 43768 when correct count is passed. */ 43769 for (i=0; i < intf_ct; i++) { 43770 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf_arr[i])){ 43771 total_intf_ct += 1; 43772 continue; 43773 } 43774 if ((BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, 43775 intf_arr[i]-BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 43776 BCM_L3_ECMP_UNDERLAY))) { 43777 tmp_intf_ct = 0; 43778 nh_index = intf_arr[i]; 43779 rv = bcm_xgs3_l3_egress_multipath_get(unit, nh_index, 0, 43780 NULL, &tmp_intf_ct); 43781 if (BCM_FAILURE(rv)) { 43782 sal_free(intf_arr_cnt); 43783 sal_free(intf_arr); 43784 return BCM_E_PARAM; 43785 } 43786 intf_arr_cnt[i] = tmp_intf_ct; 43787 total_intf_ct += tmp_intf_ct; 43788 } else { 43789 sal_free(intf_arr_cnt); 43790 sal_free(intf_arr); 43791 return BCM_E_PARAM; 43792 } 43793 } 43794 _FP_XGS3_ALLOC(total_intf_arr, sizeof(bcm_if_t) * total_intf_ct, 43795 "FP:temp intf arr"); 43796 offset = 0; 43797 for (i=0; i < intf_ct; i++) { 43798 tmp_intf_ct = 0; 43799 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf_arr[i])){ 43800 sal_memcpy(&total_intf_arr[offset], &intf_arr[i], 43801 sizeof(bcm_if_t)); 43802 offset += 1; 43803 continue; 43804 } 43805 43806 if ((BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, 43807 intf_arr[i]-BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), BCM_L3_ECMP_UNDERLAY))) { 43808 nh_index = intf_arr[i]; 43809 rv = bcm_esw_l3_egress_multipath_get(unit, nh_index, 43810 intf_arr_cnt[i], &total_intf_arr[offset], &tmp_intf_ct); 43811 if (BCM_FAILURE(rv)) { 43812 sal_free(intf_arr); 43813 sal_free(total_intf_arr); 43814 sal_free(intf_arr_cnt); 43815 return BCM_E_PARAM; 43816 } 43817 offset += tmp_intf_ct; 43818 } 43819 } 43820 sal_free(intf_arr); 43821 sal_free(intf_arr_cnt); 43822 intf_arr = total_intf_arr; 43823 intf_ct = total_intf_ct; 43824 43825 } 43826 } 43827 #endif 43828 43829 } else { 43830 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, nh_index) && 43831 !(soc_feature(unit, soc_feature_field_multi_pipe_support) && 43832 BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, nh_index))) { 43833 nh_index += BCM_XGS3_EGRESS_IDX_MIN(unit); 43834 } 43835 43836 intf_ct = 1; 43837 _FP_XGS3_ALLOC(intf_arr, (sizeof(bcm_if_t) * intf_ct), 43838 "FP: Temp Intf Array"); 43839 if (intf_arr == NULL) { 43840 return (BCM_E_MEMORY); 43841 } 43842 intf_arr[0] = nh_index; 43843 } 43844 43845 for (ct = 0; ct < intf_ct; ct++) { 43846 rv = bcm_esw_l3_egress_get(unit, intf_arr[ct], &l3_egr); 43847 if (BCM_FAILURE(rv)) { 43848 sal_free(intf_arr); 43849 return BCM_E_PARAM; 43850 } 43851 43852 if (l3_egr.flags2 & BCM_L3_FLAGS2_FIELD_ONLY) { 43853 ifp_object_ct++; 43854 } else { 43855 l3_object_ct++; 43856 } 43857 } 43858 43859 if (ifp_object_ct && l3_object_ct) { 43860 sal_free(intf_arr); 43861 return BCM_E_PARAM; 43862 } 43863 43864 if (ifp_object_ct) { 43865 *ifp_type = TRUE; 43866 } else { 43867 *ifp_type = FALSE; 43868 } 43869 43870 sal_free(intf_arr); 43871 return BCM_E_NONE; 43872 } 43873 43874 #endif /* INCLUDE_L3 */ 43875 43876 /* 43877 * Function: 43878 * _bcm_field_initialized_status_get 43879 * Purpose: 43880 * Check whether the field module is initialized 43881 * Parameters: 43882 * unit - BCM device number 43883 * status - Reference to the init status. 43884 * returns TRUE if initialized 43885 * FALSE if not initialized. 43886 */ 43887 int 43888 _bcm_field_initialized_status_get(int unit, uint8 *status) 43889 { 43890 if (status == NULL) { 43891 return BCM_E_PARAM; 43892 } 43893 43894 if (!soc_feature(unit, soc_feature_field)) { 43895 return (BCM_E_UNAVAIL); 43896 } 43897 43898 *status = FALSE; 43899 if (_field_control[unit] != NULL) { 43900 *status = (TRUE == _field_control[unit]->init) ? TRUE:FALSE; 43901 } 43902 43903 return BCM_E_NONE; 43904 } 43905 43906 43907 #ifdef BCM_WARM_BOOT_SUPPORT 43908 int 43909 _field_table_pointers_init(int unit, _field_table_pointers_t *field_tables) 43910 { 43911 if (NULL == field_tables) { 43912 return BCM_E_INTERNAL; 43913 } 43914 43915 field_tables->fp_global_mask_tcam_buf = NULL; 43916 field_tables->fp_gm_tcam_x_buf = NULL; 43917 field_tables->fp_gm_tcam_y_buf = NULL; 43918 field_tables->fp_tcam_buf = NULL; 43919 field_tables->fp_tcam_x_buf = NULL; 43920 field_tables->fp_tcam_y_buf = NULL; 43921 43922 return BCM_E_NONE; 43923 } 43924 43925 /* 43926 * Function: _field_entry_no_param_actions_scache_sync 43927 * 43928 * Purpose: 43929 * Sync entry field actions with no params into scache 43930 * Parameters: 43931 * unit - (IN) BCM device number. 43932 * stage_fc - (IN) Stage Control. 43933 * fc - (IN) Field Control. 43934 * f_ent - (IN) Entry structure. 43935 * scache_buf - (OUT) Update Scache buffer. 43936 * Returns: 43937 * BCM_E_XXXX. 43938 */ 43939 int _field_entry_no_param_actions_scache_sync(int unit, 43940 _field_stage_t *stage_fc, 43941 _field_control_t *fc, 43942 _field_entry_t *f_ent, 43943 uint8 *scache_buf) 43944 { 43945 _field_action_t *fa; 43946 _field_action_bmp_t action_bk_bitmap; /* bit map of actions used for entry */ 43947 int errcode = BCM_E_NONE; 43948 int _action = -1; 43949 int size; 43950 int copyToCpuZeroParam1 = 0; 43951 int gport_type = 0; 43952 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \ 43953 defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 43954 uint32 PortPrioIntGportVal = 0; 43955 uint32 YpPortPrioIntGportVal = 0; 43956 uint32 RpPortPrioIntGportVal = 0; 43957 #endif 43958 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 43959 int ingressGportAction = -1; 43960 int ingressGportVal = 0; 43961 #endif 43962 bcm_gport_t ingress_mirror_gport[4] = {0}; 43963 _bcmFieldActionNoParam_t ingress_mirror_actions[] = { 43964 _bcmFieldActionNoParamMirrorIngress, 43965 _bcmFieldActionNoParamMirrorIngress1, 43966 _bcmFieldActionNoParamMirrorIngress2, 43967 _bcmFieldActionNoParamMirrorIngress3}; 43968 bcm_gport_t egress_mirror_gport[4] = {0}; 43969 _bcmFieldActionNoParam_t egress_mirror_actions[] = { 43970 _bcmFieldActionNoParamMirrorEgress, 43971 _bcmFieldActionNoParamMirrorEgress1, 43972 _bcmFieldActionNoParamMirrorEgress2, 43973 _bcmFieldActionNoParamMirrorEgress3}; 43974 uint32 param0 = 0; 43975 uint8 index = 0; 43976 #if defined(BCM_KATANA_SUPPORT) 43977 uint32 param1 = 0; 43978 #endif /* BCM_KATANA_SUPPORT */ 43979 43980 if (stage_fc == NULL || fc == NULL || f_ent == NULL || scache_buf == NULL) { 43981 return BCM_E_PARAM; 43982 } 43983 43984 if ((stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) && 43985 (stage_fc->stage_id != _BCM_FIELD_STAGE_EGRESS) && 43986 (stage_fc->stage_id != _BCM_FIELD_STAGE_LOOKUP)) { 43987 return BCM_E_NONE; 43988 } 43989 43990 action_bk_bitmap.w = NULL; 43991 _FP_XGS3_ALLOC(action_bk_bitmap.w, SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount), 43992 "Action No Param Bitmap"); 43993 43994 if (action_bk_bitmap.w == NULL) { 43995 return BCM_E_MEMORY; 43996 } 43997 43998 fa = f_ent->actions; 43999 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 44000 switch(fa->action) { 44001 case bcmFieldActionPrioPktAndIntCopy: 44002 case bcmFieldActionPrioPktAndIntNew: 44003 case bcmFieldActionPrioPktNew: 44004 case bcmFieldActionPrioPktAndIntTos: 44005 case bcmFieldActionPrioPktAndIntCancel: 44006 case bcmFieldActionPrioPktCopy: 44007 case bcmFieldActionPrioPktTos: 44008 case bcmFieldActionPrioPktCancel: 44009 _action = _bcmFieldActionNoParamPrioPktNoColor; 44010 break; 44011 case bcmFieldActionPrioIntCopy: 44012 case bcmFieldActionPrioIntNew: 44013 case bcmFieldActionPrioIntTos: 44014 case bcmFieldActionPrioIntCancel: 44015 _action = _bcmFieldActionNoParamPrioIntNoColor; 44016 break; 44017 case bcmFieldActionCopyToCpu: 44018 case bcmFieldActionTimeStampToCpu: 44019 _action = _bcmFieldActionNoParamCopyToCpuNoColor; 44020 if ((fa->param[0] != 0) && (fa->param[1] == 0)) { 44021 copyToCpuZeroParam1 = 1; 44022 } 44023 break; 44024 case bcmFieldActionCopyToCpuCancel: 44025 case bcmFieldActionSwitchToCpuCancel: 44026 case bcmFieldActionSwitchToCpuReinstate: 44027 case bcmFieldActionTimeStampToCpuCancel: 44028 _action = _bcmFieldActionNoParamCopyToCpuNoColor; 44029 break; 44030 case bcmFieldActionRpCopyToCpu: 44031 case bcmFieldActionRpTimeStampToCpu: 44032 if ((fa->param[0] != 0) && (fa->param[1] == 0)) { 44033 _action = _bcmFieldActionNoParamRpCopyToCpuZeroParam1; 44034 } 44035 break; 44036 case bcmFieldActionYpCopyToCpu: 44037 case bcmFieldActionYpTimeStampToCpu: 44038 if ((fa->param[0] != 0) && (fa->param[1] == 0)) { 44039 _action = _bcmFieldActionNoParamYpCopyToCpuZeroParam1; 44040 } 44041 break; 44042 case bcmFieldActionGpCopyToCpu: 44043 case bcmFieldActionGpTimeStampToCpu: 44044 if ((fa->param[0] != 0) && (fa->param[1] == 0)) { 44045 _action = _bcmFieldActionNoParamCopyToCpuZeroParam1; 44046 } 44047 break; 44048 case bcmFieldActionDrop: 44049 case bcmFieldActionDropCancel: 44050 _action = _bcmFieldActionNoParamDropNoColor; 44051 break; 44052 case bcmFieldActionOamUpMep: 44053 if (fa->param[0] != 0) { 44054 continue; 44055 } 44056 _action = _bcmFieldActionNoParamOamUpMep; 44057 break; 44058 case bcmFieldActionOamTx: 44059 if (fa->param[0] != 0) { 44060 continue; 44061 } 44062 _action = _bcmFieldActionNoParamOamTx; 44063 break; 44064 case bcmFieldActionOamLmepEnable: 44065 if (fa->param[0] != 0) { 44066 continue; 44067 } 44068 _action = _bcmFieldActionNoParamOamLmepEnable; 44069 break; 44070 case bcmFieldActionOamLmEnable: 44071 if (fa->param[0] != 0) { 44072 continue; 44073 } 44074 _action = _bcmFieldActionNoParamOamLmEnable; 44075 break; 44076 case bcmFieldActionOamDmEnable: 44077 if (fa->param[0] != 0) { 44078 continue; 44079 } 44080 _action = _bcmFieldActionNoParamOamDmEnable; 44081 break; 44082 case bcmFieldActionOamLmepMdl: 44083 if (fa->param[0] != 0) { 44084 continue; 44085 } 44086 _action = _bcmFieldActionNoParamOamLmepMdl; 44087 break; 44088 case bcmFieldActionOamLmBasePtr: 44089 if (fa->param[0] != 0) { 44090 continue; 44091 } 44092 _action = _bcmFieldActionNoParamOamLmBasePtr; 44093 break; 44094 case bcmFieldActionOamServicePriMappingPtr: 44095 if (fa->param[0] != 0) { 44096 continue; 44097 } 44098 _action = _bcmFieldActionNoParamOamServicePriMappingPtr; 44099 break; 44100 case bcmFieldActionOamPbbteLookupEnable: 44101 if (fa->param[0] != 0) { 44102 continue; 44103 } 44104 _action = _bcmFieldActionNoParamOamPbbteLookupEnable; 44105 break; 44106 case bcmFieldActionOamLmDmSampleEnable: 44107 if (fa->param[0] != 0) { 44108 continue; 44109 } 44110 _action = _bcmFieldActionNoParamOamLmDmSampleEnable; 44111 break; 44112 case bcmFieldActionNewClassId: 44113 if (fa->param[0] != 0) { 44114 continue; 44115 } 44116 _action = _bcmFieldActionNoParamNewClassId; 44117 break; 44118 case bcmFieldActionOamLmCounterPoolId: 44119 _action = _bcmFieldActionNoParamOamLmCounterPoolId; 44120 break; 44121 case bcmFieldActionDscpNew: 44122 case bcmFieldActionDscpCancel: 44123 _action = _bcmFieldActionNoParamDscpNoColor; 44124 break; 44125 case bcmFieldActionInnerVlanPrioNew: 44126 _action = _bcmFieldActionNoParamInnerVlanPriNewNoColor; 44127 break; 44128 case bcmFieldActionOuterVlanPrioNew: 44129 _action = _bcmFieldActionNoParamOuterVlanPriNewNoColor; 44130 break; 44131 case bcmFieldActionInnerVlanCfiNew: 44132 _action = _bcmFieldActionNoParamInnerVlanCfiNewNoColor; 44133 break; 44134 case bcmFieldActionOuterVlanCfiNew: 44135 _action = _bcmFieldActionNoParamOuterVlanCfiNewNoColor; 44136 break; 44137 case bcmFieldActionEcnNew: 44138 _action = _bcmFieldActionNoParamEcnNewNoColor; 44139 break; 44140 case bcmFieldActionRpDropPrecedence: 44141 if (fa->param[0] != 0) { 44142 continue; 44143 } 44144 _action = _bcmFieldActionNoParamRpDropPrecedence; 44145 break; 44146 case bcmFieldActionYpDropPrecedence: 44147 if (fa->param[0] != 0) { 44148 continue; 44149 } 44150 _action = _bcmFieldActionNoParamYpDropPrecedence; 44151 break; 44152 case bcmFieldActionGpDropPrecedence: 44153 if (fa->param[0] != 0) { 44154 continue; 44155 } 44156 _action = _bcmFieldActionNoParamGpDropPrecedence; 44157 break; 44158 case bcmFieldActionDropPrecedence: 44159 _action = _bcmFieldActionNoParamDropPrecedenceNoColor; 44160 break; 44161 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 44162 case bcmFieldActionIngressGportSet: 44163 _action = _bcmFieldActionNoParamIngressGportSet; 44164 ingressGportAction = 1; 44165 ingressGportVal = fa->param[0]; 44166 break; 44167 #endif /* INCLUDE_L3 */ 44168 case bcmFieldActionRedirectIpmc: 44169 if (_BCM_MULTICAST_IS_WLAN(fa->param[0])) { 44170 _action = _bcmFieldActionNoParamRedirectIpmcWlan; 44171 } else if (_BCM_MULTICAST_IS_VPLS(fa->param[0])) { 44172 _action = _bcmFieldActionNoParamRedirectIpmcVpls; 44173 } else if (_BCM_MULTICAST_IS_L3(fa->param[0])) { 44174 _action = _bcmFieldActionNoParamRedirectIpmcL3; 44175 } else if (_BCM_MULTICAST_IS_VLAN(fa->param[0])) { 44176 _action = _bcmFieldActionNoParamRedirectIpmcVlan; 44177 } 44178 break; 44179 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 44180 case bcmFieldActionIncomingMplsPortSet: 44181 _action = _bcmFieldActionNoParamIncomingMplsPortSet; 44182 ingressGportAction = 1; 44183 ingressGportVal = fa->param[0]; 44184 break; 44185 #endif /* INCLUDE_L3 */ 44186 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \ 44187 defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 44188 case bcmFieldActionPortPrioIntCosQNew: 44189 _action = _bcmFieldActionNoParamPortPrioIntCosQNew; 44190 PortPrioIntGportVal = fa->param[1]; 44191 break; 44192 case bcmFieldActionGpPortPrioIntCosQNew: 44193 _action = _bcmFieldActionNoParamGpPortPrioIntCosQNew; 44194 PortPrioIntGportVal = fa->param[1]; 44195 break; 44196 case bcmFieldActionYpPortPrioIntCosQNew: 44197 _action = _bcmFieldActionNoParamYpPortPrioIntCosQNew; 44198 YpPortPrioIntGportVal = fa->param[1]; 44199 break; 44200 case bcmFieldActionRpPortPrioIntCosQNew: 44201 _action = _bcmFieldActionNoParamRpPortPrioIntCosQNew; 44202 RpPortPrioIntGportVal = fa->param[1]; 44203 break; 44204 #endif 44205 case bcmFieldActionMirrorIngress: 44206 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) { 44207 if (!BCM_GPORT_IS_MIRROR(fa->param[1])) { 44208 continue; 44209 } 44210 44211 #ifdef BCM_TRIUMPH2_SUPPORT 44212 if (((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) && 44213 soc_feature(unit, soc_feature_mirror_flexible) && 44214 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 44215 int mtp_type_index; 44216 int flexibleMirror; 44217 int directedMirror; 44218 int rv; 44219 44220 rv = bcm_esw_switch_control_get(unit,bcmSwitchFlexibleMirrorDestinations, 44221 &flexibleMirror); 44222 if (BCM_FAILURE(rv)) { 44223 errcode = rv; 44224 goto cleanup; 44225 } 44226 44227 rv = bcm_esw_switch_control_get(unit,bcmSwitchDirectedMirroring, 44228 &directedMirror); 44229 if (BCM_FAILURE(rv)) { 44230 errcode = rv; 44231 goto cleanup; 44232 } 44233 44234 if (flexibleMirror && directedMirror) { 44235 mtp_type_index = ((fa->hw_index >> BCM_MIRROR_MTP_FLEX_SLOT_SHIFT) 44236 & BCM_MIRROR_MTP_FLEX_SLOT_MASK); 44237 } else { 44238 mtp_type_index = fa->hw_index; 44239 } 44240 if ((mtp_type_index >= 4) || (mtp_type_index < 0)) { 44241 errcode = BCM_E_INTERNAL; 44242 goto cleanup; 44243 } 44244 _action = ingress_mirror_actions[mtp_type_index]; 44245 ingress_mirror_gport[mtp_type_index] = fa->param[1]; 44246 } else 44247 #endif 44248 { 44249 _action = _bcmFieldActionNoParamMirrorIngress; 44250 ingress_mirror_gport[0] = fa->param[1]; 44251 } 44252 } 44253 break; 44254 case bcmFieldActionMirrorEgress: 44255 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) { 44256 if (!BCM_GPORT_IS_MIRROR(fa->param[1])) { 44257 continue; 44258 } 44259 #ifdef BCM_TRIUMPH2_SUPPORT 44260 if (((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) && 44261 soc_feature(unit, soc_feature_mirror_flexible) && 44262 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) { 44263 int mtp_type_index; 44264 int flexibleMirror; 44265 int directedMirror; 44266 int rv; 44267 44268 rv = bcm_esw_switch_control_get(unit,bcmSwitchFlexibleMirrorDestinations, 44269 &flexibleMirror); 44270 if (BCM_FAILURE(rv)) { 44271 errcode = rv; 44272 goto cleanup; 44273 } 44274 44275 rv = bcm_esw_switch_control_get(unit,bcmSwitchDirectedMirroring, 44276 &directedMirror); 44277 if (BCM_FAILURE(rv)) { 44278 errcode = rv; 44279 goto cleanup; 44280 } 44281 44282 if (flexibleMirror && directedMirror) { 44283 mtp_type_index = ((fa->hw_index >> BCM_MIRROR_MTP_FLEX_SLOT_SHIFT) 44284 & BCM_MIRROR_MTP_FLEX_SLOT_MASK); 44285 } else { 44286 mtp_type_index = fa->hw_index; 44287 } 44288 if ((mtp_type_index >= 4) || (mtp_type_index < 0)) { 44289 errcode = BCM_E_INTERNAL; 44290 goto cleanup; 44291 } 44292 _action = egress_mirror_actions[mtp_type_index]; 44293 egress_mirror_gport[mtp_type_index] = fa->param[1]; 44294 } else 44295 #endif 44296 { 44297 _action = _bcmFieldActionNoParamMirrorEgress; 44298 egress_mirror_gport[0] = fa->param[1]; 44299 } 44300 } 44301 break; 44302 case bcmFieldActionRedirDropPrecedence: 44303 _action = _bcmFieldActionNoParamRedirDropPrecedenceNoColor; 44304 break; 44305 case bcmFieldActionFabricQueue: 44306 _action = _bcmFieldActionNoParamFabricQueue; 44307 param0 = fa->param[0]; 44308 #if defined(BCM_KATANA_SUPPORT) 44309 if (SOC_IS_KATANAX(unit)) { 44310 param1 = fa->param[1]; 44311 } 44312 #endif 44313 break; 44314 case bcmFieldActionEnableVlanCheck: 44315 _action = _bcmFieldActionNoParamEnableVlanCheck; 44316 break; 44317 case bcmFieldActionHiGigIntPriNew: 44318 _action = _bcmFieldActionNoParamHiGigIntPriNew; 44319 break; 44320 case bcmFieldActionHiGigDropPrecedenceNew: 44321 _action = _bcmFieldActionNoParamHiGigDropPrecedenceNew; 44322 break; 44323 case bcmFieldActionRedirect: 44324 #ifdef BCM_TRIUMPH3_SUPPORT 44325 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 44326 if (BCM_GPORT_IS_MPLS_PORT(fa->param[1])) { 44327 _action = _bcmFieldActionNoParamRedirectMpls; 44328 } else if (BCM_GPORT_IS_MIM_PORT(fa->param[1])) { 44329 _action = _bcmFieldActionNoParamRedirectMim; 44330 } else if (BCM_GPORT_IS_NIV_PORT(fa->param[1])) { 44331 _action = _bcmFieldActionNoParamRedirectNiv; 44332 } else if (BCM_GPORT_IS_TRILL_PORT(fa->param[1])) { 44333 _action = _bcmFieldActionNoParamRedirectTrill; 44334 } else if (BCM_GPORT_IS_L2GRE_PORT(fa->param[1])) { 44335 _action = _bcmFieldActionNoParamRedirectL2Gre; 44336 } else if (BCM_GPORT_IS_VXLAN_PORT(fa->param[1])) { 44337 _action = _bcmFieldActionNoParamRedirectVxLan; 44338 } 44339 } 44340 #endif 44341 break; 44342 case bcmFieldActionRedirectTrunk: 44343 #if defined(BCM_TRIDENT2_SUPPORT) 44344 if ((soc_feature(unit, soc_feature_vp_lag)) && 44345 ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_24)) { 44346 _action = _bcmFieldActionNoParamRedirectTrunk; 44347 } 44348 #endif 44349 break; 44350 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC) 44351 case bcmFieldActionMacSecSubPortNumAdd: 44352 if (SOC_IS_MONTEREY(unit)) { 44353 if (BCM_XFLOW_MACSEC_SUBPORT_ID_DIR_TYPE_GET(fa->param[0]) \ 44354 == BCM_XFLOW_MACSEC_ENCRYPT) { 44355 _action = _bcmFieldActionNoParamMacSecSubPortEncrypt; 44356 } else { 44357 _action = _bcmFieldActionNoParamMacSecSubPortDecrypt; 44358 } 44359 } 44360 break; 44361 #endif 44362 #if defined(BCM_GREYHOUND2_SUPPORT) 44363 case bcmFieldActionSRNetIdSource: 44364 _action = _bcmFieldActionNoParamSRNetIdSource; 44365 break; 44366 #endif /* BCM_GREYHOUND2_SUPPORT */ 44367 default: 44368 continue; 44369 } 44370 if (_action != -1) { 44371 _FP_ACTION_BMP_ADD(action_bk_bitmap, _action); 44372 _action = -1; 44373 } 44374 } 44375 44376 if (copyToCpuZeroParam1 == 1) { 44377 _FP_ACTION_BMP_ADD(action_bk_bitmap, 44378 _bcmFieldActionNoParamCopyToCpuZeroParam1); 44379 } 44380 44381 size = SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount); 44382 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 44383 "%s(): Writing actions backup bitmap[0x%x] for entry:%d size:%d" 44384 " @ byte %d.\n\r"), __func__, 44385 action_bk_bitmap.w[0], f_ent->eid, size, fc->scache_pos)); 44386 44387 /* To avoid endiness issues always sync in mutlple of 4 bytes */ 44388 scache_buf[fc->scache_pos] = action_bk_bitmap.w[0]; 44389 fc->scache_pos++; 44390 scache_buf[fc->scache_pos] = action_bk_bitmap.w[0] >> 8; 44391 fc->scache_pos++; 44392 scache_buf[fc->scache_pos] = action_bk_bitmap.w[0] >> 16; 44393 fc->scache_pos++; 44394 scache_buf[fc->scache_pos] = action_bk_bitmap.w[0] >> 24; 44395 fc->scache_pos++; 44396 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_19) { 44397 scache_buf[fc->scache_pos] = action_bk_bitmap.w[1]; 44398 fc->scache_pos++; 44399 scache_buf[fc->scache_pos] = action_bk_bitmap.w[1] >> 8; 44400 fc->scache_pos++; 44401 scache_buf[fc->scache_pos] = action_bk_bitmap.w[1] >> 16; 44402 fc->scache_pos++; 44403 scache_buf[fc->scache_pos] = action_bk_bitmap.w[1] >> 24; 44404 fc->scache_pos++; 44405 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \ 44406 defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 44407 /* Sync data only if actions are present */ 44408 if ((SHR_BITGET(action_bk_bitmap.w, _bcmFieldActionNoParamPortPrioIntCosQNew)) || 44409 (SHR_BITGET(action_bk_bitmap.w, _bcmFieldActionNoParamGpPortPrioIntCosQNew))) { 44410 scache_buf[fc->scache_pos] = PortPrioIntGportVal; 44411 fc->scache_pos++; 44412 scache_buf[fc->scache_pos] = PortPrioIntGportVal >> 8; 44413 fc->scache_pos++; 44414 scache_buf[fc->scache_pos] = PortPrioIntGportVal >> 16; 44415 fc->scache_pos++; 44416 scache_buf[fc->scache_pos] = PortPrioIntGportVal >> 24; 44417 fc->scache_pos++; 44418 } 44419 if (SHR_BITGET(action_bk_bitmap.w, _bcmFieldActionNoParamYpPortPrioIntCosQNew)) { 44420 scache_buf[fc->scache_pos] = YpPortPrioIntGportVal; 44421 fc->scache_pos++; 44422 scache_buf[fc->scache_pos] = YpPortPrioIntGportVal >> 8; 44423 fc->scache_pos++; 44424 scache_buf[fc->scache_pos] = YpPortPrioIntGportVal >> 16; 44425 fc->scache_pos++; 44426 scache_buf[fc->scache_pos] = YpPortPrioIntGportVal >> 24; 44427 fc->scache_pos++; 44428 } 44429 if (SHR_BITGET(action_bk_bitmap.w, _bcmFieldActionNoParamRpPortPrioIntCosQNew)) { 44430 scache_buf[fc->scache_pos] = RpPortPrioIntGportVal; 44431 fc->scache_pos++; 44432 scache_buf[fc->scache_pos] = RpPortPrioIntGportVal >> 8; 44433 fc->scache_pos++; 44434 scache_buf[fc->scache_pos] = RpPortPrioIntGportVal >> 16; 44435 fc->scache_pos++; 44436 scache_buf[fc->scache_pos] = RpPortPrioIntGportVal >> 24; 44437 fc->scache_pos++; 44438 } 44439 #endif 44440 } 44441 44442 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 44443 if (ingressGportAction == 1) { 44444 /* Get the source virtual port value */ 44445 if (BCM_GPORT_IS_MPLS_PORT(ingressGportVal)) { 44446 gport_type = _bcmVpTypeMpls; 44447 } else if (BCM_GPORT_IS_MIM_PORT(ingressGportVal)) { 44448 gport_type = _bcmVpTypeMim; 44449 } else if (BCM_GPORT_IS_WLAN_PORT(ingressGportVal)) { 44450 gport_type = _bcmVpTypeWlan; 44451 } else if (BCM_GPORT_IS_TRILL_PORT(ingressGportVal)) { 44452 gport_type = _bcmVpTypeTrill; 44453 } else if (BCM_GPORT_IS_NIV_PORT(ingressGportVal)) { 44454 gport_type = _bcmVpTypeNiv; 44455 } else if (BCM_GPORT_IS_VXLAN_PORT(ingressGportVal)) { 44456 gport_type = _bcmVpTypeVxlan; 44457 } else if (BCM_GPORT_IS_FLOW_PORT(ingressGportVal)) { 44458 gport_type = _bcmVpTypeFlow; 44459 } else if (BCM_GPORT_IS_VLAN_PORT(ingressGportVal)) { 44460 gport_type = _bcmVpTypeVlan; 44461 } else { 44462 errcode = BCM_E_PARAM; 44463 goto cleanup; 44464 } 44465 } 44466 #endif /* INCLUDE_L3 */ 44467 /* Reserve 1-byte to write IngressGportAction Gport Type. */ 44468 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_16) { 44469 scache_buf[fc->scache_pos] = gport_type; 44470 fc->scache_pos++; 44471 } 44472 44473 /* Reserve 4-bytes each for Ingress and Egress Mirror Gports. */ 44474 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) { 44475 for (index = 0 ; index < 4; index++) { 44476 if (SHR_BITGET(action_bk_bitmap.w, ingress_mirror_actions[index])) { 44477 scache_buf[fc->scache_pos] = ingress_mirror_gport[index]; 44478 fc->scache_pos++; 44479 scache_buf[fc->scache_pos] = ingress_mirror_gport[index] >> 8; 44480 fc->scache_pos++; 44481 scache_buf[fc->scache_pos] = ingress_mirror_gport[index] >> 16; 44482 fc->scache_pos++; 44483 scache_buf[fc->scache_pos] = ingress_mirror_gport[index] >> 24; 44484 fc->scache_pos++; 44485 } 44486 } 44487 for (index = 0 ; index < 4; index++) { 44488 if (SHR_BITGET(action_bk_bitmap.w, egress_mirror_actions[index])) { 44489 scache_buf[fc->scache_pos] = egress_mirror_gport[index]; 44490 fc->scache_pos++; 44491 scache_buf[fc->scache_pos] = egress_mirror_gport[index] >> 8; 44492 fc->scache_pos++; 44493 scache_buf[fc->scache_pos] = egress_mirror_gport[index] >> 16; 44494 fc->scache_pos++; 44495 scache_buf[fc->scache_pos] = egress_mirror_gport[index] >> 24; 44496 fc->scache_pos++; 44497 } 44498 } 44499 if ( SHR_BITGET(action_bk_bitmap.w, 44500 _bcmFieldActionNoParamFabricQueue)) { 44501 scache_buf[fc->scache_pos] = param0; 44502 fc->scache_pos++; 44503 scache_buf[fc->scache_pos] = param0 >> 8; 44504 fc->scache_pos++; 44505 scache_buf[fc->scache_pos] = param0 >> 16; 44506 fc->scache_pos++; 44507 scache_buf[fc->scache_pos] = param0 >> 24; 44508 fc->scache_pos++; 44509 #if defined(BCM_KATANA_SUPPORT) 44510 if (SOC_IS_KATANAX(unit)) { 44511 scache_buf[fc->scache_pos] = param1; 44512 fc->scache_pos++; 44513 scache_buf[fc->scache_pos] = param1 >> 8; 44514 fc->scache_pos++; 44515 scache_buf[fc->scache_pos] = param1 >> 16; 44516 fc->scache_pos++; 44517 scache_buf[fc->scache_pos] = param1 >> 24; 44518 fc->scache_pos++; 44519 } 44520 #endif /* BCM_KATANA_SUPPORT*/ 44521 } 44522 } 44523 goto cleanup; 44524 cleanup: 44525 if (action_bk_bitmap.w != NULL) { 44526 _FP_ACTION_BMP_FREE(action_bk_bitmap); 44527 action_bk_bitmap.w = NULL; 44528 } 44529 return (errcode); 44530 } 44531 44532 int _field_group_slice_sel_get(int unit, 44533 _field_group_t *fg, 44534 _field_slice_sel_info_t *slice_sels) 44535 { 44536 int i = 0; 44537 int parts_count = 0; 44538 44539 /* Retrieve the parts count for the given group */ 44540 BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit, fg->stage_id, 44541 fg->flags, &parts_count)); 44542 44543 for (i = 0; i < parts_count; i++) { 44544 if (fg->sel_codes[i].src_class_sel != _FP_INVALID_INDEX) { 44545 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44546 _bcmFieldGroupSliceSrcClassSel); 44547 } 44548 if (fg->sel_codes[i].dst_class_sel != _FP_INVALID_INDEX) { 44549 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44550 _bcmFieldGroupSliceDstClassSel); 44551 } 44552 if (fg->sel_codes[i].intf_class_sel != _FP_INVALID_INDEX) { 44553 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44554 _bcmFieldGroupSliceIntfClassSel); 44555 } 44556 if (fg->sel_codes[i].intf_class_sel != _FP_INVALID_INDEX) { 44557 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44558 _bcmFieldGroupSliceIntfClassSel); 44559 } 44560 if (fg->sel_codes[i].ingress_entity_sel != _FP_INVALID_INDEX) { 44561 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44562 _bcmFieldGroupSliceIngressEntitySel); 44563 } 44564 if (fg->sel_codes[i].src_entity_sel != _FP_INVALID_INDEX) { 44565 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44566 _bcmFieldGroupSliceSrcEntitySel); 44567 } 44568 if (fg->sel_codes[i].dst_fwd_entity_sel != _FP_INVALID_INDEX) { 44569 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44570 _bcmFieldGroupSliceDstFwdEntitySel); 44571 } 44572 if (fg->sel_codes[i].fwd_field_sel != _FP_INVALID_INDEX) { 44573 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44574 _bcmFieldGroupSliceFwdFieldSel); 44575 } 44576 if (fg->sel_codes[i].ttl_class_sel != _FP_INVALID_INDEX) { 44577 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44578 _bcmFieldGroupSliceTtlClassSelect); 44579 } 44580 if (fg->sel_codes[i].tos_class_sel != _FP_INVALID_INDEX) { 44581 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44582 _bcmFieldGroupSliceTosClassSelect); 44583 } 44584 if (fg->sel_codes[i].tcp_class_sel != _FP_INVALID_INDEX) { 44585 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44586 _bcmFieldGroupSliceTcpClassSelect); 44587 } 44588 if (fg->sel_codes[i].loopback_type_sel != _FP_INVALID_INDEX) { 44589 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44590 _bcmFieldGroupSliceLoopbackTypeSel); 44591 } 44592 if (fg->sel_codes[i].ip_header_sel != _FP_INVALID_INDEX) { 44593 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44594 _bcmFieldGroupSliceIpHeaderSel); 44595 } 44596 if (fg->sel_codes[i].ip6_addr_sel != _FP_INVALID_INDEX) { 44597 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44598 _bcmFieldGroupSliceIp6AddrSel); 44599 } 44600 if (fg->sel_codes[i].aux_tag_1_sel != _FP_INVALID_INDEX) { 44601 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44602 _bcmFieldGroupSliceAuxTag1Sel); 44603 } 44604 if (fg->sel_codes[i].aux_tag_2_sel != _FP_INVALID_INDEX) { 44605 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44606 _bcmFieldGroupSliceAuxTag2Sel); 44607 } 44608 if (fg->sel_codes[i].normalize_ip_sel != _FP_INVALID_INDEX) { 44609 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44610 _bcmFieldGroupSliceNormalizeIpSel); 44611 } 44612 if (fg->sel_codes[i].normalize_mac_sel != _FP_INVALID_INDEX) { 44613 _FP_SEL_BMP_ADD(slice_sels->slice_sel[i], 44614 _bcmFieldGroupSliceNormalizeMacSel); 44615 } 44616 } 44617 44618 return BCM_E_NONE; 44619 44620 } 44621 44622 int _field_group_slice_sel_set(int unit, _field_group_t *fg, 44623 _field_slice_sel_info_t *slice_sels) 44624 { 44625 int i = 0; 44626 int parts_count = 0; 44627 44628 /* Retrieve the parts count for the given group */ 44629 BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit, fg->stage_id, 44630 fg->flags, &parts_count)); 44631 44632 for (i = 0; i < parts_count; i++) { 44633 44634 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44635 _bcmFieldGroupSliceSrcClassSel) == 0) 44636 && (_bcmFieldGroupSliceSrcClassSel < slice_sels->slice_sel_count)) { 44637 fg->sel_codes[i].src_class_sel = _FP_INVALID_INDEX; 44638 } 44639 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44640 _bcmFieldGroupSliceDstClassSel) == 0) 44641 && (_bcmFieldGroupSliceDstClassSel < slice_sels->slice_sel_count)) { 44642 fg->sel_codes[i].dst_class_sel = _FP_INVALID_INDEX; 44643 } 44644 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44645 _bcmFieldGroupSliceIntfClassSel) == 0) 44646 && (_bcmFieldGroupSliceIntfClassSel < slice_sels->slice_sel_count)) { 44647 fg->sel_codes[i].intf_class_sel = _FP_INVALID_INDEX; 44648 } 44649 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44650 _bcmFieldGroupSliceIngressEntitySel) == 0) 44651 && (_bcmFieldGroupSliceIngressEntitySel < slice_sels->slice_sel_count)) { 44652 fg->sel_codes[i].ingress_entity_sel = _FP_INVALID_INDEX; 44653 } 44654 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44655 _bcmFieldGroupSliceSrcEntitySel) == 0) 44656 && (_bcmFieldGroupSliceSrcEntitySel < slice_sels->slice_sel_count)) { 44657 fg->sel_codes[i].src_entity_sel = _FP_INVALID_INDEX; 44658 } 44659 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44660 _bcmFieldGroupSliceDstFwdEntitySel) == 0) 44661 && (_bcmFieldGroupSliceDstFwdEntitySel < slice_sels->slice_sel_count)) { 44662 fg->sel_codes[i].dst_fwd_entity_sel = _FP_INVALID_INDEX; 44663 } 44664 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44665 _bcmFieldGroupSliceFwdFieldSel) == 0) 44666 && (_bcmFieldGroupSliceFwdFieldSel < slice_sels->slice_sel_count)) { 44667 fg->sel_codes[i].fwd_field_sel = _FP_INVALID_INDEX; 44668 } 44669 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44670 _bcmFieldGroupSliceTtlClassSelect) == 0) 44671 && (_bcmFieldGroupSliceTtlClassSelect < slice_sels->slice_sel_count)) { 44672 fg->sel_codes[i].ttl_class_sel = _FP_INVALID_INDEX; 44673 } 44674 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44675 _bcmFieldGroupSliceTosClassSelect) == 0) 44676 && (_bcmFieldGroupSliceTosClassSelect < slice_sels->slice_sel_count)) { 44677 fg->sel_codes[i].tos_class_sel = _FP_INVALID_INDEX; 44678 } 44679 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44680 _bcmFieldGroupSliceTcpClassSelect) == 0) 44681 && (_bcmFieldGroupSliceTcpClassSelect < slice_sels->slice_sel_count)) { 44682 fg->sel_codes[i].tcp_class_sel = _FP_INVALID_INDEX; 44683 } 44684 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44685 _bcmFieldGroupSliceLoopbackTypeSel) == 0) 44686 && (_bcmFieldGroupSliceLoopbackTypeSel < slice_sels->slice_sel_count)) { 44687 fg->sel_codes[i].loopback_type_sel = _FP_INVALID_INDEX; 44688 } 44689 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44690 _bcmFieldGroupSliceIpHeaderSel) == 0) 44691 && (_bcmFieldGroupSliceIpHeaderSel < slice_sels->slice_sel_count)) { 44692 fg->sel_codes[i].ip_header_sel = _FP_INVALID_INDEX; 44693 } 44694 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44695 _bcmFieldGroupSliceIp6AddrSel) == 0) 44696 && (_bcmFieldGroupSliceIp6AddrSel < slice_sels->slice_sel_count)) { 44697 fg->sel_codes[i].ip6_addr_sel = _FP_INVALID_INDEX; 44698 } 44699 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44700 _bcmFieldGroupSliceAuxTag1Sel) == 0) 44701 && (_bcmFieldGroupSliceAuxTag1Sel < slice_sels->slice_sel_count)) { 44702 fg->sel_codes[i].aux_tag_1_sel = _FP_INVALID_INDEX; 44703 } 44704 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44705 _bcmFieldGroupSliceAuxTag2Sel) == 0) 44706 && (_bcmFieldGroupSliceAuxTag2Sel < slice_sels->slice_sel_count)) { 44707 fg->sel_codes[i].aux_tag_2_sel = _FP_INVALID_INDEX; 44708 } 44709 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44710 _bcmFieldGroupSliceNormalizeIpSel) == 0) 44711 && (_bcmFieldGroupSliceNormalizeIpSel < slice_sels->slice_sel_count)) { 44712 fg->sel_codes[i].normalize_ip_sel = _FP_INVALID_INDEX; 44713 } 44714 if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i], 44715 _bcmFieldGroupSliceNormalizeMacSel) == 0) 44716 && (_bcmFieldGroupSliceNormalizeMacSel < slice_sels->slice_sel_count)) { 44717 fg->sel_codes[i].normalize_mac_sel = _FP_INVALID_INDEX; 44718 } 44719 } 44720 44721 return BCM_E_NONE; 44722 44723 } 44724 44725 44726 /* Function: _field_group_slice_selectors_sync 44727 * 44728 * Purpose: 44729 * Sync the hint id associated with the group. 44730 * Parameters: 44731 * unit - (IN) BCM device number. 44732 * uint8 - (IN) Scache_ptr 44733 * Returns: 44734 * BCM_E_XXXX. 44735 */ 44736 int _field_group_slice_selectors_sync (int unit, uint8 *scache_ptr, 44737 _field_stage_id_t stage_id) 44738 { 44739 _field_control_t *fc; /* Field control structure. */ 44740 _field_group_t *fg; /* Field group info. */ 44741 _field_slice_sel_info_t slice_sels; /* Field Group Slice selectors */ 44742 int idx = 0; 44743 int parts_count = 0; 44744 44745 if (scache_ptr == NULL) { 44746 return BCM_E_PARAM; 44747 } 44748 44749 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 44750 44751 fg = fc->groups; 44752 if (NULL == fg) { 44753 return (BCM_E_NONE); 44754 } 44755 44756 for (; fg != NULL; fg = fg->next) { 44757 if (stage_id == fg->stage_id) { 44758 /* Retrieve the parts count for the given group */ 44759 BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit, 44760 fg->stage_id, 44761 fg->flags, &parts_count)); 44762 44763 for (idx = 0; idx < parts_count; idx++) { 44764 slice_sels.slice_sel[idx].w = NULL; 44765 _FP_XGS3_ALLOC(slice_sels.slice_sel[idx].w, 44766 SHR_BITALLOCSIZE(_bcmFieldGroupSliceCount), 44767 "Group Slice Selectors Bitmap"); 44768 if (slice_sels.slice_sel[idx].w == NULL) { 44769 int index; 44770 for (index = 0; index < idx; index++) { 44771 _FP_SEL_BMP_FREE(slice_sels.slice_sel[index]); 44772 } 44773 return BCM_E_MEMORY; 44774 } 44775 } 44776 _field_group_slice_sel_get(unit, fg, 44777 &slice_sels); 44778 slice_sels.gid = fg->gid; 44779 slice_sels.slice_sel_count = _bcmFieldGroupSliceCount; 44780 44781 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 44782 "%s(): Writing gid[%d] @ byte %d.\n\r"), __func__, 44783 slice_sels.gid, fc->scache_pos)); 44784 sal_memcpy (scache_ptr, &(slice_sels.gid), 44785 sizeof(bcm_field_group_t)); 44786 fc->scache_pos += sizeof (bcm_field_group_t); 44787 scache_ptr += sizeof (bcm_field_group_t); 44788 44789 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 44790 "%s(): Writing slice_sel_count[%d] @ byte %d.\n\r"), __func__, 44791 slice_sels.slice_sel_count, fc->scache_pos)); 44792 sal_memcpy (scache_ptr, &(slice_sels.slice_sel_count), 44793 sizeof(slice_sels.slice_sel_count)); 44794 fc->scache_pos += sizeof (slice_sels.slice_sel_count); 44795 scache_ptr += sizeof (slice_sels.slice_sel_count); 44796 44797 44798 for (idx = 0; idx < parts_count; idx++) { 44799 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 44800 "%s(): Writing selector bitmap[0x%x] group:%d part:%d" 44801 " @ byte %d.\n\r"), __func__, 44802 slice_sels.slice_sel[idx].w[0], fg->gid, idx, fc->scache_pos)); 44803 44804 sal_memcpy (scache_ptr, slice_sels.slice_sel[idx].w, 44805 sizeof(_field_selector_bmp_t)); 44806 fc->scache_pos += sizeof (_field_selector_bmp_t); 44807 scache_ptr += sizeof (_field_selector_bmp_t); 44808 44809 _FP_SEL_BMP_FREE(slice_sels.slice_sel[idx]); 44810 } 44811 } 44812 } 44813 44814 return BCM_E_NONE; 44815 } 44816 44817 /* Function: _field_group_slice_selectors_recover 44818 * 44819 * Purpose: 44820 * Sync the hint id associated with the group. 44821 * Parameters: 44822 * unit - (IN) BCM device number. 44823 * uint8 - (IN) Scache_ptr 44824 * Returns: 44825 * BCM_E_XXXX. 44826 */ 44827 int _field_group_slice_selectors_recover (int unit, uint8 *scache_ptr, 44828 _field_stage_id_t stage_id) 44829 { 44830 _field_control_t *fc; /* Field control structure. */ 44831 _field_group_t *fg; /* Field group info. */ 44832 _field_slice_sel_info_t slice_sels; /* Field Group Slice selectors */ 44833 int idx = 0, grp_idx = 0; 44834 int group_count = 0; 44835 int rv = 0; 44836 int parts_count = 0; 44837 44838 if (scache_ptr == NULL) { 44839 return BCM_E_PARAM; 44840 } 44841 44842 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 44843 44844 fg = fc->groups; 44845 if (NULL == fg) { 44846 return (BCM_E_NONE); 44847 } 44848 44849 for (; fg != NULL; fg = fg->next) { 44850 if (stage_id == fg->stage_id) { 44851 group_count++; 44852 } 44853 } 44854 44855 if (group_count == 0) { 44856 return (BCM_E_NONE); 44857 } 44858 44859 fg = NULL; 44860 for (grp_idx = 0; grp_idx < group_count; grp_idx++) { 44861 sal_memcpy (&(slice_sels.gid), scache_ptr, 44862 sizeof (bcm_field_group_t)); 44863 fc->scache_pos += sizeof (bcm_field_group_t); 44864 scache_ptr += sizeof (bcm_field_group_t); 44865 44866 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 44867 "%s(): Recovering gid[%d] @ byte %d.\n\r"), __func__, 44868 slice_sels.gid, (fc->scache_pos - 4))); 44869 44870 sal_memcpy (&(slice_sels.slice_sel_count), scache_ptr, 44871 sizeof (slice_sels.slice_sel_count)); 44872 fc->scache_pos += sizeof (slice_sels.slice_sel_count); 44873 scache_ptr += sizeof (slice_sels.slice_sel_count); 44874 44875 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 44876 "%s(): Recovering slice_sel_count[%d] @ byte %d.\n\r"), __func__, 44877 slice_sels.slice_sel_count, (fc->scache_pos - 1))); 44878 44879 rv = _field_group_get(unit, slice_sels.gid, &fg); 44880 if (BCM_FAILURE(rv)) { 44881 return rv; 44882 } 44883 44884 /* Retrieve the parts count for the given group */ 44885 rv = _bcm_field_entry_tcam_parts_count(unit, 44886 fg->stage_id, 44887 fg->flags, &parts_count); 44888 if (BCM_FAILURE(rv)) { 44889 return rv; 44890 } 44891 44892 sal_memset(slice_sels.slice_sel, 0x0, 44893 sizeof(_field_selector_bmp_t) * _FP_MAX_ENTRY_WIDTH); 44894 44895 for (idx = 0; idx < parts_count; idx++) { 44896 slice_sels.slice_sel[idx].w = NULL; 44897 _FP_XGS3_ALLOC(slice_sels.slice_sel[idx].w, 44898 SHR_BITALLOCSIZE(slice_sels.slice_sel_count), 44899 "Group Slice Selectors Bitmap"); 44900 if (slice_sels.slice_sel[idx].w == NULL) { 44901 rv = BCM_E_MEMORY; 44902 goto cleanup; 44903 } 44904 44905 sal_memcpy (slice_sels.slice_sel[idx].w, scache_ptr, 44906 sizeof(_field_selector_bmp_t)); 44907 fc->scache_pos += sizeof (_field_selector_bmp_t); 44908 scache_ptr += sizeof (_field_selector_bmp_t); 44909 44910 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 44911 "%s(): Recovering selectors bitmap[0x%x] for group:%d part:%d" 44912 " @ byte %d.\n\r"), __func__, 44913 slice_sels.slice_sel[idx].w[0], fg->gid, idx, 44914 (fc->scache_pos - 4))); 44915 } 44916 44917 _field_group_slice_sel_set(unit, fg, 44918 &slice_sels); 44919 for (idx = 0; idx < parts_count; idx++) { 44920 if (slice_sels.slice_sel[idx].w != NULL) { 44921 _FP_SEL_BMP_FREE(slice_sels.slice_sel[idx]); 44922 slice_sels.slice_sel[idx].w = NULL; 44923 } 44924 } 44925 } 44926 44927 cleanup: 44928 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 44929 if (slice_sels.slice_sel[idx].w != NULL) { 44930 _FP_SEL_BMP_FREE(slice_sels.slice_sel[idx]); 44931 } 44932 } 44933 return rv; 44934 } 44935 44936 44937 #endif 44938 44939 44940 44941 /* 44942 * Function: _field_dump_brief 44943 * 44944 * Purpose: 44945 * Show current S/W state if compiled in debug mode without entries. 44946 * 44947 * Parameters: 44948 * unit - BCM device number 44949 * pfx - Character string to prefix output lines 44950 * 44951 * Returns: 44952 * BCM_E_XXX. 44953 */ 44954 44955 int 44956 _field_dump_brief(int unit, const char *pfx) 44957 { 44958 int idx; 44959 _field_group_t *fg; 44960 _field_range_t *fr; 44961 _field_stage_t *stage_fc; 44962 _field_control_t *fc; 44963 int rv = 0; 44964 int entry_ratio; /* Invalid entries ratio. */ 44965 44966 44967 FP_LOCK(unit); 44968 rv = _field_control_get(unit, &fc); 44969 if (BCM_FAILURE(rv)) { 44970 FP_UNLOCK(unit); 44971 return rv; 44972 } 44973 44974 stage_fc = fc->stages; 44975 44976 44977 LOG_CLI((BSL_META_U(unit, 44978 "%s:\tunit %d:\n"), pfx, unit)); 44979 44980 while(stage_fc) { 44981 44982 entry_ratio = (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) ? 4: 44983 ((stage_fc->flags & _FP_STAGE_HALF_SLICE) ? 2 : 1); 44984 44985 switch (stage_fc->stage_id) { 44986 case _BCM_FIELD_STAGE_INGRESS: 44987 LOG_CLI((BSL_META_U(unit, 44988 "PIPELINE STAGE INGRESS\n"))); 44989 LOG_CLI((BSL_META_U(unit, 44990 "%s:\t :tcam_sz=%d(%#x),"), 44991 pfx, stage_fc->tcam_sz/entry_ratio, 44992 stage_fc->tcam_sz/entry_ratio)); 44993 break; 44994 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 44995 case _BCM_FIELD_STAGE_LOOKUP: 44996 LOG_CLI((BSL_META_U(unit, 44997 "PIPELINE STAGE LOOKUP\n"))); 44998 LOG_CLI((BSL_META_U(unit, 44999 "%s:\t :tcam_sz=%d(%#x),"), 45000 pfx, stage_fc->tcam_sz/entry_ratio, 45001 stage_fc->tcam_sz/entry_ratio)); 45002 break; 45003 case _BCM_FIELD_STAGE_EGRESS: 45004 LOG_CLI((BSL_META_U(unit, 45005 "PIPELINE STAGE EGRESS\n"))); 45006 LOG_CLI((BSL_META_U(unit, 45007 "%s:\t :tcam_sz=%d(%#x),"), 45008 pfx, stage_fc->tcam_sz/entry_ratio, 45009 stage_fc->tcam_sz/entry_ratio)); 45010 break; 45011 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 45012 case _BCM_FIELD_STAGE_EXTERNAL: 45013 LOG_CLI((BSL_META_U(unit, 45014 "PIPELINE STAGE EXTERNAL\n"))); 45015 LOG_CLI((BSL_META_U(unit, 45016 "%s:\t :tcam_sz=%d(%#x),"), 45017 pfx, stage_fc->tcam_sz, stage_fc->tcam_sz)); 45018 break; 45019 default: 45020 break; 45021 } 45022 45023 LOG_CLI((BSL_META_U(unit, 45024 " tcam_slices=%d,"), stage_fc->tcam_slices)); 45025 LOG_CLI((BSL_META_U(unit, 45026 " tcam_ext_numb=%d,"), fc->tcam_ext_numb)); 45027 LOG_CLI((BSL_META_U(unit, 45028 "\n"))); 45029 45030 /* Display any range checkers defined. */ 45031 if ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) || 45032 (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id)) { 45033 for (fr = stage_fc->ranges; fr != NULL; fr = fr->next) { 45034 _field_range_dump(pfx, fr); 45035 } 45036 } 45037 stage_fc = stage_fc->next; 45038 } 45039 /* Print the any defined UDFs. */ 45040 for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) { 45041 if (fc->udf[idx].valid) { 45042 LOG_CLI((BSL_META_U(unit, 45043 "%s:\tudf %d: use_count=%d, udf_num=%s, user_num=%d\n"), 45044 pfx, idx, fc->udf[idx].use_count, 45045 _field_qual_name(fc->udf[idx].udf_num + _bcmFieldQualifyData0), 45046 fc->udf[idx].user_num)); 45047 } 45048 } 45049 45050 /* Print the groups, along with their entries. */ 45051 for (fg = fc->groups; fg != NULL ; fg = fg->next) { 45052 #if defined(BCM_TOMAHAWK_SUPPORT) 45053 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 45054 (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) { 45055 /* Don't dump Class Group in 'fp show brief' command */ 45056 continue; 45057 } 45058 #endif /* BCM_TOMAHAWK_SUPPORT */ 45059 _field_group_dump_brief(unit, fg->gid); 45060 } 45061 45062 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 45063 #if defined(BCM_TRX_SUPPORT) 45064 if (SOC_IS_TRX(unit)) { 45065 _bcm_trx_field_egr_ports_recovery_print (unit); 45066 } 45067 #endif 45068 } 45069 45070 FP_UNLOCK(unit); 45071 return (BCM_E_NONE); 45072 } 45073 45074 /* 45075 * Function: _field_dump_class 45076 * Purpose: 45077 * Show current S/W state for class. 45078 * Parameters: 45079 * unit - BCM device number 45080 * pfx - Character string to prefix output lines. 45081 * flag - Flag to control class display. 45082 * Returns: 45083 * BCM_E_XXX. 45084 * Notes: 45085 * If flag is -1 it dumps class group and entries as well. 45086 * Otherwise it dumps brief class table summary. 45087 */ 45088 int 45089 _field_dump_class(int unit, const char *pfx, int flag) 45090 { 45091 int rv = BCM_E_NONE; 45092 #if defined(BCM_TOMAHAWK_SUPPORT) 45093 _field_group_t *fg = NULL; 45094 _field_stage_t *stage_fc = NULL; 45095 _field_control_t *fc = NULL; 45096 45097 /* Retreive Field Control. */ 45098 45099 FP_LOCK(unit); 45100 rv = _field_control_get(unit, &fc); 45101 if (BCM_FAILURE(rv)) { 45102 FP_UNLOCK(unit); 45103 return rv; 45104 } 45105 45106 stage_fc = fc->stages; 45107 45108 LOG_CLI((BSL_META_U(unit, 45109 "%s:\tunit %d:"), pfx, unit)); 45110 45111 /* Retreive Field Stage Class Control */ 45112 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_CLASS, &stage_fc); 45113 if (BCM_FAILURE(rv)) { 45114 FP_UNLOCK(unit); 45115 return (rv); 45116 } 45117 45118 LOG_CLI((BSL_META_U(unit, 45119 "PIPELINE STAGE CLASS\n"))); 45120 _bcm_field_th_class_stage_dump(unit,stage_fc); 45121 45122 /* Dump groups and entries if flag is -1. */ 45123 if (flag == -1) { 45124 /* Print the groups, along with their entries. */ 45125 for (fg = fc->groups; fg != NULL ; fg = fg->next) { 45126 if (fg->stage_id == _BCM_FIELD_STAGE_CLASS) { 45127 /* Dump Group only if it is stage class */ 45128 _bcm_esw_field_group_dump(unit, fg->gid, -1); 45129 } 45130 } 45131 } 45132 45133 FP_UNLOCK(unit); 45134 #endif /* BCM_TOMAHAWK_SUPPORT */ 45135 return (rv); 45136 } 45137 45138 45139 /* 45140 * Function: _field_group_dump_brief 45141 * 45142 * Purpose: 45143 * Show contents of a field group without the entries. 45144 * 45145 * Parameters: 45146 * unit - BCM device number 45147 * group - Field group to dump 45148 * 45149 * Returns: 45150 * Nothing. 45151 */ 45152 int 45153 _field_group_dump_brief(int unit, bcm_field_group_t group) 45154 { 45155 _field_stage_t *stage_fc; 45156 _field_group_t *fg; 45157 int enable = 0; 45158 int parts_count = 0; 45159 int idx; 45160 /* buffer big enough to write out pbmp 45161 * as characters + 0x + terminating NULL */ 45162 char buf[BCM_PBMP_PORT_MAX + 3]; 45163 int rv; 45164 45165 45166 FP_LOCK(unit); 45167 45168 rv = _field_group_get(unit, group, &fg); 45169 if (BCM_FAILURE(rv)) { 45170 FP_UNLOCK(unit); 45171 return (rv); 45172 } 45173 45174 #if defined(BCM_TOMAHAWK_SUPPORT) 45175 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 45176 (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) { 45177 rv = _bcm_field_th_class_group_brief_dump(unit,fg); 45178 FP_UNLOCK(unit); 45179 return (rv); 45180 } 45181 #endif /* BCM_TOMAHAWK_SUPPORT */ 45182 45183 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 45184 if (BCM_FAILURE(rv)) { 45185 FP_UNLOCK(unit); 45186 return (rv); 45187 } 45188 45189 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 45190 fg->flags, &parts_count); 45191 if (BCM_FAILURE(rv)) { 45192 FP_UNLOCK(unit); 45193 return (rv); 45194 } 45195 45196 if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 45197 (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) { 45198 LOG_CLI((BSL_META_U(unit, 45199 "Quad wide intra-slice group, "))); 45200 } else if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 45201 (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE)) { 45202 if (!((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) || 45203 soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support)) && 45204 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id))) { 45205 LOG_CLI((BSL_META_U(unit, 45206 "Intra-slice double wide group, "))); 45207 } 45208 } 45209 LOG_CLI((BSL_META_U(unit, 45210 "GID %10d: gid=0x%x, mode=%s, stage=%s "), group, 45211 fg->gid, _field_group_mode_name(unit, fg->flags, stage_fc), 45212 _field_stage_name(stage_fc))); 45213 bcm_esw_field_group_enable_get(unit, group, &enable); 45214 if (enable) { 45215 LOG_CLI((BSL_META_U(unit, 45216 "lookup=Enabled, "))); 45217 } else { 45218 LOG_CLI((BSL_META_U(unit, 45219 "lookup=Disabled, "))); 45220 } 45221 45222 LOG_CLI((BSL_META_U(unit, 45223 "ActionResId={%d}, "), fg->action_res_id)); 45224 LOG_VERBOSE(BSL_LS_BCM_FP, 45225 (BSL_META_U(unit, 45226 "VMAP={%d %d %d}, "), 45227 fg->vmap_group[0], fg->vmap_group[1], fg->vmap_group[2])); 45228 45229 LOG_CLI((BSL_META_U(unit, 45230 "pbmp={%s}\n"), SOC_PBMP_FMT(fg->pbmp, buf))); 45231 45232 _field_qset_dump(" qset=", fg->qset, ",\n"); 45233 45234 #if defined(BCM_TOMAHAWK_SUPPORT) 45235 if (soc_feature(unit, soc_feature_field_preselector_support) && 45236 (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) { 45237 uint8 not_first = 0; 45238 45239 LOG_CLI((BSL_META_U(unit, 45240 " preselectors={"))); 45241 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 45242 if (fg->presel_ent_arr[idx] != NULL) { 45243 if (not_first) { 45244 LOG_CLI((BSL_META_U(unit, ", "))); 45245 } 45246 LOG_CLI((BSL_META_U(unit, "%d"), fg->presel_ent_arr[idx]->presel_id)); 45247 not_first = 1; 45248 } 45249 } 45250 LOG_CLI((BSL_META_U(unit, "}\n\r"))); 45251 } 45252 #endif /* BCM_TOMAHAWK_SUPPORT */ 45253 45254 if (fg->hintid != 0) { 45255 LOG_CLI((BSL_META_U(unit, 45256 " HintId=%d\n"), fg->hintid)); 45257 } 45258 45259 for (idx = 0; idx < parts_count; idx++) { 45260 sal_sprintf(buf, " selcodes[%d]=\n", idx); 45261 _field_selcode_dump(unit, buf, fg->sel_codes + idx, ", ", fg->stage_id); 45262 _field_qual_list_dump(" ",fg, idx,",\n"); 45263 45264 } 45265 45266 LOG_CLI((BSL_META_U(unit, 45267 "\n"))); 45268 45269 /* Print the primary slice data. */ 45270 LOG_CLI((BSL_META_U(unit, 45271 " slice_pri= %d "), fg->priority)); 45272 _field_slice_dump(unit, " ", fg, &fg->slices[0], "\n"); 45273 45274 /* Print the secondary slice data. */ 45275 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 45276 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 45277 LOG_CLI((BSL_META_U(unit," slice_sec = {slice_number=%d}\n"), 45278 fg->slices[1].slice_number)); 45279 } 45280 45281 /* Print the tertiary slice data. */ 45282 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 45283 LOG_CLI((BSL_META_U(unit," slice_ter = {slice_number=%d}\n"), 45284 fg->slices[2].slice_number)); 45285 } 45286 45287 #if defined(BCM_TOMAHAWK_SUPPORT) /* BCM_TOMAHAWK_SUPPORT */ 45288 if (soc_feature(unit, soc_feature_field_multi_pipe_support) 45289 && ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || 45290 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) || 45291 (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id))) { 45292 /* Get TH IFP group's status. */ 45293 rv = _bcm_field_th_group_status_calc(unit, fg); 45294 } else 45295 #endif /* !BCM_TOMAHAWK_SUPPORT */ 45296 { 45297 /* Update the numbers of free entries, meters and counters. */ 45298 rv = _bcm_field_group_status_calc(unit, fg); 45299 } 45300 45301 /* Print group used resources status */ 45302 if (BCM_SUCCESS(rv)) { 45303 LOG_CLI((BSL_META_U(unit, 45304 " group_status="))); 45305 _field_group_status_dump(&fg->group_status); 45306 LOG_CLI((BSL_META_U(unit, 45307 "\n"))); 45308 } 45309 45310 FP_UNLOCK(unit); 45311 return (BCM_E_NONE); 45312 } 45313 45314 /* 45315 * Function: _bcm_field_presel_dump 45316 * 45317 * Purpose: 45318 * Show current S/W state for Preselectors 45319 * 45320 * Parameters: 45321 * unit - BCM device number 45322 * pfx - Character string to prefix output lines 45323 * 45324 * Returns: 45325 * BCM_E_XXX. 45326 */ 45327 45328 int 45329 _bcm_field_presel_dump(int unit, bcm_field_presel_t presel_id, int stage) 45330 { 45331 int rv = BCM_E_UNAVAIL; 45332 #if defined(BCM_TOMAHAWK_SUPPORT) 45333 _field_action_t *fa; 45334 _field_presel_entry_t *f_presel; 45335 bcm_field_presel_t presel; 45336 _field_control_t *fc; 45337 45338 /* Preselector feature check */ 45339 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 45340 return BCM_E_UNAVAIL; 45341 } 45342 45343 FP_LOCK(unit); 45344 rv = _field_control_get(unit, &fc); 45345 if (BCM_FAILURE(rv)) { 45346 FP_UNLOCK(unit); 45347 return rv; 45348 } 45349 45350 for (presel = 0; presel < BCM_FIELD_PRESEL_SEL_MAX; presel++) { 45351 45352 if ((presel_id != -1) && (presel != presel_id)) { 45353 continue; 45354 } 45355 45356 #if defined (BCM_TOMAHAWK3_SUPPORT) 45357 if ((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) && 45358 (presel == _FP_PRESEL_INTERNAL_RESERVED_ID)) { 45359 continue; 45360 } 45361 #endif 45362 45363 /* Check if presel ID present in presel_set */ 45364 if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel)) { 45365 continue; 45366 } 45367 45368 /* Retrieve the Presel Entry */ 45369 rv = _bcm_field_presel_entry_get(unit, presel, &f_presel); 45370 if (BCM_FAILURE(rv)) { 45371 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 45372 "ERROR: Couldn't retrieve the Preselector Entry for the given" 45373 " Presel ID[%d].\n\r"), presel)); 45374 FP_UNLOCK(unit); 45375 return rv; 45376 } 45377 45378 45379 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStage)) { 45380 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) { 45381 if ((-1 != stage) && 45382 (_BCM_FIELD_STAGE_INGRESS != stage)) { 45383 continue; 45384 } 45385 LOG_CLI((BSL_META_U(unit, 45386 "PRESEL ID: %d, eid=0x%x, priority=%d, hw_index=%d\n\r"), presel, 45387 (presel | BCM_FIELD_QUALIFY_PRESEL), f_presel->priority, 45388 f_presel->hw_index)); 45389 LOG_CLI((BSL_META_U(unit, "\tStage:%s"), "Ingress, ")); 45390 } else if(BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngressExactMatch)) { 45391 if ((-1 != stage) && 45392 (_BCM_FIELD_STAGE_EXACTMATCH != stage)) { 45393 continue; 45394 } 45395 LOG_CLI((BSL_META_U(unit, 45396 "PRESEL ID: %d, eid=0x%x, priority=%d, hw_index=%d\n\r"), presel, 45397 (presel | BCM_FIELD_QUALIFY_PRESEL), f_presel->priority, 45398 f_presel->hw_index)); 45399 LOG_CLI((BSL_META_U(unit, "\tStage:%s"), "IngressExactMatch, ")); 45400 } else { /* Stage Flowtracker */ 45401 if ((-1 != stage) && 45402 (_BCM_FIELD_STAGE_FLOWTRACKER != stage)) { 45403 continue; 45404 } 45405 LOG_CLI((BSL_META_U(unit, 45406 "PRESEL ID: %d, eid=0x%x, priority=%d, hw_index=%d\n\r"), presel, 45407 (presel | BCM_FIELD_QUALIFY_PRESEL), f_presel->priority, 45408 f_presel->hw_index)); 45409 LOG_CLI((BSL_META_U(unit, "\tStage:%s"), "Flowtracker, ")); 45410 } 45411 45412 LOG_CLI((BSL_META_U(unit, " Status:"))); 45413 if (!(f_presel->flags & _FP_ENTRY_INSTALLED)) { 45414 LOG_CLI((BSL_META_U(unit, 45415 "Not installed"))); 45416 } else { 45417 LOG_CLI((BSL_META_U(unit, 45418 "Installed"))); 45419 45420 if (!(f_presel->flags & _FP_ENTRY_ENABLED)) { 45421 LOG_CLI((BSL_META_U(unit, 45422 ", Disabled"))); 45423 } else { 45424 LOG_CLI((BSL_META_U(unit, 45425 ", Enabled"))); 45426 } 45427 45428 if (f_presel->flags & _FP_ENTRY_DIRTY) { 45429 LOG_CLI((BSL_META_U(unit, 45430 ", Dirty"))); 45431 } 45432 } 45433 LOG_CLI((BSL_META_U(unit, "\n\r"))); 45434 } else { 45435 LOG_CLI((BSL_META_U(unit, 45436 "\tNot Configured\n\r"))); 45437 LOG_CLI((BSL_META_U(unit, "\n\r"))); 45438 continue; 45439 } 45440 45441 _field_qset_dump("\tQualifiers=", f_presel->p_qset, ",\n\r"); 45442 45443 _bcm_field_presel_qualifiers_dump(unit, presel); 45444 45445 LOG_CLI((BSL_META_U(unit, "\n\r"))); 45446 fa = f_presel->actions; 45447 while (fa != NULL) { 45448 LOG_CLI((BSL_META_U(unit, 45449 "\taction="))); 45450 _field_action_dump (fa); 45451 LOG_CLI((BSL_META_U(unit, 45452 "\n\r"))); 45453 fa = fa->next; 45454 } 45455 45456 if (presel_id != -1) { 45457 break; 45458 } 45459 LOG_CLI((BSL_META_U(unit, "\n\r"))); 45460 } 45461 45462 FP_UNLOCK(unit); 45463 rv = BCM_E_NONE; 45464 #endif /* BCM_TOMAHAWK_SUPPORT */ 45465 return (rv); 45466 } 45467 45468 /* 45469 * Function: _field_calc_cache_size 45470 * 45471 * Purpose: 45472 * Show Scache size for FP for current configuration 45473 * 45474 * Parameters: 45475 * unit - BCM device number 45476 * 45477 * Returns: 45478 * BCM_E_XXX. 45479 */ 45480 45481 int 45482 _field_calc_cache_size(int unit) 45483 { 45484 45485 #ifdef BCM_WARM_BOOT_SUPPORT 45486 #ifdef BCM_TOMAHAWK_SUPPORT 45487 45488 _field_control_t *fc = NULL; /* Field control Structure */ 45489 _field_stage_t *stage_fc = NULL; /* Field Stage Structure */ 45490 uint32 final_pos = 0; /* Final Scache size */ 45491 45492 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 45493 45494 fc->scache_pos = 0; 45495 wb_write_disable = 1; 45496 45497 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 45498 _BCM_FIELD_STAGE_INGRESS, 45499 &stage_fc)); 45500 45501 BCM_IF_ERROR_RETURN(_bcm_field_th_stage_ingress_sync(unit, 45502 stage_fc)); 45503 /* End Header */ 45504 fc->scache_pos = fc->scache_pos + 4; 45505 45506 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 45507 _BCM_FIELD_STAGE_CLASS, 45508 &stage_fc)); 45509 /* Start Header */ 45510 fc->scache_pos = fc->scache_pos + 5; 45511 45512 BCM_IF_ERROR_RETURN(_bcm_field_th_stage_class_sync(unit, fc, stage_fc)); 45513 45514 /* End Header */ 45515 fc->scache_pos = fc->scache_pos + 5; 45516 45517 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 45518 _BCM_FIELD_STAGE_EXACTMATCH, 45519 &stage_fc)); 45520 45521 BCM_IF_ERROR_RETURN(_bcm_field_th_stage_em_sync(unit, fc, stage_fc)); 45522 45523 /* End Header */ 45524 fc->scache_pos = fc->scache_pos + 5; 45525 45526 #if defined(BCM_HELIX5_SUPPORT) 45527 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 45528 _BCM_FIELD_STAGE_FLOWTRACKER, 45529 &stage_fc)); 45530 45531 BCM_IF_ERROR_RETURN(_bcm_field_stage_ft_sync(unit, fc, stage_fc)); 45532 45533 fc->scache_pos = fc->scache_pos + 5; 45534 #endif 45535 45536 /* size for IFP */ 45537 final_pos = (((fc->scache_pos + 1023) / 1024) * 1024) 45538 + (294 * 1024) /* Size for EFP,VFP partition 0 */ 45539 + (20 *1024); /* Size for EFP,VFP partition 1 */ 45540 /* 45541 * Scache size is increased to sync the bitmap of slice 45542 * indexes that is used to store the slice indexes of the 45543 * disabled entries. 45544 * This is added from WB version BCM_FIELD_WB_VERSION_1_27 45545 * The size is to accomodate both efp and vfp assuming each 45546 * stage have 1024 slice indexes at max. 45547 * so size is bitmap will be 45548 * ((1024/32)bits * 4)bytes*2(efp and vfp)*_FP_MAX_NUM_PIPES 45549 * (((1024/32)*4*2 * _FP_MAX_NUM_PIPES)) 45550 */ 45551 final_pos += ((1024/32)*4 *2*_FP_MAX_NUM_PIPES); 45552 LOG_CLI((BSL_META("Scache size for Field Module : %d \n"), final_pos)); 45553 wb_write_disable = 0; 45554 fc->scache_pos = 0; 45555 45556 #endif /* BCM_WARM_BOOT_SUPPORT */ 45557 #endif /* BCM_TOMAHAWK_SUPPORT */ 45558 45559 return BCM_E_NONE; 45560 } 45561 45562 #ifdef BCM_WARM_BOOT_SUPPORT 45563 45564 /* 45565 * Function: _field_scache_pointer_realloc 45566 * 45567 * Purpose: 45568 * Initialize field component scache pointers and scache sizes for 45569 * multiple partitions. 45570 * Parameters: 45571 * unit - BCM device number 45572 * fc - Field Control Structure 45573 * 45574 * Returns: 45575 * BCM_E_XXX. 45576 */ 45577 45578 45579 static int 45580 _field_scache_pointer_realloc(int unit, _field_control_t *fc) 45581 { 45582 int stable_size; 45583 int rv = BCM_E_NONE; 45584 uint32 alloc_get; 45585 soc_scache_handle_t handle; 45586 45587 if ((NULL != fc->scache_ptr[_FIELD_SCACHE_PART_0]) || 45588 (NULL != fc->scache_ptr[_FIELD_SCACHE_PART_1])) { 45589 45590 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 45591 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 45592 _FIELD_SCACHE_PART_0); 45593 if ((stable_size > 0) && !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 45594 if (SOC_IS_TRX(unit)) { 45595 45596 fc->scache_size[_FIELD_SCACHE_PART_0] = 294 * 1024; 45597 /* Taking all average number into account 45598 * (Note:S-Slices , P- Ports and Q - Qualifiers) 45599 * IFP - 16S * 48P * 25Q 45600 * VFP and EFP - 16S * 25Q 45601 */ 45602 fc->scache_size[_FIELD_SCACHE_PART_1] = 20 * 1024; 45603 45604 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_15) { 45605 /* 45606 * OAM => 70 * 1024 ((7 bytes * 8K IFP entries) + (7 bytes * 2K EFP entries)) 45607 * Policer L1 => 20 * 1024 (4 bytes * 20 slices * 256 entries.) 45608 * No Param Actions => 40 * 1024 (4 bytes * 20 slices * 512 entries.) 45609 * Slice/Secondary Selectors => 5 * 1024 (2 bytes * 128 ports/groups * 20 Slices.) 45610 */ 45611 fc->scache_size[_FIELD_SCACHE_PART_0] += 135 * 1024; 45612 } 45613 45614 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_17) { 45615 45616 /* For WB sync and recovery of configured policer rates, 45617 * syncing only the delta value (diff btw configured and programmed 45618 * for ckbits_sec, ckbits_burst, pkbits_sec, pkbits_burst. 45619 * Taking 2 bytes for each of the delta, 45620 * Required size = Maximum Number of entries * 8 bytes 45621 * IFP := 16K * 8 = 128 KB 45622 * EFP := 2K * 8 = 16KB 45623 * Total size = 144 KB 45624 */ 45625 fc->scache_size[_FIELD_SCACHE_PART_0] += 144 * 1024; 45626 } 45627 45628 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_18) { 45629 /* Sync for SVP DVP type per entry part and 45630 * ingress, src entity selcode per group part 45631 */ 45632 fc->scache_size[_FIELD_SCACHE_PART_0] += (21 * 1024); 45633 } 45634 45635 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_19) { 45636 /* Sync No Param Actions enum and PortPrioIntCosQNew Actions Gport Values 45637 * ((4) Bytes * (16 + 1 + 1) + ((12) bytes * 16) K entries 45638 * in IFP Stage 45639 */ 45640 fc->scache_size[_FIELD_SCACHE_PART_0] += (264 * 1024); 45641 } 45642 45643 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) { 45644 /* Allocate additional scache to sync IFP action ingress 45645 * and egress mirror gport value in no parm actions sync 45646 * enums per entry. IngressMirror and EgressMirror GPORT 45647 * can be assigned to single entry. Have to allocate (4+4) 45648 * bytes per entry. 45649 * IFP = (8 bytes * 512 entries * 12 slices). 45650 */ 45651 fc->scache_size[_FIELD_SCACHE_PART_0] += (48 * 1024); 45652 /* 45653 * Scache size is increased by (16 * 4) * 1024 bytes for 45654 * all devices and (8 * 4) *1024 * 2 for KT2 devices 45655 * to sync and recover the params of fabricQueue action 45656 * for all entries of Ingress. 45657 */ 45658 fc->scache_size[_FIELD_SCACHE_PART_0] += (16 * 4 * 1024); 45659 } 45660 45661 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) { 45662 /* 45663 * Group PBMP is synced with max_groups * size of the pbmp array 45664 */ 45665 fc->scache_size[_FIELD_SCACHE_PART_0] += ((512 * _SHR_PBMP_WORD_MAX * 4) + (16 * 1024 * 12)); 45666 } 45667 45668 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_23) { 45669 /* 45670 * Scache size is increased by 128 * 4 bytes 45671 * to syncloopbacktype selcode per group part. 45672 * Worst case assuming 128 IFP groups in quad mode 45673 * (128 * 4) bytes. 45674 */ 45675 fc->scache_size[_FIELD_SCACHE_PART_0] += (128 * 4); 45676 } 45677 45678 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_26) { 45679 /* 45680 * Scache size is increased by _FP_MAX_NUM_PIPES * 1 bytes 45681 * to sync instance for all pipes in EFP/VFP slice map. 45682 * _FP_MAX_NUM_PIPES * 1 bytes * 8 groups to sync group 45683 * instance for all groups in EFP/VFP 45684 */ 45685 fc->scache_size[_FIELD_SCACHE_PART_0] += ((_FP_MAX_NUM_PIPES) 45686 + (_FP_MAX_NUM_PIPES * 8)); 45687 } 45688 45689 } else { 45690 /* Allocate a section of the Level 2 Warm Boot 45691 * global cache. 45692 * Assume 90% of the total stable size - just a heuristic 45693 */ 45694 fc->scache_size[_FIELD_SCACHE_PART_0] = (9 * stable_size) / 10; 45695 fc->scache_size[_FIELD_SCACHE_PART_1] = (1 * stable_size) / 100; 45696 } 45697 45698 /* Get the pointer for the Level 2 cache */ 45699 SOC_IF_ERROR_RETURN(soc_scache_ptr_get(unit, handle, 45700 &(fc->scache_ptr[_FIELD_SCACHE_PART_0]), 45701 &alloc_get)); 45702 if (!SOC_WARM_BOOT(unit)) { 45703 /* Not yet allocated in Cold Boot */ 45704 SOC_IF_ERROR_RETURN 45705 (soc_scache_realloc(unit, handle, 45706 (fc->scache_size[_FIELD_SCACHE_PART_0] 45707 - (alloc_get - SOC_WB_SCACHE_CONTROL_SIZE)))); 45708 rv = soc_scache_ptr_get(unit, handle, 45709 &(fc->scache_ptr[_FIELD_SCACHE_PART_0]), 45710 &alloc_get); 45711 } 45712 45713 if (BCM_FAILURE(rv)) { 45714 return rv; 45715 } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_0] + 45716 SOC_WB_SCACHE_CONTROL_SIZE) { 45717 /* Expected size doesn't match retrieved size */ 45718 /* Scache size is increased by 16*1024 bytes 45719 * from version BCM_FIELD_WB_VERSION_1_6.The below check is 45720 * for upgrades from lower versions to BCM_FIELD_WB_VERSION_1_6 45721 * and above. 45722 * Scache size increased by 128 bytes from BCM_FIELD_WB_VERSION_1_8. 45723 * with respect to BCM_FIELD_WB_VERSION_1_6 45724 */ 45725 rv = _field_scache_version_size_check(unit, alloc_get, 45726 (fc->wb_recovered_version), 45727 fc->scache_size[_FIELD_SCACHE_PART_0] + 45728 SOC_WB_SCACHE_CONTROL_SIZE, 45729 (fc->wb_current_version)); 45730 if (rv != TRUE) { 45731 return BCM_E_INTERNAL; 45732 } 45733 } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_0]) { 45734 return BCM_E_MEMORY; 45735 } 45736 45737 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 1); 45738 SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_FIELD, 1); 45739 45740 /* Get the pointer for the Level 2 cache */ 45741 SOC_IF_ERROR_RETURN(soc_scache_ptr_get(unit, handle, 45742 &(fc->scache_ptr[_FIELD_SCACHE_PART_1]), 45743 &alloc_get)); 45744 if (!SOC_WARM_BOOT(unit)) { 45745 /*Allocated in Cold Boot */ 45746 SOC_IF_ERROR_RETURN 45747 (soc_scache_realloc(unit, handle, 45748 (fc->scache_size[_FIELD_SCACHE_PART_1] 45749 - (alloc_get - SOC_WB_SCACHE_CONTROL_SIZE)))); 45750 rv = (soc_scache_ptr_get(unit, handle, 45751 &(fc->scache_ptr[_FIELD_SCACHE_PART_1]), 45752 &alloc_get)); 45753 } 45754 45755 if (BCM_FAILURE(rv)) { 45756 return rv; 45757 } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_1] + 45758 SOC_WB_SCACHE_CONTROL_SIZE) { 45759 /* Expected size doesn't match retrieved size */ 45760 return BCM_E_INTERNAL; 45761 } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_1]) { 45762 return BCM_E_MEMORY; 45763 } 45764 45765 } 45766 } 45767 return rv; 45768 } 45769 45770 45771 /* 45772 * Function: _bcm_field_wb_downgrade_config_set 45773 * 45774 * Purpose: 45775 * Field Downgrade Configuration Set 45776 * 45777 * Parameters: 45778 * unit - BCM device number 45779 * warmboot_ver - WarmBoot Version for SDK 45780 * 45781 * Returns: 45782 * BCM_E_XXX. 45783 */ 45784 45785 int 45786 _bcm_field_wb_downgrade_config_set(int unit, uint32 warmboot_ver) { 45787 45788 int pos = 0; 45789 _field_control_t *fc; 45790 int rv = BCM_E_NONE; 45791 uint32 prev_version; 45792 45793 45794 FP_LOCK(unit); 45795 45796 rv = _field_control_get(unit, &fc); 45797 45798 if (BCM_FAILURE(rv)) { 45799 FP_UNLOCK(unit); 45800 return rv; 45801 } 45802 45803 prev_version = fc->wb_current_version; 45804 45805 for (pos = 0; pos < COUNTOF(_field_sdk_warmboot_version); pos++) { 45806 if (_field_sdk_warmboot_version[pos][0] == warmboot_ver) { 45807 if (fc->wb_current_version != _field_sdk_warmboot_version[pos][1]) { 45808 fc->wb_current_version = _field_sdk_warmboot_version[pos][1]; 45809 break; 45810 } else { 45811 FP_UNLOCK(unit); 45812 return BCM_E_NONE; 45813 } 45814 } else if ((pos > 0) && 45815 (_field_sdk_warmboot_version[pos][0] > warmboot_ver) && 45816 (_field_sdk_warmboot_version[pos - 1][0] < warmboot_ver)) { 45817 /* As _field_sdk_warmboot_version database will be updated only when a 45818 * WB change in present in a version. So this database structure will not have 45819 * all the version number. When a requested version number is in between 2 45820 * valid versions, use the previous version number. */ 45821 pos--; 45822 if (fc->wb_current_version != _field_sdk_warmboot_version[pos][1]) { 45823 fc->wb_current_version = _field_sdk_warmboot_version[pos][1]; 45824 break; 45825 } else { 45826 FP_UNLOCK(unit); 45827 return BCM_E_NONE; 45828 } 45829 } 45830 } 45831 45832 if (pos == COUNTOF(_field_sdk_warmboot_version)) { 45833 if (_field_sdk_warmboot_version[pos - 1][0] < warmboot_ver) { 45834 /* Upgrade case or like to like case */ 45835 if (fc->wb_current_version != _field_sdk_warmboot_version[pos -1][1]) { 45836 fc->wb_current_version = _field_sdk_warmboot_version[pos - 1][1]; 45837 } else { 45838 FP_UNLOCK(unit); 45839 return BCM_E_NONE; 45840 } 45841 } else { 45842 LOG_DEBUG(BSL_LS_BCM_FP, 45843 (BSL_META_U(unit, 45844 "Version invalid for Warmboot Downgrade\n"))); 45845 FP_UNLOCK(unit); 45846 return BCM_E_PARAM; 45847 } 45848 } 45849 45850 LOG_DEBUG(BSL_LS_BCM_FP, 45851 (BSL_META_U(unit, "FP(unit %d) Current WB version [0x%x]\n"), 45852 unit, fc->wb_current_version)); 45853 45854 #ifdef BCM_TOMAHAWK_SUPPORT 45855 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 45856 rv = (_bcm_field_scache_th_pointer_realloc(unit, fc)); 45857 } else 45858 #endif 45859 { 45860 rv = (_field_scache_pointer_realloc(unit, fc)); 45861 } 45862 45863 if (BCM_FAILURE(rv)) { 45864 /* In case of failure, reallocate based on 45865 * previous version number */ 45866 fc->wb_current_version = prev_version; 45867 #ifdef BCM_TOMAHAWK_SUPPORT 45868 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 45869 _bcm_field_scache_th_pointer_realloc(unit, fc); 45870 } else 45871 #endif 45872 { 45873 _field_scache_pointer_realloc(unit, fc); 45874 } 45875 } 45876 45877 FP_UNLOCK(unit); 45878 return rv; 45879 } 45880 45881 #endif /* BCM_WARM_BOOT_SUPPORT */ 45882 45883 45884 /* 45885 * Function: _bcm_esw_field_init 45886 * 45887 * Purpose: 45888 * Initialize field module. 45889 * 45890 * Parameters: 45891 * unit - (IN) BCM device number 45892 * 45893 * Returns: 45894 * BCM_E_UNIT - Invalid BCM unit number. 45895 * BCM_E_UNAVAIL - Field Processor not on device. 45896 * BCM_E_MEMORY - Allocation failure 45897 * BCM_E_XXX - Error code from bcm_XX_field_init() 45898 * BCM_E_NONE - Success 45899 */ 45900 int 45901 _bcm_esw_field_init(int unit) 45902 { 45903 int udf_idx; /* Iteration index. */ 45904 int rv; /* Operation return value. */ 45905 int size; /* Allocation size. */ 45906 _field_control_t *fc = NULL; /* Field control structure. */ 45907 #ifdef BCM_WARM_BOOT_SUPPORT 45908 _field_stage_id_t stage_id; 45909 _field_stage_t *stage_fc = NULL; 45910 #endif /* BCM_WARM_BOOT_SUPPORT */ 45911 #if defined(BCM_TOMAHAWK_SUPPORT) 45912 int pool = -1; 45913 #endif 45914 _field_egr_ports_recovery_t *f_egr_recovery = NULL; 45915 int pipe = -1; 45916 #if defined(BCM_TRX_SUPPORT) 45917 int entry_words; /* Redirection profile entry size. */ 45918 soc_mem_t mem; /* SOC Memory name variable. */ 45919 #endif 45920 45921 /* Make sure the Unit can support this module. */ 45922 if (SOC_IS_SHADOW(unit) || !soc_feature(unit, soc_feature_field)) { 45923 LOG_ERROR(BSL_LS_BCM_FP, 45924 (BSL_META_U(unit, 45925 "FP(unit %d) Error: No Field Processor available \n"), 45926 unit)); 45927 return (BCM_E_UNAVAIL); 45928 } 45929 45930 /* Detatch first if it's been previously initialized. */ 45931 if (_field_control[unit] != NULL) { 45932 if (SOC_WARM_BOOT(unit)) { 45933 /* Clear Sticky ExactMatch stage flag */ 45934 _field_control[unit]->flags &= ~_FP_EXACTMATCH_STAGE_SKIP_DETACH; 45935 } 45936 _field_control[unit]->init = FALSE; 45937 rv = bcm_esw_field_detach(unit); 45938 if (BCM_FAILURE(rv)) { 45939 LOG_ERROR(BSL_LS_BCM_FP, 45940 (BSL_META_U(unit, 45941 "FP(unit %d) Error: Module deinit failed.\n"), 45942 unit)); 45943 return (rv); 45944 } 45945 } 45946 45947 fc = _field_control[unit]; 45948 /* Allocate a bcm_field_control */ 45949 if (NULL == fc) { 45950 _FP_XGS3_ALLOC(fc, sizeof (_field_control_t), "field_control"); 45951 } 45952 if (NULL == fc) { 45953 return (BCM_E_MEMORY); 45954 } 45955 45956 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 45957 /* Allocate a _field_egr_ports_recovery_t */ 45958 _FP_XGS3_ALLOC(f_egr_recovery, 45959 sizeof (_field_egr_ports_recovery_t), 45960 "field_egr_ports_recovery"); 45961 if (NULL == f_egr_recovery) { 45962 _field_control_free(unit, fc); 45963 return (BCM_E_MEMORY); 45964 } 45965 45966 /* Allocate a _field_entry_egr_ports_recovery_t */ 45967 _FP_XGS3_ALLOC(f_egr_recovery->entry_recover_egr_ports, 45968 (sizeof (_field_entry_recover_egr_ports_t *) * SOC_MAX_NUM_PORTS), 45969 "field_entry_egr_ports_recovery"); 45970 45971 if (NULL == f_egr_recovery->entry_recover_egr_ports) { 45972 _field_egr_ports_recovery_control_free (unit, f_egr_recovery); 45973 _field_control_free(unit, fc); 45974 return (BCM_E_MEMORY); 45975 } 45976 45977 _field_egr_ports_recovery[unit] = f_egr_recovery; 45978 45979 /* Initialize _field_egr_ports_recovery*/ 45980 sal_memset (_field_egr_ports_recovery_lock, 0, 45981 sizeof (_field_egr_ports_recovery_lock)); 45982 } 45983 45984 #if defined (BCM_TRIUMPH3_SUPPORT) 45985 if(SOC_IS_TRIUMPH3(unit)) { 45986 fc->_fp_egr_ifp_mod_fields_size = soc_mem_index_count(unit,EGR_IFP_MOD_FIELDSm); 45987 size = SHR_BITALLOCSIZE(fc->_fp_egr_ifp_mod_fields_size); 45988 fc->field_action_l2mod_index_bmp.w = NULL; 45989 _FP_XGS3_ALLOC(fc->field_action_l2mod_index_bmp.w, 45990 size, "L2ModIndexSize Bitmap"); 45991 if (NULL == fc->field_action_l2mod_index_bmp.w) { 45992 _field_control_free(unit, fc); 45993 return (BCM_E_MEMORY); 45994 } 45995 } 45996 #endif 45997 45998 /* First check if external FP is present. */ 45999 46000 #if defined(BCM_TRIUMPH_SUPPORT) 46001 if (soc_feature(unit, soc_feature_esm_support)) { 46002 if (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) { 46003 if ((SOC_MEM_IS_VALID(unit, EXT_FP_CNTRm)) && 46004 (soc_mem_index_count(unit, EXT_FP_CNTRm)) 46005 ) { 46006 fc->flags |= _FP_EXTERNAL_PRESENT; 46007 } 46008 } 46009 } 46010 #endif /* BCM_TRIUMPH_SUPPORT */ 46011 46012 #ifdef BCM_TRIUMPH3_SUPPORT 46013 if (SOC_IS_TRIUMPH3(unit) && _bcm_field_tr3_external_present(unit)) { 46014 fc->flags |= _FP_EXTERNAL_PRESENT; 46015 } 46016 #endif 46017 46018 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 46019 if (SOC_IS_TRX(unit) || SOC_IS_BRADLEY(unit)) { 46020 /* 46021 * Note: 46022 * Enable field stat sync with hardware 46023 * for bcm_field_stat_get()/_getxx() apis. 46024 */ 46025 fc->flags |= _FP_STAT_SYNC_ENABLE; 46026 } 46027 #endif 46028 46029 /*Set field control- Color Independent to TRUE which implies - 46030 *Packet Redirect and L3SW_CHANGE_L2 field actions are applicable 46031 *to all packets(Green/Yellow/Red)*/ 46032 fc->flags |= _FP_COLOR_INDEPENDENT; 46033 46034 /* Allocate Hints lookup hash. */ 46035 _FP_XGS3_ALLOC(fc->hints_hash, _FP_HASH_SZ(fc) * \ 46036 sizeof(_field_hints_t *), "Hints hash"); 46037 if (NULL == fc->hints_hash) { 46038 _field_control_free(unit, fc); 46039 return (BCM_E_MEMORY); 46040 } 46041 size = SHR_BITALLOCSIZE(_FP_HINT_ID_MAX); 46042 46043 _FP_XGS3_ALLOC(fc->hintid_bmp.w, size, "HintIds Bitmap"); 46044 if (NULL == fc->hintid_bmp.w) { 46045 _field_control_free(unit, fc); 46046 return (BCM_E_MEMORY); 46047 } 46048 46049 /* Allocate policer lookup hash. */ 46050 _FP_XGS3_ALLOC(fc->policer_hash, _FP_HASH_SZ(fc) * \ 46051 sizeof(_field_policer_t *), "Policer hash"); 46052 if (NULL == fc->policer_hash) { 46053 _field_control_free(unit, fc); 46054 return (BCM_E_MEMORY); 46055 } 46056 46057 /* Allocate statistics collection lookup hash. */ 46058 _FP_XGS3_ALLOC(fc->stat_hash, _FP_HASH_SZ(fc) * \ 46059 sizeof(_field_stat_t *), "Stat hash"); 46060 if (NULL == fc->stat_hash) { 46061 _field_control_free(unit, fc); 46062 return (BCM_E_MEMORY); 46063 } 46064 46065 /* Initialize Pipe map or valid pipes on a device */ 46066 fc->pipe_map = 0; 46067 #ifdef BCM_TOMAHAWK3_SUPPORT 46068 if (soc_feature(unit, soc_feature_th3_style_fp)) { 46069 /* fetch active pipes */ 46070 soc_tomahawk3_pipe_map_get(unit, &(fc->pipe_map)); 46071 } else 46072 #endif 46073 { 46074 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 46075 fc->pipe_map |= (1 << pipe); 46076 } 46077 } 46078 46079 #ifdef BCM_TOMAHAWK_SUPPORT 46080 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 46081 for (pipe = 0; pipe < _FP_MAX_NUM_PIPES; pipe++) { 46082 for (pool = 0; pool < _FIELD_MAX_METER_POOLS; pool++) { 46083 fc->ifp_em_meter_in_use[pipe][pool] 46084 = BCM_FIELD_METER_POOL_USED_BY_NONE; 46085 } 46086 } 46087 } 46088 #endif 46089 46090 #ifdef BCM_TOMAHAWK_SUPPORT 46091 if (soc_feature(unit, soc_feature_field_preselector_support)) { 46092 /* Allocate memory for preselector lookup database. */ 46093 _FP_XGS3_ALLOC(fc->presel_db, BCM_FIELD_PRESEL_SEL_MAX * \ 46094 sizeof(_field_presel_entry_t *), "Presel db"); 46095 if (NULL == fc->presel_db) { 46096 _field_control_free(unit, fc); 46097 return (BCM_E_MEMORY); 46098 } 46099 46100 /* Allocate preselector information structure. */ 46101 _FP_XGS3_ALLOC(fc->presel_info, sizeof(_field_presel_info_t), 46102 "Field Control Presel Info Alloc."); 46103 if (NULL == fc->presel_info) { 46104 _field_control_free(unit, fc); 46105 return (BCM_E_MEMORY); 46106 } 46107 46108 /* Update the Preselector Max Limit */ 46109 fc->presel_info->presel_limit = _BCM_FIELD_PRESEL_ID_MAX; 46110 } 46111 46112 /* Initialize field control lt table structures. */ 46113 rv = _field_th_lt_config_init(unit, fc); 46114 if (BCM_FAILURE(rv)) { 46115 _field_control_free(unit, fc); 46116 return rv; 46117 } 46118 #endif 46119 46120 /* Allocate user defined qualifiers. */ 46121 _FP_XGS3_ALLOC(fc->udf, BCM_FIELD_USER_NUM_UDFS * \ 46122 sizeof(_field_udf_t), "Udf table"); 46123 if (NULL == fc->udf) { 46124 _field_control_free(unit, fc); 46125 return (BCM_E_MEMORY); 46126 } 46127 46128 /* Initialize pipeline stages field control structures. */ 46129 rv = _field_stages_init(unit, fc); 46130 if (BCM_FAILURE(rv)) { 46131 _field_control_free(unit, fc); 46132 return rv; 46133 } 46134 46135 /* Initialize fp status structure. */ 46136 fc->stage = bcmFieldStageDefault; 46137 46138 #ifdef BCM_WARM_BOOT_SUPPORT 46139 /* Inititalize WB default/Recovered Version */ 46140 fc->wb_current_version = BCM_FIELD_WB_DEFAULT_VERSION; 46141 fc->wb_recovered_version = 0; 46142 #endif 46143 46144 if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 46145 fc->flags |= _FP_INTRASLICE_ENABLE; 46146 } 46147 46148 /* Assign the virtual UDFs to the underlying H/W */ 46149 for (udf_idx = 0; udf_idx < BCM_FIELD_USER_NUM_UDFS; udf_idx++) { 46150 fc->udf[udf_idx].udf_num = udf_idx >> 2; 46151 fc->udf[udf_idx].user_num = udf_idx & 0x03; 46152 } 46153 46154 #if defined (BCM_TRX_SUPPORT) 46155 /* Initialize global Redirect action memory profile. */ 46156 soc_profile_mem_t_init(&fc->redirect_profile); 46157 46158 #if defined (BCM_TOMAHAWK3_SUPPORT) 46159 /* Initialize global Redirect action memory profile. */ 46160 soc_profile_mem_t_init(&fc->redirect_profile1); 46161 /* Initialize Delayed drop action memory profile. */ 46162 soc_profile_mem_t_init(&fc->ddrop_profile); 46163 /* Initialize Delayed Redirect action memory profile. */ 46164 soc_profile_mem_t_init(&fc->dredirect_profile); 46165 #endif 46166 46167 #if defined (BCM_TOMAHAWK_SUPPORT) 46168 /* Redirect HiGiG2 extended header mask profile initialization. */ 46169 if (soc_feature(unit, soc_feature_higig_lookup) && SOC_IS_TOMAHAWKX(unit)) 46170 { 46171 soc_profile_mem_t_init(&fc->eh_mask_profile); 46172 } 46173 #endif 46174 46175 /* Assign redirection profile memory name "mem" variable. */ 46176 if (soc_feature(unit, soc_feature_th3_style_fp)) { 46177 mem = IFP_OR_REDIRECTION_PROFILEm; 46178 } else { 46179 mem = IFP_REDIRECTION_PROFILEm; 46180 } 46181 46182 /* Determine redirection profile entry size in number of words. */ 46183 entry_words = sizeof(ifp_redirection_profile_entry_t) / sizeof(uint32); 46184 46185 if (SOC_MEM_IS_VALID(unit, mem)) { 46186 /* Create the redirection profile table. */ 46187 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 46188 &fc->redirect_profile); 46189 if (BCM_FAILURE(rv)) { 46190 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 46191 "FP(unit %d) Error: Redirection profile creation failed.=%d\n"), 46192 unit, rv)); 46193 return (rv); 46194 } 46195 } 46196 46197 #if defined (BCM_TOMAHAWK3_SUPPORT) 46198 if (soc_feature(unit, soc_feature_th3_style_fp)) { 46199 mem = IFP_AND_REDIRECTION_PROFILEm; 46200 /* Determine redirection profile entry size in number of words. */ 46201 entry_words = sizeof(ifp_redirection_profile_entry_t) / sizeof(uint32); 46202 46203 /* Create the redirection profile table. */ 46204 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 46205 &fc->redirect_profile1); 46206 if (BCM_FAILURE(rv)) { 46207 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 46208 "FP(unit %d) Error: Redirection profile creation failed.=%d\n"), 46209 unit, rv)); 46210 return (rv); 46211 } 46212 46213 mem = IFP_EGRESS_PORT_CHECK_FOR_DROPm; 46214 /* Determine redirection profile entry size in number of words. */ 46215 entry_words = sizeof(ifp_egress_port_check_for_drop_entry_t) / sizeof(uint32); 46216 46217 /* Create the redirection profile table. */ 46218 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 46219 &fc->ddrop_profile); 46220 if (BCM_FAILURE(rv)) { 46221 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 46222 "FP(unit %d) Error: Action Drop profile creation failed.=%d\n"), 46223 unit, rv)); 46224 return (rv); 46225 } 46226 46227 mem = IFP_EGRESS_PORT_CHECK_FOR_REDIRECTm; 46228 /* Determine redirection profile entry size in number of words. */ 46229 entry_words = sizeof(ifp_egress_port_check_for_redirect_entry_t) / sizeof(uint32); 46230 46231 /* Create the redirection profile table. */ 46232 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 46233 &fc->dredirect_profile); 46234 if (BCM_FAILURE(rv)) { 46235 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 46236 "FP(unit %d) Error: Action Redirect profile creation failed.=%d\n"), 46237 unit, rv)); 46238 return (rv); 46239 } 46240 46241 } 46242 #endif 46243 #if defined (BCM_TOMAHAWK_SUPPORT) 46244 if (soc_feature(unit, soc_feature_higig_lookup) && SOC_IS_TOMAHAWKX(unit)) { 46245 /* Assign HiGiG2 extended header mask memory name "mem" variable. */ 46246 mem = EH_MASK_PROFILEm; 46247 46248 /* Determine HiGiG2 extended header mask profile entry size 46249 * in number of words. */ 46250 entry_words = sizeof(eh_mask_profile_entry_t) / sizeof(uint32); 46251 46252 /* Create the HiGiG2 extended header mask profile table. */ 46253 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 46254 &fc->eh_mask_profile); 46255 if (BCM_FAILURE(rv)) { 46256 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 46257 "FP(unit %d) Error: HiGiG2 EH mask profile creation failed.=%d\n"), 46258 unit, rv)); 46259 return (rv); 46260 } 46261 } 46262 #endif 46263 #endif 46264 46265 #if defined(BCM_RAPTOR_SUPPORT) 46266 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) { 46267 rv = _bcm_field_raptor_init(unit, fc); 46268 } else 46269 #endif /* BCM_RAPTOR_SUPPORT */ 46270 46271 #if defined(BCM_TRIUMPH_SUPPORT) 46272 if (SOC_IS_TR_VL(unit)) { 46273 #if defined(BCM_TOMAHAWK_SUPPORT) 46274 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 46275 rv = _bcm_field_th_init(unit, fc); 46276 } else 46277 #endif /*BCM_TOMAHAWK_SUPPORT */ 46278 #if defined(BCM_TRIDENT2_SUPPORT) 46279 if (SOC_IS_TD2_TT2(unit)) { 46280 rv = _bcm_field_td2_init(unit, fc); 46281 } else 46282 #endif /*BCM_TRIDENT2_SUPPORT */ 46283 #if defined(BCM_TRIUMPH3_SUPPORT) 46284 if (SOC_IS_TRIUMPH3(unit)) { 46285 rv = _bcm_field_tr3_init(unit, fc); 46286 } else 46287 #endif /* BCM_TRIUMPH3_SUPPORT */ 46288 #if defined(BCM_TRIDENT_SUPPORT) 46289 if (SOC_IS_TD_TT(unit)) { 46290 rv = _bcm_field_trident_init(unit, fc); 46291 } else 46292 #endif /* BCM_TRIDENT_SUPPORT */ 46293 #if defined(BCM_TRIUMPH2_SUPPORT) 46294 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 46295 SOC_IS_VALKYRIE2(unit)) { 46296 rv = _bcm_field_tr2_init(unit, fc); 46297 } else 46298 #endif /* BCM_TRIUMPH2_SUPPORT */ 46299 #if defined(BCM_ENDURO_SUPPORT) 46300 if (SOC_IS_ENDURO(unit)) { 46301 rv = _bcm_field_en_init(unit, fc); 46302 } else 46303 #endif /* BCM_ENDURO_SUPPORT */ 46304 #if defined(BCM_HURRICANE1_SUPPORT) 46305 if (SOC_IS_HURRICANE(unit)) { 46306 rv = _bcm_field_hu_init(unit, fc); 46307 } else 46308 #endif /* BCM_HURRICANE1_SUPPORT */ 46309 #if defined(BCM_HURRICANE2_SUPPORT) 46310 if (SOC_IS_HURRICANE2(unit)) { 46311 rv = _bcm_field_hu2_init(unit,fc); 46312 } else 46313 #endif /* BCM_HURRICANE_SUPPORT */ 46314 #if defined(BCM_KATANA_SUPPORT) 46315 if (SOC_IS_KATANA(unit)) { 46316 rv = _bcm_field_katana_init(unit, fc); 46317 } else 46318 #endif /* BCM_KATANA_SUPPORT */ 46319 #if defined(BCM_KATANA2_SUPPORT) 46320 if (SOC_IS_KATANA2(unit)) { 46321 rv = _bcm_field_kt2_init(unit, fc); 46322 } else 46323 #endif /* BCM_KATANA_SUPPORT */ 46324 #if defined(BCM_GREYHOUND_SUPPORT) 46325 if (SOC_IS_GREYHOUND(unit)) { 46326 rv = _bcm_field_gh_init(unit,fc); 46327 } else 46328 #endif /* BCM_GREYHOUND_SUPPORT */ 46329 #if defined(BCM_HURRICANE3_SUPPORT) 46330 if (SOC_IS_HURRICANE3(unit)) { 46331 rv = _bcm_field_hr3_init(unit,fc); 46332 } else 46333 #endif /* BCM_HURRICANE3_SUPPORT */ 46334 #if defined(BCM_GREYHOUND2_SUPPORT) 46335 if (SOC_IS_GREYHOUND2(unit)) { 46336 rv = _bcm_field_gh2_init(unit,fc); 46337 } else 46338 #endif /* BCM_GREYHOUND2_SUPPORT */ 46339 46340 { 46341 rv = _bcm_field_tr_init(unit, fc); 46342 } 46343 } else 46344 #endif /* BCM_TRIUMPH_SUPPORT */ 46345 46346 #if defined(BCM_SCORPION_SUPPORT) 46347 if (SOC_IS_SC_CQ(unit)) { 46348 rv = _bcm_field_sc_init(unit, fc); 46349 } else 46350 #endif /* BCM_TRIUMPH_SUPPORT */ 46351 46352 #ifdef BCM_FIREBOLT_SUPPORT 46353 if (SOC_IS_FBX(unit)) { 46354 rv = _bcm_field_fb_init(unit, fc); 46355 } 46356 #endif /* BCM_FIREBOLT_SUPPORT */ 46357 46358 46359 /* cleanup on device specific init failure. */ 46360 if (BCM_FAILURE(rv)) { 46361 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 46362 /* Destroy all CAP stages and its FP instances. */ 46363 fc->stage_func.fp_stages_delete(unit, fc); 46364 } else { 46365 _field_stages_destroy(unit, fc); 46366 } 46367 _field_control_free(unit, fc); 46368 return rv; 46369 } 46370 46371 /* Initialize supported qset for each stage. */ 46372 _bcm_field_stages_supported_qset_init(unit, fc); 46373 46374 fc->last_allocated_eid = 0; 46375 _field_control[unit] = fc; 46376 46377 /* Register counter collection callback. */ 46378 BCM_IF_ERROR_RETURN(soc_counter_extra_register(unit, 46379 _bcm_esw_fp_counters_collect)); 46380 46381 #ifdef BCM_WARM_BOOT_SUPPORT 46382 #ifdef BCM_TOMAHAWK_SUPPORT 46383 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 46384 BCM_IF_ERROR_RETURN(_bcm_field_scache_th_pointer_init(unit, fc)); 46385 } else 46386 #endif 46387 { 46388 BCM_IF_ERROR_RETURN(_field_scache_pointer_init(unit, fc)); 46389 } 46390 /* Construct the _field_stage_t structure based on HW programming 46391 * in Warm Boot mode */ 46392 if (SOC_WARM_BOOT(unit)) { 46393 fc->l2warm = (fc->scache_size[_FIELD_SCACHE_PART_0] && 46394 !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) ? 1 : 0; 46395 46396 if (SOC_IS_FIREBOLT(unit) || SOC_IS_HB_GW(unit)) { 46397 stage_id = _BCM_FIELD_STAGE_INGRESS; 46398 46399 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, 46400 &stage_fc)); 46401 46402 rv = _field_fb_stage_reinit(unit, fc, stage_fc); 46403 if ((rv == BCM_E_INTERNAL) && 46404 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46405 (fc->l2warm == 0)) { 46406 /* Stale scache */ 46407 SOC_IF_ERROR_RETURN 46408 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 46409 SOC_STABLE_STALE, SOC_STABLE_FIELD, 0)); 46410 /* Clean up generated state and restart as Level 1 */ 46411 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46412 rv = _field_fb_stage_reinit(unit, fc, stage_fc); 46413 } 46414 } else if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) { 46415 #ifdef BCM_RAVEN_SUPPORT 46416 stage_id = _BCM_FIELD_STAGE_INGRESS; 46417 BCM_IF_ERROR_RETURN 46418 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46419 rv = _field_raven_stage_reinit(unit, fc, stage_fc); 46420 if ((rv == BCM_E_INTERNAL) && 46421 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46422 (fc->l2warm == 0)) { 46423 /* Stale scache */ 46424 SOC_IF_ERROR_RETURN 46425 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 46426 SOC_STABLE_STALE, SOC_STABLE_FIELD, 0)); 46427 /* Clean up generated state and restart as Level 1 */ 46428 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46429 rv = _field_raven_stage_reinit(unit, fc, stage_fc); 46430 } 46431 #endif 46432 } else if (SOC_IS_FIREBOLT2(unit)) { 46433 #ifdef BCM_FIREBOLT2_SUPPORT 46434 uint8 oldl2warm = 0; 46435 stage_id = _BCM_FIELD_STAGE_INGRESS; 46436 BCM_IF_ERROR_RETURN 46437 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46438 rv = _field_fb2_stage_ingress_reinit(unit, fc, stage_fc); 46439 if ((rv == BCM_E_INTERNAL) && 46440 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46441 (fc->l2warm == 0)) { 46442 /* Stale scache in ingress section */ 46443 SOC_IF_ERROR_RETURN 46444 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 46445 SOC_STABLE_STALE, SOC_STABLE_FIELD, 0)); 46446 /* Clean up generated state and restart as Level 1 */ 46447 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46448 rv = _field_fb2_stage_ingress_reinit(unit, fc, stage_fc); 46449 } 46450 if (BCM_SUCCESS(rv)) { 46451 stage_id = _BCM_FIELD_STAGE_EGRESS; 46452 BCM_IF_ERROR_RETURN 46453 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46454 oldl2warm = fc->l2warm; 46455 rv = _field_fb2_stage_egress_reinit(unit, fc, stage_fc); 46456 if ((rv == BCM_E_INTERNAL) && 46457 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46458 (fc->l2warm == 0) && (oldl2warm != 0)) { 46459 /* Stale scache in egress section */ 46460 SOC_IF_ERROR_RETURN 46461 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 46462 SOC_STABLE_STALE, 46463 SOC_STABLE_FIELD, 0)); 46464 /* Clean up generated state and restart as Level 1 */ 46465 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46466 stage_id = _BCM_FIELD_STAGE_INGRESS; 46467 BCM_IF_ERROR_RETURN 46468 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46469 rv = _field_fb2_stage_ingress_reinit(unit, fc, stage_fc); 46470 if (BCM_SUCCESS(rv)) { 46471 stage_id = _BCM_FIELD_STAGE_EGRESS; 46472 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46473 stage_id, &stage_fc)); 46474 rv = _field_fb2_stage_egress_reinit(unit, fc, stage_fc); 46475 } 46476 } 46477 } 46478 if (BCM_SUCCESS(rv)) { 46479 stage_id = _BCM_FIELD_STAGE_LOOKUP; 46480 BCM_IF_ERROR_RETURN 46481 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46482 oldl2warm = fc->l2warm; 46483 rv = _field_fb2_stage_lookup_reinit(unit, fc, stage_fc); 46484 if ((rv == BCM_E_INTERNAL) && 46485 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46486 (fc->l2warm == 0) && (oldl2warm != 0)) { 46487 /* Stale scache in lookup section */ 46488 SOC_IF_ERROR_RETURN 46489 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 46490 SOC_STABLE_STALE, 46491 SOC_STABLE_FIELD, 0)); 46492 /* Clean up generated state and restart as Level 1 */ 46493 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46494 stage_id = _BCM_FIELD_STAGE_INGRESS; 46495 BCM_IF_ERROR_RETURN 46496 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46497 rv = _field_fb2_stage_ingress_reinit(unit, fc, stage_fc); 46498 if (BCM_SUCCESS(rv)) { 46499 stage_id = _BCM_FIELD_STAGE_EGRESS; 46500 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46501 stage_id, &stage_fc)); 46502 rv = _field_fb2_stage_egress_reinit(unit, fc, stage_fc); 46503 } 46504 if (BCM_SUCCESS(rv)) { 46505 stage_id = _BCM_FIELD_STAGE_LOOKUP; 46506 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46507 stage_id, &stage_fc)); 46508 rv = _field_fb2_stage_lookup_reinit(unit, fc, stage_fc); 46509 } 46510 } 46511 } 46512 #endif 46513 } else if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 46514 46515 #if defined(BCM_TOMAHAWK_SUPPORT) 46516 46517 uint8 oldl2warm = 0; 46518 rv = BCM_E_NONE; 46519 46520 /* Tomahawk supports only level-2 for Warmboot */ 46521 if (fc->l2warm) { 46522 do { 46523 stage_id = _BCM_FIELD_STAGE_INGRESS; 46524 BCM_IF_ERROR_RETURN 46525 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46526 46527 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_9) { 46528 rv = _bcm_field_th_stage_ingress_reinit(unit, fc, stage_fc); 46529 } else { 46530 /* To account for start marker */ 46531 fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE; 46532 /* To account for end marker */ 46533 fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE; 46534 } 46535 } while (0); 46536 do { 46537 if (BCM_SUCCESS(rv) && 46538 soc_feature(unit, soc_feature_field_multi_stage)) { 46539 stage_id = _BCM_FIELD_STAGE_EGRESS; 46540 46541 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46542 if (BCM_FAILURE(rv)) { 46543 _bcm_field_th_tlv_recovery_map_free(unit); 46544 return rv; 46545 } 46546 46547 oldl2warm = fc->l2warm; 46548 rv = _bcm_field_th_stage_egress_reinit(unit, fc, stage_fc); 46549 if ((rv == BCM_E_INTERNAL) && 46550 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46551 (fc->l2warm == 0) && (oldl2warm != 0)) { 46552 46553 _bcm_field_th_tlv_recovery_map_free(unit); 46554 46555 /* Stale scache in egress section */ 46556 SOC_IF_ERROR_RETURN 46557 (soc_event_generate(unit, 46558 SOC_SWITCH_EVENT_STABLE_ERROR, 46559 SOC_STABLE_STALE, 46560 SOC_STABLE_FIELD, 0)); 46561 /* Clean up generated state and restart as Level 1 */ 46562 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46563 } 46564 } 46565 46566 } while (0); 46567 46568 do { 46569 if (BCM_SUCCESS(rv) && 46570 soc_feature(unit, soc_feature_field_multi_stage)) { 46571 46572 stage_id = _BCM_FIELD_STAGE_LOOKUP; 46573 46574 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46575 if (BCM_FAILURE(rv)) { 46576 _bcm_field_th_tlv_recovery_map_free(unit); 46577 return rv; 46578 } 46579 46580 oldl2warm = fc->l2warm; 46581 46582 rv = _bcm_field_th_stage_lookup_reinit(unit, fc, stage_fc); 46583 46584 if ((rv == BCM_E_INTERNAL) && 46585 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46586 (fc->l2warm == 0) && (oldl2warm != 0)) { 46587 46588 _bcm_field_th_tlv_recovery_map_free(unit); 46589 46590 /* Stale scache in lookup section */ 46591 SOC_IF_ERROR_RETURN 46592 (soc_event_generate(unit, 46593 SOC_SWITCH_EVENT_STABLE_ERROR, 46594 SOC_STABLE_STALE, 46595 SOC_STABLE_FIELD, 0)); 46596 46597 /* Clean up generated state and restart as Level 1 */ 46598 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46599 } 46600 } 46601 } while(0); 46602 46603 do { 46604 if (BCM_SUCCESS(rv) && 46605 soc_feature(unit, soc_feature_field_compression)) { 46606 stage_id = _BCM_FIELD_STAGE_CLASS; 46607 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46608 if (BCM_FAILURE(rv)) { 46609 _bcm_field_th_tlv_recovery_map_free(unit); 46610 return rv; 46611 } 46612 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_10) { 46613 rv = _bcm_field_th_stage_class_reinit(unit, 46614 fc, stage_fc); 46615 } 46616 } 46617 } while(0); 46618 46619 do { 46620 if (BCM_SUCCESS(rv) && 46621 soc_feature(unit, soc_feature_field_exact_match_support)) { 46622 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 46623 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46624 if (BCM_FAILURE(rv)) { 46625 _bcm_field_th_tlv_recovery_map_free(unit); 46626 return rv; 46627 } 46628 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_10) { 46629 rv = _bcm_field_th_stage_em_reinit(unit, 46630 fc, stage_fc); 46631 } 46632 } 46633 } while(0); 46634 46635 #if defined(BCM_HELIX5_SUPPORT) 46636 do { 46637 if (BCM_SUCCESS(rv) && 46638 soc_feature(unit, soc_feature_field_flowtracker_support)) { 46639 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 46640 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46641 if (BCM_FAILURE(rv)) { 46642 _bcm_field_th_tlv_recovery_map_free(unit); 46643 return rv; 46644 } 46645 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_26) { 46646 rv = _bcm_field_stage_ft_reinit(unit, fc, stage_fc); 46647 } 46648 } 46649 } while(0); 46650 #endif 46651 46652 _bcm_field_th_tlv_recovery_map_free(unit); 46653 46654 } else { 46655 LOG_WARN(BSL_LS_BCM_FP, 46656 (BSL_META_U(unit, 46657 "Warning: Level-1 not supported for FP Warmboot\n"))); 46658 } 46659 #endif 46660 } else if (SOC_IS_TRIUMPH(unit) 46661 || SOC_IS_VALKYRIE(unit) 46662 || SOC_IS_ENDURO(unit) 46663 || SOC_IS_TRIUMPH2(unit) 46664 || SOC_IS_APOLLO(unit) 46665 || SOC_IS_VALKYRIE2(unit) 46666 || SOC_IS_SC_CQ(unit) || SOC_IS_HURRICANEX(unit) 46667 || SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) 46668 || SOC_IS_GREYHOUND(unit) 46669 || SOC_IS_GREYHOUND2(unit) 46670 ) { 46671 #if defined(BCM_TRX_SUPPORT) 46672 uint8 oldl2warm = 0; 46673 stage_id = _BCM_FIELD_STAGE_INGRESS; 46674 BCM_IF_ERROR_RETURN 46675 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46676 rv = _field_tr2_stage_ingress_reinit(unit, fc, stage_fc); 46677 if ((rv == BCM_E_INTERNAL) && 46678 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46679 (fc->l2warm == 0)) { 46680 /* Stale scache in ingress section */ 46681 SOC_IF_ERROR_RETURN 46682 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 46683 SOC_STABLE_STALE, SOC_STABLE_FIELD, 0)); 46684 /* Clean up generated state and restart as Level 1 */ 46685 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46686 rv = _field_tr2_stage_ingress_reinit(unit, fc, stage_fc); 46687 } 46688 do { 46689 if (BCM_SUCCESS(rv)) { 46690 stage_id = _BCM_FIELD_STAGE_EGRESS; 46691 46692 #if defined(BCM_HURRICANE1_SUPPORT) 46693 /* Egress Stage might not be available for some devices 46694 (hurricane) */ 46695 if (SOC_IS_HURRICANE(unit) || 46696 (!soc_feature(unit, soc_feature_field_multi_stage))) { 46697 LOG_VERBOSE(BSL_LS_BCM_FP, 46698 (BSL_META_U(unit, 46699 "\t#Skipping Egress Stage(NotAvailable)\n"))); 46700 rv = BCM_E_NONE; 46701 break; 46702 } 46703 #endif /* BCM_HURRICANE1_SUPPORT */ 46704 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46705 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) { 46706 /* Cannot return as LOOKUP+External Stages need to be 46707 checked yet */ 46708 rv = BCM_E_NONE; 46709 break; 46710 } 46711 BCM_IF_ERROR_RETURN(rv); 46712 oldl2warm = fc->l2warm; 46713 rv = _field_tr2_stage_egress_reinit(unit, fc, stage_fc); 46714 if ((rv == BCM_E_INTERNAL) && 46715 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46716 (fc->l2warm == 0) && (oldl2warm != 0)) { 46717 /* Stale scache in egress section */ 46718 SOC_IF_ERROR_RETURN 46719 (soc_event_generate(unit, 46720 SOC_SWITCH_EVENT_STABLE_ERROR, 46721 SOC_STABLE_STALE, 46722 SOC_STABLE_FIELD, 0)); 46723 /* Clean up generated state and restart as Level 1 */ 46724 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46725 stage_id = _BCM_FIELD_STAGE_INGRESS; 46726 BCM_IF_ERROR_RETURN 46727 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46728 rv = _field_tr2_stage_ingress_reinit(unit, fc, 46729 stage_fc); 46730 if (BCM_SUCCESS(rv)) { 46731 stage_id = _BCM_FIELD_STAGE_EGRESS; 46732 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46733 stage_id, &stage_fc)); 46734 rv = _field_tr2_stage_egress_reinit(unit, fc, 46735 stage_fc); 46736 } 46737 } 46738 } 46739 } while (0); 46740 do { 46741 if (BCM_SUCCESS(rv)) { 46742 stage_id = _BCM_FIELD_STAGE_LOOKUP; 46743 #if defined(BCM_HURRICANE1_SUPPORT) 46744 if (SOC_IS_HURRICANE(unit) || 46745 (!soc_feature(unit, soc_feature_field_multi_stage))) { 46746 LOG_VERBOSE(BSL_LS_BCM_FP, 46747 (BSL_META_U(unit, 46748 "\t#Skipping Lookup Stage(NotAvailable)\n"))); 46749 rv = BCM_E_NONE; 46750 break; 46751 } 46752 #endif /* BCM_HURRICANE1_SUPPORT */ 46753 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46754 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) { 46755 /* Cannot return as External Stages need to be checked*/ 46756 rv = BCM_E_NONE; 46757 break; 46758 } 46759 BCM_IF_ERROR_RETURN(rv); 46760 oldl2warm = fc->l2warm; 46761 46762 #if defined(BCM_TRIDENT2_SUPPORT) 46763 if (SOC_IS_TD2_TT2(unit)) { 46764 rv = _bcm_field_td2_stage_lookup_reinit(unit, fc, stage_fc); 46765 } else 46766 #endif 46767 #if defined(BCM_KATANA2_SUPPORT) 46768 if (SOC_IS_KATANA2(unit)) { 46769 rv = _field_kt2_stage_lookup_reinit(unit, fc, stage_fc); 46770 } else 46771 #endif 46772 { 46773 rv = _field_tr2_stage_lookup_reinit(unit, fc, stage_fc); 46774 } 46775 46776 if ((rv == BCM_E_INTERNAL) && 46777 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46778 (fc->l2warm == 0) && (oldl2warm != 0)) { 46779 /* Stale scache in lookup section */ 46780 SOC_IF_ERROR_RETURN 46781 (soc_event_generate(unit, 46782 SOC_SWITCH_EVENT_STABLE_ERROR, 46783 SOC_STABLE_STALE, 46784 SOC_STABLE_FIELD, 0)); 46785 /* Clean up generated state and restart as Level 1 */ 46786 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46787 stage_id = _BCM_FIELD_STAGE_INGRESS; 46788 BCM_IF_ERROR_RETURN 46789 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46790 rv = _field_tr2_stage_ingress_reinit(unit, fc, stage_fc); 46791 if (BCM_SUCCESS(rv)) { 46792 stage_id = _BCM_FIELD_STAGE_EGRESS; 46793 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46794 stage_id, &stage_fc)); 46795 rv = _field_tr2_stage_egress_reinit(unit, fc, 46796 stage_fc); 46797 } 46798 if (BCM_SUCCESS(rv)) { 46799 stage_id = _BCM_FIELD_STAGE_LOOKUP; 46800 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46801 stage_id, &stage_fc)); 46802 #if defined(BCM_TRIDENT2_SUPPORT) 46803 if (SOC_IS_TD2_TT2(unit)) { 46804 rv = _bcm_field_td2_stage_lookup_reinit(unit, fc, stage_fc); 46805 } else 46806 #endif 46807 { 46808 rv = _field_tr2_stage_lookup_reinit(unit, fc, stage_fc); 46809 } 46810 } 46811 } 46812 } 46813 } while(0); 46814 do { 46815 if (BCM_SUCCESS(rv) && soc_feature(unit, soc_feature_esm_support)) { 46816 stage_id = _BCM_FIELD_STAGE_EXTERNAL; 46817 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46818 if (rv == BCM_E_UNAVAIL) { 46819 /* External stage supported but not configured => Skip it */ 46820 46821 rv = BCM_E_NONE; 46822 break; 46823 } 46824 BCM_IF_ERROR_RETURN(rv); 46825 46826 oldl2warm = fc->l2warm; 46827 rv = _field_tr2_stage_external_reinit(unit, fc, stage_fc); 46828 if ((rv == BCM_E_INTERNAL) && 46829 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 46830 (fc->l2warm == 0) && (oldl2warm != 0)) { 46831 /* Stale scache in lookup section */ 46832 SOC_IF_ERROR_RETURN 46833 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 46834 SOC_STABLE_STALE, 46835 SOC_STABLE_FIELD, 0)); 46836 /* Clean up generated state and restart as Level 1 */ 46837 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46838 stage_id = _BCM_FIELD_STAGE_INGRESS; 46839 BCM_IF_ERROR_RETURN 46840 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46841 rv = _field_tr2_stage_ingress_reinit(unit, fc, stage_fc); 46842 if (BCM_SUCCESS(rv)) { 46843 stage_id = _BCM_FIELD_STAGE_EGRESS; 46844 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46845 stage_id, &stage_fc)); 46846 rv = _field_tr2_stage_egress_reinit(unit, fc, stage_fc); 46847 } 46848 if (BCM_SUCCESS(rv)) { 46849 stage_id = _BCM_FIELD_STAGE_LOOKUP; 46850 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46851 stage_id, &stage_fc)); 46852 #if defined(BCM_TRIDENT2_SUPPORT) 46853 if (SOC_IS_TD2_TT2(unit)) { 46854 rv = _bcm_field_td2_stage_lookup_reinit(unit, fc, stage_fc); 46855 } else 46856 #endif 46857 { 46858 rv = _field_tr2_stage_lookup_reinit(unit, fc, stage_fc); 46859 } 46860 } 46861 if (BCM_SUCCESS(rv)) { 46862 stage_id = _BCM_FIELD_STAGE_EXTERNAL; 46863 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 46864 stage_id, &stage_fc)); 46865 rv = _field_tr2_stage_external_reinit(unit, fc, stage_fc); 46866 } 46867 } 46868 } 46869 }while(0); 46870 #endif /* BCM_TRX_SUPPORT */ 46871 } else if (SOC_IS_TRIUMPH3(unit)) { 46872 #if defined(BCM_TRIUMPH3_SUPPORT) 46873 uint8 oldl2warm = 0; 46874 stage_id = _BCM_FIELD_STAGE_INGRESS; 46875 BCM_IF_ERROR_RETURN 46876 (_field_stage_control_get(unit, stage_id, &stage_fc)); 46877 rv = _bcm_field_tr3_stage_ingress_reinit(unit, fc, stage_fc); 46878 if ((rv == BCM_E_INTERNAL) && 46879 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) 46880 && (fc->l2warm == 0)) { 46881 /* Stale scache in ingress section */ 46882 SOC_IF_ERROR_RETURN 46883 (soc_event_generate(unit, 46884 SOC_SWITCH_EVENT_STABLE_ERROR, 46885 SOC_STABLE_STALE, 46886 SOC_STABLE_FIELD, 46887 0 46888 ) 46889 ); 46890 /* Clean up generated state and restart as Level 1 */ 46891 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46892 rv = _bcm_field_tr3_stage_ingress_reinit(unit, fc, stage_fc); 46893 } 46894 do { 46895 if (BCM_SUCCESS(rv)) { 46896 stage_id = _BCM_FIELD_STAGE_EGRESS; 46897 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46898 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) { 46899 /* Cannot return as LOOKUP+External Stages need to be 46900 * checked yet. 46901 */ 46902 rv = BCM_E_NONE; 46903 break; 46904 } 46905 BCM_IF_ERROR_RETURN(rv); 46906 oldl2warm = fc->l2warm; 46907 rv = _field_tr2_stage_egress_reinit(unit, fc, stage_fc); 46908 if ((rv == BCM_E_INTERNAL) && 46909 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) 46910 && (fc->l2warm == 0) && (oldl2warm != 0)) { 46911 /* Stale scache in egress section */ 46912 SOC_IF_ERROR_RETURN 46913 (soc_event_generate(unit, 46914 SOC_SWITCH_EVENT_STABLE_ERROR, 46915 SOC_STABLE_STALE, 46916 SOC_STABLE_FIELD, 46917 0 46918 ) 46919 ); 46920 /* Clean up generated state and restart as Level 1 */ 46921 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46922 stage_id = _BCM_FIELD_STAGE_INGRESS; 46923 BCM_IF_ERROR_RETURN 46924 (_field_stage_control_get(unit, 46925 stage_id, 46926 &stage_fc) 46927 ); 46928 rv = _field_tr2_stage_ingress_reinit 46929 (unit, 46930 fc, 46931 stage_fc 46932 ); 46933 if (BCM_SUCCESS(rv)) { 46934 stage_id = _BCM_FIELD_STAGE_EGRESS; 46935 BCM_IF_ERROR_RETURN 46936 (_field_stage_control_get(unit, 46937 stage_id, 46938 &stage_fc 46939 ) 46940 ); 46941 rv = _field_tr2_stage_egress_reinit(unit, 46942 fc, 46943 stage_fc); 46944 } 46945 } 46946 } 46947 } while (0); 46948 do { 46949 if (BCM_SUCCESS(rv)) { 46950 stage_id = _BCM_FIELD_STAGE_LOOKUP; 46951 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 46952 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) { 46953 /* Cannot return as External Stages need to be checked*/ 46954 rv = BCM_E_NONE; 46955 break; 46956 } 46957 BCM_IF_ERROR_RETURN(rv); 46958 oldl2warm = fc->l2warm; 46959 rv = _bcm_field_tr3_stage_lookup_reinit(unit, fc, stage_fc); 46960 if ((rv == BCM_E_INTERNAL) && 46961 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) 46962 && (fc->l2warm == 0) && (oldl2warm != 0)) { 46963 /* Stale scache in lookup section */ 46964 SOC_IF_ERROR_RETURN 46965 (soc_event_generate(unit, 46966 SOC_SWITCH_EVENT_STABLE_ERROR, 46967 SOC_STABLE_STALE, 46968 SOC_STABLE_FIELD, 0 46969 ) 46970 ); 46971 /* Clean up generated state and restart as Level 1 */ 46972 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 46973 stage_id = _BCM_FIELD_STAGE_INGRESS; 46974 BCM_IF_ERROR_RETURN 46975 (_field_stage_control_get(unit, 46976 stage_id, 46977 &stage_fc 46978 ) 46979 ); 46980 rv = _bcm_field_tr3_stage_ingress_reinit(unit, fc, stage_fc); 46981 if (BCM_SUCCESS(rv)) { 46982 stage_id = _BCM_FIELD_STAGE_EGRESS; 46983 BCM_IF_ERROR_RETURN 46984 (_field_stage_control_get(unit, 46985 stage_id, 46986 &stage_fc 46987 ) 46988 ); 46989 rv = _field_tr2_stage_egress_reinit(unit, 46990 fc, 46991 stage_fc 46992 ); 46993 } 46994 if (BCM_SUCCESS(rv)) { 46995 stage_id = _BCM_FIELD_STAGE_LOOKUP; 46996 BCM_IF_ERROR_RETURN 46997 (_field_stage_control_get(unit, 46998 stage_id, 46999 &stage_fc 47000 ) 47001 ); 47002 rv = _bcm_field_tr3_stage_lookup_reinit(unit, 47003 fc, 47004 stage_fc 47005 ); 47006 } 47007 } 47008 } 47009 } while(0); 47010 /* Warm boot level 1 and level 2 recovery for TR3 FP ESM */ 47011 do { 47012 if (BCM_SUCCESS(rv) && soc_feature(unit, soc_feature_esm_support)) { 47013 stage_id = _BCM_FIELD_STAGE_EXTERNAL; 47014 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 47015 if (rv == BCM_E_UNAVAIL) { 47016 /* External stage supported but not configured => Skip it */ 47017 rv = BCM_E_NONE; 47018 break; 47019 } 47020 BCM_IF_ERROR_RETURN(rv); 47021 47022 oldl2warm = fc->l2warm; 47023 rv = _bcm_field_tr3_stage_external_reinit(unit, fc, stage_fc); 47024 if ((rv == BCM_E_INTERNAL) && 47025 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) && 47026 (fc->l2warm == 0) && (oldl2warm != 0)) { 47027 /* Stale scache in lookup section */ 47028 SOC_IF_ERROR_RETURN 47029 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 47030 SOC_STABLE_STALE, 47031 SOC_STABLE_FIELD, 0)); 47032 /* Clean up generated state and restart as Level 1 */ 47033 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc)); 47034 stage_id = _BCM_FIELD_STAGE_INGRESS; 47035 BCM_IF_ERROR_RETURN 47036 (_field_stage_control_get(unit, stage_id, &stage_fc)); 47037 rv = _bcm_field_tr3_stage_ingress_reinit(unit, fc, stage_fc); 47038 if (BCM_SUCCESS(rv)) { 47039 stage_id = _BCM_FIELD_STAGE_EGRESS; 47040 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 47041 stage_id, &stage_fc)); 47042 rv = _bcm_field_tr3_stage_egress_reinit(unit, fc, stage_fc); 47043 } 47044 if (BCM_SUCCESS(rv)) { 47045 stage_id = _BCM_FIELD_STAGE_LOOKUP; 47046 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 47047 stage_id, &stage_fc)); 47048 rv = _bcm_field_tr3_stage_lookup_reinit(unit, fc, stage_fc); 47049 } 47050 if (BCM_SUCCESS(rv)) { 47051 stage_id = _BCM_FIELD_STAGE_EXTERNAL; 47052 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 47053 stage_id, &stage_fc)); 47054 rv = _bcm_field_tr3_stage_external_reinit(unit, fc, stage_fc); 47055 } 47056 } 47057 } 47058 } while(0); 47059 #endif 47060 } 47061 47062 if (BCM_FAILURE(rv)) { 47063 _field_stage_delete(unit, fc, stage_fc); 47064 return (rv); 47065 } 47066 47067 /* During Warm Boot upgrade partitions not existed in previous code 47068 version but need to be existed , must be created now */ 47069 47070 if (fc->l2warm) { 47071 #ifdef BCM_TOMAHAWK_SUPPORT 47072 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 47073 BCM_IF_ERROR_RETURN(_bcm_field_scache_th_pointer_realloc(unit, 47074 fc)); 47075 } else 47076 #endif 47077 { 47078 BCM_IF_ERROR_RETURN(_field_scache_pointer_init_wb(unit, fc)); 47079 } 47080 47081 } 47082 } 47083 #endif 47084 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 47085 bcm_esw_linkscan_register(unit, _bcm_field_linkscan_update); 47086 } 47087 47088 _field_control[unit]->init = TRUE; 47089 47090 /* EM COS SW WAR for TH3 */ 47091 #if defined(BCM_TOMAHAWK3_SUPPORT) 47092 if((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) && 47093 (soc_feature(unit, soc_feature_field_exact_match_support)) && 47094 (!(SOC_WARM_BOOT(unit)))) { 47095 rv = _bcm_field_th3_internal_em_group_create(unit, 47096 fc); 47097 if (BCM_FAILURE(rv)) { 47098 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 47099 "FP(unit %d) Error:_field_internal_em_group_create =%d" 47100 "\n"), unit, rv)); 47101 return (rv); 47102 } 47103 47104 } 47105 #endif 47106 return (BCM_E_NONE); 47107 } 47108 47109 /* 47110 * Function: _bcm_esw_field_detach 47111 * 47112 * Purpose: 47113 * Free resources associated with field module 47114 * 47115 * Parameters: 47116 * unit - BCM device number 47117 * 47118 * Returns: 47119 * BCM_E_INIT - BCM Unit not initialized. 47120 * BCM_E_XXX - Error code from bcm_field_group_destroy() or 47121 * bcm_field_entry_destroy_all(). 47122 * BCM_E_NONE - Success 47123 */ 47124 47125 int 47126 _bcm_esw_field_detach(int unit) 47127 { 47128 _field_control_t *fc; 47129 _field_group_t *fg; 47130 int rv = BCM_E_NONE; 47131 int id = 0; 47132 _field_egr_ports_recovery_t *f_egr_recovery = NULL; 47133 47134 LOG_DEBUG(BSL_LS_BCM_FP, 47135 (BSL_META_U(unit, 47136 "FP(unit %d) vverb: bcm_field_detach()\n"), 47137 unit)); 47138 47139 FP_LOCK(unit); 47140 fc = _field_control[unit]; 47141 if (NULL == fc) { 47142 FP_UNLOCK(unit); 47143 return (BCM_E_NONE); 47144 } 47145 47146 /* 47147 * De-initialize the field module as all 47148 * the componenets are getting detached 47149 */ 47150 _field_control[unit]->init = FALSE; 47151 47152 soc_counter_extra_unregister(unit, _bcm_esw_fp_counters_collect); 47153 /* Unregister counter collection callback. */ 47154 47155 47156 /* Unregister link scan updates */ 47157 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 47158 rv = bcm_esw_linkscan_unregister(unit, _bcm_field_linkscan_update); 47159 if (rv != BCM_E_NONE) { 47160 LOG_VERBOSE(BSL_LS_BCM_FP, 47161 (BSL_META_U(unit, 47162 "FP(unit %d) vverb:Field Module not registered to LinkScan\n"), 47163 unit)); 47164 } 47165 } 47166 47167 /* Destroy all entries in unit. */ 47168 rv = bcm_esw_field_entry_destroy_all(unit); 47169 if (BCM_FAILURE(rv)) { 47170 FP_UNLOCK(unit); 47171 return (rv); 47172 } 47173 47174 /* EM COS SW WAR for TH3 */ 47175 #if defined(BCM_TOMAHAWK3_SUPPORT) 47176 if (soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) { 47177 rv = _field_group_get(unit, _FP_INTERNAL_RESERVED_EM_ID, &fg); 47178 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 47179 FP_UNLOCK(unit); 47180 LOG_ERROR(BSL_LS_BCM_FP, 47181 (BSL_META_U(unit, 47182 "FP(unit %d) Error: Failed to get Group=%d\n"), 47183 unit, _FP_INTERNAL_RESERVED_EM_ID)); 47184 return (rv); 47185 } 47186 rv = bcm_esw_field_entry_destroy(unit, _FP_INTERNAL_RESERVED_EM_ID); 47187 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND) ) { 47188 LOG_ERROR(BSL_LS_BCM_FP, 47189 (BSL_META_U(unit, 47190 "FP(unit %d) Error: Failed to destroy entry=%d\n"), 47191 unit, _FP_INTERNAL_RESERVED_EM_ID)); 47192 FP_UNLOCK(unit); 47193 return (rv); 47194 } 47195 } 47196 #endif 47197 47198 /* Destroy all statistics entities. */ 47199 rv = _field_stat_destroy_all(unit); 47200 if (BCM_FAILURE(rv)) { 47201 FP_UNLOCK(unit); 47202 return (rv); 47203 } 47204 47205 /* Destroy all policers. */ 47206 rv = bcm_esw_policer_destroy_all(unit); 47207 if (BCM_FAILURE(rv)) { 47208 FP_UNLOCK(unit); 47209 return (rv); 47210 } 47211 47212 /* Destroy all groups in unit. */ 47213 fg = fc->groups; 47214 47215 while (fg != NULL) { 47216 _field_group_t *fg_next = NULL; 47217 47218 fg_next = fg->next; 47219 /* 47220 * Retaining ExactMatch groups during bcm_field_init for retaining Sticky ExactMatch stage. 47221 */ 47222 if ((fc->flags & _FP_EXACTMATCH_STAGE_SKIP_DETACH) && 47223 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) { 47224 fg = fg_next; 47225 continue; 47226 } 47227 47228 rv = bcm_esw_field_group_destroy(unit, fg->gid); 47229 if (BCM_FAILURE(rv)) { 47230 FP_UNLOCK(unit); 47231 return (rv); 47232 } 47233 fg = fg_next; 47234 } 47235 47236 /* Destroy all hints */ 47237 for (id = _FP_HINT_ID_BASE; id < _FP_HINT_ID_MAX; id++) { 47238 if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, id)) { 47239 rv = bcm_esw_field_hints_destroy (unit, id); 47240 if (BCM_FAILURE(rv)) { 47241 FP_UNLOCK(unit); 47242 return (rv); 47243 } 47244 } 47245 } 47246 47247 /* Device specific detach */ 47248 if (NULL != fc->functions.fp_detach) { 47249 rv = fc->functions.fp_detach(unit, fc); 47250 if (BCM_FAILURE(rv)) { 47251 FP_UNLOCK(unit); 47252 return (rv); 47253 } 47254 } 47255 47256 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 47257 /* Invoke tomahawk stage delete routine.*/ 47258 rv = fc->stage_func.fp_stages_delete(unit, fc); 47259 } else { 47260 /* Destroy a Unit's stages*/ 47261 rv = _field_stages_destroy(unit, fc); 47262 } 47263 if (BCM_FAILURE(rv)) { 47264 FP_UNLOCK(unit); 47265 return (rv); 47266 } 47267 #if defined (BCM_APACHE_SUPPORT) 47268 if (soc_feature(unit, soc_feature_fp_based_sat)) { 47269 rv = bcm_esw_field_sat_macsa_delete_all(unit); 47270 if (BCM_FAILURE(rv)) { 47271 FP_UNLOCK(unit); 47272 return (rv); 47273 } 47274 } 47275 #endif 47276 47277 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 47278 _field_egr_ports_recovery_control_get (unit, &f_egr_recovery); 47279 _field_egr_ports_recovery_control_free (unit, f_egr_recovery); 47280 } 47281 47282 #if defined(BCM_TRX_SUPPORT) 47283 /* Destroy global redirection action profile. */ 47284 soc_profile_mem_destroy(unit, &fc->redirect_profile); 47285 47286 #if defined(BCM_TOMAHAWK3_SUPPORT) 47287 /* Destroy global redirection action profile. */ 47288 soc_profile_mem_destroy(unit, &fc->redirect_profile1); 47289 /* Destroy delayed drop action profile. */ 47290 soc_profile_mem_destroy(unit, &fc->ddrop_profile); 47291 /* Destroy delayed redirection action profile. */ 47292 soc_profile_mem_destroy(unit, &fc->dredirect_profile); 47293 #endif 47294 #endif 47295 47296 #if defined (BCM_TOMAHAWK_SUPPORT) 47297 /* Destroy HiGiG2 extended header mask profile. */ 47298 if (soc_feature(unit, soc_feature_higig_lookup) && SOC_IS_TOMAHAWKX(unit)) 47299 { 47300 soc_profile_mem_destroy(unit, &fc->eh_mask_profile); 47301 } 47302 #endif 47303 47304 _field_control_free(unit, fc); 47305 FP_UNLOCK(unit); 47306 47307 return (BCM_E_NONE); 47308 } 47309 47310 #if defined(BCM_TRX_SUPPORT) 47311 47312 /* 47313 * Function: _bcm_field_flex_port_detach 47314 * 47315 * Purpose: 47316 * Detached Flexed ports from Field Group. 47317 * 47318 * Parameters: 47319 * unit - BCM device number 47320 * port - Port to be cleared 47321 * 47322 * Returns: 47323 * BCM_E_XXX - Error code from _bcm_field_pfs_entry_clear() or 47324 * _field_control_get(). 47325 */ 47326 47327 int 47328 _bcm_field_flex_port_detach(int unit, bcm_port_t port) 47329 { 47330 _field_control_t *fc = NULL; 47331 _field_group_t *fg = NULL; 47332 int rv = BCM_E_NONE; 47333 _field_slice_t *fs = NULL; 47334 47335 FP_LOCK(unit); 47336 rv = _field_control_get(unit, &fc); 47337 if (BCM_FAILURE(rv)) { 47338 goto cleanup; 47339 } 47340 47341 for (fg = fc->groups; fg != NULL; fg = fg->next) { 47342 if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP)) { 47343 if (BCM_PBMP_MEMBER(fg->pbmp,port)) { 47344 rv = _bcm_field_pfs_entry_clear(unit, 47345 fg, port); 47346 if (BCM_FAILURE(rv)) { 47347 goto cleanup; 47348 } 47349 } 47350 } else { 47351 if(BCM_PBMP_MEMBER(fg->pbmp, port)) { 47352 BCM_PBMP_PORT_REMOVE(fg->pbmp, port); 47353 if (fg->slices != NULL) { 47354 for (fs = fg->slices; fs != NULL; fs = fs->next) { 47355 BCM_PBMP_PORT_REMOVE(fs->pbmp, port); 47356 } 47357 } 47358 } 47359 47360 } 47361 } 47362 47363 cleanup: 47364 FP_UNLOCK(unit); 47365 return (rv); 47366 } 47367 47368 /* 47369 * Function: _bcm_field_flex_port_attach 47370 * 47371 * Purpose: 47372 * Detached Flexed ports from Field Group. 47373 * 47374 * Parameters: 47375 * unit - BCM device number 47376 * port - Port to be cleared 47377 * 47378 * Returns: 47379 * BCM_E_NONE - Success 47380 */ 47381 47382 int 47383 _bcm_field_flex_port_attach(int unit, bcm_port_t port) 47384 { 47385 _field_control_t *fc = NULL; 47386 _field_group_t *fg = NULL; 47387 bcm_error_t rv = BCM_E_NONE; 47388 _field_slice_t *fs; 47389 47390 #if defined(BCM_TOMAHAWK_SUPPORT) 47391 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 47392 (!soc_feature(unit, soc_feature_field_multi_pipe_enhanced)) && 47393 (!soc_feature(unit, soc_feature_th3_style_fp)) && 47394 (!soc_feature(unit, soc_feature_td3_style_fp))) { 47395 return BCM_E_NONE; 47396 } 47397 #endif 47398 47399 FP_LOCK(unit); 47400 rv = _field_control_get(unit, &fc); 47401 if (BCM_FAILURE(rv)) { 47402 goto cleanup; 47403 } 47404 47405 for (fg = fc->groups; fg != NULL; fg = fg->next) { 47406 if (fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) { 47407 /* Ignore per port based groups*/ 47408 continue; 47409 } 47410 /* Ignore PBMP update for the stages other than Ingress */ 47411 if (fg->stage_id != _BCM_FIELD_STAGE_INGRESS) { 47412 continue; 47413 } 47414 BCM_PBMP_PORT_ADD(fg->pbmp, port); 47415 if (fg->slices != NULL) { 47416 for (fs = fg->slices; fs != NULL; fs = fs->next) { 47417 BCM_PBMP_PORT_ADD(fs->pbmp, port); 47418 } 47419 } 47420 } 47421 47422 cleanup: 47423 FP_UNLOCK(unit); 47424 return (rv); 47425 } 47426 47427 /* 47428 * Function: _bcm_field_flex_port_update 47429 * 47430 * Purpose: 47431 * Routine is invoked after performing flex operation to 47432 * update the field module resources. 47433 * 47434 * Parameters: 47435 * unit - BCM device number 47436 * detached_pbmp - Ports detached after flex operation. 47437 * attached_pbmp - Ports attached after flex operation. 47438 * 47439 * Returns: 47440 * BCM_E_xxx 47441 */ 47442 47443 int 47444 _bcm_field_flex_port_update(int unit, 47445 bcm_pbmp_t detached_pbmp, 47446 bcm_pbmp_t attached_pbmp) 47447 { 47448 _field_control_t *fc = NULL; 47449 _field_group_t *fg = NULL; 47450 bcm_error_t rv = BCM_E_NONE; 47451 47452 if (!(SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit) || 47453 SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit) || 47454 soc_feature(unit, soc_feature_td3_style_fp))) { 47455 return BCM_E_NONE; 47456 } 47457 47458 if (SOC_REG_IS_VALID(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr)) { 47459 /* considering only attached ports. */ 47460 if (BCM_PBMP_IS_NULL(attached_pbmp)) { 47461 return BCM_E_NONE; 47462 } 47463 } else { 47464 if (BCM_PBMP_IS_NULL(attached_pbmp) && BCM_PBMP_IS_NULL(detached_pbmp)) { 47465 return BCM_E_NONE; 47466 } 47467 } 47468 47469 FP_LOCK(unit); 47470 rv = _field_control_get(unit, &fc); 47471 if (BCM_FAILURE(rv)) { 47472 goto cleanup; 47473 } 47474 47475 for (fg = fc->groups; fg != NULL; fg = fg->next) { 47476 if (fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) { 47477 /* Ignore per port based groups*/ 47478 continue; 47479 } 47480 47481 /* Ignore PBMP update for the stages other than Ingress */ 47482 if (fg->stage_id != _BCM_FIELD_STAGE_INGRESS) { 47483 continue; 47484 } 47485 47486 if ((SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) && 47487 (BCM_FIELD_QSET_TEST(fg->qset, 47488 bcmFieldQualifyInPorts) || 47489 BCM_FIELD_QSET_TEST(fg->qset, 47490 bcmFieldQualifyInPort))) { 47491 (void)_bcm_field_group_entry_port_update(unit, fg, 47492 detached_pbmp, 47493 attached_pbmp); 47494 } 47495 #if defined(BCM_TOMAHAWK_SUPPORT) 47496 else if ((SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit) || 47497 soc_feature(unit, soc_feature_td3_style_fp)) && 47498 BCM_FIELD_QSET_TEST(fg->qset, 47499 bcmFieldQualifyInPorts)) { 47500 (void)_bcm_field_group_entry_pipe_port_update(unit, fg, 47501 detached_pbmp, 47502 attached_pbmp); 47503 } 47504 #endif 47505 } 47506 47507 cleanup: 47508 FP_UNLOCK(unit); 47509 return (rv); 47510 47511 } 47512 47513 /* 47514 * Function: _bcm_esw_field_group_ports_add 47515 * 47516 * Purpose: 47517 * Add ports to the specified group. 47518 * 47519 * Parameters: 47520 * unit - BCM device number 47521 * group - Field group 47522 * pbmp - Set of Ports 47523 * 47524 * Returns: 47525 * BCM_E_XXX - Error code from _bcm_field_fb_group_install() or 47526 * _field_group_get(). 47527 * BCM_E_NONE - If ports are already part of the group. 47528 */ 47529 47530 int 47531 _bcm_esw_field_group_ports_add( 47532 int unit, 47533 bcm_field_group_t group, 47534 bcm_pbmp_t pbmp) 47535 { 47536 _field_group_t *fg = NULL; 47537 bcm_port_t port; 47538 int rv = BCM_E_NONE; 47539 bcm_pbmp_t group_pbmp; 47540 bcm_pbmp_t add_pbmp; 47541 bcm_pbmp_t valid_pbmp; 47542 bcm_pbmp_t temp_pbmp; 47543 47544 BCM_PBMP_CLEAR(valid_pbmp); 47545 47546 /* check if the ports are valid */ 47547 rv = _bcm_field_valid_pbmp_get(unit, &valid_pbmp); 47548 if (BCM_FAILURE(rv)) { 47549 return rv; 47550 } 47551 47552 BCM_PBMP_ASSIGN(temp_pbmp, valid_pbmp); 47553 BCM_PBMP_OR(temp_pbmp, pbmp); 47554 if (BCM_PBMP_NEQ(valid_pbmp, temp_pbmp)) { 47555 return BCM_E_PARAM; 47556 } 47557 47558 rv = _field_group_get(unit, group, &fg); 47559 if (BCM_FAILURE(rv)){ 47560 return rv; 47561 } 47562 47563 if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP)) { 47564 47565 BCM_PBMP_CLEAR(add_pbmp); 47566 47567 BCM_PBMP_ASSIGN(group_pbmp, fg->pbmp); 47568 BCM_PBMP_OR(group_pbmp, pbmp); 47569 47570 if (BCM_PBMP_EQ(group_pbmp, fg->pbmp)) { 47571 /* Ports are already part of this group */ 47572 return BCM_E_NONE; 47573 } 47574 BCM_PBMP_ITER(pbmp, port) { 47575 if((BCM_PBMP_MEMBER(fg->slices[0].pbmp, port))) { 47576 if(BCM_PBMP_MEMBER(fg->pbmp,port)) { 47577 continue; 47578 } 47579 /* Port is part of another group in same slice */ 47580 LOG_DEBUG(BSL_LS_BCM_FP, 47581 (BSL_META_U(unit, 47582 "Port is present in another group in same slice \n"))); 47583 return BCM_E_PARAM; 47584 } 47585 BCM_PBMP_PORT_ADD(add_pbmp, port); 47586 } 47587 BCM_PBMP_OR(fg->pbmp, add_pbmp); 47588 BCM_PBMP_OR(fg->slices[0].pbmp, add_pbmp); 47589 rv = _bcm_field_fb_group_install(unit,fg); 47590 if (BCM_FAILURE(rv)){ 47591 BCM_PBMP_REMOVE(fg->pbmp, add_pbmp); 47592 BCM_PBMP_REMOVE(fg->slices[0].pbmp, add_pbmp); 47593 } 47594 } else { 47595 rv = BCM_E_PARAM; 47596 LOG_DEBUG(BSL_LS_BCM_FP, 47597 (BSL_META_U(unit, 47598 "Per port or Pbmp base Group is expected \n"))); 47599 } 47600 return (rv); 47601 47602 } 47603 /* 47604 * Function: _field_entry_update_ipbm 47605 * 47606 * Purpose: 47607 * Remove given pbmp from the entry IPBM 47608 * 47609 * Parameters: 47610 * unit - BCM device number 47611 * f_ent - Field entry structure 47612 * pbmp - Set of Ports 47613 * 47614 * Returns: 47615 * BCM_E_XXX - Error code from internal functions 47616 */ 47617 STATIC int 47618 _field_entry_update_ipbm( 47619 int unit, 47620 _field_entry_t *f_ent, 47621 bcm_pbmp_t pbmp) 47622 { 47623 int tcam_idx; 47624 bcm_error_t rv = BCM_E_NONE; 47625 bcm_error_t rv_internal = BCM_E_NONE; 47626 bcm_pbmp_t ipbm; 47627 bcm_pbmp_t ipbm_copy; 47628 bcm_field_entry_t backup_entry; 47629 fp_global_mask_tcam_entry_t ipbm_entry; 47630 47631 if (!soc_mem_is_valid(unit, FP_GLOBAL_MASK_TCAMm)) { 47632 return BCM_E_NONE; 47633 } 47634 47635 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent, &tcam_idx); 47636 BCM_IF_ERROR_RETURN(rv); 47637 47638 BCM_PBMP_CLEAR(ipbm); 47639 sal_memset(&ipbm_entry, 0, sizeof(fp_global_mask_tcam_entry_t)); 47640 47641 rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY, tcam_idx, 47642 &ipbm_entry); 47643 BCM_IF_ERROR_RETURN(rv); 47644 47645 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry, IPBMf, 47646 &ipbm); 47647 47648 BCM_PBMP_ASSIGN(ipbm_copy, ipbm); 47649 /* Removing pbmp from ipbm. ipbm &= ~pbmp */ 47650 BCM_PBMP_NEGATE(pbmp, pbmp); 47651 BCM_PBMP_AND(ipbm, pbmp); 47652 47653 if (BCM_PBMP_EQ(ipbm, ipbm_copy)) { 47654 /* pbmp is not part of f_ent IPBM. Nothing to be done */ 47655 return BCM_E_NONE; 47656 } 47657 47658 rv = _field_internal_backup_entry_create(unit, f_ent->eid, 47659 &backup_entry); 47660 BCM_IF_ERROR_RETURN(rv); 47661 47662 soc_mem_pbmp_field_set(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry, IPBMf, 47663 &ipbm); 47664 soc_mem_pbmp_field_set(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry, 47665 IPBM_MASKf, &f_ent->pbmp.mask); 47666 rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL, 47667 tcam_idx, &ipbm_entry); 47668 47669 rv_internal = _field_internal_backup_entry_delete(unit, backup_entry); 47670 if (BCM_FAILURE(rv_internal)) { 47671 LOG_DEBUG(BSL_LS_BCM_FP, 47672 (BSL_META_U(unit, 47673 "Internal backup entry delete failed \n"))); 47674 if (BCM_SUCCESS(rv)) { 47675 return rv_internal; 47676 } 47677 } 47678 return rv; 47679 } 47680 47681 /* 47682 * Routine to add newly attached port to the InPorts qualifier of all the 47683 * group entries in order to avoid the false match. 47684 * Note: The change affects only if mask parameter of InPorts qualifier 47685 * configured for all valid ports before flex operation. 47686 */ 47687 STATIC 47688 int _bcm_field_group_entry_port_update(int unit, 47689 _field_group_t *fg, 47690 bcm_pbmp_t detached_pbmp, 47691 bcm_pbmp_t attached_pbmp) 47692 { 47693 int idx; 47694 _field_entry_t *f_ent; 47695 int tcam_idx; 47696 bcm_error_t rv = BCM_E_NONE; 47697 bcm_error_t rv_internal = BCM_E_NONE; 47698 bcm_field_entry_t backup_entry; 47699 bcm_pbmp_t valid_full_mask; 47700 bcm_pbmp_t temp_mask; 47701 fp_global_mask_tcam_entry_t ipbm_entry; 47702 47703 /* Retrieve valid pbmp of the device */ 47704 rv = _bcm_field_valid_pbmp_get(unit, &valid_full_mask); 47705 if (BCM_FAILURE(rv)) { 47706 return (rv); 47707 } 47708 BCM_PBMP_OR(valid_full_mask, PBMP_LB(unit)); 47709 BCM_PBMP_REMOVE(valid_full_mask, attached_pbmp); 47710 47711 for (idx = 0; idx < fg->group_status.entry_count; idx++) { 47712 f_ent = fg->entry_arr[idx]; 47713 if ((f_ent == NULL) || 47714 BCM_PBMP_IS_NULL(f_ent->pbmp.mask)) { 47715 continue; 47716 } 47717 47718 /* Check if entry is already part of attached_pbmp */ 47719 BCM_PBMP_ASSIGN(temp_mask, f_ent->pbmp.mask); 47720 BCM_PBMP_XOR(temp_mask, detached_pbmp); 47721 BCM_PBMP_OR(temp_mask, attached_pbmp); 47722 if (BCM_PBMP_EQ(temp_mask, f_ent->pbmp.mask)) { 47723 continue; 47724 } 47725 47726 /* Check if entry pbmp contains all valid ports */ 47727 BCM_PBMP_ASSIGN(temp_mask, f_ent->pbmp.mask); 47728 BCM_PBMP_AND(temp_mask, valid_full_mask); 47729 if (BCM_PBMP_EQ(valid_full_mask, temp_mask)) { 47730 /* Remove detached ports from the entry mask */ 47731 BCM_PBMP_XOR(f_ent->pbmp.mask, detached_pbmp); 47732 /* Add newly attached ports to the entry mask */ 47733 BCM_PBMP_OR(f_ent->pbmp.mask, attached_pbmp); 47734 47735 rv = _field_internal_backup_entry_create(unit, f_ent->eid, 47736 &backup_entry); 47737 BCM_IF_ERROR_RETURN(rv); 47738 47739 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent, &tcam_idx); 47740 BCM_IF_ERROR_RETURN(rv); 47741 47742 sal_memset(&ipbm_entry, 0, sizeof(fp_global_mask_tcam_entry_t)); 47743 rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY, tcam_idx, 47744 &ipbm_entry); 47745 BCM_IF_ERROR_RETURN(rv); 47746 soc_mem_pbmp_field_set(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry, IPBMf, 47747 &f_ent->pbmp.data); 47748 soc_mem_pbmp_field_set(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry, 47749 IPBM_MASKf, &f_ent->pbmp.mask); 47750 rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL, 47751 tcam_idx, &ipbm_entry); 47752 47753 rv_internal = _field_internal_backup_entry_delete(unit, backup_entry); 47754 if (BCM_FAILURE(rv_internal)) { 47755 LOG_DEBUG(BSL_LS_BCM_FP, 47756 (BSL_META_U(unit, 47757 "Internal backup entry delete failed \n"))); 47758 if (BCM_SUCCESS(rv)) { 47759 return rv_internal; 47760 } 47761 } 47762 } 47763 } 47764 47765 return BCM_E_NONE; 47766 } 47767 47768 #if defined(BCM_TOMAHAWK_SUPPORT) 47769 /* 47770 * Routine to add newly attached port to the InPorts qualifier of all the 47771 * group entries in order to avoid the false match. 47772 * Note: The change affects only if mask parameter of InPorts qualifier 47773 * configured for all global / pipe local valid ports before flex operation. 47774 */ 47775 STATIC 47776 int _bcm_field_group_entry_pipe_port_update(int unit, 47777 _field_group_t *fg, 47778 bcm_pbmp_t detached_pbmp, 47779 bcm_pbmp_t attached_pbmp) 47780 { 47781 int idx; 47782 _field_entry_t *f_ent = NULL; 47783 _field_stage_t *stage_fc = NULL; 47784 bcm_error_t rv = BCM_E_NONE; 47785 bcm_pbmp_t valid_full_mask; 47786 bcm_pbmp_t old_valid_full_mask; 47787 bcm_pbmp_t temp_mask; 47788 bcm_pbmp_t entry_mask; 47789 bcm_pbmp_t entry_data; 47790 47791 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 47792 BCM_IF_ERROR_RETURN(rv); 47793 if (bcmFieldGroupOperModePipeLocal == stage_fc->oper_mode) { 47794 BCM_PBMP_ASSIGN(valid_full_mask, PBMP_PIPE(unit, fg->instance)); 47795 BCM_PBMP_REMOVE(valid_full_mask, PBMP_LB(unit)); 47796 } else { 47797 /* Retrieve valid pbmp of the device */ 47798 rv = _bcm_field_valid_pbmp_get(unit, &valid_full_mask); 47799 if (BCM_FAILURE(rv)) { 47800 return (rv); 47801 } 47802 } 47803 BCM_PBMP_ASSIGN(old_valid_full_mask, valid_full_mask); 47804 BCM_PBMP_REMOVE(old_valid_full_mask, attached_pbmp); 47805 47806 for (idx = 0; idx < fg->group_status.entry_count; idx++) { 47807 f_ent = fg->entry_arr[idx]; 47808 if ((f_ent == NULL) || 47809 BCM_PBMP_IS_NULL(f_ent->pbmp.mask)) { 47810 continue; 47811 } 47812 47813 /* Get entry data/mask */ 47814 rv = _bcm_field_qualify_InPorts_get(unit, f_ent->eid, bcmFieldQualifyInPorts, 47815 &entry_data, &entry_mask); 47816 BCM_IF_ERROR_RETURN(rv); 47817 47818 /* Check if entry pbmp contains all valid ports */ 47819 BCM_PBMP_ASSIGN(temp_mask, entry_mask); 47820 BCM_PBMP_AND(temp_mask, old_valid_full_mask); 47821 if (BCM_PBMP_EQ(old_valid_full_mask, temp_mask)) { 47822 /* Remove detached ports from the entry mask */ 47823 BCM_PBMP_REMOVE(entry_mask, detached_pbmp); 47824 /* Add newly attached ports to the entry mask */ 47825 BCM_PBMP_OR(entry_mask, attached_pbmp); 47826 BCM_PBMP_AND(entry_mask, valid_full_mask); 47827 47828 rv = _bcm_field_th_qualify_InPorts(unit, f_ent->eid, bcmFieldQualifyInPorts, 47829 entry_data, entry_mask); 47830 47831 rv = bcm_esw_field_entry_reinstall(unit, f_ent->eid); 47832 BCM_IF_ERROR_RETURN(rv); 47833 } 47834 } 47835 47836 return BCM_E_NONE; 47837 } 47838 #endif 47839 47840 /* 47841 * Function: _bcm_esw_field_group_ports_remove 47842 * 47843 * Purpose: 47844 * Remove ports from the specified group. 47845 * 47846 * Parameters: 47847 * unit - BCM device number 47848 * group - Field group 47849 * pbmp - Set of Ports 47850 * 47851 * Returns: 47852 * BCM_E_XXX - Error code from _bcm_field_pfs_entry_clear() or 47853 * _field_control_get(). 47854 */ 47855 47856 int 47857 _bcm_esw_field_group_ports_remove( 47858 int unit, 47859 bcm_field_group_t group, 47860 bcm_pbmp_t pbmp) 47861 { 47862 _field_group_t *fg = NULL; 47863 _field_entry_t **entries = NULL; 47864 bcm_port_t port; 47865 int rv = BCM_E_NONE; 47866 int idx; 47867 47868 rv = _field_group_get(unit, group, &fg); 47869 BCM_IF_ERROR_RETURN(rv); 47870 47871 if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP)) { 47872 BCM_PBMP_ITER(pbmp, port) { 47873 if (BCM_PBMP_MEMBER(fg->pbmp, port)) { 47874 rv = _bcm_field_pfs_entry_clear(unit, 47875 fg, port); 47876 BCM_IF_ERROR_RETURN(rv); 47877 47878 } 47879 } 47880 entries = fg->entry_arr; 47881 for (idx = 0; idx < fg->group_status.entry_count; idx++) { 47882 rv = _field_entry_update_ipbm(unit, (entries[idx]), pbmp); 47883 BCM_IF_ERROR_RETURN(rv); 47884 } 47885 } else { 47886 rv = BCM_E_PARAM; 47887 LOG_DEBUG(BSL_LS_BCM_FP, 47888 (BSL_META_U(unit, 47889 "Per port or Pbmp base Group is expected \n"))); 47890 } 47891 47892 return (rv); 47893 } 47894 47895 int 47896 _bcm_esw_field_class_map_get( 47897 int unit, 47898 bcm_field_qualify_t qual, 47899 uint32 num_entries, 47900 uint32 *orig_values_array, 47901 uint32 *map_values_array) 47902 { 47903 bcm_error_t rv = BCM_E_NONE; 47904 uint32 i = 0; 47905 ttl_fn_entry_t map_buf; 47906 47907 soc_mem_t mem = INVALIDm; 47908 soc_field_t fld = INVALIDf; 47909 47910 if ((NULL == orig_values_array) || 47911 (NULL == map_values_array)) { 47912 return BCM_E_PARAM; 47913 } 47914 47915 switch(qual) { 47916 case bcmFieldQualifyTtlClassZero : 47917 case bcmFieldQualifyTtl : 47918 mem = TTL_FNm; 47919 fld = FN0f; 47920 break; 47921 case bcmFieldQualifyTtlClassOne : 47922 mem = TTL_FNm; 47923 fld = FN1f; 47924 break; 47925 case bcmFieldQualifyTosClassZero : 47926 case bcmFieldQualifyTos : 47927 mem = TOS_FNm; 47928 fld = FN0f; 47929 break; 47930 case bcmFieldQualifyTosClassOne : 47931 mem = TOS_FNm; 47932 fld = FN1f; 47933 break; 47934 case bcmFieldQualifyTcpClassZero : 47935 case bcmFieldQualifyTcpControl : 47936 mem = TCP_FNm; 47937 fld = FN0f; 47938 break; 47939 case bcmFieldQualifyTcpClassOne : 47940 mem = TCP_FNm; 47941 fld = FN1f; 47942 break; 47943 default : 47944 LOG_ERROR(BSL_LS_BCM_FP, 47945 (BSL_META_U(unit, 47946 "FP(unit %d) Error: Field class mapping is " 47947 "not applicable for qual %s\n"), 47948 unit, _field_qual_name(qual))); 47949 return BCM_E_UNAVAIL; 47950 } 47951 47952 sal_memset(&map_buf, 0, sizeof(ttl_fn_entry_t)); 47953 for (i = 0; i < (num_entries); i++) { 47954 if ((orig_values_array[i] > soc_mem_index_max(unit, mem)) || 47955 (orig_values_array[i] < soc_mem_index_min(unit, mem))) { 47956 LOG_ERROR(BSL_LS_BCM_FP, 47957 (BSL_META_U(unit, 47958 "FP(unit %d) Error: Original value %d " 47959 "is out of range for qual %s \n"), 47960 unit,orig_values_array[i], _field_qual_name(qual))); 47961 return BCM_E_PARAM; 47962 } 47963 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 47964 orig_values_array[i], &map_values_array[i])); 47965 map_values_array[i] = soc_mem_field32_get(unit, mem, &map_values_array[i], fld); 47966 } 47967 47968 return rv; 47969 } 47970 47971 int 47972 _bcm_esw_field_class_map_set( 47973 int unit, 47974 bcm_field_qualify_t qual, 47975 uint32 num_entries, 47976 uint32 *orig_values_array, 47977 uint32 *map_values_array) 47978 { 47979 int rv = BCM_E_NONE; 47980 uint32 i = 0; 47981 uint32 hw_retain_val = 0; 47982 uint32 *hw_val_array = NULL; 47983 47984 soc_mem_t mem = INVALIDm; 47985 soc_field_t mod_fld = INVALIDf; 47986 soc_field_t retain_fld = INVALIDf; 47987 47988 if ((NULL == orig_values_array) || 47989 (NULL == map_values_array)) { 47990 return BCM_E_PARAM; 47991 } 47992 47993 switch(qual) { 47994 case bcmFieldQualifyTtlClassZero : 47995 case bcmFieldQualifyTtl : 47996 mem = TTL_FNm; 47997 mod_fld = FN0f; 47998 retain_fld = FN1f; 47999 break; 48000 case bcmFieldQualifyTtlClassOne : 48001 mem = TTL_FNm; 48002 mod_fld = FN1f; 48003 retain_fld = FN0f; 48004 break; 48005 case bcmFieldQualifyTosClassZero : 48006 case bcmFieldQualifyTos : 48007 mem = TOS_FNm; 48008 mod_fld = FN0f; 48009 retain_fld = FN1f; 48010 break; 48011 case bcmFieldQualifyTosClassOne : 48012 mem = TOS_FNm; 48013 mod_fld = FN1f; 48014 retain_fld = FN0f; 48015 break; 48016 case bcmFieldQualifyTcpClassZero : 48017 case bcmFieldQualifyTcpControl : 48018 mem = TCP_FNm; 48019 mod_fld = FN0f; 48020 retain_fld = FN1f; 48021 break; 48022 case bcmFieldQualifyTcpClassOne : 48023 mem = TCP_FNm; 48024 mod_fld = FN1f; 48025 retain_fld = FN0f; 48026 break; 48027 default : 48028 LOG_ERROR(BSL_LS_BCM_FP, 48029 (BSL_META_U(unit, 48030 "FP(unit %d) Error: Field class mapping is " 48031 "not applicable for qual %s\n"), 48032 unit, _field_qual_name(qual))); 48033 return BCM_E_UNAVAIL; 48034 } 48035 48036 _FP_XGS3_ALLOC(hw_val_array, num_entries * sizeof(uint32), "Field class Mapping array"); 48037 if (NULL == hw_val_array) { 48038 return BCM_E_MEMORY; 48039 } 48040 48041 for (i = 0; i < (num_entries); i++) { 48042 48043 if ((orig_values_array[i] > soc_mem_index_max(unit, mem)) || 48044 (orig_values_array[i] < soc_mem_index_min(unit, mem))) { 48045 48046 LOG_ERROR(BSL_LS_BCM_FP, 48047 (BSL_META_U(unit, 48048 "FP(unit %d) Error: Original value %d " 48049 "is out of range for qual %s \n"), 48050 unit,orig_values_array[i], _field_qual_name(qual))); 48051 rv = BCM_E_PARAM; 48052 goto cleanup; 48053 } 48054 48055 /* 48056 * Soc mem write over writes all fields in the memory 48057 * So retaining the other field (FN0f or FN1f). 48058 */ 48059 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 48060 orig_values_array[i], &hw_retain_val); 48061 if (BCM_FAILURE(rv)) { 48062 goto cleanup; 48063 } 48064 hw_retain_val = soc_mem_field32_get(unit, mem, &hw_retain_val, retain_fld); 48065 soc_mem_field32_set(unit, mem, &hw_val_array[i], mod_fld, map_values_array[i]); 48066 soc_mem_field32_set(unit, mem, &hw_val_array[i], retain_fld, hw_retain_val); 48067 } 48068 48069 /* Write to Hardware only after SW operations and error/range checks */ 48070 for (i = 0; i < (num_entries); i++) { 48071 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, orig_values_array[i], &hw_val_array[i]); 48072 if (BCM_FAILURE(rv)) { 48073 goto cleanup; 48074 } 48075 } 48076 48077 cleanup: 48078 sal_free(hw_val_array); 48079 return rv; 48080 } 48081 48082 /* 48083 * Function: _bcm_field_pfs_entry_clear 48084 * 48085 * Purpose: 48086 * Remove ports from the specified group's PFS entry 48087 * 48088 * Parameters: 48089 * unit - BCM device number 48090 * group - Field group 48091 * port - Port for PFS clear 48092 * 48093 * Returns: 48094 * BCM_E_XXX - Error code from _bcm_field_entry_tcam_parts_count() or 48095 * READ_FP_PORT_FIELD_SELm() or 48096 * _bcm_field_tcam_part_to_slice_number() or 48097 * WRITE_FP_PORT_FIELD_SELm(). 48098 */ 48099 48100 int _bcm_field_pfs_entry_clear(int unit, 48101 _field_group_t *fg, 48102 bcm_port_t port) { 48103 48104 fp_port_field_sel_entry_t pfs_entry; 48105 int index; 48106 int rv = 0; 48107 uint8 slice_numb = -1; 48108 int parts_count = -1; 48109 int idx = -1; 48110 48111 index = (int)port; 48112 48113 /* Get number of entry parts for the group. */ 48114 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 48115 fg->flags, &parts_count); 48116 48117 BCM_IF_ERROR_RETURN(rv); 48118 48119 /* Read Port's current entry in FP_PORT_FIELD_SEL table */ 48120 rv = READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 48121 index, &pfs_entry); 48122 BCM_IF_ERROR_RETURN(rv); 48123 48124 for (idx = 0; idx < parts_count; idx++) { 48125 48126 /* Get slice id for entry part */ 48127 rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg, 48128 &slice_numb); 48129 BCM_IF_ERROR_RETURN(rv); 48130 48131 soc_FP_PORT_FIELD_SELm_field32_set 48132 (unit, 48133 &pfs_entry, 48134 _bcm_field_trx_field_sel[slice_numb][0], 48135 0 48136 ); 48137 soc_FP_PORT_FIELD_SELm_field32_set 48138 (unit, 48139 &pfs_entry, 48140 _bcm_field_trx_field_sel[slice_numb][1], 48141 0 48142 ); 48143 soc_FP_PORT_FIELD_SELm_field32_set 48144 (unit, 48145 &pfs_entry, 48146 _bcm_field_trx_field_sel[slice_numb][2], 48147 0 48148 ); 48149 48150 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 48151 if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, 48152 _bcm_ifp_normalize_fldtbl[slice_numb][0])) { 48153 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 48154 _bcm_ifp_normalize_fldtbl[slice_numb][0], 0); 48155 } 48156 if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, 48157 _bcm_ifp_normalize_fldtbl[slice_numb][1])) { 48158 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 48159 _bcm_ifp_normalize_fldtbl[slice_numb][1], 0); 48160 } 48161 #endif 48162 if (SOC_MEM_FIELD_VALID(unit, 48163 FP_PORT_FIELD_SELm, 48164 _bcm_field_trx_d_type_sel[slice_numb])) { 48165 soc_FP_PORT_FIELD_SELm_field32_set(unit, 48166 &pfs_entry, 48167 _bcm_field_trx_d_type_sel[slice_numb], 0); 48168 } 48169 if (SOC_MEM_FIELD_VALID(unit, 48170 FP_PORT_FIELD_SELm, 48171 _bcm_field_trx_s_type_sel[slice_numb])) { 48172 soc_FP_PORT_FIELD_SELm_field32_set(unit, 48173 &pfs_entry, 48174 _bcm_field_trx_s_type_sel[slice_numb], 0); 48175 } 48176 48177 } 48178 48179 rv = WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, index, &pfs_entry); 48180 BCM_IF_ERROR_RETURN(rv); 48181 48182 BCM_PBMP_PORT_REMOVE(fg->pbmp,port); 48183 BCM_PBMP_PORT_REMOVE(fg->slices[0].pbmp, port); 48184 48185 return rv; 48186 48187 } 48188 #endif /* BCM_TRX_SUPPORT */ 48189 48190 /* Function: _bcm_esw_field_group_config_create 48191 * 48192 * Purpose: 48193 * Create a group with a mode (single, double, etc.), a port bitmap, 48194 * group size and a Group ID. 48195 * Parameters: 48196 * unit - BCM device number. 48197 * group_config - Group create attributes namely: 48198 * flags - (IN) Bits indicate which parameters have been 48199 * passed to API and should be used during group 48200 * creation. 48201 * qset - (IN) Field qualifier set 48202 * priority - (IN) Priority within allowable range, 48203 * or BCM_FIELD_GROUP_PRIO_ANY to automatically 48204 * assign a priority; each priority value may be 48205 * used only once 48206 * mode - (IN) Group mode (single, double, triple or Auto-wide) 48207 * ports - (IN) Ports where group is defined 48208 * group - (IN/OUT) Requested Group ID. If Group ID is not set, 48209 * then API allocates and returns the created 48210 * Group ID. 48211 * flags - internal Group Config flags. 48212 * 48213 * Returns: 48214 * BCM_E_INIT - BCM unit not initialized 48215 * BCM_E_RESOURCE - no select codes will satisfy qualifier set 48216 * BCM_E_NONE - Success 48217 */ 48218 int 48219 _bcm_esw_field_group_config_create(int unit, 48220 bcm_field_group_config_t *group_config, 48221 uint32 flags) 48222 { 48223 _field_group_add_fsm_t *fsm; /* Group creation state machine. */ 48224 _field_control_t *fc; /* Field control structure. */ 48225 int rv; /* Operation return status. */ 48226 bcm_pbmp_t all_pbmp; 48227 _field_hints_t *f_ht = NULL; 48228 /* Field hints Structure. */ 48229 _field_hint_t *hint_list = NULL; 48230 /* Field Hints Structure. */ 48231 bcm_field_hint_t *hint_entry; 48232 /* Hint Entry. */ 48233 48234 48235 if (NULL == group_config) { 48236 return (BCM_E_PARAM); 48237 } 48238 48239 fsm = NULL; 48240 48241 #if defined(BCM_TOMAHAWK3_SUPPORT) 48242 if ((group_config->flags & BCM_FIELD_GROUP_CREATE_WITH_ID) 48243 && (soc_feature(unit, soc_feature_th3_style_fp)) && 48244 ((group_config->group >= (_FP_INTERNAL_RESERVED_ID_MIN)) 48245 /* coverity[result_independent_of_operands : FALSE] */ 48246 && (group_config->group <= _FP_INTERNAL_RESERVED_ID_MAX))) { 48247 LOG_ERROR(BSL_LS_BCM_FP, 48248 (BSL_META_U(unit, 48249 "FP(unit %d) Error: This Group ID is reserved" 48250 " for internal use\n"), 48251 unit)); 48252 return (BCM_E_PARAM); 48253 } 48254 #endif 48255 48256 /* Both SMALL and LARGE slice combination is not encouraged */ 48257 if (soc_feature(unit, soc_feature_field_ingress_two_slice_types) 48258 && ((group_config->flags & BCM_FIELD_GROUP_CREATE_SMALL) 48259 && (group_config->flags & BCM_FIELD_GROUP_CREATE_LARGE))) { 48260 LOG_ERROR(BSL_LS_BCM_FP, 48261 (BSL_META_U(unit, 48262 "Group hint flags have" 48263 "both SMALL and LARGE\r\n"))); 48264 return (BCM_E_PARAM); 48265 } 48266 48267 #if defined(BCM_TOMAHAWK_SUPPORT) 48268 /* If device supports per-pipe FP configuration, */ 48269 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 48270 rv = _field_control_get(unit, &fc); 48271 if (BCM_FAILURE(rv)) { 48272 return rv; 48273 } 48274 /* Call Flexible Key Extraction programming function for TH IFP. */ 48275 rv = fc->functions.fp_group_add(unit, flags, group_config); 48276 return rv; 48277 } 48278 #endif /* BCM_TOMAHAWK_SUPPORT */ 48279 48280 /* Check if passed group configuration is valid for this device */ 48281 if ((0 == soc_feature(unit, soc_feature_field_ingress_two_slice_types)) 48282 && ((group_config->flags & BCM_FIELD_GROUP_CREATE_SMALL) 48283 || (group_config->flags & BCM_FIELD_GROUP_CREATE_LARGE) 48284 || group_config->hintid != 0)) { 48285 return (BCM_E_UNAVAIL); 48286 } 48287 48288 /* Read device port configuration. */ 48289 BCM_PBMP_CLEAR(all_pbmp); 48290 rv = _bcm_field_valid_pbmp_get(unit, &all_pbmp); 48291 if (BCM_FAILURE(rv)) { 48292 return (rv); 48293 } 48294 48295 rv = _field_control_get(unit, &fc); 48296 if (BCM_FAILURE(rv)) { 48297 goto bcm_error; 48298 } 48299 48300 if (!(group_config->flags & BCM_FIELD_GROUP_CREATE_WITH_ID)) { 48301 /* qset and pri are validated in bcm_field_group_create_mode_id(). */ 48302 rv = _bcm_field_group_id_generate(unit, &group_config->group); 48303 if (BCM_FAILURE(rv)) { 48304 goto bcm_error; 48305 } 48306 } 48307 48308 /* Initialize group creation tracking structure. */ 48309 _FP_XGS3_ALLOC(fsm, sizeof(_field_group_add_fsm_t), 48310 "Group fsm info "); 48311 if (fsm == NULL) { 48312 rv = BCM_E_MEMORY; 48313 goto bcm_error; 48314 } 48315 48316 fsm->fsm_state = _BCM_FP_GROUP_ADD_STATE_START; 48317 fsm->priority = group_config->priority; 48318 fsm->group_id = group_config->group; 48319 fsm->qset = group_config->qset; 48320 fsm->hintid = group_config->hintid; 48321 fsm->action_res_id = group_config->action_res_id; 48322 48323 if (fsm->hintid != 0) { 48324 if (fsm->hintid >= _FP_HINT_ID_MAX) { 48325 LOG_DEBUG(BSL_LS_BCM_FP, 48326 (BSL_META_U(unit, "HintId is out of allowed range\r\n"))); 48327 rv = BCM_E_PARAM; 48328 goto bcm_error; 48329 } 48330 48331 if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, fsm->hintid) == 0) { 48332 LOG_DEBUG(BSL_LS_BCM_FP, 48333 (BSL_META_U(unit, "Trying to attach hintid which is" 48334 " not created\r\n"))); 48335 rv = BCM_E_NOT_FOUND; 48336 goto bcm_error; 48337 } 48338 48339 rv= _field_hints_control_get (unit, group_config->hintid, &f_ht); 48340 if ( (BCM_FAILURE(rv)) || (f_ht == NULL) ){ 48341 LOG_DEBUG(BSL_LS_BCM_FP, 48342 (BSL_META_U(unit,"Hints are not attached to hintid(%d)." 48343 "\r\n"), 48344 group_config->hintid)); 48345 rv = BCM_E_NOT_FOUND; 48346 goto bcm_error; 48347 } 48348 48349 if (BCM_FIELD_QSET_TEST(fsm->qset, 48350 bcmFieldQualifyStageExternal)) { 48351 LOG_DEBUG(BSL_LS_BCM_FP, 48352 (BSL_META_U(unit,"Unsupported hint type attached" 48353 "to hintid(%d).\r\n"), 48354 group_config->hintid)); 48355 rv = BCM_E_PARAM; 48356 goto bcm_error; 48357 } 48358 48359 hint_list = f_ht->hints; 48360 while (hint_list != NULL) { 48361 hint_entry = hint_list->hint; 48362 if (hint_entry != NULL) { 48363 if ((BCM_FIELD_QSET_TEST(fsm->qset, 48364 bcmFieldQualifyStageEgress)) || 48365 (BCM_FIELD_QSET_TEST(fsm->qset, 48366 bcmFieldQualifyStageLookup))) { 48367 48368 if(!((hint_entry->hint_type == 48369 bcmFieldHintTypeGroupAutoExpansion) && 48370 (hint_entry->flags == 48371 BCM_FIELD_GROUP_MAX_SIZE_HARD_LIMIT) ) ) { 48372 LOG_DEBUG(BSL_LS_BCM_FP, 48373 (BSL_META_U(unit,"Unsupported hint type attached" 48374 "to hintid(%d).\r\n"), 48375 group_config->hintid)); 48376 rv = BCM_E_PARAM; 48377 goto bcm_error; /*error*/ 48378 } 48379 } 48380 } 48381 hint_list = hint_list->next; 48382 } /* while (hint_list != NULL) */ 48383 } 48384 48385 /* Apply group member port configuration */ 48386 if (group_config->flags & BCM_FIELD_GROUP_CREATE_WITH_PORT) { 48387 BCM_PBMP_ASSIGN(fsm->pbmp, group_config->ports); 48388 } else { 48389 BCM_PBMP_ASSIGN(fsm->pbmp, all_pbmp); 48390 } 48391 48392 /* Apply group mode configuration */ 48393 if (group_config->flags & BCM_FIELD_GROUP_CREATE_WITH_MODE) { 48394 fsm->mode = group_config->mode; 48395 } else { 48396 fsm->mode = bcmFieldGroupModeDefault; 48397 } 48398 48399 /* Apply slice selection configuration */ 48400 if (group_config->flags & BCM_FIELD_GROUP_CREATE_SMALL) { 48401 fsm->flags |= _BCM_FP_GROUP_ADD_SMALL_SLICE; 48402 } else if (group_config->flags & BCM_FIELD_GROUP_CREATE_LARGE) { 48403 fsm->flags |= _BCM_FP_GROUP_ADD_LARGE_SLICE; 48404 } 48405 48406 if (flags & _FP_GROUP_CONFIG_VALIDATE) { 48407 fsm->flags |= _FP_GROUP_CONFIG_VALIDATE; 48408 } 48409 48410 /* Add FP group. */ 48411 rv = _bcm_field_group_add(unit, fsm); 48412 48413 #ifdef BCM_WARM_BOOT_SUPPORT 48414 SOC_CONTROL_LOCK(unit); 48415 SOC_CONTROL(unit)->scache_dirty = 1; 48416 SOC_CONTROL_UNLOCK(unit); 48417 #endif 48418 48419 bcm_error: 48420 if (fsm != NULL) { 48421 sal_free(fsm); 48422 } 48423 return (rv); 48424 } 48425 48426 int 48427 _bcm_esw_field_group_config_destroy(int unit, 48428 bcm_field_group_t group, 48429 uint32 flags) 48430 { 48431 int rv = BCM_E_NONE; 48432 _field_control_t *fc = NULL; 48433 _field_group_t *fg = NULL; 48434 _field_stage_id_t stage = -1; 48435 48436 FP_LOCK(unit); 48437 48438 rv = _field_control_get(unit, &fc); 48439 if (BCM_FAILURE(rv)) { 48440 goto error; 48441 } 48442 48443 rv = _field_group_get(unit, group, &fg); 48444 if (BCM_FAILURE(rv)) { 48445 goto error; 48446 } 48447 48448 stage = fg->stage_id; 48449 48450 if ((flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC) && 48451 (_BCM_FIELD_STAGE_EXACTMATCH != stage)){ 48452 /* FLOWTRACKER SPECIFIC flag should be used for EXACTMATCH Stage only */ 48453 rv = BCM_E_PARAM; 48454 goto error; 48455 } 48456 48457 if (soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0)) { 48458 if (_BCM_FIELD_STAGE_EXACTMATCH == stage) { 48459 /* Validation for internal flag for FLOWTRACKER module */ 48460 if (0 == (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC)) { 48461 rv = BCM_E_CONFIG; 48462 goto error; 48463 } 48464 48465 /* Check to Restrict EM for internal use */ 48466 if (_FP_FLOWTRACKER_RESERVED_EM_GID_AFTER_SHIFT != 48467 ((uint32)group >> (_FP_FLOWTRACKER_RESERVED_EM_GID_SHIFT_VAL))) { 48468 rv = BCM_E_CONFIG; 48469 goto error; 48470 } 48471 48472 if (0 == (fc->flags & _FP_EXACTMATCH_STAGE_SKIP_DETACH)) { 48473 rv = BCM_E_INTERNAL; 48474 goto error; 48475 } 48476 } 48477 } else { 48478 if (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC) { 48479 /* FLOWTRACKER SPECIFIC flag should be used only if soc property FLOWTRACKER_ENABLE is enabled */ 48480 rv = BCM_E_PARAM; 48481 goto error; 48482 } 48483 } 48484 48485 rv = bcm_esw_field_group_destroy(unit, group); 48486 if (BCM_FAILURE(rv)) { 48487 goto error; 48488 } 48489 48490 if ((_BCM_FIELD_STAGE_EXACTMATCH == stage) && 48491 (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC)) { 48492 /* Check whether any group is present under EM stage */ 48493 for (fg = fc->groups; 48494 (NULL != fg) && (_BCM_FIELD_STAGE_EXACTMATCH != fg->stage_id); 48495 fg = fg->next); 48496 48497 if (NULL == fg) { 48498 /* NO EM group is present. EM flag can be cleared */ 48499 fc->flags &= ~_FP_EXACTMATCH_STAGE_SKIP_DETACH; 48500 } 48501 } 48502 48503 error: 48504 FP_UNLOCK(unit); 48505 return rv; 48506 } 48507 48508 /* 48509 * Function: _bcm_esw_field_group_config_validate 48510 * 48511 * Purpose: 48512 * To verify whether a group can be created with a given qset and mode. 48513 * 48514 * Parameters: 48515 * unit - BCM device number 48516 * gc - Field group config. 48517 * group_mode - Field Group Mode. 48518 * 48519 * Returns: 48520 * BCM_E_XXX - from _bcm_esw_field_group_config_validate() 48521 */ 48522 48523 int _bcm_esw_field_group_config_validate( 48524 int unit, 48525 bcm_field_group_config_t *group_config, 48526 bcm_field_group_mode_t *group_mode) { 48527 48528 int rv = BCM_E_NONE; 48529 _field_group_t *fg = NULL; 48530 uint32 flags = 0; 48531 _field_stage_t *stage_fc; /* Stage field control structure. */ 48532 48533 flags |= _FP_GROUP_CONFIG_VALIDATE; 48534 rv = _bcm_esw_field_group_config_create(unit,group_config, flags); 48535 if (BCM_SUCCESS(rv)) { 48536 48537 /* Search the field control for the Group ID. */ 48538 rv = _field_group_get(unit, group_config->group, &fg); 48539 if (BCM_FAILURE(rv)) { 48540 goto cleanup; 48541 } 48542 /* Get the mode from group */ 48543 rv = _bcm_esw_field_group_mode_get(fg->flags, group_mode); 48544 if (BCM_FAILURE(rv)) { 48545 goto cleanup; 48546 } 48547 48548 /* Retreive Stage Control. */ 48549 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 48550 if (BCM_FAILURE(rv)) { 48551 goto cleanup; 48552 } 48553 48554 #if defined (BCM_TOMAHAWK3_SUPPORT) 48555 if ((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support)) && 48556 (*group_mode == bcmFieldGroupModeIntraSliceDouble) && 48557 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) { 48558 *group_mode = bcmFieldGroupModeSingle; 48559 } 48560 #endif 48561 48562 fg->flags |= _FP_GROUP_CONFIG_VALIDATE; 48563 /* Destroy the group */ 48564 rv = bcm_esw_field_group_destroy(unit, group_config->group); 48565 } 48566 cleanup: 48567 return rv; 48568 } 48569 48570 #if defined(BCM_TRIDENT3_SUPPORT) 48571 int 48572 _bcm_field_action_vlan_actions_add(int unit, 48573 bcm_field_entry_t entry, 48574 bcm_field_action_t action, 48575 bcm_vlan_action_set_t *vlan_set) 48576 { 48577 _field_entry_t *f_ent = NULL; 48578 _field_action_t *fa = NULL; /* Field action descriptor. */ 48579 _field_control_t *fc; /* Field control structure. */ 48580 int rv; /* Operation return status. */ 48581 bcm_vlan_action_set_t *new_action_set = NULL; 48582 48583 if ((vlan_set == NULL) || (action != bcmFieldActionVlanActions)) { 48584 return BCM_E_PARAM; 48585 } 48586 48587 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 48588 48589 BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, 48590 _FP_ENTRY_PRIMARY, &f_ent)); 48591 48592 if (f_ent->group->stage_id != _BCM_FIELD_STAGE_LOOKUP) { 48593 return BCM_E_UNAVAIL; 48594 } 48595 48596 if (f_ent->vlan_action_set == NULL) { 48597 _FP_XGS3_ALLOC(new_action_set, sizeof(bcm_vlan_action_set_t), 48598 "FP Entry VLAN Action set"); 48599 if (new_action_set == NULL) { 48600 return BCM_E_MEMORY; 48601 } 48602 sal_memcpy(new_action_set, vlan_set, sizeof(bcm_vlan_action_set_t)); 48603 f_ent->vlan_action_set = new_action_set; 48604 } else { 48605 bcm_vlan_action_set_t *old_vlan_set; 48606 48607 old_vlan_set = f_ent->vlan_action_set; 48608 if (!sal_memcmp(old_vlan_set, vlan_set, sizeof(bcm_vlan_action_set_t))) { 48609 return BCM_E_NONE; 48610 } 48611 } 48612 48613 /* 48614 * Allocate the action descriptor, params are not valid here. 48615 */ 48616 rv = _field_action_alloc(unit, action, 0, 0, 0, 0, 0, 0, &fa); 48617 if (BCM_FAILURE(rv)) { 48618 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 48619 "Error: Action alloc failure.\n\r"))); 48620 goto cleanup; 48621 } 48622 48623 /* 48624 * Add action to entry actions list. 48625 */ 48626 rv = _field_action_add(unit, fc, entry, fa); 48627 if (BCM_FAILURE(rv)) { 48628 goto cleanup; 48629 } 48630 48631 cleanup: 48632 if (BCM_FAILURE(rv)) { 48633 if (new_action_set != NULL) { 48634 sal_free(new_action_set); 48635 f_ent->vlan_action_set = NULL; 48636 } 48637 48638 if (fa != NULL) { 48639 sal_free(fa); 48640 } 48641 } 48642 48643 return rv; 48644 } 48645 48646 int 48647 _bcm_field_action_vlan_actions_get(int unit, 48648 bcm_field_entry_t entry, 48649 bcm_field_action_t action, 48650 bcm_vlan_action_set_t *vlan_action_set) 48651 { 48652 _field_entry_t *f_ent = NULL; 48653 48654 if ((vlan_action_set == NULL) || (action != bcmFieldActionVlanActions)) { 48655 return BCM_E_PARAM; 48656 } 48657 48658 BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, 48659 _FP_ENTRY_PRIMARY, &f_ent)); 48660 48661 if (f_ent->group->stage_id != _BCM_FIELD_STAGE_LOOKUP) { 48662 return BCM_E_UNAVAIL; 48663 } 48664 48665 if (f_ent->vlan_action_set != NULL) { 48666 sal_memcpy(vlan_action_set, f_ent->vlan_action_set, 48667 sizeof(bcm_vlan_action_set_t)); 48668 } else { 48669 return BCM_E_NOT_FOUND; 48670 } 48671 48672 return BCM_E_NONE; 48673 } 48674 48675 STATIC int 48676 _field_td3_em_entry_profile_dump (int unit, _field_stage_t *stage_fc, _field_group_t *fg, _field_entry_t *f_ent) 48677 { 48678 exact_match_2_entry_t ebuf_nar; /* Narrow Entry Buffer. */ 48679 exact_match_4_entry_t ebuf_wide; /* Wide Entry Buffer. */ 48680 _field_entry_t *f_ent_part = NULL; /* Field Entry Part. */ 48681 uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0}; 48682 /* Temp Buffer One. */ 48683 uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0}; 48684 /* Temp Buffer Two. */ 48685 soc_mem_t mem = INVALIDm; 48686 int eindex = 0; /* Entry Index inn UFT memory. */ 48687 static soc_mem_t em_entry_nar_mem[_FP_MAX_NUM_PIPES] = { 48688 EXACT_MATCH_2_PIPE0m, 48689 EXACT_MATCH_2_PIPE1m 48690 }; 48691 static soc_mem_t em_entry_wide_mem[_FP_MAX_NUM_PIPES] = { 48692 EXACT_MATCH_4_PIPE0m, 48693 EXACT_MATCH_4_PIPE1m 48694 }; 48695 uint32 *bufp = NULL; /* Hardware Buffer Ptr. */ 48696 uint32 qp_idx = -1; /* Qos Actions Profile Index.*/ 48697 uint32 ap_idx = -1; /* Actions Profile Index. */ 48698 48699 if ((NULL == stage_fc) || (NULL == fg) || (NULL == f_ent)) { 48700 return BCM_E_PARAM; 48701 } 48702 48703 /* Get Hardware Buffer Pointer and memory identifier. */ 48704 if ((fg->em_mode == _FieldExactMatchMode128) || 48705 (fg->em_mode == _FieldExactMatchMode160)) { 48706 bufp = (uint32 *)&ebuf_nar; 48707 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 48708 mem = EXACT_MATCH_2m; 48709 } else { 48710 mem = em_entry_nar_mem[fg->instance]; 48711 } 48712 } else { 48713 bufp = (uint32 *)&ebuf_wide; 48714 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 48715 mem = EXACT_MATCH_4m; 48716 } else { 48717 mem = em_entry_wide_mem[fg->instance]; 48718 } 48719 } 48720 48721 /* Initialize exact match entries. */ 48722 sal_memcpy(bufp, soc_mem_entry_null(unit, mem), 48723 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 48724 48725 /* Initialize exact match entries. */ 48726 soc_mem_field32_set(unit, mem, bufp, KEY_TYPEf, fg->em_mode); 48727 /* Set Exact Match Entry */ 48728 if (fg->em_mode == _FieldExactMatchMode128) { 48729 48730 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 48731 TD3_EM_MODE128_KEY_PART0_SIZE); 48732 soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf); 48733 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 48734 TD3_EM_MODE128_KEY_PART0_SIZE, 48735 TD3_EM_MODE128_KEY_PART1_SIZE); 48736 soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf); 48737 48738 } else if (fg->em_mode == _FieldExactMatchMode160) { 48739 48740 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 48741 TD3_EM_MODE160_KEY_PART0_SIZE); 48742 soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf); 48743 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 48744 TD3_EM_MODE160_KEY_PART0_SIZE, 48745 TD3_EM_MODE160_KEY_PART1_SIZE); 48746 soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf); 48747 48748 } else if (fg->em_mode == _FieldExactMatchMode320) { 48749 48750 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 48751 TD3_EM_MODE320_KEY_PART0_SIZE); 48752 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf); 48753 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 48754 TD3_EM_MODE320_KEY_PART0_SIZE, 48755 (EM_ENTRY_PART0_KEYSIZE - 48756 TD3_EM_MODE320_KEY_PART0_SIZE)); 48757 48758 /* Key From Second Entry Part. */ 48759 f_ent_part = f_ent + 1; 48760 48761 _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf_temp, 0, 48762 (TD3_EM_MODE320_KEY_PART1_SIZE - 48763 (EM_ENTRY_PART0_KEYSIZE - 48764 TD3_EM_MODE320_KEY_PART0_SIZE))); 48765 BCM_IF_ERROR_RETURN(_bcm_field_th_val_set(tbuf, tbuf_temp, 48766 (EM_ENTRY_PART0_KEYSIZE - 48767 TD3_EM_MODE320_KEY_PART0_SIZE), 48768 (TD3_EM_MODE320_KEY_PART1_SIZE - 48769 (EM_ENTRY_PART0_KEYSIZE - 48770 TD3_EM_MODE320_KEY_PART0_SIZE)))); 48771 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf); 48772 _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf, 48773 (TD3_EM_MODE320_KEY_PART1_SIZE - 48774 (EM_ENTRY_PART0_KEYSIZE - 48775 TD3_EM_MODE320_KEY_PART0_SIZE)), 48776 TD3_EM_MODE320_KEY_PART2_SIZE); 48777 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf); 48778 _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf, 48779 ((TD3_EM_MODE320_KEY_PART1_SIZE - 48780 (EM_ENTRY_PART0_KEYSIZE - 48781 TD3_EM_MODE320_KEY_PART0_SIZE)) + 48782 TD3_EM_MODE320_KEY_PART2_SIZE), 48783 TD3_EM_MODE320_KEY_PART3_SIZE); 48784 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_3_ONLYf, tbuf); 48785 48786 } 48787 48788 BCM_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &eindex, bufp, bufp, 0)); 48789 48790 /* Get Qos and Action Profile Index Allocated From Entry. */ 48791 if (fg->em_mode == _FieldExactMatchMode128) { 48792 qp_idx = soc_mem_field32_get(unit, mem, 48793 bufp, MODE128__QOS_PROFILE_IDf); 48794 ap_idx = soc_mem_field32_get(unit, mem, 48795 bufp, MODE128__DATA_TYPEf); 48796 } else if (fg->em_mode == _FieldExactMatchMode160) { 48797 qp_idx = soc_mem_field32_get(unit, mem, 48798 bufp, MODE160__QOS_PROFILE_IDf); 48799 ap_idx = soc_mem_field32_get(unit, mem, 48800 bufp, MODE160__DATA_TYPEf); 48801 } else if (fg->em_mode == _FieldExactMatchMode320) { 48802 qp_idx = soc_mem_field32_get(unit, mem, 48803 bufp, MODE320__QOS_PROFILE_IDf); 48804 ap_idx = soc_mem_field32_get(unit, mem, 48805 bufp, MODE320__DATA_TYPEf); 48806 } 48807 48808 LOG_CLI((BSL_META_U(unit, 48809 " {Action_profile_idx=%d"), ap_idx)); 48810 LOG_CLI((BSL_META_U(unit, 48811 " Qos_action_profile_idx=%d }\n"), qp_idx)); 48812 48813 return BCM_E_NONE; 48814 } 48815 #endif /* BCM_TRIDENT3_SUPPORT */ 48816 48817 #if defined(BCM_TOMAHAWK3_SUPPORT) 48818 STATIC int 48819 _field_th3_em_entry_profile_dump (int unit, _field_stage_t *stage_fc, _field_group_t *fg, _field_entry_t *f_ent) 48820 { 48821 exact_match_2_entry_t ebuf_nar; /* Narrow Entry Buffer. */ 48822 exact_match_4_entry_t ebuf_wide; /* Wide Entry Buffer. */ 48823 _field_entry_t *f_ent_part = NULL; /* Field Entry Part. */ 48824 uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0}; 48825 /* Temp Buffer One. */ 48826 uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0}; 48827 /* Temp Buffer Two. */ 48828 soc_mem_t mem = INVALIDm; 48829 int eindex = 0; /* Entry Index inn UFT memory. */ 48830 static soc_mem_t em_entry_nar_mem[_FP_MAX_NUM_PIPES] = { 48831 EXACT_MATCH_2_PIPE0m, 48832 EXACT_MATCH_2_PIPE1m 48833 }; 48834 static soc_mem_t em_entry_wide_mem[_FP_MAX_NUM_PIPES] = { 48835 EXACT_MATCH_4_PIPE0m, 48836 EXACT_MATCH_4_PIPE1m 48837 }; 48838 uint32 *bufp = NULL; /* Hardware Buffer Ptr. */ 48839 uint32 qp_idx = -1; /* Qos Actions Profile Index.*/ 48840 uint32 ap_idx = -1; /* Actions Profile Index. */ 48841 48842 if ((NULL == stage_fc) || (NULL == fg) || (NULL == f_ent)) { 48843 return BCM_E_PARAM; 48844 } 48845 48846 /* Get Hardware Buffer Pointer and memory identifier. */ 48847 if ((fg->em_mode == _FieldExactMatchMode128) || 48848 (fg->em_mode == _FieldExactMatchMode160)) { 48849 bufp = (uint32 *)&ebuf_nar; 48850 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 48851 mem = EXACT_MATCH_2m; 48852 } else { 48853 mem = em_entry_nar_mem[fg->instance]; 48854 } 48855 } else { 48856 bufp = (uint32 *)&ebuf_wide; 48857 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 48858 mem = EXACT_MATCH_4m; 48859 } else { 48860 mem = em_entry_wide_mem[fg->instance]; 48861 } 48862 } 48863 48864 /* Initialize exact match entries. */ 48865 sal_memcpy(bufp, soc_mem_entry_null(unit, mem), 48866 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 48867 48868 /* Initialize exact match entries. */ 48869 soc_mem_field32_set(unit, mem, bufp, KEY_TYPEf, fg->em_mode); 48870 /* Set Exact Match Entry */ 48871 if (fg->em_mode == _FieldExactMatchMode128) { 48872 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 48873 TH3_EM_MODE128_KEY_PART0_SIZE); 48874 soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf); 48875 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 48876 TH3_EM_MODE128_KEY_PART0_SIZE, 48877 TH3_EM_MODE128_KEY_PART1_SIZE); 48878 soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf); 48879 } else if (fg->em_mode == _FieldExactMatchMode160) { 48880 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 48881 TH3_EM_MODE160_KEY_PART0_SIZE); 48882 soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf); 48883 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 48884 TH3_EM_MODE160_KEY_PART0_SIZE, 48885 TH3_EM_MODE160_KEY_PART1_SIZE); 48886 soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf); 48887 } else if (fg->em_mode == _FieldExactMatchMode320) { 48888 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 48889 TH3_EM_MODE320_KEY_PART0_SIZE); 48890 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf); 48891 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 48892 TH3_EM_MODE320_KEY_PART0_SIZE, 48893 (EM_ENTRY_PART0_KEYSIZE - 48894 TH3_EM_MODE320_KEY_PART0_SIZE)); 48895 48896 /* Key From Second Entry Part. */ 48897 f_ent_part = f_ent + 1; 48898 48899 _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf_temp, 0, 48900 (TH3_EM_MODE320_KEY_PART1_SIZE - 48901 (EM_ENTRY_PART0_KEYSIZE - 48902 TH3_EM_MODE320_KEY_PART0_SIZE))); 48903 BCM_IF_ERROR_RETURN(_bcm_field_th_val_set(tbuf, tbuf_temp, 48904 (EM_ENTRY_PART0_KEYSIZE - 48905 TH3_EM_MODE320_KEY_PART0_SIZE), 48906 (TH3_EM_MODE320_KEY_PART1_SIZE - 48907 (EM_ENTRY_PART0_KEYSIZE - 48908 TH3_EM_MODE320_KEY_PART0_SIZE)))); 48909 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf); 48910 _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf, 48911 (TH3_EM_MODE320_KEY_PART1_SIZE - 48912 (EM_ENTRY_PART0_KEYSIZE - 48913 TH3_EM_MODE320_KEY_PART0_SIZE)), 48914 TH3_EM_MODE320_KEY_PART2_SIZE); 48915 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf); 48916 } 48917 48918 BCM_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &eindex, bufp, bufp, 0)); 48919 48920 /* Get Qos and Action Profile Index Allocated From Entry. */ 48921 if (fg->em_mode == _FieldExactMatchMode128) { 48922 qp_idx = soc_mem_field32_get(unit, mem, 48923 bufp, MODE128__QOS_PROFILE_IDf); 48924 ap_idx = soc_mem_field32_get(unit, mem, 48925 bufp, MODE128__DATA_TYPEf); 48926 } else if (fg->em_mode == _FieldExactMatchMode160) { 48927 qp_idx = soc_mem_field32_get(unit, mem, 48928 bufp, MODE160__QOS_PROFILE_IDf); 48929 ap_idx = soc_mem_field32_get(unit, mem, 48930 bufp, MODE160__DATA_TYPEf); 48931 } else if (fg->em_mode == _FieldExactMatchMode320) { 48932 qp_idx = soc_mem_field32_get(unit, mem, 48933 bufp, MODE320__QOS_PROFILE_IDf); 48934 ap_idx = soc_mem_field32_get(unit, mem, 48935 bufp, MODE320__DATA_TYPEf); 48936 } 48937 48938 LOG_CLI((BSL_META_U(unit, 48939 " {Action_profile_idx=%d"), ap_idx)); 48940 LOG_CLI((BSL_META_U(unit, 48941 " Qos_action_profile_idx=%d }\n"), qp_idx)); 48942 48943 return BCM_E_NONE; 48944 } 48945 #endif /* BCM_TOMAHAWK3_SUPPORT */ 48946 48947 #if defined(BCM_TOMAHAWK_SUPPORT) 48948 STATIC int 48949 _field_th_em_entry_profile_dump (int unit, _field_stage_t *stage_fc, _field_group_t *fg, _field_entry_t *f_ent) 48950 { 48951 exact_match_2_entry_t ebuf_nar; /* Narrow Entry Buffer. */ 48952 exact_match_4_entry_t ebuf_wide; /* Wide Entry Buffer. */ 48953 uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0}; 48954 /* Temp Buffer One. */ 48955 uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0}; 48956 /* Temp Buffer Two. */ 48957 soc_mem_t mem = INVALIDm; 48958 int eindex = 0; /* Entry Index inn UFT memory. */ 48959 _field_entry_t *f_ent_part = NULL; 48960 static soc_mem_t em_entry_nar_mem[_FP_MAX_NUM_PIPES] = { 48961 EXACT_MATCH_2_PIPE0m, 48962 EXACT_MATCH_2_PIPE1m, 48963 EXACT_MATCH_2_PIPE2m, 48964 EXACT_MATCH_2_PIPE3m, 48965 }; 48966 static soc_mem_t em_entry_wide_mem[_FP_MAX_NUM_PIPES] = { 48967 EXACT_MATCH_4_PIPE0m, 48968 EXACT_MATCH_4_PIPE1m, 48969 EXACT_MATCH_4_PIPE2m, 48970 EXACT_MATCH_4_PIPE3m, 48971 }; 48972 uint32 *bufp = NULL; /* Hardware Buffer Ptr. */ 48973 uint32 qp_idx = -1; /* Qos Actions Profile Index.*/ 48974 uint32 ap_idx = -1; /* Actions Profile Index. */ 48975 48976 if ((NULL == stage_fc) || (NULL == fg) || (NULL == f_ent)) { 48977 return BCM_E_PARAM; 48978 } 48979 48980 /* Get Hardware Buffer Pointer and memory identifier. */ 48981 if ((fg->em_mode == _FieldExactMatchMode128) || 48982 (fg->em_mode == _FieldExactMatchMode160)) { 48983 bufp = (uint32 *)&ebuf_nar; 48984 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 48985 mem = EXACT_MATCH_2m; 48986 } else { 48987 mem = em_entry_nar_mem[fg->instance]; 48988 } 48989 } else { 48990 bufp = (uint32 *)&ebuf_wide; 48991 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 48992 mem = EXACT_MATCH_4m; 48993 } else { 48994 mem = em_entry_wide_mem[fg->instance]; 48995 } 48996 } 48997 48998 /* Initialize exact match entries. */ 48999 sal_memcpy(bufp, soc_mem_entry_null(unit, mem), 49000 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 49001 49002 /* Set Exact Match Entry Search Key. */ 49003 if (fg->em_mode == _FieldExactMatchMode128) { 49004 49005 soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode); 49006 soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode); 49007 soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1); 49008 soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1); 49009 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 49010 EM_MODE128_KEY_PART0_SIZE); 49011 soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf); 49012 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 49013 EM_MODE128_KEY_PART0_SIZE, 49014 EM_MODE128_KEY_PART1_SIZE); 49015 soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf); 49016 49017 } else if (fg->em_mode == _FieldExactMatchMode160) { 49018 49019 soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode); 49020 soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode); 49021 soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1); 49022 soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1); 49023 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 49024 EM_MODE160_KEY_PART0_SIZE); 49025 soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf); 49026 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 49027 EM_MODE160_KEY_PART0_SIZE, 49028 EM_MODE160_KEY_PART1_SIZE); 49029 soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf); 49030 49031 } else if (fg->em_mode == _FieldExactMatchMode320) { 49032 49033 soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode); 49034 soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode); 49035 soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_2f, fg->em_mode); 49036 soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_3f, fg->em_mode); 49037 soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1); 49038 soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1); 49039 soc_mem_field32_set(unit, mem, bufp, VALID_2f, 1); 49040 soc_mem_field32_set(unit, mem, bufp, VALID_3f, 1); 49041 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0, 49042 EM_MODE320_KEY_PART0_SIZE); 49043 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf); 49044 _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 49045 EM_MODE320_KEY_PART0_SIZE, 59); 49046 49047 /* Key From Second Entry Part. */ 49048 f_ent_part = f_ent + 1; 49049 _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf_temp, 0, 42); 49050 BCM_IF_ERROR_RETURN(_bcm_field_th_val_set(tbuf, tbuf_temp, 59, 42)); 49051 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf);; 49052 _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf, 42, 49053 EM_MODE320_KEY_PART2_SIZE); 49054 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf); 49055 _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf, 143, 17); 49056 soc_mem_field_set(unit, mem, bufp, MODE320__KEY_3_ONLYf, tbuf); 49057 49058 } 49059 49060 BCM_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &eindex, bufp, bufp, 0)); 49061 49062 /* Get Qos and Action Profile Index Allocated From Entry. */ 49063 if (fg->em_mode == _FieldExactMatchMode128) { 49064 qp_idx = soc_mem_field32_get(unit, mem, 49065 bufp, MODE128__QOS_PROFILE_IDf); 49066 ap_idx = soc_mem_field32_get(unit, mem, 49067 bufp, MODE128__ACTION_PROFILE_IDf); 49068 } else if (fg->em_mode == _FieldExactMatchMode160) { 49069 qp_idx = soc_mem_field32_get(unit, mem, 49070 bufp, MODE160__QOS_PROFILE_IDf); 49071 ap_idx = soc_mem_field32_get(unit, mem, 49072 bufp, MODE160__ACTION_PROFILE_IDf); 49073 } else if (fg->em_mode == _FieldExactMatchMode320) { 49074 qp_idx = soc_mem_field32_get(unit, mem, 49075 bufp, MODE320__QOS_PROFILE_IDf); 49076 ap_idx = soc_mem_field32_get(unit, mem, 49077 bufp, MODE320__ACTION_PROFILE_IDf); 49078 } 49079 49080 LOG_CLI((BSL_META_U(unit, 49081 " {Action_profile_idx=%d"), ap_idx)); 49082 LOG_CLI((BSL_META_U(unit, 49083 " Qos_action_profile_idx=%d }\n"), qp_idx)); 49084 49085 return BCM_E_NONE; 49086 } 49087 49088 #endif 49089 /* 49090 * Function: _bcm_field_entry_dump 49091 * 49092 * Purpose: 49093 * Show contents of a field entry. 49094 * 49095 * Parameters: 49096 * unit - BCM device number 49097 * entry - Field entry to dump 49098 * 49099 * Returns: 49100 * Nothing. 49101 */ 49102 int 49103 _bcm_esw_field_entry_dump(int unit, bcm_field_entry_t entry, int stage) 49104 { 49105 int parts_count = 0; 49106 _field_stage_t *stage_fc = NULL; /* Field Stage Control. */ 49107 _field_group_t *fg; 49108 _field_action_t *fa; 49109 _field_entry_t *f_ent; 49110 bcm_pbmp_t pbmp; 49111 uint8 idx; 49112 int rv; 49113 char buf_pbmp[SOC_PBMP_FMT_LEN]; 49114 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 49115 defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 49116 bcm_policer_t policer_id = 0; 49117 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT || 49118 BCM_APACHE_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 49119 49120 FP_LOCK(unit); 49121 49122 rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent); 49123 if (BCM_FAILURE(rv)) { 49124 FP_UNLOCK(unit); 49125 return (rv); 49126 } 49127 49128 #if defined(BCM_TOMAHAWK_SUPPORT) 49129 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 49130 (_BCM_FIELD_STAGE_CLASS == f_ent->group->stage_id)) { 49131 rv = _bcm_field_th_class_entry_dump(unit,f_ent); 49132 FP_UNLOCK(unit); 49133 return (rv); 49134 } 49135 #endif /* BCM_TOMAHAWK_SUPPORT */ 49136 49137 fg = f_ent->group; 49138 LOG_CLI((BSL_META_U(unit, 49139 "EID 0x%08x: gid=0x%x,\n"), f_ent->eid, fg->gid)); 49140 49141 /* Retreive Stage Control. */ 49142 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 49143 if (BCM_FAILURE(rv)) { 49144 FP_UNLOCK(unit); 49145 return (rv); 49146 } 49147 49148 /* Get number of entry parts. */ 49149 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 49150 fg->flags, &parts_count); 49151 if (BCM_FAILURE(rv)) { 49152 FP_UNLOCK(unit); 49153 return (rv); 49154 } 49155 49156 #if defined(BCM_TOMAHAWK_SUPPORT) 49157 /* Display Entry info for multi-pipe supported devices */ 49158 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 49159 ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || 49160 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) || 49161 (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id))) { 49162 rv = _bcm_field_th_entry_phys_dump(unit, f_ent); 49163 if (BCM_FAILURE(rv)) { 49164 FP_UNLOCK(unit); 49165 return (rv); 49166 } 49167 49168 if ((-1 != stage) && (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) { 49169 #if defined(BCM_TOMAHAWK3_SUPPORT) 49170 if(soc_feature(unit, soc_feature_th3_style_fp)) { 49171 rv = _field_th3_em_entry_profile_dump(unit, stage_fc, fg, f_ent); 49172 if (BCM_FAILURE(rv)) { 49173 FP_UNLOCK(unit); 49174 return (rv); 49175 } 49176 } else 49177 #endif 49178 #if defined(BCM_TRIDENT3_SUPPORT) 49179 if (soc_feature(unit, soc_feature_td3_style_fp)) { 49180 rv = _field_td3_em_entry_profile_dump(unit, stage_fc, fg, f_ent); 49181 if (BCM_FAILURE(rv)) { 49182 FP_UNLOCK(unit); 49183 return (rv); 49184 } 49185 } else 49186 #endif 49187 { 49188 rv = _field_th_em_entry_profile_dump(unit, stage_fc, fg, f_ent); 49189 if (BCM_FAILURE(rv)) { 49190 FP_UNLOCK(unit); 49191 return (rv); 49192 } 49193 } 49194 } 49195 } else 49196 #endif /* BCM_TOMAHAWK_SUPPORT */ 49197 { 49198 /* Dump the primary entry. */ 49199 for(idx = 0; idx < parts_count; idx++) { 49200 _field_entry_phys_dump(unit, f_ent + idx, idx); 49201 } 49202 } 49203 /* Display action data */ 49204 for(idx = 0; idx < parts_count; idx++) { 49205 fa = f_ent[idx].actions; 49206 while (fa != NULL) { 49207 LOG_CLI((BSL_META_U(unit, 49208 " action="))); 49209 if ((fa->action == bcmFieldActionEgressMask) || 49210 (fa->action == bcmFieldActionEgressPortsAdd) || 49211 (fa->action == bcmFieldActionRedirectPbmp) || 49212 (fa->action == bcmFieldActionRedirectBcastPbmp)) { 49213 rv = bcm_esw_field_action_ports_get (unit, f_ent->eid, fa->action, &pbmp); 49214 if (BCM_FAILURE(rv)) { 49215 FP_UNLOCK(unit); 49216 return (rv); 49217 } 49218 LOG_CLI((BSL_META("{act=%s, pbmp=%s %s"), 49219 _field_action_name(fa->action),SOC_PBMP_FMT(pbmp, buf_pbmp), 49220 (fa->flags & _FP_ACTION_DIRTY) ? ", Dirty" : "")); 49221 if (stage != -1) { 49222 LOG_CLI((BSL_META(", ActionFlags=%08x "), 49223 fa->flags)); 49224 if (!(fa->flags & _FP_ACTION_DIRTY)) { 49225 LOG_CLI((BSL_META(", Redirection_Profile=%d "), 49226 fa->hw_index)); 49227 } 49228 } 49229 LOG_CLI((BSL_META_U(unit, 49230 "}"))); 49231 49232 } else { 49233 _field_action_dump (fa); 49234 } 49235 LOG_CLI((BSL_META_U(unit, 49236 "\n"))); 49237 fa = fa->next; 49238 } 49239 } 49240 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 49241 defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 49242 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit) || 49243 SOC_IS_GREYHOUND2(unit)) { 49244 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 49245 if (f_ent->global_meter_policer.pid) { 49246 policer_id = f_ent->global_meter_policer.pid; 49247 } 49248 LOG_CLI((BSL_META_U(unit, 49249 " Global Meter policer=0x%x"), policer_id)); 49250 } 49251 } 49252 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT || 49253 BCM_APACHE_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 49254 #if defined(BCM_TRIUMPH3_SUPPORT) 49255 if (SOC_IS_TRIUMPH3(unit)) { 49256 if (_BCM_FIELD_STAGE_EXTERNAL == f_ent->group->stage_id) { 49257 if (f_ent->global_meter_policer.pid) { 49258 policer_id = f_ent->global_meter_policer.pid; 49259 } 49260 LOG_CLI((BSL_META_U(unit, 49261 " Global Meter policer=%x"), policer_id)); 49262 } 49263 } 49264 #endif 49265 49266 /* Display entry's meter. */ 49267 LOG_CLI((BSL_META_U(unit, 49268 " policer="))); 49269 _field_policers_dump(unit, f_ent); 49270 LOG_CLI((BSL_META_U(unit, 49271 "\n"))); 49272 49273 #if defined (BCM_TRIDENT2PLUS_SUPPORT) 49274 /* Display Oam Stat Actions */ 49275 if (soc_feature(unit, soc_feature_fp_based_oam)) { 49276 rv = _field_oam_stat_action_dump (unit, f_ent); 49277 if (BCM_FAILURE(rv)) { 49278 FP_UNLOCK(unit); 49279 return (rv); 49280 } 49281 } 49282 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 49283 49284 /* Display entry's counter. */ 49285 LOG_CLI((BSL_META_U(unit, 49286 " statistics="))); 49287 rv = _field_stat_dump(unit, f_ent); 49288 if (BCM_FAILURE(rv)) { 49289 FP_UNLOCK(unit); 49290 return (rv); 49291 } 49292 LOG_CLI((BSL_META_U(unit, 49293 "\n"))); 49294 49295 FP_UNLOCK(unit); 49296 return (BCM_E_NONE); 49297 } 49298 /* 49299 * Function: _bcm_field_group_dump 49300 * 49301 * Purpose: 49302 * Show contents of a field group. 49303 * 49304 * Parameters: 49305 * unit - BCM device number 49306 * group - Field group to dump 49307 * stage - -1 for print all groups otherwise stage id 49308 * 49309 * Returns: 49310 * Nothing. 49311 */ 49312 int 49313 _bcm_esw_field_group_dump(int unit, bcm_field_group_t group, int stage) 49314 { 49315 _field_stage_t *stage_fc; 49316 _field_group_t *fg; 49317 int enable = 0; 49318 int parts_count = 0; 49319 int idx; 49320 char buf[SOC_PBMP_FMT_LEN]; 49321 int rv; 49322 int entry_count; 49323 int entry_index; 49324 bcm_field_entry_t *entry_ids; 49325 49326 FP_LOCK(unit); 49327 49328 #if defined(BCM_TOMAHAWK3_SUPPORT) 49329 if ((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) && 49330 (group == _FP_INTERNAL_RESERVED_EM_ID)) { 49331 FP_UNLOCK(unit); 49332 return BCM_E_NONE; 49333 } 49334 #endif 49335 49336 49337 rv = _field_group_get(unit, group, &fg); 49338 if (BCM_FAILURE(rv)) { 49339 FP_UNLOCK(unit); 49340 return (rv); 49341 } 49342 49343 #if defined(BCM_TOMAHAWK_SUPPORT) 49344 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 49345 (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) { 49346 rv = _bcm_field_th_class_group_dump(unit,fg); 49347 FP_UNLOCK(unit); 49348 return (rv); 49349 } 49350 #endif /* BCM_TOMAHAWK_SUPPORT */ 49351 49352 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 49353 if (BCM_FAILURE(rv)) { 49354 FP_UNLOCK(unit); 49355 return (rv); 49356 } 49357 49358 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 49359 fg->flags, &parts_count); 49360 if (BCM_FAILURE(rv)) { 49361 FP_UNLOCK(unit); 49362 return (rv); 49363 } 49364 49365 if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 49366 (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) { 49367 LOG_CLI((BSL_META_U(unit, 49368 "Quad wide intra-slice group, "))); 49369 } else if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 49370 (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE)) { 49371 if (!((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) || 49372 (soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support))) && 49373 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id))) { 49374 LOG_CLI((BSL_META_U(unit, 49375 "Intra-slice double wide group, "))); 49376 } 49377 } 49378 LOG_CLI((BSL_META_U(unit, 49379 "GID %10d: gid=0x%x, instance=%d mode=%s, stage=%s "), group, 49380 fg->gid, fg->instance, 49381 _field_group_mode_name(unit, fg->flags, stage_fc), 49382 _field_stage_name(stage_fc))); 49383 bcm_esw_field_group_enable_get(unit, group, &enable); 49384 if (enable) { 49385 LOG_CLI((BSL_META_U(unit,"lookup=Enabled, "))); 49386 } else { 49387 LOG_CLI((BSL_META_U(unit,"lookup=Disabled, "))); 49388 } 49389 49390 LOG_CLI((BSL_META_U(unit, 49391 "ActionResId={%d}, "), fg->action_res_id)); 49392 LOG_VERBOSE(BSL_LS_BCM_FP, 49393 (BSL_META_U(unit, 49394 "VMAP={%d %d %d}, "), 49395 fg->vmap_group[0], fg->vmap_group[1], fg->vmap_group[2])); 49396 49397 LOG_CLI((BSL_META_U(unit, 49398 "pbmp={%s}\n"), SOC_PBMP_FMT(fg->pbmp, buf))); 49399 49400 _field_qset_dump(" qset=", fg->qset, ",\n"); 49401 49402 #if defined(BCM_TOMAHAWK_SUPPORT) 49403 if ((soc_feature(unit, soc_feature_td3_style_fp) && 49404 (_BCM_FIELD_STAGE_INGRESS == fg->stage_id)) || 49405 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) || 49406 (_BCM_FIELD_STAGE_FLOWTRACKER) == fg->stage_id) { 49407 _field_aset_dump(" aset=", fg->aset, ",\n"); 49408 } 49409 49410 if (soc_feature(unit, soc_feature_field_preselector_support) && 49411 (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) { 49412 uint8 not_first = 0; 49413 49414 LOG_CLI((BSL_META_U(unit, 49415 " preselectors={"))); 49416 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 49417 if (fg->presel_ent_arr[idx] != NULL) { 49418 if (not_first) { 49419 LOG_CLI((BSL_META_U(unit, ", "))); 49420 } 49421 LOG_CLI((BSL_META_U(unit, "%d"), fg->presel_ent_arr[idx]->presel_id)); 49422 not_first = 1; 49423 } 49424 } 49425 LOG_CLI((BSL_META_U(unit, "}\n\r"))); 49426 } 49427 #endif /* BCM_TOMAHAWK_SUPPORT */ 49428 49429 if (fg->hintid != 0) { 49430 LOG_CLI((BSL_META_U(unit," HintId=%d\n"),fg->hintid)); 49431 } 49432 49433 #if defined(BCM_TOMAHAWK_SUPPORT) 49434 if (soc_feature(unit, soc_feature_field_preselector_support) && 49435 ((_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) || 49436 (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || 49437 (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id))) { 49438 /* Lot of values to print. So we will revisit if there are 49439 * any debugging requirements. */ 49440 for (idx = 0; ((idx < parts_count) && (1 != parts_count)); idx++) { 49441 LOG_CLI((BSL_META_U(unit, 49442 " Qualifiers in Part-%d:"), idx)); 49443 _field_qual_list_dump(" ", fg, idx,",\n"); 49444 } 49445 } else 49446 #endif 49447 if ((_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) || 49448 (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) || 49449 (_BCM_FIELD_STAGE_INGRESS == fg->stage_id)) { 49450 for (idx = 0; idx < parts_count; idx++) { 49451 sal_sprintf(buf, " selcodes[%d]=\n", idx); 49452 _field_selcode_dump(unit, buf, fg->sel_codes + idx, ", ", 49453 fg->stage_id); 49454 _field_qual_list_dump(" ",fg, idx,",\n"); 49455 49456 } 49457 } 49458 49459 LOG_CLI((BSL_META_U(unit,"\n"))); 49460 49461 /* Print the primary slice data. */ 49462 LOG_CLI((BSL_META_U(unit," group_priority= %d\n"), fg->priority)); 49463 49464 LOG_CLI((BSL_META_U(unit," slice_primary ="))); 49465 49466 _field_slice_dump(unit, " ", fg, &fg->slices[0], "\n"); 49467 49468 /* Print the secondary slice data. */ 49469 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 49470 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 49471 LOG_CLI((BSL_META_U(unit," slice_secondary = {slice_number=%d}\n"), 49472 fg->slices[1].slice_number)); 49473 } 49474 49475 /* Print the tertiary slice data. */ 49476 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 49477 LOG_CLI((BSL_META_U(unit," slice_ternary = {slice_number=%d}\n"), 49478 fg->slices[2].slice_number)); 49479 49480 } 49481 #if defined(BCM_TOMAHAWK_SUPPORT) /* BCM_TOMAHAWK_SUPPORT */ 49482 if (soc_feature(unit, soc_feature_field_multi_pipe_support) 49483 && ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || 49484 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) || 49485 (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id))) { 49486 /* Get TH IFP group's status. */ 49487 rv = _bcm_field_th_group_status_calc(unit, fg); 49488 } else 49489 #endif /* !BCM_TOMAHAWK_SUPPORT */ 49490 { 49491 /* Update the numbers of free entries, meters and counters. */ 49492 rv = _bcm_field_group_status_calc(unit, fg); 49493 } 49494 49495 /* Print group used resources status */ 49496 if (BCM_SUCCESS(rv)) { 49497 LOG_CLI((BSL_META_U(unit," group_status="))); 49498 _field_group_status_dump(&fg->group_status); 49499 LOG_CLI((BSL_META_U(unit,"\n"))); 49500 } 49501 49502 #if defined(BCM_TOMAHAWK_SUPPORT) /* BCM_TOMAHAWK_SUPPORT */ 49503 if ((soc_feature(unit, soc_feature_field_multi_pipe_support) && 49504 (-1 != stage)) && 49505 ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || 49506 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id))) { 49507 for (idx = 0; idx < parts_count; idx++) { 49508 LOG_CLI((BSL_META_U(unit, 49509 "Keygen_profile%d=%u\n"), fg->instance, 49510 fg->ext_codes[idx].keygen_index)); 49511 } 49512 } 49513 #endif /* !BCM_TOMAHAWK_SUPPORT */ 49514 49515 /* Print group's entries */ 49516 rv = bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_count); 49517 49518 if (BCM_SUCCESS(rv)) 49519 { 49520 entry_ids = sal_alloc(entry_count * sizeof (bcm_field_entry_t), 49521 "Entry ID array"); 49522 49523 if (entry_ids == NULL) 49524 { 49525 rv = BCM_E_MEMORY; 49526 } 49527 else 49528 { 49529 rv = bcm_esw_field_entry_multi_get(unit, group, entry_count, 49530 entry_ids, &entry_count); 49531 49532 if (BCM_SUCCESS(rv)) 49533 { 49534 for (entry_index = 0; entry_index < entry_count; 49535 ++entry_index) 49536 { 49537 _bcm_esw_field_entry_dump(unit, entry_ids[entry_index], stage); 49538 } 49539 } 49540 49541 sal_free(entry_ids); 49542 } 49543 } 49544 49545 FP_UNLOCK(unit); 49546 return (BCM_E_NONE); 49547 } 49548 49549 /* 49550 * Function: bcm_field_show 49551 * 49552 * Purpose: 49553 * Show current S/W state if compiled in debug mode. 49554 * 49555 * Parameters: 49556 * unit - BCM device number 49557 * pfx - Character string to prefix output lines 49558 * 49559 * Returns: 49560 * Nothing. 49561 */ 49562 int 49563 _bcm_esw_field_show(int unit, const char *pfx, int stage) 49564 { 49565 _field_group_t *fg; 49566 _field_stage_t *stage_fc; 49567 _field_control_t *fc; 49568 int entry_ratio; /* Invalid entries ratio. */ 49569 int rv = 0; 49570 49571 FP_LOCK(unit); 49572 rv = _field_control_get(unit, &fc); 49573 if (BCM_FAILURE(rv)) { 49574 FP_UNLOCK(unit); 49575 return rv; 49576 } 49577 49578 stage_fc = fc->stages; 49579 49580 LOG_CLI((BSL_META_U(unit, 49581 "%s:\tunit %d:\n"), pfx, unit)); 49582 49583 while(stage_fc) { 49584 49585 if ((stage != -1) && 49586 (stage != stage_fc->stage_id)) { 49587 stage_fc = stage_fc->next; 49588 continue; 49589 } 49590 rv = _bcm_field_group_stage_validate(unit, stage_fc->stage_id); 49591 if (BCM_FAILURE(rv)) { 49592 stage_fc = stage_fc->next; 49593 continue; 49594 } 49595 49596 entry_ratio = (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) ? 4: 49597 ((stage_fc->flags & _FP_STAGE_HALF_SLICE) ? 2 : 1); 49598 49599 switch (stage_fc->stage_id) { 49600 case _BCM_FIELD_STAGE_INGRESS: 49601 LOG_CLI((BSL_META_U(unit, 49602 "PIPELINE STAGE INGRESS\n"))); 49603 /* 49604 * 80 bit mode is not supported in HX5 in IFP. 49605 * But IFP_TCAM is still available 80 bit view. 49606 * stage_fc->tcam_sz will be initialized as depth of IFP_TCAM. 49607 * As 160 bit mode is called as Single wide mode, depth has to 49608 * be halved. 49609 */ 49610 { 49611 int tcam_sz; 49612 tcam_sz = soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support) ? 49613 (stage_fc->tcam_sz/2) : (stage_fc->tcam_sz); 49614 LOG_CLI((BSL_META_U(unit, 49615 "%s:\t :tcam_sz=%d(%#x),"), 49616 pfx, tcam_sz/entry_ratio, 49617 tcam_sz/entry_ratio)); 49618 } 49619 break; 49620 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 49621 case _BCM_FIELD_STAGE_LOOKUP: 49622 LOG_CLI((BSL_META_U(unit, 49623 "PIPELINE STAGE LOOKUP\n"))); 49624 LOG_CLI((BSL_META_U(unit, 49625 "%s:\t :tcam_sz=%d(%#x),"), 49626 pfx, stage_fc->tcam_sz/entry_ratio, 49627 stage_fc->tcam_sz/entry_ratio)); 49628 break; 49629 case _BCM_FIELD_STAGE_EGRESS: 49630 LOG_CLI((BSL_META_U(unit, 49631 "PIPELINE STAGE EGRESS\n"))); 49632 LOG_CLI((BSL_META_U(unit, 49633 "%s:\t :tcam_sz=%d(%#x),"), 49634 pfx, stage_fc->tcam_sz/entry_ratio, 49635 stage_fc->tcam_sz/entry_ratio)); 49636 break; 49637 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 49638 case _BCM_FIELD_STAGE_EXTERNAL: 49639 LOG_CLI((BSL_META_U(unit, 49640 "PIPELINE STAGE EXTERNAL\n"))); 49641 LOG_CLI((BSL_META_U(unit, 49642 "%s:\t :tcam_sz=%d(%#x),"), 49643 pfx, stage_fc->tcam_sz, stage_fc->tcam_sz)); 49644 break; 49645 #ifdef BCM_TOMAHAWK_SUPPORT 49646 case _BCM_FIELD_STAGE_EXACTMATCH: 49647 if (soc_feature(unit, soc_feature_field_exact_match_support)) { 49648 LOG_CLI((BSL_META_U(unit, 49649 "PIPELINE STAGE EXACTMATCH\n"))); 49650 LOG_CLI((BSL_META_U(unit, 49651 "%s:\t :tcam_sz=%d(%#x),"), 49652 pfx, stage_fc->tcam_sz, stage_fc->tcam_sz)); 49653 } 49654 break; 49655 #endif 49656 #if defined(BCM_FLOWTRACKER_SUPPORT) 49657 case _BCM_FIELD_STAGE_FLOWTRACKER: 49658 if (soc_feature(unit, soc_feature_field_flowtracker_support)) { 49659 LOG_CLI((BSL_META_U(unit, 49660 "PIPELINE STAGE FLOWTRACKER\n"))); 49661 LOG_CLI((BSL_META_U(unit, 49662 "%s:\t :tcam_sz=%d(%#x),"), 49663 pfx, stage_fc->tcam_sz, stage_fc->tcam_sz)); 49664 } 49665 break; 49666 #endif 49667 49668 default: 49669 break; 49670 } 49671 49672 /* Skip for Stage Class alone. */ 49673 if (stage_fc->stage_id != _BCM_FIELD_STAGE_CLASS) { 49674 LOG_CLI((BSL_META_U(unit, 49675 " tcam_slices=%d,"), stage_fc->tcam_slices)); 49676 LOG_CLI((BSL_META_U(unit, 49677 " tcam_ext_numb=%d,"), fc->tcam_ext_numb)); 49678 LOG_CLI((BSL_META_U(unit, 49679 "\n"))); 49680 } 49681 49682 #ifdef BCM_TOMAHAWK_SUPPORT 49683 if (soc_feature(unit, soc_feature_field_preselector_support) && 49684 (stage_fc->stage_id == stage)) { 49685 _bcm_field_presel_dump(unit, -1, stage); 49686 } 49687 if ((-1 != stage) && (stage_fc->stage_id == _BCM_FIELD_STAGE_CLASS)) { 49688 _field_dump_class(unit, pfx, -1); 49689 } 49690 #endif 49691 stage_fc = stage_fc->next; 49692 49693 } 49694 49695 /* Print the groups, along with their entries. */ 49696 for (fg = fc->groups; fg != NULL ; fg = fg->next) { 49697 if ((stage != -1) && 49698 (stage != fg->stage_id)) { 49699 continue; 49700 } 49701 #if defined(BCM_TOMAHAWK_SUPPORT) 49702 if (soc_feature(unit, soc_feature_field_multi_pipe_support) && 49703 (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) { 49704 /* Don't dump Class Group in 'fp show' command */ 49705 continue; 49706 } 49707 /* 49708 * Don't dump ExactMatch based field configuration related to 49709 * Flowtracker module if soc property FLOWTRACKER_ENABLE is enabled. 49710 */ 49711 if ((soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0) == 1) && 49712 soc_feature(unit, soc_feature_field_multi_pipe_support) && 49713 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) { 49714 continue; 49715 } 49716 #endif /* BCM_TOMAHAWK_SUPPORT */ 49717 _bcm_esw_field_group_dump(unit, fg->gid, stage); 49718 } 49719 49720 FP_UNLOCK(unit); 49721 return (BCM_E_NONE); 49722 } 49723 /* 49724 * Function: _bcm_esw_field_range_show 49725 * 49726 * Purpose: 49727 * Show current S/W state of field range if compiled in debug mode. 49728 * 49729 * Parameters: 49730 * unit - BCM device number 49731 * pfx - Character string to prefix output lines 49732 * 49733 * Returns: 49734 * Nothing. 49735 */ 49736 int 49737 _bcm_esw_field_range_show(int unit, const char *pfx, int stage) 49738 { 49739 int rv = BCM_E_NONE; 49740 _field_range_t *fr; 49741 _field_stage_t *stage_fc; 49742 _field_control_t *fc; 49743 49744 FP_LOCK(unit); 49745 rv = _field_control_get(unit, &fc); 49746 if (BCM_FAILURE(rv)) { 49747 FP_UNLOCK(unit); 49748 return rv; 49749 } 49750 49751 stage_fc = fc->stages; 49752 49753 while(stage_fc) { 49754 rv = _bcm_field_group_stage_validate(unit, stage_fc->stage_id); 49755 if (BCM_FAILURE(rv)) { 49756 stage_fc = stage_fc->next; 49757 continue; 49758 } 49759 /* Display any range checkers defined. */ 49760 if ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) || 49761 ((_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) && (stage == -1))){ 49762 for (fr = stage_fc->ranges; fr != NULL; fr = fr->next) { 49763 _field_range_dump(pfx, fr); 49764 } 49765 } 49766 stage_fc = stage_fc->next; 49767 } 49768 49769 FP_UNLOCK(unit); 49770 return (BCM_E_NONE); 49771 } 49772 /* 49773 * Function: _bcm_esw_field_udf_show 49774 * 49775 * Purpose: 49776 * Show current S/W state of field range if compiled in debug mode. 49777 * 49778 * Parameters: 49779 * unit - BCM device number 49780 * pfx - Character string to prefix output lines 49781 * 49782 * Returns: 49783 * Nothing. 49784 */ 49785 int 49786 _bcm_esw_field_udf_show(int unit, const char *pfx) 49787 { 49788 _field_control_t *fc; 49789 int idx = 0; 49790 int rv = BCM_E_NONE; 49791 49792 FP_LOCK(unit); 49793 rv = _field_control_get(unit, &fc); 49794 if (BCM_FAILURE(rv)) { 49795 FP_UNLOCK(unit); 49796 return rv; 49797 } 49798 /* Print the any defined UDFs. */ 49799 for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) { 49800 if (fc->udf[idx].valid) { 49801 LOG_CLI((BSL_META_U(unit, 49802 "%s:\tudf %d: use_count=%d, udf_num=%s, user_num=%d\n"), 49803 pfx, idx, fc->udf[idx].use_count, 49804 _field_qual_name(fc->udf[idx].udf_num + _bcmFieldQualifyData0), 49805 fc->udf[idx].user_num)); 49806 } 49807 } 49808 FP_UNLOCK(unit); 49809 return (BCM_E_NONE); 49810 } 49811 49812 /* 49813 * Function: 49814 * _bcm_esw_field_group_info_key_get 49815 * 49816 * Purpose: 49817 * To retrieve qualifier key info for the given group 49818 * 49819 * Parmeters: 49820 * unit - (IN)BCM device number. 49821 * group - (IN)Field group id 49822 * max_parts_count - (IN)Maximum TCAM parts 49823 * qual_offset - (OUT)Qualifier used to select the correct slice 49824 * num_parts_count - (OUT)Number of TCAM parts present for group 49825 * 49826 * Returns: 49827 * BCM_E_XXX 49828 */ 49829 int 49830 _bcm_esw_field_group_info_key_get(int unit, 49831 bcm_field_group_t group, 49832 int max_parts_count, 49833 _bcm_field_group_qual_t **qual_arr, 49834 int *num_parts_count) 49835 { 49836 int rv = BCM_E_NONE; 49837 int part_idx = 0; 49838 _field_group_t *fg = NULL; 49839 49840 if ((NULL == qual_arr) || (NULL == num_parts_count)){ 49841 return BCM_E_PARAM; 49842 } 49843 49844 FP_LOCK(unit); 49845 49846 rv = _field_group_get(unit, group, &fg); 49847 if (BCM_FAILURE(rv)) { 49848 FP_UNLOCK(unit); 49849 return (rv); 49850 } 49851 49852 /* Get number of tcam parts to be read. */ 49853 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 49854 fg->flags, num_parts_count); 49855 if (BCM_FAILURE(rv)) { 49856 FP_UNLOCK(unit); 49857 return (rv); 49858 } 49859 49860 if (*num_parts_count > max_parts_count) { 49861 FP_UNLOCK(unit); 49862 return BCM_E_PARAM; 49863 } 49864 49865 /* Iterate over all entry parts. */ 49866 for (part_idx = 0; part_idx < *num_parts_count; part_idx++) { 49867 sal_memcpy(&qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx], 49868 &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx]), 49869 sizeof(_bcm_field_group_qual_t)); 49870 } 49871 49872 FP_UNLOCK(unit); 49873 return (rv); 49874 } 49875 49876 /* 49877 * Function: 49878 * _bcm_field_slice_idx_allocate 49879 * 49880 * Purpose: 49881 * Allocate free index in slice 49882 * 49883 * Parmeters: 49884 * unit - (IN) BCM device number. 49885 * stage_fc - (IN) Stage field control structure. 49886 * fg - (IN) Field group structure 49887 * fs - (IN) Field slice structure. 49888 * slice_idx - (OUT) slice index allocated. 49889 * 49890 * Returns: 49891 * BCM_E_XXX 49892 */ 49893 STATIC 49894 int _bcm_field_slice_idx_allocate(int unit, 49895 _field_stage_t *stage_fc, 49896 _field_group_t *fg, 49897 _field_slice_t *fs, 49898 uint32 *slice_idx) 49899 { 49900 int rv = BCM_E_NONE; 49901 uint32 idx = 0; 49902 49903 /* 49904 * In External TCAM, each slice has different number of entries 49905 * Also, allocation happens only at Install time 49906 */ 49907 if (fg->stage_id == _BCM_FIELD_STAGE_EXTERNAL) { 49908 idx = _FP_INVALID_INDEX; 49909 } else if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 49910 idx = _FP_INVALID_INDEX; 49911 } else if (fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) { 49912 rv = _field_multimode_slice_idx_alloc(unit, 49913 stage_fc, fg, fs, &idx); 49914 if (rv == BCM_E_RESOURCE) { 49915 rv = _field_multimode_slice_entry_compress(unit, fs); 49916 49917 if (BCM_FAILURE(rv)) { 49918 return rv; 49919 } 49920 rv = _field_multimode_slice_idx_alloc(unit, 49921 stage_fc, fg, fs, &idx); 49922 } 49923 BCM_IF_ERROR_RETURN(rv); 49924 } else { 49925 /* Get index for primary entry. */ 49926 for (idx = 0; idx < fs->entry_count; idx++) { 49927 if (NULL == fs->entries[idx]) { 49928 break; 49929 } 49930 } 49931 } 49932 49933 *slice_idx = idx; 49934 return rv; 49935 } 49936 49937 /* 49938 * Function: 49939 * _field_multimode_slice_idx_alloc 49940 * 49941 * Purpose: 49942 * Allocate a free index for entry creation in mixed entry capable slice. 49943 * 49944 * Parameters: 49945 * unit - (IN) BCM device number. 49946 * stage_fc - (IN) Stage field control structure. 49947 * fg - (IN) Field group structure. 49948 * fs - (IN) Field slice structure. 49949 * slice_idx - (OUT) slice index to be allocate 49950 * 49951 * Returns: 49952 * BCM_E_PARAM - Input params are wrong. 49953 * BCM_E_RESOURCE - Failed to allocate index in given slice. 49954 * BCM_E_NONE - Success. 49955 */ 49956 STATIC int 49957 _field_multimode_slice_idx_alloc(int unit, 49958 _field_stage_t *stage_fc, 49959 _field_group_t *fg, 49960 _field_slice_t *fs, 49961 uint32 *slice_idx) 49962 { 49963 int rv = BCM_E_NONE; 49964 int index = 0; 49965 int slice_sz = 0; 49966 int idx_type; 49967 49968 if ((stage_fc == NULL) || (fg == NULL) || 49969 (fs == NULL) || (slice_idx == NULL)) { 49970 return (BCM_E_PARAM); 49971 } 49972 49973 *slice_idx = _FP_INVALID_INDEX; 49974 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 49975 for (index = 0; index < slice_sz; index++) { 49976 _field_slice_index_type_get(unit, fg, fs, index, &idx_type); 49977 if (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_FREE) { 49978 *slice_idx = index; 49979 break; 49980 } 49981 } 49982 49983 if (index == slice_sz) { 49984 rv = BCM_E_RESOURCE; 49985 } 49986 return rv; 49987 } 49988 49989 /* 49990 * Function: 49991 * _field_multimode_slice_entry_move 49992 * 49993 * Purpose: 49994 * Move field entry in the slice by given amount. 49995 * 49996 * Parameters: 49997 * unit - (IN) BCM device number. 49998 * f_ent - (IN) field entry structure. 49999 * amount - (IN) amount of movement. 50000 * 50001 * Returns: 50002 * BCM_E_PARAM - Null field stage control structure. 50003 * BCM_E_XXX - For other errors. 50004 * BCM_E_NONE - Success. 50005 * Note: 50006 * Currently, entry movement in same slice is supported. 50007 */ 50008 STATIC int 50009 _field_multimode_slice_entry_move(int unit, 50010 _field_slice_t *fs, 50011 _field_entry_t *f_ent, 50012 int amount) 50013 { 50014 int rv = BCM_E_NONE; /* Operation return status. */ 50015 _field_control_t *fc = NULL; /* Field control structure. */ 50016 _field_stage_t *stage_fc = NULL; /* Stage field control. */ 50017 _field_group_t *fg = NULL; /* Field group control. */ 50018 int parts_count = 0; /* Field entry parts count. */ 50019 int part; /* Part iterator. */ 50020 int new_slice_idx = 0; /* New Slice index for entry. */ 50021 int new_pri_tcam_idx = 0; /* New Primary tcam index. */ 50022 int tcam_idx_old[_FP_MAX_ENTRY_WIDTH]; /* Original entry tcam index. */ 50023 int tcam_idx_new[_FP_MAX_ENTRY_WIDTH]; /* Next tcam index for the entry.*/ 50024 50025 /* validate input params */ 50026 if ((NULL == fs) || (NULL == f_ent)) { 50027 return (BCM_E_PARAM); 50028 } 50029 50030 LOG_DEBUG(BSL_LS_BCM_FP, 50031 (BSL_META_U(unit, 50032 "FP(unit %d) vverb: BEGIN _field_multimode_slice_entry_move(entry=%d," 50033 " amount=%d)\n"), unit, f_ent->eid, amount)); 50034 50035 /* Initialization. */ 50036 sal_memset(tcam_idx_old, 0, (_FP_MAX_ENTRY_WIDTH * sizeof(int))); 50037 sal_memset(tcam_idx_new, 0, (_FP_MAX_ENTRY_WIDTH * sizeof(int))); 50038 fg = f_ent->group; 50039 50040 new_slice_idx = f_ent->slice_idx + amount; 50041 50042 if (amount == 0) { 50043 LOG_WARN(BSL_LS_BCM_FP, 50044 (BSL_META_U(unit, 50045 "Warning: moving entry=%d, same slice_idx=%d(%#x)\n"), 50046 f_ent->eid, f_ent->slice_idx, f_ent->slice_idx)); 50047 return (BCM_E_NONE); 50048 } 50049 50050 /* Get field control structure. */ 50051 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 50052 50053 /* Get stage field control structure. */ 50054 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 50055 BCM_IF_ERROR_RETURN(rv); 50056 50057 /* Get number of parts. */ 50058 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 50059 fg->flags, &parts_count); 50060 BCM_IF_ERROR_RETURN(rv); 50061 50062 /* Get new primary tcam index for entry. */ 50063 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, 50064 fg->instance, fs->slice_number, 50065 new_slice_idx, &new_pri_tcam_idx); 50066 BCM_IF_ERROR_RETURN(rv); 50067 50068 /* Calculate the new and old TCAM indexes. */ 50069 for (part = 0; part < parts_count; part++) { 50070 rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + part, 50071 &tcam_idx_old[part]); 50072 BCM_IF_ERROR_RETURN(rv); 50073 50074 /* Calculate entry part tcam offset. */ 50075 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 50076 new_pri_tcam_idx, part, &tcam_idx_new[part]); 50077 BCM_IF_ERROR_RETURN(rv); 50078 } 50079 50080 /* Call Entry move if installed */ 50081 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 50082 rv = fc->functions.fp_entry_move(unit, f_ent, parts_count, 50083 tcam_idx_old, tcam_idx_new); 50084 BCM_IF_ERROR_RETURN(rv); 50085 } 50086 50087 rv = _field_entry_slice_idx_change(unit, f_ent, parts_count, tcam_idx_new); 50088 50089 return rv; 50090 } 50091 50092 /* 50093 * Function: 50094 * _field_multimode_slice_entry_compress 50095 * 50096 * Purpose: 50097 * Compress hw entries in mixed entry capable slice 50098 * 50099 * Parameters: 50100 * unit - (IN) BCM device number. 50101 * fs - (IN) Field slice control structure. 50102 * 50103 * Returns: 50104 * BCM_E_PARAM - Null field stage control structure. 50105 * BCM_E_XXX - Other errors. 50106 * BCM_E_NONE - Success. 50107 * Note: 50108 * Currently, entry movement in same slice is supported. 50109 */ 50110 STATIC int 50111 _field_multimode_slice_entry_compress(int unit, _field_slice_t *fs) 50112 { 50113 int rv = BCM_E_NONE; 50114 int to_idx = 0, from_idx = 0; 50115 int start_idx = 0, end_idx = 0; 50116 50117 if (fs == NULL) { 50118 return (BCM_E_PARAM); 50119 } 50120 50121 if (fs->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) { 50122 return (BCM_E_INTERNAL); 50123 } 50124 50125 start_idx = fs->start_tcam_idx; 50126 end_idx = start_idx + fs->entry_count - 1; 50127 50128 /* Find First hole */ 50129 while ((fs->entries[start_idx] != NULL) && 50130 (start_idx != end_idx)) { 50131 start_idx++; 50132 } 50133 50134 if (start_idx == end_idx) { 50135 return BCM_E_RESOURCE; 50136 } 50137 50138 for (to_idx = start_idx, from_idx = start_idx + 1; 50139 from_idx <= end_idx; from_idx++) { 50140 /* If it is single wide entry, move to hole */ 50141 if (fs->entries[from_idx] == NULL) { 50142 continue; 50143 } 50144 50145 if (fs->entries[from_idx]->group->flags & 50146 _FP_GROUP_DW_DEPTH_EXPANDED) { 50147 continue; 50148 } 50149 rv = _field_multimode_slice_entry_move(unit, fs, 50150 fs->entries[from_idx], to_idx - from_idx); 50151 BCM_IF_ERROR_RETURN(rv); 50152 50153 /* get next free index */ 50154 to_idx++; 50155 while ((fs->entries[to_idx] != NULL) && 50156 (start_idx != end_idx)) { 50157 to_idx++; 50158 } 50159 } 50160 return rv; 50161 } 50162 50163 /* 50164 * Function: 50165 * _field_multimode_slice_entry_shift_down 50166 * 50167 * Purpose: 50168 * Shift entry down in the mixed-entry capable slice. 50169 * 50170 * Parameters: 50171 * unit - (IN) BCM device number. 50172 * fg - (IN) Field group control structure. 50173 * target_fs - (IN) Target flice slice where entry to be shifted. 50174 * target_idx - (IN) Corresponding index in target_fs 50175 * next_null_fs-(IN) Next slice which has freee entry. 50176 * next_null_idx-(IN) Corresponding index in next_null_fs 50177 * 50178 * Returns: 50179 * BCM_E_PARAM - Null field stage control structure. 50180 * BCM_E_XXX - For other errors. 50181 * BCM_E_NONE - Success. 50182 * Note: 50183 * Currently, entry movement in same slice is supported. 50184 */ 50185 STATIC int 50186 _field_multimode_slice_entry_shift_down(int unit, 50187 _field_group_t *fg, 50188 _field_slice_t *target_fs, 50189 uint16 target_idx, 50190 _field_slice_t *next_null_fs, 50191 uint16 next_null_idx) 50192 { 50193 int rv = BCM_E_NONE; 50194 _field_slice_t *fs = NULL; 50195 int slice_idx_empty = 0; 50196 int new_shift_idx = 0; 50197 50198 /* Input parameter check. */ 50199 if ((NULL == target_fs) || (NULL == fg) || (NULL == next_null_fs)) { 50200 return (BCM_E_PARAM); 50201 } 50202 if (target_fs != next_null_fs) { 50203 return (BCM_E_INTERNAL); 50204 } 50205 50206 slice_idx_empty = next_null_idx; 50207 fs = next_null_fs; 50208 50209 /* 50210 * Idea is Move entries down in the same group based on number of parts. 50211 */ 50212 while (slice_idx_empty > target_idx) { 50213 rv = _field_slice_next_match_index_get(unit, fg, fs, 50214 slice_idx_empty, target_idx, 50215 -1, &new_shift_idx); 50216 BCM_IF_ERROR_RETURN(rv); 50217 50218 /* Perform entry move. */ 50219 rv = _field_multimode_slice_entry_move(unit, fs, 50220 fs->entries[new_shift_idx], 50221 slice_idx_empty - new_shift_idx); 50222 BCM_IF_ERROR_RETURN(rv); 50223 50224 slice_idx_empty = new_shift_idx; 50225 } 50226 50227 return rv; 50228 } 50229 50230 /* 50231 * Function: 50232 * _field_multimode_slice_entry_shift_up 50233 * 50234 * Purpose: 50235 * Shift entries up in the mixed-entry capable slice. 50236 * 50237 * Parameters: 50238 * unit - (IN) BCM device number. 50239 * fg - (IN) Field group control structure. 50240 * target_fs - (IN) Target flice slice where entry to be shifted. 50241 * target_idx - (IN) Corresponding index in target_fs 50242 * prev_null_fs-(IN) Previous slice which has freee entry. 50243 * prev_null_idx-(IN) Corresponding index in prev_null_fs 50244 * 50245 * Returns: 50246 * BCM_E_PARAM - Null field stage control structure. 50247 * BCM_E_XXX - Other errors. 50248 * BCM_E_NONE - Success. 50249 * Note: 50250 * Currently, entry movement in same slice is supported. 50251 */ 50252 STATIC int 50253 _field_multimode_slice_entry_shift_up(int unit, 50254 _field_group_t *fg, 50255 _field_slice_t *target_fs, 50256 uint16 target_idx, 50257 _field_slice_t *prev_null_fs, 50258 uint16 prev_null_idx) 50259 { 50260 int rv = BCM_E_NONE; 50261 _field_slice_t *fs = NULL; 50262 int slice_idx_empty = 0; 50263 int new_shift_idx = 0; 50264 50265 /* input parameter check. */ 50266 if ((NULL == target_fs) || (NULL == fg) || (NULL == prev_null_fs)) { 50267 return (BCM_E_PARAM); 50268 } 50269 if (target_fs != prev_null_fs) { 50270 return (BCM_E_INTERNAL); 50271 } 50272 50273 slice_idx_empty = prev_null_idx; 50274 fs = prev_null_fs; 50275 50276 /* 50277 * Idea is move entries up in the same group mode based on number of parts. 50278 */ 50279 while (slice_idx_empty < target_idx) { 50280 rv = _field_slice_next_match_index_get(unit, fg, fs, 50281 slice_idx_empty, target_idx, 50282 1, &new_shift_idx); 50283 BCM_IF_ERROR_RETURN(rv); 50284 50285 /* perform entry move. */ 50286 rv = _field_multimode_slice_entry_move(unit, fs, 50287 fs->entries[new_shift_idx], 50288 slice_idx_empty - new_shift_idx); 50289 BCM_IF_ERROR_RETURN(rv); 50290 50291 slice_idx_empty = new_shift_idx; 50292 } 50293 50294 return rv; 50295 } 50296 50297 50298 int _field_action_match_config_alloc (int unit, 50299 bcm_field_action_match_config_t *match_config, 50300 _field_action_t *fa) 50301 { 50302 uint32 port = 0; 50303 50304 /* Do not allow LB ports */ 50305 if (BCM_PBMP_NOT_NULL(match_config->egr_pbmp)) { 50306 BCM_PBMP_ITER(match_config->egr_pbmp, port) { 50307 if (BCM_PBMP_MEMBER(PBMP_LB(unit), port)) { 50308 return BCM_E_PARAM; 50309 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 50310 "Field Action Egress Pbmp has Loopback ports\r\n"))); 50311 } 50312 } 50313 } 50314 50315 if (BCM_PBMP_NOT_NULL(match_config->egr_pbmp)) { 50316 _FP_XGS3_ALLOC(fa->egress_pbmp, sizeof(bcm_pbmp_t), 50317 "Field Action Pbmp Allocation "); 50318 if (NULL == fa->egress_pbmp) { 50319 return (BCM_E_MEMORY); 50320 } 50321 BCM_PBMP_ASSIGN(*(fa->egress_pbmp), match_config->egr_pbmp); 50322 } 50323 50324 (fa->elephant_pkts_only) = (match_config->elephant_pkt_only); 50325 return BCM_E_NONE; 50326 } 50327 50328 50329 /* 50330 * Function: 50331 * _field_ddrop_profile_get 50332 * Purpose: 50333 * Get the redirect profile for the unit 50334 * Parameters: 50335 * unit - BCM device number 50336 * ddrop_profile - (OUT) redirect profile 50337 * Returns: 50338 * BCM_E_XXX 50339 * Notes: 50340 * For triumph, External TCAM and IFP refer to same IFP_EGRESS_PORT_CHECK_FOR_DROPm 50341 */ 50342 int 50343 _bcm_field_ddrop_profile_get(int unit, 50344 soc_profile_mem_t **ddrop_profile) 50345 { 50346 _field_control_t *fc = NULL; 50347 50348 /* Get field control structure. */ 50349 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 50350 50351 *ddrop_profile = &fc->ddrop_profile; 50352 50353 return (BCM_E_NONE); 50354 } 50355 50356 /* 50357 * Function: 50358 * _bcm_field_ddrop_profile_ref_count_get 50359 * Purpose: 50360 * Get redirect profile entry use count. 50361 * Parameters: 50362 * unit - (IN) BCM device number. 50363 * index - (IN) Profile entry index. 50364 * ref_count - (OUT) redirect profile use count. 50365 * Returns: 50366 * BCM_E_XXX 50367 */ 50368 int 50369 _bcm_field_ddrop_profile_ref_count_get(int unit, 50370 int index, 50371 int *ref_count) 50372 { 50373 soc_profile_mem_t *ddrop_profile; 50374 50375 if (NULL == ref_count) { 50376 return (BCM_E_PARAM); 50377 } 50378 50379 /* Get the redirect profile */ 50380 BCM_IF_ERROR_RETURN 50381 (_bcm_field_ddrop_profile_get(unit, &ddrop_profile)); 50382 50383 return (soc_profile_mem_ref_count_get(unit, ddrop_profile, 50384 index, ref_count)); 50385 } 50386 50387 /* 50388 * Function: 50389 * _bcm_field_ddrop_profile_delete 50390 * Purpose: 50391 * Delete redirect profile entry. 50392 * Parameters: 50393 * unit - (IN) BCM device number. 50394 * index - (IN) Profile entry index. 50395 * Returns: 50396 * BCM_E_XXX 50397 */ 50398 int 50399 _bcm_field_ddrop_profile_delete(int unit, int index) 50400 { 50401 soc_profile_mem_t *ddrop_profile; 50402 50403 /* Get the redirect profile */ 50404 BCM_IF_ERROR_RETURN 50405 (_bcm_field_ddrop_profile_get(unit, &ddrop_profile)); 50406 50407 return (soc_profile_mem_delete(unit, ddrop_profile, index)); 50408 } 50409 50410 /* 50411 * Function: 50412 * _field_dredirect_profile_get 50413 * Purpose: 50414 * Get the redirect profile for the unit 50415 * Parameters: 50416 * unit - BCM device number 50417 * dredirect_profile - (OUT) redirect profile 50418 * Returns: 50419 * BCM_E_XXX 50420 * Notes: 50421 * For triumph, External TCAM and IFP refer to same IFP_EGRESS_PORT_CHECK_FOR_REDIRECTm 50422 */ 50423 int 50424 _bcm_field_dredirect_profile_get(int unit, 50425 soc_profile_mem_t **dredirect_profile) 50426 { 50427 _field_control_t *fc = NULL; 50428 50429 /* Get field control structure. */ 50430 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 50431 50432 *dredirect_profile = &fc->dredirect_profile; 50433 50434 return (BCM_E_NONE); 50435 } 50436 50437 /* 50438 * Function: 50439 * _bcm_field_dredirect_profile_ref_count_get 50440 * Purpose: 50441 * Get redirect profile entry use count. 50442 * Parameters: 50443 * unit - (IN) BCM device number. 50444 * index - (IN) Profile entry index. 50445 * ref_count - (OUT) redirect profile use count. 50446 * Returns: 50447 * BCM_E_XXX 50448 */ 50449 int 50450 _bcm_field_dredirect_profile_ref_count_get(int unit, 50451 int index, 50452 int *ref_count) 50453 { 50454 soc_profile_mem_t *dredirect_profile; 50455 50456 if (NULL == ref_count) { 50457 return (BCM_E_PARAM); 50458 } 50459 50460 /* Get the redirect profile */ 50461 BCM_IF_ERROR_RETURN 50462 (_bcm_field_dredirect_profile_get(unit, &dredirect_profile)); 50463 50464 return (soc_profile_mem_ref_count_get(unit, dredirect_profile, 50465 index, ref_count)); 50466 } 50467 50468 /* 50469 * Function: 50470 * _bcm_field_dredirect_profile_delete 50471 * Purpose: 50472 * Delete redirect profile entry. 50473 * Parameters: 50474 * unit - (IN) BCM device number. 50475 * index - (IN) Profile entry index. 50476 * Returns: 50477 * BCM_E_XXX 50478 */ 50479 int 50480 _bcm_field_dredirect_profile_delete(int unit, int index) 50481 { 50482 soc_profile_mem_t *dredirect_profile; 50483 50484 /* Get the redirect profile */ 50485 BCM_IF_ERROR_RETURN 50486 (_bcm_field_dredirect_profile_get(unit, &dredirect_profile)); 50487 50488 return (soc_profile_mem_delete(unit, dredirect_profile, index)); 50489 } 50490 50491 int 50492 _field_delayed_profile_hw_alloc(int unit, _field_entry_t *f_ent) 50493 { 50494 int rv = BCM_E_NONE; /* Operation return status. */ 50495 _field_action_t *fa; /* Field action descriptor. */ 50496 50497 int ref_count; /* Profile use reference count. */ 50498 _field_control_t *fc = NULL; 50499 50500 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 50501 50502 for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) { 50503 switch (fa->action) { 50504 case bcmFieldActionMatchPbmpRedirect: 50505 /* 50506 * Store previous hardware index value in old_index. 50507 */ 50508 fa->old_index = fa->hw_index; 50509 50510 if (NULL == fc->functions.fp_dredirect_action_alloc) { 50511 return BCM_E_CONFIG; 50512 } 50513 50514 rv = fc->functions.fp_dredirect_action_alloc(unit, f_ent, fa); 50515 50516 if ((BCM_E_RESOURCE == rv) && 50517 (_FP_INVALID_INDEX != fa->old_index)) { 50518 50519 /* Destroy old profile ONLY 50520 * if it is not used by other entries. 50521 */ 50522 rv = _bcm_field_dredirect_profile_ref_count_get(unit, 50523 fa->old_index, 50524 &ref_count); 50525 BCM_IF_ERROR_RETURN(rv); 50526 if (ref_count > 1) { 50527 return (BCM_E_RESOURCE); 50528 } 50529 rv = _bcm_field_dredirect_profile_delete(unit, fa->old_index); 50530 BCM_IF_ERROR_RETURN(rv); 50531 50532 /* Destroy old profile is no longer required. */ 50533 fa->old_index = _FP_INVALID_INDEX; 50534 50535 /* Reallocate profile for new action. */ 50536 rv = fc->functions.fp_dredirect_action_alloc(unit, f_ent, fa); 50537 } 50538 break; 50539 50540 case bcmFieldActionMatchPbmpDrop: 50541 /* 50542 * Store previous hardware index value in old_index. 50543 */ 50544 fa->old_index = fa->hw_index; 50545 50546 if (NULL == fc->functions.fp_ddrop_action_alloc) { 50547 return BCM_E_CONFIG; 50548 } 50549 50550 rv = fc->functions.fp_ddrop_action_alloc(unit, f_ent, fa); 50551 50552 if ((BCM_E_RESOURCE == rv) && 50553 (_FP_INVALID_INDEX != fa->old_index)) { 50554 50555 /* Destroy old profile ONLY 50556 * if it is not used by other entries. 50557 */ 50558 rv = _bcm_field_ddrop_profile_ref_count_get(unit, 50559 fa->old_index, 50560 &ref_count); 50561 BCM_IF_ERROR_RETURN(rv); 50562 if (ref_count > 1) { 50563 return (BCM_E_RESOURCE); 50564 } 50565 rv = _bcm_field_ddrop_profile_delete(unit, fa->old_index); 50566 BCM_IF_ERROR_RETURN(rv); 50567 50568 /* Destroy old profile is no longer required. */ 50569 fa->old_index = _FP_INVALID_INDEX; 50570 50571 /* Reallocate profile for new action. */ 50572 rv = fc->functions.fp_ddrop_action_alloc(unit, f_ent, fa); 50573 } 50574 break; 50575 default: 50576 break; 50577 } 50578 if (BCM_FAILURE(rv)) { 50579 _field_delayed_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE); 50580 break; 50581 } 50582 } 50583 return rv; 50584 } 50585 50586 /* 50587 * Function: 50588 * _field_delayed_profile_hw_free 50589 * 50590 * Purpose: 50591 * Free redirect profile indexes required for entry installation. 50592 * 50593 * Parameters: 50594 * unit - (IN) BCM device number. 50595 * f_ent - (IN) Field entry descriptor. 50596 * flags - (IN) Free flags (old/new/both). 50597 * Returns: 50598 * BCM_E_XXX 50599 * Notes: 50600 */ 50601 50602 int 50603 _field_delayed_profile_hw_free(int unit, _field_entry_t *f_ent, uint32 flags) 50604 { 50605 _field_action_t *fa; /* Field action descriptor. */ 50606 int rv = BCM_E_NONE; /* Operation return status. */ 50607 50608 /* Extract the policy info from the entry structure. */ 50609 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 50610 switch (fa->action) { 50611 case bcmFieldActionMatchPbmpRedirect: 50612 if ((flags & _FP_ACTION_RESOURCE_FREE) && 50613 (_FP_INVALID_INDEX != fa->hw_index)) { 50614 rv = _bcm_field_dredirect_profile_delete(unit, 50615 fa->hw_index); 50616 BCM_IF_ERROR_RETURN(rv); 50617 fa->hw_index = _FP_INVALID_INDEX; 50618 } 50619 50620 if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) && 50621 (_FP_INVALID_INDEX != fa->old_index)) { 50622 rv = _bcm_field_dredirect_profile_delete(unit, 50623 fa->old_index); 50624 BCM_IF_ERROR_RETURN(rv); 50625 fa->old_index = _FP_INVALID_INDEX; 50626 } 50627 break; 50628 case bcmFieldActionMatchPbmpDrop: 50629 if ((flags & _FP_ACTION_RESOURCE_FREE) && 50630 (_FP_INVALID_INDEX != fa->hw_index)) { 50631 rv = _bcm_field_ddrop_profile_delete(unit, 50632 fa->hw_index); 50633 BCM_IF_ERROR_RETURN(rv); 50634 fa->hw_index = _FP_INVALID_INDEX; 50635 } 50636 50637 if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) && 50638 (_FP_INVALID_INDEX != fa->old_index)) { 50639 rv = _bcm_field_ddrop_profile_delete(unit, 50640 fa->old_index); 50641 BCM_IF_ERROR_RETURN(rv); 50642 fa->old_index = _FP_INVALID_INDEX; 50643 } 50644 break; 50645 default: 50646 break; 50647 } 50648 } 50649 return (rv); 50650 } 50651 50652 /* 50653 * Function: 50654 * _bcm_field_priority_group_get_next 50655 * Purpose: 50656 * Retrieve the next valid group pointer associated with the given priority. 50657 * Parameters: 50658 * unit - (IN BCM device number. 50659 * instance - (IN) Pipe to which group belongs to. 50660 * stage_id - (IN) Stage (IFP/VFP/EFP) to which group belongs to. 50661 * priority - (IN) Field Group Priority. 50662 * curr_group - (IN) Reference to current group index associated to group 50663 * priority. 50664 * next_group - (OUT) Reference to next available group index associated to 50665 * the given priority. 50666 * Returns: 50667 * BCM_E_XXX 50668 * Note: 50669 * "*curr_group == NULL" to retrieve the first group associated with the 50670 * given slice. 50671 */ 50672 int 50673 _bcm_field_priority_group_get_next(int unit, 50674 int instance, 50675 _field_stage_id_t stage_id, 50676 int priority, 50677 uint32 group_mode, 50678 _field_group_t **curr_group, 50679 _field_group_t **next_group) 50680 { 50681 _field_group_t *fg = NULL; 50682 50683 if (curr_group == NULL || next_group == NULL) { 50684 return BCM_E_PARAM; 50685 } 50686 50687 if (*curr_group == NULL) { 50688 _field_control_t *fc; /* Field Control Structure */ 50689 50690 /* Get device Field control structure. */ 50691 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 50692 fg = fc->groups; 50693 } else { 50694 fg = (*curr_group)->next; 50695 } 50696 50697 *next_group = NULL; 50698 for (; fg != NULL; fg = fg->next) { 50699 if ((instance != fg->instance) || 50700 (stage_id != fg->stage_id) || 50701 (priority != fg->priority)) { 50702 continue; 50703 } 50704 50705 if ((group_mode == _FP_GROUP_SPAN_MASK) || 50706 ((fg->flags & _FP_GROUP_SPAN_MASK) == group_mode)) { 50707 *next_group = fg; 50708 return BCM_E_NONE; 50709 } 50710 } 50711 50712 return BCM_E_NOT_FOUND; 50713 } 50714 50715 50716 /* 50717 * Retrieve number of groups available for a given priority. 50718 */ 50719 int 50720 _bcm_field_group_count_get(int unit, 50721 int instance, 50722 _field_stage_t *stage_fc, 50723 int group_priority, 50724 uint32 group_mode, 50725 uint16 *group_count) 50726 { 50727 int rv; 50728 _field_group_t *fg_next = NULL; 50729 50730 *group_count = 0; 50731 do { 50732 rv = _bcm_field_priority_group_get_next(unit, 50733 instance, 50734 stage_fc->stage_id, 50735 group_priority, 50736 group_mode, 50737 &fg_next, &fg_next); 50738 if (BCM_FAILURE(rv)) { 50739 break; 50740 } 50741 50742 *group_count += 1; 50743 } while (fg_next != NULL); 50744 50745 return BCM_E_NONE; 50746 } 50747 50748 #endif /* BCM_FIELD_SUPPORT */ 50749 #endif /* BCM_ESW_SUPPORT */ 50750