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