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