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 (42389B)


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