multicast.c (23976B)
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: multicast.c 8 * Purpose: Tomahawk multicast functions 9 */ 10 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 #include <shared/bsl.h> 14 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(INCLUDE_L3) 15 #include <soc/drv.h> 16 #include <soc/scache_dictionary.h> 17 #include <bcm/error.h> 18 #include <bcm/types.h> 19 #include <bcm_int/esw/tomahawk.h> 20 21 #ifdef BCM_TOMAHAWK3_SUPPORT 22 #include <bcm_int/esw/tomahawk3.h> 23 #endif 24 25 #define _TH_NUM_TRUNKS(unit) \ 26 (SOC_IS_TOMAHAWK3(unit) ? 144 : 1024) 27 #define _TH_NUM_AGGID_PER_PIPE(unit) \ 28 (SOC_IS_TOMAHAWK3(unit) ? \ 29 (soc_mem_field_length(unit, MMU_REPL_GROUP_INFO_TBLm, MEMBER_BMPf)) : \ 30 (soc_mem_field_length(unit, MMU_REPL_GROUP_INFO_TBLm, PIPE_MEMBER_BMPf))) 31 #define _TH_MAX_NUM_TRUNKS 1024 32 33 typedef struct _bcm_th_aggid_used_bmp_per_pipe_s { 34 SHR_BITDCL* pipe_aggid_bmp; 35 } _bcm_th_aggid_used_bmp_per_pipe_t; 36 37 STATIC _bcm_th_aggid_used_bmp_per_pipe_t *th_aggid_used_bmp[BCM_MAX_NUM_UNITS]; 38 39 typedef struct _bcm_th_trunk_aggid_info_s { 40 int agg_id; 41 int ref_cnt; 42 } _bcm_th_trunk_aggid_info_t; 43 44 typedef struct _bcm_th_trunk_aggid_per_pipe_info_s { 45 _bcm_th_trunk_aggid_info_t trunk_aggid_info[_TH_MAX_NUM_TRUNKS]; 46 } _bcm_th_trunk_aggid_per_pipe_info_t; 47 48 typedef struct _bcm_th_port_aggid_info_s { 49 int agg_id; 50 int ref_cnt; /* The number of the pair <mc group, nexthop> pointing to it. */ 51 int trunk_id; 52 } _bcm_th_port_aggid_info_t; 53 54 STATIC _bcm_th_trunk_aggid_per_pipe_info_t *th_trunk_aggid[BCM_MAX_NUM_UNITS]; 55 56 STATIC _bcm_th_port_aggid_info_t *th_port_aggid[BCM_MAX_NUM_UNITS]; 57 58 59 /* 60 * Function: 61 * bcm_th_aggid_info_detach 62 * Purpose: 63 * Free aggregation ID list. 64 * Parameters: 65 * unit - (IN) Unit number. 66 * Returns: 67 * BCM_E_XXX 68 */ 69 int 70 bcm_th_aggid_info_detach(int unit) 71 { 72 int num_pipes; 73 int i; 74 SHR_BITDCL *pipe_aggid_bmp; 75 76 num_pipes = NUM_PIPE(unit); 77 #ifdef BCM_TOMAHAWK3_SUPPORT 78 if(SOC_IS_TOMAHAWK3(unit)) { 79 /* IPMC repl is pipe independent in TH3 */ 80 num_pipes = 1; 81 } 82 #endif 83 if (th_aggid_used_bmp[unit] != NULL) { 84 for (i = 0; i < num_pipes; i++) { 85 pipe_aggid_bmp = th_aggid_used_bmp[unit][i].pipe_aggid_bmp; 86 if (pipe_aggid_bmp != NULL) { 87 sal_free(pipe_aggid_bmp); 88 pipe_aggid_bmp = NULL; 89 } 90 } 91 sal_free(th_aggid_used_bmp[unit]); 92 th_aggid_used_bmp[unit] = NULL; 93 } 94 95 if (th_trunk_aggid[unit] != NULL) { 96 sal_free(th_trunk_aggid[unit]); 97 th_trunk_aggid[unit] = NULL; 98 } 99 100 if (th_port_aggid[unit] != NULL) { 101 sal_free(th_port_aggid[unit]); 102 th_port_aggid[unit] = NULL; 103 } 104 105 return BCM_E_NONE; 106 } 107 108 /* 109 * Function: 110 * bcm_th_aggid_info_init 111 * Purpose: 112 * Initialize aggregation ID to trunk map array. 113 * Parameters: 114 * unit - (IN) Unit number. 115 * Returns: 116 * BCM_E_XXX 117 */ 118 int 119 bcm_th_aggid_info_init(int unit) 120 { 121 int num_pipes; 122 int i, j; 123 _bcm_th_trunk_aggid_info_t *trunk_aggid_info; 124 _bcm_th_port_aggid_info_t *port_aggid_info; 125 126 127 if (!SOC_UNIT_VALID(unit)) { 128 return BCM_E_UNIT; 129 } 130 131 num_pipes = NUM_PIPE(unit); 132 133 #ifdef BCM_TOMAHAWK3_SUPPORT 134 if(SOC_IS_TOMAHAWK3(unit)) { 135 /* IPMC repl is pipe independent in TH3 */ 136 num_pipes = 1; 137 } 138 #endif 139 bcm_th_aggid_info_detach(unit); 140 141 142 th_aggid_used_bmp[unit] = 143 sal_alloc((num_pipes * sizeof(_bcm_th_aggid_used_bmp_per_pipe_t)), 144 "aggid_used_bmp_info"); 145 if (th_aggid_used_bmp[unit] == NULL) { 146 return BCM_E_MEMORY; 147 } 148 for (i = 0; i < num_pipes; i++) { 149 th_aggid_used_bmp[unit][i].pipe_aggid_bmp = 150 sal_alloc(SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit)), 151 "aggid_used_bmp_per_piep_info"); 152 if (th_aggid_used_bmp[unit][i].pipe_aggid_bmp == NULL) { 153 bcm_th_aggid_info_detach(unit); 154 return BCM_E_MEMORY; 155 } 156 sal_memset(th_aggid_used_bmp[unit][i].pipe_aggid_bmp, 0, 157 SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit))); 158 } 159 160 /* Init trunk aggid info. */ 161 th_trunk_aggid[unit] = 162 sal_alloc((num_pipes * sizeof(_bcm_th_trunk_aggid_per_pipe_info_t)), 163 "trunk_aggid_info"); 164 if (th_trunk_aggid[unit] == NULL) { 165 bcm_th_aggid_info_detach(unit); 166 return BCM_E_MEMORY; 167 } 168 for (i = 0; i < num_pipes; i++) { 169 for (j = 0; j < _TH_NUM_TRUNKS(unit); j++) { 170 trunk_aggid_info = &(th_trunk_aggid[unit][i].trunk_aggid_info[j]); 171 trunk_aggid_info->agg_id = TH_AGG_ID_INVALID; 172 trunk_aggid_info->ref_cnt = 0; 173 } 174 } 175 176 /* Init port aggid info. */ 177 th_port_aggid[unit] = 178 sal_alloc((SOC_MAX_NUM_PORTS * sizeof(_bcm_th_port_aggid_info_t)), 179 "port_aggid_info"); 180 if (th_port_aggid[unit] == NULL) { 181 bcm_th_aggid_info_detach(unit); 182 return BCM_E_MEMORY; 183 } 184 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 185 port_aggid_info = &th_port_aggid[unit][i]; 186 port_aggid_info->agg_id = TH_AGG_ID_INVALID; 187 port_aggid_info->ref_cnt = 0; 188 port_aggid_info->trunk_id = BCM_TRUNK_INVALID; 189 } 190 191 return BCM_E_NONE; 192 } 193 194 /* 195 * Function: 196 * bcm_th_get_free_aggid 197 * Purpose: 198 * Get a free aggid for given pipe. 199 * Parameters: 200 * unit - (IN) Unit number. 201 * pipe - (IN) Pipe id. 202 * aggid - (OUT) Returned aggid. 203 * Returns: 204 * BCM_E_XXX 205 */ 206 STATIC int 207 bcm_th_get_free_aggid(int unit, int pipe, int *aggid) 208 { 209 SHR_BITDCL *aggid_bmp; 210 int i; 211 212 aggid_bmp = th_aggid_used_bmp[unit][pipe].pipe_aggid_bmp; 213 for (i = 0; i < _TH_NUM_AGGID_PER_PIPE(unit); i++) { 214 if (!SHR_BITGET(aggid_bmp, i)) { 215 *aggid = i; 216 SHR_BITSET(aggid_bmp, i); 217 return BCM_E_NONE; 218 } 219 } 220 221 if (i == _TH_NUM_AGGID_PER_PIPE(unit)) { 222 return BCM_E_FULL; 223 } 224 225 return BCM_E_NONE; 226 227 } 228 229 /* 230 * Function: 231 * bcm_th_set_free_aggid 232 * Purpose: 233 * Free aggid for given pipe. 234 * Parameters: 235 * unit - (IN) Unit number. 236 * pipe - (IN) Pipe id. 237 * aggid - (IN) Aggregation ID. 238 * Returns: 239 * BCM_E_XXX 240 */ 241 STATIC int 242 bcm_th_set_free_aggid(int unit, int pipe, int aggid) 243 { 244 SHR_BITDCL *aggid_bmp; 245 246 aggid_bmp = th_aggid_used_bmp[unit][pipe].pipe_aggid_bmp; 247 if (aggid >= _TH_NUM_AGGID_PER_PIPE(unit)) { 248 return BCM_E_PARAM; 249 } 250 SHR_BITCLR(aggid_bmp, aggid); 251 252 return BCM_E_NONE; 253 } 254 255 /* 256 * Function: 257 * bcm_th_set_port_hw_agg_map 258 * Purpose: 259 * Set HW aggid map register for a port. 260 * Parameters: 261 * unit - (IN) Unit number. 262 * port - (IN) Logical Port. 263 * aggid - (IN) Aggregation ID. 264 * Returns: 265 * BCM_E_XXX 266 */ 267 int 268 bcm_th_set_port_hw_agg_map(int unit, bcm_port_t port, int aggid) 269 { 270 uint32 regval; 271 #ifdef BCM_TOMAHAWK3_SUPPORT 272 if(SOC_IS_TOMAHAWK3(unit)) { 273 BCM_IF_ERROR_RETURN(READ_MMU_RQE_REPL_PORT_AGG_MAPr(unit, port, 274 ®val)); 275 soc_reg_field_set(unit, MMU_RQE_REPL_PORT_AGG_MAPr, ®val, 276 L3MC_PORT_AGG_IDf, aggid); 277 SOC_IF_ERROR_RETURN( 278 soc_reg32_set(unit, MMU_RQE_REPL_PORT_AGG_MAPr, port, 0, regval)); 279 return BCM_E_NONE; 280 } 281 #endif 282 BCM_IF_ERROR_RETURN(READ_MMU_DQS_REPL_PORT_AGG_MAPr(unit, port, ®val)); 283 soc_reg_field_set(unit, MMU_DQS_REPL_PORT_AGG_MAPr, ®val, 284 L3MC_PORT_AGG_IDf, aggid); 285 SOC_IF_ERROR_RETURN( 286 soc_reg32_set(unit, MMU_DQS_REPL_PORT_AGG_MAPr, port, 0, regval)); 287 288 return BCM_E_NONE; 289 } 290 291 /* 292 * Function: 293 * bcm_th_aggid_add 294 * Purpose: 295 * Increase aggid refcnt of a independ port or trunk. 296 * Parameters: 297 * unit - (IN) Unit number. 298 * port - (IN) Logical Port. 299 * tgid - (IN) Trunk id. 300 * aggid - (OUT) Returned aggid. 301 * Returns: 302 * BCM_E_XXX 303 */ 304 STATIC int 305 bcm_th_aggid_add(int unit, bcm_port_t port, bcm_trunk_t tgid, int *aggid) 306 { 307 int rv = BCM_E_NONE; 308 int pipe; 309 _bcm_th_trunk_aggid_info_t *trunk_aggid_info; 310 _bcm_th_port_aggid_info_t *port_aggid_info; 311 312 if (((tgid != BCM_TRUNK_INVALID) && (tgid < 0 || tgid >= _TH_NUM_TRUNKS(unit))) || 313 (port < 0 || port >= SOC_MAX_NUM_PORTS) || 314 (aggid == NULL)) { 315 return BCM_E_PARAM; 316 } 317 318 pipe = SOC_INFO(unit).port_pipe[port]; 319 #ifdef BCM_TOMAHAWK3_SUPPORT 320 if(SOC_IS_TOMAHAWK3(unit)) { 321 pipe = 0; 322 } 323 #endif 324 if (tgid != BCM_TRUNK_INVALID) { 325 trunk_aggid_info = &(th_trunk_aggid[unit][pipe].trunk_aggid_info[tgid]); 326 if (trunk_aggid_info->agg_id == TH_AGG_ID_INVALID) { 327 BCM_IF_ERROR_RETURN(bcm_th_get_free_aggid(unit, pipe, aggid)); 328 trunk_aggid_info->agg_id = *aggid; 329 trunk_aggid_info->ref_cnt = 1; 330 } else { 331 *aggid = trunk_aggid_info->agg_id; 332 trunk_aggid_info->ref_cnt++; 333 } 334 } else { 335 port_aggid_info = &(th_port_aggid[unit][port]); 336 if (port_aggid_info->agg_id == TH_AGG_ID_INVALID) { 337 BCM_IF_ERROR_RETURN(bcm_th_get_free_aggid(unit, pipe, aggid)); 338 rv = bcm_th_set_port_hw_agg_map(unit, port, *aggid); 339 if (BCM_FAILURE(rv)) { 340 bcm_th_set_free_aggid(unit, pipe, *aggid); 341 return rv; 342 } 343 port_aggid_info->agg_id = *aggid; 344 port_aggid_info->ref_cnt = 1; 345 port_aggid_info->trunk_id = BCM_TRUNK_INVALID; 346 } else { 347 *aggid = port_aggid_info->agg_id; 348 port_aggid_info->ref_cnt++; 349 } 350 } 351 352 return BCM_E_NONE; 353 } 354 355 /* 356 * Function: 357 * bcm_th_aggid_del 358 * Purpose: 359 * Decrease aggid refcnt of a independ port or trunk. 360 * Parameters: 361 * unit - (IN) Unit number. 362 * port - (IN) Logical Port. 363 * Returns: 364 * BCM_E_XXX 365 */ 366 STATIC int 367 bcm_th_aggid_del(int unit, bcm_port_t port) 368 { 369 int pipe; 370 bcm_trunk_t tgid; 371 int rv; 372 _bcm_th_trunk_aggid_info_t *trunk_aggid_info; 373 _bcm_th_port_aggid_info_t *port_aggid_info; 374 375 if ((port < 0) || (port >= SOC_MAX_NUM_PORTS)) { 376 return BCM_E_PARAM; 377 } 378 port_aggid_info = &(th_port_aggid[unit][port]); 379 tgid = port_aggid_info->trunk_id; 380 pipe = SOC_INFO(unit).port_pipe[port]; 381 #ifdef BCM_TOMAHAWK3_SUPPORT 382 if(SOC_IS_TOMAHAWK3(unit)) { 383 pipe = 0; 384 } 385 #endif 386 if (tgid != BCM_TRUNK_INVALID) { 387 trunk_aggid_info = &(th_trunk_aggid[unit][pipe].trunk_aggid_info[tgid]); 388 if (trunk_aggid_info->ref_cnt <= 0) { 389 return BCM_E_PARAM; 390 } 391 trunk_aggid_info->ref_cnt--; 392 if (trunk_aggid_info->ref_cnt == 0) { 393 bcm_th_set_free_aggid(unit, pipe, trunk_aggid_info->agg_id); 394 trunk_aggid_info->agg_id = TH_AGG_ID_INVALID; 395 } 396 if (port_aggid_info->ref_cnt == 0) { 397 port_aggid_info->trunk_id = BCM_TRUNK_INVALID; 398 } 399 } else { 400 if (port_aggid_info->ref_cnt <= 0) { 401 return BCM_E_PARAM; 402 } 403 port_aggid_info->ref_cnt--; 404 if (port_aggid_info->ref_cnt == 0) { 405 #ifdef BCM_TOMAHAWK3_SUPPORT 406 if (SOC_IS_TOMAHAWK3(unit)) { 407 rv = bcm_th_set_port_hw_agg_map(unit, port, TH3_AGG_ID_HW_INVALID); 408 409 } else 410 #endif 411 { 412 rv = bcm_th_set_port_hw_agg_map(unit, port, TH_AGG_ID_HW_INVALID); 413 } 414 if (BCM_FAILURE(rv)) { 415 port_aggid_info->ref_cnt++; 416 return rv; 417 } 418 bcm_th_set_free_aggid(unit, pipe, port_aggid_info->agg_id); 419 port_aggid_info->agg_id = TH_AGG_ID_INVALID; 420 } 421 } 422 423 return BCM_E_NONE; 424 } 425 426 427 /* 428 * Function: 429 * bcm_th_aggid_ref_inc_for_member 430 * Purpose: 431 * Increase aggid refcount for a trunk member port. 432 * Parameters: 433 * unit - (IN) Unit number. 434 * port - (IN) Logical Port. 435 * tgid - (IN) Trunk id. 436 * Returns: 437 * BCM_E_XXX 438 */ 439 STATIC int 440 bcm_th_aggid_ref_inc_for_member(int unit, bcm_port_t port, bcm_trunk_t tgid) 441 { 442 int aggid, pipe; 443 _bcm_th_port_aggid_info_t *port_aggid_info; 444 445 if (port < 0 || port >= SOC_MAX_NUM_PORTS) { 446 return BCM_E_PARAM; 447 } 448 449 port_aggid_info = &(th_port_aggid[unit][port]); 450 if (port_aggid_info->agg_id != TH_AGG_ID_INVALID) { 451 return BCM_E_PARAM; 452 } 453 454 if (port_aggid_info->trunk_id == BCM_TRUNK_INVALID) { 455 /* This is the first time that member port joined trunk tgid. 456 * For member port, it just uses trunk's agg_id not itself. 457 */ 458 if (port_aggid_info->ref_cnt != 0) { 459 return BCM_E_PARAM; 460 } 461 port_aggid_info->trunk_id = tgid; 462 port_aggid_info->ref_cnt = 1; 463 pipe = SOC_INFO(unit).port_pipe[port]; 464 #ifdef BCM_TOMAHAWK3_SUPPORT 465 if (SOC_IS_TOMAHAWK3(unit)) { 466 pipe = 0; 467 } 468 #endif 469 aggid = th_trunk_aggid[unit][pipe].trunk_aggid_info[tgid].agg_id; 470 BCM_IF_ERROR_RETURN(bcm_th_set_port_hw_agg_map(unit, port, aggid)); 471 } else { 472 /* member port has joined one trunk. */ 473 if (port_aggid_info->trunk_id != tgid) { 474 return BCM_E_PARAM; 475 } 476 port_aggid_info->ref_cnt++; 477 } 478 479 return BCM_E_NONE; 480 } 481 482 /* 483 * Function: 484 * bcm_th_aggid_ref_dec_for_member 485 * Purpose: 486 * Decrease aggid refcount for a trunk member port. 487 * Parameters: 488 * unit - (IN) Unit number. 489 * port - (IN) Logical Port. 490 * Returns: 491 * BCM_E_XXX 492 */ 493 STATIC int 494 bcm_th_aggid_ref_dec_for_member(int unit, bcm_port_t port) 495 { 496 _bcm_th_port_aggid_info_t *port_aggid_info; 497 int rv; 498 499 if (port < 0 || port >= SOC_MAX_NUM_PORTS) { 500 return BCM_E_PARAM; 501 } 502 503 port_aggid_info = &(th_port_aggid[unit][port]); 504 if (port_aggid_info->trunk_id == BCM_TRUNK_INVALID) { 505 return BCM_E_PARAM; 506 } 507 508 if (port_aggid_info->ref_cnt <= 0) { 509 return BCM_E_PARAM; 510 } 511 512 port_aggid_info->ref_cnt--; 513 if (port_aggid_info->ref_cnt == 0) { 514 /* All (port, mc group) has can leave the trunk. 515 * Do not set port_aggid_info->trunk_id to BCM_TRUNK_INVALID here. 516 */ 517 #ifdef BCM_TOMAHAWK3_SUPPORT 518 if (SOC_IS_TOMAHAWK3(unit)) { 519 rv = bcm_th_set_port_hw_agg_map(unit, port, TH3_AGG_ID_HW_INVALID); 520 } else 521 #endif 522 { 523 rv = bcm_th_set_port_hw_agg_map(unit, port, TH_AGG_ID_HW_INVALID); 524 } 525 if (BCM_FAILURE(rv)) { 526 port_aggid_info->ref_cnt++; 527 return rv; 528 } 529 } 530 531 return BCM_E_NONE; 532 } 533 534 /* 535 * Function: 536 * bcm_th_port_aggid_add 537 * Purpose: 538 * Add a aggid for a logical port. 539 * Parameters: 540 * unit - (IN) Unit number. 541 * port - (IN) Logical Port. 542 * tgid - (IN) Trunk id. 543 * aggid - (OUT) Returned aggid. 544 * Returns: 545 * BCM_E_XXX 546 */ 547 int 548 bcm_th_port_aggid_add(int unit, bcm_port_t port, bcm_trunk_t tgid, int *aggid) 549 { 550 int rv; 551 552 if (tgid != BCM_TRUNK_INVALID) { 553 rv = bcm_th_aggid_add(unit, port, tgid, aggid); 554 if (BCM_FAILURE(rv)) { 555 return rv; 556 } 557 rv = bcm_th_aggid_ref_inc_for_member(unit, port, tgid); 558 if (BCM_FAILURE(rv)) { 559 bcm_th_aggid_del(unit, port); 560 return rv; 561 } 562 } else { 563 rv = bcm_th_aggid_add(unit, port, tgid, aggid); 564 if (BCM_FAILURE(rv)) { 565 return rv; 566 } 567 } 568 569 return BCM_E_NONE; 570 } 571 572 /* 573 * Function: 574 * bcm_th_port_aggid_del 575 * Purpose: 576 * Del aggid of a logical port. 577 * Parameters: 578 * unit - (IN) Unit number. 579 * port - (IN) Logical Port. 580 * Returns: 581 * BCM_E_XXX 582 */ 583 int 584 bcm_th_port_aggid_del(int unit, bcm_port_t port) 585 { 586 _bcm_th_port_aggid_info_t *port_aggid_info; 587 bcm_trunk_t tgid; 588 int rv; 589 590 if (port < 0 || port >= SOC_MAX_NUM_PORTS) { 591 return BCM_E_PARAM; 592 } 593 594 port_aggid_info = &(th_port_aggid[unit][port]); 595 tgid = port_aggid_info->trunk_id; 596 597 if (tgid != BCM_TRUNK_INVALID) { 598 rv = bcm_th_aggid_ref_dec_for_member(unit, port); 599 if (BCM_FAILURE(rv)) { 600 return rv; 601 } 602 rv = bcm_th_aggid_del(unit, port); 603 if (BCM_FAILURE(rv)) { 604 bcm_th_aggid_ref_inc_for_member(unit, port, tgid); 605 return rv; 606 } 607 } else { 608 rv = bcm_th_aggid_del(unit, port); 609 if (BCM_FAILURE(rv)) { 610 return rv; 611 } 612 } 613 614 return BCM_E_NONE; 615 } 616 617 /* 618 * Function: 619 * bcm_th_port_trunkid_get 620 * Purpose: 621 * When port has been removed from trunk in trunk module, 622 * we could only get trunkid of port from previous saved DB. 623 * Parameters: 624 * unit - (IN) Unit number. 625 * port - (IN) Logical Port 626 * tgid - (OUT) returned Trunk id. 627 * Returns: 628 * BCM_E_XXX 629 * Note: This function only can be used when deleting port from trunk. 630 */ 631 int 632 bcm_th_port_trunkid_get(int unit, bcm_port_t port, int *tgid) 633 { 634 _bcm_th_port_aggid_info_t *port_aggid_info; 635 636 if ((port < 0 || port >= SOC_MAX_NUM_PORTS) || 637 (tgid == NULL)) { 638 return BCM_E_PARAM; 639 } 640 641 port_aggid_info = &(th_port_aggid[unit][port]); 642 *tgid = port_aggid_info->trunk_id; 643 644 return BCM_E_NONE; 645 } 646 647 /* 648 * Function: 649 * bcm_th_port_last_member_check 650 * Purpose: 651 * Check whether a member port is the last member of its trunk. 652 * Parameters: 653 * unit - (IN) Unit number. 654 * port - (IN) Logical Port 655 * val - (OUT) returned val. 656 * Returns: 657 * BCM_E_XXX 658 */ 659 int 660 bcm_th_port_last_member_check(int unit, bcm_port_t port, int *val) 661 { 662 int pipe; 663 bcm_trunk_t tgid; 664 _bcm_th_port_aggid_info_t *port_aggid_info; 665 int i; 666 int member_cnt = 0; 667 668 if (port < 0 || port >= SOC_MAX_NUM_PORTS) { 669 return BCM_E_PARAM; 670 } 671 672 pipe = SOC_INFO(unit).port_pipe[port]; 673 674 port_aggid_info = &(th_port_aggid[unit][port]); 675 tgid = port_aggid_info->trunk_id; 676 if (tgid == BCM_TRUNK_INVALID) { 677 return BCM_E_PARAM; 678 } 679 680 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 681 if (member_cnt > 1) { 682 *val = FALSE; 683 return BCM_E_NONE; 684 } 685 port_aggid_info = &(th_port_aggid[unit][i]); 686 #ifdef BCM_TOMAHAWK3_SUPPORT 687 if (SOC_IS_TOMAHAWK3(unit)) { 688 if (port_aggid_info->trunk_id == tgid) { 689 member_cnt++; 690 } 691 } else 692 #endif 693 if ((port_aggid_info->trunk_id == tgid) && 694 (SOC_INFO(unit).port_pipe[i] == pipe)) { 695 member_cnt++; 696 } 697 } 698 699 if (member_cnt > 1) { 700 *val = FALSE; 701 } else { 702 *val = TRUE; 703 } 704 705 return BCM_E_NONE; 706 } 707 708 /* 709 * Function: 710 * bcm_th_port_to_aggid 711 * Purpose: 712 * Get aggid value for a logical port. 713 * Parameters: 714 * unit - (IN) Unit number. 715 * aggid - (OUT) Returned aggid. 716 * Returns: 717 * BCM_E_XXX 718 */ 719 int 720 bcm_th_port_to_aggid(int unit, bcm_port_t port, int *aggid) 721 { 722 int pipe; 723 bcm_trunk_t tgid; 724 _bcm_th_port_aggid_info_t *port_aggid_info; 725 _bcm_th_trunk_aggid_info_t *trunk_aggid_info; 726 727 if (port < 0 || port >= SOC_MAX_NUM_PORTS) { 728 return BCM_E_PARAM; 729 } 730 731 pipe = SOC_INFO(unit).port_pipe[port]; 732 #ifdef BCM_TOMAHAWK3_SUPPORT 733 if(SOC_IS_TOMAHAWK3(unit)) { 734 pipe = 0; 735 } 736 #endif 737 port_aggid_info = &(th_port_aggid[unit][port]); 738 tgid = port_aggid_info->trunk_id; 739 if (tgid == BCM_TRUNK_INVALID) { 740 *aggid = port_aggid_info->agg_id; 741 } else { 742 trunk_aggid_info = &(th_trunk_aggid[unit][pipe].trunk_aggid_info[tgid]); 743 *aggid = trunk_aggid_info->agg_id; 744 } 745 if (*aggid == TH_AGG_ID_INVALID) { 746 return BCM_E_INTERNAL; 747 } 748 749 return BCM_E_NONE; 750 } 751 752 753 #ifdef BCM_WARM_BOOT_SUPPORT 754 /* 755 * Function: 756 * bcm_th_ipmc_aggid_info_scache_size_get 757 * Purpose: 758 * Get the required scache size for storing aggid info. 759 * Parameters: 760 * unit - (IN) StrataSwitch unit # 761 * size - (OUT) Number of bytes 762 * Returns: 763 * BCM_E_xxx 764 */ 765 int 766 bcm_th_ipmc_aggid_info_scache_size_get( 767 int unit, uint32 *size) 768 { 769 int num_pipes; 770 int aggid_used_bmp_size, trunk_aggid_size, port_aggid_size; 771 772 *size = 0; 773 774 num_pipes = NUM_PIPE(unit); 775 #ifdef BCM_TOMAHAWK3_SUPPORT 776 if(SOC_IS_TOMAHAWK3(unit)) { 777 /* IPMC repl is pipe independent in TH3 */ 778 num_pipes = 1; 779 } 780 #endif 781 aggid_used_bmp_size = 782 num_pipes * SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit)); 783 *size += aggid_used_bmp_size; 784 785 trunk_aggid_size = 786 num_pipes * (_TH_NUM_TRUNKS(unit) * sizeof(_bcm_th_trunk_aggid_info_t)); 787 *size += trunk_aggid_size; 788 789 port_aggid_size = SOC_MAX_NUM_PORTS * sizeof(_bcm_th_port_aggid_info_t); 790 *size += port_aggid_size; 791 792 return BCM_E_NONE; 793 } 794 795 /* 796 * Function: 797 * bcm_th_ipmc_aggid_info_sync 798 * Purpose: 799 * Sync aggid info to scache. 800 * Parameters: 801 * unit - (IN) StrataSwitch unit # 802 * scache_ptr - (IN/OUT) Scache pointer 803 * Returns: 804 * BCM_E_xxx 805 */ 806 int bcm_th_ipmc_aggid_info_sync(int unit, uint8 **scache_ptr) 807 { 808 int num_pipes; 809 int aggid_used_bmp_size, trunk_aggid_size, port_aggid_size; 810 int i; 811 812 num_pipes = NUM_PIPE(unit); 813 #ifdef BCM_TOMAHAWK3_SUPPORT 814 if(SOC_IS_TOMAHAWK3(unit)) { 815 /* IPMC repl is pipe independent in TH3 */ 816 num_pipes = 1; 817 } 818 #endif 819 aggid_used_bmp_size = SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit)); 820 for (i = 0; i < num_pipes; i++) { 821 sal_memcpy((*scache_ptr), th_aggid_used_bmp[unit][i].pipe_aggid_bmp, 822 aggid_used_bmp_size); 823 (*scache_ptr) += aggid_used_bmp_size; 824 } 825 826 trunk_aggid_size = _TH_NUM_TRUNKS(unit) * sizeof(_bcm_th_trunk_aggid_info_t); 827 for (i = 0; i < num_pipes; i++) { 828 sal_memcpy((*scache_ptr), th_trunk_aggid[unit] + i, trunk_aggid_size); 829 (*scache_ptr) += trunk_aggid_size; 830 } 831 832 port_aggid_size = SOC_MAX_NUM_PORTS * sizeof(_bcm_th_port_aggid_info_t); 833 sal_memcpy((*scache_ptr), th_port_aggid[unit], port_aggid_size); 834 (*scache_ptr) += port_aggid_size; 835 836 return BCM_E_NONE; 837 } 838 839 840 /* 841 * Function: 842 * bcm_th_ipmc_aggid_info_recover 843 * Purpose: 844 * Recover aggid info from scache. 845 * Parameters: 846 * unit - (IN) StrataSwitch unit # 847 * scache_ptr - (IN/OUT) Scache pointer 848 * Returns: 849 * BCM_E_xxx 850 */ 851 int 852 bcm_th_ipmc_aggid_info_recover(int unit, uint8 **scache_ptr) 853 { 854 int num_pipes; 855 int aggid_used_bmp_size, trunk_aggid_size, port_aggid_size; 856 int i; 857 int max_num_ports, scache_sz; 858 859 max_num_ports = soc_scache_dictionary_entry_get(unit, 860 ssden_SOC_MAX_NUM_PORTS, 861 SOC_MAX_NUM_PORTS); 862 num_pipes = NUM_PIPE(unit); 863 #ifdef BCM_TOMAHAWK3_SUPPORT 864 if(SOC_IS_TOMAHAWK3(unit)) { 865 /* IPMC repl is pipe independent in TH3 */ 866 num_pipes = 1; 867 } 868 #endif 869 aggid_used_bmp_size = SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit)); 870 for (i = 0; i < num_pipes; i++) { 871 sal_memcpy(th_aggid_used_bmp[unit][i].pipe_aggid_bmp, 872 (*scache_ptr), aggid_used_bmp_size); 873 (*scache_ptr) += aggid_used_bmp_size; 874 } 875 876 trunk_aggid_size = _TH_NUM_TRUNKS(unit) * sizeof(_bcm_th_trunk_aggid_info_t); 877 for (i = 0; i < num_pipes; i++) { 878 sal_memcpy(th_trunk_aggid[unit] + i, (*scache_ptr), trunk_aggid_size); 879 (*scache_ptr) += trunk_aggid_size; 880 } 881 882 port_aggid_size = SOC_MAX_NUM_PORTS * sizeof(_bcm_th_port_aggid_info_t); 883 scache_sz = max_num_ports * sizeof(_bcm_th_port_aggid_info_t); 884 885 SOC_SCACHE_SIZE_MIN_RECOVER(*scache_ptr, th_port_aggid[unit], 886 scache_sz, port_aggid_size); 887 888 return BCM_E_NONE; 889 } 890 891 #endif /* BCM_WARM_BOOT_SUPPORT */ 892 893 #endif 894