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