a0aba403f8d87e3db80d856da962133e107c37c7
[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->description,
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                                 const char *name)
370 {
371         uint16_t idx, size_idx;
372         uint8_t  *val = NULL;
373         uint64_t regval;
374         uint32_t val_size = 0, field_size = 0;
375
376         switch (fld->result_opcode) {
377         case BNXT_ULP_RESULT_OPC_SET_TO_CONSTANT:
378                 val = fld->result_operand;
379                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
380                         BNXT_TF_DBG(ERR, "%s failed to add field\n", name);
381                         return -EINVAL;
382                 }
383                 break;
384         case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP:
385                 if (!ulp_operand_read(fld->result_operand,
386                                       (uint8_t *)&idx, sizeof(uint16_t))) {
387                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
388                         return -EINVAL;
389                 }
390                 idx = tfp_be_to_cpu_16(idx);
391
392                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
393                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
394                         return -EINVAL;
395                 }
396                 val = &parms->act_prop->act_details[idx];
397                 field_size = ulp_mapper_act_prop_size_get(idx);
398                 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
399                         field_size  = field_size -
400                             ((fld->field_bit_size + 7) / 8);
401                         val += field_size;
402                 }
403                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
404                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
405                         return -EINVAL;
406                 }
407                 break;
408         case BNXT_ULP_RESULT_OPC_SET_TO_ENCAP_ACT_PROP_SZ:
409                 if (!ulp_operand_read(fld->result_operand,
410                                       (uint8_t *)&idx, sizeof(uint16_t))) {
411                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
412                         return -EINVAL;
413                 }
414                 idx = tfp_be_to_cpu_16(idx);
415
416                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
417                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
418                         return -EINVAL;
419                 }
420                 val = &parms->act_prop->act_details[idx];
421
422                 /* get the size index next */
423                 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
424                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
425                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
426                         return -EINVAL;
427                 }
428                 size_idx = tfp_be_to_cpu_16(size_idx);
429
430                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
431                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
432                         return -EINVAL;
433                 }
434                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
435                        sizeof(uint32_t));
436                 val_size = tfp_be_to_cpu_32(val_size);
437                 val_size = ULP_BYTE_2_BITS(val_size);
438                 ulp_blob_push_encap(blob, val, val_size);
439                 break;
440         case BNXT_ULP_RESULT_OPC_SET_TO_REGFILE:
441                 if (!ulp_operand_read(fld->result_operand,
442                                       (uint8_t *)&idx, sizeof(uint16_t))) {
443                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
444                         return -EINVAL;
445                 }
446
447                 idx = tfp_be_to_cpu_16(idx);
448                 /* Uninitialized regfile entries return 0 */
449                 if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
450                         BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
451                                     name, idx);
452                         return -EINVAL;
453                 }
454
455                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
456                 if (!val) {
457                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
458                         return -EINVAL;
459                 }
460                 break;
461         default:
462                 return -EINVAL;
463         }
464
465         return 0;
466 }
467
468 /* Function to alloc action record and set the table. */
469 static int32_t
470 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
471                                  struct bnxt_ulp_mapper_class_key_field_info *f,
472                                  struct ulp_blob *blob,
473                                  uint8_t is_key,
474                                  const char *name)
475 {
476         uint64_t regval;
477         uint16_t idx, bitlen;
478         uint32_t opcode;
479         uint8_t *operand;
480         struct ulp_regfile *regfile = parms->regfile;
481         uint8_t *val = NULL;
482         struct bnxt_ulp_mapper_class_key_field_info *fld = f;
483         uint32_t field_size;
484
485         if (is_key) {
486                 operand = fld->spec_operand;
487                 opcode  = fld->spec_opcode;
488         } else {
489                 operand = fld->mask_operand;
490                 opcode  = fld->mask_opcode;
491         }
492
493         bitlen = fld->field_bit_size;
494
495         switch (opcode) {
496         case BNXT_ULP_SPEC_OPC_SET_TO_CONSTANT:
497                 val = operand;
498                 if (!ulp_blob_push(blob, val, bitlen)) {
499                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
500                         return -EINVAL;
501                 }
502                 break;
503         case BNXT_ULP_SPEC_OPC_ADD_PAD:
504                 if (!ulp_blob_pad_push(blob, bitlen)) {
505                         BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
506                         return -EINVAL;
507                 }
508
509                 break;
510         case BNXT_ULP_SPEC_OPC_SET_TO_HDR_FIELD:
511                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
512                                       sizeof(uint16_t))) {
513                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
514                         return -EINVAL;
515                 }
516                 idx = tfp_be_to_cpu_16(idx);
517                 if (is_key)
518                         val = parms->hdr_field[idx].spec;
519                 else
520                         val = parms->hdr_field[idx].mask;
521
522                 /*
523                  * Need to account for how much data was pushed to the header
524                  * field vs how much is to be inserted in the key/mask.
525                  */
526                 field_size = parms->hdr_field[idx].size;
527                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
528                         field_size  = field_size - ((bitlen + 7) / 8);
529                         val += field_size;
530                 }
531
532                 if (!ulp_blob_push(blob, val, bitlen)) {
533                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
534                         return -EINVAL;
535                 }
536                 break;
537         case BNXT_ULP_SPEC_OPC_SET_TO_REGFILE:
538                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
539                                       sizeof(uint16_t))) {
540                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
541                         return -EINVAL;
542                 }
543                 idx = tfp_be_to_cpu_16(idx);
544
545                 if (!ulp_regfile_read(regfile, idx, &regval)) {
546                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
547                                     name, idx);
548                         return -EINVAL;
549                 }
550
551                 val = ulp_blob_push_64(blob, &regval, bitlen);
552                 if (!val) {
553                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
554                         return -EINVAL;
555                 }
556         default:
557                 break;
558         }
559
560         return 0;
561 }
562
563 /* Function to alloc action record and set the table. */
564 static int32_t
565 ulp_mapper_action_alloc_and_set(struct bnxt_ulp_mapper_parms *parms,
566                                 struct ulp_blob *blob)
567 {
568         struct ulp_flow_db_res_params           fid_parms;
569         struct tf_alloc_tbl_entry_parms         alloc_parms = { 0 };
570         struct tf_free_tbl_entry_parms          free_parms = { 0 };
571         struct bnxt_ulp_mapper_act_tbl_info     *atbls = parms->atbls;
572         int32_t                                 rc = 0;
573         int32_t trc;
574         uint64_t                                idx;
575
576         /* Set the allocation parameters for the table*/
577         alloc_parms.dir = atbls->direction;
578         alloc_parms.type = atbls->table_type;
579         alloc_parms.search_enable = atbls->srch_b4_alloc;
580         alloc_parms.result = ulp_blob_data_get(blob,
581                                                &alloc_parms.result_sz_in_bytes);
582         if (!alloc_parms.result) {
583                 BNXT_TF_DBG(ERR, "blob is not populated\n");
584                 return -EINVAL;
585         }
586
587         rc = tf_alloc_tbl_entry(parms->tfp, &alloc_parms);
588         if (rc) {
589                 BNXT_TF_DBG(ERR, "table type= [%d] dir = [%s] alloc failed\n",
590                             alloc_parms.type,
591                             (alloc_parms.dir == TF_DIR_RX) ? "RX" : "TX");
592                 return rc;
593         }
594
595         /* Need to calculate the idx for the result record */
596         /*
597          * TBD: Need to get the stride from tflib instead of having to
598          * understand the construction of the pointer
599          */
600         uint64_t tmpidx = alloc_parms.idx;
601
602         if (atbls->table_type == TF_TBL_TYPE_EXT)
603                 tmpidx = (alloc_parms.idx * TF_ACTION_RECORD_SZ) >> 4;
604         else
605                 tmpidx = alloc_parms.idx;
606
607         idx = tfp_cpu_to_be_64(tmpidx);
608
609         /* Store the allocated index for future use in the regfile */
610         rc = ulp_regfile_write(parms->regfile, atbls->regfile_wr_idx, idx);
611         if (!rc) {
612                 BNXT_TF_DBG(ERR, "regfile[%d] write failed\n",
613                             atbls->regfile_wr_idx);
614                 rc = -EINVAL;
615                 goto error;
616         }
617
618         /*
619          * The set_tbl_entry API if search is not enabled or searched entry
620          * is not found.
621          */
622         if (!atbls->srch_b4_alloc || !alloc_parms.hit) {
623                 struct tf_set_tbl_entry_parms set_parm = { 0 };
624                 uint16_t        length;
625
626                 set_parm.dir    = atbls->direction;
627                 set_parm.type   = atbls->table_type;
628                 set_parm.idx    = alloc_parms.idx;
629                 set_parm.data   = ulp_blob_data_get(blob, &length);
630                 set_parm.data_sz_in_bytes = length / 8;
631
632                 if (set_parm.type == TF_TBL_TYPE_EXT)
633                         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
634                                                         &set_parm.tbl_scope_id);
635                 else
636                         set_parm.tbl_scope_id = 0;
637
638                 /* set the table entry */
639                 rc = tf_set_tbl_entry(parms->tfp, &set_parm);
640                 if (rc) {
641                         BNXT_TF_DBG(ERR, "table[%d][%s][%d] set failed\n",
642                                     set_parm.type,
643                                     (set_parm.dir == TF_DIR_RX) ? "RX" : "TX",
644                                     set_parm.idx);
645                         goto error;
646                 }
647         }
648
649         /* Link the resource to the flow in the flow db */
650         memset(&fid_parms, 0, sizeof(fid_parms));
651         fid_parms.direction             = atbls->direction;
652         fid_parms.resource_func         = atbls->resource_func;
653         fid_parms.resource_type         = atbls->table_type;
654         fid_parms.resource_hndl         = alloc_parms.idx;
655         fid_parms.critical_resource     = 0;
656
657         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
658                                       parms->tbl_idx,
659                                       parms->fid,
660                                       &fid_parms);
661         if (rc) {
662                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
663                             rc);
664                 rc = -EINVAL;
665                 goto error;
666         }
667
668         return 0;
669 error:
670
671         free_parms.dir  = alloc_parms.dir;
672         free_parms.type = alloc_parms.type;
673         free_parms.idx  = alloc_parms.idx;
674
675         trc = tf_free_tbl_entry(parms->tfp, &free_parms);
676         if (trc)
677                 BNXT_TF_DBG(ERR, "Failed to free table entry on failure\n");
678
679         return rc;
680 }
681
682 /*
683  * Function to process the action Info. Iterate through the list
684  * action info templates and process it.
685  */
686 static int32_t
687 ulp_mapper_action_info_process(struct bnxt_ulp_mapper_parms *parms,
688                                struct bnxt_ulp_mapper_act_tbl_info *tbl)
689 {
690         struct ulp_blob                                 blob;
691         struct bnxt_ulp_mapper_result_field_info        *flds, *fld;
692         uint32_t                                        num_flds = 0;
693         uint32_t                                        encap_flds = 0;
694         uint32_t                                        i;
695         int32_t                                         rc;
696         uint16_t                                        bit_size;
697
698         if (!tbl || !parms->act_prop || !parms->act_bitmap || !parms->regfile)
699                 return -EINVAL;
700
701         /* use the max size if encap is enabled */
702         if (tbl->encap_num_fields)
703                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
704         else
705                 bit_size = tbl->result_bit_size;
706         if (!ulp_blob_init(&blob, bit_size, parms->order)) {
707                 BNXT_TF_DBG(ERR, "action blob init failed\n");
708                 return -EINVAL;
709         }
710
711         flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, &encap_flds);
712         if (!flds || !num_flds) {
713                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
714                 return -EINVAL;
715         }
716
717         for (i = 0; i < (num_flds + encap_flds); i++) {
718                 fld = &flds[i];
719                 rc = ulp_mapper_result_field_process(parms,
720                                                      fld,
721                                                      &blob,
722                                                      "Action");
723                 if (rc) {
724                         BNXT_TF_DBG(ERR, "Action field failed\n");
725                         return rc;
726                 }
727                 /* set the swap index if 64 bit swap is enabled */
728                 if (parms->encap_byte_swap && encap_flds) {
729                         if ((i + 1) == num_flds)
730                                 ulp_blob_encap_swap_idx_set(&blob);
731                         /* if 64 bit swap is enabled perform the 64bit swap */
732                         if ((i + 1) == (num_flds + encap_flds))
733                                 ulp_blob_perform_encap_swap(&blob);
734                 }
735         }
736
737         rc = ulp_mapper_action_alloc_and_set(parms, &blob);
738         return rc;
739 }
740
741 static int32_t
742 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
743                             struct bnxt_ulp_mapper_class_tbl_info *tbl)
744 {
745         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
746         struct ulp_blob key, mask, data;
747         uint32_t i, num_kflds;
748         struct tf *tfp;
749         int32_t rc, trc;
750         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
751         struct tf_set_tcam_entry_parms sparms           = { 0 };
752         struct ulp_flow_db_res_params   fid_parms       = { 0 };
753         struct tf_free_tcam_entry_parms free_parms      = { 0 };
754         uint32_t hit = 0;
755         uint16_t tmplen = 0;
756
757         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
758         if (!tfp) {
759                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
760                 return -EINVAL;
761         }
762
763         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
764         if (!kflds || !num_kflds) {
765                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
766                 return -EINVAL;
767         }
768
769         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order) ||
770             !ulp_blob_init(&mask, tbl->key_bit_size, parms->order) ||
771             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
772                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
773                 return -EINVAL;
774         }
775
776         /* create the key/mask */
777         /*
778          * NOTE: The WC table will require some kind of flag to handle the
779          * mode bits within the key/mask
780          */
781         for (i = 0; i < num_kflds; i++) {
782                 /* Setup the key */
783                 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
784                                                       &key, 1, "TCAM Key");
785                 if (rc) {
786                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
787                         return rc;
788                 }
789
790                 /* Setup the mask */
791                 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
792                                                       &mask, 0, "TCAM Mask");
793                 if (rc) {
794                         BNXT_TF_DBG(ERR, "Mask field set failed.\n");
795                         return rc;
796                 }
797         }
798
799         aparms.dir              = tbl->direction;
800         aparms.tcam_tbl_type    = tbl->table_type;
801         aparms.search_enable    = tbl->srch_b4_alloc;
802         aparms.key_sz_in_bits   = tbl->key_bit_size;
803         aparms.key              = ulp_blob_data_get(&key, &tmplen);
804         if (tbl->key_bit_size != tmplen) {
805                 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
806                             tmplen, tbl->key_bit_size);
807                 return -EINVAL;
808         }
809
810         aparms.mask             = ulp_blob_data_get(&mask, &tmplen);
811         if (tbl->key_bit_size != tmplen) {
812                 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
813                             tmplen, tbl->key_bit_size);
814                 return -EINVAL;
815         }
816
817         aparms.priority         = tbl->priority;
818
819         /*
820          * All failures after this succeeds require the entry to be freed.
821          * cannot return directly on failure, but needs to goto error
822          */
823         rc = tf_alloc_tcam_entry(tfp, &aparms);
824         if (rc) {
825                 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
826                 return rc;
827         }
828
829         hit = aparms.hit;
830
831         /* Build the result */
832         if (!tbl->srch_b4_alloc || !hit) {
833                 struct bnxt_ulp_mapper_result_field_info *dflds;
834                 struct bnxt_ulp_mapper_ident_info *idents;
835                 uint32_t num_dflds, num_idents;
836
837                 /* Alloc identifiers */
838                 idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
839
840                 for (i = 0; i < num_idents; i++) {
841                         rc = ulp_mapper_ident_process(parms, tbl, &idents[i]);
842
843                         /* Already logged the error, just return */
844                         if (rc)
845                                 goto error;
846                 }
847
848                 /* Create the result data blob */
849                 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
850                 if (!dflds || !num_dflds) {
851                         BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
852                         rc = -EINVAL;
853                         goto error;
854                 }
855
856                 for (i = 0; i < num_dflds; i++) {
857                         rc = ulp_mapper_result_field_process(parms,
858                                                              &dflds[i],
859                                                              &data,
860                                                              "TCAM Result");
861                         if (rc) {
862                                 BNXT_TF_DBG(ERR, "Failed to set data fields\n");
863                                 goto error;
864                         }
865                 }
866
867                 sparms.dir              = aparms.dir;
868                 sparms.tcam_tbl_type    = aparms.tcam_tbl_type;
869                 sparms.idx              = aparms.idx;
870                 /* Already verified the key/mask lengths */
871                 sparms.key              = ulp_blob_data_get(&key, &tmplen);
872                 sparms.mask             = ulp_blob_data_get(&mask, &tmplen);
873                 sparms.key_sz_in_bits   = tbl->key_bit_size;
874                 sparms.result           = ulp_blob_data_get(&data, &tmplen);
875
876                 if (tbl->result_bit_size != tmplen) {
877                         BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
878                                     tmplen, tbl->result_bit_size);
879                         rc = -EINVAL;
880                         goto error;
881                 }
882                 sparms.result_sz_in_bits = tbl->result_bit_size;
883
884                 rc = tf_set_tcam_entry(tfp, &sparms);
885                 if (rc) {
886                         BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n",
887                                     sparms.tcam_tbl_type,
888                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
889                                     sparms.idx);
890                         goto error;
891                 }
892         } else {
893                 BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n");
894                 rc = -EINVAL;
895                 goto error;
896         }
897
898         /* Link the resource to the flow in the flow db */
899         fid_parms.direction = tbl->direction;
900         fid_parms.resource_func = tbl->resource_func;
901         fid_parms.resource_type = tbl->table_type;
902         fid_parms.critical_resource = tbl->critical_resource;
903         fid_parms.resource_hndl = aparms.idx;
904
905         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
906                                       parms->tbl_idx,
907                                       parms->fid,
908                                       &fid_parms);
909         if (rc) {
910                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
911                             rc);
912                 /* Need to free the identifier, so goto error */
913                 goto error;
914         }
915
916         return 0;
917 error:
918         free_parms.dir                  = tbl->direction;
919         free_parms.tcam_tbl_type        = tbl->table_type;
920         free_parms.idx                  = aparms.idx;
921         trc = tf_free_tcam_entry(tfp, &free_parms);
922         if (trc)
923                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
924                             tbl->table_type, tbl->direction, aparms.idx);
925
926         return rc;
927 }
928
929 static int32_t
930 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
931                           struct bnxt_ulp_mapper_class_tbl_info *tbl)
932 {
933         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
934         struct bnxt_ulp_mapper_result_field_info *dflds;
935         struct ulp_blob key, data;
936         uint32_t i, num_kflds, num_dflds;
937         uint16_t tmplen;
938         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
939         struct ulp_rte_act_prop  *a_prop = parms->act_prop;
940         struct ulp_flow_db_res_params   fid_parms = { 0 };
941         struct tf_insert_em_entry_parms iparms = { 0 };
942         struct tf_delete_em_entry_parms free_parms = { 0 };
943         int32_t trc;
944         int32_t rc = 0;
945
946         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
947         if (!kflds || !num_kflds) {
948                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
949                 return -EINVAL;
950         }
951
952         /* Initialize the key/result blobs */
953         if (!ulp_blob_init(&key, tbl->blob_key_bit_size, parms->order) ||
954             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
955                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
956                 return -EINVAL;
957         }
958
959         /* create the key */
960         for (i = 0; i < num_kflds; i++) {
961                 /* Setup the key */
962                 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
963                                                       &key, 1, "EM Key");
964                 if (rc) {
965                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
966                         return rc;
967                 }
968         }
969
970         /*
971          * TBD: Normally should process identifiers in case of using recycle or
972          * loopback.  Not supporting recycle for now.
973          */
974
975         /* Create the result data blob */
976         dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
977         if (!dflds || !num_dflds) {
978                 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
979                 return -EINVAL;
980         }
981
982         for (i = 0; i < num_dflds; i++) {
983                 struct bnxt_ulp_mapper_result_field_info *fld;
984
985                 fld = &dflds[i];
986
987                 rc = ulp_mapper_result_field_process(parms,
988                                                      fld,
989                                                      &data,
990                                                      "EM Result");
991                 if (rc) {
992                         BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
993                         return rc;
994                 }
995         }
996
997         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
998                                              &iparms.tbl_scope_id);
999         if (rc) {
1000                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1001                 return rc;
1002         }
1003
1004         /*
1005          * NOTE: the actual blob size will differ from the size in the tbl
1006          * entry due to the padding.
1007          */
1008         iparms.dup_check                = 0;
1009         iparms.dir                      = tbl->direction;
1010         iparms.mem                      = tbl->mem;
1011         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1012         iparms.key_sz_in_bits           = tbl->key_bit_size;
1013         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1014         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1015
1016         rc = tf_insert_em_entry(tfp, &iparms);
1017         if (rc) {
1018                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1019                 return rc;
1020         }
1021
1022         if (tbl->mark_enable &&
1023             ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1024                              BNXT_ULP_ACTION_BIT_MARK)) {
1025                 uint32_t val, mark, gfid, flag;
1026                 /* TBD: Need to determine if GFID is enabled globally */
1027                 if (sizeof(val) != BNXT_ULP_ACT_PROP_SZ_MARK) {
1028                         BNXT_TF_DBG(ERR, "Mark size (%d) != expected (%zu)\n",
1029                                     BNXT_ULP_ACT_PROP_SZ_MARK, sizeof(val));
1030                         rc = -EINVAL;
1031                         goto error;
1032                 }
1033
1034                 memcpy(&val,
1035                        &a_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1036                        sizeof(val));
1037
1038                 mark = tfp_be_to_cpu_32(val);
1039
1040                 TF_GET_GFID_FROM_FLOW_ID(iparms.flow_id, gfid);
1041                 TF_GET_FLAG_FROM_FLOW_ID(iparms.flow_id, flag);
1042
1043                 rc = ulp_mark_db_mark_add(parms->ulp_ctx,
1044                                           (flag == TF_GFID_TABLE_EXTERNAL),
1045                                           gfid,
1046                                           mark);
1047                 if (rc) {
1048                         BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1049                         goto error;
1050                 }
1051
1052                 /*
1053                  * Link the mark resource to the flow in the flow db
1054                  * The mark is never the critical resource, so it is 0.
1055                  */
1056                 memset(&fid_parms, 0, sizeof(fid_parms));
1057                 fid_parms.direction     = tbl->direction;
1058                 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1059                 fid_parms.resource_type = tbl->table_type;
1060                 fid_parms.resource_hndl = iparms.flow_id;
1061                 fid_parms.critical_resource = 0;
1062
1063                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1064                                               parms->tbl_idx,
1065                                               parms->fid,
1066                                               &fid_parms);
1067                 if (rc) {
1068                         BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1069                                     rc);
1070                         /* Need to free the identifier, so goto error */
1071                         goto error;
1072                 }
1073         }
1074
1075         /* Link the EM resource to the flow in the flow db */
1076         memset(&fid_parms, 0, sizeof(fid_parms));
1077         fid_parms.direction             = tbl->direction;
1078         fid_parms.resource_func         = tbl->resource_func;
1079         fid_parms.resource_type         = tbl->table_type;
1080         fid_parms.critical_resource     = tbl->critical_resource;
1081         fid_parms.resource_hndl         = iparms.flow_handle;
1082
1083         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1084                                       parms->tbl_idx,
1085                                       parms->fid,
1086                                       &fid_parms);
1087         if (rc) {
1088                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1089                             rc);
1090                 /* Need to free the identifier, so goto error */
1091                 goto error;
1092         }
1093
1094         return 0;
1095 error:
1096         free_parms.dir          = iparms.dir;
1097         free_parms.mem          = iparms.mem;
1098         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1099         free_parms.flow_handle  = iparms.flow_handle;
1100
1101         trc = tf_delete_em_entry(tfp, &free_parms);
1102         if (trc)
1103                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1104
1105         return rc;
1106 }
1107
1108 static int32_t
1109 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1110                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1111 {
1112         struct bnxt_ulp_mapper_result_field_info *flds;
1113         struct ulp_flow_db_res_params   fid_parms;
1114         struct ulp_blob data;
1115         uint64_t idx;
1116         uint16_t tmplen;
1117         uint32_t i, num_flds;
1118         int32_t rc = 0, trc = 0;
1119         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1120         struct tf_set_tbl_entry_parms   sparms = { 0 };
1121         struct tf_free_tbl_entry_parms  free_parms = { 0 };
1122
1123         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1124
1125         if (!ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1126                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1127                 return -EINVAL;
1128         }
1129
1130         flds = ulp_mapper_result_fields_get(tbl, &num_flds);
1131         if (!flds || !num_flds) {
1132                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
1133                 return -EINVAL;
1134         }
1135
1136         for (i = 0; i < num_flds; i++) {
1137                 rc = ulp_mapper_result_field_process(parms,
1138                                                      &flds[i],
1139                                                      &data,
1140                                                      "Indexed Result");
1141                 if (rc) {
1142                         BNXT_TF_DBG(ERR, "data field failed\n");
1143                         return rc;
1144                 }
1145         }
1146
1147         aparms.dir              = tbl->direction;
1148         aparms.type             = tbl->table_type;
1149         aparms.search_enable    = tbl->srch_b4_alloc;
1150         aparms.result           = ulp_blob_data_get(&data, &tmplen);
1151         aparms.result_sz_in_bytes = ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1152
1153         /* All failures after the alloc succeeds require a free */
1154         rc = tf_alloc_tbl_entry(tfp, &aparms);
1155         if (rc) {
1156                 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1157                             tbl->table_type,
1158                             (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1159                             rc);
1160                 return rc;
1161         }
1162
1163         /* Always storing values in Regfile in BE */
1164         idx = tfp_cpu_to_be_64(aparms.idx);
1165         rc = ulp_regfile_write(parms->regfile, tbl->regfile_wr_idx, idx);
1166         if (!rc) {
1167                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1168                             tbl->regfile_wr_idx);
1169                 goto error;
1170         }
1171
1172         if (!tbl->srch_b4_alloc) {
1173                 sparms.dir              = tbl->direction;
1174                 sparms.type             = tbl->table_type;
1175                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1176                 sparms.data_sz_in_bytes =
1177                         ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1178                 sparms.idx              = aparms.idx;
1179
1180                 rc = tf_set_tbl_entry(tfp, &sparms);
1181                 if (rc) {
1182                         BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1183                                     tbl->table_type,
1184                                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1185                                     sparms.idx,
1186                                     rc);
1187
1188                         goto error;
1189                 }
1190         }
1191
1192         /* Link the resource to the flow in the flow db */
1193         memset(&fid_parms, 0, sizeof(fid_parms));
1194         fid_parms.direction     = tbl->direction;
1195         fid_parms.resource_func = tbl->resource_func;
1196         fid_parms.resource_type = tbl->table_type;
1197         fid_parms.resource_hndl = aparms.idx;
1198         fid_parms.critical_resource     = 0;
1199
1200         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1201                                       parms->tbl_idx,
1202                                       parms->fid,
1203                                       &fid_parms);
1204         if (rc) {
1205                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1206                             rc);
1207                 goto error;
1208         }
1209
1210         return rc;
1211 error:
1212         /*
1213          * Free the allocated resource since we failed to either
1214          * write to the entry or link the flow
1215          */
1216         free_parms.dir  = tbl->direction;
1217         free_parms.type = tbl->table_type;
1218         free_parms.idx  = aparms.idx;
1219
1220         trc = tf_free_tbl_entry(tfp, &free_parms);
1221         if (trc)
1222                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1223
1224         return rc;
1225 }
1226
1227 /*
1228  * Function to process the action template. Iterate through the list
1229  * action info templates and process it.
1230  */
1231 static int32_t
1232 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1233 {
1234         uint32_t        i;
1235         int32_t         rc = 0;
1236
1237         if (!parms->atbls || !parms->num_atbls) {
1238                 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
1239                             parms->dev_id, parms->act_tid);
1240                 return -EINVAL;
1241         }
1242
1243         for (i = 0; i < parms->num_atbls; i++) {
1244                 rc = ulp_mapper_action_info_process(parms, &parms->atbls[i]);
1245                 if (rc)
1246                         return rc;
1247         }
1248
1249         return rc;
1250 }
1251
1252 /* Create the classifier table entries for a flow. */
1253 static int32_t
1254 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1255 {
1256         uint32_t        i;
1257         int32_t         rc = 0;
1258
1259         if (!parms)
1260                 return -EINVAL;
1261
1262         if (!parms->ctbls || !parms->num_ctbls) {
1263                 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
1264                             parms->dev_id, parms->class_tid);
1265                 return -EINVAL;
1266         }
1267
1268         for (i = 0; i < parms->num_ctbls; i++) {
1269                 struct bnxt_ulp_mapper_class_tbl_info *tbl = &parms->ctbls[i];
1270
1271                 switch (tbl->resource_func) {
1272                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1273                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
1274                         break;
1275                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1276                         rc = ulp_mapper_em_tbl_process(parms, tbl);
1277                         break;
1278                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1279                         rc = ulp_mapper_index_tbl_process(parms, tbl);
1280                         break;
1281                 default:
1282                         BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
1283                                     tbl->resource_func);
1284                         return -EINVAL;
1285                 }
1286
1287                 if (rc) {
1288                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1289                                     tbl->resource_func);
1290                         return rc;
1291                 }
1292         }
1293
1294         return rc;
1295 }
1296
1297 static int32_t
1298 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
1299                          struct ulp_flow_db_res_params *res)
1300 {
1301         struct tf *tfp;
1302         int32_t rc = 0;
1303
1304         if (!res || !ulp) {
1305                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
1306                 return -EINVAL;
1307         }
1308
1309         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
1310         if (!tfp) {
1311                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
1312                 return -EINVAL;
1313         }
1314
1315         switch (res->resource_func) {
1316         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1317                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
1318                 break;
1319         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1320                 rc = ulp_mapper_eem_entry_free(ulp, tfp, res);
1321                 break;
1322         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1323                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
1324                 break;
1325         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1326                 rc = ulp_mapper_ident_free(ulp, tfp, res);
1327                 break;
1328         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
1329                 rc = ulp_mapper_mark_free(ulp, res);
1330                 break;
1331         default:
1332                 break;
1333         }
1334
1335         return rc;
1336 }
1337
1338 int32_t
1339 ulp_mapper_resources_free(struct bnxt_ulp_context       *ulp_ctx,
1340                           uint32_t fid,
1341                           enum bnxt_ulp_flow_db_tables  tbl_type)
1342 {
1343         struct ulp_flow_db_res_params   res_parms = { 0 };
1344         int32_t                         rc, trc;
1345
1346         if (!ulp_ctx) {
1347                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1348                 return -EINVAL;
1349         }
1350
1351         /*
1352          * Set the critical resource on the first resource del, then iterate
1353          * while status is good
1354          */
1355         res_parms.critical_resource = 1;
1356         rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms);
1357
1358         if (rc) {
1359                 /*
1360                  * This is unexpected on the first call to resource del.
1361                  * It likely means that the flow did not exist in the flow db.
1362                  */
1363                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
1364                             tbl_type, fid, rc);
1365                 return rc;
1366         }
1367
1368         while (!rc) {
1369                 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
1370                 if (trc)
1371                         /*
1372                          * On fail, we still need to attempt to free the
1373                          * remaining resources.  Don't return
1374                          */
1375                         BNXT_TF_DBG(ERR,
1376                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
1377                                     "] failed rc=%d.\n",
1378                                     tbl_type, fid, res_parms.resource_func,
1379                                     res_parms.resource_hndl, trc);
1380
1381                 /* All subsequent call require the critical_resource be zero */
1382                 res_parms.critical_resource = 0;
1383
1384                 rc = ulp_flow_db_resource_del(ulp_ctx,
1385                                               tbl_type,
1386                                               fid,
1387                                               &res_parms);
1388         }
1389
1390         /* Free the Flow ID since we've removed all resources */
1391         rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid);
1392
1393         return rc;
1394 }
1395
1396 int32_t
1397 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
1398 {
1399         if (!ulp_ctx) {
1400                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1401                 return -EINVAL;
1402         }
1403
1404         return ulp_mapper_resources_free(ulp_ctx,
1405                                          fid,
1406                                          BNXT_ULP_REGULAR_FLOW_TABLE);
1407 }
1408
1409 /* Function to handle the mapping of the Flow to be compatible
1410  * with the underlying hardware.
1411  */
1412 int32_t
1413 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
1414                        struct bnxt_ulp_mapper_create_parms *cparms,
1415                        uint32_t *flowid)
1416 {
1417         struct bnxt_ulp_device_params *device_params;
1418         struct bnxt_ulp_mapper_parms parms;
1419         struct ulp_regfile regfile;
1420         int32_t  rc, trc;
1421
1422         if (!ulp_ctx || !cparms)
1423                 return -EINVAL;
1424
1425         /* Initialize the parms structure */
1426         memset(&parms, 0, sizeof(parms));
1427         parms.act_prop = cparms->act_prop;
1428         parms.act_bitmap = cparms->act;
1429         parms.regfile = &regfile;
1430         parms.hdr_field = cparms->hdr_field;
1431         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
1432         parms.ulp_ctx = ulp_ctx;
1433
1434         /* Get the device id from the ulp context */
1435         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
1436                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
1437                 return -EINVAL;
1438         }
1439
1440         /* Get the action table entry from device id and act context id */
1441         parms.act_tid = cparms->act_tid;
1442         parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id,
1443                                                      parms.act_tid,
1444                                                      &parms.num_atbls);
1445         if (!parms.atbls || !parms.num_atbls) {
1446                 BNXT_TF_DBG(ERR, "No action tables for %d:%d\n",
1447                             parms.dev_id, parms.act_tid);
1448                 return -EINVAL;
1449         }
1450
1451         /* Get the class table entry from device id and act context id */
1452         parms.class_tid = cparms->class_tid;
1453         parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
1454                                                     parms.class_tid,
1455                                                     &parms.num_ctbls);
1456         if (!parms.ctbls || !parms.num_ctbls) {
1457                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1458                             parms.dev_id, parms.class_tid);
1459                 return -EINVAL;
1460         }
1461
1462         /* Get the byte order for the further processing from device params */
1463         device_params = bnxt_ulp_device_params_get(parms.dev_id);
1464         if (!device_params) {
1465                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1466                             parms.dev_id, parms.class_tid);
1467                 return -EINVAL;
1468         }
1469         parms.order = device_params->byte_order;
1470         parms.encap_byte_swap = device_params->encap_byte_swap;
1471
1472         /* initialize the registry file for further processing */
1473         if (!ulp_regfile_init(parms.regfile)) {
1474                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
1475                 return -EINVAL;
1476         }
1477
1478         /* Allocate a Flow ID for attaching all resources for the flow to.
1479          * Once allocated, all errors have to walk the list of resources and
1480          * free each of them.
1481          */
1482         rc = ulp_flow_db_fid_alloc(ulp_ctx,
1483                                    BNXT_ULP_REGULAR_FLOW_TABLE,
1484                                    &parms.fid);
1485         if (rc) {
1486                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
1487                 return rc;
1488         }
1489
1490         /* Process the action template list from the selected action table*/
1491         rc = ulp_mapper_action_tbls_process(&parms);
1492         if (rc) {
1493                 BNXT_TF_DBG(ERR, "action tables failed creation for %d:%d\n",
1494                             parms.dev_id, parms.act_tid);
1495                 goto flow_error;
1496         }
1497
1498         /* All good. Now process the class template */
1499         rc = ulp_mapper_class_tbls_process(&parms);
1500         if (rc) {
1501                 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n",
1502                             parms.dev_id, parms.class_tid);
1503                 goto flow_error;
1504         }
1505
1506         *flowid = parms.fid;
1507
1508         return rc;
1509
1510 flow_error:
1511         /* Free all resources that were allocated during flow creation */
1512         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
1513         if (trc)
1514                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
1515
1516         return rc;
1517 }