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