net/bnxt: support flow template for Thor
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_mapper.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include "bnxt.h"
9 #include "ulp_template_db_enum.h"
10 #include "ulp_template_struct.h"
11 #include "bnxt_tf_common.h"
12 #include "ulp_utils.h"
13 #include "bnxt_ulp.h"
14 #include "tfp.h"
15 #include "tf_ext_flow_handle.h"
16 #include "ulp_mark_mgr.h"
17 #include "ulp_mapper.h"
18 #include "ulp_flow_db.h"
19 #include "tf_util.h"
20 #include "ulp_template_db_tbl.h"
21 #include "ulp_port_db.h"
22 #include "ulp_ha_mgr.h"
23 #include "bnxt_tf_pmd_shim.h"
24
25 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
26 #include "ulp_template_debug_proto.h"
27 #include "ulp_tf_debug.h"
28 #endif
29
30 static uint8_t mapper_fld_zeros[16] = { 0 };
31
32 static uint8_t mapper_fld_ones[16] = {
33         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
34         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
35 };
36
37 static uint8_t mapper_fld_one[16] = {
38         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
39         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
40 };
41
42 static const char *
43 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type)
44 {
45         switch (tmpl_type) {
46         case BNXT_ULP_TEMPLATE_TYPE_CLASS:
47                 return "class";
48         case BNXT_ULP_TEMPLATE_TYPE_ACTION:
49                 return "action";
50         default:
51                 return "invalid template type";
52         }
53 }
54
55 static struct bnxt_ulp_glb_resource_info *
56 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
57 {
58         if (!num_entries)
59                 return NULL;
60         *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
61         return ulp_glb_resource_tbl;
62 }
63
64 /*
65  * Read the global resource from the mapper global resource list
66  *
67  * The regval is always returned in big-endian.
68  *
69  * returns 0 on success
70  */
71 static int32_t
72 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
73                              enum tf_dir dir,
74                              uint16_t idx,
75                              uint64_t *regval,
76                              bool *shared)
77 {
78         if (!mapper_data || !regval || !shared ||
79             dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)
80                 return -EINVAL;
81
82         *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
83         *shared = mapper_data->glb_res_tbl[dir][idx].shared;
84         return 0;
85 }
86
87 /*
88  * Write a global resource to the mapper global resource list
89  *
90  * The regval value must be in big-endian.
91  *
92  * return 0 on success.
93  */
94 static int32_t
95 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
96                               struct bnxt_ulp_glb_resource_info *res,
97                               uint64_t regval, bool shared)
98 {
99         struct bnxt_ulp_mapper_glb_resource_entry *ent;
100
101         /* validate the arguments */
102         if (!data || res->direction >= TF_DIR_MAX ||
103             res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)
104                 return -EINVAL;
105
106         /* write to the mapper data */
107         ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
108         ent->resource_func = res->resource_func;
109         ent->resource_type = res->resource_type;
110         ent->resource_hndl = regval;
111         ent->shared = shared;
112         return 0;
113 }
114
115 /*
116  * Internal function to allocate identity resource and store it in mapper data.
117  *
118  * returns 0 on success
119  */
120 static int32_t
121 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
122                                    struct bnxt_ulp_mapper_data *mapper_data,
123                                    struct bnxt_ulp_glb_resource_info *glb_res)
124 {
125         struct tf_alloc_identifier_parms iparms = { 0 };
126         struct tf_free_identifier_parms fparms;
127         uint64_t regval;
128         struct tf *tfp;
129         int32_t rc = 0;
130
131         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
132         if (!tfp)
133                 return -EINVAL;
134
135         iparms.ident_type = glb_res->resource_type;
136         iparms.dir = glb_res->direction;
137
138         /* Allocate the Identifier using tf api */
139         rc = tf_alloc_identifier(tfp, &iparms);
140         if (rc) {
141                 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
142                             tf_dir_2_str(iparms.dir),
143                             iparms.ident_type);
144                 return rc;
145         }
146
147         /* entries are stored as big-endian format */
148         regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
149         /*
150          * write to the mapper global resource
151          * Shared resources are never allocated through this method, so the
152          * shared flag is always false.
153          */
154         rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false);
155         if (rc) {
156                 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
157                 /* Free the identifier when update failed */
158                 fparms.dir = iparms.dir;
159                 fparms.ident_type = iparms.ident_type;
160                 fparms.id = iparms.id;
161                 tf_free_identifier(tfp, &fparms);
162                 return rc;
163         }
164 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
165 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
166         BNXT_TF_DBG(DEBUG, "Allocated Glb Res Ident [%s][%d][%d] = 0x%04x\n",
167                     tf_dir_2_str(iparms.dir),
168                     glb_res->glb_regfile_index, iparms.ident_type, iparms.id);
169 #endif
170 #endif
171         return rc;
172 }
173
174 /*
175  * Internal function to allocate index tbl resource and store it in mapper data.
176  *
177  * returns 0 on success
178  */
179 static int32_t
180 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
181                                     struct bnxt_ulp_mapper_data *mapper_data,
182                                     struct bnxt_ulp_glb_resource_info *glb_res)
183 {
184         struct tf_alloc_tbl_entry_parms aparms = { 0 };
185         struct tf_free_tbl_entry_parms  free_parms = { 0 };
186         uint64_t regval;
187         struct tf *tfp;
188         uint32_t tbl_scope_id;
189         int32_t rc = 0;
190
191         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
192         if (!tfp)
193                 return -EINVAL;
194
195         /* Get the scope id */
196         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
197         if (rc) {
198                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
199                 return rc;
200         }
201
202         aparms.type = glb_res->resource_type;
203         aparms.dir = glb_res->direction;
204         aparms.tbl_scope_id = tbl_scope_id;
205
206         /* Allocate the index tbl using tf api */
207         rc = tf_alloc_tbl_entry(tfp, &aparms);
208         if (rc) {
209                 BNXT_TF_DBG(ERR, "Failed to alloc index table [%s][%d]\n",
210                             tf_dir_2_str(aparms.dir), aparms.type);
211                 return rc;
212         }
213
214         /* entries are stored as big-endian format */
215         regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
216         /*
217          * write to the mapper global resource
218          * Shared resources are never allocated through this method, so the
219          * shared flag is always false.
220          */
221         rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false);
222         if (rc) {
223                 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
224                 /* Free the identifier when update failed */
225                 free_parms.dir = aparms.dir;
226                 free_parms.type = aparms.type;
227                 free_parms.idx = aparms.idx;
228                 tf_free_tbl_entry(tfp, &free_parms);
229                 return rc;
230         }
231 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
232 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
233         BNXT_TF_DBG(DEBUG, "Allocated Glb Res Index [%s][%d][%d] = 0x%04x\n",
234                     tf_dir_2_str(aparms.dir),
235                     glb_res->glb_regfile_index, aparms.type, aparms.idx);
236 #endif
237 #endif
238         return rc;
239 }
240
241 static int32_t
242 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
243                              uint32_t operand,
244                              uint8_t *val)
245 {
246         uint32_t t_idx;
247
248         t_idx = parms->app_id << (BNXT_ULP_APP_ID_SHIFT +
249                                   BNXT_ULP_HDR_SIG_ID_SHIFT +
250                                   BNXT_ULP_GLB_FIELD_TBL_SHIFT);
251         t_idx += parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
252                                       BNXT_ULP_GLB_FIELD_TBL_SHIFT);
253         t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
254                 BNXT_ULP_GLB_FIELD_TBL_SHIFT;
255         t_idx += operand;
256
257         if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
258                 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
259                             parms->class_tid, t_idx, operand);
260                 *val = 0;
261                 return -EINVAL; /* error */
262         }
263         *val = ulp_glb_field_tbl[t_idx];
264         return 0;
265 }
266
267 /*
268  * Get the size of the action property for a given index.
269  *
270  * idx [in] The index for the action property
271  *
272  * returns the size of the action property.
273  */
274 static uint32_t
275 ulp_mapper_act_prop_size_get(uint32_t idx)
276 {
277         if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
278                 return 0;
279         return ulp_act_prop_map_table[idx];
280 }
281
282 static struct bnxt_ulp_mapper_cond_info *
283 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
284                                 uint32_t tid,
285                                 uint32_t *num_tbls,
286                                 enum bnxt_ulp_cond_list_opc *opc)
287 {
288         uint32_t idx;
289         const struct bnxt_ulp_template_device_tbls *dev_tbls;
290
291         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
292         *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
293         *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
294         idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
295
296         return &dev_tbls->cond_list[idx];
297 }
298
299 static struct bnxt_ulp_mapper_cond_info *
300 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
301                                 struct bnxt_ulp_mapper_tbl_info *tbl,
302                                 uint32_t *num_tbls,
303                                 enum bnxt_ulp_cond_list_opc *opc)
304 {
305         uint32_t idx;
306         const struct bnxt_ulp_template_device_tbls *dev_tbls;
307
308         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
309         *num_tbls = tbl->execute_info.cond_nums;
310         *opc = tbl->execute_info.cond_list_opcode;
311         idx = tbl->execute_info.cond_start_idx;
312
313         return &dev_tbls->cond_list[idx];
314 }
315
316 /*
317  * Get a list of classifier tables that implement the flow
318  * Gets a device dependent list of tables that implement the class template id
319  *
320  * mparms [in] The mappers parms with data related to the flow.
321  *
322  * tid [in] The template id that matches the flow
323  *
324  * num_tbls [out] The number of classifier tables in the returned array
325  *
326  * returns An array of classifier tables to implement the flow, or NULL on
327  * error
328  */
329 static struct bnxt_ulp_mapper_tbl_info *
330 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
331                         uint32_t tid,
332                         uint32_t *num_tbls)
333 {
334         uint32_t idx;
335         const struct bnxt_ulp_template_device_tbls *dev_tbls;
336
337         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
338
339         idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
340         *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
341
342         return &dev_tbls->tbl_list[idx];
343 }
344
345 /*
346  * Get the list of key fields that implement the flow.
347  *
348  * mparms [in] The mapper parms with information about the flow
349  *
350  * tbl [in] A single table instance to get the key fields from
351  *
352  * num_flds [out] The number of key fields in the returned array
353  *
354  * Returns array of Key fields, or NULL on error.
355  */
356 static struct bnxt_ulp_mapper_key_info *
357 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
358                           struct bnxt_ulp_mapper_tbl_info *tbl,
359                           uint32_t *num_flds)
360 {
361         uint32_t idx;
362         const struct bnxt_ulp_template_device_tbls *dev_tbls;
363
364         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
365         if (!dev_tbls->key_info_list) {
366                 *num_flds = 0;
367                 return NULL;
368         }
369
370         idx             = tbl->key_start_idx;
371         *num_flds       = tbl->key_num_fields;
372
373         return &dev_tbls->key_info_list[idx];
374 }
375
376 /*
377  * Get the list of data fields that implement the flow.
378  *
379  * mparms [in] The mapper parms with information about the flow
380  *
381  * tbl [in] A single table instance to get the data fields from
382  *
383  * num_flds [out] The number of data fields in the returned array.
384  *
385  * num_encap_flds [out] The number of encap fields in the returned array.
386  *
387  * Returns array of data fields, or NULL on error.
388  */
389 static struct bnxt_ulp_mapper_field_info *
390 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
391                              struct bnxt_ulp_mapper_tbl_info *tbl,
392                              uint32_t *num_flds,
393                              uint32_t *num_encap_flds)
394 {
395         uint32_t idx;
396         const struct bnxt_ulp_template_device_tbls *dev_tbls;
397
398         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
399         if (!dev_tbls->result_field_list) {
400                 *num_flds = 0;
401                 *num_encap_flds = 0;
402                 return NULL;
403         }
404
405         idx             = tbl->result_start_idx;
406         *num_flds       = tbl->result_num_fields;
407         *num_encap_flds = tbl->encap_num_fields;
408
409         return &dev_tbls->result_field_list[idx];
410 }
411
412 /*
413  * Get the list of ident fields that implement the flow
414  *
415  * tbl [in] A single table instance to get the ident fields from
416  *
417  * num_flds [out] The number of ident fields in the returned array
418  *
419  * returns array of ident fields, or NULL on error
420  */
421 static struct bnxt_ulp_mapper_ident_info *
422 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
423                             struct bnxt_ulp_mapper_tbl_info *tbl,
424                             uint32_t *num_flds)
425 {
426         uint32_t idx;
427         const struct bnxt_ulp_template_device_tbls *dev_tbls;
428
429         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
430         if (!dev_tbls->ident_list) {
431                 *num_flds = 0;
432                 return NULL;
433         }
434
435         idx = tbl->ident_start_idx;
436         *num_flds = tbl->ident_nums;
437
438         return &dev_tbls->ident_list[idx];
439 }
440
441 static inline int32_t
442 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp,
443                            struct tf *tfp,
444                            struct ulp_flow_db_res_params *res)
445 {
446         struct tf_free_tcam_entry_parms fparms = {
447                 .dir            = res->direction,
448                 .tcam_tbl_type  = res->resource_type,
449                 .idx            = (uint16_t)res->resource_hndl
450         };
451
452         /* If HA is enabled, we may have to remap the TF Type */
453         if (bnxt_ulp_cntxt_ha_enabled(ulp)) {
454                 enum ulp_ha_mgr_region region;
455                 int32_t rc;
456
457                 switch (res->resource_type) {
458                 case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH:
459                 case TF_TCAM_TBL_TYPE_WC_TCAM_LOW:
460                         rc = ulp_ha_mgr_region_get(ulp, &region);
461                         if (rc)
462                                 /* Log this, but assume region is correct */
463                                 BNXT_TF_DBG(ERR,
464                                             "Unable to get HA region (%d)\n",
465                                             rc);
466                         else
467                                 fparms.tcam_tbl_type =
468                                         (region == ULP_HA_REGION_LOW) ?
469                                         TF_TCAM_TBL_TYPE_WC_TCAM_LOW :
470                                         TF_TCAM_TBL_TYPE_WC_TCAM_HIGH;
471                         break;
472                 default:
473                         break;
474                 }
475         }
476         return tf_free_tcam_entry(tfp, &fparms);
477 }
478
479 static inline int32_t
480 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
481                             struct tf *tfp,
482                             struct ulp_flow_db_res_params *res)
483 {
484         struct tf_free_tbl_entry_parms fparms = {
485                 .dir    = res->direction,
486                 .type   = res->resource_type,
487                 .idx    = (uint32_t)res->resource_hndl
488         };
489
490         /*
491          * Just get the table scope, it will be ignored if not necessary
492          * by the tf_free_tbl_entry
493          */
494         (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
495
496         return tf_free_tbl_entry(tfp, &fparms);
497 }
498
499 static inline int32_t
500 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
501                          struct tf *tfp,
502                          struct ulp_flow_db_res_params *res)
503 {
504         struct tf_delete_em_entry_parms fparms = { 0 };
505         int32_t rc;
506
507         fparms.dir              = res->direction;
508         fparms.flow_handle      = res->resource_hndl;
509
510         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
511         if (rc) {
512                 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
513                 return -EINVAL;
514         }
515
516         return tf_delete_em_entry(tfp, &fparms);
517 }
518
519 static inline int32_t
520 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
521                       struct tf *tfp,
522                       struct ulp_flow_db_res_params *res)
523 {
524         struct tf_free_identifier_parms fparms = {
525                 .dir            = res->direction,
526                 .ident_type     = res->resource_type,
527                 .id             = (uint16_t)res->resource_hndl
528         };
529
530         return tf_free_identifier(tfp, &fparms);
531 }
532
533 static inline int32_t
534 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
535                      struct ulp_flow_db_res_params *res)
536 {
537         return ulp_mark_db_mark_del(ulp,
538                                     res->resource_type,
539                                     res->resource_hndl);
540 }
541
542 static inline int32_t
543 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
544                             uint32_t parent_fid,
545                             struct ulp_flow_db_res_params *res)
546 {
547         uint32_t idx, child_fid = 0, parent_idx;
548         struct bnxt_ulp_flow_db *flow_db;
549
550         parent_idx = (uint32_t)res->resource_hndl;
551
552         /* check the validity of the parent fid */
553         if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
554             idx != parent_idx) {
555                 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
556                 return -EINVAL;
557         }
558
559         /* Clear all the child flows parent index */
560         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
561         while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
562                                                              &child_fid)) {
563                 /* update the child flows resource handle */
564                 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
565                                                  child_fid)) {
566                         BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
567                                     child_fid);
568                         return -EINVAL;
569                 }
570         }
571
572         /* free the parent entry in the parent table flow */
573         if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
574                 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
575                 return -EINVAL;
576         }
577         return 0;
578 }
579
580 static inline int32_t
581 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
582                            uint32_t child_fid,
583                            struct ulp_flow_db_res_params *res)
584 {
585         uint32_t parent_fid;
586
587         parent_fid = (uint32_t)res->resource_hndl;
588         if (!parent_fid)
589                 return 0; /* Already freed - orphan child*/
590
591         /* reset the child flow bitset*/
592         if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
593                 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
594                             parent_fid, child_fid);
595                 return -EINVAL;
596         }
597         return 0;
598 }
599
600 /*
601  * Process the flow database opcode alloc action.
602  * returns 0 on success
603  */
604 static int32_t
605 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
606                              struct bnxt_ulp_mapper_tbl_info *tbl)
607 {
608         uint32_t rid = 0;
609         uint64_t val64;
610         int32_t rc = 0;
611
612         /* allocate a new fid */
613         rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
614                                    BNXT_ULP_FDB_TYPE_RID,
615                                    0, &rid);
616         if (rc) {
617                 BNXT_TF_DBG(ERR,
618                             "Unable to allocate flow table entry\n");
619                 return -EINVAL;
620         }
621         /* Store the allocated fid in regfile*/
622         val64 = rid;
623         rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
624                                tfp_cpu_to_be_64(val64));
625         if (rc) {
626                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
627                             tbl->fdb_operand);
628                 ulp_flow_db_fid_free(parms->ulp_ctx,
629                                      BNXT_ULP_FDB_TYPE_RID, rid);
630                 return -EINVAL;
631         }
632         return 0;
633 }
634
635 /*
636  * Process the flow database opcode action.
637  * returns 0 on success.
638  */
639 static int32_t
640 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
641                            struct bnxt_ulp_mapper_tbl_info *tbl,
642                            struct ulp_flow_db_res_params *fid_parms)
643 {
644         uint32_t push_fid;
645         uint64_t val64;
646         enum bnxt_ulp_fdb_type flow_type;
647         int32_t rc = 0;
648
649         switch (tbl->fdb_opcode) {
650         case BNXT_ULP_FDB_OPC_PUSH_FID:
651                 push_fid = parms->fid;
652                 flow_type = parms->flow_type;
653                 break;
654         case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
655                 /* get the fid from the regfile */
656                 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
657                                       &val64);
658                 if (!rc) {
659                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
660                                     tbl->fdb_operand);
661                         return -EINVAL;
662                 }
663                 /* Use the extracted fid to update the flow resource */
664                 push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
665                 flow_type = BNXT_ULP_FDB_TYPE_RID;
666                 break;
667         default:
668                 return rc; /* Nothing to be done */
669         }
670
671         /* Add the resource to the flow database */
672         rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
673                                       push_fid, fid_parms);
674         if (rc)
675                 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
676                             push_fid, rc);
677         return rc;
678 }
679
680 /*
681  * Process the flow database opcode action.
682  * returns 0 on success.
683  */
684 static int32_t
685 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
686                                 struct bnxt_ulp_mapper_tbl_info *tbl,
687                                 uint32_t *priority)
688 {
689         int32_t rc = 0;
690
691         switch (tbl->pri_opcode) {
692         case BNXT_ULP_PRI_OPC_NOT_USED:
693                 *priority = 0;
694                 break;
695         case BNXT_ULP_PRI_OPC_CONST:
696                 *priority = tbl->pri_operand;
697                 break;
698         case BNXT_ULP_PRI_OPC_APP_PRI:
699                 *priority = parms->app_priority;
700                 break;
701         default:
702                 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
703                             tbl->pri_opcode);
704                 rc = -EINVAL;
705                 break;
706         }
707         return rc;
708 }
709
710 /*
711  * Process the identifier list in the given table.
712  * Extract the ident from the table entry and
713  * write it to the reg file.
714  * returns 0 on success.
715  */
716 static int32_t
717 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
718                               struct bnxt_ulp_mapper_tbl_info *tbl,
719                               uint8_t *byte_data,
720                               uint32_t byte_data_size,
721                               enum bnxt_ulp_byte_order byte_order)
722 {
723         struct bnxt_ulp_mapper_ident_info *idents;
724         uint32_t i, num_idents = 0;
725         uint64_t val64;
726
727         /* validate the null arguments */
728         if (!byte_data) {
729                 BNXT_TF_DBG(ERR, "invalid argument\n");
730                 return -EINVAL;
731         }
732
733         /* Get the ident list and process each one */
734         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
735
736         for (i = 0; i < num_idents; i++) {
737                 /* check the size of the buffer for validation */
738                 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
739                     ULP_BYTE_2_BITS(byte_data_size) ||
740                     idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
741                         BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
742                                     idents[i].ident_bit_pos,
743                                     idents[i].ident_bit_size,
744                                     byte_data_size);
745                         return -EINVAL;
746                 }
747                 val64 = 0;
748                 if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
749                         ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
750                                         sizeof(val64),
751                                         idents[i].ident_bit_pos,
752                                         idents[i].ident_bit_size);
753                 else
754                         ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
755                                         idents[i].ident_bit_pos,
756                                         idents[i].ident_bit_size);
757
758                 /* Write it to the regfile, val64 is already in big-endian*/
759                 if (ulp_regfile_write(parms->regfile,
760                                       idents[i].regfile_idx, val64)) {
761                         BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
762                                     idents[i].regfile_idx);
763                         return -EINVAL;
764                 }
765         }
766         return 0;
767 }
768
769 /*
770  * Process the identifier instruction and either store it in the flow database
771  * or return it in the val (if not NULL) on success.  If val is NULL, the
772  * identifier is to be stored in the flow database.
773  */
774 static int32_t
775 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
776                          struct bnxt_ulp_mapper_tbl_info *tbl,
777                          struct bnxt_ulp_mapper_ident_info *ident,
778                          uint16_t *val)
779 {
780         struct ulp_flow_db_res_params   fid_parms;
781         uint64_t id = 0;
782         int32_t idx;
783         struct tf_alloc_identifier_parms iparms = { 0 };
784         struct tf_free_identifier_parms free_parms = { 0 };
785         struct tf *tfp;
786         int rc;
787
788         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
789         if (!tfp) {
790                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
791                 return -EINVAL;
792         }
793
794         idx = ident->regfile_idx;
795
796         iparms.ident_type = ident->ident_type;
797         iparms.dir = tbl->direction;
798
799         rc = tf_alloc_identifier(tfp, &iparms);
800         if (rc) {
801                 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
802                             tf_dir_2_str(iparms.dir),
803                             tf_ident_2_str(iparms.ident_type));
804                 return rc;
805         }
806         BNXT_TF_INF("Alloc ident %s:%s.success.\n",
807                     tf_dir_2_str(iparms.dir),
808                     tf_ident_2_str(iparms.ident_type));
809
810         id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
811         if (ulp_regfile_write(parms->regfile, idx, id)) {
812                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
813                 rc = -EINVAL;
814                 /* Need to free the identifier, so goto error */
815                 goto error;
816         }
817
818         /* Link the resource to the flow in the flow db */
819         if (!val) {
820                 memset(&fid_parms, 0, sizeof(fid_parms));
821                 fid_parms.direction             = tbl->direction;
822                 fid_parms.resource_func = ident->resource_func;
823                 fid_parms.resource_type = ident->ident_type;
824                 fid_parms.resource_hndl = iparms.id;
825                 fid_parms.critical_resource = tbl->critical_resource;
826                 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
827
828                 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
829                 if (rc) {
830                         BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
831                                     rc);
832                         /* Need to free the identifier, so goto error */
833                         goto error;
834                 }
835         } else {
836                 *val = iparms.id;
837         }
838 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
839 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
840         ulp_mapper_ident_field_dump("Ident", ident, tbl, iparms.id);
841 #endif
842 #endif
843         return 0;
844
845 error:
846         /* Need to free the identifier */
847         free_parms.dir          = tbl->direction;
848         free_parms.ident_type   = ident->ident_type;
849         free_parms.id           = iparms.id;
850
851         (void)tf_free_identifier(tfp, &free_parms);
852
853         BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
854                     ident->description,
855                     tf_dir_2_str(tbl->direction));
856         return rc;
857 }
858
859 /*
860  * Process the identifier instruction and extract it from result blob.
861  * Increment the identifier reference count and store it in the flow database.
862  */
863 static int32_t
864 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
865                          struct bnxt_ulp_mapper_tbl_info *tbl,
866                          struct bnxt_ulp_mapper_ident_info *ident,
867                          struct ulp_blob *res_blob)
868 {
869         struct ulp_flow_db_res_params   fid_parms;
870         uint64_t id = 0;
871         uint32_t idx = 0;
872         struct tf_search_identifier_parms sparms = { 0 };
873         struct tf_free_identifier_parms free_parms = { 0 };
874         struct tf *tfp;
875         int rc;
876
877         /* Get the tfp from ulp context */
878         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
879         if (!tfp) {
880                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
881                 return -EINVAL;
882         }
883
884         /* Extract the index from the result blob */
885         rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
886                            ident->ident_bit_pos, ident->ident_bit_size);
887         if (rc) {
888                 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
889                 return -EIO;
890         }
891
892         /* populate the search params and search identifier shadow table */
893         sparms.ident_type = ident->ident_type;
894         sparms.dir = tbl->direction;
895         /* convert the idx into cpu format */
896         sparms.search_id = tfp_be_to_cpu_32(idx);
897
898         /* Search identifier also increase the reference count */
899         rc = tf_search_identifier(tfp, &sparms);
900         if (rc) {
901                 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
902                             tf_dir_2_str(sparms.dir),
903                             tf_ident_2_str(sparms.ident_type),
904                             sparms.search_id);
905                 return rc;
906         }
907         BNXT_TF_INF("Search ident %s:%s:%x.success.\n",
908                     tf_dir_2_str(sparms.dir),
909                     tf_tbl_type_2_str(sparms.ident_type),
910                     sparms.search_id);
911
912         /* Write it to the regfile */
913         id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
914         if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
915                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
916                 rc = -EINVAL;
917                 /* Need to free the identifier, so goto error */
918                 goto error;
919         }
920
921         /* Link the resource to the flow in the flow db */
922         memset(&fid_parms, 0, sizeof(fid_parms));
923         fid_parms.direction = tbl->direction;
924         fid_parms.resource_func = ident->resource_func;
925         fid_parms.resource_type = ident->ident_type;
926         fid_parms.resource_hndl = sparms.search_id;
927         fid_parms.critical_resource = tbl->critical_resource;
928         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
929
930         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
931         if (rc) {
932                 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
933                             rc);
934                 /* Need to free the identifier, so goto error */
935                 goto error;
936         }
937
938 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
939 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
940         ulp_mapper_ident_field_dump("Ident", ident, tbl, sparms.search_id);
941 #endif
942 #endif
943         return 0;
944
945 error:
946         /* Need to free the identifier */
947         free_parms.dir = tbl->direction;
948         free_parms.ident_type = ident->ident_type;
949         free_parms.id = sparms.search_id;
950         (void)tf_free_identifier(tfp, &free_parms);
951         BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
952                     ident->description,
953                     tf_dir_2_str(tbl->direction), sparms.search_id);
954         return rc;
955 }
956
957 static int32_t
958 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
959                                  uint32_t port_id,
960                                  uint16_t val16,
961                                  uint8_t **val)
962 {
963         enum bnxt_ulp_port_table port_data = val16;
964
965         switch (port_data) {
966         case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
967                 if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
968                                                     val)) {
969                         BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
970                         return -EINVAL;
971                 }
972                 break;
973         case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC:
974                 if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id,
975                                                  val)) {
976                         BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
977                         return -EINVAL;
978                 }
979                 break;
980         case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC:
981                 if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id,
982                                                 val)) {
983                         BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
984                         return -EINVAL;
985                 }
986                 break;
987         default:
988                 BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data);
989                 return -EINVAL;
990         }
991         return 0;
992 }
993
994 static int32_t
995 ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms,
996                              enum bnxt_ulp_field_src field_src,
997                              uint8_t *field_opr,
998                              enum tf_dir dir,
999                              uint8_t is_key,
1000                              uint32_t bitlen,
1001                              uint8_t **val,
1002                              uint32_t *val_len,
1003                              uint64_t *value)
1004 {
1005         struct bnxt_ulp_mapper_data *m;
1006         uint8_t bit;
1007         uint32_t port_id, val_size, field_size;
1008         uint16_t idx, size_idx, offset;
1009         uint32_t bytelen = ULP_BITS_2_BYTE(bitlen);
1010         uint8_t *buffer;
1011         uint64_t lregval;
1012         bool shared;
1013
1014         *val_len = bitlen;
1015         *value = 0;
1016         /* Perform the action */
1017         switch (field_src) {
1018         case BNXT_ULP_FIELD_SRC_ZERO:
1019                 *val = mapper_fld_zeros;
1020                 break;
1021         case BNXT_ULP_FIELD_SRC_CONST:
1022                 *val = field_opr;
1023                 break;
1024         case BNXT_ULP_FIELD_SRC_ONES:
1025                 *val = mapper_fld_ones;
1026                 *value = 1;
1027                 break;
1028         case BNXT_ULP_FIELD_SRC_CF:
1029                 if (!ulp_operand_read(field_opr,
1030                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1031                         BNXT_TF_DBG(ERR, "CF operand read failed\n");
1032                         return -EINVAL;
1033                 }
1034                 idx = tfp_be_to_cpu_16(idx);
1035                 if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint32_t)) {
1036                         BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx,
1037                                     bytelen);
1038                         return -EINVAL;
1039                 }
1040                 buffer = (uint8_t *)&parms->comp_fld[idx];
1041                 *val = &buffer[sizeof(uint64_t) - bytelen];
1042                 *value = ULP_COMP_FLD_IDX_RD(parms, idx);
1043                 break;
1044         case BNXT_ULP_FIELD_SRC_RF:
1045                 if (!ulp_operand_read(field_opr,
1046                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1047                         BNXT_TF_DBG(ERR, "RF operand read failed\n");
1048                         return -EINVAL;
1049                 }
1050
1051                 idx = tfp_be_to_cpu_16(idx);
1052                 /* Uninitialized regfile entries return 0 */
1053                 if (!ulp_regfile_read(parms->regfile, idx, &lregval) ||
1054                     sizeof(uint64_t) < bytelen) {
1055                         BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx,
1056                                     bytelen);
1057                         return -EINVAL;
1058                 }
1059                 buffer = (uint8_t *)&parms->regfile->entry[idx].data;
1060                 *val = &buffer[sizeof(uint64_t) - bytelen];
1061                 *value = tfp_be_to_cpu_64(lregval);
1062                 break;
1063         case BNXT_ULP_FIELD_SRC_ACT_PROP:
1064                 if (!ulp_operand_read(field_opr,
1065                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1066                         BNXT_TF_DBG(ERR, "Action operand read failed\n");
1067                         return -EINVAL;
1068                 }
1069                 idx = tfp_be_to_cpu_16(idx);
1070                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1071                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
1072                         return -EINVAL;
1073                 }
1074                 buffer = &parms->act_prop->act_details[idx];
1075                 field_size = ulp_mapper_act_prop_size_get(idx);
1076                 if (bytelen > field_size) {
1077                         BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n",
1078                                     idx, field_size);
1079                         return -EINVAL;
1080                 }
1081                 *val = &buffer[field_size - bytelen];
1082                 break;
1083         case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1084                 if (!ulp_operand_read(field_opr,
1085                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1086                         BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1087                         return -EINVAL;
1088                 }
1089                 idx = tfp_be_to_cpu_16(idx);
1090
1091                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1092                         BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx);
1093                         return -EINVAL;
1094                 }
1095                 *val = &parms->act_prop->act_details[idx];
1096
1097                 /* get the size index next */
1098                 if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1099                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
1100                         BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1101                         return -EINVAL;
1102                 }
1103                 size_idx = tfp_be_to_cpu_16(size_idx);
1104                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1105                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1106                         return -EINVAL;
1107                 }
1108                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1109                        sizeof(uint32_t));
1110                 val_size = tfp_be_to_cpu_32(val_size);
1111                 *val_len = ULP_BYTE_2_BITS(val_size);
1112                 break;
1113         case BNXT_ULP_FIELD_SRC_GLB_RF:
1114                 if (!ulp_operand_read(field_opr,
1115                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1116                         BNXT_TF_DBG(ERR, "Global regfile read failed\n");
1117                         return -EINVAL;
1118                 }
1119                 idx = tfp_be_to_cpu_16(idx);
1120                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1121                                                  dir, idx, &lregval, &shared) ||
1122                     sizeof(uint64_t) < bytelen) {
1123                         BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n",
1124                                     idx, bytelen);
1125                         return -EINVAL;
1126                 }
1127                 m = parms->mapper_data;
1128                 buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl;
1129                 *val = &buffer[sizeof(uint64_t) - bytelen];
1130                 *value = tfp_be_to_cpu_64(lregval);
1131                 break;
1132         case BNXT_ULP_FIELD_SRC_HF:
1133         case BNXT_ULP_FIELD_SRC_SUB_HF:
1134                 if (!ulp_operand_read(field_opr,
1135                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1136                         BNXT_TF_DBG(ERR, "Header field read failed\n");
1137                         return -EINVAL;
1138                 }
1139                 idx = tfp_be_to_cpu_16(idx);
1140                 /* get the index from the global field list */
1141                 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1142                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1143                                     idx);
1144                         return -EINVAL;
1145                 }
1146                 if (is_key)
1147                         buffer = parms->hdr_field[bit].spec;
1148                 else
1149                         buffer = parms->hdr_field[bit].mask;
1150
1151                 field_size = parms->hdr_field[bit].size;
1152                 if (bytelen > field_size) {
1153                         BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n",
1154                                     bit, field_size);
1155                         return -EINVAL;
1156                 }
1157                 if (field_src == BNXT_ULP_FIELD_SRC_HF) {
1158                         *val = &buffer[field_size - bytelen];
1159                 } else {
1160                         /* get the offset next */
1161                         if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1162                                               (uint8_t *)&offset,
1163                                               sizeof(uint16_t))) {
1164                                 BNXT_TF_DBG(ERR, "Hdr fld size read failed\n");
1165                                 return -EINVAL;
1166                         }
1167                         offset = tfp_be_to_cpu_16(offset);
1168                         offset = ULP_BITS_2_BYTE_NR(offset);
1169                         if ((offset + bytelen) > field_size) {
1170                                 BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit);
1171                                 return -EINVAL;
1172                         }
1173                         *val = &buffer[offset];
1174                 }
1175                 break;
1176         case BNXT_ULP_FIELD_SRC_HDR_BIT:
1177                 if (!ulp_operand_read(field_opr,
1178                                       (uint8_t *)&lregval, sizeof(uint64_t))) {
1179                         BNXT_TF_DBG(ERR, "Header bit read failed\n");
1180                         return -EINVAL;
1181                 }
1182                 lregval = tfp_be_to_cpu_64(lregval);
1183                 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) {
1184                         *val = mapper_fld_one;
1185                         *value = 1;
1186                 } else {
1187                         *val = mapper_fld_zeros;
1188                 }
1189                 break;
1190         case BNXT_ULP_FIELD_SRC_ACT_BIT:
1191                 if (!ulp_operand_read(field_opr,
1192                                       (uint8_t *)&lregval, sizeof(uint64_t))) {
1193                         BNXT_TF_DBG(ERR, "Action bit read failed\n");
1194                         return -EINVAL;
1195                 }
1196                 lregval = tfp_be_to_cpu_64(lregval);
1197                 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) {
1198                         *val = mapper_fld_one;
1199                         *value = 1;
1200                 } else {
1201                         *val = mapper_fld_zeros;
1202                 }
1203                 break;
1204         case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1205                 if (!ulp_operand_read(field_opr,
1206                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1207                         BNXT_TF_DBG(ERR, "Field bit read failed\n");
1208                         return -EINVAL;
1209                 }
1210                 idx = tfp_be_to_cpu_16(idx);
1211                 /* get the index from the global field list */
1212                 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1213                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1214                                     idx);
1215                         return -EINVAL;
1216                 }
1217                 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) {
1218                         *val = mapper_fld_one;
1219                         *value = 1;
1220                 } else {
1221                         *val = mapper_fld_zeros;
1222                 }
1223                 break;
1224         case BNXT_ULP_FIELD_SRC_PORT_TABLE:
1225                 /* The port id is present in the comp field list */
1226                 port_id = ULP_COMP_FLD_IDX_RD(parms,
1227                                               BNXT_ULP_CF_IDX_DEV_PORT_ID);
1228                 /* get the port table enum  */
1229                 if (!ulp_operand_read(field_opr,
1230                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1231                         BNXT_TF_DBG(ERR, "Port table enum read failed\n");
1232                         return -EINVAL;
1233                 }
1234                 idx = tfp_be_to_cpu_16(idx);
1235                 if (ulp_mapper_field_port_db_process(parms, port_id, idx,
1236                                                      val)) {
1237                         BNXT_TF_DBG(ERR, "field port table failed\n");
1238                         return -EINVAL;
1239                 }
1240         case BNXT_ULP_FIELD_SRC_SKIP:
1241                 /* do nothing */
1242                 break;
1243         case BNXT_ULP_FIELD_SRC_REJECT:
1244                 return -EINVAL;
1245         default:
1246                 BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src);
1247                 return -EINVAL;
1248         }
1249         return 0;
1250 }
1251
1252 static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen,
1253                                             uint64_t *output)
1254 {
1255         uint16_t val_16;
1256         uint32_t val_32;
1257         uint64_t val_64;
1258         uint32_t bytelen;
1259
1260         bytelen = ULP_BITS_2_BYTE(bitlen);
1261         if (bytelen == sizeof(uint8_t)) {
1262                 *output = *((uint8_t *)buffer);
1263         } else if (bytelen == sizeof(uint16_t)) {
1264                 val_16 = *((uint16_t *)buffer);
1265                 *output =  tfp_be_to_cpu_16(val_16);
1266         } else if (bytelen == sizeof(uint32_t)) {
1267                 val_32 = *((uint32_t *)buffer);
1268                 *output =  tfp_be_to_cpu_32(val_32);
1269         } else if (bytelen == sizeof(val_64)) {
1270                 val_64 = *((uint64_t *)buffer);
1271                 *output =  tfp_be_to_cpu_64(val_64);
1272         } else {
1273                 *output = 0;
1274                 return -EINVAL;
1275         }
1276         return 0;
1277 }
1278
1279 static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src,
1280                                            struct ulp_blob *blob,
1281                                            uint8_t *val,
1282                                            uint32_t val_len,
1283                                            uint8_t **out_val)
1284 {
1285         if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) {
1286                 if (ulp_blob_pad_push(blob, val_len) < 0) {
1287                         BNXT_TF_DBG(ERR, "too large for blob\n");
1288                         return -EINVAL;
1289                 }
1290         } else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) {
1291                 if (ulp_blob_push_encap(blob, val, val_len) < 0) {
1292                         BNXT_TF_DBG(ERR, "encap blob push failed\n");
1293                         return -EINVAL;
1294                 }
1295         } else {
1296                 if (!ulp_blob_push(blob, val, val_len)) {
1297                         BNXT_TF_DBG(ERR, "push of val1 failed\n");
1298                         return -EINVAL;
1299                 }
1300         }
1301         *out_val = val;
1302         return 0;
1303 }
1304
1305 static int32_t
1306 ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms,
1307                              enum tf_dir dir,
1308                              struct bnxt_ulp_mapper_field_info *fld,
1309                              struct ulp_blob *blob,
1310                              uint8_t is_key,
1311                              const char *name)
1312 {
1313         uint16_t write_idx = blob->write_idx;
1314         uint8_t *val = NULL, *val1, *val2, *val3;
1315         uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0;
1316         uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0;
1317         uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0;
1318         uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0;
1319         uint64_t value1 = 0, value2 = 0, value3 = 0;
1320         int32_t rc = 0;
1321
1322         /* prepare the field source and values */
1323         switch (fld->field_opc) {
1324         case BNXT_ULP_FIELD_OPC_SRC1:
1325                 process_src1 = 1;
1326                 break;
1327         case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1328                 process_src1 = 1;
1329                 break;
1330         case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1331         case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1332                 process_src3 = 1;
1333                 eval_src3 = 1;
1334                 process_src1 = 1;
1335                 process_src2 = 1;
1336                 eval_src1 = 1;
1337                 eval_src2 = 1;
1338                 break;
1339         case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1340         case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1341         case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1342         case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1343         case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1344         case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1345                 process_src1 = 1;
1346                 process_src2 = 1;
1347                 eval_src1 = 1;
1348                 eval_src2 = 1;
1349                 break;
1350         default:
1351                 break;
1352         }
1353
1354         /* process the src1 opcode  */
1355         if (process_src1) {
1356                 if (ulp_mapper_field_src_process(parms, fld->field_src1,
1357                                                  fld->field_opr1, dir, is_key,
1358                                                  fld->field_bit_size, &val1,
1359                                                  &val1_len, &value1)) {
1360                         BNXT_TF_DBG(ERR, "fld src1 process failed\n");
1361                         goto error;
1362                 }
1363                 if (eval_src1) {
1364                         if (ulp_mapper_field_buffer_eval(val1, val1_len,
1365                                                          &val1_int)) {
1366                                 BNXT_TF_DBG(ERR, "fld src1 eval failed\n");
1367                                 goto error;
1368                         }
1369                 }
1370         }
1371
1372         /* for "if then clause" set the correct process  */
1373         if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) {
1374                 if (value1)
1375                         process_src2 = 1;
1376                 else
1377                         process_src3 = 1;
1378         }
1379
1380         /* process src2 opcode */
1381         if (process_src2) {
1382                 if (ulp_mapper_field_src_process(parms, fld->field_src2,
1383                                                  fld->field_opr2, dir, is_key,
1384                                                  fld->field_bit_size, &val2,
1385                                                  &val2_len, &value2)) {
1386                         BNXT_TF_DBG(ERR, "fld src2 process failed\n");
1387                         goto error;
1388                 }
1389                 if (eval_src2) {
1390                         if (ulp_mapper_field_buffer_eval(val2, val2_len,
1391                                                          &val2_int)) {
1392                                 BNXT_TF_DBG(ERR, "fld src2 eval failed\n");
1393                                 goto error;
1394                         }
1395                 }
1396         }
1397
1398         /* process src3 opcode */
1399         if (process_src3) {
1400                 if (ulp_mapper_field_src_process(parms, fld->field_src3,
1401                                                  fld->field_opr3, dir, is_key,
1402                                                  fld->field_bit_size, &val3,
1403                                                  &val3_len, &value3)) {
1404                         BNXT_TF_DBG(ERR, "fld src3 process failed\n");
1405                         goto error;
1406                 }
1407                 if (eval_src3) {
1408                         if (ulp_mapper_field_buffer_eval(val3, val3_len,
1409                                                          &val3_int)) {
1410                                 BNXT_TF_DBG(ERR, "fld src3 eval failed\n");
1411                                 goto error;
1412                         }
1413                 }
1414         }
1415
1416         val_len = fld->field_bit_size;
1417         /* process the field opcodes */
1418         switch (fld->field_opc) {
1419         case BNXT_ULP_FIELD_OPC_SRC1:
1420                 rc = ulp_mapper_field_blob_write(fld->field_src1,
1421                                                  blob, val1, val1_len, &val);
1422                 val_len = val1_len;
1423                 break;
1424         case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1425                 if (value1) {
1426                         rc = ulp_mapper_field_blob_write(fld->field_src2, blob,
1427                                                          val2, val2_len, &val);
1428                         val_len = val2_len;
1429                 } else {
1430                         rc = ulp_mapper_field_blob_write(fld->field_src3, blob,
1431                                                          val3, val3_len, &val);
1432                         val_len = val3_len;
1433                 }
1434                 break;
1435         case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1436         case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1437                 val_int = val1_int + val2_int;
1438                 val_int = tfp_cpu_to_be_64(val_int);
1439                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1440                 if (!val)
1441                         rc = -EINVAL;
1442                 break;
1443         case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1444         case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1445                 val_int = val1_int - val2_int;
1446                 val_int = tfp_cpu_to_be_64(val_int);
1447                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1448                 if (!val)
1449                         rc = -EINVAL;
1450                 break;
1451         case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1452                 val_int = val1_int | val2_int;
1453                 val_int = tfp_cpu_to_be_64(val_int);
1454                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1455                 if (!val)
1456                         rc = -EINVAL;
1457                 break;
1458         case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1459                 val_int = val1_int | val2_int | val3_int;
1460                 val_int = tfp_cpu_to_be_64(val_int);
1461                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1462                 if (!val)
1463                         rc = -EINVAL;
1464                 break;
1465         case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1466                 val_int = val1_int & val2_int;
1467                 val_int = tfp_cpu_to_be_64(val_int);
1468                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1469                 if (!val)
1470                         rc = -EINVAL;
1471                 break;
1472         case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1473                 val_int = val1_int & (val2_int | val3_int);
1474                 val_int = tfp_cpu_to_be_64(val_int);
1475                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1476                 if (!val)
1477                         rc = -EINVAL;
1478                 break;
1479         case BNXT_ULP_FIELD_OPC_SKIP:
1480                 break;
1481         default:
1482                 BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc);
1483                 rc = -EINVAL;
1484                 break;
1485         }
1486
1487         if (!rc) {
1488 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1489 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1490                 if (fld->field_src1 != BNXT_ULP_FIELD_SRC_ZERO)
1491                         ulp_mapper_field_dump(name, fld, blob, write_idx, val,
1492                                               val_len);
1493 #endif
1494 #endif
1495                 return rc;
1496         }
1497 error:
1498         BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name,
1499                     fld->description, (val) ? write_idx : 0, val_len);
1500         return -EINVAL;
1501 }
1502
1503 /*
1504  * Result table process and fill the result blob.
1505  * data [out] - the result blob data
1506  */
1507 static int32_t
1508 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1509                             struct bnxt_ulp_mapper_tbl_info *tbl,
1510                             struct ulp_blob *data,
1511                             const char *name)
1512 {
1513         struct bnxt_ulp_mapper_field_info *dflds;
1514         uint32_t i, num_flds = 0, encap_flds = 0;
1515         int32_t rc = 0;
1516
1517         /* Get the result field list */
1518         dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1519                                              &encap_flds);
1520
1521         /* validate the result field list counts */
1522         if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1523              (!num_flds && !encap_flds)) || !dflds ||
1524             (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1525                 (!num_flds || encap_flds))) {
1526                 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1527                             num_flds, encap_flds);
1528                 return -EINVAL;
1529         }
1530
1531         /* process the result fields, loop through them */
1532         for (i = 0; i < (num_flds + encap_flds); i++) {
1533                 /* set the swap index if encap swap bit is enabled */
1534                 if (parms->device_params->encap_byte_swap && encap_flds &&
1535                     i == num_flds)
1536                         ulp_blob_encap_swap_idx_set(data);
1537
1538                 /* Process the result fields */
1539                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1540                                                   &dflds[i], data, 0, name);
1541                 if (rc) {
1542                         BNXT_TF_DBG(ERR, "data field failed\n");
1543                         return rc;
1544                 }
1545         }
1546
1547         /* if encap bit swap is enabled perform the bit swap */
1548         if (parms->device_params->encap_byte_swap && encap_flds) {
1549                 ulp_blob_perform_encap_swap(data);
1550 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1551 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1552                 BNXT_TF_DBG(INFO, "Dump after encap swap\n");
1553                 ulp_mapper_blob_dump(data);
1554 #endif
1555 #endif
1556         }
1557
1558         return rc;
1559 }
1560
1561 static int32_t
1562 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1563                              struct bnxt_ulp_mapper_tbl_info *tbl,
1564                              uint64_t flow_id)
1565 {
1566         struct ulp_flow_db_res_params fid_parms;
1567         uint32_t mark, gfid, mark_flag;
1568         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1569         int32_t rc = 0;
1570
1571         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1572             !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1573              ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1574                               BNXT_ULP_ACT_BIT_MARK)))
1575                 return rc; /* no need to perform gfid process */
1576
1577         /* Get the mark id details from action property */
1578         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1579                sizeof(mark));
1580         mark = tfp_be_to_cpu_32(mark);
1581
1582         TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1583         mark_flag  = BNXT_ULP_MARK_GLOBAL_HW_FID;
1584
1585         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1586                                   gfid, mark);
1587         if (rc) {
1588                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1589                 return rc;
1590         }
1591         fid_parms.direction = tbl->direction;
1592         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1593         fid_parms.critical_resource = tbl->critical_resource;
1594         fid_parms.resource_type = mark_flag;
1595         fid_parms.resource_hndl = gfid;
1596         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1597
1598         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1599         if (rc)
1600                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1601         return rc;
1602 }
1603
1604 static int32_t
1605 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1606                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1607 {
1608         struct ulp_flow_db_res_params fid_parms;
1609         uint32_t act_idx, mark, mark_flag;
1610         uint64_t val64;
1611         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1612         int32_t rc = 0;
1613
1614         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1615             !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1616              ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1617                               BNXT_ULP_ACT_BIT_MARK)))
1618                 return rc; /* no need to perform mark action process */
1619
1620         /* Get the mark id details from action property */
1621         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1622                sizeof(mark));
1623         mark = tfp_be_to_cpu_32(mark);
1624
1625         if (!ulp_regfile_read(parms->regfile,
1626                               BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1627                               &val64)) {
1628                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1629                 return -EINVAL;
1630         }
1631         act_idx = tfp_be_to_cpu_64(val64);
1632         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID;
1633         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1634                                   act_idx, mark);
1635         if (rc) {
1636                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1637                 return rc;
1638         }
1639         fid_parms.direction = tbl->direction;
1640         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1641         fid_parms.critical_resource = tbl->critical_resource;
1642         fid_parms.resource_type = mark_flag;
1643         fid_parms.resource_hndl = act_idx;
1644         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1645
1646         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1647         if (rc)
1648                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1649         return rc;
1650 }
1651
1652 static int32_t
1653 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1654                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1655 {
1656         struct ulp_flow_db_res_params fid_parms;
1657         uint32_t act_idx, mark, mark_flag;
1658         uint64_t val64;
1659         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1660         int32_t rc = 0;
1661
1662         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1663             mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1664                 return rc; /* no need to perform mark action process */
1665
1666         /* Get the mark id details from the computed field of dev port id */
1667         mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1668
1669          /* Get the main action pointer */
1670         if (!ulp_regfile_read(parms->regfile,
1671                               BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1672                               &val64)) {
1673                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1674                 return -EINVAL;
1675         }
1676         act_idx = tfp_be_to_cpu_64(val64);
1677
1678         /* Set the mark flag to local fid and vfr flag */
1679         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1680
1681         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1682                                   act_idx, mark);
1683         if (rc) {
1684                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1685                 return rc;
1686         }
1687         fid_parms.direction = tbl->direction;
1688         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1689         fid_parms.critical_resource = tbl->critical_resource;
1690         fid_parms.resource_type = mark_flag;
1691         fid_parms.resource_hndl = act_idx;
1692         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1693
1694         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1695         if (rc)
1696                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1697         return rc;
1698 }
1699
1700 /* Tcam table scan the identifier list and allocate each identifier */
1701 static int32_t
1702 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1703                                      struct bnxt_ulp_mapper_tbl_info *tbl)
1704 {
1705         struct bnxt_ulp_mapper_ident_info *idents;
1706         uint32_t num_idents;
1707         uint32_t i;
1708
1709         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1710         for (i = 0; i < num_idents; i++) {
1711                 if (ulp_mapper_ident_process(parms, tbl,
1712                                              &idents[i], NULL))
1713                         return -EINVAL;
1714         }
1715         return 0;
1716 }
1717
1718 /*
1719  * Tcam table scan the identifier list and extract the identifier from
1720  * the result blob.
1721  */
1722 static int32_t
1723 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1724                                        struct bnxt_ulp_mapper_tbl_info *tbl,
1725                                        struct ulp_blob *data)
1726 {
1727         struct bnxt_ulp_mapper_ident_info *idents;
1728         uint32_t num_idents = 0, i;
1729         int32_t rc = 0;
1730
1731         /*
1732          * Extract the listed identifiers from the result field,
1733          * no need to allocate them.
1734          */
1735         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1736         for (i = 0; i < num_idents; i++) {
1737                 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1738                 if (rc) {
1739                         BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1740                         return rc;
1741                 }
1742         }
1743         return rc;
1744 }
1745
1746 /* Internal function to write the tcam entry */
1747 static int32_t
1748 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1749                                 struct bnxt_ulp_mapper_tbl_info *tbl,
1750                                 struct ulp_blob *key,
1751                                 struct ulp_blob *mask,
1752                                 struct ulp_blob *data,
1753                                 uint16_t idx)
1754 {
1755         struct tf_set_tcam_entry_parms sparms = { 0 };
1756         struct tf *tfp;
1757         uint16_t tmplen;
1758         int32_t rc;
1759
1760         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
1761         if (!tfp) {
1762                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1763                 return -EINVAL;
1764         }
1765
1766         sparms.dir              = tbl->direction;
1767         sparms.tcam_tbl_type    = tbl->resource_type;
1768         sparms.idx              = idx;
1769         sparms.key              = ulp_blob_data_get(key, &tmplen);
1770         sparms.key_sz_in_bits   = tmplen;
1771         sparms.mask             = ulp_blob_data_get(mask, &tmplen);
1772         sparms.result           = ulp_blob_data_get(data, &tmplen);
1773         sparms.result_sz_in_bits = tmplen;
1774         if (tf_set_tcam_entry(tfp, &sparms)) {
1775                 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1776                             tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1777                             tf_dir_2_str(sparms.dir), sparms.idx);
1778                 return -EIO;
1779         }
1780         BNXT_TF_INF("tcam[%s][%s][%x] write success.\n",
1781                     tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1782                     tf_dir_2_str(sparms.dir), sparms.idx);
1783
1784         /* Mark action */
1785         rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1786         if (rc) {
1787                 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1788                 return rc;
1789         }
1790
1791 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1792 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1793         ulp_mapper_tcam_entry_dump("TCAM", idx, tbl, key, mask, data);
1794 #endif
1795 #endif
1796         return rc;
1797 }
1798
1799 /*
1800  * internal function to post process key/mask blobs for dynamic pad WC tcam tbl
1801  *
1802  * parms [in] The mappers parms with data related to the flow.
1803  *
1804  * key [in] The original key to be transformed
1805  *
1806  * mask [in] The original mask to be transformed
1807  *
1808  * tkey [in/out] The transformed key
1809  *
1810  * tmask [in/out] The transformed mask
1811  *
1812  * returns zero on success, non-zero on failure
1813  */
1814 static uint32_t
1815 ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms,
1816                                         struct ulp_blob *key,
1817                                         struct ulp_blob *mask,
1818                                         struct ulp_blob *tkey,
1819                                         struct ulp_blob *tmask)
1820 {
1821         uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset;
1822         uint32_t cword, i, rc;
1823         int32_t pad;
1824         uint8_t *val;
1825
1826         slice_width = dparms->wc_slice_width;
1827         clen = dparms->wc_ctl_size_bits;
1828         max_slices = dparms->wc_max_slices;
1829         blen = ulp_blob_data_len_get(key);
1830
1831         /* Get the length of the key based on number of slices and width */
1832         num_slices = 1;
1833         tlen = slice_width;
1834         while (tlen < blen &&
1835                num_slices <= max_slices) {
1836                 num_slices = num_slices << 1;
1837                 tlen = tlen << 1;
1838         }
1839
1840         if (num_slices > max_slices) {
1841                 BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen);
1842                 return -EINVAL;
1843         }
1844
1845         /* The key/mask may not be on a natural slice boundary, pad it */
1846         pad = tlen - blen;
1847         if (ulp_blob_pad_push(key, pad) < 0 ||
1848             ulp_blob_pad_push(mask, pad) < 0) {
1849                 BNXT_TF_DBG(ERR, "Unable to pad key/mask\n");
1850                 return -EINVAL;
1851         }
1852
1853         /* The new length accounts for the ctrl word length and num slices */
1854         tlen = tlen + clen * num_slices;
1855         if (!ulp_blob_init(tkey, tlen, key->byte_order) ||
1856             !ulp_blob_init(tmask, tlen, mask->byte_order)) {
1857                 BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n");
1858                 return -EINVAL;
1859         }
1860
1861         /* Build the transformed key/mask */
1862         cword = dparms->wc_mode_list[num_slices - 1];
1863         cword = tfp_cpu_to_be_32(cword);
1864         offset = 0;
1865         for (i = 0; i < num_slices; i++) {
1866                 val = ulp_blob_push_32(tkey, &cword, clen);
1867                 if (!val) {
1868                         BNXT_TF_DBG(ERR, "Key ctrl word push failed\n");
1869                         return -EINVAL;
1870                 }
1871                 val = ulp_blob_push_32(tmask, &cword, clen);
1872                 if (!val) {
1873                         BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n");
1874                         return -EINVAL;
1875                 }
1876                 rc = ulp_blob_append(tkey, key, offset, slice_width);
1877                 if (rc) {
1878                         BNXT_TF_DBG(ERR, "Key blob append failed\n");
1879                         return rc;
1880                 }
1881                 rc = ulp_blob_append(tmask, mask, offset, slice_width);
1882                 if (rc) {
1883                         BNXT_TF_DBG(ERR, "Mask blob append failed\n");
1884                         return rc;
1885                 }
1886                 offset += slice_width;
1887         }
1888
1889         /* The key/mask are byte reversed on every 4 byte chunk */
1890         ulp_blob_perform_byte_reverse(tkey, 4);
1891         ulp_blob_perform_byte_reverse(tmask, 4);
1892
1893         return 0;
1894 }
1895
1896 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1897 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
1898 {
1899         ulp_blob_perform_64B_word_swap(blob);
1900         ulp_blob_perform_64B_byte_swap(blob);
1901 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1902 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
1903         BNXT_TF_DBG(INFO, "Dump after wc tcam post process\n");
1904         ulp_mapper_blob_dump(blob);
1905 #endif
1906 #endif
1907 }
1908
1909 static int32_t
1910 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1911                             struct bnxt_ulp_mapper_tbl_info *tbl)
1912 {
1913         struct bnxt_ulp_mapper_key_info *kflds;
1914         struct ulp_blob okey, omask, data, update_data;
1915         struct ulp_blob tkey, tmask; /* transform key and mask */
1916         struct ulp_blob *key, *mask;
1917         uint32_t i, num_kflds;
1918         struct tf *tfp;
1919         int32_t rc, trc;
1920         struct bnxt_ulp_device_params *dparms = parms->device_params;
1921         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
1922         struct tf_search_tcam_entry_parms searchparms   = { 0 };
1923         struct ulp_flow_db_res_params   fid_parms       = { 0 };
1924         struct tf_free_tcam_entry_parms free_parms      = { 0 };
1925         uint32_t hit = 0;
1926         uint16_t tmplen = 0;
1927         uint16_t idx;
1928
1929         /* Set the key and mask to the original key and mask. */
1930         key = &okey;
1931         mask = &omask;
1932
1933         /* Skip this if table opcode is NOP */
1934         if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1935             tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1936                 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1937                             tbl->tbl_opcode);
1938                 return 0;
1939         }
1940
1941         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
1942         if (!tfp) {
1943                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1944                 return -EINVAL;
1945         }
1946
1947         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1948         if (!kflds || !num_kflds) {
1949                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1950                 return -EINVAL;
1951         }
1952
1953         if (!ulp_blob_init(key, tbl->blob_key_bit_size, tbl->byte_order) ||
1954             !ulp_blob_init(mask, tbl->blob_key_bit_size, tbl->byte_order) ||
1955             !ulp_blob_init(&data, tbl->result_bit_size, dparms->byte_order) ||
1956             !ulp_blob_init(&update_data, tbl->result_bit_size,
1957                            dparms->byte_order)) {
1958                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1959                 return -EINVAL;
1960         }
1961
1962         /* create the key/mask */
1963         /*
1964          * NOTE: The WC table will require some kind of flag to handle the
1965          * mode bits within the key/mask
1966          */
1967         for (i = 0; i < num_kflds; i++) {
1968                 /* Setup the key */
1969                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1970                                                   &kflds[i].field_info_spec,
1971                                                   key, 1, "TCAM Key");
1972                 if (rc) {
1973                         BNXT_TF_DBG(ERR, "Key field set failed %s\n",
1974                                     kflds[i].field_info_spec.description);
1975                         return rc;
1976                 }
1977
1978                 /* Setup the mask */
1979                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1980                                                   &kflds[i].field_info_mask,
1981                                                   mask, 0, "TCAM Mask");
1982                 if (rc) {
1983                         BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
1984                                     kflds[i].field_info_mask.description);
1985                         return rc;
1986                 }
1987         }
1988
1989         /* For wild card tcam perform the post process to swap the blob */
1990         if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM ||
1991             tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH ||
1992             tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW) {
1993                 if (dparms->dynamic_pad_en) {
1994                         /* Sets up the slices for writing to the WC TCAM */
1995                         rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms,
1996                                                                      key, mask,
1997                                                                      &tkey,
1998                                                                      &tmask);
1999                         if (rc) {
2000                                 BNXT_TF_DBG(ERR,
2001                                             "Failed to post proc WC entry.\n");
2002                                 return rc;
2003                         }
2004                         /* Now need to use the transform Key/Mask */
2005                         key = &tkey;
2006                         mask = &tmask;
2007                 } else {
2008                         ulp_mapper_wc_tcam_tbl_post_process(key);
2009                         ulp_mapper_wc_tcam_tbl_post_process(mask);
2010                 }
2011
2012         }
2013
2014         if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2015                 /* allocate the tcam index */
2016                 aparms.dir = tbl->direction;
2017                 aparms.tcam_tbl_type = tbl->resource_type;
2018                 aparms.key = ulp_blob_data_get(key, &tmplen);
2019                 aparms.key_sz_in_bits = tmplen;
2020                 aparms.mask = ulp_blob_data_get(mask, &tmplen);
2021
2022                 /* calculate the entry priority */
2023                 rc = ulp_mapper_priority_opc_process(parms, tbl,
2024                                                      &aparms.priority);
2025                 if (rc) {
2026                         BNXT_TF_DBG(ERR, "entry priority process failed\n");
2027                         return rc;
2028                 }
2029
2030                 rc = tf_alloc_tcam_entry(tfp, &aparms);
2031                 if (rc) {
2032                         BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
2033                         return rc;
2034                 }
2035                 idx = aparms.idx;
2036                 hit = aparms.hit;
2037         } else {
2038                 /*
2039                  * Searching before allocation to see if we already have an
2040                  * entry.  This allows re-use of a constrained resource.
2041                  */
2042                 searchparms.dir = tbl->direction;
2043                 searchparms.tcam_tbl_type = tbl->resource_type;
2044                 searchparms.key = ulp_blob_data_get(key, &tmplen);
2045                 searchparms.key_sz_in_bits = tbl->key_bit_size;
2046                 searchparms.mask = ulp_blob_data_get(mask, &tmplen);
2047                 searchparms.alloc = 1;
2048                 searchparms.result = ulp_blob_data_get(&data, &tmplen);
2049                 searchparms.result_sz_in_bits = tbl->result_bit_size;
2050
2051                 /* calculate the entry priority */
2052                 rc = ulp_mapper_priority_opc_process(parms, tbl,
2053                                                      &searchparms.priority);
2054                 if (rc) {
2055                         BNXT_TF_DBG(ERR, "entry priority process failed\n");
2056                         return rc;
2057                 }
2058
2059                 rc = tf_search_tcam_entry(tfp, &searchparms);
2060                 if (rc) {
2061                         BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
2062                         return rc;
2063                 }
2064
2065                 /* Successful search, check the result */
2066                 if (searchparms.search_status == REJECT) {
2067                         BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
2068                         return -ENOMEM;
2069                 }
2070                 idx = searchparms.idx;
2071                 hit = searchparms.hit;
2072         }
2073
2074         /* Write the tcam index into the regfile*/
2075         if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
2076                               (uint64_t)tfp_cpu_to_be_64(idx))) {
2077                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
2078                             tbl->tbl_operand);
2079                 rc = -EINVAL;
2080                 /* Need to free the tcam idx, so goto error */
2081                 goto error;
2082         }
2083
2084         /* if it is miss then it is same as no search before alloc */
2085         if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2086                 /*Scan identifier list, allocate identifier and update regfile*/
2087                 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
2088                 /* Create the result blob */
2089                 if (!rc)
2090                         rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2091                                                          "TCAM Result");
2092                 /* write the tcam entry */
2093                 if (!rc)
2094                         rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key,
2095                                                              mask, &data, idx);
2096         } else {
2097                 /*Scan identifier list, extract identifier and update regfile*/
2098                 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
2099         }
2100         if (rc)
2101                 goto error;
2102
2103         /* Add the tcam index to the flow database */
2104         fid_parms.direction = tbl->direction;
2105         fid_parms.resource_func = tbl->resource_func;
2106         fid_parms.resource_type = tbl->resource_type;
2107         fid_parms.critical_resource = tbl->critical_resource;
2108         fid_parms.resource_hndl = idx;
2109         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2110
2111         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2112         if (rc) {
2113                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2114                             rc);
2115                 /* Need to free the identifier, so goto error */
2116                 goto error;
2117         }
2118
2119         return 0;
2120 error:
2121         free_parms.dir                  = tbl->direction;
2122         free_parms.tcam_tbl_type        = tbl->resource_type;
2123         free_parms.idx                  = idx;
2124         trc = tf_free_tcam_entry(tfp, &free_parms);
2125         if (trc)
2126                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
2127                             tbl->resource_type, tbl->direction, idx);
2128         return rc;
2129 }
2130
2131 static int32_t
2132 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2133                           struct bnxt_ulp_mapper_tbl_info *tbl)
2134 {
2135         struct bnxt_ulp_mapper_key_info *kflds;
2136         struct ulp_blob key, data;
2137         uint32_t i, num_kflds;
2138         uint16_t tmplen;
2139         struct tf *tfp;
2140         struct ulp_flow_db_res_params   fid_parms = { 0 };
2141         struct tf_insert_em_entry_parms iparms = { 0 };
2142         struct tf_delete_em_entry_parms free_parms = { 0 };
2143         enum bnxt_ulp_flow_mem_type mtype;
2144         struct bnxt_ulp_device_params *dparms = parms->device_params;
2145         int32_t trc;
2146         int32_t rc = 0;
2147         int32_t pad = 0;
2148
2149         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2150         rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2151         if (rc) {
2152                 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
2153                 return -EINVAL;
2154         }
2155
2156         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2157         if (!kflds || !num_kflds) {
2158                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2159                 return -EINVAL;
2160         }
2161
2162         /* Initialize the key/result blobs */
2163         if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
2164                            tbl->byte_order) ||
2165             !ulp_blob_init(&data, tbl->result_bit_size,
2166                            tbl->byte_order)) {
2167                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
2168                 return -EINVAL;
2169         }
2170
2171         /* create the key */
2172         for (i = 0; i < num_kflds; i++) {
2173                 /* Setup the key */
2174                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2175                                                   &kflds[i].field_info_spec,
2176                                                   &key, 1, "EM Key");
2177                 if (rc) {
2178                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
2179                         return rc;
2180                 }
2181         }
2182
2183         /* if dynamic padding is enabled then add padding to result data */
2184         if (dparms->dynamic_pad_en) {
2185                 /* add padding to make sure key is at byte boundary */
2186                 ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS);
2187
2188                 /* add the pad */
2189                 pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits;
2190                 if (pad < 0) {
2191                         BNXT_TF_DBG(ERR, "Invalid em blk size and align\n");
2192                         return -EINVAL;
2193                 }
2194                 ulp_blob_pad_push(&data, (uint32_t)pad);
2195         }
2196
2197         /* Create the result data blob */
2198         rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
2199         if (rc) {
2200                 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2201                 return rc;
2202         }
2203 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2204 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2205         ulp_mapper_result_dump("EM Result", tbl, &data);
2206 #endif
2207 #endif
2208         if (dparms->dynamic_pad_en) {
2209                 uint32_t abits = dparms->em_blk_align_bits;
2210
2211                 /* when dynamic padding is enabled merge result + key */
2212                 rc = ulp_blob_block_merge(&data, &key, abits, pad);
2213                 if (rc) {
2214                         BNXT_TF_DBG(ERR, "Failed to merge the result blob\n");
2215                         return rc;
2216                 }
2217
2218                 /* add padding to make sure merged result is at slice boundary*/
2219                 ulp_blob_pad_align(&data, abits);
2220
2221                 ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits));
2222 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2223 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2224         ulp_mapper_result_dump("EM Merged Result", tbl, &data);
2225 #endif
2226 #endif
2227         }
2228
2229         /* do the transpose for the internal EM keys */
2230         if (tbl->resource_type == TF_MEM_INTERNAL) {
2231                 if (dparms->em_key_align_bytes) {
2232                         int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes);
2233
2234                         tmplen = ulp_blob_data_len_get(&key);
2235                         ulp_blob_pad_push(&key, b - tmplen);
2236                 }
2237                 tmplen = ulp_blob_data_len_get(&key);
2238                 ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen));
2239 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2240 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2241         ulp_mapper_result_dump("EM Key Transpose", tbl, &key);
2242 #endif
2243 #endif
2244         }
2245
2246         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
2247                                              &iparms.tbl_scope_id);
2248         if (rc) {
2249                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2250                 return rc;
2251         }
2252
2253         /*
2254          * NOTE: the actual blob size will differ from the size in the tbl
2255          * entry due to the padding.
2256          */
2257         iparms.dup_check                = 0;
2258         iparms.dir                      = tbl->direction;
2259         iparms.mem                      = tbl->resource_type;
2260         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
2261         iparms.key_sz_in_bits           = tbl->key_bit_size;
2262         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
2263         if (tbl->result_bit_size)
2264                 iparms.em_record_sz_in_bits     = tbl->result_bit_size;
2265         else
2266                 iparms.em_record_sz_in_bits     = tmplen;
2267
2268         rc = tf_insert_em_entry(tfp, &iparms);
2269         if (rc) {
2270                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
2271                 return rc;
2272         }
2273
2274 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2275 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2276         ulp_mapper_em_dump("EM", &key, &data, &iparms);
2277         /* tf_dump_tables(tfp, iparms.tbl_scope_id); */
2278 #endif
2279 #endif
2280         /* Mark action process */
2281         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
2282             tbl->resource_type == TF_MEM_EXTERNAL)
2283                 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
2284         else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
2285                  tbl->resource_type == TF_MEM_INTERNAL)
2286                 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
2287         if (rc) {
2288                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
2289                 goto error;
2290         }
2291
2292         /* Link the EM resource to the flow in the flow db */
2293         memset(&fid_parms, 0, sizeof(fid_parms));
2294         fid_parms.direction             = tbl->direction;
2295         fid_parms.resource_func         = tbl->resource_func;
2296         fid_parms.resource_type         = tbl->resource_type;
2297         fid_parms.critical_resource     = tbl->critical_resource;
2298         fid_parms.resource_hndl         = iparms.flow_handle;
2299
2300         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2301         if (rc) {
2302                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2303                             rc);
2304                 /* Need to free the identifier, so goto error */
2305                 goto error;
2306         }
2307
2308         return 0;
2309 error:
2310         free_parms.dir          = iparms.dir;
2311         free_parms.mem          = iparms.mem;
2312         free_parms.tbl_scope_id = iparms.tbl_scope_id;
2313         free_parms.flow_handle  = iparms.flow_handle;
2314
2315         trc = tf_delete_em_entry(tfp, &free_parms);
2316         if (trc)
2317                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2318
2319         return rc;
2320 }
2321
2322 static int32_t
2323 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2324                              struct bnxt_ulp_mapper_tbl_info *tbl)
2325 {
2326         struct ulp_flow_db_res_params fid_parms;
2327         struct ulp_blob data;
2328         uint64_t regval = 0;
2329         uint16_t tmplen;
2330         uint32_t index;
2331         int32_t rc = 0, trc = 0;
2332         struct tf_alloc_tbl_entry_parms aparms = { 0 };
2333         struct tf_set_tbl_entry_parms sparms = { 0 };
2334         struct tf_get_tbl_entry_parms gparms = { 0 };
2335         struct tf_free_tbl_entry_parms free_parms = { 0 };
2336         uint32_t tbl_scope_id;
2337         struct tf *tfp;
2338         struct bnxt_ulp_glb_resource_info glb_res = { 0 };
2339         uint16_t bit_size;
2340         bool alloc = false;
2341         bool write = false;
2342         bool global = false;
2343         uint64_t act_rec_size;
2344         bool shared = false;
2345
2346         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2347         /* use the max size if encap is enabled */
2348         if (tbl->encap_num_fields)
2349                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
2350         else
2351                 bit_size = tbl->result_bit_size;
2352
2353         /* Initialize the blob data */
2354         if (!ulp_blob_init(&data, bit_size,
2355                            parms->device_params->byte_order)) {
2356                 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2357                 return -EINVAL;
2358         }
2359
2360         /* Get the scope id first */
2361         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2362         if (rc) {
2363                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2364                 return rc;
2365         }
2366
2367         switch (tbl->tbl_opcode) {
2368         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2369                 alloc = true;
2370                 break;
2371         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2372                 /*
2373                  * Build the entry, alloc an index, write the table, and store
2374                  * the data in the regfile.
2375                  */
2376                 alloc = true;
2377                 write = true;
2378                 break;
2379         case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2380                 /*
2381                  * get the index to write to from the regfile and then write
2382                  * the table entry.
2383                  */
2384                 if (!ulp_regfile_read(parms->regfile,
2385                                       tbl->tbl_operand,
2386                                       &regval)) {
2387                         BNXT_TF_DBG(ERR,
2388                                     "Failed to get tbl idx from regfile[%d].\n",
2389                                     tbl->tbl_operand);
2390                         return -EINVAL;
2391                 }
2392                 index = tfp_be_to_cpu_64(regval);
2393                 /* For external, we need to reverse shift */
2394                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2395                         index = TF_ACT_REC_PTR_2_OFFSET(index);
2396
2397                 write = true;
2398                 break;
2399         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE:
2400                 /*
2401                  * Build the entry, alloc an index, write the table, and store
2402                  * the data in the global regfile.
2403                  */
2404                 alloc = true;
2405                 global = true;
2406                 write = true;
2407                 glb_res.direction = tbl->direction;
2408                 glb_res.resource_func = tbl->resource_func;
2409                 glb_res.resource_type = tbl->resource_type;
2410                 glb_res.glb_regfile_index = tbl->tbl_operand;
2411                 break;
2412         case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2413                 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2414                         BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2415                         return -EINVAL;
2416                 }
2417                 /*
2418                  * get the index to write to from the global regfile and then
2419                  * write the table.
2420                  */
2421                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
2422                                                  tbl->direction,
2423                                                  tbl->tbl_operand,
2424                                                  &regval, &shared)) {
2425                         BNXT_TF_DBG(ERR,
2426                                     "Failed to get tbl idx from Glb RF[%d].\n",
2427                                     tbl->tbl_operand);
2428                         return -EINVAL;
2429                 }
2430                 index = tfp_be_to_cpu_64(regval);
2431                 /* For external, we need to reverse shift */
2432                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2433                         index = TF_ACT_REC_PTR_2_OFFSET(index);
2434                 write = true;
2435                 break;
2436         case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2437                 /*
2438                  * The read is different from the rest and can be handled here
2439                  * instead of trying to use common code.  Simply read the table
2440                  * with the index from the regfile, scan and store the
2441                  * identifiers, and return.
2442                  */
2443                 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2444                         /* Not currently supporting with EXT */
2445                         BNXT_TF_DBG(ERR,
2446                                     "Ext Table Read Opcode not supported.\n");
2447                         return -EINVAL;
2448                 }
2449                 if (!ulp_regfile_read(parms->regfile,
2450                                       tbl->tbl_operand, &regval)) {
2451                         BNXT_TF_DBG(ERR,
2452                                     "Failed to get tbl idx from regfile[%d]\n",
2453                                     tbl->tbl_operand);
2454                         return -EINVAL;
2455                 }
2456                 index = tfp_be_to_cpu_64(regval);
2457                 gparms.dir = tbl->direction;
2458                 gparms.type = tbl->resource_type;
2459                 gparms.data = ulp_blob_data_get(&data, &tmplen);
2460                 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2461                 gparms.idx = index;
2462                 rc = tf_get_tbl_entry(tfp, &gparms);
2463                 if (rc) {
2464                         BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2465                                     tbl->resource_type, index);
2466                         return rc;
2467                 }
2468                 /*
2469                  * Scan the fields in the entry and push them into the regfile.
2470                  */
2471                 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2472                                                    gparms.data,
2473                                                    gparms.data_sz_in_bytes,
2474                                                    data.byte_order);
2475                 if (rc) {
2476                         BNXT_TF_DBG(ERR,
2477                                     "Failed to get flds on tbl read rc=%d\n",
2478                                     rc);
2479                         return rc;
2480                 }
2481                 return 0;
2482         default:
2483                 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2484                             tbl->tbl_opcode);
2485                 return -EINVAL;
2486         }
2487
2488         if (write) {
2489                 /* Get the result fields list */
2490                 rc = ulp_mapper_tbl_result_build(parms,
2491                                                  tbl,
2492                                                  &data,
2493                                                  "Indexed Result");
2494                 if (rc) {
2495                         BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2496                         return rc;
2497                 }
2498         }
2499
2500         if (alloc) {
2501                 aparms.dir              = tbl->direction;
2502                 aparms.type             = tbl->resource_type;
2503                 aparms.tbl_scope_id     = tbl_scope_id;
2504
2505                 /* All failures after the alloc succeeds require a free */
2506                 rc = tf_alloc_tbl_entry(tfp, &aparms);
2507                 if (rc) {
2508                         BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2509                                     tf_tbl_type_2_str(tbl->resource_type),
2510                                     tf_dir_2_str(tbl->direction), rc);
2511                         return rc;
2512                 }
2513                 index = aparms.idx;
2514
2515                 /*
2516                  * Store the index in the regfile since we either allocated it
2517                  * or it was a hit.
2518                  *
2519                  * Calculate the idx for the result record, for external EM the
2520                  * offset needs to be shifted accordingly.
2521                  * If external non-inline table types are used then need to
2522                  * revisit this logic.
2523                  */
2524                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2525                         regval = TF_ACT_REC_OFFSET_2_PTR(index);
2526                 else
2527                         regval = index;
2528                 regval = tfp_cpu_to_be_64(regval);
2529
2530                 if (global) {
2531                         /*
2532                          * Shared resources are never allocated through this
2533                          * method, so the shared flag is always false.
2534                          */
2535                         rc = ulp_mapper_glb_resource_write(parms->mapper_data,
2536                                                            &glb_res, regval,
2537                                                            false);
2538                 } else {
2539                         rc = ulp_regfile_write(parms->regfile,
2540                                                tbl->tbl_operand, regval);
2541                 }
2542                 if (rc) {
2543                         BNXT_TF_DBG(ERR,
2544                                     "Failed to write %s regfile[%d] rc=%d\n",
2545                                     (global) ? "global" : "reg",
2546                                     tbl->tbl_operand, rc);
2547                         goto error;
2548                 }
2549         }
2550
2551         if (write) {
2552                 sparms.dir = tbl->direction;
2553                 sparms.type = tbl->resource_type;
2554                 sparms.data = ulp_blob_data_get(&data, &tmplen);
2555                 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2556                 sparms.idx = index;
2557                 sparms.tbl_scope_id = tbl_scope_id;
2558                 if (shared)
2559                         tfp = bnxt_ulp_cntxt_shared_tfp_get(parms->ulp_ctx);
2560                 rc = tf_set_tbl_entry(tfp, &sparms);
2561                 if (rc) {
2562                         BNXT_TF_DBG(ERR,
2563                                     "Index table[%s][%s][%x] write fail rc=%d\n",
2564                                     tf_tbl_type_2_str(sparms.type),
2565                                     tf_dir_2_str(sparms.dir),
2566                                     sparms.idx, rc);
2567                         goto error;
2568                 }
2569                 BNXT_TF_INF("Index table[%s][%s][%x] write successful.\n",
2570                             tf_tbl_type_2_str(sparms.type),
2571                             tf_dir_2_str(sparms.dir), sparms.idx);
2572
2573                 /* Calculate action record size */
2574                 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2575                         act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
2576                         act_rec_size--;
2577                         if (ulp_regfile_write(parms->regfile,
2578                                               BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
2579                                               tfp_cpu_to_be_64(act_rec_size)))
2580                                 BNXT_TF_DBG(ERR,
2581                                             "Failed write the act rec size\n");
2582                 }
2583         }
2584
2585         /* Link the resource to the flow in the flow db */
2586         memset(&fid_parms, 0, sizeof(fid_parms));
2587         fid_parms.direction     = tbl->direction;
2588         fid_parms.resource_func = tbl->resource_func;
2589         fid_parms.resource_type = tbl->resource_type;
2590         fid_parms.resource_sub_type = tbl->resource_sub_type;
2591         fid_parms.resource_hndl = index;
2592         fid_parms.critical_resource = tbl->critical_resource;
2593         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2594
2595         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2596         if (rc) {
2597                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2598                             rc);
2599                 goto error;
2600         }
2601
2602         /* Perform the VF rep action */
2603         rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2604         if (rc) {
2605                 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2606                 goto error;
2607         }
2608         return rc;
2609 error:
2610         /* Shared resources are not freed */
2611         if (shared)
2612                 return rc;
2613         /*
2614          * Free the allocated resource since we failed to either
2615          * write to the entry or link the flow
2616          */
2617         free_parms.dir  = tbl->direction;
2618         free_parms.type = tbl->resource_type;
2619         free_parms.idx  = index;
2620         free_parms.tbl_scope_id = tbl_scope_id;
2621
2622         trc = tf_free_tbl_entry(tfp, &free_parms);
2623         if (trc)
2624                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2625
2626         return rc;
2627 }
2628
2629 static int32_t
2630 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2631                           struct bnxt_ulp_mapper_tbl_info *tbl)
2632 {
2633         struct ulp_blob data, res_blob;
2634         uint64_t idx;
2635         uint16_t tmplen;
2636         int32_t rc = 0;
2637         struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2638         struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2639         struct tf *tfp;
2640         enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2641         uint32_t res_size;
2642
2643         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2644         /* Initialize the blob data */
2645         if (!ulp_blob_init(&data, tbl->result_bit_size,
2646                            parms->device_params->byte_order)) {
2647                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2648                 return -EINVAL;
2649         }
2650
2651         /* create the result blob */
2652         rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2653         if (rc) {
2654                 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2655                 return rc;
2656         }
2657
2658         /* Get the index details */
2659         switch (if_opc) {
2660         case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2661                 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2662                 break;
2663         case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2664                 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2665                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2666                                     tbl->tbl_operand);
2667                         return -EINVAL;
2668                 }
2669                 idx = tfp_be_to_cpu_64(idx);
2670                 break;
2671         case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2672                 idx = tbl->tbl_operand;
2673                 break;
2674         case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2675                 /* Initialize the result blob */
2676                 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2677                                    parms->device_params->byte_order)) {
2678                         BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2679                         return -EINVAL;
2680                 }
2681
2682                 /* read the interface table */
2683                 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2684                 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2685                 get_parms.dir = tbl->direction;
2686                 get_parms.type = tbl->resource_type;
2687                 get_parms.idx = idx;
2688                 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2689                 get_parms.data_sz_in_bytes = res_size;
2690
2691                 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2692                 if (rc) {
2693                         BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2694                                     get_parms.type,
2695                                     tf_dir_2_str(get_parms.dir),
2696                                     get_parms.idx, rc);
2697                         return rc;
2698                 }
2699                 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2700                                                    res_blob.data,
2701                                                    res_size,
2702                                                    res_blob.byte_order);
2703                 if (rc)
2704                         BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2705                 return rc;
2706         case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2707                 return rc; /* skip it */
2708         default:
2709                 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2710                 return -EINVAL;
2711         }
2712
2713         /* Perform the tf table set by filling the set params */
2714         iftbl_params.dir = tbl->direction;
2715         iftbl_params.type = tbl->resource_type;
2716         iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2717         iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2718         iftbl_params.idx = idx;
2719
2720         rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2721         if (rc) {
2722                 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2723                             iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2724                             tf_dir_2_str(iftbl_params.dir),
2725                             iftbl_params.idx, rc);
2726                 return rc;
2727         }
2728         BNXT_TF_INF("Set table[%s][%s][%x] success.\n",
2729                     tf_if_tbl_2_str(iftbl_params.type),
2730                     tf_dir_2_str(iftbl_params.dir),
2731                     iftbl_params.idx);
2732
2733         /*
2734          * TBD: Need to look at the need to store idx in flow db for restore
2735          * the table to its original state on deletion of this entry.
2736          */
2737         return rc;
2738 }
2739
2740 static int32_t
2741 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2742                            struct bnxt_ulp_mapper_tbl_info *tbl)
2743 {
2744         struct ulp_mapper_gen_tbl_list *gen_tbl_list;
2745         struct bnxt_ulp_mapper_key_info *kflds;
2746         struct ulp_flow_db_res_params fid_parms;
2747         struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2748         struct ulp_gen_hash_entry_params hash_entry;
2749         uint16_t tmplen = 0;
2750         struct ulp_blob key, data;
2751         uint8_t *cache_key;
2752         int32_t tbl_idx;
2753         uint32_t i, num_kflds = 0, key_index = 0;
2754         uint32_t gen_tbl_miss = 1, fdb_write = 0;
2755         uint8_t *byte_data;
2756         int32_t rc = 0;
2757
2758         /* Get the key fields list and build the key. */
2759         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2760         if (!kflds || !num_kflds) {
2761                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2762                 return -EINVAL;
2763         }
2764
2765         if (!ulp_blob_init(&key, tbl->key_bit_size,
2766                            parms->device_params->byte_order)) {
2767                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2768                 return -EINVAL;
2769         }
2770         for (i = 0; i < num_kflds; i++) {
2771                 /* Setup the key */
2772                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2773                                                   &kflds[i].field_info_spec,
2774                                                   &key, 1, "Gen Tbl Key");
2775                 if (rc) {
2776                         BNXT_TF_DBG(ERR,
2777                                     "Failed to create key for Gen tbl rc=%d\n",
2778                                     rc);
2779                         return -EINVAL;
2780                 }
2781         }
2782
2783         /* Calculate the table index for the generic table*/
2784         tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2785                                                    tbl->direction);
2786         if (tbl_idx < 0) {
2787                 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2788                             tbl->resource_sub_type, tbl->direction);
2789                 return -EINVAL;
2790         }
2791
2792         /* The_key is a byte array convert it to a search index */
2793         cache_key = ulp_blob_data_get(&key, &tmplen);
2794 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
2795 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
2796         BNXT_TF_DBG(DEBUG, "The gen_tbl[%u] key\n", tbl_idx);
2797         ulp_mapper_blob_dump(&key);
2798 #endif
2799 #endif
2800         /* get the generic table  */
2801         gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx];
2802
2803         /* Check if generic hash table */
2804         if (gen_tbl_list->hash_tbl) {
2805                 if (tbl->gen_tbl_lkup_type !=
2806                     BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) {
2807                         BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n",
2808                                     gen_tbl_list->gen_tbl_name);
2809                         return -EINVAL;
2810                 }
2811                 hash_entry.key_data = cache_key;
2812                 hash_entry.key_length = ULP_BITS_2_BYTE(tmplen);
2813                 rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl,
2814                                                       &hash_entry);
2815                 if (rc) {
2816                         BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n",
2817                                     gen_tbl_list->gen_tbl_name);
2818                         return rc;
2819                 }
2820                 if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) {
2821                         key_index = hash_entry.key_idx;
2822                         /* Get the generic table entry */
2823                         if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list,
2824                                                          key_index,
2825                                                          &gen_tbl_ent))
2826                                 return -EINVAL;
2827                         /* store the hash index in the fdb */
2828                         key_index = hash_entry.hash_index;
2829                 }
2830         } else {
2831                 /* convert key to index directly */
2832                 if (ULP_BITS_2_BYTE(tmplen) > (int32_t)sizeof(key_index)) {
2833                         BNXT_TF_DBG(ERR, "%s: keysize is bigger then 4 bytes\n",
2834                                     gen_tbl_list->gen_tbl_name);
2835                         return -EINVAL;
2836                 }
2837                 memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen));
2838                 /* Get the generic table entry */
2839                 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index,
2840                                                  &gen_tbl_ent))
2841                         return -EINVAL;
2842         }
2843         switch (tbl->tbl_opcode) {
2844         case BNXT_ULP_GENERIC_TBL_OPC_READ:
2845                 if (gen_tbl_list->hash_tbl) {
2846                         if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND)
2847                                 break; /* nothing to be done , no entry */
2848                 }
2849
2850                 /* check the reference count */
2851                 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2852                         g = &gen_tbl_ent;
2853                         /* Scan ident list and create the result blob*/
2854                         rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2855                                                            g->byte_data,
2856                                                            g->byte_data_size,
2857                                                            g->byte_order);
2858                         if (rc) {
2859                                 BNXT_TF_DBG(ERR,
2860                                             "Failed to scan ident list\n");
2861                                 return -EINVAL;
2862                         }
2863                         if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2864                                 /* increment the reference count */
2865                                 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2866                         }
2867
2868                         /* it is a hit */
2869                         gen_tbl_miss = 0;
2870                         fdb_write = 1;
2871                 }
2872                 break;
2873         case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2874                 if (gen_tbl_list->hash_tbl) {
2875                         rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list,
2876                                                                &hash_entry,
2877                                                                &gen_tbl_ent);
2878                         if (rc)
2879                                 return rc;
2880                         /* store the hash index in the fdb */
2881                         key_index = hash_entry.hash_index;
2882                 }
2883                 /* check the reference count */
2884                 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2885                         /* a hit then error */
2886                         BNXT_TF_DBG(ERR, "generic entry already present\n");
2887                         return -EINVAL; /* success */
2888                 }
2889
2890                 /* Initialize the blob data */
2891                 if (!ulp_blob_init(&data, tbl->result_bit_size,
2892                                    gen_tbl_ent.byte_order)) {
2893                         BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2894                         return -EINVAL;
2895                 }
2896
2897                 /* Get the result fields list */
2898                 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2899                                                  "Gen tbl Result");
2900                 if (rc) {
2901                         BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2902                         return rc;
2903                 }
2904                 byte_data = ulp_blob_data_get(&data, &tmplen);
2905                 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2906                                                        tmplen, byte_data,
2907                                                        ULP_BITS_2_BYTE(tmplen));
2908                 if (rc) {
2909                         BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2910                         return -EINVAL;
2911                 }
2912
2913                 /* increment the reference count */
2914                 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2915                 fdb_write = 1;
2916                 parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index;
2917                 break;
2918         default:
2919                 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2920                 return -EINVAL;
2921         }
2922
2923         /* Set the generic entry hit */
2924         rc = ulp_regfile_write(parms->regfile,
2925                                BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
2926                                tfp_cpu_to_be_64(gen_tbl_miss));
2927         if (rc) {
2928                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2929                             BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
2930                 return -EIO;
2931         }
2932
2933         /* add the entry to the flow database */
2934         if (fdb_write) {
2935                 memset(&fid_parms, 0, sizeof(fid_parms));
2936                 fid_parms.direction = tbl->direction;
2937                 fid_parms.resource_func = tbl->resource_func;
2938                 fid_parms.resource_sub_type = tbl->resource_sub_type;
2939                 fid_parms.resource_hndl = key_index;
2940                 fid_parms.critical_resource = tbl->critical_resource;
2941                 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2942
2943                 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2944                 if (rc)
2945                         BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2946         }
2947         return rc;
2948 }
2949
2950 static int32_t
2951 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2952                             struct bnxt_ulp_mapper_tbl_info *tbl)
2953 {
2954         int32_t rc = 0;
2955
2956         /* process the fdb opcode for alloc push */
2957         if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
2958                 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
2959                 if (rc) {
2960                         BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
2961                         return rc;
2962                 }
2963         }
2964         return rc;
2965 }
2966
2967 static int32_t
2968 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2969                                   struct bnxt_ulp_mapper_data *mapper_data)
2970 {
2971         struct bnxt_ulp_glb_resource_info *glb_res;
2972         uint32_t num_glb_res_ids, idx, dev_id;
2973         uint8_t app_id;
2974         int32_t rc = 0;
2975
2976         glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2977         if (!glb_res || !num_glb_res_ids) {
2978                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2979                 return -EINVAL;
2980         }
2981
2982         rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
2983         if (rc) {
2984                 BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n",
2985                             rc);
2986                 return rc;
2987         }
2988
2989         rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
2990         if (rc) {
2991                 BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n",
2992                             rc);
2993                 return rc;
2994         }
2995
2996         /* Iterate the global resources and process each one */
2997         for (idx = 0; idx < num_glb_res_ids; idx++) {
2998                 if (dev_id != glb_res[idx].device_id ||
2999                     glb_res[idx].app_id != app_id)
3000                         continue;
3001                 switch (glb_res[idx].resource_func) {
3002                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3003                         rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
3004                                                                 mapper_data,
3005                                                                 &glb_res[idx]);
3006                         break;
3007                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3008                         rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
3009                                                                  mapper_data,
3010                                                                  &glb_res[idx]);
3011                         break;
3012                 default:
3013                         BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
3014                                     glb_res[idx].resource_func);
3015                         rc = -EINVAL;
3016                         break;
3017                 }
3018                 if (rc)
3019                         return rc;
3020         }
3021         return rc;
3022 }
3023
3024 /*
3025  * Iterate over the shared resources assigned during tf_open_session and store
3026  * them in the global regfile with the shared flag.
3027  */
3028 static int32_t
3029 ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
3030                                       struct bnxt_ulp_mapper_data *mapper_data)
3031 {
3032         struct tf_get_shared_tbl_increment_parms iparms;
3033         struct bnxt_ulp_glb_resource_info *glb_res;
3034         struct tf_get_session_info_parms sparms;
3035         uint32_t num_entries, i, dev_id, res;
3036         struct tf_resource_info *res_info;
3037         uint32_t addend;
3038         uint64_t regval;
3039         enum tf_dir dir;
3040         int32_t rc = 0;
3041         struct tf *tfp;
3042         uint8_t app_id;
3043
3044         memset(&sparms, 0, sizeof(sparms));
3045         glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_entries);
3046         if (!glb_res || !num_entries) {
3047                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
3048                 return -EINVAL;
3049         }
3050         tfp = bnxt_ulp_cntxt_shared_tfp_get(ulp_ctx);
3051         if (!tfp) {
3052                 BNXT_TF_DBG(ERR, "Failed to get tfp for app global init");
3053                 return -EINVAL;
3054         }
3055         /*
3056          * Retrieve the resources that were assigned during the shared session
3057          * creation.
3058          */
3059         rc = tf_get_session_info(tfp, &sparms);
3060         if (rc) {
3061                 BNXT_TF_DBG(ERR, "Failed to get session info (%d)\n", rc);
3062                 return rc;
3063         }
3064
3065         rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
3066         if (rc) {
3067                 BNXT_TF_DBG(ERR, "Failed to get the app id in glb init (%d).\n",
3068                             rc);
3069                 return rc;
3070         }
3071
3072         rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
3073         if (rc) {
3074                 BNXT_TF_DBG(ERR, "Failed to get dev id for app glb init (%d)\n",
3075                             rc);
3076                 return rc;
3077         }
3078
3079         /* Store all the app global resources */
3080         for (i = 0; i < num_entries; i++) {
3081                 if (dev_id != glb_res[i].device_id ||
3082                     app_id != glb_res[i].app_id)
3083                         continue;
3084                 dir = glb_res[i].direction;
3085                 res = glb_res[i].resource_type;
3086                 addend = 1;
3087
3088                 switch (glb_res[i].resource_func) {
3089                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3090                         res_info = &sparms.session_info.ident[dir].info[res];
3091                         break;
3092                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3093                         /*
3094                          * Tables may have various strides for the allocations.
3095                          * Need to account.
3096                          */
3097                         memset(&iparms, 0, sizeof(iparms));
3098                         iparms.dir = dir;
3099                         iparms.type = res;
3100                         rc = tf_get_shared_tbl_increment(tfp, &iparms);
3101                         if (rc) {
3102                                 BNXT_TF_DBG(ERR,
3103                                             "Failed to get addend for %s[%s] rc=(%d)\n",
3104                                             tf_tbl_type_2_str(res),
3105                                             tf_dir_2_str(dir), rc);
3106                                 return rc;
3107                         }
3108                         addend = iparms.increment_cnt;
3109                         res_info = &sparms.session_info.tbl[dir].info[res];
3110                         break;
3111                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3112                         res_info = &sparms.session_info.tcam[dir].info[res];
3113                         break;
3114                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3115                         res_info = &sparms.session_info.em[dir].info[res];
3116                         break;
3117                 default:
3118                         BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n",
3119                                     glb_res[i].resource_func);
3120                         continue;
3121                 }
3122                 regval = tfp_cpu_to_be_64((uint64_t)res_info->start);
3123                 res_info->start += addend;
3124                 /*
3125                  * All resources written to the global regfile are shared for
3126                  * this function.
3127                  */
3128                 rc = ulp_mapper_glb_resource_write(mapper_data, &glb_res[i],
3129                                                    regval, true);
3130                 if (rc)
3131                         return rc;
3132         }
3133
3134         return rc;
3135 }
3136
3137 /*
3138  * Common conditional opcode process routine that is used for both the template
3139  * rejection and table conditional execution.
3140  */
3141 static int32_t
3142 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
3143                             enum bnxt_ulp_cond_opc opc,
3144                             uint32_t operand,
3145                             int32_t *res)
3146 {
3147         enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
3148         int32_t rc = 0;
3149         uint8_t bit;
3150         uint64_t regval;
3151
3152         switch (opc) {
3153         case BNXT_ULP_COND_OPC_CF_IS_SET:
3154                 if (operand < BNXT_ULP_CF_IDX_LAST) {
3155                         *res = ULP_COMP_FLD_IDX_RD(parms, operand);
3156                 } else {
3157                         BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
3158                                     operand);
3159                         rc = -EINVAL;
3160                 }
3161                 break;
3162         case BNXT_ULP_COND_OPC_CF_NOT_SET:
3163                 if (operand < BNXT_ULP_CF_IDX_LAST) {
3164                         *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
3165                 } else {
3166                         BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
3167                                     operand);
3168                         rc = -EINVAL;
3169                 }
3170                 break;
3171         case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
3172                 if (operand < BNXT_ULP_ACT_BIT_LAST) {
3173                         *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3174                                                 operand);
3175                 } else {
3176                         BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
3177                                     operand);
3178                         rc = -EINVAL;
3179                 }
3180                 break;
3181         case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
3182                 if (operand < BNXT_ULP_ACT_BIT_LAST) {
3183                         *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3184                                                operand);
3185                 } else {
3186                         BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
3187                                     operand);
3188                         rc = -EINVAL;
3189                 }
3190                 break;
3191         case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
3192                 if (operand < BNXT_ULP_HDR_BIT_LAST) {
3193                         *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3194                                                 operand);
3195                 } else {
3196                         BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3197                                     operand);
3198                         rc = -EINVAL;
3199                 }
3200                 break;
3201         case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
3202                 if (operand < BNXT_ULP_HDR_BIT_LAST) {
3203                         *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3204                                                operand);
3205                 } else {
3206                         BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3207                                     operand);
3208                         rc = -EINVAL;
3209                 }
3210                 break;
3211         case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
3212                 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3213                 if (rc) {
3214                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
3215                                     operand);
3216                         return -EINVAL;
3217                 }
3218                 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3219                 break;
3220         case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
3221                 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3222                 if (rc) {
3223                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
3224                                     operand);
3225                         return -EINVAL;
3226                 }
3227                 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3228                 break;
3229         case BNXT_ULP_COND_OPC_RF_IS_SET:
3230                 if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
3231                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
3232                         return -EINVAL;
3233                 }
3234                 *res = regval != 0;
3235                 break;
3236         case BNXT_ULP_COND_OPC_RF_NOT_SET:
3237                 if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
3238                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
3239                         return -EINVAL;
3240                 }
3241                 *res = regval == 0;
3242                 break;
3243         case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
3244                 if (parms->flow_pattern_id == operand) {
3245                         BNXT_TF_DBG(ERR, "field pattern match failed %x\n",
3246                                     parms->flow_pattern_id);
3247                         return -EINVAL;
3248                 }
3249                 break;
3250         case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
3251                 if (parms->act_pattern_id == operand) {
3252                         BNXT_TF_DBG(ERR, "act pattern match failed %x\n",
3253                                     parms->act_pattern_id);
3254                         return -EINVAL;
3255                 }
3256                 break;
3257         case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET:
3258                 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3259                         BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3260                         return -EINVAL;
3261                 }
3262                 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1;
3263                 break;
3264         case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET:
3265                 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3266                         BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3267                         return -EINVAL;
3268                 }
3269                 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0;
3270                 break;
3271         default:
3272                 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
3273                 rc = -EINVAL;
3274                 break;
3275         }
3276         return (rc);
3277 }
3278
3279 static int32_t
3280 ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms,
3281                             enum tf_dir dir,
3282                             enum bnxt_ulp_func_src func_src,
3283                             uint16_t func_opr,
3284                             uint64_t *result)
3285 {
3286         uint64_t regval;
3287         bool shared;
3288
3289         *result =  false;
3290         switch (func_src) {
3291         case BNXT_ULP_FUNC_SRC_COMP_FIELD:
3292                 if (func_opr >= BNXT_ULP_CF_IDX_LAST) {
3293                         BNXT_TF_DBG(ERR, "invalid index %u\n", func_opr);
3294                         return -EINVAL;
3295                 }
3296                 *result = ULP_COMP_FLD_IDX_RD(parms, func_opr);
3297                 break;
3298         case BNXT_ULP_FUNC_SRC_REGFILE:
3299                 if (!ulp_regfile_read(parms->regfile, func_opr, &regval)) {
3300                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", func_opr);
3301                         return -EINVAL;
3302                 }
3303                 *result = tfp_be_to_cpu_64(regval);
3304                 break;
3305         case BNXT_ULP_FUNC_SRC_GLB_REGFILE:
3306                 if (ulp_mapper_glb_resource_read(parms->mapper_data, dir,
3307                                                  func_opr, &regval, &shared)) {
3308                         BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n",
3309                                     func_opr);
3310                         return -EINVAL;
3311                 }
3312                 *result = tfp_be_to_cpu_64(regval);
3313                 break;
3314         case BNXT_ULP_FUNC_SRC_CONST:
3315                 *result = func_opr;
3316                 break;
3317         default:
3318                 BNXT_TF_DBG(ERR, "invalid src code %u\n", func_src);
3319                 return -EINVAL;
3320         }
3321         return 0;
3322 }
3323
3324 static int32_t
3325 ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms,
3326                              struct bnxt_ulp_mapper_tbl_info *tbl)
3327 {
3328         struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info;
3329         uint64_t res = 0, res1 = 0, res2 = 0;
3330         int32_t rc = 0;
3331         uint32_t process_src1 = 0, process_src2 = 0;
3332
3333         /* determine which functional operands to compute */
3334         switch (func_info->func_opc) {
3335         case BNXT_ULP_FUNC_OPC_NOP:
3336                 return rc;
3337         case BNXT_ULP_FUNC_OPC_EQ:
3338         case BNXT_ULP_FUNC_OPC_NE:
3339         case BNXT_ULP_FUNC_OPC_GE:
3340         case BNXT_ULP_FUNC_OPC_GT:
3341         case BNXT_ULP_FUNC_OPC_LE:
3342         case BNXT_ULP_FUNC_OPC_LT:
3343                 process_src1 = 1;
3344                 process_src2 = 1;
3345                 break;
3346         case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3347                 process_src1 = 1;
3348                 break;
3349         default:
3350                 break;
3351         }
3352
3353         if (process_src1) {
3354                 rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3355                                                  func_info->func_src1,
3356                                                  func_info->func_opr1, &res1);
3357                 if (rc)
3358                         return rc;
3359         }
3360
3361         if (process_src2) {
3362                 rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3363                                                  func_info->func_src2,
3364                                                  func_info->func_opr2, &res2);
3365                 if (rc)
3366                         return rc;
3367         }
3368
3369         /* perform the functional opcode operations */
3370         switch (func_info->func_opc) {
3371         case BNXT_ULP_FUNC_OPC_EQ:
3372                 if (res1 == res2)
3373                         res = 1;
3374                 break;
3375         case BNXT_ULP_FUNC_OPC_NE:
3376                 if (res1 != res2)
3377                         res = 1;
3378                 break;
3379         case BNXT_ULP_FUNC_OPC_GE:
3380                 if (res1 >= res2)
3381                         res = 1;
3382                 break;
3383         case BNXT_ULP_FUNC_OPC_GT:
3384                 if (res1 > res2)
3385                         res = 1;
3386                 break;
3387         case BNXT_ULP_FUNC_OPC_LE:
3388                 if (res1 <= res2)
3389                         res = 1;
3390                 break;
3391         case BNXT_ULP_FUNC_OPC_LT:
3392                 if (res1 < res2)
3393                         res = 1;
3394                 break;
3395         case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3396                 res = res1;
3397                 break;
3398         case BNXT_ULP_FUNC_OPC_RSS_CONFIG:
3399                 /* apply the rss config using pmd method */
3400                 return bnxt_rss_config_action_apply(parms);
3401         case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR:
3402                 rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res);
3403                 if (rc)
3404                         return -EINVAL;
3405                 res = tfp_be_to_cpu_64(res);
3406                 break;
3407         default:
3408                 BNXT_TF_DBG(ERR, "invalid func code %u\n", func_info->func_opc);
3409                 return -EINVAL;
3410         }
3411         if (ulp_regfile_write(parms->regfile, func_info->func_dst_opr,
3412                               tfp_cpu_to_be_64(res))) {
3413                 BNXT_TF_DBG(ERR, "Failed write the func_opc %u\n",
3414                             func_info->func_dst_opr);
3415                 return -EINVAL;
3416         }
3417
3418         return rc;
3419 }
3420
3421
3422 /*
3423  * Processes a list of conditions and returns both a status and result of the
3424  * list.  The status must be checked prior to verifying the result.
3425  *
3426  * returns 0 for success, negative on failure
3427  * returns res = 1 for true, res = 0 for false.
3428  */
3429 static int32_t
3430 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
3431                                  enum bnxt_ulp_cond_list_opc list_opc,
3432                                  struct bnxt_ulp_mapper_cond_info *list,
3433                                  uint32_t num,
3434                                  int32_t *res)
3435 {
3436         uint32_t i;
3437         int32_t rc = 0, trc = 0;
3438
3439         switch (list_opc) {
3440         case BNXT_ULP_COND_LIST_OPC_AND:
3441                 /* AND Defaults to true. */
3442                 *res = 1;
3443                 break;
3444         case BNXT_ULP_COND_LIST_OPC_OR:
3445                 /* OR Defaults to false. */
3446                 *res = 0;
3447                 break;
3448         case BNXT_ULP_COND_LIST_OPC_TRUE:
3449                 *res = 1;
3450                 return rc;
3451         case BNXT_ULP_COND_LIST_OPC_FALSE:
3452                 *res = 0;
3453                 return rc;
3454         default:
3455                 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
3456                             list_opc);
3457                 *res = 0;
3458                 return -EINVAL;
3459         }
3460
3461         for (i = 0; i < num; i++) {
3462                 rc = ulp_mapper_cond_opc_process(parms,
3463                                                  list[i].cond_opcode,
3464                                                  list[i].cond_operand,
3465                                                  &trc);
3466                 if (rc)
3467                         return rc;
3468
3469                 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
3470                         /* early return if result is ever zero */
3471                         if (!trc) {
3472                                 *res = trc;
3473                                 return rc;
3474                         }
3475                 } else {
3476                         /* early return if result is ever non-zero */
3477                         if (trc) {
3478                                 *res = trc;
3479                                 return rc;
3480                         }
3481                 }
3482         }
3483
3484         return rc;
3485 }
3486
3487 /*
3488  * Processes conflict resolution and returns both a status and result.
3489  * The status must be checked prior to verifying the result.
3490  *
3491  * returns 0 for success, negative on failure
3492  * returns res = 1 for true, res = 0 for false.
3493  */
3494 static int32_t
3495 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
3496                                        struct bnxt_ulp_mapper_tbl_info *tbl,
3497                                        int32_t *res)
3498 {
3499         int32_t rc = 0;
3500         uint64_t regval;
3501         uint64_t comp_sig;
3502
3503         *res = 0;
3504         switch (tbl->accept_opcode) {
3505         case BNXT_ULP_ACCEPT_OPC_ALWAYS:
3506                 *res = 1;
3507                 break;
3508         case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
3509                 /* perform the signature validation*/
3510                 if (tbl->resource_func ==
3511                     BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
3512                         /* Perform the check that generic table is hit or not */
3513                         if (!ulp_regfile_read(parms->regfile,
3514                                               BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3515                                               &regval)) {
3516                                 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3517                                             BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3518                                 return -EINVAL;
3519                         }
3520                         if (regval) {
3521                                 /* not a hit so no need to check flow sign*/
3522                                 *res = 1;
3523                                 return rc;
3524                         }
3525                 }
3526                 /* compare the new flow signature against stored one */
3527                 if (!ulp_regfile_read(parms->regfile,
3528                                       BNXT_ULP_RF_IDX_FLOW_SIG_ID,
3529                                       &regval)) {
3530                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3531                                     BNXT_ULP_RF_IDX_FLOW_SIG_ID);
3532                         return -EINVAL;
3533                 }
3534                 comp_sig = ULP_COMP_FLD_IDX_RD(parms,
3535                                                BNXT_ULP_CF_IDX_FLOW_SIG_ID);
3536                 regval = tfp_be_to_cpu_64(regval);
3537                 if (comp_sig == regval)
3538                         *res = 1;
3539                 else
3540                         BNXT_TF_DBG(ERR, "failed signature match 0x%016"
3541                                     PRIX64 ":%x\n", comp_sig, (uint32_t)regval);
3542                 break;
3543         default:
3544                 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
3545                             tbl->accept_opcode);
3546                 return -EINVAL;
3547         }
3548         return rc;
3549 }
3550
3551 static int32_t
3552 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
3553 {
3554         struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
3555         enum bnxt_ulp_cond_list_opc cond_opc;
3556         struct bnxt_ulp_mapper_tbl_info *tbls;
3557         struct bnxt_ulp_mapper_tbl_info *tbl;
3558         uint32_t num_tbls, tbl_idx, num_cond_tbls;
3559         int32_t rc = -EINVAL, cond_rc = 0;
3560         int32_t cond_goto = 1;
3561
3562         cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
3563                                                     &num_cond_tbls,
3564                                                     &cond_opc);
3565         /*
3566          * Process the reject list if exists, otherwise assume that the
3567          * template is allowed.
3568          */
3569         if (cond_tbls && num_cond_tbls) {
3570                 rc = ulp_mapper_cond_opc_list_process(parms,
3571                                                       cond_opc,
3572                                                       cond_tbls,
3573                                                       num_cond_tbls,
3574                                                       &cond_rc);
3575                 if (rc)
3576                         return rc;
3577
3578                 /* Reject the template if True */
3579                 if (cond_rc) {
3580                         BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
3581                                     ulp_mapper_tmpl_name_str(parms->tmpl_type),
3582                                     tid);
3583                         return -EINVAL;
3584                 }
3585         }
3586
3587         tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
3588         if (!tbls || !num_tbls) {
3589                 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
3590                             ulp_mapper_tmpl_name_str(parms->tmpl_type),
3591                             parms->dev_id, tid);
3592                 return -EINVAL;
3593         }
3594
3595         for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
3596                 tbl = &tbls[tbl_idx];
3597                 cond_goto = tbl->execute_info.cond_true_goto;
3598 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
3599 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER
3600                 ulp_mapper_table_dump(tbl, tbl_idx);
3601 #endif
3602 #endif
3603                 /* Process the conditional func code opcodes */
3604                 if (ulp_mapper_func_info_process(parms, tbl)) {
3605                         BNXT_TF_DBG(ERR, "Failed to process cond update\n");
3606                         rc = -EINVAL;
3607                         goto error;
3608                 }
3609
3610                 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
3611                                                             &num_cond_tbls,
3612                                                             &cond_opc);
3613                 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
3614                                                       cond_tbls, num_cond_tbls,
3615                                                       &cond_rc);
3616                 if (rc) {
3617                         BNXT_TF_DBG(ERR, "Failed to proc cond opc list (%d)\n",
3618                                     rc);
3619                         goto error;
3620                 }
3621                 /* Skip the table if False */
3622                 if (!cond_rc) {
3623                         cond_goto = tbl->execute_info.cond_false_goto;
3624                         goto next_iteration;
3625                 }
3626
3627                 switch (tbl->resource_func) {
3628                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3629                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
3630                         break;
3631                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3632                         rc = ulp_mapper_em_tbl_process(parms, tbl);
3633                         break;
3634                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3635                         rc = ulp_mapper_index_tbl_process(parms, tbl);
3636                         break;
3637                 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
3638                         rc = ulp_mapper_if_tbl_process(parms, tbl);
3639                         break;
3640                 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3641                         rc = ulp_mapper_gen_tbl_process(parms, tbl);
3642                         break;
3643                 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3644                         rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3645                         break;
3646                 case BNXT_ULP_RESOURCE_FUNC_INVALID:
3647                         rc = 0;
3648                         break;
3649                 default:
3650                         BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3651                                     tbl->resource_func);
3652                         rc = -EINVAL;
3653                         goto error;
3654                 }
3655
3656                 if (rc) {
3657                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3658                                     tbl->resource_func);
3659                         goto error;
3660                 }
3661
3662                 /* perform the post table process */
3663                 rc  = ulp_mapper_conflict_resolution_process(parms, tbl,
3664                                                              &cond_rc);
3665                 if (rc || !cond_rc) {
3666                         BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3667                         rc = -EINVAL;
3668                         goto error;
3669                 }
3670 next_iteration:
3671                 if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) {
3672                         BNXT_TF_DBG(ERR, "reject the flow\n");
3673                         rc = -EINVAL;
3674                         goto error;
3675                 } else if (cond_goto & BNXT_ULP_COND_GOTO_RF) {
3676                         uint32_t rf_idx;
3677                         uint64_t regval;
3678
3679                         /* least significant 16 bits from reg_file index */
3680                         rf_idx = (uint32_t)(cond_goto & 0xFFFF);
3681                         if (!ulp_regfile_read(parms->regfile, rf_idx,
3682                                               &regval)) {
3683                                 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3684                                             rf_idx);
3685                                 rc = -EINVAL;
3686                                 goto error;
3687                         }
3688                         cond_goto = (int32_t)regval;
3689                 }
3690
3691                 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3692                         BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3693                                     cond_goto);
3694                         goto error;
3695                 }
3696                 tbl_idx += cond_goto;
3697         }
3698
3699         return rc;
3700 error:
3701         BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3702                     ulp_mapper_tmpl_name_str(parms->tmpl_type),
3703                     parms->dev_id, tid);
3704         return rc;
3705 }
3706
3707 static int32_t
3708 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3709                          uint32_t fid,
3710                          struct ulp_flow_db_res_params *res)
3711 {
3712         struct tf *tfp;
3713         int32_t rc = 0;
3714
3715         if (!res || !ulp) {
3716                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3717                 return -EINVAL;
3718         }
3719         if (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION)
3720                 tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_YES);
3721         else
3722                 tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_NO);
3723         if (!tfp) {
3724                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3725                 return -EINVAL;
3726         }
3727
3728         switch (res->resource_func) {
3729         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3730                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3731                 break;
3732         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3733                 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3734                 break;
3735         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3736                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3737                 break;
3738         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3739                 rc = ulp_mapper_ident_free(ulp, tfp, res);
3740                 break;
3741         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3742                 rc = ulp_mapper_mark_free(ulp, res);
3743                 break;
3744         case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3745                 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3746                 break;
3747         case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3748                 rc = ulp_mapper_child_flow_free(ulp, fid, res);
3749                 break;
3750         case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3751                 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3752                 break;
3753         default:
3754                 break;
3755         }
3756
3757         return rc;
3758 }
3759
3760 int32_t
3761 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3762                           enum bnxt_ulp_fdb_type flow_type,
3763                           uint32_t fid)
3764 {
3765         struct ulp_flow_db_res_params res_parms = { 0 };
3766         int32_t rc, trc;
3767
3768         if (!ulp_ctx) {
3769                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3770                 return -EINVAL;
3771         }
3772
3773         /*
3774          * Set the critical resource on the first resource del, then iterate
3775          * while status is good
3776          */
3777         if (flow_type != BNXT_ULP_FDB_TYPE_RID)
3778                 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3779
3780         rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3781
3782         if (rc) {
3783                 /*
3784                  * This is unexpected on the first call to resource del.
3785                  * It likely means that the flow did not exist in the flow db.
3786                  */
3787                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3788                             flow_type, fid, rc);
3789                 return rc;
3790         }
3791
3792         while (!rc) {
3793                 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3794                 if (trc)
3795                         /*
3796                          * On fail, we still need to attempt to free the
3797                          * remaining resources.  Don't return
3798                          */
3799                         BNXT_TF_DBG(ERR,
3800                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIX64
3801                                     "] failed rc=%d.\n",
3802                                     flow_type, fid, res_parms.resource_func,
3803                                     res_parms.resource_hndl, trc);
3804
3805                 /* All subsequent call require the non-critical_resource */
3806                 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3807
3808                 rc = ulp_flow_db_resource_del(ulp_ctx,
3809                                               flow_type,
3810                                               fid,
3811                                               &res_parms);
3812         }
3813
3814         /* Free the Flow ID since we've removed all resources */
3815         rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3816
3817         return rc;
3818 }
3819
3820 static void
3821 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3822                                     struct bnxt_ulp_mapper_data *mapper_data)
3823 {
3824         struct bnxt_ulp_mapper_glb_resource_entry *ent;
3825         struct ulp_flow_db_res_params res;
3826         uint32_t dir, idx;
3827
3828         /* Iterate the global resources and process each one */
3829         for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3830                 for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) {
3831                         ent = &mapper_data->glb_res_tbl[dir][idx];
3832                         if (ent->resource_func ==
3833                             BNXT_ULP_RESOURCE_FUNC_INVALID ||
3834                             ent->shared)
3835                                 continue;
3836                         memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3837                         res.resource_func = ent->resource_func;
3838                         res.direction = dir;
3839                         res.resource_type = ent->resource_type;
3840                         /*convert it from BE to cpu */
3841                         res.resource_hndl =
3842                                 tfp_be_to_cpu_64(ent->resource_hndl);
3843                         ulp_mapper_resource_free(ulp_ctx, 0, &res);
3844                 }
3845         }
3846 }
3847
3848 int32_t
3849 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3850                         enum bnxt_ulp_fdb_type flow_type,
3851                         uint32_t fid)
3852 {
3853         int32_t rc;
3854
3855         if (!ulp_ctx) {
3856                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3857                 return -EINVAL;
3858         }
3859
3860         rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3861         return rc;
3862 }
3863
3864 /* Function to handle the mapping of the Flow to be compatible
3865  * with the underlying hardware.
3866  */
3867 int32_t
3868 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3869                        struct bnxt_ulp_mapper_create_parms *cparms)
3870 {
3871         struct bnxt_ulp_mapper_parms parms;
3872         struct ulp_regfile regfile;
3873         int32_t  rc = 0, trc;
3874
3875         if (!ulp_ctx || !cparms)
3876                 return -EINVAL;
3877
3878         /* Initialize the parms structure */
3879         memset(&parms, 0, sizeof(parms));
3880         parms.act_prop = cparms->act_prop;
3881         parms.act_bitmap = cparms->act;
3882         parms.hdr_bitmap = cparms->hdr_bitmap;
3883         parms.regfile = &regfile;
3884         parms.hdr_field = cparms->hdr_field;
3885         parms.fld_bitmap = cparms->fld_bitmap;
3886         parms.comp_fld = cparms->comp_fld;
3887         parms.ulp_ctx = ulp_ctx;
3888         parms.act_tid = cparms->act_tid;
3889         parms.class_tid = cparms->class_tid;
3890         parms.flow_type = cparms->flow_type;
3891         parms.parent_flow = cparms->parent_flow;
3892         parms.parent_fid = cparms->parent_fid;
3893         parms.fid = cparms->flow_id;
3894         parms.tun_idx = cparms->tun_idx;
3895         parms.app_priority = cparms->app_priority;
3896         parms.flow_pattern_id = cparms->flow_pattern_id;
3897         parms.act_pattern_id = cparms->act_pattern_id;
3898         parms.app_id = cparms->app_id;
3899         parms.port_id = cparms->port_id;
3900
3901         /* Get the device id from the ulp context */
3902         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3903                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3904                 return -EINVAL;
3905         }
3906
3907         /* Get the device params, it will be used in later processing */
3908         parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3909         if (!parms.device_params) {
3910                 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3911                             parms.dev_id);
3912                 return -EINVAL;
3913         }
3914
3915         /*
3916          * Get the mapper data for dynamic mapper data such as default
3917          * ids.
3918          */
3919         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3920                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3921         if (!parms.mapper_data) {
3922                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3923                 return -EINVAL;
3924         }
3925
3926         /* initialize the registry file for further processing */
3927         if (!ulp_regfile_init(parms.regfile)) {
3928                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3929                 return -EINVAL;
3930         }
3931
3932         /* Process the action template list from the selected action table*/
3933         if (parms.act_tid) {
3934                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3935                 /* Process the action template tables */
3936                 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3937                 if (rc)
3938                         goto flow_error;
3939                 cparms->shared_hndl = parms.shared_hndl;
3940         }
3941
3942         if (parms.class_tid) {
3943                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3944
3945                 /* Process the class template tables.*/
3946                 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3947                 if (rc)
3948                         goto flow_error;
3949         }
3950
3951         /* setup the parent-child details */
3952         if (parms.parent_flow) {
3953                 /* create a parent flow details */
3954                 rc = ulp_flow_db_parent_flow_create(&parms);
3955                 if (rc)
3956                         goto flow_error;
3957         } else if (parms.parent_fid) {
3958                 /* create a child flow details */
3959                 rc = ulp_flow_db_child_flow_create(&parms);
3960                 if (rc)
3961                         goto flow_error;
3962         }
3963
3964         return rc;
3965
3966 flow_error:
3967         /* Free all resources that were allocated during flow creation */
3968         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
3969                                       parms.fid);
3970         if (trc)
3971                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3972
3973         return rc;
3974 }
3975
3976 int32_t
3977 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3978 {
3979         struct bnxt_ulp_mapper_data *data;
3980         struct tf *tfp;
3981         int32_t rc;
3982
3983         if (!ulp_ctx)
3984                 return -EINVAL;
3985
3986         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
3987         if (!tfp)
3988                 return -EINVAL;
3989
3990         data = rte_zmalloc("ulp_mapper_data",
3991                            sizeof(struct bnxt_ulp_mapper_data), 0);
3992         if (!data) {
3993                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3994                 return -ENOMEM;
3995         }
3996
3997         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3998                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3999                 /* Don't call deinit since the prof_func wasn't allocated. */
4000                 rte_free(data);
4001                 return -ENOMEM;
4002         }
4003
4004         /* Allocate the global resource ids */
4005         rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
4006         if (rc) {
4007                 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
4008                 goto error;
4009         }
4010
4011         /*
4012          * Only initialize the app global resources if a shared session was
4013          * created.
4014          */
4015         if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) {
4016                 rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data);
4017                 if (rc) {
4018                         BNXT_TF_DBG(ERR, "Failed to init app glb resources\n");
4019                         goto error;
4020                 }
4021         }
4022
4023         /* Allocate the generic table list */
4024         rc = ulp_mapper_generic_tbl_list_init(data);
4025         if (rc) {
4026                 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
4027                 goto error;
4028         }
4029
4030         return 0;
4031 error:
4032         /* Ignore the return code in favor of returning the original error. */
4033         ulp_mapper_deinit(ulp_ctx);
4034         return rc;
4035 }
4036
4037 void
4038 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
4039 {
4040         struct bnxt_ulp_mapper_data *data;
4041         struct tf *tfp;
4042
4043         if (!ulp_ctx) {
4044                 BNXT_TF_DBG(ERR,
4045                             "Failed to acquire ulp context, so data may not be released.\n");
4046                 return;
4047         }
4048
4049         data = (struct bnxt_ulp_mapper_data *)
4050                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
4051         if (!data) {
4052                 /* Go ahead and return since there is no allocated data. */
4053                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
4054                 return;
4055         }
4056
4057         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
4058         if (!tfp) {
4059                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
4060                 /* Free the mapper data regardless of errors. */
4061                 goto free_mapper_data;
4062         }
4063
4064         /* Free the global resource info table entries */
4065         ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
4066
4067 free_mapper_data:
4068         /* Free the generic table */
4069         (void)ulp_mapper_generic_tbl_list_deinit(data);
4070
4071         rte_free(data);
4072         /* Reset the data pointer within the ulp_ctx. */
4073         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
4074 }