xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_mapper_tfc.c (revision 0c036a1485b9d9163a8fa8059ed5272d060c05e0)
1dd0191d5SShuanglin Wang /* SPDX-License-Identifier: BSD-3-Clause
2dd0191d5SShuanglin Wang  * Copyright(c) 2014-2023 Broadcom
3dd0191d5SShuanglin Wang  * All rights reserved.
4dd0191d5SShuanglin Wang  */
5dd0191d5SShuanglin Wang #include <rte_byteorder.h>
6dd0191d5SShuanglin Wang #include "ulp_mapper.h"
7dd0191d5SShuanglin Wang #include "ulp_flow_db.h"
8dd0191d5SShuanglin Wang #include "cfa_resources.h"
9dd0191d5SShuanglin Wang #include "cfa_bld.h"
10dd0191d5SShuanglin Wang #include "tfc_util.h"
11dd0191d5SShuanglin Wang #include "bnxt_ulp_tfc.h"
12*0c036a14SPeter Spreadborough #include "bnxt_ulp_utils.h"
13dd0191d5SShuanglin Wang #include "tfc_action_handle.h"
14dd0191d5SShuanglin Wang 
15dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
16dd0191d5SShuanglin Wang #include "ulp_template_debug_proto.h"
17dd0191d5SShuanglin Wang #include "ulp_tf_debug.h"
18dd0191d5SShuanglin Wang #include "tfc_debug.h"
19dd0191d5SShuanglin Wang #endif
20dd0191d5SShuanglin Wang 
21dd0191d5SShuanglin Wang /* Internal function to write the tcam entry */
22dd0191d5SShuanglin Wang static int32_t
23dd0191d5SShuanglin Wang ulp_mapper_tfc_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
24dd0191d5SShuanglin Wang 				    struct bnxt_ulp_mapper_tbl_info *tbl,
25dd0191d5SShuanglin Wang 				    struct ulp_blob *key,
26dd0191d5SShuanglin Wang 				    struct ulp_blob *mask,
27dd0191d5SShuanglin Wang 				    struct ulp_blob *remap,
28dd0191d5SShuanglin Wang 				    uint16_t idx)
29dd0191d5SShuanglin Wang {
30dd0191d5SShuanglin Wang 	struct tfc_tcam_info tfc_info = {0};
31dd0191d5SShuanglin Wang 	struct tfc_tcam_data tfc_data = {0};
32dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
33dd0191d5SShuanglin Wang 	uint16_t key_size = 0, mask_size = 0, remap_size = 0;
34dd0191d5SShuanglin Wang 	int32_t rc;
35dd0191d5SShuanglin Wang 	uint16_t fw_fid;
36dd0191d5SShuanglin Wang 
37dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx);
38*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
39dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n");
40dd0191d5SShuanglin Wang 		return -EINVAL;
41dd0191d5SShuanglin Wang 	}
42dd0191d5SShuanglin Wang 
43dd0191d5SShuanglin Wang 	rc = bnxt_ulp_cntxt_fid_get(parms->ulp_ctx, &fw_fid);
44*0c036a14SPeter Spreadborough 	if (unlikely(rc))
45dd0191d5SShuanglin Wang 		return rc;
46dd0191d5SShuanglin Wang 
47dd0191d5SShuanglin Wang 	tfc_info.dir = tbl->direction;
48dd0191d5SShuanglin Wang 	tfc_info.rsubtype = tbl->resource_type;
49dd0191d5SShuanglin Wang 	tfc_info.id = idx;
50dd0191d5SShuanglin Wang 	tfc_data.key = ulp_blob_data_get(key, &key_size);
51dd0191d5SShuanglin Wang 	tfc_data.key_sz_in_bytes = ULP_BITS_2_BYTE(key_size);
52dd0191d5SShuanglin Wang 	tfc_data.mask = ulp_blob_data_get(mask, &mask_size);
53dd0191d5SShuanglin Wang 	tfc_data.remap = ulp_blob_data_get(remap, &remap_size);
54dd0191d5SShuanglin Wang 	remap_size = ULP_BITS_2_BYTE(remap_size);
55dd0191d5SShuanglin Wang 	tfc_data.remap_sz_in_bytes = remap_size;
56dd0191d5SShuanglin Wang 
57*0c036a14SPeter Spreadborough 	if (unlikely(tfc_tcam_set(tfcp, fw_fid, &tfc_info, &tfc_data))) {
58dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
59dd0191d5SShuanglin Wang 			     tfc_tcam_2_str(tfc_info.rsubtype),
60dd0191d5SShuanglin Wang 			     tfc_dir_2_str(tfc_info.dir), tfc_info.id);
61dd0191d5SShuanglin Wang 		return -EIO;
62dd0191d5SShuanglin Wang 	}
63dd0191d5SShuanglin Wang 	PMD_DRV_LOG_LINE(INFO, "tcam[%s][%s][%x] write success.",
64dd0191d5SShuanglin Wang 		    tfc_tcam_2_str(tfc_info.rsubtype),
65dd0191d5SShuanglin Wang 		    tfc_dir_2_str(tfc_info.dir), tfc_info.id);
66dd0191d5SShuanglin Wang 
67dd0191d5SShuanglin Wang 	/* Mark action */
68dd0191d5SShuanglin Wang 	rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
69*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
70dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed mark action processing\n");
71dd0191d5SShuanglin Wang 		return rc;
72dd0191d5SShuanglin Wang 	}
73dd0191d5SShuanglin Wang 
74dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
75dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
76dd0191d5SShuanglin Wang 	ulp_mapper_tcam_entry_dump("TCAM", idx, tbl, key, mask, remap);
77dd0191d5SShuanglin Wang #endif
78dd0191d5SShuanglin Wang #endif
79dd0191d5SShuanglin Wang 	return rc;
80dd0191d5SShuanglin Wang }
81dd0191d5SShuanglin Wang 
82dd0191d5SShuanglin Wang static uint32_t
83dd0191d5SShuanglin Wang ulp_mapper_tfc_wc_tcam_post_process(struct bnxt_ulp_device_params *dparms,
84dd0191d5SShuanglin Wang 				    struct ulp_blob *key,
85dd0191d5SShuanglin Wang 				    struct ulp_blob *tkey)
86dd0191d5SShuanglin Wang {
87dd0191d5SShuanglin Wang 	uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset;
88dd0191d5SShuanglin Wang 	uint32_t cword, i, rc;
89dd0191d5SShuanglin Wang 	int32_t pad;
90dd0191d5SShuanglin Wang 	uint8_t *val;
91dd0191d5SShuanglin Wang 
92dd0191d5SShuanglin Wang 	slice_width = dparms->wc_slice_width;
93dd0191d5SShuanglin Wang 	clen = dparms->wc_ctl_size_bits;
94dd0191d5SShuanglin Wang 	max_slices = dparms->wc_max_slices;
95dd0191d5SShuanglin Wang 	blen = ulp_blob_data_len_get(key);
96dd0191d5SShuanglin Wang 
97dd0191d5SShuanglin Wang 	/* Get the length of the key based on number of slices and width */
98dd0191d5SShuanglin Wang 	num_slices = 1;
99dd0191d5SShuanglin Wang 	tlen = slice_width;
100dd0191d5SShuanglin Wang 	while (tlen < blen &&
101dd0191d5SShuanglin Wang 	       num_slices <= max_slices) {
102dd0191d5SShuanglin Wang 		num_slices = num_slices << 1;
103dd0191d5SShuanglin Wang 		tlen = tlen << 1;
104dd0191d5SShuanglin Wang 	}
105dd0191d5SShuanglin Wang 
106*0c036a14SPeter Spreadborough 	if (unlikely(num_slices > max_slices)) {
107dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Key size (%d) too large for WC\n", blen);
108dd0191d5SShuanglin Wang 		return -EINVAL;
109dd0191d5SShuanglin Wang 	}
110dd0191d5SShuanglin Wang 
111dd0191d5SShuanglin Wang 	/* The key/mask may not be on a natural slice boundary, pad it */
112dd0191d5SShuanglin Wang 	pad = tlen - blen;
113*0c036a14SPeter Spreadborough 	if (unlikely(ulp_blob_pad_push(key, pad) < 0)) {
114dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Unable to pad key/mask\n");
115dd0191d5SShuanglin Wang 		return -EINVAL;
116dd0191d5SShuanglin Wang 	}
117dd0191d5SShuanglin Wang 
118dd0191d5SShuanglin Wang 	/* The new length accounts for the ctrl word length and num slices */
119dd0191d5SShuanglin Wang 	tlen = tlen + (clen + 1) * num_slices;
120*0c036a14SPeter Spreadborough 	if (unlikely(ulp_blob_init(tkey, tlen, key->byte_order))) {
121dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Unable to post process wc tcam entry\n");
122dd0191d5SShuanglin Wang 		return -EINVAL;
123dd0191d5SShuanglin Wang 	}
124dd0191d5SShuanglin Wang 
125dd0191d5SShuanglin Wang 	/* pad any remaining bits to do byte alignment */
126dd0191d5SShuanglin Wang 	pad = (slice_width + clen) * num_slices;
127dd0191d5SShuanglin Wang 	pad = ULP_BYTE_ROUND_OFF_8(pad) - pad;
128*0c036a14SPeter Spreadborough 	if (unlikely(ulp_blob_pad_push(tkey, pad) < 0)) {
129dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Unable to pad key/mask\n");
130dd0191d5SShuanglin Wang 		return -EINVAL;
131dd0191d5SShuanglin Wang 	}
132dd0191d5SShuanglin Wang 
133dd0191d5SShuanglin Wang 	/* Build the transformed key/mask */
134dd0191d5SShuanglin Wang 	cword = dparms->wc_mode_list[num_slices - 1];
135dd0191d5SShuanglin Wang 	cword = rte_cpu_to_be_32(cword);
136dd0191d5SShuanglin Wang 	offset = 0;
137dd0191d5SShuanglin Wang 	for (i = 0; i < num_slices; i++) {
138dd0191d5SShuanglin Wang 		val = ulp_blob_push_32(tkey, &cword, clen);
139*0c036a14SPeter Spreadborough 		if (unlikely(!val)) {
140dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Key ctrl word push failed\n");
141dd0191d5SShuanglin Wang 			return -EINVAL;
142dd0191d5SShuanglin Wang 		}
143dd0191d5SShuanglin Wang 		rc = ulp_blob_append(tkey, key, offset, slice_width);
144*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
145dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Key blob append failed\n");
146dd0191d5SShuanglin Wang 			return rc;
147dd0191d5SShuanglin Wang 		}
148dd0191d5SShuanglin Wang 		offset += slice_width;
149dd0191d5SShuanglin Wang 	}
150dd0191d5SShuanglin Wang 	blen = ulp_blob_data_len_get(tkey);
151dd0191d5SShuanglin Wang 	/* reverse the blob byte wise in reverse */
152dd0191d5SShuanglin Wang 	ulp_blob_perform_byte_reverse(tkey, ULP_BITS_2_BYTE(blen));
153dd0191d5SShuanglin Wang 	return 0;
154dd0191d5SShuanglin Wang }
155dd0191d5SShuanglin Wang 
156dd0191d5SShuanglin Wang static int32_t
157dd0191d5SShuanglin Wang ulp_mapper_tfc_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
158dd0191d5SShuanglin Wang 				struct bnxt_ulp_mapper_tbl_info *tbl)
159dd0191d5SShuanglin Wang {
160dd0191d5SShuanglin Wang 	struct bnxt_ulp_device_params *dparms = parms->device_params;
161dd0191d5SShuanglin Wang 	struct ulp_blob okey, omask, *key, *mask, data;
162dd0191d5SShuanglin Wang 	struct ulp_blob tkey, tmask; /* transform key and mask */
163dd0191d5SShuanglin Wang 	uint32_t alloc_tcam = 0, alloc_ident = 0, write_tcam = 0;
164dd0191d5SShuanglin Wang 	struct ulp_flow_db_res_params fid_parms = { 0 };
1652aa70990SKishore Padmanabha 	enum cfa_track_type tt = tbl->track_type;
166dd0191d5SShuanglin Wang 	enum bnxt_ulp_byte_order key_byte_order;
167dd0191d5SShuanglin Wang 	enum bnxt_ulp_byte_order res_byte_order;
168dd0191d5SShuanglin Wang 	struct bnxt_ulp_mapper_key_info	*kflds;
169dd0191d5SShuanglin Wang 	struct tfc_tcam_info tfc_inf = {0};
170dd0191d5SShuanglin Wang 	uint16_t key_sz_in_words = 0, key_sz_in_bits = 0;
171dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
172dd0191d5SShuanglin Wang 	uint32_t num_kflds, i;
173dd0191d5SShuanglin Wang 	uint32_t priority;
174dd0191d5SShuanglin Wang 	int32_t rc = 0, free_rc = 0;
175dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
176dd0191d5SShuanglin Wang 
177dd0191d5SShuanglin Wang 	/* Set the key and mask to the original key and mask. */
178dd0191d5SShuanglin Wang 	key = &okey;
179dd0191d5SShuanglin Wang 	mask = &omask;
180dd0191d5SShuanglin Wang 
181dd0191d5SShuanglin Wang 	switch (tbl->tbl_opcode) {
182dd0191d5SShuanglin Wang 	case BNXT_ULP_TCAM_TBL_OPC_ALLOC_IDENT:
183dd0191d5SShuanglin Wang 		alloc_ident = 1;
184dd0191d5SShuanglin Wang 		break;
185dd0191d5SShuanglin Wang 	case BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE:
186dd0191d5SShuanglin Wang 		alloc_ident = 1;
187dd0191d5SShuanglin Wang 		alloc_tcam = 1;
188dd0191d5SShuanglin Wang 		write_tcam = 1;
189dd0191d5SShuanglin Wang 		break;
190dd0191d5SShuanglin Wang 	case BNXT_ULP_TCAM_TBL_OPC_NOT_USED:
191dd0191d5SShuanglin Wang 	case BNXT_ULP_TCAM_TBL_OPC_LAST:
192dd0191d5SShuanglin Wang 	default:
193dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid tcam table opcode %d\n",
194dd0191d5SShuanglin Wang 			     tbl->tbl_opcode);
195dd0191d5SShuanglin Wang 		return -EINVAL;
196dd0191d5SShuanglin Wang 	}
197dd0191d5SShuanglin Wang 
198dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx);
199*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
200dd0191d5SShuanglin Wang 		PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer");
201dd0191d5SShuanglin Wang 		return -EINVAL;
202dd0191d5SShuanglin Wang 	}
203dd0191d5SShuanglin Wang 
204*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(parms->ulp_ctx, &fw_fid))) {
205dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func_id\n");
206dd0191d5SShuanglin Wang 		return -EINVAL;
207dd0191d5SShuanglin Wang 	}
208dd0191d5SShuanglin Wang 
209dd0191d5SShuanglin Wang 	/* Allocate the identifiers */
210dd0191d5SShuanglin Wang 	if (alloc_ident) {
211dd0191d5SShuanglin Wang 		rc = ulp_mapper_tcam_tbl_ident_alloc(parms, tbl);
212*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
213dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Failed to alloc identifier\n");
214dd0191d5SShuanglin Wang 			return rc;
215dd0191d5SShuanglin Wang 		}
216dd0191d5SShuanglin Wang 	}
217dd0191d5SShuanglin Wang 
218dd0191d5SShuanglin Wang 	/* If no allocation or write is needed, then just exit */
219*0c036a14SPeter Spreadborough 	if (unlikely(!alloc_tcam && !write_tcam))
220dd0191d5SShuanglin Wang 		return rc;
221dd0191d5SShuanglin Wang 
222dd0191d5SShuanglin Wang 	/* Initialize the blobs for write */
223dd0191d5SShuanglin Wang 	if (tbl->resource_type == CFA_RSUBTYPE_TCAM_WC)
224dd0191d5SShuanglin Wang 		key_byte_order = dparms->wc_key_byte_order;
225dd0191d5SShuanglin Wang 	else
226dd0191d5SShuanglin Wang 		key_byte_order = dparms->key_byte_order;
227dd0191d5SShuanglin Wang 
228dd0191d5SShuanglin Wang 	res_byte_order = dparms->result_byte_order;
229*0c036a14SPeter Spreadborough 	if (unlikely(ulp_blob_init(key, tbl->blob_key_bit_size, key_byte_order) ||
230c569279aSShuanglin Wang 		     ulp_blob_init(mask, tbl->blob_key_bit_size, key_byte_order) ||
231*0c036a14SPeter Spreadborough 		     ulp_blob_init(&data, tbl->result_bit_size, res_byte_order))) {
232dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "blob inits failed.\n");
233dd0191d5SShuanglin Wang 		return -EINVAL;
234dd0191d5SShuanglin Wang 	}
235dd0191d5SShuanglin Wang 
236dd0191d5SShuanglin Wang 	/* Get the key fields and update the key blob */
237dd0191d5SShuanglin Wang 	if (tbl->key_recipe_opcode == BNXT_ULP_KEY_RECIPE_OPC_DYN_KEY)
238dd0191d5SShuanglin Wang 		kflds = ulp_mapper_key_recipe_fields_get(parms, tbl, &num_kflds);
239dd0191d5SShuanglin Wang 	else
240dd0191d5SShuanglin Wang 		kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
241*0c036a14SPeter Spreadborough 	if (unlikely(!kflds || !num_kflds)) {
242dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get key fields\n");
243dd0191d5SShuanglin Wang 		return -EINVAL;
244dd0191d5SShuanglin Wang 	}
245dd0191d5SShuanglin Wang 
246dd0191d5SShuanglin Wang 	for (i = 0; i < num_kflds; i++) {
247dd0191d5SShuanglin Wang 		/* Setup the key */
248dd0191d5SShuanglin Wang 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
249dd0191d5SShuanglin Wang 						  &kflds[i].field_info_spec,
250dd0191d5SShuanglin Wang 						  key, 1, "TCAM Key");
251*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
252dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Key field set failed %s\n",
253dd0191d5SShuanglin Wang 				     kflds[i].field_info_spec.description);
254dd0191d5SShuanglin Wang 			return rc;
255dd0191d5SShuanglin Wang 		}
256dd0191d5SShuanglin Wang 
257dd0191d5SShuanglin Wang 		/* Setup the mask */
258dd0191d5SShuanglin Wang 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
259dd0191d5SShuanglin Wang 						  &kflds[i].field_info_mask,
260dd0191d5SShuanglin Wang 						  mask, 0, "TCAM Mask");
261*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
262dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Mask field set failed %s\n",
263dd0191d5SShuanglin Wang 				     kflds[i].field_info_mask.description);
264dd0191d5SShuanglin Wang 			return rc;
265dd0191d5SShuanglin Wang 		}
266dd0191d5SShuanglin Wang 	}
267dd0191d5SShuanglin Wang 
268dd0191d5SShuanglin Wang 	/* For wild card tcam perform the post process to swap the blob */
269dd0191d5SShuanglin Wang 	if (tbl->resource_type == CFA_RSUBTYPE_TCAM_WC) {
270dd0191d5SShuanglin Wang 		/* Sets up the slices for writing to the WC TCAM */
271dd0191d5SShuanglin Wang 		rc = ulp_mapper_tfc_wc_tcam_post_process(dparms, key, &tkey);
272*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
273dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
274dd0191d5SShuanglin Wang 				     "Failed to post proc WC key.\n");
275dd0191d5SShuanglin Wang 			return rc;
276dd0191d5SShuanglin Wang 		}
277dd0191d5SShuanglin Wang 		/* Sets up the slices for writing to the WC TCAM */
278dd0191d5SShuanglin Wang 		rc = ulp_mapper_tfc_wc_tcam_post_process(dparms, mask, &tmask);
279*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
280dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
281dd0191d5SShuanglin Wang 				     "Failed to post proc WC mask.\n");
282dd0191d5SShuanglin Wang 			return rc;
283dd0191d5SShuanglin Wang 		}
284dd0191d5SShuanglin Wang 		key = &tkey;
285dd0191d5SShuanglin Wang 		mask = &tmask;
286dd0191d5SShuanglin Wang 	}
287dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
288dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
289dd0191d5SShuanglin Wang 	ulp_mapper_tcam_entry_dump("TCAM", 0, tbl, key, mask, &data);
290dd0191d5SShuanglin Wang #endif
291dd0191d5SShuanglin Wang #endif
292dd0191d5SShuanglin Wang 
293dd0191d5SShuanglin Wang 	if (alloc_tcam) {
294dd0191d5SShuanglin Wang 		tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx);
295*0c036a14SPeter Spreadborough 		if (unlikely(tfcp == NULL)) {
296dd0191d5SShuanglin Wang 			PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer");
297dd0191d5SShuanglin Wang 			return -EINVAL;
298dd0191d5SShuanglin Wang 		}
299dd0191d5SShuanglin Wang 		/* calculate the entry priority*/
300dd0191d5SShuanglin Wang 		rc = ulp_mapper_priority_opc_process(parms, tbl,
301dd0191d5SShuanglin Wang 						     &priority);
302*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
303dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "entry priority process failed\n");
304dd0191d5SShuanglin Wang 			return rc;
305dd0191d5SShuanglin Wang 		}
306dd0191d5SShuanglin Wang 
307dd0191d5SShuanglin Wang 		/* allocate the tcam entry, only need the length */
308dd0191d5SShuanglin Wang 		(void)ulp_blob_data_get(key, &key_sz_in_bits);
309dd0191d5SShuanglin Wang 		key_sz_in_words = ULP_BITS_2_BYTE(key_sz_in_bits);
310dd0191d5SShuanglin Wang 		tfc_inf.dir = tbl->direction; /* PKB.need an api */
311dd0191d5SShuanglin Wang 		tfc_inf.rsubtype = tbl->resource_type;
312dd0191d5SShuanglin Wang 
313dd0191d5SShuanglin Wang 		rc = tfc_tcam_alloc(tfcp, fw_fid, tt, priority,
314dd0191d5SShuanglin Wang 				    key_sz_in_words, &tfc_inf);
315*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
316dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "TCAM Alloc failed, status:%d\n", rc);
317dd0191d5SShuanglin Wang 			return rc;
318dd0191d5SShuanglin Wang 		}
319dd0191d5SShuanglin Wang 
320dd0191d5SShuanglin Wang 		/* Write the tcam index into the regfile*/
321*0c036a14SPeter Spreadborough 		if (unlikely(ulp_regfile_write(parms->regfile, tbl->tbl_operand,
322*0c036a14SPeter Spreadborough 					       (uint64_t)rte_cpu_to_be_64(tfc_inf.id)))) {
323dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Regfile[%d] write failed.\n",
324dd0191d5SShuanglin Wang 				     tbl->tbl_operand);
325dd0191d5SShuanglin Wang 			/* Need to free the tcam idx, so goto error */
326dd0191d5SShuanglin Wang 			goto error;
327dd0191d5SShuanglin Wang 		}
328dd0191d5SShuanglin Wang 	}
329dd0191d5SShuanglin Wang 
330dd0191d5SShuanglin Wang 	if (write_tcam) {
331dd0191d5SShuanglin Wang 		/* Create the result blob */
332dd0191d5SShuanglin Wang 		rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
333dd0191d5SShuanglin Wang 						 "TCAM Result");
334dd0191d5SShuanglin Wang 		/* write the tcam entry */
335dd0191d5SShuanglin Wang 		if (!rc)
336dd0191d5SShuanglin Wang 			rc = ulp_mapper_tfc_tcam_tbl_entry_write(parms,
337dd0191d5SShuanglin Wang 								 tbl, key,
338dd0191d5SShuanglin Wang 								 mask, &data,
339dd0191d5SShuanglin Wang 								 tfc_inf.id);
340dd0191d5SShuanglin Wang 	}
341dd0191d5SShuanglin Wang 	if (rc)
342dd0191d5SShuanglin Wang 		goto error;
343dd0191d5SShuanglin Wang 
344dd0191d5SShuanglin Wang 	/* Add the tcam index to the flow database */
345dd0191d5SShuanglin Wang 	fid_parms.direction = tbl->direction;
346dd0191d5SShuanglin Wang 	fid_parms.resource_func	= tbl->resource_func;
347dd0191d5SShuanglin Wang 	fid_parms.resource_type	= tbl->resource_type;
348dd0191d5SShuanglin Wang 	fid_parms.critical_resource = tbl->critical_resource;
349dd0191d5SShuanglin Wang 	fid_parms.resource_hndl	= tfc_inf.id;
350dd0191d5SShuanglin Wang 	ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
351dd0191d5SShuanglin Wang 
352dd0191d5SShuanglin Wang 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
353*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
354dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n",
355dd0191d5SShuanglin Wang 			     rc);
356dd0191d5SShuanglin Wang 		/* Need to free the identifier, so goto error */
357dd0191d5SShuanglin Wang 		goto error;
358dd0191d5SShuanglin Wang 	}
359dd0191d5SShuanglin Wang 
360dd0191d5SShuanglin Wang 	return 0;
361dd0191d5SShuanglin Wang error:
362dd0191d5SShuanglin Wang 	free_rc = tfc_tcam_free(tfcp, fw_fid, &tfc_inf);
363dd0191d5SShuanglin Wang 	if (free_rc)
364dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "TCAM free failed on error, status:%d\n",
365dd0191d5SShuanglin Wang 			     free_rc);
366dd0191d5SShuanglin Wang 	return rc;
367dd0191d5SShuanglin Wang }
368dd0191d5SShuanglin Wang 
369dd0191d5SShuanglin Wang static const char * const mpc_error_str[] = {
370dd0191d5SShuanglin Wang 	"OK",
371dd0191d5SShuanglin Wang 	"Unsupported Opcode",
372dd0191d5SShuanglin Wang 	"Bad Format",
373dd0191d5SShuanglin Wang 	"Invalid Scope",
374dd0191d5SShuanglin Wang 	"Bad Address",
375dd0191d5SShuanglin Wang 	"Cache Error",
376dd0191d5SShuanglin Wang 	"EM Miss",
377dd0191d5SShuanglin Wang 	"Duplicate Entry",
378dd0191d5SShuanglin Wang 	"No Events",
379dd0191d5SShuanglin Wang 	"EM Abort"
380dd0191d5SShuanglin Wang };
381dd0191d5SShuanglin Wang 
382dd0191d5SShuanglin Wang /*
383dd0191d5SShuanglin Wang  * TBD: Temporary swap until a more generic solution is designed
384dd0191d5SShuanglin Wang  *
385dd0191d5SShuanglin Wang  * blob [inout] A byte array that is being edited in-place
386dd0191d5SShuanglin Wang  * block_sz [in] The size of the blocks in bytes to swap
387dd0191d5SShuanglin Wang  *
388dd0191d5SShuanglin Wang  * The length of the blob is assumed to be a multiple of block_sz
389dd0191d5SShuanglin Wang  */
390dd0191d5SShuanglin Wang static int32_t
391dd0191d5SShuanglin Wang ulp_mapper_blob_block_swap(struct ulp_blob *blob, uint32_t block_sz)
392dd0191d5SShuanglin Wang {
393dd0191d5SShuanglin Wang 	uint8_t data[block_sz]; /* size of a block for temp storage */
394dd0191d5SShuanglin Wang 	uint16_t num_words, data_sz;
395dd0191d5SShuanglin Wang 	uint8_t *pdata;
396dd0191d5SShuanglin Wang 	int i;
397dd0191d5SShuanglin Wang 
398dd0191d5SShuanglin Wang 	/* Shouldn't happen since it is internal function, but check anyway */
399*0c036a14SPeter Spreadborough 	if (unlikely(blob == NULL || !block_sz)) {
400dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid arguments\n");
401dd0191d5SShuanglin Wang 		return -EINVAL;
402dd0191d5SShuanglin Wang 	}
403dd0191d5SShuanglin Wang 
404dd0191d5SShuanglin Wang 	pdata = ulp_blob_data_get(blob, &data_sz);
405dd0191d5SShuanglin Wang 	data_sz = ULP_BITS_2_BYTE(data_sz);
406*0c036a14SPeter Spreadborough 	if (unlikely(!data_sz || (data_sz % block_sz) != 0)) {
407dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "length(%d) not a multiple of %d\n",
408dd0191d5SShuanglin Wang 			     data_sz, block_sz);
409dd0191d5SShuanglin Wang 		return -EINVAL;
410dd0191d5SShuanglin Wang 	}
411dd0191d5SShuanglin Wang 
412dd0191d5SShuanglin Wang 	num_words = data_sz / block_sz;
413dd0191d5SShuanglin Wang 	for (i = 0; i < num_words / 2; i++) {
414dd0191d5SShuanglin Wang 		memcpy(data, &pdata[i * block_sz], block_sz);
415dd0191d5SShuanglin Wang 		memcpy(&pdata[i * block_sz],
416dd0191d5SShuanglin Wang 		       &pdata[(num_words - 1 - i) * block_sz], block_sz);
417dd0191d5SShuanglin Wang 		memcpy(&pdata[(num_words - 1 - i) * block_sz],
418dd0191d5SShuanglin Wang 		       data, block_sz);
419dd0191d5SShuanglin Wang 	}
420dd0191d5SShuanglin Wang 	return 0;
421dd0191d5SShuanglin Wang }
422dd0191d5SShuanglin Wang 
423dd0191d5SShuanglin Wang static int
424dd0191d5SShuanglin Wang ulp_mapper_tfc_mpc_batch_end(struct tfc *tfcp,
425dd0191d5SShuanglin Wang 			     struct tfc_mpc_batch_info_t *batch_info)
426dd0191d5SShuanglin Wang {
427dd0191d5SShuanglin Wang 	uint32_t i;
428dd0191d5SShuanglin Wang 	int rc;
429dd0191d5SShuanglin Wang 
430dd0191d5SShuanglin Wang 	rc = tfc_mpc_batch_end(tfcp, batch_info);
431dd0191d5SShuanglin Wang 	if (unlikely(rc))
432dd0191d5SShuanglin Wang 		return rc;
433dd0191d5SShuanglin Wang 
434dd0191d5SShuanglin Wang 	for (i = 0; i < batch_info->count; i++) {
435dd0191d5SShuanglin Wang 		if (!batch_info->result[i])
436dd0191d5SShuanglin Wang 			continue;
437dd0191d5SShuanglin Wang 
438dd0191d5SShuanglin Wang 		switch (batch_info->comp_info[i].type) {
439dd0191d5SShuanglin Wang 		case TFC_MPC_EM_INSERT:
440dd0191d5SShuanglin Wang 			batch_info->em_error = batch_info->result[i];
441dd0191d5SShuanglin Wang 			break;
442dd0191d5SShuanglin Wang 		default:
443dd0191d5SShuanglin Wang 			if (batch_info->result[i] && !batch_info->error)
444dd0191d5SShuanglin Wang 				batch_info->error = batch_info->result[i];
445dd0191d5SShuanglin Wang 			break;
446dd0191d5SShuanglin Wang 		}
447dd0191d5SShuanglin Wang 	}
448dd0191d5SShuanglin Wang 
449dd0191d5SShuanglin Wang 	return rc;
450dd0191d5SShuanglin Wang }
451dd0191d5SShuanglin Wang 
452dd0191d5SShuanglin Wang static bool
453dd0191d5SShuanglin Wang ulp_mapper_tfc_mpc_batch_started(struct tfc_mpc_batch_info_t *batch_info)
454dd0191d5SShuanglin Wang {
455dd0191d5SShuanglin Wang 	return tfc_mpc_batch_started(batch_info);
456dd0191d5SShuanglin Wang }
457dd0191d5SShuanglin Wang 
458dd0191d5SShuanglin Wang static int32_t
459dd0191d5SShuanglin Wang ulp_mapper_tfc_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
460dd0191d5SShuanglin Wang 			      struct bnxt_ulp_mapper_tbl_info *tbl,
461dd0191d5SShuanglin Wang 			      void *error)
462dd0191d5SShuanglin Wang {
463dd0191d5SShuanglin Wang 	struct bnxt_ulp_device_params *dparms = parms->device_params;
464dd0191d5SShuanglin Wang 	struct bnxt_ulp_mapper_key_info	*kflds;
465dd0191d5SShuanglin Wang 	struct tfc_em_delete_parms free_parms = { 0 };
466dd0191d5SShuanglin Wang 	struct tfc_em_insert_parms iparms = { 0 };
467dd0191d5SShuanglin Wang 	struct ulp_flow_db_res_params fid_parms = { 0 };
468dd0191d5SShuanglin Wang 	uint16_t tmplen, key_len, align_len_bits;
469dd0191d5SShuanglin Wang 	enum bnxt_ulp_byte_order byte_order;
470dd0191d5SShuanglin Wang 	struct ulp_blob key, data;
471dd0191d5SShuanglin Wang 	uint32_t i, num_kflds;
472dd0191d5SShuanglin Wang 	uint64_t handle = 0;
473dd0191d5SShuanglin Wang 	struct tfc *tfcp;
474dd0191d5SShuanglin Wang 	int32_t	trc = 0;
475dd0191d5SShuanglin Wang 	uint8_t tsid = 0;
476dd0191d5SShuanglin Wang 	int32_t rc = 0;
477dd0191d5SShuanglin Wang 
478dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx);
479*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
480dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n");
481dd0191d5SShuanglin Wang 		return -EINVAL;
482dd0191d5SShuanglin Wang 	}
483dd0191d5SShuanglin Wang 
484dd0191d5SShuanglin Wang 	if (tbl->key_recipe_opcode == BNXT_ULP_KEY_RECIPE_OPC_DYN_KEY)
485dd0191d5SShuanglin Wang 		kflds = ulp_mapper_key_recipe_fields_get(parms, tbl, &num_kflds);
486dd0191d5SShuanglin Wang 	else
487dd0191d5SShuanglin Wang 		kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
488*0c036a14SPeter Spreadborough 	if (unlikely(!kflds || !num_kflds)) {
489dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get key fields\n");
490dd0191d5SShuanglin Wang 		return -EINVAL;
491dd0191d5SShuanglin Wang 	}
492dd0191d5SShuanglin Wang 
493dd0191d5SShuanglin Wang 	byte_order = dparms->em_byte_order;
494dd0191d5SShuanglin Wang 	/* Initialize the key/result blobs */
495*0c036a14SPeter Spreadborough 	if (unlikely(ulp_blob_init(&key, tbl->blob_key_bit_size, byte_order) ||
496*0c036a14SPeter Spreadborough 		     ulp_blob_init(&data, tbl->result_bit_size, byte_order))) {
497dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "blob inits failed.\n");
498dd0191d5SShuanglin Wang 		return -EINVAL;
499dd0191d5SShuanglin Wang 	}
500dd0191d5SShuanglin Wang 
501dd0191d5SShuanglin Wang 	/* create the key */
502dd0191d5SShuanglin Wang 	for (i = 0; i < num_kflds; i++) {
503dd0191d5SShuanglin Wang 		/* Setup the key */
504dd0191d5SShuanglin Wang 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
505dd0191d5SShuanglin Wang 						  &kflds[i].field_info_spec,
506dd0191d5SShuanglin Wang 						  &key, 1, "EM Key");
507*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
508dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Key field set failed.\n");
509dd0191d5SShuanglin Wang 			return rc;
510dd0191d5SShuanglin Wang 		}
511dd0191d5SShuanglin Wang 	}
512dd0191d5SShuanglin Wang 	/* add padding to make sure key is at record boundary */
513dd0191d5SShuanglin Wang 	key_len = ulp_blob_data_len_get(&key);
514dd0191d5SShuanglin Wang 	if (key_len > dparms->em_blk_align_bits) {
515dd0191d5SShuanglin Wang 		key_len = key_len - dparms->em_blk_align_bits;
516dd0191d5SShuanglin Wang 		align_len_bits = dparms->em_blk_size_bits -
517dd0191d5SShuanglin Wang 			(key_len % dparms->em_blk_size_bits);
518dd0191d5SShuanglin Wang 	} else {
519dd0191d5SShuanglin Wang 		align_len_bits = dparms->em_blk_align_bits - key_len;
520dd0191d5SShuanglin Wang 	}
521dd0191d5SShuanglin Wang 
522dd0191d5SShuanglin Wang 	ulp_blob_pad_push(&key, align_len_bits);
523dd0191d5SShuanglin Wang 	key_len = ULP_BITS_2_BYTE(ulp_blob_data_len_get(&key));
524dd0191d5SShuanglin Wang 	ulp_blob_perform_byte_reverse(&key, key_len);
525dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
526dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
527dd0191d5SShuanglin Wang 	ulp_mapper_result_dump("EM Key", tbl, &key);
528dd0191d5SShuanglin Wang #endif
529dd0191d5SShuanglin Wang #endif
530dd0191d5SShuanglin Wang 	/* Create the result data blob */
531dd0191d5SShuanglin Wang 	rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
532*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
533dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to build the result blob\n");
534dd0191d5SShuanglin Wang 		return rc;
535dd0191d5SShuanglin Wang 	}
536dd0191d5SShuanglin Wang 	ulp_blob_pad_align(&data, dparms->em_blk_align_bits);
537dd0191d5SShuanglin Wang 	key_len = ULP_BITS_2_BYTE(ulp_blob_data_len_get(&data));
538dd0191d5SShuanglin Wang 	ulp_blob_perform_byte_reverse(&data, key_len);
539dd0191d5SShuanglin Wang 
540dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
541dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
542dd0191d5SShuanglin Wang 	ulp_mapper_result_dump("EM Result", tbl, &data);
543dd0191d5SShuanglin Wang #endif
544dd0191d5SShuanglin Wang #endif
545dd0191d5SShuanglin Wang 	rc = ulp_blob_append(&key, &data, 0, dparms->em_blk_align_bits);
546*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
547dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "EM Failed to append the result to key(%d)",
548dd0191d5SShuanglin Wang 			     rc);
549dd0191d5SShuanglin Wang 		return rc;
550dd0191d5SShuanglin Wang 	}
551dd0191d5SShuanglin Wang 	/* TBD: Need to come up with a more generic way to know when to swap,
552dd0191d5SShuanglin Wang 	 * this is fine for now as this driver only supports this device.
553dd0191d5SShuanglin Wang 	 */
554dd0191d5SShuanglin Wang 	rc = ulp_mapper_blob_block_swap(&key,
555dd0191d5SShuanglin Wang 					ULP_BITS_2_BYTE(dparms->em_blk_size_bits));
556dd0191d5SShuanglin Wang 	/* Error printed within function, just return on error */
557*0c036a14SPeter Spreadborough 	if (unlikely(rc))
558dd0191d5SShuanglin Wang 		return rc;
559dd0191d5SShuanglin Wang 
560dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
561dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
562dd0191d5SShuanglin Wang 	ulp_mapper_result_dump("EM Merged Result", tbl, &key);
563dd0191d5SShuanglin Wang #endif
564dd0191d5SShuanglin Wang #endif
565dd0191d5SShuanglin Wang 	iparms.dir		 = tbl->direction;
566dd0191d5SShuanglin Wang 	iparms.lkup_key_data	 = ulp_blob_data_get(&key, &tmplen);
567dd0191d5SShuanglin Wang 	iparms.lkup_key_sz_words = ULP_BITS_TO_32_BYTE_WORD(tmplen);
568dd0191d5SShuanglin Wang 	iparms.key_data		 = NULL;
569dd0191d5SShuanglin Wang 	iparms.key_sz_bits	 = 0;
570dd0191d5SShuanglin Wang 	iparms.flow_handle	 = &handle;
571dd0191d5SShuanglin Wang 	iparms.batch_info	 = &parms->batch_info;
572dd0191d5SShuanglin Wang 
573dd0191d5SShuanglin Wang 	rc = bnxt_ulp_cntxt_tsid_get(parms->ulp_ctx, &tsid);
574*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
575dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get the table scope\n");
576dd0191d5SShuanglin Wang 		return rc;
577dd0191d5SShuanglin Wang 	}
578dd0191d5SShuanglin Wang 
579dd0191d5SShuanglin Wang 	rc = tfc_em_insert(tfcp, tsid, &iparms);
580dd0191d5SShuanglin Wang 
581dd0191d5SShuanglin Wang 	if (likely(tfc_mpc_batch_started(&parms->batch_info))) {
582dd0191d5SShuanglin Wang 		int trc;
583dd0191d5SShuanglin Wang 		int em_index = parms->batch_info.count - 1;
584dd0191d5SShuanglin Wang 
585dd0191d5SShuanglin Wang 		parms->batch_info.em_hdl[em_index] = *iparms.flow_handle;
586dd0191d5SShuanglin Wang 
587dd0191d5SShuanglin Wang 		trc = ulp_mapper_tfc_mpc_batch_end(tfcp, &parms->batch_info);
588dd0191d5SShuanglin Wang 		if (unlikely(trc))
589dd0191d5SShuanglin Wang 			return trc;
590dd0191d5SShuanglin Wang 
591dd0191d5SShuanglin Wang 		*iparms.flow_handle = parms->batch_info.em_hdl[em_index];
592dd0191d5SShuanglin Wang 
593dd0191d5SShuanglin Wang 		/* Has there been an error? */
594dd0191d5SShuanglin Wang 		if (unlikely(parms->batch_info.error)) {
595dd0191d5SShuanglin Wang 			/* If there's not an EM error the entry will need to
596dd0191d5SShuanglin Wang 			 * be deleted
597dd0191d5SShuanglin Wang 			 */
598dd0191d5SShuanglin Wang 			if (!parms->batch_info.em_error) {
599dd0191d5SShuanglin Wang 				rc = parms->batch_info.error;
600dd0191d5SShuanglin Wang 				goto error;
601dd0191d5SShuanglin Wang 			}
602dd0191d5SShuanglin Wang 		}
603dd0191d5SShuanglin Wang 
604dd0191d5SShuanglin Wang 		rc = parms->batch_info.em_error;
605dd0191d5SShuanglin Wang 	}
606dd0191d5SShuanglin Wang 
607dd0191d5SShuanglin Wang 	if (unlikely(rc)) {
608af50070eSKishore Padmanabha 		/* Set the error flag in reg file */
609af50070eSKishore Padmanabha 		if (tbl->tbl_opcode == BNXT_ULP_EM_TBL_OPC_WR_REGFILE) {
610af50070eSKishore Padmanabha 			uint64_t val = 0;
611dd0191d5SShuanglin Wang 
612be4732e8SMike Baucom 			/* hash collision */
613*0c036a14SPeter Spreadborough 			if (unlikely(rc == -E2BIG))
614be4732e8SMike Baucom 				BNXT_DRV_DBG(DEBUG, "Duplicate EM entry\n");
615be4732e8SMike Baucom 
616be4732e8SMike Baucom 			/* over max flows */
617be4732e8SMike Baucom 			if (rc == -ENOMEM) {
618af50070eSKishore Padmanabha 				val = 1;
619af50070eSKishore Padmanabha 				rc = 0;
620af50070eSKishore Padmanabha 				BNXT_DRV_DBG(DEBUG,
621af50070eSKishore Padmanabha 					     "Fail to insert EM, shall add to wc\n");
622af50070eSKishore Padmanabha 			}
623af50070eSKishore Padmanabha 			ulp_regfile_write(parms->regfile, tbl->tbl_operand,
624af50070eSKishore Padmanabha 					  rte_cpu_to_be_64(val));
625af50070eSKishore Padmanabha 		}
626be4732e8SMike Baucom 
627be4732e8SMike Baucom 		if (rc && rc != -E2BIG)
628af50070eSKishore Padmanabha 			BNXT_DRV_DBG(ERR,
629af50070eSKishore Padmanabha 				     "Failed to insert em entry rc=%d.\n", rc);
630be4732e8SMike Baucom 
631af50070eSKishore Padmanabha 		if (rc && error != NULL && tfc_is_mpc_error(rc))
632af50070eSKishore Padmanabha 			rte_flow_error_set((struct rte_flow_error *)error, EIO,
633af50070eSKishore Padmanabha 					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
634af50070eSKishore Padmanabha 					   mpc_error_str[rc * -1]);
635dd0191d5SShuanglin Wang 		return rc;
636dd0191d5SShuanglin Wang 	}
637dd0191d5SShuanglin Wang 
638dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
639dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
640dd0191d5SShuanglin Wang 	ulp_mapper_tfc_em_dump("EM", &key, &iparms);
641dd0191d5SShuanglin Wang #endif
642dd0191d5SShuanglin Wang #endif
643dd0191d5SShuanglin Wang 	/* Mark action process */
644dd0191d5SShuanglin Wang 	rc = ulp_mapper_mark_gfid_process(parms, tbl, *iparms.flow_handle);
645*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
646dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to add mark to flow\n");
647dd0191d5SShuanglin Wang 		goto error;
648dd0191d5SShuanglin Wang 	}
649dd0191d5SShuanglin Wang 
650dd0191d5SShuanglin Wang 	/* Link the EM resource to the flow in the flow db */
651dd0191d5SShuanglin Wang 	memset(&fid_parms, 0, sizeof(fid_parms));
652dd0191d5SShuanglin Wang 	fid_parms.direction = tbl->direction;
653dd0191d5SShuanglin Wang 	fid_parms.resource_func = tbl->resource_func;
654dd0191d5SShuanglin Wang 	fid_parms.resource_type	= tbl->resource_type;
655dd0191d5SShuanglin Wang 	fid_parms.critical_resource = tbl->critical_resource;
656dd0191d5SShuanglin Wang 	fid_parms.resource_hndl = *iparms.flow_handle;
657dd0191d5SShuanglin Wang 
658dd0191d5SShuanglin Wang 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
659*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
660dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
661dd0191d5SShuanglin Wang 		/* Need to free the identifier, so goto error */
662dd0191d5SShuanglin Wang 		goto error;
663dd0191d5SShuanglin Wang 	}
664dd0191d5SShuanglin Wang 
665dd0191d5SShuanglin Wang 	return 0;
666dd0191d5SShuanglin Wang error:
667dd0191d5SShuanglin Wang 	free_parms.dir = iparms.dir;
668dd0191d5SShuanglin Wang 	free_parms.flow_handle = *iparms.flow_handle;
669dd0191d5SShuanglin Wang 	free_parms.batch_info = &parms->batch_info;
670dd0191d5SShuanglin Wang 
671dd0191d5SShuanglin Wang 	trc = tfc_em_delete(tfcp, &free_parms);
672dd0191d5SShuanglin Wang 	if (trc)
673dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to delete EM entry on failed add\n");
674dd0191d5SShuanglin Wang 
675dd0191d5SShuanglin Wang 	return rc;
676dd0191d5SShuanglin Wang }
677dd0191d5SShuanglin Wang 
678dd0191d5SShuanglin Wang static int32_t
679dd0191d5SShuanglin Wang ulp_mapper_tfc_em_entry_free(struct bnxt_ulp_context *ulp,
680dd0191d5SShuanglin Wang 			     struct ulp_flow_db_res_params *res,
681dd0191d5SShuanglin Wang 			     void *error)
682dd0191d5SShuanglin Wang {
683dd0191d5SShuanglin Wang 	struct tfc_em_delete_parms free_parms = { 0 };
684dd0191d5SShuanglin Wang 	struct tfc *tfcp;
685dd0191d5SShuanglin Wang 	int32_t rc = 0;
686dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
687dd0191d5SShuanglin Wang 	struct tfc_mpc_batch_info_t batch_info;
688dd0191d5SShuanglin Wang 
689dd0191d5SShuanglin Wang 	memset(&batch_info, 0, sizeof(batch_info));
690dd0191d5SShuanglin Wang 
691*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(ulp, &fw_fid))) {
692dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func_id\n");
693dd0191d5SShuanglin Wang 		return -EINVAL;
694dd0191d5SShuanglin Wang 	}
695dd0191d5SShuanglin Wang 
696dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(ulp);
697*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
698dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n");
699dd0191d5SShuanglin Wang 		return -EINVAL;
700dd0191d5SShuanglin Wang 	}
701dd0191d5SShuanglin Wang 
702dd0191d5SShuanglin Wang 	free_parms.dir = (enum cfa_dir)res->direction;
703dd0191d5SShuanglin Wang 	free_parms.flow_handle = res->resource_hndl;
704dd0191d5SShuanglin Wang 	free_parms.batch_info = &batch_info;
705dd0191d5SShuanglin Wang 
706dd0191d5SShuanglin Wang 	rc = tfc_em_delete(tfcp, &free_parms);
707dd0191d5SShuanglin Wang 	if (rc) {
708dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
709dd0191d5SShuanglin Wang 			     "Failed to delete EM entry, res = 0x%" PRIx64 "\n",
710dd0191d5SShuanglin Wang 			     res->resource_hndl);
711dd0191d5SShuanglin Wang 		if (error != NULL && tfc_is_mpc_error(rc)) {
712dd0191d5SShuanglin Wang 			struct rte_flow_error *fe = (struct rte_flow_error *)error;
713dd0191d5SShuanglin Wang 			rte_flow_error_set(fe,
714dd0191d5SShuanglin Wang 					   EIO,
715dd0191d5SShuanglin Wang 					   RTE_FLOW_ERROR_TYPE_HANDLE,
716dd0191d5SShuanglin Wang 					   NULL,
717dd0191d5SShuanglin Wang 					   mpc_error_str[rc * -1]);
718dd0191d5SShuanglin Wang 		}
719dd0191d5SShuanglin Wang 	} else {
720dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(DEBUG, "Deleted EM entry, res = 0x%" PRIx64 "\n",
721dd0191d5SShuanglin Wang 			     res->resource_hndl);
722dd0191d5SShuanglin Wang 	}
723dd0191d5SShuanglin Wang 
724dd0191d5SShuanglin Wang 	return rc;
725dd0191d5SShuanglin Wang }
726dd0191d5SShuanglin Wang 
727dd0191d5SShuanglin Wang static uint16_t
728dd0191d5SShuanglin Wang ulp_mapper_tfc_dyn_blob_size_get(struct bnxt_ulp_mapper_parms *mparms,
729dd0191d5SShuanglin Wang 				 struct bnxt_ulp_mapper_tbl_info *tbl)
730dd0191d5SShuanglin Wang {
731dd0191d5SShuanglin Wang 	struct bnxt_ulp_device_params *d_params = mparms->device_params;
732dd0191d5SShuanglin Wang 
733dd0191d5SShuanglin Wang 	if (d_params->dynamic_sram_en) {
734dd0191d5SShuanglin Wang 		switch (tbl->resource_type) {
735dd0191d5SShuanglin Wang 		/* TBD: add more types here */
736dd0191d5SShuanglin Wang 		case CFA_BLD_ACT_OBJ_TYPE_STAT:
737dd0191d5SShuanglin Wang 		case CFA_BLD_ACT_OBJ_TYPE_ENCAP:
738dd0191d5SShuanglin Wang 		case CFA_BLD_ACT_OBJ_TYPE_MODIFY:
739dd0191d5SShuanglin Wang 			/* return max size */
740dd0191d5SShuanglin Wang 			return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
741dd0191d5SShuanglin Wang 		default:
742dd0191d5SShuanglin Wang 			break;
743dd0191d5SShuanglin Wang 		}
744dd0191d5SShuanglin Wang 	} else if (tbl->encap_num_fields) {
745dd0191d5SShuanglin Wang 		return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
746dd0191d5SShuanglin Wang 	}
747dd0191d5SShuanglin Wang 	return tbl->result_bit_size;
748dd0191d5SShuanglin Wang }
749dd0191d5SShuanglin Wang 
750dd0191d5SShuanglin Wang static int32_t
751dd0191d5SShuanglin Wang ulp_mapper_tfc_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
752dd0191d5SShuanglin Wang 				 struct bnxt_ulp_mapper_tbl_info *tbl)
753dd0191d5SShuanglin Wang {
754dd0191d5SShuanglin Wang 	bool alloc = false, write = false, global = false, regfile = false;
755dd0191d5SShuanglin Wang 	struct bnxt_ulp_glb_resource_info glb_res = { 0 };
756dd0191d5SShuanglin Wang 	uint16_t bit_size, wordlen = 0, tmplen = 0;
7572aa70990SKishore Padmanabha 	enum cfa_track_type tt = tbl->track_type;
758dd0191d5SShuanglin Wang 	struct ulp_flow_db_res_params fid_parms;
759dd0191d5SShuanglin Wang 	struct tfc_idx_tbl_info tbl_info = { 0 };
760dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
761dd0191d5SShuanglin Wang 	struct ulp_blob	data;
762dd0191d5SShuanglin Wang 	uint64_t regval = 0;
763dd0191d5SShuanglin Wang 	bool shared = false;
764dd0191d5SShuanglin Wang 	uint32_t index = 0;
765dd0191d5SShuanglin Wang 	unsigned char *data_p;
766dd0191d5SShuanglin Wang 	int32_t rc = 0;
767dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
768dd0191d5SShuanglin Wang 
769dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx);
770*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
771dd0191d5SShuanglin Wang 		PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer");
772dd0191d5SShuanglin Wang 		return -EINVAL;
773dd0191d5SShuanglin Wang 	}
774dd0191d5SShuanglin Wang 
775*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(parms->ulp_ctx, &fw_fid))) {
776dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func id\n");
777dd0191d5SShuanglin Wang 		return -EINVAL;
778dd0191d5SShuanglin Wang 	}
779dd0191d5SShuanglin Wang 
780dd0191d5SShuanglin Wang 	/* compute the blob size */
781dd0191d5SShuanglin Wang 	bit_size = ulp_mapper_tfc_dyn_blob_size_get(parms, tbl);
782dd0191d5SShuanglin Wang 
783dd0191d5SShuanglin Wang 	/* Initialize the blob data */
784*0c036a14SPeter Spreadborough 	if (unlikely(ulp_blob_init(&data, bit_size,
785*0c036a14SPeter Spreadborough 				   parms->device_params->result_byte_order))) {
786dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to initialize index table blob\n");
787dd0191d5SShuanglin Wang 		return -EINVAL;
788dd0191d5SShuanglin Wang 	}
789dd0191d5SShuanglin Wang 
790dd0191d5SShuanglin Wang 	switch (tbl->tbl_opcode) {
791dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
792dd0191d5SShuanglin Wang 		alloc = true;
793dd0191d5SShuanglin Wang 		regfile = true;
794dd0191d5SShuanglin Wang 		break;
795dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
796dd0191d5SShuanglin Wang 		/*
797dd0191d5SShuanglin Wang 		 * Build the entry, alloc an index, write the table, and store
798dd0191d5SShuanglin Wang 		 * the data in the regfile.
799dd0191d5SShuanglin Wang 		 */
800dd0191d5SShuanglin Wang 		alloc = true;
801dd0191d5SShuanglin Wang 		write = true;
802dd0191d5SShuanglin Wang 		regfile = true;
803dd0191d5SShuanglin Wang 		break;
804dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
805dd0191d5SShuanglin Wang 		/*
806dd0191d5SShuanglin Wang 		 * get the index to write to from the regfile and then write
807dd0191d5SShuanglin Wang 		 * the table entry.
808dd0191d5SShuanglin Wang 		 */
809dd0191d5SShuanglin Wang 		regfile = true;
810dd0191d5SShuanglin Wang 		write = true;
811dd0191d5SShuanglin Wang 		break;
812dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE:
813dd0191d5SShuanglin Wang 		/*
814dd0191d5SShuanglin Wang 		 * Build the entry, alloc an index, write the table, and store
815dd0191d5SShuanglin Wang 		 * the data in the global regfile.
816dd0191d5SShuanglin Wang 		 */
817dd0191d5SShuanglin Wang 		alloc = true;
818dd0191d5SShuanglin Wang 		global = true;
819dd0191d5SShuanglin Wang 		write = true;
820dd0191d5SShuanglin Wang 		break;
821dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
822*0c036a14SPeter Spreadborough 		if (unlikely(tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP)) {
823dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Template error, wrong fdb opcode\n");
824dd0191d5SShuanglin Wang 			return -EINVAL;
825dd0191d5SShuanglin Wang 		}
826dd0191d5SShuanglin Wang 		/*
827dd0191d5SShuanglin Wang 		 * get the index to write to from the global regfile and then
828dd0191d5SShuanglin Wang 		 * write the table.
829dd0191d5SShuanglin Wang 		 */
830*0c036a14SPeter Spreadborough 		if (unlikely(ulp_mapper_glb_resource_read(parms->mapper_data,
831dd0191d5SShuanglin Wang 							  tbl->direction,
832dd0191d5SShuanglin Wang 							  tbl->tbl_operand,
833*0c036a14SPeter Spreadborough 							  &regval, &shared))) {
834dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
835dd0191d5SShuanglin Wang 				     "Failed to get tbl idx from Glb RF[%d].\n",
836dd0191d5SShuanglin Wang 				     tbl->tbl_operand);
837dd0191d5SShuanglin Wang 			return -EINVAL;
838dd0191d5SShuanglin Wang 		}
839dd0191d5SShuanglin Wang 		index = rte_be_to_cpu_64(regval);
840dd0191d5SShuanglin Wang 		/* check to see if any scope id changes needs to be done*/
841dd0191d5SShuanglin Wang 		write = true;
842dd0191d5SShuanglin Wang 		break;
843dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
844dd0191d5SShuanglin Wang 		/*
845dd0191d5SShuanglin Wang 		 * The read is different from the rest and can be handled here
846dd0191d5SShuanglin Wang 		 * instead of trying to use common code.  Simply read the table
847dd0191d5SShuanglin Wang 		 * with the index from the regfile, scan and store the
848dd0191d5SShuanglin Wang 		 * identifiers, and return.
849dd0191d5SShuanglin Wang 		 */
850*0c036a14SPeter Spreadborough 		if (unlikely(ulp_regfile_read(parms->regfile,
851*0c036a14SPeter Spreadborough 					      tbl->tbl_operand, &regval))) {
852dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
853dd0191d5SShuanglin Wang 				     "Failed to get tbl idx from regfile[%d]\n",
854dd0191d5SShuanglin Wang 				     tbl->tbl_operand);
855dd0191d5SShuanglin Wang 			return -EINVAL;
856dd0191d5SShuanglin Wang 		}
857dd0191d5SShuanglin Wang 		index = rte_be_to_cpu_64(regval);
858dd0191d5SShuanglin Wang 		tbl_info.dir = tbl->direction;
859dd0191d5SShuanglin Wang 		tbl_info.rsubtype = tbl->resource_type;
860dd0191d5SShuanglin Wang 		tbl_info.id = index;
861dd0191d5SShuanglin Wang 		/* Nothing has been pushed to blob, so push bit_size */
862dd0191d5SShuanglin Wang 		tmplen = ulp_blob_pad_push(&data, bit_size);
863dd0191d5SShuanglin Wang 		data_p = ulp_blob_data_get(&data, &tmplen);
864dd0191d5SShuanglin Wang 		wordlen = ULP_BITS_2_BYTE(tmplen);
865dd0191d5SShuanglin Wang 
866dd0191d5SShuanglin Wang 		rc = tfc_idx_tbl_get(tfcp, fw_fid, &tbl_info, (uint32_t *)data_p,
867dd0191d5SShuanglin Wang 				     (uint8_t *)&wordlen);
868*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
869dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
870dd0191d5SShuanglin Wang 				     "Failed to read the tbl entry %d:%d\n",
871dd0191d5SShuanglin Wang 				     tbl->resource_type, index);
872dd0191d5SShuanglin Wang 			return rc;
873dd0191d5SShuanglin Wang 		}
874dd0191d5SShuanglin Wang 
875dd0191d5SShuanglin Wang 		/* Scan the fields in the entry and push them into the regfile*/
876dd0191d5SShuanglin Wang 		rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, data_p,
877dd0191d5SShuanglin Wang 						   wordlen, data.byte_order);
878*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
879dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
880dd0191d5SShuanglin Wang 				     "Failed to get flds on tbl read rc=%d\n",
881dd0191d5SShuanglin Wang 				     rc);
882dd0191d5SShuanglin Wang 			return rc;
883dd0191d5SShuanglin Wang 		}
884dd0191d5SShuanglin Wang 		return 0;
88549cdf043SKishore Padmanabha 	case BNXT_ULP_INDEX_TBL_OPC_NOP_REGFILE:
88649cdf043SKishore Padmanabha 		/* Special case, where hw table processing is not being done */
88749cdf043SKishore Padmanabha 		/* but only for writing the regfile into the flow database */
88849cdf043SKishore Padmanabha 		regfile = true;
88949cdf043SKishore Padmanabha 		break;
890dd0191d5SShuanglin Wang 	default:
891dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid index table opcode %d\n",
892dd0191d5SShuanglin Wang 			     tbl->tbl_opcode);
893dd0191d5SShuanglin Wang 		return -EINVAL;
894dd0191d5SShuanglin Wang 	}
895dd0191d5SShuanglin Wang 
896dd0191d5SShuanglin Wang 	/* read the CMM identifier from the regfile, it is not allocated */
897dd0191d5SShuanglin Wang 	if (!alloc && regfile) {
898*0c036a14SPeter Spreadborough 		if (unlikely(ulp_regfile_read(parms->regfile,
899dd0191d5SShuanglin Wang 					      tbl->tbl_operand,
900*0c036a14SPeter Spreadborough 					      &regval))) {
901dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
902dd0191d5SShuanglin Wang 				    "Failed to get tbl idx from regfile[%d].\n",
903dd0191d5SShuanglin Wang 				     tbl->tbl_operand);
904dd0191d5SShuanglin Wang 			return -EINVAL;
905dd0191d5SShuanglin Wang 		}
906dd0191d5SShuanglin Wang 		index = rte_be_to_cpu_64(regval);
907dd0191d5SShuanglin Wang 	}
908dd0191d5SShuanglin Wang 
909dd0191d5SShuanglin Wang 	/* Allocate the Action CMM identifier */
910dd0191d5SShuanglin Wang 	if (alloc) {
911dd0191d5SShuanglin Wang 		tbl_info.dir = tbl->direction;
912dd0191d5SShuanglin Wang 		tbl_info.rsubtype = tbl->resource_type;
913dd0191d5SShuanglin Wang 		rc =  tfc_idx_tbl_alloc(tfcp, fw_fid, tt, &tbl_info);
914*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
915dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
916dd0191d5SShuanglin Wang 				     tfc_idx_tbl_2_str(tbl_info.rsubtype),
917dd0191d5SShuanglin Wang 				     tfc_dir_2_str(tbl->direction), rc);
918dd0191d5SShuanglin Wang 			return rc;
919dd0191d5SShuanglin Wang 		}
920dd0191d5SShuanglin Wang 		index = tbl_info.id;
921dd0191d5SShuanglin Wang 	}
922dd0191d5SShuanglin Wang 
923dd0191d5SShuanglin Wang 	/* update the global register value */
924dd0191d5SShuanglin Wang 	if (alloc && global) {
925dd0191d5SShuanglin Wang 		glb_res.direction = tbl->direction;
926dd0191d5SShuanglin Wang 		glb_res.resource_func = tbl->resource_func;
927dd0191d5SShuanglin Wang 		glb_res.resource_type = tbl->resource_type;
928dd0191d5SShuanglin Wang 		glb_res.glb_regfile_index = tbl->tbl_operand;
929dd0191d5SShuanglin Wang 		regval = rte_cpu_to_be_64(index);
930dd0191d5SShuanglin Wang 
931dd0191d5SShuanglin Wang 		/*
932dd0191d5SShuanglin Wang 		 * Shared resources are never allocated through this
933dd0191d5SShuanglin Wang 		 * method, so the shared flag is always false.
934dd0191d5SShuanglin Wang 		 */
935dd0191d5SShuanglin Wang 		rc = ulp_mapper_glb_resource_write(parms->mapper_data,
936dd0191d5SShuanglin Wang 						   &glb_res, regval,
937dd0191d5SShuanglin Wang 						   false);
938*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
939dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
940dd0191d5SShuanglin Wang 				     "Failed to write %s regfile[%d] rc=%d\n",
941dd0191d5SShuanglin Wang 				     (global) ? "global" : "reg",
942dd0191d5SShuanglin Wang 				     tbl->tbl_operand, rc);
943dd0191d5SShuanglin Wang 			goto error;
944dd0191d5SShuanglin Wang 		}
945dd0191d5SShuanglin Wang 	}
946dd0191d5SShuanglin Wang 
947dd0191d5SShuanglin Wang 	/* update the local register value */
948dd0191d5SShuanglin Wang 	if (alloc && regfile) {
949dd0191d5SShuanglin Wang 		regval = rte_cpu_to_be_64(index);
950dd0191d5SShuanglin Wang 		rc = ulp_regfile_write(parms->regfile,
951dd0191d5SShuanglin Wang 				       tbl->tbl_operand, regval);
952*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
953dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
954dd0191d5SShuanglin Wang 				     "Failed to write %s regfile[%d] rc=%d\n",
955dd0191d5SShuanglin Wang 				     (global) ? "global" : "reg",
956dd0191d5SShuanglin Wang 				     tbl->tbl_operand, rc);
957dd0191d5SShuanglin Wang 			goto error;
958dd0191d5SShuanglin Wang 		}
959dd0191d5SShuanglin Wang 	}
960dd0191d5SShuanglin Wang 
961dd0191d5SShuanglin Wang 	if (write) {
962dd0191d5SShuanglin Wang 		/* Get the result fields list */
963dd0191d5SShuanglin Wang 		rc = ulp_mapper_tbl_result_build(parms,
964dd0191d5SShuanglin Wang 						 tbl,
965dd0191d5SShuanglin Wang 						 &data,
966dd0191d5SShuanglin Wang 						 "Indexed Result");
967*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
968dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Failed to build the result blob\n");
969dd0191d5SShuanglin Wang 			return rc;
970dd0191d5SShuanglin Wang 		}
971dd0191d5SShuanglin Wang 		data_p = ulp_blob_data_get(&data, &tmplen);
972dd0191d5SShuanglin Wang 		tbl_info.dir = tbl->direction;
973dd0191d5SShuanglin Wang 		tbl_info.rsubtype = tbl->resource_type;
974dd0191d5SShuanglin Wang 		tbl_info.id = index;
975dd0191d5SShuanglin Wang 		wordlen = ULP_BITS_2_BYTE(tmplen);
976dd0191d5SShuanglin Wang 		rc = tfc_idx_tbl_set(tfcp, fw_fid, &tbl_info,
977dd0191d5SShuanglin Wang 				     (uint32_t *)data_p, wordlen);
978*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
979dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
980dd0191d5SShuanglin Wang 				     "Index table[%s][%s][%x] write fail %d\n",
981dd0191d5SShuanglin Wang 				     tfc_idx_tbl_2_str(tbl_info.rsubtype),
982dd0191d5SShuanglin Wang 				     tfc_dir_2_str(tbl_info.dir),
983dd0191d5SShuanglin Wang 				     tbl_info.id, rc);
984dd0191d5SShuanglin Wang 			goto error;
985dd0191d5SShuanglin Wang 		}
986dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(DEBUG,
987dd0191d5SShuanglin Wang 			     "Index table[%s][%d][%x] write successful\n",
988dd0191d5SShuanglin Wang 			     tfc_idx_tbl_2_str(tbl_info.rsubtype),
989dd0191d5SShuanglin Wang 			     tbl_info.dir, tbl_info.id);
990dd0191d5SShuanglin Wang 	}
991dd0191d5SShuanglin Wang 	/* Link the resource to the flow in the flow db */
992dd0191d5SShuanglin Wang 	memset(&fid_parms, 0, sizeof(fid_parms));
993dd0191d5SShuanglin Wang 	fid_parms.direction	= tbl->direction;
994dd0191d5SShuanglin Wang 	fid_parms.resource_func	= tbl->resource_func;
995dd0191d5SShuanglin Wang 	fid_parms.resource_type	= tbl->resource_type;
996dd0191d5SShuanglin Wang 	fid_parms.resource_sub_type = tbl->resource_sub_type;
997dd0191d5SShuanglin Wang 	fid_parms.resource_hndl	= index;
998dd0191d5SShuanglin Wang 	fid_parms.critical_resource = tbl->critical_resource;
999dd0191d5SShuanglin Wang 	ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
1000dd0191d5SShuanglin Wang 
1001dd0191d5SShuanglin Wang 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1002*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1003dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1004dd0191d5SShuanglin Wang 			     rc);
1005dd0191d5SShuanglin Wang 		goto error;
1006dd0191d5SShuanglin Wang 	}
1007dd0191d5SShuanglin Wang 
1008dd0191d5SShuanglin Wang 	/* Perform the VF rep action */
1009dd0191d5SShuanglin Wang 	rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
1010*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1011dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
1012dd0191d5SShuanglin Wang 		goto error;
1013dd0191d5SShuanglin Wang 	}
1014dd0191d5SShuanglin Wang 	return rc;
1015dd0191d5SShuanglin Wang error:
1016dd0191d5SShuanglin Wang 	/* Shared resources are not freed */
1017dd0191d5SShuanglin Wang 	if (shared)
1018dd0191d5SShuanglin Wang 		return rc;
1019dd0191d5SShuanglin Wang 	/*
1020dd0191d5SShuanglin Wang 	 * Free the allocated resource since we failed to either
1021dd0191d5SShuanglin Wang 	 * write to the entry or link the flow
1022dd0191d5SShuanglin Wang 	 */
1023dd0191d5SShuanglin Wang 
1024dd0191d5SShuanglin Wang 	if (tfc_idx_tbl_free(tfcp, fw_fid, &tbl_info))
1025dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to free index entry on failure\n");
1026dd0191d5SShuanglin Wang 	return rc;
1027dd0191d5SShuanglin Wang }
1028dd0191d5SShuanglin Wang 
1029dd0191d5SShuanglin Wang static inline int32_t
1030dd0191d5SShuanglin Wang ulp_mapper_tfc_index_entry_free(struct bnxt_ulp_context *ulp_ctx,
1031dd0191d5SShuanglin Wang 				struct ulp_flow_db_res_params *res)
1032dd0191d5SShuanglin Wang {
1033dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
1034dd0191d5SShuanglin Wang 	struct tfc_idx_tbl_info tbl_info = { 0 };
1035dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
1036be4732e8SMike Baucom 	int32_t rc;
1037dd0191d5SShuanglin Wang 
1038*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &fw_fid))) {
1039dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func_id\n");
1040dd0191d5SShuanglin Wang 		return -EINVAL;
1041dd0191d5SShuanglin Wang 	}
1042dd0191d5SShuanglin Wang 
1043dd0191d5SShuanglin Wang #ifndef ULP_MAPPER_TFC_TEST
1044dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx);
1045*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
1046dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n");
1047dd0191d5SShuanglin Wang 		return -EINVAL;
1048dd0191d5SShuanglin Wang 	}
1049dd0191d5SShuanglin Wang #endif
1050dd0191d5SShuanglin Wang 	tbl_info.dir = (enum cfa_dir)res->direction;
1051dd0191d5SShuanglin Wang 	tbl_info.rsubtype = res->resource_type;
1052dd0191d5SShuanglin Wang 	tbl_info.id = (uint16_t)res->resource_hndl;
1053dd0191d5SShuanglin Wang 
1054dd0191d5SShuanglin Wang 	/* TBD: check to see if the memory needs to be cleaned as well*/
1055be4732e8SMike Baucom 	rc = tfc_idx_tbl_free(tfcp, fw_fid, &tbl_info);
1056be4732e8SMike Baucom #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1057be4732e8SMike Baucom #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1058be4732e8SMike Baucom 	if (!rc)
1059be4732e8SMike Baucom 		BNXT_DRV_DBG(DEBUG, "Freed Index [%s]:[%s] = 0x%X\n",
1060be4732e8SMike Baucom 		     tfc_dir_2_str(tbl_info.dir),
1061be4732e8SMike Baucom 		     tfc_idx_tbl_2_str(tbl_info.rsubtype), tbl_info.id);
1062be4732e8SMike Baucom #endif
1063be4732e8SMike Baucom #endif
1064be4732e8SMike Baucom 	return rc;
1065dd0191d5SShuanglin Wang }
1066dd0191d5SShuanglin Wang 
1067dd0191d5SShuanglin Wang static int32_t
1068dd0191d5SShuanglin Wang ulp_mapper_tfc_cmm_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1069dd0191d5SShuanglin Wang 			       struct bnxt_ulp_mapper_tbl_info *tbl,
1070dd0191d5SShuanglin Wang 			       void *error)
1071dd0191d5SShuanglin Wang {
1072dd0191d5SShuanglin Wang 	bool alloc = false, write = false, global = false, regfile = false;
1073dd0191d5SShuanglin Wang 	struct bnxt_ulp_glb_resource_info glb_res = { 0 };
1074dd0191d5SShuanglin Wang 	uint16_t bit_size, act_wordlen = 0, tmplen = 0;
1075dd0191d5SShuanglin Wang 	struct ulp_flow_db_res_params fid_parms;
1076dd0191d5SShuanglin Wang 	struct tfc_cmm_info cmm_info = { 0 };
1077dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
1078dd0191d5SShuanglin Wang 	struct ulp_blob	data;
1079dd0191d5SShuanglin Wang 	uint64_t regval = 0;
1080dd0191d5SShuanglin Wang 	bool shared = false;
1081dd0191d5SShuanglin Wang 	uint64_t handle = 0;
1082dd0191d5SShuanglin Wang 	const uint8_t *act_data;
1083dd0191d5SShuanglin Wang 	uint64_t act_rec_size = 0;
1084dd0191d5SShuanglin Wang 	uint8_t tsid = 0;
1085dd0191d5SShuanglin Wang 	int32_t rc = 0;
1086dd0191d5SShuanglin Wang 
1087dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx);
1088*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
1089dd0191d5SShuanglin Wang 		PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer");
1090dd0191d5SShuanglin Wang 		return -EINVAL;
1091dd0191d5SShuanglin Wang 	}
1092dd0191d5SShuanglin Wang 
1093dd0191d5SShuanglin Wang 	/* compute the blob size */
1094dd0191d5SShuanglin Wang 	bit_size = ulp_mapper_tfc_dyn_blob_size_get(parms, tbl);
1095dd0191d5SShuanglin Wang 
1096dd0191d5SShuanglin Wang 	/* Initialize the blob data */
1097*0c036a14SPeter Spreadborough 	if (unlikely(ulp_blob_init(&data, bit_size,
1098*0c036a14SPeter Spreadborough 				   parms->device_params->result_byte_order))) {
1099dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to initialize cmm table blob\n");
1100dd0191d5SShuanglin Wang 		return -EINVAL;
1101dd0191d5SShuanglin Wang 	}
1102dd0191d5SShuanglin Wang 
1103dd0191d5SShuanglin Wang 	switch (tbl->tbl_opcode) {
1104dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
1105dd0191d5SShuanglin Wang 		regfile = true;
1106dd0191d5SShuanglin Wang 		alloc = true;
1107dd0191d5SShuanglin Wang 		break;
1108dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
1109dd0191d5SShuanglin Wang 		/*
1110dd0191d5SShuanglin Wang 		 * Build the entry, alloc an index, write the table, and store
1111dd0191d5SShuanglin Wang 		 * the data in the regfile.
1112dd0191d5SShuanglin Wang 		 */
1113dd0191d5SShuanglin Wang 		alloc = true;
1114dd0191d5SShuanglin Wang 		write = true;
1115dd0191d5SShuanglin Wang 		regfile = true;
1116dd0191d5SShuanglin Wang 		break;
1117dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
1118dd0191d5SShuanglin Wang 		/*
1119dd0191d5SShuanglin Wang 		 * get the index to write to from the regfile and then write
1120dd0191d5SShuanglin Wang 		 * the table entry.
1121dd0191d5SShuanglin Wang 		 */
1122dd0191d5SShuanglin Wang 		regfile = true;
1123dd0191d5SShuanglin Wang 		write = true;
1124dd0191d5SShuanglin Wang 		break;
1125dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE:
1126dd0191d5SShuanglin Wang 		/*
1127dd0191d5SShuanglin Wang 		 * Build the entry, alloc an index, write the table, and store
1128dd0191d5SShuanglin Wang 		 * the data in the global regfile.
1129dd0191d5SShuanglin Wang 		 */
1130dd0191d5SShuanglin Wang 		alloc = true;
1131dd0191d5SShuanglin Wang 		global = true;
1132dd0191d5SShuanglin Wang 		write = true;
1133dd0191d5SShuanglin Wang 		break;
1134dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
1135*0c036a14SPeter Spreadborough 		if (unlikely(tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP)) {
1136dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Template error, wrong fdb opcode\n");
1137dd0191d5SShuanglin Wang 			return -EINVAL;
1138dd0191d5SShuanglin Wang 		}
1139dd0191d5SShuanglin Wang 		/*
1140dd0191d5SShuanglin Wang 		 * get the index to write to from the global regfile and then
1141dd0191d5SShuanglin Wang 		 * write the table.
1142dd0191d5SShuanglin Wang 		 */
1143*0c036a14SPeter Spreadborough 		if (unlikely(ulp_mapper_glb_resource_read(parms->mapper_data,
1144dd0191d5SShuanglin Wang 							  tbl->direction,
1145dd0191d5SShuanglin Wang 							  tbl->tbl_operand,
1146*0c036a14SPeter Spreadborough 							  &regval, &shared))) {
1147dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
1148dd0191d5SShuanglin Wang 				     "Failed to get tbl idx from Glb RF[%d].\n",
1149dd0191d5SShuanglin Wang 				     tbl->tbl_operand);
1150dd0191d5SShuanglin Wang 			return -EINVAL;
1151dd0191d5SShuanglin Wang 		}
1152dd0191d5SShuanglin Wang 		handle = rte_be_to_cpu_64(regval);
1153dd0191d5SShuanglin Wang 		/* check to see if any scope id changes needs to be done*/
1154dd0191d5SShuanglin Wang 		write = true;
1155dd0191d5SShuanglin Wang 		break;
1156dd0191d5SShuanglin Wang 	case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
1157dd0191d5SShuanglin Wang 		/*
1158dd0191d5SShuanglin Wang 		 * The read is different from the rest and can be handled here
1159dd0191d5SShuanglin Wang 		 * instead of trying to use common code.  Simply read the table
1160dd0191d5SShuanglin Wang 		 * with the index from the regfile, scan and store the
1161dd0191d5SShuanglin Wang 		 * identifiers, and return.
1162dd0191d5SShuanglin Wang 		 */
1163*0c036a14SPeter Spreadborough 		if (unlikely(ulp_regfile_read(parms->regfile,
1164*0c036a14SPeter Spreadborough 					      tbl->tbl_operand, &regval))) {
1165dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
1166dd0191d5SShuanglin Wang 				     "Failed to get tbl idx from regfile[%d]\n",
1167dd0191d5SShuanglin Wang 				     tbl->tbl_operand);
1168dd0191d5SShuanglin Wang 			return -EINVAL;
1169dd0191d5SShuanglin Wang 		}
1170dd0191d5SShuanglin Wang 		handle = rte_be_to_cpu_64(regval);
1171dd0191d5SShuanglin Wang 		return 0;
117249cdf043SKishore Padmanabha 	case BNXT_ULP_INDEX_TBL_OPC_NOP_REGFILE:
117349cdf043SKishore Padmanabha 		regfile = true;
117449cdf043SKishore Padmanabha 		alloc = false;
117549cdf043SKishore Padmanabha 		break;
1176dd0191d5SShuanglin Wang 	default:
1177dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid cmm table opcode %d\n",
1178dd0191d5SShuanglin Wang 			     tbl->tbl_opcode);
1179dd0191d5SShuanglin Wang 		return -EINVAL;
1180dd0191d5SShuanglin Wang 	}
1181dd0191d5SShuanglin Wang 
1182dd0191d5SShuanglin Wang 	/* read the CMM handle from the regfile, it is not allocated */
1183dd0191d5SShuanglin Wang 	if (!alloc && regfile) {
1184*0c036a14SPeter Spreadborough 		if (unlikely(ulp_regfile_read(parms->regfile,
1185dd0191d5SShuanglin Wang 				     tbl->tbl_operand,
1186*0c036a14SPeter Spreadborough 					      &regval))) {
1187dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
1188dd0191d5SShuanglin Wang 				    "Failed to get tbl idx from regfile[%d].\n",
1189dd0191d5SShuanglin Wang 				     tbl->tbl_operand);
1190dd0191d5SShuanglin Wang 			return -EINVAL;
1191dd0191d5SShuanglin Wang 		}
1192dd0191d5SShuanglin Wang 		handle = rte_be_to_cpu_64(regval);
1193dd0191d5SShuanglin Wang 	}
1194dd0191d5SShuanglin Wang 
1195dd0191d5SShuanglin Wang 	/* Get the result fields list */
1196dd0191d5SShuanglin Wang 	rc = ulp_mapper_tbl_result_build(parms,
1197dd0191d5SShuanglin Wang 					 tbl,
1198dd0191d5SShuanglin Wang 					 &data,
1199dd0191d5SShuanglin Wang 					 "Indexed Result");
1200*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1201dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to build the result blob\n");
1202dd0191d5SShuanglin Wang 		return rc;
1203dd0191d5SShuanglin Wang 	}
1204dd0191d5SShuanglin Wang 
1205dd0191d5SShuanglin Wang 	/* Allocate the Action CMM identifier */
1206dd0191d5SShuanglin Wang 	if (alloc) {
1207dd0191d5SShuanglin Wang 		cmm_info.dir = tbl->direction;
1208dd0191d5SShuanglin Wang 		cmm_info.rsubtype = tbl->resource_type;
1209dd0191d5SShuanglin Wang 		/* Only need the length for alloc, ignore the returned data */
1210dd0191d5SShuanglin Wang 		act_data = ulp_blob_data_get(&data, &tmplen);
1211dd0191d5SShuanglin Wang 		act_wordlen = ULP_BITS_TO_32_BYTE_WORD(tmplen);
1212dd0191d5SShuanglin Wang 
1213dd0191d5SShuanglin Wang 		rc = bnxt_ulp_cntxt_tsid_get(parms->ulp_ctx, &tsid);
1214*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
1215dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Failed to get the table scope\n");
1216dd0191d5SShuanglin Wang 			return rc;
1217dd0191d5SShuanglin Wang 		}
1218dd0191d5SShuanglin Wang 		/* All failures after the alloc succeeds require a free */
1219dd0191d5SShuanglin Wang 		rc =  tfc_act_alloc(tfcp, tsid, &cmm_info, act_wordlen);
1220*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
1221dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Alloc CMM [%d][%s] failed rc=%d\n",
1222dd0191d5SShuanglin Wang 				     cmm_info.rsubtype,
1223dd0191d5SShuanglin Wang 				     tfc_dir_2_str(cmm_info.dir), rc);
1224dd0191d5SShuanglin Wang 			return rc;
1225dd0191d5SShuanglin Wang 		}
1226dd0191d5SShuanglin Wang 		handle = cmm_info.act_handle;
1227dd0191d5SShuanglin Wang 
1228dd0191d5SShuanglin Wang 		/* Counters need to be reset when allocated to ensure counter is
1229dd0191d5SShuanglin Wang 		 * zero
1230dd0191d5SShuanglin Wang 		 */
1231dd0191d5SShuanglin Wang 		if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_CMM_STAT) {
1232dd0191d5SShuanglin Wang 			rc = tfc_act_set(tfcp,
1233dd0191d5SShuanglin Wang 					 &parms->batch_info,
1234dd0191d5SShuanglin Wang 					 &cmm_info, act_data,
1235dd0191d5SShuanglin Wang 					 act_wordlen);
1236*0c036a14SPeter Spreadborough 			if (unlikely(rc)) {
1237dd0191d5SShuanglin Wang 				BNXT_DRV_DBG(ERR, "Stat alloc/clear[%d][%s]"
1238dd0191d5SShuanglin Wang 					     "[0x%" PRIx64 "] failed rc=%d\n",
1239dd0191d5SShuanglin Wang 					     cmm_info.rsubtype,
1240dd0191d5SShuanglin Wang 					     tfc_dir_2_str(cmm_info.dir),
1241dd0191d5SShuanglin Wang 					     cmm_info.act_handle, rc);
1242dd0191d5SShuanglin Wang 				if (error != NULL && tfc_is_mpc_error(rc)) {
1243dd0191d5SShuanglin Wang 					struct rte_flow_error *fe =
1244dd0191d5SShuanglin Wang 						(struct rte_flow_error *)error;
1245dd0191d5SShuanglin Wang 					rte_flow_error_set(fe,
1246dd0191d5SShuanglin Wang 							   EIO,
1247dd0191d5SShuanglin Wang 							   RTE_FLOW_ERROR_TYPE_HANDLE,
1248dd0191d5SShuanglin Wang 							   NULL,
1249dd0191d5SShuanglin Wang 							   mpc_error_str[rc * -1]);
1250dd0191d5SShuanglin Wang 				}
1251dd0191d5SShuanglin Wang 				goto error;
1252dd0191d5SShuanglin Wang 			}
1253dd0191d5SShuanglin Wang 		}
1254dd0191d5SShuanglin Wang 	}
1255dd0191d5SShuanglin Wang 
1256dd0191d5SShuanglin Wang 	/* update the global register value */
1257dd0191d5SShuanglin Wang 	if (alloc && global) {
1258dd0191d5SShuanglin Wang 		glb_res.direction = tbl->direction;
1259dd0191d5SShuanglin Wang 		glb_res.resource_func = tbl->resource_func;
1260dd0191d5SShuanglin Wang 		glb_res.resource_type = tbl->resource_type;
1261dd0191d5SShuanglin Wang 		glb_res.glb_regfile_index = tbl->tbl_operand;
1262dd0191d5SShuanglin Wang 		regval = rte_cpu_to_be_64(handle);
1263dd0191d5SShuanglin Wang 
1264dd0191d5SShuanglin Wang 		/*
1265dd0191d5SShuanglin Wang 		 * Shared resources are never allocated through this
1266dd0191d5SShuanglin Wang 		 * method, so the shared flag is always false.
1267dd0191d5SShuanglin Wang 		 */
1268dd0191d5SShuanglin Wang 		rc = ulp_mapper_glb_resource_write(parms->mapper_data,
1269dd0191d5SShuanglin Wang 						   &glb_res, regval,
1270dd0191d5SShuanglin Wang 						   false);
1271*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
1272dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
1273dd0191d5SShuanglin Wang 				     "Failed to write %s regfile[%d] rc=%d\n",
1274dd0191d5SShuanglin Wang 				     (global) ? "global" : "reg",
1275dd0191d5SShuanglin Wang 				     tbl->tbl_operand, rc);
1276dd0191d5SShuanglin Wang 			goto error;
1277dd0191d5SShuanglin Wang 		}
1278dd0191d5SShuanglin Wang 	}
1279dd0191d5SShuanglin Wang 
1280dd0191d5SShuanglin Wang 	/* update the local register value */
1281dd0191d5SShuanglin Wang 	if (alloc && regfile) {
1282dd0191d5SShuanglin Wang 		regval = rte_cpu_to_be_64(handle);
1283dd0191d5SShuanglin Wang 		rc = ulp_regfile_write(parms->regfile,
1284dd0191d5SShuanglin Wang 				       tbl->tbl_operand, regval);
1285*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
1286dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
1287dd0191d5SShuanglin Wang 				     "Failed to write %s regfile[%d] rc=%d\n",
1288dd0191d5SShuanglin Wang 				     (global) ? "global" : "reg",
1289dd0191d5SShuanglin Wang 				     tbl->tbl_operand, rc);
1290dd0191d5SShuanglin Wang 			goto error;
1291dd0191d5SShuanglin Wang 		}
1292dd0191d5SShuanglin Wang 	}
1293dd0191d5SShuanglin Wang 
1294dd0191d5SShuanglin Wang 	if (write) {
1295dd0191d5SShuanglin Wang 		act_data = ulp_blob_data_get(&data, &tmplen);
1296dd0191d5SShuanglin Wang 		cmm_info.dir = tbl->direction;
1297dd0191d5SShuanglin Wang 		cmm_info.rsubtype = tbl->resource_type;
1298dd0191d5SShuanglin Wang 		cmm_info.act_handle = handle;
1299dd0191d5SShuanglin Wang 		act_wordlen = ULP_BITS_TO_32_BYTE_WORD(tmplen);
1300dd0191d5SShuanglin Wang 		rc = tfc_act_set(tfcp, &parms->batch_info, &cmm_info, act_data, act_wordlen);
1301*0c036a14SPeter Spreadborough 		if (unlikely(rc)) {
1302dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR,
1303dd0191d5SShuanglin Wang 				     "CMM table[%d][%s][0x%" PRIx64
1304dd0191d5SShuanglin Wang 				      "] write fail %d\n",
1305dd0191d5SShuanglin Wang 				     cmm_info.rsubtype,
1306dd0191d5SShuanglin Wang 				     tfc_dir_2_str(cmm_info.dir),
1307dd0191d5SShuanglin Wang 				     handle, rc);
1308dd0191d5SShuanglin Wang 			if (error != NULL && tfc_is_mpc_error(rc)) {
1309dd0191d5SShuanglin Wang 				struct rte_flow_error *fe =
1310dd0191d5SShuanglin Wang 					(struct rte_flow_error *)error;
1311dd0191d5SShuanglin Wang 				rte_flow_error_set(fe,
1312dd0191d5SShuanglin Wang 						   EIO,
1313dd0191d5SShuanglin Wang 						   RTE_FLOW_ERROR_TYPE_HANDLE,
1314dd0191d5SShuanglin Wang 						   NULL,
1315dd0191d5SShuanglin Wang 						   mpc_error_str[rc * -1]);
1316dd0191d5SShuanglin Wang 			}
1317dd0191d5SShuanglin Wang 			goto error;
1318dd0191d5SShuanglin Wang 		}
1319dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(DEBUG,
1320dd0191d5SShuanglin Wang 			     "CMM table[%d][%s][0x%" PRIx64
1321dd0191d5SShuanglin Wang 			      "] write successful\n",
1322dd0191d5SShuanglin Wang 			     cmm_info.rsubtype, tfc_dir_2_str(cmm_info.dir),
1323dd0191d5SShuanglin Wang 			     handle);
1324dd0191d5SShuanglin Wang 
1325dd0191d5SShuanglin Wang 		/* Calculate action record size */
1326dd0191d5SShuanglin Wang 		if (tbl->resource_type == CFA_RSUBTYPE_CMM_ACT) {
1327dd0191d5SShuanglin Wang 			act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
1328dd0191d5SShuanglin Wang 			act_rec_size--;
1329dd0191d5SShuanglin Wang 			if (ulp_regfile_write(parms->regfile,
1330dd0191d5SShuanglin Wang 					      BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
1331dd0191d5SShuanglin Wang 					      rte_cpu_to_be_64(act_rec_size)))
1332dd0191d5SShuanglin Wang 				BNXT_DRV_DBG(ERR,
1333dd0191d5SShuanglin Wang 					     "Failed write the act rec size\n");
1334dd0191d5SShuanglin Wang 		}
1335dd0191d5SShuanglin Wang 	}
1336dd0191d5SShuanglin Wang 	/* Link the resource to the flow in the flow db */
1337dd0191d5SShuanglin Wang 	memset(&fid_parms, 0, sizeof(fid_parms));
1338dd0191d5SShuanglin Wang 	fid_parms.direction	= tbl->direction;
1339dd0191d5SShuanglin Wang 	fid_parms.resource_func	= tbl->resource_func;
1340dd0191d5SShuanglin Wang 	fid_parms.resource_type	= tbl->resource_type;
1341dd0191d5SShuanglin Wang 	fid_parms.resource_sub_type = tbl->resource_sub_type;
1342dd0191d5SShuanglin Wang 	fid_parms.resource_hndl	= handle;
1343dd0191d5SShuanglin Wang 	fid_parms.critical_resource = tbl->critical_resource;
1344dd0191d5SShuanglin Wang 	ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
1345dd0191d5SShuanglin Wang 
1346dd0191d5SShuanglin Wang 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1347*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1348dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1349dd0191d5SShuanglin Wang 			     rc);
1350dd0191d5SShuanglin Wang 		goto error;
1351dd0191d5SShuanglin Wang 	}
1352dd0191d5SShuanglin Wang 
1353dd0191d5SShuanglin Wang 	/* Perform the VF rep action */
1354dd0191d5SShuanglin Wang 	rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
1355*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1356dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
1357dd0191d5SShuanglin Wang 		goto error;
1358dd0191d5SShuanglin Wang 	}
1359dd0191d5SShuanglin Wang 	return rc;
1360dd0191d5SShuanglin Wang error:
1361dd0191d5SShuanglin Wang 	/* Shared resources are not freed */
1362dd0191d5SShuanglin Wang 	if (shared)
1363dd0191d5SShuanglin Wang 		return rc;
1364dd0191d5SShuanglin Wang 	/*
1365dd0191d5SShuanglin Wang 	 * Free the allocated resource since we failed to either
1366dd0191d5SShuanglin Wang 	 * write to the entry or link the flow
1367dd0191d5SShuanglin Wang 	 */
1368dd0191d5SShuanglin Wang 
1369dd0191d5SShuanglin Wang 	if (tfc_act_free(tfcp, &cmm_info))
1370dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to free cmm entry on failure\n");
1371dd0191d5SShuanglin Wang 
1372dd0191d5SShuanglin Wang 	return rc;
1373dd0191d5SShuanglin Wang }
1374dd0191d5SShuanglin Wang 
1375dd0191d5SShuanglin Wang static int32_t
1376dd0191d5SShuanglin Wang ulp_mapper_tfc_cmm_entry_free(struct bnxt_ulp_context *ulp_ctx,
1377dd0191d5SShuanglin Wang 			      struct ulp_flow_db_res_params *res,
1378dd0191d5SShuanglin Wang 			      void *error)
1379dd0191d5SShuanglin Wang {
1380dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
1381dd0191d5SShuanglin Wang 	struct tfc_cmm_info cmm_info = { 0 };
1382dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
1383dd0191d5SShuanglin Wang 	int32_t rc = 0;
1384dd0191d5SShuanglin Wang 
1385f6e12015SKishore Padmanabha 	/* skip cmm processing if fdb flag is sw only */
1386f6e12015SKishore Padmanabha 	if (res->fdb_flags & ULP_FDB_FLAG_SW_ONLY)
138749cdf043SKishore Padmanabha 		return 0;
138849cdf043SKishore Padmanabha 
1389*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &fw_fid))) {
1390dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func_id\n");
1391dd0191d5SShuanglin Wang 		return -EINVAL;
1392dd0191d5SShuanglin Wang 	}
1393dd0191d5SShuanglin Wang 
1394dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx);
1395*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
1396dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n");
1397dd0191d5SShuanglin Wang 		return -EINVAL;
1398dd0191d5SShuanglin Wang 	}
1399dd0191d5SShuanglin Wang 
1400dd0191d5SShuanglin Wang 	cmm_info.dir = (enum cfa_dir)res->direction;
1401dd0191d5SShuanglin Wang 	cmm_info.rsubtype = res->resource_type;
1402dd0191d5SShuanglin Wang 	cmm_info.act_handle = res->resource_hndl;
1403dd0191d5SShuanglin Wang 
1404dd0191d5SShuanglin Wang 	/* TBD: check to see if the memory needs to be cleaned as well*/
1405dd0191d5SShuanglin Wang 	rc = tfc_act_free(tfcp, &cmm_info);
1406*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1407dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
1408dd0191d5SShuanglin Wang 			     "Failed to delete CMM entry,res = 0x%" PRIx64 "\n",
1409dd0191d5SShuanglin Wang 			     res->resource_hndl);
1410dd0191d5SShuanglin Wang 		if (error != NULL && tfc_is_mpc_error(rc)) {
1411dd0191d5SShuanglin Wang 			struct rte_flow_error *fe = (struct rte_flow_error *)error;
1412dd0191d5SShuanglin Wang 			rte_flow_error_set(fe,
1413dd0191d5SShuanglin Wang 					   EIO,
1414dd0191d5SShuanglin Wang 					   RTE_FLOW_ERROR_TYPE_HANDLE,
1415dd0191d5SShuanglin Wang 					   NULL,
1416dd0191d5SShuanglin Wang 					   mpc_error_str[rc * -1]);
1417dd0191d5SShuanglin Wang 		}
1418dd0191d5SShuanglin Wang 	} else {
1419dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(DEBUG, "Deleted CMM entry,res = 0x%" PRIx64 "\n",
1420dd0191d5SShuanglin Wang 			     res->resource_hndl);
1421dd0191d5SShuanglin Wang 	}
1422dd0191d5SShuanglin Wang 	return rc;
1423dd0191d5SShuanglin Wang }
1424dd0191d5SShuanglin Wang 
1425dd0191d5SShuanglin Wang static int32_t
1426dd0191d5SShuanglin Wang ulp_mapper_tfc_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1427dd0191d5SShuanglin Wang 			      struct bnxt_ulp_mapper_tbl_info *tbl)
1428dd0191d5SShuanglin Wang {
1429dd0191d5SShuanglin Wang 	struct ulp_blob	data, res_blob;
1430*0c036a14SPeter Spreadborough 	uint64_t idx = 0;
1431dd0191d5SShuanglin Wang 	int32_t rc = 0;
1432dd0191d5SShuanglin Wang 	struct tfc *tfcp;
1433dd0191d5SShuanglin Wang 	enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
1434dd0191d5SShuanglin Wang 	uint32_t res_size;
1435dd0191d5SShuanglin Wang 	struct tfc_if_tbl_info tbl_info = { 0 };
1436dd0191d5SShuanglin Wang 	unsigned char *data_p;
1437dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
1438dd0191d5SShuanglin Wang 	uint8_t data_size;
1439dd0191d5SShuanglin Wang 	uint16_t tmplen;
1440dd0191d5SShuanglin Wang 
1441*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(parms->ulp_ctx, &fw_fid))) {
1442dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func_id\n");
1443dd0191d5SShuanglin Wang 		return -EINVAL;
1444dd0191d5SShuanglin Wang 	}
1445dd0191d5SShuanglin Wang 
1446dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx);
1447*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
1448dd0191d5SShuanglin Wang 		PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer");
1449dd0191d5SShuanglin Wang 		return -EINVAL;
1450dd0191d5SShuanglin Wang 	}
1451dd0191d5SShuanglin Wang 
1452dd0191d5SShuanglin Wang 	/* Initialize the blob data */
1453*0c036a14SPeter Spreadborough 	if (unlikely(ulp_blob_init(&data, tbl->result_bit_size,
1454*0c036a14SPeter Spreadborough 				   parms->device_params->result_byte_order))) {
1455dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed initial index table blob\n");
1456dd0191d5SShuanglin Wang 		return -EINVAL;
1457dd0191d5SShuanglin Wang 	}
1458dd0191d5SShuanglin Wang 
1459dd0191d5SShuanglin Wang 	/* create the result blob */
1460dd0191d5SShuanglin Wang 	rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
1461*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1462dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to build the result blob\n");
1463dd0191d5SShuanglin Wang 		return rc;
1464dd0191d5SShuanglin Wang 	}
1465dd0191d5SShuanglin Wang 
1466dd0191d5SShuanglin Wang 	/* Get the index details */
1467dd0191d5SShuanglin Wang 	switch (if_opc) {
1468dd0191d5SShuanglin Wang 	case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
1469dd0191d5SShuanglin Wang 		idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
1470dd0191d5SShuanglin Wang 		break;
1471dd0191d5SShuanglin Wang 	case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
1472*0c036a14SPeter Spreadborough 		if (unlikely(ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx))) {
1473dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "regfile[%d] read oob\n",
1474dd0191d5SShuanglin Wang 				     tbl->tbl_operand);
1475dd0191d5SShuanglin Wang 			return -EINVAL;
1476dd0191d5SShuanglin Wang 		}
1477dd0191d5SShuanglin Wang 		idx = rte_be_to_cpu_64(idx);
1478dd0191d5SShuanglin Wang 		break;
1479dd0191d5SShuanglin Wang 	case BNXT_ULP_IF_TBL_OPC_WR_CONST:
1480dd0191d5SShuanglin Wang 		idx = tbl->tbl_operand;
1481dd0191d5SShuanglin Wang 		break;
1482dd0191d5SShuanglin Wang 	case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
1483dd0191d5SShuanglin Wang 		/* Initialize the result blob */
1484*0c036a14SPeter Spreadborough 		if (unlikely(ulp_blob_init(&res_blob, tbl->result_bit_size,
1485*0c036a14SPeter Spreadborough 					   parms->device_params->result_byte_order))) {
1486dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Failed initial result blob\n");
1487dd0191d5SShuanglin Wang 			return -EINVAL;
1488dd0191d5SShuanglin Wang 		}
1489dd0191d5SShuanglin Wang 
1490dd0191d5SShuanglin Wang 		/* read the interface table */
1491dd0191d5SShuanglin Wang 		idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
1492dd0191d5SShuanglin Wang 		res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
1493dd0191d5SShuanglin Wang 		rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
1494dd0191d5SShuanglin Wang 						   res_blob.data,
1495dd0191d5SShuanglin Wang 						   res_size,
1496dd0191d5SShuanglin Wang 						   res_blob.byte_order);
1497*0c036a14SPeter Spreadborough 		if (unlikely(rc))
1498dd0191d5SShuanglin Wang 			BNXT_DRV_DBG(ERR, "Scan and extract failed rc=%d\n",
1499dd0191d5SShuanglin Wang 				     rc);
1500dd0191d5SShuanglin Wang 		return rc;
1501dd0191d5SShuanglin Wang 	case BNXT_ULP_IF_TBL_OPC_NOT_USED:
1502dd0191d5SShuanglin Wang 		return rc; /* skip it */
1503dd0191d5SShuanglin Wang 	default:
1504dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Invalid tbl index opcode\n");
1505dd0191d5SShuanglin Wang 		return -EINVAL;
1506dd0191d5SShuanglin Wang 	}
1507dd0191d5SShuanglin Wang 
1508dd0191d5SShuanglin Wang 	tbl_info.dir = tbl->direction;
1509dd0191d5SShuanglin Wang 	tbl_info.rsubtype = tbl->resource_type;
1510dd0191d5SShuanglin Wang 	tbl_info.id = (uint32_t)idx;
1511dd0191d5SShuanglin Wang 	data_p = ulp_blob_data_get(&data, &tmplen);
1512dd0191d5SShuanglin Wang 	data_size = ULP_BITS_2_BYTE(tmplen);
1513dd0191d5SShuanglin Wang 
1514dd0191d5SShuanglin Wang 	rc = tfc_if_tbl_set(tfcp, fw_fid, &tbl_info, (uint8_t *)data_p,
1515dd0191d5SShuanglin Wang 			    data_size);
1516*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1517dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
1518dd0191d5SShuanglin Wang 			     "Failed to write the if tbl entry %d:%d\n",
1519dd0191d5SShuanglin Wang 			     tbl->resource_type, (uint32_t)idx);
1520dd0191d5SShuanglin Wang 		return rc;
1521dd0191d5SShuanglin Wang 	}
1522dd0191d5SShuanglin Wang 
1523dd0191d5SShuanglin Wang 	return rc;
1524dd0191d5SShuanglin Wang }
1525dd0191d5SShuanglin Wang 
1526dd0191d5SShuanglin Wang static int32_t
1527dd0191d5SShuanglin Wang ulp_mapper_tfc_ident_alloc(struct bnxt_ulp_context *ulp_ctx,
1528dd0191d5SShuanglin Wang 			   uint32_t session_type __rte_unused,
1529dd0191d5SShuanglin Wang 			   uint16_t ident_type,
1530dd0191d5SShuanglin Wang 			   uint8_t direction,
15312aa70990SKishore Padmanabha 			   enum cfa_track_type tt,
1532dd0191d5SShuanglin Wang 			   uint64_t *identifier_id)
1533dd0191d5SShuanglin Wang {
1534dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
1535dd0191d5SShuanglin Wang 	struct tfc_identifier_info ident_info = { 0 };
1536dd0191d5SShuanglin Wang 	int32_t rc = 0;
1537dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
1538dd0191d5SShuanglin Wang 
1539*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &fw_fid))) {
1540dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func_id\n");
1541dd0191d5SShuanglin Wang 		return -EINVAL;
1542dd0191d5SShuanglin Wang 	}
1543dd0191d5SShuanglin Wang 
1544dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx);
1545*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
1546dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n");
1547dd0191d5SShuanglin Wang 		return -EINVAL;
1548dd0191d5SShuanglin Wang 	}
1549dd0191d5SShuanglin Wang 
1550dd0191d5SShuanglin Wang 	ident_info.dir = direction;
1551dd0191d5SShuanglin Wang 	ident_info.rsubtype = ident_type;
1552dd0191d5SShuanglin Wang 
1553dd0191d5SShuanglin Wang 	rc = tfc_identifier_alloc(tfcp, fw_fid, tt, &ident_info);
1554*0c036a14SPeter Spreadborough 	if (unlikely(rc != 0)) {
1555dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "alloc failed %d\n", rc);
1556dd0191d5SShuanglin Wang 		return rc;
1557dd0191d5SShuanglin Wang 	}
1558dd0191d5SShuanglin Wang 	*identifier_id = ident_info.id;
1559dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1560dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1561dd0191d5SShuanglin Wang 	BNXT_DRV_INF("Allocated Identifier [%s]:[%s] = 0x%X\n",
1562dd0191d5SShuanglin Wang 		     tfc_dir_2_str(direction),
1563dd0191d5SShuanglin Wang 		     tfc_ident_2_str(ident_info.rsubtype), ident_info.id);
1564dd0191d5SShuanglin Wang #endif
1565dd0191d5SShuanglin Wang #endif
1566dd0191d5SShuanglin Wang 
1567dd0191d5SShuanglin Wang 	return rc;
1568dd0191d5SShuanglin Wang }
1569dd0191d5SShuanglin Wang 
1570dd0191d5SShuanglin Wang static int32_t
1571dd0191d5SShuanglin Wang ulp_mapper_tfc_ident_free(struct bnxt_ulp_context *ulp_ctx,
1572dd0191d5SShuanglin Wang 			  struct ulp_flow_db_res_params *res)
1573dd0191d5SShuanglin Wang {
1574dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
1575dd0191d5SShuanglin Wang 	struct tfc_identifier_info ident_info = { 0 };
1576dd0191d5SShuanglin Wang 	int32_t rc = 0;
1577dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
1578dd0191d5SShuanglin Wang 
1579*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &fw_fid))) {
1580dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func_id\n");
1581dd0191d5SShuanglin Wang 		return -EINVAL;
1582dd0191d5SShuanglin Wang 	}
1583dd0191d5SShuanglin Wang 
1584dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx);
1585*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
1586dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n");
1587dd0191d5SShuanglin Wang 		return -EINVAL;
1588dd0191d5SShuanglin Wang 	}
1589dd0191d5SShuanglin Wang 
1590dd0191d5SShuanglin Wang 	ident_info.dir = (enum cfa_dir)res->direction;
1591dd0191d5SShuanglin Wang 	ident_info.rsubtype = res->resource_type;
1592dd0191d5SShuanglin Wang 	ident_info.id = res->resource_hndl;
1593dd0191d5SShuanglin Wang 
1594dd0191d5SShuanglin Wang 	rc = tfc_identifier_free(tfcp, fw_fid, &ident_info);
1595*0c036a14SPeter Spreadborough 	if (unlikely(rc != 0)) {
1596dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "free failed %d\n", rc);
1597dd0191d5SShuanglin Wang 		return rc;
1598dd0191d5SShuanglin Wang 	}
1599dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1600dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1601be4732e8SMike Baucom 	BNXT_DRV_DBG(DEBUG, "Freed Identifier [%s]:[%s] = 0x%X\n",
1602dd0191d5SShuanglin Wang 		     tfc_dir_2_str(ident_info.dir),
1603dd0191d5SShuanglin Wang 		     tfc_ident_2_str(ident_info.rsubtype), ident_info.id);
1604dd0191d5SShuanglin Wang #endif
1605dd0191d5SShuanglin Wang #endif
1606dd0191d5SShuanglin Wang 
1607dd0191d5SShuanglin Wang 	return rc;
1608dd0191d5SShuanglin Wang }
1609dd0191d5SShuanglin Wang 
1610dd0191d5SShuanglin Wang static inline int32_t
1611dd0191d5SShuanglin Wang ulp_mapper_tfc_tcam_entry_free(struct bnxt_ulp_context *ulp,
1612dd0191d5SShuanglin Wang 			       struct ulp_flow_db_res_params *res)
1613dd0191d5SShuanglin Wang {
1614dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
1615dd0191d5SShuanglin Wang 	struct tfc_tcam_info tcam_info = { 0 };
1616dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
1617dd0191d5SShuanglin Wang 
1618*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(ulp, &fw_fid))) {
1619dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func_id\n");
1620dd0191d5SShuanglin Wang 		return -EINVAL;
1621dd0191d5SShuanglin Wang 	}
1622dd0191d5SShuanglin Wang 
1623dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(ulp);
1624*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
1625dd0191d5SShuanglin Wang 		PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer");
1626dd0191d5SShuanglin Wang 		return -EINVAL;
1627dd0191d5SShuanglin Wang 	}
1628dd0191d5SShuanglin Wang 	tcam_info.dir = (enum cfa_dir)res->direction;
1629dd0191d5SShuanglin Wang 	tcam_info.rsubtype = res->resource_type;
1630dd0191d5SShuanglin Wang 	tcam_info.id = (uint16_t)res->resource_hndl;
1631dd0191d5SShuanglin Wang 
1632*0c036a14SPeter Spreadborough 	if (unlikely(!tfcp || tfc_tcam_free(tfcp, fw_fid, &tcam_info))) {
1633dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Unable to free tcam resource %u\n",
1634dd0191d5SShuanglin Wang 			    tcam_info.id);
1635dd0191d5SShuanglin Wang 		return -EINVAL;
1636dd0191d5SShuanglin Wang 	}
1637be4732e8SMike Baucom #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1638be4732e8SMike Baucom #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1639be4732e8SMike Baucom 	BNXT_DRV_DBG(DEBUG, "Freed TCAM [%s]:[%s] = 0x%X\n",
1640be4732e8SMike Baucom 		     tfc_dir_2_str(tcam_info.dir),
1641be4732e8SMike Baucom 		     tfc_tcam_2_str(tcam_info.rsubtype), tcam_info.id);
1642be4732e8SMike Baucom #endif
1643be4732e8SMike Baucom #endif
1644dd0191d5SShuanglin Wang 	return 0;
1645dd0191d5SShuanglin Wang }
1646dd0191d5SShuanglin Wang 
1647dd0191d5SShuanglin Wang static uint32_t
1648dd0191d5SShuanglin Wang ulp_mapper_tfc_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms *parm __rte_unused,
1649dd0191d5SShuanglin Wang 				struct bnxt_ulp_mapper_tbl_info *tbl,
1650dd0191d5SShuanglin Wang 				uint16_t blob_len,
1651dd0191d5SShuanglin Wang 				uint16_t *out_len)
1652dd0191d5SShuanglin Wang {
1653dd0191d5SShuanglin Wang 	switch (tbl->resource_type) {
1654dd0191d5SShuanglin Wang 	case CFA_RSUBTYPE_CMM_ACT:
1655dd0191d5SShuanglin Wang 		*out_len = ULP_BITS_TO_32_BYTE_WORD(blob_len);
1656dd0191d5SShuanglin Wang 		*out_len = *out_len * 256;
1657dd0191d5SShuanglin Wang 		break;
1658dd0191d5SShuanglin Wang 	default:
1659dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Not a dynamic table %d\n", tbl->resource_type);
1660dd0191d5SShuanglin Wang 		*out_len = blob_len;
1661dd0191d5SShuanglin Wang 		break;
1662dd0191d5SShuanglin Wang 	}
1663dd0191d5SShuanglin Wang 
1664dd0191d5SShuanglin Wang 	return tbl->resource_type;
1665dd0191d5SShuanglin Wang }
1666dd0191d5SShuanglin Wang 
1667dd0191d5SShuanglin Wang static int32_t
1668dd0191d5SShuanglin Wang ulp_mapper_tfc_index_tbl_alloc_process(struct bnxt_ulp_context *ulp,
1669dd0191d5SShuanglin Wang 				       uint32_t session_type __rte_unused,
1670dd0191d5SShuanglin Wang 				       uint16_t table_type,
1671dd0191d5SShuanglin Wang 				       uint8_t direction,
1672dd0191d5SShuanglin Wang 				       uint64_t *index)
1673dd0191d5SShuanglin Wang {
1674dd0191d5SShuanglin Wang 	enum cfa_track_type tt = CFA_TRACK_TYPE_SID;
1675dd0191d5SShuanglin Wang 	struct tfc_idx_tbl_info tbl_info = { 0 };
1676dd0191d5SShuanglin Wang 	struct tfc *tfcp = NULL;
1677dd0191d5SShuanglin Wang 	uint16_t fw_fid = 0;
1678dd0191d5SShuanglin Wang 	int32_t rc = 0;
1679dd0191d5SShuanglin Wang 
1680dd0191d5SShuanglin Wang 	tfcp = bnxt_ulp_cntxt_tfcp_get(ulp);
1681*0c036a14SPeter Spreadborough 	if (unlikely(tfcp == NULL)) {
1682dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n");
1683dd0191d5SShuanglin Wang 		return -EINVAL;
1684dd0191d5SShuanglin Wang 	}
1685dd0191d5SShuanglin Wang 
1686*0c036a14SPeter Spreadborough 	if (unlikely(bnxt_ulp_cntxt_fid_get(ulp, &fw_fid))) {
1687dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Failed to get func id\n");
1688dd0191d5SShuanglin Wang 		return -EINVAL;
1689dd0191d5SShuanglin Wang 	}
1690dd0191d5SShuanglin Wang 
1691dd0191d5SShuanglin Wang 	tbl_info.rsubtype = table_type;
1692dd0191d5SShuanglin Wang 	tbl_info.dir = direction;
1693dd0191d5SShuanglin Wang 	rc = tfc_idx_tbl_alloc(tfcp, fw_fid, tt, &tbl_info);
1694*0c036a14SPeter Spreadborough 	if (unlikely(rc)) {
1695dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
1696dd0191d5SShuanglin Wang 			     tfc_idx_tbl_2_str(tbl_info.rsubtype),
1697dd0191d5SShuanglin Wang 			     tfc_dir_2_str(direction), rc);
1698dd0191d5SShuanglin Wang 		return rc;
1699dd0191d5SShuanglin Wang 	}
1700dd0191d5SShuanglin Wang 
1701dd0191d5SShuanglin Wang 	*index = tbl_info.id;
1702dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1703dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1704dd0191d5SShuanglin Wang 	BNXT_DRV_DBG(DEBUG, "Allocated Table Index [%s][%s] = 0x%04x\n",
1705dd0191d5SShuanglin Wang 		     tfc_idx_tbl_2_str(table_type), tfc_dir_2_str(direction),
1706dd0191d5SShuanglin Wang 		     tbl_info.id);
1707dd0191d5SShuanglin Wang #endif
1708dd0191d5SShuanglin Wang #endif
1709dd0191d5SShuanglin Wang 	return rc;
1710dd0191d5SShuanglin Wang }
1711dd0191d5SShuanglin Wang 
1712dd0191d5SShuanglin Wang static int32_t
1713dd0191d5SShuanglin Wang ulp_mapper_tfc_app_glb_resource_info_init(struct bnxt_ulp_context
1714dd0191d5SShuanglin Wang 					  *ulp_ctx __rte_unused,
1715dd0191d5SShuanglin Wang 					  struct bnxt_ulp_mapper_data
1716dd0191d5SShuanglin Wang 					  *mapper_data __rte_unused)
1717dd0191d5SShuanglin Wang {
1718dd0191d5SShuanglin Wang 	/* Not supported Shared Apps yet on TFC API */
1719dd0191d5SShuanglin Wang 	return 0;
1720dd0191d5SShuanglin Wang }
1721dd0191d5SShuanglin Wang 
1722dd0191d5SShuanglin Wang static int32_t
1723dd0191d5SShuanglin Wang ulp_mapper_tfc_handle_to_offset(struct bnxt_ulp_mapper_parms *parms __rte_unused,
1724dd0191d5SShuanglin Wang 				uint64_t handle,
1725dd0191d5SShuanglin Wang 				uint32_t offset,
1726dd0191d5SShuanglin Wang 				uint64_t *result)
1727dd0191d5SShuanglin Wang {
1728dd0191d5SShuanglin Wang 	uint32_t val = 0;
1729dd0191d5SShuanglin Wang 	int32_t rc = 0;
1730dd0191d5SShuanglin Wang 
1731dd0191d5SShuanglin Wang 	TFC_GET_32B_OFFSET_ACT_HANDLE(val, &handle);
1732dd0191d5SShuanglin Wang 
1733dd0191d5SShuanglin Wang 	switch (offset) {
1734dd0191d5SShuanglin Wang 	case 0:
1735dd0191d5SShuanglin Wang 		val = val << 5;
1736dd0191d5SShuanglin Wang 		break;
1737dd0191d5SShuanglin Wang 	case 4:
1738dd0191d5SShuanglin Wang 		val = val << 3;
1739dd0191d5SShuanglin Wang 		break;
1740dd0191d5SShuanglin Wang 	case 8:
1741dd0191d5SShuanglin Wang 		val = val << 2;
1742dd0191d5SShuanglin Wang 		break;
1743dd0191d5SShuanglin Wang 	case 16:
1744dd0191d5SShuanglin Wang 		val = val << 1;
1745dd0191d5SShuanglin Wang 		break;
1746dd0191d5SShuanglin Wang 	case 32:
1747dd0191d5SShuanglin Wang 		break;
1748dd0191d5SShuanglin Wang 	default:
1749dd0191d5SShuanglin Wang 		return -EINVAL;
1750dd0191d5SShuanglin Wang 	}
1751dd0191d5SShuanglin Wang 
1752dd0191d5SShuanglin Wang 	*result = val;
1753dd0191d5SShuanglin Wang 	return rc;
1754dd0191d5SShuanglin Wang }
1755dd0191d5SShuanglin Wang 
1756dd0191d5SShuanglin Wang static int
1757dd0191d5SShuanglin Wang ulp_mapper_tfc_mpc_batch_start(struct tfc_mpc_batch_info_t *batch_info)
1758dd0191d5SShuanglin Wang {
1759dd0191d5SShuanglin Wang 	return tfc_mpc_batch_start(batch_info);
1760dd0191d5SShuanglin Wang }
1761dd0191d5SShuanglin Wang 
1762dd0191d5SShuanglin Wang const struct ulp_mapper_core_ops ulp_mapper_tfc_core_ops = {
1763dd0191d5SShuanglin Wang 	.ulp_mapper_core_tcam_tbl_process = ulp_mapper_tfc_tcam_tbl_process,
1764dd0191d5SShuanglin Wang 	.ulp_mapper_core_tcam_entry_free = ulp_mapper_tfc_tcam_entry_free,
1765dd0191d5SShuanglin Wang 	.ulp_mapper_core_em_tbl_process = ulp_mapper_tfc_em_tbl_process,
1766dd0191d5SShuanglin Wang 	.ulp_mapper_core_em_entry_free = ulp_mapper_tfc_em_entry_free,
1767dd0191d5SShuanglin Wang 	.ulp_mapper_core_index_tbl_process = ulp_mapper_tfc_index_tbl_process,
1768dd0191d5SShuanglin Wang 	.ulp_mapper_core_index_entry_free = ulp_mapper_tfc_index_entry_free,
1769dd0191d5SShuanglin Wang 	.ulp_mapper_core_cmm_tbl_process = ulp_mapper_tfc_cmm_tbl_process,
1770dd0191d5SShuanglin Wang 	.ulp_mapper_core_cmm_entry_free = ulp_mapper_tfc_cmm_entry_free,
1771dd0191d5SShuanglin Wang 	.ulp_mapper_core_if_tbl_process = ulp_mapper_tfc_if_tbl_process,
1772dd0191d5SShuanglin Wang 	.ulp_mapper_core_ident_alloc_process = ulp_mapper_tfc_ident_alloc,
1773dd0191d5SShuanglin Wang 	.ulp_mapper_core_ident_free = ulp_mapper_tfc_ident_free,
1774dd0191d5SShuanglin Wang 	.ulp_mapper_core_dyn_tbl_type_get = ulp_mapper_tfc_dyn_tbl_type_get,
1775dd0191d5SShuanglin Wang 	.ulp_mapper_core_index_tbl_alloc_process =
1776dd0191d5SShuanglin Wang 		ulp_mapper_tfc_index_tbl_alloc_process,
1777dd0191d5SShuanglin Wang 	.ulp_mapper_core_app_glb_res_info_init =
1778dd0191d5SShuanglin Wang 		ulp_mapper_tfc_app_glb_resource_info_init,
1779dd0191d5SShuanglin Wang 	.ulp_mapper_core_handle_to_offset = ulp_mapper_tfc_handle_to_offset,
1780dd0191d5SShuanglin Wang 	.ulp_mapper_mpc_batch_start = ulp_mapper_tfc_mpc_batch_start,
1781dd0191d5SShuanglin Wang 	.ulp_mapper_mpc_batch_started = ulp_mapper_tfc_mpc_batch_started,
1782dd0191d5SShuanglin Wang 	.ulp_mapper_mpc_batch_end = ulp_mapper_tfc_mpc_batch_end
1783dd0191d5SShuanglin Wang };
1784