45c17cffeba963926aad32c2daf4223d5515e57c
[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 tmpval[16];
896         uint8_t bit;
897         uint32_t src1_sel = 0;
898         enum bnxt_ulp_field_src fld_src;
899         uint8_t *fld_src_oper;
900
901         bitlen = fld->field_bit_size;
902         /* Evaluate the condition */
903         switch (fld->field_cond_src) {
904         case BNXT_ULP_FIELD_COND_SRC_TRUE:
905                 src1_sel = 1;
906                 break;
907         case BNXT_ULP_FIELD_COND_SRC_CF:
908                 if (!ulp_operand_read(fld->field_cond_opr,
909                                       (uint8_t *)&idx, sizeof(uint16_t))) {
910                         BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
911                         return -EINVAL;
912                 }
913                 idx = tfp_be_to_cpu_16(idx);
914                 if (idx >= BNXT_ULP_CF_IDX_LAST) {
915                         BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
916                         return -EINVAL;
917                 }
918                 /* check if the computed field is set */
919                 if (ULP_COMP_FLD_IDX_RD(parms, idx))
920                         src1_sel = 1;
921                 break;
922         case BNXT_ULP_FIELD_COND_SRC_RF:
923                 if (!ulp_operand_read(fld->field_cond_opr,
924                                       (uint8_t *)&idx, sizeof(uint16_t))) {
925                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
926                         return -EINVAL;
927                 }
928
929                 idx = tfp_be_to_cpu_16(idx);
930                 /* Uninitialized regfile entries return 0 */
931                 if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
932                         BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
933                                     name, idx);
934                         return -EINVAL;
935                 }
936                 if (regval)
937                         src1_sel = 1;
938                 break;
939         case BNXT_ULP_FIELD_COND_SRC_ACT_BIT:
940                 if (!ulp_operand_read(fld->field_cond_opr,
941                                       (uint8_t *)&act_bit, sizeof(uint64_t))) {
942                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
943                         return -EINVAL;
944                 }
945                 act_bit = tfp_be_to_cpu_64(act_bit);
946                 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
947                         src1_sel = 1;
948                 break;
949         case BNXT_ULP_FIELD_COND_SRC_HDR_BIT:
950                 if (!ulp_operand_read(fld->field_cond_opr,
951                                       (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
952                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
953                         return -EINVAL;
954                 }
955                 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
956                 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
957                         src1_sel = 1;
958                 break;
959         case BNXT_ULP_FIELD_COND_SRC_FIELD_BIT:
960                 if (!ulp_operand_read(fld->field_cond_opr, (uint8_t *)&idx,
961                                       sizeof(uint16_t))) {
962                         BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
963                         return -EINVAL;
964                 }
965                 idx = tfp_be_to_cpu_16(idx);
966                 /* get the index from the global field list */
967                 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
968                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
969                                     idx);
970                         return -EINVAL;
971                 }
972                 if (bit && (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)))
973                         src1_sel = 1;
974                 break;
975         default:
976                 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
977                             name, fld->field_cond_src, write_idx);
978                 return -EINVAL;
979         }
980
981         /* pick the selected source */
982         if (src1_sel) {
983                 fld_src = fld->field_src1;
984                 fld_src_oper = fld->field_opr1;
985         } else {
986                 fld_src = fld->field_src2;
987                 fld_src_oper = fld->field_opr2;
988         }
989
990         /* Perform the action */
991         switch (fld_src) {
992         case BNXT_ULP_FIELD_SRC_ZERO:
993                 if (ulp_blob_pad_push(blob, bitlen) < 0) {
994                         BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
995                         return -EINVAL;
996                 }
997                 break;
998         case BNXT_ULP_FIELD_SRC_CONST:
999                 val = fld_src_oper;
1000                 if (!ulp_blob_push(blob, val, bitlen)) {
1001                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1002                         return -EINVAL;
1003                 }
1004                 break;
1005         case BNXT_ULP_FIELD_SRC_CF:
1006                 if (!ulp_operand_read(fld_src_oper,
1007                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1008                         BNXT_TF_DBG(ERR, "%s operand read failed.\n",
1009                                     name);
1010                         return -EINVAL;
1011                 }
1012                 idx = tfp_be_to_cpu_16(idx);
1013                 if (idx < BNXT_ULP_CF_IDX_LAST)
1014                         val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1015                                                bitlen);
1016                 if (!val) {
1017                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1018                         return -EINVAL;
1019                 }
1020                 break;
1021         case BNXT_ULP_FIELD_SRC_RF:
1022                 if (!ulp_operand_read(fld_src_oper,
1023                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1024                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1025                         return -EINVAL;
1026                 }
1027
1028                 idx = tfp_be_to_cpu_16(idx);
1029                 /* Uninitialized regfile entries return 0 */
1030                 if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
1031                         BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
1032                                     name, idx);
1033                         return -EINVAL;
1034                 }
1035
1036                 val = ulp_blob_push_64(blob, &regval, bitlen);
1037                 if (!val) {
1038                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1039                         return -EINVAL;
1040                 }
1041                 break;
1042         case BNXT_ULP_FIELD_SRC_ACT_PROP:
1043                 if (!ulp_operand_read(fld_src_oper,
1044                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1045                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1046                         return -EINVAL;
1047                 }
1048                 idx = tfp_be_to_cpu_16(idx);
1049
1050                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1051                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1052                         return -EINVAL;
1053                 }
1054                 val = &parms->act_prop->act_details[idx];
1055                 field_size = ulp_mapper_act_prop_size_get(idx);
1056                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1057                         field_size  = field_size - ((bitlen + 7) / 8);
1058                         val += field_size;
1059                 }
1060                 if (!ulp_blob_push(blob, val, bitlen)) {
1061                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1062                         return -EINVAL;
1063                 }
1064                 break;
1065         case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1066                 if (!ulp_operand_read(fld_src_oper,
1067                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1068                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1069                         return -EINVAL;
1070                 }
1071                 idx = tfp_be_to_cpu_16(idx);
1072
1073                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1074                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1075                         return -EINVAL;
1076                 }
1077                 val = &parms->act_prop->act_details[idx];
1078
1079                 /* get the size index next */
1080                 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1081                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
1082                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1083                         return -EINVAL;
1084                 }
1085                 size_idx = tfp_be_to_cpu_16(size_idx);
1086
1087                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1088                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1089                         return -EINVAL;
1090                 }
1091                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1092                        sizeof(uint32_t));
1093                 val_size = tfp_be_to_cpu_32(val_size);
1094                 val_size = ULP_BYTE_2_BITS(val_size);
1095                 ulp_blob_push_encap(blob, val, val_size);
1096                 break;
1097         case BNXT_ULP_FIELD_SRC_GLB_RF:
1098                 if (!ulp_operand_read(fld_src_oper,
1099                                       (uint8_t *)&idx,
1100                                       sizeof(uint16_t))) {
1101                         BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1102                         return -EINVAL;
1103                 }
1104                 idx = tfp_be_to_cpu_16(idx);
1105                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1106                                                  dir,
1107                                                  idx, &regval)) {
1108                         BNXT_TF_DBG(ERR, "%s global regfile[%d] read failed.\n",
1109                                     name, idx);
1110                         return -EINVAL;
1111                 }
1112                 val = ulp_blob_push_64(blob, &regval, bitlen);
1113                 if (!val) {
1114                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1115                         return -EINVAL;
1116                 }
1117                 break;
1118         case BNXT_ULP_FIELD_SRC_HF:
1119                 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1120                                       sizeof(uint16_t))) {
1121                         BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1122                         return -EINVAL;
1123                 }
1124                 idx = tfp_be_to_cpu_16(idx);
1125                 /* get the index from the global field list */
1126                 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1127                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1128                                     idx);
1129                         return -EINVAL;
1130                 }
1131                 if (is_key)
1132                         val = parms->hdr_field[bit].spec;
1133                 else
1134                         val = parms->hdr_field[bit].mask;
1135
1136                 /*
1137                  * Need to account for how much data was pushed to the header
1138                  * field vs how much is to be inserted in the key/mask.
1139                  */
1140                 field_size = parms->hdr_field[bit].size;
1141                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1142                         field_size  = field_size - ((bitlen + 7) / 8);
1143                         val += field_size;
1144                 }
1145
1146                 if (!ulp_blob_push(blob, val, bitlen)) {
1147                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1148                         return -EINVAL;
1149                 }
1150                 break;
1151         case BNXT_ULP_FIELD_SRC_HDR_BIT:
1152                 if (!ulp_operand_read(fld_src_oper,
1153                                       (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1154                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1155                         return -EINVAL;
1156                 }
1157                 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1158                 memset(tmpval, 0, sizeof(tmpval));
1159                 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1160                         tmpval[0] = 1;
1161                 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1162                         BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1163                         return -EINVAL;
1164                 }
1165                 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1166                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1167                         return -EINVAL;
1168                 }
1169                 val = tmpval;
1170                 break;
1171         case BNXT_ULP_FIELD_SRC_ACT_BIT:
1172                 if (!ulp_operand_read(fld_src_oper,
1173                                       (uint8_t *)&act_bit, sizeof(uint64_t))) {
1174                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1175                         return -EINVAL;
1176                 }
1177                 act_bit = tfp_be_to_cpu_64(act_bit);
1178                 memset(tmpval, 0, sizeof(tmpval));
1179                 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1180                         tmpval[0] = 1;
1181                 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1182                         BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1183                         return -EINVAL;
1184                 }
1185                 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1186                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1187                         return -EINVAL;
1188                 }
1189                 val = tmpval;
1190                 break;
1191         case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1192                 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1193                                       sizeof(uint16_t))) {
1194                         BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1195                         return -EINVAL;
1196                 }
1197                 idx = tfp_be_to_cpu_16(idx);
1198                 /* get the index from the global field list */
1199                 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1200                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1201                                     idx);
1202                         return -EINVAL;
1203                 }
1204                 memset(tmpval, 0, sizeof(tmpval));
1205                 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit))
1206                         tmpval[0] = 1;
1207                 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1208                         BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1209                         return -EINVAL;
1210                 }
1211                 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1212                         BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1213                         return -EINVAL;
1214                 }
1215                 val = tmpval;
1216                 break;
1217         case BNXT_ULP_FIELD_SRC_SKIP:
1218                 /* do nothing */
1219                 break;
1220         case BNXT_ULP_FIELD_SRC_REJECT:
1221                 return -EINVAL;
1222         default:
1223                 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1224                             name, fld_src, write_idx);
1225                 return -EINVAL;
1226         }
1227         return 0;
1228 }
1229
1230 /*
1231  * Result table process and fill the result blob.
1232  * data [out] - the result blob data
1233  */
1234 static int32_t
1235 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1236                             struct bnxt_ulp_mapper_tbl_info *tbl,
1237                             struct ulp_blob *data,
1238                             const char *name)
1239 {
1240         struct bnxt_ulp_mapper_field_info *dflds;
1241         uint32_t i, num_flds = 0, encap_flds = 0;
1242         int32_t rc = 0;
1243
1244         /* Get the result field list */
1245         dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1246                                              &encap_flds);
1247
1248         /* validate the result field list counts */
1249         if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1250              (!num_flds && !encap_flds)) || !dflds ||
1251             (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1252                 (!num_flds || encap_flds))) {
1253                 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1254                             num_flds, encap_flds);
1255                 return -EINVAL;
1256         }
1257
1258         /* process the result fields, loop through them */
1259         for (i = 0; i < (num_flds + encap_flds); i++) {
1260                 /* set the swap index if encap swap bit is enabled */
1261                 if (parms->device_params->encap_byte_swap && encap_flds &&
1262                     i == num_flds)
1263                         ulp_blob_encap_swap_idx_set(data);
1264
1265                 /* Process the result fields */
1266                 rc = ulp_mapper_field_process(parms, tbl->direction,
1267                                               &dflds[i], data, 0, name);
1268                 if (rc) {
1269                         BNXT_TF_DBG(ERR, "data field failed\n");
1270                         return rc;
1271                 }
1272         }
1273
1274         /* if encap bit swap is enabled perform the bit swap */
1275         if (parms->device_params->encap_byte_swap && encap_flds)
1276                 ulp_blob_perform_encap_swap(data);
1277
1278         return rc;
1279 }
1280
1281 static int32_t
1282 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1283                              struct bnxt_ulp_mapper_tbl_info *tbl,
1284                              uint64_t flow_id)
1285 {
1286         struct ulp_flow_db_res_params fid_parms;
1287         uint32_t mark, gfid, mark_flag;
1288         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1289         int32_t rc = 0;
1290
1291         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1292             !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1293              ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1294                               BNXT_ULP_ACT_BIT_MARK)))
1295                 return rc; /* no need to perform gfid process */
1296
1297         /* Get the mark id details from action property */
1298         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1299                sizeof(mark));
1300         mark = tfp_be_to_cpu_32(mark);
1301
1302         TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1303         mark_flag  = BNXT_ULP_MARK_GLOBAL_HW_FID;
1304
1305         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1306                                   gfid, mark);
1307         if (rc) {
1308                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1309                 return rc;
1310         }
1311         fid_parms.direction = tbl->direction;
1312         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1313         fid_parms.critical_resource = tbl->critical_resource;
1314         fid_parms.resource_type = mark_flag;
1315         fid_parms.resource_hndl = gfid;
1316         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1317         if (rc)
1318                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1319         return rc;
1320 }
1321
1322 static int32_t
1323 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1324                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1325 {
1326         struct ulp_flow_db_res_params fid_parms;
1327         uint32_t act_idx, mark, mark_flag;
1328         uint64_t val64;
1329         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1330         int32_t rc = 0;
1331
1332         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1333             !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1334              ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1335                               BNXT_ULP_ACT_BIT_MARK)))
1336                 return rc; /* no need to perform mark action process */
1337
1338         /* Get the mark id details from action property */
1339         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1340                sizeof(mark));
1341         mark = tfp_be_to_cpu_32(mark);
1342
1343         if (!ulp_regfile_read(parms->regfile,
1344                               BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1345                               &val64)) {
1346                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1347                 return -EINVAL;
1348         }
1349         act_idx = tfp_be_to_cpu_64(val64);
1350         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID;
1351         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1352                                   act_idx, mark);
1353         if (rc) {
1354                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1355                 return rc;
1356         }
1357         fid_parms.direction = tbl->direction;
1358         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1359         fid_parms.critical_resource = tbl->critical_resource;
1360         fid_parms.resource_type = mark_flag;
1361         fid_parms.resource_hndl = act_idx;
1362         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1363         if (rc)
1364                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1365         return rc;
1366 }
1367
1368 static int32_t
1369 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1370                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1371 {
1372         struct ulp_flow_db_res_params fid_parms;
1373         uint32_t act_idx, mark, mark_flag;
1374         uint64_t val64;
1375         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1376         int32_t rc = 0;
1377
1378         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1379             mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1380                 return rc; /* no need to perform mark action process */
1381
1382         /* Get the mark id details from the computed field of dev port id */
1383         mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1384
1385          /* Get the main action pointer */
1386         if (!ulp_regfile_read(parms->regfile,
1387                               BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1388                               &val64)) {
1389                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1390                 return -EINVAL;
1391         }
1392         act_idx = tfp_be_to_cpu_64(val64);
1393
1394         /* Set the mark flag to local fid and vfr flag */
1395         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1396
1397         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1398                                   act_idx, mark);
1399         if (rc) {
1400                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1401                 return rc;
1402         }
1403         fid_parms.direction = tbl->direction;
1404         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1405         fid_parms.critical_resource = tbl->critical_resource;
1406         fid_parms.resource_type = mark_flag;
1407         fid_parms.resource_hndl = act_idx;
1408         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1409         if (rc)
1410                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1411         return rc;
1412 }
1413
1414 /* Tcam table scan the identifier list and allocate each identifier */
1415 static int32_t
1416 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1417                                      struct bnxt_ulp_mapper_tbl_info *tbl)
1418 {
1419         struct bnxt_ulp_mapper_ident_info *idents;
1420         uint32_t num_idents;
1421         uint32_t i;
1422
1423         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1424         for (i = 0; i < num_idents; i++) {
1425                 if (ulp_mapper_ident_process(parms, tbl,
1426                                              &idents[i], NULL))
1427                         return -EINVAL;
1428         }
1429         return 0;
1430 }
1431
1432 /*
1433  * Tcam table scan the identifier list and extract the identifier from
1434  * the result blob.
1435  */
1436 static int32_t
1437 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1438                                        struct bnxt_ulp_mapper_tbl_info *tbl,
1439                                        struct ulp_blob *data)
1440 {
1441         struct bnxt_ulp_mapper_ident_info *idents;
1442         uint32_t num_idents = 0, i;
1443         int32_t rc = 0;
1444
1445         /*
1446          * Extract the listed identifiers from the result field,
1447          * no need to allocate them.
1448          */
1449         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1450         for (i = 0; i < num_idents; i++) {
1451                 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1452                 if (rc) {
1453                         BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1454                         return rc;
1455                 }
1456         }
1457         return rc;
1458 }
1459
1460 /* Internal function to write the tcam entry */
1461 static int32_t
1462 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1463                                 struct bnxt_ulp_mapper_tbl_info *tbl,
1464                                 struct ulp_blob *key,
1465                                 struct ulp_blob *mask,
1466                                 struct ulp_blob *data,
1467                                 uint16_t idx)
1468 {
1469         struct tf_set_tcam_entry_parms sparms = { 0 };
1470         struct tf *tfp;
1471         uint16_t tmplen;
1472         int32_t rc;
1473
1474         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1475         if (!tfp) {
1476                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1477                 return -EINVAL;
1478         }
1479
1480         sparms.dir              = tbl->direction;
1481         sparms.tcam_tbl_type    = tbl->resource_type;
1482         sparms.idx              = idx;
1483         /* Already verified the key/mask lengths */
1484         sparms.key              = ulp_blob_data_get(key, &tmplen);
1485         sparms.mask             = ulp_blob_data_get(mask, &tmplen);
1486         sparms.key_sz_in_bits   = tbl->key_bit_size;
1487         sparms.result           = ulp_blob_data_get(data, &tmplen);
1488
1489         if (tbl->result_bit_size != tmplen) {
1490                 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1491                             tmplen, tbl->result_bit_size);
1492                 return -EINVAL;
1493         }
1494         sparms.result_sz_in_bits = tbl->result_bit_size;
1495         if (tf_set_tcam_entry(tfp, &sparms)) {
1496                 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1497                             tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1498                             tf_dir_2_str(sparms.dir), sparms.idx);
1499                 return -EIO;
1500         }
1501
1502         /* Mark action */
1503         rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1504         if (rc) {
1505                 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1506                 return rc;
1507         }
1508
1509         return rc;
1510 }
1511
1512 #define BNXT_ULP_WC_TCAM_SLICE_SIZE 80
1513 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1514 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob,
1515                                                 uint32_t len)
1516 {
1517         uint8_t mode[2] = {0x0, 0x0};
1518         uint32_t mode_len = len / BNXT_ULP_WC_TCAM_SLICE_SIZE;
1519         uint32_t size, idx;
1520
1521         /* Add the mode bits to the key and mask*/
1522         if (mode_len == 2)
1523                 mode[1] = 2;
1524         else if (mode_len > 2)
1525                 mode[1] = 3;
1526
1527         size = BNXT_ULP_WC_TCAM_SLICE_SIZE + ULP_BYTE_2_BITS(sizeof(mode));
1528         for (idx = 0; idx < mode_len; idx++)
1529                 ulp_blob_insert(blob, (size * idx), mode,
1530                                 ULP_BYTE_2_BITS(sizeof(mode)));
1531         ulp_blob_perform_64B_word_swap(blob);
1532         ulp_blob_perform_64B_byte_swap(blob);
1533 }
1534
1535 static int32_t
1536 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1537                             struct bnxt_ulp_mapper_tbl_info *tbl)
1538 {
1539         struct bnxt_ulp_mapper_key_info *kflds;
1540         struct ulp_blob key, mask, data, update_data;
1541         uint32_t i, num_kflds;
1542         struct tf *tfp;
1543         int32_t rc, trc;
1544         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
1545         struct tf_search_tcam_entry_parms searchparms   = { 0 };
1546         struct ulp_flow_db_res_params   fid_parms       = { 0 };
1547         struct tf_free_tcam_entry_parms free_parms      = { 0 };
1548         uint32_t hit = 0;
1549         uint16_t tmplen = 0;
1550         uint16_t idx;
1551
1552         /* Skip this if table opcode is NOP */
1553         if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1554             tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1555                 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1556                             tbl->tbl_opcode);
1557                 return 0;
1558         }
1559
1560         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1561         if (!tfp) {
1562                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1563                 return -EINVAL;
1564         }
1565
1566         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1567         if (!kflds || !num_kflds) {
1568                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1569                 return -EINVAL;
1570         }
1571
1572         if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1573                            parms->device_params->byte_order) ||
1574             !ulp_blob_init(&mask, tbl->blob_key_bit_size,
1575                            parms->device_params->byte_order) ||
1576             !ulp_blob_init(&data, tbl->result_bit_size,
1577                            parms->device_params->byte_order) ||
1578             !ulp_blob_init(&update_data, tbl->result_bit_size,
1579                            parms->device_params->byte_order)) {
1580                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1581                 return -EINVAL;
1582         }
1583
1584         if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1585                 key.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1586                 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1587         }
1588
1589         /* create the key/mask */
1590         /*
1591          * NOTE: The WC table will require some kind of flag to handle the
1592          * mode bits within the key/mask
1593          */
1594         for (i = 0; i < num_kflds; i++) {
1595                 /* Setup the key */
1596                 rc = ulp_mapper_field_process(parms, tbl->direction,
1597                                               &kflds[i].field_info_spec,
1598                                               &key, 1, "TCAM Key");
1599                 if (rc) {
1600                         BNXT_TF_DBG(ERR, "Key field set failed %s\n",
1601                                     kflds[i].field_info_spec.description);
1602                         return rc;
1603                 }
1604
1605                 /* Setup the mask */
1606                 rc = ulp_mapper_field_process(parms, tbl->direction,
1607                                               &kflds[i].field_info_mask,
1608                                               &mask, 0, "TCAM Mask");
1609                 if (rc) {
1610                         BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
1611                                     kflds[i].field_info_mask.description);
1612                         return rc;
1613                 }
1614         }
1615
1616         /* For wild card tcam perform the post process to swap the blob */
1617         if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1618                 ulp_mapper_wc_tcam_tbl_post_process(&key, tbl->key_bit_size);
1619                 ulp_mapper_wc_tcam_tbl_post_process(&mask, tbl->key_bit_size);
1620         }
1621
1622         if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1623                 /* allocate the tcam index */
1624                 aparms.dir = tbl->direction;
1625                 aparms.tcam_tbl_type = tbl->resource_type;
1626                 aparms.key = ulp_blob_data_get(&key, &tmplen);
1627                 aparms.key_sz_in_bits = tmplen;
1628                 if (tbl->blob_key_bit_size != tmplen) {
1629                         BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1630                                     tmplen, tbl->blob_key_bit_size);
1631                         return -EINVAL;
1632                 }
1633
1634                 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
1635                 if (tbl->blob_key_bit_size != tmplen) {
1636                         BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1637                                     tmplen, tbl->blob_key_bit_size);
1638                         return -EINVAL;
1639                 }
1640
1641                 /* calculate the entry priority */
1642                 rc = ulp_mapper_priority_opc_process(parms, tbl,
1643                                                      &aparms.priority);
1644                 if (rc) {
1645                         BNXT_TF_DBG(ERR, "entry priority process failed\n");
1646                         return rc;
1647                 }
1648
1649                 rc = tf_alloc_tcam_entry(tfp, &aparms);
1650                 if (rc) {
1651                         BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1652                         return rc;
1653                 }
1654                 idx = aparms.idx;
1655                 hit = aparms.hit;
1656         } else {
1657                 /*
1658                  * Searching before allocation to see if we already have an
1659                  * entry.  This allows re-use of a constrained resource.
1660                  */
1661                 searchparms.dir = tbl->direction;
1662                 searchparms.tcam_tbl_type = tbl->resource_type;
1663                 searchparms.key = ulp_blob_data_get(&key, &tmplen);
1664                 searchparms.key_sz_in_bits = tbl->key_bit_size;
1665                 searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1666                 searchparms.alloc = 1;
1667                 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1668                 searchparms.result_sz_in_bits = tbl->result_bit_size;
1669
1670                 /* calculate the entry priority */
1671                 rc = ulp_mapper_priority_opc_process(parms, tbl,
1672                                                      &searchparms.priority);
1673                 if (rc) {
1674                         BNXT_TF_DBG(ERR, "entry priority process failed\n");
1675                         return rc;
1676                 }
1677
1678                 rc = tf_search_tcam_entry(tfp, &searchparms);
1679                 if (rc) {
1680                         BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1681                         return rc;
1682                 }
1683
1684                 /* Successful search, check the result */
1685                 if (searchparms.search_status == REJECT) {
1686                         BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1687                         return -ENOMEM;
1688                 }
1689                 idx = searchparms.idx;
1690                 hit = searchparms.hit;
1691         }
1692
1693         /* Write the tcam index into the regfile*/
1694         if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
1695                               (uint64_t)tfp_cpu_to_be_64(idx))) {
1696                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
1697                             tbl->tbl_operand);
1698                 rc = -EINVAL;
1699                 /* Need to free the tcam idx, so goto error */
1700                 goto error;
1701         }
1702
1703         /* if it is miss then it is same as no search before alloc */
1704         if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1705                 /*Scan identifier list, allocate identifier and update regfile*/
1706                 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1707                 /* Create the result blob */
1708                 if (!rc)
1709                         rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
1710                                                          "TCAM Result");
1711                 /* write the tcam entry */
1712                 if (!rc)
1713                         rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1714                                                              &mask, &data, idx);
1715         } else {
1716                 /*Scan identifier list, extract identifier and update regfile*/
1717                 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1718         }
1719         if (rc)
1720                 goto error;
1721
1722         /* Add the tcam index to the flow database */
1723         fid_parms.direction = tbl->direction;
1724         fid_parms.resource_func = tbl->resource_func;
1725         fid_parms.resource_type = tbl->resource_type;
1726         fid_parms.critical_resource = tbl->critical_resource;
1727         fid_parms.resource_hndl = idx;
1728         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1729         if (rc) {
1730                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1731                             rc);
1732                 /* Need to free the identifier, so goto error */
1733                 goto error;
1734         }
1735
1736         return 0;
1737 error:
1738         free_parms.dir                  = tbl->direction;
1739         free_parms.tcam_tbl_type        = tbl->resource_type;
1740         free_parms.idx                  = idx;
1741         trc = tf_free_tcam_entry(tfp, &free_parms);
1742         if (trc)
1743                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1744                             tbl->resource_type, tbl->direction, idx);
1745         return rc;
1746 }
1747
1748 static int32_t
1749 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1750                           struct bnxt_ulp_mapper_tbl_info *tbl)
1751 {
1752         struct bnxt_ulp_mapper_key_info *kflds;
1753         struct ulp_blob key, data;
1754         uint32_t i, num_kflds;
1755         uint16_t tmplen;
1756         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1757         struct ulp_flow_db_res_params   fid_parms = { 0 };
1758         struct tf_insert_em_entry_parms iparms = { 0 };
1759         struct tf_delete_em_entry_parms free_parms = { 0 };
1760         enum bnxt_ulp_flow_mem_type mtype;
1761         int32_t trc;
1762         int32_t rc = 0;
1763
1764         rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1765         if (rc) {
1766                 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1767                 return -EINVAL;
1768         }
1769
1770         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1771         if (!kflds || !num_kflds) {
1772                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1773                 return -EINVAL;
1774         }
1775
1776         /* Initialize the key/result blobs */
1777         if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1778                            parms->device_params->byte_order) ||
1779             !ulp_blob_init(&data, tbl->result_bit_size,
1780                            parms->device_params->byte_order)) {
1781                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1782                 return -EINVAL;
1783         }
1784
1785         /* create the key */
1786         for (i = 0; i < num_kflds; i++) {
1787                 /* Setup the key */
1788                 rc = ulp_mapper_field_process(parms, tbl->direction,
1789                                               &kflds[i].field_info_spec,
1790                                               &key, 1, "EM Key");
1791                 if (rc) {
1792                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1793                         return rc;
1794                 }
1795         }
1796
1797         /*
1798          * TBD: Normally should process identifiers in case of using recycle or
1799          * loopback.  Not supporting recycle for now.
1800          */
1801
1802         /* Create the result data blob */
1803         rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
1804         if (rc) {
1805                 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
1806                 return rc;
1807         }
1808         /* do the transpose for the internal EM keys */
1809         if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1810                 ulp_blob_perform_byte_reverse(&key);
1811
1812         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1813                                              &iparms.tbl_scope_id);
1814         if (rc) {
1815                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1816                 return rc;
1817         }
1818
1819         /*
1820          * NOTE: the actual blob size will differ from the size in the tbl
1821          * entry due to the padding.
1822          */
1823         iparms.dup_check                = 0;
1824         iparms.dir                      = tbl->direction;
1825         iparms.mem                      = tbl->resource_type;
1826         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1827         iparms.key_sz_in_bits           = tbl->key_bit_size;
1828         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1829         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1830
1831         rc = tf_insert_em_entry(tfp, &iparms);
1832         if (rc) {
1833                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1834                 return rc;
1835         }
1836
1837         /* Mark action process */
1838         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
1839             tbl->resource_type == TF_MEM_EXTERNAL)
1840                 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
1841         else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
1842                  tbl->resource_type == TF_MEM_INTERNAL)
1843                 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1844         if (rc) {
1845                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1846                 goto error;
1847         }
1848
1849         /* Link the EM resource to the flow in the flow db */
1850         memset(&fid_parms, 0, sizeof(fid_parms));
1851         fid_parms.direction             = tbl->direction;
1852         fid_parms.resource_func         = tbl->resource_func;
1853         fid_parms.resource_type         = tbl->resource_type;
1854         fid_parms.critical_resource     = tbl->critical_resource;
1855         fid_parms.resource_hndl         = iparms.flow_handle;
1856
1857         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1858         if (rc) {
1859                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1860                             rc);
1861                 /* Need to free the identifier, so goto error */
1862                 goto error;
1863         }
1864
1865         return 0;
1866 error:
1867         free_parms.dir          = iparms.dir;
1868         free_parms.mem          = iparms.mem;
1869         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1870         free_parms.flow_handle  = iparms.flow_handle;
1871
1872         trc = tf_delete_em_entry(tfp, &free_parms);
1873         if (trc)
1874                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1875
1876         return rc;
1877 }
1878
1879 static int32_t
1880 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1881                              struct bnxt_ulp_mapper_tbl_info *tbl)
1882 {
1883         struct ulp_flow_db_res_params fid_parms;
1884         struct ulp_blob data;
1885         uint64_t regval = 0;
1886         uint16_t tmplen;
1887         uint32_t index, hit;
1888         int32_t rc = 0, trc = 0;
1889         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1890         struct tf_search_tbl_entry_parms srchparms = { 0 };
1891         struct tf_set_tbl_entry_parms sparms = { 0 };
1892         struct tf_get_tbl_entry_parms gparms = { 0 };
1893         struct tf_free_tbl_entry_parms free_parms = { 0 };
1894         uint32_t tbl_scope_id;
1895         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1896         uint16_t bit_size;
1897         bool alloc = false;
1898         bool write = false;
1899         bool search = false;
1900
1901         /* use the max size if encap is enabled */
1902         if (tbl->encap_num_fields)
1903                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
1904         else
1905                 bit_size = tbl->result_bit_size;
1906
1907         /* Initialize the blob data */
1908         if (!ulp_blob_init(&data, bit_size,
1909                            parms->device_params->byte_order)) {
1910                 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
1911                 return -EINVAL;
1912         }
1913
1914         /* Get the scope id first */
1915         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1916         if (rc) {
1917                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1918                 return rc;
1919         }
1920
1921         switch (tbl->tbl_opcode) {
1922         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
1923                 alloc = true;
1924                 break;
1925         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
1926                 /*
1927                  * Build the entry, alloc an index, write the table, and store
1928                  * the data in the regfile.
1929                  */
1930                 alloc = true;
1931                 write = true;
1932                 break;
1933         case BNXT_ULP_INDEX_TBL_OPC_SRCH_ALLOC_WR_REGFILE:
1934                 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
1935                         /* Not currently supporting with EXT */
1936                         BNXT_TF_DBG(ERR,
1937                                     "Ext Table Search Opcode not supported.\n");
1938                         return -EINVAL;
1939                 }
1940                 /*
1941                  * Search for the entry in the tf core.  If it is hit, save the
1942                  * index in the regfile.  If it is a miss, Build the entry,
1943                  * alloc an index, write the table, and store the data in the
1944                  * regfile (same as ALLOC_WR).
1945                  */
1946                 search = true;
1947                 break;
1948         case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
1949                 /*
1950                  * get the index to write to from the regfile and then write
1951                  * the table entry.
1952                  */
1953                 if (!ulp_regfile_read(parms->regfile,
1954                                       tbl->tbl_operand,
1955                                       &regval)) {
1956                         BNXT_TF_DBG(ERR,
1957                                     "Failed to get tbl idx from regfile[%d].\n",
1958                                     tbl->tbl_operand);
1959                         return -EINVAL;
1960                 }
1961                 index = tfp_be_to_cpu_64(regval);
1962                 /* For external, we need to reverse shift */
1963                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
1964                         index = TF_ACT_REC_PTR_2_OFFSET(index);
1965
1966                 write = true;
1967                 break;
1968         case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
1969                 /*
1970                  * get the index to write to from the global regfile and then
1971                  * write the table.
1972                  */
1973                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1974                                                  tbl->direction,
1975                                                  tbl->tbl_operand,
1976                                                  &regval)) {
1977                         BNXT_TF_DBG(ERR,
1978                                     "Failed to get tbl idx from Global "
1979                                     "regfile[%d].\n",
1980                                     tbl->tbl_operand);
1981                         return -EINVAL;
1982                 }
1983                 index = tfp_be_to_cpu_64(regval);
1984                 /* For external, we need to reverse shift */
1985                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
1986                         index = TF_ACT_REC_PTR_2_OFFSET(index);
1987                 write = true;
1988                 break;
1989         case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
1990                 /*
1991                  * The read is different from the rest and can be handled here
1992                  * instead of trying to use common code.  Simply read the table
1993                  * with the index from the regfile, scan and store the
1994                  * identifiers, and return.
1995                  */
1996                 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
1997                         /* Not currently supporting with EXT */
1998                         BNXT_TF_DBG(ERR,
1999                                     "Ext Table Read Opcode not supported.\n");
2000                         return -EINVAL;
2001                 }
2002                 if (!ulp_regfile_read(parms->regfile,
2003                                       tbl->tbl_operand, &regval)) {
2004                         BNXT_TF_DBG(ERR,
2005                                     "Failed to get tbl idx from regfile[%d]\n",
2006                                     tbl->tbl_operand);
2007                         return -EINVAL;
2008                 }
2009                 index = tfp_be_to_cpu_64(regval);
2010                 gparms.dir = tbl->direction;
2011                 gparms.type = tbl->resource_type;
2012                 gparms.data = ulp_blob_data_get(&data, &tmplen);
2013                 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2014                 gparms.idx = index;
2015                 rc = tf_get_tbl_entry(tfp, &gparms);
2016                 if (rc) {
2017                         BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2018                                     tbl->resource_type, index);
2019                         return rc;
2020                 }
2021                 /*
2022                  * Scan the fields in the entry and push them into the regfile.
2023                  */
2024                 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2025                                                    gparms.data,
2026                                                    gparms.data_sz_in_bytes,
2027                                                    data.byte_order);
2028                 if (rc) {
2029                         BNXT_TF_DBG(ERR, "Failed to read fields on tbl read "
2030                                     "rc=%d\n", rc);
2031                         return rc;
2032                 }
2033                 return 0;
2034         default:
2035                 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2036                             tbl->tbl_opcode);
2037                 return -EINVAL;
2038         }
2039
2040         if (write || search) {
2041                 /* Get the result fields list */
2042                 rc = ulp_mapper_tbl_result_build(parms,
2043                                                  tbl,
2044                                                  &data,
2045                                                  "Indexed Result");
2046                 if (rc) {
2047                         BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2048                         return rc;
2049                 }
2050         }
2051
2052         if (search) {
2053                 /* Use the result blob to perform a search */
2054                 memset(&srchparms, 0, sizeof(srchparms));
2055                 srchparms.dir = tbl->direction;
2056                 srchparms.type = tbl->resource_type;
2057                 srchparms.alloc = 1;
2058                 srchparms.result = ulp_blob_data_get(&data, &tmplen);
2059                 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2060                 srchparms.tbl_scope_id = tbl_scope_id;
2061                 rc = tf_search_tbl_entry(tfp, &srchparms);
2062                 if (rc) {
2063                         BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2064                                     tf_tbl_type_2_str(tbl->resource_type),
2065                                     tf_dir_2_str(tbl->direction), rc);
2066                         return rc;
2067                 }
2068                 if (srchparms.search_status == REJECT) {
2069                         BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
2070                                     tf_tbl_type_2_str(tbl->resource_type),
2071                                     tf_dir_2_str(tbl->direction));
2072                         return -ENOMEM;
2073                 }
2074                 index = srchparms.idx;
2075                 hit = srchparms.hit;
2076                 if (hit)
2077                         write = false;
2078                 else
2079                         write = true;
2080         }
2081
2082         if (alloc) {
2083                 aparms.dir              = tbl->direction;
2084                 aparms.type             = tbl->resource_type;
2085                 aparms.tbl_scope_id     = tbl_scope_id;
2086
2087                 /* All failures after the alloc succeeds require a free */
2088                 rc = tf_alloc_tbl_entry(tfp, &aparms);
2089                 if (rc) {
2090                         BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2091                                     tf_tbl_type_2_str(tbl->resource_type),
2092                                     tf_dir_2_str(tbl->direction), rc);
2093                         return rc;
2094                 }
2095                 index = aparms.idx;
2096         }
2097
2098         if (search || alloc) {
2099                 /*
2100                  * Store the index in the regfile since we either allocated it
2101                  * or it was a hit.
2102                  *
2103                  * Calculate the idx for the result record, for external EM the
2104                  * offset needs to be shifted accordingly.
2105                  * If external non-inline table types are used then need to
2106                  * revisit this logic.
2107                  */
2108                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2109                         regval = TF_ACT_REC_OFFSET_2_PTR(index);
2110                 else
2111                         regval = index;
2112
2113                 rc = ulp_regfile_write(parms->regfile,
2114                                        tbl->tbl_operand,
2115                                        tfp_cpu_to_be_64(regval));
2116                 if (rc) {
2117                         BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n",
2118                                     tbl->tbl_operand, rc);
2119                         goto error;
2120                 }
2121         }
2122
2123         if (write) {
2124                 sparms.dir = tbl->direction;
2125                 sparms.type = tbl->resource_type;
2126                 sparms.data = ulp_blob_data_get(&data, &tmplen);
2127                 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2128                 sparms.idx = index;
2129                 sparms.tbl_scope_id = tbl_scope_id;
2130                 rc = tf_set_tbl_entry(tfp, &sparms);
2131                 if (rc) {
2132                         BNXT_TF_DBG(ERR,
2133                                     "Index table[%s][%s][%x] write failed "
2134                                     "rc=%d\n",
2135                                     tf_tbl_type_2_str(sparms.type),
2136                                     tf_dir_2_str(sparms.dir),
2137                                     sparms.idx, rc);
2138                         goto error;
2139                 }
2140         }
2141
2142         /* Link the resource to the flow in the flow db */
2143         memset(&fid_parms, 0, sizeof(fid_parms));
2144         fid_parms.direction     = tbl->direction;
2145         fid_parms.resource_func = tbl->resource_func;
2146         fid_parms.resource_type = tbl->resource_type;
2147         fid_parms.resource_sub_type = tbl->resource_sub_type;
2148         fid_parms.resource_hndl = index;
2149         fid_parms.critical_resource = tbl->critical_resource;
2150
2151         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2152         if (rc) {
2153                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2154                             rc);
2155                 goto error;
2156         }
2157
2158         /* Perform the VF rep action */
2159         rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2160         if (rc) {
2161                 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2162                 goto error;
2163         }
2164         return rc;
2165 error:
2166         /*
2167          * Free the allocated resource since we failed to either
2168          * write to the entry or link the flow
2169          */
2170         free_parms.dir  = tbl->direction;
2171         free_parms.type = tbl->resource_type;
2172         free_parms.idx  = index;
2173         free_parms.tbl_scope_id = tbl_scope_id;
2174
2175         trc = tf_free_tbl_entry(tfp, &free_parms);
2176         if (trc)
2177                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2178
2179         return rc;
2180 }
2181
2182 static int32_t
2183 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2184                           struct bnxt_ulp_mapper_tbl_info *tbl)
2185 {
2186         struct ulp_blob data, res_blob;
2187         uint64_t idx;
2188         uint16_t tmplen;
2189         int32_t rc = 0;
2190         struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2191         struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2192         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2193         enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2194         uint32_t res_size;
2195
2196         /* Initialize the blob data */
2197         if (!ulp_blob_init(&data, tbl->result_bit_size,
2198                            parms->device_params->byte_order)) {
2199                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2200                 return -EINVAL;
2201         }
2202
2203         /* create the result blob */
2204         rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2205         if (rc) {
2206                 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2207                 return rc;
2208         }
2209
2210         /* Get the index details */
2211         switch (if_opc) {
2212         case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2213                 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2214                 break;
2215         case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2216                 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2217                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2218                                     tbl->tbl_operand);
2219                         return -EINVAL;
2220                 }
2221                 idx = tfp_be_to_cpu_64(idx);
2222                 break;
2223         case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2224                 idx = tbl->tbl_operand;
2225                 break;
2226         case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2227                 /* Initialize the result blob */
2228                 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2229                                    parms->device_params->byte_order)) {
2230                         BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2231                         return -EINVAL;
2232                 }
2233
2234                 /* read the interface table */
2235                 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2236                 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2237                 get_parms.dir = tbl->direction;
2238                 get_parms.type = tbl->resource_type;
2239                 get_parms.idx = idx;
2240                 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2241                 get_parms.data_sz_in_bytes = res_size;
2242
2243                 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2244                 if (rc) {
2245                         BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2246                                     get_parms.type,
2247                                     tf_dir_2_str(get_parms.dir),
2248                                     get_parms.idx, rc);
2249                         return rc;
2250                 }
2251                 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2252                                                    res_blob.data,
2253                                                    res_size,
2254                                                    res_blob.byte_order);
2255                 if (rc)
2256                         BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2257                 return rc;
2258         case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2259                 return rc; /* skip it */
2260         default:
2261                 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2262                 return -EINVAL;
2263         }
2264
2265         /* Perform the tf table set by filling the set params */
2266         iftbl_params.dir = tbl->direction;
2267         iftbl_params.type = tbl->resource_type;
2268         iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2269         iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2270         iftbl_params.idx = idx;
2271
2272         rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2273         if (rc) {
2274                 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2275                             iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2276                             tf_dir_2_str(iftbl_params.dir),
2277                             iftbl_params.idx, rc);
2278                 return rc;
2279         }
2280
2281         /*
2282          * TBD: Need to look at the need to store idx in flow db for restore
2283          * the table to its original state on deletion of this entry.
2284          */
2285         return rc;
2286 }
2287
2288 static int32_t
2289 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2290                            struct bnxt_ulp_mapper_tbl_info *tbl)
2291 {
2292         struct bnxt_ulp_mapper_key_info *kflds;
2293         struct ulp_flow_db_res_params fid_parms;
2294         struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2295         uint16_t tmplen;
2296         struct ulp_blob key, data;
2297         uint8_t *cache_key;
2298         int32_t tbl_idx;
2299         uint32_t i, ckey, num_kflds = 0;
2300         uint32_t gen_tbl_hit = 0, fdb_write = 0;
2301         uint8_t *byte_data;
2302         int32_t rc = 0;
2303
2304         /* Get the key fields list and build the key. */
2305         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2306         if (!kflds || !num_kflds) {
2307                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2308                 return -EINVAL;
2309         }
2310         if (!ulp_blob_init(&key, tbl->key_bit_size,
2311                            parms->device_params->byte_order)) {
2312                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2313                 return -EINVAL;
2314         }
2315         for (i = 0; i < num_kflds; i++) {
2316                 /* Setup the key */
2317                 rc = ulp_mapper_field_process(parms, tbl->direction,
2318                                               &kflds[i].field_info_spec,
2319                                               &key, 1, "Gen Tbl Key");
2320                 if (rc) {
2321                         BNXT_TF_DBG(ERR,
2322                                     "Failed to create key for Gen tbl rc=%d\n",
2323                                     rc);
2324                         return -EINVAL;
2325                 }
2326         }
2327
2328         /* Calculate the table index for the generic table*/
2329         tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2330                                                    tbl->direction);
2331         if (tbl_idx < 0) {
2332                 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2333                             tbl->resource_sub_type, tbl->direction);
2334                 return -EINVAL;
2335         }
2336
2337         /* The_key is a byte array convert it to a search index */
2338         cache_key = ulp_blob_data_get(&key, &tmplen);
2339         memcpy(&ckey, cache_key, sizeof(ckey));
2340         /* Get the generic table entry */
2341         rc = ulp_mapper_gen_tbl_entry_get(parms->ulp_ctx,
2342                                           tbl_idx, ckey, &gen_tbl_ent);
2343         if (rc) {
2344                 BNXT_TF_DBG(ERR,
2345                             "Failed to create key for Gen tbl rc=%d\n", rc);
2346                 return -EINVAL;
2347         }
2348         switch (tbl->tbl_opcode) {
2349         case BNXT_ULP_GENERIC_TBL_OPC_READ:
2350                 /* check the reference count */
2351                 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2352                         g = &gen_tbl_ent;
2353                         /* Scan ident list and create the result blob*/
2354                         rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2355                                                            g->byte_data,
2356                                                            g->byte_data_size,
2357                                                            g->byte_order);
2358                         if (rc) {
2359                                 BNXT_TF_DBG(ERR,
2360                                             "Failed to scan ident list\n");
2361                                 return -EINVAL;
2362                         }
2363                         /* increment the reference count */
2364                         ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2365
2366                         /* it is a hit */
2367                         gen_tbl_hit = 1;
2368                         fdb_write = 1;
2369                 }
2370                 break;
2371         case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2372                 /* check the reference count */
2373                 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2374                         /* a hit then error */
2375                         BNXT_TF_DBG(ERR, "generic entry already present %x\n",
2376                                     ckey);
2377                         return -EINVAL; /* success */
2378                 }
2379
2380                 /* Initialize the blob data */
2381                 if (!ulp_blob_init(&data, tbl->result_bit_size,
2382                                    gen_tbl_ent.byte_order)) {
2383                         BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2384                         return -EINVAL;
2385                 }
2386
2387                 /* Get the result fields list */
2388                 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2389                                                  "Gen tbl Result");
2390                 if (rc) {
2391                         BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2392                         return rc;
2393                 }
2394                 byte_data = ulp_blob_data_get(&data, &tmplen);
2395                 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2396                                                        tmplen, byte_data,
2397                                                        ULP_BITS_2_BYTE(tmplen));
2398                 if (rc) {
2399                         BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2400                         return -EINVAL;
2401                 }
2402
2403                 /* increment the reference count */
2404                 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2405                 fdb_write = 1;
2406                 parms->shared_hndl = (uint64_t)tbl_idx << 32 | ckey;
2407                 break;
2408         default:
2409                 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2410                 return -EINVAL;
2411         }
2412
2413         /* Set the generic entry hit */
2414         rc = ulp_regfile_write(parms->regfile,
2415                                BNXT_ULP_RF_IDX_GENERIC_TBL_HIT,
2416                                tfp_cpu_to_be_64(gen_tbl_hit));
2417         if (rc) {
2418                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2419                             BNXT_ULP_RF_IDX_GENERIC_TBL_HIT);
2420                 return -EIO;
2421         }
2422
2423         /* add the entry to the flow database */
2424         if (fdb_write) {
2425                 memset(&fid_parms, 0, sizeof(fid_parms));
2426                 fid_parms.direction = tbl->direction;
2427                 fid_parms.resource_func = tbl->resource_func;
2428                 fid_parms.resource_sub_type = tbl->resource_sub_type;
2429                 fid_parms.resource_hndl = ckey;
2430                 fid_parms.critical_resource = tbl->critical_resource;
2431                 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2432                 if (rc)
2433                         BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2434         }
2435         return rc;
2436 }
2437
2438 static int32_t
2439 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2440                                   struct bnxt_ulp_mapper_data *mapper_data)
2441 {
2442         struct bnxt_ulp_glb_resource_info *glb_res;
2443         uint32_t num_glb_res_ids, idx;
2444         int32_t rc = 0;
2445
2446         glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2447         if (!glb_res || !num_glb_res_ids) {
2448                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2449                 return -EINVAL;
2450         }
2451
2452         /* Iterate the global resources and process each one */
2453         for (idx = 0; idx < num_glb_res_ids; idx++) {
2454                 switch (glb_res[idx].resource_func) {
2455                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2456                         rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2457                                                                 mapper_data,
2458                                                                 &glb_res[idx]);
2459                         break;
2460                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2461                         rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2462                                                                  mapper_data,
2463                                                                  &glb_res[idx]);
2464                         break;
2465                 default:
2466                         BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2467                                     glb_res[idx].resource_func);
2468                         rc = -EINVAL;
2469                         break;
2470                 }
2471                 if (rc)
2472                         return rc;
2473         }
2474         return rc;
2475 }
2476
2477 /*
2478  * Function to process the memtype opcode of the mapper table.
2479  * returns 1 to skip the table.
2480  * return 0 to continue processing the table.
2481  *
2482  * defaults to skip
2483  */
2484 static int32_t
2485 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2486                                       struct bnxt_ulp_mapper_tbl_info *tbl)
2487 {
2488         enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2489         int32_t rc = 1;
2490
2491         bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2492
2493         switch (tbl->mem_type_opcode) {
2494         case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT:
2495                 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2496                         rc = 0;
2497                 break;
2498         case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT:
2499                 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2500                         rc = 0;
2501                 break;
2502         case BNXT_ULP_MEM_TYPE_OPC_NOP:
2503                 rc = 0;
2504                 break;
2505         default:
2506                 BNXT_TF_DBG(ERR,
2507                             "Invalid arg in mapper in memtype opcode\n");
2508                 break;
2509         }
2510         return rc;
2511 }
2512
2513 /*
2514  * Common conditional opcode process routine that is used for both the template
2515  * rejection and table conditional execution.
2516  */
2517 static int32_t
2518 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
2519                             enum bnxt_ulp_cond_opc opc,
2520                             uint32_t operand,
2521                             int32_t *res)
2522 {
2523         int32_t rc = 0;
2524         uint8_t bit;
2525         uint64_t regval;
2526
2527         switch (opc) {
2528         case BNXT_ULP_COND_OPC_CF_IS_SET:
2529                 if (operand < BNXT_ULP_CF_IDX_LAST) {
2530                         *res = ULP_COMP_FLD_IDX_RD(parms, operand);
2531                 } else {
2532                         BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2533                                     operand);
2534                         rc = -EINVAL;
2535                 }
2536                 break;
2537         case BNXT_ULP_COND_OPC_CF_NOT_SET:
2538                 if (operand < BNXT_ULP_CF_IDX_LAST) {
2539                         *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
2540                 } else {
2541                         BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2542                                     operand);
2543                         rc = -EINVAL;
2544                 }
2545                 break;
2546         case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
2547                 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2548                         *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2549                                                 operand);
2550                 } else {
2551                         BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2552                                     operand);
2553                         rc = -EINVAL;
2554                 }
2555                 break;
2556         case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
2557                 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2558                         *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2559                                                operand);
2560                 } else {
2561                         BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2562                                     operand);
2563                         rc = -EINVAL;
2564                 }
2565                 break;
2566         case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
2567                 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2568                         *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2569                                                 operand);
2570                 } else {
2571                         BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2572                                     operand);
2573                         rc = -EINVAL;
2574                 }
2575                 break;
2576         case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
2577                 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2578                         *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2579                                                operand);
2580                 } else {
2581                         BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2582                                     operand);
2583                         rc = -EINVAL;
2584                 }
2585                 break;
2586         case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
2587                 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2588                 if (rc) {
2589                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2590                                     operand);
2591                         return -EINVAL;
2592                 }
2593                 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2594                 break;
2595         case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
2596                 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2597                 if (rc) {
2598                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2599                                     operand);
2600                         return -EINVAL;
2601                 }
2602                 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2603                 break;
2604         case BNXT_ULP_COND_OPC_RF_IS_SET:
2605                 if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
2606                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2607                         return -EINVAL;
2608                 }
2609                 *res = regval != 0;
2610                 break;
2611         case BNXT_ULP_COND_OPC_RF_NOT_SET:
2612                 if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
2613                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2614                         return -EINVAL;
2615                 }
2616                 *res = regval == 0;
2617                 break;
2618         default:
2619                 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
2620                 rc = -EINVAL;
2621                 break;
2622         }
2623         return (rc);
2624 }
2625
2626 /*
2627  * Processes a list of conditions and returns both a status and result of the
2628  * list.  The status must be checked prior to verifying the result.
2629  *
2630  * returns 0 for success, negative on failure
2631  * returns res = 1 for true, res = 0 for false.
2632  */
2633 static int32_t
2634 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
2635                                  enum bnxt_ulp_cond_list_opc list_opc,
2636                                  struct bnxt_ulp_mapper_cond_info *list,
2637                                  uint32_t num,
2638                                  int32_t *res)
2639 {
2640         uint32_t i;
2641         int32_t rc = 0, trc;
2642
2643         switch (list_opc) {
2644         case BNXT_ULP_COND_LIST_OPC_AND:
2645                 /* AND Defaults to true. */
2646                 *res = 1;
2647                 break;
2648         case BNXT_ULP_COND_LIST_OPC_OR:
2649                 /* OR Defaults to false. */
2650                 *res = 0;
2651                 break;
2652         case BNXT_ULP_COND_LIST_OPC_TRUE:
2653                 *res = 1;
2654                 return rc;
2655         case BNXT_ULP_COND_LIST_OPC_FALSE:
2656                 *res = 0;
2657                 return rc;
2658         default:
2659                 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
2660                             list_opc);
2661                 return -EINVAL;
2662         }
2663
2664         for (i = 0; i < num; i++) {
2665                 rc = ulp_mapper_cond_opc_process(parms,
2666                                                  list[i].cond_opcode,
2667                                                  list[i].cond_operand,
2668                                                  &trc);
2669                 if (rc)
2670                         return rc;
2671
2672                 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
2673                         /* early return if result is ever zero */
2674                         if (!trc) {
2675                                 *res = trc;
2676                                 return rc;
2677                         }
2678                 } else {
2679                         /* early return if result is ever non-zero */
2680                         if (trc) {
2681                                 *res = trc;
2682                                 return rc;
2683                         }
2684                 }
2685         }
2686
2687         return rc;
2688 }
2689
2690 /*
2691  * Processes conflict resolution and returns both a status and result.
2692  * The status must be checked prior to verifying the result.
2693  *
2694  * returns 0 for success, negative on failure
2695  * returns res = 1 for true, res = 0 for false.
2696  */
2697 static int32_t
2698 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
2699                                        struct bnxt_ulp_mapper_tbl_info *tbl,
2700                                        int32_t *res)
2701 {
2702         int32_t rc = 0;
2703         uint64_t regval;
2704         uint64_t comp_sig_id;
2705
2706         *res = 0;
2707         switch (tbl->accept_opcode) {
2708         case BNXT_ULP_ACCEPT_OPC_ALWAYS:
2709                 *res = 1;
2710                 break;
2711         case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
2712                 /* perform the signature validation*/
2713                 if (tbl->resource_func ==
2714                     BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
2715                         /* Perform the check that generic table is hit or not */
2716                         if (!ulp_regfile_read(parms->regfile,
2717                                               BNXT_ULP_RF_IDX_GENERIC_TBL_HIT,
2718                                               &regval)) {
2719                                 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2720                                             BNXT_ULP_RF_IDX_GENERIC_TBL_HIT);
2721                                 return -EINVAL;
2722                         }
2723                         if (!regval) {
2724                                 /* not a hit so no need to check flow sign*/
2725                                 *res = 1;
2726                                 return rc;
2727                         }
2728                 }
2729                 /* compare the new flow signature against stored one */
2730                 if (!ulp_regfile_read(parms->regfile,
2731                                       BNXT_ULP_RF_IDX_FLOW_SIG_ID,
2732                                       &regval)) {
2733                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2734                                     BNXT_ULP_RF_IDX_FLOW_SIG_ID);
2735                         return -EINVAL;
2736                 }
2737                 comp_sig_id = ULP_COMP_FLD_IDX_RD(parms,
2738                                                   BNXT_ULP_CF_IDX_FLOW_SIG_ID);
2739                 regval = tfp_be_to_cpu_64(regval);
2740                 if (comp_sig_id == regval)
2741                         *res = 1;
2742                 else
2743                         BNXT_TF_DBG(ERR, "failed signature match %x:%x\n",
2744                                     (uint32_t)comp_sig_id, (uint32_t)regval);
2745                 break;
2746         default:
2747                 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
2748                             tbl->accept_opcode);
2749                 return -EINVAL;
2750         }
2751         return rc;
2752 }
2753
2754 static int32_t
2755 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
2756 {
2757         struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
2758         enum bnxt_ulp_cond_list_opc cond_opc;
2759         struct bnxt_ulp_mapper_tbl_info *tbls;
2760         struct bnxt_ulp_mapper_tbl_info *tbl;
2761         uint32_t num_tbls, tbl_idx, num_cond_tbls;
2762         int32_t rc = -EINVAL, cond_rc = 0;
2763         uint32_t cond_goto = 1;
2764
2765         cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
2766                                                     &num_cond_tbls,
2767                                                     &cond_opc);
2768         /*
2769          * Process the reject list if exists, otherwise assume that the
2770          * template is allowed.
2771          */
2772         if (cond_tbls && num_cond_tbls) {
2773                 rc = ulp_mapper_cond_opc_list_process(parms,
2774                                                       cond_opc,
2775                                                       cond_tbls,
2776                                                       num_cond_tbls,
2777                                                       &cond_rc);
2778                 if (rc)
2779                         return rc;
2780
2781                 /* Reject the template if True */
2782                 if (cond_rc) {
2783                         BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
2784                                     ulp_mapper_tmpl_name_str(parms->tmpl_type),
2785                                     tid);
2786                         return -EINVAL;
2787                 }
2788         }
2789
2790         tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
2791         if (!tbls || !num_tbls) {
2792                 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
2793                             ulp_mapper_tmpl_name_str(parms->tmpl_type),
2794                             parms->dev_id, tid);
2795                 return -EINVAL;
2796         }
2797
2798         for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
2799                 tbl = &tbls[tbl_idx];
2800                 cond_goto = tbl->execute_info.cond_goto;
2801                 /* Handle the table level opcodes to determine if required. */
2802                 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl)) {
2803                         tbl_idx += 1;
2804                         continue;
2805                 }
2806
2807                 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
2808                                                             &num_cond_tbls,
2809                                                             &cond_opc);
2810                 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
2811                                                       cond_tbls, num_cond_tbls,
2812                                                       &cond_rc);
2813                 if (rc) {
2814                         BNXT_TF_DBG(ERR, "Failed to process cond opc list "
2815                                    "(%d)\n", rc);
2816                         return rc;
2817                 }
2818                 /* Skip the table if False */
2819                 if (!cond_rc) {
2820                         tbl_idx += 1;
2821                         continue;
2822                 }
2823
2824                 /* process the fdb opcode for alloc push */
2825                 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_PUSH_REGFILE) {
2826                         rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
2827                         if (rc) {
2828                                 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
2829                                 return rc;
2830                         }
2831                 }
2832
2833                 switch (tbl->resource_func) {
2834                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2835                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
2836                         break;
2837                 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2838                 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2839                         rc = ulp_mapper_em_tbl_process(parms, tbl);
2840                         break;
2841                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2842                         rc = ulp_mapper_index_tbl_process(parms, tbl);
2843                         break;
2844                 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
2845                         rc = ulp_mapper_if_tbl_process(parms, tbl);
2846                         break;
2847                 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2848                         rc = ulp_mapper_gen_tbl_process(parms, tbl);
2849                         break;
2850                 case BNXT_ULP_RESOURCE_FUNC_INVALID:
2851                 case BNXT_ULP_RESOURCE_FUNC_BRANCH_TABLE:
2852                         rc = 0;
2853                         break;
2854                 default:
2855                         BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
2856                                     tbl->resource_func);
2857                         rc = -EINVAL;
2858                         goto error;
2859                 }
2860
2861                 if (rc) {
2862                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
2863                                     tbl->resource_func);
2864                         goto error;
2865                 }
2866
2867                 /* perform the post table process */
2868                 rc  = ulp_mapper_conflict_resolution_process(parms, tbl,
2869                                                              &cond_rc);
2870                 if (rc || !cond_rc) {
2871                         BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
2872                         rc = -EINVAL;
2873                         goto error;
2874                 }
2875                 tbl_idx += cond_goto;
2876         }
2877
2878         return rc;
2879 error:
2880         BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
2881                     ulp_mapper_tmpl_name_str(parms->tmpl_type),
2882                     parms->dev_id, tid);
2883         return rc;
2884 }
2885
2886 static int32_t
2887 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
2888                          uint32_t fid,
2889                          struct ulp_flow_db_res_params *res)
2890 {
2891         struct tf *tfp;
2892         int32_t rc = 0;
2893
2894         if (!res || !ulp) {
2895                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
2896                 return -EINVAL;
2897         }
2898
2899         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
2900         if (!tfp) {
2901                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
2902                 return -EINVAL;
2903         }
2904
2905         switch (res->resource_func) {
2906         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2907                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
2908                 break;
2909         case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2910         case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2911                 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
2912                 break;
2913         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2914                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
2915                 break;
2916         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2917                 rc = ulp_mapper_ident_free(ulp, tfp, res);
2918                 break;
2919         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
2920                 rc = ulp_mapper_mark_free(ulp, res);
2921                 break;
2922         case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
2923                 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
2924                 break;
2925         case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
2926                 rc = ulp_mapper_child_flow_free(ulp, fid, res);
2927                 break;
2928         case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2929                 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
2930                 break;
2931         default:
2932                 break;
2933         }
2934
2935         return rc;
2936 }
2937
2938 int32_t
2939 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
2940                           enum bnxt_ulp_fdb_type flow_type,
2941                           uint32_t fid)
2942 {
2943         struct ulp_flow_db_res_params res_parms = { 0 };
2944         int32_t rc, trc;
2945
2946         if (!ulp_ctx) {
2947                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2948                 return -EINVAL;
2949         }
2950
2951         /*
2952          * Set the critical resource on the first resource del, then iterate
2953          * while status is good
2954          */
2955         res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
2956         rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
2957
2958         if (rc) {
2959                 /*
2960                  * This is unexpected on the first call to resource del.
2961                  * It likely means that the flow did not exist in the flow db.
2962                  */
2963                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
2964                             flow_type, fid, rc);
2965                 return rc;
2966         }
2967
2968         while (!rc) {
2969                 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
2970                 if (trc)
2971                         /*
2972                          * On fail, we still need to attempt to free the
2973                          * remaining resources.  Don't return
2974                          */
2975                         BNXT_TF_DBG(ERR,
2976                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
2977                                     "] failed rc=%d.\n",
2978                                     flow_type, fid, res_parms.resource_func,
2979                                     res_parms.resource_hndl, trc);
2980
2981                 /* All subsequent call require the non-critical_resource */
2982                 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2983
2984                 rc = ulp_flow_db_resource_del(ulp_ctx,
2985                                               flow_type,
2986                                               fid,
2987                                               &res_parms);
2988         }
2989
2990         /* Free the Flow ID since we've removed all resources */
2991         rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
2992
2993         return rc;
2994 }
2995
2996 static void
2997 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
2998                                     struct bnxt_ulp_mapper_data *mapper_data)
2999 {
3000         struct bnxt_ulp_mapper_glb_resource_entry *ent;
3001         struct ulp_flow_db_res_params res;
3002         uint32_t dir, idx;
3003
3004         /* Iterate the global resources and process each one */
3005         for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3006                 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
3007                       idx++) {
3008                         ent = &mapper_data->glb_res_tbl[dir][idx];
3009                         if (ent->resource_func ==
3010                             BNXT_ULP_RESOURCE_FUNC_INVALID)
3011                                 continue;
3012                         memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3013                         res.resource_func = ent->resource_func;
3014                         res.direction = dir;
3015                         res.resource_type = ent->resource_type;
3016                         /*convert it from BE to cpu */
3017                         res.resource_hndl =
3018                                 tfp_be_to_cpu_64(ent->resource_hndl);
3019                         ulp_mapper_resource_free(ulp_ctx, 0, &res);
3020                 }
3021         }
3022 }
3023
3024 int32_t
3025 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3026                         enum bnxt_ulp_fdb_type flow_type,
3027                         uint32_t fid)
3028 {
3029         int32_t rc;
3030
3031         if (!ulp_ctx) {
3032                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3033                 return -EINVAL;
3034         }
3035
3036         rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3037         return rc;
3038 }
3039
3040 /* Function to handle the default global templates that are allocated during
3041  * the startup and reused later.
3042  */
3043 static int32_t
3044 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
3045 {
3046         uint32_t *glbl_tmpl_list;
3047         uint32_t num_glb_tmpls, idx, dev_id;
3048         struct bnxt_ulp_mapper_parms parms;
3049         struct bnxt_ulp_mapper_data *mapper_data;
3050         int32_t rc = 0;
3051
3052         glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
3053         if (!glbl_tmpl_list || !num_glb_tmpls)
3054                 return rc; /* No global templates to process */
3055
3056         /* Get the device id from the ulp context */
3057         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
3058                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3059                 return -EINVAL;
3060         }
3061
3062         mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3063         if (!mapper_data) {
3064                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3065                 return -EINVAL;
3066         }
3067
3068         /* Iterate the global resources and process each one */
3069         for (idx = 0; idx < num_glb_tmpls; idx++) {
3070                 /* Initialize the parms structure */
3071                 memset(&parms, 0, sizeof(parms));
3072                 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3073                 parms.ulp_ctx = ulp_ctx;
3074                 parms.dev_id = dev_id;
3075                 parms.mapper_data = mapper_data;
3076                 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
3077                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3078
3079                 /* Get the class table entry from dev id and class id */
3080                 parms.class_tid = glbl_tmpl_list[idx];
3081
3082                 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3083                 if (!parms.device_params) {
3084                         BNXT_TF_DBG(ERR, "No device for device id %d\n",
3085                                     parms.dev_id);
3086                         return -EINVAL;
3087                 }
3088
3089                 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3090                 if (rc)
3091                         return rc;
3092         }
3093         return rc;
3094 }
3095
3096 /* Function to handle the mapping of the Flow to be compatible
3097  * with the underlying hardware.
3098  */
3099 int32_t
3100 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3101                        struct bnxt_ulp_mapper_create_parms *cparms)
3102 {
3103         struct bnxt_ulp_mapper_parms parms;
3104         struct ulp_regfile regfile;
3105         int32_t  rc = 0, trc;
3106
3107         if (!ulp_ctx || !cparms)
3108                 return -EINVAL;
3109
3110         /* Initialize the parms structure */
3111         memset(&parms, 0, sizeof(parms));
3112         parms.act_prop = cparms->act_prop;
3113         parms.act_bitmap = cparms->act;
3114         parms.hdr_bitmap = cparms->hdr_bitmap;
3115         parms.regfile = &regfile;
3116         parms.hdr_field = cparms->hdr_field;
3117         parms.fld_bitmap = cparms->fld_bitmap;
3118         parms.comp_fld = cparms->comp_fld;
3119         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3120         parms.ulp_ctx = ulp_ctx;
3121         parms.act_tid = cparms->act_tid;
3122         parms.class_tid = cparms->class_tid;
3123         parms.flow_type = cparms->flow_type;
3124         parms.parent_flow = cparms->parent_flow;
3125         parms.parent_fid = cparms->parent_fid;
3126         parms.fid = cparms->flow_id;
3127         parms.tun_idx = cparms->tun_idx;
3128         parms.app_priority = cparms->app_priority;
3129
3130         /* Get the device id from the ulp context */
3131         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3132                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3133                 return -EINVAL;
3134         }
3135
3136         /* Get the device params, it will be used in later processing */
3137         parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3138         if (!parms.device_params) {
3139                 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3140                             parms.dev_id);
3141                 return -EINVAL;
3142         }
3143
3144         /*
3145          * Get the mapper data for dynamic mapper data such as default
3146          * ids.
3147          */
3148         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3149                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3150         if (!parms.mapper_data) {
3151                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3152                 return -EINVAL;
3153         }
3154
3155         /* initialize the registry file for further processing */
3156         if (!ulp_regfile_init(parms.regfile)) {
3157                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3158                 return -EINVAL;
3159         }
3160
3161         /* Process the action template list from the selected action table*/
3162         if (parms.act_tid) {
3163                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3164                 /* Process the action template tables */
3165                 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3166                 if (rc)
3167                         goto flow_error;
3168         }
3169
3170         if (parms.class_tid) {
3171                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3172
3173                 /* Process the class template tables.*/
3174                 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3175                 if (rc)
3176                         goto flow_error;
3177         }
3178
3179         /* setup the parent-child details */
3180         if (parms.parent_flow) {
3181                 /* create a parent flow details */
3182                 rc = ulp_flow_db_parent_flow_create(&parms);
3183                 if (rc)
3184                         goto flow_error;
3185         } else if (parms.parent_fid) {
3186                 /* create a child flow details */
3187                 rc = ulp_flow_db_child_flow_create(&parms);
3188                 if (rc)
3189                         goto flow_error;
3190         }
3191
3192         return rc;
3193
3194 flow_error:
3195         /* Free all resources that were allocated during flow creation */
3196         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
3197                                       parms.fid);
3198         if (trc)
3199                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3200
3201         return rc;
3202 }
3203
3204 int32_t
3205 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3206 {
3207         struct bnxt_ulp_mapper_data *data;
3208         struct tf *tfp;
3209         int32_t rc;
3210
3211         if (!ulp_ctx)
3212                 return -EINVAL;
3213
3214         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3215         if (!tfp)
3216                 return -EINVAL;
3217
3218         data = rte_zmalloc("ulp_mapper_data",
3219                            sizeof(struct bnxt_ulp_mapper_data), 0);
3220         if (!data) {
3221                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3222                 return -ENOMEM;
3223         }
3224
3225         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3226                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3227                 /* Don't call deinit since the prof_func wasn't allocated. */
3228                 rte_free(data);
3229                 return -ENOMEM;
3230         }
3231
3232         /* Allocate the global resource ids */
3233         rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3234         if (rc) {
3235                 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3236                 goto error;
3237         }
3238
3239         /* Allocate the generic table list */
3240         rc = ulp_mapper_generic_tbl_list_init(data);
3241         if (rc) {
3242                 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3243                 goto error;
3244         }
3245
3246         /* Allocate global template table entries */
3247         rc = ulp_mapper_glb_template_table_init(ulp_ctx);
3248         if (rc) {
3249                 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
3250                 goto error;
3251         }
3252
3253         return 0;
3254 error:
3255         /* Ignore the return code in favor of returning the original error. */
3256         ulp_mapper_deinit(ulp_ctx);
3257         return rc;
3258 }
3259
3260 void
3261 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3262 {
3263         struct bnxt_ulp_mapper_data *data;
3264         struct tf *tfp;
3265
3266         if (!ulp_ctx) {
3267                 BNXT_TF_DBG(ERR,
3268                             "Failed to acquire ulp context, so data may "
3269                             "not be released.\n");
3270                 return;
3271         }
3272
3273         data = (struct bnxt_ulp_mapper_data *)
3274                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3275         if (!data) {
3276                 /* Go ahead and return since there is no allocated data. */
3277                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3278                 return;
3279         }
3280
3281         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3282         if (!tfp) {
3283                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3284                 /* Free the mapper data regardless of errors. */
3285                 goto free_mapper_data;
3286         }
3287
3288         /* Free the global resource info table entries */
3289         ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3290
3291 free_mapper_data:
3292         /* Free the generic table */
3293         (void)ulp_mapper_generic_tbl_list_deinit(data);
3294
3295         rte_free(data);
3296         /* Reset the data pointer within the ulp_ctx. */
3297         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
3298 }