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