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