xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_mapper.c (revision 0f27fe09)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2020 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 
21 static struct bnxt_ulp_glb_resource_info *
22 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
23 {
24 	if (!num_entries)
25 		return NULL;
26 	*num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
27 	return ulp_glb_resource_tbl;
28 }
29 
30 /*
31  * Read the global resource from the mapper global resource list
32  *
33  * The regval is always returned in big-endian.
34  *
35  * returns 0 on success
36  */
37 static int32_t
38 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
39 			     enum tf_dir dir,
40 			     uint16_t idx,
41 			     uint64_t *regval)
42 {
43 	if (!mapper_data || !regval ||
44 	    dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
45 		return -EINVAL;
46 
47 	*regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
48 	return 0;
49 }
50 
51 /*
52  * Write a global resource to the mapper global resource list
53  *
54  * The regval value must be in big-endian.
55  *
56  * return 0 on success.
57  */
58 static int32_t
59 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
60 			      struct bnxt_ulp_glb_resource_info *res,
61 			      uint64_t regval)
62 {
63 	struct bnxt_ulp_mapper_glb_resource_entry *ent;
64 
65 	/* validate the arguments */
66 	if (!data || res->direction >= TF_DIR_MAX ||
67 	    res->glb_regfile_index >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
68 		return -EINVAL;
69 
70 	/* write to the mapper data */
71 	ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
72 	ent->resource_func = res->resource_func;
73 	ent->resource_type = res->resource_type;
74 	ent->resource_hndl = regval;
75 	return 0;
76 }
77 
78 /*
79  * Internal function to allocate identity resource and store it in mapper data.
80  *
81  * returns 0 on success
82  */
83 static int32_t
84 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
85 				   struct bnxt_ulp_mapper_data *mapper_data,
86 				   struct bnxt_ulp_glb_resource_info *glb_res)
87 {
88 	struct tf_alloc_identifier_parms iparms = { 0 };
89 	struct tf_free_identifier_parms fparms;
90 	uint64_t regval;
91 	struct tf *tfp;
92 	int32_t rc = 0;
93 
94 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
95 	if (!tfp)
96 		return -EINVAL;
97 
98 	iparms.ident_type = glb_res->resource_type;
99 	iparms.dir = glb_res->direction;
100 
101 	/* Allocate the Identifier using tf api */
102 	rc = tf_alloc_identifier(tfp, &iparms);
103 	if (rc) {
104 		BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
105 			    (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
106 			    iparms.ident_type);
107 		return rc;
108 	}
109 
110 	/* entries are stored as big-endian format */
111 	regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
112 	/* write to the mapper global resource */
113 	rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
114 	if (rc) {
115 		BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
116 		/* Free the identifier when update failed */
117 		fparms.dir = iparms.dir;
118 		fparms.ident_type = iparms.ident_type;
119 		fparms.id = iparms.id;
120 		tf_free_identifier(tfp, &fparms);
121 		return rc;
122 	}
123 	return rc;
124 }
125 
126 /*
127  * Internal function to allocate index tbl resource and store it in mapper data.
128  *
129  * returns 0 on success
130  */
131 static int32_t
132 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
133 				    struct bnxt_ulp_mapper_data *mapper_data,
134 				    struct bnxt_ulp_glb_resource_info *glb_res)
135 {
136 	struct tf_alloc_tbl_entry_parms	aparms = { 0 };
137 	struct tf_free_tbl_entry_parms	free_parms = { 0 };
138 	uint64_t regval;
139 	struct tf *tfp;
140 	uint32_t tbl_scope_id;
141 	int32_t rc = 0;
142 
143 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
144 	if (!tfp)
145 		return -EINVAL;
146 
147 	/* Get the scope id */
148 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
149 	if (rc) {
150 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
151 		return rc;
152 	}
153 
154 	aparms.type = glb_res->resource_type;
155 	aparms.dir = glb_res->direction;
156 	aparms.search_enable = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO;
157 	aparms.tbl_scope_id = tbl_scope_id;
158 
159 	/* Allocate the index tbl using tf api */
160 	rc = tf_alloc_tbl_entry(tfp, &aparms);
161 	if (rc) {
162 		BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
163 			    (aparms.dir == TF_DIR_RX) ? "RX" : "TX",
164 			    aparms.type);
165 		return rc;
166 	}
167 
168 	/* entries are stored as big-endian format */
169 	regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
170 	/* write to the mapper global resource */
171 	rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
172 	if (rc) {
173 		BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
174 		/* Free the identifier when update failed */
175 		free_parms.dir = aparms.dir;
176 		free_parms.type = aparms.type;
177 		free_parms.idx = aparms.idx;
178 		tf_free_tbl_entry(tfp, &free_parms);
179 		return rc;
180 	}
181 	return rc;
182 }
183 
184 /* Retrieve the cache initialization parameters for the tbl_idx */
185 static struct bnxt_ulp_cache_tbl_params *
186 ulp_mapper_cache_tbl_params_get(uint32_t tbl_idx)
187 {
188 	if (tbl_idx >= BNXT_ULP_CACHE_TBL_MAX_SZ)
189 		return NULL;
190 
191 	return &ulp_cache_tbl_params[tbl_idx];
192 }
193 
194 /* Retrieve the global template table */
195 static uint32_t *
196 ulp_mapper_glb_template_table_get(uint32_t *num_entries)
197 {
198 	if (!num_entries)
199 		return NULL;
200 	*num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ;
201 	return ulp_glb_template_tbl;
202 }
203 
204 /*
205  * Get the size of the action property for a given index.
206  *
207  * idx [in] The index for the action property
208  *
209  * returns the size of the action property.
210  */
211 static uint32_t
212 ulp_mapper_act_prop_size_get(uint32_t idx)
213 {
214 	if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
215 		return 0;
216 	return ulp_act_prop_map_table[idx];
217 }
218 
219 /*
220  * Get a list of classifier tables that implement the flow
221  * Gets a device dependent list of tables that implement the class template id
222  *
223  * mparms [in] The mappers parms with data related to the flow.
224  *
225  * tid [in] The template id that matches the flow
226  *
227  * num_tbls [out] The number of classifier tables in the returned array
228  *
229  * returns An array of classifier tables to implement the flow, or NULL on
230  * error
231  */
232 static struct bnxt_ulp_mapper_tbl_info *
233 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
234 			uint32_t tid,
235 			uint32_t *num_tbls)
236 {
237 	uint32_t idx;
238 	const struct ulp_template_device_tbls *dev_tbls;
239 
240 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
241 
242 	idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
243 	*num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
244 
245 	return &dev_tbls->tbl_list[idx];
246 }
247 
248 /*
249  * Get the list of key fields that implement the flow.
250  *
251  * mparms [in] The mapper parms with information about the flow
252  *
253  * tbl [in] A single table instance to get the key fields from
254  *
255  * num_flds [out] The number of key fields in the returned array
256  *
257  * Returns array of Key fields, or NULL on error.
258  */
259 static struct bnxt_ulp_mapper_key_field_info *
260 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
261 			  struct bnxt_ulp_mapper_tbl_info *tbl,
262 			  uint32_t *num_flds)
263 {
264 	uint32_t idx;
265 	const struct ulp_template_device_tbls *dev_tbls;
266 
267 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
268 	if (!dev_tbls->key_field_list) {
269 		*num_flds = 0;
270 		return NULL;
271 	}
272 
273 	idx		= tbl->key_start_idx;
274 	*num_flds	= tbl->key_num_fields;
275 
276 	return &dev_tbls->key_field_list[idx];
277 }
278 
279 /*
280  * Get the list of data fields that implement the flow.
281  *
282  * mparms [in] The mapper parms with information about the flow
283  *
284  * tbl [in] A single table instance to get the data fields from
285  *
286  * num_flds [out] The number of data fields in the returned array.
287  *
288  * num_encap_flds [out] The number of encap fields in the returned array.
289  *
290  * Returns array of data fields, or NULL on error.
291  */
292 static struct bnxt_ulp_mapper_result_field_info *
293 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
294 			     struct bnxt_ulp_mapper_tbl_info *tbl,
295 			     uint32_t *num_flds,
296 			     uint32_t *num_encap_flds)
297 {
298 	uint32_t idx;
299 	const struct ulp_template_device_tbls *dev_tbls;
300 
301 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
302 	if (!dev_tbls->result_field_list) {
303 		*num_flds = 0;
304 		*num_encap_flds = 0;
305 		return NULL;
306 	}
307 
308 	idx		= tbl->result_start_idx;
309 	*num_flds	= tbl->result_num_fields;
310 	*num_encap_flds = tbl->encap_num_fields;
311 
312 	return &dev_tbls->result_field_list[idx];
313 }
314 
315 /*
316  * Get the list of ident fields that implement the flow
317  *
318  * tbl [in] A single table instance to get the ident fields from
319  *
320  * num_flds [out] The number of ident fields in the returned array
321  *
322  * returns array of ident fields, or NULL on error
323  */
324 static struct bnxt_ulp_mapper_ident_info *
325 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
326 			    struct bnxt_ulp_mapper_tbl_info *tbl,
327 			    uint32_t *num_flds)
328 {
329 	uint32_t idx;
330 	const struct ulp_template_device_tbls *dev_tbls;
331 
332 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
333 	if (!dev_tbls->ident_list) {
334 		*num_flds = 0;
335 		return NULL;
336 	}
337 
338 	idx = tbl->ident_start_idx;
339 	*num_flds = tbl->ident_nums;
340 
341 	return &dev_tbls->ident_list[idx];
342 }
343 
344 static struct bnxt_ulp_mapper_cache_entry *
345 ulp_mapper_cache_entry_get(struct bnxt_ulp_context *ulp,
346 			   uint32_t id,
347 			   uint16_t key)
348 {
349 	struct bnxt_ulp_mapper_data *mapper_data;
350 
351 	mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp);
352 	if (!mapper_data || id >= BNXT_ULP_CACHE_TBL_MAX_SZ ||
353 	    !mapper_data->cache_tbl[id]) {
354 		BNXT_TF_DBG(ERR, "Unable to acquire the cache tbl (%d)\n", id);
355 		return NULL;
356 	}
357 
358 	return &mapper_data->cache_tbl[id][key];
359 }
360 
361 /*
362  * Concatenates the tbl_type and tbl_id into a 32bit value for storing in the
363  * resource_type.  This is done to conserve memory since both the tbl_type and
364  * tbl_id are 16bit.
365  */
366 static inline void
367 ulp_mapper_cache_res_type_set(struct ulp_flow_db_res_params *res,
368 			      uint16_t tbl_type,
369 			      uint16_t tbl_id)
370 {
371 	res->resource_type = tbl_type;
372 	res->resource_sub_type = tbl_id;
373 }
374 
375 /* Extracts the tbl_type and tbl_id from the 32bit resource type. */
376 static inline void
377 ulp_mapper_cache_res_type_get(struct ulp_flow_db_res_params *res,
378 			      uint16_t *tbl_type,
379 			      uint16_t *tbl_id)
380 {
381 	*tbl_type = res->resource_type;
382 	*tbl_id = res->resource_sub_type;
383 }
384 
385 static int32_t
386 ulp_mapper_cache_entry_free(struct bnxt_ulp_context *ulp,
387 			    struct tf *tfp,
388 			    struct ulp_flow_db_res_params *res)
389 {
390 	struct bnxt_ulp_mapper_cache_entry *cache_entry;
391 	struct tf_free_identifier_parms ident_parms;
392 	struct tf_free_tcam_entry_parms tcam_parms;
393 	uint16_t table_id, table_type;
394 	int32_t rc, trc, i;
395 
396 	/*
397 	 * The table id, used for cache, and table_type, used for tcam, are
398 	 * both encoded within the resource.  We must first extract them to
399 	 * formulate the args for tf calls.
400 	 */
401 	ulp_mapper_cache_res_type_get(res, &table_type, &table_id);
402 	cache_entry = ulp_mapper_cache_entry_get(ulp, table_id,
403 						 (uint16_t)res->resource_hndl);
404 	if (!cache_entry || !cache_entry->ref_count) {
405 		BNXT_TF_DBG(ERR, "Cache entry (%d:%d) not valid on free.\n",
406 			    table_id, (uint16_t)res->resource_hndl);
407 		return -EINVAL;
408 	}
409 
410 	/*
411 	 * See if we need to delete the entry.  The tcam and identifiers are all
412 	 * tracked by the cached entries reference count.  All are deleted when
413 	 * the reference count hit zero.
414 	 */
415 	cache_entry->ref_count--;
416 	if (cache_entry->ref_count)
417 		return 0;
418 
419 	/*
420 	 * Need to delete the tcam entry and the allocated identifiers.
421 	 * In the event of a failure, need to try to delete the remaining
422 	 * resources before returning error.
423 	 */
424 	tcam_parms.dir = res->direction;
425 	tcam_parms.tcam_tbl_type = table_type;
426 	tcam_parms.idx = cache_entry->tcam_idx;
427 	rc = tf_free_tcam_entry(tfp, &tcam_parms);
428 	if (rc)
429 		BNXT_TF_DBG(ERR, "Failed to free tcam [%d][%s][0x%04x] rc=%d\n",
430 			    table_type,
431 			    (res->direction == TF_DIR_RX) ? "RX" : "TX",
432 			    tcam_parms.idx, rc);
433 
434 	/*
435 	 * Free the identifiers associated with the tcam entry.  Entries with
436 	 * negative one are considered uninitialized.
437 	 */
438 	for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) {
439 		if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
440 			continue;
441 
442 		ident_parms.dir = res->direction;
443 		ident_parms.ident_type = cache_entry->ident_types[i];
444 		ident_parms.id = cache_entry->idents[i];
445 		trc = tf_free_identifier(tfp, &ident_parms);
446 		if (trc) {
447 			BNXT_TF_DBG(ERR, "Failed to free identifier "
448 				    "[%d][%s][0x%04x] rc=%d\n",
449 				    ident_parms.ident_type,
450 				    (res->direction == TF_DIR_RX) ? "RX" : "TX",
451 				    ident_parms.id, trc);
452 			rc = trc;
453 		}
454 	}
455 
456 	return rc;
457 }
458 
459 static inline int32_t
460 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp  __rte_unused,
461 			   struct tf *tfp,
462 			   struct ulp_flow_db_res_params *res)
463 {
464 	struct tf_free_tcam_entry_parms fparms = {
465 		.dir		= res->direction,
466 		.tcam_tbl_type	= res->resource_type,
467 		.idx		= (uint16_t)res->resource_hndl
468 	};
469 
470 	return tf_free_tcam_entry(tfp, &fparms);
471 }
472 
473 static inline int32_t
474 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
475 			    struct tf *tfp,
476 			    struct ulp_flow_db_res_params *res)
477 {
478 	struct tf_free_tbl_entry_parms fparms = {
479 		.dir	= res->direction,
480 		.type	= res->resource_type,
481 		.idx	= (uint32_t)res->resource_hndl
482 	};
483 
484 	/*
485 	 * Just get the table scope, it will be ignored if not necessary
486 	 * by the tf_free_tbl_entry
487 	 */
488 	(void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
489 
490 	return tf_free_tbl_entry(tfp, &fparms);
491 }
492 
493 static inline int32_t
494 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
495 			 struct tf *tfp,
496 			 struct ulp_flow_db_res_params *res)
497 {
498 	struct tf_delete_em_entry_parms fparms = { 0 };
499 	int32_t rc;
500 
501 	fparms.dir		= res->direction;
502 	if (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE)
503 		fparms.mem = TF_MEM_EXTERNAL;
504 	else
505 		fparms.mem = TF_MEM_INTERNAL;
506 	fparms.flow_handle	= res->resource_hndl;
507 
508 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
509 	if (rc) {
510 		BNXT_TF_DBG(ERR, "Failed to get table scope\n");
511 		return -EINVAL;
512 	}
513 
514 	return tf_delete_em_entry(tfp, &fparms);
515 }
516 
517 static inline int32_t
518 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
519 		      struct tf *tfp,
520 		      struct ulp_flow_db_res_params *res)
521 {
522 	struct tf_free_identifier_parms fparms = {
523 		.dir		= res->direction,
524 		.ident_type	= res->resource_type,
525 		.id		= (uint16_t)res->resource_hndl
526 	};
527 
528 	return tf_free_identifier(tfp, &fparms);
529 }
530 
531 static inline int32_t
532 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
533 		     struct ulp_flow_db_res_params *res)
534 {
535 	return ulp_mark_db_mark_del(ulp,
536 				    res->resource_type,
537 				    res->resource_hndl);
538 }
539 
540 
541 static inline int32_t
542 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
543 			    uint32_t parent_fid,
544 			    struct ulp_flow_db_res_params *res)
545 {
546 	uint32_t idx, child_fid = 0, parent_idx;
547 	struct bnxt_ulp_flow_db *flow_db;
548 
549 	parent_idx = (uint32_t)res->resource_hndl;
550 
551 	/* check the validity of the parent fid */
552 	if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
553 	    idx != parent_idx) {
554 		BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
555 		return -EINVAL;
556 	}
557 
558 	/* Clear all the child flows parent index */
559 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
560 	while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
561 							     &child_fid)) {
562 		/* update the child flows resource handle */
563 		if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
564 						 child_fid)) {
565 			BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
566 				    child_fid);
567 			return -EINVAL;
568 		}
569 	}
570 
571 	/* free the parent entry in the parent table flow */
572 	if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
573 		BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
574 		return -EINVAL;
575 	}
576 	return 0;
577 }
578 
579 static inline int32_t
580 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
581 			   uint32_t child_fid,
582 			   struct ulp_flow_db_res_params *res)
583 {
584 	uint32_t parent_fid;
585 
586 	parent_fid = (uint32_t)res->resource_hndl;
587 	if (!parent_fid)
588 		return 0; /* Already freed - orphan child*/
589 
590 	/* reset the child flow bitset*/
591 	if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
592 		BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
593 			    parent_fid, child_fid);
594 		return -EINVAL;
595 	}
596 	return 0;
597 }
598 
599 /*
600  * Process the identifier instruction and either store it in the flow database
601  * or return it in the val (if not NULL) on success.  If val is NULL, the
602  * identifier is to be stored in the flow database.
603  */
604 static int32_t
605 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
606 			 struct bnxt_ulp_mapper_tbl_info *tbl,
607 			 struct bnxt_ulp_mapper_ident_info *ident,
608 			 uint16_t *val)
609 {
610 	struct ulp_flow_db_res_params	fid_parms;
611 	uint64_t id = 0;
612 	int32_t idx;
613 	struct tf_alloc_identifier_parms iparms = { 0 };
614 	struct tf_free_identifier_parms free_parms = { 0 };
615 	struct tf *tfp;
616 	int rc;
617 
618 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
619 	if (!tfp) {
620 		BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
621 		return -EINVAL;
622 	}
623 
624 	idx = ident->regfile_idx;
625 
626 	iparms.ident_type = ident->ident_type;
627 	iparms.dir = tbl->direction;
628 
629 	rc = tf_alloc_identifier(tfp, &iparms);
630 	if (rc) {
631 		BNXT_TF_DBG(ERR, "Alloc ident %s:%d failed.\n",
632 			    (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
633 			    iparms.ident_type);
634 		return rc;
635 	}
636 
637 	id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
638 	if (!ulp_regfile_write(parms->regfile, idx, id)) {
639 		BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
640 		rc = -EINVAL;
641 		/* Need to free the identifier, so goto error */
642 		goto error;
643 	}
644 
645 	/* Link the resource to the flow in the flow db */
646 	if (!val) {
647 		memset(&fid_parms, 0, sizeof(fid_parms));
648 		fid_parms.direction		= tbl->direction;
649 		fid_parms.resource_func	= ident->resource_func;
650 		fid_parms.resource_type	= ident->ident_type;
651 		fid_parms.resource_hndl	= iparms.id;
652 		fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
653 
654 		rc = ulp_flow_db_resource_add(parms->ulp_ctx,
655 					      parms->flow_type,
656 					      parms->fid,
657 					      &fid_parms);
658 		if (rc) {
659 			BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
660 				    rc);
661 			/* Need to free the identifier, so goto error */
662 			goto error;
663 		}
664 	} else {
665 		*val = iparms.id;
666 	}
667 
668 	return 0;
669 
670 error:
671 	/* Need to free the identifier */
672 	free_parms.dir		= tbl->direction;
673 	free_parms.ident_type	= ident->ident_type;
674 	free_parms.id		= iparms.id;
675 
676 	(void)tf_free_identifier(tfp, &free_parms);
677 
678 	BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
679 		    ident->description,
680 		    (tbl->direction == TF_DIR_RX) ? "RX" : "TX");
681 	return rc;
682 }
683 
684 /*
685  * Process the identifier instruction and extract it from result blob.
686  * Increment the identifier reference count and store it in the flow database.
687  */
688 static int32_t
689 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
690 			 struct bnxt_ulp_mapper_tbl_info *tbl,
691 			 struct bnxt_ulp_mapper_ident_info *ident,
692 			 struct ulp_blob *res_blob)
693 {
694 	struct ulp_flow_db_res_params	fid_parms;
695 	uint64_t id = 0;
696 	uint32_t idx = 0;
697 	struct tf_search_identifier_parms sparms = { 0 };
698 	struct tf_free_identifier_parms free_parms = { 0 };
699 	struct tf *tfp;
700 	int rc;
701 
702 	/* Get the tfp from ulp context */
703 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
704 	if (!tfp) {
705 		BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
706 		return -EINVAL;
707 	}
708 
709 	/* Extract the index from the result blob */
710 	rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
711 			   ident->ident_bit_pos, ident->ident_bit_size);
712 	if (rc) {
713 		BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
714 		return -EIO;
715 	}
716 
717 	/* populate the search params and search identifier shadow table */
718 	sparms.ident_type = ident->ident_type;
719 	sparms.dir = tbl->direction;
720 	/* convert the idx into cpu format */
721 	sparms.search_id = tfp_be_to_cpu_32(idx);
722 
723 	/* Search identifier also increase the reference count */
724 	rc = tf_search_identifier(tfp, &sparms);
725 	if (rc) {
726 		BNXT_TF_DBG(ERR, "Search ident %s:%x failed.\n",
727 			    tf_dir_2_str(sparms.dir),
728 			    sparms.search_id);
729 		return rc;
730 	}
731 	BNXT_TF_DBG(INFO, "Search ident %s:%x.success.\n",
732 		    tf_dir_2_str(sparms.dir),
733 		    sparms.search_id);
734 
735 	/* Write it to the regfile */
736 	id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
737 	if (!ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
738 		BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
739 		rc = -EINVAL;
740 		/* Need to free the identifier, so goto error */
741 		goto error;
742 	}
743 
744 	/* Link the resource to the flow in the flow db */
745 	memset(&fid_parms, 0, sizeof(fid_parms));
746 	fid_parms.direction = tbl->direction;
747 	fid_parms.resource_func = ident->resource_func;
748 	fid_parms.resource_type = ident->ident_type;
749 	fid_parms.resource_hndl = sparms.search_id;
750 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
751 	rc = ulp_flow_db_resource_add(parms->ulp_ctx,
752 				      parms->flow_type,
753 				      parms->fid,
754 				      &fid_parms);
755 	if (rc) {
756 		BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
757 			    rc);
758 		/* Need to free the identifier, so goto error */
759 		goto error;
760 	}
761 
762 	return 0;
763 
764 error:
765 	/* Need to free the identifier */
766 	free_parms.dir = tbl->direction;
767 	free_parms.ident_type = ident->ident_type;
768 	free_parms.id = sparms.search_id;
769 	(void)tf_free_identifier(tfp, &free_parms);
770 	BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
771 		    ident->description,
772 		    tf_dir_2_str(tbl->direction), sparms.search_id);
773 	return rc;
774 }
775 
776 static int32_t
777 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
778 				enum tf_dir dir,
779 				struct bnxt_ulp_mapper_result_field_info *fld,
780 				struct ulp_blob *blob,
781 				const char *name)
782 {
783 	uint16_t idx, size_idx;
784 	uint8_t	 *val = NULL;
785 	uint64_t regval;
786 	uint32_t val_size = 0, field_size = 0;
787 	uint64_t act_bit;
788 	uint8_t act_val[16];
789 	uint64_t hdr_bit;
790 
791 	switch (fld->result_opcode) {
792 	case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
793 		val = fld->result_operand;
794 		if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
795 			BNXT_TF_DBG(ERR, "%s failed to add field\n", name);
796 			return -EINVAL;
797 		}
798 		break;
799 	case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_PROP:
800 		if (!ulp_operand_read(fld->result_operand,
801 				      (uint8_t *)&idx, sizeof(uint16_t))) {
802 			BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
803 			return -EINVAL;
804 		}
805 		idx = tfp_be_to_cpu_16(idx);
806 
807 		if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
808 			BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
809 			return -EINVAL;
810 		}
811 		val = &parms->act_prop->act_details[idx];
812 		field_size = ulp_mapper_act_prop_size_get(idx);
813 		if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
814 			field_size  = field_size -
815 			    ((fld->field_bit_size + 7) / 8);
816 			val += field_size;
817 		}
818 		if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
819 			BNXT_TF_DBG(ERR, "%s push field failed\n", name);
820 			return -EINVAL;
821 		}
822 		break;
823 	case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_BIT:
824 		if (!ulp_operand_read(fld->result_operand,
825 				      (uint8_t *)&act_bit, sizeof(uint64_t))) {
826 			BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
827 			return -EINVAL;
828 		}
829 		act_bit = tfp_be_to_cpu_64(act_bit);
830 		memset(act_val, 0, sizeof(act_val));
831 		if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
832 			act_val[0] = 1;
833 		if (fld->field_bit_size > ULP_BYTE_2_BITS(sizeof(act_val))) {
834 			BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
835 			return -EINVAL;
836 		}
837 		if (!ulp_blob_push(blob, act_val, fld->field_bit_size)) {
838 			BNXT_TF_DBG(ERR, "%s push field failed\n", name);
839 			return -EINVAL;
840 		}
841 		val = act_val;
842 		break;
843 	case BNXT_ULP_MAPPER_OPC_SET_TO_ENCAP_ACT_PROP_SZ:
844 		if (!ulp_operand_read(fld->result_operand,
845 				      (uint8_t *)&idx, sizeof(uint16_t))) {
846 			BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
847 			return -EINVAL;
848 		}
849 		idx = tfp_be_to_cpu_16(idx);
850 
851 		if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
852 			BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
853 			return -EINVAL;
854 		}
855 		val = &parms->act_prop->act_details[idx];
856 
857 		/* get the size index next */
858 		if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
859 				      (uint8_t *)&size_idx, sizeof(uint16_t))) {
860 			BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
861 			return -EINVAL;
862 		}
863 		size_idx = tfp_be_to_cpu_16(size_idx);
864 
865 		if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
866 			BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
867 			return -EINVAL;
868 		}
869 		memcpy(&val_size, &parms->act_prop->act_details[size_idx],
870 		       sizeof(uint32_t));
871 		val_size = tfp_be_to_cpu_32(val_size);
872 		val_size = ULP_BYTE_2_BITS(val_size);
873 		ulp_blob_push_encap(blob, val, val_size);
874 		break;
875 	case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
876 		if (!ulp_operand_read(fld->result_operand,
877 				      (uint8_t *)&idx, sizeof(uint16_t))) {
878 			BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
879 			return -EINVAL;
880 		}
881 
882 		idx = tfp_be_to_cpu_16(idx);
883 		/* Uninitialized regfile entries return 0 */
884 		if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
885 			BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
886 				    name, idx);
887 			return -EINVAL;
888 		}
889 
890 		val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
891 		if (!val) {
892 			BNXT_TF_DBG(ERR, "%s push field failed\n", name);
893 			return -EINVAL;
894 		}
895 		break;
896 	case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
897 		if (!ulp_operand_read(fld->result_operand,
898 				      (uint8_t *)&idx,
899 				      sizeof(uint16_t))) {
900 			BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
901 			return -EINVAL;
902 		}
903 		idx = tfp_be_to_cpu_16(idx);
904 		if (ulp_mapper_glb_resource_read(parms->mapper_data,
905 						 dir,
906 						 idx, &regval)) {
907 			BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
908 				    name, idx);
909 			return -EINVAL;
910 		}
911 		val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
912 		if (!val) {
913 			BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
914 			return -EINVAL;
915 		}
916 		break;
917 	case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
918 		if (!ulp_operand_read(fld->result_operand,
919 				      (uint8_t *)&idx,
920 				      sizeof(uint16_t))) {
921 			BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
922 			return -EINVAL;
923 		}
924 		idx = tfp_be_to_cpu_16(idx);
925 		if (idx < BNXT_ULP_CF_IDX_LAST)
926 			val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
927 					       fld->field_bit_size);
928 		if (!val) {
929 			BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
930 			return -EINVAL;
931 		}
932 		break;
933 	case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
934 		if (ulp_blob_pad_push(blob, fld->field_bit_size) < 0) {
935 			BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
936 			return -EINVAL;
937 		}
938 
939 		break;
940 	case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST:
941 		if (!ulp_operand_read(fld->result_operand,
942 				      (uint8_t *)&act_bit, sizeof(uint64_t))) {
943 			BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
944 			return -EINVAL;
945 		}
946 		act_bit = tfp_be_to_cpu_64(act_bit);
947 		if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
948 			/* Action bit is set so consider operand_true */
949 			if (!ulp_operand_read(fld->result_operand_true,
950 					      (uint8_t *)&idx,
951 					      sizeof(uint16_t))) {
952 				BNXT_TF_DBG(ERR, "%s operand read failed\n",
953 					    name);
954 				return -EINVAL;
955 			}
956 			idx = tfp_be_to_cpu_16(idx);
957 			if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
958 				BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n",
959 					    name, idx);
960 				return -EINVAL;
961 			}
962 			val = &parms->act_prop->act_details[idx];
963 			field_size = ulp_mapper_act_prop_size_get(idx);
964 			if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
965 				field_size  = field_size -
966 				    ((fld->field_bit_size + 7) / 8);
967 				val += field_size;
968 			}
969 			if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
970 				BNXT_TF_DBG(ERR, "%s push field failed\n",
971 					    name);
972 				return -EINVAL;
973 			}
974 		} else {
975 			/* action bit is not set, use the operand false */
976 			val = fld->result_operand_false;
977 			if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
978 				BNXT_TF_DBG(ERR, "%s failed to add field\n",
979 					    name);
980 				return -EINVAL;
981 			}
982 		}
983 		break;
984 	case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST:
985 		if (!ulp_operand_read(fld->result_operand,
986 				      (uint8_t *)&act_bit, sizeof(uint64_t))) {
987 			BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
988 			return -EINVAL;
989 		}
990 		act_bit = tfp_be_to_cpu_64(act_bit);
991 		if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
992 			/* Action bit is set so consider operand_true */
993 			val = fld->result_operand_true;
994 		} else {
995 			/* action bit is not set, use the operand false */
996 			val = fld->result_operand_false;
997 		}
998 		if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
999 			BNXT_TF_DBG(ERR, "%s failed to add field\n",
1000 				    name);
1001 			return -EINVAL;
1002 		}
1003 		break;
1004 	case BNXT_ULP_MAPPER_OPC_IF_COMP_FIELD_THEN_CF_ELSE_CF:
1005 		if (!ulp_operand_read(fld->result_operand,
1006 				      (uint8_t *)&idx,
1007 				      sizeof(uint16_t))) {
1008 			BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1009 			return -EINVAL;
1010 		}
1011 		idx = tfp_be_to_cpu_16(idx);
1012 		if (idx >= BNXT_ULP_CF_IDX_LAST) {
1013 			BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
1014 			return -EINVAL;
1015 		}
1016 		/* check if the computed field is set */
1017 		if (ULP_COMP_FLD_IDX_RD(parms, idx))
1018 			val = fld->result_operand_true;
1019 		else
1020 			val = fld->result_operand_false;
1021 
1022 		/* read the appropriate computed field */
1023 		if (!ulp_operand_read(val, (uint8_t *)&idx, sizeof(uint16_t))) {
1024 			BNXT_TF_DBG(ERR, "%s val operand read failed\n", name);
1025 			return -EINVAL;
1026 		}
1027 		idx = tfp_be_to_cpu_16(idx);
1028 		if (idx >= BNXT_ULP_CF_IDX_LAST) {
1029 			BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
1030 			return -EINVAL;
1031 		}
1032 		val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1033 				       fld->field_bit_size);
1034 		if (!val) {
1035 			BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1036 			return -EINVAL;
1037 		}
1038 		break;
1039 	case BNXT_ULP_MAPPER_OPC_IF_HDR_BIT_THEN_CONST_ELSE_CONST:
1040 		if (!ulp_operand_read(fld->result_operand,
1041 				      (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1042 			BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1043 			return -EINVAL;
1044 		}
1045 		hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1046 		if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit)) {
1047 			/* Header bit is set so consider operand_true */
1048 			val = fld->result_operand_true;
1049 		} else {
1050 			/* Header bit is not set, use the operand false */
1051 			val = fld->result_operand_false;
1052 		}
1053 		if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1054 			BNXT_TF_DBG(ERR, "%s failed to add field\n",
1055 				    name);
1056 			return -EINVAL;
1057 		}
1058 		break;
1059 	default:
1060 		BNXT_TF_DBG(ERR, "invalid result mapper opcode 0x%x\n",
1061 			    fld->result_opcode);
1062 		return -EINVAL;
1063 	}
1064 	return 0;
1065 }
1066 
1067 /* Function to alloc action record and set the table. */
1068 static int32_t
1069 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
1070 				 enum tf_dir dir,
1071 				 struct bnxt_ulp_mapper_key_field_info *f,
1072 				 struct ulp_blob *blob,
1073 				 uint8_t is_key,
1074 				 const char *name)
1075 {
1076 	uint64_t val64;
1077 	uint16_t idx, bitlen;
1078 	uint32_t opcode;
1079 	uint8_t *operand;
1080 	struct ulp_regfile *regfile = parms->regfile;
1081 	uint8_t *val = NULL;
1082 	struct bnxt_ulp_mapper_key_field_info *fld = f;
1083 	uint32_t field_size;
1084 
1085 	if (is_key) {
1086 		operand = fld->spec_operand;
1087 		opcode	= fld->spec_opcode;
1088 	} else {
1089 		operand = fld->mask_operand;
1090 		opcode	= fld->mask_opcode;
1091 	}
1092 
1093 	bitlen = fld->field_bit_size;
1094 
1095 	switch (opcode) {
1096 	case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
1097 		val = operand;
1098 		if (!ulp_blob_push(blob, val, bitlen)) {
1099 			BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1100 			return -EINVAL;
1101 		}
1102 		break;
1103 	case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
1104 		if (ulp_blob_pad_push(blob, bitlen) < 0) {
1105 			BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
1106 			return -EINVAL;
1107 		}
1108 
1109 		break;
1110 	case BNXT_ULP_MAPPER_OPC_SET_TO_HDR_FIELD:
1111 		if (!ulp_operand_read(operand, (uint8_t *)&idx,
1112 				      sizeof(uint16_t))) {
1113 			BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1114 			return -EINVAL;
1115 		}
1116 		idx = tfp_be_to_cpu_16(idx);
1117 		if (is_key)
1118 			val = parms->hdr_field[idx].spec;
1119 		else
1120 			val = parms->hdr_field[idx].mask;
1121 
1122 		/*
1123 		 * Need to account for how much data was pushed to the header
1124 		 * field vs how much is to be inserted in the key/mask.
1125 		 */
1126 		field_size = parms->hdr_field[idx].size;
1127 		if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1128 			field_size  = field_size - ((bitlen + 7) / 8);
1129 			val += field_size;
1130 		}
1131 
1132 		if (!ulp_blob_push(blob, val, bitlen)) {
1133 			BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1134 			return -EINVAL;
1135 		}
1136 		break;
1137 	case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
1138 		if (!ulp_operand_read(operand, (uint8_t *)&idx,
1139 				      sizeof(uint16_t))) {
1140 			BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1141 			return -EINVAL;
1142 		}
1143 		idx = tfp_be_to_cpu_16(idx);
1144 		if (idx < BNXT_ULP_CF_IDX_LAST)
1145 			val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1146 					       bitlen);
1147 		if (!val) {
1148 			BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1149 			return -EINVAL;
1150 		}
1151 		break;
1152 	case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
1153 		if (!ulp_operand_read(operand, (uint8_t *)&idx,
1154 				      sizeof(uint16_t))) {
1155 			BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1156 			return -EINVAL;
1157 		}
1158 		idx = tfp_be_to_cpu_16(idx);
1159 
1160 		if (!ulp_regfile_read(regfile, idx, &val64)) {
1161 			BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
1162 				    name, idx);
1163 			return -EINVAL;
1164 		}
1165 
1166 		val = ulp_blob_push_64(blob, &val64, bitlen);
1167 		if (!val) {
1168 			BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1169 			return -EINVAL;
1170 		}
1171 		break;
1172 	case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
1173 		if (!ulp_operand_read(operand, (uint8_t *)&idx,
1174 				      sizeof(uint16_t))) {
1175 			BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1176 			return -EINVAL;
1177 		}
1178 		idx = tfp_be_to_cpu_16(idx);
1179 		if (ulp_mapper_glb_resource_read(parms->mapper_data,
1180 						 dir,
1181 						 idx, &val64)) {
1182 			BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
1183 				    name, idx);
1184 			return -EINVAL;
1185 		}
1186 		val = ulp_blob_push_64(blob, &val64, bitlen);
1187 		if (!val) {
1188 			BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1189 			return -EINVAL;
1190 		}
1191 		break;
1192 	default:
1193 		BNXT_TF_DBG(ERR, "invalid keymask mapper opcode 0x%x\n",
1194 			    opcode);
1195 		return -EINVAL;
1196 		break;
1197 	}
1198 
1199 	return 0;
1200 }
1201 
1202 static int32_t
1203 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1204 			     struct bnxt_ulp_mapper_tbl_info *tbl,
1205 			     uint64_t flow_id)
1206 {
1207 	enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1208 	struct ulp_flow_db_res_params fid_parms;
1209 	uint32_t mark, gfid, mark_flag;
1210 	int32_t rc = 0;
1211 
1212 	if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1213 	    !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1214 	      ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1215 			       BNXT_ULP_ACTION_BIT_MARK)))
1216 		return rc; /* no need to perform gfid process */
1217 
1218 	/* Get the mark id details from action property */
1219 	memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1220 	       sizeof(mark));
1221 	mark = tfp_be_to_cpu_32(mark);
1222 
1223 	TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1224 	mark_flag  = BNXT_ULP_MARK_GLOBAL_HW_FID;
1225 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1226 				  gfid, mark);
1227 	if (rc) {
1228 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1229 		return rc;
1230 	}
1231 	fid_parms.direction = tbl->direction;
1232 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1233 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1234 	fid_parms.resource_type	= mark_flag;
1235 	fid_parms.resource_hndl	= gfid;
1236 	rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1237 				      parms->flow_type,
1238 				      parms->fid,
1239 				      &fid_parms);
1240 	if (rc)
1241 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1242 	return rc;
1243 }
1244 
1245 static int32_t
1246 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1247 				struct bnxt_ulp_mapper_tbl_info *tbl)
1248 {
1249 	enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1250 	struct ulp_flow_db_res_params fid_parms;
1251 	uint32_t act_idx, mark, mark_flag;
1252 	uint64_t val64;
1253 	int32_t rc = 0;
1254 
1255 	if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1256 	    !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1257 	      ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1258 			       BNXT_ULP_ACTION_BIT_MARK)))
1259 		return rc; /* no need to perform mark action process */
1260 
1261 	/* Get the mark id details from action property */
1262 	memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1263 	       sizeof(mark));
1264 	mark = tfp_be_to_cpu_32(mark);
1265 
1266 	if (!ulp_regfile_read(parms->regfile,
1267 			      BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1268 			      &val64)) {
1269 		BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1270 		return -EINVAL;
1271 	}
1272 	act_idx = tfp_be_to_cpu_64(val64);
1273 	mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID;
1274 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1275 				  act_idx, mark);
1276 	if (rc) {
1277 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1278 		return rc;
1279 	}
1280 	fid_parms.direction = tbl->direction;
1281 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1282 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1283 	fid_parms.resource_type	= mark_flag;
1284 	fid_parms.resource_hndl	= act_idx;
1285 	rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1286 				      parms->flow_type,
1287 				      parms->fid,
1288 				      &fid_parms);
1289 	if (rc)
1290 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1291 	return rc;
1292 }
1293 
1294 static int32_t
1295 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1296 				struct bnxt_ulp_mapper_tbl_info *tbl)
1297 {
1298 	struct ulp_flow_db_res_params fid_parms;
1299 	uint32_t act_idx, mark, mark_flag;
1300 	uint64_t val64;
1301 	enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1302 	int32_t rc = 0;
1303 
1304 	if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1305 	    mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION)
1306 		return rc; /* no need to perform mark action process */
1307 
1308 	/* Get the mark id details from the computed field of dev port id */
1309 	mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1310 
1311 	 /* Get the main action pointer */
1312 	if (!ulp_regfile_read(parms->regfile,
1313 			      BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1314 			      &val64)) {
1315 		BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1316 		return -EINVAL;
1317 	}
1318 	act_idx = tfp_be_to_cpu_64(val64);
1319 
1320 	/* Set the mark flag to local fid and vfr flag */
1321 	mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1322 
1323 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1324 				  act_idx, mark);
1325 	if (rc) {
1326 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1327 		return rc;
1328 	}
1329 	fid_parms.direction = tbl->direction;
1330 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1331 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1332 	fid_parms.resource_type	= mark_flag;
1333 	fid_parms.resource_hndl	= act_idx;
1334 	rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1335 				      parms->flow_type,
1336 				      parms->fid,
1337 				      &fid_parms);
1338 	if (rc)
1339 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1340 	return rc;
1341 }
1342 
1343 /*
1344  * Tcam table - create the result blob.
1345  * data [out] - the result blob data
1346  */
1347 static int32_t
1348 ulp_mapper_tcam_tbl_result_create(struct bnxt_ulp_mapper_parms *parms,
1349 				  struct bnxt_ulp_mapper_tbl_info *tbl,
1350 				  struct ulp_blob *data)
1351 {
1352 	struct bnxt_ulp_mapper_result_field_info *dflds;
1353 	uint32_t num_dflds;
1354 	uint32_t encap_flds = 0;
1355 	uint32_t i;
1356 	int32_t rc = 0;
1357 
1358 	/* Create the result data blob */
1359 	dflds = ulp_mapper_result_fields_get(parms, tbl, &num_dflds,
1360 					     &encap_flds);
1361 	if (!dflds || !num_dflds || encap_flds) {
1362 		BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1363 		return -EINVAL;
1364 	}
1365 
1366 	for (i = 0; i < num_dflds; i++) {
1367 		rc = ulp_mapper_result_field_process(parms,
1368 						     tbl->direction,
1369 						     &dflds[i],
1370 						     data,
1371 						     "TCAM Result");
1372 		if (rc) {
1373 			BNXT_TF_DBG(ERR, "Failed to set data fields\n");
1374 			return -EINVAL;
1375 		}
1376 	}
1377 	return rc;
1378 }
1379 
1380 /* Tcam table scan the identifier list and allocate each identifier */
1381 static int32_t
1382 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1383 				     struct bnxt_ulp_mapper_tbl_info *tbl)
1384 {
1385 	struct bnxt_ulp_mapper_ident_info *idents;
1386 	uint32_t num_idents;
1387 	uint32_t i;
1388 
1389 	/*
1390 	 * Since the cache entry is responsible for allocating
1391 	 * identifiers when in use, allocate the identifiers only
1392 	 * during normal processing.
1393 	 */
1394 	if (parms->tcam_tbl_opc ==
1395 	    BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1396 		idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1397 
1398 		for (i = 0; i < num_idents; i++) {
1399 			if (ulp_mapper_ident_process(parms, tbl,
1400 						     &idents[i], NULL))
1401 				return -EINVAL;
1402 		}
1403 	}
1404 	return 0;
1405 }
1406 
1407 /*
1408  * Tcam table scan the identifier list and extract the identifier from
1409  * the result blob.
1410  */
1411 static int32_t
1412 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1413 				       struct bnxt_ulp_mapper_tbl_info *tbl,
1414 				       struct ulp_blob *data)
1415 {
1416 	struct bnxt_ulp_mapper_ident_info *idents;
1417 	uint32_t num_idents = 0, i;
1418 	int32_t rc = 0;
1419 
1420 	/*
1421 	 * Extract the listed identifiers from the result field,
1422 	 * no need to allocate them.
1423 	 */
1424 	idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1425 	for (i = 0; i < num_idents; i++) {
1426 		rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1427 		if (rc) {
1428 			BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1429 			return rc;
1430 		}
1431 	}
1432 	return rc;
1433 }
1434 
1435 /* Internal function to write the tcam entry */
1436 static int32_t
1437 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1438 				struct bnxt_ulp_mapper_tbl_info *tbl,
1439 				struct ulp_blob *key,
1440 				struct ulp_blob *mask,
1441 				struct ulp_blob *data,
1442 				uint16_t idx)
1443 {
1444 	struct tf_set_tcam_entry_parms sparms = { 0 };
1445 	struct tf *tfp;
1446 	uint16_t tmplen;
1447 	int32_t rc;
1448 
1449 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1450 	if (!tfp) {
1451 		BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1452 		return -EINVAL;
1453 	}
1454 
1455 	sparms.dir		= tbl->direction;
1456 	sparms.tcam_tbl_type	= tbl->resource_type;
1457 	sparms.idx		= idx;
1458 	/* Already verified the key/mask lengths */
1459 	sparms.key		= ulp_blob_data_get(key, &tmplen);
1460 	sparms.mask		= ulp_blob_data_get(mask, &tmplen);
1461 	sparms.key_sz_in_bits	= tbl->key_bit_size;
1462 	sparms.result		= ulp_blob_data_get(data, &tmplen);
1463 
1464 	if (tbl->result_bit_size != tmplen) {
1465 		BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1466 			    tmplen, tbl->result_bit_size);
1467 		return -EINVAL;
1468 	}
1469 	sparms.result_sz_in_bits = tbl->result_bit_size;
1470 	if (tf_set_tcam_entry(tfp, &sparms)) {
1471 		BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1472 			    tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1473 			    tf_dir_2_str(sparms.dir), sparms.idx);
1474 		return -EIO;
1475 	}
1476 	BNXT_TF_DBG(INFO, "tcam[%s][%s][%x] write success.\n",
1477 		    tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1478 		    tf_dir_2_str(sparms.dir), sparms.idx);
1479 
1480 	/* Update cache with TCAM index if the was cache allocated. */
1481 	if (parms->tcam_tbl_opc ==
1482 	    BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC) {
1483 		if (!parms->cache_ptr) {
1484 			BNXT_TF_DBG(ERR, "Unable to update cache");
1485 			return -EINVAL;
1486 		}
1487 		parms->cache_ptr->tcam_idx = idx;
1488 	}
1489 
1490 	/* Mark action */
1491 	rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1492 	if (rc) {
1493 		BNXT_TF_DBG(ERR, "failed mark action processing\n");
1494 		return rc;
1495 	}
1496 
1497 	return rc;
1498 }
1499 
1500 static int32_t
1501 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1502 			    struct bnxt_ulp_mapper_tbl_info *tbl)
1503 {
1504 	struct bnxt_ulp_mapper_key_field_info	*kflds;
1505 	struct ulp_blob key, mask, data, update_data;
1506 	uint32_t i, num_kflds;
1507 	struct tf *tfp;
1508 	int32_t rc, trc;
1509 	struct tf_alloc_tcam_entry_parms aparms		= { 0 };
1510 	struct tf_search_tcam_entry_parms searchparms   = { 0 };
1511 	struct ulp_flow_db_res_params	fid_parms	= { 0 };
1512 	struct tf_free_tcam_entry_parms free_parms	= { 0 };
1513 	enum bnxt_ulp_search_before_alloc search_flag;
1514 	uint32_t hit = 0;
1515 	uint16_t tmplen = 0;
1516 	uint16_t idx;
1517 
1518 	/* Skip this if was handled by the cache. */
1519 	if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) {
1520 		parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1521 		return 0;
1522 	}
1523 
1524 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1525 	if (!tfp) {
1526 		BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1527 		return -EINVAL;
1528 	}
1529 
1530 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1531 	if (!kflds || !num_kflds) {
1532 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1533 		return -EINVAL;
1534 	}
1535 
1536 	if (!ulp_blob_init(&key, tbl->key_bit_size,
1537 			   parms->device_params->byte_order) ||
1538 	    !ulp_blob_init(&mask, tbl->key_bit_size,
1539 			   parms->device_params->byte_order) ||
1540 	    !ulp_blob_init(&data, tbl->result_bit_size,
1541 			   parms->device_params->byte_order) ||
1542 	    !ulp_blob_init(&update_data, tbl->result_bit_size,
1543 			   parms->device_params->byte_order)) {
1544 		BNXT_TF_DBG(ERR, "blob inits failed.\n");
1545 		return -EINVAL;
1546 	}
1547 
1548 	/* create the key/mask */
1549 	/*
1550 	 * NOTE: The WC table will require some kind of flag to handle the
1551 	 * mode bits within the key/mask
1552 	 */
1553 	for (i = 0; i < num_kflds; i++) {
1554 		/* Setup the key */
1555 		rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1556 						      &kflds[i],
1557 						      &key, 1, "TCAM Key");
1558 		if (rc) {
1559 			BNXT_TF_DBG(ERR, "Key field set failed.\n");
1560 			return rc;
1561 		}
1562 
1563 		/* Setup the mask */
1564 		rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1565 						      &kflds[i],
1566 						      &mask, 0, "TCAM Mask");
1567 		if (rc) {
1568 			BNXT_TF_DBG(ERR, "Mask field set failed.\n");
1569 			return rc;
1570 		}
1571 	}
1572 
1573 	if (tbl->srch_b4_alloc == BNXT_ULP_SEARCH_BEFORE_ALLOC_NO) {
1574 		/*
1575 		 * No search for re-use is requested, so simply allocate the
1576 		 * tcam index.
1577 		 */
1578 		aparms.dir		= tbl->direction;
1579 		aparms.tcam_tbl_type	= tbl->resource_type;
1580 		aparms.search_enable	= tbl->srch_b4_alloc;
1581 		aparms.key_sz_in_bits	= tbl->key_bit_size;
1582 		aparms.key		= ulp_blob_data_get(&key, &tmplen);
1583 		if (tbl->key_bit_size != tmplen) {
1584 			BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1585 				    tmplen, tbl->key_bit_size);
1586 			return -EINVAL;
1587 		}
1588 
1589 		aparms.mask		= ulp_blob_data_get(&mask, &tmplen);
1590 		if (tbl->key_bit_size != tmplen) {
1591 			BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1592 				    tmplen, tbl->key_bit_size);
1593 			return -EINVAL;
1594 		}
1595 
1596 		aparms.priority		= tbl->priority;
1597 
1598 		/*
1599 		 * All failures after this succeeds require the entry to be
1600 		 * freed. cannot return directly on failure, but needs to goto
1601 		 * error.
1602 		 */
1603 		rc = tf_alloc_tcam_entry(tfp, &aparms);
1604 		if (rc) {
1605 			BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1606 			return rc;
1607 		}
1608 		idx = aparms.idx;
1609 		hit = aparms.hit;
1610 	} else {
1611 		/*
1612 		 * Searching before allocation to see if we already have an
1613 		 * entry.  This allows re-use of a constrained resource.
1614 		 */
1615 		searchparms.dir = tbl->direction;
1616 		searchparms.tcam_tbl_type = tbl->resource_type;
1617 		searchparms.key = ulp_blob_data_get(&key, &tmplen);
1618 		searchparms.key_sz_in_bits = tbl->key_bit_size;
1619 		searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1620 		searchparms.priority = tbl->priority;
1621 		searchparms.alloc = 1;
1622 		searchparms.result = ulp_blob_data_get(&data, &tmplen);
1623 		searchparms.result_sz_in_bits = tbl->result_bit_size;
1624 
1625 		rc = tf_search_tcam_entry(tfp, &searchparms);
1626 		if (rc) {
1627 			BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1628 			return rc;
1629 		}
1630 
1631 		/* Successful search, check the result */
1632 		if (searchparms.search_status == REJECT) {
1633 			BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1634 			return -ENOMEM;
1635 		}
1636 		idx = searchparms.idx;
1637 		hit = searchparms.hit;
1638 	}
1639 
1640 	/* if it is miss then it is same as no search before alloc */
1641 	if (!hit)
1642 		search_flag = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO;
1643 	else
1644 		search_flag = tbl->srch_b4_alloc;
1645 
1646 	switch (search_flag) {
1647 	case BNXT_ULP_SEARCH_BEFORE_ALLOC_NO:
1648 		/*Scan identifier list, allocate identifier and update regfile*/
1649 		rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1650 		/* Create the result blob */
1651 		if (!rc)
1652 			rc = ulp_mapper_tcam_tbl_result_create(parms, tbl,
1653 							       &data);
1654 		/* write the tcam entry */
1655 		if (!rc)
1656 			rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1657 							     &mask, &data, idx);
1658 		break;
1659 	case BNXT_ULP_SEARCH_BEFORE_ALLOC_SEARCH_IF_HIT_SKIP:
1660 		/*Scan identifier list, extract identifier and update regfile*/
1661 		rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1662 		break;
1663 	case BNXT_ULP_SEARCH_BEFORE_ALLOC_SEARCH_IF_HIT_UPDATE:
1664 		/*Scan identifier list, extract identifier and update regfile*/
1665 		rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1666 		/* Create the result blob */
1667 		if (!rc)
1668 			rc = ulp_mapper_tcam_tbl_result_create(parms, tbl,
1669 							       &update_data);
1670 		/* Update/overwrite the tcam entry */
1671 		if (!rc)
1672 			rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1673 							     &mask,
1674 							     &update_data, idx);
1675 		break;
1676 	default:
1677 		BNXT_TF_DBG(ERR, "invalid search opcode\n");
1678 		rc =  -EINVAL;
1679 		break;
1680 	}
1681 	if (rc)
1682 		goto error;
1683 
1684 	/*
1685 	 * Only link the entry to the flow db in the event that cache was not
1686 	 * used.
1687 	 */
1688 	if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1689 		fid_parms.direction = tbl->direction;
1690 		fid_parms.resource_func	= tbl->resource_func;
1691 		fid_parms.resource_type	= tbl->resource_type;
1692 		fid_parms.critical_resource = tbl->critical_resource;
1693 		fid_parms.resource_hndl	= idx;
1694 		rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1695 					      parms->flow_type,
1696 					      parms->fid,
1697 					      &fid_parms);
1698 		if (rc) {
1699 			BNXT_TF_DBG(ERR,
1700 				    "Failed to link resource to flow rc = %d\n",
1701 				    rc);
1702 			/* Need to free the identifier, so goto error */
1703 			goto error;
1704 		}
1705 	} else {
1706 		/*
1707 		 * Reset the tcam table opcode to normal in case the next tcam
1708 		 * entry does not use cache.
1709 		 */
1710 		parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1711 		parms->cache_ptr = NULL;
1712 	}
1713 
1714 	return 0;
1715 error:
1716 	parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1717 	free_parms.dir			= tbl->direction;
1718 	free_parms.tcam_tbl_type	= tbl->resource_type;
1719 	free_parms.idx			= idx;
1720 	trc = tf_free_tcam_entry(tfp, &free_parms);
1721 	if (trc)
1722 		BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1723 			    tbl->resource_type, tbl->direction, idx);
1724 
1725 	return rc;
1726 }
1727 
1728 static int32_t
1729 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1730 			  struct bnxt_ulp_mapper_tbl_info *tbl)
1731 {
1732 	struct bnxt_ulp_mapper_key_field_info	*kflds;
1733 	struct bnxt_ulp_mapper_result_field_info *dflds;
1734 	struct ulp_blob key, data;
1735 	uint32_t i, num_kflds, num_dflds;
1736 	uint16_t tmplen;
1737 	struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1738 	struct ulp_flow_db_res_params	fid_parms = { 0 };
1739 	struct tf_insert_em_entry_parms iparms = { 0 };
1740 	struct tf_delete_em_entry_parms free_parms = { 0 };
1741 	enum bnxt_ulp_flow_mem_type mtype;
1742 	int32_t	trc;
1743 	int32_t rc = 0;
1744 	uint32_t encap_flds = 0;
1745 
1746 	rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1747 	if (rc) {
1748 		BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1749 		return -EINVAL;
1750 	}
1751 
1752 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1753 	if (!kflds || !num_kflds) {
1754 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1755 		return -EINVAL;
1756 	}
1757 
1758 	/* Initialize the key/result blobs */
1759 	if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1760 			   parms->device_params->byte_order) ||
1761 	    !ulp_blob_init(&data, tbl->result_bit_size,
1762 			   parms->device_params->byte_order)) {
1763 		BNXT_TF_DBG(ERR, "blob inits failed.\n");
1764 		return -EINVAL;
1765 	}
1766 
1767 	/* create the key */
1768 	for (i = 0; i < num_kflds; i++) {
1769 		/* Setup the key */
1770 		rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1771 						      &kflds[i],
1772 						      &key, 1, "EM Key");
1773 		if (rc) {
1774 			BNXT_TF_DBG(ERR, "Key field set failed.\n");
1775 			return rc;
1776 		}
1777 	}
1778 
1779 	/*
1780 	 * TBD: Normally should process identifiers in case of using recycle or
1781 	 * loopback.  Not supporting recycle for now.
1782 	 */
1783 
1784 	/* Create the result data blob */
1785 	dflds = ulp_mapper_result_fields_get(parms, tbl,
1786 					     &num_dflds, &encap_flds);
1787 	if (!dflds || !num_dflds || encap_flds) {
1788 		BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1789 		return -EINVAL;
1790 	}
1791 
1792 	for (i = 0; i < num_dflds; i++) {
1793 		struct bnxt_ulp_mapper_result_field_info *fld;
1794 
1795 		fld = &dflds[i];
1796 
1797 		rc = ulp_mapper_result_field_process(parms,
1798 						     tbl->direction,
1799 						     fld,
1800 						     &data,
1801 						     "EM Result");
1802 		if (rc) {
1803 			BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
1804 			return rc;
1805 		}
1806 	}
1807 
1808 	/* do the transpose for the internal EM keys */
1809 	if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1810 		ulp_blob_perform_byte_reverse(&key);
1811 
1812 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1813 					     &iparms.tbl_scope_id);
1814 	if (rc) {
1815 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1816 		return rc;
1817 	}
1818 
1819 	/*
1820 	 * NOTE: the actual blob size will differ from the size in the tbl
1821 	 * entry due to the padding.
1822 	 */
1823 	iparms.dup_check		= 0;
1824 	iparms.dir			= tbl->direction;
1825 	iparms.mem			= tbl->resource_type;
1826 	iparms.key			= ulp_blob_data_get(&key, &tmplen);
1827 	iparms.key_sz_in_bits		= tbl->key_bit_size;
1828 	iparms.em_record		= ulp_blob_data_get(&data, &tmplen);
1829 	iparms.em_record_sz_in_bits	= tbl->result_bit_size;
1830 
1831 	rc = tf_insert_em_entry(tfp, &iparms);
1832 	if (rc) {
1833 		BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1834 		return rc;
1835 	}
1836 
1837 	/* Mark action process */
1838 	if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
1839 	    tbl->resource_type == TF_MEM_EXTERNAL)
1840 		rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
1841 	else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
1842 		 tbl->resource_type == TF_MEM_INTERNAL)
1843 		rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1844 	if (rc) {
1845 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1846 		goto error;
1847 	}
1848 
1849 	/* Link the EM resource to the flow in the flow db */
1850 	memset(&fid_parms, 0, sizeof(fid_parms));
1851 	fid_parms.direction		= tbl->direction;
1852 	fid_parms.resource_func		= tbl->resource_func;
1853 	fid_parms.resource_type		= tbl->resource_type;
1854 	fid_parms.critical_resource	= tbl->critical_resource;
1855 	fid_parms.resource_hndl		= iparms.flow_handle;
1856 
1857 	rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1858 				      parms->flow_type,
1859 				      parms->fid,
1860 				      &fid_parms);
1861 	if (rc) {
1862 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1863 			    rc);
1864 		/* Need to free the identifier, so goto error */
1865 		goto error;
1866 	}
1867 
1868 	return 0;
1869 error:
1870 	free_parms.dir		= iparms.dir;
1871 	free_parms.mem		= iparms.mem;
1872 	free_parms.tbl_scope_id	= iparms.tbl_scope_id;
1873 	free_parms.flow_handle	= iparms.flow_handle;
1874 
1875 	trc = tf_delete_em_entry(tfp, &free_parms);
1876 	if (trc)
1877 		BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1878 
1879 	return rc;
1880 }
1881 
1882 static int32_t
1883 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1884 			     struct bnxt_ulp_mapper_tbl_info *tbl)
1885 {
1886 	struct bnxt_ulp_mapper_result_field_info *flds;
1887 	struct ulp_flow_db_res_params	fid_parms;
1888 	struct ulp_blob	data;
1889 	uint64_t idx = 0;
1890 	uint16_t tmplen;
1891 	uint32_t i, num_flds, index, hit;
1892 	int32_t rc = 0, trc = 0;
1893 	struct tf_alloc_tbl_entry_parms	aparms = { 0 };
1894 	struct tf_search_tbl_entry_parms srchparms = { 0 };
1895 	struct tf_set_tbl_entry_parms	sparms = { 0 };
1896 	struct tf_free_tbl_entry_parms	free_parms = { 0 };
1897 	uint32_t tbl_scope_id;
1898 	struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1899 	uint16_t bit_size;
1900 	uint32_t encap_flds = 0;
1901 
1902 	/* Get the scope id first */
1903 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1904 	if (rc) {
1905 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1906 		return rc;
1907 	}
1908 
1909 	/* use the max size if encap is enabled */
1910 	if (tbl->encap_num_fields)
1911 		bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
1912 	else
1913 		bit_size = tbl->result_bit_size;
1914 
1915 	/* Initialize the blob data */
1916 	if (!ulp_blob_init(&data, bit_size,
1917 			   parms->device_params->byte_order)) {
1918 		BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1919 		return -EINVAL;
1920 	}
1921 
1922 	/* Get the result fields list */
1923 	flds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, &encap_flds);
1924 
1925 	if (!flds || (!num_flds && !encap_flds)) {
1926 		BNXT_TF_DBG(ERR, "template undefined for the index table\n");
1927 		return -EINVAL;
1928 	}
1929 
1930 	/* process the result fields, loop through them */
1931 	for (i = 0; i < (num_flds + encap_flds); i++) {
1932 		/* set the swap index if encap swap bit is enabled */
1933 		if (parms->device_params->encap_byte_swap && encap_flds &&
1934 		    (i == num_flds))
1935 			ulp_blob_encap_swap_idx_set(&data);
1936 
1937 		/* Process the result fields */
1938 		rc = ulp_mapper_result_field_process(parms,
1939 						     tbl->direction,
1940 						     &flds[i],
1941 						     &data,
1942 						     "Indexed Result");
1943 		if (rc) {
1944 			BNXT_TF_DBG(ERR, "data field failed\n");
1945 			return rc;
1946 		}
1947 	}
1948 
1949 	/* if encap bit swap is enabled perform the bit swap */
1950 	if (parms->device_params->encap_byte_swap && encap_flds) {
1951 		ulp_blob_perform_encap_swap(&data);
1952 	}
1953 
1954 	/*
1955 	 * Check for index opcode, if it is Global then
1956 	 * no need to allocate the table, just set the table
1957 	 * and exit since it is not maintained in the flow db.
1958 	 */
1959 	if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_GLOBAL) {
1960 		/* get the index from index operand */
1961 		if (tbl->index_operand < BNXT_ULP_GLB_REGFILE_INDEX_LAST &&
1962 		    ulp_mapper_glb_resource_read(parms->mapper_data,
1963 						 tbl->direction,
1964 						 tbl->index_operand,
1965 						 &idx)) {
1966 			BNXT_TF_DBG(ERR, "Glbl regfile[%d] read failed.\n",
1967 				    tbl->index_operand);
1968 			return -EINVAL;
1969 		}
1970 		/* set the Tf index table */
1971 		sparms.dir		= tbl->direction;
1972 		sparms.type		= tbl->resource_type;
1973 		sparms.data		= ulp_blob_data_get(&data, &tmplen);
1974 		sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1975 		sparms.idx		= tfp_be_to_cpu_64(idx);
1976 		sparms.tbl_scope_id	= tbl_scope_id;
1977 
1978 		rc = tf_set_tbl_entry(tfp, &sparms);
1979 		if (rc) {
1980 			BNXT_TF_DBG(ERR,
1981 				    "Glbl Set table[%d][%s][%d] failed rc=%d\n",
1982 				    sparms.type,
1983 				    (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
1984 				    sparms.idx,
1985 				    rc);
1986 			return rc;
1987 		}
1988 		return 0; /* success */
1989 	}
1990 
1991 	index = 0;
1992 	hit = 0;
1993 	/* Perform the tf table allocation by filling the alloc params */
1994 	if (tbl->srch_b4_alloc) {
1995 		memset(&srchparms, 0, sizeof(srchparms));
1996 		srchparms.dir = tbl->direction;
1997 		srchparms.type = tbl->resource_type;
1998 		srchparms.alloc	= 1;
1999 		srchparms.result = ulp_blob_data_get(&data, &tmplen);
2000 		srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2001 		srchparms.tbl_scope_id = tbl_scope_id;
2002 		rc = tf_search_tbl_entry(tfp, &srchparms);
2003 		if (rc) {
2004 			BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2005 				    tf_tbl_type_2_str(tbl->resource_type),
2006 				    tf_dir_2_str(tbl->direction), rc);
2007 			return rc;
2008 		}
2009 		if (srchparms.search_status == REJECT) {
2010 			BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
2011 				    tf_tbl_type_2_str(tbl->resource_type),
2012 				    tf_dir_2_str(tbl->direction));
2013 			return -ENOMEM;
2014 		}
2015 		index = srchparms.idx;
2016 		hit = srchparms.hit;
2017 	} else {
2018 		aparms.dir		= tbl->direction;
2019 		aparms.type		= tbl->resource_type;
2020 		aparms.search_enable	= tbl->srch_b4_alloc;
2021 		aparms.result		= ulp_blob_data_get(&data, &tmplen);
2022 		aparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2023 		aparms.tbl_scope_id	= tbl_scope_id;
2024 
2025 		/* All failures after the alloc succeeds require a free */
2026 		rc = tf_alloc_tbl_entry(tfp, &aparms);
2027 		if (rc) {
2028 			BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2029 				    tf_tbl_type_2_str(tbl->resource_type),
2030 				    tf_dir_2_str(tbl->direction), rc);
2031 			return rc;
2032 		}
2033 		index = aparms.idx;
2034 	}
2035 	/*
2036 	 * calculate the idx for the result record, for external EM the offset
2037 	 * needs to be shifted accordingly. If external non-inline table types
2038 	 * are used then need to revisit this logic.
2039 	 */
2040 	if (tbl->resource_type == TF_TBL_TYPE_EXT)
2041 		idx = TF_ACT_REC_OFFSET_2_PTR(index);
2042 	else
2043 		idx = index;
2044 
2045 	/* Always storing values in Regfile in BE */
2046 	idx = tfp_cpu_to_be_64(idx);
2047 	if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_ALLOCATE) {
2048 		rc = ulp_regfile_write(parms->regfile, tbl->index_operand, idx);
2049 		if (!rc) {
2050 			BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2051 				    tbl->index_operand);
2052 			goto error;
2053 		}
2054 	}
2055 
2056 	/* Perform the tf table set by filling the set params */
2057 	if (!tbl->srch_b4_alloc || !hit) {
2058 		sparms.dir		= tbl->direction;
2059 		sparms.type		= tbl->resource_type;
2060 		sparms.data		= ulp_blob_data_get(&data, &tmplen);
2061 		sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2062 		sparms.idx		= index;
2063 		sparms.tbl_scope_id	= tbl_scope_id;
2064 
2065 		rc = tf_set_tbl_entry(tfp, &sparms);
2066 		if (rc) {
2067 			BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
2068 				    sparms.type,
2069 				    (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
2070 				    sparms.idx,
2071 				    rc);
2072 			goto error;
2073 		}
2074 	}
2075 
2076 	/* Link the resource to the flow in the flow db */
2077 	memset(&fid_parms, 0, sizeof(fid_parms));
2078 	fid_parms.direction	= tbl->direction;
2079 	fid_parms.resource_func	= tbl->resource_func;
2080 	fid_parms.resource_type	= tbl->resource_type;
2081 	fid_parms.resource_sub_type = tbl->resource_sub_type;
2082 	fid_parms.resource_hndl	= index;
2083 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2084 
2085 	rc = ulp_flow_db_resource_add(parms->ulp_ctx,
2086 				      parms->flow_type,
2087 				      parms->fid,
2088 				      &fid_parms);
2089 	if (rc) {
2090 		BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2091 			    rc);
2092 		goto error;
2093 	}
2094 
2095 	/* Perform the VF rep action */
2096 	rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2097 	if (rc) {
2098 		BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2099 		goto error;
2100 	}
2101 	return rc;
2102 error:
2103 	/*
2104 	 * Free the allocated resource since we failed to either
2105 	 * write to the entry or link the flow
2106 	 */
2107 	free_parms.dir	= tbl->direction;
2108 	free_parms.type	= tbl->resource_type;
2109 	free_parms.idx	= index;
2110 	free_parms.tbl_scope_id = tbl_scope_id;
2111 
2112 	trc = tf_free_tbl_entry(tfp, &free_parms);
2113 	if (trc)
2114 		BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2115 
2116 	return rc;
2117 }
2118 
2119 static int32_t
2120 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2121 			     struct bnxt_ulp_mapper_tbl_info *tbl)
2122 {
2123 	struct bnxt_ulp_mapper_key_field_info *kflds;
2124 	struct bnxt_ulp_mapper_cache_entry *cache_entry;
2125 	struct bnxt_ulp_mapper_ident_info *idents;
2126 	uint32_t i, num_kflds = 0, num_idents = 0;
2127 	struct ulp_flow_db_res_params fid_parms;
2128 	struct tf_free_identifier_parms fparms;
2129 	uint16_t tmplen, tmp_ident;
2130 	struct ulp_blob key;
2131 	uint8_t *cache_key;
2132 	uint64_t regval;
2133 	uint16_t *ckey;
2134 	int32_t rc;
2135 
2136 	/* Get the key fields list and build the key. */
2137 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2138 	if (!kflds || !num_kflds) {
2139 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2140 		return -EINVAL;
2141 	}
2142 	if (!ulp_blob_init(&key, tbl->key_bit_size,
2143 			   parms->device_params->byte_order)) {
2144 		BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2145 		return -EINVAL;
2146 	}
2147 	for (i = 0; i < num_kflds; i++) {
2148 		/* Setup the key */
2149 		rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
2150 						      &kflds[i],
2151 						      &key, 1, "Cache Key");
2152 		if (rc) {
2153 			BNXT_TF_DBG(ERR,
2154 				    "Failed to create key for Cache rc=%d\n",
2155 				    rc);
2156 			return -EINVAL;
2157 		}
2158 	}
2159 
2160 	/*
2161 	 * Perform the lookup in the cache table with constructed key.  The
2162 	 * cache_key is a byte array of tmplen, it needs to be converted to a
2163 	 * index for the cache table.
2164 	 */
2165 	cache_key = ulp_blob_data_get(&key, &tmplen);
2166 	ckey = (uint16_t *)cache_key;
2167 
2168 	/*
2169 	 * The id computed based on resource sub type and direction where
2170 	 * dir is the bit0 and rest of the bits come from resource
2171 	 * sub type.
2172 	 */
2173 	cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx,
2174 						 (tbl->resource_sub_type << 1 |
2175 						 (tbl->direction & 0x1)),
2176 						 *ckey);
2177 
2178 	/*
2179 	 * Get the identifier list for processing by both the hit and miss
2180 	 * processing.
2181 	 */
2182 	idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
2183 
2184 	if (!cache_entry->ref_count) {
2185 		/* Initialize the cache entry */
2186 		cache_entry->tcam_idx = 0;
2187 		cache_entry->ref_count = 0;
2188 		for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++)
2189 			cache_entry->idents[i] = ULP_IDENTS_INVALID;
2190 
2191 		/* Need to allocate identifiers for storing in the cache. */
2192 		for (i = 0; i < num_idents; i++) {
2193 			/*
2194 			 * Since we are using the cache, the identifier does not
2195 			 * get added to the flow db.  Pass in the pointer to the
2196 			 * tmp_ident.
2197 			 */
2198 			rc = ulp_mapper_ident_process(parms, tbl,
2199 						      &idents[i], &tmp_ident);
2200 			if (rc)
2201 				goto error;
2202 
2203 			cache_entry->ident_types[i] = idents[i].ident_type;
2204 			cache_entry->idents[i] = tmp_ident;
2205 		}
2206 
2207 		/* Tell the TCAM processor to alloc an entry */
2208 		parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC;
2209 		/* Store the cache key for use by the tcam process code */
2210 		parms->cache_ptr = cache_entry;
2211 	} else {
2212 		/* Cache hit, get values from result. */
2213 		for (i = 0; i < num_idents; i++) {
2214 			regval = (uint64_t)cache_entry->idents[i];
2215 			if (!ulp_regfile_write(parms->regfile,
2216 					       idents[i].regfile_idx,
2217 					       tfp_cpu_to_be_64(regval))) {
2218 				BNXT_TF_DBG(ERR,
2219 					    "Failed to write to regfile\n");
2220 				return -EINVAL;
2221 			}
2222 		}
2223 		/*
2224 		 * The cached entry is being used, so let the tcam processing
2225 		 * know not to process this table.
2226 		 */
2227 		parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP;
2228 	}
2229 
2230 	/* Made through the cache processing, increment the reference count. */
2231 	cache_entry->ref_count++;
2232 
2233 	/* Link the cache to the flow db. */
2234 	memset(&fid_parms, 0, sizeof(fid_parms));
2235 	fid_parms.direction = tbl->direction;
2236 	fid_parms.resource_func	= tbl->resource_func;
2237 
2238 	/*
2239 	 * Cache resource type is composed of table_type, resource
2240 	 * sub type and direction, it needs to set appropriately via setter.
2241 	 */
2242 	ulp_mapper_cache_res_type_set(&fid_parms,
2243 				      tbl->resource_type,
2244 				      (tbl->resource_sub_type << 1 |
2245 				       (tbl->direction & 0x1)));
2246 	fid_parms.resource_hndl	= (uint64_t)*ckey;
2247 	fid_parms.critical_resource = tbl->critical_resource;
2248 	rc = ulp_flow_db_resource_add(parms->ulp_ctx,
2249 				      parms->flow_type,
2250 				      parms->fid,
2251 				      &fid_parms);
2252 	if (rc)
2253 		BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n");
2254 
2255 	return rc;
2256 error:
2257 	/*
2258 	 * This error handling only gets called when the idents are being
2259 	 * allocated for the cache on misses.  Using the num_idents that was
2260 	 * previously set.
2261 	 */
2262 	for (i = 0; i < num_idents; i++) {
2263 		if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
2264 			continue;
2265 
2266 		fparms.dir = tbl->direction;
2267 		fparms.ident_type = idents[i].ident_type;
2268 		fparms.id = cache_entry->idents[i];
2269 		tf_free_identifier(parms->tfp, &fparms);
2270 	}
2271 
2272 	return rc;
2273 }
2274 
2275 static int32_t
2276 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2277 			  struct bnxt_ulp_mapper_tbl_info *tbl)
2278 {
2279 	struct bnxt_ulp_mapper_result_field_info *flds;
2280 	struct ulp_blob	data;
2281 	uint64_t idx;
2282 	uint16_t tmplen;
2283 	uint32_t i, num_flds;
2284 	int32_t rc = 0;
2285 	struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2286 	struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2287 	uint32_t encap_flds;
2288 
2289 	/* Initialize the blob data */
2290 	if (!ulp_blob_init(&data, tbl->result_bit_size,
2291 			   parms->device_params->byte_order)) {
2292 		BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2293 		return -EINVAL;
2294 	}
2295 
2296 	/* Get the result fields list */
2297 	flds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, &encap_flds);
2298 
2299 	if (!flds || !num_flds || encap_flds) {
2300 		BNXT_TF_DBG(ERR, "template undefined for the IF table\n");
2301 		return -EINVAL;
2302 	}
2303 
2304 	/* process the result fields, loop through them */
2305 	for (i = 0; i < num_flds; i++) {
2306 		/* Process the result fields */
2307 		rc = ulp_mapper_result_field_process(parms,
2308 						     tbl->direction,
2309 						     &flds[i],
2310 						     &data,
2311 						     "IFtable Result");
2312 		if (rc) {
2313 			BNXT_TF_DBG(ERR, "data field failed\n");
2314 			return rc;
2315 		}
2316 	}
2317 
2318 	/* Get the index details from computed field */
2319 	if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_COMP_FIELD) {
2320 		idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand);
2321 	} else if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_CONSTANT) {
2322 		idx = tbl->index_operand;
2323 	} else {
2324 		BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2325 		return -EINVAL;
2326 	}
2327 
2328 	/* Perform the tf table set by filling the set params */
2329 	iftbl_params.dir = tbl->direction;
2330 	iftbl_params.type = tbl->resource_type;
2331 	iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2332 	iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2333 	iftbl_params.idx = idx;
2334 
2335 	rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2336 	if (rc) {
2337 		BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
2338 			    iftbl_params.type,
2339 			    (iftbl_params.dir == TF_DIR_RX) ? "RX" : "TX",
2340 			    iftbl_params.idx,
2341 			    rc);
2342 		return rc;
2343 	}
2344 
2345 	/*
2346 	 * TBD: Need to look at the need to store idx in flow db for restore
2347 	 * the table to its original state on deletion of this entry.
2348 	 */
2349 	return rc;
2350 }
2351 
2352 static int32_t
2353 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2354 				  struct bnxt_ulp_mapper_data *mapper_data)
2355 {
2356 	struct bnxt_ulp_glb_resource_info *glb_res;
2357 	uint32_t num_glb_res_ids, idx;
2358 	int32_t rc = 0;
2359 
2360 	glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2361 	if (!glb_res || !num_glb_res_ids) {
2362 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2363 		return -EINVAL;
2364 	}
2365 
2366 	/* Iterate the global resources and process each one */
2367 	for (idx = 0; idx < num_glb_res_ids; idx++) {
2368 		switch (glb_res[idx].resource_func) {
2369 		case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2370 			rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2371 								mapper_data,
2372 								&glb_res[idx]);
2373 			break;
2374 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2375 			rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2376 								 mapper_data,
2377 								 &glb_res[idx]);
2378 			break;
2379 		default:
2380 			BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2381 				    glb_res[idx].resource_func);
2382 			rc = -EINVAL;
2383 			break;
2384 		}
2385 		if (rc)
2386 			return rc;
2387 	}
2388 	return rc;
2389 }
2390 
2391 /*
2392  * Function to process the conditional opcode of the mapper table.
2393  * returns 1 to skip the table.
2394  * return 0 to continue processing the table.
2395  *
2396  * defaults to skip
2397  */
2398 static int32_t
2399 ulp_mapper_tbl_cond_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2400 				   struct bnxt_ulp_mapper_tbl_info *tbl)
2401 {
2402 	int32_t rc = 1;
2403 
2404 	switch (tbl->cond_opcode) {
2405 	case BNXT_ULP_COND_OPCODE_NOP:
2406 		rc = 0;
2407 		break;
2408 	case BNXT_ULP_COND_OPCODE_COMP_FIELD_IS_SET:
2409 		if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST &&
2410 		    ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand))
2411 			rc = 0;
2412 		break;
2413 	case BNXT_ULP_COND_OPCODE_ACTION_BIT_IS_SET:
2414 		if (ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2415 				     tbl->cond_operand))
2416 			rc = 0;
2417 		break;
2418 	case BNXT_ULP_COND_OPCODE_HDR_BIT_IS_SET:
2419 		if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2420 				     tbl->cond_operand))
2421 			rc = 0;
2422 		break;
2423 	case BNXT_ULP_COND_OPCODE_COMP_FIELD_NOT_SET:
2424 		if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST &&
2425 		    !ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand))
2426 			rc = 0;
2427 		break;
2428 	case BNXT_ULP_COND_OPCODE_ACTION_BIT_NOT_SET:
2429 		if (!ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2430 				      tbl->cond_operand))
2431 			rc = 0;
2432 		break;
2433 	case BNXT_ULP_COND_OPCODE_HDR_BIT_NOT_SET:
2434 		if (!ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2435 				      tbl->cond_operand))
2436 			rc = 0;
2437 		break;
2438 	default:
2439 		BNXT_TF_DBG(ERR,
2440 			    "Invalid arg in mapper tbl for cond opcode\n");
2441 		break;
2442 	}
2443 	return rc;
2444 }
2445 
2446 /*
2447  * Function to process the memtype opcode of the mapper table.
2448  * returns 1 to skip the table.
2449  * return 0 to continue processing the table.
2450  *
2451  * defaults to skip
2452  */
2453 static int32_t
2454 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2455 				      struct bnxt_ulp_mapper_tbl_info *tbl)
2456 {
2457 	enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2458 	int32_t rc = 1;
2459 
2460 	bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2461 
2462 	switch (tbl->mem_type_opcode) {
2463 	case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_INT:
2464 		if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2465 			rc = 0;
2466 		break;
2467 	case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_EXT:
2468 		if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2469 			rc = 0;
2470 		break;
2471 	case BNXT_ULP_MEM_TYPE_OPCODE_NOP:
2472 		rc = 0;
2473 		break;
2474 	default:
2475 		BNXT_TF_DBG(ERR,
2476 			    "Invalid arg in mapper in memtype opcode\n");
2477 		break;
2478 	}
2479 	return rc;
2480 }
2481 
2482 static int32_t
2483 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
2484 {
2485 	struct bnxt_ulp_mapper_tbl_info *tbls;
2486 	uint32_t num_tbls, i;
2487 	int32_t rc = -EINVAL;
2488 
2489 	tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
2490 	if (!tbls || !num_tbls) {
2491 		BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
2492 			    (parms->tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2493 			    "class" : "action", parms->dev_id, tid);
2494 		return -EINVAL;
2495 	}
2496 
2497 	for (i = 0; i < num_tbls; i++) {
2498 		struct bnxt_ulp_mapper_tbl_info *tbl = &tbls[i];
2499 
2500 		if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl))
2501 			continue;
2502 		if (ulp_mapper_tbl_cond_opcode_process(parms, tbl))
2503 			continue;
2504 
2505 		switch (tbl->resource_func) {
2506 		case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2507 			rc = ulp_mapper_tcam_tbl_process(parms, tbl);
2508 			break;
2509 		case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2510 		case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2511 			rc = ulp_mapper_em_tbl_process(parms, tbl);
2512 			break;
2513 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2514 			rc = ulp_mapper_index_tbl_process(parms, tbl);
2515 			break;
2516 		case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
2517 			rc = ulp_mapper_cache_tbl_process(parms, tbl);
2518 			break;
2519 		case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
2520 			rc = ulp_mapper_if_tbl_process(parms, tbl);
2521 			break;
2522 		default:
2523 			BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
2524 				    tbl->resource_func);
2525 			rc = -EINVAL;
2526 			goto error;
2527 		}
2528 
2529 		if (rc) {
2530 			BNXT_TF_DBG(ERR, "Resource type %d failed\n",
2531 				    tbl->resource_func);
2532 			goto error;
2533 		}
2534 	}
2535 
2536 	return rc;
2537 error:
2538 	BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
2539 		    (parms->tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2540 		    "class" : "action", parms->dev_id, tid);
2541 	return rc;
2542 }
2543 
2544 static int32_t
2545 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
2546 			 uint32_t fid,
2547 			 struct ulp_flow_db_res_params *res)
2548 {
2549 	struct tf *tfp;
2550 	int32_t	rc = 0;
2551 
2552 	if (!res || !ulp) {
2553 		BNXT_TF_DBG(ERR, "Unable to free resource\n ");
2554 		return -EINVAL;
2555 	}
2556 
2557 	tfp = bnxt_ulp_cntxt_tfp_get(ulp);
2558 	if (!tfp) {
2559 		BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
2560 		return -EINVAL;
2561 	}
2562 
2563 	switch (res->resource_func) {
2564 	case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
2565 		rc = ulp_mapper_cache_entry_free(ulp, tfp, res);
2566 		break;
2567 	case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2568 		rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
2569 		break;
2570 	case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2571 	case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2572 		rc = ulp_mapper_em_entry_free(ulp, tfp, res);
2573 		break;
2574 	case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2575 		rc = ulp_mapper_index_entry_free(ulp, tfp, res);
2576 		break;
2577 	case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2578 		rc = ulp_mapper_ident_free(ulp, tfp, res);
2579 		break;
2580 	case BNXT_ULP_RESOURCE_FUNC_HW_FID:
2581 		rc = ulp_mapper_mark_free(ulp, res);
2582 		break;
2583 	case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
2584 		rc = ulp_mapper_parent_flow_free(ulp, fid, res);
2585 		break;
2586 	case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
2587 		rc = ulp_mapper_child_flow_free(ulp, fid, res);
2588 		break;
2589 	default:
2590 		break;
2591 	}
2592 
2593 	return rc;
2594 }
2595 
2596 int32_t
2597 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
2598 			  enum bnxt_ulp_fdb_type flow_type,
2599 			  uint32_t fid)
2600 {
2601 	struct ulp_flow_db_res_params res_parms = { 0 };
2602 	int32_t rc, trc;
2603 
2604 	if (!ulp_ctx) {
2605 		BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2606 		return -EINVAL;
2607 	}
2608 
2609 	/*
2610 	 * Set the critical resource on the first resource del, then iterate
2611 	 * while status is good
2612 	 */
2613 	res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
2614 	rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
2615 
2616 	if (rc) {
2617 		/*
2618 		 * This is unexpected on the first call to resource del.
2619 		 * It likely means that the flow did not exist in the flow db.
2620 		 */
2621 		BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
2622 			    flow_type, fid, rc);
2623 		return rc;
2624 	}
2625 
2626 	while (!rc) {
2627 		trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
2628 		if (trc)
2629 			/*
2630 			 * On fail, we still need to attempt to free the
2631 			 * remaining resources.  Don't return
2632 			 */
2633 			BNXT_TF_DBG(ERR,
2634 				    "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
2635 				    "] failed rc=%d.\n",
2636 				    flow_type, fid, res_parms.resource_func,
2637 				    res_parms.resource_hndl, trc);
2638 
2639 		/* All subsequent call require the non-critical_resource */
2640 		res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2641 
2642 		rc = ulp_flow_db_resource_del(ulp_ctx,
2643 					      flow_type,
2644 					      fid,
2645 					      &res_parms);
2646 	}
2647 
2648 	/* Free the Flow ID since we've removed all resources */
2649 	rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
2650 
2651 	return rc;
2652 }
2653 
2654 static void
2655 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
2656 				    struct bnxt_ulp_mapper_data *mapper_data)
2657 {
2658 	struct bnxt_ulp_mapper_glb_resource_entry *ent;
2659 	struct ulp_flow_db_res_params res;
2660 	uint32_t dir, idx;
2661 
2662 	/* Iterate the global resources and process each one */
2663 	for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
2664 		for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
2665 		      idx++) {
2666 			ent = &mapper_data->glb_res_tbl[dir][idx];
2667 			if (ent->resource_func ==
2668 			    BNXT_ULP_RESOURCE_FUNC_INVALID)
2669 				continue;
2670 			memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
2671 			res.resource_func = ent->resource_func;
2672 			res.direction = dir;
2673 			res.resource_type = ent->resource_type;
2674 			/*convert it from BE to cpu */
2675 			res.resource_hndl =
2676 				tfp_be_to_cpu_64(ent->resource_hndl);
2677 			ulp_mapper_resource_free(ulp_ctx, 0, &res);
2678 		}
2679 	}
2680 }
2681 
2682 int32_t
2683 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
2684 			enum bnxt_ulp_fdb_type flow_type,
2685 			uint32_t fid)
2686 {
2687 	int32_t rc;
2688 
2689 	if (!ulp_ctx) {
2690 		BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2691 		return -EINVAL;
2692 	}
2693 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
2694 		BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
2695 		return -EINVAL;
2696 	}
2697 
2698 	rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
2699 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
2700 	return rc;
2701 
2702 }
2703 
2704 /* Function to handle the default global templates that are allocated during
2705  * the startup and reused later.
2706  */
2707 static int32_t
2708 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
2709 {
2710 	uint32_t *glbl_tmpl_list;
2711 	uint32_t num_glb_tmpls, idx, dev_id;
2712 	struct bnxt_ulp_mapper_parms parms;
2713 	struct bnxt_ulp_mapper_data *mapper_data;
2714 	int32_t rc = 0;
2715 
2716 	glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
2717 	if (!glbl_tmpl_list || !num_glb_tmpls)
2718 		return rc; /* No global templates to process */
2719 
2720 	/* Get the device id from the ulp context */
2721 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
2722 		BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2723 		return -EINVAL;
2724 	}
2725 
2726 	mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2727 	if (!mapper_data) {
2728 		BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2729 		return -EINVAL;
2730 	}
2731 
2732 	/* Iterate the global resources and process each one */
2733 	for (idx = 0; idx < num_glb_tmpls; idx++) {
2734 		/* Initialize the parms structure */
2735 		memset(&parms, 0, sizeof(parms));
2736 		parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2737 		parms.ulp_ctx = ulp_ctx;
2738 		parms.dev_id = dev_id;
2739 		parms.mapper_data = mapper_data;
2740 		parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
2741 		parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
2742 
2743 		/* Get the class table entry from dev id and class id */
2744 		parms.class_tid = glbl_tmpl_list[idx];
2745 
2746 		parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2747 		if (!parms.device_params) {
2748 			BNXT_TF_DBG(ERR, "No device for device id %d\n",
2749 				    parms.dev_id);
2750 			return -EINVAL;
2751 		}
2752 
2753 		rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
2754 		if (rc)
2755 			return rc;
2756 	}
2757 	return rc;
2758 }
2759 
2760 /* Function to handle the mapping of the Flow to be compatible
2761  * with the underlying hardware.
2762  */
2763 int32_t
2764 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
2765 		       struct bnxt_ulp_mapper_create_parms *cparms,
2766 		       uint32_t *flowid)
2767 {
2768 	struct bnxt_ulp_mapper_parms parms;
2769 	struct ulp_regfile regfile;
2770 	int32_t	 rc, trc;
2771 
2772 	if (!ulp_ctx || !cparms)
2773 		return -EINVAL;
2774 
2775 	/* Initialize the parms structure */
2776 	memset(&parms, 0, sizeof(parms));
2777 	parms.act_prop = cparms->act_prop;
2778 	parms.act_bitmap = cparms->act;
2779 	parms.hdr_bitmap = cparms->hdr_bitmap;
2780 	parms.regfile = &regfile;
2781 	parms.hdr_field = cparms->hdr_field;
2782 	parms.comp_fld = cparms->comp_fld;
2783 	parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2784 	parms.ulp_ctx = ulp_ctx;
2785 	parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
2786 	parms.act_tid = cparms->act_tid;
2787 	parms.class_tid = cparms->class_tid;
2788 	parms.flow_type = cparms->flow_type;
2789 	parms.parent_flow = cparms->parent_flow;
2790 	parms.parent_fid = cparms->parent_fid;
2791 
2792 	/* Get the device id from the ulp context */
2793 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
2794 		BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2795 		return -EINVAL;
2796 	}
2797 
2798 	/* Get the device params, it will be used in later processing */
2799 	parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2800 	if (!parms.device_params) {
2801 		BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
2802 			    parms.dev_id);
2803 		return -EINVAL;
2804 	}
2805 
2806 	/*
2807 	 * Get the mapper data for dynamic mapper data such as default
2808 	 * ids.
2809 	 */
2810 	parms.mapper_data = (struct bnxt_ulp_mapper_data *)
2811 		bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2812 	if (!parms.mapper_data) {
2813 		BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2814 		return -EINVAL;
2815 	}
2816 
2817 	/* initialize the registry file for further processing */
2818 	if (!ulp_regfile_init(parms.regfile)) {
2819 		BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
2820 		return -EINVAL;
2821 	}
2822 
2823 	rc = ulp_regfile_write(parms.regfile,
2824 			       BNXT_ULP_REGFILE_INDEX_CLASS_TID,
2825 			       tfp_cpu_to_be_64((uint64_t)parms.class_tid));
2826 	if (!rc) {
2827 		BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
2828 		return -EINVAL;
2829 	}
2830 
2831 	/* Protect flow creation */
2832 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
2833 		BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
2834 		return -EINVAL;
2835 	}
2836 
2837 	/* Allocate a Flow ID for attaching all resources for the flow to.
2838 	 * Once allocated, all errors have to walk the list of resources and
2839 	 * free each of them.
2840 	 */
2841 	rc = ulp_flow_db_fid_alloc(ulp_ctx,
2842 				   parms.flow_type,
2843 				   cparms->func_id,
2844 				   &parms.fid);
2845 	if (rc) {
2846 		BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
2847 		bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
2848 		return rc;
2849 	}
2850 
2851 	if (parms.act_tid) {
2852 		parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
2853 		/* Process the action template tables */
2854 		rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
2855 		if (rc)
2856 			goto flow_error;
2857 	}
2858 
2859 	if (parms.class_tid) {
2860 		parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
2861 
2862 		/* Process the class template tables.*/
2863 		rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
2864 		if (rc)
2865 			goto flow_error;
2866 	}
2867 
2868 	/* setup the parent-child details */
2869 	if (parms.parent_flow) {
2870 		/* create a parent flow details */
2871 		rc = ulp_flow_db_parent_flow_create(&parms);
2872 		if (rc)
2873 			goto flow_error;
2874 	} else if (parms.parent_fid) {
2875 		/* create a child flow details */
2876 		rc = ulp_flow_db_child_flow_create(&parms);
2877 		if (rc)
2878 			goto flow_error;
2879 	}
2880 
2881 	*flowid = parms.fid;
2882 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
2883 
2884 	return rc;
2885 
2886 flow_error:
2887 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
2888 	/* Free all resources that were allocated during flow creation */
2889 	trc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
2890 				      parms.fid);
2891 	if (trc)
2892 		BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
2893 
2894 	return rc;
2895 }
2896 
2897 int32_t
2898 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
2899 {
2900 	struct bnxt_ulp_cache_tbl_params *tbl;
2901 	struct bnxt_ulp_mapper_data *data;
2902 	uint32_t i;
2903 	struct tf *tfp;
2904 	int32_t rc, csize;
2905 
2906 	if (!ulp_ctx)
2907 		return -EINVAL;
2908 
2909 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2910 	if (!tfp)
2911 		return -EINVAL;
2912 
2913 	data = rte_zmalloc("ulp_mapper_data",
2914 			   sizeof(struct bnxt_ulp_mapper_data), 0);
2915 	if (!data) {
2916 		BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
2917 		return -ENOMEM;
2918 	}
2919 
2920 	if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
2921 		BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
2922 		/* Don't call deinit since the prof_func wasn't allocated. */
2923 		rte_free(data);
2924 		return -ENOMEM;
2925 	}
2926 
2927 	/* Allocate the global resource ids */
2928 	rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
2929 	if (rc) {
2930 		BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
2931 		goto error;
2932 	}
2933 
2934 	/* Allocate the ulp cache tables. */
2935 	for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2936 		tbl = ulp_mapper_cache_tbl_params_get(i);
2937 		if (!tbl) {
2938 			BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)",
2939 				    i);
2940 			goto error;
2941 		}
2942 		if (tbl->num_entries != 0) {
2943 			csize = sizeof(struct bnxt_ulp_mapper_cache_entry) *
2944 				tbl->num_entries;
2945 			data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl",
2946 							 csize, 0);
2947 			if (!data->cache_tbl[i]) {
2948 				BNXT_TF_DBG(ERR, "Failed to allocate Cache "
2949 					    "table %d.\n", i);
2950 				rc = -ENOMEM;
2951 				goto error;
2952 			}
2953 		}
2954 	}
2955 
2956 	rc = ulp_mapper_glb_template_table_init(ulp_ctx);
2957 	if (rc) {
2958 		BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
2959 		goto error;
2960 	}
2961 
2962 	return 0;
2963 error:
2964 	/* Ignore the return code in favor of returning the original error. */
2965 	ulp_mapper_deinit(ulp_ctx);
2966 	return rc;
2967 }
2968 
2969 void
2970 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
2971 {
2972 	struct bnxt_ulp_mapper_data *data;
2973 	uint32_t i;
2974 	struct tf *tfp;
2975 
2976 	if (!ulp_ctx) {
2977 		BNXT_TF_DBG(ERR,
2978 			    "Failed to acquire ulp context, so data may "
2979 			    "not be released.\n");
2980 		return;
2981 	}
2982 
2983 	data = (struct bnxt_ulp_mapper_data *)
2984 		bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2985 	if (!data) {
2986 		/* Go ahead and return since there is no allocated data. */
2987 		BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
2988 		return;
2989 	}
2990 
2991 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2992 	if (!tfp) {
2993 		BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
2994 		/* Free the mapper data regardless of errors. */
2995 		goto free_mapper_data;
2996 	}
2997 
2998 	/* Free the global resource info table entries */
2999 	ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3000 
3001 free_mapper_data:
3002 	/* Free the ulp cache tables */
3003 	for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
3004 		rte_free(data->cache_tbl[i]);
3005 		data->cache_tbl[i] = NULL;
3006 	}
3007 
3008 	rte_free(data);
3009 	/* Reset the data pointer within the ulp_ctx. */
3010 	bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
3011 }
3012