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 (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 */