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