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