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