port.c (23266B)
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 8 #include <soc/defs.h> 9 10 #include <assert.h> 11 12 #include <sal/core/libc.h> 13 #if defined(BCM_GREYHOUND_SUPPORT) 14 #include <shared/util.h> 15 #include <soc/mem.h> 16 #include <soc/cm.h> 17 #include <soc/drv.h> 18 #include <soc/register.h> 19 #include <soc/memory.h> 20 #include <soc/hash.h> 21 #include <bcm_int/esw/port.h> 22 #include <bcm_int/esw/stack.h> 23 #include <bcm_int/esw/greyhound.h> 24 #include <bcm_int/esw_dispatch.h> 25 26 /* 27 * Function: 28 * bcm_gh_port_niv_type_set 29 * Description: 30 * Set NIV port type. 31 * Parameters: 32 * unit - (IN) Device number 33 * port - (IN) Port number 34 * value - (IN) NIV port type 35 * Return Value: 36 * BCM_E_XXX 37 */ 38 int 39 bcm_gh_port_niv_type_set(int unit, bcm_port_t port, int value) 40 { 41 bcm_module_t my_modid; 42 int mod_port_index; 43 uint64 val64; 44 45 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 46 DISCARD_IF_VNTAG_NOT_PRESENTf, 0)); 47 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 48 DISCARD_IF_VNTAG_PRESENTf, 0)); 49 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 50 VNTAG_ACTIONS_IF_PRESENTf, VNTAG_NOOP)); 51 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 52 VNTAG_ACTIONS_IF_NOT_PRESENTf, VNTAG_NOOP)); 53 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 54 TX_DEST_PORT_ENABLEf, 0)); 55 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 56 NIV_VIF_LOOKUP_ENABLEf, 0)); 57 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 58 NIV_RPF_CHECK_ENABLEf, 0)); 59 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 60 NIV_UPLINK_PORTf, 0)); 61 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 62 VT_ENABLEf, 0)); 63 64 BCM_IF_ERROR_RETURN(bcm_esw_port_control_set(unit, port, 65 bcmPortControlDoNotCheckVlan, 0)); 66 67 BCM_IF_ERROR_RETURN(READ_EGR_PORT_64r(unit, port, &val64)); 68 soc_reg64_field32_set(unit, EGR_PORT_64r, &val64, \ 69 VNTAG_ACTIONS_IF_PRESENTf, VNTAG_NOOP); 70 soc_reg64_field32_set(unit, EGR_PORT_64r, &val64, \ 71 NIV_PRUNE_ENABLEf, 0); 72 soc_reg64_field32_set(unit, EGR_PORT_64r, &val64, \ 73 NIV_UPLINK_PORTf, 0); 74 SOC_IF_ERROR_RETURN(WRITE_EGR_PORT_64r(unit, port, val64)); 75 76 77 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 78 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, 79 my_modid, port, &mod_port_index)); 80 81 switch (value) { 82 case BCM_PORT_NIV_TYPE_NONE: 83 break; 84 case BCM_PORT_NIV_TYPE_SWITCH: 85 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 86 _BCM_CPU_TABS_ETHER, VT_KEY_TYPE_USE_GLPf, 1)); 87 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 88 _BCM_CPU_TABS_ETHER, VT_ENABLEf, 1)); 89 break; 90 91 case BCM_PORT_NIV_TYPE_UPLINK: 92 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 93 _BCM_CPU_TABS_ETHER, DISCARD_IF_VNTAG_NOT_PRESENTf, 1)); 94 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 95 _BCM_CPU_TABS_ETHER, NIV_VIF_LOOKUP_ENABLEf, 1)); 96 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 97 _BCM_CPU_TABS_ETHER, NIV_UPLINK_PORTf, 1)); 98 BCM_IF_ERROR_RETURN(bcm_esw_port_control_set(unit, port, 99 bcmPortControlDoNotCheckVlan, 1)); 100 101 BCM_IF_ERROR_RETURN(READ_EGR_PORT_64r(unit, port, &val64)); 102 soc_reg64_field32_set(unit, EGR_PORT_64r, &val64, \ 103 NIV_UPLINK_PORTf, 1); 104 SOC_IF_ERROR_RETURN(WRITE_EGR_PORT_64r(unit, port, val64)); 105 106 break; 107 108 case BCM_PORT_NIV_TYPE_DOWNLINK_ACCESS: 109 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 110 _BCM_CPU_TABS_ETHER, DISCARD_IF_VNTAG_PRESENTf, 1)); 111 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 112 _BCM_CPU_TABS_ETHER, VNTAG_ACTIONS_IF_NOT_PRESENTf, 113 VNTAG_ADD)); 114 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 115 _BCM_CPU_TABS_ETHER, TX_DEST_PORT_ENABLEf, 1)); 116 BCM_IF_ERROR_RETURN(bcm_esw_port_control_set(unit, port, 117 bcmPortControlDoNotCheckVlan, 1)); 118 119 BCM_IF_ERROR_RETURN(READ_EGR_PORT_64r(unit, port, &val64)); 120 soc_reg64_field32_set(unit, EGR_PORT_64r, &val64, \ 121 VNTAG_ACTIONS_IF_PRESENTf, VNTAG_DELETE); 122 soc_reg64_field32_set(unit, EGR_PORT_64r, &val64, \ 123 NIV_PRUNE_ENABLEf, 1); 124 SOC_IF_ERROR_RETURN(WRITE_EGR_PORT_64r(unit, port, val64)); 125 126 break; 127 128 case BCM_PORT_NIV_TYPE_DOWNLINK_TRANSIT: 129 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 130 _BCM_CPU_TABS_ETHER, DISCARD_IF_VNTAG_NOT_PRESENTf, 1)); 131 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 132 _BCM_CPU_TABS_ETHER, TX_DEST_PORT_ENABLEf, 1)); 133 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 134 _BCM_CPU_TABS_ETHER, NIV_RPF_CHECK_ENABLEf, 1)); 135 BCM_IF_ERROR_RETURN(bcm_esw_port_control_set(unit, port, 136 bcmPortControlDoNotCheckVlan, 1)); 137 break; 138 139 default: 140 return BCM_E_PARAM; 141 } 142 143 return BCM_E_NONE; 144 } 145 146 /* 147 * Function: 148 * bcm_gh_port_niv_type_get 149 * Description: 150 * Get NIV port type. 151 * Parameters: 152 * unit - (IN) Device number 153 * port - (IN) Port number 154 * value - (OUT) NIV port type 155 * Return Value: 156 * BCM_E_XXX 157 */ 158 int 159 bcm_gh_port_niv_type_get(int unit, bcm_port_t port, int *value) 160 { 161 int rv = BCM_E_NONE; 162 int vt_enable, uplink, rpf_enable, prune_enable; 163 uint64 val64; 164 165 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_get(unit, 166 port, VT_ENABLEf, &vt_enable)); 167 168 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_get(unit, 169 port, NIV_UPLINK_PORTf, &uplink)); 170 171 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_get(unit, 172 port, NIV_RPF_CHECK_ENABLEf, &rpf_enable)); 173 174 BCM_IF_ERROR_RETURN(READ_EGR_PORT_64r(unit, port, &val64)); 175 prune_enable = soc_reg64_field32_get(unit, EGR_PORT_64r, val64, 176 NIV_PRUNE_ENABLEf); 177 178 if (vt_enable) { 179 *value = BCM_PORT_NIV_TYPE_SWITCH; 180 } else if (uplink) { 181 *value = BCM_PORT_NIV_TYPE_UPLINK; 182 } else if (rpf_enable) { 183 *value = BCM_PORT_NIV_TYPE_DOWNLINK_TRANSIT; 184 } else if (prune_enable) { 185 *value = BCM_PORT_NIV_TYPE_DOWNLINK_ACCESS; 186 } else { 187 *value = BCM_PORT_NIV_TYPE_NONE; 188 } 189 190 return rv; 191 } 192 193 /* 194 * Function: 195 * bcm_gh_port_extender_type_set 196 * Description: 197 * Set Port Extender port type. 198 * Parameters: 199 * unit - (IN) Device number 200 * port - (IN) Port number 201 * value - (IN) Port type 202 * Return Value: 203 * BCM_E_XXX 204 */ 205 int 206 bcm_gh_port_extender_type_set(int unit, bcm_port_t port, int value) 207 { 208 switch (value) { 209 case BCM_PORT_EXTENDER_TYPE_NONE: 210 BCM_IF_ERROR_RETURN(bcm_gh_port_niv_type_set(unit, port, 211 BCM_PORT_NIV_TYPE_NONE)); 212 break; 213 case BCM_PORT_EXTENDER_TYPE_SWITCH: 214 BCM_IF_ERROR_RETURN(bcm_gh_port_niv_type_set(unit, port, 215 BCM_PORT_NIV_TYPE_SWITCH)); 216 break; 217 case BCM_PORT_EXTENDER_TYPE_UPLINK: 218 BCM_IF_ERROR_RETURN(bcm_gh_port_niv_type_set(unit, port, 219 BCM_PORT_NIV_TYPE_UPLINK)); 220 break; 221 case BCM_PORT_EXTENDER_TYPE_DOWNLINK_ACCESS: 222 BCM_IF_ERROR_RETURN(bcm_gh_port_niv_type_set(unit, port, 223 BCM_PORT_NIV_TYPE_DOWNLINK_ACCESS)); 224 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 225 _BCM_CPU_TABS_ETHER, VNTAG_ACTIONS_IF_NOT_PRESENTf, 226 2)); 227 break; 228 case BCM_PORT_EXTENDER_TYPE_DOWNLINK_TRANSIT: 229 BCM_IF_ERROR_RETURN(bcm_gh_port_niv_type_set(unit, port, 230 BCM_PORT_NIV_TYPE_DOWNLINK_TRANSIT)); 231 break; 232 default: 233 return BCM_E_PARAM; 234 } 235 236 return BCM_E_NONE; 237 } 238 239 /* 240 * Function: 241 * bcm_gh_port_extender_type_get 242 * Description: 243 * Get Port Extender port type. 244 * Parameters: 245 * unit - (IN) Device number 246 * port - (IN) Port number 247 * value - (IN) Port type 248 * Return Value: 249 * BCM_E_XXX 250 */ 251 int 252 bcm_gh_port_extender_type_get(int unit, bcm_port_t port, int *value) 253 { 254 int type; 255 256 BCM_IF_ERROR_RETURN(bcm_gh_port_niv_type_get(unit, port, &type)); 257 switch (type) { 258 case BCM_PORT_NIV_TYPE_NONE: 259 *value = BCM_PORT_EXTENDER_TYPE_NONE; 260 break; 261 case BCM_PORT_NIV_TYPE_SWITCH: 262 *value = BCM_PORT_EXTENDER_TYPE_SWITCH; 263 break; 264 case BCM_PORT_NIV_TYPE_UPLINK: 265 *value = BCM_PORT_EXTENDER_TYPE_UPLINK; 266 break; 267 case BCM_PORT_NIV_TYPE_DOWNLINK_ACCESS: 268 *value = BCM_PORT_EXTENDER_TYPE_DOWNLINK_ACCESS; 269 break; 270 case BCM_PORT_NIV_TYPE_DOWNLINK_TRANSIT: 271 *value = BCM_PORT_EXTENDER_TYPE_DOWNLINK_TRANSIT; 272 break; 273 default: 274 return BCM_E_INTERNAL; 275 } 276 277 return BCM_E_NONE; 278 } 279 280 #if defined(INCLUDE_L3) 281 /* 282 * Function: 283 * bcm_gh_port_etag_pcp_de_source_set 284 * Description: 285 * Set source of ETAG's PCP and DE fields. 286 * Parameters: 287 * unit - (IN) Device number 288 * port - (IN) Port number 289 * value - (IN) PCP and DE source 290 * Return Value: 291 * BCM_E_XXX 292 */ 293 int 294 bcm_gh_port_etag_pcp_de_source_set(int unit, bcm_port_t port, int value) 295 { 296 int source; 297 298 switch (value) { 299 case BCM_EXTENDER_PCP_DE_SELECT_OUTER_TAG: 300 source = 0; 301 break; 302 case BCM_EXTENDER_PCP_DE_SELECT_INNER_TAG: 303 source = 1; 304 break; 305 case BCM_EXTENDER_PCP_DE_SELECT_DEFAULT: 306 source = 2; 307 break; 308 case BCM_EXTENDER_PCP_DE_SELECT_PHB: 309 source = 3; 310 break; 311 default: 312 return BCM_E_PARAM; 313 } 314 315 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_ETHER, 316 ETAG_PCP_DE_SOURCEf, source)); 317 return BCM_E_NONE; 318 } 319 320 /* 321 * Function: 322 * bcm_gh_port_etag_pcp_de_source_get 323 * Description: 324 * Get source of ETAG's PCP and DE fields. 325 * Parameters: 326 * unit - (IN) Device number 327 * port - (IN) Port number 328 * value - (IN) PCP and DE source 329 * Return Value: 330 * BCM_E_XXX 331 */ 332 int 333 bcm_gh_port_etag_pcp_de_source_get(int unit, bcm_port_t port, int *value) 334 { 335 int source; 336 337 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_get(unit, port, ETAG_PCP_DE_SOURCEf, 338 &source)); 339 340 switch (source) { 341 case 0: 342 *value = BCM_EXTENDER_PCP_DE_SELECT_OUTER_TAG; 343 break; 344 case 1: 345 *value = BCM_EXTENDER_PCP_DE_SELECT_INNER_TAG; 346 break; 347 case 2: 348 *value = BCM_EXTENDER_PCP_DE_SELECT_DEFAULT; 349 break; 350 case 3: 351 *value = BCM_EXTENDER_PCP_DE_SELECT_PHB; 352 break; 353 default: 354 return BCM_E_INTERNAL; 355 } 356 357 return BCM_E_NONE; 358 } 359 #endif /* INCLUDE_L3 */ 360 361 /* 362 * Function: 363 * _bcm_gh_port_pmq_swrst_release 364 * Description: 365 * To release reset state of QSGMII PCS cores in PM4x10Q. 366 * Parameters: 367 * unit - (IN) Device number 368 * Return Value: 369 * BCM_E_XXX 370 */ 371 STATIC int 372 _bcm_gh_port_pmq_swrst_release(int unit) 373 { 374 uint32 rval; 375 /*reset ILKN FIFO*/ 376 BCM_IF_ERROR_RETURN(READ_CHIP_SWRSTr(unit, REG_PORT_ANY, &rval)); 377 soc_reg_field_set(unit, CHIP_SWRSTr, &rval, FLUSHf, 0x1); 378 soc_reg_field_set(unit, CHIP_SWRSTr, &rval, ILKN_BYPASS_RSTNf, 0); 379 BCM_IF_ERROR_RETURN(WRITE_CHIP_SWRSTr(unit, REG_PORT_ANY, rval)); 380 381 382 BCM_IF_ERROR_RETURN(READ_CHIP_SWRSTr(unit, REG_PORT_ANY, &rval)); 383 soc_reg_field_set(unit, CHIP_SWRSTr, &rval, ILKN_BYPASS_RSTNf, 0xf); 384 soc_reg_field_set(unit, CHIP_SWRSTr, &rval, FLUSHf, 0); 385 soc_reg_field_set(unit, CHIP_SWRSTr, &rval, SOFT_RESET_QSGMII_PCSf, 0); 386 soc_reg_field_set(unit, CHIP_SWRSTr, &rval, SOFT_RESET_GPORT1f, 0); 387 soc_reg_field_set(unit, CHIP_SWRSTr, &rval, SOFT_RESET_GPORT0f, 0); 388 BCM_IF_ERROR_RETURN(WRITE_CHIP_SWRSTr(unit, REG_PORT_ANY, rval)); 389 390 return BCM_E_NONE; 391 } 392 393 /* 394 * Function: 395 * bcm_gh_port_init 396 * Description: 397 * For GH specific port init process. 398 * Parameters: 399 * unit - (IN) Device number 400 * Return Value: 401 * BCM_E_XXX 402 */ 403 int 404 bcm_gh_port_init(int unit) 405 { 406 uint32 rval, pmq_disabled, qmode_en = 0; 407 408 /* special init process for PMQ(PM4x10Q in QSGMII mode) 409 * - to release PMQ's QSGMII reset state after QSGMII-PCS and UniMAC init. 410 */ 411 BCM_IF_ERROR_RETURN(READ_PGW_CTRL_0r(unit, &rval)); 412 pmq_disabled = soc_reg_field_get(unit, 413 PGW_CTRL_0r, rval, SW_PM4X10Q_DISABLEf); 414 /* ensure the pm4x10Q is enabled and QMODE enabled */ 415 if (!pmq_disabled) { 416 BCM_IF_ERROR_RETURN(READ_CHIP_CONFIGr(unit, REG_PORT_ANY, &rval)); 417 qmode_en = soc_reg_field_get(unit, CHIP_CONFIGr, rval, QMODEf); 418 if (qmode_en) { 419 BCM_IF_ERROR_RETURN(_bcm_gh_port_pmq_swrst_release(unit)); 420 } 421 } 422 423 return BCM_E_NONE; 424 } 425 426 /* 427 * Function: 428 * bcm_gh_port_priority_group_mapping_set 429 * Purpose: 430 * Assign a Priority Group for the input priority. 431 * Parameters: 432 * unit - (IN) device id. 433 * gport - (IN) generic port. 434 * prio - (IN) input priority. 435 * priority_group - (IN) priority group ID that the input priority mapped to. 436 * Returns: 437 * BCM_E_XXX 438 */ 439 int 440 bcm_gh_port_priority_group_mapping_set(int unit, bcm_gport_t gport, int prio, int priority_group) 441 { 442 int rv = BCM_E_UNAVAIL; 443 bcm_port_t port; 444 uint32 value; 445 int field_count; 446 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 447 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 448 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 449 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 450 451 if (soc_feature(unit, soc_feature_priority_flow_control) && 452 soc_feature(unit, soc_feature_gh_style_pfc_config)) { 453 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 454 if ((prio < GH_SAFC_INPUT_PRIORITY_MIN) || 455 (prio > GH_SAFC_INPUT_PRIORITY_MAX)) { 456 return BCM_E_PARAM; 457 } 458 459 if ((priority_group < GH_PRIOROTY_GROUP_ID_MIN) || 460 (priority_group > GH_PRIOROTY_GROUP_ID_MAX)) { 461 return BCM_E_PARAM; 462 } 463 464 BCM_IF_ERROR_RETURN 465 (bcm_esw_port_local_get(unit, gport, &port)); 466 if (!SOC_PORT_VALID(unit, port)) { 467 return BCM_E_PORT; 468 } 469 field_count = COUNTOF(fields_0); 470 if (prio < field_count) { 471 /* input priority 0~7 */ 472 BCM_IF_ERROR_RETURN(READ_PG_CTRL0r(unit, port, &value)); 473 soc_reg_field_set(unit, PG_CTRL0r, &value, 474 fields_0[prio], priority_group); 475 BCM_IF_ERROR_RETURN(WRITE_PG_CTRL0r(unit, port, value)); 476 return BCM_E_NONE; 477 } else { 478 /* input priority 8~15 */ 479 BCM_IF_ERROR_RETURN(READ_PG_CTRL1r(unit, port, &value)); 480 soc_reg_field_set(unit, PG_CTRL1r, &value, 481 fields_1[prio-field_count], priority_group); 482 BCM_IF_ERROR_RETURN(WRITE_PG_CTRL1r(unit, port, value)); 483 return BCM_E_NONE; 484 } 485 } 486 487 return rv; 488 } 489 490 /* 491 * Function: 492 * bcm_gh_port_priority_group_mapping_get 493 * Purpose: 494 * Get the assigned Priority Group ID of the input priority. 495 * Parameters: 496 * unit - (IN) device id. 497 * gport - (IN) generic port. 498 * prio - (IN) input priority. 499 * priority_group - (OUT) priority group ID that the input priority mapped to. 500 * Returns: 501 * BCM_E_XXX 502 */ 503 int 504 bcm_gh_port_priority_group_mapping_get(int unit, bcm_gport_t gport, int prio, int *priority_group) 505 { 506 int rv = BCM_E_UNAVAIL; 507 bcm_port_t port; 508 uint32 value; 509 int field_count; 510 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 511 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 512 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 513 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 514 515 if (soc_feature(unit, soc_feature_priority_flow_control) && 516 soc_feature(unit, soc_feature_gh_style_pfc_config)) { 517 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 518 if ((prio < GH_SAFC_INPUT_PRIORITY_MIN) || 519 (prio > GH_SAFC_INPUT_PRIORITY_MAX)) { 520 return BCM_E_PARAM; 521 } 522 523 BCM_IF_ERROR_RETURN 524 (bcm_esw_port_local_get(unit, gport, &port)); 525 if (!SOC_PORT_VALID(unit, port)) { 526 return BCM_E_PORT; 527 } 528 field_count = COUNTOF(fields_0); 529 if (prio < field_count) { 530 /* input priority 0~7 */ 531 BCM_IF_ERROR_RETURN(READ_PG_CTRL0r(unit, port, &value)); 532 *priority_group = soc_reg_field_get(unit, PG_CTRL0r, value, 533 fields_0[prio]); 534 return BCM_E_NONE; 535 } else { 536 /* input priority 8~15 */ 537 BCM_IF_ERROR_RETURN(READ_PG_CTRL1r(unit, port, &value)); 538 *priority_group = soc_reg_field_get(unit, PG_CTRL1r, value, 539 fields_1[prio-field_count]); 540 return BCM_E_NONE; 541 } 542 } 543 544 return rv; 545 } 546 547 /* 548 * Function: 549 * bcm_gh_port_priority_group_config_set 550 * Purpose: 551 * Set the port priority group configuration. 552 * Parameters: 553 * unit - (IN) device id. 554 * gport - (IN) generic port. 555 * priority_group - (IN) priority group id. 556 * prigrp_config - (IN) structure describes port priority group configuration. 557 * Returns: 558 * BCM_E_XXX 559 */ 560 int 561 bcm_gh_port_priority_group_config_set(int unit, bcm_gport_t gport, int priority_group, bcm_port_priority_group_config_t *prigrp_config) 562 { 563 int rv = BCM_E_UNAVAIL; 564 bcm_port_t port; 565 uint32 rval; 566 uint32 fval; 567 568 if (soc_feature(unit, soc_feature_priority_flow_control) && 569 soc_feature(unit, soc_feature_gh_style_pfc_config)) { 570 if ((priority_group < GH_PRIOROTY_GROUP_ID_MIN) || 571 (priority_group > GH_PRIOROTY_GROUP_ID_MAX)) { 572 return BCM_E_PARAM; 573 } 574 575 BCM_IF_ERROR_RETURN 576 (bcm_esw_port_local_get(unit, gport, &port)); 577 if (!SOC_PORT_VALID(unit, port)) { 578 return BCM_E_PORT; 579 } 580 581 BCM_IF_ERROR_RETURN(READ_PG_CTRL0r(unit, port, &rval)); 582 fval = soc_reg_field_get(unit, PG_CTRL0r, rval, PPFC_PG_ENf); 583 if (prigrp_config->pfc_transmit_enable) { 584 fval |= (1 << priority_group); 585 } else { 586 fval &= ~(1 << priority_group); 587 } 588 soc_reg_field_set(unit, PG_CTRL0r, &rval, PPFC_PG_ENf, fval); 589 BCM_IF_ERROR_RETURN(WRITE_PG_CTRL0r(unit, port, rval)); 590 591 BCM_IF_ERROR_RETURN(READ_SHARED_POOL_CTRLr(unit, port, &rval)); 592 593 fval = soc_reg_field_get(unit, SHARED_POOL_CTRLr, rval, SHARED_POOL_XOFF_ENf); 594 if (prigrp_config->shared_pool_xoff_enable) { 595 fval |= (1 << priority_group); 596 } else { 597 fval &= ~(1 << priority_group); 598 } 599 soc_reg_field_set(unit, SHARED_POOL_CTRLr, &rval, SHARED_POOL_XOFF_ENf, fval); 600 601 fval = soc_reg_field_get(unit, SHARED_POOL_CTRLr, rval, SHARED_POOL_DISCARD_ENf); 602 if (prigrp_config->shared_pool_discard_enable) { 603 fval |= (1 << priority_group); 604 } else { 605 fval &= ~(1 << priority_group); 606 } 607 soc_reg_field_set(unit, SHARED_POOL_CTRLr, &rval, SHARED_POOL_DISCARD_ENf, fval); 608 609 BCM_IF_ERROR_RETURN(WRITE_SHARED_POOL_CTRLr(unit, port, rval)); 610 611 BCM_IF_ERROR_RETURN(READ_PG2TCr(unit, port, priority_group, &rval)); 612 soc_reg_field_set(unit, PG2TCr, &rval, 613 PG_BMPf, prigrp_config->priority_enable_vector_mask); 614 BCM_IF_ERROR_RETURN(WRITE_PG2TCr(unit, port, priority_group, rval)); 615 616 return BCM_E_NONE; 617 } 618 619 return rv; 620 } 621 622 /* 623 * Function: 624 * bcm_gh_port_priority_group_config_get 625 * Purpose: 626 * Get the port priority group configuration. 627 * Parameters: 628 * unit - (IN) device id. 629 * gport - (IN) generic port. 630 * priority_group - (IN) priority group id. 631 * prigrp_config - (OUT) structure describes port priority group configuration. 632 * Returns: 633 * BCM_E_XXX 634 */ 635 int 636 bcm_gh_port_priority_group_config_get(int unit, bcm_gport_t gport, int priority_group, bcm_port_priority_group_config_t *prigrp_config) 637 { 638 int rv = BCM_E_UNAVAIL; 639 bcm_port_t port; 640 uint32 rval; 641 uint32 fval; 642 643 if (soc_feature(unit, soc_feature_priority_flow_control) && 644 soc_feature(unit, soc_feature_gh_style_pfc_config)) { 645 if ((priority_group < GH_PRIOROTY_GROUP_ID_MIN) || 646 (priority_group > GH_PRIOROTY_GROUP_ID_MAX)) { 647 return BCM_E_PARAM; 648 } 649 650 BCM_IF_ERROR_RETURN 651 (bcm_esw_port_local_get(unit, gport, &port)); 652 if (!SOC_PORT_VALID(unit, port)) { 653 return BCM_E_PORT; 654 } 655 656 BCM_IF_ERROR_RETURN(READ_PG_CTRL0r(unit, port, &rval)); 657 fval = soc_reg_field_get(unit, PG_CTRL0r, rval, PPFC_PG_ENf); 658 if (fval & (1 << priority_group)) { 659 prigrp_config->pfc_transmit_enable = 1; 660 } else { 661 prigrp_config->pfc_transmit_enable = 0; 662 } 663 664 BCM_IF_ERROR_RETURN(READ_SHARED_POOL_CTRLr(unit, port, &rval)); 665 666 fval = soc_reg_field_get(unit, SHARED_POOL_CTRLr, rval, SHARED_POOL_XOFF_ENf); 667 if (fval & (1 << priority_group)) { 668 prigrp_config->shared_pool_xoff_enable = 1; 669 } else { 670 prigrp_config->shared_pool_xoff_enable = 0; 671 } 672 673 fval = soc_reg_field_get(unit, SHARED_POOL_CTRLr, rval, SHARED_POOL_DISCARD_ENf); 674 if (fval & (1 << priority_group)) { 675 prigrp_config->shared_pool_discard_enable = 1; 676 } else { 677 prigrp_config->shared_pool_discard_enable = 0; 678 } 679 680 BCM_IF_ERROR_RETURN(READ_PG2TCr(unit, port, priority_group, &rval)); 681 prigrp_config->priority_enable_vector_mask = 682 soc_reg_field_get(unit, PG2TCr, rval, PG_BMPf); 683 684 return BCM_E_NONE; 685 } 686 687 return rv; 688 } 689 690 #endif /* BCM_GREYHOUND_SUPPORT */