field_grp.c (362384B)
1 /* 2 * 3 * 4 * 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 6 * 7 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 8 * 9 * File: field_grp.c 10 * Purpose: BCM56960 Field Processor Group management functions. 11 */ 12 13 #include <soc/defs.h> 14 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(BCM_FIELD_SUPPORT) 15 #include <shared/bsl.h> 16 #include <soc/mem.h> 17 #include <soc/drv.h> 18 #include <soc/tomahawk.h> 19 #include <bcm_int/esw/tomahawk.h> 20 #include <bcm_int/esw/helix5.h> 21 #include <bcm_int/esw/tomahawk3.h> 22 #include <bcm/field.h> 23 #include <bcm_int/esw/field.h> 24 #include <bcm_int/esw/udf.h> 25 26 #if defined(BCM_HELIX5_SUPPORT) 27 #include <bcm_int/esw/helix5.h> 28 #endif 29 30 #if defined(BCM_ESW_SUPPORT) 31 #include <bcm_int/esw/xgs4.h> 32 #endif 33 int th_prio_set_with_no_free_entries = FALSE; 34 35 /* Local functions prototypes. */ 36 STATIC int 37 _field_th_group_add(int unit, _field_group_add_fsm_t *fsm_ptr); 38 STATIC int 39 _field_th_lt_default_tcam_entry_install(int unit, bcm_field_entry_t lt_entry, 40 int group_expand, int part_index, 41 _field_lt_slice_t *lt_fs); 42 STATIC int 43 _field_th_ingress_group_expand_slice_install(int unit, _field_stage_t *stage_fc, 44 _field_group_t *fg, uint8 slice_number, 45 int part_index, int group_slice_prio); 46 STATIC int 47 _field_th_ingress_group_expand_install(int unit, _field_stage_t *stage_fc, 48 _field_group_t *fg, int entry_part, 49 _field_lt_slice_t *lt_fs); 50 #define IS_POST_MUX_QUALIFIER(qid) \ 51 ((_BCM_FIELD_IS_PBMP_QUALIFIER(qid)) \ 52 || (bcmFieldQualifyNatDstRealmId == qid) \ 53 || (bcmFieldQualifyNatNeeded == qid) \ 54 || (bcmFieldQualifyDrop == qid) \ 55 || (bcmFieldQualifyDstTrunk == qid) \ 56 || (bcmFieldQualifyDstMultipath == qid) \ 57 || (bcmFieldQualifyDstMultipathOverlay == qid) \ 58 || (bcmFieldQualifyDstMultipathUnderlay == qid) \ 59 || (bcmFieldQualifyDstL2MulticastGroup == qid) \ 60 || (bcmFieldQualifyDstL3MulticastGroup == qid) \ 61 || (bcmFieldQualifyDstL3EgressNextHops == qid) \ 62 || (bcmFieldQualifyDstL3Egress == qid) \ 63 || (bcmFieldQualifyDstPort == qid) \ 64 || (bcmFieldQualifyDstMimGport == qid) \ 65 || (bcmFieldQualifyDstNivGport == qid) \ 66 || (bcmFieldQualifyDstVxlanGport == qid) \ 67 || (bcmFieldQualifyDstVlanGport == qid) \ 68 || (bcmFieldQualifyDstMplsGport == qid) \ 69 || (bcmFieldQualifyDstWlanGport == qid) \ 70 || (bcmFieldQualifyDstMimGports == qid) \ 71 || (bcmFieldQualifyDstNivGports == qid) \ 72 || (bcmFieldQualifyDstVxlanGports == qid) \ 73 || (bcmFieldQualifyDstVlanGports == qid) \ 74 || (bcmFieldQualifyDstMplsGports == qid) \ 75 || (bcmFieldQualifyDstWlanGports == qid) \ 76 || ((int)_bcmFieldQualifyExactMatchHitStatusLookup0 == (int)qid) \ 77 || ((int)_bcmFieldQualifyExactMatchHitStatusLookup1 == (int)qid) \ 78 || ((int)_bcmFieldQualifyExactMatchActionClassIdLookup0 == (int)qid) \ 79 || ((int)_bcmFieldQualifyExactMatchActionClassIdLookup1 == (int)qid)) 80 81 #define IS_EXT_OVERLAID_POST_MUXERS(ace_flags, ext_flags) \ 82 (((ace_flags & _FP_POST_MUX_NAT_DST_REALM_ID) && \ 83 (ext_flags & _FP_EXT_ATTR_NOT_WITH_NAT_DST_REALM_ID)) || \ 84 ((ace_flags & _FP_POST_MUX_NAT_NEEDED) && \ 85 (ext_flags & _FP_EXT_ATTR_NOT_WITH_NAT_NEEDED)) || \ 86 ((ace_flags & _FP_POST_MUX_EM_HIT_STATUS_LOOKUP_0) && \ 87 (ext_flags & _FP_EXT_ATTR_NOT_WITH_EM_HIT_STATUS_LOOKUP_0)) || \ 88 ((ace_flags & _FP_POST_MUX_EM_HIT_STATUS_LOOKUP_1) && \ 89 (ext_flags & _FP_EXT_ATTR_NOT_WITH_EM_HIT_STATUS_LOOKUP_1)) || \ 90 ((ace_flags & _FP_POST_MUX_EM_ACTION_CLASSID_LOOKUP_0) && \ 91 (ext_flags & _FP_EXT_ATTR_NOT_WITH_EM_ACTION_CLASSID_LOOKUP_0)) || \ 92 ((ace_flags & _FP_POST_MUX_EM_ACTION_CLASSID_LOOKUP_1) && \ 93 (ext_flags & _FP_EXT_ATTR_NOT_WITH_EM_ACTION_CLASSID_LOOKUP_1)) || \ 94 ((ace_flags & _FP_POST_MUX_DROP) && \ 95 (ext_flags & _FP_EXT_ATTR_NOT_WITH_DROP)) || \ 96 ((ace_flags & _FP_POST_MUX_SRC_DST_CONT_1_SLI_B) && \ 97 (ext_flags & _FP_EXT_ATTR_NOT_WITH_SRC_DST_CONT_1_B)) || \ 98 ((ace_flags & _FP_POST_MUX_SRC_DST_CONT_0_SLI_B) && \ 99 (ext_flags & _FP_EXT_ATTR_NOT_WITH_SRC_DST_CONT_0_B)) || \ 100 ((ace_flags & _FP_POST_MUX_SRC_DST_CONT_1_SLI_C) && \ 101 (ext_flags & _FP_EXT_ATTR_NOT_WITH_SRC_DST_CONT_1_C)) || \ 102 ((ace_flags & _FP_POST_MUX_SRC_DST_CONT_0_SLI_C) && \ 103 (ext_flags & _FP_EXT_ATTR_NOT_WITH_SRC_DST_CONT_0_C)) || \ 104 ((ace_flags & _FP_POST_MUX_SRC_DST_CONT_1) && \ 105 (ext_flags & _FP_EXT_ATTR_NOT_WITH_SRC_DST_CONT_1)) || \ 106 ((ace_flags & _FP_POST_MUX_SRC_DST_CONT_0) && \ 107 (ext_flags & _FP_EXT_ATTR_NOT_WITH_SRC_DST_CONT_0))) 108 109 110 #define IS_EXT_OVERLAID_IPBM(ace_flags, ext_flags) \ 111 ((ace_flags & _FP_POST_MUX_IPBM) && \ 112 (ext_flags & _FP_EXT_ATTR_NOT_WITH_IPBM)) 113 114 115 #define _NUM_CHUNKS_PER_GRAN 50 116 #define _NUM_GRAN 5 117 118 #define GRAN_BASE(gran, base) \ 119 { \ 120 if (gran == 32) { \ 121 base = 0; \ 122 } else if (gran == 16) { \ 123 base = 1; \ 124 } else if (gran == 8) { \ 125 base = 2; \ 126 } else if (gran == 4) { \ 127 base = 3; \ 128 } else if (gran == 2) { \ 129 base = 4; \ 130 } \ 131 } 132 133 /* 134 * Enum to define IPBM_SOURCE 135 */ 136 typedef enum _bcmFieldIpbmSource_e { 137 _bcmFieldIpbmSourcePipeLocal = 0, /* Port Based Selective Mask. */ 138 _bcmFieldIpbmSourcePort = 1, /* Ttrunk Based Selective Mask. */ 139 _bcmFieldIpbmSourceVp = 2, /* Source VP based Selective Mask. */ 140 _bcmFieldIpbmSourceDevPort = 3 /* IPBM Index based selective Mask.*/ 141 } _bcmFieldIpbmSource_t; 142 143 144 145 /* 146 * Function: 147 * _field_th_group_add_initialize 148 * Purpose: 149 * Perform fsm initialization & execute basic checks 150 * required before field group creation. 151 * Parameters: 152 * unit - (IN) BCM device number. 153 * fsm_ptr - (IN/OUT) State machine tracking structure. 154 * Returns: 155 * BCM_E_XXX. 156 */ 157 STATIC int 158 _field_th_group_add_initialize(int unit, _field_group_add_fsm_t *fsm_ptr) 159 { 160 _field_group_t *fg_temp; /* Pointer to an existing Field Group. */ 161 _field_stage_id_t stage; /* Field Processor stage ID. */ 162 163 /* Input parameters check. */ 164 if (NULL == fsm_ptr) { 165 return (BCM_E_PARAM); 166 } 167 168 /* Save current FSM state in previous state. */ 169 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 170 171 if (BCM_SUCCESS(_field_group_get(unit, fsm_ptr->group_id, &fg_temp))) { 172 LOG_ERROR(BSL_LS_BCM_FP, 173 (BSL_META_U(unit, "FP(unit %d) Error: group=%d already exists.\n"), 174 unit, fsm_ptr->group_id)); 175 fsm_ptr->rv = (BCM_E_EXISTS); 176 } 177 178 /* Get Field Stage control pointer. */ 179 if (BCM_SUCCESS(fsm_ptr->rv)) { 180 fsm_ptr->rv = _field_control_get(unit, &fsm_ptr->fc); 181 } 182 183 /* Get pipeline stage from qualifiers set. */ 184 if (BCM_SUCCESS(fsm_ptr->rv)) { 185 fsm_ptr->rv = _bcm_field_group_stage_get(unit, &fsm_ptr->qset, &stage); 186 if ((_BCM_FIELD_STAGE_INGRESS != stage) && 187 (_BCM_FIELD_STAGE_EXACTMATCH != stage) && 188 (_BCM_FIELD_STAGE_FLOWTRACKER != stage)) { 189 fsm_ptr->rv = BCM_E_INTERNAL; 190 } 191 } 192 193 /* 194 * Attempt IntraSlice Double wide Groups if stage supports it. 195 * Note: TH IFP stage default comes up in IntraSlice Double wide mode. 196 */ 197 if (BCM_SUCCESS(fsm_ptr->rv) 198 && soc_feature(unit, soc_feature_field_intraslice_double_wide) 199 && (fsm_ptr->fc->flags & _FP_INTRASLICE_ENABLE) 200 && (stage != _BCM_FIELD_STAGE_EXACTMATCH)) { 201 fsm_ptr->flags |= _BCM_FP_GROUP_ADD_INTRA_SLICE; 202 } 203 204 /* Get Field Stage Control Pointer. */ 205 if (BCM_SUCCESS(fsm_ptr->rv)) { 206 fsm_ptr->rv = _field_stage_control_get(unit, stage, &fsm_ptr->stage_fc); 207 } 208 209 if (BCM_SUCCESS(fsm_ptr->rv)) { 210 /* Verify if requested QSET is supported by the stage. */ 211 if (FALSE == _field_qset_is_subset(&fsm_ptr->qset, 212 &fsm_ptr->stage_fc->_field_supported_qset)) { 213 LOG_INFO(BSL_LS_BCM_FP, 214 (BSL_META_U(unit, "FP(unit %d) Error: Qualifier set is not" 215 " supported by the device.\n"), unit)); 216 fsm_ptr->rv = (BCM_E_UNAVAIL); 217 } 218 } 219 220 /* Verify Group Priority for flowtracker stage */ 221 #if defined(BCM_FLOWTRACKER_SUPPORT) 222 if (BCM_SUCCESS(fsm_ptr->rv) && 223 soc_feature(unit, soc_feature_field_flowtracker_support) && 224 (fsm_ptr->stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 225 if (fsm_ptr->priority != 0) { 226 fsm_ptr->rv = (BCM_E_CONFIG); 227 LOG_INFO(BSL_LS_BCM_FP, 228 (BSL_META_U(unit, "FP(unit %d) Error: Field Group Priority" 229 " not supported at this stage.\n"), unit)); 230 } 231 } 232 #endif 233 234 if (BCM_FAILURE(fsm_ptr->rv)) { 235 /* Error return hence perform clean up. */ 236 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 237 } else { 238 /* Proceed to group allocation state. */ 239 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_ALLOC; 240 } 241 242 /* Execute the state machine for the new state. */ 243 return (BCM_E_NONE); 244 } 245 246 #if 0 247 /* 248 * Function: 249 * _field_th_group_priority_validate 250 * Purpose: 251 * Validate group prioirty value, if specified priority value is NOT 252 * BCM_FIELD_GROUP_PRIO_ANY then it must be unique. 253 * Parameters: 254 * unit - (IN BCM device number. 255 * stage_fc - (IN) Field stage control structure. 256 * fg - (IN) Field group structure. 257 * Returns: 258 * BCM_E_XXX 259 */ 260 STATIC int 261 _field_th_group_priority_validate(int unit, _field_stage_t *stage_fc, 262 _field_group_t *fg) 263 { 264 int lt_idx; /* Logical Table iterator. */ 265 _field_lt_config_t *lt_info; /* Logical Table information. */ 266 267 /* Input parameters check. */ 268 if ((NULL == stage_fc) || (NULL == fg)) { 269 return (BCM_E_PARAM); 270 } 271 272 /* 273 * If Group doesn't care about priority, one of the available 274 * priorities is allocated. Hence return done. 275 */ 276 if (BCM_FIELD_GROUP_PRIO_ANY == fg->priority) { 277 return (BCM_E_NONE); 278 } 279 280 /* 281 * Two Field groups cannot have the same priority value as hardware 282 * behavior is Indeterministic if packet matches rules in both the groups 283 * that have same Group/Action priority value. 284 */ 285 for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) { 286 lt_info = stage_fc->lt_info[fg->instance][lt_idx]; 287 if ((TRUE == lt_info->valid) && (fg->priority == lt_info->priority)) { 288 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 289 "FP(unit %d) Error: Group=%d Priority=%d already in-use.\n"), 290 unit, fg->gid, fg->priority)); 291 return (BCM_E_PARAM); 292 } 293 } 294 295 return (BCM_E_NONE); 296 } 297 #endif /* 0 */ 298 299 /* 300 * Function: 301 * _field_th_group_add_alloc 302 * Purpose: 303 * Allocate & initialize field group structure. 304 * Parameters: 305 * unit - (IN) BCM device number. 306 * fsm_ptr - (IN/OUT) State machine tracking structure. 307 * Returns: 308 * BCM_E_XXX. 309 */ 310 STATIC int 311 _field_th_group_add_alloc(int unit, _field_group_add_fsm_t *fsm_ptr) 312 { 313 int idx; /* Iterator variable. */ 314 int mem_sz; /* Memory size to be allocated. */ 315 _field_group_t *fg = NULL; /* New group inforation structure. */ 316 317 /* Input parameters check. */ 318 if (NULL == fsm_ptr) { 319 return (BCM_E_PARAM); 320 } 321 322 /* Save current state as previous state. */ 323 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 324 325 /* Determine field group structure buffer size. */ 326 mem_sz = sizeof(_field_group_t); 327 328 /* Allocate and initialize memory for Field Group. */ 329 _FP_XGS3_ALLOC(fg, mem_sz, "field group"); 330 if (NULL == fg) { 331 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 332 "FP(unit %d) Error:Allocation failure for " 333 "_field_group_t\n"), unit)); 334 /* Memory allocation failure hence proceed to clean up. */ 335 fsm_ptr->rv = BCM_E_MEMORY; 336 goto bcm_error; 337 } 338 339 /* Initialize group structure. */ 340 fg->gid = fsm_ptr->group_id; 341 fg->stage_id = fsm_ptr->stage_fc->stage_id; 342 fg->qset = fsm_ptr->qset; 343 fg->pbmp = fsm_ptr->pbmp; 344 fg->priority = fsm_ptr->priority; 345 fg->hintid = fsm_ptr->hintid; 346 fg->action_res_id = fsm_ptr->action_res_id; 347 sal_memcpy(&fg->aset, &fsm_ptr->aset, sizeof(bcm_field_aset_t)); 348 349 /* Initialize the action profile index's to -1 */ 350 for (idx=0; idx < MAX_ACT_PROF_ENTRIES_PER_GROUP; idx++) { 351 fg->action_profile_idx[idx] = -1; 352 } 353 354 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 355 fg->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 356 } 357 358 /* Clear the group's select codes and its slice Qsets. */ 359 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 360 _FIELD_SELCODE_CLEAR(fg->sel_codes[idx]); 361 } 362 363 /* Set the Field Group's instance information. */ 364 fsm_ptr->rv = _bcm_field_th_group_instance_set(unit, fg); 365 if (BCM_FAILURE(fsm_ptr->rv)) { 366 goto bcm_error; 367 } 368 369 fsm_ptr->rv = _bcm_field_hints_group_count_update(unit, fg->hintid, 1); 370 if (BCM_FAILURE(fsm_ptr->rv)) { 371 goto bcm_error; 372 } 373 374 /* Initialize group status. */ 375 fsm_ptr->rv = _bcm_field_group_status_init(unit, &fg->group_status); 376 if (BCM_FAILURE(fsm_ptr->rv)) { 377 goto bcm_error; 378 } 379 380 /* Hint Check. */ 381 fsm_ptr->rv = _bcm_field_hints_group_info_update(unit, fg); 382 if (BCM_FAILURE(fsm_ptr->rv)) { 383 goto bcm_error; 384 } 385 386 /* Set slice size selection group flags. */ 387 if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_SMALL_SLICE) { 388 fg->flags |= _FP_GROUP_SELECT_SMALL_SLICE; 389 } else if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_LARGE_SLICE) { 390 fg->flags |= _FP_GROUP_SELECT_LARGE_SLICE; 391 } 392 393 /* Clear the group's slice extractor selectors value. */ 394 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 395 _FP_EXT_SELCODE_CLEAR(fg->ext_codes[idx]); 396 } 397 398 /* By default mark group as active. */ 399 fg->flags |= _FP_GROUP_LOOKUP_ENABLED; 400 401 /* Update Preselector Support Flags */ 402 if (fsm_ptr->flags & BCM_FIELD_GROUP_CREATE_WITH_PRESELSET) { 403 bcm_field_presel_t presel; 404 405 /* Preselector feature check */ 406 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 407 fsm_ptr->rv = BCM_E_UNAVAIL; 408 goto bcm_error; 409 } 410 411 /* initialize the group preselector array */ 412 sal_memset(&fg->presel_ent_arr[0], 0x0, 413 sizeof(_field_presel_entry_t *) * _FP_PRESEL_ENTRIES_MAX_PER_GROUP); 414 415 for (presel = 0; presel < BCM_FIELD_PRESEL_SEL_MAX; presel++) { 416 if (BCM_FIELD_PRESEL_TEST(fsm_ptr->preselset, presel)) { 417 /* Assign the preselectors to the group presel array. */ 418 fsm_ptr->rv = _bcm_field_presel_group_add(unit, fg, presel); 419 if (BCM_FAILURE(fsm_ptr->rv)) { 420 goto bcm_error; 421 } 422 fg->flags |= _FP_GROUP_PRESELECTOR_SUPPORT; 423 } 424 } 425 426 if (!(fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) { 427 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 428 "ERROR: Group (GID= %d) should have atleast" 429 " one preselector assigned.\n\r"),fg->gid)); 430 fsm_ptr->rv = BCM_E_PARAM; 431 goto bcm_error; 432 } 433 #if defined(BCM_FLOWTRACKER_SUPPORT) 434 } else { 435 if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 436 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 437 "ERROR: Group (GID= %d) should have atleast" 438 " one preselector assigned.\n\r"),fg->gid)); 439 fsm_ptr->rv = BCM_E_PARAM; 440 goto bcm_error; 441 } 442 #endif 443 } 444 445 /* Set allocated poniter to FSM structure. */ 446 fsm_ptr->fg = fg; 447 448 /* Update group QSET with internal qualifiers. */ 449 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_UPDATE; 450 451 /* Execute the state machine for the new state. */ 452 return (BCM_E_NONE); 453 454 bcm_error: 455 if (fg != NULL) { 456 sal_free(fg); 457 fg = NULL; 458 } 459 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 460 return (BCM_E_NONE); 461 } 462 /* 463 * Function: 464 * _field_calc_aset_size_all_actions 465 * Purpose: 466 * For TD3 IFP 467 * Calculate the Aset size 468 * Parameters: 469 * unit - (IN) BCM device number. 470 * fg - (IN) Field group structure. 471 * aset_size - (IN/OUT) group's Aset size 472 * Returns: 473 * BCM_E_XXX 474 */ 475 static int 476 _field_calc_aset_size_all_actions(int unit, _field_group_t *fg) 477 { 478 _field_stage_t *stage_fc = NULL; /* Field Stage Control. */ 479 _bcm_field_aset_t aset; /* Action Set. */ 480 uint16 aset_key_size = 0; /* Action Set Size. */ 481 uint8 aset_cnt[_FieldActionSetCount] = {0}; 482 /* Action Per Set Count. */ 483 int a_idx; /* Action Iterator. */ 484 _bcm_field_action_set_t *action_set_ptr; 485 /* action set pointer */ 486 _bcm_field_action_conf_t *action_conf_ptr; 487 /* action configuration pointer */ 488 uint8 field_action_set; /* to hold Aset enum */ 489 490 491 /* Input parameters check. */ 492 if (NULL == fg) { 493 return BCM_E_INTERNAL; 494 } 495 496 /* Retreive Action Set */ 497 aset = fg->aset; 498 499 /* Check whether it is a valid stage */ 500 /* this fucntion is valid for TD3 IFP */ 501 if (!(soc_feature(unit, soc_feature_ifp_action_profiling) 502 && (fg->stage_id == _BCM_FIELD_STAGE_INGRESS))) 503 { 504 return BCM_E_NONE; 505 } 506 507 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 508 &stage_fc)); 509 510 action_set_ptr = stage_fc->action_set_ptr; 511 512 /* Calculate Action Size. */ 513 for (a_idx = 0; a_idx < _bcmFieldActionCount; a_idx++) { 514 if (BCM_FIELD_ASET_TEST(aset, a_idx)) { 515 /* test whether the current action is supported in this stage */ 516 action_conf_ptr = stage_fc->f_action_arr[a_idx]; 517 if (NULL != action_conf_ptr) { 518 /* get the aset enum from action_conf_pointer */ 519 field_action_set = action_conf_ptr->offset->aset; 520 } else if (a_idx == bcmFieldActionPolicerGroup) { 521 /* Flag in ASETs to indicate group 522 * policer usage with the group */ 523 field_action_set = _FieldActionMeterSet; 524 } else if (a_idx == bcmFieldActionStatGroup) { 525 /* Flag in ASETs to indicate stat group 526 * usage with the group */ 527 field_action_set = _FieldActionCounterSet; 528 } else { 529 /* Ignore the unsupported actions */ 530 continue; 531 } 532 /* if the aset for current action is 0, or 533 action_set size is 0 for this stage/chip 534 skip the hw field updation step */ 535 if ((0 == field_action_set) || 536 (0 == action_set_ptr[field_action_set].size)) { 537 continue; 538 } else { 539 if (aset_cnt[field_action_set] ==0) { 540 aset_key_size += 541 action_set_ptr[field_action_set].size; 542 aset_cnt[field_action_set]++; 543 } 544 } 545 } 546 } 547 /* Check if L3SW/Redirect action is set. 548 * If yes then reserve 1 bit for Green To Pid. */ 549 if (aset_cnt[_FieldActionL3SwChangeL2Set] || 550 aset_cnt[_FieldActionRedirectSet]) { 551 aset_key_size += 552 action_set_ptr[_FieldActionGreenToPidSet].size; 553 } 554 return aset_key_size; 555 } 556 557 558 /* Add internal actions associated with main Action */ 559 int 560 _bcm_field_qset_update_with_internal_actions(int unit, _field_group_t *fg) 561 { 562 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 563 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionIntEncapEnable) || 564 BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionNshEncapEnable)) { 565 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionEditCtrlId); 566 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionExtractionCtrlId); 567 } 568 569 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionIntTurnAround)) { 570 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionEditCtrlId); 571 } 572 573 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionIntEncapUpdate)) { 574 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionExtractionCtrlId); 575 } 576 577 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionAddIngOuterVlanToEgrOuterVlan) || 578 BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionErspan3HdrVlanCosPktCopy)) { 579 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionExtractionCtrlId); 580 } 581 582 #if 0 583 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionErspan3HdrGbpSrcIdAdd)) { 584 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionOpaque3); 585 } 586 587 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionErspan3HdrUdf2Add)) { 588 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionOpaque4); 589 } 590 #endif /* 0 */ 591 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionNshServiceIndex)) { 592 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionOpaque2); 593 } 594 595 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionNshServicePathId)) { 596 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionOpaque1); 597 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionOpaque2); 598 } 599 600 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionGbpSrcIdNew) 601 || BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionAssignNatClassId)) { 602 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionOpaque1); 603 } 604 605 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionGbpDstIdNew)) { 606 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionOpaque2); 607 } 608 609 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionAssignChangeL2FieldsClassId)) { 610 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionOpaque3); 611 } 612 613 if ((BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionGbpSrcMacMcastBitSet)) 614 || (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionGbpClassifierAdd))) { 615 BCM_FIELD_ASET_ADD(fg->aset, _bcmFieldActionExtractionCtrlId); 616 } 617 618 #endif /* BCM_TRIDENT3_SUPPORT */ 619 return BCM_E_NONE; 620 } 621 622 /* 623 * Function: 624 * _field_group_check_action_profile 625 * Purpose: 626 * Check if same action profile is shared 627 * Parameters: 628 * unit - (IN) BCM device number. 629 * fg - (IN) Field group structure. 630 * new_action_profile - (OUT) New Action Profile pointer. 631 * Returns: 632 * BCM_E_XXX 633 * Notes: 634 * This function will check if action profile indexes associated 635 * to provided group is shared by any other group in same stage. 636 * If found then it will update new_action_profile to 1. 637 */ 638 int 639 _field_group_check_action_profile(int unit, _field_group_t *fg, 640 uint16 *new_action_profile) 641 { 642 _field_control_t *fc = NULL; 643 uint16 ap_idx1 = 0, ap_idx2 = 0; 644 _field_group_t *fgt = NULL; 645 646 /* input parameter check */ 647 if (fg == NULL || new_action_profile == NULL) { 648 return (BCM_E_INTERNAL); 649 } 650 651 /* get field control strucutre */ 652 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 653 654 /* check if there is any other group with same action_profile index */ 655 for (fgt = fc->groups; fgt != NULL; fgt = fgt->next) { 656 if ((fgt->gid == fg->gid) || (fgt->stage_id != fg->stage_id)) { 657 continue; 658 } 659 for (ap_idx1 = 0; ap_idx1 < MAX_ACT_PROF_ENTRIES_PER_GROUP; ap_idx1++) { 660 if (fgt->action_profile_idx[ap_idx1] != -1) { 661 for (ap_idx2 = 0; ap_idx2 < MAX_ACT_PROF_ENTRIES_PER_GROUP; ap_idx2++) { 662 if (fgt->action_profile_idx[ap_idx1] == 663 fg->action_profile_idx[ap_idx2]) { 664 *new_action_profile = 1; 665 break; 666 } 667 } 668 } 669 } 670 } 671 672 return (BCM_E_NONE); 673 } 674 675 /* 676 * Function: 677 * _field_calc_group_aset_size 678 * Purpose: 679 * For TD3 IFP 680 * Calculate the Aset size 681 * Parameters: 682 * unit - (IN) BCM device number. 683 * fg - (IN) Field group structure. 684 * aset_size - (IN/OUT) group's Aset size 685 * Returns: 686 * BCM_E_XXX 687 */ 688 int 689 _field_calc_group_aset_size(int unit, _field_group_t *fg, uint16 *aset_size) 690 { 691 _field_stage_t *stage_fc = NULL; /* Field Stage Control. */ 692 _bcm_field_aset_t aset; /* Action Set. */ 693 uint16 aset_key_size = 0; /* Action Set Size. */ 694 uint8 aset_cnt[_FieldActionSetCount] = {0}; 695 /* Action Per Set Count. */ 696 int a_idx; /* Action Iterator. */ 697 _bcm_field_action_set_t *action_set_ptr; 698 /* action set pointer */ 699 _bcm_field_action_conf_t *action_conf_ptr; 700 /* action configuration pointer */ 701 uint8 field_action_set; /* to hold Aset enum */ 702 uint8 setChangeCosOrIntPriSet = 0; /* For Actions which has 2 Asets */ 703 uint8 setMeterSet = 0; /* For color dependent actions 704 meter set should be enabled */ 705 706 /* Input parameters check. */ 707 if (NULL == fg) { 708 return BCM_E_INTERNAL; 709 } 710 711 /* Retreive Action Set */ 712 aset = fg->aset; 713 714 /* Check whether it is a valid stage */ 715 /* this fucntion is valid for TD3 IFP */ 716 if (!(soc_feature(unit, soc_feature_ifp_action_profiling) 717 && (fg->stage_id == _BCM_FIELD_STAGE_INGRESS))) 718 { 719 return BCM_E_NONE; 720 } 721 722 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 723 &stage_fc)); 724 725 action_set_ptr = stage_fc->action_set_ptr; 726 /* Calculate Action Size. */ 727 for (a_idx = 0; a_idx < _bcmFieldActionCount; a_idx++) { 728 if (BCM_FIELD_ASET_TEST(aset, a_idx)) { 729 /* test whether the current action is supported in this stage */ 730 action_conf_ptr = stage_fc->f_action_arr[a_idx]; 731 if (NULL != action_conf_ptr) { 732 /* get the aset enum from action_conf_pointer */ 733 field_action_set = action_conf_ptr->offset->aset; 734 /* PrioPktAndInt* actions needs 2 action Sets: 735 1: _FieldActionChangePktPriSet 736 2: _FieldActionChangeCosOrIntPriSet 737 _FieldActionChangePktPriSet is set as part of 738 action initialization. 2nd Set to be taken care here 739 */ 740 /* check whether the action is PrioPktAndInt* actions */ 741 if (BCM_FIELD_ACTION_PRIO_PKT_AND_INT_TEST(a_idx)) { 742 setChangeCosOrIntPriSet = 1; 743 } 744 } else if (a_idx == bcmFieldActionPolicerGroup) { 745 /* Flag in ASETs to indicate group 746 * policer usage with the group */ 747 field_action_set = _FieldActionMeterSet; 748 } else if (a_idx == bcmFieldActionStatGroup) { 749 /* Flag in ASETs to indicate stat group 750 * usage with the group */ 751 field_action_set = _FieldActionCounterSet; 752 } else { 753 /* action is not supported in this stage */ 754 /* add log_error with stage, action, chip*/ 755 LOG_ERROR(BSL_LS_BCM_FP, 756 (BSL_META_U(unit, 757 "FP(unit %d) Error: action=%s(%d) not supported\n"), 758 unit, 759 _field_action_name(a_idx), 760 a_idx 761 )); 762 return BCM_E_UNAVAIL; 763 } 764 /* if the aset for current action is 0, or 765 action_set size is 0 for this stage/chip 766 skip the hw field updation step */ 767 if ((0 == field_action_set) || 768 (0 == action_set_ptr[field_action_set].size)) { 769 continue; 770 } else { 771 if (aset_cnt[field_action_set] ==0) { 772 aset_key_size += 773 action_set_ptr[field_action_set].size; 774 aset_cnt[field_action_set]++; 775 } 776 if (1 == action_set_ptr[field_action_set].is_color_dependent) { 777 setMeterSet = 1; 778 } 779 } 780 } 781 } 782 /* Set CosorIntPriSet in action profile mem and 783 update key size if prioPktAndInt* actions are 784 present in current group's Aset */ 785 if (1 == setChangeCosOrIntPriSet) { 786 if (0 == aset_cnt[_FieldActionChangeCosOrIntPriSet]) { 787 aset_key_size += 788 action_set_ptr[_FieldActionChangeCosOrIntPriSet].size; 789 } 790 } 791 /* Set MeterSet in action profile mem and 792 update key size if any color dependent actions are 793 present in current group's Aset */ 794 if (1 == setMeterSet) { 795 if (0 == aset_cnt[_FieldActionMeterSet]) { 796 aset_key_size += 797 action_set_ptr[_FieldActionMeterSet].size; 798 /* add meter Aset to fg's aset internally */ 799 BCM_FIELD_ASET_ADD(fg->aset, bcmFieldActionPolicerGroup); 800 } 801 } 802 /* Check if L3SW/Redirect action is set. 803 * If yes then reserve 1 bit for Green To Pid. */ 804 if (aset_cnt[_FieldActionL3SwChangeL2Set] || 805 aset_cnt[_FieldActionRedirectSet]) { 806 aset_key_size += 807 action_set_ptr[_FieldActionGreenToPidSet].size; 808 } 809 /* Update Aset size in group's structure */ 810 if (0 == aset_key_size) { 811 LOG_VERBOSE(BSL_LS_BCM_FP,(BSL_META_U(unit, 812 "VERB: Trying to create group with no actions\n" 813 "Creating the group with all supporting actions\n"))); 814 /* Update the group's Aset with all supported actions */ 815 BCM_IF_ERROR_RETURN(_field_group_default_aset_set(unit, fg)); 816 BCM_FIELD_ASET_ADD(fg->aset, bcmFieldActionPolicerGroup); 817 BCM_FIELD_ASET_ADD(fg->aset, bcmFieldActionStatGroup); 818 (void)_bcm_field_qset_update_with_internal_actions(unit, fg); 819 /* Set the group's Aset size to 820 cummulative of all supporing Action sets size */ 821 aset_key_size = _field_calc_aset_size_all_actions(unit, fg); 822 } 823 *aset_size = aset_key_size; 824 return BCM_E_NONE; 825 } 826 827 /* 828 * Function: 829 * _field_th_group_add_aset_validate 830 * Purpose: 831 * For TH EM and TD3 IFP, EM 832 * Calculate the Aset size and 833 * allocate the action profile pointer for group 834 * Parameters: 835 * unit - (IN) BCM device number. 836 * fsm_ptr - (IN/OUT) State machine tracking structure. 837 * Returns: 838 * BCM_E_XXX 839 */ 840 STATIC int 841 _field_th_group_add_aset_validate(int unit, _field_group_add_fsm_t *fsm_ptr) 842 { 843 _field_group_t *fg; /* Field Group structure pointer. */ 844 _field_stage_t *stage_fc = NULL; /* Field Stage Control. */ 845 _bcm_field_aset_t aset; /* Action Set. */ 846 uint16 aset_key_size = 0, aset_size =0; /* Action Set Size. */ 847 uint8 aset_cnt[_FieldActionSetCount] = {0}; 848 /* Action Per Set Count. */ 849 int a_idx; /* Action Iterator. */ 850 void *entries[1]; /* Profile Entry. */ 851 void *act_prof_entry[MAX_ACT_PROF_ENTRIES_PER_GROUP]; 852 /* Profile table buffer pointer */ 853 soc_mem_t mem; /* Memory Identifier. */ 854 exact_match_action_profile_entry_t em_act_prof_entry; 855 /* Action Profile Table Buffer. */ 856 ifp_policy_action_profile_entry_t 857 ifp_act_prof_entry[MAX_ACT_PROF_ENTRIES_PER_GROUP]; 858 /* Action Profile Table Buffer. */ 859 uint32 action_profile_idx[MAX_ACT_PROF_ENTRIES_PER_GROUP]; 860 /* Action profile index */ 861 _bcm_field_action_set_t *action_set_ptr; 862 /* action set pointer */ 863 _bcm_field_action_conf_t *action_conf_ptr; 864 /* action configuration pointer */ 865 uint8 field_action_set; /* to hold Aset enum */ 866 uint8 multi_mode = 0; 867 uint8 setChangeCosOrIntPriSet = 0; /* For Actions which has 2 Asets */ 868 869 /* Input parameters check. */ 870 if (NULL == fsm_ptr) { 871 return (BCM_E_PARAM); 872 } 873 874 if (NULL == fsm_ptr->fg) { 875 fsm_ptr->rv = (BCM_E_PARAM); 876 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 877 return BCM_E_NONE; 878 } 879 /* Get field group structure. */ 880 fg = fsm_ptr->fg; 881 882 /* Save current state as the previous state. */ 883 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 884 fsm_ptr->rv = (BCM_E_NONE); 885 886 /* Retreive Action Set */ 887 aset = fg->aset; 888 889 #if defined(BCM_FLOWTRACKER_SUPPORT) 890 if ((soc_feature(unit, soc_feature_field_flowtracker_support)) && 891 (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id)) { 892 /* Verify actions */ 893 for (a_idx = 0; a_idx < _bcmFieldActionCount; a_idx++) { 894 if (BCM_FIELD_ASET_TEST(aset, a_idx)) { 895 switch(a_idx) { 896 case bcmFieldActionFlowtrackerGroupId: 897 case bcmFieldActionFlowtrackerEnable: 898 case bcmFieldActionFlowtrackerNewLearnEnable: 899 aset_size++; 900 break; 901 default: 902 fsm_ptr->rv = (BCM_E_UNAVAIL); 903 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 904 return (BCM_E_NONE); 905 } 906 } 907 } 908 if (aset_size == 0) { 909 /* Update the group's Aset with all supported actions */ 910 BCM_IF_ERROR_RETURN(_field_group_default_aset_set(unit, fg)); 911 } 912 goto clean_up; 913 } 914 #endif 915 916 /* Check whether it is a valid stage */ 917 if (!(((SOC_IS_TOMAHAWKX(unit)) 918 && (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH)) 919 || soc_feature(unit, soc_feature_ifp_action_profiling))) { 920 goto clean_up; 921 } 922 /* Assign correct Action Profile Memory 923 * and Action set's depending on stage */ 924 if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 925 /* Assign Exact Match Action Profile Memory */ 926 mem = EXACT_MATCH_ACTION_PROFILEm; 927 act_prof_entry[0] = &em_act_prof_entry; 928 sal_memcpy(act_prof_entry[0], soc_mem_entry_null(unit, mem), 929 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 930 } else { 931 /* Assign ifp Action Profile Memory */ 932 mem = IFP_POLICY_ACTION_PROFILEm; 933 for (a_idx =0;a_idx < MAX_ACT_PROF_ENTRIES_PER_GROUP; a_idx++) { 934 act_prof_entry[a_idx] = &ifp_act_prof_entry[a_idx]; 935 sal_memcpy(act_prof_entry[a_idx], soc_mem_entry_null(unit, mem), 936 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 937 } 938 } 939 940 /* Update internal pseudo actions for the given ASET */ 941 BCM_IF_ERROR_RETURN(_bcm_field_qset_update_with_internal_actions(unit, fg)); 942 943 /* calculate Aset size */ 944 fsm_ptr->rv = _field_calc_group_aset_size(unit, fg, &aset_size); 945 if (BCM_FAILURE(fsm_ptr->rv)) { 946 goto clean_up; 947 } 948 949 /* Retreive Action Set (it can be updated in above func */ 950 aset = fg->aset; 951 952 if (soc_feature(unit, soc_feature_ifp_action_profiling) && 953 (fg->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 954 if (aset_size > _FP_ASET_DATA_SIZE_FOR_POLICY_WIDE) { 955 /* we need to go for multi mode Policy tables */ 956 /* i.e., 2 IFP_POLICY_TABLE_WIDE entries will be 957 used to save the policy data corresponding to each entry 958 and correspondingly 2 action profiles will be used 959 for saving group's actions bitmaps. 960 The split will be based on color dependent Asets 961 in one action profile and color independent actions in 962 another Action profile entry */ 963 multi_mode = 1; 964 } 965 } 966 967 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 968 &stage_fc)); 969 action_set_ptr = stage_fc->action_set_ptr; 970 971 /* Calculate Action Size. */ 972 for (a_idx = 0; a_idx < _bcmFieldActionCount; a_idx++) { 973 if (BCM_FIELD_ASET_TEST(aset, a_idx)) { 974 /* test whether the current action is supported in this stage */ 975 action_conf_ptr = stage_fc->f_action_arr[a_idx]; 976 if (NULL != action_conf_ptr) { 977 /* get the aset enum from action_conf_pointer */ 978 field_action_set = action_conf_ptr->offset->aset; 979 /* PrioPktAndInt* actions needs 2 action Sets: 980 1: _FieldActionChangePktPriSet 981 2: _FieldActionChangeCosOrIntPriSet 982 _FieldActionChangePktPriSet is set as part of 983 action initialization. 2nd Set to be taken care here 984 */ 985 /* check whether the action is PrioPktAndInt* actions */ 986 if (BCM_FIELD_ACTION_PRIO_PKT_AND_INT_TEST(a_idx) 987 && fg->stage_id == _BCM_FIELD_STAGE_INGRESS) { 988 setChangeCosOrIntPriSet = 1; 989 } 990 } else if (a_idx == bcmFieldActionPolicerGroup) { 991 /* Flag in ASETs to indicate group 992 * policer usage with the group */ 993 field_action_set = _FieldActionMeterSet; 994 } else if (a_idx == bcmFieldActionStatGroup) { 995 /* Flag in ASETs to indicate stat group 996 * usage with the group */ 997 field_action_set = _FieldActionCounterSet; 998 } else { 999 /* action is not supported in this stage */ 1000 /* add log_error with stage, action, chip*/ 1001 LOG_ERROR(BSL_LS_BCM_FP, 1002 (BSL_META_U(unit, 1003 "FP(unit %d) Error: action=%s(%d) not supported\n"), 1004 unit, 1005 _field_action_name(a_idx), 1006 a_idx)); 1007 fsm_ptr->rv = (BCM_E_UNAVAIL); 1008 goto clean_up; 1009 } 1010 /* if the aset for current action is 0, or 1011 action_set size is 0 for this stage/chip 1012 skip the hw field updation step */ 1013 if ((0 == field_action_set) || 1014 (0 == action_set_ptr[field_action_set].size)) { 1015 continue; 1016 } else { 1017 if (aset_cnt[field_action_set] ==0) { 1018 if (1 == multi_mode) { 1019 /* check the color dependency of aset */ 1020 /* always 1st action profile will hold color dependent asets */ 1021 if (1 == action_set_ptr[field_action_set].is_color_dependent) { 1022 soc_mem_field32_set(unit, mem, act_prof_entry[0], 1023 action_set_ptr[field_action_set].hw_field, 1); 1024 } else { 1025 soc_mem_field32_set(unit, mem, act_prof_entry[1], 1026 action_set_ptr[field_action_set].hw_field, 1); 1027 } 1028 } else { 1029 soc_mem_field32_set(unit, mem, act_prof_entry[0], 1030 action_set_ptr[field_action_set].hw_field, 1); 1031 } 1032 1033 aset_key_size += 1034 action_set_ptr[field_action_set].size; 1035 aset_cnt[field_action_set]++; 1036 } 1037 } 1038 } 1039 } 1040 /* Set CosorIntPriSet in action profile mem and 1041 update key size if prioPktAndInt* actions are 1042 present in current group's Aset */ 1043 if (1 == setChangeCosOrIntPriSet) { 1044 if (0 == aset_cnt[_FieldActionChangeCosOrIntPriSet]) { 1045 aset_key_size += 1046 action_set_ptr[_FieldActionChangeCosOrIntPriSet].size; 1047 soc_mem_field32_set(unit, mem, act_prof_entry[0], 1048 action_set_ptr[_FieldActionChangeCosOrIntPriSet].hw_field, 1); 1049 } 1050 } 1051 /* Check if L3SW/Redirect action is set. 1052 * If yes then reserve 1 bit for Green To Pid. */ 1053 if (aset_cnt[_FieldActionL3SwChangeL2Set] || 1054 aset_cnt[_FieldActionRedirectSet]) { 1055 aset_key_size += 1056 action_set_ptr[_FieldActionGreenToPidSet].size; 1057 soc_mem_field32_set(unit, mem, act_prof_entry[0], 1058 action_set_ptr[_FieldActionGreenToPidSet].hw_field , 1); 1059 } 1060 1061 /* Update Aset size in group's structure */ 1062 fsm_ptr->aset_size = aset_key_size; 1063 1064 /* for single wide group, throw e-resource error 1065 * if the aset size is more than 181b */ 1066 if ((fg->stage_id == _BCM_FIELD_STAGE_INGRESS) && 1067 (((fsm_ptr->aset_size > _FP_ASET_DATA_SIZE_FOR_POLICY_NARROW) 1068 && (fsm_ptr->mode == bcmFieldGroupModeSingle)) 1069 || ((fsm_ptr->aset_size > _FP_ASET_DATA_SIZE_FOR_POLICY_WIDE) && 1070 (fsm_ptr->mode == bcmFieldGroupModeIntraSliceDouble)))) { 1071 /* ADD error msg here */ 1072 LOG_ERROR(BSL_LS_BCM_FP, 1073 (BSL_META_U(unit, "FP(unit %d) Error: Aset size =%d is not" 1074 "supported in this group mode.\n"), 1075 unit, fsm_ptr->aset_size)); 1076 1077 fsm_ptr->rv = (BCM_E_CONFIG); 1078 goto clean_up; 1079 } 1080 1081 entries[0] = act_prof_entry[0]; 1082 /* Add Entries To Action Profile Table In Hardware. */ 1083 fsm_ptr->rv = soc_profile_mem_add(unit, 1084 &stage_fc->action_profile[fg->instance], 1085 entries, 1, &action_profile_idx[0]); 1086 if (BCM_FAILURE(fsm_ptr->rv)) { 1087 goto clean_up; 1088 } 1089 1090 fg->action_profile_idx[0] = action_profile_idx[0]; 1091 1092 if (1 == multi_mode) { 1093 entries[0] = act_prof_entry[1]; 1094 /* Add Entries To Action Profile Table In Hardware. */ 1095 fsm_ptr->rv = soc_profile_mem_add(unit, 1096 &stage_fc->action_profile[fg->instance], 1097 entries, 1, &action_profile_idx[1]); 1098 fg->action_profile_idx[1] = action_profile_idx[1]; 1099 } 1100 1101 LOG_VERBOSE(BSL_LS_BCM_FP,(BSL_META_U(unit, 1102 "VERB: groups aset size %d \n\r"), 1103 fsm_ptr->aset_size)); 1104 1105 clean_up: 1106 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 1107 return (BCM_E_NONE); 1108 } 1109 1110 /* 1111 * Function: 1112 * _field_th_group_add_qset_update 1113 * Purpose: 1114 * Update application requested qset with internal qualifiers. 1115 * Parameters: 1116 * unit - (IN) BCM device number. 1117 * fsm_ptr - (IN/OUT) State machine tracking structure. 1118 * Returns: 1119 * BCM_E_XXX 1120 */ 1121 STATIC int 1122 _field_th_group_add_qset_update(int unit, _field_group_add_fsm_t *fsm_ptr) 1123 { 1124 _field_group_t *fg; /* Field Group structure pointer. */ 1125 1126 /* Input parameters check. */ 1127 if (NULL == fsm_ptr) { 1128 return (BCM_E_PARAM); 1129 } 1130 1131 if (NULL == fsm_ptr->fg) { 1132 fsm_ptr->rv = (BCM_E_PARAM); 1133 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 1134 return BCM_E_NONE; 1135 } 1136 1137 /* Get field group structure. */ 1138 fg = fsm_ptr->fg; 1139 1140 /* Save current state as the previous state. */ 1141 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 1142 1143 /* InPorts Qualifier is not supported in TD3. */ 1144 if (soc_feature(unit, soc_feature_ifp_no_inports_support) && 1145 BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPorts)) { 1146 LOG_WARN(BSL_LS_BCM_FP, (BSL_META_U(unit, 1147 "InPorts Qualifier is not supported.\n\r"))); 1148 fsm_ptr->rv = (BCM_E_PARAM); 1149 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 1150 return BCM_E_NONE; 1151 } 1152 1153 #if defined(BCM_HELIX5_SUPPORT) 1154 if (soc_feature(unit, soc_feature_flex_flowtracker_ver_1)) { 1155 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyFlowtrackerCheck) && 1156 (0 == BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyFlowtrackerGroupId))) { 1157 LOG_ERROR(BSL_LS_BCM_FP, 1158 (BSL_META_U(unit, 1159 "(unit %d) Error: Qualifier FlowtrackerCheck needs " 1160 " to be used qualifier FlowtrackerGroupId"), 1161 unit)); 1162 fsm_ptr->rv = BCM_E_CONFIG; 1163 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 1164 return BCM_E_NONE; 1165 } 1166 } 1167 #endif 1168 /* 1169 * In-case of Atomic update, InPorts qualifier is not supported 1170 * in Global mode. 1171 */ 1172 if ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) && 1173 (_BCM_FIELD_QSET_PBMP_TEST(fg->qset))) { 1174 _field_stage_t *stage_fc; /* Stage Field control structure. */ 1175 1176 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 1177 &stage_fc)); 1178 if ((soc_property_get(unit, spn_FIELD_ATOMIC_UPDATE, FALSE) == TRUE) && 1179 (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal)) { 1180 LOG_WARN(BSL_LS_BCM_FP, (BSL_META_U(unit, 1181 "InPorts Qualifier is not supported in Global mode" 1182 " incase of atomic update.\n\r"))); 1183 fsm_ptr->rv = (BCM_E_PARAM); 1184 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 1185 return BCM_E_NONE; 1186 } 1187 } 1188 1189 /* 1190 * PBMP qualifiers conflict check. 1191 * Group QSET should not contain more than one PBMP qualifier. 1192 */ 1193 if (_BCM_FIELD_QSET_PBMP_TEST(fg->qset)) { 1194 int pbm_qual; 1195 1196 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPorts)) { 1197 pbm_qual = bcmFieldQualifyInPorts; 1198 BCM_FIELD_QSET_REMOVE(fg->qset, pbm_qual); 1199 } else if (BCM_FIELD_QSET_TEST(fg->qset, 1200 bcmFieldQualifyDevicePortBitmap)) { 1201 pbm_qual = bcmFieldQualifyDevicePortBitmap; 1202 BCM_FIELD_QSET_REMOVE(fg->qset, pbm_qual); 1203 } else if (BCM_FIELD_QSET_TEST(fg->qset, 1204 bcmFieldQualifySystemPortBitmap)) { 1205 pbm_qual = bcmFieldQualifySystemPortBitmap; 1206 BCM_FIELD_QSET_REMOVE(fg->qset, pbm_qual); 1207 } else { 1208 pbm_qual = bcmFieldQualifySourceGportBitmap; 1209 BCM_FIELD_QSET_REMOVE(fg->qset, pbm_qual); 1210 } 1211 1212 if (_BCM_FIELD_QSET_PBMP_TEST(fg->qset)) { 1213 LOG_WARN(BSL_LS_BCM_FP, (BSL_META_U(unit, 1214 "More than one Port Bitmap Qualifier is not supported in a" 1215 " group.\n\r"))); 1216 fsm_ptr->rv = (BCM_E_PARAM); 1217 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 1218 BCM_FIELD_QSET_ADD(fg->qset, pbm_qual); 1219 return BCM_E_NONE; 1220 } 1221 1222 BCM_FIELD_QSET_ADD(fg->qset, pbm_qual); 1223 #if defined BCM_TRIDENT3_SUPPORT 1224 if (soc_feature(unit, soc_feature_td3_style_fp) && 1225 (pbm_qual == bcmFieldQualifyInPorts)) { 1226 BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifyInPorts_1); 1227 BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifyInPorts_2); 1228 } 1229 #endif /* BCM_TRIDENT3_SUPPORT */ 1230 } 1231 1232 /* All ingress devices implicitly have "bcmFieldQualifyStage" in QSETs. */ 1233 if ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || 1234 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) || 1235 (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id)) { 1236 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyStage); 1237 } 1238 1239 /* Automatically include "IpType" if QSET contains Ip4 or Ip6 qualifier. */ 1240 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4) 1241 || BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6)) { 1242 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyIpType); 1243 } 1244 1245 /* Include "LogicalTableId", if preselectors are associated to the group. */ 1246 if ((fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) && 1247 (fg->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER)) { 1248 BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifyPreLogicalTableId); 1249 } 1250 1251 if((fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) && 1252 (soc_feature(unit, soc_feature_bscan_fae_port_flow_exclude))) { 1253 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInPort); 1254 } 1255 1256 /* Update Exact Match Qset. */ 1257 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyExactMatchHitStatus)) { 1258 if ((!BCM_FIELD_QSET_TEST(fg->qset, 1259 _bcmFieldQualifyExactMatchHitStatusLookup0)) && 1260 (!BCM_FIELD_QSET_TEST(fg->qset, 1261 _bcmFieldQualifyExactMatchHitStatusLookup1))) { 1262 BCM_FIELD_QSET_ADD(fg->qset, 1263 _bcmFieldQualifyExactMatchHitStatusLookup0); 1264 if (!soc_feature(unit, soc_feature_th3_style_fp)) { 1265 BCM_FIELD_QSET_ADD(fg->qset, 1266 _bcmFieldQualifyExactMatchHitStatusLookup1); 1267 } 1268 } 1269 } 1270 1271 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyExactMatchGroupClassId)) { 1272 if ((!BCM_FIELD_QSET_TEST(fg->qset, 1273 _bcmFieldQualifyExactMatchGroupClassIdLookup0)) && 1274 (!BCM_FIELD_QSET_TEST(fg->qset, 1275 _bcmFieldQualifyExactMatchGroupClassIdLookup1))) { 1276 BCM_FIELD_QSET_ADD(fg->qset, 1277 _bcmFieldQualifyExactMatchGroupClassIdLookup0); 1278 if (!soc_feature(unit, soc_feature_th3_style_fp)) { 1279 BCM_FIELD_QSET_ADD(fg->qset, 1280 _bcmFieldQualifyExactMatchGroupClassIdLookup1); 1281 } 1282 } 1283 } 1284 1285 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyExactMatchActionClassId)) { 1286 if ((!BCM_FIELD_QSET_TEST(fg->qset, 1287 _bcmFieldQualifyExactMatchActionClassIdLookup0)) && 1288 (!BCM_FIELD_QSET_TEST(fg->qset, 1289 _bcmFieldQualifyExactMatchActionClassIdLookup1))) { 1290 BCM_FIELD_QSET_ADD(fg->qset, 1291 _bcmFieldQualifyExactMatchActionClassIdLookup0); 1292 if (!soc_feature(unit, soc_feature_th3_style_fp)) { 1293 BCM_FIELD_QSET_ADD(fg->qset, 1294 _bcmFieldQualifyExactMatchActionClassIdLookup1); 1295 } 1296 } 1297 } 1298 1299 1300 /* 1301 * NOTE: 1302 * Since IPBM field is only optionally included in the IFP TCAM lookup key, 1303 * InPorts qualifier is part of the QSET only when user explicitly adds it 1304 * to the Group's QSET. SDK does not include it by default as its done 1305 * in Pre-TH devices. 1306 */ 1307 1308 /* Proceed to Extractor Mux selector selection. */ 1309 fsm_ptr->rv = (BCM_E_NONE); 1310 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_ASET_VALIDATE; 1311 1312 return (BCM_E_NONE); 1313 } 1314 1315 /* 1316 * Function: 1317 * _field_th_group_extractors_init 1318 * Purpose: 1319 * Initialize field group extractor codes. 1320 * Parameters: 1321 * unit - (IN) BCM unit number. 1322 * fg - (IN/OUT) Field Group structure. 1323 * Returns: 1324 * BCM_E_XXX 1325 */ 1326 STATIC int 1327 _field_th_group_extractors_init(int unit, _field_group_t *fg) 1328 { 1329 /* Input parameters check. */ 1330 if (NULL == fg) { 1331 return (BCM_E_NONE); 1332 } 1333 1334 /* 1335 * Initialize group extractor code flags based on group mode being 1336 * created. 1337 */ 1338 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 1339 fg->ext_codes[1].intraslice = _FP_EXT_SELCODE_DONT_USE; 1340 } else if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 1341 fg->ext_codes[1].intraslice = _FP_EXT_SELCODE_DONT_USE; 1342 fg->ext_codes[2].intraslice = _FP_EXT_SELCODE_DONT_USE; 1343 } 1344 1345 fg->ext_codes[0].secondary = _FP_EXT_SELCODE_DONT_USE; 1346 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 1347 fg->ext_codes[1].secondary = _FP_EXT_SELCODE_DONT_USE; 1348 } else if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 1349 fg->ext_codes[1].secondary = _FP_EXT_SELCODE_DONT_USE; 1350 fg->ext_codes[2].secondary = _FP_EXT_SELCODE_DONT_USE; 1351 } 1352 1353 return (BCM_E_NONE); 1354 } 1355 1356 1357 int 1358 _field_th_group_qual_info_get(int unit, 1359 _field_stage_t *stage_fc, 1360 _field_group_t *fg, 1361 bcm_field_qset_t *qset_req, 1362 bcmi_keygen_qual_info_t **qual_info_arr, 1363 uint16 *qual_info_count) 1364 { 1365 uint16 idx = 0; 1366 uint16 qual_idx = 0; 1367 _bcm_field_internal_qualify_t qual_id = _bcmFieldQualifyCount; 1368 _field_hints_t *f_ht = NULL; 1369 _field_hint_t *hint_node = NULL; 1370 1371 /* Input parameters check. */ 1372 if (NULL == qual_info_arr || NULL == qset_req || NULL == fg || 1373 NULL == qual_info_count || NULL == stage_fc) { 1374 return (BCM_E_PARAM); 1375 } 1376 1377 SHR_BIT_ITER(qset_req->w, BCM_FIELD_QUALIFY_MAX, idx) { 1378 if (stage_fc->qual_cfg_info_db->qual_cfg_info[idx] == NULL) { 1379 continue; 1380 } 1381 (*qual_info_count)++; 1382 } 1383 1384 /* If No valid qualifiers, return */ 1385 if ((*qual_info_count) == 0) { 1386 *qual_info_arr = NULL; 1387 return (BCM_E_NONE); 1388 } 1389 1390 _FP_XGS3_ALLOC((*qual_info_arr), 1391 sizeof(bcmi_keygen_qual_info_t) * (*qual_info_count), 1392 "Keygen Qualifier Information"); 1393 SHR_BIT_ITER(qset_req->w, BCM_FIELD_QUALIFY_MAX, idx) { 1394 if (stage_fc->qual_cfg_info_db->qual_cfg_info[idx] == NULL) { 1395 continue; 1396 } 1397 (*qual_info_arr)[qual_idx].qual_id = idx; 1398 qual_idx++; 1399 } 1400 1401 if (!fg->hintid) { 1402 return BCM_E_NONE; 1403 } 1404 1405 BCM_IF_ERROR_RETURN(_field_hints_control_get(unit, fg->hintid, &f_ht)); 1406 1407 for (qual_idx = 0; qual_idx < *qual_info_count; qual_idx++) { 1408 qual_id = (*qual_info_arr)[qual_idx].qual_id; 1409 if (NULL != f_ht) { 1410 if (NULL != f_ht->hints) { 1411 /* Go through all hints in HintId and get the bit map of 1412 * qualifers with hints. 1413 */ 1414 hint_node = f_ht->hints; 1415 while (NULL != hint_node) { 1416 if (bcmFieldQualifyUdf != hint_node->hint->qual) { 1417 #if defined(BCM_HELIX5_SUPPORT) 1418 if ((bcmFieldHintTypeExtraction == hint_node->hint->hint_type) && 1419 (qual_id == (_bcm_field_internal_qualify_t) hint_node->hint->qual) && 1420 ((qual_id == (_bcm_field_internal_qualify_t) bcmFieldQualifyDosAttackEvents) || 1421 (qual_id == (_bcm_field_internal_qualify_t) bcmFieldQualifyInnerDosAttackEvents))) { 1422 BCM_IF_ERROR_RETURN( 1423 _bcm_field_hx5_dosattack_event_qual_bitmap(unit, 1424 hint_node, &(*qual_info_arr)[qual_idx])); 1425 hint_node = hint_node->next; 1426 continue; 1427 } 1428 #endif 1429 if (bcmFieldHintTypeExtraction == hint_node->hint->hint_type && 1430 (qual_id == (_bcm_field_internal_qualify_t)hint_node->hint->qual)) { 1431 SHR_BITSET_RANGE((*qual_info_arr)[qual_idx].bitmap, 1432 hint_node->hint->start_bit, 1433 (hint_node->hint->end_bit - 1434 hint_node->hint->start_bit + 1)); 1435 (*qual_info_arr)[qual_idx].partial = TRUE; 1436 } 1437 hint_node = hint_node->next; 1438 } else { 1439 if ((bcmFieldHintTypeExtraction == hint_node->hint->hint_type) && 1440 (_FIELD_IS_INTERNAL_UDF_QUAL(qual_id))) { 1441 BCM_IF_ERROR_RETURN(_bcm_th_qual_hint_bmp_get(unit, 1442 (int)qual_id, 0, hint_node, 1443 (*qual_info_arr)[qual_idx].bitmap, 1, 1444 qset_req, &(*qual_info_arr)[qual_idx])); 1445 } 1446 hint_node = hint_node->next; 1447 } 1448 } 1449 } 1450 } 1451 } 1452 1453 for (qual_idx = 0; qual_idx < *qual_info_count; qual_idx++) { 1454 qual_id = (*qual_info_arr)[qual_idx].qual_id; 1455 if (_FIELD_IS_INTERNAL_UDF_QUAL(qual_id)) { 1456 if((TRUE == (*qual_info_arr)[qual_idx].partial) 1457 && (0 == (*qual_info_arr)[qual_idx].bitmap[0])) { 1458 SHR_BITCLR(qset_req->w, qual_id); 1459 } 1460 } 1461 } 1462 return BCM_E_NONE; 1463 } 1464 1465 STATIC int 1466 _field_th_group_keygen_oper_insert(int unit, 1467 _field_group_t *fg, 1468 bcmi_keygen_oper_t *keygen_oper) 1469 { 1470 int rv = BCM_E_NONE; 1471 uint8 part = 0; 1472 uint8 gran = 0; 1473 uint8 level = 0; 1474 uint8 ctrl_sel_val = 0; 1475 int parts_count = 0; 1476 uint16 ext_num = 0; 1477 uint16 ext_code_idx = 0; 1478 uint16 qual_idx = 0; 1479 uint16 offset = 0; 1480 uint16 num_offsets = 0; 1481 _field_ext_sel_t *grp_ext_code = NULL; 1482 _bcm_field_group_qual_t *group_qual = NULL; 1483 bcmi_keygen_qual_offset_info_t *qual_offset_info = NULL; 1484 bcmi_keygen_ext_ctrl_sel_info_t *keygen_ext_code = NULL; 1485 1486 /* Get number of entry parts based on the field group flags. */ 1487 BCM_IF_ERROR_RETURN( 1488 _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, &parts_count)); 1489 1490 for (part = 0; part < parts_count; part++) { 1491 if (keygen_oper->qual_offset_info == NULL) { 1492 break; 1493 } 1494 group_qual = &(fg->qual_arr[0][part]); 1495 qual_offset_info = &(keygen_oper->qual_offset_info[part]); 1496 group_qual->size = qual_offset_info->size; 1497 /* Alloc larger mem since _bcmFieldInternalQualQid is wrongly set to 4.*/ 1498 _FP_XGS3_ALLOC(group_qual->qid_arr, 1499 qual_offset_info->size * sizeof(uint32), 1500 "Group Qualifer Information"); 1501 _FP_XGS3_ALLOC(group_qual->offset_arr, 1502 qual_offset_info->size * sizeof(_bcm_field_qual_offset_t), 1503 "Group Qualifer Offset Information"); 1504 for (qual_idx = 0; qual_idx < qual_offset_info->size; qual_idx++) { 1505 group_qual->qid_arr[qual_idx] = 1506 qual_offset_info->qid_arr[qual_idx]; 1507 group_qual->offset_arr[qual_idx].field = KEYf; 1508 num_offsets = 0; 1509 for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) { 1510 if (!qual_offset_info->offset_arr[qual_idx].width[offset]) { 1511 continue; 1512 } 1513 group_qual->offset_arr[qual_idx].offset[offset] = 1514 qual_offset_info->offset_arr[qual_idx].offset[offset]; 1515 group_qual->offset_arr[qual_idx].width[offset] = 1516 qual_offset_info->offset_arr[qual_idx].width[offset]; 1517 num_offsets++; 1518 if (num_offsets == 1519 qual_offset_info->offset_arr[qual_idx].num_offsets) { 1520 break; 1521 } 1522 } 1523 group_qual->offset_arr[qual_idx].num_offsets = (offset + 1); 1524 } 1525 } 1526 1527 for (ext_code_idx = 0; 1528 ext_code_idx < keygen_oper->ext_ctrl_sel_info_count; 1529 ext_code_idx++) { 1530 keygen_ext_code = &(keygen_oper->ext_ctrl_sel_info[ext_code_idx]); 1531 part = keygen_ext_code->part; 1532 gran = keygen_ext_code->gran; 1533 level = keygen_ext_code->level; 1534 ext_num = keygen_ext_code->ext_num; 1535 ctrl_sel_val = keygen_ext_code->ctrl_sel_val; 1536 grp_ext_code = &(fg->ext_codes[part]); 1537 if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER) { 1538 if (level == 1) { 1539 if (gran == 32) { 1540 grp_ext_code->l1_e32_sel[ext_num] = ctrl_sel_val; 1541 } else if (gran == 16) { 1542 grp_ext_code->l1_e16_sel[ext_num] = ctrl_sel_val; 1543 } else if (gran == 8) { 1544 grp_ext_code->l1_e8_sel[ext_num] = ctrl_sel_val; 1545 } else if (gran == 4) { 1546 grp_ext_code->l1_e4_sel[ext_num] = ctrl_sel_val; 1547 } else if (gran == 2) { 1548 grp_ext_code->l1_e2_sel[ext_num] = ctrl_sel_val; 1549 } else { 1550 rv = BCM_E_INTERNAL; 1551 goto cleanup; 1552 } 1553 } else if (level == 2) { 1554 if (gran == 16) { 1555 grp_ext_code->l2_e16_sel[ext_num] = ctrl_sel_val; 1556 } 1557 #if defined(BCM_TOMAHAWK3_SUPPORT) 1558 else if (gran == 4) { 1559 if (SOC_IS_TOMAHAWK3(unit)) { 1560 grp_ext_code->l2_e4_sel[ext_num] = ctrl_sel_val; 1561 } else { 1562 rv = BCM_E_INTERNAL; 1563 goto cleanup; 1564 } 1565 } else if (gran == 2) { 1566 if (SOC_IS_TOMAHAWK3(unit)) { 1567 grp_ext_code->l2_e2_sel[ext_num] = ctrl_sel_val; 1568 } else { 1569 rv = BCM_E_INTERNAL; 1570 goto cleanup; 1571 } 1572 } else if (gran == 1) { 1573 if (SOC_IS_TOMAHAWK3(unit)) { 1574 grp_ext_code->l2_e1_sel[ext_num] = ctrl_sel_val; 1575 } else { 1576 rv = BCM_E_INTERNAL; 1577 goto cleanup; 1578 } 1579 } 1580 #endif 1581 else { 1582 rv = BCM_E_INTERNAL; 1583 goto cleanup; 1584 } 1585 } else if (level == 3) { 1586 if (gran == 4) { 1587 grp_ext_code->l3_e4_sel[ext_num] = ctrl_sel_val; 1588 } else if (gran == 2) { 1589 grp_ext_code->l3_e2_sel[ext_num] = ctrl_sel_val; 1590 } else if (gran == 1) { 1591 grp_ext_code->l3_e1_sel[ext_num] = ctrl_sel_val; 1592 } else { 1593 rv = BCM_E_INTERNAL; 1594 goto cleanup; 1595 } 1596 } else { 1597 rv = BCM_E_INTERNAL; 1598 goto cleanup; 1599 } 1600 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_AUX_TAG_A) { 1601 grp_ext_code->aux_tag_a_sel = keygen_ext_code->ctrl_sel_val; 1602 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_AUX_TAG_B) { 1603 grp_ext_code->aux_tag_b_sel = keygen_ext_code->ctrl_sel_val; 1604 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_AUX_TAG_C) { 1605 grp_ext_code->aux_tag_c_sel = keygen_ext_code->ctrl_sel_val; 1606 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_AUX_TAG_D) { 1607 grp_ext_code->aux_tag_d_sel = keygen_ext_code->ctrl_sel_val; 1608 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_TCP_FN) { 1609 grp_ext_code->tcp_fn_sel = keygen_ext_code->ctrl_sel_val; 1610 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_TOS_FN) { 1611 grp_ext_code->tos_fn_sel = keygen_ext_code->ctrl_sel_val; 1612 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_TTL_FN) { 1613 grp_ext_code->ttl_fn_sel = keygen_ext_code->ctrl_sel_val; 1614 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_CLASSID_A) { 1615 grp_ext_code->class_id_cont_a_sel = keygen_ext_code->ctrl_sel_val; 1616 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_CLASSID_B) { 1617 grp_ext_code->class_id_cont_b_sel = keygen_ext_code->ctrl_sel_val; 1618 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_CLASSID_C) { 1619 grp_ext_code->class_id_cont_c_sel = keygen_ext_code->ctrl_sel_val; 1620 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_CLASSID_D) { 1621 grp_ext_code->class_id_cont_d_sel = keygen_ext_code->ctrl_sel_val; 1622 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_SRC_A) { 1623 grp_ext_code->src_cont_a_sel = keygen_ext_code->ctrl_sel_val; 1624 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_SRC_B) { 1625 grp_ext_code->src_cont_b_sel = keygen_ext_code->ctrl_sel_val; 1626 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_DST_A) { 1627 grp_ext_code->dst_cont_a_sel = keygen_ext_code->ctrl_sel_val; 1628 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_DST_B) { 1629 grp_ext_code->dst_cont_b_sel = keygen_ext_code->ctrl_sel_val; 1630 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_SRC_DST_0) { 1631 grp_ext_code->src_dest_cont_0_sel = keygen_ext_code->ctrl_sel_val; 1632 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_SRC_DST_1) { 1633 grp_ext_code->src_dest_cont_1_sel = keygen_ext_code->ctrl_sel_val; 1634 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_IPBM_PRESENT) { 1635 grp_ext_code->ipbm_present = 1; 1636 grp_ext_code->ipbm_source = keygen_ext_code->ctrl_sel_val; 1637 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_L3_L4_NORM) { 1638 grp_ext_code->normalize_l3_l4_sel = keygen_ext_code->ctrl_sel_val; 1639 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_MAC_NORM) { 1640 grp_ext_code->normalize_mac_sel = keygen_ext_code->ctrl_sel_val; 1641 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_UDF) { 1642 grp_ext_code->udf_sel = keygen_ext_code->ctrl_sel_val; 1643 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_PMUX) { 1644 grp_ext_code->pmux_sel[ctrl_sel_val] = 1; 1645 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_ALT_TTL_FN) { 1646 grp_ext_code->alt_ttl_fn_sel = keygen_ext_code->ctrl_sel_val; 1647 } else if (keygen_ext_code->ctrl_sel == BCMI_KEYGEN_EXT_CTRL_SEL_LTID) { 1648 continue; 1649 } else { 1650 rv = BCM_E_INTERNAL; 1651 goto cleanup; 1652 } 1653 } 1654 1655 for (part = 0; part < parts_count; part++) { 1656 fg->ext_codes[part].normalize_l3_l4_sel = 1657 BCM_FIELD_QSET_TEST(fg->qset, 1658 bcmFieldQualifyNormalizeIpAddrs) ? 1 : 0; 1659 fg->ext_codes[part].normalize_mac_sel = 1660 BCM_FIELD_QSET_TEST(fg->qset, 1661 bcmFieldQualifyNormalizeMacAddrs) ? 1 : 0; 1662 } 1663 1664 1665 if ((BCM_FIELD_QSET_TEST(fg->qset, 1666 _bcmFieldQualifyPreLogicalTableId)) && 1667 ((fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) || 1668 (fg->stage_id == _BCM_FIELD_STAGE_INGRESS))) { 1669 if (SOC_IS_TOMAHAWK(unit) 1670 #if defined(BCM_TOMAHAWK2_SUPPORT) 1671 || SOC_IS_TOMAHAWK2(unit) 1672 #endif 1673 #if defined(BCM_TRIDENT3_SUPPORT) 1674 || (soc_feature(unit, soc_feature_td3_style_fp)) 1675 #endif 1676 ) { 1677 fg->ext_codes[0].l1_e8_sel[6]=5; 1678 fg->ext_codes[0].l3_e4_sel[20]=36; 1679 fg->ext_codes[0].l3_e2_sel[1]=74; 1680 } 1681 #if defined(BCM_TOMAHAWK3_SUPPORT) 1682 else if (SOC_IS_TOMAHAWK3(unit)) { 1683 fg->ext_codes[0].l1_e8_sel[5]=12; 1684 fg->ext_codes[0].l2_e4_sel[11]=46; 1685 } 1686 #endif 1687 } 1688 1689 return rv; 1690 1691 cleanup: 1692 for (part = 0; part < parts_count; part++) { 1693 group_qual = &(fg->qual_arr[0][part]); 1694 if (group_qual->qid_arr != NULL) { 1695 sal_free(group_qual->qid_arr); 1696 } 1697 if (group_qual->offset_arr != NULL) { 1698 sal_free(group_qual->offset_arr); 1699 } 1700 } 1701 return rv; 1702 } 1703 1704 STATIC int 1705 _field_th_keygen_ext_ctrl_info_count_get(int unit, 1706 _field_group_t *fg, 1707 uint16 *ext_ctrl_info_count) 1708 { 1709 uint8 part = 0; 1710 int parts_count = 0; 1711 uint8 idx = 0; 1712 1713 /* Input parameters check. */ 1714 if (NULL == fg || NULL == ext_ctrl_info_count) { 1715 return (BCM_E_PARAM); 1716 } 1717 1718 /* Get number of entry parts based on the field group flags. */ 1719 BCM_IF_ERROR_RETURN( 1720 _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, &parts_count)); 1721 *ext_ctrl_info_count = 0; 1722 for (part = 0; part < parts_count; part++) { 1723 if (fg->ext_codes[part].aux_tag_a_sel != -1) { 1724 (*ext_ctrl_info_count)++; 1725 } 1726 if (fg->ext_codes[part].aux_tag_b_sel != -1) { 1727 (*ext_ctrl_info_count)++; 1728 } 1729 if (fg->ext_codes[part].aux_tag_c_sel != -1) { 1730 (*ext_ctrl_info_count)++; 1731 } 1732 if (fg->ext_codes[part].aux_tag_d_sel != -1) { 1733 (*ext_ctrl_info_count)++; 1734 } 1735 if (fg->ext_codes[part].tcp_fn_sel != -1) { 1736 (*ext_ctrl_info_count)++; 1737 } 1738 if (fg->ext_codes[part].ttl_fn_sel != -1) { 1739 (*ext_ctrl_info_count)++; 1740 } 1741 if (fg->ext_codes[part].tos_fn_sel != -1) { 1742 (*ext_ctrl_info_count)++; 1743 } 1744 if (fg->ext_codes[part].class_id_cont_a_sel != -1) { 1745 (*ext_ctrl_info_count)++; 1746 } 1747 if (fg->ext_codes[part].class_id_cont_b_sel != -1) { 1748 (*ext_ctrl_info_count)++; 1749 } 1750 if (fg->ext_codes[part].class_id_cont_c_sel != -1) { 1751 (*ext_ctrl_info_count)++; 1752 } 1753 if (fg->ext_codes[part].class_id_cont_d_sel != -1) { 1754 (*ext_ctrl_info_count)++; 1755 } 1756 if (fg->ext_codes[part].src_cont_a_sel != -1) { 1757 (*ext_ctrl_info_count)++; 1758 } 1759 if (fg->ext_codes[part].src_cont_b_sel != -1) { 1760 (*ext_ctrl_info_count)++; 1761 } 1762 if (fg->ext_codes[part].src_dest_cont_0_sel != -1) { 1763 (*ext_ctrl_info_count)++; 1764 } 1765 if (fg->ext_codes[part].src_dest_cont_1_sel != -1) { 1766 (*ext_ctrl_info_count)++; 1767 } 1768 if (fg->ext_codes[part].ipbm_present != -1) { 1769 (*ext_ctrl_info_count)++; 1770 } 1771 if (fg->ext_codes[part].normalize_l3_l4_sel != -1) { 1772 (*ext_ctrl_info_count)++; 1773 } 1774 if (fg->ext_codes[part].normalize_mac_sel != -1) { 1775 (*ext_ctrl_info_count)++; 1776 } 1777 for (idx = 0; idx < 15; idx++) { 1778 if (fg->ext_codes[part].pmux_sel[idx] != -1) { 1779 (*ext_ctrl_info_count)++; 1780 } 1781 } 1782 for (idx = 0; idx < 4; idx++) { 1783 if (fg->ext_codes[part].l1_e32_sel[idx] != -1) { 1784 (*ext_ctrl_info_count)++; 1785 } 1786 } 1787 for (idx = 0; idx < 7; idx++) { 1788 if (fg->ext_codes[part].l1_e16_sel[idx] != -1) { 1789 (*ext_ctrl_info_count)++; 1790 } 1791 } 1792 for (idx = 0; idx < 7; idx++) { 1793 if (fg->ext_codes[part].l1_e8_sel[idx] != -1) { 1794 (*ext_ctrl_info_count)++; 1795 } 1796 } 1797 for (idx = 0; idx < 8; idx++) { 1798 if (fg->ext_codes[part].l1_e4_sel[idx] != -1) { 1799 (*ext_ctrl_info_count)++; 1800 } 1801 } 1802 for (idx = 0; idx < 8; idx++) { 1803 if (fg->ext_codes[part].l1_e2_sel[idx] != -1) { 1804 (*ext_ctrl_info_count)++; 1805 } 1806 } 1807 for (idx = 0; idx < 10; idx++) { 1808 if (fg->ext_codes[part].l2_e16_sel[idx] != -1) { 1809 (*ext_ctrl_info_count)++; 1810 } 1811 } 1812 for (idx = 0; idx < 16; idx++) { 1813 if (fg->ext_codes[part].l2_e4_sel[idx] != -1) { 1814 (*ext_ctrl_info_count)++; 1815 } 1816 } 1817 for (idx = 0; idx < 7; idx++) { 1818 if (fg->ext_codes[part].l2_e2_sel[idx] != -1) { 1819 (*ext_ctrl_info_count)++; 1820 } 1821 } 1822 for (idx = 0; idx < 2; idx++) { 1823 if (fg->ext_codes[part].l2_e1_sel[idx] != -1) { 1824 (*ext_ctrl_info_count)++; 1825 } 1826 } 1827 for (idx = 0; idx < 21; idx++) { 1828 if (fg->ext_codes[part].l3_e4_sel[idx] != -1) { 1829 (*ext_ctrl_info_count)++; 1830 } 1831 } 1832 for (idx = 0; idx < 5; idx++) { 1833 if (fg->ext_codes[part].l3_e2_sel[idx] != -1) { 1834 (*ext_ctrl_info_count)++; 1835 } 1836 } 1837 for (idx = 0; idx < 2; idx++) { 1838 if (fg->ext_codes[part].l3_e1_sel[idx] != -1) { 1839 (*ext_ctrl_info_count)++; 1840 } 1841 } 1842 if (fg->ext_codes[part].alt_ttl_fn_sel != -1) { 1843 (*ext_ctrl_info_count)++; 1844 } 1845 } 1846 1847 return BCM_E_NONE; 1848 } 1849 1850 STATIC int 1851 _field_th_keygen_ext_ctrl_info_get(int unit, 1852 _field_group_t *fg, 1853 bcmi_keygen_cfg_t *keygen_cfg) 1854 { 1855 uint8 part = 0; 1856 int parts_count = 0; 1857 uint16 idx = 0; 1858 uint16 ext_idx = 0; 1859 uint16 ext_ctrl_info_count = 0; 1860 bcmi_keygen_ext_ctrl_sel_info_t *ext_ctrl_info = NULL; 1861 1862 /* Input parameters check. */ 1863 if (NULL == fg || NULL == keygen_cfg) { 1864 return (BCM_E_PARAM); 1865 } 1866 1867 /* Get number of entry parts based on the field group flags. */ 1868 BCM_IF_ERROR_RETURN( 1869 _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, &parts_count)); 1870 BCM_IF_ERROR_RETURN( 1871 _field_th_keygen_ext_ctrl_info_count_get(unit, fg, &ext_ctrl_info_count)); 1872 if (ext_ctrl_info_count == 0) { 1873 return BCM_E_NONE; 1874 } 1875 _FP_XGS3_ALLOC(ext_ctrl_info, 1876 ext_ctrl_info_count * sizeof(bcmi_keygen_ext_ctrl_sel_info_t), 1877 "Keygen Extractor control information"); 1878 if (ext_ctrl_info == NULL) { 1879 return BCM_E_MEMORY; 1880 } 1881 sal_memset(ext_ctrl_info, 0, 1882 ext_ctrl_info_count * sizeof(bcmi_keygen_ext_ctrl_sel_info_t)); 1883 keygen_cfg->ext_ctrl_sel_info_count = ext_ctrl_info_count; 1884 keygen_cfg->ext_ctrl_sel_info = ext_ctrl_info; 1885 for (part = 0; part < parts_count; part++) { 1886 if (fg->ext_codes[part].aux_tag_a_sel != -1) { 1887 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_AUX_TAG_A; 1888 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].aux_tag_a_sel; 1889 ext_ctrl_info[idx].part = part; 1890 idx++; 1891 } 1892 if (fg->ext_codes[part].aux_tag_b_sel != -1) { 1893 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_AUX_TAG_B; 1894 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].aux_tag_b_sel; 1895 ext_ctrl_info[idx].part = part; 1896 idx++; 1897 } 1898 if (fg->ext_codes[part].aux_tag_c_sel != -1) { 1899 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_AUX_TAG_C; 1900 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].aux_tag_c_sel; 1901 ext_ctrl_info[idx].part = part; 1902 idx++; 1903 } 1904 if (fg->ext_codes[part].aux_tag_d_sel != -1) { 1905 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_AUX_TAG_D; 1906 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].aux_tag_d_sel; 1907 ext_ctrl_info[idx].part = part; 1908 idx++; 1909 } 1910 if (fg->ext_codes[part].tcp_fn_sel != -1) { 1911 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_TCP_FN; 1912 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].tcp_fn_sel; 1913 ext_ctrl_info[idx].part = part; 1914 idx++; 1915 } 1916 if (fg->ext_codes[part].ttl_fn_sel != -1) { 1917 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_TTL_FN; 1918 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].ttl_fn_sel; 1919 ext_ctrl_info[idx].part = part; 1920 idx++; 1921 } 1922 if (fg->ext_codes[part].tos_fn_sel != -1) { 1923 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_TOS_FN; 1924 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].tos_fn_sel; 1925 ext_ctrl_info[idx].part = part; 1926 idx++; 1927 } 1928 if (fg->ext_codes[part].class_id_cont_a_sel != -1) { 1929 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_CLASSID_A; 1930 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].class_id_cont_a_sel; 1931 ext_ctrl_info[idx].part = part; 1932 idx++; 1933 } 1934 if (fg->ext_codes[part].class_id_cont_b_sel != -1) { 1935 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_CLASSID_B; 1936 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].class_id_cont_b_sel; 1937 ext_ctrl_info[idx].part = part; 1938 idx++; 1939 } 1940 if (fg->ext_codes[part].class_id_cont_c_sel != -1) { 1941 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_CLASSID_C; 1942 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].class_id_cont_c_sel; 1943 ext_ctrl_info[idx].part = part; 1944 idx++; 1945 } 1946 if (fg->ext_codes[part].class_id_cont_d_sel != -1) { 1947 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_CLASSID_D; 1948 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].class_id_cont_d_sel; 1949 ext_ctrl_info[idx].part = part; 1950 idx++; 1951 } 1952 if (fg->ext_codes[part].src_cont_a_sel != -1) { 1953 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_SRC_A; 1954 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].src_cont_a_sel; 1955 ext_ctrl_info[idx].part = part; 1956 idx++; 1957 } 1958 if (fg->ext_codes[part].src_cont_b_sel != -1) { 1959 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_SRC_B; 1960 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].src_cont_b_sel; 1961 ext_ctrl_info[idx].part = part; 1962 idx++; 1963 } 1964 if (fg->ext_codes[part].src_dest_cont_0_sel != -1) { 1965 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_SRC_DST_0; 1966 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].src_dest_cont_0_sel; 1967 ext_ctrl_info[idx].part = part; 1968 idx++; 1969 } 1970 if (fg->ext_codes[part].src_dest_cont_1_sel != -1) { 1971 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_SRC_DST_1; 1972 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].src_dest_cont_1_sel; 1973 ext_ctrl_info[idx].part = part; 1974 idx++; 1975 } 1976 if (fg->ext_codes[part].ipbm_present == 1) { 1977 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_IPBM_PRESENT; 1978 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].ipbm_source; 1979 ext_ctrl_info[idx].part = part; 1980 idx++; 1981 } 1982 if (fg->ext_codes[part].normalize_l3_l4_sel == 1) { 1983 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_L3_L4_NORM; 1984 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].normalize_l3_l4_sel; 1985 ext_ctrl_info[idx].part = part; 1986 idx++; 1987 } 1988 if (fg->ext_codes[part].normalize_mac_sel == 1) { 1989 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_MAC_NORM; 1990 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].normalize_mac_sel; 1991 ext_ctrl_info[idx].part = part; 1992 idx++; 1993 } 1994 for (ext_idx = 0; ext_idx < 15; ext_idx++) { 1995 if (fg->ext_codes[part].pmux_sel[ext_idx] != -1) { 1996 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_PMUX; 1997 ext_ctrl_info[idx].ctrl_sel_val = ext_idx; 1998 ext_ctrl_info[idx].part = part; 1999 idx++; 2000 } 2001 } 2002 for (ext_idx = 0; ext_idx < 4; ext_idx++) { 2003 if (fg->ext_codes[part].l1_e32_sel[ext_idx] != -1) { 2004 ext_ctrl_info[idx].ctrl_sel = 2005 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2006 ext_ctrl_info[idx].ctrl_sel_val = 2007 fg->ext_codes[part].l1_e32_sel[ext_idx]; 2008 ext_ctrl_info[idx].part = part; 2009 ext_ctrl_info[idx].level = 1; 2010 ext_ctrl_info[idx].gran = 32; 2011 ext_ctrl_info[idx].ext_num = ext_idx; 2012 idx++; 2013 } 2014 } 2015 for (ext_idx = 0; ext_idx < 7; ext_idx++) { 2016 if (fg->ext_codes[part].l1_e16_sel[ext_idx] != -1) { 2017 ext_ctrl_info[idx].ctrl_sel = 2018 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2019 ext_ctrl_info[idx].ctrl_sel_val = 2020 fg->ext_codes[part].l1_e16_sel[ext_idx]; 2021 ext_ctrl_info[idx].part = part; 2022 ext_ctrl_info[idx].level = 1; 2023 ext_ctrl_info[idx].gran = 16; 2024 ext_ctrl_info[idx].ext_num = ext_idx; 2025 idx++; 2026 } 2027 } 2028 for (ext_idx = 0; ext_idx < 7; ext_idx++) { 2029 if (fg->ext_codes[part].l1_e8_sel[ext_idx] != -1) { 2030 ext_ctrl_info[idx].ctrl_sel = 2031 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2032 ext_ctrl_info[idx].ctrl_sel_val = 2033 fg->ext_codes[part].l1_e8_sel[ext_idx]; 2034 ext_ctrl_info[idx].part = part; 2035 ext_ctrl_info[idx].level = 1; 2036 ext_ctrl_info[idx].gran = 8; 2037 ext_ctrl_info[idx].ext_num = ext_idx; 2038 idx++; 2039 } 2040 } 2041 for (ext_idx = 0; ext_idx < 8; ext_idx++) { 2042 if (fg->ext_codes[part].l1_e4_sel[ext_idx] != -1) { 2043 ext_ctrl_info[idx].ctrl_sel = 2044 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2045 ext_ctrl_info[idx].ctrl_sel_val = 2046 fg->ext_codes[part].l1_e4_sel[ext_idx]; 2047 ext_ctrl_info[idx].part = part; 2048 ext_ctrl_info[idx].level = 1; 2049 ext_ctrl_info[idx].gran = 4; 2050 ext_ctrl_info[idx].ext_num = ext_idx; 2051 idx++; 2052 } 2053 } 2054 for (ext_idx = 0; ext_idx < 8; ext_idx++) { 2055 if (fg->ext_codes[part].l1_e2_sel[ext_idx] != -1) { 2056 ext_ctrl_info[idx].ctrl_sel = 2057 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2058 ext_ctrl_info[idx].ctrl_sel_val = 2059 fg->ext_codes[part].l1_e2_sel[ext_idx]; 2060 ext_ctrl_info[idx].part = part; 2061 ext_ctrl_info[idx].level = 1; 2062 ext_ctrl_info[idx].gran = 2; 2063 ext_ctrl_info[idx].ext_num = ext_idx; 2064 idx++; 2065 } 2066 } 2067 for (ext_idx = 0; ext_idx < 10; ext_idx++) { 2068 if (fg->ext_codes[part].l2_e16_sel[ext_idx] != -1) { 2069 ext_ctrl_info[idx].ctrl_sel = 2070 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2071 ext_ctrl_info[idx].ctrl_sel_val = 2072 fg->ext_codes[part].l2_e16_sel[ext_idx]; 2073 ext_ctrl_info[idx].part = part; 2074 ext_ctrl_info[idx].level = 2; 2075 ext_ctrl_info[idx].gran = 16; 2076 ext_ctrl_info[idx].ext_num = ext_idx; 2077 idx++; 2078 } 2079 } 2080 for (ext_idx = 0; ext_idx < 16; ext_idx++) { 2081 if (fg->ext_codes[part].l2_e4_sel[ext_idx] != -1) { 2082 ext_ctrl_info[idx].ctrl_sel = 2083 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2084 ext_ctrl_info[idx].ctrl_sel_val = 2085 fg->ext_codes[part].l2_e4_sel[ext_idx]; 2086 ext_ctrl_info[idx].part = part; 2087 ext_ctrl_info[idx].level = 2; 2088 ext_ctrl_info[idx].gran = 4; 2089 ext_ctrl_info[idx].ext_num = ext_idx; 2090 idx++; 2091 } 2092 } 2093 for (ext_idx = 0; ext_idx < 7; ext_idx++) { 2094 if (fg->ext_codes[part].l2_e2_sel[ext_idx] != -1) { 2095 ext_ctrl_info[idx].ctrl_sel = 2096 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2097 ext_ctrl_info[idx].ctrl_sel_val = 2098 fg->ext_codes[part].l2_e2_sel[ext_idx]; 2099 ext_ctrl_info[idx].part = part; 2100 ext_ctrl_info[idx].level = 2; 2101 ext_ctrl_info[idx].gran = 2; 2102 ext_ctrl_info[idx].ext_num = ext_idx; 2103 idx++; 2104 } 2105 } 2106 for (ext_idx = 0; ext_idx < 2; ext_idx++) { 2107 if (fg->ext_codes[part].l2_e1_sel[ext_idx] != -1) { 2108 ext_ctrl_info[idx].ctrl_sel = 2109 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2110 ext_ctrl_info[idx].ctrl_sel_val = 2111 fg->ext_codes[part].l2_e1_sel[ext_idx]; 2112 ext_ctrl_info[idx].part = part; 2113 ext_ctrl_info[idx].level = 2; 2114 ext_ctrl_info[idx].gran = 1; 2115 ext_ctrl_info[idx].ext_num = ext_idx; 2116 idx++; 2117 } 2118 } 2119 for (ext_idx = 0; ext_idx < 21; ext_idx++) { 2120 if (fg->ext_codes[part].l3_e4_sel[ext_idx] != -1) { 2121 ext_ctrl_info[idx].ctrl_sel = 2122 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2123 ext_ctrl_info[idx].ctrl_sel_val = 2124 fg->ext_codes[part].l3_e4_sel[ext_idx]; 2125 ext_ctrl_info[idx].part = part; 2126 ext_ctrl_info[idx].level = 3; 2127 ext_ctrl_info[idx].gran = 4; 2128 ext_ctrl_info[idx].ext_num = ext_idx; 2129 idx++; 2130 } 2131 } 2132 for (ext_idx = 0; ext_idx < 5; ext_idx++) { 2133 if (fg->ext_codes[part].l3_e2_sel[ext_idx] != -1) { 2134 ext_ctrl_info[idx].ctrl_sel = 2135 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2136 ext_ctrl_info[idx].ctrl_sel_val = 2137 fg->ext_codes[part].l3_e2_sel[ext_idx]; 2138 ext_ctrl_info[idx].part = part; 2139 ext_ctrl_info[idx].level = 3; 2140 ext_ctrl_info[idx].gran = 2; 2141 ext_ctrl_info[idx].ext_num = ext_idx; 2142 idx++; 2143 } 2144 } 2145 for (ext_idx = 0; ext_idx < 2; ext_idx++) { 2146 if (fg->ext_codes[part].l3_e1_sel[ext_idx] != -1) { 2147 ext_ctrl_info[idx].ctrl_sel = 2148 BCMI_KEYGEN_EXT_CTRL_SEL_MULTIPLEXER; 2149 ext_ctrl_info[idx].ctrl_sel_val = 2150 fg->ext_codes[part].l3_e1_sel[ext_idx]; 2151 ext_ctrl_info[idx].part = part; 2152 ext_ctrl_info[idx].level = 3; 2153 ext_ctrl_info[idx].gran = 1; 2154 ext_ctrl_info[idx].ext_num = ext_idx; 2155 idx++; 2156 } 2157 } 2158 if (fg->ext_codes[part].alt_ttl_fn_sel != -1) { 2159 ext_ctrl_info[idx].ctrl_sel = BCMI_KEYGEN_EXT_CTRL_SEL_ALT_TTL_FN; 2160 ext_ctrl_info[idx].ctrl_sel_val = fg->ext_codes[part].alt_ttl_fn_sel; 2161 ext_ctrl_info[idx].part = part; 2162 idx++; 2163 } 2164 } 2165 return BCM_E_NONE; 2166 } 2167 2168 #define IS_IBUS_CONT_QSET(_qset_) \ 2169 (BCM_FIELD_QSET_TEST(_qset_, bcmFieldQualifyIncomingOuterVlanId)) \ 2170 2171 /* 2172 * Function: 2173 * _field_th_ingress_ext_code_get 2174 * Purpose: 2175 * Finds extractor select encodings that will satisfy the 2176 * requested qualifier set (Qset). 2177 * Parameters: 2178 * unit - (IN) BCM unit number. 2179 * stage_fc - (IN) Stage Field control structure. 2180 * qset_req - (IN) Client qualifier set. 2181 * fg - (IN/OUT) Field group structure. 2182 * Returns: 2183 * BCM_E_XXX 2184 */ 2185 STATIC int 2186 _field_th_ingress_ext_code_get(int unit, _field_group_add_fsm_t *fsm_ptr) 2187 { 2188 int rv = BCM_E_NONE; 2189 int parts_count = 0; 2190 uint16 rkey_size = 0; 2191 uint16 qual_info_count = 0; 2192 bcmi_keygen_mode_t keygen_mode; 2193 bcmi_keygen_mode_t keygen_ext_mode; 2194 bcmi_keygen_cfg_t keygen_cfg; 2195 bcmi_keygen_oper_t keygen_oper; 2196 bcmi_keygen_qual_info_t *qual_info_arr = NULL; 2197 _field_group_t *fg; 2198 _field_stage_t *stage_fc; 2199 bcm_field_qset_t *qset_req; 2200 #if defined (BCM_TRIDENT3_SUPPORT) 2201 int ct = 0; 2202 uint8 bkup_ct = 0; 2203 uint8 num_qual_cfg_bkup[2] = {0}; 2204 bcm_field_qualify_t qual_bkup[2]; 2205 bcmi_keygen_qual_cfg_t *qual_cfg_arr_bkup[2] = {NULL}; 2206 #endif /* BCM_TRIDENT3_SUPPORT */ 2207 2208 /* Input parameters check. */ 2209 if (NULL == fsm_ptr) { 2210 return (BCM_E_PARAM); 2211 } 2212 2213 fg = fsm_ptr->fg; 2214 stage_fc = fsm_ptr->stage_fc; 2215 qset_req = &(fg->qset); 2216 /* Initialize group extractor codes based on group flags. */ 2217 rv = _field_th_group_extractors_init(unit, fg); 2218 BCM_IF_ERROR_RETURN(rv); 2219 2220 sal_memset(&keygen_cfg, 0, sizeof(bcmi_keygen_cfg_t)); 2221 sal_memset(&keygen_oper, 0, sizeof(bcmi_keygen_oper_t)); 2222 2223 /* Get number of entry parts based on the field group flags. */ 2224 BCM_IF_ERROR_RETURN( 2225 _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, &parts_count)); 2226 2227 if (soc_feature(unit, soc_feature_fp_ltid_match_all_parts) && 2228 (fg->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 2229 if (parts_count > 1) { 2230 BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifyPreLogicalTableId1); 2231 if (parts_count == 3) { 2232 BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifyPreLogicalTableId2); 2233 } 2234 } 2235 } 2236 2237 rv = _field_th_group_qual_info_get(unit, stage_fc, fg, qset_req, 2238 &qual_info_arr, &qual_info_count); 2239 BCM_IF_ERROR_RETURN(rv); 2240 2241 if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE && 2242 !(fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 2243 keygen_mode = BCMI_KEYGEN_MODE_SINGLE; 2244 keygen_ext_mode = BCMI_KEYGEN_MODE_DBLINTRA; 2245 } else if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE && 2246 fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 2247 if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 2248 if (fg->em_mode == _FieldExactMatchMode160) { 2249 keygen_mode = BCMI_KEYGEN_MODE_SINGLE_ASET_NARROW; 2250 } else if (fg->em_mode == _FieldExactMatchMode128) { 2251 keygen_mode = BCMI_KEYGEN_MODE_SINGLE_ASET_WIDE; 2252 } else { 2253 rv = BCM_E_INTERNAL; 2254 goto cleanup; 2255 } 2256 } else { 2257 keygen_mode = BCMI_KEYGEN_MODE_DBLINTRA; 2258 } 2259 keygen_ext_mode = BCMI_KEYGEN_MODE_DBLINTRA; 2260 } else if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 2261 keygen_mode = BCMI_KEYGEN_MODE_DBLINTER; 2262 keygen_ext_mode = BCMI_KEYGEN_MODE_DBLINTER; 2263 } else if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 2264 keygen_mode = BCMI_KEYGEN_MODE_TRIPLE; 2265 keygen_ext_mode = BCMI_KEYGEN_MODE_TRIPLE; 2266 } else { 2267 rv = BCM_E_INTERNAL; 2268 goto cleanup; 2269 } 2270 2271 #if defined (BCM_TRIDENT3_SUPPORT) 2272 if (soc_feature(unit, soc_feature_td3_style_fp)) { 2273 if (IS_IBUS_CONT_QSET(fsm_ptr->qset)) { 2274 if (BCM_FIELD_QSET_TEST(fsm_ptr->qset, bcmFieldQualifyIncomingOuterVlanId)) { 2275 qual_bkup[bkup_ct++] = bcmFieldQualifyIncomingOuterVlanId; 2276 } 2277 2278 for (ct = 0; ct < bkup_ct; ct++) { 2279 num_qual_cfg_bkup[ct] = 2280 stage_fc->qual_cfg_info_db->qual_cfg_info[qual_bkup[ct]]->num_qual_cfg; 2281 qual_cfg_arr_bkup[ct] = 2282 stage_fc->qual_cfg_info_db->qual_cfg_info[qual_bkup[ct]]->qual_cfg_arr; 2283 2284 rv = _bcm_field_qual_cfg_info_db_update(unit, fsm_ptr->fg->instance, 2285 qual_bkup[ct], stage_fc); 2286 if (BCM_FAILURE(rv)) { 2287 goto cleanup; 2288 } 2289 } 2290 } 2291 } 2292 #endif /* BCM_TRIDENT3_SUPPORT */ 2293 2294 keygen_cfg.qual_info_arr = qual_info_arr; 2295 keygen_cfg.qual_info_count = qual_info_count; 2296 keygen_cfg.qual_cfg_info_db = stage_fc->qual_cfg_info_db; 2297 keygen_cfg.ext_cfg_db = stage_fc->ext_cfg_db_arr[keygen_ext_mode]; 2298 keygen_cfg.mode = keygen_mode; 2299 keygen_cfg.num_parts = parts_count; 2300 if (fsm_ptr->flags & _FP_GROUP_CONFIG_VALIDATE) { 2301 keygen_cfg.flags = BCMI_KEYGEN_CFG_FLAGS_VALIDATE_ONLY; 2302 } 2303 if (fsm_ptr->flags & _FP_GROUP_QSET_UPDATE) { 2304 keygen_cfg.flags |= BCMI_KEYGEN_CFG_FLAGS_QSET_UPDATE; 2305 rv = _field_th_keygen_ext_ctrl_info_get(unit, fg, &keygen_cfg); 2306 if (BCM_FAILURE(rv)) { 2307 goto cleanup; 2308 } 2309 } 2310 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS && 2311 !(fsm_ptr->flags & _FP_GROUP_QSET_UPDATE)) { 2312 rv = bcmi_keygen_keysize_get(unit, &keygen_cfg, &rkey_size); 2313 if (BCM_FAILURE(rv)) { 2314 goto cleanup; 2315 } 2316 if (((keygen_mode == BCMI_KEYGEN_MODE_SINGLE) && (rkey_size > 80)) 2317 || ((keygen_mode == BCMI_KEYGEN_MODE_DBLINTRA) && (rkey_size > 160)) 2318 || ((keygen_mode == BCMI_KEYGEN_MODE_DBLINTER) && (rkey_size > 320)) 2319 || ((keygen_mode == BCMI_KEYGEN_MODE_TRIPLE) && (rkey_size > 480))) { 2320 rv = BCM_E_CONFIG; 2321 goto cleanup; 2322 } 2323 } 2324 rv = bcmi_keygen_cfg_process(unit, &keygen_cfg, &keygen_oper); 2325 if (BCM_FAILURE(rv)) { 2326 goto cleanup; 2327 } 2328 2329 if ((fsm_ptr->flags & _FP_GROUP_CONFIG_VALIDATE) == 0) { 2330 rv = _field_th_group_keygen_oper_insert(unit, fg, &keygen_oper); 2331 if (BCM_FAILURE(rv)) { 2332 goto cleanup; 2333 } 2334 } 2335 2336 cleanup: 2337 if (qual_info_arr != NULL) { 2338 sal_free(qual_info_arr); 2339 } 2340 if (fsm_ptr->flags & _FP_GROUP_QSET_UPDATE) { 2341 if (keygen_cfg.ext_ctrl_sel_info != NULL) { 2342 sal_free(keygen_cfg.ext_ctrl_sel_info); 2343 } 2344 } 2345 2346 #if defined (BCM_TRIDENT3_SUPPORT) 2347 if (soc_feature(unit, soc_feature_td3_style_fp)) { 2348 if (bkup_ct != 0) { 2349 uint8 ct; 2350 for (ct = 0; ct < bkup_ct; ct++) { 2351 if (BCM_FAILURE(rv)) { 2352 stage_fc->qual_cfg_info_db->qual_cfg_info[qual_bkup[ct]]->qual_cfg_arr 2353 = qual_cfg_arr_bkup[ct]; 2354 stage_fc->qual_cfg_info_db->qual_cfg_info[qual_bkup[ct]]->num_qual_cfg 2355 = num_qual_cfg_bkup[ct]; 2356 BCM_IF_ERROR_RETURN 2357 (_bcm_field_td3_field_bus_cont_sel_remove(unit, 2358 fsm_ptr->fg->instance, 2359 stage_fc, fg, 2360 qual_bkup[ct])); 2361 } else { 2362 sal_free(qual_cfg_arr_bkup[ct]); 2363 } 2364 } 2365 } 2366 } 2367 #endif /* BCM_TRIDENT3_SUPPORT */ 2368 (void)bcmi_keygen_oper_free(unit, parts_count, &keygen_oper); 2369 return rv; 2370 } 2371 2372 /* 2373 * Function: 2374 * _field_th_ext_code_assign 2375 * 2376 * Purpose: 2377 * Calculate the extractor select codes from a qualifier set and group mode. 2378 * 2379 * Parameters: 2380 * unit - (IN) BCM device number. 2381 * qset - (IN) Client qualifier set. 2382 * selcode_clear - (IN) Clear the selcodes 2383 * fsm_ptr - (IN/OUT) fsm pointer which has pointer to 2384 * group structure ans aset size 2385 * 2386 * Returns: 2387 * BCM_E_PARAM - mode unknown 2388 * BCM_E_RESOURCE - No select code will satisfy qualifier set 2389 * BCM_E_NONE - Success 2390 * 2391 * Notes: 2392 * Calling function is responsible for ensuring appropriate slices 2393 * are available. 2394 * selcode_clear will be 0 (don't clear) when this function is called 2395 * from bcm_field_group_set 2396 */ 2397 int 2398 _field_th_ext_code_assign(int unit, 2399 int selcode_clear, 2400 _field_group_add_fsm_t *fsm_ptr) 2401 { 2402 int idx; /* slice index iterator. */ 2403 _field_group_t *fg; /* Field Group structure */ 2404 2405 /*retrieve the group structure */ 2406 fg = fsm_ptr->fg; 2407 2408 /* Input parameters check. */ 2409 if (NULL == fg) { 2410 return (BCM_E_PARAM); 2411 } 2412 2413 /* 2414 * Clear group extractor selector codes. 2415 */ 2416 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 2417 if (selcode_clear) { 2418 _FP_EXT_SELCODE_CLEAR(fg->ext_codes[idx]); 2419 } 2420 } 2421 2422 /* Get keygen extractor codes for group qset. */ 2423 BCM_IF_ERROR_RETURN(_field_th_ingress_ext_code_get(unit, fsm_ptr)); 2424 return (BCM_E_NONE); 2425 } 2426 2427 /* 2428 * Function: 2429 * _field_th_group_add_extractor_codes_get 2430 * Purpose: 2431 * Calculate the extractor select codes from a qualifier set and group mode. 2432 * Parameters: 2433 * unit - (IN) BCM device number. 2434 * fsm_ptr - (IN/OUT) State machine tracking structure. 2435 * Returns: 2436 * BCM_E_XXX 2437 */ 2438 STATIC int 2439 _field_th_group_add_extractor_codes_get(int unit, 2440 _field_group_add_fsm_t *fsm_ptr) 2441 { 2442 _field_group_t *fg; /* Field Group pointer. */ 2443 int orig_group_flags; /* Original Group flags. */ 2444 2445 /* Input parameters check. */ 2446 if (NULL == fsm_ptr || NULL == fsm_ptr->fg) { 2447 return (BCM_E_PARAM); 2448 } 2449 2450 /* Check if requested mode is supported by device. */ 2451 switch (fsm_ptr->mode) { 2452 case bcmFieldGroupModeQuad: 2453 case bcmFieldGroupModeDirect: 2454 case bcmFieldGroupModeDirectExtraction: 2455 case bcmFieldGroupModeHashing: 2456 case bcmFieldGroupModeExactMatch: 2457 /* Mode not supported by device. */ 2458 fsm_ptr->rv = (BCM_E_CONFIG); 2459 break; 2460 case bcmFieldGroupModeTriple: /* 480 bit mode. */ 2461 /* Check Triple wide mode group support in device feature list. */ 2462 if (0 == soc_feature(unit, soc_feature_field_ingress_triple_wide)) { 2463 fsm_ptr->rv = (BCM_E_CONFIG); 2464 } else { 2465 if (fsm_ptr->stage_fc->stage_id 2466 == _BCM_FIELD_STAGE_EXACTMATCH) { 2467 fsm_ptr->rv = (BCM_E_CONFIG); 2468 } 2469 } 2470 break; 2471 case bcmFieldGroupModeDouble: /* 320 bit mode. */ 2472 /* Check if device supports Double wide mode. */ 2473 if (0 == soc_feature(unit, soc_feature_field_wide)) { 2474 fsm_ptr->rv = (BCM_E_CONFIG); 2475 } 2476 break; 2477 case bcmFieldGroupModeIntraSliceDouble: /*160 bit mode */ 2478 if (!(soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) || 2479 soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support))) { 2480 /* Check if device supports intraslice Double wide mode. */ 2481 if (0 == soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 2482 fsm_ptr->rv = (BCM_E_CONFIG); 2483 } 2484 } else { 2485 fsm_ptr->rv = (BCM_E_UNAVAIL); 2486 } 2487 break; 2488 case bcmFieldGroupModeSingle: /* 80 bit mode. */ 2489 if (!soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) && 2490 !soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support)) { 2491 if (_BCM_FIELD_QSET_PBMP_TEST(fsm_ptr->qset)) { 2492 fsm_ptr->rv = (BCM_E_CONFIG); 2493 } 2494 } else { 2495 /* Single mode is 160 bit mode */ 2496 fsm_ptr->mode = bcmFieldGroupModeIntraSliceDouble; 2497 } 2498 break; 2499 default: 2500 break; 2501 } 2502 2503 /* If mode check returned failure, proceed to cleanup state. */ 2504 if (BCM_FAILURE(fsm_ptr->rv)) { 2505 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 2506 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 2507 return (BCM_E_NONE); 2508 } 2509 2510 /* Group pointer initialization. */ 2511 fg = fsm_ptr->fg; 2512 2513 fsm_ptr->rv = BCM_E_RESOURCE; 2514 orig_group_flags = fg->flags; 2515 2516 if (fsm_ptr->stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 2517 2518 if (bcmFieldGroupModeAuto == fsm_ptr->mode) { 2519 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, "Group mode auto.\n"))); 2520 2521 /* For Auto mode, try Single -> Double -> Triple modes. */ 2522 /* Single wide Non-Intra slice selection. */ 2523 if (!soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) && 2524 !soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support)) { 2525 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY) && 2526 !_BCM_FIELD_QSET_PBMP_TEST(fsm_ptr->qset)) { 2527 LOG_VERBOSE(BSL_LS_BCM_FP, 2528 (BSL_META_U(unit, "Trying single...\n"))); 2529 if (soc_feature(unit, soc_feature_ifp_action_profiling) && 2530 (fsm_ptr->aset_size > _FP_ASET_DATA_SIZE_FOR_POLICY_NARROW)) 2531 { 2532 LOG_VERBOSE(BSL_LS_BCM_FP, 2533 (BSL_META_U(unit, "When Aset size is %d, Single wide group is not possible\n"), 2534 fsm_ptr->aset_size)); 2535 fsm_ptr->rv = BCM_E_RESOURCE; 2536 } else { 2537 /* 80bit mode. */ 2538 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE); 2539 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, fsm_ptr); 2540 } 2541 } 2542 } 2543 2544 /* Single wide intra slice selection. */ 2545 if ((BCM_FAILURE(fsm_ptr->rv) 2546 && (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) { 2547 if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 2548 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2549 "Trying intra...\n"))); 2550 if (soc_feature(unit, soc_feature_ifp_action_profiling) && 2551 (fsm_ptr->aset_size > _FP_ASET_DATA_SIZE_FOR_POLICY_WIDE)) 2552 { 2553 LOG_VERBOSE(BSL_LS_BCM_FP, 2554 (BSL_META_U(unit, "When Aset size is %d, Intra Slice Double wide" 2555 " group is not possible\n"), fsm_ptr->aset_size)); 2556 fsm_ptr->rv = BCM_E_RESOURCE; 2557 } else { 2558 /* 160bit mode. */ 2559 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE 2560 | _FP_GROUP_INTRASLICE_DOUBLEWIDE); 2561 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, fsm_ptr); 2562 } 2563 } 2564 } 2565 2566 /* Double wide inter slice selection. */ 2567 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2568 if (BCM_FAILURE(fsm_ptr->rv)) { 2569 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2570 "Trying double...\n"))); 2571 /* 320bit mode. */ 2572 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_DOUBLE_SLICE); 2573 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, fsm_ptr); 2574 } 2575 } 2576 2577 /* Triple wide inter slice selection. */ 2578 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2579 if (BCM_FAILURE(fsm_ptr->rv)) { 2580 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2581 "Trying triple...\n"))); 2582 /* 480bit mode. */ 2583 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_TRIPLE_SLICE); 2584 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, fsm_ptr); 2585 } 2586 } 2587 } else { 2588 switch (fsm_ptr->mode) { 2589 case bcmFieldGroupModeSingle: 2590 /* Single wide non intra slice selection. */ 2591 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2592 LOG_VERBOSE(BSL_LS_BCM_FP, 2593 (BSL_META_U(unit, "Trying single...\n"))); 2594 if (soc_feature(unit, soc_feature_ifp_action_profiling) && 2595 (fsm_ptr->aset_size > _FP_ASET_DATA_SIZE_FOR_POLICY_NARROW)) 2596 { 2597 LOG_VERBOSE(BSL_LS_BCM_FP,(BSL_META_U(unit, 2598 "When Aset size is %d,Single wide group is not possible\n"), 2599 fsm_ptr->aset_size)); 2600 fsm_ptr->rv = BCM_E_RESOURCE; 2601 } 2602 else { 2603 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE); 2604 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, 2605 fsm_ptr); 2606 } 2607 } 2608 break; 2609 case bcmFieldGroupModeIntraSliceDouble: 2610 /* Double wide intra slice selection. */ 2611 if ((soc_feature(unit, soc_feature_field_intraslice_double_wide) 2612 && (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) { 2613 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2614 "Trying intra...\n"))); 2615 if (soc_feature(unit, soc_feature_ifp_action_profiling) && 2616 (fsm_ptr->aset_size > _FP_ASET_DATA_SIZE_FOR_POLICY_WIDE)) 2617 { 2618 LOG_VERBOSE(BSL_LS_BCM_FP, 2619 (BSL_META_U(unit, "When Aset size is %d, Intra Slice Double wide" 2620 " group is not possible\n"), fsm_ptr->aset_size)); 2621 fsm_ptr->rv = BCM_E_RESOURCE; 2622 } 2623 else { 2624 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE 2625 | _FP_GROUP_INTRASLICE_DOUBLEWIDE); 2626 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, 2627 fsm_ptr); 2628 } 2629 } 2630 break; 2631 case bcmFieldGroupModeDouble: 2632 /* Double wide intra slice selection. */ 2633 if (!soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) && 2634 !soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support)) { 2635 if ((soc_feature(unit, soc_feature_field_intraslice_double_wide) 2636 && (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) { 2637 if (soc_feature(unit, soc_feature_ifp_action_profiling) && 2638 (fsm_ptr->aset_size > _FP_ASET_DATA_SIZE_FOR_POLICY_WIDE)) 2639 { 2640 LOG_VERBOSE(BSL_LS_BCM_FP, 2641 (BSL_META_U(unit, "When Aset size is %d, Intra Slice Double wide" 2642 " group is not possible\n"), fsm_ptr->aset_size)); 2643 fsm_ptr->rv = BCM_E_RESOURCE; 2644 } else { 2645 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2646 "Trying intra...\n"))); 2647 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE 2648 | _FP_GROUP_INTRASLICE_DOUBLEWIDE); 2649 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, 2650 fsm_ptr); 2651 } 2652 } 2653 } 2654 /* Double wide inter slice selection. */ 2655 if ((BCM_FAILURE(fsm_ptr->rv)) 2656 && (0 == (fsm_ptr->flags 2657 & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY))) { 2658 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2659 "Trying double...\n"))); 2660 fg->flags = (orig_group_flags | 2661 _FP_GROUP_SPAN_DOUBLE_SLICE); 2662 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, 2663 fsm_ptr); 2664 } 2665 break; 2666 case bcmFieldGroupModeTriple: 2667 /* Triple wide inter slice selection. */ 2668 if (0 == (fsm_ptr->flags 2669 & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2670 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2671 "Trying triple...\n"))); 2672 fg->flags = (orig_group_flags | 2673 _FP_GROUP_SPAN_TRIPLE_SLICE); 2674 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, 2675 fsm_ptr); 2676 } 2677 break; 2678 default: 2679 fsm_ptr->rv = (BCM_E_CONFIG); 2680 } 2681 } 2682 } else if (fsm_ptr->stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 2683 2684 if (bcmFieldGroupModeAuto == fsm_ptr->mode) { 2685 2686 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, "Group mode auto.\n"))); 2687 2688 /* Single wide intra slice selection. */ 2689 if ((0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY))) { 2690 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2691 "Trying single ...\n"))); 2692 if (fsm_ptr->aset_size <= EM_MODE160_ACTION_DATA_SIZE) { 2693 fg->em_mode = _FieldExactMatchMode160; 2694 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE 2695 | _FP_GROUP_INTRASLICE_DOUBLEWIDE; 2696 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, fsm_ptr); 2697 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE; 2698 } else if ((EM_MODE160_ACTION_DATA_SIZE < fsm_ptr->aset_size) 2699 && (fsm_ptr->aset_size <= EM_MODE128_ACTION_DATA_SIZE)) { 2700 fg->em_mode = _FieldExactMatchMode128; 2701 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE 2702 | _FP_GROUP_INTRASLICE_DOUBLEWIDE; 2703 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, fsm_ptr); 2704 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE; 2705 } 2706 } 2707 2708 /* Double wide inter slice selection. */ 2709 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2710 if (BCM_FAILURE(fsm_ptr->rv)) { 2711 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2712 "Trying double...\n"))); 2713 if (fsm_ptr->aset_size <= EM_MODE320_ACTION_DATA_SIZE) { 2714 /* 320bit mode. */ 2715 fg->em_mode = _FieldExactMatchMode320; 2716 fg->flags = (orig_group_flags | 2717 _FP_GROUP_SPAN_DOUBLE_SLICE); 2718 fsm_ptr->rv = _field_th_ext_code_assign(unit, 2719 1, fsm_ptr); 2720 } 2721 } 2722 } 2723 } else { 2724 switch (fsm_ptr->mode) { 2725 case bcmFieldGroupModeSingle: 2726 /* Single Wide selection. */ 2727 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2728 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2729 "Trying intra...\n"))); 2730 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE 2731 | _FP_GROUP_INTRASLICE_DOUBLEWIDE; 2732 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, 2733 fsm_ptr); 2734 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE; 2735 } 2736 break; 2737 case bcmFieldGroupModeDouble: 2738 /* Double wide inter slice selection. */ 2739 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2740 if (fsm_ptr->aset_size <= EM_MODE320_ACTION_DATA_SIZE) { 2741 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2742 "Trying double ..\n"))); 2743 fg->em_mode = _FieldExactMatchMode320; 2744 fg->flags = (orig_group_flags | 2745 _FP_GROUP_SPAN_DOUBLE_SLICE); 2746 fsm_ptr->rv = _field_th_ext_code_assign(unit, 1, 2747 fsm_ptr); 2748 } else { 2749 fsm_ptr->rv = (BCM_E_CONFIG); 2750 } 2751 } 2752 break; 2753 default: 2754 fsm_ptr->rv = (BCM_E_CONFIG); 2755 } 2756 } 2757 #if defined(BCM_FLOWTRACKER_SUPPORT) 2758 } else if (fsm_ptr->stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 2759 if (bcmFieldGroupModeAuto == fsm_ptr->mode) { 2760 2761 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, "Group mode auto.\n"))); 2762 2763 /* Single wide intra slice selection. */ 2764 if ((0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY))) { 2765 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2766 "Trying single ...\n"))); 2767 /* 180Bit mode. */ 2768 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE; 2769 fsm_ptr->rv = _field_hx5_ft_ext_code_assign(unit, 1, fsm_ptr); 2770 } 2771 2772 /* Double wide inter slice selection. */ 2773 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2774 if (BCM_FAILURE(fsm_ptr->rv)) { 2775 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2776 "Trying double...\n"))); 2777 /* 360bit mode. */ 2778 fg->flags = (orig_group_flags | 2779 _FP_GROUP_SPAN_SINGLE_SLICE | 2780 _FP_GROUP_DW_DEPTH_EXPANDED); 2781 fsm_ptr->rv = _field_hx5_ft_ext_code_assign(unit, 1, fsm_ptr); 2782 } 2783 } 2784 } else { 2785 switch (fsm_ptr->mode) { 2786 case bcmFieldGroupModeSingle: 2787 /* Single Wide selection. */ 2788 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2789 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2790 "Trying Single...\n"))); 2791 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE; 2792 fsm_ptr->rv = _field_hx5_ft_ext_code_assign(unit, 1, 2793 fsm_ptr); 2794 fg->flags = orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE; 2795 } 2796 break; 2797 case bcmFieldGroupModeDouble: 2798 /* Double wide selection. */ 2799 if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) { 2800 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2801 "Trying double ..\n"))); 2802 fg->flags = (orig_group_flags | 2803 _FP_GROUP_SPAN_SINGLE_SLICE | 2804 _FP_GROUP_DW_DEPTH_EXPANDED); 2805 fsm_ptr->rv = _field_hx5_ft_ext_code_assign(unit, 1, 2806 fsm_ptr); 2807 } 2808 break; 2809 default: 2810 fsm_ptr->rv = (BCM_E_CONFIG); 2811 } 2812 } 2813 #endif 2814 } else { 2815 return (BCM_E_INTERNAL); 2816 } 2817 2818 if (BCM_FAILURE(fsm_ptr->rv)) { 2819 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, "No success so far.\n"))); 2820 2821 /* No luck so far - try different alternative qset if possible. */ 2822 if ((BCM_E_RESOURCE == fsm_ptr->rv) 2823 && (_BCM_FP_GROUP_ADD_STATE_QSET_UPDATE 2824 == fsm_ptr->fsm_state_prev)) { 2825 fsm_ptr->rv = (BCM_E_NONE); 2826 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE; 2827 } 2828 } else { 2829 2830 /* Insert group into units group list. */ 2831 if (BCM_SUCCESS(fsm_ptr->rv)) { 2832 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2833 "Configuration found...\n"))); 2834 fsm_ptr->rv = _bcm_field_group_linked_list_insert(unit, fsm_ptr); 2835 } 2836 2837 if (BCM_SUCCESS(fsm_ptr->rv)) { 2838 /* Success proceed to slice allocation. */ 2839 if ((fsm_ptr->flags & _FP_GROUP_CONFIG_VALIDATE)) { 2840 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 2841 } else { 2842 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE; 2843 } 2844 } else { 2845 /* Failure proceed to cleanup. */ 2846 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 2847 } 2848 } 2849 2850 /* Set current state to be previous state. */ 2851 fsm_ptr->fsm_state_prev = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET; 2852 2853 return (BCM_E_NONE); 2854 } 2855 2856 /* 2857 * Function: 2858 * _field_th_group_add_qset_alternate 2859 * Purpose: 2860 * Currently no alternate QSET identified for TH IFP qualifiers. 2861 * Proceed to the next state in the state machine. 2862 * Parameters: 2863 * unit - (IN) BCM device number. 2864 * fsm_ptr - (IN/OUT) State machine tracking structure. 2865 * Returns: 2866 * BCM_E_XXX 2867 */ 2868 STATIC int 2869 _field_th_group_add_qset_alternate(int unit, _field_group_add_fsm_t *fsm_ptr) 2870 { 2871 /* Input parameters check. */ 2872 if (NULL == fsm_ptr) { 2873 return (BCM_E_PARAM); 2874 } 2875 2876 /* Set current state to be previous state. */ 2877 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 2878 2879 /* Alternate QSET is not available, proceed to end. */ 2880 fsm_ptr->rv = (BCM_E_RESOURCE); 2881 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 2882 2883 return (BCM_E_NONE); 2884 } 2885 2886 /* 2887 * Function: 2888 * _field_th_group_lt_slice_validate 2889 * Purpose: 2890 * Validate if the slice has enought free entries. 2891 * Parameters: 2892 * unit - (IN) BCM device number. 2893 * stage_fc - (IN) Stage field control structure pointer. 2894 * fg - (IN) Field group structure pointer. 2895 * slice_id - (IN) Physical slice number. 2896 * lt_fs - (IN) Reference to LT Slice structure. 2897 * Returns: 2898 * BCM_E_XXX 2899 */ 2900 int 2901 _field_th_group_lt_slice_validate(int unit, 2902 _field_stage_t *stage_fc, 2903 _field_group_t *fg, 2904 int slice_id, 2905 _field_lt_slice_t *lt_fs) 2906 { 2907 /* Input parameters check. */ 2908 if ((NULL == stage_fc) || (NULL == fg)) { 2909 return (BCM_E_PARAM); 2910 } 2911 2912 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 2913 int id; /* iterator. */ 2914 uint8 presel_ent_ct = 0; /* Presel Entry count. */ 2915 uint8 first_entry_flg = 0; 2916 uint8 atomicity_entry = 0; 2917 2918 /* calculated the presel entries to be created */ 2919 for (id = 0; id < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; id++) { 2920 if (fg->presel_ent_arr[id] != NULL) { 2921 presel_ent_ct++; 2922 } 2923 } 2924 2925 if (lt_fs == NULL) { 2926 lt_fs = stage_fc->lt_slices[fg->instance] + slice_id; 2927 first_entry_flg = 1; 2928 } 2929 2930 /* 2931 * To provide SW atomicity, an entry in the slice has to be kept 2932 * free to move other entries in the slice during priority configuration. 2933 * Hence, free entries has to be reduced to 1 during validation. 2934 */ 2935 if (lt_fs->slice_flags & _BCM_FIELD_SLICE_SW_ATOMICITY_SUPPORT) { 2936 if (lt_fs->free_count == 0) { 2937 return BCM_E_INTERNAL; 2938 } 2939 atomicity_entry = 1; 2940 } 2941 2942 if ((lt_fs->free_count - atomicity_entry) < presel_ent_ct) { 2943 if (first_entry_flg == 1) { 2944 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2945 "No free entries left in the LT slice[%d] to create [%d]" 2946 " Preselector entries.\n\r"), 2947 slice_id, presel_ent_ct)); 2948 return (BCM_E_CONFIG); 2949 } else { 2950 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2951 "ERROR: Can not create the requested %d Presel entries" 2952 " for the given group's priority[%d].\n\r" 2953 "Only %d free entries left in the LT slice[%d]\n\r"), 2954 presel_ent_ct, fg->priority, 2955 (lt_fs->free_count - atomicity_entry), slice_id)); 2956 return (BCM_E_RESOURCE); 2957 } 2958 } 2959 } else { 2960 int part; /* Part iterator */ 2961 int parts_count = 0; /* Entry Parts */ 2962 _field_slice_t *fs; /* Field slice structure pointer.*/ 2963 2964 /* Get number of entry parts based on the field group flags. */ 2965 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 2966 &parts_count)); 2967 2968 /* Validate slice LT_MAP status. */ 2969 for (part = 0; part < parts_count; part++) { 2970 fs = stage_fc->slices[fg->instance] + slice_id + part; 2971 if (0 != fs->lt_map) { 2972 if (!((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) && 2973 (fs->lt_map == 1))) { 2974 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2975 "FP(unit %d) Verb: Slice=%d in-use.\n"), 2976 unit, (slice_id + part))); 2977 return (BCM_E_CONFIG); 2978 } 2979 } 2980 } 2981 } 2982 2983 return (BCM_E_NONE); 2984 } 2985 2986 /* 2987 * Function: 2988 * _bcm_field_th_priority_group_get_next 2989 * Purpose: 2990 * Retrieve the next valid group pointer associated with the given priority. 2991 * Parameters: 2992 * unit - (IN BCM device number. 2993 * instance - (IN) Pipe to which group belongs to. 2994 * stage_id - (IN) Stage (IFP/VFP/EFP) to which group belongs to. 2995 * priority - (IN) Field Group Priority. 2996 * curr_group - (IN) Reference to current group index associated to group 2997 * priority. 2998 * next_group - (OUT) Reference to next available group index associated to 2999 * the given priority. 3000 * Returns: 3001 * BCM_E_XXX 3002 * Note: 3003 * "*curr_group == NULL" to retrieve the first group associated with the 3004 * given slice. 3005 */ 3006 int 3007 _bcm_field_th_priority_group_get_next(int unit, 3008 int instance, 3009 _field_stage_id_t stage_id, 3010 int priority, 3011 _field_group_t **curr_group, 3012 _field_group_t **next_group) 3013 { 3014 _field_group_t *fg = NULL; 3015 3016 if (curr_group == NULL || next_group == NULL) { 3017 return BCM_E_PARAM; 3018 } 3019 3020 if (*curr_group == NULL) { 3021 _field_control_t *fc; /* Field Control Structure */ 3022 3023 /* Get device Field control structure. */ 3024 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 3025 fg = fc->groups; 3026 } else { 3027 fg = (*curr_group)->next; 3028 } 3029 3030 *next_group = NULL; 3031 for (; fg != NULL; fg = fg->next) { 3032 if ((instance != fg->instance) || (stage_id != fg->stage_id)) { 3033 continue; 3034 } 3035 3036 if (fg->priority == priority) { 3037 *next_group = fg; 3038 return BCM_E_NONE; 3039 } 3040 } 3041 3042 return BCM_E_NOT_FOUND; 3043 } 3044 3045 /* 3046 * Function: 3047 * _bcm_field_th_group_add_slice_validate 3048 * Purpose: 3049 * Validate a candidate slice if it fits for a group. 3050 * Parameters: 3051 * unit - (IN BCM device number. 3052 * stage_fc - (IN) State machine tracking structure. 3053 * fg - (IN) Field group structure. 3054 * slice_id - (IN) Candidate slice id. 3055 * Returns: 3056 * BCM_E_XXX 3057 */ 3058 int 3059 _bcm_field_th_group_add_slice_validate(int unit, 3060 _field_stage_t *stage_fc, 3061 _field_group_t *fg, 3062 int slice_id) 3063 { 3064 int rv; /* Return status. */ 3065 _field_slice_t *fs_part[_FP_MAX_ENTRY_WIDTH] = {NULL}; /* Field slice 3066 structure 3067 pointer. */ 3068 _field_group_t *fg_ptr = NULL; 3069 _field_lt_slice_t *lt_slice = NULL; 3070 3071 /* Input parameters check. */ 3072 if (NULL == stage_fc || NULL == fg) { 3073 return (BCM_E_PARAM); 3074 } 3075 3076 /* Validate slice for exact match group. */ 3077 if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 3078 return _field_th_exactmatch_slice_validate(unit, stage_fc, 3079 fg, slice_id); 3080 } 3081 3082 #if defined(BCM_FLOWTRACKER_SUPPORT) 3083 if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 3084 return _field_hx5_ft_slice_validate(unit, stage_fc, fg, slice_id); 3085 } 3086 #endif 3087 3088 /* 3089 * If the slice belongs to an auto-expanded group and it is not the first 3090 * slice of that group, cannot use it. 3091 */ 3092 if (stage_fc->slices[fg->instance][slice_id].prev != NULL) { 3093 return (BCM_E_CONFIG); 3094 } 3095 3096 /* 3097 * Skip the slice if group slice size is small and 3098 * slice is not of smaller size. 3099 */ 3100 if ((fg->flags & _FP_GROUP_SELECT_SMALL_SLICE) && 3101 (0 == (stage_fc->slices[fg->instance][slice_id].slice_flags & 3102 _BCM_FIELD_SLICE_SIZE_SMALL))) { 3103 return (BCM_E_CONFIG); 3104 } 3105 3106 /* 3107 * Skip the slice if group slice size is large and 3108 * slice is not of large size. 3109 */ 3110 if ((fg->flags & _FP_GROUP_SELECT_LARGE_SLICE) && 3111 (0 == (stage_fc->slices[fg->instance][slice_id].slice_flags & 3112 _BCM_FIELD_SLICE_SIZE_LARGE))) { 3113 return (BCM_E_CONFIG); 3114 } 3115 3116 /* 3117 * Skip the slice if group is Intraslice and slice is not Intraslice 3118 * capable. 3119 */ 3120 if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) 3121 && !(stage_fc->slices[fg->instance][slice_id].slice_flags 3122 & _BCM_FIELD_SLICE_INTRASLICE_CAPABLE)) { 3123 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3124 "FP(unit %d) Verb: bad slice=%d for IntraSliceDouble wide-mode.\n"), 3125 unit, slice_id)); 3126 return (BCM_E_CONFIG); 3127 } 3128 3129 /* 3130 * Requested 80bit single wide group mode. Check if slice is already 3131 * operating in 160bit mode and return error if that's true 3132 */ 3133 fs_part[0] = stage_fc->slices[fg->instance] + slice_id; 3134 if (((fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) 3135 && !(fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) 3136 && (fs_part[0]->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 3137 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3138 "FP(unit %d) Verb: bad slice=%d for Single wide-mode.\n"), unit, 3139 slice_id)); 3140 return (BCM_E_CONFIG); 3141 } 3142 3143 /* 3144 * Three TCAMs are grouped to give a memory macro of size "160b * 256 * 3". 3145 * Triple wide group is created using slices within the same memory macro. 3146 */ 3147 if ((fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) && (slice_id % 3 != 0)) { 3148 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3149 "FP(unit %d) Verb: bad slice=%d for Triple wide-mode.\n"), unit, 3150 slice_id)); 3151 return (BCM_E_CONFIG); 3152 } 3153 3154 /* 3155 * Double wide group is created using consecutive slices within a memory 3156 * macro. But consecutive slices across a memory macro boundary cannot be 3157 * paried to create a double wide group. Skip slices 2, 5, 8 and 11 from 3158 * allocating for Double Wide Group base slice. 3159 */ 3160 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) && (2 == (slice_id % 3))) { 3161 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3162 "FP(unit %d) Verb: bad slice=%d for Double wide-mode.\n"), unit, 3163 slice_id)); 3164 return (BCM_E_CONFIG); 3165 } 3166 3167 /* 3168 * For slices 1, 4, 7 and 10 check if previous slice is configured for Double 3169 * wide mode. If TRUE, then skip current slice for Double wide groups. 3170 */ 3171 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) && (1 == (slice_id % 3))) { 3172 fs_part[0] = stage_fc->slices[fg->instance] + (slice_id - 1); 3173 if (fs_part[0]->group_flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 3174 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3175 "FP(unit %d) Verb: slice=%d is secondary slice of DoubleWide" 3176 " group.\n"), unit, slice_id)); 3177 return (BCM_E_CONFIG); 3178 } 3179 3180 /* 3181 * If previous slice is unused, then current slice will be used as 3182 * secondary slice for the double wide group, hence skip it. 3183 */ 3184 if (0 == (fs_part[0]->group_flags & _FP_GROUP_SPAN_MASK)) { 3185 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3186 "FP(unit %d) Verb: slice=%d accounted for DoubleWide" 3187 " group.\n"), unit, slice_id)); 3188 return (BCM_E_CONFIG); 3189 } 3190 } 3191 3192 /* 3193 * Validate slice current mode for double wide group's allocation 3194 * eligibility. 3195 */ 3196 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 3197 fs_part[0] = stage_fc->slices[fg->instance] + slice_id; 3198 fs_part[1] = stage_fc->slices[fg->instance] + (slice_id + 1); 3199 if (((fs_part[0]->group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) 3200 && !(fs_part[0]->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) 3201 || ((fs_part[1]->group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) 3202 && !(fs_part[1]->group_flags 3203 & _FP_GROUP_INTRASLICE_DOUBLEWIDE))) { 3204 /* 3205 * HW Limitation: Single wide mode slices (80-bit wide) in use 3206 * cannot be paired with another slice. 3207 */ 3208 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3209 "FP(unit %d) Verb: bad slice=%d for Double wide-mode.\n"), 3210 unit, slice_id)); 3211 return (BCM_E_CONFIG); 3212 } 3213 } 3214 3215 /* Validate slice for triple wide mode use. */ 3216 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 3217 fs_part[0] = stage_fc->slices[fg->instance] + slice_id; 3218 fs_part[1] = stage_fc->slices[fg->instance] + slice_id + 1; 3219 fs_part[2] = stage_fc->slices[fg->instance] + slice_id + 2; 3220 if (((fs_part[0]->group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) 3221 && !(fs_part[0]->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) 3222 || ((fs_part[1]->group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) 3223 && !(fs_part[1]->group_flags 3224 & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) 3225 || ((fs_part[2]->group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) 3226 && !(fs_part[2]->group_flags 3227 & _FP_GROUP_INTRASLICE_DOUBLEWIDE))) { 3228 /* 3229 * HW Limitation: Single wide mode slices (80-bit wide) in use 3230 * cannot be paired with another slice. 3231 */ 3232 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3233 "FP(unit %d) Verb: bad slice=%d for Triple-mode.\n"), unit, 3234 slice_id)); 3235 return (BCM_E_CONFIG); 3236 } 3237 } 3238 3239 /* Initialize group auto expansion support status. */ 3240 if (soc_feature(unit, soc_feature_field_virtual_slice_group)) { 3241 if (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION) { 3242 fg->flags |= _FP_GROUP_SELECT_AUTO_EXPANSION; 3243 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3244 "FP(unit %d) Verb: Group Auto Expansion status=%d.\n"), 3245 unit, (fg->flags & _FP_GROUP_SELECT_AUTO_EXPANSION) ? 1: 0)); 3246 } 3247 } 3248 3249 /* Retrieve the existing groups associated with the Slice */ 3250 rv = _bcm_field_slice_group_get_next(unit, fg->instance, 3251 fg->stage_id, slice_id, 3252 &fg_ptr, &fg_ptr); 3253 3254 if (BCM_SUCCESS(rv)) { 3255 3256 int mode; 3257 3258 /* In case of auto-expansion, go for a next slice for the same group. */ 3259 if (fg == fg_ptr) { 3260 return (BCM_E_CONFIG); 3261 } 3262 3263 /* Compare the group priority with the existing group in the slice. */ 3264 if (fg->priority != fg_ptr->priority) { 3265 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3266 "Slice[%d] contains other groups with different priority.\n\r"), 3267 slice_id)); 3268 return (BCM_E_CONFIG); 3269 } 3270 3271 /* Allow two groups without preselectors and with same prioirty for 3272 * backward comaptability. If two groups have same prioirty, that 3273 * means prioirty b/w these two groups doesnot matter to the user. 3274 */ 3275 if ((fg_ptr->flags & _FP_GROUP_PRESELECTOR_SUPPORT) == 0 && 3276 (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) == 0) { 3277 return BCM_E_CONFIG; 3278 } 3279 3280 /* 3281 * Groups can't share the slice, if the existing group 3282 * doesn't support preselector 3283 */ 3284 if ((fg_ptr->flags & _FP_GROUP_PRESELECTOR_SUPPORT) == 0) { 3285 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3286 "Group creation failed, Already default group exists" 3287 " with the same priority[%d].\n\r"), 3288 fg_ptr->priority)); 3289 return (BCM_E_PARAM); 3290 } 3291 3292 if ((fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) == 0) { 3293 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3294 "Group creation failed, can't create a group with the priority" 3295 " same as existing preselector group priority[%d]\n\r"), 3296 fg_ptr->priority)); 3297 return (BCM_E_PARAM); 3298 } 3299 3300 /* Compare the group modes */ 3301 mode = _FP_GROUP_SPAN_SINGLE_SLICE | _FP_GROUP_SPAN_DOUBLE_SLICE | 3302 _FP_GROUP_SPAN_TRIPLE_SLICE | _FP_GROUP_INTRASLICE_DOUBLEWIDE; 3303 3304 if ((fg->flags & mode) != (fg_ptr->flags & mode)) { 3305 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3306 "Group creation failed, already existing group with the same" 3307 " priority[%d] is in different mode. Can't create same priority" 3308 " groups with different modes.\n\r"), 3309 slice_id)); 3310 return (BCM_E_PARAM); 3311 } 3312 3313 /* Update the LT Slice to which the group's 3314 * preselector entries are to be created. */ 3315 lt_slice = fg_ptr->lt_slices; 3316 } else if (rv == BCM_E_NOT_FOUND) { 3317 fs_part[0] = stage_fc->slices[fg->instance] + slice_id; 3318 if (fs_part[0]->group_flags != 0x0) { 3319 /* 3320 * If group_flags is not NULL, the slice must belongs to some 3321 * other group and should be a part of double-wide or Triple-wide 3322 * for the previous slice. 3323 */ 3324 return BCM_E_CONFIG; 3325 } 3326 } else { 3327 return rv; 3328 } 3329 3330 /* 3331 * To share slices with more than one field group, mutually exclusive 3332 * pre-selection rules must be setup in LT select TCAM. In legacy mode, 3333 * only a default pre-selection rule is installed per-slice. Hence slices 3334 * cannot be shared by multiple field groups. Validate slice LT mapping to 3335 * confirm it's available for new group. For wide mode group, all slices 3336 * should be available for group create to succeed. 3337 */ 3338 BCM_IF_ERROR_RETURN(_field_th_group_lt_slice_validate(unit, stage_fc, fg, 3339 slice_id, lt_slice)); 3340 3341 return (BCM_E_NONE); 3342 } 3343 3344 /* 3345 * Function: 3346 * _field_th_ingress_slice_mode_set 3347 * Purpose: 3348 * Program group's slice mode in hardware. 3349 * Parameters: 3350 * unit - (IN) BCM device number. 3351 * stage_fc - (IN) Stage field control structure. 3352 * slice_num - (IN) Slice for which mode is to be set in HW. 3353 * fg - (IN) Field group structure pointer. 3354 * clear - (IN) Reset to hardware default value. 3355 * Returns: 3356 * BCM_E_XXX 3357 */ 3358 STATIC int 3359 _field_th_ingress_slice_mode_set(int unit, _field_stage_t *stage_fc, 3360 uint8 slice_num, _field_group_t *fg, 3361 int clear) 3362 { 3363 uint8 mode; /* Slice mode: 0-Narrow, 1-Wide. */ 3364 uint32 ifp_config; /* Register SW entry buffer. */ 3365 soc_reg_t ifp_config_reg = INVALIDr; /* Per-Pipe IFP config registers. */ 3366 3367 /* Input Parameter Check */ 3368 if (NULL == stage_fc || NULL == fg) { 3369 return (BCM_E_PARAM); 3370 } 3371 3372 /* Do nothing for exact match stage. */ 3373 if ((stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) || 3374 (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 3375 return (BCM_E_NONE); 3376 } 3377 3378 if (0 == clear) { 3379 /* Determine the slice mode based on group flags. */ 3380 mode = (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) 3381 && !(fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ? 0 : 1; 3382 } else { 3383 /* HW reset default is "1 - Wide" mode. */ 3384 mode = 1; 3385 } 3386 3387 3388 switch (stage_fc->oper_mode) { 3389 case bcmFieldGroupOperModeGlobal: 3390 /* Get slice configuration from hardware. */ 3391 BCM_IF_ERROR_RETURN(READ_IFP_CONFIGr(unit, slice_num, &ifp_config)); 3392 3393 /* Set slice mode value in register buffer. */ 3394 if (!soc_feature(unit, 3395 soc_feature_ifp_no_narrow_mode_support)) { 3396 soc_reg_field_set(unit, IFP_CONFIGr, &ifp_config, 3397 IFP_SLICE_MODEf, 3398 mode); 3399 } 3400 3401 /* Write register value to hardware. */ 3402 BCM_IF_ERROR_RETURN(WRITE_IFP_CONFIGr(unit, slice_num, ifp_config)); 3403 break; 3404 3405 case bcmFieldGroupOperModePipeLocal: 3406 BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit, 3407 IFP_CONFIGr, 3408 fg->instance, 3409 &ifp_config_reg)); 3410 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, 3411 ifp_config_reg, REG_PORT_ANY, slice_num, 3412 &ifp_config)); 3413 3414 /* Set slice mode value in register buffer. */ 3415 if (!soc_feature(unit, 3416 soc_feature_ifp_no_narrow_mode_support)) { 3417 soc_reg_field_set(unit, ifp_config_reg, &ifp_config, 3418 IFP_SLICE_MODEf, mode); 3419 } 3420 3421 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, 3422 ifp_config_reg, REG_PORT_ANY, slice_num, 3423 ifp_config)); 3424 break; 3425 default: 3426 return (BCM_E_INTERNAL); 3427 } 3428 3429 return (BCM_E_NONE); 3430 } 3431 3432 /* 3433 * Function: 3434 * _field_th_lt_entry_dirty 3435 * Purpose: 3436 * Check if logical table entry was modified after last installation 3437 * Parameters: 3438 * unit - (IN) BCM device number. 3439 * lt_f_ent - (IN) Primary entry pointer. 3440 * dirty - (OUT) Entry dirty flag status. 3441 * Returns: 3442 * BCM_E_XXX 3443 */ 3444 STATIC int 3445 _field_th_lt_entry_dirty(int unit, _field_lt_entry_t *lt_f_ent, int *dirty) 3446 { 3447 int parts_count = 0; /* Entry TCAM parts count. */ 3448 int idx; /* Entry parts iterator. */ 3449 3450 /* Input parameters check. */ 3451 if (NULL == lt_f_ent || NULL == dirty) { 3452 return (BCM_E_PARAM); 3453 } 3454 3455 /* Get number of TCAM parts based on group flags. */ 3456 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, 3457 lt_f_ent->group->flags, &parts_count)); 3458 3459 for (idx = 0; idx < parts_count; idx++) { 3460 if (lt_f_ent[idx].flags & _FP_ENTRY_DIRTY) { 3461 break; 3462 } 3463 } 3464 3465 /* Update dirty flags status based on part index value. */ 3466 *dirty = (idx < parts_count) ? TRUE : FALSE; 3467 3468 return (BCM_E_NONE); 3469 } 3470 3471 /* 3472 * Function: 3473 * _field_lt_entry_t_compare 3474 * Purpose: 3475 * Compare logical table entry id in _field_lt_entry_t structure. 3476 * Parameters: 3477 * a - (IN) first entry to compare. 3478 * b - (IN) second entry to compare with. 3479 * Returns: 3480 * a<=>b 3481 */ 3482 STATIC int 3483 _field_lt_entry_t_compare(void *a, void *b) 3484 { 3485 _field_lt_entry_t **first; /* First compared entry. */ 3486 _field_lt_entry_t **second; /* Second compared entry. */ 3487 3488 first = (_field_lt_entry_t **)a; 3489 second = (_field_lt_entry_t **)b; 3490 3491 if ((*first)->eid < (*second)->eid) { 3492 return (-1); 3493 } else if ((*first)->eid > (*second)->eid) { 3494 return (1); 3495 } 3496 return (0); 3497 } 3498 3499 /* 3500 * Function: 3501 * _field_th_entry_flags_to_tcam_part 3502 * Purpose: 3503 * Each logical table field entry contains up to 3 TCAM entries. This 3504 * routine maps sw entry flags to tcam entry (0-2). 3505 * Note this is not a physical address in tcam. 3506 * Single: 0 3507 * Single & Intraslice Double: 0 3508 * Paired: 0, 1 3509 * Triple: 0, 1, 2 3510 * Parameters: 3511 * unit - (IN) BCM device number. 3512 * entry_flags - (IN) Entry flags. 3513 * group_flags - (IN) Entry group flags. 3514 * entry_part - (OUT) Entry part (0-2) 3515 * Returns: 3516 * BCM_E_NONE - Success 3517 * BCM_E_INTERNAL - Error 3518 */ 3519 int 3520 _bcm_field_th_entry_flags_to_tcam_part(int unit, uint32 entry_flags, 3521 uint32 group_flags, 3522 uint8 *entry_part) 3523 { 3524 /* Input parameter check. */ 3525 if (NULL == entry_part) { 3526 return (BCM_E_PARAM); 3527 } 3528 3529 if (entry_flags & _FP_ENTRY_PRIMARY) { 3530 *entry_part = 0; 3531 } else if (entry_flags & _FP_ENTRY_SECONDARY) { 3532 *entry_part = 1; 3533 } else if (entry_flags & _FP_ENTRY_TERTIARY) { 3534 *entry_part = 2; 3535 } else { 3536 return (BCM_E_INTERNAL); 3537 } 3538 return (BCM_E_NONE); 3539 } 3540 3541 /* 3542 * Function: 3543 * _field_th_lt_entry_get 3544 * Purpose: 3545 * Lookup a LT entry in Group's LT entries array for a given unit ID, 3546 * Entry ID and entry flags. 3547 * Parmeters: 3548 * unit - (IN) BCM device number. 3549 * lt_eid - (IN) Logical table Entry ID. 3550 * flags - (IN) Entry flags to match. 3551 * lt_ent_p - (OUT) Entry lookup result. 3552 * Returns: 3553 * BCM_E_XXX 3554 */ 3555 STATIC int 3556 _field_th_lt_entry_get(int unit, bcm_field_entry_t lt_eid, uint32 flags, 3557 _field_lt_entry_t **lt_ent_p) 3558 { 3559 _field_lt_entry_t target; /* LT entry lookup variable. */ 3560 _field_lt_entry_t *lt_f_ent; /* LT entry lookup pointer. */ 3561 _field_control_t *fc; /* Device Field control structure. */ 3562 _field_group_t *fg; /* Field group structure. */ 3563 uint8 entry_part = 0; /* Wide entry part number. */ 3564 int idx; /* LT entry index. */ 3565 3566 /* Input parameters check. */ 3567 if (NULL == lt_ent_p) { 3568 return (BCM_E_PARAM); 3569 } 3570 3571 /* Initialize target logical table entry. */ 3572 target.eid = lt_eid; 3573 lt_f_ent = ⌖ 3574 3575 /* Get device Field control structure. */ 3576 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 3577 3578 /* Get field groups handle. */ 3579 fg = fc->groups; 3580 3581 while (NULL != fg) { 3582 /* Skip empty groups. */ 3583 if (NULL == fg->lt_entry_arr) { 3584 fg = fg->next; 3585 continue; 3586 } 3587 3588 /* Search in group entry array list.*/ 3589 idx = _shr_bsearch(fg->lt_entry_arr, fg->lt_grp_status.entry_count, 3590 sizeof(_field_lt_entry_t *), (void *)<_f_ent, 3591 _field_lt_entry_t_compare); 3592 if (idx >= 0) { 3593 (void) _bcm_field_th_entry_flags_to_tcam_part(unit, flags, 3594 fg->flags, &entry_part); 3595 *lt_ent_p = fg->lt_entry_arr[idx] + entry_part; 3596 return (BCM_E_NONE); 3597 } 3598 fg = fg->next; 3599 } 3600 3601 /* LT entry with lt_eid not found. */ 3602 return (BCM_E_NOT_FOUND); 3603 } 3604 3605 /* 3606 * Function: 3607 * _field_th_lt_entry_get_by_id 3608 * Purpose: 3609 * Lookup a complete Logical table FP rule(entry) from a unit & rule id 3610 * choice. 3611 * Parmeters: 3612 * unit - (IN) BCM device number. 3613 * lt_eid - (IN) LT Entry id. 3614 * lt_ent_arr - (OUT) Entry lookup result array. 3615 * (Array of pointers to primary/secondary/teriary ... 3616 * parts of entry). 3617 * Returns: 3618 * BCM_E_XXX 3619 */ 3620 STATIC int 3621 _field_th_lt_entry_get_by_id(int unit, bcm_field_entry_t lt_eid, 3622 _field_lt_entry_t **lt_ent_arr) 3623 { 3624 int rv; /* Operation return status. */ 3625 3626 /* Input parameter check. */ 3627 if (NULL == lt_ent_arr) { 3628 return (BCM_E_PARAM); 3629 } 3630 3631 /* Initialize entry pointer array*/ 3632 *lt_ent_arr = NULL; 3633 3634 rv = _field_th_lt_entry_get(unit, lt_eid, _FP_ENTRY_PRIMARY, lt_ent_arr); 3635 return (rv); 3636 } 3637 3638 /* 3639 * Function: 3640 * _field_th_lt_entry_tcam_idx_get 3641 * Purpose: 3642 * Get the TCAM index of an entry ID. 3643 * Parameters: 3644 * unit - (IN) BCM device number. 3645 * lt_f_ent - (IN) Pointer to field logical table entry structure. 3646 * lt_fs - (IN) Pointer to field logical table slice structure. 3647 * tcam_idx - (OUT) Entry tcam index. 3648 * 3649 * Returns: 3650 * BCM_E_XXX 3651 */ 3652 STATIC int 3653 _field_th_lt_entry_tcam_idx_get(int unit, _field_lt_entry_t *lt_f_ent, 3654 _field_lt_slice_t *lt_fs, int *tcam_idx) 3655 { 3656 /* Input parameters check. */ 3657 if ((NULL == lt_f_ent) || (NULL == tcam_idx || (NULL == lt_fs))) { 3658 return (BCM_E_PARAM); 3659 } 3660 3661 /* Requested entry structure sanity check. */ 3662 if ((NULL == lt_f_ent->group) || (NULL == lt_f_ent->lt_fs)) { 3663 return (BCM_E_PARAM); 3664 } 3665 3666 /* Calculate the TCAM index. */ 3667 *tcam_idx = lt_fs->start_tcam_idx + lt_f_ent->index; 3668 3669 return (BCM_E_NONE); 3670 } 3671 3672 /* 3673 * Function: 3674 * _field_th_lt_tcam_mem_get 3675 * Purpose: 3676 * Get logica table memory identifier based on stage group operational mode. 3677 * Parameters: 3678 * unit - (IN) BCM device number. 3679 * stage_fc - (IN) Stage field control structure. 3680 * lt_f_ent - (IN) Pointer to field logical table entry structure. 3681 * lt_tcam_mem - (IN/OUT) LT memory identifer pointer. 3682 * 3683 * Returns: 3684 * BCM_E_XXX 3685 */ 3686 STATIC int 3687 _field_th_lt_tcam_mem_get(int unit, _field_stage_t *stage_fc, 3688 _field_lt_entry_t *lt_f_ent, 3689 soc_mem_t *lt_tcam_mem) 3690 { 3691 /* Input parameters check. */ 3692 if ((NULL == stage_fc) || (NULL == lt_f_ent) || (NULL == lt_tcam_mem)) { 3693 return (BCM_E_PARAM); 3694 } 3695 3696 /* Set LT selection memory identifier based on stage group oper mode. */ 3697 switch (stage_fc->oper_mode) { 3698 case bcmFieldGroupOperModeGlobal: 3699 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 3700 *lt_tcam_mem = IFP_LOGICAL_TABLE_SELECTm; 3701 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 3702 *lt_tcam_mem = EXACT_MATCH_LOGICAL_TABLE_SELECTm; 3703 } else { 3704 return (BCM_E_INTERNAL); 3705 } 3706 break; 3707 case bcmFieldGroupOperModePipeLocal: 3708 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 3709 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 3710 IFP_LOGICAL_TABLE_SELECTm, 3711 lt_f_ent->group->instance, 3712 lt_tcam_mem)); 3713 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 3714 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 3715 EXACT_MATCH_LOGICAL_TABLE_SELECTm, 3716 lt_f_ent->group->instance, 3717 lt_tcam_mem)); 3718 } else { 3719 return (BCM_E_INTERNAL); 3720 } 3721 break; 3722 default: 3723 return (BCM_E_INTERNAL); 3724 } 3725 return (BCM_E_NONE); 3726 } 3727 3728 /* 3729 * Function: 3730 * _bcm_field_th_lt_tcam_entry_get 3731 * Purpose: 3732 * Read an entry installed in hardware into SW entry buffer. 3733 * Parameters: 3734 * unit - (IN) BCM device number. 3735 * fg - (IN) Pointer to field group structure. 3736 * lt_f_ent - (OUT) Pointer to field logical table entry structure. 3737 * Returns: 3738 * BCM_E_XXX 3739 */ 3740 int 3741 _bcm_field_th_lt_tcam_entry_get(int unit, _field_group_t *fg, 3742 _field_lt_entry_t *lt_f_ent) 3743 { 3744 uint32 tcam_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Entry buffer. */ 3745 _field_stage_t *stage_fc; /* Stage field control structure. */ 3746 int tcam_idx; /* TCAM index. */ 3747 static soc_mem_t lt_tcam_mem; /* LT selection TCAM memory ID. */ 3748 int rv; /* Operation return status. */ 3749 3750 /* Input parameters check. */ 3751 if ((NULL == lt_f_ent) || (NULL == fg)) { 3752 return (BCM_E_PARAM); 3753 } 3754 3755 /* Check if LT TCAM entry is already present in SW. */ 3756 if (NULL != lt_f_ent->tcam.key) { 3757 return (BCM_E_NONE); 3758 } 3759 3760 /* Get stage field control structure. */ 3761 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 3762 &stage_fc)); 3763 3764 /* Get key and data field based on stage */ 3765 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 3766 /* Get key field size in logical table entry. */ 3767 lt_f_ent->tcam.key_size = WORDS2BYTES(soc_mem_field_length(unit, 3768 IFP_LOGICAL_TABLE_SELECTm, KEYf)); 3769 3770 /* Get data field size in logical table entry. */ 3771 lt_f_ent->tcam.data_size = WORDS2BYTES(soc_mem_field_length(unit, 3772 IFP_LOGICAL_TABLE_SELECTm, DATAf)); 3773 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 3774 /* Get key field size in logical table entry. */ 3775 lt_f_ent->tcam.key_size = WORDS2BYTES(soc_mem_field_length(unit, 3776 EXACT_MATCH_LOGICAL_TABLE_SELECTm, KEYf)); 3777 3778 /* Get data field size in logical table entry. */ 3779 lt_f_ent->tcam.data_size = WORDS2BYTES(soc_mem_field_length(unit, 3780 EXACT_MATCH_LOGICAL_TABLE_SELECTm, DATAf)); 3781 } else { 3782 return (BCM_E_PARAM); 3783 } 3784 3785 /* Allocate memory to store entry Key info. */ 3786 _FP_XGS3_ALLOC(lt_f_ent->tcam.key, lt_f_ent->tcam.key_size, 3787 "LT Key Alloc."); 3788 if (NULL == lt_f_ent->tcam.key) { 3789 rv = BCM_E_MEMORY; 3790 goto error; 3791 } 3792 3793 /* Allocate memory to store entry Mask info. */ 3794 _FP_XGS3_ALLOC(lt_f_ent->tcam.mask, lt_f_ent->tcam.key_size, 3795 "LT Mask Alloc."); 3796 if (NULL == lt_f_ent->tcam.mask) { 3797 rv = BCM_E_MEMORY; 3798 goto error; 3799 } 3800 3801 /* Allocate memory to store entry Data info. */ 3802 _FP_XGS3_ALLOC(lt_f_ent->tcam.data, lt_f_ent->tcam.data_size, 3803 "LT Data Alloc."); 3804 if (NULL == lt_f_ent->tcam.data) { 3805 rv = BCM_E_MEMORY; 3806 goto error; 3807 } 3808 3809 /* Get entry TCAM index. */ 3810 rv = _field_th_lt_entry_tcam_idx_get(unit, lt_f_ent, lt_f_ent->lt_fs, 3811 &tcam_idx); 3812 if (BCM_FAILURE(rv)) { 3813 goto error; 3814 } 3815 3816 /* Get logical table memory name based on the group operational mode. */ 3817 BCM_IF_ERROR_RETURN(_field_th_lt_tcam_mem_get(unit, stage_fc, lt_f_ent, 3818 <_tcam_mem)); 3819 3820 /* Read entry part from hardware. */ 3821 rv = soc_th_ifp_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY, tcam_idx, 3822 tcam_entry); 3823 if (BCM_FAILURE(rv)) { 3824 goto error; 3825 } 3826 3827 /* Get entry Key value. */ 3828 soc_mem_field_get(unit, lt_tcam_mem, tcam_entry, KEYf, 3829 lt_f_ent->tcam.key); 3830 3831 /* Get entry Mask value. */ 3832 soc_mem_field_get(unit, lt_tcam_mem, tcam_entry, MASKf, 3833 lt_f_ent->tcam.mask); 3834 3835 /* Get entry Data value. */ 3836 soc_mem_field_get(unit, lt_tcam_mem, tcam_entry, DATAf, 3837 lt_f_ent->tcam.data); 3838 3839 return (BCM_E_NONE); 3840 3841 error: 3842 if (lt_f_ent->tcam.key) { 3843 sal_free(lt_f_ent->tcam.key); 3844 lt_f_ent->tcam.key = NULL; 3845 } 3846 3847 if (lt_f_ent->tcam.mask) { 3848 sal_free(lt_f_ent->tcam.mask); 3849 lt_f_ent->tcam.mask = NULL; 3850 } 3851 3852 if (lt_f_ent->tcam.data) { 3853 sal_free(lt_f_ent->tcam.data); 3854 lt_f_ent->tcam.data = NULL; 3855 } 3856 3857 return (rv); 3858 } 3859 3860 /* 3861 * Function: 3862 * _field_th_lt_default_entry_install 3863 * Purpose: 3864 * Install a logical table entry in hardware. 3865 * Parameters: 3866 * unit - (IN) BCM device number. 3867 * lt_entry - (IN) Field logical table entry. 3868 * Returns: 3869 * BCM_E_XXX 3870 */ 3871 STATIC int 3872 _field_th_lt_default_entry_install(int unit, bcm_field_entry_t lt_entry) 3873 { 3874 _field_control_t *fc; /* Field control structure. */ 3875 _field_lt_entry_t *lt_f_ent; /* LT field entry. */ 3876 int rv; /* Operation return status. */ 3877 int dirty; /* Field entry dirty flag. */ 3878 3879 /* Get device field control structure. */ 3880 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 3881 3882 /* Lookup using entry ID and get the SW entry copy. */ 3883 BCM_IF_ERROR_RETURN(_field_th_lt_entry_get(unit, lt_entry, 3884 _FP_ENTRY_PRIMARY, <_f_ent)); 3885 3886 /* Check if entry has been modified since last install in hardware. */ 3887 BCM_IF_ERROR_RETURN(_field_th_lt_entry_dirty(unit, lt_f_ent, &dirty)); 3888 3889 if (dirty) { 3890 /* Entry has changed, install in hardware. */ 3891 rv = _field_th_lt_default_tcam_entry_install(unit, lt_entry, 0, 0, NULL); 3892 } else { 3893 /* No change and nothing to do, return success. */ 3894 rv = BCM_E_NONE; 3895 } 3896 return rv; 3897 } 3898 3899 /* 3900 * Function: 3901 * _field_th_group_lt_entry_add 3902 * Purpose: 3903 * Given stage, group instance, slice and entry offset in slice, calculate 3904 * TCAM index. 3905 * Parameters: 3906 * unit - (IN) BCM device number. 3907 * fg - (IN) Field group structure. 3908 * lt_f_ent - (OUT) Field logical table entry structure. 3909 * Returns: 3910 * BCM_E_XXX 3911 */ 3912 STATIC int 3913 _field_th_group_lt_entry_add(int unit, _field_group_t *fg, 3914 _field_lt_entry_t *lt_f_ent) 3915 { 3916 _field_lt_entry_t **lt_f_ent_arr; /* Field group LT entry array. */ 3917 int mem_sz; /* Allocation memory size. */ 3918 int idx; /* Entry insertion index. */ 3919 int tmp; /* Temporary iterator. */ 3920 3921 /* Input parameters check. */ 3922 if (NULL == fg || NULL == lt_f_ent) { 3923 return (BCM_E_PARAM); 3924 } 3925 3926 /* Verify if entry is already present in the group. */ 3927 if (NULL != fg->lt_entry_arr) { 3928 idx = _shr_bsearch(fg->lt_entry_arr, fg->lt_grp_status.entry_count, 3929 sizeof(_field_lt_entry_t *), <_f_ent, 3930 _field_lt_entry_t_compare); 3931 if (idx >= 0) { 3932 return (BCM_E_NONE); 3933 } 3934 } else { 3935 idx = -1; /* Insert into 0th location. */ 3936 } 3937 3938 /* Check if group has enough room for new entry. */ 3939 if ((fg->lt_grp_status.entry_count + 1) 3940 > (fg->lt_ent_blk_cnt * _FP_GROUP_ENTRY_ARR_BLOCK)) { 3941 mem_sz = _FP_GROUP_ENTRY_ARR_BLOCK * (fg->lt_ent_blk_cnt + 1) 3942 * sizeof(_field_lt_entry_t *); 3943 lt_f_ent_arr = NULL; 3944 _FP_XGS3_ALLOC(lt_f_ent_arr, mem_sz, "field group LT entries array"); 3945 if (NULL == lt_f_ent_arr) { 3946 return (BCM_E_MEMORY); 3947 } 3948 3949 /* Copy original array to newly allocated one. */ 3950 if (NULL != fg->lt_entry_arr) { 3951 mem_sz = _FP_GROUP_ENTRY_ARR_BLOCK * (fg->lt_ent_blk_cnt) 3952 * sizeof(_field_lt_entry_t *); 3953 sal_memcpy(lt_f_ent_arr, fg->lt_entry_arr, mem_sz); 3954 sal_free(fg->lt_entry_arr); 3955 } 3956 3957 fg->lt_entry_arr = lt_f_ent_arr; 3958 fg->lt_ent_blk_cnt++; 3959 } 3960 3961 /* Check entry block exists to add the entry. */ 3962 if (NULL != fg->lt_entry_arr) { 3963 /* 3964 * Make room for entry insertion. 3965 */ 3966 idx = (((-1) * idx) - 1); 3967 tmp = fg->lt_grp_status.entry_count - 1; 3968 while (tmp >= idx) { 3969 fg->lt_entry_arr[tmp + 1] = fg->lt_entry_arr[tmp]; 3970 tmp--; 3971 } 3972 fg->lt_entry_arr[idx] = lt_f_ent; 3973 fg->lt_grp_status.entry_count++; 3974 } 3975 return (BCM_E_NONE); 3976 } 3977 3978 /* 3979 * Function: 3980 * _bcm_field_th_lt_slice_offset_to_tcam_index 3981 * Purpose: 3982 * Given stage, group instance, slice and entry offset in slice, calculate 3983 * TCAM index. 3984 * Parameters: 3985 * unit - (IN) BCM device number. 3986 * stage_fc - (IN) Pointer to field entry structure. 3987 * slice - (IN) Entry slice number. 3988 * slice_idx -(IN) Entry offset in the slice. 3989 * tcam_idx - (OUT) Entry tcam index. 3990 * Returns: 3991 * BCM_E_XXX 3992 */ 3993 int 3994 _bcm_field_th_lt_slice_offset_to_tcam_index(int unit, _field_stage_t *stage_fc, 3995 int instance, int slice, 3996 int slice_idx, int *tcam_idx) 3997 { 3998 _field_lt_slice_t *lt_fs; /* Logical table slice number. */ 3999 4000 /* Input parameters check. */ 4001 if ((NULL == stage_fc) || (NULL == tcam_idx)) { 4002 return (BCM_E_PARAM); 4003 } 4004 4005 /* Input parameters check. */ 4006 if (instance < 0 || instance >= stage_fc->num_instances) { 4007 return (BCM_E_PARAM); 4008 } 4009 4010 /* Get logical table slice structure. */ 4011 lt_fs = stage_fc->lt_slices[instance] + slice; 4012 4013 /* 4014 * Compute TCAM index using the slice start TCAM index and supplied 4015 * slice offset index. 4016 */ 4017 *tcam_idx = lt_fs->start_tcam_idx + slice_idx; 4018 4019 return (BCM_E_NONE); 4020 } 4021 4022 /* 4023 * Function: 4024 * _bcm_field_th_lt_tcam_idx_to_slice_offset 4025 * Purpose: 4026 * Given stage, group instance and tcam_index, calculate slice and entry 4027 * offset in the slice. 4028 * Parameters: 4029 * unit - (IN) BCM device number. 4030 * stage_fc - (IN) Stage field control structure. 4031 * instance - (IN) Field Group instance. 4032 * tcam_idx - (IN) Entry tcam index. 4033 * slice - (OUT) Entry slice number. 4034 * slice_idx - (OUT) Entry offset in the slice. 4035 * Returns: 4036 * BCM_E_XXX 4037 */ 4038 int 4039 _bcm_field_th_lt_tcam_idx_to_slice_offset(int unit, _field_stage_t *stage_fc, 4040 int instance, int tcam_idx, 4041 int *slice, int *slice_idx) 4042 { 4043 _field_lt_slice_t *lt_fs; /* Field Slice number. */ 4044 int idx; /* Slice iterator. */ 4045 4046 /* Input parameters check. */ 4047 if ((NULL == stage_fc) || (NULL == slice_idx) || (NULL == slice) 4048 || (instance < 0 || instance > stage_fc->num_instances)) { 4049 return (BCM_E_PARAM); 4050 } 4051 4052 for (idx = 0; idx < stage_fc->tcam_slices; idx++) { 4053 lt_fs = stage_fc->lt_slices[instance] + idx; 4054 if (tcam_idx < (lt_fs->start_tcam_idx + lt_fs->entry_count)) { 4055 *slice = idx; 4056 *slice_idx = tcam_idx - lt_fs->start_tcam_idx; 4057 break; 4058 } 4059 } 4060 4061 /* TCAM index sanity check. */ 4062 if (idx == stage_fc->tcam_slices) { 4063 return (BCM_E_PARAM); 4064 } 4065 4066 return (BCM_E_NONE); 4067 } 4068 4069 /* 4070 * Function: 4071 * _bcm_field_th_lt_entry_part_tcam_idx_get 4072 * 4073 * Purpose: 4074 * Given primary entry slice/idx calculate 4075 * secondary/tertiary slice/index. 4076 * 4077 * Parameters: 4078 * unit - (IN) BCM device number. 4079 * f_ent - (IN) Field entry pointer. 4080 * idx_pri - (IN) Primary entry tcam index. 4081 * ent_part - (IN) Entry part id. 4082 * idx_out - (OUT) Entry part tcam index. 4083 * Returns 4084 * BCM_E_XXX 4085 */ 4086 int 4087 _bcm_field_th_lt_entry_part_tcam_idx_get(int unit, _field_group_t *fg, 4088 uint32 idx_pri, uint8 ent_part, 4089 int *idx_out) 4090 { 4091 uint8 slice_num; /* Primary entry slice number. */ 4092 int pri_slice = -1; /* Prmary entry slice number. */ 4093 int pri_index = -1; /* Primary entry slice index. */ 4094 _field_stage_t *stage_fc; /* Stage field control structure. */ 4095 _field_lt_slice_t *lt_fs; /* Logical table slice structure. */ 4096 int rv; /* Operation return status. */ 4097 4098 4099 /* Input parameters check. */ 4100 if (NULL == fg || NULL == idx_out) { 4101 return (BCM_E_PARAM); 4102 } 4103 4104 /* Primary entry index. */ 4105 if (0 == ent_part) { 4106 *idx_out = idx_pri; 4107 return (BCM_E_NONE); 4108 } 4109 4110 /* Get Stage Field Control Structure. */ 4111 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 4112 &stage_fc)); 4113 4114 /* 4115 * Get primary part entry slice number and slice offset given entry TCAM 4116 * index. 4117 */ 4118 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_tcam_idx_to_slice_offset(unit, 4119 stage_fc, fg->instance, idx_pri, &pri_slice, &pri_index)); 4120 4121 /* Get entry part to slice number 0, 1, 2 */ 4122 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_slice_number(ent_part, 4123 fg->flags, &slice_num)); 4124 4125 /* Get slice descriptor structure. */ 4126 lt_fs = stage_fc->lt_slices[fg->instance] + (pri_slice + slice_num); 4127 4128 /* Get the TCAM index given slice number and slice entry offset. */ 4129 rv = _bcm_field_th_lt_slice_offset_to_tcam_index(unit, stage_fc, 4130 fg->instance, lt_fs->slice_number, pri_index, idx_out); 4131 4132 return (rv); 4133 } 4134 4135 /* 4136 * Function: 4137 * _field_th_lt_default_entry_phys_create 4138 * Purpose: 4139 * Create a physical entry in a logical table slice. 4140 * Parameters: 4141 * unit - (IN) BCM device number. 4142 * stage_fc - (IN) Stage field control structure. 4143 * lt_ent - (IN) Logical table entry identifier. 4144 * prio - (IN) Logical table entry priority. 4145 * lt_fs - (IN) Logical table slice structure. 4146 * fg - (IN) Field group structure. 4147 * ent_p - (OUT) Allocated & initialized entry. 4148 * Returns: 4149 * BCM_E_XXX 4150 */ 4151 STATIC int 4152 _field_th_lt_default_entry_phys_create(int unit, _field_stage_t *stage_fc, 4153 bcm_field_entry_t lt_ent, int prio, 4154 _field_lt_slice_t *lt_fs, _field_group_t *fg, 4155 _field_lt_entry_t **ent_p) 4156 { 4157 _field_control_t *fc; /* Field control structure. */ 4158 int idx; /* Slice entries iteration index. */ 4159 int parts_count = -1; /* Number of entry parts. */ 4160 int part_index; /* Entry parts iterator. */ 4161 int mem_sz; /* Memory allocation size. */ 4162 _field_lt_entry_t *lt_f_ent = NULL; /* LT field entry structure. */ 4163 int rv; /* Operation return status. */ 4164 int pri_tcam_idx = -1; /* Primary entry TCAM index. */ 4165 int slice_num = -1; /* Slice number. */ 4166 4167 /* Input parameters check. */ 4168 if ((NULL == stage_fc) || (NULL == lt_fs) || (NULL == fg) 4169 || (NULL == ent_p)) { 4170 return (BCM_E_PARAM); 4171 } 4172 4173 /* Check if free entries are available in the slice. */ 4174 if (0 == lt_fs->free_count) { 4175 return (BCM_E_RESOURCE); 4176 } 4177 4178 /* Get device field control structure. */ 4179 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4180 4181 /* Get number of entry parts based on group flags. */ 4182 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 4183 &parts_count)); 4184 4185 /* Calcuate buffer size required for SW entry. */ 4186 mem_sz = sizeof(_field_lt_entry_t) * parts_count; 4187 4188 /* Allocate and zero memory for LT selection entry. */ 4189 _FP_XGS3_ALLOC(lt_f_ent, mem_sz, "LT field entry"); 4190 if (NULL == lt_f_ent) { 4191 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4192 "FP(unit %d) Error: allocation failure for LT entry\n"), unit)); 4193 return (BCM_E_MEMORY); 4194 } 4195 4196 /* Get index for primary entry. */ 4197 for (idx = 0; idx < lt_fs->entry_count; idx++) { 4198 if (NULL == lt_fs->entries[idx]) { 4199 #if defined (BCM_TOMAHAWK3_SUPPORT) 4200 if ((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) && 4201 (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH)) { 4202 if (NULL == lt_fs->p_entries[idx]) { 4203 lt_f_ent->index = idx; 4204 break; 4205 } 4206 } else 4207 #endif 4208 { 4209 lt_f_ent->index = idx; 4210 break; 4211 } 4212 } 4213 } 4214 4215 /* Get entry TCAM index given slice number and entry offset in slice. */ 4216 rv = _bcm_field_th_lt_slice_offset_to_tcam_index(unit, stage_fc, 4217 fg->instance, lt_fs->slice_number, lt_f_ent->index, &pri_tcam_idx); 4218 if (BCM_FAILURE(rv)) { 4219 sal_free(lt_f_ent); 4220 return (rv); 4221 } 4222 4223 /* Fill entry primitives. */ 4224 for (idx = 0; idx < parts_count; idx++) { 4225 lt_f_ent[idx].eid = lt_ent; 4226 lt_f_ent[idx].prio = prio; 4227 lt_f_ent[idx].group = fg; 4228 4229 /* Get entry part flags. */ 4230 rv = _bcm_field_th_tcam_part_to_entry_flags(unit, idx, fg->flags, 4231 <_f_ent[idx].flags); 4232 if (BCM_FAILURE(rv)) { 4233 sal_free(lt_f_ent); 4234 return rv; 4235 } 4236 4237 /* Given primary entry TCAM index calculate entry part tcam index. */ 4238 if (0 != idx) { 4239 rv = _bcm_field_th_lt_entry_part_tcam_idx_get(unit, lt_f_ent->group, 4240 pri_tcam_idx, idx, &part_index); 4241 if (BCM_FAILURE(rv)) { 4242 sal_free(lt_f_ent); 4243 return (rv); 4244 } 4245 4246 /* 4247 * Given entry part TCAM index, determine the slice number and slice 4248 * offset index. 4249 */ 4250 rv = _bcm_field_th_lt_tcam_idx_to_slice_offset(unit, stage_fc, 4251 fg->instance, part_index, &slice_num, 4252 (int *)<_f_ent[idx].index); 4253 if (BCM_FAILURE(rv)) { 4254 sal_free(lt_f_ent); 4255 return (rv); 4256 } 4257 lt_f_ent[idx].lt_fs = stage_fc->lt_slices[fg->instance] + slice_num; 4258 } else { 4259 /* Set entry slice. */ 4260 lt_f_ent[idx].lt_fs = lt_fs; 4261 } 4262 4263 /* Mark entry dirty. */ 4264 lt_f_ent[idx].flags |= _FP_ENTRY_DIRTY; 4265 } 4266 4267 /* Insert the entry into group entry array. */ 4268 rv = _field_th_group_lt_entry_add(unit, fg, lt_f_ent); 4269 if (BCM_FAILURE(rv)) { 4270 sal_free(lt_f_ent); 4271 return (rv); 4272 } 4273 4274 /* Update slice related parameters after succesful update */ 4275 for (idx = 0; idx < parts_count; idx++) { 4276 /* Decrement slice free entry count for primary entries. */ 4277 lt_f_ent[idx].lt_fs->free_count--; 4278 4279 /* Assign entry to a slice. */ 4280 lt_f_ent[idx].lt_fs->entries[lt_f_ent[idx].index] = lt_f_ent + idx; 4281 } 4282 4283 /* Return allocated/filled entry structure to the caller. */ 4284 *ent_p = lt_f_ent; 4285 return (rv); 4286 } 4287 4288 /* 4289 * Function: 4290 * _field_th_group_lt_entry_delete 4291 * Purpose: 4292 * Delete an entry from group LT entries array. 4293 * Parameters: 4294 * unit - (IN) BCM device number. 4295 * fg - (IN) Field group structure. 4296 * lt_f_ent - (IN) Logical table entry structure. 4297 * Returns: 4298 * BCM_E_XXX 4299 */ 4300 STATIC int 4301 _field_th_group_lt_entry_delete(int unit, _field_group_t *fg, 4302 _field_lt_entry_t *lt_f_ent) 4303 { 4304 int idx; /* Entry deletion index. */ 4305 int tmp; /* Temporary iterator. */ 4306 4307 /* Input parameters check. */ 4308 if ((NULL == fg) || (NULL == lt_f_ent)) { 4309 return (BCM_E_PARAM); 4310 } 4311 4312 /* Ensure group entry array is valid. */ 4313 if (NULL == fg->lt_entry_arr) { 4314 return (BCM_E_INTERNAL); 4315 } 4316 4317 /* Confirm entry is present in the group. */ 4318 idx = _shr_bsearch(fg->lt_entry_arr, fg->lt_grp_status.entry_count, 4319 sizeof(_field_lt_entry_t *), <_f_ent, 4320 _field_lt_entry_t_compare); 4321 if (idx < 0) { 4322 return (BCM_E_NOT_FOUND); 4323 } 4324 4325 /* Store array index where the entry was found. */ 4326 tmp = idx; 4327 /* 4328 * Re-Pack the entries array to clear the last pointer due to entry deletion. 4329 */ 4330 while (tmp < fg->lt_grp_status.entry_count - 1) { 4331 fg->lt_entry_arr[tmp] = fg->lt_entry_arr[tmp + 1]; 4332 tmp++; 4333 } 4334 4335 /* Decrement total valid entry count. */ 4336 fg->lt_grp_status.entry_count--; 4337 4338 /* Clear entry address stored in the last array index. */ 4339 fg->lt_entry_arr[fg->lt_grp_status.entry_count] = NULL; 4340 4341 return (BCM_E_NONE); 4342 } 4343 4344 /* 4345 * Function: 4346 * _field_th_lt_default_entry_phys_destroy 4347 * Purpose: 4348 * Destroy a physical entry from a logical table slice. 4349 * Parameters: 4350 * unit - (IN) BCM device number. 4351 * lt_f_ent - (IN) Logical table entry structure. 4352 * Returns: 4353 * BCM_E_XXX 4354 */ 4355 STATIC int 4356 _field_th_lt_default_entry_phys_destroy(int unit, _field_lt_entry_t *lt_f_ent) 4357 { 4358 _field_control_t *fc; /* Device field control structure. */ 4359 _field_lt_slice_t *lt_fs; /* Logical table slice structure. */ 4360 _field_group_t *fg; /* Field group structure. */ 4361 int parts_count = -1; /* Entry parts count. */ 4362 int idx; /* Entry iterator index. */ 4363 uint8 slice_number; /* Slice number. */ 4364 int rv; /* Operation return status. */ 4365 4366 /* Input parameters check. */ 4367 if ((NULL == lt_f_ent) || (NULL == lt_f_ent->lt_fs)) { 4368 return (BCM_E_PARAM); 4369 } 4370 4371 /* Get field control structure. */ 4372 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4373 4374 /* Get entry slice information. */ 4375 lt_fs = lt_f_ent->lt_fs; 4376 4377 /* Get the group to which the entry belongs. */ 4378 fg = lt_f_ent->group; 4379 4380 /* Get entry parts count. */ 4381 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 4382 &parts_count)); 4383 4384 for (idx = 0; idx < parts_count; idx++) { 4385 4386 /* Free entry TCAM key buffer if valid. */ 4387 if (NULL != lt_f_ent[idx].tcam.key) { 4388 sal_free(lt_f_ent[idx].tcam.key); 4389 } 4390 4391 /* Free entry TCAM mask buffer if valid. */ 4392 if (NULL != lt_f_ent[idx].tcam.mask) { 4393 sal_free(lt_f_ent[idx].tcam.mask); 4394 } 4395 4396 /* Free entry Data mask buffer if valid. */ 4397 if (NULL != lt_f_ent[idx].tcam.data) { 4398 sal_free(lt_f_ent[idx].tcam.data); 4399 } 4400 4401 /* Get entry part slice number. */ 4402 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_slice_number(idx, 4403 fg->flags, &slice_number)); 4404 4405 /* Remove entry pointer from the slice. */ 4406 lt_fs[slice_number].entries[lt_f_ent[idx].index] = NULL; 4407 4408 /* Increment slice unused entry count. */ 4409 if (0 == (lt_f_ent[idx].flags & _FP_ENTRY_SECOND_HALF)) { 4410 lt_fs[slice_number].free_count++; 4411 } 4412 } 4413 4414 /* Remove the entry from group entry array. */ 4415 rv = _field_th_group_lt_entry_delete(unit, fg, lt_f_ent); 4416 if (BCM_FAILURE(rv)) { 4417 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4418 "FP(unit %d) Error: Group entry delete Eid=%d.\n"), 4419 unit, lt_f_ent->eid)); 4420 } 4421 4422 /* Free entry memory. */ 4423 sal_free(lt_f_ent); 4424 return (rv); 4425 } 4426 4427 /* 4428 * Function: 4429 * _field_th_lt_tcam_data_mem_get 4430 * Purpose: 4431 * Get logical table data memory identifier based on stage group operational 4432 * mode. 4433 * Parameters: 4434 * unit - (IN) BCM device number. 4435 * stage_fc - (IN) Stage field control structure. 4436 * fg - (IN) Field group control structure. 4437 * lt_tcam_mem - (IN) Logical table data view identifier. 4438 * Returns: 4439 * BCM_E_XXX 4440 */ 4441 STATIC int 4442 _field_th_lt_tcam_data_mem_get(int unit, _field_stage_t *stage_fc, 4443 _field_group_t *fg, 4444 soc_mem_t *lt_tcam_mem) 4445 { 4446 /* Input parameters check. */ 4447 if (NULL == lt_tcam_mem) { 4448 return (BCM_E_PARAM); 4449 } 4450 4451 /* 4452 * Assign LT selection TCAM memory identifier based on 4453 * stage's group operational mode. 4454 */ 4455 switch (stage_fc->oper_mode) { 4456 case bcmFieldGroupOperModeGlobal: 4457 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 4458 *lt_tcam_mem = IFP_LOGICAL_TABLE_SELECT_DATA_ONLYm; 4459 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 4460 *lt_tcam_mem = EXACT_MATCH_LOGICAL_TABLE_SELECT_DATA_ONLYm; 4461 } else { 4462 return (BCM_E_INTERNAL); 4463 } 4464 break; 4465 case bcmFieldGroupOperModePipeLocal: 4466 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 4467 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 4468 IFP_LOGICAL_TABLE_SELECT_DATA_ONLYm, 4469 fg->instance, 4470 lt_tcam_mem)); 4471 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 4472 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 4473 EXACT_MATCH_LOGICAL_TABLE_SELECT_DATA_ONLYm, 4474 fg->instance, 4475 lt_tcam_mem)); 4476 } else { 4477 return (BCM_E_INTERNAL); 4478 } 4479 break; 4480 default: 4481 return (BCM_E_INTERNAL); 4482 } 4483 return (BCM_E_NONE); 4484 } 4485 4486 /* 4487 * Function: 4488 * _bcm_field_th_lt_entry_data_value_set 4489 * Purpose: 4490 * Set LT entry DATA portion of an entry. 4491 * Parameters: 4492 * unit - (IN) BCM device number. 4493 * stage_fc - (IN) Stage field control structure. 4494 * fg - (IN) Field group structure. 4495 * index - (IN) Entry part index. 4496 * lt_data_mem - (IN) LT Data Memory. 4497 * data - (IN/OUT) Reference to LT Data to be configured. 4498 * Returns: 4499 * BCM_E_XXX 4500 */ 4501 int 4502 _bcm_field_th_lt_entry_data_value_set(int unit, _field_stage_t *stage_fc, 4503 _field_group_t *fg, int index, 4504 soc_mem_t lt_data_mem, uint32 *data) 4505 { 4506 /* Input parameters check. */ 4507 if ((NULL == stage_fc) || (NULL == fg) || (NULL == data)) { 4508 return (BCM_E_PARAM); 4509 } 4510 4511 /* Presel entry in Flowtracker stage is handled differently */ 4512 #if defined(BCM_FLOWTRACKER_SUPPORT) 4513 if ((soc_feature(unit, soc_feature_field_flowtracker_support)) && 4514 (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 4515 return _bcm_field_hx5_ft_lt_entry_data_value_set(unit, stage_fc, 4516 fg, index, lt_data_mem, data); 4517 } 4518 #endif 4519 4520 /* Group must have a valid KeyGen index, else return error. */ 4521 if (_FP_EXT_SELCODE_DONT_CARE == fg->ext_codes[index].keygen_index) { 4522 return (BCM_E_INTERNAL); 4523 } 4524 4525 /* Check and set keygen index value. */ 4526 soc_mem_field32_set(unit, lt_data_mem, data, 4527 KEY_GEN_PROGRAM_PROFILE_INDEXf, fg->ext_codes[index].keygen_index); 4528 4529 /* Check and set IP Normalize control. */ 4530 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].normalize_l3_l4_sel) { 4531 soc_mem_field32_set(unit, lt_data_mem, data, 4532 NORMALIZE_L3_L4f, fg->ext_codes[index].normalize_l3_l4_sel); 4533 } 4534 4535 /* Check and set MAC Normalize control. */ 4536 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].normalize_mac_sel) { 4537 soc_mem_field32_set(unit, lt_data_mem, data, 4538 NORMALIZE_L2f, fg->ext_codes[index].normalize_mac_sel); 4539 } 4540 4541 /* Check and set AUX TAG A selector value. */ 4542 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].aux_tag_a_sel) { 4543 soc_mem_field32_set(unit, lt_data_mem, data, 4544 AUX_TAG_A_SELf, fg->ext_codes[index].aux_tag_a_sel); 4545 } 4546 4547 /* Check and set AUX TAG B selector value. */ 4548 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].aux_tag_b_sel) { 4549 soc_mem_field32_set(unit, lt_data_mem, data, 4550 AUX_TAG_B_SELf, fg->ext_codes[index].aux_tag_b_sel); 4551 } 4552 4553 /* Check and set AUX TAG C selector value. */ 4554 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].aux_tag_c_sel) { 4555 soc_mem_field32_set(unit, lt_data_mem, data, 4556 AUX_TAG_C_SELf, fg->ext_codes[index].aux_tag_c_sel); 4557 } 4558 4559 /* Check and set AUX TAG D selector value. */ 4560 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].aux_tag_d_sel) { 4561 soc_mem_field32_set(unit, lt_data_mem, data, 4562 AUX_TAG_D_SELf, fg->ext_codes[index].aux_tag_d_sel); 4563 } 4564 4565 /* Check and set TCP function selector. */ 4566 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].tcp_fn_sel) { 4567 soc_mem_field32_set(unit, lt_data_mem, data, 4568 TCP_FN_SELf, fg->ext_codes[index].tcp_fn_sel); 4569 } 4570 4571 /* Check and set TOS function selector. */ 4572 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].tos_fn_sel) { 4573 soc_mem_field32_set(unit, lt_data_mem, data, 4574 TOS_FN_SELf, fg->ext_codes[index].tos_fn_sel); 4575 } 4576 4577 /* Check and set TTL function selector. */ 4578 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].ttl_fn_sel) { 4579 soc_mem_field32_set(unit, lt_data_mem, data, 4580 TTL_FN_SELf, fg->ext_codes[index].ttl_fn_sel); 4581 } 4582 4583 /* Check and set Class ID container A selector. */ 4584 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].class_id_cont_a_sel) { 4585 soc_mem_field32_set(unit, lt_data_mem, data, 4586 CLASS_ID_CONTAINER_A_SELf, 4587 fg->ext_codes[index].class_id_cont_a_sel); 4588 } 4589 4590 /* Check and set Class ID container B selector. */ 4591 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].class_id_cont_b_sel) { 4592 soc_mem_field32_set(unit, lt_data_mem, data, 4593 CLASS_ID_CONTAINER_B_SELf, 4594 fg->ext_codes[index].class_id_cont_b_sel); 4595 } 4596 4597 /* Check and set Class ID container C selector. */ 4598 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].class_id_cont_c_sel) { 4599 soc_mem_field32_set(unit, lt_data_mem, data, 4600 CLASS_ID_CONTAINER_C_SELf, 4601 fg->ext_codes[index].class_id_cont_c_sel); 4602 } 4603 4604 /* Check and set Class ID container D selector. */ 4605 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].class_id_cont_d_sel) { 4606 soc_mem_field32_set(unit, lt_data_mem, data, 4607 CLASS_ID_CONTAINER_D_SELf, 4608 fg->ext_codes[index].class_id_cont_d_sel); 4609 } 4610 4611 /* Check and set Source Container A selector. */ 4612 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].src_cont_a_sel) { 4613 soc_mem_field32_set(unit, lt_data_mem, data, 4614 SRC_CONTAINER_A_SELf, fg->ext_codes[index].src_cont_a_sel); 4615 } 4616 4617 /* Check and set Source Container B selector. */ 4618 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].src_cont_b_sel) { 4619 soc_mem_field32_set(unit, lt_data_mem, data, 4620 SRC_CONTAINER_B_SELf, fg->ext_codes[index].src_cont_b_sel); 4621 } 4622 4623 /* Check and set Src Dest Container 0 selector. */ 4624 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].src_dest_cont_0_sel) { 4625 soc_mem_field32_set(unit, lt_data_mem, data, 4626 SRC_DST_CONTAINER_0_SELf, fg->ext_codes[index].src_dest_cont_0_sel); 4627 } 4628 4629 /* Check and set Src Dest Container 1 selector. */ 4630 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].src_dest_cont_1_sel) { 4631 soc_mem_field32_set(unit, lt_data_mem, data, 4632 SRC_DST_CONTAINER_1_SELf, fg->ext_codes[index].src_dest_cont_1_sel); 4633 } 4634 4635 /* Check and set IPBM selector. */ 4636 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].ipbm_present) { 4637 soc_mem_field32_set(unit, lt_data_mem, data, 4638 IPBM_PRESENTf, fg->ext_codes[index].ipbm_present); 4639 } 4640 4641 /* Check and set IPBM Source. */ 4642 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].ipbm_source) { 4643 soc_mem_field32_set(unit, lt_data_mem, data, 4644 IPBM_SOURCEf, fg->ext_codes[index].ipbm_source); 4645 } 4646 4647 #if defined(BCM_TOMAHAWK3_SUPPORT) 4648 if (SOC_IS_TOMAHAWK3(unit)) { 4649 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].udf_sel) { 4650 soc_mem_field32_set(unit, lt_data_mem, data, 4651 UDF_SELf, fg->ext_codes[index].udf_sel); 4652 } 4653 /* Check and set Destination Container A selector. */ 4654 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].dst_cont_a_sel) { 4655 soc_mem_field32_set(unit, lt_data_mem, data, 4656 DST_CONTAINER_0_SELf, fg->ext_codes[index].dst_cont_a_sel); 4657 } 4658 4659 /* Check and set Destination Container B selector. */ 4660 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].dst_cont_b_sel) { 4661 soc_mem_field32_set(unit, lt_data_mem, data, 4662 DST_CONTAINER_1_SELf, fg->ext_codes[index].dst_cont_b_sel); 4663 } 4664 4665 /* Check and set ALT TTL function selector. */ 4666 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[index].alt_ttl_fn_sel) { 4667 soc_mem_field32_set(unit, lt_data_mem, data, 4668 ALT_TTL_FN_SELf, fg->ext_codes[index].alt_ttl_fn_sel); 4669 } 4670 } 4671 #endif 4672 4673 /* Set Logical Table ID value. */ 4674 if (-1 != fg->lt_id) { 4675 soc_mem_field32_set(unit, lt_data_mem, data, 4676 LOGICAL_TABLE_IDf, (fg->lt_id)); 4677 } 4678 4679 /* Enable lookup for this logical table in the slice. */ 4680 soc_mem_field32_set(unit, lt_data_mem, data, ENABLEf, 4681 (fg->flags & _FP_GROUP_LOOKUP_ENABLED) ? 1 : 0); 4682 4683 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 4684 /* Switch on entry part. */ 4685 switch (index) { 4686 case 0: 4687 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) 4688 || (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 4689 /* Multiwide mode first slice. */ 4690 soc_mem_field32_set(unit, lt_data_mem, data, 4691 MULTIWIDE_MODEf, 1); 4692 } else { 4693 /* Independent slice. */ 4694 soc_mem_field32_set(unit, lt_data_mem, data, 4695 MULTIWIDE_MODEf, 0); 4696 } 4697 break; 4698 case 1: 4699 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 4700 /* Multiwide mode second slice of THREE. */ 4701 soc_mem_field32_set(unit, lt_data_mem, data, 4702 MULTIWIDE_MODEf, 3); 4703 } else { 4704 /* Multiwide mode second slice of TWO. */ 4705 soc_mem_field32_set(unit, lt_data_mem, data, 4706 MULTIWIDE_MODEf, 2); 4707 } 4708 break; 4709 case 2: 4710 /* Multiwide mode third slice. */ 4711 soc_mem_field32_set(unit, lt_data_mem, data, 4712 MULTIWIDE_MODEf, 4); 4713 break; 4714 default: 4715 return (BCM_E_INTERNAL); 4716 } 4717 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 4718 soc_mem_field32_set(unit, lt_data_mem, data, 4719 KEY_TYPEf, fg->em_mode); 4720 } else { 4721 /* Invalid Stage Id */ 4722 return (BCM_E_INTERNAL); 4723 } 4724 4725 return (BCM_E_NONE); 4726 } 4727 4728 /* 4729 * Function: 4730 * _field_th_lt_entry_default_data_value_set 4731 * Purpose: 4732 * Set LT entry DATA portion of an entry. 4733 * Parameters: 4734 * unit - (IN) BCM device number. 4735 * stage_fc - (IN) Stage field control structure. 4736 * fg - (IN) Field group structure. 4737 * index - (IN) Entry part index. 4738 * lt_f_ent - (IN/OUT) Logical table entry structure. 4739 * Returns: 4740 * BCM_E_XXX 4741 */ 4742 STATIC int 4743 _field_th_lt_entry_default_data_value_set(int unit, _field_stage_t *stage_fc, 4744 _field_group_t *fg, int index, 4745 _field_lt_entry_t *lt_f_ent) 4746 { 4747 soc_mem_t lt_tcam_mem; /* LT selection TCAM data view memory name. */ 4748 4749 /* Input parameters check. */ 4750 if ((NULL == stage_fc) || (NULL == fg) || (NULL == lt_f_ent)) { 4751 return (BCM_E_PARAM); 4752 } 4753 4754 /* Group must have a valid KeyGen index, else return error. */ 4755 if (_FP_EXT_SELCODE_DONT_CARE == fg->ext_codes[index].keygen_index) { 4756 return (BCM_E_INTERNAL); 4757 } 4758 4759 /* Get LT select TCAM memory identifier. */ 4760 BCM_IF_ERROR_RETURN(_field_th_lt_tcam_data_mem_get(unit, stage_fc, fg, 4761 <_tcam_mem)); 4762 4763 /* Allocate entry part key, mask & data buffer. */ 4764 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_tcam_entry_get(unit, fg, lt_f_ent)); 4765 4766 /* Configure TCAM data values */ 4767 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_data_value_set(unit, stage_fc, 4768 fg, index, lt_tcam_mem, lt_f_ent->tcam.data)); 4769 4770 return (BCM_E_NONE); 4771 } 4772 4773 /* 4774 * Function: 4775 * _field_th_keygen_profiles_mem_get 4776 * Purpose: 4777 * Get LT keygen program profile memory names. 4778 * Parameters: 4779 * unit - (IN) BCM device number. 4780 * stage_fc - (IN) Stage field control structure. 4781 * fg - (IN) Field group structure. 4782 * mem_arr - (IN/OUT) Pointer to memory name array. 4783 * arr_len - (IN) Memory name array length. 4784 * Returns: 4785 * BCM_E_XXX 4786 */ 4787 STATIC int 4788 _field_th_keygen_profiles_mem_get(int unit, _field_stage_t *stage_fc, 4789 _field_group_t *fg, soc_mem_t *mem_arr, 4790 int arr_len) 4791 { 4792 int idx; /* Array index iterator. */ 4793 static const soc_mem_t ifp_global_mem[2] = 4794 { 4795 IFP_KEY_GEN_PROGRAM_PROFILEm, 4796 IFP_KEY_GEN_PROGRAM_PROFILE2m 4797 }; 4798 static const soc_mem_t em_global_mem[2] = 4799 { 4800 EXACT_MATCH_KEY_GEN_PROGRAM_PROFILEm, 4801 EXACT_MATCH_KEY_GEN_MASKm 4802 }; 4803 4804 4805 /* Input parameters check. */ 4806 if ((NULL == stage_fc) || (NULL == fg) || (NULL == mem_arr)) { 4807 return (BCM_E_PARAM); 4808 } 4809 4810 /* 4811 * Assign keygen memory identifier name based on stage group oper mode. 4812 */ 4813 switch (stage_fc->oper_mode) { 4814 case bcmFieldGroupOperModeGlobal: 4815 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 4816 for (idx = 0; idx < arr_len; idx++) { 4817 mem_arr[idx] = ifp_global_mem[idx]; 4818 } 4819 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 4820 for (idx = 0; idx < arr_len; idx++) { 4821 mem_arr[idx] = em_global_mem[idx]; 4822 } 4823 } else { 4824 return (BCM_E_PARAM); 4825 } 4826 break; 4827 case bcmFieldGroupOperModePipeLocal: 4828 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 4829 for (idx = 0; idx < arr_len; idx++) { 4830 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 4831 ifp_global_mem[idx], 4832 fg->instance, 4833 &mem_arr[idx])); 4834 } 4835 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 4836 for (idx = 0; idx < arr_len; idx++) { 4837 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 4838 em_global_mem[idx], 4839 fg->instance, 4840 &mem_arr[idx])); 4841 } 4842 } else { 4843 return (BCM_E_PARAM); 4844 } 4845 break; 4846 default: 4847 return (BCM_E_INTERNAL); 4848 } 4849 return (BCM_E_NONE); 4850 } 4851 4852 /* 4853 * Function: 4854 * _field_th_keygen_profile2_entry_pack 4855 * Purpose: 4856 * Build a LT keygen program profile2 table entry. 4857 * Parameters: 4858 * unit - (IN) BCM device number. 4859 * stage_fc - (IN) Stage field control structure. 4860 * fg - (IN) Field group structure. 4861 * part - (IN) Entry part number. 4862 * mem - (IN) Memory name identifier. 4863 * prof2_entry - (IN/OUT) Entry buffer pointer. 4864 * Returns: 4865 * BCM_E_XXX 4866 */ 4867 STATIC int 4868 _field_th_keygen_profile2_entry_pack(int unit, _field_stage_t *stage_fc, 4869 _field_group_t *fg, int part, soc_mem_t mem, 4870 ifp_key_gen_program_profile2_entry_t *prof2_entry) 4871 { 4872 int idx; /* Iterator index. */ 4873 static const soc_field_t pmux_sel[] = /* Post mux selectors. */ 4874 { 4875 POST_EXTRACTOR_MUX_0_SELf, 4876 POST_EXTRACTOR_MUX_1_SELf, 4877 POST_EXTRACTOR_MUX_2_SELf, 4878 POST_EXTRACTOR_MUX_3_SELf, 4879 POST_EXTRACTOR_MUX_4_SELf, 4880 POST_EXTRACTOR_MUX_5_SELf, 4881 POST_EXTRACTOR_MUX_6_SELf, 4882 POST_EXTRACTOR_MUX_7_SELf, 4883 POST_EXTRACTOR_MUX_8_SELf, 4884 POST_EXTRACTOR_MUX_9_SELf, 4885 POST_EXTRACTOR_MUX_10_SELf, 4886 POST_EXTRACTOR_MUX_11_SELf, 4887 POST_EXTRACTOR_MUX_12_SELf, 4888 POST_EXTRACTOR_MUX_13_SELf, 4889 POST_EXTRACTOR_MUX_14_SELf 4890 }; 4891 4892 /* Input parameters check. */ 4893 if ((NULL == stage_fc) || (NULL == fg) || (NULL == prof2_entry)) { 4894 return (BCM_E_PARAM); 4895 } 4896 4897 /* Set Post MUX extractor selcode values. */ 4898 for (idx = 0; idx < 15; idx++) { 4899 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].pmux_sel[idx]) { 4900 soc_mem_field32_set(unit, mem, prof2_entry, pmux_sel[idx], 4901 fg->ext_codes[part].pmux_sel[idx]); 4902 } 4903 } 4904 return (BCM_E_NONE); 4905 } 4906 4907 /* 4908 * Function: 4909 * _field_th_keygen_profile1_entry_pack 4910 * Purpose: 4911 * Build a LT keygen program profile1 table entry. 4912 * Parameters: 4913 * unit - (IN) BCM device number. 4914 * stage_fc - (IN) Stage field control structure. 4915 * fg - (IN) Field group structure. 4916 * part - (IN) Entry part number. 4917 * mem - (IN) Memory name identifier. 4918 * prof1_entry - (IN/OUT) Entry buffer pointer. 4919 * Returns: 4920 * BCM_E_XXX 4921 */ 4922 STATIC int 4923 _field_th_keygen_profile1_entry_pack(int unit, _field_stage_t *stage_fc, 4924 _field_group_t *fg, int part, soc_mem_t mem, 4925 ifp_key_gen_program_profile_entry_t *prof1_entry) 4926 { 4927 int idx; /* Iterator index. */ 4928 static const soc_field_t l1_32_sel[] = /* 32 bit extractors. */ 4929 { 4930 L1_E32_SEL_0f, 4931 L1_E32_SEL_1f, 4932 L1_E32_SEL_2f, 4933 L1_E32_SEL_3f 4934 }; 4935 static const soc_field_t l1_16_sel[] = /* 16 bit extractors. */ 4936 { 4937 L1_E16_SEL_0f, 4938 L1_E16_SEL_1f, 4939 L1_E16_SEL_2f, 4940 L1_E16_SEL_3f, 4941 L1_E16_SEL_4f, 4942 L1_E16_SEL_5f, 4943 L1_E16_SEL_6f 4944 }; 4945 static const soc_field_t l1_8_sel[] = /* 8 bit extractors. */ 4946 { 4947 L1_E8_SEL_0f, 4948 L1_E8_SEL_1f, 4949 L1_E8_SEL_2f, 4950 L1_E8_SEL_3f, 4951 L1_E8_SEL_4f, 4952 L1_E8_SEL_5f, 4953 L1_E8_SEL_6f 4954 }; 4955 static const soc_field_t l1_4_sel[] = /* 4 bit extractors. */ 4956 { 4957 L1_E4_SEL_0f, 4958 L1_E4_SEL_1f, 4959 L1_E4_SEL_2f, 4960 L1_E4_SEL_3f, 4961 L1_E4_SEL_4f, 4962 L1_E4_SEL_5f, 4963 L1_E4_SEL_6f, 4964 L1_E4_SEL_7f 4965 }; 4966 static const soc_field_t l1_2_sel[] = /* 2 bit extractors. */ 4967 { 4968 L1_E2_SEL_0f, 4969 L1_E2_SEL_1f, 4970 L1_E2_SEL_2f, 4971 L1_E2_SEL_3f, 4972 L1_E2_SEL_4f, 4973 L1_E2_SEL_5f, 4974 L1_E2_SEL_6f, 4975 L1_E2_SEL_7f 4976 }; 4977 static const soc_field_t l2_16_sel[] = /* 16 bit extractors. */ 4978 { 4979 L2_E16_SEL_0f, 4980 L2_E16_SEL_1f, 4981 L2_E16_SEL_2f, 4982 L2_E16_SEL_3f, 4983 L2_E16_SEL_4f, 4984 L2_E16_SEL_5f, 4985 L2_E16_SEL_6f, 4986 L2_E16_SEL_7f, 4987 L2_E16_SEL_8f, 4988 L2_E16_SEL_9f 4989 }; 4990 static const soc_field_t l3_4_sel[] = /* 4 bit extractors. */ 4991 { 4992 L3_E4_SEL_0f, 4993 L3_E4_SEL_1f, 4994 L3_E4_SEL_2f, 4995 L3_E4_SEL_3f, 4996 L3_E4_SEL_4f, 4997 L3_E4_SEL_5f, 4998 L3_E4_SEL_6f, 4999 L3_E4_SEL_7f, 5000 L3_E4_SEL_8f, 5001 L3_E4_SEL_9f, 5002 L3_E4_SEL_10f, 5003 L3_E4_SEL_11f, 5004 L3_E4_SEL_12f, 5005 L3_E4_SEL_13f, 5006 L3_E4_SEL_14f, 5007 L3_E4_SEL_15f, 5008 L3_E4_SEL_16f, 5009 L3_E4_SEL_17f, 5010 L3_E4_SEL_18f, 5011 L3_E4_SEL_19f, 5012 L3_E4_SEL_20f 5013 }; 5014 static const soc_field_t l3_2_sel[] = /* 2 bit extractors. */ 5015 { 5016 L3_E2_SEL_0f, 5017 L3_E2_SEL_1f, 5018 L3_E2_SEL_2f, 5019 L3_E2_SEL_3f, 5020 L3_E2_SEL_4f 5021 }; 5022 static const soc_field_t l3_1_sel[] = /* 1 bit extractors. */ 5023 { 5024 L3_E1_SEL_0f, 5025 L3_E1_SEL_1f 5026 }; 5027 5028 /* Input parameters check. */ 5029 if ((NULL == stage_fc) || (NULL == fg) || (NULL == prof1_entry)) { 5030 return (BCM_E_PARAM); 5031 } 5032 5033 /* Set 32bit extractor selcode values. */ 5034 for (idx = 0; idx < 4; idx++) { 5035 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e32_sel[idx]) { 5036 soc_mem_field32_set(unit, mem, prof1_entry, l1_32_sel[idx], 5037 fg->ext_codes[part].l1_e32_sel[idx]); 5038 } 5039 } 5040 5041 /* Set 16bit extractor selcode values. */ 5042 for (idx = 0; idx < 7; idx++) { 5043 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e16_sel[idx]) { 5044 soc_mem_field32_set(unit, mem, prof1_entry, l1_16_sel[idx], 5045 fg->ext_codes[part].l1_e16_sel[idx]); 5046 } 5047 } 5048 5049 /* Set 8bit extractor selcode values. */ 5050 for (idx = 0; idx < 7; idx++) { 5051 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e8_sel[idx]) { 5052 soc_mem_field32_set(unit, mem, prof1_entry, l1_8_sel[idx], 5053 fg->ext_codes[part].l1_e8_sel[idx]); 5054 } 5055 } 5056 5057 /* Set 4bit extractor selcode values. */ 5058 for (idx = 0; idx < 8; idx++) { 5059 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e4_sel[idx]) { 5060 soc_mem_field32_set(unit, mem, prof1_entry, l1_4_sel[idx], 5061 fg->ext_codes[part].l1_e4_sel[idx]); 5062 } 5063 } 5064 5065 /* Set 2bit extractor selcode values. */ 5066 for (idx = 0; idx < 8; idx++) { 5067 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e2_sel[idx]) { 5068 soc_mem_field32_set(unit, mem, prof1_entry, l1_2_sel[idx], 5069 fg->ext_codes[part].l1_e2_sel[idx]); 5070 } 5071 } 5072 5073 /* Set 16bit extractor selcode values. */ 5074 for (idx = 0; idx < 10; idx++) { 5075 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l2_e16_sel[idx]) { 5076 soc_mem_field32_set(unit, mem, prof1_entry, l2_16_sel[idx], 5077 fg->ext_codes[part].l2_e16_sel[idx]); 5078 } 5079 } 5080 5081 /* Set 4bit extractor selcode values. */ 5082 for (idx = 0; idx < 21; idx++) { 5083 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l3_e4_sel[idx]) { 5084 soc_mem_field32_set(unit, mem, prof1_entry, l3_4_sel[idx], 5085 fg->ext_codes[part].l3_e4_sel[idx]); 5086 } 5087 } 5088 5089 /* Set 2bit extractor selcode values. */ 5090 for (idx = 0; idx < 5; idx++) { 5091 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l3_e2_sel[idx]) { 5092 soc_mem_field32_set(unit, mem, prof1_entry, l3_2_sel[idx], 5093 fg->ext_codes[part].l3_e2_sel[idx]); 5094 } 5095 } 5096 5097 /* Set 1bit extractor selcode values. */ 5098 for (idx = 0; idx < 2; idx++) { 5099 if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l3_e1_sel[idx]) { 5100 soc_mem_field32_set(unit, mem, prof1_entry, l3_1_sel[idx], 5101 fg->ext_codes[part].l3_e1_sel[idx]); 5102 } 5103 } 5104 5105 return (BCM_E_NONE); 5106 } 5107 5108 /* 5109 * Function: 5110 * _bcm_field_th_group_keygen_profiles_index_alloc 5111 * Purpose: 5112 * Install LT keygen program profile table entries in hardware. 5113 * Parameters: 5114 * unit - (IN) BCM device number. 5115 * stage_fc - (IN) Stage field control structure. 5116 * fg - (IN) Field group structure. 5117 * part_index - (IN) Entry part number. 5118 * Returns: 5119 * BCM_E_XXX 5120 */ 5121 int 5122 _bcm_field_th_group_keygen_profiles_index_alloc(int unit, 5123 _field_stage_t *stage_fc, 5124 _field_group_t *fg, 5125 int part_index) 5126 { 5127 ifp_key_gen_program_profile_entry_t ifp_prof1_entry; 5128 /* IFP Keygen profile1. */ 5129 ifp_key_gen_program_profile2_entry_t ifp_prof2_entry; 5130 /* IFP Keygen profile2. */ 5131 exact_match_key_gen_program_profile_entry_t em_prof_entry; 5132 /* Exact Match Profile. */ 5133 exact_match_key_gen_mask_entry_t em_prof_mask_entry; 5134 /* Exact Match Mask Profile. */ 5135 void *entries[2]; /* Entries array. */ 5136 soc_mem_t mem[2]; /* Keygen profile memory identifier. */ 5137 int rv; /* Operation return status. */ 5138 5139 /* Input parameters check. */ 5140 if ((NULL == stage_fc) || (NULL == fg)) { 5141 return (BCM_E_PARAM); 5142 } 5143 5144 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 5145 /* Get keygen program profiles memory name identifer. */ 5146 BCM_IF_ERROR_RETURN(_field_th_keygen_profiles_mem_get(unit, stage_fc, fg, 5147 mem, COUNTOF(mem))); 5148 5149 /* Clear keygen profile entry. */ 5150 sal_memcpy(&ifp_prof1_entry, soc_mem_entry_null(unit, mem[0]), 5151 soc_mem_entry_words(unit, mem[0]) * sizeof(uint32)); 5152 5153 /* Clear keygen profile2 entry. */ 5154 sal_memcpy(&ifp_prof2_entry, soc_mem_entry_null(unit, mem[1]), 5155 soc_mem_entry_words(unit, mem[1]) * sizeof(uint32)); 5156 5157 #if defined(BCM_TOMAHAWK3_SUPPORT) 5158 if (SOC_IS_TOMAHAWK3(unit)) { 5159 /* Construct keygen profile1 table entry. */ 5160 BCM_IF_ERROR_RETURN( 5161 _bcm_field_th3_keygen_profile1_entry_pack(unit, stage_fc, fg, 5162 part_index, mem[0], &ifp_prof1_entry)); 5163 } else 5164 #endif 5165 { 5166 /* Construct keygen profile1 table entry. */ 5167 BCM_IF_ERROR_RETURN( 5168 _field_th_keygen_profile1_entry_pack(unit, stage_fc, fg, 5169 part_index, mem[0], &ifp_prof1_entry)); 5170 } 5171 5172 /* Construct keygen profile2 table entry. */ 5173 BCM_IF_ERROR_RETURN(_field_th_keygen_profile2_entry_pack(unit, stage_fc, fg, 5174 part_index, mem[1], &ifp_prof2_entry)); 5175 5176 /* Initialize entries array pointers. */ 5177 entries[0] = &ifp_prof1_entry; 5178 entries[1] = &ifp_prof2_entry; 5179 5180 /* Add entries to profile tables in hardware. */ 5181 rv = soc_profile_mem_add(unit, 5182 &stage_fc->keygen_profile[fg->instance].profile, 5183 entries, 1, &fg->ext_codes[part_index].keygen_index); 5184 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 5185 5186 BCM_IF_ERROR_RETURN(_field_th_keygen_profiles_mem_get(unit, stage_fc, fg, 5187 mem, COUNTOF(mem))); 5188 5189 /* Clear keygen profile entry. */ 5190 sal_memcpy(&em_prof_entry, soc_mem_entry_null(unit, mem[0]), 5191 soc_mem_entry_words(unit, mem[0]) * sizeof(uint32)); 5192 5193 sal_memcpy(&em_prof_mask_entry, soc_mem_entry_null(unit, mem[1]), 5194 soc_mem_entry_words(unit, mem[1]) * sizeof(uint32)); 5195 5196 /* Construct keygen profile table entry. */ 5197 #if defined(BCM_TOMAHAWK3_SUPPORT) 5198 if (soc_feature(unit, soc_feature_th3_style_fp)) { 5199 BCM_IF_ERROR_RETURN( 5200 _bcm_field_th3_keygen_em_profile_entry_pack(unit, stage_fc, fg, 5201 part_index, mem[0], 5202 &em_prof_entry)); 5203 } else 5204 #endif 5205 { 5206 BCM_IF_ERROR_RETURN(_field_th_keygen_em_profile_entry_pack(unit, stage_fc, fg, 5207 part_index, mem[0], &em_prof_entry)); 5208 } 5209 5210 /* Construct keygen mask entry */ 5211 BCM_IF_ERROR_RETURN(_field_th_keygen_em_profile_mask_entry_pack(unit, stage_fc, fg, 5212 part_index, mem[1], &em_prof_mask_entry)); 5213 5214 /* Initialize entries array pointers. */ 5215 entries[0] = &em_prof_entry; 5216 entries[1] = &em_prof_mask_entry; 5217 5218 /* Add entries to profile tables in hardware. */ 5219 rv = soc_profile_mem_add(unit, 5220 &stage_fc->keygen_profile[fg->instance].profile, 5221 entries, 1, &fg->ext_codes[part_index].keygen_index); 5222 #if defined(BCM_FLOWTRACKER_SUPPORT) 5223 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 5224 /* KeyGen is set along with lts install */ 5225 rv = BCM_E_NONE; 5226 #endif 5227 } else { 5228 /* Invalid Stage */ 5229 rv = BCM_E_PARAM; 5230 } 5231 5232 return (rv); 5233 } 5234 5235 /* 5236 * Function: 5237 * _field_th_lt_entry_default_rule_init 5238 * Purpose: 5239 * Create a default rule for the group in logical table selection TCAM with 5240 * appropriate key, mask and data values. 5241 * Parameters: 5242 * unit - (IN) BCM device number. 5243 * stage_fc - (IN) Stage field control structure. 5244 * lt_f_ent - (IN/OUT) Logical table entry structure. 5245 * Returns: 5246 * BCM_E_XXX 5247 */ 5248 STATIC int 5249 _field_th_lt_entry_default_rule_init(int unit, _field_stage_t *stage_fc, 5250 _field_lt_entry_t *lt_f_ent) 5251 { 5252 _field_group_t *fg; /* Field group structure. */ 5253 int parts_count = -1; /* Number of field entry parts. */ 5254 int idx; /* Entry parts iterator. */ 5255 5256 /* Input parameters check. */ 5257 if ((NULL == stage_fc) || (NULL == lt_f_ent)) { 5258 return (BCM_E_PARAM); 5259 } 5260 5261 /* Get entry's group structure. */ 5262 fg = lt_f_ent->group; 5263 5264 /* Get number of entry parts using group flags. */ 5265 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 5266 &parts_count)); 5267 5268 /* Install entry parts in hardware. */ 5269 for (idx = 0; idx < parts_count; idx++) { 5270 /* 5271 * Install keygen program profile table entries for the group in 5272 * hardware. 5273 */ 5274 BCM_IF_ERROR_RETURN(_bcm_field_th_group_keygen_profiles_index_alloc( 5275 unit, stage_fc, fg, idx)); 5276 /* 5277 * Build LT selection TCAM default entry. 5278 */ 5279 BCM_IF_ERROR_RETURN(_field_th_lt_entry_default_data_value_set(unit, 5280 stage_fc, fg, idx, lt_f_ent + idx)); 5281 } 5282 return (BCM_E_NONE); 5283 } 5284 5285 /* 5286 * Function: 5287 * _field_th_lt_default_tcam_entry_install 5288 * Purpose: 5289 * Install a logical table entry in hardware. 5290 * Parameters: 5291 * unit - (IN) BCM device number. 5292 * lt_entry - (IN) Field logical table entry. 5293 * group_expand - (IN) Indicates whether the LT tcam install 5294 * is for auto-expanded slices. 5295 * part_idx - (IN) Slice part, valid only if group_expand is 1. 5296 * lt_fs - (IN) Reference to LT slice, valid only if group_expand is 1. 5297 * Returns: 5298 * BCM_E_XXX 5299 */ 5300 STATIC int 5301 _field_th_lt_default_tcam_entry_install(int unit, bcm_field_entry_t lt_entry, 5302 int group_expand, int part_idx, 5303 _field_lt_slice_t *lt_fs) 5304 { 5305 _field_stage_t *stage_fc; /* Stage Field Control structure. */ 5306 int tcam_idx[_FP_MAX_ENTRY_WIDTH]; /* Entry TCAM index. */ 5307 int parts_count = 0; /* Field entry parts count. */ 5308 _field_lt_entry_t *lt_f_ent; /* Field LT entry pointer. */ 5309 _field_lt_slice_t *lt_part_fs = NULL; /* Field LT entry pointer. */ 5310 _field_control_t *fc; /* Field control pointer. */ 5311 int idx; /* Index iterator. */ 5312 int rv = BCM_E_NONE; /* Operation return status. */ 5313 soc_mem_t lt_tcam_mem; /* TCAM memory ID. */ 5314 uint8 valid; /* Entry Valid bit. */ 5315 5316 /* Get device field control structure. */ 5317 BCM_IF_ERROR_RETURN(_field_control_get(unit , &fc)); 5318 5319 /* Get all part of the entry. */ 5320 BCM_IF_ERROR_RETURN 5321 (_field_th_lt_entry_get_by_id(unit, lt_entry, <_f_ent)); 5322 5323 /* Get device stage control structure. */ 5324 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 5325 lt_f_ent->group->stage_id, &stage_fc)); 5326 5327 /* Get number of entry parts. */ 5328 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, 5329 lt_f_ent->group->flags, &parts_count)); 5330 5331 for (idx = 0; idx < parts_count; idx++) { 5332 if (group_expand == 1) { 5333 if (part_idx != idx) { 5334 continue; 5335 } 5336 lt_part_fs = lt_fs; 5337 } else { 5338 lt_part_fs = (lt_f_ent + idx)->lt_fs; 5339 } 5340 5341 BCM_IF_ERROR_RETURN(_field_th_lt_entry_tcam_idx_get(unit, 5342 lt_f_ent + idx, lt_part_fs, tcam_idx + idx)); 5343 } 5344 5345 if (lt_part_fs == NULL) { 5346 return BCM_E_INTERNAL; 5347 } 5348 5349 /* 5350 * Get TCAM view to be used for programming the hardware based on the group 5351 * operational mode. 5352 */ 5353 BCM_IF_ERROR_RETURN(_field_th_lt_tcam_mem_get(unit, stage_fc, lt_f_ent, 5354 <_tcam_mem)); 5355 5356 #if defined(BCM_TOMAHAWK2_SUPPORT) 5357 if (soc_feature(unit, soc_feature_field_multi_pipe_enhanced) && 5358 _BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 5359 valid = (lt_f_ent->group->flags & _FP_GROUP_LOOKUP_ENABLED) ? 3 : 0; 5360 } else 5361 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5362 { 5363 valid = (lt_f_ent->group->flags & _FP_GROUP_LOOKUP_ENABLED) ? 5364 (soc_feature(unit, soc_feature_td3_style_fp) ? 3 : 1) : 0; 5365 } 5366 5367 /* Install all parts of the entry in hardware. */ 5368 for (idx = 0; idx < parts_count; idx++) { 5369 /* In case of group expand, iterate for the given part. */ 5370 if ((group_expand == 1) && (part_idx != idx)) { 5371 continue; 5372 } 5373 /* 5374 * Maximum index value for entry in this TCAM is limited to 5375 * No. of slices * No. of LT_IDs/slice (12 * 32 == 384). 5376 */ 5377 if ((tcam_idx[idx] < soc_mem_index_min(unit, lt_tcam_mem)) || 5378 (tcam_idx[idx] > (stage_fc->lt_tcam_sz - 1) )) { 5379 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 5380 "Error: tcam_idx[%d]:%d is out of range.\n\r"), idx, tcam_idx[idx])); 5381 return (BCM_E_INTERNAL); 5382 } 5383 5384 5385 rv = _bcm_field_th_lt_entry_hw_install(unit, lt_tcam_mem, tcam_idx[idx], 5386 (lt_f_ent + idx)->tcam.key, 5387 (lt_f_ent + idx)->tcam.mask, 5388 (lt_f_ent + idx)->tcam.data, 5389 valid); 5390 if (BCM_FAILURE(rv)) { 5391 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 5392 "Error: LT entry HW Install failed[%d] tcam_idx[%d]:%d.\n\r"), 5393 rv, idx, tcam_idx[idx])); 5394 return (BCM_E_INTERNAL); 5395 } 5396 lt_f_ent[idx].flags &= ~_FP_ENTRY_DIRTY; 5397 lt_f_ent[idx].flags |= _FP_ENTRY_INSTALLED; 5398 lt_f_ent[idx].flags |= _FP_ENTRY_ENABLED; 5399 } 5400 5401 return (rv); 5402 } 5403 5404 /* 5405 * Function: 5406 * _field_th_lt_default_entry_create 5407 * Purpose: 5408 * Create an entry in the slice/s reserved in logical table selection TCAM 5409 * for the field group. 5410 * Parameters: 5411 * unit - (IN) BCM device number. 5412 * stage_fc - (IN) Stage field control structure. 5413 * fg - (IN) Field group structure. 5414 * lt_fs - (IN) Field logical table slice structure. 5415 * lt_entry - (OUT) Logical Table field entry identifier. 5416 * Returns: 5417 * BCM_E_XXX 5418 */ 5419 STATIC int 5420 _field_th_lt_default_entry_create(int unit, _field_stage_t *stage_fc, 5421 _field_group_t *fg, _field_lt_slice_t *lt_fs, 5422 bcm_field_entry_t *lt_entry) 5423 { 5424 _field_control_t *fc; /* Field control structure. */ 5425 _field_lt_entry_t *lt_f_ent; /* LT field entry pointer. */ 5426 int rv; /* Operation return status. */ 5427 5428 /* Input parameter check. */ 5429 if ((NULL == lt_entry) || (NULL == stage_fc) || (NULL == fg) 5430 || (NULL == lt_fs)) { 5431 return (BCM_E_PARAM); 5432 } 5433 5434 /* Get device field control handle. */ 5435 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5436 5437 /* Generate an LT entry ID. */ 5438 fc->last_allocated_lt_eid++; 5439 while (BCM_SUCCESS(_field_th_lt_entry_get(unit, fc->last_allocated_lt_eid, 5440 _FP_ENTRY_PRIMARY, <_f_ent))) { 5441 fc->last_allocated_lt_eid++; 5442 if (_FP_ID_MAX == fc->last_allocated_lt_eid) { 5443 /* Initialize base LT Entry ID*/ 5444 fc->last_allocated_lt_eid = _FP_ID_BASE; 5445 } 5446 } 5447 5448 /* Update allocated entry ID to the caller. */ 5449 *lt_entry = fc->last_allocated_lt_eid; 5450 5451 /* Create entry in primary slice. */ 5452 rv = _field_th_lt_default_entry_phys_create(unit, stage_fc, *lt_entry, 5453 BCM_FIELD_ENTRY_PRIO_LOWEST, lt_fs, fg, <_f_ent); 5454 if (BCM_FAILURE(rv)) { 5455 return (rv); 5456 } 5457 5458 /* Set up default LT selection rule based on group's keygen codes. */ 5459 rv = _field_th_lt_entry_default_rule_init(unit, stage_fc, lt_f_ent); 5460 if (BCM_FAILURE(rv)) { 5461 /* Destroy resources allocated for the entry. */ 5462 _field_th_lt_default_entry_phys_destroy(unit, lt_f_ent); 5463 return (rv); 5464 } 5465 return (rv); 5466 } 5467 5468 /* 5469 * Function: 5470 * _field_th_ingress_selcodes_install 5471 * Purpose: 5472 * Install Logical table selection rule and TCAM key generation rules in 5473 * hardware. 5474 * Parameters: 5475 * unit - (IN) BCM device number. 5476 * stage_fc - (IN) Stage field control structure. 5477 * fg - (IN) Field group structure. 5478 * lt_fs - (IN) Field logical table slice structure. 5479 * Returns: 5480 * BCM_E_XXX 5481 */ 5482 STATIC int 5483 _field_th_ingress_selcodes_install(int unit, 5484 _field_stage_t *stage_fc, 5485 _field_group_t *fg, 5486 _field_lt_slice_t *lt_fs, 5487 int lt_pri_part_prio) 5488 { 5489 int rv; /* Operation return status. */ 5490 int idx; /* iteration index. */ 5491 _field_control_t *fc; /* Field Control Structure. */ 5492 int lt_part_prio = 0; 5493 5494 /* Input parameters check. */ 5495 if ((NULL == fg) || (NULL == stage_fc) || (NULL == lt_fs)) { 5496 return (BCM_E_PARAM); 5497 } 5498 5499 /* Field control get. */ 5500 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5501 5502 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 5503 _field_presel_entry_t *f_presel; 5504 5505 /* 5506 * Create Presel Entries in the LT slice associated with the group 5507 */ 5508 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 5509 if (fg->presel_ent_arr[idx] != NULL) { 5510 f_presel = fg->presel_ent_arr[idx]; 5511 } else { 5512 continue; 5513 } 5514 5515 /* Allocate the presel entries in the LT slice for this group. */ 5516 rv = _bcm_field_th_lt_entry_config_set(unit, stage_fc, fg, lt_fs, 5517 f_presel); 5518 BCM_IF_ERROR_RETURN(rv); 5519 5520 /* Install the LT Entry in HW. */ 5521 rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel); 5522 BCM_IF_ERROR_RETURN(rv); 5523 5524 /* Check if the group is expanded across slices. */ 5525 if (f_presel->lt_fs->next != NULL) { 5526 _field_lt_slice_t *lt_part_fs; 5527 _field_presel_entry_t *f_presel_p; 5528 int p, parts_count = -1; 5529 5530 /* Get number of entry parts. */ 5531 rv = _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 5532 &parts_count); 5533 BCM_IF_ERROR_RETURN(rv); 5534 5535 f_presel_p = f_presel; 5536 for (p = 0; (p < parts_count && f_presel_p != NULL); p++) { 5537 lt_part_fs = f_presel_p->lt_fs->next; 5538 lt_part_prio = lt_pri_part_prio; 5539 for (;lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) { 5540 /* LT part prio update */ 5541 lt_part_prio -= 1; 5542 rv = _field_th_ingress_group_expand_slice_install(unit, stage_fc, 5543 fg, lt_part_fs->slice_number, p, lt_part_prio); 5544 BCM_IF_ERROR_RETURN(rv); 5545 } 5546 } 5547 } 5548 } 5549 } else { 5550 bcm_field_entry_t lt_entry; /* LT entry ID. */ 5551 5552 /* Create a default LT entry for this group. */ 5553 BCM_IF_ERROR_RETURN(_field_th_lt_default_entry_create(unit, stage_fc, fg, 5554 lt_fs, <_entry)); 5555 /* Store LT Entry ID in group LT information structure. */ 5556 fc->lt_info[fg->instance][fg->lt_id]->lt_entry = lt_entry; 5557 5558 /* Install the LT entry in hardware. */ 5559 BCM_IF_ERROR_RETURN(_field_th_lt_default_entry_install(unit, lt_entry)); 5560 } 5561 5562 return (BCM_E_NONE); 5563 } 5564 5565 /* 5566 * Function: 5567 * _field_ltmap_unused_resource_get 5568 * Purpose: 5569 * Get unused LT IDs and LT action priorities information. 5570 * Parameters: 5571 * unit - (IN) BCM device number. 5572 * stage_fc - (IN) Field stage control structure. 5573 * ltmap - (IN) Logical table configuration structure. 5574 * unused_ltids - (OUT) Unused Logical Table IDs. 5575 * Returns: 5576 * BCM_E_XXX 5577 */ 5578 STATIC int 5579 _field_ltmap_unused_resource_get(int unit, 5580 _field_stage_t *stage_fc, 5581 _field_group_t *fg, 5582 uint32 *unused_ltids) 5583 { 5584 int lt_idx; /* Logical table iterator. */ 5585 uint32 used_ltids = 0; /* Used Logical Table IDs. */ 5586 _field_control_t *fc; /* Field Control Strucutre.*/ 5587 uint32 supported_ltids = 0; /* Supported Logical Table IDs. */ 5588 5589 /* Input parameters check. */ 5590 if ((NULL == fg) || (NULL == stage_fc) || (NULL == unused_ltids)) { 5591 return (BCM_E_PARAM); 5592 } 5593 5594 #if defined(BCM_FLOWTRACKER_SUPPORT) 5595 if (_BCM_FIELD_STAGE_FLOWTRACKER == stage_fc->stage_id) { 5596 return BCM_E_NONE; 5597 } 5598 #endif 5599 5600 /* Get field control information. */ 5601 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5602 5603 /* Based on stage oper mode, derive used ltid */ 5604 5605 /* Iterate over all supported LT IDs. */ 5606 for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) { 5607 /* Skip unused LT IDs. */ 5608 if (FALSE == fc->lt_info[fg->instance][lt_idx]->valid) { 5609 continue; 5610 } 5611 /* Update bit value in the used bitmaps. */ 5612 used_ltids |= (1 << lt_idx); 5613 } 5614 5615 /* Unused caller requested information. */ 5616 *unused_ltids = ~(used_ltids); 5617 5618 /* Validate with supported LTIDs */ 5619 SHR_BITSET_RANGE(&supported_ltids, 0, stage_fc->num_logical_tables); 5620 *unused_ltids = ((*unused_ltids) & (supported_ltids)); 5621 5622 5623 return (BCM_E_NONE); 5624 } 5625 5626 /* 5627 * Function: 5628 * _field_th_ltid_alloc 5629 * Purpose: 5630 * Allocate a logical table identifier from unused logical table ID pool. 5631 * Parameters: 5632 * unit - (IN) BCM device number. 5633 * max_ltid - (IN) Logical Table ID maximum value possible. 5634 * lt_unused_bmap - (IN) Unused Logical Table IDs. 5635 * lt_id - (OUT) Logical Table Identifier. 5636 * Returns: 5637 * BCM_E_XXX 5638 */ 5639 STATIC int 5640 _field_th_ltid_alloc(int unit, int max_ltid, uint32 *lt_unused_bmap, int *lt_id) 5641 { 5642 int lt_idx; /* Logical table iterator. */ 5643 5644 /* Input parameters check. */ 5645 if (NULL == lt_unused_bmap || NULL == lt_id) { 5646 return (BCM_E_PARAM); 5647 } 5648 5649 /* If all LT_IDs have been assigned, return resource error. */ 5650 if (0 == *lt_unused_bmap) { 5651 return (BCM_E_RESOURCE); 5652 } 5653 5654 /* Iterate over unused LT_IDs bit array. */ 5655 for (lt_idx = 0; lt_idx < max_ltid; lt_idx++) { 5656 if (*lt_unused_bmap & (1 << lt_idx)) { 5657 break; 5658 } 5659 } 5660 5661 /* Mark selected LT_ID as used. */ 5662 *lt_unused_bmap &= ~(1 << lt_idx); 5663 5664 /* Update LT_ID value in caller argument. */ 5665 *lt_id = lt_idx; 5666 return (BCM_E_NONE); 5667 } 5668 5669 /* 5670 * Function: 5671 * _field_th_lt_prio_cmp 5672 * Purpose: 5673 * Compare two group priorities linked to logical tables. 5674 * Parameters: 5675 * a - (IN) First logical table group priority. 5676 * b - (IN) Second logical table group priority. 5677 * Returns: 5678 * -1 if prio_first < prio_second 5679 * 0 if prio_first == prio_second 5680 * 1 if prio_first > prio_second 5681 */ 5682 STATIC int 5683 _field_th_lt_prio_cmp(void *a, void *b) 5684 { 5685 _field_lt_config_t *first; /* First Logical table configuration. */ 5686 _field_lt_config_t *second; /* Second Logical table configuration. */ 5687 5688 first = (_field_lt_config_t *)a; 5689 second = (_field_lt_config_t *)b; 5690 5691 if (first->priority < second->priority) { 5692 return (-1); 5693 } else if (first->priority > second->priority) { 5694 return (1); 5695 } 5696 5697 return (0); 5698 } 5699 5700 /* 5701 * Function: 5702 * _field_th_lt_priority_alloc 5703 * Purpose: 5704 * Allocate logical table action priority for the group. 5705 * Parameters: 5706 * unit - (IN) BCM device number. 5707 * stage_fc - (IN/OUT) Stage field control structure. 5708 * fg - (IN) State machine tracking structure. 5709 * lt_id - (IN) Logical Table Identifier. 5710 * Returns: 5711 * BCM_E_XXX 5712 */ 5713 STATIC int 5714 _field_th_lt_priority_alloc(int unit, _field_stage_t *stage_fc, 5715 _field_group_t *fg, int lt_id) 5716 { 5717 int lt_idx; /* Logical table iterator. */ 5718 _field_lt_config_t *lt_info = NULL; /* LT information. */ 5719 int action_prio; /* LT action priority value. */ 5720 int idx; /* Iterator. */ 5721 _field_control_t *fc; /* Field Control Strucutre. */ 5722 5723 /* Input parameters check. */ 5724 if (NULL == stage_fc || NULL == fg) { 5725 return (BCM_E_PARAM); 5726 } 5727 5728 action_prio = stage_fc->num_logical_tables - 1; 5729 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5730 5731 _FP_XGS3_ALLOC(lt_info, 5732 (stage_fc->num_logical_tables * sizeof(_field_lt_config_t)), 5733 "lt info for all lt ids"); 5734 if (lt_info == NULL) { 5735 return (BCM_E_MEMORY); 5736 } 5737 /* Get LT information for the group. */ 5738 for (idx = 0; idx < stage_fc->num_logical_tables; idx++) { 5739 sal_memcpy(<_info[idx], fc->lt_info[fg->instance][idx], 5740 sizeof(_field_lt_config_t)); 5741 } 5742 5743 /* 5744 * Initialize LT information for the new logical table ID, for it to be 5745 * in the correct location after the sort. 5746 */ 5747 lt_info[lt_id].priority = fg->priority; 5748 lt_info[lt_id].lt_action_pri = 0; 5749 lt_info[lt_id].valid = TRUE; 5750 5751 for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) { 5752 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 5753 "FP(unit %d): Verb-B4-Sort: lt_id(%d): lt_grp_prio(%d): " 5754 "lt_actn_prio(%d): valid:(%d) flags(0x%x)\n"), 5755 unit, lt_info[lt_idx].lt_id, 5756 lt_info[lt_idx].priority, lt_info[lt_idx].lt_action_pri, 5757 lt_info[lt_idx].valid, lt_info[lt_idx].flags)); 5758 } 5759 5760 /* Sort the logical tables array based on group priority value. */ 5761 _shr_sort(lt_info, stage_fc->num_logical_tables, 5762 sizeof(_field_lt_config_t), 5763 _field_th_lt_prio_cmp); 5764 5765 for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) { 5766 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 5767 "FP(unit %d): Verb-Aft-Sort: lt_id(%d): lt_grp_prio(%d): " 5768 "lt_actn_prio(%d): valid:(%d) flags(0x%x)\n"), 5769 unit, lt_info[lt_idx].lt_id, lt_info[lt_idx].priority, 5770 lt_info[lt_idx].lt_action_pri, lt_info[lt_idx].valid, 5771 lt_info[lt_idx].flags)); 5772 } 5773 5774 /* 5775 * Assign LT action priority based on the position of LT ID in the sorted 5776 * array. 5777 */ 5778 for (idx = (stage_fc->num_logical_tables - 1); idx >= 0; idx--) { 5779 if (FALSE == lt_info[idx].valid) { 5780 continue; 5781 } 5782 lt_info[idx].lt_action_pri = action_prio--; 5783 } 5784 5785 for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) { 5786 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 5787 "FP(unit %d): Verb-Aft-PrioAssign: lt_id(%d): lt_grp_prio(%d): " 5788 "lt_actn_prio(%d): valid:(%d) flags(0x%x)\n"), 5789 unit, lt_info[lt_idx].lt_id, lt_info[lt_idx].priority, 5790 lt_info[lt_idx].lt_action_pri, lt_info[lt_idx].valid, 5791 lt_info[lt_idx].flags)); 5792 } 5793 5794 for (idx = 0; idx < stage_fc->num_logical_tables; idx++) { 5795 if (FALSE == lt_info[idx].valid) { 5796 continue; 5797 } 5798 lt_idx = lt_info[idx].lt_id; 5799 fc->lt_info[fg->instance][lt_idx]->lt_action_pri = 5800 lt_info[idx].lt_action_pri; 5801 } 5802 5803 sal_free(lt_info); 5804 return (BCM_E_NONE); 5805 } 5806 5807 /* 5808 * Function: 5809 * _field_th_group_ltmap_alloc 5810 * Purpose: 5811 * Allocate a Logitcal Table ID for the field group. 5812 * Parameters: 5813 * unit - (IN) BCM device number. 5814 * stage_fc - (IN/OUT) Stage field control structure. 5815 * fg - (IN/OUT) Field group structure pointer. 5816 * Returns: 5817 * BCM_E_XXX 5818 */ 5819 STATIC int 5820 _field_th_group_ltmap_alloc(int unit, _field_stage_t *stage_fc, 5821 _field_group_t *fg) 5822 { 5823 uint32 unused_ltids = 0; /* Unused LT IDs. */ 5824 int lt_id; /* Logical Table Identifier. */ 5825 _field_control_t *fc; /* Field Control Strucutre. */ 5826 5827 /* Input parameters check. */ 5828 if (NULL == stage_fc || NULL == fg) { 5829 return (BCM_E_PARAM); 5830 } 5831 5832 #if defined(BCM_FLOWTRACKER_SUPPORT) 5833 if (_BCM_FIELD_STAGE_FLOWTRACKER == stage_fc->stage_id) { 5834 return BCM_E_NONE; 5835 } 5836 #endif 5837 5838 /* Get field control information. */ 5839 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5840 5841 /* Get unused LT IDs and LT action priorites. */ 5842 BCM_IF_ERROR_RETURN(_field_ltmap_unused_resource_get(unit, stage_fc, 5843 fg, &unused_ltids)); 5844 /* Allocate a LT ID from unused LT ID pool. */ 5845 BCM_IF_ERROR_RETURN(_field_th_ltid_alloc(unit, stage_fc->num_logical_tables, 5846 &unused_ltids, <_id)); 5847 5848 /* Allocate LT action priority. */ 5849 BCM_IF_ERROR_RETURN(_field_th_lt_priority_alloc(unit, stage_fc, fg, lt_id)); 5850 5851 /* Set LT ID info in database. */ 5852 fc->lt_info[fg->instance][lt_id]->valid = TRUE; 5853 fc->lt_info[fg->instance][lt_id]->priority = fg->priority; 5854 fc->lt_info[fg->instance][lt_id]->flags = fg->flags; 5855 5856 /* Get group's LT info structure pointer. */ 5857 fg->lt_id = lt_id; 5858 5859 return (BCM_E_NONE); 5860 } 5861 5862 /* 5863 * Function: 5864 * _field_th_ingress_group_install 5865 * Purpose: 5866 * Auxiliary routine used to install field group in hardware. 5867 * Parameters: 5868 * unit - (IN) BCM device number. 5869 * stage_fc - (IN) Installed group structure. 5870 * fg - (IN/OUT) Field group structure. 5871 * Returns: 5872 * BCM_E_XXX 5873 */ 5874 STATIC int 5875 _field_th_ingress_group_install(int unit, _field_stage_t *stage_fc, 5876 _field_group_t *fg) 5877 { 5878 _field_lt_slice_t *lt_fs; /* LT Slice pointer. */ 5879 _field_slice_t *fs; /* Field slice structure pointer. */ 5880 int parts_count = -1; /* Number of entry parts. */ 5881 int part; /* Entry parts iterator. */ 5882 uint8 slice_number; /* LT Slice number. */ 5883 _field_control_t *fc; /* Field control structure. */ 5884 int lt_part_prio = _FP_MAX_LT_PART_PRIO(unit); 5885 /* LT part priority value. */ 5886 5887 /* Input parameters check. */ 5888 if ((NULL == stage_fc) || (NULL == fg) || (NULL == fg->lt_slices)) { 5889 return (BCM_E_PARAM); 5890 } 5891 5892 /* Get field control structure. */ 5893 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5894 5895 /* Allocate a Logical Table ID for the group. */ 5896 BCM_IF_ERROR_RETURN(_field_th_group_ltmap_alloc(unit, stage_fc, fg)); 5897 5898 #if defined(BCM_FLOWTRACKER_SUPPORT) 5899 /* Assign Group Key Type for the group */ 5900 BCM_IF_ERROR_RETURN(_field_hx5_ft_group_keytype_assign(unit, stage_fc, fg)); 5901 #endif 5902 5903 /* Get number of entry parts. */ 5904 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 5905 stage_fc->stage_id, fg->flags, &parts_count)); 5906 5907 /* Iterate over entry parts and program hardware for each slice. */ 5908 for (part = 0; part < parts_count; part++) { 5909 /* Get slice number to which the entry part belongs to. */ 5910 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_slice_number(part, 5911 fg->flags, &slice_number)); 5912 5913 /* Get LT entry part slice control structure. */ 5914 lt_fs = stage_fc->lt_slices[fg->instance] + 5915 fg->slices->slice_number + slice_number; 5916 5917 if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 5918 break; 5919 } 5920 5921 /* Set slice mode in hardware based on Group mode/flags. */ 5922 BCM_IF_ERROR_RETURN(_field_th_ingress_slice_mode_set(unit, stage_fc, 5923 lt_fs->slice_number, fg, 0)); 5924 /* 5925 * Initialize slice free entries count value to number of 5926 * entries in the slice. 5927 */ 5928 if (0 == fg->slices[0].lt_map) { 5929 lt_fs->free_count = lt_fs->entry_count; 5930 } 5931 5932 /* Get IFP TCAM slice information. */ 5933 fs = fg->slices + part; 5934 5935 /* Update slice LT_ID mapping in group's slice. */ 5936 fs->lt_map |= (1 << fg->lt_id); 5937 5938 fc->lt_info[fg->instance][fg->lt_id]->lt_part_map |= (1 << fs->slice_number); 5939 fc->lt_info[fg->instance][fg->lt_id]->lt_part_pri[fs->slice_number] = lt_part_prio; 5940 } 5941 5942 /* Install TCAM keygen program configuration in hardware for each slice. */ 5943 BCM_IF_ERROR_RETURN(_field_th_ingress_selcodes_install(unit, stage_fc, fg, 5944 fg->lt_slices, lt_part_prio)); 5945 5946 return (BCM_E_NONE); 5947 } 5948 5949 /* 5950 * Function: 5951 * _field_th_group_add_group_install 5952 * Purpose: 5953 * Install group slice mode in hardware and update slice parameters based on 5954 * the group mode. 5955 * Parameters: 5956 * unit - (IN) BCM device number. 5957 * fsm_ptr - (IN/OUT) State machine tracking structure. 5958 * Returns: 5959 * BCM_E_XXX 5960 */ 5961 STATIC int 5962 _field_th_group_add_group_install(int unit, 5963 _field_group_add_fsm_t *fsm_ptr) 5964 { 5965 _field_slice_t *fs; /* Slice pointer. */ 5966 _field_group_t *fg; /* Field Group Pointer. */ 5967 int parts_count = -1; /* Number of entry parts. */ 5968 int idx; /* Slice iterator. */ 5969 uint32 entry_flags; /* Entry flags. */ 5970 uint8 slice_number; /* Slice number. */ 5971 int slice_init; /* Slice SW init needed. */ 5972 5973 /* Input parameters check. */ 5974 if (NULL == fsm_ptr) { 5975 return (BCM_E_PARAM); 5976 } 5977 5978 /* Get field group pointer. */ 5979 fg = fsm_ptr->fg; 5980 5981 /* Check if this is the first group installed in slice. */ 5982 slice_init = (0 == fg->slices[0].lt_map) ? TRUE : FALSE; 5983 5984 /* Write group parameters to hardware. */ 5985 BCM_IF_ERROR_RETURN(_field_th_ingress_group_install(unit, 5986 fsm_ptr->stage_fc, fg)); 5987 5988 /* Get number of entry parts. */ 5989 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 5990 fsm_ptr->stage_fc->stage_id, fg->flags, &parts_count)); 5991 5992 for (idx = parts_count - 1; idx >=0; idx--) { 5993 /* Get entry flags. */ 5994 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_entry_flags(unit, idx, 5995 fg->flags, &entry_flags)); 5996 5997 /* Get slice number for given entry part. */ 5998 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_slice_number(idx, 5999 fg->flags, &slice_number)); 6000 6001 /* Get slice pointer. */ 6002 fs = fg->slices + slice_number; 6003 6004 if (!(entry_flags & _FP_ENTRY_SECOND_HALF)) { 6005 if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) { 6006 if (slice_init) { 6007 /* 6008 * Initialize slice free entries count value based on group 6009 * flags. 6010 */ 6011 #if defined(BCM_TOMAHAWK3_SUPPORT) 6012 if (SOC_IS_TOMAHAWK3(unit) && 6013 (fg->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 6014 fs->free_count = fs->entry_count; 6015 } else 6016 #endif 6017 { 6018 6019 if ((fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) 6020 && !(fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 6021 fs->free_count = fs->entry_count; 6022 } else { 6023 fs->entry_count >>= 1; 6024 fs->free_count = fs->entry_count; 6025 fs->start_tcam_idx >>= 1; 6026 } 6027 } 6028 /* Initialize slice group flags. */ 6029 fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK; 6030 } 6031 } else { 6032 fs->group_flags |= fg->flags & _FP_GROUP_STATUS_MASK; 6033 } 6034 } 6035 } 6036 6037 return (BCM_E_NONE); 6038 } 6039 6040 /* Function: 6041 * _bcm_field_th_group_add_mode_validate 6042 * 6043 * Purpose: 6044 * validate the group to make sure the group with same priority and mode 6045 * doesnot exist in other slices 6046 * 6047 * Paramaters: 6048 * unit - (IN) BCM device number 6049 * fg - (IN) Pointer to device field group structure 6050 * 6051 * Returns: 6052 * BCM_E_XXX 6053 */ 6054 6055 int 6056 _bcm_field_th_group_add_mode_validate(int unit, 6057 _field_group_t *fg, 6058 int *slice_number) 6059 { 6060 _field_control_t *fc; 6061 _field_group_t *curr_group; 6062 6063 if (fg == NULL) { 6064 return BCM_E_PARAM; 6065 } 6066 /* Get device Field control structure. */ 6067 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 6068 curr_group = fc->groups; 6069 6070 if (curr_group == NULL) { 6071 return BCM_E_NONE; 6072 } 6073 6074 while (curr_group != NULL) { 6075 if ((curr_group->stage_id == fg->stage_id) && 6076 (curr_group->gid != fg->gid) && 6077 (curr_group->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) && 6078 (curr_group->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) && 6079 (curr_group->instance == fg->instance) && 6080 (curr_group->priority == fg->priority)) { 6081 /* 6082 * Default group and Presel group can't have same priority. 6083 */ 6084 if ((fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) != 6085 (curr_group->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) { 6086 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 6087 "Error: Same priority is not possible between default group and" 6088 " presel group.\n\r"))); 6089 return BCM_E_PARAM; 6090 } 6091 6092 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 6093 /* Return Error if modes are different */ 6094 if ((fg->flags & _FP_GROUP_SPAN_MASK) != 6095 (curr_group->flags & _FP_GROUP_SPAN_MASK)) { 6096 return BCM_E_PARAM; 6097 } 6098 6099 /* update slice shared with same priority groups */ 6100 *slice_number = curr_group->slices->slice_number; 6101 break; 6102 } 6103 } 6104 curr_group = curr_group->next; 6105 } 6106 return BCM_E_NONE; 6107 } 6108 /* 6109 * Function: 6110 * _field_th_group_add_slice_allocate 6111 * Purpose: 6112 * Allocate slice for a new group. 6113 * Parameters: 6114 * unit - (IN) BCM device number. 6115 * fsm_ptr - (IN/OUT) State machine tracking structure. 6116 * Returns: 6117 * BCM_E_XXX 6118 */ 6119 STATIC int 6120 _field_th_group_add_slice_allocate(int unit, _field_group_add_fsm_t *fsm_ptr) 6121 { 6122 _field_group_t *fg; /* Field Group structure pointer. */ 6123 _field_stage_t *stage_fc; /* Field Stage control pointer. */ 6124 int slice; /* Slice iterator. */ 6125 uint8 slice_found = 0; /* Slice found indicator. */ 6126 6127 /* Input parameters check. */ 6128 if (NULL == fsm_ptr) { 6129 return (BCM_E_PARAM); 6130 } 6131 6132 /* Initialize field group pointer. */ 6133 fg = fsm_ptr->fg; 6134 6135 /* Initialize field stage pointer. */ 6136 stage_fc = fsm_ptr->stage_fc; 6137 6138 /* 6139 * If group priority is BCM_FIELD_GROUP_PRIO_ANY, 6140 * generate a new unique priority. 6141 */ 6142 if ((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) && 6143 (fg->priority == BCM_FIELD_GROUP_PRIO_ANY)) { 6144 stage_fc->group_running_prio += 1; 6145 fg->priority = stage_fc->group_running_prio; 6146 } 6147 6148 slice = -1; 6149 fsm_ptr->rv = _bcm_field_th_group_add_mode_validate(unit, fg, &slice); 6150 if (BCM_FAILURE(fsm_ptr->rv)) { 6151 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 6152 return BCM_E_NONE; 6153 } 6154 6155 if (slice != -1) { 6156 slice_found = 1; 6157 } else { 6158 slice = 0; 6159 } 6160 6161 /* Reserve a slice for this new Field Group. */ 6162 for (; slice < stage_fc->tcam_slices; slice++ ) { 6163 fsm_ptr->rv = _bcm_field_th_group_add_slice_validate(unit, stage_fc, fg, 6164 slice); 6165 if (BCM_SUCCESS(fsm_ptr->rv)) { 6166 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 6167 "==> %s(): SLICE[%d] allocated for group[%d].\n\r"), 6168 __func__, slice, fg->gid)); 6169 break; 6170 } else if (slice_found == 1) { 6171 fsm_ptr->rv = (BCM_E_RESOURCE); 6172 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 6173 return BCM_E_NONE; 6174 } 6175 6176 if ((BCM_E_PARAM == fsm_ptr->rv) || (BCM_E_RESOURCE == fsm_ptr->rv)) { 6177 break; 6178 } 6179 } 6180 6181 /* Check if allocation was successful. */ 6182 if (slice == stage_fc->tcam_slices) { 6183 fsm_ptr->rv = (BCM_E_RESOURCE); 6184 } 6185 6186 if (BCM_FAILURE(fsm_ptr->rv)) { 6187 if (fsm_ptr->fsm_state_prev != _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS) { 6188 fsm_ptr->rv = (BCM_E_NONE); 6189 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS; 6190 } else { 6191 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 6192 } 6193 } else { 6194 /* Update Group slices pointer. */ 6195 fg->slices = stage_fc->slices[fg->instance] + slice; 6196 6197 /* Update Group LT slices pointer. */ 6198 fg->lt_slices = stage_fc->lt_slices[fg->instance] + slice; 6199 6200 /* 6201 * Install key generation extractor codes and LT selection rule for the 6202 * group in hardware. 6203 */ 6204 fsm_ptr->rv = _field_th_group_add_group_install(unit, fsm_ptr); 6205 if (BCM_SUCCESS(fsm_ptr->rv)) { 6206 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_ADJUST_VIRTUAL_MAP; 6207 } else { 6208 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 6209 } 6210 } 6211 6212 /* Set current state as the previous state. */ 6213 fsm_ptr->fsm_state_prev = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE; 6214 return (BCM_E_NONE); 6215 } 6216 6217 /* 6218 * Function: 6219 * _bcm_field_th_entry_tcam_parts_count 6220 * Purpose: 6221 * Get number of tcam entries needed to accomodate a SW entry. 6222 * Parameters: 6223 * unit - (IN) BCM device number. 6224 * group_flags - (IN) Entry group flags. 6225 * part_count - (OUT) Entry parts count. 6226 * Returns: 6227 * BCM_E_XXX 6228 */ 6229 int 6230 _bcm_field_th_entry_tcam_parts_count(int unit, uint32 group_flags, 6231 int *part_count) 6232 { 6233 /* Input parameters check. */ 6234 if (NULL == part_count) { 6235 return (BCM_E_PARAM); 6236 } 6237 6238 /* Check group flags settings and determine number of TCAM entry parts. */ 6239 if (group_flags & _FP_GROUP_DW_DEPTH_EXPANDED) { 6240 /* Double-wide in BSK_FTFP_TCAM */ 6241 *part_count = 2; 6242 } else if (group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) { 6243 /* 6244 * Part value is same for Narrow and Wide TCAMs 6245 * (IFP_TCAM and IFP_TCAM_WIDE) 6246 * (group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) 6247 */ 6248 *part_count = 1; 6249 } else if (group_flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 6250 /* IFP_TCAM_WIDE view only. */ 6251 *part_count = 2; 6252 } else if (group_flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 6253 /* IFP_TCAM_WIDE view only. */ 6254 *part_count = 3; 6255 } 6256 return (BCM_E_NONE); 6257 } 6258 6259 /* 6260 * Function: 6261 * _bcm_field_th_lt_entry_tcam_parts_count 6262 * Purpose: 6263 * Get number of lt tcam entries needed to accomodate a SW entry. 6264 * Parameters: 6265 * unit - (IN) BCM device number. 6266 * stage_id - (IN) Stage Identifier. 6267 * group_flags - (IN) Entry group flags. 6268 * part_count - (OUT) Entry parts count. 6269 * Returns: 6270 * BCM_E_XXX 6271 */ 6272 int 6273 _bcm_field_th_lt_entry_tcam_parts_count(int unit, 6274 _field_stage_id_t stage_id, 6275 uint32 group_flags, 6276 int *part_count) 6277 { 6278 /* Input parameters check. */ 6279 if (NULL == part_count) { 6280 return (BCM_E_PARAM); 6281 } 6282 6283 if (stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 6284 *part_count = 1; 6285 return BCM_E_NONE; 6286 } 6287 6288 return _bcm_field_th_entry_tcam_parts_count(unit, group_flags, part_count); 6289 6290 } 6291 6292 /* 6293 * Function: 6294 * _bcm_field_th_slice_offset_to_tcam_idx 6295 * Purpose: 6296 * Given stage, slice number and entry index in the slice, calculate TCAM 6297 * index. 6298 * 6299 * Parameters: 6300 * unit - (IN) BCM device number. 6301 * stage_fc - (IN) Pointer to field entry structure. 6302 * instance - (IN) Field processor pipe instance. 6303 * slice - (IN) Entry slice number. 6304 * slice_idx -(IN) Entry offset in the slice. 6305 * tcam_idx - (OUT) Entry tcam index. 6306 * Returns: 6307 * BCM_E_XXX 6308 */ 6309 int 6310 _bcm_field_th_slice_offset_to_tcam_idx(int unit, _field_stage_t *stage_fc, 6311 int instance, int slice, int slice_idx, 6312 int *tcam_idx) 6313 { 6314 _field_slice_t *fs; /* Field slice structure pointer. */ 6315 6316 /* Input parameters check. */ 6317 if (NULL == stage_fc || NULL == tcam_idx) { 6318 return (BCM_E_PARAM); 6319 } 6320 6321 /* Input parameters check. */ 6322 if (instance < 0 || instance >= stage_fc->num_instances) { 6323 return (BCM_E_PARAM); 6324 } 6325 6326 /* Get the slice pointer. */ 6327 fs = stage_fc->slices[instance] + slice; 6328 6329 /* Given stage slice number and slice index, calcuate TCAM index. */ 6330 *tcam_idx = fs->start_tcam_idx + slice_idx; 6331 6332 return (BCM_E_NONE); 6333 } 6334 6335 /* 6336 * Function: 6337 * _bcm_field_th_tcam_idx_to_slice_offset 6338 * 6339 * Purpose: 6340 * Given stage and tcam_index, 6341 * calculate slice and entry offset in the 6342 * 6343 * Parameters: 6344 * unit - (IN) BCM device number. 6345 * stage_fc - (IN) Pointer to field stage structure. 6346 * f_ent - (IN) Reference to field entry structure. 6347 * tcam_idx - (IN) Entry tcam index. 6348 * slice - (OUT) Entry slice number. 6349 * slice_idx -(OUT) Entry offset in the slice. 6350 * Returns: 6351 * BCM_E_XXX 6352 */ 6353 int 6354 _bcm_field_th_tcam_idx_to_slice_offset(int unit, _field_stage_t *stage_fc, 6355 _field_entry_t *f_ent, int tcam_idx, 6356 int *slice, int *slice_idx) 6357 { 6358 _field_slice_t *fs; /* Field Slice number. */ 6359 int idx; /* Slice iterator. */ 6360 int max_entries_in_slice; /* Max entries supported in a slice.*/ 6361 6362 /* Input parameters check. */ 6363 if ((NULL == stage_fc) || (NULL == slice_idx) || (NULL == slice) 6364 || (NULL == f_ent)) { 6365 return (BCM_E_PARAM); 6366 } 6367 6368 #if defined (BCM_TOMAHAWK3_SUPPORT) 6369 if (SOC_IS_TOMAHAWK3(unit)) { 6370 return (_bcm_field_th3_tcam_idx_to_slice_offset (unit, stage_fc, 6371 f_ent, tcam_idx, 6372 slice, 6373 slice_idx)); 6374 } 6375 #endif 6376 6377 max_entries_in_slice = stage_fc->tcam_sz / stage_fc->tcam_slices; 6378 6379 if (!(f_ent->group->flags & _FP_GROUP_SPAN_SINGLE_SLICE) || 6380 (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 6381 max_entries_in_slice = max_entries_in_slice/2; 6382 } 6383 6384 for (idx = 0; idx < stage_fc->tcam_slices; idx++) { 6385 fs = stage_fc->slices[f_ent->group->instance] + idx; 6386 6387 if (tcam_idx < ((idx * max_entries_in_slice) + max_entries_in_slice)) { 6388 *slice = idx; 6389 *slice_idx = tcam_idx - fs->start_tcam_idx; 6390 break; 6391 } 6392 } 6393 6394 /* TCAM index sanity check. */ 6395 if (idx == stage_fc->tcam_slices) { 6396 return (BCM_E_PARAM); 6397 } 6398 6399 return (BCM_E_NONE); 6400 } 6401 6402 /* 6403 * Function: 6404 * _bcm_field_th_tcam_part_to_slice_number 6405 * Purpose: 6406 * Each field entry contains up to 3 TCAM entries. This routine maps tcam 6407 * entry (0-2) to a slice number 6408 * Parameters: 6409 * entry_part - (IN) Entry Part number. 6410 * group_flags - (IN) Field Group flags. 6411 * slice_number - (OUT) Slice number (0-2) 6412 * Returns: 6413 * BCM_E_XXX 6414 */ 6415 int 6416 _bcm_field_th_tcam_part_to_slice_number(int entry_part, uint32 group_flags, 6417 uint8 *slice_number) 6418 { 6419 /* Input parameters check. */ 6420 if (NULL == slice_number) { 6421 return (BCM_E_PARAM); 6422 } 6423 6424 switch (entry_part) { 6425 case 0: 6426 *slice_number = 0; 6427 break; 6428 case 1: 6429 *slice_number = 1; 6430 break; 6431 case 2: 6432 *slice_number = 2; 6433 break; 6434 default: 6435 return (BCM_E_INTERNAL); 6436 } 6437 return (BCM_E_NONE); 6438 } 6439 6440 /* 6441 * Function: 6442 * _bcm_field_th_entry_part_tcam_idx_get 6443 * 6444 * Purpose: 6445 * Given primary entry slice/idx calculate secondary/tertiary slice/index. 6446 * 6447 * Parameters: 6448 * unit - (IN) BCM device number. 6449 * f_ent - (IN) Field entry pointer. 6450 * idx_pri - (IN) Primary entry tcam index. 6451 * ent_part - (IN) Entry part id. 6452 * idx_out - (OUT) Entry part tcam index. 6453 * Returns 6454 * BCM_E_XXX 6455 */ 6456 int 6457 _bcm_field_th_entry_part_tcam_idx_get(int unit, _field_entry_t *f_ent, 6458 uint32 idx_pri, uint8 entry_part, 6459 int *idx_out) 6460 { 6461 uint8 slice_num = 0; /* Primary entry slice number. */ 6462 int pri_slice = 0; /* Primary slice number. */ 6463 int pri_index = 0; /* Primary entry. */ 6464 int part_index; /* Entry part slice index. */ 6465 _field_stage_t *stage_fc; /* Field stage control structure pointer. */ 6466 _field_slice_t *fs; /* Field slice structure pointer. */ 6467 _field_group_t *fg; /* Field Group structure. */ 6468 int rv; /* Operation return status. */ 6469 6470 /* Input parameters check. */ 6471 if (NULL == f_ent || NULL == idx_out) { 6472 return (BCM_E_PARAM); 6473 } 6474 6475 /* Primary entry index. */ 6476 if (0 == entry_part) { 6477 *idx_out = idx_pri; 6478 return (BCM_E_NONE); 6479 } 6480 6481 fg = f_ent->group; 6482 6483 /* Get stage control structure. */ 6484 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 6485 &stage_fc)); 6486 6487 /* Get primary part slice and entry index. */ 6488 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc, 6489 f_ent, idx_pri, &pri_slice, &pri_index)); 6490 6491 /* Get entry part slice number 0, 1, 2. */ 6492 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_slice_number(entry_part, 6493 fg->flags, &slice_num)); 6494 6495 fs = stage_fc->slices[fg->instance] + (pri_slice + slice_num); 6496 6497 part_index = pri_index; 6498 6499 /* 6500 * Given slice number & entry's offset index in slice, calculcate TCAM 6501 * index. 6502 */ 6503 rv = _bcm_field_th_slice_offset_to_tcam_idx(unit, stage_fc, fg->instance, 6504 fs->slice_number, part_index, idx_out); 6505 return (rv); 6506 } 6507 6508 /* 6509 * Function: 6510 * _field_th_entry_slice_idx_change 6511 * Purpose: 6512 * Move the software entry to a new slice index. 6513 * Parmeters: 6514 * unit - (IN) BCM device number. 6515 * f_ent - (IN/OUT) Field entry to be moved. 6516 * parts_count - (IN) Number of entry parts count. 6517 * tcam_idx_new - (IN) Entry new TCAM index. 6518 * Returns: 6519 * BCM_E_XXX 6520 */ 6521 STATIC int 6522 _field_th_entry_slice_idx_change(int unit, _field_entry_t *f_ent, 6523 int parts_count, int *tcam_idx_new) 6524 { 6525 _field_slice_t *fs; /* Field slice structure pointer. */ 6526 _field_group_t *fg; /* Field Group structure pointer. */ 6527 _field_stage_t *stage_fc; /* Stage Field control structure pointer. */ 6528 int new_slice_num = 0; /* Entry new slice number. */ 6529 int new_slice_idx = 0; /* Entry's new offset in the slice. */ 6530 int part; /* Entry parts iterator. */ 6531 6532 /* Input parameters check. */ 6533 if ((NULL == f_ent) || (NULL == f_ent->group) || (NULL == f_ent->fs)) { 6534 return (BCM_E_PARAM); 6535 } 6536 6537 /* Get stage control structure. */ 6538 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, f_ent->group->stage_id, 6539 &stage_fc)); 6540 6541 /* Get entry group information. */ 6542 fg = f_ent->group; 6543 for (part = 0; part < parts_count; part++) { 6544 /* Get slice control structure. */ 6545 fs = f_ent[part].fs; 6546 6547 if (FALSE == th_prio_set_with_no_free_entries) { 6548 fs->entries[f_ent[part].slice_idx] = NULL; 6549 } 6550 6551 /* 6552 * Calculate entry new slice number and offset in slice from TCAM index 6553 * value. 6554 */ 6555 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc, 6556 f_ent, tcam_idx_new[part], &new_slice_num, &new_slice_idx)); 6557 6558 /* If entry moves across the slice, update free counter.*/ 6559 if (new_slice_num != f_ent[part].fs->slice_number 6560 && (0 == (f_ent[part].flags & _FP_ENTRY_SECOND_HALF))) { 6561 fs->free_count++; 6562 stage_fc->slices[fg->instance][new_slice_num].free_count--; 6563 } 6564 6565 /* Update entry structure. */ 6566 stage_fc->slices[fg->instance][new_slice_num].entries[new_slice_idx] = 6567 f_ent + part; 6568 f_ent[part].fs = &stage_fc->slices[fg->instance][new_slice_num]; 6569 f_ent[part].slice_idx = new_slice_idx; 6570 } 6571 6572 return (BCM_E_NONE); 6573 } 6574 6575 /* 6576 * Function: 6577 * _field_th_entry_move 6578 * Purpose: 6579 * Move an entry within a slice by "amount" indexes 6580 * Parameters: 6581 * unit - BCM device number 6582 * f_ent - entry to be moved 6583 * amount - number of indexes to move + or - 6584 * Returns: 6585 * BCM_E_NONE - Success 6586 */ 6587 STATIC int 6588 _field_th_entry_move(int unit, _field_entry_t *f_ent, int amount) 6589 { 6590 int tcam_idx_old[_FP_MAX_ENTRY_WIDTH] = {0}; /* Original entry TCAM 6591 index. */ 6592 int tcam_idx_new[_FP_MAX_ENTRY_WIDTH] = {0}; /* New destination TCAM 6593 index. */ 6594 _field_control_t *fc; /* Field control structure pointer. */ 6595 _field_stage_t *stage_fc; /* Field stage structure pointer. */ 6596 _field_group_t *fg; /* Field Group structure pointer. */ 6597 /* _field_slice_t *fs; */ /* Field slice structure pointer. */ 6598 int parts_count = 0; /* Number of parts per-entry. */ 6599 int idx; /* Entry parts iterator. */ 6600 int new_offset; /* New entry offset in slice. */ 6601 int new_slice_num = -1; /* New slice number. */ 6602 6603 /* Input parameters check. */ 6604 if ((NULL == f_ent) || (NULL == f_ent->fs) || (NULL == f_ent->group)) { 6605 return (BCM_E_PARAM); 6606 } 6607 6608 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 6609 "FP(unit %d) vverb: BEGIN _field_th_entry_move(entry=%d, amount=%d)\n"), 6610 unit, f_ent->eid, amount)); 6611 6612 fg = f_ent->group; 6613 6614 if (0 == amount) { 6615 LOG_WARN(BSL_LS_BCM_FP, (BSL_META_U(unit, 6616 "FP(unit %d) warn: moving entry=%d, same slice_idx=%d(%#x)\n"), 6617 unit, f_ent->eid, f_ent->slice_idx, f_ent->slice_idx)); 6618 return (BCM_E_NONE); 6619 } 6620 6621 /* Get Field control structure. */ 6622 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 6623 6624 /* Get Stage control structure. */ 6625 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 6626 &stage_fc)); 6627 6628 /* Get number of parts. */ 6629 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 6630 &parts_count)); 6631 6632 for (idx = 0; idx < parts_count; idx++) { 6633 /* Calculate entry parts OLD TCAM indices. */ 6634 BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_idx_get(unit, f_ent + idx, 6635 &tcam_idx_old[idx])); 6636 6637 /* Calculate entry part tcam offset. */ 6638 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_part_tcam_idx_get(unit, f_ent, 6639 tcam_idx_old[0] + amount, idx, &tcam_idx_new[idx])); 6640 } 6641 6642 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc, 6643 f_ent, tcam_idx_new[0], &new_slice_num, &new_offset)); 6644 6645 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 6646 /* fs = stage_fc->slices[fg->instance] + new_slice_num; */ 6647 6648 /* Move the entry in hardware if it's already installed in HW. */ 6649 if (f_ent->flags & _FP_ENTRY_INSTALLED) { 6650 BCM_IF_ERROR_RETURN(fc->functions.fp_entry_move(unit, f_ent, 6651 parts_count, tcam_idx_old, tcam_idx_new)); 6652 } 6653 } 6654 /* Move the SW entry to the new slice index. */ 6655 BCM_IF_ERROR_RETURN(_field_th_entry_slice_idx_change(unit, f_ent, 6656 parts_count, tcam_idx_new)); 6657 6658 return (BCM_E_NONE); 6659 } 6660 6661 /* 6662 * Function: 6663 * _field_th_slice_is_empty 6664 * Purpose: 6665 * Report if a slice has any entries. 6666 * Parameters: 6667 * fc - (IN) Field control structure. 6668 * fs - (IN) Slice control structure. 6669 * empty - (OUT) True - slice is empty/False otherwise. 6670 * Returns: 6671 * BCM_E_XXX 6672 */ 6673 STATIC int 6674 _field_th_slice_is_empty(int unit, _field_slice_t *fs, uint8 *empty) 6675 { 6676 /* Input parameters check. */ 6677 if (NULL == fs || NULL == empty) { 6678 return (BCM_E_PARAM); 6679 } 6680 6681 /* Check if total entries count is equal to the free count. */ 6682 if (fs->entry_count == fs->free_count) { 6683 /* Slice has not valid group entries. */ 6684 *empty = TRUE; 6685 } else { 6686 /* Slice has atleast one valid entry. */ 6687 *empty = FALSE; 6688 } 6689 6690 return (BCM_E_NONE); 6691 } 6692 6693 /* 6694 * Function: 6695 * _field_th_ingress_slice_clear 6696 * 6697 * Purpose: 6698 * Reset the fields in a slice. Note that the entries list must be 6699 * empty before calling this. Also, this does NOT deallocate the memory for 6700 * the slice itself. Normally, this is used when a group no longer needs 6701 * ownership of a slice so the slice gets returned to the pool of available 6702 * slices. 6703 * 6704 * Paramters: 6705 * unit - (IN) BCM device number 6706 * fg - (IN) Field group structure. 6707 * fs - (IN/OUT) Link to physical slice structure to be cleared 6708 * 6709 * Returns: 6710 * BCM_E_NONE - Success 6711 * BCM_E_BUSY - Entries still in slice, can't clear slice 6712 */ 6713 STATIC int 6714 _field_th_ingress_slice_clear(int unit, _field_group_t *fg, _field_slice_t *fs) 6715 { 6716 _field_stage_t *stage_fc; /* Stage field control structure. */ 6717 _field_control_t *fc; /* Field control structure. */ 6718 uint32 entry_idx; /* Slice entries iterator. */ 6719 bcm_port_t port; /* Port iterator. */ 6720 int slice; /* Slice iterator. */ 6721 int tcam_idx; /* Slice first entry tcam index tracker. */ 6722 _field_slice_t *slice_ptr; /* Slice Pointer for traversal */ 6723 6724 /* Input parameters check. */ 6725 if ((NULL == fg) || (NULL == fs)) { 6726 return (BCM_E_PARAM); 6727 } 6728 6729 /* Skip for Flowtracker stage */ 6730 if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 6731 return (BCM_E_NONE); 6732 } 6733 6734 /* Get field control structure. */ 6735 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 6736 6737 /* Get stage field control structure. */ 6738 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fs->stage_id, 6739 &stage_fc)); 6740 6741 for (entry_idx = 0; entry_idx < fs->entry_count; entry_idx++) { 6742 if ((NULL != fs->entries[entry_idx]) 6743 && (fs->entries[entry_idx]->group->gid == fg->gid)) { 6744 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 6745 "FP(unit %d) Error: Entries still in slice=%d.\n"), 6746 unit, fs->slice_number)); 6747 return (BCM_E_BUSY); 6748 } 6749 } 6750 6751 /* Remove ports from slice's port bitmap. */ 6752 BCM_PBMP_ITER(fg->pbmp, port) { 6753 BCM_PBMP_PORT_REMOVE(fs->pbmp, port); 6754 } 6755 6756 /* Clear Group's LT_ID bit in slice LT map. */ 6757 fs->lt_map &= ~(1 << fg->lt_id); 6758 6759 /* Set entry count to invalid number */ 6760 fs->entry_count = -1; 6761 /* Initialize entries per-slice count. */ 6762 if ((soc_feature(unit, soc_feature_th3_style_fp) && 6763 (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS))) { 6764 #if defined(BCM_TOMAHAWK3_SUPPORT) 6765 if (fs->slice_number < _BCM_FIELD_TH3_INGRESS_MAX_SMALL_SLICES) { 6766 fs->entry_count = _BCM_FIELD_TH3_INGRESS_SMALL_SLICE_SZ; 6767 } else { 6768 fs->entry_count = _BCM_FIELD_TH3_INGRESS_LARGE_SLICE_SZ; 6769 } 6770 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6771 6772 for (slice = 0, tcam_idx = 0; slice < fs->slice_number; slice++) { 6773 slice_ptr = stage_fc->slices[fg->instance] + slice; 6774 tcam_idx += slice_ptr->entry_count; 6775 } 6776 fs->start_tcam_idx = tcam_idx; 6777 } else { 6778 fs->entry_count = stage_fc->tcam_sz / stage_fc->tcam_slices; 6779 fs->start_tcam_idx = fs->slice_number * fs->entry_count; 6780 } 6781 6782 /* Initialize free entries count. */ 6783 fs->free_count = fs->entry_count; 6784 6785 /* Initialize start TCAM index. */ 6786 slice_ptr = NULL; 6787 6788 /* Clear group flags settings. */ 6789 fs->group_flags = 0; 6790 6791 return (BCM_E_NONE); 6792 } 6793 /* 6794 * Function: 6795 * _bcm_field_th_ingress_slice_clear 6796 * 6797 * Purpose: 6798 * Reset the fields in a slice. Note that the entries list must be 6799 * empty before calling this. Also, this does NOT deallocate the memory for 6800 * the slice itself. Normally, this is used when a group no longer needs 6801 * ownership of a slice so the slice gets returned to the pool of available 6802 * slices. 6803 * 6804 * Paramters: 6805 * unit - (IN) BCM device number 6806 * fg - (IN) Field group structure. 6807 * fs - (IN/OUT) Link to physical slice structure to be cleared 6808 * 6809 * Returns: 6810 * BCM_E_NONE - Success 6811 * BCM_E_BUSY - Entries still in slice, can't clear slice 6812 */ 6813 int 6814 _bcm_field_th_ingress_slice_clear(int unit, 6815 _field_group_t *fg, 6816 _field_slice_t *fs) 6817 { 6818 return _field_th_ingress_slice_clear(unit, fg, fs); 6819 } 6820 6821 /* 6822 * Function to delete the LT entry from Hardware. 6823 */ 6824 STATIC int 6825 _field_th_lt_hw_entry_delete(int unit, 6826 _field_stage_t *stage_fc, 6827 _field_group_t *fg, 6828 int tcam_idx) 6829 { 6830 int rv; 6831 soc_mem_t lt_tcam_mem; 6832 uint32 entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; /*Entry buffer*/ 6833 6834 /* Get TCAM view to be used for programming the hardware */ 6835 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 6836 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 6837 fg->instance, 6838 _BCM_FIELD_MEM_TYPE_IFP_LT, 6839 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 6840 <_tcam_mem, NULL)); 6841 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 6842 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 6843 fg->instance, 6844 _BCM_FIELD_MEM_TYPE_EM_LT, 6845 _BCM_FIELD_MEM_VIEW_TYPE_TCAM, 6846 <_tcam_mem, NULL)); 6847 } else { 6848 return BCM_E_PARAM; 6849 } 6850 BCM_IF_ERROR_RETURN(rv); 6851 6852 /* Clear the entry in hardware. */ 6853 return (soc_th_ifp_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 6854 tcam_idx, entry)); 6855 } 6856 6857 6858 /* 6859 * Function: 6860 * _bcm_field_th_lt_slice_clear 6861 * 6862 * Purpose: 6863 * Reset the default LT entry or Preselector entries in a slice. 6864 * Note that the entries list must be empty before calling this. 6865 * Also, this does NOT deallocate the memory for the slice itself. 6866 * Normally, this is used when a group no longer needs ownership 6867 * of a slice so the slice gets returned to the pool of available 6868 * slices. 6869 * 6870 * Paramters: 6871 * unit - (IN) BCM device number 6872 * fg - (IN) Field group structure. 6873 * slice_num - (IN) Slice to be reset. 6874 * 6875 * Returns: 6876 * BCM_E_xxx 6877 */ 6878 STATIC int 6879 _bcm_field_th_lt_slice_clear(int unit, _field_group_t *fg, int slice_num) 6880 { 6881 int rv, idx; 6882 int tcam_idx; 6883 int part, parts = -1; 6884 _field_stage_t *stage_fc; 6885 _field_control_t *fc; 6886 _field_lt_slice_t *lt_fs; 6887 _field_lt_slice_t *lt_part_fs = NULL; 6888 bcm_field_entry_t lt_entry; 6889 _field_lt_entry_t *lt_f_entry, 6890 *lt_f_entry_p = NULL; 6891 _field_presel_entry_t *f_presel, 6892 *f_presel_p; 6893 6894 /* Input parameters check. */ 6895 if (NULL == fg) { 6896 return (BCM_E_PARAM); 6897 } 6898 6899 /* Field control get. */ 6900 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 6901 6902 /* Get stage control structure. */ 6903 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 6904 &stage_fc)); 6905 6906 /* Find the LT Slice to be cleared. */ 6907 lt_fs = stage_fc->lt_slices[fg->instance] + slice_num; 6908 6909 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 6910 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 6911 if (fg->presel_ent_arr[idx] != NULL) { 6912 f_presel = fg->presel_ent_arr[idx]; 6913 } else { 6914 continue; 6915 } 6916 6917 f_presel_p = f_presel; 6918 6919 tcam_idx = -1; 6920 for (; f_presel_p != NULL; f_presel_p = f_presel_p->next) { 6921 lt_part_fs = f_presel_p->lt_fs; 6922 6923 for (; lt_part_fs != NULL; lt_part_fs=lt_part_fs->next) { 6924 if (lt_part_fs == lt_fs) { 6925 lt_part_fs->free_count++; 6926 lt_part_fs->p_entries[f_presel_p->hw_index] = NULL; 6927 6928 rv = _bcm_field_presel_entry_tcam_idx_get(unit, 6929 f_presel_p, lt_fs, &tcam_idx); 6930 BCM_IF_ERROR_RETURN(rv); 6931 rv = _field_th_lt_hw_entry_delete(unit, stage_fc, 6932 fg, tcam_idx); 6933 BCM_IF_ERROR_RETURN(rv); 6934 6935 if (f_presel_p->lt_fs == lt_part_fs) { 6936 f_presel_p->lt_fs = lt_part_fs->next; 6937 } 6938 break; 6939 } 6940 } 6941 6942 if (tcam_idx != -1) { 6943 break; 6944 } 6945 } 6946 } 6947 } else { 6948 /* Get entry parts count. */ 6949 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, 6950 fg->flags, &parts)); 6951 lt_entry = fc->lt_info[fg->instance][fg->lt_id]->lt_entry; 6952 6953 /* Get all part of the entry. */ 6954 BCM_IF_ERROR_RETURN(_field_th_lt_entry_get_by_id(unit, 6955 lt_entry, <_f_entry)); 6956 if (lt_f_entry->lt_fs == NULL) { 6957 return BCM_E_INTERNAL; 6958 } 6959 6960 tcam_idx = -1; 6961 for (part = 0; part < parts; part++) { 6962 lt_f_entry_p = lt_f_entry + part; 6963 lt_part_fs = lt_f_entry_p->lt_fs; 6964 for (;lt_part_fs != NULL;lt_part_fs=lt_part_fs->next) { 6965 if (lt_part_fs == lt_fs) { 6966 lt_part_fs->free_count++; 6967 lt_part_fs->entries[lt_f_entry_p->index] = NULL; 6968 6969 rv = _field_th_lt_entry_tcam_idx_get(unit, lt_f_entry_p, 6970 lt_fs, &tcam_idx); 6971 BCM_IF_ERROR_RETURN(rv); 6972 rv = _field_th_lt_hw_entry_delete(unit, stage_fc, 6973 fg, tcam_idx); 6974 BCM_IF_ERROR_RETURN(rv); 6975 6976 if (lt_f_entry_p->lt_fs == lt_part_fs) { 6977 lt_f_entry_p->lt_fs = lt_part_fs->next; 6978 } 6979 break; 6980 } 6981 } 6982 if (tcam_idx != -1) { 6983 break; 6984 } 6985 } 6986 } 6987 6988 /* Update group's primary lt slice */ 6989 if (fg->lt_slices == lt_fs) { 6990 fg->lt_slices = lt_fs->next; 6991 } 6992 6993 if (lt_fs->free_count == lt_fs->entry_count) { 6994 if (lt_fs->prev != NULL) { 6995 lt_fs->prev->next = lt_fs->next; 6996 } 6997 6998 if (lt_fs->next != NULL) { 6999 lt_fs->next->prev = lt_fs->prev; 7000 } 7001 7002 lt_fs->next = NULL; 7003 lt_fs->prev = NULL; 7004 } 7005 7006 return BCM_E_NONE; 7007 } 7008 7009 /* 7010 * Function: 7011 * _bcm_field_th_group_free_unused_slices 7012 * Purpose: 7013 * Unallocate group unused slices. 7014 * Parameters: 7015 * unit - (IN) BCM device number. 7016 * stage_fc - (IN) Stage field control structure. 7017 * fg - (IN) Field group structure. 7018 * Returns: 7019 * BCM_E_XXX 7020 */ 7021 int 7022 _bcm_field_th_group_free_unused_slices(int unit, 7023 _field_stage_t *stage_fc, 7024 _field_group_t *fg) 7025 { 7026 _field_slice_t *fs; /* Field slice structure pointer. */ 7027 _field_slice_t *fs_next; /* Field slice structure pointer. */ 7028 _field_slice_t *fs_ptr; /* Field slice structure pointer. */ 7029 uint8 empty; /* Slice is empty flag. */ 7030 int slice; /* Group slices iterator. */ 7031 int count; /* Group slices span count. */ 7032 _field_control_t *fc; /* field control */ 7033 _field_meter_pool_t *f_mp; /* Meter pool descriptor. */ 7034 _field_group_t *fg_next = NULL; 7035 int pri_slice = -1; 7036 int pool_idx = 0; 7037 7038 /* Input parameters check. */ 7039 if ((NULL == stage_fc) || (NULL == fg)) { 7040 return (BCM_E_PARAM); 7041 } 7042 7043 if (NULL == fg->slices) { 7044 return (BCM_E_INTERNAL); 7045 } 7046 7047 fs = fg->slices; 7048 /* Don't free the slice if it is the last slice in the group */ 7049 if (fs->next == NULL) { 7050 return BCM_E_NONE; 7051 } 7052 7053 while (NULL != fs) { 7054 if (pri_slice == -1) { 7055 pri_slice = fs->slice_number; 7056 } 7057 fs_next = fs->next; 7058 BCM_IF_ERROR_RETURN(_field_th_slice_is_empty(unit, fs, &empty)); 7059 7060 if (empty) { 7061 BCM_IF_ERROR_RETURN(_bcm_field_group_slice_count_get(fs->group_flags, 7062 &count)); 7063 7064 do { 7065 /* Retrieve the existing groups associated with the Slice */ 7066 (void)_bcm_field_slice_group_get_next(unit, 7067 fg->instance, fg->stage_id, 7068 fs->slice_number, 7069 &fg_next, &fg_next); 7070 if (fg_next != NULL) { 7071 for (slice = 0; slice < count; slice++) { 7072 /* Remove slice from Group's slices linked list. */ 7073 fs_ptr = fs + slice; 7074 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 7075 "%s(): SLICE TO BE detached SLICE:%d fs_ptr:%p fg_slice:%p" 7076 " fg_slice_num:%d\n\r\n\r"), __func__, 7077 fs_ptr->slice_number, fs_ptr, fg->slices, 7078 (fg->slices!=NULL)?fg->slices->slice_number:-1)); 7079 7080 /* Reset the partition priority for the slice. */ 7081 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_part_prio_reset(unit, 7082 stage_fc, fg_next, fs_ptr)); 7083 /* Clear unused LT slice settings. */ 7084 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_slice_clear(unit, 7085 fg_next, fs_ptr->slice_number)); 7086 /* Clear unused slice settings. */ 7087 BCM_IF_ERROR_RETURN(_field_th_ingress_slice_clear(unit, 7088 fg_next, fs_ptr)); 7089 } 7090 } 7091 7092 if ((fg_next != NULL) && (fg_next->slices == fs)) { 7093 fg_next->slices = fs->next; 7094 7095 if (fg_next->presel_ent_arr[0]) { 7096 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 7097 "$$ GID:[%d] fg->presel_ent_arr[0]->lt_fs:%p slice:%d\n\r"), 7098 fg_next->gid, fg_next->presel_ent_arr[0]->lt_fs, 7099 (fg_next->presel_ent_arr[0]->lt_fs == NULL) ? 7100 -1 : fg_next->presel_ent_arr[0]->lt_fs->slice_number)); 7101 7102 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 7103 "$$ fg->presel_ent_arr[0]->next->lt_fs:%p slice:%d\n\r"), 7104 fg_next->presel_ent_arr[0]->next->lt_fs, 7105 (fg_next->presel_ent_arr[0]->next->lt_fs == NULL) ? 7106 -1 : fg_next->presel_ent_arr[0]->next->lt_fs->slice_number)); 7107 } 7108 } 7109 } while(fg_next != NULL); 7110 7111 /* Get field control structure. */ 7112 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7113 7114 /* When the first slice (primary slice) of the group is released, 7115 * the meter pool slice_id of the policers attached to 7116 * the remaining entries are updated to the new primary slice id. 7117 */ 7118 7119 if ((!(_FP_POLICER_GROUP_SHARE_ENABLE & fc->flags)) && 7120 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) && 7121 (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) && 7122 (fs->slice_number == pri_slice)) { 7123 for (pool_idx = 0; pool_idx < stage_fc->num_meter_pools; 7124 pool_idx++) { 7125 f_mp = stage_fc->meter_pool[fg->instance][pool_idx]; 7126 if ((f_mp->level == 0) && 7127 (f_mp->slice_id == pri_slice)) { 7128 f_mp->slice_id = fs->next->slice_number; 7129 } 7130 } 7131 } 7132 7133 /* Unlink the slice from the group's list */ 7134 for (slice = 0; slice < count; slice++) { 7135 fs_ptr = fs + slice; 7136 if (fs_ptr->next != NULL) { 7137 fs_ptr->next->prev = fs_ptr->prev; 7138 } 7139 7140 if (fs_ptr->prev != NULL) { 7141 fs_ptr->prev->next = fs_ptr->next; 7142 } 7143 fs_ptr->prev = NULL; 7144 fs_ptr->next = NULL; 7145 } 7146 } 7147 fs = fs_next; 7148 } 7149 7150 return (BCM_E_NONE); 7151 } 7152 7153 /* 7154 * Function: 7155 * _bcm_field_th_group_compress 7156 * Purpose: 7157 * Compress field group entries in order to free slices used by the group. 7158 * Paramters: 7159 * unit - (IN) BCM device number 7160 * fg - (IN) Field group structure 7161 * stage_fc - (IN) Stage field control structure. 7162 * Returns: 7163 * BCM_E_XXX 7164 */ 7165 int 7166 _bcm_field_th_group_compress(int unit, _field_group_t *fg, _field_stage_t *stage_fc) 7167 { 7168 _field_slice_t *fs; /* Field slice structure pointer. */ 7169 _field_slice_t *efs; /* Slice that contains free slots. */ 7170 int eidx; /* Empty slot index. */ 7171 int idx; /* Slice entry iterator. */ 7172 int tmp_idx1; /* Slice entry index 1. */ 7173 int tmp_idx2; /* Slice entry index 2. */ 7174 int slice_sz; /* Number of entries in a slice. */ 7175 int rv; /* Operation return status. */ 7176 7177 /* Get group slice pointer. */ 7178 fs = fg->slices; 7179 7180 efs = NULL; 7181 eidx = -1; 7182 7183 while (NULL != fs) { 7184 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 7185 for (idx = 0; idx < slice_sz; idx++) { 7186 /* Find an empty slot. */ 7187 if (NULL == fs->entries[idx]) { 7188 if (NULL == efs) { 7189 efs = fs; 7190 eidx = idx; 7191 } 7192 continue; 7193 } 7194 7195 if (NULL != efs) { 7196 /* 7197 * Given Stage, Slice number and Entry offset in the slice, 7198 * calculate the TCAM entry indices. 7199 */ 7200 BCM_IF_ERROR_RETURN(_bcm_field_th_slice_offset_to_tcam_idx(unit, 7201 stage_fc, fg->instance, efs->slice_number, eidx, &tmp_idx1)); 7202 7203 BCM_IF_ERROR_RETURN(_bcm_field_th_slice_offset_to_tcam_idx(unit, 7204 stage_fc, fg->instance, fs->slice_number, idx, &tmp_idx2)); 7205 7206 /* Move the entry in hardware. */ 7207 BCM_IF_ERROR_RETURN(_field_th_entry_move(unit, fs->entries[idx], 7208 (tmp_idx1 - tmp_idx2))); 7209 fs = efs; 7210 idx = eidx; 7211 efs = NULL; 7212 eidx = -1; 7213 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz); 7214 } 7215 } 7216 fs = fs->next; 7217 } 7218 rv = _bcm_field_th_group_free_unused_slices(unit, stage_fc, fg); 7219 return (rv); 7220 } 7221 7222 /* 7223 * Function: 7224 * _field_th_stage_group_compress 7225 * Purpose: 7226 * Compress field group entries in order to free slices used by the group. 7227 * Paramters: 7228 * unit - (IN) BCM device number 7229 * fg - (IN) Field group structure 7230 * stage_fc - (IN) Stage field control structure. 7231 * Returns: 7232 * BCM_E_XXX 7233 */ 7234 STATIC int 7235 _field_th_stage_group_compress(int unit, 7236 _field_control_t *fc, 7237 _field_stage_t *stage_fc) 7238 { 7239 _field_group_t *fg; /* Field Group structure pointer. */ 7240 int rv = BCM_E_NONE; /* Operation return status. */ 7241 7242 for (fg = fc->groups; fg != NULL; fg = fg->next) { 7243 /* Skit other stages. */ 7244 if (fg->stage_id != stage_fc->stage_id) { 7245 continue; 7246 } 7247 7248 /* Skit new groups. */ 7249 if (NULL == fg->slices) { 7250 continue; 7251 } 7252 7253 /* Ignore Non-Expanded Groups. */ 7254 if (NULL == fg->slices->next) { 7255 continue; 7256 } 7257 7258 /* 7259 * Best effort to compress groups that occupy more than one physical 7260 * table. 7261 */ 7262 rv = _bcm_field_th_group_compress(unit, fg, stage_fc); 7263 } 7264 return (rv); 7265 } 7266 7267 /* 7268 * Function: 7269 * _field_th_group_add_cam_compress 7270 * Purpose: 7271 * Compress other groups to free room for inserted group. 7272 * Parameters: 7273 * unit - (IN) BCM device number. 7274 * fsm_ptr - (IN/OUT) State machine tracking structure. 7275 * Returns: 7276 * BCM_E_XXX 7277 */ 7278 STATIC int 7279 _field_th_group_add_cam_compress(int unit, _field_group_add_fsm_t *fsm_ptr) 7280 { 7281 /* Set current stage to be previous state. */ 7282 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 7283 7284 /* Compress expanded groups. */ 7285 fsm_ptr->rv = _field_th_stage_group_compress(unit, fsm_ptr->fc, 7286 fsm_ptr->stage_fc); 7287 7288 if (BCM_SUCCESS(fsm_ptr->rv)) { 7289 /* Retry allocating slice/s for the new field group. */ 7290 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE; 7291 } else { 7292 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 7293 } 7294 7295 return (BCM_E_NONE); 7296 } 7297 7298 /* 7299 * Function: 7300 * _bcm_field_th_tcam_part_to_entry_flags 7301 * Purpose: 7302 * Each field entry contains up to 3 TCAM 7303 * entries. This routine maps tcam entry (0-2) 7304 * to SW entry flags. 7305 * Single: 0 (IFP_TCAM view) 7306 * Single & Intraslice Double: 0 (IFP_TCAM_WIDE view) 7307 * Paired: 0, 1 (IFP_TCAM_WIDE view) 7308 * Triple: 0, 1, 2 (IFP_TCAM_WIDE view) 7309 * Retrieve the part of the group entry resides in. 7310 * Parameters: 7311 * unit - (IN) BCM device number. 7312 * entry_flags - (IN) Entry flags. 7313 * group_flags - (IN) Entry group flags. 7314 * entry_part - (OUT) Entry part (0-2) 7315 * Returns: 7316 * BCM_E_NONE - Success. 7317 * BCM_E_INTERNAL - Invalid entry part. 7318 */ 7319 int 7320 _bcm_field_th_tcam_part_to_entry_flags(int unit, int entry_part, 7321 uint32 group_flags, 7322 uint32 *entry_flags) 7323 { 7324 /* Input parameters check. */ 7325 if (NULL == entry_flags) { 7326 return (BCM_E_PARAM); 7327 } 7328 7329 /* Map entry part count to entry flags. */ 7330 switch (entry_part) { 7331 case 0: 7332 *entry_flags = _FP_ENTRY_PRIMARY; 7333 break; 7334 case 1: 7335 *entry_flags = _FP_ENTRY_SECONDARY; 7336 break; 7337 case 2: 7338 *entry_flags = _FP_ENTRY_TERTIARY; 7339 break; 7340 default: 7341 return (BCM_E_INTERNAL); 7342 } 7343 return (BCM_E_NONE); 7344 } 7345 7346 /* 7347 * Function: 7348 * _field_th_group_ltmap_delete 7349 * Purpose: 7350 * Delete Logical Table's association with group. 7351 * Parameters: 7352 * unit - (IN) BCM device number. 7353 * fg - (IN/OUT) Field group structure pointer. 7354 * Returns: 7355 * BCM_E_XXX 7356 */ 7357 STATIC int 7358 _field_th_group_ltmap_delete(int unit, _field_group_t *fg) 7359 { 7360 _field_control_t *fc; /* Field Control Strucutre. */ 7361 _field_stage_t *stage_fc; /* Field stage control structure. */ 7362 7363 /* Input parameters check. */ 7364 if (NULL == fg) { 7365 return (BCM_E_PARAM); 7366 } 7367 7368 /* skip for Flowtracker stage */ 7369 if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 7370 return (BCM_E_NONE); 7371 } 7372 7373 /* Check if group has a valid logical table information pointer. */ 7374 if (fg->lt_id == -1) { 7375 return (BCM_E_NONE); 7376 } 7377 7378 /* Get field control information. */ 7379 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7380 7381 /* Get stage control information. */ 7382 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 7383 fg->stage_id, &stage_fc)); 7384 7385 7386 fc->lt_info[fg->instance][fg->lt_id]->valid = FALSE; 7387 fc->lt_info[fg->instance][fg->lt_id]->priority = 0; 7388 fc->lt_info[fg->instance][fg->lt_id]->flags = 0; 7389 fc->lt_info[fg->instance][fg->lt_id]->lt_action_pri = 0; 7390 fc->lt_info[fg->instance][fg->lt_id]->lt_entry = 0; 7391 7392 /* Clear Group's LT_ID information. */ 7393 fg->lt_id = -1; 7394 7395 return (BCM_E_NONE); 7396 } 7397 /* 7398 * Function: 7399 * _field_lt_entry_tcam_remove 7400 * Purpose: 7401 * Clears a LT selection TCAM entry for a given index from hardware. 7402 * Parameters: 7403 * unit - (IN) BCM device number. 7404 * lt_f_ent - (IN) Logical Table entry structure. 7405 * tcam_idx - (IN) Entry TCAM index. 7406 * Returns: 7407 * BCM_E_XXX 7408 */ 7409 STATIC int 7410 _field_lt_entry_tcam_remove(int unit, _field_lt_entry_t *lt_f_ent, 7411 int tcam_idx) 7412 { 7413 _field_stage_t *stage_fc; /* Stage field control structure. */ 7414 soc_mem_t lt_tcam_mem; /* LT TCAM memory name identifier. */ 7415 7416 /* Input parameters check. */ 7417 if ((NULL == lt_f_ent) || (NULL == lt_f_ent->lt_fs)) { 7418 return (BCM_E_PARAM); 7419 } 7420 7421 /* Get stage field control structure. */ 7422 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 7423 lt_f_ent->lt_fs->stage_id, &stage_fc)); 7424 7425 /* Get LT TCAM memory name. */ 7426 BCM_IF_ERROR_RETURN(_field_th_lt_tcam_mem_get(unit, stage_fc, lt_f_ent, 7427 <_tcam_mem)); 7428 7429 /* Validate supplied TCAM index. */ 7430 if (tcam_idx < soc_mem_index_min(unit, lt_tcam_mem) 7431 || tcam_idx > soc_mem_index_max(unit, lt_tcam_mem)) { 7432 return (BCM_E_PARAM); 7433 } 7434 7435 /* Clear TCAM entry in hardware at the supplied TCAM index. */ 7436 SOC_IF_ERROR_RETURN(soc_th_ifp_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 7437 tcam_idx, soc_mem_entry_null(unit, lt_tcam_mem))); 7438 7439 return (BCM_E_NONE); 7440 } 7441 7442 /* 7443 * Function: 7444 * _field_th_lt_default_entry_remove 7445 * Purpose: 7446 * Remove a logical table entry from hardware. 7447 * Parameters: 7448 * unit - (IN) BCM device number. 7449 * lt_entry - (IN) Logical Table entry identifier. 7450 * Returns: 7451 * BCM_E_XXX 7452 */ 7453 STATIC int 7454 _field_th_lt_default_entry_remove(int unit, bcm_field_entry_t lt_entry) 7455 { 7456 _field_lt_entry_t *lt_f_ent; /* LT entry structure pointer. */ 7457 int parts_count = -1; /* Entry parts count. */ 7458 int part; /* Entry part. */ 7459 int tcam_idx; /* LT TCAM entry index. */ 7460 7461 BCM_IF_ERROR_RETURN(_field_th_lt_entry_get(unit, lt_entry, 7462 _FP_ENTRY_PRIMARY, <_f_ent)); 7463 7464 if (!(lt_f_ent->flags & _FP_ENTRY_INSTALLED)) { 7465 /* Entry not installed in hardware to remove. */ 7466 return (BCM_E_NONE); 7467 } 7468 7469 /* Get number of entry parts using group flags. . */ 7470 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, 7471 lt_f_ent->group->flags, &parts_count)); 7472 7473 /* Iterate over entry parts and remove the entry from HW. */ 7474 for (part = 0; part < parts_count; part++) { 7475 /* Get LT TCAM entry details from hardware. */ 7476 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_tcam_entry_get(unit, lt_f_ent->group, 7477 lt_f_ent + part)); 7478 7479 /* Given entry part number, get the entry TCAM index. */ 7480 BCM_IF_ERROR_RETURN(_field_th_lt_entry_tcam_idx_get(unit, 7481 lt_f_ent + part, (lt_f_ent + part)->lt_fs, &tcam_idx)); 7482 7483 /* Clear the entry from hardware. */ 7484 BCM_IF_ERROR_RETURN(_field_lt_entry_tcam_remove(unit, lt_f_ent + part, 7485 tcam_idx)); 7486 7487 lt_f_ent[part].flags |= _FP_ENTRY_DIRTY; 7488 lt_f_ent[part].flags &= ~(_FP_ENTRY_INSTALLED); 7489 lt_f_ent[part].flags &= ~(_FP_ENTRY_ENABLED); 7490 } 7491 7492 return (BCM_E_NONE); 7493 } 7494 7495 /* 7496 * Function: 7497 * _field_th_lt_entry_default_rule_deinit 7498 * Purpose: 7499 * Deinit logical table default rule from hardware. 7500 * Parameters: 7501 * unit - (IN) BCM device number. 7502 * stage_fc - (IN) Field stage control structure. 7503 * lt_f_ent - (IN) Logical table entry structure. 7504 * Returns: 7505 * BCM_E_XXX 7506 */ 7507 STATIC int 7508 _field_th_lt_entry_default_rule_deinit(int unit, _field_stage_t *stage_fc, 7509 _field_lt_entry_t *lt_f_ent) 7510 { 7511 int parts_count = 0; /* Entry parts count. */ 7512 int part; /* Entry part iterator. */ 7513 _field_group_t *fg; /* Field group structure pointer. */ 7514 7515 /* Input parameters check. */ 7516 if ((NULL == stage_fc) || (NULL == lt_f_ent)) { 7517 return (BCM_E_PARAM); 7518 } 7519 7520 /* Get field group structure pointer. */ 7521 fg = lt_f_ent->group; 7522 7523 /* Get number of entry parts using group flags. */ 7524 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 7525 &parts_count)); 7526 7527 /* Uninstall entry parts keygen program profile entries from hardware. */ 7528 for (part = 0; part < parts_count; part++) { 7529 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 7530 &stage_fc->keygen_profile[fg->instance].profile, 7531 fg->ext_codes[part].keygen_index)); 7532 } 7533 7534 return (BCM_E_NONE); 7535 } 7536 7537 /* 7538 * Function: 7539 * _field_th_ingress_selcodes_uninstall 7540 * Purpose: 7541 * Uninstall group's key generation program from hardware. 7542 * Parameters: 7543 * unit - (IN) BCM device number. 7544 * stage_fc - (IN) Field stage control structure. 7545 * fg - (IN) Field Group control structure. 7546 * Returns: 7547 * BCM_E_XXX 7548 */ 7549 STATIC int 7550 _field_th_ingress_selcodes_uninstall(int unit, _field_stage_t *stage_fc, 7551 _field_group_t *fg) 7552 { 7553 _field_control_t *fc; /* Field Control Strucutre. */ 7554 7555 /* Input parameters check. */ 7556 if ((NULL == fg) || (NULL == stage_fc)) { 7557 return (BCM_E_PARAM); 7558 } 7559 7560 /* Field control get. */ 7561 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7562 7563 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 7564 int part, parts_ct = 0; 7565 int idx; 7566 _field_presel_entry_t *f_presel; 7567 7568 7569 /* Get number of entry parts. */ 7570 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 7571 fg->stage_id, fg->flags, &parts_ct)); 7572 7573 /* 7574 * Detach Presel Entries from the LT slice associated with the group 7575 */ 7576 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 7577 if (fg->presel_ent_arr[idx] != NULL) { 7578 f_presel = fg->presel_ent_arr[idx]; 7579 } else { 7580 continue; 7581 } 7582 7583 /* Uninstall entry parts keygen program profile 7584 * entries from hardware. */ 7585 if (fg->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) { 7586 for (part = 0; part < parts_ct; part++) { 7587 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 7588 &stage_fc->keygen_profile[fg->instance].profile, 7589 fg->ext_codes[part].keygen_index)); 7590 } 7591 } 7592 7593 /* Remove Presel entries from hardware. */ 7594 BCM_IF_ERROR_RETURN(_bcm_field_th_presel_entry_hw_remove 7595 (unit, f_presel)); 7596 7597 /* Destroy resources allocated for the entry. */ 7598 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_phys_destroy 7599 (unit, f_presel)); 7600 } 7601 } else { 7602 _field_lt_entry_t *lt_f_ent; /* LT field entry structure pointer. */ 7603 bcm_field_entry_t lt_entry; /* LT selection Entry ID. */ 7604 7605 /* Get Entry ID Group's LT information structure. */ 7606 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 7607 lt_entry = fc->lt_info[0][fg->lt_id]->lt_entry; 7608 } else { 7609 lt_entry = fc->lt_info[fg->instance][fg->lt_id]->lt_entry; 7610 } 7611 7612 /* Get entry LT entry structure pointer. */ 7613 BCM_IF_ERROR_RETURN(_field_th_lt_entry_get(unit, lt_entry, 7614 _FP_ENTRY_PRIMARY, <_f_ent)); 7615 7616 /* Remove LT entry from hardware. */ 7617 BCM_IF_ERROR_RETURN(_field_th_lt_default_entry_remove(unit, lt_entry)); 7618 7619 /* Delete keygen profiles used by the group. */ 7620 BCM_IF_ERROR_RETURN(_field_th_lt_entry_default_rule_deinit(unit, 7621 stage_fc, lt_f_ent)); 7622 7623 /* Destroy resources allocated for the entry. */ 7624 BCM_IF_ERROR_RETURN(_field_th_lt_default_entry_phys_destroy( 7625 unit, lt_f_ent)); 7626 } 7627 return (BCM_E_NONE); 7628 } 7629 7630 /* 7631 * Function: 7632 * _field_th_ingress_group_uninstall 7633 * Purpose: 7634 * Uninstall group from all slices. 7635 * 7636 * Parameters: 7637 * unit - (IN) BCM device number. 7638 * stage_fc - (IN) Field stage control structure. 7639 * fg - (IN) Field group. 7640 * 7641 * Returns: 7642 * BCM_E_XXX 7643 */ 7644 STATIC int 7645 _field_th_ingress_group_uninstall(int unit, _field_stage_t *stage_fc, 7646 _field_group_t *fg) 7647 { 7648 _field_control_t *fc; /* Field control structure. */ 7649 _field_slice_t *fs; /* Field slice structure. */ 7650 _field_slice_t *temp_fs; /* Expanded slices iterator. */ 7651 int parts_count = 0; /* Number of entry parts. */ 7652 uint16 group_count = 0; /* Number of groups. */ 7653 uint8 slice_number; /* Slice iterator. */ 7654 uint8 slice_reset = 0; /* Slice reset flg. */ 7655 int idx; /* Slice iterator. */ 7656 7657 /* Input parameters check. */ 7658 if (NULL == fg) { 7659 return (BCM_E_PARAM); 7660 } 7661 /* Get Field Control structure pointer. */ 7662 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7663 7664 /* 7665 * Uninstall TCAM keygen program configuration from hardware for each 7666 * slice. 7667 */ 7668 BCM_IF_ERROR_RETURN(_field_th_ingress_selcodes_uninstall(unit, stage_fc, 7669 fg)); 7670 7671 #if defined(BCM_FLOWTRACKER_SUPPORT) 7672 /* clear keytype bit */ 7673 BCM_IF_ERROR_RETURN(_field_hx5_ft_group_keytype_clear(unit, stage_fc, fg)); 7674 if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 7675 return (BCM_E_NONE); 7676 } 7677 #endif 7678 7679 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 7680 (void)_bcm_field_group_count_get(unit, fg->instance, 7681 stage_fc, 7682 fg->priority, 7683 _FP_GROUP_SPAN_MASK, 7684 &group_count); 7685 if (group_count <= 1) { 7686 slice_reset = 1; 7687 } 7688 } else { 7689 slice_reset = 1; 7690 } 7691 7692 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 7693 "SLICE CLEAR: Gid:%d prio:%d count:%d slice_num:%d mode:0x%x slice_reset:%d \n\r"), 7694 fg->gid, fg->priority, group_count, fg->slices->slice_number, 7695 (fg->flags & _FP_GROUP_SPAN_MASK), slice_reset)); 7696 7697 /* Get number of entry parts. */ 7698 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 7699 &parts_count)); 7700 7701 /* 7702 * Parse through the Group parts to clear 7703 * LT partition priority and slices. 7704 */ 7705 for (idx = parts_count - 1; idx >= 0; idx--) { 7706 /* Get Slice ID from TCAM entry part number. */ 7707 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_slice_number(idx, 7708 fg->flags, &slice_number)); 7709 7710 fs = fg->slices + slice_number; 7711 7712 if (slice_reset == 1) { 7713 /* Clear slice mode in hardware and reset to HW default. */ 7714 BCM_IF_ERROR_RETURN(_field_th_ingress_slice_mode_set(unit, stage_fc, 7715 fs->slice_number, fg, 1)); 7716 } 7717 7718 while (NULL != fs) { 7719 temp_fs = fs->next; 7720 /* Reset the LT partition priority for the slice. */ 7721 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_part_prio_reset(unit, 7722 stage_fc, fg, fs)); 7723 if (slice_reset == 1) { 7724 /* Clear slice if in-use by the group alone. */ 7725 BCM_IF_ERROR_RETURN(_field_th_ingress_slice_clear(unit, fg, fs)); 7726 fs->prev = NULL; 7727 fs->next = NULL; 7728 } 7729 7730 fs = temp_fs; 7731 } 7732 } 7733 7734 /* Free LT_ID association with this group. */ 7735 BCM_IF_ERROR_RETURN(_field_th_group_ltmap_delete(unit, fg)); 7736 7737 /* Install LT Action Priority. */ 7738 BCM_IF_ERROR_RETURN(_bcm_field_th_ingress_lt_action_prio_install(unit, 7739 stage_fc, fg)); 7740 return (BCM_E_NONE); 7741 } 7742 7743 /* 7744 * Function: 7745 * _bcm_field_th_group_lt_prio_update 7746 * Purpose: 7747 * Update a group's logical table action priority value. 7748 * Parameters: 7749 * unit - (IN) BCM device number. 7750 * fg - (IN) Field group. 7751 * priority - (IN) New field group priority value. 7752 * 7753 * Returns: 7754 * BCM_E_XXX 7755 */ 7756 int 7757 _bcm_field_th_group_lt_prio_update(int unit, _field_group_t *fg, 7758 int priority) 7759 { 7760 _field_stage_t *stage_fc; /* Field stage control. */ 7761 int lt_id; /* Logical Table Identifier. */ 7762 _field_group_t *fg_ptr = NULL; 7763 _field_control_t *fc; /* Field control structure. */ 7764 7765 /* Input parameters check. */ 7766 if (NULL == fg) { 7767 return (BCM_E_PARAM); 7768 } 7769 7770 /* Return success if there is no change in group's priority value. */ 7771 if (fg->priority == priority) { 7772 return (BCM_E_NONE); 7773 } 7774 7775 /* Get stage control structure. */ 7776 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 7777 &stage_fc)); 7778 7779 /* Get field control structure. */ 7780 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7781 7782 if (fg->slices == NULL) { 7783 return BCM_E_INTERNAL; 7784 } 7785 7786 do { 7787 /* Retrieve the existing groups associated with the Slice */ 7788 (void)_bcm_field_slice_group_get_next(unit, fg->instance, 7789 fg->stage_id, 7790 fg->slices->slice_number, 7791 &fg_ptr, &fg_ptr); 7792 if ((fg_ptr != NULL) && (fg_ptr != fg)) { 7793 if (!((soc_feature(unit, 7794 soc_feature_sw_mmu_flush_rqe_operation)) 7795 && (fg_ptr->gid == _FP_INTERNAL_RESERVED_EM_ID))) { 7796 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 7797 "Error: Can not set the priority, group's Slice has more" 7798 " than one group.\n\r"))); 7799 return BCM_E_CONFIG; 7800 } 7801 } 7802 } while(fg_ptr != NULL); 7803 7804 /* For exact match stage group priority cannot change 7805 * even if group exist with same priority but in different 7806 * slice. 7807 */ 7808 if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 7809 do { 7810 /* Retrieve the existing groups associated with the priority */ 7811 (void)_bcm_field_th_priority_group_get_next(unit, fg->instance, 7812 fg->stage_id, 7813 priority, 7814 &fg_ptr, &fg_ptr); 7815 if ((fg_ptr != NULL) && (fg_ptr != fg)) { 7816 if (!((soc_feature(unit, 7817 soc_feature_sw_mmu_flush_rqe_operation)) 7818 && (fg_ptr->gid == _FP_INTERNAL_RESERVED_EM_ID))) { 7819 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 7820 "Error: Can not set the priority, exact match" 7821 " group(%d) has same priority.\n\r"), 7822 fg_ptr->gid)); 7823 return BCM_E_CONFIG; 7824 } 7825 } 7826 } while(fg_ptr != NULL); 7827 } 7828 7829 /* Get current Logical Table ID value assigned to the Group. */ 7830 lt_id = fg->lt_id; 7831 7832 /* Update group's priority value. */ 7833 fg->priority = priority; 7834 7835 /* Allocate LT action priority. */ 7836 BCM_IF_ERROR_RETURN(_field_th_lt_priority_alloc(unit, stage_fc, fg, 7837 lt_id)); 7838 7839 /* Update priority value in Group's logical table information structure. */ 7840 fc->lt_info[fg->instance][lt_id]->priority = fg->priority; 7841 7842 /* Install LT part mapping to hardware. */ 7843 BCM_IF_ERROR_RETURN(_bcm_field_th_ingress_logical_table_map_write(unit, 7844 stage_fc, fg)); 7845 7846 return (BCM_E_NONE); 7847 } 7848 7849 /* 7850 * Function: 7851 * _bcm_field_th_group_deinit 7852 * Purpose: 7853 * Destroy field group structure. 7854 * Parameters: 7855 * unit - (IN) BCM device number. 7856 * fg - (IN) Allocated group structure. 7857 * 7858 * Returns: 7859 * BCM_E_NONE - Success 7860 */ 7861 int 7862 _bcm_field_th_group_deinit(int unit, _field_group_t *fg) 7863 { 7864 int rv = BCM_E_NONE; /* OPerational status. */ 7865 _field_control_t *fc; /* Field control structure. */ 7866 int idx; /* Qualifiers iteration index. */ 7867 _field_stage_t *stage_fc; /* Stage field control structure. */ 7868 7869 /* Nothing to do as group is already uninstalled. */ 7870 if (NULL == fg) { 7871 return (BCM_E_NONE); 7872 } 7873 7874 /* Get Field Control structure. */ 7875 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 7876 7877 /* Get device stage control structure. */ 7878 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 7879 &stage_fc)); 7880 7881 /* Uninstall group from every slice. */ 7882 if (NULL != fg->slices) { 7883 _field_th_ingress_group_uninstall(unit, stage_fc, fg); 7884 } 7885 7886 /* Deallocate group qualifiers list. */ 7887 for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) { 7888 /* If qualifier set was updated, free original qualifiers arrary. */ 7889 BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(fg, idx)); 7890 } 7891 7892 /* Decrement the use counts for any UDFs used by the group */ 7893 for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) { 7894 if (SHR_BITGET(fg->qset.udf_map, idx)) { 7895 if (fc->udf[idx].use_count > 0) { 7896 fc->udf[idx].use_count--; 7897 } 7898 } 7899 } 7900 7901 /* Deallocate group entry array if any. */ 7902 if (NULL != fg->entry_arr) { 7903 sal_free(fg->entry_arr); 7904 } 7905 7906 /* Deallocate group LT entry array if any. */ 7907 if (NULL != fg->lt_entry_arr) { 7908 sal_free(fg->lt_entry_arr); 7909 } 7910 /* Free Flowtracker stage extractor codes. */ 7911 #if defined(BCM_FLOWTRACKER_SUPPORT) 7912 if (NULL != fg->ft_ext_codes) { 7913 sal_free(fg->ft_ext_codes); 7914 } 7915 #endif 7916 /* Deallocte the action profile index allocated for group */ 7917 if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id || 7918 _BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) { 7919 for (idx =0; idx < MAX_ACT_PROF_ENTRIES_PER_GROUP;idx++) { 7920 if (-1 != fg->action_profile_idx[idx]) { 7921 rv = soc_profile_mem_delete(unit, 7922 &stage_fc->action_profile[fg->instance], 7923 fg->action_profile_idx[idx]); 7924 BCM_IF_ERROR_RETURN(rv); 7925 } 7926 } 7927 } 7928 7929 rv = _bcm_field_group_stat_destroy(unit, fg->gid); 7930 BCM_IF_ERROR_RETURN(rv); 7931 7932 /* Remove group from unit's group list. */ 7933 BCM_IF_ERROR_RETURN(_bcm_field_group_linked_list_remove(unit, fg)); 7934 7935 /* Decrement Hint count if any. */ 7936 BCM_IF_ERROR_RETURN( 7937 _bcm_field_hints_group_count_update (unit, fg->hintid, 0)); 7938 7939 7940 #if defined (BCM_TRIDENT3_SUPPORT) 7941 if (soc_feature(unit, soc_feature_td3_style_fp)) { 7942 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIncomingOuterVlanId)) { 7943 bcm_field_qualify_t qual = bcmFieldQualifyIncomingOuterVlanId; 7944 7945 rv = _bcm_field_td3_field_bus_cont_sel_remove(unit, fg->instance, 7946 stage_fc, fg, qual); 7947 BCM_IF_ERROR_RETURN(rv); 7948 } 7949 } 7950 #endif /* BCM_TRIDENT3_SUPPORT */ 7951 7952 /* Deallocate group memory. */ 7953 sal_free(fg); 7954 7955 return (BCM_E_NONE); 7956 } 7957 7958 /* 7959 * Function: 7960 * _field_th_group_add_end 7961 * Purpose: 7962 * Group add state machine last/clean up state. 7963 * Parameters: 7964 * unit - (IN) BCM device number. 7965 * fsm_ptr - (IN/OUT) State machine tracking structure. 7966 * Returns: 7967 * BCM_E_XXX 7968 */ 7969 STATIC int 7970 _field_th_group_add_end(int unit, _field_group_add_fsm_t *fsm_ptr) 7971 { 7972 /* Input parameters check. */ 7973 if (NULL == fsm_ptr) { 7974 return (BCM_E_PARAM); 7975 } 7976 7977 /* 7978 * Clear slice size selection group flags. 7979 * These internal flags are valid only at the time of group creation. 7980 * These flags are need not be intersted post group creation. 7981 * Anyways for Autoexpansion, Autoexpansion hint has to be used 7982 * for respective group sizes. 7983 */ 7984 if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_SMALL_SLICE) { 7985 fsm_ptr->fg->flags &= ~_FP_GROUP_SELECT_SMALL_SLICE; 7986 } else if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_LARGE_SLICE) { 7987 fsm_ptr->fg->flags &= ~_FP_GROUP_SELECT_LARGE_SLICE; 7988 } 7989 7990 /* Deallocate Field Group memory on failure. */ 7991 if (fsm_ptr->stage_fc != NULL) { 7992 if (fsm_ptr->stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 7993 7994 if (BCM_FAILURE(fsm_ptr->rv)) { 7995 _bcm_field_th_group_deinit(unit, fsm_ptr->fg); 7996 } 7997 else if (!soc_feature(unit, soc_feature_ifp_action_profiling)) { 7998 if (BCM_FAILURE(fsm_ptr->rv = 7999 _field_group_default_aset_set(unit, fsm_ptr->fg))) { 8000 _bcm_field_th_group_deinit(unit, fsm_ptr->fg); 8001 } 8002 } 8003 } else if ((fsm_ptr->stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) || 8004 (fsm_ptr->stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 8005 if (BCM_FAILURE(fsm_ptr->rv)) { 8006 _bcm_field_th_group_deinit(unit, fsm_ptr->fg); 8007 } 8008 } else { 8009 return (BCM_E_PARAM); 8010 } 8011 } else { 8012 if (BCM_FAILURE(fsm_ptr->rv)) { 8013 _bcm_field_th_group_deinit(unit, fsm_ptr->fg); 8014 } 8015 } 8016 8017 return (fsm_ptr->rv); 8018 } 8019 8020 /* 8021 * Function: 8022 * _field_th_group_add_adjust_lt_map 8023 * Purpose: 8024 * Update slices logical table mapping and priority in hardware. 8025 * Parameters: 8026 * unit - (IN) BCM device number. 8027 * fsm_ptr - (IN/OUT) State machine tracking structure. 8028 * Returns: 8029 * BCM_E_XXX 8030 */ 8031 STATIC int 8032 _field_th_group_add_adjust_lt_map(int unit, _field_group_add_fsm_t *fsm_ptr) 8033 { 8034 /* Input parameter check. */ 8035 if (NULL == fsm_ptr) { 8036 return (BCM_E_PARAM); 8037 } 8038 8039 /* Set current state to be the previous state. */ 8040 fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state; 8041 8042 /* Install LT part mapping to hardware. */ 8043 fsm_ptr->rv = _bcm_field_th_ingress_logical_table_map_write(unit, 8044 fsm_ptr->stage_fc, fsm_ptr->fg); 8045 8046 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END; 8047 8048 return (BCM_E_NONE); 8049 } 8050 8051 /* 8052 * Function: 8053 * _field_th_group_add 8054 * Purpose: 8055 * Create a field processor group 8056 * Parameters: 8057 * unit - (IN) BCM device number. 8058 * fsm_ptr - (IN/OUT) State machine tracking structure. 8059 * Returns: 8060 * BCM_E_PARAM - Null state machine structure pointer. 8061 * BCM_E_UNAVAIL - Unsupported group create option specified. 8062 * BCM_E_RESOURCE - Requested HW resources unavailable 8063 * or Specified QSET cannot be accomodated with available 8064 * hardware resources. 8065 * BCM_E_MEMORY - Memory allocation failure. 8066 * BCM_E_NONE - Success. 8067 */ 8068 STATIC int 8069 _field_th_group_add(int unit, _field_group_add_fsm_t *fsm_ptr) 8070 { 8071 int rv = BCM_E_INTERNAL; /* Operation return status. */ 8072 8073 /* Input parameters check. */ 8074 if (NULL == fsm_ptr) { 8075 return (BCM_E_PARAM); 8076 } 8077 8078 do 8079 { 8080 switch (fsm_ptr->fsm_state) { 8081 case _BCM_FP_GROUP_ADD_STATE_START: 8082 rv = _field_th_group_add_initialize(unit, fsm_ptr); 8083 LOG_DEBUG(BSL_LS_BCM_FP, 8084 (BSL_META_U(unit, 8085 "Completed state->" 8086 "_BCM_FP_GROUP_ADD_STATE_START\r\n"))); 8087 break; 8088 case _BCM_FP_GROUP_ADD_STATE_ALLOC: 8089 rv = _field_th_group_add_alloc(unit, fsm_ptr); 8090 LOG_DEBUG(BSL_LS_BCM_FP, 8091 (BSL_META_U(unit, 8092 "Completed state->" 8093 "_BCM_FP_GROUP_ADD_STATE_ALLOC\r\n"))); 8094 break; 8095 case _BCM_FP_GROUP_ADD_STATE_QSET_UPDATE: 8096 rv = _field_th_group_add_qset_update(unit, fsm_ptr); 8097 LOG_DEBUG(BSL_LS_BCM_FP, 8098 (BSL_META_U(unit, 8099 "Completed state->" 8100 "_BCM_FP_GROUP_ADD_STATE_QSET_UPDATE\r\n"))); 8101 break; 8102 case _BCM_FP_GROUP_ADD_STATE_ASET_VALIDATE: 8103 rv = _field_th_group_add_aset_validate(unit, fsm_ptr); 8104 break; 8105 LOG_DEBUG(BSL_LS_BCM_FP, 8106 (BSL_META_U(unit, 8107 "Completed state->" 8108 "_BCM_FP_GROUP_ADD_STATE_ASET_VALIDATE\r\n"))); 8109 break; 8110 8111 case _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET: 8112 rv = _field_th_group_add_extractor_codes_get(unit, fsm_ptr); 8113 LOG_DEBUG(BSL_LS_BCM_FP, 8114 (BSL_META_U(unit, 8115 "Completed state->" 8116 "_BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET\r\n"))); 8117 break; 8118 case _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE: 8119 rv = _field_th_group_add_qset_alternate(unit, fsm_ptr); 8120 LOG_DEBUG(BSL_LS_BCM_FP, 8121 (BSL_META_U(unit, 8122 "Completed state->" 8123 "_BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE\r\n"))); 8124 break; 8125 case _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE: 8126 rv = _field_th_group_add_slice_allocate(unit, fsm_ptr); 8127 LOG_DEBUG(BSL_LS_BCM_FP, 8128 (BSL_META_U(unit, 8129 "Completed state->" 8130 "_BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE\r\n"))); 8131 break; 8132 case _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS: 8133 rv = _field_th_group_add_cam_compress(unit, fsm_ptr); 8134 LOG_DEBUG(BSL_LS_BCM_FP, 8135 (BSL_META_U(unit, 8136 "Completed state->" 8137 "_BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS\r\n"))); 8138 break; 8139 case _BCM_FP_GROUP_ADD_STATE_ADJUST_VIRTUAL_MAP: 8140 rv = _field_th_group_add_adjust_lt_map(unit, fsm_ptr); 8141 LOG_DEBUG(BSL_LS_BCM_FP, 8142 (BSL_META_U(unit, 8143 "Completed state->" 8144 "_BCM_FP_GROUP_ADD_STATE_ADJUST_VIRTUAL_MAP\r\n"))); 8145 break; 8146 case _BCM_FP_GROUP_ADD_STATE_END: 8147 rv = _field_th_group_add_end(unit, fsm_ptr); 8148 LOG_DEBUG(BSL_LS_BCM_FP, 8149 (BSL_META_U(unit, 8150 "Completed state->" 8151 "_BCM_FP_GROUP_ADD_STATE_END\r\n"))); 8152 return rv; 8153 break; 8154 default: 8155 /* Not a valid switch-case option. */ 8156 return rv; 8157 } 8158 } while(1); 8159 8160 return (rv); 8161 } 8162 8163 /* 8164 * Function: 8165 * _bcm_field_th_group_add 8166 * Purpose: 8167 * Create a field processor group 8168 * Parameters: 8169 * unit - (IN) BCM device number. 8170 * flags - (IN) Input flags. 8171 * gc - (IN/OUT) Group configuration structure pointer. 8172 * Returns: 8173 * BCM_E_PARAM - Null group configuration structure pointer. 8174 * BCM_E_UNAVAIL - Unsupported group create option specified. 8175 * BCM_E_RESOURCE - Requested HW resources unavailable 8176 * or Specified QSET cannot be accomodated with available 8177 * hardware resources. 8178 * BCM_E_MEMORY - Memory allocation failure. 8179 * BCM_E_NONE - Success. 8180 */ 8181 int 8182 _bcm_field_th_group_add(int unit, uint32 flags, 8183 bcm_field_group_config_t *gc) 8184 { 8185 int rv = BCM_E_INTERNAL; /* Operation return status. */ 8186 _field_stage_id_t stage; /* FP stage information. */ 8187 _field_group_add_fsm_t fsm; /* Group creation state machine. */ 8188 _field_control_t *fc; 8189 _field_hints_t *f_ht = NULL; 8190 /* Field hints Structure. */ 8191 _field_hint_t *hint_list = NULL; 8192 /* Field Hints Structure. */ 8193 bcm_field_hint_t *hint_entry; 8194 /* Hint Entry. */ 8195 bcm_pbmp_t all_pbmp; /* Group port bitmap. */ 8196 8197 /* Input parameter check. */ 8198 if (NULL == gc) { 8199 return (BCM_E_PARAM); 8200 } 8201 8202 /* Get unit FP control structure. */ 8203 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 8204 8205 /* 8206 * Check and return error when SMALL or LARGE slice request flag is set 8207 * for TH device. 8208 */ 8209 if ((0 == soc_feature(unit, soc_feature_field_ingress_two_slice_types)) 8210 && (gc->flags & BCM_FIELD_GROUP_CREATE_SMALL 8211 || gc->flags & BCM_FIELD_GROUP_CREATE_LARGE)) { 8212 return (BCM_E_UNAVAIL); 8213 } 8214 8215 8216 /* Get the FP stage in which new group must be created. */ 8217 BCM_IF_ERROR_RETURN(_bcm_field_group_stage_get(unit, &gc->qset, &stage)); 8218 BCM_IF_ERROR_RETURN(_bcm_field_group_stage_validate(unit, stage)); 8219 8220 if (!(gc->flags & BCM_FIELD_GROUP_CREATE_WITH_ID)) { 8221 /* qset and pri are validated in bcm_field_group_create_mode_id(). */ 8222 BCM_IF_ERROR_RETURN(_bcm_field_group_id_generate(unit, &gc->group)); 8223 } 8224 8225 if (soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0) == 1) { 8226 /* 8227 * Return BCM_E_UNAVAIL if soc property FLOWTRACKER_ENABLE is enabled and 8228 * As flow tracker creates ExactMatch group during 8229 * their initialization and User doesn't have provision to create groups under ExactMatch stage. 8230 */ 8231 if ((_BCM_FIELD_STAGE_EXACTMATCH == stage) && 8232 (0 == (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC))) { 8233 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 8234 "Error: ExactMatch Field stage is dedicated to Flowtracker module.\n\r"))); 8235 return BCM_E_UNAVAIL; 8236 } 8237 8238 if ((flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC) && 8239 (_BCM_FIELD_STAGE_EXACTMATCH != stage)){ 8240 /* FLOWTRACKER SPECIFIC flag should be used for EXACTMATCH Stage only */ 8241 return BCM_E_PARAM; 8242 } 8243 8244 /* Check to Restrict EM for internal use */ 8245 if (((_FP_FLOWTRACKER_RESERVED_EM_GID_AFTER_SHIFT) == 8246 ((uint32)gc->group >> (_FP_FLOWTRACKER_RESERVED_EM_GID_SHIFT_VAL))) && 8247 (0 == (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC))) { 8248 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 8249 "Error: Field Group Id : %d is internally reserved for Flowtracker module.\n\r"), 8250 gc->group)); 8251 return BCM_E_UNAVAIL; 8252 } 8253 8254 /* Validation check for flowtracker module to use only reserved _FP_FLOWTRACKER_RESERVED_EM_GID_* GIDs */ 8255 if (((_FP_FLOWTRACKER_RESERVED_EM_GID_AFTER_SHIFT) != 8256 ((uint32)gc->group >> (_FP_FLOWTRACKER_RESERVED_EM_GID_SHIFT_VAL))) && 8257 (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC)) { 8258 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 8259 "Error: Field Group Id : %d is not reserved for Flowtracker module. \n\r"), 8260 gc->group)); 8261 return BCM_E_CONFIG; 8262 } 8263 } else { 8264 if (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC) { 8265 /* FLOWTRACKER SPECIFIC flag should be used only if soc property FLOWTRACKER_ENABLE is enabled */ 8266 return BCM_E_PARAM; 8267 } 8268 } 8269 8270 /* Read device port configuration. */ 8271 BCM_PBMP_CLEAR(all_pbmp); 8272 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 8273 8274 /* Initialize group creation tracking structure. */ 8275 sal_memset(&fsm, 0, sizeof(_field_group_add_fsm_t)); 8276 8277 /* Initialize group creation tracking structure. */ 8278 fsm.fsm_state = _BCM_FP_GROUP_ADD_STATE_START; 8279 fsm.priority = gc->priority; 8280 fsm.group_id = gc->group; 8281 fsm.qset = gc->qset; 8282 fsm.aset = gc->aset; 8283 fsm.rv = BCM_E_NONE; 8284 fsm.action_res_id = gc->action_res_id; 8285 fsm.hintid = gc->hintid; 8286 8287 /* Apply slice selection configuration */ 8288 if (gc->flags & BCM_FIELD_GROUP_CREATE_SMALL) { 8289 fsm.flags |= _BCM_FP_GROUP_ADD_SMALL_SLICE; 8290 } else if (gc->flags & BCM_FIELD_GROUP_CREATE_LARGE) { 8291 fsm.flags |= _BCM_FP_GROUP_ADD_LARGE_SLICE; 8292 } 8293 8294 if (fsm.hintid != 0) { 8295 if (fsm.hintid >= _FP_HINT_ID_MAX) { 8296 LOG_DEBUG(BSL_LS_BCM_FP, 8297 (BSL_META_U(unit, "HintId is out of allowed range\r\n"))); 8298 rv = BCM_E_PARAM; 8299 return (rv); 8300 } 8301 if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, fsm.hintid) == 0) { 8302 LOG_DEBUG(BSL_LS_BCM_FP, 8303 (BSL_META_U(unit, "Trying to attach hintid which is" 8304 " not created.\r\n"))); 8305 rv = BCM_E_NOT_FOUND; 8306 return (rv); 8307 } 8308 if ((BCM_FIELD_QSET_TEST(fsm.qset, bcmFieldQualifyStageExternal)) || 8309 (BCM_FIELD_QSET_TEST(fsm.qset, bcmFieldQualifyStageClass)) || 8310 (BCM_FIELD_QSET_TEST(fsm.qset, bcmFieldQualifyStageClassExactMatch))) { 8311 8312 LOG_DEBUG(BSL_LS_BCM_FP, 8313 (BSL_META_U(unit,"Unsupported hint type attached" 8314 "to hintid(%d).\r\n"), 8315 gc->hintid)); 8316 rv = BCM_E_PARAM; 8317 return (rv); 8318 } 8319 8320 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, gc->hintid, &f_ht)); 8321 if (f_ht == NULL) { 8322 LOG_DEBUG(BSL_LS_BCM_FP, 8323 (BSL_META_U(unit,"Hints are not attached to hintid(%d)." 8324 "\r\n"), 8325 gc->hintid)); 8326 rv = BCM_E_NOT_FOUND; 8327 return (rv); 8328 } 8329 8330 hint_list = f_ht->hints; 8331 while (hint_list != NULL) { 8332 hint_entry = hint_list->hint; 8333 if (hint_entry != NULL) { 8334 /* hint type _field_hints_control_get is not supported for any stage */ 8335 if (hint_entry->hint_type == 8336 bcmFieldHintTypeCompression) { 8337 LOG_DEBUG(BSL_LS_BCM_FP, 8338 (BSL_META_U(unit,"Unsupported hint type attached" 8339 "to hintid(%d).\r\n"), 8340 gc->hintid)); 8341 rv = BCM_E_PARAM; 8342 return (rv); 8343 } 8344 8345 if (!soc_feature(unit, soc_feature_field_ingress_two_slice_types)) { 8346 /* 8347 * For Ingress state, hint type auto expansion is 8348 * supported only for flags BCM_FIELD_GROUP_MAX_SIZE_HARD_LIMIT 8349 */ 8350 if((BCM_FIELD_QSET_TEST(fsm.qset, 8351 bcmFieldQualifyStageIngress)) && 8352 (hint_entry->hint_type == 8353 bcmFieldHintTypeGroupAutoExpansion)) { 8354 8355 if(hint_entry->flags != BCM_FIELD_GROUP_MAX_SIZE_HARD_LIMIT) { 8356 LOG_DEBUG(BSL_LS_BCM_FP, 8357 (BSL_META_U(unit,"Unsupported hint type attached" 8358 "to hintid(%d).\r\n"), 8359 gc->hintid)); 8360 rv = BCM_E_PARAM; 8361 return (rv); 8362 } 8363 } 8364 } 8365 /* for egress and lookup stages, only the hint type 8366 * bcmFieldHintTypeGroupAutoExpansion along with flag 8367 * BCM_FIELD_GROUP_MAX_SIZE_HARD_LIMIT is supported 8368 */ 8369 8370 if ((BCM_FIELD_QSET_TEST(fsm.qset, bcmFieldQualifyStageEgress)) || 8371 (BCM_FIELD_QSET_TEST(fsm.qset, bcmFieldQualifyStageLookup))) { 8372 8373 if(!( (hint_entry->hint_type == 8374 bcmFieldHintTypeGroupAutoExpansion) && 8375 (hint_entry->flags == BCM_FIELD_GROUP_MAX_SIZE_HARD_LIMIT) ) ) { 8376 LOG_DEBUG(BSL_LS_BCM_FP, 8377 (BSL_META_U(unit,"Unsupported hint type attached" 8378 "to hintid(%d).\r\n"), 8379 gc->hintid)); 8380 rv = BCM_E_PARAM; 8381 return (rv); 8382 } 8383 } 8384 } 8385 hint_list = hint_list->next; 8386 } 8387 } 8388 8389 8390 /* Apply group member port configuration. */ 8391 if (gc->flags & BCM_FIELD_GROUP_CREATE_WITH_PORT) { 8392 BCM_PBMP_ASSIGN(fsm.pbmp, gc->ports); 8393 } else { 8394 BCM_PBMP_ASSIGN(fsm.pbmp, all_pbmp); 8395 } 8396 8397 /* Apply group mode configuration */ 8398 if (gc->flags & BCM_FIELD_GROUP_CREATE_WITH_MODE) { 8399 fsm.mode = gc->mode; 8400 } else { 8401 fsm.mode = bcmFieldGroupModeDefault; 8402 } 8403 8404 /* Apply Validate flag if the group needs to be created partially */ 8405 if (flags & _FP_GROUP_CONFIG_VALIDATE) { 8406 fsm.flags |= _FP_GROUP_CONFIG_VALIDATE; 8407 } 8408 8409 /* Validate and Apply group Preselset configuration */ 8410 if (gc->flags & BCM_FIELD_GROUP_CREATE_WITH_PRESELSET) { 8411 fsm.preselset = gc->preselset; 8412 fsm.flags |= BCM_FIELD_GROUP_CREATE_WITH_PRESELSET; 8413 } 8414 8415 switch (stage) { 8416 case _BCM_FIELD_STAGE_LOOKUP: 8417 case _BCM_FIELD_STAGE_EGRESS: 8418 /* Add FP group. */ 8419 rv = _bcm_field_group_add(unit, &fsm); 8420 break; 8421 case _BCM_FIELD_STAGE_EXACTMATCH: 8422 /* Add FP group under EM Stage. */ 8423 rv = _field_th_group_add(unit, &fsm); 8424 if (BCM_SUCCESS(rv) && 8425 (soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0) == 1) && 8426 (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC)) { 8427 /* 8428 * _field_detach shoud not destroy Exact Match groups created by Flow Tracker. 8429 * So Setting _FP_EXACTMATCH_STAGE_SKIP_DETACH flag to retain Exact Match Stage. 8430 */ 8431 fc->flags |= _FP_EXACTMATCH_STAGE_SKIP_DETACH; 8432 } 8433 break; 8434 case _BCM_FIELD_STAGE_INGRESS: 8435 rv = _field_th_group_add(unit, &fsm); 8436 break; 8437 case _BCM_FIELD_STAGE_CLASS: 8438 rv = _bcm_field_th_class_group_add(unit, &fsm, gc->aset); 8439 break; 8440 #if defined(BCM_FLOWTRACKER_SUPPORT) 8441 case _BCM_FIELD_STAGE_FLOWTRACKER: 8442 if ((!soc_feature(unit, soc_feature_field_flowtracker_support)) || 8443 (soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 1) != 1)) { 8444 return (BCM_E_UNAVAIL); 8445 } 8446 rv = _field_th_group_add(unit, &fsm); 8447 break; 8448 #endif 8449 default: 8450 /* Invalid FP stage. */ 8451 return (BCM_E_PARAM); 8452 } 8453 8454 #ifdef BCM_WARM_BOOT_SUPPORT 8455 SOC_CONTROL_LOCK(unit); 8456 SOC_CONTROL(unit)->scache_dirty = 1; 8457 SOC_CONTROL_UNLOCK(unit); 8458 #endif 8459 8460 return (rv); 8461 } 8462 8463 /* 8464 * Function: 8465 * _field_th_ingress_selcodes_update 8466 * Purpose: 8467 * Install Logical table selection rule and TCAM key generation rules in 8468 * hardware. 8469 * Parameters: 8470 * unit - (IN) BCM device number. 8471 * stage_fc - (IN) Stage field control structure. 8472 * fg - (IN) Field group structure. 8473 * lt_fs - (IN) Field logical table slice structure. 8474 * Returns: 8475 * BCM_E_XXX 8476 */ 8477 STATIC int 8478 _field_th_ingress_selcodes_update(int unit, _field_stage_t *stage_fc, 8479 _field_group_t *fg, _field_lt_slice_t *lt_fs) 8480 { 8481 int rv; /* Operation return status. */ 8482 int idx; /* iteration index. */ 8483 _field_control_t *fc; /* Field Control Structure. */ 8484 bcm_field_entry_t lt_entry; /* LT entry ID. */ 8485 _field_lt_entry_t *lt_f_ent; /* LT field entry structure pointer. */ 8486 uint8 part; 8487 int parts_count = 0; /* number of slices allocated for the group. */ 8488 8489 /* Input parameters check. */ 8490 if ((NULL == fg) || (NULL == stage_fc) || (NULL == lt_fs)) { 8491 return (BCM_E_PARAM); 8492 } 8493 8494 /* Field control get. */ 8495 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 8496 8497 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 8498 _field_presel_entry_t *f_presel; 8499 8500 /* 8501 * Create Presel Entries in the LT slice associated with the group 8502 */ 8503 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 8504 if (fg->presel_ent_arr[idx] != NULL) { 8505 f_presel = fg->presel_ent_arr[idx]; 8506 } else { 8507 continue; 8508 } 8509 8510 rv = _field_th_lt_entry_data_config_set(unit, stage_fc, f_presel); 8511 if (BCM_FAILURE(rv)) { 8512 return (rv); 8513 } 8514 8515 /* Install the LT Entry in HW. */ 8516 rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel); 8517 BCM_IF_ERROR_RETURN(rv); 8518 8519 /* Check if the group is expanded across slices. */ 8520 if (f_presel->lt_fs->next != NULL) { 8521 _field_lt_slice_t *lt_part_fs; 8522 _field_presel_entry_t *f_presel_p; 8523 int p, parts_count = -1; 8524 8525 /* Get number of entry parts. */ 8526 rv = _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 8527 &parts_count); 8528 BCM_IF_ERROR_RETURN(rv); 8529 8530 f_presel_p = f_presel; 8531 for (p = 0; (p < parts_count && f_presel_p != NULL); p++) { 8532 lt_part_fs = f_presel_p->lt_fs->next; 8533 for (;lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) { 8534 rv = _field_th_ingress_group_expand_install(unit, stage_fc, 8535 fg, p, lt_part_fs); 8536 BCM_IF_ERROR_RETURN(rv); 8537 } 8538 } 8539 } 8540 } 8541 } else { 8542 rv = _bcm_field_th_entry_tcam_parts_count(unit,fg->flags,&parts_count); 8543 if (BCM_FAILURE(rv)) { 8544 return rv; 8545 } 8546 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 8547 lt_entry = fc->lt_info[0][fg->lt_id]->lt_entry; 8548 } else { 8549 lt_entry = fc->lt_info[fg->instance][fg->lt_id]->lt_entry; 8550 } 8551 BCM_IF_ERROR_RETURN(_field_th_lt_entry_get(unit, lt_entry, 8552 _FP_ENTRY_PRIMARY, <_f_ent)); 8553 8554 for (part = 0; part < parts_count; part++) { 8555 BCM_IF_ERROR_RETURN(_bcm_field_th_group_keygen_profiles_index_alloc( 8556 unit, stage_fc, fg, part)); 8557 8558 BCM_IF_ERROR_RETURN(_field_th_lt_entry_default_data_value_set(unit, 8559 stage_fc, fg, part, lt_f_ent + part)); 8560 lt_f_ent[part].flags |= _FP_ENTRY_DIRTY; 8561 } 8562 BCM_IF_ERROR_RETURN(_field_th_lt_default_entry_install(unit, lt_entry)); 8563 } 8564 8565 return (BCM_E_NONE); 8566 } 8567 8568 int 8569 _bcm_field_th_group_update(int unit, bcm_field_group_t group, bcm_field_qset_t *qset) 8570 { 8571 int rv = BCM_E_NONE; /* Return status. */ 8572 int idx = 0; /* Index Variable. */ 8573 int qid_index = 0; /* Index Variable. */ 8574 int qid; /* Qualifier ID. */ 8575 int parts_count = 0; /* number of slices allocated for the group. */ 8576 uint8 part; /* Group Partition. */ 8577 uint16 *qid_array[_FP_MAX_ENTRY_WIDTH] = { NULL }; 8578 /* Array of qualifiers. */ 8579 uint16 size = 0; /* Total number of qualifiers in 8580 each partition of the group. */ 8581 _field_group_t *fg = NULL; /* Field group operational Structure. */ 8582 _field_group_t *temp_fg = NULL; /* Temp field group operational structure. */ 8583 _field_stage_t *stage_fc = NULL; /* Field Stage operational structure. */ 8584 bcm_field_qset_t temp_qset; /* Temporary qset information. */ 8585 _bcm_field_qual_offset_t *offset_array[_FP_MAX_ENTRY_WIDTH] = { NULL }; 8586 /* Array of qualifiers offset information. */ 8587 _field_group_add_fsm_t fsm_ptr; 8588 _field_presel_entry_t *f_presel; 8589 8590 if(qset == NULL) { 8591 return BCM_E_PARAM; 8592 } 8593 BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg)); 8594 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc)); 8595 8596 sal_memcpy(&temp_qset, qset, sizeof(bcm_field_qset_t)); 8597 8598 for (qid = 0; qid < _bcmFieldQualifyCount; qid++) { 8599 8600 if (BCM_FIELD_QSET_TEST(temp_qset, qid) && 8601 !BCM_FIELD_QSET_TEST(fg->qset, qid) && 8602 IS_POST_MUX_QUALIFIER(qid)) { 8603 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 8604 "FP(unit %d) Verb: Adding new post mux" 8605 "qualifiers to QSET is not supported.\n"), unit)); 8606 return BCM_E_PARAM; 8607 } 8608 8609 if (BCM_FIELD_QSET_TEST(fg->qset, qid)) { 8610 BCM_FIELD_QSET_REMOVE(temp_qset, qid); 8611 } 8612 } 8613 8614 _FP_XGS3_ALLOC(temp_fg, sizeof(_field_group_t), "Temp group for update"); 8615 if (NULL == temp_fg) { 8616 return BCM_E_MEMORY; 8617 } 8618 8619 temp_fg->gid = fg->gid; 8620 temp_fg->flags = fg->flags; 8621 sal_memcpy(&temp_fg->qset, &temp_qset, sizeof(bcm_field_qset_t)); 8622 sal_memcpy(temp_fg->ext_codes, fg->ext_codes, 8623 (sizeof(_field_ext_sel_t) * _FP_MAX_ENTRY_WIDTH)); 8624 sal_memset(&fsm_ptr, 0, sizeof(_field_group_add_fsm_t)); 8625 fsm_ptr.fg = temp_fg; 8626 fsm_ptr.stage_fc = stage_fc; 8627 fsm_ptr.flags = _FP_GROUP_QSET_UPDATE; 8628 rv = _field_th_ext_code_assign(unit, 0, &fsm_ptr); 8629 8630 if (BCM_FAILURE(rv)) { 8631 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 8632 "FP(unit %d) Verb: Processing group QSET.\n"), unit)); 8633 goto cleanup; 8634 } 8635 8636 for (part = 0; part < _FP_MAX_ENTRY_WIDTH; part++) { 8637 size = 0; 8638 8639 size = temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size + 8640 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size; 8641 8642 if (size != 0) { 8643 8644 _FP_XGS3_ALLOC(qid_array[part], size * sizeof(uint16), "Qid Array"); 8645 if (NULL == qid_array[part]) { 8646 rv = BCM_E_MEMORY; 8647 goto cleanup; 8648 } 8649 8650 _FP_XGS3_ALLOC(offset_array[part], size * sizeof(_bcm_field_qual_offset_t), 8651 "Qualifier Offset Array"); 8652 if (NULL == offset_array[part]) { 8653 rv = BCM_E_MEMORY; 8654 goto cleanup; 8655 } 8656 8657 8658 qid_index = 0; 8659 for (idx = 0; idx < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size; idx++) { 8660 8661 sal_memcpy(&qid_array[part][qid_index], 8662 &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr[idx]), 8663 sizeof(uint16)); 8664 8665 sal_memcpy(&offset_array[part][qid_index], 8666 &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr[idx]), 8667 sizeof(_bcm_field_qual_offset_t)); 8668 8669 qid_index++; 8670 8671 } 8672 8673 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size = size; 8674 8675 /* Copy qualifier array and offset array of new 8676 * qualifiers in this partition. 8677 */ 8678 size = temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size; 8679 sal_memcpy(&qid_array[part][qid_index], 8680 temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr, 8681 size * sizeof(uint16)); 8682 8683 sal_memcpy(&offset_array[part][qid_index], 8684 temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr, 8685 size * sizeof(_bcm_field_qual_offset_t)); 8686 8687 if (NULL != fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr) { 8688 sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr); 8689 } 8690 8691 if (NULL != fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr) { 8692 sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr); 8693 } 8694 8695 if (NULL != temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr) { 8696 sal_free(temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr); 8697 } 8698 8699 if (NULL != temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr) { 8700 sal_free(temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr); 8701 } 8702 8703 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr = qid_array[part]; 8704 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr = offset_array[part]; 8705 } 8706 } 8707 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 8708 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 8709 if (fg->presel_ent_arr[idx] != NULL) { 8710 f_presel = fg->presel_ent_arr[idx]; 8711 } else { 8712 continue; 8713 } 8714 parts_count = 0; 8715 rv = _bcm_field_th_lt_entry_tcam_parts_count(unit, 8716 f_presel->group->stage_id, 8717 f_presel->group->flags, &parts_count); 8718 if (BCM_FAILURE(rv)) { 8719 goto cleanup; 8720 } 8721 /* Uninstall entry parts keygen program profile entries from hardware. */ 8722 for (part = 0; part < parts_count; part++) { 8723 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 8724 &stage_fc->keygen_profile[fg->instance].profile, 8725 fg->ext_codes[part].keygen_index)); 8726 } 8727 8728 } 8729 } else { 8730 rv = _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, &parts_count); 8731 if (BCM_FAILURE(rv)) { 8732 goto cleanup; 8733 } 8734 8735 /* Uninstall entry parts keygen program profile entries from hardware. */ 8736 for (part = 0; part < parts_count; part++) { 8737 rv = soc_profile_mem_delete(unit, 8738 &stage_fc->keygen_profile[fg->instance].profile, 8739 fg->ext_codes[part].keygen_index); 8740 if (BCM_FAILURE(rv)) { 8741 goto cleanup; 8742 } 8743 } 8744 } 8745 8746 for (part = 0; part < _FP_MAX_ENTRY_WIDTH; part++) { 8747 offset_array[part] = NULL; 8748 qid_array[part] = NULL; 8749 } 8750 sal_memcpy(fg->ext_codes, temp_fg->ext_codes, 8751 (sizeof(_field_ext_sel_t) * _FP_MAX_ENTRY_WIDTH)); 8752 8753 rv = _field_th_ingress_selcodes_update(unit, stage_fc, fg,fg->lt_slices); 8754 if (BCM_FAILURE(rv)) { 8755 goto cleanup; 8756 } 8757 for (qid = 0; qid < _bcmFieldQualifyCount; qid++) { 8758 if (BCM_FIELD_QSET_TEST(*qset, qid)) { 8759 BCM_FIELD_QSET_ADD(fg->qset, qid); 8760 } 8761 } 8762 8763 cleanup: 8764 for (part = 0; part < _FP_MAX_ENTRY_WIDTH; part++) { 8765 if (NULL != qid_array[part]) { 8766 sal_free(qid_array[part]); 8767 qid_array[part] = NULL; 8768 } 8769 8770 if(NULL != offset_array[part]) { 8771 sal_free(offset_array[part]); 8772 offset_array[part] = NULL; 8773 } 8774 } 8775 8776 if (NULL != temp_fg) { 8777 sal_free(temp_fg); 8778 } 8779 8780 return (rv); 8781 } 8782 /* 8783 * Function: _bcm_field_th_find_empty_slice 8784 * 8785 * Purpose: 8786 * Get a new slice for an existing group if available. 8787 * Used for auto-expansion of groups 8788 * Currently: supported in Raptor, Firebolt2. 8789 * 8790 * Parameters: 8791 * unit - (IN) BCM device number 8792 * fg - (IN) field group 8793 * fs_ptr - (IN/OUT) _field_slice_t for the PRIMARY if there is one available. 8794 * 8795 * Returns: 8796 * BCM_E_xxx 8797 */ 8798 int 8799 _bcm_field_th_find_empty_slice(int unit, _field_group_t *fg, 8800 _field_slice_t **fs_ptr) 8801 { 8802 _field_control_t *fc = NULL; /* Field control structure. */ 8803 _field_stage_t *stage_fc = NULL; /* Field stage control. */ 8804 _field_slice_t *fs = NULL; /* Field slice pointer. */ 8805 uint8 slice_idx = 0; /* Slice iterator. */ 8806 int parts_count = 0; /* Number of entry parts. */ 8807 uint32 entry_flags = 0; /* Field entry part flags. */ 8808 int rv = BCM_E_NONE; /* Operation return status. */ 8809 int lt_part_prio = 0; /* LT Partition priority. */ 8810 int part_index = 0; 8811 uint8 old_physical_slice = 0; /* Last slice in group. */ 8812 uint8 new_physical_slice = 0; /* Allocated slice. */ 8813 _field_group_t *curr_fg = NULL; 8814 _field_group_t *next_fg = NULL; 8815 uint8 *slice_arr = NULL; 8816 8817 /* Get field control structure. */ 8818 rv = _field_control_get(unit, &fc); 8819 BCM_IF_ERROR_RETURN(rv); 8820 8821 /* Get stage field control structure. */ 8822 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 8823 BCM_IF_ERROR_RETURN(rv); 8824 8825 if (0 == (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION)) { 8826 return (BCM_E_RESOURCE); 8827 } 8828 8829 fs = &fg->slices[0]; 8830 while (fs->next != NULL) { 8831 fs = fs->next; 8832 } 8833 old_physical_slice = fs->slice_number; 8834 8835 _FP_XGS3_ALLOC(slice_arr, sizeof(uint8) * stage_fc->tcam_slices, 8836 "Slice Array"); 8837 if (NULL == slice_arr) { 8838 return BCM_E_MEMORY; 8839 } 8840 8841 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 8842 slice_arr[slice_idx] = slice_idx; 8843 } 8844 8845 if ((fg->flags & _FP_GROUP_AUTO_EXPAND_SMALL_SLICE) 8846 || (fg->flags & _FP_GROUP_AUTO_EXPAND_LARGE_SLICE)){ 8847 /* Sort the slice array based on requested slice sizes */ 8848 rv = _field_fill_slice_array(unit, fg, slice_arr); 8849 BCM_IF_ERROR_CLEANUP(rv); 8850 } 8851 8852 /* 8853 * Find an empty slice 8854 * Validate the ports and mode 8855 */ 8856 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 8857 if (slice_arr[slice_idx] == old_physical_slice) { 8858 continue; 8859 } 8860 8861 rv = _bcm_field_th_group_add_slice_validate(unit, stage_fc, fg, 8862 slice_arr[slice_idx]); 8863 if (BCM_SUCCESS(rv)) { 8864 uint8 empty; 8865 8866 fs = stage_fc->slices[fg->instance] + slice_arr[slice_idx]; 8867 BCM_IF_ERROR_CLEANUP(_field_th_slice_is_empty(unit, fs, &empty)); 8868 if (empty == TRUE) { 8869 break; 8870 } 8871 } 8872 } 8873 8874 if (slice_idx == stage_fc->tcam_slices) { 8875 /* No free slice; attempt to compress existing auto expanded groups. */ 8876 rv = _field_th_stage_group_compress(unit, fc, stage_fc); 8877 BCM_IF_ERROR_CLEANUP(rv); 8878 8879 /* Retry slice allocation. */ 8880 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 8881 _field_slice_t *fs_next = NULL; 8882 uint8 curr_grp_slice = 0; 8883 8884 for (fs_next = &fg->slices[0]; fs_next; fs_next = fs_next->next) { 8885 /* Don't use current group's slices */ 8886 if (fs_next->slice_number == slice_arr[slice_idx]) { 8887 curr_grp_slice = 1; 8888 break; 8889 } 8890 } 8891 8892 if (1 != curr_grp_slice) { 8893 rv = _bcm_field_th_group_add_slice_validate(unit, stage_fc, fg, 8894 slice_arr[slice_idx]); 8895 if (BCM_SUCCESS(rv)) { 8896 break; 8897 } 8898 } 8899 } 8900 8901 if (slice_idx == stage_fc->tcam_slices) 8902 { 8903 /* No free slice */ 8904 rv = BCM_E_RESOURCE; 8905 BCM_IF_ERROR_CLEANUP(rv); 8906 } 8907 } 8908 8909 new_physical_slice = slice_arr[slice_idx]; 8910 8911 /* Get number of entry parts for the group. */ 8912 rv = _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, &parts_count); 8913 BCM_IF_ERROR_CLEANUP(rv); 8914 8915 /* Retrieve the partition priority value for wide mode group's slices.*/ 8916 rv = _bcm_field_th_lt_part_prio_value_get(unit, fg, <_part_prio); 8917 BCM_IF_ERROR_CLEANUP(rv); 8918 8919 /* Set up the new physical slice parameters in Software */ 8920 for(part_index = 0; part_index < parts_count; part_index++) { 8921 /* Get entry flags. */ 8922 rv = _bcm_field_th_tcam_part_to_entry_flags(unit, part_index, fg->flags, 8923 &entry_flags); 8924 BCM_IF_ERROR_CLEANUP(rv); 8925 8926 /* Get slice id for entry part */ 8927 rv = _bcm_field_th_tcam_part_to_slice_number(part_index, fg->flags, 8928 &slice_arr[slice_idx]); 8929 BCM_IF_ERROR_CLEANUP(rv); 8930 8931 /* Get slice pointer. */ 8932 fs = stage_fc->slices[fg->instance] + new_physical_slice 8933 + slice_arr[slice_idx]; 8934 8935 /* Enable slice. */ 8936 if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) { 8937 /* 8938 * Initialize slice free entries count value based on group 8939 * flags. 8940 */ 8941 #if defined(BCM_TOMAHAWK3_SUPPORT) 8942 if (SOC_IS_TOMAHAWK3(unit) && 8943 (fg->stage_id == _BCM_FIELD_STAGE_INGRESS)) { 8944 fs->free_count = fs->entry_count; 8945 } else 8946 #endif 8947 { 8948 if ((fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) 8949 && !(fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 8950 fs->free_count = fs->entry_count; 8951 } else { 8952 fs->entry_count >>= 1; 8953 fs->free_count = fs->entry_count; 8954 fs->start_tcam_idx >>= 1; 8955 } 8956 } 8957 8958 /* Set group flags in in slice.*/ 8959 fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK; 8960 8961 /* Add slice to slices linked list . */ 8962 stage_fc->slices[fg->instance][old_physical_slice + slice_arr[slice_idx]].next = fs; 8963 fs->prev = 8964 &stage_fc->slices[fg->instance][old_physical_slice + slice_arr[slice_idx]]; 8965 } 8966 8967 curr_fg = NULL; 8968 next_fg = NULL; 8969 do { 8970 rv = _bcm_field_slice_group_get_next(unit, fg->instance, 8971 fg->stage_id, 8972 old_physical_slice, 8973 &curr_fg, &next_fg); 8974 /* Mark it as SUCCESS when you reach the end of the group's slices */ 8975 if (BCM_E_NOT_FOUND == rv) { 8976 rv = BCM_E_NONE; 8977 break; 8978 } else if (BCM_FAILURE(rv)) { 8979 break; 8980 } 8981 8982 /* 8983 * Install TCAM keygen program configuration in hardware for all 8984 * the groups for each slice. 8985 */ 8986 rv = _field_th_ingress_group_expand_slice_install(unit, stage_fc, 8987 next_fg, 8988 new_physical_slice + slice_arr[slice_idx], 8989 part_index, lt_part_prio); 8990 BCM_IF_ERROR_CLEANUP(rv); 8991 curr_fg = next_fg; 8992 } while (next_fg != NULL); 8993 } 8994 8995 *fs_ptr = stage_fc->slices[fg->instance] + new_physical_slice; 8996 8997 cleanup: 8998 if (NULL != slice_arr) { 8999 sal_free(slice_arr); 9000 slice_arr = NULL; 9001 } 9002 return (rv); 9003 } 9004 9005 /* 9006 * Function: _bcm_field_th_group_enable_set 9007 * 9008 * Purpose: 9009 * To enable/diable the field group operational status. 9010 * Parameters: 9011 * unit - (IN) BCM device number 9012 * group - (IN) field group 9013 * enable - (IN) enable (or) disbale flag. 9014 * 9015 * Returns: 9016 * BCM_E_xxx 9017 */ 9018 int 9019 _bcm_field_th_group_enable_set(int unit, bcm_field_group_t group, uint32 enable) 9020 { 9021 int rv; /* operational status */ 9022 int tcam_idx[_FP_MAX_ENTRY_WIDTH]; /* Entry TCAM index. */ 9023 int parts_count = -1; /* Parts count. */ 9024 int idx; /* Temporary pointer variable. */ 9025 uint32 entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; /* Entry buffer. */ 9026 _field_group_t *fg; /* Field Group Structure. */ 9027 soc_mem_t lt_tcam_mem; /* TCAM memory ID. */ 9028 bcm_field_entry_t lt_entry; /* Logical table entry. */ 9029 _field_lt_entry_t *lt_f_ent; /* Field LT entry pointer. */ 9030 _field_stage_t *stage_fc; /* Stage Field control structure. */ 9031 _field_control_t *fc; /* Field Control Strucutre. */ 9032 9033 /* Field control get. */ 9034 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 9035 9036 /* Get the group control pointer. */ 9037 BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg)); 9038 9039 /* Get the stage control structure. */ 9040 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 9041 fg->stage_id, &stage_fc)); 9042 9043 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 9044 return _bcm_field_th_group_presel_enable_set(unit, stage_fc, fg, enable); 9045 } 9046 9047 lt_entry = fc->lt_info[fg->instance][fg->lt_id]->lt_entry; 9048 9049 /* Get all part of the entry. */ 9050 BCM_IF_ERROR_RETURN(_field_th_lt_entry_get_by_id(unit, lt_entry, 9051 <_f_ent)); 9052 9053 /* Get number of entry parts. */ 9054 rv = _bcm_field_th_entry_tcam_parts_count(unit, lt_f_ent->group->flags, 9055 &parts_count); 9056 BCM_IF_ERROR_RETURN(rv); 9057 9058 for (idx = 0; idx < parts_count; idx++) { 9059 rv = _field_th_lt_entry_tcam_idx_get(unit, lt_f_ent + idx, 9060 (lt_f_ent + idx)->lt_fs, tcam_idx + idx); 9061 BCM_IF_ERROR_RETURN(rv); 9062 } 9063 9064 /* 9065 * Get TCAM view to be used for programming the hardware based on the group 9066 * operational mode. 9067 */ 9068 rv = _field_th_lt_tcam_mem_get(unit, stage_fc, lt_f_ent, <_tcam_mem); 9069 BCM_IF_ERROR_RETURN(rv); 9070 9071 for (idx = 0; idx < parts_count; idx++) { 9072 /* 9073 * Maximum index value for entry in this TCAM is limited to 9074 * No. of slices * No. of LT_IDs/slice (12 * 32 == 384). 9075 */ 9076 if ((tcam_idx[idx] < soc_mem_index_min(unit, lt_tcam_mem)) 9077 || (tcam_idx[idx] > (stage_fc->lt_tcam_sz - 1) )) { 9078 return (BCM_E_PARAM); 9079 } 9080 9081 /* Clear entry buffer. */ 9082 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS); 9083 9084 /* Read entry into SW buffer. */ 9085 rv = soc_th_ifp_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY, tcam_idx[idx], 9086 entry); 9087 BCM_IF_ERROR_RETURN(rv); 9088 9089 /*valid bit in th2 is two bit width*/ 9090 #if defined(BCM_TOMAHAWK2_SUPPORT) 9091 if (soc_feature(unit, soc_feature_field_multi_pipe_enhanced) && 9092 _BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 9093 enable = enable ? 3 : 0; 9094 } else 9095 #endif /* BCM_TOMAHAWK2_SUPPORT */ 9096 { 9097 enable = enable ? (soc_feature(unit, soc_feature_td3_style_fp) ? 3 : 1) : 0; 9098 } 9099 soc_mem_field32_set(unit, lt_tcam_mem, entry, VALIDf, enable); 9100 9101 /* Install entry in hardware. */ 9102 rv = soc_th_ifp_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, tcam_idx[idx], 9103 entry); 9104 BCM_IF_ERROR_RETURN(rv); 9105 } 9106 9107 /* Enable/Disable group flags. */ 9108 if (enable) { 9109 fg->flags |= _FP_GROUP_LOOKUP_ENABLED; 9110 } else { 9111 fg->flags &= ~_FP_GROUP_LOOKUP_ENABLED; 9112 } 9113 9114 return BCM_E_NONE; 9115 } 9116 9117 /* 9118 * Function: 9119 * _bcm_field_th_group_status_calc 9120 * Purpose: 9121 * Fill in the values of a group status structure. 9122 * Parameters: 9123 * unit - (IN) BCM device number. 9124 * fg - (IN/OUT) Group to update the status structure. 9125 * Returns: 9126 * BCM_E_NONE - Success. 9127 */ 9128 int 9129 _bcm_field_th_group_status_calc(int unit, _field_group_t *fg) 9130 { 9131 bcm_field_group_status_t *status; /* Group status structure pointer. */ 9132 _field_stage_t *stage_fc; /* Stage field control structure. */ 9133 _field_stage_t *stage_ingress; /* Stage field control structure. */ 9134 _field_slice_t *fs; /* Field slice control structure. */ 9135 int count = 0; /* Generic purposes counter. */ 9136 int rv = BCM_E_NONE; /* Operation return status. */ 9137 int slice_index; /* Hardware slice index. */ 9138 uint8 single_wide = 0; /* Single wide group indicator. */ 9139 9140 /* Input parameter check. */ 9141 if (NULL == fg) { 9142 return (BCM_E_PARAM); 9143 } 9144 9145 /* Get field group stage control structure. */ 9146 BCM_IF_ERROR_RETURN 9147 (_field_stage_control_get(unit, fg->stage_id, &stage_fc)); 9148 9149 /* Get field group status structure pointer. */ 9150 status = &fg->group_status; 9151 if (NULL == status) { 9152 return (BCM_E_INTERNAL); 9153 } 9154 9155 /* Get group primary slice structure pointer. */ 9156 fs = &fg->slices[0]; 9157 9158 /* Get field group intraslice double wide status. */ 9159 single_wide = ((fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) 9160 && !(fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) ? 1 : 0; 9161 9162 if (SOC_IS_TOMAHAWK3(unit)) { 9163 single_wide = (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE); 9164 } 9165 9166 status->entries_total = 0; 9167 status->entries_free = 0; 9168 9169 if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 9170 int slice = 0; 9171 /* Retreive Slice Instance. */ 9172 fs = stage_fc->slices[fg->instance]; 9173 /* Calculate free entry count. */ 9174 for (slice = 0; slice < stage_fc->tcam_slices; slice++) { 9175 status->entries_free += fs[slice].free_count; 9176 status->entries_total += fs[slice].entry_count; 9177 } 9178 #if defined(BCM_FLOWTRACKER_SUPPORT) 9179 } else if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 9180 single_wide = (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) ? 0 : 1; 9181 fs = stage_fc->slices[fg->instance]; 9182 if (single_wide) { 9183 status->entries_total = fs->entry_count; 9184 status->entries_free = fs->free_count; 9185 } else { 9186 status->entries_total = (fs->entry_count / 2); 9187 status->entries_free = (fs->free_count / 2); 9188 } 9189 #endif 9190 } else { 9191 /* Calculate total entries count in slices allocated for the group. */ 9192 while (NULL != fs) { 9193 status->entries_total += fs->entry_count; 9194 fs = fs->next; 9195 } 9196 9197 /* Calculate total free entries count in slices allocated for the group. */ 9198 status->entries_free = 0; 9199 fs = &fg->slices[0]; 9200 while (NULL != fs) { 9201 /* Get free entries count in the slice. */ 9202 _bcm_field_entries_free_get(unit, fs, fg, &count); 9203 status->entries_free += count; 9204 fs = fs->next; 9205 } 9206 } 9207 9208 if (_BCM_FIELD_STAGE_FLOWTRACKER != fg->stage_id) { 9209 rv = _bcm_field_th_flex_counter_status_get(unit, fg, 9210 &(status->counters_total), 9211 &(status->counters_free)); 9212 } 9213 BCM_IF_ERROR_RETURN(rv); 9214 /* 9215 * Calculate total counters and meters count, free counters and meters 9216 * count. 9217 */ 9218 fs = fg->slices; 9219 9220 /* ExactMatch stage doesnt have meter pool seperately. 9221 * It uses the meters allocated to ingress stage. 9222 */ 9223 if(_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) 9224 { 9225 /* Get ingress field group stage control structure. */ 9226 BCM_IF_ERROR_RETURN 9227 (_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_ingress)); 9228 9229 status->meters_total = _bcm_field_meters_total_get(stage_ingress, 9230 fg->instance, fs); 9231 status->meters_free = _bcm_field_meter_free_get(stage_ingress, 9232 fg, fs); 9233 } else { 9234 9235 status->meters_total = _bcm_field_meters_total_get(stage_fc, fg->instance, 9236 fs); 9237 status->meters_free = _bcm_field_meter_free_get(stage_fc, fg, 9238 fs); 9239 } 9240 /* 9241 * Calculate total entries count and total free entries count for the group 9242 * if it expands to other available slices. 9243 */ 9244 if (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION) { 9245 for (slice_index = 0; slice_index < stage_fc->tcam_slices; 9246 ++slice_index) { 9247 /* Ignore the secondary and tertiary slices */ 9248 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) || 9249 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) { 9250 if (fg->slices[1].slice_number == slice_index) { 9251 continue; 9252 } 9253 } 9254 if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 9255 if (fg->slices[2].slice_number == slice_index) { 9256 continue; 9257 } 9258 } 9259 /*Ignore the primary slice as well as this is already accounted for*/ 9260 if (fg->slices[0].slice_number == slice_index) { 9261 continue; 9262 } 9263 9264 rv = _bcm_field_th_group_add_slice_validate(unit, stage_fc, fg, 9265 slice_index); 9266 if (BCM_SUCCESS(rv)) { 9267 fs = stage_fc->slices[fg->instance] + slice_index; 9268 if (single_wide) { 9269 status->entries_total += fs->entry_count; 9270 status->entries_free += fs->free_count; 9271 } else { 9272 if (SOC_IS_TOMAHAWK3(unit)) { 9273 status->entries_total += fs->entry_count; 9274 status->entries_free += fs->free_count; 9275 } else { 9276 status->entries_total += (fs->entry_count / 2); 9277 status->entries_free += (fs->free_count / 2); 9278 } 9279 } 9280 } 9281 } 9282 } 9283 9284 return (BCM_E_NONE); 9285 } 9286 9287 /* 9288 * Function: 9289 * _field_th_ingress_default_group_expand_install 9290 * Purpose: 9291 * Allocate and Install LT Entries in a group expanded slice. 9292 * Parameters: 9293 * unit - (IN) BCM device number. 9294 * stage_fc - (IN) Reference to Field Stage structure. 9295 * fg - (IN) Reference to Field Group structure. 9296 * entry_part - (IN) Slice Entry Part. 9297 * lt_fs - (IN) Reference to LT expanded slice. 9298 * Returns: 9299 * BCM_E_xxx. 9300 */ 9301 int 9302 _field_th_ingress_default_group_expand_install(int unit, 9303 _field_stage_t *stage_fc, 9304 _field_group_t *fg, 9305 int entry_part, 9306 _field_lt_slice_t *lt_fs) 9307 { 9308 int rv; 9309 int parts_count = -1; 9310 int part; 9311 uint8 slice_attached = 0; 9312 _field_lt_slice_t *lt_part_fs = NULL; 9313 _field_lt_entry_t *lt_f_entry; 9314 _field_lt_entry_t *lt_f_entry_p = NULL; 9315 _field_control_t *fc; 9316 bcm_field_entry_t lt_entry; 9317 9318 /* Input parameters check. */ 9319 if ((NULL == fg) || (NULL == stage_fc) || (NULL == lt_fs)) { 9320 return (BCM_E_PARAM); 9321 } 9322 9323 /* Field control get. */ 9324 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 9325 9326 if ((fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) != 0) { 9327 return BCM_E_INTERNAL; 9328 } 9329 9330 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 9331 "\n\r%s(): fg:%p fg->gid:%d lt_fs:%p slice_number:%d entry_part:%d\n\r"), 9332 __func__, fg, fg->gid, lt_fs, lt_fs->slice_number, entry_part)); 9333 9334 9335 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 9336 lt_entry = fc->lt_info[0][fg->lt_id]->lt_entry; 9337 } else { 9338 lt_entry = fc->lt_info[fg->instance][fg->lt_id]->lt_entry; 9339 } 9340 9341 /* Get all part of the entry. */ 9342 BCM_IF_ERROR_RETURN(_field_th_lt_entry_get_by_id(unit, 9343 lt_entry, <_f_entry)); 9344 9345 /* Get number of entry parts. */ 9346 rv = _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 9347 &parts_count); 9348 BCM_IF_ERROR_RETURN(rv); 9349 9350 for (part = 0; part < parts_count; part++) { 9351 if (part == entry_part) { 9352 lt_f_entry_p = lt_f_entry + part; 9353 break; 9354 } 9355 } 9356 9357 if (lt_f_entry_p == NULL) { 9358 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 9359 "Error[%d]: LT Part[%d]-entry_part[%d] entry is NULL," 9360 " lt_f_entry->eid:%d\n\r"), 9361 rv, part, entry_part, lt_f_entry->eid)); 9362 return BCM_E_INTERNAL; 9363 } 9364 9365 /* Get entry part flags. */ 9366 rv = _bcm_field_th_tcam_part_to_entry_flags(unit, part, fg->flags, 9367 &(lt_f_entry_p->flags)); 9368 if (BCM_FAILURE(rv)) { 9369 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 9370 "LT entry part flags get failed.\n\r"))); 9371 return rv; 9372 } 9373 9374 /* Given primary entry TCAM index calculate entry part tcam index. */ 9375 if (0 != part) { 9376 lt_f_entry_p->index = lt_f_entry->index; 9377 } 9378 9379 /* Check if the given lt slice is already associated to the entry. */ 9380 lt_part_fs = lt_f_entry_p->lt_fs; 9381 for (; lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) { 9382 if (lt_part_fs == lt_fs) { 9383 slice_attached = 1; 9384 break; 9385 } 9386 } 9387 9388 if (slice_attached == 0) { 9389 /* Attach the expanded slice for the part entry. */ 9390 lt_part_fs = lt_f_entry_p->lt_fs; 9391 for (; lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) { 9392 if (lt_part_fs->next == NULL) { 9393 lt_part_fs->next = lt_fs; 9394 lt_part_fs->next->next = NULL; 9395 lt_part_fs->next->prev = lt_part_fs; 9396 break; 9397 } 9398 } 9399 } 9400 9401 /* Mark entry dirty. */ 9402 lt_f_entry_p->flags |= _FP_ENTRY_DIRTY; 9403 9404 /* Update LT Slices. */ 9405 /* Decrement slice free entry count for primary entries. */ 9406 lt_fs->free_count--; 9407 /* Assign entry to a slice. */ 9408 lt_fs->entries[lt_f_entry_p->index] = lt_f_entry_p; 9409 9410 for (part = 0; part < parts_count; part++) { 9411 lt_f_entry_p = lt_f_entry + part; 9412 9413 if (entry_part == part) { 9414 break; 9415 } 9416 } 9417 9418 /* Install the LT Entry in HW. */ 9419 rv = _field_th_lt_default_tcam_entry_install(unit, lt_f_entry_p->eid, 1, 9420 entry_part, lt_fs); 9421 if (BCM_FAILURE(rv)) { 9422 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 9423 "LT TCAM entry install failed[%d].\n\r"), rv)); 9424 return rv; 9425 } 9426 9427 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 9428 "-----------------------------------------------------\n\r"))); 9429 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, "default_group_expand_install():" 9430 "lt_f_entry:%p eid:%d lt_fs:%p slice_num:%d slice_idx:%d\n\r"), 9431 lt_f_entry, lt_f_entry->eid, lt_fs,lt_fs->slice_number,lt_f_entry->index)); 9432 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 9433 "-----------------------------------------------------\n\r"))); 9434 9435 return rv; 9436 } 9437 9438 /* 9439 * Function: 9440 * _field_th_ingress_group_expand_install 9441 * Purpose: 9442 * Allocate and Install Presel Entries in a group expanded slice. 9443 * Parameters: 9444 * unit - (IN) BCM device number. 9445 * stage_fc - (IN) Reference to Field Stage structure. 9446 * fg - (IN) Reference to Field Group structure. 9447 * entry_part - (IN) Slice Entry Part. 9448 * lt_fs - (IN) Reference to LT expanded slice. 9449 * Returns: 9450 * BCM_E_xxx. 9451 */ 9452 STATIC int 9453 _field_th_ingress_group_expand_install(int unit, _field_stage_t *stage_fc, 9454 _field_group_t *fg, int entry_part, 9455 _field_lt_slice_t *lt_fs) 9456 { 9457 int rv, idx; 9458 int parts_count = -1; 9459 int part; 9460 uint8 slice_attached = 0; 9461 _field_lt_slice_t *lt_part_fs; 9462 _field_presel_entry_t *f_presel_p; 9463 _field_presel_entry_t *f_presel; 9464 9465 /* Input parameters check. */ 9466 if ((NULL == fg) || (NULL == stage_fc) || (NULL == lt_fs)) { 9467 return (BCM_E_PARAM); 9468 } 9469 9470 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 9471 "%s(): fg:%p fg->gid:%d lt_fs:%p slice_number:%d entry_part:%d\n\r"), 9472 __func__, fg, fg->gid, lt_fs, lt_fs->slice_number, entry_part)); 9473 9474 f_presel = fg->presel_ent_arr[0]; 9475 if (f_presel == NULL) { 9476 return BCM_E_INTERNAL; 9477 } 9478 9479 /* Get number of entry parts. */ 9480 rv = _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, 9481 &parts_count); 9482 BCM_IF_ERROR_RETURN(rv); 9483 9484 f_presel_p = f_presel; 9485 for (part = 0; (part < parts_count && f_presel_p != NULL); part++) { 9486 if (part == entry_part) { 9487 break; 9488 } 9489 f_presel_p = f_presel_p->next; 9490 } 9491 9492 if (f_presel_p == NULL || part >= parts_count) { 9493 return BCM_E_INTERNAL; 9494 } 9495 9496 /* Get entry part flags. */ 9497 rv = _bcm_field_th_tcam_part_to_entry_flags(unit, part, fg->flags, 9498 &(f_presel_p->flags)); 9499 BCM_IF_ERROR_RETURN(rv); 9500 9501 /* Given primary entry TCAM index calculate entry part tcam index. */ 9502 if (0 != part) { 9503 f_presel_p->hw_index = f_presel->hw_index; 9504 } 9505 9506 /* Check if the given lt slice is already associated to the presel entry. */ 9507 lt_part_fs = f_presel_p->lt_fs; 9508 for (; lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) { 9509 if (lt_part_fs == lt_fs) { 9510 slice_attached = 1; 9511 break; 9512 } 9513 } 9514 9515 if (slice_attached == 0) { 9516 /* Attach the expanded slice for the part entry. */ 9517 lt_part_fs = f_presel_p->lt_fs; 9518 for (; lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) { 9519 if (lt_part_fs->next == NULL) { 9520 lt_part_fs->next = lt_fs; 9521 lt_part_fs->next->next = NULL; 9522 lt_part_fs->next->prev = lt_part_fs; 9523 break; 9524 } 9525 } 9526 } 9527 9528 if (lt_part_fs == NULL) { 9529 return BCM_E_INTERNAL; 9530 } 9531 9532 /* Mark entry dirty. */ 9533 f_presel_p->flags |= _FP_ENTRY_DIRTY; 9534 9535 /* Update Presel LT Slices. */ 9536 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 9537 if (fg->presel_ent_arr[idx] != NULL) { 9538 f_presel = fg->presel_ent_arr[idx]; 9539 } else { 9540 continue; 9541 } 9542 9543 f_presel_p = f_presel; 9544 for (part = 0; (part < parts_count && f_presel_p != NULL); part++) { 9545 if (entry_part == part) { 9546 break; 9547 } 9548 f_presel_p = f_presel_p->next; 9549 } 9550 9551 if (f_presel_p == NULL || part == parts_count) { 9552 return BCM_E_INTERNAL; 9553 } 9554 9555 lt_part_fs = f_presel_p->lt_fs; 9556 for (; lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) { 9557 /* Goto the last slice. */ 9558 if (lt_part_fs->next == NULL) { 9559 /* Decrement slice free entry count for primary entries. */ 9560 lt_part_fs->free_count--; 9561 /* Assign entry to a slice. */ 9562 lt_part_fs->p_entries[f_presel_p->hw_index] = f_presel_p; 9563 break; 9564 } 9565 } 9566 9567 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 9568 "-----------------------------------------------------\n\r"))); 9569 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, "group_expand_install():" 9570 "f_presel_p:%p presel:%d lt_fs:%p slice_num:%d slice_idx:%d\n\r"), 9571 f_presel_p,f_presel_p->presel_id,lt_fs,lt_fs->slice_number, 9572 f_presel_p->hw_index)); 9573 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 9574 "-----------------------------------------------------\n\r"))); 9575 9576 /* Install the LT Entry in HW. */ 9577 rv = _bcm_field_th_lt_entry_install(unit, f_presel_p, lt_fs); 9578 BCM_IF_ERROR_RETURN(rv); 9579 } 9580 9581 9582 return BCM_E_NONE; 9583 } 9584 9585 9586 9587 /* 9588 * Function: 9589 * _field_th_ingress_group_expand_slice_install 9590 * Purpose: 9591 * Auxiliary routine used to install field group in hardware 9592 * for a given slice. 9593 * Parameters: 9594 * unit - (IN) BCM device number. 9595 * stage_fc - (IN) Installed group structure. 9596 * fg - (IN/OUT) Field group structure. 9597 * slice_number - (IN) Slice number group installed in. 9598 * part_index - (IN) Entry Part Index. 9599 * group_slice_prio - (IN) Group's Priority for the particular slice. 9600 * Returns: 9601 * BCM_E_XXX 9602 */ 9603 STATIC int 9604 _field_th_ingress_group_expand_slice_install(int unit, _field_stage_t *stage_fc, 9605 _field_group_t *fg, uint8 slice_number, 9606 int part_index, int group_slice_prio) 9607 { 9608 int rv; 9609 _field_lt_slice_t *lt_fs; /* LT Slice pointer. */ 9610 _field_slice_t *fs; /* Field slice structure pointer. */ 9611 _field_control_t *fc; /* Field control structure. */ 9612 9613 /* Input parameters check. */ 9614 if ((NULL == stage_fc) || (NULL == fg) || (NULL == fg->lt_slices)) { 9615 return (BCM_E_PARAM); 9616 } 9617 9618 /* Get field control structure. */ 9619 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 9620 9621 /* Get LT entry part slice control structure. */ 9622 lt_fs = stage_fc->lt_slices[fg->instance] + slice_number; 9623 9624 /* Set slice mode in hardware based on Group mode/flags. */ 9625 BCM_IF_ERROR_RETURN(_field_th_ingress_slice_mode_set(unit, stage_fc, 9626 lt_fs->slice_number, fg, 0)); 9627 /* 9628 * Initialize slice free entries count value to number of 9629 * entries in the slice. 9630 */ 9631 if (0 == fg->slices[0].lt_map) { 9632 lt_fs->free_count = lt_fs->entry_count; 9633 } 9634 9635 /* Get IFP TCAM slice information. */ 9636 fs = stage_fc->slices[fg->instance] + slice_number; 9637 9638 /* Update slice LT_ID mapping in group's slice. */ 9639 fs->lt_map |= (1 << fg->lt_id); 9640 9641 9642 fc->lt_info[fg->instance][fg->lt_id]->lt_part_map |= (1 << fs->slice_number); 9643 fc->lt_info[fg->instance][fg->lt_id]->lt_part_pri[fs->slice_number] = group_slice_prio; 9644 9645 /* Install TCAM keygen program configuration in hardware for each slice. */ 9646 if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) { 9647 rv = _field_th_ingress_group_expand_install(unit, stage_fc, fg, 9648 part_index, lt_fs); 9649 } else { 9650 /* Default case. */ 9651 rv = _field_th_ingress_default_group_expand_install(unit, stage_fc, fg, 9652 part_index, lt_fs); 9653 } 9654 9655 if (BCM_FAILURE(rv)) { 9656 LOG_ERROR(BSL_LS_BCM_FP, 9657 (BSL_META_U(unit, "Error[%d]: Group slice auto-expand failed for" 9658 " group:%d part:%d slice:%d\n\r"), 9659 rv, fg->gid, part_index, lt_fs->slice_number)); 9660 return rv; 9661 } 9662 9663 /* Set the partition Priority. */ 9664 #if defined (BCM_HELIX5_SUPPORT) 9665 if (SOC_IS_HELIX5(unit)) { 9666 rv = _bcm_field_hx5_ingress_lt_partition_prio_write(unit, stage_fc, fg, 9667 fg->lt_id, slice_number); 9668 } else 9669 #endif 9670 { 9671 rv =_bcm_field_th_ingress_lt_partition_prio_write(unit, stage_fc, fg, 9672 fg->lt_id, slice_number); 9673 } 9674 if (BCM_FAILURE(rv)) { 9675 LOG_ERROR(BSL_LS_BCM_FP, 9676 (BSL_META_U(unit, "Error: LT Partition Set failed for" 9677 " group:%d lt_id:%d slice:%d val:%d\n\r"), 9678 fg->gid, fg->lt_id, slice_number, group_slice_prio)); 9679 } 9680 9681 return (rv); 9682 } 9683 9684 /* 9685 * Function: 9686 * _bcm_field_th_group_instance_set 9687 * 9688 * Purpose: 9689 * Set the group instance based on the group's operational mode 9690 * and group's pbmp. 9691 * 9692 * Parameters: 9693 * unit - (IN) BCM device number. 9694 * fg - (IN) Reference to Field Group structure. 9695 * 9696 * Returns: 9697 * BCM_E_XXX 9698 */ 9699 int 9700 _bcm_field_th_group_instance_set(int unit, _field_group_t *fg) 9701 { 9702 int rv = BCM_E_NONE; /* Return Variable */ 9703 int pipe; /* Device pipe iterator. */ 9704 _field_stage_t *stage_fc; /* Stage control structure. */ 9705 bcm_pbmp_t t_pbmp; /* Pipe Port bitmap. */ 9706 bcm_pbmp_t all_pbmp; /* Group port bitmap. */ 9707 9708 /* Input parameters check. */ 9709 if (NULL == fg) { 9710 return (BCM_E_PARAM); 9711 } 9712 9713 /* Read device port configuration. */ 9714 BCM_PBMP_CLEAR(all_pbmp); 9715 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 9716 9717 /* Get stage field control structure. */ 9718 rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc); 9719 if (BCM_FAILURE(rv)) { 9720 goto bcm_error; 9721 } 9722 9723 /* 9724 * Based on the Stage Group Operational mode, set the Field Group's instance 9725 * information. 9726 */ 9727 if (bcmFieldGroupOperModeGlobal == stage_fc->oper_mode) { 9728 9729 /* 9730 * Validate user supplied IPBM value. 9731 * For global mode, all ports must be part of IPBM value, if supplied. 9732 */ 9733 if (BCM_PBMP_NEQ(all_pbmp, fg->pbmp)) { 9734 /* If port configuration get fails, go to end. */ 9735 rv = BCM_E_PARAM; 9736 goto bcm_error; 9737 } 9738 9739 /* For group global operational mode, use the default instance. */ 9740 fg->instance = _FP_DEF_INST; 9741 } else { 9742 /* 9743 * For PipeLocal group oper mode, derive the instance 9744 * information from group's PBM value. 9745 */ 9746 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 9747 #ifdef BCM_TOMAHAWK3_SUPPORT 9748 if (BCM_PBMP_IS_NULL(PBMP_PIPE(unit, pipe))) { 9749 continue; 9750 } 9751 #endif 9752 BCM_PBMP_ASSIGN(t_pbmp, PBMP_PIPE(unit, pipe)); 9753 BCM_PBMP_REMOVE(t_pbmp, PBMP_LB(unit)); 9754 /* 9755 * User must use bcm_port_config_get API to retrieve Pipe PBMP value 9756 * and pass this value in Group's pbmp parameter when creating 9757 * PipeLocal groups. 9758 */ 9759 if (BCM_PBMP_EQ(t_pbmp, fg->pbmp)) { 9760 /* 9761 * Pipe PBM matches user supplied PBM, update field group 9762 * instance. 9763 */ 9764 fg->instance = pipe; 9765 break; 9766 } 9767 } 9768 9769 /* 9770 * Portbit map value supplied by the user not matching any of the pipe's 9771 * port bitmap mask value, hence return input paramter error. 9772 */ 9773 if (NUM_PIPE(unit) == pipe) { 9774 rv = BCM_E_PARAM; 9775 goto bcm_error; 9776 } 9777 } 9778 9779 bcm_error: 9780 return rv; 9781 } 9782 9783 #else /* BCM_TOMAHAWK_SUPPORT && BCM_FIELD_SUPPORT */ 9784 int _th_field_not_empty; 9785 #endif /* !BCM_TOMAHAWK_SUPPORT && !BCM_FIELD_SUPPORT */