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