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