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