xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_mapper.c (revision 64f131a8)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include "bnxt.h"
9 #include "ulp_template_db_enum.h"
10 #include "ulp_template_struct.h"
11 #include "bnxt_tf_common.h"
12 #include "ulp_utils.h"
13 #include "bnxt_ulp.h"
14 #include "tfp.h"
15 #include "tf_ext_flow_handle.h"
16 #include "ulp_mark_mgr.h"
17 #include "ulp_mapper.h"
18 #include "ulp_flow_db.h"
19 #include "tf_util.h"
20 #include "ulp_template_db_tbl.h"
21 #include "ulp_port_db.h"
22 #include "ulp_ha_mgr.h"
23 #include "bnxt_tf_pmd_shim.h"
24 
25 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
26 #include "ulp_template_debug_proto.h"
27 #include "ulp_tf_debug.h"
28 #endif
29 
30 static uint8_t mapper_fld_zeros[16] = { 0 };
31 
32 static uint8_t mapper_fld_ones[16] = {
33 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
34 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
35 };
36 
37 static uint8_t mapper_fld_one[16] = {
38 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
39 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
40 };
41 
42 static const char *
43 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type)
44 {
45 	switch (tmpl_type) {
46 	case BNXT_ULP_TEMPLATE_TYPE_CLASS:
47 		return "class";
48 	case BNXT_ULP_TEMPLATE_TYPE_ACTION:
49 		return "action";
50 	default:
51 		return "invalid template type";
52 	}
53 }
54 
55 static struct bnxt_ulp_glb_resource_info *
56 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
57 {
58 	if (!num_entries)
59 		return NULL;
60 	*num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
61 	return ulp_glb_resource_tbl;
62 }
63 
64 /*
65  * Read the global resource from the mapper global resource list
66  *
67  * The regval is always returned in big-endian.
68  *
69  * returns 0 on success
70  */
71 static int32_t
72 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
73 			     enum tf_dir dir,
74 			     uint16_t idx,
75 			     uint64_t *regval,
76 			     bool *shared)
77 {
78 	if (!mapper_data || !regval || !shared ||
79 	    dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)
80 		return -EINVAL;
81 
82 	*regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
83 	*shared = mapper_data->glb_res_tbl[dir][idx].shared;
84 	return 0;
85 }
86 
87 /*
88  * Write a global resource to the mapper global resource list
89  *
90  * The regval value must be in big-endian.
91  *
92  * return 0 on success.
93  */
94 static int32_t
95 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
96 			      struct bnxt_ulp_glb_resource_info *res,
97 			      uint64_t regval, bool shared)
98 {
99 	struct bnxt_ulp_mapper_glb_resource_entry *ent;
100 
101 	/* validate the arguments */
102 	if (!data || res->direction >= TF_DIR_MAX ||
103 	    res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)
104 		return -EINVAL;
105 
106 	/* write to the mapper data */
107 	ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
108 	ent->resource_func = res->resource_func;
109 	ent->resource_type = res->resource_type;
110 	ent->resource_hndl = regval;
111 	ent->shared = shared;
112 	return 0;
113 }
114 
115 /*
116  * Internal function to allocate identity resource and store it in mapper data.
117  *
118  * returns 0 on success
119  */
120 static int32_t
121 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
122 				   struct bnxt_ulp_mapper_data *mapper_data,
123 				   struct bnxt_ulp_glb_resource_info *glb_res)
124 {
125 	struct tf_alloc_identifier_parms iparms = { 0 };
126 	struct tf_free_identifier_parms fparms;
127 	uint64_t regval;
128 	struct tf *tfp;
129 	int32_t rc = 0;
130 
131 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
132 	if (!tfp)
133 		return -EINVAL;
134 
135 	iparms.ident_type = glb_res->resource_type;
136 	iparms.dir = glb_res->direction;
137 
138 	/* Allocate the Identifier using tf api */
139 	rc = tf_alloc_identifier(tfp, &iparms);
140 	if (rc) {
141 		BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
142 			    tf_dir_2_str(iparms.dir),
143 			    iparms.ident_type);
144 		return rc;
145 	}
146 
147 	/* entries are stored as big-endian format */
148 	regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
149 	/*
150 	 * write to the mapper global resource
151 	 * Shared resources are never allocated through this method, so the
152 	 * shared flag is always false.
153 	 */
154 	rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false);
155 	if (rc) {
156 		BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
157 		/* Free the identifier when update failed */
158 		fparms.dir = iparms.dir;
159 		fparms.ident_type = iparms.ident_type;
160 		fparms.id = iparms.id;
161 		tf_free_identifier(tfp, &fparms);
162 		return rc;
163 	}
164 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
165 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
166 	BNXT_TF_DBG(DEBUG, "Allocated Glb Res Ident [%s][%d][%d] = 0x%04x\n",
167 		    tf_dir_2_str(iparms.dir),
168 		    glb_res->glb_regfile_index, iparms.ident_type, iparms.id);
169 #endif
170 #endif
171 	return rc;
172 }
173 
174 /*
175  * Internal function to allocate index tbl resource and store it in mapper data.
176  *
177  * returns 0 on success
178  */
179 static int32_t
180 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
181 				    struct bnxt_ulp_mapper_data *mapper_data,
182 				    struct bnxt_ulp_glb_resource_info *glb_res)
183 {
184 	struct tf_alloc_tbl_entry_parms	aparms = { 0 };
185 	struct tf_free_tbl_entry_parms	free_parms = { 0 };
186 	uint64_t regval;
187 	struct tf *tfp;
188 	uint32_t tbl_scope_id;
189 	int32_t rc = 0;
190 
191 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
192 	if (!tfp)
193 		return -EINVAL;
194 
195 	/* Get the scope id */
196 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
197 	if (rc) {
198 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
199 		return rc;
200 	}
201 
202 	aparms.type = glb_res->resource_type;
203 	aparms.dir = glb_res->direction;
204 	aparms.tbl_scope_id = tbl_scope_id;
205 
206 	/* Allocate the index tbl using tf api */
207 	rc = tf_alloc_tbl_entry(tfp, &aparms);
208 	if (rc) {
209 		BNXT_TF_DBG(ERR, "Failed to alloc index table [%s][%d]\n",
210 			    tf_dir_2_str(aparms.dir), aparms.type);
211 		return rc;
212 	}
213 
214 	/* entries are stored as big-endian format */
215 	regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
216 	/*
217 	 * write to the mapper global resource
218 	 * Shared resources are never allocated through this method, so the
219 	 * shared flag is always false.
220 	 */
221 	rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false);
222 	if (rc) {
223 		BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
224 		/* Free the identifier when update failed */
225 		free_parms.dir = aparms.dir;
226 		free_parms.type = aparms.type;
227 		free_parms.idx = aparms.idx;
228 		tf_free_tbl_entry(tfp, &free_parms);
229 		return rc;
230 	}
231 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
232 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
233 	BNXT_TF_DBG(DEBUG, "Allocated Glb Res Index [%s][%d][%d] = 0x%04x\n",
234 		    tf_dir_2_str(aparms.dir),
235 		    glb_res->glb_regfile_index, aparms.type, aparms.idx);
236 #endif
237 #endif
238 	return rc;
239 }
240 
241 static int32_t
242 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
243 			     uint32_t operand,
244 			     uint8_t *val)
245 {
246 	uint32_t t_idx;
247 
248 	t_idx = parms->app_id << (BNXT_ULP_APP_ID_SHIFT +
249 				  BNXT_ULP_HDR_SIG_ID_SHIFT +
250 				  BNXT_ULP_GLB_FIELD_TBL_SHIFT);
251 	t_idx += parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
252 				      BNXT_ULP_GLB_FIELD_TBL_SHIFT);
253 	t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
254 		BNXT_ULP_GLB_FIELD_TBL_SHIFT;
255 	t_idx += operand;
256 
257 	if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
258 		BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
259 			    parms->class_tid, t_idx, operand);
260 		*val = 0;
261 		return -EINVAL; /* error */
262 	}
263 	*val = ulp_glb_field_tbl[t_idx];
264 	return 0;
265 }
266 
267 /*
268  * Get the size of the action property for a given index.
269  *
270  * idx [in] The index for the action property
271  *
272  * returns the size of the action property.
273  */
274 static uint32_t
275 ulp_mapper_act_prop_size_get(uint32_t idx)
276 {
277 	if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
278 		return 0;
279 	return ulp_act_prop_map_table[idx];
280 }
281 
282 static struct bnxt_ulp_mapper_cond_info *
283 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
284 				uint32_t tid,
285 				uint32_t *num_tbls,
286 				enum bnxt_ulp_cond_list_opc *opc)
287 {
288 	uint32_t idx;
289 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
290 
291 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
292 	*num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
293 	*opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
294 	idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
295 
296 	return &dev_tbls->cond_list[idx];
297 }
298 
299 static struct bnxt_ulp_mapper_cond_info *
300 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
301 				struct bnxt_ulp_mapper_tbl_info *tbl,
302 				uint32_t *num_tbls,
303 				enum bnxt_ulp_cond_list_opc *opc)
304 {
305 	uint32_t idx;
306 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
307 
308 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
309 	*num_tbls = tbl->execute_info.cond_nums;
310 	*opc = tbl->execute_info.cond_list_opcode;
311 	idx = tbl->execute_info.cond_start_idx;
312 
313 	return &dev_tbls->cond_list[idx];
314 }
315 
316 /*
317  * Get a list of classifier tables that implement the flow
318  * Gets a device dependent list of tables that implement the class template id
319  *
320  * mparms [in] The mappers parms with data related to the flow.
321  *
322  * tid [in] The template id that matches the flow
323  *
324  * num_tbls [out] The number of classifier tables in the returned array
325  *
326  * returns An array of classifier tables to implement the flow, or NULL on
327  * error
328  */
329 static struct bnxt_ulp_mapper_tbl_info *
330 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
331 			uint32_t tid,
332 			uint32_t *num_tbls)
333 {
334 	uint32_t idx;
335 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
336 
337 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
338 
339 	idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
340 	*num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
341 
342 	return &dev_tbls->tbl_list[idx];
343 }
344 
345 /*
346  * Get the list of key fields that implement the flow.
347  *
348  * mparms [in] The mapper parms with information about the flow
349  *
350  * tbl [in] A single table instance to get the key fields from
351  *
352  * num_flds [out] The number of key fields in the returned array
353  *
354  * Returns array of Key fields, or NULL on error.
355  */
356 static struct bnxt_ulp_mapper_key_info *
357 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
358 			  struct bnxt_ulp_mapper_tbl_info *tbl,
359 			  uint32_t *num_flds)
360 {
361 	uint32_t idx;
362 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
363 
364 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
365 	if (!dev_tbls->key_info_list) {
366 		*num_flds = 0;
367 		return NULL;
368 	}
369 
370 	idx		= tbl->key_start_idx;
371 	*num_flds	= tbl->key_num_fields;
372 
373 	return &dev_tbls->key_info_list[idx];
374 }
375 
376 /*
377  * Get the list of data fields that implement the flow.
378  *
379  * mparms [in] The mapper parms with information about the flow
380  *
381  * tbl [in] A single table instance to get the data fields from
382  *
383  * num_flds [out] The number of data fields in the returned array.
384  *
385  * num_encap_flds [out] The number of encap fields in the returned array.
386  *
387  * Returns array of data fields, or NULL on error.
388  */
389 static struct bnxt_ulp_mapper_field_info *
390 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
391 			     struct bnxt_ulp_mapper_tbl_info *tbl,
392 			     uint32_t *num_flds,
393 			     uint32_t *num_encap_flds)
394 {
395 	uint32_t idx;
396 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
397 
398 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
399 	if (!dev_tbls->result_field_list) {
400 		*num_flds = 0;
401 		*num_encap_flds = 0;
402 		return NULL;
403 	}
404 
405 	idx		= tbl->result_start_idx;
406 	*num_flds	= tbl->result_num_fields;
407 	*num_encap_flds = tbl->encap_num_fields;
408 
409 	return &dev_tbls->result_field_list[idx];
410 }
411 
412 /*
413  * Get the list of ident fields that implement the flow
414  *
415  * tbl [in] A single table instance to get the ident fields from
416  *
417  * num_flds [out] The number of ident fields in the returned array
418  *
419  * returns array of ident fields, or NULL on error
420  */
421 static struct bnxt_ulp_mapper_ident_info *
422 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
423 			    struct bnxt_ulp_mapper_tbl_info *tbl,
424 			    uint32_t *num_flds)
425 {
426 	uint32_t idx;
427 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
428 
429 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
430 	if (!dev_tbls->ident_list) {
431 		*num_flds = 0;
432 		return NULL;
433 	}
434 
435 	idx = tbl->ident_start_idx;
436 	*num_flds = tbl->ident_nums;
437 
438 	return &dev_tbls->ident_list[idx];
439 }
440 
441 static enum tf_tbl_type
442 ulp_mapper_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms *mparms,
443 			    struct bnxt_ulp_mapper_tbl_info *tbl,
444 			    struct ulp_blob *bdata,
445 			    uint16_t *out_len)
446 {
447 	struct bnxt_ulp_device_params *d_params = mparms->device_params;
448 	uint16_t blob_len = ulp_blob_data_len_get(bdata);
449 	struct bnxt_ulp_dyn_size_map *size_map;
450 	uint32_t i;
451 
452 	if (d_params->dynamic_sram_en) {
453 		switch (tbl->resource_type) {
454 		case TF_TBL_TYPE_ACT_ENCAP_8B:
455 		case TF_TBL_TYPE_ACT_ENCAP_16B:
456 		case TF_TBL_TYPE_ACT_ENCAP_32B:
457 		case TF_TBL_TYPE_ACT_ENCAP_64B:
458 			size_map = d_params->dyn_encap_sizes;
459 			for (i = 0; i < d_params->dyn_encap_list_size; i++) {
460 				if (blob_len <= size_map[i].slab_size) {
461 					*out_len = size_map[i].slab_size;
462 					return size_map[i].tbl_type;
463 				}
464 			}
465 			break;
466 		case TF_TBL_TYPE_ACT_MODIFY_8B:
467 		case TF_TBL_TYPE_ACT_MODIFY_16B:
468 		case TF_TBL_TYPE_ACT_MODIFY_32B:
469 		case TF_TBL_TYPE_ACT_MODIFY_64B:
470 			size_map = d_params->dyn_modify_sizes;
471 			for (i = 0; i < d_params->dyn_modify_list_size; i++) {
472 				if (blob_len <= size_map[i].slab_size) {
473 					*out_len = size_map[i].slab_size;
474 					return size_map[i].tbl_type;
475 				}
476 			}
477 			break;
478 		default:
479 			break;
480 		}
481 	}
482 	return tbl->resource_type;
483 }
484 
485 static uint16_t
486 ulp_mapper_dyn_blob_size_get(struct bnxt_ulp_mapper_parms *mparms,
487 			     struct bnxt_ulp_mapper_tbl_info *tbl)
488 {
489 	struct bnxt_ulp_device_params *d_params = mparms->device_params;
490 
491 	if (d_params->dynamic_sram_en) {
492 		switch (tbl->resource_type) {
493 		case TF_TBL_TYPE_ACT_ENCAP_8B:
494 		case TF_TBL_TYPE_ACT_ENCAP_16B:
495 		case TF_TBL_TYPE_ACT_ENCAP_32B:
496 		case TF_TBL_TYPE_ACT_ENCAP_64B:
497 		case TF_TBL_TYPE_ACT_MODIFY_8B:
498 		case TF_TBL_TYPE_ACT_MODIFY_16B:
499 		case TF_TBL_TYPE_ACT_MODIFY_32B:
500 		case TF_TBL_TYPE_ACT_MODIFY_64B:
501 			/* return max size */
502 			return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
503 		default:
504 			break;
505 		}
506 	} else if (tbl->encap_num_fields) {
507 		return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
508 	}
509 	return tbl->result_bit_size;
510 }
511 
512 static inline int32_t
513 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp,
514 			   struct tf *tfp,
515 			   struct ulp_flow_db_res_params *res)
516 {
517 	struct tf_free_tcam_entry_parms fparms = {
518 		.dir		= res->direction,
519 		.tcam_tbl_type	= res->resource_type,
520 		.idx		= (uint16_t)res->resource_hndl
521 	};
522 
523 	/* If HA is enabled, we may have to remap the TF Type */
524 	if (bnxt_ulp_cntxt_ha_enabled(ulp)) {
525 		enum ulp_ha_mgr_region region;
526 		int32_t rc;
527 
528 		switch (res->resource_type) {
529 		case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH:
530 		case TF_TCAM_TBL_TYPE_WC_TCAM_LOW:
531 			rc = ulp_ha_mgr_region_get(ulp, &region);
532 			if (rc)
533 				/* Log this, but assume region is correct */
534 				BNXT_TF_DBG(ERR,
535 					    "Unable to get HA region (%d)\n",
536 					    rc);
537 			else
538 				fparms.tcam_tbl_type =
539 					(region == ULP_HA_REGION_LOW) ?
540 					TF_TCAM_TBL_TYPE_WC_TCAM_LOW :
541 					TF_TCAM_TBL_TYPE_WC_TCAM_HIGH;
542 			break;
543 		default:
544 			break;
545 		}
546 	}
547 	return tf_free_tcam_entry(tfp, &fparms);
548 }
549 
550 static inline int32_t
551 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
552 			    struct tf *tfp,
553 			    struct ulp_flow_db_res_params *res)
554 {
555 	struct tf_free_tbl_entry_parms fparms = {
556 		.dir	= res->direction,
557 		.type	= res->resource_type,
558 		.idx	= (uint32_t)res->resource_hndl
559 	};
560 
561 	/*
562 	 * Just get the table scope, it will be ignored if not necessary
563 	 * by the tf_free_tbl_entry
564 	 */
565 	(void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
566 
567 	return tf_free_tbl_entry(tfp, &fparms);
568 }
569 
570 static inline int32_t
571 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
572 			 struct tf *tfp,
573 			 struct ulp_flow_db_res_params *res)
574 {
575 	struct tf_delete_em_entry_parms fparms = { 0 };
576 	int32_t rc;
577 
578 	fparms.dir		= res->direction;
579 	fparms.flow_handle	= res->resource_hndl;
580 
581 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
582 	if (rc) {
583 		BNXT_TF_DBG(ERR, "Failed to get table scope\n");
584 		return -EINVAL;
585 	}
586 
587 	return tf_delete_em_entry(tfp, &fparms);
588 }
589 
590 static inline int32_t
591 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
592 		      struct tf *tfp,
593 		      struct ulp_flow_db_res_params *res)
594 {
595 	struct tf_free_identifier_parms fparms = {
596 		.dir		= res->direction,
597 		.ident_type	= res->resource_type,
598 		.id		= (uint16_t)res->resource_hndl
599 	};
600 
601 	return tf_free_identifier(tfp, &fparms);
602 }
603 
604 static inline int32_t
605 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
606 		     struct ulp_flow_db_res_params *res)
607 {
608 	return ulp_mark_db_mark_del(ulp,
609 				    res->resource_type,
610 				    res->resource_hndl);
611 }
612 
613 static inline int32_t
614 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
615 			    uint32_t parent_fid,
616 			    struct ulp_flow_db_res_params *res)
617 {
618 	uint32_t pc_idx;
619 
620 	pc_idx = (uint32_t)res->resource_hndl;
621 
622 	/* reset the child flow bitset*/
623 	if (ulp_flow_db_pc_db_parent_flow_set(ulp, pc_idx, parent_fid, 0)) {
624 		BNXT_TF_DBG(ERR, "error in reset parent flow bitset %x:%x\n",
625 			    pc_idx, parent_fid);
626 		return -EINVAL;
627 	}
628 	return 0;
629 }
630 
631 static inline int32_t
632 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
633 			   uint32_t child_fid,
634 			   struct ulp_flow_db_res_params *res)
635 {
636 	uint32_t pc_idx;
637 
638 	pc_idx = (uint32_t)res->resource_hndl;
639 
640 	/* reset the child flow bitset*/
641 	if (ulp_flow_db_pc_db_child_flow_set(ulp, pc_idx, child_fid, 0)) {
642 		BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
643 			    pc_idx, child_fid);
644 		return -EINVAL;
645 	}
646 	return 0;
647 }
648 
649 /*
650  * Process the flow database opcode alloc action.
651  * returns 0 on success
652  */
653 static int32_t
654 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
655 			     struct bnxt_ulp_mapper_tbl_info *tbl)
656 {
657 	uint32_t rid = 0;
658 	uint64_t val64;
659 	int32_t rc = 0;
660 
661 	/* allocate a new fid */
662 	rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
663 				   BNXT_ULP_FDB_TYPE_RID,
664 				   0, &rid);
665 	if (rc) {
666 		BNXT_TF_DBG(ERR,
667 			    "Unable to allocate flow table entry\n");
668 		return -EINVAL;
669 	}
670 	/* Store the allocated fid in regfile*/
671 	val64 = rid;
672 	rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
673 			       tfp_cpu_to_be_64(val64));
674 	if (rc) {
675 		BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
676 			    tbl->fdb_operand);
677 		ulp_flow_db_fid_free(parms->ulp_ctx,
678 				     BNXT_ULP_FDB_TYPE_RID, rid);
679 		return -EINVAL;
680 	}
681 	return 0;
682 }
683 
684 /*
685  * Process the flow database opcode action.
686  * returns 0 on success.
687  */
688 static int32_t
689 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
690 			   struct bnxt_ulp_mapper_tbl_info *tbl,
691 			   struct ulp_flow_db_res_params *fid_parms)
692 {
693 	uint32_t push_fid;
694 	uint64_t val64;
695 	enum bnxt_ulp_fdb_type flow_type;
696 	int32_t rc = 0;
697 
698 	switch (tbl->fdb_opcode) {
699 	case BNXT_ULP_FDB_OPC_PUSH_FID:
700 		push_fid = parms->fid;
701 		flow_type = parms->flow_type;
702 		break;
703 	case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
704 		/* get the fid from the regfile */
705 		rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
706 				      &val64);
707 		if (!rc) {
708 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
709 				    tbl->fdb_operand);
710 			return -EINVAL;
711 		}
712 		/* Use the extracted fid to update the flow resource */
713 		push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
714 		flow_type = BNXT_ULP_FDB_TYPE_RID;
715 		break;
716 	default:
717 		return rc; /* Nothing to be done */
718 	}
719 
720 	/* Add the resource to the flow database */
721 	rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
722 				      push_fid, fid_parms);
723 	if (rc)
724 		BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
725 			    push_fid, rc);
726 	return rc;
727 }
728 
729 /*
730  * Process the flow database opcode action.
731  * returns 0 on success.
732  */
733 static int32_t
734 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
735 				struct bnxt_ulp_mapper_tbl_info *tbl,
736 				uint32_t *priority)
737 {
738 	int32_t rc = 0;
739 
740 	switch (tbl->pri_opcode) {
741 	case BNXT_ULP_PRI_OPC_NOT_USED:
742 		*priority = 0;
743 		break;
744 	case BNXT_ULP_PRI_OPC_CONST:
745 		*priority = tbl->pri_operand;
746 		break;
747 	case BNXT_ULP_PRI_OPC_APP_PRI:
748 		*priority = parms->app_priority;
749 		break;
750 	default:
751 		BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
752 			    tbl->pri_opcode);
753 		rc = -EINVAL;
754 		break;
755 	}
756 	return rc;
757 }
758 
759 /*
760  * Process the identifier list in the given table.
761  * Extract the ident from the table entry and
762  * write it to the reg file.
763  * returns 0 on success.
764  */
765 static int32_t
766 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
767 			      struct bnxt_ulp_mapper_tbl_info *tbl,
768 			      uint8_t *byte_data,
769 			      uint32_t byte_data_size,
770 			      enum bnxt_ulp_byte_order byte_order)
771 {
772 	struct bnxt_ulp_mapper_ident_info *idents;
773 	uint32_t i, num_idents = 0;
774 	uint64_t val64;
775 
776 	/* validate the null arguments */
777 	if (!byte_data) {
778 		BNXT_TF_DBG(ERR, "invalid argument\n");
779 		return -EINVAL;
780 	}
781 
782 	/* Get the ident list and process each one */
783 	idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
784 
785 	for (i = 0; i < num_idents; i++) {
786 		/* check the size of the buffer for validation */
787 		if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
788 		    ULP_BYTE_2_BITS(byte_data_size) ||
789 		    idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
790 			BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
791 				    idents[i].ident_bit_pos,
792 				    idents[i].ident_bit_size,
793 				    byte_data_size);
794 			return -EINVAL;
795 		}
796 		val64 = 0;
797 		if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
798 			ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
799 					sizeof(val64),
800 					idents[i].ident_bit_pos,
801 					idents[i].ident_bit_size);
802 		else
803 			ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
804 					idents[i].ident_bit_pos,
805 					idents[i].ident_bit_size);
806 
807 		/* Write it to the regfile, val64 is already in big-endian*/
808 		if (ulp_regfile_write(parms->regfile,
809 				      idents[i].regfile_idx, val64)) {
810 			BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
811 				    idents[i].regfile_idx);
812 			return -EINVAL;
813 		}
814 	}
815 	return 0;
816 }
817 
818 /*
819  * Process the identifier instruction and either store it in the flow database
820  * or return it in the val (if not NULL) on success.  If val is NULL, the
821  * identifier is to be stored in the flow database.
822  */
823 static int32_t
824 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
825 			 struct bnxt_ulp_mapper_tbl_info *tbl,
826 			 struct bnxt_ulp_mapper_ident_info *ident,
827 			 uint16_t *val)
828 {
829 	struct ulp_flow_db_res_params	fid_parms;
830 	uint64_t id = 0;
831 	int32_t idx;
832 	struct tf_alloc_identifier_parms iparms = { 0 };
833 	struct tf_free_identifier_parms free_parms = { 0 };
834 	struct tf *tfp;
835 	int rc;
836 
837 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
838 	if (!tfp) {
839 		BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
840 		return -EINVAL;
841 	}
842 
843 	idx = ident->regfile_idx;
844 
845 	iparms.ident_type = ident->ident_type;
846 	iparms.dir = tbl->direction;
847 
848 	rc = tf_alloc_identifier(tfp, &iparms);
849 	if (rc) {
850 		BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
851 			    tf_dir_2_str(iparms.dir),
852 			    tf_ident_2_str(iparms.ident_type));
853 		return rc;
854 	}
855 	BNXT_TF_INF("Alloc ident %s:%s.success.\n",
856 		    tf_dir_2_str(iparms.dir),
857 		    tf_ident_2_str(iparms.ident_type));
858 
859 	id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
860 	if (ulp_regfile_write(parms->regfile, idx, id)) {
861 		BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
862 		rc = -EINVAL;
863 		/* Need to free the identifier, so goto error */
864 		goto error;
865 	}
866 
867 	/* Link the resource to the flow in the flow db */
868 	if (!val) {
869 		memset(&fid_parms, 0, sizeof(fid_parms));
870 		fid_parms.direction		= tbl->direction;
871 		fid_parms.resource_func	= ident->resource_func;
872 		fid_parms.resource_type	= ident->ident_type;
873 		fid_parms.resource_hndl	= iparms.id;
874 		fid_parms.critical_resource = tbl->critical_resource;
875 		ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
876 
877 		rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
878 		if (rc) {
879 			BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
880 				    rc);
881 			/* Need to free the identifier, so goto error */
882 			goto error;
883 		}
884 	} else {
885 		*val = iparms.id;
886 	}
887 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
888 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
889 	ulp_mapper_ident_field_dump("Ident", ident, tbl, iparms.id);
890 #endif
891 #endif
892 	return 0;
893 
894 error:
895 	/* Need to free the identifier */
896 	free_parms.dir		= tbl->direction;
897 	free_parms.ident_type	= ident->ident_type;
898 	free_parms.id		= iparms.id;
899 
900 	(void)tf_free_identifier(tfp, &free_parms);
901 
902 	BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
903 		    ident->description,
904 		    tf_dir_2_str(tbl->direction));
905 	return rc;
906 }
907 
908 /*
909  * Process the identifier instruction and extract it from result blob.
910  * Increment the identifier reference count and store it in the flow database.
911  */
912 static int32_t
913 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
914 			 struct bnxt_ulp_mapper_tbl_info *tbl,
915 			 struct bnxt_ulp_mapper_ident_info *ident,
916 			 struct ulp_blob *res_blob)
917 {
918 	struct ulp_flow_db_res_params	fid_parms;
919 	uint64_t id = 0;
920 	uint32_t idx = 0;
921 	struct tf_search_identifier_parms sparms = { 0 };
922 	struct tf_free_identifier_parms free_parms = { 0 };
923 	struct tf *tfp;
924 	int rc;
925 
926 	/* Get the tfp from ulp context */
927 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
928 	if (!tfp) {
929 		BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
930 		return -EINVAL;
931 	}
932 
933 	/* Extract the index from the result blob */
934 	rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
935 			   ident->ident_bit_pos, ident->ident_bit_size);
936 	if (rc) {
937 		BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
938 		return -EIO;
939 	}
940 
941 	/* populate the search params and search identifier shadow table */
942 	sparms.ident_type = ident->ident_type;
943 	sparms.dir = tbl->direction;
944 	/* convert the idx into cpu format */
945 	sparms.search_id = tfp_be_to_cpu_32(idx);
946 
947 	/* Search identifier also increase the reference count */
948 	rc = tf_search_identifier(tfp, &sparms);
949 	if (rc) {
950 		BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
951 			    tf_dir_2_str(sparms.dir),
952 			    tf_ident_2_str(sparms.ident_type),
953 			    sparms.search_id);
954 		return rc;
955 	}
956 	BNXT_TF_INF("Search ident %s:%s:%x.success.\n",
957 		    tf_dir_2_str(sparms.dir),
958 		    tf_tbl_type_2_str(sparms.ident_type),
959 		    sparms.search_id);
960 
961 	/* Write it to the regfile */
962 	id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
963 	if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
964 		BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
965 		rc = -EINVAL;
966 		/* Need to free the identifier, so goto error */
967 		goto error;
968 	}
969 
970 	/* Link the resource to the flow in the flow db */
971 	memset(&fid_parms, 0, sizeof(fid_parms));
972 	fid_parms.direction = tbl->direction;
973 	fid_parms.resource_func = ident->resource_func;
974 	fid_parms.resource_type = ident->ident_type;
975 	fid_parms.resource_hndl = sparms.search_id;
976 	fid_parms.critical_resource = tbl->critical_resource;
977 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
978 
979 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
980 	if (rc) {
981 		BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
982 			    rc);
983 		/* Need to free the identifier, so goto error */
984 		goto error;
985 	}
986 
987 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
988 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
989 	ulp_mapper_ident_field_dump("Ident", ident, tbl, sparms.search_id);
990 #endif
991 #endif
992 	return 0;
993 
994 error:
995 	/* Need to free the identifier */
996 	free_parms.dir = tbl->direction;
997 	free_parms.ident_type = ident->ident_type;
998 	free_parms.id = sparms.search_id;
999 	(void)tf_free_identifier(tfp, &free_parms);
1000 	BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
1001 		    ident->description,
1002 		    tf_dir_2_str(tbl->direction), sparms.search_id);
1003 	return rc;
1004 }
1005 
1006 static int32_t
1007 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
1008 				 uint32_t port_id,
1009 				 uint16_t val16,
1010 				 uint8_t **val)
1011 {
1012 	enum bnxt_ulp_port_table port_data = val16;
1013 
1014 	switch (port_data) {
1015 	case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
1016 		if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
1017 						    val)) {
1018 			BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1019 			return -EINVAL;
1020 		}
1021 		break;
1022 	case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC:
1023 		if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id,
1024 						 val)) {
1025 			BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1026 			return -EINVAL;
1027 		}
1028 		break;
1029 	case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC:
1030 		if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id,
1031 						val)) {
1032 			BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1033 			return -EINVAL;
1034 		}
1035 		break;
1036 	default:
1037 		BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data);
1038 		return -EINVAL;
1039 	}
1040 	return 0;
1041 }
1042 
1043 static int32_t
1044 ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms,
1045 			     enum bnxt_ulp_field_src field_src,
1046 			     uint8_t *field_opr,
1047 			     enum tf_dir dir,
1048 			     uint8_t is_key,
1049 			     uint32_t bitlen,
1050 			     uint8_t **val,
1051 			     uint32_t *val_len,
1052 			     uint64_t *value)
1053 {
1054 	struct bnxt_ulp_mapper_data *m;
1055 	uint8_t bit;
1056 	uint32_t port_id, val_size, field_size;
1057 	uint16_t idx, size_idx, offset;
1058 	uint32_t bytelen = ULP_BITS_2_BYTE(bitlen);
1059 	uint8_t *buffer;
1060 	uint64_t lregval;
1061 	bool shared;
1062 
1063 	*val_len = bitlen;
1064 	*value = 0;
1065 	/* Perform the action */
1066 	switch (field_src) {
1067 	case BNXT_ULP_FIELD_SRC_ZERO:
1068 		*val = mapper_fld_zeros;
1069 		break;
1070 	case BNXT_ULP_FIELD_SRC_CONST:
1071 		*val = field_opr;
1072 		break;
1073 	case BNXT_ULP_FIELD_SRC_ONES:
1074 		*val = mapper_fld_ones;
1075 		*value = 1;
1076 		break;
1077 	case BNXT_ULP_FIELD_SRC_CF:
1078 		if (!ulp_operand_read(field_opr,
1079 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1080 			BNXT_TF_DBG(ERR, "CF operand read failed\n");
1081 			return -EINVAL;
1082 		}
1083 		idx = tfp_be_to_cpu_16(idx);
1084 		if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) {
1085 			BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx,
1086 				    bytelen);
1087 			return -EINVAL;
1088 		}
1089 		buffer = (uint8_t *)&parms->comp_fld[idx];
1090 		*val = &buffer[sizeof(uint64_t) - bytelen];
1091 		*value = ULP_COMP_FLD_IDX_RD(parms, idx);
1092 		break;
1093 	case BNXT_ULP_FIELD_SRC_RF:
1094 		if (!ulp_operand_read(field_opr,
1095 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1096 			BNXT_TF_DBG(ERR, "RF operand read failed\n");
1097 			return -EINVAL;
1098 		}
1099 
1100 		idx = tfp_be_to_cpu_16(idx);
1101 		/* Uninitialized regfile entries return 0 */
1102 		if (!ulp_regfile_read(parms->regfile, idx, &lregval) ||
1103 		    sizeof(uint64_t) < bytelen) {
1104 			BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx,
1105 				    bytelen);
1106 			return -EINVAL;
1107 		}
1108 		buffer = (uint8_t *)&parms->regfile->entry[idx].data;
1109 		*val = &buffer[sizeof(uint64_t) - bytelen];
1110 		*value = tfp_be_to_cpu_64(lregval);
1111 		break;
1112 	case BNXT_ULP_FIELD_SRC_ACT_PROP:
1113 		if (!ulp_operand_read(field_opr,
1114 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1115 			BNXT_TF_DBG(ERR, "Action operand read failed\n");
1116 			return -EINVAL;
1117 		}
1118 		idx = tfp_be_to_cpu_16(idx);
1119 		if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1120 			BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
1121 			return -EINVAL;
1122 		}
1123 		buffer = &parms->act_prop->act_details[idx];
1124 		field_size = ulp_mapper_act_prop_size_get(idx);
1125 		if (bytelen > field_size) {
1126 			BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n",
1127 				    idx, field_size);
1128 			return -EINVAL;
1129 		}
1130 		*val = &buffer[field_size - bytelen];
1131 		break;
1132 	case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1133 		if (!ulp_operand_read(field_opr,
1134 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1135 			BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1136 			return -EINVAL;
1137 		}
1138 		idx = tfp_be_to_cpu_16(idx);
1139 
1140 		if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1141 			BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx);
1142 			return -EINVAL;
1143 		}
1144 		*val = &parms->act_prop->act_details[idx];
1145 
1146 		/* get the size index next */
1147 		if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1148 				      (uint8_t *)&size_idx, sizeof(uint16_t))) {
1149 			BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1150 			return -EINVAL;
1151 		}
1152 		size_idx = tfp_be_to_cpu_16(size_idx);
1153 		if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1154 			BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1155 			return -EINVAL;
1156 		}
1157 		memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1158 		       sizeof(uint32_t));
1159 		val_size = tfp_be_to_cpu_32(val_size);
1160 		*val_len = ULP_BYTE_2_BITS(val_size);
1161 		break;
1162 	case BNXT_ULP_FIELD_SRC_GLB_RF:
1163 		if (!ulp_operand_read(field_opr,
1164 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1165 			BNXT_TF_DBG(ERR, "Global regfile read failed\n");
1166 			return -EINVAL;
1167 		}
1168 		idx = tfp_be_to_cpu_16(idx);
1169 		if (ulp_mapper_glb_resource_read(parms->mapper_data,
1170 						 dir, idx, &lregval, &shared) ||
1171 		    sizeof(uint64_t) < bytelen) {
1172 			BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n",
1173 				    idx, bytelen);
1174 			return -EINVAL;
1175 		}
1176 		m = parms->mapper_data;
1177 		buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl;
1178 		*val = &buffer[sizeof(uint64_t) - bytelen];
1179 		*value = tfp_be_to_cpu_64(lregval);
1180 		break;
1181 	case BNXT_ULP_FIELD_SRC_HF:
1182 	case BNXT_ULP_FIELD_SRC_SUB_HF:
1183 		if (!ulp_operand_read(field_opr,
1184 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1185 			BNXT_TF_DBG(ERR, "Header field read failed\n");
1186 			return -EINVAL;
1187 		}
1188 		idx = tfp_be_to_cpu_16(idx);
1189 		/* get the index from the global field list */
1190 		if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1191 			BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1192 				    idx);
1193 			return -EINVAL;
1194 		}
1195 		if (is_key)
1196 			buffer = parms->hdr_field[bit].spec;
1197 		else
1198 			buffer = parms->hdr_field[bit].mask;
1199 
1200 		field_size = parms->hdr_field[bit].size;
1201 		if (bytelen > field_size) {
1202 			BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n",
1203 				    bit, field_size);
1204 			return -EINVAL;
1205 		}
1206 		if (field_src == BNXT_ULP_FIELD_SRC_HF) {
1207 			*val = &buffer[field_size - bytelen];
1208 		} else {
1209 			/* get the offset next */
1210 			if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1211 					      (uint8_t *)&offset,
1212 					      sizeof(uint16_t))) {
1213 				BNXT_TF_DBG(ERR, "Hdr fld size read failed\n");
1214 				return -EINVAL;
1215 			}
1216 			offset = tfp_be_to_cpu_16(offset);
1217 			offset = ULP_BITS_2_BYTE_NR(offset);
1218 			if ((offset + bytelen) > field_size) {
1219 				BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit);
1220 				return -EINVAL;
1221 			}
1222 			*val = &buffer[offset];
1223 		}
1224 		break;
1225 	case BNXT_ULP_FIELD_SRC_HDR_BIT:
1226 		if (!ulp_operand_read(field_opr,
1227 				      (uint8_t *)&lregval, sizeof(uint64_t))) {
1228 			BNXT_TF_DBG(ERR, "Header bit read failed\n");
1229 			return -EINVAL;
1230 		}
1231 		lregval = tfp_be_to_cpu_64(lregval);
1232 		if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) {
1233 			*val = mapper_fld_one;
1234 			*value = 1;
1235 		} else {
1236 			*val = mapper_fld_zeros;
1237 		}
1238 		break;
1239 	case BNXT_ULP_FIELD_SRC_ACT_BIT:
1240 		if (!ulp_operand_read(field_opr,
1241 				      (uint8_t *)&lregval, sizeof(uint64_t))) {
1242 			BNXT_TF_DBG(ERR, "Action bit read failed\n");
1243 			return -EINVAL;
1244 		}
1245 		lregval = tfp_be_to_cpu_64(lregval);
1246 		if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) {
1247 			*val = mapper_fld_one;
1248 			*value = 1;
1249 		} else {
1250 			*val = mapper_fld_zeros;
1251 		}
1252 		break;
1253 	case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1254 		if (!ulp_operand_read(field_opr,
1255 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1256 			BNXT_TF_DBG(ERR, "Field bit read failed\n");
1257 			return -EINVAL;
1258 		}
1259 		idx = tfp_be_to_cpu_16(idx);
1260 		/* get the index from the global field list */
1261 		if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1262 			BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1263 				    idx);
1264 			return -EINVAL;
1265 		}
1266 		if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) {
1267 			*val = mapper_fld_one;
1268 			*value = 1;
1269 		} else {
1270 			*val = mapper_fld_zeros;
1271 		}
1272 		break;
1273 	case BNXT_ULP_FIELD_SRC_PORT_TABLE:
1274 		/* The port id is present in the comp field list */
1275 		port_id = ULP_COMP_FLD_IDX_RD(parms,
1276 					      BNXT_ULP_CF_IDX_DEV_PORT_ID);
1277 		/* get the port table enum  */
1278 		if (!ulp_operand_read(field_opr,
1279 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1280 			BNXT_TF_DBG(ERR, "Port table enum read failed\n");
1281 			return -EINVAL;
1282 		}
1283 		idx = tfp_be_to_cpu_16(idx);
1284 		if (ulp_mapper_field_port_db_process(parms, port_id, idx,
1285 						     val)) {
1286 			BNXT_TF_DBG(ERR, "field port table failed\n");
1287 			return -EINVAL;
1288 		}
1289 		break;
1290 	case BNXT_ULP_FIELD_SRC_ENC_HDR_BIT:
1291 		if (!ulp_operand_read(field_opr,
1292 				      (uint8_t *)&lregval, sizeof(uint64_t))) {
1293 			BNXT_TF_DBG(ERR, "Header bit read failed\n");
1294 			return -EINVAL;
1295 		}
1296 		lregval = tfp_be_to_cpu_64(lregval);
1297 		if (ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, lregval)) {
1298 			*val = mapper_fld_one;
1299 			*value = 1;
1300 		} else {
1301 			*val = mapper_fld_zeros;
1302 		}
1303 		break;
1304 	case BNXT_ULP_FIELD_SRC_ENC_FIELD:
1305 		if (!ulp_operand_read(field_opr,
1306 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1307 			BNXT_TF_DBG(ERR, "Header field read failed\n");
1308 			return -EINVAL;
1309 		}
1310 		idx = tfp_be_to_cpu_16(idx);
1311 		/* get the index from the global field list */
1312 		if (idx >= BNXT_ULP_ENC_FIELD_LAST) {
1313 			BNXT_TF_DBG(ERR, "invalid encap field tbl idx %d\n",
1314 				    idx);
1315 			return -EINVAL;
1316 		}
1317 		buffer = parms->enc_field[idx].spec;
1318 		field_size = parms->enc_field[idx].size;
1319 		if (bytelen > field_size) {
1320 			BNXT_TF_DBG(ERR, "Encap field[%d] size small %u\n",
1321 				    idx, field_size);
1322 			return -EINVAL;
1323 		}
1324 		*val = &buffer[field_size - bytelen];
1325 		break;
1326 	case BNXT_ULP_FIELD_SRC_SKIP:
1327 		/* do nothing */
1328 		*val = mapper_fld_zeros;
1329 		*val_len = 0;
1330 		break;
1331 	case BNXT_ULP_FIELD_SRC_REJECT:
1332 		return -EINVAL;
1333 	default:
1334 		BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src);
1335 		return -EINVAL;
1336 	}
1337 	return 0;
1338 }
1339 
1340 static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen,
1341 					    uint64_t *output)
1342 {
1343 	uint16_t val_16;
1344 	uint32_t val_32;
1345 	uint64_t val_64;
1346 	uint32_t bytelen;
1347 
1348 	bytelen = ULP_BITS_2_BYTE(bitlen);
1349 	if (bytelen == sizeof(uint8_t)) {
1350 		*output = *((uint8_t *)buffer);
1351 	} else if (bytelen == sizeof(uint16_t)) {
1352 		val_16 = *((uint16_t *)buffer);
1353 		*output =  tfp_be_to_cpu_16(val_16);
1354 	} else if (bytelen == sizeof(uint32_t)) {
1355 		val_32 = *((uint32_t *)buffer);
1356 		*output =  tfp_be_to_cpu_32(val_32);
1357 	} else if (bytelen == sizeof(val_64)) {
1358 		val_64 = *((uint64_t *)buffer);
1359 		*output =  tfp_be_to_cpu_64(val_64);
1360 	} else {
1361 		*output = 0;
1362 		return -EINVAL;
1363 	}
1364 	return 0;
1365 }
1366 
1367 static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src,
1368 					   struct ulp_blob *blob,
1369 					   uint8_t *val,
1370 					   uint32_t val_len,
1371 					   uint8_t **out_val)
1372 {
1373 	if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) {
1374 		if (ulp_blob_pad_push(blob, val_len) < 0) {
1375 			BNXT_TF_DBG(ERR, "too large for blob\n");
1376 			return -EINVAL;
1377 		}
1378 	} else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) {
1379 		if (ulp_blob_push_encap(blob, val, val_len) < 0) {
1380 			BNXT_TF_DBG(ERR, "encap blob push failed\n");
1381 			return -EINVAL;
1382 		}
1383 	} else if (fld_src == BNXT_ULP_FIELD_SRC_SKIP) {
1384 		/* do nothing */
1385 	} else {
1386 		if (!ulp_blob_push(blob, val, val_len)) {
1387 			BNXT_TF_DBG(ERR, "push of val1 failed\n");
1388 			return -EINVAL;
1389 		}
1390 	}
1391 	*out_val = val;
1392 	return 0;
1393 }
1394 
1395 static int32_t
1396 ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms,
1397 			     enum tf_dir dir,
1398 			     struct bnxt_ulp_mapper_field_info *fld,
1399 			     struct ulp_blob *blob,
1400 			     uint8_t is_key,
1401 			     const char *name)
1402 {
1403 	uint16_t write_idx = blob->write_idx;
1404 	uint8_t *val = NULL, *val1, *val2, *val3;
1405 	uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0;
1406 	uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0;
1407 	uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0;
1408 	uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0;
1409 	uint64_t value1 = 0, value2 = 0, value3 = 0;
1410 	int32_t rc = 0;
1411 
1412 	/* prepare the field source and values */
1413 	switch (fld->field_opc) {
1414 	case BNXT_ULP_FIELD_OPC_SRC1:
1415 		process_src1 = 1;
1416 		break;
1417 	case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1418 		process_src1 = 1;
1419 		break;
1420 	case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1421 	case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1422 		process_src3 = 1;
1423 		eval_src3 = 1;
1424 		process_src1 = 1;
1425 		process_src2 = 1;
1426 		eval_src1 = 1;
1427 		eval_src2 = 1;
1428 		break;
1429 	case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1430 	case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1431 	case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1432 	case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1433 	case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1434 	case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1435 		process_src1 = 1;
1436 		process_src2 = 1;
1437 		eval_src1 = 1;
1438 		eval_src2 = 1;
1439 		break;
1440 	default:
1441 		break;
1442 	}
1443 
1444 	/* process the src1 opcode  */
1445 	if (process_src1) {
1446 		if (ulp_mapper_field_src_process(parms, fld->field_src1,
1447 						 fld->field_opr1, dir, is_key,
1448 						 fld->field_bit_size, &val1,
1449 						 &val1_len, &value1)) {
1450 			BNXT_TF_DBG(ERR, "fld src1 process failed\n");
1451 			goto error;
1452 		}
1453 		if (eval_src1) {
1454 			if (ulp_mapper_field_buffer_eval(val1, val1_len,
1455 							 &val1_int)) {
1456 				BNXT_TF_DBG(ERR, "fld src1 eval failed\n");
1457 				goto error;
1458 			}
1459 		}
1460 	}
1461 
1462 	/* for "if then clause" set the correct process  */
1463 	if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) {
1464 		if (value1)
1465 			process_src2 = 1;
1466 		else
1467 			process_src3 = 1;
1468 	}
1469 
1470 	/* process src2 opcode */
1471 	if (process_src2) {
1472 		if (ulp_mapper_field_src_process(parms, fld->field_src2,
1473 						 fld->field_opr2, dir, is_key,
1474 						 fld->field_bit_size, &val2,
1475 						 &val2_len, &value2)) {
1476 			BNXT_TF_DBG(ERR, "fld src2 process failed\n");
1477 			goto error;
1478 		}
1479 		if (eval_src2) {
1480 			if (ulp_mapper_field_buffer_eval(val2, val2_len,
1481 							 &val2_int)) {
1482 				BNXT_TF_DBG(ERR, "fld src2 eval failed\n");
1483 				goto error;
1484 			}
1485 		}
1486 	}
1487 
1488 	/* process src3 opcode */
1489 	if (process_src3) {
1490 		if (ulp_mapper_field_src_process(parms, fld->field_src3,
1491 						 fld->field_opr3, dir, is_key,
1492 						 fld->field_bit_size, &val3,
1493 						 &val3_len, &value3)) {
1494 			BNXT_TF_DBG(ERR, "fld src3 process failed\n");
1495 			goto error;
1496 		}
1497 		if (eval_src3) {
1498 			if (ulp_mapper_field_buffer_eval(val3, val3_len,
1499 							 &val3_int)) {
1500 				BNXT_TF_DBG(ERR, "fld src3 eval failed\n");
1501 				goto error;
1502 			}
1503 		}
1504 	}
1505 
1506 	val_len = fld->field_bit_size;
1507 	/* process the field opcodes */
1508 	switch (fld->field_opc) {
1509 	case BNXT_ULP_FIELD_OPC_SRC1:
1510 		rc = ulp_mapper_field_blob_write(fld->field_src1,
1511 						 blob, val1, val1_len, &val);
1512 		val_len = val1_len;
1513 		break;
1514 	case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1515 		if (value1) {
1516 			rc = ulp_mapper_field_blob_write(fld->field_src2, blob,
1517 							 val2, val2_len, &val);
1518 			val_len = val2_len;
1519 		} else {
1520 			rc = ulp_mapper_field_blob_write(fld->field_src3, blob,
1521 							 val3, val3_len, &val);
1522 			val_len = val3_len;
1523 		}
1524 		break;
1525 	case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1526 	case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1527 		val_int = val1_int + val2_int;
1528 		val_int = tfp_cpu_to_be_64(val_int);
1529 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1530 		if (!val)
1531 			rc = -EINVAL;
1532 		break;
1533 	case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1534 	case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1535 		val_int = val1_int - val2_int;
1536 		val_int = tfp_cpu_to_be_64(val_int);
1537 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1538 		if (!val)
1539 			rc = -EINVAL;
1540 		break;
1541 	case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1542 		val_int = val1_int | val2_int;
1543 		val_int = tfp_cpu_to_be_64(val_int);
1544 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1545 		if (!val)
1546 			rc = -EINVAL;
1547 		break;
1548 	case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1549 		val_int = val1_int | val2_int | val3_int;
1550 		val_int = tfp_cpu_to_be_64(val_int);
1551 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1552 		if (!val)
1553 			rc = -EINVAL;
1554 		break;
1555 	case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1556 		val_int = val1_int & val2_int;
1557 		val_int = tfp_cpu_to_be_64(val_int);
1558 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1559 		if (!val)
1560 			rc = -EINVAL;
1561 		break;
1562 	case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1563 		val_int = val1_int & (val2_int | val3_int);
1564 		val_int = tfp_cpu_to_be_64(val_int);
1565 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1566 		if (!val)
1567 			rc = -EINVAL;
1568 		break;
1569 	case BNXT_ULP_FIELD_OPC_SKIP:
1570 		break;
1571 	default:
1572 		BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc);
1573 		rc = -EINVAL;
1574 		break;
1575 	}
1576 
1577 	if (!rc) {
1578 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1579 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1580 		if (fld->field_src1 != BNXT_ULP_FIELD_SRC_ZERO && val_len)
1581 			ulp_mapper_field_dump(name, fld, blob, write_idx, val,
1582 					      val_len);
1583 #endif
1584 #endif
1585 		return rc;
1586 	}
1587 error:
1588 	BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name,
1589 		    fld->description, (val) ? write_idx : 0, val_len);
1590 	return -EINVAL;
1591 }
1592 
1593 /*
1594  * Result table process and fill the result blob.
1595  * data [out] - the result blob data
1596  */
1597 static int32_t
1598 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1599 			    struct bnxt_ulp_mapper_tbl_info *tbl,
1600 			    struct ulp_blob *data,
1601 			    const char *name)
1602 {
1603 	struct bnxt_ulp_mapper_field_info *dflds;
1604 	uint32_t i = 0, num_flds = 0, encap_flds = 0;
1605 	struct ulp_blob encap_blob;
1606 	int32_t rc = 0;
1607 
1608 	/* Get the result field list */
1609 	dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1610 					     &encap_flds);
1611 
1612 	/* validate the result field list counts */
1613 	if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1614 	     (!num_flds && !encap_flds)) || !dflds ||
1615 	    (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1616 		(!num_flds || encap_flds))) {
1617 		BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1618 			    num_flds, encap_flds);
1619 		return -EINVAL;
1620 	}
1621 
1622 	/* process the result fields */
1623 	for (i = 0; i < num_flds; i++) {
1624 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1625 						  &dflds[i], data, 0, name);
1626 		if (rc) {
1627 			BNXT_TF_DBG(ERR, "result field processing failed\n");
1628 			return rc;
1629 		}
1630 	}
1631 
1632 	/* process encap fields if any */
1633 	if (encap_flds) {
1634 		uint32_t pad = 0;
1635 		/* Initialize the encap blob */
1636 		if (!tbl->record_size &&
1637 		    !parms->device_params->dynamic_sram_en) {
1638 			BNXT_TF_DBG(ERR, "Encap tbl record size incorrect\n");
1639 			return -EINVAL;
1640 		}
1641 		if (!ulp_blob_init(&encap_blob,
1642 				   ULP_BYTE_2_BITS(tbl->record_size),
1643 				   parms->device_params->encap_byte_order)) {
1644 			BNXT_TF_DBG(ERR, "blob inits failed.\n");
1645 			return -EINVAL;
1646 		}
1647 		for (; i < encap_flds; i++) {
1648 			rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1649 							  &dflds[i],
1650 							  &encap_blob, 0, name);
1651 			if (rc) {
1652 				BNXT_TF_DBG(ERR,
1653 					    "encap field processing failed\n");
1654 				return rc;
1655 			}
1656 		}
1657 		/* add the dynamic pad push */
1658 		if (parms->device_params->dynamic_sram_en) {
1659 			uint16_t rec_s = ULP_BYTE_2_BITS(tbl->record_size);
1660 
1661 			(void)ulp_mapper_dyn_tbl_type_get(parms, tbl,
1662 							  &encap_blob, &rec_s);
1663 			pad = rec_s - ulp_blob_data_len_get(&encap_blob);
1664 		} else {
1665 			pad = ULP_BYTE_2_BITS(tbl->record_size) -
1666 				ulp_blob_data_len_get(&encap_blob);
1667 		}
1668 		if (ulp_blob_pad_push(&encap_blob, pad) < 0) {
1669 			BNXT_TF_DBG(ERR, "encap buffer padding failed\n");
1670 			return -EINVAL;
1671 		}
1672 
1673 
1674 		/* perform the 64 bit byte swap */
1675 		ulp_blob_perform_64B_byte_swap(&encap_blob);
1676 		/* Append encap blob to the result blob */
1677 		rc = ulp_blob_buffer_copy(data, &encap_blob);
1678 		if (rc) {
1679 			BNXT_TF_DBG(ERR, "encap buffer copy failed\n");
1680 			return rc;
1681 		}
1682 	}
1683 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1684 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1685 	BNXT_TF_DBG(DEBUG, "Result dump\n");
1686 	ulp_mapper_blob_dump(data);
1687 #endif
1688 #endif
1689 	return rc;
1690 }
1691 
1692 static int32_t
1693 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1694 			     struct bnxt_ulp_mapper_tbl_info *tbl,
1695 			     uint64_t flow_id)
1696 {
1697 	struct ulp_flow_db_res_params fid_parms;
1698 	uint32_t mark, gfid, mark_flag;
1699 	enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1700 	int32_t rc = 0;
1701 
1702 	if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1703 	    !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1704 	     ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1705 			      BNXT_ULP_ACT_BIT_MARK)))
1706 		return rc; /* no need to perform gfid process */
1707 
1708 	/* Get the mark id details from action property */
1709 	memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1710 	       sizeof(mark));
1711 	mark = tfp_be_to_cpu_32(mark);
1712 
1713 	TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1714 	mark_flag  = BNXT_ULP_MARK_GLOBAL_HW_FID;
1715 
1716 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1717 				  gfid, mark);
1718 	if (rc) {
1719 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1720 		return rc;
1721 	}
1722 	fid_parms.direction = tbl->direction;
1723 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1724 	fid_parms.critical_resource = tbl->critical_resource;
1725 	fid_parms.resource_type	= mark_flag;
1726 	fid_parms.resource_hndl	= gfid;
1727 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1728 
1729 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1730 	if (rc)
1731 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1732 	return rc;
1733 }
1734 
1735 static int32_t
1736 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1737 				struct bnxt_ulp_mapper_tbl_info *tbl)
1738 {
1739 	struct ulp_flow_db_res_params fid_parms;
1740 	uint32_t act_idx, mark, mark_flag;
1741 	uint64_t val64;
1742 	enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1743 	int32_t rc = 0;
1744 
1745 	if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1746 	    !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1747 	     ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1748 			      BNXT_ULP_ACT_BIT_MARK)))
1749 		return rc; /* no need to perform mark action process */
1750 
1751 	/* Get the mark id details from action property */
1752 	memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1753 	       sizeof(mark));
1754 	mark = tfp_be_to_cpu_32(mark);
1755 
1756 	if (!ulp_regfile_read(parms->regfile,
1757 			      BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1758 			      &val64)) {
1759 		BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1760 		return -EINVAL;
1761 	}
1762 	act_idx = tfp_be_to_cpu_64(val64);
1763 	mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID;
1764 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1765 				  act_idx, mark);
1766 	if (rc) {
1767 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1768 		return rc;
1769 	}
1770 	fid_parms.direction = tbl->direction;
1771 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1772 	fid_parms.critical_resource = tbl->critical_resource;
1773 	fid_parms.resource_type	= mark_flag;
1774 	fid_parms.resource_hndl	= act_idx;
1775 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1776 
1777 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1778 	if (rc)
1779 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1780 	return rc;
1781 }
1782 
1783 static int32_t
1784 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1785 				struct bnxt_ulp_mapper_tbl_info *tbl)
1786 {
1787 	struct ulp_flow_db_res_params fid_parms;
1788 	uint32_t act_idx, mark, mark_flag;
1789 	uint64_t val64;
1790 	enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1791 	int32_t rc = 0;
1792 
1793 	if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1794 	    mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1795 		return rc; /* no need to perform mark action process */
1796 
1797 	/* Get the mark id details from the computed field of dev port id */
1798 	mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1799 
1800 	 /* Get the main action pointer */
1801 	if (!ulp_regfile_read(parms->regfile,
1802 			      BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1803 			      &val64)) {
1804 		BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1805 		return -EINVAL;
1806 	}
1807 	act_idx = tfp_be_to_cpu_64(val64);
1808 
1809 	/* Set the mark flag to local fid and vfr flag */
1810 	mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1811 
1812 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1813 				  act_idx, mark);
1814 	if (rc) {
1815 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1816 		return rc;
1817 	}
1818 	fid_parms.direction = tbl->direction;
1819 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1820 	fid_parms.critical_resource = tbl->critical_resource;
1821 	fid_parms.resource_type	= mark_flag;
1822 	fid_parms.resource_hndl	= act_idx;
1823 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1824 
1825 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1826 	if (rc)
1827 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1828 	return rc;
1829 }
1830 
1831 /* Tcam table scan the identifier list and allocate each identifier */
1832 static int32_t
1833 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1834 				     struct bnxt_ulp_mapper_tbl_info *tbl)
1835 {
1836 	struct bnxt_ulp_mapper_ident_info *idents;
1837 	uint32_t num_idents;
1838 	uint32_t i;
1839 
1840 	idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1841 	for (i = 0; i < num_idents; i++) {
1842 		if (ulp_mapper_ident_process(parms, tbl,
1843 					     &idents[i], NULL))
1844 			return -EINVAL;
1845 	}
1846 	return 0;
1847 }
1848 
1849 /*
1850  * Tcam table scan the identifier list and extract the identifier from
1851  * the result blob.
1852  */
1853 static int32_t
1854 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1855 				       struct bnxt_ulp_mapper_tbl_info *tbl,
1856 				       struct ulp_blob *data)
1857 {
1858 	struct bnxt_ulp_mapper_ident_info *idents;
1859 	uint32_t num_idents = 0, i;
1860 	int32_t rc = 0;
1861 
1862 	/*
1863 	 * Extract the listed identifiers from the result field,
1864 	 * no need to allocate them.
1865 	 */
1866 	idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1867 	for (i = 0; i < num_idents; i++) {
1868 		rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1869 		if (rc) {
1870 			BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1871 			return rc;
1872 		}
1873 	}
1874 	return rc;
1875 }
1876 
1877 /* Internal function to write the tcam entry */
1878 static int32_t
1879 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1880 				struct bnxt_ulp_mapper_tbl_info *tbl,
1881 				struct ulp_blob *key,
1882 				struct ulp_blob *mask,
1883 				struct ulp_blob *data,
1884 				uint16_t idx)
1885 {
1886 	struct tf_set_tcam_entry_parms sparms = { 0 };
1887 	struct tf *tfp;
1888 	uint16_t tmplen;
1889 	int32_t rc;
1890 
1891 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
1892 	if (!tfp) {
1893 		BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1894 		return -EINVAL;
1895 	}
1896 
1897 	sparms.dir		= tbl->direction;
1898 	sparms.tcam_tbl_type	= tbl->resource_type;
1899 	sparms.idx		= idx;
1900 	sparms.key		= ulp_blob_data_get(key, &tmplen);
1901 	sparms.key_sz_in_bits	= tmplen;
1902 	sparms.mask		= ulp_blob_data_get(mask, &tmplen);
1903 	sparms.result		= ulp_blob_data_get(data, &tmplen);
1904 	sparms.result_sz_in_bits = tmplen;
1905 	if (tf_set_tcam_entry(tfp, &sparms)) {
1906 		BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1907 			    tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1908 			    tf_dir_2_str(sparms.dir), sparms.idx);
1909 		return -EIO;
1910 	}
1911 	BNXT_TF_INF("tcam[%s][%s][%x] write success.\n",
1912 		    tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1913 		    tf_dir_2_str(sparms.dir), sparms.idx);
1914 
1915 	/* Mark action */
1916 	rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1917 	if (rc) {
1918 		BNXT_TF_DBG(ERR, "failed mark action processing\n");
1919 		return rc;
1920 	}
1921 
1922 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1923 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1924 	ulp_mapper_tcam_entry_dump("TCAM", idx, tbl, key, mask, data);
1925 #endif
1926 #endif
1927 	return rc;
1928 }
1929 
1930 /*
1931  * internal function to post process key/mask blobs for dynamic pad WC tcam tbl
1932  *
1933  * parms [in] The mappers parms with data related to the flow.
1934  *
1935  * key [in] The original key to be transformed
1936  *
1937  * mask [in] The original mask to be transformed
1938  *
1939  * tkey [in/out] The transformed key
1940  *
1941  * tmask [in/out] The transformed mask
1942  *
1943  * returns zero on success, non-zero on failure
1944  */
1945 static uint32_t
1946 ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms,
1947 					struct ulp_blob *key,
1948 					struct ulp_blob *mask,
1949 					struct ulp_blob *tkey,
1950 					struct ulp_blob *tmask)
1951 {
1952 	uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset;
1953 	uint32_t cword, i, rc;
1954 	int32_t pad;
1955 	uint8_t *val;
1956 
1957 	slice_width = dparms->wc_slice_width;
1958 	clen = dparms->wc_ctl_size_bits;
1959 	max_slices = dparms->wc_max_slices;
1960 	blen = ulp_blob_data_len_get(key);
1961 
1962 	/* Get the length of the key based on number of slices and width */
1963 	num_slices = 1;
1964 	tlen = slice_width;
1965 	while (tlen < blen &&
1966 	       num_slices <= max_slices) {
1967 		num_slices = num_slices << 1;
1968 		tlen = tlen << 1;
1969 	}
1970 
1971 	if (num_slices > max_slices) {
1972 		BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen);
1973 		return -EINVAL;
1974 	}
1975 
1976 	/* The key/mask may not be on a natural slice boundary, pad it */
1977 	pad = tlen - blen;
1978 	if (ulp_blob_pad_push(key, pad) < 0 ||
1979 	    ulp_blob_pad_push(mask, pad) < 0) {
1980 		BNXT_TF_DBG(ERR, "Unable to pad key/mask\n");
1981 		return -EINVAL;
1982 	}
1983 
1984 	/* The new length accounts for the ctrl word length and num slices */
1985 	tlen = tlen + clen * num_slices;
1986 	if (!ulp_blob_init(tkey, tlen, key->byte_order) ||
1987 	    !ulp_blob_init(tmask, tlen, mask->byte_order)) {
1988 		BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n");
1989 		return -EINVAL;
1990 	}
1991 
1992 	/* Build the transformed key/mask */
1993 	cword = dparms->wc_mode_list[num_slices - 1];
1994 	cword = tfp_cpu_to_be_32(cword);
1995 	offset = 0;
1996 	for (i = 0; i < num_slices; i++) {
1997 		val = ulp_blob_push_32(tkey, &cword, clen);
1998 		if (!val) {
1999 			BNXT_TF_DBG(ERR, "Key ctrl word push failed\n");
2000 			return -EINVAL;
2001 		}
2002 		val = ulp_blob_push_32(tmask, &cword, clen);
2003 		if (!val) {
2004 			BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n");
2005 			return -EINVAL;
2006 		}
2007 		rc = ulp_blob_append(tkey, key, offset, slice_width);
2008 		if (rc) {
2009 			BNXT_TF_DBG(ERR, "Key blob append failed\n");
2010 			return rc;
2011 		}
2012 		rc = ulp_blob_append(tmask, mask, offset, slice_width);
2013 		if (rc) {
2014 			BNXT_TF_DBG(ERR, "Mask blob append failed\n");
2015 			return rc;
2016 		}
2017 		offset += slice_width;
2018 	}
2019 
2020 	/* The key/mask are byte reversed on every 4 byte chunk */
2021 	ulp_blob_perform_byte_reverse(tkey, 4);
2022 	ulp_blob_perform_byte_reverse(tmask, 4);
2023 
2024 	return 0;
2025 }
2026 
2027 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
2028 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
2029 {
2030 	ulp_blob_perform_64B_word_swap(blob);
2031 	ulp_blob_perform_64B_byte_swap(blob);
2032 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2033 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2034 	BNXT_TF_DBG(INFO, "Dump after wc tcam post process\n");
2035 	ulp_mapper_blob_dump(blob);
2036 #endif
2037 #endif
2038 }
2039 
2040 static int32_t ulp_mapper_tcam_is_wc_tcam(struct bnxt_ulp_mapper_tbl_info *tbl)
2041 {
2042 	if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM ||
2043 	    tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH ||
2044 	    tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW)
2045 		return 1;
2046 	return 0;
2047 }
2048 
2049 static int32_t
2050 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2051 			    struct bnxt_ulp_mapper_tbl_info *tbl)
2052 {
2053 	struct bnxt_ulp_mapper_key_info	*kflds;
2054 	struct ulp_blob okey, omask, data, update_data;
2055 	struct ulp_blob tkey, tmask; /* transform key and mask */
2056 	struct ulp_blob *key, *mask;
2057 	uint32_t i, num_kflds;
2058 	struct tf *tfp;
2059 	int32_t rc, trc;
2060 	struct bnxt_ulp_device_params *dparms = parms->device_params;
2061 	struct tf_alloc_tcam_entry_parms aparms		= { 0 };
2062 	struct tf_search_tcam_entry_parms searchparms   = { 0 };
2063 	struct ulp_flow_db_res_params	fid_parms	= { 0 };
2064 	struct tf_free_tcam_entry_parms free_parms	= { 0 };
2065 	uint32_t hit = 0;
2066 	uint16_t tmplen = 0;
2067 	uint16_t idx;
2068 	enum bnxt_ulp_byte_order key_byte_order;
2069 
2070 	/* Set the key and mask to the original key and mask. */
2071 	key = &okey;
2072 	mask = &omask;
2073 
2074 	/* Skip this if table opcode is NOP */
2075 	if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
2076 	    tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
2077 		BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
2078 			    tbl->tbl_opcode);
2079 		return 0;
2080 	}
2081 
2082 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2083 	if (!tfp) {
2084 		BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
2085 		return -EINVAL;
2086 	}
2087 
2088 	/* If only allocation of identifier then perform and exit */
2089 	if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_IDENT) {
2090 		rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
2091 		return rc;
2092 	}
2093 
2094 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2095 	if (!kflds || !num_kflds) {
2096 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2097 		return -EINVAL;
2098 	}
2099 
2100 	if (ulp_mapper_tcam_is_wc_tcam(tbl))
2101 		key_byte_order = dparms->wc_key_byte_order;
2102 	else
2103 		key_byte_order = dparms->key_byte_order;
2104 
2105 	if (!ulp_blob_init(key, tbl->blob_key_bit_size, key_byte_order) ||
2106 	    !ulp_blob_init(mask, tbl->blob_key_bit_size, key_byte_order) ||
2107 	    !ulp_blob_init(&data, tbl->result_bit_size,
2108 			   dparms->result_byte_order) ||
2109 	    !ulp_blob_init(&update_data, tbl->result_bit_size,
2110 			   dparms->result_byte_order)) {
2111 		BNXT_TF_DBG(ERR, "blob inits failed.\n");
2112 		return -EINVAL;
2113 	}
2114 
2115 	/* create the key/mask */
2116 	/*
2117 	 * NOTE: The WC table will require some kind of flag to handle the
2118 	 * mode bits within the key/mask
2119 	 */
2120 	for (i = 0; i < num_kflds; i++) {
2121 		/* Setup the key */
2122 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2123 						  &kflds[i].field_info_spec,
2124 						  key, 1, "TCAM Key");
2125 		if (rc) {
2126 			BNXT_TF_DBG(ERR, "Key field set failed %s\n",
2127 				    kflds[i].field_info_spec.description);
2128 			return rc;
2129 		}
2130 
2131 		/* Setup the mask */
2132 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2133 						  &kflds[i].field_info_mask,
2134 						  mask, 0, "TCAM Mask");
2135 		if (rc) {
2136 			BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
2137 				    kflds[i].field_info_mask.description);
2138 			return rc;
2139 		}
2140 	}
2141 
2142 	/* For wild card tcam perform the post process to swap the blob */
2143 	if (ulp_mapper_tcam_is_wc_tcam(tbl)) {
2144 		if (dparms->dynamic_pad_en) {
2145 			/* Sets up the slices for writing to the WC TCAM */
2146 			rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms,
2147 								     key, mask,
2148 								     &tkey,
2149 								     &tmask);
2150 			if (rc) {
2151 				BNXT_TF_DBG(ERR,
2152 					    "Failed to post proc WC entry.\n");
2153 				return rc;
2154 			}
2155 			/* Now need to use the transform Key/Mask */
2156 			key = &tkey;
2157 			mask = &tmask;
2158 		} else {
2159 			ulp_mapper_wc_tcam_tbl_post_process(key);
2160 			ulp_mapper_wc_tcam_tbl_post_process(mask);
2161 		}
2162 
2163 	}
2164 
2165 	if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2166 		/* allocate the tcam index */
2167 		aparms.dir = tbl->direction;
2168 		aparms.tcam_tbl_type = tbl->resource_type;
2169 		aparms.key = ulp_blob_data_get(key, &tmplen);
2170 		aparms.key_sz_in_bits = tmplen;
2171 		aparms.mask = ulp_blob_data_get(mask, &tmplen);
2172 
2173 		/* calculate the entry priority */
2174 		rc = ulp_mapper_priority_opc_process(parms, tbl,
2175 						     &aparms.priority);
2176 		if (rc) {
2177 			BNXT_TF_DBG(ERR, "entry priority process failed\n");
2178 			return rc;
2179 		}
2180 
2181 		rc = tf_alloc_tcam_entry(tfp, &aparms);
2182 		if (rc) {
2183 			BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
2184 			return rc;
2185 		}
2186 		idx = aparms.idx;
2187 		hit = aparms.hit;
2188 	} else {
2189 		/*
2190 		 * Searching before allocation to see if we already have an
2191 		 * entry.  This allows re-use of a constrained resource.
2192 		 */
2193 		searchparms.dir = tbl->direction;
2194 		searchparms.tcam_tbl_type = tbl->resource_type;
2195 		searchparms.key = ulp_blob_data_get(key, &tmplen);
2196 		searchparms.key_sz_in_bits = tbl->key_bit_size;
2197 		searchparms.mask = ulp_blob_data_get(mask, &tmplen);
2198 		searchparms.alloc = 1;
2199 		searchparms.result = ulp_blob_data_get(&data, &tmplen);
2200 		searchparms.result_sz_in_bits = tbl->result_bit_size;
2201 
2202 		/* calculate the entry priority */
2203 		rc = ulp_mapper_priority_opc_process(parms, tbl,
2204 						     &searchparms.priority);
2205 		if (rc) {
2206 			BNXT_TF_DBG(ERR, "entry priority process failed\n");
2207 			return rc;
2208 		}
2209 
2210 		rc = tf_search_tcam_entry(tfp, &searchparms);
2211 		if (rc) {
2212 			BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
2213 			return rc;
2214 		}
2215 
2216 		/* Successful search, check the result */
2217 		if (searchparms.search_status == REJECT) {
2218 			BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
2219 			return -ENOMEM;
2220 		}
2221 		idx = searchparms.idx;
2222 		hit = searchparms.hit;
2223 	}
2224 
2225 	/* Write the tcam index into the regfile*/
2226 	if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
2227 			      (uint64_t)tfp_cpu_to_be_64(idx))) {
2228 		BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
2229 			    tbl->tbl_operand);
2230 		rc = -EINVAL;
2231 		/* Need to free the tcam idx, so goto error */
2232 		goto error;
2233 	}
2234 
2235 	/* if it is miss then it is same as no search before alloc */
2236 	if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2237 		/*Scan identifier list, allocate identifier and update regfile*/
2238 		rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
2239 		/* Create the result blob */
2240 		if (!rc)
2241 			rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2242 							 "TCAM Result");
2243 		/* write the tcam entry */
2244 		if (!rc)
2245 			rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key,
2246 							     mask, &data, idx);
2247 	} else {
2248 		/*Scan identifier list, extract identifier and update regfile*/
2249 		rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
2250 	}
2251 	if (rc)
2252 		goto error;
2253 
2254 	/* Add the tcam index to the flow database */
2255 	fid_parms.direction = tbl->direction;
2256 	fid_parms.resource_func	= tbl->resource_func;
2257 	fid_parms.resource_type	= tbl->resource_type;
2258 	fid_parms.critical_resource = tbl->critical_resource;
2259 	fid_parms.resource_hndl	= idx;
2260 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2261 
2262 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2263 	if (rc) {
2264 		BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2265 			    rc);
2266 		/* Need to free the identifier, so goto error */
2267 		goto error;
2268 	}
2269 
2270 	return 0;
2271 error:
2272 	free_parms.dir			= tbl->direction;
2273 	free_parms.tcam_tbl_type	= tbl->resource_type;
2274 	free_parms.idx			= idx;
2275 	trc = tf_free_tcam_entry(tfp, &free_parms);
2276 	if (trc)
2277 		BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
2278 			    tbl->resource_type, tbl->direction, idx);
2279 	return rc;
2280 }
2281 
2282 static int32_t
2283 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2284 			  struct bnxt_ulp_mapper_tbl_info *tbl)
2285 {
2286 	struct bnxt_ulp_mapper_key_info	*kflds;
2287 	struct ulp_blob key, data;
2288 	uint32_t i, num_kflds;
2289 	uint16_t tmplen;
2290 	struct tf *tfp;
2291 	struct ulp_flow_db_res_params	fid_parms = { 0 };
2292 	struct tf_insert_em_entry_parms iparms = { 0 };
2293 	struct tf_delete_em_entry_parms free_parms = { 0 };
2294 	enum bnxt_ulp_flow_mem_type mtype;
2295 	struct bnxt_ulp_device_params *dparms = parms->device_params;
2296 	int32_t	trc;
2297 	int32_t rc = 0;
2298 	int32_t pad = 0;
2299 	enum bnxt_ulp_byte_order key_order, res_order;
2300 
2301 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2302 	rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2303 	if (rc) {
2304 		BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
2305 		return -EINVAL;
2306 	}
2307 
2308 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2309 	if (!kflds || !num_kflds) {
2310 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2311 		return -EINVAL;
2312 	}
2313 
2314 	key_order = dparms->em_byte_order;
2315 	res_order = dparms->em_byte_order;
2316 
2317 	/* Initialize the key/result blobs */
2318 	if (!ulp_blob_init(&key, tbl->blob_key_bit_size, key_order) ||
2319 	    !ulp_blob_init(&data, tbl->result_bit_size, res_order)) {
2320 		BNXT_TF_DBG(ERR, "blob inits failed.\n");
2321 		return -EINVAL;
2322 	}
2323 
2324 	/* create the key */
2325 	for (i = 0; i < num_kflds; i++) {
2326 		/* Setup the key */
2327 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2328 						  &kflds[i].field_info_spec,
2329 						  &key, 1, "EM Key");
2330 		if (rc) {
2331 			BNXT_TF_DBG(ERR, "Key field set failed.\n");
2332 			return rc;
2333 		}
2334 	}
2335 
2336 	/* if dynamic padding is enabled then add padding to result data */
2337 	if (dparms->dynamic_pad_en) {
2338 		/* add padding to make sure key is at byte boundary */
2339 		ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS);
2340 
2341 		/* add the pad */
2342 		pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits;
2343 		if (pad < 0) {
2344 			BNXT_TF_DBG(ERR, "Invalid em blk size and align\n");
2345 			return -EINVAL;
2346 		}
2347 		ulp_blob_pad_push(&data, (uint32_t)pad);
2348 	}
2349 
2350 	/* Create the result data blob */
2351 	rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
2352 	if (rc) {
2353 		BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2354 		return rc;
2355 	}
2356 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2357 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2358 	ulp_mapper_result_dump("EM Result", tbl, &data);
2359 #endif
2360 #endif
2361 	if (dparms->dynamic_pad_en) {
2362 		uint32_t abits = dparms->em_blk_align_bits;
2363 
2364 		/* when dynamic padding is enabled merge result + key */
2365 		rc = ulp_blob_block_merge(&data, &key, abits, pad);
2366 		if (rc) {
2367 			BNXT_TF_DBG(ERR, "Failed to merge the result blob\n");
2368 			return rc;
2369 		}
2370 
2371 		/* add padding to make sure merged result is at slice boundary*/
2372 		ulp_blob_pad_align(&data, abits);
2373 
2374 		ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits));
2375 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2376 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2377 	ulp_mapper_result_dump("EM Merged Result", tbl, &data);
2378 #endif
2379 #endif
2380 	}
2381 
2382 	/* do the transpose for the internal EM keys */
2383 	if (tbl->resource_type == TF_MEM_INTERNAL) {
2384 		if (dparms->em_key_align_bytes) {
2385 			int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes);
2386 
2387 			tmplen = ulp_blob_data_len_get(&key);
2388 			ulp_blob_pad_push(&key, b - tmplen);
2389 		}
2390 		tmplen = ulp_blob_data_len_get(&key);
2391 		ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen));
2392 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2393 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2394 	ulp_mapper_result_dump("EM Key Transpose", tbl, &key);
2395 #endif
2396 #endif
2397 	}
2398 
2399 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
2400 					     &iparms.tbl_scope_id);
2401 	if (rc) {
2402 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2403 		return rc;
2404 	}
2405 
2406 	/*
2407 	 * NOTE: the actual blob size will differ from the size in the tbl
2408 	 * entry due to the padding.
2409 	 */
2410 	iparms.dup_check		= 0;
2411 	iparms.dir			= tbl->direction;
2412 	iparms.mem			= tbl->resource_type;
2413 	iparms.key			= ulp_blob_data_get(&key, &tmplen);
2414 	iparms.key_sz_in_bits		= tbl->key_bit_size;
2415 	iparms.em_record		= ulp_blob_data_get(&data, &tmplen);
2416 	if (tbl->result_bit_size)
2417 		iparms.em_record_sz_in_bits	= tbl->result_bit_size;
2418 	else
2419 		iparms.em_record_sz_in_bits	= tmplen;
2420 
2421 	rc = tf_insert_em_entry(tfp, &iparms);
2422 	if (rc) {
2423 		BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
2424 		return rc;
2425 	}
2426 
2427 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2428 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2429 	ulp_mapper_em_dump("EM", &key, &data, &iparms);
2430 	/* tf_dump_tables(tfp, iparms.tbl_scope_id); */
2431 #endif
2432 #endif
2433 	/* Mark action process */
2434 	if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
2435 	    tbl->resource_type == TF_MEM_EXTERNAL)
2436 		rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
2437 	else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
2438 		 tbl->resource_type == TF_MEM_INTERNAL)
2439 		rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
2440 	if (rc) {
2441 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
2442 		goto error;
2443 	}
2444 
2445 	/* Link the EM resource to the flow in the flow db */
2446 	memset(&fid_parms, 0, sizeof(fid_parms));
2447 	fid_parms.direction		= tbl->direction;
2448 	fid_parms.resource_func		= tbl->resource_func;
2449 	fid_parms.resource_type		= tbl->resource_type;
2450 	fid_parms.critical_resource	= tbl->critical_resource;
2451 	fid_parms.resource_hndl		= iparms.flow_handle;
2452 
2453 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2454 	if (rc) {
2455 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2456 			    rc);
2457 		/* Need to free the identifier, so goto error */
2458 		goto error;
2459 	}
2460 
2461 	return 0;
2462 error:
2463 	free_parms.dir		= iparms.dir;
2464 	free_parms.mem		= iparms.mem;
2465 	free_parms.tbl_scope_id	= iparms.tbl_scope_id;
2466 	free_parms.flow_handle	= iparms.flow_handle;
2467 
2468 	trc = tf_delete_em_entry(tfp, &free_parms);
2469 	if (trc)
2470 		BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2471 
2472 	return rc;
2473 }
2474 
2475 static int32_t
2476 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2477 			     struct bnxt_ulp_mapper_tbl_info *tbl)
2478 {
2479 	struct ulp_flow_db_res_params fid_parms;
2480 	struct ulp_blob	data;
2481 	uint64_t regval = 0;
2482 	uint16_t tmplen;
2483 	uint32_t index;
2484 	int32_t rc = 0, trc = 0;
2485 	struct tf_alloc_tbl_entry_parms aparms = { 0 };
2486 	struct tf_set_tbl_entry_parms sparms = { 0 };
2487 	struct tf_get_tbl_entry_parms gparms = { 0 };
2488 	struct tf_free_tbl_entry_parms free_parms = { 0 };
2489 	uint32_t tbl_scope_id;
2490 	struct tf *tfp;
2491 	struct bnxt_ulp_glb_resource_info glb_res = { 0 };
2492 	uint16_t bit_size;
2493 	bool alloc = false;
2494 	bool write = false;
2495 	bool global = false;
2496 	uint64_t act_rec_size;
2497 	bool shared = false;
2498 	enum tf_tbl_type tbl_type = tbl->resource_type;
2499 
2500 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2501 	/* compute the blob size */
2502 	bit_size = ulp_mapper_dyn_blob_size_get(parms, tbl);
2503 
2504 	/* Initialize the blob data */
2505 	if (!ulp_blob_init(&data, bit_size,
2506 			   parms->device_params->result_byte_order)) {
2507 		BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2508 		return -EINVAL;
2509 	}
2510 
2511 	/* Get the scope id first */
2512 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2513 	if (rc) {
2514 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2515 		return rc;
2516 	}
2517 
2518 	switch (tbl->tbl_opcode) {
2519 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2520 		alloc = true;
2521 		break;
2522 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2523 		/*
2524 		 * Build the entry, alloc an index, write the table, and store
2525 		 * the data in the regfile.
2526 		 */
2527 		alloc = true;
2528 		write = true;
2529 		break;
2530 	case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2531 		/*
2532 		 * get the index to write to from the regfile and then write
2533 		 * the table entry.
2534 		 */
2535 		if (!ulp_regfile_read(parms->regfile,
2536 				      tbl->tbl_operand,
2537 				      &regval)) {
2538 			BNXT_TF_DBG(ERR,
2539 				    "Failed to get tbl idx from regfile[%d].\n",
2540 				    tbl->tbl_operand);
2541 			return -EINVAL;
2542 		}
2543 		index = tfp_be_to_cpu_64(regval);
2544 		/* For external, we need to reverse shift */
2545 		if (tbl->resource_type == TF_TBL_TYPE_EXT)
2546 			index = TF_ACT_REC_PTR_2_OFFSET(index);
2547 
2548 		write = true;
2549 		break;
2550 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE:
2551 		/*
2552 		 * Build the entry, alloc an index, write the table, and store
2553 		 * the data in the global regfile.
2554 		 */
2555 		alloc = true;
2556 		global = true;
2557 		write = true;
2558 		glb_res.direction = tbl->direction;
2559 		glb_res.resource_func = tbl->resource_func;
2560 		glb_res.resource_type = tbl->resource_type;
2561 		glb_res.glb_regfile_index = tbl->tbl_operand;
2562 		break;
2563 	case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2564 		if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2565 			BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2566 			return -EINVAL;
2567 		}
2568 		/*
2569 		 * get the index to write to from the global regfile and then
2570 		 * write the table.
2571 		 */
2572 		if (ulp_mapper_glb_resource_read(parms->mapper_data,
2573 						 tbl->direction,
2574 						 tbl->tbl_operand,
2575 						 &regval, &shared)) {
2576 			BNXT_TF_DBG(ERR,
2577 				    "Failed to get tbl idx from Glb RF[%d].\n",
2578 				    tbl->tbl_operand);
2579 			return -EINVAL;
2580 		}
2581 		index = tfp_be_to_cpu_64(regval);
2582 		/* For external, we need to reverse shift */
2583 		if (tbl->resource_type == TF_TBL_TYPE_EXT)
2584 			index = TF_ACT_REC_PTR_2_OFFSET(index);
2585 		write = true;
2586 		break;
2587 	case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2588 		/*
2589 		 * The read is different from the rest and can be handled here
2590 		 * instead of trying to use common code.  Simply read the table
2591 		 * with the index from the regfile, scan and store the
2592 		 * identifiers, and return.
2593 		 */
2594 		if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2595 			/* Not currently supporting with EXT */
2596 			BNXT_TF_DBG(ERR,
2597 				    "Ext Table Read Opcode not supported.\n");
2598 			return -EINVAL;
2599 		}
2600 		if (!ulp_regfile_read(parms->regfile,
2601 				      tbl->tbl_operand, &regval)) {
2602 			BNXT_TF_DBG(ERR,
2603 				    "Failed to get tbl idx from regfile[%d]\n",
2604 				    tbl->tbl_operand);
2605 			return -EINVAL;
2606 		}
2607 		index = tfp_be_to_cpu_64(regval);
2608 		gparms.dir = tbl->direction;
2609 		gparms.type = tbl->resource_type;
2610 		gparms.data = ulp_blob_data_get(&data, &tmplen);
2611 		gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2612 		gparms.idx = index;
2613 		rc = tf_get_tbl_entry(tfp, &gparms);
2614 		if (rc) {
2615 			BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2616 				    tbl->resource_type, index);
2617 			return rc;
2618 		}
2619 		/*
2620 		 * Scan the fields in the entry and push them into the regfile.
2621 		 */
2622 		rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2623 						   gparms.data,
2624 						   gparms.data_sz_in_bytes,
2625 						   data.byte_order);
2626 		if (rc) {
2627 			BNXT_TF_DBG(ERR,
2628 				    "Failed to get flds on tbl read rc=%d\n",
2629 				    rc);
2630 			return rc;
2631 		}
2632 		return 0;
2633 	default:
2634 		BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2635 			    tbl->tbl_opcode);
2636 		return -EINVAL;
2637 	}
2638 
2639 	if (write) {
2640 		/* Get the result fields list */
2641 		rc = ulp_mapper_tbl_result_build(parms,
2642 						 tbl,
2643 						 &data,
2644 						 "Indexed Result");
2645 		if (rc) {
2646 			BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2647 			return rc;
2648 		}
2649 	}
2650 
2651 	if (alloc) {
2652 		aparms.dir		= tbl->direction;
2653 		tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl,
2654 						       &data, &tmplen);
2655 		aparms.type = tbl_type;
2656 		aparms.tbl_scope_id	= tbl_scope_id;
2657 
2658 		/* All failures after the alloc succeeds require a free */
2659 		rc = tf_alloc_tbl_entry(tfp, &aparms);
2660 		if (rc) {
2661 			BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2662 				    tf_tbl_type_2_str(aparms.type),
2663 				    tf_dir_2_str(tbl->direction), rc);
2664 			return rc;
2665 		}
2666 		index = aparms.idx;
2667 
2668 		/*
2669 		 * Store the index in the regfile since we either allocated it
2670 		 * or it was a hit.
2671 		 *
2672 		 * Calculate the idx for the result record, for external EM the
2673 		 * offset needs to be shifted accordingly.
2674 		 * If external non-inline table types are used then need to
2675 		 * revisit this logic.
2676 		 */
2677 		if (tbl->resource_type == TF_TBL_TYPE_EXT)
2678 			regval = TF_ACT_REC_OFFSET_2_PTR(index);
2679 		else
2680 			regval = index;
2681 		regval = tfp_cpu_to_be_64(regval);
2682 
2683 		if (global) {
2684 			/*
2685 			 * Shared resources are never allocated through this
2686 			 * method, so the shared flag is always false.
2687 			 */
2688 			rc = ulp_mapper_glb_resource_write(parms->mapper_data,
2689 							   &glb_res, regval,
2690 							   false);
2691 		} else {
2692 			rc = ulp_regfile_write(parms->regfile,
2693 					       tbl->tbl_operand, regval);
2694 		}
2695 		if (rc) {
2696 			BNXT_TF_DBG(ERR,
2697 				    "Failed to write %s regfile[%d] rc=%d\n",
2698 				    (global) ? "global" : "reg",
2699 				    tbl->tbl_operand, rc);
2700 			goto error;
2701 		}
2702 	}
2703 
2704 	if (write) {
2705 		sparms.dir = tbl->direction;
2706 		sparms.data = ulp_blob_data_get(&data, &tmplen);
2707 		tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl, &data,
2708 						       &tmplen);
2709 		sparms.type = tbl_type;
2710 		sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2711 		sparms.idx = index;
2712 		sparms.tbl_scope_id = tbl_scope_id;
2713 		if (shared)
2714 			tfp = bnxt_ulp_cntxt_shared_tfp_get(parms->ulp_ctx);
2715 		rc = tf_set_tbl_entry(tfp, &sparms);
2716 		if (rc) {
2717 			BNXT_TF_DBG(ERR,
2718 				    "Index table[%s][%s][%x] write fail rc=%d\n",
2719 				    tf_tbl_type_2_str(sparms.type),
2720 				    tf_dir_2_str(sparms.dir),
2721 				    sparms.idx, rc);
2722 			goto error;
2723 		}
2724 		BNXT_TF_INF("Index table[%s][%s][%x] write successful.\n",
2725 			    tf_tbl_type_2_str(sparms.type),
2726 			    tf_dir_2_str(sparms.dir), sparms.idx);
2727 
2728 		/* Calculate action record size */
2729 		if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2730 			act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
2731 			act_rec_size--;
2732 			if (ulp_regfile_write(parms->regfile,
2733 					      BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
2734 					      tfp_cpu_to_be_64(act_rec_size)))
2735 				BNXT_TF_DBG(ERR,
2736 					    "Failed write the act rec size\n");
2737 		}
2738 	}
2739 
2740 	/* Link the resource to the flow in the flow db */
2741 	memset(&fid_parms, 0, sizeof(fid_parms));
2742 	fid_parms.direction	= tbl->direction;
2743 	fid_parms.resource_func	= tbl->resource_func;
2744 	fid_parms.resource_type	= tbl_type;
2745 	fid_parms.resource_sub_type = tbl->resource_sub_type;
2746 	fid_parms.resource_hndl	= index;
2747 	fid_parms.critical_resource = tbl->critical_resource;
2748 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2749 
2750 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2751 	if (rc) {
2752 		BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2753 			    rc);
2754 		goto error;
2755 	}
2756 
2757 	/* Perform the VF rep action */
2758 	rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2759 	if (rc) {
2760 		BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2761 		goto error;
2762 	}
2763 	return rc;
2764 error:
2765 	/* Shared resources are not freed */
2766 	if (shared)
2767 		return rc;
2768 	/*
2769 	 * Free the allocated resource since we failed to either
2770 	 * write to the entry or link the flow
2771 	 */
2772 	free_parms.dir	= tbl->direction;
2773 	free_parms.type	= tbl_type;
2774 	free_parms.idx	= index;
2775 	free_parms.tbl_scope_id = tbl_scope_id;
2776 
2777 	trc = tf_free_tbl_entry(tfp, &free_parms);
2778 	if (trc)
2779 		BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2780 
2781 	return rc;
2782 }
2783 
2784 static int32_t
2785 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2786 			  struct bnxt_ulp_mapper_tbl_info *tbl)
2787 {
2788 	struct ulp_blob	data, res_blob;
2789 	uint64_t idx;
2790 	uint16_t tmplen;
2791 	int32_t rc = 0;
2792 	struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2793 	struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2794 	struct tf *tfp;
2795 	enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2796 	uint32_t res_size;
2797 
2798 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2799 	/* Initialize the blob data */
2800 	if (!ulp_blob_init(&data, tbl->result_bit_size,
2801 			   parms->device_params->result_byte_order)) {
2802 		BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2803 		return -EINVAL;
2804 	}
2805 
2806 	/* create the result blob */
2807 	rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2808 	if (rc) {
2809 		BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2810 		return rc;
2811 	}
2812 
2813 	/* Get the index details */
2814 	switch (if_opc) {
2815 	case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2816 		idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2817 		break;
2818 	case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2819 		if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2820 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2821 				    tbl->tbl_operand);
2822 			return -EINVAL;
2823 		}
2824 		idx = tfp_be_to_cpu_64(idx);
2825 		break;
2826 	case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2827 		idx = tbl->tbl_operand;
2828 		break;
2829 	case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2830 		/* Initialize the result blob */
2831 		if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2832 				   parms->device_params->result_byte_order)) {
2833 			BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2834 			return -EINVAL;
2835 		}
2836 
2837 		/* read the interface table */
2838 		idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2839 		res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2840 		get_parms.dir = tbl->direction;
2841 		get_parms.type = tbl->resource_type;
2842 		get_parms.idx = idx;
2843 		get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2844 		get_parms.data_sz_in_bytes = res_size;
2845 
2846 		rc = tf_get_if_tbl_entry(tfp, &get_parms);
2847 		if (rc) {
2848 			BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2849 				    get_parms.type,
2850 				    tf_dir_2_str(get_parms.dir),
2851 				    get_parms.idx, rc);
2852 			return rc;
2853 		}
2854 		rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2855 						   res_blob.data,
2856 						   res_size,
2857 						   res_blob.byte_order);
2858 		if (rc)
2859 			BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2860 		return rc;
2861 	case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2862 		return rc; /* skip it */
2863 	default:
2864 		BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2865 		return -EINVAL;
2866 	}
2867 
2868 	/* Perform the tf table set by filling the set params */
2869 	iftbl_params.dir = tbl->direction;
2870 	iftbl_params.type = tbl->resource_type;
2871 	iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2872 	iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2873 	iftbl_params.idx = idx;
2874 
2875 	rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2876 	if (rc) {
2877 		BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2878 			    iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2879 			    tf_dir_2_str(iftbl_params.dir),
2880 			    iftbl_params.idx, rc);
2881 		return rc;
2882 	}
2883 	BNXT_TF_INF("Set table[%s][%s][%x] success.\n",
2884 		    tf_if_tbl_2_str(iftbl_params.type),
2885 		    tf_dir_2_str(iftbl_params.dir),
2886 		    iftbl_params.idx);
2887 
2888 	/*
2889 	 * TBD: Need to look at the need to store idx in flow db for restore
2890 	 * the table to its original state on deletion of this entry.
2891 	 */
2892 	return rc;
2893 }
2894 
2895 static int32_t
2896 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2897 			   struct bnxt_ulp_mapper_tbl_info *tbl)
2898 {
2899 	struct ulp_mapper_gen_tbl_list *gen_tbl_list;
2900 	struct bnxt_ulp_mapper_key_info *kflds;
2901 	struct ulp_flow_db_res_params fid_parms;
2902 	struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2903 	struct ulp_gen_hash_entry_params hash_entry;
2904 	uint16_t tmplen = 0;
2905 	struct ulp_blob key, data;
2906 	uint8_t *cache_key;
2907 	int32_t tbl_idx;
2908 	uint32_t i, num_kflds = 0, key_index = 0;
2909 	uint32_t gen_tbl_miss = 1, fdb_write = 0;
2910 	uint8_t *byte_data;
2911 	int32_t rc = 0;
2912 
2913 	/* Get the key fields list and build the key. */
2914 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2915 	if (!kflds || !num_kflds) {
2916 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2917 		return -EINVAL;
2918 	}
2919 
2920 	if (!ulp_blob_init(&key, tbl->key_bit_size,
2921 			   parms->device_params->key_byte_order)) {
2922 		BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2923 		return -EINVAL;
2924 	}
2925 	for (i = 0; i < num_kflds; i++) {
2926 		/* Setup the key */
2927 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2928 						  &kflds[i].field_info_spec,
2929 						  &key, 1, "Gen Tbl Key");
2930 		if (rc) {
2931 			BNXT_TF_DBG(ERR,
2932 				    "Failed to create key for Gen tbl rc=%d\n",
2933 				    rc);
2934 			return -EINVAL;
2935 		}
2936 	}
2937 
2938 	/* Calculate the table index for the generic table*/
2939 	tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2940 						   tbl->direction);
2941 	if (tbl_idx < 0) {
2942 		BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2943 			    tbl->resource_sub_type, tbl->direction);
2944 		return -EINVAL;
2945 	}
2946 
2947 	/* The_key is a byte array convert it to a search index */
2948 	cache_key = ulp_blob_data_get(&key, &tmplen);
2949 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2950 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2951 	ulp_mapper_gen_tbl_dump(tbl->resource_sub_type, tbl->direction, &key);
2952 #endif
2953 #endif
2954 	/* get the generic table  */
2955 	gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx];
2956 
2957 	/* Check if generic hash table */
2958 	if (gen_tbl_list->hash_tbl) {
2959 		if (tbl->gen_tbl_lkup_type !=
2960 		    BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) {
2961 			BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n",
2962 				    gen_tbl_list->gen_tbl_name);
2963 			return -EINVAL;
2964 		}
2965 		hash_entry.key_data = cache_key;
2966 		hash_entry.key_length = ULP_BITS_2_BYTE(tmplen);
2967 		rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl,
2968 						      &hash_entry);
2969 		if (rc) {
2970 			BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n",
2971 				    gen_tbl_list->gen_tbl_name);
2972 			return rc;
2973 		}
2974 		if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) {
2975 			key_index = hash_entry.key_idx;
2976 			/* Get the generic table entry */
2977 			if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list,
2978 							 key_index,
2979 							 &gen_tbl_ent))
2980 				return -EINVAL;
2981 			/* store the hash index in the fdb */
2982 			key_index = hash_entry.hash_index;
2983 		}
2984 	} else {
2985 		/* convert key to index directly */
2986 		if (ULP_BITS_2_BYTE(tmplen) > (int32_t)sizeof(key_index)) {
2987 			BNXT_TF_DBG(ERR, "%s: keysize is bigger then 4 bytes\n",
2988 				    gen_tbl_list->gen_tbl_name);
2989 			return -EINVAL;
2990 		}
2991 		memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen));
2992 		/* Get the generic table entry */
2993 		if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index,
2994 						 &gen_tbl_ent))
2995 			return -EINVAL;
2996 	}
2997 	switch (tbl->tbl_opcode) {
2998 	case BNXT_ULP_GENERIC_TBL_OPC_READ:
2999 		if (gen_tbl_list->hash_tbl) {
3000 			if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND)
3001 				break; /* nothing to be done , no entry */
3002 		}
3003 
3004 		/* check the reference count */
3005 		if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
3006 			g = &gen_tbl_ent;
3007 			/* Scan ident list and create the result blob*/
3008 			rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
3009 							   g->byte_data,
3010 							   g->byte_data_size,
3011 							   g->byte_order);
3012 			if (rc) {
3013 				BNXT_TF_DBG(ERR,
3014 					    "Failed to scan ident list\n");
3015 				return -EINVAL;
3016 			}
3017 			if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
3018 				/* increment the reference count */
3019 				ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
3020 			}
3021 
3022 			/* it is a hit */
3023 			gen_tbl_miss = 0;
3024 			fdb_write = 1;
3025 		}
3026 		break;
3027 	case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
3028 		if (gen_tbl_list->hash_tbl) {
3029 			rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list,
3030 							       &hash_entry,
3031 							       &gen_tbl_ent);
3032 			if (rc)
3033 				return rc;
3034 			/* store the hash index in the fdb */
3035 			key_index = hash_entry.hash_index;
3036 		}
3037 		/* check the reference count */
3038 		if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
3039 			/* a hit then error */
3040 			BNXT_TF_DBG(ERR, "generic entry already present\n");
3041 			return -EINVAL; /* success */
3042 		}
3043 
3044 		/* Initialize the blob data */
3045 		if (!ulp_blob_init(&data, tbl->result_bit_size,
3046 				   gen_tbl_ent.byte_order)) {
3047 			BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
3048 			return -EINVAL;
3049 		}
3050 
3051 		/* Get the result fields list */
3052 		rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
3053 						 "Gen tbl Result");
3054 		if (rc) {
3055 			BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
3056 			return rc;
3057 		}
3058 		byte_data = ulp_blob_data_get(&data, &tmplen);
3059 		rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
3060 						       tmplen, byte_data,
3061 						       ULP_BITS_2_BYTE(tmplen));
3062 		if (rc) {
3063 			BNXT_TF_DBG(ERR, "Failed to write generic table\n");
3064 			return -EINVAL;
3065 		}
3066 
3067 		/* increment the reference count */
3068 		ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
3069 		fdb_write = 1;
3070 		parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index;
3071 		break;
3072 	default:
3073 		BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
3074 		return -EINVAL;
3075 	}
3076 
3077 	/* Set the generic entry hit */
3078 	rc = ulp_regfile_write(parms->regfile,
3079 			       BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3080 			       tfp_cpu_to_be_64(gen_tbl_miss));
3081 	if (rc) {
3082 		BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
3083 			    BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3084 		return -EIO;
3085 	}
3086 
3087 	/* add the entry to the flow database */
3088 	if (fdb_write) {
3089 		memset(&fid_parms, 0, sizeof(fid_parms));
3090 		fid_parms.direction = tbl->direction;
3091 		fid_parms.resource_func	= tbl->resource_func;
3092 		fid_parms.resource_sub_type = tbl->resource_sub_type;
3093 		fid_parms.resource_hndl	= key_index;
3094 		fid_parms.critical_resource = tbl->critical_resource;
3095 		ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
3096 
3097 		rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
3098 		if (rc)
3099 			BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
3100 	}
3101 	return rc;
3102 }
3103 
3104 static int32_t
3105 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
3106 			    struct bnxt_ulp_mapper_tbl_info *tbl)
3107 {
3108 	int32_t rc = 0;
3109 
3110 	/* process the fdb opcode for alloc push */
3111 	if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
3112 		rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
3113 		if (rc) {
3114 			BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
3115 			return rc;
3116 		}
3117 	}
3118 	return rc;
3119 }
3120 
3121 static int32_t
3122 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
3123 				  struct bnxt_ulp_mapper_data *mapper_data)
3124 {
3125 	struct bnxt_ulp_glb_resource_info *glb_res;
3126 	uint32_t num_glb_res_ids, idx, dev_id;
3127 	uint8_t app_id;
3128 	int32_t rc = 0;
3129 
3130 	glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
3131 	if (!glb_res || !num_glb_res_ids) {
3132 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
3133 		return -EINVAL;
3134 	}
3135 
3136 	rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
3137 	if (rc) {
3138 		BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n",
3139 			    rc);
3140 		return rc;
3141 	}
3142 
3143 	rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
3144 	if (rc) {
3145 		BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n",
3146 			    rc);
3147 		return rc;
3148 	}
3149 
3150 	/* Iterate the global resources and process each one */
3151 	for (idx = 0; idx < num_glb_res_ids; idx++) {
3152 		if (dev_id != glb_res[idx].device_id ||
3153 		    glb_res[idx].app_id != app_id)
3154 			continue;
3155 		switch (glb_res[idx].resource_func) {
3156 		case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3157 			rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
3158 								mapper_data,
3159 								&glb_res[idx]);
3160 			break;
3161 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3162 			rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
3163 								 mapper_data,
3164 								 &glb_res[idx]);
3165 			break;
3166 		default:
3167 			BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
3168 				    glb_res[idx].resource_func);
3169 			rc = -EINVAL;
3170 			break;
3171 		}
3172 		if (rc)
3173 			return rc;
3174 	}
3175 	return rc;
3176 }
3177 
3178 /*
3179  * Iterate over the shared resources assigned during tf_open_session and store
3180  * them in the global regfile with the shared flag.
3181  */
3182 static int32_t
3183 ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
3184 				      struct bnxt_ulp_mapper_data *mapper_data)
3185 {
3186 	struct tf_get_shared_tbl_increment_parms iparms;
3187 	struct bnxt_ulp_glb_resource_info *glb_res;
3188 	struct tf_get_session_info_parms sparms;
3189 	uint32_t num_entries, i, dev_id, res;
3190 	struct tf_resource_info *res_info;
3191 	uint32_t addend;
3192 	uint64_t regval;
3193 	enum tf_dir dir;
3194 	int32_t rc = 0;
3195 	struct tf *tfp;
3196 	uint8_t app_id;
3197 
3198 	memset(&sparms, 0, sizeof(sparms));
3199 	glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_entries);
3200 	if (!glb_res || !num_entries) {
3201 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
3202 		return -EINVAL;
3203 	}
3204 	tfp = bnxt_ulp_cntxt_shared_tfp_get(ulp_ctx);
3205 	if (!tfp) {
3206 		BNXT_TF_DBG(ERR, "Failed to get tfp for app global init");
3207 		return -EINVAL;
3208 	}
3209 	/*
3210 	 * Retrieve the resources that were assigned during the shared session
3211 	 * creation.
3212 	 */
3213 	rc = tf_get_session_info(tfp, &sparms);
3214 	if (rc) {
3215 		BNXT_TF_DBG(ERR, "Failed to get session info (%d)\n", rc);
3216 		return rc;
3217 	}
3218 
3219 	rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
3220 	if (rc) {
3221 		BNXT_TF_DBG(ERR, "Failed to get the app id in glb init (%d).\n",
3222 			    rc);
3223 		return rc;
3224 	}
3225 
3226 	rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
3227 	if (rc) {
3228 		BNXT_TF_DBG(ERR, "Failed to get dev id for app glb init (%d)\n",
3229 			    rc);
3230 		return rc;
3231 	}
3232 
3233 	/* Store all the app global resources */
3234 	for (i = 0; i < num_entries; i++) {
3235 		if (dev_id != glb_res[i].device_id ||
3236 		    app_id != glb_res[i].app_id)
3237 			continue;
3238 		dir = glb_res[i].direction;
3239 		res = glb_res[i].resource_type;
3240 		addend = 1;
3241 
3242 		switch (glb_res[i].resource_func) {
3243 		case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3244 			res_info = &sparms.session_info.ident[dir].info[res];
3245 			break;
3246 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3247 			/*
3248 			 * Tables may have various strides for the allocations.
3249 			 * Need to account.
3250 			 */
3251 			memset(&iparms, 0, sizeof(iparms));
3252 			iparms.dir = dir;
3253 			iparms.type = res;
3254 			rc = tf_get_shared_tbl_increment(tfp, &iparms);
3255 			if (rc) {
3256 				BNXT_TF_DBG(ERR,
3257 					    "Failed to get addend for %s[%s] rc=(%d)\n",
3258 					    tf_tbl_type_2_str(res),
3259 					    tf_dir_2_str(dir), rc);
3260 				return rc;
3261 			}
3262 			addend = iparms.increment_cnt;
3263 			res_info = &sparms.session_info.tbl[dir].info[res];
3264 			break;
3265 		case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3266 			res_info = &sparms.session_info.tcam[dir].info[res];
3267 			break;
3268 		case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3269 			res_info = &sparms.session_info.em[dir].info[res];
3270 			break;
3271 		default:
3272 			BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n",
3273 				    glb_res[i].resource_func);
3274 			continue;
3275 		}
3276 		regval = tfp_cpu_to_be_64((uint64_t)res_info->start);
3277 		res_info->start += addend;
3278 		/*
3279 		 * All resources written to the global regfile are shared for
3280 		 * this function.
3281 		 */
3282 		rc = ulp_mapper_glb_resource_write(mapper_data, &glb_res[i],
3283 						   regval, true);
3284 		if (rc)
3285 			return rc;
3286 	}
3287 
3288 	return rc;
3289 }
3290 
3291 /*
3292  * Common conditional opcode process routine that is used for both the template
3293  * rejection and table conditional execution.
3294  */
3295 static int32_t
3296 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
3297 			    enum bnxt_ulp_cond_opc opc,
3298 			    uint32_t operand,
3299 			    int32_t *res)
3300 {
3301 	enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
3302 	int32_t rc = 0;
3303 	uint8_t bit;
3304 	uint64_t regval;
3305 
3306 	switch (opc) {
3307 	case BNXT_ULP_COND_OPC_CF_IS_SET:
3308 		if (operand < BNXT_ULP_CF_IDX_LAST) {
3309 			*res = ULP_COMP_FLD_IDX_RD(parms, operand);
3310 		} else {
3311 			BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
3312 				    operand);
3313 			rc = -EINVAL;
3314 		}
3315 		break;
3316 	case BNXT_ULP_COND_OPC_CF_NOT_SET:
3317 		if (operand < BNXT_ULP_CF_IDX_LAST) {
3318 			*res = !ULP_COMP_FLD_IDX_RD(parms, operand);
3319 		} else {
3320 			BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
3321 				    operand);
3322 			rc = -EINVAL;
3323 		}
3324 		break;
3325 	case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
3326 		if (operand < BNXT_ULP_ACT_BIT_LAST) {
3327 			*res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3328 						operand);
3329 		} else {
3330 			BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
3331 				    operand);
3332 			rc = -EINVAL;
3333 		}
3334 		break;
3335 	case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
3336 		if (operand < BNXT_ULP_ACT_BIT_LAST) {
3337 			*res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3338 					       operand);
3339 		} else {
3340 			BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
3341 				    operand);
3342 			rc = -EINVAL;
3343 		}
3344 		break;
3345 	case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
3346 		if (operand < BNXT_ULP_HDR_BIT_LAST) {
3347 			*res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3348 						operand);
3349 		} else {
3350 			BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3351 				    operand);
3352 			rc = -EINVAL;
3353 		}
3354 		break;
3355 	case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
3356 		if (operand < BNXT_ULP_HDR_BIT_LAST) {
3357 			*res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3358 					       operand);
3359 		} else {
3360 			BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3361 				    operand);
3362 			rc = -EINVAL;
3363 		}
3364 		break;
3365 	case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
3366 		rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3367 		if (rc) {
3368 			BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
3369 				    operand);
3370 			return -EINVAL;
3371 		}
3372 		*res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3373 		break;
3374 	case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
3375 		rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3376 		if (rc) {
3377 			BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
3378 				    operand);
3379 			return -EINVAL;
3380 		}
3381 		*res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3382 		break;
3383 	case BNXT_ULP_COND_OPC_RF_IS_SET:
3384 		if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
3385 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
3386 			return -EINVAL;
3387 		}
3388 		*res = regval != 0;
3389 		break;
3390 	case BNXT_ULP_COND_OPC_RF_NOT_SET:
3391 		if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
3392 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
3393 			return -EINVAL;
3394 		}
3395 		*res = regval == 0;
3396 		break;
3397 	case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
3398 		*res = parms->flow_pattern_id == operand;
3399 		break;
3400 	case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
3401 		*res = parms->act_pattern_id == operand;
3402 		break;
3403 	case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET:
3404 		if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3405 			BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3406 			return -EINVAL;
3407 		}
3408 		*res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1;
3409 		break;
3410 	case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET:
3411 		if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3412 			BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3413 			return -EINVAL;
3414 		}
3415 		*res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0;
3416 		break;
3417 	case BNXT_ULP_COND_OPC_ENC_HDR_BIT_IS_SET:
3418 		if (operand < BNXT_ULP_HDR_BIT_LAST) {
3419 			*res = ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits,
3420 						operand);
3421 		} else {
3422 			BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3423 				    operand);
3424 			rc = -EINVAL;
3425 		}
3426 		break;
3427 	case BNXT_ULP_COND_OPC_ENC_HDR_BIT_NOT_SET:
3428 		if (operand < BNXT_ULP_HDR_BIT_LAST) {
3429 			*res = !ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits,
3430 						 operand);
3431 		} else {
3432 			BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3433 				    operand);
3434 			rc = -EINVAL;
3435 		}
3436 		break;
3437 	default:
3438 		BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
3439 		rc = -EINVAL;
3440 		break;
3441 	}
3442 	return (rc);
3443 }
3444 
3445 static int32_t
3446 ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms,
3447 			    enum tf_dir dir,
3448 			    enum bnxt_ulp_func_src func_src,
3449 			    uint16_t func_opr,
3450 			    uint64_t *result)
3451 {
3452 	uint64_t regval;
3453 	bool shared;
3454 
3455 	*result =  false;
3456 	switch (func_src) {
3457 	case BNXT_ULP_FUNC_SRC_COMP_FIELD:
3458 		if (func_opr >= BNXT_ULP_CF_IDX_LAST) {
3459 			BNXT_TF_DBG(ERR, "invalid index %u\n", func_opr);
3460 			return -EINVAL;
3461 		}
3462 		*result = ULP_COMP_FLD_IDX_RD(parms, func_opr);
3463 		break;
3464 	case BNXT_ULP_FUNC_SRC_REGFILE:
3465 		if (!ulp_regfile_read(parms->regfile, func_opr, &regval)) {
3466 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", func_opr);
3467 			return -EINVAL;
3468 		}
3469 		*result = tfp_be_to_cpu_64(regval);
3470 		break;
3471 	case BNXT_ULP_FUNC_SRC_GLB_REGFILE:
3472 		if (ulp_mapper_glb_resource_read(parms->mapper_data, dir,
3473 						 func_opr, &regval, &shared)) {
3474 			BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n",
3475 				    func_opr);
3476 			return -EINVAL;
3477 		}
3478 		*result = tfp_be_to_cpu_64(regval);
3479 		break;
3480 	case BNXT_ULP_FUNC_SRC_CONST:
3481 		*result = func_opr;
3482 		break;
3483 	default:
3484 		BNXT_TF_DBG(ERR, "invalid src code %u\n", func_src);
3485 		return -EINVAL;
3486 	}
3487 	return 0;
3488 }
3489 
3490 static int32_t
3491 ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms,
3492 			     struct bnxt_ulp_mapper_tbl_info *tbl)
3493 {
3494 	struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info;
3495 	uint64_t res = 0, res1 = 0, res2 = 0;
3496 	int32_t rc = 0;
3497 	uint32_t process_src1 = 0, process_src2 = 0;
3498 
3499 	/* determine which functional operands to compute */
3500 	switch (func_info->func_opc) {
3501 	case BNXT_ULP_FUNC_OPC_NOP:
3502 		return rc;
3503 	case BNXT_ULP_FUNC_OPC_EQ:
3504 	case BNXT_ULP_FUNC_OPC_NE:
3505 	case BNXT_ULP_FUNC_OPC_GE:
3506 	case BNXT_ULP_FUNC_OPC_GT:
3507 	case BNXT_ULP_FUNC_OPC_LE:
3508 	case BNXT_ULP_FUNC_OPC_LT:
3509 		process_src1 = 1;
3510 		process_src2 = 1;
3511 		break;
3512 	case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3513 		process_src1 = 1;
3514 		break;
3515 	default:
3516 		break;
3517 	}
3518 
3519 	if (process_src1) {
3520 		rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3521 						 func_info->func_src1,
3522 						 func_info->func_opr1, &res1);
3523 		if (rc)
3524 			return rc;
3525 	}
3526 
3527 	if (process_src2) {
3528 		rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3529 						 func_info->func_src2,
3530 						 func_info->func_opr2, &res2);
3531 		if (rc)
3532 			return rc;
3533 	}
3534 
3535 	/* perform the functional opcode operations */
3536 	switch (func_info->func_opc) {
3537 	case BNXT_ULP_FUNC_OPC_EQ:
3538 		if (res1 == res2)
3539 			res = 1;
3540 		break;
3541 	case BNXT_ULP_FUNC_OPC_NE:
3542 		if (res1 != res2)
3543 			res = 1;
3544 		break;
3545 	case BNXT_ULP_FUNC_OPC_GE:
3546 		if (res1 >= res2)
3547 			res = 1;
3548 		break;
3549 	case BNXT_ULP_FUNC_OPC_GT:
3550 		if (res1 > res2)
3551 			res = 1;
3552 		break;
3553 	case BNXT_ULP_FUNC_OPC_LE:
3554 		if (res1 <= res2)
3555 			res = 1;
3556 		break;
3557 	case BNXT_ULP_FUNC_OPC_LT:
3558 		if (res1 < res2)
3559 			res = 1;
3560 		break;
3561 	case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3562 		res = res1;
3563 		break;
3564 	case BNXT_ULP_FUNC_OPC_RSS_CONFIG:
3565 		/* apply the rss config using pmd method */
3566 		return bnxt_rss_config_action_apply(parms);
3567 	case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR:
3568 		rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res);
3569 		if (rc)
3570 			return -EINVAL;
3571 		res = tfp_be_to_cpu_64(res);
3572 		break;
3573 	default:
3574 		BNXT_TF_DBG(ERR, "invalid func code %u\n", func_info->func_opc);
3575 		return -EINVAL;
3576 	}
3577 	if (ulp_regfile_write(parms->regfile, func_info->func_dst_opr,
3578 			      tfp_cpu_to_be_64(res))) {
3579 		BNXT_TF_DBG(ERR, "Failed write the func_opc %u\n",
3580 			    func_info->func_dst_opr);
3581 		return -EINVAL;
3582 	}
3583 
3584 	return rc;
3585 }
3586 
3587 /*
3588  * Processes a list of conditions and returns both a status and result of the
3589  * list.  The status must be checked prior to verifying the result.
3590  *
3591  * returns 0 for success, negative on failure
3592  * returns res = 1 for true, res = 0 for false.
3593  */
3594 static int32_t
3595 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
3596 				 enum bnxt_ulp_cond_list_opc list_opc,
3597 				 struct bnxt_ulp_mapper_cond_info *list,
3598 				 uint32_t num,
3599 				 int32_t *res)
3600 {
3601 	uint32_t i;
3602 	int32_t rc = 0, trc = 0;
3603 
3604 	switch (list_opc) {
3605 	case BNXT_ULP_COND_LIST_OPC_AND:
3606 		/* AND Defaults to true. */
3607 		*res = 1;
3608 		break;
3609 	case BNXT_ULP_COND_LIST_OPC_OR:
3610 		/* OR Defaults to false. */
3611 		*res = 0;
3612 		break;
3613 	case BNXT_ULP_COND_LIST_OPC_TRUE:
3614 		*res = 1;
3615 		return rc;
3616 	case BNXT_ULP_COND_LIST_OPC_FALSE:
3617 		*res = 0;
3618 		return rc;
3619 	default:
3620 		BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
3621 			    list_opc);
3622 		*res = 0;
3623 		return -EINVAL;
3624 	}
3625 
3626 	for (i = 0; i < num; i++) {
3627 		rc = ulp_mapper_cond_opc_process(parms,
3628 						 list[i].cond_opcode,
3629 						 list[i].cond_operand,
3630 						 &trc);
3631 		if (rc)
3632 			return rc;
3633 
3634 		if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
3635 			/* early return if result is ever zero */
3636 			if (!trc) {
3637 				*res = trc;
3638 				return rc;
3639 			}
3640 		} else {
3641 			/* early return if result is ever non-zero */
3642 			if (trc) {
3643 				*res = trc;
3644 				return rc;
3645 			}
3646 		}
3647 	}
3648 
3649 	return rc;
3650 }
3651 
3652 /*
3653  * Processes conflict resolution and returns both a status and result.
3654  * The status must be checked prior to verifying the result.
3655  *
3656  * returns 0 for success, negative on failure
3657  * returns res = 1 for true, res = 0 for false.
3658  */
3659 static int32_t
3660 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
3661 				       struct bnxt_ulp_mapper_tbl_info *tbl,
3662 				       int32_t *res)
3663 {
3664 	int32_t rc = 0;
3665 	uint64_t regval;
3666 	uint64_t comp_sig;
3667 
3668 	*res = 0;
3669 	switch (tbl->accept_opcode) {
3670 	case BNXT_ULP_ACCEPT_OPC_ALWAYS:
3671 		*res = 1;
3672 		break;
3673 	case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
3674 		/* perform the signature validation*/
3675 		if (tbl->resource_func ==
3676 		    BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
3677 			/* Perform the check that generic table is hit or not */
3678 			if (!ulp_regfile_read(parms->regfile,
3679 					      BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3680 					      &regval)) {
3681 				BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3682 					    BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3683 				return -EINVAL;
3684 			}
3685 			if (regval) {
3686 				/* not a hit so no need to check flow sign*/
3687 				*res = 1;
3688 				return rc;
3689 			}
3690 		}
3691 		/* compare the new flow signature against stored one */
3692 		if (!ulp_regfile_read(parms->regfile,
3693 				      BNXT_ULP_RF_IDX_FLOW_SIG_ID,
3694 				      &regval)) {
3695 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3696 				    BNXT_ULP_RF_IDX_FLOW_SIG_ID);
3697 			return -EINVAL;
3698 		}
3699 		comp_sig = ULP_COMP_FLD_IDX_RD(parms,
3700 					       BNXT_ULP_CF_IDX_FLOW_SIG_ID);
3701 		regval = tfp_be_to_cpu_64(regval);
3702 		if (comp_sig == regval)
3703 			*res = 1;
3704 		else
3705 			BNXT_TF_DBG(ERR, "failed signature match 0x%016"
3706 				    PRIX64 ":%x\n", comp_sig, (uint32_t)regval);
3707 		break;
3708 	default:
3709 		BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
3710 			    tbl->accept_opcode);
3711 		return -EINVAL;
3712 	}
3713 	return rc;
3714 }
3715 
3716 static int32_t
3717 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
3718 {
3719 	struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
3720 	enum bnxt_ulp_cond_list_opc cond_opc;
3721 	struct bnxt_ulp_mapper_tbl_info *tbls;
3722 	struct bnxt_ulp_mapper_tbl_info *tbl;
3723 	uint32_t num_tbls, tbl_idx, num_cond_tbls;
3724 	int32_t rc = -EINVAL, cond_rc = 0;
3725 	int32_t cond_goto = 1;
3726 
3727 	cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
3728 						    &num_cond_tbls,
3729 						    &cond_opc);
3730 	/*
3731 	 * Process the reject list if exists, otherwise assume that the
3732 	 * template is allowed.
3733 	 */
3734 	if (cond_tbls && num_cond_tbls) {
3735 		rc = ulp_mapper_cond_opc_list_process(parms,
3736 						      cond_opc,
3737 						      cond_tbls,
3738 						      num_cond_tbls,
3739 						      &cond_rc);
3740 		if (rc)
3741 			return rc;
3742 
3743 		/* Reject the template if True */
3744 		if (cond_rc) {
3745 			BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
3746 				    ulp_mapper_tmpl_name_str(parms->tmpl_type),
3747 				    tid);
3748 			return -EINVAL;
3749 		}
3750 	}
3751 
3752 	tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
3753 	if (!tbls || !num_tbls) {
3754 		BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
3755 			    ulp_mapper_tmpl_name_str(parms->tmpl_type),
3756 			    parms->dev_id, tid);
3757 		return -EINVAL;
3758 	}
3759 
3760 	for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
3761 		tbl = &tbls[tbl_idx];
3762 		cond_goto = tbl->execute_info.cond_true_goto;
3763 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
3764 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
3765 		ulp_mapper_table_dump(tbl, tbl_idx);
3766 #endif
3767 #endif
3768 		/* Process the conditional func code opcodes */
3769 		if (ulp_mapper_func_info_process(parms, tbl)) {
3770 			BNXT_TF_DBG(ERR, "Failed to process cond update\n");
3771 			rc = -EINVAL;
3772 			goto error;
3773 		}
3774 
3775 		cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
3776 							    &num_cond_tbls,
3777 							    &cond_opc);
3778 		rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
3779 						      cond_tbls, num_cond_tbls,
3780 						      &cond_rc);
3781 		if (rc) {
3782 			BNXT_TF_DBG(ERR, "Failed to proc cond opc list (%d)\n",
3783 				    rc);
3784 			goto error;
3785 		}
3786 		/* Skip the table if False */
3787 		if (!cond_rc) {
3788 			cond_goto = tbl->execute_info.cond_false_goto;
3789 			goto next_iteration;
3790 		}
3791 
3792 		switch (tbl->resource_func) {
3793 		case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3794 			rc = ulp_mapper_tcam_tbl_process(parms, tbl);
3795 			break;
3796 		case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3797 			rc = ulp_mapper_em_tbl_process(parms, tbl);
3798 			break;
3799 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3800 			rc = ulp_mapper_index_tbl_process(parms, tbl);
3801 			break;
3802 		case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
3803 			rc = ulp_mapper_if_tbl_process(parms, tbl);
3804 			break;
3805 		case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3806 			rc = ulp_mapper_gen_tbl_process(parms, tbl);
3807 			break;
3808 		case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3809 			rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3810 			break;
3811 		case BNXT_ULP_RESOURCE_FUNC_INVALID:
3812 			rc = 0;
3813 			break;
3814 		default:
3815 			BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3816 				    tbl->resource_func);
3817 			rc = -EINVAL;
3818 			goto error;
3819 		}
3820 
3821 		if (rc) {
3822 			BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3823 				    tbl->resource_func);
3824 			goto error;
3825 		}
3826 
3827 		/* perform the post table process */
3828 		rc  = ulp_mapper_conflict_resolution_process(parms, tbl,
3829 							     &cond_rc);
3830 		if (rc || !cond_rc) {
3831 			BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3832 			rc = -EINVAL;
3833 			goto error;
3834 		}
3835 next_iteration:
3836 		if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) {
3837 			BNXT_TF_DBG(ERR, "reject the flow\n");
3838 			rc = -EINVAL;
3839 			goto error;
3840 		} else if (cond_goto & BNXT_ULP_COND_GOTO_RF) {
3841 			uint32_t rf_idx;
3842 			uint64_t regval;
3843 
3844 			/* least significant 16 bits from reg_file index */
3845 			rf_idx = (uint32_t)(cond_goto & 0xFFFF);
3846 			if (!ulp_regfile_read(parms->regfile, rf_idx,
3847 					      &regval)) {
3848 				BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3849 					    rf_idx);
3850 				rc = -EINVAL;
3851 				goto error;
3852 			}
3853 			cond_goto = (int32_t)regval;
3854 		}
3855 
3856 		if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3857 			BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3858 				    cond_goto);
3859 			goto error;
3860 		}
3861 		tbl_idx += cond_goto;
3862 	}
3863 
3864 	return rc;
3865 error:
3866 	BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3867 		    ulp_mapper_tmpl_name_str(parms->tmpl_type),
3868 		    parms->dev_id, tid);
3869 	return rc;
3870 }
3871 
3872 static int32_t
3873 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3874 			 uint32_t fid,
3875 			 struct ulp_flow_db_res_params *res)
3876 {
3877 	struct tf *tfp;
3878 	int32_t	rc = 0;
3879 
3880 	if (!res || !ulp) {
3881 		BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3882 		return -EINVAL;
3883 	}
3884 	if (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION)
3885 		tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_YES);
3886 	else
3887 		tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_NO);
3888 	if (!tfp) {
3889 		BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3890 		return -EINVAL;
3891 	}
3892 
3893 	switch (res->resource_func) {
3894 	case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3895 		rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3896 		break;
3897 	case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3898 		rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3899 		break;
3900 	case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3901 		rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3902 		break;
3903 	case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3904 		rc = ulp_mapper_ident_free(ulp, tfp, res);
3905 		break;
3906 	case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3907 		rc = ulp_mapper_mark_free(ulp, res);
3908 		break;
3909 	case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3910 		rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3911 		break;
3912 	case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3913 		rc = ulp_mapper_child_flow_free(ulp, fid, res);
3914 		break;
3915 	case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3916 		rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3917 		break;
3918 	default:
3919 		break;
3920 	}
3921 
3922 	return rc;
3923 }
3924 
3925 int32_t
3926 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3927 			  enum bnxt_ulp_fdb_type flow_type,
3928 			  uint32_t fid)
3929 {
3930 	struct ulp_flow_db_res_params res_parms = { 0 };
3931 	int32_t rc, trc;
3932 
3933 	if (!ulp_ctx) {
3934 		BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3935 		return -EINVAL;
3936 	}
3937 
3938 	/*
3939 	 * Set the critical resource on the first resource del, then iterate
3940 	 * while status is good
3941 	 */
3942 	res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3943 
3944 	rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3945 
3946 	if (rc) {
3947 		/*
3948 		 * This is unexpected on the first call to resource del.
3949 		 * It likely means that the flow did not exist in the flow db.
3950 		 */
3951 		BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3952 			    flow_type, fid, rc);
3953 		return rc;
3954 	}
3955 
3956 	while (!rc) {
3957 		trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3958 		if (trc)
3959 			/*
3960 			 * On fail, we still need to attempt to free the
3961 			 * remaining resources.  Don't return
3962 			 */
3963 			BNXT_TF_DBG(ERR,
3964 				    "Flow[%d][0x%x] Res[%d][0x%016" PRIX64
3965 				    "] failed rc=%d.\n",
3966 				    flow_type, fid, res_parms.resource_func,
3967 				    res_parms.resource_hndl, trc);
3968 
3969 		/* All subsequent call require the non-critical_resource */
3970 		res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3971 
3972 		rc = ulp_flow_db_resource_del(ulp_ctx,
3973 					      flow_type,
3974 					      fid,
3975 					      &res_parms);
3976 	}
3977 
3978 	/* Free the Flow ID since we've removed all resources */
3979 	rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3980 
3981 	return rc;
3982 }
3983 
3984 static void
3985 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3986 				    struct bnxt_ulp_mapper_data *mapper_data)
3987 {
3988 	struct bnxt_ulp_mapper_glb_resource_entry *ent;
3989 	struct ulp_flow_db_res_params res;
3990 	uint32_t dir, idx;
3991 
3992 	/* Iterate the global resources and process each one */
3993 	for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3994 		for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) {
3995 			ent = &mapper_data->glb_res_tbl[dir][idx];
3996 			if (ent->resource_func ==
3997 			    BNXT_ULP_RESOURCE_FUNC_INVALID ||
3998 			    ent->shared)
3999 				continue;
4000 			memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
4001 			res.resource_func = ent->resource_func;
4002 			res.direction = dir;
4003 			res.resource_type = ent->resource_type;
4004 			/*convert it from BE to cpu */
4005 			res.resource_hndl =
4006 				tfp_be_to_cpu_64(ent->resource_hndl);
4007 			ulp_mapper_resource_free(ulp_ctx, 0, &res);
4008 		}
4009 	}
4010 }
4011 
4012 int32_t
4013 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
4014 			enum bnxt_ulp_fdb_type flow_type,
4015 			uint32_t fid)
4016 {
4017 	int32_t rc;
4018 
4019 	if (!ulp_ctx) {
4020 		BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
4021 		return -EINVAL;
4022 	}
4023 
4024 	rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
4025 	return rc;
4026 }
4027 
4028 /* Function to handle the mapping of the Flow to be compatible
4029  * with the underlying hardware.
4030  */
4031 int32_t
4032 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
4033 		       struct bnxt_ulp_mapper_create_parms *cparms)
4034 {
4035 	struct bnxt_ulp_mapper_parms parms;
4036 	struct ulp_regfile regfile;
4037 	int32_t	 rc = 0, trc;
4038 
4039 	if (!ulp_ctx || !cparms)
4040 		return -EINVAL;
4041 
4042 	/* Initialize the parms structure */
4043 	memset(&parms, 0, sizeof(parms));
4044 	parms.act_prop = cparms->act_prop;
4045 	parms.act_bitmap = cparms->act;
4046 	parms.hdr_bitmap = cparms->hdr_bitmap;
4047 	parms.enc_hdr_bitmap = cparms->enc_hdr_bitmap;
4048 	parms.regfile = &regfile;
4049 	parms.hdr_field = cparms->hdr_field;
4050 	parms.enc_field = cparms->enc_field;
4051 	parms.fld_bitmap = cparms->fld_bitmap;
4052 	parms.comp_fld = cparms->comp_fld;
4053 	parms.ulp_ctx = ulp_ctx;
4054 	parms.act_tid = cparms->act_tid;
4055 	parms.class_tid = cparms->class_tid;
4056 	parms.flow_type = cparms->flow_type;
4057 	parms.parent_flow = cparms->parent_flow;
4058 	parms.child_flow = cparms->child_flow;
4059 	parms.fid = cparms->flow_id;
4060 	parms.tun_idx = cparms->tun_idx;
4061 	parms.app_priority = cparms->app_priority;
4062 	parms.flow_pattern_id = cparms->flow_pattern_id;
4063 	parms.act_pattern_id = cparms->act_pattern_id;
4064 	parms.app_id = cparms->app_id;
4065 	parms.port_id = cparms->port_id;
4066 
4067 	/* Get the device id from the ulp context */
4068 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
4069 		BNXT_TF_DBG(ERR, "Invalid ulp context\n");
4070 		return -EINVAL;
4071 	}
4072 
4073 	/* Get the device params, it will be used in later processing */
4074 	parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
4075 	if (!parms.device_params) {
4076 		BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
4077 			    parms.dev_id);
4078 		return -EINVAL;
4079 	}
4080 
4081 	/*
4082 	 * Get the mapper data for dynamic mapper data such as default
4083 	 * ids.
4084 	 */
4085 	parms.mapper_data = (struct bnxt_ulp_mapper_data *)
4086 		bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
4087 	if (!parms.mapper_data) {
4088 		BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
4089 		return -EINVAL;
4090 	}
4091 
4092 	/* initialize the registry file for further processing */
4093 	if (!ulp_regfile_init(parms.regfile)) {
4094 		BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
4095 		return -EINVAL;
4096 	}
4097 
4098 	/* Process the action template list from the selected action table*/
4099 	if (parms.act_tid) {
4100 		parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
4101 		/* Process the action template tables */
4102 		rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
4103 		if (rc)
4104 			goto flow_error;
4105 		cparms->shared_hndl = parms.shared_hndl;
4106 	}
4107 
4108 	if (parms.class_tid) {
4109 		parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
4110 
4111 		/* Process the class template tables.*/
4112 		rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
4113 		if (rc)
4114 			goto flow_error;
4115 	}
4116 
4117 	/* setup the parent-child details */
4118 	if (parms.parent_flow) {
4119 		/* create a parent flow details */
4120 		rc = ulp_flow_db_parent_flow_create(&parms);
4121 		if (rc)
4122 			goto flow_error;
4123 	} else if (parms.child_flow) {
4124 		/* create a child flow details */
4125 		rc = ulp_flow_db_child_flow_create(&parms);
4126 		if (rc)
4127 			goto flow_error;
4128 	}
4129 
4130 	return rc;
4131 
4132 flow_error:
4133 	/* Free all resources that were allocated during flow creation */
4134 	trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
4135 				      parms.fid);
4136 	if (trc)
4137 		BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
4138 
4139 	return rc;
4140 }
4141 
4142 int32_t
4143 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
4144 {
4145 	struct bnxt_ulp_mapper_data *data;
4146 	struct tf *tfp;
4147 	int32_t rc;
4148 
4149 	if (!ulp_ctx)
4150 		return -EINVAL;
4151 
4152 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
4153 	if (!tfp)
4154 		return -EINVAL;
4155 
4156 	data = rte_zmalloc("ulp_mapper_data",
4157 			   sizeof(struct bnxt_ulp_mapper_data), 0);
4158 	if (!data) {
4159 		BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
4160 		return -ENOMEM;
4161 	}
4162 
4163 	if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
4164 		BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
4165 		/* Don't call deinit since the prof_func wasn't allocated. */
4166 		rte_free(data);
4167 		return -ENOMEM;
4168 	}
4169 
4170 	/* Allocate the global resource ids */
4171 	rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
4172 	if (rc) {
4173 		BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
4174 		goto error;
4175 	}
4176 
4177 	/*
4178 	 * Only initialize the app global resources if a shared session was
4179 	 * created.
4180 	 */
4181 	if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) {
4182 		rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data);
4183 		if (rc) {
4184 			BNXT_TF_DBG(ERR, "Failed to init app glb resources\n");
4185 			goto error;
4186 		}
4187 	}
4188 
4189 	/* Allocate the generic table list */
4190 	rc = ulp_mapper_generic_tbl_list_init(data);
4191 	if (rc) {
4192 		BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
4193 		goto error;
4194 	}
4195 
4196 	return 0;
4197 error:
4198 	/* Ignore the return code in favor of returning the original error. */
4199 	ulp_mapper_deinit(ulp_ctx);
4200 	return rc;
4201 }
4202 
4203 void
4204 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
4205 {
4206 	struct bnxt_ulp_mapper_data *data;
4207 	struct tf *tfp;
4208 
4209 	if (!ulp_ctx) {
4210 		BNXT_TF_DBG(ERR,
4211 			    "Failed to acquire ulp context, so data may not be released.\n");
4212 		return;
4213 	}
4214 
4215 	data = (struct bnxt_ulp_mapper_data *)
4216 		bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
4217 	if (!data) {
4218 		/* Go ahead and return since there is no allocated data. */
4219 		BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
4220 		return;
4221 	}
4222 
4223 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
4224 	if (!tfp) {
4225 		BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
4226 		/* Free the mapper data regardless of errors. */
4227 		goto free_mapper_data;
4228 	}
4229 
4230 	/* Free the global resource info table entries */
4231 	ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
4232 
4233 free_mapper_data:
4234 	/* Free the generic table */
4235 	(void)ulp_mapper_generic_tbl_list_deinit(data);
4236 
4237 	rte_free(data);
4238 	/* Reset the data pointer within the ulp_ctx. */
4239 	bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
4240 }
4241