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