oob.c (32920B)
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 * OOB Flow Control and OOB Stats 8 * Purpose: API to set different OOB Flow Control and OOB Stats registers. 9 */ 10 #ifdef BCM_TOMAHAWK3_SUPPORT 11 #include <sal/core/libc.h> 12 13 #include <shared/bsl.h> 14 #include <soc/defs.h> 15 16 #include <soc/drv.h> 17 #include <soc/mem.h> 18 #include <soc/debug.h> 19 #include <soc/tomahawk.h> 20 21 #include <bcm/error.h> 22 #include <bcm/oob.h> 23 24 #include <bcm_int/esw/mbcm.h> 25 #include <bcm_int/esw/tomahawk.h> 26 #include <bcm_int/esw/oob.h> 27 #include <bcm_int/esw/tomahawk3.h> 28 #include <bcm_int/tomahawk3_dispatch.h> 29 #include <bcm_int/esw/stat.h> 30 31 #define _BCM_TH3_PORT_EN0_WIDTH 64 32 #define _BCM_TH3_PORT_EN1_WIDTH 64 33 #define _BCM_TH3_OOB_FC_EGR_PROFILE_MAX 4 34 #define _BCM_TH3_PORT_EN2_BEGIN 128 35 #define _BCM_TH3_OOB_PORT_MAX 155 36 #define _BCM_TH3_OOB_PORT_INVALID_HW 0xff 37 #define _BCM_TH3_OOB_PORT_VALID(port) \ 38 ((port) >= 0 && (port) < _BCM_TH3_OOB_PORT_MAX) 39 40 #define _BCM_LPORT_IS_SPARE(port) ((58 == port) || (78 == port) || \ 41 (98 == port) || (138 == port) || (158 == port)) 42 43 44 /* 45 * Function: 46 * _bcm_th3_oob_fc_tx_config_egr_mode_get 47 * Purpose: 48 * Get OOB FC Tx egress congestion reporting mode 49 * Parameters: 50 * unit - (IN) StrataSwitch unit number. 51 * config - (OUT) OOB FC Tx configuration 52 * Returns: 53 * BCM_E_XXX 54 */ 55 STATIC int 56 _bcm_th3_oob_fc_egr_mode_get(int unit, 57 int *mode) 58 { 59 uint32 rval; 60 61 BCM_IF_ERROR_RETURN 62 (soc_reg32_get(unit, MMU_INTFO_CONFIG0r, 63 REG_PORT_ANY, 0, &rval)); 64 65 *mode = soc_reg_field_get(unit, MMU_INTFO_CONFIG0r, 66 rval, ENG_PORT_WIDTHf); 67 68 return BCM_E_NONE; 69 } 70 71 STATIC 72 int _bcm_th3_oob_port_set_hw( 73 int unit, 74 int port, 75 int oob_port) 76 { 77 int mmu_chip_port, max_index; 78 soc_mem_t mem; 79 soc_field_t field = OOB_PORT_NUMf; 80 mmu_intfo_mmu_port_to_oob_port_mapping_thdi_entry_t ingress_entry; 81 mmu_intfo_mmu_port_to_oob_port_mapping_thdo0_entry_t egress_entry; 82 83 mem = MMU_INTFO_MMU_PORT_TO_OOB_PORT_MAPPING_THDIm; 84 max_index = soc_mem_index_max(unit, mem); 85 mmu_chip_port = SOC_TH3_MMU_CHIP_PORT(unit, port); 86 87 if(mmu_chip_port < 0 || mmu_chip_port > max_index) { 88 return BCM_E_INTERNAL; 89 } 90 BCM_IF_ERROR_RETURN 91 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, mmu_chip_port, &ingress_entry)); 92 soc_mem_field32_set(unit, mem, &ingress_entry, field, oob_port); 93 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 94 mmu_chip_port, &ingress_entry)); 95 96 mem = MMU_INTFO_MMU_PORT_TO_OOB_PORT_MAPPING_THDO0m; 97 BCM_IF_ERROR_RETURN 98 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, mmu_chip_port, &egress_entry)); 99 soc_mem_field32_set(unit, mem, &egress_entry, field, oob_port); 100 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 101 mmu_chip_port, &egress_entry)); 102 103 return BCM_E_NONE; 104 } 105 106 STATIC int _bcm_th3_oob_port_get_hw( 107 int unit, 108 int port, 109 int *oob_port) 110 { 111 int mmu_chip_port, max_index; 112 soc_mem_t mem; 113 soc_field_t field = OOB_PORT_NUMf; 114 mmu_intfo_mmu_port_to_oob_port_mapping_thdi_entry_t ingress_entry; 115 116 if(!SOC_PORT_VALID(unit, port) || oob_port == NULL) { 117 return BCM_E_PARAM; 118 } 119 mem = MMU_INTFO_MMU_PORT_TO_OOB_PORT_MAPPING_THDIm; 120 max_index = soc_mem_index_max(unit, mem); 121 mmu_chip_port = SOC_TH3_MMU_CHIP_PORT(unit, port); 122 123 if(mmu_chip_port < 0 || mmu_chip_port > max_index) { 124 return BCM_E_INTERNAL; 125 } 126 BCM_IF_ERROR_RETURN 127 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, mmu_chip_port, &ingress_entry)); 128 *oob_port = soc_mem_field32_get(unit, mem, &ingress_entry, field); 129 130 return BCM_E_NONE; 131 } 132 133 int 134 bcm_tomahawk3_oob_fc_tx_port_mapping_get( 135 int unit, 136 int max_count, 137 int *port_array, 138 int *oob_port_array, 139 int *count) 140 { 141 int i; 142 int num; 143 if (port_array == NULL || oob_port_array == NULL || 144 count == NULL) { 145 return BCM_E_PARAM; 146 } 147 *count = 0; 148 num = (max_count > _TH3_DEV_PORTS_PER_DEV) ? 149 _TH3_DEV_PORTS_PER_DEV : max_count; 150 for(i = 0; i < num; i++) { 151 if(_BCM_LPORT_IS_SPARE(port_array[i])) { 152 oob_port_array[i] = -1; 153 continue; 154 } 155 BCM_IF_ERROR_RETURN( 156 _bcm_th3_oob_port_get_hw(unit, port_array[i], 157 &oob_port_array[i])); 158 if(_BCM_TH3_OOB_PORT_INVALID_HW == oob_port_array[i]) { 159 oob_port_array[i] = -1; 160 } 161 } 162 *count = i; 163 return BCM_E_NONE; 164 } 165 166 167 int 168 bcm_tomahawk3_oob_fc_tx_port_mapping_set( 169 int unit, 170 int count, 171 int *port_array, 172 int *oob_port_array) 173 { 174 int i, port, oob_port_used[_BCM_TH3_OOB_PORT_MAX] = { 0 }; 175 int *lport_allocated = NULL; 176 177 if (port_array == NULL || oob_port_array == NULL 178 || count == 0) { 179 return BCM_E_PARAM; 180 } 181 lport_allocated = sal_alloc(_TH3_DEV_PORTS_PER_DEV * sizeof(int), 182 "logical port to oob mapping"); 183 if (lport_allocated == NULL) { 184 return BCM_E_MEMORY; 185 } 186 for (i = 0; i < _TH3_DEV_PORTS_PER_DEV; i++) { 187 lport_allocated[i] = -1; 188 } 189 /* valid input before writing to HW*/ 190 for (i = 0; i < count; i++) { 191 if(!SOC_PORT_VALID(unit, port_array[i]) 192 || !_BCM_TH3_OOB_PORT_VALID(oob_port_array[i])) { 193 return BCM_E_PARAM; 194 } 195 /* if more than one port mapped to the same oob port, 196 * or one port is mapped to different oob ports 197 * input is invalid 198 */ 199 if (oob_port_used[oob_port_array[i]] || 200 lport_allocated[port_array[i]] != -1) { 201 return BCM_E_PARAM; 202 } 203 oob_port_used[oob_port_array[i]] = 1; 204 lport_allocated[port_array[i]] = oob_port_array[i]; 205 } 206 /* populate the entire table */ 207 PBMP_ALL_ITER(unit, port) { 208 if(_BCM_LPORT_IS_SPARE(port)) { 209 /* spare port is not mapped to any oob port */ 210 continue; 211 } 212 if (lport_allocated[port] != -1) { 213 BCM_IF_ERROR_RETURN( 214 _bcm_th3_oob_port_set_hw(unit, port, lport_allocated[port])); 215 } else { 216 BCM_IF_ERROR_RETURN( 217 _bcm_th3_oob_port_set_hw(unit, port, 218 _BCM_TH3_OOB_PORT_INVALID_HW)); 219 220 } 221 222 } 223 sal_free(lport_allocated); 224 return BCM_E_NONE; 225 } 226 227 int 228 bcm_tomahawk3_oob_fc_tx_queue_profile_get( 229 int unit, 230 int profile_id, 231 int max_count, 232 bcm_oob_fc_tx_queue_config_t *config, 233 int *count) 234 { 235 int i; 236 soc_reg_t reg; 237 uint64 rval64; 238 soc_reg_t profile_regs[] = { 239 MMU_INTFO_OOBFC_ENG_Q_MAP0r, 240 MMU_INTFO_OOBFC_ENG_Q_MAP1r, 241 MMU_INTFO_OOBFC_ENG_Q_MAP2r, 242 MMU_INTFO_OOBFC_ENG_Q_MAP3r 243 }; 244 soc_field_t offset_fields[] = { 245 MMUQ0_TO_OOB_BIT_OFFSETf, MMUQ1_TO_OOB_BIT_OFFSETf, 246 MMUQ2_TO_OOB_BIT_OFFSETf, MMUQ3_TO_OOB_BIT_OFFSETf, 247 MMUQ4_TO_OOB_BIT_OFFSETf, MMUQ5_TO_OOB_BIT_OFFSETf, 248 MMUQ6_TO_OOB_BIT_OFFSETf, MMUQ7_TO_OOB_BIT_OFFSETf, 249 MMUQ8_TO_OOB_BIT_OFFSETf, MMUQ9_TO_OOB_BIT_OFFSETf, 250 MMUQ10_TO_OOB_BIT_OFFSETf, MMUQ11_TO_OOB_BIT_OFFSETf 251 }; 252 soc_field_t en_fields[] = { 253 MMUQ0_TO_OOB_ENf, MMUQ1_TO_OOB_ENf, 254 MMUQ2_TO_OOB_ENf, MMUQ3_TO_OOB_ENf, 255 MMUQ4_TO_OOB_ENf, MMUQ5_TO_OOB_ENf, 256 MMUQ6_TO_OOB_ENf, MMUQ7_TO_OOB_ENf, 257 MMUQ8_TO_OOB_ENf, MMUQ9_TO_OOB_ENf, 258 MMUQ10_TO_OOB_ENf, MMUQ11_TO_OOB_ENf 259 }; 260 261 if(config == NULL || profile_id < 0 || 262 profile_id >= _BCM_TH3_OOB_FC_EGR_PROFILE_MAX) { 263 return BCM_E_PARAM; 264 } 265 reg = profile_regs[profile_id]; 266 COMPILER_64_ZERO(rval64); 267 BCM_IF_ERROR_RETURN( 268 soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 269 for(i = 0; i < max_count && i < SOC_TH3_NUM_GP_QUEUES; i++) { 270 config[i].cosq = i; 271 config[i].queue_enable = 272 soc_reg64_field32_get(unit, reg, rval64, en_fields[i]); 273 config[i].queue_offset = 274 soc_reg64_field32_get(unit, reg, rval64, offset_fields[i]); 275 } 276 *count = i; 277 return BCM_E_NONE; 278 } 279 280 int 281 bcm_tomahawk3_oob_fc_tx_queue_profile_set( 282 int unit, 283 int profile_id, 284 int count, 285 bcm_oob_fc_tx_queue_config_t *config) 286 { 287 #define _BCM_TH3_OOB_FC_EGR_MODE0_WIDTH 8 288 #define _BCM_TH3_OOB_FC_EGR_MODE1_WIDTH 16 289 int i, mode, num_bit; 290 uint64 rval64; 291 soc_reg_t reg; 292 bcm_oob_fc_tx_queue_config_t entire_profile[SOC_TH3_NUM_GP_QUEUES]; 293 int offset_ref[_BCM_TH3_OOB_FC_EGR_MODE1_WIDTH] = {0}; 294 int ret_count = 0; 295 soc_reg_t profile_regs[] = { 296 MMU_INTFO_OOBFC_ENG_Q_MAP0r, 297 MMU_INTFO_OOBFC_ENG_Q_MAP1r, 298 MMU_INTFO_OOBFC_ENG_Q_MAP2r, 299 MMU_INTFO_OOBFC_ENG_Q_MAP3r 300 }; 301 soc_field_t offset_fields[] = { 302 MMUQ0_TO_OOB_BIT_OFFSETf, MMUQ1_TO_OOB_BIT_OFFSETf, 303 MMUQ2_TO_OOB_BIT_OFFSETf, MMUQ3_TO_OOB_BIT_OFFSETf, 304 MMUQ4_TO_OOB_BIT_OFFSETf, MMUQ5_TO_OOB_BIT_OFFSETf, 305 MMUQ6_TO_OOB_BIT_OFFSETf, MMUQ7_TO_OOB_BIT_OFFSETf, 306 MMUQ8_TO_OOB_BIT_OFFSETf, MMUQ9_TO_OOB_BIT_OFFSETf, 307 MMUQ10_TO_OOB_BIT_OFFSETf, MMUQ11_TO_OOB_BIT_OFFSETf 308 }; 309 soc_field_t en_fields[] = { 310 MMUQ0_TO_OOB_ENf, MMUQ1_TO_OOB_ENf, 311 MMUQ2_TO_OOB_ENf, MMUQ3_TO_OOB_ENf, 312 MMUQ4_TO_OOB_ENf, MMUQ5_TO_OOB_ENf, 313 MMUQ6_TO_OOB_ENf, MMUQ7_TO_OOB_ENf, 314 MMUQ8_TO_OOB_ENf, MMUQ9_TO_OOB_ENf, 315 MMUQ10_TO_OOB_ENf, MMUQ11_TO_OOB_ENf 316 }; 317 if(config == NULL || count <=0 || count > SOC_TH3_NUM_GP_QUEUES || 318 profile_id < 0 || profile_id >= _BCM_TH3_OOB_FC_EGR_PROFILE_MAX) { 319 return BCM_E_PARAM; 320 } 321 num_bit = _BCM_TH3_OOB_FC_EGR_MODE0_WIDTH; 322 BCM_IF_ERROR_RETURN(_bcm_th3_oob_fc_egr_mode_get(unit, &mode)); 323 if(mode == 0) { 324 num_bit = _BCM_TH3_OOB_FC_EGR_MODE0_WIDTH; 325 } else if (mode == 1) { 326 /* Limit to max cos. Bits [15:12] are unused or driven to 0 */ 327 num_bit = SOC_TH3_COS_MAX; 328 } 329 reg = profile_regs[profile_id]; 330 COMPILER_64_ZERO(rval64); 331 BCM_IF_ERROR_RETURN( 332 soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 333 /* get old profile */ 334 BCM_IF_ERROR_RETURN( 335 bcm_tomahawk3_oob_fc_tx_queue_profile_get(unit, profile_id, 336 SOC_TH3_NUM_GP_QUEUES, entire_profile, &ret_count)); 337 /* overwrite existing profile with new entry */ 338 for (i = 0; i < count; i++) { 339 int mmu_q_id; 340 if (config[i].queue_offset >= num_bit) { 341 return BCM_E_PARAM; 342 } 343 if (config[i].queue_enable != 0 && config[i].queue_enable != 1) { 344 return BCM_E_PARAM; 345 } 346 if ((config[i].cosq < 0) || (config[i].cosq >= SOC_TH3_NUM_GP_QUEUES)) { 347 return BCM_E_PARAM; 348 } 349 mmu_q_id = config[i].cosq; 350 sal_memcpy(&entire_profile[mmu_q_id], &config[i], 351 sizeof(bcm_oob_fc_tx_queue_config_t)); 352 } 353 /* write profile to HW */ 354 for (i = 0; i < SOC_TH3_NUM_GP_QUEUES; i++) { 355 if (entire_profile[i].queue_enable) { 356 offset_ref[entire_profile[i].queue_offset]++; 357 if (offset_ref[entire_profile[i].queue_offset] > 2) { 358 /* at most two queues can be mapped to the same bit offset */ 359 return BCM_E_PARAM; 360 } 361 } 362 soc_reg64_field32_set(unit, reg, &rval64, offset_fields[i], 363 entire_profile[i].queue_offset); 364 soc_reg64_field32_set(unit, reg, &rval64, en_fields[i], 365 entire_profile[i].queue_enable); 366 } 367 BCM_IF_ERROR_RETURN( 368 soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64)); 369 370 #undef _BCM_TH3_OOB_FC_EGR_MODE0_WIDTH 371 #undef _BCM_TH3_OOB_FC_EGR_MODE1_WIDTH 372 373 return BCM_E_NONE; 374 } 375 376 /* 377 * Function: 378 * _bcm_th3_oob_fc_tx_port_ing_egr_set 379 * Purpose: 380 * Set OOB FC Tx Port reporting configuration. 381 * Parameters: 382 * unit - (IN) StrataSwitch unit number. 383 * port - (IN) Local port 384 * status - (IN) Status of Congestion State reporting 385 * dir - (IN) Direction 0 = Ingreess, 1 = Egress, 386 * 2 = Internal congestion reporting. 387 * Returns: 388 * BCM_E_XXX 389 */ 390 static int 391 _bcm_th3_oob_fc_tx_port_ing_egr_set(int unit, bcm_port_t port, 392 int status, int dir) 393 { 394 uint32 rval = 0; 395 uint64 rval64; 396 int oob_port = -1; 397 static const soc_field_t field[3] = {ING_PORT_ENf, 398 ENG_PORT_ENf, CONGST_ST_ENf}; 399 static const soc_reg_t reg[3][3] = { 400 {MMU_INTFO_OOBFC_ING_PORT_EN0_64r, MMU_INTFO_OOBFC_ING_PORT_EN1_64r, 401 MMU_INTFO_OOBFC_ING_PORT_EN2r}, 402 {MMU_INTFO_OOBFC_ENG_PORT_EN0_64r, MMU_INTFO_OOBFC_ENG_PORT_EN1_64r, 403 MMU_INTFO_OOBFC_ENG_PORT_EN2r}, 404 {MMU_INTFO_OOBFC_CONGST_ST_EN0_64r, MMU_INTFO_OOBFC_CONGST_ST_EN1_64r, 405 MMU_INTFO_OOBFC_CONGST_ST_EN2r}}; 406 407 if ((status != 1) && (status != 0)) { 408 /* 0: disable 409 * 1: enable 410 */ 411 return BCM_E_PARAM; 412 } 413 414 if (dir > 2) { 415 return BCM_E_PARAM; 416 } 417 418 COMPILER_64_ZERO(rval64); 419 BCM_IF_ERROR_RETURN( 420 _bcm_th3_oob_port_get_hw(unit, port, &oob_port)); 421 if(_BCM_TH3_OOB_PORT_INVALID_HW == oob_port) { 422 return BCM_E_PORT; 423 } 424 425 if ((oob_port >= 0) && (oob_port < _BCM_TH3_PORT_EN0_WIDTH)) { 426 /* For OOB port 0-63 */ 427 428 BCM_IF_ERROR_RETURN 429 (soc_reg64_get(unit, reg[dir][0], REG_PORT_ANY, 0, &rval64)); 430 if (((status == 1) && (!COMPILER_64_BITTEST(rval64, oob_port))) || 431 ((status == 0) && (COMPILER_64_BITTEST(rval64, oob_port)))) { 432 if (status == 1) { 433 COMPILER_64_BITSET(rval64, oob_port); 434 } else { 435 COMPILER_64_BITCLR(rval64, oob_port); 436 } 437 soc_reg64_field_set(unit, reg[dir][0], &rval64, 438 field[dir], rval64); 439 BCM_IF_ERROR_RETURN 440 (soc_reg64_set(unit, reg[dir][0], REG_PORT_ANY, 0, rval64)); 441 } 442 } else if ((oob_port >= _BCM_TH3_PORT_EN0_WIDTH) && 443 (oob_port < _BCM_TH3_PORT_EN2_BEGIN)) { 444 /* For OOB port 64-127 */ 445 446 BCM_IF_ERROR_RETURN 447 (soc_reg64_get(unit, reg[dir][1], REG_PORT_ANY, 0, &rval64)); 448 if (((status == 1) && (!COMPILER_64_BITTEST(rval64, (oob_port % _BCM_TH3_PORT_EN0_WIDTH)))) || 449 ((status == 0) && (COMPILER_64_BITTEST(rval64, (oob_port % _BCM_TH3_PORT_EN0_WIDTH))))) { 450 if (status == 1) { 451 COMPILER_64_BITSET(rval64, (oob_port % _BCM_TH3_PORT_EN0_WIDTH)); 452 } else { 453 COMPILER_64_BITCLR(rval64, (oob_port % _BCM_TH3_PORT_EN0_WIDTH)); 454 } 455 soc_reg64_field_set(unit, reg[dir][1], &rval64, 456 field[dir], rval64); 457 BCM_IF_ERROR_RETURN 458 (soc_reg64_set(unit, reg[dir][1], REG_PORT_ANY, 0, rval64)); 459 } 460 } else if ((oob_port >= _BCM_TH3_PORT_EN2_BEGIN) 461 && (oob_port < _BCM_TH3_OOB_PORT_MAX)) { 462 /* For oob port 128-154 */ 463 464 BCM_IF_ERROR_RETURN 465 (soc_reg32_get(unit, reg[dir][2], REG_PORT_ANY, 0, &rval)); 466 if (((status == 1) && (!(rval & (0x1 << (oob_port % _BCM_TH3_PORT_EN2_BEGIN))))) || 467 ((status == 0) && ((rval & (0x1 << (oob_port % _BCM_TH3_PORT_EN2_BEGIN)))))) { 468 if (status == 1) { 469 rval |= 0x1 << (oob_port % _BCM_TH3_PORT_EN2_BEGIN); 470 } else { 471 rval &= ~(0x1 << (oob_port % _BCM_TH3_PORT_EN2_BEGIN)); 472 } 473 soc_reg_field_set(unit, reg[dir][2], &rval, field[dir], rval); 474 475 BCM_IF_ERROR_RETURN 476 (soc_reg32_set(unit, reg[dir][2], REG_PORT_ANY, 0, rval)); 477 } 478 } else { 479 return BCM_E_PARAM; 480 } 481 482 return BCM_E_NONE; 483 } 484 485 static int 486 _bcm_th3_oob_fc_tx_congst_set(int unit, bcm_port_t port) { 487 int ing_status = 0, egr_status = 0; 488 489 BCM_IF_ERROR_RETURN( 490 bcm_th3_oob_fc_tx_port_control_get(unit, port, &ing_status, 0)); 491 BCM_IF_ERROR_RETURN( 492 bcm_th3_oob_fc_tx_port_control_get(unit, port, &egr_status, 1)); 493 494 /* turn off congestion reporting from MMU to OOB 495 * only when ingress and egress reporting are both turned off 496 */ 497 if (!ing_status && !egr_status) { 498 BCM_IF_ERROR_RETURN( 499 _bcm_th3_oob_fc_tx_port_ing_egr_set(unit, port, 0, 2)); 500 } else { 501 BCM_IF_ERROR_RETURN( 502 _bcm_th3_oob_fc_tx_port_ing_egr_set(unit, port, 1, 2)); 503 } 504 505 return BCM_E_NONE; 506 } 507 508 /* 509 * Function: 510 * bcm_th3_oob_fc_tx_port_control_set 511 * Purpose: 512 * Set OOB FC Tx Port configuration. 513 * Parameters: 514 * unit - (IN) StrataSwitch unit number. 515 * port - (IN) Local port 516 * status - (IN) Status of Congestion State reporting 517 * dir - (IN) Direction 0 = Ingreess, 1 = Egress 518 * Returns: 519 * BCM_E_XXX 520 */ 521 int 522 bcm_th3_oob_fc_tx_port_control_set(int unit, bcm_port_t port, 523 int status, int dir) 524 { 525 if ((status != 1) && (status != 0)) { 526 /* 0: disable 527 * 1: enable 528 */ 529 return BCM_E_PARAM; 530 } 531 if (dir > 1) { 532 return BCM_E_PARAM; 533 } 534 BCM_IF_ERROR_RETURN( 535 _bcm_th3_oob_fc_tx_port_ing_egr_set(unit, port, status, dir)); 536 BCM_IF_ERROR_RETURN( 537 _bcm_th3_oob_fc_tx_congst_set(unit, port)); 538 return BCM_E_NONE; 539 } 540 541 /* 542 * Function: 543 * bcm_th3_oob_fc_tx_port_control_get 544 * Purpose: 545 * Get OOB FC Tx side Port configuration. 546 * Parameters: 547 * unit - (IN) StrataSwitch unit number. 548 * port - (IN) Logical port 549 * status - (OUT) Status of Congestion State reporting 550 * dir - (IN) Direction 0 = Ingreess, 1 = Egress 551 * Returns: 552 * BCM_E_XXX 553 */ 554 int 555 bcm_th3_oob_fc_tx_port_control_get(int unit, bcm_port_t port, 556 int *status, int dir) 557 { 558 uint32 rval = 0; 559 uint64 rval64; 560 int oob_port = -1; 561 static const soc_reg_t reg[2][3] = { 562 {MMU_INTFO_OOBFC_ING_PORT_EN0_64r, MMU_INTFO_OOBFC_ING_PORT_EN1_64r, 563 MMU_INTFO_OOBFC_ING_PORT_EN2r}, 564 {MMU_INTFO_OOBFC_ENG_PORT_EN0_64r, MMU_INTFO_OOBFC_ENG_PORT_EN1_64r, 565 MMU_INTFO_OOBFC_ENG_PORT_EN2r}}; 566 567 if (dir > 1) { 568 return BCM_E_PARAM; 569 } 570 BCM_IF_ERROR_RETURN( 571 _bcm_th3_oob_port_get_hw(unit, port, &oob_port)); 572 if(_BCM_TH3_OOB_PORT_INVALID_HW == oob_port) { 573 return BCM_E_NOT_FOUND; 574 } 575 COMPILER_64_ZERO(rval64); 576 577 if ((oob_port >= 0) && (oob_port < _BCM_TH3_PORT_EN0_WIDTH)) { 578 /* For logical port 0-63 */ 579 BCM_IF_ERROR_RETURN 580 (soc_reg64_get(unit, reg[dir][0], REG_PORT_ANY, 0, &rval64)); 581 if (COMPILER_64_BITTEST(rval64, oob_port)) { 582 *status = 0x1; 583 } else { 584 *status = 0x0; 585 } 586 } else if ((oob_port >= _BCM_TH3_PORT_EN0_WIDTH) && 587 (oob_port < _BCM_TH3_PORT_EN2_BEGIN)) { 588 /* For logical port 64-127 */ 589 BCM_IF_ERROR_RETURN 590 (soc_reg64_get(unit, reg[dir][1], REG_PORT_ANY, 0, &rval64)); 591 592 if (COMPILER_64_BITTEST(rval64, (oob_port % _BCM_TH3_PORT_EN0_WIDTH))) { 593 *status = 0x1; 594 } else { 595 *status = 0x0; 596 } 597 } else if ((oob_port >= _BCM_TH3_PORT_EN2_BEGIN) && 598 (oob_port < _BCM_TH3_OOB_PORT_MAX)) { 599 /* For logical port 128-154 */ 600 BCM_IF_ERROR_RETURN 601 (soc_reg32_get(unit, reg[dir][2], REG_PORT_ANY, 0, &rval)); 602 if (rval & (0x1 << (oob_port % _BCM_TH3_PORT_EN2_BEGIN))) { 603 *status = 0x1; 604 } else { 605 *status = 0x0; 606 } 607 } else { 608 return BCM_E_PARAM; 609 } 610 611 return BCM_E_NONE; 612 } 613 614 int bcm_th3_oob_fx_egress_profile_id_set(int unit, bcm_port_t port, 615 int profile_id) 616 { 617 soc_mem_t mem = MMU_INTFO_OOBFC_ENG_PORT_PSELm; 618 int max_index, mmu_chip_port; 619 soc_field_t field = ENG_PORT_PROFILE_SELf; 620 mmu_intfo_oobfc_eng_port_psel_entry_t entry; 621 if(!(SOC_PORT_VALID(unit, port)) || profile_id < 0 || 622 profile_id > _BCM_TH3_OOB_FC_EGR_PROFILE_MAX) { 623 return BCM_E_PARAM; 624 } 625 max_index = soc_mem_index_max(unit, mem); 626 mmu_chip_port = SOC_TH3_MMU_CHIP_PORT(unit, port); 627 628 if(mmu_chip_port < 0 || mmu_chip_port > max_index) { 629 return BCM_E_INTERNAL; 630 } 631 BCM_IF_ERROR_RETURN( 632 soc_mem_read(unit, mem, MEM_BLOCK_ANY, mmu_chip_port, &entry)); 633 soc_mem_field32_set(unit, mem, &entry, field, profile_id); 634 BCM_IF_ERROR_RETURN( 635 soc_mem_write(unit, mem, MEM_BLOCK_ALL, mmu_chip_port, &entry)); 636 637 return BCM_E_NONE; 638 } 639 640 int bcm_th3_oob_fx_egress_profile_id_get(int unit, bcm_port_t port, 641 int *profile_id) 642 { 643 soc_mem_t mem = MMU_INTFO_OOBFC_ENG_PORT_PSELm; 644 soc_field_t field = ENG_PORT_PROFILE_SELf; 645 int max_index, mmu_chip_port; 646 mmu_intfo_oobfc_eng_port_psel_entry_t entry; 647 if(!(SOC_PORT_VALID(unit, port)) || profile_id == NULL) { 648 return BCM_E_PARAM; 649 } 650 max_index = soc_mem_index_max(unit, mem); 651 mmu_chip_port = SOC_TH3_MMU_CHIP_PORT(unit, port); 652 653 if(mmu_chip_port < 0 || mmu_chip_port > max_index) { 654 return BCM_E_INTERNAL; 655 } 656 BCM_IF_ERROR_RETURN( 657 soc_mem_read(unit, mem, MEM_BLOCK_ANY, mmu_chip_port, &entry)); 658 *profile_id = soc_mem_field32_get(unit, mem, &entry, field); 659 660 return BCM_E_NONE; 661 } 662 663 /* 664 * Function: 665 * _bcm_th3_oob_fc_tx_config_flags_set 666 * Purpose: 667 * Set OOB FC Tx enable flags 668 * Parameters: 669 * unit - (IN) StrataSwitch unit number. 670 * flags - (IN) OOB FC Tx flags 671 * Returns: 672 * BCM_E_XXX 673 */ 674 STATIC int 675 _bcm_th3_oob_fc_tx_config_flags_set(int unit, uint32 flags) 676 { 677 uint32 rval = 0; 678 uint32 fval = 0; 679 soc_reg_t reg = INVALIDr; 680 681 if (flags & BCM_OOB_FC_TX_FCN_EN) { 682 return BCM_E_UNAVAIL; 683 } 684 685 reg = MMU_INTFO_OOBFC_CHANNEL_BASE_64r; 686 BCM_IF_ERROR_RETURN 687 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 688 if (flags & BCM_OOB_FC_TX_ING_EN) { 689 fval = 1; 690 } 691 soc_reg_field_set(unit, reg, &rval, ING_ENf, fval); 692 693 fval = 0; 694 if (flags & BCM_OOB_FC_TX_EGR_EN) { 695 fval = 1; 696 } 697 soc_reg_field_set(unit, reg, &rval, ENG_ENf, fval); 698 699 fval = 0; 700 if (flags & BCM_OOB_FC_TX_POOL_EN) { 701 fval = 1; 702 } 703 soc_reg_field_set(unit, reg, &rval, POOL_ENf, fval); 704 705 BCM_IF_ERROR_RETURN 706 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 707 708 return BCM_E_NONE; 709 } 710 711 /* 712 * Function: 713 * _bcm_th3_oob_fc_tx_config_flags_get 714 * Purpose: 715 * Get OOB FC Tx enable status 716 * Parameters: 717 * unit - (IN) StrataSwitch unit number. 718 * config - (OUT) OOB FC Tx configuration 719 * Returns: 720 * BCM_E_XXX 721 */ 722 STATIC int 723 _bcm_th3_oob_fc_tx_config_flags_get(int unit, 724 bcm_oob_fc_tx_config_t *config) 725 { 726 uint32 fval; 727 uint32 rval; 728 soc_reg_t reg = MMU_INTFO_OOBFC_CHANNEL_BASE_64r; 729 rval = 0; 730 731 config->flags = 0x0; 732 733 734 BCM_IF_ERROR_RETURN 735 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 736 737 fval = soc_reg_field_get(unit, reg, rval, ING_ENf); 738 if (fval) { 739 config->flags |= BCM_OOB_FC_TX_ING_EN; 740 } 741 742 fval = soc_reg_field_get(unit, reg, rval, ENG_ENf); 743 if (fval) { 744 config->flags |= BCM_OOB_FC_TX_EGR_EN; 745 } 746 747 fval = soc_reg_field_get(unit, reg, rval, POOL_ENf); 748 749 if (fval) { 750 config->flags |= BCM_OOB_FC_TX_POOL_EN; 751 } 752 753 return BCM_E_NONE; 754 } 755 756 /* 757 * Function: 758 * _bcm_th3_oob_fc_tx_config_gcs_id_set 759 * Purpose: 760 * Set OOB FC Tx global congestion reporting 761 * service pool id 762 * Parameters: 763 * unit - (IN) StrataSwitch unit number. 764 * id - (IN) OOB FC Tx global congestion service pool id 765 * Returns: 766 * BCM_E_XXX 767 */ 768 STATIC int 769 _bcm_th3_oob_fc_tx_config_gcs_id_set(int unit, 770 bcm_service_pool_id_t id) 771 { 772 uint32 rval; 773 soc_reg_t reg = MMU_INTFO_OOBFC_GCSr; 774 BCM_IF_ERROR_RETURN 775 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 776 soc_reg_field_set(unit, reg, &rval, 777 GCS_IDf, id); 778 BCM_IF_ERROR_RETURN 779 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 780 781 return BCM_E_NONE; 782 } 783 784 /* 785 * Function: 786 * _bcm_th3_oob_fc_tx_config_gcs_id_get 787 * Purpose: 788 * Get OOB FC Tx global congestion reporting 789 * service pool id 790 * Parameters: 791 * unit - (IN) StrataSwitch unit number. 792 * config - (OUT) OOB FC Tx configuration 793 * Returns: 794 * BCM_E_XXX 795 */ 796 STATIC int 797 _bcm_th3_oob_fc_tx_config_gcs_id_get(int unit, 798 bcm_oob_fc_tx_config_t *config) 799 { 800 uint32 rval; 801 802 BCM_IF_ERROR_RETURN 803 (soc_reg32_get(unit, MMU_INTFO_OOBFC_GCSr, REG_PORT_ANY, 0, &rval)); 804 805 config->gcs_id = soc_reg_field_get(unit, MMU_INTFO_OOBFC_GCSr, rval, 806 GCS_IDf); 807 808 return BCM_E_NONE; 809 } 810 811 /* 812 * Function: 813 * _bcm_th3_oob_fc_tx_config_ipg_set 814 * Purpose: 815 * Set OOB FC Tx inter packet gap 816 * Parameters: 817 * unit - (IN) StrataSwitch unit number. 818 * ipg - (IN) OOB FC Tx inter packet gap 819 * Returns: 820 * BCM_E_XXX 821 */ 822 STATIC int 823 _bcm_th3_oob_fc_tx_config_ipg_set(int unit, uint8 ipg) 824 { 825 uint32 rval; 826 soc_reg_t reg = MMU_INTFO_OOBFC_TX_IDLEr; 827 BCM_IF_ERROR_RETURN 828 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 829 soc_reg_field_set(unit, reg, &rval, IDLE_GAPf, ipg); 830 BCM_IF_ERROR_RETURN 831 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 832 return BCM_E_NONE; 833 } 834 835 /* 836 * Function: 837 * _bcm_th_oob_fc_tx_config_ipg_get 838 * Purpose: 839 * Get OOB FC Tx inter packet gap 840 * Parameters: 841 * unit - (IN) StrataSwitch unit number. 842 * config - (OUT) OOB FC Tx configuration 843 * Returns: 844 * BCM_E_XXX 845 */ 846 STATIC int 847 _bcm_th3_oob_fc_tx_config_ipg_get(int unit, 848 bcm_oob_fc_tx_config_t *config) 849 { 850 uint32 rval; 851 852 BCM_IF_ERROR_RETURN 853 (soc_reg32_get(unit, MMU_INTFO_OOBFC_TX_IDLEr, REG_PORT_ANY, 0, &rval)); 854 855 config->inter_pkt_gap = soc_reg_field_get(unit, MMU_INTFO_OOBFC_TX_IDLEr, 856 rval, IDLE_GAPf); 857 858 return BCM_E_NONE; 859 } 860 861 /* 862 * Function: 863 * _bcm_th3_oob_fc_tx_config_egr_mode_set 864 * Purpose: 865 * Set OOB FC Tx egress congestion reporting mode 866 * Parameters: 867 * unit - (IN) StrataSwitch unit number. 868 * mode - (IN) OOB FC Tx egress congestion reporting mode 869 * Returns: 870 * BCM_E_XXX 871 */ 872 STATIC int 873 _bcm_th3_oob_fc_tx_config_egr_mode_set(int unit, 874 int mode) 875 { 876 uint32 rval; 877 soc_reg_t reg = MMU_INTFO_CONFIG0r; 878 879 BCM_IF_ERROR_RETURN 880 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 881 882 soc_reg_field_set(unit, reg, &rval, ENG_PORT_WIDTHf, mode); 883 BCM_IF_ERROR_RETURN 884 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 885 886 return BCM_E_NONE; 887 } 888 889 /* 890 * Function: 891 * _bcm_th3_oob_fc_tx_config_egr_mode_get 892 * Purpose: 893 * Get OOB FC Tx egress congestion reporting mode 894 * Parameters: 895 * unit - (IN) StrataSwitch unit number. 896 * config - (OUT) OOB FC Tx configuration 897 * Returns: 898 * BCM_E_XXX 899 */ 900 STATIC int 901 _bcm_th3_oob_fc_tx_config_egr_mode_get(int unit, 902 bcm_oob_fc_tx_config_t *config) 903 { 904 int mode = 0; 905 BCM_IF_ERROR_RETURN(_bcm_th3_oob_fc_egr_mode_get(unit, &mode)); 906 907 config->egr_mode = mode; 908 909 return BCM_E_NONE; 910 } 911 912 /* 913 * Function: 914 * bcm_th3_oob_fc_tx_config_set 915 * Purpose: 916 * Set OOB FC Tx global configuration. 917 * Parameters: 918 * unit - (IN) StrataSwitch unit number. 919 * config - (IN) OOB FC Tx global configuration 920 * Returns: 921 * BCM_E_XXX 922 */ 923 int 924 bcm_th3_oob_fc_tx_config_set(int unit, 925 bcm_oob_fc_tx_config_t *config) 926 { 927 if (config == NULL) { 928 return BCM_E_PARAM; 929 } 930 931 if ((config->gcs_id < 0) || (config->gcs_id >= _TH3_MMU_NUM_POOL)) { 932 return BCM_E_PARAM; 933 } 934 935 /* egress mode - 0: 8bit, 1: 16bit */ 936 if ((config->egr_mode < 0) || (config->egr_mode > 1)) { 937 return BCM_E_PARAM; 938 } 939 940 /* Enabling/Disabling OOBFC Tx Ingress, Egress and Service Pool */ 941 BCM_IF_ERROR_RETURN 942 (_bcm_th3_oob_fc_tx_config_flags_set(unit, config->flags)); 943 944 /* Setting Inter packet Gap between two HCFC message */ 945 BCM_IF_ERROR_RETURN 946 (_bcm_th3_oob_fc_tx_config_ipg_set(unit, config->inter_pkt_gap)); 947 948 /* Setting service pool id whose congestion state will be 949 reported in every HCFC message */ 950 BCM_IF_ERROR_RETURN 951 (_bcm_th3_oob_fc_tx_config_gcs_id_set(unit, config->gcs_id)); 952 953 /* Setting Egress mode for reporting OOBFC message. */ 954 955 BCM_IF_ERROR_RETURN 956 (_bcm_th3_oob_fc_tx_config_egr_mode_set(unit, config->egr_mode)); 957 958 return BCM_E_NONE; 959 } 960 961 /* 962 * Function: 963 * bcm_th3_oob_fc_tx_config_get 964 * Purpose: 965 * Get OOB FC Tx global configuration. 966 * Parameters: 967 * unit - (IN) StrataSwitch unit number. 968 * config - (OUT) OOB FC Tx global configuration 969 * Returns: 970 * BCM_E_XXX 971 */ 972 int 973 bcm_th3_oob_fc_tx_config_get(int unit, 974 bcm_oob_fc_tx_config_t *config) 975 { 976 if (config == NULL) { 977 return BCM_E_PARAM; 978 } 979 980 /* Get the congestion state reporting status of FCN, 981 OOBFC Tx Ingress, Egress and Service Pool */ 982 BCM_IF_ERROR_RETURN 983 (_bcm_th3_oob_fc_tx_config_flags_get(unit, config)); 984 985 /* Get the configured Inter Packet Gap between OOBFC Tx message.*/ 986 BCM_IF_ERROR_RETURN 987 (_bcm_th3_oob_fc_tx_config_ipg_get(unit, config)); 988 989 /* Setting service pool id whose congestion state will be 990 reported in every HCFC message */ 991 BCM_IF_ERROR_RETURN 992 (_bcm_th3_oob_fc_tx_config_gcs_id_get(unit, config)); 993 994 /* Get the configured Egress mode of OOBFC Tx side */ 995 BCM_IF_ERROR_RETURN 996 (_bcm_th3_oob_fc_tx_config_egr_mode_get(unit, config)); 997 998 return BCM_E_NONE; 999 } 1000 1001 int 1002 bcm_th3_oob_port_mapping_init(int unit) 1003 { 1004 int port, oob_port = 0; 1005 PBMP_ALL_ITER(unit, port) { 1006 if (_BCM_LPORT_IS_SPARE(port)) { 1007 BCM_IF_ERROR_RETURN( 1008 _bcm_th3_oob_port_set_hw(unit, port, _BCM_TH3_OOB_PORT_INVALID_HW)); 1009 } 1010 BCM_IF_ERROR_RETURN( 1011 _bcm_th3_oob_port_set_hw(unit, port, oob_port)); 1012 oob_port++; 1013 } 1014 return BCM_E_NONE; 1015 } 1016 1017 /* 1018 * Function: 1019 * bcm_th3_oob_fc_tx_info_get 1020 * Purpose: 1021 * Get OOB FC Tx global information. 1022 * Parameters: 1023 * unit - (IN) StrataSwitch unit number. 1024 * info - (OUT) OOB FC Tx global information 1025 * Returns: 1026 * BCM_E_XXX 1027 */ 1028 int 1029 bcm_th3_oob_fc_tx_info_get(int unit, bcm_oob_fc_tx_info_t *info) 1030 { 1031 uint32 rval; 1032 soc_reg_t reg = MMU_INTFO_OOBFC_CHANNEL_BASE_64r; /* 32 bit reg */ 1033 if (info == NULL) { 1034 return BCM_E_PARAM; 1035 } 1036 1037 BCM_IF_ERROR_RETURN 1038 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1039 1040 /* Get the Channel base value for HCFC messages containing 1041 congestion state of different resources */ 1042 /* Ingress Ports */ 1043 info->ing_base = (uint8)soc_reg_field_get(unit, reg, 1044 rval, ING_BASEf); 1045 1046 /* Egress Unicast Queue not supported in TH3*/ 1047 info->ucast_base = 0; 1048 1049 /* Egress Multicast Queue not supported in TH3*/ 1050 info->mcast_base = 0; 1051 1052 /* Egress OOB Class */ 1053 info->cos_base = (uint8)soc_reg_field_get(unit, reg, 1054 rval, ENG_BASEf); 1055 1056 /* Ingress and Egress Service Pool Congestion */ 1057 1058 info->pool_base = (uint8)soc_reg_field_get(unit, reg, 1059 rval, POOL_BASEf); 1060 1061 return BCM_E_NONE; 1062 } 1063 1064 #endif 1065 1066