net/bnxt: add resource subtype to class and action tables
[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->resource_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->resource_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->resource_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->resource_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->resource_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->resource_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->resource_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->resource_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_flow_db_res_params   fid_parms = { 0 };
1290         struct tf_insert_em_entry_parms iparms = { 0 };
1291         struct tf_delete_em_entry_parms free_parms = { 0 };
1292         int32_t trc;
1293         int32_t rc = 0;
1294
1295         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1296         if (!kflds || !num_kflds) {
1297                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1298                 return -EINVAL;
1299         }
1300
1301         /* Initialize the key/result blobs */
1302         if (!ulp_blob_init(&key, tbl->blob_key_bit_size, parms->order) ||
1303             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1304                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1305                 return -EINVAL;
1306         }
1307
1308         /* create the key */
1309         for (i = 0; i < num_kflds; i++) {
1310                 /* Setup the key */
1311                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1312                                                       &kflds[i],
1313                                                       &key, 1, "EM Key");
1314                 if (rc) {
1315                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1316                         return rc;
1317                 }
1318         }
1319
1320         /*
1321          * TBD: Normally should process identifiers in case of using recycle or
1322          * loopback.  Not supporting recycle for now.
1323          */
1324
1325         /* Create the result data blob */
1326         dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
1327         if (!dflds || !num_dflds) {
1328                 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1329                 return -EINVAL;
1330         }
1331
1332         for (i = 0; i < num_dflds; i++) {
1333                 struct bnxt_ulp_mapper_result_field_info *fld;
1334
1335                 fld = &dflds[i];
1336
1337                 rc = ulp_mapper_result_field_process(parms,
1338                                                      tbl->direction,
1339                                                      fld,
1340                                                      &data,
1341                                                      "EM Result");
1342                 if (rc) {
1343                         BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
1344                         return rc;
1345                 }
1346         }
1347
1348         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1349                                              &iparms.tbl_scope_id);
1350         if (rc) {
1351                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1352                 return rc;
1353         }
1354
1355         /*
1356          * NOTE: the actual blob size will differ from the size in the tbl
1357          * entry due to the padding.
1358          */
1359         iparms.dup_check                = 0;
1360         iparms.dir                      = tbl->direction;
1361         iparms.mem                      = tbl->resource_type;
1362         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1363         iparms.key_sz_in_bits           = tbl->key_bit_size;
1364         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1365         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1366
1367         rc = tf_insert_em_entry(tfp, &iparms);
1368         if (rc) {
1369                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1370                 return rc;
1371         }
1372
1373         /* Link the EM resource to the flow in the flow db */
1374         memset(&fid_parms, 0, sizeof(fid_parms));
1375         fid_parms.direction             = tbl->direction;
1376         fid_parms.resource_func         = tbl->resource_func;
1377         fid_parms.resource_type         = tbl->resource_type;
1378         fid_parms.critical_resource     = tbl->critical_resource;
1379         fid_parms.resource_hndl         = iparms.flow_handle;
1380
1381         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1382                                       parms->tbl_idx,
1383                                       parms->fid,
1384                                       &fid_parms);
1385         if (rc) {
1386                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1387                             rc);
1388                 /* Need to free the identifier, so goto error */
1389                 goto error;
1390         }
1391
1392         return 0;
1393 error:
1394         free_parms.dir          = iparms.dir;
1395         free_parms.mem          = iparms.mem;
1396         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1397         free_parms.flow_handle  = iparms.flow_handle;
1398
1399         trc = tf_delete_em_entry(tfp, &free_parms);
1400         if (trc)
1401                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1402
1403         return rc;
1404 }
1405
1406 static int32_t
1407 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1408                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1409 {
1410         struct bnxt_ulp_mapper_result_field_info *flds;
1411         struct ulp_flow_db_res_params   fid_parms;
1412         struct ulp_blob data;
1413         uint64_t idx;
1414         uint16_t tmplen;
1415         uint32_t i, num_flds;
1416         int32_t rc = 0, trc = 0;
1417         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1418         struct tf_set_tbl_entry_parms   sparms = { 0 };
1419         struct tf_free_tbl_entry_parms  free_parms = { 0 };
1420         uint32_t tbl_scope_id;
1421         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1422
1423         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1424
1425         if (!ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1426                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1427                 return -EINVAL;
1428         }
1429
1430         flds = ulp_mapper_result_fields_get(tbl, &num_flds);
1431         if (!flds || !num_flds) {
1432                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
1433                 return -EINVAL;
1434         }
1435
1436         for (i = 0; i < num_flds; i++) {
1437                 rc = ulp_mapper_result_field_process(parms,
1438                                                      tbl->direction,
1439                                                      &flds[i],
1440                                                      &data,
1441                                                      "Indexed Result");
1442                 if (rc) {
1443                         BNXT_TF_DBG(ERR, "data field failed\n");
1444                         return rc;
1445                 }
1446         }
1447
1448         aparms.dir              = tbl->direction;
1449         aparms.type             = tbl->resource_type;
1450         aparms.search_enable    = tbl->srch_b4_alloc;
1451         aparms.result           = ulp_blob_data_get(&data, &tmplen);
1452         aparms.result_sz_in_bytes = ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1453         aparms.tbl_scope_id     = tbl_scope_id;
1454
1455         /* All failures after the alloc succeeds require a free */
1456         rc = tf_alloc_tbl_entry(tfp, &aparms);
1457         if (rc) {
1458                 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1459                             tbl->resource_type,
1460                             (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1461                             rc);
1462                 return rc;
1463         }
1464
1465         /* Always storing values in Regfile in BE */
1466         idx = tfp_cpu_to_be_64(aparms.idx);
1467         rc = ulp_regfile_write(parms->regfile, tbl->regfile_wr_idx, idx);
1468         if (!rc) {
1469                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1470                             tbl->regfile_wr_idx);
1471                 goto error;
1472         }
1473
1474         if (!tbl->srch_b4_alloc) {
1475                 sparms.dir              = tbl->direction;
1476                 sparms.type             = tbl->resource_type;
1477                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1478                 sparms.data_sz_in_bytes =
1479                         ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1480                 sparms.idx              = aparms.idx;
1481                 sparms.tbl_scope_id     = tbl_scope_id;
1482
1483                 rc = tf_set_tbl_entry(tfp, &sparms);
1484                 if (rc) {
1485                         BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1486                                     tbl->resource_type,
1487                                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1488                                     sparms.idx,
1489                                     rc);
1490
1491                         goto error;
1492                 }
1493         }
1494
1495         /* Link the resource to the flow in the flow db */
1496         memset(&fid_parms, 0, sizeof(fid_parms));
1497         fid_parms.direction     = tbl->direction;
1498         fid_parms.resource_func = tbl->resource_func;
1499         fid_parms.resource_type = tbl->resource_type;
1500         fid_parms.resource_hndl = aparms.idx;
1501         fid_parms.critical_resource     = 0;
1502
1503         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1504                                       parms->tbl_idx,
1505                                       parms->fid,
1506                                       &fid_parms);
1507         if (rc) {
1508                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1509                             rc);
1510                 goto error;
1511         }
1512
1513         return rc;
1514 error:
1515         /*
1516          * Free the allocated resource since we failed to either
1517          * write to the entry or link the flow
1518          */
1519         free_parms.dir  = tbl->direction;
1520         free_parms.type = tbl->resource_type;
1521         free_parms.idx  = aparms.idx;
1522         free_parms.tbl_scope_id = tbl_scope_id;
1523
1524         trc = tf_free_tbl_entry(tfp, &free_parms);
1525         if (trc)
1526                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1527
1528         return rc;
1529 }
1530
1531 static int32_t
1532 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1533                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1534 {
1535         struct bnxt_ulp_mapper_class_key_field_info *kflds;
1536         struct bnxt_ulp_mapper_cache_entry *cache_entry;
1537         struct bnxt_ulp_mapper_ident_info *idents;
1538         uint32_t i, num_kflds = 0, num_idents = 0;
1539         struct ulp_flow_db_res_params fid_parms;
1540         struct tf_free_identifier_parms fparms;
1541         uint16_t tmplen, tmp_ident;
1542         struct ulp_blob key;
1543         uint8_t *cache_key;
1544         uint64_t regval;
1545         uint16_t *ckey;
1546         int32_t rc;
1547
1548         /* Get the key fields list and build the key. */
1549         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1550         if (!kflds || !num_kflds) {
1551                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1552                 return -EINVAL;
1553         }
1554         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order)) {
1555                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
1556                 return -EINVAL;
1557         }
1558         for (i = 0; i < num_kflds; i++) {
1559                 /* Setup the key */
1560                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1561                                                       &kflds[i],
1562                                                       &key, 1, "Cache Key");
1563                 if (rc) {
1564                         BNXT_TF_DBG(ERR,
1565                                     "Failed to create key for Cache rc=%d\n",
1566                                     rc);
1567                         return -EINVAL;
1568                 }
1569         }
1570
1571         /*
1572          * Perform the lookup in the cache table with constructed key.  The
1573          * cache_key is a byte array of tmplen, it needs to be converted to a
1574          * index for the cache table.
1575          */
1576         cache_key = ulp_blob_data_get(&key, &tmplen);
1577         ckey = (uint16_t *)cache_key;
1578         cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx,
1579                                                  tbl->cache_tbl_id,
1580                                                  *ckey);
1581
1582         /*
1583          * Get the identifier list for processing by both the hit and miss
1584          * processing.
1585          */
1586         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1587
1588         if (!cache_entry->ref_count) {
1589                 /* Initialize the cache entry */
1590                 cache_entry->tcam_idx = 0;
1591                 cache_entry->ref_count = 0;
1592                 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++)
1593                         cache_entry->idents[i] = ULP_IDENTS_INVALID;
1594
1595                 /* Need to allocate identifiers for storing in the cache. */
1596                 for (i = 0; i < num_idents; i++) {
1597                         /*
1598                          * Since we are using the cache, the identifier does not
1599                          * get added to the flow db.  Pass in the pointer to the
1600                          * tmp_ident.
1601                          */
1602                         rc = ulp_mapper_ident_process(parms, tbl,
1603                                                       &idents[i], &tmp_ident);
1604                         if (rc)
1605                                 goto error;
1606
1607                         cache_entry->ident_types[i] = idents[i].ident_type;
1608                         cache_entry->idents[i] = tmp_ident;
1609                 }
1610
1611                 /* Tell the TCAM processor to alloc an entry */
1612                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC;
1613                 /* Store the cache key for use by the tcam process code */
1614                 parms->cache_ptr = cache_entry;
1615         } else {
1616                 /* Cache hit, get values from result. */
1617                 for (i = 0; i < num_idents; i++) {
1618                         regval = (uint64_t)cache_entry->idents[i];
1619                         if (!ulp_regfile_write(parms->regfile,
1620                                                idents[i].regfile_wr_idx,
1621                                                tfp_cpu_to_be_64(regval))) {
1622                                 BNXT_TF_DBG(ERR,
1623                                             "Failed to write to regfile\n");
1624                                 return -EINVAL;
1625                         }
1626                 }
1627                 /*
1628                  * The cached entry is being used, so let the tcam processing
1629                  * know not to process this table.
1630                  */
1631                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP;
1632         }
1633
1634         /* Made through the cache processing, increment the reference count. */
1635         cache_entry->ref_count++;
1636
1637         /* Link the cache to the flow db. */
1638         memset(&fid_parms, 0, sizeof(fid_parms));
1639         fid_parms.direction = tbl->direction;
1640         fid_parms.resource_func = tbl->resource_func;
1641
1642         /*
1643          * Cache resource type is composed of both table_type and cache_tbl_id
1644          * need to set it appropriately via setter.
1645          */
1646         ulp_mapper_cache_res_type_set(&fid_parms,
1647                                       tbl->resource_type,
1648                                       tbl->cache_tbl_id);
1649         fid_parms.resource_hndl = (uint64_t)*ckey;
1650         fid_parms.critical_resource = tbl->critical_resource;
1651         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1652                                       parms->tbl_idx,
1653                                       parms->fid,
1654                                       &fid_parms);
1655         if (rc)
1656                 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n");
1657
1658         return rc;
1659 error:
1660         /*
1661          * This error handling only gets called when the idents are being
1662          * allocated for the cache on misses.  Using the num_idents that was
1663          * previously set.
1664          */
1665         for (i = 0; i < num_idents; i++) {
1666                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
1667                         continue;
1668
1669                 fparms.dir = tbl->direction;
1670                 fparms.ident_type = idents[i].ident_type;
1671                 fparms.id = cache_entry->idents[i];
1672                 tf_free_identifier(parms->tfp, &fparms);
1673         }
1674
1675         return rc;
1676 }
1677
1678 static int32_t
1679 ulp_mapper_glb_resource_info_init(struct tf *tfp,
1680                                   struct bnxt_ulp_mapper_data *mapper_data)
1681 {
1682         struct bnxt_ulp_glb_resource_info *glb_res;
1683         uint32_t num_glb_res_ids, idx;
1684         int32_t rc = 0;
1685
1686         glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
1687         if (!glb_res || !num_glb_res_ids) {
1688                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1689                 return -EINVAL;
1690         }
1691
1692         /* Iterate the global resources and process each one */
1693         for (idx = 0; idx < num_glb_res_ids; idx++) {
1694                 switch (glb_res[idx].resource_func) {
1695                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1696                         rc = ulp_mapper_resource_ident_allocate(tfp,
1697                                                                 mapper_data,
1698                                                                 &glb_res[idx]);
1699                         break;
1700                 default:
1701                         BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
1702                                     glb_res[idx].resource_func);
1703                         break;
1704                 }
1705         }
1706         return rc;
1707 }
1708
1709 /*
1710  * Function to process the action template. Iterate through the list
1711  * action info templates and process it.
1712  */
1713 static int32_t
1714 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1715 {
1716         uint32_t        i;
1717         int32_t         rc = 0;
1718
1719         if (!parms->atbls || !parms->num_atbls) {
1720                 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
1721                             parms->dev_id, parms->act_tid);
1722                 return -EINVAL;
1723         }
1724
1725         for (i = 0; i < parms->num_atbls; i++) {
1726                 rc = ulp_mapper_action_info_process(parms, &parms->atbls[i]);
1727                 if (rc)
1728                         return rc;
1729         }
1730
1731         return rc;
1732 }
1733
1734 /* Create the classifier table entries for a flow. */
1735 static int32_t
1736 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1737 {
1738         uint32_t        i;
1739         int32_t         rc = 0;
1740
1741         if (!parms)
1742                 return -EINVAL;
1743
1744         if (!parms->ctbls || !parms->num_ctbls) {
1745                 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
1746                             parms->dev_id, parms->class_tid);
1747                 return -EINVAL;
1748         }
1749
1750         for (i = 0; i < parms->num_ctbls; i++) {
1751                 struct bnxt_ulp_mapper_class_tbl_info *tbl = &parms->ctbls[i];
1752
1753                 switch (tbl->resource_func) {
1754                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1755                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
1756                         break;
1757                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1758                         rc = ulp_mapper_em_tbl_process(parms, tbl);
1759                         break;
1760                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1761                         rc = ulp_mapper_index_tbl_process(parms, tbl);
1762                         break;
1763                 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1764                         rc = ulp_mapper_cache_tbl_process(parms, tbl);
1765                         break;
1766                 default:
1767                         BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
1768                                     tbl->resource_func);
1769                         return -EINVAL;
1770                 }
1771
1772                 if (rc) {
1773                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1774                                     tbl->resource_func);
1775                         return rc;
1776                 }
1777         }
1778
1779         return rc;
1780 }
1781
1782 static int32_t
1783 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
1784                          struct ulp_flow_db_res_params *res)
1785 {
1786         struct tf *tfp;
1787         int32_t rc = 0;
1788
1789         if (!res || !ulp) {
1790                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
1791                 return -EINVAL;
1792         }
1793
1794         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
1795         if (!tfp) {
1796                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
1797                 return -EINVAL;
1798         }
1799
1800         switch (res->resource_func) {
1801         case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1802                 rc = ulp_mapper_cache_entry_free(ulp, tfp, res);
1803                 break;
1804         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1805                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
1806                 break;
1807         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1808                 rc = ulp_mapper_eem_entry_free(ulp, tfp, res);
1809                 break;
1810         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1811                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
1812                 break;
1813         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1814                 rc = ulp_mapper_ident_free(ulp, tfp, res);
1815                 break;
1816         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
1817                 rc = ulp_mapper_mark_free(ulp, res);
1818                 break;
1819         default:
1820                 break;
1821         }
1822
1823         return rc;
1824 }
1825
1826 int32_t
1827 ulp_mapper_resources_free(struct bnxt_ulp_context       *ulp_ctx,
1828                           uint32_t fid,
1829                           enum bnxt_ulp_flow_db_tables  tbl_type)
1830 {
1831         struct ulp_flow_db_res_params   res_parms = { 0 };
1832         int32_t                         rc, trc;
1833
1834         if (!ulp_ctx) {
1835                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1836                 return -EINVAL;
1837         }
1838
1839         /*
1840          * Set the critical resource on the first resource del, then iterate
1841          * while status is good
1842          */
1843         res_parms.critical_resource = 1;
1844         rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms);
1845
1846         if (rc) {
1847                 /*
1848                  * This is unexpected on the first call to resource del.
1849                  * It likely means that the flow did not exist in the flow db.
1850                  */
1851                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
1852                             tbl_type, fid, rc);
1853                 return rc;
1854         }
1855
1856         while (!rc) {
1857                 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
1858                 if (trc)
1859                         /*
1860                          * On fail, we still need to attempt to free the
1861                          * remaining resources.  Don't return
1862                          */
1863                         BNXT_TF_DBG(ERR,
1864                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
1865                                     "] failed rc=%d.\n",
1866                                     tbl_type, fid, res_parms.resource_func,
1867                                     res_parms.resource_hndl, trc);
1868
1869                 /* All subsequent call require the critical_resource be zero */
1870                 res_parms.critical_resource = 0;
1871
1872                 rc = ulp_flow_db_resource_del(ulp_ctx,
1873                                               tbl_type,
1874                                               fid,
1875                                               &res_parms);
1876         }
1877
1878         /* Free the Flow ID since we've removed all resources */
1879         rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid);
1880
1881         return rc;
1882 }
1883
1884 static void
1885 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
1886                                     struct bnxt_ulp_mapper_data *mapper_data)
1887 {
1888         struct bnxt_ulp_mapper_glb_resource_entry *ent;
1889         struct ulp_flow_db_res_params res;
1890         uint32_t dir, idx;
1891
1892         /* Iterate the global resources and process each one */
1893         for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
1894                 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_INFO_TBL_MAX_SZ;
1895                       idx++) {
1896                         ent = &mapper_data->glb_res_tbl[dir][idx];
1897                         if (ent->resource_func ==
1898                             BNXT_ULP_RESOURCE_FUNC_INVALID)
1899                                 continue;
1900                         memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
1901                         res.resource_func = ent->resource_func;
1902                         res.direction = dir;
1903                         res.resource_type = ent->resource_type;
1904                         res.resource_hndl = ent->resource_hndl;
1905                         ulp_mapper_resource_free(ulp_ctx, &res);
1906                 }
1907         }
1908 }
1909
1910 int32_t
1911 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
1912 {
1913         if (!ulp_ctx) {
1914                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1915                 return -EINVAL;
1916         }
1917
1918         return ulp_mapper_resources_free(ulp_ctx,
1919                                          fid,
1920                                          BNXT_ULP_REGULAR_FLOW_TABLE);
1921 }
1922
1923 /* Function to handle the mapping of the Flow to be compatible
1924  * with the underlying hardware.
1925  */
1926 int32_t
1927 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
1928                        struct bnxt_ulp_mapper_create_parms *cparms,
1929                        uint32_t *flowid)
1930 {
1931         struct bnxt_ulp_device_params *device_params;
1932         struct bnxt_ulp_mapper_parms parms;
1933         struct ulp_regfile regfile;
1934         int32_t  rc, trc;
1935
1936         if (!ulp_ctx || !cparms)
1937                 return -EINVAL;
1938
1939         /* Initialize the parms structure */
1940         memset(&parms, 0, sizeof(parms));
1941         parms.act_prop = cparms->act_prop;
1942         parms.act_bitmap = cparms->act;
1943         parms.regfile = &regfile;
1944         parms.hdr_field = cparms->hdr_field;
1945         parms.comp_fld = cparms->comp_fld;
1946         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
1947         parms.ulp_ctx = ulp_ctx;
1948         parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1949
1950         /* Get the device id from the ulp context */
1951         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
1952                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
1953                 return -EINVAL;
1954         }
1955
1956         /*
1957          * Get the mapper data for dynamic mapper data such as default
1958          * ids.
1959          */
1960         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
1961                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
1962         if (!parms.mapper_data) {
1963                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
1964                 return -EINVAL;
1965         }
1966
1967         /* Get the action table entry from device id and act context id */
1968         parms.act_tid = cparms->act_tid;
1969         parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id,
1970                                                      parms.act_tid,
1971                                                      &parms.num_atbls);
1972         if (!parms.atbls || !parms.num_atbls) {
1973                 BNXT_TF_DBG(ERR, "No action tables for %d:%d\n",
1974                             parms.dev_id, parms.act_tid);
1975                 return -EINVAL;
1976         }
1977
1978         /* Get the class table entry from device id and act context id */
1979         parms.class_tid = cparms->class_tid;
1980         parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
1981                                                     parms.class_tid,
1982                                                     &parms.num_ctbls);
1983         if (!parms.ctbls || !parms.num_ctbls) {
1984                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1985                             parms.dev_id, parms.class_tid);
1986                 return -EINVAL;
1987         }
1988
1989         /* Get the byte order for the further processing from device params */
1990         device_params = bnxt_ulp_device_params_get(parms.dev_id);
1991         if (!device_params) {
1992                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1993                             parms.dev_id, parms.class_tid);
1994                 return -EINVAL;
1995         }
1996         parms.order = device_params->byte_order;
1997         parms.encap_byte_swap = device_params->encap_byte_swap;
1998
1999         /* initialize the registry file for further processing */
2000         if (!ulp_regfile_init(parms.regfile)) {
2001                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
2002                 return -EINVAL;
2003         }
2004
2005         rc = ulp_regfile_write(parms.regfile,
2006                                BNXT_ULP_REGFILE_INDEX_CLASS_TID,
2007                                tfp_cpu_to_be_64((uint64_t)parms.class_tid));
2008         if (!rc) {
2009                 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
2010                 return -EINVAL;
2011         }
2012
2013         /* Allocate a Flow ID for attaching all resources for the flow to.
2014          * Once allocated, all errors have to walk the list of resources and
2015          * free each of them.
2016          */
2017         rc = ulp_flow_db_fid_alloc(ulp_ctx,
2018                                    BNXT_ULP_REGULAR_FLOW_TABLE,
2019                                    cparms->func_id,
2020                                    &parms.fid);
2021         if (rc) {
2022                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
2023                 return rc;
2024         }
2025
2026         /* Process the action template list from the selected action table*/
2027         rc = ulp_mapper_action_tbls_process(&parms);
2028         if (rc) {
2029                 BNXT_TF_DBG(ERR, "action tables failed creation for %d:%d\n",
2030                             parms.dev_id, parms.act_tid);
2031                 goto flow_error;
2032         }
2033
2034         /* All good. Now process the class template */
2035         rc = ulp_mapper_class_tbls_process(&parms);
2036         if (rc) {
2037                 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n",
2038                             parms.dev_id, parms.class_tid);
2039                 goto flow_error;
2040         }
2041
2042         *flowid = parms.fid;
2043
2044         return rc;
2045
2046 flow_error:
2047         /* Free all resources that were allocated during flow creation */
2048         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
2049         if (trc)
2050                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
2051
2052         return rc;
2053 }
2054
2055 int32_t
2056 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
2057 {
2058         struct bnxt_ulp_cache_tbl_params *tbl;
2059         struct bnxt_ulp_mapper_data *data;
2060         uint32_t i;
2061         struct tf *tfp;
2062         int32_t rc, csize;
2063
2064         if (!ulp_ctx)
2065                 return -EINVAL;
2066
2067         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2068         if (!tfp)
2069                 return -EINVAL;
2070
2071         data = rte_zmalloc("ulp_mapper_data",
2072                            sizeof(struct bnxt_ulp_mapper_data), 0);
2073         if (!data) {
2074                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
2075                 return -ENOMEM;
2076         }
2077
2078         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
2079                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
2080                 /* Don't call deinit since the prof_func wasn't allocated. */
2081                 rte_free(data);
2082                 return -ENOMEM;
2083         }
2084
2085         /* Allocate the global resource ids */
2086         rc = ulp_mapper_glb_resource_info_init(tfp, data);
2087         if (rc) {
2088                 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
2089                 goto error;
2090         }
2091
2092         /* Allocate the ulp cache tables. */
2093         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2094                 tbl = ulp_mapper_cache_tbl_params_get(i);
2095                 if (!tbl) {
2096                         BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)",
2097                                     i);
2098                         goto error;
2099                 }
2100                 if (tbl->num_entries != 0) {
2101                         csize = sizeof(struct bnxt_ulp_mapper_cache_entry) *
2102                                 tbl->num_entries;
2103                         data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl",
2104                                                          csize, 0);
2105                         if (!data->cache_tbl[i]) {
2106                                 BNXT_TF_DBG(ERR, "Failed to allocate Cache "
2107                                             "table %d.\n", i);
2108                                 rc = -ENOMEM;
2109                                 goto error;
2110                         }
2111                 }
2112         }
2113
2114         return 0;
2115 error:
2116         /* Ignore the return code in favor of returning the original error. */
2117         ulp_mapper_deinit(ulp_ctx);
2118         return rc;
2119 }
2120
2121 void
2122 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
2123 {
2124         struct bnxt_ulp_mapper_data *data;
2125         uint32_t i;
2126         struct tf *tfp;
2127
2128         if (!ulp_ctx) {
2129                 BNXT_TF_DBG(ERR,
2130                             "Failed to acquire ulp context, so data may "
2131                             "not be released.\n");
2132                 return;
2133         }
2134
2135         data = (struct bnxt_ulp_mapper_data *)
2136                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2137         if (!data) {
2138                 /* Go ahead and return since there is no allocated data. */
2139                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
2140                 return;
2141         }
2142
2143         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2144         if (!tfp) {
2145                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
2146                 /* Free the mapper data regardless of errors. */
2147                 goto free_mapper_data;
2148         }
2149
2150         /* Free the global resource info table entries */
2151         ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
2152
2153 free_mapper_data:
2154         /* Free the ulp cache tables */
2155         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2156                 rte_free(data->cache_tbl[i]);
2157                 data->cache_tbl[i] = NULL;
2158         }
2159
2160         rte_free(data);
2161         /* Reset the data pointer within the ulp_ctx. */
2162         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
2163 }