xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_fc_mgr_tf.c (revision 0c036a1485b9d9163a8fa8059ed5272d060c05e0)
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