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