net/bnxt: modify mark manager validity checks
[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 /* Retrieve the cache initialization parameters for the tbl_idx */
70 static struct bnxt_ulp_cache_tbl_params *
71 ulp_mapper_cache_tbl_params_get(uint32_t tbl_idx)
72 {
73         if (tbl_idx >= BNXT_ULP_CACHE_TBL_MAX_SZ)
74                 return NULL;
75
76         return &ulp_cache_tbl_params[tbl_idx];
77 }
78
79 /*
80  * Get the size of the action property for a given index.
81  *
82  * idx [in] The index for the action property
83  *
84  * returns the size of the action property.
85  */
86 static uint32_t
87 ulp_mapper_act_prop_size_get(uint32_t idx)
88 {
89         if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
90                 return 0;
91         return ulp_act_prop_map_table[idx];
92 }
93
94 /*
95  * Get the list of result fields that implement the flow action.
96  * Gets a device dependent list of tables that implement the action template id.
97  *
98  * dev_id [in] The device id of the forwarding element
99  *
100  * tid [in] The action template id that matches the flow
101  *
102  * num_tbls [out] The number of action tables in the returned array
103  *
104  * Returns An array of action tables to implement the flow, or NULL on error.
105  */
106 static struct bnxt_ulp_mapper_act_tbl_info *
107 ulp_mapper_action_tbl_list_get(uint32_t dev_id,
108                                uint32_t tid,
109                                uint32_t *num_tbls)
110 {
111         uint32_t        idx;
112         uint32_t        tidx;
113
114         if (!num_tbls) {
115                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
116                 return NULL;
117         }
118
119         /* template shift and device mask */
120         tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id);
121
122         /* NOTE: Need to have something from template compiler to help validate
123          * range of dev_id and act_tid
124          */
125         idx             = ulp_act_tmpl_list[tidx].start_tbl_idx;
126         *num_tbls       = ulp_act_tmpl_list[tidx].num_tbls;
127
128         return &ulp_act_tbl_list[idx];
129 }
130
131 /** Get a list of classifier tables that implement the flow
132  * Gets a device dependent list of tables that implement the class template id
133  *
134  * dev_id [in] The device id of the forwarding element
135  *
136  * tid [in] The template id that matches the flow
137  *
138  * num_tbls [out] The number of classifier tables in the returned array
139  *
140  * returns An array of classifier tables to implement the flow, or NULL on
141  * error
142  */
143 static struct bnxt_ulp_mapper_class_tbl_info *
144 ulp_mapper_class_tbl_list_get(uint32_t dev_id,
145                               uint32_t tid,
146                               uint32_t *num_tbls)
147 {
148         uint32_t idx;
149         uint32_t tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id);
150
151         if (!num_tbls)
152                 return NULL;
153
154         /* NOTE: Need to have something from template compiler to help validate
155          * range of dev_id and tid
156          */
157         idx             = ulp_class_tmpl_list[tidx].start_tbl_idx;
158         *num_tbls       = ulp_class_tmpl_list[tidx].num_tbls;
159
160         return &ulp_class_tbl_list[idx];
161 }
162
163 /*
164  * Get the list of key fields that implement the flow.
165  *
166  * ctxt [in] The ulp context
167  *
168  * tbl [in] A single table instance to get the key fields from
169  *
170  * num_flds [out] The number of key fields in the returned array
171  *
172  * Returns array of Key fields, or NULL on error.
173  */
174 static struct bnxt_ulp_mapper_class_key_field_info *
175 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
176                           uint32_t *num_flds)
177 {
178         uint32_t idx;
179
180         if (!tbl || !num_flds)
181                 return NULL;
182
183         idx             = tbl->key_start_idx;
184         *num_flds       = tbl->key_num_fields;
185
186         /* NOTE: Need template to provide range checking define */
187         return &ulp_class_key_field_list[idx];
188 }
189
190 /*
191  * Get the list of data fields that implement the flow.
192  *
193  * ctxt [in] The ulp context
194  *
195  * tbl [in] A single table instance to get the data fields from
196  *
197  * num_flds [out] The number of data fields in the returned array.
198  *
199  * Returns array of data fields, or NULL on error.
200  */
201 static struct bnxt_ulp_mapper_result_field_info *
202 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
203                              uint32_t *num_flds)
204 {
205         uint32_t idx;
206
207         if (!tbl || !num_flds)
208                 return NULL;
209
210         idx             = tbl->result_start_idx;
211         *num_flds       = tbl->result_num_fields;
212
213         /* NOTE: Need template to provide range checking define */
214         return &ulp_class_result_field_list[idx];
215 }
216
217 /*
218  * Get the list of result fields that implement the flow action.
219  *
220  * tbl [in] A single table instance to get the results fields
221  * from num_flds [out] The number of data fields in the returned
222  * array.
223  *
224  * Returns array of data fields, or NULL on error.
225  */
226 static struct bnxt_ulp_mapper_result_field_info *
227 ulp_mapper_act_result_fields_get(struct bnxt_ulp_mapper_act_tbl_info *tbl,
228                                  uint32_t *num_rslt_flds,
229                                  uint32_t *num_encap_flds)
230 {
231         uint32_t idx;
232
233         if (!tbl || !num_rslt_flds || !num_encap_flds)
234                 return NULL;
235
236         idx             = tbl->result_start_idx;
237         *num_rslt_flds  = tbl->result_num_fields;
238         *num_encap_flds = tbl->encap_num_fields;
239
240         /* NOTE: Need template to provide range checking define */
241         return &ulp_act_result_field_list[idx];
242 }
243
244 /*
245  * Get the list of ident fields that implement the flow
246  *
247  * tbl [in] A single table instance to get the ident fields from
248  *
249  * num_flds [out] The number of ident fields in the returned array
250  *
251  * returns array of ident fields, or NULL on error
252  */
253 static struct bnxt_ulp_mapper_ident_info *
254 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
255                             uint32_t *num_flds)
256 {
257         uint32_t idx;
258
259         if (!tbl || !num_flds)
260                 return NULL;
261
262         idx = tbl->ident_start_idx;
263         *num_flds = tbl->ident_nums;
264
265         /* NOTE: Need template to provide range checking define */
266         return &ulp_ident_list[idx];
267 }
268
269 static struct bnxt_ulp_mapper_cache_entry *
270 ulp_mapper_cache_entry_get(struct bnxt_ulp_context *ulp,
271                            enum bnxt_ulp_cache_tbl_id id,
272                            uint16_t key)
273 {
274         struct bnxt_ulp_mapper_data *mapper_data;
275
276         mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp);
277         if (!mapper_data || !mapper_data->cache_tbl[id]) {
278                 BNXT_TF_DBG(ERR, "Unable to acquire the cache tbl (%d)\n", id);
279                 return NULL;
280         }
281
282         return &mapper_data->cache_tbl[id][key];
283 }
284
285 /*
286  * Concatenates the tbl_type and tbl_id into a 32bit value for storing in the
287  * resource_type.  This is done to conserve memory since both the tbl_type and
288  * tbl_id are 16bit.
289  */
290 static inline void
291 ulp_mapper_cache_res_type_set(struct ulp_flow_db_res_params *res,
292                               uint16_t tbl_type,
293                               uint16_t tbl_id)
294 {
295         res->resource_type =
296                 ((uint32_t)tbl_id << ULP_MAPPER_CACHE_RES_TBL_ID_SHFT) |
297                 ((uint32_t)tbl_type << ULP_MAPPER_CACHE_RES_TBL_TYPE_SHFT);
298 }
299
300 /* Extracts the tbl_type and tbl_id from the 32bit resource type. */
301 static inline void
302 ulp_mapper_cache_res_type_get(struct ulp_flow_db_res_params *res,
303                               uint16_t *tbl_type,
304                               uint16_t *tbl_id)
305 {
306         *tbl_type = (uint16_t)((res->resource_type >>
307                                 ULP_MAPPER_CACHE_RES_TBL_TYPE_SHFT) &
308                                ULP_MAPPER_CACHE_RES_TBL_MASK);
309         *tbl_id = (uint16_t)((res->resource_type >>
310                               ULP_MAPPER_CACHE_RES_TBL_ID_SHFT) &
311                              ULP_MAPPER_CACHE_RES_TBL_MASK);
312 }
313
314 static int32_t
315 ulp_mapper_cache_entry_free(struct bnxt_ulp_context *ulp,
316                            struct tf *tfp,
317                            struct ulp_flow_db_res_params *res)
318 {
319         struct bnxt_ulp_mapper_cache_entry *cache_entry;
320         struct tf_free_identifier_parms ident_parms;
321         struct tf_free_tcam_entry_parms tcam_parms;
322         uint16_t table_id, table_type;
323         int32_t rc, trc, i;
324
325         /*
326          * The table id, used for cache, and table_type, used for tcam, are
327          * both encoded within the resource.  We must first extract them to
328          * formulate the args for tf calls.
329          */
330         ulp_mapper_cache_res_type_get(res, &table_type, &table_id);
331
332         cache_entry = ulp_mapper_cache_entry_get(ulp, table_id,
333                                                  (uint16_t)res->resource_hndl);
334         if (!cache_entry || !cache_entry->ref_count) {
335                 BNXT_TF_DBG(ERR, "Cache entry (%d:%d) not valid on free.\n",
336                             table_id, (uint16_t)res->resource_hndl);
337                 return -EINVAL;
338         }
339
340         /*
341          * See if we need to delete the entry.  The tcam and identifiers are all
342          * tracked by the cached entries reference count.  All are deleted when
343          * the reference count hit zero.
344          */
345         cache_entry->ref_count--;
346         if (cache_entry->ref_count)
347                 return 0;
348
349         /*
350          * Need to delete the tcam entry and the allocated identifiers.
351          * In the event of a failure, need to try to delete the remaining
352          * resources before returning error.
353          */
354         tcam_parms.dir = res->direction;
355         tcam_parms.tcam_tbl_type = table_type;
356         tcam_parms.idx = cache_entry->tcam_idx;
357         rc = tf_free_tcam_entry(tfp, &tcam_parms);
358         if (rc)
359                 BNXT_TF_DBG(ERR, "Failed to free tcam [%d][%s][0x%04x] rc=%d\n",
360                             table_type,
361                             (res->direction == TF_DIR_RX) ? "RX" : "TX",
362                             tcam_parms.idx, rc);
363
364         /*
365          * Free the identifiers associated with the tcam entry.  Entries with
366          * negative one are considered uninitialized.
367          */
368         for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) {
369                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
370                         continue;
371
372                 ident_parms.dir = res->direction;
373                 ident_parms.ident_type = cache_entry->ident_types[i];
374                 ident_parms.id = cache_entry->idents[i];
375                 trc = tf_free_identifier(tfp, &ident_parms);
376                 if (trc) {
377                         BNXT_TF_DBG(ERR, "Failed to free identifier "
378                                     "[%d][%s][0x%04x] rc=%d\n",
379                                     ident_parms.ident_type,
380                                     (res->direction == TF_DIR_RX) ? "RX" : "TX",
381                                     ident_parms.id, trc);
382                         rc = trc;
383                 }
384         }
385
386         return rc;
387 }
388
389 static inline int32_t
390 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp  __rte_unused,
391                            struct tf *tfp,
392                            struct ulp_flow_db_res_params *res)
393 {
394         struct tf_free_tcam_entry_parms fparms = {
395                 .dir            = res->direction,
396                 .tcam_tbl_type  = res->resource_type,
397                 .idx            = (uint16_t)res->resource_hndl
398         };
399
400         return tf_free_tcam_entry(tfp, &fparms);
401 }
402
403 static inline int32_t
404 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
405                             struct tf *tfp,
406                             struct ulp_flow_db_res_params *res)
407 {
408         struct tf_free_tbl_entry_parms fparms = {
409                 .dir    = res->direction,
410                 .type   = res->resource_type,
411                 .idx    = (uint32_t)res->resource_hndl
412         };
413
414         /*
415          * Just set the table scope, it will be ignored if not necessary
416          * by the tf_free_tbl_entry
417          */
418         bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
419
420         return tf_free_tbl_entry(tfp, &fparms);
421 }
422
423 static inline int32_t
424 ulp_mapper_eem_entry_free(struct bnxt_ulp_context *ulp,
425                           struct tf *tfp,
426                           struct ulp_flow_db_res_params *res)
427 {
428         struct tf_delete_em_entry_parms fparms = { 0 };
429         int32_t rc;
430
431         fparms.dir              = res->direction;
432         fparms.mem              = TF_MEM_EXTERNAL;
433         fparms.flow_handle      = res->resource_hndl;
434
435         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
436         if (rc) {
437                 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
438                 return -EINVAL;
439         }
440
441         return tf_delete_em_entry(tfp, &fparms);
442 }
443
444 static inline int32_t
445 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
446                       struct tf *tfp,
447                       struct ulp_flow_db_res_params *res)
448 {
449         struct tf_free_identifier_parms fparms = {
450                 .dir            = res->direction,
451                 .ident_type     = res->resource_type,
452                 .id             = (uint16_t)res->resource_hndl
453         };
454
455         return tf_free_identifier(tfp, &fparms);
456 }
457
458 static inline int32_t
459 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
460                      struct ulp_flow_db_res_params *res)
461 {
462         return ulp_mark_db_mark_del(ulp,
463                                     res->resource_type,
464                                     res->resource_hndl);
465 }
466
467 /*
468  * Process the identifier instruction and either store it in the flow database
469  * or return it in the val (if not NULL) on success.  If val is NULL, the
470  * identifier is to be stored in the flow database.
471  */
472 static int32_t
473 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
474                          struct bnxt_ulp_mapper_class_tbl_info *tbl,
475                          struct bnxt_ulp_mapper_ident_info *ident,
476                          uint16_t *val)
477 {
478         struct ulp_flow_db_res_params   fid_parms;
479         uint64_t id = 0;
480         int32_t idx;
481         struct tf_alloc_identifier_parms iparms = { 0 };
482         struct tf_free_identifier_parms free_parms = { 0 };
483         struct tf *tfp;
484         int rc;
485
486         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
487         if (!tfp) {
488                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
489                 return -EINVAL;
490         }
491
492         idx = ident->regfile_wr_idx;
493
494         iparms.ident_type = ident->ident_type;
495         iparms.dir = tbl->direction;
496
497         rc = tf_alloc_identifier(tfp, &iparms);
498         if (rc) {
499                 BNXT_TF_DBG(ERR, "Alloc ident %s:%d failed.\n",
500                             (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
501                             iparms.ident_type);
502                 return rc;
503         }
504
505         id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
506         if (!ulp_regfile_write(parms->regfile, idx, id)) {
507                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
508                 rc = -EINVAL;
509                 /* Need to free the identifier, so goto error */
510                 goto error;
511         }
512
513         /* Link the resource to the flow in the flow db */
514         if (!val) {
515                 memset(&fid_parms, 0, sizeof(fid_parms));
516                 fid_parms.direction             = tbl->direction;
517                 fid_parms.resource_func = ident->resource_func;
518                 fid_parms.resource_type = ident->ident_type;
519                 fid_parms.resource_hndl = iparms.id;
520                 fid_parms.critical_resource     = 0;
521
522                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
523                                               parms->tbl_idx,
524                                               parms->fid,
525                                               &fid_parms);
526                 if (rc) {
527                         BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
528                                     rc);
529                         /* Need to free the identifier, so goto error */
530                         goto error;
531                 }
532         } else {
533                 *val = iparms.id;
534         }
535
536         return 0;
537
538 error:
539         /* Need to free the identifier */
540         free_parms.dir          = tbl->direction;
541         free_parms.ident_type   = ident->ident_type;
542         free_parms.id           = iparms.id;
543
544         (void)tf_free_identifier(tfp, &free_parms);
545
546         BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
547                     ident->description,
548                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX");
549         return rc;
550 }
551
552 static int32_t
553 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
554                                 enum tf_dir dir,
555                                 struct bnxt_ulp_mapper_result_field_info *fld,
556                                 struct ulp_blob *blob,
557                                 const char *name)
558 {
559         uint16_t idx, size_idx;
560         uint8_t  *val = NULL;
561         uint64_t regval;
562         uint32_t val_size = 0, field_size = 0;
563
564         switch (fld->result_opcode) {
565         case BNXT_ULP_RESULT_OPC_SET_TO_CONSTANT:
566                 val = fld->result_operand;
567                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
568                         BNXT_TF_DBG(ERR, "%s failed to add field\n", name);
569                         return -EINVAL;
570                 }
571                 break;
572         case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP:
573                 if (!ulp_operand_read(fld->result_operand,
574                                       (uint8_t *)&idx, sizeof(uint16_t))) {
575                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
576                         return -EINVAL;
577                 }
578                 idx = tfp_be_to_cpu_16(idx);
579
580                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
581                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
582                         return -EINVAL;
583                 }
584                 val = &parms->act_prop->act_details[idx];
585                 field_size = ulp_mapper_act_prop_size_get(idx);
586                 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
587                         field_size  = field_size -
588                             ((fld->field_bit_size + 7) / 8);
589                         val += field_size;
590                 }
591                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
592                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
593                         return -EINVAL;
594                 }
595                 break;
596         case BNXT_ULP_RESULT_OPC_SET_TO_ENCAP_ACT_PROP_SZ:
597                 if (!ulp_operand_read(fld->result_operand,
598                                       (uint8_t *)&idx, sizeof(uint16_t))) {
599                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
600                         return -EINVAL;
601                 }
602                 idx = tfp_be_to_cpu_16(idx);
603
604                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
605                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
606                         return -EINVAL;
607                 }
608                 val = &parms->act_prop->act_details[idx];
609
610                 /* get the size index next */
611                 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
612                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
613                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
614                         return -EINVAL;
615                 }
616                 size_idx = tfp_be_to_cpu_16(size_idx);
617
618                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
619                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
620                         return -EINVAL;
621                 }
622                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
623                        sizeof(uint32_t));
624                 val_size = tfp_be_to_cpu_32(val_size);
625                 val_size = ULP_BYTE_2_BITS(val_size);
626                 ulp_blob_push_encap(blob, val, val_size);
627                 break;
628         case BNXT_ULP_RESULT_OPC_SET_TO_REGFILE:
629                 if (!ulp_operand_read(fld->result_operand,
630                                       (uint8_t *)&idx, sizeof(uint16_t))) {
631                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
632                         return -EINVAL;
633                 }
634
635                 idx = tfp_be_to_cpu_16(idx);
636                 /* Uninitialized regfile entries return 0 */
637                 if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
638                         BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
639                                     name, idx);
640                         return -EINVAL;
641                 }
642
643                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
644                 if (!val) {
645                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
646                         return -EINVAL;
647                 }
648                 break;
649         case BNXT_ULP_RESULT_OPC_SET_TO_DEF_REGFILE:
650                 if (!ulp_operand_read(fld->result_operand,
651                                       (uint8_t *)&idx,
652                                       sizeof(uint16_t))) {
653                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
654                         return -EINVAL;
655                 }
656                 idx = tfp_be_to_cpu_16(idx);
657                 if (ulp_mapper_def_regfile_read(parms->mapper_data,
658                                                 dir,
659                                                 idx, &regval)) {
660                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
661                                     name, idx);
662                         return -EINVAL;
663                 }
664                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
665                 if (!val) {
666                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
667                         return -EINVAL;
668                 }
669                 break;
670         default:
671                 return -EINVAL;
672         }
673         return 0;
674 }
675
676 /* Function to alloc action record and set the table. */
677 static int32_t
678 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
679                                  enum tf_dir dir,
680                                  struct bnxt_ulp_mapper_class_key_field_info *f,
681                                  struct ulp_blob *blob,
682                                  uint8_t is_key,
683                                  const char *name)
684 {
685         uint64_t val64;
686         uint16_t idx, bitlen;
687         uint32_t opcode;
688         uint8_t *operand;
689         struct ulp_regfile *regfile = parms->regfile;
690         uint8_t *val = NULL;
691         struct bnxt_ulp_mapper_class_key_field_info *fld = f;
692         uint32_t field_size;
693
694         if (is_key) {
695                 operand = fld->spec_operand;
696                 opcode  = fld->spec_opcode;
697         } else {
698                 operand = fld->mask_operand;
699                 opcode  = fld->mask_opcode;
700         }
701
702         bitlen = fld->field_bit_size;
703
704         switch (opcode) {
705         case BNXT_ULP_SPEC_OPC_SET_TO_CONSTANT:
706                 val = operand;
707                 if (!ulp_blob_push(blob, val, bitlen)) {
708                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
709                         return -EINVAL;
710                 }
711                 break;
712         case BNXT_ULP_SPEC_OPC_ADD_PAD:
713                 if (!ulp_blob_pad_push(blob, bitlen)) {
714                         BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
715                         return -EINVAL;
716                 }
717
718                 break;
719         case BNXT_ULP_SPEC_OPC_SET_TO_HDR_FIELD:
720                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
721                                       sizeof(uint16_t))) {
722                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
723                         return -EINVAL;
724                 }
725                 idx = tfp_be_to_cpu_16(idx);
726                 if (is_key)
727                         val = parms->hdr_field[idx].spec;
728                 else
729                         val = parms->hdr_field[idx].mask;
730
731                 /*
732                  * Need to account for how much data was pushed to the header
733                  * field vs how much is to be inserted in the key/mask.
734                  */
735                 field_size = parms->hdr_field[idx].size;
736                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
737                         field_size  = field_size - ((bitlen + 7) / 8);
738                         val += field_size;
739                 }
740
741                 if (!ulp_blob_push(blob, val, bitlen)) {
742                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
743                         return -EINVAL;
744                 }
745                 break;
746         case BNXT_ULP_SPEC_OPC_SET_TO_REGFILE:
747                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
748                                       sizeof(uint16_t))) {
749                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
750                         return -EINVAL;
751                 }
752                 idx = tfp_be_to_cpu_16(idx);
753
754                 if (!ulp_regfile_read(regfile, idx, &val64)) {
755                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
756                                     name, idx);
757                         return -EINVAL;
758                 }
759
760                 val = ulp_blob_push_64(blob, &val64, bitlen);
761                 if (!val) {
762                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
763                         return -EINVAL;
764                 }
765                 break;
766         case BNXT_ULP_SPEC_OPC_SET_TO_DEF_REGFILE:
767                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
768                                       sizeof(uint16_t))) {
769                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
770                         return -EINVAL;
771                 }
772                 idx = tfp_be_to_cpu_16(idx);
773                 if (ulp_mapper_def_regfile_read(parms->mapper_data,
774                                                 dir,
775                                                 idx, &val64)) {
776                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
777                                     name, idx);
778                         return -EINVAL;
779                 }
780                 val = ulp_blob_push_64(blob, &val64, bitlen);
781                 if (!val) {
782                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
783                         return -EINVAL;
784                 }
785                 break;
786         default:
787                 break;
788         }
789
790         return 0;
791 }
792
793 /* Function to alloc action record and set the table. */
794 static int32_t
795 ulp_mapper_action_alloc_and_set(struct bnxt_ulp_mapper_parms *parms,
796                                 struct ulp_blob *blob)
797 {
798         struct ulp_flow_db_res_params           fid_parms;
799         struct tf_alloc_tbl_entry_parms         alloc_parms = { 0 };
800         struct tf_free_tbl_entry_parms          free_parms = { 0 };
801         struct bnxt_ulp_mapper_act_tbl_info     *atbls = parms->atbls;
802         int32_t                                 rc = 0;
803         int32_t trc;
804         uint64_t                                idx;
805         uint32_t tbl_scope_id;
806
807         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
808
809         /* Set the allocation parameters for the table*/
810         alloc_parms.dir = atbls->direction;
811         alloc_parms.type = atbls->table_type;
812         alloc_parms.search_enable = atbls->srch_b4_alloc;
813         alloc_parms.result = ulp_blob_data_get(blob,
814                                                &alloc_parms.result_sz_in_bytes);
815         alloc_parms.tbl_scope_id = tbl_scope_id;
816         if (!alloc_parms.result) {
817                 BNXT_TF_DBG(ERR, "blob is not populated\n");
818                 return -EINVAL;
819         }
820
821         rc = tf_alloc_tbl_entry(parms->tfp, &alloc_parms);
822         if (rc) {
823                 BNXT_TF_DBG(ERR, "table type= [%d] dir = [%s] alloc failed\n",
824                             alloc_parms.type,
825                             (alloc_parms.dir == TF_DIR_RX) ? "RX" : "TX");
826                 return rc;
827         }
828
829         /* Need to calculate the idx for the result record */
830         uint64_t tmpidx = alloc_parms.idx;
831
832         if (atbls->table_type == TF_TBL_TYPE_EXT)
833                 tmpidx = TF_ACT_REC_OFFSET_2_PTR(alloc_parms.idx);
834         else
835                 tmpidx = alloc_parms.idx;
836
837         idx = tfp_cpu_to_be_64(tmpidx);
838
839         /* Store the allocated index for future use in the regfile */
840         rc = ulp_regfile_write(parms->regfile, atbls->regfile_wr_idx, idx);
841         if (!rc) {
842                 BNXT_TF_DBG(ERR, "regfile[%d] write failed\n",
843                             atbls->regfile_wr_idx);
844                 rc = -EINVAL;
845                 goto error;
846         }
847
848         /*
849          * The set_tbl_entry API if search is not enabled or searched entry
850          * is not found.
851          */
852         if (!atbls->srch_b4_alloc || !alloc_parms.hit) {
853                 struct tf_set_tbl_entry_parms set_parm = { 0 };
854                 uint16_t        length;
855
856                 set_parm.dir    = atbls->direction;
857                 set_parm.type   = atbls->table_type;
858                 set_parm.idx    = alloc_parms.idx;
859                 set_parm.data   = ulp_blob_data_get(blob, &length);
860                 set_parm.data_sz_in_bytes = length / 8;
861
862                 if (set_parm.type == TF_TBL_TYPE_EXT)
863                         set_parm.tbl_scope_id = tbl_scope_id;
864
865                 /* set the table entry */
866                 rc = tf_set_tbl_entry(parms->tfp, &set_parm);
867                 if (rc) {
868                         BNXT_TF_DBG(ERR, "table[%d][%s][%d] set failed\n",
869                                     set_parm.type,
870                                     (set_parm.dir == TF_DIR_RX) ? "RX" : "TX",
871                                     set_parm.idx);
872                         goto error;
873                 }
874         }
875
876         /* Link the resource to the flow in the flow db */
877         memset(&fid_parms, 0, sizeof(fid_parms));
878         fid_parms.direction             = atbls->direction;
879         fid_parms.resource_func         = atbls->resource_func;
880         fid_parms.resource_type         = atbls->table_type;
881         fid_parms.resource_hndl         = alloc_parms.idx;
882         fid_parms.critical_resource     = 0;
883
884         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
885                                       parms->tbl_idx,
886                                       parms->fid,
887                                       &fid_parms);
888         if (rc) {
889                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
890                             rc);
891                 rc = -EINVAL;
892                 goto error;
893         }
894
895         return 0;
896 error:
897
898         free_parms.dir  = alloc_parms.dir;
899         free_parms.type = alloc_parms.type;
900         free_parms.idx  = alloc_parms.idx;
901
902         trc = tf_free_tbl_entry(parms->tfp, &free_parms);
903         if (trc)
904                 BNXT_TF_DBG(ERR, "Failed to free table entry on failure\n");
905
906         return rc;
907 }
908
909 /*
910  * Function to process the action Info. Iterate through the list
911  * action info templates and process it.
912  */
913 static int32_t
914 ulp_mapper_action_info_process(struct bnxt_ulp_mapper_parms *parms,
915                                struct bnxt_ulp_mapper_act_tbl_info *tbl)
916 {
917         struct ulp_blob                                 blob;
918         struct bnxt_ulp_mapper_result_field_info        *flds, *fld;
919         uint32_t                                        num_flds = 0;
920         uint32_t                                        encap_flds = 0;
921         uint32_t                                        i;
922         int32_t                                         rc;
923         uint16_t                                        bit_size;
924
925         if (!tbl || !parms->act_prop || !parms->act_bitmap || !parms->regfile)
926                 return -EINVAL;
927
928         /* use the max size if encap is enabled */
929         if (tbl->encap_num_fields)
930                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
931         else
932                 bit_size = tbl->result_bit_size;
933         if (!ulp_blob_init(&blob, bit_size, parms->order)) {
934                 BNXT_TF_DBG(ERR, "action blob init failed\n");
935                 return -EINVAL;
936         }
937
938         flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, &encap_flds);
939         if (!flds || !num_flds) {
940                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
941                 return -EINVAL;
942         }
943
944         for (i = 0; i < (num_flds + encap_flds); i++) {
945                 fld = &flds[i];
946                 rc = ulp_mapper_result_field_process(parms,
947                                                      tbl->direction,
948                                                      fld,
949                                                      &blob,
950                                                      "Action");
951                 if (rc) {
952                         BNXT_TF_DBG(ERR, "Action field failed\n");
953                         return rc;
954                 }
955                 /* set the swap index if 64 bit swap is enabled */
956                 if (parms->encap_byte_swap && encap_flds) {
957                         if ((i + 1) == num_flds)
958                                 ulp_blob_encap_swap_idx_set(&blob);
959                         /* if 64 bit swap is enabled perform the 64bit swap */
960                         if ((i + 1) == (num_flds + encap_flds))
961                                 ulp_blob_perform_encap_swap(&blob);
962                 }
963         }
964
965         rc = ulp_mapper_action_alloc_and_set(parms, &blob);
966         return rc;
967 }
968
969 static int32_t
970 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
971                             struct bnxt_ulp_mapper_class_tbl_info *tbl)
972 {
973         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
974         struct ulp_blob key, mask, data;
975         uint32_t i, num_kflds;
976         struct tf *tfp;
977         int32_t rc, trc;
978         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
979         struct tf_set_tcam_entry_parms sparms           = { 0 };
980         struct ulp_flow_db_res_params   fid_parms       = { 0 };
981         struct tf_free_tcam_entry_parms free_parms      = { 0 };
982         uint32_t hit = 0;
983         uint16_t tmplen = 0;
984
985         /* Skip this if was handled by the cache. */
986         if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) {
987                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
988                 return 0;
989         }
990
991         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
992         if (!tfp) {
993                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
994                 return -EINVAL;
995         }
996
997         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
998         if (!kflds || !num_kflds) {
999                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1000                 return -EINVAL;
1001         }
1002
1003         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order) ||
1004             !ulp_blob_init(&mask, tbl->key_bit_size, parms->order) ||
1005             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1006                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1007                 return -EINVAL;
1008         }
1009
1010         /* create the key/mask */
1011         /*
1012          * NOTE: The WC table will require some kind of flag to handle the
1013          * mode bits within the key/mask
1014          */
1015         for (i = 0; i < num_kflds; i++) {
1016                 /* Setup the key */
1017                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1018                                                       &kflds[i],
1019                                                       &key, 1, "TCAM Key");
1020                 if (rc) {
1021                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1022                         return rc;
1023                 }
1024
1025                 /* Setup the mask */
1026                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1027                                                       &kflds[i],
1028                                                       &mask, 0, "TCAM Mask");
1029                 if (rc) {
1030                         BNXT_TF_DBG(ERR, "Mask field set failed.\n");
1031                         return rc;
1032                 }
1033         }
1034
1035         aparms.dir              = tbl->direction;
1036         aparms.tcam_tbl_type    = tbl->table_type;
1037         aparms.search_enable    = tbl->srch_b4_alloc;
1038         aparms.key_sz_in_bits   = tbl->key_bit_size;
1039         aparms.key              = ulp_blob_data_get(&key, &tmplen);
1040         if (tbl->key_bit_size != tmplen) {
1041                 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1042                             tmplen, tbl->key_bit_size);
1043                 return -EINVAL;
1044         }
1045
1046         aparms.mask             = ulp_blob_data_get(&mask, &tmplen);
1047         if (tbl->key_bit_size != tmplen) {
1048                 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1049                             tmplen, tbl->key_bit_size);
1050                 return -EINVAL;
1051         }
1052
1053         aparms.priority         = tbl->priority;
1054
1055         /*
1056          * All failures after this succeeds require the entry to be freed.
1057          * cannot return directly on failure, but needs to goto error
1058          */
1059         rc = tf_alloc_tcam_entry(tfp, &aparms);
1060         if (rc) {
1061                 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1062                 return rc;
1063         }
1064
1065         hit = aparms.hit;
1066
1067         /* Build the result */
1068         if (!tbl->srch_b4_alloc || !hit) {
1069                 struct bnxt_ulp_mapper_result_field_info *dflds;
1070                 struct bnxt_ulp_mapper_ident_info *idents;
1071                 uint32_t num_dflds, num_idents;
1072
1073                 /*
1074                  * Since the cache entry is responsible for allocating
1075                  * identifiers when in use, allocate the identifiers only
1076                  * during normal processing.
1077                  */
1078                 if (parms->tcam_tbl_opc ==
1079                     BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1080                         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1081
1082                         for (i = 0; i < num_idents; i++) {
1083                                 rc = ulp_mapper_ident_process(parms, tbl,
1084                                                               &idents[i], NULL);
1085                                 /* Already logged the error, just return */
1086                                 if (rc)
1087                                         goto error;
1088                         }
1089                 }
1090
1091                 /* Create the result data blob */
1092                 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
1093                 if (!dflds || !num_dflds) {
1094                         BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1095                         rc = -EINVAL;
1096                         goto error;
1097                 }
1098
1099                 for (i = 0; i < num_dflds; i++) {
1100                         rc = ulp_mapper_result_field_process(parms,
1101                                                              tbl->direction,
1102                                                              &dflds[i],
1103                                                              &data,
1104                                                              "TCAM Result");
1105                         if (rc) {
1106                                 BNXT_TF_DBG(ERR, "Failed to set data fields\n");
1107                                 goto error;
1108                         }
1109                 }
1110
1111                 sparms.dir              = aparms.dir;
1112                 sparms.tcam_tbl_type    = aparms.tcam_tbl_type;
1113                 sparms.idx              = aparms.idx;
1114                 /* Already verified the key/mask lengths */
1115                 sparms.key              = ulp_blob_data_get(&key, &tmplen);
1116                 sparms.mask             = ulp_blob_data_get(&mask, &tmplen);
1117                 sparms.key_sz_in_bits   = tbl->key_bit_size;
1118                 sparms.result           = ulp_blob_data_get(&data, &tmplen);
1119
1120                 if (tbl->result_bit_size != tmplen) {
1121                         BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1122                                     tmplen, tbl->result_bit_size);
1123                         rc = -EINVAL;
1124                         goto error;
1125                 }
1126                 sparms.result_sz_in_bits = tbl->result_bit_size;
1127
1128                 rc = tf_set_tcam_entry(tfp, &sparms);
1129                 if (rc) {
1130                         BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n",
1131                                     sparms.tcam_tbl_type,
1132                                     (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
1133                                     sparms.idx);
1134                         goto error;
1135                 }
1136
1137                 /* Update cache with TCAM index if the was cache allocated. */
1138                 if (parms->tcam_tbl_opc ==
1139                     BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC) {
1140                         if (!parms->cache_ptr) {
1141                                 BNXT_TF_DBG(ERR, "Unable to update cache");
1142                                 rc = -EINVAL;
1143                                 goto error;
1144                         }
1145                         parms->cache_ptr->tcam_idx = aparms.idx;
1146                 }
1147
1148         } else {
1149                 BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n");
1150                 rc = -EINVAL;
1151                 goto error;
1152         }
1153
1154         /*
1155          * Only link the entry to the flow db in the event that cache was not
1156          * used.
1157          */
1158         if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1159                 fid_parms.direction = tbl->direction;
1160                 fid_parms.resource_func = tbl->resource_func;
1161                 fid_parms.resource_type = tbl->table_type;
1162                 fid_parms.critical_resource = tbl->critical_resource;
1163                 fid_parms.resource_hndl = aparms.idx;
1164                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1165                                               parms->tbl_idx,
1166                                               parms->fid,
1167                                               &fid_parms);
1168                 if (rc) {
1169                         BNXT_TF_DBG(ERR,
1170                                     "Failed to link resource to flow rc = %d\n",
1171                                     rc);
1172                         /* Need to free the identifier, so goto error */
1173                         goto error;
1174                 }
1175         } else {
1176                 /*
1177                  * Reset the tcam table opcode to normal in case the next tcam
1178                  * entry does not use cache.
1179                  */
1180                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1181                 parms->cache_ptr = NULL;
1182         }
1183
1184         return 0;
1185 error:
1186         parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1187         free_parms.dir                  = tbl->direction;
1188         free_parms.tcam_tbl_type        = tbl->table_type;
1189         free_parms.idx                  = aparms.idx;
1190         trc = tf_free_tcam_entry(tfp, &free_parms);
1191         if (trc)
1192                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1193                             tbl->table_type, tbl->direction, aparms.idx);
1194
1195         return rc;
1196 }
1197
1198 static int32_t
1199 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1200                           struct bnxt_ulp_mapper_class_tbl_info *tbl)
1201 {
1202         struct bnxt_ulp_mapper_class_key_field_info     *kflds;
1203         struct bnxt_ulp_mapper_result_field_info *dflds;
1204         struct ulp_blob key, data;
1205         uint32_t i, num_kflds, num_dflds;
1206         uint16_t tmplen;
1207         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1208         struct ulp_rte_act_prop  *a_prop = parms->act_prop;
1209         struct ulp_flow_db_res_params   fid_parms = { 0 };
1210         struct tf_insert_em_entry_parms iparms = { 0 };
1211         struct tf_delete_em_entry_parms free_parms = { 0 };
1212         int32_t trc;
1213         int32_t rc = 0;
1214
1215         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1216         if (!kflds || !num_kflds) {
1217                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1218                 return -EINVAL;
1219         }
1220
1221         /* Initialize the key/result blobs */
1222         if (!ulp_blob_init(&key, tbl->blob_key_bit_size, parms->order) ||
1223             !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1224                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1225                 return -EINVAL;
1226         }
1227
1228         /* create the key */
1229         for (i = 0; i < num_kflds; i++) {
1230                 /* Setup the key */
1231                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1232                                                       &kflds[i],
1233                                                       &key, 1, "EM Key");
1234                 if (rc) {
1235                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1236                         return rc;
1237                 }
1238         }
1239
1240         /*
1241          * TBD: Normally should process identifiers in case of using recycle or
1242          * loopback.  Not supporting recycle for now.
1243          */
1244
1245         /* Create the result data blob */
1246         dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
1247         if (!dflds || !num_dflds) {
1248                 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1249                 return -EINVAL;
1250         }
1251
1252         for (i = 0; i < num_dflds; i++) {
1253                 struct bnxt_ulp_mapper_result_field_info *fld;
1254
1255                 fld = &dflds[i];
1256
1257                 rc = ulp_mapper_result_field_process(parms,
1258                                                      tbl->direction,
1259                                                      fld,
1260                                                      &data,
1261                                                      "EM Result");
1262                 if (rc) {
1263                         BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
1264                         return rc;
1265                 }
1266         }
1267
1268         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1269                                              &iparms.tbl_scope_id);
1270         if (rc) {
1271                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1272                 return rc;
1273         }
1274
1275         /*
1276          * NOTE: the actual blob size will differ from the size in the tbl
1277          * entry due to the padding.
1278          */
1279         iparms.dup_check                = 0;
1280         iparms.dir                      = tbl->direction;
1281         iparms.mem                      = tbl->mem;
1282         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1283         iparms.key_sz_in_bits           = tbl->key_bit_size;
1284         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1285         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1286
1287         rc = tf_insert_em_entry(tfp, &iparms);
1288         if (rc) {
1289                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1290                 return rc;
1291         }
1292
1293         if (tbl->mark_enable &&
1294             ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1295                              BNXT_ULP_ACTION_BIT_MARK)) {
1296                 uint32_t val, mark, gfid, flag;
1297                 /* TBD: Need to determine if GFID is enabled globally */
1298                 if (sizeof(val) != BNXT_ULP_ACT_PROP_SZ_MARK) {
1299                         BNXT_TF_DBG(ERR, "Mark size (%d) != expected (%zu)\n",
1300                                     BNXT_ULP_ACT_PROP_SZ_MARK, sizeof(val));
1301                         rc = -EINVAL;
1302                         goto error;
1303                 }
1304
1305                 memcpy(&val,
1306                        &a_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1307                        sizeof(val));
1308
1309                 mark = tfp_be_to_cpu_32(val);
1310
1311                 TF_GET_GFID_FROM_FLOW_ID(iparms.flow_id, gfid);
1312                 flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1313                 rc = ulp_mark_db_mark_add(parms->ulp_ctx,
1314                                           flag,
1315                                           gfid,
1316                                           mark);
1317                 if (rc) {
1318                         BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1319                         goto error;
1320                 }
1321
1322                 /*
1323                  * Link the mark resource to the flow in the flow db
1324                  * The mark is never the critical resource, so it is 0.
1325                  */
1326                 memset(&fid_parms, 0, sizeof(fid_parms));
1327                 fid_parms.direction     = tbl->direction;
1328                 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1329                 fid_parms.resource_type = flag;
1330                 fid_parms.resource_hndl = gfid;
1331                 fid_parms.critical_resource = 0;
1332
1333                 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1334                                               parms->tbl_idx,
1335                                               parms->fid,
1336                                               &fid_parms);
1337                 if (rc) {
1338                         BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1339                                     rc);
1340                         /* Need to free the identifier, so goto error */
1341                         goto error;
1342                 }
1343         }
1344
1345         /* Link the EM resource to the flow in the flow db */
1346         memset(&fid_parms, 0, sizeof(fid_parms));
1347         fid_parms.direction             = tbl->direction;
1348         fid_parms.resource_func         = tbl->resource_func;
1349         fid_parms.resource_type         = tbl->table_type;
1350         fid_parms.critical_resource     = tbl->critical_resource;
1351         fid_parms.resource_hndl         = iparms.flow_handle;
1352
1353         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1354                                       parms->tbl_idx,
1355                                       parms->fid,
1356                                       &fid_parms);
1357         if (rc) {
1358                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1359                             rc);
1360                 /* Need to free the identifier, so goto error */
1361                 goto error;
1362         }
1363
1364         return 0;
1365 error:
1366         free_parms.dir          = iparms.dir;
1367         free_parms.mem          = iparms.mem;
1368         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1369         free_parms.flow_handle  = iparms.flow_handle;
1370
1371         trc = tf_delete_em_entry(tfp, &free_parms);
1372         if (trc)
1373                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1374
1375         return rc;
1376 }
1377
1378 static int32_t
1379 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1380                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1381 {
1382         struct bnxt_ulp_mapper_result_field_info *flds;
1383         struct ulp_flow_db_res_params   fid_parms;
1384         struct ulp_blob data;
1385         uint64_t idx;
1386         uint16_t tmplen;
1387         uint32_t i, num_flds;
1388         int32_t rc = 0, trc = 0;
1389         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1390         struct tf_set_tbl_entry_parms   sparms = { 0 };
1391         struct tf_free_tbl_entry_parms  free_parms = { 0 };
1392         uint32_t tbl_scope_id;
1393         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1394
1395         bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1396
1397         if (!ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
1398                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1399                 return -EINVAL;
1400         }
1401
1402         flds = ulp_mapper_result_fields_get(tbl, &num_flds);
1403         if (!flds || !num_flds) {
1404                 BNXT_TF_DBG(ERR, "Template undefined for action\n");
1405                 return -EINVAL;
1406         }
1407
1408         for (i = 0; i < num_flds; i++) {
1409                 rc = ulp_mapper_result_field_process(parms,
1410                                                      tbl->direction,
1411                                                      &flds[i],
1412                                                      &data,
1413                                                      "Indexed Result");
1414                 if (rc) {
1415                         BNXT_TF_DBG(ERR, "data field failed\n");
1416                         return rc;
1417                 }
1418         }
1419
1420         aparms.dir              = tbl->direction;
1421         aparms.type             = tbl->table_type;
1422         aparms.search_enable    = tbl->srch_b4_alloc;
1423         aparms.result           = ulp_blob_data_get(&data, &tmplen);
1424         aparms.result_sz_in_bytes = ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1425         aparms.tbl_scope_id     = tbl_scope_id;
1426
1427         /* All failures after the alloc succeeds require a free */
1428         rc = tf_alloc_tbl_entry(tfp, &aparms);
1429         if (rc) {
1430                 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1431                             tbl->table_type,
1432                             (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1433                             rc);
1434                 return rc;
1435         }
1436
1437         /* Always storing values in Regfile in BE */
1438         idx = tfp_cpu_to_be_64(aparms.idx);
1439         rc = ulp_regfile_write(parms->regfile, tbl->regfile_wr_idx, idx);
1440         if (!rc) {
1441                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1442                             tbl->regfile_wr_idx);
1443                 goto error;
1444         }
1445
1446         if (!tbl->srch_b4_alloc) {
1447                 sparms.dir              = tbl->direction;
1448                 sparms.type             = tbl->table_type;
1449                 sparms.data             = ulp_blob_data_get(&data, &tmplen);
1450                 sparms.data_sz_in_bytes =
1451                         ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1452                 sparms.idx              = aparms.idx;
1453                 sparms.tbl_scope_id     = tbl_scope_id;
1454
1455                 rc = tf_set_tbl_entry(tfp, &sparms);
1456                 if (rc) {
1457                         BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1458                                     tbl->table_type,
1459                                     (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1460                                     sparms.idx,
1461                                     rc);
1462
1463                         goto error;
1464                 }
1465         }
1466
1467         /* Link the resource to the flow in the flow db */
1468         memset(&fid_parms, 0, sizeof(fid_parms));
1469         fid_parms.direction     = tbl->direction;
1470         fid_parms.resource_func = tbl->resource_func;
1471         fid_parms.resource_type = tbl->table_type;
1472         fid_parms.resource_hndl = aparms.idx;
1473         fid_parms.critical_resource     = 0;
1474
1475         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1476                                       parms->tbl_idx,
1477                                       parms->fid,
1478                                       &fid_parms);
1479         if (rc) {
1480                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1481                             rc);
1482                 goto error;
1483         }
1484
1485         return rc;
1486 error:
1487         /*
1488          * Free the allocated resource since we failed to either
1489          * write to the entry or link the flow
1490          */
1491         free_parms.dir  = tbl->direction;
1492         free_parms.type = tbl->table_type;
1493         free_parms.idx  = aparms.idx;
1494         free_parms.tbl_scope_id = tbl_scope_id;
1495
1496         trc = tf_free_tbl_entry(tfp, &free_parms);
1497         if (trc)
1498                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1499
1500         return rc;
1501 }
1502
1503 static int32_t
1504 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1505                              struct bnxt_ulp_mapper_class_tbl_info *tbl)
1506 {
1507         struct bnxt_ulp_mapper_class_key_field_info *kflds;
1508         struct bnxt_ulp_mapper_cache_entry *cache_entry;
1509         struct bnxt_ulp_mapper_ident_info *idents;
1510         uint32_t i, num_kflds = 0, num_idents = 0;
1511         struct ulp_flow_db_res_params fid_parms;
1512         struct tf_free_identifier_parms fparms;
1513         uint16_t tmplen, tmp_ident;
1514         struct ulp_blob key;
1515         uint8_t *cache_key;
1516         uint64_t regval;
1517         uint16_t *ckey;
1518         int32_t rc;
1519
1520         /* Get the key fields list and build the key. */
1521         kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
1522         if (!kflds || !num_kflds) {
1523                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1524                 return -EINVAL;
1525         }
1526         if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order)) {
1527                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
1528                 return -EINVAL;
1529         }
1530         for (i = 0; i < num_kflds; i++) {
1531                 /* Setup the key */
1532                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1533                                                       &kflds[i],
1534                                                       &key, 1, "Cache Key");
1535                 if (rc) {
1536                         BNXT_TF_DBG(ERR,
1537                                     "Failed to create key for Cache rc=%d\n",
1538                                     rc);
1539                         return -EINVAL;
1540                 }
1541         }
1542
1543         /*
1544          * Perform the lookup in the cache table with constructed key.  The
1545          * cache_key is a byte array of tmplen, it needs to be converted to a
1546          * index for the cache table.
1547          */
1548         cache_key = ulp_blob_data_get(&key, &tmplen);
1549         ckey = (uint16_t *)cache_key;
1550         cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx,
1551                                                  tbl->cache_tbl_id,
1552                                                  *ckey);
1553
1554         /*
1555          * Get the identifier list for processing by both the hit and miss
1556          * processing.
1557          */
1558         idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
1559
1560         if (!cache_entry->ref_count) {
1561                 /* Initialize the cache entry */
1562                 cache_entry->tcam_idx = 0;
1563                 cache_entry->ref_count = 0;
1564                 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++)
1565                         cache_entry->idents[i] = ULP_IDENTS_INVALID;
1566
1567                 /* Need to allocate identifiers for storing in the cache. */
1568                 for (i = 0; i < num_idents; i++) {
1569                         /*
1570                          * Since we are using the cache, the identifier does not
1571                          * get added to the flow db.  Pass in the pointer to the
1572                          * tmp_ident.
1573                          */
1574                         rc = ulp_mapper_ident_process(parms, tbl,
1575                                                       &idents[i], &tmp_ident);
1576                         if (rc)
1577                                 goto error;
1578
1579                         cache_entry->ident_types[i] = idents[i].ident_type;
1580                         cache_entry->idents[i] = tmp_ident;
1581                 }
1582
1583                 /* Tell the TCAM processor to alloc an entry */
1584                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC;
1585                 /* Store the cache key for use by the tcam process code */
1586                 parms->cache_ptr = cache_entry;
1587         } else {
1588                 /* Cache hit, get values from result. */
1589                 for (i = 0; i < num_idents; i++) {
1590                         regval = (uint64_t)cache_entry->idents[i];
1591                         if (!ulp_regfile_write(parms->regfile,
1592                                                idents[i].regfile_wr_idx,
1593                                                tfp_cpu_to_be_64(regval))) {
1594                                 BNXT_TF_DBG(ERR,
1595                                             "Failed to write to regfile\n");
1596                                 return -EINVAL;
1597                         }
1598                 }
1599                 /*
1600                  * The cached entry is being used, so let the tcam processing
1601                  * know not to process this table.
1602                  */
1603                 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP;
1604         }
1605
1606         /* Made through the cache processing, increment the reference count. */
1607         cache_entry->ref_count++;
1608
1609         /* Link the cache to the flow db. */
1610         memset(&fid_parms, 0, sizeof(fid_parms));
1611         fid_parms.direction = tbl->direction;
1612         fid_parms.resource_func = tbl->resource_func;
1613
1614         /*
1615          * Cache resource type is composed of both table_type and cache_tbl_id
1616          * need to set it appropriately via setter.
1617          */
1618         ulp_mapper_cache_res_type_set(&fid_parms,
1619                                       tbl->table_type,
1620                                       tbl->cache_tbl_id);
1621         fid_parms.resource_hndl = (uint64_t)*ckey;
1622         fid_parms.critical_resource = tbl->critical_resource;
1623         rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1624                                       parms->tbl_idx,
1625                                       parms->fid,
1626                                       &fid_parms);
1627         if (rc)
1628                 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n");
1629
1630         return rc;
1631 error:
1632         /*
1633          * This error handling only gets called when the idents are being
1634          * allocated for the cache on misses.  Using the num_idents that was
1635          * previously set.
1636          */
1637         for (i = 0; i < num_idents; i++) {
1638                 if (cache_entry->idents[i] == ULP_IDENTS_INVALID)
1639                         continue;
1640
1641                 fparms.dir = tbl->direction;
1642                 fparms.ident_type = idents[i].ident_type;
1643                 fparms.id = cache_entry->idents[i];
1644                 tf_free_identifier(parms->tfp, &fparms);
1645         }
1646
1647         return rc;
1648 }
1649
1650 /*
1651  * Function to process the action template. Iterate through the list
1652  * action info templates and process it.
1653  */
1654 static int32_t
1655 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1656 {
1657         uint32_t        i;
1658         int32_t         rc = 0;
1659
1660         if (!parms->atbls || !parms->num_atbls) {
1661                 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
1662                             parms->dev_id, parms->act_tid);
1663                 return -EINVAL;
1664         }
1665
1666         for (i = 0; i < parms->num_atbls; i++) {
1667                 rc = ulp_mapper_action_info_process(parms, &parms->atbls[i]);
1668                 if (rc)
1669                         return rc;
1670         }
1671
1672         return rc;
1673 }
1674
1675 /* Create the classifier table entries for a flow. */
1676 static int32_t
1677 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1678 {
1679         uint32_t        i;
1680         int32_t         rc = 0;
1681
1682         if (!parms)
1683                 return -EINVAL;
1684
1685         if (!parms->ctbls || !parms->num_ctbls) {
1686                 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
1687                             parms->dev_id, parms->class_tid);
1688                 return -EINVAL;
1689         }
1690
1691         for (i = 0; i < parms->num_ctbls; i++) {
1692                 struct bnxt_ulp_mapper_class_tbl_info *tbl = &parms->ctbls[i];
1693
1694                 switch (tbl->resource_func) {
1695                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1696                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
1697                         break;
1698                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1699                         rc = ulp_mapper_em_tbl_process(parms, tbl);
1700                         break;
1701                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1702                         rc = ulp_mapper_index_tbl_process(parms, tbl);
1703                         break;
1704                 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1705                         rc = ulp_mapper_cache_tbl_process(parms, tbl);
1706                         break;
1707                 default:
1708                         BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
1709                                     tbl->resource_func);
1710                         return -EINVAL;
1711                 }
1712
1713                 if (rc) {
1714                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1715                                     tbl->resource_func);
1716                         return rc;
1717                 }
1718         }
1719
1720         return rc;
1721 }
1722
1723 static int32_t
1724 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
1725                          struct ulp_flow_db_res_params *res)
1726 {
1727         struct tf *tfp;
1728         int32_t rc = 0;
1729
1730         if (!res || !ulp) {
1731                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
1732                 return -EINVAL;
1733         }
1734
1735         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
1736         if (!tfp) {
1737                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
1738                 return -EINVAL;
1739         }
1740
1741         switch (res->resource_func) {
1742         case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE:
1743                 rc = ulp_mapper_cache_entry_free(ulp, tfp, res);
1744                 break;
1745         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1746                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
1747                 break;
1748         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1749                 rc = ulp_mapper_eem_entry_free(ulp, tfp, res);
1750                 break;
1751         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1752                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
1753                 break;
1754         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
1755                 rc = ulp_mapper_ident_free(ulp, tfp, res);
1756                 break;
1757         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
1758                 rc = ulp_mapper_mark_free(ulp, res);
1759                 break;
1760         default:
1761                 break;
1762         }
1763
1764         return rc;
1765 }
1766
1767 int32_t
1768 ulp_mapper_resources_free(struct bnxt_ulp_context       *ulp_ctx,
1769                           uint32_t fid,
1770                           enum bnxt_ulp_flow_db_tables  tbl_type)
1771 {
1772         struct ulp_flow_db_res_params   res_parms = { 0 };
1773         int32_t                         rc, trc;
1774
1775         if (!ulp_ctx) {
1776                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1777                 return -EINVAL;
1778         }
1779
1780         /*
1781          * Set the critical resource on the first resource del, then iterate
1782          * while status is good
1783          */
1784         res_parms.critical_resource = 1;
1785         rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms);
1786
1787         if (rc) {
1788                 /*
1789                  * This is unexpected on the first call to resource del.
1790                  * It likely means that the flow did not exist in the flow db.
1791                  */
1792                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
1793                             tbl_type, fid, rc);
1794                 return rc;
1795         }
1796
1797         while (!rc) {
1798                 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms);
1799                 if (trc)
1800                         /*
1801                          * On fail, we still need to attempt to free the
1802                          * remaining resources.  Don't return
1803                          */
1804                         BNXT_TF_DBG(ERR,
1805                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
1806                                     "] failed rc=%d.\n",
1807                                     tbl_type, fid, res_parms.resource_func,
1808                                     res_parms.resource_hndl, trc);
1809
1810                 /* All subsequent call require the critical_resource be zero */
1811                 res_parms.critical_resource = 0;
1812
1813                 rc = ulp_flow_db_resource_del(ulp_ctx,
1814                                               tbl_type,
1815                                               fid,
1816                                               &res_parms);
1817         }
1818
1819         /* Free the Flow ID since we've removed all resources */
1820         rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid);
1821
1822         return rc;
1823 }
1824
1825 int32_t
1826 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
1827 {
1828         if (!ulp_ctx) {
1829                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
1830                 return -EINVAL;
1831         }
1832
1833         return ulp_mapper_resources_free(ulp_ctx,
1834                                          fid,
1835                                          BNXT_ULP_REGULAR_FLOW_TABLE);
1836 }
1837
1838 /* Function to handle the mapping of the Flow to be compatible
1839  * with the underlying hardware.
1840  */
1841 int32_t
1842 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
1843                        struct bnxt_ulp_mapper_create_parms *cparms,
1844                        uint32_t *flowid)
1845 {
1846         struct bnxt_ulp_device_params *device_params;
1847         struct bnxt_ulp_mapper_parms parms;
1848         struct ulp_regfile regfile;
1849         int32_t  rc, trc;
1850
1851         if (!ulp_ctx || !cparms)
1852                 return -EINVAL;
1853
1854         /* Initialize the parms structure */
1855         memset(&parms, 0, sizeof(parms));
1856         parms.act_prop = cparms->act_prop;
1857         parms.act_bitmap = cparms->act;
1858         parms.regfile = &regfile;
1859         parms.hdr_field = cparms->hdr_field;
1860         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
1861         parms.ulp_ctx = ulp_ctx;
1862         parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1863
1864         /* Get the device id from the ulp context */
1865         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
1866                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
1867                 return -EINVAL;
1868         }
1869
1870         /*
1871          * Get the mapper data for dynamic mapper data such as default
1872          * ids.
1873          */
1874         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
1875                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
1876         if (!parms.mapper_data) {
1877                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
1878                 return -EINVAL;
1879         }
1880
1881         /* Get the action table entry from device id and act context id */
1882         parms.act_tid = cparms->act_tid;
1883         parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id,
1884                                                      parms.act_tid,
1885                                                      &parms.num_atbls);
1886         if (!parms.atbls || !parms.num_atbls) {
1887                 BNXT_TF_DBG(ERR, "No action tables for %d:%d\n",
1888                             parms.dev_id, parms.act_tid);
1889                 return -EINVAL;
1890         }
1891
1892         /* Get the class table entry from device id and act context id */
1893         parms.class_tid = cparms->class_tid;
1894         parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id,
1895                                                     parms.class_tid,
1896                                                     &parms.num_ctbls);
1897         if (!parms.ctbls || !parms.num_ctbls) {
1898                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1899                             parms.dev_id, parms.class_tid);
1900                 return -EINVAL;
1901         }
1902
1903         /* Get the byte order for the further processing from device params */
1904         device_params = bnxt_ulp_device_params_get(parms.dev_id);
1905         if (!device_params) {
1906                 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n",
1907                             parms.dev_id, parms.class_tid);
1908                 return -EINVAL;
1909         }
1910         parms.order = device_params->byte_order;
1911         parms.encap_byte_swap = device_params->encap_byte_swap;
1912
1913         /* initialize the registry file for further processing */
1914         if (!ulp_regfile_init(parms.regfile)) {
1915                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
1916                 return -EINVAL;
1917         }
1918
1919         rc = ulp_regfile_write(parms.regfile,
1920                                BNXT_ULP_REGFILE_INDEX_CLASS_TID,
1921                                tfp_cpu_to_be_64((uint64_t)parms.class_tid));
1922         if (!rc) {
1923                 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
1924                 return -EINVAL;
1925         }
1926
1927         /* Allocate a Flow ID for attaching all resources for the flow to.
1928          * Once allocated, all errors have to walk the list of resources and
1929          * free each of them.
1930          */
1931         rc = ulp_flow_db_fid_alloc(ulp_ctx,
1932                                    BNXT_ULP_REGULAR_FLOW_TABLE,
1933                                    cparms->func_id,
1934                                    &parms.fid);
1935         if (rc) {
1936                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
1937                 return rc;
1938         }
1939
1940         /* Process the action template list from the selected action table*/
1941         rc = ulp_mapper_action_tbls_process(&parms);
1942         if (rc) {
1943                 BNXT_TF_DBG(ERR, "action tables failed creation for %d:%d\n",
1944                             parms.dev_id, parms.act_tid);
1945                 goto flow_error;
1946         }
1947
1948         /* All good. Now process the class template */
1949         rc = ulp_mapper_class_tbls_process(&parms);
1950         if (rc) {
1951                 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n",
1952                             parms.dev_id, parms.class_tid);
1953                 goto flow_error;
1954         }
1955
1956         *flowid = parms.fid;
1957
1958         return rc;
1959
1960 flow_error:
1961         /* Free all resources that were allocated during flow creation */
1962         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
1963         if (trc)
1964                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
1965
1966         return rc;
1967 }
1968
1969 int32_t
1970 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
1971 {
1972         struct bnxt_ulp_cache_tbl_params *tbl;
1973         struct tf_alloc_identifier_parms iparms;
1974         struct bnxt_ulp_mapper_data *data;
1975         struct bnxt_ulp_def_ident_info *dflt_ids;
1976         uint32_t i, num_dflt_ids, reg_idx;
1977         uint64_t regval;
1978         struct tf *tfp;
1979         int32_t rc, csize;
1980
1981         if (!ulp_ctx)
1982                 return -EINVAL;
1983
1984         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
1985         if (!tfp)
1986                 return -EINVAL;
1987
1988         data = rte_zmalloc("ulp_mapper_data",
1989                            sizeof(struct bnxt_ulp_mapper_data), 0);
1990         if (!data) {
1991                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
1992                 return -ENOMEM;
1993         }
1994
1995         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
1996                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
1997                 /* Don't call deinit since the prof_func wasn't allocated. */
1998                 rte_free(data);
1999                 return -ENOMEM;
2000         }
2001
2002         /* Allocate the default ids. */
2003         dflt_ids = ulp_mapper_def_ident_info_list_get(&num_dflt_ids);
2004         for (i = 0; i < num_dflt_ids; i++) {
2005                 iparms.ident_type = dflt_ids[i].ident_type;
2006                 iparms.dir = dflt_ids[i].direction;
2007
2008                 rc = tf_alloc_identifier(tfp, &iparms);
2009                 if (rc) {
2010                         BNXT_TF_DBG(ERR, "Failed to alloc dflt "
2011                                     "identifier [%s][%d]\n",
2012                                     (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
2013                                     iparms.ident_type);
2014                         goto error;
2015                 }
2016                 reg_idx = dflt_ids[i].def_regfile_index;
2017                 /* All regfile entries are stored as 64bit big-endian values. */
2018                 regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
2019                 rc = ulp_mapper_def_regfile_write(data, iparms.dir,
2020                                                  reg_idx, regval);
2021                 if (rc) {
2022                         BNXT_TF_DBG(ERR, "Failed to write to default "
2023                                     "regfile.\n");
2024                         goto error;
2025                 }
2026         }
2027
2028         /* Allocate the ulp cache tables. */
2029         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2030                 tbl = ulp_mapper_cache_tbl_params_get(i);
2031                 if (!tbl) {
2032                         BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)",
2033                                     i);
2034                         goto error;
2035                 }
2036                 if (tbl->num_entries != 0) {
2037                         csize = sizeof(struct bnxt_ulp_mapper_cache_entry) *
2038                                 tbl->num_entries;
2039                         data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl",
2040                                                          csize, 0);
2041                         if (!data->cache_tbl[i]) {
2042                                 BNXT_TF_DBG(ERR, "Failed to allocate Cache "
2043                                             "table %d.\n", i);
2044                                 rc = -ENOMEM;
2045                                 goto error;
2046                         }
2047                 }
2048         }
2049
2050         return 0;
2051 error:
2052         /* Ignore the return code in favor of returning the original error. */
2053         ulp_mapper_deinit(ulp_ctx);
2054         return rc;
2055 }
2056
2057 void
2058 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
2059 {
2060         struct tf_free_identifier_parms free_parms;
2061         struct bnxt_ulp_def_ident_info *dflt_ids;
2062         struct bnxt_ulp_mapper_data *data;
2063         uint32_t i, num_dflt_ids, reg_idx;
2064         enum tf_dir dir;
2065         uint64_t regval;
2066         struct tf *tfp;
2067
2068         if (!ulp_ctx) {
2069                 BNXT_TF_DBG(ERR,
2070                             "Failed to acquire ulp context, so data may "
2071                             "not be released.\n");
2072                 return;
2073         }
2074
2075         data = (struct bnxt_ulp_mapper_data *)
2076                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2077         if (!data) {
2078                 /* Go ahead and return since there is no allocated data. */
2079                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
2080                 return;
2081         }
2082
2083         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2084         if (!tfp) {
2085                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
2086                 /* Free the mapper data regardless of errors. */
2087                 goto free_mapper_data;
2088         }
2089
2090         /* Free the default prof func ids per direction. */
2091         dflt_ids = ulp_mapper_def_ident_info_list_get(&num_dflt_ids);
2092         for (i = 0; i < num_dflt_ids; i++) {
2093                 reg_idx = dflt_ids[i].def_regfile_index;
2094                 dir = dflt_ids[i].direction;
2095                 free_parms.ident_type = dflt_ids[i].ident_type;
2096                 free_parms.dir = dir;
2097                 if (ulp_mapper_def_regfile_read(data, dir, reg_idx, &regval)) {
2098                         BNXT_TF_DBG(ERR, "Failed to read def regfile to free "
2099                                     "identifier.\n");
2100                         continue;
2101                 }
2102                 /*
2103                  * All regfile entries are stored as 64bit big-endian.  Need
2104                  * to convert the value to cpu before calling tf.
2105                  */
2106                 regval = tfp_be_to_cpu_64(regval);
2107                 free_parms.id = (uint16_t)regval;
2108                 /* Ignore errors and free the remaining identifiers. */
2109                 tf_free_identifier(tfp, &free_parms);
2110         }
2111
2112 free_mapper_data:
2113         /* Free the ulp cache tables */
2114         for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) {
2115                 rte_free(data->cache_tbl[i]);
2116                 data->cache_tbl[i] = NULL;
2117         }
2118
2119         rte_free(data);
2120         /* Reset the data pointer within the ulp_ctx. */
2121         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
2122 }