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