field.c (582443B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * File: field.c 7 * Purpose: BCM56504 Field Processor installation functions. 8 */ 9 #include <shared/bsl.h> 10 11 #include <soc/drv.h> 12 #include <soc/scache.h> 13 14 #include <bcm/error.h> 15 16 #include <bcm/field.h> 17 #include <bcm/mirror.h> 18 19 #include <bcm_int/esw_dispatch.h> 20 #if defined(BCM_FIREBOLT_SUPPORT) 21 #include <bcm_int/esw/firebolt.h> 22 #endif 23 #if defined(BCM_TRIUMPH_SUPPORT) 24 #include <bcm_int/esw/triumph.h> 25 #endif 26 #if defined(BCM_TRX_SUPPORT) 27 #include <bcm_int/esw/trx.h> 28 #endif 29 #if defined(BCM_HURRICANE2_SUPPORT) 30 #include <bcm_int/esw/hurricane2.h> 31 #endif 32 #include <bcm_int/esw/field.h> 33 #include <bcm_int/esw/mirror.h> 34 #if defined(BCM_KATANA_SUPPORT) 35 #include <bcm_int/esw/katana.h> 36 #endif 37 #if defined(BCM_KATANA2_SUPPORT) 38 #include <bcm_int/esw/katana2.h> 39 #endif 40 #if defined(BCM_TOMAHAWK_SUPPORT) 41 #include <bcm_int/esw/tomahawk.h> 42 #endif 43 #if defined(BCM_TRIDENT3_SUPPORT) 44 #include <bcm_int/esw/trident3.h> 45 #endif 46 47 #if defined(BCM_FIREBOLT_SUPPORT) && defined(BCM_FIELD_SUPPORT) 48 49 /* local/static function prototypes */ 50 STATIC void _field_fb_functions_init(int unit, _field_funct_t *functions); 51 STATIC int _field_fb_detach(int unit, _field_control_t *fc); 52 STATIC int _field_fb_hw_clear(int unit, _field_stage_t *stage_fc); 53 54 STATIC int _field_fb_tcam_policy_install(int unit, _field_entry_t *f_ent, 55 int tcam_idx); 56 STATIC int _field_fb_tcam_policy_reinstall(int unit, _field_entry_t *f_ent, 57 int tcam_idx); 58 STATIC int _field_fb_tcam_get(int unit, _field_entry_t *f_ent, 59 soc_mem_t mem, uint32 *buf); 60 STATIC int _field_fb_action_get(int unit, soc_mem_t mem, 61 _field_entry_t *f_ent, int tcam_idx, 62 _field_action_t *fa, uint32 *buf); 63 64 #ifdef BROADCOM_DEBUG 65 STATIC char *_field_fb_action_name(bcm_field_action_t action); 66 #endif /* BROADCOM_DEBUG */ 67 68 static soc_field_t _fb_ing_f4_reg[16] = { 69 SLICE_0_F4f, SLICE_1_F4f, 70 SLICE_2_F4f, SLICE_3_F4f, 71 SLICE_4_F4f, SLICE_5_F4f, 72 SLICE_6_F4f, SLICE_7_F4f, 73 SLICE_8_F4f, SLICE_9_F4f, 74 SLICE_10_F4f, SLICE_11_F4f, 75 SLICE_12_F4f, SLICE_13_F4f, 76 SLICE_14_F4f, SLICE_15_F4f}; 77 78 #if defined(BCM_FIREBOLT2_SUPPORT) 79 static soc_field_t _fb2_ifp_double_wide_key[16] = { 80 SLICE0_DOUBLE_WIDE_KEY_SELECTf, 81 SLICE1_DOUBLE_WIDE_KEY_SELECTf, 82 SLICE2_DOUBLE_WIDE_KEY_SELECTf, 83 SLICE3_DOUBLE_WIDE_KEY_SELECTf, 84 SLICE4_DOUBLE_WIDE_KEY_SELECTf, 85 SLICE5_DOUBLE_WIDE_KEY_SELECTf, 86 SLICE6_DOUBLE_WIDE_KEY_SELECTf, 87 SLICE7_DOUBLE_WIDE_KEY_SELECTf, 88 SLICE8_DOUBLE_WIDE_KEY_SELECTf, 89 SLICE9_DOUBLE_WIDE_KEY_SELECTf, 90 SLICE10_DOUBLE_WIDE_KEY_SELECTf, 91 SLICE11_DOUBLE_WIDE_KEY_SELECTf, 92 SLICE12_DOUBLE_WIDE_KEY_SELECTf, 93 SLICE13_DOUBLE_WIDE_KEY_SELECTf, 94 SLICE14_DOUBLE_WIDE_KEY_SELECTf, 95 SLICE15_DOUBLE_WIDE_KEY_SELECTf}; 96 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 97 98 static soc_field_t _fb_field_tbl[16][3] = { 99 {SLICE0_F1f, SLICE0_F2f, SLICE0_F3f}, 100 {SLICE1_F1f, SLICE1_F2f, SLICE1_F3f}, 101 {SLICE2_F1f, SLICE2_F2f, SLICE2_F3f}, 102 {SLICE3_F1f, SLICE3_F2f, SLICE3_F3f}, 103 {SLICE4_F1f, SLICE4_F2f, SLICE4_F3f}, 104 {SLICE5_F1f, SLICE5_F2f, SLICE5_F3f}, 105 {SLICE6_F1f, SLICE6_F2f, SLICE6_F3f}, 106 {SLICE7_F1f, SLICE7_F2f, SLICE7_F3f}, 107 {SLICE8_F1f, SLICE8_F2f, SLICE8_F3f}, 108 {SLICE9_F1f, SLICE9_F2f, SLICE9_F3f}, 109 {SLICE10_F1f, SLICE10_F2f, SLICE10_F3f}, 110 {SLICE11_F1f, SLICE11_F2f, SLICE11_F3f}, 111 {SLICE12_F1f, SLICE12_F2f, SLICE12_F3f}, 112 {SLICE13_F1f, SLICE13_F2f, SLICE13_F3f}, 113 {SLICE14_F1f, SLICE14_F2f, SLICE14_F3f}, 114 {SLICE15_F1f, SLICE15_F2f, SLICE15_F3f}}; 115 static soc_field_t _fb_ing_slice_mode_field[16] = { 116 SLICE_0_MODEf, SLICE_1_MODEf, 117 SLICE_2_MODEf, SLICE_3_MODEf, 118 SLICE_4_MODEf, SLICE_5_MODEf, 119 SLICE_6_MODEf, SLICE_7_MODEf, 120 SLICE_8_MODEf, SLICE_9_MODEf, 121 SLICE_10_MODEf, SLICE_11_MODEf, 122 SLICE_12_MODEf, SLICE_13_MODEf, 123 SLICE_14_MODEf, SLICE_15_MODEf}; 124 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 125 static soc_field_t _vfp_slice_wide_mode_field[4] = { 126 SLICE_0_DOUBLE_WIDE_MODEf, 127 SLICE_1_DOUBLE_WIDE_MODEf, 128 SLICE_2_DOUBLE_WIDE_MODEf, 129 SLICE_3_DOUBLE_WIDE_MODEf}; 130 static soc_field_t _vfp_slice_pairing_field[2] = { 131 SLICE1_0_PAIRINGf, SLICE3_2_PAIRINGf}; 132 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 133 #if defined (BCM_FIREBOLT2_SUPPORT) 134 static soc_field_t _fb2_slice_pairing_field[8] = { 135 SLICE1_0_PAIRINGf, SLICE3_2_PAIRINGf, 136 SLICE5_4_PAIRINGf, SLICE7_6_PAIRINGf, 137 SLICE9_8_PAIRINGf, SLICE11_10_PAIRINGf, 138 SLICE13_12_PAIRINGf, SLICE15_14_PAIRINGf}; 139 static soc_field_t _fb2_slice_wide_mode_field[16] = { 140 SLICE0_DOUBLE_WIDE_MODEf, 141 SLICE1_DOUBLE_WIDE_MODEf, 142 SLICE2_DOUBLE_WIDE_MODEf, 143 SLICE3_DOUBLE_WIDE_MODEf, 144 SLICE4_DOUBLE_WIDE_MODEf, 145 SLICE5_DOUBLE_WIDE_MODEf, 146 SLICE6_DOUBLE_WIDE_MODEf, 147 SLICE7_DOUBLE_WIDE_MODEf, 148 SLICE8_DOUBLE_WIDE_MODEf, 149 SLICE9_DOUBLE_WIDE_MODEf, 150 SLICE10_DOUBLE_WIDE_MODEf, 151 SLICE11_DOUBLE_WIDE_MODEf, 152 SLICE12_DOUBLE_WIDE_MODEf, 153 SLICE13_DOUBLE_WIDE_MODEf, 154 SLICE14_DOUBLE_WIDE_MODEf, 155 SLICE15_DOUBLE_WIDE_MODEf}; 156 static soc_field_t _efp_slice_mode[] = { 157 SLICE_0_MODEf, SLICE_1_MODEf, 158 SLICE_2_MODEf, SLICE_3_MODEf}; 159 static soc_field_t _vfp_field_tbl[4][2] = { 160 {SLICE_0_F2f, SLICE_0_F3f}, 161 {SLICE_1_F2f, SLICE_1_F3f}, 162 {SLICE_2_F2f, SLICE_2_F3f}, 163 {SLICE_3_F2f, SLICE_3_F3f}}; 164 #endif /* BCM_FIREBOLT2_SUPPORT */ 165 166 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) \ 167 || defined(BCM_TRX_SUPPORT) && defined(BCM_WARM_BOOT_SUPPORT) 168 static uint32 virtual_to_physical_map[] = { 169 VIRTUAL_SLICE_0_PHYSICAL_SLICE_NUMBERf, 170 VIRTUAL_SLICE_1_PHYSICAL_SLICE_NUMBERf, 171 VIRTUAL_SLICE_2_PHYSICAL_SLICE_NUMBERf, 172 VIRTUAL_SLICE_3_PHYSICAL_SLICE_NUMBERf, 173 VIRTUAL_SLICE_4_PHYSICAL_SLICE_NUMBERf, 174 VIRTUAL_SLICE_5_PHYSICAL_SLICE_NUMBERf, 175 VIRTUAL_SLICE_6_PHYSICAL_SLICE_NUMBERf, 176 VIRTUAL_SLICE_7_PHYSICAL_SLICE_NUMBERf 177 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) \ 178 || defined(BCM_TRX_SUPPORT) && defined(BCM_WARM_BOOT_SUPPORT) 179 , 180 VIRTUAL_SLICE_8_PHYSICAL_SLICE_NUMBERf, 181 VIRTUAL_SLICE_9_PHYSICAL_SLICE_NUMBERf, 182 VIRTUAL_SLICE_10_PHYSICAL_SLICE_NUMBERf, 183 VIRTUAL_SLICE_11_PHYSICAL_SLICE_NUMBERf, 184 VIRTUAL_SLICE_12_PHYSICAL_SLICE_NUMBERf, 185 VIRTUAL_SLICE_13_PHYSICAL_SLICE_NUMBERf, 186 VIRTUAL_SLICE_14_PHYSICAL_SLICE_NUMBERf, 187 VIRTUAL_SLICE_15_PHYSICAL_SLICE_NUMBERf 188 #endif /* BCM_RAVEN_SUPPORT || BCM_FIREBOLT2_SUPPORT 189 || BCM_TRX_SUPPORT && BCM_WARM_BOOT_SUPPORT */ 190 }; 191 static uint32 virtual_to_group_map[] = { 192 VIRTUAL_SLICE_0_VIRTUAL_SLICE_GROUPf, 193 VIRTUAL_SLICE_1_VIRTUAL_SLICE_GROUPf, 194 VIRTUAL_SLICE_2_VIRTUAL_SLICE_GROUPf, 195 VIRTUAL_SLICE_3_VIRTUAL_SLICE_GROUPf, 196 VIRTUAL_SLICE_4_VIRTUAL_SLICE_GROUPf, 197 VIRTUAL_SLICE_5_VIRTUAL_SLICE_GROUPf, 198 VIRTUAL_SLICE_6_VIRTUAL_SLICE_GROUPf, 199 VIRTUAL_SLICE_7_VIRTUAL_SLICE_GROUPf 200 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) \ 201 || defined(BCM_TRX_SUPPORT) && defined(BCM_WARM_BOOT_SUPPORT) 202 , 203 VIRTUAL_SLICE_8_VIRTUAL_SLICE_GROUPf, 204 VIRTUAL_SLICE_9_VIRTUAL_SLICE_GROUPf, 205 VIRTUAL_SLICE_10_VIRTUAL_SLICE_GROUPf, 206 VIRTUAL_SLICE_11_VIRTUAL_SLICE_GROUPf, 207 VIRTUAL_SLICE_12_VIRTUAL_SLICE_GROUPf, 208 VIRTUAL_SLICE_13_VIRTUAL_SLICE_GROUPf, 209 VIRTUAL_SLICE_14_VIRTUAL_SLICE_GROUPf, 210 VIRTUAL_SLICE_15_VIRTUAL_SLICE_GROUPf 211 #endif /* BCM_RAVEN_SUPPORT || BCM_FIREBOLT2_SUPPORT 212 || BCM_TRX_SUPPORT && BCM_WARM_BOOT_SUPPORT */ 213 }; 214 #endif /* BCM_RAPTOR_SUPPORT || BCM_FIREBOLT2_SUPPORT 215 || BCM_TRX_SUPPORT && BCM_WARM_BOOT_SUPPORT */ 216 217 #ifdef BCM_WARM_BOOT_SUPPORT 218 219 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) || \ 220 defined(BCM_TRX_SUPPORT) 221 int 222 _field_slice_expanded_status_get(int unit, _field_control_t *fc, _field_stage_t *stage_fc, 223 int *expanded, int *slice_master_idx) 224 { 225 int i, vslice, slice_idx = 0, vgroup = -1, max = -1, slice_num = 0; 226 fp_slice_map_entry_t map_entry; 227 soc_field_t fld; 228 #if defined(BCM_TRX_SUPPORT) 229 uint32 map_val; 230 #endif 231 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 232 uint8 vmap; 233 234 if (fc->l2warm) { 235 } 236 237 if (!soc_feature(unit, soc_feature_field_multi_pipe_support)) { 238 BCM_IF_ERROR_RETURN(READ_FP_SLICE_MAPm(unit, MEM_BLOCK_ANY, 0, &map_entry)); 239 slice_num = SOC_IS_HAWKEYE(unit)? 4 : 16; 240 if (SOC_IS_SC_CQ(unit)) { 241 slice_num = 12; 242 } 243 } 244 if ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) || 245 (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP)) { 246 slice_num = 4; 247 } 248 249 /* Iterate over virtual slices to get physical slices and virtual groups */ 250 for (vslice = 0; vslice < slice_num; vslice++) { 251 switch (stage_fc->stage_id) { 252 case _BCM_FIELD_STAGE_INGRESS: 253 fld = virtual_to_physical_map[vslice]; 254 slice_idx = soc_FP_SLICE_MAPm_field32_get(unit, &map_entry, fld); 255 /* Now get virtual group for this virtual slice */ 256 fld = virtual_to_group_map[vslice]; 257 vgroup = soc_FP_SLICE_MAPm_field32_get(unit, &map_entry, fld); 258 break; 259 #if defined(BCM_TRX_SUPPORT) 260 case _BCM_FIELD_STAGE_EGRESS: 261 BCM_IF_ERROR_RETURN(READ_EFP_SLICE_MAPr(unit, &map_val)); 262 fld = virtual_to_physical_map[vslice]; 263 slice_idx = soc_reg_field_get(unit, EFP_SLICE_MAPr, map_val, fld); 264 /* Now get virtual group for this virtual slice */ 265 fld = virtual_to_group_map[vslice]; 266 vgroup = soc_reg_field_get(unit, EFP_SLICE_MAPr, map_val, fld); 267 break; 268 case _BCM_FIELD_STAGE_LOOKUP: 269 BCM_IF_ERROR_RETURN(READ_VFP_SLICE_MAPr(unit, &map_val)); 270 fld = virtual_to_physical_map[vslice]; 271 slice_idx = soc_reg_field_get(unit, VFP_SLICE_MAPr, map_val, fld); 272 /* Now get virtual group for this virtual slice */ 273 fld = virtual_to_group_map[vslice]; 274 vgroup = soc_reg_field_get(unit, VFP_SLICE_MAPr, map_val, fld); 275 break; 276 #endif 277 default: 278 break; /* Should never happen */ 279 } 280 /* Phys slice_idx <=> virtual vslice <=> vgroup */ 281 stage_fc->vmap[_FP_DEF_INST][0][vslice].vmap_key = slice_idx; 282 stage_fc->vmap[_FP_DEF_INST][0][vslice].virtual_group = vgroup; 283 stage_fc->vmap[_FP_DEF_INST][0][vslice].priority = vgroup; 284 285 } 286 287 /* See if virtual slice is the highest number in the virtual group */ 288 for (vslice = 0; vslice < slice_num; vslice++) { 289 max = -1; 290 for (i = 0; i < slice_num; i++) { 291 if ((stage_fc->vmap[_FP_DEF_INST][0][vslice].virtual_group == 292 stage_fc->vmap[_FP_DEF_INST][0][i].virtual_group)) { 293 if (i > max) { 294 max = i; 295 } 296 } 297 } 298 if (!((fc->l2warm) 299 && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_8))) { 300 if ((max != vslice) && (max != -1)) { 301 expanded[stage_fc->vmap[_FP_DEF_INST][0][vslice].vmap_key] = 1; 302 } 303 } 304 } 305 306 /* Software mantains 3 MAPS, make them identical if only 1 map is present */ 307 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) { 308 for (vmap = 1; vmap < _FP_VMAP_CNT; ++vmap) { 309 for (vslice = 0; vslice < slice_num; vslice++) { 310 stage_fc->vmap[_FP_DEF_INST][vmap][vslice] = 311 stage_fc->vmap[_FP_DEF_INST][0][vslice]; 312 } 313 } 314 } 315 316 if ((fc->l2warm) 317 && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_8)) { 318 for (i = 0; i < slice_num; i++) { 319 expanded[i] = buf[fc->scache_pos] & 0x1; 320 slice_master_idx[i] = buf[fc->scache_pos] >> 1; 321 fc->scache_pos++; 322 } 323 } 324 325 return BCM_E_NONE; 326 } 327 328 int 329 _field_physical_to_virtual(int unit, int inst, int slice_idx, 330 _field_stage_t *stage_fc) 331 { 332 int vslice, slice_num; 333 slice_num = SOC_IS_HAWKEYE(unit) ? 4 : (SOC_IS_KATANAX(unit) ? 12 : 16); 334 for (vslice = 0; vslice < slice_num; vslice++) { 335 if (stage_fc->vmap[inst][0][vslice].vmap_key == slice_idx) { 336 return vslice; 337 } 338 } 339 return -1; 340 } 341 #endif 342 343 /* Function: _mask_is_set(_bcm_field_qual_offset_t *offset, uint32 *buf) 344 * Returns: 1 if any bit of buf is set between offset->offset and 345 * offset->offset + offset->width 346 * 0 otherwise 347 */ 348 int 349 _mask_is_set(int unit, _bcm_field_qual_offset_t *offset, uint32 *buf, 350 _field_stage_id_t stage_id) 351 { 352 int len = offset->width[0], bp = offset->offset[0]; 353 uint32 temp; 354 /* coverity[forward_null : FALSE] */ 355 soc_mem_info_t *meminfo = NULL; 356 357 switch (stage_id) { 358 case _BCM_FIELD_STAGE_INGRESS: 359 meminfo = &SOC_MEM_INFO(unit, FP_TCAMm); 360 break; 361 case _BCM_FIELD_STAGE_EGRESS: 362 meminfo = &SOC_MEM_INFO(unit, EFP_TCAMm); 363 break; 364 case _BCM_FIELD_STAGE_LOOKUP: 365 meminfo = &SOC_MEM_INFO(unit, VFP_TCAMm); 366 break; 367 default: 368 /* Should never happen */ 369 return (FALSE); 370 } 371 #define FIX_MEM_ORDER_E(v,m) (((m)->flags & SOC_MEM_FLAG_BE) ? \ 372 BYTES2WORDS((m)->bytes)-1-(v) : \ 373 (v)) 374 while (len > 0) { 375 temp = 0; 376 do { 377 /* coverity [forward_null] */ 378 temp = 379 (temp << 1) | 380 ((buf[FIX_MEM_ORDER_E(bp / 32, meminfo)] >> 381 (bp & (32 - 1))) & 1); 382 if (temp > 0) { 383 return TRUE; 384 } 385 len--; 386 bp++; 387 } while (len & (32 - 1)); 388 } 389 return FALSE; 390 } 391 392 int 393 _field_fb_counter_recover(int unit, _field_entry_t *f_ent, uint32 ctr_mode, 394 uint32 ctr_idx, int part, bcm_field_stat_t sid) 395 { 396 _field_group_t *fg; 397 _field_stage_t *stage_fc; 398 _field_stage_id_t stage_id; 399 _field_control_t *fc; 400 _field_slice_t *fs; 401 _field_stat_t *f_st = NULL; 402 _field_entry_stat_t *f_ent_st; 403 int rv, idx, stat_id, found; 404 uint32 sub_mode = 0, ent_st_flags = 0; 405 bcm_field_stat_t stat_arr[2]; 406 uint8 nstat = 1; 407 uint8 hw_entry_count = 1; 408 409 fg = f_ent->group; 410 fs = f_ent[part].fs; 411 412 sal_memset(stat_arr, 0, sizeof(stat_arr)); 413 414 /* Get field control and stage control */ 415 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 416 stage_id = f_ent->group->stage_id; 417 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 418 BCM_IF_ERROR_RETURN(rv); 419 420 /* Search if counter has already been detected */ 421 /* Go over the counter in the slice */ 422 if (stage_id == _BCM_FIELD_STAGE_INGRESS) { 423 sub_mode = ctr_mode & ~BCM_FIELD_COUNTER_MODE_BYTES; 424 if ((sub_mode == BCM_FIELD_COUNTER_MODE_RED) || 425 (sub_mode == BCM_FIELD_COUNTER_MODE_YELLOW) || 426 (sub_mode == BCM_FIELD_COUNTER_MODE_GREEN) || 427 (sub_mode == BCM_FIELD_COUNTER_MODE_YES_NO) || 428 (sub_mode == BCM_FIELD_COUNTER_MODE_DEFAULT)) { 429 hw_entry_count = 1; 430 } else { 431 hw_entry_count = 2; 432 } 433 } else if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) { 434 hw_entry_count = 1; 435 } 436 if (((_FP_COUNTER_BMP_TEST(fs->counter_bmp, 2 * ctr_idx)) && 437 (_FP_COUNTER_BMP_TEST(fs->counter_bmp, 2 * ctr_idx + 1)) && 438 (2 == hw_entry_count)) || 439 ((_FP_COUNTER_BMP_TEST(fs->counter_bmp, 2 * ctr_idx)) && 440 (hw_entry_count == 1) && (ctr_mode % 2 == 0)) || 441 ((_FP_COUNTER_BMP_TEST(fs->counter_bmp, 2 * ctr_idx + 1)) && 442 (hw_entry_count == 1) && (ctr_mode % 2))) { 443 /* Counter has been detected - increment reference count */ 444 /* Happens when counter is shared by different entries */ 445 /* Search the hash to match against the HW index */ 446 found = 0; 447 for (idx = 0; idx < _FP_HASH_SZ(fc); idx++) { 448 f_st = fc->stat_hash[idx]; 449 while (f_st != NULL) { 450 if ((f_st->hw_index == ctr_idx) && 451 (f_st->pool_index == fs->slice_number) && 452 (f_st->hw_mode == ctr_mode) && 453 (f_st->stage_id == stage_id)) { 454 found = 1; 455 break; 456 } 457 f_st = f_st->next; 458 } 459 if (found) { 460 break; 461 } 462 } 463 if (!found) { 464 return BCM_E_INTERNAL; 465 } 466 f_st->hw_ref_count++; 467 f_st->sw_ref_count++; 468 f_ent_st = &f_ent->statistic; 469 } else { 470 /* Allocate new stat object */ 471 if (fc->l2warm) { 472 stat_id = sid; 473 } else { 474 BCM_IF_ERROR_RETURN(_bcm_field_stat_id_alloc(unit, &stat_id)); 475 } 476 _FP_XGS3_ALLOC(f_st, sizeof (_field_stat_t), "Field stat entity"); 477 if (NULL == f_st) { 478 return (BCM_E_MEMORY); 479 } 480 ent_st_flags |= _FP_ENTRY_STAT_INSTALLED; 481 f_st->sw_ref_count = 2; 482 f_st->hw_ref_count = 1; 483 f_st->pool_index = fs->slice_number; 484 f_st->hw_index = ctr_idx; 485 f_st->sid = stat_id; 486 f_st->stage_id = fg->stage_id; 487 f_st->gid = fg->gid; 488 f_st->hw_mode = ctr_mode; 489 f_ent_st = &f_ent->statistic; 490 if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) { 491 switch (sub_mode) { 492 case (0x1): 493 case (0x2): 494 stat_arr[0] = bcmFieldStatPackets; 495 nstat = 1; 496 break; 497 case (0x9): 498 case (0xa): 499 stat_arr[0] = bcmFieldStatBytes; 500 nstat = 1; 501 break; 502 case (0x3): 503 stat_arr[0] = bcmFieldStatRedPackets; 504 stat_arr[1] = bcmFieldStatNotRedPackets; 505 nstat = 2; 506 break; 507 case (0xb): 508 stat_arr[0] = bcmFieldStatRedBytes; 509 stat_arr[1] = bcmFieldStatNotRedBytes; 510 nstat = 2; 511 break; 512 case (0x4): 513 stat_arr[0] = bcmFieldStatGreenPackets; 514 stat_arr[1] = bcmFieldStatNotGreenPackets; 515 nstat = 2; 516 break; 517 case (0xc): 518 stat_arr[0] = bcmFieldStatGreenBytes; 519 stat_arr[1] = bcmFieldStatNotGreenBytes; 520 nstat = 2; 521 break; 522 case (0x5): 523 stat_arr[0] = bcmFieldStatGreenPackets; 524 stat_arr[1] = bcmFieldStatRedPackets; 525 nstat = 2; 526 break; 527 case (0xd): 528 stat_arr[0] = bcmFieldStatGreenBytes; 529 stat_arr[1] = bcmFieldStatRedBytes; 530 nstat = 2; 531 break; 532 case (0x6): 533 stat_arr[0] = bcmFieldStatGreenPackets; 534 stat_arr[1] = bcmFieldStatYellowPackets; 535 nstat = 2; 536 break; 537 case (0xe): 538 stat_arr[0] = bcmFieldStatGreenBytes; 539 stat_arr[1] = bcmFieldStatYellowBytes; 540 nstat = 2; 541 break; 542 case (0x7): 543 stat_arr[0] = bcmFieldStatRedPackets; 544 stat_arr[1] = bcmFieldStatYellowPackets; 545 nstat = 2; 546 break; 547 case (0xf): 548 stat_arr[0] = bcmFieldStatRedBytes; 549 stat_arr[1] = bcmFieldStatYellowBytes; 550 nstat = 2; 551 break; 552 default: 553 break; 554 } 555 } else if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) { 556 stat_arr[0] = bcmFieldStatPackets; 557 } 558 rv = _bcm_field_stat_array_init(unit, fc, f_st, nstat, stat_arr); 559 if (BCM_FAILURE(rv)) { 560 sal_free(f_st); 561 return rv; 562 } 563 564 /* Assume counter was created using the stat_create API */ 565 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 566 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 567 if ((part == 2) || (part == 3)) { 568 f_ent->flags |= _FP_ENTRY_STAT_IN_SECONDARY_SLICE; 569 } 570 } else { 571 if (part == 1) { 572 f_ent->flags |= _FP_ENTRY_STAT_IN_SECONDARY_SLICE; 573 } 574 } 575 } 576 _FP_HASH_INSERT(fc->stat_hash, f_st, 577 (stat_id & _FP_HASH_INDEX_MASK(fc))); 578 fc->stat_count++; 579 /* Mark as used in the slice */ 580 if (2 == f_st->hw_entry_count) { 581 _FP_COUNTER_BMP_ADD(fs->counter_bmp, 2 * ctr_idx); 582 _FP_COUNTER_BMP_ADD(fs->counter_bmp, 2 * ctr_idx + 1); 583 } else { 584 if (ctr_mode % 2) { 585 _FP_COUNTER_BMP_ADD(fs->counter_bmp, 2 * ctr_idx + 1); 586 } else { 587 _FP_COUNTER_BMP_ADD(fs->counter_bmp, 2 * ctr_idx); 588 } 589 } 590 fg->group_status.counter_count = 591 fg->group_status.counter_count + f_st->hw_entry_count; 592 } 593 594 /* Associate the stat object with the entry */ 595 f_ent_st->flags |= (_FP_ENTRY_STAT_VALID | ent_st_flags); 596 f_ent_st->sid = f_st->sid; 597 598 return BCM_E_NONE; 599 } 600 601 /* 602 * Function: 603 * _field_fb_meter_index_in_use 604 * Purpose: 605 * Returns success if meter index/meter pair is in use. 606 * Parameters: 607 * unit - (IN) BCM device number. 608 * fs - (IN) Slice where meter resides. 609 * meter_pair_mode - (IN) Meter mode. 610 * meter_offset - (IN) Odd/Even meter offset value. 611 * idx - (IN) Meter pair index. 612 * Returns: 613 * BCM_E_XXX 614 */ 615 STATIC 616 int _field_fb_meter_index_in_use(int unit, 617 _field_slice_t *fs, 618 uint32 meter_pair_mode, 619 uint32 meter_offset, 620 int idx) 621 { 622 /* Input parameter check. */ 623 if (NULL == fs) { 624 return (BCM_E_INTERNAL); 625 } 626 627 /* Meters are per-slice resource. */ 628 if (meter_pair_mode == BCM_FIELD_METER_MODE_FLOW 629 && _FP_METER_BMP_TEST(fs->meter_bmp, ((idx * 2) + meter_offset))) { 630 /* Flow mode meter index in use. */ 631 return (BCM_E_NONE); 632 } else if (_FP_METER_BMP_TEST(fs->meter_bmp, (idx * 2)) 633 && _FP_METER_BMP_TEST(fs->meter_bmp, ((idx * 2) + 1))) { 634 /* Non-Flow mode meter pair index in use. */ 635 return (BCM_E_NONE); 636 } 637 return (BCM_E_NOT_FOUND); 638 } 639 640 int 641 _field_fb_meter_recover(int unit, _field_entry_t *f_ent, 642 _meter_config_t *meter_conf, int part, 643 bcm_policer_t pid) 644 { 645 _field_group_t *fg; 646 _field_stage_t *stage_fc; 647 _field_stage_id_t stage_id; 648 _field_control_t *fc; 649 _field_slice_t *fs; 650 _field_policer_t *f_pl = NULL; 651 _field_entry_policer_t *f_ent_pl; 652 int rv, idx, policer_id, found, mem_idx, meter_offset = 0; 653 uint32 ent[SOC_MAX_MEM_FIELD_WORDS], ent_pl_flags = 0; 654 uint32 refresh_count, bucket_count; 655 #ifdef BCM_FIREBOLT2_SUPPORT 656 uint32 bucket_size; 657 #endif /* BCM_FIREBOLT2_SUPPORT */ 658 659 if ((meter_conf->meter_mode == 0) && (meter_conf->meter_idx == 0)) { 660 return BCM_E_NONE; 661 } 662 663 fg = f_ent->group; 664 fs = f_ent[part].fs; 665 666 /* Get field control and stage control */ 667 BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc)); 668 stage_id = f_ent->group->stage_id; 669 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 670 BCM_IF_ERROR_RETURN(rv); 671 672 #ifdef BCM_FIREBOLT2_SUPPORT 673 if ((meter_conf->meter_mode == 4) && 674 (stage_id == _BCM_FIELD_STAGE_EGRESS)) { 675 return BCM_E_NONE; 676 } 677 #endif 678 679 if (BCM_FIELD_METER_MODE_FLOW == meter_conf->meter_mode) { 680 meter_offset = (meter_conf->meter_update_even 681 && meter_conf->meter_test_even) ? 0 : 1; 682 } 683 684 if (BCM_SUCCESS(_field_fb_meter_index_in_use(unit, fs, 685 meter_conf->meter_mode, meter_offset, meter_conf->meter_idx))) { 686 found = 0; 687 for (idx = 0; idx < _FP_HASH_SZ(fc); idx++) { 688 f_pl = fc->policer_hash[idx]; 689 while (f_pl != NULL) { 690 if ((f_pl->hw_index == meter_conf->meter_idx) && 691 (f_pl->pool_index == fs->slice_number) && 692 (f_pl->stage_id == stage_id)) { 693 if (meter_conf->meter_mode == 694 BCM_FIELD_METER_MODE_FLOW) { 695 if (((meter_offset == 1) && 696 (_FP_POLICER_EXCESS_HW_METER(f_pl))) || 697 ((meter_offset == 0) && 698 !(_FP_POLICER_EXCESS_HW_METER(f_pl)))) { 699 f_pl = f_pl->next; 700 continue; 701 } else { 702 found =1; 703 break; 704 } 705 } else { 706 found = 1; 707 break; 708 } 709 } 710 f_pl = f_pl->next; 711 } 712 if (found) { 713 break; 714 } 715 } 716 if (!found) { 717 return BCM_E_INTERNAL; 718 } 719 f_pl->hw_ref_count++; 720 f_pl->sw_ref_count++; 721 } else { 722 /* Allocate new policer object */ 723 if (fc->l2warm) { 724 policer_id = pid; 725 } else { 726 BCM_IF_ERROR_RETURN(_field_policer_id_alloc(unit, &policer_id)); 727 } 728 _FP_XGS3_ALLOC(f_pl, sizeof (_field_policer_t), "Field policer entity"); 729 if (NULL == f_pl) { 730 return (BCM_E_MEMORY); 731 } 732 ent_pl_flags |= _FP_POLICER_INSTALLED; 733 f_pl->sw_ref_count = 2; 734 f_pl->hw_ref_count = 1; 735 f_pl->pool_index = fs->slice_number; 736 f_pl->hw_index = meter_conf->meter_idx; 737 f_pl->pid = policer_id; 738 f_pl->stage_id = fg->stage_id; 739 740 switch (meter_conf->meter_mode) { 741 case BCM_FIELD_METER_MODE_DEFAULT: /* 0 */ 742 f_pl->cfg.mode = bcmPolicerModeGreen; 743 break; 744 case BCM_FIELD_METER_MODE_FLOW: /* 1 */ 745 f_pl->cfg.mode = bcmPolicerModeCommitted; 746 747 if (meter_offset) { 748 /* Flow mode using committed hardware meter. */ 749 _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl); 750 } else { 751 /* Flow mode using excess hardware meter. */ 752 _FP_POLICER_EXCESS_HW_METER_SET(f_pl); 753 } 754 755 mem_idx = 756 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx 757 + (2 * f_pl->hw_index) + meter_offset; 758 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY, 759 mem_idx, ent); 760 if (BCM_FAILURE(rv)) { 761 sal_free(f_pl); 762 return rv; 763 } 764 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 765 REFRESHCOUNTf); 766 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 767 BUCKETCOUNTf); 768 769 f_pl->cfg.ckbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE; 770 #ifdef BCM_FIREBOLT2_SUPPORT 771 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 772 BUCKETSIZEf); 773 if (SOC_IS_FIREBOLT2(unit)) { 774 f_pl->cfg.ckbits_burst 775 = _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE); 776 } else 777 #endif 778 { 779 f_pl->cfg.ckbits_burst = bucket_count / 2 / 1024; 780 /* Refer to _field_fb_bucket_calc */ 781 } 782 break; 783 case BCM_FIELD_METER_MODE_trTCM_COLOR_BLIND: /* 2 */ 784 f_pl->cfg.flags |= BCM_POLICER_COLOR_BLIND; 785 /* Fall through */ 786 case BCM_FIELD_METER_MODE_trTCM_COLOR_AWARE: /* 3 */ 787 f_pl->cfg.mode = bcmPolicerModeTrTcm; 788 /* Get the peak attributes */ 789 mem_idx = 790 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx 791 + (2 * f_pl->hw_index); 792 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY, 793 mem_idx, ent); 794 if (BCM_FAILURE(rv)) { 795 sal_free(f_pl); 796 return rv; 797 } 798 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 799 REFRESHCOUNTf); 800 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 801 BUCKETCOUNTf); 802 f_pl->cfg.pkbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE; 803 #ifdef BCM_FIREBOLT2_SUPPORT 804 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 805 BUCKETSIZEf); 806 if (SOC_IS_FIREBOLT2(unit)) { 807 f_pl->cfg.pkbits_burst = 808 _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE); 809 } else 810 #endif 811 { 812 f_pl->cfg.pkbits_burst = bucket_count / 2 / 1024; 813 /* Refer to _field_fb_bucket_calc */ 814 } 815 /* Get the committed attributes */ 816 mem_idx = 817 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx 818 + (2 * f_pl->hw_index) + 1; 819 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY, 820 mem_idx, ent); 821 if (BCM_FAILURE(rv)) { 822 sal_free(f_pl); 823 return rv; 824 } 825 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 826 REFRESHCOUNTf); 827 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 828 BUCKETCOUNTf); 829 f_pl->cfg.ckbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE; 830 #ifdef BCM_FIREBOLT2_SUPPORT 831 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 832 BUCKETSIZEf); 833 if (SOC_IS_FIREBOLT2(unit)) { 834 f_pl->cfg.ckbits_burst = 835 _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE); 836 } else 837 #endif 838 { 839 f_pl->cfg.ckbits_burst = bucket_count / 2 / 1024; 840 /* Refer to _field_fb_bucket_calc */ 841 } 842 break; 843 case 4: 844 if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) { 845 f_pl->cfg.mode = bcmPolicerModePassThrough; 846 } 847 break; 848 case 5: 849 break; 850 case BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND: /* 6 */ 851 f_pl->cfg.flags |= BCM_POLICER_COLOR_BLIND; 852 /* Fall through */ 853 case BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE: /* 7 */ 854 f_pl->cfg.mode = bcmPolicerModeSrTcm; 855 /* Get the peak attributes */ 856 mem_idx = 857 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx 858 + (2 * f_pl->hw_index); 859 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY, 860 mem_idx, ent); 861 if (BCM_FAILURE(rv)) { 862 sal_free(f_pl); 863 return rv; 864 } 865 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 866 REFRESHCOUNTf); 867 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 868 BUCKETCOUNTf); 869 f_pl->cfg.pkbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE; 870 #ifdef BCM_FIREBOLT2_SUPPORT 871 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 872 BUCKETSIZEf); 873 if (SOC_IS_FIREBOLT2(unit)) { 874 f_pl->cfg.pkbits_burst = 875 _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE); 876 } else 877 #endif 878 { 879 f_pl->cfg.pkbits_burst = bucket_count / 2 / 1024; 880 /* Refer to _field_fb_bucket_calc */ 881 } 882 /* Get the committed attributes */ 883 mem_idx = 884 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx 885 + (2 * f_pl->hw_index) + 1; 886 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY, 887 mem_idx, ent); 888 if (BCM_FAILURE(rv)) { 889 sal_free(f_pl); 890 return rv; 891 } 892 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 893 REFRESHCOUNTf); 894 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 895 BUCKETCOUNTf); 896 f_pl->cfg.ckbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE; 897 #ifdef BCM_FIREBOLT2_SUPPORT 898 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent, 899 BUCKETSIZEf); 900 if (SOC_IS_FIREBOLT2(unit)) { 901 f_pl->cfg.ckbits_burst = 902 _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE); 903 } else 904 #endif 905 { 906 f_pl->cfg.ckbits_burst = bucket_count / 2 / 1024; 907 /* Refer to _field_fb_bucket_calc */ 908 } 909 break; 910 default: 911 break; 912 } 913 914 /* Assume policer was created using the policer_create API */ 915 if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 916 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 917 if ((part == 2) || (part == 3)) { 918 f_ent->flags |= _FP_ENTRY_POLICER_IN_SECONDARY_SLICE; 919 } 920 } else { 921 if (part == 1) { 922 f_ent->flags |= _FP_ENTRY_POLICER_IN_SECONDARY_SLICE; 923 } 924 } 925 } 926 _FP_HASH_INSERT(fc->policer_hash, f_pl, 927 (policer_id & _FP_HASH_INDEX_MASK(fc))); 928 fc->policer_count++; 929 /* Mark as used in the slice */ 930 if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) { 931 _FP_METER_BMP_ADD(fs->meter_bmp, (f_pl->hw_index * 2)); 932 _FP_METER_BMP_ADD(fs->meter_bmp, ((f_pl->hw_index * 2) + 1)); 933 } else { 934 _FP_METER_BMP_ADD(fs->meter_bmp, ((f_pl->hw_index * 2) + meter_offset)); 935 } 936 fg->group_status.meter_count++; 937 } 938 939 /* Associate the policer object with the entry */ 940 f_ent_pl = &f_ent->policer[0]; 941 f_ent_pl->flags |= (_FP_POLICER_VALID | ent_pl_flags); 942 f_ent_pl->pid = f_pl->pid; 943 944 return BCM_E_NONE; 945 } 946 947 STATIC int 948 _field_fb_actions_recover_action_add(int unit, 949 _field_entry_t *f_ent, 950 bcm_field_action_t action, 951 uint32 param0, 952 uint32 param1, 953 uint32 param2, 954 uint32 param3, 955 uint32 hw_index 956 ) 957 { 958 int rv; 959 _field_action_t *fa = NULL; 960 961 rv = _field_action_alloc(unit, action, 962 param0, param1, param2, param3, 0, 0, &fa); 963 if (BCM_FAILURE(rv)) { 964 return rv; 965 } 966 967 fa->hw_index = hw_index; 968 969 fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */ 970 971 /* Add action to front of entry's linked-list. */ 972 fa->next = f_ent->actions; 973 f_ent->actions = fa; 974 975 return (BCM_E_NONE); 976 } 977 978 int 979 _field_fb_actions_recover(int unit, uint32 *policy_entry, 980 _field_entry_t *f_ent, int part, soc_mem_t mem, 981 _field_entry_wb_info_t *f_ent_wb_info) 982 { 983 soc_field_t fld; /* Policy table field */ 984 uint32 fldval, param0, param1, append; /* Field value and action params */ 985 uint32 ctr_mode, ctr_idx; /* Counter mode and index */ 986 _field_action_t *fa = NULL; /* Action details */ 987 bcm_field_action_t action; /* Action type */ 988 int rv, i, num_fields; /* Number of policy table fields */ 989 _meter_config_t meter_conf; /* Meter config info */ 990 egr_l3_next_hop_entry_t egr_l3_next_hop_entry; /* Egress Next Hop table 991 * entry info */ 992 sal_mac_addr_t mac_addr; /* MAC address info */ 993 uint32 mac_addr_words[2]; /* MAC address info for Param[0], 994 * Param[1] */ 995 uint16 vlan_id; /* VLAN ID info */ 996 uint32 hw_index; /* Policy table index info */ 997 int action_sync = 1; 998 999 if (f_ent_wb_info == NULL) { 1000 return BCM_E_INTERNAL; 1001 } 1002 1003 num_fields = SOC_MEM_INFO(unit, mem).nFields; 1004 if (f_ent_wb_info->action_bmp == NULL || f_ent_wb_info->action_bmp->w == NULL) { 1005 action_sync = 0; 1006 } 1007 1008 for (i = 0; i < num_fields; i++) { 1009 fld = SOC_MEM_INFO(unit, mem).fields[i].field; 1010 fldval = PolicyGet(unit, mem, policy_entry, fld); 1011 action = param0 = param1 = append = 0; 1012 switch (fld) { 1013 case GREEN_TO_PIDf: 1014 if (fldval) { 1015 f_ent->flags |= _FP_ENTRY_COLOR_INDEPENDENT; 1016 } 1017 break; 1018 case ECN_CNGf: 1019 if (fldval) { 1020 action = bcmFieldActionEcnNew; 1021 append = 1; 1022 } 1023 break; 1024 case CHANGE_PRIORITYf: 1025 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 1026 if (fldval) { 1027 action = bcmFieldActionOuterVlanPrioNew; 1028 param0 = PolicyGet(unit, mem, policy_entry, 1029 NEW_PRIORITYf); 1030 append = 1; 1031 } 1032 } else { 1033 switch (fldval) { 1034 case 1: 1035 action = bcmFieldActionCosQNew; 1036 param0 = PolicyGet(unit, mem, policy_entry, 1037 NEWPRIf); 1038 append = 1; 1039 break; 1040 case 2: 1041 action = bcmFieldActionCosQCpuNew; 1042 param0 = PolicyGet(unit, mem, policy_entry, 1043 NEWPRIf); 1044 append = 1; 1045 break; 1046 case 4: 1047 action = bcmFieldActionPrioPktAndIntCopy; 1048 append = 1; 1049 break; 1050 case 5: 1051 action = bcmFieldActionPrioPktAndIntNew; 1052 param0 = PolicyGet(unit, mem, policy_entry, 1053 NEWPRIf); 1054 append = 1; 1055 break; 1056 case 6: 1057 action = bcmFieldActionPrioPktAndIntTos; 1058 append = 1; 1059 break; 1060 case 7: 1061 action = bcmFieldActionPrioPktAndIntCancel; 1062 append = 1; 1063 break; 1064 case 8: 1065 action = bcmFieldActionPrioPktCopy; 1066 append = 1; 1067 break; 1068 case 9: 1069 action = bcmFieldActionPrioPktNew; 1070 param0 = PolicyGet(unit, mem, policy_entry, 1071 NEWPRIf); 1072 append = 1; 1073 break; 1074 case 10: 1075 action = bcmFieldActionPrioPktTos; 1076 append = 1; 1077 break; 1078 case 11: 1079 action = bcmFieldActionPrioPktCancel; 1080 append = 1; 1081 break; 1082 case 12: 1083 action = bcmFieldActionPrioIntCopy; 1084 append = 1; 1085 break; 1086 case 13: 1087 action = bcmFieldActionPrioIntNew; 1088 param0 = PolicyGet(unit, mem, policy_entry, 1089 NEWPRIf); 1090 append = 1; 1091 break; 1092 case 14: 1093 action = bcmFieldActionPrioIntTos; 1094 append = 1; 1095 break; 1096 case 15: 1097 action = bcmFieldActionPrioIntCancel; 1098 append = 1; 1099 break; 1100 default: 1101 break; /* Do nothing */ 1102 } 1103 } 1104 break; 1105 case CHANGE_DSCP_TOSf: 1106 switch (fldval) { 1107 case 1: 1108 action = bcmFieldActionTosNew; 1109 param0 = PolicyGet(unit, mem, policy_entry, NEWDSCP_TOSf); 1110 append = 1; 1111 break; 1112 case 2: 1113 action = bcmFieldActionTosCopy; 1114 append = 1; 1115 break; 1116 case 3: 1117 action = bcmFieldActionDscpNew; 1118 param0 = PolicyGet(unit, mem, policy_entry, NEWDSCP_TOSf); 1119 append = 1; 1120 break; 1121 case 4: 1122 action = bcmFieldActionDscpCancel; 1123 append = 1; 1124 break; 1125 default: 1126 break; /* Do nothing */ 1127 } 1128 break; 1129 case RP_CHANGE_DSCPf: 1130 switch (fldval) { 1131 case 1: 1132 action = bcmFieldActionRpDscpNew; 1133 param0 = PolicyGet(unit, mem, policy_entry, RP_DSCPf); 1134 append = 1; 1135 break; 1136 default: 1137 break; /* Do nothing */ 1138 } 1139 break; 1140 case YP_CHANGE_DSCPf: 1141 switch (fldval) { 1142 case 1: 1143 action = bcmFieldActionYpDscpNew; 1144 param0 = PolicyGet(unit, mem, policy_entry, YP_DSCPf); 1145 append = 1; 1146 break; 1147 default: 1148 break; /* Do nothing */ 1149 } 1150 break; 1151 case COPY_TO_CPUf: 1152 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 1153 if (fldval) { 1154 action = bcmFieldActionCopyToCpu; 1155 param0 = 1; 1156 append = 1; 1157 } 1158 } else { 1159 switch (fldval) { 1160 case 1: 1161 action = bcmFieldActionCopyToCpu; 1162 param1 = PolicyGet(unit, mem, policy_entry, 1163 MATCHED_RULEf); 1164 if (param1 != 0) { 1165 param0 = 1; 1166 } 1167 append = 1; 1168 break; 1169 case 2: 1170 action = bcmFieldActionCopyToCpuCancel; 1171 append = 1; 1172 break; 1173 case 3: 1174 action = bcmFieldActionSwitchToCpuCancel; 1175 append = 1; 1176 break; 1177 default: 1178 break; /* Do nothing */ 1179 } 1180 } 1181 break; 1182 case YP_COPY_TO_CPUf: 1183 switch (fldval) { 1184 case 1: 1185 action = bcmFieldActionYpCopyToCpu; 1186 param1 = PolicyGet(unit, mem, policy_entry, MATCHED_RULEf); 1187 if (param1 != 0) { 1188 param0 = 1; 1189 } 1190 append = 1; 1191 break; 1192 case 2: 1193 action = bcmFieldActionYpCopyToCpuCancel; 1194 append = 1; 1195 break; 1196 default: 1197 break; /* Do nothing */ 1198 } 1199 break; 1200 case RP_COPY_TO_CPUf: 1201 switch (fldval) { 1202 case 1: 1203 action = bcmFieldActionRpCopyToCpu; 1204 param1 = PolicyGet(unit, mem, policy_entry, MATCHED_RULEf); 1205 if (param1 != 0) { 1206 param0 = 1; 1207 } 1208 append = 1; 1209 break; 1210 case 2: 1211 action = bcmFieldActionRpCopyToCpuCancel; 1212 append = 1; 1213 break; 1214 case 3: 1215 action = bcmFieldActionRpSwitchToCpuCancel; 1216 append = 1; 1217 break; 1218 default: 1219 break; /* Do nothing */ 1220 } 1221 break; 1222 case PACKET_REDIRECTIONf: 1223 switch (fldval) { 1224 case 1: 1225 if (PolicyGet(unit, mem, policy_entry, 1226 REDIRECTIONf) & 0x20) { 1227 action = bcmFieldActionRedirectTrunk; 1228 param0 = PolicyGet(unit, mem, policy_entry, 1229 REDIRECTIONf) & 0x1f; 1230 } else { 1231 action = bcmFieldActionRedirect; 1232 param0 = PolicyGet(unit, mem, policy_entry, 1233 REDIRECTIONf) >> 6; 1234 param1 = PolicyGet(unit, mem, policy_entry, 1235 REDIRECTIONf) & 0x3f; 1236 } 1237 append = 1; 1238 break; 1239 case 2: 1240 action = bcmFieldActionRedirectCancel; 1241 append = 1; 1242 break; 1243 case 3: 1244 action = bcmFieldActionRedirectPbmp; 1245 param0 = PolicyGet(unit, mem, policy_entry, REDIRECTIONf); 1246 append = 1; 1247 break; 1248 case 4: 1249 action = bcmFieldActionEgressMask; 1250 param0 = PolicyGet(unit, mem, policy_entry, REDIRECTIONf); 1251 append = 1; 1252 break; 1253 default: 1254 break; /* Do nothing */ 1255 } 1256 break; 1257 case DROPf: 1258 switch (fldval) { 1259 case 1: 1260 action = bcmFieldActionDrop; 1261 append = 1; 1262 break; 1263 case 2: 1264 action = bcmFieldActionDropCancel; 1265 append = 1; 1266 break; 1267 default: 1268 break; /* Do nothing */ 1269 } 1270 break; 1271 case YP_DROPf: 1272 switch (fldval) { 1273 case 1: 1274 action = bcmFieldActionYpDrop; 1275 append = 1; 1276 break; 1277 case 2: 1278 action = bcmFieldActionYpDropCancel; 1279 append = 1; 1280 break; 1281 default: 1282 break; /* Do nothing */ 1283 } 1284 break; 1285 case RP_DROPf: 1286 switch (fldval) { 1287 case 1: 1288 action = bcmFieldActionRpDrop; 1289 append = 1; 1290 break; 1291 case 2: 1292 action = bcmFieldActionRpDropCancel; 1293 append = 1; 1294 break; 1295 default: 1296 break; /* Do nothing */ 1297 } 1298 break; 1299 case GP_DROPf: 1300 switch (fldval) { 1301 case 1: 1302 action = bcmFieldActionGpDrop; 1303 append = 1; 1304 break; 1305 case 2: 1306 action = bcmFieldActionGpDropCancel; 1307 append = 1; 1308 break; 1309 default: 1310 break; /* Do nothing */ 1311 } 1312 break; 1313 case MIRROR_OVERRIDEf: 1314 if (fldval) { 1315 action = bcmFieldActionMirrorOverride; 1316 append = 1; 1317 } 1318 break; 1319 case MIRRORf: 1320 if (fldval & 0x1) { 1321 uint32 im_entry[SOC_MAX_MEM_FIELD_WORDS]; 1322 action = bcmFieldActionMirrorIngress; 1323 rv = _field_action_alloc(unit, action, 1324 param0, param1, 0, 0, 0, 0, &fa); 1325 fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */ 1326 if (BCM_FAILURE(rv)) { 1327 return rv; 1328 } 1329 fa->hw_index = PolicyGet(unit, mem, policy_entry, 1330 IM_MTP_INDEXf); 1331 rv = soc_mem_read(unit, IM_MTP_INDEXm, MEM_BLOCK_ANY, 1332 fa->hw_index, &im_entry); 1333 if (BCM_FAILURE(rv)) { 1334 sal_free(fa); 1335 return rv; 1336 } 1337 fa->param[0] = soc_IM_MTP_INDEXm_field32_get(unit, im_entry, 1338 MODULE_IDf); 1339 fa->param[1] = soc_IM_MTP_INDEXm_field32_get(unit, im_entry, 1340 PORT_TGIDf); 1341 /* Add action to front of entry's linked-list. */ 1342 fa->next = f_ent->actions; 1343 f_ent->actions = fa; 1344 } 1345 if (fldval & 0x2) { 1346 uint32 em_entry[SOC_MAX_MEM_FIELD_WORDS]; 1347 action = bcmFieldActionMirrorEgress; 1348 rv = _field_action_alloc(unit, action, 1349 param0, param1, 0, 0, 0, 0, &fa); 1350 fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */ 1351 if (BCM_FAILURE(rv)) { 1352 return rv; 1353 } 1354 fa->hw_index = PolicyGet(unit, mem, policy_entry, 1355 EM_MTP_INDEXf); 1356 rv = soc_mem_read(unit, EM_MTP_INDEXm, MEM_BLOCK_ANY, 1357 fa->hw_index, &em_entry); 1358 if (BCM_FAILURE(rv)) { 1359 sal_free(fa); 1360 return rv; 1361 } 1362 fa->param[0] = soc_EM_MTP_INDEXm_field32_get(unit, em_entry, 1363 MODULE_IDf); 1364 fa->param[1] = soc_EM_MTP_INDEXm_field32_get(unit, em_entry, 1365 PORT_TGIDf); 1366 /* Add action to front of entry's linked-list. */ 1367 fa->next = f_ent->actions; 1368 f_ent->actions = fa; 1369 } 1370 break; 1371 case L3SW_CHANGE_MACDA_OR_VLANf: 1372 switch (fldval) { 1373 int ecmp_paths, nh_ecmp; 1374 case 1: 1375 action = bcmFieldActionL3ChangeVlan; 1376 if (PolicyGet(unit, mem, policy_entry, ECMPf)) { 1377 ecmp_paths = PolicyGet(unit, mem, 1378 policy_entry, ECMP_COUNTf) + 1; 1379 nh_ecmp = PolicyGet(unit, mem, 1380 policy_entry, ECMP_PTRf); 1381 param0 = _FP_L3_ACTION_PACK_ECMP(nh_ecmp, ecmp_paths); 1382 } else { 1383 nh_ecmp = PolicyGet(unit, mem, 1384 policy_entry, NEXT_HOP_INDEXf); 1385 param0 = _FP_L3_ACTION_PACK_NEXT_HOP(nh_ecmp); 1386 } 1387 append = 1; 1388 1389 if (PolicyGet(unit, mem, policy_entry, ECMPf) == 0) { 1390 1391 /* Get the Next Hop Index value */ 1392 hw_index = PolicyGet(unit, mem, policy_entry, 1393 NEXT_HOP_INDEXf); 1394 1395 /* Read Next Hop information into entry */ 1396 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1397 MEM_BLOCK_ANY, hw_index, 1398 egr_l3_next_hop_entry.entry_data); 1399 if (BCM_FAILURE(rv)) { 1400 return (rv); 1401 } 1402 1403 /* Get the VLAN ID infomation */ 1404 vlan_id = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 1405 egr_l3_next_hop_entry.entry_data, 1406 INTF_NUMf); 1407 1408 /* Re-Create bcmFieldActionOuterVlanNew action for the 1409 * FP entry */ 1410 rv = _field_fb_actions_recover_action_add(unit, 1411 f_ent, bcmFieldActionOuterVlanNew, vlan_id, 0, 1412 0, 0, hw_index); 1413 if (BCM_FAILURE(rv)) { 1414 return (rv); 1415 } 1416 } 1417 break; 1418 case 2: 1419 action = bcmFieldActionL3ChangeVlanCancel; 1420 append = 1; 1421 break; 1422 case 3: 1423 /*recover fabricQueue action*/ 1424 if ((action_sync == 1) && 1425 SHR_BITGET(f_ent_wb_info->action_bmp->w, 1426 _bcmFieldActionNoParamFabricQueue)) { 1427 action = bcmFieldActionFabricQueue; 1428 append = 1; 1429 param0 = f_ent_wb_info->action_fabricQueue_wb.cosq_gport; 1430 } 1431 break; 1432 case 4: 1433 action = bcmFieldActionL3ChangeMacDa; 1434 if (PolicyGet(unit, mem, policy_entry, ECMPf)) { 1435 ecmp_paths = PolicyGet(unit, mem, 1436 policy_entry, ECMP_COUNTf) + 1; 1437 nh_ecmp = PolicyGet(unit, mem, 1438 policy_entry, ECMP_PTRf); 1439 param0 = _FP_L3_ACTION_PACK_ECMP(nh_ecmp, ecmp_paths); 1440 } else { 1441 nh_ecmp = PolicyGet(unit, mem, 1442 policy_entry, NEXT_HOP_INDEXf); 1443 param0 = _FP_L3_ACTION_PACK_NEXT_HOP(nh_ecmp); 1444 } 1445 append = 1; 1446 1447 if (PolicyGet(unit, mem, policy_entry, ECMPf) == 0) { 1448 1449 /* Get the Next Hop Index value */ 1450 hw_index = PolicyGet(unit, mem, policy_entry, 1451 NEXT_HOP_INDEXf); 1452 1453 /* Read Next Hop information into entry */ 1454 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1455 MEM_BLOCK_ANY, hw_index, 1456 egr_l3_next_hop_entry.entry_data); 1457 if (BCM_FAILURE(rv)) { 1458 return (rv); 1459 } 1460 1461 /* Get the DA/DMAC infomation */ 1462 soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, 1463 egr_l3_next_hop_entry.entry_data, 1464 MAC_ADDRESSf, mac_addr); 1465 SAL_MAC_ADDR_TO_UINT32(mac_addr, mac_addr_words); 1466 1467 /* Re-Create bcmFieldActionDstMacNew action for the 1468 * FP entry */ 1469 rv = _field_fb_actions_recover_action_add(unit, 1470 f_ent, bcmFieldActionDstMacNew, 1471 mac_addr_words[0], mac_addr_words[1], 0, 0, 1472 hw_index); 1473 if (BCM_FAILURE(rv)) { 1474 return (rv); 1475 } 1476 } 1477 break; 1478 case 5: 1479 action = bcmFieldActionL3ChangeMacDaCancel; 1480 append = 1; 1481 break; 1482 case 6: 1483 #ifdef INCLUDE_L3 1484 action = bcmFieldActionL3Switch; 1485 if (PolicyGet(unit, mem, policy_entry, ECMPf)) { 1486 ecmp_paths = PolicyGet(unit, mem, 1487 policy_entry, ECMP_COUNTf) + 1; 1488 nh_ecmp = PolicyGet(unit, mem, 1489 policy_entry, ECMP_PTRf); 1490 param0 = (nh_ecmp) + 1491 (BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)); 1492 } else { 1493 nh_ecmp = PolicyGet(unit, mem, 1494 policy_entry, NEXT_HOP_INDEXf); 1495 param0 = (nh_ecmp) + 1496 (BCM_XGS3_EGRESS_IDX_MIN(unit)); 1497 } 1498 append = 1; 1499 #endif /* INCLUDE_L3 */ 1500 break; 1501 case 7: 1502 action = bcmFieldActionL3SwitchCancel; 1503 append = 1; 1504 break; 1505 default: 1506 break; /* Do nothing */ 1507 } 1508 break; 1509 case DROP_PRECEDENCEf: 1510 if (fldval) { 1511 action = bcmFieldActionDropPrecedence; 1512 param0 = fldval; 1513 append = 1; 1514 } 1515 break; 1516 case RP_DROP_PRECEDENCEf: 1517 if (fldval) { 1518 action = bcmFieldActionRpDropPrecedence; 1519 param0 = fldval; 1520 append = 1; 1521 } 1522 break; 1523 case YP_DROP_PRECEDENCEf: 1524 if (fldval) { 1525 action = bcmFieldActionYpDropPrecedence; 1526 param0 = fldval; 1527 append = 1; 1528 } 1529 break; 1530 case COUNTER_MODEf: 1531 if (fldval) { 1532 ctr_mode = fldval; 1533 ctr_idx = PolicyGet(unit, mem, policy_entry, 1534 COUNTER_INDEXf); 1535 BCM_IF_ERROR_RETURN 1536 (_field_fb_counter_recover(unit, f_ent, ctr_mode, 1537 ctr_idx, part, f_ent_wb_info->sid)); 1538 } 1539 break; 1540 case METER_PAIR_MODEf: 1541 meter_conf.meter_mode = fldval; 1542 meter_conf.meter_mode_modifier 1543 = soc_mem_field_valid(unit, mem, METER_PAIR_MODE_MODIFIERf) 1544 ? PolicyGet(unit, mem, policy_entry, METER_PAIR_MODE_MODIFIERf) 1545 : 0; 1546 meter_conf.meter_idx = PolicyGet(unit, mem, 1547 policy_entry, 1548 METER_INDEX_EVENf); 1549 meter_conf.meter_update_odd = PolicyGet(unit, mem, 1550 policy_entry, 1551 METER_UPDATE_ODDf); 1552 meter_conf.meter_test_odd = PolicyGet(unit, mem, 1553 policy_entry, 1554 METER_TEST_ODDf); 1555 meter_conf.meter_update_even = PolicyGet(unit, mem, 1556 policy_entry, 1557 METER_UPDATE_EVENf); 1558 meter_conf.meter_test_even = PolicyGet(unit, mem, 1559 policy_entry, 1560 METER_TEST_EVENf); 1561 BCM_IF_ERROR_RETURN 1562 (_field_fb_meter_recover(unit, f_ent, &meter_conf, part, f_ent_wb_info->pid)); 1563 break; 1564 case PID_REPLACE_INNER_VIDf: 1565 if (fldval) { 1566 action = bcmFieldActionInnerVlanNew; 1567 param0 = PolicyGet(unit, mem, policy_entry, PID_NEW_INNER_VIDf); 1568 append = 1; 1569 } 1570 break; 1571 case PID_REPLACE_INNER_PRIf: 1572 if (fldval) { 1573 action = bcmFieldActionInnerVlanPrioNew; 1574 param0 = PolicyGet(unit, mem, policy_entry, PID_NEW_INNER_PRIf); 1575 append = 1; 1576 } 1577 break; 1578 case PID_REPLACE_OUTER_VIDf: 1579 if (fldval) { 1580 action = bcmFieldActionOuterVlanNew; 1581 param0 = PolicyGet(unit, mem, policy_entry, PID_NEW_OUTER_VIDf); 1582 append = 1; 1583 } 1584 break; 1585 case PID_REPLACE_OUTER_TPIDf: 1586 if (fldval) { 1587 uint32 mode; 1588 uint16 tpid; 1589 action = bcmFieldActionInnerVlanPrioNew; 1590 mode = PolicyGet(unit, mem, policy_entry, PID_TPID_INDEXf); 1591 BCM_IF_ERROR_RETURN 1592 (_field_tpid_hw_decode(unit, mode, &tpid)); 1593 param0 = tpid; 1594 append = 1; 1595 } 1596 break; 1597 case RP_CHANGE_DOT1Pf: 1598 if (fldval) { 1599 action = bcmFieldActionRpOuterVlanPrioNew; 1600 param0 = PolicyGet(unit, mem, policy_entry, RP_NEW_DOT1Pf); 1601 append = 1; 1602 } 1603 break; 1604 case YP_CHANGE_DOT1Pf: 1605 if (fldval) { 1606 action = bcmFieldActionYpOuterVlanPrioNew; 1607 param0 = PolicyGet(unit, mem, policy_entry, YP_NEW_DOT1Pf); 1608 append = 1; 1609 } 1610 break; 1611 case GP_CHANGE_DOT1Pf: 1612 if (fldval) { 1613 action = bcmFieldActionGpOuterVlanPrioNew; 1614 param0 = PolicyGet(unit, mem, policy_entry, GP_NEW_DOT1Pf); 1615 append = 1; 1616 } 1617 break; 1618 case PID_INCR_COUNTERf: 1619 if (fldval) { 1620 ctr_mode = fldval; 1621 ctr_idx = PolicyGet(unit, mem, policy_entry, 1622 PID_COUNTER_INDEXf); 1623 BCM_IF_ERROR_RETURN 1624 (_field_fb_counter_recover(unit, f_ent, ctr_mode, 1625 ctr_idx, part, f_ent_wb_info->sid)); 1626 } 1627 break; 1628 case CHANGE_VLANf: 1629 switch (fldval) { 1630 case 1: 1631 action = bcmFieldActionVlanAdd; 1632 param0 = PolicyGet(unit, mem, policy_entry, NEW_VLANf); 1633 append = 1; 1634 break; 1635 case 2: 1636 action = bcmFieldActionOuterVlanNew; 1637 param0 = PolicyGet(unit, mem, policy_entry, NEW_VLANf); 1638 append = 1; 1639 break; 1640 default: 1641 break; /* Do nothing */ 1642 } 1643 break; 1644 case USE_VFP_CLASS_IDf: 1645 if (fldval) { 1646 action = bcmFieldActionClassSet; 1647 param0 = PolicyGet(unit, mem, policy_entry, VFP_CLASS_IDf); 1648 append = 1; 1649 } 1650 break; 1651 case USE_VFP_VRF_IDf: 1652 if (fldval) { 1653 action = bcmFieldActionVrfSet; 1654 param0 = PolicyGet(unit, mem, policy_entry, VFP_VRF_IDf); 1655 append = 1; 1656 } 1657 break; 1658 default: 1659 break; /* Do nothing */ 1660 } 1661 if (append) { 1662 rv = _field_action_alloc(unit, action, 1663 param0, param1, 0, 0, 0, 0, &fa); 1664 fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */ 1665 if (BCM_FAILURE(rv)) { 1666 return rv; 1667 } 1668 /* Add action to front of entry's linked-list. */ 1669 fa->next = f_ent->actions; 1670 f_ent->actions = fa; 1671 } 1672 } 1673 return BCM_E_NONE; 1674 } 1675 1676 int 1677 _field_group_info_retrieve(int unit, 1678 bcm_port_t port, 1679 int inst, 1680 bcm_field_group_t *gid, 1681 int *priority, 1682 int *action_res_id, 1683 bcm_pbmp_t *group_pbmp, 1684 int8 *efp_key_info, 1685 int *group_flags, 1686 bcm_field_qset_t *qset, 1687 _field_control_t *fc 1688 ) 1689 { 1690 1691 _field_slice_group_info_t *current; 1692 current = fc->group_arr; 1693 while (current) { 1694 if (current->found) { 1695 *gid = -1; /* GID has already been copied */ 1696 if(!(current = current->next)) { 1697 return BCM_E_NONE; /* Will detect it later */ 1698 } 1699 continue; 1700 } 1701 if (((port == -1) || (BCM_PBMP_MEMBER(current->pbmp, port))) && 1702 (current->instance == inst)) { 1703 *gid = current->gid; 1704 *priority = current->priority; 1705 *group_flags = current->flags; 1706 *action_res_id = current->action_res_id; 1707 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_21) { 1708 SOC_PBMP_ASSIGN(*group_pbmp, current->pbmp); 1709 } 1710 1711 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) || 1712 soc_feature(unit, soc_feature_field_multi_pipe_support)) && 1713 efp_key_info) { 1714 efp_key_info[0] = current->efp_pri_key; 1715 efp_key_info[1] = current->efp_sec_key; 1716 } 1717 sal_memcpy(qset, ¤t->qset, sizeof(bcm_field_qset_t)); 1718 current->found = 1; 1719 return BCM_E_NONE; 1720 } else if (!current->next) { 1721 *gid = -1; /* Will detect it later */ 1722 return BCM_E_NONE; 1723 } 1724 current = current->next; 1725 } 1726 return BCM_E_NOT_FOUND; 1727 } 1728 1729 /* Retrieve all GIDs from a slice during Level 2 warm boot */ 1730 int 1731 _field_scache_slice_group_recover(int unit, _field_control_t *fc, 1732 int slice_num, int *multigroup) 1733 { 1734 int i, slice_idx; 1735 int next_group_valid = 1, rv = BCM_E_NONE; 1736 int qset_count; 1737 int qset; 1738 bcm_field_group_t gid; 1739 bcm_port_t port; 1740 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 1741 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 1742 _field_slice_group_info_t *new_grp = NULL; 1743 int priority; 1744 int action_res_id; 1745 soc_pbmp_t group_pbmp; 1746 uint8 udf_count = 0; 1747 uint8 udf_idx = 0; 1748 1749 /* Parse the scache buffer to recover GIDs and QSETs */ 1750 /* To be used in stage reinit */ 1751 slice_idx = buf[fc->scache_pos] >> 1; 1752 LOG_VERBOSE(BSL_LS_BCM_FP, 1753 (BSL_META_U(unit, 1754 "Read slice index %d @ byte %d\n"), 1755 slice_idx, fc->scache_pos)); 1756 if (multigroup) { 1757 *multigroup = buf[fc->scache_pos] & 0x1; 1758 } 1759 fc->scache_pos++; 1760 if (slice_idx != slice_num) { 1761 /* No groups stored for this slice */ 1762 fc->scache_pos--; 1763 return BCM_E_NOT_FOUND; 1764 } 1765 fc->group_arr = NULL; 1766 1767 /* Parse all the group data for this slice */ 1768 while (next_group_valid) { 1769 SOC_PBMP_CLEAR(group_pbmp); 1770 gid = 0; 1771 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) { 1772 /* Read full GID */ 1773 1774 gid |= buf[fc->scache_pos]; 1775 fc->scache_pos++; 1776 gid |= buf[fc->scache_pos] << 8; 1777 fc->scache_pos++; 1778 gid |= buf[fc->scache_pos] << 16; 1779 fc->scache_pos++; 1780 gid |= buf[fc->scache_pos] << 24; 1781 fc->scache_pos++; 1782 1783 port = buf[fc->scache_pos]; 1784 fc->scache_pos++; 1785 } else { 1786 /* Read compact GID */ 1787 1788 gid |= buf[fc->scache_pos]; /* GID */ 1789 fc->scache_pos++; 1790 port = 0; 1791 port |= buf[fc->scache_pos] & 0xF; /* Rep_port_lo */ 1792 fc->scache_pos++; 1793 port |= (buf[fc->scache_pos] & 0x3) << 4; /* Rep_port_hi */ 1794 fc->scache_pos++; 1795 } 1796 1797 LOG_VERBOSE(BSL_LS_BCM_FP, 1798 (BSL_META_U(unit, 1799 "Read group id %d @ %d.\n"), 1800 gid, fc->scache_pos - 3)); 1801 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_21) { 1802 int i = 0; 1803 for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) { 1804 group_pbmp.pbits[i] = buf[fc->scache_pos]; 1805 fc->scache_pos++; 1806 group_pbmp.pbits[i] |= buf[fc->scache_pos] << 8; 1807 fc->scache_pos++; 1808 group_pbmp.pbits[i] |= buf[fc->scache_pos] << 16; 1809 fc->scache_pos++; 1810 group_pbmp.pbits[i] |= buf[fc->scache_pos] << 24; 1811 fc->scache_pos++; 1812 } 1813 } 1814 /* Read group priority */ 1815 priority = 0; 1816 priority |= buf[fc->scache_pos]; 1817 fc->scache_pos++; 1818 priority |= buf[fc->scache_pos] << 8; 1819 fc->scache_pos++; 1820 priority |= buf[fc->scache_pos] << 16; 1821 fc->scache_pos++; 1822 priority |= buf[fc->scache_pos] << 24; 1823 fc->scache_pos++; 1824 1825 /* Read group action res id */ 1826 action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 1827 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_8) { 1828 action_res_id = 0; 1829 action_res_id |= buf[fc->scache_pos]; 1830 fc->scache_pos++; 1831 action_res_id |= buf[fc->scache_pos] << 8; 1832 fc->scache_pos++; 1833 action_res_id |= buf[fc->scache_pos] << 16; 1834 fc->scache_pos++; 1835 action_res_id |= buf[fc->scache_pos] << 24; 1836 fc->scache_pos++; 1837 } 1838 1839 /* Add group info to temp linked list */ 1840 new_grp = NULL; 1841 _FP_XGS3_ALLOC(new_grp, sizeof(_field_slice_group_info_t), 1842 "Temp group info"); 1843 new_grp->gid = gid; 1844 new_grp->priority = priority; 1845 new_grp->action_res_id = action_res_id; 1846 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_21) { 1847 SOC_PBMP_ASSIGN(new_grp->pbmp, group_pbmp); 1848 } 1849 BCM_PBMP_PORT_ADD(new_grp->pbmp, port); 1850 new_grp->next = fc->group_arr; 1851 fc->group_arr = new_grp; 1852 qset_count = buf[fc->scache_pos]; /* QSET_count */ 1853 fc->scache_pos++; 1854 1855 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 1856 "Before Read qset count %d @ s_pos=%d s_pos1=%d\n"), 1857 qset_count, fc->scache_pos, fc->scache_pos1)); 1858 1859 for (i = 0; i < qset_count; i++) { 1860 qset = 0; 1861 qset |= buf[fc->scache_pos]; 1862 fc->scache_pos++; 1863 if(NULL != buf1) { 1864 qset |= buf1[fc->scache_pos1] << 8; 1865 fc->scache_pos1++; 1866 } 1867 BCM_FIELD_QSET_ADD(new_grp->qset, qset); 1868 1869 LOG_VERBOSE(BSL_LS_BCM_FP, 1870 (BSL_META_U(unit, 1871 "Read qualifier id %d @ %d.\n"), 1872 qset, fc->scache_pos - 1)); 1873 } 1874 1875 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 1876 "After Read qset count %d @ s_pos=%d s_pos1=%d\n"), 1877 qset_count, fc->scache_pos, fc->scache_pos1)); 1878 1879 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_10) { 1880 qset_count = buf[fc->scache_pos]; /* Internal QSET_count */ 1881 fc->scache_pos++; 1882 1883 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 1884 "Internal Qset count %d @ s_pos=%d s_pos1=%d\n"), 1885 qset_count, fc->scache_pos - 1, fc->scache_pos1)); 1886 1887 for (i = 0; i < qset_count; i++) { 1888 qset = 0; 1889 qset |= buf[fc->scache_pos]; 1890 fc->scache_pos++; 1891 if(NULL != buf1) { 1892 qset |= buf1[fc->scache_pos1] << 8; 1893 fc->scache_pos1++; 1894 } 1895 qset += bcmFieldQualifyCount; 1896 BCM_FIELD_QSET_ADD(new_grp->qset, qset); 1897 1898 LOG_VERBOSE(BSL_LS_BCM_FP, 1899 (BSL_META_U(unit, 1900 "Read internal qualifier %d @ %d.\n"), 1901 qset, fc->scache_pos - 1)); 1902 } 1903 1904 LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit, 1905 "After Read qset count %d @ s_pos=%d s_pos1=%d\n"), 1906 qset_count, fc->scache_pos, fc->scache_pos1)); 1907 1908 udf_count = buf[fc->scache_pos]; 1909 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 1910 "Read udf count %d @ s_pos=%d\n"), 1911 udf_count, fc->scache_pos)); 1912 fc->scache_pos++; 1913 for (i = 0; i < udf_count; i++) { 1914 udf_idx = buf[fc->scache_pos]; 1915 fc->scache_pos++; 1916 SHR_BITSET(new_grp->qset.udf_map, udf_idx); 1917 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 1918 "Read UDF idx %d @ byte %d.\n"), 1919 udf_idx, fc->scache_pos - 1)); 1920 } 1921 } 1922 1923 /* 1924 * In this byte, 1925 * bit 0 -- to indicate wheather next group 1926 * in this slice is valid or not 1927 * bit 1,2 -- contains group's instance. 1928 * bit 5 -- to indicate group lookup enable status. 1929 * bit 6 -- to indicate group is WLAN. 1930 * bit 7 -- to indicate group auto expansion status. 1931 */ 1932 1933 next_group_valid = buf[fc->scache_pos] & _FIELD_GROUP_NEXT_GROUP_VALID; 1934 1935 if (buf[fc->scache_pos] & _FIELD_GROUP_AUTO_EXPANSION) { 1936 new_grp->flags = new_grp->flags | _FP_GROUP_SELECT_AUTO_EXPANSION; 1937 } 1938 1939 if (buf[fc->scache_pos] & _FIELD_GROUP_LOOKUP_ENABLED) { 1940 new_grp->flags = new_grp->flags | _FP_GROUP_LOOKUP_ENABLED; 1941 } 1942 1943 if (buf[fc->scache_pos] & _FIELD_GROUP_WLAN) { 1944 new_grp->flags = new_grp->flags | _FP_GROUP_WLAN; 1945 } 1946 1947 new_grp->instance = ((buf[fc->scache_pos] >> 1) & 0x3); 1948 fc->scache_pos++; 1949 } 1950 /* The pointer has now advanced to the "entries" section */ 1951 1952 LOG_VERBOSE(BSL_LS_BCM_FP, 1953 (BSL_META_U(unit, 1954 "Done reading slice @ %d.\n"), 1955 fc->scache_pos)); 1956 return rv; 1957 } 1958 1959 int 1960 _field_entry_info_retrieve(int unit, _field_control_t *fc, _field_stage_t *stage_fc, 1961 int multigroup, int *prev_prio, 1962 _field_entry_wb_info_t *f_ent_wb_info) 1963 { 1964 uint8 stat_present, pol_present, prio_ctrl; 1965 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 1966 uint8 part_index = 0; 1967 uint8 part_count = 0; 1968 _bcmFieldActionNoParam_t ingress_mirror_actions[] = { 1969 _bcmFieldActionNoParamMirrorIngress, 1970 _bcmFieldActionNoParamMirrorIngress1, 1971 _bcmFieldActionNoParamMirrorIngress2, 1972 _bcmFieldActionNoParamMirrorIngress3}; 1973 _bcmFieldActionNoParam_t egress_mirror_actions[] = { 1974 _bcmFieldActionNoParamMirrorEgress, 1975 _bcmFieldActionNoParamMirrorEgress1, 1976 _bcmFieldActionNoParamMirrorEgress2, 1977 _bcmFieldActionNoParamMirrorEgress3}; 1978 1979 if (f_ent_wb_info == NULL) { 1980 return BCM_E_INTERNAL; 1981 } 1982 1983 f_ent_wb_info->eid = f_ent_wb_info->sid = f_ent_wb_info->pid = 0; 1984 1985 f_ent_wb_info->color_independent = (fc->flags & _FP_COLOR_INDEPENDENT) ? 1 : 0; 1986 1987 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) { 1988 /* Read long EID and flags */ 1989 1990 f_ent_wb_info->eid |= buf[fc->scache_pos]; 1991 fc->scache_pos++; 1992 f_ent_wb_info->eid |= buf[fc->scache_pos] << 8; 1993 fc->scache_pos++; 1994 f_ent_wb_info->eid |= buf[fc->scache_pos] << 16; 1995 fc->scache_pos++; 1996 f_ent_wb_info->eid |= buf[fc->scache_pos] << 24; 1997 fc->scache_pos++; 1998 1999 prio_ctrl = buf[fc->scache_pos] & 1; 2000 stat_present = (buf[fc->scache_pos] >> 1) & 1; 2001 pol_present = (buf[fc->scache_pos] >> 2) & 1; 2002 fc->scache_pos++; 2003 } else { 2004 /* Read compact EID and flags */ 2005 2006 f_ent_wb_info->eid |= buf[fc->scache_pos]; /* EID_lo */ 2007 fc->scache_pos++; 2008 f_ent_wb_info->eid |= (buf[fc->scache_pos] & 0xF) << 8; /* EID_hi */ 2009 prio_ctrl = (buf[fc->scache_pos] >> 4) & 0x1; 2010 stat_present = (buf[fc->scache_pos] >> 5) & 0x1; 2011 pol_present = (buf[fc->scache_pos] >> 6) & 0x1; 2012 fc->scache_pos++; 2013 } 2014 2015 LOG_VERBOSE(BSL_LS_BCM_FP, 2016 (BSL_META_U(unit, 2017 "Read entry id %d @ byte %d.\n"), 2018 f_ent_wb_info->eid, fc->scache_pos - 2)); 2019 2020 if (multigroup) { 2021 fc->scache_pos += (fc->flags & _FP_STABLE_SAVE_LONG_IDS) ? 4 : 2; /* Skip over GID */ 2022 } 2023 2024 if (prio_ctrl) { 2025 f_ent_wb_info->prio = 0; 2026 f_ent_wb_info->prio |= buf[fc->scache_pos]; 2027 fc->scache_pos++; 2028 f_ent_wb_info->prio |= buf[fc->scache_pos] << 8; 2029 fc->scache_pos++; 2030 f_ent_wb_info->prio |= buf[fc->scache_pos] << 16; 2031 fc->scache_pos++; 2032 f_ent_wb_info->prio |= buf[fc->scache_pos] << 24; 2033 fc->scache_pos++; 2034 *prev_prio = f_ent_wb_info->prio; 2035 } else { 2036 f_ent_wb_info->prio = *prev_prio; 2037 } 2038 2039 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) { 2040 /* Read long policer and stat ids, if present */ 2041 2042 if (pol_present) { 2043 f_ent_wb_info->pid |= buf[fc->scache_pos]; 2044 fc->scache_pos++; 2045 f_ent_wb_info->pid |= buf[fc->scache_pos] << 8; 2046 fc->scache_pos++; 2047 f_ent_wb_info->pid |= buf[fc->scache_pos] << 16; 2048 fc->scache_pos++; 2049 f_ent_wb_info->pid |= buf[fc->scache_pos] << 24; 2050 fc->scache_pos++; 2051 } 2052 2053 if (stat_present) { 2054 f_ent_wb_info->sid |= buf[fc->scache_pos]; 2055 fc->scache_pos++; 2056 f_ent_wb_info->sid |= buf[fc->scache_pos] << 8; 2057 fc->scache_pos++; 2058 f_ent_wb_info->sid |= buf[fc->scache_pos] << 16; 2059 fc->scache_pos++; 2060 f_ent_wb_info->sid |= buf[fc->scache_pos] << 24; 2061 fc->scache_pos++; 2062 } 2063 } else { 2064 /* Read compact policer and stat ids, if present */ 2065 2066 if (pol_present) { 2067 f_ent_wb_info->pid |= buf[fc->scache_pos]; /* PID_lo */ 2068 fc->scache_pos++; 2069 } 2070 if (stat_present) { 2071 f_ent_wb_info->sid |= buf[fc->scache_pos] & 0xF; /* SID_lo */ 2072 if (pol_present) { 2073 f_ent_wb_info->pid |= (buf[fc->scache_pos] & 0xF0) << 4; /* PID_hi */ 2074 } 2075 fc->scache_pos++; 2076 f_ent_wb_info->sid |= (buf[fc->scache_pos] << 4); /* SID_hi */ 2077 fc->scache_pos++; 2078 } else if (pol_present) { 2079 f_ent_wb_info->pid |= (buf[fc->scache_pos] & 0xF0) << 4; /* PID_hi */ 2080 fc->scache_pos++; 2081 } 2082 } 2083 2084 /* Retrieve Entry part count */ 2085 if (((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_18) && 2086 ((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) || 2087 (stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) || 2088 (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP))) { 2089 part_count = buf[fc->scache_pos]; 2090 fc->scache_pos++; 2091 } else { 2092 part_count = 0; 2093 } 2094 2095 /* Retrieve DVP_tpe */ 2096 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_6) { 2097 f_ent_wb_info->dvp_type[0] = buf[fc->scache_pos]; 2098 fc->scache_pos++; 2099 part_index = 1; 2100 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_18) { 2101 for (; part_index < part_count; part_index++) { 2102 f_ent_wb_info->dvp_type[part_index] = buf[fc->scache_pos]; 2103 fc->scache_pos++; 2104 } 2105 } 2106 for (; part_index < _FP_MAX_ENTRY_WIDTH; part_index++) { 2107 f_ent_wb_info->dvp_type[part_index] = f_ent_wb_info->dvp_type[0]; 2108 } 2109 } 2110 2111 /* Retrieve SVP_type */ 2112 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_16) { 2113 f_ent_wb_info->svp_type[0] = buf[fc->scache_pos]; 2114 fc->scache_pos++; 2115 part_index = 1; 2116 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_18) { 2117 for (; part_index < part_count; part_index++) { 2118 f_ent_wb_info->svp_type[part_index] = buf[fc->scache_pos]; 2119 fc->scache_pos++; 2120 } 2121 } 2122 for (; part_index < _FP_MAX_ENTRY_WIDTH; part_index++) { 2123 f_ent_wb_info->svp_type[part_index] = f_ent_wb_info->svp_type[0]; 2124 } 2125 } 2126 2127 /*Retrieve Color Indpendent info*/ 2128 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_13) { 2129 f_ent_wb_info->color_independent = (buf[fc->scache_pos] >> 7) & 1; 2130 fc->scache_pos++; 2131 } 2132 2133 /* Retrieve Action bitmap */ 2134 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 2135 if(f_ent_wb_info->action_bmp->w == NULL) { 2136 return BCM_E_PARAM; 2137 } 2138 2139 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 2140 "Read action bitmap[0x%x] @ byte %d.\n"), 2141 buf[fc->scache_pos], fc->scache_pos)); 2142 2143 f_ent_wb_info->action_bmp->w[0] = buf[fc->scache_pos]; 2144 fc->scache_pos++; 2145 f_ent_wb_info->action_bmp->w[0] |= buf[fc->scache_pos] << 8; 2146 fc->scache_pos++; 2147 f_ent_wb_info->action_bmp->w[0] |= buf[fc->scache_pos] << 16; 2148 fc->scache_pos++; 2149 f_ent_wb_info->action_bmp->w[0] |= buf[fc->scache_pos] << 24; 2150 fc->scache_pos++; 2151 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_19) { 2152 f_ent_wb_info->action_bmp->w[1] = buf[fc->scache_pos]; 2153 fc->scache_pos++; 2154 f_ent_wb_info->action_bmp->w[1] |= buf[fc->scache_pos] << 8; 2155 fc->scache_pos++; 2156 f_ent_wb_info->action_bmp->w[1] |= buf[fc->scache_pos] << 16; 2157 fc->scache_pos++; 2158 f_ent_wb_info->action_bmp->w[1] |= buf[fc->scache_pos] << 24; 2159 fc->scache_pos++; 2160 } 2161 2162 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_16) { 2163 /* Recover IngressGportType Entry Action. */ 2164 f_ent_wb_info->ing_gport_type = buf[fc->scache_pos]; 2165 fc->scache_pos++; 2166 } 2167 2168 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_20) { 2169 uint8 index, max_index = 1; 2170 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_21) { 2171 max_index = 4; 2172 } 2173 for (index = 0 ; index < max_index ; index++) { 2174 if (SHR_BITGET(f_ent_wb_info->action_bmp->w, ingress_mirror_actions[index])) { 2175 f_ent_wb_info->ingress_mirror[index] = buf[fc->scache_pos]; 2176 fc->scache_pos++; 2177 f_ent_wb_info->ingress_mirror[index] |= buf[fc->scache_pos] << 8; 2178 fc->scache_pos++; 2179 f_ent_wb_info->ingress_mirror[index] |= buf[fc->scache_pos] << 16; 2180 fc->scache_pos++; 2181 f_ent_wb_info->ingress_mirror[index] |= buf[fc->scache_pos] << 24; 2182 fc->scache_pos++; 2183 } 2184 } 2185 for (index = 0 ; index < max_index ; index++) { 2186 if (SHR_BITGET(f_ent_wb_info->action_bmp->w, egress_mirror_actions[index])) { 2187 f_ent_wb_info->egress_mirror[index] = buf[fc->scache_pos]; 2188 fc->scache_pos++; 2189 f_ent_wb_info->egress_mirror[index] |= buf[fc->scache_pos] << 8; 2190 fc->scache_pos++; 2191 f_ent_wb_info->egress_mirror[index] |= buf[fc->scache_pos] << 16; 2192 fc->scache_pos++; 2193 f_ent_wb_info->egress_mirror[index] |= buf[fc->scache_pos] << 24; 2194 fc->scache_pos++; 2195 } 2196 } 2197 if ( SHR_BITGET(f_ent_wb_info->action_bmp->w, 2198 _bcmFieldActionNoParamFabricQueue)) { 2199 (f_ent_wb_info->action_fabricQueue_wb.cosq_gport) = 2200 buf[fc->scache_pos]; 2201 fc->scache_pos++; 2202 (f_ent_wb_info->action_fabricQueue_wb.cosq_gport) |= 2203 buf[fc->scache_pos] << 8; 2204 fc->scache_pos++; 2205 (f_ent_wb_info->action_fabricQueue_wb.cosq_gport) |= 2206 buf[fc->scache_pos] << 16; 2207 fc->scache_pos++; 2208 (f_ent_wb_info->action_fabricQueue_wb.cosq_gport) |= 2209 buf[fc->scache_pos] << 24; 2210 fc->scache_pos++; 2211 } 2212 } 2213 } 2214 2215 LOG_VERBOSE(BSL_LS_BCM_FP, 2216 (BSL_META_U(unit, 2217 "Done reading entry @ %d.\n"), 2218 fc->scache_pos)); 2219 2220 return BCM_E_NONE; 2221 } 2222 2223 /* Free the slice-specific group information after we're done with it */ 2224 void 2225 _field_scache_slice_group_free(int unit, _field_control_t *fc, 2226 int slice_num) 2227 { 2228 _field_slice_group_info_t *current = NULL; 2229 current = fc->group_arr; 2230 while (current) { 2231 fc->group_arr = current->next; 2232 sal_free(current); 2233 current = fc->group_arr; 2234 } 2235 fc->group_arr = NULL; 2236 return; 2237 } 2238 2239 #if defined(BCM_FIREBOLT2_SUPPORT) 2240 STATIC int 2241 _field_fb2_group_construct(int unit, _field_hw_qual_info_t *hw_sel, 2242 int intraslice, int paired, _field_control_t *fc, 2243 bcm_port_t port, _field_stage_id_t stage_id, 2244 int slice_idx) 2245 { 2246 int i, j, k, idx, size, selector_match, parts_count = 1, rv = BCM_E_NONE; 2247 _field_group_t *fg_ptr = fc->groups; 2248 bcm_field_group_t gid; 2249 int priority; 2250 int group_flags; 2251 _bcm_field_qual_info_t *f_qual_arr = NULL; 2252 _field_stage_t *stage_fc; 2253 _bcm_field_qual_offset_t *q_offset_arr = NULL; 2254 uint16 *qid_arr = NULL; 2255 bcm_field_qset_t qset; 2256 int action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 2257 bcm_pbmp_t group_pbmp ; 2258 2259 bcm_field_qset_t_init(&qset); 2260 2261 /* Get the stage control structure */ 2262 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc)); 2263 2264 /* Iterate over groups and compare all selectors - IFP */ 2265 fg_ptr = fc->groups; 2266 while (fg_ptr != NULL) { 2267 if (intraslice && !(fg_ptr->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 2268 fg_ptr = fg_ptr->next; 2269 continue; 2270 } 2271 if (!intraslice && (fg_ptr->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 2272 fg_ptr = fg_ptr->next; 2273 continue; 2274 } 2275 if (paired && (fg_ptr->flags & _FP_GROUP_SPAN_SINGLE_SLICE)) { 2276 fg_ptr = fg_ptr->next; 2277 continue; 2278 } 2279 if (!paired && (fg_ptr->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) { 2280 fg_ptr = fg_ptr->next; 2281 continue; 2282 } 2283 /* Check for primary slice numbers - there may be groups with the same 2284 QSET but residing in different slices */ 2285 if (slice_idx != fg_ptr->slices[0].slice_number) { 2286 fg_ptr = fg_ptr->next; 2287 continue; 2288 } 2289 /* Compare primary slice selectors */ 2290 if ((fg_ptr->sel_codes[0].fpf1 != hw_sel->pri_slice[0].fpf1) || 2291 (fg_ptr->sel_codes[0].fpf2 != hw_sel->pri_slice[0].fpf2) || 2292 (fg_ptr->sel_codes[0].fpf3 != hw_sel->pri_slice[0].fpf3) || 2293 (fg_ptr->sel_codes[0].fpf4 != hw_sel->pri_slice[0].fpf4)) { 2294 fg_ptr = fg_ptr->next; 2295 continue; 2296 } 2297 if (intraslice && (fg_ptr->sel_codes[1].fpf2 != 2298 hw_sel->pri_slice[1].fpf2)) { 2299 fg_ptr = fg_ptr->next; 2300 continue; 2301 } 2302 /* Compare secondary slice if paired */ 2303 if (paired) { 2304 if ((fg_ptr->sel_codes[2].fpf1 != hw_sel->sec_slice[0].fpf1) || 2305 (fg_ptr->sel_codes[2].fpf2 != hw_sel->sec_slice[0].fpf2) || 2306 (fg_ptr->sel_codes[2].fpf3 != hw_sel->sec_slice[0].fpf3) || 2307 (fg_ptr->sel_codes[2].fpf4 != hw_sel->sec_slice[0].fpf4)) { 2308 fg_ptr = fg_ptr->next; 2309 continue; 2310 } 2311 if (intraslice && (fg_ptr->sel_codes[3].fpf2 != 2312 hw_sel->sec_slice[1].fpf2)) { 2313 fg_ptr = fg_ptr->next; 2314 continue; 2315 } 2316 } 2317 2318 /* Found a match - add port to group pbmp */ 2319 BCM_PBMP_PORT_ADD(fg_ptr->pbmp, port); 2320 BCM_PBMP_OR(fg_ptr->slices[0].pbmp, fg_ptr->pbmp); 2321 if (paired) { 2322 BCM_PBMP_OR(fg_ptr->slices[1].pbmp, fg_ptr->pbmp); 2323 } 2324 2325 group_flags = 0; 2326 if (fc->l2warm) { 2327 /* Get stored group ID and QSET for Level 2 */ 2328 BCM_IF_ERROR_RETURN 2329 (_field_group_info_retrieve(unit, port, _FP_DEF_INST, &gid, 2330 &priority, &action_res_id, &group_pbmp, NULL, 2331 &group_flags, &qset, fc)); 2332 if (gid != -1) { 2333 sal_memcpy(&fg_ptr->qset, &qset, sizeof(bcm_field_qset_t)); 2334 fg_ptr->gid = gid; 2335 fg_ptr->priority = priority; 2336 fg_ptr->action_res_id = action_res_id; 2337 if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) { 2338 fg_ptr->flags = fg_ptr->flags | 2339 _FP_GROUP_SELECT_AUTO_EXPANSION; 2340 } 2341 2342 } 2343 } 2344 break; 2345 } 2346 if (fg_ptr == NULL) { 2347 /* No match - create a new group and populate the group structure */ 2348 _FP_XGS3_ALLOC(fg_ptr, sizeof(_field_group_t), "field group"); 2349 if (NULL == fg_ptr) { 2350 return BCM_E_MEMORY; 2351 } 2352 2353 /* Initialize action res id and VMAP group to default */ 2354 action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 2355 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 2356 fg_ptr->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 2357 } 2358 2359 group_flags = 0; 2360 if (fc->l2warm) { 2361 /* Get stored group ID and QSET for Level 2 */ 2362 rv = _field_group_info_retrieve(unit, port, _FP_DEF_INST, &gid, 2363 &priority, &action_res_id, &group_pbmp, NULL, 2364 &group_flags, &qset, fc); 2365 if (gid != -1) { 2366 sal_memcpy(&fg_ptr->qset, &qset, sizeof(bcm_field_qset_t)); 2367 } 2368 else { 2369 sal_free(fg_ptr); 2370 return rv; 2371 } 2372 } else { 2373 /* Generate group ID (a ++ operation) for Level 1 */ 2374 rv = _bcm_field_group_id_generate(unit, &gid); 2375 priority = slice_idx; 2376 } 2377 if (BCM_FAILURE(rv)) { 2378 sal_free(fg_ptr); 2379 return rv; 2380 } 2381 fg_ptr->gid = gid; 2382 fg_ptr->priority = priority; 2383 fg_ptr->action_res_id = action_res_id; 2384 if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) { 2385 fg_ptr->flags = fg_ptr->flags | _FP_GROUP_SELECT_AUTO_EXPANSION; 2386 } 2387 fg_ptr->stage_id = stage_id; 2388 fg_ptr->sel_codes[0].fpf1 = hw_sel->pri_slice[0].fpf1; 2389 fg_ptr->sel_codes[0].fpf2 = hw_sel->pri_slice[0].fpf2; 2390 fg_ptr->sel_codes[0].fpf3 = hw_sel->pri_slice[0].fpf3; 2391 fg_ptr->sel_codes[0].fpf4 = hw_sel->pri_slice[0].fpf4; 2392 fg_ptr->sel_codes[0].inner_vlan_overlay = 2393 hw_sel->pri_slice[0].inner_vlan_overlay; 2394 if (port != -1) { 2395 BCM_PBMP_PORT_ADD(fg_ptr->pbmp, port); 2396 } else { 2397 SOC_PBMP_ASSIGN(fg_ptr->pbmp, PBMP_ALL(unit)); 2398 } 2399 if (intraslice) { 2400 fg_ptr->flags |= _FP_GROUP_INTRASLICE_DOUBLEWIDE; 2401 fg_ptr->sel_codes[1].fpf2 = hw_sel->pri_slice[1].fpf2; 2402 fg_ptr->sel_codes[1].fpf4 = hw_sel->pri_slice[1].fpf4; 2403 fg_ptr->sel_codes[1].intraslice = 1; 2404 fg_ptr->sel_codes[1].inner_vlan_overlay = 2405 hw_sel->pri_slice[1].inner_vlan_overlay; 2406 } 2407 if (paired) { 2408 parts_count = 2; 2409 fg_ptr->flags |= _FP_GROUP_SPAN_DOUBLE_SLICE; 2410 fg_ptr->sel_codes[2].fpf1 = hw_sel->sec_slice[0].fpf1; 2411 fg_ptr->sel_codes[2].fpf2 = hw_sel->sec_slice[0].fpf2; 2412 fg_ptr->sel_codes[2].fpf3 = hw_sel->sec_slice[0].fpf3; 2413 fg_ptr->sel_codes[2].fpf4 = hw_sel->sec_slice[0].fpf4; 2414 fg_ptr->sel_codes[2].inner_vlan_overlay = 2415 hw_sel->sec_slice[0].inner_vlan_overlay; 2416 if (intraslice) { 2417 parts_count = 4; 2418 fg_ptr->sel_codes[3].fpf2 = hw_sel->sec_slice[1].fpf2; 2419 fg_ptr->sel_codes[3].fpf4 = hw_sel->sec_slice[1].fpf4; 2420 fg_ptr->sel_codes[3].intraslice = 1; 2421 fg_ptr->sel_codes[3].inner_vlan_overlay = 2422 hw_sel->sec_slice[1].inner_vlan_overlay; 2423 } 2424 } else { 2425 fg_ptr->flags |= _FP_GROUP_SPAN_SINGLE_SLICE; 2426 } 2427 /* Determine the QSET based on selector values */ 2428 for (i = 0; i < parts_count; i++) { 2429 for (idx = 0; idx < _bcmFieldQualifyCount; idx++) { 2430 f_qual_arr = stage_fc->f_qual_arr[idx]; 2431 if (f_qual_arr == NULL) { 2432 continue; /* Qualifier does not exist in this stage */ 2433 } 2434 if (fc->l2warm && !BCM_FIELD_QSET_TEST(fg_ptr->qset, idx)) { 2435 continue; /* Qualifier not present in the group */ 2436 } 2437 /* Go over the API level qualifier's configuration info */ 2438 for (j = 0; j < f_qual_arr->conf_sz; j++) { 2439 selector_match = 0; 2440 /* Check if it matches F1's value */ 2441 if ((f_qual_arr->conf_arr[j].selector.pri_sel == 2442 _bcmFieldSliceSelFpf1) && 2443 (f_qual_arr->conf_arr[j].selector.pri_sel_val == 2444 fg_ptr->sel_codes[i].fpf1)) { 2445 /* Qualifier found - add to group's qset and group 2446 qualifier info */ 2447 /* Tentatively add to fg->qual_arr[i] */ 2448 if (stage_id == _BCM_FIELD_STAGE_INGRESS) { 2449 if ((fg_ptr->sel_codes[i].fpf1 != 3) && 2450 (fg_ptr->sel_codes[i].fpf1 != 6)) { 2451 selector_match = 1; 2452 } else { 2453 /* Deal with inner_vlan_overlay */ 2454 if ((idx == bcmFieldQualifyInnerVlan) || 2455 (idx == bcmFieldQualifyInnerVlanId) || 2456 (idx == bcmFieldQualifyInnerVlanPri) || 2457 (idx == bcmFieldQualifyInnerVlanCfi)) { 2458 if (fg_ptr->sel_codes[i].inner_vlan_overlay 2459 == 0) { 2460 selector_match = 1; 2461 } 2462 } else if ((idx == bcmFieldQualifyVrf) || 2463 (idx == bcmFieldQualifyDstClassField) || 2464 (idx == bcmFieldQualifySrcClassL2)) { 2465 if (fg_ptr->sel_codes[i].inner_vlan_overlay 2466 == 1) { 2467 selector_match = 1; 2468 } 2469 } else { 2470 selector_match = 1; 2471 } 2472 } 2473 } else { 2474 selector_match = 1; 2475 } 2476 } 2477 /* Check if it matches F2's value */ 2478 if ((f_qual_arr->conf_arr[j].selector.pri_sel == 2479 _bcmFieldSliceSelFpf2) && 2480 (f_qual_arr->conf_arr[j].selector.pri_sel_val == 2481 fg_ptr->sel_codes[i].fpf2)) { 2482 /* Qualifier found - add to group's qset and group 2483 qualifier info */ 2484 /* Tentatively add to fg->qual_arr[i] */ 2485 selector_match = 1; 2486 } 2487 /* Check if it matches F3's value */ 2488 if ((f_qual_arr->conf_arr[j].selector.pri_sel == 2489 _bcmFieldSliceSelFpf3) && 2490 (f_qual_arr->conf_arr[j].selector.pri_sel_val == 2491 fg_ptr->sel_codes[i].fpf3)) { 2492 /* Qualifier found - add to group's qset and group 2493 qualifier info */ 2494 /* Tentatively add to fg->qual_arr[i] */ 2495 selector_match = 1; 2496 } 2497 /* Check if it matches F4's value */ 2498 if ((f_qual_arr->conf_arr[j].selector.pri_sel == 2499 _bcmFieldSliceSelFpf4) && 2500 (f_qual_arr->conf_arr[j].selector.pri_sel_val == 2501 fg_ptr->sel_codes[i].fpf4)) { 2502 /* Qualifier found - add to group's qset and group 2503 qualifier info */ 2504 /* Tentatively add to fg->qual_arr[i] */ 2505 selector_match = 1; 2506 } 2507 if (selector_match) { 2508 BCM_FIELD_QSET_ADD(fg_ptr->qset, idx); 2509 /* Allocate memory for this qualfier and its 2510 associated offset information if not already added 2511 to fg->qual_arr[i] */ 2512 /* May change later depending on the mask */ 2513 for (k = 0; k < fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; k++) { 2514 if (fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[k] == idx) { 2515 break; /* Qualifier already added */ 2516 } 2517 } 2518 if (k == fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size) { 2519 size = fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size + 1; 2520 qid_arr = NULL; 2521 _FP_XGS3_ALLOC(qid_arr, size * sizeof (uint16), 2522 "Group qual id"); 2523 if (NULL == qid_arr) { 2524 sal_free (fg_ptr); 2525 return (BCM_E_MEMORY); 2526 } 2527 q_offset_arr = NULL; 2528 _FP_XGS3_ALLOC(q_offset_arr, size * 2529 sizeof (_bcm_field_qual_offset_t), 2530 "Group qual offset"); 2531 if (NULL == q_offset_arr) { 2532 sal_free (fg_ptr); 2533 sal_free (qid_arr); 2534 return (BCM_E_MEMORY); 2535 } 2536 if (size) { 2537 sal_memcpy(qid_arr, fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr, 2538 fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size * 2539 sizeof (uint16)); 2540 sal_memcpy(q_offset_arr, 2541 fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr, 2542 fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size * 2543 sizeof (_bcm_field_qual_offset_t)); 2544 if (fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size) { 2545 sal_free(fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr); 2546 sal_free(fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr); 2547 } 2548 } 2549 fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr = qid_arr; 2550 fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr = q_offset_arr; 2551 fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[size - 1] = idx; 2552 fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[size - 1].field = 2553 f_qual_arr->conf_arr[j].offset.field; 2554 2555 sal_memcpy(&fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[size - 1], 2556 &f_qual_arr->conf_arr[j].offset, sizeof(f_qual_arr->conf_arr[j].offset)); 2557 2558 fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size = size; 2559 2560 _field_qset_udf_bmap_reinit(unit, 2561 stage_fc, 2562 &fg_ptr->qset, 2563 idx 2564 ); 2565 2566 break; /* Just added the qualifier */ 2567 } 2568 } 2569 } 2570 } 2571 } 2572 /* Associate slice(s) to group */ 2573 if (fg_ptr->slices == NULL) { 2574 fg_ptr->slices = stage_fc->slices[_FP_DEF_INST] + slice_idx; 2575 if (intraslice) { 2576 fg_ptr->slices->group_flags |= _FP_GROUP_INTRASLICE_DOUBLEWIDE; 2577 if (paired) { 2578 fg_ptr->slices[1].group_flags |= 2579 _FP_GROUP_INTRASLICE_DOUBLEWIDE; 2580 } 2581 } 2582 } 2583 2584 BCM_PBMP_OR(fg_ptr->slices[0].pbmp, fg_ptr->pbmp); 2585 if (paired) { 2586 BCM_PBMP_OR(fg_ptr->slices[1].pbmp, fg_ptr->pbmp); 2587 } 2588 2589 /* Initialize group default ASET list. */ 2590 rv = _field_group_default_aset_set(unit, fg_ptr); 2591 if (BCM_FAILURE(rv)) { 2592 return (rv); 2593 } 2594 2595 if (fc->l2warm 2596 && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15)) { 2597 if (group_flags & _FP_GROUP_LOOKUP_ENABLED) { 2598 fg_ptr->flags = fg_ptr->flags | _FP_GROUP_LOOKUP_ENABLED; 2599 } 2600 if (group_flags & _FP_GROUP_WLAN) { 2601 fg_ptr->flags = fg_ptr->flags | _FP_GROUP_WLAN; 2602 } 2603 } else { 2604 fg_ptr->flags |= _FP_GROUP_LOOKUP_ENABLED; 2605 } 2606 2607 fg_ptr->next = fc->groups; 2608 fc->groups = fg_ptr; 2609 } 2610 return rv; 2611 } 2612 2613 int 2614 _field_fb2_stage_ingress_reinit(int unit, _field_control_t *fc, 2615 _field_stage_t *stage_fc) 2616 { 2617 int idx, idx1, slice_idx, vslice_idx,index_min, index_max, ratio, rv = BCM_E_NONE; 2618 int entries_per_slice, group_found, mem_sz, parts_count, qual_idx; 2619 int i, j, k, pri_tcam_idx, part_index, slice_number, expanded[16], slice_master_idx[16]; 2620 int prev_prio, multigroup, max, master_slice; 2621 char *fp_tcam_buf = NULL; /* Buffer to read the FP_TCAM table */ 2622 char *fp_pfs_buf = NULL; /* Buffer to read the FP_PORT_FIELD_SEL table */ 2623 char *fp_policy_buf = NULL; /* Buffer to read the FP_POLICY table */ 2624 uint32 pbm, rval, paired, intraslice, dbl_wide_key, dbl_wide_key_sec; 2625 uint32 f4_sel_val, qualified, inner_vlan_overlay; 2626 uint32 *tcam_entry_buf, temp; 2627 soc_field_t fld; 2628 bcm_port_t port; 2629 fp_port_field_sel_entry_t *pfs_entry; 2630 fp_tcam_entry_t *tcam_entry; 2631 fp_policy_table_entry_t *policy_entry; 2632 _field_hw_qual_info_t hw_sels; 2633 _field_slice_t *fs; 2634 _field_group_t *fg = NULL, *group = NULL; 2635 _field_entry_t *f_ent = NULL; 2636 bcm_pbmp_t entry_pbmp, temp_pbmp; 2637 _bcm_field_qual_info_t *f_qual_arr = NULL; 2638 _field_sel_t *sel_ptr; 2639 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 2640 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 2641 uint8 old_physical_slice, slice_num; 2642 uint32 entry_flags; 2643 _field_slice_t *fs_temp = NULL; 2644 _field_action_bmp_t action_bmp; 2645 _field_entry_wb_info_t f_ent_wb_info; 2646 2647 soc_field_t en_flds[16] = 2648 {FP_SLICE_ENABLE_SLICE_0f, FP_SLICE_ENABLE_SLICE_1f, 2649 FP_SLICE_ENABLE_SLICE_2f, FP_SLICE_ENABLE_SLICE_3f, 2650 FP_SLICE_ENABLE_SLICE_4f, FP_SLICE_ENABLE_SLICE_5f, 2651 FP_SLICE_ENABLE_SLICE_6f, FP_SLICE_ENABLE_SLICE_7f, 2652 FP_SLICE_ENABLE_SLICE_8f, FP_SLICE_ENABLE_SLICE_9f, 2653 FP_SLICE_ENABLE_SLICE_10f, FP_SLICE_ENABLE_SLICE_11f, 2654 FP_SLICE_ENABLE_SLICE_12f, FP_SLICE_ENABLE_SLICE_13f, 2655 FP_SLICE_ENABLE_SLICE_14f, FP_SLICE_ENABLE_SLICE_15f}; 2656 soc_field_t lk_en_flds[16] = 2657 {FP_LOOKUP_ENABLE_SLICE_0f, FP_LOOKUP_ENABLE_SLICE_1f, 2658 FP_LOOKUP_ENABLE_SLICE_2f, FP_LOOKUP_ENABLE_SLICE_3f, 2659 FP_LOOKUP_ENABLE_SLICE_4f, FP_LOOKUP_ENABLE_SLICE_5f, 2660 FP_LOOKUP_ENABLE_SLICE_6f, FP_LOOKUP_ENABLE_SLICE_7f, 2661 FP_LOOKUP_ENABLE_SLICE_8f, FP_LOOKUP_ENABLE_SLICE_9f, 2662 FP_LOOKUP_ENABLE_SLICE_10f, FP_LOOKUP_ENABLE_SLICE_11f, 2663 FP_LOOKUP_ENABLE_SLICE_12f, FP_LOOKUP_ENABLE_SLICE_13f, 2664 FP_LOOKUP_ENABLE_SLICE_14f, FP_LOOKUP_ENABLE_SLICE_15f}; 2665 2666 2667 fc->scache_pos = 0; 2668 fc->scache_pos1 = 0; 2669 2670 /* Reset Action bitmap to NULL. */ 2671 action_bmp.w = NULL; 2672 2673 if (fc->l2warm) { 2674 if ((fc->wb_recovered_version) > (fc->wb_current_version)) { 2675 /* Notify the application with an event */ 2676 /* The application will then need to reconcile the 2677 version differences using the documented behavioral 2678 differences on per module (handle) basis */ 2679 SOC_IF_ERROR_RETURN 2680 (soc_event_generate(unit, SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE, 2681 BCM_MODULE_FIELD, (fc->wb_recovered_version), 2682 (fc->wb_current_version))); 2683 } 2684 2685 fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE; 2686 2687 if(NULL != fc->scache_ptr[_FIELD_SCACHE_PART_1]) { 2688 if ((fc->wb_recovered_version) > (fc->wb_current_version)) { 2689 /* Notify the application with an event */ 2690 /* The application will then need to reconcile the 2691 version differences using the documented behavioral 2692 differences on per module (handle) basis */ 2693 SOC_IF_ERROR_RETURN 2694 (soc_event_generate(unit, 2695 SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE, 2696 BCM_MODULE_FIELD, (fc->wb_recovered_version), 2697 (fc->wb_current_version))); 2698 } 2699 2700 fc->scache_pos1 += SOC_WB_SCACHE_CONTROL_SIZE; 2701 } 2702 2703 2704 } 2705 2706 SOC_PBMP_CLEAR(entry_pbmp); 2707 sal_memset(expanded, 0, 16 * sizeof(int)); 2708 sal_memset(slice_master_idx, 0, 16 * sizeof(int)); 2709 2710 if (fc->l2warm) { 2711 rv = _field_scache_stage_hdr_chk(fc, _FIELD_IFP_DATA_START); 2712 if (BCM_FAILURE(rv)) { 2713 return (rv); 2714 } 2715 } 2716 2717 /* DMA various tables */ 2718 fp_tcam_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, FP_TCAMm), 2719 "FP TCAM buffer"); 2720 if (NULL == fp_tcam_buf) { 2721 return BCM_E_MEMORY; 2722 } 2723 index_min = soc_mem_index_min(unit, FP_TCAMm); 2724 index_max = soc_mem_index_max(unit, FP_TCAMm); 2725 if ((rv = soc_mem_read_range(unit, FP_TCAMm, MEM_BLOCK_ALL, 2726 index_min, index_max, fp_tcam_buf)) < 0 ) { 2727 goto cleanup; 2728 } 2729 fp_pfs_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, 2730 FP_PORT_FIELD_SELm), 2731 "FP PORT_FIELD_SEL buffer"); 2732 if (NULL == fp_pfs_buf) { 2733 rv = BCM_E_MEMORY; 2734 goto cleanup; 2735 } 2736 index_min = soc_mem_index_min(unit, FP_PORT_FIELD_SELm); 2737 index_max = soc_mem_index_max(unit, FP_PORT_FIELD_SELm); 2738 if ((rv = soc_mem_read_range(unit, FP_PORT_FIELD_SELm, MEM_BLOCK_ALL, 2739 index_min, index_max, fp_pfs_buf)) < 0 ) { 2740 goto cleanup; 2741 } 2742 fp_policy_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES 2743 (unit, FP_POLICY_TABLEm), 2744 "FP POLICY TABLE buffer"); 2745 if (NULL == fp_policy_buf) { 2746 rv = BCM_E_MEMORY; 2747 goto cleanup; 2748 } 2749 index_min = soc_mem_index_min(unit, FP_POLICY_TABLEm); 2750 index_max = soc_mem_index_max(unit, FP_POLICY_TABLEm); 2751 if ((rv = soc_mem_read_range(unit, FP_POLICY_TABLEm, MEM_BLOCK_ALL, 2752 index_min, index_max, fp_policy_buf)) < 0 ) { 2753 goto cleanup; 2754 } 2755 2756 entries_per_slice = 256; 2757 2758 if ((rv = READ_FP_F4_SELECTr(unit, &f4_sel_val)) < 0) { 2759 goto cleanup; 2760 } 2761 2762 /* Recover range checkers */ 2763 rv = _field_range_check_reinit(unit, stage_fc, fc); 2764 if (BCM_FAILURE(rv)) { 2765 goto cleanup; 2766 } 2767 2768 /* Recover data qualifiers */ 2769 rv = _field_data_qual_recover(unit, fc, stage_fc); 2770 if (BCM_FAILURE(rv)) { 2771 goto cleanup; 2772 } 2773 2774 /* Get per-device selectors */ 2775 if ((rv = READ_ING_MISC_CONFIG2r(unit, &rval)) < 0) { 2776 goto cleanup; 2777 } 2778 inner_vlan_overlay = soc_reg_field_get(unit, ING_MISC_CONFIG2r, rval, 2779 FP_INNER_VLAN_OVERLAY_ENABLEf); 2780 2781 /* Get slice expansion status and virtual map */ 2782 if ((rv = _field_slice_expanded_status_get(unit, fc, stage_fc, 2783 expanded, slice_master_idx)) < 0) { 2784 goto cleanup; 2785 } 2786 2787 /* Iterate over the slices */ 2788 if ((rv = READ_FP_SLICE_ENABLEr(unit, &rval)) < 0) { 2789 goto cleanup; 2790 } 2791 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 2792 /* Ignore disabled slice */ 2793 if ((soc_reg_field_get 2794 (unit, FP_SLICE_ENABLEr, rval, en_flds[slice_idx]) == 0) || 2795 (soc_reg_field_get 2796 (unit, FP_SLICE_ENABLEr, rval, lk_en_flds[slice_idx]) == 0)) { 2797 continue; 2798 } 2799 /* Ignore secondary slice in paired mode */ 2800 pfs_entry = soc_mem_table_idx_to_pointer(unit, FP_PORT_FIELD_SELm, 2801 fp_port_field_sel_entry_t *, 2802 fp_pfs_buf, 0); 2803 fld = _fb2_slice_pairing_field[slice_idx / 2]; 2804 paired = soc_FP_PORT_FIELD_SELm_field32_get(unit, 2805 pfs_entry, fld); 2806 fld = _fb2_slice_wide_mode_field[slice_idx]; 2807 intraslice = soc_FP_PORT_FIELD_SELm_field32_get(unit, 2808 pfs_entry, fld); 2809 if (paired && (slice_idx % 2)) { 2810 continue; 2811 } 2812 2813 /* Don't need to read selectors for expanded slice */ 2814 if (expanded[slice_idx]) { 2815 continue; 2816 } 2817 2818 /* Skip if slice has no valid groups and entries */ 2819 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 2820 for (idx = 0; idx < fs->entry_count; idx++) { 2821 tcam_entry = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 2822 fp_tcam_entry_t *, 2823 fp_tcam_buf, idx + 2824 entries_per_slice * 2825 slice_idx); 2826 if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) != 0) { 2827 break; 2828 } 2829 } 2830 if ((idx == fs->entry_count) && !fc->l2warm) { 2831 continue; 2832 } 2833 2834 /* If Level 2, retrieve the GIDs in this slice */ 2835 if (fc->l2warm) { 2836 rv = _field_scache_slice_group_recover(unit, fc, slice_idx, 2837 &multigroup); 2838 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 2839 fc->l2warm = 0; 2840 goto cleanup; 2841 } 2842 if (rv == BCM_E_NOT_FOUND) { 2843 rv = BCM_E_NONE; 2844 continue; 2845 } 2846 } 2847 2848 /* Iterate over FP_PORT_FIELD_SEL for all ports and this slice 2849 * to identify bins for selectors (also groups for level 1) */ 2850 PBMP_ALL_ITER(unit, port) { 2851 sal_memset(&hw_sels, 0, sizeof(_field_hw_qual_info_t)); 2852 pfs_entry = soc_mem_table_idx_to_pointer 2853 (unit, FP_PORT_FIELD_SELm, 2854 fp_port_field_sel_entry_t *, fp_pfs_buf, port); 2855 /* Get primary slice's selectors */ 2856 hw_sels.pri_slice[0].fpf1 = soc_FP_PORT_FIELD_SELm_field32_get(unit, 2857 pfs_entry, _fb_field_tbl[slice_idx][0]); 2858 hw_sels.pri_slice[0].fpf2 = soc_FP_PORT_FIELD_SELm_field32_get(unit, 2859 pfs_entry, _fb_field_tbl[slice_idx][1]); 2860 hw_sels.pri_slice[0].fpf3 = soc_FP_PORT_FIELD_SELm_field32_get(unit, 2861 pfs_entry, _fb_field_tbl[slice_idx][2]); 2862 hw_sels.pri_slice[0].fpf4 = soc_reg_field_get(unit, 2863 FP_F4_SELECTr, f4_sel_val, 2864 _fb_ing_f4_reg[slice_idx]); 2865 hw_sels.pri_slice[0].inner_vlan_overlay = inner_vlan_overlay; 2866 /* If intraslice, get double-wide key - only 2 options */ 2867 if (intraslice) { 2868 dbl_wide_key = soc_FP_PORT_FIELD_SELm_field32_get(unit, 2869 pfs_entry, _fb2_ifp_double_wide_key[slice_idx]); 2870 hw_sels.pri_slice[1].intraslice = 1; 2871 hw_sels.pri_slice[1].fpf2 = dbl_wide_key; 2872 hw_sels.pri_slice[1].fpf4 = dbl_wide_key; 2873 hw_sels.pri_slice[1].inner_vlan_overlay = inner_vlan_overlay; 2874 } 2875 /* If paired, get secondary slice's selectors */ 2876 if (paired) { 2877 hw_sels.sec_slice[0].fpf1 = soc_FP_PORT_FIELD_SELm_field32_get 2878 (unit, pfs_entry, 2879 _fb_field_tbl[slice_idx + 1][0]); 2880 hw_sels.sec_slice[0].fpf2 = soc_FP_PORT_FIELD_SELm_field32_get 2881 (unit, pfs_entry, 2882 _fb_field_tbl[slice_idx + 1][1]); 2883 hw_sels.sec_slice[0].fpf3 = soc_FP_PORT_FIELD_SELm_field32_get 2884 (unit, pfs_entry, 2885 _fb_field_tbl[slice_idx + 1][2]); hw_sels.sec_slice[0].fpf4 = soc_reg_field_get(unit, 2886 FP_F4_SELECTr, f4_sel_val, 2887 _fb_ing_f4_reg[slice_idx + 1]); 2888 hw_sels.sec_slice[0].inner_vlan_overlay = inner_vlan_overlay; 2889 if (intraslice) { 2890 dbl_wide_key_sec = soc_FP_PORT_FIELD_SELm_field32_get 2891 (unit, pfs_entry, _fb2_ifp_double_wide_key[slice_idx]); 2892 hw_sels.sec_slice[1].intraslice = 1; 2893 hw_sels.sec_slice[1].fpf2 = dbl_wide_key_sec; 2894 hw_sels.sec_slice[1].fpf4 = dbl_wide_key_sec; 2895 hw_sels.sec_slice[1].inner_vlan_overlay = inner_vlan_overlay; 2896 } 2897 } 2898 /* Create a group based on HW qualifiers (or find existing) */ 2899 rv = _field_fb2_group_construct(unit, &hw_sels, intraslice, 2900 paired, fc, port, 2901 _BCM_FIELD_STAGE_INGRESS, 2902 slice_idx); 2903 if (BCM_FAILURE(rv)) { 2904 goto cleanup; 2905 } 2906 } 2907 /* Now go over the entries in this slice */ 2908 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 2909 if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 2910 ratio = 2; 2911 fs->free_count >>= 1; 2912 } else { 2913 ratio = 1; 2914 } 2915 prev_prio = -1; 2916 for (idx = 0; idx < fs->entry_count / ratio; idx++) { 2917 group_found = 0; 2918 tcam_entry = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 2919 fp_tcam_entry_t *, 2920 fp_tcam_buf, idx + 2921 entries_per_slice * 2922 slice_idx); 2923 if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) == 0) { 2924 continue; 2925 } 2926 /* Check which ports are applicable to this entry */ 2927 SOC_PBMP_CLEAR(entry_pbmp); 2928 if ((soc_FP_TCAMm_field32_get(unit, tcam_entry, IPBM_SELf)) && 2929 (soc_FP_TCAMm_field32_get(unit, tcam_entry, 2930 IPBM_SEL_MASKf))) { 2931 pbm = soc_FP_TCAMm_field32_get(unit, tcam_entry, F1f) & 2932 soc_FP_TCAMm_field32_get(unit, tcam_entry, F1_MASKf); 2933 SOC_PBMP_WORD_SET(entry_pbmp, 0, pbm); 2934 } else if ((f4_sel_val == 0) && 2935 soc_FP_TCAMm_field32_get(unit, tcam_entry, F4_MASKf)) { 2936 pbm = soc_FP_TCAMm_field32_get(unit, tcam_entry, F4f) & 2937 soc_FP_TCAMm_field32_get(unit, tcam_entry, F4_MASKf); 2938 SOC_PBMP_PORT_ADD(entry_pbmp, pbm); 2939 } else { 2940 SOC_PBMP_ASSIGN(entry_pbmp, PBMP_ALL(unit)); 2941 } 2942 /* Search groups to find match */ 2943 fg = fc->groups; 2944 while (fg != NULL) { 2945 /* Check if group is in this slice */ 2946 fs = &fg->slices[0]; 2947 if (fs->slice_number != slice_idx) { 2948 fg = fg->next; 2949 continue; 2950 } 2951 /* Check if entry_pbmp is a subset of group pbmp */ 2952 SOC_PBMP_ASSIGN(temp_pbmp, fg->pbmp); 2953 SOC_PBMP_OR(temp_pbmp, PBMP_LB(unit)); 2954 SOC_PBMP_AND(temp_pbmp, entry_pbmp); 2955 if (SOC_PBMP_EQ(temp_pbmp, entry_pbmp)) { 2956 group_found = 1; 2957 break; 2958 } 2959 fg = fg->next; 2960 } 2961 if (!group_found) { 2962 return BCM_E_INTERNAL; /* Should never happen */ 2963 } 2964 /* Allocate memory for the entry */ 2965 rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id, 2966 fg->flags, &parts_count); 2967 if (BCM_FAILURE(rv)) { 2968 goto cleanup; 2969 } 2970 mem_sz = parts_count * sizeof (_field_entry_t); 2971 _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry"); 2972 if (f_ent == NULL) { 2973 rv = BCM_E_MEMORY; 2974 goto cleanup; 2975 } 2976 for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) { 2977 f_ent->policer[idx1].pid = _FP_INVALID_INDEX; 2978 } 2979 2980 sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t)); 2981 f_ent_wb_info.sid = f_ent_wb_info.pid = -1; 2982 if (fc->l2warm) { 2983 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 2984 action_bmp.w = NULL; 2985 _FP_XGS3_ALLOC(action_bmp.w, 2986 SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount), 2987 "Action No Param Bitmap"); 2988 if (action_bmp.w == NULL) { 2989 rv = BCM_E_MEMORY; 2990 sal_free(f_ent); 2991 goto cleanup; 2992 } 2993 } 2994 f_ent_wb_info.action_bmp = &action_bmp; 2995 2996 rv = _field_entry_info_retrieve(unit, fc, stage_fc, 2997 multigroup, &prev_prio, 2998 &f_ent_wb_info); 2999 3000 if (BCM_FAILURE(rv)) { 3001 sal_free(f_ent); 3002 goto cleanup; 3003 } 3004 } else { 3005 _bcm_field_last_alloc_eid_incr(unit); 3006 } 3007 vslice_idx = _field_physical_to_virtual(unit, _FP_DEF_INST, 3008 slice_idx, stage_fc); 3009 if (vslice_idx == -1) { 3010 rv = BCM_E_INTERNAL; 3011 sal_free(f_ent); 3012 goto cleanup; 3013 } 3014 pri_tcam_idx = idx + entries_per_slice * slice_idx; 3015 for (i = 0; i < parts_count; i++) { 3016 if (fc->l2warm) { 3017 /* Use retrieved EID */ 3018 f_ent[i].eid = f_ent_wb_info.eid; 3019 /* Set retrieved dvp_type and svp_type */ 3020 f_ent[i].dvp_type = f_ent_wb_info.dvp_type[i]; 3021 f_ent[i].svp_type = f_ent_wb_info.svp_type[i]; 3022 f_ent[i].prio = f_ent_wb_info.prio; 3023 } else { 3024 f_ent[i].eid = _bcm_field_last_alloc_eid_get(unit); 3025 f_ent[i].prio = (vslice_idx << 10) | (entries_per_slice - idx); 3026 } 3027 f_ent[i].group = fg; 3028 rv = _bcm_field_tcam_part_to_entry_flags(unit, i, fg, 3029 &f_ent[i].flags); 3030 if (BCM_FAILURE(rv)) { 3031 sal_free(f_ent); 3032 goto cleanup; 3033 } 3034 if (f_ent_wb_info.color_independent) { 3035 f_ent[i].flags |= _FP_ENTRY_COLOR_INDEPENDENT; 3036 } 3037 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 3038 pri_tcam_idx, 3039 i, &part_index); 3040 if (BCM_FAILURE(rv)) { 3041 sal_free(f_ent); 3042 goto cleanup; 3043 } 3044 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc, 3045 _FP_DEF_INST, 3046 part_index, 3047 &slice_number, 3048 (int *)&f_ent[i].slice_idx); 3049 if (BCM_FAILURE(rv)) { 3050 sal_free(f_ent); 3051 goto cleanup; 3052 } 3053 f_ent[i].fs = stage_fc->slices[_FP_DEF_INST] + slice_number; 3054 BCM_PBMP_OR(f_ent[i].fs->pbmp, fg->pbmp); 3055 if (0 == (f_ent[i].flags & _FP_ENTRY_SECOND_HALF)) { 3056 /* Decrement slice free entry count for primary 3057 entries. */ 3058 f_ent[i].fs->free_count--; 3059 } 3060 /* Assign entry to a slice */ 3061 f_ent[i].fs->entries[f_ent[i].slice_idx] = f_ent + i; 3062 f_ent[i].flags |= _FP_ENTRY_INSTALLED; 3063 3064 if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) == 3) { 3065 f_ent[i].flags |= _FP_ENTRY_ENABLED; 3066 } 3067 3068 /* tcam_entry_buf must point to the entry part */ 3069 tcam_entry_buf = (uint32 *)soc_mem_table_idx_to_pointer 3070 (unit, FP_TCAMm, 3071 fp_tcam_entry_t *, 3072 fp_tcam_buf, part_index); 3073 3074 /* Use this part to determine fg->qual_arr[i] */ 3075 /* Iterate over the HW qualifiers and match offsets with 3076 the non-zero masks */ 3077 for (j = 0; j < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) { 3078 qual_idx = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j]; 3079 f_qual_arr = stage_fc->f_qual_arr[qual_idx]; 3080 /* Loop over configurations of this qualifier */ 3081 for (k = 0; k < f_qual_arr->conf_sz; k++) { 3082 if (_mask_is_set(unit, &f_qual_arr->conf_arr[k].offset, 3083 tcam_entry_buf, _BCM_FIELD_STAGE_INGRESS)) { 3084 qualified = 0; 3085 sel_ptr = NULL; 3086 switch (i) { 3087 case 0: 3088 sel_ptr = &hw_sels.pri_slice[0]; 3089 break; 3090 case 1: 3091 if (fs->group_flags & 3092 _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 3093 sel_ptr = &hw_sels.pri_slice[1]; 3094 } else { 3095 sel_ptr = &hw_sels.sec_slice[0]; 3096 } 3097 break; 3098 case 2: 3099 sel_ptr = &hw_sels.sec_slice[0]; 3100 break; 3101 case 3: 3102 sel_ptr = &hw_sels.sec_slice[1]; 3103 break; 3104 default: 3105 break; 3106 } 3107 if (((f_qual_arr->conf_arr[k].selector.pri_sel == 3108 _bcmFieldSliceSelFpf1) && 3109 (f_qual_arr->conf_arr[k].selector.pri_sel_val 3110 == sel_ptr->fpf1)) || 3111 ((f_qual_arr->conf_arr[k].selector.pri_sel == 3112 _bcmFieldSliceSelFpf2) && 3113 (f_qual_arr->conf_arr[k].selector.pri_sel_val 3114 == sel_ptr->fpf2)) || 3115 ((f_qual_arr->conf_arr[k].selector.pri_sel == 3116 _bcmFieldSliceSelFpf3) && 3117 (f_qual_arr->conf_arr[k].selector.pri_sel_val 3118 == sel_ptr->fpf3)) || 3119 ((f_qual_arr->conf_arr[k].selector.pri_sel == 3120 _bcmFieldSliceSelFpf4) && 3121 (f_qual_arr->conf_arr[k].selector.pri_sel_val 3122 == sel_ptr->fpf4))) { 3123 qualified = 1; 3124 } 3125 if (qualified) { 3126 sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j], 3127 &f_qual_arr->conf_arr[k].offset, 3128 sizeof(f_qual_arr->conf_arr[k].offset)); 3129 } 3130 break; 3131 } 3132 } 3133 } 3134 /* Get the actions associated with this part of the entry */ 3135 policy_entry = soc_mem_table_idx_to_pointer 3136 (unit, FP_POLICY_TABLEm, 3137 fp_policy_table_entry_t *, 3138 fp_policy_buf, part_index); 3139 rv = _field_fb_actions_recover(unit, (uint32 *)policy_entry, 3140 f_ent, i, FP_POLICY_TABLEm, 3141 &f_ent_wb_info); 3142 if (BCM_FAILURE(rv)) { 3143 sal_free(f_ent); 3144 goto cleanup; 3145 } 3146 if (action_bmp.w != NULL) { 3147 _FP_ACTION_BMP_FREE(action_bmp); 3148 action_bmp.w = NULL; 3149 } 3150 } 3151 /* Add to the group */ 3152 rv = _field_group_entry_add(unit, fg, f_ent); 3153 if (BCM_FAILURE(rv)) { 3154 sal_free(f_ent); 3155 goto cleanup; 3156 } 3157 f_ent = NULL; 3158 } 3159 /* Free up the temporary slice group info */ 3160 if (fc->l2warm) { 3161 _field_scache_slice_group_free(unit, fc, slice_idx); 3162 } 3163 } 3164 3165 /* Now go over the expanded slices */ 3166 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 3167 if (!expanded[slice_idx]) { 3168 continue; 3169 } 3170 /* Skip if slice has no valid groups and entries */ 3171 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 3172 for (idx = 0; idx < fs->entry_count; idx++) { 3173 tcam_entry = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 3174 fp_tcam_entry_t *, 3175 fp_tcam_buf, idx + 3176 entries_per_slice * 3177 slice_idx); 3178 if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) != 0) { 3179 break; 3180 } 3181 } 3182 if (idx == fs->entry_count){ 3183 continue; 3184 } 3185 /* If Level 2, retrieve the GIDs in this slice */ 3186 if (fc->l2warm) { 3187 rv = _field_scache_slice_group_recover(unit, fc, slice_idx, 3188 &multigroup); 3189 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 3190 fc->l2warm = 0; 3191 goto cleanup; 3192 } 3193 if (rv == BCM_E_NOT_FOUND) { 3194 rv = BCM_E_NONE; 3195 continue; 3196 } 3197 } 3198 /* Now find the master slice for this virtual group */ 3199 vslice_idx = _field_physical_to_virtual(unit, _FP_DEF_INST, 3200 slice_idx, stage_fc); 3201 if (vslice_idx == -1) { 3202 /* vslice_idx - Must be a valid hardware slice index value */ 3203 rv = BCM_E_INTERNAL; 3204 goto cleanup; 3205 } 3206 3207 if (fc->l2warm 3208 && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_8)) { 3209 master_slice = slice_master_idx[slice_idx]; 3210 } else { 3211 max = -1; 3212 for (i = 0; i < stage_fc->tcam_slices; i++) { 3213 if ((stage_fc->vmap[_FP_DEF_INST][0][vslice_idx].virtual_group == 3214 stage_fc->vmap[_FP_DEF_INST][0][i].virtual_group) && (i != vslice_idx)) { 3215 if (i > max) { 3216 max = i; 3217 } 3218 } 3219 } 3220 3221 /* max - Must be a valid hardware slice index value */ 3222 if (-1 == max) { 3223 rv = BCM_E_INTERNAL; 3224 goto cleanup; 3225 } 3226 3227 master_slice = stage_fc->vmap[_FP_DEF_INST][0][max].vmap_key; 3228 } 3229 /* See which group is in this slice - can be only one */ 3230 fg = fc->groups; 3231 while (fg != NULL) { 3232 /* Check if group is in this slice */ 3233 fs = &fg->slices[0]; 3234 if ((fg->stage_id == stage_fc->stage_id) 3235 && (fs->slice_number == master_slice)) { 3236 break; 3237 } 3238 fg = fg->next; 3239 } 3240 if (fg == 0) { 3241 rv = BCM_E_INTERNAL; 3242 goto cleanup; 3243 } 3244 3245 /* Get number of entry parts for the group. */ 3246 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 3247 fg->flags, &parts_count); 3248 BCM_IF_ERROR_RETURN(rv); 3249 3250 old_physical_slice = fs->slice_number; 3251 3252 /* Set up the new physical slice parameters in Software */ 3253 for(part_index = parts_count - 1; part_index >= 0; part_index--) { 3254 /* Get entry flags. */ 3255 rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, fg, &entry_flags); 3256 BCM_IF_ERROR_RETURN(rv); 3257 3258 /* Get slice id for entry part */ 3259 rv = _bcm_field_tcam_part_to_slice_number(unit, part_index, 3260 fg, &slice_num); 3261 BCM_IF_ERROR_RETURN(rv); 3262 3263 /* Get slice pointer. */ 3264 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx 3265 + slice_num; 3266 3267 if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) { 3268 /* Set per slice configuration & number of free entries in the slice.*/ 3269 fs->free_count = fs->entry_count; 3270 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 3271 fs->free_count >>= 1; 3272 } 3273 /* Set group flags in in slice.*/ 3274 fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK; 3275 3276 /* Add slice to slices linked list . */ 3277 fs_temp = stage_fc->slices[_FP_DEF_INST] + old_physical_slice + slice_num; 3278 /* To handle more than one auto expanded slice in a group */ 3279 while (fs_temp->next != NULL) { 3280 fs_temp = fs_temp->next; 3281 } 3282 fs_temp->next = fs; 3283 fs->prev = fs_temp; 3284 } 3285 } 3286 3287 /* Now go over the entries in this slice */ 3288 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 3289 if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 3290 ratio = 2; 3291 } else { 3292 ratio = 1; 3293 } 3294 prev_prio = -1; 3295 for (idx = 0; idx < fs->entry_count / ratio; idx++) { 3296 group_found = 0; 3297 tcam_entry = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 3298 fp_tcam_entry_t *, 3299 fp_tcam_buf, idx + 3300 entries_per_slice * 3301 slice_idx); 3302 if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) == 0) { 3303 continue; 3304 } 3305 /* Check which ports are applicable to this entry */ 3306 SOC_PBMP_CLEAR(entry_pbmp); 3307 if ((soc_FP_TCAMm_field32_get(unit, tcam_entry, IPBM_SELf)) && 3308 (soc_FP_TCAMm_field32_get(unit, tcam_entry, 3309 IPBM_SEL_MASKf))) { 3310 pbm = soc_FP_TCAMm_field32_get(unit, tcam_entry, F1f) & 3311 soc_FP_TCAMm_field32_get(unit, tcam_entry, F1_MASKf); 3312 SOC_PBMP_WORD_SET(entry_pbmp, 0, pbm); 3313 } else if ((f4_sel_val == 0) && 3314 soc_FP_TCAMm_field32_get(unit, tcam_entry, F4_MASKf)) { 3315 pbm = soc_FP_TCAMm_field32_get(unit, tcam_entry, F4f) & 3316 soc_FP_TCAMm_field32_get(unit, tcam_entry, F4_MASKf); 3317 SOC_PBMP_PORT_ADD(entry_pbmp, pbm); 3318 } else { 3319 SOC_PBMP_ASSIGN(entry_pbmp, PBMP_ALL(unit)); 3320 } 3321 /* Search groups to find match */ 3322 fg = fc->groups; 3323 while (fg != NULL) { 3324 /* Check if group is in this slice */ 3325 fs = &fg->slices[0]; 3326 if ((fg->stage_id != stage_fc->stage_id) 3327 || (fs->slice_number != master_slice)) { 3328 fg = fg->next; 3329 continue; 3330 } 3331 /* Check if entry_pbmp is a subset of group pbmp */ 3332 SOC_PBMP_ASSIGN(temp_pbmp, fg->pbmp); 3333 SOC_PBMP_OR(temp_pbmp, PBMP_LB(unit)); 3334 SOC_PBMP_AND(temp_pbmp, entry_pbmp); 3335 if (SOC_PBMP_EQ(temp_pbmp, entry_pbmp)) { 3336 group_found = 1; 3337 break; 3338 } 3339 fg = fg->next; 3340 } 3341 if (!group_found) { 3342 return BCM_E_INTERNAL; /* Should never happen */ 3343 } 3344 /* Allocate memory for the entry */ 3345 /* coverity[forward_null : FALSE] */ 3346 rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id, 3347 fg->flags, &parts_count); 3348 if (BCM_FAILURE(rv)) { 3349 goto cleanup; 3350 } 3351 mem_sz = parts_count * sizeof (_field_entry_t); 3352 _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry"); 3353 if (f_ent == NULL) { 3354 rv = BCM_E_MEMORY; 3355 goto cleanup; 3356 } 3357 for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) { 3358 f_ent->policer[idx1].pid = _FP_INVALID_INDEX; 3359 } 3360 3361 sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t)); 3362 f_ent_wb_info.sid = f_ent_wb_info.pid = -1; 3363 if (fc->l2warm) { 3364 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 3365 action_bmp.w = NULL; 3366 _FP_XGS3_ALLOC(action_bmp.w, 3367 SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount), 3368 "Action No Param Bitmap"); 3369 if (action_bmp.w == NULL) { 3370 rv = BCM_E_MEMORY; 3371 sal_free(f_ent); 3372 goto cleanup; 3373 } 3374 } 3375 f_ent_wb_info.action_bmp = &action_bmp; 3376 3377 rv = _field_entry_info_retrieve(unit, fc, stage_fc, 3378 multigroup, &prev_prio, 3379 &f_ent_wb_info); 3380 3381 if (BCM_FAILURE(rv)) { 3382 sal_free(f_ent); 3383 goto cleanup; 3384 } 3385 } else { 3386 _bcm_field_last_alloc_eid_incr(unit); 3387 } 3388 pri_tcam_idx = idx + entries_per_slice * slice_idx; 3389 for (i = 0; i < parts_count; i++) { 3390 if (fc->l2warm) { 3391 /* Use retrieved EID */ 3392 f_ent[i].eid = f_ent_wb_info.eid; 3393 /* Set retrieved dvp_type and svp_type */ 3394 f_ent[i].dvp_type = f_ent_wb_info.dvp_type[i]; 3395 f_ent[i].svp_type = f_ent_wb_info.svp_type[i]; 3396 f_ent[i].prio = f_ent_wb_info.prio; 3397 } else { 3398 f_ent[i].eid = _bcm_field_last_alloc_eid_get(unit); 3399 f_ent[i].prio = (vslice_idx << 10) | (entries_per_slice - idx); 3400 } 3401 f_ent[i].group = fg; 3402 rv = _bcm_field_tcam_part_to_entry_flags(unit, i, fg, 3403 &f_ent[i].flags); 3404 if (BCM_FAILURE(rv)) { 3405 sal_free(f_ent); 3406 goto cleanup; 3407 } 3408 if (f_ent_wb_info.color_independent) { 3409 f_ent[i].flags |= _FP_ENTRY_COLOR_INDEPENDENT; 3410 } 3411 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 3412 pri_tcam_idx, 3413 i, &part_index); 3414 if (BCM_FAILURE(rv)) { 3415 sal_free(f_ent); 3416 goto cleanup; 3417 } 3418 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc, 3419 _FP_DEF_INST, 3420 part_index, 3421 &slice_number, 3422 (int *)&f_ent[i].slice_idx); 3423 if (BCM_FAILURE(rv)) { 3424 sal_free(f_ent); 3425 goto cleanup; 3426 } 3427 f_ent[i].fs = stage_fc->slices[_FP_DEF_INST] + slice_number; 3428 BCM_PBMP_OR(f_ent[i].fs->pbmp, fg->pbmp); 3429 if (0 == (f_ent[i].flags & _FP_ENTRY_SECOND_HALF)) { 3430 /* Decrement slice free entry count for primary 3431 entries. */ 3432 f_ent[i].fs->free_count--; 3433 } 3434 /* Assign entry to a slice */ 3435 f_ent[i].fs->entries[f_ent[i].slice_idx] = f_ent + i; 3436 f_ent[i].flags |= _FP_ENTRY_INSTALLED; 3437 3438 if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) == 3) { 3439 f_ent[i].flags |= _FP_ENTRY_ENABLED; 3440 } 3441 3442 /* tcam_entry_buf must point to the entry part */ 3443 tcam_entry_buf = (uint32 *)soc_mem_table_idx_to_pointer 3444 (unit, FP_TCAMm, 3445 fp_tcam_entry_t *, 3446 fp_tcam_buf, part_index); 3447 3448 /* Use this part to determine fg->qual_arr[i] */ 3449 /* Iterate over the HW qualifiers and match offsets with 3450 the non-zero masks */ 3451 for (j = 0; j < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) { 3452 qual_idx = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j]; 3453 f_qual_arr = stage_fc->f_qual_arr[qual_idx]; 3454 /* Loop over configurations of this qualifier */ 3455 for (k = 0; k < f_qual_arr->conf_sz; k++) { 3456 if (_mask_is_set(unit, &f_qual_arr->conf_arr[k].offset, 3457 tcam_entry_buf, _BCM_FIELD_STAGE_INGRESS)) { 3458 qualified = 0; 3459 sel_ptr = NULL; 3460 switch (i) { 3461 case 0: 3462 sel_ptr = &hw_sels.pri_slice[0]; 3463 break; 3464 case 1: 3465 if (fs->group_flags & 3466 _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 3467 sel_ptr = &hw_sels.pri_slice[1]; 3468 } else { 3469 sel_ptr = &hw_sels.sec_slice[0]; 3470 } 3471 break; 3472 case 2: 3473 sel_ptr = &hw_sels.sec_slice[0]; 3474 break; 3475 case 3: 3476 sel_ptr = &hw_sels.sec_slice[1]; 3477 break; 3478 default: 3479 break; 3480 } 3481 if (((f_qual_arr->conf_arr[k].selector.pri_sel == 3482 _bcmFieldSliceSelFpf1) && 3483 (f_qual_arr->conf_arr[k].selector.pri_sel_val 3484 == sel_ptr->fpf1)) || 3485 ((f_qual_arr->conf_arr[k].selector.pri_sel == 3486 _bcmFieldSliceSelFpf2) && 3487 (f_qual_arr->conf_arr[k].selector.pri_sel_val 3488 == sel_ptr->fpf2)) || 3489 ((f_qual_arr->conf_arr[k].selector.pri_sel == 3490 _bcmFieldSliceSelFpf3) && 3491 (f_qual_arr->conf_arr[k].selector.pri_sel_val 3492 == sel_ptr->fpf3)) || 3493 ((f_qual_arr->conf_arr[k].selector.pri_sel == 3494 _bcmFieldSliceSelFpf4) && 3495 (f_qual_arr->conf_arr[k].selector.pri_sel_val 3496 == sel_ptr->fpf4))) { 3497 qualified = 1; 3498 } 3499 if (qualified) { 3500 sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j], 3501 &f_qual_arr->conf_arr[k].offset.field, 3502 sizeof(f_qual_arr->conf_arr[k].offset.field)); 3503 } 3504 break; 3505 } 3506 } 3507 } 3508 /* Get the actions associated with this part of the entry */ 3509 policy_entry = soc_mem_table_idx_to_pointer 3510 (unit, FP_POLICY_TABLEm, 3511 fp_policy_table_entry_t *, 3512 fp_policy_buf, part_index); 3513 rv = _field_fb_actions_recover(unit, (uint32 *)policy_entry, 3514 f_ent, i, FP_POLICY_TABLEm, 3515 &f_ent_wb_info); 3516 if (BCM_FAILURE(rv)) { 3517 sal_free(f_ent); 3518 goto cleanup; 3519 } 3520 if (action_bmp.w != NULL) { 3521 _FP_ACTION_BMP_FREE(action_bmp); 3522 action_bmp.w = NULL; 3523 } 3524 } 3525 /* Add to the group */ 3526 rv = _field_group_entry_add(unit, fg, f_ent); 3527 if (BCM_FAILURE(rv)) { 3528 sal_free(f_ent); 3529 goto cleanup; 3530 } 3531 f_ent = NULL; 3532 } 3533 /* Free up the temporary slice group info */ 3534 if (fc->l2warm) { 3535 _field_scache_slice_group_free(unit, fc, slice_idx); 3536 } 3537 } 3538 3539 /* To set per port flags */ 3540 group = fc->groups; 3541 while (group != NULL) { 3542 if (group->stage_id == _BCM_FIELD_STAGE_INGRESS) { 3543 if (!BCM_PBMP_EQ(PBMP_ALL(unit), group->pbmp)) { 3544 /* Update Group Flags to denote Port based Group */ 3545 group->flags |= _FP_GROUP_PER_PORT_OR_PBMP; 3546 } 3547 } 3548 group = group->next; 3549 } 3550 3551 if (fc->l2warm) { 3552 3553 /* Mark end of Slice Info */ 3554 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 3555 fc->scache_pos++; 3556 } 3557 3558 /* Group Slice Selectors */ 3559 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 3560 rv = _field_group_slice_selectors_recover(unit, 3561 &buf[fc->scache_pos], stage_fc->stage_id); 3562 if (BCM_FAILURE(rv)) { 3563 goto cleanup; 3564 } 3565 } 3566 3567 temp = 0; 3568 temp |= buf[fc->scache_pos]; 3569 fc->scache_pos++; 3570 temp |= buf[fc->scache_pos] << 8; 3571 fc->scache_pos++; 3572 temp |= buf[fc->scache_pos] << 16; 3573 fc->scache_pos++; 3574 temp |= buf[fc->scache_pos] << 24; 3575 fc->scache_pos++; 3576 if (temp != _FIELD_IFP_DATA_END) { 3577 fc->l2warm = 0; 3578 rv = BCM_E_INTERNAL; 3579 } 3580 if (NULL != buf1) { 3581 temp = 0; 3582 temp |= buf1[fc->scache_pos1]; 3583 fc->scache_pos1++; 3584 temp |= buf1[fc->scache_pos1] << 8; 3585 fc->scache_pos1++; 3586 temp |= buf1[fc->scache_pos1] << 16; 3587 fc->scache_pos1++; 3588 temp |= buf1[fc->scache_pos1] << 24; 3589 fc->scache_pos1++; 3590 if (temp != _FIELD_IFP_DATA_END) { 3591 fc->l2warm = 0; 3592 rv = BCM_E_INTERNAL; 3593 } 3594 } 3595 3596 } 3597 3598 if (BCM_SUCCESS(rv)) { 3599 _field_group_slice_vmap_recovery(unit, fc, stage_fc); 3600 } 3601 3602 cleanup: 3603 if (fp_tcam_buf) { 3604 soc_cm_sfree(unit, fp_tcam_buf); 3605 } 3606 if (fp_pfs_buf) { 3607 soc_cm_sfree(unit, fp_pfs_buf); 3608 } 3609 if (fp_policy_buf) { 3610 soc_cm_sfree(unit, fp_policy_buf); 3611 } 3612 if (action_bmp.w != NULL) { 3613 _FP_ACTION_BMP_FREE(action_bmp); 3614 action_bmp.w = NULL; 3615 } 3616 3617 return rv; 3618 } 3619 3620 static uint16 list_key1[22] = {bcmFieldQualifyIpFrag, bcmFieldQualifyTcpControl, 3621 bcmFieldQualifyL4DstPort, bcmFieldQualifyL4SrcPort, 3622 bcmFieldQualifyTtl, bcmFieldQualifyIpProtocol, 3623 bcmFieldQualifyDstIp, bcmFieldQualifySrcIp, 3624 bcmFieldQualifyIpType, bcmFieldQualifyTos, 3625 bcmFieldQualifyInPort, bcmFieldQualifyL3Routable, 3626 bcmFieldQualifyMirrorCopy, bcmFieldQualifyOuterVlan, 3627 bcmFieldQualifyOuterVlanId, bcmFieldQualifyOuterVlanCfi, 3628 bcmFieldQualifyOuterVlanPri, bcmFieldQualifyVlanFormat, 3629 bcmFieldQualifyDstHiGig, bcmFieldQualifyInterfaceClassPort, 3630 bcmFieldQualifyOutPort, bcmFieldQualifyIp4}; 3631 3632 static uint16 list_key2[16] = {bcmFieldQualifyIpProtocol, bcmFieldQualifySrcIp6, 3633 bcmFieldQualifyIpType, bcmFieldQualifyDSCP, 3634 bcmFieldQualifyInPort, bcmFieldQualifyL3Routable, 3635 bcmFieldQualifyMirrorCopy, bcmFieldQualifyOuterVlan, 3636 bcmFieldQualifyOuterVlanId, bcmFieldQualifyOuterVlanCfi, 3637 bcmFieldQualifyOuterVlanPri, bcmFieldQualifyVlanFormat, 3638 bcmFieldQualifyDstHiGig, bcmFieldQualifyInterfaceClassPort, 3639 bcmFieldQualifyOutPort, bcmFieldQualifyIp6}; 3640 3641 static uint16 list_key3[7] = {bcmFieldQualifyIpFrag, bcmFieldQualifyTcpControl, 3642 bcmFieldQualifyL4DstPort, bcmFieldQualifyL4SrcPort, 3643 bcmFieldQualifyTtl, bcmFieldQualifyDstIp6, 3644 bcmFieldQualifyDstIp6}; 3645 3646 static uint16 list_key4[19] = {bcmFieldQualifyL2Format, bcmFieldQualifyEtherType, 3647 bcmFieldQualifySrcMac, bcmFieldQualifyDstMac, 3648 bcmFieldQualifyInnerVlan, bcmFieldQualifyInnerVlanId, 3649 bcmFieldQualifyInnerVlanCfi, bcmFieldQualifyInnerVlanPri, 3650 bcmFieldQualifyInPort, bcmFieldQualifyL3Routable, 3651 bcmFieldQualifyMirrorCopy, bcmFieldQualifyOuterVlan, 3652 bcmFieldQualifyOuterVlanId, bcmFieldQualifyOuterVlanCfi, 3653 bcmFieldQualifyOuterVlanPri, bcmFieldQualifyVlanFormat, 3654 bcmFieldQualifyDstHiGig, bcmFieldQualifyInterfaceClassPort, 3655 bcmFieldQualifyOutPort}; 3656 3657 int 3658 _field_fb2_stage_egress_reinit(int unit, _field_control_t *fc, 3659 _field_stage_t *stage_fc) 3660 { 3661 int idx, idx1, slice_idx, index_min, index_max, rv = BCM_E_NONE; 3662 int entries_per_slice, mem_sz, qual_idx, parts_count = 1; 3663 int i, j, k, pri_tcam_idx, part_index, slice_number; 3664 int size, list_size[2], prev_prio; 3665 uint16 *list_arr[2]; 3666 char *efp_tcam_buf = NULL; /* Buffer to read the EFP_TCAM table */ 3667 char *efp_policy_buf = NULL; /* Buffer to read the EFP_POLICY table */ 3668 uint32 rval, efp_slice_mode, key_match_type, temp; 3669 uint32 *efp_tcam_entry_buf; 3670 bcm_field_group_t gid; 3671 int priority; 3672 int group_flags; 3673 efp_tcam_entry_t *efp_tcam_entry; 3674 efp_policy_table_entry_t *efp_policy_entry; 3675 _field_slice_t *fs; 3676 _field_group_t *fg = NULL; 3677 _field_entry_t *f_ent = NULL; 3678 _bcm_field_qual_info_t *f_qual_arr = NULL; 3679 _bcm_field_qual_offset_t *q_offset_arr = NULL; 3680 uint16 *qid_arr = NULL; 3681 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 3682 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 3683 bcm_field_qset_t qset; 3684 int action_res_id; 3685 bcm_pbmp_t group_pbmp; 3686 _field_entry_wb_info_t f_ent_wb_info; 3687 soc_field_t efp_en_flds[4] = {SLICE_ENABLE_SLICE_0f, SLICE_ENABLE_SLICE_1f, 3688 SLICE_ENABLE_SLICE_2f, SLICE_ENABLE_SLICE_3f}; 3689 3690 soc_field_t efp_lk_en_flds[4] = 3691 {LOOKUP_ENABLE_SLICE_0f, LOOKUP_ENABLE_SLICE_1f, 3692 LOOKUP_ENABLE_SLICE_2f, LOOKUP_ENABLE_SLICE_3f}; 3693 _field_action_bmp_t action_bmp; 3694 3695 /* Reset Action bitmap to NULL. */ 3696 action_bmp.w = NULL; 3697 3698 if (fc->l2warm) { 3699 rv = _field_scache_stage_hdr_chk(fc, _FIELD_EFP_DATA_START); 3700 if (BCM_FAILURE(rv)) { 3701 return (rv); 3702 } 3703 } 3704 3705 /* DMA various tables */ 3706 efp_tcam_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES 3707 (unit, EFP_TCAMm), 3708 "EFP TCAM buffer"); 3709 if (NULL == efp_tcam_buf) { 3710 return BCM_E_MEMORY; 3711 } 3712 index_min = soc_mem_index_min(unit, EFP_TCAMm); 3713 index_max = soc_mem_index_max(unit, EFP_TCAMm); 3714 if ((rv = soc_mem_read_range(unit, EFP_TCAMm, MEM_BLOCK_ALL, 3715 index_min, index_max, 3716 efp_tcam_buf)) < 0 ) { 3717 goto cleanup; 3718 } 3719 efp_policy_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES 3720 (unit, EFP_POLICY_TABLEm), 3721 "EFP POLICY TABLE buffer"); 3722 if (NULL == efp_policy_buf) { 3723 return BCM_E_MEMORY; 3724 } 3725 index_min = soc_mem_index_min(unit, EFP_POLICY_TABLEm); 3726 index_max = soc_mem_index_max(unit, EFP_POLICY_TABLEm); 3727 if ((rv = soc_mem_read_range(unit, EFP_POLICY_TABLEm, MEM_BLOCK_ALL, 3728 index_min, index_max, 3729 efp_policy_buf)) < 0 ) { 3730 goto cleanup; 3731 } 3732 entries_per_slice = 128; 3733 3734 /* Iterate over the slices */ 3735 if ((rv = READ_EFP_SLICE_CONTROLr(unit, &rval)) < 0) { 3736 goto cleanup; 3737 } 3738 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 3739 /* Ignore disabled slice */ 3740 if ((soc_reg_field_get(unit, EFP_SLICE_CONTROLr, rval, 3741 efp_en_flds[slice_idx]) == 0) || 3742 (soc_reg_field_get(unit, EFP_SLICE_CONTROLr, rval, 3743 efp_lk_en_flds[slice_idx]) == 0)) { 3744 continue; 3745 } 3746 3747 efp_slice_mode = soc_reg_field_get(unit, EFP_SLICE_CONTROLr, rval, 3748 _efp_slice_mode[slice_idx]); 3749 /* Skip if slice has no valid entries */ 3750 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 3751 for (idx = 0; idx < fs->entry_count; idx++) { 3752 efp_tcam_entry = soc_mem_table_idx_to_pointer 3753 (unit, EFP_TCAMm, efp_tcam_entry_t *, 3754 efp_tcam_buf, idx + 3755 entries_per_slice * slice_idx); 3756 if (soc_EFP_TCAMm_field32_get(unit, efp_tcam_entry, 3757 VALIDf) != 0) { 3758 /* Get KEY_MATCH_TYPE from first valid entry */ 3759 /* 3760 * COVERITY 3761 * 3762 * Call to _field_extract is taken care in all the flows 3763 * by not setting the width mrore than 32. 3764 */ 3765 /* coverity[callee_ptr_arith] */ 3766 _field_extract((uint32 *)efp_tcam_entry, 181 + 2, 3, 3767 &key_match_type); 3768 break; 3769 } 3770 } 3771 if ((idx == fs->entry_count) && !fc->l2warm) { 3772 continue; 3773 } 3774 /* Skip second part of slice pair */ 3775 if ((efp_slice_mode == _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE) && 3776 (slice_idx % 2)) { 3777 continue; 3778 } 3779 fg = NULL; 3780 if (efp_slice_mode != 3) { /* Invalid value */ 3781 /* If Level 2, retrieve the GIDs in this slice */ 3782 if (fc->l2warm) { 3783 rv = _field_scache_slice_group_recover(unit, fc, slice_idx, 3784 NULL); 3785 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 3786 fc->l2warm = 0; 3787 goto cleanup; 3788 } 3789 if (rv == BCM_E_NOT_FOUND) { 3790 rv = BCM_E_NONE; 3791 continue; 3792 } 3793 } 3794 /* Create a new group - one group per slice */ 3795 _FP_XGS3_ALLOC(fg, sizeof(_field_group_t), "field group"); 3796 if (NULL == fg) { 3797 goto cleanup; 3798 } 3799 3800 /* Initialize action res id and VMAP group to default */ 3801 action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 3802 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 3803 fg->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 3804 } 3805 3806 group_flags = 0; 3807 if (fc->l2warm) { 3808 /* Get stored group ID and QSET for Level 2 */ 3809 rv = _field_group_info_retrieve(unit, -1, _FP_DEF_INST, &gid, 3810 &priority, &action_res_id, &group_pbmp, NULL, 3811 &group_flags, &qset, fc); 3812 if (gid != -1) { 3813 sal_memcpy(&fg->qset, &qset, sizeof(bcm_field_qset_t)); 3814 } else { 3815 sal_free(fg); 3816 goto cleanup; 3817 } 3818 } else { 3819 rv = _bcm_field_group_id_generate(unit, &gid); 3820 priority = slice_idx; 3821 } 3822 if (BCM_FAILURE(rv)) { 3823 sal_free(fg); 3824 goto cleanup; 3825 } 3826 fg->gid = gid; 3827 fg->priority = priority; 3828 fg->action_res_id = action_res_id; 3829 if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) { 3830 fg->flags = fg->flags | _FP_GROUP_SELECT_AUTO_EXPANSION; 3831 } 3832 3833 fg->stage_id = stage_fc->stage_id; 3834 list_arr[0] = list_arr[1] = NULL; 3835 switch (efp_slice_mode) { 3836 case _BCM_FIELD_EGRESS_SLICE_MODE_SINGLE_L2: 3837 fg->flags |= _FP_GROUP_SPAN_SINGLE_SLICE; 3838 fg->sel_codes[0].fpf3 = _BCM_FIELD_EFP_KEY4; 3839 parts_count = 1; 3840 list_size[0] = 19; 3841 list_arr[0] = list_key4; 3842 break; 3843 case _BCM_FIELD_EGRESS_SLICE_MODE_SINGLE_L3: 3844 fg->flags |= _FP_GROUP_SPAN_SINGLE_SLICE; 3845 fg->sel_codes[0].fpf3 = _BCM_FIELD_EFP_KEY1; 3846 parts_count = 1; 3847 list_size[0] = 22; 3848 list_arr[0] = list_key1; 3849 break; 3850 case _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE: 3851 fg->flags |= _FP_GROUP_SPAN_DOUBLE_SLICE; 3852 if (key_match_type == 3853 _BCM_FIELD_EFP_KEY2_KEY3_MATCH_TYPE) { 3854 fg->sel_codes[0].fpf3 = _BCM_FIELD_EFP_KEY3; 3855 fg->sel_codes[1].fpf3 = _BCM_FIELD_EFP_KEY2; 3856 list_size[0] = 7; 3857 list_size[1] = 16; 3858 list_arr[0] = list_key3; 3859 list_arr[1] = list_key2; 3860 } else { /* _BCM_FIELD_EFP_KEY1_KEY4_MATCH_TYPE */ 3861 fg->sel_codes[0].fpf3 = _BCM_FIELD_EFP_KEY1; 3862 fg->sel_codes[1].fpf3 = _BCM_FIELD_EFP_KEY4; 3863 list_size[0] = 22; 3864 list_size[1] = 19; 3865 list_arr[0] = list_key1; 3866 list_arr[1] = list_key4; 3867 } 3868 parts_count = 2; 3869 break; 3870 default: 3871 /* slice mode must be a valid value. */ 3872 sal_free(fg); 3873 rv = BCM_E_INTERNAL; 3874 goto cleanup; 3875 } 3876 /* Determine QSET based on selector values */ 3877 /* Add the appropriate list of qualifiers */ 3878 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyStageEgress); 3879 for (i = 0; i < parts_count; i++) { 3880 for (j = 0; j < list_size[i]; j++) { 3881 if (fc->l2warm && !BCM_FIELD_QSET_TEST(fg->qset, 3882 list_arr[i][j])) { 3883 continue; 3884 } 3885 BCM_FIELD_QSET_ADD(fg->qset, list_arr[i][j]); 3886 f_qual_arr = stage_fc->f_qual_arr[list_arr[i][j]]; 3887 for (k = 0; k < f_qual_arr->conf_sz; k++) { 3888 if ((f_qual_arr->conf_arr[k].selector.pri_sel_val == 3889 fg->sel_codes[i].fpf3)) { 3890 break; 3891 } 3892 } 3893 /* Allocate memory for this qualfier and its 3894 associated ofset information if not already added 3895 to fg->qual_arr[i] */ 3896 size = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size + 1; 3897 qid_arr = NULL; 3898 _FP_XGS3_ALLOC(qid_arr, size * sizeof (uint16), 3899 "Group qual id"); 3900 if (NULL == qid_arr) { 3901 goto cleanup; 3902 } 3903 q_offset_arr = NULL; 3904 _FP_XGS3_ALLOC(q_offset_arr, size * 3905 sizeof (_bcm_field_qual_offset_t), 3906 "Group qual offset"); 3907 if (NULL == q_offset_arr) { 3908 sal_free (qid_arr); 3909 goto cleanup; 3910 } 3911 if (size) { 3912 sal_memcpy(qid_arr, fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr, 3913 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size * 3914 sizeof (uint16)); 3915 sal_memcpy(q_offset_arr, 3916 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr, 3917 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size * 3918 sizeof (_bcm_field_qual_offset_t)); 3919 if (fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size) { 3920 sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr); 3921 sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr); 3922 } 3923 } 3924 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr = qid_arr; 3925 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr = q_offset_arr; 3926 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[size - 1] = list_arr[i][j]; 3927 3928 sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[size - 1], 3929 &f_qual_arr->conf_arr[k].offset, 3930 sizeof(f_qual_arr->conf_arr[k].offset)); 3931 3932 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size = size; 3933 } 3934 } 3935 /* Associate slice(s) to group */ 3936 fg->slices = stage_fc->slices[_FP_DEF_INST] + slice_idx; 3937 SOC_PBMP_ASSIGN(fg->pbmp, PBMP_ALL(unit)); 3938 BCM_PBMP_OR(fs->pbmp, fg->pbmp); 3939 3940 /* Initialize group default ASET list. */ 3941 rv = _field_group_default_aset_set(unit, fg); 3942 if (BCM_FAILURE(rv)) { 3943 /* Free group's qualifier and offset array memories. */ 3944 for (i = 0; i < parts_count; i++) { 3945 if (NULL != fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr) { 3946 sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr); 3947 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr = NULL; 3948 } 3949 if (NULL != fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr) { 3950 sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr); 3951 fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr = NULL; 3952 } 3953 } 3954 3955 /* Free group's memory*/ 3956 sal_free(fg); 3957 goto cleanup; 3958 } 3959 3960 if (fc->l2warm 3961 && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15)) { 3962 if (group_flags & _FP_GROUP_LOOKUP_ENABLED) { 3963 fg->flags = fg->flags | _FP_GROUP_LOOKUP_ENABLED; 3964 } 3965 if (group_flags & _FP_GROUP_WLAN) { 3966 fg->flags = fg->flags | _FP_GROUP_WLAN; 3967 } 3968 } else { 3969 fg->flags |= _FP_GROUP_LOOKUP_ENABLED; 3970 } 3971 3972 fg->next = fc->groups; 3973 fc->groups = fg; 3974 3975 /* Now go over the entries in this slice */ 3976 prev_prio = -1; 3977 for (idx = 0; idx < fs->entry_count; idx++) { 3978 efp_tcam_entry = soc_mem_table_idx_to_pointer 3979 (unit, EFP_TCAMm, efp_tcam_entry_t *, 3980 efp_tcam_buf, idx + 3981 entries_per_slice * slice_idx); 3982 if (soc_EFP_TCAMm_field32_get(unit, efp_tcam_entry, 3983 VALIDf) == 0) { 3984 continue; 3985 } 3986 /* Allocate memory for this entry */ 3987 mem_sz = parts_count * sizeof (_field_entry_t); 3988 _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry"); 3989 if (f_ent == NULL) { 3990 rv = BCM_E_MEMORY; 3991 goto cleanup; 3992 } 3993 3994 for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) { 3995 f_ent->policer[idx1].pid = _FP_INVALID_INDEX; 3996 } 3997 3998 sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t)); 3999 f_ent_wb_info.sid = f_ent_wb_info.pid = -1; 4000 if (fc->l2warm) { 4001 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 4002 action_bmp.w = NULL; 4003 _FP_XGS3_ALLOC(action_bmp.w, 4004 SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount), 4005 "Action No Param Bitmap"); 4006 if (action_bmp.w == NULL) { 4007 rv = BCM_E_MEMORY; 4008 sal_free(f_ent); 4009 goto cleanup; 4010 } 4011 } 4012 f_ent_wb_info.action_bmp = &action_bmp; 4013 4014 rv = _field_entry_info_retrieve(unit, fc, stage_fc, 4015 0, &prev_prio, 4016 &f_ent_wb_info); 4017 4018 if (BCM_FAILURE(rv)) { 4019 sal_free(f_ent); 4020 goto cleanup; 4021 } 4022 } else { 4023 _bcm_field_last_alloc_eid_incr(unit); 4024 } 4025 pri_tcam_idx = idx + entries_per_slice * slice_idx; 4026 for (i = 0; i < parts_count; i++) { 4027 if (fc->l2warm) { 4028 f_ent[i].eid = f_ent_wb_info.eid; 4029 /* Set retrieved dvp_type and svp_type */ 4030 f_ent[i].dvp_type = f_ent_wb_info.dvp_type[i]; 4031 f_ent[i].svp_type = f_ent_wb_info.svp_type[i]; 4032 } else { 4033 f_ent[i].eid = _bcm_field_last_alloc_eid_get(unit); 4034 } 4035 f_ent[i].group = fg; 4036 rv = _bcm_field_tcam_part_to_entry_flags(unit, i, fg, 4037 &f_ent[i].flags); 4038 if (BCM_FAILURE(rv)) { 4039 sal_free(f_ent); 4040 goto cleanup; 4041 } 4042 if (f_ent_wb_info.color_independent) { 4043 f_ent[i].flags |= _FP_ENTRY_COLOR_INDEPENDENT; 4044 } 4045 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 4046 pri_tcam_idx, 4047 i, &part_index); 4048 if (BCM_FAILURE(rv)) { 4049 sal_free(f_ent); 4050 goto cleanup; 4051 } 4052 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc, 4053 _FP_DEF_INST, 4054 part_index, 4055 &slice_number, 4056 (int *)&f_ent[i].slice_idx); 4057 if (BCM_FAILURE(rv)) { 4058 sal_free(f_ent); 4059 goto cleanup; 4060 } 4061 f_ent[i].fs = stage_fc->slices[_FP_DEF_INST] + slice_number; 4062 if (0 == (f_ent[i].flags & _FP_ENTRY_SECOND_HALF)) { 4063 /* Decrement slice free entry count for primary 4064 entries. */ 4065 f_ent[i].fs->free_count--; 4066 } 4067 /* Assign entry to a slice */ 4068 f_ent[i].fs->entries[f_ent[i].slice_idx] = f_ent + i; 4069 f_ent[i].flags |= _FP_ENTRY_INSTALLED; 4070 4071 if (soc_EFP_TCAMm_field32_get(unit, efp_tcam_entry, VALIDf) == 3) { 4072 f_ent[i].flags |= _FP_ENTRY_ENABLED; 4073 } 4074 4075 /* efp_tcam_entry_buf must point to the entry part */ 4076 efp_tcam_entry_buf = (uint32 *) 4077 soc_mem_table_idx_to_pointer 4078 (unit, EFP_TCAMm, 4079 efp_tcam_entry_t *, 4080 efp_tcam_buf, part_index); 4081 4082 /* Use this part to determine fg->qual_arr[i] */ 4083 /* Iterate over the HW qualifiers and match offsets with 4084 the non-zero masks */ 4085 for (j = 0; j < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) { 4086 qual_idx = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j]; 4087 f_qual_arr = stage_fc->f_qual_arr[qual_idx]; 4088 /* Loop over configurations of this qualifier */ 4089 for (k = 0; k < f_qual_arr->conf_sz; k++) { 4090 if (_mask_is_set(unit, 4091 &f_qual_arr->conf_arr[k].offset, 4092 efp_tcam_entry_buf, 4093 _BCM_FIELD_STAGE_EGRESS)) { 4094 sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j].field, 4095 &f_qual_arr->conf_arr[k].offset, 4096 sizeof(f_qual_arr->conf_arr[k].offset)); 4097 break; 4098 } 4099 } 4100 } 4101 /* Get the actions associated with this entry part */ 4102 efp_policy_entry = soc_mem_table_idx_to_pointer 4103 (unit, EFP_POLICY_TABLEm, 4104 efp_policy_table_entry_t *, 4105 efp_policy_buf, part_index); 4106 rv = _field_fb_actions_recover(unit, (uint32 *) 4107 efp_policy_entry, f_ent, 4108 i, EFP_POLICY_TABLEm, 4109 &f_ent_wb_info); 4110 if (BCM_FAILURE(rv)) { 4111 sal_free(f_ent); 4112 goto cleanup; 4113 } 4114 if (action_bmp.w != NULL) { 4115 _FP_ACTION_BMP_FREE(action_bmp); 4116 action_bmp.w = NULL; 4117 } 4118 } 4119 /* Add to the group */ 4120 rv = _field_group_entry_add(unit, fg, f_ent); 4121 if (BCM_FAILURE(rv)) { 4122 sal_free(f_ent); 4123 goto cleanup; 4124 } 4125 f_ent = NULL; 4126 } 4127 } 4128 /* Free up the temporary slice group info */ 4129 if (fc->l2warm) { 4130 _field_scache_slice_group_free(unit, fc, slice_idx); 4131 } 4132 } 4133 4134 if (fc->l2warm) { 4135 4136 /* Mark end of Slice Info */ 4137 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 4138 fc->scache_pos++; 4139 } 4140 4141 /* Group Slice Selectors */ 4142 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 4143 rv = (_field_group_slice_selectors_recover(unit, 4144 &buf[fc->scache_pos], stage_fc->stage_id)); 4145 if (BCM_FAILURE(rv)) { 4146 goto cleanup; 4147 } 4148 } 4149 4150 temp = 0; 4151 temp |= buf[fc->scache_pos]; 4152 fc->scache_pos++; 4153 temp |= buf[fc->scache_pos] << 8; 4154 fc->scache_pos++; 4155 temp |= buf[fc->scache_pos] << 16; 4156 fc->scache_pos++; 4157 temp |= buf[fc->scache_pos] << 24; 4158 fc->scache_pos++; 4159 if (temp != _FIELD_EFP_DATA_END) { 4160 fc->l2warm = 0; 4161 rv = BCM_E_INTERNAL; 4162 } 4163 4164 if (NULL != buf1) { 4165 temp = 0; 4166 temp |= buf1[fc->scache_pos1]; 4167 fc->scache_pos1++; 4168 temp |= buf1[fc->scache_pos1] << 8; 4169 fc->scache_pos1++; 4170 temp |= buf1[fc->scache_pos1] << 16; 4171 fc->scache_pos1++; 4172 temp |= buf1[fc->scache_pos1] << 24; 4173 fc->scache_pos1++; 4174 if (temp != _FIELD_EFP_DATA_END) { 4175 fc->l2warm = 0; 4176 rv = BCM_E_INTERNAL; 4177 } 4178 } 4179 } 4180 cleanup: 4181 if (efp_tcam_buf) { 4182 soc_cm_sfree(unit, efp_tcam_buf); 4183 } 4184 if (efp_policy_buf) { 4185 soc_cm_sfree(unit, efp_policy_buf); 4186 } 4187 if (fg != NULL) { 4188 sal_free(fg); 4189 } 4190 if (action_bmp.w != NULL) { 4191 _FP_ACTION_BMP_FREE(action_bmp); 4192 action_bmp.w = NULL; 4193 } 4194 return rv; 4195 } 4196 4197 int 4198 _field_fb2_stage_lookup_reinit(int unit, _field_control_t *fc, 4199 _field_stage_t *stage_fc) 4200 { 4201 int idx, idx1, slice_idx, index_min, index_max, ratio, rv = BCM_E_NONE; 4202 int entries_per_slice, group_found, mem_sz, parts_count, qual_idx; 4203 int i, j, k, pri_tcam_idx, part_index, slice_number, prev_prio; 4204 char *vfp_tcam_buf = NULL; /* Buffer to read the VFP_TCAM table */ 4205 char *vfp_policy_buf = NULL; /* Buffer to read the VFP_POLICY table */ 4206 uint32 rval, paired, intraslice, dbl_wide_key, dbl_wide_key_sec; 4207 uint32 vfp_key, temp; 4208 uint32 *vfp_tcam_entry_buf; 4209 soc_field_t fld; 4210 vfp_tcam_entry_t *vfp_tcam_entry; 4211 vfp_policy_table_entry_t *vfp_policy_entry; 4212 _field_hw_qual_info_t hw_sels; 4213 _field_slice_t *fs; 4214 _field_group_t *fg; 4215 _field_entry_t *f_ent = NULL; 4216 bcm_pbmp_t entry_pbmp, temp_pbmp; 4217 _bcm_field_qual_info_t *f_qual_arr = NULL; 4218 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 4219 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 4220 _field_entry_wb_info_t f_ent_wb_info; 4221 4222 soc_field_t vfp_en_flds[4] = {SLICE_ENABLE_SLICE_0f, SLICE_ENABLE_SLICE_1f, 4223 SLICE_ENABLE_SLICE_2f, SLICE_ENABLE_SLICE_3f}; 4224 4225 soc_field_t vfp_lk_en_flds[4] = 4226 {LOOKUP_ENABLE_SLICE_0f, LOOKUP_ENABLE_SLICE_1f, 4227 LOOKUP_ENABLE_SLICE_2f, LOOKUP_ENABLE_SLICE_3f}; 4228 _field_action_bmp_t action_bmp; 4229 4230 /* Reset Action bitmap to NULL. */ 4231 action_bmp.w = NULL; 4232 4233 SOC_PBMP_CLEAR(entry_pbmp); 4234 4235 if (fc->l2warm) { 4236 rv = _field_scache_stage_hdr_chk(fc, _FIELD_VFP_DATA_START); 4237 if (BCM_FAILURE(rv)) { 4238 return (rv); 4239 } 4240 } 4241 4242 /* DMA various tables */ 4243 vfp_tcam_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES 4244 (unit, VFP_TCAMm), 4245 "VFP TCAM buffer"); 4246 if (NULL == vfp_tcam_buf) { 4247 return BCM_E_MEMORY; 4248 } 4249 index_min = soc_mem_index_min(unit, VFP_TCAMm); 4250 index_max = soc_mem_index_max(unit, VFP_TCAMm); 4251 if ((rv = soc_mem_read_range(unit, VFP_TCAMm, MEM_BLOCK_ALL, 4252 index_min, index_max, 4253 vfp_tcam_buf)) < 0 ) { 4254 goto cleanup; 4255 } 4256 vfp_policy_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES 4257 (unit, VFP_POLICY_TABLEm), 4258 "VFP POLICY TABLE buffer"); 4259 if (NULL == vfp_policy_buf) { 4260 return BCM_E_MEMORY; 4261 } 4262 index_min = soc_mem_index_min(unit, VFP_POLICY_TABLEm); 4263 index_max = soc_mem_index_max(unit, VFP_POLICY_TABLEm); 4264 if ((rv = soc_mem_read_range(unit, VFP_POLICY_TABLEm, MEM_BLOCK_ALL, 4265 index_min, index_max, 4266 vfp_policy_buf)) < 0 ) { 4267 goto cleanup; 4268 } 4269 entries_per_slice = 256; 4270 4271 /* Iterate over the slices */ 4272 if ((rv = READ_VFP_SLICE_CONTROLr(unit, &rval)) < 0) { 4273 goto cleanup; 4274 } 4275 if ((rv = READ_VFP_KEY_CONTROLr(unit, &vfp_key)) < 0) { 4276 goto cleanup; 4277 } 4278 for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) { 4279 /* Ignore disabled slice */ 4280 if ((soc_reg_field_get(unit, VFP_SLICE_CONTROLr, rval, 4281 vfp_en_flds[slice_idx]) == 0) || 4282 (soc_reg_field_get(unit, VFP_SLICE_CONTROLr, rval, 4283 vfp_lk_en_flds[slice_idx]) == 0)) { 4284 continue; 4285 } 4286 /* Ignore secondary slice in paired mode */ 4287 fld = _vfp_slice_pairing_field[slice_idx / 2]; 4288 paired = soc_reg_field_get(unit, VFP_KEY_CONTROLr, vfp_key, fld); 4289 fld = _vfp_slice_wide_mode_field[slice_idx]; 4290 intraslice = soc_reg_field_get(unit, VFP_KEY_CONTROLr, vfp_key, fld); 4291 if (paired && (slice_idx % 2)) { 4292 continue; 4293 } 4294 /* Skip if slice has no valid groups and entries */ 4295 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 4296 for (idx = 0; idx < fs->entry_count; idx++) { 4297 vfp_tcam_entry = soc_mem_table_idx_to_pointer 4298 (unit, VFP_TCAMm, vfp_tcam_entry_t *, 4299 vfp_tcam_buf, idx + 4300 entries_per_slice * slice_idx); 4301 if (soc_VFP_TCAMm_field32_get(unit, vfp_tcam_entry, 4302 VALIDf) != 0) { 4303 break; 4304 } 4305 } 4306 if ((idx == fs->entry_count) && !fc->l2warm) { 4307 continue; 4308 } 4309 /* If Level 2, retrieve the GIDs in this slice */ 4310 if (fc->l2warm) { 4311 rv = _field_scache_slice_group_recover(unit, fc, slice_idx, 4312 NULL); 4313 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 4314 fc->l2warm = 0; 4315 goto cleanup; 4316 } 4317 if (rv == BCM_E_NOT_FOUND) { 4318 rv = BCM_E_NONE; 4319 continue; 4320 } 4321 } 4322 /* Construct the group based on HW selector values */ 4323 sal_memset(&hw_sels, 0, sizeof(_field_hw_qual_info_t)); 4324 /* Get primary slice's selectors */ 4325 hw_sels.pri_slice[0].fpf2 = soc_reg_field_get(unit, VFP_KEY_CONTROLr, 4326 vfp_key, _vfp_field_tbl[slice_idx][0]); 4327 hw_sels.pri_slice[0].fpf3 = soc_reg_field_get(unit, VFP_KEY_CONTROLr, 4328 vfp_key, _vfp_field_tbl[slice_idx][1]); 4329 /* If intraslice, get double-wide key - only 2 options */ 4330 if (intraslice) { 4331 dbl_wide_key = soc_reg_field_get(unit, VFP_KEY_CONTROLr, vfp_key, 4332 _vfp_slice_wide_mode_field[slice_idx]); 4333 hw_sels.pri_slice[1].intraslice = 1; 4334 hw_sels.pri_slice[1].fpf2 = dbl_wide_key; 4335 hw_sels.pri_slice[1].fpf3 = 0; 4336 } 4337 /* If paired, get secondary slice's selectors */ 4338 if (paired) { 4339 hw_sels.sec_slice[0].fpf2 = soc_reg_field_get(unit, 4340 VFP_KEY_CONTROLr, 4341 vfp_key, 4342 _vfp_field_tbl[slice_idx + 1][0]); 4343 hw_sels.sec_slice[0].fpf3 = soc_reg_field_get(unit, 4344 VFP_KEY_CONTROLr, 4345 vfp_key, 4346 _vfp_field_tbl[slice_idx + 1][1]); 4347 if (intraslice) { 4348 dbl_wide_key_sec = soc_reg_field_get(unit, VFP_KEY_CONTROLr, 4349 vfp_key, _vfp_slice_wide_mode_field[slice_idx + 1]); 4350 hw_sels.sec_slice[1].intraslice = 1; 4351 hw_sels.sec_slice[1].fpf2 = dbl_wide_key_sec; 4352 hw_sels.sec_slice[1].fpf3 = 0; 4353 } 4354 } 4355 /* Create a group based on HW qualifiers (or find existing) */ 4356 rv = _field_fb2_group_construct(unit, &hw_sels, intraslice, 4357 paired, fc, -1, 4358 _BCM_FIELD_STAGE_LOOKUP, 4359 slice_idx); 4360 if (BCM_FAILURE(rv)) { 4361 goto cleanup; 4362 } 4363 /* Now go over the entries */ 4364 fs = stage_fc->slices[_FP_DEF_INST] + slice_idx; 4365 if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) { 4366 ratio = 2; 4367 } else { 4368 ratio = 1; 4369 } 4370 prev_prio = -1; 4371 for (idx = 0; idx < fs->entry_count / ratio; idx++) { 4372 group_found = 0; 4373 vfp_tcam_entry = soc_mem_table_idx_to_pointer 4374 (unit, VFP_TCAMm, vfp_tcam_entry_t *, 4375 vfp_tcam_buf, idx + 4376 entries_per_slice * slice_idx); 4377 if (soc_VFP_TCAMm_field32_get(unit, vfp_tcam_entry, 4378 VALIDf) == 0) { 4379 continue; 4380 } 4381 /* All ports are applicable to this entry */ 4382 SOC_PBMP_ASSIGN(entry_pbmp, PBMP_ALL(unit)); 4383 /* Search groups to find match */ 4384 fg = fc->groups; 4385 while (fg != NULL) { 4386 /* Check if group is in this slice */ 4387 fs = &fg->slices[0]; 4388 if (fs->slice_number != slice_idx) { 4389 fg = fg->next; 4390 continue; 4391 } 4392 /* Check if entry_pbmp is a subset of group pbmp */ 4393 SOC_PBMP_ASSIGN(temp_pbmp, fg->pbmp); 4394 SOC_PBMP_AND(temp_pbmp, entry_pbmp); 4395 if (SOC_PBMP_EQ(temp_pbmp, entry_pbmp)) { 4396 group_found = 1; 4397 break; 4398 } 4399 fg = fg->next; 4400 } 4401 if (!group_found) { 4402 return BCM_E_INTERNAL; /* Should never happen */ 4403 } 4404 /* Allocate memory for the entry */ 4405 rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id, 4406 fg->flags, &parts_count); 4407 if (BCM_FAILURE(rv)) { 4408 goto cleanup; 4409 } 4410 mem_sz = parts_count * sizeof (_field_entry_t); 4411 _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry"); 4412 if (f_ent == NULL) { 4413 rv = BCM_E_MEMORY; 4414 goto cleanup; 4415 } 4416 for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) { 4417 f_ent->policer[idx1].pid = _FP_INVALID_INDEX; 4418 } 4419 4420 sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t)); 4421 f_ent_wb_info.sid = f_ent_wb_info.pid = -1; 4422 4423 if (fc->l2warm) { 4424 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 4425 action_bmp.w = NULL; 4426 _FP_XGS3_ALLOC(action_bmp.w, 4427 SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount), 4428 "Action No Param Bitmap"); 4429 if (action_bmp.w == NULL) { 4430 rv = BCM_E_MEMORY; 4431 sal_free(f_ent); 4432 goto cleanup; 4433 } 4434 } 4435 f_ent_wb_info.action_bmp = &action_bmp; 4436 rv = _field_entry_info_retrieve(unit, fc, stage_fc, 4437 0, &prev_prio, 4438 &f_ent_wb_info); 4439 4440 if (BCM_FAILURE(rv)) { 4441 sal_free(f_ent); 4442 goto cleanup; 4443 } 4444 } else { 4445 _bcm_field_last_alloc_eid_incr(unit); 4446 } 4447 pri_tcam_idx = idx + entries_per_slice * slice_idx; 4448 for (i = 0; i < parts_count; i++) { 4449 if (fc->l2warm) { 4450 /* Use retrieved EID */ 4451 f_ent[i].eid = f_ent_wb_info.eid; 4452 /* Set retrieved dvp_type and svp_type */ 4453 f_ent[i].dvp_type = f_ent_wb_info.dvp_type[i]; 4454 f_ent[i].svp_type = f_ent_wb_info.svp_type[i]; 4455 f_ent[i].prio = f_ent_wb_info.prio; 4456 } else { 4457 f_ent[i].eid = _bcm_field_last_alloc_eid_get(unit); 4458 f_ent[i].prio = (slice_idx << 10) | (entries_per_slice - idx); 4459 } 4460 f_ent[i].group = fg; 4461 rv = _bcm_field_tcam_part_to_entry_flags(unit, i, fg, 4462 &f_ent[i].flags); 4463 if (BCM_FAILURE(rv)) { 4464 sal_free(f_ent); 4465 goto cleanup; 4466 } 4467 if (f_ent_wb_info.color_independent) { 4468 f_ent[i].flags |= _FP_ENTRY_COLOR_INDEPENDENT; 4469 } 4470 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 4471 pri_tcam_idx, 4472 i, &part_index); 4473 if (BCM_FAILURE(rv)) { 4474 sal_free(f_ent); 4475 goto cleanup; 4476 } 4477 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc, 4478 _FP_DEF_INST, 4479 part_index, 4480 &slice_number, 4481 (int *)&f_ent[i].slice_idx); 4482 if (BCM_FAILURE(rv)) { 4483 sal_free(f_ent); 4484 goto cleanup; 4485 } 4486 f_ent[i].fs = stage_fc->slices[_FP_DEF_INST] + slice_number; 4487 if (0 == (f_ent[i].flags & _FP_ENTRY_SECOND_HALF)) { 4488 /* Decrement slice free entry count for primary 4489 entries. */ 4490 f_ent[i].fs->free_count--; 4491 } 4492 /* Assign entry to a slice */ 4493 f_ent[i].fs->entries[f_ent[i].slice_idx] = f_ent + i; 4494 BCM_PBMP_OR(f_ent[i].fs->pbmp, fg->pbmp); 4495 f_ent[i].flags |= _FP_ENTRY_INSTALLED; 4496 4497 if (soc_VFP_TCAMm_field32_get(unit, vfp_tcam_entry, VALIDf) == 3) { 4498 f_ent[i].flags |= _FP_ENTRY_ENABLED; 4499 } 4500 4501 /* tcam_entry_buf must point to the entry part */ 4502 vfp_tcam_entry_buf = (uint32 *)soc_mem_table_idx_to_pointer 4503 (unit, VFP_TCAMm, 4504 vfp_tcam_entry_t *, 4505 vfp_tcam_buf, part_index); 4506 4507 /* Use this part to determine fg->qual_arr[i] */ 4508 /* Iterate over the HW qualifiers and match offsets with 4509 the non-zero masks */ 4510 for (j = 0; j < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) { 4511 qual_idx = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j]; 4512 f_qual_arr = stage_fc->f_qual_arr[qual_idx]; 4513 /* Loop over configurations of this qualifier */ 4514 for (k = 0; k < f_qual_arr->conf_sz; k++) { 4515 if (_mask_is_set(unit, &f_qual_arr->conf_arr[k].offset, 4516 vfp_tcam_entry_buf, _BCM_FIELD_STAGE_LOOKUP)) { 4517 sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j], 4518 &f_qual_arr->conf_arr[k].offset, 4519 sizeof(f_qual_arr->conf_arr[k].offset)); 4520 break; 4521 } 4522 } 4523 } 4524 /* Get the actions associated with this part of the entry */ 4525 vfp_policy_entry = soc_mem_table_idx_to_pointer 4526 (unit, VFP_POLICY_TABLEm, 4527 vfp_policy_table_entry_t *, 4528 vfp_policy_buf, part_index); 4529 rv = _field_fb_actions_recover(unit, (uint32 *)vfp_policy_entry, 4530 f_ent, i, VFP_POLICY_TABLEm, 4531 &f_ent_wb_info); 4532 if (BCM_FAILURE(rv)) { 4533 sal_free(f_ent); 4534 goto cleanup; 4535 } 4536 if (action_bmp.w != NULL) { 4537 _FP_ACTION_BMP_FREE(action_bmp); 4538 action_bmp.w = NULL; 4539 } 4540 } 4541 /* Add to the group */ 4542 rv = _field_group_entry_add(unit, fg, f_ent); 4543 if (BCM_FAILURE(rv)) { 4544 sal_free(f_ent); 4545 goto cleanup; 4546 } 4547 f_ent = NULL; 4548 } 4549 /* Free up the temporary slice group info */ 4550 if (fc->l2warm) { 4551 _field_scache_slice_group_free(unit, fc, slice_idx); 4552 } 4553 } 4554 4555 if (fc->l2warm) { 4556 4557 /* Mark end of Slice Info */ 4558 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 4559 fc->scache_pos++; 4560 } 4561 4562 /* Group Slice Selectors */ 4563 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 4564 rv = (_field_group_slice_selectors_recover(unit, 4565 &buf[fc->scache_pos], stage_fc->stage_id)); 4566 if (BCM_FAILURE(rv)) { 4567 goto cleanup; 4568 } 4569 } 4570 4571 temp = 0; 4572 temp |= buf[fc->scache_pos]; 4573 fc->scache_pos++; 4574 temp |= buf[fc->scache_pos] << 8; 4575 fc->scache_pos++; 4576 temp |= buf[fc->scache_pos] << 16; 4577 fc->scache_pos++; 4578 temp |= buf[fc->scache_pos] << 24; 4579 fc->scache_pos++; 4580 if (temp != _FIELD_VFP_DATA_END) { 4581 fc->l2warm = 0; 4582 rv = BCM_E_INTERNAL; 4583 } 4584 4585 if (NULL != buf1) { 4586 temp = 0; 4587 temp |= buf1[fc->scache_pos1]; 4588 fc->scache_pos1++; 4589 temp |= buf1[fc->scache_pos1] << 8; 4590 fc->scache_pos1++; 4591 temp |= buf1[fc->scache_pos1] << 16; 4592 fc->scache_pos1++; 4593 temp |= buf1[fc->scache_pos1] << 24; 4594 fc->scache_pos1++; 4595 if (temp != _FIELD_VFP_DATA_END) { 4596 fc->l2warm = 0; 4597 rv = BCM_E_INTERNAL; 4598 } 4599 } 4600 4601 } 4602 cleanup: 4603 if (vfp_tcam_buf) { 4604 soc_cm_sfree(unit, vfp_tcam_buf); 4605 } 4606 if (vfp_policy_buf) { 4607 soc_cm_sfree(unit, vfp_policy_buf); 4608 } 4609 if (action_bmp.w != NULL) { 4610 _FP_ACTION_BMP_FREE(action_bmp); 4611 action_bmp.w = NULL; 4612 } 4613 return rv; 4614 } 4615 #endif /* BCM_FIREBOLT2_SUPPORT */ 4616 #else 4617 #define _field_fb_stage_reinit (NULL) 4618 #endif /* BCM_WARM_BOOT_SUPPORT */ 4619 4620 #ifdef BCM_WARM_BOOT_SUPPORT 4621 typedef enum 4622 { 4623 _fieldFBSliceModeSingle = 0, 4624 _fieldFBSliceModeDouble = 1, 4625 _fieldFBSliceModeTriple = 2, 4626 _fieldFBSliceModeCount 4627 } _field_fb_slice_mode_t; 4628 4629 typedef struct 4630 { 4631 int8 fpf1; 4632 int8 fpf2; 4633 int8 fpf3; 4634 int8 fpf4; 4635 } _field_fb_sel_codes_t; 4636 4637 STATIC int _field_fb_group_construct(int unit, _field_control_t *fc, 4638 uint32 slice_mode, _field_stage_id_t stage_id, int slice_index, 4639 bcm_port_t port, _field_fb_sel_codes_t *hw_sel_codes) 4640 { 4641 int rv; 4642 _field_stage_t *stage_fc; 4643 _field_group_t *fg_p; 4644 int part_index; 4645 bcm_field_group_t group_id; 4646 int priority = 0; 4647 int group_flags = 0; 4648 uint16 qualifier_id; 4649 _bcm_field_qual_info_t *stage_qualifier_p; 4650 int config_index; 4651 _bcm_field_qual_conf_t *config_p = NULL; 4652 _bcm_field_selector_t selector; 4653 int qualifier_id_index; 4654 _bcm_field_group_qual_t *part_qualifier_p; 4655 int old_qualifier_count; 4656 int new_qualifier_count; 4657 uint16 *qualifier_ids_p; 4658 _bcm_field_qual_offset_t *qualifier_offsets_p; 4659 _bcm_field_qual_offset_t *offset_p; 4660 bcm_field_qset_t qset; 4661 int action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 4662 int idx; 4663 bcm_pbmp_t group_pbmp; 4664 4665 bcm_field_qset_t_init(&qset); 4666 4667 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc)); 4668 4669 for (fg_p = fc->groups; fg_p != NULL; fg_p = fg_p->next) 4670 { 4671 if (((slice_mode == _fieldFBSliceModeSingle) && 4672 ((fg_p->flags & _FP_GROUP_SPAN_SINGLE_SLICE) == 0)) || 4673 ((slice_mode == _fieldFBSliceModeDouble) && 4674 ((fg_p->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) == 0)) || 4675 ((slice_mode == _fieldFBSliceModeTriple) && 4676 ((fg_p->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) == 0))) 4677 { 4678 /* This group isn't the same width as the one 4679 we're reconstructing */ 4680 4681 continue; 4682 } 4683 4684 /* Check for primary slice numbers - there may be groups with the same 4685 QSET but residing in different slices */ 4686 if (slice_index != fg_p->slices[0].slice_number) { 4687 continue; 4688 } 4689 4690 /* See if selector codes match */ 4691 4692 for (part_index = 0; part_index <= slice_mode; ++part_index) 4693 { 4694 if ((fg_p->sel_codes[part_index].fpf1 != 4695 hw_sel_codes[part_index].fpf1) || 4696 (fg_p->sel_codes[part_index].fpf2 != 4697 hw_sel_codes[part_index].fpf2) || 4698 (fg_p->sel_codes[part_index].fpf3 != 4699 hw_sel_codes[part_index].fpf3) || 4700 (fg_p->sel_codes[part_index].fpf4 != 4701 hw_sel_codes[part_index].fpf4)) 4702 { 4703 /* Selectors don't match */ 4704 4705 break; 4706 } 4707 } 4708 4709 if (part_index <= slice_mode) 4710 { 4711 /* Found a mismatch */ 4712 4713 continue; 4714 } 4715 4716 /* 4717 * If we've gotten this far, everything matches, so add 4718 * the port to the group's PBMP 4719 */ 4720 BCM_PBMP_PORT_ADD(fg_p->pbmp, port); 4721 BCM_PBMP_OR(fg_p->slices[0].pbmp, fg_p->pbmp); 4722 4723 group_flags = 0; 4724 if (fc->l2warm) 4725 { 4726 /* Get stored group ID and qset for level 2 */ 4727 4728 BCM_IF_ERROR_RETURN(_field_group_info_retrieve(unit, port, 4729 _FP_DEF_INST, 4730 &group_id, 4731 &priority, 4732 &action_res_id, 4733 &group_pbmp, 4734 NULL, 4735 &group_flags, 4736 &qset, 4737 fc 4738 ) 4739 ); 4740 4741 if (group_id != -1) 4742 { 4743 sal_memcpy(&fg_p->qset, &qset, sizeof(bcm_field_qset_t)); 4744 4745 fg_p->gid = group_id; 4746 fg_p->priority = priority; 4747 fg_p->action_res_id = action_res_id; 4748 if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) { 4749 fg_p->flags = fg_p->flags | 4750 _FP_GROUP_SELECT_AUTO_EXPANSION; 4751 } 4752 } 4753 } 4754 4755 return BCM_E_NONE; 4756 } 4757 4758 /* No existing groups match; create a new one */ 4759 4760 _FP_XGS3_ALLOC(fg_p, sizeof(_field_group_t), "field group"); 4761 4762 if (fg_p == NULL) 4763 { 4764 return BCM_E_MEMORY; 4765 } 4766 4767 4768 /* Initialize action res id and VMAP group to default */ 4769 action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 4770 for (idx = 0; idx < _FP_PAIR_MAX; idx++) { 4771 fg_p->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT; 4772 } 4773 4774 group_flags = 0; 4775 if (fc->l2warm) 4776 { 4777 /* Get stored group ID and QSET */ 4778 4779 rv = _field_group_info_retrieve(unit, port, _FP_DEF_INST, 4780 &group_id, 4781 &priority, 4782 &action_res_id, 4783 &group_pbmp, 4784 NULL, 4785 &group_flags, 4786 &qset, 4787 fc 4788 ); 4789 4790 if (group_id != -1) 4791 { 4792 sal_memcpy(&fg_p->qset, &qset, sizeof(bcm_field_qset_t)); 4793 } else { 4794 sal_free(fg_p); 4795 return rv; 4796 } 4797 } 4798 else 4799 { 4800 rv = _bcm_field_group_id_generate(unit, &group_id); 4801 priority = slice_index; 4802 } 4803 4804 if (BCM_FAILURE(rv)) 4805 { 4806 sal_free(fg_p); 4807 4808 return rv; 4809 } 4810 4811 fg_p->gid = group_id; 4812 fg_p->priority = priority; 4813 fg_p->action_res_id = action_res_id; 4814 if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) { 4815 fg_p->flags = fg_p->flags | _FP_GROUP_SELECT_AUTO_EXPANSION; 4816 } 4817 fg_p->stage_id = stage_id; 4818 4819 BCM_PBMP_PORT_ADD(fg_p->pbmp, port); 4820 4821 for (part_index = 0; part_index <= slice_mode; ++part_index) 4822 { 4823 fg_p->sel_codes[part_index].fpf1 = hw_sel_codes[part_index].fpf1; 4824 fg_p->sel_codes[part_index].fpf2 = hw_sel_codes[part_index].fpf2; 4825 fg_p->sel_codes[part_index].fpf3 = hw_sel_codes[part_index].fpf3; 4826 fg_p->sel_codes[part_index].fpf4 = hw_sel_codes[part_index].fpf4; 4827 } 4828 4829 switch (slice_mode) 4830 { 4831 case _fieldFBSliceModeSingle: 4832 fg_p->flags |= _FP_GROUP_SPAN_SINGLE_SLICE; 4833 break; 4834 4835 case _fieldFBSliceModeDouble: 4836 fg_p->flags |= _FP_GROUP_SPAN_DOUBLE_SLICE; 4837 break; 4838 4839 case _fieldFBSliceModeTriple: 4840 fg_p->flags |= _FP_GROUP_SPAN_TRIPLE_SLICE; 4841 break; 4842 4843 } 4844 4845 /* Build qset from selectors */ 4846 4847 for (part_index = 0; part_index <= slice_mode; ++part_index) 4848 { 4849 for (qualifier_id = 0; qualifier_id < _bcmFieldQualifyCount; 4850 ++qualifier_id) 4851 { 4852 stage_qualifier_p = stage_fc->f_qual_arr[qualifier_id]; 4853 4854 if (stage_qualifier_p == NULL) 4855 { 4856 /* Qualifier does not exist in this stage */ 4857 4858 continue; 4859 } 4860 4861 for (config_index = 0; config_index < stage_qualifier_p->conf_sz; 4862 ++config_index) 4863 { 4864 config_p = stage_qualifier_p->conf_arr + config_index; 4865 4866 selector = config_p->selector; 4867 4868 /* Check for F1 match */ 4869 4870 if ((selector.pri_sel == _bcmFieldSliceSelFpf1) && 4871 (selector.pri_sel_val == 4872 fg_p->sel_codes[part_index].fpf1)) 4873 { 4874 break; 4875 } 4876 4877 /* Check for F2 match */ 4878 4879 if ((selector.pri_sel == _bcmFieldSliceSelFpf2) && 4880 (selector.pri_sel_val == 4881 fg_p->sel_codes[part_index].fpf2)) 4882 { 4883 break; 4884 } 4885 4886 /* Check for F3 match */ 4887 4888 if ((selector.pri_sel == _bcmFieldSliceSelFpf3) && 4889 (selector.pri_sel_val == 4890 fg_p->sel_codes[part_index].fpf3)) 4891 { 4892 break; 4893 } 4894 4895 /* Check for F4 match */ 4896 4897 if ((selector.pri_sel == _bcmFieldSliceSelFpf4) && 4898 (selector.pri_sel_val == 4899 fg_p->sel_codes[part_index].fpf4)) 4900 { 4901 break; 4902 } 4903 } 4904 4905 if (config_index < stage_qualifier_p->conf_sz) 4906 { 4907 /* Found a match; add the qualifier to the qset */ 4908 4909 BCM_FIELD_QSET_ADD(fg_p->qset, qualifier_id); 4910 4911 part_qualifier_p = &(fg_p->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_index]); 4912 4913 for (qualifier_id_index = 0; 4914 qualifier_id_index < part_qualifier_p->size; 4915 ++qualifier_id_index) 4916 { 4917 if (part_qualifier_p->qid_arr[qualifier_id_index] == 4918 qualifier_id) 4919 { 4920 /* Qualifier already in the qset */ 4921 4922 break; 4923 } 4924 } 4925 4926 if (qualifier_id_index == part_qualifier_p->size) 4927 { 4928 /* Qualifier not already in the qset; add it */ 4929 4930 old_qualifier_count = part_qualifier_p->size; 4931 new_qualifier_count = old_qualifier_count + 1; 4932 4933 qualifier_ids_p = NULL; 4934 qualifier_offsets_p = NULL; 4935 4936 _FP_XGS3_ALLOC(qualifier_ids_p, new_qualifier_count * 4937 sizeof (uint16), "Group qualifier ids"); 4938 4939 if (qualifier_ids_p == NULL) 4940 { 4941 sal_free(fg_p); 4942 return BCM_E_MEMORY; 4943 } 4944 4945 _FP_XGS3_ALLOC(qualifier_offsets_p, new_qualifier_count * 4946 sizeof (_bcm_field_qual_offset_t), 4947 "Group qual offsets"); 4948 4949 if (qualifier_offsets_p == NULL) 4950 { 4951 sal_free(fg_p); 4952 sal_free(qualifier_ids_p); 4953 return BCM_E_MEMORY; 4954 } 4955 4956 if (old_qualifier_count > 0) 4957 { 4958 /* Copy existing data */ 4959 4960 sal_memcpy(qualifier_ids_p, part_qualifier_p->qid_arr, 4961 old_qualifier_count * sizeof (uint16)); 4962 4963 sal_memcpy(qualifier_offsets_p, 4964 part_qualifier_p->offset_arr, 4965 old_qualifier_count * 4966 sizeof (_bcm_field_qual_offset_t)); 4967 4968 sal_free(part_qualifier_p->qid_arr); 4969 sal_free(part_qualifier_p->offset_arr); 4970 } 4971 4972 part_qualifier_p->qid_arr = qualifier_ids_p; 4973 part_qualifier_p->offset_arr = qualifier_offsets_p; 4974 4975 part_qualifier_p->qid_arr[old_qualifier_count] = 4976 qualifier_id; 4977 4978 offset_p = part_qualifier_p->offset_arr + 4979 old_qualifier_count; 4980 4981 sal_memcpy(offset_p, &config_p->offset, 4982 sizeof(config_p->offset)); 4983 4984 part_qualifier_p->size = new_qualifier_count; 4985 4986 _field_qset_udf_bmap_reinit(unit, 4987 stage_fc, 4988 &fg_p->qset, 4989 qualifier_id 4990 ); 4991 } 4992 } 4993 } 4994 } 4995 4996 /* Associate slice with group */ 4997 4998 if (fg_p->slices == NULL) 4999 { 5000 fg_p->slices = stage_fc->slices[_FP_DEF_INST] + slice_index; 5001 } 5002 5003 BCM_PBMP_OR(fg_p->slices[0].pbmp, fg_p->pbmp); 5004 5005 if (fc->l2warm 5006 && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15)) { 5007 if (group_flags & _FP_GROUP_LOOKUP_ENABLED) { 5008 fg_p->flags = fg_p->flags | _FP_GROUP_LOOKUP_ENABLED; 5009 } 5010 if (group_flags & _FP_GROUP_WLAN) { 5011 fg_p->flags = fg_p->flags | _FP_GROUP_WLAN; 5012 } 5013 } else { 5014 fg_p->flags |= _FP_GROUP_LOOKUP_ENABLED; 5015 } 5016 5017 fg_p->next = fc->groups; 5018 fc->groups = fg_p; 5019 5020 return BCM_E_NONE; 5021 } 5022 5023 int _field_fb_slice_is_primary(int unit, int slice_index, 5024 int *is_primary_p, int *slice_mode_p) 5025 { 5026 uint32 fp_slice_config_val; 5027 5028 soc_field_t slice_mode_fields[16] = 5029 { 5030 SLICE_0_MODEf, SLICE_1_MODEf, SLICE_2_MODEf, SLICE_3_MODEf, 5031 SLICE_4_MODEf, SLICE_5_MODEf, SLICE_6_MODEf, SLICE_7_MODEf, 5032 SLICE_8_MODEf, SLICE_9_MODEf, SLICE_10_MODEf, SLICE_11_MODEf, 5033 SLICE_12_MODEf, SLICE_13_MODEf, SLICE_14_MODEf, SLICE_15_MODEf 5034 }; 5035 5036 BCM_IF_ERROR_RETURN(READ_FP_SLICE_CONFIGr(unit, &fp_slice_config_val)); 5037 5038 *slice_mode_p = soc_reg_field_get(unit, FP_SLICE_CONFIGr, 5039 fp_slice_config_val, slice_mode_fields[slice_index]); 5040 5041 if ((*slice_mode_p == _fieldFBSliceModeDouble && slice_index % 2 != 0) || 5042 (*slice_mode_p == _fieldFBSliceModeTriple && slice_index %4 != 0)) 5043 { 5044 *is_primary_p = 0; 5045 } 5046 else 5047 { 5048 *is_primary_p = 1; 5049 } 5050 5051 return BCM_E_NONE; 5052 } 5053 5054 #define _FP_FB_IF_FAILURE_CLEANUP(op) \ 5055 rv = (op); if (BCM_FAILURE(rv)) goto cleanup; 5056 5057 int _field_fb_stage_reinit(int unit, _field_control_t *fc, 5058 _field_stage_t *stage_fc) 5059 { 5060 int rv, idx1; 5061 int temp; 5062 char *fp_tcam_buffer = NULL; 5063 char *fp_port_field_sel_buffer = NULL; 5064 int slice_index; 5065 int slice_mode; 5066 _field_slice_t *fs_p; 5067 int entry_index; 5068 bcm_port_t port; 5069 _field_fb_sel_codes_t sel_codes[_fieldFBSliceModeCount]; 5070 _field_fb_sel_codes_t *sel_codes_p; 5071 uint32 fp_f4_select_value; 5072 char *fp_policy_table_buffer = NULL; 5073 fp_tcam_entry_t *fp_tcam_entry_p; 5074 bcm_pbmp_t entry_pbmp; 5075 _field_group_t *fg_p; 5076 _field_slice_t *group_slice_p; 5077 int part_count; 5078 _field_entry_t *entries_p; 5079 int primary_tcam_index; 5080 int part_slice_index; 5081 int part_tcam_index; 5082 int part_index; 5083 fp_port_field_sel_entry_t *port_field_sel_entry_p; 5084 _field_entry_t *entry_p = NULL; 5085 _bcm_field_group_qual_t *part_qualifier_p; 5086 int group_qualifier_index; 5087 int qualifier_id; 5088 _bcm_field_qual_info_t *stage_qualifier_p; 5089 int config_index; 5090 _bcm_field_qual_offset_t *config_offset_p; 5091 _bcm_field_qual_offset_t *group_qualifier_offset_p; 5092 fp_policy_table_entry_t *policy_entry_p; 5093 uint32 ipbm_sel_value, pbm; 5094 _bcm_field_selector_t config_selector; 5095 int selector; 5096 uint8 selector_value; 5097 int multigroup; 5098 int prev_prio; 5099 int slice_is_primary; 5100 uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0]; 5101 uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1]; 5102 bcm_pbmp_t temp_pbmp; 5103 _field_action_bmp_t action_bmp; 5104 _field_entry_wb_info_t f_ent_wb_info; 5105 5106 soc_field_t slice_f1_fields[16] = 5107 { 5108 SLICE0_F1f, SLICE1_F1f, SLICE2_F1f, SLICE3_F1f, 5109 SLICE4_F1f, SLICE5_F1f, SLICE6_F1f, SLICE7_F1f, 5110 SLICE8_F1f, SLICE9_F1f, SLICE10_F1f, SLICE11_F1f, 5111 SLICE12_F1f, SLICE13_F1f, SLICE14_F1f, SLICE15_F1f, 5112 }; 5113 5114 soc_field_t slice_f2_fields[16] = 5115 { 5116 SLICE0_F2f, SLICE1_F2f, SLICE2_F2f, SLICE3_F2f, 5117 SLICE4_F2f, SLICE5_F2f, SLICE6_F2f, SLICE7_F2f, 5118 SLICE8_F2f, SLICE9_F2f, SLICE10_F2f, SLICE11_F2f, 5119 SLICE12_F2f, SLICE13_F2f, SLICE14_F2f, SLICE15_F2f, 5120 }; 5121 5122 soc_field_t slice_f3_fields[16] = 5123 { 5124 SLICE0_F3f, SLICE1_F3f, SLICE2_F3f, SLICE3_F3f, 5125 SLICE4_F3f, SLICE5_F3f, SLICE6_F3f, SLICE7_F3f, 5126 SLICE8_F3f, SLICE9_F3f, SLICE10_F3f, SLICE11_F3f, 5127 SLICE12_F3f, SLICE13_F3f, SLICE14_F3f, SLICE15_F3f, 5128 }; 5129 5130 soc_field_t slice_f4_fields[16] = 5131 { 5132 SLICE_0_F4f, SLICE_1_F4f, SLICE_2_F4f, SLICE_3_F4f, 5133 SLICE_4_F4f, SLICE_5_F4f, SLICE_6_F4f, SLICE_7_F4f, 5134 SLICE_8_F4f, SLICE_9_F4f, SLICE_10_F4f, SLICE_11_F4f, 5135 SLICE_12_F4f, SLICE_13_F4f, SLICE_14_F4f, SLICE_15_F4f, 5136 }; 5137 5138 5139 /* Clear selector codes, set as invalid */ 5140 sal_memset(&sel_codes, (int8)_FP_SELCODE_DONT_CARE, 5141 sizeof(_field_fb_sel_codes_t)); 5142 5143 /* Reset Action bitmap to NULL. */ 5144 action_bmp.w = NULL; 5145 5146 fc->scache_pos = 0; 5147 fc->scache_pos1 = 0; 5148 5149 if (fc->l2warm) { 5150 if ((fc->wb_recovered_version) > (fc->wb_current_version)) { 5151 /* Notify the application with an event */ 5152 /* The application will then need to reconcile the 5153 version differences using the documented behavioral 5154 differences on per module (handle) basis */ 5155 SOC_IF_ERROR_RETURN 5156 (soc_event_generate(unit, SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE, 5157 BCM_MODULE_FIELD, (fc->wb_recovered_version), 5158 (fc->wb_current_version))); 5159 } 5160 5161 fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE; 5162 5163 if(NULL != fc->scache_ptr[_FIELD_SCACHE_PART_1]) { 5164 if ((fc->wb_recovered_version) > (fc->wb_current_version)) { 5165 /* Notify the application with an event */ 5166 /* The application will then need to reconcile the 5167 version differences using the documented behavioral 5168 differences on per module (handle) basis */ 5169 SOC_IF_ERROR_RETURN 5170 (soc_event_generate(unit, 5171 SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE, 5172 BCM_MODULE_FIELD, (fc->wb_recovered_version), 5173 (fc->wb_current_version))); 5174 } 5175 5176 fc->scache_pos1 += SOC_WB_SCACHE_CONTROL_SIZE; 5177 } 5178 } 5179 5180 if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) 5181 { 5182 return BCM_E_PARAM; 5183 } 5184 5185 LOG_DEBUG(BSL_LS_BCM_FP, 5186 (BSL_META_U(unit, 5187 "Beginning ingress stage recovery.\n"))); 5188 5189 if (fc->l2warm) { 5190 rv = _field_scache_stage_hdr_chk(fc, _FIELD_IFP_DATA_START); 5191 if (BCM_FAILURE(rv)) { 5192 return (rv); 5193 } 5194 } 5195 5196 /* Read TCAM into memory */ 5197 5198 _FP_FB_IF_FAILURE_CLEANUP(_field_table_read(unit, FP_TCAMm, 5199 &fp_tcam_buffer, "FP_TCAM buffer")); 5200 5201 /* Read FP_PORT_FIELD_SEL into memory */ 5202 5203 _FP_FB_IF_FAILURE_CLEANUP(_field_table_read(unit, 5204 FP_PORT_FIELD_SELm, &fp_port_field_sel_buffer, 5205 "FP_PORT_FIELD_SEL buffer")); 5206 5207 /* Read FP_POLICY_TABLE table into memory */ 5208 5209 _FP_FB_IF_FAILURE_CLEANUP(_field_table_read(unit, 5210 FP_POLICY_TABLEm, &fp_policy_table_buffer, 5211 "FP_POLICY_TABLE")); 5212 5213 /* Read F4 selectors */ 5214 5215 _FP_FB_IF_FAILURE_CLEANUP(READ_FP_F4_SELECTr(unit, &fp_f4_select_value)); 5216 5217 /* Recover range checkers */ 5218 rv = _field_range_check_reinit(unit, stage_fc, fc); 5219 if (BCM_FAILURE(rv)) { 5220 goto cleanup; 5221 } 5222 5223 /* Recover data qualifiers */ 5224 rv = _field_data_qual_recover(unit, fc, stage_fc); 5225 if (BCM_FAILURE(rv)) { 5226 goto cleanup; 5227 } 5228 5229 for (slice_index = 0; slice_index < stage_fc->tcam_slices; ++slice_index) 5230 { 5231 LOG_DEBUG(BSL_LS_BCM_FP, 5232 (BSL_META_U(unit, 5233 " Checking slice %d...\n"), 5234 slice_index)); 5235 5236 _FP_FB_IF_FAILURE_CLEANUP(_field_fb_slice_is_primary(unit, 5237 slice_index, &slice_is_primary, &slice_mode)); 5238 5239 if (!slice_is_primary) 5240 { 5241 /* Don't need selectors for second slice of double or for 5242 second and third slices of triple */ 5243 5244 LOG_DEBUG(BSL_LS_BCM_FP, 5245 (BSL_META_U(unit, 5246 " Not a primary slice.\n"))); 5247 5248 continue; 5249 } 5250 5251 /* Check if the slice has any valid entries */ 5252 5253 fs_p = stage_fc->slices[_FP_DEF_INST] + slice_index; 5254 5255 for (entry_index = 0; entry_index < fs_p->entry_count; ++entry_index) 5256 { 5257 fp_tcam_entry_p = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 5258 fp_tcam_entry_t *, fp_tcam_buffer, 5259 entry_index + fs_p->entry_count * slice_index); 5260 5261 if (soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, VALIDf) != 0) 5262 { 5263 /* There's at least one valid entry in the slice */ 5264 5265 break; 5266 } 5267 } 5268 5269 if ((entry_index == fs_p->entry_count) && !fc->l2warm) 5270 { 5271 /* No valid groups and entries in the slice */ 5272 5273 LOG_DEBUG(BSL_LS_BCM_FP, 5274 (BSL_META_U(unit, 5275 " No valid groups and entries in slice.\n"))); 5276 5277 continue; 5278 } 5279 5280 if (fc->l2warm) 5281 { 5282 /* Retrieve the group IDs in this slice */ 5283 5284 rv = _field_scache_slice_group_recover(unit, fc, 5285 slice_index, &multigroup); 5286 5287 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 5288 fc->l2warm = 0; 5289 goto cleanup; 5290 } 5291 if (rv == BCM_E_NOT_FOUND) { 5292 rv = BCM_E_NONE; 5293 continue; 5294 } 5295 } 5296 5297 PBMP_ALL_ITER(unit, port) 5298 { 5299 port_field_sel_entry_p = soc_mem_table_idx_to_pointer( 5300 unit, FP_PORT_FIELD_SELm, fp_port_field_sel_entry_t *, 5301 fp_port_field_sel_buffer, port); 5302 5303 for (part_index = 0; part_index < COUNTOF(sel_codes); ++part_index) { 5304 sel_codes[part_index].fpf1 = _FP_SELCODE_DONT_CARE; 5305 sel_codes[part_index].fpf2 = _FP_SELCODE_DONT_CARE; 5306 sel_codes[part_index].fpf3 = _FP_SELCODE_DONT_CARE; 5307 sel_codes[part_index].fpf4 = _FP_SELCODE_DONT_CARE; 5308 } 5309 5310 for (part_index = 0; part_index <= slice_mode; ++part_index) 5311 { 5312 sel_codes_p = sel_codes + part_index; 5313 5314 sel_codes_p->fpf1 = soc_FP_PORT_FIELD_SELm_field32_get( 5315 unit, port_field_sel_entry_p, 5316 slice_f1_fields[slice_index + part_index]); 5317 5318 sel_codes_p->fpf2 = soc_FP_PORT_FIELD_SELm_field32_get( 5319 unit, port_field_sel_entry_p, 5320 slice_f2_fields[slice_index + part_index]); 5321 5322 sel_codes_p->fpf3 = soc_FP_PORT_FIELD_SELm_field32_get( 5323 unit, port_field_sel_entry_p, 5324 slice_f3_fields[slice_index + part_index]); 5325 5326 sel_codes_p->fpf4 = soc_reg_field_get(unit, FP_F4_SELECTr, 5327 fp_f4_select_value, slice_f4_fields[slice_index + 5328 part_index]); 5329 } 5330 5331 _FP_FB_IF_FAILURE_CLEANUP(_field_fb_group_construct(unit, 5332 fc, slice_mode, stage_fc->stage_id, slice_index, port, 5333 sel_codes)); 5334 } 5335 5336 /* Recover entries in this slice */ 5337 5338 fs_p = stage_fc->slices[_FP_DEF_INST] + slice_index; 5339 prev_prio = -1; 5340 5341 for (entry_index = 0; entry_index < fs_p->entry_count; ++entry_index) 5342 { 5343 fp_tcam_entry_p = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 5344 fp_tcam_entry_t *, fp_tcam_buffer, entry_index + 5345 slice_index * fs_p->entry_count); 5346 5347 if (soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, VALIDf) == 0) 5348 { 5349 /* Skip empty entry */ 5350 5351 continue; 5352 } 5353 5354 LOG_DEBUG(BSL_LS_BCM_FP, 5355 (BSL_META_U(unit, 5356 " Checking entry %d...\n"), 5357 entry_index)); 5358 5359 /* Determine pbmp for this entry */ 5360 5361 ipbm_sel_value = 5362 soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, IPBM_SELf); 5363 SOC_PBMP_CLEAR(entry_pbmp); 5364 5365 if ((soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, 5366 IPBM_SEL_MASKf) != 0) && (ipbm_sel_value != 0)) 5367 { 5368 SOC_PBMP_WORD_SET(entry_pbmp, 0, ipbm_sel_value); 5369 } 5370 else if ((fp_f4_select_value == 0) && 5371 soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, F4_MASKf)) 5372 { 5373 pbm = soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, F4f) & 5374 soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, F4_MASKf); 5375 SOC_PBMP_PORT_ADD(entry_pbmp, pbm); 5376 } 5377 else 5378 { 5379 SOC_PBMP_ASSIGN(entry_pbmp, PBMP_ALL(unit)); 5380 } 5381 5382 /* Find a matching group */ 5383 5384 for (fg_p = fc->groups; fg_p != NULL; fg_p = fg_p->next) 5385 { 5386 group_slice_p = fg_p->slices; 5387 5388 if (group_slice_p->slice_number != slice_index) 5389 { 5390 /* Not this slice */ 5391 5392 continue; 5393 } 5394 5395 SOC_PBMP_CLEAR(temp_pbmp); 5396 SOC_PBMP_ASSIGN(temp_pbmp, fg_p->pbmp); 5397 SOC_PBMP_OR(temp_pbmp, PBMP_LB(unit)); 5398 SOC_PBMP_AND(temp_pbmp, entry_pbmp); 5399 if (SOC_PBMP_EQ(temp_pbmp, entry_pbmp)) 5400 { 5401 /* Found a match */ 5402 5403 break; 5404 } 5405 5406 /* Check if entry pbmp is a subset of the group pbmp */ 5407 5408 SOC_PBMP_ITER(entry_pbmp, port) 5409 { 5410 if (SOC_PBMP_MEMBER(fg_p->pbmp, port) == 0) 5411 { 5412 break; 5413 } 5414 } 5415 5416 if (port == SOC_PBMP_PORT_MAX) 5417 { 5418 /* Got all the way through with no mismatches */ 5419 5420 break; 5421 } 5422 } 5423 5424 if (fg_p == NULL) 5425 { 5426 /* This should never happen */ 5427 5428 LOG_ERROR(BSL_LS_BCM_FP, 5429 (BSL_META_U(unit, 5430 "Could not find a matching group for entry %d.\n"), 5431 entry_index)); 5432 5433 return BCM_E_INTERNAL; 5434 } 5435 5436 /* Allocate the entry */ 5437 5438 _FP_FB_IF_FAILURE_CLEANUP( 5439 _bcm_field_entry_tcam_parts_count(unit, fg_p->stage_id, 5440 fg_p->flags, &part_count)); 5441 5442 entries_p = NULL; 5443 5444 _FP_XGS3_ALLOC(entries_p, part_count * sizeof (_field_entry_t), 5445 "field entry"); 5446 5447 if (entries_p == NULL) 5448 { 5449 rv = BCM_E_MEMORY; 5450 5451 goto cleanup; 5452 } 5453 5454 for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) { 5455 entries_p->policer[idx1].pid = _FP_INVALID_INDEX; 5456 } 5457 5458 5459 LOG_DEBUG(BSL_LS_BCM_FP, 5460 (BSL_META_U(unit, 5461 " Entry matches group %d.\n"), 5462 fg_p->gid)); 5463 5464 sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t)); 5465 f_ent_wb_info.sid = -1; 5466 f_ent_wb_info.pid = -1; 5467 5468 if (fc->l2warm) 5469 { 5470 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 5471 action_bmp.w = NULL; 5472 _FP_XGS3_ALLOC(action_bmp.w, 5473 SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount), 5474 "Action No Param Bitmap"); 5475 if (action_bmp.w == NULL) { 5476 rv = BCM_E_MEMORY; 5477 sal_free(entries_p); 5478 goto cleanup; 5479 } 5480 } 5481 f_ent_wb_info.action_bmp = &action_bmp; 5482 5483 rv = _field_entry_info_retrieve(unit, fc, stage_fc, 5484 multigroup, &prev_prio, &f_ent_wb_info); 5485 5486 if (BCM_FAILURE(rv)) 5487 { 5488 LOG_ERROR(BSL_LS_BCM_FP, 5489 (BSL_META_U(unit, 5490 "Failed to retrieve entry info."))); 5491 5492 sal_free(entries_p); 5493 5494 goto cleanup; 5495 } 5496 if (action_bmp.w != NULL) { 5497 _FP_ACTION_BMP_FREE(action_bmp); 5498 action_bmp.w = NULL; 5499 } 5500 5501 } 5502 else 5503 { 5504 _bcm_field_last_alloc_eid_incr(unit); 5505 5506 f_ent_wb_info.eid = _bcm_field_last_alloc_eid_get(unit); 5507 } 5508 5509 primary_tcam_index = 5510 slice_index * fs_p->entry_count + entry_index; 5511 5512 for (part_index = 0; part_index < part_count; ++part_index) 5513 { 5514 entry_p = entries_p + part_index; 5515 5516 entry_p->eid = f_ent_wb_info.eid; 5517 entry_p->group = fg_p; 5518 /* Set retrieved dvp_type and svp_type */ 5519 entry_p->dvp_type = f_ent_wb_info.dvp_type[part_index]; 5520 entry_p->svp_type = f_ent_wb_info.svp_type[part_index]; 5521 5522 /* Set entry flags */ 5523 rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, 5524 fg_p, &entry_p->flags); 5525 if (BCM_FAILURE(rv)) { 5526 sal_free(entries_p); 5527 goto cleanup; 5528 } 5529 5530 if (f_ent_wb_info.color_independent) 5531 { 5532 entry_p->flags |= _FP_ENTRY_COLOR_INDEPENDENT; 5533 } 5534 5535 /* Get index of entry in tcam */ 5536 5537 rv = _bcm_field_entry_part_tcam_idx_get(unit, entries_p, 5538 primary_tcam_index, part_index, &part_tcam_index); 5539 if (BCM_FAILURE(rv)) { 5540 sal_free(entries_p); 5541 goto cleanup; 5542 } 5543 5544 /* Get slice and index within the slice */ 5545 5546 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc, 5547 _FP_DEF_INST, part_tcam_index, &part_slice_index, 5548 (int *) (&entry_p->slice_idx)); 5549 if (BCM_FAILURE(rv)) { 5550 sal_free(entries_p); 5551 goto cleanup; 5552 } 5553 5554 /* Point the entry to its slice */ 5555 5556 entry_p->fs = stage_fc->slices[_FP_DEF_INST] + part_slice_index; 5557 --entry_p->fs->free_count; 5558 5559 /* Set the slice pbmp */ 5560 5561 BCM_PBMP_OR(entry_p->fs->pbmp, fg_p->pbmp); 5562 5563 /* Assign entry to slice */ 5564 5565 entry_p->fs->entries[entry_p->slice_idx] = entry_p; 5566 entry_p->flags |= _FP_ENTRY_INSTALLED; 5567 5568 if (soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, VALIDf) == 3) { 5569 entry_p->flags |= _FP_ENTRY_ENABLED; 5570 } 5571 /* Skip empty entry */ 5572 fp_tcam_entry_p = 5573 (fp_tcam_entry_t *) soc_mem_table_idx_to_pointer(unit, 5574 FP_TCAMm, fp_tcam_entry_t *, fp_tcam_buffer, 5575 part_tcam_index); 5576 5577 part_qualifier_p = &(fg_p->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_index]); 5578 5579 for (group_qualifier_index = 0; 5580 group_qualifier_index < part_qualifier_p->size; 5581 ++group_qualifier_index) 5582 { 5583 qualifier_id = 5584 part_qualifier_p->qid_arr[group_qualifier_index]; 5585 5586 stage_qualifier_p = stage_fc->f_qual_arr[qualifier_id]; 5587 5588 for (config_index = 0; 5589 config_index < stage_qualifier_p->conf_sz; 5590 ++config_index) 5591 { 5592 config_offset_p = &((stage_qualifier_p->conf_arr + 5593 config_index)->offset); 5594 5595 group_qualifier_offset_p = 5596 part_qualifier_p->offset_arr + 5597 group_qualifier_index; 5598 5599 if (_mask_is_set(unit, config_offset_p, 5600 (uint32 *) fp_tcam_entry_p, 5601 stage_fc->stage_id) != 0) 5602 { 5603 config_selector = stage_qualifier_p-> 5604 conf_arr[config_index].selector; 5605 5606 selector = config_selector.pri_sel; 5607 selector_value = config_selector.pri_sel_val; 5608 5609 if ((selector == _bcmFieldSliceSelFpf1 && 5610 selector_value == sel_codes[part_index].fpf1) || 5611 (selector == _bcmFieldSliceSelFpf2 && 5612 selector_value == sel_codes[part_index].fpf2) || 5613 (selector == _bcmFieldSliceSelFpf3 && 5614 selector_value == sel_codes[part_index].fpf3) || 5615 (selector == _bcmFieldSliceSelFpf4 && 5616 selector_value == sel_codes[part_index].fpf4)) 5617 { 5618 /* This qualifier exists in this entry */ 5619 5620 *group_qualifier_offset_p = *config_offset_p; 5621 5622 /* No need to check more configs */ 5623 5624 break; 5625 } 5626 } 5627 } 5628 } 5629 5630 /* Get the actions for this part of the entry */ 5631 5632 policy_entry_p = soc_mem_table_idx_to_pointer(unit, 5633 FP_POLICY_TABLEm, fp_policy_table_entry_t *, 5634 fp_policy_table_buffer, part_tcam_index); 5635 5636 rv = _field_fb_actions_recover(unit, 5637 (uint32 *)policy_entry_p, entries_p, part_index, 5638 FP_POLICY_TABLEm, &f_ent_wb_info); 5639 if (BCM_FAILURE(rv)) { 5640 sal_free(entries_p); 5641 goto cleanup; 5642 } 5643 5644 entry_p->prio = fc->l2warm ? f_ent_wb_info.prio : 5645 (slice_index << 10) | (fs_p->entry_count - entry_index); 5646 5647 } 5648 LOG_DEBUG(BSL_LS_BCM_FP, 5649 (BSL_META_U(unit, 5650 " Entry id = %d, priority = %d.\n"), 5651 entries_p->eid, 5652 entries_p->prio)); 5653 5654 /* Add the entry to the group */ 5655 5656 rv = _field_group_entry_add(unit, fg_p, entries_p); 5657 5658 if (rv != BCM_E_NONE) { 5659 sal_free(entries_p); 5660 5661 goto cleanup; 5662 } 5663 } 5664 5665 if (fc->l2warm) 5666 { 5667 _field_scache_slice_group_free(unit, fc, slice_index); 5668 } 5669 } 5670 5671 if (fc->l2warm) { 5672 5673 /* Mark end of Slice Info */ 5674 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 5675 fc->scache_pos++; 5676 } 5677 5678 /* Group Slice Selectors */ 5679 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 5680 rv = (_field_group_slice_selectors_recover(unit, 5681 &buf[fc->scache_pos], stage_fc->stage_id)); 5682 if (BCM_FAILURE(rv)) { 5683 goto cleanup; 5684 } 5685 } 5686 5687 temp = 0; 5688 temp |= buf[fc->scache_pos]; 5689 fc->scache_pos++; 5690 temp |= buf[fc->scache_pos] << 8; 5691 fc->scache_pos++; 5692 temp |= buf[fc->scache_pos] << 16; 5693 fc->scache_pos++; 5694 temp |= buf[fc->scache_pos] << 24; 5695 fc->scache_pos++; 5696 if (temp != _FIELD_IFP_DATA_END) { 5697 fc->l2warm = 0; 5698 rv = BCM_E_INTERNAL; 5699 } 5700 5701 if (NULL != buf1) { 5702 temp = 0; 5703 temp |= buf1[fc->scache_pos1]; 5704 fc->scache_pos1++; 5705 temp |= buf1[fc->scache_pos1] << 8; 5706 fc->scache_pos1++; 5707 temp |= buf1[fc->scache_pos1] << 16; 5708 fc->scache_pos1++; 5709 temp |= buf1[fc->scache_pos1] << 24; 5710 fc->scache_pos1++; 5711 if (temp != _FIELD_IFP_DATA_END) { 5712 fc->l2warm = 0; 5713 rv = BCM_E_INTERNAL; 5714 } 5715 } 5716 } 5717 5718 LOG_DEBUG(BSL_LS_BCM_FP, 5719 (BSL_META_U(unit, 5720 "Ingress stage recovery complete.\n"))); 5721 5722 cleanup: 5723 if (fp_tcam_buffer != NULL) 5724 { 5725 soc_cm_sfree(unit, fp_tcam_buffer); 5726 } 5727 if (fp_port_field_sel_buffer != NULL) 5728 { 5729 soc_cm_sfree(unit, fp_port_field_sel_buffer); 5730 } 5731 if (fp_policy_table_buffer != NULL) 5732 { 5733 soc_cm_sfree(unit, fp_policy_table_buffer); 5734 } 5735 if (action_bmp.w != NULL) { 5736 _FP_ACTION_BMP_FREE(action_bmp); 5737 action_bmp.w = NULL; 5738 } 5739 5740 LOG_DEBUG(BSL_LS_BCM_FP, 5741 (BSL_META_U(unit, 5742 "Leaving ingress stage recovery.\n"))); 5743 5744 return rv; 5745 } 5746 #else 5747 #define _field_fb_stage_reinit (NULL) 5748 #endif /* BCM_WARM_BOOT_SUPPORT */ 5749 5750 /* 5751 * Function: 5752 * _field_fb_tcam_policy_mem_get 5753 * 5754 * Purpose: 5755 * Get tcam & policy memories for a specific chip pipeline stage. 5756 * 5757 * Parameters: 5758 * unit - (IN)BCM device number. 5759 * stage_id - (IN)FP stage pipeline id. 5760 * tcam_mem - (IN)Tcam memory id. 5761 * policy_mem - (IN)Policy memory id. 5762 * 5763 * Returns: 5764 * BCM_E_XXX 5765 */ 5766 int 5767 _field_fb_tcam_policy_mem_get(int unit, _field_stage_id_t stage_id, 5768 soc_mem_t *tcam_mem, soc_mem_t *policy_mem) 5769 { 5770 5771 /* Input parameters check. */ 5772 if ((NULL == tcam_mem) || (NULL == policy_mem)) { 5773 return (BCM_E_PARAM); 5774 } 5775 5776 if (_BCM_FIELD_STAGE_INGRESS == stage_id) { 5777 *tcam_mem = FP_TCAMm; 5778 *policy_mem= FP_POLICY_TABLEm; 5779 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 5780 } else if (soc_feature(unit, soc_feature_field_multi_stage)) { 5781 if (_BCM_FIELD_STAGE_EGRESS == stage_id) { 5782 *tcam_mem = EFP_TCAMm; 5783 *policy_mem = EFP_POLICY_TABLEm; 5784 } else if (_BCM_FIELD_STAGE_LOOKUP== stage_id) { 5785 *tcam_mem = VFP_TCAMm; 5786 *policy_mem = VFP_POLICY_TABLEm; 5787 } else { 5788 /* Unknown stage specified */ 5789 (*policy_mem) = (*tcam_mem) = INVALIDm; 5790 return (BCM_E_PARAM); 5791 } 5792 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 5793 } else { 5794 /* Not ingress stage specified while multi stage is not enabled */ 5795 (*policy_mem) = (*tcam_mem) = INVALIDm; 5796 return (BCM_E_UNAVAIL); 5797 } 5798 return (BCM_E_NONE); 5799 } 5800 5801 #ifdef BCM_FIREBOLT2_SUPPORT 5802 /* 5803 * Function: 5804 * _field_fb2_lookup_qualifiers_init 5805 * Purpose: 5806 * Initialize device stage lookup qaualifiers 5807 * select codes & offsets 5808 * Parameters: 5809 * unit - (IN) BCM device number. 5810 * stage_fc - (IN) Field Processor stage control structure. 5811 * 5812 * Returns: 5813 * BCM_E_NONE 5814 */ 5815 STATIC int 5816 _field_fb2_lookup_qualifiers_init(int unit, _field_stage_t *stage_fc) 5817 { 5818 int rv; /* Operation return status. */ 5819 _FP_QUAL_DECL; 5820 _key_fld_ = KEYf; 5821 5822 /* Input parameters check. */ 5823 if (NULL == stage_fc) { 5824 return (BCM_E_PARAM); 5825 } 5826 5827 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStageLookup, 5828 _bcmFieldSliceSelDisable, 0, 0, 0); 5829 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp4, 5830 _bcmFieldSliceSelDisable, 0, 0, 0); 5831 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp6, 5832 _bcmFieldSliceSelDisable, 0, 0, 0); 5833 5834 /* 5835 * Enable the overlay of Sender Ethernet Address onto 5836 * MACSA on ARP/RARP packets. 5837 */ 5838 rv = soc_reg_field32_modify(unit, ING_CONFIGr, REG_PORT_ANY, 5839 ARP_VALIDATION_ENf, 1); 5840 BCM_IF_ERROR_RETURN(rv); 5841 5842 /* FPF3 */ 5843 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerTpid, 5844 _bcmFieldSliceSelFpf3, 0, 0, 2); 5845 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterTpid, 5846 _bcmFieldSliceSelFpf3, 0, 0, 2); 5847 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format, 5848 _bcmFieldSliceSelFpf3, 0, 4, 2); 5849 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy, 5850 _bcmFieldSliceSelFpf3, 0, 6, 1); 5851 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig, 5852 _bcmFieldSliceSelFpf3, 0, 7, 1); 5853 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 5854 _bcmFieldSliceSelFpf3, 0, 8, 16); 5855 5856 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerTpid, 5857 _bcmFieldSliceSelFpf3, 1, 0, 2); 5858 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterTpid, 5859 _bcmFieldSliceSelFpf3, 1, 0, 2); 5860 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format, 5861 _bcmFieldSliceSelFpf3, 1, 4, 2); 5862 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy, 5863 _bcmFieldSliceSelFpf3, 1, 6, 1); 5864 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig, 5865 _bcmFieldSliceSelFpf3, 1, 7, 1); 5866 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 5867 _bcmFieldSliceSelFpf3, 1, 8, 16); 5868 5869 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerTpid, 5870 _bcmFieldSliceSelFpf3, 2, 0, 2); 5871 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterTpid, 5872 _bcmFieldSliceSelFpf3, 2, 0, 2); 5873 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format, 5874 _bcmFieldSliceSelFpf3, 2, 4, 2); 5875 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy, 5876 _bcmFieldSliceSelFpf3, 2, 6, 1); 5877 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig, 5878 _bcmFieldSliceSelFpf3, 2, 7, 1); 5879 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 5880 _bcmFieldSliceSelFpf3, 2, 8, 16); 5881 5882 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerTpid, 5883 _bcmFieldSliceSelFpf3, 3, 0, 2); 5884 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterTpid, 5885 _bcmFieldSliceSelFpf3, 3, 0, 2); 5886 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format, 5887 _bcmFieldSliceSelFpf3, 3, 4, 2); 5888 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy, 5889 _bcmFieldSliceSelFpf3, 3, 6, 1); 5890 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig, 5891 _bcmFieldSliceSelFpf3, 3, 7, 1); 5892 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan, 5893 _bcmFieldSliceSelFpf3, 3, 8, 16); 5894 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri, 5895 _bcmFieldSliceSelFpf3, 3, 8, 3); 5896 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi, 5897 _bcmFieldSliceSelFpf3, 3, 11, 1); 5898 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId, 5899 _bcmFieldSliceSelFpf3, 3, 12, 12); 5900 5901 /* FPF2 */ 5902 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 5903 _bcmFieldSliceSelFpf2, 0, 24, 8); 5904 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 5905 _bcmFieldSliceSelFpf2, 0, 32, 6); 5906 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 5907 _bcmFieldSliceSelFpf2, 0, 38, 2); 5908 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 5909 _bcmFieldSliceSelFpf2, 0, 40, 8); 5910 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 5911 _bcmFieldSliceSelFpf2, 0, 48, 16); 5912 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 5913 _bcmFieldSliceSelFpf2, 0, 64, 16); 5914 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 5915 _bcmFieldSliceSelFpf2, 0, 80, 8); 5916 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 5917 _bcmFieldSliceSelFpf2, 0, 88, 32); 5918 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 5919 _bcmFieldSliceSelFpf2, 0, 120, 32); 5920 5921 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6, 5922 _bcmFieldSliceSelFpf2, 1, 24, 128); 5923 5924 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6, 5925 _bcmFieldSliceSelFpf2, 2, 24, 128); 5926 5927 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 5928 _bcmFieldSliceSelFpf2, 3, 40, 16); 5929 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac, 5930 _bcmFieldSliceSelFpf2, 3, 56, 48); 5931 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac, 5932 _bcmFieldSliceSelFpf2, 3, 104, 48); 5933 5934 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 5935 _bcmFieldSliceSelFpf2, 4, 24, 8); 5936 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 5937 _bcmFieldSliceSelFpf2, 4, 32, 8); 5938 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 5939 _bcmFieldSliceSelFpf2, 4, 40, 32); 5940 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 5941 _bcmFieldSliceSelFpf2, 4, 72, 32); 5942 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac, 5943 _bcmFieldSliceSelFpf2, 4, 104, 48); 5944 5945 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 5946 _bcmFieldSliceSelFpf2, 5, 24, 8); 5947 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 5948 _bcmFieldSliceSelFpf2, 5, 32, 8); 5949 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 5950 _bcmFieldSliceSelFpf2, 5, 40, 32); 5951 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 5952 _bcmFieldSliceSelFpf2, 5, 72, 32); 5953 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac, 5954 _bcmFieldSliceSelFpf2, 5, 104, 48); 5955 5956 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6High, 5957 _bcmFieldSliceSelFpf2, 6, 24, 64); 5958 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6High, 5959 _bcmFieldSliceSelFpf2, 6, 88, 64); 5960 5961 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySnap, 5962 _bcmFieldSliceSelFpf2, 7, 88, 40); 5963 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyLlc, 5964 _bcmFieldSliceSelFpf2, 7, 128, 24); 5965 /* FPF1 */ 5966 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocolCommon, 5967 _bcmFieldSliceSelFpf1, 0, 152, 3); 5968 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 5969 _bcmFieldSliceSelFpf1, 0, 155, 16); 5970 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 5971 _bcmFieldSliceSelFpf1, 0, 155, 3); 5972 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 5973 _bcmFieldSliceSelFpf1, 0, 158, 1); 5974 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 5975 _bcmFieldSliceSelFpf1, 0, 159, 12); 5976 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat, 5977 _bcmFieldSliceSelFpf1, 0, 171, 2); 5978 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort, 5979 _bcmFieldSliceSelFpf1, 0, 173, 5); 5980 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInterfaceClassPort, 5981 _bcmFieldSliceSelFpf1, 0, 178, 4); 5982 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 5983 _bcmFieldSliceSelFpf1, 0, 182, 2); 5984 5985 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 5986 _bcmFieldDevSelIntrasliceVfpKey, 0, 5987 _bcmFieldSliceSelFpf2, 0, 5988 _bcmFieldSliceSelDisable, 0, 1, 5989 0, 8, 0, 0, 0, 0, 0); 5990 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 5991 _bcmFieldDevSelIntrasliceVfpKey, 0, 5992 _bcmFieldSliceSelFpf2, 0, 5993 _bcmFieldSliceSelDisable, 0, 1, 5994 8, 16, 0, 0, 0, 0, 0); 5995 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyTtl, 5996 _bcmFieldDevSelIntrasliceVfpKey, 0, 5997 _bcmFieldSliceSelFpf2, 0, 5998 _bcmFieldSliceSelDisable, 0, 1, 5999 24, 8, 0, 0, 0, 0, 0); 6000 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6001 _bcmFieldDevSelIntrasliceVfpKey, 0, 6002 _bcmFieldSliceSelFpf2, 0, 6003 _bcmFieldSliceSelDisable, 0, 1, 6004 32, 6, 0, 0, 0, 0, 0); 6005 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 6006 _bcmFieldDevSelIntrasliceVfpKey, 0, 6007 _bcmFieldSliceSelFpf2, 0, 6008 _bcmFieldSliceSelDisable, 0, 1, 6009 38, 2, 0, 0, 0, 0, 0); 6010 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 6011 _bcmFieldDevSelIntrasliceVfpKey, 0, 6012 _bcmFieldSliceSelFpf2, 0, 6013 _bcmFieldSliceSelDisable, 0, 1, 6014 64, 16, 0, 0, 0, 0, 0); 6015 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6016 _bcmFieldDevSelIntrasliceVfpKey, 0, 6017 _bcmFieldSliceSelFpf2, 0, 6018 _bcmFieldSliceSelDisable, 0, 1, 6019 80, 8, 0, 0, 0, 0, 0); 6020 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6021 _bcmFieldDevSelIntrasliceVfpKey, 0, 6022 _bcmFieldSliceSelFpf2, 0, 6023 _bcmFieldSliceSelDisable, 0, 1, 6024 88, 32, 0, 0, 0, 0, 0); 6025 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6026 _bcmFieldDevSelIntrasliceVfpKey, 0, 6027 _bcmFieldSliceSelFpf2, 0, 6028 _bcmFieldSliceSelDisable, 0, 1, 6029 120, 32, 0, 0, 0, 0, 0); 6030 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 6031 _bcmFieldDevSelIntrasliceVfpKey, 0, 6032 _bcmFieldSliceSelFpf2, 0, 6033 _bcmFieldSliceSelDisable, 0, 1, 6034 152, 16, 0, 0, 0, 0, 0); 6035 6036 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6037 _bcmFieldDevSelIntrasliceVfpKey, 1, 6038 _bcmFieldSliceSelFpf2, 1, 6039 _bcmFieldSliceSelDisable, 0, 1, 6040 0, 8, 0, 0, 0, 0, 0); 6041 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 6042 _bcmFieldDevSelIntrasliceVfpKey, 1, 6043 _bcmFieldSliceSelFpf2, 1, 6044 _bcmFieldSliceSelDisable, 0, 1, 6045 8, 16, 0, 0, 0, 0, 0); 6046 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcIp6, 6047 _bcmFieldDevSelIntrasliceVfpKey, 1, 6048 _bcmFieldSliceSelFpf2, 1, 6049 _bcmFieldSliceSelDisable, 0, 1, 6050 24, 128, 0, 0, 0, 0, 0); 6051 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 6052 _bcmFieldDevSelIntrasliceVfpKey, 1, 6053 _bcmFieldSliceSelFpf2, 1, 6054 _bcmFieldSliceSelDisable, 0, 1, 6055 152, 16, 0, 0, 0, 0, 0); 6056 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6057 _bcmFieldDevSelIntrasliceVfpKey, 1, 6058 _bcmFieldSliceSelFpf2, 1, 6059 _bcmFieldSliceSelDisable, 0, 1, 6060 168, 8, 0, 0, 0, 0, 0); 6061 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6062 _bcmFieldDevSelIntrasliceVfpKey, 1, 6063 _bcmFieldSliceSelFpf2, 1, 6064 _bcmFieldSliceSelDisable, 0, 1, 6065 176, 8, 0, 0, 0, 0, 0); 6066 return (BCM_E_NONE); 6067 } 6068 6069 /* 6070 * Function: 6071 * _field_fb2_egress_qualifiers_init 6072 * Purpose: 6073 * Initialize device stage egress qaualifiers 6074 * select codes & offsets 6075 * Parameters: 6076 * unit - (IN) BCM device number. 6077 * stage_fc - (IN) Field Processor stage control structure. 6078 * 6079 * Returns: 6080 * BCM_E_NONE 6081 */ 6082 STATIC int 6083 _field_fb2_egress_qualifiers_init(int unit, _field_stage_t *stage_fc) 6084 { 6085 _FP_QUAL_DECL; 6086 _key_fld_ = KEYf; 6087 6088 /* Input parameters check. */ 6089 if (NULL == stage_fc) { 6090 return (BCM_E_PARAM); 6091 } 6092 6093 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStageEgress, 6094 _bcmFieldSliceSelDisable, 0, 0, 0); 6095 6096 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format, 6097 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 0, 2); 6098 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 6099 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 2, 16); 6100 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac, 6101 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 18, 48); 6102 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac, 6103 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 66, 48); 6104 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan, 6105 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 114, 16); 6106 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId, 6107 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 114, 12); 6108 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi, 6109 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 126, 1); 6110 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri, 6111 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 127, 3); 6112 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort, 6113 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 146, 5); 6114 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6115 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 151, 1); 6116 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMirrorCopy, 6117 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 152, 1); 6118 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6119 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 153, 16); 6120 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6121 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 153, 12); 6122 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6123 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 165, 1); 6124 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6125 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 166, 3); 6126 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat, 6127 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 169, 2); 6128 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstHiGig, 6129 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 171, 1); 6130 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInterfaceClassPort, 6131 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 172, 4); 6132 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOutPort, 6133 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 176, 5); 6134 6135 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 6136 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 0, 2); 6137 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6138 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 2, 6); 6139 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 6140 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 8, 16); 6141 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 6142 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 24, 16); 6143 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6144 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 40, 8); 6145 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6146 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 61, 8); 6147 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6148 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 69, 32); 6149 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6150 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 101, 32); 6151 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6152 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 133, 1); 6153 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTos, 6154 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 134, 8); 6155 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort, 6156 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 146, 5); 6157 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6158 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 151, 1); 6159 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMirrorCopy, 6160 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 152, 1); 6161 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6162 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 153, 16); 6163 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6164 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 153, 12); 6165 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6166 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 165, 1); 6167 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6168 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 166, 3); 6169 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat, 6170 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 169, 2); 6171 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstHiGig, 6172 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 171, 1); 6173 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInterfaceClassPort, 6174 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 172, 4); 6175 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOutPort, 6176 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 176, 5); 6177 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp4, 6178 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 0, 0); 6179 6180 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6181 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 0, 8); 6182 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6, 6183 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 8, 128); 6184 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6185 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 136, 1); 6186 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6187 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 137, 8); 6188 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort, 6189 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 146, 5); 6190 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6191 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 151, 1); 6192 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMirrorCopy, 6193 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 152, 1); 6194 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6195 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 153, 16); 6196 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6197 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 153, 12); 6198 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6199 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 165, 1); 6200 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6201 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 166, 3); 6202 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat, 6203 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 169, 2); 6204 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstHiGig, 6205 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 171, 1); 6206 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInterfaceClassPort, 6207 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 172, 4); 6208 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOutPort, 6209 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 176, 5); 6210 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp6, 6211 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 0, 0); 6212 6213 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 6214 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 0, 2); 6215 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6216 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 2, 6); 6217 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 6218 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 8, 16); 6219 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 6220 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 24, 16); 6221 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6222 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 40, 8); 6223 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6, 6224 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 48, 128); 6225 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6, 6226 _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 0, 0); 6227 6228 return (BCM_E_NONE); 6229 } 6230 #endif /*BCM_FIREBOLT2_SUPPORT */ 6231 6232 6233 /* 6234 * Function: 6235 * _field_fb_ingress_qualifiers_init 6236 * Purpose: 6237 * Initialize device stage ingress qaualifiers 6238 * select codes & offsets 6239 * Parameters: 6240 * unit - (IN) BCM device number. 6241 * stage_fc - (IN) Field Processor stage control structure. 6242 * 6243 * Returns: 6244 * BCM_E_NONE 6245 */ 6246 STATIC int 6247 _field_fb_ingress_qualifiers_init(int unit, _field_stage_t *stage_fc) 6248 { 6249 soc_mem_t tcam_mem; /* TCAM memory id. */ 6250 soc_mem_t policy_mem; /* Policy table memory id . */ 6251 int offset; /* Tcam field offset. */ 6252 int rv; /* Operation return status. */ 6253 _FP_QUAL_DECL; 6254 6255 /* Input parameters check. */ 6256 if (NULL == stage_fc) { 6257 return (BCM_E_PARAM); 6258 } 6259 6260 rv = _field_fb_tcam_policy_mem_get(unit, stage_fc->stage_id, 6261 &tcam_mem, &policy_mem); 6262 BCM_IF_ERROR_RETURN(rv); 6263 6264 _key_fld_ = F4f; 6265 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort, 6266 _bcmFieldSliceSelFpf4, 0, 0, 5); 6267 6268 if (soc_feature(unit, soc_feature_field_qual_drop)) { 6269 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6270 _bcmFieldSliceSelFpf4, 1, 0, 2); 6271 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format, 6272 _bcmFieldSliceSelFpf4, 1, 2, 2); 6273 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDrop, 6274 _bcmFieldSliceSelFpf4, 1, 4, 1); 6275 } 6276 6277 _key_fld_ = KEYf; 6278 offset = 0; 6279 6280 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStage, 6281 _bcmFieldSliceSelDisable, 0, 0, 0); 6282 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStageIngress, 6283 _bcmFieldSliceSelDisable, 0, 0, 0); 6284 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp4, 6285 _bcmFieldSliceSelDisable, 0, 0, 0); 6286 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp6, 6287 _bcmFieldSliceSelDisable, 0, 0, 0); 6288 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig, 6289 _bcmFieldSliceSelDisable, 0, 0, 0); 6290 if (SOC_IS_FIREBOLT2(unit)) { 6291 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDrop, 6292 _bcmFieldSliceSelDisable, 0, 0, 0); 6293 6294 } 6295 6296 6297 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format, 6298 _bcmFieldSliceSelFpf3, 0, 0, 2); 6299 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat, 6300 _bcmFieldSliceSelFpf3, 0, 2, 2); 6301 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6302 _bcmFieldSliceSelFpf3, 0, 4, 2); 6303 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode, 6304 _bcmFieldSliceSelFpf3, 0, 6, 3); 6305 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyPacketRes, 6306 _bcmFieldSliceSelFpf3, 0, 9, 4); 6307 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpInfo, 6308 _bcmFieldSliceSelFpf3, 0, 13, 3); 6309 6310 #if defined(BCM_BRADLEY_SUPPORT) 6311 if (SOC_IS_HB_GW(unit)) { 6312 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcPort, 6313 _bcmFieldSliceSelFpf3, 1, 0, 14); 6314 if (soc_feature(unit, soc_feature_field_wide)) { 6315 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode, 6316 _bcmFieldSliceSelFpf3, 1, 14, 3); 6317 } 6318 } else 6319 #endif /* BCM_BRADLEY_SUPPORT */ 6320 { 6321 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcPort, 6322 _bcmFieldSliceSelFpf3, 1, 0, 12); 6323 if (soc_feature(unit, soc_feature_field_wide)) { 6324 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode, 6325 _bcmFieldSliceSelFpf3, 1, 12, 3); 6326 } 6327 } 6328 6329 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcTrunk, 6330 _bcmFieldSliceSelFpf3, 1, 0, 8); 6331 6332 6333 #if defined(BCM_BRADLEY_SUPPORT) 6334 if (SOC_IS_HB_GW(unit)) { 6335 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstPort, 6336 _bcmFieldSliceSelFpf3, 2, 0, 14); 6337 if (soc_feature(unit, soc_feature_field_wide)) { 6338 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode, 6339 _bcmFieldSliceSelFpf3, 2, 14, 3); 6340 } 6341 } else 6342 #endif /* BCM_BRADLEY_SUPPORT */ 6343 { 6344 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstPort, 6345 _bcmFieldSliceSelFpf3, 2, 0, 12); 6346 if (soc_feature(unit, soc_feature_field_wide)) { 6347 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode, 6348 _bcmFieldSliceSelFpf3, 2, 12, 3); 6349 } 6350 } 6351 6352 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstTrunk, 6353 _bcmFieldSliceSelFpf3, 2, 0, 8); 6354 6355 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTunnelTerminated, 6356 _bcmFieldSliceSelFpf3, 3, 0, 1); 6357 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanTranslationHit, 6358 _bcmFieldSliceSelFpf3, 3, 1, 1); 6359 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyForwardingVlanValid, 6360 _bcmFieldSliceSelFpf3, 3, 2, 1); 6361 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIngressStpState, 6362 _bcmFieldSliceSelFpf3, 3, 3, 2); 6363 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcHit, 6364 _bcmFieldSliceSelFpf3, 3, 5, 1); 6365 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcStatic, 6366 _bcmFieldSliceSelFpf3, 3, 6, 1); 6367 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2DestHit, 6368 _bcmFieldSliceSelFpf3, 3, 7, 1); 6369 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6370 _bcmFieldSliceSelFpf3, 3, 8, 1); 6371 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2CacheHit, 6372 _bcmFieldSliceSelFpf3, 3, 9, 1); 6373 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3SrcHostHit, 6374 _bcmFieldSliceSelFpf3, 3, 10, 1); 6375 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestHostHit, 6376 _bcmFieldSliceSelFpf3, 3, 11, 1); 6377 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpmcStarGroupHit, 6378 _bcmFieldSliceSelFpf3, 3, 12, 1); 6379 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestRouteHit, 6380 _bcmFieldSliceSelFpf3, 3, 13, 1); 6381 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2StationMove, 6382 _bcmFieldSliceSelFpf3, 3, 14, 1); 6383 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack, 6384 _bcmFieldSliceSelFpf3, 3, 15, 1); 6385 6386 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6387 _bcmFieldSliceSelFpf3, 4, 0, 6); 6388 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6389 _bcmFieldSliceSelFpf3, 4, 6, 8); 6390 6391 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6392 _bcmFieldSliceSelFpf3, 5, 0, 16); 6393 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6394 _bcmFieldSliceSelFpf3, 5, 0, 12); 6395 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6396 _bcmFieldSliceSelFpf3, 5, 12, 1); 6397 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6398 _bcmFieldSliceSelFpf3, 5, 13, 3); 6399 6400 if (soc_feature(unit, soc_feature_field_wide)) { 6401 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6402 _bcmFieldSliceSelFpf3, 6, 0, 8); 6403 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6404 _bcmFieldSliceSelFpf3, 6, 8, 8); 6405 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck, 6406 _bcmFieldSliceSelFpf3, 7, 0, 16); 6407 } 6408 6409 /* FPF2 */ 6410 offset += _FIELD_MEM_FIELD_LENGTH(unit, tcam_mem, F3f); 6411 6412 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6413 _bcmFieldSliceSelFpf2, 0, offset, 8); 6414 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6415 _bcmFieldSliceSelFpf2, 0, (offset + 8), 6); 6416 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFlags, 6417 _bcmFieldSliceSelFpf2, 0, (offset + 14), 2); 6418 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6419 _bcmFieldSliceSelFpf2, 0, (offset + 16), 8); 6420 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 6421 _bcmFieldSliceSelFpf2, 0, (offset + 24), 16); 6422 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 6423 _bcmFieldSliceSelFpf2, 0, (offset + 40), 16); 6424 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6425 _bcmFieldSliceSelFpf2, 0, (offset + 56), 8); 6426 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6427 _bcmFieldSliceSelFpf2, 0, (offset + 64), 32); 6428 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6429 _bcmFieldSliceSelFpf2, 0, (offset + 96), 32); 6430 6431 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6432 _bcmFieldSliceSelFpf2, 1, offset, 8); 6433 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6434 _bcmFieldSliceSelFpf2, 1, (offset + 8), 6); 6435 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFlags, 6436 _bcmFieldSliceSelFpf2, 1, (offset + 14), 2); 6437 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6438 _bcmFieldSliceSelFpf2, 1, (offset + 16), 8); 6439 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 6440 _bcmFieldSliceSelFpf2, 1, (offset + 24), 16); 6441 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck, 6442 _bcmFieldSliceSelFpf2, 1, (offset + 40), 16); 6443 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6444 _bcmFieldSliceSelFpf2, 1, (offset + 56), 8); 6445 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6446 _bcmFieldSliceSelFpf2, 1, (offset + 64), 32); 6447 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6448 _bcmFieldSliceSelFpf2, 1, (offset + 96), 32); 6449 6450 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6451 _bcmFieldSliceSelFpf2, 2, offset, 8); 6452 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6453 _bcmFieldSliceSelFpf2, 2, (offset + 8), 6); 6454 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFlags, 6455 _bcmFieldSliceSelFpf2, 2, (offset + 14), 2); 6456 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6457 _bcmFieldSliceSelFpf2, 2, (offset + 16), 8); 6458 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 6459 _bcmFieldSliceSelFpf2, 2, (offset + 24), 16); 6460 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck, 6461 _bcmFieldSliceSelFpf2, 2, (offset + 40), 16); 6462 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6463 _bcmFieldSliceSelFpf2, 2, (offset + 56), 8); 6464 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6465 _bcmFieldSliceSelFpf2, 2, (offset + 64), 32); 6466 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6467 _bcmFieldSliceSelFpf2, 2, (offset + 96), 32); 6468 6469 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6, 6470 _bcmFieldSliceSelFpf2, 3, offset, 128); 6471 6472 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6, 6473 _bcmFieldSliceSelFpf2, 4, offset, 128); 6474 6475 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6476 _bcmFieldSliceSelFpf2, 5, offset, 6); 6477 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6478 _bcmFieldSliceSelFpf2, 5, (offset + 6), 8); 6479 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp6FlowLabel, 6480 _bcmFieldSliceSelFpf2, 5, (offset + 14), 20); 6481 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6482 _bcmFieldSliceSelFpf2, 5, (offset + 34), 8); 6483 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6484 _bcmFieldSliceSelFpf2, 5, (offset + 42), 8); 6485 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6High, 6486 _bcmFieldSliceSelFpf2, 5, (offset + 50), 64); 6487 6488 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6489 _bcmFieldSliceSelFpf2, 6, offset, 16); 6490 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6491 _bcmFieldSliceSelFpf2, 6, offset, 12); 6492 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6493 _bcmFieldSliceSelFpf2, 6, (offset + 12), 1); 6494 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6495 _bcmFieldSliceSelFpf2, 6, (offset + 13), 3); 6496 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 6497 _bcmFieldSliceSelFpf2, 6, (offset + 16), 16); 6498 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac, 6499 _bcmFieldSliceSelFpf2, 6, (offset + 32), 48); 6500 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac, 6501 _bcmFieldSliceSelFpf2, 6, (offset + 80), 48); 6502 6503 6504 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6505 _bcmFieldSliceSelFpf2, 7, offset, 16); 6506 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6507 _bcmFieldSliceSelFpf2, 7, offset, 12); 6508 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6509 _bcmFieldSliceSelFpf2, 7, (offset + 12), 1); 6510 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6511 _bcmFieldSliceSelFpf2, 7, (offset + 13), 3); 6512 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 6513 _bcmFieldSliceSelFpf2, 7, (offset + 16), 16); 6514 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6515 _bcmFieldSliceSelFpf2, 7, (offset + 32), 32); 6516 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac, 6517 _bcmFieldSliceSelFpf2, 7, (offset + 64), 48); 6518 6519 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6520 _bcmFieldSliceSelFpf2, 8, offset, 16); 6521 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6522 _bcmFieldSliceSelFpf2, 8, offset, 12); 6523 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6524 _bcmFieldSliceSelFpf2, 8, (offset + 12), 1); 6525 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6526 _bcmFieldSliceSelFpf2, 8, (offset + 13), 3); 6527 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 6528 _bcmFieldSliceSelFpf2, 8, (offset + 16), 16); 6529 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6530 _bcmFieldSliceSelFpf2, 8, (offset + 32), 32); 6531 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac, 6532 _bcmFieldSliceSelFpf2, 8, (offset + 64), 48); 6533 6534 _FP_QUAL_ADD(unit, stage_fc, _bcmFieldQualifyData0, 6535 _bcmFieldSliceSelFpf2, 9, offset, 128); 6536 6537 _FP_QUAL_ADD(unit, stage_fc, _bcmFieldQualifyData1, 6538 _bcmFieldSliceSelFpf2, 0xA, offset, 128); 6539 6540 if (soc_feature(unit, soc_feature_field_qual_Ip6High)) { 6541 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6High, 6542 _bcmFieldSliceSelFpf2, 0xb, offset + 64, 64); 6543 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6High, 6544 _bcmFieldSliceSelFpf2, 0xb, offset, 64); 6545 } 6546 6547 6548 #ifdef BCM_FIREBOLT2_SUPPORT 6549 if (SOC_IS_FIREBOLT2(unit)) { 6550 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6551 _bcmFieldSliceSelFpf2, 0xc, offset, 8); 6552 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6553 _bcmFieldSliceSelFpf2, 0xc, (offset + 8), 6); 6554 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 6555 _bcmFieldSliceSelFpf2, 0xc, (offset + 14), 2); 6556 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6557 _bcmFieldSliceSelFpf2, 0xc, (offset + 16), 8); 6558 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 6559 _bcmFieldSliceSelFpf2, 0xc, (offset + 24), 16); 6560 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 6561 _bcmFieldSliceSelFpf2, 0xc, (offset + 40), 16); 6562 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6563 _bcmFieldSliceSelFpf2, 0xc, (offset + 56), 8); 6564 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6565 _bcmFieldSliceSelFpf2, 0xc, (offset + 64), 32); 6566 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6567 _bcmFieldSliceSelFpf2, 0xc, (offset + 96), 32); 6568 6569 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6570 _bcmFieldSliceSelFpf2, 0xd, offset, 8); 6571 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6572 _bcmFieldSliceSelFpf2, 0xd, (offset + 8), 6); 6573 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 6574 _bcmFieldSliceSelFpf2, 0xd, (offset + 14), 2); 6575 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6576 _bcmFieldSliceSelFpf2, 0xd, (offset + 16), 8); 6577 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 6578 _bcmFieldSliceSelFpf2, 0xd, (offset + 24), 16); 6579 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck, 6580 _bcmFieldSliceSelFpf2, 0xd, (offset + 40), 16); 6581 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6582 _bcmFieldSliceSelFpf2, 0xd, (offset + 56), 8); 6583 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6584 _bcmFieldSliceSelFpf2, 0xd, (offset + 64), 32); 6585 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6586 _bcmFieldSliceSelFpf2, 0xd, (offset + 96), 32); 6587 6588 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6589 _bcmFieldSliceSelFpf2, 0xe, offset, 8); 6590 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6591 _bcmFieldSliceSelFpf2, 0xe, (offset + 8), 6); 6592 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 6593 _bcmFieldSliceSelFpf2, 0xe, (offset + 14), 2); 6594 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6595 _bcmFieldSliceSelFpf2, 0xe, (offset + 16), 8); 6596 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 6597 _bcmFieldSliceSelFpf2, 0xe, (offset + 24), 16); 6598 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck, 6599 _bcmFieldSliceSelFpf2, 0xe, (offset + 40), 16); 6600 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6601 _bcmFieldSliceSelFpf2, 0xe, (offset + 56), 8); 6602 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 6603 _bcmFieldSliceSelFpf2, 0xe, (offset + 64), 32); 6604 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 6605 _bcmFieldSliceSelFpf2, 0xe, (offset + 96), 32); 6606 6607 } 6608 6609 #endif /* BCM_FIREBOLT2_SUPPORT */ 6610 6611 /* FPF1 */ 6612 offset += _FIELD_MEM_FIELD_LENGTH(unit, tcam_mem, F2f); 6613 6614 #if defined (BCM_BRADLEY_SUPPORT) 6615 if (SOC_IS_HB_GW(unit)) { 6616 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPorts, 6617 _bcmFieldSliceSelFpf1, 0, offset, 21); 6618 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6619 _bcmFieldSliceSelFpf1, 0, (offset + 21), 2); 6620 } else 6621 #endif /* BCM_BRADLEY_SUPPORT */ 6622 { 6623 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPorts, 6624 _bcmFieldSliceSelFpf1, 0, offset, 29); 6625 if (soc_feature(unit, soc_feature_field_wide)) { 6626 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6627 _bcmFieldSliceSelFpf1, 0, (offset + 29), 2); 6628 6629 } 6630 #ifdef BCM_FIREBOLT2_SUPPORT 6631 if (SOC_IS_FIREBOLT2(unit)) { 6632 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6633 _bcmFieldSliceSelFpf1, 0, (offset + 31), 1); 6634 } 6635 #endif /* BCM_FIREBOLT2_SUPPORT */ 6636 } 6637 6638 #if defined (BCM_BRADLEY_SUPPORT) 6639 if (SOC_IS_HB_GW(unit)) { 6640 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstTrunk, 6641 _bcmFieldSliceSelFpf1, 1, offset, 8); 6642 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstPort, 6643 _bcmFieldSliceSelFpf1, 1, offset, 14); 6644 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcTrunk, 6645 _bcmFieldSliceSelFpf1, 1, (offset + 14), 8); 6646 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcPort, 6647 _bcmFieldSliceSelFpf1, 1, (offset + 14), 14); 6648 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode, 6649 _bcmFieldSliceSelFpf1, 1, (offset + 28), 3); 6650 } else 6651 #endif /* BCM_BRADLEY_SUPPORT */ 6652 6653 { 6654 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstTrunk, 6655 _bcmFieldSliceSelFpf1, 1, offset, 8); 6656 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstPort, 6657 _bcmFieldSliceSelFpf1, 1, offset, 12); 6658 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcTrunk, 6659 _bcmFieldSliceSelFpf1, 1, (offset + 12), 8); 6660 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcPort, 6661 _bcmFieldSliceSelFpf1, 1, (offset + 12), 12); 6662 if (soc_feature(unit, soc_feature_field_wide)) { 6663 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode, 6664 _bcmFieldSliceSelFpf1, 1, (offset + 24), 3); 6665 } 6666 } 6667 6668 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 6669 _bcmFieldSliceSelFpf1, 2, offset, 16); 6670 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 6671 _bcmFieldSliceSelFpf1, 2, (offset + 16), 16); 6672 6673 #if defined(BCM_FIREBOLT2_SUPPORT) 6674 if (SOC_IS_FIREBOLT2(unit)) { 6675 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan, 6676 _bcmFieldDevSelInnerVlanOverlay, 0, 6677 _bcmFieldSliceSelFpf1, 3, 6678 _bcmFieldSliceSelDisable, 0, 0, 6679 offset, 16, 0, 0, 0, 0, 0); 6680 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId, 6681 _bcmFieldDevSelInnerVlanOverlay, 0, 6682 _bcmFieldSliceSelFpf1, 3, 6683 _bcmFieldSliceSelDisable, 0, 0, 6684 offset, 12, 0, 0, 0, 0, 0); 6685 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi, 6686 _bcmFieldDevSelInnerVlanOverlay, 0, 6687 _bcmFieldSliceSelFpf1, 3, 6688 _bcmFieldSliceSelDisable, 0, 0, 6689 (offset + 12), 1, 0, 0, 0, 0, 0); 6690 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri, 6691 _bcmFieldDevSelInnerVlanOverlay, 0, 6692 _bcmFieldSliceSelFpf1, 3, 6693 _bcmFieldSliceSelDisable, 0, 0, 6694 (offset + 13), 3, 0, 0, 0, 0, 0); 6695 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyVrf, 6696 _bcmFieldDevSelInnerVlanOverlay, 1, 6697 _bcmFieldSliceSelFpf1, 3, 6698 _bcmFieldSliceSelDisable, 0, 0, 6699 offset, 6, 0, 0, 0, 0, 0); 6700 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDstClassField, 6701 _bcmFieldDevSelInnerVlanOverlay, 1, 6702 _bcmFieldSliceSelFpf1, 3, 6703 _bcmFieldSliceSelDisable, 0, 0, 6704 (offset + 6), 5, 0, 0, 0, 0, 0); 6705 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcClassL2, 6706 _bcmFieldDevSelInnerVlanOverlay, 1, 6707 _bcmFieldSliceSelFpf1, 3, 6708 _bcmFieldSliceSelDisable, 0, 0, 6709 (offset + 11), 5, 0, 0, 0, 0, 0); 6710 } else 6711 #endif /* BCM_FIREBOLT2_SUPPORT */ 6712 if (soc_feature(unit, soc_feature_src_mac_group)) { 6713 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan, 6714 _bcmFieldDevSelInnerVlanOverlay, 0, 6715 _bcmFieldSliceSelFpf1, 3, 6716 _bcmFieldSliceSelDisable, 0, 0, 6717 offset, 16, 0, 0, 0, 0, 0); 6718 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId, 6719 _bcmFieldDevSelInnerVlanOverlay, 0, 6720 _bcmFieldSliceSelFpf1, 3, 6721 _bcmFieldSliceSelDisable, 0, 0, 6722 offset, 12, 0, 0, 0, 0, 0); 6723 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi, 6724 _bcmFieldDevSelInnerVlanOverlay, 0, 6725 _bcmFieldSliceSelFpf1, 3, 6726 _bcmFieldSliceSelDisable, 0, 0, 6727 (offset + 12), 1, 0, 0, 0, 0, 0); 6728 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri, 6729 _bcmFieldDevSelInnerVlanOverlay, 0, 6730 _bcmFieldSliceSelFpf1, 3, 6731 _bcmFieldSliceSelDisable, 0, 0, 6732 (offset + 13), 3, 0, 0, 0, 0, 0); 6733 6734 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcClassL2, 6735 _bcmFieldDevSelInnerVlanOverlay, 1, 6736 _bcmFieldSliceSelFpf1, 3, 6737 _bcmFieldSliceSelDisable, 0, 0, 6738 (offset + 12), 4, 0, 0, 0, 0, 0); 6739 } else { 6740 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan, 6741 _bcmFieldSliceSelFpf1, 3, offset, 16); 6742 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId, 6743 _bcmFieldSliceSelFpf1, 3, offset, 12); 6744 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi, 6745 _bcmFieldSliceSelFpf1, 3, (offset + 12), 1); 6746 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri, 6747 _bcmFieldSliceSelFpf1, 3, (offset + 13), 3); 6748 6749 } 6750 6751 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6752 _bcmFieldSliceSelFpf1, 3, (offset + 16), 16); 6753 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6754 _bcmFieldSliceSelFpf1, 3, (offset + 16), 12); 6755 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6756 _bcmFieldSliceSelFpf1, 3, (offset + 28), 1); 6757 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6758 _bcmFieldSliceSelFpf1, 3, (offset + 29), 3); 6759 6760 6761 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6762 _bcmFieldSliceSelFpf1, 4, offset, 16); 6763 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6764 _bcmFieldSliceSelFpf1, 4, offset, 12); 6765 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6766 _bcmFieldSliceSelFpf1, 4, (offset + 12), 1); 6767 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6768 _bcmFieldSliceSelFpf1, 4, (offset + 13), 3); 6769 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 6770 _bcmFieldSliceSelFpf1, 4, (offset + 16), 16); 6771 6772 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6773 _bcmFieldSliceSelFpf1, 5, offset, 8); 6774 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType, 6775 _bcmFieldSliceSelFpf1, 5, (offset + 8), 16); 6776 6777 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTunnelTerminated, 6778 _bcmFieldSliceSelFpf1, 6, offset, 1); 6779 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanTranslationHit, 6780 _bcmFieldSliceSelFpf1, 6, (offset + 1), 1); 6781 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyForwardingVlanValid, 6782 _bcmFieldSliceSelFpf1, 6, (offset + 2), 1); 6783 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIngressStpState, 6784 _bcmFieldSliceSelFpf1, 6, (offset + 3), 2); 6785 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcHit, 6786 _bcmFieldSliceSelFpf1, 6, (offset + 5), 1); 6787 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcStatic, 6788 _bcmFieldSliceSelFpf1, 6, (offset + 6), 1); 6789 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2DestHit, 6790 _bcmFieldSliceSelFpf1, 6, (offset + 7), 1); 6791 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6792 _bcmFieldSliceSelFpf1, 6, (offset + 8), 1); 6793 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2CacheHit, 6794 _bcmFieldSliceSelFpf1, 6, (offset + 9), 1); 6795 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3SrcHostHit, 6796 _bcmFieldSliceSelFpf1, 6, (offset + 10), 1); 6797 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestHostHit, 6798 _bcmFieldSliceSelFpf1, 6, (offset + 11), 1); 6799 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpmcStarGroupHit, 6800 _bcmFieldSliceSelFpf1, 6, (offset + 12), 1); 6801 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestRouteHit, 6802 _bcmFieldSliceSelFpf1, 6, (offset + 13), 1); 6803 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2StationMove, 6804 _bcmFieldSliceSelFpf1, 6, (offset + 14), 1); 6805 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack, 6806 _bcmFieldSliceSelFpf1, 6, (offset + 15), 1); 6807 #if defined(BCM_FIREBOLT2_SUPPORT) 6808 if (SOC_IS_FIREBOLT2(unit)) { 6809 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan, 6810 _bcmFieldDevSelInnerVlanOverlay, 0, 6811 _bcmFieldSliceSelFpf1, 6, 6812 _bcmFieldSliceSelDisable, 0, 0, 6813 (offset + 16), 16, 0, 0, 0, 0, 0); 6814 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId, 6815 _bcmFieldDevSelInnerVlanOverlay, 0, 6816 _bcmFieldSliceSelFpf1, 6, 6817 _bcmFieldSliceSelDisable, 0, 0, 6818 (offset + 16), 12, 0, 0, 0, 0, 0); 6819 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi, 6820 _bcmFieldDevSelInnerVlanOverlay, 0, 6821 _bcmFieldSliceSelFpf1, 6, 6822 _bcmFieldSliceSelDisable, 0, 0, 6823 (offset + 28), 1, 0, 0, 0, 0, 0); 6824 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri, 6825 _bcmFieldDevSelInnerVlanOverlay, 0, 6826 _bcmFieldSliceSelFpf1, 6, 6827 _bcmFieldSliceSelDisable, 0, 0, 6828 (offset + 29), 3, 0, 0, 0, 0, 0); 6829 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyVrf, 6830 _bcmFieldDevSelInnerVlanOverlay, 1, 6831 _bcmFieldSliceSelFpf1, 6, 6832 _bcmFieldSliceSelDisable, 0, 0, 6833 (offset + 16), 6, 0, 0, 0, 0, 0); 6834 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDstClassField, 6835 _bcmFieldDevSelInnerVlanOverlay, 1, 6836 _bcmFieldSliceSelFpf1, 6, 6837 _bcmFieldSliceSelDisable, 0, 0, 6838 (offset + 22), 5, 0, 0, 0, 0, 0); 6839 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcClassL2, 6840 _bcmFieldDevSelInnerVlanOverlay, 1, 6841 _bcmFieldSliceSelFpf1, 6, 6842 _bcmFieldSliceSelDisable, 0, 0, 6843 (offset + 27), 5, 0, 0, 0, 0, 0); 6844 } else 6845 #endif /* BCM_FIREBOLT2_SUPPORT */ 6846 if (soc_feature(unit, soc_feature_src_mac_group)) { 6847 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan, 6848 _bcmFieldDevSelInnerVlanOverlay, 0, 6849 _bcmFieldSliceSelFpf1, 6, 6850 _bcmFieldSliceSelDisable, 0, 0, 6851 (offset + 16), 16, 0, 0, 0, 0, 0); 6852 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId, 6853 _bcmFieldDevSelInnerVlanOverlay, 0, 6854 _bcmFieldSliceSelFpf1, 6, 6855 _bcmFieldSliceSelDisable, 0, 0, 6856 (offset + 16), 12, 0, 0, 0, 0, 0); 6857 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi, 6858 _bcmFieldDevSelInnerVlanOverlay, 0, 6859 _bcmFieldSliceSelFpf1, 6, 6860 _bcmFieldSliceSelDisable, 0, 0, 6861 (offset + 28), 1, 0, 0, 0, 0, 0); 6862 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri, 6863 _bcmFieldDevSelInnerVlanOverlay, 0, 6864 _bcmFieldSliceSelFpf1, 6, 6865 _bcmFieldSliceSelDisable, 0, 0, 6866 (offset + 29), 3, 0, 0, 0, 0, 0); 6867 _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcClassL2, 6868 _bcmFieldDevSelInnerVlanOverlay, 1, 6869 _bcmFieldSliceSelFpf1, 6, 6870 _bcmFieldSliceSelDisable, 0, 0, 6871 (offset + 28), 4, 0, 0, 0, 0, 0); 6872 } else { 6873 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan, 6874 _bcmFieldSliceSelFpf1, 6, (offset + 16), 16); 6875 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId, 6876 _bcmFieldSliceSelFpf1, 6, (offset + 16), 12); 6877 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi, 6878 _bcmFieldSliceSelFpf1, 6, (offset + 28), 1); 6879 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri, 6880 _bcmFieldSliceSelFpf1, 6, (offset + 29), 3); 6881 } 6882 6883 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6884 _bcmFieldSliceSelFpf1, 7, offset, 16); 6885 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6886 _bcmFieldSliceSelFpf1, 7, offset, 12); 6887 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6888 _bcmFieldSliceSelFpf1, 7, (offset + 12), 1); 6889 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6890 _bcmFieldSliceSelFpf1, 7, (offset + 13), 3); 6891 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format, 6892 _bcmFieldSliceSelFpf1, 7, (offset + 16), 2); 6893 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat, 6894 _bcmFieldSliceSelFpf1, 7, (offset + 18), 2); 6895 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6896 _bcmFieldSliceSelFpf1, 7, (offset + 20), 2); 6897 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode, 6898 _bcmFieldSliceSelFpf1, 7, (offset + 22), 3); 6899 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyPacketRes, 6900 _bcmFieldSliceSelFpf1, 7, (offset + 25), 4); 6901 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpInfo, 6902 _bcmFieldSliceSelFpf1, 7, (offset + 29), 3); 6903 6904 6905 #ifdef BCM_FIREBOLT2_SUPPORT 6906 if (SOC_IS_FIREBOLT2(unit)) { 6907 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 6908 _bcmFieldSliceSelFpf1, 0xc, offset, 16); 6909 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 6910 _bcmFieldSliceSelFpf1, 0xc, offset, 12); 6911 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 6912 _bcmFieldSliceSelFpf1, 0xc, (offset + 12), 1); 6913 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 6914 _bcmFieldSliceSelFpf1, 0xc, (offset + 13), 3); 6915 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVrf, 6916 _bcmFieldSliceSelFpf1, 0xc, (offset + 16), 6); 6917 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstClassField, 6918 _bcmFieldSliceSelFpf1, 0xc, (offset + 22), 5); 6919 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6920 _bcmFieldSliceSelFpf1, 0xc, (offset + 29), 2); 6921 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6922 _bcmFieldSliceSelFpf1, 0xc, (offset + 31), 1); 6923 6924 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6925 _bcmFieldSliceSelFpf1, 0xd, offset , 8); 6926 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVrf, 6927 _bcmFieldSliceSelFpf1, 0xd, (offset + 8) , 6); 6928 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstClassField, 6929 _bcmFieldSliceSelFpf1, 0xd, (offset + 14) , 5); 6930 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType, 6931 _bcmFieldSliceSelFpf1, 0xd, (offset + 21) , 2); 6932 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6933 _bcmFieldSliceSelFpf1, 0xd, (offset + 23) , 1); 6934 _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6935 _bcmFieldSliceSelFpf1, 0xd, (offset + 24) , 8); 6936 6937 /* Intraslice. */ 6938 _key_fld_ = DATAf; 6939 6940 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 6941 _bcmFieldSliceSelFpf2, 0, 6942 _bcmFieldSliceSelDisable, 0, 8, 8); 6943 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 6944 _bcmFieldSliceSelFpf2, 0, 6945 _bcmFieldSliceSelDisable, 0, 16, 8); 6946 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyTtl, 6947 _bcmFieldSliceSelFpf2, 0, 6948 _bcmFieldSliceSelDisable, 0, 24, 8); 6949 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 6950 _bcmFieldSliceSelFpf2, 0, 6951 _bcmFieldSliceSelDisable, 0, 32, 6); 6952 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 6953 _bcmFieldSliceSelFpf2, 0, 6954 _bcmFieldSliceSelDisable, 0, 38, 2); 6955 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 6956 bcmFieldQualifyTunnelTerminated, 6957 _bcmFieldSliceSelFpf2, 0, 6958 _bcmFieldSliceSelDisable, 0, 40, 1); 6959 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 6960 bcmFieldQualifyVlanTranslationHit, 6961 _bcmFieldSliceSelFpf2, 0, 6962 _bcmFieldSliceSelDisable, 0, 41, 1); 6963 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 6964 bcmFieldQualifyForwardingVlanValid, 6965 _bcmFieldSliceSelFpf2, 0, 6966 _bcmFieldSliceSelDisable, 0, 42, 1); 6967 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 6968 bcmFieldQualifyIngressStpState, 6969 _bcmFieldSliceSelFpf2, 0, 6970 _bcmFieldSliceSelDisable, 0, 43, 2); 6971 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL2SrcHit, 6972 _bcmFieldSliceSelFpf2, 0, 6973 _bcmFieldSliceSelDisable, 0, 45, 1); 6974 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL2SrcStatic, 6975 _bcmFieldSliceSelFpf2, 0, 6976 _bcmFieldSliceSelDisable, 0, 46, 1); 6977 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL2DestHit, 6978 _bcmFieldSliceSelFpf2, 0, 6979 _bcmFieldSliceSelDisable, 0, 47, 1); 6980 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL3Routable, 6981 _bcmFieldSliceSelFpf2, 0, 6982 _bcmFieldSliceSelDisable, 0, 48, 1); 6983 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL2CacheHit, 6984 _bcmFieldSliceSelFpf2, 0, 6985 _bcmFieldSliceSelDisable, 0, 49, 1); 6986 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 6987 bcmFieldQualifyL3SrcHostHit, 6988 _bcmFieldSliceSelFpf2, 0, 6989 _bcmFieldSliceSelDisable, 0, 50, 1); 6990 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 6991 bcmFieldQualifyL3DestHostHit, 6992 _bcmFieldSliceSelFpf2, 0, 6993 _bcmFieldSliceSelDisable, 0, 51, 1); 6994 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 6995 bcmFieldQualifyIpmcStarGroupHit, 6996 _bcmFieldSliceSelFpf2, 0, 6997 _bcmFieldSliceSelDisable, 0, 52, 1); 6998 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 6999 bcmFieldQualifyL3DestRouteHit, 7000 _bcmFieldSliceSelFpf2, 0, 7001 _bcmFieldSliceSelDisable, 0, 53, 1); 7002 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, 7003 bcmFieldQualifyL2StationMove, 7004 _bcmFieldSliceSelFpf2, 0, 7005 _bcmFieldSliceSelDisable, 0, 54, 1); 7006 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyDosAttack, 7007 _bcmFieldSliceSelFpf2, 0, 7008 _bcmFieldSliceSelDisable, 0, 55, 1); 7009 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan, 7010 _bcmFieldSliceSelFpf2, 0, 7011 _bcmFieldSliceSelDisable, 0, 56, 16); 7012 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId, 7013 _bcmFieldSliceSelFpf2, 0, 7014 _bcmFieldSliceSelDisable, 0, 56, 12); 7015 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi, 7016 _bcmFieldSliceSelFpf2, 0, 7017 _bcmFieldSliceSelDisable, 0, 68, 1); 7018 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri, 7019 _bcmFieldSliceSelFpf2, 0, 7020 _bcmFieldSliceSelDisable, 0, 69, 3); 7021 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck, 7022 _bcmFieldSliceSelFpf2, 0, 7023 _bcmFieldSliceSelDisable, 0, 72, 16); 7024 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyDstIp, 7025 _bcmFieldSliceSelFpf2, 0, 7026 _bcmFieldSliceSelDisable, 0, 88, 32); 7027 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifySrcIp, 7028 _bcmFieldSliceSelFpf2, 0, 7029 _bcmFieldSliceSelDisable, 0, 120, 32); 7030 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 7031 _bcmFieldSliceSelFpf2, 0, 7032 _bcmFieldSliceSelDisable, 0, 152, 16); 7033 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 7034 _bcmFieldSliceSelFpf2, 0, 7035 _bcmFieldSliceSelDisable, 0, 168, 16); 7036 7037 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyTcpControl, 7038 _bcmFieldSliceSelFpf2, 1, 7039 _bcmFieldSliceSelDisable, 0, 0, 6); 7040 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyDSCP, 7041 _bcmFieldSliceSelFpf2, 1, 7042 _bcmFieldSliceSelDisable, 0, 8, 8); 7043 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol, 7044 _bcmFieldSliceSelFpf2, 1, 7045 _bcmFieldSliceSelDisable, 0, 16, 8); 7046 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifySrcIp6, 7047 _bcmFieldSliceSelFpf2, 1, 7048 _bcmFieldSliceSelDisable, 0, 24, 128); 7049 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort, 7050 _bcmFieldSliceSelFpf2, 1, 7051 _bcmFieldSliceSelDisable, 0, 152, 16); 7052 _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort, 7053 _bcmFieldSliceSelFpf2, 1, 7054 _bcmFieldSliceSelDisable, 0, 168, 16); 7055 } 7056 #endif /* BCM_FIREBOLT2_SUPPORT */ 7057 return (BCM_E_NONE); 7058 } 7059 7060 /* 7061 * Function: 7062 * _field_fb_qualifiers_init 7063 * Purpose: 7064 * Initialize device qaualifiers select codes & offsets 7065 * Parameters: 7066 * unit - (IN) BCM device number. 7067 * stage_fc - (IN) Field Processor stage control structure. 7068 * 7069 * Returns: 7070 * BCM_E_NONE 7071 * Notes: 7072 */ 7073 STATIC int 7074 _field_fb_qualifiers_init(int unit, _field_stage_t *stage_fc) 7075 { 7076 int rv; /* Operation return status. */ 7077 7078 /* Input parameters check. */ 7079 if (NULL == stage_fc) { 7080 return (BCM_E_PARAM); 7081 } 7082 7083 /* Allocated stage qualifiers configuration array. */ 7084 _FP_XGS3_ALLOC(stage_fc->f_qual_arr, 7085 (_bcmFieldQualifyCount * sizeof(_bcm_field_qual_info_t *)), 7086 "Field qualifiers"); 7087 if (NULL == stage_fc->f_qual_arr) { 7088 return (BCM_E_MEMORY); 7089 } 7090 7091 switch (stage_fc->stage_id) { 7092 case _BCM_FIELD_STAGE_INGRESS: 7093 rv = _field_fb_ingress_qualifiers_init(unit, stage_fc); 7094 break; 7095 #if defined (BCM_FIREBOLT2_SUPPORT) 7096 case _BCM_FIELD_STAGE_LOOKUP: 7097 if (SOC_IS_FIREBOLT2(unit)) { 7098 rv = _field_fb2_lookup_qualifiers_init(unit, stage_fc); 7099 } else { 7100 rv = (BCM_E_NONE); 7101 } 7102 break; 7103 case _BCM_FIELD_STAGE_EGRESS: 7104 if (SOC_IS_FIREBOLT2(unit)) { 7105 rv = _field_fb2_egress_qualifiers_init(unit, stage_fc); 7106 } else { 7107 rv = (BCM_E_NONE); 7108 } 7109 break; 7110 #endif /* BCM_FIREBOLT2_SUPPORT */ 7111 default: 7112 sal_free(stage_fc->f_qual_arr); 7113 return (BCM_E_PARAM); 7114 } 7115 return (rv); 7116 } 7117 7118 /* 7119 * Function: 7120 * _field_fb_init 7121 * Purpose: 7122 * Perform initializations that are specific to BCM56504. This 7123 * includes initializing the FP field select bit offset tables for FPF[1-3] 7124 * for every stage. 7125 * Parameters: 7126 * unit - (IN) BCM device number. 7127 * fc - (IN) Field Processor control structure. 7128 * 7129 * Returns: 7130 * BCM_E_NONE 7131 * Notes: 7132 */ 7133 int 7134 _bcm_field_fb_init(int unit, _field_control_t *fc) 7135 { 7136 _field_stage_t *stage_p; /* Stages iteration pointer */ 7137 7138 /* Input parameters check. */ 7139 if (NULL == fc) { 7140 return (BCM_E_PARAM); 7141 } 7142 7143 stage_p = fc->stages; 7144 while (stage_p) { 7145 /* Clear hardware table */ 7146 BCM_IF_ERROR_RETURN(_field_fb_hw_clear(unit, stage_p)); 7147 7148 /* Initialize qualifiers info. */ 7149 BCM_IF_ERROR_RETURN(_field_fb_qualifiers_init(unit, stage_p)); 7150 7151 /* Goto next stage */ 7152 stage_p = stage_p->next; 7153 } 7154 7155 if (!SOC_WARM_BOOT(unit)) { 7156 /* Enable filter processor */ 7157 BCM_IF_ERROR_RETURN(_field_port_filter_enable_set(unit, fc, TRUE)); 7158 7159 /* Enable meter refresh */ 7160 BCM_IF_ERROR_RETURN(_field_meter_refresh_enable_set(unit, fc, TRUE)); 7161 if (SOC_IS_FIREBOLT(unit) && 7162 !soc_feature(unit, soc_feature_field_wide)) { 7163 BCM_IF_ERROR_RETURN 7164 (soc_reg_field32_modify(unit, FP_CAM_CONTROL_UPPERr, 7165 REG_PORT_ANY, 7166 SECRET_CHAIN_MODEf,1)); 7167 } 7168 } 7169 7170 /* Initialize the function pointers */ 7171 _field_fb_functions_init(unit, &fc->functions);; 7172 7173 return (BCM_E_NONE); 7174 } 7175 7176 /* 7177 * Function: 7178 * _field_fb_hw_clear 7179 * Purpose: 7180 * Clear hardware memory of requested stage. 7181 * Parameters: 7182 * unit - (IN) BCM device number. 7183 * stage_fc - (IN) Field Processor stage control structure. 7184 * 7185 * Returns: 7186 * BCM_E_NONE 7187 * Notes: 7188 */ 7189 STATIC int 7190 _field_fb_hw_clear(int unit, _field_stage_t *stage_fc) 7191 { 7192 if (SOC_WARM_BOOT(unit)) { 7193 return (BCM_E_NONE); 7194 } 7195 7196 if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) { 7197 BCM_IF_ERROR_RETURN 7198 (soc_mem_clear((unit), FP_UDF_OFFSETm, COPYNO_ALL, TRUE)); 7199 BCM_IF_ERROR_RETURN 7200 (soc_mem_clear((unit), FP_RANGE_CHECKm, COPYNO_ALL, TRUE)); 7201 BCM_IF_ERROR_RETURN 7202 (soc_mem_clear((unit), FP_TCAMm, COPYNO_ALL, TRUE)); 7203 BCM_IF_ERROR_RETURN 7204 (soc_mem_clear((unit), FP_POLICY_TABLEm, COPYNO_ALL, TRUE)); 7205 BCM_IF_ERROR_RETURN 7206 (soc_mem_clear((unit), FP_METER_TABLEm, COPYNO_ALL, TRUE)); 7207 if (SOC_MEM_IS_VALID(unit, FP_COUNTER_TABLEm)) { 7208 BCM_IF_ERROR_RETURN 7209 (soc_mem_clear((unit), FP_COUNTER_TABLEm, COPYNO_ALL, TRUE)); 7210 } 7211 #if defined(BCM_SCORPION_SUPPORT) 7212 if (SOC_MEM_IS_VALID(unit, FP_COUNTER_TABLE_Xm)) { 7213 BCM_IF_ERROR_RETURN 7214 (soc_mem_clear((unit), FP_COUNTER_TABLE_Xm, COPYNO_ALL, TRUE)); 7215 } 7216 if (SOC_MEM_IS_VALID(unit, FP_COUNTER_TABLE_Ym)) { 7217 BCM_IF_ERROR_RETURN 7218 (soc_mem_clear((unit), FP_COUNTER_TABLE_Ym, COPYNO_ALL, TRUE)); 7219 } 7220 #endif /* BCM_SCORPION_SUPPORT */ 7221 BCM_IF_ERROR_RETURN 7222 (soc_mem_clear((unit), FP_PORT_FIELD_SELm, COPYNO_ALL, TRUE)); 7223 if (SOC_MEM_IS_VALID(unit, IFP_PORT_FIELD_SELm)) { 7224 BCM_IF_ERROR_RETURN 7225 (soc_mem_clear(unit, IFP_PORT_FIELD_SELm, COPYNO_ALL, TRUE)); 7226 } 7227 #if defined(BCM_TRX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) || \ 7228 defined(BCM_RAPTOR_SUPPORT) 7229 if (SOC_MEM_IS_VALID(unit, FP_SLICE_MAPm)) { 7230 BCM_IF_ERROR_RETURN 7231 (soc_mem_clear(unit, FP_SLICE_MAPm, COPYNO_ALL, TRUE)); 7232 } 7233 #endif /* RAPTOR || TRX || FB2 */ 7234 #ifdef BCM_FIREBOLT2_SUPPORT 7235 } else if (soc_feature(unit, soc_feature_field_multi_stage)) { 7236 7237 if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) { 7238 BCM_IF_ERROR_RETURN 7239 (soc_mem_clear((unit), VFP_TCAMm, COPYNO_ALL, TRUE)); 7240 BCM_IF_ERROR_RETURN 7241 (soc_mem_clear((unit), VFP_POLICY_TABLEm, COPYNO_ALL, TRUE)); 7242 7243 } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) { 7244 7245 BCM_IF_ERROR_RETURN 7246 (soc_mem_clear((unit), EFP_TCAMm, COPYNO_ALL, TRUE)); 7247 BCM_IF_ERROR_RETURN 7248 (soc_mem_clear((unit), EFP_POLICY_TABLEm, COPYNO_ALL, TRUE)); 7249 BCM_IF_ERROR_RETURN 7250 (soc_mem_clear((unit), EFP_METER_TABLEm, COPYNO_ALL, TRUE)); 7251 BCM_IF_ERROR_RETURN 7252 (soc_mem_clear((unit), EFP_COUNTER_TABLEm, COPYNO_ALL, TRUE)); 7253 } 7254 #endif /* BCM_FIREBOLT2_SUPPORT */ 7255 } else { 7256 return (BCM_E_UNAVAIL); 7257 } 7258 7259 return (BCM_E_NONE); 7260 } 7261 7262 /* 7263 * Function: 7264 * _field_fb_detach 7265 * 7266 * Purpose: 7267 * Deallocates BCM5650x's field tables. 7268 * 7269 * Parameters: 7270 * unit - BCM device number 7271 * 7272 * Returns: 7273 * BCM_E_NONE 7274 */ 7275 STATIC int 7276 _field_fb_detach(int unit, _field_control_t *fc) 7277 { 7278 _field_stage_t *stage_p; /* Stage iteration pointer. */ 7279 7280 stage_p = fc->stages; 7281 7282 while (stage_p) { 7283 /* Clear the hardware tables */ 7284 BCM_IF_ERROR_RETURN(_field_fb_hw_clear(unit, stage_p)); 7285 7286 /* Goto next stage */ 7287 stage_p = stage_p->next; 7288 } 7289 7290 /* Clear udf match criteria registers. */ 7291 BCM_IF_ERROR_RETURN(_bcm_field_fb_udf_ipprotocol_delete_all(unit)); 7292 BCM_IF_ERROR_RETURN(_bcm_field_fb_udf_ethertype_delete_all(unit)); 7293 7294 /* Don't disable port controls during Warmboot or Reloading state */ 7295 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 7296 /* Clear the Filter Enable flags in the port table */ 7297 BCM_IF_ERROR_RETURN (_field_port_filter_enable_set(unit, fc, FALSE)); 7298 } 7299 7300 BCM_IF_ERROR_RETURN (_field_meter_refresh_enable_set(unit, fc, FALSE)); 7301 7302 return (BCM_E_NONE); 7303 } 7304 7305 #ifdef BROADCOM_DEBUG 7306 /* 7307 * Function: 7308 * _field_fb_action_name 7309 * Purpose: 7310 * Return text name of indicated action enum value. 7311 */ 7312 STATIC char * 7313 _field_fb_action_name(bcm_field_action_t action) 7314 { 7315 /* Text names of Actions. These are used for debugging output and CLIs. 7316 * Note that the order needs to match the bcm_field_action_t enum order. 7317 */ 7318 static char *action_text[] = BCM_FIELD_ACTION_STRINGS; 7319 assert(COUNTOF(action_text) == bcmFieldActionCount); 7320 return (action >= bcmFieldActionCount ? "??" : action_text[action]); 7321 } 7322 7323 #endif /* BROADCOM_DEBUG*/ 7324 7325 #if defined(BCM_FIREBOLT2_SUPPORT) 7326 /* 7327 * Function: 7328 * _field_fb_egress_selcode_get 7329 * Purpose: 7330 * Finds a select encodings that will satisfy the 7331 * requested qualifier set (Qset). 7332 * Parameters: 7333 * unit - (IN) BCM unit number. 7334 * stage_fc - (IN) Stage Field control structure. 7335 * qset_req - (IN) Client qualifier set. 7336 * fg - (IN/OUT)Select code information filled into the group. 7337 * 7338 * Returns: 7339 * BCM_E_XXX 7340 */ 7341 STATIC int 7342 _field_fb_egress_selcode_get(int unit, _field_stage_t *stage_fc, 7343 bcm_field_qset_t *qset_req, 7344 _field_group_t *fg) 7345 { 7346 int rv; /* Operation return status. */ 7347 7348 /* Input parameters check. */ 7349 if ((NULL == fg) || (NULL == qset_req) || (NULL == stage_fc)) { 7350 return (BCM_E_PARAM); 7351 } 7352 7353 if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) { 7354 /* Attempt _BCM_FIELD_EFP_KEY4 (L2 key). */ 7355 rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 7356 _BCM_FIELD_EFP_KEY4, 0, fg); 7357 if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) { 7358 return rv; 7359 } 7360 7361 /* Attempt _BCM_FIELD_EFP_KEY1 (IPv4 key). */ 7362 if (BCM_FIELD_QSET_TEST(*qset_req, bcmFieldQualifyIp4)) { 7363 rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 7364 _BCM_FIELD_EFP_KEY1, 0, fg); 7365 if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) { 7366 return rv; 7367 } 7368 } 7369 7370 /* Attempt _BCM_FIELD_EFP_KEY2 (IPv6 key). */ 7371 if (BCM_FIELD_QSET_TEST(*qset_req, bcmFieldQualifyIp6)) { 7372 rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 7373 _BCM_FIELD_EFP_KEY2, 0, fg); 7374 if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) { 7375 return rv; 7376 } 7377 } 7378 } else { 7379 /* IPv6 double wide predefined key. */ 7380 if (BCM_FIELD_QSET_TEST(*qset_req, bcmFieldQualifyIp6)) { 7381 rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 7382 _BCM_FIELD_EFP_KEY3, 7383 _BCM_FIELD_EFP_KEY2, fg); 7384 if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) { 7385 return rv; 7386 } 7387 } 7388 7389 /* L2 + L3 double wide predefined key. */ 7390 if (BCM_FIELD_QSET_TEST(*qset_req, bcmFieldQualifyIp4)) { 7391 rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 7392 _BCM_FIELD_EFP_KEY1, 7393 _BCM_FIELD_EFP_KEY4, fg); 7394 if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) { 7395 return rv; 7396 } 7397 } 7398 } 7399 return (BCM_E_RESOURCE); 7400 } 7401 #endif /* BCM_FIREBOLT2_SUPPORT */ 7402 7403 7404 /* 7405 * Function: 7406 * _bcm_field_fb_group_inner_vlan_overlay_get 7407 * Purpose: 7408 * Returns inner vlan overlay for a group. 7409 * Parameters: 7410 * uint - (IN) BCM unit number. 7411 * value - (OUT) Inner vlan overlay value. 7412 * 7413 * Returns: 7414 * BCM_E_XXX 7415 * Note: 7416 */ 7417 int 7418 _bcm_field_fb_group_inner_vlan_overlay_get (int unit, int *value) 7419 { 7420 _field_control_t *fc; /* field control structure. */ 7421 _field_group_t *fg; /* field group structure. */ 7422 7423 if (NULL == value) { 7424 return (BCM_E_PARAM); 7425 } 7426 7427 /* Get field control strucutre.*/ 7428 BCM_IF_ERROR_RETURN(_field_control_get (unit, &fc)); 7429 7430 /* Iterate over all the groups to check for conflicts. */ 7431 fg = fc->groups; 7432 7433 while (NULL != fg) { 7434 if ((fg->stage_id == _BCM_FIELD_STAGE_INGRESS) && 7435 (_FP_SELCODE_DONT_CARE != fg->sel_codes[0].inner_vlan_overlay)) { 7436 *value = fg->sel_codes[0].inner_vlan_overlay; 7437 break; 7438 } 7439 fg = fg->next; 7440 } 7441 7442 if (NULL == fg) { 7443 *value = _FP_SELCODE_DONT_CARE; 7444 } 7445 return (BCM_E_NONE); 7446 } 7447 #if defined (BCM_FIREBOLT2_SUPPORT) 7448 /* 7449 * Function: 7450 * _bcm_field_vfp_doublewide_key_select_get 7451 * Purpose: 7452 * Returns vfp doublewide key selection on FB2 7453 * Parameters: 7454 * uint - (IN) BCM unit number. 7455 * value - (OUT) Inner vlan overlay value. 7456 * 7457 * Returns: 7458 * BCM_E_RESOURCE - Conflict observed inside the group. 7459 * BCM_E_NONE - otherwise 7460 * Note: 7461 */ 7462 int 7463 _bcm_field_vfp_doublewide_key_select_get(int unit, int *value) 7464 { 7465 _field_control_t *fc; /* field control structure. */ 7466 _field_group_t *fg; /* field group structure. */ 7467 7468 if (NULL == value) { 7469 return (BCM_E_PARAM); 7470 } 7471 7472 if (0 == SOC_IS_FIREBOLT2(unit)) { 7473 *value = _FP_SELCODE_DONT_CARE; 7474 return (BCM_E_NONE); 7475 } 7476 7477 /* Get field control strucutre.*/ 7478 BCM_IF_ERROR_RETURN(_field_control_get (unit, &fc)); 7479 7480 /* Iterate over all the groups to check for conflicts. */ 7481 fg = fc->groups; 7482 7483 while (NULL != fg) { 7484 if ((fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) && 7485 (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 7486 (_FP_SELCODE_DONT_CARE != fg->sel_codes[0].intraslice_vfp_sel)) { 7487 *value = fg->sel_codes[0].intraslice_vfp_sel; 7488 break; 7489 } 7490 fg = fg->next; 7491 } 7492 7493 if (NULL == fg) { 7494 *value = _FP_SELCODE_DONT_CARE; 7495 } 7496 return (BCM_E_NONE); 7497 } 7498 #endif /* BCM_FIREBOLT2_SUPPORT */ 7499 7500 7501 /* 7502 * Function: 7503 * _field_fb_tcam_policy_clear 7504 * 7505 * Purpose: 7506 * Writes a null entry into the TCAM plus Policy table. 7507 * 7508 * Parameters: 7509 * unit - (IN)BCM device number. 7510 * stage_id - (IN)FP stage pipeline id. 7511 * tcam_idx - (IN)Entry tcam index. 7512 * 7513 * Returns: 7514 * BCM_E_XXX 7515 * 7516 * Note: 7517 * Unit lock should be held by calling function. 7518 */ 7519 int 7520 _field_fb_tcam_policy_clear(int unit, _field_entry_t *f_ent, 7521 _field_stage_id_t stage_id, int tcam_idx) 7522 { 7523 soc_mem_t tcam_mem; /* TCAM memory id. */ 7524 soc_mem_t policy_mem; /* Policy table memory id . */ 7525 7526 BCM_IF_ERROR_RETURN 7527 (_field_fb_tcam_policy_mem_get(unit, stage_id, &tcam_mem, &policy_mem)); 7528 7529 /* Memory index sanity check. */ 7530 if (tcam_idx > soc_mem_index_max(unit, tcam_mem)) { 7531 return (BCM_E_PARAM); 7532 } 7533 7534 /* Write the TCAM & Policy Tables */ 7535 SOC_IF_ERROR_RETURN 7536 (soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, tcam_idx, 7537 soc_mem_entry_null(unit, tcam_mem))); 7538 SOC_IF_ERROR_RETURN 7539 (soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx, 7540 soc_mem_entry_null(unit, policy_mem))); 7541 #ifdef BCM_TRIDENT2_SUPPORT 7542 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit) || SOC_IS_TD2P_TT2P(unit)) { 7543 if ((SOC_MEM_IS_VALID(unit, FP_GM_FIELDSm)) && 7544 (stage_id == _BCM_FIELD_STAGE_INGRESS) && 7545 (f_ent != NULL) && (f_ent->flags & _FP_ENTRY_SECONDARY)) { 7546 SOC_IF_ERROR_RETURN 7547 (soc_mem_write(unit, FP_GM_FIELDSm, 7548 MEM_BLOCK_ALL, tcam_idx, 7549 soc_mem_entry_null(unit, FP_GM_FIELDSm))); 7550 } else if ((SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) && 7551 (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 7552 SOC_IF_ERROR_RETURN 7553 (soc_mem_write(unit, FP_GLOBAL_MASK_TCAMm, 7554 MEM_BLOCK_ALL, tcam_idx, 7555 soc_mem_entry_null 7556 (unit, FP_GLOBAL_MASK_TCAMm))); 7557 } 7558 } else 7559 #endif 7560 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 7561 if ((SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) && 7562 (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 7563 SOC_IF_ERROR_RETURN (soc_mem_write(unit, FP_GLOBAL_MASK_TCAMm, 7564 MEM_BLOCK_ALL, tcam_idx, 7565 soc_mem_entry_null(unit, FP_GLOBAL_MASK_TCAMm))); 7566 } 7567 #endif /* BCM_TRIUMPH_SUPPORT */ 7568 7569 #if defined(BCM_SCORPION_SUPPORT) 7570 if ((SOC_IS_SC_CQ(unit)) && (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 7571 SOC_IF_ERROR_RETURN 7572 (soc_mem_write(unit, FP_TCAM_Ym, 7573 MEM_BLOCK_ALL, tcam_idx, 7574 soc_mem_entry_null(unit, FP_TCAM_Ym))); 7575 } 7576 #endif /* BCM_SCORPION_SUPPORT */ 7577 7578 return (BCM_E_NONE); 7579 } 7580 7581 7582 /* 7583 * Function: 7584 * _bcm_field_fb_counter_adjust_wide_mode 7585 * Purpose: 7586 * For wide mode entries, 7587 * if there is movement across slices, 7588 * handle the counter mode and index 7589 * Parameters: 7590 * unit - BCM unit 7591 * policy_mem - policy memory 7592 * f_st - Statistics collection entity. 7593 * f_ent_pri - PRI entry 7594 * f_ent_sec - SEC entry 7595 * p_entry_pri - policy table for PRI entry 7596 * p_entry_sec - policy table for SEC entry 7597 * Returns: 7598 * none 7599 * Notes: 7600 * FOUR cases are to be handled 7601 * 1. previously counter in PRI slice, now in PRI slice 7602 * 2. previously counter in PRI slice, now in SEC slice 7603 * 3. previously counter in SEC slice, now in PRI slice 7604 * 4. previously counter in SEC slice, now in SEC slice 7605 */ 7606 void 7607 _bcm_field_fb_counter_adjust_wide_mode(int unit, 7608 soc_mem_t policy_mem, 7609 _field_stat_t *f_st, 7610 _field_entry_t *f_ent_pri, 7611 _field_entry_t *f_ent_sec, 7612 int new_slice_numb, 7613 uint32 p_entry_pri[], 7614 uint32 p_entry_sec[]) 7615 { 7616 int mode; 7617 7618 if ((mode = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, 7619 COUNTER_MODEf)) != 0) { 7620 if (new_slice_numb == f_st->pool_index) { 7621 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7622 COUNTER_INDEXf, f_st->hw_index); 7623 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7624 COUNTER_MODEf, f_st->hw_mode); 7625 } else if ((new_slice_numb + 1) == f_st->pool_index) { 7626 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7627 COUNTER_MODEf, 0); 7628 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7629 COUNTER_MODEf, f_st->hw_mode); 7630 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7631 COUNTER_INDEXf, f_st->hw_index); 7632 } 7633 } else if ((mode = soc_mem_field32_get(unit, policy_mem, 7634 (uint32 *) p_entry_sec, COUNTER_MODEf)) != 0) { 7635 if (new_slice_numb == f_st->pool_index) { 7636 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7637 COUNTER_MODEf, f_st->hw_mode); 7638 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7639 COUNTER_INDEXf, f_st->hw_index); 7640 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7641 COUNTER_MODEf, 0); 7642 } else if ((new_slice_numb + 1) == f_st->pool_index) { 7643 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7644 COUNTER_INDEXf, f_st->hw_index); 7645 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7646 COUNTER_MODEf, f_st->hw_mode); 7647 } 7648 } 7649 } 7650 7651 /* 7652 * Function: 7653 * _bcm_field_fb_meter_adjust_wide_mode 7654 * Purpose: 7655 * For wide mode entries, 7656 * if there is movement across slices, 7657 * handle the meter mode, index, update & valid bits 7658 * Parameters: 7659 * unit - BCM unit 7660 * policy_mem - policy memory 7661 * f_ent_pri - PRI entry 7662 * f_ent_sec - SEC entry 7663 * p_entry_pri - policy table for PRI entry 7664 * p_entry_sec - policy table for SEC entry 7665 * Returns: 7666 * none 7667 * Notes: 7668 * FOUR cases are to be handled 7669 * 1. previously meter in PRI slice, now in PRI slice 7670 * 2. previously meter in PRI slice, now in SEC slice 7671 * 3. previously meter in SEC slice, now in PRI slice 7672 * 4. previously meter in SEC slice, now in SEC slice 7673 * MUST BE CALLED AFTER COUNTER ADJUST. 7674 */ 7675 void 7676 _bcm_field_fb_meter_adjust_wide_mode(int unit, 7677 soc_mem_t policy_mem, 7678 _field_policer_t *f_pl, 7679 _field_entry_t *f_ent_pri, 7680 _field_entry_t *f_ent_sec, 7681 uint32 p_entry_pri[], 7682 uint32 p_entry_sec[]) 7683 { 7684 uint32 counter_mode_pri; 7685 uint32 counter_mode_sec; 7686 uint32 counter_idx_pri; 7687 uint32 counter_idx_sec; 7688 int mode; 7689 int restore_counter = FALSE; 7690 7691 7692 /* Preserve counter mode. */ 7693 if (f_pl->stage_id == _BCM_FIELD_STAGE_EGRESS ) { 7694 counter_mode_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, PID_COUNTER_MODEf); 7695 counter_idx_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, PID_COUNTER_INDEXf); 7696 counter_mode_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, PID_COUNTER_MODEf); 7697 counter_idx_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, PID_COUNTER_INDEXf); 7698 } else if (f_pl->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 7699 counter_mode_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, USE_VINTF_CTR_IDXf); 7700 counter_idx_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, VINTF_CTR_IDXf); 7701 counter_mode_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, USE_VINTF_CTR_IDXf); 7702 counter_idx_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, VINTF_CTR_IDXf); 7703 } else { 7704 counter_mode_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, COUNTER_MODEf); 7705 counter_idx_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, COUNTER_INDEXf); 7706 counter_mode_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, COUNTER_MODEf); 7707 counter_idx_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, COUNTER_INDEXf); 7708 } 7709 /* if meter to be moved is from primary slice*/ 7710 if ((mode = soc_mem_field32_get(unit, policy_mem, 7711 (uint32 *) p_entry_pri, METER_PAIR_MODEf)) != 0) { 7712 if ((f_pl->stage_id == _BCM_FIELD_STAGE_EGRESS) && 7713 (SOC_IS_TRIDENT2PLUS(unit))) { 7714 /* if the destination entry is allocated from primar slice, 7715 * even or odd meter mode should be managed accordingly 7716 */ 7717 if (!(f_ent_pri->flags & _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE)) { 7718 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7719 METER_INDEX_EVENf, f_pl->hw_index); 7720 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7721 METER_INDEX_ODDf, f_pl->hw_index); 7722 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 7723 /* Excess meter - even index. */ 7724 soc_mem_field32_set(unit, policy_mem, 7725 (uint32 *) p_entry_pri, 7726 METER_TEST_ODDf, 0); 7727 if (SOC_IS_KATANA2(unit) && 7728 (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) { 7729 soc_mem_field32_set(unit, policy_mem, 7730 (uint32 *) p_entry_pri, 7731 METER_TEST_EVENf, 0); 7732 } else { 7733 soc_mem_field32_set(unit, policy_mem, 7734 (uint32 *) p_entry_pri, 7735 METER_TEST_EVENf, 1); 7736 } 7737 soc_mem_field32_set(unit, policy_mem, 7738 (uint32 *) p_entry_pri, 7739 METER_UPDATE_ODDf, 0); 7740 soc_mem_field32_set(unit, policy_mem, 7741 (uint32 *) p_entry_pri, 7742 METER_UPDATE_EVENf, 1); 7743 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 7744 /* Committed meter - odd index. */ 7745 if (SOC_IS_KATANA2(unit) && 7746 (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) { 7747 soc_mem_field32_set(unit, policy_mem, 7748 (uint32 *) p_entry_pri, 7749 METER_TEST_ODDf, 0); 7750 } else { 7751 soc_mem_field32_set(unit, policy_mem, 7752 (uint32 *) p_entry_pri, 7753 METER_TEST_ODDf, 1); 7754 } 7755 soc_mem_field32_set(unit, policy_mem, 7756 (uint32 *) p_entry_pri, 7757 METER_TEST_EVENf, 0); 7758 soc_mem_field32_set(unit, policy_mem, 7759 (uint32 *) p_entry_pri, 7760 METER_UPDATE_ODDf, 1); 7761 soc_mem_field32_set(unit, policy_mem, 7762 (uint32 *) p_entry_pri, 7763 METER_UPDATE_EVENf, 0); 7764 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) { 7765 soc_mem_field32_set(unit, policy_mem, 7766 (uint32 *) p_entry_pri, 7767 METER_TEST_EVENf, 1); 7768 } 7769 #if defined(BCM_TRIDENT2_SUPPORT) 7770 else if (f_pl->cfg.mode == bcmPolicerModeSrTcmModified 7771 && (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 7772 soc_mem_field32_set(unit, policy_mem, 7773 (uint32 *) p_entry_pri, 7774 METER_MODE_MODIFIERf, 1); 7775 } 7776 #endif 7777 } else { 7778 sal_memcpy(p_entry_sec, p_entry_pri, 7779 soc_mem_entry_words(unit, policy_mem)*sizeof(uint32)); 7780 sal_memset(p_entry_pri, 0, 7781 soc_mem_entry_words(unit, policy_mem)*sizeof(uint32)); 7782 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7783 METER_PAIR_MODEf, mode); 7784 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7785 METER_INDEX_EVENf, f_pl->hw_index); 7786 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7787 METER_INDEX_ODDf, f_pl->hw_index); 7788 restore_counter = TRUE; 7789 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 7790 /* Excess meter - even index. */ 7791 soc_mem_field32_set(unit, policy_mem, 7792 (uint32 *) p_entry_sec, 7793 METER_TEST_ODDf, 0); 7794 if (SOC_IS_KATANA2(unit) && 7795 (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) { 7796 soc_mem_field32_set(unit, policy_mem, 7797 (uint32 *) p_entry_sec, 7798 METER_TEST_EVENf, 0); 7799 } else { 7800 soc_mem_field32_set(unit, policy_mem, 7801 (uint32 *) p_entry_sec, 7802 METER_TEST_EVENf, 1); 7803 } 7804 soc_mem_field32_set(unit, policy_mem, 7805 (uint32 *) p_entry_sec, 7806 METER_UPDATE_ODDf, 0); 7807 soc_mem_field32_set(unit, policy_mem, 7808 (uint32 *) p_entry_sec, 7809 METER_UPDATE_EVENf, 1); 7810 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 7811 /* Committed meter - odd index. */ 7812 if (SOC_IS_KATANA2(unit) && 7813 (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) { 7814 soc_mem_field32_set(unit, policy_mem, 7815 (uint32 *) p_entry_sec, 7816 METER_TEST_ODDf, 0); 7817 } else { 7818 soc_mem_field32_set(unit, policy_mem, 7819 (uint32 *) p_entry_sec, 7820 METER_TEST_ODDf, 1); 7821 } 7822 soc_mem_field32_set(unit, policy_mem, 7823 (uint32 *) p_entry_sec, 7824 METER_TEST_EVENf, 0); 7825 soc_mem_field32_set(unit, policy_mem, 7826 (uint32 *) p_entry_sec, 7827 METER_UPDATE_ODDf, 1); 7828 soc_mem_field32_set(unit, policy_mem, 7829 (uint32 *) p_entry_sec, 7830 METER_UPDATE_EVENf, 0); 7831 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) { 7832 soc_mem_field32_set(unit, policy_mem, 7833 (uint32 *) p_entry_sec, 7834 METER_TEST_EVENf, 1); 7835 } 7836 #if defined(BCM_TRIDENT2_SUPPORT) 7837 else if (f_pl->cfg.mode == bcmPolicerModeSrTcmModified 7838 && (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 7839 soc_mem_field32_set(unit, policy_mem, 7840 (uint32 *) p_entry_sec, 7841 METER_MODE_MODIFIERf, 1); 7842 } 7843 #endif 7844 } 7845 } else { 7846 if (f_ent_pri->fs->slice_number == f_pl->pool_index) { 7847 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7848 METER_INDEX_EVENf, f_pl->hw_index); 7849 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7850 METER_INDEX_ODDf, f_pl->hw_index); 7851 7852 } else if (f_ent_sec->fs->slice_number == f_pl->pool_index) { 7853 sal_memcpy(p_entry_sec, p_entry_pri, 7854 soc_mem_entry_words(unit, policy_mem)*sizeof(uint32)); 7855 sal_memset(p_entry_pri, 0, 7856 soc_mem_entry_words(unit, policy_mem)*sizeof(uint32)); 7857 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7858 METER_PAIR_MODEf, mode); 7859 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7860 METER_INDEX_EVENf, f_pl->hw_index); 7861 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7862 METER_INDEX_ODDf, f_pl->hw_index); 7863 restore_counter = TRUE; 7864 } 7865 } 7866 /* if source entry is allocated from secondary slice */ 7867 } else if ((mode = soc_mem_field32_get(unit, policy_mem, 7868 (uint32 *) p_entry_sec, METER_PAIR_MODEf)) != 0) { 7869 7870 if ((f_pl->stage_id == _BCM_FIELD_STAGE_EGRESS) && 7871 (SOC_IS_TRIDENT2PLUS(unit))) { 7872 if (!(f_ent_pri->flags & _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE)) { 7873 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7874 METER_INDEX_EVENf, f_pl->hw_index); 7875 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 7876 METER_INDEX_ODDf, f_pl->hw_index); 7877 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 7878 /* Excess meter - even index. */ 7879 soc_mem_field32_set(unit, policy_mem, 7880 (uint32 *) p_entry_pri, 7881 METER_TEST_ODDf, 0); 7882 if (SOC_IS_KATANA2(unit) && 7883 (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) { 7884 soc_mem_field32_set(unit, policy_mem, 7885 (uint32 *) p_entry_pri, 7886 METER_TEST_EVENf, 0); 7887 } else { 7888 soc_mem_field32_set(unit, policy_mem, 7889 (uint32 *) p_entry_pri, 7890 METER_TEST_EVENf, 1); 7891 } 7892 soc_mem_field32_set(unit, policy_mem, 7893 (uint32 *) p_entry_pri, 7894 METER_UPDATE_ODDf, 0); 7895 soc_mem_field32_set(unit, policy_mem, 7896 (uint32 *) p_entry_pri, 7897 METER_UPDATE_EVENf, 1); 7898 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 7899 /* Committed meter - odd index. */ 7900 if (SOC_IS_KATANA2(unit) && 7901 (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) { 7902 soc_mem_field32_set(unit, policy_mem, 7903 (uint32 *) p_entry_pri, 7904 METER_TEST_ODDf, 0); 7905 } else { 7906 soc_mem_field32_set(unit, policy_mem, 7907 (uint32 *) p_entry_pri, 7908 METER_TEST_ODDf, 1); 7909 } 7910 soc_mem_field32_set(unit, policy_mem, 7911 (uint32 *) p_entry_pri, 7912 METER_TEST_EVENf, 0); 7913 soc_mem_field32_set(unit, policy_mem, 7914 (uint32 *) p_entry_pri, 7915 METER_UPDATE_ODDf, 1); 7916 soc_mem_field32_set(unit, policy_mem, 7917 (uint32 *) p_entry_pri, 7918 METER_UPDATE_EVENf, 0); 7919 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) { 7920 soc_mem_field32_set(unit, policy_mem, 7921 (uint32 *) p_entry_pri, 7922 METER_TEST_EVENf, 1); 7923 } 7924 #if defined(BCM_TRIDENT2_SUPPORT) 7925 else if (f_pl->cfg.mode == bcmPolicerModeSrTcmModified 7926 && (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 7927 soc_mem_field32_set(unit, policy_mem, 7928 (uint32 *) p_entry_pri, 7929 METER_MODE_MODIFIERf, 1); 7930 } 7931 #endif 7932 } else { 7933 sal_memcpy(p_entry_sec, p_entry_pri, 7934 soc_mem_entry_words(unit, policy_mem)*sizeof(uint32)); 7935 sal_memset(p_entry_pri, 0, 7936 soc_mem_entry_words(unit, policy_mem)*sizeof(uint32)); 7937 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7938 METER_PAIR_MODEf, mode); 7939 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7940 METER_INDEX_EVENf, f_pl->hw_index); 7941 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 7942 METER_INDEX_ODDf, f_pl->hw_index); 7943 restore_counter = TRUE; 7944 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 7945 /* Excess meter - even index. */ 7946 soc_mem_field32_set(unit, policy_mem, 7947 (uint32 *) p_entry_sec, 7948 METER_TEST_ODDf, 0); 7949 if (SOC_IS_KATANA2(unit) && 7950 (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) { 7951 soc_mem_field32_set(unit, policy_mem, 7952 (uint32 *) p_entry_sec, 7953 METER_TEST_EVENf, 0); 7954 } else { 7955 soc_mem_field32_set(unit, policy_mem, 7956 (uint32 *) p_entry_sec, 7957 METER_TEST_EVENf, 1); 7958 } 7959 soc_mem_field32_set(unit, policy_mem, 7960 (uint32 *) p_entry_sec, 7961 METER_UPDATE_ODDf, 0); 7962 soc_mem_field32_set(unit, policy_mem, 7963 (uint32 *) p_entry_sec, 7964 METER_UPDATE_EVENf, 1); 7965 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 7966 /* Committed meter - odd index. */ 7967 if (SOC_IS_KATANA2(unit) && 7968 (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) { 7969 soc_mem_field32_set(unit, policy_mem, 7970 (uint32 *) p_entry_sec, 7971 METER_TEST_ODDf, 0); 7972 } else { 7973 soc_mem_field32_set(unit, policy_mem, 7974 (uint32 *) p_entry_sec, 7975 METER_TEST_ODDf, 1); 7976 } 7977 soc_mem_field32_set(unit, policy_mem, 7978 (uint32 *) p_entry_sec, 7979 METER_TEST_EVENf, 0); 7980 soc_mem_field32_set(unit, policy_mem, 7981 (uint32 *) p_entry_sec, 7982 METER_UPDATE_ODDf, 1); 7983 soc_mem_field32_set(unit, policy_mem, 7984 (uint32 *) p_entry_sec, 7985 METER_UPDATE_EVENf, 0); 7986 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) { 7987 soc_mem_field32_set(unit, policy_mem, 7988 (uint32 *) p_entry_sec, 7989 METER_TEST_EVENf, 1); 7990 } 7991 #if defined(BCM_TRIDENT2_SUPPORT) 7992 else if (f_pl->cfg.mode == bcmPolicerModeSrTcmModified 7993 && (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 7994 soc_mem_field32_set(unit, policy_mem, 7995 (uint32 *) p_entry_sec, 7996 METER_MODE_MODIFIERf, 1); 7997 } 7998 #endif 7999 } 8000 } else { 8001 if (f_ent_pri->fs->slice_number == f_pl->pool_index) { 8002 sal_memcpy(p_entry_pri, p_entry_sec, 8003 soc_mem_entry_words(unit, policy_mem)*sizeof(uint32)); 8004 sal_memset(p_entry_sec, 0, 8005 soc_mem_entry_words(unit, policy_mem)*sizeof(uint32)); 8006 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8007 METER_PAIR_MODEf, mode); 8008 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8009 METER_INDEX_EVENf, f_pl->hw_index); 8010 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8011 METER_INDEX_ODDf, f_pl->hw_index); 8012 restore_counter = TRUE; 8013 } else if (f_ent_sec->fs->slice_number == f_pl->pool_index) { 8014 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 8015 METER_INDEX_EVENf, f_pl->hw_index); 8016 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 8017 METER_INDEX_ODDf, f_pl->hw_index); 8018 } 8019 } 8020 } 8021 8022 if (restore_counter) { 8023 if (f_pl->stage_id == _BCM_FIELD_STAGE_EGRESS ) { 8024 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 8025 PID_COUNTER_INDEXf, counter_idx_sec); 8026 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 8027 PID_COUNTER_MODEf, counter_mode_sec); 8028 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8029 PID_COUNTER_INDEXf, counter_idx_pri); 8030 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8031 PID_COUNTER_MODEf, counter_mode_pri); 8032 } if (f_pl->stage_id == _BCM_FIELD_STAGE_LOOKUP ) { 8033 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 8034 VINTF_CTR_IDXf, counter_idx_sec); 8035 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 8036 USE_VINTF_CTR_IDXf, counter_mode_sec); 8037 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8038 VINTF_CTR_IDXf, counter_idx_pri); 8039 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8040 USE_VINTF_CTR_IDXf, counter_mode_pri); 8041 } else { 8042 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 8043 COUNTER_INDEXf, counter_idx_sec); 8044 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 8045 COUNTER_MODEf, counter_mode_sec); 8046 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8047 COUNTER_INDEXf, counter_idx_pri); 8048 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 8049 COUNTER_MODEf, counter_mode_pri); 8050 } 8051 } 8052 } 8053 8054 /* 8055 * Function: 8056 * _bcm_field_fb_entry_move 8057 * Purpose: 8058 * Copy an entry from one TCAM index to another. It copies the values in 8059 * hardware from the old index to the new index. 8060 * IT IS ASSUMED THAT THE NEW INDEX IS EMPTY (VALIDf=00) IN HARDWARE. 8061 * The old Hardware index is cleared at the end. 8062 * Parameters: 8063 * unit - (IN) BCM device number. 8064 * f_ent - (IN) Entry to move 8065 * parts_count - (IN) Field entry parts count. 8066 * tcam_idx_old - (IN) Source entry tcam index. 8067 * tcam_idx_new - (IN) Destination entry tcam index. 8068 * 8069 * Returns: 8070 * BCM_E_XXX 8071 */ 8072 int 8073 _bcm_field_fb_entry_move(int unit, _field_entry_t *f_ent, int parts_count, 8074 int *tcam_idx_old, int *tcam_idx_new) 8075 { 8076 static uint32 e_buf[BCM_MAX_NUM_UNITS][25]; 8077 /* For TCAM */ 8078 static uint32 p_buf[BCM_MAX_NUM_UNITS][_FP_MAX_ENTRY_WIDTH][25]; 8079 /* For policies */ 8080 int new_slice_numb = 0; /* Entry new slice number. */ 8081 int new_slice_idx = 0; /* Entry new offset in the slice */ 8082 soc_mem_t tcam_mem; /* TCAM memory id. */ 8083 soc_mem_t policy_mem; /* Policy table memory id . */ 8084 int tcam_idx_max; /* TCAM memory max index. */ 8085 int tcam_idx_min; /* TCAM memory min index. */ 8086 _field_stage_t *stage_fc; /* Stage field control structure. */ 8087 _field_stage_id_t stage_id; /* Field pipeline stage id. */ 8088 int idx; /* Iteration index. */ 8089 _field_policer_t *f_pl = NULL; /* Field policer descriptor. */ 8090 _field_stat_t *f_st = NULL; /* Field statistics descriptor. */ 8091 _field_group_t *fg; /* Field group structure. */ 8092 int rv; /* Operation return status. */ 8093 int is_backup_entry = 0; /* Flag ,checks the entry is backup entry or not*/ 8094 #ifdef BCM_TRIUMPH_SUPPORT 8095 fp_global_mask_tcam_entry_t ipbm_entry[_FP_MAX_ENTRY_WIDTH]; /* Always in PRI entry, 1st half */ 8096 #endif /* BCM_TRIUMPH_SUPPORT */ 8097 #ifdef BCM_TRIDENT_SUPPORT 8098 fp_global_mask_tcam_x_entry_t fp_global_mask_x[_FP_MAX_ENTRY_WIDTH]; 8099 fp_global_mask_tcam_y_entry_t fp_global_mask_y[_FP_MAX_ENTRY_WIDTH]; 8100 fp_global_mask_tcam_entry_t fp_global_mask[_FP_MAX_ENTRY_WIDTH]; 8101 fp_gm_fields_entry_t fp_gm_fields[_FP_MAX_ENTRY_WIDTH]; 8102 bcm_pbmp_t pbmp_x, pbmp_y; 8103 #endif /* !BCM_TRIDENT_SUPPORT */ 8104 8105 8106 /* Input parameters check. */ 8107 if ((NULL == f_ent) || (NULL == tcam_idx_old) || (NULL == tcam_idx_new)) { 8108 return (BCM_E_PARAM); 8109 } 8110 8111 fg = f_ent->group; 8112 8113 /* Get field stage control . */ 8114 stage_id = f_ent->group->stage_id; 8115 rv = _field_stage_control_get(unit, stage_id, &stage_fc); 8116 BCM_IF_ERROR_RETURN(rv); 8117 8118 /* Get entry tcam and actions. */ 8119 rv = _field_fb_tcam_policy_mem_get(unit, stage_id, &tcam_mem, &policy_mem); 8120 BCM_IF_ERROR_RETURN(rv); 8121 8122 tcam_idx_max = soc_mem_index_max(unit, tcam_mem); 8123 tcam_idx_min = soc_mem_index_min(unit, tcam_mem); 8124 8125 /* Update policy entry if moving across the slices. */ 8126 if (((NULL != f_ent->ent_copy) && 8127 (f_ent->ent_copy->eid == _FP_INTERNAL_RESERVED_ID))) { 8128 is_backup_entry = 1; 8129 } 8130 8131 for (idx = 0; idx < parts_count; idx++) { 8132 /* Index sanity check. */ 8133 if ((tcam_idx_old[idx] < tcam_idx_min) || (tcam_idx_old[idx] > tcam_idx_max) || 8134 (tcam_idx_new[idx] < tcam_idx_min) || (tcam_idx_new[idx] > tcam_idx_max)) { 8135 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, 8136 "Invalid index range from %d to %d."), 8137 tcam_idx_old[idx], tcam_idx_new[idx])); 8138 8139 rv = BCM_E_PARAM; 8140 /* coverity[dead_error_line:FALSE] */ 8141 BCM_IF_ERROR_RETURN(rv); 8142 } 8143 8144 /* Read policy entry from current tcam index. */ 8145 rv = soc_mem_read(unit, policy_mem, MEM_BLOCK_ANY, tcam_idx_old[idx], 8146 p_buf[unit][idx]); 8147 BCM_IF_ERROR_RETURN(rv); 8148 8149 #ifdef BCM_TRIDENT_SUPPORT 8150 /* 8151 * On Trident, VALIDf of FP_GLOBAL_MASK_TCAMm must be set 8152 * for all parts of an wide/paired mode entry. 8153 * This bit would have been set during entry install. 8154 * Read this value from all parts of an entry while moving. 8155 * Otherwise, actions related to this entry would not work. 8156 */ 8157 if (SOC_IS_TD_TT(unit) && (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 8158 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) 8159 && (0x1 & idx)) { 8160 rv = READ_FP_GM_FIELDSm(unit, MEM_BLOCK_ANY, 8161 tcam_idx_old[idx], &fp_gm_fields[idx]); 8162 BCM_IF_ERROR_RETURN(rv); 8163 } else { 8164 rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY, 8165 tcam_idx_old[idx], &fp_global_mask[idx]); 8166 BCM_IF_ERROR_RETURN(rv); 8167 } 8168 } else 8169 #endif /* !BCM_TRIDENT_SUPPORT */ 8170 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 8171 if ((SOC_IS_KATANAX(unit) 8172 || SOC_IS_TRIUMPH3(unit)) 8173 && (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 8174 rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY, 8175 tcam_idx_old[idx], &ipbm_entry[idx]); 8176 BCM_IF_ERROR_RETURN(rv); 8177 } else 8178 #endif /* BCM_KATANA_SUPPORT */ 8179 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 8180 { 8181 if ((SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) 8182 && (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 8183 rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY, 8184 tcam_idx_old[idx], &ipbm_entry[idx]); 8185 BCM_IF_ERROR_RETURN(rv); 8186 } 8187 } 8188 #endif /* BCM_TRIUMPH_SUPPORT || BCM_TRIUMPH2_SUPPORT */ 8189 } 8190 8191 /* Calculate primary entry new slice & offset in the slice. */ 8192 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc, _FP_DEF_INST, 8193 tcam_idx_new[0], 8194 &new_slice_numb, &new_slice_idx); 8195 BCM_IF_ERROR_RETURN(rv); 8196 8197 /* Update policy entry if moving across the slices. */ 8198 if ((1 != is_backup_entry) && (f_ent->fs->slice_number != new_slice_numb)) { 8199 /* Get policer associated with the entry. */ 8200 if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) && 8201 (f_ent->policer[0].flags & _FP_POLICER_INSTALLED)) { 8202 rv = _bcm_field_policer_get(unit, 8203 f_ent->policer[0].pid, 8204 &f_pl); 8205 BCM_IF_ERROR_RETURN(rv); 8206 } 8207 /* Get statistics entity associated with the entry. */ 8208 if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS)) && 8209 (0 == (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) && 8210 (f_ent->statistic.flags & _FP_ENTRY_STAT_INSTALLED)) { 8211 rv = _bcm_field_stat_get(unit, 8212 f_ent->statistic.sid, 8213 &f_st); 8214 BCM_IF_ERROR_RETURN(rv); 8215 } 8216 if (fg->flags & (_FP_GROUP_SPAN_SINGLE_SLICE | 8217 _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 8218 /* 8219 * For _FP_GROUP_INTRASLICE_DOUBLEWIDE, *even* if it is 8220 * _FP_GROUP_SPAN_DOUBLE_SLICE, we do this. 8221 * This is because in intraslice double-wide, the PRI 8222 * slice has tcam_slice_sz/2 entries, and same number 8223 * of counter/meter pairs. 8224 * Thus, counter/meter will always be allocated in the 8225 * PRI slice. 8226 */ 8227 if (NULL != f_st) { 8228 /* 8229 * Set the index of the counter for entry in new slice 8230 * The new index has already been calculated in 8231 * _field_entry_move 8232 */ 8233 8234 if (stage_id == _BCM_FIELD_STAGE_EGRESS ) { 8235 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0], 8236 PID_COUNTER_INDEXf, f_st->hw_index); 8237 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0], 8238 PID_COUNTER_MODEf, f_st->hw_mode); 8239 } else if (stage_id == _BCM_FIELD_STAGE_LOOKUP ) { 8240 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0], 8241 VINTF_CTR_IDXf, f_st->hw_index); 8242 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0], 8243 USE_VINTF_CTR_IDXf, f_st->hw_mode); 8244 } else { 8245 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0], 8246 COUNTER_INDEXf, f_st->hw_index); 8247 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0], 8248 COUNTER_MODEf, f_st->hw_mode); 8249 } 8250 } 8251 if (NULL != f_pl) { 8252 /* 8253 * Set the index of the meter for entry in new slice 8254 * The new index has already been calculated in 8255 * _field_entry_move 8256 */ 8257 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0], 8258 METER_INDEX_EVENf, f_pl->hw_index); 8259 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0], 8260 METER_INDEX_ODDf, f_pl->hw_index); 8261 } 8262 } else { 8263 if (NULL != f_st) { 8264 _bcm_field_fb_counter_adjust_wide_mode(unit, policy_mem, 8265 f_st, f_ent, 8266 f_ent + 1, 8267 new_slice_numb, 8268 p_buf[unit][0], 8269 p_buf[unit][1]); 8270 } 8271 if (NULL != f_pl) { 8272 _bcm_field_fb_meter_adjust_wide_mode(unit, policy_mem, 8273 f_pl, f_ent, f_ent + 1, 8274 p_buf[unit][0], 8275 p_buf[unit][1]); 8276 } 8277 } 8278 } 8279 8280 /* 8281 * Write entry to the destination 8282 * ORDER is important 8283 */ 8284 for (idx = parts_count - 1; idx >= 0; idx--) { 8285 8286 /* Write duplicate policy entry to new tcam index. */ 8287 rv = soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx_new[idx], 8288 p_buf[unit][idx]); 8289 BCM_IF_ERROR_RETURN(rv); 8290 #ifdef BCM_TRIDENT_SUPPORT 8291 if ((SOC_IS_TD_TT(unit)) && (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 8292 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) 8293 && (0x1 & idx)) { 8294 rv = WRITE_FP_GM_FIELDSm(unit, MEM_BLOCK_ALL, 8295 tcam_idx_new[idx], &fp_gm_fields[idx]); 8296 BCM_IF_ERROR_RETURN(rv); 8297 } else { 8298 rv = READ_FP_GLOBAL_MASK_TCAM_Xm(unit, MEM_BLOCK_ANY, 8299 tcam_idx_old[idx], &fp_global_mask_x[idx]); 8300 BCM_IF_ERROR_RETURN(rv); 8301 rv = READ_FP_GLOBAL_MASK_TCAM_Ym(unit, MEM_BLOCK_ANY, 8302 tcam_idx_old[idx], &fp_global_mask_y[idx]); 8303 BCM_IF_ERROR_RETURN(rv); 8304 8305 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAM_Xm, &fp_global_mask_x[idx], 8306 IPBMf, &pbmp_x); 8307 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAM_Ym, &fp_global_mask_y[idx], 8308 IPBMf, &pbmp_y); 8309 BCM_PBMP_OR(pbmp_x, pbmp_y); 8310 8311 soc_mem_pbmp_field_set(unit, 8312 FP_GLOBAL_MASK_TCAMm, 8313 &fp_global_mask[idx], 8314 IPBMf, 8315 &pbmp_x 8316 ); 8317 8318 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAM_Xm, &fp_global_mask_x[idx], 8319 IPBM_MASKf, &pbmp_x); 8320 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAM_Ym, &fp_global_mask_y[idx], 8321 IPBM_MASKf, &pbmp_y); 8322 BCM_PBMP_OR(pbmp_x, pbmp_y); 8323 8324 soc_mem_pbmp_field_set(unit, 8325 FP_GLOBAL_MASK_TCAMm, 8326 &fp_global_mask[idx], 8327 IPBM_MASKf, 8328 &pbmp_x 8329 ); 8330 8331 8332 rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL, 8333 tcam_idx_new[idx], &fp_global_mask[idx]); 8334 BCM_IF_ERROR_RETURN(rv); 8335 } 8336 } else 8337 #endif 8338 #if defined (BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 8339 if ((SOC_IS_KATANAX(unit) 8340 || SOC_IS_TRIUMPH3(unit)) 8341 && (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 8342 rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL, 8343 tcam_idx_new[idx], &ipbm_entry[idx]); 8344 BCM_IF_ERROR_RETURN(rv); 8345 } else 8346 #endif /* BCM_KATANA_SUPPORT */ 8347 #ifdef BCM_TRIUMPH_SUPPORT 8348 { 8349 if ((SOC_IS_TR_VL(unit)) && 8350 (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 8351 rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL, 8352 tcam_idx_new[idx], &ipbm_entry[idx]); 8353 BCM_IF_ERROR_RETURN(rv); 8354 } 8355 } 8356 #endif /* BCM_TRIUMPH_SUPPORT */ 8357 8358 #ifdef BCM_SCORPION_SUPPORT 8359 /* 8360 * Writing IPBMf value into FP_TCAMm sets IPBMf in FP_TCAM_Xm 8361 * and FP_TCAM_Ym but clears IPBM_MASKf in FP_TCAM_Ym unexpectedly. 8362 * Similarly setting IPBM_MASKf in FP_TCAMm sets IPBM_MASKf in 8363 * FP_TCAM_Xm and FP_TCAM_Ym but clears IPBMf in FP_TCAM_Ym unexpectedly. 8364 * On scorpion family, read and write entries only from FP_TCAM_Xm and 8365 * FP_TCAM_Ym. Avoid Read/Write into FP_TCAMm while moving entries. 8366 * Read is also not good on FP_TCAMm, as Read operation returns values 8367 * from FP_TCAM_Xm only. 8368 */ 8369 if ((SOC_IS_SC_CQ(unit)) && (stage_id == _BCM_FIELD_STAGE_INGRESS)) { 8370 rv = soc_mem_read(unit, FP_TCAM_Xm, MEM_BLOCK_ANY, 8371 tcam_idx_old[idx], e_buf[unit]); 8372 BCM_IF_ERROR_RETURN(rv); 8373 8374 rv = soc_mem_write(unit, FP_TCAM_Xm, MEM_BLOCK_ALL, 8375 tcam_idx_new[idx], e_buf[unit]); 8376 BCM_IF_ERROR_RETURN(rv); 8377 8378 rv = soc_mem_read(unit, FP_TCAM_Ym, MEM_BLOCK_ANY, 8379 tcam_idx_old[idx], e_buf[unit]); 8380 BCM_IF_ERROR_RETURN(rv); 8381 8382 rv = soc_mem_write(unit, FP_TCAM_Ym, MEM_BLOCK_ALL, 8383 tcam_idx_new[idx], e_buf[unit]); 8384 BCM_IF_ERROR_RETURN(rv); 8385 8386 } else 8387 #endif /* BCM_SCORPION_SUPPORT */ 8388 { 8389 /* Read tcam entry from current tcam index. */ 8390 rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY, 8391 tcam_idx_old[idx], e_buf[unit]); 8392 BCM_IF_ERROR_RETURN(rv); 8393 8394 /* Write duplicate tcam entry to new tcam index. */ 8395 rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, 8396 tcam_idx_new[idx], e_buf[unit]); 8397 BCM_IF_ERROR_RETURN(rv); 8398 } 8399 } 8400 8401 8402 8403 /* 8404 * fp_entry_move is invoked even for backup entry create 8405 * to copy TCAM and FP_POLICY_TABLE tables. In this case 8406 * TCAM and FP_POLICY_TABLEs should not be erased for 8407 * original entry. 8408 */ 8409 if (1 != is_backup_entry) { 8410 /* 8411 * Clear old location 8412 * ORDER is important 8413 */ 8414 for (idx = 0; idx < parts_count; idx++) { 8415 rv = _field_fb_tcam_policy_clear(unit, NULL, stage_id, tcam_idx_old[idx]); 8416 BCM_IF_ERROR_RETURN(rv); 8417 } 8418 } 8419 return (BCM_E_NONE); 8420 } 8421 8422 /* 8423 * Function: 8424 * _field_fb_stat_action_set 8425 * 8426 * Purpose: 8427 * Get counter portion of Policy Table. 8428 * 8429 * Parameters: 8430 * unit - (IN)BCM device number. 8431 * f_ent - (IN)Software entry structure to get tcam info from. 8432 * mem - (IN)Policy table memory. 8433 * buf - (IN/OUT)Hardware policy entry 8434 * 8435 * Returns: 8436 * BCM_E_XXX 8437 */ 8438 STATIC int 8439 _field_fb_stat_action_set(int unit, _field_entry_t *f_ent, 8440 soc_mem_t mem, uint32 *buf) 8441 { 8442 _field_stat_t *f_st; /* Field policer descriptor. */ 8443 int mode; /* Counter hw mode. */ 8444 int idx; /* Counter index. */ 8445 8446 /* Input parameter check. */ 8447 if ((NULL == f_ent) || (NULL == buf)) { 8448 return (BCM_E_PARAM); 8449 } 8450 if (NULL == f_ent->group) { 8451 return (BCM_E_PARAM); 8452 } 8453 8454 #if defined(BCM_FIREBOLT2_SUPPORT) 8455 /* VFP doesn't have counters. */ 8456 if ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id)) { 8457 return (BCM_E_NONE); 8458 } 8459 #endif /* BCM_FIREBOLT2_SUPPORT */ 8460 8461 8462 /* Disable counting if counter was not attached to the entry. */ 8463 if ((0 == (f_ent->statistic.flags & _FP_ENTRY_STAT_INSTALLED)) || 8464 ((f_ent->flags & _FP_ENTRY_PRIMARY) && 8465 (f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE))) { 8466 idx = 0; 8467 mode = 0; 8468 } else { 8469 /* Get statistics entity description structure. */ 8470 BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent->statistic.sid, &f_st)); 8471 idx = f_st->hw_index; 8472 mode = f_st->hw_mode; 8473 /* Adjust counter hw mode for COUNTER_MODE_YES_NO/NO_YES */ 8474 if (f_ent->statistic.flags & _FP_ENTRY_STAT_USE_ODD) { 8475 mode++; 8476 } 8477 } 8478 8479 #if defined(BCM_FIREBOLT2_SUPPORT) 8480 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 8481 PolicySet(unit, mem, buf, PID_INCR_COUNTERf, (mode) ? 1 : 0); 8482 PolicySet(unit, mem, buf, PID_COUNTER_INDEXf, idx); 8483 } else 8484 #endif /* BCM_FIREBOLT2_SUPPORT */ 8485 { 8486 PolicySet(unit, mem, buf, COUNTER_INDEXf, idx); 8487 PolicySet(unit, mem, buf, COUNTER_MODEf, mode); 8488 } 8489 return (BCM_E_NONE); 8490 } 8491 8492 /* 8493 * Function: 8494 * _field_fb_tcam_policy_reinstall 8495 * 8496 * Purpose: 8497 * Write entry into the chip's memory. 8498 * 8499 * Parameters: 8500 * unit - BCM Unit 8501 * f_ent - Physical entry structure to be installed 8502 * tcam_idx - location in TCAM 8503 * 8504 * Returns: 8505 * BCM_E_XXX On TCAM read/write errors 8506 * BCM_E_NONE 8507 * 8508 * Note: 8509 * Unit lock should be held by calling function. 8510 */ 8511 STATIC int 8512 _field_fb_tcam_policy_reinstall(int unit, _field_entry_t *f_ent, int tcam_idx) 8513 { 8514 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to fill Policy & TCAM entry.*/ 8515 soc_mem_t tcam_mem; /* tcAM memory id. */ 8516 soc_mem_t policy_mem; /* Policy table memory id . */ 8517 _field_action_t *fa; /* Actions iterator. */ 8518 8519 8520 /* Input parameters check. */ 8521 if (NULL == f_ent) { 8522 return (BCM_E_PARAM); 8523 } 8524 8525 if (NULL == f_ent->fs) { 8526 return (BCM_E_PARAM); 8527 } 8528 8529 BCM_IF_ERROR_RETURN 8530 (_field_fb_tcam_policy_mem_get(unit, f_ent->fs->stage_id, 8531 &tcam_mem, &policy_mem)); 8532 8533 if ((tcam_idx < soc_mem_index_min(unit, tcam_mem)) || 8534 (tcam_idx > soc_mem_index_max(unit, tcam_mem))) { 8535 return (BCM_E_PARAM); 8536 } 8537 8538 /* Reset buffer. */ 8539 sal_memset(e, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 8540 8541 /* Extract the policy info from the entry structure. */ 8542 for (fa = f_ent->actions; 8543 ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) { 8544 BCM_IF_ERROR_RETURN( 8545 _field_fb_action_get(unit, policy_mem, f_ent, tcam_idx, fa, e)); 8546 } 8547 8548 /* Handle color dependence/independence */ 8549 if (soc_mem_field_valid(unit, policy_mem, GREEN_TO_PIDf)) { 8550 soc_mem_field32_set(unit, policy_mem, e, GREEN_TO_PIDf, 8551 (f_ent->flags & _FP_ENTRY_COLOR_INDEPENDENT) ? 1 : 0); 8552 } 8553 8554 /* Install meter */ 8555 BCM_IF_ERROR_RETURN(_bcm_field_fb_meter_action_set(unit, f_ent, 8556 policy_mem, e)); 8557 8558 /* Install counter */ 8559 BCM_IF_ERROR_RETURN(_field_fb_stat_action_set(unit, f_ent, policy_mem, e)); 8560 8561 /* Write policy entry. */ 8562 SOC_IF_ERROR_RETURN 8563 (soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx, e)); 8564 8565 return BCM_E_NONE; 8566 } 8567 8568 /* 8569 * Function: 8570 * _field_fb_tcam_policy_install 8571 * 8572 * Purpose: 8573 * Write entry into the chip's memory. 8574 * 8575 * Parameters: 8576 * unit - BCM Unit 8577 * f_ent - Physical entry structure to be installed 8578 * tcam_idx - location in TCAM 8579 * 8580 * Returns: 8581 * BCM_E_XXX On TCAM read/write errors 8582 * BCM_E_NONE 8583 * 8584 * Note: 8585 * Unit lock should be held by calling function. 8586 */ 8587 STATIC int 8588 _field_fb_tcam_policy_install(int unit, _field_entry_t *f_ent, int tcam_idx) 8589 { 8590 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to fill Policy & TCAM entry.*/ 8591 soc_mem_t tcam_mem; /* tcAM memory id. */ 8592 soc_mem_t policy_mem; /* Policy table memory id . */ 8593 _field_action_t *fa; /* Actions iterator. */ 8594 8595 8596 /* Input parameters check. */ 8597 if (NULL == f_ent) { 8598 return (BCM_E_PARAM); 8599 } 8600 8601 if (NULL == f_ent->fs) { 8602 return (BCM_E_PARAM); 8603 } 8604 8605 BCM_IF_ERROR_RETURN 8606 (_field_fb_tcam_policy_mem_get(unit, f_ent->fs->stage_id, 8607 &tcam_mem, &policy_mem)); 8608 8609 if ((tcam_idx < soc_mem_index_min(unit, tcam_mem)) || 8610 (tcam_idx > soc_mem_index_max(unit, tcam_mem))) { 8611 return (BCM_E_PARAM); 8612 } 8613 8614 /* Reset buffer. */ 8615 sal_memset(e, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 8616 8617 /* Extract the policy info from the entry structure. */ 8618 for (fa = f_ent->actions; 8619 ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) { 8620 BCM_IF_ERROR_RETURN( 8621 _field_fb_action_get(unit, policy_mem, f_ent, tcam_idx, fa, e)); 8622 } 8623 8624 /* Handle color dependence/independence */ 8625 if (soc_mem_field_valid(unit, policy_mem, GREEN_TO_PIDf)) { 8626 soc_mem_field32_set(unit, policy_mem, e, GREEN_TO_PIDf, 8627 (f_ent->flags & _FP_ENTRY_COLOR_INDEPENDENT) ? 1 : 0); 8628 } 8629 8630 /* Install meter */ 8631 BCM_IF_ERROR_RETURN(_bcm_field_fb_meter_action_set(unit, f_ent, 8632 policy_mem, e)); 8633 8634 /* Install counter */ 8635 BCM_IF_ERROR_RETURN(_field_fb_stat_action_set(unit, f_ent, policy_mem, e)); 8636 8637 /* Write policy entry. */ 8638 SOC_IF_ERROR_RETURN 8639 (soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx, e)); 8640 8641 /* Reset buffer. */ 8642 sal_memset(e, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 8643 8644 /* Extract the qualifier info from the entry structure. */ 8645 BCM_IF_ERROR_RETURN( 8646 _field_fb_tcam_get(unit, f_ent, tcam_mem, e)); 8647 8648 /* Write tcam entry. */ 8649 SOC_IF_ERROR_RETURN 8650 (soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, tcam_idx, e)); 8651 8652 return BCM_E_NONE; 8653 } 8654 8655 /* 8656 * Function: 8657 * _field_fb_tcam_get 8658 * 8659 * Purpose: 8660 * Write entry into the chip's memory. 8661 * 8662 * Parameters: 8663 * unit - (IN)BCM device number. 8664 * f_ent - (IN)Entry structure to get tcam info from. 8665 * mem - (IN)Tcam memory. 8666 * buf - (OUT) TCAM hardware entry 8667 * 8668 * Returns: 8669 * BCM_E_NONE - Success 8670 * 8671 * Note: 8672 * Unit lock should be held by calling function. 8673 */ 8674 STATIC int 8675 _field_fb_tcam_get(int unit, _field_entry_t *f_ent, 8676 soc_mem_t mem, uint32 *buf) 8677 { 8678 _field_tcam_t *tcam; 8679 _field_group_t *fg; 8680 uint8 ent_part; 8681 int test_var; 8682 8683 if ((NULL == f_ent) || (NULL == buf)) { 8684 return (BCM_E_PARAM); 8685 } 8686 8687 tcam = &f_ent->tcam; 8688 fg = f_ent->group; 8689 8690 if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 8691 soc_mem_field32_set(unit, mem, buf, VALIDf, 8692 (fg->flags & _FP_GROUP_LOOKUP_ENABLED) ? 3 : 2); 8693 if (f_ent->flags & _FP_ENTRY_SECOND_HALF) { 8694 /* Intra-slice double wide key */ 8695 #ifdef BCM_FIREBOLT2_SUPPORT 8696 if (SOC_IS_FIREBOLT2(unit)) { 8697 soc_mem_field_set(unit, mem, buf, DATAf, tcam->key); 8698 soc_mem_field_set(unit, mem, buf, DATA_MASKf, tcam->mask); 8699 } 8700 #endif /* BCM_FIREBOLT2_SUPPORT */ 8701 } else { 8702 /* Single wide key */ 8703 soc_mem_field_set(unit, mem, buf, KEYf, tcam->key); 8704 soc_mem_field_set(unit, mem, buf, MASKf, tcam->mask); 8705 8706 /* 8707 * Notes: 8708 * 1. SOURCE_PORT_NUMBER is same as F4.0 8709 * 2. DROP is part of F4.1 8710 * 3. PORT_FIELD_SEL_INDEX is same as F4.2 (not implemented 8711 * 2006.01.18) 8712 */ 8713 if ((BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPort)) && 8714 (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_PORT_NUMBERf))) { 8715 soc_mem_field32_set(unit, mem, buf, SOURCE_PORT_NUMBERf, 8716 tcam->f4); 8717 soc_mem_field32_set(unit, mem, buf, SOURCE_PORT_NUMBER_MASKf, 8718 tcam->f4_mask); 8719 } else if (SOC_MEM_FIELD_VALID(unit, mem, F4f)) { 8720 soc_mem_field32_set(unit, mem, buf, F4f, tcam->f4); 8721 soc_mem_field32_set(unit, mem, buf, F4_MASKf, tcam->f4_mask); 8722 } 8723 8724 /* 8725 * Check if IPBM_SEL needs to be set 8726 * Will be set if fpf1.0 is selected 8727 * First find out the part of the group, entry resides in 8728 * Then check the corresponding sel_codes 8729 */ 8730 BCM_IF_ERROR_RETURN 8731 (_bcm_field_entry_flags_to_tcam_part (unit, f_ent->flags, 8732 fg, 8733 &ent_part)); 8734 test_var = (fg->sel_codes[ent_part].fpf1 == 0) ? 1 : 0; 8735 8736 soc_mem_field32_set(unit, mem, buf, IPBM_SELf, test_var); 8737 soc_mem_field32_set(unit, mem, buf, IPBM_SEL_MASKf, test_var); 8738 8739 /* 8740 * Qualify on HiGig packets. 8741 */ 8742 test_var = 8743 (BCM_FIELD_QSET_TEST(fg->qset, 8744 bcmFieldQualifyHiGig) && tcam->higig) ? 1 : 0; 8745 soc_mem_field32_set(unit, mem, buf, PKT_TYPEf, test_var); 8746 8747 test_var = 8748 (BCM_FIELD_QSET_TEST(fg->qset, 8749 bcmFieldQualifyHiGig) && tcam->higig_mask) ? 1 : 0; 8750 soc_mem_field32_set(unit, mem, buf, PKT_TYPE_MASKf, test_var); 8751 #ifdef BCM_FIREBOLT2_SUPPORT 8752 /* 8753 * Qualify on Drop. 8754 */ 8755 if (SOC_IS_FIREBOLT2(unit)) { 8756 test_var = 8757 (BCM_FIELD_QSET_TEST(fg->qset, 8758 bcmFieldQualifyDrop) && tcam->drop) ? 1 : 0; 8759 8760 soc_mem_field32_set(unit, mem, buf, DROPf, test_var); 8761 8762 test_var = 8763 (BCM_FIELD_QSET_TEST(fg->qset, 8764 bcmFieldQualifyDrop) && tcam->drop_mask) ? 1 : 0; 8765 soc_mem_field32_set(unit, mem, buf, DROP_MASKf, test_var); 8766 } 8767 #endif 8768 } 8769 #ifdef BCM_FIREBOLT2_SUPPORT 8770 } else if (soc_feature(unit, soc_feature_field_multi_stage)) { 8771 soc_field_t mask_field; 8772 if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) { 8773 mask_field = MASKf; 8774 } else if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id){ 8775 mask_field = KEY_MASKf; 8776 } else { 8777 return (BCM_E_PARAM); 8778 } 8779 soc_mem_field_set(unit, mem, buf, KEYf, tcam->key); 8780 soc_mem_field_set(unit, mem, buf, mask_field, tcam->mask); 8781 soc_mem_field32_set(unit, mem, buf, VALIDf, 8782 (fg->flags & _FP_GROUP_LOOKUP_ENABLED) ? 3 : 2); 8783 #endif 8784 } else { 8785 return (BCM_E_INTERNAL); 8786 } 8787 8788 return (BCM_E_NONE); 8789 } 8790 8791 /* 8792 * Function: 8793 * _bcm_field_fb_meter_action_set 8794 * 8795 * Purpose: 8796 * Get metering portion of Policy Table. 8797 * 8798 * Parameters: 8799 * unit - (IN)BCM device number. 8800 * f_ent - (IN)Software entry structure to get tcam info from. 8801 * mem - (IN)Policy table memory. 8802 * buf - (IN/OUT)Hardware policy entry 8803 * 8804 * Returns: 8805 * BCM_E_NONE - Success 8806 * 8807 * Note: 8808 * Unit lock should be held by calling function. 8809 */ 8810 int 8811 _bcm_field_fb_meter_action_set(int unit, _field_entry_t *f_ent, 8812 soc_mem_t mem, uint32 *buf) 8813 { 8814 _field_policer_t *f_pl; /* Field policer descriptor. */ 8815 uint32 meter_pair_mode; /* Meter usage. */ 8816 8817 /* Input parameter check. */ 8818 if ((NULL == f_ent) || (NULL == buf)) { 8819 return (BCM_E_PARAM); 8820 } 8821 if (NULL == f_ent->group) { 8822 return (BCM_E_PARAM); 8823 } 8824 8825 #if defined(BCM_FIREBOLT2_SUPPORT) 8826 /* VFP doesn't have meters. */ 8827 if ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id)) { 8828 return (BCM_E_NONE); 8829 } 8830 #endif /* BCM_FIREBOLT2_SUPPORT */ 8831 8832 8833 if ((0 == (f_ent->policer[0].flags & _FP_POLICER_INSTALLED)) || 8834 ((f_ent->flags & _FP_ENTRY_PRIMARY) && 8835 (f_ent->flags & _FP_ENTRY_POLICER_IN_SECONDARY_SLICE))) { 8836 /* If no meter, install default meter pair mode. 8837 * Default meter pair mode doesn't need to burn a real meter. 8838 */ 8839 soc_mem_field32_set(unit, mem, buf, METER_PAIR_MODEf, 0); 8840 soc_mem_field32_set(unit, mem, buf, METER_TEST_EVENf, 1); 8841 8842 #if defined(BCM_FIREBOLT2_SUPPORT) 8843 if ((SOC_IS_FIREBOLT2(unit) && 8844 _BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) { 8845 soc_mem_field32_set(unit, mem, buf, METER_PAIR_MODEf, 4); 8846 } 8847 #endif /* BCM_FIREBOLT2_SUPPORT */ 8848 return (BCM_E_NONE); 8849 } 8850 8851 /* Get policer description structure. */ 8852 BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent->policer[0].pid, 8853 &f_pl)); 8854 /* Get the even and odd indexes from the entry. The even and odd 8855 * meter indices are the same. 8856 */ 8857 soc_mem_field32_set(unit, mem, buf, METER_INDEX_EVENf, 8858 f_pl->hw_index); 8859 soc_mem_field32_set(unit, mem, buf, METER_INDEX_ODDf, 8860 f_pl->hw_index); 8861 8862 8863 /* Get hw encoding for meter mode. */ 8864 BCM_IF_ERROR_RETURN 8865 (_bcm_field_meter_pair_mode_get(unit, f_pl, &meter_pair_mode)); 8866 8867 /* 8868 * Flow mode is the only one that cares about the test and update bits. 8869 * Even = BCM_FIELD_METER_PEAK 8870 * Odd = BCM_FIELD_METER_COMMITTED 8871 */ 8872 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 8873 soc_mem_field32_set(unit, mem, buf, METER_TEST_ODDf, 0); 8874 soc_mem_field32_set(unit, mem, buf, METER_TEST_EVENf, 1); 8875 soc_mem_field32_set(unit, mem, buf, METER_UPDATE_ODDf, 0); 8876 soc_mem_field32_set(unit, mem, buf, METER_UPDATE_EVENf, 1); 8877 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) { 8878 soc_mem_field32_set(unit, mem, buf, METER_TEST_ODDf, 1); 8879 soc_mem_field32_set(unit, mem, buf, METER_TEST_EVENf, 0); 8880 soc_mem_field32_set(unit, mem, buf, METER_UPDATE_ODDf, 1); 8881 soc_mem_field32_set(unit, mem, buf, METER_UPDATE_EVENf, 0); 8882 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) { 8883 if (SOC_MEM_FIELD_VALID(unit, mem, METER_PAIR_MODE_MODIFIERf)) { 8884 soc_mem_field32_set(unit, mem, buf, METER_PAIR_MODE_MODIFIERf, 1); 8885 } 8886 soc_mem_field32_set(unit, mem, buf, METER_TEST_EVENf, 1); 8887 } 8888 8889 soc_mem_field32_set(unit, mem, buf, METER_PAIR_MODEf, meter_pair_mode); 8890 return (BCM_E_NONE); 8891 } 8892 8893 /* 8894 * Function: 8895 * _field_fb_ingress_selcodes_install 8896 * 8897 * Purpose: 8898 * Writes the field select codes (ie. FPFx). 8899 * 8900 * Parameters: 8901 * unit - (IN) BCM device number. 8902 * fg - (IN) Field group. 8903 * slice_numb - (IN) Slice number group installed in. 8904 * pbmp - (IN) Group active port bit map. 8905 * selcode_index - (IN) Index into select codes array. 8906 * fs - slice that needs its select codes written 8907 * 8908 * Returns: 8909 * BCM_E_XXX 8910 */ 8911 STATIC int 8912 _field_fb_ingress_selcodes_install(int unit, _field_group_t *fg, 8913 uint8 slice_numb, bcm_pbmp_t pbmp, 8914 int selcode_index) 8915 { 8916 bcm_port_t port; 8917 fp_port_field_sel_entry_t pfs_entry; 8918 ifp_port_field_sel_entry_t ipfs_entry; 8919 soc_field_t f1_field, f2_field, f3_field; 8920 uint32 fpf4; 8921 int i_write_flag; 8922 _field_sel_t *sel = NULL; 8923 int rv; 8924 #if defined(BCM_FIREBOLT2_SUPPORT) 8925 soc_field_t dw_fld; 8926 bcm_pbmp_t all_pbmp; 8927 #endif /* BCM_FIREBOLT2_SUPPORT */ 8928 8929 /* Input parameters check. */ 8930 if (NULL == fg) { 8931 return (BCM_E_PARAM); 8932 } 8933 8934 sel = &fg->sel_codes[selcode_index]; 8935 8936 if (slice_numb >= 16) { 8937 return (BCM_E_PARAM); 8938 } 8939 8940 8941 if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 8942 ((selcode_index == 1) || (selcode_index == 3))) { 8943 #if defined(BCM_FIREBOLT2_SUPPORT) 8944 if (SOC_IS_FIREBOLT2(unit)) { 8945 8946 /* Write appropriate values in FP_DOUBLE_WIDE_F4_SELECTr and */ 8947 /* FP_PORT_FIELD_SELm for an intra-slice double wide group */ 8948 /* V4 key => F4 should be FP_PORT_FIELD_SEL_INDEX: sel->fpf2 = 0 */ 8949 /* V6 key => F4 should be TCP flags: sel->fpf2 = 1*/ 8950 dw_fld = _fb_ing_f4_reg[slice_numb]; 8951 if ((sel->fpf2 != _FP_SELCODE_DONT_CARE) && 8952 SOC_REG_FIELD_VALID(unit, FP_DOUBLE_WIDE_F4_SELECTr, dw_fld)) { 8953 rv = soc_reg_field32_modify(unit, FP_DOUBLE_WIDE_F4_SELECTr, 8954 REG_PORT_ANY, dw_fld, sel->fpf2); 8955 BCM_IF_ERROR_RETURN(rv); 8956 } 8957 8958 /* Read device port configuration. */ 8959 rv = _bcm_field_valid_pbmp_get(unit, &all_pbmp); 8960 BCM_IF_ERROR_RETURN(rv); 8961 8962 dw_fld = _fb2_ifp_double_wide_key[slice_numb]; 8963 if ((sel->fpf2 != _FP_SELCODE_DONT_CARE) && 8964 SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, dw_fld)) { 8965 /* Do the same thing for each entry in FP_PORT_FIELD_SEL table */ 8966 BCM_PBMP_ITER(all_pbmp, port) { 8967 rv = READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ANY, port, &pfs_entry); 8968 BCM_IF_ERROR_RETURN(rv); 8969 8970 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 8971 dw_fld, sel->fpf2); 8972 rv = WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port, &pfs_entry); 8973 BCM_IF_ERROR_RETURN(rv); 8974 8975 if (_FIELD_NEED_I_WRITE(unit, port, IFP_PORT_FIELD_SELm)) { 8976 rv = READ_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ANY, 8977 port, &pfs_entry); 8978 BCM_IF_ERROR_RETURN(rv); 8979 8980 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 8981 dw_fld, sel->fpf2); 8982 8983 rv = WRITE_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 8984 port, &pfs_entry); 8985 BCM_IF_ERROR_RETURN(rv); 8986 } 8987 } 8988 } 8989 } 8990 #endif /* BCM_FIREBOLT2_SUPPORT */ 8991 } else { 8992 8993 /* Determine which 3 fields will be modified */ 8994 f1_field = _fb_field_tbl[slice_numb][0]; 8995 f2_field = _fb_field_tbl[slice_numb][1]; 8996 f3_field = _fb_field_tbl[slice_numb][2]; 8997 8998 /* Iterate over all ports */ 8999 PBMP_ITER(pbmp, port) { 9000 i_write_flag = _FIELD_NEED_I_WRITE(unit, port, 9001 IFP_PORT_FIELD_SELm); 9002 /* Read Port's current entry in FP_PORT_FIELD_SEL table */ 9003 rv = READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 9004 port, &pfs_entry); 9005 BCM_IF_ERROR_RETURN(rv); 9006 if (i_write_flag) { 9007 rv = READ_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 9008 port, &ipfs_entry); 9009 BCM_IF_ERROR_RETURN(rv); 9010 } 9011 9012 /* modify 0-3 fields depending on state of SELCODE_INVALID */ 9013 if (sel->fpf1 != _FP_SELCODE_DONT_CARE) { 9014 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 9015 f1_field, sel->fpf1); 9016 if (i_write_flag) { 9017 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9018 f1_field, sel->fpf1); 9019 } 9020 } 9021 9022 if (sel->fpf2 != _FP_SELCODE_DONT_CARE) { 9023 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 9024 f2_field, 9025 sel->fpf2); 9026 if (i_write_flag) { 9027 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9028 f2_field, 9029 sel->fpf2); 9030 } 9031 } 9032 9033 if (sel->fpf3 != _FP_SELCODE_DONT_CARE) { 9034 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 9035 f3_field, 9036 sel->fpf3); 9037 if (i_write_flag) { 9038 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9039 f3_field, 9040 sel->fpf3); 9041 } 9042 } 9043 9044 /* Write each port's new entry */ 9045 rv = WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 9046 port, &pfs_entry); 9047 BCM_IF_ERROR_RETURN(rv); 9048 if (i_write_flag) { 9049 rv = WRITE_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 9050 port, &ipfs_entry); 9051 BCM_IF_ERROR_RETURN(rv); 9052 } 9053 } 9054 9055 /* If the device supports it, write the F4 select code. */ 9056 if (soc_feature(unit, soc_feature_field_qual_drop)) { 9057 fpf4 = (sel->fpf4 == _FP_SELCODE_DONT_CARE) ? 0 : sel->fpf4; 9058 rv = soc_reg_field32_modify(unit, FP_F4_SELECTr, REG_PORT_ANY, 9059 _fb_ing_f4_reg[slice_numb], fpf4); 9060 BCM_IF_ERROR_RETURN(rv); 9061 } 9062 9063 /* Set inner vlan overlay config. */ 9064 if (_FP_SELCODE_DONT_CARE != fg->sel_codes[0].inner_vlan_overlay) { 9065 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 9066 if (SOC_REG_FIELD_VALID(unit, ING_MISC_CONFIG2r, 9067 FP_INNER_VLAN_OVERLAY_ENABLEf)) { 9068 rv = soc_reg_field32_modify(unit, ING_MISC_CONFIG2r, REG_PORT_ANY, 9069 FP_INNER_VLAN_OVERLAY_ENABLEf, 9070 fg->sel_codes[0].inner_vlan_overlay); 9071 BCM_IF_ERROR_RETURN(rv); 9072 } else 9073 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 9074 if (SOC_REG_FIELD_VALID(unit, ING_CONFIGr, MAC_BLOCK_INDEX_OVERLAYf)) { 9075 rv = soc_reg_field32_modify(unit, ING_CONFIGr, REG_PORT_ANY, 9076 MAC_BLOCK_INDEX_OVERLAYf, 9077 fg->sel_codes[0].inner_vlan_overlay); 9078 BCM_IF_ERROR_RETURN(rv); 9079 } 9080 } 9081 } 9082 return (BCM_E_NONE); 9083 } 9084 9085 /* 9086 * Function: 9087 * _field_fb_ingress_slice_clear 9088 * 9089 * Purpose: 9090 * Resets the IFP field slice configuration. 9091 * 9092 * Parameters: 9093 * unit - (IN) BCM device number. 9094 * slice_numb - (IN) Field slice number. 9095 * 9096 * Returns: 9097 * BCM_E_XXX 9098 */ 9099 STATIC int 9100 _field_fb_ingress_slice_clear(int unit, uint8 slice_numb) 9101 { 9102 bcm_port_t port; 9103 fp_port_field_sel_entry_t pfs_entry; 9104 ifp_port_field_sel_entry_t ipfs_entry; 9105 bcm_pbmp_t all_pbmp; 9106 soc_field_t f1_field, f2_field, f3_field; 9107 int i_write_flag; 9108 int rv; 9109 #if defined (BCM_FIREBOLT2_SUPPORT) 9110 soc_field_t dw_fld; 9111 #endif /* BCM_FIREBOLT2_SUPPORT */ 9112 9113 f1_field = _fb_field_tbl[slice_numb][0]; 9114 f2_field = _fb_field_tbl[slice_numb][1]; 9115 f3_field = _fb_field_tbl[slice_numb][2]; 9116 9117 /* Read device port configuration. */ 9118 BCM_PBMP_CLEAR(all_pbmp); 9119 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 9120 9121 /* Iterate over all ports */ 9122 BCM_PBMP_ITER(all_pbmp, port) { 9123 i_write_flag = _FIELD_NEED_I_WRITE(unit, port, IFP_PORT_FIELD_SELm); 9124 #if defined (BCM_RAVEN_SUPPORT) 9125 /* IFP_PORT_FIELD_SEL table will be automatically updated by the 9126 hardware when FP_FIELD_PORT_SEL table is configured for hg ports. 9127 So configuring IFP_PORT_FIELD_SEL table again from software is 9128 not required. However, when cpu port is configured in higig mode 9129 (PORT_TAB.HIGIG_PACKET) software has to update this table */ 9130 if (SOC_IS_RAVEN(unit) && !IS_CPU_PORT(unit, port)) { 9131 i_write_flag = 0; 9132 } 9133 #endif 9134 /* Read Port's current entry in FP_PORT_FIELD_SEL table */ 9135 rv = READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 9136 port, &pfs_entry); 9137 BCM_IF_ERROR_RETURN(rv); 9138 9139 if (i_write_flag) { 9140 rv = READ_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 9141 port, &ipfs_entry); 9142 BCM_IF_ERROR_RETURN(rv); 9143 } 9144 9145 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 9146 f1_field, 0); 9147 if (i_write_flag) { 9148 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9149 f1_field, 0); 9150 } 9151 9152 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 9153 f2_field, 0); 9154 if (i_write_flag) { 9155 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9156 f2_field, 0); 9157 } 9158 9159 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 9160 f3_field, 0); 9161 if (i_write_flag) { 9162 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9163 f3_field, 0); 9164 } 9165 9166 #if defined (BCM_FIREBOLT2_SUPPORT) 9167 dw_fld = _fb2_ifp_double_wide_key[slice_numb]; 9168 if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, dw_fld)) { 9169 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 9170 dw_fld, 0); 9171 if (i_write_flag) { 9172 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9173 dw_fld, 0); 9174 } 9175 } 9176 9177 dw_fld = _fb2_slice_wide_mode_field[slice_numb]; 9178 if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, dw_fld)) { 9179 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, dw_fld, 0); 9180 if (i_write_flag) { 9181 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9182 dw_fld, 0); 9183 } 9184 } 9185 9186 dw_fld = _fb2_slice_pairing_field[slice_numb / 2]; 9187 if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, dw_fld)) { 9188 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, dw_fld, 0); 9189 if (i_write_flag) { 9190 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 9191 dw_fld, 0); 9192 } 9193 } 9194 #endif /* BCM_FIREBOLT2_SUPPORT */ 9195 9196 rv = WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port, 9197 &pfs_entry); 9198 BCM_IF_ERROR_RETURN(rv); 9199 9200 if (i_write_flag) { 9201 rv = WRITE_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port, 9202 &ipfs_entry); 9203 BCM_IF_ERROR_RETURN(rv); 9204 } 9205 } 9206 9207 if (SOC_REG_FIELD_VALID(unit, FP_SLICE_CONFIGr, 9208 _fb_ing_slice_mode_field[slice_numb])) { 9209 rv = soc_reg_field32_modify(unit, FP_SLICE_CONFIGr, REG_PORT_ANY, 9210 _fb_ing_slice_mode_field[slice_numb], 0); 9211 BCM_IF_ERROR_RETURN(rv); 9212 } 9213 9214 /* If the device supports it, write the F4 select code. */ 9215 if (SOC_REG_FIELD_VALID(unit, FP_F4_SELECTr, _fb_ing_f4_reg[slice_numb])) { 9216 rv = soc_reg_field32_modify(unit, FP_F4_SELECTr, REG_PORT_ANY, 9217 _fb_ing_f4_reg[slice_numb],0); 9218 BCM_IF_ERROR_RETURN(rv); 9219 } 9220 #if defined (BCM_FIREBOLT2_SUPPORT) 9221 dw_fld = _fb_ing_f4_reg[slice_numb]; 9222 if (SOC_REG_FIELD_VALID(unit, FP_DOUBLE_WIDE_F4_SELECTr, dw_fld)) { 9223 rv = soc_reg_field32_modify(unit, FP_DOUBLE_WIDE_F4_SELECTr, 9224 REG_PORT_ANY, dw_fld, 0); 9225 BCM_IF_ERROR_RETURN(rv); 9226 } 9227 #endif /* BCM_FIREBOLT2_SUPPORT */ 9228 return (BCM_E_NONE); 9229 } 9230 9231 #if defined(BCM_FIREBOLT2_SUPPORT) 9232 9233 /* 9234 * Function: 9235 * _field_fb_lookup_selcodes_install 9236 * 9237 * Purpose: 9238 * Writes the field select codes (ie. FPFx). 9239 * for VFP (_BCM_FIELD_STAGE_LOOKUP) lookup stage. 9240 * 9241 * Parameters: 9242 * unit - BCM device number 9243 * fs - slice that needs its select codes written 9244 * 9245 * Returns: 9246 * BCM_E_INTERNAL - On read/write errors 9247 * BCM_E_NONE - Success 9248 * 9249 * Note: 9250 * Unit lock should be held by calling function. 9251 */ 9252 STATIC int 9253 _field_fb_lookup_selcodes_install(int unit, _field_group_t *fg, 9254 uint8 slice_numb, int selcode_index) 9255 { 9256 uint32 reg_val; 9257 _field_sel_t *sel; 9258 9259 sel = &fg->sel_codes[selcode_index]; 9260 9261 9262 SOC_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, ®_val)); 9263 if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 9264 (selcode_index % 2)) { 9265 if (sel->fpf2 != _FP_SELCODE_DONT_CARE) { 9266 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9267 DOUBLE_WIDE_KEY_SELECTf, sel->fpf2); 9268 } 9269 } else { 9270 /* FPF1 is fixed in Firebolt2 VFP */ 9271 if (sel->fpf2 != _FP_SELCODE_DONT_CARE) { 9272 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9273 _vfp_field_tbl[slice_numb][0], sel->fpf2); 9274 } 9275 if (sel->fpf3 != _FP_SELCODE_DONT_CARE) { 9276 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9277 _vfp_field_tbl[slice_numb][1], sel->fpf3); 9278 } 9279 } 9280 SOC_IF_ERROR_RETURN(WRITE_VFP_KEY_CONTROLr(unit, reg_val)); 9281 return (BCM_E_NONE); 9282 } 9283 9284 /* 9285 * Function: 9286 * _field_fb_lookup_slice_clear 9287 * 9288 * Purpose: 9289 * Reset slice configuraton on group deletion event. 9290 * 9291 * Parameters: 9292 * unit - BCM device number 9293 * fs - slice that needs its select codes written 9294 * 9295 * Returns: 9296 * BCM_E_NONE - Success 9297 * 9298 * Note: 9299 * Unit lock should be held by calling function. 9300 */ 9301 STATIC int 9302 _field_fb_lookup_slice_clear(int unit, uint8 slice_numb) 9303 { 9304 uint32 reg_val; 9305 9306 SOC_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, ®_val)); 9307 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9308 DOUBLE_WIDE_KEY_SELECTf, 0); 9309 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9310 _vfp_field_tbl[slice_numb][0], 0); 9311 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9312 _vfp_field_tbl[slice_numb][1], 0); 9313 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9314 _vfp_slice_pairing_field[slice_numb / 2], 0); 9315 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9316 _vfp_slice_wide_mode_field[slice_numb], 0); 9317 SOC_IF_ERROR_RETURN(WRITE_VFP_KEY_CONTROLr(unit, reg_val)); 9318 return (BCM_E_NONE); 9319 } 9320 #endif /* BCM_FIREBOLT2_SUPPORT */ 9321 9322 /* 9323 * Function: 9324 * _field_fb_ingress_mode_set 9325 * 9326 * Purpose: 9327 * Helper function to _bcm_field_fb_mode_install that sets the mode of a 9328 * slice in a register value that is to be used for FP_SLICE_CONFIGr. 9329 * 9330 * Parameters: 9331 * unit - (IN) BCM device number. 9332 * slice_numb - (IN) Slice number to set mode for. 9333 * fg - (IN) Installed group structure. 9334 * flags - (IN) New group/slice mode. 9335 * 9336 * Returns: 9337 * BCM_E_XXX 9338 */ 9339 int 9340 _field_fb_ingress_mode_set(int unit, uint8 slice_numb, 9341 _field_group_t *fg, uint8 flags) 9342 { 9343 int mode; 9344 #if defined(BCM_FIREBOLT2_SUPPORT) 9345 bcm_pbmp_t all_pbmp; 9346 int paired, dbl_wide; 9347 soc_field_t fld; 9348 #endif /* BCM_FIREBOLT2_SUPPORT */ 9349 9350 if (slice_numb >= COUNTOF(_fb_ing_slice_mode_field)) { 9351 return BCM_E_PARAM; 9352 } 9353 9354 9355 #if defined(BCM_FIREBOLT2_SUPPORT) 9356 if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) { 9357 int port; 9358 fp_port_field_sel_entry_t pfs_entry; 9359 9360 /* Read device port configuration. */ 9361 BCM_PBMP_CLEAR(all_pbmp); 9362 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp)); 9363 9364 /* Do the same thing for each port (index) in FP_PORT_FIELD_SEL table */ 9365 BCM_PBMP_ITER(all_pbmp, port) { 9366 9367 BCM_IF_ERROR_RETURN 9368 (READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ANY, port, &pfs_entry)); 9369 9370 fld = _fb2_slice_wide_mode_field[slice_numb]; 9371 if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, fld)) { 9372 dbl_wide = (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ? 1 : 0; 9373 9374 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, fld, 9375 dbl_wide); 9376 } 9377 9378 paired = (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ? 1 : 0; 9379 fld = _fb2_slice_pairing_field[slice_numb / 2]; 9380 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, fld, paired); 9381 9382 BCM_IF_ERROR_RETURN 9383 (WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port, &pfs_entry)); 9384 9385 if (_FIELD_NEED_I_WRITE(unit, port, IFP_PORT_FIELD_SELm)) { 9386 9387 BCM_IF_ERROR_RETURN 9388 (READ_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ANY, port, &pfs_entry)); 9389 9390 fld = _fb2_slice_wide_mode_field[slice_numb]; 9391 if (SOC_MEM_FIELD_VALID(unit, IFP_PORT_FIELD_SELm, fld)) { 9392 dbl_wide = (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ? 1 : 0; 9393 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, fld, 9394 dbl_wide); 9395 } 9396 9397 paired = (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ? 1 : 0; 9398 fld = _fb2_slice_pairing_field[slice_numb / 2]; 9399 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, fld, 9400 paired); 9401 9402 BCM_IF_ERROR_RETURN 9403 (WRITE_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port, 9404 &pfs_entry)); 9405 } 9406 9407 } 9408 } else 9409 #endif /* BCM_FIREBOLT2_SUPPORT */ 9410 { 9411 if (flags & _FP_GROUP_SPAN_SINGLE_SLICE) { 9412 mode = 0; 9413 } else if (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 9414 mode = 1; 9415 } else if (flags & _FP_GROUP_SPAN_TRIPLE_SLICE) { 9416 mode = 2; 9417 } else { 9418 return (BCM_E_PARAM); 9419 } 9420 9421 BCM_IF_ERROR_RETURN 9422 (soc_reg_field32_modify(unit, FP_SLICE_CONFIGr, REG_PORT_ANY, 9423 _fb_ing_slice_mode_field[slice_numb], 9424 mode)); 9425 } 9426 return (BCM_E_NONE); 9427 } 9428 9429 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 9430 /* 9431 * Function: 9432 * _bcm_field_fb_lookup_mode_set 9433 * 9434 * Purpose: 9435 * Helper function to _bcm_field_fb_mode_install that sets the mode of a 9436 * slice in a register value that is to be used for VFP_KEY_CONTROLr. 9437 * 9438 * Parameters: 9439 * unit - (IN) BCM device number. 9440 * slice_numb - (IN) Slice number to set mode for. 9441 * fg - (IN) Filed group structure. 9442 * flags - (IN) New group/slice mode. 9443 * 9444 * Returns: 9445 * BCM_E_XXX 9446 */ 9447 int 9448 _bcm_field_fb_lookup_mode_set(int unit, uint8 slice_numb, 9449 _field_group_t *fg, uint8 flags) 9450 { 9451 int paired,dbl_wide; 9452 uint32 reg_val; 9453 if (slice_numb >= COUNTOF(_vfp_slice_wide_mode_field)) { 9454 return (BCM_E_PARAM); 9455 } 9456 SOC_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, ®_val)); 9457 9458 paired = (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ? 1 : 0; 9459 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9460 _vfp_slice_pairing_field[slice_numb / 2], paired); 9461 9462 dbl_wide = (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ? 1 : 0; 9463 soc_reg_field_set(unit, VFP_KEY_CONTROLr, ®_val, 9464 _vfp_slice_wide_mode_field[slice_numb], dbl_wide); 9465 9466 SOC_IF_ERROR_RETURN(WRITE_VFP_KEY_CONTROLr(unit, reg_val)); 9467 return (BCM_E_NONE); 9468 } 9469 9470 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT*/ 9471 9472 #if defined(BCM_FIREBOLT2_SUPPORT) 9473 /* 9474 * Function: 9475 * _field_fb_egress_mode_set 9476 * 9477 * Purpose: 9478 * Helper function to _bcm_field_fb_mode_install that sets the mode of a 9479 * slice in a register value that is to be used for FP_SLICE_CONFIGr. 9480 * 9481 * Parameters: 9482 * unit - (IN) BCM device number. 9483 * slice_numb - (IN) Slice number to set mode for. 9484 * fg - (IN) Installed group structure. 9485 * flags - (IN) New group/slice mode. 9486 * 9487 * Returns: 9488 * BCM_E_XXX 9489 */ 9490 STATIC int 9491 _field_fb_egress_mode_set(int unit, uint8 slice_numb, 9492 _field_group_t *fg, uint8 flags) 9493 { 9494 int mode_val; 9495 9496 /* Input parameters check. */ 9497 if ((NULL == fg) || (slice_numb >= COUNTOF(_efp_slice_mode))) { 9498 return (BCM_E_PARAM); 9499 } 9500 9501 if (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) { 9502 BCM_IF_ERROR_RETURN 9503 (soc_reg_field32_modify(unit, EFP_SLICE_CONTROLr, REG_PORT_ANY, 9504 _efp_slice_mode[slice_numb], 9505 _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE)); 9506 } else { 9507 mode_val = (3 == fg->sel_codes[0].fpf3) ? 9508 _BCM_FIELD_EGRESS_SLICE_MODE_SINGLE_L2 : 9509 _BCM_FIELD_EGRESS_SLICE_MODE_SINGLE_L3; 9510 BCM_IF_ERROR_RETURN 9511 (soc_reg_field32_modify(unit, EFP_SLICE_CONTROLr, REG_PORT_ANY, 9512 _efp_slice_mode[slice_numb], mode_val)); 9513 } 9514 return (BCM_E_NONE); 9515 } 9516 /* 9517 * Function: 9518 * _field_fb_egress_slice_clear 9519 * 9520 * Purpose: 9521 * Reset slice configuraton on group deletion event. 9522 * 9523 * Parameters: 9524 * unit - (IN) BCM device number. 9525 * slice_numb - (IN) Slice number to set mode for. 9526 * 9527 * Returns: 9528 * BCM_E_XXX 9529 */ 9530 STATIC int 9531 _field_fb_egress_slice_clear(int unit, uint8 slice_numb) 9532 { 9533 int rv; 9534 9535 /* Input parameters check. */ 9536 if (slice_numb >= COUNTOF(_efp_slice_mode)) { 9537 return (BCM_E_PARAM); 9538 } 9539 9540 rv = soc_reg_field32_modify(unit, EFP_SLICE_CONTROLr, REG_PORT_ANY, 9541 _efp_slice_mode[slice_numb], 0); 9542 return rv; 9543 } 9544 #endif /* BCM_FIREBOLT2_SUPPORT */ 9545 9546 9547 /* 9548 * Function: 9549 * _bcm_field_fb_mode_set 9550 * 9551 * Purpose: 9552 * Auxiliary routine used to set group pairing mode. 9553 * Parameters: 9554 * unit - (IN) BCM device number. 9555 * slice_numb - (IN) Slice number to set mode for. 9556 * fg - (IN) Installed group structure. 9557 * flags - (IN) New group/slice mode. 9558 * 9559 * Returns: 9560 * BCM_E_XXX 9561 */ 9562 int 9563 _bcm_field_fb_mode_set(int unit, uint8 slice_numb, _field_group_t *fg, uint8 flags) 9564 { 9565 int rv; /* Operation return status. */ 9566 9567 /* Input parameter check. */ 9568 if (NULL == fg) { 9569 return (BCM_E_PARAM); 9570 } 9571 9572 if (!soc_feature(unit, soc_feature_field_wide)) { 9573 if (flags & _FP_GROUP_SPAN_SINGLE_SLICE) { 9574 return (BCM_E_NONE); 9575 } 9576 return (BCM_E_UNAVAIL); 9577 } 9578 9579 switch (fg->stage_id) { 9580 case _BCM_FIELD_STAGE_INGRESS: 9581 rv = _field_fb_ingress_mode_set(unit, slice_numb, fg, flags); 9582 break; 9583 #if defined(BCM_FIREBOLT2_SUPPORT) 9584 case _BCM_FIELD_STAGE_LOOKUP: 9585 rv = _bcm_field_fb_lookup_mode_set(unit, slice_numb, fg, flags); 9586 break; 9587 case _BCM_FIELD_STAGE_EGRESS: 9588 rv = _field_fb_egress_mode_set(unit, slice_numb, fg, flags); 9589 break; 9590 #endif /* BCM_FIREBOLT2_SUPPORT */ 9591 default: 9592 rv = BCM_E_PARAM; 9593 } 9594 return (rv); 9595 } 9596 9597 9598 /* 9599 * Function: 9600 * _field_selcodes_install 9601 * 9602 * Purpose: 9603 * Writes the field select codes (ie. FPFx). 9604 * 9605 * Parameters: 9606 * unit - BCM device number 9607 * fs - slice that needs its select codes written 9608 * 9609 * Returns: 9610 * BCM_E_INTERNAL - On read/write errors 9611 * BCM_E_NONE - Success 9612 * 9613 * Note: 9614 * Unit lock should be held by calling function. 9615 */ 9616 STATIC int 9617 _field_selcodes_install(int unit, _field_group_t *fg, 9618 uint8 slice_numb, bcm_pbmp_t pbmp, 9619 int selcode_index) 9620 { 9621 int rv; /* Operation return status. */ 9622 9623 /* Input parameters check. */ 9624 if (NULL == fg) { 9625 return (BCM_E_PARAM); 9626 } 9627 9628 9629 /* Set slice mode. Single/Double/Triple, Intraslice */ 9630 rv = _bcm_field_fb_mode_set(unit, slice_numb, fg, fg->flags); 9631 BCM_IF_ERROR_RETURN(rv); 9632 9633 switch (fg->stage_id) { 9634 case _BCM_FIELD_STAGE_INGRESS: 9635 rv = _field_fb_ingress_selcodes_install(unit, fg, slice_numb, 9636 pbmp, selcode_index); 9637 break; 9638 #if defined(BCM_FIREBOLT2_SUPPORT) 9639 case _BCM_FIELD_STAGE_LOOKUP: 9640 rv = _field_fb_lookup_selcodes_install(unit, fg, slice_numb, 9641 selcode_index); 9642 break; 9643 case _BCM_FIELD_STAGE_EGRESS: 9644 rv = (BCM_E_NONE); 9645 break; 9646 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 9647 default: 9648 rv = (BCM_E_PARAM); 9649 } 9650 return (rv); 9651 } 9652 9653 /* 9654 * Function: 9655 * _bcm_field_fb_group_install 9656 * 9657 * Purpose: 9658 * Writes the Group's mode and field select codes into hardware. This 9659 * should be called both at group creation time and any time the select 9660 * codes change (i.e. bcm_field_group_set calls). 9661 * 9662 * Parameters: 9663 * unit - BCM device number 9664 * fg - group to install 9665 * 9666 * Returns: 9667 * BCM_E_INTERNAL - On read/write errors 9668 * BCM_E_NONE - Success 9669 * 9670 * Note: 9671 * Unit lock should be held by calling function. 9672 */ 9673 int 9674 _bcm_field_fb_group_install(int unit, _field_group_t *fg) 9675 { 9676 _field_slice_t *fs; /* Slice pointer. */ 9677 uint8 slice_number; /* Slices iterator. */ 9678 int parts_count; /* Number of entry parts. */ 9679 int idx; /* Iteration index. */ 9680 int rv; /* Operation return status. */ 9681 9682 if (NULL == fg) { 9683 return (BCM_E_PARAM); 9684 } 9685 9686 /* Get number of entry parts. */ 9687 rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, 9688 fg->flags, &parts_count); 9689 BCM_IF_ERROR_RETURN(rv); 9690 9691 for (idx = 0; idx < parts_count; idx++) { 9692 9693 /* Get slice id for entry part */ 9694 rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg, 9695 &slice_number); 9696 BCM_IF_ERROR_RETURN(rv); 9697 9698 /* Get slice pointer. */ 9699 fs = fg->slices + slice_number; 9700 9701 #if defined(BCM_TOMAHAWK_SUPPORT) 9702 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) { 9703 rv = _bcm_field_th_selcodes_install (unit, fg, fs->slice_number, 9704 fg->pbmp, idx); 9705 } else 9706 #endif 9707 #if defined(BCM_TRX_SUPPORT) 9708 if (SOC_IS_TRX(unit) && !(SOC_IS_HURRICANE2(unit) || 9709 SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 9710 SOC_IS_GREYHOUND2(unit))) { 9711 rv = _bcm_field_trx_selcodes_install (unit, fg, fs->slice_number, 9712 fg->pbmp, idx); 9713 } else 9714 #if defined(BCM_HURRICANE2_SUPPORT) 9715 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 9716 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 9717 rv = _bcm_field_hu2_selcodes_install (unit, fg, fs->slice_number, 9718 fg->pbmp, idx); 9719 } else 9720 #endif /* BCM_HURRICANE2_SUPPORT */ 9721 #endif /* BCM_TRX_SUPPORT */ 9722 { 9723 rv = _field_selcodes_install(unit, fg, fs->slice_number, fg->pbmp, idx); 9724 } 9725 BCM_IF_ERROR_RETURN(rv); 9726 } 9727 return (BCM_E_NONE); 9728 } 9729 9730 /* 9731 * Function: 9732 * _bcm_field_fb_slice_clear 9733 * 9734 * Purpose: 9735 * Clear slice configuration on group removal 9736 * 9737 * Parameters: 9738 * unit - BCM device number 9739 * fg - Field group slice belongs to 9740 * fs - Field slice structure. 9741 * 9742 * Returns: 9743 * BCM_E_XXX 9744 */ 9745 int 9746 _bcm_field_fb_slice_clear(int unit, _field_group_t *fg, _field_slice_t *fs) 9747 { 9748 int rv; 9749 9750 switch (fs->stage_id) { 9751 case _BCM_FIELD_STAGE_INGRESS: 9752 rv = _field_fb_ingress_slice_clear(unit, fs->slice_number); 9753 break; 9754 #if defined(BCM_FIREBOLT2_SUPPORT) 9755 case _BCM_FIELD_STAGE_LOOKUP: 9756 rv = _field_fb_lookup_slice_clear(unit, fs->slice_number); 9757 break; 9758 case _BCM_FIELD_STAGE_EGRESS: 9759 rv = _field_fb_egress_slice_clear(unit, fs->slice_number); 9760 break; 9761 #endif /* BCM_FIREBOLT2_SUPPORT */ 9762 default: 9763 rv = BCM_E_INTERNAL; 9764 } 9765 9766 return (rv); 9767 } 9768 9769 /* 9770 * Function: 9771 * _bcm_field_fb_entry_remove 9772 * Purpose: 9773 * Remove a previously installed physical entry. 9774 * Parameters: 9775 * unit - BCM device number 9776 * f_ent - Physical entry data 9777 * Returns: 9778 * BCM_E_XXX 9779 * BCM_E_NONE 9780 * Notes: 9781 * FP unit lock should be held by calling function. 9782 */ 9783 int 9784 _bcm_field_fb_entry_remove(int unit, _field_entry_t *f_ent, int tcam_idx) 9785 { 9786 #ifdef BCM_KATANA_SUPPORT 9787 uint32 param0 = 0, param1 = 0, in_flags = 0; 9788 int queue_id = 0; 9789 ing_queue_map_entry_t ing_queue_entry; 9790 int referenceCount = 0; 9791 _field_action_t *fa = NULL; 9792 #endif 9793 #ifdef BCM_KATANA2_SUPPORT 9794 int rv = BCM_E_NONE; 9795 #endif 9796 9797 if (NULL == f_ent) { 9798 return (BCM_E_PARAM); 9799 } 9800 9801 if (NULL == f_ent->fs) { 9802 return (BCM_E_PARAM); 9803 } 9804 9805 9806 BCM_IF_ERROR_RETURN 9807 (_field_fb_tcam_policy_clear(unit, f_ent, f_ent->fs->stage_id, tcam_idx)); 9808 9809 #if defined(BCM_KATANA_SUPPORT) 9810 if (SOC_IS_KATANAX(unit)) { 9811 if ((f_ent->fs->stage_id == _BCM_FIELD_STAGE_INGRESS) && 9812 (!(f_ent->flags & _FP_ENTRY_DIRTY)) ) { 9813 9814 for (fa = f_ent->actions; fa != NULL; fa = fa->next) { 9815 if (fa->action == bcmFieldActionFabricQueue) { 9816 sal_memset(&ing_queue_entry, 0, 9817 sizeof(ing_queue_map_entry_t)); 9818 param0 = fa->param[0]; 9819 param1 = fa->param[1]; 9820 /* For Katana if param1 BCM_FABRIC_QUEUE_xxx 9821 * flags are set then param0 is 9822 * ucast/ucast_subscriber group cosq gport */ 9823 if ((param1 & BCM_FABRIC_QUEUE_DEST_OFFSET) || 9824 (param1 & BCM_FABRIC_QUEUE_CUSTOMER)) { 9825 if(BCM_GPORT_IS_UCAST_QUEUE_GROUP(param0) || 9826 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(param0) || 9827 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(param0)) { 9828 #if defined(BCM_KATANA2_SUPPORT) 9829 if (SOC_IS_KATANA2(unit)) { 9830 queue_id = -1; 9831 rv = _bcm_kt2_cosq_index_resolve( 9832 unit, param0, 0, 9833 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 9834 NULL, &queue_id, NULL); 9835 if (BCM_FAILURE(rv) && 9836 (rv != BCM_E_NOT_FOUND)) { 9837 return rv; 9838 } 9839 } else 9840 #endif 9841 { 9842 if (SOC_IS_KATANA(unit)) { 9843 BCM_IF_ERROR_RETURN( 9844 _bcm_kt_cosq_index_resolve( 9845 unit, param0, 0, 9846 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 9847 NULL, &queue_id, NULL)); 9848 } 9849 } 9850 } else { 9851 queue_id = param0 & 0xffff; 9852 } 9853 in_flags = param1; 9854 } else { 9855 queue_id = param0 & 0xffff; 9856 in_flags = param0; 9857 } 9858 9859 if (in_flags & BCM_FABRIC_QUEUE_DEST_OFFSET) { 9860 if (queue_id != -1) { 9861 BCM_IF_ERROR_RETURN( 9862 _bcm_field_fabricQueue_action_node_delete (unit, 9863 queue_id, param1, &referenceCount)); 9864 if(referenceCount == 0) { 9865 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, 9866 ING_QUEUE_MAPm, 9867 queue_id, &ing_queue_entry)); 9868 } 9869 fa->flags = fa->flags | _FP_ACTION_DIRTY; 9870 } 9871 } 9872 } 9873 } 9874 } 9875 } 9876 #endif 9877 f_ent->flags |= _FP_ENTRY_DIRTY; /* Mark entry as not installed */ 9878 9879 return (BCM_E_NONE); 9880 } 9881 #ifdef INCLUDE_L3 9882 /* 9883 * Function: 9884 * _bcm_field_policy_set_l3_info 9885 * Purpose: 9886 * Install l3 forwarding policy entry. 9887 * Parameters: 9888 * unit - (IN) BCM device number 9889 * mem - (IN) Policy table memory. 9890 * value - (IN) Egress object id or combined next hop information. 9891 * buf - (IN/OUT) Hw entry buffer to write. 9892 * Returns: 9893 * BCM_E_XXX 9894 */ 9895 9896 int 9897 _bcm_field_policy_set_l3_info(int unit, soc_mem_t mem, int value, uint32 *buf) 9898 { 9899 uint32 flags; /* L3 forwarding flags */ 9900 int nh_ecmp_id; /* Next hop/Ecmp group id. */ 9901 int max_ecmp_paths; /* Maximum number of ecmp paths. */ 9902 int retval; /* Operation return value. */ 9903 9904 /* Resove next hop /ecmp group id. */ 9905 retval = _bcm_field_policy_set_l3_nh_resolve(unit, value, 9906 &flags, &nh_ecmp_id); 9907 BCM_IF_ERROR_RETURN(retval); 9908 9909 if (flags & BCM_L3_MULTIPATH) { 9910 PolicySet(unit, mem, buf, ECMPf, 1); 9911 PolicySet(unit, mem, buf, ECMP_PTRf, nh_ecmp_id); 9912 BCM_IF_ERROR_RETURN(bcm_xgs3_max_ecmp_get(unit, &max_ecmp_paths)); 9913 PolicySet(unit, mem, buf, ECMP_COUNTf, max_ecmp_paths - 1); 9914 } else { 9915 PolicySet(unit, mem, buf, ECMPf, 0); 9916 PolicySet(unit, mem, buf, NEXT_HOP_INDEXf, nh_ecmp_id); 9917 } 9918 return (BCM_E_NONE); 9919 } 9920 #endif /* INCLUDE_L3 */ 9921 /* 9922 * Function: 9923 * _field_fb_action_copy_to_cpu 9924 * Purpose: 9925 * Install copy to cpu action in policy table. 9926 * Parameters: 9927 * unit - (IN) BCM device number 9928 * mem - (IN) Policy table memory 9929 * f_ent - (IN) Field entry structure to get policy info from 9930 * fa - (IN Field action 9931 * buf - (OUT) Field Policy table entry 9932 * Returns: 9933 * BCM_E_XXX 9934 */ 9935 STATIC int 9936 _field_fb_action_copy_to_cpu(int unit, soc_mem_t mem, _field_entry_t *f_ent, 9937 _field_action_t *fa, uint32 *buf) 9938 { 9939 if (NULL == f_ent || NULL == fa || NULL == buf) { 9940 return (BCM_E_PARAM); 9941 } 9942 9943 if ((fa->param[0] != 0) && (fa->param[1] >= (1 << 8))) { 9944 LOG_ERROR(BSL_LS_BCM_FP, 9945 (BSL_META_U(unit, 9946 "FP(unit %d) Error: param1=%d out of range for CopyToCpu.\n"), 9947 unit, fa->param[1])); 9948 return (BCM_E_PARAM); 9949 } 9950 9951 switch (fa->action) { 9952 case bcmFieldActionCopyToCpu: 9953 #if defined(BCM_FIREBOLT2_SUPPORT) 9954 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 9955 PolicySet(unit, mem, buf, COPY_TO_CPUf, 0x1); 9956 } else 9957 #endif /* BCM_FIREBOLT2_SUPPORT */ 9958 { 9959 PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 0x1); 9960 PolicySet(unit, mem, buf, YP_COPY_TO_CPUf, 0x1); 9961 PolicySet(unit, mem, buf, COPY_TO_CPUf, 0x1); 9962 } 9963 break; 9964 case bcmFieldActionRpCopyToCpu: 9965 PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 0x1); 9966 break; 9967 case bcmFieldActionYpCopyToCpu: 9968 PolicySet(unit, mem, buf, YP_COPY_TO_CPUf, 0x1); 9969 break; 9970 case bcmFieldActionGpCopyToCpu: 9971 PolicySet(unit, mem, buf, COPY_TO_CPUf, 0x1); 9972 break; 9973 9974 default: 9975 return (BCM_E_INTERNAL); 9976 } 9977 9978 if (fa->param[0] != 0) { 9979 if (SOC_MEM_FIELD_VALID(unit, mem, MATCHED_RULEf)) { 9980 PolicySet(unit, mem, buf, MATCHED_RULEf, fa->param[1]); 9981 } 9982 } 9983 return (BCM_E_NONE); 9984 } 9985 9986 9987 /* 9988 * Function: 9989 * _field_fb_action_get 9990 * Purpose: 9991 * Install an action into the hardware tables. 9992 * Parameters: 9993 * unit - BCM device number 9994 * mem - Policy table memory. 9995 * tcam_idx - index into TCAM 9996 * fa - field action 9997 * buf - (OUT) Field TCAM plus Policy table entry 9998 * Returns: 9999 * BCM_E_NONE 10000 * BCM_E_PARAM - Action parameter out-of-range or unrecognized action. 10001 * Notes: 10002 * This is a simple read/modify/write pattern. 10003 * FP unit lock should be held by calling function. 10004 */ 10005 STATIC int 10006 _field_fb_action_get(int unit, soc_mem_t mem, _field_entry_t *f_ent, 10007 int tcam_idx, _field_action_t *fa, uint32 *buf) 10008 { 10009 #if defined (BCM_FIREBOLT2_SUPPORT) 10010 uint32 mode; 10011 #endif /* BCM_FIREBOLT2_SUPPORT */ 10012 uint32 redir_field = 0; 10013 10014 if (NULL == f_ent || NULL == fa || NULL == buf) { 10015 return (BCM_E_PARAM); 10016 } 10017 10018 LOG_DEBUG(BSL_LS_BCM_FP, 10019 (BSL_META_U(unit, 10020 "FP(unit %d) vverb: BEGIN _field_fb_action_get(eid=%d, tcam_idx=0x%x, "), 10021 unit, f_ent->eid, tcam_idx)); 10022 #ifdef BROADCOM_DEBUG 10023 LOG_DEBUG(BSL_LS_BCM_FP, 10024 (BSL_META_U(unit, 10025 "action={%s,%d,%d})\n"), 10026 _field_fb_action_name(fa->action), 10027 fa->param[0], fa->param[1])); 10028 #endif 10029 10030 switch (fa->action) { 10031 case bcmFieldActionCosQNew: 10032 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 1); 10033 PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]); 10034 break; 10035 case bcmFieldActionCosQCpuNew: 10036 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 2); 10037 PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]); 10038 break; 10039 case bcmFieldActionPrioPktAndIntCopy: 10040 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 4); 10041 break; 10042 case bcmFieldActionPrioPktAndIntNew: 10043 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 5); 10044 PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]); 10045 break; 10046 case bcmFieldActionPrioPktAndIntTos: 10047 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 6); 10048 break; 10049 case bcmFieldActionPrioPktAndIntCancel: 10050 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 7); 10051 break; 10052 case bcmFieldActionPrioPktCopy: 10053 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 8); 10054 break; 10055 case bcmFieldActionPrioPktNew: 10056 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 9); 10057 PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]); 10058 break; 10059 case bcmFieldActionPrioPktTos: 10060 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 10); 10061 break; 10062 case bcmFieldActionPrioPktCancel: 10063 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 11); 10064 break; 10065 case bcmFieldActionPrioIntCopy: 10066 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 12); 10067 break; 10068 case bcmFieldActionPrioIntNew: 10069 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 13); 10070 PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]); 10071 break; 10072 case bcmFieldActionPrioIntTos: 10073 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 14); 10074 break; 10075 case bcmFieldActionPrioIntCancel: 10076 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 15); 10077 break; 10078 case bcmFieldActionTosNew: 10079 PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 1); 10080 PolicySet(unit, mem, buf, NEWDSCP_TOSf, fa->param[0]); 10081 break; 10082 case bcmFieldActionTosCopy: 10083 PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 2); 10084 break; 10085 case bcmFieldActionDscpNew: 10086 #if defined(BCM_FIREBOLT2_SUPPORT) 10087 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10088 PolicySet(unit, mem, buf, RP_CHANGE_DSCPf, 1); 10089 PolicySet(unit, mem, buf, YP_CHANGE_DSCPf, 1); 10090 PolicySet(unit, mem, buf, GP_CHANGE_DSCPf, 1); 10091 PolicySet(unit, mem, buf, RP_NEW_DSCPf, fa->param[0]); 10092 PolicySet(unit, mem, buf, YP_NEW_DSCPf, fa->param[0]); 10093 PolicySet(unit, mem, buf, GP_NEW_DSCPf, fa->param[0]); 10094 } else 10095 #endif /* BCM_FIREBOLT2_SUPPORT */ 10096 { 10097 PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 3); 10098 PolicySet(unit, mem, buf, NEWDSCP_TOSf, fa->param[0]); 10099 PolicySet(unit, mem, buf, RP_CHANGE_DSCPf, 1); 10100 PolicySet(unit, mem, buf, RP_DSCPf, fa->param[0]); 10101 PolicySet(unit, mem, buf, YP_CHANGE_DSCPf, 1); 10102 PolicySet(unit, mem, buf, YP_DSCPf, fa->param[0]); 10103 } 10104 break; 10105 case bcmFieldActionTosCancel: 10106 PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 4); 10107 break; 10108 case bcmFieldActionDscpCancel: 10109 PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 4); 10110 break; 10111 case bcmFieldActionCopyToCpu: 10112 case bcmFieldActionRpCopyToCpu: 10113 case bcmFieldActionYpCopyToCpu: 10114 case bcmFieldActionGpCopyToCpu: 10115 BCM_IF_ERROR_RETURN 10116 (_field_fb_action_copy_to_cpu(unit, mem, f_ent, fa, buf)); 10117 break; 10118 case bcmFieldActionGpCopyToCpuCancel: 10119 PolicySet(unit, mem, buf, COPY_TO_CPUf, 2); 10120 break; 10121 case bcmFieldActionCopyToCpuCancel: 10122 PolicySet(unit, mem, buf, COPY_TO_CPUf, 2); 10123 PolicySet(unit, mem, buf, YP_COPY_TO_CPUf, 2); 10124 PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 2); 10125 break; 10126 case bcmFieldActionSwitchToCpuCancel: 10127 PolicySet(unit, mem, buf, COPY_TO_CPUf, 3); 10128 break; 10129 case bcmFieldActionRedirect: /* param0=modid, param1=port/tgid */ 10130 PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 1); 10131 PolicySet(unit, mem, buf, REDIRECTIONf, 10132 (fa->param[0] << 6) | fa->param[1]); 10133 break; 10134 case bcmFieldActionRedirectTrunk: /* param0 = trunk ID */ 10135 if (soc_property_get(unit, spn_TRUNK_EXTEND, 1)) { 10136 redir_field = ((fa->param[0] & 0x60) << 1) | (fa->param[0] & 0x1f); 10137 } else { 10138 redir_field = fa->param[0] & 0x1f; 10139 } 10140 redir_field |= 0x20; 10141 PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 1); 10142 PolicySet(unit, mem, buf, REDIRECTIONf, redir_field); 10143 break; 10144 case bcmFieldActionRedirectCancel: 10145 PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 2); 10146 break; 10147 case bcmFieldActionRedirectPbmp: 10148 PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 3); 10149 PolicySet(unit, mem, buf, REDIRECTIONf, fa->param[0]); 10150 break; 10151 case bcmFieldActionEgressMask: 10152 PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 4); 10153 PolicySet(unit, mem, buf, REDIRECTIONf, fa->param[0]); 10154 break; 10155 case bcmFieldActionDrop: 10156 #if defined (BCM_FIREBOLT2_SUPPORT) 10157 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10158 PolicySet(unit, mem, buf, RP_DROPf, 1); 10159 PolicySet(unit, mem, buf, YP_DROPf, 1); 10160 PolicySet(unit, mem, buf, GP_DROPf, 1); 10161 } else if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 10162 PolicySet(unit, mem, buf, DROPf, 1); 10163 } else 10164 #endif /* BCM_FIREBOLT2_SUPPORT */ 10165 { 10166 PolicySet(unit, mem, buf, RP_DROPf, 1); 10167 PolicySet(unit, mem, buf, YP_DROPf, 1); 10168 PolicySet(unit, mem, buf, DROPf, 1); 10169 } 10170 break; 10171 case bcmFieldActionDropCancel: 10172 #if defined (BCM_FIREBOLT2_SUPPORT) 10173 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10174 PolicySet(unit, mem, buf, RP_DROPf, 2); 10175 PolicySet(unit, mem, buf, YP_DROPf, 2); 10176 PolicySet(unit, mem, buf, GP_DROPf, 2); 10177 } else if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 10178 PolicySet(unit, mem, buf, DROPf, 2); 10179 } else 10180 #endif /* BCM_FIREBOLT2_SUPPORT */ 10181 { 10182 PolicySet(unit, mem, buf, RP_DROPf, 2); 10183 PolicySet(unit, mem, buf, YP_DROPf, 2); 10184 PolicySet(unit, mem, buf, DROPf, 2); 10185 } 10186 break; 10187 case bcmFieldActionMirrorOverride: 10188 if (soc_feature(unit, soc_feature_field_mirror_ovr)) { 10189 PolicySet(unit, mem, buf, MIRROR_OVERRIDEf, 1); 10190 } else { 10191 return BCM_E_PARAM; 10192 } 10193 break; 10194 case bcmFieldActionMirrorIngress: /* param0=modid, param1=port/tgid */ 10195 PolicySet(unit, mem, buf, IM_MTP_INDEXf, fa->hw_index); 10196 PolicySet(unit, mem, buf, MIRRORf, 10197 PolicyGet(unit, mem, buf, MIRRORf) | 0x1); 10198 if (soc_feature(unit, soc_feature_field_mirror_pkts_ctl)) { 10199 BCM_IF_ERROR_RETURN 10200 (soc_reg_field32_modify(unit, ING_CONFIGr, REG_PORT_ANY, 10201 ENABLE_FP_FOR_MIRROR_PKTSf, 1)); 10202 } 10203 break; 10204 case bcmFieldActionMirrorEgress: /* param0=modid, param1=port/tgid */ 10205 PolicySet(unit, mem, buf, EM_MTP_INDEXf, fa->hw_index); 10206 PolicySet(unit, mem, buf, MIRRORf, 10207 PolicyGet(unit, mem, buf, MIRRORf) | 2); 10208 if (soc_feature(unit, soc_feature_field_mirror_pkts_ctl)) { 10209 BCM_IF_ERROR_RETURN 10210 (soc_reg_field32_modify(unit, ING_CONFIGr, REG_PORT_ANY, 10211 ENABLE_FP_FOR_MIRROR_PKTSf, 1)); 10212 } 10213 break; 10214 #ifdef INCLUDE_L3 10215 case bcmFieldActionL3ChangeVlan: 10216 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 1); 10217 BCM_IF_ERROR_RETURN 10218 (_bcm_field_policy_set_l3_info(unit, mem, fa->param[0], buf)); 10219 break; 10220 case bcmFieldActionL3ChangeVlanCancel: 10221 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 2); 10222 break; 10223 case bcmFieldActionL3ChangeMacDa: 10224 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 4); 10225 BCM_IF_ERROR_RETURN 10226 (_bcm_field_policy_set_l3_info(unit, mem, fa->param[0], buf)); 10227 break; 10228 case bcmFieldActionSrcMacNew: 10229 case bcmFieldActionDstMacNew: 10230 PolicySet(unit, mem, buf, ECMPf, 0); 10231 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 0x4); 10232 PolicySet(unit, mem, buf, NEXT_HOP_INDEXf, fa->hw_index); 10233 break; 10234 case bcmFieldActionL3ChangeMacDaCancel: 10235 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 5); 10236 break; 10237 case bcmFieldActionL3Switch: 10238 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 6); 10239 BCM_IF_ERROR_RETURN 10240 (_bcm_field_policy_set_l3_info(unit, mem, fa->param[0], buf)); 10241 break; 10242 case bcmFieldActionL3SwitchCancel: 10243 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 7); 10244 break; 10245 #endif /* INCLUDE_L3 */ 10246 case bcmFieldActionAddClassTag: 10247 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 3); 10248 PolicySet(unit, mem, buf, CLASSIFICATION_TAGf, fa->param[0]); 10249 break; 10250 case bcmFieldActionEcnNew: 10251 /* Ecn in tos byte will be forced to a Drop Precedence value. */ 10252 PolicySet(unit, mem, buf, ECN_CNGf, 0x1); 10253 /* coverity[MISSING_BREAK : FALSE] */ 10254 /* passthru */ 10255 case bcmFieldActionDropPrecedence: 10256 PolicySet(unit, mem, buf, RP_DROP_PRECEDENCEf, fa->param[0]); 10257 PolicySet(unit, mem, buf, YP_DROP_PRECEDENCEf, fa->param[0]); 10258 PolicySet(unit, mem, buf, DROP_PRECEDENCEf, fa->param[0]); 10259 break; 10260 case bcmFieldActionGpDropPrecedence: 10261 PolicySet(unit, mem, buf, DROP_PRECEDENCEf, fa->param[0]); 10262 break; 10263 case bcmFieldActionRpDrop: 10264 PolicySet(unit, mem, buf, RP_DROPf, 1); 10265 break; 10266 case bcmFieldActionRpDropCancel: 10267 PolicySet(unit, mem, buf, RP_DROPf, 2); 10268 break; 10269 case bcmFieldActionRpDropPrecedence: 10270 PolicySet(unit, mem, buf, RP_DROP_PRECEDENCEf, fa->param[0]); 10271 break; 10272 case bcmFieldActionRpCopyToCpuCancel: 10273 PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 2); 10274 break; 10275 case bcmFieldActionRpDscpNew: 10276 PolicySet(unit, mem, buf, RP_CHANGE_DSCPf, 1); 10277 #if defined(BCM_FIREBOLT2_SUPPORT) 10278 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10279 PolicySet(unit, mem, buf, RP_NEW_DSCPf, fa->param[0]); 10280 } else 10281 #endif /* BCM_FIREBOLT2_SUPPORT */ 10282 { 10283 PolicySet(unit, mem, buf, RP_DSCPf, fa->param[0]); 10284 } 10285 break; 10286 case bcmFieldActionYpDrop: 10287 PolicySet(unit, mem, buf, YP_DROPf, 1); 10288 break; 10289 case bcmFieldActionYpDropCancel: 10290 PolicySet(unit, mem, buf, YP_DROPf, 2); 10291 break; 10292 case bcmFieldActionYpDropPrecedence: 10293 PolicySet(unit, mem, buf, YP_DROP_PRECEDENCEf, fa->param[0]); 10294 break; 10295 case bcmFieldActionYpCopyToCpuCancel: 10296 PolicySet(unit, mem, buf, YP_COPY_TO_CPUf, 2); 10297 break; 10298 case bcmFieldActionYpDscpNew: 10299 PolicySet(unit, mem, buf, YP_CHANGE_DSCPf, 1); 10300 #if defined(BCM_FIREBOLT2_SUPPORT) 10301 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10302 PolicySet(unit, mem, buf, YP_NEW_DSCPf, fa->param[0]); 10303 } else 10304 #endif /* BCM_FIREBOLT2_SUPPORT */ 10305 { 10306 PolicySet(unit, mem, buf, YP_DSCPf, fa->param[0]); 10307 } 10308 break; 10309 case bcmFieldActionGpDrop: 10310 #if defined (BCM_FIREBOLT2_SUPPORT) 10311 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10312 PolicySet(unit, mem, buf, GP_DROPf, 1); 10313 } else 10314 #endif /* BCM_FIREBOLT2_SUPPORT */ 10315 { 10316 PolicySet(unit, mem, buf, DROPf, 1); 10317 } 10318 break; 10319 case bcmFieldActionGpDropCancel: 10320 #if defined (BCM_FIREBOLT2_SUPPORT) 10321 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10322 PolicySet(unit, mem, buf, GP_DROPf, 2); 10323 } else 10324 #endif /* BCM_FIREBOLT2_SUPPORT */ 10325 { 10326 PolicySet(unit, mem, buf, DROPf, 2); 10327 } 10328 break; 10329 case bcmFieldActionGpDscpNew: 10330 #if defined(BCM_FIREBOLT2_SUPPORT) 10331 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10332 PolicySet(unit, mem, buf, GP_CHANGE_DSCPf, 1); 10333 PolicySet(unit, mem, buf, GP_NEW_DSCPf, fa->param[0]); 10334 } else 10335 #endif /* BCM_FIREBOLT2_SUPPORT */ 10336 { 10337 PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 3); 10338 PolicySet(unit, mem, buf, NEWDSCP_TOSf, fa->param[0]); 10339 } 10340 break; 10341 #if defined(BCM_FIREBOLT2_SUPPORT) 10342 case bcmFieldActionRpOuterVlanPrioNew: 10343 PolicySet(unit, mem, buf, RP_CHANGE_DOT1Pf, 1); 10344 PolicySet(unit, mem, buf, RP_NEW_DOT1Pf, fa->param[0]); 10345 break; 10346 case bcmFieldActionYpOuterVlanPrioNew: 10347 PolicySet(unit, mem, buf, YP_CHANGE_DOT1Pf, 1); 10348 PolicySet(unit, mem, buf, YP_NEW_DOT1Pf, fa->param[0]); 10349 break; 10350 case bcmFieldActionGpOuterVlanPrioNew: 10351 PolicySet(unit, mem, buf, GP_CHANGE_DOT1Pf, 1); 10352 PolicySet(unit, mem, buf, GP_NEW_DOT1Pf, fa->param[0]); 10353 break; 10354 case bcmFieldActionClassSet: 10355 PolicySet(unit, mem, buf, USE_VFP_CLASS_IDf, 1); 10356 PolicySet(unit, mem, buf, VFP_CLASS_IDf, fa->param[0]); 10357 break; 10358 case bcmFieldActionVrfSet: 10359 PolicySet(unit, mem, buf, USE_VFP_VRF_IDf, 1); 10360 PolicySet(unit, mem, buf, VFP_VRF_IDf, fa->param[0]); 10361 break; 10362 case bcmFieldActionVlanAdd: 10363 PolicySet(unit, mem, buf, CHANGE_VLANf, 1); 10364 PolicySet(unit, mem, buf, NEW_VLANf, fa->param[0]); 10365 break; 10366 case bcmFieldActionInnerVlanNew: 10367 PolicySet(unit, mem, buf, PID_REPLACE_INNER_VIDf, 1); 10368 PolicySet(unit, mem, buf, PID_NEW_INNER_VIDf, fa->param[0]); 10369 break; 10370 case bcmFieldActionInnerVlanPrioNew: 10371 PolicySet(unit, mem, buf, PID_REPLACE_INNER_PRIf, 1); 10372 PolicySet(unit, mem, buf, PID_NEW_INNER_PRIf, fa->param[0]); 10373 break; 10374 case bcmFieldActionOuterVlanPrioNew: 10375 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 10376 PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 1); 10377 PolicySet(unit, mem, buf, NEW_PRIORITYf, fa->param[0]); 10378 } else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10379 PolicySet(unit, mem, buf, RP_CHANGE_DOT1Pf, 1); 10380 PolicySet(unit, mem, buf, RP_NEW_DOT1Pf, fa->param[0]); 10381 PolicySet(unit, mem, buf, YP_CHANGE_DOT1Pf, 1); 10382 PolicySet(unit, mem, buf, YP_NEW_DOT1Pf, fa->param[0]); 10383 PolicySet(unit, mem, buf, GP_CHANGE_DOT1Pf, 1); 10384 PolicySet(unit, mem, buf, GP_NEW_DOT1Pf, fa->param[0]); 10385 } 10386 break; 10387 case bcmFieldActionOuterTpidNew: 10388 BCM_IF_ERROR_RETURN(_bcm_field_tpid_hw_encode(unit, fa->param[0], &mode)); 10389 PolicySet(unit, mem, buf, PID_REPLACE_OUTER_TPIDf, 1); 10390 PolicySet(unit, mem, buf, PID_TPID_INDEXf, mode); 10391 break; 10392 case bcmFieldActionRpSwitchToCpuCancel: 10393 PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 0x3); 10394 break; 10395 #endif /* BCM_FIREBOLT2_SUPPORT */ 10396 case bcmFieldActionOuterVlanNew: 10397 #if defined(BCM_FIREBOLT2_SUPPORT) 10398 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 10399 PolicySet(unit, mem, buf, CHANGE_VLANf, 2); 10400 PolicySet(unit, mem, buf, NEW_VLANf, fa->param[0]); 10401 } 10402 else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10403 PolicySet(unit, mem, buf, PID_REPLACE_OUTER_VIDf, 1); 10404 PolicySet(unit, mem, buf, PID_NEW_OUTER_VIDf, fa->param[0]); 10405 } else 10406 #endif /* BCM_FIREBOLT2_SUPPORT */ 10407 { 10408 PolicySet(unit, mem, buf, ECMPf, 0); 10409 PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 0x1); 10410 PolicySet(unit, mem, buf, NEXT_HOP_INDEXf, fa->hw_index); 10411 } 10412 break; 10413 default: 10414 LOG_ERROR(BSL_LS_BCM_FP, 10415 (BSL_META_U(unit, 10416 "FP(unit %d) Error: Unknown action (%d)\n"), 10417 unit, (uint32)fa->action)); 10418 return BCM_E_PARAM; 10419 } 10420 10421 fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */ 10422 10423 LOG_DEBUG(BSL_LS_BCM_FP, 10424 (BSL_META_U(unit, 10425 "FP(unit %d) vverb: END _field_fb_action_get()\n"), 10426 unit)); 10427 return BCM_E_NONE; 10428 } 10429 10430 /* 10431 * Function: 10432 * _field_fb_action_params_check 10433 * Purpose: 10434 * Check field action parameters. 10435 * Parameters: 10436 * unit - BCM device number 10437 * f_ent - Field entry structure. 10438 * fa - field action 10439 * Returns: 10440 * BCM_E_XXX 10441 */ 10442 STATIC int 10443 _field_fb_action_params_check(int unit,_field_entry_t *f_ent, 10444 _field_action_t *fa) 10445 { 10446 uint32 redir_field = 0; /* Redirection field value.*/ 10447 #if defined(INCLUDE_L3) 10448 uint32 flags; /* L3 forwarding flags. */ 10449 int nh_ecmp_id; /* Next hop/Ecmp group id. */ 10450 #endif /* INCLUDE_L3 */ 10451 soc_mem_t mem; /* Policy table memory id. */ 10452 soc_mem_t tcam_mem; /* Tcam memory id. */ 10453 int rv; /* Operation return value. */ 10454 10455 10456 /* Input parameters check. */ 10457 if ((NULL == f_ent) || (fa == NULL)){ 10458 return (BCM_E_PARAM); 10459 } 10460 10461 rv = _field_fb_tcam_policy_mem_get(unit, f_ent->group->stage_id, 10462 &tcam_mem, &mem); 10463 BCM_IF_ERROR_RETURN(rv); 10464 10465 switch (fa->action) { 10466 case bcmFieldActionCosQNew: 10467 PolicyCheck(unit, mem, NEWPRIf, fa->param[0]); 10468 break; 10469 case bcmFieldActionCosQCpuNew: 10470 PolicyCheck(unit, mem, NEWPRIf, fa->param[0]); 10471 break; 10472 case bcmFieldActionPrioPktAndIntNew: 10473 PolicyCheck(unit, mem, NEWPRIf, fa->param[0]); 10474 break; 10475 case bcmFieldActionPrioPktNew: 10476 PolicyCheck(unit, mem, NEWPRIf, fa->param[0]); 10477 break; 10478 case bcmFieldActionPrioIntNew: 10479 PolicyCheck(unit, mem, NEWPRIf, fa->param[0]); 10480 break; 10481 case bcmFieldActionTosNew: 10482 PolicyCheck(unit, mem, NEWDSCP_TOSf, fa->param[0]); 10483 break; 10484 case bcmFieldActionDscpNew: 10485 #if defined(BCM_FIREBOLT2_SUPPORT) 10486 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10487 PolicyCheck(unit, mem, RP_NEW_DSCPf, fa->param[0]); 10488 PolicyCheck(unit, mem, YP_NEW_DSCPf, fa->param[0]); 10489 PolicyCheck(unit, mem, GP_NEW_DSCPf, fa->param[0]); 10490 } else 10491 #endif /* BCM_FIREBOLT2_SUPPORT */ 10492 { 10493 PolicyCheck(unit, mem, NEWDSCP_TOSf, fa->param[0]); 10494 PolicyCheck(unit, mem, RP_DSCPf, fa->param[0]); 10495 PolicyCheck(unit, mem, YP_DSCPf, fa->param[0]); 10496 } 10497 break; 10498 case bcmFieldActionCopyToCpu: 10499 case bcmFieldActionRpCopyToCpu: 10500 case bcmFieldActionYpCopyToCpu: 10501 case bcmFieldActionGpCopyToCpu: 10502 if (fa->param[0]) { 10503 PolicyCheck(unit, mem, MATCHED_RULEf, fa->param[1]); 10504 } 10505 break; 10506 case bcmFieldActionRedirect: /* param0 = modid, param1 = port/tgid */ 10507 rv = _bcm_field_action_dest_check(unit, fa); 10508 BCM_IF_ERROR_RETURN(rv); 10509 10510 if (fa->param[0] > 0x3f || fa->param[1] > 0x3f) { 10511 return BCM_E_PARAM; 10512 } 10513 PolicyCheck(unit, mem, REDIRECTIONf, 10514 (fa->param[0] << 6) | fa->param[1]); 10515 break; 10516 case bcmFieldActionRedirectTrunk: /* param0 = trunk ID */ 10517 if (soc_property_get(unit, spn_TRUNK_EXTEND, 1)) { 10518 redir_field = ((fa->param[0] & 0x60) << 1) | (fa->param[0] & 0x1f); 10519 } else { 10520 redir_field = fa->param[0] & 0x1f; 10521 } 10522 redir_field |= 0x20; 10523 PolicyCheck(unit, mem, REDIRECTIONf, redir_field); 10524 break; 10525 case bcmFieldActionRedirectPbmp: 10526 PolicyCheck(unit, mem, REDIRECTIONf, fa->param[0]); 10527 break; 10528 case bcmFieldActionEgressMask: 10529 PolicyCheck(unit, mem, REDIRECTIONf, fa->param[0]); 10530 break; 10531 case bcmFieldActionMirrorIngress: 10532 case bcmFieldActionMirrorEgress: 10533 rv = _bcm_field_action_dest_check(unit, fa); 10534 BCM_IF_ERROR_RETURN(rv); 10535 break; 10536 #ifdef INCLUDE_L3 10537 case bcmFieldActionL3ChangeVlan: 10538 case bcmFieldActionL3ChangeMacDa: 10539 case bcmFieldActionL3Switch: 10540 rv = _bcm_field_policy_set_l3_nh_resolve(unit, fa->param[0], 10541 &flags, &nh_ecmp_id); 10542 BCM_IF_ERROR_RETURN(rv); 10543 if (flags & BCM_L3_MULTIPATH) { 10544 PolicyCheck(unit, mem, ECMP_PTRf, nh_ecmp_id); 10545 } else { 10546 PolicyCheck(unit, mem, NEXT_HOP_INDEXf, nh_ecmp_id); 10547 } 10548 break; 10549 #endif /* INCLUDE_L3 */ 10550 case bcmFieldActionAddClassTag: 10551 PolicyCheck(unit, mem, CLASSIFICATION_TAGf, fa->param[0]); 10552 break; 10553 case bcmFieldActionDropPrecedence: 10554 PolicyCheck(unit, mem, RP_DROP_PRECEDENCEf, fa->param[0]); 10555 PolicyCheck(unit, mem, YP_DROP_PRECEDENCEf, fa->param[0]); 10556 PolicyCheck(unit, mem, DROP_PRECEDENCEf, fa->param[0]); 10557 break; 10558 case bcmFieldActionGpDropPrecedence: 10559 PolicyCheck(unit, mem, DROP_PRECEDENCEf, fa->param[0]); 10560 break; 10561 case bcmFieldActionRpDropPrecedence: 10562 PolicyCheck(unit, mem, RP_DROP_PRECEDENCEf, fa->param[0]); 10563 break; 10564 case bcmFieldActionRpDscpNew: 10565 #if defined(BCM_FIREBOLT2_SUPPORT) 10566 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10567 PolicyCheck(unit, mem, RP_NEW_DSCPf, fa->param[0]); 10568 } else 10569 #endif /* BCM_FIREBOLT2_SUPPORT */ 10570 { 10571 PolicyCheck(unit, mem, RP_DSCPf, fa->param[0]); 10572 } 10573 break; 10574 case bcmFieldActionYpDropPrecedence: 10575 PolicyCheck(unit, mem, YP_DROP_PRECEDENCEf, fa->param[0]); 10576 break; 10577 case bcmFieldActionYpDscpNew: 10578 #if defined(BCM_FIREBOLT2_SUPPORT) 10579 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10580 PolicyCheck(unit, mem, YP_NEW_DSCPf, fa->param[0]); 10581 } else 10582 #endif /* BCM_FIREBOLT2_SUPPORT */ 10583 { 10584 PolicyCheck(unit, mem, YP_DSCPf, fa->param[0]); 10585 } 10586 break; 10587 #if defined(BCM_FIREBOLT2_SUPPORT) 10588 case bcmFieldActionRpOuterVlanPrioNew: 10589 PolicyCheck(unit, mem, RP_NEW_DOT1Pf, fa->param[0]); 10590 break; 10591 case bcmFieldActionYpOuterVlanPrioNew: 10592 PolicyCheck(unit, mem, YP_NEW_DOT1Pf, fa->param[0]); 10593 break; 10594 case bcmFieldActionGpOuterVlanPrioNew: 10595 PolicyCheck(unit, mem, GP_NEW_DOT1Pf, fa->param[0]); 10596 break; 10597 case bcmFieldActionClassSet: 10598 PolicyCheck(unit, mem, VFP_CLASS_IDf, fa->param[0]); 10599 break; 10600 case bcmFieldActionVrfSet: 10601 if (fa->param[0] > SOC_VRF_MAX(unit)) { 10602 return BCM_E_PARAM; 10603 } 10604 PolicyCheck(unit, mem, VFP_VRF_IDf, fa->param[0]); 10605 break; 10606 case bcmFieldActionVlanAdd: 10607 PolicyCheck(unit, mem, NEW_VLANf, fa->param[0]); 10608 break; 10609 case bcmFieldActionGpDscpNew: 10610 #if defined(BCM_FIREBOLT2_SUPPORT) 10611 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10612 PolicyCheck(unit, mem, GP_NEW_DSCPf, fa->param[0]); 10613 } else 10614 #endif /* BCM_FIREBOLT2_SUPPORT */ 10615 { 10616 PolicyCheck(unit, mem, NEWDSCP_TOSf, fa->param[0]); 10617 } 10618 break; 10619 case bcmFieldActionInnerVlanNew: 10620 PolicyCheck(unit, mem, PID_NEW_INNER_VIDf, fa->param[0]); 10621 break; 10622 case bcmFieldActionInnerVlanPrioNew: 10623 PolicyCheck(unit, mem, PID_NEW_INNER_PRIf, fa->param[0]); 10624 break; 10625 case bcmFieldActionOuterVlanPrioNew: 10626 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 10627 PolicyCheck(unit, mem, NEW_PRIORITYf, fa->param[0]); 10628 } else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10629 PolicyCheck(unit, mem, RP_NEW_DOT1Pf, fa->param[0]); 10630 PolicyCheck(unit, mem, YP_NEW_DOT1Pf, fa->param[0]); 10631 PolicyCheck(unit, mem, GP_NEW_DOT1Pf, fa->param[0]); 10632 } 10633 break; 10634 case bcmFieldActionOuterVlanNew: 10635 if (_BCM_FIELD_STAGE_LOOKUP== f_ent->group->stage_id) { 10636 PolicyCheck(unit, mem, NEW_VLANf, fa->param[0]); 10637 } 10638 else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 10639 PolicyCheck(unit, mem, PID_NEW_OUTER_VIDf, fa->param[0]); 10640 } 10641 break; 10642 #endif /* BCM_FIREBOLT2_SUPPORT */ 10643 default: 10644 return BCM_E_NONE; 10645 } 10646 return BCM_E_NONE; 10647 } 10648 10649 #define BCM_FB_BITS_IN_4_KBYTES (1 << 15) /* (4 * 1024 * 8) 4K bytes */ 10650 /* 10651 * Function: 10652 * _field_fb_bucket_calc 10653 * Purpose: 10654 * Lookup the proper meter bucket size encoding. 10655 */ 10656 10657 STATIC int 10658 _field_fb_bucket_calc(int unit, uint32 burst, 10659 uint32 *bucket_size, uint32 *bucket_count) 10660 { 10661 uint32 b_size; 10662 10663 /* Input parameters check. */ 10664 if ((NULL == bucket_size) || (NULL == bucket_count)) { 10665 return (BCM_E_PARAM); 10666 } 10667 10668 /* If requested rate is 0 -> set size & count to 0 */ 10669 if (0 == burst) { 10670 *bucket_size = *bucket_count = 0; 10671 return (BCM_E_NONE); 10672 } 10673 10674 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 10675 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_SC_CQ(unit)) 10676 { 10677 int linear_mode = TRUE; 10678 uint32 max_bucket_size; 10679 10680 /* Bucket size is in 4 KBytes granularity */ 10681 b_size = _bcm_fb2_kbits_to_bucket_encoding(burst, linear_mode); 10682 10683 /* Verify that value fits into hw field. */ 10684 max_bucket_size = 10685 (1 << soc_mem_field_length(unit, FP_METER_TABLEm, BUCKETSIZEf)) - 1; 10686 if (b_size > max_bucket_size) { 10687 return (BCM_E_PARAM); 10688 } 10689 10690 *bucket_size = b_size; 10691 /* Bucket count is in 1/2 bit granularity and bucket size is 10692 * in 4 KByte granularity. 10693 */ 10694 *bucket_count = 2 * b_size * BCM_FB_BITS_IN_4_KBYTES; 10695 } else 10696 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 10697 { 10698 uint8 b_code; 10699 10700 /* Bucket size is encoded as follow 10701 * Bucket Size 10702 * 4'd0 : 4 K - 1 10703 * 4'd1 : 8 K - 1 10704 * 4'd2 : 16 K - 1 10705 * 4'd3 : 32 K - 1 10706 * 4'd4 : 64 K - 1 10707 * 4'd5 : 128 K - 1 10708 * 4'd6 : 256 K - 1 10709 * 4'd7 : 512 K - 1 10710 * 4'd8 : 1 M - 1 10711 * 4'd9 : 2 M - 1 10712 * 4'd10 : 4 M - 1 10713 * 4'd11 : 8 M - 1 10714 * 4'd12 : 16 M - 1 10715 */ 10716 #define BCM_FB_BUCKET_SIZE_MAX (12) 10717 b_size = BCM_FB_BITS_IN_4_KBYTES; 10718 burst = burst * 1000; /* Convert KBits to bits */ 10719 for (b_code = 0; b_code <= BCM_FB_BUCKET_SIZE_MAX; b_code++) { 10720 if (burst < b_size) { 10721 break; 10722 } 10723 b_size *= 2; 10724 } 10725 *bucket_size = b_code; 10726 if (*bucket_size > BCM_FB_BUCKET_SIZE_MAX) { 10727 return (BCM_E_PARAM); 10728 } 10729 #undef BCM_FB_BUCKET_SIZE_MAX 10730 10731 /* Bucket count is in 1/2 of a bit granularity */ 10732 *bucket_count = 2 * b_size; 10733 } 10734 LOG_DEBUG(BSL_LS_BCM_FP, 10735 (BSL_META_U(unit, 10736 "FP(unit %d) vverb: _field_fb_bucket_calc rate=%d, bucket_count=%d, " 10737 "bucket_size=%d\n"), unit, burst, *bucket_count, *bucket_size)); 10738 return (BCM_E_NONE); 10739 } 10740 #undef BCM_FB_BITS_IN_4_KBYTES 10741 10742 int 10743 _field_fb_policer_mem_get(int unit, _field_entry_t *f_ent, 10744 soc_mem_t *mem) 10745 { 10746 _field_group_t *fg; /* Field group structure. */ 10747 soc_mem_t meter_table = INVALIDm; /* Hw meter table. */ 10748 10749 /* Input parameters check. */ 10750 if ((NULL == f_ent) || (NULL == mem)) { 10751 return (BCM_E_PARAM); 10752 } 10753 10754 fg = f_ent->group; 10755 if (NULL == fg) { 10756 return (BCM_E_INTERNAL); 10757 } 10758 10759 if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) { 10760 #ifdef BCM_HB_GW_SUPPORT 10761 if (SOC_IS_HB_GW(unit)) { 10762 meter_table = FP_METER_TABLE_Xm; 10763 } else 10764 #endif /* BCM_BRADLEY_SUPPORT */ 10765 { 10766 meter_table = FP_METER_TABLEm; 10767 } 10768 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 10769 } if (soc_feature(unit, soc_feature_field_multi_stage)) { 10770 if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) { 10771 meter_table = EFP_METER_TABLEm; 10772 } 10773 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 10774 } 10775 if (INVALIDm == meter_table) { 10776 return (BCM_E_INTERNAL); 10777 } 10778 *mem = meter_table; 10779 return (BCM_E_NONE); 10780 } 10781 10782 STATIC int 10783 _field_fb_policer_hw_update(int unit, _field_entry_t *f_ent, 10784 _field_policer_t *f_pl, uint8 index_mtr, 10785 uint32 bucket_size, uint32 bucket_count, 10786 uint32 refresh_count) 10787 { 10788 _field_stage_t *stage_fc; /* Stage field control. */ 10789 int meter_offset; /* HW buffer for meter entry. */ 10790 uint32 meter_entry[SOC_MAX_MEM_FIELD_WORDS]; 10791 int mem_field_width; 10792 soc_mem_t mem; /* Meter table memory. */ 10793 int meter_hw_idx; /* Meter memory entry index. */ 10794 10795 if ((NULL == f_pl) || (NULL == f_ent)) { 10796 return (BCM_E_PARAM); 10797 } 10798 10799 /* Get meter table memory. */ 10800 BCM_IF_ERROR_RETURN(_field_fb_policer_mem_get(unit, f_ent, &mem)); 10801 10802 /* Get stage control structure. */ 10803 BCM_IF_ERROR_RETURN 10804 (_field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc)); 10805 10806 mem_field_width = soc_mem_field_length(unit, mem, REFRESHCOUNTf); 10807 if (refresh_count > (uint32)((1 << mem_field_width) - 1)) { 10808 return (BCM_E_PARAM); 10809 } 10810 10811 meter_offset = (BCM_FIELD_METER_PEAK == index_mtr) ? 0 : 1; 10812 10813 if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) { 10814 meter_hw_idx = (2 * f_pl->pool_index * 10815 stage_fc->meter_pool[_FP_DEF_INST][f_pl->pool_index]->pool_size) + 10816 (2 * f_pl->hw_index) + meter_offset; 10817 } else { 10818 meter_hw_idx = 10819 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx + \ 10820 (2 * f_pl->hw_index) + meter_offset; 10821 } 10822 10823 if (meter_hw_idx < soc_mem_index_min(unit, mem) || 10824 meter_hw_idx > soc_mem_index_max(unit, mem)) { 10825 return (BCM_E_INTERNAL); 10826 } 10827 10828 SOC_IF_ERROR_RETURN 10829 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, 10830 meter_hw_idx, &meter_entry)); 10831 10832 soc_mem_field32_set(unit, mem, &meter_entry, REFRESHCOUNTf, 10833 refresh_count); 10834 soc_mem_field32_set(unit, mem, &meter_entry, BUCKETSIZEf, 10835 bucket_size); 10836 soc_mem_field32_set(unit, mem, &meter_entry, BUCKETCOUNTf, 10837 bucket_count); 10838 10839 /* Refresh mode is only set to 1 for Single Rate. Other modes get 0 */ 10840 10841 if (f_pl->cfg.mode == bcmPolicerModeSrTcm) { 10842 soc_mem_field32_set(unit, mem, &meter_entry, REFRESH_MODEf, 1); 10843 } else { 10844 soc_mem_field32_set(unit, mem, &meter_entry, REFRESH_MODEf, 0); 10845 } 10846 10847 #if defined(BCM_TRX_SUPPORT) 10848 if (((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) || 10849 (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL)) && 10850 (SOC_MEM_FIELD_VALID(unit, mem, METER_GRANf))) { 10851 soc_mem_field32_set(unit, mem, &meter_entry, METER_GRANf, 3); 10852 } 10853 #endif /* BCM_TRX_SUPPORT) */ 10854 10855 BCM_IF_ERROR_RETURN 10856 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 10857 meter_hw_idx, meter_entry)); 10858 10859 #ifdef BCM_HB_GW_SUPPORT 10860 if (SOC_IS_HB_GW(unit)) { 10861 BCM_IF_ERROR_RETURN 10862 (soc_mem_write(unit, FP_METER_TABLE_Ym, MEM_BLOCK_ALL, 10863 meter_hw_idx, meter_entry)); 10864 } 10865 #endif /* BCM_BRADLEY_SUPPORT */ 10866 10867 return (BCM_E_NONE); 10868 } 10869 10870 /* 10871 * Function: 10872 * _bcm_field_fb_policer_install 10873 * Purpose: 10874 * Install a policer pair into the hardware tables. 10875 * Parameters: 10876 * unit - (IN) BCM device number 10877 * f_ent - (IN) Field entry structure. 10878 * f_pl - (IN) Field policer descriptor. 10879 * Returns: 10880 * BCM_E_XXX 10881 */ 10882 int 10883 _bcm_field_fb_policer_install(int unit, _field_entry_t *f_ent, 10884 _field_policer_t *f_pl) 10885 { 10886 uint32 bucket_size = 0; 10887 uint32 refresh_count = 0; 10888 uint32 bucket_count = 0; 10889 10890 if ((NULL == f_ent) || (NULL == f_pl)) { 10891 return (BCM_E_PARAM); 10892 } 10893 10894 if (NULL == f_ent->group || NULL == f_ent->fs) { 10895 return (BCM_E_INTERNAL); 10896 } 10897 10898 if (0 == (f_pl->hw_flags & _FP_POLICER_DIRTY)) { 10899 return (BCM_E_NONE); 10900 } 10901 10902 /* lookup bucket size from tables */ 10903 if (f_pl->hw_flags & _FP_POLICER_COMMITTED_DIRTY) { 10904 BCM_IF_ERROR_RETURN 10905 (_field_fb_bucket_calc(unit, f_pl->cfg.ckbits_burst, 10906 &bucket_size, &bucket_count)); 10907 10908 /* A value of one in the REFRESHCOUNT is 64 kbits/sec */ 10909 refresh_count = f_pl->cfg.ckbits_sec / _FP_POLICER_REFRESH_RATE; 10910 10911 BCM_IF_ERROR_RETURN 10912 (_field_fb_policer_hw_update(unit, f_ent, f_pl, 10913 BCM_FIELD_METER_COMMITTED, 10914 bucket_size, bucket_count, 10915 refresh_count)); 10916 10917 LOG_DEBUG(BSL_LS_BCM_FP, 10918 (BSL_META_U(unit, 10919 "FP(unit %d) vverb: commited-> bucket_size=%u, bucket_count=%u, " 10920 "refresh_count=%u\n"), unit, bucket_size, bucket_count, 10921 refresh_count)); 10922 f_pl->hw_flags &= ~_FP_POLICER_COMMITTED_DIRTY; 10923 } 10924 10925 if (f_pl->hw_flags & _FP_POLICER_PEAK_DIRTY) { 10926 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 10927 /* 10928 * Rates are always set in committed variables, for flow meters. 10929 */ 10930 f_pl->cfg.pkbits_sec = f_pl->cfg.ckbits_sec; 10931 f_pl->cfg.pkbits_burst = f_pl->cfg.ckbits_burst; 10932 } 10933 10934 BCM_IF_ERROR_RETURN 10935 (_field_fb_bucket_calc(unit, f_pl->cfg.pkbits_burst, 10936 &bucket_size, &bucket_count)); 10937 10938 refresh_count = f_pl->cfg.pkbits_sec / _FP_POLICER_REFRESH_RATE; 10939 10940 BCM_IF_ERROR_RETURN 10941 (_field_fb_policer_hw_update(unit, f_ent, f_pl, 10942 BCM_FIELD_METER_PEAK, 10943 bucket_size, bucket_count, 10944 refresh_count)); 10945 10946 LOG_DEBUG(BSL_LS_BCM_FP, 10947 (BSL_META_U(unit, 10948 "FP(unit %d) vverb: commited-> bucket_size=%u, bucket_count=%u, " 10949 "refresh_count=%u\n"), unit, bucket_size, bucket_count, 10950 refresh_count)); 10951 10952 f_pl->hw_flags &= ~_FP_POLICER_PEAK_DIRTY; 10953 10954 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) { 10955 /* 10956 * Reset rates in peak meter variables. 10957 */ 10958 f_pl->cfg.pkbits_sec = 0; 10959 f_pl->cfg.pkbits_burst = 0; 10960 } 10961 } 10962 return BCM_E_NONE; 10963 } 10964 #undef _FP_POLICER_REFRESH_RATE 10965 10966 #if defined(BCM_FIREBOLT2_SUPPORT) 10967 /* 10968 * Function: 10969 * _field_fb2_key_match_type_set 10970 * 10971 * Purpose: 10972 * Set key match type based on entry group. 10973 * NOTE: For double wide entries key type must be the same for 10974 * both parts of the entry. 10975 * Parameters: 10976 * unit - (IN) BCM device number 10977 * f_ent - (IN) Slice number to enable 10978 * Returns: 10979 * BCM_E_XXX 10980 */ 10981 STATIC int 10982 _field_fb2_key_match_type_set(int unit, _field_entry_t *f_ent) 10983 { 10984 _field_group_t *fg; /* Field group entry belongs to. */ 10985 uint32 data; /* Key match type. */ 10986 uint32 mask; /* Key match type mask. */ 10987 /* Key match type offset. */ 10988 _bcm_field_qual_offset_t q_offset; 10989 { 10990 sal_memset(&q_offset, 0, sizeof(q_offset)); 10991 q_offset.field = KEYf; 10992 q_offset.num_offsets = 1; 10993 q_offset.offset[0] = 181; 10994 q_offset.width[0] = 3; 10995 } 10996 10997 /* Input parameters check. */ 10998 if (NULL == f_ent) { 10999 return (BCM_E_PARAM); 11000 } 11001 if (NULL == (fg = f_ent->group)) { 11002 return (BCM_E_PARAM); 11003 } 11004 11005 if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) { 11006 switch (fg->sel_codes[0].fpf3) { 11007 case _BCM_FIELD_EFP_KEY1: 11008 data = _BCM_FIELD_EFP_KEY1_MATCH_TYPE; 11009 break; 11010 case _BCM_FIELD_EFP_KEY2: 11011 data = _BCM_FIELD_EFP_KEY2_MATCH_TYPE; 11012 break; 11013 case _BCM_FIELD_EFP_KEY4: 11014 data = _BCM_FIELD_EFP_KEY4_MATCH_TYPE; 11015 break; 11016 default: 11017 return (BCM_E_INTERNAL); 11018 } 11019 } else { 11020 switch (fg->sel_codes[1].fpf3) { 11021 case _BCM_FIELD_EFP_KEY2: 11022 data = _BCM_FIELD_EFP_KEY2_KEY3_MATCH_TYPE; 11023 break; 11024 case _BCM_FIELD_EFP_KEY4: 11025 data = _BCM_FIELD_EFP_KEY1_KEY4_MATCH_TYPE; 11026 break; 11027 default: 11028 return (BCM_E_INTERNAL); 11029 } 11030 } 11031 mask = 0x7; 11032 /* 11033 * COVERITY 11034 * 11035 *This flow takes care of the Out-of-bounds access issue as 11036 * the offset that is being passed is defined. 11037 */ 11038 /* coverity[callee_ptr_arith] */ 11039 return _bcm_field_qual_value_set(unit, &q_offset, f_ent, &data, &mask); 11040 } 11041 #endif /* BCM_FIREBOLT2_SUPPORT */ 11042 11043 /* 11044 * Function: 11045 * _bcm_field_fb_write_slice_map 11046 * 11047 * Purpose: 11048 * Write the FP_SLICE_MAP 11049 * 11050 * Parameters: 11051 * unit 11052 * stage_fc - pointer to stage control block 11053 * fg - Reference to Field Group Structure. 11054 * 11055 * Returns: 11056 * nothing 11057 * 11058 * Notes: 11059 */ 11060 int 11061 _bcm_field_fb_write_slice_map(int unit, _field_stage_t *stage_fc, 11062 _field_group_t *fg) 11063 { 11064 int rv = BCM_E_NONE; 11065 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 11066 int idx; 11067 fp_slice_map_entry_t map_entry; 11068 soc_field_t field; 11069 int vmap_size; 11070 uint32 value; 11071 11072 /* Calculate virtual map size. */ 11073 rv = _bcm_field_virtual_map_size_get(unit, stage_fc, &vmap_size); 11074 BCM_IF_ERROR_RETURN(rv); 11075 11076 rv = READ_FP_SLICE_MAPm(unit, MEM_BLOCK_ANY, 0, &map_entry); 11077 BCM_IF_ERROR_RETURN(rv); 11078 11079 for (idx = 0; idx < vmap_size; idx++) { 11080 value = (stage_fc->vmap[_FP_DEF_INST][0][idx]).vmap_key; 11081 field = virtual_to_physical_map[idx]; 11082 soc_FP_SLICE_MAPm_field32_set(unit, &map_entry, field, value); 11083 11084 value = (stage_fc->vmap[_FP_DEF_INST][0][idx]).virtual_group; 11085 field = virtual_to_group_map[idx]; 11086 soc_FP_SLICE_MAPm_field32_set(unit, &map_entry, field, value); 11087 } 11088 11089 rv = WRITE_FP_SLICE_MAPm(unit, MEM_BLOCK_ALL, 0, &map_entry); 11090 #endif /* BCM_RAPTOR_SUPPORT || BCM_FIREBOLT2_SUPPORT */ 11091 return (rv); 11092 } 11093 11094 /* 11095 * Function: 11096 * _field_fb_qualify_ip_type 11097 * Purpose: 11098 * Install ip type qualifier into TCAM 11099 * Parameters: 11100 * unit - (IN) BCM device number 11101 * entry - (IN) Field entry index 11102 * type - (IN) Ip Type. 11103 * qual - (IN) Qualifier(IpType) 11104 * Returns: 11105 * BCM_E_XXX 11106 * Notes: 11107 */ 11108 #define BCM_FIELD_IPTYPE_BAD 0xff 11109 STATIC int 11110 _field_fb_qualify_ip_type(int unit, bcm_field_entry_t entry, 11111 bcm_field_IpType_t type, 11112 bcm_field_qualify_t qual) 11113 { 11114 _field_group_t *fg; 11115 _field_entry_t *f_ent; 11116 uint32 data = BCM_FIELD_IPTYPE_BAD, 11117 mask = BCM_FIELD_IPTYPE_BAD; 11118 11119 BCM_IF_ERROR_RETURN 11120 (_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent)); 11121 11122 fg = f_ent->group; 11123 if (NULL == fg) { 11124 return (BCM_E_INTERNAL); 11125 } 11126 11127 /* 11128 * Devices with a separate PacketFormat and IpType use different hardware 11129 * encodings for IpType. 11130 */ 11131 if (soc_feature(unit, soc_feature_field_qual_IpType)) { 11132 if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) { 11133 switch (type) { 11134 case bcmFieldIpTypeAny: 11135 data = 0x0; 11136 mask = 0x0; 11137 break; 11138 case bcmFieldIpTypeNonIp: 11139 data = 0x0; 11140 mask = 0x3; 11141 break; 11142 case bcmFieldIpTypeIpv4Not: 11143 data = 0x0; 11144 mask = 0x1; 11145 break; 11146 case bcmFieldIpTypeIpv4NoOpts: 11147 data = 0x1; 11148 mask = 0x3; 11149 break; 11150 case bcmFieldIpTypeIpv4WithOpts: 11151 data = 0x3; 11152 mask = 0x3; 11153 break; 11154 case bcmFieldIpTypeIpv4Any: 11155 data = 0x1; 11156 mask = 0x1; 11157 break; 11158 case bcmFieldIpTypeIpv6: 11159 data = 0x2; 11160 mask = 0x3; 11161 break; 11162 default: 11163 break; 11164 } 11165 } 11166 #ifdef BCM_FIREBOLT2_SUPPORT 11167 else if (fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 11168 switch (type) { 11169 case bcmFieldIpTypeNonIp: 11170 data = 0x2; 11171 mask = 0x2; 11172 break; 11173 case bcmFieldIpTypeIpv4Any: 11174 data = 0x0; 11175 mask = 0x3; 11176 break; 11177 case bcmFieldIpTypeIpv6: 11178 data = 0x1; 11179 mask = 0x3; 11180 break; 11181 case bcmFieldIpTypeIp: 11182 data = 0x0; 11183 mask = 0x2; 11184 break; 11185 case bcmFieldIpTypeArp: 11186 data = 0x2; 11187 mask = 0x3; 11188 break; 11189 default: 11190 break; 11191 } 11192 } else if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) { 11193 switch (type) { 11194 case bcmFieldIpTypeIpv4WithOpts: 11195 data = 0x1; 11196 mask = 0x1; 11197 break; 11198 case bcmFieldIpTypeIpv4NoOpts: 11199 data = 0x0; 11200 mask = 0x1; 11201 break; 11202 case bcmFieldIpTypeIpv4Any: 11203 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4)) { 11204 return (BCM_E_NONE); 11205 } 11206 return (BCM_E_UNAVAIL); 11207 case bcmFieldIpTypeIpv6: 11208 if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6)) { 11209 return (BCM_E_NONE); 11210 } 11211 return (BCM_E_UNAVAIL); 11212 default: 11213 return (BCM_E_UNAVAIL); 11214 } 11215 } 11216 #endif /* BCM_FIREBOLT2_SUPPORT */ 11217 } else { /* Devices without separate IpType field. */ 11218 switch (type) { 11219 case bcmFieldIpTypeAny: 11220 data = 0x0; 11221 mask = 0x0; 11222 break; 11223 case bcmFieldIpTypeNonIp: 11224 data = 0x0; 11225 mask = 0x3; 11226 break; 11227 case bcmFieldIpTypeIpv4Not: 11228 data = 0x0; 11229 mask = 0x1; 11230 break; 11231 case bcmFieldIpTypeIpv4Any: 11232 data = 0x1; 11233 mask = 0x3; 11234 break; 11235 case bcmFieldIpTypeIpv6: 11236 data = 0x2; 11237 mask = 0x3; 11238 break; 11239 case bcmFieldIpTypeIpv6Not: 11240 data = 0x0; 11241 mask = 0x2; 11242 break; 11243 default: 11244 break; 11245 } 11246 } 11247 11248 LOG_DEBUG(BSL_LS_BCM_FP, 11249 (BSL_META_U(unit, 11250 "FP(unit %d) vverb: entry=%d qualifying on Iptype, data=%#x, mask=%#x\n"), 11251 unit, f_ent->eid, data, mask)); 11252 11253 if ((data == BCM_FIELD_IPTYPE_BAD) || 11254 (mask == BCM_FIELD_IPTYPE_BAD)) { 11255 return (BCM_E_UNAVAIL); 11256 } 11257 return _field_qualify32(unit, f_ent->eid, qual, 11258 data, mask); 11259 } 11260 #undef BCM_FIELD_IPTYPE_BAD 11261 11262 /* 11263 * Function: 11264 * _field_fb_qualify_ip_type_get 11265 * Purpose: 11266 * Read ip type qualifier match criteria from the HW. 11267 * Parameters: 11268 * unit - (IN) BCM device number 11269 * entry - (IN) Field entry index 11270 * type - (OUT) Ip Type. 11271 * qual - (IN) Qualifier(IpType) 11272 * Returns: 11273 * BCM_E_XXX 11274 * Notes: 11275 */ 11276 STATIC int 11277 _field_fb_qualify_ip_type_get(int unit, bcm_field_entry_t entry, 11278 bcm_field_IpType_t *type, 11279 bcm_field_qualify_t qual) 11280 { 11281 _field_group_t *fg; /* Field group structure. */ 11282 _field_entry_t *f_ent; /* Field Entry structure. */ 11283 uint32 hw_data; /* HW encoded qualifier data. */ 11284 uint32 hw_mask; /* HW encoding qualifier mask. */ 11285 int rv; /* Operation return status. */ 11286 11287 /* Input parameters checks. */ 11288 if (NULL == type) { 11289 return (BCM_E_PARAM); 11290 } 11291 11292 BCM_IF_ERROR_RETURN 11293 (_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent)); 11294 11295 fg = f_ent->group; 11296 if (NULL == fg) { 11297 return (BCM_E_INTERNAL); 11298 } 11299 11300 /* Read qualifier match value and mask. */ 11301 rv = _bcm_field_entry_qualifier_uint32_get(unit, f_ent->eid, 11302 qual, 11303 &hw_data, &hw_mask); 11304 BCM_IF_ERROR_RETURN(rv); 11305 11306 /* Read IpType encoding for qualifier data and mask */ 11307 rv = _bcm_field_fb_qualify_ip_type_encode_get(unit, fg, hw_data, 11308 hw_mask, type); 11309 11310 return rv; 11311 } 11312 /* 11313 * Function: 11314 * _bcm_field_fb_qualify_ip_type_encode_get 11315 * Purpose: 11316 * Get ip type qualifier encode value for given data and mask. 11317 * Parameters: 11318 * unit - (IN) BCM device number 11319 * fg - (IN) Field group 11320 * data - (IN) qualifier data. 11321 * mask - (IN) qualifier mask. 11322 * type - (OUT) Ip Type. 11323 * Returns: 11324 * BCM_E_XXX 11325 * Notes: 11326 */ 11327 11328 int 11329 _bcm_field_fb_qualify_ip_type_encode_get(int unit, _field_group_t *fg, 11330 uint32 hw_data, uint32 hw_mask, 11331 bcm_field_IpType_t *type) 11332 { 11333 /* 11334 * Devices with a separate PacketFormat and IpType use different hardware 11335 * encodings for IpType. 11336 */ 11337 if (soc_feature(unit, soc_feature_field_qual_IpType)) { 11338 if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) { 11339 if ((hw_data == 0) && (hw_mask == 0)) { 11340 *type = bcmFieldIpTypeAny; 11341 } else if ((hw_data == 0) && (hw_mask == 3)) { 11342 *type = bcmFieldIpTypeNonIp; 11343 } else if ((hw_data == 0) && (hw_mask == 1)) { 11344 *type = bcmFieldIpTypeIpv4Not; 11345 } else if ((hw_data == 1) && (hw_mask == 3)) { 11346 *type = bcmFieldIpTypeIpv4NoOpts; 11347 } else if ((hw_data == 3) && (hw_mask == 3)) { 11348 *type = bcmFieldIpTypeIpv4WithOpts; 11349 } else if ((hw_data == 1) && (hw_mask == 1)) { 11350 *type = bcmFieldIpTypeIpv4Any; 11351 } else if ((hw_data == 2) && (hw_mask == 3)) { 11352 *type = bcmFieldIpTypeIpv6; 11353 } else { 11354 return (BCM_E_INTERNAL); 11355 } 11356 } 11357 #ifdef BCM_FIREBOLT2_SUPPORT 11358 else if (fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) { 11359 if ((hw_data == 2) && (hw_mask == 2)) { 11360 *type = bcmFieldIpTypeNonIp; 11361 } else if ((hw_data == 0) && (hw_mask == 3)) { 11362 *type = bcmFieldIpTypeIpv4Any; 11363 } else if ((hw_data == 1) && (hw_mask == 3)) { 11364 *type = bcmFieldIpTypeIpv6; 11365 } else if ((hw_data == 0) && (hw_mask == 2)) { 11366 *type = bcmFieldIpTypeIp; 11367 } else if ((hw_data == 2) && (hw_mask == 3)) { 11368 *type = bcmFieldIpTypeArp; 11369 } else { 11370 return (BCM_E_INTERNAL); 11371 } 11372 } else if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) { 11373 if ((hw_data == 1) && (hw_mask == 1)) { 11374 *type = bcmFieldIpTypeIpv4WithOpts; 11375 } else if ((hw_data == 0) && (hw_mask == 1)) { 11376 *type = bcmFieldIpTypeIpv4NoOpts; 11377 } else if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4)) { 11378 *type = bcmFieldIpTypeIpv4Any; 11379 } else if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6)) { 11380 *type = bcmFieldIpTypeIpv6; 11381 } else { 11382 return (BCM_E_INTERNAL); 11383 } 11384 } 11385 #endif /* BCM_FIREBOLT2_SUPPORT */ 11386 } else { /* Devices without separate IpType field. */ 11387 if ((hw_data == 0) && (hw_mask == 0)) { 11388 *type = bcmFieldIpTypeAny; 11389 } else if ((hw_data == 0) && (hw_mask == 3)) { 11390 *type = bcmFieldIpTypeNonIp; 11391 } else if ((hw_data == 0) && (hw_mask == 1)) { 11392 *type = bcmFieldIpTypeIpv4Not; 11393 } else if ((hw_data == 1) && (hw_mask == 3)) { 11394 *type = bcmFieldIpTypeIpv4Any; 11395 } else if ((hw_data == 2) && (hw_mask == 3)) { 11396 *type = bcmFieldIpTypeIpv6; 11397 } else if ((hw_data == 0) && (hw_mask == 2)) { 11398 *type = bcmFieldIpTypeIpv6Not; 11399 } else { 11400 return (BCM_E_INTERNAL); 11401 } 11402 } 11403 return (BCM_E_NONE); 11404 } 11405 11406 /* 11407 * Function: 11408 * _field_fb_action_conflict_check 11409 * 11410 * Purpose: 11411 * Check if two action conflict (occupy the same field in FP policy table) 11412 * 11413 * Parameters: 11414 * unit -(IN)BCM device number 11415 * f_ent -(IN)Field entry structure. 11416 * action -(IN) Action to check(bcmFieldActionXXX) 11417 * action1 -(IN) Action to check(bcmFieldActionXXX) 11418 * 11419 * Returns: 11420 * BCM_E_CONFIG - if actions do conflict 11421 * BCM_E_NONE - if there is no conflict 11422 */ 11423 STATIC int 11424 _field_fb_action_conflict_check(int unit, _field_entry_t *f_ent, 11425 bcm_field_action_t action1, 11426 bcm_field_action_t action) 11427 { 11428 /* Input parameters check */ 11429 if (NULL == f_ent) { 11430 return (BCM_E_PARAM); 11431 } 11432 if (NULL == f_ent->group) { 11433 return (BCM_E_PARAM); 11434 } 11435 11436 /* Two identical actions are forbidden. */ 11437 _FP_ACTIONS_CONFLICT(action1); 11438 11439 #ifdef BCM_FIREBOLT2_SUPPORT 11440 if (SOC_IS_FIREBOLT2(unit)) { 11441 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 11442 switch (action1) { 11443 case bcmFieldActionDrop: 11444 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11445 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropCancel); 11446 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropCancel); 11447 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropCancel); 11448 break; 11449 case bcmFieldActionDropCancel: 11450 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11451 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDrop); 11452 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDrop); 11453 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDrop); 11454 break; 11455 case bcmFieldActionRpDrop: 11456 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11457 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropCancel); 11458 break; 11459 case bcmFieldActionRpDropCancel: 11460 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11461 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDrop); 11462 break; 11463 case bcmFieldActionYpDrop: 11464 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11465 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropCancel); 11466 break; 11467 case bcmFieldActionYpDropCancel: 11468 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11469 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDrop); 11470 break; 11471 case bcmFieldActionGpDrop: 11472 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11473 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropCancel); 11474 break; 11475 case bcmFieldActionGpDropCancel: 11476 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11477 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDrop); 11478 break; 11479 case bcmFieldActionDscpNew: 11480 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpNew); 11481 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpNew); 11482 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpNew); 11483 break; 11484 case bcmFieldActionRpDscpNew: 11485 case bcmFieldActionYpDscpNew: 11486 case bcmFieldActionGpDscpNew: 11487 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew); 11488 break; 11489 case bcmFieldActionRpOuterVlanPrioNew: 11490 case bcmFieldActionYpOuterVlanPrioNew: 11491 case bcmFieldActionGpOuterVlanPrioNew: 11492 _FP_ACTIONS_CONFLICT(bcmFieldActionOuterVlanPrioNew); 11493 break; 11494 case bcmFieldActionOuterVlanPrioNew: 11495 _FP_ACTIONS_CONFLICT(bcmFieldActionRpOuterVlanPrioNew); 11496 _FP_ACTIONS_CONFLICT(bcmFieldActionYpOuterVlanPrioNew); 11497 _FP_ACTIONS_CONFLICT(bcmFieldActionGpOuterVlanPrioNew); 11498 break; 11499 case bcmFieldActionInnerVlanPrioNew: 11500 case bcmFieldActionInnerVlanNew: 11501 case bcmFieldActionOuterVlanNew: 11502 case bcmFieldActionOuterTpidNew: 11503 break; 11504 default: 11505 break; 11506 } 11507 return (BCM_E_NONE); 11508 } 11509 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 11510 switch (action1) { 11511 case bcmFieldActionDrop: 11512 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11513 break; 11514 case bcmFieldActionDropCancel: 11515 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11516 break; 11517 case bcmFieldActionOuterVlanNew: 11518 case bcmFieldActionVlanAdd: 11519 case bcmFieldActionOuterVlanPrioNew: 11520 case bcmFieldActionCopyToCpu: 11521 case bcmFieldActionVrfSet: 11522 case bcmFieldActionClassSet: 11523 break; 11524 default: 11525 break; 11526 } 11527 return (BCM_E_NONE); 11528 } 11529 } 11530 #endif /* BCM_FIREBOLT2_SUPPORT */ 11531 11532 switch (action1) { 11533 case bcmFieldActionCosQNew: 11534 case bcmFieldActionCosQCpuNew: 11535 case bcmFieldActionPrioPktAndIntCopy: 11536 case bcmFieldActionPrioPktAndIntNew: 11537 case bcmFieldActionPrioPktAndIntTos: 11538 case bcmFieldActionPrioPktAndIntCancel: 11539 case bcmFieldActionPrioPktCopy: 11540 case bcmFieldActionPrioPktNew: 11541 case bcmFieldActionPrioPktTos: 11542 case bcmFieldActionPrioPktCancel: 11543 case bcmFieldActionPrioIntCopy: 11544 case bcmFieldActionPrioIntNew: 11545 case bcmFieldActionPrioIntTos: 11546 case bcmFieldActionPrioIntCancel: 11547 _FP_ACTIONS_CONFLICT(bcmFieldActionCosQNew); 11548 _FP_ACTIONS_CONFLICT(bcmFieldActionCosQCpuNew); 11549 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktAndIntCopy); 11550 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktAndIntNew); 11551 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktAndIntTos); 11552 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktAndIntCancel); 11553 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktCopy); 11554 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktNew); 11555 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktTos); 11556 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktCancel); 11557 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioIntCopy); 11558 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioIntNew); 11559 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioIntTos); 11560 _FP_ACTIONS_CONFLICT(bcmFieldActionPrioIntCancel); 11561 break; 11562 case bcmFieldActionTosNew: 11563 case bcmFieldActionTosCopy: 11564 case bcmFieldActionTosCancel: 11565 _FP_ACTIONS_CONFLICT(bcmFieldActionEcnNew); 11566 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew); 11567 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpCancel); 11568 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpNew); 11569 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpNew); 11570 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpNew); 11571 break; 11572 case bcmFieldActionDscpNew: 11573 case bcmFieldActionDscpCancel: 11574 _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew); 11575 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy); 11576 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel); 11577 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpNew); 11578 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpNew); 11579 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpNew); 11580 break; 11581 case bcmFieldActionRpDscpNew: 11582 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpNew); 11583 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpCancel); 11584 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew); 11585 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpCancel); 11586 _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew); 11587 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy); 11588 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel); 11589 break; 11590 case bcmFieldActionYpDscpNew: 11591 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpNew); 11592 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpCancel); 11593 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew); 11594 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpCancel); 11595 _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew); 11596 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy); 11597 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel); 11598 break; 11599 case bcmFieldActionGpDscpNew: 11600 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpNew); 11601 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpCancel); 11602 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew); 11603 _FP_ACTIONS_CONFLICT(bcmFieldActionDscpCancel); 11604 _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew); 11605 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy); 11606 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel); 11607 break; 11608 case bcmFieldActionEcnNew: 11609 _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew); 11610 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy); 11611 _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel); 11612 break; 11613 11614 case bcmFieldActionCopyToCpu: 11615 case bcmFieldActionCopyToCpuCancel: 11616 case bcmFieldActionSwitchToCpuCancel: 11617 _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpu); 11618 _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpuCancel); 11619 _FP_ACTIONS_CONFLICT(bcmFieldActionSwitchToCpuCancel); 11620 _FP_ACTIONS_CONFLICT(bcmFieldActionRpCopyToCpu); 11621 _FP_ACTIONS_CONFLICT(bcmFieldActionRpCopyToCpuCancel); 11622 _FP_ACTIONS_CONFLICT(bcmFieldActionYpCopyToCpu); 11623 _FP_ACTIONS_CONFLICT(bcmFieldActionYpCopyToCpuCancel); 11624 _FP_ACTIONS_CONFLICT(bcmFieldActionGpCopyToCpu); 11625 _FP_ACTIONS_CONFLICT(bcmFieldActionGpCopyToCpuCancel); 11626 _FP_ACTIONS_CONFLICT(bcmFieldActionRpSwitchToCpuCancel); 11627 break; 11628 case bcmFieldActionRpCopyToCpu: 11629 case bcmFieldActionRpCopyToCpuCancel: 11630 case bcmFieldActionRpSwitchToCpuCancel: 11631 _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpu); 11632 _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpuCancel); 11633 _FP_ACTIONS_CONFLICT(bcmFieldActionSwitchToCpuCancel); 11634 _FP_ACTIONS_CONFLICT(bcmFieldActionRpCopyToCpu); 11635 _FP_ACTIONS_CONFLICT(bcmFieldActionRpCopyToCpuCancel); 11636 _FP_ACTIONS_CONFLICT(bcmFieldActionRpSwitchToCpuCancel); 11637 break; 11638 case bcmFieldActionYpCopyToCpu: 11639 case bcmFieldActionYpCopyToCpuCancel: 11640 _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpu); 11641 _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpuCancel); 11642 _FP_ACTIONS_CONFLICT(bcmFieldActionSwitchToCpuCancel); 11643 _FP_ACTIONS_CONFLICT(bcmFieldActionYpCopyToCpu); 11644 _FP_ACTIONS_CONFLICT(bcmFieldActionYpCopyToCpuCancel); 11645 break; 11646 case bcmFieldActionGpCopyToCpu: 11647 case bcmFieldActionGpCopyToCpuCancel: 11648 _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpu); 11649 _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpuCancel); 11650 _FP_ACTIONS_CONFLICT(bcmFieldActionSwitchToCpuCancel); 11651 _FP_ACTIONS_CONFLICT(bcmFieldActionGpCopyToCpu); 11652 _FP_ACTIONS_CONFLICT(bcmFieldActionGpCopyToCpuCancel); 11653 break; 11654 case bcmFieldActionDrop: 11655 case bcmFieldActionDropCancel: 11656 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11657 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11658 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDrop); 11659 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropCancel); 11660 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDrop); 11661 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropCancel); 11662 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDrop); 11663 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropCancel); 11664 break; 11665 case bcmFieldActionRpDrop: 11666 case bcmFieldActionRpDropCancel: 11667 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11668 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11669 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDrop); 11670 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropCancel); 11671 break; 11672 case bcmFieldActionYpDrop: 11673 case bcmFieldActionYpDropCancel: 11674 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11675 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11676 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDrop); 11677 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropCancel); 11678 break; 11679 case bcmFieldActionGpDrop: 11680 case bcmFieldActionGpDropCancel: 11681 _FP_ACTIONS_CONFLICT(bcmFieldActionDrop); 11682 _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel); 11683 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDrop); 11684 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropCancel); 11685 break; 11686 case bcmFieldActionRedirect: 11687 case bcmFieldActionRedirectTrunk: 11688 case bcmFieldActionRedirectCancel: 11689 case bcmFieldActionRedirectPbmp: 11690 case bcmFieldActionEgressMask: 11691 _FP_ACTIONS_CONFLICT(bcmFieldActionRedirect); 11692 _FP_ACTIONS_CONFLICT(bcmFieldActionRedirectTrunk); 11693 _FP_ACTIONS_CONFLICT(bcmFieldActionRedirectCancel); 11694 _FP_ACTIONS_CONFLICT(bcmFieldActionRedirectPbmp); 11695 _FP_ACTIONS_CONFLICT(bcmFieldActionEgressMask); 11696 break; 11697 case bcmFieldActionMirrorIngress: 11698 _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorIngress); 11699 _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorOverride); 11700 break; 11701 case bcmFieldActionMirrorEgress: 11702 _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorOverride); 11703 _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorEgress); 11704 break; 11705 case bcmFieldActionMirrorOverride: 11706 _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorIngress); 11707 _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorEgress); 11708 break; 11709 case bcmFieldActionL3ChangeVlan: 11710 case bcmFieldActionL3ChangeVlanCancel: 11711 case bcmFieldActionL3ChangeMacDa: 11712 case bcmFieldActionL3ChangeMacDaCancel: 11713 case bcmFieldActionL3Switch: 11714 case bcmFieldActionL3SwitchCancel: 11715 case bcmFieldActionAddClassTag: 11716 _FP_ACTIONS_CONFLICT(bcmFieldActionAddClassTag); 11717 _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeVlan); 11718 _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeVlanCancel); 11719 _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeMacDa); 11720 _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeMacDaCancel); 11721 _FP_ACTIONS_CONFLICT(bcmFieldActionL3Switch); 11722 _FP_ACTIONS_CONFLICT(bcmFieldActionL3SwitchCancel); 11723 _FP_ACTIONS_CONFLICT(bcmFieldActionSrcMacNew); 11724 _FP_ACTIONS_CONFLICT(bcmFieldActionDstMacNew); 11725 _FP_ACTIONS_CONFLICT(bcmFieldActionOuterVlanNew); 11726 break; 11727 case bcmFieldActionOuterVlanNew: 11728 case bcmFieldActionSrcMacNew: 11729 case bcmFieldActionDstMacNew: 11730 _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeVlan); 11731 _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeVlanCancel); 11732 _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeMacDa); 11733 _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeMacDaCancel); 11734 _FP_ACTIONS_CONFLICT(bcmFieldActionL3Switch); 11735 _FP_ACTIONS_CONFLICT(bcmFieldActionL3SwitchCancel); 11736 break; 11737 case bcmFieldActionDropPrecedence: 11738 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropPrecedence); 11739 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropPrecedence); 11740 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropPrecedence); 11741 break; 11742 case bcmFieldActionRpDropPrecedence: 11743 _FP_ACTIONS_CONFLICT(bcmFieldActionDropPrecedence); 11744 _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropPrecedence); 11745 break; 11746 case bcmFieldActionYpDropPrecedence: 11747 _FP_ACTIONS_CONFLICT(bcmFieldActionDropPrecedence); 11748 _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropPrecedence); 11749 break; 11750 case bcmFieldActionGpDropPrecedence: 11751 _FP_ACTIONS_CONFLICT(bcmFieldActionDropPrecedence); 11752 _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropPrecedence); 11753 break; 11754 case bcmFieldActionColorIndependent: 11755 break; 11756 default: 11757 break; 11758 } 11759 11760 return (BCM_E_NONE); 11761 } 11762 11763 11764 /* 11765 * Function: 11766 * _field_fb_action_support_check 11767 * 11768 * Purpose: 11769 * Check if action is supported by device. 11770 * 11771 * Parameters: 11772 * unit -(IN)BCM device number 11773 * f_ent -(IN)Field entry structure. 11774 * action -(IN) Action to check(bcmFieldActionXXX) 11775 * result -(OUT) 11776 * TRUE - action is supported by device 11777 * FALSE - action is NOT supported by device 11778 * 11779 * Returns: 11780 * BCM_E_XXX 11781 */ 11782 STATIC int 11783 _field_fb_action_support_check(int unit, _field_entry_t *f_ent, 11784 bcm_field_action_t action, int *result) 11785 { 11786 /* Input parameters check */ 11787 if ((NULL == f_ent) || (NULL == result)) { 11788 return (BCM_E_PARAM); 11789 } 11790 if (NULL == f_ent->group) { 11791 return (BCM_E_PARAM); 11792 } 11793 11794 #ifdef BCM_FIREBOLT2_SUPPORT 11795 if (SOC_IS_FIREBOLT2(unit)) { 11796 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 11797 switch (action) { 11798 case bcmFieldActionDrop: 11799 case bcmFieldActionDropCancel: 11800 case bcmFieldActionDscpNew: 11801 case bcmFieldActionRpDrop: 11802 case bcmFieldActionYpDrop: 11803 case bcmFieldActionGpDrop: 11804 case bcmFieldActionRpDropCancel: 11805 case bcmFieldActionYpDropCancel: 11806 case bcmFieldActionGpDropCancel: 11807 case bcmFieldActionRpDscpNew: 11808 case bcmFieldActionYpDscpNew: 11809 case bcmFieldActionGpDscpNew: 11810 case bcmFieldActionRpOuterVlanPrioNew: 11811 case bcmFieldActionYpOuterVlanPrioNew: 11812 case bcmFieldActionGpOuterVlanPrioNew: 11813 case bcmFieldActionInnerVlanPrioNew: 11814 case bcmFieldActionOuterVlanPrioNew: 11815 case bcmFieldActionInnerVlanNew: 11816 case bcmFieldActionOuterVlanNew: 11817 case bcmFieldActionOuterTpidNew: 11818 *result = TRUE; 11819 break; 11820 default: 11821 *result = FALSE; 11822 } 11823 return (BCM_E_NONE); 11824 } 11825 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) { 11826 switch (action) { 11827 case bcmFieldActionOuterVlanNew: 11828 case bcmFieldActionVlanAdd: 11829 case bcmFieldActionOuterVlanPrioNew: 11830 case bcmFieldActionDrop: 11831 case bcmFieldActionDropCancel: 11832 case bcmFieldActionCopyToCpu: 11833 case bcmFieldActionVrfSet: 11834 case bcmFieldActionClassSet: 11835 *result = TRUE; 11836 break; 11837 default: 11838 *result = FALSE; 11839 } 11840 return (BCM_E_NONE); 11841 } 11842 } 11843 #endif /* BCM_FIREBOLT2_SUPPORT */ 11844 11845 switch (action) { 11846 case bcmFieldActionCosQNew: 11847 case bcmFieldActionCosQCpuNew: 11848 case bcmFieldActionColorIndependent: 11849 *result = 11850 (soc_feature(unit, soc_feature_field_wide)) ? TRUE : FALSE; 11851 break; 11852 case bcmFieldActionMirrorOverride: 11853 *result = (soc_feature(unit, soc_feature_field_mirror_ovr)) ? \ 11854 TRUE : FALSE; 11855 break; 11856 case bcmFieldActionSrcMacNew: 11857 *result = FALSE; 11858 break; 11859 case bcmFieldActionDstMacNew: 11860 case bcmFieldActionOuterVlanNew: 11861 #if defined(INCLUDE_L3) /* INCLUDE_L3 */ 11862 *result = (soc_feature(unit, soc_feature_field_action_l2_change) && 11863 soc_feature(unit, soc_feature_l3)) ? \ 11864 TRUE : FALSE; 11865 #else 11866 *result = FALSE; 11867 #endif /* !INCLUDE_L3 */ 11868 break; 11869 case bcmFieldActionPrioPktAndIntCopy: 11870 case bcmFieldActionPrioPktAndIntNew: 11871 case bcmFieldActionPrioPktAndIntTos: 11872 case bcmFieldActionPrioPktAndIntCancel: 11873 case bcmFieldActionPrioPktCopy: 11874 case bcmFieldActionPrioPktNew: 11875 case bcmFieldActionPrioPktTos: 11876 case bcmFieldActionPrioPktCancel: 11877 case bcmFieldActionPrioIntCopy: 11878 case bcmFieldActionPrioIntNew: 11879 case bcmFieldActionPrioIntTos: 11880 case bcmFieldActionPrioIntCancel: 11881 case bcmFieldActionTosNew: 11882 case bcmFieldActionTosCopy: 11883 case bcmFieldActionTosCancel: 11884 case bcmFieldActionDscpNew: 11885 case bcmFieldActionDscpCancel: 11886 case bcmFieldActionCopyToCpu: 11887 case bcmFieldActionCopyToCpuCancel: 11888 case bcmFieldActionSwitchToCpuCancel: 11889 case bcmFieldActionRedirect: 11890 case bcmFieldActionRedirectTrunk: 11891 case bcmFieldActionRedirectCancel: 11892 case bcmFieldActionRedirectPbmp: 11893 case bcmFieldActionEgressMask: 11894 case bcmFieldActionDrop: 11895 case bcmFieldActionDropCancel: 11896 case bcmFieldActionMirrorIngress: 11897 case bcmFieldActionMirrorEgress: 11898 case bcmFieldActionL3ChangeVlan: 11899 case bcmFieldActionL3ChangeVlanCancel: 11900 case bcmFieldActionL3ChangeMacDa: 11901 case bcmFieldActionL3ChangeMacDaCancel: 11902 case bcmFieldActionL3Switch: 11903 case bcmFieldActionL3SwitchCancel: 11904 case bcmFieldActionAddClassTag: 11905 case bcmFieldActionDropPrecedence: 11906 case bcmFieldActionRpDrop: 11907 case bcmFieldActionRpDropCancel: 11908 case bcmFieldActionRpDropPrecedence: 11909 case bcmFieldActionRpCopyToCpu: 11910 case bcmFieldActionRpCopyToCpuCancel: 11911 case bcmFieldActionRpDscpNew: 11912 case bcmFieldActionYpDrop: 11913 case bcmFieldActionYpDropCancel: 11914 case bcmFieldActionYpDropPrecedence: 11915 case bcmFieldActionYpCopyToCpu: 11916 case bcmFieldActionYpCopyToCpuCancel: 11917 case bcmFieldActionYpDscpNew: 11918 case bcmFieldActionGpDrop: 11919 case bcmFieldActionGpDropCancel: 11920 case bcmFieldActionGpDropPrecedence: 11921 case bcmFieldActionGpCopyToCpu: 11922 case bcmFieldActionGpCopyToCpuCancel: 11923 case bcmFieldActionGpDscpNew: 11924 *result = TRUE; 11925 break; 11926 #if defined(BCM_FIREBOLT2_SUPPORT) 11927 case bcmFieldActionRpSwitchToCpuCancel: 11928 *result = (SOC_IS_FIREBOLT2(unit)) ? TRUE: FALSE; 11929 break; 11930 #endif 11931 case bcmFieldActionEcnNew: 11932 *result = (SOC_MEM_FIELD_VALID(unit, FP_POLICY_TABLEm, ECN_CNGf)) ? 11933 TRUE : FALSE; 11934 break; 11935 default: 11936 *result = FALSE; 11937 } 11938 11939 return (BCM_E_NONE); 11940 } 11941 11942 /* 11943 * Function: 11944 * _bcm_field_fb_stat_hw_mode_to_bmap 11945 * 11946 * Description: 11947 * HW counter mode to statistics bitmap. 11948 * Parameters: 11949 * unit - (IN) BCM device number. 11950 * mode - (IN) HW counter mode. 11951 * stage_id - (IN) Stage id. 11952 * hw_bmap - (OUT) Statistics bitmap. 11953 * hw_entry_count - (OUT) Number of counters required. 11954 * Returns: 11955 * BCM_E_XXX 11956 */ 11957 int 11958 _bcm_field_fb_stat_hw_mode_to_bmap(int unit, uint16 mode, 11959 _field_stage_id_t stage_id, 11960 uint32 *hw_bmap, uint8 *hw_entry_count) 11961 { 11962 uint32 value = 0; 11963 /* Input parameters check. */ 11964 if ((NULL == hw_bmap) || (NULL == hw_entry_count)) { 11965 return (BCM_E_PARAM); 11966 } 11967 11968 #if defined (BCM_FIREBOLT2_SUPPORT) 11969 if (_BCM_FIELD_STAGE_EGRESS == stage_id) { 11970 if (1 == mode) { 11971 value |= (1 << (int)bcmFieldStatPackets); 11972 *hw_entry_count = 1; 11973 } 11974 *hw_bmap = value; 11975 return (BCM_E_NONE); 11976 } 11977 #endif /* BCM_FIREBOLT2_SUPPORT */ 11978 11979 /* 11980 * 4 -bit value h/w encoding 11981 * The msb indicates if the counter should be incremented by one or be 11982 * increased by the packet byte count. 11983 * 11984 * The next 3 bits indicate how and when to update one of the two counters 11985 * in the pair. 11986 * MODE UPPER_COUNTER_UPDATE LOWER_COUNTER_UPDATE 11987 * 3b000 NO NO 11988 * 3b001 NO YES 11989 * 3b010 YES NO 11990 * 3b011 IF RED IF NOT RED 11991 * 3b100 IF GREEN IF NOT GREEN 11992 * 3b101 IF GREEN IF RED 11993 * 3b110 IF GREEN IF YELLOW 11994 * 3b111 IF RED IF YELLOW 11995 */ 11996 switch (mode) { 11997 case (0x1): 11998 case (0x2): 11999 value |= (1 << (int)bcmFieldStatPackets); 12000 *hw_entry_count = 1; 12001 break; 12002 case (0x9): 12003 case (0xa): 12004 value |= (1 << (int)bcmFieldStatBytes); 12005 *hw_entry_count = 1; 12006 break; 12007 case (0x3): 12008 value |= (1 << (int)bcmFieldStatRedPackets); 12009 value |= (1 << (int)bcmFieldStatNotRedPackets); 12010 *hw_entry_count = 2; 12011 break; 12012 case (0xb): 12013 value |= (1 << (int)bcmFieldStatRedBytes); 12014 value |= (1 << (int)bcmFieldStatNotRedBytes); 12015 *hw_entry_count = 2; 12016 break; 12017 case (0x4): 12018 value |= (1 << (int)bcmFieldStatGreenPackets); 12019 value |= (1 << (int)bcmFieldStatNotGreenPackets); 12020 *hw_entry_count = 2; 12021 break; 12022 case (0xc): 12023 value |= (1 << (int)bcmFieldStatGreenBytes); 12024 value |= (1 << (int)bcmFieldStatNotGreenBytes); 12025 *hw_entry_count = 2; 12026 break; 12027 case (0x5): 12028 value |= (1 << (int)bcmFieldStatGreenPackets); 12029 value |= (1 << (int)bcmFieldStatRedPackets); 12030 value |= (1 << (int)bcmFieldStatNotYellowPackets); 12031 *hw_entry_count = 2; 12032 break; 12033 case (0xd): 12034 value |= (1 << (int)bcmFieldStatGreenBytes); 12035 value |= (1 << (int)bcmFieldStatRedBytes); 12036 value |= (1 << (int)bcmFieldStatNotYellowBytes); 12037 *hw_entry_count = 2; 12038 break; 12039 case (0x6): 12040 value |= (1 << (int)bcmFieldStatGreenPackets); 12041 value |= (1 << (int)bcmFieldStatYellowPackets); 12042 value |= (1 << (int)bcmFieldStatNotRedPackets); 12043 *hw_entry_count = 2; 12044 break; 12045 case (0xe): 12046 value |= (1 << (int)bcmFieldStatGreenBytes); 12047 value |= (1 << (int)bcmFieldStatYellowBytes); 12048 value |= (1 << (int)bcmFieldStatNotRedBytes); 12049 *hw_entry_count = 2; 12050 break; 12051 case (0x7): 12052 value |= (1 << (int)bcmFieldStatRedPackets); 12053 value |= (1 << (int)bcmFieldStatYellowPackets); 12054 value |= (1 << (int)bcmFieldStatNotGreenPackets); 12055 *hw_entry_count = 2; 12056 break; 12057 case (0xf): 12058 value |= (1 << (int)bcmFieldStatRedBytes); 12059 value |= (1 << (int)bcmFieldStatYellowBytes); 12060 value |= (1 << (int)bcmFieldStatNotGreenBytes); 12061 *hw_entry_count = 2; 12062 break; 12063 default: 12064 *hw_entry_count = 0; 12065 } 12066 *hw_bmap = value; 12067 return (BCM_E_NONE); 12068 } 12069 12070 #if defined(BCM_BRADLEY_SUPPORT) 12071 /* 12072 * Function: 12073 * _field_br_counter_write 12074 * Purpose: 12075 * Update accumulated sw counter and return current counter value. 12076 * Parameters: 12077 * unit - (IN) BCM device number. 12078 * stage_fc - (IN) Stage field control. 12079 * counter_x_mem - (IN) HW memory name. 12080 * mem_x_buf - (IN) Memory table entry. 12081 * counter_y_mem - (IN) HW memory name. 12082 * mem_y_buf - (IN) Memory table entry. 12083 * idx - (IN) Counter index. 12084 * packet_count - (OUT) Packet Counter value 12085 * byte_count - (OUT) Byte Counter value 12086 * Returns: 12087 * BCM_E_XXX 12088 */ 12089 STATIC int 12090 _field_br_counter_write(int unit, soc_mem_t mem, int idx, uint32 *buf, 12091 _field_counter64_collect_t *cntrs64_buf, 12092 uint64 *value) 12093 { 12094 uint32 hw_val[2]; /* Parsed field counter value.*/ 12095 12096 /* Set accumulated SW counter. */ 12097 COMPILER_64_ZERO(cntrs64_buf->accumulated_counter); 12098 COMPILER_64_OR(cntrs64_buf->accumulated_counter, (*value)); 12099 COMPILER_64_SET(cntrs64_buf->last_hw_value, 12100 COMPILER_64_HI(*value) & 0xf, COMPILER_64_LO(*value)); 12101 12102 /* 36 LSB set as a last hw value. */ 12103 hw_val[0] = COMPILER_64_LO(cntrs64_buf->last_hw_value); 12104 hw_val[1] = COMPILER_64_HI(cntrs64_buf->last_hw_value); 12105 soc_mem_field_set(unit, mem, buf, COUNTERf, hw_val); 12106 return soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, buf); 12107 } 12108 12109 12110 /* 12111 * Function: 12112 * _field_br_counter_set 12113 * Purpose: 12114 * Set accumulated sw & hw counters. 12115 * Parameters: 12116 * unit - (IN) BCM device number. 12117 * stage_fc - (IN) Stage field control. 12118 * counter_x_mem - (IN) HW memory name. 12119 * mem_x_buf - (IN) Memory table entry. 12120 * counter_y_mem - (IN) HW memory name. 12121 * mem_y_buf - (IN) Memory table entry. 12122 * idx - (IN) Counter index. 12123 * packet_count - (OUT) Packet Counter value 12124 * byte_count - (OUT) Byte Counter value 12125 * Returns: 12126 * BCM_E_XXX 12127 */ 12128 STATIC int 12129 _field_br_counter_set(int unit, _field_stage_t *stage_fc, 12130 soc_mem_t counter_x_mem, uint32 *mem_x_buf, 12131 soc_mem_t counter_y_mem, uint32 *mem_y_buf, 12132 int idx, uint64 *packet_count, uint64 *byte_count) 12133 { 12134 _field_counter64_collect_t *cntrs64_buf; /* Sw packet counter value */ 12135 uint64 *value; /* Counter accumulated value. */ 12136 int rv; /* Operation return status. */ 12137 12138 /* Input parameters check. */ 12139 if (NULL == stage_fc) { 12140 return (BCM_E_PARAM); 12141 } 12142 12143 value = (NULL == packet_count) ? byte_count : packet_count; 12144 12145 /* Write X pipeline counter value. */ 12146 if (NULL != mem_x_buf) { 12147 cntrs64_buf = &stage_fc->_field_x64_counters[idx]; 12148 rv = _field_br_counter_write(unit, counter_x_mem, idx, mem_x_buf, 12149 cntrs64_buf, value); 12150 BCM_IF_ERROR_RETURN(rv); 12151 } 12152 12153 /* Extract Y pipeline counter value. */ 12154 if (NULL != mem_y_buf) { 12155 COMPILER_64_ZERO(*value); 12156 cntrs64_buf = &stage_fc->_field_y64_counters[idx]; 12157 rv = _field_br_counter_write(unit, counter_y_mem, idx, mem_y_buf, 12158 cntrs64_buf, value); 12159 BCM_IF_ERROR_RETURN(rv); 12160 } 12161 return (BCM_E_NONE); 12162 } 12163 /* 12164 * Function: 12165 * _field_br_counter_read 12166 * Purpose: 12167 * Update accumulated sw counter and return current counter value. 12168 * Parameters: 12169 * unit - (IN) BCM device number. 12170 * stage_fc - (IN) Stage field control. 12171 * counter_x_mem - (IN) HW memory name. 12172 * mem_x_buf - (IN) Memory table entry. 12173 * counter_y_mem - (IN) HW memory name. 12174 * mem_y_buf - (IN) Memory table entry. 12175 * idx - (IN) Counter index. 12176 * packet_count - (OUT) Packet Counter value 12177 * byte_count - (OUT) Byte Counter value 12178 * Returns: 12179 * BCM_E_XXX 12180 */ 12181 STATIC int 12182 _field_br_counter_read(int unit, soc_memacc_t *memacc, uint32 *buf, 12183 _field_counter64_collect_t *cntrs64_buf, 12184 uint64 *count) 12185 { 12186 uint32 hw_val[2]; /* Parsed field counter value.*/ 12187 12188 /* Byte counter. */ 12189 hw_val[0] = hw_val[1] = 0; 12190 soc_memacc_field_get(memacc, buf, hw_val); 12191 12192 _bcm_field_36bit_counter_update(unit, hw_val, cntrs64_buf); 12193 if (NULL != count) { 12194 COMPILER_64_ADD_64(*count, cntrs64_buf->accumulated_counter); 12195 } 12196 return (BCM_E_NONE); 12197 } 12198 12199 12200 /* 12201 * Function: 12202 * _field_br_counter_get 12203 * Purpose: 12204 * Update accumulated sw counter and return current counter value. 12205 * Parameters: 12206 * unit - (IN) BCM device number. 12207 * stage_fc - (IN) Stage field control. 12208 * counter_x_mem - (IN) HW memory name. 12209 * mem_x_buf - (IN) Memory table entry. 12210 * counter_y_mem - (IN) HW memory name. 12211 * mem_y_buf - (IN) Memory table entry. 12212 * idx - (IN) Counter index. 12213 * packet_count - (OUT) Packet Counter value 12214 * byte_count - (OUT) Byte Counter value 12215 * Returns: 12216 * BCM_E_XXX 12217 */ 12218 STATIC int 12219 _field_br_counter_get(int unit, _field_stage_t *stage_fc, 12220 soc_mem_t counter_x_mem, uint32 *mem_x_buf, 12221 soc_mem_t counter_y_mem, uint32 *mem_y_buf, 12222 int idx, uint64 *packet_count, uint64 *byte_count) 12223 { 12224 _field_counter64_collect_t *cntrs64_buf; /* Sw packet counter value */ 12225 uint64 value; /* Counter accumulated value. */ 12226 soc_memacc_t *memacc_x, *memacc_y; /* Memory access cache. */ 12227 12228 /* Input parameters check. */ 12229 if (NULL == stage_fc) { 12230 return (BCM_E_PARAM); 12231 } 12232 12233 sal_memset(&value, 0, sizeof(uint64)); 12234 12235 /* Extract X pipeline counter value. */ 12236 if (NULL != mem_x_buf) { 12237 cntrs64_buf = &stage_fc->_field_x64_counters[idx]; 12238 memacc_x = 12239 &(stage_fc->_field_memacc_counters[_FIELD_COUNTER_MEMACC_COUNTER]); 12240 SOC_IF_ERROR_RETURN 12241 (_field_br_counter_read(unit, memacc_x, mem_x_buf, 12242 cntrs64_buf, &value)); 12243 } 12244 12245 /* Extract Y pipeline counter value. */ 12246 if (NULL != mem_y_buf) { 12247 cntrs64_buf = &stage_fc->_field_y64_counters[idx]; 12248 memacc_y = 12249 &(stage_fc->_field_memacc_counters[_FIELD_COUNTER_MEMACC_COUNTER_Y]); 12250 SOC_IF_ERROR_RETURN 12251 (_field_br_counter_read(unit, memacc_y, mem_y_buf, 12252 cntrs64_buf, &value)); 12253 } 12254 12255 /* Return accumulated value to the caller routine. */ 12256 if (NULL != packet_count) { 12257 COMPILER_64_OR(*packet_count, value); 12258 } 12259 if (NULL != byte_count) { 12260 COMPILER_64_OR(*byte_count, value); 12261 } 12262 return (BCM_E_NONE); 12263 } 12264 #endif /* BCM_BRADLEY_SUPPORT */ 12265 12266 12267 /* 12268 * Function: 12269 * _bcm_field_fb_counter_set 12270 * Purpose: 12271 * Set accumulated sw & hw counters. 12272 * Parameters: 12273 * unit - (IN) BCM device number. 12274 * stage_fc - (IN) Stage field control. 12275 * counter_x_mem - (IN) HW memory name. 12276 * mem_x_buf - (IN) Memory table entry. 12277 * counter_y_mem - (IN) HW memory name. 12278 * mem_y_buf - (IN) Memory table entry. 12279 * idx - (IN) Counter index. 12280 * packet_count - (OUT) Packet Counter value 12281 * byte_count - (OUT) Byte Counter value 12282 * Returns: 12283 * BCM_E_XXX 12284 */ 12285 int 12286 _bcm_field_fb_counter_set(int unit, _field_stage_t *stage_fc, 12287 soc_mem_t counter_x_mem, uint32 *mem_x_buf, 12288 soc_mem_t counter_y_mem, uint32 *mem_y_buf, 12289 int idx, uint64 *packet_count, uint64 *byte_count) 12290 { 12291 _field_counter32_collect_t *cntrs32_buf; /* Sw packet counter value */ 12292 uint32 hw_val[2]; /* Parsed field counter value.*/ 12293 uint64 *value; /* Programmed value. */ 12294 12295 /* Input parameters check. */ 12296 if ((NULL == mem_x_buf) || (INVALIDm == counter_x_mem) || \ 12297 (NULL == stage_fc)) { 12298 return (BCM_E_PARAM); 12299 } 12300 12301 hw_val[0] = hw_val[1] = 0; 12302 /* Set accumulated sw counter. */ 12303 value = (NULL == packet_count) ? byte_count : packet_count; 12304 cntrs32_buf = &stage_fc->_field_x32_counters[idx]; 12305 COMPILER_64_ZERO(cntrs32_buf->accumulated_counter); 12306 COMPILER_64_OR(cntrs32_buf->accumulated_counter, *value); 12307 COMPILER_64_TO_32_LO(cntrs32_buf->last_hw_value, *value); 12308 cntrs32_buf->last_hw_value &= 0x1fffffff; /* 29 bits */ 12309 12310 /* Set lsb hw counter. */ 12311 hw_val[0] = cntrs32_buf->last_hw_value; 12312 hw_val[1] = 0; 12313 soc_mem_field_set(unit, counter_x_mem, mem_x_buf, COUNTERf, hw_val); 12314 return soc_mem_write(unit, counter_x_mem, MEM_BLOCK_ALL, idx, mem_x_buf); 12315 } 12316 12317 12318 /* 12319 * Function: 12320 * _bcm_field_fb_counter_get 12321 * Purpose: 12322 * Update accumulated sw counter and return current counter value. 12323 * Parameters: 12324 * unit - (IN) BCM device number. 12325 * stage_fc - (IN) Stage field control. 12326 * counter_x_mem - (IN) HW memory name. 12327 * mem_x_buf - (IN) Memory table entry. 12328 * counter_y_mem - (IN) HW memory name. 12329 * mem_y_buf - (IN) Memory table entry. 12330 * idx - (IN) Counter index. 12331 * packet_count - (OUT) Packet Counter value 12332 * byte_count - (OUT) Byte Counter value 12333 * Returns: 12334 * BCM_E_XXX 12335 */ 12336 int 12337 _bcm_field_fb_counter_get(int unit, _field_stage_t *stage_fc, 12338 soc_mem_t counter_x_mem, uint32 *mem_x_buf, 12339 soc_mem_t counter_y_mem, uint32 *mem_y_buf, 12340 int idx, uint64 *packet_count, uint64 *byte_count) 12341 { 12342 _field_counter32_collect_t *cntrs32_buf; /* Sw packet counter value */ 12343 soc_memacc_t *memacc; /* Memory access cache. */ 12344 uint32 hw_val[2]; /* Parsed field counter value.*/ 12345 12346 /* Input parameters check. */ 12347 if ((NULL == mem_x_buf) || (INVALIDm == counter_x_mem) || \ 12348 (NULL == stage_fc)) { 12349 return (BCM_E_PARAM); 12350 } 12351 12352 hw_val[0] = hw_val[1] = 0; 12353 cntrs32_buf = &stage_fc->_field_x32_counters[idx]; 12354 memacc = 12355 &(stage_fc->_field_memacc_counters[_FIELD_COUNTER_MEMACC_COUNTER]); 12356 soc_memacc_field_get(memacc, mem_x_buf, hw_val); 12357 _bcm_field_32bit_counter_update(unit, hw_val, cntrs32_buf); 12358 /* Return counter value to caller if (out) pointer was provided. */ 12359 if (NULL != byte_count) { 12360 COMPILER_64_OR(*byte_count, cntrs32_buf->accumulated_counter); 12361 } 12362 if (NULL != packet_count) { 12363 COMPILER_64_OR(*packet_count, cntrs32_buf->accumulated_counter); 12364 } 12365 return (BCM_E_NONE); 12366 } 12367 12368 /* 12369 * Function: 12370 * _bcm_field_fb_counter_get 12371 * Purpose: 12372 * Get hw indexes and flags needed to compose requested statistic. 12373 * 12374 * Parameters: 12375 * unit - (IN) BCM device number. 12376 * f_st - (IN) Field statistics entity. 12377 * stat - (IN) Counter type. 12378 * idx1 - (OUT) Primary counter index. 12379 * idx2 - (OUT) Secondary counter index. 12380 * out_flags - (OUT) Counter flags. 12381 * Returns: 12382 * BCM_E_XXX 12383 */ 12384 int 12385 _bcm_field_fb_stat_index_get(int unit, _field_stat_t *f_st, 12386 bcm_field_stat_t stat, 12387 int *idx1, int *idx2, int *idx3, uint32 *out_flags) 12388 { 12389 _field_stage_t *stage_fc; /* Stage field control structure. */ 12390 int rv; /* Operation return status. */ 12391 uint32 flags = 0; /* _FP_STAT_XXX flags. */ 12392 uint32 counter_tbl_idx; /* Counter table index. */ 12393 int index1 = _FP_INVALID_INDEX; 12394 int index2 = _FP_INVALID_INDEX; 12395 12396 /* Input parameters check. */ 12397 if ((NULL == idx1) || (NULL == idx2) || (NULL == idx3) || 12398 (NULL == out_flags) || (NULL == f_st)) { 12399 return (BCM_E_PARAM); 12400 } 12401 12402 /* Stat entity indexes are adjusted for policy table counter pairs. */ 12403 #if defined (BCM_FIREBOLT2_SUPPORT) 12404 if (SOC_IS_FIREBOLT2(unit) && (_BCM_FIELD_STAGE_EGRESS == f_st->stage_id)) { 12405 /* 5651x doesn't have counter pairs on stage egress. */ 12406 counter_tbl_idx = f_st->hw_index; 12407 } else 12408 #endif /* BCM_FIREBOLT2_SUPPORT */ 12409 { 12410 counter_tbl_idx = f_st->hw_index << 1; 12411 } 12412 12413 switch ((int)stat) { 12414 case bcmFieldStatBytes: 12415 flags |= _FP_STAT_BYTES; 12416 /* passthru */ 12417 /* coverity[MISSING_BREAK: FALSE] */ 12418 case bcmFieldStatPackets: 12419 switch (f_st->hw_mode) { 12420 case (0x2): 12421 case (0xa): 12422 index1 = counter_tbl_idx + 1; 12423 break; 12424 case (0x1): 12425 case (0x9): 12426 index1 = counter_tbl_idx; 12427 break; 12428 default: 12429 return (BCM_E_INTERNAL); 12430 } 12431 break; 12432 case bcmFieldStatGreenBytes: 12433 switch (f_st->hw_mode) { 12434 case (0xc): 12435 case (0xd): 12436 case (0xe): 12437 index1 = counter_tbl_idx + 1; /* Green bytes. */ 12438 break; 12439 default: 12440 return (BCM_E_INTERNAL); 12441 } 12442 flags |= _FP_STAT_BYTES; 12443 break; 12444 case bcmFieldStatGreenPackets: 12445 switch (f_st->hw_mode) { 12446 case (0x4): 12447 case (0x5): 12448 case (0x6): 12449 index1 = counter_tbl_idx + 1; /* Green packets. */ 12450 break; 12451 default: 12452 return (BCM_E_INTERNAL); 12453 } 12454 break; 12455 case bcmFieldStatYellowBytes: 12456 switch (f_st->hw_mode) { 12457 case (0xe): 12458 case (0xf): 12459 index1 = counter_tbl_idx; /* Yellow bytes. */ 12460 break; 12461 default: 12462 return (BCM_E_INTERNAL); 12463 } 12464 flags |= _FP_STAT_BYTES; 12465 break; 12466 case bcmFieldStatYellowPackets: 12467 switch (f_st->hw_mode) { 12468 case (0x6): 12469 case (0x7): 12470 index1 = counter_tbl_idx; /* Yellow packets. */ 12471 break; 12472 default: 12473 return (BCM_E_INTERNAL); 12474 } 12475 break; 12476 case bcmFieldStatRedBytes: 12477 switch (f_st->hw_mode) { 12478 case (0xb): 12479 case (0xf): 12480 index1 = counter_tbl_idx + 1; /* Red bytes. */ 12481 break; 12482 case (0xd): 12483 index1 = counter_tbl_idx; /* Red bytes. */ 12484 break; 12485 default: 12486 return (BCM_E_INTERNAL); 12487 } 12488 flags |= _FP_STAT_BYTES; 12489 break; 12490 case bcmFieldStatRedPackets: 12491 switch (f_st->hw_mode) { 12492 case (0x3): 12493 case (0x7): 12494 index1 = counter_tbl_idx + 1; /* Red packets. */ 12495 break; 12496 case (0x5): 12497 index1 = counter_tbl_idx; /* Red packets. */ 12498 break; 12499 default: 12500 return (BCM_E_INTERNAL); 12501 } 12502 break; 12503 case bcmFieldStatNotGreenBytes: 12504 switch (f_st->hw_mode) { 12505 case (0xc): 12506 index1 = counter_tbl_idx; /* Not Green bytes. */ 12507 break; 12508 case (0xf): 12509 index1 = counter_tbl_idx + 1; /* Red bytes. */ 12510 index2 = counter_tbl_idx; /* Yellow bytes. */ 12511 flags |= _FP_STAT_ADD; 12512 break; 12513 default: 12514 return (BCM_E_INTERNAL); 12515 } 12516 flags |= _FP_STAT_BYTES; 12517 break; 12518 case bcmFieldStatNotGreenPackets: 12519 switch (f_st->hw_mode) { 12520 case (0x4): 12521 index1 = counter_tbl_idx; /* Green packets. */ 12522 break; 12523 case (0x7): 12524 index1 = counter_tbl_idx + 1; /* Red packets. */ 12525 index2 = counter_tbl_idx; /* Yellow packets. */ 12526 flags |= _FP_STAT_ADD; 12527 break; 12528 default: 12529 return (BCM_E_INTERNAL); 12530 } 12531 break; 12532 case bcmFieldStatNotYellowBytes: 12533 switch (f_st->hw_mode) { 12534 case (0xd): 12535 index1 = counter_tbl_idx; /* Green bytes. */ 12536 index2 = counter_tbl_idx + 1; /* Red bytes. */ 12537 flags |= _FP_STAT_ADD; 12538 break; 12539 default: 12540 return (BCM_E_INTERNAL); 12541 } 12542 flags |= _FP_STAT_BYTES; 12543 break; 12544 case bcmFieldStatNotYellowPackets: 12545 switch (f_st->hw_mode) { 12546 case (0x5): 12547 index1 = counter_tbl_idx + 1; /* Green packets. */ 12548 index2 = counter_tbl_idx; /* Red packets. */ 12549 flags |= _FP_STAT_ADD; 12550 break; 12551 default: 12552 return (BCM_E_INTERNAL); 12553 } 12554 break; 12555 case bcmFieldStatNotRedBytes: 12556 switch (f_st->hw_mode) { 12557 case (0xb): 12558 index1 = counter_tbl_idx; /* Not red bytes. */ 12559 break; 12560 case (0xe): 12561 index1 = counter_tbl_idx + 1; /* Yellow bytes. */ 12562 index2 = counter_tbl_idx; /* Green bytes. */ 12563 flags |= _FP_STAT_ADD; 12564 break; 12565 default: 12566 return (BCM_E_INTERNAL); 12567 } 12568 flags |= _FP_STAT_BYTES; 12569 break; 12570 case bcmFieldStatNotRedPackets: 12571 switch (f_st->hw_mode) { 12572 case (0x3): 12573 index1 = counter_tbl_idx; /* Not red packets. */ 12574 break; 12575 case (0x6): 12576 index1 = counter_tbl_idx; /* Yellow packets. */ 12577 index2 = counter_tbl_idx + 1; /* Green packets. */ 12578 flags |= _FP_STAT_ADD; 12579 break; 12580 default: 12581 return (BCM_E_INTERNAL); 12582 } 12583 break; 12584 default: 12585 return (BCM_E_INTERNAL); 12586 } 12587 12588 /* Get stage field control structure. */ 12589 rv = _field_stage_control_get(unit, f_st->stage_id, &stage_fc); 12590 BCM_IF_ERROR_RETURN(rv); 12591 12592 /* Calculate counter table entry index. */ 12593 if (_FP_INVALID_INDEX != index1) { 12594 #if defined (BCM_FIREBOLT2_SUPPORT) 12595 if (SOC_IS_FIREBOLT2(unit) && (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id)) { 12596 *idx1 = index1; 12597 } else 12598 #endif /* BCM_FIREBOLT2_SUPPORT */ 12599 { 12600 *idx1 = 12601 stage_fc->slices[_FP_DEF_INST][f_st->pool_index].start_tcam_idx 12602 + index1; 12603 } 12604 } else { 12605 *idx1 = _FP_INVALID_INDEX; 12606 } 12607 12608 if (_FP_INVALID_INDEX != index2) { 12609 *idx2 = 12610 stage_fc->slices[_FP_DEF_INST][f_st->pool_index].start_tcam_idx 12611 + index2; 12612 } else { 12613 *idx2 = _FP_INVALID_INDEX; 12614 } 12615 *idx3 = _FP_INVALID_INDEX; 12616 *out_flags = flags; 12617 return (BCM_E_NONE); 12618 } 12619 12620 #if defined(BCM_FIREBOLT2_SUPPORT) 12621 /* 12622 * Function: _bcm_field_fb2_qualify_ttl 12623 * 12624 * Purpose: 12625 * Add a field qualification to a filter entry. 12626 * 12627 * Parameters: 12628 * unit - BCM device number 12629 * entry - Field entry array. 12630 * data - Data to qualify with 12631 * mask - Mask to qualify with 12632 * 12633 * Returns: 12634 * BCM_E_XXX Other errors 12635 */ 12636 int 12637 _bcm_field_fb2_qualify_ttl(int unit, bcm_field_entry_t entry, 12638 uint8 data, uint8 mask) 12639 { 12640 _field_entry_t *f_ent; 12641 _field_group_t *fg = NULL; 12642 uint8 result; 12643 int rv; 12644 12645 rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent); 12646 BCM_IF_ERROR_RETURN(rv); 12647 12648 fg = f_ent->group; 12649 /* Check if ttl is part of group qset. */ 12650 rv = _bcm_field_qset_test(bcmFieldQualifyTtl, &fg->qset, &result); 12651 BCM_IF_ERROR_RETURN(rv); 12652 12653 if (result) { 12654 return _field_qualify32(unit, entry, bcmFieldQualifyTtl, data, mask); 12655 } 12656 12657 /* Only intraslice groups support encoded TTL values. */ 12658 if (0 == (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 12659 return BCM_E_PARAM; 12660 } 12661 12662 /* bcmFieldQualifyTtl not present, use TTL_ENCODE (if present) */ 12663 switch (data & mask) { 12664 case 0: 12665 data = 0x0; 12666 mask &= 0x3; 12667 break; 12668 case 1: 12669 data = 0x1; 12670 mask &= 0x3; 12671 break; 12672 case 255: 12673 data = 0x3; 12674 mask &= 0x3; 12675 break; 12676 default: 12677 data = 0x2; 12678 mask &= 0x3; 12679 } 12680 /* Write the TTL_ENCODE data and mask - only for FB 2 */ 12681 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + 1); 12682 BCM_IF_ERROR_RETURN(rv); 12683 12684 f_ent[1].tcam.key[0] &= ~(mask << 6); 12685 f_ent[1].tcam.key[0] |= data << 6; 12686 12687 f_ent[1].tcam.mask[0] &= ~(mask << 6); 12688 f_ent[1].tcam.mask[0] |= mask << 6; 12689 f_ent[1].flags |= _FP_ENTRY_DIRTY; 12690 return BCM_E_NONE; 12691 } 12692 12693 /* 12694 * Function: _bcm_field_fb2_qualify_ttl_get 12695 * 12696 * Purpose: 12697 * Add a field qualification to a filter entry. 12698 * 12699 * Parameters: 12700 * unit - BCM device number 12701 * entry - Field entry array. 12702 * data - Data to qualify with 12703 * mask - Mask to qualify with 12704 * 12705 * Returns: 12706 * BCM_E_XXX Other errors 12707 */ 12708 int 12709 _bcm_field_fb2_qualify_ttl_get(int unit, bcm_field_entry_t entry, 12710 uint8 *data, uint8 *mask) 12711 { 12712 _field_entry_t *f_ent; 12713 _field_group_t *fg = NULL; 12714 uint8 free_tcam = FALSE; 12715 uint8 result; 12716 int rv; 12717 12718 rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent); 12719 BCM_IF_ERROR_RETURN(rv); 12720 12721 fg = f_ent->group; 12722 /* Check if ttl is part of group qset. */ 12723 rv = _bcm_field_qset_test(bcmFieldQualifyTtl, &fg->qset, &result); 12724 BCM_IF_ERROR_RETURN(rv); 12725 12726 if (result) { 12727 return _bcm_field_entry_qualifier_uint8_get(unit, entry, 12728 bcmFieldQualifyTtl, 12729 data, mask); 12730 } 12731 12732 /* Only intraslice groups support encoded TTL values. */ 12733 if (0 == (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) { 12734 return BCM_E_PARAM; 12735 } 12736 12737 if (NULL == f_ent[1].tcam.key) { 12738 free_tcam = TRUE; 12739 } 12740 12741 /* Read the TTL_ENCODE data and mask - only for FB 2 */ 12742 rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + 1); 12743 BCM_IF_ERROR_RETURN(rv); 12744 12745 /* bcmFieldQualifyTtl not present, use TTL_ENCODE (if present) */ 12746 switch ((f_ent[1].tcam.key[0] >> 6) & 0x3) { 12747 case 0: 12748 *data = 0x0; 12749 *mask = 0xff; 12750 break; 12751 case 1: 12752 *data = 0x1; 12753 *mask &= 0xff; 12754 break; 12755 case 3: 12756 *data = 0xff; 12757 *mask &= 0xff; 12758 break; 12759 default: 12760 return (BCM_E_UNAVAIL); 12761 } 12762 if (free_tcam) { 12763 _bcm_field_qual_tcam_key_mask_free(unit, f_ent + 1); 12764 } 12765 return BCM_E_NONE; 12766 } 12767 #endif /* BCM_FIREBOLT2_SUPPORT */ 12768 12769 /* 12770 * Function: 12771 * _bcm_field_fb_selcode_get 12772 * Purpose: 12773 * Finds a 4-tuple of select encodings that will satisfy the 12774 * requested qualifier set (Qset). 12775 * Parameters: 12776 * unit - (IN) BCM unit number. 12777 * stage_fc - (IN) Stage Field control structure. 12778 * qset_req - (IN) Client qualifier set. 12779 * fg - (IN/OUT)Select code information filled into the group. 12780 * 12781 * Returns: 12782 * BCM_E_XXX 12783 */ 12784 int 12785 _bcm_field_fb_selcode_get(int unit, _field_stage_t *stage_fc, 12786 bcm_field_qset_t *qset_req, 12787 _field_group_t *fg) 12788 { 12789 int rv; /* Operation return status. */ 12790 12791 /* Input parameters check. */ 12792 if ((NULL == fg) || (NULL == qset_req) || (NULL == stage_fc)) { 12793 return (BCM_E_PARAM); 12794 } 12795 12796 /* Egress qualifiers are selected based on Key. */ 12797 switch (stage_fc->stage_id) { 12798 #if defined(BCM_FIREBOLT2_SUPPORT) 12799 case _BCM_FIELD_STAGE_EGRESS: 12800 rv = _field_fb_egress_selcode_get(unit, stage_fc, qset_req, fg); 12801 break; 12802 #endif /* BCM_FIREBOLT2_SUPPORT */ 12803 default: 12804 rv = _bcm_field_selcode_get(unit, stage_fc, qset_req, fg); 12805 } 12806 return (rv); 12807 } 12808 12809 /* 12810 * Function: _bcm_field_fb_udf_ipprotocol_delete_all 12811 * 12812 * Purpose: 12813 * Delete all the UDF ip protocol match values. 12814 * 12815 * Parameters: 12816 * unit - (IN) BCM device number 12817 * Returns: 12818 * BCM_E_XXX 12819 */ 12820 int 12821 _bcm_field_fb_udf_ipprotocol_delete_all(int unit) 12822 { 12823 int index; 12824 12825 if (0 == SOC_REG_IS_VALID(unit, UDF_IPPROTO_MATCHr)) { 12826 return (BCM_E_NONE); 12827 } 12828 12829 for (index = 0; index < _FP_DATA_IP_PROTOCOL_MAX; index++) { 12830 SOC_IF_ERROR_RETURN(WRITE_UDF_IPPROTO_MATCHr(unit, index, 0)); 12831 } 12832 return (BCM_E_NONE); 12833 } 12834 12835 /* 12836 * Function: _bcm_field_fb_udf_ip_protocol_set 12837 * 12838 * Purpose: 12839 * Set the UDF Ip Protocol match value. 12840 * 12841 * Parameters: 12842 * unit - (IN) BCM device number 12843 * index - (IN) 0->7, Ethertype match index 12844 * flags - (IN) IP version match is enabled 12845 * proto - (IN) IP protocol id. 12846 * 12847 * Returns: 12848 * BCM_E_XXX 12849 */ 12850 int 12851 _bcm_field_fb_udf_ipprotocol_set(int unit, int index, uint32 flags, uint8 proto) 12852 { 12853 uint32 reg_val = 0; 12854 uint32 ip4_enable = 0; 12855 uint32 ip6_enable = 0; 12856 uint32 protocol = 0; 12857 12858 if (0 == SOC_REG_IS_VALID(unit, UDF_IPPROTO_MATCHr)) { 12859 return (BCM_E_UNAVAIL); 12860 } 12861 12862 /* Range check index. */ 12863 if (index < 0 || (_FP_DATA_IP_PROTOCOL_MAX <= index)) { 12864 return (BCM_E_PARAM); 12865 } 12866 12867 protocol = proto; 12868 switch (flags) { 12869 case 0: 12870 break; 12871 case BCM_FIELD_DATA_FORMAT_IP4: 12872 ip4_enable = TRUE; 12873 break; 12874 case BCM_FIELD_DATA_FORMAT_IP6: 12875 ip6_enable = TRUE; 12876 break; 12877 case (BCM_FIELD_DATA_FORMAT_IP4 | BCM_FIELD_DATA_FORMAT_IP6): 12878 ip4_enable = ip6_enable = TRUE; 12879 break; 12880 default: 12881 return (BCM_E_PARAM); 12882 } 12883 12884 /* Update UDF_IPPROTO_MATCHr register. */ 12885 SOC_IF_ERROR_RETURN(READ_UDF_IPPROTO_MATCHr(unit, index, ®_val)); 12886 soc_reg_field_set(unit, UDF_IPPROTO_MATCHr, ®_val, IPV4ENABLEf, ip4_enable); 12887 soc_reg_field_set(unit, UDF_IPPROTO_MATCHr, ®_val, IPV6ENABLEf, ip6_enable); 12888 soc_reg_field_set(unit, UDF_IPPROTO_MATCHr, ®_val, PROTOCOLf, protocol); 12889 SOC_IF_ERROR_RETURN(WRITE_UDF_IPPROTO_MATCHr(unit, index, reg_val)); 12890 12891 return (BCM_E_NONE); 12892 } 12893 12894 /* 12895 * Function: _bcm_field_fb_udf_ip_protocol_get 12896 * 12897 * Purpose: 12898 * Get the UDF Ip Protocol match value. 12899 * 12900 * Parameters: 12901 * unit - (IN) BCM device number 12902 * index - (IN) 0->7, Ethertype match index 12903 * flags - (OUT) IP version match is enabled 12904 * proto - (OUT) IP protocol id. 12905 * Returns: 12906 * BCM_E_XXX 12907 */ 12908 int 12909 _bcm_field_fb_udf_ipprotocol_get(int unit, int index, uint32 *flags, uint8 *proto) 12910 { 12911 uint32 reg_val = 0; 12912 12913 /* Input parameters check. */ 12914 if ((NULL == flags) || (NULL == proto)) { 12915 return (BCM_E_PARAM); 12916 } 12917 12918 if (0 == SOC_REG_IS_VALID(unit, UDF_IPPROTO_MATCHr)) { 12919 return (BCM_E_UNAVAIL); 12920 } 12921 12922 /* Range check index. */ 12923 if (index < 0 || (_FP_DATA_IP_PROTOCOL_MAX <= index)) { 12924 return (BCM_E_PARAM); 12925 } 12926 12927 SOC_IF_ERROR_RETURN(READ_UDF_IPPROTO_MATCHr(unit, index, ®_val)); 12928 12929 *flags = 0; 12930 if (soc_reg_field_get(unit, UDF_IPPROTO_MATCHr, reg_val, IPV4ENABLEf)) { 12931 *flags |= BCM_FIELD_DATA_FORMAT_IP4; 12932 } 12933 if (soc_reg_field_get(unit, UDF_IPPROTO_MATCHr, reg_val, IPV6ENABLEf)) { 12934 *flags |= BCM_FIELD_DATA_FORMAT_IP6; 12935 } 12936 12937 *proto = soc_reg_field_get(unit, UDF_IPPROTO_MATCHr, reg_val, PROTOCOLf); 12938 12939 return (BCM_E_NONE); 12940 } 12941 12942 /* 12943 * Function: _bcm_field_fb_udf_ethertype_delete_all 12944 * 12945 * Purpose: 12946 * Delete all the UDF ethertype match values. 12947 * 12948 * Parameters: 12949 * unit - (IN) BCM device number 12950 * Returns: 12951 * BCM_E_XXX 12952 */ 12953 int 12954 _bcm_field_fb_udf_ethertype_delete_all(int unit) 12955 { 12956 int index; 12957 12958 if (0 == SOC_REG_IS_VALID(unit, UDF_ETHERTYPE_MATCHr)) { 12959 return (BCM_E_NONE); 12960 } 12961 12962 for (index = 0; index < _FP_DATA_ETHERTYPE_MAX; index++) { 12963 SOC_IF_ERROR_RETURN(WRITE_UDF_ETHERTYPE_MATCHr(unit, index, 0)); 12964 } 12965 return (BCM_E_NONE); 12966 } 12967 12968 /* 12969 * Function: _bcm_field_fb_udf_ethertype_set 12970 * 12971 * Purpose: 12972 * Set the UDF Ethertype match value. 12973 * 12974 * Parameters: 12975 * unit - (IN) BCM device number 12976 * index - (IN) 0->7, Ethertype match index 12977 * frametype - (IN) BCM_FIELD_DATA_FORMAT_L2_XXX 12978 * ethertype - (IN) Ethertype value to match 12979 * 12980 * Returns: 12981 * BCM_E_XXX 12982 */ 12983 int 12984 _bcm_field_fb_udf_ethertype_set(int unit, int index, 12985 bcm_port_frametype_t frametype, 12986 bcm_port_ethertype_t ethertype) 12987 { 12988 uint32 reg_val; 12989 uint32 enable; 12990 uint32 frame_type; 12991 12992 if (0 == SOC_REG_IS_VALID(unit, UDF_ETHERTYPE_MATCHr)) { 12993 return (BCM_E_UNAVAIL); 12994 } 12995 12996 /* Range check index. */ 12997 if (index < 0 || (_FP_DATA_ETHERTYPE_MAX <= index)) { 12998 return (BCM_E_PARAM); 12999 } 13000 13001 switch (frametype) { 13002 case 0: 13003 enable = FALSE; 13004 ethertype = 0; 13005 frame_type = 0; 13006 break; 13007 case BCM_PORT_FRAMETYPE_ETHER2: 13008 frame_type = 0; 13009 enable = TRUE; 13010 break; 13011 case BCM_PORT_FRAMETYPE_SNAP: 13012 frame_type = 1; 13013 enable = TRUE; 13014 break; 13015 case BCM_PORT_FRAMETYPE_LLC: 13016 frame_type = 2; 13017 enable = TRUE; 13018 break; 13019 default: 13020 return (BCM_E_PARAM); 13021 } 13022 13023 /* Update UDF_ETHERTYPE_MATCHr register. */ 13024 SOC_IF_ERROR_RETURN(READ_UDF_ETHERTYPE_MATCHr(unit, index, ®_val)); 13025 soc_reg_field_set(unit, UDF_ETHERTYPE_MATCHr, ®_val, ENABLEf, enable); 13026 soc_reg_field_set(unit, UDF_ETHERTYPE_MATCHr, ®_val, L2_PACKET_FORMATf, 13027 frame_type); 13028 soc_reg_field_set(unit, UDF_ETHERTYPE_MATCHr, ®_val, ETHERTYPEf, 13029 (uint32)ethertype); 13030 SOC_IF_ERROR_RETURN(WRITE_UDF_ETHERTYPE_MATCHr(unit, index, reg_val)); 13031 return (BCM_E_NONE); 13032 } 13033 13034 /* 13035 * Function: _bcm_field_fb_udf_ethertype_get 13036 * 13037 * Purpose: 13038 * Set the UDF Ethertype match value. 13039 * 13040 * Parameters: 13041 * unit - (IN) BCM device number 13042 * index - (IN) 0->7, Ethertype match index 13043 * frametype - (OUT) BCM_FIELD_DATA_FORMAT_L2_XXX 13044 * ethertype - (OUT) Ethertype value to match 13045 * 13046 * Returns: 13047 * BCM_E_XXX 13048 */ 13049 int 13050 _bcm_field_fb_udf_ethertype_get(int unit, int index, 13051 bcm_port_frametype_t *frametype, 13052 bcm_port_ethertype_t *ethertype) 13053 { 13054 uint32 reg_val = 0; 13055 uint32 enable; 13056 uint32 frame_type; 13057 13058 if (0 == SOC_REG_IS_VALID(unit, UDF_ETHERTYPE_MATCHr)) { 13059 return (BCM_E_UNAVAIL); 13060 } 13061 13062 /* Range check index. */ 13063 if (index < 0 || (_FP_DATA_ETHERTYPE_MAX <= index)) { 13064 return (BCM_E_PARAM); 13065 } 13066 13067 /* Input parameters check */ 13068 if ((NULL == frametype) || (NULL == ethertype)) { 13069 return (BCM_E_PARAM); 13070 } 13071 13072 SOC_IF_ERROR_RETURN(READ_UDF_ETHERTYPE_MATCHr(unit, index, ®_val)); 13073 13074 enable = soc_reg_field_get(unit, UDF_ETHERTYPE_MATCHr, reg_val, 13075 ENABLEf); 13076 if (enable) { 13077 frame_type = soc_reg_field_get(unit, UDF_ETHERTYPE_MATCHr, reg_val, 13078 L2_PACKET_FORMATf); 13079 13080 switch (frame_type) { 13081 case 0: 13082 *frametype = BCM_PORT_FRAMETYPE_ETHER2; 13083 break; 13084 case 1: 13085 *frametype = BCM_PORT_FRAMETYPE_SNAP; 13086 break; 13087 case 2: 13088 *frametype = BCM_PORT_FRAMETYPE_LLC; 13089 break; 13090 default: 13091 return (BCM_E_PARAM); 13092 } 13093 13094 *ethertype = soc_reg_field_get(unit, UDF_ETHERTYPE_MATCHr, reg_val, 13095 ETHERTYPEf); 13096 } else { 13097 *frametype = 0; 13098 *ethertype = 0; 13099 } 13100 return (BCM_E_NONE); 13101 } 13102 13103 /* 13104 * Function: 13105 * _field_fb_udf_idx_to_l2_format 13106 * Purpose: 13107 * Translate udf offset index l2 portion to packet l2 format. 13108 * Parameters: 13109 * unit - (IN) Bcm device number. 13110 * idx - (IN) Udf offset table index. 13111 * l2 - (OUT)Packet L2 format specification. 13112 * Returns: 13113 * BCM_E_XXX 13114 */ 13115 STATIC int 13116 _field_fb_udf_idx_to_l2_format(int unit, int idx, uint16 *l2) 13117 { 13118 int l2_idx; /* L2 portion of udf offset table index. */ 13119 13120 /* Input parameters check. */ 13121 if (NULL == l2) { 13122 return (BCM_E_PARAM); 13123 } 13124 13125 if (SOC_IS_TR_VL(unit)) { 13126 l2_idx = idx >> 5; 13127 } else if (SOC_IS_SC_CQ(unit)) { 13128 l2_idx = idx >> 4; 13129 } else { 13130 l2_idx = idx >> 3; 13131 } 13132 13133 switch (l2_idx & 0x3) { 13134 case 0: 13135 *l2 = BCM_FIELD_DATA_FORMAT_L2_ETH_II; 13136 break; 13137 case 1: 13138 *l2 = BCM_FIELD_DATA_FORMAT_L2_SNAP; 13139 break; 13140 case 2: 13141 *l2 = BCM_FIELD_DATA_FORMAT_L2_LLC; 13142 break; 13143 default: 13144 /* for case 3 */ 13145 *l2 = _BCM_FIELD_DATA_FORMAT_ETHERTYPE; 13146 break; 13147 } 13148 return (BCM_E_NONE); 13149 } 13150 13151 13152 /* 13153 * Function: 13154 * _field_fb_udf_idx_to_vlan_format 13155 * Purpose: 13156 * Translate udf offset index vlan portion to packet vlan tag format. 13157 * Parameters: 13158 * unit - (IN) Bcm device number. 13159 * idx - (IN) Udf offset table index. 13160 * vlan - (OUT)Packet vlan format specification. 13161 * Returns: 13162 * BCM_E_XXX 13163 */ 13164 STATIC int 13165 _field_fb_udf_idx_to_vlan_format(int unit, int idx, uint16 *vlan) 13166 { 13167 int vlan_idx; /* Vlan portion of udf offset table index. */ 13168 13169 /* Input parameters check. */ 13170 if (NULL == vlan) { 13171 return (BCM_E_PARAM); 13172 } 13173 13174 if (SOC_IS_TR_VL(unit)) { 13175 vlan_idx = idx >> 7; 13176 } else if (SOC_IS_SC_CQ(unit)) { 13177 vlan_idx = idx >> 6; 13178 } else { 13179 vlan_idx = idx >> 5; 13180 } 13181 13182 switch (vlan_idx & 0x3) { 13183 case 0: 13184 *vlan = BCM_FIELD_DATA_FORMAT_VLAN_NO_TAG; 13185 break; 13186 case 1: 13187 *vlan = BCM_FIELD_DATA_FORMAT_VLAN_SINGLE_TAGGED; 13188 break; 13189 case 2: 13190 *vlan = BCM_FIELD_DATA_FORMAT_VLAN_DOUBLE_TAGGED; 13191 break; 13192 default: 13193 return (BCM_E_EMPTY); 13194 } 13195 return (BCM_E_NONE); 13196 } 13197 13198 /* 13199 * Function: 13200 * _field_fb_udf_idx_to_ip_format 13201 * Purpose: 13202 * Translate udf offset index ip portion to packet ip format. 13203 * Parameters: 13204 * unit - (IN) Bcm device number. 13205 * idx - (IN) Udf offset table index. 13206 * pkt_fmt - (OUT)Packet format specification. 13207 * Returns: 13208 * BCM_E_XXX 13209 */ 13210 STATIC int 13211 _field_fb_udf_idx_to_ip_format(int unit, int idx, 13212 bcm_field_data_packet_format_t *pkt_fmt) 13213 { 13214 int ip_idx; /* Ip portion of udf offset table index. */ 13215 13216 /* Input parameters check. */ 13217 if (NULL == pkt_fmt) { 13218 return (BCM_E_PARAM); 13219 } 13220 13221 if (SOC_IS_TR_VL(unit)) { 13222 ip_idx = idx & 0x1f; 13223 } else if (SOC_IS_SC_CQ(unit)) { 13224 ip_idx = idx & 0xf; 13225 } else { 13226 ip_idx = idx & 0x7; 13227 } 13228 13229 /* Init tunnel/ip header version to none. */ 13230 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_NONE; 13231 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP_NONE; 13232 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP_NONE; 13233 13234 switch (ip_idx) { 13235 case 0: 13236 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_NONE; 13237 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4; 13238 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP_NONE; 13239 break; 13240 case 1: 13241 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_NONE; 13242 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6; 13243 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP_NONE; 13244 break; 13245 case 2: 13246 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP; 13247 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4; 13248 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP4; 13249 break; 13250 case 3: 13251 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP; 13252 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4; 13253 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP6; 13254 break; 13255 case 4: 13256 if (SOC_IS_TRX(unit)) { 13257 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP; 13258 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6; 13259 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP4; 13260 } 13261 break; 13262 case 5: 13263 if (SOC_IS_TRX(unit)) { 13264 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP; 13265 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6; 13266 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP6; 13267 } else { 13268 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0; 13269 } 13270 break; 13271 case 6: 13272 if (SOC_IS_TRX(unit)) { 13273 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_GRE; 13274 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4; 13275 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP4; 13276 } else { 13277 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1; 13278 } 13279 break; 13280 case 7: 13281 if (SOC_IS_TRX(unit)) { 13282 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_GRE; 13283 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4; 13284 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP6; 13285 } else { 13286 return (BCM_E_EMPTY); 13287 } 13288 break; 13289 case 8: 13290 if (SOC_IS_TRX(unit)) { 13291 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_GRE; 13292 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6; 13293 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP4; 13294 } else { 13295 return (BCM_E_EMPTY); 13296 } 13297 break; 13298 case 9: 13299 if (SOC_IS_TRX(unit)) { 13300 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_GRE; 13301 pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6; 13302 pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP6; 13303 } else { 13304 return (BCM_E_EMPTY); 13305 } 13306 break; 13307 case 0xa: 13308 if (SOC_IS_SC_CQ(unit)) { 13309 /* _BCM_FIELD_USER_IP_NOTUSED */ 13310 } else if (SOC_IS_TR_VL(unit)) { 13311 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS; 13312 pkt_fmt->mpls = BCM_FIELD_DATA_FORMAT_MPLS_ONE_LABEL; 13313 } else { 13314 return (BCM_E_EMPTY); 13315 } 13316 break; 13317 case 0xb: 13318 if (SOC_IS_SC_CQ(unit)) { 13319 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0; 13320 } else if (SOC_IS_TR_VL(unit)) { 13321 pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS; 13322 pkt_fmt->mpls = BCM_FIELD_DATA_FORMAT_MPLS_TWO_LABELS; 13323 } else { 13324 return (BCM_E_EMPTY); 13325 } 13326 break; 13327 case 0xc: 13328 if (SOC_IS_SC_CQ(unit)) { 13329 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1; 13330 } 13331 /* SOC_IS_TR_VL: _BCM_FIELD_USER_IP_NOTUSED */ 13332 break; 13333 case 0xd: 13334 if (SOC_IS_SC_CQ(unit)) { 13335 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL0; 13336 } else if (SOC_IS_TR_VL(unit)) { 13337 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0; 13338 } else { 13339 return (BCM_E_EMPTY); 13340 } 13341 break; 13342 case 0xe: 13343 if (SOC_IS_SC_CQ(unit)) { 13344 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL1; 13345 } else if (SOC_IS_TR_VL(unit)) { 13346 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1; 13347 } else { 13348 return (BCM_E_EMPTY); 13349 } 13350 break; 13351 case 0xf: 13352 if (SOC_IS_TR_VL(unit)) { 13353 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL0; 13354 } else { 13355 return (BCM_E_EMPTY); 13356 } 13357 break; 13358 case 0x10: 13359 if (SOC_IS_TR_VL(unit)) { 13360 pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL1; 13361 } else { 13362 return (BCM_E_EMPTY); 13363 } 13364 break; 13365 default: 13366 return (BCM_E_EMPTY); 13367 } 13368 return (BCM_E_NONE); 13369 } 13370 13371 /* 13372 * Function: 13373 * _field_udf_offset_idx_to_packet_format 13374 * Purpose: 13375 * Translate udf offset table index to packet format. 13376 * Parameters: 13377 * unit - (IN) Bcm device number. 13378 * idx - (IN) Udf offset table index. 13379 * pkt_fmt - (OUT)Packet format specification. 13380 * Returns: 13381 * BCM_E_XXX 13382 */ 13383 STATIC int 13384 _field_fb_udf_offset_idx_to_packet_format(int unit, int idx, 13385 bcm_field_data_packet_format_t *pkt_fmt) 13386 { 13387 int rv; /* Operation return status. */ 13388 13389 /* Input parameters check. */ 13390 if (NULL == pkt_fmt) { 13391 return (BCM_E_PARAM); 13392 } 13393 13394 /* parse L2 format */ 13395 rv = _field_fb_udf_idx_to_l2_format(unit, idx, &pkt_fmt->l2); 13396 BCM_IF_ERROR_RETURN(rv); 13397 13398 /* Ignore ethertype based indexes. */ 13399 if (pkt_fmt->l2 == _BCM_FIELD_DATA_FORMAT_ETHERTYPE) { 13400 return (BCM_E_EMPTY); 13401 } 13402 13403 /* parse vlan tag format */ 13404 rv = _field_fb_udf_idx_to_vlan_format(unit, idx, &pkt_fmt->vlan_tag); 13405 BCM_IF_ERROR_RETURN(rv); 13406 13407 /* parse L3 tunnel type/ Ip headers format */ 13408 rv = _field_fb_udf_idx_to_ip_format(unit, idx, pkt_fmt); 13409 BCM_IF_ERROR_RETURN(rv); 13410 13411 /* Ignore ip protcol based indexes. */ 13412 if ((pkt_fmt->outer_ip == _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0) || 13413 (pkt_fmt->outer_ip == _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1) || 13414 (pkt_fmt->outer_ip == _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL0) || 13415 (pkt_fmt->outer_ip == _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL1)) { 13416 return (BCM_E_EMPTY); 13417 } 13418 13419 return (BCM_E_NONE); 13420 } 13421 13422 /* 13423 * Function: 13424 * _field_fb_data_offset_install 13425 * Purpose: 13426 * Write the info in udf_spec to hardware 13427 * Parameters: 13428 * unit - (IN) BCM device number. 13429 * f_dq - (IN) Data qualifier structure. 13430 * tbl_idx - (IN) FP_UDF_OFFSETm table index. 13431 * offset - (IN) Word offset value. 13432 * Returns: 13433 * BCM_E_PARAM - UDF number or User number out of range 13434 * BCM_E_NONE 13435 * Notes: 13436 * Calling function should have unit's lock. 13437 */ 13438 STATIC int 13439 _field_fb_data_offset_install(int unit, _field_data_qualifier_t *f_dq, 13440 int tbl_idx, int offset) 13441 { 13442 fp_udf_offset_entry_t tbl_entry; /* HW table buffer. */ 13443 uint32 word_offset; /* Offset iterator. */ 13444 int idx; /* Data qualifier words iterator. */ 13445 int offset_idx; /* Swapped udf_offsetX number. */ 13446 uint32 value; /* HW buffer value. */ 13447 13448 static soc_field_t off_field[] = {UDF1_OFFSET0f, UDF1_OFFSET1f, 13449 UDF1_OFFSET2f, UDF1_OFFSET3f, 13450 UDF2_OFFSET0f, UDF2_OFFSET1f, 13451 UDF2_OFFSET2f, UDF2_OFFSET3f}; 13452 13453 static soc_field_t option_field[] = {UDF1_ADD_IPV4_OPTIONS0f, 13454 UDF1_ADD_IPV4_OPTIONS1f, 13455 UDF1_ADD_IPV4_OPTIONS2f, 13456 UDF1_ADD_IPV4_OPTIONS3f, 13457 UDF2_ADD_IPV4_OPTIONS0f, 13458 UDF2_ADD_IPV4_OPTIONS1f, 13459 UDF2_ADD_IPV4_OPTIONS2f, 13460 UDF2_ADD_IPV4_OPTIONS3f}; 13461 13462 static soc_field_t gre_option_field[] = {UDF1_ADD_GRE_OPTIONS0f, 13463 UDF1_ADD_GRE_OPTIONS1f, 13464 UDF1_ADD_GRE_OPTIONS2f, 13465 UDF1_ADD_GRE_OPTIONS3f, 13466 UDF2_ADD_GRE_OPTIONS0f, 13467 UDF2_ADD_GRE_OPTIONS1f, 13468 UDF2_ADD_GRE_OPTIONS2f, 13469 UDF2_ADD_GRE_OPTIONS3f}; 13470 13471 /* Input parameters check. */ 13472 if (NULL == f_dq) { 13473 return (BCM_E_PARAM); 13474 } 13475 13476 /* index sanity check. */ 13477 if ((tbl_idx < soc_mem_index_min(unit, FP_UDF_OFFSETm)) || 13478 (tbl_idx > soc_mem_index_max(unit, FP_UDF_OFFSETm))) { 13479 return (BCM_E_PARAM); 13480 } 13481 13482 /* Read udf offset table enty.*/ 13483 BCM_IF_ERROR_RETURN 13484 (READ_FP_UDF_OFFSETm(unit, MEM_BLOCK_ANY, tbl_idx, &tbl_entry)); 13485 13486 word_offset = (offset < 0) ? 0 : (uint32)offset; 13487 13488 /* Find a proper word to insert the data. */ 13489 for (idx = 0; idx <= _FP_DATA_DATA1_WORD_MAX; idx++) { 13490 if (0 == (f_dq->hw_bmap & (1 << idx))) { 13491 continue; 13492 } 13493 13494 if (word_offset > 31) { 13495 return BCM_E_PARAM; 13496 } 13497 13498 offset_idx = idx; 13499 soc_FP_UDF_OFFSETm_field32_set(unit, &tbl_entry, off_field[offset_idx], 13500 word_offset); 13501 13502 /* Set the UDFn_ADD_IPV4_OPTIONSm bit accordingly */ 13503 value = (f_dq->flags & 13504 BCM_FIELD_DATA_QUALIFIER_OFFSET_IP4_OPTIONS_ADJUST) ? TRUE : FALSE; 13505 soc_FP_UDF_OFFSETm_field32_set(unit, &tbl_entry, 13506 option_field[offset_idx], value); 13507 13508 /* Set the UDFn_ADD_IPV4_OPTIONSm bit accordingly */ 13509 if (SOC_MEM_FIELD_VALID(unit, FP_UDF_OFFSETm, UDF1_ADD_GRE_OPTIONS0f)) { 13510 value = (f_dq->flags & 13511 BCM_FIELD_DATA_QUALIFIER_OFFSET_GRE_OPTIONS_ADJUST) ? TRUE : FALSE; 13512 soc_FP_UDF_OFFSETm_field32_set(unit, &tbl_entry, 13513 gre_option_field[offset_idx], value); 13514 } 13515 13516 if (offset >= 0) { 13517 /* 13518 * If word_offset is 31, reset the offset to 0 for 126th and 127th byte 13519 * of the incoming packet 13520 */ 13521 if (word_offset == 31) { 13522 word_offset = 0; 13523 } else { 13524 word_offset++; 13525 } 13526 } 13527 } 13528 13529 /* Write back udf offset table enty.*/ 13530 BCM_IF_ERROR_RETURN 13531 (WRITE_FP_UDF_OFFSETm(unit, MEM_BLOCK_ALL, tbl_idx, &tbl_entry)); 13532 13533 return BCM_E_NONE; 13534 } 13535 13536 /* 13537 * Function: 13538 * _field_fb_data_qualifier_ethertype_install 13539 * Purpose: 13540 * Add ethertype based offset to data qualifier object. 13541 * Parameters: 13542 * unit - (IN) bcm device. 13543 * f_dq - (IN) Data qualifier descriptor. 13544 * etype_idx - (IN) Ethertype index. 13545 * etype - (IN) Ethertype based offset specification. 13546 * Returns: 13547 * BCM_E_XXX 13548 */ 13549 STATIC int 13550 _field_fb_data_qualifier_ethertype_install (int unit, 13551 _field_data_qualifier_t *f_dq, 13552 uint8 idx, 13553 _field_data_ethertype_t *etype) 13554 { 13555 bcm_port_frametype_t frametype; /* HW register encoding. */ 13556 int idx_mask; /* Ethertype id index mask. */ 13557 int offset; /* Adjusted word offset. */ 13558 int tbl_idx; /* Udf offset table iterator. */ 13559 uint16 l2; /* L2 packet format. */ 13560 uint16 vlan_tag; /* Vlan packet format. */ 13561 13562 int rv; /* Operation return status. */ 13563 uint8 avail = 0; 13564 13565 13566 /* Input parameters check. */ 13567 if ((NULL == f_dq) || (NULL == etype)) { 13568 return (BCM_E_PARAM); 13569 } 13570 /* Verify UDF offset memory is valid. */ 13571 if (0 == SOC_MEM_IS_VALID(unit, FP_UDF_OFFSETm)){ 13572 return (BCM_E_UNAVAIL); 13573 } 13574 13575 switch (etype->l2) { 13576 case BCM_FIELD_DATA_FORMAT_L2_ETH_II: 13577 frametype = BCM_PORT_FRAMETYPE_ETHER2; 13578 break; 13579 case BCM_FIELD_DATA_FORMAT_L2_SNAP: 13580 frametype = BCM_PORT_FRAMETYPE_SNAP; 13581 break; 13582 case BCM_FIELD_DATA_FORMAT_L2_LLC: 13583 frametype = BCM_PORT_FRAMETYPE_LLC; 13584 break; 13585 default: 13586 frametype = 0; 13587 } 13588 13589 13590 /* Get ethertype index mask. */ 13591 if (SOC_IS_TR_VL(unit)) { 13592 idx_mask = 0x1f; /* Ethertype is 5 lower bits of udf index. */ 13593 } else { 13594 idx_mask = 0x7; /* Ethertype is 3 lower bits of udf index. */ 13595 } 13596 13597 /* Calculate offset */ 13598 offset = f_dq->offset + etype->relative_offset; 13599 if ((offset < 0) || ((offset + f_dq->length) > _FP_DATA_OFFSET_MAX)) { 13600 return (BCM_E_PARAM); 13601 } 13602 offset = ((offset + 2) % 128) / 4; 13603 13604 /* Update ethertype match register. */ 13605 rv = _bcm_field_fb_udf_ethertype_set(unit, idx, frametype, etype->ethertype); 13606 BCM_IF_ERROR_RETURN(rv); 13607 13608 for (tbl_idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 13609 tbl_idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); tbl_idx++) { 13610 13611 if ((tbl_idx & idx_mask) != idx) { 13612 continue; 13613 } 13614 13615 /* parse L2 format */ 13616 rv = _field_fb_udf_idx_to_l2_format(unit, tbl_idx, &l2); 13617 BCM_IF_ERROR_RETURN(rv); 13618 13619 /* Ignore not ethertype based indexes. */ 13620 if (l2 != _BCM_FIELD_DATA_FORMAT_ETHERTYPE) { 13621 continue; 13622 } 13623 13624 /* parse vlan tag format */ 13625 rv = _field_fb_udf_idx_to_vlan_format(unit, tbl_idx, &vlan_tag); 13626 BCM_IF_ERROR_RETURN(rv); 13627 /* Compare packet vlan tag format. */ 13628 if ((etype->vlan_tag != BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY) && 13629 (etype->vlan_tag != vlan_tag)) { 13630 continue; 13631 } 13632 13633 /* Write offset to udf offset table . */ 13634 rv = _field_fb_data_offset_install(unit, f_dq, tbl_idx, offset); 13635 BCM_IF_ERROR_RETURN(rv); 13636 avail = 1; 13637 } 13638 13639 if (avail) { 13640 return (BCM_E_NONE); 13641 } else { 13642 return (BCM_E_UNAVAIL); 13643 } 13644 } 13645 13646 /* 13647 * Function: 13648 * _field_data_qualifier_ip_protocol_install 13649 * Purpose: 13650 * Add ip_protocol based offset to data qualifier object. 13651 * Parameters: 13652 * unit - (IN) bcm device. 13653 * f_dq - (IN) Data qualifier descriptor. 13654 * idx - (IN) Ip protocol index. 13655 * proto - (IN) Ip protocol based offset specification. 13656 * Returns: 13657 * BCM_E_XXX 13658 */ 13659 STATIC int 13660 _field_fb_data_qualifier_ip_protocol_install(int unit, 13661 _field_data_qualifier_t *f_dq, 13662 uint8 idx, 13663 _field_data_protocol_t *proto) 13664 { 13665 bcm_field_data_packet_format_t pkt_fmt; 13666 int offset; /* Adjusted word offset. */ 13667 int tbl_idx; /* Udf offset table iterator. */ 13668 uint16 l2; /* L2 packet format. */ 13669 uint16 vlan_tag; /* Vlan packet format. */ 13670 int rv; /* Operation return status. */ 13671 uint8 avail = 0; 13672 13673 /* Input parameters check. */ 13674 if ((NULL == f_dq) || (NULL == proto)) { 13675 return (BCM_E_PARAM); 13676 } 13677 13678 /* Verify UDF offset memory is valid. */ 13679 if (0 == SOC_MEM_IS_VALID(unit, FP_UDF_OFFSETm)){ 13680 return (BCM_E_UNAVAIL); 13681 } 13682 13683 /* Calculate offset */ 13684 offset = f_dq->offset + proto->relative_offset; 13685 if ((offset < 0) || ((offset + f_dq->length) > _FP_DATA_OFFSET_MAX)) { 13686 return (BCM_E_PARAM); 13687 } 13688 offset = ((offset + 2) % 128) / 4; 13689 13690 /* Update ip_protocol match register. */ 13691 rv = _bcm_field_fb_udf_ipprotocol_set(unit, idx, proto->flags, proto->ip); 13692 BCM_IF_ERROR_RETURN(rv); 13693 13694 for (tbl_idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 13695 tbl_idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); tbl_idx++) { 13696 /* parse L3 tunnel type/ Ip headers format */ 13697 rv = _field_fb_udf_idx_to_ip_format(unit, tbl_idx, &pkt_fmt); 13698 if (rv == BCM_E_EMPTY) { 13699 continue; 13700 } 13701 BCM_IF_ERROR_RETURN(rv); 13702 13703 /* Ignore not ip protcol based indexes. */ 13704 if (idx == 0) { 13705 if (((pkt_fmt.outer_ip != _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0) || 13706 (0 == (proto->flags & BCM_FIELD_DATA_FORMAT_IP4))) && 13707 (((pkt_fmt.outer_ip != _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL0) || 13708 (0 == (proto->flags & BCM_FIELD_DATA_FORMAT_IP6))))) { 13709 continue; 13710 } 13711 } else { 13712 if (((pkt_fmt.outer_ip != _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1) || 13713 (0 == (proto->flags & BCM_FIELD_DATA_FORMAT_IP4))) && 13714 (((pkt_fmt.outer_ip != _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL1) || 13715 (0 == (proto->flags & BCM_FIELD_DATA_FORMAT_IP6))))) { 13716 continue; 13717 } 13718 } 13719 13720 /* parse l2 format */ 13721 rv = _field_fb_udf_idx_to_l2_format(unit, tbl_idx, &l2); 13722 if (rv == BCM_E_EMPTY) { 13723 continue; 13724 } 13725 BCM_IF_ERROR_RETURN(rv); 13726 /* Compare packet l2 format. */ 13727 if ((proto->l2 != BCM_FIELD_DATA_FORMAT_L2_ANY) && 13728 (proto->l2 != l2)) { 13729 continue; 13730 } 13731 13732 /* parse vlan tag format */ 13733 rv = _field_fb_udf_idx_to_vlan_format(unit, tbl_idx, &vlan_tag); 13734 if (rv == BCM_E_EMPTY) { 13735 continue; 13736 } 13737 BCM_IF_ERROR_RETURN(rv); 13738 /* Compare packet vlan tag format. */ 13739 if ((proto->vlan_tag != BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY) && 13740 (proto->vlan_tag != vlan_tag)) { 13741 continue; 13742 } 13743 13744 /* Write offset to udf offset table . */ 13745 rv = _field_fb_data_offset_install(unit, f_dq, tbl_idx, offset); 13746 BCM_IF_ERROR_RETURN(rv); 13747 avail = 1; 13748 } 13749 13750 if (avail) { 13751 return (BCM_E_NONE); 13752 } else { 13753 return (BCM_E_UNAVAIL); 13754 } 13755 } 13756 13757 13758 /* 13759 * Function: 13760 * _field_fb_packet_format_is_subset 13761 * Purpose: 13762 * Check if master packet format is superset of 13763 * subset packet format. 13764 * Parameters: 13765 * unit - (IN) Bcm device number. 13766 * master - (IN) Superset packet format. 13767 * subset - (IN) Subset packet format. 13768 * cmp_result - (OUT)Comparison result. 13769 * Returns: 13770 * BCM_E_XXX 13771 */ 13772 STATIC int 13773 _field_fb_packet_format_is_subset(int unit, 13774 bcm_field_data_packet_format_t *master, 13775 bcm_field_data_packet_format_t *subset, 13776 uint8 *cmp_result) 13777 { 13778 /* Input parameters check. */ 13779 if ((NULL == master) || (NULL == subset) || (NULL == cmp_result)) { 13780 return (BCM_E_PARAM); 13781 } 13782 13783 /* Compare packet l2 format. */ 13784 if ((master->l2 != BCM_FIELD_DATA_FORMAT_L2_ANY) && 13785 (master->l2 != subset->l2)) { 13786 *cmp_result = FALSE; 13787 return (BCM_E_NONE); 13788 } 13789 13790 /* Compare packet vlan tag format. */ 13791 if ((master->vlan_tag != BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY) && 13792 (master->vlan_tag != subset->vlan_tag)) { 13793 *cmp_result = FALSE; 13794 return (BCM_E_NONE); 13795 } 13796 13797 /* Compare packet tunnel type. */ 13798 if ((master->tunnel != BCM_FIELD_DATA_FORMAT_TUNNEL_ANY) && 13799 (master->tunnel != subset->tunnel)) { 13800 *cmp_result = FALSE; 13801 return (BCM_E_NONE); 13802 } 13803 13804 /* Compare outer ip header. */ 13805 if ((master->tunnel != BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS) && 13806 (master->outer_ip != BCM_FIELD_DATA_FORMAT_IP_ANY) && 13807 (master->outer_ip != subset->outer_ip)) { 13808 *cmp_result = FALSE; 13809 return (BCM_E_NONE); 13810 } 13811 13812 /* Compare inner ip header. */ 13813 if ((master->tunnel != BCM_FIELD_DATA_FORMAT_TUNNEL_NONE) && 13814 (master->tunnel != BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS) && 13815 (master->inner_ip != BCM_FIELD_DATA_FORMAT_IP_ANY) && 13816 (master->inner_ip != subset->inner_ip)) { 13817 *cmp_result = FALSE; 13818 return (BCM_E_NONE); 13819 } 13820 13821 /* Compare number of mpls labels. */ 13822 if ((master->tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS) && 13823 (master->mpls != BCM_FIELD_DATA_FORMAT_MPLS_ANY) && 13824 (master->mpls != subset->mpls)) { 13825 *cmp_result = FALSE; 13826 return (BCM_E_NONE); 13827 } 13828 *cmp_result = TRUE; 13829 return (BCM_E_NONE); 13830 } 13831 13832 /* 13833 * Function: 13834 * _field_fb_packet_format_tunnel_shim_size_get 13835 * Purpose: 13836 * Get tunnel shim size based on packet 13837 * format descriptor. 13838 * Parameters: 13839 * unit - (IN) Bcm device number. 13840 * pkt_fmt - (IN) Packet format. 13841 * *size - (OUT)Outer L3 + tunnel shim size. 13842 * Returns: 13843 * BCM_E_XXX 13844 * NOTE: 13845 * This api calculates basic header size. 13846 * Gre Options... are not handled here. 13847 * Please set proper FIELD_DATA_QUALIFIER_XXX options adjust flag. 13848 */ 13849 STATIC int 13850 _field_fb_packet_format_tunnel_shim_size_get(int unit, 13851 bcm_field_data_packet_format_t *pkt_fmt, 13852 uint8 *size) 13853 { 13854 /* Input parameters check. */ 13855 if ((NULL == pkt_fmt) || (NULL == size)) { 13856 return (BCM_E_PARAM); 13857 } 13858 13859 if (BCM_FIELD_DATA_FORMAT_TUNNEL_GRE == pkt_fmt->tunnel) { 13860 *size = 4; /* Basic (no key/no checksum/no options). */ 13861 } else { 13862 *size = 0; /* IPv4 header size. */ 13863 } 13864 return (BCM_E_NONE); 13865 } 13866 13867 /* 13868 * Function: 13869 * _field_fb_packet_format_ip_size_get 13870 * Purpose: 13871 * Get outer l3 header + tunnel shim size based on packet 13872 * format descriptor. 13873 * Parameters: 13874 * unit - (IN) Bcm device number. 13875 * ip - (IN) BCM_FIELD_DATA_FORMAT_IP_XXX. 13876 * *size - (OUT)Outer L3 + tunnel shim size. 13877 * Returns: 13878 * BCM_E_XXX 13879 * NOTE: 13880 * This api calculates basic header size. 13881 * IP options/Extension headers ... are not handled here. 13882 * Please set proper FIELD_DATA_QUALIFIER_XXX options adjust flag. 13883 */ 13884 STATIC int 13885 _field_fb_packet_format_ip_size_get(int unit, uint16 ip, uint8 *size) 13886 { 13887 /* Input parameters check. */ 13888 if (NULL == size) { 13889 return (BCM_E_PARAM); 13890 } 13891 13892 if (BCM_FIELD_DATA_FORMAT_IP6 == ip) { 13893 *size = 40; /* Ipv6 header size */ 13894 } else if (BCM_FIELD_DATA_FORMAT_IP4 == ip) { 13895 *size = 20; /* IPv4 header size. */ 13896 } else if (BCM_FIELD_DATA_FORMAT_IP_NONE == ip) { 13897 *size = 0; 13898 } else { 13899 return (BCM_E_INTERNAL); 13900 } 13901 return (BCM_E_NONE); 13902 } 13903 13904 /* 13905 * Function: 13906 * _field_fb_packet_format_mpls_labels_size_get 13907 * Purpose: 13908 * Get mpls labels size based on packet format descriptor. 13909 * Parameters: 13910 * unit - (IN) Bcm device number. 13911 * pkt_fmt - (IN) Packet format. 13912 * *size - (OUT)mpls labels size. 13913 * Returns: 13914 * BCM_E_XXX 13915 */ 13916 STATIC int 13917 _field_fb_packet_format_mpls_labels_size_get(int unit, 13918 bcm_field_data_packet_format_t *pkt_fmt, 13919 uint8 *size) 13920 { 13921 /* Input parameters check. */ 13922 if ((NULL == pkt_fmt) || (NULL == size)) { 13923 return (BCM_E_PARAM); 13924 } 13925 13926 if (BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS != pkt_fmt->tunnel) { 13927 *size = 0; 13928 } else if (BCM_FIELD_DATA_FORMAT_MPLS_ONE_LABEL == pkt_fmt->mpls) { 13929 *size = 4; 13930 } else if (BCM_FIELD_DATA_FORMAT_MPLS_TWO_LABELS == pkt_fmt->mpls) { 13931 *size = 8; 13932 } else { 13933 return (BCM_E_INTERNAL); 13934 } 13935 return (BCM_E_NONE); 13936 } 13937 13938 /* 13939 * Function: 13940 * _field_fb_packet_format_l2_header_size_get 13941 * Purpose: 13942 * Get l2 header size based on packet format descriptor. 13943 * Parameters: 13944 * unit - (IN) Bcm device number. 13945 * pkt_fmt - (IN) Packet format. 13946 * *size - (OUT)L2 header size. 13947 * Returns: 13948 * BCM_E_XXX 13949 */ 13950 STATIC int 13951 _field_fb_packet_format_l2_header_size_get(int unit, 13952 bcm_field_data_packet_format_t *pkt_fmt, 13953 uint8 *size) 13954 { 13955 uint8 tmp; 13956 13957 /* Input parameters check. */ 13958 if ((NULL == pkt_fmt) || (NULL == size)) { 13959 return (BCM_E_PARAM); 13960 } 13961 13962 switch(pkt_fmt->l2) { 13963 case BCM_FIELD_DATA_FORMAT_L2_ETH_II: 13964 case BCM_FIELD_DATA_FORMAT_L2_LLC: 13965 tmp = 14; 13966 break; 13967 case BCM_FIELD_DATA_FORMAT_L2_SNAP: 13968 tmp = 22; 13969 break; 13970 default: 13971 return (BCM_E_INTERNAL); 13972 } 13973 13974 switch(pkt_fmt->vlan_tag) { 13975 case BCM_FIELD_DATA_FORMAT_VLAN_NO_TAG: 13976 break; 13977 case BCM_FIELD_DATA_FORMAT_VLAN_SINGLE_TAGGED: 13978 tmp += 4; 13979 break; 13980 case BCM_FIELD_DATA_FORMAT_VLAN_DOUBLE_TAGGED: 13981 tmp += 8; 13982 break; 13983 default: 13984 return (BCM_E_INTERNAL); 13985 } 13986 *size = tmp; 13987 return (BCM_E_NONE); 13988 } 13989 13990 /* 13991 * Function: 13992 * _field_fb_packet_format_offset_adjust 13993 * Purpose: 13994 * Calculate word offset for data qualifier 13995 * based on offset based, relative offset & master offset. 13996 * Parameters: 13997 * unit - (IN) Bcm device number. 13998 * f_dq - (IN) Data qualifier descriptor. 13999 * pkt_fmt - (IN) Installed packet format. 14000 * offset - (OUT)Final word offset. 14001 * Returns: 14002 * BCM_E_XXX 14003 */ 14004 STATIC int 14005 _field_fb_packet_format_offset_adjust(int unit, 14006 _field_data_qualifier_t *f_dq, 14007 bcm_field_data_packet_format_t *pkt_fmt, 14008 int *offset) 14009 { 14010 int tmp_offset; /* Local calculation variable. */ 14011 uint8 size; /* Various headers sizes. */ 14012 int rv; /* Operation return status. */ 14013 14014 /* Input parameters check. */ 14015 if ((NULL == f_dq) || (NULL == pkt_fmt) || (NULL == offset)) { 14016 return (BCM_E_PARAM); 14017 } 14018 14019 /* Calculate offset */ 14020 tmp_offset = f_dq->offset + pkt_fmt->relative_offset; 14021 14022 if (tmp_offset == _FP_DATA_OFFSET_MAX - 2) { 14023 if (f_dq->length > 4) { 14024 return (BCM_E_PARAM); 14025 } 14026 } else if ((tmp_offset < 0) || 14027 (tmp_offset + f_dq->length) >= _FP_DATA_OFFSET_MAX) { 14028 return (BCM_E_PARAM); 14029 } 14030 14031 switch (f_dq->offset_base) { 14032 case bcmFieldDataOffsetBasePacketStart: 14033 break; 14034 14035 case bcmFieldDataOffsetBaseOuterL3Header: 14036 /* a) Add L2 header size. */ 14037 rv = _field_fb_packet_format_l2_header_size_get(unit, pkt_fmt, &size); 14038 BCM_IF_ERROR_RETURN(rv); 14039 tmp_offset += size; 14040 14041 /* b) Add size of mpls labels. */ 14042 rv = _field_fb_packet_format_mpls_labels_size_get(unit, pkt_fmt, &size); 14043 BCM_IF_ERROR_RETURN(rv); 14044 tmp_offset += size; 14045 break; 14046 14047 case bcmFieldDataOffsetBaseInnerL3Header: 14048 /* a) Add L2 header size. */ 14049 rv = _field_fb_packet_format_l2_header_size_get(unit, pkt_fmt, &size); 14050 BCM_IF_ERROR_RETURN(rv); 14051 tmp_offset += size; 14052 14053 14054 /* b) Add size of outer l3 header . */ 14055 rv = _field_fb_packet_format_ip_size_get(unit, pkt_fmt->outer_ip, &size); 14056 BCM_IF_ERROR_RETURN(rv); 14057 tmp_offset += size; 14058 14059 /* c) Add size of GRE shim. */ 14060 rv = _field_fb_packet_format_tunnel_shim_size_get(unit, pkt_fmt, &size); 14061 BCM_IF_ERROR_RETURN(rv); 14062 tmp_offset += size; 14063 break; 14064 14065 case bcmFieldDataOffsetBaseOuterL4Header: 14066 /* a) Add L2 header size. */ 14067 rv = _field_fb_packet_format_l2_header_size_get(unit, pkt_fmt, &size); 14068 BCM_IF_ERROR_RETURN(rv); 14069 tmp_offset += size; 14070 14071 /* b) Add size of outer l3 header . */ 14072 rv = _field_fb_packet_format_ip_size_get(unit, pkt_fmt->outer_ip, &size); 14073 BCM_IF_ERROR_RETURN(rv); 14074 tmp_offset += size; 14075 break; 14076 14077 case bcmFieldDataOffsetBaseInnerL4Header: 14078 /* a) Add L2 header size. */ 14079 rv = _field_fb_packet_format_l2_header_size_get(unit, pkt_fmt, &size); 14080 BCM_IF_ERROR_RETURN(rv); 14081 tmp_offset += size; 14082 14083 14084 /* b) Add size of outer l3 header . */ 14085 rv = _field_fb_packet_format_ip_size_get(unit, pkt_fmt->outer_ip, &size); 14086 BCM_IF_ERROR_RETURN(rv); 14087 tmp_offset += size; 14088 14089 /* c) Add size of GRE shim. */ 14090 rv = _field_fb_packet_format_tunnel_shim_size_get(unit, pkt_fmt, &size); 14091 BCM_IF_ERROR_RETURN(rv); 14092 tmp_offset += size; 14093 14094 /* d) Add size of inner l3 header . */ 14095 rv = _field_fb_packet_format_ip_size_get(unit, pkt_fmt->inner_ip, &size); 14096 BCM_IF_ERROR_RETURN(rv); 14097 tmp_offset += size; 14098 break; 14099 14100 case bcmFieldDataOffsetBaseHigigHeader: 14101 if (SOC_IS_FB(unit) || 14102 SOC_IS_HB_GW(unit) || 14103 SOC_IS_SC_CQ(unit) || 14104 SOC_IS_ENDURO(unit) || 14105 soc_feature(unit, soc_feature_field_udf_offset_hg_114B)) { 14106 /* Hardcoded Higig header offset is 114 bytes. */ 14107 tmp_offset += 0x72; 14108 } else { 14109 /* Hardcoded Higig header length is 12 bytes. */ 14110 tmp_offset += 0xc; 14111 } 14112 break; 14113 14114 case bcmFieldDataOffsetBaseHigig2Header: 14115 if (SOC_IS_FB(unit) || 14116 SOC_IS_HB_GW(unit) || 14117 SOC_IS_SC_CQ(unit) || 14118 SOC_IS_ENDURO(unit) || 14119 soc_feature(unit, soc_feature_field_udf_offset_hg2_110B)) { 14120 /* Hardcoded Higig2 header offset is 110 bytes. */ 14121 tmp_offset += 0x6e; 14122 } else { 14123 /* Hardcoded Higig2 header length is 16 bytes. */ 14124 tmp_offset += 0x10; 14125 } 14126 break; 14127 14128 default: 14129 return (BCM_E_PARAM); 14130 } 14131 14132 *offset = ((tmp_offset + 2) % 128) / 4; 14133 return (BCM_E_NONE); 14134 } 14135 14136 14137 /* 14138 * Function: 14139 * _bcm_field_fb_data_qualifier_packet_format_add 14140 * Purpose: 14141 * Add packet format based offset to data qualifier object. 14142 * Parameters: 14143 * unit - (IN) Bcm device number. 14144 * qual_id - (IN) Data qualifier id. 14145 * packet_format - (IN) Packet format specification. 14146 * Returns: 14147 * BCM_E_XXX 14148 */ 14149 int 14150 _bcm_field_fb_data_qualifier_packet_format_add(int unit, int qual_id, 14151 bcm_field_data_packet_format_t *packet_format) 14152 { 14153 bcm_field_data_packet_format_t pkt_fmt; /* Packet format iterator. */ 14154 _field_data_qualifier_t *f_dq; /* Data qualifier descriptor. */ 14155 _field_stage_t *stage_fc; /* Stage field control. */ 14156 uint8 cmp_result;/* Packet format compare result*/ 14157 int offset = 0;/* Adjusted word offset. */ 14158 int idx; /* Udf offset table iterator. */ 14159 int rv; /* Operation return status. */ 14160 uint8 avail = 0; 14161 14162 /* Input parameters check. */ 14163 if ((NULL == packet_format)) { 14164 return (BCM_E_PARAM); 14165 } 14166 14167 /* Verify UDF offset memory is valid. */ 14168 if (0 == SOC_MEM_IS_VALID(unit, FP_UDF_OFFSETm)){ 14169 return (BCM_E_UNAVAIL); 14170 } 14171 14172 /* Get stage field control structure. */ 14173 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 14174 BCM_IF_ERROR_RETURN(rv); 14175 14176 /* Get data qualifier info. */ 14177 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq); 14178 BCM_IF_ERROR_RETURN(rv); 14179 14180 14181 for (idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 14182 idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); idx++) { 14183 sal_memset(&pkt_fmt, 0, sizeof (bcm_field_data_packet_format_t)); 14184 14185 /* Get packet format associated with an index. */ 14186 rv = _field_fb_udf_offset_idx_to_packet_format(unit, idx, &pkt_fmt); 14187 if (BCM_FAILURE(rv)) { 14188 if (rv == BCM_E_EMPTY) { 14189 /* Unused/ethertype/ip protocol table index. */ 14190 continue; 14191 } 14192 return (rv); 14193 } 14194 14195 /* Check that idx packet format is subset of installed packet format. */ 14196 rv = _field_fb_packet_format_is_subset(unit, packet_format, 14197 &pkt_fmt, &cmp_result); 14198 BCM_IF_ERROR_RETURN(rv); 14199 if (FALSE == cmp_result) { 14200 continue; 14201 } 14202 14203 /* Calculate base offset adjusted offset. */ 14204 rv = _field_fb_packet_format_offset_adjust(unit, f_dq, 14205 packet_format, &offset); 14206 BCM_IF_ERROR_RETURN(rv); 14207 14208 14209 /* Write offset to udf offset table . */ 14210 rv = _field_fb_data_offset_install(unit, f_dq, idx, offset); 14211 BCM_IF_ERROR_RETURN(rv); 14212 avail = 1; 14213 14214 } 14215 14216 if (avail) { 14217 return (BCM_E_NONE); 14218 } else { 14219 return (BCM_E_UNAVAIL); 14220 } 14221 } 14222 14223 /* 14224 * Function: 14225 * _bcm_field_fb_data_qualifier_packet_format_delete 14226 * Purpose: 14227 * Remove packet format based offset to data qualifier object. 14228 * Parameters: 14229 * unit - (IN) Bcm device number. 14230 * qual_id - (IN) Data qualifier id. 14231 * packet_format - (IN) Packet format specification. 14232 * Returns: 14233 * BCM_E_XXX 14234 */ 14235 int 14236 _bcm_field_fb_data_qualifier_packet_format_delete(int unit, int qual_id, 14237 bcm_field_data_packet_format_t *packet_format) 14238 { 14239 bcm_field_data_packet_format_t pkt_fmt; /* Packet format iterator. */ 14240 _field_data_qualifier_t *f_dq; /* Data qualifier descriptor. */ 14241 _field_stage_t *stage_fc; /* Stage field control. */ 14242 uint8 cmp_result;/* Packet format compare result*/ 14243 int idx; /* Udf offset table iterator. */ 14244 int rv; /* Operation return status. */ 14245 14246 /* Input parameters check. */ 14247 if ((NULL == packet_format)) { 14248 return (BCM_E_PARAM); 14249 } 14250 14251 /* Verify UDF offset memory is valid. */ 14252 if (0 == SOC_MEM_IS_VALID(unit, FP_UDF_OFFSETm)){ 14253 return (BCM_E_UNAVAIL); 14254 } 14255 14256 /* Get stage field control structure. */ 14257 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 14258 BCM_IF_ERROR_RETURN(rv); 14259 14260 /* Get data qualifier info. */ 14261 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq); 14262 BCM_IF_ERROR_RETURN(rv); 14263 14264 14265 for (idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 14266 idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); idx++) { 14267 sal_memset(&pkt_fmt, 0, sizeof (bcm_field_data_packet_format_t)); 14268 14269 /* Get packet format associated with an index. */ 14270 rv = _field_fb_udf_offset_idx_to_packet_format(unit, idx, &pkt_fmt); 14271 if (BCM_FAILURE(rv)) { 14272 if (rv == BCM_E_EMPTY) { 14273 /* Unused/ethertype/ip protocol table index. */ 14274 continue; 14275 } 14276 return (rv); 14277 } 14278 14279 /* Check that idx packet format is subset of installed packet format. */ 14280 rv = _field_fb_packet_format_is_subset(unit, packet_format, &pkt_fmt, 14281 &cmp_result); 14282 BCM_IF_ERROR_RETURN(rv); 14283 if (FALSE == cmp_result) { 14284 continue; 14285 } 14286 14287 /* Write offset to udf offset table . */ 14288 rv = _field_fb_data_offset_install(unit, f_dq, idx, -1); 14289 BCM_IF_ERROR_RETURN(rv); 14290 14291 } 14292 return (BCM_E_NONE); 14293 } 14294 14295 /* 14296 * Function: 14297 * _field_fb_data_qualifier_ethertype_add 14298 * Purpose: 14299 * Add ethertype based offset to data qualifier object. 14300 * Parameters: 14301 * unit - (IN) bcm device. 14302 * qual_id - (IN) Data qualifier id. 14303 * etype - (IN) Ethertype based offset specification. 14304 * Returns: 14305 * BCM_E_XXX 14306 */ 14307 int 14308 _field_fb_data_qualifier_ethertype_add(int unit, int qual_id, 14309 bcm_field_data_ethertype_t *etype) 14310 { 14311 _field_data_ethertype_t *etype_ptr;/* Ether type pointer. */ 14312 _field_stage_t *stage_fc; /* Stage field control. */ 14313 _field_data_qualifier_t *f_dq; /* Data qualifier descriptor. */ 14314 int idx; /* Ethertype allocation index. */ 14315 int unused_idx;/* Unused ethertype index. */ 14316 int rv; /* Operation return status. */ 14317 14318 /* Input parameters check. */ 14319 if ((NULL == etype)) { 14320 return (BCM_E_PARAM); 14321 } 14322 14323 /* Get stage field control structure. */ 14324 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 14325 BCM_IF_ERROR_RETURN(rv); 14326 14327 /* Get data qualifier info. */ 14328 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq); 14329 BCM_IF_ERROR_RETURN(rv); 14330 14331 /* 14332 * Ethertype based qualifier offset must be 14333 * from the beginning of the packet. 14334 */ 14335 if (f_dq->offset_base != bcmFieldDataOffsetBasePacketStart) { 14336 return (BCM_E_UNAVAIL); 14337 } 14338 14339 unused_idx = -1; 14340 for (idx = 0; idx < _FP_DATA_ETHERTYPE_MAX; idx++) { 14341 etype_ptr = stage_fc->data_ctrl->etype + idx; 14342 /* Find an entry with identical ethertype/l2format. */ 14343 if ((etype->l2 == etype_ptr->l2) && 14344 (etype->ethertype == etype_ptr->ethertype) && 14345 (etype_ptr->ref_count > 0)) { 14346 etype_ptr->ref_count++; 14347 rv = BCM_E_NONE; 14348 break; 14349 } 14350 14351 /* Find unused entry. */ 14352 if ((-1 == unused_idx) && (0 == etype_ptr->ref_count)) { 14353 unused_idx = idx; 14354 } 14355 } 14356 14357 if (_FP_DATA_ETHERTYPE_MAX == idx) { 14358 /* No match found -> check for unused entry. */ 14359 if (-1 == unused_idx) { 14360 return (BCM_E_RESOURCE); 14361 } 14362 idx = unused_idx; 14363 etype_ptr = stage_fc->data_ctrl->etype + idx; 14364 etype_ptr->ref_count = 1; 14365 } 14366 etype_ptr->ethertype = etype->ethertype; 14367 etype_ptr->l2 = etype->l2; 14368 etype_ptr->vlan_tag = etype->vlan_tag; 14369 etype_ptr->relative_offset = etype->relative_offset; 14370 14371 rv = _field_fb_data_qualifier_ethertype_install(unit, f_dq, 14372 idx, etype_ptr); 14373 14374 return (rv); 14375 } 14376 14377 /* 14378 * Function: 14379 * _field_fb_data_qualifier_ethertype_delete 14380 * Purpose: 14381 * Remove ethertype based offset from data qualifier object. 14382 * Parameters: 14383 * unit - (IN) bcm device. 14384 * qual_id - (IN) Data qualifier id. 14385 * etype - (IN) Ethertype based offset specification. 14386 * Returns: 14387 * BCM_E_XXX 14388 */ 14389 int 14390 _field_fb_data_qualifier_ethertype_delete(int unit, int qual_id, 14391 bcm_field_data_ethertype_t *etype) 14392 { 14393 _field_stage_t *stage_fc; /* Stage field control. */ 14394 _field_data_qualifier_t *f_dq; /* Data qualifier descriptor. */ 14395 int idx; /* Ethertype allocation index. */ 14396 int offset_idx;/* UDF offset. */ 14397 int rv; /* Operation return status. */ 14398 _field_data_ethertype_t *etype_ptr = NULL;/* Ether type pointer. */ 14399 int tbl_idx; /* Udf offset table iterator. */ 14400 int idx_mask; /* Ethertype id index mask. */ 14401 uint16 l2 = 0; /* L2 packet format. */ 14402 uint16 vlan_tag; /* Vlan packet format. */ 14403 fp_udf_offset_entry_t tbl_entry; /* HW table buffer. */ 14404 int match_found = 0; 14405 14406 static soc_field_t off_field[] = {UDF1_OFFSET0f, UDF1_OFFSET1f, 14407 UDF1_OFFSET2f, UDF1_OFFSET3f, 14408 UDF2_OFFSET0f, UDF2_OFFSET1f, 14409 UDF2_OFFSET2f, UDF2_OFFSET3f}; 14410 14411 /* Input parameters check. */ 14412 if ((NULL == etype)) { 14413 return (BCM_E_PARAM); 14414 } 14415 14416 /* Get ethertype index mask. */ 14417 if (SOC_IS_TR_VL(unit)) { 14418 idx_mask = 0x1f; /* Ethertype is 5 lower bits of udf index. */ 14419 } else { 14420 idx_mask = 0x7; /* Ethertype is 3 lower bits of udf index. */ 14421 } 14422 14423 /* Get stage field control structure. */ 14424 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 14425 BCM_IF_ERROR_RETURN(rv); 14426 14427 /* Get data qualifier info. */ 14428 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq); 14429 BCM_IF_ERROR_RETURN(rv); 14430 14431 for (idx = 0; idx < _FP_DATA_ETHERTYPE_MAX; idx++) { 14432 etype_ptr = stage_fc->data_ctrl->etype + idx; 14433 14434 if (etype_ptr->ref_count <= 0) { 14435 continue; 14436 } 14437 14438 /* Find an entry with identical ethertype/l2format. */ 14439 if ((etype->l2 == etype_ptr->l2) && 14440 (etype->ethertype == etype_ptr->ethertype)) { 14441 for (tbl_idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 14442 tbl_idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); tbl_idx++) { 14443 14444 if ((tbl_idx & idx_mask) != idx) { 14445 continue; 14446 } 14447 14448 /* parse L2 format */ 14449 rv = _field_fb_udf_idx_to_l2_format(unit, tbl_idx, &l2); 14450 BCM_IF_ERROR_RETURN(rv); 14451 14452 /* Ignore not ethertype based indexes. */ 14453 if (l2 != _BCM_FIELD_DATA_FORMAT_ETHERTYPE) { 14454 continue; 14455 } 14456 14457 /* parse vlan tag format */ 14458 rv = _field_fb_udf_idx_to_vlan_format(unit, tbl_idx, &vlan_tag); 14459 BCM_IF_ERROR_RETURN(rv); 14460 /* Compare packet vlan tag format. */ 14461 if (etype->vlan_tag != vlan_tag) { 14462 continue; 14463 } 14464 14465 /* Read udf offset table enty.*/ 14466 BCM_IF_ERROR_RETURN 14467 (READ_FP_UDF_OFFSETm(unit, MEM_BLOCK_ANY, tbl_idx, &tbl_entry)); 14468 14469 /* Check whether the entry has valid data or not.*/ 14470 for (offset_idx = 0; offset_idx < _FP_DATA_DATA1_WORD_MAX ; 14471 offset_idx++) { 14472 if ((soc_FP_UDF_OFFSETm_field32_get( 14473 unit, &tbl_entry, off_field[offset_idx])) != 0) { 14474 match_found = 1; 14475 break; 14476 } 14477 } 14478 14479 if (!match_found) { 14480 continue; 14481 } 14482 14483 etype_ptr->ref_count--; 14484 if (etype_ptr->ref_count >= 0) { 14485 /* Write offset to udf offset table . */ 14486 rv = _field_fb_data_offset_install(unit, f_dq, tbl_idx, -1); 14487 BCM_IF_ERROR_RETURN(rv); 14488 if (etype_ptr->ref_count == 0) { 14489 /* Update ethertype match register. */ 14490 rv = _bcm_field_fb_udf_ethertype_set(unit, idx, 0, 0); 14491 BCM_IF_ERROR_RETURN(rv); 14492 } 14493 break; 14494 } 14495 } 14496 if (match_found) { 14497 break; 14498 } 14499 } 14500 } 14501 14502 if (_FP_DATA_ETHERTYPE_MAX == idx) { 14503 return (BCM_E_NOT_FOUND); 14504 } 14505 14506 return (rv); 14507 } 14508 14509 /* 14510 * Function: 14511 * _bcm_field_fb_data_qualifier_ip_protocol_add 14512 * Purpose: 14513 * Add ip_protocol based offset to data qualifier object. 14514 * Parameters: 14515 * unit - (IN) Bcm device number. 14516 * qual_id - (IN) Data qualifier id. 14517 * ip_protocol- (IN) Ip protocol based offset specification. 14518 * Returns: 14519 * BCM_E_XXX 14520 */ 14521 int 14522 _bcm_field_fb_data_qualifier_ip_protocol_add(int unit, int qual_id, 14523 bcm_field_data_ip_protocol_t *ip_protocol) 14524 { 14525 _field_data_protocol_t *proto_ptr;/* Ip protocol pointer. */ 14526 _field_data_qualifier_t *f_dq; /* Data qualifier descriptor. */ 14527 _field_stage_t *stage_fc; /* Stage field control. */ 14528 int unused_idx;/* Unused ip_protocol index. */ 14529 int idx; /* Ethertype allocation index. */ 14530 int flags; /* Ip protocol version flags. */ 14531 int rv; /* Operation return status. */ 14532 14533 /* Input parameters check. */ 14534 if ((NULL == ip_protocol)) { 14535 return (BCM_E_PARAM); 14536 } 14537 14538 /* Get stage field control structure. */ 14539 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 14540 BCM_IF_ERROR_RETURN(rv); 14541 14542 /* Get data qualifier info. */ 14543 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq); 14544 BCM_IF_ERROR_RETURN(rv); 14545 14546 unused_idx = -1; 14547 flags = ip_protocol->flags & 14548 (BCM_FIELD_DATA_FORMAT_IP4 | BCM_FIELD_DATA_FORMAT_IP6); 14549 for (idx = 0; idx < _FP_DATA_IP_PROTOCOL_MAX; idx++) { 14550 proto_ptr = stage_fc->data_ctrl->ip + idx; 14551 14552 /* Find an entry with identical ip_protocol. */ 14553 if ((ip_protocol->ip == proto_ptr->ip) && 14554 ((proto_ptr->ip4_ref_count > 0) || 14555 ((proto_ptr->ip6_ref_count > 0)))) { 14556 break; 14557 } 14558 /* Find unused entry. */ 14559 if ((-1 == unused_idx) && 14560 (0 == proto_ptr->ip4_ref_count) && 14561 (0 == proto_ptr->ip6_ref_count)) { 14562 unused_idx = idx; 14563 } 14564 } 14565 if (_FP_DATA_IP_PROTOCOL_MAX == idx) { 14566 /* No match found -> check for unused entry. */ 14567 if (-1 == unused_idx) { 14568 return (BCM_E_RESOURCE); 14569 } 14570 idx = unused_idx; 14571 } 14572 14573 proto_ptr = stage_fc->data_ctrl->ip + idx; 14574 /* Increment reference count. */ 14575 if (flags & BCM_FIELD_DATA_FORMAT_IP4) { 14576 proto_ptr->ip4_ref_count++; 14577 } 14578 if (flags & BCM_FIELD_DATA_FORMAT_IP6) { 14579 proto_ptr->ip6_ref_count++; 14580 } 14581 14582 /* Check if reinstall is required. */ 14583 proto_ptr->ip = ip_protocol->ip; 14584 proto_ptr->l2 = ip_protocol->l2; 14585 proto_ptr->vlan_tag = ip_protocol->vlan_tag; 14586 proto_ptr->flags = flags; 14587 proto_ptr->relative_offset = ip_protocol->relative_offset; 14588 14589 rv = _field_fb_data_qualifier_ip_protocol_install(unit, f_dq, 14590 idx, proto_ptr); 14591 return (rv); 14592 } 14593 14594 /* 14595 * Function: 14596 * _bcm_field_fb_data_qualifier_ip_protocol_delete 14597 * Purpose: 14598 * Remove ip protocol based offset from data qualifier object. 14599 * Parameters: 14600 * unit - (IN) bcm device. 14601 * qual_id - (IN) Data qualifier id. 14602 * ip_protocol - (IN) Ip Protocol based offset specification. 14603 * Returns: 14604 * BCM_E_XXX 14605 */ 14606 int 14607 _bcm_field_fb_data_qualifier_ip_protocol_delete(int unit, int qual_id, 14608 bcm_field_data_ip_protocol_t *ip_protocol) 14609 { 14610 _field_data_protocol_t *proto_ptr;/* Ip protocol pointer. */ 14611 _field_data_qualifier_t *f_dq; /* Data qualifier descriptor. */ 14612 _field_stage_t *stage_fc; /* Stage field control. */ 14613 int idx; /* Ethertype allocation index. */ 14614 int flags; /* Ip protocol version flags. */ 14615 int rv; /* Operation return status. */ 14616 14617 /* Input parameters check. */ 14618 if ((NULL == ip_protocol)) { 14619 return (BCM_E_PARAM); 14620 } 14621 14622 /* Get stage field control structure. */ 14623 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 14624 BCM_IF_ERROR_RETURN(rv); 14625 14626 /* Get data qualifier info. */ 14627 rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq); 14628 BCM_IF_ERROR_RETURN(rv); 14629 14630 flags = ip_protocol->flags & 14631 (BCM_FIELD_DATA_FORMAT_IP4 | BCM_FIELD_DATA_FORMAT_IP6); 14632 for (idx = 0; idx < _FP_DATA_IP_PROTOCOL_MAX; idx++) { 14633 proto_ptr = stage_fc->data_ctrl->ip + idx; 14634 14635 /* Find an entry with identical ip_protocol. */ 14636 if ((ip_protocol->ip == proto_ptr->ip) && 14637 ((proto_ptr->ip4_ref_count > 0) || 14638 ((proto_ptr->ip6_ref_count > 0)))) { 14639 break; 14640 } 14641 } 14642 if (_FP_DATA_IP_PROTOCOL_MAX == idx) { 14643 /* No match found. */ 14644 return (BCM_E_NOT_FOUND); 14645 } 14646 14647 proto_ptr = stage_fc->data_ctrl->ip + idx; 14648 /* Increment reference count. */ 14649 if ((flags & BCM_FIELD_DATA_FORMAT_IP4) && 14650 (proto_ptr->ip4_ref_count > 0)) { 14651 proto_ptr->ip4_ref_count--; 14652 if (0 == proto_ptr->ip4_ref_count) { 14653 proto_ptr->flags &= ~BCM_FIELD_DATA_FORMAT_IP4; 14654 } 14655 } 14656 if ((flags & BCM_FIELD_DATA_FORMAT_IP6) && 14657 (proto_ptr->ip6_ref_count > 0)) { 14658 proto_ptr->ip6_ref_count--; 14659 if (0 == proto_ptr->ip6_ref_count) { 14660 proto_ptr->flags &= ~BCM_FIELD_DATA_FORMAT_IP6; 14661 } 14662 } 14663 14664 /* Mark entry as unused. */ 14665 if ((0 == proto_ptr->ip4_ref_count) && (0 == proto_ptr->ip6_ref_count)) { 14666 proto_ptr->ip = 0; 14667 proto_ptr->flags = 0; 14668 } 14669 14670 /* Install protocol match register. */ 14671 rv = _bcm_field_fb_udf_ipprotocol_set(unit, idx, proto_ptr->flags, 14672 proto_ptr->ip); 14673 return (rv); 14674 } 14675 14676 14677 #define _FP_L2_FORMAT_MIN (0) 14678 #define _FP_L2_FORMAT_MAX (2) 14679 /* 14680 * Function: 14681 * _bcm_field_fb_data_qualifier_ethertype_add 14682 * Purpose: 14683 * Add ethertype based offset to data qualifier object. 14684 * Parameters: 14685 * unit - (IN) bcm device. 14686 * qual_id - (IN) Data qualifier id. 14687 * etype - (IN) Ethertype based offset specification. 14688 * Returns: 14689 * BCM_E_XXX 14690 */ 14691 int 14692 _bcm_field_fb_data_qualifier_ethertype_add(int unit, int qual_id, 14693 bcm_field_data_ethertype_t *etype) 14694 { 14695 int idx; /* L2 format iteration index.*/ 14696 uint16 l2; /* Installed L2 format. */ 14697 int rv = BCM_E_NONE; /* Operation return status. */ 14698 14699 /* Input parameters check. */ 14700 if (NULL == etype) { 14701 return (BCM_E_PARAM); 14702 } 14703 14704 l2 = etype->l2; 14705 for (idx = _FP_L2_FORMAT_MIN; idx <= _FP_L2_FORMAT_MAX; idx++) { 14706 if (0 == (l2 & (1 << idx))) { 14707 continue; 14708 } 14709 etype->l2 = (1 << idx); 14710 rv = _field_fb_data_qualifier_ethertype_add(unit, qual_id, etype); 14711 if (BCM_FAILURE(rv)) { 14712 break; 14713 } 14714 } 14715 14716 return (rv); 14717 } 14718 14719 /* 14720 * Function: 14721 * _bcm_field_fb_data_qualifier_ethertype_delete 14722 * Purpose: 14723 * Remove ethertype based offset from data qualifier object. 14724 * Parameters: 14725 * unit - (IN) bcm device. 14726 * qual_id - (IN) Data qualifier id. 14727 * etype - (IN) Ethertype based offset specification. 14728 * Returns: 14729 * BCM_E_XXX 14730 */ 14731 int 14732 _bcm_field_fb_data_qualifier_ethertype_delete(int unit, int qual_id, 14733 bcm_field_data_ethertype_t *etype) 14734 { 14735 int idx; /* L2 format iteration index.*/ 14736 uint16 l2; /* Installed L2 format. */ 14737 int rv = BCM_E_NONE; /* Operation return status. */ 14738 14739 /* Input parameters check. */ 14740 if (NULL == etype) { 14741 return (BCM_E_PARAM); 14742 } 14743 14744 l2 = etype->l2; 14745 for (idx = _FP_L2_FORMAT_MIN; idx <= _FP_L2_FORMAT_MAX; idx++) { 14746 if (0 == (l2 & (1 << idx))) { 14747 continue; 14748 } 14749 etype->l2 = (1 << idx); 14750 rv = _field_fb_data_qualifier_ethertype_delete(unit, qual_id, etype); 14751 if (BCM_FAILURE(rv)) { 14752 break; 14753 } 14754 } 14755 return (rv); 14756 } 14757 #undef _FP_L2_FORMAT_MIN 14758 #undef _FP_L2_FORMAT_MAX 14759 14760 14761 /* 14762 * Function: 14763 * _field_fb_functions_init 14764 * 14765 * Purpose: 14766 * Set up functions pointers 14767 * 14768 * Parameters: 14769 * unit - (IN) BCM device number. 14770 * stage_fc - (IN/OUT) pointers to stage control block whe the device 14771 * and stage specific functions will be registered. 14772 * 14773 * Returns: 14774 * nothing 14775 * Notes: 14776 */ 14777 STATIC void 14778 _field_fb_functions_init(int unit, _field_funct_t *functions) 14779 { 14780 functions->fp_detach = _field_fb_detach; 14781 functions->fp_group_install = _bcm_field_fb_group_install; 14782 functions->fp_selcodes_install = _field_selcodes_install; 14783 functions->fp_slice_clear = _bcm_field_fb_slice_clear; 14784 functions->fp_entry_remove = _bcm_field_fb_entry_remove; 14785 functions->fp_entry_move = _bcm_field_fb_entry_move; 14786 functions->fp_selcode_get = _bcm_field_fb_selcode_get; 14787 functions->fp_selcode_to_qset = _bcm_field_selcode_to_qset; 14788 functions->fp_qual_list_get = _bcm_field_qual_lists_get; 14789 functions->fp_tcam_policy_clear = _field_fb_tcam_policy_clear; 14790 functions->fp_tcam_policy_install = _field_fb_tcam_policy_install; 14791 functions->fp_tcam_policy_reinstall = _field_fb_tcam_policy_reinstall; 14792 functions->fp_policer_install = _bcm_field_fb_policer_install; 14793 functions->fp_write_slice_map = _bcm_field_fb_write_slice_map; 14794 functions->fp_qualify_ip_type = _field_fb_qualify_ip_type; 14795 functions->fp_qualify_ip_type_get = _field_fb_qualify_ip_type_get; 14796 functions->fp_action_support_check = _field_fb_action_support_check; 14797 functions->fp_action_conflict_check = _field_fb_action_conflict_check; 14798 functions->fp_stat_index_get = _bcm_field_fb_stat_index_get; 14799 functions->fp_action_params_check = _field_fb_action_params_check; 14800 functions->fp_data_qualifier_ethertype_add = 14801 _bcm_field_fb_data_qualifier_ethertype_add; 14802 functions->fp_data_qualifier_ethertype_delete= 14803 _bcm_field_fb_data_qualifier_ethertype_delete; 14804 functions->fp_data_qualifier_ip_protocol_add = 14805 _bcm_field_fb_data_qualifier_ip_protocol_add; 14806 functions->fp_data_qualifier_ip_protocol_delete= 14807 _bcm_field_fb_data_qualifier_ip_protocol_delete; 14808 functions->fp_data_qualifier_packet_format_add= 14809 _bcm_field_fb_data_qualifier_packet_format_add; 14810 functions->fp_data_qualifier_packet_format_delete= 14811 _bcm_field_fb_data_qualifier_packet_format_delete; 14812 14813 #if defined(BCM_BRADLEY_SUPPORT) 14814 if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 14815 functions->fp_counter_get = _field_br_counter_get; 14816 functions->fp_counter_set = _field_br_counter_set; 14817 } else 14818 #endif /* BCM_BRADLEY_SUPPORT */ 14819 { 14820 functions->fp_counter_get = _bcm_field_fb_counter_get; 14821 functions->fp_counter_set = _bcm_field_fb_counter_set; 14822 } 14823 14824 #if defined(BCM_FIREBOLT2_SUPPORT) 14825 functions->fp_egress_key_match_type_set = _field_fb2_key_match_type_set; 14826 #else /* BCM_FIREBOLT2_SUPPORT */ 14827 functions->fp_egress_key_match_type_set = NULL; 14828 #endif /* BCM_FIREBOLT2_SUPPORT */ 14829 functions->fp_external_entry_install = NULL; 14830 functions->fp_external_entry_reinstall = NULL; 14831 functions->fp_external_entry_remove = NULL; 14832 functions->fp_external_entry_prio_set = NULL; 14833 functions->fp_stat_value_get = NULL; 14834 functions->fp_stat_value_set = NULL; 14835 functions->fp_control_set = _bcm_field_control_set; 14836 functions->fp_control_get = _bcm_field_control_get; 14837 functions->fp_stat_hw_mode_get = _bcm_field_stat_hw_mode_get; 14838 functions->fp_stat_hw_alloc = _bcm_field_stat_hw_alloc; 14839 functions->fp_stat_hw_free = _bcm_field_stat_hw_free; 14840 functions->fp_group_add = NULL; 14841 functions->fp_qualify_trunk = _bcm_field_qualify_trunk; 14842 functions->fp_qualify_trunk_get = _bcm_field_qualify_trunk_get; 14843 functions->fp_qualify_inports = _bcm_field_qualify_InPorts; 14844 functions->fp_entry_stat_extended_attach = NULL; 14845 functions->fp_entry_stat_extended_get = NULL; 14846 functions->fp_entry_stat_detach = _bcm_field_entry_stat_detach; 14847 functions->fp_class_size_get = NULL; 14848 functions->fp_qualify_packet_res = _field_qualify_PacketRes; 14849 functions->fp_qualify_packet_res_get = _field_qualify_PacketRes_get; 14850 } 14851 #else /*BCM_FIREBOLT_SUPPORT && BCM_FIELD_SUPPORT */ 14852 int _firebolt_field_not_empty; 14853 #endif /* BCM_FIREBOLT_SUPPORT && BCM_FIELD_SUPPORT */