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