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

l2x.c (9856B)


      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  * XGS TD2 Bulk Aging Management.
      8  */
      9 
     10 #include <sal/core/libc.h>
     11 #include <shared/bsl.h>
     12 #include <soc/drv.h>
     13 #include <soc/l2x.h>
     14 #include <soc/ptable.h>
     15 #include <soc/debug.h>
     16 #include <soc/util.h>
     17 #include <soc/mem.h>
     18 
     19 #ifdef BCM_XGS_SWITCH_SUPPORT
     20 #ifdef BCM_TRIDENT2_SUPPORT
     21 
     22 #define _SOC_IF_ERROR_UNLOCK_EXIT(rv) \
     23         if (!SOC_SUCCESS(rv)) { \
     24             soc_mem_unlock(unit, L2Xm); \
     25             sal_sem_give(soc->l2x_age_sync); \
     26             LOG_ERROR(BSL_LS_SOC_L2, \
     27                       (BSL_META_U(unit, \
     28                                   "rv: %d\n"), rv)); \
     29             goto thread_exit; \
     30         }
     31 
     32 static int _soc_td2_l2_bulk_age_iter[SOC_MAX_NUM_DEVICES] = {0};
     33 
     34 /*
     35  * Function:
     36  *  _soc_td2_l2_bulk_age
     37  * Purpose:
     38  *  l2 bulk age thread
     39  * Parameters:
     40  *  unit - unit number.
     41  * Returns:
     42  *  none
     43  */
     44 STATIC void
     45 _soc_td2_l2_bulk_age(void *unit_vp)
     46 {
     47     int unit = PTR_TO_INT(unit_vp);
     48     soc_control_t *soc = SOC_CONTROL(unit);
     49     sal_usecs_t interval, cfg_interval, stime, etime;
     50     l2x_entry_t match_data;
     51     l2x_entry_t match_mask;
     52     l2x_entry_t new_data;
     53     l2x_entry_t new_mask;
     54     uint32 rval;
     55     int i, rv, iter = 0;
     56 
     57     cfg_interval = soc_property_get(unit, spn_L2_SW_AGING_INTERVAL, 300);
     58 
     59     while ((interval = soc->l2x_age_interval) != 0) {
     60         if (!iter) {
     61             goto age_delay;
     62         }
     63 
     64         LOG_VERBOSE(BSL_LS_SOC_ARL,
     65                     (BSL_META_U(unit,
     66                                 "l2_bulk_age_thread: "
     67                                 "Process iters(total:%d, this run:%d\n"),
     68                      ++_soc_td2_l2_bulk_age_iter[unit], iter));
     69 
     70         stime = sal_time_usecs();
     71 
     72         if (!soc->l2x_age_enable) {
     73             goto age_delay;
     74         }
     75 
     76         sal_sem_take(soc->l2x_age_sync, sal_sem_FOREVER);
     77         soc_mem_lock(unit, L2Xm);
     78 
     79         /* Match VALIDf=1, STATICf=0, HITSAf=0, HITDAf=0 */
     80         /* Set match data */
     81         sal_memset(&match_data, 0, sizeof(l2x_entry_t));
     82         soc_mem_field32_set(unit, L2Xm, &match_data, VALIDf, 1);
     83 
     84         /* Set match mask */
     85         sal_memset(&match_mask, 0, sizeof(l2x_entry_t));
     86         soc_mem_field32_set(unit, L2Xm, &match_mask, VALIDf, 1);
     87         soc_mem_field32_set(unit, L2Xm, &match_mask, STATIC_BITf, 1);
     88         soc_mem_field32_set(unit, L2Xm, &match_mask, HITSAf, 1);
     89         soc_mem_field32_set(unit, L2Xm, &match_mask, HITDAf, 1);
     90 
     91         _SOC_IF_ERROR_UNLOCK_EXIT
     92             (WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0, &match_data));
     93         _SOC_IF_ERROR_UNLOCK_EXIT
     94             (WRITE_L2_BULK_MATCH_MASKm(unit, MEM_BLOCK_ALL, 0, &match_mask));
     95 
     96         sal_memset(&new_data, 0, sizeof(l2x_entry_t));
     97         if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) { /* Clear VALIDf */
     98             sal_memset(&new_mask, 0, sizeof(l2x_entry_t));
     99             soc_mem_field32_set(unit, L2Xm, &new_mask, VALIDf, 1);
    100         } else { /* Clear All Fields */
    101             sal_memset(&new_mask, 0xff, sizeof(l2x_entry_t));
    102         }
    103 
    104         _SOC_IF_ERROR_UNLOCK_EXIT
    105             (WRITE_L2_BULK_REPLACE_DATAm(unit, MEM_BLOCK_ALL, 0, &new_data));
    106         _SOC_IF_ERROR_UNLOCK_EXIT
    107             (WRITE_L2_BULK_REPLACE_MASKm(unit, MEM_BLOCK_ALL, 0, &new_mask));
    108 
    109         /* Set bulk control action */
    110         _SOC_IF_ERROR_UNLOCK_EXIT(READ_L2_BULK_CONTROLr(unit, &rval));
    111         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 2);
    112         if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
    113             soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, 
    114                               L2_MOD_FIFO_RECORDf, 1);
    115         }
    116         _SOC_IF_ERROR_UNLOCK_EXIT(WRITE_L2_BULK_CONTROLr(unit, rval));
    117 
    118         rv = soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    119         if (rv == SOC_E_TIMEOUT) {
    120             goto age_exit;
    121         }
    122         _SOC_IF_ERROR_UNLOCK_EXIT(rv);
    123 
    124         /* Match VALIDf=1, HITSAf=1, HITDAf=1 */
    125         /* Set match data */
    126         sal_memset(&match_data, 0, sizeof(l2x_entry_t));
    127         soc_mem_field32_set(unit, L2Xm, &match_data, VALIDf, 1);
    128 
    129         /* Set match mask */
    130         sal_memset(&match_mask, 0, sizeof(l2x_entry_t));
    131         soc_mem_field32_set(unit, L2Xm, &match_mask, VALIDf, 1);
    132         /* soc_mem_field32_set(unit, L2Xm, &match_mask, STATIC_BITf, 1); */
    133 
    134         _SOC_IF_ERROR_UNLOCK_EXIT
    135             (WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0, &match_data));
    136         _SOC_IF_ERROR_UNLOCK_EXIT
    137             (WRITE_L2_BULK_MATCH_MASKm(unit, MEM_BLOCK_ALL, 0, &match_mask));
    138 
    139         sal_memset(&new_data, 0, sizeof(l2x_entry_t));
    140         /* Clear HIT bits */
    141         sal_memset(&new_mask, 0, sizeof(l2x_entry_t));
    142         soc_mem_field32_set(unit, L2Xm, &new_mask, HITSAf, 1);
    143         soc_mem_field32_set(unit, L2Xm, &new_mask, HITDAf, 1);
    144         soc_mem_field32_set(unit, L2Xm, &new_mask, LOCAL_SAf, 1);
    145 
    146         _SOC_IF_ERROR_UNLOCK_EXIT
    147             (WRITE_L2_BULK_REPLACE_DATAm(unit, MEM_BLOCK_ALL, 0, &new_data));
    148         _SOC_IF_ERROR_UNLOCK_EXIT
    149             (WRITE_L2_BULK_REPLACE_MASKm(unit, MEM_BLOCK_ALL, 0, &new_mask));
    150 
    151         /* Set bulk control action */
    152         _SOC_IF_ERROR_UNLOCK_EXIT(READ_L2_BULK_CONTROLr(unit, &rval));
    153         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 2);
    154         if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
    155             soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, 
    156                               L2_MOD_FIFO_RECORDf, 0);
    157         }
    158         _SOC_IF_ERROR_UNLOCK_EXIT(WRITE_L2_BULK_CONTROLr(unit, rval));
    159 
    160         rv = soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    161         if (rv == SOC_E_TIMEOUT) {
    162             goto age_exit;
    163         }
    164         _SOC_IF_ERROR_UNLOCK_EXIT(rv);
    165 
    166 age_exit:
    167         soc_mem_unlock(unit, L2Xm);
    168         sal_sem_give(soc->l2x_age_sync);
    169 
    170         etime = sal_time_usecs();
    171         LOG_VERBOSE(BSL_LS_SOC_ARL,
    172                     (BSL_META_U(unit,
    173                                 "l2_bulk_age_thread: unit=%d: done in %d usec with rv=%d\n"),
    174                      unit, SAL_USECS_SUB(etime, stime), rv));
    175 
    176 age_delay:
    177         rv = -1;
    178         for (i = 0; i < interval / cfg_interval; i++) {
    179             rv = sal_sem_take(soc->l2x_age_notify, cfg_interval * 1000000);
    180             if (interval != soc->l2x_age_interval || rv == 0) {
    181                 break;
    182             }
    183         }
    184         /* age interval is not changed */
    185         if (rv != 0 && interval == soc->l2x_age_interval && interval % cfg_interval) {
    186             rv = sal_sem_take(soc->l2x_age_notify, interval % cfg_interval * 1000000);
    187         }
    188         /* age interval is changed */
    189         if (soc->l2x_age_interval && (interval != soc->l2x_age_interval || rv == 0)) {
    190             interval = soc->l2x_age_interval;
    191             goto age_delay;
    192         }
    193 
    194         iter++;
    195     }
    196 
    197 thread_exit:
    198     LOG_VERBOSE(BSL_LS_SOC_L2,
    199                 (BSL_META_U(unit,
    200                             "l2_bulk_age_thread: exiting\n")));
    201 
    202     soc->l2x_age_pid = SAL_THREAD_ERROR;
    203     soc->l2x_age_interval = 0;
    204     soc->l2x_age_enable = 0;
    205 
    206     sal_thread_exit(0);
    207 }
    208 
    209 /*
    210  * Function:
    211  *  soc_td2_l2_bulk_age_start
    212  * Purpose:
    213  *  Start l2 bulk age thread
    214  * Parameters:
    215  *  unit - unit number.
    216  * Returns:
    217  *  SOC_E_XXX
    218  */
    219 int
    220 soc_td2_l2_bulk_age_start(int unit, int interval)
    221 {
    222     soc_control_t *soc = SOC_CONTROL(unit);
    223     int cfg_interval;
    224     int thread_prio;
    225 
    226     if (soc->l2x_age_pid && soc->l2x_age_pid != SAL_THREAD_ERROR) {
    227         return SOC_E_NONE;
    228     }
    229 
    230     cfg_interval = soc_property_get(unit, spn_L2_SW_AGING_INTERVAL, 300);
    231 
    232     SOC_CONTROL_LOCK(unit);
    233     soc->l2x_age_interval = interval ? interval : cfg_interval;
    234     soc->l2x_age_enable = interval ? 1 : 0;
    235     sal_snprintf(soc->l2x_age_name, sizeof(soc->l2x_age_name), "bcmL2age.%d", unit);
    236     thread_prio = 50;
    237     if (soc_feature(unit, soc_feature_l2_hw_aging_bug)) {
    238         /* Real-time threads not permitted in simulation environments */
    239         if (!SAL_BOOT_SIMULATION) {
    240             thread_prio = SAL_THREAD_PRIO_NO_PREEMPT;
    241         }
    242     }
    243     soc->l2x_age_pid = sal_thread_create(soc->l2x_age_name, SAL_THREAD_STKSZ,
    244                                          soc_property_get(unit, spn_L2AGE_THREAD_PRI, thread_prio),
    245                                          _soc_td2_l2_bulk_age, INT_TO_PTR(unit));
    246     if (soc->l2x_age_pid == SAL_THREAD_ERROR) {
    247         LOG_ERROR(BSL_LS_SOC_L2,
    248                   (BSL_META_U(unit,
    249                               "Could not start L2 bulk age thread\n")));
    250         SOC_CONTROL_UNLOCK(unit);
    251         return SOC_E_MEMORY;
    252     }
    253     SOC_CONTROL_UNLOCK(unit);
    254 
    255     return SOC_E_NONE;
    256 }
    257 
    258 /*
    259  * Function:
    260  *  soc_td2_l2_bulk_age_stop
    261  * Purpose:
    262  *  Stop l2 bulk age thread
    263  * Parameters:
    264  *  unit - unit number.
    265  * Returns:
    266  *  SOC_E_XXX
    267  */
    268 int
    269 soc_td2_l2_bulk_age_stop(int unit)
    270 {
    271     soc_control_t *soc = SOC_CONTROL(unit);
    272     soc_timeout_t to;
    273     int rv = SOC_E_NONE;
    274 
    275     SOC_CONTROL_LOCK(unit);
    276     soc->l2x_age_interval = 0;
    277     soc->l2x_age_enable = 0;
    278     SOC_CONTROL_UNLOCK(unit);
    279 
    280     if (soc->l2x_age_pid && soc->l2x_age_pid != SAL_THREAD_ERROR) {
    281         sal_sem_give(soc->l2x_age_notify);
    282 
    283         if (SAL_BOOT_SIMULATION) {
    284             soc_timeout_init(&to, 300 * 1000000, 0);
    285         } else {
    286             soc_timeout_init(&to, 60 * 1000000, 0);
    287         }
    288 
    289         while (soc->l2x_age_pid != SAL_THREAD_ERROR) {
    290             if (soc_timeout_check(&to)) {
    291                 LOG_ERROR(BSL_LS_SOC_L2,
    292                           (BSL_META_U(unit,
    293                                       "thread will not exit\n")));
    294                 rv = SOC_E_INTERNAL;
    295                 break;
    296             }
    297         }
    298     }
    299 
    300     return rv;
    301 }
    302 
    303 #endif /* BCM_TRIDENT2_SUPPORT */
    304 #endif /* BCM_XGS_SWITCH_SUPPORT */