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