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