bcmx.c (58209B)
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: bcmx.c 8 * Purpose: Basic infrastructure code for BCMX 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <shared/alloc.h> 14 #include <sal/core/libc.h> 15 16 #include <bcmx/lport.h> 17 #include <bcmx/bcmx.h> 18 #include <bcmx/rx.h> 19 #include <bcmx/l2.h> 20 #include <bcmx/link.h> 21 22 #include <bcm/port.h> 23 #include <bcm/stack.h> 24 #include <bcm_int/rpc/rlink.h> 25 26 #include "bcmx_int.h" 27 #include "api_ref.h" 28 29 30 /* 31 * BCMX Port Information 32 * 33 * BCMX Port information will be kept in a 'hash' table 34 * rather than an array indexed by the 'lport' value. This allows 35 * BCMX interfaces to take a 'gport' any place where 'lport' is present. 36 * 37 * The GPORT types that are used for BCMX ports are: 38 * MODPORT - For devices with module id 39 * DEVPORT - For devices with NO module id 40 */ 41 42 /* BCMX Port Information Hash Table */ 43 #define BCMX_PORT_HASH_COUNT 73 /* Prime */ 44 #define BCMX_PORT_HASH_INDEX(_key) \ 45 (((unsigned int)(_key)) % BCMX_PORT_HASH_COUNT) 46 47 typedef struct _bcmx_port_info_s _bcmx_port_info_t; 48 49 /* List to maintain ports in the order in which ports were added in BCMX */ 50 typedef struct _bcmx_port_list_s { 51 _bcmx_port_info_t *prev; 52 _bcmx_port_info_t *next; 53 } _bcmx_port_list_t; 54 55 /* Hash Table Data Structure */ 56 struct _bcmx_port_info_s { 57 bcmx_lport_t lport; /* Logical port number, hash key*/ 58 _bcmx_port_t port; /* BCMX port data struct */ 59 _bcmx_port_info_t *prev; 60 _bcmx_port_info_t *next; 61 _bcmx_port_list_t list; /* Use for ordered port list */ 62 }; 63 64 /* Port Information Hash Table */ 65 static _bcmx_port_info_t *_bcmx_port_info[BCMX_PORT_HASH_COUNT]; 66 67 /* Port List */ 68 static _bcmx_port_info_t *_bcmx_port_list_first = NULL; 69 static _bcmx_port_info_t *_bcmx_port_list_last = NULL; 70 71 72 /* 73 * Port Mapping - DEVPORT hash 74 * 75 * Definitions for faster search based on gport DEVPORT hash key 76 * (key is composed of unit/port) 77 */ 78 typedef struct _bcmx_devport_hash_s _bcmx_devport_hash_t; 79 struct _bcmx_devport_hash_s { 80 bcm_gport_t key; /* Hash key, gport DEVPORT */ 81 _bcmx_port_info_t *port_info; /* Reference to port info object */ 82 _bcmx_devport_hash_t *next; 83 _bcmx_devport_hash_t *prev; 84 }; 85 static _bcmx_devport_hash_t *_bcmx_devport_hash[BCMX_PORT_HASH_COUNT]; 86 87 88 /* 89 * BCMX Uport <-> Lport Mapping 90 */ 91 _bcmx_uport_hash_t *_bcmx_uport_hash[BCMX_UPORT_HASH_COUNT]; 92 93 /* Application definition for Uport */ 94 bcmx_uport_create_f bcmx_uport_create; 95 bcmx_lport_remove_notify_f bcmx_lport_remove_notify; 96 97 /* 98 * Default Uport 99 * 100 * If application 'uport' definition is not provided, the default 101 * uport is applied (see _bcmx_uport_create_default). 102 * The default uport is of type 'int'. 103 * Values are assigned starting with the lowest unused integer number 104 * (this assignment logic is the same* as the one used before 105 * 'lport' was converted to 'gport'). 106 */ 107 #define BCMX_UPORT_TO_INT(_uport) PTR_TO_INT(_uport) 108 109 110 /* 111 * BCMX unit list 112 */ 113 int bcmx_unit_list[BCMX_UNITS_MAX]; 114 int bcmx_unit_count; 115 116 /* Cache for device->CPU port map */ 117 bcmx_lport_t bcmx_lport_local_cpu[BCM_CONTROL_MAX]; 118 119 sal_mutex_t bcmx_config_lock; 120 121 122 /* 123 * BCMX generic conversion routines for destinations 124 * 125 * Check macros 126 */ 127 #define BCMX_DEST_MODID_PORT_FLAG_CHECK(_flags) \ 128 if (((_flags) | BCMX_DEST_GPORT_AWARE) != BCMX_DEST_GPORT_AWARE) { \ 129 return BCM_E_PARAM; \ 130 } 131 132 #define BCMX_DEST_UNIT_PORT_FLAG_CHECK(_flags) \ 133 BCMX_DEST_MODID_PORT_FLAG_CHECK(_flags) 134 135 136 137 /* 138 * DEPRECATED 139 */ 140 int bcmx_lport_max = 0; /* Number of lports supported */ 141 _bcmx_port_t *_bcmx_port; 142 bcmx_lport_t _bcmx_lport_first = BCMX_LPORT_INVALID; 143 bcmx_uport_t _bcmx_uport_invalid = BCMX_UPORT_INVALID; 144 145 146 147 /**************************************************************** 148 * Internal Functions 149 */ 150 151 STATIC INLINE void 152 _bcmx_uport_remove(bcmx_uport_t uport) 153 { 154 _bcmx_uport_hash_t *uph; 155 int h_idx; 156 157 h_idx = BCMX_UPORT_HASH(uport); 158 uph = _bcmx_uport_hash[h_idx]; 159 while (uph != NULL) { 160 if (BCMX_UPORT_EQ(uph->uport, uport)) { 161 break; 162 } 163 uph = uph->next; 164 } 165 166 if (uph == NULL) { /* Not there */ 167 return; 168 } 169 170 /* Is this the first entry? */ 171 if (uph->prev == NULL) { /* Yes */ 172 _bcmx_uport_hash[h_idx] = uph->next; 173 } else { 174 uph->prev->next = uph->next; 175 } 176 177 /* Is this the last entry? */ 178 if (uph->next != NULL) { /* No */ 179 uph->next->prev = uph->prev; 180 } 181 182 sal_free(uph); 183 } 184 185 STATIC INLINE _bcmx_uport_hash_t * 186 _bcmx_uport_add(bcmx_uport_t uport, bcmx_lport_t lport) 187 { 188 _bcmx_uport_hash_t *uph; 189 int h_idx; 190 191 h_idx = BCMX_UPORT_HASH(uport); 192 193 uph = sal_alloc(sizeof(_bcmx_uport_hash_t), "bcmx_uport_add"); 194 if (uph == NULL) { 195 return NULL; 196 } 197 198 uph->uport = uport; 199 uph->lport = lport; 200 uph->prev = NULL; 201 uph->next = _bcmx_uport_hash[h_idx]; 202 if (uph->next != NULL) { 203 uph->next->prev = uph; 204 } 205 _bcmx_uport_hash[h_idx] = uph; 206 207 return uph; 208 } 209 210 211 /* 212 * Function: 213 * _bcmx_uport_create_default 214 * Purpose: 215 * Return a new user port number using the default 216 * definition for uport (integer). 217 * Parameters: 218 * none 219 * Returns: 220 * A new 'uport' value. 221 * Notes: 222 * Assumes lock is held. 223 */ 224 STATIC bcmx_uport_t 225 _bcmx_uport_create_default(void) 226 { 227 int i = 0; 228 229 /* Find lowest unused uport integer */ 230 while(bcmx_uport_to_lport(BCMX_UPORT_CAST(i)) != BCMX_LPORT_INVALID) { 231 i++; 232 } 233 234 return BCMX_UPORT_CAST(i); 235 } 236 237 238 /* 239 * Function: 240 * _bcmx_devport_hash_add 241 * Purpose: 242 * Add the port information reference to the devport hash 243 * table array. 244 * Parameters: 245 * unit - Device number 246 * port - Device port number 247 * port_info - Pointer to port information object 248 * Returns: 249 * Pointer to added devport hash, if successful. 250 * NULL, on failure to allocate struct. 251 * Notes: 252 * Assumes lock is held. 253 */ 254 STATIC _bcmx_devport_hash_t * 255 _bcmx_devport_hash_add(int unit, bcm_port_t port, _bcmx_port_info_t *port_info) 256 { 257 bcm_gport_t key; 258 int index; 259 _bcmx_devport_hash_t *devport; 260 261 if ((devport = sal_alloc(sizeof(_bcmx_devport_hash_t), 262 "bcmx_devport_add")) == NULL) { 263 return NULL; 264 } 265 266 BCM_GPORT_DEVPORT_SET(key, unit, port); 267 index = BCMX_PORT_HASH_INDEX(key); 268 269 devport->key = key; 270 devport->port_info = port_info; 271 devport->prev = NULL; 272 devport->next = _bcmx_devport_hash[index]; 273 if (devport->next != NULL) { 274 devport->next->prev = devport; 275 } 276 _bcmx_devport_hash[index] = devport; 277 278 return devport; 279 } 280 281 282 /* 283 * Function: 284 * _bcmx_devport_hash_remove 285 * Purpose: 286 * Remove devport hash information for given BCM unit/port. 287 * Parameters: 288 * unit - Device number 289 * port - Device port number 290 * Returns: 291 * None 292 * Notes: 293 * Assumes lock is held. 294 */ 295 STATIC void 296 _bcmx_devport_hash_remove(int unit, bcm_port_t port) 297 { 298 bcm_gport_t key; 299 int index; 300 _bcmx_devport_hash_t *devport; 301 302 BCM_GPORT_DEVPORT_SET(key, unit, port); 303 index = BCMX_PORT_HASH_INDEX(key); 304 305 306 devport = _bcmx_devport_hash[index]; 307 while (devport != NULL) { 308 if (devport->key == key) { 309 break; 310 } 311 devport = devport->next; 312 } 313 314 if (devport == NULL) { /* Not found */ 315 return; 316 } 317 318 /* Check first entry */ 319 if (devport->prev == NULL) { /* Yes */ 320 _bcmx_devport_hash[index] = devport->next; 321 } else { 322 devport->prev->next = devport->next; 323 } 324 325 /* Check last entry */ 326 if (devport->next != NULL) { /* No */ 327 devport->next->prev = devport->prev; 328 } 329 330 sal_free(devport); 331 } 332 333 334 /* 335 * Function: 336 * _bcmx_port_info_find 337 * Purpose: 338 * Find the BCMX port information for a given lport key. 339 * Parameters: 340 * lport - BCMX logical port number (gport format) 341 * tbl_index - (OUT) Table array index for given port 342 * Returns: 343 * Pointer to BCXM port information struct, if key was found. 344 * NULL, on failure to find key. 345 * Notes: 346 * Assumes lock is held. 347 */ 348 STATIC _bcmx_port_info_t* 349 _bcmx_port_info_find(bcmx_lport_t lport, int *tbl_index) 350 { 351 _bcmx_port_info_t *port_info = NULL; 352 353 *tbl_index = BCMX_PORT_HASH_INDEX(lport); 354 355 port_info = _bcmx_port_info[*tbl_index]; 356 while (port_info != NULL) { 357 if (port_info->lport == lport) { 358 break; 359 } 360 port_info = port_info->next; 361 } 362 363 return port_info; 364 } 365 366 367 /* 368 * Function: 369 * _bcmx_port_add 370 * Purpose: 371 * Add the port information into the BCMX port hash 372 * table array. 373 * Parameters: 374 * unit - Device number 375 * port - Device port number 376 * flags - Port flags BCMX_PORT_F_xxx 377 * Returns: 378 * BCM_E_NONE - Success 379 * BCM_E_EXISTS - Port already exist in BCMX port table 380 * BCM_E_RESOURCE - Could not allocate port information structure 381 * Notes: 382 * Assumes lock is held. 383 */ 384 STATIC int 385 _bcmx_port_add(int unit, bcm_port_t port, bcm_gport_t lport, uint32 flags) 386 { 387 int index; 388 bcm_port_t modport; 389 bcm_module_t modid; 390 bcmx_uport_t uport; 391 _bcmx_port_info_t *port_info; 392 393 /* BCMX lport should unique */ 394 if (_bcmx_port_info_find(lport, &index) != NULL) { 395 return BCM_E_EXISTS; 396 } 397 398 if ((port_info = sal_alloc(sizeof(_bcmx_port_info_t), 399 "bcmx_port_info_add")) == NULL) { 400 return BCM_E_RESOURCE; 401 } 402 403 if (BCM_GPORT_IS_MODPORT(lport)) { 404 modport = BCM_GPORT_MODPORT_PORT_GET(lport); 405 modid = BCM_GPORT_MODPORT_MODID_GET(lport); 406 } else { 407 modport = port; 408 modid = -1; 409 } 410 411 /* Set uport */ 412 if (bcmx_uport_create != NULL) { 413 uport = bcmx_uport_create(lport, unit, port, flags); 414 } else { 415 /* Use default uport assignment */ 416 uport = _bcmx_uport_create_default(); 417 } 418 /* Update uport <-> lport map table */ 419 if (_bcmx_uport_add(uport, lport) == NULL) { 420 LOG_WARN(BSL_LS_BCMX_COMMON, 421 (BSL_META_U(unit, 422 "BCMX: Failed to add uport hash, " 423 "u %d, p %d\n"), unit, port)); 424 } 425 426 /* Set Cache CPU port */ 427 if (flags & BCMX_PORT_F_CPU) { 428 bcmx_lport_local_cpu[unit] = lport; 429 } 430 431 /* Set BCMX port information */ 432 port_info->lport = lport; 433 port_info->port.bcm_unit = unit; 434 port_info->port.bcm_port = port; 435 port_info->port.modid = modid; 436 port_info->port.modport = modport; 437 port_info->port.uport = uport; 438 port_info->port.flags = flags; 439 440 /* Update hash table link list */ 441 index = BCMX_PORT_HASH_INDEX(lport); 442 port_info->prev = NULL; 443 port_info->next = _bcmx_port_info[index]; 444 if (port_info->next != NULL) { 445 port_info->next->prev = port_info; 446 } 447 _bcmx_port_info[index] = port_info; 448 449 /* Update port list */ 450 if (_bcmx_port_list_first == NULL) { 451 _bcmx_port_list_first = port_info; 452 } 453 if (_bcmx_port_list_last != NULL) { 454 _bcmx_port_list_last->list.next = port_info; 455 } 456 port_info->list.prev = _bcmx_port_list_last; 457 port_info->list.next = NULL; 458 _bcmx_port_list_last = port_info; 459 460 /* Update devport hash table */ 461 if (_bcmx_devport_hash_add(unit, port, port_info) == NULL) { 462 LOG_WARN(BSL_LS_BCMX_COMMON, 463 (BSL_META_U(unit, 464 "BCMX: Failed to add devport hash, " 465 "u %d, p %d\n"), unit, port)); 466 } 467 468 return BCM_E_NONE; 469 } 470 471 472 /* 473 * Function: 474 * _bcmx_port_info_remove_by_unit 475 * Purpose: 476 * Remove all port information associated with the given unit. 477 * Parameters: 478 * unit - Device number to remove ports for 479 * Returns: 480 * BCM_E_NONE - Success 481 * Notes: 482 * Assumes lock is held. 483 */ 484 STATIC int 485 _bcmx_port_info_remove_by_unit(int unit) 486 { 487 int i; 488 _bcmx_port_info_t *port_info; 489 _bcmx_port_info_t *next; 490 491 /* Check each link list in port table */ 492 for (i = 0; i < BCMX_PORT_HASH_COUNT; i++) { 493 494 port_info = _bcmx_port_info[i]; 495 496 /* Check each entry in link list */ 497 while (port_info != NULL) { 498 next = port_info->next; 499 500 /* Remove port if unit matches */ 501 if (port_info->port.bcm_unit == unit) { 502 503 /* Clear uport */ 504 if (bcmx_lport_remove_notify != NULL) { 505 bcmx_lport_remove_notify(port_info->lport, 506 port_info->port.uport); 507 } 508 /* Update uport <-> lport map table */ 509 _bcmx_uport_remove(port_info->port.uport); 510 511 /* Update devport hash table */ 512 _bcmx_devport_hash_remove(port_info->port.bcm_unit, 513 port_info->port.bcm_port); 514 515 /* Update hash table */ 516 /* Check first entry */ 517 if (port_info->prev == NULL) { /* Yes */ 518 _bcmx_port_info[i] = port_info->next; 519 } else { 520 port_info->prev->next = port_info->next; 521 } 522 /* Check last entry */ 523 if (port_info->next != NULL) { /* No */ 524 port_info->next->prev = port_info->prev; 525 } 526 527 /* Update port list */ 528 if (_bcmx_port_list_first == port_info) { 529 _bcmx_port_list_first = port_info->list.next; 530 } 531 if (_bcmx_port_list_last == port_info) { 532 _bcmx_port_list_last = port_info->list.prev; 533 } 534 if (port_info->list.prev != NULL) { 535 port_info->list.prev->list.next = port_info->list.next; 536 } 537 if (port_info->list.next != NULL) { 538 port_info->list.next->list.prev = port_info->list.prev; 539 } 540 541 sal_free(port_info); 542 } 543 544 port_info = next; 545 } 546 } 547 548 /* Clear cached CPU port info */ 549 bcmx_lport_local_cpu[unit] = BCMX_LPORT_INVALID; 550 551 return BCM_E_NONE; 552 } 553 554 555 /* 556 * Function: 557 * _bcmx_lport_flags_get 558 * Purpose: 559 * Get the port flags for given lport. 560 * Parameters: 561 * lport - The port to get flags for 562 * flags - (OUT) Flags for given port 563 * Returns: 564 * BCM_E_XXX 565 * Notes: 566 */ 567 STATIC int 568 _bcmx_lport_flags_get(bcmx_lport_t lport, uint32 *flags) 569 { 570 int rv = BCM_E_NOT_FOUND; 571 int index; 572 _bcmx_port_info_t *port_info; 573 574 BCMX_READY_CHECK; 575 BCMX_LPORT_CHECK(lport); 576 577 BCMX_CONFIG_LOCK; 578 if ((port_info = _bcmx_port_info_find(lport, &index)) != NULL) { 579 *flags = port_info->port.flags; 580 rv = BCM_E_NONE; 581 } 582 BCMX_CONFIG_UNLOCK; 583 584 return rv; 585 } 586 587 588 /* 589 * Function: 590 * _bcmx_lport_flags_set 591 * Purpose: 592 * Set the port flags for given lport. 593 * Parameters: 594 * lport - The port to set flags for 595 * flags - Flags for given port 596 * Returns: 597 * BCM_E_XXX 598 * Notes: 599 */ 600 STATIC int 601 _bcmx_lport_flags_set(bcmx_lport_t lport, uint32 flags) 602 { 603 int rv = BCM_E_NOT_FOUND; 604 int index; 605 _bcmx_port_info_t *port_info; 606 607 BCMX_READY_CHECK; 608 BCMX_LPORT_CHECK(lport); 609 610 BCMX_CONFIG_LOCK; 611 if ((port_info = _bcmx_port_info_find(lport, &index)) != NULL) { 612 port_info->port.flags = flags; 613 rv = BCM_E_NONE; 614 } 615 BCMX_CONFIG_UNLOCK; 616 617 return rv; 618 } 619 620 621 /* 622 * Function: 623 * _bcmx_port_flags_create 624 * Purpose: 625 * Create the BCMX port flags for the given port. 626 * Parameters: 627 * unit - unit 628 * Returns: 629 * BCM_E_XXX 630 * Notes: 631 */ 632 STATIC int 633 _bcmx_port_flags_create(bcm_port_config_t *config, 634 bcm_port_t port, uint32 *flags) 635 { 636 uint32 port_flags; 637 638 port_flags = BCMX_PORT_F_VALID; 639 if (BCM_PBMP_MEMBER(config->cpu, port)) { 640 port_flags |= BCMX_PORT_F_CPU; 641 } 642 if (BCM_PBMP_MEMBER(config->hg, port)) { 643 port_flags |= BCMX_PORT_F_HG; 644 } 645 if (BCM_PBMP_MEMBER(config->fe, port)) { 646 port_flags |= BCMX_PORT_F_FE; 647 } 648 if (BCM_PBMP_MEMBER(config->ge, port)) { 649 port_flags |= BCMX_PORT_F_GE; 650 } 651 if (BCM_PBMP_MEMBER(config->xe, port)) { 652 port_flags |= BCMX_PORT_F_XE; 653 } 654 if (BCM_PBMP_MEMBER(config->ce, port)) { 655 port_flags |= BCMX_PORT_F_CE; 656 } 657 if (BCM_PBMP_MEMBER(config->stack_int, port)) { 658 port_flags |= BCMX_PORT_F_STACK_INT; 659 } 660 if (BCM_PBMP_MEMBER(config->stack_ext, port)) { 661 port_flags |= BCMX_PORT_F_STACK_EXT; 662 } 663 664 *flags = port_flags; 665 return BCM_E_NONE; 666 } 667 668 /* 669 * Function: 670 * _bcmx_port_changed 671 * Purpose: 672 * Update internal BCMX information for the given port 673 * Parameters: 674 * port - port 675 * Returns: 676 * BCM_E_XXX 677 * Notes: 678 */ 679 int 680 _bcmx_port_changed(bcmx_lport_t lport) 681 { 682 int rv = BCM_E_PORT; 683 int bcm_unit; 684 bcm_port_config_t config; 685 bcm_port_t bcm_port; 686 uint32 port_flags; 687 688 bcm_unit = bcmx_lport_bcm_unit(lport); 689 bcm_port = bcmx_lport_bcm_port(lport); 690 691 if (bcm_unit >= 0 && bcm_port >= 0) { 692 rv = bcm_port_config_get(bcm_unit, &config); 693 if (BCM_SUCCESS(rv)) { 694 rv = _bcmx_port_flags_create(&config, bcm_port, &port_flags); 695 if (BCM_SUCCESS(rv)) { 696 rv = _bcmx_lport_flags_set(lport, port_flags); 697 } 698 } 699 } 700 701 return rv; 702 } 703 704 /* 705 * Function: 706 * _bcmx_port_changed_callback 707 * Purpose: 708 * Update cached port information when called 709 * Parameters: 710 * port - port 711 * info - port info 712 * Returns: 713 * void 714 * Notes: 715 * Registered with bcmx linkscan to track port changes. 716 * Limitation: will not catch changes to ports if the 717 * port link state is always down. 718 */ 719 STATIC void 720 _bcmx_port_changed_callback(bcmx_lport_t lport, bcm_port_info_t *info) 721 { 722 COMPILER_REFERENCE(info); 723 (void)_bcmx_port_changed(lport); 724 } 725 726 /* 727 * Function: 728 * bcmx_lport_first 729 * Purpose: 730 * Return the first lport found in the BCMX port information table. 731 * Parameters: 732 * none 733 * Returns: 734 * First BCMX logical port found in the BCMX port information table. 735 * (-1) on empty table 736 * Notes: 737 * - The 'first' port returned is the first port added in BCMX. 738 * - This routine should have been private to BCMX, but is exposed 739 * to maintain support of existing public macros. 740 */ 741 bcmx_lport_t 742 bcmx_lport_first(void) 743 { 744 bcmx_lport_t lport_first = BCMX_LPORT_INVALID; 745 746 if (!BCMX_READY) { 747 return BCMX_LPORT_INVALID; 748 } 749 750 BCMX_CONFIG_LOCK; 751 if (_bcmx_port_list_first != NULL) { 752 lport_first = _bcmx_port_list_first->lport; 753 } 754 BCMX_CONFIG_UNLOCK; 755 756 return lport_first; 757 } 758 759 760 /* 761 * Function: 762 * bcmx_lport_next 763 * Purpose: 764 * Return the lport next to the given port in the BCMX port 765 * information table. 766 * Parameters: 767 * lport - BCMX logical port number (gport format) 768 * Returns: 769 * Next lport to given port in the BCMX port information table. 770 * (-1) if no more ports is found. 771 * Notes: 772 * - The 'next' port returned is the port that was added in BCMX 773 * after the specified port. 774 * - This routine should have been private to BCMX, but is exposed 775 * to maintain support of existing public macros. 776 */ 777 bcmx_lport_t 778 bcmx_lport_next(bcmx_lport_t lport) 779 { 780 bcmx_lport_t lport_next = BCMX_LPORT_INVALID; 781 int index; 782 _bcmx_port_info_t *port_info; 783 784 if (!BCMX_READY || !BCMX_IS_LPORT(lport)) { 785 return BCMX_LPORT_INVALID; 786 } 787 788 BCMX_CONFIG_LOCK; 789 if ((port_info = _bcmx_port_info_find(lport, &index)) != NULL) { 790 /* Get next one */ 791 if (port_info->list.next != NULL) { 792 lport_next = port_info->list.next->lport; 793 } 794 } 795 BCMX_CONFIG_UNLOCK; 796 797 return lport_next; 798 } 799 800 801 /* 802 * Function: 803 * bcmx_lport_init 804 * Purpose: 805 * Initialize the internal BCMX port information structures. 806 * Parameters: 807 * none 808 * Returns: 809 * BCM_E_MEMORY if unable to allocate structures 810 * Notes: 811 * Destroys all current information and initializes structures 812 * Destroys user port info; does not make callouts that they're 813 * disappearing. 814 */ 815 int 816 bcmx_lport_init(void) 817 { 818 int i; 819 _bcmx_port_info_t *port_info; 820 _bcmx_port_info_t *port_info_next; 821 _bcmx_uport_hash_t *uport_next; 822 _bcmx_devport_hash_t *devport; 823 _bcmx_devport_hash_t *devport_next; 824 825 BCMX_INIT_CHECK; 826 827 BCMX_CONFIG_LOCK; 828 829 /* Clear BCMX port information table */ 830 for (i = 0; i < BCMX_PORT_HASH_COUNT; i++) { 831 port_info = _bcmx_port_info[i]; 832 while (port_info != NULL) { 833 port_info_next = port_info->next; 834 sal_free(port_info); 835 port_info = port_info_next; 836 } 837 _bcmx_port_info[i] = NULL; 838 } 839 840 /* Clear port lists */ 841 _bcmx_port_list_first = NULL; 842 _bcmx_port_list_last = NULL; 843 844 /* Clear out BCMX uport <-> lport mapping */ 845 for (i = 0; i < BCMX_UPORT_HASH_COUNT; i++) { 846 while (_bcmx_uport_hash[i] != NULL) { 847 uport_next = _bcmx_uport_hash[i]->next; 848 sal_free(_bcmx_uport_hash[i]); 849 _bcmx_uport_hash[i] = uport_next; 850 } 851 _bcmx_uport_hash[i] = NULL; 852 } 853 854 /* Clear devport hash table */ 855 for (i = 0; i < BCMX_PORT_HASH_COUNT; i++) { 856 devport = _bcmx_devport_hash[i]; 857 while (devport != NULL) { 858 devport_next = devport->next; 859 sal_free(devport); 860 devport = devport_next; 861 } 862 _bcmx_devport_hash[i] = NULL; 863 } 864 865 /* Clear cache CPU port */ 866 for (i = 0; i < BCM_CONTROL_MAX; i++) { 867 bcmx_lport_local_cpu[i] = BCMX_LPORT_INVALID; 868 } 869 870 BCMX_CONFIG_UNLOCK; 871 872 return BCM_E_NONE; 873 } 874 875 876 /* 877 * Function: 878 * bcmx_init 879 * Purpose: 880 * Initialize the BCMX subsystem. 881 * Returns: 882 * BCM_E_NONE if successful 883 * BCM_E_MEMORY if unable to allocate structures 884 * Notes: 885 * Initialize mutex. 886 */ 887 int 888 bcmx_init(void) 889 { 890 int rv = BCM_E_NONE; 891 void *api_ptr = (void *)bcmx_api_tbl; 892 893 /* This should never be true; done to include api table */ 894 if (api_ptr == NULL) { 895 /* 896 * Coverity 897 * Defencive check 898 * coverity[dead_error_line] 899 */ 900 return 0; 901 } 902 903 if (bcmx_config_lock == NULL) { 904 bcmx_config_lock = sal_mutex_create("bcmx_init"); 905 if (bcmx_config_lock == NULL) { 906 return BCM_E_MEMORY; 907 } 908 } 909 910 /* Reset port information tables */ 911 rv = bcmx_lport_init(); 912 913 /* Register with linkscan to track port changes */ 914 bcmx_linkscan_register(_bcmx_port_changed_callback); 915 916 return rv; 917 } 918 919 920 /* 921 * Function: 922 * bcmx_uport_create_callback_set 923 * Purpose: 924 * Set the callback for uport create. 925 * Parameters: 926 * create_callback - Function to callback on 927 * Returns: 928 * BCM_E_XXX 929 * Notes: 930 * Call with NULL pointer to turn off the callback. 931 */ 932 int 933 bcmx_uport_create_callback_set(bcmx_uport_create_f create_callback) 934 { 935 bcmx_uport_create = create_callback; 936 return BCM_E_NONE; 937 } 938 939 940 /* 941 * Function: 942 * bcmx_device_attach 943 * Purpose: 944 * Make BCMX aware of the indicated device. 945 * Parameters: 946 * bcm_unit - The BCM (dispatch) unit number of the device 947 * Returns: 948 * BCM_E_XXX 949 * Notes: 950 * This should only be used for "normal" units. 951 */ 952 int 953 bcmx_device_attach(int bcm_unit) 954 { 955 uint32 port_flags; 956 bcm_port_config_t config; 957 bcm_port_t port; 958 int i; 959 int rv; 960 bcm_gport_t lport[BCM_PBMP_PORT_MAX]; 961 962 if (bcmx_config_lock == NULL) { 963 BCM_IF_ERROR_RETURN(bcmx_init()); 964 } 965 966 /* Gather information that requires RPC call before applying lock */ 967 rv = bcm_port_config_get(bcm_unit, &config); 968 if (rv < 0) { 969 LOG_WARN(BSL_LS_BCMX_COMMON, 970 (BSL_META("BCMX: Could not get port config %d: %s\n"), 971 rv, bcm_errmsg(rv))); 972 return rv; 973 } 974 975 LOG_VERBOSE(BSL_LS_BCMX_COMMON, 976 (BSL_META("BCMX: Attaching unit %d\n"), 977 bcm_unit)); 978 BCMX_CONFIG_LOCK; 979 /* See if the unit is on the list of those known */ 980 for (i = 0; i < bcmx_unit_count; i++) { 981 if (bcm_unit == bcmx_unit_list[i]) { 982 BCMX_CONFIG_UNLOCK; 983 LOG_ERROR(BSL_LS_BCMX_COMMON, 984 (BSL_META("BCMX: unit exists\n"))); 985 return BCM_E_EXISTS; 986 } 987 } 988 if (bcmx_unit_count >= BCMX_UNITS_MAX) { 989 BCMX_CONFIG_UNLOCK; 990 return BCM_E_RESOURCE; 991 } 992 bcmx_unit_list[bcmx_unit_count++] = bcm_unit; 993 994 i = 0; 995 BCM_PBMP_ITER(config.all, port) { 996 997 _bcmx_port_flags_create(&config, port, &port_flags); 998 999 /* Add port */ 1000 rv = _bcmx_port_add(bcm_unit, port, lport[i], port_flags); 1001 if (BCM_FAILURE(rv)) { 1002 LOG_WARN(BSL_LS_BCMX_COMMON, 1003 (BSL_META("BCMX: Failed to add lport 0x%x (unit %d, port %d). " 1004 "%d: %s.\n"), 1005 lport[i], bcm_unit, port, rv, bcm_errmsg(rv))); 1006 1007 /* If BCM_E_EXISTS, do not exit, try remaining ports */ 1008 if (rv != BCM_E_EXISTS) { 1009 BCMX_CONFIG_UNLOCK; 1010 return rv; 1011 } 1012 } 1013 i++; 1014 } 1015 1016 BCMX_CONFIG_UNLOCK; 1017 1018 /* 1019 * Check modules that are running that need to know about 1020 * new units 1021 */ 1022 rv = bcmx_rx_device_add(bcm_unit); 1023 if (rv < 0) { 1024 LOG_WARN(BSL_LS_BCMX_COMMON, 1025 (BSL_META("BCMX: Failed to add unit to RX, " 1026 "u %d. %d: %s\n"), bcm_unit, rv, bcm_errmsg(rv))); 1027 } 1028 1029 rv = bcmx_l2_device_add(bcm_unit); 1030 if (rv < 0 && rv != BCM_E_UNAVAIL) { 1031 LOG_WARN(BSL_LS_BCMX_COMMON, 1032 (BSL_META("BCMX: Failed to add unit for L2 notify, " 1033 "u %d. %d: %s\n"), bcm_unit, rv, bcm_errmsg(rv))); 1034 } 1035 1036 rv = bcmx_linkscan_device_add(bcm_unit); 1037 if (rv < 0) { 1038 LOG_WARN(BSL_LS_BCMX_COMMON, 1039 (BSL_META("BCMX: Failed to add unit for linkscan, " 1040 "u %d. %d: %s\n"), bcm_unit, rv, bcm_errmsg(rv))); 1041 } 1042 1043 return BCM_E_NONE; 1044 } 1045 1046 1047 /* 1048 * Function: 1049 * bcmx_device_detach 1050 * Purpose: 1051 * Remove unit from BCMX configuration. 1052 * Parameters: 1053 * bcm_unit - The BCM (dispatch) unit number of the device 1054 * Returns: 1055 * BCM_E_XXX 1056 */ 1057 int 1058 bcmx_device_detach(int bcm_unit) 1059 { 1060 int i, j; 1061 int found = FALSE; 1062 #if defined(BCM_RPC_SUPPORT) 1063 int rv; 1064 #endif 1065 1066 BCMX_INIT_CHECK; 1067 1068 LOG_VERBOSE(BSL_LS_BCMX_COMMON, 1069 (BSL_META("BCMX: Detaching unit %d\n"), 1070 bcm_unit)); 1071 1072 BCMX_CONFIG_LOCK; 1073 1074 /* First, look for the unit on the list of known units */ 1075 for (i = 0; i < bcmx_unit_count; i++) { 1076 if (bcm_unit == bcmx_unit_list[i]) { 1077 found = TRUE; 1078 for (j = i + 1; j < bcmx_unit_count; j++) { 1079 bcmx_unit_list[j - 1] = bcmx_unit_list[j]; 1080 } 1081 bcmx_unit_count--; 1082 break; 1083 } 1084 } 1085 if (!found) { 1086 BCMX_CONFIG_UNLOCK; 1087 return BCM_E_NOT_FOUND; 1088 } 1089 1090 /* Remove all port information for given unit */ 1091 _bcmx_port_info_remove_by_unit(bcm_unit); 1092 1093 BCMX_CONFIG_UNLOCK; 1094 1095 /* De-register rlink facilities in case local */ 1096 bcmx_rx_device_remove(bcm_unit); 1097 bcmx_linkscan_device_remove(bcm_unit); 1098 bcmx_l2_device_remove(bcm_unit); 1099 1100 #if defined(BCM_RPC_SUPPORT) 1101 /* Detach device from rlink */ 1102 if ((rv = bcm_rlink_device_detach(bcm_unit)) < 0) { 1103 LOG_WARN(BSL_LS_BCMX_COMMON, 1104 (BSL_META("BCMX(unit %d): Rlink device detach failed: %d\n"), 1105 bcm_unit, rv)); 1106 } 1107 #endif 1108 1109 return BCM_E_NONE; 1110 } 1111 1112 1113 /* 1114 * Function: 1115 * bcmx_lport_valid 1116 * Purpose: 1117 * Check if given LPORT is an existing valid BCMX logical port. 1118 * Parameters: 1119 * lport - The logical port 1120 * Returns: 1121 * TRUE - LPORT is valid and exists 1122 * FALSE - LPORT value is invalid or it does not exist 1123 */ 1124 int 1125 bcmx_lport_valid(bcmx_lport_t lport) 1126 { 1127 int index; 1128 _bcmx_port_info_t *port_info; 1129 1130 if (!BCMX_READY || !BCMX_IS_LPORT(lport)) { 1131 return FALSE; 1132 } 1133 1134 BCMX_CONFIG_LOCK; 1135 port_info = _bcmx_port_info_find(lport, &index); 1136 BCMX_CONFIG_UNLOCK; 1137 1138 return (port_info != NULL); 1139 } 1140 1141 1142 /**************************************************************** 1143 * 1144 * CPU port accessor 1145 */ 1146 1147 /* 1148 * Function: 1149 * bcmx_lport_local_cpu_get 1150 * Purpose: 1151 * Get the lport associated to the device CPU port. 1152 * Parameters: 1153 * bcm_unit - Device number 1154 * lport - (OUT) BCMX logical port 1155 * Returns: 1156 * BCM_E_NONE on success; sets lport to the CPU port. 1157 * BCM_E_NOT_FOUND otherwise; lport is set to BCMX_LPORT_INVALID 1158 * Notes: 1159 */ 1160 int 1161 bcmx_lport_local_cpu_get(int bcm_unit, bcmx_lport_t *lport) 1162 { 1163 BCMX_READY_CHECK; 1164 BCMX_PARAM_NULL_CHECK(lport); 1165 1166 *lport = bcmx_lport_local_cpu[bcm_unit]; 1167 if (bcmx_lport_local_cpu[bcm_unit] == BCMX_LPORT_INVALID) { 1168 return BCM_E_NOT_FOUND; 1169 } 1170 1171 return BCM_E_NONE; 1172 } 1173 1174 1175 /**************************************************************** 1176 * 1177 * Logical and User port functions 1178 */ 1179 1180 /* 1181 * Function: 1182 * bcmx_uport_get 1183 * Purpose: 1184 * Get the uport associated with an lport. 1185 * Parameters: 1186 * lport - The BCMX logical port 1187 * Returns: 1188 * The uport for the given lport. 1189 * 'uport' is invalid on failure (lport not found) 1190 * You can also use the macro BCMX_UPORT_GET. 1191 */ 1192 bcmx_uport_t 1193 bcmx_uport_get(bcmx_lport_t lport) 1194 { 1195 int index; 1196 _bcmx_port_info_t *port_info; 1197 bcmx_uport_t uport = BCMX_UPORT_INVALID; 1198 1199 if (!BCMX_READY || !BCMX_IS_LPORT(lport)) { 1200 return BCMX_UPORT_INVALID; 1201 } 1202 1203 BCMX_CONFIG_LOCK; 1204 if ((port_info = _bcmx_port_info_find(lport, &index)) != NULL) { 1205 uport = port_info->port.uport; 1206 } 1207 BCMX_CONFIG_UNLOCK; 1208 1209 return uport; 1210 } 1211 1212 1213 /* 1214 * Function: 1215 * bcmx_uport_set 1216 * Purpose: 1217 * Set the uport associated with an lport. 1218 * Parameters: 1219 * lport - The BCMX logical port 1220 * uport - The user port 1221 * Returns: 1222 * BCM_E_XXX; 1223 * Returns an error if the uport is already bound to a 1224 * different lport. 1225 */ 1226 int 1227 bcmx_uport_set(bcmx_lport_t lport, bcmx_uport_t uport) 1228 { 1229 int rv = BCM_E_NONE; 1230 int index; 1231 _bcmx_port_info_t *port_info; 1232 bcmx_lport_t tmp_lport; 1233 1234 BCMX_READY_CHECK; 1235 BCMX_LPORT_CHECK(lport); 1236 1237 BCMX_CONFIG_LOCK; 1238 1239 /* Invalid uport: clear current lport <-> uport */ 1240 if (uport == BCMX_UPORT_INVALID) { 1241 if ((port_info = _bcmx_port_info_find(lport, &index)) != NULL) { 1242 _bcmx_uport_remove(port_info->port.uport); 1243 port_info->port.uport = uport; 1244 } else { 1245 rv = BCM_E_PORT; 1246 } 1247 1248 BCMX_CONFIG_UNLOCK; 1249 return rv; 1250 } 1251 1252 /* See if uport is already mapped to a logical port */ 1253 tmp_lport = BCMX_UPORT_TO_LPORT(uport); 1254 if (BCMX_LPORT_VALID(tmp_lport)) { 1255 /* Check if logical port is same, if so, nothing to do, return ok */ 1256 if (tmp_lport != lport) { 1257 rv = BCM_E_EXISTS; 1258 } 1259 1260 BCMX_CONFIG_UNLOCK; 1261 return rv; 1262 } 1263 1264 /* Update lport <-> uport */ 1265 if ((port_info = _bcmx_port_info_find(lport, &index)) != NULL) { 1266 1267 /* Update uport <-> lport mapping, if different */ 1268 if (port_info->port.uport != uport) { 1269 if (_bcmx_uport_add(uport, lport) == NULL) { 1270 rv = BCM_E_MEMORY; 1271 } else { 1272 _bcmx_uport_remove(port_info->port.uport); 1273 port_info->port.uport = uport; 1274 } 1275 } 1276 1277 } else { 1278 rv = BCM_E_PORT; 1279 } 1280 1281 BCMX_CONFIG_UNLOCK; 1282 1283 return rv; 1284 } 1285 1286 1287 /* 1288 * Function: 1289 * bcmx_lport_to_unit_port 1290 * Purpose: 1291 * Map an LPORT to a BCM dispatch unit/port pair. 1292 * Parameters: 1293 * lport - The port to map 1294 * unit - (OUT) Device unit mapped to lport 1295 * port - (OUT) Device port mapped to lport 1296 * Returns: 1297 * BCM_E_XXX 1298 * Notes: 1299 */ 1300 int 1301 bcmx_lport_to_unit_port(bcmx_lport_t lport, int *unit, bcm_port_t *port) 1302 { 1303 int rv = BCM_E_PORT; 1304 int index; 1305 _bcmx_port_info_t *port_info; 1306 1307 BCMX_READY_CHECK; 1308 BCMX_LPORT_CHECK(lport); 1309 BCMX_PARAM_NULL_CHECK(unit); 1310 BCMX_PARAM_NULL_CHECK(port); 1311 1312 BCMX_CONFIG_LOCK; 1313 if ((port_info = _bcmx_port_info_find(lport, &index)) != NULL) { 1314 *unit = port_info->port.bcm_unit; 1315 *port = port_info->port.bcm_port; 1316 rv = BCM_E_NONE; 1317 } 1318 BCMX_CONFIG_UNLOCK; 1319 1320 return rv; 1321 } 1322 1323 1324 /* 1325 * Function: 1326 * bcmx_lport_to_modid_port 1327 * Purpose: 1328 * Map an LPORT to a device module ID and physical port. 1329 * Parameters: 1330 * lport - The port to map 1331 * modid - (OUT) System mod id mapped to lport 1332 * port - (OUT) Unit's port mapped to lport 1333 * Returns: 1334 * BCM_E_XXX 1335 * Notes: 1336 */ 1337 int 1338 bcmx_lport_to_modid_port(bcmx_lport_t lport, 1339 int *modid, bcm_port_t *modport) 1340 { 1341 int rv = BCM_E_PORT; 1342 int index; 1343 _bcmx_port_info_t *port_info; 1344 1345 BCMX_READY_CHECK; 1346 BCMX_LPORT_CHECK(lport); 1347 BCMX_PARAM_NULL_CHECK(modid); 1348 BCMX_PARAM_NULL_CHECK(modport); 1349 1350 BCMX_CONFIG_LOCK; 1351 if ((port_info = _bcmx_port_info_find(lport, &index)) != NULL) { 1352 *modid = port_info->port.modid; 1353 *modport = port_info->port.modport; 1354 rv = BCM_E_NONE; 1355 } 1356 BCMX_CONFIG_UNLOCK; 1357 1358 return rv; 1359 } 1360 1361 1362 /* 1363 * Function: 1364 * bcmx_lport_to_modid 1365 * Purpose: 1366 * Map an LPORT to its mod id, if appropriate. 1367 * Parameters: 1368 * lport - The lport to lookup 1369 * modid - (OUT) Returns the modid for given port 1370 * Returns: 1371 * BCM_E_XXX 1372 */ 1373 int 1374 bcmx_lport_to_modid(bcmx_lport_t lport, int *modid) 1375 { 1376 int rv; 1377 bcm_port_t modport; 1378 1379 rv = bcmx_lport_to_modid_port(lport, modid, &modport); 1380 1381 return rv; 1382 } 1383 1384 1385 /* 1386 * Function: 1387 * bcmx_unit_port_to_lport 1388 * Purpose: 1389 * Map BCM unit and port number to logical port. 1390 * Parameters: 1391 * unit - BCM unit to map 1392 * port - Unit's port to map 1393 * Returns: 1394 * lport value 1395 * Notes: 1396 */ 1397 bcmx_lport_t 1398 bcmx_unit_port_to_lport(int unit, bcm_port_t port) 1399 { 1400 bcmx_lport_t lport = BCMX_LPORT_INVALID; 1401 bcm_gport_t key; 1402 int index; 1403 _bcmx_devport_hash_t *devport; 1404 1405 if (!BCMX_READY) { 1406 return BCMX_LPORT_INVALID; 1407 } 1408 1409 BCMX_CONFIG_LOCK; 1410 1411 BCM_GPORT_DEVPORT_SET(key, unit, port); 1412 index = BCMX_PORT_HASH_INDEX(key); 1413 1414 devport = _bcmx_devport_hash[index]; 1415 while (devport != NULL) { 1416 if (devport->key == key) { 1417 if (devport->port_info != NULL) { 1418 lport = devport->port_info->lport; 1419 } 1420 break; 1421 } 1422 devport = devport->next; 1423 } 1424 1425 BCMX_CONFIG_UNLOCK; 1426 1427 return lport; 1428 } 1429 1430 1431 /* 1432 * Function: 1433 * bcmx_modid_port_to_lport 1434 * Purpose: 1435 * Map module ID and physical port to logical port. 1436 * Parameters: 1437 * modid - System mod id to map 1438 * port - Unit's port to map 1439 * Returns: 1440 * lport value 1441 * Notes: 1442 */ 1443 bcmx_lport_t 1444 bcmx_modid_port_to_lport(int modid, bcm_port_t port) 1445 { 1446 bcmx_lport_t lport = BCMX_LPORT_INVALID; 1447 bcm_gport_t key; 1448 int index; 1449 _bcmx_port_info_t *port_info; 1450 1451 if (!BCMX_READY) { 1452 return BCMX_LPORT_INVALID; 1453 } 1454 1455 /* Generate hash key (gport value) from mod/port */ 1456 BCM_GPORT_MODPORT_SET(key, modid, port); 1457 1458 BCMX_CONFIG_LOCK; 1459 if ((port_info = _bcmx_port_info_find(key, &index)) != NULL) { 1460 if ((port_info->port.modid == modid) && 1461 (port_info->port.modport == port)) { 1462 lport = key; 1463 } 1464 } 1465 BCMX_CONFIG_UNLOCK; 1466 1467 return lport; 1468 } 1469 1470 1471 /* 1472 * Function: 1473 * bcmx_uport_to_lport 1474 * Purpose: 1475 * Map a user port to a BCMX lport. 1476 * Parameters: 1477 * uport - The user port 1478 * Returns: 1479 * lport; may be invalid if uport not found. 1480 * You can also use the macro BCMX_UPORT_TO_LPORT 1481 */ 1482 bcmx_lport_t 1483 bcmx_uport_to_lport(bcmx_uport_t uport) 1484 { 1485 _bcmx_uport_hash_t *cur; 1486 bcmx_lport_t lport = BCMX_LPORT_INVALID; 1487 1488 if (!BCMX_READY) { 1489 return BCMX_LPORT_INVALID; 1490 } 1491 1492 BCMX_CONFIG_LOCK; 1493 cur = _bcmx_uport_hash[BCMX_UPORT_HASH(uport)]; 1494 while (cur != NULL) { 1495 if (BCMX_UPORT_EQ(uport, cur->uport)) { 1496 lport = cur->lport; 1497 break; 1498 } 1499 cur = cur->next; 1500 } 1501 BCMX_CONFIG_UNLOCK; 1502 1503 return lport; 1504 } 1505 1506 1507 /* 1508 * Function: 1509 * bcmx_modid_to_bcm_unit 1510 * Purpose: 1511 * Get the device unit number associated with given module id. 1512 * Parameters: 1513 * modid - Device module id 1514 * bcm_unit - (OUT) The device unit number for given module id 1515 * Returns: 1516 * BCM_E_XXX 1517 */ 1518 int 1519 bcmx_modid_to_bcm_unit(int modid, int *bcm_unit) 1520 { 1521 int rv = BCM_E_NOT_FOUND; 1522 int i; 1523 _bcmx_port_info_t *port_info; 1524 1525 BCMX_READY_CHECK; 1526 BCMX_PARAM_NULL_CHECK(bcm_unit); 1527 1528 BCMX_CONFIG_LOCK; 1529 1530 /* Check each list */ 1531 for (i = 0; i < BCMX_PORT_HASH_COUNT; i++) { 1532 port_info = _bcmx_port_info[i]; 1533 1534 /* Check each entry in link list */ 1535 while (port_info != NULL) { 1536 if (port_info->port.modid == modid) { 1537 *bcm_unit = port_info->port.bcm_unit; 1538 rv = BCM_E_NONE; 1539 break; 1540 } 1541 port_info = port_info->next; 1542 } 1543 } 1544 1545 BCMX_CONFIG_UNLOCK; 1546 1547 return rv; 1548 } 1549 1550 /* 1551 * Function: 1552 * bcmx_uport_to_unit_port 1553 * Purpose: 1554 * Map a user port to BCM unit and port pair. 1555 * Parameters: 1556 * uport - The user port 1557 * bcm_unit - (OUT) BCM unit 1558 * bcm_port - (OUT) BCM port 1559 * Returns: 1560 * BCM_E_XXX 1561 */ 1562 int 1563 bcmx_uport_to_unit_port(bcmx_uport_t uport, 1564 int *bcm_unit, bcm_port_t *bcm_port) 1565 { 1566 int rv = BCM_E_NOT_FOUND; 1567 bcmx_lport_t lport; 1568 1569 BCMX_READY_CHECK; 1570 BCMX_PARAM_NULL_CHECK(bcm_unit); 1571 BCMX_PARAM_NULL_CHECK(bcm_port); 1572 1573 BCMX_CONFIG_LOCK; 1574 if ((lport = bcmx_uport_to_lport(uport)) != BCMX_LPORT_INVALID) { 1575 rv = bcmx_lport_to_unit_port(lport, bcm_unit, bcm_port); 1576 } 1577 BCMX_CONFIG_UNLOCK; 1578 1579 return rv; 1580 } 1581 1582 1583 /* 1584 * NOTE 1585 * The following wrapper routines are necessary to maintain 1586 * support of old public macros. 1587 */ 1588 int 1589 bcmx_lport_bcm_unit(bcmx_lport_t lport) 1590 { 1591 int unit = -1; 1592 bcm_port_t port = -1; 1593 1594 (void)bcmx_lport_to_unit_port(lport, &unit, &port); 1595 1596 return unit; 1597 } 1598 1599 bcm_port_t 1600 bcmx_lport_bcm_port(bcmx_lport_t lport) 1601 { 1602 int unit = -1; 1603 bcm_port_t port = -1; 1604 1605 (void)bcmx_lport_to_unit_port(lport, &unit, &port); 1606 1607 return port; 1608 } 1609 1610 int 1611 bcmx_lport_modid(bcmx_lport_t lport) 1612 { 1613 int modid = -1; 1614 bcm_port_t modport = -1; 1615 1616 (void)bcmx_lport_to_modid_port(lport, &modid, &modport); 1617 1618 return modid; 1619 } 1620 1621 bcm_port_t 1622 bcmx_lport_modport(bcmx_lport_t lport) 1623 { 1624 int modid = -1; 1625 bcm_port_t modport = -1; 1626 1627 (void)bcmx_lport_to_modid_port(lport, &modid, &modport); 1628 1629 return modport; 1630 } 1631 1632 uint32 1633 bcmx_lport_flags(bcmx_lport_t lport) 1634 { 1635 uint32 flags = 0x0; 1636 1637 (void)_bcmx_lport_flags_get(lport, &flags); 1638 1639 return flags; 1640 } 1641 1642 1643 /* 1644 * Function: 1645 * _bcmx_port_info_dump 1646 * Purpose: 1647 * Displays internal BCMX port information table. 1648 * Used for debugging purposes. 1649 * Parameters: 1650 * none 1651 * Returns: 1652 * BCM_E_XXX 1653 */ 1654 int 1655 _bcmx_port_info_dump(void) 1656 { 1657 int i; 1658 _bcmx_port_info_t *port_info; 1659 1660 BCMX_INIT_CHECK; 1661 1662 LOG_INFO(BSL_LS_BCMX_COMMON, 1663 (BSL_META("BCMX port info dump\n"))); 1664 1665 BCMX_CONFIG_LOCK; 1666 1667 /* Iterate over hash table link list */ 1668 for (i = 0; i < BCMX_PORT_HASH_COUNT; i++) { 1669 port_info = _bcmx_port_info[i]; 1670 1671 /* Check each entry in link list */ 1672 while (port_info != NULL) { 1673 LOG_INFO(BSL_LS_BCMX_COMMON, 1674 (BSL_META(" %d: lport=0x%x unit=%d port=%d uport=%d flags=0x%x " 1675 "modid=%d modport=%d\n"), 1676 i, port_info->lport, 1677 port_info->port.bcm_unit, port_info->port.bcm_port, 1678 PTR_TO_INT(port_info->port.uport), port_info->port.flags, 1679 port_info->port.modid, port_info->port.modport)); 1680 port_info = port_info->next; 1681 } 1682 } 1683 1684 BCMX_CONFIG_UNLOCK; 1685 1686 return BCM_E_NONE; 1687 } 1688 1689 1690 /* 1691 * BCMX Generic Conversion Destination Functions 1692 * 1693 * The following set of internal conversion routines for destination 1694 * to/from BCMX/BCM handle both, old and new gport, BCM port formats. 1695 * 1696 * The BCMX driver should use these new routines rather than 1697 * the previous conversion routines (e.g. bcmx_lport_to_modid_port) 1698 * which only converts to/from old BCM port format. 1699 * 1700 * In addition, these generic routines will help with the current work 1701 * in progress at the BCM layer to have all APIs handle the new gport 1702 * format. 1703 */ 1704 1705 /* 1706 * Function: 1707 * _bcmx_dest_bcmx_t_init 1708 * Purpose: 1709 * Initializer routine for BCMX destination structure. 1710 * Parameters: 1711 * dest_bcmx - (OUT) Pointer to structure to initialize 1712 * Returns: 1713 * None 1714 */ 1715 void 1716 _bcmx_dest_bcmx_t_init(_bcmx_dest_bcmx_t *dest_bcmx) 1717 { 1718 if (dest_bcmx != NULL) { 1719 dest_bcmx->port = BCMX_LPORT_INVALID; 1720 dest_bcmx->trunk = BCM_TRUNK_INVALID; 1721 dest_bcmx->mcast = -1; 1722 } 1723 } 1724 1725 /* 1726 * Function: 1727 * _bcmx_dest_bcm_t_init 1728 * Purpose: 1729 * Initializer routine for BCM destination structure. 1730 * Parameters: 1731 * dest_bcm - (OUT) Pointer to structure to initialize 1732 * Returns: 1733 * None 1734 */ 1735 void 1736 _bcmx_dest_bcm_t_init(_bcmx_dest_bcm_t *dest_bcm) 1737 { 1738 if (dest_bcm != NULL) { 1739 dest_bcm->unit = -1; 1740 dest_bcm->port = BCM_GPORT_INVALID; 1741 dest_bcm->module_id = -1; 1742 dest_bcm->module_port = BCM_GPORT_INVALID; 1743 dest_bcm->trunk = BCM_TRUNK_INVALID; 1744 dest_bcm->mcast = -1; 1745 } 1746 } 1747 1748 /* 1749 * Function: 1750 * _bcmx_dest_to_bcm 1751 * Purpose: 1752 * Converts BCMX to BCM destination information. 1753 * 1754 * Translation of data is on flags setting and one in following order: 1755 * (a) If MCAST flag is set, set mcast field using old format 1756 * (b) If TRUNK flag is set, set trunk field using old format 1757 * (c) Else, 1758 * (c.1) If logical port is in GPORT format: 1759 * - If GPORT_AWARE flag is set, direct assignment to port field, 1760 * with the exception of DEVPORT. See notes below. 1761 * - Else, convert to old non-gport format based on GPORT type 1762 * (c.2) Else, error 1763 * Parameters: 1764 * from_bcmx - BCMX destination information to convert 1765 * to_bcm - (OUT) Returns converted BCM destination information 1766 * flags - (IN/OUT) Indicates what is being converted 1767 * Returns: 1768 * BCM_E_NONE - Success 1769 * BCM_E_xxx - Failure 1770 * Notes: 1771 * (1) A BLACK HOLE gport is being handled at the BCMX layer by setting 1772 * the 'discard' flag (if any). The extra type check can be removed 1773 * once BCM handles the BLACK HOLE gport type. 1774 * (2) Note that when GPORT format is returned, the GPORT value is 1775 * returned in both members "port" and "module_port". 1776 * (3) If given logical port is a DEVPORT, port will return 1777 * in old BCM port format regardless of flag. The unit in DEVPORT 1778 * has meaning only in BCMX. 1779 */ 1780 int 1781 _bcmx_dest_to_bcm(_bcmx_dest_bcmx_t *from_bcmx, _bcmx_dest_bcm_t *to_bcm, 1782 uint32 *flags) 1783 { 1784 uint32 flags_out = 0x0; 1785 1786 BCMX_PARAM_NULL_CHECK(to_bcm); 1787 BCMX_PARAM_NULL_CHECK(from_bcmx); 1788 BCMX_PARAM_NULL_CHECK(flags); 1789 1790 _bcmx_dest_bcm_t_init(to_bcm); 1791 1792 /* Convert to BCM */ 1793 1794 /* Check MCAST flag first */ 1795 if (*flags & BCMX_DEST_MCAST) { 1796 flags_out |= BCMX_DEST_MCAST; 1797 to_bcm->mcast = from_bcmx->mcast; 1798 1799 } else if (*flags & BCMX_DEST_TRUNK) { 1800 /* Check TRUNK flag next */ 1801 flags_out |= BCMX_DEST_TRUNK; 1802 to_bcm->trunk = from_bcmx->trunk; 1803 1804 } else { 1805 1806 if (BCM_GPORT_IS_SET(from_bcmx->port)) { 1807 /* 1808 * If GPORT_AWARE flag is set, direct assignment 1809 * (BCM can handle gport format). 1810 */ 1811 if (*flags & BCMX_DEST_GPORT_AWARE) { 1812 flags_out |= BCMX_DEST_GPORT_AWARE; 1813 to_bcm->port = from_bcmx->port; 1814 to_bcm->module_port = from_bcmx->port; 1815 1816 /* Get also the 'unit' and 'module-id', if applicable */ 1817 if (BCM_GPORT_IS_MODPORT(from_bcmx->port) || 1818 BCM_GPORT_IS_DEVPORT(from_bcmx->port)) { 1819 bcm_port_t port_tmp = -1; 1820 1821 (void)bcmx_lport_to_unit_port(from_bcmx->port, 1822 &to_bcm->unit, 1823 &port_tmp); 1824 /* 1825 * If DEVPORT, set the port to old format 1826 * since the unit in DEVPORT is in BCMX context and 1827 * has no meaning in the corresponding remote device. 1828 */ 1829 if (BCM_GPORT_IS_DEVPORT(from_bcmx->port)) { 1830 to_bcm->port = port_tmp; 1831 to_bcm->module_port = port_tmp; 1832 } 1833 1834 (void)bcmx_lport_to_modid_port(from_bcmx->port, 1835 &to_bcm->module_id, 1836 &port_tmp); 1837 } 1838 1839 } else { 1840 /* 1841 * Convert gport to old format based on GPORT type: 1842 * MCAST ==> set mcast flag, set mcast 1843 * TRUNK ==> set trunk flag, set trunk 1844 * BLACK_HOLE ==> set discard flag, set port 1845 * LOCAL_CPU ==> set local_cpu flag, set port 1846 * MODPORT/DEVPORT ==> set unit/port and mod/port 1847 * Other ==> direct assignment 1848 */ 1849 if (BCM_GPORT_IS_MCAST(from_bcmx->port)) { 1850 flags_out |= BCMX_DEST_MCAST; 1851 to_bcm->mcast = BCM_GPORT_MCAST_GET(from_bcmx->port); 1852 1853 } else if (BCM_GPORT_IS_TRUNK(from_bcmx->port)) { 1854 flags_out |= BCMX_DEST_TRUNK; 1855 to_bcm->trunk = BCM_GPORT_TRUNK_GET(from_bcmx->port); 1856 1857 } else if (BCM_GPORT_IS_BLACK_HOLE(from_bcmx->port)) { 1858 flags_out |= (BCMX_DEST_DISCARD | BCMX_DEST_GPORT_AWARE); 1859 to_bcm->port = from_bcmx->port; 1860 to_bcm->module_port = from_bcmx->port; 1861 1862 } else if (BCM_GPORT_IS_LOCAL_CPU(from_bcmx->port)) { 1863 flags_out |= (BCMX_DEST_LOCAL_CPU | BCMX_DEST_GPORT_AWARE); 1864 to_bcm->port = from_bcmx->port; 1865 to_bcm->module_port = from_bcmx->port; 1866 1867 } else if (BCM_GPORT_IS_MODPORT(from_bcmx->port) || 1868 BCM_GPORT_IS_DEVPORT(from_bcmx->port)) { 1869 /* 1870 * NOTE that bcmx_lport_to_modid_port() returns 1871 * success when it finds an existing bcmx logical port 1872 * (so, some calls could return a modid = -1, but a valid 1873 * bcm port number, in cases when the device does not 1874 * have a module id assigned to id. 1875 */ 1876 BCM_IF_ERROR_RETURN 1877 (bcmx_lport_to_unit_port(from_bcmx->port, 1878 &to_bcm->unit, 1879 &to_bcm->port)); 1880 BCM_IF_ERROR_RETURN 1881 (bcmx_lport_to_modid_port(from_bcmx->port, 1882 &to_bcm->module_id, 1883 &to_bcm->module_port)); 1884 } else { 1885 flags_out |= BCMX_DEST_GPORT_AWARE; 1886 to_bcm->port = from_bcmx->port; 1887 to_bcm->module_port = from_bcmx->port; 1888 } 1889 } 1890 1891 } else { 1892 return BCM_E_PORT; 1893 } 1894 } 1895 1896 *flags = flags_out; 1897 1898 return BCM_E_NONE; 1899 } 1900 1901 /* 1902 * Function: 1903 * _bcmx_dest_from_bcm 1904 * Purpose: 1905 * Converts BCM to BCMX destination information. 1906 * 1907 * Translation of data is on flags setting and one in following order: 1908 * (a) If MCAST flag is set, set mcast field using old format 1909 * (b) If TRUNK flag is set, set trunk field using old format 1910 * (c) Else, 1911 * (c.1) If port (either 'port' or 'module_port') is in GPORT format, 1912 * direct assignment to BCMX port field 1913 * (c.2) Else, translate BCM old format, unit/port or mod/port, to 1914 * BCMX lport 1915 * 1916 * Parameters: 1917 * to_bcmx - (OUT) Returns converted BCMX destination information 1918 * from_bcm - BCM destination information to convert 1919 * flags - (IN/OUT) Indicates what is being converted 1920 * Returns: 1921 * BCM_E_NONE - Success 1922 * BCM_E_xxx - Failure 1923 */ 1924 int 1925 _bcmx_dest_from_bcm(_bcmx_dest_bcmx_t *to_bcmx, _bcmx_dest_bcm_t *from_bcm, 1926 uint32 *flags) 1927 { 1928 uint32 flags_out = 0x0; 1929 1930 BCMX_PARAM_NULL_CHECK(to_bcmx); 1931 BCMX_PARAM_NULL_CHECK(from_bcm); 1932 BCMX_PARAM_NULL_CHECK(flags); 1933 1934 _bcmx_dest_bcmx_t_init(to_bcmx); 1935 1936 /* Check MCAST flag first */ 1937 if (*flags & BCMX_DEST_MCAST) { 1938 flags_out |= BCMX_DEST_MCAST; 1939 to_bcmx->mcast = from_bcm->mcast; 1940 1941 } else if (*flags & BCMX_DEST_TRUNK) { 1942 /* Check TRUNK flag next */ 1943 flags_out |= BCMX_DEST_TRUNK; 1944 to_bcmx->trunk = from_bcm->trunk; 1945 1946 } else { 1947 /* BCMX lport is always returning in GPORT format */ 1948 flags_out |= BCMX_DEST_GPORT_AWARE; 1949 1950 /* 1951 * If port is in GPORT format ==> direct assigment 1952 * NOTE: Use either 'port' or 'module_port' value. 1953 * If both are 'valid' gport values, they need to be 1954 * the same. 1955 * 1956 * Otherwise get the BCMX lport from old format. 1957 * Try mod/port pair first, if fails, try unit/port 1958 */ 1959 if (BCM_GPORT_IS_SET(from_bcm->port) && 1960 BCM_GPORT_IS_SET(from_bcm->module_port)) { 1961 if (from_bcm->port != from_bcm->module_port) { 1962 return BCM_E_PORT; 1963 } 1964 to_bcmx->port = (bcmx_lport_t) from_bcm->port; 1965 1966 } else if (BCM_GPORT_IS_SET(from_bcm->port)) { 1967 to_bcmx->port = (bcmx_lport_t) from_bcm->port; 1968 1969 } else if (BCM_GPORT_IS_SET(from_bcm->module_port)) { 1970 to_bcmx->port = (bcmx_lport_t) from_bcm->module_port; 1971 1972 } else { 1973 /* Convert from old format */ 1974 to_bcmx->port = bcmx_modid_port_to_lport(from_bcm->module_id, 1975 from_bcm->module_port); 1976 if (to_bcmx->port == BCMX_LPORT_INVALID) { 1977 to_bcmx->port = bcmx_unit_port_to_lport(from_bcm->unit, 1978 from_bcm->port); 1979 } 1980 1981 if (to_bcmx->port == BCMX_LPORT_INVALID) { 1982 return BCM_E_PORT; 1983 } 1984 } 1985 } 1986 1987 *flags = flags_out; 1988 1989 return BCM_E_NONE; 1990 } 1991 1992 1993 /* 1994 * Function: 1995 * _bcmx_dest_to_modid_port 1996 * Purpose: 1997 * Converts BCMX logical port to BCM module/port destination in 1998 * old or new port format, based on flags. 1999 * Parameters: 2000 * port - BCMX logical port to convert 2001 * bcm_module - (OUT) Returns BCM module id (when in old format) 2002 * bcm_port - (OUT) Returns BCM port in old or new gport format 2003 * flags - Indicates whether to convert to old or new BCM port format 2004 * Returns: 2005 * BCM_E_NONE - Success 2006 * BCM_E_xxx - Failure 2007 * Notes: 2008 * Valid flags are: 2009 * BCMX_DEST_GPORT_AWARE - Convert to new gport format 2010 */ 2011 int 2012 _bcmx_dest_to_modid_port(bcmx_lport_t port, 2013 bcm_module_t *bcm_module, bcm_port_t *bcm_port, 2014 uint32 flags) 2015 { 2016 uint32 flags_orig = flags; 2017 _bcmx_dest_bcm_t to_bcm; 2018 _bcmx_dest_bcmx_t from_bcmx; 2019 2020 BCMX_DEST_MODID_PORT_FLAG_CHECK(flags); 2021 2022 _bcmx_dest_bcmx_t_init(&from_bcmx); 2023 from_bcmx.port = port; 2024 2025 BCM_IF_ERROR_RETURN(_bcmx_dest_to_bcm(&from_bcmx, &to_bcm, &flags)); 2026 2027 if ((to_bcm.module_port == BCM_GPORT_INVALID) || 2028 ((flags_orig & BCMX_DEST_GPORT_AWARE) && 2029 !BCM_GPORT_IS_SET(to_bcm.module_port))) { 2030 return BCM_E_PORT; 2031 } 2032 2033 *bcm_module = to_bcm.module_id; 2034 *bcm_port = to_bcm.module_port; 2035 2036 return BCM_E_NONE; 2037 } 2038 2039 2040 /* 2041 * Function: 2042 * _bcmx_dest_from_modid_port 2043 * Purpose: 2044 * Converts BCM module/port, in old or new gport format, to 2045 * BCMX logical port destination. 2046 * Parameters: 2047 * port - (OUT) Returns BCMX logical port 2048 * bcm_module - BCM module id to convert 2049 * bcm_port - BCM port to convert (in old or new gport format) 2050 * flags - Not used currently, but valid flag must be passed in 2051 * Returns: 2052 * BCM_E_NONE - Success 2053 * BCM_E_xxx - Failure 2054 * Notes: 2055 * Valid flags are: 2056 * BCMX_DEST_GPORT_AWARE - No effect when converting 'from' BCM 2057 */ 2058 int 2059 _bcmx_dest_from_modid_port(bcmx_lport_t *port, 2060 bcm_module_t bcm_module, bcm_port_t bcm_port, 2061 uint32 flags) 2062 { 2063 _bcmx_dest_bcm_t from_bcm; 2064 _bcmx_dest_bcmx_t to_bcmx; 2065 2066 BCMX_DEST_MODID_PORT_FLAG_CHECK(flags); 2067 2068 _bcmx_dest_bcm_t_init(&from_bcm); 2069 from_bcm.module_id = bcm_module; 2070 from_bcm.module_port = bcm_port; 2071 2072 BCM_IF_ERROR_RETURN(_bcmx_dest_from_bcm(&to_bcmx, &from_bcm, &flags)); 2073 2074 *port = to_bcmx.port; 2075 2076 return BCM_E_NONE; 2077 } 2078 2079 /* 2080 * Function: 2081 * _bcmx_dest_to_unit_port 2082 * Purpose: 2083 * Converts BCMX logical port to BCM unit/port destination in 2084 * old or new port format, based on flags. 2085 * Parameters: 2086 * port - BCMX logical port to convert 2087 * bcm_unit - (OUT) Returns BCM device unit 2088 * bcm_port - (OUT) Returns BCM port in old or new gport format 2089 * flags - Indicates whether to convert to old or new BCM port format 2090 * Returns: 2091 * BCM_E_NONE - Success 2092 * BCM_E_xxx - Failure 2093 * Notes: 2094 * Valid flags are: 2095 * BCMX_DEST_GPORT_AWARE - Convert to new gport format 2096 * 2097 * If given 'port' is a DEVPORT, 'bcm_port' will return 2098 * in old BCM port format regardless of flag. The unit in DEVPORT 2099 * has meaning only in BCMX. 2100 */ 2101 int 2102 _bcmx_dest_to_unit_port(bcmx_lport_t port, 2103 int *bcm_unit, bcm_port_t *bcm_port, 2104 uint32 flags) 2105 { 2106 uint32 flags_orig = flags; 2107 _bcmx_dest_bcm_t to_bcm; 2108 _bcmx_dest_bcmx_t from_bcmx; 2109 2110 BCMX_DEST_UNIT_PORT_FLAG_CHECK(flags); 2111 2112 _bcmx_dest_bcmx_t_init(&from_bcmx); 2113 from_bcmx.port = port; 2114 2115 BCM_IF_ERROR_RETURN(_bcmx_dest_to_bcm(&from_bcmx, &to_bcm, &flags)); 2116 2117 if ((to_bcm.unit == -1) || 2118 (to_bcm.port == BCM_GPORT_INVALID) || 2119 (!BCM_GPORT_IS_DEVPORT(from_bcmx.port) && 2120 ((flags_orig & BCMX_DEST_GPORT_AWARE) && 2121 !BCM_GPORT_IS_SET(to_bcm.port)))) { 2122 return BCM_E_PORT; 2123 } 2124 2125 *bcm_unit = to_bcm.unit; 2126 *bcm_port = to_bcm.port; 2127 2128 return BCM_E_NONE; 2129 } 2130 2131 /* 2132 * Function: 2133 * _bcmx_dest_from_unit_port 2134 * Purpose: 2135 * Converts BCM unit/port, in old or new gport format, to 2136 * BCMX logical port destination. 2137 * Parameters: 2138 * port - (OUT) Returns BCMX logical port 2139 * bcm_unit - BCM device unit to convert 2140 * bcm_port - BCM port to convert (in old or new gport format) 2141 * flags - Not used currently, but valid flag must be passed in 2142 * Returns: 2143 * BCM_E_NONE - Success 2144 * BCM_E_xxx - Failure 2145 * Notes: 2146 * Valid flags are: 2147 * BCMX_DEST_GPORT_AWARE - No effect when converting 'from' BCM 2148 */ 2149 int 2150 _bcmx_dest_from_unit_port(bcmx_lport_t *port, 2151 int bcm_unit, bcm_port_t bcm_port, 2152 uint32 flags) 2153 { 2154 _bcmx_dest_bcm_t from_bcm; 2155 _bcmx_dest_bcmx_t to_bcmx; 2156 2157 BCMX_DEST_UNIT_PORT_FLAG_CHECK(flags); 2158 2159 _bcmx_dest_bcm_t_init(&from_bcm); 2160 from_bcm.unit = bcm_unit; 2161 from_bcm.port = bcm_port; 2162 2163 BCM_IF_ERROR_RETURN(_bcmx_dest_from_bcm(&to_bcmx, &from_bcm, &flags)); 2164 2165 *port = to_bcmx.port; 2166 2167 return BCM_E_NONE; 2168 } 2169 2170 /* 2171 * Function: 2172 * _bcmx_error_check 2173 * Purpose: 2174 * Checks given BCM error code as follows: 2175 * - If error code is BCM_E_UNAVAIL and unit is fabric, 2176 * 'rv' value is unchanged and function returns successful. 2177 * - If error code is successful or matches the ignore code, 2178 * 'rv' and function returns successful. 2179 * - Else, 'rv' and function returns failure code. 2180 * Parameters: 2181 * unit - Device unit 2182 * check - Error code to be checked 2183 * ignore - Error code to ignore (treated as BCM_E_NONE) 2184 * rv - (IN/OUT) Returns value based on above logic. 2185 * Returns: 2186 * BCM_E_NONE - Successful, given error code to check is: 2187 * is a successful error code, or 2188 * matches ignore code, or 2189 * is BCM_E_UNAVAIL on a fabric unit 2190 * BCM_E_XXX - Failure 2191 */ 2192 int 2193 _bcmx_error_check(int unit, int check, int ignore, int *rv) 2194 { 2195 if (BCMX_FABRIC_E_UNAVAIL(unit, check)) { 2196 return BCM_E_NONE; 2197 } 2198 2199 if (check == ignore) { 2200 check = BCM_E_NONE; 2201 } 2202 2203 *rv = check; 2204 2205 return *rv; 2206 }