udf.c (228033B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: udf.c 8 * Purpose: Manages XGS4 UDF_TCAM and UDF_OFFSET tables 9 */ 10 11 12 #include <shared/bsl.h> 13 14 #include <soc/field.h> 15 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/error.h> 19 20 #include <shared/bitop.h> 21 22 #include <bcm/udf.h> 23 #include <bcm/field.h> 24 #include <bcm/error.h> 25 #include <bcm/module.h> 26 27 #include <bcm_int/esw/xgs4.h> 28 #include <bcm_int/esw/switch.h> 29 #include <bcm_int/esw/field.h> 30 31 #define OUTER_IP4_TYPE_VAL(x) (SOC_IS_TD_TT(x) || SOC_IS_TRIUMPH3(x)) ? 1 : 2 32 #define OUTER_IP6_TYPE_VAL(x) (SOC_IS_TD_TT(x) || SOC_IS_TRIUMPH3(x)) ? 5 : 4 33 34 /* WarmBoot Sensitive Macro : Need to bump up scache version if changes */ 35 #define TD2_UDF_MAX_OBJECTS 0xff 36 37 #define UDF_MALLOC(_p_, _t_, _sz_, _desc_) \ 38 do { \ 39 if (!_p_) { \ 40 (_p_) = (_t_ *) sal_alloc((_sz_), (_desc_)); \ 41 } \ 42 if (_p_) { \ 43 sal_memset((_p_), 0, (_sz_)); \ 44 } \ 45 } while(0) 46 47 #define UDF_UNLINK_OFFSET_NODE(_t_) \ 48 do { \ 49 if ((_t_)->prev) { \ 50 (_t_)->prev->next = (_t_)->next; \ 51 } else { \ 52 UDF_CTRL(unit)->offset_info_head = (_t_)->next; \ 53 } \ 54 if ((_t_)->next) { \ 55 ((_t_)->next)->prev = (_t_)->prev; \ 56 } \ 57 } while(0) 58 59 #define UDF_UNLINK_TCAM_NODE(_t_) \ 60 do { \ 61 if ((_t_)->prev) { \ 62 (_t_)->prev->next = (_t_)->next; \ 63 } else { \ 64 UDF_CTRL(unit)->tcam_info_head = (_t_)->next; \ 65 } \ 66 if ((_t_)->next) { \ 67 ((_t_)->next)->prev = (_t_)->prev; \ 68 } \ 69 } while(0) 70 71 #define BCM_IF_NULL_RETURN_PARAM(_p_) \ 72 do { \ 73 if ((_p_) == NULL) { \ 74 return BCM_E_PARAM; \ 75 } \ 76 } while(0) 77 78 79 #define UDF_IF_ERROR_CLEANUP(_rv_) \ 80 do { \ 81 if (BCM_FAILURE(rv)) { \ 82 goto cleanup; \ 83 } \ 84 } while (0) 85 86 #define UDF_ID_VALIDATE(_id_) \ 87 do { \ 88 if (((_id_) < BCMI_XGS4_UDF_ID_MIN) || \ 89 ((_id_) > BCMI_XGS4_UDF_ID_MAX)) { \ 90 return BCM_E_PARAM; \ 91 } \ 92 } while(0) 93 #define UDF_ID_VALIDATE_UNLOCK(unit, _id_) \ 94 do { \ 95 if (((_id_) < BCMI_XGS4_UDF_ID_MIN) || \ 96 ((_id_) > BCMI_XGS4_UDF_ID_MAX)) { \ 97 UDF_UNLOCK(unit); \ 98 return BCM_E_PARAM; \ 99 } \ 100 } while(0) 101 102 #define UDF_PKT_FORMAT_ID_VALIDATE(_id_) \ 103 do { \ 104 if (((_id_) < BCMI_XGS4_UDF_PKT_FORMAT_ID_MIN) || \ 105 ((_id_) > BCMI_XGS4_UDF_PKT_FORMAT_ID_MAX)) { \ 106 return BCM_E_PARAM; \ 107 } \ 108 } while(0) 109 110 #define UDF_PKT_FORMAT_ID_VALIDATE_UNLOCK(unit, _id_) \ 111 do { \ 112 if (((_id_) < BCMI_XGS4_UDF_PKT_FORMAT_ID_MIN) || \ 113 ((_id_) > BCMI_XGS4_UDF_PKT_FORMAT_ID_MAX)) { \ 114 UDF_UNLOCK(unit); \ 115 return BCM_E_PARAM; \ 116 } \ 117 } while(0) 118 119 120 /* Global UDF control structure pointers */ 121 bcmi_xgs4_udf_ctrl_t *udf_control[BCM_MAX_NUM_UNITS]; 122 123 typedef enum { 124 bcmiUdfObjectUdf = 1, 125 bcmiUdfObjectPktFormat = 2 126 } bcmiUdfObjectType; 127 128 typedef enum bcmi_xgs4_udf_pkt_format_misc_e { 129 bcmiUdfPktFormatHigig = 0, 130 bcmiUdfPktFormatCntag = 1, 131 bcmiUdfPktFormatIcnm = 2, 132 bcmiUdfPktFormatVntag = 3, 133 bcmiUdfPktFormatEtag = 4, 134 bcmiUdfPktFormatSubportTag = 5, 135 bcmiUdfPktFormatIntPkt = 6, 136 bcmiUdfPktFormatNone 137 } bcmi_xgs4_udf_pkt_format_misc_t; 138 139 140 141 /* STATIC function declarations */ 142 STATIC int bcmi_xgs4_udf_ctrl_init(int unit); 143 144 STATIC int bcmi_xgs4_udf_hw_init(int unit); 145 146 STATIC int bcmi_xgs4_udf_offset_reserve(int unit, int max, int offset[], 147 int pipe_num); 148 149 STATIC int bcmi_xgs4_udf_offset_unreserve(int unit, int max, int offset[], 150 int pipe_num); 151 152 STATIC int bcmi_xgs4_udf_offset_hw_alloc(int unit, 153 bcm_udf_alloc_hints_t *hints, 154 bcmi_xgs4_udf_offset_info_t *offset_info); 155 156 STATIC int bcmi_xgs4_udf_layer_to_offset_base(int unit, 157 bcmi_xgs4_udf_offset_info_t *offset_info, 158 bcmi_xgs4_udf_tcam_info_t *tcam_info, 159 int *base, int *baseoffset); 160 161 STATIC int bcmi_xgs4_udf_offset_info_alloc(int unit, 162 bcmi_xgs4_udf_offset_info_t **offset_info); 163 164 STATIC int bcmi_xgs4_udf_offset_info_add(int unit, 165 bcm_udf_t *udf_info, bcmi_xgs4_udf_offset_info_t **offset_info); 166 167 STATIC int bcmi_xgs4_udf_offset_node_add( 168 int unit, bcmi_xgs4_udf_offset_info_t *new); 169 170 STATIC int bcmi_xgs4_udf_offset_node_delete(int unit, 171 bcm_udf_id_t udf_id, bcmi_xgs4_udf_offset_info_t **del); 172 173 STATIC int bcmi_xgs4_udf_tcam_info_alloc(int unit, 174 bcmi_xgs4_udf_tcam_info_t **tcam_info); 175 176 STATIC int bcmi_xgs4_udf_tcam_info_add(int unit, 177 bcm_udf_pkt_format_info_t *pkt_format, 178 bcmi_xgs4_udf_tcam_info_t **tcam_info); 179 180 STATIC int bcmi_xgs4_udf_tcam_node_add( 181 int unit, bcmi_xgs4_udf_tcam_info_t *new); 182 183 STATIC int bcmi_xgs4_udf_tcam_node_delete(int unit, 184 bcm_udf_pkt_format_id_t pkt_format_id, bcmi_xgs4_udf_tcam_info_t **del); 185 186 STATIC int bcmi_xgs4_udf_id_running_id_alloc(int unit, 187 bcmiUdfObjectType type, int *id); 188 189 STATIC int bcmi_xgs4_udf_offset_to_hw_field(int unit, int udf_num, int user_num, 190 soc_field_t *base_hw_f, soc_field_t *offset_hw_f); 191 192 STATIC int bcmi_xgs4_udf_offset_install(int unit, 193 int e, uint32 hw_bmap, int base, int offset, int pipe_num, int class_id, uint8 flags); 194 195 #if defined (BCM_TOMAHAWK_SUPPORT) 196 int bcmi_xgs4_udf_ser_init(int unit, 197 bcm_udf_oper_mode_t mode); 198 #endif 199 /* tcam help apis */ 200 STATIC int bcmi_xgs4_udf_tcam_entry_move(int unit, 201 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, int src, int dst, int pipe_num); 202 203 STATIC int bcmi_xgs4_udf_tcam_move_up(int unit, 204 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, int dest, int free_slot, int pipe_num); 205 206 STATIC int bcmi_xgs4_udf_tcam_move_down(int unit, 207 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, int dest, int free_slot, int pipe_num); 208 209 STATIC int bcmi_xgs4_udf_tcam_entry_match(int unit, 210 bcmi_xgs4_udf_tcam_info_t *new, bcmi_xgs4_udf_tcam_info_t **match); 211 212 STATIC int bcmi_xgs4_udf_tcam_entry_insert(int unit, 213 bcmi_xgs4_udf_tcam_info_t *tcam_new); 214 215 STATIC int bcmi_xgs4_udf_tcam_entry_vlanformat_parse(int unit, 216 uint32 *hw_buf, bcm_udf_pkt_format_info_t *pkt_fmt); 217 218 STATIC int bcmi_xgs4_udf_tcam_entry_l2format_parse(int unit, 219 uint32 *hw_buf, bcm_udf_pkt_format_info_t *pkt_fmt); 220 221 STATIC int bcmi_xgs4_udf_tcam_entry_l3_parse(int unit, 222 uint32 *hw_buf, bcm_udf_pkt_format_info_t *pkt_fmt); 223 224 STATIC int bcmi_xgs4_udf_tcam_entry_misc_parse(int unit, 225 int type, uint32 *hw_buf, uint16 *flags); 226 227 STATIC int bcmi_xgs4_udf_tcam_entry_vlanformat_init(int unit, 228 bcm_udf_pkt_format_info_t *pkt_fmt, uint32 *hw_buf); 229 230 STATIC int bcmi_xgs4_udf_tcam_entry_l2format_init(int unit, 231 bcm_udf_pkt_format_info_t *pkt_fmt, uint32 *hw_buf); 232 233 STATIC int bcmi_xgs4_udf_tcam_entry_l3_init(int unit, 234 bcm_udf_pkt_format_info_t *pkt_fmt, uint32 *hw_buf); 235 236 STATIC int bcmi_xgs4_udf_tcam_entry_misc_init(int unit, 237 int type, uint16 flags, uint32 *hw_buf); 238 239 STATIC int bcmi_xgs4_udf_tcam_entry_parse(int unit, 240 uint32 *hw_buf, bcm_udf_pkt_format_info_t *pkt_fmt); 241 242 STATIC int bcmi_xgs4_udf_pkt_format_tcam_key_init(int unit, 243 bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf); 244 245 STATIC int bcmi_xgs4_udf_tcam_misc_format_to_hw_fields(int unit, int type, 246 soc_field_t *data_f, soc_field_t *mask_f, 247 int *present, int *none, int *any, int *support); 248 249 STATIC int bcmi_xgs4_udf_hash_config_set(int unit, 250 bcm_udf_hash_config_t *config, bcmi_xgs4_udf_offset_info_t *offset_info); 251 252 /* static global variable */ 253 #if defined (BCM_TOMAHAWK_SUPPORT) 254 STATIC bcm_udf_oper_mode_t bcmi_xgs4_udf_oper_mode[BCM_MAX_NUM_UNITS] = {bcmUdfOperModeGlobal}; 255 #endif 256 257 /* 258 * Function: 259 * bcmi_xgs4_udf_ctrl_free 260 * Purpose: 261 * Frees udf control structure and its members. 262 * Parameters: 263 * unit - (IN) Unit number. 264 * udfc - (IN) UDF Control structure to free. 265 * Returns: 266 * BCM_E_XXX 267 * Notes: 268 */ 269 STATIC int 270 bcmi_xgs4_udf_ctrl_free(int unit, bcmi_xgs4_udf_ctrl_t *udfc) 271 { 272 bcmi_xgs4_udf_tcam_info_t *prv_t, *cur_t; 273 bcmi_xgs4_udf_offset_info_t *prv_o, *cur_o; 274 int pipe_id = 0; 275 276 #if defined (BCM_TOMAHAWK_SUPPORT) 277 int pipe; 278 #endif 279 280 if (NULL == udfc) { 281 /* Already freed */ 282 return BCM_E_NONE; 283 } 284 285 /* Free mutex */ 286 if (NULL != udfc->udf_mutex) { 287 sal_mutex_destroy(udfc->udf_mutex); 288 udfc->udf_mutex = NULL; 289 } 290 291 #if defined (BCM_TOMAHAWK_SUPPORT) 292 if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) { 293 for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) { 294 if (NULL != udfc->tcam_entry_array_per_pipe[pipe]) { 295 sal_free(udfc->tcam_entry_array_per_pipe[pipe]); 296 udfc->tcam_entry_array_per_pipe[pipe] = NULL; 297 } 298 if (NULL != udfc->offset_entry_array_per_pipe[pipe]) { 299 sal_free(udfc->offset_entry_array_per_pipe[pipe]); 300 udfc->offset_entry_array_per_pipe[pipe] = NULL; 301 } 302 } 303 } 304 #endif 305 /* Free tcam entry array */ 306 if (NULL != udfc->tcam_entry_array) { 307 sal_free(udfc->tcam_entry_array); 308 udfc->tcam_entry_array = NULL; 309 } 310 311 /* Free offset entry array */ 312 if (NULL != udfc->offset_entry_array) { 313 sal_free(udfc->offset_entry_array); 314 udfc->offset_entry_array = NULL; 315 } 316 317 /* Free list of pkt format objects */ 318 cur_o = udfc->offset_info_head; 319 320 while (NULL != cur_o) { 321 prv_o = cur_o; 322 cur_o = cur_o->next; 323 324 sal_free(prv_o); 325 } 326 udfc->offset_info_head = NULL; 327 328 /* Free list of offset objects */ 329 cur_t = udfc->tcam_info_head; 330 331 while (NULL != cur_t) { 332 prv_t = cur_t; 333 cur_t = cur_t->next; 334 335 sal_free(prv_t); 336 } 337 udfc->tcam_info_head = NULL; 338 339 /* Clean up udf field module resources */ 340 if (soc_feature(unit, soc_feature_udf_selector_support)) { 341 for (pipe_id = 0; pipe_id < SOC_MAX_NUM_PIPES; pipe_id++) { 342 if (NULL != udfc->udf_field_bmp[pipe_id].w) { 343 _BCMI_UDF_BMP_FREE(udfc->udf_field_bmp[pipe_id]); 344 } 345 udfc->max_chunks = 0; 346 } 347 } 348 /* Free the udf control structure */ 349 sal_free(udfc); 350 351 udf_control[unit] = NULL; 352 353 return BCM_E_NONE; 354 } 355 356 /* 357 * Function: 358 * bcmi_xgs4_udf_ctrl_init 359 * Purpose: 360 * Initialize UDF control and internal data structures. 361 * Parameters: 362 * unit - (IN) bcm device. 363 * 364 * Returns: 365 * BCM_E_XXX 366 */ 367 STATIC int 368 bcmi_xgs4_udf_ctrl_init(int unit) 369 { 370 int alloc_sz; 371 soc_mem_t tcam_mem, offset_mem; 372 int nentries, noffsets; 373 bcmi_xgs4_udf_ctrl_t *udf_ctrl = NULL; 374 int pipe_id = 0; 375 #if defined (BCM_TOMAHAWK_SUPPORT) 376 int pipe; 377 #endif 378 tcam_mem = FP_UDF_TCAMm; 379 offset_mem = FP_UDF_OFFSETm; 380 381 /* Detach module if already installed */ 382 if (udf_control[unit] != NULL) { 383 bcmi_xgs4_udf_detach(unit); 384 } 385 386 nentries = soc_mem_index_count(unit, tcam_mem); 387 388 /* No. of maximum offset chunks supported */ 389 if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF1_OFFSET4f)) { 390 noffsets = UDF_OFFSET_CHUNKS16; 391 } else { 392 noffsets = UDF_OFFSET_CHUNKS8; 393 } 394 395 if (udf_control[unit] != NULL) { 396 (void)bcmi_xgs4_udf_ctrl_free(unit, udf_control[unit]); 397 } 398 399 /* Allocating memory of UDF control structure */ 400 alloc_sz = sizeof(bcmi_xgs4_udf_ctrl_t); 401 UDF_MALLOC(udf_ctrl, bcmi_xgs4_udf_ctrl_t, alloc_sz, "udf control"); 402 if (udf_ctrl == NULL) { 403 return BCM_E_MEMORY; 404 } 405 406 udf_control[unit] = udf_ctrl; 407 408 /* Allocate memory for tcam_entry_array structure */ 409 #if defined (BCM_TOMAHAWK_SUPPORT) 410 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 411 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 412 sal_memset(udf_ctrl->hw_bmap_per_pipe, 0, sizeof(udf_ctrl->hw_bmap_per_pipe)); 413 sal_memset(udf_ctrl->byte_bmap_per_pipe, 0, sizeof(udf_ctrl->byte_bmap_per_pipe)); 414 415 /* Allocate memory for tcam_entry_array structure */ 416 alloc_sz = sizeof(bcmi_xgs4_udf_tcam_entry_t) * nentries; 417 for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) { 418 UDF_MALLOC(udf_ctrl->tcam_entry_array_per_pipe[pipe], bcmi_xgs4_udf_tcam_entry_t, 419 alloc_sz, "udf tcam entry array per pipe"); 420 if (udf_ctrl->tcam_entry_array_per_pipe[pipe] == NULL) { 421 /* Free udf control struct */ 422 (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl); 423 return BCM_E_MEMORY; 424 } 425 } 426 427 /* Allocate memory for offset_entry_array structure */ 428 alloc_sz = sizeof(bcmi_xgs4_udf_offset_entry_t) * noffsets; 429 for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) { 430 UDF_MALLOC(udf_ctrl->offset_entry_array_per_pipe[pipe], bcmi_xgs4_udf_offset_entry_t, 431 alloc_sz, "udf offset entry array per pipe"); 432 433 if (udf_ctrl->offset_entry_array_per_pipe[pipe] == NULL) { 434 /* Free udf control struct */ 435 (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl); 436 return BCM_E_MEMORY; 437 } 438 } 439 } else 440 #endif 441 { 442 /* Allocate memory for tcam_entry_array structure */ 443 alloc_sz = sizeof(bcmi_xgs4_udf_tcam_entry_t) * nentries; 444 UDF_MALLOC(udf_ctrl->tcam_entry_array, bcmi_xgs4_udf_tcam_entry_t, 445 alloc_sz, "udf tcam entry array"); 446 if (udf_ctrl->tcam_entry_array == NULL) { 447 /* Free udf control struct */ 448 (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl); 449 return BCM_E_MEMORY; 450 } 451 452 /* Allocate memory for offset_entry_array structure */ 453 alloc_sz = sizeof(bcmi_xgs4_udf_offset_entry_t) * noffsets; 454 UDF_MALLOC(udf_ctrl->offset_entry_array, bcmi_xgs4_udf_offset_entry_t, 455 alloc_sz, "udf offset entry array"); 456 if (udf_ctrl->offset_entry_array == NULL) { 457 /* Free udf control struct */ 458 (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl); 459 return BCM_E_MEMORY; 460 } 461 } 462 463 /* Create UDF lock */ 464 if (udf_ctrl->udf_mutex == NULL) { 465 udf_ctrl->udf_mutex = sal_mutex_create("udf_mutex"); 466 if (udf_ctrl->udf_mutex == NULL) { 467 /* Free udf control struct */ 468 (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl); 469 return BCM_E_MEMORY; 470 } 471 } 472 473 474 udf_ctrl->tcam_mem = tcam_mem; 475 udf_ctrl->offset_mem = offset_mem; 476 477 /* Check if GRE options adjust for UDF selection is supported */ 478 if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF1_ADD_GRE_OPTIONS0f)) { 479 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_OFFSET_ADJUST_GRE; 480 } 481 482 /* Check if IPV4 options adjust for UDF selection is supported */ 483 if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF1_ADD_IPV4_OPTIONS0f)) { 484 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_OFFSET_ADJUST_IP4; 485 } 486 if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF_CLASS_IDf)) { 487 udf_ctrl->flags |= BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID; 488 } 489 490 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, HIGIGf)) { 491 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_HIGIG; 492 } 493 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, VNTAG_PRESENTf)) { 494 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_VNTAG; 495 } 496 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, ETAG_PACKETf)) { 497 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_ETAG; 498 } 499 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, CNTAG_PRESENTf)) { 500 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_CNTAG; 501 } 502 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, ICNM_PACKETf)) { 503 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_ICNM; 504 } 505 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SUBPORT_TAG_PRESENTf)) { 506 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG; 507 } 508 #if defined(BCM_TOMAHAWK_SUPPORT) 509 if (SOC_MEM_FIELD_VALID(unit, offset_mem, 510 ENABLE_UDF_CONDITIONAL_CHECKf)) { 511 udf_ctrl->flags |= BCMI_XGS4_UDF_CONDITIONAL_CHECK; 512 } 513 #endif 514 515 #if defined(BCM_TRIDENT2_SUPPORT) 516 /* Check if flex hash is supported */ 517 if soc_feature(unit, soc_feature_flex_hashing) { 518 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_FLEXHASH; 519 } 520 /* Check if udf hash is supported */ 521 if soc_feature(unit, soc_feature_udf_hashing) { 522 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_UDFHASH; 523 } 524 #endif 525 526 #if defined(BCM_TOMAHAWK_SUPPORT) 527 if (SOC_IS_TOMAHAWKX(unit)) { 528 /* UDF Range Checker is supported only in Tomahawk. */ 529 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_RANGE_CHECK; 530 } 531 #endif 532 if soc_feature(unit, soc_feature_advanced_flex_counter) { 533 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_FLEX_COUNTER; 534 } 535 536 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, L4_DST_PORTf)) { 537 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_L4_DST_PORT; 538 } 539 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, OPAQUE_TAG_TYPEf)) { 540 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_OPAQUE_TAG_TYPE; 541 } 542 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, INT_PKTf)) { 543 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_INT_PKT; 544 } 545 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_PORT_NUMBERf)) { 546 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_SRC_PORT; 547 } 548 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, LOOPBACK_PKT_TYPEf)) { 549 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_LB_PKT_TYPE; 550 } 551 552 udf_ctrl->nentries = nentries; 553 udf_ctrl->noffsets = noffsets; 554 555 /* restriction merely for warmboot purposes */ 556 udf_ctrl->max_udfs = TD2_UDF_MAX_OBJECTS; 557 558 /* restriction merely for byte selection */ 559 udf_ctrl->max_parse_bytes = BCMI_XGS4_UDF_MAX_BYTE_SELECTION; 560 561 /* offset chunk granularity */ 562 if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF1_OFFSET4f)) { 563 udf_ctrl->gran = UDF_OFFSET_GRAN2; 564 } else { 565 udf_ctrl->gran = UDF_OFFSET_GRAN4; 566 } 567 568 /* Check if policer group is supported */ 569 if (soc_feature(unit, soc_feature_global_meter)) { 570 udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_POLICER_GROUP; 571 } 572 573 /* udf hash chunks */ 574 #if defined(BCM_TRIDENT2_SUPPORT) 575 if soc_feature(unit, soc_feature_udf_hashing) { 576 udf_ctrl->udf_hash_1 = 6; 577 udf_ctrl->udf_hash_2 = 7; 578 } 579 #endif 580 581 if (soc_feature(unit, soc_feature_udf_selector_support)) { 582 /* Allocate udf field module related resources */ 583 for (pipe_id = 0; pipe_id < SOC_MAX_NUM_PIPES; pipe_id++) { 584 udf_ctrl->max_chunks = 16; 585 udf_ctrl->udf_field_bmp[pipe_id].w = NULL; 586 _FP_XGS3_ALLOC(udf_ctrl->udf_field_bmp[pipe_id].w, 587 SHR_BITALLOCSIZE(udf_ctrl->max_chunks), 588 "UDF BMP"); 589 if (udf_ctrl->udf_field_bmp[pipe_id].w == NULL) { 590 return BCM_E_MEMORY; 591 } 592 } 593 } 594 595 udf_ctrl->udf_used_by_module = UDF_USED_BY_NONE; 596 597 return BCM_E_NONE; 598 } 599 600 /* 601 * Function: 602 * bcmi_xgs4_udf_hw_init 603 * Purpose: 604 * Clears the hardware tables related to UDF. 605 * Parameters: 606 * unit - (IN) Unit number. 607 * Returns: 608 * BCM_E_XXX 609 * Notes: 610 */ 611 STATIC int 612 bcmi_xgs4_udf_hw_init(int unit) 613 { 614 int rv; 615 616 /* Clear UDF_TCAM table */ 617 rv = soc_mem_clear(unit, UDF_CTRL(unit)->tcam_mem, MEM_BLOCK_ALL, TRUE); 618 SOC_IF_ERROR_RETURN(rv); 619 620 /* Clear UDF_OFFSET table */ 621 rv = soc_mem_clear(unit, UDF_CTRL(unit)->offset_mem, MEM_BLOCK_ALL, TRUE); 622 SOC_IF_ERROR_RETURN(rv); 623 624 return BCM_E_NONE; 625 } 626 627 628 #if defined (BCM_WARM_BOOT_SUPPORT) 629 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1, 3) 630 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1, 2) 631 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1, 1) 632 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1, 0) 633 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1, 4) 634 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1, 5) 635 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_5 636 637 /* Data structure for UDF Offset entry */ 638 struct bcmi_xgs4_wb_offset_entry_1_0 { 639 uint8 flags; 640 uint8 grp_id; 641 uint8 num_pkt_formats; 642 }; 643 644 /* Data structure for UDF offset info */ 645 struct bcmi_xgs4_wb_offset_info_1_0 { 646 647 uint8 layer; 648 uint8 start; 649 uint8 width; 650 uint8 flags; 651 652 uint16 num_pkt_formats; 653 654 uint16 id; 655 uint32 byte_bmap; 656 #if defined (BCM_TOMAHAWK_SUPPORT) 657 bcm_pbmp_t associated_ports; 658 uint32 associated_pipe; 659 #endif 660 }; 661 662 /* Data structure for UDF tcam info */ 663 struct bcmi_xgs4_wb_tcam_info_1_0 { 664 uint16 hw_id; 665 uint16 num_udfs; 666 667 uint16 id; 668 uint16 priority; 669 670 uint16 udf_id_list[MAX_UDF_OFFSET_CHUNKS]; 671 #if defined (BCM_TOMAHAWK_SUPPORT) 672 uint32 associated_pipe; 673 #endif 674 }; 675 676 #if defined (BCM_TOMAHAWK_SUPPORT) 677 struct bcmi_xgs4_wb_tcam_info_1_3 { 678 uint16 hw_idx; 679 uint32 class_id; 680 uint32 associated_pipe; 681 }; 682 683 struct bcmi_xgs4_wb_tcam_info_1_4 { 684 uint16 hw_idx[SOC_MAX_NUM_PIPES]; 685 uint16 num_udfs[SOC_MAX_NUM_PIPES]; 686 uint32 offset_bmap[SOC_MAX_NUM_PIPES]; 687 uint32 associated_pipes[SOC_MAX_NUM_PIPES]; 688 uint16 udf_id_list[MAX_UDF_ID_LIST]; 689 }; 690 #endif 691 692 struct bcmi_xgs4_wb_tcam_info_1_5 { 693 uint32 udf_field_bmp[SOC_MAX_NUM_PIPES]; 694 int max_chunks; 695 }; 696 697 /* Returns required scache size in bytes for version = 1_0 */ 698 STATIC int 699 bcmi_xgs4_udf_wb_scache_size_get_1_0(int unit, int *req_scache_size) 700 { 701 int alloc_size = 0; 702 bcmi_xgs4_udf_ctrl_t *udf_ctrl; 703 704 udf_ctrl = UDF_CTRL(unit); 705 706 /* Number of UDFs */ 707 alloc_size += sizeof(udf_ctrl->num_udfs); 708 709 /* Number of Packet formats */ 710 alloc_size += sizeof(udf_ctrl->num_pkt_formats); 711 712 #if defined (BCM_TOMAHAWK_SUPPORT) 713 if (SOC_IS_TOMAHAWKX(unit)) { 714 /* operation mode */ 715 alloc_size += sizeof(bcmi_xgs4_udf_oper_mode[unit]); 716 } 717 if ((SOC_IS_TOMAHAWKX(unit)) && 718 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 719 720 alloc_size += (udf_ctrl->noffsets * SOC_MAX_NUM_PIPES * 721 sizeof (struct bcmi_xgs4_wb_offset_entry_1_0)); 722 /* offset nodes */ 723 alloc_size += (udf_ctrl->max_udfs * SOC_MAX_NUM_PIPES * 724 sizeof(struct bcmi_xgs4_wb_offset_info_1_0)); 725 726 /* tcam nodes */ 727 alloc_size += (udf_ctrl->nentries * SOC_MAX_NUM_PIPES * 728 sizeof(struct bcmi_xgs4_wb_tcam_info_1_0)); 729 730 } else 731 #endif 732 { 733 /* offset entries */ 734 alloc_size += (udf_ctrl->noffsets * 735 sizeof (struct bcmi_xgs4_wb_offset_entry_1_0)); 736 737 /* offset nodes */ 738 alloc_size += (udf_ctrl->max_udfs * 739 sizeof(struct bcmi_xgs4_wb_offset_info_1_0)); 740 741 /* tcam nodes */ 742 alloc_size += (udf_ctrl->nentries * 743 sizeof(struct bcmi_xgs4_wb_tcam_info_1_0)); 744 } 745 746 *req_scache_size = alloc_size; 747 748 return BCM_E_NONE; 749 } 750 751 /* Returns required scache size in bytes for version = 1_1 */ 752 STATIC int 753 bcmi_xgs4_udf_wb_scache_size_get_1_1(int unit, int *req_scache_size) 754 { 755 int alloc_size = 0; 756 757 /* udf used by module */ 758 alloc_size += sizeof(UDF_CTRL(unit)->udf_used_by_module); 759 760 *req_scache_size += alloc_size; 761 762 return BCM_E_NONE; 763 } 764 765 #if defined (BCM_TOMAHAWK_SUPPORT) 766 /* Returns required scache size in bytes for version = 1_3 */ 767 STATIC int 768 bcmi_xgs4_udf_wb_scache_size_get_1_3(int unit, int *req_scache_size) 769 { 770 int alloc_size = 0; 771 772 alloc_size += (UDF_CTRL(unit)->nentries * SOC_MAX_NUM_PIPES * 773 sizeof(struct bcmi_xgs4_wb_tcam_info_1_3)); 774 775 *req_scache_size += alloc_size; 776 777 return BCM_E_NONE; 778 } 779 780 STATIC int 781 bcmi_xgs4_udf_wb_scache_size_get_1_4(int unit, int *req_scache_size) 782 { 783 int alloc_size = 0; 784 785 alloc_size = (UDF_CTRL(unit)->nentries * 786 sizeof(struct bcmi_xgs4_wb_tcam_info_1_4)); 787 788 *req_scache_size += alloc_size; 789 790 return BCM_E_NONE; 791 } 792 #endif 793 794 795 STATIC int 796 bcmi_xgs4_udf_wb_scache_size_get_1_5(int unit, int *req_scache_size) 797 { 798 799 *req_scache_size += sizeof(struct bcmi_xgs4_wb_tcam_info_1_5); 800 801 return BCM_E_NONE; 802 } 803 804 805 /* get warmboot recover version */ 806 STATIC int 807 bcmi_xgs4_udf_recovered_version_get( 808 int unit, 809 uint16 *recovered_ver) 810 { 811 int rv = BCM_E_INTERNAL; 812 uint8 *scache_ptr; 813 soc_scache_handle_t scache_handle; 814 815 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_UDF, 0); 816 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 817 0, &scache_ptr, 818 BCM_WB_DEFAULT_VERSION, recovered_ver); 819 820 if (rv == BCM_E_NOT_FOUND) { 821 *recovered_ver = BCM_WB_DEFAULT_VERSION; 822 return BCM_E_NONE; 823 } 824 825 BCM_IF_ERROR_RETURN(rv); 826 827 return BCM_E_NONE; 828 } 829 830 /* Recovers offsets info nodes from scache for version = 1_0 */ 831 STATIC int 832 bcmi_xgs4_udf_wb_offset_info_reinit_1_0(int unit, int num_offset_nodes, 833 uint8 **scache_ptr) 834 { 835 int rv; 836 int i; 837 int val = 0; 838 uint32 offset_reserve[MAX_UDF_OFFSET_CHUNKS] = {0}; 839 int gran, max_chunks; 840 bcm_udf_t udf_info; 841 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 842 bcmi_xgs4_udf_offset_entry_t *offset_entry_array; /* offset entries array. */ 843 struct bcmi_xgs4_wb_offset_info_1_0 *scache_offset_p; 844 uint8 byte_offset = 0; 845 uint16 recovered_ver = BCM_WB_DEFAULT_VERSION; 846 #if defined (BCM_TOMAHAWK_SUPPORT) 847 int offset_num, port; 848 soc_info_t *si; 849 si = &SOC_INFO(unit); 850 #endif 851 852 BCM_IF_ERROR_RETURN( 853 bcmi_xgs4_udf_recovered_version_get( 854 unit, 855 &recovered_ver)); 856 857 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 858 max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 859 860 scache_offset_p = (struct bcmi_xgs4_wb_offset_info_1_0 *)(*scache_ptr); 861 862 /* Recover offset nodes from scache */ 863 while (num_offset_nodes > 0) { 864 865 offset_info = NULL; 866 sal_memset(offset_reserve, 0, sizeof(offset_reserve)); 867 868 udf_info.start = BYTES2BITS(scache_offset_p->start); 869 udf_info.width = BYTES2BITS(scache_offset_p->width); 870 udf_info.layer = scache_offset_p->layer; 871 #if defined (BCM_TOMAHAWK_SUPPORT) 872 if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) && 873 (recovered_ver >= BCM_WB_VERSION_1_2)) { 874 SOC_PBMP_ASSIGN(udf_info.ports, scache_offset_p->associated_ports); 875 } 876 #endif 877 878 rv = bcmi_xgs4_udf_offset_info_add(unit, &udf_info, &offset_info); 879 BCM_IF_ERROR_RETURN(rv); 880 881 offset_info->udf_id = scache_offset_p->id; 882 offset_info->flags = scache_offset_p->flags; 883 offset_info->num_pkt_formats = scache_offset_p->num_pkt_formats; 884 offset_info->byte_bmap = scache_offset_p->byte_bmap; 885 886 #if defined (BCM_TOMAHAWK_SUPPORT) 887 if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) && 888 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 889 SOC_PBMP_ITER(udf_info.ports, port) { 890 offset_info->associated_pipe = si->port_pipe[port]; 891 break; 892 } 893 offset_entry_array = 894 UDF_CTRL(unit)->offset_entry_array_per_pipe[offset_info->associated_pipe]; 895 } else 896 #endif 897 { 898 offset_entry_array = UDF_CTRL(unit)->offset_entry_array; 899 } 900 /* Compute byte offset again and store */ 901 if (gran == UDF_OFFSET_GRAN2) { 902 byte_offset = offset_info->start % gran; 903 } else { 904 if (offset_info->layer == bcmUdfLayerL2Header) { 905 byte_offset = (offset_info->start + 2) % gran; 906 } else { 907 byte_offset = offset_info->start % gran; 908 } 909 } 910 offset_info->byte_offset = byte_offset; 911 912 if (offset_info->udf_id > UDF_CTRL(unit)->udf_id_running) { 913 UDF_CTRL(unit)->udf_id_running = offset_info->udf_id; 914 } 915 916 for (i = 0; i < max_chunks; i++) { 917 SHR_BITTEST_RANGE(&(scache_offset_p->byte_bmap), 918 (i * gran), gran, val); 919 if (val) { 920 SHR_BITCOPY_RANGE(&offset_reserve[i], 0, &(scache_offset_p->byte_bmap), i*gran, gran); 921 SHR_BITSET(&(offset_info->hw_bmap), i); 922 offset_info->grp_id = offset_entry_array[i].grp_id; 923 } 924 } 925 926 /* Mark the global bitmap as used */ 927 (void) bcmi_xgs4_udf_offset_reserve(unit, max_chunks, (int *)offset_reserve, 928 offset_info->associated_pipe); 929 930 scache_offset_p++; 931 num_offset_nodes--; 932 } 933 934 *scache_ptr = (uint8 *)scache_offset_p; 935 936 /* clear invalid udf_offset cache recovery */ 937 #if defined (BCM_TOMAHAWK_SUPPORT) 938 if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) { 939 offset_num = soc_mem_index_count(unit, FP_UDF_OFFSETm); 940 for(i=0;i<offset_num;i++){ 941 if (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) { 942 soc_mem_cache_invalidate(unit, FP_UDF_OFFSETm, MEM_BLOCK_ALL, i); 943 } 944 else{ 945 soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE0m, MEM_BLOCK_ALL, i); 946 soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE1m, MEM_BLOCK_ALL, i); 947 soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE2m, MEM_BLOCK_ALL, i); 948 soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE3m, MEM_BLOCK_ALL, i); 949 } 950 } 951 } 952 #endif 953 return BCM_E_NONE; 954 } 955 956 /* Recovers tcam info nodes from scache for version = 1_0 */ 957 958 STATIC int 959 bcmi_xgs4_udf_wb_tcam_info_reinit_1_0(int unit, int num_tcam_nodes, 960 uint8 **scache_ptr) 961 { 962 uint32 *buffer; /* Hw buffer to dma udf tcam. */ 963 uint32 *entry_ptr = 0; /* Tcam entry pointer. */ 964 int alloc_size; /* Memory allocation size. */ 965 int entry_size; /* Single tcam entry size. */ 966 soc_mem_t tcam_mem; /* UDF_TCAM memory */ 967 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr; /* Tcam entries array. */ 968 int idx; /* Tcam entries iterator. */ 969 int rv; /* Operation return status. */ 970 int udf_id; 971 bcmi_xgs4_udf_offset_info_t *offset_info; 972 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 973 fp_udf_tcam_entry_t *tcam_buf; 974 struct bcmi_xgs4_wb_tcam_info_1_0 *scache_tcam_p; 975 uint16 recovered_ver = BCM_WB_DEFAULT_VERSION; 976 977 BCM_IF_ERROR_RETURN( 978 bcmi_xgs4_udf_recovered_version_get( 979 unit, 980 &recovered_ver)); 981 982 tcam_mem = UDF_CTRL(unit)->tcam_mem; 983 tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array; 984 985 entry_size = sizeof(fp_udf_tcam_entry_t); 986 alloc_size = SOC_MEM_TABLE_BYTES(unit, tcam_mem); 987 988 /* Allocate memory buffer. */ 989 buffer = soc_cm_salloc(unit, alloc_size, "Udf tcam"); 990 if (buffer == NULL) { 991 return (BCM_E_MEMORY); 992 } 993 994 sal_memset(buffer, 0, alloc_size); 995 996 /* Read table to the buffer. */ 997 rv = soc_mem_read_range(unit, tcam_mem, MEM_BLOCK_ANY, 998 soc_mem_index_min(unit, tcam_mem), 999 soc_mem_index_max(unit, tcam_mem), buffer); 1000 if (BCM_FAILURE(rv)) { 1001 soc_cm_sfree(unit, buffer); 1002 return (BCM_E_INTERNAL); 1003 } 1004 1005 1006 1007 scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_0 *)(*scache_ptr); 1008 1009 /* Recover tcam info from scache */ 1010 while (num_tcam_nodes > 0) { 1011 1012 tcam_info = sal_alloc(sizeof(bcmi_xgs4_udf_tcam_info_t), "tcam info"); 1013 sal_memset(tcam_info, 0, sizeof(bcmi_xgs4_udf_tcam_info_t)); 1014 1015 idx = scache_tcam_p->hw_id; 1016 tcam_info->hw_idx = idx; 1017 tcam_info->pkt_format_id = scache_tcam_p->id; 1018 tcam_info->priority = scache_tcam_p->priority; 1019 tcam_info->num_udfs = scache_tcam_p->num_udfs; 1020 #if defined (BCM_TOMAHAWK_SUPPORT) 1021 if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) && 1022 (recovered_ver >= BCM_WB_VERSION_1_2) && 1023 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 1024 tcam_info->associated_pipe = scache_tcam_p->associated_pipe; 1025 if (tcam_info->associated_pipe == BCMI_XGS4_UDF_INVALID_PIPE_NUM) { 1026 return BCM_E_PARAM; 1027 } 1028 tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array_per_pipe[tcam_info->associated_pipe]; 1029 tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[tcam_info->associated_pipe]; 1030 } 1031 #endif 1032 entry_ptr = soc_mem_table_idx_to_pointer(unit, tcam_mem, uint32 *, 1033 buffer, idx); 1034 1035 tcam_buf = (fp_udf_tcam_entry_t *)&(tcam_info->hw_buf); 1036 sal_memcpy(tcam_buf, entry_ptr, entry_size); 1037 1038 if (soc_mem_field32_get(unit, tcam_mem, entry_ptr, VALIDf)) { 1039 tcam_entry_arr[idx].valid = 1; 1040 tcam_entry_arr[idx].tcam_info = tcam_info; 1041 } 1042 1043 /* Not installed entries will have 512 as hw_idx */ 1044 if (idx < MAX_UDF_TCAM_ENTRIES) { 1045 1046 for (idx = 0; idx < MAX_UDF_OFFSET_CHUNKS; idx++) { 1047 1048 udf_id = scache_tcam_p->udf_id_list[idx]; 1049 1050 if (udf_id != 0) { 1051 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, 1052 &offset_info); 1053 /* Continue recovering other udfs added to the tcam entry */ 1054 if (BCM_SUCCESS(rv)) { 1055 tcam_info->offset_info_list[offset_info->grp_id] = 1056 offset_info; 1057 tcam_info->offset_bmap |= offset_info->hw_bmap; 1058 tcam_info->udf_id_list[idx] = offset_info->udf_id; 1059 } 1060 } 1061 } 1062 if (tcam_info->pkt_format_id > 1063 UDF_CTRL(unit)->udf_pkt_format_id_running) { 1064 1065 UDF_CTRL(unit)->udf_pkt_format_id_running = 1066 tcam_info->pkt_format_id; 1067 } 1068 1069 } 1070 1071 /* Continue recovering other packet format entries even on failure */ 1072 (void) bcmi_xgs4_udf_tcam_node_add(unit, tcam_info); 1073 1074 scache_tcam_p++; 1075 num_tcam_nodes--; 1076 } 1077 1078 *scache_ptr = (uint8 *)scache_tcam_p; 1079 1080 soc_cm_sfree(unit, buffer); 1081 1082 return BCM_E_NONE; 1083 } 1084 1085 1086 /* Syncs offset nodes info into scache for version = 1_0 */ 1087 STATIC int 1088 bcmi_xgs4_udf_wb_offset_info_sync_1_0(int unit, int num_offset_nodes, 1089 uint8 **scache_ptr) 1090 { 1091 bcmi_xgs4_udf_offset_info_t *offset_info; 1092 struct bcmi_xgs4_wb_offset_info_1_0 *scache_offset_p; 1093 1094 scache_offset_p = (struct bcmi_xgs4_wb_offset_info_1_0 *)(*scache_ptr); 1095 1096 offset_info = UDF_CTRL(unit)->offset_info_head; 1097 1098 /* Recover offset nodes from scache */ 1099 while (num_offset_nodes > 0) { 1100 1101 scache_offset_p->layer = offset_info->layer; 1102 scache_offset_p->start = offset_info->start; 1103 scache_offset_p->width = offset_info->width; 1104 scache_offset_p->flags = offset_info->flags; 1105 1106 scache_offset_p->num_pkt_formats = offset_info->num_pkt_formats; 1107 1108 scache_offset_p->id = offset_info->udf_id; 1109 scache_offset_p->byte_bmap = offset_info->byte_bmap; 1110 #if defined (BCM_TOMAHAWK_SUPPORT) 1111 if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) { 1112 scache_offset_p->associated_pipe = offset_info->associated_pipe; 1113 SOC_PBMP_ASSIGN(scache_offset_p->associated_ports, offset_info->associated_ports); 1114 } 1115 #endif 1116 num_offset_nodes--; 1117 scache_offset_p++; 1118 offset_info = offset_info->next; 1119 } 1120 1121 *scache_ptr = (uint8 *)scache_offset_p; 1122 1123 return BCM_E_NONE; 1124 } 1125 1126 /* Syncs tcam nodes info into scache for version = 1_0 */ 1127 STATIC int 1128 bcmi_xgs4_udf_wb_tcam_info_sync_1_0(int unit, int num_tcam_nodes, 1129 uint8 **scache_ptr) 1130 { 1131 int idx; 1132 bcmi_xgs4_udf_tcam_info_t *tcam_info; 1133 struct bcmi_xgs4_wb_tcam_info_1_0 *scache_tcam_p; 1134 1135 1136 tcam_info = UDF_CTRL(unit)->tcam_info_head; 1137 scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_0 *)(*scache_ptr); 1138 1139 /* Sync data to scache */ 1140 while (num_tcam_nodes > 0) { 1141 1142 idx = scache_tcam_p->hw_id; 1143 scache_tcam_p->hw_id = tcam_info->hw_idx; 1144 scache_tcam_p->id = tcam_info->pkt_format_id; 1145 scache_tcam_p->priority = tcam_info->priority; 1146 scache_tcam_p->num_udfs = tcam_info->num_udfs; 1147 #if defined (BCM_TOMAHAWK_SUPPORT) 1148 if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) { 1149 scache_tcam_p->associated_pipe = tcam_info->associated_pipe; 1150 } 1151 #endif 1152 1153 for (idx = 0; idx < MAX_UDF_OFFSET_CHUNKS; idx++) { 1154 if (tcam_info->offset_info_list[idx] != NULL) { 1155 scache_tcam_p->udf_id_list[idx] = 1156 (tcam_info->offset_info_list[idx])->udf_id; 1157 } else { 1158 scache_tcam_p->udf_id_list[idx] = 0; 1159 } 1160 } 1161 1162 scache_tcam_p++; 1163 num_tcam_nodes--; 1164 tcam_info = tcam_info->next; 1165 } 1166 1167 *scache_ptr = (uint8 *)scache_tcam_p; 1168 1169 return BCM_E_NONE; 1170 } 1171 1172 #if defined (BCM_TOMAHAWK_SUPPORT) && defined (BCM_WB_VERSION_1_3) 1173 STATIC int 1174 bcmi_xgs4_udf_wb_offset_info_reinit_1_2_to_1_3 1175 (int unit, int num_offset_nodes, 1176 uint8 **scache_ptr, 1177 struct bcmi_xgs4_wb_offset_entry_1_0 *offset_entry_scache_p) 1178 { 1179 1180 int rv; 1181 int i; 1182 int val = 0; 1183 uint32 offset_reserve[MAX_UDF_OFFSET_CHUNKS] = {0}; 1184 int gran; 1185 bcm_udf_t udf_info; 1186 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 1187 bcmi_xgs4_udf_offset_entry_t *offset_entry_array; /* offset entries array. */ 1188 struct bcmi_xgs4_wb_offset_entry_1_0 *offset_entry_recover_p; 1189 struct bcmi_xgs4_wb_offset_info_1_0 *scache_offset_p; 1190 uint8 byte_offset = 0; 1191 int offset_num; 1192 int port = 0, max_chunks = 0; 1193 soc_info_t *si; 1194 si = &SOC_INFO(unit); 1195 1196 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 1197 max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 1198 1199 offset_entry_recover_p = offset_entry_scache_p; 1200 for (i = 0; i < max_chunks; i++) { 1201 /* skip offset entry reinit */ 1202 offset_entry_scache_p++; 1203 } 1204 scache_offset_p = (struct bcmi_xgs4_wb_offset_info_1_0 *)offset_entry_scache_p; 1205 1206 /* Recover offset nodes from scache */ 1207 while (num_offset_nodes > 0) { 1208 1209 offset_info = NULL; 1210 sal_memset(offset_reserve, 0, sizeof(offset_reserve)); 1211 1212 udf_info.start = BYTES2BITS(scache_offset_p->start); 1213 udf_info.width = BYTES2BITS(scache_offset_p->width); 1214 udf_info.layer = scache_offset_p->layer; 1215 1216 SOC_PBMP_ASSIGN(udf_info.ports, scache_offset_p->associated_ports); 1217 1218 rv = bcmi_xgs4_udf_offset_info_add(unit, &udf_info, &offset_info); 1219 BCM_IF_ERROR_RETURN(rv); 1220 1221 offset_info->udf_id = scache_offset_p->id; 1222 offset_info->flags = scache_offset_p->flags; 1223 offset_info->num_pkt_formats = scache_offset_p->num_pkt_formats; 1224 offset_info->byte_bmap = scache_offset_p->byte_bmap; 1225 1226 SOC_PBMP_ITER(udf_info.ports, port) { 1227 offset_info->associated_pipe = si->port_pipe[port]; 1228 break; 1229 } 1230 1231 offset_entry_array = 1232 UDF_CTRL(unit)->offset_entry_array_per_pipe[offset_info->associated_pipe]; 1233 1234 /* Compute byte offset again and store */ 1235 if (gran == UDF_OFFSET_GRAN2) { 1236 byte_offset = offset_info->start % gran; 1237 } else { 1238 if (offset_info->layer == bcmUdfLayerL2Header) { 1239 byte_offset = (offset_info->start + 2) % gran; 1240 } else { 1241 byte_offset = offset_info->start % gran; 1242 } 1243 } 1244 offset_info->byte_offset = byte_offset; 1245 1246 if (offset_info->udf_id > UDF_CTRL(unit)->udf_id_running) { 1247 UDF_CTRL(unit)->udf_id_running = offset_info->udf_id; 1248 } 1249 1250 for (i = 0; i < max_chunks; i++) { 1251 SHR_BITTEST_RANGE(&(scache_offset_p->byte_bmap), 1252 (i * gran), gran, val); 1253 offset_entry_scache_p = offset_entry_recover_p; 1254 if (val) { 1255 SHR_BITCOPY_RANGE(&offset_reserve[i], 0, &(scache_offset_p->byte_bmap), i*gran, gran); 1256 SHR_BITSET(&(offset_info->hw_bmap), i); 1257 1258 offset_entry_scache_p += i; 1259 offset_entry_array[i].flags = offset_entry_scache_p->flags; 1260 offset_entry_array[i].grp_id = offset_entry_scache_p->grp_id; 1261 offset_entry_array[i].num_pkt_formats = offset_entry_scache_p->num_pkt_formats; 1262 1263 offset_info->grp_id = offset_entry_scache_p->grp_id; 1264 1265 } 1266 } 1267 1268 /* Mark the global bitmap as used */ 1269 (void) bcmi_xgs4_udf_offset_reserve(unit, max_chunks, (int *)offset_reserve, 1270 offset_info->associated_pipe); 1271 1272 scache_offset_p++; 1273 num_offset_nodes--; 1274 } 1275 1276 *scache_ptr = (uint8 *)scache_offset_p; 1277 1278 /* clear invalid udf_offset cache recovery */ 1279 offset_num = soc_mem_index_count(unit, FP_UDF_OFFSETm); 1280 for(i=0;i<offset_num;i++){ 1281 if (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) { 1282 soc_mem_cache_invalidate(unit, FP_UDF_OFFSETm, MEM_BLOCK_ALL, i); 1283 } 1284 else{ 1285 soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE0m, MEM_BLOCK_ALL, i); 1286 soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE1m, MEM_BLOCK_ALL, i); 1287 soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE2m, MEM_BLOCK_ALL, i); 1288 soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE3m, MEM_BLOCK_ALL, i); 1289 } 1290 } 1291 1292 rv = bcmi_xgs4_udf_wb_tcam_info_reinit_1_0(unit, 1293 UDF_CTRL(unit)->num_pkt_formats, scache_ptr); 1294 BCM_IF_ERROR_RETURN(rv); 1295 1296 return BCM_E_NONE; 1297 } 1298 1299 /* Recovers UDF control state for offset multipipe support */ 1300 STATIC int 1301 bcmi_xgs4_udf_wb_reinit_multipipe 1302 (int unit, 1303 uint8 **scache_ptr, 1304 struct bcmi_xgs4_wb_offset_entry_1_0* offset_entry_scache_p, 1305 uint16 recovered_ver, int max_chunks 1306 ) 1307 { 1308 int pipe, i, rv; 1309 bcmi_xgs4_udf_offset_entry_t *offset_entry; 1310 1311 if (recovered_ver >= BCM_WB_VERSION_1_3) { 1312 for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) { 1313 for (i = 0; i < max_chunks; i++) { 1314 offset_entry = &(UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe][i]); 1315 offset_entry->flags = offset_entry_scache_p->flags; 1316 offset_entry->grp_id = offset_entry_scache_p->grp_id; 1317 offset_entry->num_pkt_formats = offset_entry_scache_p->num_pkt_formats; 1318 offset_entry_scache_p++; 1319 } 1320 } 1321 } else { 1322 rv = bcmi_xgs4_udf_wb_offset_info_reinit_1_2_to_1_3(unit, 1323 UDF_CTRL(unit)->num_udfs, 1324 scache_ptr, offset_entry_scache_p); 1325 return rv; 1326 } 1327 *scache_ptr = (uint8 *)offset_entry_scache_p; 1328 1329 rv = bcmi_xgs4_udf_wb_offset_info_reinit_1_0(unit, 1330 UDF_CTRL(unit)->num_udfs, scache_ptr); 1331 BCM_IF_ERROR_RETURN(rv); 1332 1333 rv = bcmi_xgs4_udf_wb_tcam_info_reinit_1_0(unit, 1334 UDF_CTRL(unit)->num_pkt_formats, scache_ptr); 1335 BCM_IF_ERROR_RETURN(rv); 1336 1337 return BCM_E_NONE; 1338 1339 } 1340 #endif /* (BCM_TOMAHAWK_SUPPORT) && (BCM_WB_VERSION_1_3) */ 1341 1342 /* Recovers UDF control state from scache for version = 1_0 */ 1343 STATIC int 1344 bcmi_xgs4_udf_wb_reinit_1_0(int unit, uint8 **scache_ptr) 1345 { 1346 int rv; 1347 int i; 1348 int max_chunks; 1349 bcmi_xgs4_udf_offset_entry_t *offset_entry; 1350 struct bcmi_xgs4_wb_offset_entry_1_0 *offset_entry_scache_p; 1351 uint32 *u32_scache_p; 1352 uint16 recovered_ver = BCM_WB_DEFAULT_VERSION; 1353 1354 BCM_IF_ERROR_RETURN( 1355 bcmi_xgs4_udf_recovered_version_get( 1356 unit, 1357 &recovered_ver)); 1358 1359 max_chunks = UDF_CTRL(unit)->noffsets; 1360 1361 u32_scache_p = (uint32 *)(*scache_ptr); 1362 1363 #if defined (BCM_TOMAHAWK_SUPPORT) 1364 if ((SOC_IS_TOMAHAWKX(unit)) && 1365 (recovered_ver >= BCM_WB_VERSION_1_2)) { 1366 /* Operation Mode Retrieval */ 1367 bcmi_xgs4_udf_oper_mode_set(unit,u32_scache_p[2]); 1368 } 1369 #endif 1370 1371 /* Number of UDFs created */ 1372 UDF_CTRL(unit)->num_udfs = *u32_scache_p; 1373 u32_scache_p++; 1374 1375 /* Number of Packet formats created */ 1376 UDF_CTRL(unit)->num_pkt_formats = *u32_scache_p; 1377 u32_scache_p++; 1378 1379 #if defined (BCM_TOMAHAWK_SUPPORT) 1380 if ((SOC_IS_TOMAHAWKX(unit)) && 1381 (recovered_ver >= BCM_WB_VERSION_1_2)) { 1382 /* Pass Operation Mode */ 1383 u32_scache_p++; 1384 } 1385 #endif 1386 offset_entry_scache_p = 1387 (struct bcmi_xgs4_wb_offset_entry_1_0 *)u32_scache_p; 1388 1389 1390 #if defined (BCM_TOMAHAWK_SUPPORT) && defined (BCM_WB_VERSION_1_3) 1391 if ((SOC_IS_TOMAHAWKX(unit)) && 1392 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 1393 rv = bcmi_xgs4_udf_wb_reinit_multipipe(unit, scache_ptr, 1394 offset_entry_scache_p, 1395 recovered_ver, max_chunks); 1396 return rv; 1397 } 1398 #endif 1399 for (i = 0; i < max_chunks; i++) { 1400 offset_entry = &(UDF_CTRL(unit)->offset_entry_array[i]); 1401 1402 offset_entry->flags = offset_entry_scache_p->flags; 1403 offset_entry->grp_id = offset_entry_scache_p->grp_id; 1404 offset_entry->num_pkt_formats = offset_entry_scache_p->num_pkt_formats; 1405 1406 offset_entry_scache_p++; 1407 } 1408 *scache_ptr = (uint8 *)offset_entry_scache_p; 1409 1410 rv = bcmi_xgs4_udf_wb_offset_info_reinit_1_0(unit, 1411 UDF_CTRL(unit)->num_udfs, scache_ptr); 1412 BCM_IF_ERROR_RETURN(rv); 1413 1414 rv = bcmi_xgs4_udf_wb_tcam_info_reinit_1_0(unit, 1415 UDF_CTRL(unit)->num_pkt_formats, scache_ptr); 1416 BCM_IF_ERROR_RETURN(rv); 1417 1418 return BCM_E_NONE; 1419 } 1420 1421 /* Recovers UDF control state from scache for version = 1_1 */ 1422 STATIC int 1423 bcmi_xgs4_udf_wb_reinit_1_1(int unit, uint8 **scache_ptr) 1424 { 1425 uint32 *u32_scache_p; 1426 1427 u32_scache_p = (uint32 *)(*scache_ptr); 1428 1429 /* Udf resource of used module */ 1430 UDF_CTRL(unit)->udf_used_by_module = *u32_scache_p; 1431 u32_scache_p++; 1432 1433 *scache_ptr = (uint8 *)u32_scache_p; 1434 1435 return BCM_E_NONE; 1436 } 1437 1438 #if defined (BCM_TOMAHAWK_SUPPORT) 1439 /* Recovers UDF control state from scache for version = 1_3 */ 1440 STATIC int 1441 bcmi_xgs4_udf_wb_reinit_1_3(int unit, uint8 **scache_ptr) 1442 { 1443 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr; /* Tcam entries array. */ 1444 int num_tcam_nodes; 1445 struct bcmi_xgs4_wb_tcam_info_1_3 *scache_tcam_p; 1446 1447 scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_3 *)(*scache_ptr); 1448 num_tcam_nodes = UDF_CTRL(unit)->num_pkt_formats; 1449 1450 while (num_tcam_nodes > 0) { 1451 if (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) { 1452 tcam_entry_arr = 1453 UDF_CTRL(unit)->tcam_entry_array_per_pipe[scache_tcam_p->associated_pipe]; 1454 } else { 1455 tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array; 1456 } 1457 if (tcam_entry_arr[scache_tcam_p->hw_idx].tcam_info != NULL) { 1458 tcam_entry_arr[scache_tcam_p->hw_idx].tcam_info->class_id = scache_tcam_p->class_id; 1459 } 1460 scache_tcam_p++; 1461 num_tcam_nodes--; 1462 } 1463 1464 *scache_ptr = (uint8 *)scache_tcam_p; 1465 1466 return BCM_E_NONE; 1467 } 1468 1469 STATIC int 1470 bcmi_xgs4_udf_wb_tcam_info_reinit_1_2_to_1_4(int unit) 1471 { 1472 int idx; 1473 int pipe; 1474 bcmi_xgs4_udf_tcam_info_t *tcam_info; 1475 1476 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 1477 bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) { 1478 tcam_info = UDF_CTRL(unit)->tcam_info_head; 1479 1480 while (tcam_info) { 1481 for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) { 1482 tcam_info->hw_idx_per_pipe[idx] = MAX_UDF_TCAM_ENTRIES; 1483 tcam_info->associated_pipes[idx] = BCMI_XGS4_UDF_INVALID_PIPE_NUM; 1484 } 1485 1486 pipe = tcam_info->associated_pipe; 1487 tcam_info->hw_idx_per_pipe[pipe] = tcam_info->hw_idx; 1488 tcam_info->num_udfs_per_pipe[pipe] = tcam_info->num_udfs; 1489 tcam_info->offset_bmap_per_pipe[pipe] = tcam_info->offset_bmap; 1490 tcam_info->associated_pipes[pipe] = pipe; 1491 tcam_info = tcam_info->next; 1492 } 1493 } 1494 1495 return BCM_E_NONE; 1496 } 1497 1498 STATIC int 1499 bcmi_xgs4_udf_wb_reinit_1_4(int unit, uint8 **scache_ptr) 1500 { 1501 int idx; 1502 int pipe; 1503 int hw_idx; 1504 soc_mem_t tcam_mem; 1505 bcmi_xgs4_udf_tcam_info_t *tcam_info; 1506 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr; 1507 struct bcmi_xgs4_wb_tcam_info_1_4 *scache_tcam_p; 1508 1509 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 1510 bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) { 1511 tcam_info = UDF_CTRL(unit)->tcam_info_head; 1512 scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_4*)(*scache_ptr); 1513 1514 while (tcam_info) { 1515 for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) { 1516 tcam_info->hw_idx_per_pipe[idx] = scache_tcam_p->hw_idx[idx]; 1517 tcam_info->num_udfs_per_pipe[idx] = scache_tcam_p->num_udfs[idx]; 1518 tcam_info->offset_bmap_per_pipe[idx] = scache_tcam_p->offset_bmap[idx]; 1519 tcam_info->associated_pipes[idx] = scache_tcam_p->associated_pipes[idx]; 1520 1521 pipe = tcam_info->associated_pipes[idx]; 1522 hw_idx = tcam_info->hw_idx_per_pipe[idx]; 1523 if (hw_idx == MAX_UDF_TCAM_ENTRIES || 1524 pipe == BCMI_XGS4_UDF_INVALID_PIPE_NUM) { 1525 continue; 1526 } 1527 1528 tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array_per_pipe[pipe]; 1529 tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[pipe]; 1530 1531 BCM_IF_ERROR_RETURN( 1532 soc_mem_read(unit, tcam_mem, MEM_BLOCK_ALL, hw_idx, &tcam_info->hw_buf)); 1533 1534 if (soc_mem_field32_get(unit, tcam_mem, &tcam_info->hw_buf, VALIDf)) { 1535 tcam_entry_arr[hw_idx].valid = 1; 1536 tcam_entry_arr[hw_idx].tcam_info = tcam_info; 1537 } 1538 } 1539 1540 for (idx = 0; idx < MAX_UDF_ID_LIST; idx++) { 1541 tcam_info->udf_id_list[idx] = scache_tcam_p->udf_id_list[idx]; 1542 } 1543 1544 scache_tcam_p++; 1545 tcam_info = tcam_info->next; 1546 } 1547 1548 *scache_ptr = (uint8 *)scache_tcam_p; 1549 } 1550 1551 return BCM_E_NONE; 1552 } 1553 #endif 1554 1555 STATIC int 1556 bcmi_xgs4_udf_wb_reinit_1_5(int unit, uint8 **scache_ptr) 1557 { 1558 int idx; 1559 struct bcmi_xgs4_wb_tcam_info_1_5 *scache_tcam_p; 1560 1561 scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_5*)(*scache_ptr); 1562 1563 for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) { 1564 sal_memcpy(UDF_CTRL(unit)->udf_field_bmp[idx].w, 1565 &(scache_tcam_p->udf_field_bmp[idx]), 1566 sizeof(uint32)); 1567 } 1568 UDF_CTRL(unit)->max_chunks = scache_tcam_p->max_chunks; 1569 1570 scache_tcam_p++; 1571 *scache_ptr = (uint8 *)scache_tcam_p; 1572 1573 1574 return BCM_E_NONE; 1575 } 1576 1577 /* Syncs UDF control state into scache for version = 1_0 */ 1578 STATIC int 1579 bcmi_xgs4_udf_wb_sync_1_0(int unit, uint8 **scache_ptr) 1580 { 1581 int rv; 1582 int i; 1583 int max_chunks; 1584 struct bcmi_xgs4_wb_offset_entry_1_0 *offset_entry_scache_p; 1585 uint32 *u32_scache_p; 1586 1587 #if defined (BCM_TOMAHAWK_SUPPORT) 1588 int pipe = 0; 1589 #endif 1590 max_chunks = UDF_CTRL(unit)->noffsets; 1591 1592 u32_scache_p = (uint32 *)(*scache_ptr); 1593 1594 /* Number of UDFs created */ 1595 *u32_scache_p = UDF_CTRL(unit)->num_udfs; 1596 u32_scache_p++; 1597 1598 /* Number of Packet formats created */ 1599 *u32_scache_p = UDF_CTRL(unit)->num_pkt_formats; 1600 u32_scache_p++; 1601 1602 #if defined (BCM_TOMAHAWK_SUPPORT) 1603 if (SOC_IS_TOMAHAWKX(unit)) { 1604 /* saving operation mode */ 1605 *u32_scache_p = bcmi_xgs4_udf_oper_mode[unit] ; 1606 u32_scache_p++; 1607 } 1608 #endif 1609 1610 offset_entry_scache_p = 1611 (struct bcmi_xgs4_wb_offset_entry_1_0 *)u32_scache_p; 1612 1613 #if defined (BCM_TOMAHAWK_SUPPORT) 1614 if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) && 1615 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 1616 1617 for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) { 1618 for (i = 0; i < max_chunks; i++) { 1619 offset_entry_scache_p->flags = 1620 (UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe][i]).flags; 1621 offset_entry_scache_p->grp_id = 1622 (UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe][i]).grp_id; 1623 offset_entry_scache_p->num_pkt_formats = 1624 (UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe][i]).num_pkt_formats; 1625 offset_entry_scache_p++; 1626 } 1627 } 1628 } else 1629 #endif 1630 { 1631 for (i = 0; i < max_chunks; i++) { 1632 offset_entry_scache_p->flags = 1633 (UDF_CTRL(unit)->offset_entry_array[i]).flags; 1634 offset_entry_scache_p->grp_id = 1635 (UDF_CTRL(unit)->offset_entry_array[i]).grp_id; 1636 offset_entry_scache_p->num_pkt_formats = 1637 (UDF_CTRL(unit)->offset_entry_array[i]).num_pkt_formats; 1638 1639 offset_entry_scache_p++; 1640 } 1641 } 1642 1643 *scache_ptr = (uint8 *)offset_entry_scache_p; 1644 1645 rv = bcmi_xgs4_udf_wb_offset_info_sync_1_0(unit, 1646 UDF_CTRL(unit)->num_udfs, scache_ptr); 1647 BCM_IF_ERROR_RETURN(rv); 1648 1649 rv = bcmi_xgs4_udf_wb_tcam_info_sync_1_0(unit, 1650 UDF_CTRL(unit)->num_pkt_formats, scache_ptr); 1651 BCM_IF_ERROR_RETURN(rv); 1652 1653 return BCM_E_NONE; 1654 } 1655 1656 /* Syncs UDF control state into scache for version = 1_1 */ 1657 STATIC int 1658 bcmi_xgs4_udf_wb_sync_1_1(int unit, uint8 **scache_ptr) 1659 { 1660 uint32 *u32_scache_p; 1661 1662 u32_scache_p = (uint32 *)(*scache_ptr); 1663 1664 /* Udf resource of used module */ 1665 *u32_scache_p = UDF_CTRL(unit)->udf_used_by_module; 1666 u32_scache_p++; 1667 1668 *scache_ptr = (uint8 *)u32_scache_p; 1669 1670 return BCM_E_NONE; 1671 } 1672 1673 #if defined (BCM_TOMAHAWK_SUPPORT) 1674 /* Syncs UDF control state into scache for version = 1_3 */ 1675 STATIC int 1676 bcmi_xgs4_udf_wb_sync_1_3(int unit, uint8 **scache_ptr) 1677 { 1678 int num_tcam_nodes; 1679 bcmi_xgs4_udf_tcam_info_t *tcam_info; 1680 struct bcmi_xgs4_wb_tcam_info_1_3 *scache_tcam_p; 1681 1682 tcam_info = UDF_CTRL(unit)->tcam_info_head; 1683 scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_3 *)(*scache_ptr); 1684 num_tcam_nodes = UDF_CTRL(unit)->num_pkt_formats; 1685 1686 /* Sync data to scache */ 1687 while (num_tcam_nodes > 0) { 1688 scache_tcam_p->hw_idx = tcam_info->hw_idx; 1689 scache_tcam_p->class_id = tcam_info->class_id; 1690 /* in global mode, this should be always 0 */ 1691 scache_tcam_p->associated_pipe=tcam_info->associated_pipe; 1692 scache_tcam_p++; 1693 num_tcam_nodes--; 1694 tcam_info = tcam_info->next; 1695 } 1696 1697 *scache_ptr = (uint8 *)scache_tcam_p; 1698 1699 return BCM_E_NONE; 1700 } 1701 1702 STATIC int 1703 bcmi_xgs4_udf_wb_sync_1_4(int unit, uint8 **scache_ptr) 1704 { 1705 int idx; 1706 bcmi_xgs4_udf_tcam_info_t *tcam_info; 1707 struct bcmi_xgs4_wb_tcam_info_1_4 *scache_tcam_p; 1708 1709 if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) && 1710 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 1711 tcam_info = UDF_CTRL(unit)->tcam_info_head; 1712 scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_4*)(*scache_ptr); 1713 1714 while (tcam_info) { 1715 for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) { 1716 scache_tcam_p->hw_idx[idx] = tcam_info->hw_idx_per_pipe[idx]; 1717 scache_tcam_p->num_udfs[idx] = tcam_info->num_udfs_per_pipe[idx]; 1718 scache_tcam_p->offset_bmap[idx] = tcam_info->offset_bmap_per_pipe[idx]; 1719 scache_tcam_p->associated_pipes[idx] = tcam_info->associated_pipes[idx]; 1720 } 1721 1722 for (idx = 0; idx < MAX_UDF_ID_LIST; idx++) { 1723 scache_tcam_p->udf_id_list[idx] = tcam_info->udf_id_list[idx]; 1724 } 1725 1726 scache_tcam_p++; 1727 tcam_info = tcam_info->next; 1728 } 1729 1730 *scache_ptr = (uint8*)scache_tcam_p; 1731 } 1732 1733 return BCM_E_NONE; 1734 } 1735 #endif 1736 1737 STATIC int 1738 bcmi_xgs4_udf_wb_sync_1_5(int unit, uint8 **scache_ptr) 1739 { 1740 int idx; 1741 struct bcmi_xgs4_wb_tcam_info_1_5 *scache_tcam_p; 1742 1743 scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_5*)(*scache_ptr); 1744 1745 for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) { 1746 sal_memcpy(&(scache_tcam_p->udf_field_bmp[idx]), 1747 UDF_CTRL(unit)->udf_field_bmp[idx].w, 1748 sizeof(uint32)); 1749 } 1750 scache_tcam_p->max_chunks = UDF_CTRL(unit)->max_chunks; 1751 scache_tcam_p++; 1752 *scache_ptr = (uint8*)scache_tcam_p; 1753 1754 return BCM_E_NONE; 1755 } 1756 1757 1758 /* Returns required scache size for UDF module */ 1759 STATIC int 1760 bcmi_xgs4_udf_wb_scache_size_get(int unit, int *req_scache_size) 1761 { 1762 BCM_IF_ERROR_RETURN( 1763 bcmi_xgs4_udf_wb_scache_size_get_1_0(unit, req_scache_size)); 1764 1765 BCM_IF_ERROR_RETURN( 1766 bcmi_xgs4_udf_wb_scache_size_get_1_1(unit, req_scache_size)); 1767 1768 #if defined (BCM_TOMAHAWK_SUPPORT) 1769 BCM_IF_ERROR_RETURN( 1770 bcmi_xgs4_udf_wb_scache_size_get_1_3(unit, req_scache_size)); 1771 1772 BCM_IF_ERROR_RETURN( 1773 bcmi_xgs4_udf_wb_scache_size_get_1_4(unit, req_scache_size)); 1774 #endif 1775 1776 if (soc_feature(unit, soc_feature_udf_selector_support)) { 1777 BCM_IF_ERROR_RETURN( 1778 bcmi_xgs4_udf_wb_scache_size_get_1_5(unit, req_scache_size)); 1779 } 1780 1781 return BCM_E_NONE; 1782 } 1783 1784 /* Allocates required scache size for the UDF module recovery */ 1785 STATIC int 1786 bcmi_xgs4_udf_wb_alloc(int unit) 1787 { 1788 int rv; 1789 int req_scache_size; 1790 uint8 *scache_ptr; 1791 soc_scache_handle_t scache_handle; 1792 1793 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_UDF, 0); 1794 1795 rv = bcmi_xgs4_udf_wb_scache_size_get(unit, &req_scache_size); 1796 BCM_IF_ERROR_RETURN(rv); 1797 1798 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 1799 req_scache_size, &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 1800 1801 if (BCM_E_NOT_FOUND == rv) { 1802 /* Proceed with Level 1 Warm Boot */ 1803 rv = BCM_E_NONE; 1804 } 1805 1806 BCM_IF_ERROR_RETURN(rv); 1807 1808 return BCM_E_NONE; 1809 } 1810 1811 /* 1812 * Function: 1813 * bcmi_xgs4_udf_wb_sync 1814 * Purpose: 1815 * Syncs UDF warmboot state to scache 1816 * Parameters: 1817 * unit - (IN) Unit number. 1818 * Returns: 1819 * BCM_E_XXX 1820 * Notes: 1821 */ 1822 int 1823 bcmi_xgs4_udf_wb_sync(int unit) 1824 { 1825 uint8 *scache_ptr; 1826 soc_scache_handle_t scache_handle; 1827 1828 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_UDF, 0); 1829 1830 BCM_IF_ERROR_RETURN 1831 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1832 0, &scache_ptr, 1833 BCM_WB_DEFAULT_VERSION, NULL)); 1834 if (UDF_CTRL(unit) != NULL) { 1835 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_0(unit, &scache_ptr)); 1836 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_1(unit, &scache_ptr)); 1837 #if defined (BCM_TOMAHAWK_SUPPORT) 1838 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_3(unit, &scache_ptr)); 1839 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_4(unit, &scache_ptr)); 1840 #endif 1841 } 1842 if (soc_feature(unit, soc_feature_udf_selector_support)) { 1843 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_5(unit, &scache_ptr)); 1844 } 1845 return BCM_E_NONE; 1846 } 1847 1848 1849 1850 /* 1851 * Function: 1852 * bcmi_xgs4_udf_reinit 1853 * Purpose: 1854 * Recovers UDF warmboot state from scache 1855 * Parameters: 1856 * unit - (IN) Unit number. 1857 * Returns: 1858 * BCM_E_XXX 1859 * Notes: 1860 */ 1861 STATIC int 1862 bcmi_xgs4_udf_reinit(int unit) 1863 { 1864 int rv = BCM_E_INTERNAL; 1865 uint8 *scache_ptr; 1866 uint16 recovered_ver = 0; 1867 soc_scache_handle_t scache_handle; 1868 1869 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_UDF, 0); 1870 1871 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1872 0, &scache_ptr, 1873 BCM_WB_DEFAULT_VERSION, &recovered_ver); 1874 1875 if (BCM_E_NOT_FOUND == rv) { 1876 /* Proceed with Level 1 Warm Boot */ 1877 rv = BCM_E_NONE; 1878 } 1879 1880 BCM_IF_ERROR_RETURN(rv); 1881 1882 if (recovered_ver >= BCM_WB_VERSION_1_0) { 1883 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_0(unit, &scache_ptr)); 1884 } 1885 1886 if (recovered_ver >= BCM_WB_VERSION_1_1) { 1887 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_1(unit, &scache_ptr)); 1888 } 1889 1890 #if defined (BCM_TOMAHAWK_SUPPORT) 1891 if (recovered_ver >= BCM_WB_VERSION_1_2) { 1892 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_tcam_info_reinit_1_2_to_1_4(unit)); 1893 } 1894 1895 if (recovered_ver >= BCM_WB_VERSION_1_3) { 1896 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_3(unit, &scache_ptr)); 1897 } 1898 1899 if (recovered_ver >= BCM_WB_VERSION_1_4) { 1900 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_4(unit, &scache_ptr)); 1901 } 1902 #endif 1903 1904 if (soc_feature(unit, soc_feature_udf_selector_support)) { 1905 if (recovered_ver >= BCM_WB_VERSION_1_5) { 1906 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_5(unit, &scache_ptr)); 1907 } 1908 } 1909 1910 if (BCM_SUCCESS(rv) && 1911 (recovered_ver < BCM_WB_DEFAULT_VERSION)) { 1912 /* This will handle the below cases 1913 1. When warboot from release which didn't had UDF module in SCACHE or 1914 2. The current release SCACHE size required is more than preivous version or 1915 3. Level 1 warmboot in this case memory will not be allocated. */ 1916 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_alloc(unit)); 1917 } 1918 1919 return rv; 1920 } 1921 1922 #endif /* BCM_WARM_BOOT_SUPPORT */ 1923 1924 /* 1925 * Function: 1926 * bcmi_xgs4_udf_offset_reserve 1927 * Purpose: 1928 * Reserves requested offset chunks. 1929 * Parameters: 1930 * unit - (IN) Unit number. 1931 * max_offsets - (IN) Number of offsets to reserve. 1932 * offset[] - (IN) Array of offset chunks requested. 1933 * pipe_num - (IN) Pipe Num where offset is reserved 1934 * Returns: 1935 * BCM_E_XXX 1936 * Notes: 1937 * offset[i]: 0x1 means only first half of the chunk is used. 1938 * offset[i]: 0x2 means only second half of the chunk is used. 1939 * offset[i]: 0x3 means both the chunks are used. 1940 */ 1941 STATIC int 1942 bcmi_xgs4_udf_offset_reserve(int unit, int max_offsets, int offset[], int pipe_num) 1943 { 1944 int j; 1945 int first = 1; 1946 int grp_id = 0; 1947 int gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 1948 bcmi_xgs4_udf_offset_entry_t *offset_entry; 1949 bcmi_xgs4_udf_offset_entry_t *offset_entry_array; 1950 SHR_BITDCL *chunk_bmap; 1951 SHR_BITDCL *byte_bmap; 1952 1953 #if defined (BCM_TOMAHAWK_SUPPORT) 1954 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 1955 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 1956 1957 offset_entry_array = UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe_num]; 1958 chunk_bmap = &(UDF_CTRL(unit)->hw_bmap_per_pipe[pipe_num]); 1959 byte_bmap = &(UDF_CTRL(unit)->byte_bmap_per_pipe[pipe_num]); 1960 } else 1961 #endif 1962 { 1963 offset_entry_array = UDF_CTRL(unit)->offset_entry_array; 1964 chunk_bmap = &(UDF_CTRL(unit)->hw_bmap); 1965 byte_bmap = &(UDF_CTRL(unit)->byte_bmap); 1966 } 1967 1968 1969 for (j = 0; j < max_offsets; j++) { 1970 if (offset[j] == 0) { 1971 continue; 1972 } 1973 1974 /* Return BCM_E_RESOURCE if the offset chunk is already in use */ 1975 if (SHR_BITGET(chunk_bmap, j)) { 1976 return BCM_E_RESOURCE; 1977 } 1978 1979 offset_entry = &(offset_entry_array[j]); 1980 1981 #if defined (BCM_TOMAHAWK_SUPPORT) 1982 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 1983 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 1984 offset_entry->associated_pipe = pipe_num; 1985 } 1986 #endif 1987 offset_entry->num_udfs += 1; 1988 1989 if (offset_entry_array[j].num_udfs == 1) { 1990 /* Mark the entries as used */ 1991 SHR_BITSET(chunk_bmap, j); 1992 *byte_bmap |= offset[j] << (j * gran); 1993 } 1994 1995 if (gran == UDF_OFFSET_GRAN2) { 1996 /* Offset flag updated when gran is 2. 1997 * offset[i] can be 1,2,3 only in case of gran2 1998 */ 1999 if ((offset[j] == 0x1) || (offset[j] == 0x2)) { 2000 offset_entry_array[j].flags |= 2001 BCMI_XGS4_UDF_OFFSET_ENTRY_HALF; 2002 } 2003 } 2004 2005 if (first == 1) { 2006 offset_entry_array[j].flags |= 2007 BCMI_XGS4_UDF_OFFSET_ENTRY_GROUP; 2008 2009 offset_entry_array[j].grp_id = j; 2010 2011 first = 0; 2012 grp_id = j; 2013 } else { 2014 offset_entry_array[j].flags |= 2015 BCMI_XGS4_UDF_OFFSET_ENTRY_MEMBER; 2016 offset_entry_array[j].grp_id = grp_id; 2017 } 2018 } 2019 2020 return BCM_E_NONE; 2021 } 2022 2023 /* 2024 * Function: 2025 * _bcmi_xgs4_th3_qset_udf_offsets_alloc 2026 * Purpose: 2027 * Allocates offset chunks based on the INPUT qset. 2028 * Parameters: 2029 * unit - (IN) Unit number. 2030 * req_offsets - (IN) Number of chunks to be allocated. 2031 * offset_array - (OUT) Offset chunks in the order of availability. 2032 * max_chunks - (OUT) Number of chunks allocated 2033 * pipe_num - (IN) Pipe Number 2034 * 2035 * Returns: 2036 * BCM_E_XXX 2037 * Notes: 2038 */ 2039 int 2040 _bcmi_xgs4_th3_qset_udf_offsets_alloc(int unit, int req_offsets, 2041 int offset_array[], int *max_chunks, 2042 int pipe_num) 2043 { 2044 int chunk = 0; 2045 uint32 hw_bmap[1]; 2046 int num_chunks = 0; 2047 uint8 use_udf1 = 0, use_udf2 = 0, use_udf12 = 0; 2048 int pipe = 0; 2049 int udf1_used_chunks = 0, udf2_used_chunks = 0; 2050 2051 #if defined (BCM_TOMAHAWK_SUPPORT) 2052 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 2053 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 2054 hw_bmap[0] = UDF_CTRL(unit)->hw_bmap_per_pipe[pipe_num]; 2055 pipe = pipe_num; 2056 } else 2057 #endif 2058 { 2059 hw_bmap[0] = UDF_CTRL(unit)->hw_bmap; 2060 pipe = 0; 2061 } 2062 2063 /* Count the number of used chunks in UDF 1 and 2 */ 2064 for (chunk = 0; chunk < (UDF_CTRL(unit)->max_chunks); 2065 chunk++) { 2066 if (SHR_BITGET(&(hw_bmap[0]), chunk)) { 2067 if (chunk < (UDF_CTRL(unit)->max_chunks / 2)) { 2068 udf1_used_chunks++; 2069 } else { 2070 udf2_used_chunks++; 2071 } 2072 } 2073 } 2074 2075 /* verify if resources are available in order of udf1 alone, 2076 udf2 alone, followed by udf1 + udf2 together */ 2077 2078 if (((UDF_CTRL(unit)->max_chunks / 2 ) 2079 - udf1_used_chunks) >= req_offsets ) { 2080 use_udf1 = 1; 2081 } else if (((UDF_CTRL(unit)->max_chunks / 2 ) 2082 - udf2_used_chunks) >= req_offsets ) { 2083 use_udf2 = 1; 2084 } else if ((UDF_CTRL(unit)->max_chunks 2085 - (udf1_used_chunks 2086 + udf2_used_chunks)) >= req_offsets) { 2087 use_udf12 = 1; 2088 } else { 2089 /* No resources available in all cases */ 2090 return (BCM_E_RESOURCE); 2091 } 2092 2093 2094 if (use_udf1) { /* Use UDF1 */ 2095 chunk = 0; 2096 while ((chunk < (UDF_CTRL(unit)->max_chunks / 2)) && (num_chunks < req_offsets)) { 2097 if (((_BCMI_UDF_BMP_TEST(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk)) == 0) 2098 && (SHR_BITGET(&(hw_bmap[0]), chunk) == 0)) { 2099 offset_array[num_chunks] = chunk; 2100 udf1_used_chunks++; 2101 num_chunks++; 2102 _BCMI_UDF_BMP_ADD(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk); 2103 } 2104 chunk++; 2105 } 2106 } else if (use_udf2) { /* Use UDF2 */ 2107 chunk = (UDF_CTRL(unit)->max_chunks / 2); 2108 2109 while ((chunk < UDF_CTRL(unit)->max_chunks) && (num_chunks < req_offsets)) { 2110 if (((_BCMI_UDF_BMP_TEST(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk)) == 0) 2111 && (SHR_BITGET(&(hw_bmap[0]), chunk) == 0)) { 2112 offset_array[num_chunks] = chunk; 2113 udf2_used_chunks++; 2114 num_chunks++; 2115 _BCMI_UDF_BMP_ADD(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk); 2116 } 2117 chunk++; 2118 } 2119 } else if (use_udf12) { /* Use UDF1 and UDF2 */ 2120 chunk = 0; 2121 while ((chunk < UDF_CTRL(unit)->max_chunks) && (num_chunks < req_offsets)) { 2122 if (((_BCMI_UDF_BMP_TEST(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk)) == 0) 2123 && (SHR_BITGET(&(hw_bmap[0]), chunk) == 0)) { 2124 offset_array[num_chunks] = chunk; 2125 num_chunks++; 2126 if (chunk < (UDF_CTRL(unit)->max_chunks / 2)) { 2127 udf1_used_chunks++; 2128 } else { 2129 udf2_used_chunks++; 2130 } 2131 _BCMI_UDF_BMP_ADD(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk); 2132 } 2133 chunk++; 2134 } 2135 } 2136 2137 if (num_chunks < req_offsets) { 2138 /* Mismatch in internal calculations */ 2139 return (BCM_E_INTERNAL); 2140 } 2141 2142 2143 *max_chunks = num_chunks; 2144 2145 return BCM_E_NONE; 2146 } 2147 2148 int 2149 _bcmi_xgs4_th3_qset_udf_offsets_free(int unit, int chunk, int pipe) { 2150 2151 _BCMI_UDF_BMP_REMOVE(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk); 2152 return BCM_E_NONE; 2153 2154 } 2155 2156 2157 /* 2158 * Function: 2159 * bcmi_xgs4_udf_offset_unreserve 2160 * Purpose: 2161 * UnReserves offset chunks. 2162 * Parameters: 2163 * unit - (IN) Unit number. 2164 * max_offsets - (IN) Number of offsets to unreserve. 2165 * offset[] - (IN) Array of offset chunks to be unreserved. 2166 * pipe_num - (IN) Pipe Num where offset is unreserved 2167 * Returns: 2168 * BCM_E_XXX 2169 * Notes: 2170 */ 2171 STATIC int 2172 bcmi_xgs4_udf_offset_unreserve(int unit, int max_offsets, int offset[], int pipe_num) 2173 { 2174 int j; 2175 int gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 2176 bcmi_xgs4_udf_offset_entry_t *offset_entry; 2177 bcmi_xgs4_udf_offset_entry_t *offset_entry_array; 2178 SHR_BITDCL *chunk_bmap; 2179 SHR_BITDCL *byte_bmap; 2180 2181 #if defined (BCM_TOMAHAWK_SUPPORT) 2182 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 2183 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 2184 2185 offset_entry_array = UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe_num]; 2186 chunk_bmap = &(UDF_CTRL(unit)->hw_bmap_per_pipe[pipe_num]); 2187 byte_bmap = &(UDF_CTRL(unit)->byte_bmap_per_pipe[pipe_num]); 2188 } else 2189 #endif 2190 { 2191 offset_entry_array = UDF_CTRL(unit)->offset_entry_array; 2192 chunk_bmap = &(UDF_CTRL(unit)->hw_bmap); 2193 byte_bmap = &(UDF_CTRL(unit)->byte_bmap); 2194 } 2195 2196 for (j = 0; j < max_offsets; j++) { 2197 if (offset[j] == 0) { 2198 continue; 2199 } 2200 2201 offset_entry = &(offset_entry_array[j]); 2202 2203 /* Decr ref_cnt on the offset entry */ 2204 offset_entry->num_udfs -= 1; 2205 2206 if (offset_entry->num_udfs == 0) { 2207 /* Defensive Check: num_pkt_formats must be 0 */ 2208 if (offset_entry->num_pkt_formats != 0) { 2209 return BCM_E_INTERNAL; 2210 } 2211 2212 /* Mark the entries as free */ 2213 SHR_BITCLR(chunk_bmap, j); 2214 *byte_bmap &= ~(offset[j] << (j * gran)); 2215 2216 if (soc_feature(unit, soc_feature_udf_selector_support)) { 2217 /* Free the chunk in field module */ 2218 BCM_IF_ERROR_RETURN(_bcmi_xgs4_th3_qset_udf_offsets_free(unit, j, pipe_num)); 2219 } 2220 2221 /* Clear the UDF Offset entry */ 2222 offset_entry->flags = 0x0; 2223 offset_entry->grp_id = 0x0; 2224 } 2225 } 2226 2227 return BCM_E_NONE; 2228 } 2229 2230 /* 2231 * Function: 2232 * bcmi_xgs4_udf_offset_hw_alloc 2233 * Purpose: 2234 * Allocates offsets for the UDF 2235 * Parameters: 2236 * unit - (IN) Unit number. 2237 * hints - (IN) Hints for allocation of offset chunks. 2238 * offset_info - (INOUT) UDF Offset info struct 2239 * Returns: 2240 * BCM_E_XXX 2241 * Notes: 2242 */ 2243 STATIC int 2244 bcmi_xgs4_udf_offset_hw_alloc(int unit, bcm_udf_alloc_hints_t *hints, 2245 bcmi_xgs4_udf_offset_info_t *offset_info) 2246 { 2247 int rv; 2248 int i, j; 2249 int gran; 2250 int grp_id = -1; 2251 int max_chunks; 2252 uint32 hw_bmap[1]; 2253 uint32 alloc_bmap = 0; 2254 uint32 byte_bmap = 0; 2255 int *offset_order; 2256 int offset_array[MAX_UDF_OFFSET_CHUNKS] = {0}; 2257 int offset_order_d[MAX_UDF_OFFSET_CHUNKS] = {0}; 2258 int alloc_cnt = 0, max_offsets = 0, req_offsets = 0; 2259 uint8 byte_offset = 0; 2260 int widthcovergbl = 0, widthcoverint = 0; 2261 2262 /* offset allocation order */ 2263 int bcmi_xgs4_udf_offsets_gran2_default[] = {2, 3, 6, 7, 0, 1, 4, 5, 2264 8, 9, 10, 11, 12, 13, 14, 15}; 2265 int bcmi_xgs4_udf_offsets_gran4_default[] = {1, 3, 0, 2, 4, 5, 6, 7}; 2266 int bcmi_xgs4_udf_offsets_flexhash[] = {12, 13, 14, 15}; 2267 int bcmi_xgs4_udf_offsets_udfhash[] = {6, 7}; 2268 int bcmi_xgs4_udf_offsets_policer[] = {0, 1}; 2269 int bcmi_xgs4_udf_offsets_range_checker[] = {5}; /*UDF1 chunk 2: bits (47 - 32 of UDF1)*/ 2270 int bcmi_xgs4_udf_offsets_flex_counter[] = {0, 1}; 2271 2272 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 2273 max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 2274 2275 /* 2276 * The 'start' and 'width' need not always align to the offset granularity. 2277 * Every offset can extract 2 bytes or 4 bytes. 2278 * Also on devices with gran 4 if layer is L2 Header then offset 2279 * need to be adjusted with negative offset of 2. 2280 * This negative offset of 2 for L2 Header start is done because first 2281 * chunk will pick up B0,B1,B126,B127 bytes of frame. 2282 * If the user request a UDF that starts/ends on an odd-byte boundary, 2283 * SDK should allocate extra chunk(s) to facilitate for the requested 2284 * byte extraction and account for this extra byte in the field APIs 2285 * (by masking "don'tcare" for those extra bytes. 2286 */ 2287 if (gran == UDF_OFFSET_GRAN2) { 2288 byte_offset = offset_info->start % gran; 2289 } else { 2290 if (offset_info->layer == bcmUdfLayerL2Header) { 2291 byte_offset = (offset_info->start + 2) % gran; 2292 } else { 2293 byte_offset = offset_info->start % gran; 2294 } 2295 } 2296 2297 offset_info->byte_offset = byte_offset; 2298 req_offsets = (offset_info->width + byte_offset + gran -1) / gran; 2299 2300 /* 2301 * FLEXHASH and IFP/VFP flags can be set at the same time 2302 * Since FLEXHASH has limited chunks, it is preferred during allocation 2303 */ 2304 2305 if ((hints != NULL) && (hints->flags & BCM_UDF_CREATE_O_FLEXHASH)) { 2306 max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_flexhash); 2307 offset_order = &bcmi_xgs4_udf_offsets_flexhash[0]; 2308 2309 } else if ((hints != NULL) && (hints->flags & BCM_UDF_CREATE_O_UDFHASH)) { 2310 max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_udfhash); 2311 offset_order = &bcmi_xgs4_udf_offsets_udfhash[0]; 2312 2313 } else if ((hints != NULL) && 2314 (hints->flags & BCM_UDF_CREATE_O_RANGE_CHECK)) { 2315 max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_range_checker); 2316 offset_order = &bcmi_xgs4_udf_offsets_range_checker[0]; 2317 2318 } else if ((hints != NULL) && 2319 ((hints->flags & BCM_UDF_CREATE_O_FIELD_INGRESS) || 2320 (hints->flags & BCM_UDF_CREATE_O_FIELD_LOOKUP))) { 2321 2322 _field_stage_id_t stage; 2323 2324 if (hints->flags & BCM_UDF_CREATE_O_FIELD_INGRESS) { 2325 stage = _BCM_FIELD_STAGE_INGRESS; 2326 } else { 2327 stage = _BCM_FIELD_STAGE_LOOKUP; 2328 } 2329 2330 /* allocate based on qset */ 2331 if (soc_feature(unit, soc_feature_udf_selector_support)) { 2332 rv = _bcmi_xgs4_th3_qset_udf_offsets_alloc(unit, 2333 req_offsets, &offset_order_d[0], &max_offsets, 2334 offset_info->associated_pipe); 2335 BCM_IF_ERROR_RETURN(rv); 2336 } else { 2337 rv = _bcm_esw_field_qset_udf_offsets_alloc(unit, stage, hints->qset, 2338 req_offsets, &offset_order_d[0], &max_offsets, 2339 offset_info->associated_pipe); 2340 BCM_IF_ERROR_RETURN(rv); 2341 } 2342 2343 2344 offset_order = &offset_order_d[0]; 2345 } else if ((hints != NULL) && 2346 (hints->flags & BCM_UDF_CREATE_O_POLICER_GROUP)) { 2347 max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_policer); 2348 offset_order = &bcmi_xgs4_udf_offsets_policer[0]; 2349 2350 } else if ((hints != NULL) && 2351 (hints->flags & BCM_UDF_CREATE_O_FLEX_COUNTER)) { 2352 max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_flex_counter); 2353 offset_order = &bcmi_xgs4_udf_offsets_flex_counter[0]; 2354 2355 } else { 2356 if (gran == UDF_OFFSET_GRAN2) { 2357 max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_gran2_default); 2358 offset_order = &bcmi_xgs4_udf_offsets_gran2_default[0]; 2359 } else { 2360 max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_gran4_default); 2361 offset_order = &bcmi_xgs4_udf_offsets_gran4_default[0]; 2362 } 2363 } 2364 2365 /* max_chunks cannot be greater than 8 for chipsets with gran 4 2366 * and greater than 16 for chipsets with gran 2 2367 */ 2368 #if defined (BCM_TOMAHAWK_SUPPORT) 2369 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 2370 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 2371 hw_bmap[0] = UDF_CTRL(unit)->hw_bmap_per_pipe[offset_info->associated_pipe]; 2372 } else 2373 #endif 2374 { 2375 hw_bmap[0] = UDF_CTRL(unit)->hw_bmap; 2376 } 2377 2378 /* All chunks are reserved */ 2379 if ((hw_bmap[0] & 0xffff) == 0xffff) { 2380 return BCM_E_RESOURCE; 2381 } 2382 2383 for (j = 0; j < max_offsets; j++) { 2384 if ((SHR_BITGET(&(hw_bmap[0]), offset_order[j]))) { 2385 offset_array[offset_order[j]] = 0; 2386 continue; 2387 } 2388 2389 /* Mark the first offset entry as the grp_id */ 2390 if (grp_id == -1) { 2391 grp_id = offset_order[j]; 2392 } else if (grp_id > offset_order[j]) { 2393 grp_id = offset_order[j]; 2394 } 2395 2396 /* offset_order will have order of chunks to be allocated. 2397 * offset_array should be filled with 0x1, 0x2 or 0x3 if 2398 * first half, or second half or full chunk is alloc'ed respy. 2399 */ 2400 alloc_bmap |= (1 << offset_order[j]); 2401 if (alloc_cnt == 0) { 2402 /* First Chunk to be allocated */ 2403 for(i = 0;i< (gran - byte_offset); i++) { 2404 if (widthcovergbl < offset_info->width) { 2405 byte_bmap |= (0x1 << (((offset_order[j]+1) * gran) - byte_offset -i -1)); 2406 offset_array[offset_order[j]] |= (0x1 << (gran - byte_offset -i -1)); 2407 widthcovergbl++; 2408 } 2409 } 2410 } else { 2411 /* Rest all chunk to be allocated */ 2412 widthcoverint = 0; 2413 for(i = 0;(i <(offset_info->width - widthcovergbl) && (i < gran)); i++){ 2414 byte_bmap |= (0x1 << (((offset_order[j]+1) * gran) -i -1)); 2415 offset_array[offset_order[j]] |= (0x1 << (gran -i -1)); 2416 widthcoverint++; 2417 } 2418 widthcovergbl += widthcoverint; 2419 } 2420 2421 if (++alloc_cnt == req_offsets) { 2422 break; 2423 } 2424 } 2425 2426 if (alloc_cnt < req_offsets) { 2427 return BCM_E_RESOURCE; 2428 } 2429 2430 rv = bcmi_xgs4_udf_offset_reserve(unit, max_chunks, offset_array, 2431 offset_info->associated_pipe); 2432 BCM_IF_ERROR_RETURN(rv); 2433 2434 /* grp_id is the first chunk number */ 2435 offset_info->grp_id = grp_id; 2436 2437 offset_info->hw_bmap |= alloc_bmap; 2438 offset_info->byte_bmap |= byte_bmap; 2439 2440 return BCM_E_NONE; 2441 } 2442 2443 2444 /* 2445 * Function: 2446 * bcmi_xgs4_udf_layer_to_offset_base 2447 * Purpose: 2448 * Fetches base and offsets values to configure in UDF_OFFSET table. 2449 * Parameters: 2450 * unit - (IN) Unit number. 2451 * offset_info - (IN) UDF Offset info struct 2452 * tcam_info - (IN) UDF tcam info struct 2453 * base - (OUT) base_offset to be configured in BASE_OFFSETx 2454 * baseoffset - (OUT) base offset to be configured in OFFSETx field 2455 * Returns: 2456 * BCM_E_XXX 2457 * Notes: 2458 * Users can implement bcmUdfLayerUserPayload according to the requirement. 2459 */ 2460 STATIC int 2461 bcmi_xgs4_udf_layer_to_offset_base(int unit, 2462 bcmi_xgs4_udf_offset_info_t *offset_info, 2463 bcmi_xgs4_udf_tcam_info_t *tcam_info, 2464 int *base, int *baseoffset) 2465 { 2466 int gran; 2467 2468 /* get udf gran from udf control */ 2469 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 2470 2471 /* base offset */ 2472 switch (offset_info->layer) { 2473 case bcmUdfLayerL2Header: 2474 *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_L2; 2475 break; 2476 case bcmUdfLayerL3OuterHeader: 2477 case bcmUdfLayerTunnelHeader: 2478 *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_OUTER_L3; 2479 break; 2480 case bcmUdfLayerL3InnerHeader: 2481 case bcmUdfLayerL4OuterHeader: 2482 *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_INNER_L3; 2483 break; 2484 case bcmUdfLayerL4InnerHeader: 2485 case bcmUdfLayerTunnelPayload: 2486 *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_L4; 2487 break; 2488 case bcmUdfLayerHigigHeader: 2489 case bcmUdfLayerHigig2Header: 2490 *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_MH; 2491 break; 2492 default: 2493 /* Unknown layer type: Return Error */ 2494 return BCM_E_PARAM; 2495 } 2496 2497 /* Base offset value */ 2498 if (gran == UDF_OFFSET_GRAN2) { 2499 *baseoffset = ((offset_info->start % UDF_PACKET_PARSE_LENGTH) 2500 / gran); 2501 } else { 2502 if ((offset_info->layer == bcmUdfLayerL2Header) || 2503 (offset_info->layer == bcmUdfLayerHigigHeader) || 2504 (offset_info->layer == bcmUdfLayerHigig2Header)) { 2505 *baseoffset = (((offset_info->start + 2) % UDF_PACKET_PARSE_LENGTH) 2506 / gran); 2507 } else { 2508 *baseoffset = ((offset_info->start % UDF_PACKET_PARSE_LENGTH) 2509 / gran); 2510 } 2511 } 2512 2513 return BCM_E_NONE; 2514 } 2515 2516 /* 2517 * Function: 2518 * bcmi_xgs4_udf_get 2519 * Purpose: 2520 * To fetch the udf info given the UDF ID. 2521 * Parameters: 2522 * unit - (IN) Unit number. 2523 * udf_id - (IN) UDF Id. 2524 * udf_info - (OUT) UDF info struct 2525 * Returns: 2526 * BCM_E_XXX 2527 * Notes: 2528 */ 2529 int 2530 bcmi_xgs4_udf_get(int unit, bcm_udf_id_t udf_id, bcm_udf_t *udf_info) 2531 { 2532 int rv; 2533 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 2534 2535 /* UDF Module Init check */ 2536 UDF_INIT_CHECK(unit); 2537 2538 BCM_IF_NULL_RETURN_PARAM(udf_info); 2539 2540 /* UDF Module Lock */ 2541 UDF_LOCK(unit); 2542 2543 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info); 2544 if (BCM_FAILURE(rv)) { 2545 UDF_UNLOCK(unit); 2546 return rv; 2547 } 2548 2549 /* Copy tmp to offset_info */ 2550 udf_info->start = BYTES2BITS(offset_info->start); 2551 udf_info->width = BYTES2BITS(offset_info->width); 2552 udf_info->layer = offset_info->layer; 2553 #if defined (BCM_TOMAHAWK_SUPPORT) 2554 if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) { 2555 SOC_PBMP_ASSIGN(udf_info->ports, offset_info->associated_ports); 2556 } 2557 #endif 2558 /* Not used for XGS4 */ 2559 udf_info->flags = 0; 2560 2561 /* Release UDF mutex */ 2562 UDF_UNLOCK(unit); 2563 2564 return BCM_E_NONE; 2565 } 2566 2567 2568 /* 2569 * Function: 2570 * bcmi_xgs4_udf_get_all 2571 * Purpose: 2572 * To fetch all the udfs in the system. 2573 * Parameters: 2574 * unit - (IN) Unit number. 2575 * max - (IN) Number of udf ids to fetch. 2576 * udf_id_list - (OUT) List of UDF Ids fetched. 2577 * actual - (OUT) Actual udfs fetched. 2578 * Returns: 2579 * BCM_E_XXX 2580 * Notes: 2581 */ 2582 int 2583 bcmi_xgs4_udf_get_all(int unit, int max, bcm_udf_id_t *udf_list, int *actual) 2584 { 2585 bcmi_xgs4_udf_offset_info_t *tmp; 2586 2587 /* UDF Module Init check */ 2588 UDF_INIT_CHECK(unit); 2589 2590 BCM_IF_NULL_RETURN_PARAM(actual); 2591 2592 /* UDF Module Lock */ 2593 UDF_LOCK(unit); 2594 2595 *actual = 0; 2596 tmp = UDF_CTRL(unit)->offset_info_head; 2597 2598 while (tmp != NULL) { 2599 if ((udf_list != NULL) && (*actual < max)) { 2600 udf_list[(*actual)] = tmp->udf_id; 2601 } 2602 2603 (*actual) += 1; 2604 tmp = tmp->next; 2605 } 2606 2607 /* Release UDF mutex */ 2608 UDF_UNLOCK(unit); 2609 2610 return BCM_E_NONE; 2611 } 2612 2613 /* 2614 * Function: 2615 * bcmi_xgs4_udf_get_all 2616 * Purpose: 2617 * To destroy udf object. 2618 * Parameters: 2619 * unit - (IN) Unit number. 2620 * udf_id - (IN) UDF ID to be destroyed. 2621 * Returns: 2622 * BCM_E_XXX 2623 * Notes: 2624 */ 2625 int 2626 bcmi_xgs4_udf_destroy(int unit, bcm_udf_id_t udf_id) 2627 { 2628 int rv; 2629 int i; 2630 int max, gran; 2631 uint32 offset[MAX_UDF_OFFSET_CHUNKS] = {0}; 2632 bcmi_xgs4_udf_offset_info_t *cur = NULL; 2633 2634 /* UDF Module Init check */ 2635 UDF_INIT_CHECK(unit); 2636 2637 /* UDF Module Lock */ 2638 UDF_LOCK(unit); 2639 2640 if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_FIELD_MODULE) { 2641 LOG_CLI((BSL_META("Udf resource is used by FIELD module. \n"))); 2642 UDF_UNLOCK(unit); 2643 return BCM_E_RESOURCE; 2644 } 2645 2646 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 2647 max = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);; 2648 2649 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &cur); 2650 if (BCM_FAILURE(rv)) { 2651 UDF_UNLOCK(unit); 2652 return rv; 2653 } 2654 2655 /* Matching node not found */ 2656 if (cur == NULL) { 2657 UDF_UNLOCK(unit); 2658 return BCM_E_NOT_FOUND; 2659 } 2660 2661 if (cur->num_pkt_formats >= 1) { 2662 UDF_UNLOCK(unit); 2663 return BCM_E_BUSY; 2664 } 2665 2666 for (i = 0; i < max; i++) { 2667 SHR_BITCOPY_RANGE(&offset[i], 0, &(cur->byte_bmap), i*gran, gran); 2668 } 2669 2670 /* unreserve the offset chunks */ 2671 rv = bcmi_xgs4_udf_offset_unreserve(unit, max, (int *)offset, 2672 cur->associated_pipe); 2673 if (BCM_FAILURE(rv)) { 2674 UDF_UNLOCK(unit); 2675 return rv; 2676 } 2677 2678 /* Free the cur node */ 2679 UDF_UNLINK_OFFSET_NODE(cur); 2680 sal_free(cur); 2681 2682 UDF_CTRL(unit)->num_udfs -= 1; 2683 2684 if (NULL == UDF_CTRL(unit)->offset_info_head) { 2685 UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_NONE; 2686 } 2687 2688 /* Release UDF mutex */ 2689 UDF_UNLOCK(unit); 2690 2691 return BCM_E_NONE; 2692 } 2693 2694 2695 /* 2696 * Function: 2697 * bcmi_xgs4_udf_offset_info_alloc 2698 * Purpose: 2699 * To allocate memory for UDF offset info struct 2700 * Parameters: 2701 * unit - (IN) Unit number. 2702 * offset_info - (OUT) Pointer to hold the allocated memory. 2703 * Returns: 2704 * BCM_E_XXX 2705 * Notes: 2706 */ 2707 STATIC int 2708 bcmi_xgs4_udf_offset_info_alloc(int unit, 2709 bcmi_xgs4_udf_offset_info_t **offset_info) 2710 { 2711 int mem_sz; 2712 2713 mem_sz = sizeof(bcmi_xgs4_udf_offset_info_t); 2714 2715 /* Allocate memory for bcmi_xgs4_udf_offset_info_t structure. */ 2716 UDF_MALLOC((*offset_info), bcmi_xgs4_udf_offset_info_t, 2717 mem_sz, "udf offset info"); 2718 2719 if (NULL == *offset_info) { 2720 return (BCM_E_MEMORY); 2721 } 2722 2723 2724 return BCM_E_NONE; 2725 } 2726 2727 2728 /* 2729 * Function: 2730 * bcmi_xgs4_udf_offset_info_add 2731 * Purpose: 2732 * To convert the UDF info to offset info and add to the linked list. 2733 * Parameters: 2734 * unit - (IN) Unit number. 2735 * udf_info - (IN) UDF info to be added to linked list. 2736 * offset_info - (INOUT) Pointer to hold the allocated memory. 2737 * Returns: 2738 * BCM_E_XXX 2739 * Notes: 2740 */ 2741 STATIC int 2742 bcmi_xgs4_udf_offset_info_add(int unit, bcm_udf_t *udf_info, 2743 bcmi_xgs4_udf_offset_info_t **offset_info) 2744 { 2745 int rv; 2746 #if defined (BCM_TOMAHAWK_SUPPORT) 2747 int port; 2748 soc_info_t *si; 2749 si = &SOC_INFO(unit); 2750 #endif 2751 2752 /* Allocate memory for bcmi_xgs4_udf_offset_info_t structure. */ 2753 rv = bcmi_xgs4_udf_offset_info_alloc(unit, offset_info); 2754 BCM_IF_ERROR_RETURN(rv); 2755 2756 /* Save user inputs into the offset_info struct */ 2757 (*offset_info)->layer = udf_info->layer; 2758 (*offset_info)->start = BITS2BYTES(udf_info->start); 2759 (*offset_info)->width = BITS2BYTES(udf_info->width); 2760 2761 #if defined (BCM_TOMAHAWK_SUPPORT) 2762 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 2763 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 2764 2765 /* save pbmp ports in order to return in get function */ 2766 SOC_PBMP_ASSIGN((*offset_info)->associated_ports, udf_info->ports); 2767 2768 /* get the pipe where the entry will be configured */ 2769 SOC_PBMP_ITER(udf_info->ports, port) { 2770 (*offset_info)->associated_pipe = si->port_pipe[port]; 2771 break; 2772 } 2773 } 2774 #endif 2775 2776 /* Add offset_info item to the linked list */ 2777 rv = bcmi_xgs4_udf_offset_node_add(unit, *offset_info); 2778 if (BCM_FAILURE(rv)) { 2779 sal_free(*offset_info); 2780 *offset_info = NULL; 2781 } 2782 2783 return rv; 2784 } 2785 2786 /* Linked list node add: for offset nodes */ 2787 STATIC int 2788 bcmi_xgs4_udf_offset_node_add(int unit, bcmi_xgs4_udf_offset_info_t *new) 2789 { 2790 bcmi_xgs4_udf_offset_info_t *tmp; 2791 2792 if (new == NULL) { 2793 return BCM_E_INTERNAL; 2794 } 2795 2796 tmp = (UDF_CTRL(unit)->offset_info_head); 2797 2798 if (NULL == tmp) { 2799 /* Adding first node */ 2800 (UDF_CTRL(unit)->offset_info_head) = new; 2801 new->prev = NULL; 2802 2803 } else { 2804 2805 /* traverse to the end of the list */ 2806 while (tmp->next != NULL) { 2807 tmp = tmp->next; 2808 } 2809 2810 /* insert new node to the end of the list */ 2811 new->prev = tmp; 2812 tmp->next = new; 2813 2814 } 2815 2816 new->next = NULL; 2817 2818 return BCM_E_NONE; 2819 } 2820 2821 /* Linked list node delete: for offset nodes */ 2822 STATIC int 2823 bcmi_xgs4_udf_offset_node_delete(int unit, bcm_udf_id_t udf_id, 2824 bcmi_xgs4_udf_offset_info_t **del) 2825 { 2826 int rv; 2827 bcmi_xgs4_udf_offset_info_t *cur = NULL; 2828 2829 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &cur); 2830 BCM_IF_ERROR_RETURN(rv); 2831 2832 /* Matching node not found */ 2833 if (cur == NULL) { 2834 return BCM_E_NOT_FOUND; 2835 } 2836 2837 /* unlink cur from the list */ 2838 if (cur->prev) { 2839 (cur->prev)->next = cur->next; 2840 } else { 2841 /* cur node is the head */ 2842 UDF_CTRL(unit)->offset_info_head = cur->next; 2843 } 2844 2845 if (cur->next) { 2846 (cur->next)->prev = cur->prev; 2847 } 2848 2849 /* Callee function to free the node */ 2850 *del = cur; 2851 2852 return BCM_E_NONE; 2853 } 2854 2855 /* 2856 * Function: 2857 * bcmi_xgs4_udf_tcam_info_alloc 2858 * Purpose: 2859 * To allocate memory for UDF tcam info struct 2860 * Parameters: 2861 * unit - (IN) Unit number. 2862 * tcam_info - (OUT) Pointer to hold the allocated memory. 2863 * Returns: 2864 * BCM_E_XXX 2865 * Notes: 2866 */ 2867 STATIC int 2868 bcmi_xgs4_udf_tcam_info_alloc(int unit, bcmi_xgs4_udf_tcam_info_t **tcam_info) 2869 { 2870 int mem_sz; 2871 2872 mem_sz = sizeof(bcmi_xgs4_udf_tcam_info_t); 2873 2874 /* Allocate memory for bcmi_xgs4_udf_offset_info_t structure. */ 2875 UDF_MALLOC((*tcam_info), bcmi_xgs4_udf_tcam_info_t, 2876 mem_sz, "udf tcam info"); 2877 2878 if (NULL == *tcam_info) { 2879 return (BCM_E_MEMORY); 2880 } 2881 2882 /* Mark entry invalid */ 2883 (*tcam_info)->hw_idx = MAX_UDF_TCAM_ENTRIES; 2884 2885 #if defined (BCM_TOMAHAWK_SUPPORT) 2886 if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) { 2887 int i; 2888 /* Mark pipe num invalid */ 2889 (*tcam_info)->associated_pipe = BCMI_XGS4_UDF_INVALID_PIPE_NUM; 2890 2891 for (i = 0; i < SOC_MAX_NUM_PIPES; i++) { 2892 (*tcam_info)->hw_idx_per_pipe[i] = MAX_UDF_TCAM_ENTRIES; 2893 (*tcam_info)->associated_pipes[i] = BCMI_XGS4_UDF_INVALID_PIPE_NUM; 2894 } 2895 } 2896 #endif 2897 return BCM_E_NONE; 2898 } 2899 2900 2901 /* 2902 * Function: 2903 * bcmi_xgs4_udf_tcam_info_add 2904 * Purpose: 2905 * To convert the packet format info to tcam info and add to the list. 2906 * Parameters: 2907 * unit - (IN) Unit number. 2908 * pkt_format - (IN) UDF Packet format to be added to list. 2909 * tcam_info - (INOUT) Pointer to hold the allocated memory. 2910 * Returns: 2911 * BCM_E_XXX 2912 * Notes: 2913 */ 2914 STATIC int 2915 bcmi_xgs4_udf_tcam_info_add(int unit, 2916 bcm_udf_pkt_format_info_t *pkt_format, 2917 bcmi_xgs4_udf_tcam_info_t **tcam_info) 2918 { 2919 int rv; 2920 fp_udf_tcam_entry_t *tcam_buf; 2921 2922 /* Allocate memory for bcmi_xgs4_udf_tcam_info_t structure. */ 2923 rv = bcmi_xgs4_udf_tcam_info_alloc(unit, tcam_info); 2924 BCM_IF_ERROR_RETURN(rv); 2925 2926 tcam_buf = (fp_udf_tcam_entry_t *)&((*tcam_info)->hw_buf); 2927 sal_memset(tcam_buf, 0, sizeof(fp_udf_tcam_entry_t)); 2928 2929 /* Initialize packet format entry */ 2930 rv = bcmi_xgs4_udf_pkt_format_tcam_key_init(unit, pkt_format, 2931 (uint32 *)tcam_buf); 2932 if (BCM_FAILURE(rv)) { 2933 sal_free(*tcam_info); 2934 (*tcam_info) = NULL; 2935 return rv; 2936 } 2937 2938 (*tcam_info)->priority = pkt_format->prio; 2939 #if defined (BCM_TOMAHAWK_SUPPORT) 2940 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) { 2941 (*tcam_info)->class_id = pkt_format->class_id; 2942 } 2943 #endif 2944 /* Add offset_info item to the linked list */ 2945 rv = bcmi_xgs4_udf_tcam_node_add(unit, *tcam_info); 2946 if (BCM_FAILURE(rv)) { 2947 sal_free(*tcam_info); 2948 (*tcam_info) = NULL; 2949 } 2950 2951 return rv; 2952 } 2953 2954 /* Linked list node add: for tcam nodes */ 2955 STATIC int 2956 bcmi_xgs4_udf_tcam_node_add(int unit, bcmi_xgs4_udf_tcam_info_t *new) 2957 { 2958 bcmi_xgs4_udf_tcam_info_t *tmp; 2959 2960 if (new == NULL) { 2961 return BCM_E_INTERNAL; 2962 } 2963 2964 tmp = (UDF_CTRL(unit)->tcam_info_head); 2965 2966 if (NULL == tmp) { 2967 /* Adding first node */ 2968 (UDF_CTRL(unit)->tcam_info_head) = new; 2969 new->prev = NULL; 2970 2971 } else { 2972 2973 /* traverse to the end of the list */ 2974 while (tmp->next != NULL) { 2975 tmp = tmp->next; 2976 } 2977 2978 /* insert new node to the end of the list */ 2979 new->prev = tmp; 2980 tmp->next = new; 2981 2982 } 2983 new->next = NULL; 2984 2985 return BCM_E_NONE; 2986 } 2987 2988 /* Linked list node delete: for tcam nodes */ 2989 STATIC int 2990 bcmi_xgs4_udf_tcam_node_delete(int unit, bcm_udf_pkt_format_id_t pkt_format_id, 2991 bcmi_xgs4_udf_tcam_info_t **del) 2992 { 2993 int rv; 2994 bcmi_xgs4_udf_tcam_info_t *cur = NULL; 2995 2996 rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &cur); 2997 BCM_IF_ERROR_RETURN(rv); 2998 2999 *del = NULL; 3000 3001 /* Matching node not found */ 3002 if (cur == NULL) { 3003 return BCM_E_NOT_FOUND; 3004 } 3005 3006 /* unlink cur from the list */ 3007 if (cur->prev) { 3008 (cur->prev)->next = cur->next; 3009 } else { 3010 /* cur node is the head node */ 3011 UDF_CTRL(unit)->tcam_info_head = cur->next; 3012 } 3013 if (cur->next) { 3014 (cur->next)->prev = cur->prev; 3015 } 3016 3017 /* Callee function to free the node */ 3018 *del = cur; 3019 3020 return BCM_E_NONE; 3021 } 3022 3023 3024 /* To allocate running id for UDF and Packet format IDs. */ 3025 STATIC int 3026 bcmi_xgs4_udf_id_running_id_alloc(int unit, bcmiUdfObjectType type, int *id) 3027 { 3028 int rv; 3029 int ix; 3030 int min_ix, max_ix; 3031 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 3032 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 3033 3034 if (type == bcmiUdfObjectUdf) { 3035 min_ix = BCMI_XGS4_UDF_ID_MIN; 3036 max_ix = BCMI_XGS4_UDF_ID_MAX; 3037 3038 ix = BCMI_XGS4_UDF_ID_RUNNING(unit); 3039 } else { 3040 min_ix = BCMI_XGS4_UDF_PKT_FORMAT_ID_MIN; 3041 max_ix = BCMI_XGS4_UDF_PKT_FORMAT_ID_MAX; 3042 3043 ix = BCMI_XGS4_UDF_PKT_FORMAT_ID_RUNNING(unit); 3044 } 3045 3046 if (max_ix < ix) { 3047 for (ix = min_ix; ix <= max_ix; ix++) { 3048 if (type == bcmiUdfObjectUdf) { 3049 rv = bcmi_xgs4_udf_offset_node_get(unit, ix, &offset_info); 3050 if (BCM_E_NOT_FOUND == rv) { 3051 break; 3052 } 3053 } else { 3054 rv = bcmi_xgs4_udf_tcam_node_get(unit, ix, &tcam_info); 3055 if (BCM_E_NOT_FOUND == rv) { 3056 break; 3057 } 3058 } 3059 if (BCM_FAILURE(rv)) { 3060 break; 3061 } 3062 } 3063 3064 /* All 64k udf ids are used up */ 3065 if (max_ix < ix) { 3066 return BCM_E_FULL; 3067 } 3068 } 3069 3070 *id = ix; 3071 3072 return BCM_E_NONE; 3073 } 3074 3075 /* Conveerts chunk ID to OFFSET_xf and BASE_OFFSET_xf fields */ 3076 STATIC int 3077 bcmi_xgs4_udf_offset_to_hw_field(int unit, int udf_num, int user_num, 3078 soc_field_t *base_hw_f, soc_field_t *offset_hw_f) 3079 { 3080 soc_field_t offset_f[2][8] = { 3081 { 3082 UDF1_OFFSET0f, UDF1_OFFSET1f, 3083 UDF1_OFFSET2f, UDF1_OFFSET3f, 3084 UDF1_OFFSET4f, UDF1_OFFSET5f, 3085 UDF1_OFFSET6f, UDF1_OFFSET7f 3086 }, 3087 { 3088 UDF2_OFFSET0f, UDF2_OFFSET1f, 3089 UDF2_OFFSET2f, UDF2_OFFSET3f, 3090 UDF2_OFFSET4f, UDF2_OFFSET5f, 3091 UDF2_OFFSET6f, UDF2_OFFSET7f 3092 } 3093 }; 3094 3095 soc_field_t base_offset_f[2][8] = { 3096 { 3097 UDF1_BASE_OFFSET_0f, UDF1_BASE_OFFSET_1f, 3098 UDF1_BASE_OFFSET_2f, UDF1_BASE_OFFSET_3f, 3099 UDF1_BASE_OFFSET_4f, UDF1_BASE_OFFSET_5f, 3100 UDF1_BASE_OFFSET_6f, UDF1_BASE_OFFSET_7f 3101 }, 3102 { 3103 UDF2_BASE_OFFSET_0f, UDF2_BASE_OFFSET_1f, 3104 UDF2_BASE_OFFSET_2f, UDF2_BASE_OFFSET_3f, 3105 UDF2_BASE_OFFSET_4f, UDF2_BASE_OFFSET_5f, 3106 UDF2_BASE_OFFSET_6f, UDF2_BASE_OFFSET_7f 3107 } 3108 }; 3109 3110 *base_hw_f = base_offset_f[udf_num][user_num]; 3111 *offset_hw_f = offset_f[udf_num][user_num]; 3112 3113 return BCM_E_NONE; 3114 } 3115 3116 /* 3117 * Function: 3118 * bcmi_xgs4_udf_offset_uninstall 3119 * Purpose: 3120 * To uninstall the UDF offsets in the hardware 3121 * Parameters: 3122 * unit - (IN) Unit number. 3123 * e - (IN) Entry in the UDF_OFFSET table. 3124 * hw_bmap - (IN) Offsets to uninstall. 3125 * pipe_num - (IN) pipe_num (used only in pipeLocal mode) 3126 * Returns: 3127 * BCM_E_XXX 3128 * Notes: 3129 */ 3130 STATIC int 3131 bcmi_xgs4_udf_offset_uninstall(int unit, int e, uint32 hw_bmap, int pipe_num) 3132 { 3133 int udf_idx, user_idx; 3134 int rv; 3135 int base = 0x0; 3136 int offset = 0x0; 3137 soc_mem_t mem; 3138 soc_field_t base_f, offset_f; 3139 fp_udf_offset_entry_t offset_buf; 3140 3141 if ((e < 0) && (e > BCMI_XGS4_UDF_CTRL_MAX_UDF_ENTRIES(unit))) { 3142 return BCM_E_PARAM; 3143 } 3144 3145 #if defined (BCM_TOMAHAWK_SUPPORT) 3146 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 3147 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 3148 mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->offset_mem)[pipe_num]; 3149 } else 3150 #endif 3151 { 3152 mem = UDF_CTRL(unit)->offset_mem; 3153 } 3154 3155 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, e, &offset_buf); 3156 BCM_IF_ERROR_RETURN(rv); 3157 3158 for (udf_idx = 0; udf_idx < 2; udf_idx++) { 3159 for (user_idx = 0; user_idx < (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit)/2); user_idx++) { 3160 if (!(hw_bmap & (1 << (udf_idx * 3161 (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit)/2) + user_idx)))) { 3162 continue; 3163 } 3164 3165 3166 rv = bcmi_xgs4_udf_offset_to_hw_field(unit, udf_idx, user_idx, &base_f, &offset_f); 3167 BCM_IF_ERROR_RETURN(rv); 3168 3169 soc_mem_field32_set(unit, mem, &offset_buf, base_f, base); 3170 soc_mem_field32_set(unit, mem, &offset_buf, offset_f, offset); 3171 } 3172 } 3173 #if defined (BCM_TOMAHAWK_SUPPORT) 3174 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) { 3175 soc_mem_field32_set(unit, mem, &offset_buf, UDF_CLASS_IDf, 0); 3176 } 3177 #endif 3178 3179 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, e, &offset_buf); 3180 BCM_IF_ERROR_RETURN(rv); 3181 3182 return BCM_E_NONE; 3183 } 3184 3185 /* 3186 * Function: 3187 * bcmi_xgs4_udf_offset_install 3188 * Purpose: 3189 * To install the UDF offsets in the hardware 3190 * Parameters: 3191 * unit - (IN) Unit number. 3192 * e - (IN) Entry in the UDF_OFFSET table. 3193 * hw_bmap - (IN) Offsets to uninstall. 3194 * base - (IN) value to write in BASE_OFFSETx. 3195 * offset - (IN) Value to write in the OFFSETx. 3196 * pipe_num - (IN) Pipe number (used only in pipeLocal) 3197 * udf_class_id - (IN) Class ID used by the IFP Key Selection Mechanism 3198 * flags - (IN) Flags for offset entry 3199 * Returns: 3200 * BCM_E_XXX 3201 * Notes: 3202 */ 3203 STATIC int 3204 bcmi_xgs4_udf_offset_install(int unit, int e, uint32 hw_bmap, 3205 int base, int offset, int pipe_num, 3206 int class_id, uint8 flags) 3207 { 3208 int udf_idx, user_idx; 3209 int rv, max_offset; 3210 soc_mem_t mem; 3211 soc_field_t base_f, offset_f; 3212 fp_udf_offset_entry_t offset_buf; 3213 3214 if ((e < 0) && (e > BCMI_XGS4_UDF_CTRL_MAX_UDF_ENTRIES(unit))) { 3215 return BCM_E_PARAM; 3216 } 3217 if (!BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit)) { 3218 return BCM_E_PARAM; 3219 } 3220 max_offset = UDF_PACKET_PARSE_LENGTH/BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 3221 3222 #if defined (BCM_TOMAHAWK_SUPPORT) 3223 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 3224 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 3225 mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->offset_mem)[pipe_num]; 3226 } else 3227 #endif 3228 { 3229 mem = UDF_CTRL(unit)->offset_mem; 3230 } 3231 offset = (offset < 0) ? 0 : (uint32)offset; 3232 3233 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, e, &offset_buf); 3234 BCM_IF_ERROR_RETURN(rv); 3235 3236 for (udf_idx = 0; udf_idx < 2; udf_idx++) { 3237 for (user_idx = 0; user_idx < (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit)/2); user_idx++) { 3238 if (!(hw_bmap & (1 << (udf_idx * 3239 (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit)/2) + user_idx)))) { 3240 continue; 3241 } 3242 3243 rv = bcmi_xgs4_udf_offset_to_hw_field(unit, udf_idx, user_idx, &base_f, &offset_f); 3244 BCM_IF_ERROR_RETURN(rv); 3245 3246 /*handling wrap around*/ 3247 if((offset >= max_offset) || (offset < 0)){ 3248 offset = 0; 3249 } 3250 3251 soc_mem_field32_set(unit, mem, &offset_buf, base_f, base); 3252 soc_mem_field32_set(unit, mem, &offset_buf, offset_f, offset); 3253 3254 /* Every other offset chunk should have offset incr by 1 */ 3255 offset += 1; 3256 } 3257 } 3258 3259 #if defined (BCM_TOMAHAWK_SUPPORT) 3260 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) { 3261 soc_mem_field32_set(unit, mem, &offset_buf, UDF_CLASS_IDf, class_id); 3262 } 3263 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CONDITIONAL_CHECK) { 3264 if (flags & BCMI_XGS4_UDF_OFFSET_FLEXHASH) { 3265 soc_mem_field32_set(unit, mem, &offset_buf, 3266 ENABLE_UDF_CONDITIONAL_CHECKf, 1); 3267 } 3268 } 3269 #endif 3270 3271 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, e, &offset_buf); 3272 BCM_IF_ERROR_RETURN(rv); 3273 3274 3275 return BCM_E_NONE; 3276 } 3277 3278 /* 3279 * Function: 3280 * bcmi_xgs4_udf_tcam_entry_move 3281 * Purpose: 3282 * Move a single entry in udf tcam and offset tables. 3283 * Parameters: 3284 * unit - (IN) BCM device number. 3285 * tcam_entry_arr - (IN) Data control structure. 3286 * src - (IN) Move from index. 3287 * dst - (IN) Move to index. 3288 * pipe - (IN) Pipe num 3289 * Returns: 3290 * BCM_E_XXX 3291 */ 3292 STATIC int 3293 bcmi_xgs4_udf_tcam_entry_move(int unit, 3294 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, 3295 int src, int dst, int pipe_num) 3296 { 3297 int rv; /* Operation return status. */ 3298 soc_mem_t offset_mem, tcam_mem; /* Memory Ids */ 3299 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */ 3300 3301 /* Input parameters check. */ 3302 BCM_IF_NULL_RETURN_PARAM(tcam_entry_arr); 3303 3304 #if defined (BCM_TOMAHAWK_SUPPORT) 3305 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 3306 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 3307 if (pipe_num == BCMI_XGS4_UDF_INVALID_PIPE_NUM) { 3308 return BCM_E_PARAM; 3309 } 3310 tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[pipe_num]; 3311 offset_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->offset_mem)[pipe_num]; 3312 } else 3313 #endif 3314 { 3315 tcam_mem = UDF_CTRL(unit)->tcam_mem; 3316 offset_mem = UDF_CTRL(unit)->offset_mem; 3317 } 3318 if (tcam_mem == INVALIDm || offset_mem == INVALIDm) { 3319 return BCM_E_INTERNAL; 3320 } 3321 3322 rv = soc_mem_read(unit, offset_mem, MEM_BLOCK_ANY, src, hw_buf); 3323 BCM_IF_ERROR_RETURN(rv); 3324 rv = soc_mem_write(unit, offset_mem, MEM_BLOCK_ALL, dst, hw_buf); 3325 BCM_IF_ERROR_RETURN(rv); 3326 3327 rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY, src, hw_buf); 3328 BCM_IF_ERROR_RETURN(rv); 3329 rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, dst, hw_buf); 3330 BCM_IF_ERROR_RETURN(rv); 3331 3332 /* Clear entries at old index. */ 3333 rv = soc_mem_write(unit, offset_mem, MEM_BLOCK_ALL, src, 3334 soc_mem_entry_null(unit, offset_mem)); 3335 BCM_IF_ERROR_RETURN(rv); 3336 3337 rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, src, 3338 soc_mem_entry_null(unit, tcam_mem)); 3339 BCM_IF_ERROR_RETURN(rv); 3340 3341 /* Update hw_idx in the packet formats */ 3342 tcam_entry_arr[src].tcam_info->hw_idx = dst; 3343 3344 /* Update sw structure tracking entry use. */ 3345 sal_memcpy(tcam_entry_arr + dst, 3346 tcam_entry_arr + src, 3347 sizeof(bcmi_xgs4_udf_tcam_entry_t)); 3348 3349 sal_memset(tcam_entry_arr + src, 0, 3350 sizeof(bcmi_xgs4_udf_tcam_entry_t)); 3351 3352 3353 return (BCM_E_NONE); 3354 } 3355 3356 /* 3357 * Function: 3358 * bcmi_xgs4_udf_tcam_move_up 3359 * Purpose: 3360 * Moved udf tcam entries up. 3361 * Parameters: 3362 * unit - (IN) BCM device number. 3363 * tcam_entry_arr - (IN) Data control structure. 3364 * dest - (IN) Insertion target index. 3365 * free_slot - (IN) Free slot. 3366 * pipe_num - (IN) Pipe num 3367 * Returns: 3368 * BCM_E_XXX 3369 */ 3370 STATIC int 3371 bcmi_xgs4_udf_tcam_move_up(int unit, 3372 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, 3373 int dest, int free_slot, int pipe_num) 3374 { 3375 int idx; /* Entries iterator. */ 3376 int rv; /* Operation return status. */ 3377 3378 for (idx = free_slot; idx > dest; idx --) { 3379 rv = bcmi_xgs4_udf_tcam_entry_move(unit, tcam_entry_arr, 3380 idx - 1, idx, pipe_num); 3381 BCM_IF_ERROR_RETURN(rv); 3382 } 3383 3384 return (BCM_E_NONE); 3385 } 3386 3387 /* 3388 * Function: 3389 * bcmi_xgs4_udf_tcam_move_down 3390 * Purpose: 3391 * Moved udf tcam entries down 3392 * Parameters: 3393 * unit - (IN) BCM device number. 3394 * tcam_entry_arr - (IN) Data control structure. 3395 * dest - (IN) Insertion target index. 3396 * pipe_num - (IN) Pipe num 3397 * free_slot - (IN) Free slot. 3398 * Returns: 3399 * BCM_E_XXX 3400 */ 3401 STATIC int 3402 bcmi_xgs4_udf_tcam_move_down(int unit, 3403 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, 3404 int dest, int free_slot, int pipe_num) 3405 { 3406 int idx; /* Entries iterator. */ 3407 int rv; /* Operation return status. */ 3408 3409 for (idx = free_slot; idx < dest; idx ++) { 3410 rv = bcmi_xgs4_udf_tcam_entry_move(unit, tcam_entry_arr, 3411 idx + 1, idx, pipe_num); 3412 BCM_IF_ERROR_RETURN(rv); 3413 } 3414 return (BCM_E_NONE); 3415 } 3416 3417 STATIC int 3418 bcmi_xgs4_udf_tcam_entries_compare(int unit, 3419 uint32 *hw_entry, uint32 *sw_entry) 3420 { 3421 return sal_memcmp(sw_entry, hw_entry, sizeof(fp_udf_tcam_entry_t)); 3422 } 3423 3424 3425 /* 3426 * Function: 3427 * bcmi_xgs4_udf_tcam_entry_match 3428 * Purpose: 3429 * Match tcam entry against currently instllaed ones 3430 * Parameters: 3431 * unit - (IN) BCM device number. 3432 * new - (IN New Tcam info structure. 3433 * match - (IN Matched Tcam info structure. 3434 * Returns: 3435 * BCM_E_XXX 3436 */ 3437 STATIC int 3438 bcmi_xgs4_udf_tcam_entry_match(int unit, bcmi_xgs4_udf_tcam_info_t *new, 3439 bcmi_xgs4_udf_tcam_info_t **match) 3440 { 3441 uint32 *old_buf; /* Tcam entry pointer. */ 3442 uint32 *new_buf; /* Tcam entry pointer. */ 3443 bcmi_xgs4_udf_tcam_info_t *tmp; 3444 3445 /* Input parameters check. */ 3446 BCM_IF_NULL_RETURN_PARAM(new); 3447 3448 new_buf = (uint32 *)&(new->hw_buf); 3449 3450 tmp = UDF_CTRL(unit)->tcam_info_head; 3451 3452 *match = NULL; 3453 3454 while (tmp != NULL) { 3455 if (tmp == new) { 3456 tmp = tmp->next; 3457 continue; 3458 } 3459 3460 old_buf = (uint32 *)&(tmp->hw_buf); 3461 3462 if (!bcmi_xgs4_udf_tcam_entries_compare(unit, old_buf, new_buf)) { 3463 *match = tmp; 3464 break; 3465 } 3466 3467 tmp = tmp->next; 3468 } 3469 3470 if (*match == NULL) { 3471 return BCM_E_NOT_FOUND; 3472 } 3473 3474 3475 return BCM_E_NONE; 3476 3477 } 3478 3479 /* 3480 * Function: 3481 * bcmi_xgs4_udf_tcam_entry_insert 3482 * Purpose: 3483 * To insert an entry in UDF_TCAM at an available index. 3484 * Parameters: 3485 * unit - (IN) BCM device number. 3486 * tcam_new - (IN) Tcam info to be inserted. 3487 * Returns: 3488 * BCM_E_XXX 3489 */ 3490 STATIC int 3491 bcmi_xgs4_udf_tcam_entry_insert(int unit, bcmi_xgs4_udf_tcam_info_t *tcam_new) 3492 { 3493 int idx; /* FP UDF tcam table interator. */ 3494 int rv; /* Operation return status. */ 3495 int idx_max; /* FP UDF tcam table index max. */ 3496 int idx_min; /* FP UDF tcam table index min. */ 3497 int range_min; /* Index min for entry insertion. */ 3498 int range_max; /* Index max for entry insertion. */ 3499 int tcam_idx; 3500 int unused_entry_min; /* Unused entry before the range. */ 3501 int unused_entry_max; /* Unused entry after the range. */ 3502 bcmi_xgs4_udf_tcam_info_t *tcam_info; 3503 bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr; /* Tcam entries array. */ 3504 soc_mem_t tcam_mem; /* tcam memory access */ 3505 int pipe_num = BCMI_XGS4_UDF_INVALID_PIPE_NUM; /* used only in pipeLocal mode */ 3506 3507 /* Initialization. */ 3508 idx_min = soc_mem_index_min(unit, UDF_CTRL(unit)->tcam_mem); 3509 idx_max = soc_mem_index_max(unit, UDF_CTRL(unit)->tcam_mem); 3510 3511 if ((idx_min < 0) || (idx_max < 0)) { 3512 return BCM_E_INTERNAL; 3513 } 3514 3515 range_min = idx_min; 3516 range_max = idx_max; 3517 unused_entry_min = unused_entry_max = -1; 3518 3519 #if defined (BCM_TOMAHAWK_SUPPORT) 3520 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 3521 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 3522 pipe_num = tcam_new->associated_pipe; 3523 tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array_per_pipe[pipe_num]; 3524 tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[pipe_num]; 3525 } else 3526 #endif 3527 { 3528 tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array; 3529 tcam_mem = UDF_CTRL(unit)->tcam_mem; 3530 } 3531 3532 /* No identical entry found try to allocate an unused entry and 3533 * reshuffle tcam if necessary to organize entries by priority. 3534 */ 3535 for (idx = idx_min; idx <= idx_max; idx++) { 3536 if (0 == tcam_entry_arr[idx].valid) { 3537 if (idx <= range_max) { 3538 /* Any free index below range max can be used for insertion. */ 3539 unused_entry_min = idx; 3540 } else { 3541 /* There is no point to continue after first 3542 * free index above range max. 3543 */ 3544 unused_entry_max = idx; 3545 break; 3546 } 3547 } else { 3548 tcam_info = tcam_entry_arr[idx].tcam_info; 3549 /* Identify insertion range. */ 3550 /* 3551 * Principle: 3552 * 1. Different entries must have different priorities, unless 0 3553 * 2. Place entry of higher priority to lower index. 3554 * 3. If priorities are equal (0), place entry of higher 3555 * pkt_format_id to lower index. 3556 * Process: 3557 * If existed tcam priority is explicitly configured (non-zero), 3558 * find the minimum entry whose priority is more than new priority, 3559 * and the maximum entry priority is less than new priority. 3560 * If existed tcam priority is not specified (zero), 3561 * if new priority is non-zero, find available place; 3562 * if new priority is zero, find available place using pkt_format_id. 3563 * If new priority is non-zero and equals to exsited priority, 3564 * or new pkt_format_id equals to exsited pkt_format_id, 3565 * don't insert, return parameter error. 3566 */ 3567 if (0 < tcam_info->priority) { 3568 if (tcam_info->priority > tcam_new->priority) { 3569 range_min = idx; 3570 } else if (tcam_info->priority < tcam_new->priority) { 3571 if (idx < range_max) { 3572 range_max = idx; 3573 } 3574 } else { 3575 return BCM_E_PARAM; 3576 } 3577 } else if (0 == tcam_info->priority) { 3578 if (0 == tcam_new->priority) { 3579 if (tcam_info->pkt_format_id > tcam_new->pkt_format_id) { 3580 range_min = idx; 3581 } else if (tcam_info->pkt_format_id < 3582 tcam_new->pkt_format_id) { 3583 if (idx < range_max) { 3584 range_max = idx; 3585 } 3586 } else { 3587 return BCM_E_PARAM; 3588 } 3589 } else if (0 < tcam_new->priority) { 3590 if (idx < range_max) { 3591 range_max = idx; 3592 } 3593 } else { 3594 return BCM_E_PARAM; 3595 } 3596 } else { 3597 return BCM_E_PARAM; 3598 } 3599 } 3600 } 3601 3602 /* Check if tcam is completely full. */ 3603 if ((unused_entry_min == -1) && (unused_entry_max == -1)) { 3604 return (BCM_E_FULL); 3605 } 3606 3607 /* Tcam entries shuffling. */ 3608 if (unused_entry_min > range_min) { 3609 tcam_idx = unused_entry_min; 3610 } else if (unused_entry_min == -1) { 3611 rv = bcmi_xgs4_udf_tcam_move_up(unit, tcam_entry_arr, 3612 range_max, unused_entry_max, 3613 pipe_num); 3614 3615 BCM_IF_ERROR_RETURN(rv); 3616 tcam_idx = range_max; 3617 } else if (unused_entry_max == -1) { 3618 rv = bcmi_xgs4_udf_tcam_move_down(unit, tcam_entry_arr, 3619 range_min, unused_entry_min, 3620 pipe_num); 3621 BCM_IF_ERROR_RETURN(rv); 3622 tcam_idx = range_min; 3623 } else if ((range_min - unused_entry_min) > 3624 (unused_entry_max - range_max)) { 3625 rv = bcmi_xgs4_udf_tcam_move_up(unit, tcam_entry_arr, 3626 range_max, unused_entry_max, 3627 pipe_num); 3628 BCM_IF_ERROR_RETURN(rv); 3629 tcam_idx = range_max; 3630 } else { 3631 rv = bcmi_xgs4_udf_tcam_move_down(unit, tcam_entry_arr, 3632 range_min, unused_entry_min, 3633 pipe_num); 3634 BCM_IF_ERROR_RETURN(rv); 3635 tcam_idx = range_min; 3636 } 3637 3638 /* Install the entry into hardware */ 3639 rv = soc_mem_write(unit, tcam_mem, 3640 MEM_BLOCK_ALL, tcam_idx, &(tcam_new->hw_buf)); 3641 SOC_IF_ERROR_RETURN(rv); 3642 3643 /* Index was successfully allocated. */ 3644 tcam_new->hw_idx = tcam_idx; 3645 tcam_entry_arr[tcam_idx].valid = 1; 3646 tcam_entry_arr[tcam_idx].tcam_info = tcam_new; 3647 3648 #ifdef BCM_TOMAHAWK_SUPPORT 3649 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 3650 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 3651 tcam_new->hw_idx_per_pipe[tcam_new->associated_pipe] = tcam_idx; 3652 } 3653 #endif 3654 3655 return (BCM_E_NONE); 3656 } 3657 3658 /* 3659 * Function: 3660 * bcmi_xgs4_udf_tcam_entry_l3_parse 3661 * Purpose: 3662 * Parse udf tcam entry l3 format match key. 3663 * Parameters: 3664 * unit - (IN) BCM device number. 3665 * hw_buf - (IN) Hw buffer. 3666 * pkt_fmt - (OUT) Packet format structure. 3667 * Returns: 3668 * BCM_E_XXX 3669 */ 3670 STATIC int 3671 bcmi_xgs4_udf_tcam_entry_l3_parse(int unit, uint32 *hw_buf, 3672 bcm_udf_pkt_format_info_t *pkt_fmt) 3673 { 3674 uint32 ethertype = -1; 3675 uint32 inner_iptype = -1; 3676 uint32 ethertype_mask = -1; 3677 uint32 outer_iptype = -1; 3678 uint32 outer_iptype_ip4_val = -1; 3679 uint32 outer_iptype_ip6_val = -1; 3680 uint32 outer_iptype_mask = -1; 3681 uint32 inner_iptype_mask = -1; 3682 uint32 l3fields = -1; 3683 uint32 l3fields_mask = -1; 3684 soc_mem_t mem = UDF_CTRL(unit)->tcam_mem; 3685 uint32 iptype_none_val = 0; 3686 uint8 fc_header_encode = 0; 3687 uint8 fc_hdr_encode_mask = 0; 3688 3689 /* Input parameters check. */ 3690 BCM_IF_NULL_RETURN_PARAM(hw_buf); 3691 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 3692 3693 if (SOC_IS_TD_TT(unit) 3694 || SOC_IS_KATANAX(unit) 3695 || SOC_IS_TRIUMPH3(unit)) { 3696 iptype_none_val = 2; 3697 } 3698 if ((ethertype_mask = 3699 soc_mem_field32_get(unit, mem, hw_buf, L2_ETHER_TYPE_MASKf))) { 3700 ethertype = soc_mem_field32_get(unit, mem, hw_buf, L2_ETHER_TYPEf); 3701 } 3702 3703 if ((inner_iptype_mask = 3704 soc_mem_field32_get(unit, mem, hw_buf, INNER_IP_TYPE_MASKf))) { 3705 inner_iptype = soc_mem_field32_get(unit, mem, hw_buf, INNER_IP_TYPEf); 3706 } 3707 3708 outer_iptype = soc_mem_field32_get(unit, mem, hw_buf, OUTER_IP_TYPEf); 3709 outer_iptype_mask = soc_mem_field32_get(unit, mem, 3710 hw_buf, OUTER_IP_TYPE_MASKf); 3711 3712 if (soc_mem_field32_get(unit, mem, hw_buf, L3_FIELDS_MASKf)) { 3713 l3fields = soc_mem_field32_get(unit, mem, hw_buf, L3_FIELDSf); 3714 l3fields_mask = soc_mem_field32_get(unit, mem, hw_buf, L3_FIELDS_MASKf); 3715 if (0x8847 != ethertype) { 3716 /* MPLS_ANY has L3_FIELDSf == 0 */ 3717 pkt_fmt->ip_protocol = (l3fields >> 16); 3718 pkt_fmt->ip_protocol_mask = (l3fields_mask >> 16); 3719 } 3720 } 3721 3722 outer_iptype_ip4_val = OUTER_IP4_TYPE_VAL(unit); 3723 outer_iptype_ip6_val = OUTER_IP6_TYPE_VAL(unit); 3724 3725 pkt_fmt->ethertype = ethertype; 3726 pkt_fmt->ethertype_mask = ethertype_mask; 3727 3728 /* 3729 * Logic below implicitly checks Ethertype value for IP, MPLS and FCoE 3730 * frames. 3731 * 0x0800 - IPv4, 0x86DD - IPv6, 0x8847 - MPLS , 0x8906 + 0x8914 - FCoE 3732 */ 3733 3734 if ((ethertype == 0x800) && (outer_iptype == outer_iptype_ip4_val)) { 3735 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE; 3736 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4_WITH_OPTIONS; 3737 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE; 3738 } else if ((ethertype == 0x86dd) && 3739 (outer_iptype == outer_iptype_ip6_val)) { 3740 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE; 3741 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6_WITH_OPTIONS; 3742 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE; 3743 } else if ((ethertype == 0x800) && (inner_iptype == iptype_none_val)) { 3744 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE; 3745 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4; 3746 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE; 3747 } else if ((ethertype == 0x86dd) && (inner_iptype == iptype_none_val)) { 3748 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE; 3749 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6; 3750 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE; 3751 } else if ((ethertype == 0x800) && (l3fields == 0x40000)) { 3752 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_IP_IN_IP; 3753 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4; 3754 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP4; 3755 } else if ((ethertype == 0x800) && (l3fields == 0x290000)) { 3756 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_IP_IN_IP; 3757 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4; 3758 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP6; 3759 } else if ((ethertype == 0x86dd) && (l3fields == 0x40000)) { 3760 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_IP_IN_IP; 3761 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6; 3762 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP4; 3763 } else if ((ethertype == 0x86dd) && (l3fields == 0x290000)) { 3764 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_IP_IN_IP; 3765 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6; 3766 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP6; 3767 } else if ((ethertype == 0x800) && (l3fields == 0x2f0800)) { 3768 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE; 3769 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4; 3770 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP4; 3771 } else if ((ethertype == 0x800) && (l3fields == 0x2f86dd)) { 3772 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE; 3773 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4; 3774 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP6; 3775 } else if ((ethertype == 0x86dd) && (l3fields == 0x2f0800)) { 3776 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE; 3777 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6; 3778 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP4; 3779 } else if ((ethertype == 0x86dd) && (l3fields == 0x2f86dd)) { 3780 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE; 3781 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6; 3782 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP6; 3783 } else if ((ethertype == 0x800) && (l3fields & 0xffff)) { 3784 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE; 3785 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4; 3786 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE; 3787 pkt_fmt->inner_protocol = (uint16)(l3fields & 0xffff); 3788 pkt_fmt->inner_protocol_mask = (uint16)(l3fields_mask & 0xffff); 3789 } else if ((ethertype == 0x86dd) && (l3fields & 0xffff)) { 3790 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE; 3791 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6; 3792 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE; 3793 pkt_fmt->inner_protocol = (uint16)(l3fields & 0xffff); 3794 pkt_fmt->inner_protocol_mask = (uint16)(l3fields_mask & 0xffff); 3795 } else if ((ethertype == 0x8847)) { 3796 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_MPLS; 3797 3798 switch (l3fields & 0xf) { 3799 3800 case 1: 3801 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_ONE_LABEL; 3802 break; 3803 case 2: 3804 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_TWO_LABELS; 3805 break; 3806 case 3: 3807 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_THREE_LABELS; 3808 break; 3809 case 4: 3810 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_FOUR_LABELS; 3811 break; 3812 case 5: 3813 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_FIVE_LABELS; 3814 break; 3815 default : 3816 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_ANY; 3817 break; 3818 } 3819 #if defined (BCM_TOMAHAWK3_SUPPORT) 3820 if (SOC_IS_TOMAHAWK3(unit)) { 3821 pkt_fmt->first_2bytes_after_mpls_bos 3822 = ((l3fields >> MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS) 3823 & 0xffff); 3824 pkt_fmt->first_2bytes_after_mpls_bos_mask 3825 = ((l3fields_mask 3826 >> MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS) 3827 & 0xffff); 3828 } 3829 #endif 3830 3831 } else if (ethertype == 0x8906 || ethertype == 0x8914) { 3832 pkt_fmt->tunnel = (ethertype == 0x8906) 3833 ? BCM_PKT_FORMAT_TUNNEL_FCOE 3834 : BCM_PKT_FORMAT_TUNNEL_FCOE_INIT; 3835 3836 fc_header_encode = soc_mem_field32_get(unit, mem, hw_buf, 3837 FC_HDR_ENCODE_1f); 3838 fc_hdr_encode_mask = soc_mem_field32_get(unit, mem, hw_buf, 3839 FC_HDR_ENCODE_1_MASKf); 3840 3841 if (0 != fc_header_encode && 0 != fc_hdr_encode_mask) { 3842 3843 switch (fc_header_encode & fc_hdr_encode_mask) { 3844 case 1: 3845 pkt_fmt->fibre_chan_outer 3846 = BCM_PKT_FORMAT_FIBRE_CHAN; 3847 break; 3848 case 2: 3849 pkt_fmt->fibre_chan_outer 3850 = BCM_PKT_FORMAT_FIBRE_CHAN_VIRTUAL; 3851 break; 3852 case 3: 3853 pkt_fmt->fibre_chan_outer 3854 = BCM_PKT_FORMAT_FIBRE_CHAN_ENCAP; 3855 break; 3856 case 4: 3857 pkt_fmt->fibre_chan_outer 3858 = BCM_PKT_FORMAT_FIBRE_CHAN_ROUTED; 3859 break; 3860 default: 3861 return (BCM_E_INTERNAL); 3862 } 3863 } 3864 3865 fc_header_encode = soc_mem_field32_get(unit, mem, hw_buf, 3866 FC_HDR_ENCODE_2f); 3867 fc_hdr_encode_mask = soc_mem_field32_get(unit, mem, hw_buf, 3868 FC_HDR_ENCODE_2_MASKf); 3869 if (0 != fc_header_encode && 0 != fc_hdr_encode_mask) { 3870 3871 switch (fc_header_encode & fc_hdr_encode_mask) { 3872 case 1: 3873 pkt_fmt->fibre_chan_inner 3874 = BCM_PKT_FORMAT_FIBRE_CHAN; 3875 break; 3876 case 2: 3877 pkt_fmt->fibre_chan_inner 3878 = BCM_PKT_FORMAT_FIBRE_CHAN_VIRTUAL; 3879 break; 3880 case 3: 3881 pkt_fmt->fibre_chan_inner 3882 = BCM_PKT_FORMAT_FIBRE_CHAN_ENCAP; 3883 break; 3884 case 4: 3885 pkt_fmt->fibre_chan_inner 3886 = BCM_PKT_FORMAT_FIBRE_CHAN_ROUTED; 3887 break; 3888 default: 3889 return (BCM_E_INTERNAL); 3890 } 3891 } 3892 } else if (outer_iptype_mask == 0x7) { 3893 /* 3894 * For Non-IP traffic: OUTER_IP_TYPE_MASK = 0x7 and 3895 * outer_ip_type_val = 0 (TR2) or 2 (Trident, Katana). 3896 */ 3897 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE; 3898 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP_NONE; 3899 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE; 3900 } else if (0x0 == ethertype_mask && 0x0 == inner_iptype_mask 3901 && 0x0 == outer_iptype_mask) { 3902 /* 3903 * Do not care about IP headers and Tunnel Type. 3904 */ 3905 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_ANY; 3906 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP_ANY; 3907 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_ANY; 3908 } else if (outer_iptype_mask == 0x0) { 3909 /* 3910 * Do not care about Outer IP. Inner IP is not valid 3911 * as its not a Tunnel. 3912 */ 3913 pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE; 3914 pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP_ANY; 3915 pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE; 3916 } else { 3917 return (BCM_E_INTERNAL); 3918 } 3919 3920 3921 return (BCM_E_NONE); 3922 } 3923 3924 /* 3925 * Function: 3926 * bcmi_xgs4_udf_tcam_entry_l3_init 3927 * Purpose: 3928 * Initialize udf tcam entry l2 format match key. 3929 * Parameters: 3930 * unit - (IN) BCM device number. 3931 * pkt_fmt - (IN) Packet format structure. 3932 * hw_buf - (IN/OUT) Hw buffer. 3933 * Returns: 3934 * BCM_E_XXX 3935 */ 3936 STATIC int 3937 bcmi_xgs4_udf_tcam_entry_l3_init(int unit, 3938 bcm_udf_pkt_format_info_t *pkt_fmt, 3939 uint32 *hw_buf) 3940 { 3941 uint32 iptype_none_val = 0; 3942 uint32 outer_iptype_ip4_val = 0; 3943 uint32 outer_iptype_ip6_val = 0; 3944 3945 uint16 l2_ethertype_val = 0; 3946 uint16 l2_ethertype_mask = 0; 3947 uint32 l3_fields_val = 0; 3948 uint32 l3_fields_mask = 0; 3949 uint32 inner_ip_type_val = 0; 3950 uint32 inner_ip_type_mask = 0; 3951 uint32 outer_ip_type_val = 0; 3952 uint32 outer_ip_type_mask = 0; 3953 uint32 inner_chn_key = 0; 3954 uint32 inner_chn_mask = 0; 3955 uint32 outer_chn_key = 0; 3956 uint32 outer_chn_mask = 0; 3957 #if defined (BCM_TOMAHAWK3_SUPPORT) 3958 uint16 first_2bytes_after_mpls_bos = 0; 3959 uint16 first_2bytes_after_mpls_bos_mask = 0; 3960 #endif 3961 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; 3962 3963 3964 /* Input parameters check. */ 3965 BCM_IF_NULL_RETURN_PARAM(hw_buf); 3966 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 3967 3968 if (SOC_IS_TD_TT(unit) 3969 || SOC_IS_KATANAX(unit) 3970 || SOC_IS_TRIUMPH3(unit)) { 3971 iptype_none_val = 2; 3972 } 3973 3974 outer_iptype_ip4_val = OUTER_IP4_TYPE_VAL(unit); 3975 outer_iptype_ip6_val = OUTER_IP6_TYPE_VAL(unit); 3976 3977 if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_NONE) { 3978 3979 /* inner ip type (none). */ 3980 inner_ip_type_val = iptype_none_val; 3981 inner_ip_type_mask = 0x7; 3982 3983 3984 switch (pkt_fmt->outer_ip) { 3985 3986 case BCM_PKT_FORMAT_IP4_WITH_OPTIONS: 3987 l2_ethertype_val = 0x800; 3988 l2_ethertype_mask = 0xffff; 3989 outer_ip_type_val = outer_iptype_ip4_val; 3990 outer_ip_type_mask = 0x7; 3991 break; 3992 3993 case BCM_PKT_FORMAT_IP6_WITH_OPTIONS: 3994 l2_ethertype_val = 0x86dd; 3995 l2_ethertype_mask = 0xffff; 3996 outer_ip_type_val = outer_iptype_ip6_val; 3997 outer_ip_type_mask = 0x7; 3998 break; 3999 4000 case BCM_PKT_FORMAT_IP4: 4001 l2_ethertype_val = 0x0800; 4002 l2_ethertype_mask = 0xffff; 4003 break; 4004 4005 case BCM_PKT_FORMAT_IP6: 4006 l2_ethertype_val = 0x86dd; 4007 l2_ethertype_mask = 0xffff; 4008 break; 4009 4010 case BCM_PKT_FORMAT_IP_NONE: 4011 outer_ip_type_val = iptype_none_val; 4012 outer_ip_type_mask = 0x7; 4013 break; 4014 4015 default: 4016 outer_ip_type_mask = 0x0; 4017 } 4018 } else if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_IP_IN_IP) { 4019 l2_ethertype_mask = 0xffff; 4020 l3_fields_mask = 0xff0000; 4021 if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP4) { 4022 /* Inner ip protocol v4. */ 4023 l3_fields_val = 0x40000; 4024 } else if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP6) { 4025 /* Inner ip protocol v6. */ 4026 l3_fields_val = 0x290000; 4027 } else { 4028 return (BCM_E_UNAVAIL); 4029 } 4030 4031 if (pkt_fmt->outer_ip == BCM_PKT_FORMAT_IP4) { 4032 /* L2 ether type 0x800 */ 4033 l2_ethertype_val = 0x800; 4034 } else if (pkt_fmt->outer_ip == BCM_PKT_FORMAT_IP6) { 4035 /* L2 ether type 0x86dd */ 4036 l2_ethertype_val = 0x86dd; 4037 } else { 4038 return (BCM_E_UNAVAIL); 4039 } 4040 } else if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_GRE) { 4041 4042 l2_ethertype_mask = 0xffff; 4043 l3_fields_mask = 0xffffff; 4044 if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP4) { 4045 /* Inner ip protocol gre, gre ethertype 0x800. */ 4046 l3_fields_val = 0x2f0800; 4047 } else if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP6) { 4048 /* Inner ip protocol gre, gre ethertype 0x86dd. */ 4049 l3_fields_val = 0x2f86dd; 4050 } else if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP_NONE) { 4051 /*when set inner_ip to IP_NONE, inner_protocal should not be IPV4 and IPV6*/ 4052 if (pkt_fmt->inner_protocol == 0x0800 || 4053 pkt_fmt->inner_protocol == 0x86dd) { 4054 return BCM_E_PARAM; 4055 } 4056 l3_fields_val = (pkt_fmt->inner_protocol & 0xffff); 4057 l3_fields_mask = (pkt_fmt->inner_protocol_mask & 0xffff); 4058 } else { 4059 return (BCM_E_UNAVAIL); 4060 } 4061 4062 if (pkt_fmt->outer_ip == BCM_PKT_FORMAT_IP4) { 4063 l2_ethertype_val = 0x0800; 4064 } else if (pkt_fmt->outer_ip == BCM_PKT_FORMAT_IP6) { 4065 /* L2 ether type 0x86dd */ 4066 l2_ethertype_val = 0x86dd; 4067 } else { 4068 return (BCM_E_UNAVAIL); 4069 } 4070 } else if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_MPLS) { 4071 4072 l3_fields_mask = 0x0f; 4073 switch (pkt_fmt->mpls) { 4074 4075 case BCM_PKT_FORMAT_MPLS_ONE_LABEL: 4076 l3_fields_val = 0x01; 4077 break; 4078 4079 case BCM_PKT_FORMAT_MPLS_TWO_LABELS: 4080 l3_fields_val = 0x02; 4081 break; 4082 4083 #ifdef MPLS_FIVE_LABELS_SUPPORT 4084 4085 case BCM_PKT_FORMAT_MPLS_THREE_LABELS: 4086 l3_fields_val = 0x03; 4087 break; 4088 4089 case BCM_PKT_FORMAT_MPLS_FOUR_LABELS: 4090 l3_fields_val = 0x04; 4091 break; 4092 4093 case BCM_PKT_FORMAT_MPLS_FIVE_LABELS: 4094 l3_fields_val = 0x05; 4095 break; 4096 #endif /* MPLS_FIVE_LABELS_SUPPORT */ 4097 case BCM_PKT_FORMAT_MPLS_ANY: 4098 l3_fields_val = 0x0; 4099 l3_fields_mask = 0x0; 4100 break; 4101 4102 default: 4103 return (BCM_E_UNAVAIL); 4104 } 4105 4106 l2_ethertype_val = 0x8847; 4107 l2_ethertype_mask = 0xffff; 4108 4109 #if defined (BCM_TOMAHAWK3_SUPPORT) 4110 if (SOC_IS_TOMAHAWK3(unit)) { 4111 if (pkt_fmt->first_2bytes_after_mpls_bos_mask != 0) { 4112 first_2bytes_after_mpls_bos = soc_mem_field32_get(unit, tcam_mem, 4113 hw_buf, L3_FIELDSf); 4114 first_2bytes_after_mpls_bos_mask = soc_mem_field32_get(unit, tcam_mem, 4115 hw_buf, L3_FIELDS_MASKf); 4116 4117 first_2bytes_after_mpls_bos 4118 = ((first_2bytes_after_mpls_bos 4119 >> MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS) 4120 & 0xffff); 4121 first_2bytes_after_mpls_bos_mask 4122 = ((first_2bytes_after_mpls_bos_mask 4123 >> MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS) 4124 & 0xffff); 4125 4126 if ((first_2bytes_after_mpls_bos_mask != 0) && 4127 ((first_2bytes_after_mpls_bos & first_2bytes_after_mpls_bos_mask) != 4128 (pkt_fmt->first_2bytes_after_mpls_bos 4129 & pkt_fmt->first_2bytes_after_mpls_bos_mask))) { 4130 return BCM_E_CONFIG; 4131 4132 } else { 4133 l3_fields_val = (((pkt_fmt->first_2bytes_after_mpls_bos & 0xffff) 4134 << MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS) | 4135 (l3_fields_val & 0xf)); 4136 l3_fields_mask = (((pkt_fmt->first_2bytes_after_mpls_bos_mask 4137 & 0xffff) << MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS) | 4138 (l3_fields_mask & 0xf)); 4139 } 4140 } 4141 } 4142 #endif 4143 4144 } else if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_FCOE || 4145 pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_FCOE_INIT) { 4146 if (!SOC_MEM_FIELD_VALID(unit, tcam_mem, FC_HDR_ENCODE_1f)) { 4147 return BCM_E_UNAVAIL; 4148 } 4149 4150 l2_ethertype_val = ((pkt_fmt->tunnel == 4151 BCM_PKT_FORMAT_TUNNEL_FCOE) ? 4152 0x8906 : 0x8914); 4153 4154 l2_ethertype_mask = 0xffff; 4155 4156 outer_chn_mask = 0x7; 4157 switch (pkt_fmt->fibre_chan_outer) { 4158 case BCM_PKT_FORMAT_FIBRE_CHAN: 4159 outer_chn_key = 1; 4160 break; 4161 case BCM_PKT_FORMAT_FIBRE_CHAN_ENCAP: 4162 outer_chn_key = 3; 4163 break; 4164 case BCM_PKT_FORMAT_FIBRE_CHAN_VIRTUAL: 4165 outer_chn_key = 2; 4166 break; 4167 case BCM_PKT_FORMAT_FIBRE_CHAN_ROUTED: 4168 outer_chn_key = 4; 4169 break; 4170 case BCM_PKT_FORMAT_FIBRE_CHAN_ANY: 4171 outer_chn_key = 0; 4172 outer_chn_mask = 0; 4173 break; 4174 default: 4175 return BCM_E_UNAVAIL; 4176 } 4177 4178 /* Entry matching on two extended headers has higher priority */ 4179 inner_chn_mask = 0x07; 4180 4181 switch (pkt_fmt->fibre_chan_inner) { 4182 case BCM_PKT_FORMAT_FIBRE_CHAN: 4183 inner_chn_key = 1; 4184 break; 4185 case BCM_PKT_FORMAT_FIBRE_CHAN_ENCAP: 4186 inner_chn_key = 3; 4187 break; 4188 case BCM_PKT_FORMAT_FIBRE_CHAN_VIRTUAL: 4189 inner_chn_key = 2; 4190 break; 4191 case BCM_PKT_FORMAT_FIBRE_CHAN_ROUTED: 4192 inner_chn_key = 4; 4193 break; 4194 case BCM_PKT_FORMAT_FIBRE_CHAN_ANY: 4195 inner_chn_key = 0; 4196 inner_chn_mask = 0; 4197 break; 4198 default: 4199 return BCM_E_UNAVAIL; 4200 } 4201 4202 } else if (BCM_PKT_FORMAT_TUNNEL_ANY == pkt_fmt->tunnel 4203 && BCM_PKT_FORMAT_IP_ANY == pkt_fmt->outer_ip 4204 && BCM_PKT_FORMAT_IP_ANY == pkt_fmt->inner_ip) { 4205 4206 l2_ethertype_val = 0; 4207 l2_ethertype_mask = 0; 4208 l3_fields_val = 0; 4209 l3_fields_mask = 0; 4210 outer_ip_type_val = 0; 4211 outer_ip_type_mask = 0; 4212 inner_ip_type_val = 0; 4213 inner_ip_type_mask = 0; 4214 inner_chn_key =0; 4215 inner_chn_mask =0; 4216 outer_chn_key =0; 4217 outer_chn_mask =0; 4218 4219 } else { 4220 return (BCM_E_UNAVAIL); 4221 } 4222 4223 /* Configure ip_protocol/mask fields */ 4224 if ((pkt_fmt->tunnel != BCM_PKT_FORMAT_TUNNEL_MPLS)) { 4225 l3_fields_val |= (pkt_fmt->ip_protocol << 16); 4226 l3_fields_mask |= (pkt_fmt->ip_protocol_mask << 16); 4227 } 4228 4229 /* ALL the keys are configured. Now set them in entry */ 4230 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4231 L2_ETHER_TYPEf, l2_ethertype_val); 4232 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4233 L2_ETHER_TYPE_MASKf, l2_ethertype_mask); 4234 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4235 L3_FIELDSf, l3_fields_val); 4236 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4237 L3_FIELDS_MASKf, l3_fields_mask); 4238 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4239 OUTER_IP_TYPEf, outer_ip_type_val); 4240 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4241 OUTER_IP_TYPE_MASKf, outer_ip_type_mask); 4242 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4243 INNER_IP_TYPEf, inner_ip_type_val); 4244 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4245 INNER_IP_TYPE_MASKf,inner_ip_type_mask); 4246 4247 if (SOC_MEM_FIELD_VALID(unit, tcam_mem,FC_HDR_ENCODE_1f)) { 4248 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4249 FC_HDR_ENCODE_1f, outer_chn_key); 4250 } 4251 if (SOC_MEM_FIELD_VALID(unit, tcam_mem,FC_HDR_ENCODE_1_MASKf)) { 4252 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4253 FC_HDR_ENCODE_1_MASKf, outer_chn_mask); 4254 } 4255 if (SOC_MEM_FIELD_VALID(unit, tcam_mem,FC_HDR_ENCODE_2f)) { 4256 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4257 FC_HDR_ENCODE_2f, inner_chn_key); 4258 } 4259 if (SOC_MEM_FIELD_VALID(unit, tcam_mem,FC_HDR_ENCODE_2_MASKf)) { 4260 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4261 FC_HDR_ENCODE_2_MASKf, inner_chn_mask); 4262 } 4263 4264 return (BCM_E_NONE); 4265 } 4266 4267 4268 /* Converts the misc packet format flags to fields in the UDF_TCAM */ 4269 STATIC int 4270 bcmi_xgs4_udf_tcam_misc_format_to_hw_fields( 4271 int unit, int type, 4272 soc_field_t *data_f, soc_field_t *mask_f, 4273 int *present, int *none, int *any, int *support) 4274 { 4275 4276 soc_field_t hw_fields_f[2][7] = { 4277 { 4278 HIGIGf, CNTAG_PRESENTf, 4279 ICNM_PACKETf, VNTAG_PRESENTf, 4280 ETAG_PACKETf, SUBPORT_TAG_PRESENTf, 4281 INT_PKTf 4282 }, 4283 { 4284 HIGIG_MASKf, CNTAG_PRESENT_MASKf, 4285 ICNM_PACKET_MASKf, VNTAG_PRESENT_MASKf, 4286 ETAG_PACKET_MASKf, SUBPORT_TAG_PRESENT_MASKf, 4287 INT_PKT_MASKf 4288 } 4289 }; 4290 int sw_flags[3][7] = { 4291 { 4292 BCM_PKT_FORMAT_HIGIG_PRESENT, 4293 BCM_PKT_FORMAT_CNTAG_PRESENT, 4294 BCM_PKT_FORMAT_ICNM_PRESENT, 4295 BCM_PKT_FORMAT_VNTAG_PRESENT, 4296 BCM_PKT_FORMAT_ETAG_PRESENT, 4297 BCM_PKT_FORMAT_SUBPORT_TAG_PRESENT, 4298 BCM_PKT_FORMAT_INT_PKT_PRESENT, 4299 }, 4300 { 4301 BCM_PKT_FORMAT_HIGIG_NONE, 4302 BCM_PKT_FORMAT_CNTAG_NONE, 4303 BCM_PKT_FORMAT_ICNM_NONE, 4304 BCM_PKT_FORMAT_VNTAG_NONE, 4305 BCM_PKT_FORMAT_ETAG_NONE, 4306 BCM_PKT_FORMAT_SUBPORT_TAG_NONE, 4307 BCM_PKT_FORMAT_INT_PKT_NONE, 4308 }, 4309 { 4310 BCM_PKT_FORMAT_HIGIG_ANY, 4311 BCM_PKT_FORMAT_CNTAG_ANY, 4312 BCM_PKT_FORMAT_ICNM_ANY, 4313 BCM_PKT_FORMAT_VNTAG_ANY, 4314 BCM_PKT_FORMAT_ETAG_ANY, 4315 BCM_PKT_FORMAT_SUBPORT_TAG_ANY, 4316 BCM_PKT_FORMAT_INT_PKT_ANY, 4317 } 4318 }; 4319 int ctrl_flags[1][7] = { 4320 { 4321 BCMI_XGS4_UDF_CTRL_TCAM_HIGIG, 4322 BCMI_XGS4_UDF_CTRL_TCAM_CNTAG, 4323 BCMI_XGS4_UDF_CTRL_TCAM_ICNM, 4324 BCMI_XGS4_UDF_CTRL_TCAM_VNTAG, 4325 BCMI_XGS4_UDF_CTRL_TCAM_ETAG, 4326 BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG, 4327 BCMI_XGS4_UDF_CTRL_INT_PKT, 4328 } 4329 }; 4330 4331 *data_f = hw_fields_f[0][type]; 4332 *mask_f = hw_fields_f[1][type]; 4333 *present = sw_flags[0][type]; 4334 *none = sw_flags[1][type]; 4335 *any = sw_flags[2][type]; 4336 *support = ctrl_flags[0][type]; 4337 4338 return BCM_E_NONE; 4339 } 4340 4341 /* 4342 * Function: 4343 * bcmi_xgs4_udf_tcam_entry_misc_parse 4344 * Purpose: 4345 * Parse udf tcam entry flags format match key. 4346 * Parameters: 4347 * unit - (IN) BCM device number. 4348 * hw_buf - (IN) Hw buffer. 4349 * flags - (OUT) BCM_PKT_FORMAT_F_XXX 4350 * Returns: 4351 * BCM_E_XXX 4352 */ 4353 STATIC int 4354 bcmi_xgs4_udf_tcam_entry_misc_parse(int unit, int type, 4355 uint32 *hw_buf, uint16 *flags) 4356 { 4357 int rv; 4358 soc_mem_t mem; 4359 uint32 data, mask; 4360 soc_field_t data_f, mask_f; 4361 int present, none, any, support; 4362 4363 /* Input parameters check. */ 4364 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4365 BCM_IF_NULL_RETURN_PARAM(flags); 4366 4367 mem = UDF_CTRL(unit)->tcam_mem; 4368 4369 rv = bcmi_xgs4_udf_tcam_misc_format_to_hw_fields(unit, type, 4370 &data_f, &mask_f, &present, &none, &any, &support); 4371 BCM_IF_ERROR_RETURN(rv); 4372 4373 /* If the field is not supported, return ANY */ 4374 if (!(UDF_CTRL(unit)->flags & support)) { 4375 *flags = any; 4376 return BCM_E_NONE; 4377 } 4378 4379 if (soc_mem_field32_get(unit, mem, hw_buf, mask_f)) { 4380 data = soc_mem_field32_get(unit, mem, hw_buf, data_f); 4381 mask = soc_mem_field32_get(unit, mem, hw_buf, mask_f); 4382 *flags |= ((mask == 0) ? any : ((data == 1) ? present : none)); 4383 } 4384 4385 return (BCM_E_NONE); 4386 } 4387 4388 /* 4389 * Function: 4390 * bcmi_xgs4_udf_tcam_entry_misc_init 4391 * Purpose: 4392 * Initialize udf tcam entry flags match key. 4393 * Parameters: 4394 * unit - (IN) BCM device number. 4395 * flags - (IN) BCM_PKT_FORMAT_F_XXX 4396 * hw_buf - (OUT) Hw buffer. 4397 * Returns: 4398 * BCM_E_XXX 4399 */ 4400 STATIC int 4401 bcmi_xgs4_udf_tcam_entry_misc_init(int unit, int type, 4402 uint16 flags, uint32 *hw_buf) 4403 { 4404 int rv; 4405 soc_mem_t mem; 4406 soc_field_t data_f, mask_f; 4407 int present, none, any, support; 4408 4409 4410 /* Input parameters check. */ 4411 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4412 4413 mem = UDF_CTRL(unit)->tcam_mem; 4414 4415 rv = bcmi_xgs4_udf_tcam_misc_format_to_hw_fields(unit, type, 4416 &data_f, &mask_f, &present, &none, &any, &support); 4417 BCM_IF_ERROR_RETURN(rv); 4418 4419 /* If the field is not supported, only ANY is allowed, 4420 * hw_buf should not be set */ 4421 if (!(UDF_CTRL(unit)->flags & support)) { 4422 if (flags != any) { 4423 return BCM_E_PARAM; 4424 } else { 4425 return BCM_E_NONE; 4426 } 4427 } 4428 4429 /* Both PRESENT and NONE flags cannot be set 4430 * If it is required to match on all packets, set ANY */ 4431 if ((flags & present) && (flags & none)) { 4432 return BCM_E_PARAM; 4433 } 4434 4435 if ((flags & present) || (flags & none)) { 4436 soc_mem_field32_set(unit, mem, hw_buf, mask_f, 1); 4437 soc_mem_field32_set(unit, mem, hw_buf, data_f, (flags & present) ? 1:0); 4438 } else { 4439 /* any */ 4440 soc_mem_field32_set(unit, mem, hw_buf, data_f, 0); 4441 soc_mem_field32_set(unit, mem, hw_buf, mask_f, 0); 4442 } 4443 4444 return BCM_E_NONE; 4445 4446 } 4447 4448 /* 4449 * Function: 4450 * bcmi_xgs4_udf_tcam_entry_l2format_init 4451 * Purpose: 4452 * Initialize udf tcam entry l2 format match key. 4453 * Parameters: 4454 * unit - (IN) BCM device number. 4455 * l2format - (IN) BCM_PKT_FORMAT_L2_XXX 4456 * hw_buf - (OUT) Hw buffer. 4457 * Returns: 4458 * BCM_E_XXX 4459 */ 4460 STATIC int 4461 bcmi_xgs4_udf_tcam_entry_l2format_init(int unit, 4462 bcm_udf_pkt_format_info_t *pkt_fmt, 4463 uint32 *hw_buf) 4464 { 4465 uint16 l2format = pkt_fmt->l2; 4466 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4467 4468 /* Input parameters check. */ 4469 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4470 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 4471 4472 /* Translate L2 flag bits to index */ 4473 switch (l2format) { 4474 case BCM_PKT_FORMAT_L2_ETH_II: 4475 /* L2 Format . */ 4476 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4477 L2_TYPEf, 0); 4478 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4479 L2_TYPE_MASKf, 0x3); 4480 4481 break; 4482 case BCM_PKT_FORMAT_L2_SNAP: 4483 /* L2 Format . */ 4484 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4485 L2_TYPEf, 1); 4486 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4487 L2_TYPE_MASKf, 0x3); 4488 4489 break; 4490 case BCM_PKT_FORMAT_L2_LLC: 4491 /* L2 Format . */ 4492 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4493 L2_TYPEf, 2); 4494 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4495 L2_TYPE_MASKf, 0x3); 4496 4497 break; 4498 case BCM_PKT_FORMAT_L2_ANY: 4499 /* L2 Format . */ 4500 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4501 L2_TYPEf, 0); 4502 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4503 L2_TYPE_MASKf, 0); 4504 break; 4505 default: 4506 return (BCM_E_PARAM); 4507 } 4508 return (BCM_E_NONE); 4509 } 4510 4511 /* 4512 * Function: 4513 * bcmi_xgs4_udf_tcam_entry_l2format_parse 4514 * Purpose: 4515 * Parse udf tcam entry l2 format match key. 4516 * Parameters: 4517 * unit - (IN) BCM device number. 4518 * hw_buf - (IN) Hw buffer. 4519 * l2format - (OUT) BCM_PKT_FORMAT_L2_XXX 4520 * Returns: 4521 * BCM_E_XXX 4522 */ 4523 STATIC int 4524 bcmi_xgs4_udf_tcam_entry_l2format_parse(int unit, uint32 *hw_buf, 4525 bcm_udf_pkt_format_info_t *pkt_fmt) 4526 { 4527 uint32 l2type; 4528 uint16 *l2format = &pkt_fmt->l2; 4529 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4530 4531 /* Input parameters check. */ 4532 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4533 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 4534 4535 if (soc_mem_field32_get(unit, tcam_mem, hw_buf, L2_TYPE_MASKf)) { 4536 l2type = soc_mem_field32_get(unit, tcam_mem, hw_buf, L2_TYPEf); 4537 switch (l2type) { 4538 case 0: 4539 *l2format = BCM_PKT_FORMAT_L2_ETH_II; 4540 break; 4541 case 1: 4542 *l2format = BCM_PKT_FORMAT_L2_SNAP; 4543 break; 4544 case 2: 4545 *l2format = BCM_PKT_FORMAT_L2_LLC; 4546 break; 4547 default: 4548 break; 4549 } 4550 } else { 4551 *l2format = BCM_PKT_FORMAT_L2_ANY; 4552 } 4553 return (BCM_E_NONE); 4554 } 4555 4556 /* 4557 * Function: 4558 * bcmi_xgs4_udf_tcam_entry_vlanformat_parse 4559 * Purpose: 4560 * Parse udf tcam entry l2 format match key. 4561 * Parameters: 4562 * unit - (IN) BCM device number. 4563 * hw_buf - (IN) Hw buffer. 4564 * vlanformat - (OUT) BCM_PKT_FORMAT_L2_XXX 4565 * Returns: 4566 * BCM_E_XXX 4567 */ 4568 STATIC int 4569 bcmi_xgs4_udf_tcam_entry_vlanformat_parse(int unit, uint32 *hw_buf, 4570 bcm_udf_pkt_format_info_t *pkt_fmt) 4571 { 4572 uint32 tag_status; 4573 uint16 *vlanformat = &pkt_fmt->vlan_tag; 4574 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4575 4576 /* Input parameters check. */ 4577 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4578 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 4579 4580 if (soc_mem_field32_get(unit, tcam_mem, hw_buf, L2_TAG_STATUS_MASKf)) { 4581 tag_status = soc_mem_field32_get(unit, tcam_mem, hw_buf, 4582 L2_TAG_STATUSf); 4583 switch (tag_status) { 4584 case 0: 4585 *vlanformat = BCM_PKT_FORMAT_VLAN_TAG_NONE; 4586 break; 4587 case 1: 4588 *vlanformat = BCM_PKT_FORMAT_VLAN_TAG_SINGLE; 4589 break; 4590 case 2: 4591 *vlanformat = BCM_PKT_FORMAT_VLAN_TAG_DOUBLE; 4592 break; 4593 default: 4594 break; 4595 } 4596 } else { 4597 *vlanformat = BCM_PKT_FORMAT_VLAN_TAG_ANY; 4598 } 4599 return (BCM_E_NONE); 4600 } 4601 4602 /* 4603 * Function: 4604 * bcmi_xgs4_udf_tcam_entry_vlanformat_init 4605 * Purpose: 4606 * Initialize udf tcam entry vlan tag format match key. 4607 * Parameters: 4608 * unit - (IN) BCM device number. 4609 * vlanformat - (IN) BCM_PKT_FORMAT_L2_XXX 4610 * hw_buf - (IN/OUT) Hw buffer. 4611 * Returns: 4612 * BCM_E_XXX 4613 */ 4614 STATIC int 4615 bcmi_xgs4_udf_tcam_entry_vlanformat_init(int unit, 4616 bcm_udf_pkt_format_info_t *pkt_fmt, 4617 uint32 *hw_buf) 4618 { 4619 uint16 vlanformat = pkt_fmt->vlan_tag; 4620 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4621 4622 /* Input parameters check. */ 4623 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4624 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 4625 4626 /* Translate L2 flag bits to index */ 4627 switch (vlanformat) { 4628 case BCM_PKT_FORMAT_VLAN_TAG_NONE: 4629 /* L2 Format . */ 4630 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4631 L2_TAG_STATUSf, 0); 4632 if (soc_feature(unit, soc_feature_fp_no_inner_vlan_support)) { 4633 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4634 L2_TAG_STATUS_MASKf, 0x1); 4635 } else { 4636 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4637 L2_TAG_STATUS_MASKf, 0x3); 4638 } 4639 4640 break; 4641 case BCM_PKT_FORMAT_VLAN_TAG_SINGLE: 4642 /* L2 Format . */ 4643 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4644 L2_TAG_STATUSf, 1); 4645 if (soc_feature(unit, soc_feature_fp_no_inner_vlan_support)) { 4646 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4647 L2_TAG_STATUS_MASKf, 0x1); 4648 } else { 4649 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4650 L2_TAG_STATUS_MASKf, 0x3); 4651 } 4652 4653 break; 4654 case BCM_PKT_FORMAT_VLAN_TAG_DOUBLE: 4655 if (soc_feature(unit, soc_feature_fp_no_inner_vlan_support)) { 4656 return (BCM_E_UNAVAIL); 4657 } else { 4658 /* L2 Format . */ 4659 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4660 L2_TAG_STATUSf, 2); 4661 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4662 L2_TAG_STATUS_MASKf, 0x3); 4663 } 4664 4665 break; 4666 case BCM_PKT_FORMAT_VLAN_TAG_ANY: 4667 /* L2 Format . */ 4668 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4669 L2_TAG_STATUSf, 0); 4670 soc_mem_field32_set(unit, tcam_mem, hw_buf, 4671 L2_TAG_STATUS_MASKf, 0); 4672 break; 4673 default: 4674 return (BCM_E_PARAM); 4675 } 4676 return (BCM_E_NONE); 4677 } 4678 4679 4680 /* 4681 * Function: 4682 * bcmi_xgs4_udf_tcam_entry_lb_pkt_type_parse 4683 * Purpose: 4684 * Parse udf tcam entry loopback pkt type match key. 4685 * Parameters: 4686 * unit - (IN) BCM device number. 4687 * hw_buf - (IN) Hw buffer. 4688 * lb_pkt_type - (OUT) BCM_PKT_FORMAT_LB_TYPE_XXX 4689 * Returns: 4690 * BCM_E_XXX 4691 */ 4692 STATIC int 4693 bcmi_xgs4_udf_tcam_entry_lb_pkt_type_parse(int unit, uint32 *hw_buf, 4694 bcm_udf_pkt_format_info_t *pkt_fmt) 4695 { 4696 uint32 type; 4697 uint8 *lb_pkt_type = &pkt_fmt->lb_pkt_type; 4698 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4699 4700 /* Input parameters check. */ 4701 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4702 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 4703 4704 if (soc_mem_field32_get(unit, tcam_mem, hw_buf, LOOPBACK_PKT_TYPE_MASKf)) { 4705 type = soc_mem_field32_get(unit, tcam_mem, hw_buf, 4706 LOOPBACK_PKT_TYPEf); 4707 switch (type) { 4708 case 1: 4709 if (SOC_IS_TOMAHAWK3(unit)) { 4710 *lb_pkt_type = BCM_PKT_FORMAT_LB_TYPE_GENERIC; 4711 } else { 4712 *lb_pkt_type = BCM_PKT_FORMAT_LB_TYPE_MIM; 4713 } 4714 break; 4715 default: 4716 break; 4717 } 4718 } else { 4719 *lb_pkt_type = BCM_PKT_FORMAT_LB_TYPE_ANY; 4720 } 4721 4722 return (BCM_E_NONE); 4723 } 4724 4725 /* 4726 * Function: 4727 * bcmi_xgs4_udf_tcam_entry_l4_dst_port_parse 4728 * Purpose: 4729 * Parse udf tcam entry loopback pkt type match key. 4730 * Parameters: 4731 * unit - (IN) BCM device number. 4732 * hw_buf - (IN) Hw buffer. 4733 * l4_dst_port - (OUT) BCM_PKT_FORMAT_LB_TYPE_XXX 4734 * Returns: 4735 * BCM_E_XXX 4736 */ 4737 STATIC int 4738 bcmi_xgs4_udf_tcam_entry_l4_dst_port_parse(int unit, uint32 *hw_buf, 4739 bcm_udf_pkt_format_info_t *pkt_fmt) 4740 { 4741 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4742 4743 /* Input parameters check. */ 4744 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4745 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 4746 4747 pkt_fmt->l4_dst_port = soc_mem_field32_get(unit, tcam_mem, hw_buf, 4748 L4_DST_PORTf); 4749 pkt_fmt->l4_dst_port_mask = soc_mem_field32_get(unit, tcam_mem, hw_buf, 4750 L4_DST_PORT_MASKf); 4751 4752 return (BCM_E_NONE); 4753 4754 } 4755 4756 /* 4757 * Function: 4758 * bcmi_xgs4_udf_tcam_entry_opaque_tag_type_parse 4759 * Purpose: 4760 * Parse udf tcam entry loopback pkt type match key. 4761 * Parameters: 4762 * unit - (IN) BCM device number. 4763 * hw_buf - (IN) Hw buffer. 4764 * opaque_tag_type - (OUT) BCM_PKT_FORMAT_LB_TYPE_XXX 4765 * Returns: 4766 * BCM_E_XXX 4767 */ 4768 STATIC int 4769 bcmi_xgs4_udf_tcam_entry_opaque_tag_type_parse(int unit, uint32 *hw_buf, 4770 bcm_udf_pkt_format_info_t *pkt_fmt) 4771 { 4772 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4773 4774 /* Input parameters check. */ 4775 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4776 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 4777 4778 4779 pkt_fmt->opaque_tag_type = soc_mem_field32_get(unit, tcam_mem, hw_buf, 4780 OPAQUE_TAG_TYPEf); 4781 pkt_fmt->opaque_tag_type_mask = soc_mem_field32_get(unit, tcam_mem, hw_buf, 4782 OPAQUE_TAG_TYPE_MASKf); 4783 4784 return (BCM_E_NONE); 4785 4786 } 4787 4788 /* 4789 * Function: 4790 * bcmi_xgs4_udf_tcam_entry_src_port_parse 4791 * Purpose: 4792 * Parse udf tcam entry loopback pkt type match key. 4793 * Parameters: 4794 * unit - (IN) BCM device number. 4795 * hw_buf - (IN) Hw buffer. 4796 * src_port - (OUT) BCM_PKT_FORMAT_LB_TYPE_XXX 4797 * Returns: 4798 * BCM_E_XXX 4799 */ 4800 STATIC int 4801 bcmi_xgs4_udf_tcam_entry_src_port_parse(int unit, uint32 *hw_buf, 4802 bcm_udf_pkt_format_info_t *pkt_fmt) 4803 { 4804 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4805 4806 /* Input parameters check. */ 4807 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4808 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 4809 4810 pkt_fmt->src_port = soc_mem_field32_get(unit, tcam_mem, hw_buf, 4811 SOURCE_PORT_NUMBERf); 4812 pkt_fmt->src_port_mask = soc_mem_field32_get(unit, tcam_mem, hw_buf, 4813 SOURCE_PORT_NUMBER_MASKf); 4814 4815 return (BCM_E_NONE); 4816 4817 4818 } 4819 4820 /* 4821 * Function: 4822 * bcmi_xgs4_udf_tcam_entry_parse 4823 * Purpose: 4824 * Parse udf tcam entry key to packet format info 4825 * Parameters: 4826 * unit - (IN) BCM device number. 4827 * hw_buf - (IN) Hw buffer. 4828 * pkt_fmt - (OUT) Packet format to be filled in. 4829 * Returns: 4830 * BCM_E_XXX 4831 */ 4832 4833 STATIC int 4834 bcmi_xgs4_udf_tcam_entry_parse(int unit, uint32 *hw_buf, 4835 bcm_udf_pkt_format_info_t *pkt_fmt) 4836 { 4837 int rv; 4838 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 4839 4840 /* Input parameters check. */ 4841 BCM_IF_NULL_RETURN_PARAM(hw_buf); 4842 4843 bcm_udf_pkt_format_info_t_init(pkt_fmt); 4844 4845 /* If entry not valid, return empty pkt_format. */ 4846 if (!soc_mem_field32_get(unit, tcam_mem, hw_buf, VALIDf)) { 4847 return (BCM_E_NONE); 4848 } 4849 4850 /* Parse vlan_tag format.*/ 4851 rv = bcmi_xgs4_udf_tcam_entry_vlanformat_parse(unit, hw_buf, pkt_fmt); 4852 BCM_IF_ERROR_RETURN(rv); 4853 4854 /* Parse l2 format.*/ 4855 rv = bcmi_xgs4_udf_tcam_entry_l2format_parse(unit, hw_buf, pkt_fmt); 4856 BCM_IF_ERROR_RETURN(rv); 4857 4858 /* Parse l3 fields.*/ 4859 rv = bcmi_xgs4_udf_tcam_entry_l3_parse(unit, hw_buf, pkt_fmt); 4860 BCM_IF_ERROR_RETURN(rv); 4861 4862 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_HIGIG) { 4863 rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatHigig, 4864 hw_buf, (uint16 *)&pkt_fmt->higig); 4865 BCM_IF_ERROR_RETURN(rv); 4866 } 4867 4868 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_VNTAG) { 4869 rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatVntag, 4870 hw_buf, (uint16 *)&pkt_fmt->vntag); 4871 BCM_IF_ERROR_RETURN(rv); 4872 } 4873 4874 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ETAG) { 4875 rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatEtag, 4876 hw_buf, (uint16 *)&pkt_fmt->etag); 4877 BCM_IF_ERROR_RETURN(rv); 4878 } 4879 4880 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_CNTAG) { 4881 rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatCntag, 4882 hw_buf, (uint16 *)&pkt_fmt->cntag); 4883 BCM_IF_ERROR_RETURN(rv); 4884 } 4885 4886 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ICNM) { 4887 rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatIcnm, 4888 hw_buf, (uint16 *)&pkt_fmt->icnm); 4889 BCM_IF_ERROR_RETURN(rv); 4890 } 4891 4892 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG) { 4893 rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatSubportTag, 4894 hw_buf, (uint16 *)&pkt_fmt->subport_tag); 4895 BCM_IF_ERROR_RETURN(rv); 4896 } 4897 4898 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_INT_PKT) { 4899 rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatIntPkt, 4900 hw_buf, (uint16 *)&pkt_fmt->int_pkt); 4901 BCM_IF_ERROR_RETURN(rv); 4902 } 4903 4904 /* Parse lb_pkt_type fields.*/ 4905 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_LB_PKT_TYPE) { 4906 rv = bcmi_xgs4_udf_tcam_entry_lb_pkt_type_parse(unit, hw_buf, pkt_fmt); 4907 BCM_IF_ERROR_RETURN(rv); 4908 } 4909 4910 /* Parse l4_dst_port fields.*/ 4911 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_L4_DST_PORT) { 4912 rv = bcmi_xgs4_udf_tcam_entry_l4_dst_port_parse(unit, hw_buf, pkt_fmt); 4913 BCM_IF_ERROR_RETURN(rv); 4914 } 4915 4916 /* Parse opaque_tag_type fields.*/ 4917 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_OPAQUE_TAG_TYPE) { 4918 rv = bcmi_xgs4_udf_tcam_entry_opaque_tag_type_parse(unit, hw_buf, pkt_fmt); 4919 BCM_IF_ERROR_RETURN(rv); 4920 } 4921 4922 /* Parse src_port fields.*/ 4923 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_SRC_PORT) { 4924 rv = bcmi_xgs4_udf_tcam_entry_src_port_parse(unit, hw_buf, pkt_fmt); 4925 BCM_IF_ERROR_RETURN(rv); 4926 } 4927 4928 return (BCM_E_NONE); 4929 } 4930 4931 /* Parse ethertype and mask from pkt_format to hw_buf */ 4932 STATIC int 4933 bcmi_xgs4_udf_tcam_ethertype_init(int unit, 4934 bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf) 4935 { 4936 soc_mem_t mem; 4937 bcm_ethertype_t ethertype; 4938 bcm_ethertype_t ethertype_mask; 4939 4940 mem = UDF_CTRL(unit)->tcam_mem; 4941 4942 if (pkt_format->ethertype_mask != 0) { 4943 ethertype = soc_mem_field32_get(unit, mem, 4944 hw_buf, L2_ETHER_TYPEf); 4945 ethertype_mask = soc_mem_field32_get(unit, mem, 4946 hw_buf, L2_ETHER_TYPE_MASKf); 4947 4948 if ((ethertype_mask != 0) && 4949 ((ethertype & ethertype_mask) != 4950 (pkt_format->ethertype & pkt_format->ethertype_mask))) { 4951 return BCM_E_CONFIG; 4952 } else { 4953 soc_mem_field32_set(unit, mem, hw_buf, 4954 L2_ETHER_TYPEf, pkt_format->ethertype); 4955 soc_mem_field32_set(unit, mem, hw_buf, 4956 L2_ETHER_TYPE_MASKf, pkt_format->ethertype_mask); 4957 } 4958 } 4959 4960 return BCM_E_NONE; 4961 } 4962 4963 /* Parse l4_dst_port and mask from pkt_format to hw_buf */ 4964 STATIC int 4965 bcmi_xgs4_udf_tcam_entry_l4_dst_port_init(int unit, 4966 bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf) 4967 { 4968 soc_mem_t mem; 4969 uint32 l4_dst_port; 4970 uint32 l4_dst_port_mask; 4971 4972 mem = UDF_CTRL(unit)->tcam_mem; 4973 4974 if (pkt_format->l4_dst_port_mask != 0) { 4975 l4_dst_port = soc_mem_field32_get(unit, mem, 4976 hw_buf, L4_DST_PORTf); 4977 l4_dst_port_mask = soc_mem_field32_get(unit, mem, 4978 hw_buf, L4_DST_PORT_MASKf); 4979 4980 if ((l4_dst_port_mask != 0) && 4981 ((l4_dst_port & l4_dst_port_mask) != 4982 (pkt_format->l4_dst_port & pkt_format->l4_dst_port_mask))) { 4983 return BCM_E_CONFIG; 4984 } else { 4985 soc_mem_field32_set(unit, mem, hw_buf, 4986 L4_DST_PORTf, pkt_format->l4_dst_port); 4987 soc_mem_field32_set(unit, mem, hw_buf, 4988 L4_DST_PORT_MASKf, pkt_format->l4_dst_port_mask); 4989 } 4990 } 4991 4992 return BCM_E_NONE; 4993 } 4994 4995 /* Parse opaque_tag_type and mask from pkt_format to hw_buf */ 4996 STATIC int 4997 bcmi_xgs4_udf_tcam_entry_opaque_tag_type_init(int unit, 4998 bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf) 4999 { 5000 soc_mem_t mem; 5001 uint8 opaque_tag_type; 5002 uint8 opaque_tag_type_mask; 5003 5004 mem = UDF_CTRL(unit)->tcam_mem; 5005 5006 if (pkt_format->opaque_tag_type_mask != 0) { 5007 opaque_tag_type = soc_mem_field32_get(unit, mem, 5008 hw_buf, OPAQUE_TAG_TYPEf); 5009 opaque_tag_type_mask = soc_mem_field32_get(unit, mem, 5010 hw_buf, OPAQUE_TAG_TYPE_MASKf); 5011 5012 if ((opaque_tag_type_mask != 0) && 5013 ((opaque_tag_type & opaque_tag_type_mask) != 5014 (pkt_format->opaque_tag_type & pkt_format->opaque_tag_type_mask))) { 5015 return BCM_E_CONFIG; 5016 } else { 5017 soc_mem_field32_set(unit, mem, hw_buf, 5018 OPAQUE_TAG_TYPEf, pkt_format->opaque_tag_type); 5019 soc_mem_field32_set(unit, mem, hw_buf, 5020 OPAQUE_TAG_TYPE_MASKf, pkt_format->opaque_tag_type_mask); 5021 } 5022 } 5023 5024 return BCM_E_NONE; 5025 } 5026 5027 /* Parse src_port and mask from pkt_format to hw_buf */ 5028 STATIC int 5029 bcmi_xgs4_udf_tcam_entry_src_port_init(int unit, 5030 bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf) 5031 { 5032 soc_mem_t mem; 5033 uint8 src_port; 5034 uint8 src_port_mask; 5035 5036 mem = UDF_CTRL(unit)->tcam_mem; 5037 5038 if (pkt_format->src_port_mask != 0) { 5039 src_port = soc_mem_field32_get(unit, mem, 5040 hw_buf, SOURCE_PORT_NUMBERf); 5041 src_port_mask = soc_mem_field32_get(unit, mem, 5042 hw_buf, SOURCE_PORT_NUMBER_MASKf); 5043 5044 if ((src_port_mask != 0) && 5045 ((src_port & src_port_mask) != 5046 (pkt_format->src_port & pkt_format->src_port_mask))) { 5047 return BCM_E_CONFIG; 5048 } else { 5049 soc_mem_field32_set(unit, mem, hw_buf, 5050 SOURCE_PORT_NUMBERf, pkt_format->src_port); 5051 soc_mem_field32_set(unit, mem, hw_buf, 5052 SOURCE_PORT_NUMBER_MASKf, pkt_format->src_port_mask); 5053 } 5054 } 5055 5056 return BCM_E_NONE; 5057 } 5058 5059 5060 /* 5061 * Function: 5062 * bcmi_xgs4_udf_tcam_entry_lb_pkt_type_init 5063 * Purpose: 5064 * Initialize udf tcam entry loopback packet type match key. 5065 * Parameters: 5066 * unit - (IN) BCM device number. 5067 * l2format - (IN) BCM_PKT_FORMAT_LB_TYPE_XXX 5068 * hw_buf - (OUT) Hw buffer. 5069 * Returns: 5070 * BCM_E_XXX 5071 */ 5072 STATIC int 5073 bcmi_xgs4_udf_tcam_entry_lb_pkt_type_init(int unit, 5074 bcm_udf_pkt_format_info_t *pkt_fmt, 5075 uint32 *hw_buf) 5076 { 5077 uint16 type = pkt_fmt->lb_pkt_type; 5078 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 5079 5080 /* Input parameters check. */ 5081 BCM_IF_NULL_RETURN_PARAM(hw_buf); 5082 BCM_IF_NULL_RETURN_PARAM(pkt_fmt); 5083 5084 /* Translate L2 flag bits to index */ 5085 switch (type) { 5086 case BCM_PKT_FORMAT_LB_TYPE_MIM: 5087 /* L2 Format . */ 5088 if (SOC_IS_TOMAHAWK3(unit)) { 5089 return (BCM_E_PARAM); 5090 } else { 5091 soc_mem_field32_set(unit, tcam_mem, hw_buf, 5092 LOOPBACK_PKT_TYPEf, 1); 5093 soc_mem_field32_set(unit, tcam_mem, hw_buf, 5094 LOOPBACK_PKT_TYPE_MASKf, 0x3); 5095 } 5096 break; 5097 case BCM_PKT_FORMAT_LB_TYPE_GENERIC: 5098 /* L2 Format . */ 5099 if (SOC_IS_TOMAHAWK3(unit)) { 5100 soc_mem_field32_set(unit, tcam_mem, hw_buf, 5101 LOOPBACK_PKT_TYPEf, 1); 5102 soc_mem_field32_set(unit, tcam_mem, hw_buf, 5103 LOOPBACK_PKT_TYPE_MASKf, 0x3); 5104 } else { 5105 return (BCM_E_PARAM); 5106 } 5107 break; 5108 case BCM_PKT_FORMAT_LB_TYPE_ANY: 5109 soc_mem_field32_set(unit, tcam_mem, hw_buf, 5110 LOOPBACK_PKT_TYPEf, 0); 5111 soc_mem_field32_set(unit, tcam_mem, hw_buf, 5112 LOOPBACK_PKT_TYPE_MASKf, 0); 5113 5114 break; 5115 default: 5116 return (BCM_E_PARAM); 5117 } 5118 return (BCM_E_NONE); 5119 } 5120 5121 /* 5122 * Function: 5123 * _field_trx2_data_qualifier_etype_tcam_key_init 5124 * Purpose: 5125 * Initialize ethertype based udf tcam entry. 5126 * Parameters: 5127 * unit - (IN) bcm device. 5128 * pkt_format - (IN) Packet format info 5129 * hw_buf - (OUT) Hardware buffer. 5130 * Returns: 5131 * BCM_E_XXX 5132 */ 5133 STATIC int 5134 bcmi_xgs4_udf_pkt_format_tcam_key_init(int unit, 5135 bcm_udf_pkt_format_info_t *pkt_format, 5136 uint32 *hw_buf) 5137 { 5138 int rv; 5139 soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem; /* UDF_TCAM memory */ 5140 5141 /* Input parameters check. */ 5142 BCM_IF_NULL_RETURN_PARAM(hw_buf); 5143 BCM_IF_NULL_RETURN_PARAM(pkt_format); 5144 5145 /* Set valid bit. */ 5146 soc_mem_field32_set(unit, tcam_mem, hw_buf, VALIDf, 1); 5147 5148 /* Set l2 format. */ 5149 rv = bcmi_xgs4_udf_tcam_entry_l2format_init(unit, pkt_format, hw_buf); 5150 BCM_IF_ERROR_RETURN(rv); 5151 5152 /* Set vlan tag format. */ 5153 rv = bcmi_xgs4_udf_tcam_entry_vlanformat_init(unit, pkt_format, hw_buf); 5154 BCM_IF_ERROR_RETURN(rv); 5155 5156 /* Set l3 packet format. */ 5157 rv = bcmi_xgs4_udf_tcam_entry_l3_init(unit, pkt_format, hw_buf); 5158 BCM_IF_ERROR_RETURN(rv); 5159 5160 /* Set HiGig packet formats */ 5161 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_HIGIG) { 5162 rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatHigig, 5163 pkt_format->higig, hw_buf); 5164 BCM_IF_ERROR_RETURN(rv); 5165 } 5166 5167 /* Set VNTAG packet formats */ 5168 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_VNTAG) { 5169 rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatVntag, 5170 pkt_format->vntag, hw_buf); 5171 BCM_IF_ERROR_RETURN(rv); 5172 } 5173 5174 /* Set ETAG packet formats */ 5175 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ETAG) { 5176 rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatEtag, 5177 pkt_format->etag, hw_buf); 5178 BCM_IF_ERROR_RETURN(rv); 5179 } 5180 5181 /* Set CNTAG packet formats */ 5182 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_CNTAG) { 5183 rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatCntag, 5184 pkt_format->cntag, hw_buf); 5185 BCM_IF_ERROR_RETURN(rv); 5186 } 5187 5188 /* Set ICNM packet formats */ 5189 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ICNM) { 5190 rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatIcnm, 5191 pkt_format->icnm, hw_buf); 5192 BCM_IF_ERROR_RETURN(rv); 5193 } 5194 5195 /* Set Subport tag packet formats */ 5196 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG) { 5197 rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatSubportTag, 5198 pkt_format->subport_tag, hw_buf); 5199 BCM_IF_ERROR_RETURN(rv); 5200 } 5201 5202 /* Set Inband Telemetry Pkt packet formats */ 5203 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_INT_PKT) { 5204 rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatIntPkt, 5205 pkt_format->int_pkt, hw_buf); 5206 BCM_IF_ERROR_RETURN(rv); 5207 } 5208 5209 /* Set L4 Dst Port packet formats */ 5210 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_L4_DST_PORT) { 5211 rv = bcmi_xgs4_udf_tcam_entry_l4_dst_port_init(unit, pkt_format, hw_buf); 5212 BCM_IF_ERROR_RETURN(rv); 5213 } 5214 5215 /* Set Opaque Tag Type packet formats */ 5216 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_OPAQUE_TAG_TYPE) { 5217 rv = bcmi_xgs4_udf_tcam_entry_opaque_tag_type_init(unit, pkt_format, hw_buf); 5218 BCM_IF_ERROR_RETURN(rv); 5219 } 5220 5221 5222 /* Set Source Port packet formats */ 5223 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_SRC_PORT) { 5224 rv = bcmi_xgs4_udf_tcam_entry_src_port_init(unit, pkt_format, hw_buf); 5225 BCM_IF_ERROR_RETURN(rv); 5226 } 5227 5228 /* Set Loopback Packet Type packet formats */ 5229 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_LB_PKT_TYPE) { 5230 rv = bcmi_xgs4_udf_tcam_entry_lb_pkt_type_init(unit, pkt_format, hw_buf); 5231 BCM_IF_ERROR_RETURN(rv); 5232 } 5233 5234 5235 rv = bcmi_xgs4_udf_tcam_ethertype_init(unit, pkt_format, hw_buf); 5236 BCM_IF_ERROR_RETURN(rv); 5237 5238 return (rv); 5239 } 5240 5241 /* 5242 * Function: 5243 * bcmi_xgs4_udf_offset_node_get 5244 * Purpose: 5245 * Fetches UDF offset node given udf id. 5246 * Parameters: 5247 * unit - (IN) Unit number. 5248 * udf_id - (IN) UDF Id. 5249 * offset_info - (INOUT) Fecthed udf offset info. 5250 * Returns: 5251 * BCM_E_XXX 5252 * Notes: 5253 */ 5254 int 5255 bcmi_xgs4_udf_offset_node_get(int unit, bcm_udf_id_t udf_id, 5256 bcmi_xgs4_udf_offset_info_t **cur) 5257 { 5258 bcmi_xgs4_udf_offset_info_t *tmp; 5259 5260 tmp = UDF_CTRL(unit)->offset_info_head; 5261 5262 while (tmp != NULL) { 5263 if (tmp->udf_id == udf_id) { 5264 break; 5265 } 5266 tmp = tmp->next; 5267 } 5268 5269 /* Reached end of the list */ 5270 if (tmp == NULL) { 5271 *cur = NULL; 5272 return BCM_E_NOT_FOUND; 5273 } 5274 5275 *cur = tmp; 5276 5277 return BCM_E_NONE; 5278 } 5279 5280 5281 /* 5282 * Function: 5283 * bcmi_xgs4_udf_tcam_node_get 5284 * Purpose: 5285 * Fetches UDF tcam node given packet format id. 5286 * Parameters: 5287 * unit - (IN) Unit number. 5288 * pkt_format_id - (IN) UDF Packet format Id. 5289 * offset_info - (INOUT) Fecthed udf tcam info. 5290 * Returns: 5291 * BCM_E_XXX 5292 * Notes: 5293 */ 5294 int 5295 bcmi_xgs4_udf_tcam_node_get(int unit, 5296 bcm_udf_pkt_format_id_t pkt_format_id, 5297 bcmi_xgs4_udf_tcam_info_t **cur) 5298 { 5299 bcmi_xgs4_udf_tcam_info_t *tmp; 5300 5301 tmp = UDF_CTRL(unit)->tcam_info_head; 5302 5303 while (tmp != NULL) { 5304 if (tmp->pkt_format_id == pkt_format_id) { 5305 break; 5306 } 5307 tmp = tmp->next; 5308 } 5309 5310 /* Reached end of the list */ 5311 if (tmp == NULL) { 5312 *cur = NULL; 5313 return BCM_E_NOT_FOUND; 5314 } 5315 5316 *cur = tmp; 5317 5318 return BCM_E_NONE; 5319 } 5320 5321 /* 5322 * Function: 5323 * bcmi_xgs4_udf_detach 5324 * Purpose: 5325 * Detaches udf module and cleans software state. 5326 * Parameters: 5327 * unit - (IN) Unit number. 5328 * Returns: 5329 * BCM_E_XXX 5330 * Notes: 5331 */ 5332 int 5333 bcmi_xgs4_udf_detach(int unit) 5334 { 5335 UDF_INIT_CHECK(unit); 5336 5337 /* Free resources related to UDF module */ 5338 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_ctrl_free(unit, UDF_CTRL(unit))); 5339 5340 /* Reset udf module init state */ 5341 5342 return BCM_E_NONE; 5343 } 5344 5345 /* 5346 * Function: 5347 * bcmi_xgs4_udf_init 5348 * Purpose: 5349 * initializes/ReInitializes the UDF module. 5350 * Parameters: 5351 * unit - (IN) Unit number. 5352 * Returns: 5353 * BCM_E_XXX 5354 * Notes: 5355 */ 5356 int 5357 bcmi_xgs4_udf_init(int unit) 5358 { 5359 int rv; 5360 5361 #if defined (BCM_TOMAHAWK_SUPPORT) 5362 if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) { 5363 bcmi_xgs4_udf_oper_mode[unit] = bcmUdfOperModeGlobal; 5364 } 5365 #endif 5366 5367 /* Init control structures */ 5368 rv = bcmi_xgs4_udf_ctrl_init(unit); 5369 BCM_IF_ERROR_RETURN(rv); 5370 5371 #if defined (BCM_WARM_BOOT_SUPPORT) 5372 if (SOC_WARM_BOOT(unit)) { 5373 rv = bcmi_xgs4_udf_reinit(unit); 5374 BCM_IF_ERROR_RETURN(rv); 5375 } else 5376 #endif /* BCM_WARM_BOOT_SUPPORT */ 5377 { 5378 rv = bcmi_xgs4_udf_hw_init(unit); 5379 BCM_IF_ERROR_RETURN(rv); 5380 5381 #if defined (BCM_WARM_BOOT_SUPPORT) 5382 rv = bcmi_xgs4_udf_wb_alloc(unit); 5383 BCM_IF_ERROR_RETURN(rv); 5384 #endif /* BCM_WARM_BOOT_SUPPORT */ 5385 5386 } 5387 5388 return BCM_E_NONE; 5389 } 5390 5391 /* To sanitize udf_info/pkt_format_info input structures */ 5392 STATIC int 5393 bcmi_xgs4_udf_sanitize_inputs(int unit, bcm_udf_t *udf_info, 5394 bcm_udf_alloc_hints_t *hints, 5395 bcm_udf_pkt_format_info_t *pkt_format) 5396 { 5397 #if defined (BCM_TOMAHAWK_SUPPORT) 5398 int port_count = 0, port = 0, first_pipe = BCMI_XGS4_UDF_INVALID_PIPE_NUM; 5399 soc_info_t *si; 5400 si = &SOC_INFO(unit); 5401 #endif 5402 5403 if (udf_info != NULL) { 5404 5405 /* start and width should be at byte boundary */ 5406 if (((udf_info->start % 8) != 0) || ((udf_info->width % 8) != 0)) { 5407 return BCM_E_PARAM; 5408 } 5409 5410 /* start and width should be less than max byte selection */ 5411 if (BITS2BYTES(udf_info->start + udf_info->width) > 5412 UDF_CTRL(unit)->max_parse_bytes) { 5413 return BCM_E_PARAM; 5414 } 5415 5416 /* flags in udf_info is currently not used; must be 0 */ 5417 if (udf_info->flags != 0) { 5418 return BCM_E_PARAM; 5419 } 5420 5421 /* check if layer is in known range */ 5422 if ((udf_info->layer < bcmUdfLayerL2Header) || 5423 (udf_info->layer >= bcmUdfLayerCount)) { 5424 return BCM_E_PARAM; 5425 } 5426 5427 5428 if (udf_info->layer == bcmUdfLayerUserPayload) { 5429 return BCM_E_PARAM; 5430 } 5431 5432 #if defined (BCM_TOMAHAWK_SUPPORT) 5433 /* get the pipe where the entry will be configured */ 5434 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 5435 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 5436 5437 BCM_PBMP_COUNT(udf_info->ports, port_count); 5438 if (port_count == 0) { 5439 return BCM_E_PARAM; 5440 } 5441 5442 SOC_PBMP_ITER(udf_info->ports, port) { 5443 if (first_pipe == BCMI_XGS4_UDF_INVALID_PIPE_NUM ) { 5444 first_pipe = si->port_pipe[port]; 5445 } else if (first_pipe != si->port_pipe[port]) { 5446 return BCM_E_PARAM; 5447 } 5448 } 5449 } 5450 #endif 5451 } 5452 5453 if (hints != NULL) { 5454 /* check if chip support flex hash */ 5455 if ((hints->flags & BCM_UDF_CREATE_O_FLEXHASH) && 5456 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_FLEXHASH))) { 5457 return BCM_E_PARAM; 5458 } 5459 /* check if chip support policer group */ 5460 if ((hints->flags & BCM_UDF_CREATE_O_POLICER_GROUP) && 5461 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_POLICER_GROUP))) { 5462 return BCM_E_PARAM; 5463 } 5464 /* check if chip support udf hash */ 5465 if ((hints->flags & BCM_UDF_CREATE_O_UDFHASH) && 5466 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_UDFHASH))) { 5467 return BCM_E_PARAM; 5468 } 5469 /* check create udf if withid is used together with replace*/ 5470 if (((hints->flags & BCM_UDF_CREATE_O_WITHID) && 5471 !(hints->flags & BCM_UDF_CREATE_O_REPLACE)) || 5472 (!(hints->flags & BCM_UDF_CREATE_O_WITHID) && 5473 (hints->flags & BCM_UDF_CREATE_O_REPLACE))) { 5474 return BCM_E_PARAM; 5475 } 5476 /* shared udf id should be valid */ 5477 if ((hints->flags & BCM_UDF_CREATE_O_SHARED_HWID) && 5478 ((hints->shared_udf < BCMI_XGS4_UDF_ID_MIN) || 5479 (hints->shared_udf > BCMI_XGS4_UDF_ID_MAX))) { 5480 return BCM_E_PARAM; 5481 } 5482 /* check if chip supports Range Check */ 5483 if ((hints->flags & BCM_UDF_CREATE_O_RANGE_CHECK) && 5484 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_RANGE_CHECK))) { 5485 return BCM_E_PARAM; 5486 } 5487 /* check if chip support flex counter */ 5488 if ((hints->flags & BCM_UDF_CREATE_O_FLEX_COUNTER) && 5489 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_FLEX_COUNTER))) { 5490 return BCM_E_PARAM; 5491 } 5492 } 5493 5494 if (pkt_format != NULL) { 5495 5496 if ((pkt_format->prio < 0) || (pkt_format->prio > 0xffff)) { 5497 /* Soft restriction - prio maintained as 'short' integer */ 5498 return BCM_E_PARAM; 5499 } 5500 if ((!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_HIGIG) && 5501 (pkt_format->higig > 0)) || 5502 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_VNTAG) && 5503 (pkt_format->vntag > 0)) || 5504 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ETAG) && 5505 (pkt_format->etag > 0)) || 5506 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ICNM) && 5507 (pkt_format->icnm > 0)) || 5508 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_CNTAG) && 5509 (pkt_format->cntag > 0)) || 5510 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG) && 5511 (pkt_format->subport_tag > 0)) || 5512 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_L4_DST_PORT) && 5513 (pkt_format->l4_dst_port > 0)) || 5514 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_OPAQUE_TAG_TYPE) && 5515 (pkt_format->opaque_tag_type > 0)) || 5516 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_INT_PKT) && 5517 (pkt_format->int_pkt > 0)) || 5518 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_SRC_PORT) && 5519 (pkt_format->src_port > 0)) || 5520 (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_LB_PKT_TYPE) && 5521 (pkt_format->lb_pkt_type > 0))) { 5522 return BCM_E_UNAVAIL; 5523 } 5524 #if defined (BCM_TOMAHAWK_SUPPORT) 5525 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) { 5526 if ((pkt_format->class_id < 0) || (pkt_format->class_id > 255)) { 5527 return BCM_E_PARAM; 5528 } 5529 } 5530 #endif 5531 } 5532 5533 return BCM_E_NONE; 5534 } 5535 5536 /* 5537 * Function: 5538 * bcm_udf_create 5539 * Purpose: 5540 * Creates a UDF object 5541 * Parameters: 5542 * unit - (IN) Unit number. 5543 * hints - (IN) Hints to UDF allocator 5544 * udf_info - (IN) UDF structure 5545 * udf_id - (IN/OUT) UDF ID 5546 * Returns: 5547 * BCM_E_NONE UDF created successfully. 5548 * BCM_E_EXISTS Entry already exists. 5549 * BCM_E_FULL UDF table full. 5550 * BCM_E_UNIT Invalid BCM Unit number. 5551 * BCM_E_INIT UDF module not initialized. 5552 * BCM_E_UNAVAIL Feature not supported. 5553 * BCM_E_XXX Standard error code. 5554 * Notes: 5555 */ 5556 int 5557 bcmi_xgs4_udf_create( 5558 int unit, 5559 bcm_udf_alloc_hints_t *hints, 5560 bcm_udf_t *udf_info, 5561 bcm_udf_id_t *udf_id) 5562 { 5563 int i; 5564 int gran; 5565 int max_chunks; 5566 int id_running_allocated = 0; 5567 int rv = BCM_E_NONE; 5568 bcmi_xgs4_udf_offset_info_t *offset_del = NULL; 5569 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 5570 bcmi_xgs4_udf_offset_entry_t *offset_entry_array; 5571 uint32 offset[MAX_UDF_OFFSET_CHUNKS] = {0}; 5572 5573 /* UDF Module Init check */ 5574 UDF_INIT_CHECK(unit); 5575 5576 /* NULL check; hints can be NULL */ 5577 BCM_IF_NULL_RETURN_PARAM(udf_id); 5578 BCM_IF_NULL_RETURN_PARAM(udf_info); 5579 5580 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 5581 5582 /* Sanitize input parameters */ 5583 rv = bcmi_xgs4_udf_sanitize_inputs(unit, udf_info, hints, NULL); 5584 BCM_IF_ERROR_RETURN(rv); 5585 5586 /* UDF Module Lock */ 5587 UDF_LOCK(unit); 5588 5589 if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_FIELD_MODULE) { 5590 LOG_CLI((BSL_META("Udf resource is used by FIELD module. \n"))); 5591 UDF_UNLOCK(unit); 5592 return BCM_E_RESOURCE; 5593 } 5594 5595 max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); 5596 5597 /* Check if similar entry already existing */ 5598 if ((hints != NULL) && (hints->flags & BCM_UDF_CREATE_O_WITHID)) { 5599 5600 UDF_ID_VALIDATE_UNLOCK(unit, *udf_id); 5601 5602 /* Fetch the udf offset info; get should be successful */ 5603 rv = bcmi_xgs4_udf_offset_node_get(unit, *udf_id, &offset_info); 5604 5605 if ((BCM_FAILURE(rv)) || (offset_info == NULL)) { 5606 UDF_UNLOCK(unit); 5607 return BCM_E_NOT_FOUND; 5608 } 5609 5610 if ((hints->flags & BCM_UDF_CREATE_O_REPLACE)) { 5611 if (offset_info->num_pkt_formats >= 1) { 5612 /* UDF already in use */ 5613 UDF_UNLOCK(unit); 5614 return BCM_E_CONFIG; 5615 } 5616 5617 for (i = 0; i < max_chunks; i++) { 5618 SHR_BITCOPY_RANGE(&offset[i], 0, &(offset_info->byte_bmap), 5619 i*gran, gran); 5620 } 5621 5622 /* unreserve the offset chunks */ 5623 rv = bcmi_xgs4_udf_offset_unreserve(unit, max_chunks, (int *)offset, 5624 offset_info->associated_pipe); 5625 if (BCM_FAILURE(rv)) { 5626 UDF_UNLOCK(unit); 5627 return rv; 5628 } 5629 5630 /* Delete the UDF entry and recreate one */ 5631 rv = bcmi_xgs4_udf_offset_node_delete(unit, *udf_id, &offset_del); 5632 if (BCM_FAILURE(rv)) { 5633 UDF_UNLOCK(unit); 5634 return rv; 5635 } 5636 } else { 5637 UDF_UNLOCK(unit); 5638 return BCM_E_PARAM; 5639 } 5640 } else { 5641 /* Fresh udf creation */ 5642 5643 /* Allocate udf id */ 5644 rv = bcmi_xgs4_udf_id_running_id_alloc(unit, bcmiUdfObjectUdf, udf_id); 5645 if (BCM_FAILURE(rv)) { 5646 UDF_UNLOCK(unit); 5647 return rv; 5648 } else { 5649 id_running_allocated = 1; 5650 } 5651 } 5652 5653 /* Add udf info structure to linked list */ 5654 rv = bcmi_xgs4_udf_offset_info_add(unit, udf_info, &offset_info); 5655 if ((BCM_FAILURE(rv)) || (offset_info == NULL)) { 5656 UDF_UNLOCK(unit); 5657 return BCM_E_MEMORY; 5658 } 5659 5660 if ((UDF_CTRL(unit)->num_udfs + 1) == UDF_CTRL(unit)->max_udfs) { 5661 rv = BCM_E_RESOURCE; 5662 } 5663 UDF_IF_ERROR_CLEANUP(rv); 5664 5665 offset_entry_array = UDF_CTRL(unit)->offset_entry_array; 5666 #if defined (BCM_TOMAHAWK_SUPPORT) 5667 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 5668 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 5669 offset_entry_array = 5670 UDF_CTRL(unit)->offset_entry_array_per_pipe[offset_info->associated_pipe]; 5671 } 5672 #endif 5673 5674 /* For shared hwid, just copy the hw details */ 5675 if ((hints != NULL) && (hints->flags & BCM_UDF_CREATE_O_SHARED_HWID)) { 5676 bcmi_xgs4_udf_offset_info_t *offset_shared; 5677 5678 rv = bcmi_xgs4_udf_offset_node_get(unit, hints->shared_udf, 5679 &offset_shared); 5680 UDF_IF_ERROR_CLEANUP(rv); 5681 5682 /* A shared udf should also should use the same width */ 5683 if (offset_info->width != offset_shared->width) { 5684 rv = BCM_E_CONFIG; 5685 } 5686 5687 /* Shared offset should 'start' at the same byte boundary 5688 * Otherwise the chunks allocated may not suffice the requirement 5689 */ 5690 if ((offset_info->start % gran) != (offset_shared->start % gran)) { 5691 rv = BCM_E_CONFIG; 5692 } 5693 5694 /* In Old devices with gran 4, if base offset is packet start 5695 * then extra check is need for layer also as bcmUdfLayerL2Header 5696 * have negative offset adjustment of 2 */ 5697 if (gran == UDF_OFFSET_GRAN4) { 5698 if (offset_info->start == bcmUdfLayerL2Header) { 5699 if (offset_shared->start != bcmUdfLayerL2Header) { 5700 rv = BCM_E_CONFIG; 5701 } 5702 } else { 5703 if(offset_shared->start == bcmUdfLayerL2Header) { 5704 rv = BCM_E_CONFIG; 5705 } 5706 } 5707 } 5708 5709 UDF_IF_ERROR_CLEANUP(rv); 5710 5711 /* Since shared, copy the same chunk bitmap */ 5712 offset_info->grp_id = offset_shared->grp_id; 5713 offset_info->hw_bmap = offset_shared->hw_bmap; 5714 offset_info->byte_bmap = offset_shared->byte_bmap; 5715 offset_info->byte_offset = offset_shared->byte_offset; 5716 5717 offset_info->flags |= BCMI_XGS4_UDF_OFFSET_INFO_SHARED; 5718 offset_shared->flags |= BCMI_XGS4_UDF_OFFSET_INFO_SHARED; 5719 5720 /* Mark the entry as shared */ 5721 for (i = 0; i < max_chunks; i ++) { 5722 if (SHR_BITGET(&(offset_info->hw_bmap), i)) { 5723 offset_entry_array[i].grp_id = offset_info->grp_id; 5724 offset_entry_array[i].num_udfs += 1; 5725 offset_entry_array[i].flags |= 5726 BCMI_XGS4_UDF_OFFSET_ENTRY_SHARED; 5727 } 5728 } 5729 } else { 5730 5731 /* allocate udf chunks */ 5732 rv = bcmi_xgs4_udf_offset_hw_alloc(unit, hints, offset_info); 5733 UDF_IF_ERROR_CLEANUP(rv); 5734 5735 } 5736 5737 /* update udf_id in the offset_info */ 5738 offset_info->udf_id = *udf_id; 5739 5740 if (hints != NULL) { 5741 if (hints->flags & BCM_UDF_CREATE_O_FLEXHASH) { 5742 offset_info->flags |= BCMI_XGS4_UDF_OFFSET_FLEXHASH; 5743 } 5744 if (hints->flags & BCM_UDF_CREATE_O_FIELD_INGRESS) { 5745 offset_info->flags |= BCMI_XGS4_UDF_OFFSET_IFP; 5746 } 5747 if (hints->flags & BCM_UDF_CREATE_O_FIELD_LOOKUP) { 5748 offset_info->flags |= BCMI_XGS4_UDF_OFFSET_VFP; 5749 } 5750 if (hints->flags & BCM_UDF_CREATE_O_POLICER_GROUP) { 5751 offset_info->flags |= BCMI_XGS4_UDF_OFFSET_POLICER; 5752 } 5753 if (hints->flags & BCM_UDF_CREATE_O_UDFHASH) { 5754 offset_info->flags |= BCMI_XGS4_UDF_OFFSET_UDFHASH; 5755 } 5756 if (hints->flags & BCM_UDF_CREATE_O_RANGE_CHECK) { 5757 offset_info->flags |= BCMI_XGS4_UDF_OFFSET_RANGE_CHECK; 5758 } 5759 } 5760 5761 /* Increment num udfs */ 5762 if ((hints != NULL) && !(hints->flags & BCM_UDF_CREATE_O_REPLACE)) { 5763 UDF_CTRL(unit)->num_udfs += 1; 5764 } 5765 5766 UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_UDF_MODULE; 5767 5768 cleanup: 5769 5770 5771 if (BCM_FAILURE(rv)) { 5772 5773 if ((id_running_allocated == 1) && 5774 (UDF_CTRL(unit)->udf_id_running != BCMI_XGS4_UDF_ID_MAX)) { 5775 /* Decrement the running udf id */ 5776 UDF_CTRL(unit)->udf_id_running -= 1; 5777 } 5778 5779 /* Delete the offset node */ 5780 if (offset_info != NULL) { 5781 UDF_UNLINK_OFFSET_NODE(offset_info); 5782 sal_free(offset_info); 5783 } 5784 } 5785 5786 /* Release UDF mutex */ 5787 UDF_UNLOCK(unit); 5788 5789 5790 return rv; 5791 } 5792 5793 /* 5794 * Function: 5795 * bcm_udf_pkt_format_create 5796 * Purpose: 5797 * Create a packet format entry 5798 * Parameters: 5799 * unit - (IN) Unit number. 5800 * options - (IN) API Options. 5801 * pkt_format - (IN) UDF packet format info structure 5802 * pkt_format_id - (OUT) Packet format ID 5803 * Returns: 5804 * BCM_E_NONE UDF packet format entry created 5805 * successfully. 5806 * BCM_E_UNIT Invalid BCM Unit number. 5807 * BCM_E_INIT UDF module not initialized. 5808 * BCM_E_UNAVAIL Feature not supported. 5809 * BCM_E_XXX Standard error code. 5810 * Notes: 5811 */ 5812 int 5813 bcmi_xgs4_udf_pkt_format_create( 5814 int unit, 5815 bcm_udf_pkt_format_options_t options, 5816 bcm_udf_pkt_format_info_t *pkt_format_info, 5817 bcm_udf_pkt_format_id_t *pkt_format_id) 5818 { 5819 int id_running_allocated = 0; 5820 bcmi_xgs4_udf_tcam_info_t *tcam_info_match = NULL; 5821 bcmi_xgs4_udf_tcam_info_t *tcam_info_local = NULL; 5822 5823 int rv = BCM_E_NONE; 5824 5825 /* UDF Module Init check */ 5826 UDF_INIT_CHECK(unit); 5827 5828 5829 /* Input parameters check. */ 5830 BCM_IF_NULL_RETURN_PARAM(pkt_format_id); 5831 BCM_IF_NULL_RETURN_PARAM(pkt_format_info); 5832 5833 /* Sanitize input parameters */ 5834 rv = bcmi_xgs4_udf_sanitize_inputs(unit, NULL, NULL, pkt_format_info); 5835 BCM_IF_ERROR_RETURN(rv); 5836 5837 /* UDF Module Lock */ 5838 UDF_LOCK(unit); 5839 5840 /* Check if similar entry already existing */ 5841 if (options & BCM_UDF_PKT_FORMAT_CREATE_O_WITHID) { 5842 5843 UDF_PKT_FORMAT_ID_VALIDATE_UNLOCK(unit, *pkt_format_id); 5844 5845 /* Fetch the tcam info; get should be successful */ 5846 rv = bcmi_xgs4_udf_tcam_node_get(unit, *pkt_format_id, 5847 &tcam_info_local); 5848 5849 if (BCM_FAILURE(rv)) { 5850 UDF_UNLOCK(unit); 5851 return rv; 5852 } 5853 5854 if ((options & BCM_UDF_PKT_FORMAT_CREATE_O_REPLACE)) { 5855 if (tcam_info_local->num_udfs >= 1) { 5856 /* UDF Pkt format entry already in use */ 5857 UDF_UNLOCK(unit); 5858 return BCM_E_CONFIG; 5859 } 5860 /* Delete the UDF pkt format entry and recreate one */ 5861 rv = bcmi_xgs4_udf_tcam_node_delete(unit, *pkt_format_id, 5862 &tcam_info_match); 5863 if (BCM_FAILURE(rv)) { 5864 UDF_UNLOCK(unit); 5865 return rv; 5866 } 5867 5868 /* Free tcam node */ 5869 sal_free(tcam_info_match); 5870 } 5871 } else { 5872 5873 /* Allocate new id */ 5874 rv = bcmi_xgs4_udf_id_running_id_alloc(unit, bcmiUdfObjectPktFormat, 5875 pkt_format_id); 5876 if (BCM_FAILURE(rv)) { 5877 UDF_UNLOCK(unit); 5878 return rv; 5879 } else { 5880 id_running_allocated = 1; 5881 } 5882 } 5883 5884 /* Insert the packet format entry in the linked list */ 5885 rv = bcmi_xgs4_udf_tcam_info_add(unit, pkt_format_info, &tcam_info_local); 5886 UDF_IF_ERROR_CLEANUP(rv); 5887 5888 if ((UDF_CTRL(unit)->num_pkt_formats + 1) == 5889 BCMI_XGS4_UDF_CTRL_MAX_UDF_ENTRIES(unit)) { 5890 rv = BCM_E_RESOURCE; 5891 } 5892 UDF_IF_ERROR_CLEANUP(rv); 5893 5894 5895 /* 5896 * The packet format matching hardware is a tcam and hence 5897 * there is no point in allowing to create more than one entry 5898 * of similar configuration. Search for a matching entry in 5899 * list of already installed objects and return error appropriately. 5900 */ 5901 5902 rv = bcmi_xgs4_udf_tcam_entry_match(unit, 5903 tcam_info_local, &tcam_info_match); 5904 if (BCM_SUCCESS(rv)) { 5905 if (tcam_info_match->priority == pkt_format_info->prio) { 5906 rv = BCM_E_EXISTS; 5907 } else { 5908 rv = BCM_E_RESOURCE; 5909 } 5910 } else { 5911 if (rv == BCM_E_NOT_FOUND) { 5912 rv = BCM_E_NONE; 5913 } 5914 5915 } 5916 UDF_IF_ERROR_CLEANUP(rv); 5917 5918 /* Increment num udfs */ 5919 UDF_CTRL(unit)->num_pkt_formats += 1; 5920 5921 /* update pkt_format_id in the tcam_info */ 5922 tcam_info_local->pkt_format_id = *pkt_format_id; 5923 5924 cleanup: 5925 5926 if (BCM_FAILURE(rv)) { 5927 if ((id_running_allocated) && 5928 (UDF_CTRL(unit)->udf_pkt_format_id_running != 5929 BCMI_XGS4_UDF_PKT_FORMAT_ID_MAX)) { 5930 /* Decrement the running pkt format id */ 5931 UDF_CTRL(unit)->udf_pkt_format_id_running -= 1; 5932 } 5933 5934 /* Delete the offset node */ 5935 if (tcam_info_local != NULL) { 5936 UDF_UNLINK_TCAM_NODE(tcam_info_local); 5937 sal_free(tcam_info_local); 5938 } 5939 } 5940 5941 /* Release UDF mutex */ 5942 UDF_UNLOCK(unit); 5943 5944 5945 return rv; 5946 } 5947 5948 5949 /* 5950 * Function: 5951 * bcm_udf_pkt_format_destroy 5952 * Purpose: 5953 * Destroy existing packet format entry 5954 * Parameters: 5955 * unit - (IN) Unit number. 5956 * pkt_format_id - (IN) Packet format ID 5957 * pkt_format - (IN) UDF packet format info structure 5958 * Returns: 5959 * BCM_E_NONE Destroy packet format entry. 5960 * BCM_E_NOT_FOUND Packet format ID does not exist. 5961 * BCM_E_UNIT Invalid BCM Unit number. 5962 * BCM_E_INIT UDF module not initialized. 5963 * BCM_E_UNAVAIL Feature not supported. 5964 * BCM_E_XXX Standard error code. 5965 * Notes: 5966 */ 5967 int 5968 bcmi_xgs4_udf_pkt_format_destroy(int unit, 5969 bcm_udf_pkt_format_id_t pkt_format_id) 5970 { 5971 int rv; 5972 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 5973 5974 /* UDF Module Init check */ 5975 UDF_INIT_CHECK(unit); 5976 5977 /* UDF Module Lock */ 5978 UDF_LOCK(unit); 5979 5980 /* Retrieve the node indexed by pkt_format_id */ 5981 rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info); 5982 if (BCM_FAILURE(rv)) { 5983 UDF_UNLOCK(unit); 5984 return rv; 5985 } 5986 5987 /* Delete the software object */ 5988 if (tcam_info->num_udfs >= 1) { 5989 UDF_UNLOCK(unit); 5990 return BCM_E_BUSY; 5991 } else { 5992 UDF_UNLINK_TCAM_NODE(tcam_info); 5993 5994 /* Decrement num pkt_formats */ 5995 UDF_CTRL(unit)->num_pkt_formats -= 1; 5996 5997 /* Free the tcam node */ 5998 sal_free(tcam_info); 5999 } 6000 6001 /* Release UDF mutex */ 6002 UDF_UNLOCK(unit); 6003 6004 return BCM_E_NONE; 6005 } 6006 6007 6008 /* 6009 * Function: 6010 * bcm_udf_pkt_format_info_get 6011 * Purpose: 6012 * Retrieve packet format info given the packet format Id 6013 * Parameters: 6014 * unit - (IN) Unit number. 6015 * pkt_format_id - (IN) Packet format ID 6016 * pkt_format - (OUT) UDF packet format info structure 6017 * Returns: 6018 * BCM_E_NONE Packet format get successful. 6019 * BCM_E_NOT_FOUND Packet format entry does not exist. 6020 * BCM_E_UNIT Invalid BCM Unit number. 6021 * BCM_E_INIT UDF module not initialized. 6022 * BCM_E_UNAVAIL Feature not supported. 6023 * BCM_E_XXX Standard error code. 6024 * Notes: 6025 */ 6026 int 6027 bcmi_xgs4_udf_pkt_format_info_get( 6028 int unit, 6029 bcm_udf_pkt_format_id_t pkt_format_id, 6030 bcm_udf_pkt_format_info_t *pkt_format_info) 6031 { 6032 int rv; 6033 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 6034 6035 /* UDF Module Init check */ 6036 UDF_INIT_CHECK(unit); 6037 6038 BCM_IF_NULL_RETURN_PARAM(pkt_format_info); 6039 6040 /* UDF Module Lock */ 6041 UDF_LOCK(unit); 6042 6043 /* Retrieve the node indexed by pkt_format_id */ 6044 rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info); 6045 if (BCM_FAILURE(rv)) { 6046 UDF_UNLOCK(unit); 6047 return rv; 6048 } 6049 6050 /* Fetch the tcam entry info and convert to user-readable form */ 6051 rv = bcmi_xgs4_udf_tcam_entry_parse(unit, 6052 (uint32 *)&(tcam_info->hw_buf), pkt_format_info); 6053 if (BCM_FAILURE(rv)) { 6054 UDF_UNLOCK(unit); 6055 return rv; 6056 } 6057 6058 pkt_format_info->prio = tcam_info->priority; 6059 6060 #if defined (BCM_TOMAHAWK_SUPPORT) 6061 if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) { 6062 pkt_format_info->class_id = tcam_info->class_id; 6063 } 6064 #endif 6065 6066 /* Release UDF mutex */ 6067 UDF_UNLOCK(unit); 6068 6069 6070 return BCM_E_NONE; 6071 } 6072 6073 /* 6074 * Function: 6075 * bcm_udf_pkt_format_add 6076 * Purpose: 6077 * Adds packet format entry to UDF object 6078 * Parameters: 6079 * unit - (IN) Unit number. 6080 * udf_id - (IN) UDF ID 6081 * pkt_format_id - (IN) Packet format ID 6082 * Returns: 6083 * BCM_E_NONE Packet format entry added to UDF 6084 * successfully. 6085 * BCM_E_NOT_FOUND UDF Id or packet format entry does not 6086 * exist. 6087 * BCM_E_UNIT Invalid BCM Unit number. 6088 * BCM_E_INIT UDF module not initialized. 6089 * BCM_E_UNAVAIL Feature not supported. 6090 * BCM_E_XXX Standard error code. 6091 * Notes: 6092 */ 6093 int 6094 bcmi_xgs4_udf_pkt_format_add( 6095 int unit, 6096 bcm_udf_id_t udf_id, 6097 bcm_udf_pkt_format_id_t pkt_format_id) 6098 { 6099 int rv; 6100 int idx; 6101 int base = 0; 6102 int offset = 0; 6103 int num_udfs = 0; 6104 uint32 offset_bmap; 6105 bcmi_xgs4_udf_offset_entry_t *offset_entry; 6106 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 6107 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 6108 6109 /* UDF Module Init check */ 6110 UDF_INIT_CHECK(unit); 6111 6112 /* Sanitize input params */ 6113 UDF_ID_VALIDATE(udf_id); 6114 UDF_PKT_FORMAT_ID_VALIDATE(pkt_format_id); 6115 6116 /* UDF Module Lock */ 6117 UDF_LOCK(unit); 6118 6119 /* Retrieve the node indexed by pkt_format_id */ 6120 rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info); 6121 if (BCM_FAILURE(rv)) { 6122 UDF_UNLOCK(unit); 6123 return rv; 6124 } 6125 6126 /* Read UDF info */ 6127 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info); 6128 if (BCM_FAILURE(rv)) { 6129 UDF_UNLOCK(unit); 6130 return rv; 6131 } 6132 6133 /* Convert udf layer+start to udf_offset info */ 6134 rv = bcmi_xgs4_udf_layer_to_offset_base(unit, offset_info, 6135 tcam_info, &base, &offset); 6136 if (BCM_FAILURE(rv)) { 6137 UDF_UNLOCK(unit); 6138 return rv; 6139 } 6140 6141 if ((offset_info->num_pkt_formats + 1) >= MAX_UDF_TCAM_ENTRIES) { 6142 UDF_UNLOCK(unit); 6143 return BCM_E_RESOURCE; 6144 } 6145 6146 #ifdef BCM_TOMAHAWK_SUPPORT 6147 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 6148 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 6149 if (offset_info->associated_pipe >= SOC_MAX_NUM_PIPES) { 6150 UDF_UNLOCK(unit); 6151 return BCM_E_PARAM; 6152 } 6153 6154 tcam_info->associated_pipe = offset_info->associated_pipe; 6155 tcam_info->associated_pipes[offset_info->associated_pipe] = 6156 offset_info->associated_pipe; 6157 6158 num_udfs = tcam_info->num_udfs_per_pipe[tcam_info->associated_pipe]; 6159 offset_bmap = tcam_info->offset_bmap_per_pipe[tcam_info->associated_pipe]; 6160 } else 6161 #endif 6162 { 6163 num_udfs = tcam_info->num_udfs; 6164 offset_bmap = tcam_info->offset_bmap; 6165 } 6166 6167 if (offset_bmap & offset_info->hw_bmap) { 6168 /* Packet format object is already using the bmap */ 6169 UDF_UNLOCK(unit); 6170 return BCM_E_EXISTS; 6171 } 6172 6173 if ((num_udfs + 1) > MAX_UDF_OFFSET_CHUNKS) { 6174 UDF_UNLOCK(unit); 6175 return BCM_E_RESOURCE; 6176 } 6177 6178 /* Packet format is associated with the first UDF, install it */ 6179 if (num_udfs == 0) { 6180 rv = bcmi_xgs4_udf_tcam_entry_insert(unit, tcam_info); 6181 if (BCM_FAILURE(rv)) { 6182 UDF_UNLOCK(unit); 6183 return rv; 6184 } 6185 } 6186 6187 #ifdef BCM_TOMAHAWK_SUPPORT 6188 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 6189 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 6190 tcam_info->hw_idx = 6191 tcam_info->hw_idx_per_pipe[tcam_info->associated_pipe]; 6192 } 6193 #endif 6194 6195 /* Add the udf offset info to the UDF_OFFSET entry */ 6196 rv = bcmi_xgs4_udf_offset_install(unit, tcam_info->hw_idx, 6197 offset_info->hw_bmap, base, offset, 6198 tcam_info->associated_pipe, 6199 tcam_info->class_id, 6200 offset_info->flags); 6201 6202 if (BCM_FAILURE(rv)) { 6203 UDF_UNLOCK(unit); 6204 return rv; 6205 } 6206 6207 /* set the offset_bmap */ 6208 tcam_info->num_udfs++; 6209 offset_info->num_pkt_formats++; 6210 tcam_info->offset_info_list[offset_info->grp_id] = offset_info; 6211 6212 for (idx = 0; idx < MAX_UDF_ID_LIST; idx++) { 6213 if (tcam_info->udf_id_list[idx] == 0) { 6214 tcam_info->udf_id_list[idx] = udf_id; 6215 break; 6216 } 6217 } 6218 6219 #ifdef BCM_TOMAHAWK_SUPPORT 6220 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 6221 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 6222 tcam_info->num_udfs_per_pipe[tcam_info->associated_pipe]++; 6223 tcam_info->offset_bmap_per_pipe[tcam_info->associated_pipe] |= offset_info->hw_bmap; 6224 offset_entry = &(UDF_CTRL(unit)->offset_entry_array_per_pipe[offset_info->associated_pipe][(offset_info->grp_id)]); 6225 } else 6226 #endif 6227 { 6228 tcam_info->offset_bmap |= (offset_info->hw_bmap); 6229 offset_entry = &(UDF_CTRL(unit)->offset_entry_array[(offset_info->grp_id)]); 6230 } 6231 6232 offset_entry->num_pkt_formats++; 6233 6234 /* Release UDF mutex */ 6235 UDF_UNLOCK(unit); 6236 6237 return BCM_E_NONE; 6238 } 6239 6240 /* 6241 * Function: 6242 * bcm_udf_pkt_format_delete 6243 * Purpose: 6244 * Deletes packet format spec associated with the UDF 6245 * Parameters: 6246 * unit - (IN) Unit number. 6247 * udf_id - (IN) UDF ID 6248 * pkt_format_id - (IN) Packet format ID 6249 * Returns: 6250 * BCM_E_NONE Packet format configuration successfully 6251 * deleted from UDF. 6252 * BCM_E_NOT_FOUND UDF Id or packet format entry does not 6253 * exist. 6254 * BCM_E_UNIT Invalid BCM Unit number. 6255 * BCM_E_INIT UDF module not initialized. 6256 * BCM_E_UNAVAIL Feature not supported. 6257 * BCM_E_XXX Standard error code. 6258 * Notes: 6259 */ 6260 int 6261 bcmi_xgs4_udf_pkt_format_delete( 6262 int unit, 6263 bcm_udf_id_t udf_id, 6264 bcm_udf_pkt_format_id_t pkt_format_id) 6265 { 6266 int rv; 6267 int idx; 6268 int hw_idx; 6269 int *num_udfs; 6270 uint32 *offset_bmap; 6271 soc_mem_t tcam_mem; 6272 bcmi_xgs4_udf_tcam_entry_t *tcam_entry; 6273 bcmi_xgs4_udf_offset_entry_t *offset_entry; 6274 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 6275 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 6276 6277 #if defined (BCM_TOMAHAWK_SUPPORT) 6278 int pipe_num = BCMI_XGS4_UDF_INVALID_PIPE_NUM; 6279 #endif 6280 6281 /* UDF Module Init check */ 6282 UDF_INIT_CHECK(unit); 6283 6284 /* Sanitize input params */ 6285 UDF_ID_VALIDATE(udf_id); 6286 UDF_PKT_FORMAT_ID_VALIDATE(pkt_format_id); 6287 6288 /* UDF Module Lock */ 6289 UDF_LOCK(unit); 6290 6291 /* Retrieve the node indexed by pkt_format_id */ 6292 rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info); 6293 if (BCM_FAILURE(rv)) { 6294 UDF_UNLOCK(unit); 6295 return rv; 6296 } 6297 6298 /* Read UDF info */ 6299 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info); 6300 if (BCM_FAILURE(rv)) { 6301 UDF_UNLOCK(unit); 6302 return rv; 6303 } 6304 6305 /* Either of the entry is not installed to the hardware yet */ 6306 if (offset_info->num_pkt_formats == 0) { 6307 UDF_UNLOCK(unit); 6308 return BCM_E_CONFIG; 6309 } 6310 6311 #if defined (BCM_TOMAHAWK_SUPPORT) 6312 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 6313 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 6314 if (offset_info->associated_pipe >= SOC_MAX_NUM_PIPES) { 6315 UDF_UNLOCK(unit); 6316 return BCM_E_PARAM; 6317 } 6318 6319 pipe_num = tcam_info->associated_pipes[offset_info->associated_pipe]; 6320 if (pipe_num == BCMI_XGS4_UDF_INVALID_PIPE_NUM) { 6321 UDF_UNLOCK(unit); 6322 return BCM_E_PARAM; 6323 } 6324 6325 hw_idx = tcam_info->hw_idx_per_pipe[pipe_num]; 6326 num_udfs = &(tcam_info->num_udfs_per_pipe[pipe_num]); 6327 offset_bmap = &(tcam_info->offset_bmap_per_pipe[pipe_num]); 6328 } else 6329 #endif 6330 { 6331 hw_idx = tcam_info->hw_idx; 6332 num_udfs = &(tcam_info->num_udfs); 6333 offset_bmap = &(tcam_info->offset_bmap); 6334 } 6335 6336 /* Unrelated packet format id and udf id */ 6337 if (!(*offset_bmap & offset_info->hw_bmap)) { 6338 UDF_UNLOCK(unit); 6339 return BCM_E_CONFIG; 6340 } 6341 6342 if (*num_udfs == 0) { 6343 UDF_UNLOCK(unit); 6344 return BCM_E_CONFIG; 6345 } 6346 6347 #if defined (BCM_TOMAHAWK_SUPPORT) 6348 if (soc_feature(unit, soc_feature_udf_multi_pipe_support) && 6349 (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) { 6350 tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[pipe_num]; 6351 tcam_entry = &(UDF_CTRL(unit)->tcam_entry_array_per_pipe[pipe_num][hw_idx]); 6352 offset_entry = &(UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe_num][offset_info->grp_id]); 6353 tcam_info->num_udfs--; 6354 } else 6355 #endif 6356 { 6357 tcam_mem = UDF_CTRL(unit)->tcam_mem; 6358 tcam_entry = &(UDF_CTRL(unit)->tcam_entry_array[hw_idx]); 6359 offset_entry = &(UDF_CTRL(unit)->offset_entry_array[(offset_info->grp_id)]); 6360 } 6361 6362 *num_udfs = *num_udfs - 1; 6363 offset_info->num_pkt_formats -= 1; 6364 offset_entry->num_pkt_formats -= 1; 6365 tcam_info->offset_info_list[offset_info->grp_id] = NULL; 6366 6367 for (idx = 0; idx < MAX_UDF_ID_LIST; idx++) { 6368 if (tcam_info->udf_id_list[idx] == udf_id) { 6369 tcam_info->udf_id_list[idx] = 0; 6370 break; 6371 } 6372 } 6373 6374 /* Packet format is dissociated with the first UDF, uninstall it */ 6375 if (*num_udfs == 0) { 6376 6377 /* Install the entry into hardware */ 6378 rv = soc_mem_write(unit, tcam_mem, 6379 MEM_BLOCK_ALL, hw_idx, 6380 soc_mem_entry_null(unit, UDF_CTRL(unit)->tcam_mem)); 6381 6382 if (SOC_FAILURE(rv)) { 6383 UDF_UNLOCK(unit); 6384 return rv; 6385 } 6386 6387 tcam_entry->valid = 0; 6388 tcam_entry->tcam_info = NULL; 6389 } 6390 6391 /* clear the offset_bmap */ 6392 *offset_bmap &= ~(offset_info->hw_bmap); 6393 6394 /* Remove the udf offset info to the UDF_OFFSET entry */ 6395 rv = bcmi_xgs4_udf_offset_uninstall(unit, hw_idx, 6396 offset_info->hw_bmap, 6397 offset_info->associated_pipe); 6398 if (BCM_FAILURE(rv)) { 6399 UDF_UNLOCK(unit); 6400 return rv; 6401 } 6402 6403 /* Release UDF mutex */ 6404 UDF_UNLOCK(unit); 6405 6406 return BCM_E_NONE; 6407 } 6408 6409 /* 6410 * Function: 6411 * bcm_udf_pkt_format_get_all 6412 * Purpose: 6413 * Retrieves the user defined format specification configuration 6414 * from UDF 6415 * Parameters: 6416 * unit - (IN) Unit number. 6417 * udf_id - (IN) UDF ID 6418 * max - (IN) Max Packet formats attached to a UDF object 6419 * pkt_format_id_list - (OUT) List of packet format entries added to udf id 6420 * actual - (OUT) Actual number of Packet formats retrieved 6421 * Returns: 6422 * BCM_E_NONE Success. 6423 * BCM_E_NOT_FOUND Either the UDF or packet format entry does 6424 * not exist. 6425 * BCM_E_UNIT Invalid BCM Unit number. 6426 * BCM_E_INIT UDF module not initialized. 6427 * BCM_E_UNAVAIL Feature not supported. 6428 * BCM_E_XXX Standard error code. 6429 * Notes: 6430 */ 6431 int 6432 bcmi_xgs4_udf_pkt_format_get_all( 6433 int unit, 6434 bcm_udf_id_t udf_id, 6435 int max, 6436 bcm_udf_pkt_format_id_t *pkt_format_id_list, 6437 int *actual) 6438 { 6439 int i; 6440 int rv; 6441 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 6442 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 6443 6444 /* UDF Module Init check */ 6445 UDF_INIT_CHECK(unit); 6446 6447 BCM_IF_NULL_RETURN_PARAM(actual); 6448 6449 /* Sanitize input params */ 6450 UDF_ID_VALIDATE(udf_id); 6451 6452 /* UDF Module Lock */ 6453 UDF_LOCK(unit); 6454 6455 /* Read UDF info */ 6456 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info); 6457 if (BCM_FAILURE(rv)) { 6458 UDF_UNLOCK(unit); 6459 return rv; 6460 } 6461 6462 if ((max == 0) || (pkt_format_id_list == NULL)) { 6463 *actual = offset_info->num_pkt_formats; 6464 UDF_UNLOCK(unit); 6465 return BCM_E_NONE; 6466 } 6467 6468 tcam_info = UDF_CTRL(unit)->tcam_info_head; 6469 while (tcam_info) { 6470 for (i = 0; i < MAX_UDF_ID_LIST; i++) { 6471 if (tcam_info->udf_id_list[i] == udf_id) { 6472 if (*actual < max) { 6473 pkt_format_id_list[*actual] = tcam_info->pkt_format_id; 6474 } 6475 6476 (*actual) += 1; 6477 break; 6478 } 6479 } 6480 6481 tcam_info = tcam_info->next; 6482 } 6483 6484 /* Release UDF mutex */ 6485 UDF_UNLOCK(unit); 6486 6487 return BCM_E_NONE; 6488 } 6489 6490 /* 6491 * Function: 6492 * bcm_udf_pkt_format_delete_all 6493 * Purpose: 6494 * Deletes all packet format specs associated with the UDF 6495 * Parameters: 6496 * unit - (IN) Unit number. 6497 * udf_id - (IN) UDF ID 6498 * Returns: 6499 * BCM_E_NONE Deletes all packet formats associated with 6500 * the UDF. 6501 * BCM_E_NOT_FOUND UDF Id does not exist. 6502 * BCM_E_UNIT Invalid BCM Unit number. 6503 * BCM_E_INIT UDF module not initialized. 6504 * BCM_E_UNAVAIL Feature not supported. 6505 * BCM_E_XXX Standard error code. 6506 * Notes: 6507 */ 6508 int 6509 bcmi_xgs4_udf_pkt_format_delete_all( 6510 int unit, bcm_udf_id_t udf_id) 6511 { 6512 int i; 6513 int rv; 6514 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 6515 6516 /* UDF Module Init check */ 6517 UDF_INIT_CHECK(unit); 6518 6519 /* Sanitize input params */ 6520 UDF_ID_VALIDATE(udf_id); 6521 6522 /* UDF Module Lock */ 6523 UDF_LOCK(unit); 6524 6525 tcam_info = UDF_CTRL(unit)->tcam_info_head; 6526 while (tcam_info) { 6527 for (i = 0; i < MAX_UDF_ID_LIST; i++) { 6528 if (tcam_info->udf_id_list[i] == udf_id) { 6529 rv = bcmi_xgs4_udf_pkt_format_delete(unit, udf_id, 6530 tcam_info->pkt_format_id); 6531 6532 if (BCM_FAILURE(rv)) { 6533 UDF_UNLOCK(unit); 6534 return rv; 6535 } 6536 break; 6537 } 6538 } 6539 6540 tcam_info = tcam_info->next; 6541 } 6542 6543 /* Release UDF mutex */ 6544 UDF_UNLOCK(unit); 6545 6546 return BCM_E_NONE; 6547 } 6548 6549 6550 /* 6551 * Function: 6552 * bcm_udf_pkt_format_get 6553 * Purpose: 6554 * Fetches all UDFs that share the common packet format entry. 6555 * Parameters: 6556 * unit - (IN) Unit number. 6557 * pkt_format_id - (IN) Packet format ID. 6558 * max - (IN) Max number of UDF IDs 6559 * udf_id_list - (OUT) List of UDF IDs 6560 * actual - (OUT) Actual udfs retrieved 6561 * Returns: 6562 * BCM_E_NONE Success. 6563 * BCM_E_UNIT Invalid BCM Unit number. 6564 * BCM_E_INIT UDF module not initialized. 6565 * BCM_E_UNAVAIL Feature not supported. 6566 * BCM_E_XXX Standard error code. 6567 * Notes: 6568 */ 6569 int 6570 bcmi_xgs4_udf_pkt_format_get( 6571 int unit, 6572 bcm_udf_pkt_format_id_t pkt_format_id, 6573 int max, 6574 bcm_udf_id_t *udf_id_list, 6575 int *actual) 6576 { 6577 int i; 6578 int rv; 6579 uint16 udf_id; 6580 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 6581 6582 /* UDF Module Init check */ 6583 UDF_INIT_CHECK(unit); 6584 6585 BCM_IF_NULL_RETURN_PARAM(actual); 6586 6587 /* Sanitize input params */ 6588 UDF_PKT_FORMAT_ID_VALIDATE(pkt_format_id); 6589 6590 /* UDF Module Lock */ 6591 UDF_LOCK(unit); 6592 6593 6594 /* Read UDF info */ 6595 rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info); 6596 if (BCM_FAILURE(rv)) { 6597 UDF_UNLOCK(unit); 6598 return rv; 6599 } 6600 6601 if ((udf_id_list == NULL) || (max == 0)) { 6602 *actual = tcam_info->num_udfs; 6603 UDF_UNLOCK(unit); 6604 return rv; 6605 } 6606 6607 for (i = 0; i < MAX_UDF_ID_LIST; i++) { 6608 udf_id = tcam_info->udf_id_list[i]; 6609 if (udf_id > 0) { 6610 if (*actual < max) { 6611 udf_id_list[*actual] = udf_id; 6612 } 6613 6614 (*actual) += 1; 6615 } 6616 } 6617 6618 /* Release UDF mutex */ 6619 UDF_UNLOCK(unit); 6620 6621 return BCM_E_NONE; 6622 } 6623 6624 6625 /* 6626 * Function: 6627 * bcmi_xgs4_udf_hash_config_add 6628 * Purpose: 6629 * Add UDF id into hashing list and configure it 6630 * Parameters: 6631 * unit (IN) BCM unit number 6632 * options (IN) See BCM_UDF_HASH_ADD_O_xxx. 6633 * Currently not supported, 6634 * reserved for future usage. 6635 * config (IN) UDF hashing configuration info 6636 * Returns: 6637 * BCM_E_NONE UDF hashing added successfully 6638 * BCM_E_XXX Standard error code 6639 * Notes: 6640 */ 6641 int 6642 bcmi_xgs4_udf_hash_config_add( 6643 int unit, 6644 uint32 options, 6645 bcm_udf_hash_config_t *config) 6646 { 6647 int rv; 6648 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 6649 6650 /* UDF Module Init check */ 6651 UDF_INIT_CHECK(unit); 6652 6653 /* UDF Module Lock */ 6654 UDF_LOCK(unit); 6655 6656 if ((config == NULL)) { 6657 UDF_UNLOCK(unit); 6658 return BCM_E_PARAM; 6659 } 6660 6661 rv = bcmi_xgs4_udf_offset_node_get(unit, config->udf_id, &offset_info); 6662 if (BCM_FAILURE(rv)) { 6663 UDF_UNLOCK(unit); 6664 return BCM_E_PARAM; 6665 } 6666 6667 rv = bcmi_xgs4_udf_hash_config_set(unit, config, offset_info); 6668 if (BCM_FAILURE(rv)) { 6669 UDF_UNLOCK(unit); 6670 return rv; 6671 } 6672 6673 /* Set flag to indicate the object is in the list that 6674 participates in hash calculation */ 6675 offset_info->flags |= BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG; 6676 6677 /* Release UDF mutex */ 6678 UDF_UNLOCK(unit); 6679 6680 return BCM_E_NONE; 6681 } 6682 6683 /* 6684 * Function: 6685 * bcmi_xgs4_udf_hash_config_delete 6686 * Purpose: 6687 * Delete UDF id from hashing list 6688 * Parameters: 6689 * unit (IN) BCM unit number 6690 * config (IN) UDF hashing configuration info 6691 * Returns: 6692 * BCM_E_NONE UDF hashing added successfully 6693 * BCM_E_XXX Standard error code 6694 * Notes: 6695 */ 6696 int 6697 bcmi_xgs4_udf_hash_config_delete( 6698 int unit, 6699 bcm_udf_hash_config_t *config) 6700 { 6701 int rv; 6702 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 6703 6704 /* UDF Module Init check */ 6705 UDF_INIT_CHECK(unit); 6706 6707 /* UDF Module Lock */ 6708 UDF_LOCK(unit); 6709 6710 if ((config == NULL)) { 6711 return BCM_E_PARAM; 6712 UDF_UNLOCK(unit); 6713 } 6714 6715 rv = bcmi_xgs4_udf_offset_node_get(unit, config->udf_id, &offset_info); 6716 if (BCM_FAILURE(rv)) { 6717 UDF_UNLOCK(unit); 6718 return BCM_E_BADID; 6719 } 6720 6721 /* set mask to zero */ 6722 sal_memset(config->hash_mask, 0, sizeof(config->hash_mask)); 6723 config->mask_length = offset_info->width; 6724 rv = bcmi_xgs4_udf_hash_config_set(unit, config, offset_info); 6725 if (BCM_FAILURE(rv)) { 6726 UDF_UNLOCK(unit); 6727 return rv; 6728 } 6729 6730 /* Clear flag */ 6731 offset_info->flags &= ~BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG; 6732 6733 /* Release UDF mutex */ 6734 UDF_UNLOCK(unit); 6735 6736 return BCM_E_NONE; 6737 } 6738 6739 6740 /* 6741 * Function: 6742 * bcmi_xgs4_udf_hash_config_delete_all 6743 * Purpose: 6744 * Delete all UDF id from hashing list 6745 * Parameters: 6746 * unit (IN) BCM unit number 6747 * Returns: 6748 * BCM_E_NONE UDF hashing added successfully 6749 * BCM_E_XXX Standard error code 6750 * Notes: 6751 */ 6752 int 6753 bcmi_xgs4_udf_hash_config_delete_all( 6754 int unit) 6755 { 6756 bcmi_xgs4_udf_offset_info_t *tmp; 6757 bcm_udf_hash_config_t config; 6758 int rv; 6759 6760 /* UDF Module Init check */ 6761 UDF_INIT_CHECK(unit); 6762 6763 tmp = UDF_CTRL(unit)->offset_info_head; 6764 6765 while (tmp != NULL) { 6766 if (tmp->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG) { 6767 /* the udf id is in the list, set mask to zero */ 6768 sal_memset((&config)->hash_mask, 0, sizeof((&config)->hash_mask)); 6769 (&config)->mask_length = tmp->width; 6770 (&config)->udf_id = tmp->udf_id; 6771 rv = bcmi_xgs4_udf_hash_config_set(unit, &config, tmp); 6772 if (BCM_FAILURE(rv)) { 6773 UDF_UNLOCK(unit); 6774 return rv; 6775 } 6776 6777 /* Clear flag */ 6778 tmp->flags &= ~BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG; 6779 } 6780 6781 tmp = tmp->next; 6782 } 6783 6784 return BCM_E_NONE; 6785 } 6786 6787 6788 /* 6789 * Function: 6790 * bcmi_xgs4_udf_hash_config_set 6791 * Purpose: 6792 * Set udf hash configuration to hw 6793 * Parameters: 6794 * unit (IN) BCM unit number 6795 * config (IN) UDF hashing configuration info 6796 * offset_info (IN) Offset info node in offset link 6797 * Returns: 6798 * BCM_E_NONE UDF hashing added successfully 6799 * BCM_E_BADID UDF id does not exist or is not for UDF hashing usage 6800 * BCM_E_XXX Standard error code 6801 * Notes: 6802 */ 6803 STATIC int 6804 bcmi_xgs4_udf_hash_config_set( 6805 int unit, 6806 bcm_udf_hash_config_t *config, 6807 bcmi_xgs4_udf_offset_info_t *offset_info) 6808 { 6809 int i, j, rv; 6810 bcmi_xgs4_udf_offset_info_t *offset_match = NULL; 6811 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 6812 soc_mem_t mem; 6813 fp_udf_offset_entry_t offset_buf; 6814 uint8 udf_hash_1, udf_hash_2; 6815 uint32 mask; 6816 uint16 mask_1, mask_2, mask_en_1, mask_en_2; 6817 int byte_map[] = {13, 12, 15, 14}; 6818 6819 if ((config == NULL) 6820 || (config->mask_length > BCM_UDF_HASH_MAX_LENGTH)) { 6821 return BCM_E_PARAM; 6822 } 6823 6824 udf_hash_1 = UDF_CTRL(unit)->udf_hash_1; 6825 udf_hash_2 = UDF_CTRL(unit)->udf_hash_2; 6826 if (!(offset_info->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH) || 6827 !(offset_info->hw_bmap & ((1 << udf_hash_1) | (1 << udf_hash_2))) || 6828 (offset_info->width != config->mask_length)) { 6829 return BCM_E_PARAM; 6830 } 6831 6832 mask = 0; 6833 /* mask[0]~[3] reflect to the order in byte_map */ 6834 for (i = 0, j = 0; i < BCM_UDF_HASH_MAX_LENGTH; i++) { 6835 if (offset_info->byte_bmap & (1 << byte_map[i])) { 6836 mask |= (config->hash_mask[j++] << (8 * (3 - i))); 6837 } 6838 } 6839 mask_1 = (mask & 0xFFFF0000) >> 16; 6840 mask_2 = mask & 0x0000FFFF; 6841 mask_en_1 = (offset_info->hw_bmap & (1 << udf_hash_1)) ? 1 : 0; 6842 mask_en_2 = (offset_info->hw_bmap & (1 << udf_hash_2)) ? 1 : 0; 6843 6844 tcam_info = UDF_CTRL(unit)->tcam_info_head; 6845 mem = UDF_CTRL(unit)->offset_mem; 6846 6847 while (tcam_info != NULL) { 6848 for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) { 6849 offset_match = tcam_info->offset_info_list[i]; 6850 /* Set same mask to all entries related to the UDF id */ 6851 if (offset_info == offset_match) { 6852 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 6853 tcam_info->hw_idx, &offset_buf); 6854 if (BCM_FAILURE(rv)) { 6855 return rv; 6856 } 6857 6858 if (mask_en_1) { 6859 soc_mem_field32_set(unit, mem, &offset_buf, 6860 HASH_MASK_1f, mask_1); 6861 } 6862 if (mask_en_2) { 6863 soc_mem_field32_set(unit, mem, &offset_buf, 6864 HASH_MASK_2f, mask_2); 6865 } 6866 6867 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, 6868 tcam_info->hw_idx, &offset_buf); 6869 if (BCM_FAILURE(rv)) { 6870 return rv; 6871 } 6872 break; 6873 } 6874 } 6875 6876 tcam_info = tcam_info->next; 6877 } 6878 6879 return BCM_E_NONE; 6880 } 6881 6882 6883 /* 6884 * Function: 6885 * bcmi_xgs4_udf_hash_config_get 6886 * Purpose: 6887 * Get UDF hashing configuration of a certain id 6888 * Parameters: 6889 * unit (IN) BCM unit number 6890 * config (INOUT) UDF hashing configuration info 6891 * Returns: 6892 * BCM_E_NONE UDF hashing added successfully 6893 * BCM_E_NOT_FOUND Requested UDF hashing info does not exist 6894 * BCM_E_XXX Standard error code 6895 * Notes: 6896 */ 6897 int 6898 bcmi_xgs4_udf_hash_config_get( 6899 int unit, 6900 bcm_udf_hash_config_t *config) 6901 { 6902 int i, j, found = 0, rv; 6903 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 6904 bcmi_xgs4_udf_offset_info_t *offset_match = NULL; 6905 bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL; 6906 soc_mem_t mem; 6907 fp_udf_offset_entry_t offset_buf; 6908 uint8 udf_hash_1, udf_hash_2; 6909 uint32 mask, mask_1 = 0, mask_2 = 0; 6910 int byte_map[] = {13, 12, 15, 14}; 6911 6912 /* UDF Module Init check */ 6913 UDF_INIT_CHECK(unit); 6914 6915 /* UDF Module Lock */ 6916 UDF_LOCK(unit); 6917 6918 if ((config == NULL)) { 6919 UDF_UNLOCK(unit); 6920 return BCM_E_PARAM; 6921 } 6922 6923 rv = bcmi_xgs4_udf_offset_node_get(unit, config->udf_id, &offset_info); 6924 if (BCM_FAILURE(rv)) { 6925 UDF_UNLOCK(unit); 6926 return rv; 6927 } 6928 6929 udf_hash_1 = UDF_CTRL(unit)->udf_hash_1; 6930 udf_hash_2 = UDF_CTRL(unit)->udf_hash_2; 6931 if (!(offset_info->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH) || 6932 !(offset_info->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG) || 6933 !(offset_info->hw_bmap & ((1 << udf_hash_1) | (1 << udf_hash_2)))) { 6934 UDF_UNLOCK(unit); 6935 return BCM_E_PARAM; 6936 } 6937 6938 mem = UDF_CTRL(unit)->offset_mem; 6939 6940 tcam_info = UDF_CTRL(unit)->tcam_info_head; 6941 6942 while (tcam_info != NULL) { 6943 /* Get the first entry related to the UDF id */ 6944 for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) { 6945 offset_match = tcam_info->offset_info_list[i]; 6946 if (offset_info == offset_match) { 6947 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 6948 tcam_info->hw_idx, &offset_buf); 6949 if (BCM_FAILURE(rv)) { 6950 UDF_UNLOCK(unit); 6951 return rv; 6952 } 6953 6954 mask_1 = soc_mem_field32_get(unit, mem, &offset_buf, 6955 HASH_MASK_1f); 6956 mask_2 = soc_mem_field32_get(unit, mem, &offset_buf, 6957 HASH_MASK_2f); 6958 6959 found = 1; 6960 break; 6961 } 6962 } 6963 6964 if (found) { 6965 break; 6966 } 6967 tcam_info = tcam_info->next; 6968 } 6969 6970 mask = (mask_1 << 16) | (mask_2 & 0xFFFF); 6971 6972 /* mask[0]~[3] reflect to the order in byte_bmap */ 6973 for (i = 0, j = 0; i < BCM_UDF_HASH_MAX_LENGTH; i++) { 6974 if (offset_info->byte_bmap & (1 << byte_map[i])) { 6975 config->hash_mask[j++] = (mask >> (8 * (3 - i))) & 0xFF; 6976 } 6977 } 6978 config->mask_length = offset_info->width; 6979 config->flags = 0; 6980 6981 /* Release UDF mutex */ 6982 UDF_UNLOCK(unit); 6983 6984 return BCM_E_NONE; 6985 } 6986 6987 6988 /* 6989 * Function: 6990 * bcmi_xgs4_udf_hash_config_get_all 6991 * Purpose: 6992 * Get all added UDF ids from list 6993 * Parameters: 6994 * unit (IN) BCM unit number 6995 * max (IN) Max count of UDF ids in the list. 6996 * udf_hash_config_list (OUT) List of UDF hashing configuration 6997 * actual (OUT) Actual count of UDF ids 6998 * Returns: 6999 * BCM_E_NONE UDF hashing added successfully 7000 * BCM_E_XXX Standard error code 7001 * Notes: 7002 */ 7003 int 7004 bcmi_xgs4_udf_hash_config_get_all( 7005 int unit, 7006 int max, 7007 bcm_udf_hash_config_t *udf_hash_config_list, 7008 int *actual) 7009 { 7010 bcmi_xgs4_udf_offset_info_t *tmp; 7011 bcm_udf_hash_config_t config; 7012 int rv; 7013 7014 /* UDF Module Init check */ 7015 UDF_INIT_CHECK(unit); 7016 7017 BCM_IF_NULL_RETURN_PARAM(actual); 7018 7019 /* UDF Module Lock */ 7020 UDF_LOCK(unit); 7021 7022 *actual = 0; 7023 tmp = UDF_CTRL(unit)->offset_info_head; 7024 7025 while (tmp != NULL) { 7026 /* the udf id is in the list, get its config */ 7027 if (tmp->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG) { 7028 if ((*actual < max) && (udf_hash_config_list != NULL)) { 7029 (&config)->udf_id = tmp->udf_id; 7030 rv = bcmi_xgs4_udf_hash_config_get(unit, &config); 7031 if (BCM_FAILURE(rv)) { 7032 UDF_UNLOCK(unit); 7033 return rv; 7034 } 7035 sal_memcpy((udf_hash_config_list + (*actual)), &config, 7036 sizeof(bcm_udf_hash_config_t)); 7037 } 7038 7039 (*actual) += 1; 7040 } 7041 7042 tmp = tmp->next; 7043 } 7044 7045 /* Release UDF mutex */ 7046 UDF_UNLOCK(unit); 7047 7048 return BCM_E_NONE; 7049 } 7050 7051 #if defined (BCM_TOMAHAWK_SUPPORT) 7052 /* 7053 * Function: 7054 * bcmi_xgs4_udf_oper_mode_set 7055 * Purpose: 7056 * Configure udf operation mode 7057 * Parameters: 7058 * unit - (IN) Unit number. 7059 * oper_mode - (IN) operation mode. 7060 * Returns: 7061 * BCM_E_NONE - Operation successful 7062 * BCM_E_PARAM - Invalid operational mode 7063 * BCM_E_INIT - BCM unit not initialized 7064 * BCM_E_BUSY - UDF tcam or offset memory has a valid entry configured 7065 * Notes: 7066 */ 7067 int 7068 bcmi_xgs4_udf_oper_mode_set( 7069 int unit, 7070 bcm_udf_oper_mode_t mode) 7071 { 7072 if (!(soc_feature(unit, soc_feature_udf_multi_pipe_support))) { 7073 return BCM_E_UNAVAIL; 7074 } 7075 7076 /* UDF Module Init check */ 7077 UDF_INIT_CHECK(unit); 7078 7079 if ((mode != bcmUdfOperModeGlobal) && 7080 (mode != bcmUdfOperModePipeLocal)) { 7081 return BCM_E_PARAM; 7082 } 7083 7084 if (bcmi_xgs4_udf_oper_mode[unit] == mode) { 7085 return BCM_E_NONE; 7086 } 7087 7088 if (UDF_CTRL(unit)->num_udfs > 0 || 7089 UDF_CTRL(unit)->num_pkt_formats > 0) { 7090 return BCM_E_BUSY; 7091 } 7092 7093 if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_FIELD_MODULE) { 7094 return BCM_E_BUSY; 7095 } 7096 7097 bcmi_xgs4_udf_oper_mode[unit] = mode; 7098 7099 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_ser_init(unit, mode)); 7100 7101 BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_ctrl_init(unit)); 7102 7103 UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_UDF_MODULE; 7104 return BCM_E_NONE; 7105 } 7106 7107 /* 7108 * Function: 7109 * bcmi_xgs4_udf_oper_mode_get 7110 * Purpose: 7111 * Retrieve udf operation mode 7112 * Parameters: 7113 * unit - (IN) Unit number. 7114 * oper_mode - (INOUT) operation mode. 7115 * Returns: 7116 * BCM_E_NONE - Operation successful 7117 * BCM_E_INIT - BCM unit not initialized 7118 * BCM_E_UNAVAIL - Feature is not available 7119 * Notes: 7120 */ 7121 int 7122 bcmi_xgs4_udf_oper_mode_get( 7123 int unit, 7124 bcm_udf_oper_mode_t *mode) 7125 { 7126 if (!(soc_feature(unit, soc_feature_udf_multi_pipe_support))) { 7127 return BCM_E_UNAVAIL; 7128 } 7129 /* UDF Module Init check */ 7130 UDF_INIT_CHECK(unit); 7131 7132 *mode = bcmi_xgs4_udf_oper_mode[unit]; 7133 7134 return BCM_E_NONE; 7135 } 7136 7137 /* 7138 * Function: 7139 * bcmi_xgs4_udf_ser_init 7140 * Purpose: 7141 * Initialize the SER for the given operational mode 7142 * 7143 * Parameters: 7144 * unit - (IN) BCM Device number. 7145 * mode - (IN) UDF Operational Mode enum value. 7146 * Returns: 7147 * BCM_E_NONE - Operation successful. 7148 * BCM_E_PARAM - Invalid operational mode. 7149 * BCM_E_XXX - For others. 7150 * 7151 * Notes: 7152 */ 7153 int 7154 bcmi_xgs4_udf_ser_init( 7155 int unit, 7156 bcm_udf_oper_mode_t mode) 7157 { 7158 int ser_mode; /* SER mode */ 7159 int rv; /* Return Value */ 7160 7161 /* Validate input parameters */ 7162 if ((mode != bcmUdfOperModeGlobal) && 7163 (mode != bcmUdfOperModePipeLocal)) { 7164 return BCM_E_PARAM; 7165 } 7166 7167 /* Update the SER mode */ 7168 ser_mode = (mode == bcmUdfOperModeGlobal) ? 7169 _SOC_SER_MEM_MODE_GLOBAL:_SOC_SER_MEM_MODE_PIPE_UNIQUE; 7170 7171 SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_stop(unit)); 7172 rv = soc_generic_ser_mem_update(unit, FP_UDF_TCAMm, 7, ser_mode); 7173 if (SOC_FAILURE(rv)) { 7174 LOG_CLI((BSL_META("Udf TCAM SER memory update fail \n"))); 7175 return rv; 7176 } 7177 7178 rv = soc_generic_ser_mem_update(unit, FP_UDF_OFFSETm, -1, ser_mode); 7179 if (SOC_FAILURE(rv)) { 7180 LOG_CLI((BSL_META("Udf OFFSET SER memory update fail \n"))); 7181 return rv; 7182 } 7183 SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_start(unit)); 7184 7185 return BCM_E_NONE; 7186 } 7187 7188 #endif