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