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