10513f0afSPeter Spreadborough /* SPDX-License-Identifier: BSD-3-Clause 20513f0afSPeter Spreadborough * Copyright(c) 2014-2021 Broadcom 30513f0afSPeter Spreadborough * All rights reserved. 40513f0afSPeter Spreadborough */ 50513f0afSPeter Spreadborough 6*ca827d42SPeter Spreadborough #include <sched.h> 7*ca827d42SPeter Spreadborough #include <unistd.h> 80513f0afSPeter Spreadborough #include <rte_common.h> 90513f0afSPeter Spreadborough #include <rte_cycles.h> 100513f0afSPeter Spreadborough #include <rte_malloc.h> 110513f0afSPeter Spreadborough #include <rte_log.h> 120513f0afSPeter Spreadborough #include "bnxt.h" 130513f0afSPeter Spreadborough #include "bnxt_ulp.h" 140513f0afSPeter Spreadborough #include "bnxt_ulp_utils.h" 150513f0afSPeter Spreadborough #include "bnxt_ulp_tfc.h" 160513f0afSPeter Spreadborough #include "bnxt_tf_common.h" 170513f0afSPeter Spreadborough #include "ulp_sc_mgr.h" 180513f0afSPeter Spreadborough #include "ulp_flow_db.h" 190513f0afSPeter Spreadborough #include "ulp_template_db_enum.h" 200513f0afSPeter Spreadborough #include "ulp_template_struct.h" 210513f0afSPeter Spreadborough #include "tfc.h" 220513f0afSPeter Spreadborough #include "tfc_debug.h" 230513f0afSPeter Spreadborough #include "tfc_action_handle.h" 240513f0afSPeter Spreadborough 250513f0afSPeter Spreadborough #define ULP_TFC_CNTR_READ_BYTES 32 260513f0afSPeter Spreadborough #define ULP_TFC_CNTR_ALIGN 32 270513f0afSPeter Spreadborough #define ULP_TFC_ACT_WORD_SZ 32 280513f0afSPeter Spreadborough 290513f0afSPeter Spreadborough static const struct bnxt_ulp_sc_core_ops * 300513f0afSPeter Spreadborough bnxt_ulp_sc_ops_get(struct bnxt_ulp_context *ctxt) 310513f0afSPeter Spreadborough { 320513f0afSPeter Spreadborough int32_t rc; 330513f0afSPeter Spreadborough enum bnxt_ulp_device_id dev_id; 340513f0afSPeter Spreadborough const struct bnxt_ulp_sc_core_ops *func_ops; 350513f0afSPeter Spreadborough 360513f0afSPeter Spreadborough rc = bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id); 370513f0afSPeter Spreadborough if (rc) 380513f0afSPeter Spreadborough return NULL; 390513f0afSPeter Spreadborough 400513f0afSPeter Spreadborough switch (dev_id) { 410513f0afSPeter Spreadborough case BNXT_ULP_DEVICE_ID_THOR2: 420513f0afSPeter Spreadborough func_ops = &ulp_sc_tfc_core_ops; 430513f0afSPeter Spreadborough break; 440513f0afSPeter Spreadborough case BNXT_ULP_DEVICE_ID_THOR: 450513f0afSPeter Spreadborough case BNXT_ULP_DEVICE_ID_STINGRAY: 460513f0afSPeter Spreadborough case BNXT_ULP_DEVICE_ID_WH_PLUS: 470513f0afSPeter Spreadborough default: 480513f0afSPeter Spreadborough func_ops = NULL; 490513f0afSPeter Spreadborough break; 500513f0afSPeter Spreadborough } 510513f0afSPeter Spreadborough return func_ops; 520513f0afSPeter Spreadborough } 530513f0afSPeter Spreadborough 540513f0afSPeter Spreadborough int32_t ulp_sc_mgr_init(struct bnxt_ulp_context *ctxt) 550513f0afSPeter Spreadborough { 560513f0afSPeter Spreadborough const struct bnxt_ulp_sc_core_ops *sc_ops; 570513f0afSPeter Spreadborough struct bnxt_ulp_device_params *dparms; 580513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 590513f0afSPeter Spreadborough uint32_t stats_cache_tbl_sz; 600513f0afSPeter Spreadborough uint32_t dev_id; 61*ca827d42SPeter Spreadborough uint8_t *data; 620513f0afSPeter Spreadborough int rc; 63*ca827d42SPeter Spreadborough int i; 640513f0afSPeter Spreadborough 650513f0afSPeter Spreadborough if (!ctxt) { 660513f0afSPeter Spreadborough BNXT_DRV_DBG(DEBUG, "Invalid ULP CTXT\n"); 670513f0afSPeter Spreadborough return -EINVAL; 680513f0afSPeter Spreadborough } 690513f0afSPeter Spreadborough 700513f0afSPeter Spreadborough if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) { 710513f0afSPeter Spreadborough BNXT_DRV_DBG(DEBUG, "Failed to get device id\n"); 720513f0afSPeter Spreadborough return -EINVAL; 730513f0afSPeter Spreadborough } 740513f0afSPeter Spreadborough 750513f0afSPeter Spreadborough dparms = bnxt_ulp_device_params_get(dev_id); 760513f0afSPeter Spreadborough if (!dparms) { 770513f0afSPeter Spreadborough BNXT_DRV_DBG(DEBUG, "Failed to device parms\n"); 780513f0afSPeter Spreadborough return -EINVAL; 790513f0afSPeter Spreadborough } 800513f0afSPeter Spreadborough 810513f0afSPeter Spreadborough sc_ops = bnxt_ulp_sc_ops_get(ctxt); 820513f0afSPeter Spreadborough if (sc_ops == NULL) { 830513f0afSPeter Spreadborough BNXT_DRV_DBG(DEBUG, "Failed to get the counter ops\n"); 840513f0afSPeter Spreadborough return -EINVAL; 850513f0afSPeter Spreadborough } 860513f0afSPeter Spreadborough 870513f0afSPeter Spreadborough ulp_sc_info = rte_zmalloc("ulp_sc_info", sizeof(*ulp_sc_info), 0); 880513f0afSPeter Spreadborough if (!ulp_sc_info) { 890513f0afSPeter Spreadborough rc = -ENOMEM; 900513f0afSPeter Spreadborough goto error; 910513f0afSPeter Spreadborough } 920513f0afSPeter Spreadborough 930513f0afSPeter Spreadborough ulp_sc_info->sc_ops = sc_ops; 940513f0afSPeter Spreadborough ulp_sc_info->flags = 0; 950513f0afSPeter Spreadborough 960513f0afSPeter Spreadborough /* Add the SC info tbl to the ulp context. */ 970513f0afSPeter Spreadborough bnxt_ulp_cntxt_ptr2_sc_info_set(ctxt, ulp_sc_info); 980513f0afSPeter Spreadborough 990513f0afSPeter Spreadborough ulp_sc_info->num_counters = dparms->ext_flow_db_num_entries; 1000513f0afSPeter Spreadborough if (!ulp_sc_info->num_counters) { 1010513f0afSPeter Spreadborough /* No need for software counters, call fw directly */ 1020513f0afSPeter Spreadborough BNXT_DRV_DBG(DEBUG, "Sw flow counter support not enabled\n"); 1030513f0afSPeter Spreadborough return 0; 1040513f0afSPeter Spreadborough } 1050513f0afSPeter Spreadborough 1060513f0afSPeter Spreadborough /* 1070513f0afSPeter Spreadborough * Size is determined by the number of flows + 10% to cover IDs 1080513f0afSPeter Spreadborough * used for resources. 1090513f0afSPeter Spreadborough */ 11067ad4000SKishore Padmanabha ulp_sc_info->cache_tbl_size = ulp_sc_info->num_counters + 11167ad4000SKishore Padmanabha (ulp_sc_info->num_counters / 10); 1120513f0afSPeter Spreadborough stats_cache_tbl_sz = sizeof(struct ulp_sc_tfc_stats_cache_entry) * 11367ad4000SKishore Padmanabha ulp_sc_info->cache_tbl_size; 1140513f0afSPeter Spreadborough 1150513f0afSPeter Spreadborough ulp_sc_info->stats_cache_tbl = rte_zmalloc("ulp_stats_cache_tbl", 1160513f0afSPeter Spreadborough stats_cache_tbl_sz, 0); 1170513f0afSPeter Spreadborough if (!ulp_sc_info->stats_cache_tbl) { 1180513f0afSPeter Spreadborough rc = -ENOMEM; 1190513f0afSPeter Spreadborough goto error; 1200513f0afSPeter Spreadborough } 1210513f0afSPeter Spreadborough 1220513f0afSPeter Spreadborough ulp_sc_info->read_data = rte_zmalloc("ulp_stats_cache_read_data", 1230513f0afSPeter Spreadborough ULP_SC_BATCH_SIZE * ULP_SC_PAGE_SIZE, 1240513f0afSPeter Spreadborough ULP_SC_PAGE_SIZE); 1250513f0afSPeter Spreadborough if (!ulp_sc_info->read_data) { 1260513f0afSPeter Spreadborough rte_free(ulp_sc_info->stats_cache_tbl); 1270513f0afSPeter Spreadborough rc = -ENOMEM; 1280513f0afSPeter Spreadborough goto error; 1290513f0afSPeter Spreadborough } 1300513f0afSPeter Spreadborough 131*ca827d42SPeter Spreadborough data = ulp_sc_info->read_data; 132*ca827d42SPeter Spreadborough for (i = 0; i < ULP_SC_BATCH_SIZE; i++) { 133*ca827d42SPeter Spreadborough ulp_sc_info->read_data_iova[i] = (uint64_t)rte_mem_virt2iova(data); 134*ca827d42SPeter Spreadborough data += ULP_SC_PAGE_SIZE; 135*ca827d42SPeter Spreadborough } 136*ca827d42SPeter Spreadborough 1370513f0afSPeter Spreadborough rc = ulp_sc_mgr_thread_start(ctxt); 1380513f0afSPeter Spreadborough if (rc) 1390513f0afSPeter Spreadborough BNXT_DRV_DBG(DEBUG, "Stats counter thread start failed\n"); 1400513f0afSPeter Spreadborough 1410513f0afSPeter Spreadborough error: 1420513f0afSPeter Spreadborough return rc; 1430513f0afSPeter Spreadborough } 1440513f0afSPeter Spreadborough 1450513f0afSPeter Spreadborough /* 1460513f0afSPeter Spreadborough * Release all resources in the Flow Counter Manager for this ulp context 1470513f0afSPeter Spreadborough * 1480513f0afSPeter Spreadborough * ctxt [in] The ulp context for the Flow Counter manager 1490513f0afSPeter Spreadborough * 1500513f0afSPeter Spreadborough */ 1510513f0afSPeter Spreadborough int32_t 1520513f0afSPeter Spreadborough ulp_sc_mgr_deinit(struct bnxt_ulp_context *ctxt) 1530513f0afSPeter Spreadborough { 1540513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 1550513f0afSPeter Spreadborough 1560513f0afSPeter Spreadborough ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt); 1570513f0afSPeter Spreadborough 1580513f0afSPeter Spreadborough if (!ulp_sc_info) 1590513f0afSPeter Spreadborough return -EINVAL; 1600513f0afSPeter Spreadborough 1610513f0afSPeter Spreadborough if (ulp_sc_info->stats_cache_tbl) 1620513f0afSPeter Spreadborough rte_free(ulp_sc_info->stats_cache_tbl); 1630513f0afSPeter Spreadborough 1640513f0afSPeter Spreadborough if (ulp_sc_info->read_data) 1650513f0afSPeter Spreadborough rte_free(ulp_sc_info->read_data); 1660513f0afSPeter Spreadborough 1670513f0afSPeter Spreadborough rte_free(ulp_sc_info); 1680513f0afSPeter Spreadborough 1690513f0afSPeter Spreadborough /* Safe to ignore on deinit */ 1700513f0afSPeter Spreadborough (void)bnxt_ulp_cntxt_ptr2_sc_info_set(ctxt, NULL); 1710513f0afSPeter Spreadborough 1720513f0afSPeter Spreadborough return 0; 1730513f0afSPeter Spreadborough } 1740513f0afSPeter Spreadborough 17567ad4000SKishore Padmanabha #define ULP_SC_PERIOD_US 256 17667ad4000SKishore Padmanabha #define ULP_SC_CTX_DELAY 10000 1770513f0afSPeter Spreadborough 1780513f0afSPeter Spreadborough static uint32_t ulp_stats_cache_main_loop(void *arg) 1790513f0afSPeter Spreadborough { 1800513f0afSPeter Spreadborough struct ulp_sc_tfc_stats_cache_entry *count; 18167ad4000SKishore Padmanabha const struct bnxt_ulp_sc_core_ops *sc_ops = NULL; 1820513f0afSPeter Spreadborough struct ulp_sc_tfc_stats_cache_entry *sce; 1830513f0afSPeter Spreadborough struct ulp_sc_tfc_stats_cache_entry *sce_end; 1840513f0afSPeter Spreadborough struct tfc_mpc_batch_info_t batch_info; 1850513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 1860513f0afSPeter Spreadborough struct bnxt_ulp_context *ctxt = NULL; 1870513f0afSPeter Spreadborough uint16_t words = (ULP_TFC_CNTR_READ_BYTES + ULP_TFC_ACT_WORD_SZ - 1) / ULP_TFC_ACT_WORD_SZ; 1880513f0afSPeter Spreadborough uint32_t batch_size; 1890513f0afSPeter Spreadborough struct tfc *tfcp = NULL; 19067ad4000SKishore Padmanabha uint32_t batch, stat_cnt; 1910513f0afSPeter Spreadborough uint8_t *data; 1920513f0afSPeter Spreadborough int rc; 1930513f0afSPeter Spreadborough 19467ad4000SKishore Padmanabha while (true) { 19567ad4000SKishore Padmanabha ctxt = NULL; 1960513f0afSPeter Spreadborough while (!ctxt) { 1970513f0afSPeter Spreadborough ctxt = bnxt_ulp_cntxt_entry_acquire(arg); 1980513f0afSPeter Spreadborough 1990513f0afSPeter Spreadborough if (ctxt) 2000513f0afSPeter Spreadborough break; 20167ad4000SKishore Padmanabha /* If there are no more contexts just exit */ 20267ad4000SKishore Padmanabha if (bnxt_ulp_cntxt_list_count() == 0) 20367ad4000SKishore Padmanabha goto terminate; 20467ad4000SKishore Padmanabha rte_delay_us_block(ULP_SC_CTX_DELAY); 2050513f0afSPeter Spreadborough } 2060513f0afSPeter Spreadborough 20767ad4000SKishore Padmanabha /* get the stats counter info block from ulp context */ 2080513f0afSPeter Spreadborough ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt); 20967ad4000SKishore Padmanabha if (unlikely(!ulp_sc_info)) { 2100513f0afSPeter Spreadborough bnxt_ulp_cntxt_entry_release(); 2110513f0afSPeter Spreadborough goto terminate; 2120513f0afSPeter Spreadborough } 2130513f0afSPeter Spreadborough 21467ad4000SKishore Padmanabha sce = ulp_sc_info->stats_cache_tbl; 21567ad4000SKishore Padmanabha sce_end = sce + ulp_sc_info->cache_tbl_size; 21667ad4000SKishore Padmanabha 21767ad4000SKishore Padmanabha if (unlikely(!sc_ops)) 2180513f0afSPeter Spreadborough sc_ops = ulp_sc_info->sc_ops; 2190513f0afSPeter Spreadborough 22067ad4000SKishore Padmanabha stat_cnt = 0; 22167ad4000SKishore Padmanabha while (stat_cnt < ulp_sc_info->num_entries && (sce < sce_end)) { 2220513f0afSPeter Spreadborough data = ulp_sc_info->read_data; 2230513f0afSPeter Spreadborough 2240513f0afSPeter Spreadborough if (bnxt_ulp_cntxt_acquire_fdb_lock(ctxt)) 2250513f0afSPeter Spreadborough break; 2260513f0afSPeter Spreadborough 22767ad4000SKishore Padmanabha rc = tfc_mpc_batch_start(&batch_info); 22867ad4000SKishore Padmanabha if (unlikely(rc)) { 2290513f0afSPeter Spreadborough PMD_DRV_LOG_LINE(ERR, 23067ad4000SKishore Padmanabha "MPC batch start failed rc:%d", rc); 23167ad4000SKishore Padmanabha bnxt_ulp_cntxt_release_fdb_lock(ctxt); 23267ad4000SKishore Padmanabha break; 2330513f0afSPeter Spreadborough } 2340513f0afSPeter Spreadborough 23567ad4000SKishore Padmanabha for (batch = 0; (batch < ULP_SC_BATCH_SIZE) && 23667ad4000SKishore Padmanabha (sce < sce_end);) { 2370513f0afSPeter Spreadborough if (!(sce->flags & ULP_SC_ENTRY_FLAG_VALID)) { 2380513f0afSPeter Spreadborough sce++; 2390513f0afSPeter Spreadborough continue; 2400513f0afSPeter Spreadborough } 24167ad4000SKishore Padmanabha stat_cnt++; 2420513f0afSPeter Spreadborough tfcp = bnxt_ulp_cntxt_tfcp_get(sce->ctxt); 24367ad4000SKishore Padmanabha if (unlikely(!tfcp)) { 24467ad4000SKishore Padmanabha bnxt_ulp_cntxt_release_fdb_lock(ctxt); 2450513f0afSPeter Spreadborough bnxt_ulp_cntxt_entry_release(); 2460513f0afSPeter Spreadborough goto terminate; 2470513f0afSPeter Spreadborough } 2480513f0afSPeter Spreadborough 2490513f0afSPeter Spreadborough /* Store the entry pointer to use for counter update */ 25067ad4000SKishore Padmanabha batch_info.em_hdl[batch_info.count] = 25167ad4000SKishore Padmanabha (uint64_t)sce; 2520513f0afSPeter Spreadborough 2530513f0afSPeter Spreadborough rc = sc_ops->ulp_stats_cache_update(tfcp, 2540513f0afSPeter Spreadborough sce->dir, 255*ca827d42SPeter Spreadborough &ulp_sc_info->read_data_iova[batch], 2560513f0afSPeter Spreadborough sce->handle, 2570513f0afSPeter Spreadborough &words, 2580513f0afSPeter Spreadborough &batch_info, 2590513f0afSPeter Spreadborough sce->reset); 26067ad4000SKishore Padmanabha if (unlikely(rc)) { 2610513f0afSPeter Spreadborough /* Abort this batch */ 2620513f0afSPeter Spreadborough PMD_DRV_LOG_LINE(ERR, 26367ad4000SKishore Padmanabha "read_counter() failed:%d", rc); 2640513f0afSPeter Spreadborough break; 2650513f0afSPeter Spreadborough } 2660513f0afSPeter Spreadborough 2670513f0afSPeter Spreadborough if (sce->reset) 2680513f0afSPeter Spreadborough sce->reset = false; 2690513f0afSPeter Spreadborough 2700513f0afSPeter Spreadborough /* Next */ 2710513f0afSPeter Spreadborough batch++; 2720513f0afSPeter Spreadborough sce++; 2730513f0afSPeter Spreadborough data += ULP_SC_PAGE_SIZE; 2740513f0afSPeter Spreadborough } 2750513f0afSPeter Spreadborough 2760513f0afSPeter Spreadborough batch_size = batch_info.count; 2770513f0afSPeter Spreadborough rc = tfc_mpc_batch_end(tfcp, &batch_info); 2780513f0afSPeter Spreadborough 2790513f0afSPeter Spreadborough bnxt_ulp_cntxt_release_fdb_lock(ctxt); 2800513f0afSPeter Spreadborough 28167ad4000SKishore Padmanabha if (unlikely(rc)) { 28267ad4000SKishore Padmanabha PMD_DRV_LOG_LINE(ERR, "MPC batch end failed rc:%d", rc); 2830513f0afSPeter Spreadborough batch_info.enabled = false; 2840513f0afSPeter Spreadborough break; 2850513f0afSPeter Spreadborough } 2860513f0afSPeter Spreadborough 2870513f0afSPeter Spreadborough /* Process counts */ 2880513f0afSPeter Spreadborough data = ulp_sc_info->read_data; 2890513f0afSPeter Spreadborough 2900513f0afSPeter Spreadborough for (batch = 0; batch < batch_size; batch++) { 2910513f0afSPeter Spreadborough /* Check for error in completion */ 2920513f0afSPeter Spreadborough if (batch_info.result[batch]) { 29367ad4000SKishore Padmanabha PMD_DRV_LOG_LINE(ERR, "batch:%d result:%d", 2940513f0afSPeter Spreadborough batch, batch_info.result[batch]); 2950513f0afSPeter Spreadborough } else { 2960513f0afSPeter Spreadborough count = (struct ulp_sc_tfc_stats_cache_entry *) 2970513f0afSPeter Spreadborough ((uintptr_t)batch_info.em_hdl[batch]); 2980513f0afSPeter Spreadborough memcpy(&count->packet_count, data, ULP_TFC_ACT_WORD_SZ); 2990513f0afSPeter Spreadborough } 3000513f0afSPeter Spreadborough 3010513f0afSPeter Spreadborough data += ULP_SC_PAGE_SIZE; 3020513f0afSPeter Spreadborough } 3030513f0afSPeter Spreadborough } 30467ad4000SKishore Padmanabha bnxt_ulp_cntxt_entry_release(); 30567ad4000SKishore Padmanabha /* Sleep to give any other threads opportunity to access ULP */ 30667ad4000SKishore Padmanabha rte_delay_us_sleep(ULP_SC_PERIOD_US); 3070513f0afSPeter Spreadborough } 3080513f0afSPeter Spreadborough 3090513f0afSPeter Spreadborough terminate: 31067ad4000SKishore Padmanabha PMD_DRV_LOG_LINE(DEBUG, "Terminating the stats cachce thread"); 3110513f0afSPeter Spreadborough return 0; 3120513f0afSPeter Spreadborough } 3130513f0afSPeter Spreadborough 3140513f0afSPeter Spreadborough /* 3150513f0afSPeter Spreadborough * Check if the alarm thread that walks through the flows is started 3160513f0afSPeter Spreadborough * 3170513f0afSPeter Spreadborough * ctxt [in] The ulp context for the flow counter manager 3180513f0afSPeter Spreadborough * 3190513f0afSPeter Spreadborough */ 3200513f0afSPeter Spreadborough bool ulp_sc_mgr_thread_isstarted(struct bnxt_ulp_context *ctxt) 3210513f0afSPeter Spreadborough { 3220513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 3230513f0afSPeter Spreadborough 3240513f0afSPeter Spreadborough ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt); 3250513f0afSPeter Spreadborough 3260513f0afSPeter Spreadborough if (ulp_sc_info) 3270513f0afSPeter Spreadborough return !!(ulp_sc_info->flags & ULP_FLAG_SC_THREAD); 3280513f0afSPeter Spreadborough 3290513f0afSPeter Spreadborough return false; 3300513f0afSPeter Spreadborough } 3310513f0afSPeter Spreadborough 3320513f0afSPeter Spreadborough /* 3330513f0afSPeter Spreadborough * Setup the Flow counter timer thread that will fetch/accumulate raw counter 3340513f0afSPeter Spreadborough * data from the chip's internal flow counters 3350513f0afSPeter Spreadborough * 3360513f0afSPeter Spreadborough * ctxt [in] The ulp context for the flow counter manager 3370513f0afSPeter Spreadborough * 3380513f0afSPeter Spreadborough */ 3390513f0afSPeter Spreadborough int32_t 3400513f0afSPeter Spreadborough ulp_sc_mgr_thread_start(struct bnxt_ulp_context *ctxt) 3410513f0afSPeter Spreadborough { 3420513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 343*ca827d42SPeter Spreadborough rte_thread_attr_t attr; 344*ca827d42SPeter Spreadborough rte_cpuset_t mask; 345*ca827d42SPeter Spreadborough size_t i; 3460513f0afSPeter Spreadborough int rc; 3470513f0afSPeter Spreadborough 3480513f0afSPeter Spreadborough ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt); 3490513f0afSPeter Spreadborough 3500513f0afSPeter Spreadborough if (ulp_sc_info && !(ulp_sc_info->flags & ULP_FLAG_SC_THREAD)) { 351*ca827d42SPeter Spreadborough rte_thread_attr_init(&attr); 352*ca827d42SPeter Spreadborough 353*ca827d42SPeter Spreadborough rte_thread_get_affinity(&mask); 354*ca827d42SPeter Spreadborough 355*ca827d42SPeter Spreadborough for (i = 1; i < CPU_SETSIZE; i++) { 356*ca827d42SPeter Spreadborough if (CPU_ISSET(i, &mask)) { 357*ca827d42SPeter Spreadborough CPU_ZERO(&mask); 358*ca827d42SPeter Spreadborough CPU_SET(i + 2, &mask); 359*ca827d42SPeter Spreadborough break; 360*ca827d42SPeter Spreadborough } 361*ca827d42SPeter Spreadborough } 362*ca827d42SPeter Spreadborough 363*ca827d42SPeter Spreadborough rc = rte_thread_attr_set_affinity(&attr, &mask); 364*ca827d42SPeter Spreadborough if (rc) 365*ca827d42SPeter Spreadborough return rc; 366*ca827d42SPeter Spreadborough 3670513f0afSPeter Spreadborough rc = rte_thread_create(&ulp_sc_info->tid, 368*ca827d42SPeter Spreadborough &attr, 3690513f0afSPeter Spreadborough &ulp_stats_cache_main_loop, 3700513f0afSPeter Spreadborough (void *)ctxt->cfg_data); 3710513f0afSPeter Spreadborough if (rc) 3720513f0afSPeter Spreadborough return rc; 3730513f0afSPeter Spreadborough 374*ca827d42SPeter Spreadborough rte_thread_set_prefixed_name(ulp_sc_info->tid, "ulp_sc_mgr"); 375*ca827d42SPeter Spreadborough 3760513f0afSPeter Spreadborough ulp_sc_info->flags |= ULP_FLAG_SC_THREAD; 3770513f0afSPeter Spreadborough } 3780513f0afSPeter Spreadborough 3790513f0afSPeter Spreadborough return 0; 3800513f0afSPeter Spreadborough } 3810513f0afSPeter Spreadborough 3820513f0afSPeter Spreadborough /* 3830513f0afSPeter Spreadborough * Cancel the alarm handler 3840513f0afSPeter Spreadborough * 3850513f0afSPeter Spreadborough * ctxt [in] The ulp context for the flow counter manager 3860513f0afSPeter Spreadborough * 3870513f0afSPeter Spreadborough */ 3880513f0afSPeter Spreadborough void ulp_sc_mgr_thread_cancel(struct bnxt_ulp_context *ctxt) 3890513f0afSPeter Spreadborough { 3900513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 3910513f0afSPeter Spreadborough 3920513f0afSPeter Spreadborough ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt); 3930513f0afSPeter Spreadborough if (!ulp_sc_info) 3940513f0afSPeter Spreadborough return; 3950513f0afSPeter Spreadborough 3960513f0afSPeter Spreadborough ulp_sc_info->flags &= ~ULP_FLAG_SC_THREAD; 3970513f0afSPeter Spreadborough } 3980513f0afSPeter Spreadborough 3990513f0afSPeter Spreadborough /* 4000513f0afSPeter Spreadborough * Fill the rte_flow_query_count 'data' argument passed 4010513f0afSPeter Spreadborough * in the rte_flow_query() with the values obtained and 4020513f0afSPeter Spreadborough * accumulated locally. 4030513f0afSPeter Spreadborough * 4040513f0afSPeter Spreadborough * ctxt [in] The ulp context for the flow counter manager 4050513f0afSPeter Spreadborough * 4060513f0afSPeter Spreadborough * flow_id [in] The HW flow ID 4070513f0afSPeter Spreadborough * 4080513f0afSPeter Spreadborough * count [out] The rte_flow_query_count 'data' that is set 4090513f0afSPeter Spreadborough * 4100513f0afSPeter Spreadborough */ 4110513f0afSPeter Spreadborough int ulp_sc_mgr_query_count_get(struct bnxt_ulp_context *ctxt, 4120513f0afSPeter Spreadborough uint32_t flow_id, 4130513f0afSPeter Spreadborough struct rte_flow_query_count *count) 4140513f0afSPeter Spreadborough { 4150513f0afSPeter Spreadborough struct ulp_sc_tfc_stats_cache_entry *sce; 4160513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 417a089734aSShuanglin Wang struct ulp_fdb_parent_info *pc_entry; 418a089734aSShuanglin Wang struct bnxt_ulp_flow_db *flow_db; 419a089734aSShuanglin Wang uint32_t max_array; 420a089734aSShuanglin Wang uint32_t child_fid; 421a089734aSShuanglin Wang uint32_t a_idx; 422a089734aSShuanglin Wang uint32_t f2_cnt; 423a089734aSShuanglin Wang uint64_t *t; 424a089734aSShuanglin Wang uint64_t bs; 4250513f0afSPeter Spreadborough int rc = 0; 4260513f0afSPeter Spreadborough 427a089734aSShuanglin Wang /* Get stats cache info */ 4280513f0afSPeter Spreadborough ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt); 4290513f0afSPeter Spreadborough if (!ulp_sc_info) 4300513f0afSPeter Spreadborough return -ENODEV; 4310513f0afSPeter Spreadborough 4320513f0afSPeter Spreadborough sce = ulp_sc_info->stats_cache_tbl; 4330513f0afSPeter Spreadborough sce += flow_id; 4340513f0afSPeter Spreadborough 435a089734aSShuanglin Wang /* To handle the parent flow */ 436a089734aSShuanglin Wang if (sce->flags & ULP_SC_ENTRY_FLAG_PARENT) { 437a089734aSShuanglin Wang flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ctxt); 438a089734aSShuanglin Wang if (!flow_db) { 439a089734aSShuanglin Wang BNXT_DRV_DBG(ERR, "parent child db validation failed\n"); 440a089734aSShuanglin Wang return -EINVAL; 441a089734aSShuanglin Wang } 442a089734aSShuanglin Wang 443a089734aSShuanglin Wang /* Validate the arguments and parent child entry */ 444a089734aSShuanglin Wang pc_entry = ulp_flow_db_pc_db_entry_get(ctxt, sce->pc_idx); 445a089734aSShuanglin Wang if (!pc_entry) { 446a089734aSShuanglin Wang BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n"); 447a089734aSShuanglin Wang return -EINVAL; 448a089734aSShuanglin Wang } 449a089734aSShuanglin Wang 450a089734aSShuanglin Wang t = pc_entry->child_fid_bitset; 451a089734aSShuanglin Wang f2_cnt = pc_entry->f2_cnt; 452a089734aSShuanglin Wang max_array = flow_db->parent_child_db.child_bitset_size * 8 / ULP_INDEX_BITMAP_SIZE; 453a089734aSShuanglin Wang 454a089734aSShuanglin Wang /* Iterate all possible child flows */ 455a089734aSShuanglin Wang for (a_idx = 0; (a_idx < max_array) && f2_cnt; a_idx++) { 456a089734aSShuanglin Wang /* If it is zero, then check the next bitset */ 457a089734aSShuanglin Wang bs = t[a_idx]; 458a089734aSShuanglin Wang if (!bs) 459a089734aSShuanglin Wang continue; 460a089734aSShuanglin Wang 461a089734aSShuanglin Wang /* check one bitset */ 462a089734aSShuanglin Wang do { 463a089734aSShuanglin Wang /* get the next child fid */ 464a089734aSShuanglin Wang child_fid = (a_idx * ULP_INDEX_BITMAP_SIZE) + rte_clz64(bs); 465a089734aSShuanglin Wang sce = ulp_sc_info->stats_cache_tbl; 466a089734aSShuanglin Wang sce += child_fid; 467a089734aSShuanglin Wang 468a089734aSShuanglin Wang /* clear the bit for this child flow */ 469a089734aSShuanglin Wang ULP_INDEX_BITMAP_RESET(bs, child_fid); 470a089734aSShuanglin Wang f2_cnt--; 471a089734aSShuanglin Wang 472a089734aSShuanglin Wang /* no counter action, then ignore flows */ 473a089734aSShuanglin Wang if (!(sce->flags & ULP_SC_ENTRY_FLAG_VALID)) 474a089734aSShuanglin Wang continue; 475a089734aSShuanglin Wang count->hits += sce->packet_count; 476a089734aSShuanglin Wang count->hits_set = 1; 477a089734aSShuanglin Wang count->bytes += sce->byte_count; 478a089734aSShuanglin Wang count->bytes_set = 1; 479a089734aSShuanglin Wang } while (bs && f2_cnt); 480a089734aSShuanglin Wang } 481a089734aSShuanglin Wang } else { 482a089734aSShuanglin Wang /* To handle regular or child flows */ 4830513f0afSPeter Spreadborough /* If entry is not valid return an error */ 4840513f0afSPeter Spreadborough if (!(sce->flags & ULP_SC_ENTRY_FLAG_VALID)) 4850513f0afSPeter Spreadborough return -EBUSY; 4860513f0afSPeter Spreadborough 4870513f0afSPeter Spreadborough count->hits = sce->packet_count; 4880513f0afSPeter Spreadborough count->hits_set = 1; 4890513f0afSPeter Spreadborough count->bytes = sce->byte_count; 4900513f0afSPeter Spreadborough count->bytes_set = 1; 4910513f0afSPeter Spreadborough 4920513f0afSPeter Spreadborough if (count->reset) 4930513f0afSPeter Spreadborough sce->reset = true; 494a089734aSShuanglin Wang } 4950513f0afSPeter Spreadborough return rc; 4960513f0afSPeter Spreadborough } 4970513f0afSPeter Spreadborough 4980513f0afSPeter Spreadborough 4990513f0afSPeter Spreadborough int ulp_sc_mgr_entry_alloc(struct bnxt_ulp_mapper_parms *parms, 5000513f0afSPeter Spreadborough uint64_t counter_handle, 5010513f0afSPeter Spreadborough struct bnxt_ulp_mapper_tbl_info *tbl) 5020513f0afSPeter Spreadborough { 5030513f0afSPeter Spreadborough struct ulp_sc_tfc_stats_cache_entry *sce; 5040513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 5050513f0afSPeter Spreadborough 5060513f0afSPeter Spreadborough ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(parms->ulp_ctx); 5070513f0afSPeter Spreadborough if (!ulp_sc_info) 5080513f0afSPeter Spreadborough return -ENODEV; 5090513f0afSPeter Spreadborough 5100513f0afSPeter Spreadborough sce = ulp_sc_info->stats_cache_tbl; 5110513f0afSPeter Spreadborough sce += parms->flow_id; 5120513f0afSPeter Spreadborough 5130513f0afSPeter Spreadborough /* If entry is not free return an error */ 5140513f0afSPeter Spreadborough if (sce->flags & ULP_SC_ENTRY_FLAG_VALID) { 51567ad4000SKishore Padmanabha BNXT_DRV_DBG(ERR, "Entry is not free, invalid flow id %u\n", 51667ad4000SKishore Padmanabha parms->flow_id); 5170513f0afSPeter Spreadborough return -EBUSY; 5180513f0afSPeter Spreadborough } 5190513f0afSPeter Spreadborough 5200513f0afSPeter Spreadborough memset(sce, 0, sizeof(*sce)); 5210513f0afSPeter Spreadborough sce->ctxt = parms->ulp_ctx; 5220513f0afSPeter Spreadborough sce->flags |= ULP_SC_ENTRY_FLAG_VALID; 523a089734aSShuanglin Wang if (parms->parent_flow) 524a089734aSShuanglin Wang sce->flags |= ULP_SC_ENTRY_FLAG_PARENT; 5250513f0afSPeter Spreadborough sce->handle = counter_handle; 5260513f0afSPeter Spreadborough sce->dir = tbl->direction; 5270513f0afSPeter Spreadborough ulp_sc_info->num_entries++; 5280513f0afSPeter Spreadborough return 0; 5290513f0afSPeter Spreadborough } 5300513f0afSPeter Spreadborough 5310513f0afSPeter Spreadborough void ulp_sc_mgr_entry_free(struct bnxt_ulp_context *ulp, 5320513f0afSPeter Spreadborough uint32_t fid) 5330513f0afSPeter Spreadborough { 5340513f0afSPeter Spreadborough struct ulp_sc_tfc_stats_cache_entry *sce; 5350513f0afSPeter Spreadborough struct bnxt_ulp_sc_info *ulp_sc_info; 5360513f0afSPeter Spreadborough 5370513f0afSPeter Spreadborough ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ulp); 5380513f0afSPeter Spreadborough if (!ulp_sc_info) 5390513f0afSPeter Spreadborough return; 5400513f0afSPeter Spreadborough 5410513f0afSPeter Spreadborough sce = ulp_sc_info->stats_cache_tbl; 5420513f0afSPeter Spreadborough sce += fid; 5430513f0afSPeter Spreadborough 5440513f0afSPeter Spreadborough if (!(sce->flags & ULP_SC_ENTRY_FLAG_VALID)) { 54567ad4000SKishore Padmanabha BNXT_DRV_DBG(ERR, "Entry already free, invalid flow id %u\n", 54667ad4000SKishore Padmanabha fid); 5470513f0afSPeter Spreadborough return; 5480513f0afSPeter Spreadborough } 5490513f0afSPeter Spreadborough 5500513f0afSPeter Spreadborough sce->flags = 0; 5510513f0afSPeter Spreadborough ulp_sc_info->num_entries--; 5520513f0afSPeter Spreadborough } 553a089734aSShuanglin Wang 554a089734aSShuanglin Wang /* 555a089734aSShuanglin Wang * Set pc_idx for the flow if stat cache info is valid 556a089734aSShuanglin Wang * 557a089734aSShuanglin Wang * ctxt [in] The ulp context for the flow counter manager 558a089734aSShuanglin Wang * 559a089734aSShuanglin Wang * flow_id [in] The HW flow ID 560a089734aSShuanglin Wang * 561a089734aSShuanglin Wang * pc_idx [in] The parent flow entry idx 562a089734aSShuanglin Wang * 563a089734aSShuanglin Wang */ 564a089734aSShuanglin Wang void ulp_sc_mgr_set_pc_idx(struct bnxt_ulp_context *ctxt, 565a089734aSShuanglin Wang uint32_t flow_id, 566a089734aSShuanglin Wang uint32_t pc_idx) 567a089734aSShuanglin Wang { 568a089734aSShuanglin Wang struct ulp_sc_tfc_stats_cache_entry *sce; 569a089734aSShuanglin Wang struct bnxt_ulp_sc_info *ulp_sc_info; 570a089734aSShuanglin Wang 571a089734aSShuanglin Wang /* Get stats cache info */ 572a089734aSShuanglin Wang ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt); 573a089734aSShuanglin Wang if (!ulp_sc_info) 574a089734aSShuanglin Wang return; 575a089734aSShuanglin Wang 576a089734aSShuanglin Wang sce = ulp_sc_info->stats_cache_tbl; 577a089734aSShuanglin Wang sce += flow_id; 578a089734aSShuanglin Wang sce->pc_idx = pc_idx & ULP_SC_PC_IDX_MASK; 579a089734aSShuanglin Wang } 580