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