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