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