openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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