1dd0191d5SShuanglin Wang /* SPDX-License-Identifier: BSD-3-Clause 2dd0191d5SShuanglin Wang * Copyright(c) 2014-2021 Broadcom 3dd0191d5SShuanglin Wang * All rights reserved. 4dd0191d5SShuanglin Wang */ 5dd0191d5SShuanglin Wang 6dd0191d5SShuanglin Wang #include <rte_common.h> 7dd0191d5SShuanglin Wang #include <rte_cycles.h> 8dd0191d5SShuanglin Wang #include <rte_malloc.h> 9dd0191d5SShuanglin Wang #include <rte_log.h> 10dd0191d5SShuanglin Wang #include <rte_alarm.h> 11dd0191d5SShuanglin Wang #include "bnxt.h" 12dd0191d5SShuanglin Wang #include "bnxt_ulp.h" 13*0c036a14SPeter Spreadborough #include "bnxt_ulp_utils.h" 14dd0191d5SShuanglin Wang #include "bnxt_ulp_tf.h" 15dd0191d5SShuanglin Wang #include "bnxt_tf_common.h" 16dd0191d5SShuanglin Wang #include "ulp_fc_mgr.h" 17dd0191d5SShuanglin Wang #include "ulp_flow_db.h" 18dd0191d5SShuanglin Wang #include "ulp_template_db_enum.h" 19dd0191d5SShuanglin Wang #include "ulp_template_struct.h" 20dd0191d5SShuanglin Wang #include "tf_tbl.h" 21dd0191d5SShuanglin Wang 22dd0191d5SShuanglin Wang /* 23dd0191d5SShuanglin Wang * DMA-in the raw counter data from the HW and accumulate in the 24dd0191d5SShuanglin Wang * local accumulator table using the TF-Core API 25dd0191d5SShuanglin Wang * 26dd0191d5SShuanglin Wang * tfp [in] The TF-Core context 27dd0191d5SShuanglin Wang * 28dd0191d5SShuanglin Wang * fc_info [in] The ULP Flow counter info ptr 29dd0191d5SShuanglin Wang * 30dd0191d5SShuanglin Wang * dir [in] The direction of the flow 31dd0191d5SShuanglin Wang * 32dd0191d5SShuanglin Wang * num_counters [in] The number of counters 33dd0191d5SShuanglin Wang * 34dd0191d5SShuanglin Wang */ 35dd0191d5SShuanglin Wang static int32_t __rte_unused 36dd0191d5SShuanglin Wang ulp_bulk_get_flow_stats(struct tf *tfp, 37dd0191d5SShuanglin Wang struct bnxt_ulp_fc_info *fc_info, 38dd0191d5SShuanglin Wang enum tf_dir dir, 39dd0191d5SShuanglin Wang struct bnxt_ulp_device_params *dparms) 40dd0191d5SShuanglin Wang /* MARK AS UNUSED FOR NOW TO AVOID COMPILATION ERRORS TILL API is RESOLVED */ 41dd0191d5SShuanglin Wang { 42dd0191d5SShuanglin Wang int rc = 0; 43dd0191d5SShuanglin Wang struct tf_tbl_get_bulk_parms parms = { 0 }; 44dd0191d5SShuanglin Wang enum tf_tbl_type stype = TF_TBL_TYPE_ACT_STATS_64; /* TBD: Template? */ 45dd0191d5SShuanglin Wang struct sw_acc_counter *sw_acc_tbl_entry = NULL; 46dd0191d5SShuanglin Wang uint64_t *stats = NULL; 47dd0191d5SShuanglin Wang uint16_t i = 0; 48dd0191d5SShuanglin Wang 49dd0191d5SShuanglin Wang parms.dir = dir; 50dd0191d5SShuanglin Wang parms.type = stype; 51dd0191d5SShuanglin Wang parms.starting_idx = fc_info->shadow_hw_tbl[dir].start_idx; 52dd0191d5SShuanglin Wang parms.num_entries = dparms->flow_count_db_entries / 2; /* direction */ 53dd0191d5SShuanglin Wang /* 54dd0191d5SShuanglin Wang * TODO: 55dd0191d5SShuanglin Wang * Size of an entry needs to obtained from template 56dd0191d5SShuanglin Wang */ 57dd0191d5SShuanglin Wang parms.entry_sz_in_bytes = sizeof(uint64_t); 58dd0191d5SShuanglin Wang stats = (uint64_t *)fc_info->shadow_hw_tbl[dir].mem_va; 59dd0191d5SShuanglin Wang parms.physical_mem_addr = (uint64_t) 60dd0191d5SShuanglin Wang ((uintptr_t)(fc_info->shadow_hw_tbl[dir].mem_pa)); 61dd0191d5SShuanglin Wang 62dd0191d5SShuanglin Wang if (!stats) { 63dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 64dd0191d5SShuanglin Wang "BULK: Memory not initialized id:0x%x dir:%d\n", 65dd0191d5SShuanglin Wang parms.starting_idx, dir); 66dd0191d5SShuanglin Wang return -EINVAL; 67dd0191d5SShuanglin Wang } 68dd0191d5SShuanglin Wang 69dd0191d5SShuanglin Wang rc = tf_tbl_bulk_get(tfp, &parms); 70dd0191d5SShuanglin Wang if (rc) { 71dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 72dd0191d5SShuanglin Wang "BULK: Get failed for id:0x%x rc:%d\n", 73dd0191d5SShuanglin Wang parms.starting_idx, rc); 74dd0191d5SShuanglin Wang return rc; 75dd0191d5SShuanglin Wang } 76dd0191d5SShuanglin Wang 77dd0191d5SShuanglin Wang for (i = 0; i < parms.num_entries; i++) { 78dd0191d5SShuanglin Wang /* TBD - Get PKT/BYTE COUNT SHIFT/MASK from Template */ 79dd0191d5SShuanglin Wang sw_acc_tbl_entry = &fc_info->sw_acc_tbl[dir][i]; 80dd0191d5SShuanglin Wang if (!sw_acc_tbl_entry->valid) 81dd0191d5SShuanglin Wang continue; 82dd0191d5SShuanglin Wang sw_acc_tbl_entry->pkt_count += FLOW_CNTR_PKTS(stats[i], 83dd0191d5SShuanglin Wang dparms); 84dd0191d5SShuanglin Wang sw_acc_tbl_entry->byte_count += FLOW_CNTR_BYTES(stats[i], 85dd0191d5SShuanglin Wang dparms); 86dd0191d5SShuanglin Wang } 87dd0191d5SShuanglin Wang 88dd0191d5SShuanglin Wang return rc; 89dd0191d5SShuanglin Wang } 90dd0191d5SShuanglin Wang 91dd0191d5SShuanglin Wang static int ulp_fc_tf_flow_stat_update(struct bnxt_ulp_context *ctxt, 92dd0191d5SShuanglin Wang struct tf *tfp, 93dd0191d5SShuanglin Wang struct bnxt_ulp_fc_info *fc_info, 94dd0191d5SShuanglin Wang enum tf_dir dir, 95dd0191d5SShuanglin Wang uint32_t hw_cntr_id, 96dd0191d5SShuanglin Wang struct bnxt_ulp_device_params *dparms) 97dd0191d5SShuanglin Wang { 98dd0191d5SShuanglin Wang int rc = 0; 99dd0191d5SShuanglin Wang struct tf_get_tbl_entry_parms parms = { 0 }; 100dd0191d5SShuanglin Wang enum tf_tbl_type stype = TF_TBL_TYPE_ACT_STATS_64; /* TBD:Template? */ 101dd0191d5SShuanglin Wang struct sw_acc_counter *sw_acc_tbl_entry = NULL, *t_sw; 102dd0191d5SShuanglin Wang uint64_t stats = 0; 103dd0191d5SShuanglin Wang uint32_t sw_cntr_indx = 0; 104dd0191d5SShuanglin Wang 105dd0191d5SShuanglin Wang parms.dir = dir; 106dd0191d5SShuanglin Wang parms.type = stype; 107dd0191d5SShuanglin Wang parms.idx = hw_cntr_id; 108dd0191d5SShuanglin Wang /* 109dd0191d5SShuanglin Wang * TODO: 110dd0191d5SShuanglin Wang * Size of an entry needs to obtained from template 111dd0191d5SShuanglin Wang */ 112dd0191d5SShuanglin Wang parms.data_sz_in_bytes = sizeof(uint64_t); 113dd0191d5SShuanglin Wang parms.data = (uint8_t *)&stats; 114dd0191d5SShuanglin Wang rc = tf_get_tbl_entry(tfp, &parms); 115dd0191d5SShuanglin Wang if (rc) { 116dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 117dd0191d5SShuanglin Wang "Get failed for id:0x%x rc:%d\n", 118dd0191d5SShuanglin Wang parms.idx, rc); 119dd0191d5SShuanglin Wang return rc; 120dd0191d5SShuanglin Wang } 121dd0191d5SShuanglin Wang 122dd0191d5SShuanglin Wang /* PKT/BYTE COUNT SHIFT/MASK are device specific */ 123dd0191d5SShuanglin Wang sw_cntr_indx = hw_cntr_id - fc_info->shadow_hw_tbl[dir].start_idx; 124dd0191d5SShuanglin Wang sw_acc_tbl_entry = &fc_info->sw_acc_tbl[dir][sw_cntr_indx]; 125dd0191d5SShuanglin Wang 126dd0191d5SShuanglin Wang /* Some dpdk applications may accumulate the flow counters while some 127dd0191d5SShuanglin Wang * may not. In cases where the application is accumulating the counters 128dd0191d5SShuanglin Wang * the PMD need not do the accumulation itself and viceversa to report 129dd0191d5SShuanglin Wang * the correct flow counters. 130dd0191d5SShuanglin Wang */ 131dd0191d5SShuanglin Wang sw_acc_tbl_entry->pkt_count += FLOW_CNTR_PKTS(stats, dparms); 132dd0191d5SShuanglin Wang sw_acc_tbl_entry->byte_count += FLOW_CNTR_BYTES(stats, dparms); 133dd0191d5SShuanglin Wang 134dd0191d5SShuanglin Wang /* Update the parent counters if it is child flow */ 135dd0191d5SShuanglin Wang if (sw_acc_tbl_entry->pc_flow_idx & FLOW_CNTR_PC_FLOW_VALID) { 136dd0191d5SShuanglin Wang uint32_t pc_idx; 137dd0191d5SShuanglin Wang 138dd0191d5SShuanglin Wang /* Update the parent counters */ 139dd0191d5SShuanglin Wang t_sw = sw_acc_tbl_entry; 140dd0191d5SShuanglin Wang pc_idx = t_sw->pc_flow_idx & ~FLOW_CNTR_PC_FLOW_VALID; 141dd0191d5SShuanglin Wang if (ulp_flow_db_parent_flow_count_update(ctxt, pc_idx, 142dd0191d5SShuanglin Wang t_sw->pkt_count, 143dd0191d5SShuanglin Wang t_sw->byte_count)) { 144dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Error updating parent counters\n"); 145dd0191d5SShuanglin Wang } 146dd0191d5SShuanglin Wang } 147dd0191d5SShuanglin Wang 148dd0191d5SShuanglin Wang return rc; 149dd0191d5SShuanglin Wang } 150dd0191d5SShuanglin Wang 151dd0191d5SShuanglin Wang static int32_t 152dd0191d5SShuanglin Wang ulp_fc_tf_update_accum_stats(struct bnxt_ulp_context *ctxt, 153dd0191d5SShuanglin Wang struct bnxt_ulp_fc_info *fc_info, 154dd0191d5SShuanglin Wang struct bnxt_ulp_device_params *dparms) 155dd0191d5SShuanglin Wang { 156dd0191d5SShuanglin Wang uint32_t hw_cntr_id = 0, num_entries = 0, j; 157dd0191d5SShuanglin Wang int32_t rc = 0; 158dd0191d5SShuanglin Wang enum tf_dir dir; 159dd0191d5SShuanglin Wang struct tf *tfp; 160dd0191d5SShuanglin Wang 161dd0191d5SShuanglin Wang num_entries = dparms->flow_count_db_entries / 2; 162dd0191d5SShuanglin Wang for (dir = 0; dir < TF_DIR_MAX; dir++) { 163dd0191d5SShuanglin Wang for (j = 0; j < num_entries; j++) { 164dd0191d5SShuanglin Wang if (!fc_info->sw_acc_tbl[dir][j].valid) 165dd0191d5SShuanglin Wang continue; 166f6e12015SKishore Padmanabha tfp = bnxt_ulp_cntxt_tfp_get(ctxt, 167f6e12015SKishore Padmanabha fc_info->sw_acc_tbl[dir][j].session_type); 168f6e12015SKishore Padmanabha if (!tfp) { 169f6e12015SKishore Padmanabha BNXT_DRV_DBG(ERR, 170f6e12015SKishore Padmanabha "Failed to get the tfp\n"); 171f6e12015SKishore Padmanabha return 0; 172f6e12015SKishore Padmanabha } 173f6e12015SKishore Padmanabha 174dd0191d5SShuanglin Wang hw_cntr_id = fc_info->sw_acc_tbl[dir][j].hw_cntr_id; 175dd0191d5SShuanglin Wang 176dd0191d5SShuanglin Wang rc = ulp_fc_tf_flow_stat_update(ctxt, tfp, fc_info, dir, 177dd0191d5SShuanglin Wang hw_cntr_id, dparms); 178dd0191d5SShuanglin Wang if (rc) 179dd0191d5SShuanglin Wang break; 180dd0191d5SShuanglin Wang } 181dd0191d5SShuanglin Wang } 182dd0191d5SShuanglin Wang 183dd0191d5SShuanglin Wang return rc; 184dd0191d5SShuanglin Wang } 185dd0191d5SShuanglin Wang 186dd0191d5SShuanglin Wang static int32_t 187dd0191d5SShuanglin Wang ulp_fc_tf_flow_stat_get(struct bnxt_ulp_context *ctxt, 188dd0191d5SShuanglin Wang uint8_t direction, 189f6e12015SKishore Padmanabha uint32_t session_type, 190dd0191d5SShuanglin Wang uint64_t handle, 191dd0191d5SShuanglin Wang struct rte_flow_query_count *qcount) 192dd0191d5SShuanglin Wang { 193dd0191d5SShuanglin Wang struct tf *tfp; 194dd0191d5SShuanglin Wang struct bnxt_ulp_device_params *dparms; 195dd0191d5SShuanglin Wang struct tf_get_tbl_entry_parms parms = { 0 }; 196dd0191d5SShuanglin Wang struct tf_set_tbl_entry_parms sparms = { 0 }; 197dd0191d5SShuanglin Wang enum tf_tbl_type stype = TF_TBL_TYPE_ACT_STATS_64; 198dd0191d5SShuanglin Wang uint64_t stats = 0; 199dd0191d5SShuanglin Wang uint32_t dev_id = 0; 200dd0191d5SShuanglin Wang int32_t rc = 0; 201dd0191d5SShuanglin Wang 202f6e12015SKishore Padmanabha tfp = bnxt_ulp_cntxt_tfp_get(ctxt, session_type); 203dd0191d5SShuanglin Wang if (!tfp) { 204dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get the truflow pointer\n"); 205dd0191d5SShuanglin Wang return -EINVAL; 206dd0191d5SShuanglin Wang } 207dd0191d5SShuanglin Wang 208dd0191d5SShuanglin Wang if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) { 209dd0191d5SShuanglin Wang BNXT_DRV_DBG(DEBUG, "Failed to get device id\n"); 210dd0191d5SShuanglin Wang bnxt_ulp_cntxt_entry_release(); 211dd0191d5SShuanglin Wang return -EINVAL; 212dd0191d5SShuanglin Wang } 213dd0191d5SShuanglin Wang 214dd0191d5SShuanglin Wang dparms = bnxt_ulp_device_params_get(dev_id); 215dd0191d5SShuanglin Wang if (!dparms) { 216dd0191d5SShuanglin Wang BNXT_DRV_DBG(DEBUG, "Failed to device parms\n"); 217dd0191d5SShuanglin Wang bnxt_ulp_cntxt_entry_release(); 218dd0191d5SShuanglin Wang return -EINVAL; 219dd0191d5SShuanglin Wang } 220dd0191d5SShuanglin Wang parms.dir = (enum tf_dir)direction; 221dd0191d5SShuanglin Wang parms.type = stype; 222dd0191d5SShuanglin Wang parms.idx = (uint32_t)handle; 223dd0191d5SShuanglin Wang parms.data_sz_in_bytes = sizeof(uint64_t); 224dd0191d5SShuanglin Wang parms.data = (uint8_t *)&stats; 225dd0191d5SShuanglin Wang rc = tf_get_tbl_entry(tfp, &parms); 226dd0191d5SShuanglin Wang if (rc) { 227dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 228dd0191d5SShuanglin Wang "Get failed for id:0x%x rc:%d\n", 229dd0191d5SShuanglin Wang parms.idx, rc); 230dd0191d5SShuanglin Wang return rc; 231dd0191d5SShuanglin Wang } 232dd0191d5SShuanglin Wang qcount->hits = FLOW_CNTR_PKTS(stats, dparms); 233dd0191d5SShuanglin Wang if (qcount->hits) 234dd0191d5SShuanglin Wang qcount->hits_set = 1; 235dd0191d5SShuanglin Wang qcount->bytes = FLOW_CNTR_BYTES(stats, dparms); 236dd0191d5SShuanglin Wang if (qcount->bytes) 237dd0191d5SShuanglin Wang qcount->bytes_set = 1; 238dd0191d5SShuanglin Wang 239dd0191d5SShuanglin Wang if (qcount->reset) { 240dd0191d5SShuanglin Wang stats = 0; 241dd0191d5SShuanglin Wang sparms.dir = (enum tf_dir)direction; 242dd0191d5SShuanglin Wang sparms.type = stype; 243dd0191d5SShuanglin Wang sparms.idx = (uint32_t)handle; 244dd0191d5SShuanglin Wang sparms.data = (uint8_t *)&stats; 245dd0191d5SShuanglin Wang sparms.data_sz_in_bytes = sizeof(uint64_t); 246dd0191d5SShuanglin Wang rc = tf_set_tbl_entry(tfp, &sparms); 247dd0191d5SShuanglin Wang if (rc) { 248dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Set failed for id:0x%x rc:%d\n", 249dd0191d5SShuanglin Wang sparms.idx, rc); 250dd0191d5SShuanglin Wang return rc; 251dd0191d5SShuanglin Wang } 252dd0191d5SShuanglin Wang } 253dd0191d5SShuanglin Wang return rc; 254dd0191d5SShuanglin Wang } 255dd0191d5SShuanglin Wang 256dd0191d5SShuanglin Wang const struct bnxt_ulp_fc_core_ops ulp_fc_tf_core_ops = { 257dd0191d5SShuanglin Wang .ulp_flow_stat_get = ulp_fc_tf_flow_stat_get, 258dd0191d5SShuanglin Wang .ulp_flow_stats_accum_update = ulp_fc_tf_update_accum_stats 259dd0191d5SShuanglin Wang }; 260