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