net/bnxt: support alloc and program key and act 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 "bnxt.h"
8 #include "ulp_template_db.h"
9 #include "ulp_template_struct.h"
10 #include "bnxt_tf_common.h"
11 #include "ulp_utils.h"
12 #include "bnxt_ulp.h"
13 #include "tfp.h"
14 #include "tf_ext_flow_handle.h"
15 #include "ulp_mark_mgr.h"
16 #include "ulp_flow_db.h"
17 #include "ulp_mapper.h"
18
19 /*
20  * Get the size of the action property for a given index.
21  *
22  * idx [in] The index for the action property
23  *
24  * returns the size of the action property.
25  */
26 static uint32_t
27 ulp_mapper_act_prop_size_get(uint32_t idx)
28 {
29         if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
30                 return 0;
31         return ulp_act_prop_map_table[idx];
32 }
33
34 /*
35  * Get the list of result fields that implement the flow action.
36  * Gets a device dependent list of tables that implement the action template id.
37  *
38  * dev_id [in] The device id of the forwarding element
39  *
40  * tid [in] The action template id that matches the flow
41  *
42  * num_tbls [out] The number of action tables in the returned array
43  *
44  * Returns An array of action tables to implement the flow, or NULL on error.
45  */
46 static struct bnxt_ulp_mapper_act_tbl_info *
47 ulp_mapper_action_tbl_list_get(uint32_t dev_id,
48                                uint32_t tid,
49                                uint32_t *num_tbls)
50 {
51         uint32_t        idx;
52         uint32_t        tidx;
53
54         if (!num_tbls) {
55                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
56                 return NULL;
57         }
58
59         /* template shift and device mask */
60         tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id);
61
62         /* NOTE: Need to have something from template compiler to help validate
63          * range of dev_id and act_tid
64          */
65         idx             = ulp_act_tmpl_list[tidx].start_tbl_idx;
66         *num_tbls       = ulp_act_tmpl_list[tidx].num_tbls;
67
68         return &ulp_act_tbl_list[idx];
69 }
70
71 /** Get a list of classifier tables that implement the flow
72  * Gets a device dependent list of tables that implement the class template id
73  *
74  * dev_id [in] The device id of the forwarding element
75  *
76  * tid [in] The template id that matches the flow
77  *
78  * num_tbls [out] The number of classifier tables in the returned array
79  *
80  * returns An array of classifier tables to implement the flow, or NULL on
81  * error
82  */
83 static struct bnxt_ulp_mapper_class_tbl_info *
84 ulp_mapper_class_tbl_list_get(uint32_t dev_id,
85                               uint32_t tid,
86                               uint32_t *num_tbls)
87 {
88         uint32_t idx;
89         uint32_t tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id);
90
91         if (!num_tbls)
92                 return NULL;
93
94         /* NOTE: Need to have something from template compiler to help validate
95          * range of dev_id and tid
96          */
97         idx             = ulp_class_tmpl_list[tidx].start_tbl_idx;
98         *num_tbls       = ulp_class_tmpl_list[tidx].num_tbls;
99
100         return &ulp_class_tbl_list[idx];
101 }
102
103 /*
104  * Get the list of key fields that implement the flow.
105  *
106  * ctxt [in] The ulp context
107  *
108  * tbl [in] A single table instance to get the key fields from
109  *
110  * num_flds [out] The number of key fields in the returned array
111  *
112  * Returns array of Key fields, or NULL on error.
113  */
114 static struct bnxt_ulp_mapper_class_key_field_info *
115 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
116                           uint32_t *num_flds)
117 {
118         uint32_t idx;
119
120         if (!tbl || !num_flds)
121                 return NULL;
122
123         idx             = tbl->key_start_idx;
124         *num_flds       = tbl->key_num_fields;
125
126         /* NOTE: Need template to provide range checking define */
127         return &ulp_class_key_field_list[idx];
128 }
129
130 /*
131  * Get the list of data fields that implement the flow.
132  *
133  * ctxt [in] The ulp context
134  *
135  * tbl [in] A single table instance to get the data fields from
136  *
137  * num_flds [out] The number of data fields in the returned array.
138  *
139  * Returns array of data fields, or NULL on error.
140  */
141 static struct bnxt_ulp_mapper_result_field_info *
142 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
143                              uint32_t *num_flds)
144 {
145         uint32_t idx;
146
147         if (!tbl || !num_flds)
148                 return NULL;
149
150         idx             = tbl->result_start_idx;
151         *num_flds       = tbl->result_num_fields;
152
153         /* NOTE: Need template to provide range checking define */
154         return &ulp_class_result_field_list[idx];
155 }
156
157 /*
158  * Get the list of result fields that implement the flow action.
159  *
160  * tbl [in] A single table instance to get the results fields
161  * from num_flds [out] The number of data fields in the returned
162  * array.
163  *
164  * Returns array of data fields, or NULL on error.
165  */
166 static struct bnxt_ulp_mapper_result_field_info *
167 ulp_mapper_act_result_fields_get(struct bnxt_ulp_mapper_act_tbl_info *tbl,
168                                  uint32_t *num_rslt_flds,
169                                  uint32_t *num_encap_flds)
170 {
171         uint32_t idx;
172
173         if (!tbl || !num_rslt_flds || !num_encap_flds)
174                 return NULL;
175
176         idx             = tbl->result_start_idx;
177         *num_rslt_flds  = tbl->result_num_fields;
178         *num_encap_flds = tbl->encap_num_fields;
179
180         /* NOTE: Need template to provide range checking define */
181         return &ulp_act_result_field_list[idx];
182 }
183
184 /*
185  * Get the list of ident fields that implement the flow
186  *
187  * tbl [in] A single table instance to get the ident fields from
188  *
189  * num_flds [out] The number of ident fields in the returned array
190  *
191  * returns array of ident fields, or NULL on error
192  */
193 static struct bnxt_ulp_mapper_ident_info *
194 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
195                             uint32_t *num_flds)
196 {
197         uint32_t idx;
198
199         if (!tbl || !num_flds)
200                 return NULL;
201
202         idx = tbl->ident_start_idx;
203         *num_flds = tbl->ident_nums;
204
205         /* NOTE: Need template to provide range checking define */
206         return &ulp_ident_list[idx];
207 }
208
209 static inline int32_t
210 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp  __rte_unused,
211                            struct tf *tfp,
212                            struct ulp_flow_db_res_params *res)
213 {
214         struct tf_free_tcam_entry_parms fparms = {
215                 .dir            = res->direction,
216                 .tcam_tbl_type  = res->resource_type,
217                 .idx            = (uint16_t)res->resource_hndl
218         };
219
220         return tf_free_tcam_entry(tfp, &fparms);
221 }
222
223 static inline int32_t
224 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp  __rte_unused,
225                             struct tf *tfp,
226                             struct ulp_flow_db_res_params *res)
227 {
228         struct tf_free_tbl_entry_parms fparms = {
229                 .dir    = res->direction,
230                 .type   = res->resource_type,
231                 .idx    = (uint32_t)res->resource_hndl
232         };
233
234         return tf_free_tbl_entry(tfp, &fparms);
235 }
236
237 static inline int32_t
238 ulp_mapper_eem_entry_free(struct bnxt_ulp_context *ulp,
239                           struct tf *tfp,
240                           struct ulp_flow_db_res_params *res)
241 {
242         struct tf_delete_em_entry_parms fparms = { 0 };
243         int32_t rc;
244
245         fparms.dir              = res->direction;
246         fparms.mem              = TF_MEM_EXTERNAL;
247         fparms.flow_handle      = res->resource_hndl;
248
249         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
250         if (rc) {
251                 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
252                 return -EINVAL;
253         }
254
255         return tf_delete_em_entry(tfp, &fparms);
256 }
257
258 static inline int32_t
259 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
260                       struct tf *tfp,
261                       struct ulp_flow_db_res_params *res)
262 {
263         struct tf_free_identifier_parms fparms = {
264                 .dir            = res->direction,
265                 .ident_type     = res->resource_type,
266                 .id             = (uint16_t)res->resource_hndl
267         };
268
269         return tf_free_identifier(tfp, &fparms);
270 }
271
272 static inline int32_t
273 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
274                      struct ulp_flow_db_res_params *res)
275 {
276         uint32_t flag;
277         uint32_t fid;
278         uint32_t gfid;
279
280         fid       = (uint32_t)res->resource_hndl;
281         TF_GET_FLAG_FROM_FLOW_ID(fid, flag);
282         TF_GET_GFID_FROM_FLOW_ID(fid, gfid);
283
284         return ulp_mark_db_mark_del(ulp,
285                                     (flag == TF_GFID_TABLE_EXTERNAL),
286                                     gfid,
287                                     0);
288 }
289
290 static int32_t
291 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
292                          struct bnxt_ulp_mapper_class_tbl_info *tbl,
293                          struct bnxt_ulp_mapper_ident_info *ident)
294 {
295         struct ulp_flow_db_res_params   fid_parms;
296         uint64_t id = 0;
297         int32_t idx;
298         struct tf_alloc_identifier_parms iparms = { 0 };
299         struct tf_free_identifier_parms free_parms = { 0 };
300         struct tf *tfp;
301         int rc;
302
303         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
304         if (!tfp) {
305                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
306                 return -EINVAL;
307         }
308
309         idx = ident->regfile_wr_idx;
310
311         iparms.ident_type = ident->ident_type;
312         iparms.dir = tbl->direction;
313
314         rc = tf_alloc_identifier(tfp, &iparms);
315         if (rc) {
316                 BNXT_TF_DBG(ERR, "Alloc ident %s:%d failed.\n",
317                             (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
318                             iparms.ident_type);
319                 return rc;
320         }
321
322         id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
323         if (!ulp_regfile_write(parms->regfile, idx, id)) {
324                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
325                 rc = -EINVAL;
326                 /* Need to free the identifier, so goto error */
327                 goto error;
328         }
329
330         /* Link the resource to the flow in the flow db */
331         memset(&fid_parms, 0, sizeof(fid_parms));
332         fid_parms.direction             = tbl->direction;
333         fid_parms.resource_func = ident->resource_func;
334         fid_parms.resource_type = ident->ident_type;
335         fid_parms.resource_hndl = iparms.id;
336         fid_parms.critical_resource     = 0;
337
338         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
339                                       parms->tbl_idx,
340                                       parms->fid,
341                                       &fid_parms);
342         if (rc) {
343                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
344                             rc);
345                 /* Need to free the identifier, so goto error */
346                 goto error;
347         }
348
349         return 0;
350
351 error:
352         /* Need to free the identifier */
353         free_parms.dir          = tbl->direction;
354         free_parms.ident_type   = ident->ident_type;
355         free_parms.id           = iparms.id;
356
357         (void)tf_free_identifier(tfp, &free_parms);
358
359         BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
360                     ident->name,
361                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX");
362         return rc;
363 }
364
365 static int32_t
366 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
367                                 struct bnxt_ulp_mapper_result_field_info *fld,
368                                 struct ulp_blob *blob)
369 {
370         uint16_t idx, size_idx;
371         uint8_t  *val = NULL;
372         uint64_t regval;
373         uint32_t val_size = 0, field_size = 0;
374
375         switch (fld->result_opcode) {
376         case BNXT_ULP_RESULT_OPC_SET_TO_CONSTANT:
377                 val = fld->result_operand;
378                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
379                         BNXT_TF_DBG(ERR, "Failed to add field\n");
380                         return -EINVAL;
381                 }
382                 break;
383         case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP:
384                 if (!ulp_operand_read(fld->result_operand,
385                                       (uint8_t *)&idx, sizeof(uint16_t))) {
386                         BNXT_TF_DBG(ERR, "operand read failed\n");
387                         return -EINVAL;
388                 }
389                 idx = tfp_be_to_cpu_16(idx);
390
391                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
392                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
393                         return -EINVAL;
394                 }
395                 val = &parms->act_prop->act_details[idx];
396                 field_size = ulp_mapper_act_prop_size_get(idx);
397                 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
398                         field_size  = field_size -
399                             ((fld->field_bit_size + 7) / 8);
400                         val += field_size;
401                 }
402                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
403                         BNXT_TF_DBG(ERR, "push field failed\n");
404                         return -EINVAL;
405                 }
406                 break;
407         case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP_SZ:
408                 if (!ulp_operand_read(fld->result_operand,
409                                       (uint8_t *)&idx, sizeof(uint16_t))) {
410                         BNXT_TF_DBG(ERR, "operand read failed\n");
411                         return -EINVAL;
412                 }
413                 idx = tfp_be_to_cpu_16(idx);
414
415                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
416                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
417                         return -EINVAL;
418                 }
419                 val = &parms->act_prop->act_details[idx];
420
421                 /* get the size index next */
422                 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
423                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
424                         BNXT_TF_DBG(ERR, "operand read failed\n");
425                         return -EINVAL;
426                 }
427                 size_idx = tfp_be_to_cpu_16(size_idx);
428
429                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
430                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
431                         return -EINVAL;
432                 }
433                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
434                        sizeof(uint32_t));
435                 val_size = tfp_be_to_cpu_32(val_size);
436                 val_size = ULP_BYTE_2_BITS(val_size);
437                 ulp_blob_push_encap(blob, val, val_size);
438                 break;
439         case BNXT_ULP_RESULT_OPC_SET_TO_REGFILE:
440                 if (!ulp_operand_read(fld->result_operand,
441                                       (uint8_t *)&idx, sizeof(uint16_t))) {
442                         BNXT_TF_DBG(ERR, "operand read failed\n");
443                         return -EINVAL;
444                 }
445
446                 idx = tfp_be_to_cpu_16(idx);
447                 /* Uninitialized regfile entries return 0 */
448                 if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
449                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", idx);
450                         return -EINVAL;
451                 }
452
453                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
454                 if (!val) {
455                         BNXT_TF_DBG(ERR, "push field failed\n");
456                         return -EINVAL;
457                 }
458                 break;
459         default:
460                 return -EINVAL;
461         }
462
463         return 0;
464 }
465
466 /* Function to alloc action record and set the table. */
467 static int32_t
468 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
469                                  struct bnxt_ulp_mapper_class_key_field_info *f,
470                                  struct ulp_blob *blob,
471                                  uint8_t is_key)
472 {
473         uint64_t regval;
474         uint16_t idx, bitlen;
475         uint32_t opcode;
476         uint8_t *operand;
477         struct ulp_regfile *regfile = parms->regfile;
478         uint8_t *val = NULL;
479         struct bnxt_ulp_mapper_class_key_field_info *fld = f;
480         uint32_t field_size;
481
482         if (is_key) {
483                 operand = fld->spec_operand;
484                 opcode  = fld->spec_opcode;
485         } else {
486                 operand = fld->mask_operand;
487                 opcode  = fld->mask_opcode;
488         }
489
490         bitlen = fld->field_bit_size;
491
492         switch (opcode) {
493         case BNXT_ULP_SPEC_OPC_SET_TO_CONSTANT:
494                 val = operand;
495                 if (!ulp_blob_push(blob, val, bitlen)) {
496                         BNXT_TF_DBG(ERR, "push to key blob failed\n");
497                         return -EINVAL;
498                 }
499                 break;
500         case BNXT_ULP_SPEC_OPC_ADD_PAD:
501                 if (!ulp_blob_pad_push(blob, bitlen)) {
502                         BNXT_TF_DBG(ERR, "Pad too large for blob\n");
503                         return -EINVAL;
504                 }
505
506                 break;
507         case BNXT_ULP_SPEC_OPC_SET_TO_HDR_FIELD:
508                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
509                                       sizeof(uint16_t))) {
510                         BNXT_TF_DBG(ERR, "key operand read failed.\n");
511                         return -EINVAL;
512                 }
513                 idx = tfp_be_to_cpu_16(idx);
514                 if (is_key)
515                         val = parms->hdr_field[idx].spec;
516                 else
517                         val = parms->hdr_field[idx].mask;
518
519                 /*
520                  * Need to account for how much data was pushed to the header
521                  * field vs how much is to be inserted in the key/mask.
522                  */
523                 field_size = parms->hdr_field[idx].size;
524                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
525                         field_size  = field_size - ((bitlen + 7) / 8);
526                         val += field_size;
527                 }
528
529                 if (!ulp_blob_push(blob, val, bitlen)) {
530                         BNXT_TF_DBG(ERR, "push to key blob failed\n");
531                         return -EINVAL;
532                 }
533                 break;
534         case BNXT_ULP_SPEC_OPC_SET_TO_REGFILE:
535                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
536                                       sizeof(uint16_t))) {
537                         BNXT_TF_DBG(ERR, "key operand read failed.\n");
538                         return -EINVAL;
539                 }
540                 idx = tfp_be_to_cpu_16(idx);
541
542                 if (!ulp_regfile_read(regfile, idx, &regval)) {
543                         BNXT_TF_DBG(ERR, "regfile[%d] read failed.\n",
544                                     idx);
545                         return -EINVAL;
546                 }
547
548                 val = ulp_blob_push_64(blob, &regval, bitlen);
549                 if (!val) {
550                         BNXT_TF_DBG(ERR, "push to key blob failed\n");
551                         return -EINVAL;
552                 }
553         default:
554                 break;
555         }
556
557         return 0;
558 }
559
560 /* Function to alloc action record and set the table. */
561 static int32_t
562 ulp_mapper_action_alloc_and_set(struct bnxt_ulp_mapper_parms *parms,
563                                 struct ulp_blob *blob)
564 {
565         struct ulp_flow_db_res_params           fid_parms;
566         struct tf_alloc_tbl_entry_parms         alloc_parms = { 0 };
567         struct tf_free_tbl_entry_parms          free_parms = { 0 };
568         struct bnxt_ulp_mapper_act_tbl_info     *atbls = parms->atbls;
569         int32_t                                 rc = 0;
570         int32_t trc;
571         uint64_t                                idx;
572
573         /* Set the allocation parameters for the table*/
574         alloc_parms.dir = atbls->direction;
575         alloc_parms.type = atbls->table_type;
576         alloc_parms.search_enable = atbls->srch_b4_alloc;
577         alloc_parms.result = ulp_blob_data_get(blob,
578                                                &alloc_parms.result_sz_in_bytes);
579         if (!alloc_parms.result) {
580                 BNXT_TF_DBG(ERR, "blob is not populated\n");
581                 return -EINVAL;
582         }
583
584         rc = tf_alloc_tbl_entry(parms->tfp, &alloc_parms);
585         if (rc) {
586                 BNXT_TF_DBG(ERR, "table type= [%d] dir = [%s] alloc failed\n",
587                             alloc_parms.type,
588                             (alloc_parms.dir == TF_DIR_RX) ? "RX" : "TX");
589                 return rc;
590         }
591
592         /* Need to calculate the idx for the result record */
593         /*
594          * TBD: Need to get the stride from tflib instead of having to
595          * understand the construction of the pointer
596          */
597         uint64_t tmpidx = alloc_parms.idx;
598
599         if (atbls->table_type == TF_TBL_TYPE_EXT)
600                 tmpidx = (alloc_parms.idx * TF_ACTION_RECORD_SZ) >> 4;
601         else
602                 tmpidx = alloc_parms.idx;
603
604         idx = tfp_cpu_to_be_64(tmpidx);
605
606         /* Store the allocated index for future use in the regfile */
607         rc = ulp_regfile_write(parms->regfile, atbls->regfile_wr_idx, idx);
608         if (!rc) {
609                 BNXT_TF_DBG(ERR, "regfile[%d] write failed\n",
610                             atbls->regfile_wr_idx);
611                 rc = -EINVAL;
612                 goto error;
613         }
614
615         /*
616          * The set_tbl_entry API if search is not enabled or searched entry
617          * is not found.
618          */
619         if (!atbls->srch_b4_alloc || !alloc_parms.hit) {
620                 struct tf_set_tbl_entry_parms set_parm = { 0 };
621                 uint16_t        length;
622
623                 set_parm.dir    = atbls->direction;
624                 set_parm.type   = atbls->table_type;
625                 set_parm.idx    = alloc_parms.idx;
626                 set_parm.data   = ulp_blob_data_get(blob, &length);
627                 set_parm.data_sz_in_bytes = length / 8;
628
629                 if (set_parm.type == TF_TBL_TYPE_EXT)
630                         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
631                                                         &set_parm.tbl_scope_id);
632                 else
633                         set_parm.tbl_scope_id = 0;
634
635                 /* set the table entry */
636                 rc = tf_set_tbl_entry(parms->tfp, &set_parm);
637                 if (rc) {
638                         BNXT_TF_DBG(ERR, "table[%d][%s][%d] set failed\n",
639                                     set_parm.type,
640                                     (set_parm.dir == TF_DIR_RX) ? "RX" : "TX",
641                                     set_parm.idx);
642                         goto error;
643                 }
644         }
645
646         /* Link the resource to the flow in the flow db */
647         memset(&fid_parms, 0, sizeof(fid_parms));
648         fid_parms.direction             = atbls->direction;
649         fid_parms.resource_func         = atbls->resource_func;
650         fid_parms.resource_type         = atbls->table_type;
651         fid_parms.resource_hndl         = alloc_parms.idx;
652         fid_parms.critical_resource     = 0;
653
654         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
655                                       parms->tbl_idx,
656                                       parms->fid,
657                                       &fid_parms);
658         if (rc) {
659                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
660                             rc);
661                 rc = -EINVAL;
662                 goto error;
663         }
664
665         return 0;
666 error:
667
668         free_parms.dir  = alloc_parms.dir;
669         free_parms.type = alloc_parms.type;
670         free_parms.idx  = alloc_parms.idx;
671
672         trc = tf_free_tbl_entry(parms->tfp, &free_parms);
673         if (trc)
674                 BNXT_TF_DBG(ERR, "Failed to free table entry on failure\n");
675
676         return rc;
677 }
678
679 /*
680  * Function to process the action Info. Iterate through the list
681  * action info templates and process it.
682  */
683 static int32_t
684 ulp_mapper_action_info_process(struct bnxt_ulp_mapper_parms *parms,
685                                struct bnxt_ulp_mapper_act_tbl_info *tbl)
686 {
687         struct ulp_blob                                 blob;
688         struct bnxt_ulp_mapper_result_field_info        *flds, *fld;
689         uint32_t                                        num_flds = 0;
690         uint32_t                                        encap_flds = 0;
691         uint32_t                                        i;
692         int32_t                                         rc;
693         uint16_t                                        bit_size;
694
695         if (!tbl || !parms->act_prop || !parms->act_bitmap || !parms->regfile)
696                 return -EINVAL;
697
698         /* use the max size if encap is enabled */
699         if (tbl->encap_num_fields)
700                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
701         else
702                 bit_size = tbl->result_bit_size;
703         if (!ulp_blob_init(&blob, bit_size, parms->order)) {
704                 BNXT_TF_DBG(ERR, "action blob init failed\n");
705                 return -EINVAL;
706         }
707
708         flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, &encap_flds);
709         if (!flds || !num_flds) {
710                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
711                 return -EINVAL;
712         }
713
714         for (i = 0; i < (num_flds + encap_flds); i++) {
715                 fld = &flds[i];
716                 rc = ulp_mapper_result_field_process(parms,
717                                                      fld,
718                                                      &blob);
719                 if (rc) {
720                         BNXT_TF_DBG(ERR, "Action field failed\n");
721                         return rc;
722                 }
723                 /* set the swap index if 64 bit swap is enabled */
724                 if (parms->encap_byte_swap && encap_flds) {
725                         if ((i + 1) == num_flds)
726                                 ulp_blob_encap_swap_idx_set(&blob);
727                         /* if 64 bit swap is enabled perform the 64bit swap */
728                         if ((i + 1) == (num_flds + encap_flds))
729                                 ulp_blob_perform_encap_swap(&blob);
730                 }
731         }
732
733         rc = ulp_mapper_action_alloc_and_set(parms, &blob);
734         return rc;
735 }
736
737 static int32_t
738 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
739                             struct bnxt_ulp_mapper_class_tbl_info *tbl)
740 {
741         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
742         struct ulp_blob key, mask, data;
743         uint32_t i, num_kflds;
744         struct tf *tfp;
745         int32_t rc, trc;
746         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
747         struct tf_set_tcam_entry_parms sparms           = { 0 };
748         struct ulp_flow_db_res_params   fid_parms       = { 0 };
749         struct tf_free_tcam_entry_parms free_parms      = { 0 };
750         uint32_t hit = 0;
751         uint16_t tmplen = 0;
752
753         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
754         if (!tfp) {
755                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
756                 return -EINVAL;
757         }
758
759         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
760         if (!kflds || !num_kflds) {
761                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
762                 return -EINVAL;
763         }
764
765         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order) ||
766             !ulp_blob_init(&mask, tbl->key_bit_size, parms->order) ||
767             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
768                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
769                 return -EINVAL;
770         }
771
772         /* create the key/mask */
773         /*
774          * NOTE: The WC table will require some kind of flag to handle the
775          * mode bits within the key/mask
776          */
777         for (i = 0; i < num_kflds; i++) {
778                 /* Setup the key */
779                 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
780                                                       &key, 1);
781                 if (rc) {
782                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
783                         return rc;
784                 }
785
786                 /* Setup the mask */
787                 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
788                                                       &mask, 0);
789                 if (rc) {
790                         BNXT_TF_DBG(ERR, "Mask field set failed.\n");
791                         return rc;
792                 }
793         }
794
795         aparms.dir              = tbl->direction;
796         aparms.tcam_tbl_type    = tbl->table_type;
797         aparms.search_enable    = tbl->srch_b4_alloc;
798         aparms.key_sz_in_bits   = tbl->key_bit_size;
799         aparms.key              = ulp_blob_data_get(&key, &tmplen);
800         if (tbl->key_bit_size != tmplen) {
801                 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
802                             tmplen, tbl->key_bit_size);
803                 return -EINVAL;
804         }
805
806         aparms.mask             = ulp_blob_data_get(&mask, &tmplen);
807         if (tbl->key_bit_size != tmplen) {
808                 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
809                             tmplen, tbl->key_bit_size);
810                 return -EINVAL;
811         }
812
813         aparms.priority         = tbl->priority;
814
815         /*
816          * All failures after this succeeds require the entry to be freed.
817          * cannot return directly on failure, but needs to goto error
818          */
819         rc = tf_alloc_tcam_entry(tfp, &aparms);
820         if (rc) {
821                 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
822                 return rc;
823         }
824
825         hit = aparms.hit;
826
827         /* Build the result */
828         if (!tbl->srch_b4_alloc || !hit) {
829                 struct bnxt_ulp_mapper_result_field_info *dflds;
830                 struct bnxt_ulp_mapper_ident_info *idents;
831                 uint32_t num_dflds, num_idents;
832
833                 /* Alloc identifiers */
834                 idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
835
836                 for (i = 0; i < num_idents; i++) {
837                         rc = ulp_mapper_ident_process(parms, tbl, &idents[i]);
838
839                         /* Already logged the error, just return */
840                         if (rc)
841                                 goto error;
842                 }
843
844                 /* Create the result data blob */
845                 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
846                 if (!dflds || !num_dflds) {
847                         BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
848                         rc = -EINVAL;
849                         goto error;
850                 }
851
852                 for (i = 0; i < num_dflds; i++) {
853                         rc = ulp_mapper_result_field_process(parms,
854                                                              &dflds[i],
855                                                              &data);
856                         if (rc) {
857                                 BNXT_TF_DBG(ERR, "Failed to set data fields\n");
858                                 goto error;
859                         }
860                 }
861
862                 sparms.dir              = aparms.dir;
863                 sparms.tcam_tbl_type    = aparms.tcam_tbl_type;
864                 sparms.idx              = aparms.idx;
865                 /* Already verified the key/mask lengths */
866                 sparms.key              = ulp_blob_data_get(&key, &tmplen);
867                 sparms.mask             = ulp_blob_data_get(&mask, &tmplen);
868                 sparms.key_sz_in_bits   = tbl->key_bit_size;
869                 sparms.result           = ulp_blob_data_get(&data, &tmplen);
870
871                 if (tbl->result_bit_size != tmplen) {
872                         BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
873                                     tmplen, tbl->result_bit_size);
874                         rc = -EINVAL;
875                         goto error;
876                 }
877                 sparms.result_sz_in_bits = tbl->result_bit_size;
878
879                 rc = tf_set_tcam_entry(tfp, &sparms);
880                 if (rc) {
881                         BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n",
882                                     sparms.tcam_tbl_type,
883                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
884                                     sparms.idx);
885                         goto error;
886                 }
887         } else {
888                 BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n");
889                 rc = -EINVAL;
890                 goto error;
891         }
892
893         /* Link the resource to the flow in the flow db */
894         fid_parms.direction = tbl->direction;
895         fid_parms.resource_func = tbl->resource_func;
896         fid_parms.resource_type = tbl->table_type;
897         fid_parms.critical_resource = tbl->critical_resource;
898         fid_parms.resource_hndl = aparms.idx;
899
900         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
901                                       parms->tbl_idx,
902                                       parms->fid,
903                                       &fid_parms);
904         if (rc) {
905                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
906                             rc);
907                 /* Need to free the identifier, so goto error */
908                 goto error;
909         }
910
911         return 0;
912 error:
913         free_parms.dir                  = tbl->direction;
914         free_parms.tcam_tbl_type        = tbl->table_type;
915         free_parms.idx                  = aparms.idx;
916         trc = tf_free_tcam_entry(tfp, &free_parms);
917         if (trc)
918                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
919                             tbl->table_type, tbl->direction, aparms.idx);
920
921         return rc;
922 }
923
924 static int32_t
925 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
926                           struct bnxt_ulp_mapper_class_tbl_info *tbl)
927 {
928         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
929         struct bnxt_ulp_mapper_result_field_info *dflds;
930         struct ulp_blob key, data;
931         uint32_t i, num_kflds, num_dflds;
932         uint16_t tmplen;
933         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
934         struct ulp_rte_act_prop  *a_prop = parms->act_prop;
935         struct ulp_flow_db_res_params   fid_parms = { 0 };
936         struct tf_insert_em_entry_parms iparms = { 0 };
937         struct tf_delete_em_entry_parms free_parms = { 0 };
938         int32_t trc;
939         int32_t rc = 0;
940
941         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
942         if (!kflds || !num_kflds) {
943                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
944                 return -EINVAL;
945         }
946
947         /* Initialize the key/result blobs */
948         if (!ulp_blob_init(&key, tbl->blob_key_bit_size, parms->order) ||
949             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
950                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
951                 return -EINVAL;
952         }
953
954         /* create the key */
955         for (i = 0; i < num_kflds; i++) {
956                 /* Setup the key */
957                 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
958                                                       &key, 1);
959                 if (rc) {
960                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
961                         return rc;
962                 }
963         }
964
965         /*
966          * TBD: Normally should process identifiers in case of using recycle or
967          * loopback.  Not supporting recycle for now.
968          */
969
970         /* Create the result data blob */
971         dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
972         if (!dflds || !num_dflds) {
973                 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
974                 return -EINVAL;
975         }
976
977         for (i = 0; i < num_dflds; i++) {
978                 struct bnxt_ulp_mapper_result_field_info *fld;
979
980                 fld = &dflds[i];
981
982                 rc = ulp_mapper_result_field_process(parms,
983                                                      fld,
984                                                      &data);
985                 if (rc) {
986                         BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
987                         return rc;
988                 }
989         }
990
991         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
992                                              &iparms.tbl_scope_id);
993         if (rc) {
994                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
995                 return rc;
996         }
997
998         /*
999          * NOTE: the actual blob size will differ from the size in the tbl
1000          * entry due to the padding.
1001          */
1002         iparms.dup_check                = 0;
1003         iparms.dir                      = tbl->direction;
1004         iparms.mem                      = tbl->mem;
1005         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1006         iparms.key_sz_in_bits           = tbl->key_bit_size;
1007         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1008         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1009
1010         rc = tf_insert_em_entry(tfp, &iparms);
1011         if (rc) {
1012                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1013                 return rc;
1014         }
1015
1016         if (tbl->mark_enable &&
1017             ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1018                              BNXT_ULP_ACTION_BIT_MARK)) {
1019                 uint32_t val, mark, gfid, flag;
1020                 /* TBD: Need to determine if GFID is enabled globally */
1021                 if (sizeof(val) != BNXT_ULP_ACT_PROP_SZ_MARK) {
1022                         BNXT_TF_DBG(ERR, "Mark size (%d) != expected (%zu)\n",
1023                                     BNXT_ULP_ACT_PROP_SZ_MARK, sizeof(val));
1024                         rc = -EINVAL;
1025                         goto error;
1026                 }
1027
1028                 memcpy(&val,
1029                        &a_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1030                        sizeof(val));
1031
1032                 mark = tfp_be_to_cpu_32(val);
1033
1034                 TF_GET_GFID_FROM_FLOW_ID(iparms.flow_id, gfid);
1035                 TF_GET_FLAG_FROM_FLOW_ID(iparms.flow_id, flag);
1036
1037                 rc = ulp_mark_db_mark_add(parms->ulp_ctx,
1038                                           (flag == TF_GFID_TABLE_EXTERNAL),
1039                                           gfid,
1040                                           mark);
1041                 if (rc) {
1042                         BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1043                         goto error;
1044                 }
1045
1046                 /*
1047                  * Link the mark resource to the flow in the flow db
1048                  * The mark is never the critical resource, so it is 0.
1049                  */
1050                 memset(&fid_parms, 0, sizeof(fid_parms));
1051                 fid_parms.direction     = tbl->direction;
1052                 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1053                 fid_parms.resource_type = tbl->table_type;
1054                 fid_parms.resource_hndl = iparms.flow_id;
1055                 fid_parms.critical_resource = 0;
1056
1057                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1058                                               parms->tbl_idx,
1059                                               parms->fid,
1060                                               &fid_parms);
1061                 if (rc) {
1062                         BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1063                                     rc);
1064                         /* Need to free the identifier, so goto error */
1065                         goto error;
1066                 }
1067         }
1068
1069         /* Link the EM resource to the flow in the flow db */
1070         memset(&fid_parms, 0, sizeof(fid_parms));
1071         fid_parms.direction             = tbl->direction;
1072         fid_parms.resource_func         = tbl->resource_func;
1073         fid_parms.resource_type         = tbl->table_type;
1074         fid_parms.critical_resource     = tbl->critical_resource;
1075         fid_parms.resource_hndl         = iparms.flow_handle;
1076
1077         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1078                                       parms->tbl_idx,
1079                                       parms->fid,
1080                                       &fid_parms);
1081         if (rc) {
1082                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1083                             rc);
1084                 /* Need to free the identifier, so goto error */
1085                 goto error;
1086         }
1087
1088         return 0;
1089 error:
1090         free_parms.dir          = iparms.dir;
1091         free_parms.mem          = iparms.mem;
1092         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1093         free_parms.flow_handle  = iparms.flow_handle;
1094
1095         trc = tf_delete_em_entry(tfp, &free_parms);
1096         if (trc)
1097                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1098
1099         return rc;
1100 }
1101
1102 static int32_t
1103 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1104                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1105 {
1106         struct bnxt_ulp_mapper_result_field_info *flds;
1107         struct ulp_flow_db_res_params   fid_parms;
1108         struct ulp_blob data;
1109         uint64_t idx;
1110         uint16_t tmplen;
1111         uint32_t i, num_flds;
1112         int32_t rc = 0, trc = 0;
1113         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1114         struct tf_set_tbl_entry_parms   sparms = { 0 };
1115         struct tf_free_tbl_entry_parms  free_parms = { 0 };
1116
1117         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1118
1119         if (!ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1120                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1121                 return -EINVAL;
1122         }
1123
1124         flds = ulp_mapper_result_fields_get(tbl, &num_flds);
1125         if (!flds || !num_flds) {
1126                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
1127                 return -EINVAL;
1128         }
1129
1130         for (i = 0; i < num_flds; i++) {
1131                 rc = ulp_mapper_result_field_process(parms,
1132                                                      &flds[i],
1133                                                      &data);
1134                 if (rc) {
1135                         BNXT_TF_DBG(ERR, "data field failed\n");
1136                         return rc;
1137                 }
1138         }
1139
1140         aparms.dir              = tbl->direction;
1141         aparms.type             = tbl->table_type;
1142         aparms.search_enable    = tbl->srch_b4_alloc;
1143         aparms.result           = ulp_blob_data_get(&data, &tmplen);
1144         aparms.result_sz_in_bytes = ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1145
1146         /* All failures after the alloc succeeds require a free */
1147         rc = tf_alloc_tbl_entry(tfp, &aparms);
1148         if (rc) {
1149                 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1150                             tbl->table_type,
1151                             (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1152                             rc);
1153                 return rc;
1154         }
1155
1156         /* Always storing values in Regfile in BE */
1157         idx = tfp_cpu_to_be_64(aparms.idx);
1158         rc = ulp_regfile_write(parms->regfile, tbl->regfile_wr_idx, idx);
1159         if (!rc) {
1160                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1161                             tbl->regfile_wr_idx);
1162                 goto error;
1163         }
1164
1165         if (!tbl->srch_b4_alloc) {
1166                 sparms.dir              = tbl->direction;
1167                 sparms.type             = tbl->table_type;
1168                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1169                 sparms.data_sz_in_bytes =
1170                         ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1171                 sparms.idx              = aparms.idx;
1172
1173                 rc = tf_set_tbl_entry(tfp, &sparms);
1174                 if (rc) {
1175                         BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1176                                     tbl->table_type,
1177                                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1178                                     sparms.idx,
1179                                     rc);
1180
1181                         goto error;
1182                 }
1183         }
1184
1185         /* Link the resource to the flow in the flow db */
1186         memset(&fid_parms, 0, sizeof(fid_parms));
1187         fid_parms.direction     = tbl->direction;
1188         fid_parms.resource_func = tbl->resource_func;
1189         fid_parms.resource_type = tbl->table_type;
1190         fid_parms.resource_hndl = aparms.idx;
1191         fid_parms.critical_resource     = 0;
1192
1193         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1194                                       parms->tbl_idx,
1195                                       parms->fid,
1196                                       &fid_parms);
1197         if (rc) {
1198                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1199                             rc);
1200                 goto error;
1201         }
1202
1203         return rc;
1204 error:
1205         /*
1206          * Free the allocated resource since we failed to either
1207          * write to the entry or link the flow
1208          */
1209         free_parms.dir  = tbl->direction;
1210         free_parms.type = tbl->table_type;
1211         free_parms.idx  = aparms.idx;
1212
1213         trc = tf_free_tbl_entry(tfp, &free_parms);
1214         if (trc)
1215                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1216
1217         return rc;
1218 }
1219
1220 /*
1221  * Function to process the action template. Iterate through the list
1222  * action info templates and process it.
1223  */
1224 static int32_t
1225 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1226 {
1227         uint32_t        i;
1228         int32_t         rc = 0;
1229
1230         if (!parms->atbls || !parms->num_atbls) {
1231                 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
1232                             parms->dev_id, parms->act_tid);
1233                 return -EINVAL;
1234         }
1235
1236         for (i = 0; i < parms->num_atbls; i++) {
1237                 rc = ulp_mapper_action_info_process(parms, &parms->atbls[i]);
1238                 if (rc)
1239                         return rc;
1240         }
1241
1242         return rc;
1243 }
1244
1245 /* Create the classifier table entries for a flow. */
1246 static int32_t
1247 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1248 {
1249         uint32_t        i;
1250         int32_t         rc = 0;
1251
1252         if (!parms)
1253                 return -EINVAL;
1254
1255         if (!parms->ctbls || !parms->num_ctbls) {
1256                 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
1257                             parms->dev_id, parms->class_tid);
1258                 return -EINVAL;
1259         }
1260
1261         for (i = 0; i < parms->num_ctbls; i++) {
1262                 struct bnxt_ulp_mapper_class_tbl_info *tbl = &parms->ctbls[i];
1263
1264                 switch (tbl->resource_func) {
1265                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1266                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
1267                         break;
1268                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1269                         rc = ulp_mapper_em_tbl_process(parms, tbl);
1270                         break;
1271                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1272                         rc = ulp_mapper_index_tbl_process(parms, tbl);
1273                         break;
1274                 default:
1275                         BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
1276                                     tbl->resource_func);
1277                         return -EINVAL;
1278                 }
1279
1280                 if (rc) {
1281                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1282                                     tbl->resource_func);
1283                         return rc;
1284                 }
1285         }
1286
1287         return rc;
1288 }
1289
1290 static int32_t
1291 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
1292                          struct ulp_flow_db_res_params *res)
1293 {
1294         struct tf *tfp;
1295         int32_t rc = 0;
1296
1297         if (!res || !ulp) {
1298                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
1299                 return -EINVAL;
1300         }
1301
1302         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
1303         if (!tfp) {
1304                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
1305                 return -EINVAL;
1306         }
1307
1308         switch (res->resource_func) {
1309         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1310                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
1311                 break;
1312         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1313                 rc = ulp_mapper_eem_entry_free(ulp, tfp, res);
1314                 break;
1315         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1316                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
1317                 break;
1318         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1319                 rc = ulp_mapper_ident_free(ulp, tfp, res);
1320                 break;
1321         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
1322                 rc = ulp_mapper_mark_free(ulp, res);
1323                 break;
1324         default:
1325                 break;
1326         }
1327
1328         return rc;
1329 }
1330
1331 int32_t
1332 ulp_mapper_resources_free(struct bnxt_ulp_context       *ulp_ctx,
1333                           uint32_t fid,
1334                           enum bnxt_ulp_flow_db_tables  tbl_type)
1335 {
1336         struct ulp_flow_db_res_params   res_parms = { 0 };
1337         int32_t                         rc, trc;
1338
1339         if (!ulp_ctx) {
1340                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1341                 return -EINVAL;
1342         }
1343
1344         /*
1345          * Set the critical resource on the first resource del, then iterate
1346          * while status is good
1347          */
1348         res_parms.critical_resource = 1;
1349         rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms);
1350
1351         if (rc) {
1352                 /*
1353                  * This is unexpected on the first call to resource del.
1354                  * It likely means that the flow did not exist in the flow db.
1355                  */
1356                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
1357                             tbl_type, fid, rc);
1358                 return rc;
1359         }
1360
1361         while (!rc) {
1362                 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
1363                 if (trc)
1364                         /*
1365                          * On fail, we still need to attempt to free the
1366                          * remaining resources.  Don't return
1367                          */
1368                         BNXT_TF_DBG(ERR,
1369                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
1370                                     "] failed rc=%d.\n",
1371                                     tbl_type, fid, res_parms.resource_func,
1372                                     res_parms.resource_hndl, trc);
1373
1374                 /* All subsequent call require the critical_resource be zero */
1375                 res_parms.critical_resource = 0;
1376
1377                 rc = ulp_flow_db_resource_del(ulp_ctx,
1378                                               tbl_type,
1379                                               fid,
1380                                               &res_parms);
1381         }
1382
1383         /* Free the Flow ID since we've removed all resources */
1384         rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid);
1385
1386         return rc;
1387 }
1388
1389 int32_t
1390 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
1391 {
1392         if (!ulp_ctx) {
1393                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1394                 return -EINVAL;
1395         }
1396
1397         return ulp_mapper_resources_free(ulp_ctx,
1398                                          fid,
1399                                          BNXT_ULP_REGULAR_FLOW_TABLE);
1400 }
1401
1402 /* Function to handle the mapping of the Flow to be compatible
1403  * with the underlying hardware.
1404  */
1405 int32_t
1406 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
1407                        uint32_t app_priority __rte_unused,
1408                        struct ulp_rte_hdr_bitmap *hdr_bitmap __rte_unused,
1409                        struct ulp_rte_hdr_field *hdr_field,
1410                        struct ulp_rte_act_bitmap *act_bitmap,
1411                        struct ulp_rte_act_prop *act_prop,
1412                        uint32_t class_tid,
1413                        uint32_t act_tid,
1414                        uint32_t *flow_id)
1415 {
1416         struct ulp_regfile              regfile;
1417         struct bnxt_ulp_mapper_parms    parms;
1418         struct bnxt_ulp_device_params   *device_params;
1419         int32_t                         rc, trc;
1420
1421         /* Initialize the parms structure */
1422         memset(&parms, 0, sizeof(parms));
1423         parms.act_prop = act_prop;
1424         parms.act_bitmap = act_bitmap;
1425         parms.regfile = &regfile;
1426         parms.hdr_field = hdr_field;
1427         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
1428         parms.ulp_ctx = ulp_ctx;
1429
1430         /* Get the device id from the ulp context */
1431         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
1432                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
1433                 return -EINVAL;
1434         }
1435
1436         /* Get the action table entry from device id and act context id */
1437         parms.act_tid = act_tid;
1438         parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id,
1439                                                      parms.act_tid,
1440                                                      &parms.num_atbls);
1441         if (!parms.atbls || !parms.num_atbls) {
1442                 BNXT_TF_DBG(ERR, "No action tables for %d:%d\n",
1443                             parms.dev_id, parms.act_tid);
1444                 return -EINVAL;
1445         }
1446
1447         /* Get the class table entry from device id and act context id */
1448         parms.class_tid = class_tid;
1449         parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
1450                                                     parms.class_tid,
1451                                                     &parms.num_ctbls);
1452         if (!parms.ctbls || !parms.num_ctbls) {
1453                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1454                             parms.dev_id, parms.class_tid);
1455                 return -EINVAL;
1456         }
1457
1458         /* Get the byte order for the further processing from device params */
1459         device_params = bnxt_ulp_device_params_get(parms.dev_id);
1460         if (!device_params) {
1461                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1462                             parms.dev_id, parms.class_tid);
1463                 return -EINVAL;
1464         }
1465         parms.order = device_params->byte_order;
1466         parms.encap_byte_swap = device_params->encap_byte_swap;
1467
1468         /* initialize the registry file for further processing */
1469         if (!ulp_regfile_init(parms.regfile)) {
1470                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
1471                 return -EINVAL;
1472         }
1473
1474         /* Allocate a Flow ID for attaching all resources for the flow to.
1475          * Once allocated, all errors have to walk the list of resources and
1476          * free each of them.
1477          */
1478         rc = ulp_flow_db_fid_alloc(ulp_ctx,
1479                                    BNXT_ULP_REGULAR_FLOW_TABLE,
1480                                    &parms.fid);
1481         if (rc) {
1482                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
1483                 return rc;
1484         }
1485
1486         /* Process the action template list from the selected action table*/
1487         rc = ulp_mapper_action_tbls_process(&parms);
1488         if (rc) {
1489                 BNXT_TF_DBG(ERR, "action tables failed creation for %d:%d\n",
1490                             parms.dev_id, parms.act_tid);
1491                 goto flow_error;
1492         }
1493
1494         /* All good. Now process the class template */
1495         rc = ulp_mapper_class_tbls_process(&parms);
1496         if (rc) {
1497                 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n",
1498                             parms.dev_id, parms.class_tid);
1499                 goto flow_error;
1500         }
1501
1502         *flow_id = parms.fid;
1503
1504         return rc;
1505
1506 flow_error:
1507         /* Free all resources that were allocated during flow creation */
1508         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
1509         if (trc)
1510                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
1511
1512         return rc;
1513 }