net/bnxt: support IF table processing
[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;
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         /* Perform the tf table allocation by filling the alloc params */
1520         aparms.dir              = tbl->direction;
1521         aparms.type             = tbl->resource_type;
1522         aparms.search_enable    = tbl->srch_b4_alloc;
1523         aparms.result           = ulp_blob_data_get(&data, &tmplen);
1524         aparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1525         aparms.tbl_scope_id     = tbl_scope_id;
1526
1527         /* All failures after the alloc succeeds require a free */
1528         rc = tf_alloc_tbl_entry(tfp, &aparms);
1529         if (rc) {
1530                 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1531                             aparms.type,
1532                             (aparms.dir == TF_DIR_RX) ? "RX" : "TX",
1533                             rc);
1534                 return rc;
1535         }
1536
1537         /*
1538          * calculate the idx for the result record, for external EM the offset
1539          * needs to be shifted accordingly. If external non-inline table types
1540          * are used then need to revisit this logic.
1541          */
1542         if (aparms.type == TF_TBL_TYPE_EXT)
1543                 idx = TF_ACT_REC_OFFSET_2_PTR(aparms.idx);
1544         else
1545                 idx = aparms.idx;
1546
1547         /* Always storing values in Regfile in BE */
1548         idx = tfp_cpu_to_be_64(idx);
1549         rc = ulp_regfile_write(parms->regfile, tbl->regfile_idx, idx);
1550         if (!rc) {
1551                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1552                             tbl->regfile_idx);
1553                 goto error;
1554         }
1555
1556         /* Perform the tf table set by filling the set params */
1557         if (!tbl->srch_b4_alloc || !aparms.hit) {
1558                 sparms.dir              = tbl->direction;
1559                 sparms.type             = tbl->resource_type;
1560                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1561                 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1562                 sparms.idx              = aparms.idx;
1563                 sparms.tbl_scope_id     = tbl_scope_id;
1564
1565                 rc = tf_set_tbl_entry(tfp, &sparms);
1566                 if (rc) {
1567                         BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1568                                     sparms.type,
1569                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
1570                                     sparms.idx,
1571                                     rc);
1572                         goto error;
1573                 }
1574         }
1575
1576         /* Link the resource to the flow in the flow db */
1577         memset(&fid_parms, 0, sizeof(fid_parms));
1578         fid_parms.direction     = tbl->direction;
1579         fid_parms.resource_func = tbl->resource_func;
1580         fid_parms.resource_type = tbl->resource_type;
1581         fid_parms.resource_hndl = aparms.idx;
1582         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1583
1584         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1585                                       parms->tbl_idx,
1586                                       parms->fid,
1587                                       &fid_parms);
1588         if (rc) {
1589                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1590                             rc);
1591                 goto error;
1592         }
1593
1594         /* Perform the VF rep action */
1595         rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
1596         if (rc) {
1597                 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
1598                 goto error;
1599         }
1600         return rc;
1601 error:
1602         /*
1603          * Free the allocated resource since we failed to either
1604          * write to the entry or link the flow
1605          */
1606         free_parms.dir  = tbl->direction;
1607         free_parms.type = tbl->resource_type;
1608         free_parms.idx  = aparms.idx;
1609         free_parms.tbl_scope_id = tbl_scope_id;
1610
1611         trc = tf_free_tbl_entry(tfp, &free_parms);
1612         if (trc)
1613                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1614
1615         return rc;
1616 }
1617
1618 static int32_t
1619 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1620                              struct bnxt_ulp_mapper_tbl_info *tbl)
1621 {
1622         struct bnxt_ulp_mapper_class_key_field_info *kflds;
1623         struct bnxt_ulp_mapper_cache_entry *cache_entry;
1624         struct bnxt_ulp_mapper_ident_info *idents;
1625         uint32_t i, num_kflds = 0, num_idents = 0;
1626         struct ulp_flow_db_res_params fid_parms;
1627         struct tf_free_identifier_parms fparms;
1628         uint16_t tmplen, tmp_ident;
1629         struct ulp_blob key;
1630         uint8_t *cache_key;
1631         uint64_t regval;
1632         uint16_t *ckey;
1633         int32_t rc;
1634
1635         /* Get the key fields list and build the key. */
1636         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1637         if (!kflds || !num_kflds) {
1638                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1639                 return -EINVAL;
1640         }
1641         if (!ulp_blob_init(&key, tbl->key_bit_size,
1642                            parms->device_params->byte_order)) {
1643                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
1644                 return -EINVAL;
1645         }
1646         for (i = 0; i < num_kflds; i++) {
1647                 /* Setup the key */
1648                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1649                                                       &kflds[i],
1650                                                       &key, 1, "Cache Key");
1651                 if (rc) {
1652                         BNXT_TF_DBG(ERR,
1653                                     "Failed to create key for Cache rc=%d\n",
1654                                     rc);
1655                         return -EINVAL;
1656                 }
1657         }
1658
1659         /*
1660          * Perform the lookup in the cache table with constructed key.  The
1661          * cache_key is a byte array of tmplen, it needs to be converted to a
1662          * index for the cache table.
1663          */
1664         cache_key = ulp_blob_data_get(&key, &tmplen);
1665         ckey = (uint16_t *)cache_key;
1666
1667         /*
1668          * The id computed based on resource sub type and direction where
1669          * dir is the bit0 and rest of the bits come from resource
1670          * sub type.
1671          */
1672         cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx,
1673                                                  (tbl->resource_sub_type << 1 |
1674                                                  (tbl->direction & 0x1)),
1675                                                  *ckey);
1676
1677         /*
1678          * Get the identifier list for processing by both the hit and miss
1679          * processing.
1680          */
1681         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1682
1683         if (!cache_entry->ref_count) {
1684                 /* Initialize the cache entry */
1685                 cache_entry->tcam_idx = 0;
1686                 cache_entry->ref_count = 0;
1687                 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++)
1688                         cache_entry->idents[i] = ULP_IDENTS_INVALID;
1689
1690                 /* Need to allocate identifiers for storing in the cache. */
1691                 for (i = 0; i < num_idents; i++) {
1692                         /*
1693                          * Since we are using the cache, the identifier does not
1694                          * get added to the flow db.  Pass in the pointer to the
1695                          * tmp_ident.
1696                          */
1697                         rc = ulp_mapper_ident_process(parms, tbl,
1698                                                       &idents[i], &tmp_ident);
1699                         if (rc)
1700                                 goto error;
1701
1702                         cache_entry->ident_types[i] = idents[i].ident_type;
1703                         cache_entry->idents[i] = tmp_ident;
1704                 }
1705
1706                 /* Tell the TCAM processor to alloc an entry */
1707                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC;
1708                 /* Store the cache key for use by the tcam process code */
1709                 parms->cache_ptr = cache_entry;
1710         } else {
1711                 /* Cache hit, get values from result. */
1712                 for (i = 0; i < num_idents; i++) {
1713                         regval = (uint64_t)cache_entry->idents[i];
1714                         if (!ulp_regfile_write(parms->regfile,
1715                                                idents[i].regfile_idx,
1716                                                tfp_cpu_to_be_64(regval))) {
1717                                 BNXT_TF_DBG(ERR,
1718                                             "Failed to write to regfile\n");
1719                                 return -EINVAL;
1720                         }
1721                 }
1722                 /*
1723                  * The cached entry is being used, so let the tcam processing
1724                  * know not to process this table.
1725                  */
1726                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP;
1727         }
1728
1729         /* Made through the cache processing, increment the reference count. */
1730         cache_entry->ref_count++;
1731
1732         /* Link the cache to the flow db. */
1733         memset(&fid_parms, 0, sizeof(fid_parms));
1734         fid_parms.direction = tbl->direction;
1735         fid_parms.resource_func = tbl->resource_func;
1736
1737         /*
1738          * Cache resource type is composed of table_type, resource
1739          * sub type and direction, it needs to set appropriately via setter.
1740          */
1741         ulp_mapper_cache_res_type_set(&fid_parms,
1742                                       tbl->resource_type,
1743                                       (tbl->resource_sub_type << 1 |
1744                                        (tbl->direction & 0x1)));
1745         fid_parms.resource_hndl = (uint64_t)*ckey;
1746         fid_parms.critical_resource = tbl->critical_resource;
1747         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1748                                       parms->tbl_idx,
1749                                       parms->fid,
1750                                       &fid_parms);
1751         if (rc)
1752                 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n");
1753
1754         return rc;
1755 error:
1756         /*
1757          * This error handling only gets called when the idents are being
1758          * allocated for the cache on misses.  Using the num_idents that was
1759          * previously set.
1760          */
1761         for (i = 0; i < num_idents; i++) {
1762                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
1763                         continue;
1764
1765                 fparms.dir = tbl->direction;
1766                 fparms.ident_type = idents[i].ident_type;
1767                 fparms.id = cache_entry->idents[i];
1768                 tf_free_identifier(parms->tfp, &fparms);
1769         }
1770
1771         return rc;
1772 }
1773
1774 static int32_t
1775 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1776                           struct bnxt_ulp_mapper_tbl_info *tbl)
1777 {
1778         struct bnxt_ulp_mapper_result_field_info *flds;
1779         struct ulp_blob data;
1780         uint64_t idx;
1781         uint16_t tmplen;
1782         uint32_t i, num_flds;
1783         int32_t rc = 0;
1784         struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
1785         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1786         uint32_t encap_flds;
1787
1788         /* Initialize the blob data */
1789         if (!ulp_blob_init(&data, tbl->result_bit_size,
1790                            parms->device_params->byte_order)) {
1791                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1792                 return -EINVAL;
1793         }
1794
1795         /* Get the result fields list */
1796         flds = ulp_mapper_result_fields_get(tbl, &num_flds, &encap_flds);
1797
1798         if (!flds || !num_flds || encap_flds) {
1799                 BNXT_TF_DBG(ERR, "template undefined for the IF table\n");
1800                 return -EINVAL;
1801         }
1802
1803         /* process the result fields, loop through them */
1804         for (i = 0; i < num_flds; i++) {
1805                 /* Process the result fields */
1806                 rc = ulp_mapper_result_field_process(parms,
1807                                                      tbl->direction,
1808                                                      &flds[i],
1809                                                      &data,
1810                                                      "IFtable Result");
1811                 if (rc) {
1812                         BNXT_TF_DBG(ERR, "data field failed\n");
1813                         return rc;
1814                 }
1815         }
1816
1817         /* Get the index details from computed field */
1818         idx = ULP_COMP_FLD_IDX_RD(parms, tbl->comp_field_idx);
1819
1820         /* Perform the tf table set by filling the set params */
1821         iftbl_params.dir = tbl->direction;
1822         iftbl_params.type = tbl->resource_type;
1823         iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
1824         iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1825         iftbl_params.idx = idx;
1826
1827         rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
1828         if (rc) {
1829                 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1830                             iftbl_params.type,
1831                             (iftbl_params.dir == TF_DIR_RX) ? "RX" : "TX",
1832                             iftbl_params.idx,
1833                             rc);
1834                 return rc;
1835         }
1836
1837         /*
1838          * TBD: Need to look at the need to store idx in flow db for restore
1839          * the table to its original state on deletion of this entry.
1840          */
1841         return rc;
1842 }
1843
1844 static int32_t
1845 ulp_mapper_glb_resource_info_init(struct tf *tfp,
1846                                   struct bnxt_ulp_mapper_data *mapper_data)
1847 {
1848         struct bnxt_ulp_glb_resource_info *glb_res;
1849         uint32_t num_glb_res_ids, idx;
1850         int32_t rc = 0;
1851
1852         glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
1853         if (!glb_res || !num_glb_res_ids) {
1854                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1855                 return -EINVAL;
1856         }
1857
1858         /* Iterate the global resources and process each one */
1859         for (idx = 0; idx < num_glb_res_ids; idx++) {
1860                 switch (glb_res[idx].resource_func) {
1861                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1862                         rc = ulp_mapper_resource_ident_allocate(tfp,
1863                                                                 mapper_data,
1864                                                                 &glb_res[idx]);
1865                         break;
1866                 default:
1867                         BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
1868                                     glb_res[idx].resource_func);
1869                         break;
1870                 }
1871         }
1872         return rc;
1873 }
1874
1875 /*
1876  * Function to process the action template. Iterate through the list
1877  * action info templates and process it.
1878  */
1879 static int32_t
1880 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1881 {
1882         uint32_t        i;
1883         int32_t         rc = 0;
1884         struct bnxt_ulp_mapper_tbl_info *tbl;
1885
1886         if (!parms->atbls || !parms->num_atbls) {
1887                 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
1888                             parms->dev_id, parms->act_tid);
1889                 return -EINVAL;
1890         }
1891
1892         for (i = 0; i < parms->num_atbls; i++) {
1893                 tbl = &parms->atbls[i];
1894                 switch (tbl->resource_func) {
1895                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1896                         rc = ulp_mapper_index_tbl_process(parms, tbl, false);
1897                         if (rc) {
1898                                 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1899                                             tbl->resource_func);
1900                                 return rc;
1901                         }
1902                         break;
1903                 default:
1904                         BNXT_TF_DBG(ERR, "Unexpected action resource %d\n",
1905                                     tbl->resource_func);
1906                         return -EINVAL;
1907                 }
1908         }
1909
1910         return rc;
1911 }
1912
1913 /* Create the classifier table entries for a flow. */
1914 static int32_t
1915 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1916 {
1917         uint32_t        i;
1918         int32_t         rc = 0;
1919
1920         if (!parms)
1921                 return -EINVAL;
1922
1923         if (!parms->ctbls || !parms->num_ctbls) {
1924                 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
1925                             parms->dev_id, parms->class_tid);
1926                 return -EINVAL;
1927         }
1928
1929         for (i = 0; i < parms->num_ctbls; i++) {
1930                 struct bnxt_ulp_mapper_tbl_info *tbl = &parms->ctbls[i];
1931
1932                 switch (tbl->resource_func) {
1933                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1934                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
1935                         break;
1936                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1937                         rc = ulp_mapper_em_tbl_process(parms, tbl);
1938                         break;
1939                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1940                         rc = ulp_mapper_index_tbl_process(parms, tbl, true);
1941                         break;
1942                 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1943                         rc = ulp_mapper_cache_tbl_process(parms, tbl);
1944                         break;
1945                 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
1946                         rc = ulp_mapper_if_tbl_process(parms, tbl);
1947                         break;
1948                 default:
1949                         BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
1950                                     tbl->resource_func);
1951                         return -EINVAL;
1952                 }
1953
1954                 if (rc) {
1955                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1956                                     tbl->resource_func);
1957                         return rc;
1958                 }
1959         }
1960
1961         return rc;
1962 }
1963
1964 static int32_t
1965 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
1966                          struct ulp_flow_db_res_params *res)
1967 {
1968         struct tf *tfp;
1969         int32_t rc = 0;
1970
1971         if (!res || !ulp) {
1972                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
1973                 return -EINVAL;
1974         }
1975
1976         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
1977         if (!tfp) {
1978                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
1979                 return -EINVAL;
1980         }
1981
1982         switch (res->resource_func) {
1983         case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1984                 rc = ulp_mapper_cache_entry_free(ulp, tfp, res);
1985                 break;
1986         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1987                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
1988                 break;
1989         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1990                 rc = ulp_mapper_eem_entry_free(ulp, tfp, res);
1991                 break;
1992         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1993                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
1994                 break;
1995         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1996                 rc = ulp_mapper_ident_free(ulp, tfp, res);
1997                 break;
1998         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
1999                 rc = ulp_mapper_mark_free(ulp, res);
2000                 break;
2001         default:
2002                 break;
2003         }
2004
2005         return rc;
2006 }
2007
2008 int32_t
2009 ulp_mapper_resources_free(struct bnxt_ulp_context       *ulp_ctx,
2010                           uint32_t fid,
2011                           enum bnxt_ulp_flow_db_tables  tbl_type)
2012 {
2013         struct ulp_flow_db_res_params   res_parms = { 0 };
2014         int32_t                         rc, trc;
2015
2016         if (!ulp_ctx) {
2017                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2018                 return -EINVAL;
2019         }
2020
2021         /*
2022          * Set the critical resource on the first resource del, then iterate
2023          * while status is good
2024          */
2025         res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
2026         rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms);
2027
2028         if (rc) {
2029                 /*
2030                  * This is unexpected on the first call to resource del.
2031                  * It likely means that the flow did not exist in the flow db.
2032                  */
2033                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
2034                             tbl_type, fid, rc);
2035                 return rc;
2036         }
2037
2038         while (!rc) {
2039                 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
2040                 if (trc)
2041                         /*
2042                          * On fail, we still need to attempt to free the
2043                          * remaining resources.  Don't return
2044                          */
2045                         BNXT_TF_DBG(ERR,
2046                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
2047                                     "] failed rc=%d.\n",
2048                                     tbl_type, fid, res_parms.resource_func,
2049                                     res_parms.resource_hndl, trc);
2050
2051                 /* All subsequent call require the non-critical_resource */
2052                 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2053
2054                 rc = ulp_flow_db_resource_del(ulp_ctx,
2055                                               tbl_type,
2056                                               fid,
2057                                               &res_parms);
2058         }
2059
2060         /* Free the Flow ID since we've removed all resources */
2061         rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid);
2062
2063         return rc;
2064 }
2065
2066 static void
2067 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
2068                                     struct bnxt_ulp_mapper_data *mapper_data)
2069 {
2070         struct bnxt_ulp_mapper_glb_resource_entry *ent;
2071         struct ulp_flow_db_res_params res;
2072         uint32_t dir, idx;
2073
2074         /* Iterate the global resources and process each one */
2075         for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
2076                 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_INFO_TBL_MAX_SZ;
2077                       idx++) {
2078                         ent = &mapper_data->glb_res_tbl[dir][idx];
2079                         if (ent->resource_func ==
2080                             BNXT_ULP_RESOURCE_FUNC_INVALID)
2081                                 continue;
2082                         memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
2083                         res.resource_func = ent->resource_func;
2084                         res.direction = dir;
2085                         res.resource_type = ent->resource_type;
2086                         res.resource_hndl = ent->resource_hndl;
2087                         ulp_mapper_resource_free(ulp_ctx, &res);
2088                 }
2089         }
2090 }
2091
2092 int32_t
2093 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
2094 {
2095         if (!ulp_ctx) {
2096                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2097                 return -EINVAL;
2098         }
2099
2100         return ulp_mapper_resources_free(ulp_ctx,
2101                                          fid,
2102                                          BNXT_ULP_REGULAR_FLOW_TABLE);
2103 }
2104
2105 /* Function to handle the mapping of the Flow to be compatible
2106  * with the underlying hardware.
2107  */
2108 int32_t
2109 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
2110                        struct bnxt_ulp_mapper_create_parms *cparms,
2111                        uint32_t *flowid)
2112 {
2113         struct bnxt_ulp_mapper_parms parms;
2114         struct ulp_regfile regfile;
2115         int32_t  rc, trc;
2116
2117         if (!ulp_ctx || !cparms)
2118                 return -EINVAL;
2119
2120         /* Initialize the parms structure */
2121         memset(&parms, 0, sizeof(parms));
2122         parms.act_prop = cparms->act_prop;
2123         parms.act_bitmap = cparms->act;
2124         parms.regfile = &regfile;
2125         parms.hdr_field = cparms->hdr_field;
2126         parms.comp_fld = cparms->comp_fld;
2127         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2128         parms.ulp_ctx = ulp_ctx;
2129         parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
2130
2131         /* Get the device id from the ulp context */
2132         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
2133                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2134                 return -EINVAL;
2135         }
2136
2137         /*
2138          * Get the mapper data for dynamic mapper data such as default
2139          * ids.
2140          */
2141         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
2142                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2143         if (!parms.mapper_data) {
2144                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2145                 return -EINVAL;
2146         }
2147
2148         /* Get the action table entry from device id and act context id */
2149         parms.act_tid = cparms->act_tid;
2150
2151         /*
2152          * Perform the action table get only if act template is not zero
2153          * for act template zero like for default rules ignore the action
2154          * table processing.
2155          */
2156         if (parms.act_tid) {
2157                 parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id,
2158                                                              parms.act_tid,
2159                                                              &parms.num_atbls);
2160                 if (!parms.atbls || !parms.num_atbls) {
2161                         BNXT_TF_DBG(ERR, "No action tables for %d:%d\n",
2162                                     parms.dev_id, parms.act_tid);
2163                         return -EINVAL;
2164                 }
2165         }
2166
2167         /* Get the class table entry from device id and act context id */
2168         parms.class_tid = cparms->class_tid;
2169         parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
2170                                                     parms.class_tid,
2171                                                     &parms.num_ctbls,
2172                                                     &parms.tbl_idx);
2173         if (!parms.ctbls || !parms.num_ctbls) {
2174                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
2175                             parms.dev_id, parms.class_tid);
2176                 return -EINVAL;
2177         }
2178
2179         /* Get the device params, it will be used in later processing */
2180         parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2181         if (!parms.device_params) {
2182                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
2183                             parms.dev_id, parms.class_tid);
2184                 return -EINVAL;
2185         }
2186
2187         /* initialize the registry file for further processing */
2188         if (!ulp_regfile_init(parms.regfile)) {
2189                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
2190                 return -EINVAL;
2191         }
2192
2193         rc = ulp_regfile_write(parms.regfile,
2194                                BNXT_ULP_REGFILE_INDEX_CLASS_TID,
2195                                tfp_cpu_to_be_64((uint64_t)parms.class_tid));
2196         if (!rc) {
2197                 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
2198                 return -EINVAL;
2199         }
2200
2201         /* Allocate a Flow ID for attaching all resources for the flow to.
2202          * Once allocated, all errors have to walk the list of resources and
2203          * free each of them.
2204          */
2205         rc = ulp_flow_db_fid_alloc(ulp_ctx,
2206                                    parms.tbl_idx,
2207                                    cparms->func_id,
2208                                    &parms.fid);
2209         if (rc) {
2210                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
2211                 return rc;
2212         }
2213
2214         /* Process the action template list from the selected action table*/
2215         if (parms.act_tid) {
2216                 rc = ulp_mapper_action_tbls_process(&parms);
2217                 if (rc) {
2218                         BNXT_TF_DBG(ERR,
2219                                     "action tables failed creation for %d:%d\n",
2220                                     parms.dev_id, parms.act_tid);
2221                         goto flow_error;
2222                 }
2223         }
2224
2225         /* All good. Now process the class template */
2226         rc = ulp_mapper_class_tbls_process(&parms);
2227         if (rc) {
2228                 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n",
2229                             parms.dev_id, parms.class_tid);
2230                 goto flow_error;
2231         }
2232
2233         *flowid = parms.fid;
2234
2235         return rc;
2236
2237 flow_error:
2238         /* Free all resources that were allocated during flow creation */
2239         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
2240         if (trc)
2241                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
2242
2243         return rc;
2244 }
2245
2246 int32_t
2247 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
2248 {
2249         struct bnxt_ulp_cache_tbl_params *tbl;
2250         struct bnxt_ulp_mapper_data *data;
2251         uint32_t i;
2252         struct tf *tfp;
2253         int32_t rc, csize;
2254
2255         if (!ulp_ctx)
2256                 return -EINVAL;
2257
2258         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2259         if (!tfp)
2260                 return -EINVAL;
2261
2262         data = rte_zmalloc("ulp_mapper_data",
2263                            sizeof(struct bnxt_ulp_mapper_data), 0);
2264         if (!data) {
2265                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
2266                 return -ENOMEM;
2267         }
2268
2269         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
2270                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
2271                 /* Don't call deinit since the prof_func wasn't allocated. */
2272                 rte_free(data);
2273                 return -ENOMEM;
2274         }
2275
2276         /* Allocate the global resource ids */
2277         rc = ulp_mapper_glb_resource_info_init(tfp, data);
2278         if (rc) {
2279                 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
2280                 goto error;
2281         }
2282
2283         /* Allocate the ulp cache tables. */
2284         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2285                 tbl = ulp_mapper_cache_tbl_params_get(i);
2286                 if (!tbl) {
2287                         BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)",
2288                                     i);
2289                         goto error;
2290                 }
2291                 if (tbl->num_entries != 0) {
2292                         csize = sizeof(struct bnxt_ulp_mapper_cache_entry) *
2293                                 tbl->num_entries;
2294                         data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl",
2295                                                          csize, 0);
2296                         if (!data->cache_tbl[i]) {
2297                                 BNXT_TF_DBG(ERR, "Failed to allocate Cache "
2298                                             "table %d.\n", i);
2299                                 rc = -ENOMEM;
2300                                 goto error;
2301                         }
2302                 }
2303         }
2304
2305         return 0;
2306 error:
2307         /* Ignore the return code in favor of returning the original error. */
2308         ulp_mapper_deinit(ulp_ctx);
2309         return rc;
2310 }
2311
2312 void
2313 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
2314 {
2315         struct bnxt_ulp_mapper_data *data;
2316         uint32_t i;
2317         struct tf *tfp;
2318
2319         if (!ulp_ctx) {
2320                 BNXT_TF_DBG(ERR,
2321                             "Failed to acquire ulp context, so data may "
2322                             "not be released.\n");
2323                 return;
2324         }
2325
2326         data = (struct bnxt_ulp_mapper_data *)
2327                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2328         if (!data) {
2329                 /* Go ahead and return since there is no allocated data. */
2330                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
2331                 return;
2332         }
2333
2334         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2335         if (!tfp) {
2336                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
2337                 /* Free the mapper data regardless of errors. */
2338                 goto free_mapper_data;
2339         }
2340
2341         /* Free the global resource info table entries */
2342         ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
2343
2344 free_mapper_data:
2345         /* Free the ulp cache tables */
2346         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2347                 rte_free(data->cache_tbl[i]);
2348                 data->cache_tbl[i] = NULL;
2349         }
2350
2351         rte_free(data);
2352         /* Reset the data pointer within the ulp_ctx. */
2353         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
2354 }