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