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