range.c (70754B)
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: range.c 8 * Purpose: Manages RANGE_CHECKER (IFP_RANGE_CHECK) 9 */ 10 11 #include <shared/bsl.h> 12 #include <soc/drv.h> 13 #include <soc/scache.h> 14 15 #include <bcm/range.h> 16 #include <bcm/error.h> 17 #include <bcm/module.h> 18 #include <bcm_int/esw/range.h> 19 #include <bcm_int/esw/switch.h> 20 #include <bcm_int/esw/xgs4.h> 21 #include <bcm_int/esw_dispatch.h> 22 23 #define RANGE_MALLOC(_p_, _t_, _sz_, _desc_) \ 24 do { \ 25 if (!_p_) { \ 26 (_p_) = (_t_ *) sal_alloc((_sz_), (_desc_)); \ 27 } \ 28 if (_p_) { \ 29 sal_memset((_p_), 0, (_sz_)); \ 30 } \ 31 } while(0) 32 33 #define BCM_IF_NULL_RETURN_PARAM(_p_) \ 34 do { \ 35 if ((_p_) == NULL) { \ 36 return BCM_E_PARAM; \ 37 } \ 38 } while(0) 39 40 /* Global Range control structure pointers */ 41 bcmi_xgs5_range_ctrl_t *range_control[BCM_MAX_NUM_UNITS]; 42 43 /* STATIC function declarations */ 44 STATIC int bcmi_xgs5_range_ctrl_init(int unit); 45 46 STATIC int bcmi_xgs5_range_hw_init(int unit); 47 48 STATIC int bcmi_xgs5_range_ctrl_free(int unit, bcmi_xgs5_range_ctrl_t *rangec); 49 50 soc_field_t range_group_fields[] = 51 { 52 IFP_RANGE_CHECK_MASK_0f, 53 IFP_RANGE_CHECK_MASK_1f, 54 IFP_RANGE_CHECK_MASK_2f, 55 IFP_RANGE_CHECK_MASK_3f, 56 IFP_RANGE_CHECK_MASK_4f, 57 IFP_RANGE_CHECK_MASK_5f, 58 IFP_RANGE_CHECK_MASK_6f, 59 IFP_RANGE_CHECK_MASK_7f, 60 IFP_RANGE_CHECK_MASK_8f, 61 IFP_RANGE_CHECK_MASK_9f, 62 IFP_RANGE_CHECK_MASK_10f, 63 IFP_RANGE_CHECK_MASK_11f, 64 IFP_RANGE_CHECK_MASK_12f, 65 IFP_RANGE_CHECK_MASK_13f, 66 IFP_RANGE_CHECK_MASK_14f, 67 IFP_RANGE_CHECK_MASK_15f 68 }; 69 70 71 /* Function : bcmi_xgs5_range_ctrl_free 72 * Purpose : Free Range control structure 73 * Parameters : unit - (IN) BCM device number 74 * rangec - (IN) Range control structure. 75 * Returns : BCM_E_XXX 76 */ 77 78 STATIC int 79 bcmi_xgs5_range_ctrl_free(int unit, bcmi_xgs5_range_ctrl_t *rangec) 80 { 81 LOG_DEBUG(BSL_LS_BCM_RANGE, 82 (BSL_META_U(unit, 83 "bcmi_xgs5_range_ctrl_free\n"))); 84 if (NULL == rangec) { 85 /* Already freed */ 86 return BCM_E_NONE; 87 } 88 89 /* Free mutex */ 90 if (NULL != rangec->range_mutex) { 91 sal_mutex_destroy(rangec->range_mutex); 92 rangec->range_mutex = NULL; 93 } 94 95 /* Free the range control structure */ 96 sal_free(rangec); 97 98 range_control[unit] = NULL; 99 100 return BCM_E_NONE; 101 } 102 103 /* Function : bcmi_xgs5_range_ctrl_init 104 * Purpose : Allocate and Initialise range control structure. 105 * Parameters : unit - (IN) BCM unit 106 * Returns : BCM_E_XXX 107 */ 108 STATIC int 109 bcmi_xgs5_range_ctrl_init(int unit) 110 { 111 int alloc_sz = 0; /* Allocation size */ 112 soc_mem_t range_mem = INVALIDm; /* Range Checker Memory ID */ 113 bcmi_xgs5_range_ctrl_t *range_ctrl = NULL; /* Range Control Structure */ 114 115 range_mem = IFP_RANGE_CHECKm; 116 117 if (range_control[unit] != NULL) { 118 bcmi_xgs5_range_detach(unit); 119 } 120 121 if (range_control[unit] != NULL) { 122 (void)bcmi_xgs5_range_ctrl_free(unit, range_control[unit]); 123 } 124 125 /* Allocating memory of Range control Structure */ 126 alloc_sz = sizeof(bcmi_xgs5_range_ctrl_t); 127 RANGE_MALLOC(range_ctrl, bcmi_xgs5_range_ctrl_t, alloc_sz, "range control"); 128 if(range_ctrl == NULL) { 129 LOG_ERROR(BSL_LS_BCM_RANGE, 130 (BSL_META_U(unit, 131 "Range Module(unit %d) Error: Module alloc failed.\n"), 132 unit)); 133 return BCM_E_MEMORY; 134 } 135 136 range_control[unit] = range_ctrl; 137 138 /* Create Range Mutex*/ 139 if(range_ctrl->range_mutex == NULL) { 140 range_ctrl->range_mutex = sal_mutex_create("range_mutex"); 141 if (range_ctrl->range_mutex == NULL) { 142 /*Free range ctrl structure. */ 143 (void)bcmi_xgs5_range_ctrl_free(unit, range_ctrl); 144 LOG_ERROR(BSL_LS_BCM_RANGE, 145 (BSL_META_U(unit, 146 "Range Module(unit %d) Error: Mutex alloc failed.\n"), 147 unit)); 148 return BCM_E_MEMORY; 149 } 150 } 151 152 range_ctrl->range_mem = range_mem; 153 154 range_ctrl->max_ranges = _RANGE_ID_MAX(unit); 155 156 range_ctrl->max_groups = _RANGE_GROUP_MAX(unit); 157 158 range_ctrl->range_used_by_module = RANGE_USED_BY_FIELD_MODULE; 159 160 if (soc_feature(unit, soc_feature_range_check_group_support)) { 161 range_ctrl->range_used_by_module = RANGE_USED_BY_RANGE_MODULE; 162 } 163 164 sal_memset(range_ctrl->range_group_used_bitmap, 0, 165 (sizeof(SHR_BITDCL) * SOC_MAX_NUM_PIPES)); 166 167 return BCM_E_NONE; 168 } 169 170 /* Function : bcmi_xgs5_range_hw_init 171 * Purpose : Clear hardware Range Checker memory 172 * Parameters : unit - (IN) BCM device number. 173 * Returns : BCM_E_XXX 174 */ 175 STATIC int 176 bcmi_xgs5_range_hw_init(int unit) 177 { 178 int rv; /* Operation return status. */ 179 180 /* Clear RANGE_CHECK mem*/ 181 rv = soc_mem_clear(unit, RANGE_CTRL(unit)->range_mem, MEM_BLOCK_ALL, TRUE); 182 SOC_IF_ERROR_RETURN(rv); 183 184 return BCM_E_NONE; 185 } 186 187 #if defined (BCM_WARM_BOOT_SUPPORT) 188 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1, 0) 189 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1, 1) 190 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1 191 192 /* Function : bcmi_xgs5_range_wb_scache_size_get_1_0 193 * Purpose : Returns required scache size in bytes for version = 1_0 194 * Parameters : unit - (IN) BCM device number. 195 * req_scache_size -(OUT) Required scache size 196 * Returns : BCM_E_XXX 197 */ 198 STATIC int 199 bcmi_xgs5_range_wb_scache_size_get_1_0(int unit, int *req_scache_size) 200 { 201 int alloc_size = 0; /* Allocation size */ 202 _range_t range; /* Range structure */ 203 204 bcmi_xgs5_range_ctrl_t *range_ctrl; 205 206 range_ctrl = RANGE_CTRL(unit); 207 208 /* The following fields from the Range Control Structure needs to 209 be synced for recovery after Warmboot: 210 1. range_oper_mode - to know whether the module was operating in 211 Per Pipe/ Global Mode to read appropriate 212 Memory. 213 2. num_ranges - Number of Ranges existing in the System. 214 3. range_used_by_module - Whether Range resource is being used by 215 Field Module or Range Module.*/ 216 alloc_size += sizeof(range_ctrl->range_oper_mode); 217 alloc_size += sizeof(range_ctrl->num_ranges); 218 alloc_size += sizeof(range_ctrl->range_used_by_module); 219 220 /* The following fields from the Range Structure needs to 221 be synced for recovery : 222 1. Range Id, 223 2. Range Offset, 224 3. Range Width, 225 4. UDF id mapped with the Range, 226 5. pipe_instance to which this range is mapped to. 227 Rest all fields in the range structure can be recovered from the Hardware. 228 */ 229 230 alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.rid); 231 alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.offset); 232 alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.width); 233 alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.udf_id); 234 alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.pipe_instance); 235 236 *req_scache_size = alloc_size; 237 238 return BCM_E_NONE; 239 } 240 241 /* Function : bcmi_xgs5_range_wb_scache_size_get_1_1 242 * Purpose : Returns required scache size in bytes for version = 1_1 243 * Parameters : unit - (IN) BCM device number. 244 * req_scache_size -(OUT) Required scache size 245 * Returns : BCM_E_XXX 246 */ 247 STATIC int 248 bcmi_xgs5_range_wb_scache_size_get_1_1(int unit, int *req_scache_size) 249 { 250 251 bcmi_xgs5_range_ctrl_t *range_ctrl; 252 253 range_ctrl = RANGE_CTRL(unit); 254 255 /* The following fields from the Range Control Structure needs to 256 be synced for recovery after Warmboot: 257 range_group_used_bitmap - Used HW masks of the range group */ 258 259 *req_scache_size += sizeof(range_ctrl->range_group_used_bitmap); 260 261 return BCM_E_NONE; 262 } 263 264 /* Function : bcmi_xgs5_range_wb_scache_size_get 265 * Purpose : Returns required scache size 266 * Parameters : unit - (IN) BCM device number. 267 * req_scache_size -(OUT) Required scache size 268 * Returns : BCM_E_XXX 269 */ 270 STATIC int 271 bcmi_xgs5_range_wb_scache_size_get(int unit, int *req_scache_size) 272 { 273 BCM_IF_ERROR_RETURN( 274 bcmi_xgs5_range_wb_scache_size_get_1_0(unit, req_scache_size)); 275 BCM_IF_ERROR_RETURN( 276 bcmi_xgs5_range_wb_scache_size_get_1_1(unit, req_scache_size)); 277 278 return BCM_E_NONE; 279 } 280 281 /* Function : bcmi_xgs5_range_wb_alloc 282 * Purpose : Allocates required scache size for the Range module recovery 283 * Paramters : unit - (IN) BCM device number. 284 * Returns : BCM_E_XXX 285 */ 286 STATIC int bcmi_xgs5_range_wb_alloc(int unit) 287 { 288 int rv = BCM_E_NONE; /* Operation return status. */ 289 int req_scache_size; /* Required Scache Size. */ 290 uint8 *scache_ptr; /* Scache ptr. */ 291 soc_scache_handle_t scache_handle; /* Scache handle. */ 292 293 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_RANGE, 0); 294 295 /*Obtain the required size for scache sync*/ 296 rv = bcmi_xgs5_range_wb_scache_size_get(unit, &req_scache_size); 297 BCM_IF_ERROR_RETURN(rv); 298 299 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 300 req_scache_size, &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 301 302 if (BCM_E_NOT_FOUND == rv) { 303 /* Proceed with Level 1 Warm Boot */ 304 rv = BCM_E_NONE; 305 } 306 307 return rv; 308 } 309 310 /* Function : bcmi_xgs5_range_wb_reinit_1_0 311 * Purpose : Recovers Range warmboot state from scache 312 * Parameters : unit - (IN) Unit number. 313 * scache_ptr - (IN) Pointer to scache 314 * Returns : BCM_E_XXX 315 */ 316 STATIC int 317 bcmi_xgs5_range_wb_reinit_1_0(int unit, uint8 **scache_ptr) 318 { 319 uint8 *scache_p; /* Pointer to scache */ 320 soc_mem_t mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */ 321 int idx; /* Range iteration index */ 322 int index_min; /* Range memory minimum index */ 323 int index_max; /* Range memory maximum index */ 324 uint32 enable; /* Whether the entry is valid or not.*/ 325 uint32 type; /* Range checker type. */ 326 uint32 tbl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Range checker entry buffer. */ 327 _range_t *range_p; /* Pointer to a range. */ 328 _range_t **last_range_p; /* Pointer to the last range reinit. */ 329 bcm_port_config_t pc; /* Port configuration. */ 330 int rv; /* Operation return value */ 331 332 /* Initialize port configuration structure. */ 333 bcm_port_config_t_init(&pc); 334 335 /* Get device port configuration. */ 336 rv = bcm_esw_port_config_get(unit, &pc); 337 if (BCM_FAILURE(rv)) { 338 return rv; 339 } 340 341 scache_p = (uint8 *)(*scache_ptr); 342 343 /* Range module oper mode */ 344 RANGE_CTRL(unit)->range_oper_mode = *scache_p; 345 scache_p++; 346 347 /* Number of Ranges created */ 348 RANGE_CTRL(unit)->num_ranges = *scache_p; 349 scache_p++; 350 351 /* Range resource is being used by which module */ 352 RANGE_CTRL(unit)->range_used_by_module = *scache_p; 353 scache_p++; 354 355 last_range_p = &(RANGE_CTRL(unit)->ranges); 356 index_min = soc_mem_index_min(unit, mem); 357 index_max = soc_mem_index_max(unit, mem); 358 359 for (idx = index_min; idx <= index_max; idx ++) { 360 sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 361 362 /* Create a new range entry for the list */ 363 if ((range_p = sal_alloc(sizeof (*range_p), "range")) == NULL) { 364 return (BCM_E_MEMORY); 365 } 366 sal_memset(range_p, 0, sizeof(_range_t)); 367 368 /* Copy Pipe instance */ 369 range_p->pipe_instance = *scache_p; 370 scache_p++; 371 372 /* Copy the ports bitmap used by the range. */ 373 range_p->ports = pc.all; 374 375 if(RANGE_CTRL(unit)->range_oper_mode == bcmRangeOperModePipeLocal) { 376 /*Fetch the memory based on the pipe instance. */ 377 if (range_p->pipe_instance < SOC_MAX_NUM_PIPES) { 378 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 379 IFP_RANGE_CHECKm, 380 range_p->pipe_instance, 381 &mem)); 382 } else { 383 sal_free(range_p); 384 return BCM_E_INTERNAL; 385 } 386 387 /*In Perpipe mode, only that particular pipe's PBMP will be used*/ 388 range_p->ports = pc.per_pipe[range_p->pipe_instance]; 389 } 390 391 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tbl_entry); 392 if (BCM_FAILURE(rv)) { 393 sal_free(range_p); 394 return rv; 395 } 396 397 soc_mem_field_get(unit, mem, tbl_entry, ENABLEf, &enable); 398 if (enable == 0) { 399 sal_free(range_p); 400 continue; 401 } 402 /* Populate the structure */ 403 /* Get the Range Id */ 404 sal_memcpy(&(range_p->rid), scache_p, sizeof(uint32)); 405 scache_p += sizeof(uint32); 406 407 /* Get the UDF Id mapped to the range */ 408 sal_memcpy(&(range_p->udf_id), scache_p, sizeof(bcm_udf_id_t)); 409 scache_p += sizeof(bcm_udf_id_t); 410 411 /* Get the UDF offset */ 412 range_p->offset = *scache_p; 413 scache_p++; 414 415 /* Get the UDF width */ 416 range_p->width = *scache_p; 417 scache_p++; 418 419 /* Get the hw_index the range maps to */ 420 range_p->hw_index = idx; 421 422 /* Read the min value from the hw */ 423 soc_mem_field_get(unit, mem, tbl_entry, LOWER_BOUNDSf, 424 (uint32 *)&(range_p->min)); 425 426 /* Read the max value from the hw */ 427 soc_mem_field_get(unit, mem, tbl_entry, UPPER_BOUNDSf, 428 (uint32 *)&(range_p->max)); 429 430 /* Read the Range Checker Type from the hw*/ 431 if ((SOC_MEM_FIELD_VALID(unit, mem, FIELD_SELECTf))) { 432 soc_mem_field_get(unit, mem, tbl_entry, FIELD_SELECTf, (uint32 *)&(range_p->rtype)); 433 } else { 434 soc_mem_field_get(unit, mem, tbl_entry, 435 SOURCE_DESTINATION_SELECTf, &type); 436 if (type == 0) { 437 range_p->rtype = bcmRangeTypeL4SrcPort; 438 } else if (type == 1) { 439 range_p->rtype = bcmRangeTypeL4DstPort; 440 } 441 } 442 443 *last_range_p = range_p; 444 last_range_p = &range_p->next; 445 } 446 447 return BCM_E_NONE; 448 } 449 450 /* Function : bcmi_xgs5_range_wb_reinit_1_1 451 * Purpose : Recovers Range warmboot state from scache 452 * Parameters : unit - (IN) Unit number. 453 * scache_ptr - (IN) Pointer to scache 454 * Returns : BCM_E_XXX 455 */ 456 STATIC int 457 bcmi_xgs5_range_wb_reinit_1_1(int unit, uint8 **scache_ptr) 458 { 459 uint8 *scache_p; /* Scache pointer */ 460 461 scache_p = (uint8 *)(*scache_ptr); 462 sal_memcpy(&(RANGE_CTRL(unit)->range_group_used_bitmap), 463 scache_p, 464 (sizeof(SHR_BITDCL) * SOC_MAX_NUM_PIPES)); 465 scache_p++; 466 467 return BCM_E_NONE; 468 469 } 470 471 /* Function : bcmi_xgs5_range_wb_sync_1_0 472 * Purpose : Sync Range module info into scache for version = 1_0 473 * Parameters : unit - (IN) Unit number 474 * scache_ptr - (IN) Pointer to scache 475 * Returns : BCM_E_XXX 476 */ 477 STATIC int 478 bcmi_xgs5_range_wb_sync_1_0(int unit, uint8 **scache_ptr) 479 { 480 uint8 *scache_p; /* Scache pointer */ 481 _range_t *range_p; /* Pointer to a range */ 482 483 scache_p = (uint8 *)(*scache_ptr); 484 485 /* Sync the Range Module Oper Mode */ 486 *scache_p = RANGE_CTRL(unit)->range_oper_mode; 487 scache_p++; 488 489 /* Sync the number of Ranges in the system */ 490 *scache_p = RANGE_CTRL(unit)->num_ranges; 491 scache_p++; 492 493 /* Sync the information on which module uses the Range resources */ 494 *scache_p = RANGE_CTRL(unit)->range_used_by_module; 495 scache_p++; 496 497 range_p = RANGE_CTRL(unit)->ranges; 498 499 while(range_p) { 500 /* The following fields from the Range Structure needs to 501 be synced for recovery : 502 1. pipe_instance to which this range is mapped to. 503 2. Range Id, 504 3. UDF id mapped with the Range, 505 4. Range Offset, 506 5. Range Width, 507 Rest all fields in the range structure can be recovered from the Hardware. 508 */ 509 *scache_p = range_p->pipe_instance; 510 scache_p++; 511 512 sal_memcpy(scache_p, &(range_p->rid), sizeof(uint32)); 513 scache_p += sizeof(uint32); 514 515 sal_memcpy(scache_p, &(range_p->udf_id), sizeof(bcm_udf_id_t)); 516 scache_p += sizeof(bcm_udf_id_t); 517 518 *scache_p = range_p->offset; 519 scache_p++; 520 521 *scache_p = range_p->width; 522 scache_p++; 523 524 range_p = range_p->next; 525 } 526 527 return BCM_E_NONE; 528 } 529 530 531 /* Function : bcmi_xgs5_range_wb_sync_1_1 532 * Purpose : Sync Range module info into scache for version = 1_0 533 * Parameters : unit - (IN) Unit number 534 * scache_ptr - (IN) Pointer to scache 535 * Returns : BCM_E_XXX 536 */ 537 STATIC int 538 bcmi_xgs5_range_wb_sync_1_1(int unit, uint8 **scache_ptr) 539 { 540 uint8 *scache_p; /* Scache pointer */ 541 542 scache_p = (uint8 *)(*scache_ptr); 543 sal_memcpy(scache_p, 544 &(RANGE_CTRL(unit)->range_group_used_bitmap), 545 (sizeof(SHR_BITDCL) * SOC_MAX_NUM_PIPES)); 546 scache_p++; 547 548 return BCM_E_NONE; 549 } 550 551 /* Function : bcmi_xgs5_range_wb_sync 552 * Purpose : Sync Range module warmboot state to scache 553 * Parameters : unit - (IN) Unit number. 554 * Returns : BCM_E_XXX 555 */ 556 int 557 bcmi_xgs5_range_wb_sync(int unit) 558 { 559 uint8 *scache_ptr; /* Scache pointer */ 560 soc_scache_handle_t scache_handle; /* Scache handle */ 561 562 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_RANGE, 0); 563 564 BCM_IF_ERROR_RETURN 565 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 566 0, &scache_ptr, 567 BCM_WB_DEFAULT_VERSION, NULL)); 568 569 BCM_IF_ERROR_RETURN(bcmi_xgs5_range_wb_sync_1_0(unit, &scache_ptr)); 570 BCM_IF_ERROR_RETURN(bcmi_xgs5_range_wb_sync_1_1(unit, &scache_ptr)); 571 return BCM_E_NONE; 572 } 573 574 /* Function : bcmi_xgs5_range_reinit 575 * Purpose : Recovers Range module warmboot state from scache 576 * Parameters : unit - (IN) Unit number. 577 * Returns : BCM_E_XXX 578 */ 579 STATIC int 580 bcmi_xgs5_range_reinit(int unit) 581 { 582 int rv = BCM_E_INTERNAL; /* Operation return value */ 583 uint8 *scache_ptr; /* Scache pointer */ 584 uint16 recovered_ver = 0; /* Recovered warmboot version */ 585 soc_scache_handle_t scache_handle; /* Scache handle */ 586 587 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_RANGE, 0); 588 589 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 590 0, &scache_ptr, 591 BCM_WB_DEFAULT_VERSION, &recovered_ver); 592 593 if (BCM_E_NOT_FOUND == rv) { 594 /* Proceed with Level 1 Warm Boot */ 595 rv = BCM_E_NONE; 596 } else if (BCM_E_NONE == rv) { 597 if (recovered_ver >= BCM_WB_VERSION_1_0) { 598 BCM_IF_ERROR_RETURN(bcmi_xgs5_range_wb_reinit_1_0(unit, &scache_ptr)); 599 } 600 if (recovered_ver >= BCM_WB_VERSION_1_1) { 601 BCM_IF_ERROR_RETURN(bcmi_xgs5_range_wb_reinit_1_1(unit, &scache_ptr)); 602 } 603 } 604 605 return rv; 606 } 607 608 #endif /*BCM_WARM_BOOT_SUPPORT*/ 609 610 /* Function : bcmi_xgs5_range_init 611 * 612 * Purpose : Initialize range module 613 * 614 * Parameters : unit - (IN) Unit number. 615 * 616 * Returns: 617 * BCM_E_NONE : Range Module initialized successfully. 618 * BCM_E_UNIT : Invalid BCM Unit number. 619 * BCM_E_XXX : Standard error code. 620 */ 621 int 622 bcmi_xgs5_range_init( int unit ) 623 { 624 int rv; /* Operation return value */ 625 626 /* Init control structures */ 627 rv = bcmi_xgs5_range_ctrl_init(unit); 628 if (BCM_E_NONE != rv) { 629 LOG_ERROR(BSL_LS_BCM_RANGE, 630 (BSL_META_U(unit, 631 "Range(unit %d) Error: Module ctrl init failed.\n"), 632 unit)); 633 } 634 BCM_IF_ERROR_RETURN(rv); 635 636 #if defined (BCM_WARM_BOOT_SUPPORT) 637 if (SOC_WARM_BOOT(unit)) { 638 rv = bcmi_xgs5_range_reinit(unit); 639 if (BCM_E_NONE != rv) { 640 LOG_ERROR(BSL_LS_BCM_RANGE, 641 (BSL_META_U(unit, 642 "Range(unit %d) Error: Module reinit failed.\n"), 643 unit)); 644 } 645 BCM_IF_ERROR_RETURN(rv); 646 } else 647 #endif /* BCM_WARM_BOOT_SUPPORT */ 648 { 649 rv = bcmi_xgs5_range_hw_init(unit); 650 if (BCM_E_NONE != rv) { 651 LOG_ERROR(BSL_LS_BCM_RANGE, 652 (BSL_META_U(unit, 653 "Range(unit %d) Error: Module hw init failed.\n"), 654 unit)); 655 } 656 BCM_IF_ERROR_RETURN(rv); 657 658 #if defined (BCM_WARM_BOOT_SUPPORT) 659 rv = bcmi_xgs5_range_wb_alloc(unit); 660 if (BCM_E_NONE != rv) { 661 LOG_ERROR(BSL_LS_BCM_RANGE, 662 (BSL_META_U(unit, 663 "Range(unit %d) Error: Module warmboot alloc failed.\n"), 664 unit)); 665 } 666 BCM_IF_ERROR_RETURN(rv); 667 #endif /* BCM_WARM_BOOT_SUPPORT */ 668 } 669 670 return BCM_E_NONE; 671 } 672 673 /* Function : bcmi_xgs5_range_detach 674 * Purpose : Detaches Range module and cleans software state 675 * Parameters : unit - (IN) Unit number 676 * Returns : BCM_E_XXX 677 */ 678 int 679 bcmi_xgs5_range_detach(int unit) 680 { 681 RANGE_INIT_CHECK(unit); 682 683 /* Free resources related to Range module */ 684 BCM_IF_ERROR_RETURN(bcmi_xgs5_range_ctrl_free(unit, RANGE_CTRL(unit))); 685 686 return BCM_E_NONE; 687 } 688 689 /* Function : bcmi_range_id_generate 690 * Purpose : Find an unused range ID. 691 * Parameters : unit - (IN) Unit number. 692 * rid - (OUT) Range ID. 693 * Returns : BCM_E_XXX 694 */ 695 int bcmi_range_id_generate( 696 int unit, 697 bcm_range_t *rid) 698 { 699 bcm_range_config_t range_config; /* Range config structure */ 700 701 *rid = _RANGE_ID_BASE; 702 703 memset(&range_config, 0, sizeof(range_config)); 704 while(*rid <= RANGE_CTRL(unit)->max_ranges) { 705 range_config.rid = *rid; 706 707 if(BCM_E_NONE != (bcmi_xgs5_range_get(unit, &range_config))) 708 { 709 LOG_DEBUG(BSL_LS_BCM_RANGE, 710 (BSL_META_U(unit, 711 "bcmi_range_id_generate: Generated Rid = %d \n"), range_config.rid)); 712 return BCM_E_NONE; 713 } 714 else { 715 (*rid)++; 716 } 717 } 718 719 if (*rid > RANGE_CTRL(unit)->max_ranges) { 720 LOG_DEBUG(BSL_LS_BCM_RANGE, 721 (BSL_META_U(unit, 722 "bcmi_range_id_generate: All ranges are used up\n"))); 723 return BCM_E_RESOURCE; 724 } 725 726 return BCM_E_NONE; 727 } 728 729 /* Function : bcmi_xgs5_range_create 730 * Purpose : Create a Range object 731 * Parameters : unit - (IN) Unit number. 732 * flags - (IN) Flags to create a Range 733 * range_config - (IN) Range config structure. 734 * Returns : BCM_E_XXX 735 */ 736 int bcmi_xgs5_range_create( 737 int unit, 738 int flags, 739 bcm_range_config_t *range_config) 740 { 741 int rv; /* Operation return value */ 742 uint32 max_field_val; /* Max value that the field in memory can hold */ 743 SHR_BITDCL *range_bmap; /* Used indexes map. */ 744 int hw_index = -1; /* Free/matching rang index.*/ 745 int idx_max; /* Loop termination index. */ 746 _range_t *tmp = NULL; /* Range pointer */ 747 soc_mem_t mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */ 748 bcmi_xgs4_udf_offset_info_t *udf_offset_info;/* UDF offset info */ 749 uint16 udf_mask = ~0; /* UDF mask */ 750 bcm_range_oper_mode_t oper_mode = 0; /*Range module operational mode */ 751 int pipe_instance = 0; /* Pipe instance */ 752 753 754 /* Input parameters check */ 755 BCM_IF_NULL_RETURN_PARAM(range_config); 756 757 if (RANGE_CTRL(unit)->range_used_by_module == RANGE_USED_BY_FIELD_MODULE) { 758 LOG_CLI((BSL_META("Range resource is used by FIELD module. \n"))); 759 return BCM_E_UNAVAIL; 760 } 761 762 rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode); 763 LOG_DEBUG(BSL_LS_BCM_RANGE, 764 (BSL_META_U(unit, 765 "bcmi_xgs5_range_create: Error fetching Range Oper Mode \n"))); 766 BCM_IF_ERROR_RETURN(rv); 767 768 rv = bcmi_xgs5_range_validate_port_config (unit, oper_mode, range_config->ports, &pipe_instance) ; 769 LOG_DEBUG(BSL_LS_BCM_RANGE, 770 (BSL_META_U(unit, 771 "bcmi_xgs5_range_create: Error Validating Port Config \n"))); 772 BCM_IF_ERROR_RETURN (rv); 773 774 max_field_val = (1 << soc_mem_field_length(unit, mem, LOWER_BOUNDSf)) - 1 ; 775 if(range_config->min > max_field_val) { 776 return (BCM_E_PARAM); 777 } 778 779 max_field_val = (1 << soc_mem_field_length(unit, mem, UPPER_BOUNDSf)) - 1 ; 780 if(range_config->max > max_field_val) { 781 return (BCM_E_PARAM); 782 } 783 784 if((range_config->rtype < bcmRangeTypeL4SrcPort) 785 || (range_config->rtype > bcmRangeTypeUdf)) { 786 return (BCM_E_PARAM); 787 } 788 789 if (range_config->rtype == bcmRangeTypeUdf) { 790 if (soc_feature(unit, soc_feature_udf_td3x_support)) { 791 uint8 num_chunks; 792 uint32 chunk_bmap; 793 bcm_udf_chunk_info_t udf_chunk_info; 794 795 rv = bcm_esw_udf_chunk_info_get(unit, range_config->udf_id, &udf_chunk_info); 796 BCM_IF_ERROR_RETURN(rv); 797 798 rv = bcm_esw_udf_range_checker_chunk_info_get(unit, &num_chunks, &chunk_bmap); 799 BCM_IF_ERROR_RETURN(rv); 800 801 if (udf_chunk_info.chunk_bmap != chunk_bmap) { 802 return BCM_E_PARAM; 803 } 804 } else if (soc_feature(unit, soc_feature_udf_support)) { 805 /* Check UDF chunk id */ 806 memset(&udf_offset_info, 0, sizeof(udf_offset_info)); 807 808 rv = bcmi_xgs4_udf_offset_node_get(unit, range_config->udf_id, &udf_offset_info); 809 LOG_DEBUG(BSL_LS_BCM_RANGE, 810 (BSL_META_U(unit, 811 "bcmi_xgs5_range_create: Error fetching Udf Offset Node \n"))); 812 BCM_IF_ERROR_RETURN(rv); 813 814 if(!(udf_offset_info->flags & BCMI_XGS4_UDF_OFFSET_RANGE_CHECK)) { 815 /* UDF should be created with Range Check hints */ 816 return (BCM_E_PARAM); 817 } 818 819 /* UDF1 Chunk 2: (47 - 32 bits) which is UDF_OFFSET5*/ 820 if(udf_offset_info->hw_bmap != 0x20) { 821 return BCM_E_PARAM; 822 } 823 } else { 824 return BCM_E_PARAM; 825 } 826 } 827 828 idx_max = soc_mem_index_max(unit, mem); 829 range_bmap = NULL; 830 831 RANGE_MALLOC(range_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges"); 832 if (NULL == range_bmap) { 833 LOG_DEBUG(BSL_LS_BCM_RANGE, 834 (BSL_META_U(unit, 835 "bcmi_xgs5_range_create: Error Allocating memory for range_bmap \n"))); 836 return (BCM_E_MEMORY); 837 } 838 839 /* Search existing ranges */ 840 if (flags & BCM_RANGE_CREATE_WITH_ID) { 841 if ((soc_feature(unit, soc_feature_th3_style_fp)) && 842 (range_config->rid > RANGE_CTRL(unit)->max_ranges)) { 843 sal_free(range_bmap); 844 return (BCM_E_PARAM); 845 } 846 for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) { 847 if(tmp->rid == range_config->rid) { 848 LOG_DEBUG(BSL_LS_BCM_RANGE, 849 (BSL_META_U(unit, 850 "bcmi_xgs5_range_create: Duplicate Range Id \n"))); 851 sal_free(range_bmap); 852 return BCM_E_EXISTS; 853 } 854 } 855 } else { 856 rv = bcmi_range_id_generate(unit, &(range_config->rid)); 857 if (BCM_FAILURE(rv)) { 858 sal_free(range_bmap); 859 return rv; 860 } 861 } 862 863 /* Search existing ranges */ 864 for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) { 865 SHR_BITSET(range_bmap, tmp->hw_index); 866 /* Found an exisiting match so use it. */ 867 if (tmp->rtype == range_config->rtype && tmp->min == range_config->min 868 && tmp->max == range_config->max) { 869 hw_index = tmp->hw_index; 870 } 871 } 872 873 /* If no match found, allocate a new hardware index. */ 874 if (hw_index < 0) { 875 hw_index = soc_mem_index_min(unit, RANGE_CTRL(unit)->range_mem); 876 for (; hw_index <= idx_max; hw_index++) { 877 if (0 == SHR_BITGET(range_bmap, hw_index)) { 878 break; 879 } 880 } 881 /* No hardware indexes left. */ 882 if (hw_index == (idx_max + 1)) { 883 sal_free(range_bmap); 884 return (BCM_E_RESOURCE); 885 } 886 } 887 888 /* Create a new range entry for the list */ 889 if ((tmp = sal_alloc(sizeof(*tmp), "Range")) == NULL) { 890 sal_free(range_bmap); 891 return (BCM_E_MEMORY); 892 } 893 894 895 memset(tmp, 0, sizeof(_range_t)); 896 udf_mask <<= (range_config->width); 897 udf_mask = ~udf_mask; 898 udf_mask <<= range_config->offset; 899 900 tmp->rid = range_config->rid; 901 tmp->hw_index = hw_index; 902 tmp->min = range_config->min; 903 tmp->max = range_config->max; 904 tmp->rtype = range_config->rtype; 905 tmp->offset = range_config->offset; 906 tmp->width = range_config->width; 907 tmp->udf_id = range_config->udf_id; 908 909 if (oper_mode == bcmRangeOperModeGlobal) { 910 tmp->ports = PBMP_ALL(unit); 911 } else if (oper_mode == bcmRangeOperModePipeLocal) { 912 tmp->ports = range_config->ports; 913 } 914 915 tmp->pipe_instance = pipe_instance; 916 917 rv = bcmi_range_check_set(unit, tmp, hw_index, 1, udf_mask); 918 919 if (BCM_FAILURE(rv)) { 920 sal_free(range_bmap); 921 sal_free(tmp); 922 return rv; 923 } 924 925 /* Add to list of range checkers. */ 926 { 927 _range_t *p, **pp; 928 for (pp = &RANGE_CTRL(unit)->ranges; (p = *pp) && tmp->hw_index > p->hw_index; pp = &p->next); 929 (*pp = tmp)->next = p; 930 } 931 932 LOG_DEBUG(BSL_LS_BCM_RANGE, 933 (BSL_META_U(unit, 934 "bcmi_xgs5_range_create: Range Create Successful \n"))); 935 936 sal_free(range_bmap); 937 return rv; 938 939 } 940 941 /* Function : bcmi_xgs5_range_get 942 * Purpose : Retrieve range info given the range ID 943 * Parameters : unit - (IN) Unit number. 944 * range_config - (OUT) range config structure 945 * Returns : BCM_E_XXX 946 */ 947 int bcmi_xgs5_range_get( 948 int unit, 949 bcm_range_config_t *range_config) 950 { 951 int rv; /* Operation return value */ 952 953 /* Input parameters check */ 954 BCM_IF_NULL_RETURN_PARAM(range_config); 955 956 rv = bcmi_xgs5_range_node_get(unit, range_config); 957 958 return rv; 959 } 960 961 /* Function : bcmi_xgs5_range_destroy 962 * Purpose : To destroy range object 963 * Parameters : unit - (IN) Unit number 964 * rid - (IN) Range Id to be destroyed 965 */ 966 int bcmi_xgs5_range_destroy( 967 int unit, 968 bcm_range_t rid) 969 { 970 int rv; /* Operation return value */ 971 _range_t *cur = NULL; /* Ptr to Current range being traversed */ 972 _range_t *prev = NULL; /* Ptr to Previous range traversed */ 973 _range_t range_tmp; /* Range structure */ 974 975 memset(&range_tmp, 0, sizeof(range_tmp)); 976 977 if (RANGE_CTRL(unit)->range_used_by_module == RANGE_USED_BY_FIELD_MODULE) { 978 LOG_CLI((BSL_META("Range resource is used by FIELD module. \n"))); 979 return BCM_E_UNAVAIL; 980 } 981 982 for (cur = RANGE_CTRL(unit)->ranges; cur != NULL; cur = cur->next) { 983 if(cur->rid == rid) { 984 /* Found the node. */ 985 break; 986 } 987 prev = cur; 988 } 989 990 /* Matching node not found */ 991 if (cur == NULL) { 992 return BCM_E_NOT_FOUND; 993 } 994 995 range_tmp.rid = cur->rid; 996 range_tmp.pipe_instance = cur->pipe_instance; 997 range_tmp.hw_index = cur->hw_index; 998 999 rv = bcmi_range_check_set(unit, &range_tmp, range_tmp.hw_index, 0, 0); 1000 1001 if (BCM_FAILURE(rv)) { 1002 return rv; 1003 } 1004 1005 /* Free the cur node */ 1006 if (prev == NULL) { 1007 RANGE_CTRL(unit)->ranges = cur->next; 1008 } else { 1009 prev->next = cur->next; 1010 } 1011 sal_free(cur); 1012 1013 RANGE_CTRL(unit)->num_ranges -= 1; 1014 1015 return BCM_E_NONE; 1016 } 1017 1018 /* Function : bcmi_xgs5_range_node_get 1019 * Purpose : Retrieve range node given the range id 1020 * Parameters : unit - (IN) Unit number 1021 * range_config - (IN) Range config structure 1022 * Returns : BCM_E_XXX 1023 */ 1024 int 1025 bcmi_xgs5_range_node_get( 1026 int unit, 1027 bcm_range_config_t *range_config) 1028 { 1029 _range_t *tmp = NULL; /* Range structure. */ 1030 int rv = BCM_E_NONE; /* Operation return value. */ 1031 1032 tmp = RANGE_CTRL(unit)->ranges; 1033 1034 while (tmp != NULL) { 1035 if(tmp->rid == range_config->rid) { 1036 /* Found the node. */ 1037 break; 1038 } 1039 tmp = tmp->next; 1040 } 1041 1042 if (tmp == NULL) { 1043 rv = BCM_E_NOT_FOUND; 1044 } else { 1045 range_config->rtype = tmp->rtype; 1046 range_config->min = tmp->min; 1047 range_config->max = tmp->max; 1048 range_config->offset = tmp->offset; 1049 range_config->width = tmp->width; 1050 range_config->udf_id = tmp->udf_id; 1051 range_config->ports = tmp->ports; 1052 } 1053 1054 return rv; 1055 1056 } 1057 1058 /* Function : bcmi_range_check_set 1059 * Purpose : Write the range check parameters into the memory 1060 * Parameters : unit - (IN) BCM unit number 1061 * range - (IN) range structure 1062 * hw_index - (IN) Range hw index 1063 * enable - (IN) True or False 1064 * udf_mask - (IN) Udf mask 1065 * Returns : BCM_E_XXX 1066 */ 1067 int 1068 bcmi_range_check_set( 1069 int unit, 1070 _range_t *range, 1071 int hw_index, 1072 int enable, 1073 uint16 udf_mask) 1074 { 1075 int rv; /* Operation return value */ 1076 soc_mem_t range_check_mem = INVALIDm; /* Range Checker Memory ID */ 1077 uint32 tbl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Range checker entry buffer. */ 1078 bcm_range_oper_mode_t oper_mode = 0; /* Range module operational mode */ 1079 uint32 mask = udf_mask; 1080 1081 rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode); 1082 BCM_IF_ERROR_RETURN(rv); 1083 1084 /* Get the memory to which the configurations need to be written to. */ 1085 if (oper_mode == bcmRangeOperModeGlobal) { 1086 range_check_mem = RANGE_CTRL(unit)->range_mem; 1087 } else if(oper_mode == bcmRangeOperModePipeLocal) { 1088 if (range->pipe_instance < SOC_MAX_NUM_PIPES) { 1089 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 1090 IFP_RANGE_CHECKm, 1091 range->pipe_instance, 1092 &range_check_mem)); 1093 } else { 1094 return BCM_E_INTERNAL; 1095 } 1096 1097 } 1098 1099 if (INVALIDm == range_check_mem) { 1100 return (BCM_E_UNAVAIL); 1101 } 1102 1103 /* Index sanity check. */ 1104 if (!soc_mem_index_valid(unit, range_check_mem, hw_index)) { 1105 return (BCM_E_PARAM); 1106 } 1107 1108 /* write range check memory */ 1109 sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1110 1111 /* Set source/destination port selection. */ 1112 soc_mem_field_set(unit, range_check_mem, tbl_entry, 1113 FIELD_SELECTf, &(range->rtype)); 1114 1115 if (SOC_MEM_FIELD_VALID(unit, range_check_mem, ENABLEf)) { 1116 soc_mem_field_set(unit, range_check_mem, tbl_entry, 1117 ENABLEf, (uint32 *) &enable); 1118 } 1119 1120 /* Set range min value. */ 1121 soc_mem_field_set(unit, range_check_mem, tbl_entry, 1122 LOWER_BOUNDSf, (uint32 *) &(range->min)); 1123 1124 /* Set range max value. */ 1125 soc_mem_field_set(unit, range_check_mem, tbl_entry, 1126 UPPER_BOUNDSf, (uint32 *) &(range->max)); 1127 1128 if(range->rtype == bcmRangeTypeUdf) { 1129 soc_mem_field_set(unit, range_check_mem, tbl_entry, 1130 UDF_MASKf, (uint32 *) &(mask)); 1131 } 1132 1133 /* Write entry back to hw. */ 1134 BCM_IF_ERROR_RETURN(soc_mem_write(unit, range_check_mem, 1135 MEM_BLOCK_ALL, hw_index, tbl_entry)); 1136 1137 return BCM_E_NONE; 1138 } 1139 1140 /* Function : bcmi_xgs5_range_hw_clear 1141 * Purpose : Clear hardware 1142 * Parameters : unit - (IN) BCM unit number 1143 * Returns : BCM_E_XXX 1144 */ 1145 int bcmi_xgs5_range_hw_clear( 1146 int unit) 1147 { 1148 /* DO NOT CLEAR HW when in warmboot mode. */ 1149 if (SOC_WARM_BOOT(unit)) { 1150 return (BCM_E_NONE); 1151 } 1152 1153 BCM_IF_ERROR_RETURN(soc_mem_clear(unit, RANGE_CTRL(unit)->range_mem, 1154 COPYNO_ALL, TRUE)); 1155 1156 return BCM_E_NONE; 1157 } 1158 1159 /* 1160 * Function : bcmi_xgs5_range_oper_mode_set 1161 * Purpose : Configure Range Module Operational Mode 1162 * Parameters : unit - (IN) BCM Device number. 1163 * oper_mode - (IN) Range Operational Mode enum value. 1164 * Returns : BCM_E_XXX 1165 */ 1166 int bcmi_xgs5_range_oper_mode_set( 1167 int unit, 1168 bcm_range_oper_mode_t oper_mode) 1169 { 1170 /* Validate input parameters */ 1171 if ((oper_mode != bcmRangeOperModeGlobal) && 1172 (oper_mode != bcmRangeOperModePipeLocal)){ 1173 return BCM_E_PARAM; 1174 } 1175 1176 /* Range Module Init Check */ 1177 RANGE_INIT_CHECK(unit); 1178 1179 /* Verify whether mode is already set */ 1180 if (RANGE_CTRL(unit)->range_oper_mode == oper_mode) { 1181 return BCM_E_NONE; 1182 } 1183 1184 /* Range Module Lock */ 1185 RANGE_LOCK(unit); 1186 1187 if (RANGE_CTRL(unit)->ranges) { 1188 /*Cannot set opermode when there are already existing ranges*/ 1189 return BCM_E_BUSY; 1190 } 1191 1192 /* Hw_clear*/ 1193 BCM_IF_ERROR_RETURN(bcmi_xgs5_range_hw_clear(unit)); 1194 1195 /* Set Oper mode */ 1196 RANGE_CTRL(unit)->range_oper_mode = oper_mode; 1197 1198 /* Unlock Range Module */ 1199 RANGE_UNLOCK(unit); 1200 1201 return BCM_E_NONE; 1202 } 1203 1204 /* 1205 * Function : bcmi_xgs5_range_oper_mode_get 1206 * Purpose : Retrieve Range Module Operational Mode 1207 * Parameters : unit - (IN) BCM Device number. 1208 * mode - (OUT) Reference to Range Operational Mode value. 1209 * Returns : BCM_E_XXX 1210 */ 1211 int bcmi_xgs5_range_oper_mode_get( 1212 int unit, 1213 bcm_range_oper_mode_t *oper_mode) 1214 { 1215 /* Validate Input parameters */ 1216 if (oper_mode == NULL) { 1217 return BCM_E_PARAM; 1218 } 1219 1220 /* Range Module Init Check */ 1221 RANGE_INIT_CHECK(unit); 1222 1223 /* Fetch the mode */ 1224 *oper_mode = RANGE_CTRL(unit)->range_oper_mode; 1225 1226 return BCM_E_NONE; 1227 } 1228 1229 /* 1230 * Function : bcmi_xgs5_range_traverse 1231 * Purpose : Traverse all the ranges in the system, calling a specified 1232 * callback for each one 1233 * Parameters : unit - (IN) Unit number. 1234 * callback - (IN) A pointer to the callback function to call for each range 1235 * user_data - (IN) Pointer to user data to supply in the callback 1236 * Returns : BCM_E_XXX 1237 */ 1238 int bcmi_xgs5_range_traverse( 1239 int unit, 1240 bcm_range_traverse_cb callback, 1241 void *user_data) 1242 { 1243 bcm_range_config_t range_config; /* Range config structure */ 1244 int rv = BCM_E_NONE; /* Operation return value */ 1245 _range_t *tmp = NULL; /* Range structure */ 1246 1247 /* Validate Input Parameters */ 1248 if (NULL == callback) { 1249 return BCM_E_PARAM; 1250 } 1251 1252 /* Range Module Init Check */ 1253 RANGE_INIT_CHECK(unit); 1254 1255 /* Range Module Lock */ 1256 RANGE_LOCK(unit); 1257 1258 tmp = RANGE_CTRL(unit)->ranges; 1259 1260 if (tmp == NULL) { 1261 RANGE_UNLOCK(unit); 1262 return BCM_E_NOT_FOUND; 1263 } 1264 1265 while (tmp) { 1266 memset (&range_config, 0, sizeof(range_config)); 1267 range_config.rid = tmp->rid; 1268 range_config.rtype = tmp->rtype; 1269 range_config.min = tmp->min; 1270 range_config.max = tmp->max; 1271 range_config.offset = tmp->offset; 1272 range_config.width = tmp->width; 1273 range_config.udf_id = tmp->udf_id; 1274 range_config.ports = tmp->ports; 1275 1276 /* Call user callback. */ 1277 rv = (callback)(unit, &range_config, user_data); 1278 if (BCM_FAILURE(rv)) { 1279 break; 1280 } 1281 tmp = tmp->next; 1282 } 1283 1284 RANGE_UNLOCK(unit); 1285 return (BCM_E_NONE); 1286 } 1287 1288 /* Function : bcmi_xgs5_range_get_hw_index 1289 * Purpose : Retrieve hardware index used by a range id 1290 * Parameters : unit - (IN) Unit number. 1291 * rid - (IN) Range ID. 1292 * hw_index - (OUT) hw index 1293 * Returns : BCM_E_XXX 1294 */ 1295 int 1296 bcmi_xgs5_range_get_hw_index( 1297 int unit, 1298 bcm_range_t rid, 1299 int *hw_index) 1300 { 1301 _range_t *tmp = NULL; /* Range structure */ 1302 1303 if(!hw_index) { 1304 return BCM_E_PARAM; 1305 } 1306 1307 for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) { 1308 /* Find the matching Range Id */ 1309 if(tmp->rid == rid) { 1310 *hw_index = tmp->hw_index; 1311 return BCM_E_NONE; 1312 } 1313 } 1314 1315 return BCM_E_NOT_FOUND; 1316 } 1317 1318 /* Function : bcmi_xgs5_range_validate_port_config 1319 * Purpose : Validate the ports config against the Oper mode of the Range module. 1320 * When Global mode is set, only all port bitmaps are allowed. 1321 * When perpipe mode is set, only perpipe port bitmaps are allowed. 1322 * Parameters : unit - (IN) Unit number. 1323 * oper_mode - (IN) Range module Operational mode 1324 * ports - (IN) PBMP given by user 1325 * pipe_instance - (OUT) Pipe number when in PerPipe mode 1326 * Returns : BCM_E_XXX 1327 */ 1328 int bcmi_xgs5_range_validate_port_config ( 1329 int unit, 1330 bcm_range_oper_mode_t oper_mode, 1331 bcm_pbmp_t ports, 1332 int *pipe_instance) 1333 { 1334 int pipe; /* Device pipe iterator. */ 1335 bcm_port_config_t pc; /* Port configuration. */ 1336 int rv; /* Operation return value. */ 1337 1338 /* Initialize port configuration structure. */ 1339 bcm_port_config_t_init(&pc); 1340 1341 /* Get device port configuration. */ 1342 rv = bcm_esw_port_config_get(unit, &pc); 1343 if (BCM_FAILURE(rv)) { 1344 return rv; 1345 } 1346 1347 if (oper_mode == bcmRangeOperModeGlobal) { 1348 /* Global Mode : All ports must be part of IPBM value, if supplied. */ 1349 if (BCM_PBMP_NEQ(pc.all, ports)) { 1350 return BCM_E_PARAM; 1351 } 1352 /* Default value is 0*/ 1353 *pipe_instance = 0; 1354 } 1355 else if (oper_mode == bcmRangeOperModePipeLocal) { 1356 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 1357 if (BCM_PBMP_EQ(pc.per_pipe[pipe], ports)) { 1358 *pipe_instance = pipe; 1359 break; 1360 } 1361 } 1362 if (NUM_PIPE(unit) == pipe) { 1363 return BCM_E_PARAM; 1364 } 1365 } 1366 return (BCM_E_NONE); 1367 } 1368 1369 /* Function : bcmi_xgs5_range_validate_field_stage_oper_mode 1370 * Purpose : Validate Field Stage Oper Mode against Range Module Oper Mode 1371 * Parameters : unit - (IN) Unit number. 1372 * oper_mode - (IN) Operational mode of the Field Group's Stage 1373 * Returns : BCM_E_XXX 1374 */ 1375 int bcmi_xgs5_range_validate_field_stage_oper_mode ( 1376 int unit, 1377 bcm_field_group_oper_mode_t grp_oper_mode) 1378 { 1379 int rv; /* Operation return value */ 1380 bcm_range_oper_mode_t range_oper_mode = 0; /* Range module operational mode */ 1381 1382 rv = bcmi_xgs5_range_oper_mode_get(unit, &range_oper_mode); 1383 BCM_IF_ERROR_RETURN(rv); 1384 1385 if (((grp_oper_mode == bcmFieldGroupOperModeGlobal) && 1386 (range_oper_mode != bcmRangeOperModeGlobal))) 1387 { 1388 return BCM_E_PARAM; 1389 } 1390 1391 return BCM_E_NONE; 1392 } 1393 1394 /* Function : bcmi_xgs5_validate_field_group_instance 1395 * Purpose : Retrieve hardware index used by a range id 1396 * Parameters : unit - (IN) Unit number. 1397 * rid - (IN) Range ID. 1398 * grp_instance - (IN) pipe instance, the field group is configured on 1399 * Returns : BCM_E_XXX 1400 */ 1401 int bcmi_xgs5_range_validate_field_group_instance( 1402 int unit, 1403 bcm_range_t rid, 1404 int grp_instance) 1405 { 1406 int rv; 1407 _range_t *tmp = NULL; /* Range structure */ 1408 bcm_range_oper_mode_t range_oper_mode = 0; /* Range module operational mode */ 1409 1410 tmp = RANGE_CTRL(unit)->ranges; 1411 1412 if (tmp == NULL) { 1413 return BCM_E_NOT_FOUND; 1414 } 1415 1416 rv = bcmi_xgs5_range_oper_mode_get(unit, &range_oper_mode); 1417 BCM_IF_ERROR_RETURN(rv); 1418 1419 if (range_oper_mode == bcmRangeOperModeGlobal) { 1420 return BCM_E_NONE; 1421 } 1422 1423 for (; tmp != NULL; tmp = tmp->next) { 1424 if(tmp->rid == rid) { 1425 if (tmp->pipe_instance == grp_instance) { 1426 return BCM_E_NONE; 1427 } 1428 } 1429 } 1430 1431 return BCM_E_PARAM; 1432 } 1433 1434 /* 1435 * Function : bcmi_xgs5_range_RangeCheckersAPIType_set 1436 * Purpose : Configure Switch Control for RangeCheckersAPIType 1437 * Parameters : unit - (IN) BCM Device number. 1438 * api_type - (IN) Setting this switch control to 0 allows to use only field API's. 1439 * Setting it to 1 allows to use only new range module API's. 1440 * Returns : BCM_E_XXX 1441 */ 1442 int bcmi_xgs5_range_RangeCheckersAPIType_set ( 1443 int unit, 1444 int api_type) 1445 { 1446 1447 RANGE_INIT_CHECK(unit); 1448 1449 if ((api_type < 0) || (api_type >1)) { 1450 /* Value of 0 or 1 only is allowed*/ 1451 return BCM_E_PARAM; 1452 } 1453 1454 if (api_type == 0) { 1455 if (RANGE_CTRL(unit)->ranges) { 1456 LOG_DEBUG(BSL_LS_BCM_RANGE, 1457 (BSL_META_U(unit, 1458 "Range resource is used by RANGE module. \n"))); 1459 return BCM_E_UNAVAIL; 1460 } 1461 RANGE_CTRL(unit)->range_used_by_module = RANGE_USED_BY_FIELD_MODULE; 1462 } 1463 else { 1464 if (_bcm_field_is_stage_range_check_exist(unit, 1465 _BCM_FIELD_STAGE_INGRESS) == BCM_E_EXISTS) { 1466 LOG_DEBUG(BSL_LS_BCM_RANGE, 1467 (BSL_META_U(unit, 1468 "Range resource is used by FIELD module. \n"))); 1469 return BCM_E_UNAVAIL; 1470 } 1471 RANGE_CTRL(unit)->range_used_by_module = RANGE_USED_BY_RANGE_MODULE; 1472 } 1473 1474 return BCM_E_NONE; 1475 } 1476 1477 /* 1478 * Function : bcmi_xgs5_range_RangeCheckersAPIType_get 1479 * Purpose : Configure Switch Control for RangeCheckersAPIType 1480 * Parameters : unit - (IN) BCM Device number. 1481 * api_type - (OUT) Get this switch control value. 1482 * 0 - Only field API's are allowed. 1483 * 1 - Only new range module API's are allowed. 1484 * Returns : BCM_E_XXX 1485 */ 1486 int bcmi_xgs5_range_RangeCheckersAPIType_get ( 1487 int unit, 1488 int *api_type) 1489 { 1490 RANGE_INIT_CHECK(unit); 1491 1492 *api_type = RANGE_CTRL(unit)->range_used_by_module; 1493 return BCM_E_NONE; 1494 } 1495 1496 /* Function to install group bitmap to HW */ 1497 int bcmi_range_group_hw_install(int unit, 1498 uint32 range_group_id, 1499 SHR_BITDCL *range_hw_bmap, 1500 bcm_range_oper_mode_t oper_mode, 1501 int pipe_instance) 1502 { 1503 soc_mem_t mem = INVALIDm; /* Memory for Range check */ 1504 uint32 tbl_entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; /* Range checker entry buffer. */ 1505 1506 if (SOC_MEM_IS_VALID(unit, IFP_RANGE_CHECK_MASKm)) { 1507 mem = (oper_mode == bcmRangeOperModeGlobal) \ 1508 ? (IFP_RANGE_CHECK_MASKm) \ 1509 : (SOC_MEM_UNIQUE_ACC(unit, IFP_RANGE_CHECK_MASKm)[pipe_instance]) ; 1510 sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1511 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, range_group_id, tbl_entry)); 1512 soc_mem_field_set(unit, mem, tbl_entry, MASKf, range_hw_bmap); 1513 1514 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, range_group_id, tbl_entry)); 1515 1516 return BCM_E_NONE; 1517 } 1518 1519 if (oper_mode == bcmRangeOperModeGlobal) { 1520 if (range_group_id < (RANGE_CTRL(unit)->max_groups/2)) { 1521 mem = IFP_RANGE_CHECK_MASK_Am; 1522 } else { 1523 mem = IFP_RANGE_CHECK_MASK_Bm; 1524 } 1525 } else if (oper_mode == bcmRangeOperModePipeLocal) { 1526 if (range_group_id < (RANGE_CTRL(unit)->max_groups/2)) { 1527 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 1528 IFP_RANGE_CHECK_MASK_Am, 1529 pipe_instance, 1530 &mem)); 1531 } else { 1532 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 1533 IFP_RANGE_CHECK_MASK_Bm, 1534 pipe_instance, 1535 &mem)); 1536 } 1537 } else { 1538 return (BCM_E_INTERNAL); 1539 } 1540 1541 1542 /* Write range check memory */ 1543 sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1544 1545 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, tbl_entry)); 1546 1547 soc_mem_field_set(unit, mem, tbl_entry, 1548 range_group_fields[range_group_id], 1549 range_hw_bmap); 1550 1551 /* Write entry back to hw. */ 1552 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, 1553 MEM_BLOCK_ALL, 0, tbl_entry)); 1554 1555 return BCM_E_NONE; 1556 } 1557 1558 /* Function to install group bitmap to HW */ 1559 int bcmi_range_group_hw_get(int unit, 1560 uint32 range_group_id, 1561 SHR_BITDCL *range_hw_bmap, 1562 bcm_range_oper_mode_t oper_mode, 1563 int pipe_instance) 1564 { 1565 soc_mem_t mem = INVALIDm; /* Memory for Range check */ 1566 uint32 tbl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Range checker entry buffer. */ 1567 1568 if (SOC_MEM_IS_VALID(unit, IFP_RANGE_CHECK_MASKm)) { 1569 mem = (oper_mode == bcmRangeOperModeGlobal) \ 1570 ? (IFP_RANGE_CHECK_MASKm) \ 1571 : (SOC_MEM_UNIQUE_ACC(unit, IFP_RANGE_CHECK_MASKm)[pipe_instance]); 1572 sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1573 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, range_group_id, tbl_entry)); 1574 soc_mem_field_get(unit, mem, tbl_entry, MASKf, range_hw_bmap); 1575 return BCM_E_NONE; 1576 } 1577 1578 if (oper_mode == bcmRangeOperModeGlobal) { 1579 if (range_group_id < (RANGE_CTRL(unit)->max_groups/2)) { 1580 mem = IFP_RANGE_CHECK_MASK_Am; 1581 } else { 1582 mem = IFP_RANGE_CHECK_MASK_Bm; 1583 } 1584 } else if (oper_mode == bcmRangeOperModePipeLocal) { 1585 if (range_group_id < (RANGE_CTRL(unit)->max_groups/2)) { 1586 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 1587 IFP_RANGE_CHECK_MASK_Am, 1588 pipe_instance, 1589 &mem)); 1590 } else { 1591 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit, 1592 IFP_RANGE_CHECK_MASK_Bm, 1593 pipe_instance, 1594 &mem)); 1595 } 1596 } else { 1597 return (BCM_E_INTERNAL); 1598 } 1599 1600 /* Write range check memory */ 1601 sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1602 1603 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, tbl_entry)); 1604 1605 soc_mem_field_get(unit, mem, tbl_entry, 1606 range_group_fields[range_group_id], 1607 range_hw_bmap); 1608 return BCM_E_NONE; 1609 } 1610 1611 1612 /* 1613 * This API will help to combine different Range Checkers into a single 1614 * group. It returns a range group identifier that can be passed to 1615 * 'bcm_field_qualify_RangeGroup' API, to qualify a Field entry with 1616 * Range Group match criteria. The Individual RangeCheck conditions and 1617 * its IDs has to be created separately using bcm_range_create API. 1618 */ 1619 int bcmi_xgs5_range_group_create( 1620 int unit, 1621 bcm_range_group_config_t *range_group_config) 1622 { 1623 SHR_BITDCL *range_hw_bmap; /* Used indexes map. */ 1624 SHR_BITDCL *range_hw_bmap_cmp;/* Used indexes map. */ 1625 int idx; /* Loop termination index. */ 1626 _range_t *tmp = NULL; /* Range pointer */ 1627 int idx_max; /* Loop termination index. */ 1628 soc_mem_t mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */ 1629 bcm_range_oper_mode_t oper_mode = 0; /*Range module operational mode */ 1630 int pipe_instance = 0; 1631 uint8 resource_avail = 0; 1632 int rv = 0; 1633 uint32 range_group_id = -1; 1634 1635 /* Input parameters check */ 1636 BCM_IF_NULL_RETURN_PARAM(range_group_config); 1637 1638 rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode); 1639 if (BCM_FAILURE(rv)) { 1640 LOG_DEBUG(BSL_LS_BCM_RANGE, 1641 (BSL_META_U(unit, 1642 "bcmi_xgs5_range_group_create: Error Fetching Range Oper Mode \n"))); 1643 return (rv); 1644 } 1645 1646 rv = bcmi_xgs5_range_validate_port_config(unit, oper_mode, 1647 range_group_config->ports, &pipe_instance); 1648 if (BCM_FAILURE(rv)) { 1649 LOG_DEBUG(BSL_LS_BCM_RANGE, 1650 (BSL_META_U(unit, 1651 "bcmi_xgs5_range_group_create: Error Validating Port Config \n"))); 1652 return (rv); 1653 } 1654 1655 /* Validate resource availability */ 1656 for (idx = 0; idx < RANGE_CTRL(unit)->max_groups; idx++) { 1657 if (0 == SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), idx)) { 1658 resource_avail = 1; 1659 range_group_id = idx; 1660 break; 1661 } 1662 } 1663 if (!resource_avail) { 1664 LOG_CLI((BSL_META("bcmi_xgs5_range_group_create: Range group resources are not available\n"))); 1665 return BCM_E_RESOURCE; 1666 } 1667 1668 idx_max = soc_mem_index_max(unit, mem); 1669 range_hw_bmap = NULL; 1670 1671 RANGE_MALLOC(range_hw_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges"); 1672 if (NULL == range_hw_bmap) { 1673 LOG_DEBUG(BSL_LS_BCM_RANGE, 1674 (BSL_META_U(unit, 1675 "bcmi_xgs5_range_group_create: Error Allocating memory for range_bmap \n"))); 1676 return (BCM_E_MEMORY); 1677 } 1678 1679 range_hw_bmap_cmp = NULL; 1680 1681 RANGE_MALLOC(range_hw_bmap_cmp, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges"); 1682 if (NULL == range_hw_bmap_cmp) { 1683 LOG_DEBUG(BSL_LS_BCM_RANGE, 1684 (BSL_META_U(unit, 1685 "bcmi_xgs5_range_group_create: Error Allocating memory for range_bmap_cmp \n"))); 1686 sal_free(range_hw_bmap); 1687 return (BCM_E_MEMORY); 1688 } 1689 1690 1691 /* Get HW index of range ids in bitmap */ 1692 for (idx = 0; idx < RANGE_CTRL(unit)->max_ranges; idx ++ ) { 1693 if (BCM_RANGE_ID_BMP_TEST(range_group_config->range_bmp, idx)) { 1694 for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) { 1695 if (idx == tmp->rid) { 1696 SHR_BITSET(range_hw_bmap, tmp->hw_index); 1697 } 1698 } 1699 } 1700 } 1701 1702 /* Check if same range group already exists */ 1703 for (idx = 0; idx < RANGE_CTRL(unit)->max_groups; idx++) { 1704 if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), idx)) { 1705 rv = bcmi_range_group_hw_get(unit, idx, range_hw_bmap_cmp, 1706 oper_mode, pipe_instance); 1707 if (BCM_FAILURE(rv)) { 1708 sal_free(range_hw_bmap); 1709 sal_free(range_hw_bmap_cmp); 1710 return rv; 1711 } 1712 1713 if (!(sal_memcmp(range_hw_bmap, range_hw_bmap_cmp, 1714 (SHR_BITALLOCSIZE(idx_max + 1))))) { 1715 sal_free(range_hw_bmap); 1716 sal_free(range_hw_bmap_cmp); 1717 return (BCM_E_EXISTS); 1718 1719 } 1720 } 1721 } 1722 1723 /* Call install function with mask id[range group id] */ 1724 1725 rv = bcmi_range_group_hw_install(unit, range_group_id, 1726 range_hw_bmap, oper_mode, pipe_instance); 1727 if (BCM_SUCCESS(rv)) { 1728 SHR_BITSET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), 1729 range_group_id); 1730 range_group_config->range_group_id = (range_group_id 1731 + (RANGE_CTRL(unit)->max_groups * pipe_instance)); 1732 } 1733 1734 LOG_DEBUG(BSL_LS_BCM_RANGE, 1735 (BSL_META_U(unit, 1736 "bcmi_xgs5_range_group_create: Range Create Successful \n"))); 1737 1738 sal_free(range_hw_bmap); 1739 sal_free(range_hw_bmap_cmp); 1740 return rv; 1741 } 1742 1743 1744 /* 1745 * This API will help to delete the range group created using 1746 * bcm_range_group_create. 1747 */ 1748 int bcmi_xgs5_range_group_delete( 1749 int unit, 1750 bcm_range_group_config_t *range_group_config) 1751 { 1752 SHR_BITDCL *range_hw_bmap; /* Used indexes map. */ 1753 int idx_max; /* Loop termination index. */ 1754 soc_mem_t mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */ 1755 bcm_range_oper_mode_t oper_mode = 0; /*Range module operational mode */ 1756 int pipe_instance = 0; 1757 int rv = 0; 1758 uint32 range_group_id = 0; 1759 1760 /* Input parameters check */ 1761 BCM_IF_NULL_RETURN_PARAM(range_group_config); 1762 1763 rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode); 1764 if (BCM_FAILURE(rv)) { 1765 LOG_DEBUG(BSL_LS_BCM_RANGE, 1766 (BSL_META_U(unit, 1767 "bcmi_xgs5_range_group_delete: Error Fetching Range Oper Mode \n"))); 1768 return (rv); 1769 } 1770 1771 pipe_instance = (range_group_config->range_group_id / RANGE_CTRL(unit)->max_groups); 1772 range_group_id = (range_group_config->range_group_id % RANGE_CTRL(unit)->max_groups); 1773 1774 if ((pipe_instance < 0) || (pipe_instance >= SOC_MAX_NUM_PIPES)) { 1775 LOG_DEBUG(BSL_LS_BCM_RANGE, 1776 (BSL_META_U(unit, 1777 "bcmi_xgs5_range_group_delete: Error Validating Range Group ID \n"))); 1778 return (BCM_E_INTERNAL); 1779 } 1780 1781 BCM_IF_ERROR_RETURN (rv); 1782 1783 idx_max = soc_mem_index_max(unit, mem); 1784 range_hw_bmap = NULL; 1785 1786 RANGE_MALLOC(range_hw_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges"); 1787 if (NULL == range_hw_bmap) { 1788 LOG_DEBUG(BSL_LS_BCM_RANGE, 1789 (BSL_META_U(unit, 1790 "bcmi_xgs5_range_group_delete: Error Allocating memory for range_bmap \n"))); 1791 return (BCM_E_MEMORY); 1792 } 1793 1794 if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), 1795 range_group_id)) { 1796 rv = bcmi_range_group_hw_install(unit, range_group_id, 1797 range_hw_bmap, oper_mode, pipe_instance); 1798 SHR_BITCLR(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), 1799 range_group_id); 1800 } else { 1801 rv = BCM_E_NOT_FOUND; 1802 } 1803 1804 LOG_DEBUG(BSL_LS_BCM_RANGE, 1805 (BSL_META_U(unit, 1806 "bcmi_xgs5_range_group_delete: Range Create Successful \n"))); 1807 1808 sal_free(range_hw_bmap); 1809 return rv; 1810 } 1811 1812 /* 1813 * This API will help to update the range IDs in the range group created 1814 * using bcm_range_group_create. 1815 */ 1816 int bcmi_xgs5_range_group_update( 1817 int unit, 1818 bcm_range_group_config_t *range_group_config) 1819 { 1820 SHR_BITDCL *range_hw_bmap; /* Used indexes map. */ 1821 SHR_BITDCL *range_hw_bmap_cmp;/* Used indexes map. */ 1822 int idx; /* Loop termination index. */ 1823 _range_t *tmp = NULL; /* Range pointer */ 1824 int idx_max; /* Loop termination index. */ 1825 soc_mem_t mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */ 1826 bcm_range_oper_mode_t oper_mode = 0; /*Range module operational mode */ 1827 int pipe_instance = 0; 1828 int rv = 0; 1829 uint32 range_group_id = 0; 1830 1831 /* Input parameters check */ 1832 BCM_IF_NULL_RETURN_PARAM(range_group_config); 1833 1834 rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode); 1835 if (BCM_FAILURE(rv)) { 1836 LOG_DEBUG(BSL_LS_BCM_RANGE, 1837 (BSL_META_U(unit, 1838 "bcmi_xgs5_range_group_update: Error Fetching Range Oper Mode \n"))); 1839 return (rv); 1840 } 1841 1842 pipe_instance = (range_group_config->range_group_id / RANGE_CTRL(unit)->max_groups); 1843 range_group_id = (range_group_config->range_group_id % RANGE_CTRL(unit)->max_groups); 1844 1845 if ((pipe_instance < 0) || (pipe_instance >= SOC_MAX_NUM_PIPES)) { 1846 LOG_DEBUG(BSL_LS_BCM_RANGE, 1847 (BSL_META_U(unit, 1848 "bcmi_xgs5_range_group_update: Error Validating Range Group ID \n"))); 1849 return (BCM_E_INTERNAL); 1850 } 1851 1852 idx_max = soc_mem_index_max(unit, mem); 1853 range_hw_bmap = NULL; 1854 1855 RANGE_MALLOC(range_hw_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges"); 1856 if (NULL == range_hw_bmap) { 1857 LOG_DEBUG(BSL_LS_BCM_RANGE, 1858 (BSL_META_U(unit, 1859 "bcmi_xgs5_range_group_update: Error Allocating memory for range_bmap \n"))); 1860 return (BCM_E_MEMORY); 1861 } 1862 1863 range_hw_bmap_cmp = NULL; 1864 1865 RANGE_MALLOC(range_hw_bmap_cmp, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges"); 1866 if (NULL == range_hw_bmap_cmp) { 1867 LOG_DEBUG(BSL_LS_BCM_RANGE, 1868 (BSL_META_U(unit, 1869 "bcmi_xgs5_range_group_update: Error Allocating memory for range_bmap_cmp \n"))); 1870 sal_free(range_hw_bmap); 1871 return (BCM_E_MEMORY); 1872 } 1873 1874 /* Get HW index of range ids in bitmap */ 1875 for (idx = 0; idx < RANGE_CTRL(unit)->max_ranges; idx ++ ) { 1876 if (BCM_RANGE_ID_BMP_TEST(range_group_config->range_bmp, idx)) { 1877 for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) { 1878 if (idx == tmp->rid) { 1879 SHR_BITSET(range_hw_bmap, tmp->hw_index); 1880 } 1881 } 1882 } 1883 } 1884 1885 /* Check if same range group already exists */ 1886 for (idx = 0; idx < RANGE_CTRL(unit)->max_groups; idx++) { 1887 if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), idx)) { 1888 rv = bcmi_range_group_hw_get(unit, idx, range_hw_bmap_cmp, 1889 oper_mode, pipe_instance); 1890 if (BCM_FAILURE(rv)) { 1891 sal_free(range_hw_bmap); 1892 sal_free(range_hw_bmap_cmp); 1893 return rv; 1894 } 1895 1896 if (!(sal_memcmp(range_hw_bmap, range_hw_bmap_cmp, 1897 (SHR_BITALLOCSIZE(idx_max + 1))))) { 1898 sal_free(range_hw_bmap); 1899 sal_free(range_hw_bmap_cmp); 1900 return (BCM_E_EXISTS); 1901 1902 } 1903 } 1904 } 1905 1906 if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), 1907 range_group_id)) { 1908 rv = bcmi_range_group_hw_install(unit, range_group_id, 1909 range_hw_bmap, oper_mode, pipe_instance); 1910 } else { 1911 rv = BCM_E_NOT_FOUND; 1912 } 1913 1914 LOG_DEBUG(BSL_LS_BCM_RANGE, 1915 (BSL_META_U(unit, 1916 "bcmi_xgs5_range_group_update: Range Create Successful \n"))); 1917 1918 sal_free(range_hw_bmap); 1919 sal_free(range_hw_bmap_cmp); 1920 return rv; 1921 1922 } 1923 1924 /* 1925 * This API will help to fetch the range group configuration created 1926 * using bcm_range_group_create. 1927 */ 1928 int bcmi_xgs5_range_group_get( 1929 int unit, 1930 bcm_range_group_config_t *range_group_config) 1931 { 1932 SHR_BITDCL *range_hw_bmap; /* Used indexes map. */ 1933 int idx; /* Loop termination index. */ 1934 _range_t *tmp = NULL; /* Range pointer */ 1935 int idx_max; /* Loop termination index. */ 1936 soc_mem_t mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */ 1937 bcm_range_oper_mode_t oper_mode = 0; /*Range module operational mode */ 1938 int pipe_instance = 0; 1939 int rv = 0; 1940 uint32 range_group_id = 0; 1941 1942 /* Input parameters check */ 1943 BCM_IF_NULL_RETURN_PARAM(range_group_config); 1944 1945 rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode); 1946 if (BCM_FAILURE(rv)) { 1947 LOG_DEBUG(BSL_LS_BCM_RANGE, 1948 (BSL_META_U(unit, 1949 "bcmi_xgs5_range_group_get: Error Fetching Range Oper Mode \n"))); 1950 return (rv); 1951 } 1952 1953 pipe_instance = (range_group_config->range_group_id / RANGE_CTRL(unit)->max_groups); 1954 range_group_id = (range_group_config->range_group_id % RANGE_CTRL(unit)->max_groups); 1955 1956 if ((pipe_instance < 0) || (pipe_instance >= SOC_MAX_NUM_PIPES)) { 1957 LOG_DEBUG(BSL_LS_BCM_RANGE, 1958 (BSL_META_U(unit, 1959 "bcmi_xgs5_range_group_get: Error Validating Range Group ID \n"))); 1960 return (BCM_E_INTERNAL); 1961 } 1962 1963 idx_max = soc_mem_index_max(unit, mem); 1964 range_hw_bmap = NULL; 1965 1966 RANGE_MALLOC(range_hw_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges"); 1967 if (NULL == range_hw_bmap) { 1968 LOG_DEBUG(BSL_LS_BCM_RANGE, 1969 (BSL_META_U(unit, 1970 "bcmi_xgs5_range_group_get: Error Allocating memory for range_bmap \n"))); 1971 return (BCM_E_MEMORY); 1972 } 1973 1974 if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), 1975 range_group_id)) { 1976 rv = bcmi_range_group_hw_get(unit, range_group_id, 1977 range_hw_bmap, oper_mode, pipe_instance); 1978 } else { 1979 rv = BCM_E_NOT_FOUND; 1980 } 1981 1982 /* Convert hw bmap to range id bmap */ 1983 for (idx = 0; idx < RANGE_CTRL(unit)->max_ranges; idx ++ ) { 1984 if (SHR_BITGET(range_hw_bmap, idx)) { 1985 for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) { 1986 if (idx == tmp->hw_index) { 1987 BCM_RANGE_ID_BMP_ADD(range_group_config->range_bmp, tmp->rid); 1988 } 1989 } 1990 } 1991 } 1992 1993 LOG_DEBUG(BSL_LS_BCM_RANGE, 1994 (BSL_META_U(unit, 1995 "bcmi_xgs5_range_group_get: Range Create Successful \n"))); 1996 1997 sal_free(range_hw_bmap); 1998 return rv; 1999 } 2000 2001 /* Function : bcmi_xgs5_range_group_hw_idx_get 2002 * Purpose : Fetch Range Group HW Index 2003 * Parameters : unit - (IN) Unit number. 2004 * range_group_id - (IN) Range Group ID. 2005 pipe_id - (IN) Pipe Instance 2006 hw_index - (OUT) Hardware index 2007 * Returns : BCM_E_XXX 2008 */ 2009 int bcmi_xgs5_range_group_hw_idx_get( 2010 int unit, 2011 uint8 range_grp_id, 2012 uint8 pipe_id, 2013 uint8 *hw_index) 2014 { 2015 uint32 range_group_id = 0; 2016 int pipe_instance = 0; 2017 bcm_range_oper_mode_t oper_mode = 0; /*Range module operational mode */ 2018 int rv = BCM_E_NONE; 2019 2020 if (range_grp_id > ((RANGE_CTRL(unit)->max_groups * SOC_MAX_NUM_PIPES) - 1)) { 2021 return BCM_E_PARAM; 2022 } 2023 2024 pipe_instance = (range_grp_id / RANGE_CTRL(unit)->max_groups); 2025 range_group_id = (range_grp_id % RANGE_CTRL(unit)->max_groups); 2026 2027 rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode); 2028 if (BCM_FAILURE(rv)) { 2029 LOG_DEBUG(BSL_LS_BCM_RANGE, 2030 (BSL_META_U(unit, 2031 "bcmi_xgs5_range_group_hw_idx_get: Error Fetching Range Oper Mode \n"))); 2032 return (rv); 2033 } 2034 2035 if ((pipe_instance != pipe_id) && (oper_mode == bcmRangeOperModePipeLocal)) { 2036 LOG_DEBUG(BSL_LS_BCM_RANGE, 2037 (BSL_META_U(unit, 2038 "bcmi_xgs5_range_group_hw_idx_get: Error Validating Pipe Instance \n"))); 2039 return BCM_E_PARAM; 2040 } 2041 2042 if ((pipe_instance < 0) || (pipe_instance >= SOC_MAX_NUM_PIPES)) { 2043 LOG_DEBUG(BSL_LS_BCM_RANGE, 2044 (BSL_META_U(unit, 2045 "bcmi_xgs5_range_group_hw_idx_get: Error Validating Range Group ID \n"))); 2046 return BCM_E_PARAM; 2047 } 2048 2049 if (!(SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) 2050 + pipe_instance), range_group_id))) { 2051 return BCM_E_PARAM; 2052 } 2053 2054 *hw_index = range_group_id; 2055 return rv; 2056 } 2057 2058 /* Function : bcmi_xgs5_range_group_id_get 2059 * Purpose : Fetch Range Group Id 2060 * Parameters : unit - (IN) Unit number. 2061 pipe_id - (IN) Pipe Instance. 2062 hw_index - (IN) Hardware index 2063 * range_group_id - (OUT) Range Group ID. 2064 * Returns : BCM_E_XXX 2065 */ 2066 int bcmi_xgs5_range_group_id_get( 2067 int unit, 2068 uint8 pipe_id, 2069 uint8 *range_grp_id) 2070 { 2071 int rv = BCM_E_NONE; 2072 bcm_range_oper_mode_t oper_mode = 0; /*Range module operational mode */ 2073 2074 rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode); 2075 if (BCM_FAILURE(rv)) { 2076 LOG_DEBUG(BSL_LS_BCM_RANGE, 2077 (BSL_META_U(unit, 2078 "bcmi_xgs5_range_group_hw_idx_get: Error Fetching Range Oper Mode \n"))); 2079 return (rv); 2080 } 2081 2082 if (oper_mode == bcmRangeOperModePipeLocal) { 2083 *range_grp_id = (*range_grp_id) 2084 + (RANGE_CTRL(unit)->max_groups * pipe_id); 2085 } 2086 2087 return rv; 2088 } 2089