pfc_deadlock.c (42389B)
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 15 #include <soc/drv.h> 16 #include <soc/mem.h> 17 #include <soc/debug.h> 18 #include <soc/trident3.h> 19 20 #include <bcm/debug.h> 21 #include <bcm/error.h> 22 #include <bcm/cosq.h> 23 #include <bcm_int/esw/mbcm.h> 24 #include <bcm_int/esw/stack.h> 25 #include <bcm_int/esw/cosq.h> 26 #include <bcm_int/esw/pfc_deadlock.h> 27 #include <bcm_int/esw/virtual.h> 28 #include <bcm_int/esw/trident3.h> 29 30 #if defined(BCM_TRIDENT3_SUPPORT) 31 32 #define BCM_TD3_PFC_DEADLOCK_CHIP_CONFIG_0_MAX_COS 4 33 34 _bcm_td3_pfc_deadlock_control_t *_bcm_td3_pfc_deadlock_control[BCM_MAX_NUM_UNITS]; 35 36 STATIC sal_mutex_t _bcm_td3_pfc_lock[SOC_MAX_NUM_DEVICES] = {NULL}; 37 #define PFC_LOCK(unit) sal_mutex_take(_bcm_td3_pfc_lock[unit], sal_mutex_FOREVER) 38 #define PFC_UNLOCK(unit) sal_mutex_give(_bcm_td3_pfc_lock[unit]) 39 40 int 41 _bcm_td3_pfc_deadlock_ignore_pfc_xoff_clear(int unit, int cos, bcm_port_t port) 42 { 43 int priority = 0; 44 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 45 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 46 uint32 rval; 47 48 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 49 hw_res = &pfc_deadlock_control->hw_regs_fields; 50 51 if (port >= MAX_PORT(unit)) { 52 return BCM_E_PARAM; /* Process for valid ports */ 53 } 54 55 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 56 /* For that port, set ignore_pfc_xoff = 0 (per port reg) */ 57 rval = 0; 58 SOC_IF_ERROR_RETURN( 59 soc_reg32_get(unit, hw_res->port_config, port, 0, &rval)); 60 rval &= ~(1 << priority); 61 SOC_IF_ERROR_RETURN( 62 soc_reg32_set(unit, hw_res->port_config, port, 0, rval)); 63 64 return BCM_E_NONE; 65 } 66 67 int 68 _bcm_td3_pfc_deadlock_hw_cos_index_get(int unit, 69 bcm_cos_t priority, int *hw_cos_index) 70 { 71 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 72 73 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 74 75 if (pfc_deadlock_control->hw_cos_idx_inuse[priority] == TRUE) { 76 *hw_cos_index = priority; 77 return BCM_E_NONE; 78 } 79 return BCM_E_NOT_FOUND; 80 } 81 82 int 83 _bcm_td3_pfc_deadlock_hw_cos_index_set(int unit, 84 bcm_cos_t priority, int *hw_cos_index) 85 { 86 int rv = BCM_E_NONE; 87 int temp_hw_index = -1; 88 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 89 _bcm_pfc_deadlock_config_t *pfc_deadlock_config = NULL; 90 91 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 92 93 rv = _bcm_td3_pfc_deadlock_hw_cos_index_get(unit, priority, &temp_hw_index); 94 if (rv != BCM_E_NONE) { 95 if (rv != BCM_E_NOT_FOUND) { 96 return rv; 97 } 98 } 99 100 if (temp_hw_index != -1) { 101 /* Config for this priority exists already. Donot reprogram */ 102 *hw_cos_index = temp_hw_index; 103 return BCM_E_NONE; 104 } 105 106 /* New priority */ 107 pfc_deadlock_control->hw_cos_idx_inuse[priority] = TRUE; 108 pfc_deadlock_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 109 pfc_deadlock_config->priority = priority; 110 pfc_deadlock_config->flags |= _BCM_PFC_DEADLOCK_F_ENABLE; 111 pfc_deadlock_control->pfc_deadlock_cos_used++; 112 *hw_cos_index = priority; 113 return BCM_E_NONE; 114 } 115 116 /* Routine to Reset the recovery state of a port and config the port back in 117 * original state 118 */ 119 int 120 _bcm_td3_pfc_deadlock_recovery_end(int unit, int cos, bcm_port_t port) 121 { 122 int pipe, split, pos, priority = 0; 123 uint64 rval64, temp_mask64, temp_en64; 124 uint32 rval, uc_cos_bmp; 125 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 126 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 127 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 128 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 129 130 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 131 hw_res = &pfc_deadlock_control->hw_regs_fields; 132 133 if (port >= MAX_PORT(unit)) { 134 return BCM_E_PARAM; /* Process for valid ports */ 135 } 136 137 SOC_IF_ERROR_RETURN( 138 soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos)); 139 140 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 141 pfc_deadlock_pri_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 142 143 COMPILER_64_ZERO(temp_en64); 144 COMPILER_64_ZERO(temp_mask64); 145 146 if (pos < 32) { 147 COMPILER_64_SET(temp_mask64, 0, (1 << pos)); 148 } else { 149 COMPILER_64_SET(temp_mask64, (1 << (pos - 32)), 0); 150 } 151 152 COMPILER_64_OR(temp_en64, temp_mask64); 153 154 LOG_INFO(BSL_LS_BCM_COSQ, 155 (BSL_META_U(unit, 156 "PFC Deadlock Recovery ends: Prio %d port=%d\n"), 157 priority, port)); 158 159 /* For that port, set ignore_pfc_xoff = 0 (per port reg) */ 160 rval = 0; 161 SOC_IF_ERROR_RETURN( 162 soc_reg32_get(unit, hw_res->port_config, port, 0, &rval)); 163 164 rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, port, 165 &uc_cos_bmp); 166 167 if(rval != BCM_E_NONE) { 168 rval = 0; 169 rval &= ~(1 << priority); 170 } else { 171 rval = 0; 172 rval &= ~uc_cos_bmp; 173 } 174 175 SOC_IF_ERROR_RETURN( 176 soc_reg32_set(unit, hw_res->port_config, port, 0, rval)); 177 178 /* Mask the Intr DD_TIMER_MASK by setting 0 (pbmp) */ 179 COMPILER_64_ZERO(rval64); 180 SOC_IF_ERROR_RETURN( 181 soc_trident3_xpe_reg_get(unit, hw_res->timer_mask[split], -1, pipe, 182 cos, &rval64)); 183 COMPILER_64_NOT(temp_mask64); 184 COMPILER_64_AND(rval64, temp_mask64); 185 SOC_IF_ERROR_RETURN( 186 soc_trident3_xpe_reg_set(unit, hw_res->timer_mask[split], -1, pipe, 187 cos, rval64)); 188 189 /* Turn timer off DD_TIMER_ENABLE by setting 1 (pbmp) */ 190 COMPILER_64_ZERO(rval64); 191 SOC_IF_ERROR_RETURN( 192 soc_trident3_xpe_reg_get(unit, hw_res->timer_en[split], -1, pipe, 193 cos, &rval64)); 194 COMPILER_64_OR(rval64, temp_en64); 195 SOC_IF_ERROR_RETURN( 196 soc_trident3_xpe_reg_set(unit, hw_res->timer_en[split], -1, pipe, 197 cos, rval64)); 198 199 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 200 if(pfc_deadlock_cb->pfc_deadlock_cb) { 201 pfc_deadlock_cb->pfc_deadlock_cb(unit, port, priority, 202 bcmCosqPfcDeadlockRecoveryEventEnd, 203 pfc_deadlock_cb->pfc_deadlock_userdata); 204 } 205 206 SOC_PBMP_PORT_REMOVE(pfc_deadlock_pri_config->deadlock_ports, port); 207 208 return BCM_E_NONE; 209 } 210 211 /* Routine to begin recovery when a Port is deaclared to be in Deadlock by 212 * Hardware. 213 */ 214 STATIC int 215 _bcm_td3_pfc_deadlock_recovery_begin(int unit, int cos, bcm_port_t port) 216 { 217 uint32 rval,uc_cos_bmp = 0, user_rval = 0; 218 int pipe, split, pos, priority = 0; 219 uint64 rval64, temp_mask64, temp_en64; 220 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 221 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 222 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 223 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 224 225 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 226 hw_res = &pfc_deadlock_control->hw_regs_fields; 227 SOC_IF_ERROR_RETURN( 228 soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos)); 229 230 COMPILER_64_ZERO(temp_en64); 231 COMPILER_64_ZERO(temp_mask64); 232 233 if (pos < 32) { 234 COMPILER_64_SET(temp_mask64, 0, (1 << pos)); 235 } else { 236 COMPILER_64_SET(temp_mask64, (1 << (pos - 32)), 0); 237 } 238 239 COMPILER_64_OR(temp_en64, temp_mask64); 240 241 LOG_INFO(BSL_LS_BCM_COSQ, 242 (BSL_META_U(unit, 243 "PFC Deadlock Detected: Cos %d port=%d\n"), cos, port)); 244 245 /* Mask the Intr DD_TIMER_MASK by setting 1 (pbmp) */ 246 COMPILER_64_ZERO(rval64); 247 SOC_IF_ERROR_RETURN( 248 soc_trident3_xpe_reg_get(unit, hw_res->timer_mask[split], -1, pipe, 249 cos, &rval64)); 250 COMPILER_64_OR(rval64, temp_mask64); 251 SOC_IF_ERROR_RETURN( 252 soc_trident3_xpe_reg_set(unit, hw_res->timer_mask[split], -1, pipe, 253 cos, rval64)); 254 255 /* Turn timer off DD_TIMER_ENABLE by setting 0 (pbmp) */ 256 COMPILER_64_ZERO(rval64); 257 SOC_IF_ERROR_RETURN( 258 soc_trident3_xpe_reg_get(unit, hw_res->timer_en[split], -1, pipe, 259 cos, &rval64)); 260 COMPILER_64_NOT(temp_en64); 261 COMPILER_64_AND(rval64, temp_en64); 262 SOC_IF_ERROR_RETURN( 263 soc_trident3_xpe_reg_set(unit, hw_res->timer_en[split], -1, pipe, 264 cos, rval64)); 265 266 SOC_IF_ERROR_RETURN( 267 soc_reg32_get(unit, hw_res->port_config, port, 0, &rval)); 268 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 269 270 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 271 if (soc_property_get(unit, spn_PFC_DEADLOCK_SEQ_CONTROL, 0) && 272 pfc_deadlock_cb->pfc_deadlock_cb) { 273 user_rval = pfc_deadlock_cb->pfc_deadlock_cb(unit, port, 274 priority, bcmCosqPfcDeadlockRecoveryEventBegin, 275 pfc_deadlock_cb->pfc_deadlock_userdata); 276 if (user_rval) { 277 rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen( 278 unit, priority, port, &uc_cos_bmp); 279 if (rval != BCM_E_NONE) { 280 rval = 0; 281 rval |= (1 << priority); 282 } else { 283 rval = 0; 284 rval |= uc_cos_bmp; 285 } 286 287 SOC_IF_ERROR_RETURN( 288 soc_reg32_set(unit, hw_res->port_config, port, 0, rval)); 289 } 290 return BCM_E_NONE; 291 } 292 293 rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, port, 294 &uc_cos_bmp); 295 296 if(rval != BCM_E_NONE) { 297 rval = 0; 298 rval |= (1 << priority); 299 } else { 300 rval = 0; 301 rval |= uc_cos_bmp; 302 } 303 304 SOC_IF_ERROR_RETURN( 305 soc_reg32_set(unit, hw_res->port_config, port, 0, rval)); 306 307 if(pfc_deadlock_cb->pfc_deadlock_cb) { 308 pfc_deadlock_cb->pfc_deadlock_cb(unit, port, 309 priority, bcmCosqPfcDeadlockRecoveryEventBegin, 310 pfc_deadlock_cb->pfc_deadlock_userdata); 311 } 312 313 pfc_deadlock_pri_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 314 315 /* Recovery count calculated from Configured Recovery timer. 316 * Note: recovery_timer is in msecs and cb_interval is in usecs. 317 */ 318 pfc_deadlock_pri_config->port_recovery_count[port] = 1 + 319 ((pfc_deadlock_pri_config->recovery_timer * 1000) / 320 _BCM_TD3_PFC_DEADLOCK_CB_INTERVAL(0)); 321 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->deadlock_ports, port); 322 323 return BCM_E_NONE; 324 } 325 326 /* Routine to update the recovery status of ports which are in Recovery state 327 */ 328 int 329 _bcm_td3_pfc_deadlock_recovery_update(int unit, int cos) 330 { 331 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 332 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 333 bcm_port_t port; 334 int priority = 0; 335 336 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 337 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 338 pfc_deadlock_pri_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 339 340 BCM_PBMP_ITER(pfc_deadlock_pri_config->deadlock_ports, port) { 341 if (port >= MAX_PORT(unit)) { 342 break; /* Process for valid ports */ 343 } 344 /* 345 * COVERITY 346 * 347 * Max Port num will be updated dynamically per device. 348 */ 349 /* coverity[overrun-local : FALSE] */ 350 if (pfc_deadlock_pri_config->port_recovery_count[port]) { 351 pfc_deadlock_pri_config->port_recovery_count[port]--; 352 } else { 353 BCM_IF_ERROR_RETURN( 354 _bcm_td3_pfc_deadlock_recovery_end(unit, cos, port)); 355 } 356 } 357 return BCM_E_NONE; 358 } 359 360 /* 361 * Function: 362 * _bcm_td3_pfc_deadlock_monitor 363 * Purpose: 364 * 1) Monitor the hardware for Deadlock status 365 * 2) Start Recovery process for the Deadlocked port/queue 366 * 3) Reset Port back to original state on expiry of recovery phase 367 * Parameters: 368 * unit - (IN) unit number 369 * Returns: 370 * BCM_E_XXX 371 * Notes: 372 * Step 1 - Monitor (Deadlock Detection phase): 373 * Sw polls for Deadlock detection intr set for port 374 * Q_SCHED_DD_TIMER_STATUS_SPLIT0|1 (pbmp) 375 * 376 * Step 2: Recovery Begin phase 377 * 2.a: Mask the Intr Q_SCHED_DD_TIMER_STATUS_MASK_SPLIT0|1 by setting 1 (pbmp) 378 * 2.b: Turn timer off Q_SCHED_DD_TIMER_ENABLE_SPLITE0|1 by setting 0 (pbmp) 379 * 2.c: For that port, set ignore_pfc_xoff = 1 (per port reg) 380 * 2.4: Start recovery timer 381 * Step 3: Recovery End phase (On expiry of recovery timer) 382 * 3.a: Reset ignore_xoff; set ignore_pfc_xoff = 0 383 * 3.b: UnMask the Intr Q_SCHED_DD_TIMER_STATUS_MASK_SPLIT0|1 by setting 0 (pbmp) 384 * 3.c: Turn timer off Q_SCHED_DD_TIMER_ENABLE_SPLITE0|1 by setting 1 (pbmp) 385 */ 386 int 387 _bcm_td3_pfc_deadlock_monitor(int unit) 388 { 389 int rv = 0; 390 int cos = 0, priority = 0, user_control = 0; 391 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 392 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 393 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 394 _bcm_pfc_deadlock_cb_t *pfc_deadlock_cb = NULL; 395 uint64 status64, mask64; 396 int pipe, split, pos; 397 bcm_port_t port; 398 399 COMPILER_64_ZERO(status64); 400 COMPILER_64_ZERO(mask64); 401 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 402 hw_res = &pfc_deadlock_control->hw_regs_fields; 403 404 pfc_deadlock_cb = _BCM_UNIT_PFC_DEADLOCK_CB(unit); 405 if (soc_property_get(unit, spn_PFC_DEADLOCK_SEQ_CONTROL, 0) && 406 pfc_deadlock_cb->pfc_deadlock_cb) { 407 user_control = 1; 408 } 409 410 PFC_LOCK(unit); 411 for (cos = 0; cos < pfc_deadlock_control->pfc_deadlock_cos_max; cos++) { 412 /* Check if index is in Use */ 413 if (pfc_deadlock_control->hw_cos_idx_inuse[cos] == TRUE) { 414 /* Check Hardware if New ports have been declared to be in 415 * Deadlock condition 416 */ 417 PBMP_ALL_ITER(unit, port) { 418 /* PFC deadlock feature not supported on CPU and Loopback ports */ 419 if ((IS_CPU_PORT(unit, port)) || (IS_LB_PORT(unit, port))) { 420 continue; 421 } 422 rv = soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos); 423 if (BCM_FAILURE(rv)) { 424 PFC_UNLOCK(unit); 425 return rv; 426 } 427 rv = soc_trident3_xpe_reg_get(unit, hw_res->timer_status[split], -1, 428 pipe, cos, &status64); 429 if (BCM_FAILURE(rv)) { 430 PFC_UNLOCK(unit); 431 return rv; 432 } 433 rv = soc_trident3_xpe_reg_get(unit, hw_res->timer_mask[split], -1, 434 pipe, cos, &mask64); 435 if (BCM_FAILURE(rv)) { 436 PFC_UNLOCK(unit); 437 return rv; 438 } 439 /* Mask - bit 0 indicates enabled for reporting */ 440 COMPILER_64_NOT(mask64); 441 COMPILER_64_AND(status64, mask64); 442 443 if (COMPILER_64_IS_ZERO(status64) == 0) { 444 /* New ports declared to be in Deadlock status */ 445 if (pos < 32) { 446 if ((COMPILER_64_LO(status64) & 447 (1 << pos)) == FALSE) { 448 continue; 449 } 450 } else { 451 if ((COMPILER_64_HI(status64) & 452 (1 << (pos - 32))) == FALSE) { 453 continue; 454 } 455 } 456 rv = _bcm_td3_pfc_deadlock_recovery_begin(unit, cos, port); 457 if (BCM_FAILURE(rv)) { 458 PFC_UNLOCK(unit); 459 return rv; 460 } 461 } 462 } 463 464 if (!user_control) { 465 /* Update the count for ports already in Deadlock state and Reset 466 * those ports where recovery timer has expired. 467 */ 468 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 469 pfc_deadlock_pri_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 470 /* Updates required for Enabled COS */ 471 if (SOC_PBMP_NOT_NULL(pfc_deadlock_pri_config->deadlock_ports)) { 472 rv = _bcm_td3_pfc_deadlock_recovery_update(unit, cos); 473 if (BCM_FAILURE(rv)) { 474 PFC_UNLOCK(unit); 475 return rv; 476 } 477 } 478 } 479 } 480 } 481 482 PFC_UNLOCK(unit); 483 return BCM_E_NONE; 484 } 485 486 /* TD3 Q_SCHED_DD_CHIP_CONFIG CONTENTS 487 * Q_SCHED_DD_CHIP_CONFIG0:DD_TIMER_INIT_VALUE_COS_0~DD_TIMER_INIT_VALUE_COS_4 488 * Q_SCHED_DD_CHIP_CONFIG1:DD_TIMER_INIT_VALUE_COS_5~DD_TIMER_INIT_VALUE_COS_9 489 * Q_SCHED_DD_CHIP_CONFIG2: ignore_pfc_off_pkt_discard 490 */ 491 int 492 _bcm_td3_pfc_deadlock_chip_config_get(int unit, 493 bcm_cos_t priority, 494 soc_reg_t* chip_config) 495 { 496 if (priority <= BCM_TD3_PFC_DEADLOCK_CHIP_CONFIG_0_MAX_COS) { 497 *chip_config = Q_SCHED_DD_CHIP_CONFIG0r; 498 } else { 499 *chip_config = Q_SCHED_DD_CHIP_CONFIG1r; 500 } 501 return BCM_E_NONE; 502 } 503 504 /* Routine to perform the Set/Get operation for the Priority */ 505 int 506 _bcm_td3_pfc_deadlock_hw_oper(int unit, 507 _bcm_pfc_deadlock_oper_t operation, 508 bcm_cos_t priority, 509 _bcm_pfc_deadlock_config_t *config) 510 { 511 int rv = 0; 512 int hw_cos_index = -1; 513 uint32 rval = 0; 514 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 515 uint32 detection_granularity = 0; 516 soc_reg_t chip_config; 517 soc_field_t cos_init_timer_field; 518 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 519 520 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 521 hw_res = &pfc_deadlock_control->hw_regs_fields; 522 detection_granularity = (_BCM_TD3_PFC_DEADLOCK_TIME_UNIT(unit) == 523 bcmSwitchPFCDeadlockDetectionInterval10MiliSecond) ? 10 : 100; 524 525 BCM_IF_ERROR_RETURN( 526 _bcm_td3_pfc_deadlock_chip_config_get(unit, priority, &chip_config)); 527 528 rval = 0; 529 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, 530 REG_PORT_ANY, 0, &rval)); 531 532 PFC_LOCK(unit); 533 if (operation == _bcmPfcDeadlockOperGet) { 534 535 config->detection_timer = soc_reg_field_get(unit, 536 chip_config, rval, 537 hw_res->time_init_val[priority]); 538 config->detection_timer *= detection_granularity; 539 } else { /* _bcmPfcDeadlockOperSet */ 540 rv = _bcm_td3_pfc_deadlock_hw_cos_index_set(unit, priority, &hw_cos_index); 541 if (BCM_FAILURE(rv)) { 542 PFC_UNLOCK(unit); 543 return rv; 544 } 545 if (hw_cos_index == -1) { 546 /* No matching or free hw_index available for use */ 547 PFC_UNLOCK(unit); 548 return BCM_E_RESOURCE; 549 } 550 551 cos_init_timer_field = hw_res->time_init_val[hw_cos_index]; 552 soc_reg_field_set(unit, chip_config, &rval, 553 cos_init_timer_field, 554 (config->detection_timer / detection_granularity)); 555 rv = soc_reg32_set(unit, chip_config, REG_PORT_ANY, 0, rval); 556 if (BCM_FAILURE(rv)) { 557 PFC_UNLOCK(unit); 558 return rv; 559 } 560 561 config->priority = priority; 562 pfc_deadlock_control->pfc_cos2pri[hw_cos_index] = priority; 563 pfc_deadlock_control->pfc_pri2cos[priority] = hw_cos_index; 564 } 565 566 PFC_UNLOCK(unit); 567 return BCM_E_NONE; 568 } 569 570 int 571 _bcm_td3_pfc_deadlock_q_config_helper(int unit, 572 _bcm_pfc_deadlock_oper_t operation, 573 bcm_gport_t gport, 574 bcm_cosq_pfc_deadlock_queue_config_t *config, 575 uint8 *enable_status) 576 { 577 int rv = BCM_E_NONE; 578 uint32 temp_val_lo = 0, temp_val_hi = 0; 579 uint64 rval64; 580 bcm_port_t local_port; 581 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 582 int pipe, split, pos; 583 int priority, hw_cos_index = -1; 584 585 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 586 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 587 588 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 589 590 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 591 /* Invalid Gport */ 592 return BCM_E_PARAM; 593 } 594 hw_res = &pfc_deadlock_control->hw_regs_fields; 595 if (pfc_deadlock_control->cosq_inv_mapping_get) { 596 rv = pfc_deadlock_control->cosq_inv_mapping_get(unit, gport, -1, 597 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 598 &local_port, &priority); 599 } else { 600 /* Mapping function not defined */ 601 return BCM_E_INIT; 602 } 603 if (rv != BCM_E_NONE) { 604 if (rv == BCM_E_NOT_FOUND) { 605 /* Given GPort/Queue has No Input priority mapping */ 606 return BCM_E_RESOURCE; 607 } 608 return rv; 609 } 610 611 PFC_LOCK(unit); 612 pfc_deadlock_pri_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 613 614 rv = _bcm_td3_pfc_deadlock_hw_cos_index_get(unit, priority, &hw_cos_index); 615 if (BCM_FAILURE(rv)) { 616 PFC_UNLOCK(unit); 617 return rv; 618 } 619 if (hw_cos_index == -1) { 620 /* No matching or free hw_index available for use */ 621 PFC_UNLOCK(unit); 622 return BCM_E_RESOURCE; 623 } 624 625 rv = soc_td3_mmu_bmp_reg_pos_get(unit, local_port, &pipe, &split, &pos); 626 if (BCM_FAILURE(rv)) { 627 PFC_UNLOCK(unit); 628 return rv; 629 } 630 631 COMPILER_64_ZERO(rval64); 632 rv = soc_trident3_xpe_reg_get(unit, hw_res->timer_en[split], -1, pipe, 633 hw_cos_index, &rval64); 634 if (BCM_FAILURE(rv)) { 635 PFC_UNLOCK(unit); 636 return rv; 637 } 638 639 if (operation == _bcmPfcDeadlockOperGet) { /* GET */ 640 if (enable_status) { 641 *enable_status = 642 BCM_PBMP_MEMBER(pfc_deadlock_pri_config->deadlock_ports, 643 local_port); 644 } 645 if (config) { 646 if (pos < 32) { 647 config->enable = 648 (COMPILER_64_LO(rval64) & (1 << pos)) ? TRUE : FALSE; 649 } else { 650 config->enable = 651 (COMPILER_64_HI(rval64) & (1 << (pos - 32))) ? 652 TRUE : FALSE; 653 } 654 } 655 656 PFC_UNLOCK(unit); 657 return BCM_E_NONE; 658 } else { /* _bcmPfcDeadlockOperSet */ 659 temp_val_lo = COMPILER_64_LO(rval64); 660 temp_val_hi = COMPILER_64_HI(rval64); 661 662 if (config->enable) { 663 if (pos < 32) { 664 temp_val_lo |= (1 << pos); 665 } else { 666 temp_val_hi |= (1 << (pos - 32)); 667 } 668 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, 669 local_port); 670 } else { 671 if (pos < 32) { 672 temp_val_lo &= ~(1 << pos); 673 } else { 674 temp_val_hi &= ~(1 << (pos - 32)); 675 } 676 677 SOC_PBMP_PORT_REMOVE(pfc_deadlock_pri_config->enabled_ports, 678 local_port); 679 } 680 681 COMPILER_64_SET(rval64, temp_val_hi, temp_val_lo); 682 rv = soc_trident3_xpe_reg_set(unit, hw_res->timer_en[split], -1, pipe, 683 hw_cos_index, rval64); 684 if (BCM_FAILURE(rv)) { 685 PFC_UNLOCK(unit); 686 return rv; 687 } 688 689 if (!config->enable && 690 SOC_PBMP_MEMBER(pfc_deadlock_pri_config->deadlock_ports, local_port)) { 691 rv = _bcm_td3_pfc_deadlock_recovery_end(unit, hw_cos_index, local_port); 692 if (BCM_FAILURE(rv)) { 693 PFC_UNLOCK(unit); 694 return rv; 695 } 696 } 697 if (SOC_PBMP_IS_NULL(pfc_deadlock_pri_config->enabled_ports)) { 698 /*First for that port, set ignore_pfc_xoff = 0 (per port reg) */ 699 rv = _bcm_td3_pfc_deadlock_ignore_pfc_xoff_clear( 700 unit, hw_cos_index, local_port); 701 if (BCM_FAILURE(rv)) { 702 PFC_UNLOCK(unit); 703 return rv; 704 } 705 pfc_deadlock_control->hw_cos_idx_inuse[hw_cos_index] = FALSE; 706 pfc_deadlock_pri_config->flags &= ~_BCM_PFC_DEADLOCK_F_ENABLE; 707 pfc_deadlock_control->pfc_cos2pri[hw_cos_index] = -1; 708 pfc_deadlock_control->pfc_pri2cos[priority] = -1; 709 } 710 } 711 712 PFC_UNLOCK(unit); 713 BCM_IF_ERROR_RETURN(_bcm_td3_pfc_deadlock_update_cos_used(unit)); 714 return BCM_E_NONE; 715 } 716 717 /* 718 * Function: 719 * _bcm_pfc_deadlock_recovery_reset 720 * Purpose: 721 * Recover the system back to default state. 722 * Restore all ports from Deadlock/Recovery state, if Warm boot when 723 * recovery was in progress 724 * Parameters: 725 * unit - unit number 726 * Returns: 727 * BCM_E_XXX 728 */ 729 int 730 _bcm_td3_pfc_deadlock_recovery_reset(int unit) 731 { 732 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 733 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 734 int priority = 0, i; 735 bcm_port_t port; 736 737 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 738 739 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 740 priority = pfc_deadlock_control->pfc_cos2pri[i]; 741 /* Skipping invalid priorities */ 742 if ((priority < 0) || (priority >= _TD3_MMU_NUM_INT_PRI)) { 743 continue; 744 } 745 pfc_deadlock_pri_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 746 747 /* 748 * COVERITY: Max Port will take care of Port beyond supported 749 * range 750 */ 751 /* coverity[overrun-local : FALSE] */ 752 BCM_PBMP_ITER(pfc_deadlock_pri_config->deadlock_ports, port) { 753 if (port >= MAX_PORT(unit)) { 754 break; /* Process for valid ports */ 755 } 756 /* 757 * COVERITY: Max Port num will be updated dynamically per device. 758 */ 759 /* coverity[overrun-local : FALSE] */ 760 pfc_deadlock_pri_config->port_recovery_count[port] = 0; 761 BCM_IF_ERROR_RETURN( 762 _bcm_td3_pfc_deadlock_recovery_end(unit, i, port)); 763 } 764 } 765 pfc_deadlock_control->cb_enabled = FALSE; 766 BCM_IF_ERROR_RETURN(_bcm_td3_pfc_deadlock_update_cos_used(unit)); 767 pfc_deadlock_control->cosq_inv_mapping_get = NULL; 768 769 return BCM_E_NONE; 770 } 771 772 /* 773 * Function: 774 * _bcm_pfc_deadlock_control_set 775 * Description: 776 * Set PFC Deadlock feature's switch config. 777 * Parameters: 778 * unit - Device unit number 779 * type - The desired configuration parameter to set. 780 * arg - Pointer to set value 781 * Returns: 782 * BCM_E_xxx 783 * Notes: 784 * bcmSwitchPFCDeadlockCosMax - Set operation is not permitted 785 */ 786 int 787 _bcm_td3_pfc_deadlock_control_set(int unit, bcm_switch_control_t type, int arg) 788 { 789 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 790 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 791 uint32 rval = 0, field_val = 0; 792 soc_reg_t chip_config; 793 794 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 795 if (pfc_deadlock_control == NULL) { 796 return BCM_E_UNAVAIL; 797 } 798 hw_res = &pfc_deadlock_control->hw_regs_fields; 799 800 switch (type) { 801 case bcmSwitchPFCDeadlockDetectionTimeInterval: 802 if ((arg < 0) || 803 (arg >= bcmSwitchPFCDeadlockDetectionIntervalCount)) { 804 return BCM_E_PARAM; 805 } 806 chip_config = hw_res->chip_config[1]; 807 808 rval = 0; 809 if (arg == bcmSwitchPFCDeadlockDetectionInterval10MiliSecond) { 810 field_val = 0; 811 } else { 812 field_val = 1; /* Default Unit - Order of 100ms */ 813 } 814 815 if (chip_config == INVALIDr) { 816 return BCM_E_UNAVAIL; 817 } 818 819 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, 820 REG_PORT_ANY, 0, &rval)); 821 soc_reg_field_set(unit, chip_config, &rval, 822 hw_res->time_unit_field, field_val); 823 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, chip_config, 824 REG_PORT_ANY, 0, rval)); 825 pfc_deadlock_control->time_unit = arg; 826 break; 827 case bcmSwitchPFCDeadlockRecoveryAction: 828 if ((arg < 0) || 829 (arg >= bcmSwitchPFCDeadlockActionMaxCount)) { 830 return BCM_E_PARAM; 831 } 832 833 chip_config = hw_res->chip_config[2]; 834 rval = 0; 835 if (arg == bcmSwitchPFCDeadlockActionDrop) { 836 field_val = 1; 837 } else { 838 field_val = 0; /* Default action - Transmit */ 839 } 840 841 if (chip_config == INVALIDr) { 842 return BCM_E_UNAVAIL; 843 } 844 845 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, 846 REG_PORT_ANY, 0, &rval)); 847 soc_reg_field_set(unit, chip_config, &rval, 848 hw_res->recovery_action_field, field_val); 849 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, chip_config, 850 REG_PORT_ANY, 0, rval)); 851 pfc_deadlock_control->recovery_action = arg; 852 break; 853 default: 854 return BCM_E_UNAVAIL; 855 } 856 return BCM_E_NONE; 857 } 858 859 /* 860 * Function: 861 * _bcm_pfc_deadlock_control_get 862 * Description: 863 * Get PFC Deadlock feature's switch config. 864 * Parameters: 865 * unit - Device unit number 866 * type - The desired configuration parameter to retrieve. 867 * arg - Pointer to retrieved value 868 * Returns: 869 * BCM_E_xxx 870 */ 871 int 872 _bcm_td3_pfc_deadlock_control_get(int unit, bcm_switch_control_t type, int *arg) 873 { 874 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 875 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 876 877 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 878 if (pfc_deadlock_control == NULL) { 879 return BCM_E_UNAVAIL; 880 } 881 hw_res = &pfc_deadlock_control->hw_regs_fields; 882 883 switch (type) { 884 case bcmSwitchPFCDeadlockDetectionTimeInterval: 885 if (hw_res->chip_config[1] == INVALIDr) { 886 return BCM_E_UNAVAIL; 887 } 888 *arg = pfc_deadlock_control->time_unit; 889 break; 890 case bcmSwitchPFCDeadlockRecoveryAction: 891 if (hw_res->chip_config[2] == INVALIDr) { 892 return BCM_E_UNAVAIL; 893 } 894 *arg = pfc_deadlock_control->recovery_action; 895 break; 896 default: 897 return BCM_E_UNAVAIL; 898 } 899 return BCM_E_NONE; 900 } 901 902 /* 903 * Function: 904 * _bcm_td3_pfc_deadlock_control_get_hw 905 * Description: 906 * Retrieve PFC Deadlock feature's switch config. 907 * Parameters: 908 * unit - Device unit number 909 * type - The desired configuration parameter to retrieve. 910 * arg - Pointer to retrieved value 911 * Returns: 912 * BCM_E_xxx 913 */ 914 int 915 _bcm_td3_pfc_deadlock_control_get_hw(int unit, bcm_switch_control_t type, int *arg) 916 { 917 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 918 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 919 uint32 rval = 0, field_val = 0; 920 soc_reg_t chip_config; 921 922 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 923 if (pfc_deadlock_control == NULL) { 924 return BCM_E_UNAVAIL; 925 } 926 hw_res = &pfc_deadlock_control->hw_regs_fields; 927 928 switch (type) { 929 case bcmSwitchPFCDeadlockDetectionTimeInterval: 930 chip_config = hw_res->chip_config[1]; 931 if (chip_config == INVALIDr) { 932 return BCM_E_UNAVAIL; 933 } 934 rval = 0; 935 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, REG_PORT_ANY, 0, 936 &rval)); 937 field_val = soc_reg_field_get(unit, chip_config, 938 rval, hw_res->time_unit_field); 939 if (field_val == 0) { 940 *arg = bcmSwitchPFCDeadlockDetectionInterval10MiliSecond; 941 } else { 942 *arg = bcmSwitchPFCDeadlockDetectionInterval100MiliSecond; 943 } 944 break; 945 case bcmSwitchPFCDeadlockRecoveryAction: 946 chip_config = hw_res->chip_config[2]; 947 if (chip_config == INVALIDr) { 948 return BCM_E_UNAVAIL; 949 } 950 rval = 0; 951 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, chip_config, 952 REG_PORT_ANY, 0, &rval)); 953 field_val = soc_reg_field_get(unit, chip_config, rval, 954 hw_res->recovery_action_field); 955 956 if (field_val == 1) { 957 *arg = bcmSwitchPFCDeadlockActionDrop; 958 } else { 959 *arg = bcmSwitchPFCDeadlockActionTransmit; 960 } 961 break; 962 default: 963 return BCM_E_UNAVAIL; 964 } 965 return BCM_E_NONE; 966 } 967 968 /* Set Chip level defautl values */ 969 STATIC int 970 _bcm_td3_pfc_deadlock_default(int unit) 971 { 972 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 973 int i = 0; 974 975 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 976 977 _BCM_TD3_PFC_DEADLOCK_HW_RES_INIT(&pfc_deadlock_control->hw_regs_fields); 978 pfc_deadlock_control->pfc_deadlock_cos_max = 0; 979 pfc_deadlock_control->pfc_deadlock_cos_used = 0; 980 981 for (i = 0; i < COUNTOF(pfc_deadlock_control->hw_cos_idx_inuse); i++) { 982 pfc_deadlock_control->hw_cos_idx_inuse[i] = FALSE; 983 } 984 for (i = 0; i < TD3_PFC_DEADLOCK_MAX_COS; i++) { 985 pfc_deadlock_control->pfc_cos2pri[i] = -1; 986 pfc_deadlock_control->pfc_pri2cos[i] = -1; 987 } 988 sal_memset(pfc_deadlock_control->pfc_cos2pri, -1, 989 (TD3_PFC_DEADLOCK_MAX_COS * sizeof(bcm_cos_t))); 990 sal_memset(pfc_deadlock_control->pfc_pri2cos, -1, 991 (TD3_PFC_DEADLOCK_MAX_COS * sizeof(bcm_cos_t))); 992 pfc_deadlock_control->cb_enabled = FALSE; 993 pfc_deadlock_control->time_unit = 0; /* 100 ms */ 994 pfc_deadlock_control->cb_interval = 100 * 1000; /* 100 ms */ 995 return BCM_E_NONE; 996 } 997 998 /* HW res init */ 999 int 1000 _bcm_td3_pfc_deadlock_hw_res_init(int unit) 1001 { 1002 int i = 0; 1003 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 1004 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1005 1006 static soc_reg_t timer_count[1] = { 1007 Q_SCHED_DD_TIMERr 1008 }; 1009 static soc_reg_t timer_en_regs[2] = { 1010 Q_SCHED_DD_TIMER_ENABLE_SPLIT0r, Q_SCHED_DD_TIMER_ENABLE_SPLIT1r 1011 }; 1012 static soc_reg_t timer_status_regs[2] = { 1013 Q_SCHED_DD_TIMER_STATUS_SPLIT0r, Q_SCHED_DD_TIMER_STATUS_SPLIT1r 1014 }; 1015 static soc_reg_t timer_mask_regs[2] = { 1016 Q_SCHED_DD_TIMER_STATUS_MASK_SPLIT0r, Q_SCHED_DD_TIMER_STATUS_MASK_SPLIT1r 1017 }; 1018 static soc_reg_t config_regs[3] = { 1019 Q_SCHED_DD_CHIP_CONFIG0r, Q_SCHED_DD_CHIP_CONFIG1r, Q_SCHED_DD_CHIP_CONFIG2r 1020 }; 1021 1022 static soc_field_t deadlock_time_field[10] = { 1023 DD_TIMER_INIT_VALUE_COS_0f, DD_TIMER_INIT_VALUE_COS_1f, 1024 DD_TIMER_INIT_VALUE_COS_2f, DD_TIMER_INIT_VALUE_COS_3f, 1025 DD_TIMER_INIT_VALUE_COS_4f, DD_TIMER_INIT_VALUE_COS_5f, 1026 DD_TIMER_INIT_VALUE_COS_6f, DD_TIMER_INIT_VALUE_COS_7f, 1027 DD_TIMER_INIT_VALUE_COS_8f, DD_TIMER_INIT_VALUE_COS_9f 1028 }; 1029 1030 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 1031 hw_res = &pfc_deadlock_control->hw_regs_fields; 1032 1033 hw_res->timer_count[0] = timer_count[0]; 1034 hw_res->timer_status[0] = timer_status_regs[0]; 1035 hw_res->timer_status[1] = timer_status_regs[1]; 1036 hw_res->timer_mask[0] = timer_mask_regs[0]; 1037 hw_res->timer_mask[1] = timer_mask_regs[1]; 1038 hw_res->timer_en[0] = timer_en_regs[0]; 1039 hw_res->timer_en[1] = timer_en_regs[1]; 1040 1041 for (i = 0; i < TD3_PFC_DEADLOCK_MAX_COS; i++) { 1042 hw_res->time_init_val[i] = deadlock_time_field[i]; 1043 } 1044 hw_res->port_config = Q_SCHED_DD_PORT_CONFIGr; 1045 hw_res->chip_config[0] = config_regs[0]; 1046 hw_res->chip_config[1] = config_regs[1]; 1047 hw_res->chip_config[2] = config_regs[2]; 1048 /* Q_SCHED_DD_CHIP_CONFIG1 */ 1049 hw_res->time_unit_field = DD_TIMER_TICK_UNITf; 1050 /* Q_SCHED_DD_CHIP_CONFIG2 */ 1051 hw_res->recovery_action_field = IGNORE_PFC_OFF_PKT_DISCARDf; 1052 /* Q_SCHED_DD_TIMER_STATUS_SPLIT0/1 */ 1053 hw_res->deadlock_status_field = DEADLOCK_DETECTEDf; 1054 return BCM_E_NONE; 1055 } 1056 1057 /* Chip specific init and assign default values */ 1058 int 1059 _bcm_td3_pfc_deadlock_init(int unit) 1060 { 1061 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1062 1063 BCM_IF_ERROR_RETURN(_bcm_td3_pfc_deadlock_default(unit)); 1064 BCM_IF_ERROR_RETURN(_bcm_td3_pfc_deadlock_hw_res_init(unit)); 1065 1066 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 1067 pfc_deadlock_control->pfc_deadlock_cos_max = TD3_PFC_DEADLOCK_MAX_COS; 1068 pfc_deadlock_control->cosq_inv_mapping_get = _bcm_td3_cosq_inv_mapping_get; 1069 1070 _bcm_td3_pfc_lock[unit] = sal_mutex_create("pfc lock"); 1071 if (_bcm_td3_pfc_lock[unit] == NULL) { 1072 return BCM_E_MEMORY; 1073 } 1074 1075 return BCM_E_NONE; 1076 } 1077 1078 /* 1079 * Function: 1080 * _bcm_pfc_deadlock_deinit 1081 * Purpose: 1082 * De-Initialize allocated memory for PFC Deadlock feature 1083 * Parameters: 1084 * unit - unit number 1085 * Returns: 1086 * BCM_E_XXX 1087 */ 1088 int 1089 _bcm_td3_pfc_deadlock_deinit(int unit) 1090 { 1091 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1092 1093 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 1094 1095 if (pfc_deadlock_control != NULL) { 1096 sal_free(pfc_deadlock_control); 1097 _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit) = NULL; 1098 } 1099 1100 if (_bcm_td3_pfc_lock[unit]) { 1101 sal_mutex_destroy(_bcm_td3_pfc_lock[unit]); 1102 _bcm_td3_pfc_lock[unit] = NULL; 1103 } 1104 1105 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_deinit(unit)); 1106 1107 return BCM_E_NONE; 1108 } 1109 1110 #ifdef BCM_WARM_BOOT_SUPPORT 1111 /* 1112 * Function: 1113 * _bcm_pfc_deadlock_reinit 1114 * Purpose: 1115 * Reinitialize all states/data-structures from HW(Level 1 warmboot) 1116 * Parameters: 1117 * unit - unit number 1118 * Returns: 1119 * BCM_E_XXX 1120 */ 1121 int 1122 _bcm_td3_pfc_deadlock_reinit(int unit) 1123 { 1124 _bcm_td3_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 1125 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 1126 _bcm_td3_pfc_hw_resorces_t *hw_res = NULL; 1127 int priority = 0, i, split, rv, temp_hw_index = -1, arg_value; 1128 int port, pipe, pos; 1129 uint64 en_rval64[2]; 1130 uint64 mask_rval64[2]; 1131 1132 pfc_deadlock_control = _BCM_TD3_UNIT_PFC_DEADLOCK_CONTROL(unit); 1133 hw_res = &pfc_deadlock_control->hw_regs_fields; 1134 1135 BCM_IF_ERROR_RETURN 1136 (_bcm_td3_pfc_deadlock_control_get_hw(unit, 1137 bcmSwitchPFCDeadlockDetectionTimeInterval, 1138 &arg_value)); 1139 pfc_deadlock_control->time_unit = arg_value; 1140 BCM_IF_ERROR_RETURN 1141 (_bcm_td3_pfc_deadlock_control_get_hw(unit, 1142 bcmSwitchPFCDeadlockRecoveryAction, 1143 &arg_value)); 1144 pfc_deadlock_control->recovery_action = arg_value; 1145 1146 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 1147 priority = pfc_deadlock_control->pfc_cos2pri[i]; 1148 /* Skipping invalid priorities */ 1149 if ((priority < 0) || (priority >= PFC_DEADLOCK_MAX_COS)) { 1150 continue; 1151 } 1152 pfc_deadlock_pri_config = _BCM_TD3_PFC_DEADLOCK_CONFIG(unit, priority); 1153 1154 /* coverity[overrun-call] */ 1155 rv = _bcm_td3_pfc_deadlock_hw_cos_index_get(unit, priority, 1156 &temp_hw_index); 1157 if (BCM_SUCCESS(rv)) { 1158 pfc_deadlock_pri_config->flags |= _BCM_PFC_DEADLOCK_F_ENABLE; 1159 pfc_deadlock_pri_config->priority = priority; 1160 /* coverity[overrun-call] */ 1161 BCM_IF_ERROR_RETURN( 1162 _bcm_td3_pfc_deadlock_hw_oper(unit, _bcmPfcDeadlockOperGet, 1163 priority, pfc_deadlock_pri_config)); 1164 1165 for (split = 0; split < 2; split++) { 1166 COMPILER_64_ZERO(en_rval64[split]); 1167 COMPILER_64_ZERO(mask_rval64[split]); 1168 1169 SOC_IF_ERROR_RETURN( 1170 soc_trident3_xpe_reg_get(unit, hw_res->timer_en[split], -1, 1171 0, i, &en_rval64[split])); 1172 SOC_IF_ERROR_RETURN( 1173 soc_trident3_xpe_reg_get(unit, hw_res->timer_mask[split], -1, 1174 0, i, &mask_rval64[split])); 1175 } 1176 1177 PBMP_ALL_ITER(unit, port) { 1178 SOC_IF_ERROR_RETURN( 1179 soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, 1180 &pos)); 1181 if (pos < 32) { 1182 if (COMPILER_64_LO(en_rval64[pipe]) & (1 << pos)) { 1183 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, port); 1184 } else if (COMPILER_64_LO(mask_rval64[pipe]) & (1 << pos)) { 1185 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, port); 1186 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->deadlock_ports, port); 1187 } 1188 } else { 1189 if (COMPILER_64_HI(en_rval64[pipe]) & (1 << (pos - 32))) { 1190 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, port); 1191 } else if (COMPILER_64_LO(mask_rval64[pipe]) & (1 << (pos - 32))) { 1192 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->enabled_ports, port); 1193 BCM_PBMP_PORT_ADD(pfc_deadlock_pri_config->deadlock_ports, port); 1194 } 1195 } 1196 } 1197 } 1198 } 1199 1200 return BCM_E_NONE; 1201 } 1202 #endif 1203 #endif /* BCM_TRIDENT3_SUPPORT */