net/bnxt: support global resource templates
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_mapper.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2020 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_flow_db.h"
18 #include "ulp_mapper.h"
19
20 static struct bnxt_ulp_glb_resource_info *
21 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
22 {
23         if (!num_entries)
24                 return NULL;
25         *num_entries = BNXT_ULP_GLB_RESOURCE_INFO_TBL_MAX_SZ;
26         return ulp_glb_resource_tbl;
27 }
28
29 /*
30  * Read the global resource from the mapper global resource list
31  *
32  * The regval is always returned in big-endian.
33  *
34  * returns 0 on success
35  */
36 static int32_t
37 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
38                              enum tf_dir dir,
39                              uint16_t idx,
40                              uint64_t *regval)
41 {
42         if (!mapper_data || !regval ||
43             dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
44                 return -EINVAL;
45
46         *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
47         return 0;
48 }
49
50 /*
51  * Write a global resource to the mapper global resource list
52  *
53  * The regval value must be in big-endian.
54  *
55  * return 0 on success.
56  */
57 static int32_t
58 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
59                               struct bnxt_ulp_glb_resource_info *res,
60                               uint64_t regval)
61 {
62         struct bnxt_ulp_mapper_glb_resource_entry *ent;
63
64         /* validate the arguments */
65         if (!data || res->direction >= TF_DIR_MAX ||
66             res->glb_regfile_index >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
67                 return -EINVAL;
68
69         /* write to the mapper data */
70         ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
71         ent->resource_func = res->resource_func;
72         ent->resource_type = res->resource_type;
73         ent->resource_hndl = regval;
74         return 0;
75 }
76
77 /*
78  * Internal function to allocate identity resource and store it in mapper data.
79  *
80  * returns 0 on success
81  */
82 static int32_t
83 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
84                                    struct bnxt_ulp_mapper_data *mapper_data,
85                                    struct bnxt_ulp_glb_resource_info *glb_res)
86 {
87         struct tf_alloc_identifier_parms iparms = { 0 };
88         struct tf_free_identifier_parms fparms;
89         uint64_t regval;
90         struct tf *tfp;
91         int32_t rc = 0;
92
93         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
94         if (!tfp)
95                 return -EINVAL;
96
97         iparms.ident_type = glb_res->resource_type;
98         iparms.dir = glb_res->direction;
99
100         /* Allocate the Identifier using tf api */
101         rc = tf_alloc_identifier(tfp, &iparms);
102         if (rc) {
103                 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
104                             (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
105                             iparms.ident_type);
106                 return rc;
107         }
108
109         /* entries are stored as big-endian format */
110         regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
111         /* write to the mapper global resource */
112         rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
113         if (rc) {
114                 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
115                 /* Free the identifier when update failed */
116                 fparms.dir = iparms.dir;
117                 fparms.ident_type = iparms.ident_type;
118                 fparms.id = iparms.id;
119                 tf_free_identifier(tfp, &fparms);
120                 return rc;
121         }
122 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
123         BNXT_TF_DBG(DEBUG, "Allocated Glb Res Ident [%s][%d][%d] = 0x%04x\n",
124                     (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
125                     glb_res->glb_regfile_index, iparms.ident_type, iparms.id);
126 #endif
127         return rc;
128 }
129
130 /*
131  * Internal function to allocate index tbl resource and store it in mapper data.
132  *
133  * returns 0 on success
134  */
135 static int32_t
136 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
137                                     struct bnxt_ulp_mapper_data *mapper_data,
138                                     struct bnxt_ulp_glb_resource_info *glb_res)
139 {
140         struct tf_alloc_tbl_entry_parms aparms = { 0 };
141         struct tf_free_tbl_entry_parms  free_parms = { 0 };
142         uint64_t regval;
143         struct tf *tfp;
144         uint32_t tbl_scope_id;
145         int32_t rc = 0;
146
147         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
148         if (!tfp)
149                 return -EINVAL;
150
151         /* Get the scope id */
152         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
153         if (rc) {
154                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
155                 return rc;
156         }
157
158         aparms.type = glb_res->resource_type;
159         aparms.dir = glb_res->direction;
160         aparms.search_enable = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO;
161         aparms.tbl_scope_id = tbl_scope_id;
162
163         /* Allocate the index tbl using tf api */
164         rc = tf_alloc_tbl_entry(tfp, &aparms);
165         if (rc) {
166                 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
167                             (aparms.dir == TF_DIR_RX) ? "RX" : "TX",
168                             aparms.type);
169                 return rc;
170         }
171
172         /* entries are stored as big-endian format */
173         regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
174         /* write to the mapper global resource */
175         rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
176         if (rc) {
177                 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
178                 /* Free the identifier when update failed */
179                 free_parms.dir = aparms.dir;
180                 free_parms.type = aparms.type;
181                 free_parms.idx = aparms.idx;
182                 tf_free_tbl_entry(tfp, &free_parms);
183                 return rc;
184         }
185 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
186         BNXT_TF_DBG(DEBUG, "Allocated Glb Res Index [%s][%d][%d] = 0x%04x\n",
187                     (aparms.dir == TF_DIR_RX) ? "RX" : "TX",
188                     glb_res->glb_regfile_index, aparms.type, aparms.idx);
189 #endif
190         return rc;
191 }
192
193 /* Retrieve the cache initialization parameters for the tbl_idx */
194 static struct bnxt_ulp_cache_tbl_params *
195 ulp_mapper_cache_tbl_params_get(uint32_t tbl_idx)
196 {
197         if (tbl_idx >= BNXT_ULP_CACHE_TBL_MAX_SZ)
198                 return NULL;
199
200         return &ulp_cache_tbl_params[tbl_idx];
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 /*
214  * Get the size of the action property for a given index.
215  *
216  * idx [in] The index for the action property
217  *
218  * returns the size of the action property.
219  */
220 static uint32_t
221 ulp_mapper_act_prop_size_get(uint32_t idx)
222 {
223         if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
224                 return 0;
225         return ulp_act_prop_map_table[idx];
226 }
227
228 /*
229  * Get the list of result fields that implement the flow action.
230  * Gets a device dependent list of tables that implement the action template id.
231  *
232  * dev_id [in] The device id of the forwarding element
233  *
234  * tid [in] The action template id that matches the flow
235  *
236  * num_tbls [out] The number of action tables in the returned array
237  *
238  * Returns An array of action tables to implement the flow, or NULL on error.
239  */
240 static struct bnxt_ulp_mapper_tbl_info *
241 ulp_mapper_action_tbl_list_get(uint32_t dev_id,
242                                uint32_t tid,
243                                uint32_t *num_tbls)
244 {
245         uint32_t        idx;
246         uint32_t        tidx;
247
248         if (!num_tbls) {
249                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
250                 return NULL;
251         }
252
253         /* template shift and device mask */
254         tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id);
255
256         /* NOTE: Need to have something from template compiler to help validate
257          * range of dev_id and act_tid
258          */
259         idx             = ulp_act_tmpl_list[tidx].start_tbl_idx;
260         *num_tbls       = ulp_act_tmpl_list[tidx].num_tbls;
261
262         return &ulp_act_tbl_list[idx];
263 }
264
265 /*
266  * Get a list of classifier tables that implement the flow
267  * Gets a device dependent list of tables that implement the class template id
268  *
269  * dev_id [in] The device id of the forwarding element
270  *
271  * tid [in] The template id that matches the flow
272  *
273  * num_tbls [out] The number of classifier tables in the returned array
274  *
275  * fdb_tbl_idx [out] The flow database index Regular or default
276  *
277  * returns An array of classifier tables to implement the flow, or NULL on
278  * error
279  */
280 static struct bnxt_ulp_mapper_tbl_info *
281 ulp_mapper_class_tbl_list_get(uint32_t dev_id,
282                               uint32_t tid,
283                               uint32_t *num_tbls,
284                               uint32_t *fdb_tbl_idx)
285 {
286         uint32_t idx;
287         uint32_t tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id);
288
289         if (!num_tbls)
290                 return NULL;
291
292         /* NOTE: Need to have something from template compiler to help validate
293          * range of dev_id and tid
294          */
295         idx             = ulp_class_tmpl_list[tidx].start_tbl_idx;
296         *num_tbls       = ulp_class_tmpl_list[tidx].num_tbls;
297         *fdb_tbl_idx = ulp_class_tmpl_list[tidx].flow_db_table_type;
298         return &ulp_class_tbl_list[idx];
299 }
300
301 /*
302  * Get the list of key fields that implement the flow.
303  *
304  * ctxt [in] The ulp context
305  *
306  * tbl [in] A single table instance to get the key fields from
307  *
308  * num_flds [out] The number of key fields in the returned array
309  *
310  * Returns array of Key fields, or NULL on error.
311  */
312 static struct bnxt_ulp_mapper_class_key_field_info *
313 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_tbl_info *tbl,
314                           uint32_t *num_flds)
315 {
316         uint32_t idx;
317
318         if (!tbl || !num_flds)
319                 return NULL;
320
321         idx             = tbl->key_start_idx;
322         *num_flds       = tbl->key_num_fields;
323
324         /* NOTE: Need template to provide range checking define */
325         return &ulp_class_key_field_list[idx];
326 }
327
328 /*
329  * Get the list of data fields that implement the flow.
330  *
331  * ctxt [in] The ulp context
332  *
333  * tbl [in] A single table instance to get the data fields from
334  *
335  * num_flds [out] The number of data fields in the returned array.
336  *
337  * Returns array of data fields, or NULL on error.
338  */
339 static struct bnxt_ulp_mapper_result_field_info *
340 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_tbl_info *tbl,
341                              uint32_t *num_flds,
342                              uint32_t *num_encap_flds)
343 {
344         uint32_t idx;
345
346         if (!tbl || !num_flds)
347                 return NULL;
348
349         idx             = tbl->result_start_idx;
350         *num_flds       = tbl->result_num_fields;
351         *num_encap_flds = tbl->encap_num_fields;
352
353         /* NOTE: Need template to provide range checking define */
354         return &ulp_class_result_field_list[idx];
355 }
356
357 /*
358  * Get the list of result fields that implement the flow action.
359  *
360  * tbl [in] A single table instance to get the results fields
361  * from num_flds [out] The number of data fields in the returned
362  * array.
363  *
364  * Returns array of data fields, or NULL on error.
365  */
366 static struct bnxt_ulp_mapper_result_field_info *
367 ulp_mapper_act_result_fields_get(struct bnxt_ulp_mapper_tbl_info *tbl,
368                                  uint32_t *num_rslt_flds,
369                                  uint32_t *num_encap_flds)
370 {
371         uint32_t idx;
372
373         if (!tbl || !num_rslt_flds || !num_encap_flds)
374                 return NULL;
375
376         idx             = tbl->result_start_idx;
377         *num_rslt_flds  = tbl->result_num_fields;
378         *num_encap_flds = tbl->encap_num_fields;
379
380         /* NOTE: Need template to provide range checking define */
381         return &ulp_act_result_field_list[idx];
382 }
383
384 /*
385  * Get the list of ident fields that implement the flow
386  *
387  * tbl [in] A single table instance to get the ident fields from
388  *
389  * num_flds [out] The number of ident fields in the returned array
390  *
391  * returns array of ident fields, or NULL on error
392  */
393 static struct bnxt_ulp_mapper_ident_info *
394 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_tbl_info *tbl,
395                             uint32_t *num_flds)
396 {
397         uint32_t idx;
398
399         if (!tbl || !num_flds)
400                 return NULL;
401
402         idx = tbl->ident_start_idx;
403         *num_flds = tbl->ident_nums;
404
405         /* NOTE: Need template to provide range checking define */
406         return &ulp_ident_list[idx];
407 }
408
409 static struct bnxt_ulp_mapper_cache_entry *
410 ulp_mapper_cache_entry_get(struct bnxt_ulp_context *ulp,
411                            uint32_t id,
412                            uint16_t key)
413 {
414         struct bnxt_ulp_mapper_data *mapper_data;
415
416         mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp);
417         if (!mapper_data || id >= BNXT_ULP_CACHE_TBL_MAX_SZ ||
418             !mapper_data->cache_tbl[id]) {
419                 BNXT_TF_DBG(ERR, "Unable to acquire the cache tbl (%d)\n", id);
420                 return NULL;
421         }
422
423         return &mapper_data->cache_tbl[id][key];
424 }
425
426 /*
427  * Concatenates the tbl_type and tbl_id into a 32bit value for storing in the
428  * resource_type.  This is done to conserve memory since both the tbl_type and
429  * tbl_id are 16bit.
430  */
431 static inline void
432 ulp_mapper_cache_res_type_set(struct ulp_flow_db_res_params *res,
433                               uint16_t tbl_type,
434                               uint16_t tbl_id)
435 {
436         res->resource_type = tbl_type;
437         res->resource_sub_type = tbl_id;
438 }
439
440 /* Extracts the tbl_type and tbl_id from the 32bit resource type. */
441 static inline void
442 ulp_mapper_cache_res_type_get(struct ulp_flow_db_res_params *res,
443                               uint16_t *tbl_type,
444                               uint16_t *tbl_id)
445 {
446         *tbl_type = res->resource_type;
447         *tbl_id = res->resource_sub_type;
448 }
449
450 static int32_t
451 ulp_mapper_cache_entry_free(struct bnxt_ulp_context *ulp,
452                             struct tf *tfp,
453                             struct ulp_flow_db_res_params *res)
454 {
455         struct bnxt_ulp_mapper_cache_entry *cache_entry;
456         struct tf_free_identifier_parms ident_parms;
457         struct tf_free_tcam_entry_parms tcam_parms;
458         uint16_t table_id, table_type;
459         int32_t rc, trc, i;
460
461         /*
462          * The table id, used for cache, and table_type, used for tcam, are
463          * both encoded within the resource.  We must first extract them to
464          * formulate the args for tf calls.
465          */
466         ulp_mapper_cache_res_type_get(res, &table_type, &table_id);
467         cache_entry = ulp_mapper_cache_entry_get(ulp, table_id,
468                                                  (uint16_t)res->resource_hndl);
469         if (!cache_entry || !cache_entry->ref_count) {
470                 BNXT_TF_DBG(ERR, "Cache entry (%d:%d) not valid on free.\n",
471                             table_id, (uint16_t)res->resource_hndl);
472                 return -EINVAL;
473         }
474
475         /*
476          * See if we need to delete the entry.  The tcam and identifiers are all
477          * tracked by the cached entries reference count.  All are deleted when
478          * the reference count hit zero.
479          */
480         cache_entry->ref_count--;
481         if (cache_entry->ref_count)
482                 return 0;
483
484         /*
485          * Need to delete the tcam entry and the allocated identifiers.
486          * In the event of a failure, need to try to delete the remaining
487          * resources before returning error.
488          */
489         tcam_parms.dir = res->direction;
490         tcam_parms.tcam_tbl_type = table_type;
491         tcam_parms.idx = cache_entry->tcam_idx;
492         rc = tf_free_tcam_entry(tfp, &tcam_parms);
493         if (rc)
494                 BNXT_TF_DBG(ERR, "Failed to free tcam [%d][%s][0x%04x] rc=%d\n",
495                             table_type,
496                             (res->direction == TF_DIR_RX) ? "RX" : "TX",
497                             tcam_parms.idx, rc);
498
499         /*
500          * Free the identifiers associated with the tcam entry.  Entries with
501          * negative one are considered uninitialized.
502          */
503         for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) {
504                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
505                         continue;
506
507                 ident_parms.dir = res->direction;
508                 ident_parms.ident_type = cache_entry->ident_types[i];
509                 ident_parms.id = cache_entry->idents[i];
510                 trc = tf_free_identifier(tfp, &ident_parms);
511                 if (trc) {
512                         BNXT_TF_DBG(ERR, "Failed to free identifier "
513                                     "[%d][%s][0x%04x] rc=%d\n",
514                                     ident_parms.ident_type,
515                                     (res->direction == TF_DIR_RX) ? "RX" : "TX",
516                                     ident_parms.id, trc);
517                         rc = trc;
518                 }
519         }
520
521         return rc;
522 }
523
524 static inline int32_t
525 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp  __rte_unused,
526                            struct tf *tfp,
527                            struct ulp_flow_db_res_params *res)
528 {
529         struct tf_free_tcam_entry_parms fparms = {
530                 .dir            = res->direction,
531                 .tcam_tbl_type  = res->resource_type,
532                 .idx            = (uint16_t)res->resource_hndl
533         };
534
535         return tf_free_tcam_entry(tfp, &fparms);
536 }
537
538 static inline int32_t
539 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
540                             struct tf *tfp,
541                             struct ulp_flow_db_res_params *res)
542 {
543         struct tf_free_tbl_entry_parms fparms = {
544                 .dir    = res->direction,
545                 .type   = res->resource_type,
546                 .idx    = (uint32_t)res->resource_hndl
547         };
548
549         /*
550          * Just set the table scope, it will be ignored if not necessary
551          * by the tf_free_tbl_entry
552          */
553         bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
554
555         return tf_free_tbl_entry(tfp, &fparms);
556 }
557
558 static inline int32_t
559 ulp_mapper_eem_entry_free(struct bnxt_ulp_context *ulp,
560                           struct tf *tfp,
561                           struct ulp_flow_db_res_params *res)
562 {
563         struct tf_delete_em_entry_parms fparms = { 0 };
564         int32_t rc;
565
566         fparms.dir              = res->direction;
567         fparms.mem              = TF_MEM_EXTERNAL;
568         fparms.flow_handle      = res->resource_hndl;
569
570         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
571         if (rc) {
572                 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
573                 return -EINVAL;
574         }
575
576         return tf_delete_em_entry(tfp, &fparms);
577 }
578
579 static inline int32_t
580 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
581                       struct tf *tfp,
582                       struct ulp_flow_db_res_params *res)
583 {
584         struct tf_free_identifier_parms fparms = {
585                 .dir            = res->direction,
586                 .ident_type     = res->resource_type,
587                 .id             = (uint16_t)res->resource_hndl
588         };
589
590         return tf_free_identifier(tfp, &fparms);
591 }
592
593 static inline int32_t
594 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
595                      struct ulp_flow_db_res_params *res)
596 {
597         return ulp_mark_db_mark_del(ulp,
598                                     res->resource_type,
599                                     res->resource_hndl);
600 }
601
602 /*
603  * Process the identifier instruction and either store it in the flow database
604  * or return it in the val (if not NULL) on success.  If val is NULL, the
605  * identifier is to be stored in the flow database.
606  */
607 static int32_t
608 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
609                          struct bnxt_ulp_mapper_tbl_info *tbl,
610                          struct bnxt_ulp_mapper_ident_info *ident,
611                          uint16_t *val)
612 {
613         struct ulp_flow_db_res_params   fid_parms;
614         uint64_t id = 0;
615         int32_t idx;
616         struct tf_alloc_identifier_parms iparms = { 0 };
617         struct tf_free_identifier_parms free_parms = { 0 };
618         struct tf *tfp;
619         int rc;
620
621         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
622         if (!tfp) {
623                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
624                 return -EINVAL;
625         }
626
627         idx = ident->regfile_idx;
628
629         iparms.ident_type = ident->ident_type;
630         iparms.dir = tbl->direction;
631
632         rc = tf_alloc_identifier(tfp, &iparms);
633         if (rc) {
634                 BNXT_TF_DBG(ERR, "Alloc ident %s:%d failed.\n",
635                             (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
636                             iparms.ident_type);
637                 return rc;
638         }
639
640         id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
641         if (!ulp_regfile_write(parms->regfile, idx, id)) {
642                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
643                 rc = -EINVAL;
644                 /* Need to free the identifier, so goto error */
645                 goto error;
646         }
647
648         /* Link the resource to the flow in the flow db */
649         if (!val) {
650                 memset(&fid_parms, 0, sizeof(fid_parms));
651                 fid_parms.direction             = tbl->direction;
652                 fid_parms.resource_func = ident->resource_func;
653                 fid_parms.resource_type = ident->ident_type;
654                 fid_parms.resource_hndl = iparms.id;
655                 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
656
657                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
658                                               parms->tbl_idx,
659                                               parms->fid,
660                                               &fid_parms);
661                 if (rc) {
662                         BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
663                                     rc);
664                         /* Need to free the identifier, so goto error */
665                         goto error;
666                 }
667         } else {
668                 *val = iparms.id;
669         }
670
671         return 0;
672
673 error:
674         /* Need to free the identifier */
675         free_parms.dir          = tbl->direction;
676         free_parms.ident_type   = ident->ident_type;
677         free_parms.id           = iparms.id;
678
679         (void)tf_free_identifier(tfp, &free_parms);
680
681         BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
682                     ident->description,
683                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX");
684         return rc;
685 }
686
687 static int32_t
688 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
689                                 enum tf_dir dir,
690                                 struct bnxt_ulp_mapper_result_field_info *fld,
691                                 struct ulp_blob *blob,
692                                 const char *name)
693 {
694         uint16_t idx, size_idx;
695         uint8_t  *val = NULL;
696         uint64_t regval;
697         uint32_t val_size = 0, field_size = 0;
698         uint64_t act_bit;
699         uint8_t act_val;
700
701         switch (fld->result_opcode) {
702         case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
703                 val = fld->result_operand;
704                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
705                         BNXT_TF_DBG(ERR, "%s failed to add field\n", name);
706                         return -EINVAL;
707                 }
708                 break;
709         case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_PROP:
710                 if (!ulp_operand_read(fld->result_operand,
711                                       (uint8_t *)&idx, sizeof(uint16_t))) {
712                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
713                         return -EINVAL;
714                 }
715                 idx = tfp_be_to_cpu_16(idx);
716
717                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
718                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
719                         return -EINVAL;
720                 }
721                 val = &parms->act_prop->act_details[idx];
722                 field_size = ulp_mapper_act_prop_size_get(idx);
723                 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
724                         field_size  = field_size -
725                             ((fld->field_bit_size + 7) / 8);
726                         val += field_size;
727                 }
728                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
729                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
730                         return -EINVAL;
731                 }
732                 break;
733         case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_BIT:
734                 if (!ulp_operand_read(fld->result_operand,
735                                       (uint8_t *)&act_bit, sizeof(uint64_t))) {
736                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
737                         return -EINVAL;
738                 }
739                 act_bit = tfp_be_to_cpu_64(act_bit);
740                 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
741                         act_val = 1;
742                 else
743                         act_val = 0;
744                 if (fld->field_bit_size > ULP_BYTE_2_BITS(sizeof(act_val))) {
745                         BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
746                         return -EINVAL;
747                 }
748                 if (!ulp_blob_push(blob, &act_val, fld->field_bit_size)) {
749                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
750                         return -EINVAL;
751                 }
752                 val = &act_val;
753                 break;
754         case BNXT_ULP_MAPPER_OPC_SET_TO_ENCAP_ACT_PROP_SZ:
755                 if (!ulp_operand_read(fld->result_operand,
756                                       (uint8_t *)&idx, sizeof(uint16_t))) {
757                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
758                         return -EINVAL;
759                 }
760                 idx = tfp_be_to_cpu_16(idx);
761
762                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
763                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
764                         return -EINVAL;
765                 }
766                 val = &parms->act_prop->act_details[idx];
767
768                 /* get the size index next */
769                 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
770                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
771                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
772                         return -EINVAL;
773                 }
774                 size_idx = tfp_be_to_cpu_16(size_idx);
775
776                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
777                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
778                         return -EINVAL;
779                 }
780                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
781                        sizeof(uint32_t));
782                 val_size = tfp_be_to_cpu_32(val_size);
783                 val_size = ULP_BYTE_2_BITS(val_size);
784                 ulp_blob_push_encap(blob, val, val_size);
785                 break;
786         case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
787                 if (!ulp_operand_read(fld->result_operand,
788                                       (uint8_t *)&idx, sizeof(uint16_t))) {
789                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
790                         return -EINVAL;
791                 }
792
793                 idx = tfp_be_to_cpu_16(idx);
794                 /* Uninitialized regfile entries return 0 */
795                 if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
796                         BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
797                                     name, idx);
798                         return -EINVAL;
799                 }
800
801                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
802                 if (!val) {
803                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
804                         return -EINVAL;
805                 }
806                 break;
807         case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
808                 if (!ulp_operand_read(fld->result_operand,
809                                       (uint8_t *)&idx,
810                                       sizeof(uint16_t))) {
811                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
812                         return -EINVAL;
813                 }
814                 idx = tfp_be_to_cpu_16(idx);
815                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
816                                                  dir,
817                                                  idx, &regval)) {
818                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
819                                     name, idx);
820                         return -EINVAL;
821                 }
822                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
823                 if (!val) {
824                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
825                         return -EINVAL;
826                 }
827                 break;
828         case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
829                 if (!ulp_operand_read(fld->result_operand,
830                                       (uint8_t *)&idx,
831                                       sizeof(uint16_t))) {
832                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
833                         return -EINVAL;
834                 }
835                 idx = tfp_be_to_cpu_16(idx);
836                 if (idx < BNXT_ULP_CF_IDX_LAST)
837                         val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
838                                                fld->field_bit_size);
839                 if (!val) {
840                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
841                         return -EINVAL;
842                 }
843                 break;
844         case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
845                 if (ulp_blob_pad_push(blob, fld->field_bit_size) < 0) {
846                         BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
847                         return -EINVAL;
848                 }
849
850                 break;
851         default:
852                 return -EINVAL;
853         }
854         return 0;
855 }
856
857 /* Function to alloc action record and set the table. */
858 static int32_t
859 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
860                                  enum tf_dir dir,
861                                  struct bnxt_ulp_mapper_class_key_field_info *f,
862                                  struct ulp_blob *blob,
863                                  uint8_t is_key,
864                                  const char *name)
865 {
866         uint64_t val64;
867         uint16_t idx, bitlen;
868         uint32_t opcode;
869         uint8_t *operand;
870         struct ulp_regfile *regfile = parms->regfile;
871         uint8_t *val = NULL;
872         struct bnxt_ulp_mapper_class_key_field_info *fld = f;
873         uint32_t field_size;
874
875         if (is_key) {
876                 operand = fld->spec_operand;
877                 opcode  = fld->spec_opcode;
878         } else {
879                 operand = fld->mask_operand;
880                 opcode  = fld->mask_opcode;
881         }
882
883         bitlen = fld->field_bit_size;
884
885         switch (opcode) {
886         case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
887                 val = operand;
888                 if (!ulp_blob_push(blob, val, bitlen)) {
889                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
890                         return -EINVAL;
891                 }
892                 break;
893         case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
894                 if (ulp_blob_pad_push(blob, bitlen) < 0) {
895                         BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
896                         return -EINVAL;
897                 }
898
899                 break;
900         case BNXT_ULP_MAPPER_OPC_SET_TO_HDR_FIELD:
901                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
902                                       sizeof(uint16_t))) {
903                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
904                         return -EINVAL;
905                 }
906                 idx = tfp_be_to_cpu_16(idx);
907                 if (is_key)
908                         val = parms->hdr_field[idx].spec;
909                 else
910                         val = parms->hdr_field[idx].mask;
911
912                 /*
913                  * Need to account for how much data was pushed to the header
914                  * field vs how much is to be inserted in the key/mask.
915                  */
916                 field_size = parms->hdr_field[idx].size;
917                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
918                         field_size  = field_size - ((bitlen + 7) / 8);
919                         val += field_size;
920                 }
921
922                 if (!ulp_blob_push(blob, val, bitlen)) {
923                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
924                         return -EINVAL;
925                 }
926                 break;
927         case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
928                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
929                                       sizeof(uint16_t))) {
930                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
931                         return -EINVAL;
932                 }
933                 idx = tfp_be_to_cpu_16(idx);
934                 if (idx < BNXT_ULP_CF_IDX_LAST)
935                         val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
936                                                bitlen);
937                 if (!val) {
938                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
939                         return -EINVAL;
940                 }
941                 break;
942         case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
943                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
944                                       sizeof(uint16_t))) {
945                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
946                         return -EINVAL;
947                 }
948                 idx = tfp_be_to_cpu_16(idx);
949
950                 if (!ulp_regfile_read(regfile, idx, &val64)) {
951                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
952                                     name, idx);
953                         return -EINVAL;
954                 }
955
956                 val = ulp_blob_push_64(blob, &val64, bitlen);
957                 if (!val) {
958                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
959                         return -EINVAL;
960                 }
961                 break;
962         case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
963                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
964                                       sizeof(uint16_t))) {
965                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
966                         return -EINVAL;
967                 }
968                 idx = tfp_be_to_cpu_16(idx);
969                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
970                                                  dir,
971                                                  idx, &val64)) {
972                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
973                                     name, idx);
974                         return -EINVAL;
975                 }
976                 val = ulp_blob_push_64(blob, &val64, bitlen);
977                 if (!val) {
978                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
979                         return -EINVAL;
980                 }
981                 break;
982         default:
983                 break;
984         }
985
986         return 0;
987 }
988
989 static int32_t
990 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
991                              struct bnxt_ulp_mapper_tbl_info *tbl,
992                              uint64_t flow_id)
993 {
994         enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
995         struct ulp_flow_db_res_params fid_parms;
996         uint32_t mark, gfid, mark_flag;
997         int32_t rc = 0;
998
999         if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1000             !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1001               ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1002                                BNXT_ULP_ACTION_BIT_MARK)))
1003                 return rc; /* no need to perform gfid process */
1004
1005         /* Get the mark id details from action property */
1006         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1007                sizeof(mark));
1008         mark = tfp_be_to_cpu_32(mark);
1009
1010         TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1011         mark_flag  = BNXT_ULP_MARK_GLOBAL_HW_FID;
1012         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1013                                   gfid, mark);
1014         if (rc) {
1015                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1016                 return rc;
1017         }
1018         fid_parms.direction = tbl->direction;
1019         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1020         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1021         fid_parms.resource_type = mark_flag;
1022         fid_parms.resource_hndl = gfid;
1023         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1024                                       parms->tbl_idx,
1025                                       parms->fid,
1026                                       &fid_parms);
1027         if (rc)
1028                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1029         return rc;
1030 }
1031
1032 static int32_t
1033 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1034                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1035 {
1036         enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1037         struct ulp_flow_db_res_params fid_parms;
1038         uint32_t act_idx, mark, mark_flag;
1039         uint64_t val64;
1040         int32_t rc = 0;
1041
1042         if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1043             !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1044               ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1045                                BNXT_ULP_ACTION_BIT_MARK)))
1046                 return rc; /* no need to perform mark action process */
1047
1048         /* Get the mark id details from action property */
1049         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1050                sizeof(mark));
1051         mark = tfp_be_to_cpu_32(mark);
1052
1053         if (!ulp_regfile_read(parms->regfile,
1054                               BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1055                               &val64)) {
1056                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1057                 return -EINVAL;
1058         }
1059         act_idx = tfp_be_to_cpu_64(val64);
1060         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID;
1061         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1062                                   act_idx, mark);
1063         if (rc) {
1064                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1065                 return rc;
1066         }
1067         fid_parms.direction = tbl->direction;
1068         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1069         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1070         fid_parms.resource_type = mark_flag;
1071         fid_parms.resource_hndl = act_idx;
1072         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1073                                       parms->tbl_idx,
1074                                       parms->fid,
1075                                       &fid_parms);
1076         if (rc)
1077                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1078         return rc;
1079 }
1080
1081 static int32_t
1082 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1083                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1084 {
1085         struct ulp_flow_db_res_params fid_parms;
1086         uint32_t act_idx, mark, mark_flag;
1087         uint64_t val64;
1088         enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1089         int32_t rc = 0;
1090
1091         if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1092             mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION)
1093                 return rc; /* no need to perform mark action process */
1094
1095         /* Get the mark id details from the computed field of dev port id */
1096         mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1097
1098          /* Get the main action pointer */
1099         if (!ulp_regfile_read(parms->regfile,
1100                               BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1101                               &val64)) {
1102                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1103                 return -EINVAL;
1104         }
1105         act_idx = tfp_be_to_cpu_64(val64);
1106
1107         /* Set the mark flag to local fid and vfr flag */
1108         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1109
1110         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1111                                   act_idx, mark);
1112         if (rc) {
1113                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1114                 return rc;
1115         }
1116         fid_parms.direction = tbl->direction;
1117         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1118         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1119         fid_parms.resource_type = mark_flag;
1120         fid_parms.resource_hndl = act_idx;
1121         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1122                                       parms->tbl_idx,
1123                                       parms->fid,
1124                                       &fid_parms);
1125         if (rc)
1126                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1127         return rc;
1128 }
1129
1130 static int32_t
1131 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1132                             struct bnxt_ulp_mapper_tbl_info *tbl)
1133 {
1134         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
1135         struct ulp_blob key, mask, data;
1136         uint32_t i, num_kflds;
1137         struct tf *tfp;
1138         int32_t rc, trc;
1139         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
1140         struct tf_set_tcam_entry_parms sparms           = { 0 };
1141         struct ulp_flow_db_res_params   fid_parms       = { 0 };
1142         struct tf_free_tcam_entry_parms free_parms      = { 0 };
1143         uint32_t hit = 0;
1144         uint16_t tmplen = 0;
1145
1146         /* Skip this if was handled by the cache. */
1147         if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) {
1148                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1149                 return 0;
1150         }
1151
1152         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1153         if (!tfp) {
1154                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1155                 return -EINVAL;
1156         }
1157
1158         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1159         if (!kflds || !num_kflds) {
1160                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1161                 return -EINVAL;
1162         }
1163
1164         if (!ulp_blob_init(&key, tbl->key_bit_size,
1165                            parms->device_params->byte_order) ||
1166             !ulp_blob_init(&mask, tbl->key_bit_size,
1167                            parms->device_params->byte_order) ||
1168             !ulp_blob_init(&data, tbl->result_bit_size,
1169                            parms->device_params->byte_order)) {
1170                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1171                 return -EINVAL;
1172         }
1173
1174         /* create the key/mask */
1175         /*
1176          * NOTE: The WC table will require some kind of flag to handle the
1177          * mode bits within the key/mask
1178          */
1179         for (i = 0; i < num_kflds; i++) {
1180                 /* Setup the key */
1181                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1182                                                       &kflds[i],
1183                                                       &key, 1, "TCAM Key");
1184                 if (rc) {
1185                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1186                         return rc;
1187                 }
1188
1189                 /* Setup the mask */
1190                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1191                                                       &kflds[i],
1192                                                       &mask, 0, "TCAM Mask");
1193                 if (rc) {
1194                         BNXT_TF_DBG(ERR, "Mask field set failed.\n");
1195                         return rc;
1196                 }
1197         }
1198
1199         aparms.dir              = tbl->direction;
1200         aparms.tcam_tbl_type    = tbl->resource_type;
1201         aparms.search_enable    = tbl->srch_b4_alloc;
1202         aparms.key_sz_in_bits   = tbl->key_bit_size;
1203         aparms.key              = ulp_blob_data_get(&key, &tmplen);
1204         if (tbl->key_bit_size != tmplen) {
1205                 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1206                             tmplen, tbl->key_bit_size);
1207                 return -EINVAL;
1208         }
1209
1210         aparms.mask             = ulp_blob_data_get(&mask, &tmplen);
1211         if (tbl->key_bit_size != tmplen) {
1212                 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1213                             tmplen, tbl->key_bit_size);
1214                 return -EINVAL;
1215         }
1216
1217         aparms.priority         = tbl->priority;
1218
1219         /*
1220          * All failures after this succeeds require the entry to be freed.
1221          * cannot return directly on failure, but needs to goto error
1222          */
1223         rc = tf_alloc_tcam_entry(tfp, &aparms);
1224         if (rc) {
1225                 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1226                 return rc;
1227         }
1228
1229         hit = aparms.hit;
1230
1231         /* Build the result */
1232         if (!tbl->srch_b4_alloc || !hit) {
1233                 struct bnxt_ulp_mapper_result_field_info *dflds;
1234                 struct bnxt_ulp_mapper_ident_info *idents;
1235                 uint32_t num_dflds, num_idents;
1236                 uint32_t encap_flds = 0;
1237
1238                 /*
1239                  * Since the cache entry is responsible for allocating
1240                  * identifiers when in use, allocate the identifiers only
1241                  * during normal processing.
1242                  */
1243                 if (parms->tcam_tbl_opc ==
1244                     BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1245                         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1246
1247                         for (i = 0; i < num_idents; i++) {
1248                                 rc = ulp_mapper_ident_process(parms, tbl,
1249                                                               &idents[i], NULL);
1250                                 /* Already logged the error, just return */
1251                                 if (rc)
1252                                         goto error;
1253                         }
1254                 }
1255
1256                 /* Create the result data blob */
1257                 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds,
1258                                                      &encap_flds);
1259                 if (!dflds || !num_dflds || encap_flds) {
1260                         BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1261                         rc = -EINVAL;
1262                         goto error;
1263                 }
1264
1265                 for (i = 0; i < num_dflds; i++) {
1266                         rc = ulp_mapper_result_field_process(parms,
1267                                                              tbl->direction,
1268                                                              &dflds[i],
1269                                                              &data,
1270                                                              "TCAM Result");
1271                         if (rc) {
1272                                 BNXT_TF_DBG(ERR, "Failed to set data fields\n");
1273                                 goto error;
1274                         }
1275                 }
1276
1277                 sparms.dir              = aparms.dir;
1278                 sparms.tcam_tbl_type    = aparms.tcam_tbl_type;
1279                 sparms.idx              = aparms.idx;
1280                 /* Already verified the key/mask lengths */
1281                 sparms.key              = ulp_blob_data_get(&key, &tmplen);
1282                 sparms.mask             = ulp_blob_data_get(&mask, &tmplen);
1283                 sparms.key_sz_in_bits   = tbl->key_bit_size;
1284                 sparms.result           = ulp_blob_data_get(&data, &tmplen);
1285
1286                 if (tbl->result_bit_size != tmplen) {
1287                         BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1288                                     tmplen, tbl->result_bit_size);
1289                         rc = -EINVAL;
1290                         goto error;
1291                 }
1292                 sparms.result_sz_in_bits = tbl->result_bit_size;
1293
1294                 rc = tf_set_tcam_entry(tfp, &sparms);
1295                 if (rc) {
1296                         BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n",
1297                                     sparms.tcam_tbl_type,
1298                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
1299                                     sparms.idx);
1300                         goto error;
1301                 }
1302
1303                 /* Update cache with TCAM index if the was cache allocated. */
1304                 if (parms->tcam_tbl_opc ==
1305                     BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC) {
1306                         if (!parms->cache_ptr) {
1307                                 BNXT_TF_DBG(ERR, "Unable to update cache");
1308                                 rc = -EINVAL;
1309                                 goto error;
1310                         }
1311                         parms->cache_ptr->tcam_idx = aparms.idx;
1312                 }
1313
1314                 /* Mark action */
1315                 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1316                 if (rc)
1317                         goto error;
1318
1319         } else {
1320                 BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n");
1321                 rc = -EINVAL;
1322                 goto error;
1323         }
1324
1325         /*
1326          * Only link the entry to the flow db in the event that cache was not
1327          * used.
1328          */
1329         if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1330                 fid_parms.direction = tbl->direction;
1331                 fid_parms.resource_func = tbl->resource_func;
1332                 fid_parms.resource_type = tbl->resource_type;
1333                 fid_parms.critical_resource = tbl->critical_resource;
1334                 fid_parms.resource_hndl = aparms.idx;
1335                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1336                                               parms->tbl_idx,
1337                                               parms->fid,
1338                                               &fid_parms);
1339                 if (rc) {
1340                         BNXT_TF_DBG(ERR,
1341                                     "Failed to link resource to flow rc = %d\n",
1342                                     rc);
1343                         /* Need to free the identifier, so goto error */
1344                         goto error;
1345                 }
1346         } else {
1347                 /*
1348                  * Reset the tcam table opcode to normal in case the next tcam
1349                  * entry does not use cache.
1350                  */
1351                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1352                 parms->cache_ptr = NULL;
1353         }
1354
1355         return 0;
1356 error:
1357         parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1358         free_parms.dir                  = tbl->direction;
1359         free_parms.tcam_tbl_type        = tbl->resource_type;
1360         free_parms.idx                  = aparms.idx;
1361         trc = tf_free_tcam_entry(tfp, &free_parms);
1362         if (trc)
1363                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1364                             tbl->resource_type, tbl->direction, aparms.idx);
1365
1366         return rc;
1367 }
1368
1369 static int32_t
1370 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1371                           struct bnxt_ulp_mapper_tbl_info *tbl)
1372 {
1373         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
1374         struct bnxt_ulp_mapper_result_field_info *dflds;
1375         struct ulp_blob key, data;
1376         uint32_t i, num_kflds, num_dflds;
1377         uint16_t tmplen;
1378         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1379         struct ulp_flow_db_res_params   fid_parms = { 0 };
1380         struct tf_insert_em_entry_parms iparms = { 0 };
1381         struct tf_delete_em_entry_parms free_parms = { 0 };
1382         int32_t trc;
1383         enum bnxt_ulp_flow_mem_type mtype = parms->device_params->flow_mem_type;
1384         int32_t rc = 0;
1385         uint32_t encap_flds = 0;
1386
1387         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1388         if (!kflds || !num_kflds) {
1389                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1390                 return -EINVAL;
1391         }
1392
1393         /* Initialize the key/result blobs */
1394         if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1395                            parms->device_params->byte_order) ||
1396             !ulp_blob_init(&data, tbl->result_bit_size,
1397                            parms->device_params->byte_order)) {
1398                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1399                 return -EINVAL;
1400         }
1401
1402         /* create the key */
1403         for (i = 0; i < num_kflds; i++) {
1404                 /* Setup the key */
1405                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1406                                                       &kflds[i],
1407                                                       &key, 1, "EM Key");
1408                 if (rc) {
1409                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1410                         return rc;
1411                 }
1412         }
1413
1414         /*
1415          * TBD: Normally should process identifiers in case of using recycle or
1416          * loopback.  Not supporting recycle for now.
1417          */
1418
1419         /* Create the result data blob */
1420         dflds = ulp_mapper_result_fields_get(tbl, &num_dflds, &encap_flds);
1421         if (!dflds || !num_dflds || encap_flds) {
1422                 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1423                 return -EINVAL;
1424         }
1425
1426         for (i = 0; i < num_dflds; i++) {
1427                 struct bnxt_ulp_mapper_result_field_info *fld;
1428
1429                 fld = &dflds[i];
1430
1431                 rc = ulp_mapper_result_field_process(parms,
1432                                                      tbl->direction,
1433                                                      fld,
1434                                                      &data,
1435                                                      "EM Result");
1436                 if (rc) {
1437                         BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
1438                         return rc;
1439                 }
1440         }
1441 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1442         ulp_mapper_result_dump("EEM Result", tbl, &data);
1443 #endif
1444
1445         /* do the transpose for the internal EM keys */
1446         if (tbl->resource_type == TF_MEM_INTERNAL)
1447                 ulp_blob_perform_byte_reverse(&key);
1448
1449         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1450                                              &iparms.tbl_scope_id);
1451         if (rc) {
1452                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1453                 return rc;
1454         }
1455
1456         /*
1457          * NOTE: the actual blob size will differ from the size in the tbl
1458          * entry due to the padding.
1459          */
1460         iparms.dup_check                = 0;
1461         iparms.dir                      = tbl->direction;
1462         iparms.mem                      = tbl->resource_type;
1463         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1464         iparms.key_sz_in_bits           = tbl->key_bit_size;
1465         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1466         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1467
1468         rc = tf_insert_em_entry(tfp, &iparms);
1469         if (rc) {
1470                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1471                 return rc;
1472         }
1473
1474         /* Mark action process */
1475         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
1476             tbl->resource_type == TF_MEM_EXTERNAL)
1477                 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
1478         else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
1479                  tbl->resource_type == TF_MEM_INTERNAL)
1480                 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1481         if (rc) {
1482                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1483                 goto error;
1484         }
1485
1486         /* Link the EM resource to the flow in the flow db */
1487         memset(&fid_parms, 0, sizeof(fid_parms));
1488         fid_parms.direction             = tbl->direction;
1489         fid_parms.resource_func         = tbl->resource_func;
1490         fid_parms.resource_type         = tbl->resource_type;
1491         fid_parms.critical_resource     = tbl->critical_resource;
1492         fid_parms.resource_hndl         = iparms.flow_handle;
1493
1494         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1495                                       parms->tbl_idx,
1496                                       parms->fid,
1497                                       &fid_parms);
1498         if (rc) {
1499                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1500                             rc);
1501                 /* Need to free the identifier, so goto error */
1502                 goto error;
1503         }
1504
1505         return 0;
1506 error:
1507         free_parms.dir          = iparms.dir;
1508         free_parms.mem          = iparms.mem;
1509         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1510         free_parms.flow_handle  = iparms.flow_handle;
1511
1512         trc = tf_delete_em_entry(tfp, &free_parms);
1513         if (trc)
1514                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1515
1516         return rc;
1517 }
1518
1519 static int32_t
1520 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1521                              struct bnxt_ulp_mapper_tbl_info *tbl,
1522                              bool is_class_tbl)
1523 {
1524         struct bnxt_ulp_mapper_result_field_info *flds;
1525         struct ulp_flow_db_res_params   fid_parms;
1526         struct ulp_blob data;
1527         uint64_t idx = 0;
1528         uint16_t tmplen;
1529         uint32_t i, num_flds;
1530         int32_t rc = 0, trc = 0;
1531         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1532         struct tf_set_tbl_entry_parms   sparms = { 0 };
1533         struct tf_free_tbl_entry_parms  free_parms = { 0 };
1534         uint32_t tbl_scope_id;
1535         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1536         uint16_t bit_size;
1537         uint32_t encap_flds = 0;
1538
1539         /* Get the scope id first */
1540         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1541         if (rc) {
1542                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1543                 return rc;
1544         }
1545
1546         /* use the max size if encap is enabled */
1547         if (tbl->encap_num_fields)
1548                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
1549         else
1550                 bit_size = tbl->result_bit_size;
1551
1552         /* Initialize the blob data */
1553         if (!ulp_blob_init(&data, bit_size,
1554                            parms->device_params->byte_order)) {
1555                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1556                 return -EINVAL;
1557         }
1558
1559         /* Get the result fields list */
1560         if (is_class_tbl)
1561                 flds = ulp_mapper_result_fields_get(tbl, &num_flds,
1562                                                     &encap_flds);
1563         else
1564                 flds = ulp_mapper_act_result_fields_get(tbl, &num_flds,
1565                                                         &encap_flds);
1566
1567         if (!flds || (!num_flds && !encap_flds)) {
1568                 BNXT_TF_DBG(ERR, "template undefined for the index table\n");
1569                 return -EINVAL;
1570         }
1571
1572         /* process the result fields, loop through them */
1573         for (i = 0; i < (num_flds + encap_flds); i++) {
1574                 /* set the swap index if encap swap bit is enabled */
1575                 if (parms->device_params->encap_byte_swap && encap_flds &&
1576                     (i == num_flds))
1577                         ulp_blob_encap_swap_idx_set(&data);
1578
1579                 /* Process the result fields */
1580                 rc = ulp_mapper_result_field_process(parms,
1581                                                      tbl->direction,
1582                                                      &flds[i],
1583                                                      &data,
1584                                                      "Indexed Result");
1585                 if (rc) {
1586                         BNXT_TF_DBG(ERR, "data field failed\n");
1587                         return rc;
1588                 }
1589         }
1590
1591         /* if encap bit swap is enabled perform the bit swap */
1592         if (parms->device_params->encap_byte_swap && encap_flds) {
1593                 ulp_blob_perform_encap_swap(&data);
1594 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1595                 BNXT_TF_DBG(INFO, "Dump after encap swap\n");
1596                 ulp_mapper_blob_dump(&data);
1597 #endif
1598         }
1599
1600         /*
1601          * Check for index opcode, if it is Global then
1602          * no need to allocate the table, just set the table
1603          * and exit since it is not maintained in the flow db.
1604          */
1605         if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_GLOBAL) {
1606                 /* get the index from index operand */
1607                 if (tbl->index_operand < BNXT_ULP_GLB_REGFILE_INDEX_LAST &&
1608                     ulp_mapper_glb_resource_read(parms->mapper_data,
1609                                                  tbl->direction,
1610                                                  tbl->index_operand,
1611                                                  &idx)) {
1612                         BNXT_TF_DBG(ERR, "Glbl regfile[%d] read failed.\n",
1613                                     tbl->index_operand);
1614                         return -EINVAL;
1615                 }
1616                 /* set the Tf index table */
1617                 sparms.dir              = tbl->direction;
1618                 sparms.type             = tbl->resource_type;
1619                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1620                 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1621                 sparms.idx              = tfp_be_to_cpu_64(idx);
1622                 sparms.tbl_scope_id     = tbl_scope_id;
1623
1624                 rc = tf_set_tbl_entry(tfp, &sparms);
1625                 if (rc) {
1626                         BNXT_TF_DBG(ERR,
1627                                     "Glbl Set table[%d][%s][%d] failed rc=%d\n",
1628                                     sparms.type,
1629                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
1630                                     sparms.idx,
1631                                     rc);
1632                         return rc;
1633                 }
1634                 return 0; /* success */
1635         }
1636
1637         /* Perform the tf table allocation by filling the alloc params */
1638         aparms.dir              = tbl->direction;
1639         aparms.type             = tbl->resource_type;
1640         aparms.search_enable    = tbl->srch_b4_alloc;
1641         aparms.result           = ulp_blob_data_get(&data, &tmplen);
1642         aparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1643         aparms.tbl_scope_id     = tbl_scope_id;
1644
1645         /* All failures after the alloc succeeds require a free */
1646         rc = tf_alloc_tbl_entry(tfp, &aparms);
1647         if (rc) {
1648                 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1649                             aparms.type,
1650                             (aparms.dir == TF_DIR_RX) ? "RX" : "TX",
1651                             rc);
1652                 return rc;
1653         }
1654
1655         /*
1656          * calculate the idx for the result record, for external EM the offset
1657          * needs to be shifted accordingly. If external non-inline table types
1658          * are used then need to revisit this logic.
1659          */
1660         if (aparms.type == TF_TBL_TYPE_EXT)
1661                 idx = TF_ACT_REC_OFFSET_2_PTR(aparms.idx);
1662         else
1663                 idx = aparms.idx;
1664
1665         /* Always storing values in Regfile in BE */
1666         idx = tfp_cpu_to_be_64(idx);
1667         if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_ALLOCATE) {
1668                 rc = ulp_regfile_write(parms->regfile, tbl->index_operand, idx);
1669                 if (!rc) {
1670                         BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1671                                     tbl->index_operand);
1672                         goto error;
1673                 }
1674         }
1675
1676         /* Perform the tf table set by filling the set params */
1677         if (!tbl->srch_b4_alloc || !aparms.hit) {
1678                 sparms.dir              = tbl->direction;
1679                 sparms.type             = tbl->resource_type;
1680                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1681                 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1682                 sparms.idx              = aparms.idx;
1683                 sparms.tbl_scope_id     = tbl_scope_id;
1684
1685                 rc = tf_set_tbl_entry(tfp, &sparms);
1686                 if (rc) {
1687                         BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1688                                     sparms.type,
1689                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
1690                                     sparms.idx,
1691                                     rc);
1692                         goto error;
1693                 }
1694         }
1695
1696         /* Link the resource to the flow in the flow db */
1697         memset(&fid_parms, 0, sizeof(fid_parms));
1698         fid_parms.direction     = tbl->direction;
1699         fid_parms.resource_func = tbl->resource_func;
1700         fid_parms.resource_type = tbl->resource_type;
1701         fid_parms.resource_sub_type = tbl->resource_sub_type;
1702         fid_parms.resource_hndl = aparms.idx;
1703         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1704
1705         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1706                                       parms->tbl_idx,
1707                                       parms->fid,
1708                                       &fid_parms);
1709         if (rc) {
1710                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1711                             rc);
1712                 goto error;
1713         }
1714
1715         /* Perform the VF rep action */
1716         rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
1717         if (rc) {
1718                 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
1719                 goto error;
1720         }
1721         return rc;
1722 error:
1723         /*
1724          * Free the allocated resource since we failed to either
1725          * write to the entry or link the flow
1726          */
1727         free_parms.dir  = tbl->direction;
1728         free_parms.type = tbl->resource_type;
1729         free_parms.idx  = aparms.idx;
1730         free_parms.tbl_scope_id = tbl_scope_id;
1731
1732         trc = tf_free_tbl_entry(tfp, &free_parms);
1733         if (trc)
1734                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1735
1736         return rc;
1737 }
1738
1739 static int32_t
1740 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1741                              struct bnxt_ulp_mapper_tbl_info *tbl)
1742 {
1743         struct bnxt_ulp_mapper_class_key_field_info *kflds;
1744         struct bnxt_ulp_mapper_cache_entry *cache_entry;
1745         struct bnxt_ulp_mapper_ident_info *idents;
1746         uint32_t i, num_kflds = 0, num_idents = 0;
1747         struct ulp_flow_db_res_params fid_parms;
1748         struct tf_free_identifier_parms fparms;
1749         uint16_t tmplen, tmp_ident;
1750         struct ulp_blob key;
1751         uint8_t *cache_key;
1752         uint64_t regval;
1753         uint16_t *ckey;
1754         int32_t rc;
1755
1756         /* Get the key fields list and build the key. */
1757         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1758         if (!kflds || !num_kflds) {
1759                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1760                 return -EINVAL;
1761         }
1762         if (!ulp_blob_init(&key, tbl->key_bit_size,
1763                            parms->device_params->byte_order)) {
1764                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
1765                 return -EINVAL;
1766         }
1767         for (i = 0; i < num_kflds; i++) {
1768                 /* Setup the key */
1769                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1770                                                       &kflds[i],
1771                                                       &key, 1, "Cache Key");
1772                 if (rc) {
1773                         BNXT_TF_DBG(ERR,
1774                                     "Failed to create key for Cache rc=%d\n",
1775                                     rc);
1776                         return -EINVAL;
1777                 }
1778         }
1779
1780         /*
1781          * Perform the lookup in the cache table with constructed key.  The
1782          * cache_key is a byte array of tmplen, it needs to be converted to a
1783          * index for the cache table.
1784          */
1785         cache_key = ulp_blob_data_get(&key, &tmplen);
1786         ckey = (uint16_t *)cache_key;
1787
1788         /*
1789          * The id computed based on resource sub type and direction where
1790          * dir is the bit0 and rest of the bits come from resource
1791          * sub type.
1792          */
1793         cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx,
1794                                                  (tbl->resource_sub_type << 1 |
1795                                                  (tbl->direction & 0x1)),
1796                                                  *ckey);
1797
1798         /*
1799          * Get the identifier list for processing by both the hit and miss
1800          * processing.
1801          */
1802         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1803
1804         if (!cache_entry->ref_count) {
1805                 /* Initialize the cache entry */
1806                 cache_entry->tcam_idx = 0;
1807                 cache_entry->ref_count = 0;
1808                 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++)
1809                         cache_entry->idents[i] = ULP_IDENTS_INVALID;
1810
1811                 /* Need to allocate identifiers for storing in the cache. */
1812                 for (i = 0; i < num_idents; i++) {
1813                         /*
1814                          * Since we are using the cache, the identifier does not
1815                          * get added to the flow db.  Pass in the pointer to the
1816                          * tmp_ident.
1817                          */
1818                         rc = ulp_mapper_ident_process(parms, tbl,
1819                                                       &idents[i], &tmp_ident);
1820                         if (rc)
1821                                 goto error;
1822
1823                         cache_entry->ident_types[i] = idents[i].ident_type;
1824                         cache_entry->idents[i] = tmp_ident;
1825                 }
1826
1827                 /* Tell the TCAM processor to alloc an entry */
1828                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC;
1829                 /* Store the cache key for use by the tcam process code */
1830                 parms->cache_ptr = cache_entry;
1831         } else {
1832                 /* Cache hit, get values from result. */
1833                 for (i = 0; i < num_idents; i++) {
1834                         regval = (uint64_t)cache_entry->idents[i];
1835                         if (!ulp_regfile_write(parms->regfile,
1836                                                idents[i].regfile_idx,
1837                                                tfp_cpu_to_be_64(regval))) {
1838                                 BNXT_TF_DBG(ERR,
1839                                             "Failed to write to regfile\n");
1840                                 return -EINVAL;
1841                         }
1842                 }
1843                 /*
1844                  * The cached entry is being used, so let the tcam processing
1845                  * know not to process this table.
1846                  */
1847                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP;
1848         }
1849
1850         /* Made through the cache processing, increment the reference count. */
1851         cache_entry->ref_count++;
1852
1853         /* Link the cache to the flow db. */
1854         memset(&fid_parms, 0, sizeof(fid_parms));
1855         fid_parms.direction = tbl->direction;
1856         fid_parms.resource_func = tbl->resource_func;
1857
1858         /*
1859          * Cache resource type is composed of table_type, resource
1860          * sub type and direction, it needs to set appropriately via setter.
1861          */
1862         ulp_mapper_cache_res_type_set(&fid_parms,
1863                                       tbl->resource_type,
1864                                       (tbl->resource_sub_type << 1 |
1865                                        (tbl->direction & 0x1)));
1866         fid_parms.resource_hndl = (uint64_t)*ckey;
1867         fid_parms.critical_resource = tbl->critical_resource;
1868         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1869                                       parms->tbl_idx,
1870                                       parms->fid,
1871                                       &fid_parms);
1872         if (rc)
1873                 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n");
1874
1875         return rc;
1876 error:
1877         /*
1878          * This error handling only gets called when the idents are being
1879          * allocated for the cache on misses.  Using the num_idents that was
1880          * previously set.
1881          */
1882         for (i = 0; i < num_idents; i++) {
1883                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
1884                         continue;
1885
1886                 fparms.dir = tbl->direction;
1887                 fparms.ident_type = idents[i].ident_type;
1888                 fparms.id = cache_entry->idents[i];
1889                 tf_free_identifier(parms->tfp, &fparms);
1890         }
1891
1892         return rc;
1893 }
1894
1895 static int32_t
1896 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1897                           struct bnxt_ulp_mapper_tbl_info *tbl)
1898 {
1899         struct bnxt_ulp_mapper_result_field_info *flds;
1900         struct ulp_blob data;
1901         uint64_t idx;
1902         uint16_t tmplen;
1903         uint32_t i, num_flds;
1904         int32_t rc = 0;
1905         struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
1906         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1907         uint32_t encap_flds;
1908
1909         /* Initialize the blob data */
1910         if (!ulp_blob_init(&data, tbl->result_bit_size,
1911                            parms->device_params->byte_order)) {
1912                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1913                 return -EINVAL;
1914         }
1915
1916         /* Get the result fields list */
1917         flds = ulp_mapper_result_fields_get(tbl, &num_flds, &encap_flds);
1918
1919         if (!flds || !num_flds || encap_flds) {
1920                 BNXT_TF_DBG(ERR, "template undefined for the IF table\n");
1921                 return -EINVAL;
1922         }
1923
1924         /* process the result fields, loop through them */
1925         for (i = 0; i < num_flds; i++) {
1926                 /* Process the result fields */
1927                 rc = ulp_mapper_result_field_process(parms,
1928                                                      tbl->direction,
1929                                                      &flds[i],
1930                                                      &data,
1931                                                      "IFtable Result");
1932                 if (rc) {
1933                         BNXT_TF_DBG(ERR, "data field failed\n");
1934                         return rc;
1935                 }
1936         }
1937
1938         /* Get the index details from computed field */
1939         if (tbl->index_opcode != BNXT_ULP_INDEX_OPCODE_COMP_FIELD) {
1940                 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
1941                 return -EINVAL;
1942         }
1943         idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand);
1944
1945         /* Perform the tf table set by filling the set params */
1946         iftbl_params.dir = tbl->direction;
1947         iftbl_params.type = tbl->resource_type;
1948         iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
1949         iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1950         iftbl_params.idx = idx;
1951
1952         rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
1953         if (rc) {
1954                 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1955                             iftbl_params.type,
1956                             (iftbl_params.dir == TF_DIR_RX) ? "RX" : "TX",
1957                             iftbl_params.idx,
1958                             rc);
1959                 return rc;
1960         }
1961
1962         /*
1963          * TBD: Need to look at the need to store idx in flow db for restore
1964          * the table to its original state on deletion of this entry.
1965          */
1966         return rc;
1967 }
1968
1969 static int32_t
1970 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
1971                                   struct bnxt_ulp_mapper_data *mapper_data)
1972 {
1973         struct bnxt_ulp_glb_resource_info *glb_res;
1974         uint32_t num_glb_res_ids, idx;
1975         int32_t rc = 0;
1976
1977         glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
1978         if (!glb_res || !num_glb_res_ids) {
1979                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1980                 return -EINVAL;
1981         }
1982
1983         /* Iterate the global resources and process each one */
1984         for (idx = 0; idx < num_glb_res_ids; idx++) {
1985                 switch (glb_res[idx].resource_func) {
1986                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1987                         rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
1988                                                                 mapper_data,
1989                                                                 &glb_res[idx]);
1990                         break;
1991                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1992                         rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
1993                                                                  mapper_data,
1994                                                                  &glb_res[idx]);
1995                         break;
1996                 default:
1997                         BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
1998                                     glb_res[idx].resource_func);
1999                         rc = -EINVAL;
2000                         break;
2001                 }
2002                 if (rc)
2003                         return rc;
2004         }
2005         return rc;
2006 }
2007
2008 /*
2009  * Function to process the action template. Iterate through the list
2010  * action info templates and process it.
2011  */
2012 static int32_t
2013 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
2014 {
2015         uint32_t        i;
2016         int32_t         rc = 0;
2017         struct bnxt_ulp_mapper_tbl_info *tbl;
2018
2019         if (!parms->atbls || !parms->num_atbls) {
2020                 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
2021                             parms->dev_id, parms->act_tid);
2022                 return -EINVAL;
2023         }
2024
2025         for (i = 0; i < parms->num_atbls; i++) {
2026                 tbl = &parms->atbls[i];
2027                 switch (tbl->resource_func) {
2028                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2029                         rc = ulp_mapper_index_tbl_process(parms, tbl, false);
2030                         if (rc) {
2031                                 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
2032                                             tbl->resource_func);
2033                                 return rc;
2034                         }
2035                         break;
2036                 default:
2037                         BNXT_TF_DBG(ERR, "Unexpected action resource %d\n",
2038                                     tbl->resource_func);
2039                         return -EINVAL;
2040                 }
2041         }
2042
2043         return rc;
2044 }
2045
2046 /* Create the classifier table entries for a flow. */
2047 static int32_t
2048 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
2049 {
2050         uint32_t        i;
2051         int32_t         rc = 0;
2052
2053         if (!parms)
2054                 return -EINVAL;
2055
2056         if (!parms->ctbls || !parms->num_ctbls) {
2057                 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
2058                             parms->dev_id, parms->class_tid);
2059                 return -EINVAL;
2060         }
2061
2062         for (i = 0; i < parms->num_ctbls; i++) {
2063                 struct bnxt_ulp_mapper_tbl_info *tbl = &parms->ctbls[i];
2064
2065                 switch (tbl->resource_func) {
2066                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2067                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
2068                         break;
2069                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
2070                         rc = ulp_mapper_em_tbl_process(parms, tbl);
2071                         break;
2072                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2073                         rc = ulp_mapper_index_tbl_process(parms, tbl, true);
2074                         break;
2075                 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
2076                         rc = ulp_mapper_cache_tbl_process(parms, tbl);
2077                         break;
2078                 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
2079                         rc = ulp_mapper_if_tbl_process(parms, tbl);
2080                         break;
2081                 default:
2082                         BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
2083                                     tbl->resource_func);
2084                         return -EINVAL;
2085                 }
2086
2087                 if (rc) {
2088                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
2089                                     tbl->resource_func);
2090                         return rc;
2091                 }
2092         }
2093
2094         return rc;
2095 }
2096
2097 static int32_t
2098 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
2099                          struct ulp_flow_db_res_params *res)
2100 {
2101         struct tf *tfp;
2102         int32_t rc = 0;
2103
2104         if (!res || !ulp) {
2105                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
2106                 return -EINVAL;
2107         }
2108
2109         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
2110         if (!tfp) {
2111                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
2112                 return -EINVAL;
2113         }
2114
2115         switch (res->resource_func) {
2116         case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
2117                 rc = ulp_mapper_cache_entry_free(ulp, tfp, res);
2118                 break;
2119         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2120                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
2121                 break;
2122         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
2123                 rc = ulp_mapper_eem_entry_free(ulp, tfp, res);
2124                 break;
2125         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2126                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
2127                 break;
2128         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2129                 rc = ulp_mapper_ident_free(ulp, tfp, res);
2130                 break;
2131         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
2132                 rc = ulp_mapper_mark_free(ulp, res);
2133                 break;
2134         default:
2135                 break;
2136         }
2137
2138         return rc;
2139 }
2140
2141 int32_t
2142 ulp_mapper_resources_free(struct bnxt_ulp_context       *ulp_ctx,
2143                           uint32_t fid,
2144                           enum bnxt_ulp_flow_db_tables  tbl_type)
2145 {
2146         struct ulp_flow_db_res_params   res_parms = { 0 };
2147         int32_t                         rc, trc;
2148
2149         if (!ulp_ctx) {
2150                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2151                 return -EINVAL;
2152         }
2153
2154         /*
2155          * Set the critical resource on the first resource del, then iterate
2156          * while status is good
2157          */
2158         res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
2159         rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms);
2160
2161         if (rc) {
2162                 /*
2163                  * This is unexpected on the first call to resource del.
2164                  * It likely means that the flow did not exist in the flow db.
2165                  */
2166                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
2167                             tbl_type, fid, rc);
2168                 return rc;
2169         }
2170
2171         while (!rc) {
2172                 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
2173                 if (trc)
2174                         /*
2175                          * On fail, we still need to attempt to free the
2176                          * remaining resources.  Don't return
2177                          */
2178                         BNXT_TF_DBG(ERR,
2179                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
2180                                     "] failed rc=%d.\n",
2181                                     tbl_type, fid, res_parms.resource_func,
2182                                     res_parms.resource_hndl, trc);
2183
2184                 /* All subsequent call require the non-critical_resource */
2185                 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2186
2187                 rc = ulp_flow_db_resource_del(ulp_ctx,
2188                                               tbl_type,
2189                                               fid,
2190                                               &res_parms);
2191         }
2192
2193         /* Free the Flow ID since we've removed all resources */
2194         rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid);
2195
2196         return rc;
2197 }
2198
2199 static void
2200 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
2201                                     struct bnxt_ulp_mapper_data *mapper_data)
2202 {
2203         struct bnxt_ulp_mapper_glb_resource_entry *ent;
2204         struct ulp_flow_db_res_params res;
2205         uint32_t dir, idx;
2206
2207         /* Iterate the global resources and process each one */
2208         for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
2209                 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_INFO_TBL_MAX_SZ;
2210                       idx++) {
2211                         ent = &mapper_data->glb_res_tbl[dir][idx];
2212                         if (ent->resource_func ==
2213                             BNXT_ULP_RESOURCE_FUNC_INVALID)
2214                                 continue;
2215                         memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
2216                         res.resource_func = ent->resource_func;
2217                         res.direction = dir;
2218                         res.resource_type = ent->resource_type;
2219                         /*convert it from BE to cpu */
2220                         res.resource_hndl =
2221                                 tfp_be_to_cpu_64(ent->resource_hndl);
2222                         ulp_mapper_resource_free(ulp_ctx, &res);
2223                 }
2224         }
2225 }
2226
2227 int32_t
2228 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
2229 {
2230         if (!ulp_ctx) {
2231                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2232                 return -EINVAL;
2233         }
2234
2235         return ulp_mapper_resources_free(ulp_ctx,
2236                                          fid,
2237                                          BNXT_ULP_REGULAR_FLOW_TABLE);
2238 }
2239
2240 /* Function to handle the default global templates that are allocated during
2241  * the startup and reused later.
2242  */
2243 static int32_t
2244 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
2245 {
2246         uint32_t *glbl_tmpl_list;
2247         uint32_t num_glb_tmpls, idx, dev_id;
2248         struct bnxt_ulp_mapper_parms parms;
2249         struct bnxt_ulp_mapper_data *mapper_data;
2250         int32_t rc = 0;
2251
2252         glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
2253         if (!glbl_tmpl_list || !num_glb_tmpls)
2254                 return rc; /* No global templates to process */
2255
2256         /* Get the device id from the ulp context */
2257         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
2258                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2259                 return -EINVAL;
2260         }
2261
2262         mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2263         if (!mapper_data) {
2264                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2265                 return -EINVAL;
2266         }
2267
2268         /* Iterate the global resources and process each one */
2269         for (idx = 0; idx < num_glb_tmpls; idx++) {
2270                 /* Initialize the parms structure */
2271                 memset(&parms, 0, sizeof(parms));
2272                 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2273                 parms.ulp_ctx = ulp_ctx;
2274                 parms.dev_id = dev_id;
2275                 parms.mapper_data = mapper_data;
2276
2277                 /* Get the class table entry from dev id and class id */
2278                 parms.class_tid = glbl_tmpl_list[idx];
2279                 parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
2280                                                             parms.class_tid,
2281                                                             &parms.num_ctbls,
2282                                                             &parms.tbl_idx);
2283                 if (!parms.ctbls || !parms.num_ctbls) {
2284                         BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
2285                                     parms.dev_id, parms.class_tid);
2286                         return -EINVAL;
2287                 }
2288                 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2289                 if (!parms.device_params) {
2290                         BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
2291                                     parms.dev_id, parms.class_tid);
2292                         return -EINVAL;
2293                 }
2294                 rc = ulp_mapper_class_tbls_process(&parms);
2295                 if (rc) {
2296                         BNXT_TF_DBG(ERR,
2297                                     "class tables failed creation for %d:%d\n",
2298                                     parms.dev_id, parms.class_tid);
2299                         return rc;
2300                 }
2301         }
2302         return rc;
2303 }
2304
2305 /* Function to handle the mapping of the Flow to be compatible
2306  * with the underlying hardware.
2307  */
2308 int32_t
2309 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
2310                        struct bnxt_ulp_mapper_create_parms *cparms,
2311                        uint32_t *flowid)
2312 {
2313         struct bnxt_ulp_mapper_parms parms;
2314         struct ulp_regfile regfile;
2315         int32_t  rc, trc;
2316
2317         if (!ulp_ctx || !cparms)
2318                 return -EINVAL;
2319
2320         /* Initialize the parms structure */
2321         memset(&parms, 0, sizeof(parms));
2322         parms.act_prop = cparms->act_prop;
2323         parms.act_bitmap = cparms->act;
2324         parms.regfile = &regfile;
2325         parms.hdr_field = cparms->hdr_field;
2326         parms.comp_fld = cparms->comp_fld;
2327         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2328         parms.ulp_ctx = ulp_ctx;
2329         parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
2330
2331         /* Get the device id from the ulp context */
2332         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
2333                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2334                 return -EINVAL;
2335         }
2336
2337         /*
2338          * Get the mapper data for dynamic mapper data such as default
2339          * ids.
2340          */
2341         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
2342                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2343         if (!parms.mapper_data) {
2344                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2345                 return -EINVAL;
2346         }
2347
2348         /* Get the action table entry from device id and act context id */
2349         parms.act_tid = cparms->act_tid;
2350
2351         /*
2352          * Perform the action table get only if act template is not zero
2353          * for act template zero like for default rules ignore the action
2354          * table processing.
2355          */
2356         if (parms.act_tid) {
2357                 parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id,
2358                                                              parms.act_tid,
2359                                                              &parms.num_atbls);
2360                 if (!parms.atbls || !parms.num_atbls) {
2361                         BNXT_TF_DBG(ERR, "No action tables for %d:%d\n",
2362                                     parms.dev_id, parms.act_tid);
2363                         return -EINVAL;
2364                 }
2365         }
2366
2367         /* Get the class table entry from device id and act context id */
2368         parms.class_tid = cparms->class_tid;
2369         parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
2370                                                     parms.class_tid,
2371                                                     &parms.num_ctbls,
2372                                                     &parms.tbl_idx);
2373         if (!parms.ctbls || !parms.num_ctbls) {
2374                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
2375                             parms.dev_id, parms.class_tid);
2376                 return -EINVAL;
2377         }
2378
2379         /* Get the device params, it will be used in later processing */
2380         parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2381         if (!parms.device_params) {
2382                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
2383                             parms.dev_id, parms.class_tid);
2384                 return -EINVAL;
2385         }
2386
2387         /* initialize the registry file for further processing */
2388         if (!ulp_regfile_init(parms.regfile)) {
2389                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
2390                 return -EINVAL;
2391         }
2392
2393         rc = ulp_regfile_write(parms.regfile,
2394                                BNXT_ULP_REGFILE_INDEX_CLASS_TID,
2395                                tfp_cpu_to_be_64((uint64_t)parms.class_tid));
2396         if (!rc) {
2397                 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
2398                 return -EINVAL;
2399         }
2400
2401         /* Allocate a Flow ID for attaching all resources for the flow to.
2402          * Once allocated, all errors have to walk the list of resources and
2403          * free each of them.
2404          */
2405         rc = ulp_flow_db_fid_alloc(ulp_ctx,
2406                                    parms.tbl_idx,
2407                                    cparms->func_id,
2408                                    &parms.fid);
2409         if (rc) {
2410                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
2411                 return rc;
2412         }
2413
2414         /* Process the action template list from the selected action table*/
2415         if (parms.act_tid) {
2416                 rc = ulp_mapper_action_tbls_process(&parms);
2417                 if (rc) {
2418                         BNXT_TF_DBG(ERR,
2419                                     "action tables failed creation for %d:%d\n",
2420                                     parms.dev_id, parms.act_tid);
2421                         goto flow_error;
2422                 }
2423         }
2424
2425         /* All good. Now process the class template */
2426         rc = ulp_mapper_class_tbls_process(&parms);
2427         if (rc) {
2428                 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n",
2429                             parms.dev_id, parms.class_tid);
2430                 goto flow_error;
2431         }
2432
2433         *flowid = parms.fid;
2434
2435         return rc;
2436
2437 flow_error:
2438         /* Free all resources that were allocated during flow creation */
2439         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
2440         if (trc)
2441                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
2442
2443         return rc;
2444 }
2445
2446 int32_t
2447 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
2448 {
2449         struct bnxt_ulp_cache_tbl_params *tbl;
2450         struct bnxt_ulp_mapper_data *data;
2451         uint32_t i;
2452         struct tf *tfp;
2453         int32_t rc, csize;
2454
2455         if (!ulp_ctx)
2456                 return -EINVAL;
2457
2458         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2459         if (!tfp)
2460                 return -EINVAL;
2461
2462         data = rte_zmalloc("ulp_mapper_data",
2463                            sizeof(struct bnxt_ulp_mapper_data), 0);
2464         if (!data) {
2465                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
2466                 return -ENOMEM;
2467         }
2468
2469         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
2470                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
2471                 /* Don't call deinit since the prof_func wasn't allocated. */
2472                 rte_free(data);
2473                 return -ENOMEM;
2474         }
2475
2476         /* Allocate the global resource ids */
2477         rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
2478         if (rc) {
2479                 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
2480                 goto error;
2481         }
2482
2483         /* Allocate the ulp cache tables. */
2484         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2485                 tbl = ulp_mapper_cache_tbl_params_get(i);
2486                 if (!tbl) {
2487                         BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)",
2488                                     i);
2489                         goto error;
2490                 }
2491                 if (tbl->num_entries != 0) {
2492                         csize = sizeof(struct bnxt_ulp_mapper_cache_entry) *
2493                                 tbl->num_entries;
2494                         data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl",
2495                                                          csize, 0);
2496                         if (!data->cache_tbl[i]) {
2497                                 BNXT_TF_DBG(ERR, "Failed to allocate Cache "
2498                                             "table %d.\n", i);
2499                                 rc = -ENOMEM;
2500                                 goto error;
2501                         }
2502                 }
2503         }
2504
2505         rc = ulp_mapper_glb_template_table_init(ulp_ctx);
2506         if (rc) {
2507                 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
2508                 goto error;
2509         }
2510
2511         return 0;
2512 error:
2513         /* Ignore the return code in favor of returning the original error. */
2514         ulp_mapper_deinit(ulp_ctx);
2515         return rc;
2516 }
2517
2518 void
2519 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
2520 {
2521         struct bnxt_ulp_mapper_data *data;
2522         uint32_t i;
2523         struct tf *tfp;
2524
2525         if (!ulp_ctx) {
2526                 BNXT_TF_DBG(ERR,
2527                             "Failed to acquire ulp context, so data may "
2528                             "not be released.\n");
2529                 return;
2530         }
2531
2532         data = (struct bnxt_ulp_mapper_data *)
2533                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2534         if (!data) {
2535                 /* Go ahead and return since there is no allocated data. */
2536                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
2537                 return;
2538         }
2539
2540         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2541         if (!tfp) {
2542                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
2543                 /* Free the mapper data regardless of errors. */
2544                 goto free_mapper_data;
2545         }
2546
2547         /* Free the global resource info table entries */
2548         ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
2549
2550 free_mapper_data:
2551         /* Free the ulp cache tables */
2552         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2553                 rte_free(data->cache_tbl[i]);
2554                 data->cache_tbl[i] = NULL;
2555         }
2556
2557         rte_free(data);
2558         /* Reset the data pointer within the ulp_ctx. */
2559         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
2560 }