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