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