field_presel.c (235814B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: field_presel.c 8 * Purpose: Field Processor routines Specific to Preselector Module. 9 */ 10 11 #include <soc/defs.h> 12 13 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(BCM_FIELD_SUPPORT) 14 15 #include <bcm/error.h> 16 #include <bcm/field.h> 17 #include <shared/bsl.h> 18 19 #include <bcm_int/esw/field.h> 20 #include <bcm_int/esw/tomahawk.h> 21 #include <bcm_int/esw/tomahawk3.h> 22 #if defined(BCM_HELIX5_SUPPORT) 23 #include <bcm_int/esw/helix5.h> 24 #endif /* BCM_HELIX5_SUPPORT */ 25 26 /* Function Declarations */ 27 STATIC int 28 _bcm_field_presel_action_remove_all(int unit, bcm_field_entry_t entry); 29 30 #define _BCM_FIELD_PRESEL_IS_STAGE_SUPPORTED(_stage_) \ 31 ((_stage_ == bcmFieldStageIngress) || \ 32 (_stage_ == bcmFieldStageIngressExactMatch) || \ 33 (_stage_ == bcmFieldStageIngressFlowtracker)) 34 /* 35 * Function: 36 * _field_th_presel_qualifiers_init 37 * 38 * Purpose: 39 * Initialize Field Ingress Stage Preselector Qualifiers. 40 * 41 * Parameters: 42 * unit - (IN) BCM device number. 43 * stage_fc - (IN/OUT) Field Processor stage control structure. 44 * 45 * Returns: 46 * BCM_E_PARAM - Null field stage control structure. 47 * BCM_E_MEMORY - Allocation failure. 48 * BCM_E_INTERNAL - Invalid CAP Stage ID. 49 * BCM_E_NONE - Success. 50 */ 51 STATIC int 52 _field_th_presel_qualifiers_init(int unit, _field_stage_t *stage_fc) 53 { 54 /* 55 * All the qualifiers offset mentioned are the actual individual HW field 56 * offset in IFP_LOGICAL_TABLE_SELECT Memory which are starting from bit 57 * position 2. "KEY" overlap field in the memory is used during write, 58 * hence to accomidate in the field, the offsets of the qualifiers has to 59 * be substracted by 2. 60 */ 61 static int8 key_base_off; 62 soc_mem_t mem = INVALIDm; 63 soc_field_info_t *field_info = NULL; 64 _FP_QUAL_DECL; 65 66 67 /* Allocated stage qualifiers configuration array. */ 68 _FP_XGS3_ALLOC(stage_fc->f_presel_qual_arr, 69 (_bcmFieldQualifyCount * sizeof(_bcm_field_qual_info_t *)), 70 "IFP Preselector qualifiers"); 71 72 if (stage_fc->f_presel_qual_arr == 0) { 73 return (BCM_E_MEMORY); 74 } 75 76 if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 77 mem = EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLYm; 78 } else { 79 mem = IFP_LOGICAL_TABLE_SELECT_TCAM_ONLYm; 80 } 81 82 field_info = soc_mem_fieldinfo_get(unit, mem, KEYf); 83 if (field_info == NULL) { 84 return BCM_E_PARAM; 85 } 86 key_base_off = field_info->bp; 87 88 /* Preselector qualifiers. */ 89 /* SOURCE_CLASS - 32 */ 90 field_info = soc_mem_fieldinfo_get(unit, mem, SOURCE_CLASSf); 91 if (field_info != NULL) { 92 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMixedSrcClassId, 93 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 94 field_info->bp - key_base_off, 32); 95 } 96 97 /* EXACT_MATCH_LOGICAL_TABLE_ID_0 - 5 */ 98 field_info = soc_mem_fieldinfo_get(unit, mem, 99 EXACT_MATCH_LOGICAL_TABLE_ID_0f); 100 if (field_info != NULL) { 101 _FP_PRESEL_QUAL_ADD(unit, stage_fc, 102 _bcmFieldQualifyExactMatchGroupClassIdLookup0, 103 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 104 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 105 field_info->bp - key_base_off, 5); 106 } else { 107 /* EXACT_MATCH_LOGICAL_TABLE_ID - 5 */ 108 field_info = soc_mem_fieldinfo_get(unit, mem, 109 EXACT_MATCH_LOGICAL_TABLE_IDf); 110 if (field_info != NULL) { 111 _FP_PRESEL_QUAL_ADD(unit, stage_fc, 112 _bcmFieldQualifyExactMatchGroupClassIdLookup0, 113 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 114 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 115 field_info->bp - key_base_off, 5); 116 } 117 } 118 119 /* EXACT_MATCH_LOGICAL_TABLE_ID_1 - 5 */ 120 field_info = soc_mem_fieldinfo_get(unit, mem, EXACT_MATCH_LOGICAL_TABLE_ID_1f); 121 if (field_info != NULL) { 122 _FP_PRESEL_QUAL_ADD(unit, stage_fc, 123 _bcmFieldQualifyExactMatchGroupClassIdLookup1, 124 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT 125 , _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 126 field_info->bp - key_base_off, 5); 127 } 128 129 /* RESERVED_0 - 1 */ 130 131 /* HG_LOOKUP - 1 */ 132 field_info = soc_mem_fieldinfo_get(unit, mem, HG_LOOKUPf); 133 if (field_info != NULL) { 134 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy, 135 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 136 field_info->bp - key_base_off , 1); 137 } 138 139 /* CPU_PKT_PROFILE_KEY_CONTROL - 1 */ 140 #if 0 141 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualify, 142 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 143 45 - key_base_off , 1); 144 #endif 145 146 /* MIRROR - 1 */ 147 field_info = soc_mem_fieldinfo_get(unit, mem, MIRRORf); 148 if (field_info != NULL) { 149 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMirrorCopy, 150 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 151 field_info->bp - key_base_off , 1); 152 } 153 154 /* HG - 1 */ 155 field_info = soc_mem_fieldinfo_get(unit, mem, HGf); 156 if (field_info != NULL) { 157 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig, 158 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 159 field_info->bp - key_base_off , 1); 160 } 161 162 /* DROP - 1 */ 163 field_info = soc_mem_fieldinfo_get(unit, mem, DROPf); 164 if (field_info != NULL) { 165 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDrop, 166 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 167 field_info->bp - key_base_off , 1); 168 } 169 170 /* PKT_RESOLUTION - 6 */ 171 field_info = soc_mem_fieldinfo_get(unit, mem, PKT_RESOLUTIONf); 172 if (field_info != NULL) { 173 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyPacketRes, 174 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 175 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 176 field_info->bp - key_base_off , 6); 177 } 178 179 /* FORWARDING_TYPE - 4 */ 180 field_info = soc_mem_fieldinfo_get(unit, mem, FORWARDING_TYPEf); 181 if (field_info != NULL) { 182 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyForwardingType, 183 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 184 field_info->bp - key_base_off , 4); 185 } 186 187 /* LOOKUP_STATUS_VECTOR - 19 */ 188 field_info = soc_mem_fieldinfo_get(unit, mem, LOOKUP_STATUS_VECTORf); 189 if (field_info != NULL) { 190 if (SOC_IS_TOMAHAWK3(unit)) { 191 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIngressStpState, 192 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 193 field_info->bp+0 - key_base_off , 2); 194 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStpState, 195 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 196 field_info->bp+0 - key_base_off , 2); 197 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack, 198 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 199 field_info->bp+2 - key_base_off , 1); 200 _FP_PRESEL_QUAL_ADD(unit, stage_fc, 201 bcmFieldQualifyForwardingVlanValid, 202 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 203 field_info->bp+3 - key_base_off , 1); 204 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsLabel1Hit, 205 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 206 field_info->bp+4 - key_base_off , 1); 207 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsLabel2Hit, 208 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 209 field_info->bp+5 - key_base_off , 1); 210 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsTerminated, 211 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 212 field_info->bp+6 - key_base_off , 1); 213 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpTunnelHit, 214 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 215 field_info->bp+7 - key_base_off , 1); 216 } else { 217 _FP_PRESEL_QUAL_ADD(unit, stage_fc, 218 bcmFieldQualifyVlanTranslationHit, 219 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 220 field_info->bp+0 - key_base_off , 3); 221 _FP_PRESEL_QUAL_ADD(unit, stage_fc, 222 bcmFieldQualifyForwardingVlanValid, 223 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 224 field_info->bp+3 - key_base_off , 1); 225 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIngressStpState, 226 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 227 field_info->bp+4 - key_base_off , 2); 228 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStpState, 229 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 230 field_info->bp+4 - key_base_off , 2); 231 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcHit, 232 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 233 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 234 field_info->bp+6 - key_base_off , 1); 235 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcStatic, 236 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 237 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 238 field_info->bp+7 - key_base_off , 1); 239 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2DestHit, 240 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 241 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 242 field_info->bp+8 - key_base_off , 1); 243 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2CacheHit, 244 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 245 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 246 field_info->bp+9 - key_base_off , 1); 247 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3SrcHostHit, 248 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 249 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 250 field_info->bp+10 - key_base_off , 1); 251 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpmcStarGroupHit, 252 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 253 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 254 field_info->bp+10 - key_base_off , 1); 255 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestHostHit, 256 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 257 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 258 field_info->bp+11 - key_base_off , 1); 259 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestRouteHit, 260 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 261 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 262 field_info->bp+12 - key_base_off , 1); 263 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2StationMove, 264 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT, 265 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 266 field_info->bp+13 - key_base_off , 1); 267 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack, 268 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 269 field_info->bp+14 - key_base_off , 1); 270 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpTunnelHit, 271 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 272 field_info->bp+15 - key_base_off , 1); 273 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsLabel1Hit, 274 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 275 field_info->bp+16 - key_base_off , 1); 276 _FP_PRESEL_QUAL_ADD(unit, stage_fc, 277 bcmFieldQualifyTrillEgressRbridgeHit, 278 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 279 field_info->bp+16 - key_base_off , 1); 280 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2GreSrcIpHit, 281 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 282 field_info->bp+16 - key_base_off , 1); 283 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMimSrcGportHit, 284 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 285 field_info->bp+16 - key_base_off , 1); 286 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsLabel2Hit, 287 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 288 field_info->bp+17 - key_base_off , 1); 289 _FP_PRESEL_QUAL_ADD(unit, stage_fc, 290 bcmFieldQualifyTrillIngressRbridgeHit, 291 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 292 field_info->bp+17 - key_base_off , 1); 293 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2GreVfiHit, 294 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 295 field_info->bp+17 - key_base_off , 1); 296 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMimVfiHit, 297 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 298 field_info->bp+17 - key_base_off , 1); 299 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsTerminated, 300 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 301 field_info->bp+18 - key_base_off , 1); 302 } 303 } 304 305 /* SVP_VALID - 1 */ 306 field_info = soc_mem_fieldinfo_get(unit, mem, SVP_VALIDf); 307 if (field_info != NULL) { 308 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcVirtualPortValid, 309 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 310 field_info->bp - key_base_off , 1); 311 } 312 313 /* TUNNEL_TERMINATED - 1 */ 314 field_info = soc_mem_fieldinfo_get(unit, mem, TUNNEL_TERMINATEDf); 315 if (field_info != NULL) { 316 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTunnelTerminated, 317 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 318 field_info->bp - key_base_off , 1); 319 } 320 321 /* MY_STATION_HIT - 1 */ 322 field_info = soc_mem_fieldinfo_get(unit, mem, MY_STATION_HITf); 323 if (field_info != NULL) { 324 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMyStationHit, 325 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 326 field_info->bp - key_base_off , 1); 327 } 328 329 /* TUNNEL_TYPE_LOOPBACK_TYPE - 5 */ 330 field_info = soc_mem_fieldinfo_get(unit, mem, TUNNEL_TYPE_LOOPBACK_TYPEf); 331 if (field_info != NULL) { 332 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyLoopbackType, 333 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 334 field_info->bp - key_base_off , 5); 335 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTunnelType, 336 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 337 field_info->bp - key_base_off , 5); 338 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyLoopback, 339 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 340 field_info->bp + 4 - key_base_off , 1); 341 } 342 343 /* L4_VALID - 1 */ 344 field_info = soc_mem_fieldinfo_get(unit, mem, L4_VALIDf); 345 if (field_info != NULL) { 346 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4Ports, 347 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 348 field_info->bp - key_base_off , 1); 349 } 350 351 /* L3_TYPE - 5 */ 352 field_info = soc_mem_fieldinfo_get(unit, mem, L3_TYPEf); 353 if (field_info != NULL) { 354 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 355 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 356 field_info->bp - key_base_off , 5); 357 } 358 359 return (BCM_E_NONE); 360 } 361 362 /* 363 * Function: 364 * _field_th_lt_config_init 365 * Purpose: 366 * Initialize a Logical Table configuration in field control. 367 * Parameters: 368 * unit - (IN) BCM device number. 369 * fc - (IN) field control structure pointer. 370 * Returns: 371 * BCM_E_PARAM - Device field control information is NULL 372 * BCM_E_NONE - Success 373 */ 374 int 375 _field_th_lt_config_init(int unit, _field_control_t *fc) 376 { 377 int lt_idx; /* Logical Table iterator. */ 378 int inst; /* Instance iterator. */ 379 _field_lt_config_t *lt_p = NULL; 380 /* Field LT configuration pointer. */ 381 382 int max_lt_parts = _FP_MAX_LT_PARTS(unit); 383 /* Input parameters check. */ 384 if (NULL == fc) { 385 return (BCM_E_PARAM); 386 } 387 388 /* Initialize for all pipes and all logical tables. */ 389 for (inst = 0; inst < NUM_PIPE(unit); inst++) { 390 for (lt_idx = 0; lt_idx < _FP_MAX_NUM_LT; lt_idx++) { 391 392 /* Allocate memory to store LT information. */ 393 _FP_XGS3_ALLOC(lt_p, sizeof(_field_lt_config_t), 394 "logical table config"); 395 396 if (NULL == lt_p) { 397 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 398 "FP(unit %d) Error: LT(Inst=%d) allocation=%d\n"), 399 unit, inst, (BCM_E_MEMORY))); 400 return (BCM_E_MEMORY); 401 } 402 403 lt_p->lt_part_pri = NULL; 404 405 /* Allocate memory for Lt part pri */ 406 _FP_XGS3_ALLOC(lt_p->lt_part_pri, (sizeof(int) * max_lt_parts), 407 "Part Pri for logical table "); 408 409 if (NULL == lt_p->lt_part_pri) { 410 sal_free(lt_p); 411 lt_p = NULL; 412 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 413 "FP(unit %d) Error: LT Part Pri(Inst=%d) allocation=%d\n"), 414 unit, inst, (BCM_E_MEMORY))); 415 return (BCM_E_MEMORY); 416 } 417 418 /* Initialize Logical Table ID. */ 419 lt_p->lt_id = lt_idx; 420 421 /* Initialize stage LT pointer for given instance. */ 422 fc->lt_info[inst][lt_idx] = lt_p; 423 lt_p = NULL; 424 } 425 } 426 return (BCM_E_NONE); 427 } 428 429 /* 430 * Function: 431 * _field_th_instance_lt_slices_init 432 * Purpose: 433 * Initialize a Logical Table instance slices for Ingress stage. 434 * Parameters: 435 * unit - (IN) BCM device number 436 * stage_fc - (IN) stage control structure. 437 * inst - (IN) Field Pipe Instance for which Logical tables must be 438 * deinitialized. 439 * Returns: 440 * BCM_E_PARAM - Device stage field control information is NULL 441 * or Invalid instance specified. 442 * BCM_E_NONE - Success 443 */ 444 STATIC int 445 _field_th_instance_lt_slices_init(int unit, 446 _field_stage_t *stage_fc, 447 int inst) 448 { 449 _field_lt_slice_t *lt_fs; /* Logical table slice info. */ 450 int slice; /* Slice iterator. */ 451 int mem_sz; /* Memory allocation buffer size. */ 452 uint32 flags; /* Stage slice related flags */ 453 454 /* Input parameters check. */ 455 if (NULL == stage_fc) { 456 return (BCM_E_PARAM); 457 } 458 459 /* Validate instance value. */ 460 if (inst < 0 || inst >= stage_fc->num_instances) { 461 return (BCM_E_PARAM); 462 } 463 464 if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 465 flags = _BCM_FIELD_SLICE_HW_ATOMICITY_SUPPORT; 466 } else { 467 flags = _BCM_FIELD_SLICE_SW_ATOMICITY_SUPPORT; 468 } 469 /* Allocate memory to store logical table slices information. */ 470 mem_sz = stage_fc->tcam_slices * sizeof(_field_lt_slice_t); 471 lt_fs = sal_alloc(mem_sz, "stage LT slices info"); 472 if (NULL == lt_fs) { 473 return (BCM_E_MEMORY); 474 } 475 476 /* Initialize memory allocated for logical tables. */ 477 sal_memset(lt_fs, 0, mem_sz); 478 479 /* Update stage's logical table slices pointer for the instance. */ 480 stage_fc->lt_slices[inst] = lt_fs; 481 482 /* Initialize LT slice structure fields. */ 483 for (slice = 0; slice < stage_fc->tcam_slices; slice++) { 484 lt_fs[slice].slice_number = slice; 485 lt_fs[slice].stage_id = stage_fc->stage_id; 486 lt_fs[slice].next = NULL; 487 lt_fs[slice].prev = NULL; 488 lt_fs[slice].slice_flags = flags; 489 } 490 491 return (BCM_E_NONE); 492 } 493 494 /* 495 * Function: 496 * _field_th_stage_lt_entries_free 497 * Purpose: 498 * Deallocate Logical Table entries for all instance in StageIngress. 499 * Parameters: 500 * unit - (IN) BCM device number. 501 * stage_fc - (IN) stage control structure pointer. 502 * Returns: 503 * BCM_E_PARAM - Device stage field control information is NULL. 504 * BCM_E_NONE - Success 505 */ 506 STATIC int 507 _field_th_stage_lt_entries_free(int unit, _field_stage_t *stage_fc) 508 { 509 _field_lt_slice_t *lt_fs; /* Field logical table slice pointer. */ 510 int slice; /* Slice iterator. */ 511 int inst; /* Instance iterator. */ 512 _field_control_t *fc; /* Field Control Info */ 513 514 /* Input prameters check. */ 515 if (NULL == stage_fc) { 516 return (BCM_E_PARAM); 517 } 518 519 /* Get field control structure. */ 520 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 521 522 /* Deallocate instance entry pointers. */ 523 for (inst = 0; inst < stage_fc->num_instances; inst++) { 524 if (!(fc->pipe_map & (1 << inst))) { 525 continue; 526 } 527 /* Ensure stage's logical table slices instance is valid. */ 528 if (NULL != stage_fc->lt_slices[inst]) { 529 for (slice = 0; slice < stage_fc->tcam_slices; slice++) { 530 lt_fs = stage_fc->lt_slices[inst] + slice; 531 if (NULL != lt_fs->entries) { 532 sal_free(lt_fs->entries); 533 lt_fs->entries = NULL; 534 } 535 536 if (NULL != lt_fs->p_entries) { 537 sal_free(lt_fs->p_entries); 538 lt_fs->p_entries = NULL; 539 } 540 } 541 } 542 } 543 544 return (BCM_E_NONE); 545 } 546 547 /* 548 * Function: 549 * _field_th_instance_lt_entries_init 550 * Purpose: 551 * Initialize Logical Table slices for a StageIngress instance. 552 * Parameters: 553 * unit - (IN) BCM device number. 554 * stage_fc - (IN) stage control structure pointer. 555 * inst - (IN) Field Pipe Instance for which Logical tables must be 556 * deinitialized. 557 * Returns: 558 * BCM_E_PARAM - Device stage field control information is NULL 559 * or Invalid instance specified. 560 * BCM_E_NONE - Success 561 */ 562 STATIC int 563 _field_th_instance_lt_entries_init(int unit, _field_stage_t *stage_fc, int inst) 564 { 565 _field_lt_slice_t *lt_fs; /* Field logical table slice pointer. */ 566 int slice; /* Slice index iterator. */ 567 int tcam_idx; /* Slice first entry tcam index tracker. */ 568 int mem_sz; /* Size of memory to be allocated. */ 569 570 /* Input parameters check. */ 571 if (NULL == stage_fc) { 572 return (BCM_E_PARAM); 573 } 574 575 /* Check if instance is in valid range. */ 576 if (inst < 0 || inst >= stage_fc->num_instances) { 577 return (BCM_E_PARAM); 578 } 579 580 /* Make sure slices array is initialized. */ 581 if (NULL == stage_fc->lt_slices[inst]) { 582 return (BCM_E_INTERNAL); 583 } 584 585 /* Iterate over all stage's slices and allocate entries for each slice. */ 586 for (slice = 0, tcam_idx = 0; slice < stage_fc->tcam_slices; slice++) { 587 /* Get Pipe slice control structure pointer. */ 588 lt_fs = stage_fc->lt_slices[inst] + slice; 589 590 /* Initialize entries per-slice count. */ 591 lt_fs->entry_count = stage_fc->lt_tcam_sz / stage_fc->tcam_slices; 592 593 /* Calculate size for total entry pointers. */ 594 mem_sz = lt_fs->entry_count * sizeof(void *); 595 596 /* Allocate slice entries pointers array. */ 597 _FP_XGS3_ALLOC(lt_fs->entries, mem_sz, "LT array of entry pointers."); 598 599 /* Allocate slice presel entries pointers array. */ 600 _FP_XGS3_ALLOC(lt_fs->p_entries, mem_sz, 601 "Presel LT array of entry pointers."); 602 if ((NULL == lt_fs->p_entries) || (NULL == lt_fs->entries)) { 603 /* Allocation failed free all previously allocated entries. */ 604 _field_th_stage_lt_entries_free(unit, stage_fc); 605 return (BCM_E_MEMORY); 606 } 607 608 lt_fs->start_tcam_idx = tcam_idx; 609 tcam_idx += lt_fs->entry_count; 610 lt_fs->free_count = lt_fs->entry_count; 611 } 612 return (BCM_E_NONE); 613 } 614 615 /* 616 * Function: 617 * _field_th_presel_qual_init 618 * Purpose: 619 * Initialize Field control Preselector qualifiers. 620 * Parameters: 621 * unit - (IN) BCM device number. 622 * fc - (IN) Reference to Field Control structure. 623 * stage_fc - (IN/OUT) Stage field control structure. 624 * Returns: 625 * BCM_E_PARAM - Device field control information is NULL. 626 * BCM_E_MEMORY - In-case of Allocation fails. 627 * BCM_E_NONE - Success. 628 */ 629 630 STATIC int 631 _field_th_presel_qual_init(int unit, 632 _field_control_t *fc, 633 _field_stage_t *stage_fc) 634 { 635 int rv; /* Operation return status. */ 636 int qual_idx; /* Qualifier index. */ 637 638 /* Input parameters check. */ 639 if (NULL == fc || NULL == stage_fc) { 640 return (BCM_E_PARAM); 641 } 642 643 /* Initialize qualifiers info. */ 644 #if defined(BCM_TRIDENT3_SUPPORT) 645 if (soc_feature(unit, soc_feature_td3_style_fp)) { 646 rv = (_field_td3_presel_qualifiers_init(unit, stage_fc)); 647 } else 648 #endif 649 #if defined(BCM_TOMAHAWK3_SUPPORT) 650 if (soc_feature(unit, soc_feature_th3_style_fp)) { 651 rv = (_field_th3_presel_qualifiers_init(unit, stage_fc)); 652 } else 653 #endif 654 { 655 rv = (_field_th_presel_qualifiers_init(unit, stage_fc)); 656 } 657 658 if (BCM_FAILURE(rv)) { 659 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 660 "Error: Preselector Qualifiers init failed[%d].\n"), 661 rv)); 662 return rv; 663 } 664 665 /* Update the Valid Preselector QSET */ 666 for (qual_idx = 0; qual_idx < _bcmFieldQualifyCount; qual_idx++) { 667 if ((NULL != stage_fc->f_presel_qual_arr[qual_idx]) && 668 (NULL != stage_fc->f_presel_qual_arr[qual_idx]->conf_arr)) { 669 BCM_FIELD_QSET_ADD(stage_fc->presel_qset, qual_idx); 670 } 671 } 672 673 return (BCM_E_NONE); 674 } 675 676 /* 677 * Function: 678 * _field_th_stage_preselector_init 679 * Purpose: 680 * Initialize Preselector resources for given stage and field control. 681 * - Logical Table configuration initialization for each instance. 682 * - Logical Table Slice initialization for each instance. 683 * - Logical Table Entries initialization for each instance. 684 * - Preselection Qualifier Database initialization. 685 * 686 * Parameters: 687 * unit - (IN) BCM device number. 688 * fc - (IN) Field control structure. 689 * stage_fc - (IN/OUT) Stage field control structure. 690 * 691 * Returns: 692 * BCM_E_PARAM - NULL stage control or field control pointer. 693 * BCM_E_MEMORY - Allocation failure. 694 * BCM_E_NONE - Success. 695 */ 696 int 697 _bcm_field_th_stage_preselector_init(int unit, 698 _field_control_t *fc, 699 _field_stage_t *stage_fc) 700 { 701 int inst; /* Field processor pipe instance. */ 702 int rv; /* Operation return status. */ 703 704 /* Input parameters check. */ 705 if (NULL == fc || NULL == stage_fc) { 706 return (BCM_E_PARAM); 707 } 708 709 /* Do nothing for Non-PresePreseltages. */ 710 if ((_BCM_FIELD_STAGE_INGRESS != stage_fc->stage_id) && 711 (_BCM_FIELD_STAGE_EXACTMATCH != stage_fc->stage_id) && 712 (_BCM_FIELD_STAGE_FLOWTRACKER != stage_fc->stage_id)) { 713 return (BCM_E_NONE); 714 } 715 716 /* Initialize Preselection qualifiers */ 717 rv = _field_th_presel_qual_init(unit, fc, stage_fc); 718 if (BCM_FAILURE(rv)) { 719 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 720 "FP(unit %d) Error: Presel Info init failed(%d)\n"), 721 unit, rv)); 722 return (rv); 723 } 724 725 for (inst = 0; inst < stage_fc->num_instances; inst++) { 726 if (!(fc->pipe_map & (1 << inst))) { 727 continue; 728 } 729 /* Initialize logical table slices for IFP and EM stage. */ 730 rv = _field_th_instance_lt_slices_init(unit, stage_fc, inst); 731 if (BCM_FAILURE(rv)) { 732 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 733 "FP(unit %d) Error: LT(Inst=%d) Slices Init=%d\n"), 734 unit, inst, rv)); 735 return (rv); 736 } 737 738 /* Initialize logical table slice entries for IFP and EM stage. */ 739 rv = _field_th_instance_lt_entries_init(unit, stage_fc, inst); 740 if (BCM_FAILURE(rv)) { 741 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 742 "FP(unit %d) Error: LT(Inst=%d) Entries Init=%d\n"), 743 unit, inst, rv)); 744 return (rv); 745 } 746 } 747 748 return (BCM_E_NONE); 749 } 750 751 /* 752 * Function: 753 * _field_th_presel_qual_free 754 * Purpose: 755 * De-Initialize Preselector Qualifier Database. 756 * Parameters: 757 * unit - (IN) BCM device number. 758 * stage_fc - (IN) Stage field control structure. 759 * Returns: 760 * BCM_E_PARAM - Device field control information is NULL. 761 * BCM_E_MEMORY - In-case of Allocation fails. 762 * BCM_E_NONE - Success. 763 */ 764 765 STATIC int 766 _field_th_presel_qual_free(int unit, 767 _field_stage_t *stage_fc) 768 { 769 _bcm_field_qual_info_t *f_qual; /* Qualifier descriptor. */ 770 int idx; /* Qualifiers iteration index. */ 771 772 /* Input parameters check. */ 773 if (NULL == stage_fc) { 774 return (BCM_E_PARAM); 775 } 776 777 if (NULL == stage_fc->f_presel_qual_arr) { 778 return (BCM_E_NONE); 779 } 780 781 for (idx = 0; idx < _bcmFieldQualifyCount; idx++) { 782 f_qual = stage_fc->f_presel_qual_arr[idx]; 783 784 /* Skip unused qualifiers. */ 785 if (NULL == f_qual) { 786 continue; 787 } 788 /* Free qualifier configurations array. */ 789 if (NULL != f_qual->conf_arr) sal_free(f_qual->conf_arr); 790 791 /* Free qualifier descriptor structure. */ 792 sal_free(f_qual); 793 794 /* Mark qualifier as unused. */ 795 stage_fc->f_presel_qual_arr[idx] = NULL; 796 } 797 798 /* Free qualifiers array. */ 799 sal_free(stage_fc->f_presel_qual_arr); 800 stage_fc->f_presel_qual_arr = NULL; 801 802 return (BCM_E_NONE); 803 } 804 805 /* 806 * Function: 807 * _bcm_field_th_preselector_deinit 808 * Purpose: 809 * Deinitialize a Preselector resources in Ingress stage. 810 * - Deallocate Logical table slice entries and slices for each instance. 811 * - Deallocate Logical table configuration structures for each instance. 812 * - Deallocate Preselector Qualifiers Information. 813 * Parameters: 814 * unit - (IN) BCM device number 815 * fc - (IN) Field control structure. 816 * stage_fc - (IN) Stage field control structure. 817 * Returns: 818 * BCM_E_PARAM - Device field control or stage field control information 819 * is NULL. 820 * BCM_E_NONE - Success 821 */ 822 int 823 _bcm_field_th_preselector_deinit(int unit, 824 _field_control_t *fc, 825 _field_stage_t *stage_fc) 826 { 827 int slice; /* Slice iterator. */ 828 int inst; /* Pipe instance. */ 829 _field_lt_slice_t *lt_fs; /* Logical Table slice information. */ 830 831 /* Input parameters check. */ 832 if (NULL == fc || NULL == stage_fc) { 833 return (BCM_E_PARAM); 834 } 835 836 /* Do nothing for Non-Presel stages. */ 837 if ((_BCM_FIELD_STAGE_INGRESS != stage_fc->stage_id) && 838 (_BCM_FIELD_STAGE_EXACTMATCH != stage_fc->stage_id) && 839 (_BCM_FIELD_STAGE_FLOWTRACKER != stage_fc->stage_id)) { 840 return (BCM_E_NONE); 841 } 842 843 /* Free the resources for each instance. */ 844 for (inst = 0; inst < stage_fc->num_instances; inst++) { 845 if (!(fc->pipe_map & (1 << inst))) { 846 continue; 847 } 848 /* Ensure stage's logical table slices instance is valid. */ 849 if (NULL != stage_fc->lt_slices[inst]) { 850 /* Deallocate logical table entry pointers for the given instance. */ 851 for (slice = 0; slice < stage_fc->tcam_slices; slice++) { 852 lt_fs = stage_fc->lt_slices[inst] + slice; 853 if (NULL != lt_fs->entries) { 854 sal_free(lt_fs->entries); 855 lt_fs->entries = NULL; 856 } 857 if (NULL != lt_fs->p_entries) { 858 sal_free(lt_fs->p_entries); 859 lt_fs->p_entries = NULL; 860 } 861 } 862 863 /* Free logical table slices memory for active instances. */ 864 sal_free(stage_fc->lt_slices[inst]); 865 stage_fc->lt_slices[inst] = NULL; 866 } 867 } 868 869 /* Deallocate Field Control Preselector information */ 870 _field_th_presel_qual_free(unit, stage_fc); 871 872 return (BCM_E_NONE); 873 } 874 875 /* 876 * Function: bcmi_field_th_presel_alloc 877 * 878 * Purpose: Allocate a preselector 879 * 880 * Parameters: 881 * unit - (IN) BCM device number. 882 * presel_id - (OUT) Reference to a new preselector ID to be created 883 * 884 * Returns: 885 * BCM_E_NONE - Success 886 * BCM_E_XXX - BCM_E_xx appropriately otherwise 887 */ 888 int 889 _bcm_field_th_presel_create(int unit, 890 _bcm_field_presel_flags_t flags, 891 bcm_field_presel_t *presel) 892 { 893 bcm_field_presel_t id = -1; /* Presel id */ 894 _field_presel_entry_t *f_presel = NULL; /* Internal Presel descriptor */ 895 _field_presel_info_t *presel_info; /* Presel information structure */ 896 _field_control_t *fc; /* Field control structure. */ 897 898 /* Validate input arguments NULL reference */ 899 if (presel == NULL) { 900 return BCM_E_PARAM; 901 } 902 903 /* Get field control structure. */ 904 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 905 906 /* Get the preselector information */ 907 presel_info = fc->presel_info; 908 if (presel_info == NULL) { 909 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 910 "ERROR: Field control for Presel Information returns NULL.\n\r"))); 911 return BCM_E_INTERNAL; 912 } 913 914 /* Presel create with ID */ 915 if (flags & _bcmFieldPreselCreateWithId) { 916 id = *presel; 917 if ((id < 0) || (id >= presel_info->presel_limit)) { 918 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 919 "ERROR: Invalid Preselector ID %d.\n\r"), id)); 920 return BCM_E_PARAM; 921 } 922 923 /* TH3 COS SW WAR */ 924 if ((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) && 925 (id == _FP_PRESEL_INTERNAL_RESERVED_ID)) { 926 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 927 "ERROR: Invalid Preselector ID %d.\n\r"), id)); 928 return BCM_E_PARAM; 929 } 930 931 /* Check if presel ID is already created */ 932 if (BCM_FIELD_PRESEL_TEST(presel_info->presel_set, id)) { 933 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 934 "ERROR: Preselector ID[%d] is already created.\n\r"), id)); 935 return BCM_E_EXISTS; 936 } 937 } else { 938 uint32 max_count; /* Maximum number of ids supported */ 939 940 max_count = presel_info->presel_limit; 941 942 if (soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) { 943 max_count = (presel_info->presel_limit - 1); 944 } 945 946 while (max_count) { 947 id = presel_info->last_allocated_id++; 948 949 if (soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) { 950 if (id == (presel_info->presel_limit - 2)) { 951 presel_info->last_allocated_id = 0; 952 } 953 } else { 954 if (id == (presel_info->presel_limit - 1)) { 955 presel_info->last_allocated_id = 0; 956 } 957 } 958 959 if (!BCM_FIELD_PRESEL_TEST(presel_info->presel_set, id)) { 960 *presel = id; 961 break; 962 } 963 max_count--; 964 } 965 966 if (max_count == 0) { 967 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 968 "ERROR: Can't create the ID, max limit reached[0x%x].\n\r"), 969 (soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) 970 ?(presel_info->presel_limit -1):(presel_info->presel_limit))); 971 return BCM_E_RESOURCE; 972 } 973 } 974 975 /* Allocate presel descriptor. */ 976 _FP_XGS3_ALLOC(f_presel, sizeof (_field_presel_entry_t), "Field Presel entity"); 977 if (NULL == f_presel) { 978 return BCM_E_MEMORY; 979 } 980 981 /* Initialize the newly created presel id */ 982 f_presel->presel_id = id; 983 /* Initialize the hw index to No HW resources allocated */ 984 f_presel->hw_index = _FP_INVALID_INDEX; 985 /* Initialize internal flags and stage information */ 986 f_presel->flags = flags; 987 988 /* Insert Presel into Preselector database */ 989 if (fc->presel_db == NULL) { 990 sal_free(f_presel); 991 return BCM_E_INTERNAL; 992 } 993 994 fc->presel_db[id] = f_presel; 995 996 /* Update preselector global information */ 997 /* coverity[negative_shift : FALSE] */ 998 BCM_FIELD_PRESEL_ADD(presel_info->presel_set, id); 999 1000 return BCM_E_NONE; 1001 } 1002 1003 1004 /* 1005 * Function: bcmi_field_th_presel_destroy 1006 * 1007 * Purpose: Destroy a preselector entry 1008 * 1009 * Parameters: 1010 * unit - (IN) BCM device number. 1011 * presel_id - (IN) A preselector ID to be deleted 1012 * 1013 * Returns: 1014 * BCM_E_NONE - Success 1015 * BCM_E_BUSY - If the presel is already in use by a group. 1016 * BCM_E_XXX - BCM_E_xx appropriately otherwise 1017 */ 1018 1019 int 1020 _bcm_field_th_presel_destroy(int unit, 1021 bcm_field_presel_t presel_id) 1022 { 1023 int rv; /* Operation return status. */ 1024 _field_control_t *fc; /* Field control structure */ 1025 _field_presel_entry_t *f_presel; /* Internal preselector descriptor*/ 1026 1027 /* Validate the Preselector ID */ 1028 if (_BCM_FIELD_IS_PRESEL_VALID(presel_id) == FALSE) { 1029 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1030 "ERROR: Invalid Presel ID[%d].\n\r"), presel_id)); 1031 return BCM_E_PARAM; 1032 } 1033 1034 /* Get field control structure. */ 1035 BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc)); 1036 1037 /* Check if presel ID present in presel_set */ 1038 if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel_id)) { 1039 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1040 "ERROR: Preselector ID[%d] is not found.\n\r"), presel_id)); 1041 return BCM_E_NOT_FOUND; 1042 } 1043 1044 /* Check if presel ID is operational */ 1045 if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel_id)) { 1046 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1047 "ERROR: Preselector ID[%d] is in USE.\n\r"), presel_id)); 1048 return BCM_E_BUSY; 1049 } 1050 1051 /* Find preselector descriptor */ 1052 BCM_IF_ERROR_RETURN 1053 (_bcm_field_presel_entry_get(unit, presel_id, &f_presel)); 1054 1055 /* Remove the actions associated with the preselector entry */ 1056 rv = _bcm_field_presel_action_remove_all(unit, 1057 (presel_id | BCM_FIELD_QUALIFY_PRESEL)); 1058 if (BCM_FAILURE(rv)) { 1059 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1060 "ERROR: Unable to remove the actions associated with the" 1061 "Preselector Id[%d].\n\r"), presel_id)); 1062 return BCM_E_INTERNAL; 1063 } 1064 1065 /* Remove preselector for lookup database. */ 1066 fc->presel_db[presel_id] = NULL; 1067 1068 /* Deallocate the memories */ 1069 if (f_presel->lt_tcam.key != NULL) sal_free(f_presel->lt_tcam.key); 1070 if (f_presel->lt_tcam.mask != NULL) sal_free(f_presel->lt_tcam.mask); 1071 if (f_presel->lt_data.data != NULL) sal_free(f_presel->lt_data.data); 1072 sal_free (f_presel); 1073 1074 /* Get the preselector information */ 1075 BCM_FIELD_PRESEL_REMOVE(fc->presel_info->presel_set, presel_id); 1076 1077 return BCM_E_NONE; 1078 } 1079 1080 /* 1081 * Function: _bcm_field_presel_entry_get 1082 * 1083 * Purpose: Get the preselector description structure for the given presel id 1084 * 1085 * Parameters: 1086 * unit - (IN) BCM device number. 1087 * presel_id - (IN) Preselector ID 1088 * presel - (OUT) Reference to the preselector description structure 1089 * 1090 * Returns: 1091 * BCM_E_NONE - Success 1092 * BCM_E_NOT_FOUND - If the ID is not found. 1093 * BCM_E_XXX - BCM_E_xx appropriately otherwise 1094 */ 1095 int 1096 _bcm_field_presel_entry_get(int unit, 1097 bcm_field_presel_t presel_id, 1098 _field_presel_entry_t **presel) 1099 { 1100 _field_control_t *fc; /* Field control structure */ 1101 _field_presel_entry_t *f_presel; /* Preselector lookup pointer */ 1102 1103 /* Input parameters check */ 1104 if (NULL == presel) { 1105 return BCM_E_PARAM; 1106 } 1107 1108 /* Get field control structure. */ 1109 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 1110 1111 /* Check if presel ID present in presel_set */ 1112 if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel_id)) { 1113 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1114 "ERROR: Preselector ID[%d] is not found.\n\r"), presel_id)); 1115 return BCM_E_NOT_FOUND; 1116 } 1117 1118 f_presel = fc->presel_db[presel_id]; 1119 if (f_presel != NULL) { 1120 /* Match entry id */ 1121 *presel = f_presel; 1122 return BCM_E_NONE; 1123 } 1124 1125 return BCM_E_INTERNAL; 1126 } 1127 1128 /* 1129 * Function: _bcm_field_entry_presel_resolve 1130 * 1131 * Purpose: 1132 * Resolve the presel info from the given entry id. 1133 * 1134 * Parameters: 1135 * unit - (IN) BCM device number. 1136 * entry - (IN) An entry id to be validated for presel. 1137 * presel - (OUT) Reference to the resolved presel id. 1138 * presel - (OUT) Reference to the preselector description structure 1139 * 1140 * Returns: 1141 * BCM_E_PARAM - presel contained in entry id is not valid 1142 * or presel == NULL. 1143 * BCM_E_UNAVAIL - entry id doesn't contain a presel id. 1144 * BCM_E_NOT_FOUND - presel id is not found. 1145 * BCM_E_NONE - returns valid presel id. 1146 */ 1147 STATIC int 1148 _bcm_field_entry_presel_resolve(int unit, 1149 bcm_field_entry_t entry, 1150 bcm_field_presel_t *presel, 1151 _field_presel_entry_t **f_presel) 1152 { 1153 int rv; /* Operation return status. */ 1154 1155 if (presel == NULL) { 1156 return BCM_E_PARAM; 1157 } 1158 1159 if (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE) { 1160 _field_control_t *fc; /* Field control structure */ 1161 bcm_field_presel_t id; /* Preselector Id */ 1162 1163 1164 id = _BCM_FIELD_PRESEL_FROM_ENTRY(entry); 1165 if (_BCM_FIELD_IS_PRESEL_VALID(id) == FALSE) { 1166 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1167 "ERROR: Invalid Presel ID[%d] retrieved from Entry ID[%d].\n\r"), 1168 id, entry)); 1169 return BCM_E_PARAM; 1170 } 1171 1172 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 1173 /* Check if presel ID present in presel_set */ 1174 if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, id)) { 1175 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1176 "ERROR: Preselector ID[%d] is not found.\n\r"), id)); 1177 return BCM_E_NOT_FOUND; 1178 } 1179 1180 *presel = id; 1181 1182 /* Retrieve the Presel Entry */ 1183 rv = _bcm_field_presel_entry_get(unit, id, f_presel); 1184 if (BCM_FAILURE(rv)) { 1185 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1186 "ERROR: Couldn't retrieve the Preselector Entry for the given" 1187 " Presel ID[%d].\n\r"), *presel)); 1188 return rv; 1189 } 1190 } else { 1191 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1192 "ERROR: Entry ID[%d] is not of Preselector Type.\n\r"), entry)); 1193 return BCM_E_UNAVAIL; 1194 } 1195 1196 return BCM_E_NONE; 1197 } 1198 1199 /* 1200 * Function: 1201 * _field_presel_qual_offset_get 1202 * Purpose: 1203 * Retrieve qualifier offsets for the given preselector qual. 1204 * Parameters: 1205 * unit - (IN) BCM device number. 1206 * stage_fc - (IN) Stage field control structure. 1207 * f_presel - (IN) Reference to Field preselector entry descriptor. 1208 * qid - (IN) Qualifier id. 1209 * q_offset - (OUT) Qualifier offset and width. 1210 * Returns: 1211 * BCM_E_XXX 1212 */ 1213 STATIC int 1214 _field_presel_qual_offset_get(int unit, _field_stage_t *stage_fc, 1215 _field_presel_entry_t *f_presel, 1216 int qid, _bcm_field_qual_offset_t *q_offset) 1217 { 1218 int ct; 1219 _field_control_t *fc; /* Field control structure. */ 1220 _bcm_field_qual_info_t *f_qual = NULL; 1221 _bcm_field_qual_conf_t *conf_arr = NULL; 1222 1223 /* Input parameters check. */ 1224 if ((NULL == stage_fc) || (NULL == f_presel) || (NULL == q_offset)) { 1225 return (BCM_E_PARAM); 1226 } 1227 1228 /* Retrieve the control structure */ 1229 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 1230 1231 /* Validate the Qualifier */ 1232 if (0 == BCM_FIELD_QSET_TEST(stage_fc->presel_qset, qid)) { 1233 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1234 "ERROR: Preselector Stage doesn't support the qualifier[%s].\n\r"), 1235 _field_qual_name(qid))); 1236 return (BCM_E_PARAM); 1237 } 1238 1239 f_qual = stage_fc->f_presel_qual_arr[qid]; 1240 if (f_qual == NULL) { 1241 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1242 "ERROR: Unable to retrieve Preselector Qualifier[%s] offset.\n\r"), 1243 _field_qual_name(qid))); 1244 return BCM_E_INTERNAL; 1245 } 1246 1247 for (ct = 0; ct < f_qual->conf_sz; ct++) { 1248 conf_arr = &f_qual->conf_arr[ct]; 1249 if ((conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_NONE) || 1250 (conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L3) || 1251 (conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L2)) { 1252 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1253 bcmFieldQualifyPktFlowType)) { 1254 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1255 _bcmFieldQualifyPktFlowTypeTunnelNone) && 1256 !(conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_NONE)) { 1257 continue; 1258 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1259 _bcmFieldQualifyPktFlowTypeTunnelL3) && 1260 !(conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L3)) { 1261 continue; 1262 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1263 _bcmFieldQualifyPktFlowTypeTunnelL2) && 1264 !(conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L2)) { 1265 continue; 1266 } 1267 } 1268 } 1269 1270 /* Get qualifier information. */ 1271 sal_memcpy(q_offset, 1272 &conf_arr->offset, 1273 sizeof(_bcm_field_qual_offset_t)); 1274 return (BCM_E_NONE); 1275 } 1276 1277 return (BCM_E_NOT_FOUND); 1278 } 1279 1280 /* 1281 * Function: 1282 * _bcm_field_presel_entry_tcam_idx_get 1283 * Purpose: 1284 * Get the TCAM index of an entry ID. 1285 * Parameters: 1286 * unit - (IN) BCM device number. 1287 * f_presel - (IN) Pointer to field logical table entry structure. 1288 * lt_fs - (IN) Pointer to field logical table slice structure. 1289 * tcam_idx - (OUT) Entry tcam index. 1290 * 1291 * Returns: 1292 * BCM_E_XXX 1293 */ 1294 int 1295 _bcm_field_presel_entry_tcam_idx_get(int unit, _field_presel_entry_t *f_presel, 1296 _field_lt_slice_t *lt_fs, int *tcam_idx) 1297 { 1298 /* Input parameters check. */ 1299 if ((NULL == f_presel) || (NULL == lt_fs) || (NULL == tcam_idx)) { 1300 return (BCM_E_PARAM); 1301 } 1302 1303 /* Requested entry structure sanity check. */ 1304 if ((NULL == f_presel->group) || (NULL == f_presel->lt_fs)) { 1305 return (BCM_E_PARAM); 1306 } 1307 1308 /* Calculate the TCAM index. */ 1309 *tcam_idx = lt_fs->start_tcam_idx + f_presel->hw_index; 1310 1311 return (BCM_E_NONE); 1312 } 1313 1314 1315 /* 1316 * Function: 1317 * _bcm_field_th_presel_tcam_key_mask_get 1318 * Purpose: 1319 * Allocate & read from hw preselector tcam key/mask image. 1320 * Parameters: 1321 * unit - (IN) BCM device number. 1322 * stage_fc - (IN) Reference to Field Stage control structure. 1323 * inst - (IN) Pipe Instance. 1324 * f_presel - (IN/OUT) Field Presel Entry. 1325 * tcam - (IN) Reference to Presel Entry TCAM structure. 1326 * Returns: 1327 * BCM_E_XXX 1328 */ 1329 int 1330 _bcm_field_th_presel_tcam_key_mask_get(int unit, 1331 _field_stage_t *stage_fc, 1332 int inst, 1333 _field_presel_entry_t *f_presel, 1334 _field_presel_tcam_t *tcam) 1335 { 1336 uint32 tcam_key_words; /* tcam key length */ 1337 soc_mem_t tcam_mem; /* TCAM Memory name */ 1338 1339 1340 /* Validate input parameters */ 1341 if (NULL == f_presel || NULL == tcam) { 1342 return BCM_E_PARAM; 1343 } 1344 1345 /* Check if tcam info already present. */ 1346 if (NULL != f_presel->lt_tcam.key) { 1347 return (BCM_E_NONE); 1348 } 1349 1350 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 1351 BCM_IF_ERROR_RETURN 1352 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst, 1353 _BCM_FIELD_MEM_TYPE_IFP_LT, 1354 _BCM_FIELD_MEM_VIEW_TYPE_TCAM, 1355 &tcam_mem, NULL)); 1356 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 1357 BCM_IF_ERROR_RETURN 1358 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst, 1359 _BCM_FIELD_MEM_TYPE_EM_LT, 1360 _BCM_FIELD_MEM_VIEW_TYPE_TCAM, 1361 &tcam_mem, NULL)); 1362 #if defined(BCM_FLOWTRACKER_SUPPORT) 1363 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 1364 BCM_IF_ERROR_RETURN 1365 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst, 1366 _BCM_FIELD_MEM_TYPE_FT_LT, 1367 _BCM_FIELD_MEM_VIEW_TYPE_TCAM, 1368 &tcam_mem, NULL)); 1369 #endif 1370 } else { 1371 return BCM_E_PARAM; 1372 } 1373 1374 tcam_key_words = BITS2WORDS(soc_mem_field_length(unit, 1375 tcam_mem, 1376 KEYf)); 1377 /* Retrieve the key size */ 1378 tcam->key_size = WORDS2BYTES(tcam_key_words); 1379 1380 /* Allocate Memory for TCAM Key and Mask */ 1381 _FP_XGS3_ALLOC(tcam->key, tcam->key_size, 1382 "IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY Key Alloc."); 1383 if (tcam->key == NULL) { 1384 return BCM_E_MEMORY; 1385 } 1386 _FP_XGS3_ALLOC(tcam->mask, tcam->key_size, 1387 "IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY Mask Alloc."); 1388 if (tcam->mask == NULL) { 1389 sal_free(tcam->key); 1390 tcam->key = NULL; 1391 return BCM_E_MEMORY; 1392 } 1393 1394 return (BCM_E_NONE); 1395 } 1396 1397 /* 1398 * Function: 1399 * _bcm_field_th_presel_mem_data_get 1400 * Purpose: 1401 * Allocate & read from hw preselector data image. 1402 * Parameters: 1403 * unit - (IN) BCM device number. 1404 * stage_fc - (IN) Reference to Field Stage control structure. 1405 * inst - (IN) Pipe Instance. 1406 * f_presel - (IN/OUT) Field Presel Entry. 1407 * p_data - (OUT) Reference to Presel Entry Data structure. 1408 * Returns: 1409 * BCM_E_XXX 1410 */ 1411 int 1412 _bcm_field_th_presel_mem_data_get(int unit, 1413 _field_stage_t *stage_fc, 1414 int inst, 1415 _field_presel_entry_t *f_presel, 1416 _field_presel_data_t *p_data) 1417 { 1418 int rv; /* Operation return status. */ 1419 int data_idx; /* Data Mem index. */ 1420 soc_mem_t lt_mem; /* LT TCAM-DATA mem. */ 1421 uint32 mem_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Entry buffer. */ 1422 1423 /* Validate input parameters */ 1424 if (NULL == f_presel || NULL == p_data || 1425 NULL == stage_fc) { 1426 return BCM_E_PARAM; 1427 } 1428 1429 /* Check if tcam info already present. */ 1430 if (NULL != f_presel->lt_data.data) { 1431 return (BCM_E_NONE); 1432 } 1433 1434 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 1435 BCM_IF_ERROR_RETURN 1436 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst, 1437 _BCM_FIELD_MEM_TYPE_IFP_LT, 1438 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 1439 <_mem, NULL)); 1440 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 1441 BCM_IF_ERROR_RETURN 1442 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst, 1443 _BCM_FIELD_MEM_TYPE_EM_LT, 1444 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 1445 <_mem, NULL)); 1446 #if defined(BCM_FLOWTRACKER_SUPPORT) 1447 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 1448 /* Getting mem for Data table as combo is not supported */ 1449 BCM_IF_ERROR_RETURN 1450 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst, 1451 _BCM_FIELD_MEM_TYPE_FT_LT, 1452 _BCM_FIELD_MEM_VIEW_TYPE_DATA, 1453 NULL, <_mem)); 1454 #endif 1455 } else { 1456 return BCM_E_PARAM; 1457 } 1458 1459 /* Get data field size in logical table entry. */ 1460 if (!SOC_IS_TOMAHAWK3(unit)) { 1461 p_data->data_size = WORDS2BYTES(soc_mem_field_length(unit, 1462 lt_mem, DATAf)); 1463 } else { 1464 p_data->data_size = 57; 1465 } 1466 1467 /* Allocate Memory for SRAM Data */ 1468 _FP_XGS3_ALLOC(p_data->data, p_data->data_size, 1469 "IFP_LOGICAL_TABLE_SELECT Data Alloc."); 1470 if (p_data->data == NULL) { 1471 return BCM_E_MEMORY; 1472 } 1473 1474 if (!(f_presel->flags & _FP_ENTRY_DIRTY)) { 1475 /* Get entry Data Entry index. */ 1476 rv = _bcm_field_presel_entry_tcam_idx_get(unit, f_presel, 1477 f_presel->lt_fs, &data_idx); 1478 if (BCM_FAILURE(rv)) { 1479 goto bcm_error; 1480 } 1481 1482 /* Read entry part from hardware. */ 1483 rv = soc_mem_read(unit, lt_mem, MEM_BLOCK_ANY, data_idx, 1484 mem_entry); 1485 if (BCM_FAILURE(rv)) { 1486 goto bcm_error; 1487 } 1488 1489 if (!SOC_IS_TOMAHAWK3(unit)) { 1490 /* Get entry Data value. */ 1491 soc_mem_field_get(unit, lt_mem, mem_entry, DATAf, 1492 p_data->data); 1493 } 1494 } 1495 1496 return (BCM_E_NONE); 1497 1498 bcm_error: 1499 sal_free(p_data->data); 1500 p_data->data = NULL; 1501 return rv; 1502 } 1503 1504 1505 /* 1506 * Function: 1507 * _field_presel_qual_value_set 1508 * 1509 * Purpose: 1510 * Set a qualifier field from the designated data and mask arrays. 1511 * 1512 * Parameters: 1513 * unit - (IN) BCM devices number 1514 * stage_fc - (IN) Stage field control structure. 1515 * inst - (IN) Pipe Instance. 1516 * qi - (IN) Qualifier offset inside tcam. 1517 * f_presel - (IN) Field Presel entry descriptor. 1518 * p_data - (IN) Inserted data. 1519 * p_mask - (IN) Data mask. 1520 * Returns: 1521 * BCM_E_XXX 1522 */ 1523 STATIC int 1524 _field_presel_qual_value_set(int unit, _field_stage_t *stage_fc, 1525 int inst, _qual_info_t *qi, 1526 _field_presel_entry_t *f_presel, 1527 uint32 *p_data, uint32 *p_mask) 1528 { 1529 int rv; /* Operation return status. */ 1530 uint32 u32_mask, 1531 *p_fn_data, *p_fn_mask; 1532 int idx, wp, bp, len; 1533 1534 #undef DATA_TOO_BIG_FOR_FIELD 1535 #define DATA_TOO_BIG_FOR_FIELD ((p_data[idx] & ~u32_mask) != 0) 1536 1537 wp = qi->offset / 32; 1538 bp = qi->offset & (32 - 1); 1539 idx = 0; 1540 p_fn_data = p_fn_mask = NULL; 1541 1542 LOG_DEBUG(BSL_LS_BCM_FP, 1543 (BSL_META_U(unit, 1544 "vverb: qi={offset=%d, width=%d}, data=0x%08x, mask=0x%08x\n"), 1545 qi->offset, qi->width, *p_data, *p_mask)); 1546 1547 /* Allocate memory for TCAM Key and Mask. */ 1548 rv = _bcm_field_th_presel_tcam_key_mask_get(unit, stage_fc, inst, 1549 f_presel, &f_presel->lt_tcam); 1550 if (BCM_FAILURE(rv)) { 1551 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1552 "Error: Unable to allocate the Presel Entry TCAM Key and Mask.\n\r"))); 1553 return rv; 1554 } 1555 1556 switch (qi->fpf) { 1557 case KEYf: 1558 p_fn_data = f_presel->lt_tcam.key; 1559 p_fn_mask = f_presel->lt_tcam.mask; 1560 break; 1561 1562 default: 1563 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1564 "Error: Bad TCAM field=%#05x\n"), qi->fpf)); 1565 return (BCM_E_INTERNAL); 1566 }; 1567 1568 for (len = qi->width; len > 0; len -= 32) { 1569 if (bp) { 1570 if (len < 32) { 1571 u32_mask = (1 << len) - 1; 1572 /* Chop mask to fit mask field. */ 1573 p_mask[idx] &= u32_mask; 1574 if (DATA_TOO_BIG_FOR_FIELD) { 1575 LOG_ERROR(BSL_LS_BCM_FP, 1576 (BSL_META_U(unit, 1577 "FP(unit %d) Error: data=%#x "), 1578 unit, *p_data)); 1579 LOG_ERROR(BSL_LS_BCM_FP, 1580 (BSL_META_U(unit, 1581 "or mask=%#x too big for field\n"), 1582 *p_mask)); 1583 return (BCM_E_PARAM); 1584 } 1585 } else { 1586 u32_mask = 0xffffffff; 1587 } 1588 1589 p_fn_data[wp] &= ~(u32_mask << bp); 1590 p_fn_data[wp] |= p_data[idx] << bp; 1591 1592 /* coverity[ptr_arith : FALSE] */ 1593 p_fn_mask[wp] &= ~(u32_mask << bp); 1594 p_fn_mask[wp++] |= p_mask[idx] << bp; 1595 1596 p_fn_data[wp] &= ~(u32_mask >> (32 - bp)); 1597 p_fn_data[wp] |= p_data[idx] >> (32 - bp) & ((1 << bp) - 1); 1598 1599 p_fn_mask[wp] &= ~(u32_mask >> (32 - bp)); 1600 p_fn_mask[wp] |= p_mask[idx] >> (32 - bp) & ((1 << bp) - 1); 1601 } else { 1602 if (len < 32) { 1603 u32_mask = (1 << len) - 1; 1604 /* Chop mask to fit mask field. */ 1605 p_mask[idx] &= u32_mask; 1606 if (DATA_TOO_BIG_FOR_FIELD) { 1607 LOG_ERROR(BSL_LS_BCM_FP, 1608 (BSL_META_U(unit, 1609 "Error: data=%#x or mask=%#x " 1610 "too big for field\n\r"), 1611 *p_data, *p_mask)); 1612 return (BCM_E_PARAM); 1613 } 1614 p_fn_data[wp] &= ~u32_mask; 1615 p_fn_data[wp] |= p_data[idx]; 1616 /* coverity[ptr_arith : FALSE] */ 1617 p_fn_mask[wp] &= ~u32_mask; 1618 p_fn_mask[wp++] |= p_mask[idx]; 1619 } else { 1620 p_fn_data[wp] = p_data[idx]; 1621 /* coverity[ptr_arith : FALSE] */ 1622 p_fn_mask[wp++] = p_mask[idx]; 1623 } 1624 } 1625 1626 idx++; 1627 } 1628 1629 f_presel->flags |= _FP_ENTRY_DIRTY; 1630 f_presel->flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY); 1631 return (BCM_E_NONE); 1632 } 1633 #undef DATA_TOO_BIG_FOR_FIELD 1634 1635 1636 /* 1637 * Function: 1638 * _field_presel_qual_part_value_set 1639 * 1640 * Purpose: 1641 * Set a preselector qualifier field from the designated 1642 * data and mask arrays. 1643 * 1644 * Parameters: 1645 * unit - (IN) BCM devices number 1646 * stage_fc - (IN) Stage field control structure. 1647 * inst - (IN) Pipe Instance. 1648 * q_offset - (IN) Qualifier offset inside tcam. 1649 * qual_part - (IN) Split qualifier part. 1650 * f_presel - (IN) Field entry descriptor. 1651 * p_data - (IN) Inserted data. 1652 * p_mask - (IN) Data mask. 1653 * Returns: 1654 * BCM_E_XXX 1655 */ 1656 STATIC int 1657 _field_presel_qual_part_value_set(int unit, _field_stage_t *stage_fc, int inst, 1658 _bcm_field_qual_offset_t *q_offset, 1659 uint8 qual_part, 1660 _field_presel_entry_t *f_presel, 1661 uint32 *p_data, uint32 *p_mask) 1662 { 1663 int rv; /* Operation return status. */ 1664 int idx = 0, 1665 offset = 0; 1666 _qual_info_t qi; 1667 _bcm_field_qual_data_t data; 1668 _bcm_field_qual_data_t mask; 1669 1670 /* Input parameters check. */ 1671 if ((NULL == q_offset) || (NULL == f_presel) || 1672 (NULL == p_data) || (NULL == p_mask)) { 1673 return (BCM_E_PARAM); 1674 } 1675 1676 /* Primary offset handling. */ 1677 sal_memset(&qi, 0, sizeof(_qual_info_t)); 1678 qi.fpf = q_offset->field; 1679 qi.offset = q_offset->offset[qual_part]; 1680 qi.width = q_offset->width[qual_part]; 1681 /* calculate offset */ 1682 for (idx = 0; idx < qual_part; idx++) { 1683 offset += q_offset->width[idx]; 1684 } 1685 1686 /* Split primary portion of the qualifier. */ 1687 rv = _bcm_field_qual_partial_data_get (p_data, offset, 1688 qi.width, data); 1689 BCM_IF_ERROR_RETURN(rv); 1690 rv = _bcm_field_qual_partial_data_get(p_mask, offset, 1691 qi.width, mask); 1692 BCM_IF_ERROR_RETURN(rv); 1693 1694 /* Program qualifier into tcam */ 1695 rv = _field_presel_qual_value_set(unit, stage_fc, inst, &qi, 1696 f_presel, data, mask); 1697 return (rv); 1698 } 1699 1700 1701 /* 1702 * Function: 1703 * _bcm_field_presel_qual_value_set 1704 * 1705 * Purpose: 1706 * Set a preselector qual field from the designated data and mask arrays. 1707 * 1708 * Parameters: 1709 * unit - (IN) BCM devices number 1710 * stage_fc - (IN) Stage field control structure. 1711 * inst - (IN) Pipe Instance. 1712 * q_offset - (IN) Qualifier offset inside tcam. 1713 * f_presel - (IN) Field Preselector entry descriptor. 1714 * p_data - (IN) Inserted data. 1715 * p_mask - (IN) Data mask. 1716 * 1717 * Returns: 1718 * BCM_E_XXX 1719 */ 1720 1721 STATIC int 1722 _bcm_field_presel_qual_value_set(int unit, _field_stage_t *stage_fc, int inst, 1723 _bcm_field_qual_offset_t *q_offset, 1724 _field_presel_entry_t *f_presel, 1725 uint32 *p_data, uint32 *p_mask) 1726 { 1727 int rv; 1728 uint8 qual_part; 1729 1730 LOG_DEBUG(BSL_LS_BCM_FP, 1731 (BSL_META_U(unit, 1732 "_bcm_field_qual_value_set\n"))); 1733 1734 /* Input parameters check. */ 1735 if ((NULL == stage_fc) || (NULL == q_offset) || (NULL == f_presel) || 1736 (NULL == p_data) || (NULL == p_mask)) { 1737 return (BCM_E_PARAM); 1738 } 1739 1740 /* Iterate for the number of offsets handling. */ 1741 for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) { 1742 if (q_offset->width[qual_part] > 0) 1743 { 1744 rv = _field_presel_qual_part_value_set(unit, stage_fc, inst, 1745 q_offset, qual_part, f_presel, 1746 p_data, p_mask); 1747 BCM_IF_ERROR_RETURN(rv); 1748 } 1749 } 1750 1751 return (BCM_E_NONE); 1752 } 1753 1754 1755 /* 1756 * Function: _bcm_field_presel_qualify_set 1757 * 1758 * Purpose: 1759 * Qualify the presel for the given qualifier 1760 * 1761 * Parameters: 1762 * unit - (IN) BCM device number. 1763 * entry - (IN) Entry ID contains preselector Id. 1764 * qual - (IN) Qualifier Id. 1765 * data - (IN) Data 1766 * mask - (IN) Mask 1767 * 1768 * Returns: 1769 * BCM_E_PARAM - presel contained in entry id is not valid 1770 * or presel == NULL. 1771 * BCM_E_NOT_FOUND - presel id is not found. 1772 * BCM_E_NONE - returns on Success 1773 */ 1774 1775 int 1776 _bcm_field_presel_qualify_set(int unit, 1777 bcm_field_entry_t entry, 1778 bcm_field_qualify_t qual, 1779 uint32 *data, 1780 uint32 *mask) 1781 { 1782 int rv; /* Operation return status. */ 1783 int inst; /* Pipe Instance. */ 1784 int width; /* Qualifier Width. */ 1785 bcm_field_presel_t presel; /* Presel id. */ 1786 _field_presel_entry_t *f_presel = NULL; /* Presel Entry descriptor. */ 1787 _field_control_t *fc; /* Field control structure. */ 1788 _field_stage_t *stage_fc; /* Field Stage structure. */ 1789 _bcm_field_qual_offset_t q_offset; /* Qualifier offset instance. */ 1790 _field_stage_id_t stage_id; /* Stage id. */ 1791 1792 /* Preselector feature check */ 1793 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 1794 return BCM_E_UNAVAIL; 1795 } 1796 1797 /* Retrieve the control structure */ 1798 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 1799 1800 /* Resolve the Preselector ID from the given Entry ID */ 1801 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 1802 if (BCM_FAILURE(rv)) { 1803 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1804 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 1805 return rv; 1806 } 1807 1808 1809 /* Verify and update the mandate qualifier. */ 1810 if (qual == bcmFieldQualifyStage) { 1811 bcm_field_stage_t stage; 1812 1813 stage = *data; 1814 if (_BCM_FIELD_PRESEL_IS_STAGE_SUPPORTED(stage) == FALSE) { 1815 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1816 "ERROR: Preselector doesn't support the given stage:[%d].\n\r"), 1817 stage)); 1818 return BCM_E_PARAM; 1819 } 1820 1821 if ((stage == bcmFieldStageIngressFlowtracker) && 1822 ((!soc_feature(unit, soc_feature_field_flowtracker_support)) || 1823 (soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 1) != 1))) { 1824 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1825 "ERROR: Stage is not available."))); 1826 return BCM_E_UNAVAIL; 1827 } 1828 1829 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, qual)) { 1830 if (((stage == bcmFieldStageIngress) && 1831 (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1832 bcmFieldQualifyStageIngress))) || 1833 ((stage == bcmFieldStageIngressExactMatch) && 1834 (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1835 bcmFieldQualifyStageIngressExactMatch))) || 1836 ((stage == bcmFieldStageIngressFlowtracker) && 1837 (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1838 bcmFieldQualifyStageIngressFlowtracker)))) { 1839 return BCM_E_NONE; 1840 } 1841 1842 /* 1843 * If the entry's lt_tcam->key is not NULL, indicates some other 1844 * non-stage qualifier is associated to the presel entry. 1845 */ 1846 if (f_presel->lt_tcam.key != NULL) { 1847 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1848 "ERROR: Stage is already associated with the given Presel" 1849 " Entry[%d] and the entry is in use.\n\r"), presel)); 1850 return BCM_E_BUSY; 1851 } 1852 } 1853 1854 BCM_FIELD_QSET_INIT(f_presel->p_qset); 1855 BCM_FIELD_QSET_ADD(f_presel->p_qset, bcmFieldQualifyStage); 1856 if (stage == bcmFieldStageIngress) { 1857 BCM_FIELD_QSET_ADD(f_presel->p_qset, bcmFieldQualifyStageIngress); 1858 } else if (stage == bcmFieldStageIngressExactMatch) { 1859 BCM_FIELD_QSET_ADD(f_presel->p_qset, 1860 bcmFieldQualifyStageIngressExactMatch); 1861 } else { /* stage == bcmFieldStageIngressFlowtracker */ 1862 BCM_FIELD_QSET_ADD(f_presel->p_qset, 1863 bcmFieldQualifyStageIngressFlowtracker); 1864 } 1865 1866 return BCM_E_NONE; 1867 } else { 1868 /* Verify if the Presel Entry is already associated with the stage. */ 1869 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStage) 1870 == FALSE) { 1871 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1872 "ERROR: Preselector Entry[%d] doesn't associated with any stage." 1873 "\n\rIt is mandate to qualify the Stage first.\n\r"), presel)); 1874 return BCM_E_PARAM; 1875 } 1876 } 1877 1878 /* Retrieve the stage id. */ 1879 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) { 1880 stage_id = _BCM_FIELD_STAGE_INGRESS; 1881 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1882 bcmFieldQualifyStageIngressExactMatch)) { 1883 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 1884 #if defined(BCM_FLOWTRACKER_SUPPORT) 1885 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 1886 bcmFieldQualifyStageIngressFlowtracker)) { 1887 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 1888 #endif 1889 } else { 1890 return BCM_E_INTERNAL; 1891 } 1892 1893 /* Get stage field control structure. */ 1894 BCM_IF_ERROR_RETURN 1895 (_field_stage_control_get(unit, stage_id, &stage_fc)); 1896 1897 /* Pkt flow mandate qualifier */ 1898 if (qual == bcmFieldQualifyPktFlowType) { 1899 _bcm_field_internal_qualify_t _qual; 1900 1901 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, qual)) { 1902 return BCM_E_EXISTS; 1903 } 1904 1905 switch (*data) { 1906 case bcmFieldPktFlowTypeTunnelNone: 1907 _qual = _bcmFieldQualifyPktFlowTypeTunnelNone; 1908 break; 1909 case bcmFieldPktFlowTypeTunnelL2: 1910 _qual = _bcmFieldQualifyPktFlowTypeTunnelL2; 1911 break; 1912 case bcmFieldPktFlowTypeTunnelL3: 1913 _qual = _bcmFieldQualifyPktFlowTypeTunnelL3; 1914 break; 1915 default: 1916 return BCM_E_PARAM; 1917 } 1918 BCM_FIELD_QSET_ADD(f_presel->p_qset, qual); 1919 BCM_FIELD_QSET_ADD(f_presel->p_qset, _qual); 1920 return BCM_E_NONE; 1921 } 1922 1923 /* Verify if the given Qualifier belongs to Preselector QSET */ 1924 if (BCM_FIELD_QSET_TEST(stage_fc->presel_qset, qual) == FALSE) { 1925 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1926 "ERROR: Preselector Stage doesn't support the qualifier[%s].\n\r"), 1927 _field_qual_name(qual))); 1928 return BCM_E_PARAM; 1929 } 1930 1931 1932 /* Retrieve the qualifier offset */ 1933 rv = _field_presel_qual_offset_get(unit, stage_fc, f_presel, 1934 qual, &q_offset); 1935 if (BCM_FAILURE(rv)) { 1936 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1937 "ERROR: Unable to retrieve the qualifier's offset[%d].\n\r"), qual)); 1938 return rv; 1939 } 1940 1941 /* Check if the qualifier is associated to PktFlowType. */ 1942 if ((q_offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L2) || 1943 (q_offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L3) || 1944 (q_offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_NONE)) { 1945 if (!BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyPktFlowType)) { 1946 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 1947 "ERROR: Preselector Entry[%d] doesn't associated with any packet flow." 1948 "\n\rIt is mandate to associate the packet flow 'bcmFieldQualifyPktFlowType'" 1949 " prior to '%s' configuration.\n\r"), 1950 presel, _field_qual_name(qual))); 1951 return BCM_E_PARAM; 1952 } 1953 } 1954 1955 /* Combined width of a qualifier for a given part */ 1956 _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(&q_offset, width); 1957 1958 /* Validate the Qualifier Data with the offset's width. */ 1959 if (width < 32) { 1960 if (data[0] & ~((1 << width) - 1)) { 1961 return BCM_E_PARAM; 1962 } 1963 } 1964 1965 /* 1966 * Assuming Instance as 0, Pipe instance is unknown at this point and 1967 * and also it doesn't make any difference as key and mask fields for 1968 * a TCAM is same for all the instances. 1969 */ 1970 inst = 0; 1971 1972 /* Program data/mask pair to tcam buffer. */ 1973 /* coverity[callee_ptr_arith : FALSE] */ 1974 rv = _bcm_field_presel_qual_value_set(unit, stage_fc, inst, &q_offset, 1975 f_presel, data, mask); 1976 BCM_IF_ERROR_RETURN(rv); 1977 1978 BCM_FIELD_QSET_ADD(f_presel->p_qset, qual); 1979 f_presel->flags |= _FP_ENTRY_DIRTY; 1980 return BCM_E_NONE; 1981 } 1982 1983 /* 1984 * Function: 1985 * _field_presel_qual_value_get 1986 * 1987 * Purpose: 1988 * Retrieve a qualifier value from the designated data/mask 1989 * field pair, returning them to *p_data and *p_mask. 1990 * 1991 * Returns: 1992 * BCM_E_NONE - Success 1993 */ 1994 STATIC int 1995 _field_presel_qual_value_get(int unit, _field_stage_t *stage_fc, int inst, 1996 _qual_info_t *qi, _field_presel_entry_t *f_presel, 1997 uint32 *p_data, uint32 *p_mask) 1998 { 1999 int rv; /* Operation return status. */ 2000 uint32 *p_fn_data, *p_fn_mask; 2001 int idx, wp, bp, len; 2002 2003 /* Input parameters check. */ 2004 if ((NULL == f_presel) || (NULL == p_data) || 2005 (NULL == qi) || (NULL == p_mask)) { 2006 return (BCM_E_PARAM); 2007 } 2008 2009 wp = qi->offset / 32; 2010 bp = qi->offset & (32 - 1); 2011 idx = 0; 2012 p_fn_data = p_fn_mask = NULL; 2013 2014 /* Allocate memory for TCAM Key and Mask. */ 2015 rv = _bcm_field_th_presel_tcam_key_mask_get(unit, stage_fc, inst, 2016 f_presel, &f_presel->lt_tcam); 2017 if (BCM_FAILURE(rv)) { 2018 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2019 "Error: Unable to allocate the Presel Entry TCAM Key and Mask.\n\r"))); 2020 return rv; 2021 } 2022 2023 switch (qi->fpf) { 2024 case KEYf: 2025 p_fn_data = f_presel->lt_tcam.key; 2026 p_fn_mask = f_presel->lt_tcam.mask; 2027 break; 2028 default: 2029 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2030 "Error: Bad TCAM field=%#05x\n"), qi->fpf)); 2031 return (BCM_E_INTERNAL); 2032 }; 2033 2034 for (len = qi->width; len > 0; len -= 32) { 2035 if ((NULL == p_fn_data) || (NULL == p_fn_mask)) { 2036 /* 2037 * IPBM Overlay qualifier set in the group but 2038 * not qualified for this entry. 2039 */ 2040 p_data[idx] = 0x0; 2041 p_mask[idx] = 0x0; 2042 } else { 2043 if (bp) { 2044 p_data[idx] = (p_fn_data[wp] >> bp) & ((1 << (32 - bp)) - 1); 2045 /* coverity[ptr_arith : FALSE] */ 2046 p_mask[idx] = (p_fn_mask[wp++] >> bp) & ((1 << (32 - bp)) - 1); 2047 p_data[idx] |= p_fn_data[wp] << (32 - bp); 2048 p_mask[idx] |= p_fn_mask[wp] << (32 - bp); 2049 } else { 2050 p_data[idx] = p_fn_data[wp]; 2051 /* coverity[ptr_arith : FALSE] */ 2052 p_mask[idx] = p_fn_mask[wp++]; 2053 } 2054 } 2055 2056 if (len < 32) { 2057 p_data[idx] &= ((1 << len) - 1); 2058 p_mask[idx] &= ((1 << len) - 1); 2059 } 2060 2061 idx++; 2062 } 2063 2064 return (BCM_E_NONE); 2065 } 2066 2067 2068 2069 /* 2070 * Function: 2071 * _field_presel_qual_part_value_get 2072 * 2073 * Purpose: 2074 * Get a qualifier field from the designated data and mask arrays. 2075 * 2076 * Parameters: 2077 * unit - (IN) BCM devices number 2078 * stage_fc - (IN) Stage field control structure. 2079 * inst - (IN) Pipe Instance. 2080 * q_offset - (IN) Qualifier offset inside tcam. 2081 * f_presel - (IN) Field Presel entry descriptor. 2082 * p_data - (IN) Inserted data. 2083 * p_mask - (IN) Data mask. 2084 * 2085 * Returns: 2086 * BCM_E_XXX 2087 */ 2088 STATIC int 2089 _field_presel_qual_part_value_get(int unit, _field_stage_t *stage_fc, int inst, 2090 _bcm_field_qual_offset_t *q_offset, 2091 uint8 qual_part, 2092 _field_presel_entry_t *f_presel, 2093 _bcm_field_qual_data_t p_data, 2094 _bcm_field_qual_data_t p_mask) 2095 { 2096 _qual_info_t qi; 2097 int rv; 2098 _bcm_field_qual_data_t data; 2099 _bcm_field_qual_data_t mask; 2100 int offset = 0, idx = 0; 2101 2102 /* Input parameters check. */ 2103 if ((NULL == stage_fc) || (NULL == q_offset) || (NULL == f_presel) || 2104 (NULL == p_data) || (NULL == p_mask)) { 2105 return (BCM_E_PARAM); 2106 } 2107 2108 /* Primary offset handling. */ 2109 sal_memset(&qi, 0, sizeof(_qual_info_t)); 2110 2111 _FP_QUAL_DATA_CLEAR(data); 2112 _FP_QUAL_DATA_CLEAR(mask); 2113 qi.fpf = q_offset->field; 2114 qi.offset = q_offset->offset[qual_part]; 2115 qi.width = q_offset->width[qual_part]; 2116 /* calculate offset */ 2117 for (idx = 0; idx < qual_part; idx++) { 2118 offset += q_offset->width[idx]; 2119 } 2120 2121 /* Read qualifier information from tcam.. */ 2122 rv = _field_presel_qual_value_get(unit, stage_fc, inst, &qi, 2123 f_presel, data, mask); 2124 BCM_IF_ERROR_RETURN(rv); 2125 2126 /* Split primary portion of the qualifier. */ 2127 rv = _bcm_field_qual_partial_data_set(data, offset, 2128 qi.width, p_data); 2129 BCM_IF_ERROR_RETURN(rv); 2130 rv = _bcm_field_qual_partial_data_set(mask, offset, 2131 qi.width, p_mask); 2132 BCM_IF_ERROR_RETURN(rv); 2133 2134 return (BCM_E_NONE); 2135 } 2136 2137 2138 /* 2139 * Function: 2140 * _bcm_field_presel_value_get 2141 * 2142 * Purpose: 2143 * Get a qualifier field from the designated data and mask arrays. 2144 * 2145 * Parameters: 2146 * unit - (IN) BCM devices number 2147 * stage_fc - (IN) Stage field control structure. 2148 * inst - (IN) Pipe Instance. 2149 * q_offset - (IN) Qualifier offset inside tcam. 2150 * f_presel - (IN) Field presel entry descriptor. 2151 * p_data - (IN) Inserted data. 2152 * p_mask - (IN) Data mask. 2153 * 2154 * Returns: 2155 * BCM_E_XXX 2156 */ 2157 STATIC int 2158 _bcm_field_presel_qual_value_get(int unit, _field_stage_t *stage_fc, int inst, 2159 _bcm_field_qual_offset_t *q_offset, 2160 _field_presel_entry_t *f_presel, 2161 _bcm_field_qual_data_t p_data, 2162 _bcm_field_qual_data_t p_mask) 2163 { 2164 int rv, qual_part; 2165 2166 /* Input parameters check. */ 2167 if ((NULL == stage_fc) || (NULL == q_offset) || (NULL == f_presel) || 2168 (NULL == p_data) || (NULL == p_mask)) { 2169 return (BCM_E_PARAM); 2170 } 2171 2172 _FP_QUAL_DATA_CLEAR(p_data); 2173 _FP_QUAL_DATA_CLEAR(p_mask); 2174 2175 /* offset handling */ 2176 for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) { 2177 if (q_offset->width[qual_part] > 0) 2178 { 2179 rv = _field_presel_qual_part_value_get(unit, stage_fc, inst, 2180 q_offset, qual_part, 2181 f_presel, p_data, p_mask); 2182 BCM_IF_ERROR_RETURN(rv); 2183 } 2184 } 2185 2186 return (BCM_E_NONE); 2187 } 2188 2189 2190 /* 2191 * Function: 2192 * _bcm_field_presel_qualifier_get 2193 * 2194 * Purpose: 2195 * Get qualifier match value and mask. 2196 * 2197 * Parameters: 2198 * unit - BCM device number 2199 * entry - Entry id. 2200 * qual_id - qualifier id. 2201 * q_data - Qualifier data array. 2202 * q_mask - Qualifier mask array. 2203 * Returns: 2204 * Nothing. 2205 */ 2206 int 2207 _bcm_field_presel_qualifier_get(int unit, 2208 bcm_field_entry_t entry, 2209 int qual_id, 2210 _bcm_field_qual_data_t q_data, 2211 _bcm_field_qual_data_t q_mask) 2212 { 2213 _bcm_field_qual_offset_t q_offset; /* Qualifier offset in the tcam. */ 2214 _field_presel_entry_t *f_presel; /* Field entry structure. */ 2215 bcm_field_presel_t presel; /* Field Preselector ID. */ 2216 int rv; /* Operation return status. */ 2217 int inst; /* Pipe Instance. */ 2218 _field_stage_t *stage_fc; 2219 _field_control_t *fc; 2220 _field_stage_id_t stage_id; /* Stage id. */ 2221 2222 /* Preselector feature check */ 2223 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 2224 return BCM_E_UNAVAIL; 2225 } 2226 2227 /* Retrieve the control structure */ 2228 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 2229 2230 /* Resolve the Preselector ID from the given Entry ID */ 2231 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 2232 if (BCM_FAILURE(rv)) { 2233 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2234 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 2235 return rv; 2236 } 2237 2238 /* Verify and update the mandate qualifier. */ 2239 if (qual_id == bcmFieldQualifyStage) { 2240 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) { 2241 q_data[0] = q_mask[0] = bcmFieldStageIngress; 2242 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 2243 bcmFieldQualifyStageIngressExactMatch)) { 2244 q_data[0] = q_mask[0] = bcmFieldStageIngressExactMatch; 2245 #if defined(BCM_FLOWTRACKER_SUPPORT) 2246 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 2247 bcmFieldQualifyStageIngressFlowtracker)) { 2248 q_data[0] = q_mask[0] = bcmFieldStageIngressFlowtracker; 2249 #endif 2250 } 2251 return BCM_E_NONE; 2252 } 2253 2254 if (qual_id == bcmFieldQualifyPktFlowType) { 2255 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, _bcmFieldQualifyPktFlowTypeTunnelNone)) { 2256 q_data[0] = q_mask[0] = bcmFieldPktFlowTypeTunnelNone; 2257 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, _bcmFieldQualifyPktFlowTypeTunnelL3)) { 2258 q_data[0] = q_mask[0] = bcmFieldPktFlowTypeTunnelL3; 2259 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, _bcmFieldQualifyPktFlowTypeTunnelL2)) { 2260 q_data[0] = q_mask[0] = bcmFieldPktFlowTypeTunnelL2; 2261 } else { 2262 return BCM_E_NOT_FOUND; 2263 } 2264 return BCM_E_NONE; 2265 } 2266 2267 /* Retrieve the stage id. */ 2268 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) { 2269 stage_id = _BCM_FIELD_STAGE_INGRESS; 2270 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 2271 bcmFieldQualifyStageIngressExactMatch)) { 2272 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 2273 #if defined(BCM_FLOWTRACKER_SUPPORT) 2274 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 2275 bcmFieldQualifyStageIngressFlowtracker)) { 2276 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 2277 #endif 2278 } else { 2279 return BCM_E_INTERNAL; 2280 } 2281 2282 /* Get stage field control structure. */ 2283 BCM_IF_ERROR_RETURN 2284 (_field_stage_control_get(unit, stage_id, &stage_fc)); 2285 2286 2287 /* Verify if the given Qualifier belongs to Preselector QSET */ 2288 if (BCM_FIELD_QSET_TEST(stage_fc->presel_qset, qual_id) == FALSE) { 2289 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2290 "ERROR: Preselector Stage doesn't support the qualifier[%s].\n\r"), 2291 _field_qual_name(qual_id))); 2292 return BCM_E_PARAM; 2293 } 2294 2295 /* Initialize q_offset to NULL */ 2296 sal_memset(&q_offset, 0x0, sizeof(q_offset)); 2297 2298 /* Retrieve the Qualifier offsets */ 2299 rv = _field_presel_qual_offset_get(unit, stage_fc, f_presel, 2300 qual_id, &q_offset); 2301 if (BCM_FAILURE(rv)) { 2302 return rv; 2303 } 2304 2305 /* Instance setting to 0 */ 2306 inst = 0; 2307 2308 /* Read qualifier match value and mask. */ 2309 rv = _bcm_field_presel_qual_value_get(unit, stage_fc, inst, &q_offset, 2310 f_presel, q_data, q_mask); 2311 return (BCM_E_NONE); 2312 } 2313 2314 #if defined(BCM_TOMAHAWK_SUPPORT) 2315 /* 2316 * Dump Preselector Qualifiers. 2317 */ 2318 int 2319 _bcm_field_presel_qualifiers_dump(int unit, bcm_field_presel_t presel_id) 2320 { 2321 _bcm_field_qual_offset_t q_offset; /* Qualifier offset in the tcam. */ 2322 _field_presel_entry_t *f_presel; /* Field entry structure. */ 2323 bcm_field_entry_t entry; /* Field entry structure. */ 2324 int rv; /* Operation return status. */ 2325 int inst = 0; /* Pipe Instance. */ 2326 int idx = 0; 2327 int num_qual = 0; 2328 _field_stage_t *stage_fc; 2329 _field_control_t *fc; 2330 _bcm_field_qual_data_t q_data; 2331 _bcm_field_qual_data_t q_mask; 2332 int qual_id; 2333 _field_stage_id_t stage_id; /* Stage id. */ 2334 bcm_field_src_class_t data; /* MixedSrcClassId data */ 2335 bcm_field_src_class_t mask; /* MixedSrcClassId mask */ 2336 2337 /* Preselector feature check */ 2338 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 2339 return BCM_E_UNAVAIL; 2340 } 2341 2342 /* Retrieve the control structure */ 2343 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 2344 2345 /* Check if presel ID present in presel_set */ 2346 if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel_id)) { 2347 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2348 "ERROR: Preselector ID[%d] not found.\n\r"), presel_id)); 2349 return BCM_E_NOT_FOUND; 2350 } 2351 2352 /* Retrieve the Presel Entry */ 2353 rv = _bcm_field_presel_entry_get(unit, presel_id, &f_presel); 2354 if (BCM_FAILURE(rv)) { 2355 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2356 "ERROR: Couldn't retrieve the Preselector Entry for the given" 2357 " Presel ID[%d].\n\r"), presel_id)); 2358 return rv; 2359 } 2360 2361 /* Retrieve the stage id. */ 2362 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) { 2363 stage_id = _BCM_FIELD_STAGE_INGRESS; 2364 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 2365 bcmFieldQualifyStageIngressExactMatch)) { 2366 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 2367 #if defined(BCM_FLOWTRACKER_SUPPORT) 2368 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 2369 bcmFieldQualifyStageIngressFlowtracker)) { 2370 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 2371 #endif 2372 } else { 2373 return BCM_E_INTERNAL; 2374 } 2375 2376 /* Get stage field control structure. */ 2377 BCM_IF_ERROR_RETURN 2378 (_field_stage_control_get(unit, stage_id, &stage_fc)); 2379 2380 /* Get the entry ID from presel ID */ 2381 BCM_FIELD_PRESEL_ENTRY_SET(entry, presel_id); 2382 2383 for (qual_id = 0; qual_id < _bcmFieldQualifyCount; qual_id++) { 2384 /* Verify if the given Qualifier belongs to Preselector QSET */ 2385 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, qual_id) == FALSE) { 2386 continue; 2387 } 2388 2389 if ((qual_id == bcmFieldQualifyStage) || 2390 (qual_id == bcmFieldQualifyStageIngress) || 2391 (qual_id == bcmFieldQualifyStageIngressExactMatch) || 2392 (qual_id == bcmFieldQualifyStageIngressFlowtracker) || 2393 (qual_id == _bcmFieldQualifyPktFlowTypeTunnelNone) || 2394 (qual_id == _bcmFieldQualifyPktFlowTypeTunnelL2) || 2395 (qual_id == _bcmFieldQualifyPktFlowTypeTunnelL3) || 2396 (qual_id == bcmFieldQualifyPktFlowType)) { 2397 continue; 2398 } 2399 2400 LOG_CLI((BSL_META_U(unit, " %-10s\n\r"), _field_qual_name(qual_id))); 2401 /* Initialize q_offset to NULL */ 2402 sal_memset(&q_offset, 0x0, sizeof(q_offset)); 2403 2404 /* Retrieve the Qualifier offsets */ 2405 rv = _field_presel_qual_offset_get(unit, stage_fc, f_presel, 2406 qual_id, &q_offset); 2407 if (BCM_FAILURE(rv)) { 2408 return rv; 2409 } 2410 2411 /* Instance setting to 0 */ 2412 inst = 0; 2413 2414 _FP_QUAL_DATA_CLEAR(q_data); 2415 _FP_QUAL_DATA_CLEAR(q_mask); 2416 2417 /* Read qualifier match value and mask. */ 2418 BCM_IF_ERROR_RETURN (_bcm_field_presel_qual_value_get(unit, stage_fc, 2419 inst, &q_offset, f_presel, q_data, q_mask)); 2420 for (idx = 0; idx <q_offset.num_offsets; idx++) { 2421 LOG_CLI((BSL_META_U(unit, "\tOffset: %-2d Width: %-2d\n\r"), 2422 q_offset.offset[idx], q_offset.width[idx])); 2423 } 2424 2425 LOG_CLI((BSL_META_U(unit, "\tData: 0x%x\n\r"), q_data[0])); 2426 LOG_CLI((BSL_META_U(unit, "\tMask: 0x%x\n\r"), q_mask[0])); 2427 2428 /* if qualifier is MixedSrcClassId */ 2429 /* print the detailed data and mask */ 2430 if ((qual_id == bcmFieldQualifyMixedSrcClassId)) { 2431 BCM_IF_ERROR_RETURN( 2432 _bcm_field_th_qualify_MixedSrcClassId_get(unit, 2433 entry, f_presel->mixed_src_class_pbmp, 2434 q_data[0], q_mask[0], &data, &mask)); 2435 if (mask.src_class_field != 0) { 2436 LOG_CLI((BSL_META_U(unit, "\tSrc Class Data: 0x%x\n\r"), data.src_class_field)); 2437 LOG_CLI((BSL_META_U(unit, "\tSrc Class Mask: 0x%x\n\r"), mask.src_class_field)); 2438 } 2439 if (mask.dst_class_field != 0) { 2440 LOG_CLI((BSL_META_U(unit, "\tDst Class Data: 0x%x\n\r"), data.dst_class_field)); 2441 LOG_CLI((BSL_META_U(unit, "\tDst Class Mask: 0x%x\n\r"), mask.dst_class_field)); 2442 } 2443 if (mask.udf_class != 0) { 2444 LOG_CLI((BSL_META_U(unit, "\tUdf Class Data: 0x%x\n\r"), data.udf_class)); 2445 LOG_CLI((BSL_META_U(unit, "\tUdf Class Mask: 0x%x\n\r"), mask.udf_class)); 2446 } 2447 if (mask.intf_class_port != 0) { 2448 LOG_CLI((BSL_META_U(unit, "\tIntf Class Port Data: 0x%x\n\r"), data.intf_class_port)); 2449 LOG_CLI((BSL_META_U(unit, "\tIntf Class Port Mask: 0x%x\n\r"), mask.intf_class_port)); 2450 } 2451 if (mask.intf_class_l2 != 0) { 2452 LOG_CLI((BSL_META_U(unit, "\tIntf Class L2 Data: 0x%x\n\r"), data.intf_class_l2)); 2453 LOG_CLI((BSL_META_U(unit, "\tIntf Class L2 Mask: 0x%x\n\r"), mask.intf_class_l2)); 2454 } 2455 } 2456 /* Reference count */ 2457 num_qual = 1; 2458 } 2459 2460 if (num_qual == 0) { 2461 LOG_CLI((BSL_META_U(unit, "No Qualifiers Associated.\n\r"))); 2462 } 2463 return BCM_E_NONE; 2464 } 2465 2466 #endif /* BCM_TOMAHAWK_SUPPORT */ 2467 2468 /* 2469 * Function: 2470 * _bcm_field_presel_action_params_check 2471 * Purpose: 2472 * Check field action parameters. 2473 * Parameters: 2474 * unit - (IN) BCM device number 2475 * stage_fc - (IN) Stage field control structure. 2476 * inst - (IN) Pipe Instance. 2477 * f_presel - (IN) Field Preselector entry structure. 2478 * fa - (IN) Field action structure. 2479 * action - (IN) Field Action of type bcmFieldActionXXX. 2480 * Returns: 2481 * BCM_E_XXX 2482 */ 2483 STATIC int 2484 _bcm_field_presel_action_params_check(int unit, 2485 _field_stage_t *stage_fc, 2486 int inst, 2487 _field_presel_entry_t *f_presel, 2488 _field_action_t *fa) 2489 { 2490 _field_action_params_t params; /* Field Params Structutre. */ 2491 bcm_field_action_t action; /* Field Action of Type bcmFieldActionXXX. */ 2492 soc_mem_t data_mem; 2493 2494 /* Validate input parameters */ 2495 if (NULL == stage_fc || NULL == f_presel || NULL == fa) { 2496 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META("Invalid Parameters\n"))); 2497 return BCM_E_PARAM; 2498 } 2499 2500 sal_memset(¶ms , 0, sizeof(params)); 2501 2502 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 2503 BCM_IF_ERROR_RETURN 2504 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst, 2505 _BCM_FIELD_MEM_TYPE_IFP_LT, 2506 _BCM_FIELD_MEM_VIEW_TYPE_DATA, 2507 NULL, &data_mem)); 2508 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 2509 BCM_IF_ERROR_RETURN 2510 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst, 2511 _BCM_FIELD_MEM_TYPE_EM_LT, 2512 _BCM_FIELD_MEM_VIEW_TYPE_DATA, 2513 NULL, &data_mem)); 2514 } else { 2515 return BCM_E_PARAM; 2516 } 2517 2518 action = fa->action; 2519 switch (action) { 2520 case bcmFieldActionGroupClassSet: 2521 PolicyCheck(unit, data_mem, LOGICAL_TABLE_CLASS_IDf, fa->param[0]); 2522 break; 2523 case bcmFieldActionGroupLookupDisable: 2524 break; 2525 default: 2526 return BCM_E_PARAM; 2527 break; 2528 } 2529 2530 return BCM_E_NONE; 2531 } 2532 2533 /* 2534 * Function: 2535 * _field_presel_entry_action_set 2536 * Purpose: 2537 * Set the action to the given Preselector Entry Data buffer 2538 * Parameters: 2539 * unit - (IN) BCM device number 2540 * data_mem - (IN) LT Data Memory 2541 * f_presel - (IN) Reference to Preselector Entry structure. 2542 * fa - (IN) field action 2543 * buf - (OUT) Entry data buffer. 2544 * Returns: 2545 * BCM_E_XXX 2546 */ 2547 STATIC int 2548 _field_presel_entry_action_set(int unit, soc_mem_t data_mem, 2549 _field_presel_entry_t *f_presel, 2550 _field_action_t *fa, uint32 *buf) 2551 { 2552 /* Input parameters check. */ 2553 if ((NULL == f_presel) || (NULL == fa) || (NULL == buf)) { 2554 return (BCM_E_PARAM); 2555 } 2556 2557 switch (fa->action) { 2558 case bcmFieldActionGroupClassSet: 2559 soc_mem_field32_set(unit, data_mem, buf, LOGICAL_TABLE_CLASS_IDf, 2560 fa->param[0]); 2561 break; 2562 case bcmFieldActionGroupLookupDisable: 2563 soc_mem_field32_set(unit, data_mem, buf, ENABLEf, 0); 2564 break; 2565 default: 2566 return BCM_E_INTERNAL; 2567 break; 2568 } 2569 2570 return BCM_E_NONE; 2571 } 2572 2573 /* 2574 * Function: 2575 * _bcm_field_presel_entry_actions_set 2576 * Purpose: 2577 * Set the actions to the given Preselector Entry Data buffer 2578 * Parameters: 2579 * unit - (IN) BCM device number 2580 * data_mem - (IN) LT Data Memory 2581 * f_presel - (IN) Reference to Preselector Entry structure. 2582 * fa - (IN) field action 2583 * buf - (OUT) Entry data buffer. 2584 * Returns: 2585 * BCM_E_NONE 2586 * BCM_E_PARAM - Action parameter out-of-range or unrecognized action. 2587 */ 2588 int 2589 _bcm_field_presel_entry_actions_set(int unit, soc_mem_t data_mem, 2590 _field_presel_entry_t *f_presel, 2591 uint32 *buf) 2592 { 2593 _field_action_t *fa_iter; /* Presel actions iterator. */ 2594 2595 /* Input parameters check. */ 2596 if ((NULL == f_presel) || (NULL == buf)) { 2597 return (BCM_E_PARAM); 2598 } 2599 2600 /* Assign Action to the Preselector entry */ 2601 for (fa_iter = f_presel->actions; fa_iter != NULL; fa_iter = fa_iter->next) 2602 { 2603 BCM_IF_ERROR_RETURN 2604 (_field_presel_entry_action_set(unit, data_mem, f_presel, 2605 fa_iter, buf)); 2606 } 2607 2608 return BCM_E_NONE; 2609 } 2610 2611 2612 /* 2613 * Function: _bcm_field_presel_action_add 2614 * 2615 * Purpose: 2616 * Associate the action descriptor to the preselector entry. 2617 * 2618 * Parameters: 2619 * unit - (IN) BCM device number. 2620 * fc - (IN) Field control structure. 2621 * entry - (IN) Field Preselector Entry id. 2622 * fa - (IN) Field action structure. 2623 * Returns: 2624 * BCM_E_XXX 2625 */ 2626 int 2627 _bcm_field_presel_action_add(int unit, _field_control_t *fc, 2628 bcm_field_entry_t entry, _field_action_t *fa) 2629 { 2630 int rv; /* Operation return status. */ 2631 _field_presel_entry_t *f_presel; /* Presel entry structure. */ 2632 _field_action_t *fa_iter; /* Presel actions iterator. */ 2633 _field_action_t *fa_prev_ptr=NULL; /* Action previous pointer. */ 2634 _field_stage_t *stage_fc; /* Reference to stage control. */ 2635 _field_stage_id_t stage_id; /* Stage id. */ 2636 bcm_field_presel_t presel; /* Field Preselector ID. */ 2637 2638 /* Input parameters check. */ 2639 if ((NULL == fc) || (NULL == fa)) { 2640 return (BCM_E_PARAM); 2641 } 2642 2643 /* Preselector feature check */ 2644 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 2645 return BCM_E_UNAVAIL; 2646 } 2647 2648 /* Resolve the Preselector ID from the given Entry ID */ 2649 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 2650 if (BCM_FAILURE(rv)) { 2651 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2652 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 2653 return rv; 2654 } 2655 2656 /* Verify if the Presel ID is already in USE */ 2657 if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel) && 2658 !(f_presel->flags & _FP_ENTRY_DIRTY)) { 2659 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2660 "ERROR: Preselector ID[%d] is in USE.\n\r"), presel)); 2661 return BCM_E_BUSY; 2662 } 2663 2664 /* Retrieve the stage id. */ 2665 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) { 2666 stage_id = _BCM_FIELD_STAGE_INGRESS; 2667 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 2668 bcmFieldQualifyStageIngressExactMatch)) { 2669 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 2670 #if defined(BCM_FLOWTRACKER_SUPPORT) 2671 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 2672 bcmFieldQualifyStageIngressFlowtracker)) { 2673 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 2674 #endif 2675 } else { 2676 return BCM_E_INTERNAL; 2677 } 2678 2679 #if defined(BCM_FLOWTRACKER_SUPPORT) 2680 if (_BCM_FIELD_STAGE_FLOWTRACKER == stage_id) { 2681 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2682 "ERROR: Presel Action is not supported in this stage\n\r"))); 2683 return BCM_E_UNAVAIL; 2684 } 2685 #endif 2686 2687 /* Get stage field control structure. */ 2688 BCM_IF_ERROR_RETURN 2689 (_field_stage_control_get(unit, stage_id, &stage_fc)); 2690 2691 /* Verify the Params */ 2692 rv = _bcm_field_presel_action_params_check(unit, stage_fc, 0, f_presel, fa); 2693 if (BCM_FAILURE(rv)) { 2694 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2695 "ERROR: Invalid Preselector Action Parameters.\n\r"))); 2696 return rv; 2697 } 2698 2699 /* Assign Action to the Preselector entry */ 2700 for (fa_iter = f_presel->actions; 2701 fa_iter != NULL; 2702 fa_iter = fa_iter->next) { 2703 if (fa_iter->action == fa->action) { 2704 fa->next = fa_iter->next; 2705 if (fa_prev_ptr == NULL) { 2706 f_presel->actions = fa; 2707 } else { 2708 fa_prev_ptr->next = fa; 2709 } 2710 sal_free (fa_iter); 2711 return BCM_E_NONE; 2712 } 2713 fa_prev_ptr = fa_iter; 2714 } 2715 2716 /* Add action to the front of presel entry's linked-list */ 2717 fa->next = f_presel->actions; 2718 f_presel->actions = fa; 2719 2720 return BCM_E_NONE; 2721 } 2722 2723 /* 2724 * Function: 2725 * _bcm_field_presel_action_delete 2726 * Purpose: 2727 * Delete field action from a field preselector entry. 2728 * Parameters: 2729 * unit - (IN) BCM device number 2730 * entry - (IN) Entry ID 2731 * action - (IN) Action to remove (bcmFieldActionXXX) 2732 * param0 - (IN) Action parameter (use 0 if not required) 2733 * param1 - (IN) Action parameter (use 0 if not required) 2734 * Returns: 2735 * BCM_E_XXX 2736 * Notes: 2737 */ 2738 int 2739 _bcm_field_presel_action_delete(int unit, bcm_field_entry_t entry, 2740 bcm_field_action_t action, 2741 uint32 param0, uint32 param1) 2742 { 2743 int rv; /* Operation return status. */ 2744 _field_presel_entry_t *f_presel; /* Presel entry structure. */ 2745 _field_action_t *fa_iter; /* Presel actions iterator. */ 2746 _field_action_t *fa_prev_ptr=NULL; /* Action previous pointer. */ 2747 _field_control_t *fc; /* Field control structure. */ 2748 bcm_field_presel_t presel; /* Field Preselector ID. */ 2749 2750 /* Preselector feature check */ 2751 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 2752 return BCM_E_UNAVAIL; 2753 } 2754 2755 /* Resolve the Preselector ID from the given Entry ID */ 2756 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 2757 if (BCM_FAILURE(rv)) { 2758 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2759 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 2760 return rv; 2761 } 2762 2763 /* Retrieve the control structure */ 2764 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 2765 2766 /* Verify if the Presel ID is already in USE */ 2767 if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel) && 2768 !(f_presel->flags & _FP_ENTRY_DIRTY)) { 2769 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2770 "ERROR: Preselector ID[%d] is in USE.\n\r"), presel)); 2771 return BCM_E_BUSY; 2772 } 2773 2774 /* Search and Delete the Action from the Preselector entry */ 2775 for (fa_iter = f_presel->actions; 2776 fa_iter != NULL; 2777 fa_iter = fa_iter->next) { 2778 if (fa_iter->action == action) { 2779 if (fa_prev_ptr == NULL) { 2780 f_presel->actions = fa_iter->next; 2781 } else { 2782 fa_prev_ptr->next = fa_iter->next; 2783 } 2784 sal_free (fa_iter); 2785 return BCM_E_NONE; 2786 } 2787 fa_prev_ptr = fa_iter; 2788 } 2789 2790 return BCM_E_NONE; 2791 } 2792 2793 /* 2794 * Function: _bcm_field_presel_action_get 2795 * 2796 * Purpose: 2797 * Get parameters associated with the preselection entry action 2798 * 2799 * Parameters: 2800 * unit - (IN) BCM device number 2801 * entry - (IN) Preselector Entry ID 2802 * action - (IN) Action to perform (bcmFieldActionXXX) 2803 * param0 - (OUT) Action parameter 2804 * param1 - (OUT) Action parameter 2805 * 2806 * Returns: 2807 * BCM_E_INIT - BCM Unit not initialized 2808 * BCM_E_NOT_FOUND - Entry ID not found 2809 * BCM_E_NOT_FOUND - No matching Action for entry 2810 * BCM_E_PARAM - paramX is NULL 2811 * BCM_E_NONE - Success 2812 */ 2813 2814 int 2815 _bcm_field_presel_action_get(int unit, 2816 bcm_field_entry_t entry, 2817 bcm_field_action_t action, 2818 uint32 *param0, 2819 uint32 *param1) 2820 { 2821 int rv; /* Operation return status. */ 2822 _field_presel_entry_t *f_presel; /* Presel entry structure. */ 2823 _field_action_t *fa; /* Presel actions iterator. */ 2824 _field_control_t *fc; /* Field control structure. */ 2825 bcm_field_presel_t presel; /* Field Preselector ID. */ 2826 2827 /* Input parameters check. */ 2828 if ((NULL == param0) || (NULL == param1)) { 2829 return (BCM_E_PARAM); 2830 } 2831 2832 /* Resolve the Preselector ID from the given Entry ID */ 2833 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 2834 if (BCM_FAILURE(rv)) { 2835 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2836 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 2837 return rv; 2838 } 2839 2840 /* Retrieve the control structure */ 2841 FP_LOCK(unit); 2842 rv = _field_control_get(unit, &fc); 2843 if (BCM_FAILURE(rv)) { 2844 FP_UNLOCK(unit); 2845 return rv; 2846 } 2847 2848 /* Find matching action in the entry */ 2849 for (fa = f_presel->actions; fa != NULL; fa = fa->next) { 2850 if (fa->action == action) { 2851 break; 2852 } 2853 } 2854 2855 if (fa == NULL) { 2856 FP_UNLOCK(unit); 2857 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 2858 "Error: Action[%d] not found in the preselector entry[0x%x]\n\r"), 2859 action, entry)); 2860 return (BCM_E_NOT_FOUND); 2861 } 2862 2863 *param0 = fa->param[0]; 2864 *param1 = fa->param[1]; 2865 2866 /* Unlock the module. */ 2867 FP_UNLOCK(unit); 2868 return (rv); 2869 } 2870 2871 /* 2872 * Function: _bcm_field_presel_action_remove_all 2873 * 2874 * Purpose: 2875 * Remove all actions from a preselector entry rule. 2876 * 2877 * Parameters: 2878 * unit - (IN) BCM device number 2879 * entry - (IN) Preselector Entry ID 2880 * 2881 * Returns: 2882 * BCM_E_INIT - BCM Unit not initialized 2883 * BCM_E_NOT_FOUND - Entry ID not found 2884 * BCM_E_NONE - Success 2885 */ 2886 2887 STATIC int 2888 _bcm_field_presel_action_remove_all(int unit, 2889 bcm_field_entry_t entry) 2890 { 2891 int rv; /* Operation return status. */ 2892 _field_presel_entry_t *f_presel; /* Presel entry structure. */ 2893 _field_action_t *fa; /* Presel actions iterator. */ 2894 _field_action_t *fa_ptr=NULL; /* Action previous pointer. */ 2895 _field_control_t *fc; /* Field control structure. */ 2896 bcm_field_presel_t presel; /* Field Preselector ID. */ 2897 2898 2899 /* Get field control structure. */ 2900 FP_LOCK(unit); 2901 rv = _field_control_get(unit, &fc); 2902 if (BCM_FAILURE(rv)) { 2903 FP_UNLOCK(unit); 2904 return rv; 2905 } 2906 2907 /* Resolve the Preselector ID from the given Entry ID */ 2908 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 2909 if (BCM_FAILURE(rv)) { 2910 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2911 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 2912 FP_UNLOCK(unit); 2913 return rv; 2914 } 2915 2916 /* Verify if the Presel ID is already in USE */ 2917 if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel) && 2918 !(f_presel->flags & _FP_ENTRY_DIRTY)) { 2919 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2920 "ERROR: Preselector ID[%d] is in USE.\n\r"), presel)); 2921 return BCM_E_BUSY; 2922 } 2923 2924 /* start at the head of the actions list and burn them up */ 2925 fa = f_presel->actions; 2926 2927 /* Search and Delete the Action from the Preselector entry */ 2928 while (fa != NULL) { 2929 fa_ptr = fa; 2930 f_presel->actions = fa = fa->next; 2931 sal_free (fa_ptr); 2932 } 2933 2934 FP_UNLOCK(unit); 2935 return (BCM_E_NONE); 2936 } 2937 2938 int 2939 _bcm_field_presel_group_prio_sort(int unit, _field_group_t *fg) 2940 { 2941 _field_presel_entry_t *f_presel[_FP_PRESEL_ENTRIES_MAX_PER_GROUP]; 2942 _field_presel_entry_t *f_presel_tmp; 2943 int i,j; 2944 2945 /* Input parameters check. */ 2946 if (NULL == fg) { 2947 return (BCM_E_PARAM); 2948 } 2949 2950 sal_memcpy(f_presel, fg->presel_ent_arr, 2951 sizeof(_field_presel_entry_t *) * _FP_PRESEL_ENTRIES_MAX_PER_GROUP); 2952 2953 for (i = 0; i < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; i++) { 2954 for (j = i; j < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; j++) { 2955 if (f_presel[i] && f_presel[j]) { 2956 if (f_presel[i]->priority < f_presel[j]->priority) { 2957 f_presel_tmp = f_presel[i]; 2958 f_presel[i] = f_presel[j]; 2959 f_presel[j] = f_presel_tmp; 2960 } 2961 } 2962 } 2963 } 2964 2965 return BCM_E_NONE; 2966 } 2967 2968 /* 2969 * Function: _bcm_field_presel_group_add 2970 * 2971 * Purpose: 2972 * Add preselector Id to a field group structure 2973 * 2974 * Parameters: 2975 * unit - (IN) BCM device number 2976 * fg - (IN) Reference to Field Group structure 2977 * presel - (IN) Preselector Id. 2978 * 2979 * Returns: 2980 * BCM_E_XXX 2981 */ 2982 int 2983 _bcm_field_presel_group_add(int unit, _field_group_t *fg, 2984 bcm_field_presel_t presel) 2985 { 2986 _field_presel_entry_t *f_presel; /* Presel entry structure. */ 2987 _field_control_t *fc; /* Field control structure. */ 2988 _field_stage_id_t stage_id; /* Stage id. */ 2989 uint8 id, idx; 2990 2991 /* Input parameters check. */ 2992 if (NULL == fg) { 2993 return (BCM_E_PARAM); 2994 } 2995 2996 /* Validate the Preselector ID */ 2997 if (_BCM_FIELD_IS_PRESEL_VALID(presel) == FALSE) { 2998 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 2999 "ERROR: Invalid Presel ID[%d].\n\r"), presel)); 3000 return BCM_E_PARAM; 3001 } 3002 3003 /* Get field control structure. */ 3004 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 3005 3006 /* Check if presel ID is already created */ 3007 if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel)) { 3008 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3009 "ERROR: Preselector ID[%d] is not created.\n\r"), presel)); 3010 return BCM_E_NOT_FOUND; 3011 } 3012 3013 /* Verify if the Presel ID is already in USE */ 3014 if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel)) { 3015 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3016 "ERROR: Preselector ID[%d] is already in USE" 3017 " by some other group.\n\r"), presel)); 3018 return BCM_E_BUSY; 3019 } 3020 3021 /* Find preselector descriptor */ 3022 BCM_IF_ERROR_RETURN 3023 (_bcm_field_presel_entry_get(unit, presel, &f_presel)); 3024 3025 /* Retrieve the stage id. */ 3026 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) { 3027 stage_id = _BCM_FIELD_STAGE_INGRESS; 3028 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 3029 bcmFieldQualifyStageIngressExactMatch)) { 3030 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 3031 #if defined(BCM_FLOWTRACKER_SUPPORT) 3032 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 3033 bcmFieldQualifyStageIngressFlowtracker)) { 3034 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 3035 #endif 3036 } else { 3037 return BCM_E_INTERNAL; 3038 } 3039 3040 /* Validate the Group's stage_id with Presel Entry stage_id */ 3041 if (stage_id != fg->stage_id) { 3042 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3043 "ERROR: Presel Entry[%d] doesn't belongs to Field Group's stage.\n\r"), 3044 presel)); 3045 return BCM_E_PARAM; 3046 } 3047 3048 /* Verify the last entry in the array to check the free slot */ 3049 if (fg->presel_ent_arr[_FP_PRESEL_ENTRIES_MAX_PER_GROUP-1] != NULL) { 3050 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, "ERROR: Exceeded Max " 3051 "Preselector IDs[%d] for the group[%d].\n\r"), 3052 _FP_PRESEL_ENTRIES_MAX_PER_GROUP, fg->gid)); 3053 return BCM_E_FULL; 3054 } 3055 3056 /* Adjust the presel entry as per the priority. */ 3057 for (id = 0; id < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; id++) { 3058 if (fg->presel_ent_arr[id] == NULL) { 3059 fg->presel_ent_arr[id] = f_presel; 3060 break; 3061 } else { 3062 if (fg->presel_ent_arr[id]->priority < f_presel->priority) { 3063 /* Move down all the entries */ 3064 for (idx = _FP_PRESEL_ENTRIES_MAX_PER_GROUP-1; idx > id; idx--) { 3065 fg->presel_ent_arr[idx] = fg->presel_ent_arr[idx - 1]; 3066 } 3067 fg->presel_ent_arr[id] = f_presel; 3068 break; 3069 } 3070 } 3071 } 3072 3073 /* Debug prints to be removed */ 3074 for (id = 0; id < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; id++) { 3075 if (fg->presel_ent_arr[id]) { 3076 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3077 "arr[%d]:priority[%d]\n\r"), 3078 id, fg->presel_ent_arr[id]->priority)); 3079 } 3080 } 3081 3082 return BCM_E_NONE; 3083 } 3084 3085 STATIC int 3086 _field_presel_entry_part_update(int unit, _field_stage_t *stage_fc, 3087 _field_presel_entry_t *f_presel) 3088 { 3089 int rv; /* Operation return status. */ 3090 _field_group_t *fg; 3091 _field_lt_slice_t *lt_fs; 3092 _field_presel_entry_t *f_presel_p; 3093 int part, parts_count; 3094 int slice_num, pri_tcam_idx, 3095 part_index; 3096 3097 /* Input parameters check. */ 3098 if (NULL == stage_fc || NULL == f_presel) { 3099 return (BCM_E_PARAM); 3100 } 3101 3102 fg = f_presel->group; 3103 lt_fs = f_presel->lt_fs; 3104 if (NULL == fg || NULL == lt_fs) { 3105 return BCM_E_INTERNAL; 3106 } 3107 3108 /* Get entry TCAM index given slice number and entry offset in slice. */ 3109 rv = _bcm_field_th_lt_slice_offset_to_tcam_index(unit, stage_fc, 3110 fg->instance, lt_fs->slice_number, 3111 f_presel->hw_index, &pri_tcam_idx); 3112 BCM_IF_ERROR_RETURN(rv); 3113 3114 /* Get number of entry parts based on group flags. */ 3115 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 3116 fg->stage_id, fg->flags, 3117 &parts_count)); 3118 3119 f_presel_p = f_presel; 3120 for (part = 0; (part < parts_count && f_presel_p != NULL); part++) { 3121 /* Given primary entry TCAM index calculate entry part tcam index. */ 3122 if (0 != part) { 3123 rv = _bcm_field_th_lt_entry_part_tcam_idx_get(unit, fg, 3124 pri_tcam_idx, 3125 part, &part_index); 3126 if (BCM_FAILURE(rv)) { 3127 return BCM_E_INTERNAL; 3128 } 3129 3130 /* 3131 * Given entry part TCAM index, determine the slice number and slice 3132 * offset index. 3133 */ 3134 rv = _bcm_field_th_lt_tcam_idx_to_slice_offset(unit, stage_fc, 3135 fg->instance, part_index, &slice_num, 3136 (int *)&f_presel_p->hw_index); 3137 if (BCM_FAILURE(rv)) { 3138 return BCM_E_INTERNAL; 3139 } 3140 } 3141 /* Assign entry to a slice. */ 3142 f_presel_p->lt_fs->p_entries[f_presel_p->hw_index] = f_presel_p; 3143 f_presel_p = f_presel_p->next; 3144 } 3145 3146 return BCM_E_NONE; 3147 } 3148 3149 /* 3150 * Function: _field_presel_entry_prio_set 3151 * 3152 * Purpose: 3153 * 3154 * Parameters: 3155 * unit - (IN) BCM device number 3156 * f_presel - (IN) Reference to Field preselector entry structure. 3157 * prio - (IN) Presel Entry Priority value. 3158 * 3159 * Returns: 3160 * BCM_E_XX 3161 * 3162 * Notes: 3163 * The earlier checks guarantee that there is a free slot somewhere 3164 * i.e. in one of the alloted slices for the group. 3165 */ 3166 STATIC int 3167 _field_presel_entry_prio_set(int unit, 3168 _field_presel_entry_t *f_presel, 3169 int prio) 3170 { 3171 int rv; /* Operation return status. */ 3172 _field_group_t *fg; /* Field Group structure. */ 3173 _field_control_t *fc; /* Field control structure. */ 3174 _field_stage_t *stage_fc; 3175 _field_presel_entry_t *f_presel_tmp; 3176 _field_lt_slice_t *lt_fs; 3177 uint8 move_down = 0; 3178 uint8 move_required = 0; 3179 uint8 skip = 0; 3180 int idx, curr_idx, dest_idx = -1, move_idx, pre_idx; 3181 int next_hw_index, dest_hw_index = -1; 3182 int target_hw_index = -1; 3183 int valid_entries = 0; 3184 int no_move_down_match = 0; 3185 _field_presel_entry_t *presel_entries[_FP_PRESEL_ENTRIES_MAX_PER_GROUP+1]; 3186 3187 /* Input parameters check. */ 3188 if (NULL == f_presel) { 3189 return (BCM_E_PARAM); 3190 } 3191 3192 /* If the priority is same, return */ 3193 if (f_presel->priority == prio) { 3194 return BCM_E_NONE; 3195 } 3196 3197 /* Get field control structure. */ 3198 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 3199 3200 if (NULL == f_presel->group) { 3201 return BCM_E_INTERNAL; 3202 } 3203 3204 fg = f_presel->group; 3205 if (NULL == fg->presel_ent_arr[0]) { 3206 return BCM_E_INTERNAL; 3207 } 3208 3209 /* Retrieve the slice the entry belongs to. */ 3210 lt_fs = f_presel->lt_fs; 3211 if (lt_fs == NULL) { 3212 return BCM_E_INTERNAL; 3213 } 3214 3215 if(fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 3216 /* Currently, not supporting priority movement in this stage */ 3217 return BCM_E_NONE; 3218 } 3219 3220 /* Check if the slice supports SW Atomicity */ 3221 if ((lt_fs->slice_flags & _BCM_FIELD_SLICE_SW_ATOMICITY_SUPPORT) == 0) { 3222 return BCM_E_CONFIG; 3223 } 3224 3225 /* Update LT Slice's last free entry index. */ 3226 target_hw_index = lt_fs->entry_count - 1; 3227 /* Verify if the last entry in the slice is free */ 3228 if (lt_fs->p_entries[target_hw_index] != NULL) { 3229 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3230 "ERROR: No free entries left to swap.\n\r"))); 3231 return BCM_E_INTERNAL; 3232 } 3233 3234 /* Get stage field control structure. */ 3235 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 3236 &stage_fc)); 3237 3238 /* Count Valid entries in the group preselector array. */ 3239 LOG_VERBOSE(BSL_LS_BCM_FP, 3240 (BSL_META_U(unit, "Before Prio Set ..\n\r"))); 3241 valid_entries = 0; 3242 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 3243 if (fg->presel_ent_arr[idx]) { 3244 LOG_VERBOSE(BSL_LS_BCM_FP, 3245 (BSL_META_U(unit, "arr[%d]:presel_id[%d]:" 3246 "hw_index[%d]:priority[%d]"), 3247 idx, fg->presel_ent_arr[idx]->presel_id, 3248 fg->presel_ent_arr[idx]->hw_index, 3249 fg->presel_ent_arr[idx]->priority)); 3250 if (f_presel == fg->presel_ent_arr[idx]) { 3251 LOG_VERBOSE(BSL_LS_BCM_FP, 3252 (BSL_META_U(unit, ":next_priority:[%d]\n\r"), prio)); 3253 } else { 3254 LOG_VERBOSE(BSL_LS_BCM_FP,(BSL_META_U(unit, "\n\r"))); 3255 } 3256 valid_entries++; 3257 } 3258 } 3259 3260 /* Validate if the given priority entry has to be move up or down. */ 3261 if (prio > f_presel->priority) { 3262 /* the entry should move upward */ 3263 move_down = 0; 3264 curr_idx = -1; 3265 } else { 3266 /* the entry should move downward */ 3267 move_down = 1; 3268 curr_idx = valid_entries; 3269 } 3270 3271 3272 no_move_down_match = 0; 3273 /* Get the Destination hw index */ 3274 for (idx = 0; idx < valid_entries; idx++) { 3275 f_presel_tmp = fg->presel_ent_arr[idx]; 3276 if (f_presel_tmp != NULL) { 3277 if ((move_down == 1) && (prio < f_presel_tmp->priority)) { 3278 no_move_down_match++; 3279 } 3280 if (f_presel_tmp == f_presel) { 3281 curr_idx = idx; 3282 continue; 3283 } 3284 3285 if (((move_down == 1) && (curr_idx < idx) && 3286 (prio >= f_presel_tmp->priority)) || 3287 ((move_down == 0) && (curr_idx == -1) && 3288 (prio > f_presel_tmp->priority) && 3289 (f_presel->priority <= f_presel_tmp->priority))) { 3290 3291 if ((move_down == 1) && (curr_idx + 1) == idx) { 3292 /* Down move is not required as the immediate next entry 3293 * priority is still less than or equal to the new priority. */ 3294 break; 3295 } 3296 3297 /* movement required. */ 3298 move_required = 1; 3299 dest_hw_index = f_presel_tmp->hw_index; 3300 dest_idx = idx; 3301 break; 3302 } 3303 } 3304 } 3305 3306 /* 3307 * This case occurs when the priority of the entry to be set 3308 * is the least priority among all the existing entries. 3309 */ 3310 if (no_move_down_match == valid_entries) { 3311 move_required = 1; 3312 dest_idx = valid_entries; 3313 } 3314 3315 if (move_required == 0) { 3316 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 3317 "== Move Not Required ==\n\r"))); 3318 return BCM_E_NONE; 3319 } 3320 3321 /* initialize the local preselector array */ 3322 sal_memset(&presel_entries[0], 0x0, 3323 sizeof(_field_presel_entry_t *) * (_FP_PRESEL_ENTRIES_MAX_PER_GROUP+1)); 3324 3325 /* 3326 * Iteration Move down the low priority entries and adjust the 3327 * given presel entry as per its new priority. 3328 */ 3329 for (idx = valid_entries-1; idx >= 0; idx--) { 3330 f_presel_tmp = fg->presel_ent_arr[idx]; 3331 move_idx = 0; 3332 if (f_presel_tmp != NULL) { 3333 if (((move_down == 1) && ((prio >= f_presel_tmp->priority) || 3334 (f_presel_tmp == f_presel))) || 3335 ((move_down == 0) && ((prio > f_presel_tmp->priority) && 3336 (f_presel_tmp->hw_index >= dest_hw_index)))) { 3337 3338 next_hw_index = f_presel_tmp->hw_index; 3339 f_presel_tmp->hw_index = target_hw_index; 3340 3341 rv = _field_presel_entry_part_update(unit, stage_fc, f_presel_tmp); 3342 if (BCM_FAILURE(rv)) { 3343 return BCM_E_INTERNAL; 3344 } 3345 3346 rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel_tmp); 3347 if (BCM_FAILURE(rv)) { 3348 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3349 "ERROR: Unable to install Presel Entry hw_index:%d\n\r"), 3350 f_presel_tmp->hw_index)); 3351 return BCM_E_INTERNAL; 3352 } 3353 3354 target_hw_index = next_hw_index; 3355 move_idx = 1; 3356 } 3357 if (f_presel_tmp == f_presel) { 3358 curr_idx = idx + move_idx; 3359 if (move_down == 1) { 3360 presel_entries[dest_idx] = f_presel_tmp; 3361 continue; 3362 } 3363 } 3364 presel_entries[idx + move_idx] = f_presel_tmp; 3365 } 3366 } 3367 3368 if (target_hw_index == -1) { 3369 return BCM_E_INTERNAL; 3370 } 3371 3372 pre_idx = 0; 3373 skip = 1; 3374 /* 3375 * Iteration to bring up the entries to the destination indices. 3376 */ 3377 for (idx = 0; idx <= valid_entries; idx++) { 3378 f_presel_tmp = presel_entries[idx]; 3379 3380 if (move_down == 0) { 3381 /* Look for a free entry in the presel_entries */ 3382 if (f_presel_tmp == NULL) { 3383 if (dest_idx != idx) { 3384 continue; 3385 } 3386 if (curr_idx < 0) { 3387 return BCM_E_INTERNAL; 3388 } 3389 f_presel_tmp = presel_entries[curr_idx]; 3390 } else if (idx < curr_idx) { 3391 fg->presel_ent_arr[idx] = f_presel_tmp; 3392 continue; 3393 } else if (idx == curr_idx) { 3394 continue; 3395 } 3396 } else { 3397 if (f_presel_tmp == NULL) { 3398 pre_idx = 1; 3399 skip = 0; 3400 continue; 3401 } else if (skip == 1) { /* Skip till free entry */ 3402 continue; 3403 } 3404 } 3405 3406 next_hw_index = f_presel_tmp->hw_index; 3407 f_presel_tmp->hw_index = target_hw_index; 3408 rv = _field_presel_entry_part_update(unit, stage_fc, f_presel_tmp); 3409 if (BCM_FAILURE(rv)) { 3410 return BCM_E_INTERNAL; 3411 } 3412 3413 rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel_tmp); 3414 if (BCM_FAILURE(rv)) { 3415 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3416 "ERROR: Unable to install Presel Entry hw_index:%d\n\r"), 3417 f_presel_tmp->hw_index)); 3418 return BCM_E_INTERNAL; 3419 } 3420 3421 target_hw_index = next_hw_index; 3422 fg->presel_ent_arr[idx - pre_idx] = f_presel_tmp; 3423 } 3424 3425 /* Delete Slice's last entry. */ 3426 f_presel_tmp = presel_entries[valid_entries]; 3427 if (f_presel_tmp != NULL) { 3428 int parts_count, part, tcam_idx; 3429 int last_hw_index; 3430 soc_mem_t lt_tcam_mem; 3431 _field_presel_entry_t *f_presel_p; 3432 uint32 entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; 3433 /* Entry buffer. */ 3434 3435 last_hw_index = lt_fs->entry_count - 1; 3436 3437 /* Get number of entry parts. */ 3438 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, 3439 fg->flags, &parts_count)); 3440 3441 /* Get TCAM view to be used for programming the hardware. */ 3442 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 3443 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 3444 f_presel->group->instance, 3445 _BCM_FIELD_MEM_TYPE_IFP_LT, 3446 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 3447 <_tcam_mem, NULL)); 3448 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 3449 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 3450 f_presel->group->instance, 3451 _BCM_FIELD_MEM_TYPE_EM_LT, 3452 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 3453 <_tcam_mem, NULL)); 3454 } else { 3455 return BCM_E_INTERNAL; 3456 } 3457 BCM_IF_ERROR_RETURN(rv); 3458 3459 f_presel_p = f_presel_tmp; 3460 for (part = parts_count -1; part >= 0; part--) { 3461 if (f_presel_p == NULL) { 3462 break; 3463 } 3464 /* Calculate the TCAM index. */ 3465 tcam_idx = f_presel_p->lt_fs->start_tcam_idx + last_hw_index; 3466 3467 /* Clear the entry in hardware. */ 3468 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 3469 tcam_idx, entry)); 3470 3471 /* Update the entry to a slice. */ 3472 f_presel_p->lt_fs->p_entries[last_hw_index] = NULL; 3473 f_presel_p = f_presel_p->next; 3474 } 3475 } 3476 3477 f_presel->priority = prio; 3478 3479 LOG_VERBOSE(BSL_LS_BCM_FP,(BSL_META_U(unit, "After Prio Set...\n\r"))); 3480 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 3481 if (fg->presel_ent_arr[idx]) { 3482 LOG_VERBOSE(BSL_LS_BCM_FP, 3483 (BSL_META_U(unit, "arr[%d]:presel_id[%d]:" 3484 "hw_index[%d]:priority[%d]\n\r"), 3485 idx, fg->presel_ent_arr[idx]->presel_id, 3486 fg->presel_ent_arr[idx]->hw_index, 3487 fg->presel_ent_arr[idx]->priority)); 3488 } 3489 } 3490 return BCM_E_NONE; 3491 } 3492 3493 /* 3494 * Function:_field_presel_delete_last_entry_hw 3495 * Purpose:To delete the last presel entry in the slice 3496 * 3497 * Parameters: 3498 * unit - (IN) BCM device number 3499 * f_presel - (IN) Reference to Field preselector entry structure. 3500 * 3501 * Returns: 3502 * BCM_E_XX 3503 */ 3504 STATIC int 3505 _field_presel_delete_last_entry_hw(int unit, 3506 _field_presel_entry_t *f_presel) 3507 { 3508 3509 int rv; /* Operation return status. */ 3510 _field_group_t *fg; /* Field Group structure. */ 3511 _field_stage_t *stage_fc; 3512 _field_presel_entry_t *f_presel_tmp = NULL; 3513 _field_lt_slice_t *lt_fs; 3514 int idx; 3515 int last_hw_index; 3516 /* Input parameters check. */ 3517 if (NULL == f_presel) { 3518 return (BCM_E_PARAM); 3519 } 3520 3521 if (NULL == f_presel->group) { 3522 return BCM_E_INTERNAL; 3523 } 3524 3525 fg = f_presel->group; 3526 if (NULL == fg->presel_ent_arr[0]) { 3527 return BCM_E_INTERNAL; 3528 } 3529 3530 /* Get stage field control structure. */ 3531 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 3532 &stage_fc)); 3533 /*Find the last entry */ 3534 for (idx = _FP_PRESEL_ENTRIES_MAX_PER_GROUP - 1; idx >=0; idx--) { 3535 if (fg->presel_ent_arr[idx]) { 3536 f_presel_tmp = fg->presel_ent_arr[idx]; 3537 break; 3538 } 3539 } 3540 lt_fs = f_presel->lt_fs; 3541 if (lt_fs == NULL) { 3542 return BCM_E_INTERNAL; 3543 } 3544 3545 3546 3547 if (f_presel_tmp != NULL) { 3548 int parts_count, part, tcam_idx; 3549 soc_mem_t lt_tcam_mem; 3550 uint32 entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; 3551 /* Entry buffer. */ 3552 3553 last_hw_index = lt_fs->entry_count - 1; 3554 3555 /* Get number of entry parts. */ 3556 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 3557 fg->stage_id, fg->flags, &parts_count)); 3558 3559 /* Get TCAM view to be used for programming the hardware. */ 3560 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 3561 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 3562 f_presel->group->instance, 3563 _BCM_FIELD_MEM_TYPE_IFP_LT, 3564 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 3565 <_tcam_mem, NULL)); 3566 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 3567 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 3568 f_presel->group->instance, 3569 _BCM_FIELD_MEM_TYPE_EM_LT, 3570 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 3571 <_tcam_mem, NULL)); 3572 #if defined(BCM_FLOWTRACKER_SUPPORT) 3573 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 3574 /* Combo view is not available */ 3575 return _field_hx5_ft_presel_delete_last_entry_hw(unit, 3576 f_presel_tmp, last_hw_index); 3577 #endif 3578 } else { 3579 return BCM_E_INTERNAL; 3580 } 3581 BCM_IF_ERROR_RETURN(rv); 3582 3583 for (part = parts_count -1; part >= 0; part--) { 3584 if (f_presel_tmp == NULL) { 3585 break; 3586 } 3587 /* Calculate the TCAM index. */ 3588 tcam_idx = f_presel_tmp->lt_fs->start_tcam_idx + last_hw_index; 3589 /* Clear the entry in hardware. */ 3590 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 3591 tcam_idx, entry)); 3592 /* Update the entry to a slice. */ 3593 f_presel_tmp->lt_fs->p_entries[last_hw_index] = NULL; 3594 f_presel_tmp= f_presel_tmp->next; 3595 } 3596 } 3597 return BCM_E_NONE; 3598 } 3599 3600 3601 /* 3602 * Function: _field_presel_entries_move_down_hw 3603 * Purpose:To move the entries down in the hardware 3604 * 3605 * Parameters: 3606 * unit - (IN) BCM device number 3607 * f_presel - (IN) Reference to Field preselector entry structure. 3608 * 3609 * Returns: 3610 * BCM_E_XX 3611 */ 3612 STATIC int 3613 _field_presel_entries_move_down_hw (int unit, 3614 _field_presel_entry_t *f_presel) 3615 { 3616 int target_hw_index = -1, next_hw_index =-1; 3617 int rv; /* Operation return status. */ 3618 int idx; 3619 _field_stage_t *stage_fc; 3620 _field_group_t *fg; /* Field Group structure. */ 3621 _field_lt_slice_t *lt_fs; 3622 _field_presel_entry_t *f_presel_tmp; 3623 lt_fs = f_presel->lt_fs; 3624 target_hw_index = lt_fs->entry_count - 1; /*Index of the free slice entry*/ 3625 if (NULL == f_presel->group) { 3626 return BCM_E_INTERNAL; 3627 } 3628 fg = f_presel->group; 3629 3630 /* Get stage field control structure. */ 3631 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 3632 &stage_fc)); 3633 /* 3634 * Iteration to move down the low priority entries and the entry being updated. 3635 */ 3636 for (idx = _FP_PRESEL_ENTRIES_MAX_PER_GROUP - 1; idx >= 0; idx--) { 3637 f_presel_tmp = fg->presel_ent_arr[idx]; 3638 if (f_presel_tmp != NULL) { 3639 next_hw_index = f_presel_tmp->hw_index; 3640 f_presel_tmp->hw_index = target_hw_index; 3641 3642 rv = _field_presel_entry_part_update(unit, stage_fc, f_presel_tmp); 3643 if (BCM_FAILURE(rv)) { 3644 return BCM_E_INTERNAL; 3645 } 3646 3647 rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel_tmp); 3648 if (BCM_FAILURE(rv)) { 3649 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3650 "ERROR: Unable to install Presel Entry hw_index:%d\n\r"), 3651 f_presel_tmp->hw_index)); 3652 return BCM_E_INTERNAL; 3653 } 3654 if(f_presel_tmp == f_presel) { 3655 break; 3656 } 3657 target_hw_index = next_hw_index; 3658 } 3659 } 3660 3661 return BCM_E_NONE; 3662 } 3663 /* 3664 * Function: _field_presel_entries_move_up_hw 3665 * Purpose:To move the entries up in the hardware 3666 * 3667 * Parameters: 3668 * unit - (IN) BCM device number 3669 * entry_index - (IN) presel_ent_arr index, entries after this will 3670 * updated with next below entry HW index 3671 * start_entry_hw_index - (IN) HW index to be updated for the first entry 3672 * below the intry with index entry_index 3673 * f_presel - (IN) Reference to Field preselector entry structure. 3674 * 3675 * Returns: 3676 * BCM_E_XX 3677 */ 3678 3679 STATIC int 3680 _field_presel_entries_move_up_hw (int unit, 3681 int entry_index, 3682 int start_entry_hw_index, 3683 _field_presel_entry_t *f_presel) 3684 { 3685 int rv; /* Operation return status. */ 3686 _field_group_t *fg; /* Field Group structure. */ 3687 _field_presel_entry_t *f_presel_tmp = NULL; 3688 int target_hw_index = -1, next_hw_index=-1; 3689 _field_stage_t *stage_fc; 3690 int idx; 3691 if (NULL == f_presel->group) { 3692 return BCM_E_INTERNAL; 3693 } 3694 3695 fg = f_presel->group; 3696 if (NULL == fg->presel_ent_arr[0]) { 3697 return BCM_E_INTERNAL; 3698 } 3699 /* Get stage field control structure. */ 3700 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 3701 &stage_fc)); 3702 3703 target_hw_index = start_entry_hw_index; 3704 3705 /*The operation starts from the entry below the entry to be updated*/ 3706 for (idx = entry_index + 1; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 3707 if ((fg->presel_ent_arr[idx] != NULL)) { 3708 f_presel_tmp = fg->presel_ent_arr[idx]; 3709 next_hw_index = f_presel_tmp->hw_index; 3710 f_presel_tmp->hw_index = target_hw_index; 3711 3712 } else { 3713 if (f_presel_tmp != NULL) { 3714 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 3715 "No more entry to move up as this is last valid entry:%d\n\r"), 3716 f_presel_tmp->hw_index)); 3717 } else { 3718 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 3719 "No entries available to move up \n\r"))); 3720 } 3721 return BCM_E_NONE; 3722 } 3723 target_hw_index = next_hw_index; 3724 3725 rv = _field_presel_entry_part_update(unit, stage_fc, f_presel_tmp); 3726 if (BCM_FAILURE(rv)) { 3727 return BCM_E_INTERNAL; 3728 } 3729 3730 rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel_tmp); 3731 if (BCM_FAILURE(rv)) { 3732 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3733 "ERROR: Unable to install Presel Entry hw_index:%d\n\r"), 3734 f_presel_tmp->hw_index)); 3735 return BCM_E_INTERNAL; 3736 } 3737 3738 } 3739 return BCM_E_NONE; 3740 } 3741 3742 /* 3743 * Function: _field_presel_entry_update_hw_index 3744 * Purpose:To re-install the Presel entry with given HW index in the hardware 3745 * 3746 * Parameters: 3747 * unit - (IN) BCM device number 3748 * entry_hw_index - (IN) Hardware index of the entry to be updated. 3749 * f_presel - (IN) Reference to Field preselector entry structure. 3750 * 3751 * Returns: 3752 * BCM_E_XX 3753 */ 3754 STATIC int 3755 _field_presel_entry_update_hw_index(int unit, 3756 int entry_hw_index, 3757 _field_presel_entry_t *f_presel) 3758 { 3759 int rv; /* Operation return status. */ 3760 _field_group_t *fg; /* Field Group structure. */ 3761 _field_stage_t *stage_fc; 3762 3763 if (NULL == f_presel->group) { 3764 return BCM_E_INTERNAL; 3765 } 3766 3767 fg = f_presel->group; 3768 /* Get stage field controBCM_E_NONE l structure. */ 3769 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 3770 &stage_fc)); 3771 /*Update the Presel with new qualifier value in the H/W */ 3772 f_presel->hw_index = entry_hw_index; 3773 rv = _field_presel_entry_part_update(unit, stage_fc, f_presel); 3774 if (BCM_FAILURE(rv)) { 3775 return BCM_E_INTERNAL; 3776 } 3777 3778 rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel); 3779 if (BCM_FAILURE(rv)) { 3780 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3781 "ERROR: Unable to install Presel Entry hw_index:%d\n\r"), 3782 f_presel->hw_index)); 3783 return BCM_E_INTERNAL; 3784 } 3785 3786 return BCM_E_NONE; 3787 } 3788 3789 /* 3790 * Function: _field_presel_entry_update 3791 * Purpose:To update the Presel entry into hardware when the group is operational. 3792 * 3793 * Parameters: 3794 * unit - (IN) BCM device number 3795 * f_presel - (IN) Reference to Field preselector entry structure. 3796 * 3797 * Returns: 3798 * BCM_E_XX 3799 * 3800 * Notes: 3801 * The earlier checks guarantee that there is a free slot somewhere 3802 * i.e. in one of the alloted slices for the group. 3803 */ 3804 STATIC int 3805 _field_presel_entry_update(int unit, 3806 _field_presel_entry_t *f_presel) 3807 { 3808 int rv; /* Operation return status. */ 3809 _field_group_t *fg; /* Field Group structure. */ 3810 _field_control_t *fc; /* Field control structure. */ 3811 _field_stage_t *stage_fc; 3812 _field_lt_slice_t *lt_fs; 3813 int entry_hw_index, copy_entry_hw_index; 3814 int free_hw_index = -1; 3815 int idx, entry_idx = -1; 3816 3817 /* Input parameters check. */ 3818 if (NULL == f_presel) { 3819 return (BCM_E_PARAM); 3820 } 3821 3822 /* Get field control structure. */ 3823 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 3824 3825 if (NULL == f_presel->group) { 3826 return BCM_E_INTERNAL; 3827 } 3828 3829 fg = f_presel->group; 3830 if (NULL == fg->presel_ent_arr[0]) { 3831 return BCM_E_INTERNAL; 3832 } 3833 3834 /* Retrieve the slice the entry belongs to. */ 3835 lt_fs = f_presel->lt_fs; 3836 if (lt_fs == NULL) { 3837 return BCM_E_INTERNAL; 3838 } 3839 3840 if (lt_fs->slice_flags & _BCM_FIELD_SLICE_HW_ATOMICITY_SUPPORT) { 3841 entry_hw_index = f_presel->hw_index; 3842 rv = _field_presel_entry_update_hw_index(unit, entry_hw_index, f_presel); 3843 if (BCM_FAILURE(rv)) { 3844 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3845 "ERROR: updating the entry with index:%d\n\r"), 3846 entry_hw_index)); 3847 return BCM_E_INTERNAL; 3848 } 3849 return rv; 3850 } 3851 3852 /* Check if the slice supports SW Atomicity */ 3853 if ((lt_fs->slice_flags & _BCM_FIELD_SLICE_SW_ATOMICITY_SUPPORT) == 0) { 3854 return BCM_E_CONFIG; 3855 } 3856 /*Hardware index of the entry to be updated*/ 3857 entry_hw_index = f_presel->hw_index; 3858 3859 /* Update LT Slice's last free entry index. */ 3860 free_hw_index = lt_fs->entry_count - 1; 3861 /* Verify if the last entry in the slice is free */ 3862 if (lt_fs->p_entries[free_hw_index] != NULL) { 3863 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3864 "ERROR: No free entries left to swap.\n\r"))); 3865 return BCM_E_INTERNAL; 3866 } 3867 3868 /* Get stage field control structure. */ 3869 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 3870 &stage_fc)); 3871 3872 /*Find the index of the entry being updated */ 3873 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 3874 if (fg->presel_ent_arr[idx]) { 3875 LOG_VERBOSE(BSL_LS_BCM_FP, 3876 (BSL_META_U(unit, "arr[%d]:presel_id[%d]:" 3877 "hw_index[%d]:priority[%d]"), 3878 idx, fg->presel_ent_arr[idx]->presel_id, 3879 fg->presel_ent_arr[idx]->hw_index, 3880 fg->presel_ent_arr[idx]->priority)); 3881 if (fg->presel_ent_arr[idx]->hw_index == f_presel->hw_index) { 3882 entry_idx = idx; 3883 break; 3884 } 3885 } 3886 } 3887 3888 /* Move down the low priority entries and along with the entry being changed. 3889 */ 3890 rv =_field_presel_entries_move_down_hw(unit, f_presel); 3891 if (BCM_FAILURE(rv)) { 3892 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3893 "ERROR: shifting the entries down starting from index:%d\n\r"), 3894 entry_hw_index)); 3895 return BCM_E_INTERNAL; 3896 } 3897 3898 copy_entry_hw_index = f_presel->hw_index; 3899 3900 /*Update the Presel with new qualifier value in the H/W */ 3901 rv = _field_presel_entry_update_hw_index(unit, entry_hw_index, f_presel); 3902 if (BCM_FAILURE(rv)) { 3903 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3904 "ERROR: updating the entry with index:%d\n\r"), 3905 entry_hw_index)); 3906 return BCM_E_INTERNAL; 3907 } 3908 3909 /* Move up the low priority entries. 3910 */ 3911 rv =_field_presel_entries_move_up_hw(unit, entry_idx, copy_entry_hw_index, f_presel); 3912 if (BCM_FAILURE(rv)) { 3913 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3914 "ERROR: shifting the entries up below index:%d\n\r"), 3915 entry_hw_index)); 3916 return BCM_E_INTERNAL; 3917 } 3918 /*Delete the last entry to keep a free entry*/ 3919 rv =_field_presel_delete_last_entry_hw(unit, f_presel); 3920 if (BCM_FAILURE(rv)) { 3921 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3922 "ERROR: Deleting the last entry with index:%d\n\r"), 3923 free_hw_index)); 3924 return BCM_E_INTERNAL; 3925 } 3926 3927 return BCM_E_NONE; 3928 } 3929 3930 /* 3931 * Function: _bcm_field_presel_entry_prio_set 3932 * 3933 * Purpose: 3934 * 3935 * Parameters: 3936 * unit - (IN) BCM device number 3937 * entry - (IN) Field presel entry to operate on. 3938 * prio - (IN) Presel Entry Priority value. 3939 * 3940 * Returns: 3941 * BCM_E_XX 3942 * 3943 * Notes: 3944 * The earlier checks guarantee that there is a free slot somewhere 3945 * i.e. in one of the alloted slices for the group. 3946 */ 3947 int 3948 _bcm_field_presel_entry_prio_set(int unit, bcm_field_entry_t entry, int prio) 3949 { 3950 int rv; /* Operation return status. */ 3951 _field_control_t *fc; /* Field control structure. */ 3952 _field_presel_entry_t *f_presel; /* Presel entry structure. */ 3953 bcm_field_presel_t presel; /* Field Preselector ID. */ 3954 3955 /* Preselector feature check */ 3956 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 3957 return BCM_E_UNAVAIL; 3958 } 3959 3960 /* Resolve the Preselector ID from the given Entry ID */ 3961 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 3962 if (BCM_FAILURE(rv)) { 3963 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 3964 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 3965 return rv; 3966 } 3967 3968 /* Get field control structure. */ 3969 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 3970 3971 /* Verify if the Presel ID is already in USE */ 3972 if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel) && 3973 !(f_presel->flags & _FP_ENTRY_DIRTY)) { 3974 BCM_IF_ERROR_RETURN (_field_presel_entry_prio_set(unit, f_presel, prio)); 3975 } 3976 3977 /* Assign the priority */ 3978 f_presel->priority = prio; 3979 3980 return BCM_E_NONE; 3981 } 3982 3983 /* 3984 * Function: _bcm_field_presel_entry_prio_get 3985 * 3986 * Purpose: Retreive the preselector entry priority value. 3987 * 3988 * Parameters: 3989 * unit - (IN) BCM device number 3990 * entry - (IN) Field presel entry to operate on. 3991 * prio - (OUT) Presel Entry Priority value. 3992 * 3993 * Returns: 3994 * BCM_E_XX 3995 */ 3996 int 3997 _bcm_field_presel_entry_prio_get(int unit, bcm_field_entry_t entry, int *prio) 3998 { 3999 int rv; /* Operation return status. */ 4000 _field_presel_entry_t *f_presel; /* Presel entry structure. */ 4001 bcm_field_presel_t presel; /* Field Preselector ID. */ 4002 4003 /* Validate input parameters. */ 4004 if (prio == NULL) { 4005 return BCM_E_PARAM; 4006 } 4007 4008 /* Preselector feature check */ 4009 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 4010 return BCM_E_UNAVAIL; 4011 } 4012 4013 /* Resolve the Preselector ID from the given Entry ID */ 4014 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 4015 if (BCM_FAILURE(rv)) { 4016 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4017 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 4018 return rv; 4019 } 4020 4021 *prio = f_presel->priority; 4022 return BCM_E_NONE; 4023 } 4024 4025 4026 /* 4027 * Function: 4028 * _field_th_lt_entry_data_config_set 4029 * Purpose: 4030 * Configure LT Entry data parameters generated by group (keygen profile ..) 4031 * and actions configured by the presel. 4032 * Parameters: 4033 * unit - (IN) BCM device number. 4034 * stage_fc - (IN) Stage field control structure. 4035 * f_presel - (IN/OUT) Preselector Entry structure. 4036 * Returns: 4037 * BCM_E_XXX 4038 */ 4039 int 4040 _field_th_lt_entry_data_config_set(int unit, _field_stage_t *stage_fc, 4041 _field_presel_entry_t *f_presel) 4042 { 4043 int idx; /* Entry parts iterator. */ 4044 int parts; /* Number of field entry parts. */ 4045 _field_group_t *fg; /* Field group structure. */ 4046 soc_mem_t lt_data_mem; 4047 _field_presel_entry_t *f_presel_part; 4048 4049 /* Input parameters check. */ 4050 if ((NULL == stage_fc) || (NULL == f_presel)) { 4051 return (BCM_E_PARAM); 4052 } 4053 4054 /* Get entry's group structure. */ 4055 fg = f_presel->group; 4056 4057 /* Get number of lt entry parts. */ 4058 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 4059 stage_fc->stage_id, fg->flags, &parts)); 4060 4061 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 4062 BCM_IF_ERROR_RETURN (_bcm_field_th_lt_tcam_policy_mem_get( 4063 unit, stage_fc, fg->instance, 4064 _BCM_FIELD_MEM_TYPE_IFP_LT, 4065 _BCM_FIELD_MEM_VIEW_TYPE_DATA, 4066 NULL, <_data_mem)); 4067 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 4068 BCM_IF_ERROR_RETURN (_bcm_field_th_lt_tcam_policy_mem_get( 4069 unit, stage_fc, fg->instance, 4070 _BCM_FIELD_MEM_TYPE_EM_LT, 4071 _BCM_FIELD_MEM_VIEW_TYPE_DATA, 4072 NULL, <_data_mem)); 4073 #if defined(BCM_FLOWTRACKER_SUPPORT) 4074 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 4075 BCM_IF_ERROR_RETURN (_bcm_field_th_lt_tcam_policy_mem_get( 4076 unit, stage_fc, fg->instance, 4077 _BCM_FIELD_MEM_TYPE_FT_LT, 4078 _BCM_FIELD_MEM_VIEW_TYPE_DATA, 4079 NULL, <_data_mem)); 4080 #endif 4081 } else { 4082 return (BCM_E_PARAM); 4083 } 4084 4085 f_presel_part = f_presel; 4086 /* Install entry parts in hardware. */ 4087 for (idx = 0; (idx < parts && f_presel_part != NULL); idx++) { 4088 /* Install keygen program profile table entries for the group in HW */ 4089 BCM_IF_ERROR_RETURN (_bcm_field_th_group_keygen_profiles_index_alloc( 4090 unit, stage_fc, 4091 fg, idx)); 4092 4093 /* Allocate the Preselector Data Memory. */ 4094 BCM_IF_ERROR_RETURN (_bcm_field_th_presel_mem_data_get( 4095 unit, stage_fc, fg->instance, 4096 f_presel_part, 4097 &f_presel_part->lt_data)); 4098 4099 /* Build LT selection Data entry. */ 4100 BCM_IF_ERROR_RETURN (_bcm_field_th_lt_entry_data_value_set( 4101 unit, stage_fc, fg, idx, 4102 lt_data_mem, 4103 f_presel_part->lt_data.data)); 4104 4105 /* Assign the Preselector Entry Actions to the LT Data entry. */ 4106 BCM_IF_ERROR_RETURN (_bcm_field_presel_entry_actions_set( 4107 unit, lt_data_mem, 4108 f_presel_part, 4109 f_presel_part->lt_data.data)); 4110 4111 f_presel_part = f_presel_part->next; 4112 } 4113 4114 return (BCM_E_NONE); 4115 } 4116 4117 4118 /* 4119 * Function: 4120 * _field_th_lt_entry_phys_create 4121 * Purpose: 4122 * Create a physical entry in a logical table slice. 4123 * Parameters: 4124 * unit - (IN) BCM device number. 4125 * stage_fc - (IN) Stage field control structure. 4126 * lt_ent - (IN) Logical table entry identifier. 4127 * prio - (IN) Logical table entry priority. 4128 * lt_fs - (IN) Logical table slice structure. 4129 * fg - (IN) Field group structure. 4130 * f_presel - (OUT) Allocated & initialized entry. 4131 * Returns: 4132 * BCM_E_XXX 4133 */ 4134 STATIC int 4135 _field_th_lt_entry_phys_create(int unit, _field_stage_t *stage_fc, 4136 bcm_field_presel_t lt_ent, int prio, 4137 _field_lt_slice_t *lt_fs, _field_group_t *fg, 4138 _field_presel_entry_t *f_presel) 4139 { 4140 _field_control_t *fc; /* Field control structure. */ 4141 int idx; /* Slice entries iteration index. */ 4142 int parts_count = -1; /* Number of entry parts. */ 4143 int part_index; /* Entry parts iterator. */ 4144 int rv; /* Operation return status. */ 4145 int pri_tcam_idx = -1; /* Primary entry TCAM index. */ 4146 int slice_num = -1; /* Slice number. */ 4147 _field_presel_entry_t *f_presel_p = NULL; /* LT field entry structure. */ 4148 4149 /* Input parameters check. */ 4150 if ((NULL == stage_fc) || (NULL == lt_fs) || 4151 (NULL == fg) || (NULL == f_presel)) { 4152 return (BCM_E_PARAM); 4153 } 4154 4155 /* Check if free entries are available in the slice. */ 4156 if (0 == lt_fs->free_count) { 4157 return (BCM_E_RESOURCE); 4158 } 4159 4160 /* Get device field control structure. */ 4161 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4162 4163 /* Get number of entry partss. */ 4164 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 4165 stage_fc->stage_id, fg->flags, &parts_count)); 4166 4167 /* Get index for primary entry. */ 4168 for (idx = 0; idx < lt_fs->entry_count; idx++) { 4169 if (NULL == lt_fs->p_entries[idx]) { 4170 f_presel->hw_index = idx; 4171 break; 4172 } 4173 } 4174 4175 if (idx == lt_fs->entry_count) { 4176 /* If this condition occurs, that means, free_count is not decremented 4177 * properly, it would have caught above for (0 == lt_fs->free_count) */ 4178 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4179 "Error: Allocation failure for presel[%d], Entries reached max" 4180 "entries in the slice, free_count is not decremented properly.\n\r"), 4181 f_presel->presel_id)); 4182 return BCM_E_INTERNAL; 4183 } 4184 4185 /* Get entry TCAM index given slice number and entry offset in slice. */ 4186 rv = _bcm_field_th_lt_slice_offset_to_tcam_index(unit, stage_fc, 4187 fg->instance, lt_fs->slice_number, 4188 f_presel->hw_index, &pri_tcam_idx); 4189 if (BCM_FAILURE(rv)) { 4190 return rv; 4191 } 4192 4193 if (parts_count > 1) { 4194 _field_presel_entry_t *p_ent_alloc; 4195 4196 f_presel_p = f_presel; 4197 /* Allocate memory for presel entries for double/triple wide modes. */ 4198 for (idx = 1; idx < parts_count; idx++) { 4199 p_ent_alloc = NULL; 4200 _FP_XGS3_ALLOC(p_ent_alloc, sizeof(_field_presel_entry_t), 4201 "Presel Entry Alloc."); 4202 if (NULL == p_ent_alloc) { 4203 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4204 "Error: allocation failure for Presel[%d] Parts entry[%d]\n"), 4205 f_presel->presel_id, idx)); 4206 return (BCM_E_MEMORY); 4207 } 4208 /* Copy the base presel entry contents to its allocated part entry */ 4209 sal_memcpy(p_ent_alloc, f_presel_p, sizeof(_field_presel_entry_t)); 4210 f_presel_p->next = p_ent_alloc; 4211 f_presel_p = p_ent_alloc; 4212 } 4213 } 4214 4215 f_presel_p = f_presel; 4216 /* Fill entry primitives. */ 4217 for (idx = 0; (idx < parts_count && f_presel_p != NULL); idx++) { 4218 /* Get entry part flags. */ 4219 rv = _bcm_field_th_tcam_part_to_entry_flags(unit, idx, fg->flags, 4220 &(f_presel_p->flags)); 4221 if (BCM_FAILURE(rv)) { 4222 goto bcm_error; 4223 } 4224 4225 /* Given primary entry TCAM index calculate entry part tcam index. */ 4226 if (0 != idx) { 4227 rv = _bcm_field_th_lt_entry_part_tcam_idx_get(unit, fg, 4228 pri_tcam_idx, 4229 idx, &part_index); 4230 if (BCM_FAILURE(rv)) { 4231 goto bcm_error; 4232 } 4233 4234 /* 4235 * Given entry part TCAM index, determine the slice number and slice 4236 * offset index. 4237 */ 4238 rv = _bcm_field_th_lt_tcam_idx_to_slice_offset(unit, stage_fc, 4239 fg->instance, part_index, &slice_num, 4240 (int *)&f_presel_p->hw_index); 4241 if (BCM_FAILURE(rv)) { 4242 goto bcm_error; 4243 } 4244 f_presel_p->lt_fs = stage_fc->lt_slices[fg->instance] + slice_num; 4245 } else { 4246 /* Set entry slice. */ 4247 f_presel_p->lt_fs = lt_fs; 4248 } 4249 4250 /* Assign the group it belongs to. */ 4251 f_presel_p->group = fg; 4252 4253 /* Decrement slice free entry count for primary entries. */ 4254 f_presel_p->lt_fs->free_count--; 4255 4256 /* Assign entry to a slice. */ 4257 f_presel_p->lt_fs->p_entries[f_presel_p->hw_index] = f_presel_p; 4258 4259 /* Mark entry dirty. */ 4260 f_presel_p->flags |= _FP_ENTRY_DIRTY; 4261 4262 /* Next Entry Part */ 4263 f_presel_p = f_presel_p->next; 4264 } 4265 4266 /* Add the Preselector from field control operational status. */ 4267 BCM_FIELD_PRESEL_ADD(fc->presel_info->operational_set, f_presel->presel_id); 4268 4269 return (rv); 4270 4271 bcm_error: 4272 if (BCM_FAILURE(rv)) { 4273 _field_presel_entry_t *p_ent_free = NULL; 4274 4275 f_presel_p = f_presel; 4276 /* Allocate memory for presel entries for double/triple wide modes. */ 4277 for (idx = 1; idx < parts_count; idx++) { 4278 if (f_presel_p != NULL) { 4279 p_ent_free = f_presel_p; 4280 f_presel_p = f_presel_p->next; 4281 sal_free(p_ent_free); 4282 } 4283 } 4284 } 4285 4286 return rv; 4287 } 4288 4289 /* 4290 * Function: 4291 * _bcm_field_th_lt_entry_phys_destroy 4292 * Purpose: 4293 * Destroy a physical entry from a logical table slice. 4294 * Parameters: 4295 * unit - (IN) BCM device number. 4296 * f_presel - (IN) Preselector Logical table entry structure. 4297 * Returns: 4298 * BCM_E_XXX 4299 */ 4300 int 4301 _bcm_field_th_lt_entry_phys_destroy(int unit, _field_presel_entry_t *f_presel) 4302 { 4303 int idx; /* Entry iterator index. */ 4304 int parts; /* Entry parts count. */ 4305 uint8 slice_number; /* Slice number. */ 4306 _field_control_t *fc; /* Device field control structure. */ 4307 _field_group_t *fg; /* Field group structure. */ 4308 _field_presel_entry_t *f_presel_p; /* Presel Part Entry. */ 4309 _field_presel_entry_t *f_presel_free; /* Presel entry to be freed. */ 4310 4311 /* Input parameters check. */ 4312 if ((NULL == f_presel) || (NULL == f_presel->lt_fs)) { 4313 return (BCM_E_PARAM); 4314 } 4315 4316 /* Get field control structure. */ 4317 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4318 4319 /* Get the group to which the entry belongs. */ 4320 fg = f_presel->group; 4321 4322 /* Get entry parts count. */ 4323 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 4324 fg->stage_id, fg->flags, &parts)); 4325 4326 f_presel_p = f_presel; 4327 for (idx = 0; (idx < parts && f_presel_p != NULL); idx++) { 4328 /* Free entry Data mask buffer if valid. */ 4329 if (NULL != f_presel_p->lt_data.data) { 4330 sal_free(f_presel_p->lt_data.data); 4331 f_presel_p->lt_data.data = NULL; 4332 } 4333 4334 /* Get entry part slice number. */ 4335 BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_slice_number(idx, 4336 fg->flags, &slice_number)); 4337 4338 /* Remove entry pointer from the slice. */ 4339 f_presel_p->lt_fs->p_entries[f_presel_p->hw_index] = NULL; 4340 4341 /* Increment slice unused entry count. */ 4342 f_presel_p->lt_fs->free_count++; 4343 4344 f_presel_free = f_presel_p; 4345 f_presel_p = f_presel_p->next; 4346 4347 /* De-allocate the part entries except Primary entry */ 4348 if (f_presel_free != f_presel) { 4349 sal_free(f_presel_free); 4350 f_presel_free = NULL; 4351 } 4352 } 4353 f_presel->next = NULL; 4354 4355 /* Remove the Preselector from field control operational status. */ 4356 BCM_FIELD_PRESEL_REMOVE(fc->presel_info->operational_set, 4357 f_presel->presel_id); 4358 4359 return (BCM_E_NONE); 4360 } 4361 4362 /* 4363 * Function: 4364 * _bcm_field_th_lt_entry_config_set 4365 * Purpose: 4366 * Associate presel entry to the slice/s reserved in logical table selection 4367 * TCAM for the field group. 4368 * Parameters: 4369 * unit - (IN) BCM device number. 4370 * stage_fc - (IN) Stage field control structure. 4371 * fg - (IN) Field group structure. 4372 * lt_fs - (IN) Field logical table slice structure. 4373 * f_presel - (IN) Reference to Field Preselector Entry strcture. 4374 * Returns: 4375 * BCM_E_XXX 4376 */ 4377 int 4378 _bcm_field_th_lt_entry_config_set(int unit, 4379 _field_stage_t *stage_fc, 4380 _field_group_t *fg, 4381 _field_lt_slice_t *lt_fs, 4382 _field_presel_entry_t *f_presel) 4383 { 4384 _field_control_t *fc; /* Field control structure. */ 4385 int rv; /* Operation return status. */ 4386 4387 /* Input parameter check. */ 4388 if ((NULL == stage_fc) || (NULL == fg) || 4389 (NULL == lt_fs) || (NULL == f_presel)) { 4390 return (BCM_E_PARAM); 4391 } 4392 4393 /* Check if Presel Flags are appropriate */ 4394 if (!(fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) { 4395 return (BCM_E_INTERNAL); 4396 } 4397 4398 /* Get device field control handle. */ 4399 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4400 4401 /* 4402 * Create Presel Entries in the LT slice associated with the group 4403 */ 4404 rv = _field_th_lt_entry_phys_create 4405 (unit, stage_fc, f_presel->presel_id, 4406 BCM_FIELD_ENTRY_PRIO_LOWEST, lt_fs, fg, f_presel); 4407 if (BCM_FAILURE(rv)) { 4408 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4409 "Error: Presel Slice Entry Creation failed for Id[%d]\n\r"), 4410 f_presel->presel_id)); 4411 return (rv); 4412 } 4413 4414 /* Set up LT selection rule based on group's keygen codes. */ 4415 rv = _field_th_lt_entry_data_config_set(unit, stage_fc, f_presel); 4416 if (BCM_FAILURE(rv)) { 4417 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4418 "Error: Presel Entry Rule Configuration failed for Id[%d]\n\r"), 4419 f_presel->presel_id)); 4420 /* Destroy resources allocated for the entry. */ 4421 _bcm_field_th_lt_entry_phys_destroy(unit, f_presel); 4422 return (rv); 4423 } 4424 return (rv); 4425 } 4426 4427 /* 4428 * Function: 4429 * _bcm_field_th_lt_entry_hw_install 4430 * Purpose: 4431 * Install an LT TCAM entry part in hardware at the supplied entry index. 4432 * Parameters: 4433 * unit - (IN) BCM device number. 4434 * lt_tcam_mem - (IN) LT TCAM Memory. 4435 * tcam_idx - (IN) TCAM index at which entry must be written in HW. 4436 * key - (IN) TCAM Entry Key to be written. 4437 * mask - (IN) TCAM Entry Mask to be written. 4438 * data - (IN) TCAM Entry Data to be written. 4439 * valid - (IN) Entry Valid (TRUE) / Invalid (FALSE) 4440 * Returns: 4441 * BCM_E_XXX 4442 * 4443 * Note: To only enable/disable the entry, invoke this function with NULL key, mask and data. 4444 */ 4445 int 4446 _bcm_field_th_lt_entry_hw_install(int unit, soc_mem_t lt_tcam_mem, int tcam_idx, 4447 uint32 *key, uint32 *mask, uint32 *data, 4448 uint8 valid) 4449 { 4450 uint32 entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; /* Entry buffer. */ 4451 4452 /* Input parameters check. */ 4453 if ((NULL == key) || (NULL == mask) || (NULL == data)) { 4454 /* Read entry into SW buffer. */ 4455 BCM_IF_ERROR_RETURN(soc_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY, 4456 tcam_idx, entry)); 4457 } else { 4458 /* Clear the entry in hardware. */ 4459 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 4460 tcam_idx, entry)); 4461 /* Read entry into SW buffer. */ 4462 BCM_IF_ERROR_RETURN(soc_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY, tcam_idx, 4463 entry)); 4464 /* Set entry Key, Mask and Data value. */ 4465 soc_mem_field_set(unit, lt_tcam_mem, entry, KEYf, key); 4466 soc_mem_field_set(unit, lt_tcam_mem, entry, MASKf, mask); 4467 soc_mem_field_set(unit, lt_tcam_mem, entry, DATAf, data); 4468 } 4469 4470 /* Set entry valid bit status. */ 4471 soc_mem_field32_set(unit, lt_tcam_mem, entry, VALIDf, valid); 4472 4473 /* Install entry in hardware. */ 4474 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 4475 tcam_idx, entry)); 4476 return (BCM_E_NONE); 4477 } 4478 4479 /* 4480 * Function: 4481 * _bcm_field_th_lt_entry_install 4482 * Purpose: 4483 * Install a logical table entry in hardware. 4484 * Parameters: 4485 * unit - (IN) BCM device number. 4486 * f_presel - (IN) Reference to Field Preselector Entry structure. 4487 * lt_fs - (IN) Reference to the Logical table slice structure. 4488 * Returns: 4489 * BCM_E_XXX 4490 */ 4491 int 4492 _bcm_field_th_lt_entry_install(int unit, _field_presel_entry_t *f_presel, 4493 _field_lt_slice_t *lt_fs) 4494 { 4495 _field_stage_t *stage_fc; /* Stage Field Control structure. */ 4496 int tcam_idx; /* Entry TCAM index. */ 4497 _field_control_t *fc; /* Field control pointer. */ 4498 int rv = BCM_E_NONE; /* Operation return status. */ 4499 soc_mem_t lt_tcam_mem; /* TCAM memory ID. */ 4500 uint8 valid; /* Entry Valid bit. */ 4501 4502 /* Input parameters check. */ 4503 if (NULL == f_presel || NULL == lt_fs) { 4504 return (BCM_E_PARAM); 4505 } 4506 4507 /* Get device field control structure. */ 4508 BCM_IF_ERROR_RETURN(_field_control_get(unit , &fc)); 4509 4510 /* Get device stage control structure. */ 4511 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 4512 f_presel->group->stage_id, &stage_fc)); 4513 4514 /* 4515 * Get TCAM view to be used for programming the hardware based on the group 4516 * operational mode. 4517 */ 4518 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 4519 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 4520 f_presel->group->instance, 4521 _BCM_FIELD_MEM_TYPE_IFP_LT, 4522 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 4523 <_tcam_mem, NULL)); 4524 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 4525 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 4526 f_presel->group->instance, 4527 _BCM_FIELD_MEM_TYPE_EM_LT, 4528 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 4529 <_tcam_mem, NULL)); 4530 #if defined(BCM_FLOWTRACKER_SUPPORT) 4531 } else if ((soc_feature(unit, soc_feature_field_flowtracker_support)) && 4532 (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 4533 return _bcm_field_hx5_ft_lt_entry_install(unit, f_presel, lt_fs); 4534 #endif 4535 } else { 4536 return (BCM_E_PARAM); 4537 } 4538 BCM_IF_ERROR_RETURN(rv); 4539 4540 #if defined(BCM_TOMAHAWK2_SUPPORT) 4541 if (soc_feature(unit, soc_feature_field_multi_pipe_enhanced) && 4542 _BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 4543 valid = (f_presel->group->flags & _FP_GROUP_LOOKUP_ENABLED) ? 3 : 0; 4544 } else 4545 #endif /* BCM_TOMAHAWK2_SUPPORT */ 4546 { 4547 valid = (f_presel->group->flags & _FP_GROUP_LOOKUP_ENABLED) ? 4548 (soc_feature(unit, soc_feature_td3_style_fp) ? 3 : 1) : 0; 4549 } 4550 rv = _bcm_field_presel_entry_tcam_idx_get(unit, f_presel, lt_fs, 4551 &tcam_idx); 4552 BCM_IF_ERROR_RETURN(rv); 4553 4554 /* Install all parts of the entry in hardware. */ 4555 rv = _bcm_field_th_lt_entry_hw_install(unit, lt_tcam_mem, tcam_idx, 4556 f_presel->lt_tcam.key, 4557 f_presel->lt_tcam.mask, 4558 f_presel->lt_data.data, 4559 valid); 4560 if (BCM_FAILURE(rv)) { 4561 return (rv); 4562 } 4563 4564 f_presel->flags &= ~_FP_ENTRY_DIRTY; 4565 f_presel->flags |= _FP_ENTRY_INSTALLED; 4566 f_presel->flags |= _FP_ENTRY_ENABLED; 4567 4568 return (rv); 4569 } 4570 4571 /* 4572 * Function: 4573 * _bcm_field_th_lt_entry_parts_install 4574 * Purpose: 4575 * Install a logical table entry and its parts in hardware. 4576 * Parameters: 4577 * unit - (IN) BCM device number. 4578 * f_presel - (IN) Reference to Field Preselector Entry strcture. 4579 * Returns: 4580 * BCM_E_XXX 4581 */ 4582 int 4583 _bcm_field_th_lt_entry_parts_install(int unit, _field_presel_entry_t *f_presel) 4584 { 4585 int part, parts_count = -1; 4586 _field_lt_slice_t *lt_fs; 4587 _field_presel_entry_t *f_presel_p; 4588 4589 /* Input parameters check. */ 4590 if (NULL == f_presel) { 4591 return (BCM_E_PARAM); 4592 } 4593 4594 /* Get number of entry parts. */ 4595 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit, 4596 f_presel->group->stage_id, 4597 f_presel->group->flags, &parts_count)); 4598 4599 f_presel_p = f_presel; 4600 for (part = parts_count -1; part >= 0; part--) { 4601 if (f_presel_p == NULL) { 4602 return BCM_E_INTERNAL; 4603 } 4604 4605 lt_fs = f_presel_p->lt_fs; 4606 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_install 4607 (unit, f_presel_p, lt_fs)); 4608 f_presel_p = f_presel_p->next; 4609 } 4610 4611 return BCM_E_NONE; 4612 } 4613 4614 /* 4615 * Function: _bcm_field_th_group_presel_get 4616 * 4617 * Purpose: 4618 * Retrieve the set of preselectors associated with the given group. 4619 * 4620 * Parameters: 4621 * unit - (IN) BCM device number. 4622 * group - (IN) Group Id. 4623 * presel - (OUT) Reference to the set of preselectors. 4624 * 4625 * Returns: 4626 * BCM_E_PARAM - if presel_id == NULL or given group Id is not valid. 4627 * BCM_E_UNAVAIL - not supported 4628 * BCM_E_NONE - Success 4629 */ 4630 4631 int 4632 _bcm_field_th_group_presel_get( 4633 int unit, 4634 bcm_field_group_t group, 4635 bcm_field_presel_set_t *presel) 4636 { 4637 int idx; 4638 _field_group_t *fg; /* Field group pointer. */ 4639 _field_control_t *fc; /* Field control structure. */ 4640 4641 /* Input parameters check. */ 4642 if (NULL == presel) { 4643 return (BCM_E_PARAM); 4644 } 4645 4646 /* Get field control structure. */ 4647 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4648 4649 BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg)); 4650 4651 sal_memset(presel, 0x0, sizeof(bcm_field_presel_set_t)); 4652 /* count the number of preselector entries associated to the group */ 4653 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 4654 if (fg->presel_ent_arr[idx] != NULL) { 4655 BCM_FIELD_PRESEL_ADD(*presel, fg->presel_ent_arr[idx]->presel_id); 4656 } 4657 } 4658 4659 return BCM_E_NONE; 4660 } 4661 4662 /* 4663 * Function: _bcm_field_th_field_presel_set 4664 * 4665 * Purpose: 4666 * Set the preselectors to the given group. 4667 * 4668 * Parameters: 4669 * unit - (IN) BCM device number. 4670 * group - (IN) Group Id. 4671 * presel - (IN) Reference to the set of preselectors. 4672 * 4673 * Returns: 4674 * BCM_E_PARAM - if presel_id == NULL 4675 * BCM_E_UNAVAIL - not supported 4676 * BCM_E_NOT_FOUND - if the presel Ids are not created. 4677 * BCM_E_INTERAL - in-case of internal functionality issues. 4678 * BCM_E_NONE - Success 4679 */ 4680 4681 int 4682 _bcm_field_th_group_presel_set( 4683 int unit, 4684 bcm_field_group_t group, 4685 bcm_field_presel_set_t *presel) 4686 { 4687 int rv = BCM_E_UNAVAIL; /* Operation return status. */ 4688 _field_group_t *fg; /* Field group pointer. */ 4689 _field_control_t *fc; /* Field control structure. */ 4690 _field_stage_t *stage_fc; /* Stage field structure. */ 4691 int idx, ent_ct; 4692 int presel_ent_ct = 0, presel_id_ct = 0; 4693 int prio[_FP_PRESEL_ENTRIES_MAX_PER_GROUP]; 4694 _field_presel_entry_t *f_presel; 4695 _field_presel_entry_t *f_presel_arr[_FP_PRESEL_ENTRIES_MAX_PER_GROUP]; 4696 _field_lt_slice_t *lt_fs; 4697 4698 /* Get field control structure. */ 4699 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4700 4701 BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg)); 4702 4703 /* Get device stage control structure. */ 4704 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 4705 fg->stage_id, &stage_fc)); 4706 4707 /* Group should support the preselector feature. */ 4708 if (!(fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) { 4709 return BCM_E_UNAVAIL; 4710 } 4711 4712 4713 /* Validate all the preselector entries in the set */ 4714 for (idx = 0; idx < BCM_FIELD_PRESEL_SEL_MAX; idx++) { 4715 if (BCM_FIELD_PRESEL_TEST(*presel, idx)) { 4716 /* Check if presel ID is already created */ 4717 if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, idx)) { 4718 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4719 "ERROR: Preselector ID[%d] is not created.\n\r"), idx)); 4720 return BCM_E_NOT_FOUND; 4721 } 4722 if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, idx)) { 4723 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 4724 "Preselector ID[%d] is already in USE" 4725 "Updating the hardware.\n\r"), idx)); 4726 BCM_IF_ERROR_RETURN(_bcm_field_presel_entry_get(unit, idx, 4727 &f_presel)); 4728 rv = _field_presel_entry_update(unit, f_presel); 4729 } 4730 presel_id_ct++; 4731 } 4732 } 4733 if(BCM_E_UNAVAIL != rv) { 4734 return rv; 4735 } 4736 /* count the number of preselector entries associated to the group */ 4737 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 4738 if (fg->presel_ent_arr[idx] != NULL) { 4739 presel_ent_ct++; 4740 } 4741 } 4742 4743 /* Check if group supports the presel entries. */ 4744 if ((presel_ent_ct + presel_id_ct) > _FP_PRESEL_ENTRIES_MAX_PER_GROUP) { 4745 return BCM_E_RESOURCE; 4746 } 4747 4748 /* Check if the Slice has free entries */ 4749 lt_fs = fg->presel_ent_arr[0]->lt_fs; 4750 if (lt_fs->free_count < presel_id_ct) { 4751 return BCM_E_RESOURCE; 4752 } 4753 4754 ent_ct = 0; 4755 /* Add the preselector entries to the group */ 4756 for (idx = 0; idx < BCM_FIELD_PRESEL_SEL_MAX; idx++) { 4757 if (BCM_FIELD_PRESEL_TEST(*presel, idx)) { 4758 BCM_IF_ERROR_RETURN(_bcm_field_presel_entry_get(unit, idx, 4759 &f_presel)); 4760 f_presel_arr[ent_ct] = f_presel; 4761 prio[ent_ct] = f_presel->priority; 4762 f_presel->priority = 0; 4763 ent_ct++; 4764 } 4765 } 4766 4767 /* 4768 * Create Presel Entries in the LT slice associated with the group 4769 */ 4770 for (idx = 0; idx < ent_ct; idx++) { 4771 f_presel = f_presel_arr[idx]; 4772 /* Assign the preselectors to the group presel array. */ 4773 rv = _bcm_field_presel_group_add(unit, fg, f_presel->presel_id); 4774 if (BCM_FAILURE(rv)) { 4775 return rv; 4776 } 4777 4778 /* Allocate the presel entries in the LT slice for this group. */ 4779 BCM_IF_ERROR_RETURN 4780 (_bcm_field_th_lt_entry_config_set(unit, stage_fc, fg, 4781 lt_fs, f_presel)); 4782 4783 /* Install the LT Entry in HW. */ 4784 rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel); 4785 BCM_IF_ERROR_RETURN(rv); 4786 4787 rv = _field_presel_entry_prio_set(unit, f_presel, prio[idx]); 4788 if (BCM_FAILURE(rv)) { 4789 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 4790 "ERROR: Unable to set the priority[%d] for Preselector ID[%d].\n\r"), 4791 prio[idx], idx)); 4792 return BCM_E_INTERNAL; 4793 } 4794 } 4795 4796 return rv; 4797 } 4798 4799 /* 4800 * Function: 4801 * _bcm_field_th_ingress_lt_action_prio_install 4802 * Purpose: 4803 * Write logical table action priortiy information to hardware. 4804 * Parameters: 4805 * unit - (IN) BCM device number. 4806 * stage_fc - (IN) Field stage control structure. 4807 * fg - (IN) Field group Structure. 4808 * Returns: 4809 * BCM_E_XXX 4810 */ 4811 int 4812 _bcm_field_th_ingress_lt_action_prio_install(int unit, 4813 _field_stage_t *stage_fc, 4814 _field_group_t *fg) 4815 { 4816 soc_field_t field; /* HW entry field. */ 4817 uint32 value; /* Entry field value. */ 4818 int lt_idx; /* LT iterator. */ 4819 _field_lt_config_t *lt_info; /* Logical table info. */ 4820 _field_control_t *fc; /* Field control structure. */ 4821 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 4822 /* Entry buffer. */ 4823 static const soc_field_t lt_action_pri[] = { /* LT action priority 4824 fields list. */ 4825 LOGICAL_TABLE_0_ACTION_PRIORITYf, 4826 LOGICAL_TABLE_1_ACTION_PRIORITYf, 4827 LOGICAL_TABLE_2_ACTION_PRIORITYf, 4828 LOGICAL_TABLE_3_ACTION_PRIORITYf, 4829 LOGICAL_TABLE_4_ACTION_PRIORITYf, 4830 LOGICAL_TABLE_5_ACTION_PRIORITYf, 4831 LOGICAL_TABLE_6_ACTION_PRIORITYf, 4832 LOGICAL_TABLE_7_ACTION_PRIORITYf, 4833 LOGICAL_TABLE_8_ACTION_PRIORITYf, 4834 LOGICAL_TABLE_9_ACTION_PRIORITYf, 4835 LOGICAL_TABLE_10_ACTION_PRIORITYf, 4836 LOGICAL_TABLE_11_ACTION_PRIORITYf, 4837 LOGICAL_TABLE_12_ACTION_PRIORITYf, 4838 LOGICAL_TABLE_13_ACTION_PRIORITYf, 4839 LOGICAL_TABLE_14_ACTION_PRIORITYf, 4840 LOGICAL_TABLE_15_ACTION_PRIORITYf, 4841 LOGICAL_TABLE_16_ACTION_PRIORITYf, 4842 LOGICAL_TABLE_17_ACTION_PRIORITYf, 4843 LOGICAL_TABLE_18_ACTION_PRIORITYf, 4844 LOGICAL_TABLE_19_ACTION_PRIORITYf, 4845 LOGICAL_TABLE_20_ACTION_PRIORITYf, 4846 LOGICAL_TABLE_21_ACTION_PRIORITYf, 4847 LOGICAL_TABLE_22_ACTION_PRIORITYf, 4848 LOGICAL_TABLE_23_ACTION_PRIORITYf, 4849 LOGICAL_TABLE_24_ACTION_PRIORITYf, 4850 LOGICAL_TABLE_25_ACTION_PRIORITYf, 4851 LOGICAL_TABLE_26_ACTION_PRIORITYf, 4852 LOGICAL_TABLE_27_ACTION_PRIORITYf, 4853 LOGICAL_TABLE_28_ACTION_PRIORITYf, 4854 LOGICAL_TABLE_29_ACTION_PRIORITYf, 4855 LOGICAL_TABLE_30_ACTION_PRIORITYf, 4856 LOGICAL_TABLE_31_ACTION_PRIORITYf 4857 }; 4858 4859 static soc_mem_t lt_action_mem; 4860 4861 /* Input parameters check. */ 4862 if (NULL == fg || NULL == stage_fc) { 4863 return (BCM_E_PARAM); 4864 } 4865 4866 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4867 4868 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 4869 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 4870 IFP_LOGICAL_TABLE_ACTION_PRIORITYm, 4871 _FP_GLOBAL_INST, <_action_mem)); 4872 } else { 4873 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 4874 IFP_LOGICAL_TABLE_ACTION_PRIORITYm, 4875 fg->instance, <_action_mem)); 4876 } 4877 /* Read logical table action priority entry from hardware. */ 4878 BCM_IF_ERROR_RETURN(soc_mem_read(unit, lt_action_mem, 4879 MEM_BLOCK_ANY, 0, &entry)); 4880 4881 /* Program Logical Tables configuration in hardware. */ 4882 for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) { 4883 /* Get logical table info for the default FP instance. */ 4884 lt_info = fc->lt_info[fg->instance][lt_idx]; 4885 4886 /* Get LT action priority value. */ 4887 value = lt_info->lt_action_pri; 4888 field = lt_action_pri[lt_idx]; 4889 4890 /* Set the value in entry buffer that's to be programmed in HW. */ 4891 soc_mem_field32_set(unit, lt_action_mem, &entry, 4892 field, value); 4893 } 4894 4895 /* Write LT action priority entry in hardware. */ 4896 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_action_mem, 4897 MEM_BLOCK_ANY, 0, &entry)); 4898 4899 return BCM_E_NONE; 4900 } 4901 4902 #if defined (BCM_HELIX5_SUPPORT) 4903 /* 4904 * Function: 4905 * _field_hx5_ingress_lt_partition_prio_write 4906 * Purpose: 4907 * Write LT Partition priortiy for the given LT ID and Slice to HW. 4908 * Parameters: 4909 * unit - (IN) BCM device number. 4910 * stage_fc - (IN) Field stage control structure. 4911 * fg - (IN) Field group Structure. 4912 * Returns: 4913 * BCM_E_XXX 4914 * Note: slice == -1 implies configure partition priority for all slices 4915 * for the given lt_id. 4916 */ 4917 4918 int 4919 _bcm_field_hx5_ingress_lt_partition_prio_write(int unit, 4920 _field_stage_t *stage_fc, 4921 _field_group_t *fg, int lt_id, 4922 int slice) 4923 { 4924 int rv; /* Operation return status. */ 4925 int slice_num; /* Slice number. */ 4926 int value; /* Partition Prio value. */ 4927 uint32 lt_config_entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; 4928 /* HW entry buffer. */ 4929 _field_lt_config_t *lt_info; /* Logical table info. */ 4930 soc_field_t field; /* HW entry field. */ 4931 _field_control_t *fc; /* Field control structure. */ 4932 4933 static const soc_field_t lt_part_pri[] = { 4934 LOGICAL_PARTITION_PRIORITY_0f, 4935 LOGICAL_PARTITION_PRIORITY_1f, 4936 LOGICAL_PARTITION_PRIORITY_2f, 4937 LOGICAL_PARTITION_PRIORITY_3f, 4938 LOGICAL_PARTITION_PRIORITY_4f, 4939 LOGICAL_PARTITION_PRIORITY_5f, 4940 LOGICAL_PARTITION_PRIORITY_6f, 4941 LOGICAL_PARTITION_PRIORITY_7f, 4942 LOGICAL_PARTITION_PRIORITY_8f, 4943 LOGICAL_PARTITION_PRIORITY_9f, 4944 LOGICAL_PARTITION_PRIORITY_10f, 4945 LOGICAL_PARTITION_PRIORITY_11f, 4946 LOGICAL_PARTITION_PRIORITY_12f, 4947 LOGICAL_PARTITION_PRIORITY_13f, 4948 LOGICAL_PARTITION_PRIORITY_14f, 4949 LOGICAL_PARTITION_PRIORITY_15f, 4950 LOGICAL_PARTITION_PRIORITY_16f, 4951 LOGICAL_PARTITION_PRIORITY_17f 4952 4953 }; 4954 4955 static soc_mem_t lt_config_mem = IFP_LOGICAL_TABLE_CONFIGm; 4956 4957 /* Input parameters check. */ 4958 if (NULL == fg || NULL == stage_fc) { 4959 return (BCM_E_PARAM); 4960 } 4961 4962 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 4963 4964 rv = soc_mem_read(unit, lt_config_mem, MEM_BLOCK_ANY, 4965 lt_id, <_config_entry); 4966 BCM_IF_ERROR_RETURN(rv); 4967 4968 /* Get logical table info for the default FP instance. */ 4969 lt_info = fc->lt_info[fg->instance][lt_id]; 4970 for (slice_num = 0; slice_num < stage_fc->tcam_slices; slice_num++) { 4971 if ((slice != -1) && (slice_num != slice)) { 4972 continue; 4973 } 4974 field = lt_part_pri[slice_num]; 4975 value = lt_info->lt_part_pri[slice_num]; 4976 soc_mem_field32_set(unit, lt_config_mem, 4977 <_config_entry, field, value); 4978 } 4979 soc_mem_field32_set(unit, lt_config_mem, <_config_entry, 4980 LOGICAL_PARTITION_MAPf, lt_info->lt_part_map); 4981 4982 /* Write new LT configuration in hardware. */ 4983 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_config_mem, 4984 MEM_BLOCK_ANY, lt_id, <_config_entry)); 4985 return BCM_E_NONE; 4986 } 4987 4988 /* 4989 * Function: 4990 * _field_hx5_ingress_lt_partition_prio_install 4991 * Purpose: 4992 * Write logical table Partition priortiy information to hardware. 4993 * Parameters: 4994 * unit - (IN) BCM device number. 4995 * stage_fc - (IN) Field stage control structure. 4996 * fg - (IN) Field group Structure. 4997 * Returns: 4998 * BCM_E_XXX 4999 */ 5000 STATIC int 5001 _field_hx5_ingress_lt_partition_prio_install(int unit, _field_stage_t *stage_fc, 5002 _field_group_t *fg) 5003 { 5004 soc_field_t field; /* HW entry field. */ 5005 uint32 value; /* Entry field value. */ 5006 int lt_idx; /* LT iterator. */ 5007 int slice; /* Slice iterator. */ 5008 uint32 lt_config_entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; 5009 /* HW entry buffer. */ 5010 _field_lt_config_t *lt_info; /* Logical table info. */ 5011 int rv; /* Operation return status. */ 5012 _field_control_t *fc; /* Field control structure. */ 5013 5014 static const soc_field_t lt_part_pri[] = { 5015 LOGICAL_PARTITION_PRIORITY_0f, 5016 LOGICAL_PARTITION_PRIORITY_1f, 5017 LOGICAL_PARTITION_PRIORITY_2f, 5018 LOGICAL_PARTITION_PRIORITY_3f, 5019 LOGICAL_PARTITION_PRIORITY_4f, 5020 LOGICAL_PARTITION_PRIORITY_5f, 5021 LOGICAL_PARTITION_PRIORITY_6f, 5022 LOGICAL_PARTITION_PRIORITY_7f, 5023 LOGICAL_PARTITION_PRIORITY_8f, 5024 LOGICAL_PARTITION_PRIORITY_9f, 5025 LOGICAL_PARTITION_PRIORITY_10f, 5026 LOGICAL_PARTITION_PRIORITY_11f, 5027 LOGICAL_PARTITION_PRIORITY_12f, 5028 LOGICAL_PARTITION_PRIORITY_13f, 5029 LOGICAL_PARTITION_PRIORITY_14f, 5030 LOGICAL_PARTITION_PRIORITY_15f, 5031 LOGICAL_PARTITION_PRIORITY_16f, 5032 LOGICAL_PARTITION_PRIORITY_17f 5033 5034 }; 5035 5036 static soc_mem_t lt_config_mem = IFP_LOGICAL_TABLE_CONFIGm; 5037 5038 /* Input parameters check. */ 5039 if (NULL == fg || NULL == stage_fc) { 5040 return (BCM_E_PARAM); 5041 } 5042 5043 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5044 5045 /* Program Logical Tables configuration in hardware. */ 5046 for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) { 5047 5048 /* Get logical table info for the default FP instance. */ 5049 lt_info = fc->lt_info[fg->instance][lt_idx]; 5050 5051 rv = soc_mem_read(unit, lt_config_mem, MEM_BLOCK_ANY, 5052 lt_idx, <_config_entry); 5053 BCM_IF_ERROR_RETURN(rv); 5054 5055 /* 5056 * Construct the LT Partition Map and Partition 5057 * Priority entry for the LT. 5058 */ 5059 for (slice = 0; slice < stage_fc->tcam_slices; slice++) { 5060 field = lt_part_pri[slice]; 5061 value = lt_info->lt_part_pri[slice]; 5062 soc_mem_field32_set(unit, lt_config_mem, 5063 <_config_entry, field, value); 5064 } 5065 5066 soc_mem_field32_set(unit, lt_config_mem, <_config_entry, 5067 LOGICAL_PARTITION_MAPf, lt_info->lt_part_map); 5068 5069 /* Write new LT configuration in hardware. */ 5070 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_config_mem, 5071 MEM_BLOCK_ANY, lt_idx, <_config_entry)); 5072 } 5073 return BCM_E_NONE; 5074 } 5075 #endif 5076 5077 /* 5078 * Function: 5079 * _field_th_ingress_lt_partition_prio_write 5080 * Purpose: 5081 * Write LT Partition priortiy for the given LT ID and Slice to HW. 5082 * Parameters: 5083 * unit - (IN) BCM device number. 5084 * stage_fc - (IN) Field stage control structure. 5085 * fg - (IN) Field group Structure. 5086 * Returns: 5087 * BCM_E_XXX 5088 * Note: slice == -1 implies configure partition priority for all slices 5089 * for the given lt_id. 5090 */ 5091 5092 int 5093 _bcm_field_th_ingress_lt_partition_prio_write(int unit, 5094 _field_stage_t *stage_fc, 5095 _field_group_t *fg, int lt_id, 5096 int slice) 5097 { 5098 int rv; /* Operation return status. */ 5099 int slice_num; /* Slice number. */ 5100 int value; /* Partition Prio value. */ 5101 uint64 lt_config_entry; /* HW entry buffer. */ 5102 _field_lt_config_t *lt_info; /* Logical table info. */ 5103 soc_field_t field; /* HW entry field. */ 5104 _field_control_t *fc; /* Field control structure. */ 5105 5106 static const soc_field_t lt_part_pri[] = { 5107 LOGICAL_PARTITION_PRIORITY_0f, 5108 LOGICAL_PARTITION_PRIORITY_1f, 5109 LOGICAL_PARTITION_PRIORITY_2f, 5110 LOGICAL_PARTITION_PRIORITY_3f, 5111 LOGICAL_PARTITION_PRIORITY_4f, 5112 LOGICAL_PARTITION_PRIORITY_5f, 5113 LOGICAL_PARTITION_PRIORITY_6f, 5114 LOGICAL_PARTITION_PRIORITY_7f, 5115 LOGICAL_PARTITION_PRIORITY_8f, 5116 LOGICAL_PARTITION_PRIORITY_9f, 5117 LOGICAL_PARTITION_PRIORITY_10f, 5118 LOGICAL_PARTITION_PRIORITY_11f 5119 }; 5120 5121 static soc_reg_t lt_config_reg; 5122 5123 /* Input parameters check. */ 5124 if (NULL == fg || NULL == stage_fc) { 5125 return (BCM_E_PARAM); 5126 } 5127 5128 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5129 5130 /* Retrieve the Pipe instance. */ 5131 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 5132 5133 BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit, 5134 IFP_LOGICAL_TABLE_CONFIGr, 5135 _FP_GLOBAL_INST, 5136 <_config_reg)); 5137 } else { 5138 BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit, 5139 IFP_LOGICAL_TABLE_CONFIGr, 5140 fg->instance, 5141 <_config_reg)); 5142 } 5143 5144 rv = soc_reg_get(unit, lt_config_reg, REG_PORT_ANY, 5145 lt_id, <_config_entry); 5146 BCM_IF_ERROR_RETURN(rv); 5147 5148 /* Get logical table info for the default FP instance. */ 5149 lt_info = fc->lt_info[fg->instance][lt_id]; 5150 for (slice_num = 0; slice_num < stage_fc->tcam_slices; slice_num++) { 5151 if ((slice != -1) && (slice_num != slice)) { 5152 continue; 5153 } 5154 field = lt_part_pri[slice_num]; 5155 value = lt_info->lt_part_pri[slice_num]; 5156 soc_reg64_field32_set(unit, lt_config_reg, 5157 <_config_entry, field, value); 5158 } 5159 soc_reg64_field32_set(unit, lt_config_reg, <_config_entry, 5160 LOGICAL_PARTITION_MAPf, lt_info->lt_part_map); 5161 5162 /* Write new LT configuration in hardware. */ 5163 BCM_IF_ERROR_RETURN(soc_reg_set(unit, lt_config_reg, 5164 REG_PORT_ANY, lt_id, lt_config_entry)); 5165 return BCM_E_NONE; 5166 } 5167 5168 /* 5169 * Function: 5170 * _field_th_ingress_lt_partition_prio_install 5171 * Purpose: 5172 * Write logical table Partition priortiy information to hardware. 5173 * Parameters: 5174 * unit - (IN) BCM device number. 5175 * stage_fc - (IN) Field stage control structure. 5176 * fg - (IN) Field group Structure. 5177 * Returns: 5178 * BCM_E_XXX 5179 */ 5180 STATIC int 5181 _field_th_ingress_lt_partition_prio_install(int unit, _field_stage_t *stage_fc, 5182 _field_group_t *fg) 5183 { 5184 soc_field_t field; /* HW entry field. */ 5185 uint32 value; /* Entry field value. */ 5186 int lt_idx; /* LT iterator. */ 5187 int slice; /* Slice iterator. */ 5188 uint64 lt_config_entry; /* HW entry buffer. */ 5189 _field_lt_config_t *lt_info; /* Logical table info. */ 5190 int rv; /* Operation return status. */ 5191 _field_control_t *fc; /* Field control structure. */ 5192 5193 static const soc_field_t lt_part_pri[] = { 5194 LOGICAL_PARTITION_PRIORITY_0f, 5195 LOGICAL_PARTITION_PRIORITY_1f, 5196 LOGICAL_PARTITION_PRIORITY_2f, 5197 LOGICAL_PARTITION_PRIORITY_3f, 5198 LOGICAL_PARTITION_PRIORITY_4f, 5199 LOGICAL_PARTITION_PRIORITY_5f, 5200 LOGICAL_PARTITION_PRIORITY_6f, 5201 LOGICAL_PARTITION_PRIORITY_7f, 5202 LOGICAL_PARTITION_PRIORITY_8f, 5203 LOGICAL_PARTITION_PRIORITY_9f, 5204 LOGICAL_PARTITION_PRIORITY_10f, 5205 LOGICAL_PARTITION_PRIORITY_11f 5206 }; 5207 5208 static soc_reg_t lt_config_reg; 5209 5210 /* Input parameters check. */ 5211 if (NULL == fg || NULL == stage_fc) { 5212 return (BCM_E_PARAM); 5213 } 5214 5215 /* Skip for Flowtracker */ 5216 #if defined(BCM_FLOWTRACKER_SUPPORT) 5217 if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 5218 return BCM_E_NONE; 5219 } 5220 #endif 5221 5222 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5223 5224 /* Retrieve the Pipe instance. */ 5225 if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) { 5226 BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit, 5227 IFP_LOGICAL_TABLE_CONFIGr, 5228 _FP_GLOBAL_INST, 5229 <_config_reg)); 5230 } else { 5231 5232 BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit, 5233 IFP_LOGICAL_TABLE_CONFIGr, 5234 fg->instance, 5235 <_config_reg)); 5236 } 5237 /* Program Logical Tables configuration in hardware. */ 5238 for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) { 5239 5240 /* Get logical table info for the default FP instance. */ 5241 lt_info = fc->lt_info[fg->instance][lt_idx]; 5242 5243 rv = soc_reg_get(unit, lt_config_reg, REG_PORT_ANY, 5244 lt_idx, <_config_entry); 5245 BCM_IF_ERROR_RETURN(rv); 5246 5247 /* 5248 * Construct the LT Partition Map and Partition 5249 * Priority entry for the LT. 5250 */ 5251 for (slice = 0; slice < stage_fc->tcam_slices; slice++) { 5252 field = lt_part_pri[slice]; 5253 value = lt_info->lt_part_pri[slice]; 5254 soc_reg64_field32_set(unit, lt_config_reg, 5255 <_config_entry, field, value); 5256 } 5257 soc_reg64_field32_set(unit, lt_config_reg, <_config_entry, 5258 LOGICAL_PARTITION_MAPf, lt_info->lt_part_map); 5259 5260 /* Write new LT configuration in hardware. */ 5261 BCM_IF_ERROR_RETURN(soc_reg_set(unit, lt_config_reg, 5262 REG_PORT_ANY, lt_idx, lt_config_entry)); 5263 } 5264 return BCM_E_NONE; 5265 } 5266 5267 /* 5268 * Function: 5269 * _bcm_field_th_ingress_logical_table_map_write 5270 * Purpose: 5271 * Write logical table partition map information to hardware. 5272 * Parameters: 5273 * unit - (IN) BCM device number. 5274 * stage_fc - (IN) Field stage control structure. 5275 * fg - (IN) Field group Structure. 5276 * Returns: 5277 * BCM_E_XXX 5278 */ 5279 int 5280 _bcm_field_th_ingress_logical_table_map_write(int unit, 5281 _field_stage_t *stage_fc, 5282 _field_group_t *fg) 5283 { 5284 int rv; /* Operation return status. */ 5285 5286 /* Input parameters check. */ 5287 if (NULL == fg || NULL == stage_fc) { 5288 return (BCM_E_PARAM); 5289 } 5290 5291 if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) { 5292 return BCM_E_NONE; 5293 } 5294 5295 /* Install LT Action Priority. */ 5296 rv = _bcm_field_th_ingress_lt_action_prio_install(unit, stage_fc, fg); 5297 if (BCM_FAILURE(rv)) { 5298 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 5299 "Error: LT Action Priority Install failed for group:%d\n\r"), 5300 fg->gid)); 5301 return rv; 5302 } 5303 5304 /* Install LT Partition Priority. */ 5305 #if defined (BCM_HELIX5_SUPPORT) 5306 if (SOC_IS_HELIX5(unit)) { 5307 rv = _field_hx5_ingress_lt_partition_prio_install(unit, stage_fc, fg); 5308 5309 } else 5310 #endif 5311 { 5312 rv = _field_th_ingress_lt_partition_prio_install(unit, stage_fc, fg); 5313 } 5314 5315 if (BCM_FAILURE(rv)) { 5316 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 5317 "Error: LT Partition Priority Install failed for group:%d\n\r"), 5318 fg->gid)); 5319 return rv; 5320 } 5321 5322 return BCM_E_NONE; 5323 } 5324 5325 /* 5326 * Function: 5327 * _bcm_field_th_lt_part_prio_reset 5328 * Purpose: 5329 * Reset the LT Partition Priority and also clear the 5330 * lt_map for the given slice. 5331 * Parameters: 5332 * unit - (IN) BCM device number. 5333 * stage_fc - (IN) Field stage control structure. 5334 * fg - (IN) Field group Structure. 5335 * fs - (IN) Field slice Structure. 5336 * Returns: 5337 * BCM_E_XXX 5338 */ 5339 int _bcm_field_th_lt_part_prio_reset(int unit, _field_stage_t *stage_fc, 5340 _field_group_t *fg, 5341 _field_slice_t *fs) 5342 { 5343 int rv; 5344 int found = 0; 5345 _field_slice_t *fs_ptr; 5346 _field_control_t *fc; /* Field control structure. */ 5347 5348 /* Input parameters check. */ 5349 if (NULL == stage_fc || NULL == fg || NULL == fs) { 5350 return (BCM_E_PARAM); 5351 } 5352 5353 if (NULL == fg->slices) { 5354 return BCM_E_INTERNAL; 5355 } 5356 5357 /* Get field control structure. */ 5358 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5359 5360 /* Clear Group's LT_ID bit in slice LT map. */ 5361 fs->lt_map &= ~(1 << fg->lt_id); 5362 5363 /* Reset the LT Partition Priority. */ 5364 fc->lt_info[fg->instance][fg->lt_id]->lt_part_map &= ~(1 << fs->slice_number); 5365 fc->lt_info[fg->instance][fg->lt_id]->lt_part_pri[fs->slice_number] = 0; 5366 5367 /* 5368 * Parse the existing auto-expanded slices for the group 5369 * And updae the partition priority. 5370 */ 5371 for (fs_ptr = fg->slices; fs_ptr != NULL; fs_ptr = fs_ptr->next) { 5372 if (fs_ptr == fs) { 5373 found = 1; 5374 continue; 5375 } 5376 5377 if (found == 1) { 5378 fc->lt_info[fg->instance][fg->lt_id]->lt_part_pri[fs_ptr->slice_number] += 1; 5379 } 5380 } 5381 5382 /* Set the partition Priority. */ 5383 #if defined (BCM_HELIX5_SUPPORT) 5384 if (SOC_IS_HELIX5(unit)) { 5385 rv = _bcm_field_hx5_ingress_lt_partition_prio_write(unit, stage_fc, fg, 5386 fg->lt_id, -1); 5387 5388 } else 5389 #endif 5390 { 5391 rv = _bcm_field_th_ingress_lt_partition_prio_write(unit, stage_fc, fg, 5392 fg->lt_id, -1); 5393 } 5394 5395 if (BCM_FAILURE(rv)) { 5396 LOG_ERROR(BSL_LS_BCM_FP, 5397 (BSL_META_U(unit, "Error: LT Partition Reset failed for" 5398 " group:%d lt_id:%d slice:%d\n\r"), 5399 fg->gid, fg->lt_id, fs->slice_number)); 5400 } 5401 5402 return rv; 5403 } 5404 5405 5406 /* 5407 * Function: 5408 * _bcm_field_th_lt_part_prio_value_get 5409 * Purpose: 5410 * Configure and return a LT Partition Priority for the given LT ID from a group. 5411 * Parameters: 5412 * unit - (IN) BCM device number. 5413 * fg - (IN) Field group Structure. 5414 * lt_part_prio - (OUT) LT Partition priority value. 5415 * Returns: 5416 * BCM_E_XXX 5417 */ 5418 int _bcm_field_th_lt_part_prio_value_get(int unit, _field_group_t *fg, 5419 int *lt_part_prio) 5420 { 5421 int part_prio = 0; 5422 _field_slice_t *group_fs; 5423 _field_control_t *fc; /* Field control structure. */ 5424 _field_stage_t *stage_fc; /* Stage field control. */ 5425 5426 /* Input parameters check. */ 5427 if (NULL == fg || NULL == lt_part_prio) { 5428 return (BCM_E_PARAM); 5429 } 5430 5431 /* Get field control structure. */ 5432 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5433 5434 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id, 5435 &stage_fc)); 5436 5437 /* Parse the existing auto-expanded slices for the group */ 5438 for (group_fs = fg->slices; group_fs != NULL; group_fs = group_fs->next) { 5439 part_prio = fc->lt_info[fg->instance][fg->lt_id]->lt_part_pri[group_fs->slice_number]; 5440 } 5441 5442 /* Assign the least priority to the latest slice. */ 5443 *lt_part_prio = part_prio - 1; 5444 if (*lt_part_prio <= 0) { 5445 return BCM_E_INTERNAL; 5446 } 5447 5448 return BCM_E_NONE; 5449 } 5450 5451 /* 5452 * Function: 5453 * _bcm_field_th_presel_entry_hw_remove 5454 * Purpose: 5455 * Remove Preselector Entries from hardware. 5456 * Parameters: 5457 * unit - (IN) BCM device number. 5458 * f_presel - (IN) Field Preselector Entries. 5459 * Returns: 5460 * BCM_E_XXX 5461 */ 5462 int 5463 _bcm_field_th_presel_entry_hw_remove(int unit, _field_presel_entry_t *f_presel) 5464 { 5465 int parts_count = -1; /* Entry parts count. */ 5466 int part; /* Entry part. */ 5467 int tcam_idx; /* LT TCAM entry index. */ 5468 soc_mem_t lt_tcam_mem; /* LT TCAM Memory. */ 5469 _field_stage_t *stage_fc; /* Field Stage Pointer. */ 5470 _field_presel_entry_t *f_presel_p; /* Presel Part entry. */ 5471 5472 /* Input parameters check. */ 5473 if (NULL == f_presel) { 5474 return (BCM_E_PARAM); 5475 } 5476 5477 if ((f_presel->flags & _FP_ENTRY_INSTALLED) == 0) { 5478 /* Entry not installed in hardware. */ 5479 return (BCM_E_NONE); 5480 } 5481 5482 /* Get device stage control structure. */ 5483 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 5484 f_presel->group->stage_id, &stage_fc)); 5485 5486 /* Get number of entry parts using group flags. . */ 5487 BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit, 5488 f_presel->group->flags, &parts_count)); 5489 5490 /* Get TCAM view to be used for programming the hardware. */ 5491 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 5492 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 5493 f_presel->group->instance, 5494 _BCM_FIELD_MEM_TYPE_IFP_LT, 5495 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 5496 <_tcam_mem, NULL)); 5497 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 5498 BCM_IF_ERROR_RETURN(_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 5499 f_presel->group->instance, 5500 _BCM_FIELD_MEM_TYPE_EM_LT, 5501 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 5502 <_tcam_mem, NULL)); 5503 #if defined(BCM_FLOWTRACKER_SUPPORT) 5504 } else if ((soc_feature(unit, soc_feature_field_flowtracker_support)) && 5505 (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) { 5506 return _bcm_field_hx5_ft_lt_entry_hw_remove(unit, f_presel); 5507 #endif 5508 } else { 5509 return (BCM_E_PARAM); 5510 } 5511 5512 /* Iterate over entry parts and remove the entry from HW. */ 5513 f_presel_p = f_presel; 5514 for (part = 0; part < parts_count; part++) { 5515 if (f_presel_p == NULL) { 5516 break; 5517 } 5518 5519 /* Given entry part number, get the entry TCAM index. */ 5520 BCM_IF_ERROR_RETURN(_bcm_field_presel_entry_tcam_idx_get(unit, 5521 f_presel_p, f_presel_p->lt_fs, &tcam_idx)); 5522 5523 /* Clear TCAM entry in hardware at the supplied TCAM index. */ 5524 SOC_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 5525 tcam_idx, soc_mem_entry_null(unit, lt_tcam_mem))); 5526 5527 f_presel_p->flags |= _FP_ENTRY_DIRTY; 5528 f_presel_p->flags &= ~(_FP_ENTRY_INSTALLED); 5529 f_presel_p->flags &= ~(_FP_ENTRY_ENABLED); 5530 5531 f_presel_p = f_presel_p->next; 5532 } 5533 5534 return (BCM_E_NONE); 5535 } 5536 5537 /* Function to disable the presel entries for a given group */ 5538 int 5539 _bcm_field_th_group_presel_enable_set(int unit, 5540 _field_stage_t *stage_fc, 5541 _field_group_t *fg, 5542 uint32 valid) 5543 { 5544 int rv, idx; 5545 int tcam_idx; 5546 soc_mem_t lt_tcam_mem; 5547 _field_lt_slice_t *lt_part_fs; 5548 _field_presel_entry_t *f_presel_p; 5549 _field_presel_entry_t *f_presel; 5550 5551 /* Input parameters check. */ 5552 if ((NULL == fg) || (NULL == stage_fc)) { 5553 return (BCM_E_PARAM); 5554 } 5555 5556 /* 5557 * Get TCAM view to be used for programming the hardware based on the group 5558 * operational mode. 5559 */ 5560 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 5561 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 5562 fg->instance, 5563 _BCM_FIELD_MEM_TYPE_IFP_LT, 5564 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 5565 <_tcam_mem, NULL)); 5566 /* 5567 * For TH2 and TD3, the IFP valid field is of 2 bits, 5568 * hence the value 3 has to be set in case of enable 5569 */ 5570 valid = (valid) ? 5571 ((soc_feature(unit, soc_feature_field_multi_pipe_enhanced) || 5572 soc_feature(unit, soc_feature_td3_style_fp)) ? 3 : 1) : 0; 5573 } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) { 5574 rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 5575 fg->instance, 5576 _BCM_FIELD_MEM_TYPE_EM_LT, 5577 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB, 5578 <_tcam_mem, NULL)); 5579 /* TD3 EM valid field is of 2 bits */ 5580 valid = (valid) ? 5581 (soc_feature(unit, soc_feature_td3_style_fp) ? 3 : 1) : 0; 5582 } else { 5583 return (BCM_E_PARAM); 5584 } 5585 BCM_IF_ERROR_RETURN(rv); 5586 5587 f_presel = fg->presel_ent_arr[0]; 5588 if (f_presel == NULL) { 5589 return BCM_E_INTERNAL; 5590 } 5591 5592 /* Update Presel LT Slices. */ 5593 for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) { 5594 if (fg->presel_ent_arr[idx] != NULL) { 5595 f_presel = fg->presel_ent_arr[idx]; 5596 } else { 5597 continue; 5598 } 5599 5600 f_presel_p = f_presel; 5601 for (; f_presel_p != NULL; f_presel_p = f_presel_p->next) { 5602 lt_part_fs = f_presel_p->lt_fs; 5603 for (; lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) { 5604 rv = _bcm_field_presel_entry_tcam_idx_get(unit, f_presel_p, 5605 lt_part_fs, 5606 &tcam_idx); 5607 BCM_IF_ERROR_RETURN(rv); 5608 /* Install the LT Entry in HW. */ 5609 rv = _bcm_field_th_lt_entry_hw_install(unit, lt_tcam_mem, 5610 tcam_idx, 5611 NULL, NULL, NULL, 5612 valid); 5613 BCM_IF_ERROR_RETURN(rv); 5614 } 5615 } 5616 } 5617 5618 /* Enable/Disable group flags. */ 5619 if (valid) { 5620 fg->flags |= _FP_GROUP_LOOKUP_ENABLED; 5621 } else { 5622 fg->flags &= ~_FP_GROUP_LOOKUP_ENABLED; 5623 } 5624 5625 return BCM_E_NONE; 5626 } 5627 5628 5629 5630 /* 5631 * Function: 5632 * _bcm_field_th_source_class_mode_set 5633 * Purpose: 5634 * Retrieve Field Processor Source Class operational mode 5635 * per-CAP stage. 5636 * Parameters: 5637 * unit - (IN) BCM Device number. 5638 * stage - (IN) Field Stage enum value. 5639 * pbmp - (IN) Device Port Bitmap value 5640 * mode - (IN) Reference to Field Source Class Operational 5641 * Mode enum value. 5642 * Returns: 5643 * BCM_E_XXX 5644 * Notes: 5645 * Valid "stage" input parameter values supported by 5646 * this API are: 5647 * "bcmFieldStageIngress" 5648 * "bcmFieldStageIngressExactMatch" 5649 */ 5650 int 5651 _bcm_field_th_source_class_mode_set(int unit, 5652 bcm_field_stage_t stage, 5653 bcm_pbmp_t pbmp, 5654 bcm_field_src_class_mode_t mode) 5655 { 5656 _field_stage_t *stage_fc; /* Stage field control structure. */ 5657 _field_stage_id_t stage_id; /* Pipeline stage id */ 5658 _field_control_t *fc; 5659 _field_presel_entry_t *f_presel = NULL; /* Internal Presel descriptor */ 5660 _field_presel_info_t *presel_info; /* Presel information structure */ 5661 bcm_field_presel_t presel_idx = 0; 5662 bcm_field_qualify_t stage_qual; 5663 bcm_field_group_oper_mode_t group_mode; 5664 uint8 pipe_idx = 0; 5665 bcm_pbmp_t pbmp_temp; 5666 soc_reg_t lt_select_cfg_reg = INVALIDr; 5667 bcm_pbmp_t all_pbmp; /* Group port bitmap. */ 5668 5669 if (mode >= bcmFieldSrcClassModeCount) { 5670 return (BCM_E_PARAM); 5671 } 5672 5673 switch (stage) { 5674 case bcmFieldStageIngress: 5675 lt_select_cfg_reg = IFP_LOGICAL_TABLE_SELECT_CONFIGr; 5676 stage_id = _BCM_FIELD_STAGE_INGRESS; 5677 stage_qual = bcmFieldQualifyStageIngress; 5678 break; 5679 case bcmFieldStageIngressExactMatch: 5680 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 5681 stage_qual = bcmFieldQualifyStageIngressExactMatch; 5682 lt_select_cfg_reg = EXACT_MATCH_LOGICAL_TABLE_SELECT_CONFIGr; 5683 break; 5684 #if defined (BCM_FLOWTRACKER_SUPPORT) 5685 case bcmFieldStageIngressFlowtracker: 5686 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 5687 stage_qual = bcmFieldQualifyStageIngressFlowtracker; 5688 lt_select_cfg_reg = BROADSCAN_LOGICAL_TABLE_SELECT_CONFIGr; 5689 break; 5690 #endif 5691 default: 5692 return BCM_E_PARAM; 5693 } 5694 5695 5696 5697 /* Verifiy PBMP based on group mode and port config */ 5698 /* Get group mode */ 5699 if (soc_feature(unit, soc_feature_field_single_pipe_support)) { 5700 group_mode = bcmFieldGroupOperModeGlobal; 5701 } else { 5702 BCM_IF_ERROR_RETURN(bcm_esw_field_group_oper_mode_get(unit, 5703 stage_qual, &group_mode)); 5704 } 5705 5706 /* Read device port configuration. */ 5707 BCM_PBMP_CLEAR(all_pbmp); 5708 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 5709 5710 if (group_mode == bcmFieldGroupOperModeGlobal) { 5711 /* Pbmp should match all the valid ports */ 5712 if (!BCM_PBMP_EQ(all_pbmp, pbmp)) { 5713 return BCM_E_PARAM; 5714 } 5715 } else if (group_mode == bcmFieldGroupOperModePipeLocal) { 5716 /* Pbmp provided should be belong to only one pipe */ 5717 for (pipe_idx = 0; pipe_idx < BCM_PIPES_MAX ; pipe_idx++) { 5718 BCM_PBMP_CLEAR(pbmp_temp); 5719 BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PIPE(unit, pipe_idx)); 5720 SOC_PBMP_REMOVE(pbmp_temp, PBMP_LB(unit)); 5721 SOC_PBMP_REMOVE(pbmp_temp, PBMP_RDB_ALL(unit)); 5722 SOC_PBMP_REMOVE(pbmp_temp, PBMP_FAE_ALL(unit)); 5723 if (BCM_PBMP_EQ(pbmp_temp, pbmp)) { 5724 break; 5725 } 5726 } 5727 5728 /* Pbmp doesn't match any of the pipes */ 5729 if (pipe_idx == BCM_PIPES_MAX) { 5730 return BCM_E_PARAM; 5731 } 5732 5733 BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit, 5734 lt_select_cfg_reg, 5735 pipe_idx, 5736 <_select_cfg_reg)); 5737 } else { 5738 return BCM_E_INTERNAL; 5739 } 5740 5741 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc)); 5742 5743 /* Mode can't be changed unless no entry is configured for that stage */ 5744 if(mode != stage_fc->field_src_class_mode[pipe_idx]) { 5745 5746 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 5747 5748 /* Get the preselector information */ 5749 presel_info = fc->presel_info; 5750 if (presel_info == NULL) { 5751 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 5752 "ERROR: Field control for Presel Information returns NULL.\n\r"))); 5753 return BCM_E_INTERNAL; 5754 } 5755 5756 /* Loop through all the presel id to check if Mixed src class was configured 5757 * for any entry belonging to this stage */ 5758 for (presel_idx = 0 ; presel_idx < presel_info->presel_limit; presel_idx++) { 5759 if (BCM_FIELD_PRESEL_TEST(presel_info->presel_set, presel_idx)) { 5760 /* Find preselector descriptor */ 5761 BCM_IF_ERROR_RETURN 5762 (_bcm_field_presel_entry_get(unit, presel_idx, &f_presel)); 5763 5764 /* Preselecor attached to ingress or extact match stage 5765 * if MIXED SRC FLAG is set return error */ 5766 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, stage_qual) && 5767 BCM_PBMP_EQ(f_presel->mixed_src_class_pbmp, pbmp) && 5768 (f_presel->flags & _FP_ENTRY_MIXED_SRC_CLASS_QUALIFIED)) { 5769 return BCM_E_PARAM; 5770 } 5771 } 5772 } 5773 5774 stage_fc->field_src_class_mode[pipe_idx] = mode; 5775 /* Write to HW */ 5776 if ((lt_select_cfg_reg != INVALIDr) && 5777 SOC_REG_FIELD_VALID(unit, lt_select_cfg_reg, SOURCE_CLASS_MODEf)) { 5778 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, lt_select_cfg_reg, 5779 REG_PORT_ANY, 5780 SOURCE_CLASS_MODEf, 5781 mode)); 5782 } else { 5783 return BCM_E_INTERNAL; 5784 } 5785 } 5786 5787 return BCM_E_NONE; 5788 } 5789 5790 /* 5791 * Function: 5792 * _bcm_field_th_source_class_mode_get 5793 * Purpose: 5794 * Retrieve Field Processor Source Class operational mode 5795 * per-CAP stage. 5796 * Parameters: 5797 * unit - (IN) BCM Device number. 5798 * stage - (IN) Field Stage enum value. 5799 * pbmp - (IN) Device Port Bitmap value 5800 * mode - (OUT) Reference to Field Source Class Operational 5801 * Mode enum value. 5802 * Returns: 5803 * BCM_E_XXX 5804 * Notes: 5805 * Valid "stage" input parameter values supported by 5806 * this API are: 5807 * "bcmFieldStageIngress" 5808 * "bcmFieldStageIngressExactMatch" 5809 * "bcmFieldStageIngressFlowtracker" 5810 */ 5811 int 5812 _bcm_field_th_source_class_mode_get(int unit, 5813 bcm_field_stage_t stage, 5814 bcm_pbmp_t pbmp, 5815 bcm_field_src_class_mode_t *mode) 5816 { 5817 _field_stage_t *stage_fc; /* Stage field control structure. */ 5818 _field_stage_id_t stage_id; /* Pipeline stage id */ 5819 bcm_field_qualify_t stage_qual; 5820 bcm_field_group_oper_mode_t group_mode; 5821 uint8 pipe_idx = 0; 5822 bcm_pbmp_t pbmp_temp; 5823 bcm_pbmp_t all_pbmp; /* Group port bitmap. */ 5824 5825 /* Applicable for Ingress and ExtactMatch only */ 5826 if ((stage != bcmFieldStageIngress) && 5827 (stage != bcmFieldStageIngressExactMatch) && 5828 (stage != bcmFieldStageIngressFlowtracker)) { 5829 return (BCM_E_PARAM); 5830 } 5831 5832 if (stage == bcmFieldStageIngress) { 5833 stage_id = _BCM_FIELD_STAGE_INGRESS; 5834 stage_qual = bcmFieldQualifyStageIngress; 5835 } else if (stage == bcmFieldStageIngressExactMatch) { 5836 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 5837 stage_qual = bcmFieldQualifyStageIngressExactMatch; 5838 } else { /* bcmFieldStageIngressFlowtracker */ 5839 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 5840 stage_qual = bcmFieldQualifyStageIngressFlowtracker; 5841 } 5842 5843 /* Verifiy PBMP based on group mode and port config */ 5844 /* Get group mode */ 5845 if (soc_feature(unit, soc_feature_field_single_pipe_support)) { 5846 group_mode = bcmFieldGroupOperModeGlobal; 5847 } else { 5848 BCM_IF_ERROR_RETURN(bcm_esw_field_group_oper_mode_get(unit, 5849 stage_qual, &group_mode)); 5850 } 5851 5852 /* Read device port configuration. */ 5853 BCM_PBMP_CLEAR(all_pbmp); 5854 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 5855 5856 if (group_mode == bcmFieldGroupOperModeGlobal) { 5857 /* Pbmp should match all the valid ports */ 5858 if (!BCM_PBMP_EQ(all_pbmp, pbmp)) { 5859 return BCM_E_PARAM; 5860 } 5861 } else if (group_mode == bcmFieldGroupOperModePipeLocal) { 5862 /* Pbmp provided should be belong to only one pipe */ 5863 for (pipe_idx = 0; pipe_idx < BCM_PIPES_MAX ; pipe_idx++) { 5864 BCM_PBMP_CLEAR(pbmp_temp); 5865 BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PIPE(unit, pipe_idx)); 5866 SOC_PBMP_REMOVE(pbmp_temp, PBMP_LB(unit)); 5867 SOC_PBMP_REMOVE(pbmp_temp, PBMP_RDB_ALL(unit)); 5868 SOC_PBMP_REMOVE(pbmp_temp, PBMP_FAE_ALL(unit)); 5869 if (BCM_PBMP_EQ(pbmp_temp, pbmp)) { 5870 break; 5871 } 5872 } 5873 5874 /* Pbmp doesn't match any of the pipes */ 5875 if (pipe_idx == BCM_PIPES_MAX) { 5876 return BCM_E_PARAM; 5877 } 5878 } else { 5879 return BCM_E_INTERNAL; 5880 } 5881 5882 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc)); 5883 5884 *mode = stage_fc->field_src_class_mode[pipe_idx]; 5885 5886 return BCM_E_NONE; 5887 } 5888 5889 /* 5890 * Function: 5891 * _bcm_field_th_qualify_MixedSrcClassId 5892 * Purpose: 5893 * Add a Mixed Source Class Id field qualification to a field entry. 5894 * Parameters: 5895 * unit - (IN) Unit number. 5896 * entry - (IN) Field Entry id. 5897 * pbmp - (IN) Device Port Bitmap value 5898 * data - (IN) Mixed Source Class Id. 5899 * mask - (IN) Mixed Source Class Id mask. 5900 * Returns: 5901 * BCM_E_XXX 5902 * Notes: 5903 */ 5904 int 5905 _bcm_field_th_qualify_MixedSrcClassId(int unit, 5906 bcm_field_entry_t entry, 5907 bcm_pbmp_t pbmp, 5908 bcm_field_src_class_t data, 5909 bcm_field_src_class_t mask) 5910 { 5911 bcm_field_presel_t presel; /* Presel id. */ 5912 _field_presel_entry_t *f_presel = NULL; /* Presel Entry descriptor. */ 5913 _field_stage_id_t stage_id; 5914 _field_stage_t *stage_fc; 5915 uint32 hw_data; /* HW data match criteria. */ 5916 uint32 hw_mask; /* HW data mask. */ 5917 int rv = BCM_E_UNAVAIL; /* Operation return status. */ 5918 bcm_field_qualify_t stage_qual; 5919 bcm_field_group_oper_mode_t group_mode; 5920 uint8 pipe_idx = 0; 5921 bcm_pbmp_t pbmp_temp; 5922 bcm_pbmp_t all_pbmp; /* Group port bitmap. */ 5923 5924 if (!(soc_feature(unit, soc_feature_field_preselector_support) && 5925 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE))) { 5926 return (BCM_E_PARAM); 5927 } 5928 5929 BCM_IF_ERROR_RETURN(_bcm_field_entry_presel_resolve(unit, 5930 entry, &presel, &f_presel)); 5931 5932 /* Mixed source class is applicable only 5933 * for Ingress, extact match and flowtracker stages */ 5934 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 5935 bcmFieldQualifyStageIngress)) { 5936 stage_id = _BCM_FIELD_STAGE_INGRESS; 5937 stage_qual = bcmFieldQualifyStageIngress; 5938 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 5939 bcmFieldQualifyStageIngressExactMatch)) { 5940 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 5941 stage_qual = bcmFieldQualifyStageIngressExactMatch; 5942 #if defined(BCM_FLOWTRACKER_SUPPORT) 5943 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 5944 bcmFieldQualifyStageIngressFlowtracker)) { 5945 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 5946 stage_qual = bcmFieldQualifyStageIngressFlowtracker; 5947 #endif 5948 } else { 5949 return (BCM_E_PARAM); 5950 } 5951 5952 /* Verifiy PBMP based on group mode and port config */ 5953 /* Get group mode */ 5954 if (soc_feature(unit, soc_feature_field_single_pipe_support)) { 5955 group_mode = bcmFieldGroupOperModeGlobal; 5956 } else { 5957 BCM_IF_ERROR_RETURN(bcm_esw_field_group_oper_mode_get(unit, 5958 stage_qual, &group_mode)); 5959 } 5960 5961 /* Read device port configuration. */ 5962 BCM_PBMP_CLEAR(all_pbmp); 5963 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 5964 5965 if (group_mode == bcmFieldGroupOperModeGlobal) { 5966 /* Pbmp should match all the valid ports */ 5967 if (!BCM_PBMP_EQ(all_pbmp, pbmp)) { 5968 return BCM_E_PARAM; 5969 } 5970 } else if (group_mode == bcmFieldGroupOperModePipeLocal) { 5971 /* Pbmp provided should be belong to only one pipe */ 5972 for (pipe_idx = 0; pipe_idx < BCM_PIPES_MAX ; pipe_idx++) { 5973 BCM_PBMP_CLEAR(pbmp_temp); 5974 BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PIPE(unit, pipe_idx)); 5975 5976 SOC_PBMP_REMOVE(pbmp_temp, PBMP_LB(unit)); 5977 SOC_PBMP_REMOVE(pbmp_temp, PBMP_RDB_ALL(unit)); 5978 SOC_PBMP_REMOVE(pbmp_temp, PBMP_FAE_ALL(unit)); 5979 if (BCM_PBMP_EQ(pbmp_temp, pbmp)) { 5980 break; 5981 } 5982 } 5983 5984 /* Pbmp doesn't match any of the pipes */ 5985 if (pipe_idx == BCM_PIPES_MAX) { 5986 return BCM_E_PARAM; 5987 } 5988 } else { 5989 return BCM_E_INTERNAL; 5990 } 5991 5992 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc)); 5993 switch (stage_fc->field_src_class_mode[pipe_idx]) { 5994 case bcmFieldSrcClassModeDefault: 5995 if (soc_feature(unit, soc_feature_th3_style_fp)) { 5996 hw_data = (uint32)((uint32)((data.intf_class_l2 & 0xF) << 28)) 5997 | ((data.src_class_field & 0x3) << 26) 5998 | ((data.dst_class_field & 0x3FF) << 16) 5999 | ((data.udf_class & 0xFF) << 8) 6000 | (data.intf_class_port & 0xFF); 6001 6002 hw_mask = (uint32)((uint32)((mask.intf_class_l2 & 0xF) << 28)) 6003 | ((mask.src_class_field & 0x3) << 26) 6004 | ((mask.dst_class_field & 0x3FF) << 16) 6005 | ((mask.udf_class & 0xFF) << 8) 6006 | (mask.intf_class_port & 0xFF); 6007 } else { 6008 hw_data = (uint32)((uint32)( 6009 (data.src_class_field & 0x3) << 30)) 6010 | ((data.dst_class_field & 0x3FF) << 20) 6011 | ((data.udf_class & 0xFF) << 12) 6012 | ((data.intf_class_port & 0xFF) << 4) 6013 | (data.intf_class_l2 & 0xF); 6014 6015 hw_mask = (uint32)((uint32)( 6016 (mask.src_class_field & 0x3) << 30 )) 6017 | ((mask.dst_class_field & 0x3FF) << 20) 6018 | ((mask.udf_class & 0xFF) << 12) 6019 | ((mask.intf_class_port & 0xFF) << 4) 6020 | (mask.intf_class_l2 & 0xF); 6021 } 6022 break; 6023 case bcmFieldSrcClassModeSDN: 6024 if (soc_feature(unit, soc_feature_th3_style_fp)) { 6025 hw_data = (uint32)((uint32)((data.intf_class_l2 & 0xF) << 28)) 6026 | ((data.src_class_field & 0x3) << 26) 6027 | ((data.dst_class_field & 0x3FF) << 16) 6028 | ((data.udf_class & 0xF) << 12) 6029 | ((data.intf_class_port & 0xF) << 4) 6030 | (data.intf_class_l3 & 0xF); 6031 6032 hw_mask = (uint32)((uint32)((mask.intf_class_l2 & 0xF) << 28)) 6033 | ((mask.src_class_field & 0x3) << 26) 6034 | ((mask.dst_class_field & 0x3FF) << 16) 6035 | ((mask.udf_class & 0xF) << 12) 6036 | ((mask.intf_class_port & 0xF) << 4) 6037 | (mask.intf_class_l3 & 0xF); 6038 } else { 6039 hw_data = (uint32)((uint32)( 6040 (data.src_class_field & 0x3) << 30)) 6041 | ((data.dst_class_field & 0x3FF) << 20) 6042 | ((data.udf_class & 0xF) << 16) 6043 | ((data.intf_class_port & 0xF) << 12) 6044 | ((data.intf_class_l2 & 0xF) << 8) 6045 | ((data.intf_class_vport & 0xF) << 4) 6046 | (data.intf_class_l3 & 0xF); 6047 6048 hw_mask = (uint32)((uint32)( 6049 (mask.src_class_field & 0x3) << 30)) 6050 | ((mask.dst_class_field & 0x3FF) << 20) 6051 | ((mask.udf_class & 0xF) << 16) 6052 | ((mask.intf_class_port & 0xF) << 12) 6053 | ((mask.intf_class_l2 & 0xF) << 8) 6054 | ((mask.intf_class_vport & 0xF) << 4) 6055 | (mask.intf_class_l3 & 0xF); 6056 } 6057 break; 6058 case bcmFieldSrcClassModeBalanced: 6059 if (soc_feature(unit, soc_feature_th3_style_fp)) { 6060 hw_data = (uint32)((uint32)((data.intf_class_l2 & 0xF) << 28)) 6061 | ((data.dst_class_field & 0xFF) << 20) 6062 | ((data.udf_class & 0xF) << 16) 6063 | ((data.intf_class_port & 0xFF) << 4) 6064 | (data.intf_class_l3 & 0xF); 6065 hw_mask = (uint32)((uint32)((mask.intf_class_l2 & 0xF) << 28)) 6066 | ((mask.dst_class_field & 0xFF) << 20) 6067 | ((mask.udf_class & 0xF) << 16) 6068 | ((mask.intf_class_port & 0xFF) << 4) 6069 | (mask.intf_class_l3 & 0xF); 6070 } else { 6071 hw_data = (uint32)((uint32)( 6072 (data.dst_class_field & 0xFF) << 24)) 6073 | ((data.udf_class & 0xF) << 20) 6074 | ((data.intf_class_port & 0xFF) << 12) 6075 | ((data.intf_class_l2 & 0xF) << 8) 6076 | ((data.intf_class_vport & 0xF) << 4) 6077 | (data.intf_class_l3 & 0xF); 6078 6079 hw_mask = (uint32)((uint32)( 6080 (mask.dst_class_field & 0xFF) << 24)) 6081 | ((mask.udf_class & 0xF) << 20) 6082 | ((mask.intf_class_port & 0xFF) << 12) 6083 | ((mask.intf_class_l2 & 0xF) << 8) 6084 | ((mask.intf_class_vport & 0xF) << 4) 6085 | (mask.intf_class_l3 & 0xF); 6086 } 6087 break; 6088 case bcmFieldSrcClassModeOverlayNetworks: 6089 if (soc_feature(unit, soc_feature_th3_style_fp)) { 6090 hw_data = (uint32)((uint32)((data.intf_class_l2 & 0xFF) << 24)) 6091 | ((data.dst_class_field & 0xF) << 20) 6092 | ((data.intf_class_port & 0xF) << 8) 6093 | (data.intf_class_l3 & 0xFF); 6094 6095 hw_mask = (uint32)((uint32)((mask.intf_class_l2 & 0xFF) << 24)) 6096 | ((mask.dst_class_field & 0xF) << 20) 6097 | ((mask.intf_class_port & 0xF) << 8) 6098 | (mask.intf_class_l3 & 0xFF); 6099 } else { 6100 hw_data = (uint32)((uint32)( 6101 (data.dst_class_field & 0xF) << 28)) 6102 | ((data.intf_class_port & 0xF) << 24) 6103 | ((data.intf_class_l2 & 0xFF) << 16) 6104 | ((data.intf_class_vport & 0xFF) << 8) 6105 | (data.intf_class_l3 & 0xFF); 6106 6107 hw_mask = (uint32)((uint32)( 6108 (mask.dst_class_field & 0xF) << 28)) 6109 | ((mask.intf_class_port & 0xF) << 24) 6110 | ((mask.intf_class_l2 & 0xFF) << 16) 6111 | ((mask.intf_class_vport & 0xFF) << 8) 6112 | (mask.intf_class_l3 & 0xFF); 6113 } 6114 break; 6115 default: 6116 return (BCM_E_PARAM); 6117 break; 6118 } 6119 rv = _field_qualify32(unit, entry, bcmFieldQualifyMixedSrcClassId, 6120 hw_data, hw_mask); 6121 if (BCM_SUCCESS(rv)) { 6122 f_presel->flags |= _FP_ENTRY_MIXED_SRC_CLASS_QUALIFIED; 6123 BCM_PBMP_ASSIGN(f_presel->mixed_src_class_pbmp, pbmp); 6124 } 6125 6126 return (rv); 6127 } 6128 6129 /* 6130 * Function: 6131 * _bcm_field_th_qualify_MixedSrcClassId_get 6132 * Purpose: 6133 * Get match criteria for bcmFieildQualifyMixedSrcClassId 6134 * qualifier from the field entry. 6135 * Parameters: 6136 * unit - (IN) Unit number. 6137 * entry - (IN) Field Entry id. 6138 * pbmp - (IN) Device Port Bitmap value 6139 * data - (OUT) Mixed Source Class Id. 6140 * mask - (OUT) Mixed Source Class Id mask. 6141 * Returns: 6142 * BCM_E_XXX 6143 * Notes: 6144 */ 6145 int 6146 _bcm_field_th_qualify_MixedSrcClassId_get(int unit, 6147 bcm_field_entry_t entry, 6148 bcm_pbmp_t pbmp, 6149 uint32 hw_data, 6150 uint32 hw_mask, 6151 bcm_field_src_class_t *data, 6152 bcm_field_src_class_t *mask) 6153 { 6154 bcm_field_presel_t presel; /* Presel id. */ 6155 _field_presel_entry_t *f_presel = NULL; /* Presel Entry descriptor. */ 6156 _field_stage_id_t stage_id; 6157 _field_stage_t *stage_fc; 6158 bcm_field_qualify_t stage_qual; 6159 bcm_field_group_oper_mode_t group_mode; 6160 uint8 pipe_idx = 0; 6161 bcm_pbmp_t pbmp_temp; 6162 bcm_pbmp_t all_pbmp; /* Group port bitmap. */ 6163 6164 if ((data == NULL) || (mask == NULL)) { 6165 return BCM_E_PARAM; 6166 } 6167 6168 if (!(soc_feature(unit, soc_feature_field_preselector_support) && 6169 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE))) { 6170 return (BCM_E_PARAM); 6171 } 6172 6173 BCM_IF_ERROR_RETURN(_bcm_field_entry_presel_resolve(unit, 6174 entry, &presel, &f_presel)); 6175 6176 /* Mixed source class is applicable only 6177 * for Ingress, extact match and flowtracker stages */ 6178 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 6179 bcmFieldQualifyStageIngress)) { 6180 stage_id = _BCM_FIELD_STAGE_INGRESS; 6181 stage_qual = bcmFieldQualifyStageIngress; 6182 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 6183 bcmFieldQualifyStageIngressExactMatch)) { 6184 stage_id = _BCM_FIELD_STAGE_EXACTMATCH; 6185 stage_qual = bcmFieldQualifyStageIngressExactMatch; 6186 #if defined(BCM_FLOWTRACKER_SUPPORT) 6187 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, 6188 bcmFieldQualifyStageIngressFlowtracker)) { 6189 stage_id = _BCM_FIELD_STAGE_FLOWTRACKER; 6190 stage_qual = bcmFieldQualifyStageIngressFlowtracker; 6191 #endif 6192 } else { 6193 return (BCM_E_PARAM); 6194 } 6195 6196 /* Verifiy PBMP based on group mode and port config */ 6197 /* Get group mode */ 6198 if (soc_feature(unit, soc_feature_field_single_pipe_support)) { 6199 group_mode = bcmFieldGroupOperModeGlobal; 6200 } else { 6201 BCM_IF_ERROR_RETURN(bcm_esw_field_group_oper_mode_get(unit, 6202 stage_qual, &group_mode)); 6203 } 6204 6205 /* Read device port configuration. */ 6206 BCM_PBMP_CLEAR(all_pbmp); 6207 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 6208 6209 if (group_mode == bcmFieldGroupOperModeGlobal) { 6210 /* Pbmp should match all the valid ports */ 6211 if (!BCM_PBMP_EQ(all_pbmp, pbmp)) { 6212 return BCM_E_PARAM; 6213 } 6214 } else if (group_mode == bcmFieldGroupOperModePipeLocal) { 6215 /* Pbmp provided should be belong to only one pipe */ 6216 for (pipe_idx = 0; pipe_idx < BCM_PIPES_MAX ; pipe_idx++) { 6217 BCM_PBMP_CLEAR(pbmp_temp); 6218 BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PIPE(unit, pipe_idx)); 6219 SOC_PBMP_REMOVE(pbmp_temp, PBMP_LB(unit)); 6220 SOC_PBMP_REMOVE(pbmp_temp, PBMP_RDB_ALL(unit)); 6221 SOC_PBMP_REMOVE(pbmp_temp, PBMP_FAE_ALL(unit)); 6222 if (BCM_PBMP_EQ(pbmp_temp, pbmp)) { 6223 break; 6224 } 6225 } 6226 6227 /* Pbmp doesn't match any of the pipes */ 6228 if (pipe_idx == BCM_PIPES_MAX) { 6229 return BCM_E_PARAM; 6230 } 6231 } else { 6232 return BCM_E_INTERNAL; 6233 } 6234 6235 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc)); 6236 6237 sal_memset(data, 0, sizeof(bcm_field_src_class_t)); 6238 sal_memset(mask, 0, sizeof(bcm_field_src_class_t)); 6239 6240 switch (stage_fc->field_src_class_mode[pipe_idx]) { 6241 case bcmFieldSrcClassModeDefault: 6242 if (soc_feature(unit, soc_feature_th3_style_fp)) { 6243 data->intf_class_l2 = (hw_data >> 28) & 0xF; 6244 data->src_class_field = (hw_data >> 26) & 0x3; 6245 data->dst_class_field = (hw_data >> 16) & 0x3FF; 6246 data->udf_class = (hw_data >> 8) & 0xFF; 6247 data->intf_class_port = hw_data & 0xFF; 6248 6249 mask->intf_class_l2 = (hw_mask >> 28) & 0xF; 6250 mask->src_class_field = (hw_mask >> 26) & 0x3; 6251 mask->dst_class_field = (hw_mask >> 16) & 0x3FF; 6252 mask->udf_class = (hw_mask >> 8) & 0xFF; 6253 mask->intf_class_port = hw_mask & 0xFF; 6254 } else { 6255 data->src_class_field = (hw_data >> 30) & 0x3; 6256 data->dst_class_field = (hw_data >> 20) & 0x3FF; 6257 data->udf_class = (hw_data >> 12) & 0xFF; 6258 data->intf_class_port = (hw_data >> 4) & 0xFF; 6259 data->intf_class_l2 = hw_data & 0xF; 6260 6261 mask->src_class_field = (hw_mask >> 30) & 0x3; 6262 mask->dst_class_field = (hw_mask >> 20) & 0x3FF; 6263 mask->udf_class = (hw_mask >> 12) & 0xFF; 6264 mask->intf_class_port = (hw_mask >> 4) & 0xFF; 6265 mask->intf_class_l2 = hw_mask & 0xF; 6266 } 6267 break; 6268 case bcmFieldSrcClassModeSDN: 6269 if (soc_feature(unit, soc_feature_th3_style_fp)) { 6270 data->intf_class_l2 = (hw_data >> 28) & 0xF; 6271 data->src_class_field = (hw_data >> 26) & 0x3; 6272 data->dst_class_field = (hw_data >> 16) & 0x3FF; 6273 data->udf_class = (hw_data >> 12) & 0xF; 6274 data->intf_class_port = (hw_data >> 4) & 0xF; 6275 data->intf_class_l3 = hw_data & 0xF; 6276 6277 mask->intf_class_l2 = (hw_mask >> 28) & 0xF; 6278 mask->src_class_field = (hw_mask >> 26) & 0x3; 6279 mask->dst_class_field = (hw_mask >> 16) & 0x3FF; 6280 mask->udf_class = (hw_mask >> 12) & 0xF; 6281 mask->intf_class_port = (hw_mask >> 4) & 0xF; 6282 mask->intf_class_l3 = hw_mask & 0xF; 6283 } else { 6284 data->src_class_field = (hw_data >> 30) & 0x3; 6285 data->dst_class_field = (hw_data >> 20) & 0x3FF; 6286 data->udf_class = (hw_data >> 16) & 0xF; 6287 data->intf_class_port = (hw_data >> 12) & 0xF; 6288 data->intf_class_l2 = (hw_data >> 8) & 0xF; 6289 data->intf_class_vport = (hw_data >> 4) & 0xF; 6290 data->intf_class_l3 = hw_data & 0xF; 6291 6292 mask->src_class_field = (hw_mask >> 30) & 0x3; 6293 mask->dst_class_field = (hw_mask >> 20) & 0x3FF; 6294 mask->udf_class = (hw_mask >> 16) & 0xF; 6295 mask->intf_class_port = (hw_mask >> 12) & 0xF; 6296 mask->intf_class_l2 = (hw_mask >> 8) & 0xF; 6297 mask->intf_class_vport = (hw_mask >> 4) & 0xF; 6298 mask->intf_class_l3 = hw_mask & 0xF; 6299 } 6300 break; 6301 case bcmFieldSrcClassModeBalanced: 6302 if (soc_feature(unit, soc_feature_th3_style_fp)) { 6303 data->intf_class_l2 = (hw_data >> 28) & 0xF; 6304 data->dst_class_field = (hw_data >> 20) & 0xFF; 6305 data->udf_class = (hw_data >> 16) & 0xF; 6306 data->intf_class_port = (hw_data >> 4) & 0xFF; 6307 data->intf_class_l3 = hw_data & 0xF; 6308 6309 mask->intf_class_l2 = (hw_mask >> 28) & 0xF; 6310 mask->dst_class_field = (hw_mask >> 20) & 0xFF; 6311 mask->udf_class = (hw_mask >> 16) & 0xF; 6312 mask->intf_class_port = (hw_mask >> 4) & 0xFF; 6313 mask->intf_class_l3 = hw_mask & 0xF; 6314 } else { 6315 data->dst_class_field = (hw_data >> 24) & 0xFF; 6316 data->udf_class = (hw_data >> 20) & 0xF; 6317 data->intf_class_port = (hw_data >> 12) & 0xFF; 6318 data->intf_class_l2 = (hw_data >> 8) & 0xF; 6319 data->intf_class_vport = (hw_data >> 4) & 0xF; 6320 data->intf_class_l3 = hw_data & 0xF; 6321 6322 mask->dst_class_field = (hw_mask >> 24) & 0xFF; 6323 mask->udf_class = (hw_mask >> 20) & 0xF; 6324 mask->intf_class_port = (hw_mask >> 12) & 0xFF; 6325 mask->intf_class_l2 = (hw_mask >> 8) & 0xF; 6326 mask->intf_class_vport = (hw_mask >> 4) & 0xF; 6327 mask->intf_class_l3 = hw_mask & 0xF; 6328 } 6329 break; 6330 case bcmFieldSrcClassModeOverlayNetworks: 6331 if (soc_feature(unit, soc_feature_th3_style_fp)) { 6332 data->intf_class_l2 = (hw_data >> 24) & 0xFF; 6333 data->dst_class_field = (hw_data >> 20) & 0xF; 6334 data->intf_class_port = (hw_data >> 8) & 0xF; 6335 data->intf_class_l3 = hw_data & 0xFF; 6336 6337 mask->intf_class_l2 = (hw_mask >> 24) & 0xFF; 6338 mask->dst_class_field = (hw_mask >> 20) & 0xF; 6339 mask->intf_class_port = (hw_mask >> 8) & 0xF; 6340 mask->intf_class_l3 = hw_mask & 0xFF; 6341 } else { 6342 data->dst_class_field = (hw_data >> 28) & 0xF; 6343 data->intf_class_port = (hw_data >> 24) & 0xF; 6344 data->intf_class_l2 = (hw_data >> 16) & 0xFF; 6345 data->intf_class_vport = (hw_data >> 8) & 0xFF; 6346 data->intf_class_l3 = hw_data & 0xFF; 6347 6348 mask->dst_class_field = (hw_mask >> 28) & 0xF; 6349 mask->intf_class_port = (hw_mask >> 24) & 0xF; 6350 mask->intf_class_l2 = (hw_mask >> 16) & 0xFF; 6351 mask->intf_class_vport = (hw_mask >> 8) & 0xFF; 6352 mask->intf_class_l3 = hw_mask & 0xFF; 6353 } 6354 break; 6355 default: 6356 return (BCM_E_PARAM); 6357 } 6358 return (BCM_E_NONE); 6359 } 6360 6361 /* 6362 * Function: _bcm_field_th_qualifier_MixedSrcClassId_delete 6363 * 6364 * Purpose: Resets data related to MixedSrxClassId 6365 * 6366 * Parameters: 6367 * unit - (IN) BCM device number 6368 * entry - (IN) Field presel entry to operate on. 6369 * 6370 * Returns: 6371 * BCM_E_XX 6372 */ 6373 int 6374 _bcm_field_th_qualifier_MixedSrcClassId_delete(int unit, bcm_field_entry_t entry) 6375 { 6376 int rv; /* Operation return status. */ 6377 _field_presel_entry_t *f_presel; /* Presel entry structure. */ 6378 bcm_field_presel_t presel; /* Field Preselector ID. */ 6379 6380 /* Preselector feature check */ 6381 if (!soc_feature(unit, soc_feature_field_preselector_support)) { 6382 return BCM_E_UNAVAIL; 6383 } 6384 6385 /* Resolve the Preselector ID from the given Entry ID */ 6386 rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel); 6387 if (BCM_FAILURE(rv)) { 6388 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, 6389 "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry)); 6390 return rv; 6391 } 6392 6393 f_presel->flags &= ~(_FP_ENTRY_MIXED_SRC_CLASS_QUALIFIED); 6394 BCM_PBMP_CLEAR(f_presel->mixed_src_class_pbmp); 6395 6396 return BCM_E_NONE; 6397 } 6398 6399 int 6400 _bcm_field_max_lt_part_prio_get(int unit) 6401 { 6402 if (SOC_IS_HELIX5(unit)) { 6403 return 18; 6404 } else { 6405 return 15; 6406 } 6407 } 6408 6409 int 6410 _bcm_field_th_max_lt_parts_get(int unit) 6411 { 6412 #ifdef BCM_TOMAHAWK3_SUPPORT 6413 if (SOC_IS_TOMAHAWK3(unit)) { 6414 return 9; 6415 } else 6416 #endif 6417 { 6418 if (soc_feature(unit, soc_feature_field_slices18)) { 6419 return 18; 6420 } else { 6421 return 12; 6422 } 6423 } 6424 } 6425 6426 #endif /* (BCM_TOMAHAWK_SUPPORT) && (BCM_FIELD_SUPPORT) */