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