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