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