net/bnxt: modify table processing
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_mapper.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 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_enum.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_mapper.h"
18 #include "ulp_flow_db.h"
19 #include "tf_util.h"
20 #include "ulp_template_db_tbl.h"
21
22 static struct bnxt_ulp_glb_resource_info *
23 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
24 {
25         if (!num_entries)
26                 return NULL;
27         *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
28         return ulp_glb_resource_tbl;
29 }
30
31 /*
32  * Read the global resource from the mapper global resource list
33  *
34  * The regval is always returned in big-endian.
35  *
36  * returns 0 on success
37  */
38 static int32_t
39 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
40                              enum tf_dir dir,
41                              uint16_t idx,
42                              uint64_t *regval)
43 {
44         if (!mapper_data || !regval ||
45             dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
46                 return -EINVAL;
47
48         *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
49         return 0;
50 }
51
52 /*
53  * Write a global resource to the mapper global resource list
54  *
55  * The regval value must be in big-endian.
56  *
57  * return 0 on success.
58  */
59 static int32_t
60 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
61                               struct bnxt_ulp_glb_resource_info *res,
62                               uint64_t regval)
63 {
64         struct bnxt_ulp_mapper_glb_resource_entry *ent;
65
66         /* validate the arguments */
67         if (!data || res->direction >= TF_DIR_MAX ||
68             res->glb_regfile_index >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
69                 return -EINVAL;
70
71         /* write to the mapper data */
72         ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
73         ent->resource_func = res->resource_func;
74         ent->resource_type = res->resource_type;
75         ent->resource_hndl = regval;
76         return 0;
77 }
78
79 /*
80  * Internal function to allocate identity resource and store it in mapper data.
81  *
82  * returns 0 on success
83  */
84 static int32_t
85 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
86                                    struct bnxt_ulp_mapper_data *mapper_data,
87                                    struct bnxt_ulp_glb_resource_info *glb_res)
88 {
89         struct tf_alloc_identifier_parms iparms = { 0 };
90         struct tf_free_identifier_parms fparms;
91         uint64_t regval;
92         struct tf *tfp;
93         int32_t rc = 0;
94
95         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
96         if (!tfp)
97                 return -EINVAL;
98
99         iparms.ident_type = glb_res->resource_type;
100         iparms.dir = glb_res->direction;
101
102         /* Allocate the Identifier using tf api */
103         rc = tf_alloc_identifier(tfp, &iparms);
104         if (rc) {
105                 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
106                             tf_dir_2_str(iparms.dir),
107                             iparms.ident_type);
108                 return rc;
109         }
110
111         /* entries are stored as big-endian format */
112         regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
113         /* write to the mapper global resource */
114         rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
115         if (rc) {
116                 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
117                 /* Free the identifier when update failed */
118                 fparms.dir = iparms.dir;
119                 fparms.ident_type = iparms.ident_type;
120                 fparms.id = iparms.id;
121                 tf_free_identifier(tfp, &fparms);
122                 return rc;
123         }
124         return rc;
125 }
126
127 /*
128  * Internal function to allocate index tbl resource and store it in mapper data.
129  *
130  * returns 0 on success
131  */
132 static int32_t
133 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
134                                     struct bnxt_ulp_mapper_data *mapper_data,
135                                     struct bnxt_ulp_glb_resource_info *glb_res)
136 {
137         struct tf_alloc_tbl_entry_parms aparms = { 0 };
138         struct tf_free_tbl_entry_parms  free_parms = { 0 };
139         uint64_t regval;
140         struct tf *tfp;
141         uint32_t tbl_scope_id;
142         int32_t rc = 0;
143
144         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
145         if (!tfp)
146                 return -EINVAL;
147
148         /* Get the scope id */
149         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
150         if (rc) {
151                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
152                 return rc;
153         }
154
155         aparms.type = glb_res->resource_type;
156         aparms.dir = glb_res->direction;
157         aparms.search_enable = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO;
158         aparms.tbl_scope_id = tbl_scope_id;
159
160         /* Allocate the index tbl using tf api */
161         rc = tf_alloc_tbl_entry(tfp, &aparms);
162         if (rc) {
163                 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
164                             tf_dir_2_str(aparms.dir), aparms.type);
165                 return rc;
166         }
167
168         /* entries are stored as big-endian format */
169         regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
170         /* write to the mapper global resource */
171         rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
172         if (rc) {
173                 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
174                 /* Free the identifier when update failed */
175                 free_parms.dir = aparms.dir;
176                 free_parms.type = aparms.type;
177                 free_parms.idx = aparms.idx;
178                 tf_free_tbl_entry(tfp, &free_parms);
179                 return rc;
180         }
181         return rc;
182 }
183
184 /* Retrieve the global template table */
185 static uint32_t *
186 ulp_mapper_glb_template_table_get(uint32_t *num_entries)
187 {
188         if (!num_entries)
189                 return NULL;
190         *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ;
191         return ulp_glb_template_tbl;
192 }
193
194 static uint8_t *
195 ulp_mapper_glb_field_tbl_get(uint32_t idx)
196 {
197         return &ulp_glb_field_tbl[idx];
198 }
199
200 /*
201  * Get the size of the action property for a given index.
202  *
203  * idx [in] The index for the action property
204  *
205  * returns the size of the action property.
206  */
207 static uint32_t
208 ulp_mapper_act_prop_size_get(uint32_t idx)
209 {
210         if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
211                 return 0;
212         return ulp_act_prop_map_table[idx];
213 }
214
215 static struct bnxt_ulp_mapper_cond_info *
216 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
217                                 uint32_t tid,
218                                 uint32_t *num_tbls,
219                                 enum bnxt_ulp_cond_list_opc *opc)
220 {
221         uint32_t idx;
222         const struct ulp_template_device_tbls *dev_tbls;
223
224         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
225         *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
226         *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
227         idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
228
229         return &dev_tbls->cond_list[idx];
230 }
231
232 static struct bnxt_ulp_mapper_cond_info *
233 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
234                                 struct bnxt_ulp_mapper_tbl_info *tbl,
235                                 uint32_t *num_tbls,
236                                 enum bnxt_ulp_cond_list_opc *opc)
237 {
238         uint32_t idx;
239         const struct ulp_template_device_tbls *dev_tbls;
240
241         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
242         *num_tbls = tbl->execute_info.cond_nums;
243         *opc = tbl->execute_info.cond_list_opcode;
244         idx = tbl->execute_info.cond_start_idx;
245
246         return &dev_tbls->cond_list[idx];
247 }
248
249 /*
250  * Get a list of classifier tables that implement the flow
251  * Gets a device dependent list of tables that implement the class template id
252  *
253  * mparms [in] The mappers parms with data related to the flow.
254  *
255  * tid [in] The template id that matches the flow
256  *
257  * num_tbls [out] The number of classifier tables in the returned array
258  *
259  * returns An array of classifier tables to implement the flow, or NULL on
260  * error
261  */
262 static struct bnxt_ulp_mapper_tbl_info *
263 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
264                         uint32_t tid,
265                         uint32_t *num_tbls)
266 {
267         uint32_t idx;
268         const struct ulp_template_device_tbls *dev_tbls;
269
270         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
271
272         idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
273         *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
274
275         return &dev_tbls->tbl_list[idx];
276 }
277
278 /*
279  * Get the list of key fields that implement the flow.
280  *
281  * mparms [in] The mapper parms with information about the flow
282  *
283  * tbl [in] A single table instance to get the key fields from
284  *
285  * num_flds [out] The number of key fields in the returned array
286  *
287  * Returns array of Key fields, or NULL on error.
288  */
289 static struct bnxt_ulp_mapper_key_field_info *
290 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
291                           struct bnxt_ulp_mapper_tbl_info *tbl,
292                           uint32_t *num_flds)
293 {
294         uint32_t idx;
295         const struct ulp_template_device_tbls *dev_tbls;
296
297         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
298         if (!dev_tbls->key_field_list) {
299                 *num_flds = 0;
300                 return NULL;
301         }
302
303         idx             = tbl->key_start_idx;
304         *num_flds       = tbl->key_num_fields;
305
306         return &dev_tbls->key_field_list[idx];
307 }
308
309 /*
310  * Get the list of data fields that implement the flow.
311  *
312  * mparms [in] The mapper parms with information about the flow
313  *
314  * tbl [in] A single table instance to get the data fields from
315  *
316  * num_flds [out] The number of data fields in the returned array.
317  *
318  * num_encap_flds [out] The number of encap fields in the returned array.
319  *
320  * Returns array of data fields, or NULL on error.
321  */
322 static struct bnxt_ulp_mapper_result_field_info *
323 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
324                              struct bnxt_ulp_mapper_tbl_info *tbl,
325                              uint32_t *num_flds,
326                              uint32_t *num_encap_flds)
327 {
328         uint32_t idx;
329         const struct ulp_template_device_tbls *dev_tbls;
330
331         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
332         if (!dev_tbls->result_field_list) {
333                 *num_flds = 0;
334                 *num_encap_flds = 0;
335                 return NULL;
336         }
337
338         idx             = tbl->result_start_idx;
339         *num_flds       = tbl->result_num_fields;
340         *num_encap_flds = tbl->encap_num_fields;
341
342         return &dev_tbls->result_field_list[idx];
343 }
344
345 /*
346  * Get the list of ident fields that implement the flow
347  *
348  * tbl [in] A single table instance to get the ident fields from
349  *
350  * num_flds [out] The number of ident fields in the returned array
351  *
352  * returns array of ident fields, or NULL on error
353  */
354 static struct bnxt_ulp_mapper_ident_info *
355 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
356                             struct bnxt_ulp_mapper_tbl_info *tbl,
357                             uint32_t *num_flds)
358 {
359         uint32_t idx;
360         const struct ulp_template_device_tbls *dev_tbls;
361
362         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
363         if (!dev_tbls->ident_list) {
364                 *num_flds = 0;
365                 return NULL;
366         }
367
368         idx = tbl->ident_start_idx;
369         *num_flds = tbl->ident_nums;
370
371         return &dev_tbls->ident_list[idx];
372 }
373
374 static inline int32_t
375 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp  __rte_unused,
376                            struct tf *tfp,
377                            struct ulp_flow_db_res_params *res)
378 {
379         struct tf_free_tcam_entry_parms fparms = {
380                 .dir            = res->direction,
381                 .tcam_tbl_type  = res->resource_type,
382                 .idx            = (uint16_t)res->resource_hndl
383         };
384
385         return tf_free_tcam_entry(tfp, &fparms);
386 }
387
388 static inline int32_t
389 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
390                             struct tf *tfp,
391                             struct ulp_flow_db_res_params *res)
392 {
393         struct tf_free_tbl_entry_parms fparms = {
394                 .dir    = res->direction,
395                 .type   = res->resource_type,
396                 .idx    = (uint32_t)res->resource_hndl
397         };
398
399         /*
400          * Just get the table scope, it will be ignored if not necessary
401          * by the tf_free_tbl_entry
402          */
403         (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
404
405         return tf_free_tbl_entry(tfp, &fparms);
406 }
407
408 static inline int32_t
409 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
410                          struct tf *tfp,
411                          struct ulp_flow_db_res_params *res)
412 {
413         struct tf_delete_em_entry_parms fparms = { 0 };
414         int32_t rc;
415
416         fparms.dir              = res->direction;
417         if (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE)
418                 fparms.mem = TF_MEM_EXTERNAL;
419         else
420                 fparms.mem = TF_MEM_INTERNAL;
421         fparms.flow_handle      = res->resource_hndl;
422
423         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
424         if (rc) {
425                 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
426                 return -EINVAL;
427         }
428
429         return tf_delete_em_entry(tfp, &fparms);
430 }
431
432 static inline int32_t
433 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
434                       struct tf *tfp,
435                       struct ulp_flow_db_res_params *res)
436 {
437         struct tf_free_identifier_parms fparms = {
438                 .dir            = res->direction,
439                 .ident_type     = res->resource_type,
440                 .id             = (uint16_t)res->resource_hndl
441         };
442
443         return tf_free_identifier(tfp, &fparms);
444 }
445
446 static inline int32_t
447 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
448                      struct ulp_flow_db_res_params *res)
449 {
450         return ulp_mark_db_mark_del(ulp,
451                                     res->resource_type,
452                                     res->resource_hndl);
453 }
454
455 static inline int32_t
456 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
457                             uint32_t parent_fid,
458                             struct ulp_flow_db_res_params *res)
459 {
460         uint32_t idx, child_fid = 0, parent_idx;
461         struct bnxt_ulp_flow_db *flow_db;
462
463         parent_idx = (uint32_t)res->resource_hndl;
464
465         /* check the validity of the parent fid */
466         if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
467             idx != parent_idx) {
468                 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
469                 return -EINVAL;
470         }
471
472         /* Clear all the child flows parent index */
473         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
474         while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
475                                                              &child_fid)) {
476                 /* update the child flows resource handle */
477                 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
478                                                  child_fid)) {
479                         BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
480                                     child_fid);
481                         return -EINVAL;
482                 }
483         }
484
485         /* free the parent entry in the parent table flow */
486         if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
487                 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
488                 return -EINVAL;
489         }
490         return 0;
491 }
492
493 static inline int32_t
494 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
495                            uint32_t child_fid,
496                            struct ulp_flow_db_res_params *res)
497 {
498         uint32_t parent_fid;
499
500         parent_fid = (uint32_t)res->resource_hndl;
501         if (!parent_fid)
502                 return 0; /* Already freed - orphan child*/
503
504         /* reset the child flow bitset*/
505         if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
506                 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
507                             parent_fid, child_fid);
508                 return -EINVAL;
509         }
510         return 0;
511 }
512
513 /*
514  * Process the flow database opcode action.
515  * returns 0 on success.
516  */
517 static int32_t
518 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
519                            struct bnxt_ulp_mapper_tbl_info *tbl,
520                            struct ulp_flow_db_res_params *fid_parms)
521 {
522         uint32_t push_fid, fid = 0;
523         uint64_t val64;
524         int32_t rc = 0;
525
526         switch (tbl->fdb_opcode) {
527         case BNXT_ULP_FDB_OPC_PUSH:
528                 push_fid = parms->fid;
529                 break;
530         case BNXT_ULP_FDB_OPC_ALLOC_PUSH_REGFILE:
531                 /* allocate a new fid */
532                 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
533                                            parms->flow_type,
534                                            tbl->resource_func, &fid);
535                 if (rc) {
536                         BNXT_TF_DBG(ERR,
537                                     "Unable to allocate flow table entry\n");
538                         return rc;
539                 }
540                 /* Store the allocated fid in regfile*/
541                 val64 = fid;
542                 rc = ulp_regfile_write(parms->regfile, tbl->flow_db_operand,
543                                        tfp_cpu_to_be_64(val64));
544                 if (!rc) {
545                         BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
546                                     tbl->flow_db_operand);
547                         rc = -EINVAL;
548                         goto error;
549                 }
550                 /* Use the allocated fid to update the flow resource */
551                 push_fid = fid;
552                 break;
553         case BNXT_ULP_FDB_OPC_PUSH_REGFILE:
554                 /* get the fid from the regfile */
555                 rc = ulp_regfile_read(parms->regfile, tbl->flow_db_operand,
556                                       &val64);
557                 if (!rc) {
558                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
559                                     tbl->flow_db_operand);
560                         return -EINVAL;
561                 }
562                 /* Use the extracted fid to update the flow resource */
563                 push_fid = tfp_be_to_cpu_64((uint32_t)val64);
564                 break;
565         default:
566                 return rc; /* Nothing to be done */
567         }
568
569         /* Add the resource to the flow database */
570         rc = ulp_flow_db_resource_add(parms->ulp_ctx, parms->flow_type,
571                                       push_fid, fid_parms);
572         if (rc) {
573                 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
574                             push_fid, rc);
575                 goto error;
576         }
577         return rc;
578
579 error:
580         /* free the allocated fid */
581         if (fid)
582                 ulp_flow_db_fid_free(parms->ulp_ctx,
583                                      BNXT_ULP_FDB_TYPE_REGULAR, fid);
584         return rc;
585 }
586
587 /*
588  * Process the identifier list in the given table.
589  * Extract the ident from the table entry and
590  * write it to the reg file.
591  * returns 0 on success.
592  */
593 static int32_t
594 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
595                               struct bnxt_ulp_mapper_tbl_info *tbl,
596                               uint8_t *byte_data,
597                               uint32_t byte_data_size,
598                               enum bnxt_ulp_byte_order byte_order)
599 {
600         struct bnxt_ulp_mapper_ident_info *idents;
601         uint32_t i, num_idents = 0;
602         uint64_t val64;
603
604         /* validate the null arguments */
605         if (!byte_data) {
606                 BNXT_TF_DBG(ERR, "invalid argument\n");
607                 return -EINVAL;
608         }
609
610         /* Get the ident list and process each one */
611         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
612
613         for (i = 0; i < num_idents; i++) {
614                 /* check the size of the buffer for validation */
615                 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
616                     ULP_BYTE_2_BITS(byte_data_size) ||
617                     idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
618                         BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
619                                     idents[i].ident_bit_pos,
620                                     idents[i].ident_bit_size,
621                                     byte_data_size);
622                         return -EINVAL;
623                 }
624                 if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
625                         ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
626                                         sizeof(val64),
627                                         idents[i].ident_bit_pos,
628                                         idents[i].ident_bit_size);
629                 else
630                         ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
631                                         idents[i].ident_bit_pos,
632                                         idents[i].ident_bit_size);
633
634                 /* Write it to the regfile, val64 is already in big-endian*/
635                 if (!ulp_regfile_write(parms->regfile,
636                                        idents[i].regfile_idx,
637                                        val64)) {
638                         BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
639                                     idents[i].regfile_idx);
640                         return -EINVAL;
641                 }
642         }
643         return 0;
644 }
645
646 /*
647  * Process the identifier instruction and either store it in the flow database
648  * or return it in the val (if not NULL) on success.  If val is NULL, the
649  * identifier is to be stored in the flow database.
650  */
651 static int32_t
652 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
653                          struct bnxt_ulp_mapper_tbl_info *tbl,
654                          struct bnxt_ulp_mapper_ident_info *ident,
655                          uint16_t *val)
656 {
657         struct ulp_flow_db_res_params   fid_parms;
658         uint64_t id = 0;
659         int32_t idx;
660         struct tf_alloc_identifier_parms iparms = { 0 };
661         struct tf_free_identifier_parms free_parms = { 0 };
662         struct tf *tfp;
663         int rc;
664
665         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
666         if (!tfp) {
667                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
668                 return -EINVAL;
669         }
670
671         idx = ident->regfile_idx;
672
673         iparms.ident_type = ident->ident_type;
674         iparms.dir = tbl->direction;
675
676         rc = tf_alloc_identifier(tfp, &iparms);
677         if (rc) {
678                 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
679                             tf_dir_2_str(iparms.dir),
680                             tf_ident_2_str(iparms.ident_type));
681                 return rc;
682         }
683
684         id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
685         if (!ulp_regfile_write(parms->regfile, idx, id)) {
686                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
687                 rc = -EINVAL;
688                 /* Need to free the identifier, so goto error */
689                 goto error;
690         }
691
692         /* Link the resource to the flow in the flow db */
693         if (!val) {
694                 memset(&fid_parms, 0, sizeof(fid_parms));
695                 fid_parms.direction             = tbl->direction;
696                 fid_parms.resource_func = ident->resource_func;
697                 fid_parms.resource_type = ident->ident_type;
698                 fid_parms.resource_hndl = iparms.id;
699                 fid_parms.critical_resource = tbl->critical_resource;
700
701                 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
702                 if (rc) {
703                         BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
704                                     rc);
705                         /* Need to free the identifier, so goto error */
706                         goto error;
707                 }
708         } else {
709                 *val = iparms.id;
710         }
711         return 0;
712
713 error:
714         /* Need to free the identifier */
715         free_parms.dir          = tbl->direction;
716         free_parms.ident_type   = ident->ident_type;
717         free_parms.id           = iparms.id;
718
719         (void)tf_free_identifier(tfp, &free_parms);
720
721         BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
722                     ident->description,
723                     tf_dir_2_str(tbl->direction));
724         return rc;
725 }
726
727 /*
728  * Process the identifier instruction and extract it from result blob.
729  * Increment the identifier reference count and store it in the flow database.
730  */
731 static int32_t
732 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
733                          struct bnxt_ulp_mapper_tbl_info *tbl,
734                          struct bnxt_ulp_mapper_ident_info *ident,
735                          struct ulp_blob *res_blob)
736 {
737         struct ulp_flow_db_res_params   fid_parms;
738         uint64_t id = 0;
739         uint32_t idx = 0;
740         struct tf_search_identifier_parms sparms = { 0 };
741         struct tf_free_identifier_parms free_parms = { 0 };
742         struct tf *tfp;
743         int rc;
744
745         /* Get the tfp from ulp context */
746         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
747         if (!tfp) {
748                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
749                 return -EINVAL;
750         }
751
752         /* Extract the index from the result blob */
753         rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
754                            ident->ident_bit_pos, ident->ident_bit_size);
755         if (rc) {
756                 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
757                 return -EIO;
758         }
759
760         /* populate the search params and search identifier shadow table */
761         sparms.ident_type = ident->ident_type;
762         sparms.dir = tbl->direction;
763         /* convert the idx into cpu format */
764         sparms.search_id = tfp_be_to_cpu_32(idx);
765
766         /* Search identifier also increase the reference count */
767         rc = tf_search_identifier(tfp, &sparms);
768         if (rc) {
769                 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
770                             tf_dir_2_str(sparms.dir),
771                             tf_ident_2_str(sparms.ident_type),
772                             sparms.search_id);
773                 return rc;
774         }
775
776         /* Write it to the regfile */
777         id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
778         if (!ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
779                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
780                 rc = -EINVAL;
781                 /* Need to free the identifier, so goto error */
782                 goto error;
783         }
784
785         /* Link the resource to the flow in the flow db */
786         memset(&fid_parms, 0, sizeof(fid_parms));
787         fid_parms.direction = tbl->direction;
788         fid_parms.resource_func = ident->resource_func;
789         fid_parms.resource_type = ident->ident_type;
790         fid_parms.resource_hndl = sparms.search_id;
791         fid_parms.critical_resource = tbl->critical_resource;
792         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
793         if (rc) {
794                 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
795                             rc);
796                 /* Need to free the identifier, so goto error */
797                 goto error;
798         }
799
800         return 0;
801
802 error:
803         /* Need to free the identifier */
804         free_parms.dir = tbl->direction;
805         free_parms.ident_type = ident->ident_type;
806         free_parms.id = sparms.search_id;
807         (void)tf_free_identifier(tfp, &free_parms);
808         BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
809                     ident->description,
810                     tf_dir_2_str(tbl->direction), sparms.search_id);
811         return rc;
812 }
813
814 static int32_t
815 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
816                                 enum tf_dir dir,
817                                 struct bnxt_ulp_mapper_result_field_info *fld,
818                                 struct ulp_blob *blob,
819                                 const char *name)
820 {
821         uint16_t idx, size_idx;
822         uint8_t  *val = NULL;
823         uint16_t write_idx = blob->write_idx;
824         uint64_t regval;
825         uint32_t val_size = 0, field_size = 0;
826         uint64_t act_bit;
827         uint8_t act_val[16];
828         uint64_t hdr_bit;
829
830         switch (fld->result_opcode) {
831         case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
832                 val = fld->result_operand;
833                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
834                         BNXT_TF_DBG(ERR, "%s failed to add field\n", name);
835                         return -EINVAL;
836                 }
837                 break;
838         case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_PROP:
839                 if (!ulp_operand_read(fld->result_operand,
840                                       (uint8_t *)&idx, sizeof(uint16_t))) {
841                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
842                         return -EINVAL;
843                 }
844                 idx = tfp_be_to_cpu_16(idx);
845
846                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
847                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
848                         return -EINVAL;
849                 }
850                 val = &parms->act_prop->act_details[idx];
851                 field_size = ulp_mapper_act_prop_size_get(idx);
852                 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
853                         field_size  = field_size -
854                             ((fld->field_bit_size + 7) / 8);
855                         val += field_size;
856                 }
857                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
858                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
859                         return -EINVAL;
860                 }
861                 break;
862         case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_BIT:
863                 if (!ulp_operand_read(fld->result_operand,
864                                       (uint8_t *)&act_bit, sizeof(uint64_t))) {
865                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
866                         return -EINVAL;
867                 }
868                 act_bit = tfp_be_to_cpu_64(act_bit);
869                 memset(act_val, 0, sizeof(act_val));
870                 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
871                         act_val[0] = 1;
872                 if (fld->field_bit_size > ULP_BYTE_2_BITS(sizeof(act_val))) {
873                         BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
874                         return -EINVAL;
875                 }
876                 if (!ulp_blob_push(blob, act_val, fld->field_bit_size)) {
877                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
878                         return -EINVAL;
879                 }
880                 val = act_val;
881                 break;
882         case BNXT_ULP_MAPPER_OPC_SET_TO_ENCAP_ACT_PROP_SZ:
883                 if (!ulp_operand_read(fld->result_operand,
884                                       (uint8_t *)&idx, sizeof(uint16_t))) {
885                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
886                         return -EINVAL;
887                 }
888                 idx = tfp_be_to_cpu_16(idx);
889
890                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
891                         BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
892                         return -EINVAL;
893                 }
894                 val = &parms->act_prop->act_details[idx];
895
896                 /* get the size index next */
897                 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
898                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
899                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
900                         return -EINVAL;
901                 }
902                 size_idx = tfp_be_to_cpu_16(size_idx);
903
904                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
905                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
906                         return -EINVAL;
907                 }
908                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
909                        sizeof(uint32_t));
910                 val_size = tfp_be_to_cpu_32(val_size);
911                 val_size = ULP_BYTE_2_BITS(val_size);
912                 ulp_blob_push_encap(blob, val, val_size);
913                 break;
914         case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
915                 if (!ulp_operand_read(fld->result_operand,
916                                       (uint8_t *)&idx, sizeof(uint16_t))) {
917                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
918                         return -EINVAL;
919                 }
920
921                 idx = tfp_be_to_cpu_16(idx);
922                 /* Uninitialized regfile entries return 0 */
923                 if (!ulp_regfile_read(parms->regfile, idx, &regval)) {
924                         BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
925                                     name, idx);
926                         return -EINVAL;
927                 }
928
929                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
930                 if (!val) {
931                         BNXT_TF_DBG(ERR, "%s push field failed\n", name);
932                         return -EINVAL;
933                 }
934                 break;
935         case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
936                 if (!ulp_operand_read(fld->result_operand,
937                                       (uint8_t *)&idx,
938                                       sizeof(uint16_t))) {
939                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
940                         return -EINVAL;
941                 }
942                 idx = tfp_be_to_cpu_16(idx);
943                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
944                                                  dir,
945                                                  idx, &regval)) {
946                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
947                                     name, idx);
948                         return -EINVAL;
949                 }
950                 val = ulp_blob_push_64(blob, &regval, fld->field_bit_size);
951                 if (!val) {
952                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
953                         return -EINVAL;
954                 }
955                 break;
956         case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
957                 if (!ulp_operand_read(fld->result_operand,
958                                       (uint8_t *)&idx,
959                                       sizeof(uint16_t))) {
960                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
961                         return -EINVAL;
962                 }
963                 idx = tfp_be_to_cpu_16(idx);
964                 if (idx < BNXT_ULP_CF_IDX_LAST)
965                         val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
966                                                fld->field_bit_size);
967                 if (!val) {
968                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
969                         return -EINVAL;
970                 }
971                 break;
972         case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
973                 if (ulp_blob_pad_push(blob, fld->field_bit_size) < 0) {
974                         BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
975                         return -EINVAL;
976                 }
977
978                 break;
979         case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST:
980                 if (!ulp_operand_read(fld->result_operand,
981                                       (uint8_t *)&act_bit, sizeof(uint64_t))) {
982                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
983                         return -EINVAL;
984                 }
985                 act_bit = tfp_be_to_cpu_64(act_bit);
986                 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
987                         /* Action bit is set so consider operand_true */
988                         if (!ulp_operand_read(fld->result_operand_true,
989                                               (uint8_t *)&idx,
990                                               sizeof(uint16_t))) {
991                                 BNXT_TF_DBG(ERR, "%s operand read failed\n",
992                                             name);
993                                 return -EINVAL;
994                         }
995                         idx = tfp_be_to_cpu_16(idx);
996                         if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
997                                 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n",
998                                             name, idx);
999                                 return -EINVAL;
1000                         }
1001                         val = &parms->act_prop->act_details[idx];
1002                         field_size = ulp_mapper_act_prop_size_get(idx);
1003                         if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
1004                                 field_size  = field_size -
1005                                     ((fld->field_bit_size + 7) / 8);
1006                                 val += field_size;
1007                         }
1008                         if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1009                                 BNXT_TF_DBG(ERR, "%s push field failed\n",
1010                                             name);
1011                                 return -EINVAL;
1012                         }
1013                 } else {
1014                         /* action bit is not set, use the operand false */
1015                         val = fld->result_operand_false;
1016                         if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1017                                 BNXT_TF_DBG(ERR, "%s failed to add field\n",
1018                                             name);
1019                                 return -EINVAL;
1020                         }
1021                 }
1022                 break;
1023         case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST:
1024                 if (!ulp_operand_read(fld->result_operand,
1025                                       (uint8_t *)&act_bit, sizeof(uint64_t))) {
1026                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1027                         return -EINVAL;
1028                 }
1029                 act_bit = tfp_be_to_cpu_64(act_bit);
1030                 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
1031                         /* Action bit is set so consider operand_true */
1032                         val = fld->result_operand_true;
1033                 } else {
1034                         /* action bit is not set, use the operand false */
1035                         val = fld->result_operand_false;
1036                 }
1037                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1038                         BNXT_TF_DBG(ERR, "%s failed to add field\n",
1039                                     name);
1040                         return -EINVAL;
1041                 }
1042                 break;
1043         case BNXT_ULP_MAPPER_OPC_IF_COMP_FIELD_THEN_CF_ELSE_CF:
1044                 if (!ulp_operand_read(fld->result_operand,
1045                                       (uint8_t *)&idx,
1046                                       sizeof(uint16_t))) {
1047                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1048                         return -EINVAL;
1049                 }
1050                 idx = tfp_be_to_cpu_16(idx);
1051                 if (idx >= BNXT_ULP_CF_IDX_LAST) {
1052                         BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
1053                         return -EINVAL;
1054                 }
1055                 /* check if the computed field is set */
1056                 if (ULP_COMP_FLD_IDX_RD(parms, idx))
1057                         val = fld->result_operand_true;
1058                 else
1059                         val = fld->result_operand_false;
1060
1061                 /* read the appropriate computed field */
1062                 if (!ulp_operand_read(val, (uint8_t *)&idx, sizeof(uint16_t))) {
1063                         BNXT_TF_DBG(ERR, "%s val operand read failed\n", name);
1064                         return -EINVAL;
1065                 }
1066                 idx = tfp_be_to_cpu_16(idx);
1067                 if (idx >= BNXT_ULP_CF_IDX_LAST) {
1068                         BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
1069                         return -EINVAL;
1070                 }
1071                 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1072                                        fld->field_bit_size);
1073                 if (!val) {
1074                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1075                         return -EINVAL;
1076                 }
1077                 break;
1078         case BNXT_ULP_MAPPER_OPC_IF_HDR_BIT_THEN_CONST_ELSE_CONST:
1079                 if (!ulp_operand_read(fld->result_operand,
1080                                       (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1081                         BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1082                         return -EINVAL;
1083                 }
1084                 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1085                 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit)) {
1086                         /* Header bit is set so consider operand_true */
1087                         val = fld->result_operand_true;
1088                 } else {
1089                         /* Header bit is not set, use the operand false */
1090                         val = fld->result_operand_false;
1091                 }
1092                 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1093                         BNXT_TF_DBG(ERR, "%s failed to add field\n",
1094                                     name);
1095                         return -EINVAL;
1096                 }
1097                 break;
1098         default:
1099                 BNXT_TF_DBG(ERR, "invalid result mapper opcode 0x%x at %d\n",
1100                             fld->result_opcode, write_idx);
1101                 return -EINVAL;
1102         }
1103         return 0;
1104 }
1105
1106 /*
1107  * Result table process and fill the result blob.
1108  * data [out] - the result blob data
1109  */
1110 static int32_t
1111 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1112                             struct bnxt_ulp_mapper_tbl_info *tbl,
1113                             struct ulp_blob *data,
1114                             const char *name)
1115 {
1116         struct bnxt_ulp_mapper_result_field_info *dflds;
1117         uint32_t i, num_flds = 0, encap_flds = 0;
1118         int32_t rc = 0;
1119
1120         /* Get the result field list */
1121         dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1122                                              &encap_flds);
1123
1124         /* validate the result field list counts */
1125         if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1126              (!num_flds && !encap_flds)) || !dflds ||
1127             (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1128                 (!num_flds || encap_flds))) {
1129                 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1130                             num_flds, encap_flds);
1131                 return -EINVAL;
1132         }
1133
1134         /* process the result fields, loop through them */
1135         for (i = 0; i < (num_flds + encap_flds); i++) {
1136                 /* set the swap index if encap swap bit is enabled */
1137                 if (parms->device_params->encap_byte_swap && encap_flds &&
1138                     i == num_flds)
1139                         ulp_blob_encap_swap_idx_set(data);
1140
1141                 /* Process the result fields */
1142                 rc = ulp_mapper_result_field_process(parms, tbl->direction,
1143                                                      &dflds[i], data, name);
1144                 if (rc) {
1145                         BNXT_TF_DBG(ERR, "data field failed\n");
1146                         return rc;
1147                 }
1148         }
1149
1150         /* if encap bit swap is enabled perform the bit swap */
1151         if (parms->device_params->encap_byte_swap && encap_flds)
1152                 ulp_blob_perform_encap_swap(data);
1153
1154         return rc;
1155 }
1156
1157 /* Function to alloc action record and set the table. */
1158 static int32_t
1159 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
1160                                  enum tf_dir dir,
1161                                  struct bnxt_ulp_mapper_key_field_info *f,
1162                                  struct ulp_blob *blob,
1163                                  uint8_t is_key,
1164                                  const char *name)
1165 {
1166         uint64_t val64;
1167         uint16_t idx, bitlen;
1168         uint32_t opcode;
1169         uint8_t *operand;
1170         struct ulp_regfile *regfile = parms->regfile;
1171         uint8_t *val = NULL;
1172         struct bnxt_ulp_mapper_key_field_info *fld = f;
1173         uint32_t field_size;
1174
1175         if (is_key) {
1176                 operand = fld->spec_operand;
1177                 opcode  = fld->spec_opcode;
1178         } else {
1179                 operand = fld->mask_operand;
1180                 opcode  = fld->mask_opcode;
1181         }
1182
1183         bitlen = fld->field_bit_size;
1184
1185         switch (opcode) {
1186         case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
1187                 val = operand;
1188                 if (!ulp_blob_push(blob, val, bitlen)) {
1189                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1190                         return -EINVAL;
1191                 }
1192                 break;
1193         case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
1194                 if (ulp_blob_pad_push(blob, bitlen) < 0) {
1195                         BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
1196                         return -EINVAL;
1197                 }
1198
1199                 break;
1200         case BNXT_ULP_MAPPER_OPC_SET_TO_HDR_FIELD:
1201                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1202                                       sizeof(uint16_t))) {
1203                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1204                         return -EINVAL;
1205                 }
1206                 idx = tfp_be_to_cpu_16(idx);
1207                 if (is_key)
1208                         val = parms->hdr_field[idx].spec;
1209                 else
1210                         val = parms->hdr_field[idx].mask;
1211
1212                 /*
1213                  * Need to account for how much data was pushed to the header
1214                  * field vs how much is to be inserted in the key/mask.
1215                  */
1216                 field_size = parms->hdr_field[idx].size;
1217                 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1218                         field_size  = field_size - ((bitlen + 7) / 8);
1219                         val += field_size;
1220                 }
1221
1222                 if (!ulp_blob_push(blob, val, bitlen)) {
1223                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1224                         return -EINVAL;
1225                 }
1226                 break;
1227         case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
1228                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1229                                       sizeof(uint16_t))) {
1230                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1231                         return -EINVAL;
1232                 }
1233                 idx = tfp_be_to_cpu_16(idx);
1234                 if (idx < BNXT_ULP_CF_IDX_LAST)
1235                         val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1236                                                bitlen);
1237                 if (!val) {
1238                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1239                         return -EINVAL;
1240                 }
1241                 break;
1242         case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
1243                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1244                                       sizeof(uint16_t))) {
1245                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1246                         return -EINVAL;
1247                 }
1248                 idx = tfp_be_to_cpu_16(idx);
1249
1250                 if (!ulp_regfile_read(regfile, idx, &val64)) {
1251                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
1252                                     name, idx);
1253                         return -EINVAL;
1254                 }
1255
1256                 val = ulp_blob_push_64(blob, &val64, bitlen);
1257                 if (!val) {
1258                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1259                         return -EINVAL;
1260                 }
1261                 break;
1262         case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
1263                 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1264                                       sizeof(uint16_t))) {
1265                         BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1266                         return -EINVAL;
1267                 }
1268                 idx = tfp_be_to_cpu_16(idx);
1269                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1270                                                  dir,
1271                                                  idx, &val64)) {
1272                         BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
1273                                     name, idx);
1274                         return -EINVAL;
1275                 }
1276                 val = ulp_blob_push_64(blob, &val64, bitlen);
1277                 if (!val) {
1278                         BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1279                         return -EINVAL;
1280                 }
1281                 break;
1282         default:
1283                 BNXT_TF_DBG(ERR, "invalid keymask mapper opcode 0x%x\n",
1284                             opcode);
1285                 return -EINVAL;
1286         }
1287         return 0;
1288 }
1289
1290 static int32_t
1291 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1292                              struct bnxt_ulp_mapper_tbl_info *tbl,
1293                              uint64_t flow_id)
1294 {
1295         struct ulp_flow_db_res_params fid_parms;
1296         uint32_t mark, gfid, mark_flag;
1297         enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1298         int32_t rc = 0;
1299
1300         if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1301             !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1302              ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1303                               BNXT_ULP_ACTION_BIT_MARK)))
1304                 return rc; /* no need to perform gfid process */
1305
1306         /* Get the mark id details from action property */
1307         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1308                sizeof(mark));
1309         mark = tfp_be_to_cpu_32(mark);
1310
1311         TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1312         mark_flag  = BNXT_ULP_MARK_GLOBAL_HW_FID;
1313
1314         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1315                                   gfid, mark);
1316         if (rc) {
1317                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1318                 return rc;
1319         }
1320         fid_parms.direction = tbl->direction;
1321         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1322         fid_parms.critical_resource = tbl->critical_resource;
1323         fid_parms.resource_type = mark_flag;
1324         fid_parms.resource_hndl = gfid;
1325         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1326         if (rc)
1327                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1328         return rc;
1329 }
1330
1331 static int32_t
1332 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1333                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1334 {
1335         struct ulp_flow_db_res_params fid_parms;
1336         uint32_t act_idx, mark, mark_flag;
1337         uint64_t val64;
1338         enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1339         int32_t rc = 0;
1340
1341         if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1342             !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1343              ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1344                               BNXT_ULP_ACTION_BIT_MARK)))
1345                 return rc; /* no need to perform mark action process */
1346
1347         /* Get the mark id details from action property */
1348         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1349                sizeof(mark));
1350         mark = tfp_be_to_cpu_32(mark);
1351
1352         if (!ulp_regfile_read(parms->regfile,
1353                               BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1354                               &val64)) {
1355                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1356                 return -EINVAL;
1357         }
1358         act_idx = tfp_be_to_cpu_64(val64);
1359         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID;
1360         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1361                                   act_idx, mark);
1362         if (rc) {
1363                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1364                 return rc;
1365         }
1366         fid_parms.direction = tbl->direction;
1367         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1368         fid_parms.critical_resource = tbl->critical_resource;
1369         fid_parms.resource_type = mark_flag;
1370         fid_parms.resource_hndl = act_idx;
1371         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1372         if (rc)
1373                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1374         return rc;
1375 }
1376
1377 static int32_t
1378 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1379                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1380 {
1381         struct ulp_flow_db_res_params fid_parms;
1382         uint32_t act_idx, mark, mark_flag;
1383         uint64_t val64;
1384         enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1385         int32_t rc = 0;
1386
1387         if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1388             mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION)
1389                 return rc; /* no need to perform mark action process */
1390
1391         /* Get the mark id details from the computed field of dev port id */
1392         mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1393
1394          /* Get the main action pointer */
1395         if (!ulp_regfile_read(parms->regfile,
1396                               BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1397                               &val64)) {
1398                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1399                 return -EINVAL;
1400         }
1401         act_idx = tfp_be_to_cpu_64(val64);
1402
1403         /* Set the mark flag to local fid and vfr flag */
1404         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1405
1406         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1407                                   act_idx, mark);
1408         if (rc) {
1409                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1410                 return rc;
1411         }
1412         fid_parms.direction = tbl->direction;
1413         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1414         fid_parms.critical_resource = tbl->critical_resource;
1415         fid_parms.resource_type = mark_flag;
1416         fid_parms.resource_hndl = act_idx;
1417         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1418         if (rc)
1419                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1420         return rc;
1421 }
1422
1423 /* Tcam table scan the identifier list and allocate each identifier */
1424 static int32_t
1425 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1426                                      struct bnxt_ulp_mapper_tbl_info *tbl)
1427 {
1428         struct bnxt_ulp_mapper_ident_info *idents;
1429         uint32_t num_idents;
1430         uint32_t i;
1431
1432         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1433         for (i = 0; i < num_idents; i++) {
1434                 if (ulp_mapper_ident_process(parms, tbl,
1435                                              &idents[i], NULL))
1436                         return -EINVAL;
1437         }
1438         return 0;
1439 }
1440
1441 /*
1442  * Tcam table scan the identifier list and extract the identifier from
1443  * the result blob.
1444  */
1445 static int32_t
1446 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1447                                        struct bnxt_ulp_mapper_tbl_info *tbl,
1448                                        struct ulp_blob *data)
1449 {
1450         struct bnxt_ulp_mapper_ident_info *idents;
1451         uint32_t num_idents = 0, i;
1452         int32_t rc = 0;
1453
1454         /*
1455          * Extract the listed identifiers from the result field,
1456          * no need to allocate them.
1457          */
1458         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1459         for (i = 0; i < num_idents; i++) {
1460                 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1461                 if (rc) {
1462                         BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1463                         return rc;
1464                 }
1465         }
1466         return rc;
1467 }
1468
1469 /* Internal function to write the tcam entry */
1470 static int32_t
1471 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1472                                 struct bnxt_ulp_mapper_tbl_info *tbl,
1473                                 struct ulp_blob *key,
1474                                 struct ulp_blob *mask,
1475                                 struct ulp_blob *data,
1476                                 uint16_t idx)
1477 {
1478         struct tf_set_tcam_entry_parms sparms = { 0 };
1479         struct tf *tfp;
1480         uint16_t tmplen;
1481         int32_t rc;
1482
1483         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1484         if (!tfp) {
1485                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1486                 return -EINVAL;
1487         }
1488
1489         sparms.dir              = tbl->direction;
1490         sparms.tcam_tbl_type    = tbl->resource_type;
1491         sparms.idx              = idx;
1492         /* Already verified the key/mask lengths */
1493         sparms.key              = ulp_blob_data_get(key, &tmplen);
1494         sparms.key_sz_in_bits   = tmplen;
1495         sparms.mask             = ulp_blob_data_get(mask, &tmplen);
1496         sparms.result           = ulp_blob_data_get(data, &tmplen);
1497
1498         if (tbl->result_bit_size != tmplen) {
1499                 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1500                             tmplen, tbl->result_bit_size);
1501                 return -EINVAL;
1502         }
1503         sparms.result_sz_in_bits = tbl->result_bit_size;
1504         if (tf_set_tcam_entry(tfp, &sparms)) {
1505                 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1506                             tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1507                             tf_dir_2_str(sparms.dir), sparms.idx);
1508                 return -EIO;
1509         }
1510
1511         /* Mark action */
1512         rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1513         if (rc) {
1514                 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1515                 return rc;
1516         }
1517
1518         return rc;
1519 }
1520
1521 #define BNXT_ULP_WC_TCAM_SLICE_SIZE 80
1522 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1523 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob,
1524                                                 uint32_t len)
1525 {
1526         uint8_t mode[2] = {0x0, 0x0};
1527         uint32_t mode_len = len / BNXT_ULP_WC_TCAM_SLICE_SIZE;
1528         uint32_t size, idx;
1529
1530         /* Add the mode bits to the key and mask*/
1531         if (mode_len == 2)
1532                 mode[1] = 2;
1533         else if (mode_len > 2)
1534                 mode[1] = 3;
1535
1536         size = BNXT_ULP_WC_TCAM_SLICE_SIZE + ULP_BYTE_2_BITS(sizeof(mode));
1537         for (idx = 0; idx < mode_len; idx++)
1538                 ulp_blob_insert(blob, (size * idx), mode,
1539                                 ULP_BYTE_2_BITS(sizeof(mode)));
1540         ulp_blob_perform_64B_word_swap(blob);
1541         ulp_blob_perform_64B_byte_swap(blob);
1542 }
1543
1544 static int32_t
1545 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1546                             struct bnxt_ulp_mapper_tbl_info *tbl)
1547 {
1548         struct bnxt_ulp_mapper_key_field_info   *kflds;
1549         struct ulp_blob key, mask, data, update_data;
1550         uint32_t i, num_kflds;
1551         struct tf *tfp;
1552         int32_t rc, trc;
1553         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
1554         struct tf_search_tcam_entry_parms searchparms   = { 0 };
1555         struct ulp_flow_db_res_params   fid_parms       = { 0 };
1556         struct tf_free_tcam_entry_parms free_parms      = { 0 };
1557         uint32_t hit = 0;
1558         uint16_t tmplen = 0;
1559         uint16_t idx;
1560
1561         /* Skip this if table opcode is NOP */
1562         if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1563             tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1564                 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1565                             tbl->tbl_opcode);
1566                 return 0;
1567         }
1568
1569         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1570         if (!tfp) {
1571                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1572                 return -EINVAL;
1573         }
1574
1575         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1576         if (!kflds || !num_kflds) {
1577                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1578                 return -EINVAL;
1579         }
1580
1581         if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1582                            parms->device_params->byte_order) ||
1583             !ulp_blob_init(&mask, tbl->blob_key_bit_size,
1584                            parms->device_params->byte_order) ||
1585             !ulp_blob_init(&data, tbl->result_bit_size,
1586                            parms->device_params->byte_order) ||
1587             !ulp_blob_init(&update_data, tbl->result_bit_size,
1588                            parms->device_params->byte_order)) {
1589                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1590                 return -EINVAL;
1591         }
1592
1593         if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1594                 key.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1595                 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1596         }
1597
1598         /* create the key/mask */
1599         /*
1600          * NOTE: The WC table will require some kind of flag to handle the
1601          * mode bits within the key/mask
1602          */
1603         for (i = 0; i < num_kflds; i++) {
1604                 /* Setup the key */
1605                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1606                                                       &kflds[i],
1607                                                       &key, 1, "TCAM Key");
1608                 if (rc) {
1609                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1610                         return rc;
1611                 }
1612
1613                 /* Setup the mask */
1614                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1615                                                       &kflds[i],
1616                                                       &mask, 0, "TCAM Mask");
1617                 if (rc) {
1618                         BNXT_TF_DBG(ERR, "Mask field set failed.\n");
1619                         return rc;
1620                 }
1621         }
1622
1623         /* For wild card tcam perform the post process to swap the blob */
1624         if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1625                 ulp_mapper_wc_tcam_tbl_post_process(&key, tbl->key_bit_size);
1626                 ulp_mapper_wc_tcam_tbl_post_process(&mask, tbl->key_bit_size);
1627         }
1628
1629         if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1630                 /* allocate the tcam index */
1631                 aparms.dir = tbl->direction;
1632                 aparms.tcam_tbl_type = tbl->resource_type;
1633                 aparms.key = ulp_blob_data_get(&key, &tmplen);
1634                 aparms.key_sz_in_bits = tmplen;
1635                 if (tbl->blob_key_bit_size != tmplen) {
1636                         BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1637                                     tmplen, tbl->blob_key_bit_size);
1638                         return -EINVAL;
1639                 }
1640
1641                 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
1642                 if (tbl->blob_key_bit_size != tmplen) {
1643                         BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1644                                     tmplen, tbl->blob_key_bit_size);
1645                         return -EINVAL;
1646                 }
1647                 aparms.priority = tbl->priority;
1648                 rc = tf_alloc_tcam_entry(tfp, &aparms);
1649                 if (rc) {
1650                         BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1651                         return rc;
1652                 }
1653                 idx = aparms.idx;
1654                 hit = aparms.hit;
1655         } else {
1656                 /*
1657                  * Searching before allocation to see if we already have an
1658                  * entry.  This allows re-use of a constrained resource.
1659                  */
1660                 searchparms.dir = tbl->direction;
1661                 searchparms.tcam_tbl_type = tbl->resource_type;
1662                 searchparms.key = ulp_blob_data_get(&key, &tmplen);
1663                 searchparms.key_sz_in_bits = tbl->key_bit_size;
1664                 searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1665                 searchparms.priority = tbl->priority;
1666                 searchparms.alloc = 1;
1667                 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1668                 searchparms.result_sz_in_bits = tbl->result_bit_size;
1669
1670                 rc = tf_search_tcam_entry(tfp, &searchparms);
1671                 if (rc) {
1672                         BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1673                         return rc;
1674                 }
1675
1676                 /* Successful search, check the result */
1677                 if (searchparms.search_status == REJECT) {
1678                         BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1679                         return -ENOMEM;
1680                 }
1681                 idx = searchparms.idx;
1682                 hit = searchparms.hit;
1683         }
1684
1685         /* Write the tcam index into the regfile*/
1686         if (!ulp_regfile_write(parms->regfile, tbl->tbl_operand,
1687                                (uint64_t)tfp_cpu_to_be_64(idx))) {
1688                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
1689                             tbl->tbl_operand);
1690                 rc = -EINVAL;
1691                 /* Need to free the tcam idx, so goto error */
1692                 goto error;
1693         }
1694
1695         /* if it is miss then it is same as no search before alloc */
1696         if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1697                 /*Scan identifier list, allocate identifier and update regfile*/
1698                 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1699                 /* Create the result blob */
1700                 if (!rc)
1701                         rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
1702                                                          "TCAM Result");
1703                 /* write the tcam entry */
1704                 if (!rc)
1705                         rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1706                                                              &mask, &data, idx);
1707         } else {
1708                 /*Scan identifier list, extract identifier and update regfile*/
1709                 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1710         }
1711         if (rc)
1712                 goto error;
1713
1714         /* Add the tcam index to the flow database */
1715         fid_parms.direction = tbl->direction;
1716         fid_parms.resource_func = tbl->resource_func;
1717         fid_parms.resource_type = tbl->resource_type;
1718         fid_parms.critical_resource = tbl->critical_resource;
1719         fid_parms.resource_hndl = idx;
1720         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1721         if (rc) {
1722                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1723                             rc);
1724                 /* Need to free the identifier, so goto error */
1725                 goto error;
1726         }
1727
1728         return 0;
1729 error:
1730         free_parms.dir                  = tbl->direction;
1731         free_parms.tcam_tbl_type        = tbl->resource_type;
1732         free_parms.idx                  = idx;
1733         trc = tf_free_tcam_entry(tfp, &free_parms);
1734         if (trc)
1735                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1736                             tbl->resource_type, tbl->direction, idx);
1737         return rc;
1738 }
1739
1740 static int32_t
1741 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1742                           struct bnxt_ulp_mapper_tbl_info *tbl)
1743 {
1744         struct bnxt_ulp_mapper_key_field_info   *kflds;
1745         struct ulp_blob key, data;
1746         uint32_t i, num_kflds;
1747         uint16_t tmplen;
1748         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1749         struct ulp_flow_db_res_params   fid_parms = { 0 };
1750         struct tf_insert_em_entry_parms iparms = { 0 };
1751         struct tf_delete_em_entry_parms free_parms = { 0 };
1752         enum bnxt_ulp_flow_mem_type mtype;
1753         int32_t trc;
1754         int32_t rc = 0;
1755
1756         rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1757         if (rc) {
1758                 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1759                 return -EINVAL;
1760         }
1761
1762         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1763         if (!kflds || !num_kflds) {
1764                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1765                 return -EINVAL;
1766         }
1767
1768         /* Initialize the key/result blobs */
1769         if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1770                            parms->device_params->byte_order) ||
1771             !ulp_blob_init(&data, tbl->result_bit_size,
1772                            parms->device_params->byte_order)) {
1773                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1774                 return -EINVAL;
1775         }
1776
1777         /* create the key */
1778         for (i = 0; i < num_kflds; i++) {
1779                 /* Setup the key */
1780                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1781                                                       &kflds[i],
1782                                                       &key, 1, "EM Key");
1783                 if (rc) {
1784                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
1785                         return rc;
1786                 }
1787         }
1788
1789         /*
1790          * TBD: Normally should process identifiers in case of using recycle or
1791          * loopback.  Not supporting recycle for now.
1792          */
1793
1794         /* Create the result data blob */
1795         rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
1796         if (rc) {
1797                 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
1798                 return rc;
1799         }
1800         /* do the transpose for the internal EM keys */
1801         if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1802                 ulp_blob_perform_byte_reverse(&key);
1803
1804         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1805                                              &iparms.tbl_scope_id);
1806         if (rc) {
1807                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1808                 return rc;
1809         }
1810
1811         /*
1812          * NOTE: the actual blob size will differ from the size in the tbl
1813          * entry due to the padding.
1814          */
1815         iparms.dup_check                = 0;
1816         iparms.dir                      = tbl->direction;
1817         iparms.mem                      = tbl->resource_type;
1818         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
1819         iparms.key_sz_in_bits           = tbl->key_bit_size;
1820         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
1821         iparms.em_record_sz_in_bits     = tbl->result_bit_size;
1822
1823         rc = tf_insert_em_entry(tfp, &iparms);
1824         if (rc) {
1825                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1826                 return rc;
1827         }
1828
1829         /* Mark action process */
1830         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
1831             tbl->resource_type == TF_MEM_EXTERNAL)
1832                 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
1833         else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
1834                  tbl->resource_type == TF_MEM_INTERNAL)
1835                 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1836         if (rc) {
1837                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1838                 goto error;
1839         }
1840
1841         /* Link the EM resource to the flow in the flow db */
1842         memset(&fid_parms, 0, sizeof(fid_parms));
1843         fid_parms.direction             = tbl->direction;
1844         fid_parms.resource_func         = tbl->resource_func;
1845         fid_parms.resource_type         = tbl->resource_type;
1846         fid_parms.critical_resource     = tbl->critical_resource;
1847         fid_parms.resource_hndl         = iparms.flow_handle;
1848
1849         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1850         if (rc) {
1851                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1852                             rc);
1853                 /* Need to free the identifier, so goto error */
1854                 goto error;
1855         }
1856
1857         return 0;
1858 error:
1859         free_parms.dir          = iparms.dir;
1860         free_parms.mem          = iparms.mem;
1861         free_parms.tbl_scope_id = iparms.tbl_scope_id;
1862         free_parms.flow_handle  = iparms.flow_handle;
1863
1864         trc = tf_delete_em_entry(tfp, &free_parms);
1865         if (trc)
1866                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1867
1868         return rc;
1869 }
1870
1871 static int32_t
1872 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1873                              struct bnxt_ulp_mapper_tbl_info *tbl)
1874 {
1875         struct ulp_flow_db_res_params fid_parms;
1876         struct ulp_blob data;
1877         uint64_t regval = 0;
1878         uint16_t tmplen;
1879         uint32_t index, hit;
1880         int32_t rc = 0, trc = 0;
1881         struct tf_alloc_tbl_entry_parms aparms = { 0 };
1882         struct tf_search_tbl_entry_parms srchparms = { 0 };
1883         struct tf_set_tbl_entry_parms sparms = { 0 };
1884         struct tf_get_tbl_entry_parms gparms = { 0 };
1885         struct tf_free_tbl_entry_parms free_parms = { 0 };
1886         uint32_t tbl_scope_id;
1887         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1888         uint16_t bit_size;
1889         bool alloc = false;
1890         bool write = false;
1891         bool search = false;
1892
1893         /* use the max size if encap is enabled */
1894         if (tbl->encap_num_fields)
1895                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
1896         else
1897                 bit_size = tbl->result_bit_size;
1898
1899         /* Initialize the blob data */
1900         if (!ulp_blob_init(&data, bit_size,
1901                            parms->device_params->byte_order)) {
1902                 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
1903                 return -EINVAL;
1904         }
1905
1906         /* Get the scope id first */
1907         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1908         if (rc) {
1909                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1910                 return rc;
1911         }
1912
1913         switch (tbl->tbl_opcode) {
1914         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
1915                 alloc = true;
1916                 break;
1917         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
1918                 /*
1919                  * Build the entry, alloc an index, write the table, and store
1920                  * the data in the regfile.
1921                  */
1922                 alloc = true;
1923                 write = true;
1924                 break;
1925         case BNXT_ULP_INDEX_TBL_OPC_SRCH_ALLOC_WR_REGFILE:
1926                 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
1927                         /* Not currently supporting with EXT */
1928                         BNXT_TF_DBG(ERR,
1929                                     "Ext Table Search Opcode not supported.\n");
1930                         return -EINVAL;
1931                 }
1932                 /*
1933                  * Search for the entry in the tf core.  If it is hit, save the
1934                  * index in the regfile.  If it is a miss, Build the entry,
1935                  * alloc an index, write the table, and store the data in the
1936                  * regfile (same as ALLOC_WR).
1937                  */
1938                 search = true;
1939                 break;
1940         case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
1941                 /*
1942                  * get the index to write to from the regfile and then write
1943                  * the table entry.
1944                  */
1945                 if (!ulp_regfile_read(parms->regfile,
1946                                       tbl->tbl_operand,
1947                                       &regval)) {
1948                         BNXT_TF_DBG(ERR,
1949                                     "Failed to get tbl idx from regfile[%d].\n",
1950                                     tbl->tbl_operand);
1951                         return -EINVAL;
1952                 }
1953                 index = tfp_be_to_cpu_64(regval);
1954                 /* For external, we need to reverse shift */
1955                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
1956                         index = TF_ACT_REC_PTR_2_OFFSET(index);
1957
1958                 write = true;
1959                 break;
1960         case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
1961                 /*
1962                  * get the index to write to from the global regfile and then
1963                  * write the table.
1964                  */
1965                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1966                                                  tbl->direction,
1967                                                  tbl->tbl_operand,
1968                                                  &regval)) {
1969                         BNXT_TF_DBG(ERR,
1970                                     "Failed to get tbl idx from Global "
1971                                     "regfile[%d].\n",
1972                                     tbl->index_operand);
1973                         return -EINVAL;
1974                 }
1975                 index = tfp_be_to_cpu_64(regval);
1976                 /* For external, we need to reverse shift */
1977                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
1978                         index = TF_ACT_REC_PTR_2_OFFSET(index);
1979                 write = true;
1980                 break;
1981         case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
1982                 /*
1983                  * The read is different from the rest and can be handled here
1984                  * instead of trying to use common code.  Simply read the table
1985                  * with the index from the regfile, scan and store the
1986                  * identifiers, and return.
1987                  */
1988                 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
1989                         /* Not currently supporting with EXT */
1990                         BNXT_TF_DBG(ERR,
1991                                     "Ext Table Read Opcode not supported.\n");
1992                         return -EINVAL;
1993                 }
1994                 if (!ulp_regfile_read(parms->regfile,
1995                                       tbl->tbl_operand, &regval)) {
1996                         BNXT_TF_DBG(ERR,
1997                                     "Failed to get tbl idx from regfile[%d]\n",
1998                                     tbl->tbl_operand);
1999                         return -EINVAL;
2000                 }
2001                 index = tfp_be_to_cpu_64(regval);
2002                 gparms.dir = tbl->direction;
2003                 gparms.type = tbl->resource_type;
2004                 gparms.data = ulp_blob_data_get(&data, &tmplen);
2005                 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2006                 gparms.idx = index;
2007                 rc = tf_get_tbl_entry(tfp, &gparms);
2008                 if (rc) {
2009                         BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2010                                     tbl->resource_type, index);
2011                         return rc;
2012                 }
2013                 /*
2014                  * Scan the fields in the entry and push them into the regfile.
2015                  */
2016                 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2017                                                    gparms.data,
2018                                                    gparms.data_sz_in_bytes,
2019                                                    data.byte_order);
2020                 if (rc) {
2021                         BNXT_TF_DBG(ERR, "Failed to read fields on tbl read "
2022                                     "rc=%d\n", rc);
2023                         return rc;
2024                 }
2025                 return 0;
2026         default:
2027                 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2028                             tbl->tbl_opcode);
2029                 return -EINVAL;
2030         }
2031
2032         if (write || search) {
2033                 /* Get the result fields list */
2034                 rc = ulp_mapper_tbl_result_build(parms,
2035                                                  tbl,
2036                                                  &data,
2037                                                  "Indexed Result");
2038                 if (rc) {
2039                         BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2040                         return rc;
2041                 }
2042         }
2043
2044         if (search) {
2045                 /* Use the result blob to perform a search */
2046                 memset(&srchparms, 0, sizeof(srchparms));
2047                 srchparms.dir = tbl->direction;
2048                 srchparms.type = tbl->resource_type;
2049                 srchparms.alloc = 1;
2050                 srchparms.result = ulp_blob_data_get(&data, &tmplen);
2051                 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2052                 srchparms.tbl_scope_id = tbl_scope_id;
2053                 rc = tf_search_tbl_entry(tfp, &srchparms);
2054                 if (rc) {
2055                         BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2056                                     tf_tbl_type_2_str(tbl->resource_type),
2057                                     tf_dir_2_str(tbl->direction), rc);
2058                         return rc;
2059                 }
2060                 if (srchparms.search_status == REJECT) {
2061                         BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
2062                                     tf_tbl_type_2_str(tbl->resource_type),
2063                                     tf_dir_2_str(tbl->direction));
2064                         return -ENOMEM;
2065                 }
2066                 index = srchparms.idx;
2067                 hit = srchparms.hit;
2068                 if (hit)
2069                         write = false;
2070                 else
2071                         write = true;
2072         }
2073
2074         if (alloc) {
2075                 aparms.dir              = tbl->direction;
2076                 aparms.type             = tbl->resource_type;
2077                 aparms.tbl_scope_id     = tbl_scope_id;
2078
2079                 /* All failures after the alloc succeeds require a free */
2080                 rc = tf_alloc_tbl_entry(tfp, &aparms);
2081                 if (rc) {
2082                         BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2083                                     tf_tbl_type_2_str(tbl->resource_type),
2084                                     tf_dir_2_str(tbl->direction), rc);
2085                         return rc;
2086                 }
2087                 index = aparms.idx;
2088         }
2089
2090         if (search || alloc) {
2091                 /*
2092                  * Store the index in the regfile since we either allocated it
2093                  * or it was a hit.
2094                  *
2095                  * Calculate the idx for the result record, for external EM the
2096                  * offset needs to be shifted accordingly.
2097                  * If external non-inline table types are used then need to
2098                  * revisit this logic.
2099                  */
2100                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2101                         regval = TF_ACT_REC_OFFSET_2_PTR(index);
2102                 else
2103                         regval = index;
2104
2105                 rc = ulp_regfile_write(parms->regfile,
2106                                        tbl->tbl_operand,
2107                                        tfp_cpu_to_be_64(regval));
2108                 if (!rc) {
2109                         BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n",
2110                                     tbl->tbl_operand, rc);
2111                         goto error;
2112                 }
2113         }
2114
2115         if (write) {
2116                 sparms.dir = tbl->direction;
2117                 sparms.type = tbl->resource_type;
2118                 sparms.data = ulp_blob_data_get(&data, &tmplen);
2119                 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2120                 sparms.idx = index;
2121                 sparms.tbl_scope_id = tbl_scope_id;
2122                 rc = tf_set_tbl_entry(tfp, &sparms);
2123                 if (rc) {
2124                         BNXT_TF_DBG(ERR,
2125                                     "Index table[%s][%s][%x] write failed "
2126                                     "rc=%d\n",
2127                                     tf_tbl_type_2_str(sparms.type),
2128                                     tf_dir_2_str(sparms.dir),
2129                                     sparms.idx, rc);
2130                         goto error;
2131                 }
2132         }
2133
2134         /* Link the resource to the flow in the flow db */
2135         memset(&fid_parms, 0, sizeof(fid_parms));
2136         fid_parms.direction     = tbl->direction;
2137         fid_parms.resource_func = tbl->resource_func;
2138         fid_parms.resource_type = tbl->resource_type;
2139         fid_parms.resource_sub_type = tbl->resource_sub_type;
2140         fid_parms.resource_hndl = index;
2141         fid_parms.critical_resource = tbl->critical_resource;
2142
2143         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2144         if (rc) {
2145                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2146                             rc);
2147                 goto error;
2148         }
2149
2150         /* Perform the VF rep action */
2151         rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2152         if (rc) {
2153                 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2154                 goto error;
2155         }
2156         return rc;
2157 error:
2158         /*
2159          * Free the allocated resource since we failed to either
2160          * write to the entry or link the flow
2161          */
2162         free_parms.dir  = tbl->direction;
2163         free_parms.type = tbl->resource_type;
2164         free_parms.idx  = index;
2165         free_parms.tbl_scope_id = tbl_scope_id;
2166
2167         trc = tf_free_tbl_entry(tfp, &free_parms);
2168         if (trc)
2169                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2170
2171         return rc;
2172 }
2173
2174 static int32_t
2175 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2176                           struct bnxt_ulp_mapper_tbl_info *tbl)
2177 {
2178         struct ulp_blob data, res_blob;
2179         uint64_t idx;
2180         uint16_t tmplen;
2181         int32_t rc = 0;
2182         struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2183         struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2184         struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2185         enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2186         uint32_t res_size;
2187
2188         /* Initialize the blob data */
2189         if (!ulp_blob_init(&data, tbl->result_bit_size,
2190                            parms->device_params->byte_order)) {
2191                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2192                 return -EINVAL;
2193         }
2194
2195         /* create the result blob */
2196         rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2197         if (rc) {
2198                 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2199                 return rc;
2200         }
2201
2202         /* Get the index details */
2203         switch (if_opc) {
2204         case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2205                 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2206                 break;
2207         case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2208                 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2209                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2210                                     tbl->tbl_operand);
2211                         return -EINVAL;
2212                 }
2213                 idx = tfp_be_to_cpu_64(idx);
2214                 break;
2215         case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2216                 idx = tbl->tbl_operand;
2217                 break;
2218         case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2219                 /* Initialize the result blob */
2220                 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2221                                    parms->device_params->byte_order)) {
2222                         BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2223                         return -EINVAL;
2224                 }
2225
2226                 /* read the interface table */
2227                 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2228                 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2229                 get_parms.dir = tbl->direction;
2230                 get_parms.type = tbl->resource_type;
2231                 get_parms.idx = idx;
2232                 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2233                 get_parms.data_sz_in_bytes = res_size;
2234
2235                 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2236                 if (rc) {
2237                         BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2238                                     get_parms.type,
2239                                     tf_dir_2_str(get_parms.dir),
2240                                     get_parms.idx, rc);
2241                         return rc;
2242                 }
2243                 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2244                                                    res_blob.data,
2245                                                    res_size,
2246                                                    res_blob.byte_order);
2247                 if (rc)
2248                         BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2249                 return rc;
2250         case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2251                 return rc; /* skip it */
2252         default:
2253                 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2254                 return -EINVAL;
2255         }
2256
2257         /* Perform the tf table set by filling the set params */
2258         iftbl_params.dir = tbl->direction;
2259         iftbl_params.type = tbl->resource_type;
2260         iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2261         iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2262         iftbl_params.idx = idx;
2263
2264         rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2265         if (rc) {
2266                 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2267                             iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2268                             tf_dir_2_str(iftbl_params.dir),
2269                             iftbl_params.idx, rc);
2270                 return rc;
2271         }
2272
2273         /*
2274          * TBD: Need to look at the need to store idx in flow db for restore
2275          * the table to its original state on deletion of this entry.
2276          */
2277         return rc;
2278 }
2279
2280 static int32_t
2281 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2282                            struct bnxt_ulp_mapper_tbl_info *tbl)
2283 {
2284         struct bnxt_ulp_mapper_key_field_info *kflds;
2285         struct ulp_flow_db_res_params fid_parms;
2286         struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2287         uint16_t tmplen;
2288         struct ulp_blob key, data;
2289         uint8_t *cache_key;
2290         int32_t tbl_idx;
2291         uint32_t i, ckey, num_kflds = 0;
2292         uint32_t gen_tbl_hit = 0, fdb_write = 0;
2293         uint8_t *byte_data;
2294         int32_t rc = 0;
2295
2296         /* Get the key fields list and build the key. */
2297         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2298         if (!kflds || !num_kflds) {
2299                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2300                 return -EINVAL;
2301         }
2302         if (!ulp_blob_init(&key, tbl->key_bit_size,
2303                            parms->device_params->byte_order)) {
2304                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2305                 return -EINVAL;
2306         }
2307         for (i = 0; i < num_kflds; i++) {
2308                 /* Setup the key */
2309                 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
2310                                                       &kflds[i],
2311                                                       &key, 1, "Gen Tbl Key");
2312                 if (rc) {
2313                         BNXT_TF_DBG(ERR,
2314                                     "Failed to create key for Gen tbl rc=%d\n",
2315                                     rc);
2316                         return -EINVAL;
2317                 }
2318         }
2319
2320         /* Calculate the table index for the generic table*/
2321         tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2322                                                    tbl->direction);
2323         if (tbl_idx < 0) {
2324                 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2325                             tbl->resource_sub_type, tbl->direction);
2326                 return -EINVAL;
2327         }
2328
2329         /* The_key is a byte array convert it to a search index */
2330         cache_key = ulp_blob_data_get(&key, &tmplen);
2331         memcpy(&ckey, cache_key, sizeof(ckey));
2332         /* Get the generic table entry */
2333         rc = ulp_mapper_gen_tbl_entry_get(parms->ulp_ctx,
2334                                           tbl_idx, ckey, &gen_tbl_ent);
2335         if (rc) {
2336                 BNXT_TF_DBG(ERR,
2337                             "Failed to create key for Gen tbl rc=%d\n", rc);
2338                 return -EINVAL;
2339         }
2340         switch (tbl->tbl_opcode) {
2341         case BNXT_ULP_GENERIC_TBL_OPC_READ:
2342                 /* check the reference count */
2343                 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2344                         g = &gen_tbl_ent;
2345                         /* Scan ident list and create the result blob*/
2346                         rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2347                                                            g->byte_data,
2348                                                            g->byte_data_size,
2349                                                            g->byte_order);
2350                         if (rc) {
2351                                 BNXT_TF_DBG(ERR,
2352                                             "Failed to scan ident list\n");
2353                                 return -EINVAL;
2354                         }
2355                         /* increment the reference count */
2356                         ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2357
2358                         /* it is a hit */
2359                         gen_tbl_hit = 1;
2360                         fdb_write = 1;
2361                 }
2362                 break;
2363         case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2364                 /* check the reference count */
2365                 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2366                         /* a hit then error */
2367                         BNXT_TF_DBG(ERR, "generic entry already present %x\n",
2368                                     ckey);
2369                         return -EINVAL; /* success */
2370                 }
2371
2372                 /* Initialize the blob data */
2373                 if (!ulp_blob_init(&data, tbl->result_bit_size,
2374                                    BNXT_ULP_BYTE_ORDER_BE)) {
2375                         BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2376                         return -EINVAL;
2377                 }
2378
2379                 /* Get the result fields list */
2380                 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2381                                                  "Gen tbl Result");
2382                 if (rc) {
2383                         BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2384                         return rc;
2385                 }
2386                 byte_data = ulp_blob_data_get(&data, &tmplen);
2387                 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent, 0,
2388                                                        tmplen, byte_data,
2389                                                        ULP_BITS_2_BYTE(tmplen));
2390                 if (rc) {
2391                         BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2392                         return -EINVAL;
2393                 }
2394
2395                 /* increment the reference count */
2396                 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2397                 fdb_write = 1;
2398                 break;
2399         default:
2400                 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2401                 return -EINVAL;
2402         }
2403
2404         /* Set the generic entry hit */
2405         rc = ulp_regfile_write(parms->regfile,
2406                                BNXT_ULP_REGFILE_INDEX_GENERIC_TBL_HIT,
2407                                tfp_cpu_to_be_64(gen_tbl_hit));
2408         if (!rc) {
2409                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2410                             tbl->index_operand);
2411                 return -EIO;
2412         }
2413
2414         /* add the entry to the flow database */
2415         if (fdb_write) {
2416                 memset(&fid_parms, 0, sizeof(fid_parms));
2417                 fid_parms.direction = tbl->direction;
2418                 fid_parms.resource_func = tbl->resource_func;
2419                 fid_parms.resource_sub_type = tbl->resource_sub_type;
2420                 fid_parms.resource_hndl = ckey;
2421                 fid_parms.critical_resource = tbl->critical_resource;
2422                 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2423                 if (rc)
2424                         BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2425         }
2426         return rc;
2427 }
2428
2429 static int32_t
2430 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2431                                   struct bnxt_ulp_mapper_data *mapper_data)
2432 {
2433         struct bnxt_ulp_glb_resource_info *glb_res;
2434         uint32_t num_glb_res_ids, idx;
2435         int32_t rc = 0;
2436
2437         glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2438         if (!glb_res || !num_glb_res_ids) {
2439                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2440                 return -EINVAL;
2441         }
2442
2443         /* Iterate the global resources and process each one */
2444         for (idx = 0; idx < num_glb_res_ids; idx++) {
2445                 switch (glb_res[idx].resource_func) {
2446                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2447                         rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2448                                                                 mapper_data,
2449                                                                 &glb_res[idx]);
2450                         break;
2451                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2452                         rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2453                                                                  mapper_data,
2454                                                                  &glb_res[idx]);
2455                         break;
2456                 default:
2457                         BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2458                                     glb_res[idx].resource_func);
2459                         rc = -EINVAL;
2460                         break;
2461                 }
2462                 if (rc)
2463                         return rc;
2464         }
2465         return rc;
2466 }
2467
2468 /*
2469  * Function to process the memtype opcode of the mapper table.
2470  * returns 1 to skip the table.
2471  * return 0 to continue processing the table.
2472  *
2473  * defaults to skip
2474  */
2475 static int32_t
2476 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2477                                       struct bnxt_ulp_mapper_tbl_info *tbl)
2478 {
2479         enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2480         int32_t rc = 1;
2481
2482         bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2483
2484         switch (tbl->mem_type_opcode) {
2485         case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_INT:
2486                 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2487                         rc = 0;
2488                 break;
2489         case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_EXT:
2490                 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2491                         rc = 0;
2492                 break;
2493         case BNXT_ULP_MEM_TYPE_OPCODE_NOP:
2494                 rc = 0;
2495                 break;
2496         default:
2497                 BNXT_TF_DBG(ERR,
2498                             "Invalid arg in mapper in memtype opcode\n");
2499                 break;
2500         }
2501         return rc;
2502 }
2503
2504 /*
2505  * Common conditional opcode process routine that is used for both the template
2506  * rejection and table conditional execution.
2507  */
2508 static int32_t
2509 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
2510                             enum bnxt_ulp_cond_opc opc,
2511                             uint32_t operand,
2512                             int32_t *res)
2513 {
2514         int32_t rc = 0;
2515         uint8_t *bit;
2516         uint32_t idx;
2517         uint64_t regval;
2518
2519         switch (opc) {
2520         case BNXT_ULP_COND_OPC_COMP_FIELD_IS_SET:
2521                 if (operand < BNXT_ULP_CF_IDX_LAST) {
2522                         *res = ULP_COMP_FLD_IDX_RD(parms, operand);
2523                 } else {
2524                         BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2525                                     operand);
2526                         rc = -EINVAL;
2527                 }
2528                 break;
2529         case BNXT_ULP_COND_OPC_COMP_FIELD_NOT_SET:
2530                 if (operand < BNXT_ULP_CF_IDX_LAST) {
2531                         *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
2532                 } else {
2533                         BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2534                                     operand);
2535                         rc = -EINVAL;
2536                 }
2537                 break;
2538         case BNXT_ULP_COND_OPC_ACTION_BIT_IS_SET:
2539                 if (operand < BNXT_ULP_ACTION_BIT_LAST) {
2540                         *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2541                                                 operand);
2542                 } else {
2543                         BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2544                                     operand);
2545                         rc = -EINVAL;
2546                 }
2547                 break;
2548         case BNXT_ULP_COND_OPC_ACTION_BIT_NOT_SET:
2549                 if (operand < BNXT_ULP_ACTION_BIT_LAST) {
2550                         *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2551                                                operand);
2552                 } else {
2553                         BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2554                                     operand);
2555                         rc = -EINVAL;
2556                 }
2557                 break;
2558         case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
2559                 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2560                         *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2561                                                 operand);
2562                 } else {
2563                         BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2564                                     operand);
2565                         rc = -EINVAL;
2566                 }
2567                 break;
2568         case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
2569                 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2570                         *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2571                                                operand);
2572                 } else {
2573                         BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2574                                     operand);
2575                         rc = -EINVAL;
2576                 }
2577                 break;
2578         case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
2579                 idx = (parms->class_tid << BNXT_ULP_GLB_FIELD_TBL_SHIFT) |
2580                         operand;
2581                 bit = ulp_mapper_glb_field_tbl_get(idx);
2582                 if (!bit) {
2583                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2584                                     idx);
2585                         return -EINVAL;
2586                 }
2587                 *res = ULP_BITMAP_ISSET(parms->fld_bitmap->bits, (1 << *bit));
2588                 break;
2589         case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
2590                 idx = (parms->class_tid << BNXT_ULP_GLB_FIELD_TBL_SHIFT) |
2591                         operand;
2592                 bit = ulp_mapper_glb_field_tbl_get(idx);
2593                 if (!bit) {
2594                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2595                                     idx);
2596                         return -EINVAL;
2597                 }
2598                 *res = !ULP_BITMAP_ISSET(parms->fld_bitmap->bits, (1 << *bit));
2599                 break;
2600         case BNXT_ULP_COND_OPC_REGFILE_IS_SET:
2601                 if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
2602                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2603                         return -EINVAL;
2604                 }
2605                 *res = regval != 0;
2606                 break;
2607         case BNXT_ULP_COND_OPC_REGFILE_NOT_SET:
2608                 if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
2609                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2610                         return -EINVAL;
2611                 }
2612                 *res = regval == 0;
2613                 break;
2614         default:
2615                 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
2616                 rc = -EINVAL;
2617                 break;
2618         }
2619         return (rc);
2620 }
2621
2622 /*
2623  * Processes a list of conditions and returns both a status and result of the
2624  * list.  The status must be checked prior to verifying the result.
2625  *
2626  * returns 0 for success, negative on failure
2627  * returns res = 1 for true, res = 0 for false.
2628  */
2629 static int32_t
2630 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
2631                                  enum bnxt_ulp_cond_list_opc list_opc,
2632                                  struct bnxt_ulp_mapper_cond_info *list,
2633                                  uint32_t num,
2634                                  int32_t *res)
2635 {
2636         uint32_t i;
2637         int32_t rc = 0, trc;
2638
2639         switch (list_opc) {
2640         case BNXT_ULP_COND_LIST_OPC_AND:
2641                 /* AND Defaults to true. */
2642                 *res = 1;
2643                 break;
2644         case BNXT_ULP_COND_LIST_OPC_OR:
2645                 /* OR Defaults to false. */
2646                 *res = 0;
2647                 break;
2648         case BNXT_ULP_COND_LIST_OPC_TRUE:
2649                 *res = 1;
2650                 return rc;
2651         case BNXT_ULP_COND_LIST_OPC_FALSE:
2652                 *res = 0;
2653                 return rc;
2654         default:
2655                 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
2656                             list_opc);
2657                 return -EINVAL;
2658         }
2659
2660         for (i = 0; i < num; i++) {
2661                 rc = ulp_mapper_cond_opc_process(parms,
2662                                                  list[i].cond_opcode,
2663                                                  list[i].cond_operand,
2664                                                  &trc);
2665                 if (rc)
2666                         return rc;
2667
2668                 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
2669                         /* early return if result is ever zero */
2670                         if (!trc) {
2671                                 *res = trc;
2672                                 return rc;
2673                         }
2674                 } else {
2675                         /* early return if result is ever non-zero */
2676                         if (trc) {
2677                                 *res = trc;
2678                                 return rc;
2679                         }
2680                 }
2681         }
2682
2683         return rc;
2684 }
2685
2686 static int32_t
2687 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
2688 {
2689         struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
2690         enum bnxt_ulp_cond_list_opc cond_opc;
2691         struct bnxt_ulp_mapper_tbl_info *tbls;
2692         struct bnxt_ulp_mapper_tbl_info *tbl;
2693         uint32_t num_tbls, i, num_cond_tbls;
2694         int32_t rc = -EINVAL, cond_rc = 0;
2695
2696         cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
2697                                                     &num_cond_tbls,
2698                                                     &cond_opc);
2699         /*
2700          * Process the reject list if exists, otherwise assume that the
2701          * template is allowed.
2702          */
2703         if (cond_tbls && num_cond_tbls) {
2704                 rc = ulp_mapper_cond_opc_list_process(parms,
2705                                                       cond_opc,
2706                                                       cond_tbls,
2707                                                       num_cond_tbls,
2708                                                       &cond_rc);
2709                 if (rc)
2710                         return rc;
2711
2712                 /* Reject the template if True */
2713                 if (cond_rc) {
2714                         BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
2715                                     (parms->tmpl_type ==
2716                                      BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2717                                     "class" : "action", tid);
2718                         return -EINVAL;
2719                 }
2720         }
2721
2722         tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
2723         if (!tbls || !num_tbls) {
2724                 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
2725                             (parms->tmpl_type == BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2726                             "class" : "action", parms->dev_id, tid);
2727                 return -EINVAL;
2728         }
2729
2730         for (i = 0; i < num_tbls; i++) {
2731                 tbl = &tbls[i];
2732
2733                 /* Handle the table level opcodes to determine if required. */
2734                 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl))
2735                         continue;
2736                 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
2737                                                             &num_cond_tbls,
2738                                                             &cond_opc);
2739                 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
2740                                                       cond_tbls, num_cond_tbls,
2741                                                       &cond_rc);
2742                 if (rc) {
2743                         BNXT_TF_DBG(ERR, "Failed to process cond opc list "
2744                                    "(%d)\n", rc);
2745                         return rc;
2746                 }
2747                 /* Skip the table if False */
2748                 if (!cond_rc)
2749                         continue;
2750
2751                 switch (tbl->resource_func) {
2752                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2753                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
2754                         break;
2755                 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2756                 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2757                         rc = ulp_mapper_em_tbl_process(parms, tbl);
2758                         break;
2759                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2760                         rc = ulp_mapper_index_tbl_process(parms, tbl);
2761                         break;
2762                 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
2763                         rc = ulp_mapper_if_tbl_process(parms, tbl);
2764                         break;
2765                 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2766                         rc = ulp_mapper_gen_tbl_process(parms, tbl);
2767                         break;
2768                 case BNXT_ULP_RESOURCE_FUNC_INVALID:
2769                         rc = 0;
2770                         break;
2771                 default:
2772                         BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
2773                                     tbl->resource_func);
2774                         rc = -EINVAL;
2775                         goto error;
2776                 }
2777
2778                 if (rc) {
2779                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
2780                                     tbl->resource_func);
2781                         goto error;
2782                 }
2783         }
2784
2785         return rc;
2786 error:
2787         BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
2788                     (parms->tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2789                     "class" : "action", parms->dev_id, tid);
2790         return rc;
2791 }
2792
2793 static int32_t
2794 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
2795                          uint32_t fid,
2796                          struct ulp_flow_db_res_params *res)
2797 {
2798         struct tf *tfp;
2799         int32_t rc = 0;
2800
2801         if (!res || !ulp) {
2802                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
2803                 return -EINVAL;
2804         }
2805
2806         tfp = bnxt_ulp_cntxt_tfp_get(ulp);
2807         if (!tfp) {
2808                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
2809                 return -EINVAL;
2810         }
2811
2812         switch (res->resource_func) {
2813         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2814                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
2815                 break;
2816         case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2817         case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2818                 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
2819                 break;
2820         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2821                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
2822                 break;
2823         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2824                 rc = ulp_mapper_ident_free(ulp, tfp, res);
2825                 break;
2826         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
2827                 rc = ulp_mapper_mark_free(ulp, res);
2828                 break;
2829         case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
2830                 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
2831                 break;
2832         case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
2833                 rc = ulp_mapper_child_flow_free(ulp, fid, res);
2834                 break;
2835         case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2836                 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
2837                 break;
2838         default:
2839                 break;
2840         }
2841
2842         return rc;
2843 }
2844
2845 int32_t
2846 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
2847                           enum bnxt_ulp_fdb_type flow_type,
2848                           uint32_t fid)
2849 {
2850         struct ulp_flow_db_res_params res_parms = { 0 };
2851         int32_t rc, trc;
2852
2853         if (!ulp_ctx) {
2854                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2855                 return -EINVAL;
2856         }
2857
2858         /*
2859          * Set the critical resource on the first resource del, then iterate
2860          * while status is good
2861          */
2862         res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
2863         rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
2864
2865         if (rc) {
2866                 /*
2867                  * This is unexpected on the first call to resource del.
2868                  * It likely means that the flow did not exist in the flow db.
2869                  */
2870                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
2871                             flow_type, fid, rc);
2872                 return rc;
2873         }
2874
2875         while (!rc) {
2876                 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
2877                 if (trc)
2878                         /*
2879                          * On fail, we still need to attempt to free the
2880                          * remaining resources.  Don't return
2881                          */
2882                         BNXT_TF_DBG(ERR,
2883                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
2884                                     "] failed rc=%d.\n",
2885                                     flow_type, fid, res_parms.resource_func,
2886                                     res_parms.resource_hndl, trc);
2887
2888                 /* All subsequent call require the non-critical_resource */
2889                 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2890
2891                 rc = ulp_flow_db_resource_del(ulp_ctx,
2892                                               flow_type,
2893                                               fid,
2894                                               &res_parms);
2895         }
2896
2897         /* Free the Flow ID since we've removed all resources */
2898         rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
2899
2900         return rc;
2901 }
2902
2903 static void
2904 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
2905                                     struct bnxt_ulp_mapper_data *mapper_data)
2906 {
2907         struct bnxt_ulp_mapper_glb_resource_entry *ent;
2908         struct ulp_flow_db_res_params res;
2909         uint32_t dir, idx;
2910
2911         /* Iterate the global resources and process each one */
2912         for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
2913                 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
2914                       idx++) {
2915                         ent = &mapper_data->glb_res_tbl[dir][idx];
2916                         if (ent->resource_func ==
2917                             BNXT_ULP_RESOURCE_FUNC_INVALID)
2918                                 continue;
2919                         memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
2920                         res.resource_func = ent->resource_func;
2921                         res.direction = dir;
2922                         res.resource_type = ent->resource_type;
2923                         /*convert it from BE to cpu */
2924                         res.resource_hndl =
2925                                 tfp_be_to_cpu_64(ent->resource_hndl);
2926                         ulp_mapper_resource_free(ulp_ctx, 0, &res);
2927                 }
2928         }
2929 }
2930
2931 int32_t
2932 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
2933                         enum bnxt_ulp_fdb_type flow_type,
2934                         uint32_t fid)
2935 {
2936         int32_t rc;
2937
2938         if (!ulp_ctx) {
2939                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2940                 return -EINVAL;
2941         }
2942
2943         rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
2944         return rc;
2945 }
2946
2947 /* Function to handle the default global templates that are allocated during
2948  * the startup and reused later.
2949  */
2950 static int32_t
2951 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
2952 {
2953         uint32_t *glbl_tmpl_list;
2954         uint32_t num_glb_tmpls, idx, dev_id;
2955         struct bnxt_ulp_mapper_parms parms;
2956         struct bnxt_ulp_mapper_data *mapper_data;
2957         int32_t rc = 0;
2958
2959         glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
2960         if (!glbl_tmpl_list || !num_glb_tmpls)
2961                 return rc; /* No global templates to process */
2962
2963         /* Get the device id from the ulp context */
2964         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
2965                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2966                 return -EINVAL;
2967         }
2968
2969         mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2970         if (!mapper_data) {
2971                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2972                 return -EINVAL;
2973         }
2974
2975         /* Iterate the global resources and process each one */
2976         for (idx = 0; idx < num_glb_tmpls; idx++) {
2977                 /* Initialize the parms structure */
2978                 memset(&parms, 0, sizeof(parms));
2979                 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2980                 parms.ulp_ctx = ulp_ctx;
2981                 parms.dev_id = dev_id;
2982                 parms.mapper_data = mapper_data;
2983                 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
2984                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
2985
2986                 /* Get the class table entry from dev id and class id */
2987                 parms.class_tid = glbl_tmpl_list[idx];
2988
2989                 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2990                 if (!parms.device_params) {
2991                         BNXT_TF_DBG(ERR, "No device for device id %d\n",
2992                                     parms.dev_id);
2993                         return -EINVAL;
2994                 }
2995
2996                 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
2997                 if (rc)
2998                         return rc;
2999         }
3000         return rc;
3001 }
3002
3003 /* Function to handle the mapping of the Flow to be compatible
3004  * with the underlying hardware.
3005  */
3006 int32_t
3007 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3008                        struct bnxt_ulp_mapper_create_parms *cparms)
3009 {
3010         struct bnxt_ulp_mapper_parms parms;
3011         struct ulp_regfile regfile;
3012         int32_t  rc, trc;
3013
3014         if (!ulp_ctx || !cparms)
3015                 return -EINVAL;
3016
3017         /* Initialize the parms structure */
3018         memset(&parms, 0, sizeof(parms));
3019         parms.act_prop = cparms->act_prop;
3020         parms.act_bitmap = cparms->act;
3021         parms.hdr_bitmap = cparms->hdr_bitmap;
3022         parms.regfile = &regfile;
3023         parms.hdr_field = cparms->hdr_field;
3024         parms.comp_fld = cparms->comp_fld;
3025         parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3026         parms.ulp_ctx = ulp_ctx;
3027         parms.act_tid = cparms->act_tid;
3028         parms.class_tid = cparms->class_tid;
3029         parms.flow_type = cparms->flow_type;
3030         parms.parent_flow = cparms->parent_flow;
3031         parms.parent_fid = cparms->parent_fid;
3032         parms.fid = cparms->flow_id;
3033         parms.tun_idx = cparms->tun_idx;
3034
3035         /* Get the device id from the ulp context */
3036         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3037                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3038                 return -EINVAL;
3039         }
3040
3041         /* Get the device params, it will be used in later processing */
3042         parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3043         if (!parms.device_params) {
3044                 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3045                             parms.dev_id);
3046                 return -EINVAL;
3047         }
3048
3049         /*
3050          * Get the mapper data for dynamic mapper data such as default
3051          * ids.
3052          */
3053         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3054                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3055         if (!parms.mapper_data) {
3056                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3057                 return -EINVAL;
3058         }
3059
3060         /* initialize the registry file for further processing */
3061         if (!ulp_regfile_init(parms.regfile)) {
3062                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3063                 return -EINVAL;
3064         }
3065
3066         rc = ulp_regfile_write(parms.regfile,
3067                                BNXT_ULP_REGFILE_INDEX_CLASS_TID,
3068                                tfp_cpu_to_be_64((uint64_t)parms.class_tid));
3069         if (!rc) {
3070                 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
3071                 return -EINVAL;
3072         }
3073
3074         /* Process the action template list from the selected action table*/
3075         if (parms.act_tid) {
3076                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3077                 /* Process the action template tables */
3078                 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3079                 if (rc)
3080                         goto flow_error;
3081         }
3082
3083         if (parms.class_tid) {
3084                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3085
3086                 /* Process the class template tables.*/
3087                 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3088                 if (rc)
3089                         goto flow_error;
3090         }
3091
3092         /* setup the parent-child details */
3093         if (parms.parent_flow) {
3094                 /* create a parent flow details */
3095                 rc = ulp_flow_db_parent_flow_create(&parms);
3096                 if (rc)
3097                         goto flow_error;
3098         } else if (parms.parent_fid) {
3099                 /* create a child flow details */
3100                 rc = ulp_flow_db_child_flow_create(&parms);
3101                 if (rc)
3102                         goto flow_error;
3103         }
3104
3105         return rc;
3106
3107 flow_error:
3108         /* Free all resources that were allocated during flow creation */
3109         trc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
3110                                       parms.fid);
3111         if (trc)
3112                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3113
3114         return rc;
3115 }
3116
3117 int32_t
3118 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3119 {
3120         struct bnxt_ulp_mapper_data *data;
3121         struct tf *tfp;
3122         int32_t rc;
3123
3124         if (!ulp_ctx)
3125                 return -EINVAL;
3126
3127         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3128         if (!tfp)
3129                 return -EINVAL;
3130
3131         data = rte_zmalloc("ulp_mapper_data",
3132                            sizeof(struct bnxt_ulp_mapper_data), 0);
3133         if (!data) {
3134                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3135                 return -ENOMEM;
3136         }
3137
3138         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3139                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3140                 /* Don't call deinit since the prof_func wasn't allocated. */
3141                 rte_free(data);
3142                 return -ENOMEM;
3143         }
3144
3145         /* Allocate the global resource ids */
3146         rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3147         if (rc) {
3148                 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3149                 goto error;
3150         }
3151
3152         /* Allocate the generic table list */
3153         rc = ulp_mapper_generic_tbl_list_init(data);
3154         if (rc) {
3155                 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3156                 goto error;
3157         }
3158
3159         /* Allocate global template table entries */
3160         rc = ulp_mapper_glb_template_table_init(ulp_ctx);
3161         if (rc) {
3162                 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
3163                 goto error;
3164         }
3165
3166         return 0;
3167 error:
3168         /* Ignore the return code in favor of returning the original error. */
3169         ulp_mapper_deinit(ulp_ctx);
3170         return rc;
3171 }
3172
3173 void
3174 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3175 {
3176         struct bnxt_ulp_mapper_data *data;
3177         struct tf *tfp;
3178
3179         if (!ulp_ctx) {
3180                 BNXT_TF_DBG(ERR,
3181                             "Failed to acquire ulp context, so data may "
3182                             "not be released.\n");
3183                 return;
3184         }
3185
3186         data = (struct bnxt_ulp_mapper_data *)
3187                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3188         if (!data) {
3189                 /* Go ahead and return since there is no allocated data. */
3190                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3191                 return;
3192         }
3193
3194         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3195         if (!tfp) {
3196                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3197                 /* Free the mapper data regardless of errors. */
3198                 goto free_mapper_data;
3199         }
3200
3201         /* Free the global resource info table entries */
3202         ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3203
3204 free_mapper_data:
3205         /* Free the generic table */
3206         (void)ulp_mapper_generic_tbl_list_deinit(data);
3207
3208         rte_free(data);
3209         /* Reset the data pointer within the ulp_ctx. */
3210         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
3211 }