pfc_deadlock.c (66305B)
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 * PFC Deadlock Detection & Recovery 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <soc/defs.h> 13 #include <sal/core/libc.h> 14 #include <sal/core/dpc.h> 15 #include <sal/core/time.h> 16 17 #include <soc/drv.h> 18 #include <soc/mem.h> 19 #include <soc/debug.h> 20 #include <soc/tomahawk.h> 21 #include <soc/trident3.h> 22 23 #include <bcm/debug.h> 24 #include <bcm/error.h> 25 #include <bcm/cosq.h> 26 #include <bcm_int/esw/mbcm.h> 27 #include <bcm_int/esw/stack.h> 28 #include <bcm_int/esw/cosq.h> 29 #include <bcm_int/esw/pfc_deadlock.h> 30 #include <bcm_int/esw/virtual.h> 31 #include <bcm_int/esw/tomahawk.h> 32 #include <bcm_int/esw/trident3.h> 33 #include <bcm_int/esw/helix5.h> 34 35 #include <bcm_int/esw_dispatch.h> 36 37 #ifdef BCM_WARM_BOOT_SUPPORT 38 #include <bcm_int/esw/switch.h> 39 #endif /* BCM_WARM_BOOT_SUPPORT */ 40 41 #if defined(BCM_TOMAHAWK_SUPPORT) 42 #define _MMU_PORT_STRIDE SOC_TH_MMU_PORT_STRIDE 43 #else 44 #define _MMU_PORT_STRIDE 64 45 #endif 46 47 _bcm_pfc_deadlock_control_t *_bcm_pfc_deadlock_control[BCM_MAX_NUM_UNITS]; 48 _bcm_pfc_deadlock_cb_t *_bcm_pfc_deadlock_cb[BCM_MAX_NUM_UNITS]; 49 50 int 51 _bcm_pfc_deadlock_ignore_pfc_xoff_clear(int unit, int cos, bcm_port_t port) 52 { 53 int priority = 0; 54 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 55 _bcm_pfc_hw_resorces_t *hw_res = NULL; 56 uint32 rval; 57 58 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 59 hw_res = &pfc_deadlock_control->hw_regs_fields; 60 61 if (port >= MAX_PORT(unit)) { 62 return BCM_E_PARAM; /* Process for valid ports */ 63 } 64 65 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 66 /* For that port, set ignore_pfc_xoff = 0 (per port reg) */ 67 rval = 0; 68 SOC_IF_ERROR_RETURN( 69 soc_reg32_get(unit, hw_res->port_config, port, 0, &rval)); 70 rval &= ~(1 << priority); 71 SOC_IF_ERROR_RETURN( 72 soc_reg32_set(unit, hw_res->port_config, port, 0, rval)); 73 74 return BCM_E_NONE; 75 } 76 int 77 _bcm_pfc_deadlock_ignore_pfc_xoff_gen(int unit, int priority, 78 bcm_port_t port, uint32 *rval32) 79 { 80 81 #ifdef BCM_TOMAHAWK_SUPPORT 82 if (SOC_IS_TOMAHAWKX(unit)) { 83 BCM_IF_ERROR_RETURN( 84 bcm_th_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, 85 port, rval32)); 86 } 87 #endif 88 89 #if defined(BCM_HELIX5_SUPPORT) 90 if (SOC_IS_HELIX5(unit)) { 91 return( 92 bcm_hx5_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, 93 port, rval32)); 94 } 95 #endif 96 97 #if defined(BCM_TRIDENT3_SUPPORT) 98 if (SOC_IS_TRIDENT3X(unit)) { 99 return( 100 bcm_td3_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, 101 port, rval32)); 102 } 103 #endif 104 105 return BCM_E_NONE; 106 } 107 108 /* Routine to Reset the recovery state of a port and config the port back in 109 * original state 110 */ 111 STATIC int 112 _bcm_pfc_deadlock_recovery_end(int unit, int cos, bcm_port_t port) 113 { 114 soc_info_t *si; 115 int phy_port, mmu_port, pipe_mmu_port, pipe, priority = 0; 116 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 117 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 118 uint64 rval64, temp_rval64, temp_mask64, temp_en64; 119 uint32 rval, setval, uc_cos_bmp = 0; 120 _bcm_pfc_hw_resorces_t *hw_res = NULL; 121 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 122 123 #ifdef BCM_HELIX5_SUPPORT 124 if (SOC_IS_HELIX5(unit)) { 125 return (_bcm_hx5_pfc_deadlock_recovery_end(unit, 126 cos, port)); 127 } 128 #endif 129 130 #ifdef BCM_TRIDENT3_SUPPORT 131 if (SOC_IS_TRIDENT3X(unit)) { 132 return (_bcm_td3_pfc_deadlock_recovery_end(unit, 133 cos, port)); 134 } 135 #endif 136 137 si = &SOC_INFO(unit); 138 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 139 hw_res = &pfc_deadlock_control->hw_regs_fields; 140 141 if (port >= MAX_PORT(unit)) { 142 return BCM_E_PARAM; /* Process for valid ports */ 143 } 144 phy_port = si->port_l2p_mapping[port]; 145 mmu_port = si->port_p2m_mapping[phy_port]; 146 pipe_mmu_port = mmu_port % _MMU_PORT_STRIDE; 147 148 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, port, &pipe)); 149 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 150 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 151 152 COMPILER_64_ZERO(temp_en64); 153 COMPILER_64_ZERO(temp_mask64); 154 COMPILER_64_ZERO(temp_rval64); 155 156 if (pipe_mmu_port < 32) { 157 COMPILER_64_SET(temp_rval64, 0, (1 << pipe_mmu_port)); 158 } else { 159 COMPILER_64_SET(temp_rval64, (1 << (pipe_mmu_port - 32)), 0); 160 } 161 COMPILER_64_OR(temp_mask64, temp_rval64); 162 COMPILER_64_OR(temp_en64, temp_rval64); 163 164 LOG_INFO(BSL_LS_BCM_COSQ, 165 (BSL_META_U(unit, 166 "PFC Deadlock Recovery ends: Prio %d port=%d\n"), 167 priority, port)); 168 169 /* 3.a: For that port, set ignore_pfc_xoff = 0 (per port reg) */ 170 setval = 0; 171 SOC_IF_ERROR_RETURN( 172 soc_reg32_get(unit, hw_res->port_config, port, 0, &setval)); 173 174 rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, 175 port, &uc_cos_bmp); 176 if(rval != BCM_E_NONE) { 177 setval &= ~(1 << priority); 178 } else { 179 setval &= ~uc_cos_bmp; 180 } 181 SOC_IF_ERROR_RETURN( 182 soc_reg32_set(unit, hw_res->port_config, port, 0, setval)); 183 184 /* 3.b: Mask the Intr DD_TIMER_MASK_A|_B by setting 0 (pbmp) */ 185 COMPILER_64_ZERO(rval64); 186 187 SOC_IF_ERROR_RETURN( 188 soc_reg_get(unit, hw_res->timer_mask[cos], pipe, 189 0, &rval64)); 190 191 COMPILER_64_NOT(temp_mask64); 192 COMPILER_64_AND(rval64, temp_mask64); 193 SOC_IF_ERROR_RETURN( 194 soc_reg_set(unit, hw_res->timer_mask[cos], pipe, 0, rval64)); 195 196 /* 3.c: Turn timer off DD_TIMER_ENABLE_A|_B by setting 1 (pbmp) */ 197 COMPILER_64_ZERO(rval64); 198 199 SOC_IF_ERROR_RETURN( 200 soc_reg_get(unit, hw_res->timer_en[cos], pipe, 201 0, &rval64)); 202 203 COMPILER_64_OR(rval64, temp_en64); 204 SOC_IF_ERROR_RETURN( 205 soc_reg_set(unit, hw_res->timer_en[cos], pipe, 0, rval64)); 206 207 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 208 if(pfc_deadlock_cb->pfc_deadlock_cb) { 209 pfc_deadlock_cb->pfc_deadlock_cb(unit, port, priority, 210 bcmCosqPfcDeadlockRecoveryEventEnd, 211 pfc_deadlock_cb->pfc_deadlock_userdata); 212 } 213 214 215 SOC_PBMP_PORT_REMOVE(pfc_deadlock_pri_config->deadlock_ports, port); 216 217 return BCM_E_NONE; 218 } 219 220 /* Routine to update the recovery status of ports which are in Recovery state 221 */ 222 int 223 _bcm_pfc_deadlock_recovery_update(int unit, int cos) 224 { 225 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 226 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 227 bcm_port_t port; 228 int priority = 0; 229 230 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 231 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 232 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 233 234 BCM_PBMP_ITER(pfc_deadlock_pri_config->deadlock_ports, port) { 235 if (port >= MAX_PORT(unit)) { 236 break; /* Process for valid ports */ 237 } 238 /* 239 * COVERITY 240 * 241 * Max Port num will be updated dynamically per device. 242 */ 243 /* coverity[overrun-local : FALSE] */ 244 if (pfc_deadlock_pri_config->port_recovery_count[port]) { 245 pfc_deadlock_pri_config->port_recovery_count[port]--; 246 } else { 247 BCM_IF_ERROR_RETURN( 248 _bcm_pfc_deadlock_recovery_end(unit, cos, port)); 249 } 250 } 251 return BCM_E_NONE; 252 } 253 254 /* Routine to begin recovery when a Port is deaclared to be in Deadlock by 255 * Hardware 256 */ 257 STATIC int 258 _bcm_pfc_deadlock_recovery_begin(int unit, int cos, int pipe, int pipe_mmu_port) 259 { 260 soc_info_t *si; 261 uint32 rval, setval, uc_cos_bmp = 0; 262 int phy_port, port, mmu_port, priority = 0; 263 uint64 rval64, temp_rval64, temp_mask64, temp_en64; 264 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 265 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 266 _bcm_pfc_hw_resorces_t *hw_res = NULL; 267 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 268 #ifdef BCM_TOMAHAWK_SUPPORT 269 uint32 user_rval = 0; 270 #endif 271 si = &SOC_INFO(unit); 272 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 273 hw_res = &pfc_deadlock_control->hw_regs_fields; 274 275 /* convert local mmu_port(per pipe) to global mmu_port */ 276 mmu_port = pipe_mmu_port + (pipe * _MMU_PORT_STRIDE); 277 phy_port = si->port_m2p_mapping[mmu_port]; 278 port = si->port_p2l_mapping[phy_port]; 279 COMPILER_64_ZERO(temp_en64); 280 COMPILER_64_ZERO(temp_mask64); 281 COMPILER_64_ZERO(temp_rval64); 282 283 if (port >= MAX_PORT(unit)) { 284 return BCM_E_PARAM; /* Process for valid ports */ 285 } 286 if (pipe_mmu_port < 32) { 287 COMPILER_64_SET(temp_rval64, 0, (1 << pipe_mmu_port)); 288 } else { 289 COMPILER_64_SET(temp_rval64, (1 << (pipe_mmu_port - 32)), 0); 290 } 291 COMPILER_64_OR(temp_mask64, temp_rval64); 292 COMPILER_64_OR(temp_en64, temp_rval64); 293 294 LOG_INFO(BSL_LS_BCM_COSQ, 295 (BSL_META_U(unit, 296 "PFC Deadlock Detected: Cos %d port=%d\n"), 297 cos, port)); 298 299 /* 2.a: Mask the Intr DD_TIMER_MASK_A|_B by setting 1 (pbmp) */ 300 COMPILER_64_ZERO(rval64); 301 302 SOC_IF_ERROR_RETURN( 303 soc_reg_get(unit, hw_res->timer_mask[cos], pipe, 304 0, &rval64)); 305 306 COMPILER_64_OR(rval64, temp_mask64); 307 SOC_IF_ERROR_RETURN( 308 soc_reg_set(unit, hw_res->timer_mask[cos], pipe, 309 0, rval64)); 310 311 /* 2.b: Turn timer off DD_TIMER_ENABLE_A|_B by setting 0 (pbmp) */ 312 COMPILER_64_ZERO(rval64); 313 314 SOC_IF_ERROR_RETURN( 315 soc_reg_get(unit, hw_res->timer_en[cos], pipe, 316 0, &rval64)); 317 318 COMPILER_64_NOT(temp_en64); 319 COMPILER_64_AND(rval64, temp_en64); 320 SOC_IF_ERROR_RETURN( 321 soc_reg_set(unit, hw_res->timer_en[cos], pipe, 322 0, rval64)); 323 324 /* 2.c: For that port, set ignore_pfc_xoff = 1 (per port reg) */ 325 setval = 0; 326 SOC_IF_ERROR_RETURN( 327 soc_reg32_get(unit, hw_res->port_config, port, 0, &setval)); 328 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 329 330 #ifdef BCM_TOMAHAWK_SUPPORT 331 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 332 if (soc_property_get(unit, spn_PFC_DEADLOCK_SEQ_CONTROL, 0) && 333 SOC_IS_TOMAHAWKX(unit) && pfc_deadlock_cb->pfc_deadlock_cb) { 334 user_rval = pfc_deadlock_cb->pfc_deadlock_cb(unit, port, priority, 335 bcmCosqPfcDeadlockRecoveryEventBegin, 336 pfc_deadlock_cb->pfc_deadlock_userdata); 337 338 if (user_rval) { 339 rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, 340 port, &uc_cos_bmp); 341 if (rval != BCM_E_NONE) { 342 rval = 0; 343 rval |= (1 << priority); 344 } else { 345 rval = 0; 346 rval |= uc_cos_bmp; 347 } 348 setval |= rval; 349 350 SOC_IF_ERROR_RETURN( 351 soc_reg32_set(unit, hw_res->port_config, port, 0, setval)); 352 } 353 return BCM_E_NONE; 354 } else 355 #endif 356 { 357 rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, 358 port, &uc_cos_bmp); 359 if(rval != BCM_E_NONE) { 360 rval = 0; 361 rval |= (1 << priority); 362 } else { 363 rval = 0; 364 rval |= uc_cos_bmp; 365 } 366 367 SOC_IF_ERROR_RETURN( 368 soc_reg32_set(unit, hw_res->port_config, port, 0, rval)); 369 370 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 371 if(pfc_deadlock_cb->pfc_deadlock_cb) { 372 pfc_deadlock_cb->pfc_deadlock_cb(unit, port, priority, 373 bcmCosqPfcDeadlockRecoveryEventBegin, 374 pfc_deadlock_cb->pfc_deadlock_userdata); 375 } 376 } 377 378 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 379 380 /* Recovery count calculated from Configured Recovery timer. 381 * Note: recovery_timer is in msecs and cb_interval is in usecs. 382 */ 383 pfc_deadlock_pri_config->port_recovery_count[port] = 1 + 384 ((pfc_deadlock_pri_config->recovery_timer * 1000) / 385 _BCM_PFC_DEADLOCK_CB_INTERVAL(0)); 386 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->deadlock_ports, port); 387 return BCM_E_NONE; 388 } 389 390 /* 391 * Function: 392 * _bcm_pfc_deadlock_monitor 393 * Purpose: 394 * 1) Monitor the hardware for Deadlock status 395 * 2) Start Recovery process for the Deadlocked port/queue 396 * 3) Reset Port back to original state on expiry of recovery phase 397 * Parameters: 398 * unit - (IN) unit number 399 * Returns: 400 * BCM_E_XXX 401 * Notes: 402 * Step 1 - Monitor (Deadlock Detection phase): 403 * Sw polls for Deadlock detection intr set for port 404 * DD_TIMER_STATUS_A|_B (pbmp) 405 * 406 * Step 2: Recovery Begin phase 407 * 2.a: Mask the Intr DD_TIMER_MASK_A|_B by setting 1 (pbmp) 408 * 2.b: Turn timer off DD_TIMER_ENABLE_A|_B by setting 0 (pbmp) 409 * 2.c: For that port, set ignore_pfc_xoff = 1 (per port reg) 410 * 2.4: Start recovery timer 411 * Step 3: Recovery End phase (On expiry of recovery timer) 412 * 3.a: Reset ignore_xoff; set ignore_pfc_xoff = 0 413 * 3.b: UnMask the Intr DD_TIMER_MASK_A|_B by setting 0 (pbmp) 414 * 3.c: Turn timer off DD_TIMER_ENABLE_A|_B by setting 1 (pbmp) 415 */ 416 STATIC int 417 _bcm_pfc_deadlock_monitor(int unit) 418 { 419 int i = 0, pipe, mmu_port, priority = 0, user_control = 0; 420 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 421 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 422 #ifdef BCM_TOMAHAWK_SUPPORT 423 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 424 #endif 425 _bcm_pfc_hw_resorces_t *hw_res = NULL; 426 uint64 status64, mask64; 427 428 #ifdef BCM_HELIX5_SUPPORT 429 if (SOC_IS_HELIX5(unit)) { 430 return (_bcm_hx5_pfc_deadlock_monitor(unit)); 431 } 432 #endif 433 434 #ifdef BCM_TRIDENT3_SUPPORT 435 if (SOC_IS_TRIDENT3X(unit)) { 436 return (_bcm_td3_pfc_deadlock_monitor(unit)); 437 } 438 #endif 439 440 COMPILER_64_ZERO(status64); 441 COMPILER_64_ZERO(mask64); 442 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 443 if (!pfc_deadlock_control) { 444 return BCM_E_INIT; 445 } 446 hw_res = &pfc_deadlock_control->hw_regs_fields; 447 448 #ifdef BCM_TOMAHAWK_SUPPORT 449 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 450 if (!pfc_deadlock_cb) { 451 return BCM_E_INIT; 452 } 453 if (soc_property_get(unit, spn_PFC_DEADLOCK_SEQ_CONTROL, 0) && 454 SOC_IS_TOMAHAWKX(unit) && pfc_deadlock_cb->pfc_deadlock_cb) { 455 user_control = 1; 456 } 457 #endif 458 459 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 460 /* Check if index is in Use */ 461 if (pfc_deadlock_control->hw_cos_idx_inuse[i] == TRUE) { 462 /* Check Hardware if New ports have been declared to be in 463 * Deadlock condition 464 */ 465 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 466 SOC_IF_ERROR_RETURN( 467 soc_reg_get(unit, hw_res->timer_status[i], pipe, 468 0, &status64)); 469 SOC_IF_ERROR_RETURN( 470 soc_reg_get(unit, hw_res->timer_mask[i], pipe, 471 0, &mask64)); 472 /* Mask - bit 0 indicates enabled for reporting */ 473 COMPILER_64_NOT(mask64); 474 COMPILER_64_AND(status64, mask64); 475 476 if (COMPILER_64_IS_ZERO(status64) == 0) { 477 /* New ports declared to be in Deadlock status */ 478 for (mmu_port = 0; mmu_port < 34; mmu_port++) { 479 if (mmu_port < 32) { 480 if ((COMPILER_64_LO(status64) & 481 (1 << mmu_port)) == FALSE) { 482 continue; 483 } 484 } else { 485 if ((COMPILER_64_HI(status64) & 486 (1 << (mmu_port - 32))) == FALSE) { 487 continue; 488 } 489 } 490 BCM_IF_ERROR_RETURN( 491 _bcm_pfc_deadlock_recovery_begin(unit, i, 492 pipe, mmu_port)); 493 } 494 } 495 } 496 497 if (!user_control) { 498 /* Update the count for ports already in Deadlock state and Reset 499 * those ports where recovery timer has expired. 500 */ 501 priority = pfc_deadlock_control->pfc_cos2pri[i]; 502 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 503 /* Updates required for Enabled COS */ 504 if (SOC_PBMP_NOT_NULL(pfc_deadlock_pri_config->deadlock_ports)) { 505 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_recovery_update(unit, i)); 506 } 507 } 508 } 509 } 510 return BCM_E_NONE; 511 } 512 513 /* Callback routine registered with DPC framework for, 514 * 1) Monitoring Deadlock status 515 * 2) Start/Stop Recovery process 516 */ 517 STATIC void 518 pfc_deadlock_cb(void* owner, void* time_as_ptr, void *cb_time_as_ptr, 519 void *unit_as_ptr, void* unused_3) 520 { 521 int callback_time; 522 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 523 int unit = (int) (int)(size_t)unit_as_ptr; 524 525 sal_dpc_cancel(owner); 526 _bcm_pfc_deadlock_monitor(unit); 527 528 #ifdef BCM_HELIX5_SUPPORT 529 if (SOC_IS_HELIX5(unit)) { 530 callback_time = _BCM_HX5_PFC_DEADLOCK_CB_INTERVAL(unit); 531 if (_BCM_HX5_PFC_DEADLOCK_CB_ENABLED(unit)) { 532 sal_dpc_time(callback_time, &pfc_deadlock_cb, owner, 533 INT_TO_PTR(sal_time_usecs()), INT_TO_PTR(callback_time), 534 0, 0); 535 } 536 _BCM_HX5_PFC_DEADLOCK_CB_COUNT(unit)++; 537 } else 538 #endif 539 #ifdef BCM_TRIDENT3_SUPPORT 540 if (SOC_IS_TRIDENT3X(unit) && !SOC_IS_HELIX5(unit)) { 541 callback_time = _BCM_TD3_PFC_DEADLOCK_CB_INTERVAL(unit); 542 if (_BCM_TD3_PFC_DEADLOCK_CB_ENABLED(unit)) { 543 sal_dpc_time(callback_time, &pfc_deadlock_cb, owner, 544 INT_TO_PTR(sal_time_usecs()), INT_TO_PTR(callback_time), 545 0, 0); 546 } 547 _BCM_TD3_PFC_DEADLOCK_CB_COUNT(unit)++; 548 } else 549 #endif 550 { 551 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 552 if (!pfc_deadlock_control) { 553 return; 554 } 555 callback_time = _BCM_PFC_DEADLOCK_CB_INTERVAL(unit); 556 if (_BCM_PFC_DEADLOCK_CB_ENABLED(unit)) { 557 sal_dpc_time(callback_time, &pfc_deadlock_cb, owner, 558 INT_TO_PTR(sal_time_usecs()), INT_TO_PTR(callback_time), 559 0, 0); 560 } 561 _BCM_PFC_DEADLOCK_CB_COUNT(unit)++; 562 } 563 } 564 565 STATIC int 566 _bcm_pfc_deadlock_hw_cos_index_get(int unit, bcm_cos_t priority, 567 int *hw_cos_index) 568 { 569 int i, cos_val; 570 uint32 rval = 0; 571 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 572 _bcm_pfc_hw_resorces_t *hw_res = NULL; 573 574 #ifdef BCM_HELIX5_SUPPORT 575 if (SOC_IS_HELIX5(unit)) { 576 return (_bcm_hx5_pfc_deadlock_hw_cos_index_get(unit, 577 priority, hw_cos_index)); 578 } 579 #endif 580 #ifdef BCM_TRIDENT3_SUPPORT 581 if (SOC_IS_TRIDENT3X(unit)) { 582 return (_bcm_td3_pfc_deadlock_hw_cos_index_get(unit, 583 priority, hw_cos_index)); 584 } 585 #endif 586 587 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 588 hw_res = &pfc_deadlock_control->hw_regs_fields; 589 590 SOC_IF_ERROR_RETURN( 591 soc_reg32_get(unit, hw_res->chip_config[0], REG_PORT_ANY, 0, &rval)); 592 593 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 594 cos_val = soc_reg_field_get(unit, hw_res->chip_config[0], rval, 595 hw_res->cos_field[i]); 596 if ((cos_val == priority) && 597 (pfc_deadlock_control->hw_cos_idx_inuse[i] == TRUE)) { 598 *hw_cos_index = i; 599 return BCM_E_NONE; 600 } 601 } 602 return BCM_E_NOT_FOUND; 603 } 604 605 STATIC int 606 _bcm_pfc_deadlock_hw_cos_index_set(int unit, bcm_cos_t priority, 607 int *hw_cos_index) 608 { 609 int i, first_avail = -1, rv = BCM_E_NONE; 610 int temp_hw_index = -1; 611 uint32 rval = 0; 612 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 613 _bcm_pfc_deadlock_config_t *pfc_deadlock_config = NULL; 614 _bcm_pfc_hw_resorces_t *hw_res = NULL; 615 616 #ifdef BCM_HELIX5_SUPPORT 617 if (SOC_IS_HELIX5(unit)) { 618 return (_bcm_hx5_pfc_deadlock_hw_cos_index_set(unit, 619 priority, hw_cos_index)); 620 } 621 #endif 622 #ifdef BCM_TRIDENT3_SUPPORT 623 if (SOC_IS_TRIDENT3X(unit)) { 624 return (_bcm_td3_pfc_deadlock_hw_cos_index_set(unit, 625 priority, hw_cos_index)); 626 } 627 #endif 628 629 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 630 hw_res = &pfc_deadlock_control->hw_regs_fields; 631 632 rv = _bcm_pfc_deadlock_hw_cos_index_get(unit, priority, &temp_hw_index); 633 if (rv != BCM_E_NONE) { 634 if (rv != BCM_E_NOT_FOUND) { 635 return rv; 636 } 637 } 638 639 if (temp_hw_index != -1) { 640 /* Config for this priority exists already. Donot reprogram */ 641 *hw_cos_index = temp_hw_index; 642 return BCM_E_NONE; 643 } 644 645 if (pfc_deadlock_control->pfc_deadlock_cos_used >= 646 pfc_deadlock_control->pfc_deadlock_cos_max) { 647 /* Config does not exist for given Priority and System Max reached */ 648 return BCM_E_RESOURCE;; 649 } 650 651 SOC_IF_ERROR_RETURN( 652 soc_reg32_get(unit, hw_res->chip_config[0], REG_PORT_ANY, 0, &rval)); 653 654 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 655 if ((first_avail == -1) && 656 (pfc_deadlock_control->hw_cos_idx_inuse[i] == FALSE)) { 657 /* Store the First available Cos idx for Use */ 658 first_avail = i; 659 break; 660 } 661 } 662 663 if (first_avail == -1) { 664 /* New index required, yet No available slots */ 665 return BCM_E_RESOURCE; 666 } 667 668 /* New priority. Free slot found (first_avail) for programming */ 669 pfc_deadlock_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 670 pfc_deadlock_config->priority = priority; 671 pfc_deadlock_config->flags |= _BCM_PFC_DEADLOCK_F_ENABLE; 672 pfc_deadlock_control->hw_cos_idx_inuse[first_avail] = TRUE; 673 pfc_deadlock_control->pfc_deadlock_cos_used++; 674 *hw_cos_index = first_avail; 675 return BCM_E_NONE; 676 } 677 678 /* Routine to check given detection_timer against the time_unit configured using 679 * Switch control bcmSwitchPFCDeadlockDetectionTimeInterval 680 * 681 * Return: 682 * BCM_E_PARAM - if timer does not fall within the range 683 * BCM_E_NONE - Operation success 684 * Note: 685 * detection_timer - (INOUT) - Aligned timer(floor value) will be returned. 686 */ 687 STATIC int 688 _bcm_pfc_deadlock_detection_timer_validate(int unit, uint32 *detection_timer) 689 { 690 uint32 detection_granularity = 0, time_offset; 691 692 #ifdef BCM_HELIX5_SUPPORT 693 if (SOC_IS_HELIX5(unit)) { 694 detection_granularity = (_BCM_HX5_PFC_DEADLOCK_TIME_UNIT(unit) == 695 bcmSwitchPFCDeadlockDetectionInterval10MiliSecond)? 10 : 100; 696 } else 697 #endif 698 #ifdef BCM_TRIDENT3_SUPPORT 699 if (SOC_IS_TRIDENT3X(unit) && !SOC_IS_HELIX5(unit)) { 700 detection_granularity = (_BCM_TD3_PFC_DEADLOCK_TIME_UNIT(unit) == 701 bcmSwitchPFCDeadlockDetectionInterval10MiliSecond)? 10 : 100; 702 } else 703 #endif 704 { 705 detection_granularity = (_BCM_PFC_DEADLOCK_TIME_UNIT(unit) == 706 bcmSwitchPFCDeadlockDetectionInterval10MiliSecond) ? 10 : 100; 707 } 708 709 time_offset = *detection_timer / detection_granularity; 710 if (time_offset > 15) { 711 /* Time val can take value from 0-15 (4b) */ 712 return BCM_E_PARAM; 713 } 714 *detection_timer = time_offset * detection_granularity; 715 return BCM_E_NONE; 716 } 717 718 /* Routine to perform the Set/Get operation for the Priority */ 719 STATIC int 720 _bcm_pfc_deadlock_hw_oper(int unit, 721 _bcm_pfc_deadlock_oper_t operation, 722 bcm_cos_t priority, 723 _bcm_pfc_deadlock_config_t *config) 724 { 725 int hw_cos_index = -1; 726 uint32 rval = 0; 727 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 728 _bcm_pfc_hw_resorces_t *hw_res = NULL; 729 uint32 detection_granularity = 0; 730 731 #ifdef BCM_HELIX5_SUPPORT 732 if (SOC_IS_HELIX5(unit)){ 733 return _bcm_hx5_pfc_deadlock_hw_oper(unit, operation, 734 priority, config); 735 } 736 #endif 737 #ifdef BCM_TRIDENT3_SUPPORT 738 if (SOC_IS_TRIDENT3X(unit)){ 739 return _bcm_td3_pfc_deadlock_hw_oper(unit, operation, 740 priority, config); 741 } 742 #endif 743 744 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 745 hw_res = &pfc_deadlock_control->hw_regs_fields; 746 detection_granularity = (_BCM_PFC_DEADLOCK_TIME_UNIT(unit) == 747 bcmSwitchPFCDeadlockDetectionInterval10MiliSecond) ? 10 : 100; 748 749 BCM_IF_ERROR_RETURN( 750 _bcm_pfc_deadlock_hw_cos_index_set(unit, priority, &hw_cos_index)); 751 752 if (hw_cos_index == -1) { 753 /* No matching or free hw_index available for use */ 754 return BCM_E_RESOURCE; 755 } 756 757 rval = 0; 758 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, hw_res->chip_config[0], 759 REG_PORT_ANY, 0, &rval)); 760 if (operation == _bcmPfcDeadlockOperGet) { 761 762 config->detection_timer = soc_reg_field_get(unit, 763 hw_res->chip_config[0], rval, 764 hw_res->time_init_val[hw_cos_index]); 765 config->detection_timer *= detection_granularity; 766 } else { /* _bcmPfcDeadlockOperSet */ 767 soc_reg_field_set(unit, hw_res->chip_config[0], &rval, 768 hw_res->time_init_val[hw_cos_index], 769 (config->detection_timer / detection_granularity)); 770 soc_reg_field_set(unit, hw_res->chip_config[0], &rval, 771 hw_res->cos_field[hw_cos_index], priority); 772 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, hw_res->chip_config[0], 773 REG_PORT_ANY, 0, rval)); 774 config->priority = priority; 775 pfc_deadlock_control->pfc_cos2pri[hw_cos_index] = priority; 776 pfc_deadlock_control->pfc_pri2cos[priority] = hw_cos_index; 777 } 778 779 return BCM_E_NONE; 780 } 781 782 #ifdef BCM_TRIDENT3_SUPPORT 783 int _bcm_td3_pfc_deadlock_update_cos_used(int unit) 784 { 785 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 786 _bcm_pfc_deadlock_config_t *pfc_deadlock_config = NULL; 787 int idx = 0; 788 789 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 790 pfc_deadlock_control->pfc_deadlock_cos_used = 0; 791 792 for (idx = 0; idx < TD3_PFC_DEADLOCK_MAX_COS; idx++) { 793 pfc_deadlock_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, idx); 794 if (pfc_deadlock_config && 795 SOC_PBMP_NOT_NULL(pfc_deadlock_config->enabled_ports)) { 796 pfc_deadlock_control->pfc_deadlock_cos_used++; 797 } 798 } 799 if (pfc_deadlock_control->pfc_deadlock_cos_used == 0) { 800 sal_dpc_cancel(INT_TO_PTR(&pfc_deadlock_cb)); 801 pfc_deadlock_control->cb_enabled = FALSE; 802 } else { 803 if (pfc_deadlock_control->cb_enabled == FALSE) { 804 pfc_deadlock_control->cb_enabled = TRUE; 805 pfc_deadlock_cb(INT_TO_PTR(&pfc_deadlock_cb), 806 INT_TO_PTR(_BCM_TD3_PFC_DEADLOCK_CB_INTERVAL(unit)), 807 INT_TO_PTR(sal_time_usecs()), 808 INT_TO_PTR(unit), 0); 809 } 810 } 811 812 if (pfc_deadlock_control->pfc_deadlock_cos_used > 813 pfc_deadlock_control->pfc_deadlock_cos_max) { 814 /* Illegal case */ 815 return BCM_E_INIT; 816 } 817 return BCM_E_NONE; 818 } 819 #endif 820 821 #ifdef BCM_HELIX5_SUPPORT 822 int _bcm_hx5_pfc_deadlock_update_cos_used(int unit) 823 { 824 _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 825 _bcm_pfc_deadlock_config_t *pfc_deadlock_config = NULL; 826 int idx = 0; 827 828 pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit); 829 pfc_deadlock_control->pfc_deadlock_cos_used = 0; 830 831 for (idx = 0; idx < HX5_PFC_DEADLOCK_MAX_COS; idx++) { 832 pfc_deadlock_config = _BCM_HX5_PFC_DEADLOCK_CONFIG(unit, idx); 833 if (pfc_deadlock_config && 834 SOC_PBMP_NOT_NULL(pfc_deadlock_config->enabled_ports)) { 835 pfc_deadlock_control->pfc_deadlock_cos_used++; 836 } 837 } 838 if (pfc_deadlock_control->pfc_deadlock_cos_used == 0) { 839 sal_dpc_cancel(INT_TO_PTR(&pfc_deadlock_cb)); 840 pfc_deadlock_control->cb_enabled = FALSE; 841 } else { 842 if (pfc_deadlock_control->cb_enabled == FALSE) { 843 pfc_deadlock_control->cb_enabled = TRUE; 844 pfc_deadlock_cb(INT_TO_PTR(&pfc_deadlock_cb), 845 INT_TO_PTR(_BCM_HX5_PFC_DEADLOCK_CB_INTERVAL(unit)), 846 INT_TO_PTR(sal_time_usecs()), 847 INT_TO_PTR(unit), 0); 848 } 849 } 850 851 if (pfc_deadlock_control->pfc_deadlock_cos_used > 852 pfc_deadlock_control->pfc_deadlock_cos_max) { 853 /* Illegal case */ 854 return BCM_E_INIT; 855 } 856 return BCM_E_NONE; 857 } 858 #endif 859 int _bcm_pfc_deadlock_update_cos_used(int unit) 860 { 861 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 862 _bcm_pfc_deadlock_config_t *pfc_deadlock_config = NULL; 863 int idx = 0; 864 865 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 866 867 pfc_deadlock_control->pfc_deadlock_cos_used = 0; 868 869 for (idx = 0; idx < PFC_DEADLOCK_MAX_COS; idx++) { 870 pfc_deadlock_config = _BCM_PFC_DEADLOCK_CONFIG(unit, idx); 871 if (pfc_deadlock_config && 872 SOC_PBMP_NOT_NULL(pfc_deadlock_config->enabled_ports)) { 873 pfc_deadlock_control->pfc_deadlock_cos_used++; 874 } 875 } 876 if (pfc_deadlock_control->pfc_deadlock_cos_used == 0) { 877 sal_dpc_cancel(INT_TO_PTR(&pfc_deadlock_cb)); 878 pfc_deadlock_control->cb_enabled = FALSE; 879 } else { 880 if (pfc_deadlock_control->cb_enabled == FALSE) { 881 pfc_deadlock_control->cb_enabled = TRUE; 882 pfc_deadlock_cb(INT_TO_PTR(&pfc_deadlock_cb), 883 INT_TO_PTR(_BCM_PFC_DEADLOCK_CB_INTERVAL(unit)), 884 INT_TO_PTR(sal_time_usecs()), INT_TO_PTR(unit), 0); 885 } 886 } 887 888 if (pfc_deadlock_control->pfc_deadlock_cos_used > 889 pfc_deadlock_control->pfc_deadlock_cos_max) { 890 /* Illegal case */ 891 return BCM_E_INIT; 892 } 893 return BCM_E_NONE; 894 } 895 896 STATIC int 897 _bcm_pfc_deadlock_q_config_helper(int unit, 898 _bcm_pfc_deadlock_oper_t operation, 899 bcm_gport_t gport, 900 bcm_cosq_pfc_deadlock_queue_config_t *config, 901 uint8 *enable_status) 902 { 903 int rv = BCM_E_NONE; 904 uint32 temp_val_lo = 0, temp_val_hi = 0; 905 uint64 rval64; 906 bcm_port_t local_port; 907 _bcm_pfc_hw_resorces_t *hw_res = NULL; 908 soc_reg_t reg = INVALIDr; 909 soc_info_t *si = &SOC_INFO(unit); 910 int phy_port, mmu_port, pipe, priority, hw_cos_index = -1; 911 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 912 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 913 914 #ifdef BCM_HELIX5_SUPPORT 915 if (SOC_IS_HELIX5(unit)) { 916 return (_bcm_hx5_pfc_deadlock_q_config_helper(unit, 917 operation, gport, config, 918 enable_status)); 919 } else 920 #endif 921 #ifdef BCM_TRIDENT3_SUPPORT 922 if (SOC_IS_TRIDENT3X(unit)) { 923 return (_bcm_td3_pfc_deadlock_q_config_helper(unit, 924 operation, gport, config, 925 enable_status)); 926 } 927 #endif 928 929 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 930 931 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 932 /* Invalid Gport */ 933 return BCM_E_PARAM; 934 } 935 936 hw_res = &pfc_deadlock_control->hw_regs_fields; 937 if (pfc_deadlock_control->cosq_inv_mapping_get) { 938 rv = pfc_deadlock_control->cosq_inv_mapping_get(unit, gport, -1, 939 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 940 &local_port, &priority); 941 } else { 942 /* Mapping function not defined */ 943 return BCM_E_INIT; 944 } 945 if (rv != BCM_E_NONE) { 946 if (rv == BCM_E_NOT_FOUND) { 947 /* Given GPort/Queue has No Input priority mapping */ 948 return BCM_E_RESOURCE; 949 } 950 return rv; 951 } 952 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 953 954 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 955 956 BCM_IF_ERROR_RETURN( 957 _bcm_pfc_deadlock_hw_cos_index_get(unit, priority, &hw_cos_index)); 958 if (hw_cos_index == -1) { 959 /* No matching or free hw_index available for use */ 960 return BCM_E_RESOURCE; 961 } 962 963 reg = hw_res->timer_en[hw_cos_index]; 964 965 phy_port = si->port_l2p_mapping[local_port]; 966 mmu_port = si->port_p2m_mapping[phy_port]; 967 mmu_port %= SOC_TH_MMU_PORT_STRIDE; 968 COMPILER_64_ZERO(rval64); 969 970 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pipe, 0, &rval64)); 971 972 if (operation == _bcmPfcDeadlockOperGet) { /* GET */ 973 if (enable_status) { 974 *enable_status = 975 BCM_PBMP_MEMBER(pfc_deadlock_pri_config->deadlock_ports, 976 local_port); 977 } 978 if (config) { 979 if (mmu_port < 32) { 980 config->enable = 981 (COMPILER_64_LO(rval64) & (1 << mmu_port)) ? TRUE : FALSE; 982 } else { 983 config->enable = 984 (COMPILER_64_HI(rval64) & (1 << (mmu_port - 32))) ? 985 TRUE : FALSE; 986 } 987 } 988 return BCM_E_NONE; 989 } else { /* _bcmPfcDeadlockOperSet */ 990 temp_val_lo = COMPILER_64_LO(rval64); 991 temp_val_hi = COMPILER_64_HI(rval64); 992 993 if (config->enable) { 994 if (mmu_port < 32) { 995 temp_val_lo |= (1 << mmu_port); 996 } else { 997 temp_val_hi |= (1 << (mmu_port - 32)); 998 } 999 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, 1000 local_port); 1001 } else { 1002 if (mmu_port < 32) { 1003 temp_val_lo &= ~(1 << mmu_port); 1004 } else { 1005 temp_val_hi &= ~(1 << (mmu_port - 32)); 1006 } 1007 1008 SOC_PBMP_PORT_REMOVE(pfc_deadlock_pri_config->enabled_ports, 1009 local_port); 1010 } 1011 COMPILER_64_SET(rval64, temp_val_hi, temp_val_lo); 1012 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, pipe, 0, rval64)); 1013 1014 if (!config->enable && 1015 SOC_PBMP_MEMBER(pfc_deadlock_pri_config->deadlock_ports, local_port)) { 1016 BCM_IF_ERROR_RETURN( 1017 _bcm_pfc_deadlock_recovery_end(unit, hw_cos_index, local_port)); 1018 } 1019 if (SOC_PBMP_IS_NULL(pfc_deadlock_pri_config->enabled_ports)) { 1020 /*First for that port, set ignore_pfc_xoff = 0 (per port reg) */ 1021 BCM_IF_ERROR_RETURN( 1022 _bcm_pfc_deadlock_ignore_pfc_xoff_clear(unit, hw_cos_index, local_port)); 1023 pfc_deadlock_control->hw_cos_idx_inuse[hw_cos_index] = FALSE; 1024 pfc_deadlock_pri_config->flags &= ~_BCM_PFC_DEADLOCK_F_ENABLE; 1025 pfc_deadlock_pri_config->priority = -1; 1026 pfc_deadlock_control->pfc_cos2pri[hw_cos_index] = -1; 1027 pfc_deadlock_control->pfc_pri2cos[priority] = -1; 1028 } 1029 } 1030 1031 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_update_cos_used(unit)); 1032 return BCM_E_NONE; 1033 } 1034 1035 STATIC int 1036 _bcm_pfc_deadlock_config_helper(int unit, 1037 _bcm_pfc_deadlock_oper_t operation, 1038 bcm_cos_t priority, 1039 bcm_cosq_pfc_deadlock_config_t *config, 1040 bcm_cosq_pfc_deadlock_info_t *info) 1041 { 1042 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 1043 int hw_cos_index = -1; 1044 #ifdef BCM_HELIX5_SUPPORT 1045 int encode_cos_value; 1046 if (SOC_IS_HELIX5(unit)) { 1047 encode_cos_value = (priority & ~_BCM_PFC_DEADLOCK_MASK); 1048 if (encode_cos_value) { 1049 priority &= _BCM_PFC_DEADLOCK_MASK; 1050 if (encode_cos_value == BCM_COSQ_PFC_DEADLOCK_WIRELESS_COS) { 1051 priority += (1 * 8); 1052 }else if(encode_cos_value == BCM_COSQ_PFC_DEADLOCK_TRANSIT_COS) { 1053 priority += (2 * 8); 1054 } 1055 } else { 1056 priority &= _BCM_PFC_DEADLOCK_MASK; 1057 } 1058 pfc_deadlock_pri_config = _BCM_HX5_PFC_DEADLOCK_CONFIG(unit, priority); 1059 if (priority >= HX5_PFC_DEADLOCK_MAX_COS) { 1060 return BCM_E_PARAM; 1061 } 1062 } else 1063 #endif 1064 #ifdef BCM_TRIDENT3_SUPPORT 1065 if (SOC_IS_TRIDENT3X(unit) && !SOC_IS_HELIX5(unit)) { 1066 pfc_deadlock_pri_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 1067 if (priority >= TD3_PFC_DEADLOCK_MAX_COS) { 1068 return BCM_E_PARAM; 1069 } 1070 } else 1071 #endif 1072 { 1073 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 1074 if (priority >= PFC_DEADLOCK_MAX_COS) { 1075 return BCM_E_PARAM; 1076 } 1077 } 1078 1079 if ((config == NULL) && (info == NULL)) { 1080 return BCM_E_PARAM; 1081 } 1082 1083 if (operation == _bcmPfcDeadlockOperGet) { /* GET */ 1084 BCM_IF_ERROR_RETURN( 1085 _bcm_pfc_deadlock_hw_cos_index_get(unit, priority, &hw_cos_index)); 1086 if ((hw_cos_index == -1) || 1087 (!(pfc_deadlock_pri_config->flags & _BCM_PFC_DEADLOCK_F_ENABLE))) { 1088 return BCM_E_NOT_FOUND; 1089 } 1090 if (config != NULL) { 1091 config->detection_timer = pfc_deadlock_pri_config->detection_timer; 1092 config->recovery_timer = pfc_deadlock_pri_config->recovery_timer; 1093 } 1094 if (info != NULL) { 1095 info->enabled_pbmp = pfc_deadlock_pri_config->enabled_ports; 1096 /* Call to get current status */ 1097 info->deadlock_pbmp = pfc_deadlock_pri_config->deadlock_ports; 1098 } 1099 } else { /* _bcmPfcDeadlockOperSet */ 1100 if (config != NULL) { 1101 if (SOC_PBMP_NOT_NULL(pfc_deadlock_pri_config->deadlock_ports)) { 1102 /* Return BUSY if trying to modify config for existing Priority, 1103 * when recovery is in progress for some ports 1104 */ 1105 return BCM_E_BUSY; 1106 } 1107 pfc_deadlock_pri_config->detection_timer = config->detection_timer; 1108 pfc_deadlock_pri_config->recovery_timer = config->recovery_timer; 1109 /* 1110 * COVERITY 1111 */ 1112 /* coverity[overrun-call] */ 1113 BCM_IF_ERROR_RETURN( 1114 _bcm_pfc_deadlock_hw_oper(unit, operation, priority, 1115 pfc_deadlock_pri_config)); 1116 } 1117 } 1118 1119 return BCM_E_NONE; 1120 } 1121 1122 /* 1123 * Function: 1124 * _bcm_pfc_deadlock_control_set 1125 * Description: 1126 * Set PFC Deadlock feature's switch config. 1127 * Parameters: 1128 * unit - Device unit number 1129 * type - The desired configuration parameter to retrieve. 1130 * arg - Pointer to retrieved value 1131 * Returns: 1132 * BCM_E_xxx 1133 * Notes: 1134 * bcmSwitchPFCDeadlockCosMax - Set operation is not permitted 1135 */ 1136 int _bcm_pfc_deadlock_control_set(int unit, bcm_switch_control_t type, int arg) 1137 { 1138 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1139 _bcm_pfc_hw_resorces_t *hw_res = NULL; 1140 uint32 rval = 0, field_val = 0; 1141 soc_reg_t chip_config; 1142 1143 #ifdef BCM_HELIX5_SUPPORT 1144 if (SOC_IS_HELIX5(unit)) { 1145 return _bcm_hx5_pfc_deadlock_control_set(unit, type, arg); 1146 } 1147 #endif 1148 #ifdef BCM_TRIDENT3_SUPPORT 1149 if (SOC_IS_TRIDENT3X(unit)) { 1150 return _bcm_td3_pfc_deadlock_control_set(unit, type, arg); 1151 } 1152 #endif 1153 1154 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1155 if (pfc_deadlock_control == NULL) { 1156 return BCM_E_UNAVAIL; 1157 } 1158 hw_res = &pfc_deadlock_control->hw_regs_fields; 1159 1160 switch (type) { 1161 case bcmSwitchPFCDeadlockDetectionTimeInterval: 1162 if ((arg < 0) || 1163 (arg >= bcmSwitchPFCDeadlockDetectionIntervalCount)) { 1164 return BCM_E_PARAM; 1165 } 1166 1167 chip_config = hw_res->chip_config[0]; 1168 1169 rval = 0; 1170 if (arg == bcmSwitchPFCDeadlockDetectionInterval10MiliSecond) { 1171 field_val = 0; 1172 } else { 1173 field_val = 1; /* Default Unit - Order of 100ms */ 1174 } 1175 1176 if (chip_config == INVALIDr) { 1177 return BCM_E_UNAVAIL; 1178 } 1179 1180 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, 1181 REG_PORT_ANY, 0, &rval)); 1182 soc_reg_field_set(unit, chip_config, &rval, 1183 hw_res->time_unit_field, field_val); 1184 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, chip_config, 1185 REG_PORT_ANY, 0, rval)); 1186 pfc_deadlock_control->time_unit = arg; 1187 break; 1188 case bcmSwitchPFCDeadlockRecoveryAction: 1189 if ((arg < 0) || 1190 (arg >= bcmSwitchPFCDeadlockActionMaxCount)) { 1191 return BCM_E_PARAM; 1192 } 1193 1194 chip_config = hw_res->chip_config[1]; 1195 1196 rval = 0; 1197 if (arg == bcmSwitchPFCDeadlockActionDrop) { 1198 field_val = 1; 1199 } else { 1200 field_val = 0; /* Default action - Transmit */ 1201 } 1202 1203 if (chip_config == INVALIDr) { 1204 return BCM_E_UNAVAIL; 1205 } 1206 1207 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, 1208 REG_PORT_ANY, 0, &rval)); 1209 soc_reg_field_set(unit, chip_config, &rval, 1210 hw_res->recovery_action_field, field_val); 1211 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, chip_config, 1212 REG_PORT_ANY, 0, rval)); 1213 pfc_deadlock_control->recovery_action = arg; 1214 break; 1215 default: 1216 return BCM_E_UNAVAIL; 1217 } 1218 return BCM_E_NONE; 1219 } 1220 1221 /* 1222 * Function: 1223 * _bcm_pfc_deadlock_control_get 1224 * Description: 1225 * Retrieve PFC Deadlock feature's switch config. 1226 * Parameters: 1227 * unit - Device unit number 1228 * type - The desired configuration parameter to retrieve. 1229 * arg - Pointer to retrieved value 1230 * Returns: 1231 * BCM_E_xxx 1232 */ 1233 int _bcm_pfc_deadlock_control_get(int unit, bcm_switch_control_t type, int *arg) 1234 { 1235 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1236 _bcm_pfc_hw_resorces_t *hw_res = NULL; 1237 1238 #ifdef BCM_HELIX5_SUPPORT 1239 if (SOC_IS_HELIX5(unit)) { 1240 return _bcm_hx5_pfc_deadlock_control_get(unit, type, arg); 1241 } 1242 #endif 1243 #ifdef BCM_TRIDENT3_SUPPORT 1244 if (SOC_IS_TRIDENT3X(unit)) { 1245 return _bcm_td3_pfc_deadlock_control_get(unit, type, arg); 1246 } 1247 #endif 1248 1249 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1250 if (pfc_deadlock_control == NULL) { 1251 return BCM_E_UNAVAIL; 1252 } 1253 hw_res = &pfc_deadlock_control->hw_regs_fields; 1254 1255 switch (type) { 1256 case bcmSwitchPFCDeadlockDetectionTimeInterval: 1257 if (hw_res->chip_config[0] == INVALIDr) { 1258 return BCM_E_UNAVAIL; 1259 } 1260 *arg = pfc_deadlock_control->time_unit; 1261 break; 1262 case bcmSwitchPFCDeadlockRecoveryAction: 1263 if (hw_res->chip_config[1] == INVALIDr) { 1264 return BCM_E_UNAVAIL; 1265 } 1266 *arg = pfc_deadlock_control->recovery_action; 1267 break; 1268 default: 1269 return BCM_E_UNAVAIL; 1270 } 1271 return BCM_E_NONE; 1272 } 1273 1274 /* 1275 * Function: 1276 * _bcm_pfc_deadlock_control_get_hw 1277 * Description: 1278 * Retrieve PFC Deadlock feature's switch config. 1279 * Parameters: 1280 * unit - Device unit number 1281 * type - The desired configuration parameter to retrieve. 1282 * arg - Pointer to retrieved value 1283 * Returns: 1284 * BCM_E_xxx 1285 */ 1286 int 1287 _bcm_pfc_deadlock_control_get_hw(int unit, bcm_switch_control_t type, int *arg) 1288 { 1289 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1290 _bcm_pfc_hw_resorces_t *hw_res = NULL; 1291 uint32 rval = 0, field_val = 0; 1292 soc_reg_t chip_config; 1293 1294 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1295 1296 if (pfc_deadlock_control == NULL) { 1297 return BCM_E_UNAVAIL; 1298 } 1299 hw_res = &pfc_deadlock_control->hw_regs_fields; 1300 1301 switch (type) { 1302 case bcmSwitchPFCDeadlockDetectionTimeInterval: 1303 chip_config = hw_res->chip_config[0]; 1304 if (chip_config == INVALIDr) { 1305 return BCM_E_UNAVAIL; 1306 } 1307 rval = 0; 1308 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, 1309 REG_PORT_ANY, 0, &rval)); 1310 field_val = soc_reg_field_get(unit, chip_config, rval, 1311 hw_res->time_unit_field); 1312 if (field_val == 0) { 1313 *arg = bcmSwitchPFCDeadlockDetectionInterval10MiliSecond; 1314 } else { 1315 *arg = bcmSwitchPFCDeadlockDetectionInterval100MiliSecond; 1316 } 1317 break; 1318 case bcmSwitchPFCDeadlockRecoveryAction: 1319 chip_config = hw_res->chip_config[1]; 1320 if (chip_config == INVALIDr) { 1321 return BCM_E_UNAVAIL; 1322 } 1323 rval = 0; 1324 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, 1325 REG_PORT_ANY, 0, &rval)); 1326 field_val = soc_reg_field_get(unit, chip_config, rval, 1327 hw_res->recovery_action_field); 1328 1329 if (field_val == 1) { 1330 *arg = bcmSwitchPFCDeadlockActionDrop; 1331 } else { 1332 *arg = bcmSwitchPFCDeadlockActionTransmit; 1333 } 1334 break; 1335 default: 1336 return BCM_E_UNAVAIL; 1337 } 1338 return BCM_E_NONE; 1339 } 1340 1341 /* 1342 * Function: 1343 * _bcm_pfc_deadlock_max_cos_get 1344 * Description: 1345 * Retrieve PFC Deadlock feature's max supported cos. 1346 * Parameters: 1347 * unit - Device unit number 1348 * entries - Pointer to retrieved value 1349 * Returns: 1350 * BCM_E_xxx 1351 */ 1352 int _bcm_pfc_deadlock_max_cos_get(int unit, int *entries) 1353 { 1354 1355 #ifdef BCM_TOMAHAWK3_SUPPORT 1356 if (SOC_IS_TOMAHAWK3(unit)) { 1357 return BCM_E_UNAVAIL; 1358 } 1359 #endif 1360 #ifdef BCM_HELIX5_SUPPORT 1361 if (SOC_IS_HELIX5(unit)) { 1362 _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1363 pfc_deadlock_control = _bcm_hx5_pfc_deadlock_control[(unit)]; 1364 *entries = pfc_deadlock_control->pfc_deadlock_cos_max; 1365 } else 1366 #endif 1367 #ifdef BCM_TRIDENT3_SUPPORT 1368 if (SOC_IS_TRIDENT3X(unit) && !SOC_IS_HELIX5(unit)) { 1369 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1370 pfc_deadlock_control = _bcm_td3_pfc_deadlock_control[(unit)]; 1371 *entries = pfc_deadlock_control->pfc_deadlock_cos_max; 1372 } else 1373 #endif 1374 { 1375 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1376 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1377 *entries = pfc_deadlock_control->pfc_deadlock_cos_max; 1378 } 1379 return BCM_E_NONE; 1380 } 1381 1382 /* 1383 * Function: 1384 * _bcm_pfc_deadlock_config_set 1385 * Purpose: 1386 * Setup PFC deadlock feature to monitor for the given priority with 1387 * associated values. 1388 * Parameters: 1389 * unit - (IN) unit number 1390 * priority - (IN) priority 1391 * config - (IN) Config for a given priority 1392 * Returns: 1393 * BCM_E_XXX 1394 */ 1395 int _bcm_pfc_deadlock_config_set(int unit, bcm_cos_t priority, 1396 bcm_cosq_pfc_deadlock_config_t *config) 1397 { 1398 BCM_IF_ERROR_RETURN( 1399 _bcm_pfc_deadlock_detection_timer_validate(unit, 1400 &config->detection_timer)); 1401 BCM_IF_ERROR_RETURN( 1402 _bcm_pfc_deadlock_config_helper(unit, _bcmPfcDeadlockOperSet, 1403 priority, config, NULL)); 1404 return BCM_E_NONE; 1405 } 1406 1407 /* 1408 * Function: 1409 * _bcm_pfc_deadlock_config_get 1410 * Purpose: 1411 * Get config values for a given priority in PFC deadlock feature. 1412 * Parameters: 1413 * unit - (IN) unit number 1414 * priority - (IN) priority 1415 * config - (OUT) Config for a given priority 1416 * Returns: 1417 * BCM_E_XXX 1418 */ 1419 int _bcm_pfc_deadlock_config_get(int unit, bcm_cos_t priority, 1420 bcm_cosq_pfc_deadlock_config_t *config) 1421 { 1422 BCM_IF_ERROR_RETURN( 1423 _bcm_pfc_deadlock_config_helper(unit, _bcmPfcDeadlockOperGet, 1424 priority, config, NULL)); 1425 return BCM_E_NONE; 1426 } 1427 1428 /* 1429 * Function: 1430 * _bcm_pfc_deadlock_queue_config_set 1431 * Purpose: 1432 * Enable or disable the given Port/Queue for PFC deadlock feature to 1433 * monitor. 1434 * Parameters: 1435 * unit - (IN) unit number 1436 * gport - (IN) gport 1437 * config - (IN) Config for a given UC Queue Gport 1438 * Returns: 1439 * BCM_E_XXX 1440 */ 1441 int _bcm_pfc_deadlock_queue_config_set(int unit, bcm_gport_t gport, 1442 bcm_cosq_pfc_deadlock_queue_config_t *config) 1443 { 1444 BCM_IF_ERROR_RETURN( 1445 _bcm_pfc_deadlock_q_config_helper(unit, _bcmPfcDeadlockOperSet, 1446 gport, config, NULL)); 1447 return BCM_E_NONE; 1448 } 1449 1450 /* 1451 * Function: 1452 * _bcm_pfc_deadlock_queue_config_get 1453 * Purpose: 1454 * Get the Enable or disable monitoring status for the given Port/Queue. 1455 * Parameters: 1456 * unit - (IN) unit number 1457 * gport - (IN) gport 1458 * config - (OUT) Config for a given UC Queue Gport 1459 * Returns: 1460 * BCM_E_XXX 1461 */ 1462 int _bcm_pfc_deadlock_queue_config_get(int unit, bcm_gport_t gport, 1463 bcm_cosq_pfc_deadlock_queue_config_t *config) 1464 { 1465 BCM_IF_ERROR_RETURN( 1466 _bcm_pfc_deadlock_q_config_helper(unit, _bcmPfcDeadlockOperGet, 1467 gport, config, NULL)); 1468 return BCM_E_NONE; 1469 } 1470 1471 /* 1472 * Function: 1473 * _bcm_pfc_deadlock_queue_status_get 1474 * Purpose: 1475 * Get the current Deadlock status for the given Port/Queue. 1476 * Parameters: 1477 * unit - (IN) unit number 1478 * gport - (IN) gport 1479 * deadlock_status - (OUT) Deatlock status for the given UC Queue Gport 1480 * Returns: 1481 * BCM_E_XXX 1482 */ 1483 int _bcm_pfc_deadlock_queue_status_get(int unit, bcm_gport_t gport, 1484 uint8 *enable) 1485 { 1486 BCM_IF_ERROR_RETURN( 1487 _bcm_pfc_deadlock_q_config_helper(unit, _bcmPfcDeadlockOperGet, 1488 gport, NULL, enable)); 1489 1490 return BCM_E_NONE; 1491 } 1492 1493 /* 1494 * Function: 1495 * _bcm_cosq_pfc_deadlock_callback_register 1496 * Purpose: 1497 * Register pfc deadlock recovery callback in PFC deadlock feature. 1498 * Parameters: 1499 * unit - (IN) unit number 1500 * callback - (IN) callback function 1501 * userdata - (IN) user data 1502 * Returns: 1503 * BCM_E_XXX 1504 */ 1505 1506 int _bcm_cosq_pfc_deadlock_recovery_event_register( 1507 int unit, 1508 bcm_cosq_pfc_deadlock_recovery_event_cb_t callback, 1509 void *userdata) 1510 { 1511 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 1512 1513 #ifdef BCM_TOMAHAWK3_SUPPORT 1514 if (SOC_IS_TOMAHAWK3(unit)) { 1515 return _bcm_th3_pfc_deadlock_recovery_event_register(unit, callback, 1516 userdata); 1517 } 1518 #endif 1519 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 1520 pfc_deadlock_cb->pfc_deadlock_cb = callback; 1521 pfc_deadlock_cb->pfc_deadlock_userdata = userdata; 1522 1523 return BCM_E_NONE; 1524 } 1525 1526 /* 1527 * Function: 1528 * _bcm_cosq_pfc_deadlock_callback_unregister 1529 * Purpose: 1530 * Unregister pfc deadlock recovery callback in PFC deadlock feature. 1531 * Parameters: 1532 * unit - (IN) unit number 1533 * callback - (IN) callback function 1534 * userdata - (IN) user data 1535 * Returns: 1536 * BCM_E_XXX 1537 */ 1538 1539 int _bcm_cosq_pfc_deadlock_recovery_event_unregister( 1540 int unit, 1541 bcm_cosq_pfc_deadlock_recovery_event_cb_t callback, 1542 void *userdata) 1543 { 1544 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 1545 1546 #ifdef BCM_TOMAHAWK3_SUPPORT 1547 if (SOC_IS_TOMAHAWK3(unit)) { 1548 return _bcm_th3_pfc_deadlock_recovery_event_unregister(unit, callback, 1549 userdata); 1550 } 1551 #endif 1552 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 1553 pfc_deadlock_cb->pfc_deadlock_cb = NULL; 1554 pfc_deadlock_cb->pfc_deadlock_userdata = NULL; 1555 1556 return BCM_E_NONE; 1557 } 1558 1559 /* 1560 * Function: 1561 * bcm_esw_cosq_pfc_deadlock_info_get 1562 * Purpose: 1563 * Get bitmap of Enabled(Admin) and Current Deadlock ports status for a 1564 * given priority in PFC deadlock feature. 1565 * Parameters: 1566 * unit - (IN) unit number 1567 * priority - (IN) priority 1568 * info - (OUT) Info for a given priority 1569 * Returns: 1570 * BCM_E_XXX 1571 */ 1572 int _bcm_pfc_deadlock_info_get(int unit, bcm_cos_t priority, 1573 bcm_cosq_pfc_deadlock_info_t *pfc_deadlock_info) 1574 { 1575 BCM_IF_ERROR_RETURN( 1576 _bcm_pfc_deadlock_config_helper(unit, _bcmPfcDeadlockOperGet, priority, 1577 NULL, pfc_deadlock_info)); 1578 return BCM_E_NONE; 1579 } 1580 1581 #if defined(BCM_TOMAHAWK_SUPPORT) 1582 /* Set Chip level defautl values */ 1583 STATIC int 1584 _bcm_pfc_deadlock_default(int unit) 1585 { 1586 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1587 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 1588 int i = 0; 1589 1590 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1591 1592 _BCM_PFC_DEADLOCK_HW_RES_INIT(&pfc_deadlock_control->hw_regs_fields); 1593 pfc_deadlock_control->pfc_deadlock_cos_max = 0; 1594 pfc_deadlock_control->pfc_deadlock_cos_used = 0; 1595 1596 for (i = 0; i < COUNTOF(pfc_deadlock_control->hw_cos_idx_inuse); i++) { 1597 pfc_deadlock_control->hw_cos_idx_inuse[i] = FALSE; 1598 } 1599 for (i = 0; i < PFC_DEADLOCK_MAX_COS; i++) { 1600 pfc_deadlock_control->pfc_cos2pri[i] = -1; 1601 pfc_deadlock_control->pfc_pri2cos[i] = -1; 1602 1603 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, i); 1604 pfc_deadlock_pri_config->priority = -1; 1605 } 1606 sal_memset(pfc_deadlock_control->pfc_cos2pri, -1, 1607 (PFC_DEADLOCK_MAX_COS * sizeof(bcm_cos_t))); 1608 sal_memset(pfc_deadlock_control->pfc_pri2cos, -1, 1609 (PFC_DEADLOCK_MAX_COS * sizeof(bcm_cos_t))); 1610 pfc_deadlock_control->cb_enabled = FALSE; 1611 pfc_deadlock_control->time_unit = 0; /* 100 ms */ 1612 pfc_deadlock_control->cb_interval = 100 * 1000; /* 100 ms */ 1613 return BCM_E_NONE; 1614 } 1615 #endif /* BCM_TOMAHAWK_SUPPORT */ 1616 1617 /* 1618 * Function: 1619 * _bcm_pfc_deadlock_recovery_reset 1620 * Purpose: 1621 * Recover the system back to default state. 1622 * Restore all ports from Deadlock/Recovery state, if Warm boot when 1623 * recovery was in progress 1624 * Parameters: 1625 * unit - unit number 1626 * Returns: 1627 * BCM_E_XXX 1628 */ 1629 int 1630 _bcm_pfc_deadlock_recovery_reset(int unit) 1631 { 1632 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1633 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 1634 int priority = 0, i; 1635 bcm_port_t port; 1636 1637 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1638 1639 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 1640 priority = pfc_deadlock_control->pfc_cos2pri[i]; 1641 /* Skipping invalid priorities */ 1642 if ((priority < 0) || (priority >= _TH_MMU_NUM_INT_PRI)) { 1643 continue; 1644 } 1645 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 1646 1647 /* 1648 * COVERITY: Max Port will take care of Port beyond supported range 1649 */ 1650 /* coverity[overrun-local : FALSE] */ 1651 BCM_PBMP_ITER(pfc_deadlock_pri_config->deadlock_ports, port) { 1652 if (port >= MAX_PORT(unit)) { 1653 break; /* Process for valid ports */ 1654 } 1655 /* 1656 * COVERITY 1657 * 1658 * Max Port num will be updated dynamically per device. 1659 */ 1660 /* coverity[overrun-local : FALSE] */ 1661 pfc_deadlock_pri_config->port_recovery_count[port] = 0; 1662 BCM_IF_ERROR_RETURN( 1663 _bcm_pfc_deadlock_recovery_end(unit, i, port)); 1664 } 1665 } 1666 pfc_deadlock_control->cb_enabled = FALSE; 1667 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_update_cos_used(unit)); 1668 pfc_deadlock_control->cosq_inv_mapping_get = NULL; 1669 1670 return BCM_E_NONE; 1671 } 1672 #ifdef BCM_WARM_BOOT_SUPPORT 1673 int 1674 _bcm_pfc_deadlock_alloc_size(int unit) 1675 { 1676 int alloc_sz = 0; 1677 int pfc_deadlock_cos_max = 0; 1678 1679 #if defined(BCM_TOMAHAWK_SUPPORT) 1680 if (SOC_IS_TOMAHAWKX(unit)) { 1681 pfc_deadlock_cos_max = 2; 1682 } 1683 #endif 1684 1685 /* pfc_cos2pri[pfc_deadlock_cos_max] */ 1686 alloc_sz += pfc_deadlock_cos_max * sizeof(int); 1687 /* cb_interval */ 1688 alloc_sz += sizeof(uint32); 1689 1690 return alloc_sz; 1691 } 1692 1693 /* 1694 * Function: 1695 * _bcm_pfc_deadlock_reinit 1696 * Purpose: 1697 * Reinitialize all states/data-structures from HW(Level 1 warmboot) 1698 * Parameters: 1699 * unit - unit number 1700 * Returns: 1701 * BCM_E_XXX 1702 */ 1703 int 1704 _bcm_pfc_deadlock_reinit(int unit) 1705 { 1706 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1707 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 1708 _bcm_pfc_hw_resorces_t *hw_res = NULL; 1709 int priority = 0, i, rv, temp_hw_index = -1, arg_value; 1710 int port, phy_port, mmu_port, pipe; 1711 soc_info_t *si = &SOC_INFO(unit); 1712 soc_reg_t en_reg, mask_reg; 1713 uint64 en_rval64[_TH_PIPES_PER_DEV]; 1714 uint64 mask_rval64[_TH_PIPES_PER_DEV]; 1715 1716 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1717 hw_res = &pfc_deadlock_control->hw_regs_fields; 1718 1719 BCM_IF_ERROR_RETURN 1720 (_bcm_pfc_deadlock_control_get_hw(unit, 1721 bcmSwitchPFCDeadlockDetectionTimeInterval, 1722 &arg_value)); 1723 pfc_deadlock_control->time_unit = arg_value; 1724 BCM_IF_ERROR_RETURN 1725 (_bcm_pfc_deadlock_control_get_hw(unit, 1726 bcmSwitchPFCDeadlockRecoveryAction, 1727 &arg_value)); 1728 pfc_deadlock_control->recovery_action = arg_value; 1729 1730 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 1731 priority = pfc_deadlock_control->pfc_cos2pri[i]; 1732 /* Skipping invalid priorities */ 1733 if ((priority < 0) || (priority >= PFC_DEADLOCK_MAX_COS)) { 1734 continue; 1735 } 1736 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 1737 1738 /* coverity[overrun-call] */ 1739 rv = _bcm_pfc_deadlock_hw_cos_index_get(unit, priority, &temp_hw_index); 1740 if (BCM_SUCCESS(rv)) { 1741 pfc_deadlock_pri_config->flags |= _BCM_PFC_DEADLOCK_F_ENABLE; 1742 pfc_deadlock_pri_config->priority = priority; 1743 /* coverity[overrun-call] */ 1744 BCM_IF_ERROR_RETURN( 1745 _bcm_pfc_deadlock_hw_oper(unit, _bcmPfcDeadlockOperGet, 1746 priority, pfc_deadlock_pri_config)); 1747 en_reg = hw_res->timer_en[temp_hw_index]; 1748 mask_reg = hw_res->timer_mask[temp_hw_index]; 1749 1750 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 1751 COMPILER_64_ZERO(en_rval64[pipe]); 1752 COMPILER_64_ZERO(mask_rval64[pipe]); 1753 1754 SOC_IF_ERROR_RETURN(soc_reg_get(unit, en_reg, 1755 pipe, 0, &en_rval64[pipe])); 1756 SOC_IF_ERROR_RETURN(soc_reg_get(unit, mask_reg, 1757 pipe, 0, &mask_rval64[pipe])); 1758 } 1759 1760 PBMP_ALL_ITER(unit, port) { 1761 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, port, &pipe)); 1762 phy_port = si->port_l2p_mapping[port]; 1763 mmu_port = si->port_p2m_mapping[phy_port]; 1764 mmu_port %= SOC_TH_MMU_PORT_STRIDE; 1765 if (mmu_port < 32) { 1766 if (COMPILER_64_LO(en_rval64[pipe]) & (1 << mmu_port)) { 1767 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, port); 1768 } else if (COMPILER_64_LO(mask_rval64[pipe]) & (1 << mmu_port)) { 1769 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, port); 1770 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->deadlock_ports, port); 1771 } 1772 } else { 1773 if (COMPILER_64_HI(en_rval64[pipe]) & (1 << (mmu_port - 32))) { 1774 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, port); 1775 } else if (COMPILER_64_LO(mask_rval64[pipe]) & (1 << (mmu_port - 32))) { 1776 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, port); 1777 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->deadlock_ports, port); 1778 } 1779 } 1780 } 1781 } 1782 } 1783 1784 return BCM_E_NONE; 1785 } 1786 #endif /* BCM_WARM_BOOT_SUPPORT */ 1787 /* 1788 * Function: 1789 * _bcm_pfc_deadlock_deinit 1790 * Purpose: 1791 * De-Initialize allocated memory for PFC Deadlock feature 1792 * Parameters: 1793 * unit - unit number 1794 * Returns: 1795 * BCM_E_XXX 1796 */ 1797 int 1798 _bcm_pfc_deadlock_deinit(int unit) 1799 { 1800 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1801 _bcm_pfc_deadlock_cb_t *pfc_deadlock_callback = NULL; 1802 1803 sal_dpc_cancel(INT_TO_PTR(&pfc_deadlock_cb)); 1804 1805 pfc_deadlock_callback = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 1806 if (pfc_deadlock_callback != NULL) { 1807 sal_free(pfc_deadlock_callback); 1808 _BCM_UNIT_PFC_DEADLOCK_CB(unit) = NULL; 1809 } 1810 1811 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1812 if (pfc_deadlock_control != NULL) { 1813 sal_free(pfc_deadlock_control); 1814 _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit) = NULL; 1815 } 1816 return BCM_E_NONE; 1817 } 1818 1819 /* 1820 * Function: 1821 * _bcm_pfc_deadlock_init 1822 * Purpose: 1823 * Initialize (clear) all states/data-structures 1824 * Parameters: 1825 * unit - unit number 1826 * Returns: 1827 * BCM_E_XXX 1828 */ 1829 int 1830 _bcm_pfc_deadlock_init(int unit) 1831 { 1832 int pfc_support = FALSE; 1833 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 1834 1835 #ifdef BCM_HELIX5_SUPPORT 1836 if (SOC_IS_HELIX5(unit)) { 1837 _bcm_hx5_pfc_deadlock_control_t *hx5_pfc_deadlock_control = NULL; 1838 BCM_IF_ERROR_RETURN(_bcm_hx5_pfc_deadlock_deinit(unit)); 1839 hx5_pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit); 1840 if (NULL == hx5_pfc_deadlock_control) { 1841 hx5_pfc_deadlock_control = 1842 sal_alloc(sizeof(_bcm_hx5_pfc_deadlock_control_t), "hx5_pfc_deadlock_ctrl"); 1843 if (!hx5_pfc_deadlock_control) { 1844 return BCM_E_MEMORY; 1845 } 1846 } 1847 sal_memset(hx5_pfc_deadlock_control, 0, sizeof(_bcm_hx5_pfc_deadlock_control_t)); 1848 _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit) = hx5_pfc_deadlock_control; 1849 } else 1850 #endif 1851 #ifdef BCM_TRIDENT3_SUPPORT 1852 if (SOC_IS_TRIDENT3X(unit) && !SOC_IS_HELIX5(unit)) { 1853 _bcm_td3_pfc_deadlock_control_t *td3_pfc_deadlock_control = NULL; 1854 BCM_IF_ERROR_RETURN(_bcm_td3_pfc_deadlock_deinit(unit)); 1855 td3_pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 1856 if (NULL == td3_pfc_deadlock_control) { 1857 td3_pfc_deadlock_control = 1858 sal_alloc(sizeof(_bcm_td3_pfc_deadlock_control_t), "td3_pfc_deadlock_ctrl"); 1859 if (!td3_pfc_deadlock_control) { 1860 return BCM_E_MEMORY; 1861 } 1862 } 1863 sal_memset(td3_pfc_deadlock_control, 0, sizeof(_bcm_td3_pfc_deadlock_control_t)); 1864 _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit) = td3_pfc_deadlock_control; 1865 } else 1866 #endif 1867 { 1868 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1869 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_deinit(unit)); 1870 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 1871 1872 if (NULL == pfc_deadlock_control) { 1873 pfc_deadlock_control = 1874 sal_alloc(sizeof(_bcm_pfc_deadlock_control_t), "pfc_deadlock_ctrl"); 1875 if (!pfc_deadlock_control) { 1876 return BCM_E_MEMORY; 1877 } 1878 } 1879 sal_memset(pfc_deadlock_control, 0, sizeof(_bcm_pfc_deadlock_control_t)); 1880 _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit) = pfc_deadlock_control; 1881 } 1882 1883 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 1884 1885 if (NULL == pfc_deadlock_cb) { 1886 pfc_deadlock_cb = 1887 sal_alloc(sizeof(_bcm_pfc_deadlock_cb_t), "pfc_deadlock_cb"); 1888 if (!pfc_deadlock_cb) { 1889 return BCM_E_MEMORY; 1890 } 1891 } 1892 sal_memset(pfc_deadlock_cb, 0, sizeof(_bcm_pfc_deadlock_cb_t)); 1893 pfc_deadlock_cb->pfc_deadlock_cb = NULL; 1894 pfc_deadlock_cb->pfc_deadlock_userdata = NULL; 1895 _BCM_UNIT_PFC_DEADLOCK_CB(unit) = pfc_deadlock_cb; 1896 1897 1898 #if defined(BCM_TOMAHAWK_SUPPORT) 1899 if (SOC_IS_TOMAHAWKX(unit)) { 1900 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_default(unit)); 1901 SOC_IF_ERROR_RETURN(_bcm_th_pfc_deadlock_init(unit)); 1902 pfc_support = TRUE; 1903 } else 1904 #endif 1905 #if defined(BCM_HELIX5_SUPPORT) 1906 if (SOC_IS_HELIX5(unit)) { 1907 SOC_IF_ERROR_RETURN(_bcm_hx5_pfc_deadlock_init(unit)); 1908 pfc_support = TRUE; 1909 } else 1910 #endif 1911 #if defined(BCM_TRIDENT3_SUPPORT) 1912 if (SOC_IS_TRIDENT3X(unit) && !SOC_IS_HELIX5(unit)) { 1913 SOC_IF_ERROR_RETURN(_bcm_td3_pfc_deadlock_init(unit)); 1914 pfc_support = TRUE; 1915 } 1916 #endif 1917 if (pfc_support == FALSE) { 1918 return BCM_E_INIT; 1919 } 1920 if (!SOC_WARM_BOOT(unit)) { 1921 /* Default Detection timer Unit of Time is 100ms */ 1922 BCM_IF_ERROR_RETURN( 1923 _bcm_pfc_deadlock_control_set(unit, 1924 bcmSwitchPFCDeadlockDetectionTimeInterval, 1925 bcmSwitchPFCDeadlockDetectionInterval100MiliSecond)); 1926 } 1927 return BCM_E_NONE; 1928 } 1929 1930